From 5677eab3c86d47a40105295719e24d419f8314c1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 21 May 2019 09:56:24 +0100 Subject: [PATCH 0001/7155] soc: fsl: fix spelling mistake "Firmaware" -> "Firmware" There is a spelling mistake in a pr_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Li Yang --- drivers/soc/fsl/dpaa2-console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c index 9168d8ddc932..27243f706f37 100644 --- a/drivers/soc/fsl/dpaa2-console.c +++ b/drivers/soc/fsl/dpaa2-console.c @@ -73,7 +73,7 @@ static u64 get_mc_fw_base_address(void) mcfbaregs = ioremap(mc_base_addr.start, resource_size(&mc_base_addr)); if (!mcfbaregs) { - pr_err("could not map MC Firmaware Base registers\n"); + pr_err("could not map MC Firmware Base registers\n"); return 0; } -- GitLab From f03de74d92aca6a5399c088074550a164ae44eec Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:14:54 +0000 Subject: [PATCH 0002/7155] soc: fsl: qe: drop useless static qualifier The local variable snum_init has no reason to have static storage duration. Reviewed-by: Christophe Leroy Reviewed-by: Qiang Zhao Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 612d9c551be5..855373deb746 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -306,7 +306,7 @@ static void qe_snums_init(void) 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59, 0x68, 0x69, 0x78, 0x79, 0x80, 0x81, }; - static const u8 *snum_init; + const u8 *snum_init; qe_num_of_snum = qe_get_num_of_snums(); -- GitLab From 875f2aabfcfa321dd39298849e3833b44ee54b4d Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:14:56 +0000 Subject: [PATCH 0003/7155] soc: fsl: qe: reduce static memory footprint by 1.7K The current array of struct qe_snum use 256*4 bytes for just keeping track of the free/used state of each index, and the struct layout means there's another 768 bytes of padding. If we just unzip that structure, the array of snum values just use 256 bytes, while the free/inuse state can be tracked in a 32 byte bitmap. So this reduces the .data footprint by 1760 bytes. It also serves as preparation for introducing another DT binding for specifying the snum values. Reviewed-by: Christophe Leroy Reviewed-by: Qiang Zhao Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe.c | 42 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 855373deb746..4b59109df22b 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -14,6 +14,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include #include #include #include @@ -43,25 +44,14 @@ static DEFINE_SPINLOCK(qe_lock); DEFINE_SPINLOCK(cmxgcr_lock); EXPORT_SYMBOL(cmxgcr_lock); -/* QE snum state */ -enum qe_snum_state { - QE_SNUM_STATE_USED, - QE_SNUM_STATE_FREE -}; - -/* QE snum */ -struct qe_snum { - u8 num; - enum qe_snum_state state; -}; - /* We allocate this here because it is used almost exclusively for * the communication processor devices. */ struct qe_immap __iomem *qe_immr; EXPORT_SYMBOL(qe_immr); -static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */ +static u8 snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */ +static DECLARE_BITMAP(snum_state, QE_NUM_OF_SNUM); static unsigned int qe_num_of_snum; static phys_addr_t qebase = -1; @@ -315,10 +305,8 @@ static void qe_snums_init(void) else snum_init = snum_init_46; - for (i = 0; i < qe_num_of_snum; i++) { - snums[i].num = snum_init[i]; - snums[i].state = QE_SNUM_STATE_FREE; - } + bitmap_zero(snum_state, QE_NUM_OF_SNUM); + memcpy(snums, snum_init, qe_num_of_snum); } int qe_get_snum(void) @@ -328,12 +316,10 @@ int qe_get_snum(void) int i; spin_lock_irqsave(&qe_lock, flags); - for (i = 0; i < qe_num_of_snum; i++) { - if (snums[i].state == QE_SNUM_STATE_FREE) { - snums[i].state = QE_SNUM_STATE_USED; - snum = snums[i].num; - break; - } + i = find_first_zero_bit(snum_state, qe_num_of_snum); + if (i < qe_num_of_snum) { + set_bit(i, snum_state); + snum = snums[i]; } spin_unlock_irqrestore(&qe_lock, flags); @@ -343,14 +329,10 @@ EXPORT_SYMBOL(qe_get_snum); void qe_put_snum(u8 snum) { - int i; + const u8 *p = memchr(snums, snum, qe_num_of_snum); - for (i = 0; i < qe_num_of_snum; i++) { - if (snums[i].num == snum) { - snums[i].state = QE_SNUM_STATE_FREE; - break; - } - } + if (p) + clear_bit(p - snums, snum_state); } EXPORT_SYMBOL(qe_put_snum); -- GitLab From d7fc5963664198d25ca525f120f72ff053ba334f Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:14:57 +0000 Subject: [PATCH 0004/7155] soc: fsl: qe: introduce qe_get_device_node helper The 'try of_find_compatible_node(NULL, NULL, "fsl,qe"), fall back to of_find_node_by_type(NULL, "qe")' pattern is repeated five times. Factor it into a common helper. Reviewed-by: Christophe Leroy Reviewed-by: Qiang Zhao Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe.c | 71 +++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 4b59109df22b..4b444846d590 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -56,6 +56,20 @@ static unsigned int qe_num_of_snum; static phys_addr_t qebase = -1; +static struct device_node *qe_get_device_node(void) +{ + struct device_node *qe; + + /* + * Newer device trees have an "fsl,qe" compatible property for the QE + * node, but we still need to support older device trees. + */ + qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); + if (qe) + return qe; + return of_find_node_by_type(NULL, "qe"); +} + static phys_addr_t get_qe_base(void) { struct device_node *qe; @@ -65,12 +79,9 @@ static phys_addr_t get_qe_base(void) if (qebase != -1) return qebase; - qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!qe) { - qe = of_find_node_by_type(NULL, "qe"); - if (!qe) - return qebase; - } + qe = qe_get_device_node(); + if (!qe) + return qebase; ret = of_address_to_resource(qe, 0, &res); if (!ret) @@ -164,12 +175,9 @@ unsigned int qe_get_brg_clk(void) if (brg_clk) return brg_clk; - qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!qe) { - qe = of_find_node_by_type(NULL, "qe"); - if (!qe) - return brg_clk; - } + qe = qe_get_device_node(); + if (!qe) + return brg_clk; prop = of_get_property(qe, "brg-frequency", &size); if (prop && size == sizeof(*prop)) @@ -558,16 +566,9 @@ struct qe_firmware_info *qe_get_firmware_info(void) initialized = 1; - /* - * Newer device trees have an "fsl,qe" compatible property for the QE - * node, but we still need to support older device trees. - */ - qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!qe) { - qe = of_find_node_by_type(NULL, "qe"); - if (!qe) - return NULL; - } + qe = qe_get_device_node(); + if (!qe) + return NULL; /* Find the 'firmware' child node */ fw = of_get_child_by_name(qe, "firmware"); @@ -613,16 +614,9 @@ unsigned int qe_get_num_of_risc(void) unsigned int num_of_risc = 0; const u32 *prop; - qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!qe) { - /* Older devices trees did not have an "fsl,qe" - * compatible property, so we need to look for - * the QE node by name. - */ - qe = of_find_node_by_type(NULL, "qe"); - if (!qe) - return num_of_risc; - } + qe = qe_get_device_node(); + if (!qe) + return num_of_risc; prop = of_get_property(qe, "fsl,qe-num-riscs", &size); if (prop && size == sizeof(*prop)) @@ -642,16 +636,9 @@ unsigned int qe_get_num_of_snums(void) const u32 *prop; num_of_snums = 28; /* The default number of snum for threads is 28 */ - qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!qe) { - /* Older devices trees did not have an "fsl,qe" - * compatible property, so we need to look for - * the QE node by name. - */ - qe = of_find_node_by_type(NULL, "qe"); - if (!qe) - return num_of_snums; - } + qe = qe_get_device_node(); + if (!qe) + return num_of_snums; prop = of_get_property(qe, "fsl,qe-num-snums", &size); if (prop && size == sizeof(*prop)) { -- GitLab From 8f762fe5819f8561343cf02e234789744ed68a98 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:14:58 +0000 Subject: [PATCH 0005/7155] dt-bindings: soc: fsl: qe: document new fsl,qe-snums binding Reading table 4-30, and its footnotes, of the QUICC Engine Block Reference Manual shows that the set of snum _values_ is not necessarily just a function of the _number_ of snums, as given in the fsl,qe-num-snums property. As an alternative, to make it easier to add support for other variants of the QUICC engine IP, this introduces a new binding fsl,qe-snums, which automatically encodes both the number of snums and the actual values to use. Signed-off-by: Rasmus Villemoes Reviewed-by: Rob Herring Signed-off-by: Li Yang --- .../devicetree/bindings/soc/fsl/cpm_qe/qe.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt index d7afaff5faff..05ec2a838c54 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/qe.txt @@ -18,7 +18,8 @@ Required properties: - reg : offset and length of the device registers. - bus-frequency : the clock frequency for QUICC Engine. - fsl,qe-num-riscs: define how many RISC engines the QE has. -- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the +- fsl,qe-snums: This property has to be specified as '/bits/ 8' value, + defining the array of serial number (SNUM) values for the virtual threads. Optional properties: @@ -34,6 +35,11 @@ Recommended properties - brg-frequency : the internal clock source frequency for baud-rate generators in Hz. +Deprecated properties +- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use + for the threads. Use fsl,qe-snums instead to not only specify the + number of snums, but also their values. + Example: qe@e0100000 { #address-cells = <1>; @@ -44,6 +50,11 @@ Example: reg = ; brg-frequency = <0>; bus-frequency = <179A7B00>; + fsl,qe-snums = /bits/ 8 < + 0x04 0x05 0x0C 0x0D 0x14 0x15 0x1C 0x1D + 0x24 0x25 0x2C 0x2D 0x34 0x35 0x88 0x89 + 0x98 0x99 0xA8 0xA9 0xB8 0xB9 0xC8 0xC9 + 0xD8 0xD9 0xE8 0xE9>; } * Multi-User RAM (MURAM) -- GitLab From 5cfca8911ddd59150ba53cff16956eabe1b3dcac Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:15:00 +0000 Subject: [PATCH 0006/7155] soc: fsl: qe: support fsl,qe-snums property Add driver support for the newly introduced fsl,qe-snums property. Conveniently, of_property_read_variable_u8_array does exactly what we need: If the property fsl,qe-snums is found (and has an allowed size), the array of values get copied to snums, and the return value is the number of snums - we cannot assign directly to num_of_snums, since we need to check whether the return value is negative. Reviewed-by: Christophe Leroy Reviewed-by: Qiang Zhao Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 4b444846d590..1d27187b251c 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -283,7 +283,6 @@ EXPORT_SYMBOL(qe_clock_source); */ static void qe_snums_init(void) { - int i; static const u8 snum_init_76[] = { 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, @@ -304,7 +303,21 @@ static void qe_snums_init(void) 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59, 0x68, 0x69, 0x78, 0x79, 0x80, 0x81, }; + struct device_node *qe; const u8 *snum_init; + int i; + + bitmap_zero(snum_state, QE_NUM_OF_SNUM); + qe = qe_get_device_node(); + if (qe) { + i = of_property_read_variable_u8_array(qe, "fsl,qe-snums", + snums, 1, QE_NUM_OF_SNUM); + of_node_put(qe); + if (i > 0) { + qe_num_of_snum = i; + return; + } + } qe_num_of_snum = qe_get_num_of_snums(); @@ -313,7 +326,6 @@ static void qe_snums_init(void) else snum_init = snum_init_46; - bitmap_zero(snum_state, QE_NUM_OF_SNUM); memcpy(snums, snum_init, qe_num_of_snum); } -- GitLab From 21560067fb1f5e87abedc3ecec5d46f67ac0c019 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 May 2019 11:15:01 +0000 Subject: [PATCH 0007/7155] soc: fsl: qe: fold qe_get_num_of_snums into qe_snums_init The comment "No QE ever has fewer than 28 SNUMs" is false; e.g. the MPC8309 has 14. The code path returning -EINVAL is also a recipe for instant disaster, since the caller (qe_snums_init) uncritically assigns the return value to the unsigned qe_num_of_snum, and would thus proceed to attempt to copy 4GB from snum_init_46[] to the snum[] array. So fold the handling of the legacy fsl,qe-num-snums into qe_snums_init, and make sure we do not end up using the snum_init_46 array in cases other than the two where we know it makes sense. Reviewed-by: Christophe Leroy Reviewed-by: Qiang Zhao Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe.c | 46 ++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 1d27187b251c..852060caff24 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -308,24 +308,33 @@ static void qe_snums_init(void) int i; bitmap_zero(snum_state, QE_NUM_OF_SNUM); + qe_num_of_snum = 28; /* The default number of snum for threads is 28 */ qe = qe_get_device_node(); if (qe) { i = of_property_read_variable_u8_array(qe, "fsl,qe-snums", snums, 1, QE_NUM_OF_SNUM); - of_node_put(qe); if (i > 0) { + of_node_put(qe); qe_num_of_snum = i; return; } + /* + * Fall back to legacy binding of using the value of + * fsl,qe-num-snums to choose one of the static arrays + * above. + */ + of_property_read_u32(qe, "fsl,qe-num-snums", &qe_num_of_snum); + of_node_put(qe); } - qe_num_of_snum = qe_get_num_of_snums(); - - if (qe_num_of_snum == 76) + if (qe_num_of_snum == 76) { snum_init = snum_init_76; - else + } else if (qe_num_of_snum == 28 || qe_num_of_snum == 46) { snum_init = snum_init_46; - + } else { + pr_err("QE: unsupported value of fsl,qe-num-snums: %u\n", qe_num_of_snum); + return; + } memcpy(snums, snum_init, qe_num_of_snum); } @@ -642,30 +651,7 @@ EXPORT_SYMBOL(qe_get_num_of_risc); unsigned int qe_get_num_of_snums(void) { - struct device_node *qe; - int size; - unsigned int num_of_snums; - const u32 *prop; - - num_of_snums = 28; /* The default number of snum for threads is 28 */ - qe = qe_get_device_node(); - if (!qe) - return num_of_snums; - - prop = of_get_property(qe, "fsl,qe-num-snums", &size); - if (prop && size == sizeof(*prop)) { - num_of_snums = *prop; - if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) { - /* No QE ever has fewer than 28 SNUMs */ - pr_err("QE: number of snum is invalid\n"); - of_node_put(qe); - return -EINVAL; - } - } - - of_node_put(qe); - - return num_of_snums; + return qe_num_of_snum; } EXPORT_SYMBOL(qe_get_num_of_snums); -- GitLab From 0e84ec96b561d298bc9a22d58e7a4730bc408aca Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Thu, 30 May 2019 14:10:14 -0300 Subject: [PATCH 0008/7155] KVM: PPC: Remove leftover comment from emulate_loadstore.c Commit 4eeb85568e56 ("KVM: PPC: Remove mmio_vsx_tx_sx_enabled in KVM MMIO emulation") removed the mmio_vsx_tx_sx_enabled field, but its documentation was left behind. Remove the superfluous comment. Signed-off-by: Fabiano Rosas Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/emulate_loadstore.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c index f91b1309a0a8..806dbc439131 100644 --- a/arch/powerpc/kvm/emulate_loadstore.c +++ b/arch/powerpc/kvm/emulate_loadstore.c @@ -100,12 +100,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) rs = get_rs(inst); rt = get_rt(inst); - /* - * if mmio_vsx_tx_sx_enabled == 0, copy data between - * VSR[0..31] and memory - * if mmio_vsx_tx_sx_enabled == 1, copy data between - * VSR[32..63] and memory - */ vcpu->arch.mmio_vsx_copy_nums = 0; vcpu->arch.mmio_vsx_offset = 0; vcpu->arch.mmio_copy_type = KVMPPC_VSX_COPY_NONE; -- GitLab From 3bda7f0ae0f786b202c0c5124c208be067acca30 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 14 Jun 2019 19:57:45 +0100 Subject: [PATCH 0009/7155] KVM: PPC: Book3S PR: Fix software breakpoints QEMU's kvm_handle_debug() function identifies software breakpoints by checking for a value of 0 in kvm_debug_exit_arch's status field. Since this field isn't explicitly set to 0 when the software breakpoint instruction is detected, any previous non-zero value present causes a hang in QEMU as it tries to process the breakpoint instruction incorrectly as a hardware breakpoint. Ensure that the kvm_debug_exit_arch status field is set to 0 when the software breakpoint instruction is detected (similar to the existing logic in booke.c and e500_emulate.c) to restore software breakpoint functionality under Book3S PR. Signed-off-by: Mark Cave-Ayland Reviewed-by: Fabiano Rosas Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/emulate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 9f5b8c01c4e1..e77becaad5dd 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -282,6 +282,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) */ if (inst == KVMPPC_INST_SW_BREAKPOINT) { run->exit_reason = KVM_EXIT_DEBUG; + run->debug.arch.status = 0; run->debug.arch.address = kvmppc_get_pc(vcpu); emulated = EMULATE_EXIT_USER; advance = 0; -- GitLab From 163fa23435cc9c705a71001d4aa15f3f945554a1 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Wed, 3 Jul 2019 16:25:52 +0800 Subject: [PATCH 0010/7155] percpu: Make pcpu_setup_first_chunk() void function pcpu_setup_first_chunk() will panic or BUG_ON if the are some error and doesn't return any error, hence it can be defined to return void. Reported-by: kbuild test robot Signed-off-by: Kefeng Wang Signed-off-by: Dennis Zhou [Dennis: fixed kbuild warning for pcpu_page_first_chunk()] --- arch/ia64/mm/contig.c | 5 +---- arch/ia64/mm/discontig.c | 5 +---- include/linux/percpu.h | 2 +- mm/percpu.c | 19 +++++++------------ 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index d29fb6b9fa33..db09a693f094 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -134,10 +134,7 @@ setup_per_cpu_areas(void) ai->atom_size = PAGE_SIZE; ai->alloc_size = PERCPU_PAGE_SIZE; - rc = pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]); - if (rc) - panic("failed to setup percpu area (err=%d)", rc); - + pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]); pcpu_free_alloc_info(ai); } #else diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 05490dd073e6..004dee231874 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -245,10 +245,7 @@ void __init setup_per_cpu_areas(void) gi->cpu_map = &cpu_map[unit]; } - rc = pcpu_setup_first_chunk(ai, base); - if (rc) - panic("failed to setup percpu area (err=%d)", rc); - + pcpu_setup_first_chunk(ai, base); pcpu_free_alloc_info(ai); } #endif diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 9909dc0e273a..5e76af742c80 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -105,7 +105,7 @@ extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups, int nr_units); extern void __init pcpu_free_alloc_info(struct pcpu_alloc_info *ai); -extern int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, +extern void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, void *base_addr); #ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK diff --git a/mm/percpu.c b/mm/percpu.c index 9821241fdede..5a918a4b1da0 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -2267,12 +2267,9 @@ static void pcpu_dump_alloc_info(const char *lvl, * share the same vm, but use offset regions in the area allocation map. * The chunk serving the dynamic region is circulated in the chunk slots * and available for dynamic allocation like any other chunk. - * - * RETURNS: - * 0 on success, -errno on failure. */ -int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, - void *base_addr) +void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + void *base_addr) { size_t size_sum = ai->static_size + ai->reserved_size + ai->dyn_size; size_t static_size, dyn_size; @@ -2457,7 +2454,6 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, /* we're done */ pcpu_base_addr = base_addr; - return 0; } #ifdef CONFIG_SMP @@ -2710,7 +2706,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size, struct pcpu_alloc_info *ai; size_t size_sum, areas_size; unsigned long max_distance; - int group, i, highest_group, rc; + int group, i, highest_group, rc = 0; ai = pcpu_build_alloc_info(reserved_size, dyn_size, atom_size, cpu_distance_fn); @@ -2795,7 +2791,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size, PFN_DOWN(size_sum), ai->static_size, ai->reserved_size, ai->dyn_size, ai->unit_size); - rc = pcpu_setup_first_chunk(ai, base); + pcpu_setup_first_chunk(ai, base); goto out_free; out_free_areas: @@ -2839,7 +2835,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size, int unit_pages; size_t pages_size; struct page **pages; - int unit, i, j, rc; + int unit, i, j, rc = 0; int upa; int nr_g0_units; @@ -2920,7 +2916,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size, unit_pages, psize_str, ai->static_size, ai->reserved_size, ai->dyn_size); - rc = pcpu_setup_first_chunk(ai, vm.addr); + pcpu_setup_first_chunk(ai, vm.addr); goto out_free_ar; enomem: @@ -3014,8 +3010,7 @@ void __init setup_per_cpu_areas(void) ai->groups[0].nr_units = 1; ai->groups[0].cpu_map[0] = 0; - if (pcpu_setup_first_chunk(ai, fc) < 0) - panic("Failed to initialize percpu areas."); + pcpu_setup_first_chunk(ai, fc); pcpu_free_alloc_info(ai); } -- GitLab From 9f02b8f61f29f4518581770d57bfffe99b1ea599 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Wed, 3 Jul 2019 12:03:50 +0200 Subject: [PATCH 0011/7155] tee: optee: add might_sleep for RPC requests If the kernel is compiled with CONFIG_PREEMPT_VOLUNTARY and OP-TEE is executing a long running workload, the following errors are raised: [ 1705.971228] rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [ 1705.977195] rcu: (detected by 0, t=2102 jiffies, g=51977, q=3) [ 1705.983152] rcu: All QSes seen, last rcu_sched kthread activity 2102 (140596-138494), jiffies_till_next_fqs=1, root ->qsmask 0x0 [ 1705.994729] optee-xtest R running task 0 169 157 0x00000002 While OP-TEE is returning regularly to the kernel due to timer interrupts, the OPTEE_SMC_FUNC_FOREIGN_INTR case does not contain an explicit rescheduling point. Add a might_sleep() to the RPC request case to ensure that the kernel can reschedule another task if OP-TEE requests RPC handling. Signed-off-by: Rouven Czerwinski Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index aa942703ae65..13b0269a0abc 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -148,6 +148,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) */ optee_cq_wait_for_completion(&optee->call_queue, &w); } else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) { + might_sleep(); param.a0 = res.a0; param.a1 = res.a1; param.a2 = res.a2; -- GitLab From 0be0bfd2de9dfdd2098a9c5b14bdd8f739c9165d Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Fri, 12 Jul 2019 15:24:34 +0300 Subject: [PATCH 0012/7155] ovl: fix regression caused by overlapping layers detection Once upon a time, commit 2cac0c00a6cd ("ovl: get exclusive ownership on upper/work dirs") in v4.13 added some sanity checks on overlayfs layers. This change caused a docker regression. The root cause was mount leaks by docker, which as far as I know, still exist. To mitigate the regression, commit 85fdee1eef1a ("ovl: fix regression caused by exclusive upper/work dir protection") in v4.14 turned the mount errors into warnings for the default index=off configuration. Recently, commit 146d62e5a586 ("ovl: detect overlapping layers") in v5.2, re-introduced exclusive upper/work dir checks regardless of index=off configuration. This changes the status quo and mount leak related bug reports have started to re-surface. Restore the status quo to fix the regressions. To clarify, index=off does NOT relax overlapping layers check for this ovelayfs mount. index=off only relaxes exclusive upper/work dir checks with another overlayfs mount. To cover the part of overlapping layers detection that used the exclusive upper/work dir checks to detect overlap with self upper/work dir, add a trap also on the work base dir. Link: https://github.com/moby/moby/issues/34672 Link: https://lore.kernel.org/linux-fsdevel/20171006121405.GA32700@veci.piliscsaba.szeredi.hu/ Link: https://github.com/containers/libpod/issues/3540 Fixes: 146d62e5a586 ("ovl: detect overlapping layers") Cc: # v4.19+ Signed-off-by: Amir Goldstein Tested-by: Colin Walters Signed-off-by: Miklos Szeredi --- Documentation/filesystems/overlayfs.txt | 2 +- fs/overlayfs/ovl_entry.h | 1 + fs/overlayfs/super.c | 73 ++++++++++++++++--------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt index 1da2f1668f08..845d689e0fd7 100644 --- a/Documentation/filesystems/overlayfs.txt +++ b/Documentation/filesystems/overlayfs.txt @@ -302,7 +302,7 @@ beneath or above the path of another overlay lower layer path. Using an upper layer path and/or a workdir path that are already used by another overlay mount is not allowed and may fail with EBUSY. Using -partially overlapping paths is not allowed but will not fail with EBUSY. +partially overlapping paths is not allowed and may fail with EBUSY. If files are accessed from two overlayfs mounts which share or overlap the upper layer and/or workdir path the behavior of the overlay is undefined, though it will not result in a crash or deadlock. diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 28a2d12a1029..a8279280e88d 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -66,6 +66,7 @@ struct ovl_fs { bool workdir_locked; /* Traps in ovl inode cache */ struct inode *upperdir_trap; + struct inode *workbasedir_trap; struct inode *workdir_trap; struct inode *indexdir_trap; /* Inode numbers in all layers do not use the high xino_bits */ diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index b368e2e102fa..afbcb116a7f1 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -212,6 +212,7 @@ static void ovl_free_fs(struct ovl_fs *ofs) { unsigned i; + iput(ofs->workbasedir_trap); iput(ofs->indexdir_trap); iput(ofs->workdir_trap); iput(ofs->upperdir_trap); @@ -1003,6 +1004,25 @@ static int ovl_setup_trap(struct super_block *sb, struct dentry *dir, return 0; } +/* + * Determine how we treat concurrent use of upperdir/workdir based on the + * index feature. This is papering over mount leaks of container runtimes, + * for example, an old overlay mount is leaked and now its upperdir is + * attempted to be used as a lower layer in a new overlay mount. + */ +static int ovl_report_in_use(struct ovl_fs *ofs, const char *name) +{ + if (ofs->config.index) { + pr_err("overlayfs: %s is in-use as upperdir/workdir of another mount, mount with '-o index=off' to override exclusive upperdir protection.\n", + name); + return -EBUSY; + } else { + pr_warn("overlayfs: %s is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.\n", + name); + return 0; + } +} + static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, struct path *upperpath) { @@ -1040,14 +1060,12 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); ofs->upper_mnt = upper_mnt; - err = -EBUSY; if (ovl_inuse_trylock(ofs->upper_mnt->mnt_root)) { ofs->upperdir_locked = true; - } else if (ofs->config.index) { - pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); - goto out; } else { - pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); + err = ovl_report_in_use(ofs, "upperdir"); + if (err) + goto out; } err = 0; @@ -1157,16 +1175,19 @@ static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ofs, ofs->workbasedir = dget(workpath.dentry); - err = -EBUSY; if (ovl_inuse_trylock(ofs->workbasedir)) { ofs->workdir_locked = true; - } else if (ofs->config.index) { - pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); - goto out; } else { - pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); + err = ovl_report_in_use(ofs, "workdir"); + if (err) + goto out; } + err = ovl_setup_trap(sb, ofs->workbasedir, &ofs->workbasedir_trap, + "workdir"); + if (err) + goto out; + err = ovl_make_workdir(sb, ofs, &workpath); out: @@ -1313,16 +1334,16 @@ static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs, if (err < 0) goto out; - err = -EBUSY; - if (ovl_is_inuse(stack[i].dentry)) { - pr_err("overlayfs: lowerdir is in-use as upperdir/workdir\n"); - goto out; - } - err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir"); if (err) goto out; + if (ovl_is_inuse(stack[i].dentry)) { + err = ovl_report_in_use(ofs, "lowerdir"); + if (err) + goto out; + } + mnt = clone_private_mount(&stack[i]); err = PTR_ERR(mnt); if (IS_ERR(mnt)) { @@ -1469,8 +1490,8 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb, * - another layer of this overlayfs instance * - upper/work dir of any overlayfs instance */ -static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, - const char *name) +static int ovl_check_layer(struct super_block *sb, struct ovl_fs *ofs, + struct dentry *dentry, const char *name) { struct dentry *next = dentry, *parent; int err = 0; @@ -1482,13 +1503,11 @@ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, /* Walk back ancestors to root (inclusive) looking for traps */ while (!err && parent != next) { - if (ovl_is_inuse(parent)) { - err = -EBUSY; - pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n", - name); - } else if (ovl_lookup_trap_inode(sb, parent)) { + if (ovl_lookup_trap_inode(sb, parent)) { err = -ELOOP; pr_err("overlayfs: overlapping %s path\n", name); + } else if (ovl_is_inuse(parent)) { + err = ovl_report_in_use(ofs, name); } next = parent; parent = dget_parent(next); @@ -1509,7 +1528,8 @@ static int ovl_check_overlapping_layers(struct super_block *sb, int i, err; if (ofs->upper_mnt) { - err = ovl_check_layer(sb, ofs->upper_mnt->mnt_root, "upperdir"); + err = ovl_check_layer(sb, ofs, ofs->upper_mnt->mnt_root, + "upperdir"); if (err) return err; @@ -1520,13 +1540,14 @@ static int ovl_check_overlapping_layers(struct super_block *sb, * workbasedir. In that case, we already have their traps in * inode cache and we will catch that case on lookup. */ - err = ovl_check_layer(sb, ofs->workbasedir, "workdir"); + err = ovl_check_layer(sb, ofs, ofs->workbasedir, "workdir"); if (err) return err; } for (i = 0; i < ofs->numlower; i++) { - err = ovl_check_layer(sb, ofs->lower_layers[i].mnt->mnt_root, + err = ovl_check_layer(sb, ofs, + ofs->lower_layers[i].mnt->mnt_root, "lowerdir"); if (err) return err; -- GitLab From 8a6836ee384909ae01e3bd0731d082e0e6667e54 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 16 May 2019 17:56:14 -0500 Subject: [PATCH 0013/7155] ARM: dts: at91: Avoid colliding 'display' node and property names While properties and child nodes with the same name are valid DT, the practice is not encouraged. Furthermore, the collision is problematic for YAML encoded DT. Let's just avoid the issue and rename the nodes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20190516225614.1458-1-robh@kernel.org Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9261ek.dts | 2 +- arch/arm/boot/dts/at91sam9263ek.dts | 2 +- arch/arm/boot/dts/at91sam9m10g45ek.dts | 2 +- arch/arm/boot/dts/at91sam9rlek.dts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts index 7debdeabcf2f..c4ef74fea97c 100644 --- a/arch/arm/boot/dts/at91sam9261ek.dts +++ b/arch/arm/boot/dts/at91sam9261ek.dts @@ -40,7 +40,7 @@ atmel,power-control-gpio = <&pioA 12 GPIO_ACTIVE_LOW>; status = "okay"; - display0: display { + display0: panel { bits-per-pixel = <16>; atmel,lcdcon-backlight; atmel,dmacon = <0x1>; diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts index 45e0c6e88cab..62d218542a48 100644 --- a/arch/arm/boot/dts/at91sam9263ek.dts +++ b/arch/arm/boot/dts/at91sam9263ek.dts @@ -110,7 +110,7 @@ display = <&display0>; status = "okay"; - display0: display { + display0: panel { bits-per-pixel = <16>; atmel,lcdcon-backlight; atmel,dmacon = <0x1>; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 06d74ff1a7d0..84bed6f55fcd 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -235,7 +235,7 @@ display = <&display0>; status = "okay"; - display0: display { + display0: panel { bits-per-pixel = <32>; atmel,lcdcon-backlight; atmel,dmacon = <0x1>; diff --git a/arch/arm/boot/dts/at91sam9rlek.dts b/arch/arm/boot/dts/at91sam9rlek.dts index 3a3869444fdc..0de75d3c4f18 100644 --- a/arch/arm/boot/dts/at91sam9rlek.dts +++ b/arch/arm/boot/dts/at91sam9rlek.dts @@ -36,7 +36,7 @@ display = <&display0>; status = "okay"; - display0: display { + display0: panel { bits-per-pixel = <16>; atmel,lcdcon-backlight; atmel,dmacon = <0x1>; -- GitLab From ff0ebee239ce3461cab68ebb8e1a359fc34329de Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2019 12:18:05 -0400 Subject: [PATCH 0014/7155] filename_lookup(): audit_inode() argument is always 0 We hadn't been passing LOOKUP_PARENT in flags to that thing since filename_parentat() had been split off back in 2015. Signed-off-by: Al Viro --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 209c51a5226c..83e5fb3fad76 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2350,7 +2350,7 @@ int filename_lookup(int dfd, struct filename *name, unsigned flags, retval = path_lookupat(&nd, flags | LOOKUP_REVAL, path); if (likely(!retval)) - audit_inode(name, path->dentry, flags & LOOKUP_PARENT); + audit_inode(name, path->dentry, 0); restore_nameidata(); putname(name); return retval; -- GitLab From 39145f5f0cc924b494ad55a2bc9c1b4969b5a038 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2019 12:19:57 -0400 Subject: [PATCH 0015/7155] filename_mountpoint(): make LOOKUP_NO_EVAL unconditional there user_path_mountpoint_at() always gets it and the reasons to have it there (i.e. in umount(2)) apply to kern_path_mountpoint() callers as well. Signed-off-by: Al Viro --- fs/namei.c | 2 +- fs/namespace.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 83e5fb3fad76..5b8c72dc0217 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2718,7 +2718,7 @@ filename_mountpoint(int dfd, struct filename *name, struct path *path, if (unlikely(error == -ESTALE)) error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path); if (likely(!error)) - audit_inode(name, path->dentry, flags & LOOKUP_NO_EVAL); + audit_inode(name, path->dentry, LOOKUP_NO_EVAL); restore_nameidata(); putname(name); return error; diff --git a/fs/namespace.c b/fs/namespace.c index 6464ea4acba9..697f8820dff5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1675,8 +1675,6 @@ int ksys_umount(char __user *name, int flags) if (!(flags & UMOUNT_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; - lookup_flags |= LOOKUP_NO_EVAL; - retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path); if (retval) goto out; -- GitLab From c9b07eab0c8760bdd4cf8624c482ee145a322a3b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2019 13:22:27 -0400 Subject: [PATCH 0016/7155] audit_inode(): switch to passing AUDIT_INODE_... don't bother with remapping LOOKUP_... values - all callers pass constants and we can just as well pass the right ones from the very beginning. Signed-off-by: Al Viro --- fs/namei.c | 6 +++--- include/linux/audit.h | 20 +++++++------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 5b8c72dc0217..3fca26398bc2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2391,7 +2391,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name, if (likely(!retval)) { *last = nd.last; *type = nd.last_type; - audit_inode(name, parent->dentry, LOOKUP_PARENT); + audit_inode(name, parent->dentry, AUDIT_INODE_PARENT); } else { putname(name); name = ERR_PTR(retval); @@ -2718,7 +2718,7 @@ filename_mountpoint(int dfd, struct filename *name, struct path *path, if (unlikely(error == -ESTALE)) error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path); if (likely(!error)) - audit_inode(name, path->dentry, LOOKUP_NO_EVAL); + audit_inode(name, path->dentry, AUDIT_INODE_NOEVAL); restore_nameidata(); putname(name); return error; @@ -3299,7 +3299,7 @@ static int do_last(struct nameidata *nd, if (error) return error; - audit_inode(nd->name, dir, LOOKUP_PARENT); + audit_inode(nd->name, dir, AUDIT_INODE_PARENT); /* trailing slashes? */ if (unlikely(nd->last.name[nd->last.len])) return -EISDIR; diff --git a/include/linux/audit.h b/include/linux/audit.h index 97d0925454df..543763ab0354 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -252,6 +252,10 @@ static inline int audit_signal_info(int sig, struct task_struct *t) #define audit_is_compat(arch) false #endif +#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ +#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ +#define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */ + #ifdef CONFIG_AUDITSYSCALL #include /* for syscall_get_arch() */ @@ -265,9 +269,6 @@ extern void __audit_syscall_exit(int ret_success, long ret_value); extern struct filename *__audit_reusename(const __user char *uptr); extern void __audit_getname(struct filename *name); -#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ -#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ -#define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */ extern void __audit_inode(struct filename *name, const struct dentry *dentry, unsigned int flags); extern void __audit_file(const struct file *); @@ -328,16 +329,9 @@ static inline void audit_getname(struct filename *name) } static inline void audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int flags) { - if (unlikely(!audit_dummy_context())) { - unsigned int aflags = 0; - - if (flags & LOOKUP_PARENT) - aflags |= AUDIT_INODE_PARENT; - if (flags & LOOKUP_NO_EVAL) - aflags |= AUDIT_INODE_NOEVAL; + unsigned int aflags) { + if (unlikely(!audit_dummy_context())) __audit_inode(name, dentry, aflags); - } } static inline void audit_file(struct file *file) { @@ -561,7 +555,7 @@ static inline void __audit_inode_child(struct inode *parent, { } static inline void audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int parent) + unsigned int aflags) { } static inline void audit_file(struct file *file) { -- GitLab From 95671ec23696d7351b47d159159c6bdcb64fafe4 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 1 Apr 2019 10:17:23 -0700 Subject: [PATCH 0017/7155] ARM: dts: rockchip: Specify rk3288-veyron-chromebook's display timings Let's document the display timings that most veyron chromebooks (like jaq, jerry, mighty, speedy) have been using out in the field. This uses the standard blankings but a slightly slower clock rate, thus getting a refresh rate 58.3 Hz. NOTE: this won't really do anything except cause DRM to properly report the refresh rate since vop_crtc_mode_fixup() was rounding the pixel clock to 74.25 MHz anyway. Apparently the adjusted rate isn't exposed to userspace so it's important that the rate we're trying to achieve is mostly right. For the downstream kernel change related to this see See https://crrev.com/c/324558. NOTE: minnie uses a different panel will be fixed up in a future patch, so for now we'll just delete the panel timings there. Signed-off-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/rk3288-veyron-minnie.dts | 2 ++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi index 1cadb522fd0d..6a28ce345ba0 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi @@ -91,6 +91,20 @@ power-supply = <&vcc33_lcd>; backlight = <&backlight>; + panel-timing { + clock-frequency = <74250000>; + hactive = <1366>; + hfront-porch = <136>; + hback-porch = <60>; + hsync-len = <30>; + hsync-active = <0>; + vactive = <768>; + vfront-porch = <8>; + vback-porch = <12>; + vsync-len = <12>; + vsync-active = <0>; + }; + ports { panel_in: port { panel_in_edp: endpoint { diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts index 9008e703c07e..92ab897edb1b 100644 --- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts +++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts @@ -138,6 +138,8 @@ &panel { compatible = "auo,b101ean01", "simple-panel"; power-supply= <&panel_regulator>; + + /delete-node/ panel-timing; }; &rk808 { -- GitLab From 123643e5c40a9c7d77649e306ccb5b0354938d49 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 1 Apr 2019 10:17:24 -0700 Subject: [PATCH 0018/7155] ARM: dts: rockchip: Specify rk3288-veyron-minnie's display timings Just like we did for rk3288-veyron-chromebook, we want to be able to use one of the fixed PLLs in the system to make the pixel clock for minnie. Specifying these timings matches us with how the display is used on the downstream Chrome OS kernel. See https://crrev.com/c/323211. Unlike what we did for rk3288-veyron-chromebook, this CL actually changes the timings (though not the pixel clock) that is used when using the upstream kernel. Booting up a minnie shows that it ended up with a 66.67 MHz pixel clock but it was still using the porches/blankings it would have wanted for a 72.5 MHz pixel clock. NOTE: compared to the downstream kernel, this seems to cause a slightly different result reported in the 'modetest' command on a Chromebook. The downstream kernel shows: 1280x800 60 1280 1298 1330 1351 800 804 822 830 66667 With this patch we have: 1280x800 59 1280 1298 1330 1351 800 804 822 830 66666 Specifically modetest was reporting 60 Hz on the downstream kernel but the upstream kernel does the math and comesup with 59 (because we actually achieve 59.45 Hz). Also upstream doesn't round the Hz up when converting to kHz--it seems to truncate. ALSO NOTE: when I look at the EDID from the datasheet, I see: -hsync -vsync ...but it seems like we've never actually run with that so I've continued leaving that out. Signed-off-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-minnie.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts index 92ab897edb1b..4cc7d3659484 100644 --- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts +++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts @@ -140,6 +140,18 @@ power-supply= <&panel_regulator>; /delete-node/ panel-timing; + + panel-timing { + clock-frequency = <66666667>; + hactive = <1280>; + hfront-porch = <18>; + hback-porch = <21>; + hsync-len = <32>; + vactive = <800>; + vfront-porch = <4>; + vback-porch = <8>; + vsync-len = <18>; + }; }; &rk808 { -- GitLab From 84ebd2da6d046781a67430cf3e6a138afe2ce15e Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 1 Apr 2019 10:17:20 -0700 Subject: [PATCH 0019/7155] arm64: dts: rockchip: Specify override mode for kevin panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds an override mode for kevin devices. The mode increases both back porches to allow a pixel clock of 26666kHz as opposed to the 'typical' value of 252750kHz. This is needed to avoid interference with the touch digitizer on these laptops. Cc: Doug Anderson Cc: Eric Anholt Cc: Heiko Stuebner Cc: Jeffy Chen Cc: Rob Herring Cc: Stéphane Marchesin Cc: Thierry Reding Cc: devicetree@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-rockchip@lists.infradead.org Signed-off-by: Sean Paul Tested-by: Enric Balletbo i Serra Signed-off-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index 3e2272b56eb7..e152b0ca0290 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -43,6 +43,20 @@ backlight = <&backlight>; power-supply = <&pp3300_disp>; + panel-timing { + clock-frequency = <266604720>; + hactive = <2400>; + hfront-porch = <48>; + hback-porch = <84>; + hsync-len = <32>; + hsync-active = <0>; + vactive = <1600>; + vfront-porch = <3>; + vback-porch = <120>; + vsync-len = <10>; + vsync-active = <0>; + }; + port { panel_in_edp: endpoint { remote-endpoint = <&edp_out_panel>; -- GitLab From 849b7e3bb2029cfd6fb353509449b5fac914e682 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 24 Jun 2019 11:30:44 -0700 Subject: [PATCH 0020/7155] dt-bindings: arm: fsl: Add support for ZII i.MX7 RMU2 board Add support for ZII i.MX7 RMU2 board. Signed-off-by: Andrey Smirnov Reviewed-by: Fabio Estevam Reviewed-by: Rob Herring Cc: Shawn Guo Cc: Chris Healy Cc: Lucas Stach Cc: Fabio Estevam Cc: Bob Langer Cc: Liang Pan Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 7294ac36f4c0..fec6b07f8a23 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -188,6 +188,7 @@ properties: - fsl,imx7d-sdb # i.MX7 SabreSD Board - novtech,imx7d-meerkat96 # i.MX7 Meerkat96 Board - tq,imx7d-mba7 # i.MX7D TQ MBa7 with TQMa7D SoM + - zii,imx7d-rmu2 # ZII RMU2 Board - zii,imx7d-rpu2 # ZII RPU2 Board - const: fsl,imx7d -- GitLab From 7f4e4afa140cd3bccd0f0b408f7c4a211eaef2ac Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Wed, 17 Jul 2019 14:47:10 +0800 Subject: [PATCH 0021/7155] arm64: defconfig: Enable SDMA on i.mx8mq/8mm Enable SDMA support on i.mx8mq/8mm chips, including enabling CONFIG_FW_LOADER_USER_HELPER/CONFIG_FW_LOADER_USER_HELPER_FALLBACK for firmware loaded by udev. Signed-off-by: Robin Gong Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0e58ef02880c..30b996b27580 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -196,6 +196,8 @@ CONFIG_PCIE_HISI_STB=y CONFIG_PCIE_TEGRA194=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_HISILICON_LPC=y CONFIG_SIMPLE_PM_BUS=y CONFIG_MTD=y @@ -651,6 +653,7 @@ CONFIG_DMADEVICES=y CONFIG_FSL_EDMA=y CONFIG_DMA_BCM2835=m CONFIG_DMA_SUN6I=m +CONFIG_IMX_SDMA=y CONFIG_K3_DMA=y CONFIG_MV_XOR=y CONFIG_MV_XOR_V2=y -- GitLab From 4d53ea811b212b58b5696ef501b6822430253ba9 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 11 Jun 2019 20:25:35 +0800 Subject: [PATCH 0022/7155] arm64: defconfig: Select CONFIG_PINCTRL_IMX8MN by default Enable CONFIG_PINCTRL_IMX8MN by default to support i.MX8MN pinctrl driver. Signed-off-by: Anson Huang Reviewed-by: Dong Aisheng Acked-by: Linus Walleij Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 30b996b27580..989165fa3aed 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -394,6 +394,7 @@ CONFIG_SPMI=y CONFIG_PINCTRL_SINGLE=y CONFIG_PINCTRL_MAX77620=y CONFIG_PINCTRL_IMX8MM=y +CONFIG_PINCTRL_IMX8MN=y CONFIG_PINCTRL_IMX8MQ=y CONFIG_PINCTRL_IMX8QXP=y CONFIG_PINCTRL_IPQ8074=y -- GitLab From 3026d0b7a4972fd5fb56f5a454d1efe7534e84fc Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 18 Jul 2019 15:13:11 +0800 Subject: [PATCH 0023/7155] soc: imx8: Add i.MX8MQ UID(unique identifier) support Add i.MX8MQ SoC UID(unique identifier) support, user can read it from sysfs: root@imx8mqevk:~# cat /sys/devices/soc0/soc_uid D56911D6F060954B Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c index f924ae8c6514..c19ef4b95668 100644 --- a/drivers/soc/imx/soc-imx8.c +++ b/drivers/soc/imx/soc-imx8.c @@ -16,6 +16,9 @@ #define IMX8MQ_SW_INFO_B1 0x40 #define IMX8MQ_SW_MAGIC_B1 0xff0055aa +#define OCOTP_UID_LOW 0x410 +#define OCOTP_UID_HIGH 0x420 + /* Same as ANADIG_DIGPROG_IMX7D */ #define ANADIG_DIGPROG_IMX8MM 0x800 @@ -24,6 +27,16 @@ struct imx8_soc_data { u32 (*soc_revision)(void); }; +static u64 soc_uid; + +static ssize_t soc_uid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%016llX\n", soc_uid); +} + +static DEVICE_ATTR_RO(soc_uid); + static u32 __init imx8mq_soc_revision(void) { struct device_node *np; @@ -42,6 +55,10 @@ static u32 __init imx8mq_soc_revision(void) if (magic == IMX8MQ_SW_MAGIC_B1) rev = REV_B1; + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + iounmap(ocotp_base); out: @@ -140,6 +157,11 @@ static int __init imx8_soc_init(void) goto free_rev; } + ret = device_create_file(soc_device_to_device(soc_dev), + &dev_attr_soc_uid); + if (ret) + goto free_rev; + if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); -- GitLab From 8dfe397431e0e05d9e66a9f20511833bda91f978 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Jun 2019 15:44:15 +0800 Subject: [PATCH 0024/7155] soc: imx8: Add i.MX8MM UID(unique identifier) support Add i.MX8MM SoC UID(unique identifier) support, user can read it from sysfs: root@imx8mmevk:~# cat /sys/devices/soc0/soc_uid B365FA0A5C85D6EE Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx8.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c index c19ef4b95668..b9831576dd25 100644 --- a/drivers/soc/imx/soc-imx8.c +++ b/drivers/soc/imx/soc-imx8.c @@ -66,6 +66,26 @@ static u32 __init imx8mq_soc_revision(void) return rev; } +static void __init imx8mm_soc_uid(void) +{ + void __iomem *ocotp_base; + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp"); + if (!np) + return; + + ocotp_base = of_iomap(np, 0); + WARN_ON(!ocotp_base); + + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + + iounmap(ocotp_base); + of_node_put(np); +} + static u32 __init imx8mm_soc_revision(void) { struct device_node *np; @@ -83,6 +103,9 @@ static u32 __init imx8mm_soc_revision(void) iounmap(anatop_base); of_node_put(np); + + imx8mm_soc_uid(); + return rev; } -- GitLab From c6c0ad740916425669d5c4a64cf1436f76e40065 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 10 Jun 2019 16:17:50 +0800 Subject: [PATCH 0025/7155] ARM: dts: imx6ul: add dma support on ecspi Add dma support on ecspi. Signed-off-by: Robin Gong Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 81d4b4925127..33d3468c0222 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -227,6 +227,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI1>, <&clks IMX6UL_CLK_ECSPI1>; clock-names = "ipg", "per"; + dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -239,6 +241,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI2>, <&clks IMX6UL_CLK_ECSPI2>; clock-names = "ipg", "per"; + dmas = <&sdma 5 7 1>, <&sdma 6 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -251,6 +255,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI3>, <&clks IMX6UL_CLK_ECSPI3>; clock-names = "ipg", "per"; + dmas = <&sdma 7 7 1>, <&sdma 8 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -263,6 +269,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI4>, <&clks IMX6UL_CLK_ECSPI4>; clock-names = "ipg", "per"; + dmas = <&sdma 9 7 1>, <&sdma 10 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; -- GitLab From 779988c5e61847774d81ec43d77b244f43ea6d79 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 10 Jun 2019 16:17:51 +0800 Subject: [PATCH 0026/7155] ARM: dts: imx6sll: correct sdma compatible Correct sdma compatible since ecspi errata ERR009165 has been fixed on i.mx6sll as i.mx6ul. Signed-off-by: Robin Gong Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sll.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index b0a77ff70b67..97bb1e7cb0cc 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -621,7 +621,7 @@ }; sdma: dma-controller@20ec000 { - compatible = "fsl,imx6sll-sdma", "fsl,imx35-sdma"; + compatible = "fsl,imx6sll-sdma", "fsl,imx6ul-sdma"; reg = <0x020ec000 0x4000>; interrupts = ; clocks = <&clks IMX6SLL_CLK_IPG>, -- GitLab From f496e6750083af4200e2f8fb9914db9c1bf93d32 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 24 Jun 2019 11:30:43 -0700 Subject: [PATCH 0027/7155] ARM: dts: Add ZII support for ZII i.MX7 RMU2 board Add support for ZII's i.MX7 based Remote Modem Unit 2 (RMU2) board. Signed-off-by: Andrey Smirnov Reviewed-by: Fabio Estevam Cc: Shawn Guo Cc: Rob Herring Cc: Chris Healy Cc: Lucas Stach Cc: Fabio Estevam Cc: Bob Langer Cc: Liang Pan Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: devicetree@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx7d-zii-rmu2.dts | 357 +++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 arch/arm/boot/dts/imx7d-zii-rmu2.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9159fa2cea90..4653ddc9d5fb 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -594,6 +594,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-sdb.dtb \ imx7d-sdb-reva.dtb \ imx7d-sdb-sht11.dtb \ + imx7d-zii-rmu2.dtb \ imx7d-zii-rpu2.dtb \ imx7s-colibri-eval-v3.dtb \ imx7s-mba7.dtb \ diff --git a/arch/arm/boot/dts/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/imx7d-zii-rmu2.dts new file mode 100644 index 000000000000..2b8d6cc45a53 --- /dev/null +++ b/arch/arm/boot/dts/imx7d-zii-rmu2.dts @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device tree file for ZII's RMU2 board + * + * RMU - Remote Modem Unit + * + * Copyright (C) 2019 Zodiac Inflight Innovations + */ + +/dts-v1/; +#include +#include "imx7d.dtsi" + +/ { + model = "ZII RMU2 Board"; + compatible = "zii,imx7d-rmu2", "fsl,imx7d"; + + chosen { + stdout-path = &uart2; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&pinctrl_leds_debug>; + pinctrl-names = "default"; + + debug { + label = "zii:green:debug1"; + gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&cpu0 { + arm-supply = <&sw1a_reg>; +}; + +&ecspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + cs-gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <20000000>; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>, + <&clks IMX7D_ENET1_TIME_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>; + assigned-clock-rates = <0>, <100000000>; + phy-mode = "rgmii"; + phy-handle = <&fec1_phy>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + fec1_phy: ethernet-phy@0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1_phy_reset>, + <&pinctrl_enet1_phy_interrupt>; + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic@8 { + compatible = "fsl,pfuze3000"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1a { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw1c_reg: sw1b { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1475000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1850000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1650000>; + regulator-boot-on; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + vgen1_reg: vldo1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen2_reg: vldo2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + regulator-always-on; + }; + + vgen3_reg: vccsd { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen4_reg: v33 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vldo4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; + + eeprom@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + + eeprom@52 { + compatible = "atmel,24c04"; + reg = <0x52>; + }; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + assigned-clocks = <&clks IMX7D_UART4_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>; + status = "okay"; + + rave-sp { + compatible = "zii,rave-sp-rdu2"; + current-speed = <1000000>; + #address-cells = <1>; + #size-cells = <1>; + + watchdog { + compatible = "zii,rave-sp-watchdog"; + }; + + eeprom@a3 { + compatible = "zii,rave-sp-eeprom"; + reg = <0xa3 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + zii,eeprom-name = "main-eeprom"; + }; + }; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + bus-width = <4>; + no-1-8-v; + no-sdio; + keep-power-in-suspend; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + bus-width = <8>; + no-1-8-v; + non-removable; + no-sdio; + no-sd; + keep-power-in-suspend; + status = "okay"; +}; + +&wdog1 { + status = "disabled"; +}; + +&iomuxc { + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x2 + MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x2 + MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO 0x2 + MX7D_PAD_ECSPI1_SS0__GPIO4_IO19 0x59 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX7D_PAD_SD2_CD_B__ENET1_MDIO 0x3 + MX7D_PAD_SD2_WP__ENET1_MDC 0x3 + MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1 + MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1 + MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1 + MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1 + MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1 + MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1 + MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1 + MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1 + MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1 + MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1 + MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1 + MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1 + >; + }; + + pinctrl_enet1_phy_reset: enet1phyresetgrp { + fsl,pins = < + MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x14 + + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f + MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f + >; + }; + + pinctrl_leds_debug: ledsgrp { + fsl,pins = < + MX7D_PAD_EPDC_DATA08__GPIO2_IO8 0x59 + >; + }; + + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x79 + MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 0x79 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX7D_PAD_SD2_DATA0__UART4_DCE_RX 0x79 + MX7D_PAD_SD2_DATA1__UART4_DCE_TX 0x79 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x59 + MX7D_PAD_SD1_CLK__SD1_CLK 0x19 + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59 + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX7D_PAD_SD3_CMD__SD3_CMD 0x59 + MX7D_PAD_SD3_CLK__SD3_CLK 0x19 + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59 + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59 + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59 + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59 + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59 + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59 + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59 + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59 + MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x59 + >; + }; +}; + +&iomuxc_lpsr { + pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp { + fsl,phy = < + MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x08 + >; + }; +}; -- GitLab From 4931b5f160164807c33f0d935c76781695ab7757 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 24 Jun 2019 17:54:31 -0300 Subject: [PATCH 0028/7155] ARM: dts: imx7d-zii-rpu2: Remove unneeded snvs_pwrkey node Since commit 4664179fe679 ("ARM: dts: imx7s: Enable SNVS power key according to board design") snvs_pwrkey is disabled by default, so there is no need for disabling it explicitly in the board dts anymore. Signed-off-by: Fabio Estevam Reviewed-by: Chris Healy Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7d-zii-rpu2.dts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/imx7d-zii-rpu2.dts b/arch/arm/boot/dts/imx7d-zii-rpu2.dts index 4a78ddc7513d..39812c92bf0d 100644 --- a/arch/arm/boot/dts/imx7d-zii-rpu2.dts +++ b/arch/arm/boot/dts/imx7d-zii-rpu2.dts @@ -669,10 +669,6 @@ status = "disabled"; }; -&snvs_pwrkey { - status = "disabled"; -}; - &iomuxc { pinctrl_ecspi1: ecspi1grp { fsl,pins = < -- GitLab From 5f7a6cd1345716195c27876b1b2a100291da6bab Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 24 Jun 2019 17:54:32 -0300 Subject: [PATCH 0029/7155] ARM: dts: imx7-colibri: Remove unneeded snvs_pwrkey node Since commit 4664179fe679 ("ARM: dts: imx7s: Enable SNVS power key according to board design") snvs_pwrkey is disabled by default, so there is no need for disabling it explicitly in the board dts anymore. Signed-off-by: Fabio Estevam Reviewed-by: Chris Healy Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7-colibri.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index 895fbde4d433..0d00aeb64336 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -267,10 +267,6 @@ status = "okay"; }; -&snvs_pwrkey { - status = "disabled"; -}; - &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_ctrl1 &pinctrl_uart1_ctrl2>; -- GitLab From 0be9af7770493955a27b704bf502b146f8167b6e Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Thu, 18 Jul 2019 10:48:18 +0800 Subject: [PATCH 0030/7155] ARM: dts: imx7ulp: add edma device node Add edma device node in dts. Signed-off-by: Robin Gong Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7ulp.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi index 992747a57442..f689ce596080 100644 --- a/arch/arm/boot/dts/imx7ulp.dtsi +++ b/arch/arm/boot/dts/imx7ulp.dtsi @@ -101,6 +101,34 @@ reg = <0x40000000 0x800000>; ranges; + edma1: dma-controller@40080000 { + #dma-cells = <2>; + compatible = "fsl,imx7ulp-edma"; + reg = <0x40080000 0x2000>, + <0x40210000 0x1000>; + dma-channels = <32>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + clock-names = "dma", "dmamux0"; + clocks = <&pcc2 IMX7ULP_CLK_DMA1>, + <&pcc2 IMX7ULP_CLK_DMA_MUX1>; + }; + crypto: crypto@40240000 { compatible = "fsl,sec-v4.0"; #address-cells = <1>; -- GitLab From a99b26b14bea50624db9e971f7b9e422ee2bb6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 25 Jun 2019 10:27:20 +0200 Subject: [PATCH 0031/7155] arm64: dts: imx8mq: Add MIPI D-PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a node for the Mixel MIPI D-PHY, "disabled" by default. Signed-off-by: Guido Günther Acked-by: Angus Ainslie (Purism) Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index d09b808eff87..891ee7578c2d 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -728,6 +728,19 @@ status = "disabled"; }; + dphy: dphy@30a00300 { + compatible = "fsl,imx8mq-mipi-dphy"; + reg = <0x30a00300 0x100>; + clocks = <&clk IMX8MQ_CLK_DSI_PHY_REF>; + clock-names = "phy_ref"; + assigned-clocks = <&clk IMX8MQ_CLK_DSI_PHY_REF>; + assigned-clock-parents = <&clk IMX8MQ_VIDEO_PLL1_OUT>; + assigned-clock-rates = <24000000>; + #phy-cells = <0>; + power-domains = <&pgc_mipi>; + status = "disabled"; + }; + i2c1: i2c@30a20000 { compatible = "fsl,imx8mq-i2c", "fsl,imx21-i2c"; reg = <0x30a20000 0x10000>; -- GitLab From 9d9005a5a23fc92832cc1b042ac6de76891caccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 25 Jun 2019 10:27:21 +0200 Subject: [PATCH 0032/7155] arm64: dts: imx8mq-librem5: Enable MIPI D-PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables the Mixel MIPI D-PHY on the Librem 5 devkit Signed-off-by: Guido Günther Acked-by: Angus Ainslie (Purism) Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 5179e22f5126..683a11035643 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -174,6 +174,10 @@ assigned-clock-rates = <786432000>, <722534400>; }; +&dphy { + status = "okay"; +}; + &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_fec1>; -- GitLab From 87ff1f88552a7d3b3f865d89ce4ed002777fe2ab Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 13:52:47 +0800 Subject: [PATCH 0033/7155] arm64: defconfig: Select CONFIG_CLK_IMX8MN by default Enable CONFIG_CLK_IMX8MN to support i.MX8MN clock driver. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 989165fa3aed..ba65833d08cc 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -681,6 +681,7 @@ CONFIG_COMMON_CLK_S2MPS11=y CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_PWM=y CONFIG_CLK_IMX8MM=y +CONFIG_CLK_IMX8MN=y CONFIG_CLK_IMX8MQ=y CONFIG_CLK_IMX8QXP=y CONFIG_TI_SCI_CLK=y -- GitLab From 1991529f0fc91e0931ef534906397138e21f56d3 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 21 Jun 2019 15:07:17 +0800 Subject: [PATCH 0034/7155] arm64: Enable TIMER_IMX_SYS_CTR for ARCH_MXC platforms ARCH_MXC platforms needs system counter as broadcast timer to support cpuidle, enable it by default. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/Kconfig.platforms | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 4778c775de1b..f5e623fca2ec 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -173,6 +173,7 @@ config ARCH_MXC select PM select PM_GENERIC_DOMAINS select SOC_BUS + select TIMER_IMX_SYS_CTR help This enables support for the ARMv8 based SoCs in the NXP i.MX family. -- GitLab From ebf256e36754fc5c4a259bb28f3c0a081eb70467 Mon Sep 17 00:00:00 2001 From: Keyur Patel Date: Sun, 14 Jul 2019 13:27:06 -0400 Subject: [PATCH 0035/7155] staging: most: Delete an error message for a failed memory allocation The kfifo_alloc() failure generates enough information and doesn't need to be accompanied by another error statement. Signed-off-by: Keyur Patel Link: https://lore.kernel.org/r/20190714172708.5067-1-iamkeyur96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index d0cc0b746107..724d098aeef0 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -463,10 +463,8 @@ static int comp_probe(struct most_interface *iface, int channel_id, spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); - if (retval) { - pr_info("failed to alloc channel kfifo"); + if (retval) goto err_del_cdev_and_free_channel; - } init_waitqueue_head(&c->wq); mutex_init(&c->io_mutex); spin_lock_irqsave(&ch_list_lock, cl_flags); -- GitLab From baacd53a3b72d1dc74a340d16b8cf560dfe24717 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 5 Jul 2019 18:41:31 +0530 Subject: [PATCH 0036/7155] staging: greybus: Replace function gb_i2c_device_setup() Remove function gb_i2c_device_setup as all it does is call gb_i2c_functionality_operation. Rename gb_i2c_functionality_operation to gb_i2c_device_setup to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190705131131.27354-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/i2c.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 7bb85a75d3b1..b2522043a1a4 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -31,7 +31,14 @@ static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) return gb_i2c_functionality; /* All bits the same for now */ } -static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) +/* + * Do initial setup of the i2c device. This includes verifying we + * can support it (based on the protocol version it advertises). + * If that's OK, we get and cached its functionality bits. + * + * Note: gb_i2c_dev->connection is assumed to have been valid. + */ +static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) { struct gb_i2c_functionality_response response; u32 functionality; @@ -235,19 +242,6 @@ static const struct i2c_algorithm gb_i2c_algorithm = { .functionality = gb_i2c_functionality, }; -/* - * Do initial setup of the i2c device. This includes verifying we - * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits. - * - * Note: gb_i2c_dev->connection is assumed to have been valid. - */ -static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) -{ - /* Assume the functionality never changes, just get it once */ - return gb_i2c_functionality_operation(gb_i2c_dev); -} - static int gb_i2c_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { -- GitLab From e1928327353d5ddd00b7d4d46f46961ea5c2dc34 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 4 Jul 2019 14:30:31 +0100 Subject: [PATCH 0037/7155] staging: greybus: remove redundant assignment to variable is_empty The variable is_empty is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Vaibhav Agarwal Reviewed-by: Mark Greer Link: https://lore.kernel.org/r/20190704133031.28809-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index c2a4af4c1d06..9b19ea9d3fa1 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_remove); void gb_audio_manager_remove_all(void) { struct gb_audio_manager_module *module, *next; - int is_empty = 1; + int is_empty; down_write(&modules_rwsem); -- GitLab From e82a9a17d49c52a5ea96589a0ee738d3fef33323 Mon Sep 17 00:00:00 2001 From: Pratik Shinde Date: Mon, 15 Jul 2019 17:51:27 +0530 Subject: [PATCH 0038/7155] staging: erofs:converting all 'unsigned' to 'unsigned int' Fixed checkpatch warnings: converting all 'unsigned' to 'unsigned int' Signed-off-by: Pratik Shinde Reviewed-by: Gao Xiang Link: https://lore.kernel.org/r/20190715122127.13733-1-pratikshinde320@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 7 ++++--- drivers/staging/erofs/unzip_pagevec.h | 11 ++++++----- drivers/staging/erofs/unzip_vle.h | 8 ++++---- drivers/staging/erofs/xattr.h | 17 +++++++++-------- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 963cc1b8b896..0ebc294120c2 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -359,8 +359,8 @@ struct erofs_vnode { unsigned char inode_isize; unsigned short xattr_isize; - unsigned xattr_shared_count; - unsigned *xattr_shared_xattrs; + unsigned int xattr_shared_count; + unsigned int *xattr_shared_xattrs; union { erofs_blk_t raw_blkaddr; @@ -510,7 +510,8 @@ erofs_grab_bio(struct super_block *sb, return bio; } -static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags) +static inline void __submit_bio(struct bio *bio, unsigned int op, + unsigned int op_flags) { bio_set_op_attrs(bio, op, op_flags); submit_bio(bio); diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h index 7af0ba8d8495..e65dbca93ae8 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/unzip_pagevec.h @@ -54,9 +54,9 @@ static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, static inline struct page * z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, - unsigned nr) + unsigned int nr) { - unsigned index; + unsigned int index; /* keep away from occupied pages */ if (ctor->next) @@ -64,7 +64,7 @@ z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, for (index = 0; index < nr; ++index) { const erofs_vtptr_t t = ctor->pages[index]; - const unsigned tags = tagptr_unfold_tags(t); + const unsigned int tags = tagptr_unfold_tags(t); if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) return tagptr_unfold_ptr(t); @@ -91,8 +91,9 @@ z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, } static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - unsigned nr, - erofs_vtptr_t *pages, unsigned i) + unsigned int nr, + erofs_vtptr_t *pages, + unsigned int i) { ctor->nr = nr; ctor->curr = ctor->next = NULL; diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h index ab509d75aefd..df91ad149439 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/unzip_vle.h @@ -34,7 +34,7 @@ struct z_erofs_vle_work { unsigned short nr_pages; /* L: queued pages in pagevec[] */ - unsigned vcnt; + unsigned int vcnt; union { /* L: pagevec */ @@ -124,7 +124,7 @@ union z_erofs_onlinepage_converter { unsigned long *v; }; -static inline unsigned z_erofs_onlinepage_index(struct page *page) +static inline unsigned int z_erofs_onlinepage_index(struct page *page) { union z_erofs_onlinepage_converter u; @@ -164,7 +164,7 @@ static inline void z_erofs_onlinepage_fixup(struct page *page, } v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | - ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned)down); + ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); if (cmpxchg(p, o, v) != o) goto repeat; } @@ -172,7 +172,7 @@ static inline void z_erofs_onlinepage_fixup(struct page *page, static inline void z_erofs_onlinepage_endio(struct page *page) { union z_erofs_onlinepage_converter u; - unsigned v; + unsigned int v; DBG_BUGON(!PagePrivate(page)); u.v = &page_private(page); diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 35ba5ac2139a..3990805dfc6c 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -20,14 +20,14 @@ /* Attribute not found */ #define ENOATTR ENODATA -static inline unsigned inlinexattr_header_size(struct inode *inode) +static inline unsigned int inlinexattr_header_size(struct inode *inode) { return sizeof(struct erofs_xattr_ibody_header) + sizeof(u32) * EROFS_V(inode)->xattr_shared_count; } -static inline erofs_blk_t -xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi, + unsigned int xattr_id) { #ifdef CONFIG_EROFS_FS_XATTR return sbi->xattr_blkaddr + @@ -37,8 +37,8 @@ xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) #endif } -static inline unsigned -xattrblock_offset(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, + unsigned int xattr_id) { return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; } @@ -49,7 +49,7 @@ extern const struct xattr_handler erofs_xattr_trusted_handler; extern const struct xattr_handler erofs_xattr_security_handler; #endif -static inline const struct xattr_handler *erofs_xattr_handler(unsigned index) +static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) { static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, @@ -63,8 +63,9 @@ static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, #endif }; - return index && index < ARRAY_SIZE(xattr_handler_map) ? - xattr_handler_map[index] : NULL; + + return idx && idx < ARRAY_SIZE(xattr_handler_map) ? + xattr_handler_map[idx] : NULL; } #ifdef CONFIG_EROFS_FS_XATTR -- GitLab From 2ac3b368f40f31fccad2377939a66e6986b54976 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:42:47 +0530 Subject: [PATCH 0039/7155] staging: erofs: Remove function erofs_kill_sb() Remove function erofs_kill_sb as all it does is call kill_block_super. Modify references to the former to point to the latter. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190712071247.2357-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 54494412eba4..3e2a65ba1945 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -554,16 +554,11 @@ static struct dentry *erofs_mount( &priv, erofs_fill_super); } -static void erofs_kill_sb(struct super_block *sb) -{ - kill_block_super(sb); -} - static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", .mount = erofs_mount, - .kill_sb = erofs_kill_sb, + .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("erofs"); -- GitLab From d327ace0f301c6c203c0ed1aa5da823ab6fef5f6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 09:25:54 +0100 Subject: [PATCH 0040/7155] staging: rtl8712: remove redundant assignment to variable res The variable res is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190705082554.15588-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 307b0e292976..dac79e6dcdcb 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -739,7 +739,7 @@ static void dump_xframe(struct _adapter *padapter, int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - int res = _SUCCESS; + int res; res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); pxmitframe->pkt = NULL; -- GitLab From 8826a1985f96d402a66e25fe6eab09144b4d8003 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:43 +0530 Subject: [PATCH 0041/7155] staging: most: dim2: Replace function dim_norm_ctrl_async_buffer_size() Remove function dim_norm_ctrl_async_buffer_size as it does nothing except call norm_ctrl_async_buffer_size. Rename norm_ctrl_async_buffer_size to dim_norm_ctrl_async_buffer_size to maintain compatibility with call sites of the latter. Change type of new dim_norm_ctrl_async_buffer_size from static inline to non-static to match the old version. Modify only remaining call site of norm_ctrl_async_buffer_size to call dim_norm_ctrl_async_buffer_size instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/hal.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index 699e02f83bd4..d4d532e76147 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -471,7 +471,7 @@ static inline bool check_bytes_per_frame(u32 bytes_per_frame) return true; } -static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) +u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) { u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; @@ -652,7 +652,7 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && - buf_size != norm_ctrl_async_buffer_size(buf_size)) + buf_size != dim_norm_ctrl_async_buffer_size(buf_size)) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad control/async buffer size"); @@ -780,11 +780,6 @@ void dim_service_mlb_int_irq(void) dimcb_io_write(&g.dim2->MS1, 0); } -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) -{ - return norm_ctrl_async_buffer_size(buf_size); -} - /** * Retrieves maximal possible correct buffer size for isochronous data type * conform to given packet length and not bigger than given buffer size. -- GitLab From 41e359e6daf47cd47c9fde77220653886b8f5969 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:44 +0530 Subject: [PATCH 0042/7155] staging: most: dim2: Remove function dimcb_io_read() Remove function dimcb_io_read as it does nothing except call inbuilt function readl. Modify call sites accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/dim2.c | 9 --------- drivers/staging/most/dim2/hal.c | 15 ++++++++------- drivers/staging/most/dim2/hal.h | 2 -- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 31fbc1a75b06..8d3da8e1d436 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -128,15 +128,6 @@ bool dim2_sysfs_get_state_cb(void) return state; } -/** - * dimcb_io_read - callback from HAL to read an I/O register - * @ptr32: register address - */ -u32 dimcb_io_read(u32 __iomem *ptr32) -{ - return readl(ptr32); -} - /** * dimcb_io_write - callback from HAL to write value to an I/O register * @ptr32: register address diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index d4d532e76147..fcf5d2a0f491 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -13,6 +13,7 @@ #include "reg.h" #include #include +#include /* * Size factor for isochronous DBR buffer. @@ -146,7 +147,7 @@ static void dim2_transfer_madr(u32 val) dimcb_io_write(&g.dim2->MADR, val); /* wait for transfer completion */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + while ((readl(&g.dim2->MCTL) & 1) != 1) continue; dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ @@ -170,7 +171,7 @@ static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) { dim2_transfer_madr(ctr_addr); - return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); + return readl((&g.dim2->MDAT0) + mdat_idx); } static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) @@ -357,14 +358,14 @@ static void dim2_configure_channel( /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); + readl(&g.dim2->ACMR0) | bit_mask(ch_addr)); } static void dim2_clear_channel(u8 ch_addr) { /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); dim2_clear_cat(AHB_CAT, ch_addr); dim2_clear_adt(ch_addr); @@ -562,12 +563,12 @@ static bool dim2_is_mlb_locked(void) u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | bit_mask(MLBC1_LOCKERR_BIT); - u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); + u32 const c1 = readl(&g.dim2->MLBC1); u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); - return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && - (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; + return (readl(&g.dim2->MLBC1) & mask1) == 0 && + (readl(&g.dim2->MLBC0) & mask0) != 0; } /* -------------------------------------------------------------------------- */ diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index fca6c22de8a6..d16268bd9317 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -97,8 +97,6 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -u32 dimcb_io_read(u32 __iomem *ptr32); - void dimcb_io_write(u32 __iomem *ptr32, u32 value); void dimcb_on_error(u8 error_id, const char *error_message); -- GitLab From 6fa4e8eb3f1906decdd9d426708bf5134d77f5ad Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:45 +0530 Subject: [PATCH 0043/7155] staging: most: dim2: Remove function dimcb_io_write() Remove function dimcb_io_write as all it does is call writel. Modify calls to dimcb_io_write to writel, flipping the order of the arguments as required. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/dim2.c | 10 ---- drivers/staging/most/dim2/hal.c | 79 +++++++++++++++----------------- drivers/staging/most/dim2/hal.h | 2 - 3 files changed, 38 insertions(+), 53 deletions(-) diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 8d3da8e1d436..043a3e14fdfc 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -128,16 +128,6 @@ bool dim2_sysfs_get_state_cb(void) return state; } -/** - * dimcb_io_write - callback from HAL to write value to an I/O register - * @ptr32: register address - * @value: value to write - */ -void dimcb_io_write(u32 __iomem *ptr32, u32 value) -{ - writel(value, ptr32); -} - /** * dimcb_on_error - callback from HAL to report miscommunication between * HDM and HAL diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index fcf5d2a0f491..39e17a7d2f24 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -144,13 +144,13 @@ static void free_dbr(int offs, int size) static void dim2_transfer_madr(u32 val) { - dimcb_io_write(&g.dim2->MADR, val); + writel(val, &g.dim2->MADR); /* wait for transfer completion */ while ((readl(&g.dim2->MCTL) & 1) != 1) continue; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ } static void dim2_clear_dbr(u16 addr, u16 size) @@ -160,8 +160,8 @@ static void dim2_clear_dbr(u16 addr, u16 size) u16 const end_addr = addr + size; u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - dimcb_io_write(&g.dim2->MDAT0, 0); + writel(0, &g.dim2->MCTL); /* clear transfer complete */ + writel(0, &g.dim2->MDAT0); for (; addr < end_addr; addr++) dim2_transfer_madr(cmd | addr); @@ -178,21 +178,21 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) { enum { MADR_WNR_BIT = 31 }; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ if (mask[0] != 0) - dimcb_io_write(&g.dim2->MDAT0, value[0]); + writel(value[0], &g.dim2->MDAT0); if (mask[1] != 0) - dimcb_io_write(&g.dim2->MDAT1, value[1]); + writel(value[1], &g.dim2->MDAT1); if (mask[2] != 0) - dimcb_io_write(&g.dim2->MDAT2, value[2]); + writel(value[2], &g.dim2->MDAT2); if (mask[3] != 0) - dimcb_io_write(&g.dim2->MDAT3, value[3]); + writel(value[3], &g.dim2->MDAT3); - dimcb_io_write(&g.dim2->MDWE0, mask[0]); - dimcb_io_write(&g.dim2->MDWE1, mask[1]); - dimcb_io_write(&g.dim2->MDWE2, mask[2]); - dimcb_io_write(&g.dim2->MDWE3, mask[3]); + writel(mask[0], &g.dim2->MDWE0); + writel(mask[1], &g.dim2->MDWE1); + writel(mask[2], &g.dim2->MDWE2); + writel(mask[3], &g.dim2->MDWE3); dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } @@ -357,15 +357,13 @@ static void dim2_configure_channel( dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1); /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - readl(&g.dim2->ACMR0) | bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) | bit_mask(ch_addr), &g.dim2->ACMR0); } static void dim2_clear_channel(u8 ch_addr) { /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr), &g.dim2->ACMR0); dim2_clear_cat(AHB_CAT, ch_addr); dim2_clear_adt(ch_addr); @@ -374,7 +372,7 @@ static void dim2_clear_channel(u8 ch_addr) dim2_clear_cdt(ch_addr); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); } /* -------------------------------------------------------------------------- */ @@ -518,20 +516,20 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) static void dim2_cleanup(void) { /* disable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); + writel(false << MLBC0_MLBEN_BIT, &g.dim2->MLBC0); dim2_clear_ctram(); /* disable mlb_int interrupt */ - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); /* clear status for all dma channels */ - dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->ACSR0); + writel(0xFFFFFFFF, &g.dim2->ACSR1); /* mask interrupts for all channels */ - dimcb_io_write(&g.dim2->ACMR0, 0); - dimcb_io_write(&g.dim2->ACMR1, 0); + writel(0, &g.dim2->ACMR0); + writel(0, &g.dim2->ACMR1); } static void dim2_initialize(bool enable_6pin, u8 mlb_clock) @@ -539,23 +537,22 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) dim2_cleanup(); /* configure and enable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, - enable_6pin << MLBC0_MLBPEN_BIT | - mlb_clock << MLBC0_MLBCLK_SHIFT | - g.fcnt << MLBC0_FCNT_SHIFT | - true << MLBC0_MLBEN_BIT); + writel(enable_6pin << MLBC0_MLBPEN_BIT | + mlb_clock << MLBC0_MLBCLK_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | + true << MLBC0_MLBEN_BIT, + &g.dim2->MLBC0); /* activate all HBI channels */ - dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->HCMR0); + writel(0xFFFFFFFF, &g.dim2->HCMR1); /* enable HBI */ - dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); + writel(bit_mask(HCTL_EN_BIT), &g.dim2->HCTL); /* configure DMA */ - dimcb_io_write(&g.dim2->ACTL, - ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | - true << ACTL_SCE_BIT); + writel(ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | + true << ACTL_SCE_BIT, &g.dim2->ACTL); } static bool dim2_is_mlb_locked(void) @@ -566,7 +563,7 @@ static bool dim2_is_mlb_locked(void) u32 const c1 = readl(&g.dim2->MLBC1); u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; - dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); + writel(c1 & nda_mask, &g.dim2->MLBC1); return (readl(&g.dim2->MLBC1) & mask1) == 0 && (readl(&g.dim2->MLBC0) & mask0) != 0; } @@ -591,7 +588,7 @@ static inline bool service_channel(u8 ch_addr, u8 idx) dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); return true; } @@ -777,8 +774,8 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, void dim_service_mlb_int_irq(void) { - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); + writel(0, &g.dim2->MS0); + writel(0, &g.dim2->MS1); } /** @@ -825,7 +822,7 @@ u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, if (is_tx && !g.atx_dbr.ch_addr) { g.atx_dbr.ch_addr = ch->addr; dbrcnt_init(ch->addr, ch->dbr_size); - dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); + writel(bit_mask(20), &g.dim2->MIEN); } return ret; @@ -892,7 +889,7 @@ u8 dim_destroy_channel(struct dim_channel *ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; if (ch->addr == g.atx_dbr.ch_addr) { - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); g.atx_dbr.ch_addr = 0; } diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index d16268bd9317..20531449acab 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -97,8 +97,6 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -void dimcb_io_write(u32 __iomem *ptr32, u32 value); - void dimcb_on_error(u8 error_id, const char *error_message); #endif /* _DIM2_HAL_H */ -- GitLab From 72da91bc590a3a789b2130718c9dc810851273fe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:57:58 +0530 Subject: [PATCH 0044/7155] staging: wlan-ng: Remove function hfa384x_dorrid_wait() Remove function hfa384x_dorrid_wait as it is only called once and it does nothing except call hfa384x_dorrid. Move contents of hfa384x_dorrid_wait to its only call site to maintain functionality. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index ab734534093b..4befc615d8e2 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -834,14 +834,6 @@ hfa384x_docmd_async(struct hfa384x *hw, return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dorrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dorrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - static inline int hfa384x_dorrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, @@ -2061,7 +2053,7 @@ int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, */ int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dorrid_wait(hw, rid, buf, len); + return hfa384x_dorrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- -- GitLab From 83c23c8e79ee85c0e7f71844a50aab0c1156a788 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:57:59 +0530 Subject: [PATCH 0045/7155] staging: wlan-ng: Remove function hfa384x_dowrid_wait() Remove inline function hfa384x_dowrid_wait as it is only called once (in hfa384x_drvr_setconfig) and its contents are only a single line (a call to hfa384x_dowrid). Replace the call to hfa384x_dowrid_wait with its contents i.e the call to hfa384x_dowrid. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 4befc615d8e2..dc6abc654165 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -845,14 +845,6 @@ hfa384x_dorrid_async(struct hfa384x *hw, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dowrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dowrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - static inline int hfa384x_dowrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, @@ -2414,7 +2406,7 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) */ int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dowrid_wait(hw, rid, buf, len); + return hfa384x_dowrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- -- GitLab From 57d100b8aa686ce7bccc74e702aa1f3e8051d518 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:00 +0530 Subject: [PATCH 0046/7155] staging: wlan-ng: Remove function hfa384x_dowrid_async() Remove function hfa384x_dowrid_async as it does nothing except call hfa384x_dowrid, and itself is called only once. Move the contents of hfa384x_dowrid_async (i.e the call to hfa384x_dowrid) to its call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index dc6abc654165..732ffb6aab0b 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -845,17 +845,6 @@ hfa384x_dorrid_async(struct hfa384x *hw, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dowrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -2078,8 +2067,8 @@ hfa384x_drvr_setconfig_async(struct hfa384x *hw, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data) { - return hfa384x_dowrid_async(hw, rid, buf, len, - hfa384x_cb_status, usercb, usercb_data); + return hfa384x_dowrid(hw, DOASYNC, rid, buf, len, hfa384x_cb_status, + usercb, usercb_data); } /*---------------------------------------------------------------- -- GitLab From bb75c586cabd0d192b9e713143f49b44112e64cb Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:01 +0530 Subject: [PATCH 0047/7155] staging: wlan-ng: Remove unused function hfa384x_dorrid_async() Remove unused function hfa384x_dorrid_async. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 732ffb6aab0b..c1a315bf5a81 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -834,17 +834,6 @@ hfa384x_docmd_async(struct hfa384x *hw, return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dorrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dorrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- GitLab From f2a82b0941ea0075fa402792ea8bc9c6c5db7bfe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:02 +0530 Subject: [PATCH 0048/7155] staging: wlan-ng: Remove unused function hfa384x_dormem_async() Remove unused function hfa384x_dormem_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c1a315bf5a81..95dae0b271fc 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -842,17 +842,6 @@ hfa384x_dormem_wait(struct hfa384x *hw, page, offset, data, len, NULL, NULL, NULL); } -static inline int -hfa384x_dormem_async(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dormem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- GitLab From 71b289cc5aa6b3bbe7e1a87612037b2c5bae9649 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:03 +0530 Subject: [PATCH 0049/7155] staging: wlan-ng: Remove function hfa384x_dowmem_async() Remove unused function hfa384x_dowmem_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 95dae0b271fc..20ac2dbd8a00 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -850,20 +850,6 @@ hfa384x_dowmem_wait(struct hfa384x *hw, page, offset, data, len, NULL, NULL, NULL); } -static inline int -hfa384x_dowmem_async(struct hfa384x *hw, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowmem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - /*---------------------------------------------------------------- * hfa384x_cmd_initialize * -- GitLab From aef29ca497f005fe3cd38aefc77639dc551bbd18 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:04 +0530 Subject: [PATCH 0050/7155] staging: wlan-ng: Remove unused function hfa384x_docmd_async() Remove unused function hfa384x_docmd_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 20ac2dbd8a00..ce1a9ee995a0 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -826,14 +826,6 @@ static inline int hfa384x_docmd_wait(struct hfa384x *hw, return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } -static inline int -hfa384x_docmd_async(struct hfa384x *hw, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- GitLab From 53055d6a915cb1753334dc18d6249f8b4ac62d88 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:05 +0530 Subject: [PATCH 0051/7155] staging: wlan-ng: Remove function hfa384x_docmd_wait() As hfa384x_docmd is only called by hfa384x_docmd_wait, and hfa384x_docmd_wait always passes 4 constant arguments (DOWAIT, NULL, NULL, NULL) to hfa384x_docmd, these constant parameters may be removed from hfa384x_docmd and their values used directly instead. Remove check for one of these constant parameters of hfa384x_docmd as it is no longer necessary. Remove hfa384x_docmd_wait as it does nothing except call hfa384x_docmd. Modify call sites of hfa384x_docmd_wait to call hfa384x_docmd instead. Change type of hfa384x_docmd to inline to match type of former hfa384x_docmd_wait. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 43 +++++++++------------------ 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index ce1a9ee995a0..c469b89948e6 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -226,11 +226,9 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + struct hfa384x_metacmd *cmd); static int hfa384x_dorrid(struct hfa384x *hw, @@ -820,12 +818,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int hfa384x_docmd_wait(struct hfa384x *hw, - struct hfa384x_metacmd *cmd) -{ - return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -873,7 +865,7 @@ int hfa384x_cmd_initialize(struct hfa384x *hw) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); + result = hfa384x_docmd(hw, &cmd); pr_debug("cmdresp.init: status=0x%04x, resp0=0x%04x, resp1=0x%04x, resp2=0x%04x\n", cmd.result.status, @@ -919,7 +911,7 @@ int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -953,7 +945,7 @@ int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -996,7 +988,7 @@ int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1053,7 +1045,7 @@ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, cmd.parm1 = highaddr; cmd.parm2 = codelen; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1213,13 +1205,8 @@ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * cmd cmd structure. Includes all arguments and result * data points. All in host order. in host order - * cmdcb command-specific callback - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls, NULL - * for DOWAIT calls * * Returns: * 0 success @@ -1235,11 +1222,9 @@ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, * process *---------------------------------------------------------------- */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + struct hfa384x_metacmd *cmd) { int result; struct hfa384x_usbctlx *ctlx; @@ -1262,15 +1247,15 @@ hfa384x_docmd(struct hfa384x *hw, pr_debug("cmdreq: cmd=0x%04x parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor cmd_completor; struct usbctlx_completor *completor; -- GitLab From 28c03f82607730901830170259a4a17b33d5152e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:06 +0530 Subject: [PATCH 0052/7155] staging: wlan-ng: Replace function hfa384x_dormem() Remove parameters mode, cmdcb, usercb, and usercb_data from hfa384x_dormem as these parameters are only assigned the same constant values (DOWAIT, NULL, NULL, NULL respectively). Modify hfa384x_dormem to use these constants directly. Remove check for value of mode (as it will always be DOWAIT). Remove function hfa384x_dormem_wait as it does nothing except call hfa384x_dormem with these extra arguments. Modify call sites of hfa384x_dormem_wait to call hfa384x_dormem instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 37 ++++++++------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c469b89948e6..9be06a33268c 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -248,12 +248,10 @@ hfa384x_dowrid(struct hfa384x *hw, static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_dowmem(struct hfa384x *hw, @@ -818,14 +816,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int -hfa384x_dormem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dormem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - static inline int hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -1454,14 +1444,10 @@ hfa384x_dowrid(struct hfa384x *hw, * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer to receive read * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls * * Returns: * 0 success @@ -1473,18 +1459,15 @@ hfa384x_dowrid(struct hfa384x *hw, * Side effects: * * Call context: - * interrupt (DOASYNC) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1512,15 +1495,15 @@ hfa384x_dormem(struct hfa384x *hw, pr_debug("pktsize=%zd\n", ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_rmem_completor completor; result = @@ -2252,8 +2235,8 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); /* units of bytes */ - result = hfa384x_dormem_wait(hw, currpage, curroffset, buf, - len); + result = hfa384x_dormem(hw, currpage, curroffset, buf, + len); if (result) { netdev_warn(hw->wlandev->netdev, -- GitLab From 68336404aa5123401133c9433a8c91e4b96322e6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:07 +0530 Subject: [PATCH 0053/7155] staging: wlan-ng: Replace function hfa384x_dowmem() Remove parameters mode, cmdcb, usercb, and usercb_data from hfa384x_dowmem as these parameters are only assigned the same constant values (DOWAIT, NULL, NULL, NULL respectively). Modify hfa384x_dowmem to use these constants directly. Remove check for value of mode (as it will always be DOWAIT). Remove function hfa384x_dowmem_wait as it does nothing except call hfa384x_dowmem with these extra arguments. Modify call sites of hfa384x_dowmem_wait to call hfa384x_dowmem instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-10-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 51 +++++++++------------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 9be06a33268c..28d372a0663a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -255,12 +255,10 @@ hfa384x_dormem(struct hfa384x *hw, static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_isgood_pdrcode(u16 pdrcode); @@ -816,14 +814,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int -hfa384x_dowmem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dowmem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - /*---------------------------------------------------------------- * hfa384x_cmd_initialize * @@ -1529,14 +1519,10 @@ hfa384x_dormem(struct hfa384x *hw, * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer containing write data * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls. * * Returns: * 0 success @@ -1549,17 +1535,15 @@ hfa384x_dormem(struct hfa384x *hw, * * Call context: * interrupt (DOWAIT) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1586,15 +1570,15 @@ hfa384x_dowmem(struct hfa384x *hw, sizeof(ctlx->outbuf.wmemreq.offset) + sizeof(ctlx->outbuf.wmemreq.page) + len; - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor completor; struct hfa384x_cmdresult wmemresult; @@ -1901,10 +1885,10 @@ int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? HFA384x_USB_RWMEM_MAXLEN : writelen; - result = hfa384x_dowmem_wait(hw, - writepage, - writeoffset, - writebuf, writelen); + result = hfa384x_dowmem(hw, + writepage, + writeoffset, + writebuf, writelen); } /* set the download 'write flash' mode */ @@ -2158,12 +2142,11 @@ int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) currlen = HFA384x_USB_RWMEM_MAXLEN; /* Do blocking ctlx */ - result = hfa384x_dowmem_wait(hw, - currpage, - curroffset, - data + - (i * HFA384x_USB_RWMEM_MAXLEN), - currlen); + result = hfa384x_dowmem(hw, + currpage, + curroffset, + data + (i * HFA384x_USB_RWMEM_MAXLEN), + currlen); if (result) break; -- GitLab From 4ad366015d0560abf749d62b525177d38b02a1a9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:50:09 +0530 Subject: [PATCH 0054/7155] staging: wilc1000: Replace function wilc_wlan_cfg_get_val() Include wilc_wlan_cfg.h in wilc_netdev.c to enable it to call functions in wilc_wlan_cfg.c. Remove function wilc_wlan_cfg_get_val as all it does is call wilc_wlan_cfg_get_wid_value in file wilc_wlan_cfg.c. Rename function wilc_wlan_cfg_get_wid_value to wilc_wlan_cfg_get_val to maintain compatibility with call sites (including in wilc_netdev.c). Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712072009.2550-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 1 + drivers/staging/wilc1000/wilc_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wlan.h | 2 -- drivers/staging/wilc1000/wilc_wlan_cfg.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan_cfg.h | 4 ++-- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 565e2b5d0616..8d8b7e4399f7 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -11,6 +11,7 @@ #include #include "wilc_wfi_cfgoperations.h" +#include "wilc_wlan_cfg.h" #define WILC_MULTICAST_TABLE_SIZE 8 diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d46876edcfeb..2cbdbf0090e4 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1196,11 +1196,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, return ret_size; } -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size) -{ - return wilc_wlan_cfg_get_wid_value(wl, wid, buffer, buffer_size); -} - int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index d2eef7b4c3b7..b70014142686 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -291,8 +291,6 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*func)(void *, int)); void wilc_chip_sleep_manually(struct wilc *wilc); diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 9dc5de4eb08d..f4144f93e4a9 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -320,8 +320,8 @@ int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) return 2; } -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size) +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size) { u32 type = (wid >> 12) & 0xf; int i, ret = 0; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h index e5ca6cea0682..614c5673f232 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.h +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h @@ -44,8 +44,8 @@ struct wilc_cfg { struct wilc; int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size); int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id); -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size); void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, struct wilc_cfg_rsp *rsp); int wilc_wlan_cfg_init(struct wilc *wl); -- GitLab From 26a7ae2949a86e1b74e2485d725efb528e2a81bb Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 10 Jul 2019 19:00:56 -0400 Subject: [PATCH 0055/7155] staging: wlan-ng: use "%*pE" for serial number Almost every user of "%*pE" in the kernel uses just bare "%*pE". This is the only user of "%pEhp". I can't see why it's needed. Signed-off-by: J. Bruce Fields Link: https://lore.kernel.org/r/1562799656-13401-1-git-send-email-bfields@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index fb5441399131..8f25496188aa 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -846,7 +846,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, snum, HFA384x_RID_NICSERIALNUMBER_LEN); if (!result) { - netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n", + netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n", HFA384x_RID_NICSERIALNUMBER_LEN, snum); } else { netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); -- GitLab From 543ba01d99cc6b4007c1f9a475c1d572c46a5543 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:11 +0300 Subject: [PATCH 0056/7155] staging: fsl-dpaa2/ethsw: Fix setting port learning/flooding flags ethsw_set_learning()/ethsw_set_flood() use flags parameter as an enable/disable (1/0) indicator. Previous usage sent incorrect values. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-2-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index f73edaf6ce87..87470070c3a5 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -673,11 +673,12 @@ static int port_attr_br_flags_set(struct net_device *netdev, return 0; /* Learning is enabled per switch */ - err = ethsw_set_learning(port_priv->ethsw_data, flags & BR_LEARNING); + err = ethsw_set_learning(port_priv->ethsw_data, + !!(flags & BR_LEARNING)); if (err) goto exit; - err = ethsw_port_set_flood(port_priv, flags & BR_FLOOD); + err = ethsw_port_set_flood(port_priv, !!(flags & BR_FLOOD)); exit: return err; -- GitLab From b2fdbfa91b8c54c8884323b8914b0a7b81e67fc2 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:12 +0300 Subject: [PATCH 0057/7155] staging: fsl-dpaa2/ethsw: Add network interface statistics Allocate MC portal with atomic context for I/O and enable network interface statistics for hardware counters. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-3-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 87470070c3a5..b2273f840813 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -521,6 +521,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_stop = port_stop, .ndo_set_mac_address = eth_mac_addr, + .ndo_get_stats64 = port_get_stats, .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, @@ -1483,7 +1484,8 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) ethsw->dev = dev; dev_set_drvdata(dev, ethsw); - err = fsl_mc_portal_allocate(sw_dev, 0, ðsw->mc_io); + err = fsl_mc_portal_allocate(sw_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + ðsw->mc_io); if (err) { if (err == -ENXIO) err = -EPROBE_DEFER; -- GitLab From 7dbac0c9a1c4a86be928e2b13398346ca5b57233 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:13 +0300 Subject: [PATCH 0058/7155] staging: fsl-dpaa2/ethsw: Remove netdevice on port probing error If the ethsw_port_init() call failed, the netdevice remains registered in the system. Use labels to ensure that netdevice is unregistered and freed in this case. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-4-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b2273f840813..9f1617164865 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1460,13 +1460,23 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); - free_netdev(port_netdev); - return err; + goto err_register_netdev; } ethsw->ports[port_idx] = port_priv; - return ethsw_port_init(port_priv, port_idx); + err = ethsw_port_init(port_priv, port_idx); + if (err) + goto err_ethsw_port_init; + + return 0; + +err_ethsw_port_init: + unregister_netdev(port_netdev); +err_register_netdev: + free_netdev(port_netdev); + + return err; } static int ethsw_probe(struct fsl_mc_device *sw_dev) -- GitLab From de7ee3aea2e8255b28d047a0d8588f96bf522f4b Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:14 +0300 Subject: [PATCH 0059/7155] staging: fsl-dpaa2/ethsw: Add ndo_get_phys_port_name Add the ndo_get_phys_port_name callback to the ethsw driver. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-5-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 9f1617164865..341c36b3a76d 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -516,6 +516,19 @@ static int swdev_get_port_parent_id(struct net_device *dev, return 0; } +static int port_get_phys_name(struct net_device *netdev, char *name, + size_t len) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + int err; + + err = snprintf(name, len, "p%d", port_priv->idx); + if (err >= len) + return -EINVAL; + + return 0; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -528,6 +541,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_start_xmit = port_dropframe, .ndo_get_port_parent_id = swdev_get_port_parent_id, + .ndo_get_phys_port_name = port_get_phys_name, }; static void ethsw_links_state_update(struct ethsw_core *ethsw) -- GitLab From c5bd72f8713e13085267a8ebccfa5b8b3f2c674d Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:16 +0300 Subject: [PATCH 0060/7155] staging: fsl-dpaa2/ethsw: Add comments to ETHSW_VLAN flags Document each ETHSW_VLAN flag with the appropriate comment. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-7-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index c48783680a05..3ea8a0ad8c10 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -23,9 +23,13 @@ /* Number of IRQs supported */ #define DPSW_IRQ_NUM 2 +/* Port is member of VLAN */ #define ETHSW_VLAN_MEMBER 1 +/* VLAN to be treated as untagged on egress */ #define ETHSW_VLAN_UNTAGGED 2 +/* Untagged frames will be assigned to this VLAN */ #define ETHSW_VLAN_PVID 4 +/* VLAN configured on the switch */ #define ETHSW_VLAN_GLOBAL 8 /* Maximum Frame Length supported by HW (currently 10k) */ -- GitLab From 6c90bade52bbabdbdf3604d7f9279c878ebafed2 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 7 Jul 2019 18:56:49 +0200 Subject: [PATCH 0061/7155] staging: rtl8188eu: remove unused definitions from hal8188e_phy_reg.h Remove unused definitions from the file hal8188e_phy_reg.h. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190707165649.1558-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- .../rtl8188eu/include/hal8188e_phy_reg.h | 881 ------------------ 1 file changed, 881 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h index 53afcea21c96..bd915a1f2511 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h @@ -16,55 +16,10 @@ /* 5. Other definition for BB/RF R/W */ /* */ - -/* */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -/* */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* 2. Page2(0x200) */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB r/w cmd address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB r/w cmd data. */ - /* 3. Page8(0x800) */ #define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */ - -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - #define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - #define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ #define rFPGA0_XA_HSSIParameter2 0x824 #define rFPGA0_XB_HSSIParameter1 0x828 @@ -73,9 +28,6 @@ #define rFPGA0_XA_LSSIParameter 0x840 #define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - #define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ #define rFPGA0_XCD_SwitchControl 0x85c @@ -86,181 +38,63 @@ #define rFPGA0_XCD_RFInterfaceSW 0x874 #define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -/* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter1 0x880 -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 -/* enable ad/da clock1 for dual-phy */ -#define rFPGA0_AdDaClockEn 0x888 -#define rFPGA0_AnalogParameter4 0x88c #define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */ #define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -/* Transceiver A HSPI Readback */ #define TransceiverA_HSPI_Readback 0x8b8 -/* Transceiver B HSPI Readback */ #define TransceiverB_HSPI_Readback 0x8bc -/* Useless now RF Interface Readback Value */ #define rFPGA0_XAB_RFInterfaceRB 0x8e0 -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ /* 4. Page9(0x900) */ /* RF mode & OFDM TxSC RF BW Setting?? */ #define rFPGA1_RFMOD 0x900 -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report */ - /* 5. PageA(0xA00) */ /* Set Control channel to upper or lower - required only for 40MHz */ #define rCCK0_System 0xa00 -/* Disable init gain now Select RX path by RSSI */ -#define rCCK0_AFESetting 0xa04 -/* Disable init gain now Init gain */ -#define rCCK0_CCA 0xa08 - -/* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, - * RX LNA Threshold useless now. Not the same as 90 series - */ -#define rCCK0_RxAGC1 0xa0c -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -/* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter1 0xa18 -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ - /* */ /* PageB(0xB00) */ /* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 #define rConfig_AntA 0xb68 #define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 /* */ /* 6. PageC(0xC00) */ /* */ -#define rOFDM0_LSTF 0xc00 - #define rOFDM0_TRxPathEnable 0xc04 #define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c /* RxIQ DC offset, Rx digital filter, DC notch filter */ #define rOFDM0_XARxAFE 0xc10 #define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ #define rOFDM0_XBRxAFE 0xc18 #define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /*PD,BW & SBD DM tune init gain*/ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ #define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ #define rOFDM0_XAAGCCore1 0xc50 /* DIG */ #define rOFDM0_XAAGCCore2 0xc54 #define rOFDM0_XBAGCCore1 0xc58 #define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 #define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c #define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ #define rOFDM0_XATxAFE 0xc84 #define rOFDM0_XBTxIQImbalance 0xc88 #define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 #define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 #define rOFDM0_XDTxAFE 0xc9c #define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 - /* */ /* 7. PageD(0xD00) */ /* */ #define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - /* */ /* 8. PageE(0xE00) */ @@ -292,10 +126,6 @@ #define rRx_IQK 0xe44 #define rIQK_AGC_Pts 0xe48 #define rIQK_AGC_Rsp 0xe4c -#define rTx_IQK_Tone_B 0xe50 -#define rRx_IQK_Tone_B 0xe54 -#define rTx_IQK_PI_B 0xe58 -#define rRx_IQK_PI_B 0xe5c #define rIQK_AGC_Cont 0xe60 #define rBlue_Tooth 0xe6c @@ -311,17 +141,13 @@ #define rTx_Power_Before_IQK_A 0xe94 #define rTx_Power_After_IQK_A 0xe9c -#define rRx_Power_Before_IQK_A 0xea0 #define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 #define rRx_Power_After_IQK_A_2 0xeac #define rTx_Power_Before_IQK_B 0xeb4 #define rTx_Power_After_IQK_B 0xebc -#define rRx_Power_Before_IQK_B 0xec0 #define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 #define rRx_Power_After_IQK_B_2 0xecc #define rRx_OFDM 0xed0 @@ -331,752 +157,45 @@ #define rSleep 0xee0 #define rPMPD_ANAEN 0xeec -/* */ -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -/* endif */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - /* */ /* RL6052 Register definition */ /* */ #define RF_AC 0x00 /* */ - -#define RF_IQADJ_G1 0x01 /* */ -#define RF_IQADJ_G2 0x02 /* */ - -#define RF_POW_TRSW 0x05 /* */ - -#define RF_GAIN_RX 0x06 /* */ -#define RF_GAIN_TX 0x07 /* */ - -#define RF_TXM_IDAC 0x08 /* */ -#define RF_IPA_G 0x09 /* */ -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C /* */ -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F /* */ - -#define RF_MODE1 0x10 /* */ -#define RF_MODE2 0x11 /* */ - -#define RF_RX_AGC_HP 0x12 /* */ -#define RF_TX_AGC 0x13 /* */ -#define RF_BIAS 0x14 /* */ -#define RF_IPA 0x15 /* */ -#define RF_TXBIAS 0x16 -#define RF_POW_ABILITY 0x17 /* */ #define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 /* */ - -#define RF_RX_G1 0x1A /* */ -#define RF_RX_G2 0x1B /* */ - -#define RF_RX_BB2 0x1C /* */ -#define RF_RX_BB1 0x1D /* */ - -#define RF_RCK1 0x1E /* */ -#define RF_RCK2 0x1F /* */ - -#define RF_TX_G1 0x20 /* */ -#define RF_TX_G2 0x21 /* */ -#define RF_TX_G3 0x22 /* */ - -#define RF_TX_BB1 0x23 /* */ - -#define RF_T_METER_92D 0x42 /* */ #define RF_T_METER_88E 0x42 /* */ -#define RF_T_METER 0x24 /* */ - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - #define RF_RCK_OS 0x30 /* RF TX PA control */ #define RF_TXPA_G1 0x31 /* RF TX PA control */ #define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C /* */ -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B -#define RF_0x52 0x52 #define RF_WE_LUT 0xEF - /* */ /* Bit Mask */ /* */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) /* 2. Page8(0x800) */ #define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 #define bCCKEn 0x1000000 #define bOFDMEn 0x2000000 -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* change gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 - -/* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireDataLength 0x800 -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ - -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - #define bLSSIReadAddress 0x7f800000 /* T65 RF */ - #define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ - #define bLSSIReadBackData 0xfffff /* T65 RF */ -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ -#define bADClkPhase 0x4000000 - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - #define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */ -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - - /* */ /* Other Definition */ /* */ -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - /* for PutRegsetting & GetRegSetting BitMask */ #define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ #define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 #define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff #define bMaskDWord 0xffffffff #define bMask12Bits 0xfff -#define bMaskH4Bits 0xf0000000 #define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f /* for PutRFRegsetting & GetRFRegSetting BitMask */ #define bRFRegOffsetMask 0xfffff -#define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/*--------------------------Define Parameters-------------------------------*/ - - #endif -- GitLab From d59381d639af22da6eb49c5d851faf15feb6b462 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 11 Jul 2019 22:07:26 +0800 Subject: [PATCH 0062/7155] staging: kpc2000: kpc_spi: Remove unnecessary null check before kfree A null check before a kfree is redundant, so remove it. This is detected by coccinelle. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190711140726.46732-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c index 35ac1d7070b3..3be33c450cab 100644 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ b/drivers/staging/kpc2000/kpc2000_spi.c @@ -412,8 +412,7 @@ kp_spi_cleanup(struct spi_device *spidev) { struct kp_spi_controller_state *cs = spidev->controller_state; - if (cs) - kfree(cs); + kfree(cs); } /****************** -- GitLab From 2e7a3f1158eecb0675199d7b030f3ef9db82eb25 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 22:54:51 +0530 Subject: [PATCH 0063/7155] staging: rtl8723bs: hal: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714172451.GA6779@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index 638b12ae6ee9..eddd56abbb2d 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -152,10 +152,7 @@ bool HAL_IsLegalChannel(struct adapter *Adapter, u32 Channel) { bool bLegalChannel = true; - if (Channel > 14) { - bLegalChannel = false; - DBG_871X("Channel > 14 but wireless_mode do not support 5G\n"); - } else if ((Channel <= 14) && (Channel >= 1)) { + if ((Channel <= 14) && (Channel >= 1)) { if (IsSupported24G(Adapter->registrypriv.wireless_mode) == false) { bLegalChannel = false; DBG_871X("(Channel <= 14) && (Channel >= 1) but wireless_mode do not support 2.4G\n"); -- GitLab From 2615f966f9f27b30de7d9c10316bf482d1d2964e Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 22:58:26 +0530 Subject: [PATCH 0064/7155] staging: rtl8723bs: core: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714172826.GA6950@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 4285844420cb..967da715ffa4 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -295,11 +295,7 @@ static void init_mlme_ext_priv_value(struct adapter *padapter) init_mlme_default_rate_set(padapter); - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - + pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; pmlmeext->sitesurvey_res.state = SCAN_DISABLE; pmlmeext->sitesurvey_res.channel_idx = 0; pmlmeext->sitesurvey_res.bss_cnt = 0; -- GitLab From b21f9b8352aa189e708c4ccfb5216b56880a1851 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 23:01:34 +0530 Subject: [PATCH 0065/7155] staging: rtl8723bs: os_dep: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714173134.GA7111@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 544e799d0a03..18d61e5722f5 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -239,9 +239,6 @@ static void loadparam(struct adapter *padapter, _nic_hdl pnetdev) registry_par->channel = (u8)rtw_channel; registry_par->wireless_mode = (u8)rtw_wireless_mode; - if (registry_par->channel > 14) - registry_par->channel = 1; - registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense ; registry_par->vcs_type = (u8)rtw_vcs_type; registry_par->rts_thresh = (u16)rtw_rts_thresh; -- GitLab From 067756acdac8e0dd91edf4800e844fcb6e0cc72a Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Mon, 15 Jul 2019 23:16:18 +0530 Subject: [PATCH 0066/7155] staging: rtl8723bs: core: Change return type of init_mlme_ext_priv As init_mlme_ext_priv function always returns SUCCESS , We can change return type from int to void. Fixes below issue identified by coccicheck drivers/staging/rtl8723bs/core/rtw_mlme_ext.c:464:5-8: Unneeded variable: "res". Return "_SUCCESS" on line 492 Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190715174618.GA8947@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 6 +----- drivers/staging/rtl8723bs/include/rtw_mlme_ext.h | 2 +- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 6 +----- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 967da715ffa4..6d0014251f86 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -455,9 +455,8 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_ return chanset_size; } -int init_mlme_ext_priv(struct adapter *padapter) +void init_mlme_ext_priv(struct adapter *padapter) { - int res = _SUCCESS; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -484,9 +483,6 @@ int init_mlme_ext_priv(struct adapter *padapter) #ifdef DBG_FIXED_CHAN pmlmeext->fixed_chan = 0xFF; #endif - - return res; - } void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 733bb9425448..70cd8c0e3641 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -535,7 +535,7 @@ struct mlme_ext_priv }; void init_mlme_default_rate_set(struct adapter *padapter); -int init_mlme_ext_priv(struct adapter *padapter); +void init_mlme_ext_priv(struct adapter *padapter); int init_hw_mlme_ext(struct adapter *padapter); void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext); extern void init_mlme_ext_timer(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 18d61e5722f5..50928b2000b9 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -765,11 +765,7 @@ u8 rtw_init_drv_sw(struct adapter *padapter) goto exit; } - if (init_mlme_ext_priv(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n")); - ret8 = _FAIL; - goto exit; - } + init_mlme_ext_priv(padapter); if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) { DBG_871X("Can't _rtw_init_xmit_priv\n"); -- GitLab From 6290da3e439d5aa4a692196b61f34a3b6e8e9b1c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:38 +0530 Subject: [PATCH 0067/7155] staging: rtl8188eu: core: Replace function Set_MSR() Change reference to Set_NETYPE0_MSR to Set_MSR. Replace the contents of Set_MSR with the contents of Set_NETYPE0_MSR as Set_MSR does nothing but call Set_NETYPE0_MSR. Delete Set_NETYPE0_MSR. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 2 +- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 6f3c03201f64..18dc9fc1c04a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4854,7 +4854,7 @@ u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) } rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); - /* Set_NETYPE0_MSR(padapter, type); */ + /* Set_MSR(padapter, type); */ return H2C_SUCCESS; } diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7bfc5b7c2757..b75568efb46f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -270,14 +270,9 @@ void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable) rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode)); } -static void Set_NETYPE0_MSR(struct adapter *padapter, u8 type) -{ - rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); -} - void Set_MSR(struct adapter *padapter, u8 type) { - Set_NETYPE0_MSR(padapter, type); + rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); } inline u8 rtw_get_oper_ch(struct adapter *adapter) -- GitLab From d6a496f937523048aab1fef0df74786b0ae6fe17 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:39 +0530 Subject: [PATCH 0068/7155] staging: rtl8188eu: core: Remove function enable_rate_adaptive() Remove function enable_rate_adaptive as it does nothing except call Update_RA_Entry. Modify call site of enable_rate_adaptive to call Update_RA_Entry instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index b75568efb46f..1f2763ff2a70 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1174,15 +1174,10 @@ void Update_RA_Entry(struct adapter *padapter, u32 mac_id) rtw_hal_update_ra_mask(padapter, mac_id, 0); } -static void enable_rate_adaptive(struct adapter *padapter, u32 mac_id) -{ - Update_RA_Entry(padapter, mac_id); -} - void set_sta_rate(struct adapter *padapter, struct sta_info *psta) { /* rate adaptive */ - enable_rate_adaptive(padapter, psta->mac_id); + Update_RA_Entry(padapter, psta->mac_id); } /* Update RRSR and Rate for USERATE */ -- GitLab From 01625b0bbb523e6ce2818d4691812f66fe9c42b4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:40 +0530 Subject: [PATCH 0069/7155] staging: rtl8188eu: Replace function beacon_timing_control() Remove function beacon_timing_control as all it does is call rtw_hal_bcn_related_reg_setting. Rename rtw_hal_bcn_related_reg_setting to beacon_timing_control for compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 5 ----- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/hal_intf.h | 2 +- drivers/staging/rtl8188eu/include/rtw_mlme_ext.h | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 1f2763ff2a70..c985b1468d41 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1466,8 +1466,3 @@ void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext) { rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL); } - -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index ac5552050752..89babcb12d02 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1934,7 +1934,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) psta->init_rate = init_rate; } -void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) +void beacon_timing_control(struct adapter *adapt) { u32 value32; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 8b65fcba1967..516a89647003 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -199,7 +199,7 @@ void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level); void rtw_hal_clone_data(struct adapter *dst_adapt, struct adapter *src_adapt); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 327f7d1bc20c..d70780c8fd62 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -535,7 +535,6 @@ void report_del_sta_event(struct adapter *padapter, void report_add_sta_event(struct adapter *padapter, unsigned char *addr, int cam_idx); -void beacon_timing_control(struct adapter *padapter); u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); -- GitLab From c6255d2d2432623ee50f48970c51050e979befc3 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:41 +0530 Subject: [PATCH 0070/7155] staging: rtl8188eu: Remove function rtw_os_indicate_scan_done() In function rtw_indicate_scan_done, replace call to rtw_os_indicate_scan_done with call to indicate_wx_scan_complete_event as all that rtw_os_indicate_scan_done does is call indicate_wx_scan_complete_event. Remove now-unused function rtw_os_indicate_scan_done. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme.c | 2 +- drivers/staging/rtl8188eu/include/mlme_osdep.h | 1 - drivers/staging/rtl8188eu/os_dep/mlme_linux.c | 5 ----- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index d2f7a88e992e..43c7531e777e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -827,7 +827,7 @@ void rtw_indicate_disconnect(struct adapter *padapter) inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted) { - rtw_os_indicate_scan_done(padapter, aborted); + indicate_wx_scan_complete_event(padapter); } static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork) diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/rtl8188eu/include/mlme_osdep.h index eda16c06336a..8e919441c2aa 100644 --- a/drivers/staging/rtl8188eu/include/mlme_osdep.h +++ b/drivers/staging/rtl8188eu/include/mlme_osdep.h @@ -13,7 +13,6 @@ void rtw_init_mlme_timer(struct adapter *padapter); void rtw_os_indicate_disconnect(struct adapter *adapter); void rtw_os_indicate_connect(struct adapter *adapter); -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted); void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie); void rtw_reset_securitypriv(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index e660bd4d91ef..321b2c46479c 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -27,11 +27,6 @@ void rtw_os_indicate_connect(struct adapter *adapter) netif_carrier_on(adapter->pnetdev); } -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted) -{ - indicate_wx_scan_complete_event(padapter); -} - static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE]; void rtw_reset_securitypriv(struct adapter *adapter) -- GitLab From 04c8c1985618b45e59433d6c46e3f787e146017e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:42 +0530 Subject: [PATCH 0071/7155] staging: rtl8188eu: Remove function rtw_modular64() Remove function rtw_modular64 as all it does is call do_div. Replace call to rtw_modular64 with call to do_div. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/osdep_service.h | 2 -- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 89babcb12d02..994392ac249b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1298,7 +1298,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ + tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index cfe5698fbbb1..c0114ad79788 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -80,8 +80,6 @@ void rtw_free_netdev(struct net_device *netdev); #define FUNC_ADPT_FMT "%s(%s)" #define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name -u64 rtw_modular64(u64 x, u64 y); - /* Macros for handling unaligned memory accesses */ #define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 105f3f21bdea..69d4b1d66b6f 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -59,11 +59,6 @@ void rtw_free_netdev(struct net_device *netdev) return; } -u64 rtw_modular64(u64 x, u64 y) -{ - return do_div(x, y); -} - void rtw_buf_free(u8 **buf, u32 *buf_len) { *buf_len = 0; -- GitLab From 5cace672b9a4da8586ade62d3a7f204a4adced2e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:43 +0530 Subject: [PATCH 0072/7155] staging: rtl8188eu: Replace function rtw_alloc_network() Change external call site of _rtw_alloc_network to rtw_alloc_network. Remove function rtw_alloc_network as all it does is call _rtw_alloc_network. Rename _rtw_alloc_network to rtw_alloc_network to maintain compatibility with call sites. Keep its type as non-static (even though the old rtw_alloc_network was static) as this functionality is used in other files as well. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 2 +- drivers/staging/rtl8188eu/core/rtw_mlme.c | 9 ++------- drivers/staging/rtl8188eu/include/rtw_mlme.h | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index a24b40761af2..815dfee11968 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -1200,7 +1200,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) rtw_indicate_connect(padapter); } else { - pwlan = _rtw_alloc_network(pmlmepriv); + pwlan = rtw_alloc_network(pmlmepriv); spin_lock_bh(&pmlmepriv->scanned_queue.lock); if (!pwlan) { pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 43c7531e777e..1ec3b237212e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -104,7 +104,7 @@ void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) } } -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) /* _queue *free_queue) */ { struct wlan_network *pnetwork; @@ -119,7 +119,7 @@ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) list_del_init(&pnetwork->list); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list)); + ("rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; @@ -272,11 +272,6 @@ u8 *rtw_get_beacon_interval_from_ie(u8 *ie) return ie + 8; } -static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) -{ - return _rtw_alloc_network(pmlmepriv); -} - int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork) { int ret = true; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 9abb7c320192..010f0c42368a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -333,7 +333,7 @@ void rtw_dynamic_check_timer_handlder(struct timer_list *t); void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv); +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv); int rtw_if_up(struct adapter *padapter); -- GitLab From 792d89ee4bd6ca4ba803a9f522cf9d0a35dd763f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:44 +0530 Subject: [PATCH 0073/7155] staging: rtl8188eu: Replace function rtl88e_phy_rf6052_config() Remove function rtl88e_phy_rf6052_config as all it does is call rf6052_conf_para. Rename rf6052_conf_para to rtl88e_phy_rf6052_config to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 02aeb12c9870..89ee74e795f8 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -218,7 +218,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) return true; } -static bool rf6052_conf_para(struct adapter *adapt) +static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; @@ -247,11 +247,6 @@ static bool rf6052_conf_para(struct adapter *adapt) return rtstatus; } -static bool rtl88e_phy_rf6052_config(struct adapter *adapt) -{ - return rf6052_conf_para(adapt); -} - bool rtl88eu_phy_rf_config(struct adapter *adapt) { return rtl88e_phy_rf6052_config(adapt); -- GitLab From 384329ddc42ad91a9f1f0eab3c53ce0b0402bc60 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:45 +0530 Subject: [PATCH 0074/7155] staging: rtl8188eu: Replace function rtl88eu_phy_rf_config() Remove function rtl88eu_phy_rf_config as all it does is call rtl88e_phy_rf6052_config. Rename rtl88e_phy_rf6052_config to rtl88eu_phy_rf_config and change its type from static to non-static to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 89ee74e795f8..739e62dc60e3 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -218,7 +218,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) return true; } -static bool rtl88e_phy_rf6052_config(struct adapter *adapt) +bool rtl88eu_phy_rf_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; @@ -246,8 +246,3 @@ static bool rtl88e_phy_rf6052_config(struct adapter *adapt) return rtstatus; } - -bool rtl88eu_phy_rf_config(struct adapter *adapt) -{ - return rtl88e_phy_rf6052_config(adapt); -} -- GitLab From 44a22dc3dd890ff476e708e39895c2536ad99cf2 Mon Sep 17 00:00:00 2001 From: Benjamin Sherman Date: Tue, 16 Jul 2019 00:57:55 -0400 Subject: [PATCH 0075/7155] staging: vt6656: change alignment to match parenthesis Change indentation to match parentheses. This complies with the Linux kernel coding style and improves readability. Signed-off-by: Benjamin Sherman Link: https://lore.kernel.org/r/20190716045754.fivh5n44bybe2uce@valkyrie-mobile.localdomain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 10 +++++----- drivers/staging/vt6656/usbpipe.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9def0748ffee..4e9cfacf75f2 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -287,12 +287,12 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); buf->duration_b = vnt_get_duration_le(priv, - PK_TYPE_11B, need_ack); + PK_TYPE_11B, need_ack); } buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -325,7 +325,7 @@ static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context, buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -655,7 +655,7 @@ static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context, u8 need_ack = tx_context->need_ack; buf->rrv_time = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type, - frame_len, current_rate, need_ack); + frame_len, current_rate, need_ack); if (need_mic) head = &tx_head->tx_ab.tx.mic.head; @@ -1036,7 +1036,7 @@ static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb) /* Get Duration and TimeStampOff */ short_head->duration = vnt_get_duration_le(priv, - PK_TYPE_11B, false); + PK_TYPE_11B, false); short_head->time_stamp_off = vnt_time_stamp_off(priv, current_rate); } diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index ff351a7a0876..d3304df6bd53 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -216,7 +216,7 @@ static void vnt_submit_rx_urb_complete(struct urb *urb) } urb->transfer_buffer = skb_put(rcb->skb, - skb_tailroom(rcb->skb)); + skb_tailroom(rcb->skb)); } if (usb_submit_urb(urb, GFP_ATOMIC)) { -- GitLab From 441dfcc8861ed9cbc778c655f85e5ce5db08035e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 16 Jul 2019 17:44:22 +0800 Subject: [PATCH 0076/7155] staging: erofs: avoid opened loop codes Use __GFP_NOFAIL to avoid opened loop codes in z_erofs_vle_unzip(). Signed-off-by: Chao Yu Reviewed-by: Gao Xiang Link: https://lore.kernel.org/r/20190716094422.110805-1-yuchao0@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/unzip_vle.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index f0dab81ff816..56c009cf611e 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -921,18 +921,18 @@ static int z_erofs_vle_unzip(struct super_block *sb, mutex_trylock(&z_pagemap_global_lock)) pages = z_pagemap_global; else { -repeat: + gfp_t gfp_flags = GFP_KERNEL; + + if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) + gfp_flags |= __GFP_NOFAIL; + pages = kvmalloc_array(nr_pages, sizeof(struct page *), - GFP_KERNEL); + gfp_flags); /* fallback to global pagemap for the lowmem scenario */ if (unlikely(!pages)) { - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) - goto repeat; - else { - mutex_lock(&z_pagemap_global_lock); - pages = z_pagemap_global; - } + mutex_lock(&z_pagemap_global_lock); + pages = z_pagemap_global; } } -- GitLab From 9da681e017a36a411f70ca1ff68c499a30d2039d Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 16 Jul 2019 17:32:56 +0800 Subject: [PATCH 0077/7155] staging: erofs: support bmap Add erofs_bmap() to support FIBMAP ioctl on flatmode inode. Reviewed-by: Gao Xiang Signed-off-by: Chao Yu Link: https://lore.kernel.org/r/20190716093256.108791-1-yuchao0@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index cc31c3e5984c..f73e4720cd3e 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -392,9 +392,42 @@ static int erofs_raw_access_readpages(struct file *filp, return 0; } +static int erofs_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + struct erofs_map_blocks map = { + .m_la = iblock << 9, + }; + int err; + + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + if (err) + return err; + + if (map.m_flags & EROFS_MAP_MAPPED) + bh->b_blocknr = erofs_blknr(map.m_pa); + + return err; +} + +static sector_t erofs_bmap(struct address_space *mapping, sector_t block) +{ + struct inode *inode = mapping->host; + + if (is_inode_flat_inline(inode)) { + erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE; + + if (block >> LOG_SECTORS_PER_BLOCK >= blks) + return 0; + } + + return generic_block_bmap(mapping, block, erofs_get_block); +} + /* for uncompressed (aligned) files and raw access for other files */ const struct address_space_operations erofs_raw_access_aops = { .readpage = erofs_raw_access_readpage, .readpages = erofs_raw_access_readpages, + .bmap = erofs_bmap, }; -- GitLab From 2125a44149cdf6be61fdabce898d26e9ba37dcd0 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 11:29:44 +0530 Subject: [PATCH 0078/7155] staging: mt7621-pci: Add of_node_put() before return Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190716055944.3237-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 89fa813142ab..2e37fd136ab8 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -400,6 +400,7 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) err = of_pci_get_devfn(child); if (err < 0) { + of_node_put(child); dev_err(dev, "failed to parse devfn: %d\n", err); return err; } @@ -407,8 +408,10 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) slot = PCI_SLOT(err); err = mt7621_pcie_parse_port(pcie, child, slot); - if (err) + if (err) { + of_node_put(child); return err; + } } return 0; -- GitLab From c4011dde241d371972788a735cd1b5d547991d46 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 11:29:08 +0530 Subject: [PATCH 0079/7155] staging: mt7621-pinctrl: Add of_node_put() before return Each iteration of for_each_compatible_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Add an of_node_put before the return. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190716055908.3183-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c index 9b52d44abef1..d0f06790d38f 100644 --- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c +++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c @@ -358,12 +358,15 @@ static int rt2880_pinmux_probe(struct platform_device *pdev) gpiobase = of_get_property(np, "ralink,gpio-base", NULL); if (!ngpio || !gpiobase) { dev_err(&pdev->dev, "failed to load chip info\n"); + of_node_put(np); return -EINVAL; } range = devm_kzalloc(p->dev, sizeof(*range), GFP_KERNEL); - if (!range) + if (!range) { + of_node_put(np); return -ENOMEM; + } range->name = "pio"; range->npins = __be32_to_cpu(*ngpio); range->base = __be32_to_cpu(*gpiobase); -- GitLab From f328584f7bff86858249bb358f1adcecde48388a Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 12 Jun 2019 12:28:15 -0400 Subject: [PATCH 0080/7155] cpufreq: Add sun50i nvmem based CPU scaling driver For some SoCs, the CPU frequency subset and voltage value of each OPP varies based on the silicon variant in use. The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. Signed-off-by: Yangtao Li Acked-by: Maxime Ripard Signed-off-by: Viresh Kumar --- MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 12 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sun50i-cpufreq-nvmem.c | 226 +++++++++++++++++++++++++ 5 files changed, 248 insertions(+) create mode 100644 drivers/cpufreq/sun50i-cpufreq-nvmem.c diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..d3964379841b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -676,6 +676,13 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/staging/media/allegro-dvt/ +ALLWINNER CPUFREQ DRIVER +M: Yangtao Li +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt +F: drivers/cpufreq/sun50i-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe L: linux-crypto@vger.kernel.org diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 56c31a78c692..70c2b4bea55c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -19,6 +19,18 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM + tristate "Allwinner nvmem based SUN50I CPUFreq driver" + depends on ARCH_SUNXI + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the nvmem based CPUFreq driver for Allwinner + h6 SoC. + + To compile this driver as a module, choose M here: the + module will be called sun50i-cpufreq-nvmem. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 5a6c70d26c98..7f2d2e1079d4 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o +obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o obj-$(CONFIG_ARM_TANGO_CPUFREQ) += tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 03dc4244ab00..f9444ddd35ab 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -101,6 +101,8 @@ static const struct of_device_id whitelist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blacklist[] __initconst = { + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "calxeda,highbank", }, { .compatible = "calxeda,ecx-2000", }, diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c new file mode 100644 index 000000000000..eca32e443716 --- /dev/null +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner CPUFreq nvmem based driver + * + * The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to + * provide the OPP framework with required information. + * + * Copyright (C) 2019 Yangtao Li + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define MAX_NAME_LEN 7 + +#define NVMEM_MASK 0x7 +#define NVMEM_SHIFT 5 + +static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; + +/** + * sun50i_cpufreq_get_efuse() - Parse and return efuse value present on SoC + * @versions: Set to the value parsed from efuse + * + * Returns 0 if success. + */ +static int sun50i_cpufreq_get_efuse(u32 *versions) +{ + struct nvmem_cell *speedbin_nvmem; + struct device_node *np; + struct device *cpu_dev; + u32 *speedbin, efuse_value; + size_t len; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) + return -ENODEV; + + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); + if (!np) + return -ENOENT; + + ret = of_device_is_compatible(np, + "allwinner,sun50i-h6-operating-points"); + if (!ret) { + of_node_put(np); + return -ENOENT; + } + + speedbin_nvmem = of_nvmem_cell_get(np, NULL); + of_node_put(np); + if (IS_ERR(speedbin_nvmem)) { + if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) + pr_err("Could not get nvmem cell: %ld\n", + PTR_ERR(speedbin_nvmem)); + return PTR_ERR(speedbin_nvmem); + } + + speedbin = nvmem_cell_read(speedbin_nvmem, &len); + nvmem_cell_put(speedbin_nvmem); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK; + switch (efuse_value) { + case 0b0001: + *versions = 1; + break; + case 0b0011: + *versions = 2; + break; + default: + /* + * For other situations, we treat it as bin0. + * This vf table can be run for any good cpu. + */ + *versions = 0; + break; + } + + kfree(speedbin); + return 0; +}; + +static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) +{ + struct opp_table **opp_tables; + char name[MAX_NAME_LEN]; + unsigned int cpu; + u32 speed = 0; + int ret; + + opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), + GFP_KERNEL); + if (!opp_tables) + return -ENOMEM; + + ret = sun50i_cpufreq_get_efuse(&speed); + if (ret) + return ret; + + snprintf(name, MAX_NAME_LEN, "speed%d", speed); + + for_each_possible_cpu(cpu) { + struct device *cpu_dev = get_cpu_device(cpu); + + if (!cpu_dev) { + ret = -ENODEV; + goto free_opp; + } + + opp_tables[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name); + if (IS_ERR(opp_tables[cpu])) { + ret = PTR_ERR(opp_tables[cpu]); + pr_err("Failed to set prop name\n"); + goto free_opp; + } + } + + cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, + NULL, 0); + if (!IS_ERR(cpufreq_dt_pdev)) { + platform_set_drvdata(pdev, opp_tables); + return 0; + } + + ret = PTR_ERR(cpufreq_dt_pdev); + pr_err("Failed to register platform device\n"); + +free_opp: + for_each_possible_cpu(cpu) { + if (IS_ERR_OR_NULL(opp_tables[cpu])) + break; + dev_pm_opp_put_prop_name(opp_tables[cpu]); + } + kfree(opp_tables); + + return ret; +} + +static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) +{ + struct opp_table **opp_tables = platform_get_drvdata(pdev); + unsigned int cpu; + + platform_device_unregister(cpufreq_dt_pdev); + + for_each_possible_cpu(cpu) + dev_pm_opp_put_prop_name(opp_tables[cpu]); + + kfree(opp_tables); + + return 0; +} + +static struct platform_driver sun50i_cpufreq_driver = { + .probe = sun50i_cpufreq_nvmem_probe, + .remove = sun50i_cpufreq_nvmem_remove, + .driver = { + .name = "sun50i-cpufreq-nvmem", + }, +}; + +static const struct of_device_id sun50i_cpufreq_match_list[] = { + { .compatible = "allwinner,sun50i-h6" }, + {} +}; + +static const struct of_device_id *sun50i_cpufreq_match_node(void) +{ + const struct of_device_id *match; + struct device_node *np; + + np = of_find_node_by_path("/"); + match = of_match_node(sun50i_cpufreq_match_list, np); + of_node_put(np); + + return match; +} + +/* + * Since the driver depends on nvmem drivers, which may return EPROBE_DEFER, + * all the real activity is done in the probe, which may be defered as well. + * The init here is only registering the driver and the platform device. + */ +static int __init sun50i_cpufreq_init(void) +{ + const struct of_device_id *match; + int ret; + + match = sun50i_cpufreq_match_node(); + if (!match) + return -ENODEV; + + ret = platform_driver_register(&sun50i_cpufreq_driver); + if (unlikely(ret < 0)) + return ret; + + sun50i_cpufreq_pdev = + platform_device_register_simple("sun50i-cpufreq-nvmem", + -1, NULL, 0); + ret = PTR_ERR_OR_ZERO(sun50i_cpufreq_pdev); + if (ret == 0) + return 0; + + platform_driver_unregister(&sun50i_cpufreq_driver); + return ret; +} +module_init(sun50i_cpufreq_init); + +static void __exit sun50i_cpufreq_exit(void) +{ + platform_device_unregister(sun50i_cpufreq_pdev); + platform_driver_unregister(&sun50i_cpufreq_driver); +} +module_exit(sun50i_cpufreq_exit); + +MODULE_DESCRIPTION("Sun50i-h6 cpufreq driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From b880c18336252df4866d07f850ea7872b6e83f0a Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 12 Jun 2019 12:28:16 -0400 Subject: [PATCH 0081/7155] dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. The "allwinner,sun50i-h6-operating-points" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-microvolt-: voltage in micro Volts. At runtime, the platform can pick a and matching opp-microvolt- property. HW: : sun50i-h6 speed0 speed1 speed2 Signed-off-by: Yangtao Li Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Viresh Kumar --- .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt new file mode 100644 index 000000000000..7deae57a587b --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt @@ -0,0 +1,167 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=================================== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: +-------------------- +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'allwinner,sun50i-h6-operating-points'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the speedbin + that is used to select the right frequency/voltage value + pair. Please refer the for nvmem-cells bindings + Documentation/devicetree/bindings/nvmem/nvmem.txt and + also examples below. + +In every OPP node: +- opp-microvolt-: Voltage in micro Volts. + At runtime, the platform can pick a and + matching opp-microvolt- property. + [See: opp.txt] + HW: : + sun50i-h6 speed0 speed1 speed2 + +Example 1: +--------- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; + }; + }; + + cpu_opp_table: opp_table { + compatible = "allwinner,sun50i-h6-operating-points"; + nvmem-cells = <&speedbin_efuse>; + opp-shared; + + opp@480000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <480000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp@720000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <720000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp@816000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <816000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp@888000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <888000000>; + + opp-microvolt-speed0 = <940000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp@1080000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1080000000>; + + opp-microvolt-speed0 = <1060000>; + opp-microvolt-speed1 = <880000>; + opp-microvolt-speed2 = <840000>; + }; + + opp@1320000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1320000000>; + + opp-microvolt-speed0 = <1160000>; + opp-microvolt-speed1 = <940000>; + opp-microvolt-speed2 = <900000>; + }; + + opp@1488000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1488000000>; + + opp-microvolt-speed0 = <1160000>; + opp-microvolt-speed1 = <1000000>; + opp-microvolt-speed2 = <960000>; + }; + }; +.... +soc { +.... + sid: sid@3006000 { + compatible = "allwinner,sun50i-h6-sid"; + reg = <0x03006000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + .... + speedbin_efuse: speed@1c { + reg = <0x1c 4>; + }; + }; +}; -- GitLab From 3355c91b79394593ebbb197c8e930a91826f4ff3 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 21 Jul 2019 23:38:15 +0530 Subject: [PATCH 0082/7155] cpufreq: ap806: Add NULL check after kcalloc Add NULL check after kcalloc. Fix below issue reported by coccicheck ./drivers/cpufreq/armada-8k-cpufreq.c:138:1-12: alloc with no test, possible model on line 151 Signed-off-by: Hariprasad Kelam Signed-off-by: Viresh Kumar --- drivers/cpufreq/armada-8k-cpufreq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c index 988ebc326bdb..39e34f5066d3 100644 --- a/drivers/cpufreq/armada-8k-cpufreq.c +++ b/drivers/cpufreq/armada-8k-cpufreq.c @@ -136,6 +136,8 @@ static int __init armada_8k_cpufreq_init(void) nb_cpus = num_possible_cpus(); freq_tables = kcalloc(nb_cpus, sizeof(*freq_tables), GFP_KERNEL); + if (!freq_tables) + return -ENOMEM; cpumask_copy(&cpus, cpu_possible_mask); /* -- GitLab From bf58de429387b928268a8567e34cb4d3c109b727 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 4 Jul 2019 11:53:22 +0300 Subject: [PATCH 0083/7155] arm64: defconfig: Build imx8 ddr pmu as module This is available on all imx8 but is not "boot critical" in any way so build as a module. Signed-off-by: Leonard Crestez Acked-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index ba65833d08cc..121aeb205247 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -785,6 +785,7 @@ CONFIG_PHY_ROCKCHIP_TYPEC=y CONFIG_PHY_UNIPHIER_USB2=y CONFIG_PHY_UNIPHIER_USB3=y CONFIG_PHY_TEGRA_XUSB=y +CONFIG_FSL_IMX8_DDR_PMU=m CONFIG_HISI_PMU=y CONFIG_QCOM_L2_PMU=y CONFIG_QCOM_L3_PMU=y -- GitLab From d9aa4d4fca67823838fe9861456201430c545e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Szymanski?= Date: Thu, 4 Jul 2019 16:23:23 +0200 Subject: [PATCH 0084/7155] ARM: dts: opos6uldev: use OF graph to describe the display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make use of the new eLCDIF DRM driver OF graph description is required. Describe the display using OF graph nodes. Reviewed-by: Fabio Estevam Signed-off-by: Sébastien Szymanski Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-opos6uldev.dts | 37 +++++++++++-------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-opos6uldev.dts b/arch/arm/boot/dts/imx6ul-opos6uldev.dts index 0e59ee57fd55..8ecdb9ad2b2e 100644 --- a/arch/arm/boot/dts/imx6ul-opos6uldev.dts +++ b/arch/arm/boot/dts/imx6ul-opos6uldev.dts @@ -56,7 +56,7 @@ stdout-path = &uart1; }; - backlight { + backlight: backlight { compatible = "pwm-backlight"; pwms = <&pwm3 0 191000>; brightness-levels = <0 4 8 16 32 64 128 255>; @@ -97,6 +97,18 @@ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; }; + panel: panel { + compatible = "armadeus,st0700-adapt"; + power-supply = <®_3v3>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&lcdif_out>; + }; + }; + }; + reg_5v: regulator-5v { compatible = "regulator-fixed"; regulator-name = "5V"; @@ -182,28 +194,11 @@ &lcdif { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcdif>; - display = <&display0>; - lcd-supply = <®_3v3>; status = "okay"; - display0: display0 { - bits-per-pixel = <32>; - bus-width = <18>; - - display-timings { - timing0: timing0 { - clock-frequency = <33000033>; - hactive = <800>; - vactive = <480>; - hback-porch = <96>; - hfront-porch = <96>; - vback-porch = <20>; - vfront-porch = <21>; - hsync-len = <64>; - vsync-len = <4>; - de-active = <1>; - pixelclk-active = <0>; - }; + port { + lcdif_out: endpoint { + remote-endpoint = <&panel_in>; }; }; }; -- GitLab From 551626ec0ad28dc43cae3094c35be7088cc625ab Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 17 Jul 2019 14:30:23 +0200 Subject: [PATCH 0085/7155] ALSA: hda/hdmi - Don't report spurious jack state changes The HDMI jack handling reports the state change always via snd_jack_report() whenever hdmi_present_sense() is called, even if the state itself doesn't change from the previous time. This is mostly harmless but still a bit confusing to user-space. This patch reduces such spurious jack state changes and reports only when the state really changed. Also, as a minor optimization, avoid overwriting the pin ELD data when the state is identical. Reviewed-by: Kai Vehmanen Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bea7b0961080..c380596b2e84 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1421,7 +1421,7 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec, /* update per_pin ELD from the given new ELD; * setup info frame and notification accordingly */ -static void update_eld(struct hda_codec *codec, +static bool update_eld(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin, struct hdmi_eld *eld) { @@ -1452,18 +1452,22 @@ static void update_eld(struct hda_codec *codec, snd_hdmi_show_eld(codec, &eld->info); eld_changed = (pin_eld->eld_valid != eld->eld_valid); - if (eld->eld_valid && pin_eld->eld_valid) + eld_changed |= (pin_eld->monitor_present != eld->monitor_present); + if (!eld_changed && eld->eld_valid && pin_eld->eld_valid) if (pin_eld->eld_size != eld->eld_size || memcmp(pin_eld->eld_buffer, eld->eld_buffer, eld->eld_size) != 0) eld_changed = true; - pin_eld->monitor_present = eld->monitor_present; - pin_eld->eld_valid = eld->eld_valid; - pin_eld->eld_size = eld->eld_size; - if (eld->eld_valid) - memcpy(pin_eld->eld_buffer, eld->eld_buffer, eld->eld_size); - pin_eld->info = eld->info; + if (eld_changed) { + pin_eld->monitor_present = eld->monitor_present; + pin_eld->eld_valid = eld->eld_valid; + pin_eld->eld_size = eld->eld_size; + if (eld->eld_valid) + memcpy(pin_eld->eld_buffer, eld->eld_buffer, + eld->eld_size); + pin_eld->info = eld->info; + } /* * Re-setup pin and infoframe. This is needed e.g. when @@ -1481,6 +1485,7 @@ static void update_eld(struct hda_codec *codec, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); + return eld_changed; } /* update ELD and jack state via HD-audio verbs */ @@ -1582,6 +1587,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; struct snd_jack *jack = NULL; + bool changed; int size; mutex_lock(&per_pin->lock); @@ -1608,15 +1614,13 @@ static void sync_eld_via_acomp(struct hda_codec *codec, * disconnected event. Jack must be fetched before update_eld() */ jack = pin_idx_to_jack(codec, per_pin); - update_eld(codec, per_pin, eld); + changed = update_eld(codec, per_pin, eld); if (jack == NULL) jack = pin_idx_to_jack(codec, per_pin); - if (jack == NULL) - goto unlock; - snd_jack_report(jack, - (eld->monitor_present && eld->eld_valid) ? + if (changed && jack) + snd_jack_report(jack, + (eld->monitor_present && eld->eld_valid) ? SND_JACK_AVOUT : 0); - unlock: mutex_unlock(&per_pin->lock); } -- GitLab From ade49db337a9d44ac5835cfce1ee873549011b27 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 18:05:52 +0200 Subject: [PATCH 0086/7155] ALSA: hda/hdmi - Allow audio component for AMD/ATI and Nvidia HDMI AMD/ATI and Nvidia HDMI codec drivers didn't have the audio component binding like i915, but it worked only with the traditional HD-audio unsolicited event for the HDMI hotplug detection and the ELD read-up thereafter. This has been a problem in many ways: first of all, it goes through the hardware event transition (from GPU register write, HD-audio controller trigger, and finally to HD-audio unsolicited event handling), which is often unreliable and may miss some opportunities. Second, each unsol event handling and ELD read-up need the explicit power up / down when the codec is in the runtime suspend. Last but not least, which is the most important, the hotplug wakeup may be missed when the HD-audio controller is in runtime suspend. Especially the last point is a big problem due to the recent change relevant with vga_switcheroo that forcibly enables the runtime PM for AMD HDMI controllers. These issues are solved by introducing the audio component; the hotplug notification is done by a direct function callback, which is more accurate and reliable, and it can be processed without the actual hardware access, i.e. no runtime PM trigger is needed, and the HD-audio gets the event even if it's in runtime suspend. The same for ELD query, as it's read directly from the cached ELD bytes stored in the DRM driver, hence the whole hardware access can be skipped. So here it is: this patch implements the audio component binding with AMD/ATI and Nouveau DRM drivers. The biggest difference from i915 implementation is that this binding is fully optional and it can be enabled asynchronously on the fly. That is, the driver will switch from the HD-audio unsolicited event to the notify callback once when the DRM component gets bound. Similarly, when DRM driver gets unloaded, the HDMI event handling returns to the legacy mode, too. Also, another difference from i915 is that the new code registers the component in the codec driver, while i915 HDMI codec assumes the component binding was already done in the HD-audio controller driver. Hence the new code does need to de-register the component binding at the codec exit, too. Some other details: - The match component ops assumes that both VGA and HD-audio controller PCI entries belong to the same PCI bus, and only accepts such an entry. - The pin2port audio_ops is implemented with assumption of the fixed widget layout. For AMD, it's starting from 3, with step 2 (3, 5, 7, ...), while for Nvidia, it's starting from 4, with step 1 (4, 5, 6, ...) As of this patch, the corresponding component isn't implemented in DRM side, so this change alone won't give any benefit. By the following changes in DRM sides, the mission will be completed. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 233 +++++++++++++++++++++++++++++++++---- 1 file changed, 211 insertions(+), 22 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c380596b2e84..2096993eaf28 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -119,6 +120,7 @@ struct hdmi_pcm { }; struct hdmi_spec { + struct hda_codec *codec; int num_cvts; struct snd_array cvts; /* struct hdmi_spec_per_cvt */ hda_nid_t cvt_nids[4]; /* only for haswell fix */ @@ -163,9 +165,11 @@ struct hdmi_spec { struct hda_multi_out multiout; struct hda_pcm_stream pcm_playback; - /* i915/powerwell (Haswell+/Valleyview+) specific */ - bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ + bool use_jack_detect; /* jack detection enabled */ + bool use_acomp_notifier; /* use eld_notify callback for hotplug */ + bool acomp_registered; /* audio component registered in this driver */ struct drm_audio_component_audio_ops drm_audio_ops; + int (*port2pin)(struct hda_codec *, int); /* reverse port/pin mapping */ struct hdac_chmap chmap; hda_nid_t vendor_nid; @@ -765,6 +769,10 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid, static void jack_callback(struct hda_codec *codec, struct hda_jack_callback *jack) { + /* stop polling when notification is enabled */ + if (codec_has_acomp(codec)) + return; + /* hda_jack don't support DP MST */ check_presence_and_report(codec, jack->nid, 0); } @@ -823,6 +831,9 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) int tag = res >> AC_UNSOL_RES_TAG_SHIFT; int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + if (codec_has_acomp(codec)) + return; + if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); return; @@ -1636,18 +1647,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) snd_hda_power_down_pm(codec); return false; } - } - - if (codec_has_acomp(codec)) { + ret = hdmi_present_sense_via_verbs(per_pin, repoll); + snd_hda_power_down_pm(codec); + } else { sync_eld_via_acomp(codec, per_pin); ret = false; /* don't call snd_hda_jack_report_sync() */ - } else { - ret = hdmi_present_sense_via_verbs(per_pin, repoll); } - if (!codec_has_acomp(codec)) - snd_hda_power_down_pm(codec); - return ret; } @@ -2252,6 +2258,8 @@ static int generic_hdmi_init(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int pin_idx; + mutex_lock(&spec->pcm_lock); + spec->use_jack_detect = !codec->jackpoll_interval; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; @@ -2259,11 +2267,15 @@ static int generic_hdmi_init(struct hda_codec *codec) snd_hda_set_dev_select(codec, pin_nid, dev_id); hdmi_init_pin(codec, pin_nid); - if (!codec_has_acomp(codec)) + if (codec_has_acomp(codec)) + continue; + if (spec->use_jack_detect) + snd_hda_jack_detect_enable(codec, pin_nid); + else snd_hda_jack_detect_enable_callback(codec, pin_nid, - codec->jackpoll_interval > 0 ? - jack_callback : NULL); + jack_callback); } + mutex_unlock(&spec->pcm_lock); return 0; } @@ -2296,7 +2308,9 @@ static void generic_hdmi_free(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int pin_idx, pcm_idx; - if (codec_has_acomp(codec)) { + if (spec->acomp_registered) { + snd_hdac_acomp_exit(&codec->bus->core); + } else if (codec_has_acomp(codec)) { snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); codec->relaxed_resume = 0; } @@ -2364,6 +2378,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec) if (!spec) return -ENOMEM; + spec->codec = codec; spec->ops = generic_standard_hdmi_ops; spec->dev_num = 1; /* initialize to 1 */ mutex_init(&spec->pcm_lock); @@ -2401,6 +2416,136 @@ static int patch_generic_hdmi(struct hda_codec *codec) return 0; } +/* + * generic audio component binding + */ + +/* turn on / off the unsol event jack detection dynamically */ +static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, + bool use_acomp) +{ + struct hda_jack_tbl *tbl; + + tbl = snd_hda_jack_tbl_get(codec, nid); + if (tbl) { + /* clear unsol even if component notifier is used, or re-enable + * if notifier is cleared + */ + unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl->tag); + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_UNSOLICITED_ENABLE, val); + } else { + /* if no jack entry was defined beforehand, create a new one + * at need (i.e. only when notifier is cleared) + */ + if (!use_acomp) + snd_hda_jack_detect_enable(codec, nid); + } +} + +/* set up / clear component notifier dynamically */ +static void generic_acomp_notifier_set(struct drm_audio_component *acomp, + bool use_acomp) +{ + struct hdmi_spec *spec; + int i; + + spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); + mutex_lock(&spec->pcm_lock); + spec->use_acomp_notifier = use_acomp; + spec->codec->relaxed_resume = use_acomp; + /* reprogram each jack detection logic depending on the notifier */ + if (spec->use_jack_detect) { + for (i = 0; i < spec->num_pins; i++) + reprogram_jack_detect(spec->codec, + get_pin(spec, i)->pin_nid, + use_acomp); + } + mutex_unlock(&spec->pcm_lock); +} + +/* enable / disable the notifier via master bind / unbind */ +static int generic_acomp_master_bind(struct device *dev, + struct drm_audio_component *acomp) +{ + generic_acomp_notifier_set(acomp, true); + return 0; +} + +static void generic_acomp_master_unbind(struct device *dev, + struct drm_audio_component *acomp) +{ + generic_acomp_notifier_set(acomp, false); +} + +/* check whether both HD-audio and DRM PCI devices belong to the same bus */ +static int match_bound_vga(struct device *dev, int subtype, void *data) +{ + struct hdac_bus *bus = data; + struct pci_dev *pci, *master; + + if (!dev_is_pci(dev) || !dev_is_pci(bus->dev)) + return 0; + master = to_pci_dev(bus->dev); + pci = to_pci_dev(dev); + return master->bus == pci->bus; +} + +/* audio component notifier for AMD/Nvidia HDMI codecs */ +static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) +{ + struct hda_codec *codec = audio_ptr; + struct hdmi_spec *spec = codec->spec; + hda_nid_t pin_nid = spec->port2pin(codec, port); + + if (!pin_nid) + return; + if (get_wcaps_type(get_wcaps(codec, pin_nid)) != AC_WID_PIN) + return; + /* skip notification during system suspend (but not in runtime PM); + * the state will be updated at resume + */ + if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) + return; + /* ditto during suspend/resume process itself */ + if (snd_hdac_is_in_pm(&codec->core)) + return; + + check_presence_and_report(codec, pin_nid, dev_id); +} + +/* set up the private drm_audio_ops from the template */ +static void setup_drm_audio_ops(struct hda_codec *codec, + const struct drm_audio_component_audio_ops *ops) +{ + struct hdmi_spec *spec = codec->spec; + + spec->drm_audio_ops.audio_ptr = codec; + /* intel_audio_codec_enable() or intel_audio_codec_disable() + * will call pin_eld_notify with using audio_ptr pointer + * We need make sure audio_ptr is really setup + */ + wmb(); + spec->drm_audio_ops.pin2port = ops->pin2port; + spec->drm_audio_ops.pin_eld_notify = ops->pin_eld_notify; + spec->drm_audio_ops.master_bind = ops->master_bind; + spec->drm_audio_ops.master_unbind = ops->master_unbind; +} + +/* initialize the generic HDMI audio component */ +static void generic_acomp_init(struct hda_codec *codec, + const struct drm_audio_component_audio_ops *ops, + int (*port2pin)(struct hda_codec *, int)) +{ + struct hdmi_spec *spec = codec->spec; + + spec->port2pin = port2pin; + setup_drm_audio_ops(codec, ops); + if (!snd_hdac_acomp_init(&codec->bus->core, &spec->drm_audio_ops, + match_bound_vga, 0)) + spec->acomp_registered = true; +} + /* * Intel codec parsers and helpers */ @@ -2569,20 +2714,19 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) check_presence_and_report(codec, pin_nid, dev_id); } +static const struct drm_audio_component_audio_ops intel_audio_ops = { + .pin2port = intel_pin2port, + .pin_eld_notify = intel_pin_eld_notify, +}; + /* register i915 component pin_eld_notify callback */ static void register_i915_notifier(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; spec->use_acomp_notifier = true; - spec->drm_audio_ops.audio_ptr = codec; - /* intel_audio_codec_enable() or intel_audio_codec_disable() - * will call pin_eld_notify with using audio_ptr pointer - * We need make sure audio_ptr is really setup - */ - wmb(); - spec->drm_audio_ops.pin2port = intel_pin2port; - spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; + spec->port2pin = intel_port2pin; + setup_drm_audio_ops(codec, &intel_audio_ops); snd_hdac_acomp_register_notifier(&codec->bus->core, &spec->drm_audio_ops); /* no need for forcible resume for jack check thanks to notifier */ @@ -2980,6 +3124,7 @@ static int patch_simple_hdmi(struct hda_codec *codec, if (!spec) return -ENOMEM; + spec->codec = codec; codec->spec = spec; hdmi_array_init(spec, 1); @@ -3284,6 +3429,26 @@ static int nvhdmi_chmap_validate(struct hdac_chmap *chmap, return 0; } +/* map from pin NID to port; port is 0-based */ +/* for Nvidia: assume widget NID starting from 4, with step 1 (4, 5, 6, ...) */ +static int nvhdmi_pin2port(void *audio_ptr, int pin_nid) +{ + return pin_nid - 4; +} + +/* reverse-map from port to pin NID: see above */ +static int nvhdmi_port2pin(struct hda_codec *codec, int port) +{ + return port + 4; +} + +static const struct drm_audio_component_audio_ops nvhdmi_audio_ops = { + .pin2port = nvhdmi_pin2port, + .pin_eld_notify = generic_acomp_pin_eld_notify, + .master_bind = generic_acomp_master_bind, + .master_unbind = generic_acomp_master_unbind, +}; + static int patch_nvhdmi(struct hda_codec *codec) { struct hdmi_spec *spec; @@ -3300,6 +3465,8 @@ static int patch_nvhdmi(struct hda_codec *codec) nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin); + return 0; } @@ -3787,6 +3954,26 @@ static int atihdmi_init(struct hda_codec *codec) return 0; } +/* map from pin NID to port; port is 0-based */ +/* for AMD: assume widget NID starting from 3, with step 2 (3, 5, 7, ...) */ +static int atihdmi_pin2port(void *audio_ptr, int pin_nid) +{ + return pin_nid / 2 - 1; +} + +/* reverse-map from port to pin NID: see above */ +static int atihdmi_port2pin(struct hda_codec *codec, int port) +{ + return port * 2 + 3; +} + +static const struct drm_audio_component_audio_ops atihdmi_audio_ops = { + .pin2port = atihdmi_pin2port, + .pin_eld_notify = generic_acomp_pin_eld_notify, + .master_bind = generic_acomp_master_bind, + .master_unbind = generic_acomp_master_unbind, +}; + static int patch_atihdmi(struct hda_codec *codec) { struct hdmi_spec *spec; @@ -3835,6 +4022,8 @@ static int patch_atihdmi(struct hda_codec *codec) */ codec->link_down_at_suspend = 1; + generic_acomp_init(codec, &atihdmi_audio_ops, atihdmi_port2pin); + return 0; } -- GitLab From caa8422d01e983782548648e125fd617cadcec3f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 20 Jul 2019 12:33:37 +0100 Subject: [PATCH 0087/7155] ALSA: hda: Flush interrupts on disabling I was looking at <4> [241.835158] general protection fault: 0000 [#1] PREEMPT SMP PTI <4> [241.835181] CPU: 1 PID: 214 Comm: kworker/1:3 Tainted: G U 5.2.0-CI-CI_DRM_6509+ #1 <4> [241.835199] Hardware name: Dell Inc. OptiPlex 745 /0GW726, BIOS 2.3.1 05/21/2007 <4> [241.835234] Workqueue: events snd_hdac_bus_process_unsol_events [snd_hda_core] <4> [241.835256] RIP: 0010:input_handle_event+0x16d/0x5e0 <4> [241.835270] Code: 48 8b 93 58 01 00 00 8b 52 08 89 50 04 8b 83 f8 06 00 00 48 8b 93 00 07 00 00 8d 70 01 48 8d 04 c2 83 e1 08 89 b3 f8 06 00 00 <66> 89 28 66 44 89 60 02 44 89 68 04 8b 93 f8 06 00 00 0f 84 fd fe <4> [241.835304] RSP: 0018:ffffc9000019fda0 EFLAGS: 00010046 <4> [241.835317] RAX: 6b6b6b6ec6c6c6c3 RBX: ffff8880290fefc8 RCX: 0000000000000000 <4> [241.835332] RDX: 000000006b6b6b6b RSI: 000000006b6b6b6c RDI: 0000000000000046 <4> [241.835347] RBP: 0000000000000005 R08: 0000000000000000 R09: 0000000000000001 <4> [241.835362] R10: ffffc9000019faa0 R11: 0000000000000000 R12: 0000000000000004 <4> [241.835377] R13: 0000000000000000 R14: ffff8880290ff1d0 R15: 0000000000000293 <4> [241.835392] FS: 0000000000000000(0000) GS:ffff88803de80000(0000) knlGS:0000000000000000 <4> [241.835409] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4> [241.835422] CR2: 00007ffe9a99e9b7 CR3: 000000002f588000 CR4: 00000000000006e0 <4> [241.835436] Call Trace: <4> [241.835449] input_event+0x45/0x70 <4> [241.835464] snd_jack_report+0xdc/0x100 <4> [241.835490] snd_hda_jack_report_sync+0x83/0xc0 [snd_hda_codec] <4> [241.835512] snd_hdac_bus_process_unsol_events+0x5a/0x70 [snd_hda_core] <4> [241.835530] process_one_work+0x245/0x610 which has the hallmarks of a worker queued from interrupt after it was supposedly cancelled (note the POISON_FREE), and I could not see where the interrupt would be flushed on shutdown so added the likely suspects. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111174 Signed-off-by: Chris Wilson Signed-off-by: Takashi Iwai --- sound/hda/hdac_controller.c | 2 ++ sound/pci/hda/hda_intel.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 3b0110545070..196bbc85699e 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -447,6 +447,8 @@ static void azx_int_disable(struct hdac_bus *bus) list_for_each_entry(azx_dev, &bus->stream_list, list) snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); + synchronize_irq(bus->irq); + /* disable SIE for all streams */ snd_hdac_chip_writeb(bus, INTCTL, 0); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cb8b0945547c..fdde80d95966 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1301,9 +1301,9 @@ static int azx_free(struct azx *chip) } if (bus->chip_init) { + azx_stop_chip(chip); azx_clear_irq_pending(chip); azx_stop_all_streams(chip); - azx_stop_chip(chip); } if (bus->irq >= 0) -- GitLab From 2a40d1b291138a7dce787b60f017d888b7d34349 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Jun 2019 21:21:09 +0200 Subject: [PATCH 0088/7155] ARM: dts: sunxi: Switch to the generic PHY properties The DWMAC specific properties to manage the PHY have been superseeded by the generic PHY properties. Let's move to it. Reviewed-by: Andrew Lunn Tested-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 6 +++--- arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts | 6 +++--- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 9 ++++----- arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts | 8 ++++---- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 09832b4e8fc8..2652d737fe7c 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -155,13 +155,13 @@ pinctrl-0 = <&gmac_rgmii_pins>; phy = <&phy1>; phy-mode = "rgmii"; - snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 30000>; status = "okay"; phy1: ethernet-phy@1 { reg = <1>; + reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <30000>; }; }; diff --git a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts index 8e724c52feff..7899712400b2 100644 --- a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts +++ b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts @@ -95,13 +95,13 @@ phy = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_dldo1>; - snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>; /* PA21 */ - snps,reset-active-low; - snps,reset-delays-us = <0 10000 30000>; status = "okay"; phy1: ethernet-phy@1 { reg = <1>; + reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; /* PA21 */ + reset-assert-us = <10000>; + reset-deassert-us = <30000>; }; }; diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index fd0153f65685..b01d91d025ec 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -103,15 +103,14 @@ phy = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_vdd>; - /* phy reset config */ - snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>; /* PA17 */ - snps,reset-active-low; - /* wait 1s after reset, otherwise fail to read phy id */ - snps,reset-delays-us = <0 10000 1000000>; status = "okay"; phy1: ethernet-phy@1 { reg = <1>; + reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ + reset-assert-us = <10000>; + /* wait 1s after reset, otherwise fail to read phy id */ + reset-deassert-us = <1000000>; }; }; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts index c34a83f666c7..ca12cee27072 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts @@ -108,14 +108,14 @@ phy = <&phy3>; phy-mode = "rgmii"; phy-supply = <®_vcc3v3>; - - snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 1000000>; status = "okay"; phy3: ethernet-phy@3 { reg = <3>; + reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ + reset-assert-us = <10000>; + /* wait 1s after reset, otherwise fail to read phy id */ + reset-deassert-us = <1000000>; }; }; -- GitLab From de332de26d19a6102c6e82c8774f983b32a74488 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 19 Jun 2019 11:03:17 +0200 Subject: [PATCH 0089/7155] ARM: dts: sunxi: Switch from phy to phy-handle The phy device tree property has been deprecated in favor of phy-handle, let's replace it. Reviewed-by: Andrew Lunn Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-a1000.dts | 2 +- arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts | 2 +- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 2 +- arch/arm/boot/dts/sun4i-a10-hackberry.dts | 2 +- arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts | 2 +- arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts | 2 +- arch/arm/boot/dts/sun4i-a10-marsboard.dts | 2 +- arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 2 +- arch/arm/boot/dts/sun4i-a10-pcduino.dts | 2 +- arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 2 +- arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts | 2 +- arch/arm/boot/dts/sun6i-a31-colombus.dts | 2 +- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 2 +- arch/arm/boot/dts/sun6i-a31-i7.dts | 2 +- arch/arm/boot/dts/sun6i-a31-m9.dts | 2 +- arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts | 2 +- arch/arm/boot/dts/sun6i-a31s-cs908.dts | 2 +- arch/arm/boot/dts/sun6i-a31s-sina31s.dts | 2 +- arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts | 2 +- arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 2 +- arch/arm/boot/dts/sun7i-a20-bananapi.dts | 2 +- arch/arm/boot/dts/sun7i-a20-bananapro.dts | 2 +- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 2 +- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 2 +- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 2 +- arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 2 +- arch/arm/boot/dts/sun7i-a20-icnova-swac.dts | 2 +- arch/arm/boot/dts/sun7i-a20-itead-ibox.dts | 2 +- arch/arm/boot/dts/sun7i-a20-m3.dts | 2 +- arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts | 2 +- arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts | 2 +- arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts | 2 +- arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts | 2 +- arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 2 +- arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts | 2 +- arch/arm/boot/dts/sun7i-a20-orangepi.dts | 2 +- arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts | 2 +- arch/arm/boot/dts/sun7i-a20-pcduino3.dts | 2 +- arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts | 2 +- arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 2 +- arch/arm/boot/dts/sun9i-a80-optimus.dts | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts index 6c254ec4c85b..8692b11a83c3 100644 --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts @@ -125,7 +125,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts index 38a2c4134952..816d534ac093 100644 --- a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts +++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts @@ -68,7 +68,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index 7306c65df88a..6ca02e824acc 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -114,7 +114,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts index cc988ccd5ca7..47dea0922501 100644 --- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts +++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts @@ -80,7 +80,7 @@ }; &emac { - phy = <&phy0>; + phy-handle = <&phy0>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts b/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts index 80ecd78247ac..d4e319d16aae 100644 --- a/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts +++ b/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts @@ -58,7 +58,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&emac_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts index 247fa27ef717..8a7b4c53d278 100644 --- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts +++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts @@ -94,7 +94,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/sun4i-a10-marsboard.dts index 58ad2ad9041f..a843e57530ed 100644 --- a/arch/arm/boot/dts/sun4i-a10-marsboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-marsboard.dts @@ -105,7 +105,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts index a8e537fd4bd6..845f76824d57 100644 --- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts @@ -112,7 +112,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts index 0f1e781069e9..83287b6c975e 100644 --- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts +++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts @@ -110,7 +110,7 @@ }; &emac { - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts index 5340b4164df2..7033a123c9a3 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts @@ -98,7 +98,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&emac_pa_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts index b5ee8fb13a92..1f74ba1634cc 100644 --- a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts +++ b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts @@ -91,7 +91,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&emac_pd_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index c3d56dc93513..50092b0bd0fe 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -76,7 +76,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 2652d737fe7c..7c611ddbaf2f 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -153,7 +153,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/sun6i-a31-i7.dts index 091eb2ac53b3..ebb0b4710afb 100644 --- a/arch/arm/boot/dts/sun6i-a31-i7.dts +++ b/arch/arm/boot/dts/sun6i-a31-i7.dts @@ -117,7 +117,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts index 6eafb6361a26..4910c6ccf2f7 100644 --- a/arch/arm/boot/dts/sun6i-a31-m9.dts +++ b/arch/arm/boot/dts/sun6i-a31-m9.dts @@ -84,7 +84,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts index ca036f97923a..703e1c19b407 100644 --- a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts +++ b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts @@ -84,7 +84,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/sun6i-a31s-cs908.dts index 72a02c045a38..6e9ec3f1695e 100644 --- a/arch/arm/boot/dts/sun6i-a31s-cs908.dts +++ b/arch/arm/boot/dts/sun6i-a31s-cs908.dts @@ -67,7 +67,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; phy1: ethernet-phy@1 { diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts index 4865c3271ab0..c92779bc8f85 100644 --- a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts +++ b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts @@ -115,7 +115,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; diff --git a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts index 7899712400b2..e993b2d8ddd0 100644 --- a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts +++ b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts @@ -92,7 +92,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_dldo1>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts index e2bfe0058830..c601ecf5ab35 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts @@ -129,7 +129,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts index 4df921632f7a..c5730b30a15d 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts @@ -131,7 +131,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/sun7i-a20-bananapro.dts index 0176e9de0180..86f4ebb77703 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapro.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapro.dts @@ -109,7 +109,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 08e5a5abf8cc..e322f0f06003 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -115,7 +115,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 99f531b8d2a7..a8f7f63fdde1 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -150,7 +150,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index b01d91d025ec..322717cb0b9a 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -100,7 +100,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_vdd>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index 5f1c4f573d3e..8a610dacb983 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -115,7 +115,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts index 7449aac3f43b..a20e91c8dbe5 100644 --- a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts +++ b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts @@ -76,7 +76,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts index b90a7607d069..c27567c0b027 100644 --- a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts +++ b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts @@ -97,7 +97,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts index b8a1aaaf3976..bde0ef783e71 100644 --- a/arch/arm/boot/dts/sun7i-a20-m3.dts +++ b/arch/arm/boot/dts/sun7i-a20-m3.dts @@ -82,7 +82,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts index f0e6a96e5785..f419b9ee9d1e 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts @@ -111,7 +111,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts index ca12cee27072..d3d03b7ffb1a 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts @@ -105,7 +105,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy3>; + phy-handle = <&phy3>; phy-mode = "rgmii"; phy-supply = <®_vcc3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts index e40dd47df8ce..70a883276d34 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts @@ -106,7 +106,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 56f451c07f93..0fe657e062a7 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -111,7 +111,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index 0dcba070444a..559736961b54 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -118,7 +118,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>, <&gmac_txerr>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts index 9628041bb3a3..a94ff50bcf73 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts @@ -120,7 +120,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts index 7b3532665c28..956579a10b5f 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts @@ -96,7 +96,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts index 173b676436e9..993fb97d19df 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts @@ -114,7 +114,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index 14a88aa16a97..02e321523d0e 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -122,7 +122,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_mii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts index f8475a39777b..9dfe7e2a08cc 100644 --- a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts +++ b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts @@ -81,7 +81,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts index 18156ffa3ce9..650890b049e2 100644 --- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts +++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts @@ -128,7 +128,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_cldo1>; status = "okay"; diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts index 2ed28d9e2787..03ad25534f20 100644 --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts @@ -123,7 +123,7 @@ &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; - phy = <&phy1>; + phy-handle = <&phy1>; phy-mode = "rgmii"; phy-supply = <®_cldo1>; status = "okay"; -- GitLab From 229b969b3d38bc28bcd55841ee7ca9a9afb922f3 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 14 Jul 2019 08:23:14 -0700 Subject: [PATCH 0090/7155] x86/apic: Initialize TPR to block interrupts 16-31 The APIC, per spec, is fundamentally confused and thinks that interrupt vectors 16-31 are valid. This makes no sense -- the CPU reserves vectors 0-31 for exceptions (faults, traps, etc). Obviously, no device should actually produce an interrupt with vector 16-31, but robustness can be improved by setting the APIC TPR class to 1, which will prevent delivery of an interrupt with a vector below 32. Note: This is *not* intended as a security measure against attackers who control malicious hardware. Any PCI or similar hardware that can be controlled by an attacker MUST be behind a functional IOMMU that remaps interrupts. The purpose of this change is to reduce the chance that a certain class of device malfunctions crashes the kernel in hard-to-debug ways. Suggested-by: Andrew Cooper Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/dc04a9f8b234d7b0956a8d2560b8945bcd9c4bf7.1563117760.git.luto@kernel.org --- arch/x86/kernel/apic/apic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index f5291362da1a..84032bf81476 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1561,11 +1561,14 @@ static void setup_local_APIC(void) #endif /* - * Set Task Priority to 'accept all'. We never change this - * later on. + * Set Task Priority to 'accept all except vectors 0-31'. An APIC + * vector in the 16-31 range could be delivered if TPR == 0, but we + * would think it's an exception and terrible things will happen. We + * never change this later on. */ value = apic_read(APIC_TASKPRI); value &= ~APIC_TPRI_MASK; + value |= 0x10; apic_write(APIC_TASKPRI, value); apic_pending_intr_clear(); -- GitLab From 83b584d9c6a1494170abd3a8b24f41939b23d625 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 15 Jul 2019 16:16:41 +0100 Subject: [PATCH 0091/7155] x86/paravirt: Drop {read,write}_cr8() hooks There is a lot of infrastructure for functionality which is used exclusively in __{save,restore}_processor_state() on the suspend/resume path. cr8 is an alias of APIC_TASKPRI, and APIC_TASKPRI is saved/restored by lapic_{suspend,resume}(). Saving and restoring cr8 independently of the rest of the Local APIC state isn't a clever thing to be doing. Delete the suspend/resume cr8 handling, which shrinks the size of struct saved_context, and allows for the removal of both PVOPS. Signed-off-by: Andrew Cooper Signed-off-by: Thomas Gleixner Reviewed-by: Juergen Gross Link: https://lkml.kernel.org/r/20190715151641.29210-1-andrew.cooper3@citrix.com --- arch/x86/include/asm/paravirt.h | 12 ------------ arch/x86/include/asm/paravirt_types.h | 5 ----- arch/x86/include/asm/special_insns.h | 24 ------------------------ arch/x86/include/asm/suspend_64.h | 2 +- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/paravirt.c | 4 ---- arch/x86/power/cpu.c | 4 ---- arch/x86/xen/enlighten_pv.c | 15 --------------- 8 files changed, 1 insertion(+), 66 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index dce26f1d13e1..69089d46f128 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -139,18 +139,6 @@ static inline void __write_cr4(unsigned long x) PVOP_VCALL1(cpu.write_cr4, x); } -#ifdef CONFIG_X86_64 -static inline unsigned long read_cr8(void) -{ - return PVOP_CALL0(unsigned long, cpu.read_cr8); -} - -static inline void write_cr8(unsigned long x) -{ - PVOP_VCALL1(cpu.write_cr8, x); -} -#endif - static inline void arch_safe_halt(void) { PVOP_VCALL0(irq.safe_halt); diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 639b2df445ee..70b654f3ffe5 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -119,11 +119,6 @@ struct pv_cpu_ops { void (*write_cr4)(unsigned long); -#ifdef CONFIG_X86_64 - unsigned long (*read_cr8)(void); - void (*write_cr8)(unsigned long); -#endif - /* Segment descriptor handling */ void (*load_tr_desc)(void); void (*load_gdt)(const struct desc_ptr *); diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h index 219be88a59d2..6d37b8fcfc77 100644 --- a/arch/x86/include/asm/special_insns.h +++ b/arch/x86/include/asm/special_insns.h @@ -73,20 +73,6 @@ static inline unsigned long native_read_cr4(void) void native_write_cr4(unsigned long val); -#ifdef CONFIG_X86_64 -static inline unsigned long native_read_cr8(void) -{ - unsigned long cr8; - asm volatile("movq %%cr8,%0" : "=r" (cr8)); - return cr8; -} - -static inline void native_write_cr8(unsigned long val) -{ - asm volatile("movq %0,%%cr8" :: "r" (val) : "memory"); -} -#endif - #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS static inline u32 rdpkru(void) { @@ -200,16 +186,6 @@ static inline void wbinvd(void) #ifdef CONFIG_X86_64 -static inline unsigned long read_cr8(void) -{ - return native_read_cr8(); -} - -static inline void write_cr8(unsigned long x) -{ - native_write_cr8(x); -} - static inline void load_gs_index(unsigned selector) { native_load_gs_index(selector); diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h index a7af9f53c0cb..35bb35d28733 100644 --- a/arch/x86/include/asm/suspend_64.h +++ b/arch/x86/include/asm/suspend_64.h @@ -34,7 +34,7 @@ struct saved_context { */ unsigned long kernelmode_gs_base, usermode_gs_base, fs_base; - unsigned long cr0, cr2, cr3, cr4, cr8; + unsigned long cr0, cr2, cr3, cr4; u64 misc_enable; bool misc_enable_saved; struct saved_msrs saved_msrs; diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index d3d075226c0a..8b54d8e3a561 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -62,7 +62,6 @@ int main(void) ENTRY(cr2); ENTRY(cr3); ENTRY(cr4); - ENTRY(cr8); ENTRY(gdt_desc); BLANK(); #undef ENTRY diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 0aa6256eedd8..59d3d2763a9e 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -311,10 +311,6 @@ struct paravirt_patch_template pv_ops = { .cpu.read_cr0 = native_read_cr0, .cpu.write_cr0 = native_write_cr0, .cpu.write_cr4 = native_write_cr4, -#ifdef CONFIG_X86_64 - .cpu.read_cr8 = native_read_cr8, - .cpu.write_cr8 = native_write_cr8, -#endif .cpu.wbinvd = native_wbinvd, .cpu.read_msr = native_read_msr, .cpu.write_msr = native_write_msr, diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 24b079e94bc2..1c58d8982728 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -122,9 +122,6 @@ static void __save_processor_state(struct saved_context *ctxt) ctxt->cr2 = read_cr2(); ctxt->cr3 = __read_cr3(); ctxt->cr4 = __read_cr4(); -#ifdef CONFIG_X86_64 - ctxt->cr8 = read_cr8(); -#endif ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE, &ctxt->misc_enable); msr_save_context(ctxt); @@ -207,7 +204,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) #else /* CONFIG X86_64 */ wrmsrl(MSR_EFER, ctxt->efer); - write_cr8(ctxt->cr8); __write_cr4(ctxt->cr4); #endif write_cr3(ctxt->cr3); diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 7ceb32821093..58f79ab32358 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -877,16 +877,6 @@ static void xen_write_cr4(unsigned long cr4) native_write_cr4(cr4); } -#ifdef CONFIG_X86_64 -static inline unsigned long xen_read_cr8(void) -{ - return 0; -} -static inline void xen_write_cr8(unsigned long val) -{ - BUG_ON(val); -} -#endif static u64 xen_read_msr_safe(unsigned int msr, int *err) { @@ -1023,11 +1013,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .write_cr4 = xen_write_cr4, -#ifdef CONFIG_X86_64 - .read_cr8 = xen_read_cr8, - .write_cr8 = xen_write_cr8, -#endif - .wbinvd = native_wbinvd, .read_msr = xen_read_msr, -- GitLab From 45e29d119e9923ff14dfb840e3482bef1667bbfb Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 3 Jul 2019 13:34:05 -0700 Subject: [PATCH 0092/7155] x86/syscalls: Make __X32_SYSCALL_BIT be unsigned long Currently, it's an int. This is bizarre. Fortunately, the code using it still works: ~__X32_SYSCALL_BIT is also int, so, if nr is unsigned long, then C kindly sign-extends the ~__X32_SYSCALL_BIT part, and it actually results in the desired value. This is far more subtle than it deserves to be. Syscall numbers are, for all practical purposes, unsigned long, so make __X32_SYSCALL_BIT be unsigned long. Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/99b0d83ad891c67105470a1a6b63243fd63a5061.1562185330.git.luto@kernel.org --- arch/x86/include/uapi/asm/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/uapi/asm/unistd.h b/arch/x86/include/uapi/asm/unistd.h index 30d7d04d72d6..196fdd02b8b1 100644 --- a/arch/x86/include/uapi/asm/unistd.h +++ b/arch/x86/include/uapi/asm/unistd.h @@ -3,7 +3,7 @@ #define _UAPI_ASM_X86_UNISTD_H /* x32 syscall flag bit */ -#define __X32_SYSCALL_BIT 0x40000000 +#define __X32_SYSCALL_BIT 0x40000000UL #ifndef __KERNEL__ # ifdef __i386__ -- GitLab From a8d03c3f300eefff3b5c14798409e4b43e37dd9b Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 3 Jul 2019 13:34:02 -0700 Subject: [PATCH 0093/7155] x86/syscalls: Use the compat versions of rt_sigsuspend() and rt_sigprocmask() I'm working on some code that detects at build time if there's a COMPAT_SYSCALL_DEFINE() that is not referenced in the x86 syscall tables. It catches three offenders: rt_sigsuspend(), rt_sigprocmask(), and sendfile64(). For rt_sigsuspend() and rt_sigprocmask(), the only potential difference between the native and compat versions is that the compat version converts the sigset_t, but, on little endian architectures, the conversion is a no-op. This is why they both currently work on x86. To make the code more consistent, and to make the upcoming patches work, rewire x86 to use the compat vesions. sendfile64() is more complicated, and will be addressed separately. Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/51643ac3157b5921eae0e172a8a0b1d953e68ebb.1562185330.git.luto@kernel.org --- arch/x86/entry/syscalls/syscall_32.tbl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index c00019abd076..3fe02546aed3 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -186,11 +186,11 @@ 172 i386 prctl sys_prctl __ia32_sys_prctl 173 i386 rt_sigreturn sys_rt_sigreturn sys32_rt_sigreturn 174 i386 rt_sigaction sys_rt_sigaction __ia32_compat_sys_rt_sigaction -175 i386 rt_sigprocmask sys_rt_sigprocmask __ia32_sys_rt_sigprocmask +175 i386 rt_sigprocmask sys_rt_sigprocmask __ia32_compat_sys_rt_sigprocmask 176 i386 rt_sigpending sys_rt_sigpending __ia32_compat_sys_rt_sigpending 177 i386 rt_sigtimedwait sys_rt_sigtimedwait_time32 __ia32_compat_sys_rt_sigtimedwait_time32 178 i386 rt_sigqueueinfo sys_rt_sigqueueinfo __ia32_compat_sys_rt_sigqueueinfo -179 i386 rt_sigsuspend sys_rt_sigsuspend __ia32_sys_rt_sigsuspend +179 i386 rt_sigsuspend sys_rt_sigsuspend __ia32_compat_sys_rt_sigsuspend 180 i386 pread64 sys_pread64 __ia32_compat_sys_x86_pread 181 i386 pwrite64 sys_pwrite64 __ia32_compat_sys_x86_pwrite 182 i386 chown sys_chown16 __ia32_sys_chown16 -- GitLab From f85a8573ceb225e606fcf38a9320782316f47c71 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 3 Jul 2019 13:34:03 -0700 Subject: [PATCH 0094/7155] x86/syscalls: Disallow compat entries for all types of 64-bit syscalls A "compat" entry in the syscall tables means to use a different entry on 32-bit and 64-bit builds. This only makes sense for syscalls that exist in the first place in 32-bit builds, so disallow it for anything other than i386. Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/4b7565954c5a06530ac01d98cb1592538fd8ae51.1562185330.git.luto@kernel.org --- arch/x86/entry/syscalls/syscalltbl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 94fcd1951aca..53c8c1a9adf9 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -27,8 +27,8 @@ emit() { compat="$4" umlentry="" - if [ "$abi" = "64" -a -n "$compat" ]; then - echo "a compat entry for a 64-bit syscall makes no sense" >&2 + if [ "$abi" != "I386" -a -n "$compat" ]; then + echo "a compat entry ($abi: $compat) for a 64-bit syscall makes no sense" >&2 exit 1 fi -- GitLab From 6365b842aae4490ebfafadfc6bb27a6d3cc54757 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 3 Jul 2019 13:34:04 -0700 Subject: [PATCH 0095/7155] x86/syscalls: Split the x32 syscalls into their own table For unfortunate historical reasons, the x32 syscalls and the x86_64 syscalls are not all numbered the same. As an example, ioctl() is nr 16 on x86_64 but 514 on x32. This has potentially nasty consequences, since it means that there are two valid RAX values to do ioctl(2) and two invalid RAX values. The valid values are 16 (i.e. ioctl(2) using the x86_64 ABI) and (514 | 0x40000000) (i.e. ioctl(2) using the x32 ABI). The invalid values are 514 and (16 | 0x40000000). 514 will enter the "COMPAT_SYSCALL_DEFINE3(ioctl, ...)" entry point with in_compat_syscall() and in_x32_syscall() returning false, whereas (16 | 0x40000000) will enter the native entry point with in_compat_syscall() and in_x32_syscall() returning true. Both are bogus, and both will exercise code paths in the kernel and in any running seccomp filters that really ought to be unreachable. Splitting out the x32 syscalls into their own tables, allows both bogus invocations to return -ENOSYS. I've checked glibc, musl, and Bionic, and all of them appear to call syscalls with their correct numbers, so this change should have no effect on them. There is an added benefit going forward: new syscalls that need special handling on x32 can share the same number on x32 and x86_64. This means that the special syscall range 512-547 can be treated as a legacy wart instead of something that may need to be extended in the future. Also add a selftest to verify the new behavior. Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/208024256b764312598f014ebfb0a42472c19354.1562185330.git.luto@kernel.org --- arch/x86/entry/common.c | 13 +-- arch/x86/entry/syscall_64.c | 25 ++++++ arch/x86/entry/syscalls/syscalltbl.sh | 31 ++++--- arch/x86/include/asm/syscall.h | 4 + arch/x86/include/asm/unistd.h | 6 -- arch/x86/kernel/asm-offsets_64.c | 20 +++++ tools/testing/selftests/x86/Makefile | 2 +- .../testing/selftests/x86/syscall_numbering.c | 89 +++++++++++++++++++ 8 files changed, 163 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/x86/syscall_numbering.c diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 536b574b6161..3f8e22615812 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -285,15 +285,16 @@ __visible void do_syscall_64(unsigned long nr, struct pt_regs *regs) if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) nr = syscall_trace_enter(regs); - /* - * NB: Native and x32 syscalls are dispatched from the same - * table. The only functional difference is the x32 bit in - * regs->orig_ax, which changes the behavior of some syscalls. - */ - nr &= __SYSCALL_MASK; if (likely(nr < NR_syscalls)) { nr = array_index_nospec(nr, NR_syscalls); regs->ax = sys_call_table[nr](regs); +#ifdef CONFIG_X86_X32_ABI + } else if (likely((nr & __X32_SYSCALL_BIT) && + (nr & ~__X32_SYSCALL_BIT) < X32_NR_syscalls)) { + nr = array_index_nospec(nr & ~__X32_SYSCALL_BIT, + X32_NR_syscalls); + regs->ax = x32_sys_call_table[nr](regs); +#endif } syscall_return_slowpath(regs); diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index d5252bc1e380..b1bf31713374 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -10,10 +10,13 @@ /* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */ extern asmlinkage long sys_ni_syscall(const struct pt_regs *); #define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *); +#define __SYSCALL_X32(nr, sym, qual) __SYSCALL_64(nr, sym, qual) #include #undef __SYSCALL_64 +#undef __SYSCALL_X32 #define __SYSCALL_64(nr, sym, qual) [nr] = sym, +#define __SYSCALL_X32(nr, sym, qual) asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* @@ -23,3 +26,25 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { [0 ... __NR_syscall_max] = &sys_ni_syscall, #include }; + +#undef __SYSCALL_64 +#undef __SYSCALL_X32 + +#ifdef CONFIG_X86_X32_ABI + +#define __SYSCALL_64(nr, sym, qual) +#define __SYSCALL_X32(nr, sym, qual) [nr] = sym, + +asmlinkage const sys_call_ptr_t x32_sys_call_table[__NR_syscall_x32_max+1] = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. + */ + [0 ... __NR_syscall_x32_max] = &sys_ni_syscall, +#include +}; + +#undef __SYSCALL_64 +#undef __SYSCALL_X32 + +#endif diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 53c8c1a9adf9..1af2be39e7d9 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -1,13 +1,13 @@ -#!/bin/sh +#!/bin/bash # SPDX-License-Identifier: GPL-2.0 in="$1" out="$2" syscall_macro() { - abi="$1" - nr="$2" - entry="$3" + local abi="$1" + local nr="$2" + local entry="$3" # Entry can be either just a function name or "function/qualifier" real_entry="${entry%%/*}" @@ -21,11 +21,11 @@ syscall_macro() { } emit() { - abi="$1" - nr="$2" - entry="$3" - compat="$4" - umlentry="" + local abi="$1" + local nr="$2" + local entry="$3" + local compat="$4" + local umlentry="" if [ "$abi" != "I386" -a -n "$compat" ]; then echo "a compat entry ($abi: $compat) for a 64-bit syscall makes no sense" >&2 @@ -62,14 +62,17 @@ grep '^[0-9]' "$in" | sort -n | ( while read nr abi name entry compat; do abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` if [ "$abi" = "COMMON" -o "$abi" = "64" ]; then - # COMMON is the same as 64, except that we don't expect X32 - # programs to use it. Our expectation has nothing to do with - # any generated code, so treat them the same. emit 64 "$nr" "$entry" "$compat" + if [ "$abi" = "COMMON" ]; then + # COMMON means that this syscall exists in the same form for + # 64-bit and X32. + echo "#ifdef CONFIG_X86_X32_ABI" + emit X32 "$nr" "$entry" "$compat" + echo "#endif" + fi elif [ "$abi" = "X32" ]; then - # X32 is equivalent to 64 on an X32-compatible kernel. echo "#ifdef CONFIG_X86_X32_ABI" - emit 64 "$nr" "$entry" "$compat" + emit X32 "$nr" "$entry" "$compat" echo "#endif" elif [ "$abi" = "I386" ]; then emit "$abi" "$nr" "$entry" "$compat" diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 2dc4a021beea..8db3fdb6102e 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -36,6 +36,10 @@ extern const sys_call_ptr_t sys_call_table[]; extern const sys_call_ptr_t ia32_sys_call_table[]; #endif +#ifdef CONFIG_X86_X32_ABI +extern const sys_call_ptr_t x32_sys_call_table[]; +#endif + /* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 097589753fec..a7dd080749ce 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -5,12 +5,6 @@ #include -# ifdef CONFIG_X86_X32_ABI -# define __SYSCALL_MASK (~(__X32_SYSCALL_BIT)) -# else -# define __SYSCALL_MASK (~0) -# endif - # ifdef CONFIG_X86_32 # include diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index d3d075226c0a..70e97727a26a 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -6,13 +6,28 @@ #include #define __SYSCALL_64(nr, sym, qual) [nr] = 1, +#define __SYSCALL_X32(nr, sym, qual) static char syscalls_64[] = { #include }; +#undef __SYSCALL_64 +#undef __SYSCALL_X32 + +#ifdef CONFIG_X86_X32_ABI +#define __SYSCALL_64(nr, sym, qual) +#define __SYSCALL_X32(nr, sym, qual) [nr] = 1, +static char syscalls_x32[] = { +#include +}; +#undef __SYSCALL_64 +#undef __SYSCALL_X32 +#endif + #define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls_ia32[] = { #include }; +#undef __SYSCALL_I386 #if defined(CONFIG_KVM_GUEST) && defined(CONFIG_PARAVIRT_SPINLOCKS) #include @@ -80,6 +95,11 @@ int main(void) DEFINE(__NR_syscall_max, sizeof(syscalls_64) - 1); DEFINE(NR_syscalls, sizeof(syscalls_64)); +#ifdef CONFIG_X86_X32_ABI + DEFINE(__NR_syscall_x32_max, sizeof(syscalls_x32) - 1); + DEFINE(X32_NR_syscalls, sizeof(syscalls_x32)); +#endif + DEFINE(__NR_syscall_compat_max, sizeof(syscalls_ia32) - 1); DEFINE(IA32_NR_syscalls, sizeof(syscalls_ia32)); diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index fa07d526fe39..07b6387f28cf 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -17,7 +17,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer -TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip +TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip syscall_numbering # Some selftests require 32bit support enabled also on 64bit systems TARGETS_C_32BIT_NEEDED := ldt_gdt ptrace_syscall diff --git a/tools/testing/selftests/x86/syscall_numbering.c b/tools/testing/selftests/x86/syscall_numbering.c new file mode 100644 index 000000000000..d6b09cb1aa2c --- /dev/null +++ b/tools/testing/selftests/x86/syscall_numbering.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * syscall_arg_fault.c - tests faults 32-bit fast syscall stack args + * Copyright (c) 2018 Andrew Lutomirski + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +static int nerrs; + +#define X32_BIT 0x40000000UL + +static void check_enosys(unsigned long nr, bool *ok) +{ + /* If this fails, a segfault is reasonably likely. */ + fflush(stdout); + + long ret = syscall(nr, 0, 0, 0, 0, 0, 0); + if (ret == 0) { + printf("[FAIL]\tsyscall %lu succeeded, but it should have failed\n", nr); + *ok = false; + } else if (errno != ENOSYS) { + printf("[FAIL]\tsyscall %lu had error code %d, but it should have reported ENOSYS\n", nr, errno); + *ok = false; + } +} + +static void test_x32_without_x32_bit(void) +{ + bool ok = true; + + /* + * Syscalls 512-547 are "x32" syscalls. They are intended to be + * called with the x32 (0x40000000) bit set. Calling them without + * the x32 bit set is nonsense and should not work. + */ + printf("[RUN]\tChecking syscalls 512-547\n"); + for (int i = 512; i <= 547; i++) + check_enosys(i, &ok); + + /* + * Check that a handful of 64-bit-only syscalls are rejected if the x32 + * bit is set. + */ + printf("[RUN]\tChecking some 64-bit syscalls in x32 range\n"); + check_enosys(16 | X32_BIT, &ok); /* ioctl */ + check_enosys(19 | X32_BIT, &ok); /* readv */ + check_enosys(20 | X32_BIT, &ok); /* writev */ + + /* + * Check some syscalls with high bits set. + */ + printf("[RUN]\tChecking numbers above 2^32-1\n"); + check_enosys((1UL << 32), &ok); + check_enosys(X32_BIT | (1UL << 32), &ok); + + if (!ok) + nerrs++; + else + printf("[OK]\tThey all returned -ENOSYS\n"); +} + +int main() +{ + /* + * Anyone diagnosing a failure will want to know whether the kernel + * supports x32. Tell them. + */ + printf("\tChecking for x32..."); + fflush(stdout); + if (syscall(39 | X32_BIT, 0, 0, 0, 0, 0, 0) >= 0) { + printf(" supported\n"); + } else if (errno == ENOSYS) { + printf(" not supported\n"); + } else { + printf(" confused\n"); + } + + test_x32_without_x32_bit(); + + return nerrs ? 1 : 0; +} -- GitLab From 1e0c08e3034de0659367393bfa825188462f22e6 Mon Sep 17 00:00:00 2001 From: Gayatri Kammela Date: Wed, 17 Jul 2019 16:46:31 -0700 Subject: [PATCH 0096/7155] cpu/cpuid-deps: Add a tab to cpuid dependent features Improve code readability by adding a tab between the elements of each structure in an array of cpuid-dep struct so longer feature names will fit. Signed-off-by: Gayatri Kammela Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190717234632.32673-2-gayatri.kammela@intel.com --- arch/x86/kernel/cpu/cpuid-deps.c | 96 ++++++++++++++++---------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c index b5353244749b..630a9f77fb6b 100644 --- a/arch/x86/kernel/cpu/cpuid-deps.c +++ b/arch/x86/kernel/cpu/cpuid-deps.c @@ -20,54 +20,54 @@ struct cpuid_dep { * but it's difficult to tell that to the init reference checker. */ static const struct cpuid_dep cpuid_deps[] = { - { X86_FEATURE_FXSR, X86_FEATURE_FPU }, - { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE }, - { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE }, - { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE }, - { X86_FEATURE_AVX, X86_FEATURE_XSAVE }, - { X86_FEATURE_PKU, X86_FEATURE_XSAVE }, - { X86_FEATURE_MPX, X86_FEATURE_XSAVE }, - { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE }, - { X86_FEATURE_CMOV, X86_FEATURE_FXSR }, - { X86_FEATURE_MMX, X86_FEATURE_FXSR }, - { X86_FEATURE_MMXEXT, X86_FEATURE_MMX }, - { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR }, - { X86_FEATURE_XSAVE, X86_FEATURE_FXSR }, - { X86_FEATURE_XMM, X86_FEATURE_FXSR }, - { X86_FEATURE_XMM2, X86_FEATURE_XMM }, - { X86_FEATURE_XMM3, X86_FEATURE_XMM2 }, - { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 }, - { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 }, - { X86_FEATURE_XMM3, X86_FEATURE_XMM2 }, - { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 }, - { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, }, - { X86_FEATURE_F16C, X86_FEATURE_XMM2, }, - { X86_FEATURE_AES, X86_FEATURE_XMM2 }, - { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 }, - { X86_FEATURE_FMA, X86_FEATURE_AVX }, - { X86_FEATURE_AVX2, X86_FEATURE_AVX, }, - { X86_FEATURE_AVX512F, X86_FEATURE_AVX, }, - { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL }, - { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VAES, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL }, - { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL }, - { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL }, - { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F }, - { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F }, - { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC }, - { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC }, - { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC }, - { X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL }, + { X86_FEATURE_FXSR, X86_FEATURE_FPU }, + { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE }, + { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE }, + { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE }, + { X86_FEATURE_AVX, X86_FEATURE_XSAVE }, + { X86_FEATURE_PKU, X86_FEATURE_XSAVE }, + { X86_FEATURE_MPX, X86_FEATURE_XSAVE }, + { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE }, + { X86_FEATURE_CMOV, X86_FEATURE_FXSR }, + { X86_FEATURE_MMX, X86_FEATURE_FXSR }, + { X86_FEATURE_MMXEXT, X86_FEATURE_MMX }, + { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR }, + { X86_FEATURE_XSAVE, X86_FEATURE_FXSR }, + { X86_FEATURE_XMM, X86_FEATURE_FXSR }, + { X86_FEATURE_XMM2, X86_FEATURE_XMM }, + { X86_FEATURE_XMM3, X86_FEATURE_XMM2 }, + { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 }, + { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 }, + { X86_FEATURE_XMM3, X86_FEATURE_XMM2 }, + { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 }, + { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, }, + { X86_FEATURE_F16C, X86_FEATURE_XMM2, }, + { X86_FEATURE_AES, X86_FEATURE_XMM2 }, + { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 }, + { X86_FEATURE_FMA, X86_FEATURE_AVX }, + { X86_FEATURE_AVX2, X86_FEATURE_AVX, }, + { X86_FEATURE_AVX512F, X86_FEATURE_AVX, }, + { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL }, + { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL }, + { X86_FEATURE_VAES, X86_FEATURE_AVX512VL }, + { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL }, + { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL }, + { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL }, + { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F }, + { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC }, + { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC }, + { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC }, + { X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL }, {} }; -- GitLab From 018ebca8bd704f18d56f8fff38e2c3d76d7d39fb Mon Sep 17 00:00:00 2001 From: Gayatri Kammela Date: Wed, 17 Jul 2019 16:46:32 -0700 Subject: [PATCH 0097/7155] x86/cpufeatures: Enable a new AVX512 CPU feature Add a new AVX512 instruction group/feature for enumeration in /proc/cpuinfo: AVX512_VP2INTERSECT. CPUID.(EAX=7,ECX=0):EDX[bit 8] AVX512_VP2INTERSECT Detailed information of CPUID bits for this feature can be found in the Intel Architecture Intsruction Set Extensions Programming Reference document (refer to Table 1-2). A copy of this document is available at https://bugzilla.kernel.org/show_bug.cgi?id=204215. Signed-off-by: Gayatri Kammela Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190717234632.32673-3-gayatri.kammela@intel.com --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/kernel/cpu/cpuid-deps.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 998c2cc08363..56f53bf3bbbf 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -353,6 +353,7 @@ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */ #define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ #define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c index 630a9f77fb6b..3cbe24ca80ab 100644 --- a/arch/x86/kernel/cpu/cpuid-deps.c +++ b/arch/x86/kernel/cpu/cpuid-deps.c @@ -64,6 +64,7 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F }, + { X86_FEATURE_AVX512_VP2INTERSECT, X86_FEATURE_AVX512VL }, { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC }, { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC }, { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC }, -- GitLab From fcd3f6222a4ece735d0b3ffb93f646eff693aa69 Mon Sep 17 00:00:00 2001 From: Maya Nakamura Date: Fri, 12 Jul 2019 08:14:47 +0000 Subject: [PATCH 0098/7155] x86/hyperv: Create and use Hyper-V page definitions Define HV_HYP_PAGE_SHIFT, HV_HYP_PAGE_SIZE, and HV_HYP_PAGE_MASK because the Linux guest page size and hypervisor page size concepts are different, even though they happen to be the same value on x86. Also, replace PAGE_SIZE with HV_HYP_PAGE_SIZE. Signed-off-by: Maya Nakamura Signed-off-by: Thomas Gleixner Reviewed-by: Michael Kelley Reviewed-by: Vitaly Kuznetsov Link: https://lkml.kernel.org/r/e95111629abf65d016e983f72494cbf110ce605f.1562916939.git.m.maya.nakamura@gmail.com --- arch/x86/include/asm/hyperv-tlfs.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index af78cd72b8f3..7a2705694f5b 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -12,6 +12,16 @@ #include #include +/* + * While not explicitly listed in the TLFS, Hyper-V always runs with a page size + * of 4096. These definitions are used when communicating with Hyper-V using + * guest physical pages and guest physical page addresses, since the guest page + * size may not be 4096 on all architectures. + */ +#define HV_HYP_PAGE_SHIFT 12 +#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT) +#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1)) + /* * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent * is set by CPUID(HvCpuIdFunctionVersionAndFeatures). @@ -847,7 +857,7 @@ union hv_gpa_page_range { * count is equal with how many entries of union hv_gpa_page_range can * be populated into the input parameter page. */ -#define HV_MAX_FLUSH_REP_COUNT ((PAGE_SIZE - 2 * sizeof(u64)) / \ +#define HV_MAX_FLUSH_REP_COUNT ((HV_HYP_PAGE_SIZE - 2 * sizeof(u64)) / \ sizeof(union hv_gpa_page_range)) struct hv_guest_mapping_flush_list { -- GitLab From 8c3e44bde7fd1b8291515f046008225711ac7beb Mon Sep 17 00:00:00 2001 From: Maya Nakamura Date: Fri, 12 Jul 2019 08:21:25 +0000 Subject: [PATCH 0099/7155] x86/hyperv: Add functions to allocate/deallocate page for Hyper-V Introduce two new functions, hv_alloc_hyperv_page() and hv_free_hyperv_page(), to allocate/deallocate memory with the size and alignment that Hyper-V expects as a page. Although currently they are not used, they are ready to be used to allocate/deallocate memory on x86 when their ARM64 counterparts are implemented, keeping symmetry between architectures with potentially different guest page sizes. Signed-off-by: Maya Nakamura Signed-off-by: Thomas Gleixner Reviewed-by: Michael Kelley Reviewed-by: Vitaly Kuznetsov Link: https://lore.kernel.org/lkml/alpine.DEB.2.21.1906272334560.32342@nanos.tec.linutronix.de/ Link: https://lore.kernel.org/lkml/87muindr9c.fsf@vitty.brq.redhat.com/ Link: https://lkml.kernel.org/r/706b2e71eb3e587b5f8801e50f090fae2a00e35d.1562916939.git.m.maya.nakamura@gmail.com --- arch/x86/hyperv/hv_init.c | 14 ++++++++++++++ arch/x86/include/asm/mshyperv.h | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 0d258688c8cf..d314cf1e15fd 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -37,6 +37,20 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); u32 hv_max_vp_index; EXPORT_SYMBOL_GPL(hv_max_vp_index); +void *hv_alloc_hyperv_page(void) +{ + BUILD_BUG_ON(PAGE_SIZE != HV_HYP_PAGE_SIZE); + + return (void *)__get_free_page(GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page); + +void hv_free_hyperv_page(unsigned long addr) +{ + free_page(addr); +} +EXPORT_SYMBOL_GPL(hv_free_hyperv_page); + static int hv_cpu_init(unsigned int cpu) { u64 msr_vp_index; diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 2ef31cc8c529..f4138aeb4280 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -218,7 +218,8 @@ static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) void __init hyperv_init(void); void hyperv_setup_mmu_ops(void); - +void *hv_alloc_hyperv_page(void); +void hv_free_hyperv_page(unsigned long addr); void hyperv_reenlightenment_intr(struct pt_regs *regs); void set_hv_tscchange_cb(void (*cb)(void)); void clear_hv_tscchange_cb(void); @@ -241,6 +242,8 @@ static inline void hv_apic_init(void) {} #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline void hyperv_setup_mmu_ops(void) {} +static inline void *hv_alloc_hyperv_page(void) { return NULL; } +static inline void hv_free_hyperv_page(unsigned long addr) {} static inline void set_hv_tscchange_cb(void (*cb)(void)) {} static inline void clear_hv_tscchange_cb(void) {} static inline void hyperv_stop_tsc_emulation(void) {}; -- GitLab From 83527ef7abf7c02c33a90b00f0954db35415adbd Mon Sep 17 00:00:00 2001 From: Maya Nakamura Date: Fri, 12 Jul 2019 08:25:18 +0000 Subject: [PATCH 0100/7155] drivers: hv: vmbus: Replace page definition with Hyper-V specific one Replace PAGE_SIZE with HV_HYP_PAGE_SIZE because the guest page size may not be 4096 on all architectures and Hyper-V always runs with a page size of 4096. Signed-off-by: Maya Nakamura Signed-off-by: Thomas Gleixner Reviewed-by: Michael Kelley Reviewed-by: Vitaly Kuznetsov Acked-by: Sasha Levin Link: https://lkml.kernel.org/r/0d9e80ecabcc950dc279fdd2e39bea4060123ba4.1562916939.git.m.maya.nakamura@gmail.com --- drivers/hv/hyperv_vmbus.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 362e70e9d145..6bf64cb6e31a 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -192,11 +192,11 @@ int hv_ringbuffer_read(struct vmbus_channel *channel, u64 *requestid, bool raw); /* - * Maximum channels is determined by the size of the interrupt page - * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt - * and the other is receive endpoint interrupt + * The Maximum number of channels (16348) is determined by the size of the + * interrupt page, which is HV_HYP_PAGE_SIZE. 1/2 of HV_HYP_PAGE_SIZE is to + * send endpoint interrupts, and the other is to receive endpoint interrupts. */ -#define MAX_NUM_CHANNELS ((PAGE_SIZE >> 1) << 3) /* 16348 channels */ +#define MAX_NUM_CHANNELS ((HV_HYP_PAGE_SIZE >> 1) << 3) /* The value here must be in multiple of 32 */ /* TODO: Need to make this configurable */ -- GitLab From 69732102426b1c55a257386841fb80ec1f425d32 Mon Sep 17 00:00:00 2001 From: Pingfan Liu Date: Tue, 16 Jul 2019 16:40:24 +0800 Subject: [PATCH 0101/7155] x86/realmode: Remove trampoline_status There is no reader of trampoline_status, it's only written. It turns out that after commit ce4b1b16502b ("x86/smpboot: Initialize secondary CPU only if master CPU will wait for it"), trampoline_status is not needed any more. Signed-off-by: Pingfan Liu Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/1563266424-3472-1-git-send-email-kernelfans@gmail.com --- arch/x86/include/asm/realmode.h | 1 - arch/x86/kernel/smpboot.c | 5 ----- arch/x86/realmode/rm/header.S | 1 - arch/x86/realmode/rm/trampoline_32.S | 3 --- arch/x86/realmode/rm/trampoline_64.S | 3 --- arch/x86/realmode/rm/trampoline_common.S | 4 ---- 6 files changed, 17 deletions(-) diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index c53682303c9c..09ecc32f6524 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h @@ -20,7 +20,6 @@ struct real_mode_header { u32 ro_end; /* SMP trampoline */ u32 trampoline_start; - u32 trampoline_status; u32 trampoline_header; #ifdef CONFIG_X86_64 u32 trampoline_pgd; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fdbd47ceb84d..497e9b7077c1 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1023,8 +1023,6 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle) static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, int *cpu0_nmi_registered) { - volatile u32 *trampoline_status = - (volatile u32 *) __va(real_mode_header->trampoline_status); /* start_ip had better be page-aligned! */ unsigned long start_ip = real_mode_header->trampoline_start; @@ -1116,9 +1114,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, } } - /* mark "stuck" area as not stuck */ - *trampoline_status = 0; - if (x86_platform.legacy.warm_reset) { /* * Cleanup possible dangling ends... diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index 30b0d30d861a..6363761cc74c 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S @@ -19,7 +19,6 @@ GLOBAL(real_mode_header) .long pa_ro_end /* SMP trampoline */ .long pa_trampoline_start - .long pa_trampoline_status .long pa_trampoline_header #ifdef CONFIG_X86_64 .long pa_trampoline_pgd; diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S index 2dd866c9e21e..1868b158480d 100644 --- a/arch/x86/realmode/rm/trampoline_32.S +++ b/arch/x86/realmode/rm/trampoline_32.S @@ -41,9 +41,6 @@ ENTRY(trampoline_start) movl tr_start, %eax # where we need to go - movl $0xA5A5A5A5, trampoline_status - # write marker for master knows we're running - /* * GDT tables in non default location kernel can be beyond 16MB and * lgdt will not be able to load the address as in real mode default diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index 24bb7598774e..aee2b45d83b8 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S @@ -49,9 +49,6 @@ ENTRY(trampoline_start) mov %ax, %es mov %ax, %ss - movl $0xA5A5A5A5, trampoline_status - # write marker for master knows we're running - # Setup stack movl $rm_stack_end, %esp diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S index 7c706772ab59..8d8208dcca24 100644 --- a/arch/x86/realmode/rm/trampoline_common.S +++ b/arch/x86/realmode/rm/trampoline_common.S @@ -2,7 +2,3 @@ .section ".rodata","a" .balign 16 tr_idt: .fill 1, 6, 0 - - .bss - .balign 4 -GLOBAL(trampoline_status) .space 4 -- GitLab From 48febc03e6c239d96f46d8b38d91863769fc18c8 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Fri, 5 Jul 2019 10:53:18 -0700 Subject: [PATCH 0102/7155] x86/mpx: Remove selftests Makefile entry MPX is being removed from the kernel due to a lack of support in the toolchain going forward (gcc). This is the smallest possible patch to fix some issues that have been reported around running the MPX selftests. It it would also have been part of any removal series, it is offered first. Signed-off-by: Dave Hansen Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190705175318.784C233E@viggo.jf.intel.com --- tools/testing/selftests/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index fa07d526fe39..3bc5b744e644 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -11,7 +11,7 @@ CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c) CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie) TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ - check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \ + check_initial_reg_state sigreturn iopl ioperm \ protection_keys test_vdso test_vsyscall mov_ss_trap \ syscall_arg_fault TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \ -- GitLab From e28df79ae2dfebf18e08dc66c0948b7950e4368a Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Fri, 5 Jul 2019 10:53:20 -0700 Subject: [PATCH 0103/7155] x86/mpx: Remove selftests themselves MPX is being removed from the kernel due to a lack of support in the toolchain going forward (gcc). Remove the x86 selftests since they have been causing some issues because of their propensity to do some debug-aiding tracepoint mucking. Signed-off-by: Dave Hansen Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190705175320.6542F8AE@viggo.jf.intel.com --- tools/testing/selftests/x86/mpx-debug.h | 15 - tools/testing/selftests/x86/mpx-dig.c | 497 ------ tools/testing/selftests/x86/mpx-hw.h | 124 -- tools/testing/selftests/x86/mpx-mini-test.c | 1613 ------------------- tools/testing/selftests/x86/mpx-mm.h | 10 - 5 files changed, 2259 deletions(-) delete mode 100644 tools/testing/selftests/x86/mpx-debug.h delete mode 100644 tools/testing/selftests/x86/mpx-dig.c delete mode 100644 tools/testing/selftests/x86/mpx-hw.h delete mode 100644 tools/testing/selftests/x86/mpx-mini-test.c delete mode 100644 tools/testing/selftests/x86/mpx-mm.h diff --git a/tools/testing/selftests/x86/mpx-debug.h b/tools/testing/selftests/x86/mpx-debug.h deleted file mode 100644 index 7546eba7f17a..000000000000 --- a/tools/testing/selftests/x86/mpx-debug.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _MPX_DEBUG_H -#define _MPX_DEBUG_H - -#ifndef DEBUG_LEVEL -#define DEBUG_LEVEL 0 -#endif -#define dprintf_level(level, args...) do { if(level <= DEBUG_LEVEL) printf(args); } while(0) -#define dprintf1(args...) dprintf_level(1, args) -#define dprintf2(args...) dprintf_level(2, args) -#define dprintf3(args...) dprintf_level(3, args) -#define dprintf4(args...) dprintf_level(4, args) -#define dprintf5(args...) dprintf_level(5, args) - -#endif /* _MPX_DEBUG_H */ diff --git a/tools/testing/selftests/x86/mpx-dig.c b/tools/testing/selftests/x86/mpx-dig.c deleted file mode 100644 index 880fbf676968..000000000000 --- a/tools/testing/selftests/x86/mpx-dig.c +++ /dev/null @@ -1,497 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Written by Dave Hansen - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mpx-debug.h" -#include "mpx-mm.h" -#include "mpx-hw.h" - -unsigned long bounds_dir_global; - -#define mpx_dig_abort() __mpx_dig_abort(__FILE__, __func__, __LINE__) -static void inline __mpx_dig_abort(const char *file, const char *func, int line) -{ - fprintf(stderr, "MPX dig abort @ %s::%d in %s()\n", file, line, func); - printf("MPX dig abort @ %s::%d in %s()\n", file, line, func); - abort(); -} - -/* - * run like this (BDIR finds the probably bounds directory): - * - * BDIR="$(cat /proc/$pid/smaps | grep -B1 2097152 \ - * | head -1 | awk -F- '{print $1}')"; - * ./mpx-dig $pid 0x$BDIR - * - * NOTE: - * assumes that the only 2097152-kb VMA is the bounds dir - */ - -long nr_incore(void *ptr, unsigned long size_bytes) -{ - int i; - long ret = 0; - long vec_len = size_bytes / PAGE_SIZE; - unsigned char *vec = malloc(vec_len); - int incore_ret; - - if (!vec) - mpx_dig_abort(); - - incore_ret = mincore(ptr, size_bytes, vec); - if (incore_ret) { - printf("mincore ret: %d\n", incore_ret); - perror("mincore"); - mpx_dig_abort(); - } - for (i = 0; i < vec_len; i++) - ret += vec[i]; - free(vec); - return ret; -} - -int open_proc(int pid, char *file) -{ - static char buf[100]; - int fd; - - snprintf(&buf[0], sizeof(buf), "/proc/%d/%s", pid, file); - fd = open(&buf[0], O_RDONLY); - if (fd < 0) - perror(buf); - - return fd; -} - -struct vaddr_range { - unsigned long start; - unsigned long end; -}; -struct vaddr_range *ranges; -int nr_ranges_allocated; -int nr_ranges_populated; -int last_range = -1; - -int __pid_load_vaddrs(int pid) -{ - int ret = 0; - int proc_maps_fd = open_proc(pid, "maps"); - char linebuf[10000]; - unsigned long start; - unsigned long end; - char rest[1000]; - FILE *f = fdopen(proc_maps_fd, "r"); - - if (!f) - mpx_dig_abort(); - nr_ranges_populated = 0; - while (!feof(f)) { - char *readret = fgets(linebuf, sizeof(linebuf), f); - int parsed; - - if (readret == NULL) { - if (feof(f)) - break; - mpx_dig_abort(); - } - - parsed = sscanf(linebuf, "%lx-%lx%s", &start, &end, rest); - if (parsed != 3) - mpx_dig_abort(); - - dprintf4("result[%d]: %lx-%lx<->%s\n", parsed, start, end, rest); - if (nr_ranges_populated >= nr_ranges_allocated) { - ret = -E2BIG; - break; - } - ranges[nr_ranges_populated].start = start; - ranges[nr_ranges_populated].end = end; - nr_ranges_populated++; - } - last_range = -1; - fclose(f); - close(proc_maps_fd); - return ret; -} - -int pid_load_vaddrs(int pid) -{ - int ret; - - dprintf2("%s(%d)\n", __func__, pid); - if (!ranges) { - nr_ranges_allocated = 4; - ranges = malloc(nr_ranges_allocated * sizeof(ranges[0])); - dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__, pid, - nr_ranges_allocated, ranges); - assert(ranges != NULL); - } - do { - ret = __pid_load_vaddrs(pid); - if (!ret) - break; - if (ret == -E2BIG) { - dprintf2("%s(%d) need to realloc\n", __func__, pid); - nr_ranges_allocated *= 2; - ranges = realloc(ranges, - nr_ranges_allocated * sizeof(ranges[0])); - dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__, - pid, nr_ranges_allocated, ranges); - assert(ranges != NULL); - dprintf1("reallocating to hold %d ranges\n", nr_ranges_allocated); - } - } while (1); - - dprintf2("%s(%d) done\n", __func__, pid); - - return ret; -} - -static inline int vaddr_in_range(unsigned long vaddr, struct vaddr_range *r) -{ - if (vaddr < r->start) - return 0; - if (vaddr >= r->end) - return 0; - return 1; -} - -static inline int vaddr_mapped_by_range(unsigned long vaddr) -{ - int i; - - if (last_range > 0 && vaddr_in_range(vaddr, &ranges[last_range])) - return 1; - - for (i = 0; i < nr_ranges_populated; i++) { - struct vaddr_range *r = &ranges[i]; - - if (vaddr_in_range(vaddr, r)) - continue; - last_range = i; - return 1; - } - return 0; -} - -const int bt_entry_size_bytes = sizeof(unsigned long) * 4; - -void *read_bounds_table_into_buf(unsigned long table_vaddr) -{ -#ifdef MPX_DIG_STANDALONE - static char bt_buf[MPX_BOUNDS_TABLE_SIZE_BYTES]; - off_t seek_ret = lseek(fd, table_vaddr, SEEK_SET); - if (seek_ret != table_vaddr) - mpx_dig_abort(); - - int read_ret = read(fd, &bt_buf, sizeof(bt_buf)); - if (read_ret != sizeof(bt_buf)) - mpx_dig_abort(); - return &bt_buf; -#else - return (void *)table_vaddr; -#endif -} - -int dump_table(unsigned long table_vaddr, unsigned long base_controlled_vaddr, - unsigned long bde_vaddr) -{ - unsigned long offset_inside_bt; - int nr_entries = 0; - int do_abort = 0; - char *bt_buf; - - dprintf3("%s() base_controlled_vaddr: 0x%012lx bde_vaddr: 0x%012lx\n", - __func__, base_controlled_vaddr, bde_vaddr); - - bt_buf = read_bounds_table_into_buf(table_vaddr); - - dprintf4("%s() read done\n", __func__); - - for (offset_inside_bt = 0; - offset_inside_bt < MPX_BOUNDS_TABLE_SIZE_BYTES; - offset_inside_bt += bt_entry_size_bytes) { - unsigned long bt_entry_index; - unsigned long bt_entry_controls; - unsigned long this_bt_entry_for_vaddr; - unsigned long *bt_entry_buf; - int i; - - dprintf4("%s() offset_inside_bt: 0x%lx of 0x%llx\n", __func__, - offset_inside_bt, MPX_BOUNDS_TABLE_SIZE_BYTES); - bt_entry_buf = (void *)&bt_buf[offset_inside_bt]; - if (!bt_buf) { - printf("null bt_buf\n"); - mpx_dig_abort(); - } - if (!bt_entry_buf) { - printf("null bt_entry_buf\n"); - mpx_dig_abort(); - } - dprintf4("%s() reading *bt_entry_buf @ %p\n", __func__, - bt_entry_buf); - if (!bt_entry_buf[0] && - !bt_entry_buf[1] && - !bt_entry_buf[2] && - !bt_entry_buf[3]) - continue; - - nr_entries++; - - bt_entry_index = offset_inside_bt/bt_entry_size_bytes; - bt_entry_controls = sizeof(void *); - this_bt_entry_for_vaddr = - base_controlled_vaddr + bt_entry_index*bt_entry_controls; - /* - * We sign extend vaddr bits 48->63 which effectively - * creates a hole in the virtual address space. - * This calculation corrects for the hole. - */ - if (this_bt_entry_for_vaddr > 0x00007fffffffffffUL) - this_bt_entry_for_vaddr |= 0xffff800000000000; - - if (!vaddr_mapped_by_range(this_bt_entry_for_vaddr)) { - printf("bt_entry_buf: %p\n", bt_entry_buf); - printf("there is a bte for %lx but no mapping\n", - this_bt_entry_for_vaddr); - printf(" bde vaddr: %016lx\n", bde_vaddr); - printf("base_controlled_vaddr: %016lx\n", base_controlled_vaddr); - printf(" table_vaddr: %016lx\n", table_vaddr); - printf(" entry vaddr: %016lx @ offset %lx\n", - table_vaddr + offset_inside_bt, offset_inside_bt); - do_abort = 1; - mpx_dig_abort(); - } - if (DEBUG_LEVEL < 4) - continue; - - printf("table entry[%lx]: ", offset_inside_bt); - for (i = 0; i < bt_entry_size_bytes; i += sizeof(unsigned long)) - printf("0x%016lx ", bt_entry_buf[i]); - printf("\n"); - } - if (do_abort) - mpx_dig_abort(); - dprintf4("%s() done\n", __func__); - return nr_entries; -} - -int search_bd_buf(char *buf, int len_bytes, unsigned long bd_offset_bytes, - int *nr_populated_bdes) -{ - unsigned long i; - int total_entries = 0; - - dprintf3("%s(%p, %x, %lx, ...) buf end: %p\n", __func__, buf, - len_bytes, bd_offset_bytes, buf + len_bytes); - - for (i = 0; i < len_bytes; i += sizeof(unsigned long)) { - unsigned long bd_index = (bd_offset_bytes + i) / sizeof(unsigned long); - unsigned long *bounds_dir_entry_ptr = (unsigned long *)&buf[i]; - unsigned long bounds_dir_entry; - unsigned long bd_for_vaddr; - unsigned long bt_start; - unsigned long bt_tail; - int nr_entries; - - dprintf4("%s() loop i: %ld bounds_dir_entry_ptr: %p\n", __func__, i, - bounds_dir_entry_ptr); - - bounds_dir_entry = *bounds_dir_entry_ptr; - if (!bounds_dir_entry) { - dprintf4("no bounds dir at index 0x%lx / 0x%lx " - "start at offset:%lx %lx\n", bd_index, bd_index, - bd_offset_bytes, i); - continue; - } - dprintf3("found bounds_dir_entry: 0x%lx @ " - "index 0x%lx buf ptr: %p\n", bounds_dir_entry, i, - &buf[i]); - /* mask off the enable bit: */ - bounds_dir_entry &= ~0x1; - (*nr_populated_bdes)++; - dprintf4("nr_populated_bdes: %p\n", nr_populated_bdes); - dprintf4("*nr_populated_bdes: %d\n", *nr_populated_bdes); - - bt_start = bounds_dir_entry; - bt_tail = bounds_dir_entry + MPX_BOUNDS_TABLE_SIZE_BYTES - 1; - if (!vaddr_mapped_by_range(bt_start)) { - printf("bounds directory 0x%lx points to nowhere\n", - bounds_dir_entry); - mpx_dig_abort(); - } - if (!vaddr_mapped_by_range(bt_tail)) { - printf("bounds directory end 0x%lx points to nowhere\n", - bt_tail); - mpx_dig_abort(); - } - /* - * Each bounds directory entry controls 1MB of virtual address - * space. This variable is the virtual address in the process - * of the beginning of the area controlled by this bounds_dir. - */ - bd_for_vaddr = bd_index * (1UL<<20); - - nr_entries = dump_table(bounds_dir_entry, bd_for_vaddr, - bounds_dir_global+bd_offset_bytes+i); - total_entries += nr_entries; - dprintf5("dir entry[%4ld @ %p]: 0x%lx %6d entries " - "total this buf: %7d bd_for_vaddrs: 0x%lx -> 0x%lx\n", - bd_index, buf+i, - bounds_dir_entry, nr_entries, total_entries, - bd_for_vaddr, bd_for_vaddr + (1UL<<20)); - } - dprintf3("%s(%p, %x, %lx, ...) done\n", __func__, buf, len_bytes, - bd_offset_bytes); - return total_entries; -} - -int proc_pid_mem_fd = -1; - -void *fill_bounds_dir_buf_other(long byte_offset_inside_bounds_dir, - long buffer_size_bytes, void *buffer) -{ - unsigned long seekto = bounds_dir_global + byte_offset_inside_bounds_dir; - int read_ret; - off_t seek_ret = lseek(proc_pid_mem_fd, seekto, SEEK_SET); - - if (seek_ret != seekto) - mpx_dig_abort(); - - read_ret = read(proc_pid_mem_fd, buffer, buffer_size_bytes); - /* there shouldn't practically be short reads of /proc/$pid/mem */ - if (read_ret != buffer_size_bytes) - mpx_dig_abort(); - - return buffer; -} -void *fill_bounds_dir_buf_self(long byte_offset_inside_bounds_dir, - long buffer_size_bytes, void *buffer) - -{ - unsigned char vec[buffer_size_bytes / PAGE_SIZE]; - char *dig_bounds_dir_ptr = - (void *)(bounds_dir_global + byte_offset_inside_bounds_dir); - /* - * use mincore() to quickly find the areas of the bounds directory - * that have memory and thus will be worth scanning. - */ - int incore_ret; - - int incore = 0; - int i; - - dprintf4("%s() dig_bounds_dir_ptr: %p\n", __func__, dig_bounds_dir_ptr); - - incore_ret = mincore(dig_bounds_dir_ptr, buffer_size_bytes, &vec[0]); - if (incore_ret) { - printf("mincore ret: %d\n", incore_ret); - perror("mincore"); - mpx_dig_abort(); - } - for (i = 0; i < sizeof(vec); i++) - incore += vec[i]; - dprintf4("%s() total incore: %d\n", __func__, incore); - if (!incore) - return NULL; - dprintf3("%s() total incore: %d\n", __func__, incore); - return dig_bounds_dir_ptr; -} - -int inspect_pid(int pid) -{ - static int dig_nr; - long offset_inside_bounds_dir; - char bounds_dir_buf[sizeof(unsigned long) * (1UL << 15)]; - char *dig_bounds_dir_ptr; - int total_entries = 0; - int nr_populated_bdes = 0; - int inspect_self; - - if (getpid() == pid) { - dprintf4("inspecting self\n"); - inspect_self = 1; - } else { - dprintf4("inspecting pid %d\n", pid); - mpx_dig_abort(); - } - - for (offset_inside_bounds_dir = 0; - offset_inside_bounds_dir < MPX_BOUNDS_TABLE_SIZE_BYTES; - offset_inside_bounds_dir += sizeof(bounds_dir_buf)) { - static int bufs_skipped; - int this_entries; - - if (inspect_self) { - dig_bounds_dir_ptr = - fill_bounds_dir_buf_self(offset_inside_bounds_dir, - sizeof(bounds_dir_buf), - &bounds_dir_buf[0]); - } else { - dig_bounds_dir_ptr = - fill_bounds_dir_buf_other(offset_inside_bounds_dir, - sizeof(bounds_dir_buf), - &bounds_dir_buf[0]); - } - if (!dig_bounds_dir_ptr) { - bufs_skipped++; - continue; - } - this_entries = search_bd_buf(dig_bounds_dir_ptr, - sizeof(bounds_dir_buf), - offset_inside_bounds_dir, - &nr_populated_bdes); - total_entries += this_entries; - } - printf("mpx dig (%3d) complete, SUCCESS (%8d / %4d)\n", ++dig_nr, - total_entries, nr_populated_bdes); - return total_entries + nr_populated_bdes; -} - -#ifdef MPX_DIG_REMOTE -int main(int argc, char **argv) -{ - int err; - char *c; - unsigned long bounds_dir_entry; - int pid; - - printf("mpx-dig starting...\n"); - err = sscanf(argv[1], "%d", &pid); - printf("parsing: '%s', err: %d\n", argv[1], err); - if (err != 1) - mpx_dig_abort(); - - err = sscanf(argv[2], "%lx", &bounds_dir_global); - printf("parsing: '%s': %d\n", argv[2], err); - if (err != 1) - mpx_dig_abort(); - - proc_pid_mem_fd = open_proc(pid, "mem"); - if (proc_pid_mem_fd < 0) - mpx_dig_abort(); - - inspect_pid(pid); - return 0; -} -#endif - -long inspect_me(struct mpx_bounds_dir *bounds_dir) -{ - int pid = getpid(); - - pid_load_vaddrs(pid); - bounds_dir_global = (unsigned long)bounds_dir; - dprintf4("enter %s() bounds dir: %p\n", __func__, bounds_dir); - return inspect_pid(pid); -} diff --git a/tools/testing/selftests/x86/mpx-hw.h b/tools/testing/selftests/x86/mpx-hw.h deleted file mode 100644 index d1b61ab870f8..000000000000 --- a/tools/testing/selftests/x86/mpx-hw.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _MPX_HW_H -#define _MPX_HW_H - -#include - -/* Describe the MPX Hardware Layout in here */ - -#define NR_MPX_BOUNDS_REGISTERS 4 - -#ifdef __i386__ - -#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 16 /* 4 * 32-bits */ -#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 14) /* 16k */ -#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 4 -#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 22) /* 4MB */ - -#define MPX_BOUNDS_TABLE_BOTTOM_BIT 2 -#define MPX_BOUNDS_TABLE_TOP_BIT 11 -#define MPX_BOUNDS_DIR_BOTTOM_BIT 12 -#define MPX_BOUNDS_DIR_TOP_BIT 31 - -#else - -/* - * Linear Address of "pointer" (LAp) - * 0 -> 2: ignored - * 3 -> 19: index in to bounds table - * 20 -> 47: index in to bounds directory - * 48 -> 63: ignored - */ - -#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 32 -#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 22) /* 4MB */ -#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 8 -#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 31) /* 2GB */ - -#define MPX_BOUNDS_TABLE_BOTTOM_BIT 3 -#define MPX_BOUNDS_TABLE_TOP_BIT 19 -#define MPX_BOUNDS_DIR_BOTTOM_BIT 20 -#define MPX_BOUNDS_DIR_TOP_BIT 47 - -#endif - -#define MPX_BOUNDS_DIR_NR_ENTRIES \ - (MPX_BOUNDS_DIR_SIZE_BYTES/MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES) -#define MPX_BOUNDS_TABLE_NR_ENTRIES \ - (MPX_BOUNDS_TABLE_SIZE_BYTES/MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES) - -#define MPX_BOUNDS_TABLE_ENTRY_VALID_BIT 0x1 - -struct mpx_bd_entry { - union { - char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES]; - void *contents[0]; - }; -} __attribute__((packed)); - -struct mpx_bt_entry { - union { - char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES]; - unsigned long contents[0]; - }; -} __attribute__((packed)); - -struct mpx_bounds_dir { - struct mpx_bd_entry entries[MPX_BOUNDS_DIR_NR_ENTRIES]; -} __attribute__((packed)); - -struct mpx_bounds_table { - struct mpx_bt_entry entries[MPX_BOUNDS_TABLE_NR_ENTRIES]; -} __attribute__((packed)); - -static inline unsigned long GET_BITS(unsigned long val, int bottombit, int topbit) -{ - int total_nr_bits = topbit - bottombit; - unsigned long mask = (1UL << total_nr_bits)-1; - return (val >> bottombit) & mask; -} - -static inline unsigned long __vaddr_bounds_table_index(void *vaddr) -{ - return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_TABLE_BOTTOM_BIT, - MPX_BOUNDS_TABLE_TOP_BIT); -} - -static inline unsigned long __vaddr_bounds_directory_index(void *vaddr) -{ - return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_DIR_BOTTOM_BIT, - MPX_BOUNDS_DIR_TOP_BIT); -} - -static inline struct mpx_bd_entry *mpx_vaddr_to_bd_entry(void *vaddr, - struct mpx_bounds_dir *bounds_dir) -{ - unsigned long index = __vaddr_bounds_directory_index(vaddr); - return &bounds_dir->entries[index]; -} - -static inline int bd_entry_valid(struct mpx_bd_entry *bounds_dir_entry) -{ - unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents; - return (__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT); -} - -static inline struct mpx_bounds_table * -__bd_entry_to_bounds_table(struct mpx_bd_entry *bounds_dir_entry) -{ - unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents; - assert(__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT); - __bd_entry &= ~MPX_BOUNDS_TABLE_ENTRY_VALID_BIT; - return (struct mpx_bounds_table *)__bd_entry; -} - -static inline struct mpx_bt_entry * -mpx_vaddr_to_bt_entry(void *vaddr, struct mpx_bounds_dir *bounds_dir) -{ - struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(vaddr, bounds_dir); - struct mpx_bounds_table *bt = __bd_entry_to_bounds_table(bde); - unsigned long index = __vaddr_bounds_table_index(vaddr); - return &bt->entries[index]; -} - -#endif /* _MPX_HW_H */ diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c deleted file mode 100644 index 23ddd453f362..000000000000 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ /dev/null @@ -1,1613 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * mpx-mini-test.c: routines to test Intel MPX (Memory Protection eXtentions) - * - * Written by: - * "Ren, Qiaowei" - * "Wei, Gang" - * "Hansen, Dave" - */ - -/* - * 2014-12-05: Dave Hansen: fixed all of the compiler warnings, and made sure - * it works on 32-bit. - */ - -int inspect_every_this_many_mallocs = 100; -int zap_all_every_this_many_mallocs = 1000; - -#define _GNU_SOURCE -#define _LARGEFILE64_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpx-hw.h" -#include "mpx-debug.h" -#include "mpx-mm.h" - -#ifndef __always_inline -#define __always_inline inline __attribute__((always_inline) -#endif - -#ifndef TEST_DURATION_SECS -#define TEST_DURATION_SECS 3 -#endif - -void write_int_to(char *prefix, char *file, int int_to_write) -{ - char buf[100]; - int fd = open(file, O_RDWR); - int len; - int ret; - - assert(fd >= 0); - len = snprintf(buf, sizeof(buf), "%s%d", prefix, int_to_write); - assert(len >= 0); - assert(len < sizeof(buf)); - ret = write(fd, buf, len); - assert(ret == len); - ret = close(fd); - assert(!ret); -} - -void write_pid_to(char *prefix, char *file) -{ - write_int_to(prefix, file, getpid()); -} - -void trace_me(void) -{ -/* tracing events dir */ -#define TED "/sys/kernel/debug/tracing/events/" -/* - write_pid_to("common_pid=", TED "signal/filter"); - write_pid_to("common_pid=", TED "exceptions/filter"); - write_int_to("", TED "signal/enable", 1); - write_int_to("", TED "exceptions/enable", 1); -*/ - write_pid_to("", "/sys/kernel/debug/tracing/set_ftrace_pid"); - write_int_to("", "/sys/kernel/debug/tracing/trace", 0); -} - -#define test_failed() __test_failed(__FILE__, __LINE__) -static void __test_failed(char *f, int l) -{ - fprintf(stderr, "abort @ %s::%d\n", f, l); - abort(); -} - -/* Error Printf */ -#define eprintf(args...) fprintf(stderr, args) - -#ifdef __i386__ - -/* i386 directory size is 4MB */ -#define REG_IP_IDX REG_EIP -#define REX_PREFIX - -#define XSAVE_OFFSET_IN_FPMEM sizeof(struct _libc_fpstate) - -/* - * __cpuid() is from the Linux Kernel: - */ -static inline void __cpuid(unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) -{ - /* ecx is often an input as well as an output. */ - asm volatile( - "push %%ebx;" - "cpuid;" - "mov %%ebx, %1;" - "pop %%ebx" - : "=a" (*eax), - "=g" (*ebx), - "=c" (*ecx), - "=d" (*edx) - : "0" (*eax), "2" (*ecx)); -} - -#else /* __i386__ */ - -#define REG_IP_IDX REG_RIP -#define REX_PREFIX "0x48, " - -#define XSAVE_OFFSET_IN_FPMEM 0 - -/* - * __cpuid() is from the Linux Kernel: - */ -static inline void __cpuid(unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) -{ - /* ecx is often an input as well as an output. */ - asm volatile( - "cpuid;" - : "=a" (*eax), - "=b" (*ebx), - "=c" (*ecx), - "=d" (*edx) - : "0" (*eax), "2" (*ecx)); -} - -#endif /* !__i386__ */ - -struct xsave_hdr_struct { - uint64_t xstate_bv; - uint64_t reserved1[2]; - uint64_t reserved2[5]; -} __attribute__((packed)); - -struct bndregs_struct { - uint64_t bndregs[8]; -} __attribute__((packed)); - -struct bndcsr_struct { - uint64_t cfg_reg_u; - uint64_t status_reg; -} __attribute__((packed)); - -struct xsave_struct { - uint8_t fpu_sse[512]; - struct xsave_hdr_struct xsave_hdr; - uint8_t ymm[256]; - uint8_t lwp[128]; - struct bndregs_struct bndregs; - struct bndcsr_struct bndcsr; -} __attribute__((packed)); - -uint8_t __attribute__((__aligned__(64))) buffer[4096]; -struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer; - -uint8_t __attribute__((__aligned__(64))) test_buffer[4096]; -struct xsave_struct *xsave_test_buf = (struct xsave_struct *)test_buffer; - -uint64_t num_bnd_chk; - -static __always_inline void xrstor_state(struct xsave_struct *fx, uint64_t mask) -{ - uint32_t lmask = mask; - uint32_t hmask = mask >> 32; - - asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" - : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) - : "memory"); -} - -static __always_inline void xsave_state_1(void *_fx, uint64_t mask) -{ - uint32_t lmask = mask; - uint32_t hmask = mask >> 32; - unsigned char *fx = _fx; - - asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t" - : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) - : "memory"); -} - -static inline uint64_t xgetbv(uint32_t index) -{ - uint32_t eax, edx; - - asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */ - : "=a" (eax), "=d" (edx) - : "c" (index)); - return eax + ((uint64_t)edx << 32); -} - -static uint64_t read_mpx_status_sig(ucontext_t *uctxt) -{ - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, - (uint8_t *)uctxt->uc_mcontext.fpregs + XSAVE_OFFSET_IN_FPMEM, - sizeof(struct xsave_struct)); - - return xsave_buf->bndcsr.status_reg; -} - -#include - -static uint8_t *get_next_inst_ip(uint8_t *addr) -{ - uint8_t *ip = addr; - uint8_t sib; - uint8_t rm; - uint8_t mod; - uint8_t base; - uint8_t modrm; - - /* determine the prefix. */ - switch(*ip) { - case 0xf2: - case 0xf3: - case 0x66: - ip++; - break; - } - - /* look for rex prefix */ - if ((*ip & 0x40) == 0x40) - ip++; - - /* Make sure we have a MPX instruction. */ - if (*ip++ != 0x0f) - return addr; - - /* Skip the op code byte. */ - ip++; - - /* Get the modrm byte. */ - modrm = *ip++; - - /* Break it down into parts. */ - rm = modrm & 7; - mod = (modrm >> 6); - - /* Init the parts of the address mode. */ - base = 8; - - /* Is it a mem mode? */ - if (mod != 3) { - /* look for scaled indexed addressing */ - if (rm == 4) { - /* SIB addressing */ - sib = *ip++; - base = sib & 7; - switch (mod) { - case 0: - if (base == 5) - ip += 4; - break; - - case 1: - ip++; - break; - - case 2: - ip += 4; - break; - } - - } else { - /* MODRM addressing */ - switch (mod) { - case 0: - /* DISP32 addressing, no base */ - if (rm == 5) - ip += 4; - break; - - case 1: - ip++; - break; - - case 2: - ip += 4; - break; - } - } - } - return ip; -} - -#ifdef si_lower -static inline void *__si_bounds_lower(siginfo_t *si) -{ - return si->si_lower; -} - -static inline void *__si_bounds_upper(siginfo_t *si) -{ - return si->si_upper; -} -#else - -/* - * This deals with old version of _sigfault in some distros: - * - -old _sigfault: - struct { - void *si_addr; - } _sigfault; - -new _sigfault: - struct { - void __user *_addr; - int _trapno; - short _addr_lsb; - union { - struct { - void __user *_lower; - void __user *_upper; - } _addr_bnd; - __u32 _pkey; - }; - } _sigfault; - * - */ - -static inline void **__si_bounds_hack(siginfo_t *si) -{ - void *sigfault = &si->_sifields._sigfault; - void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault); - int *trapno = (int*)end_sigfault; - /* skip _trapno and _addr_lsb */ - void **__si_lower = (void**)(trapno + 2); - - return __si_lower; -} - -static inline void *__si_bounds_lower(siginfo_t *si) -{ - return *__si_bounds_hack(si); -} - -static inline void *__si_bounds_upper(siginfo_t *si) -{ - return *(__si_bounds_hack(si) + 1); -} -#endif - -static int br_count; -static int expected_bnd_index = -1; -uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */ -unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS]; - -/* Failed address bound checks: */ -#ifndef SEGV_BNDERR -# define SEGV_BNDERR 3 -#endif - -/* - * The kernel is supposed to provide some information about the bounds - * exception in the siginfo. It should match what we have in the bounds - * registers that we are checking against. Just check against the shadow copy - * since it is easily available, and we also check that *it* matches the real - * registers. - */ -void check_siginfo_vs_shadow(siginfo_t* si) -{ - int siginfo_ok = 1; - void *shadow_lower = (void *)(unsigned long)shadow_plb[expected_bnd_index][0]; - void *shadow_upper = (void *)(unsigned long)shadow_plb[expected_bnd_index][1]; - - if ((expected_bnd_index < 0) || - (expected_bnd_index >= NR_MPX_BOUNDS_REGISTERS)) { - fprintf(stderr, "ERROR: invalid expected_bnd_index: %d\n", - expected_bnd_index); - exit(6); - } - if (__si_bounds_lower(si) != shadow_lower) - siginfo_ok = 0; - if (__si_bounds_upper(si) != shadow_upper) - siginfo_ok = 0; - - if (!siginfo_ok) { - fprintf(stderr, "ERROR: siginfo bounds do not match " - "shadow bounds for register %d\n", expected_bnd_index); - exit(7); - } -} - -void handler(int signum, siginfo_t *si, void *vucontext) -{ - int i; - ucontext_t *uctxt = vucontext; - int trapno; - unsigned long ip; - - dprintf1("entered signal handler\n"); - - trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO]; - ip = uctxt->uc_mcontext.gregs[REG_IP_IDX]; - - if (trapno == 5) { - typeof(si->si_addr) *si_addr_ptr = &si->si_addr; - uint64_t status = read_mpx_status_sig(uctxt); - uint64_t br_reason = status & 0x3; - - br_count++; - dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); - - dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", - status, ip, br_reason); - dprintf2("si_signo: %d\n", si->si_signo); - dprintf2(" signum: %d\n", signum); - dprintf2("info->si_code == SEGV_BNDERR: %d\n", - (si->si_code == SEGV_BNDERR)); - dprintf2("info->si_code: %d\n", si->si_code); - dprintf2("info->si_lower: %p\n", __si_bounds_lower(si)); - dprintf2("info->si_upper: %p\n", __si_bounds_upper(si)); - - for (i = 0; i < 8; i++) - dprintf3("[%d]: %p\n", i, si_addr_ptr[i]); - switch (br_reason) { - case 0: /* traditional BR */ - fprintf(stderr, - "Undefined status with bound exception:%jx\n", - status); - exit(5); - case 1: /* #BR MPX bounds exception */ - /* these are normal and we expect to see them */ - - check_siginfo_vs_shadow(si); - - dprintf1("bounds exception (normal): status 0x%jx at %p si_addr: %p\n", - status, (void *)ip, si->si_addr); - num_bnd_chk++; - uctxt->uc_mcontext.gregs[REG_IP_IDX] = - (greg_t)get_next_inst_ip((uint8_t *)ip); - break; - case 2: - fprintf(stderr, "#BR status == 2, missing bounds table," - "kernel should have handled!!\n"); - exit(4); - break; - default: - fprintf(stderr, "bound check error: status 0x%jx at %p\n", - status, (void *)ip); - num_bnd_chk++; - uctxt->uc_mcontext.gregs[REG_IP_IDX] = - (greg_t)get_next_inst_ip((uint8_t *)ip); - fprintf(stderr, "bound check error: si_addr %p\n", si->si_addr); - exit(3); - } - } else if (trapno == 14) { - eprintf("ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n", - trapno, ip); - eprintf("si_addr %p\n", si->si_addr); - eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]); - test_failed(); - } else { - eprintf("unexpected trap %d! at 0x%lx\n", trapno, ip); - eprintf("si_addr %p\n", si->si_addr); - eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]); - test_failed(); - } -} - -static inline void cpuid_count(unsigned int op, int count, - unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) -{ - *eax = op; - *ecx = count; - __cpuid(eax, ebx, ecx, edx); -} - -#define XSTATE_CPUID 0x0000000d - -/* - * List of XSAVE features Linux knows about: - */ -enum xfeature_bit { - XSTATE_BIT_FP, - XSTATE_BIT_SSE, - XSTATE_BIT_YMM, - XSTATE_BIT_BNDREGS, - XSTATE_BIT_BNDCSR, - XSTATE_BIT_OPMASK, - XSTATE_BIT_ZMM_Hi256, - XSTATE_BIT_Hi16_ZMM, - - XFEATURES_NR_MAX, -}; - -#define XSTATE_FP (1 << XSTATE_BIT_FP) -#define XSTATE_SSE (1 << XSTATE_BIT_SSE) -#define XSTATE_YMM (1 << XSTATE_BIT_YMM) -#define XSTATE_BNDREGS (1 << XSTATE_BIT_BNDREGS) -#define XSTATE_BNDCSR (1 << XSTATE_BIT_BNDCSR) -#define XSTATE_OPMASK (1 << XSTATE_BIT_OPMASK) -#define XSTATE_ZMM_Hi256 (1 << XSTATE_BIT_ZMM_Hi256) -#define XSTATE_Hi16_ZMM (1 << XSTATE_BIT_Hi16_ZMM) - -#define MPX_XSTATES (XSTATE_BNDREGS | XSTATE_BNDCSR) /* 0x18 */ - -bool one_bit(unsigned int x, int bit) -{ - return !!(x & (1<xsave_hdr.xstate_bv = 0x10; - xsave_buf->bndcsr.cfg_reg_u = (unsigned long)l1base | 1; - xsave_buf->bndcsr.status_reg = 0; - - dprintf2("bf xrstor\n"); - dprintf2("xsave cndcsr: status %jx, configu %jx\n", - xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u); - xrstor_state(xsave_buf, 0x18); - dprintf2("after xrstor\n"); - - xsave_state_1(xsave_buf, 0x18); - - dprintf1("xsave bndcsr: status %jx, configu %jx\n", - xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u); -} - -#include - -struct mpx_bounds_dir *bounds_dir_ptr; - -unsigned long __bd_incore(const char *func, int line) -{ - unsigned long ret = nr_incore(bounds_dir_ptr, MPX_BOUNDS_DIR_SIZE_BYTES); - return ret; -} -#define bd_incore() __bd_incore(__func__, __LINE__) - -void check_clear(void *ptr, unsigned long sz) -{ - unsigned long *i; - - for (i = ptr; (void *)i < ptr + sz; i++) { - if (*i) { - dprintf1("%p is NOT clear at %p\n", ptr, i); - assert(0); - } - } - dprintf1("%p is clear for %lx\n", ptr, sz); -} - -void check_clear_bd(void) -{ - check_clear(bounds_dir_ptr, 2UL << 30); -} - -#define USE_MALLOC_FOR_BOUNDS_DIR 1 -bool process_specific_init(void) -{ - unsigned long size; - unsigned long *dir; - /* Guarantee we have the space to align it, add padding: */ - unsigned long pad = getpagesize(); - - size = 2UL << 30; /* 2GB */ - if (sizeof(unsigned long) == 4) - size = 4UL << 20; /* 4MB */ - dprintf1("trying to allocate %ld MB bounds directory\n", (size >> 20)); - - if (USE_MALLOC_FOR_BOUNDS_DIR) { - unsigned long _dir; - - dir = malloc(size + pad); - assert(dir); - _dir = (unsigned long)dir; - _dir += 0xfffUL; - _dir &= ~0xfffUL; - dir = (void *)_dir; - } else { - /* - * This makes debugging easier because the address - * calculations are simpler: - */ - dir = mmap((void *)0x200000000000, size + pad, - PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if (dir == (void *)-1) { - perror("unable to allocate bounds directory"); - abort(); - } - check_clear(dir, size); - } - bounds_dir_ptr = (void *)dir; - madvise(bounds_dir_ptr, size, MADV_NOHUGEPAGE); - bd_incore(); - dprintf1("bounds directory: 0x%p -> 0x%p\n", bounds_dir_ptr, - (char *)bounds_dir_ptr + size); - check_clear(dir, size); - enable_mpx(dir); - check_clear(dir, size); - if (prctl(43, 0, 0, 0, 0)) { - printf("no MPX support\n"); - abort(); - return false; - } - return true; -} - -bool process_specific_finish(void) -{ - if (prctl(44)) { - printf("no MPX support\n"); - return false; - } - return true; -} - -void setup_handler() -{ - int r, rs; - struct sigaction newact; - struct sigaction oldact; - - /* #BR is mapped to sigsegv */ - int signum = SIGSEGV; - - newact.sa_handler = 0; /* void(*)(int)*/ - newact.sa_sigaction = handler; /* void (*)(int, siginfo_t*, void *) */ - - /*sigset_t - signals to block while in the handler */ - /* get the old signal mask. */ - rs = sigprocmask(SIG_SETMASK, 0, &newact.sa_mask); - assert(rs == 0); - - /* call sa_sigaction, not sa_handler*/ - newact.sa_flags = SA_SIGINFO; - - newact.sa_restorer = 0; /* void(*)(), obsolete */ - r = sigaction(signum, &newact, &oldact); - assert(r == 0); -} - -void mpx_prepare(void) -{ - dprintf2("%s()\n", __func__); - setup_handler(); - process_specific_init(); -} - -void mpx_cleanup(void) -{ - printf("%s(): %jd BRs. bye...\n", __func__, num_bnd_chk); - process_specific_finish(); -} - -/*-------------- the following is test case ---------------*/ -#include -#include -#include -#include -#include - -uint64_t num_lower_brs; -uint64_t num_upper_brs; - -#define MPX_CONFIG_OFFSET 1024 -#define MPX_BOUNDS_OFFSET 960 -#define MPX_HEADER_OFFSET 512 -#define MAX_ADDR_TESTED (1<<28) -#define TEST_ROUNDS 100 - -/* - 0F 1A /r BNDLDX-Load - 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation - 66 0F 1A /r BNDMOV bnd1, bnd2/m128 - 66 0F 1B /r BNDMOV bnd1/m128, bnd2 - F2 0F 1A /r BNDCU bnd, r/m64 - F2 0F 1B /r BNDCN bnd, r/m64 - F3 0F 1A /r BNDCL bnd, r/m64 - F3 0F 1B /r BNDMK bnd, m64 -*/ - -static __always_inline void xsave_state(void *_fx, uint64_t mask) -{ - uint32_t lmask = mask; - uint32_t hmask = mask >> 32; - unsigned char *fx = _fx; - - asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t" - : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) - : "memory"); -} - -static __always_inline void mpx_clear_bnd0(void) -{ - long size = 0; - void *ptr = NULL; - /* F3 0F 1B /r BNDMK bnd, m64 */ - /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */ - asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t" - : : "c" (ptr), "d" (size-1) - : "memory"); -} - -static __always_inline void mpx_make_bound_helper(unsigned long ptr, - unsigned long size) -{ - /* F3 0F 1B /r BNDMK bnd, m64 */ - /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */ - asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t" - : : "c" (ptr), "d" (size-1) - : "memory"); -} - -static __always_inline void mpx_check_lowerbound_helper(unsigned long ptr) -{ - /* F3 0F 1A /r NDCL bnd, r/m64 */ - /* f3 0f 1a 01 bndcl (%rcx),%bnd0 */ - asm volatile(".byte 0xf3,0x0f,0x1a,0x01\n\t" - : : "c" (ptr) - : "memory"); -} - -static __always_inline void mpx_check_upperbound_helper(unsigned long ptr) -{ - /* F2 0F 1A /r BNDCU bnd, r/m64 */ - /* f2 0f 1a 01 bndcu (%rcx),%bnd0 */ - asm volatile(".byte 0xf2,0x0f,0x1a,0x01\n\t" - : : "c" (ptr) - : "memory"); -} - -static __always_inline void mpx_movbndreg_helper() -{ - /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */ - /* 66 0f 1b c2 bndmov %bnd0,%bnd2 */ - - asm volatile(".byte 0x66,0x0f,0x1b,0xc2\n\t"); -} - -static __always_inline void mpx_movbnd2mem_helper(uint8_t *mem) -{ - /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */ - /* 66 0f 1b 01 bndmov %bnd0,(%rcx) */ - asm volatile(".byte 0x66,0x0f,0x1b,0x01\n\t" - : : "c" (mem) - : "memory"); -} - -static __always_inline void mpx_movbnd_from_mem_helper(uint8_t *mem) -{ - /* 66 0F 1A /r BNDMOV bnd1, bnd2/m128 */ - /* 66 0f 1a 01 bndmov (%rcx),%bnd0 */ - asm volatile(".byte 0x66,0x0f,0x1a,0x01\n\t" - : : "c" (mem) - : "memory"); -} - -static __always_inline void mpx_store_dsc_helper(unsigned long ptr_addr, - unsigned long ptr_val) -{ - /* 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation */ - /* 0f 1b 04 11 bndstx %bnd0,(%rcx,%rdx,1) */ - asm volatile(".byte 0x0f,0x1b,0x04,0x11\n\t" - : : "c" (ptr_addr), "d" (ptr_val) - : "memory"); -} - -static __always_inline void mpx_load_dsc_helper(unsigned long ptr_addr, - unsigned long ptr_val) -{ - /* 0F 1A /r BNDLDX-Load */ - /*/ 0f 1a 04 11 bndldx (%rcx,%rdx,1),%bnd0 */ - asm volatile(".byte 0x0f,0x1a,0x04,0x11\n\t" - : : "c" (ptr_addr), "d" (ptr_val) - : "memory"); -} - -void __print_context(void *__print_xsave_buffer, int line) -{ - uint64_t *bounds = (uint64_t *)(__print_xsave_buffer + MPX_BOUNDS_OFFSET); - uint64_t *cfg = (uint64_t *)(__print_xsave_buffer + MPX_CONFIG_OFFSET); - - int i; - eprintf("%s()::%d\n", "print_context", line); - for (i = 0; i < 4; i++) { - eprintf("bound[%d]: 0x%016lx 0x%016lx(0x%016lx)\n", i, - (unsigned long)bounds[i*2], - ~(unsigned long)bounds[i*2+1], - (unsigned long)bounds[i*2+1]); - } - - eprintf("cpcfg: %jx cpstatus: %jx\n", cfg[0], cfg[1]); -} -#define print_context(x) __print_context(x, __LINE__) -#ifdef DEBUG -#define dprint_context(x) print_context(x) -#else -#define dprint_context(x) do{}while(0) -#endif - -void init() -{ - int i; - - srand((unsigned int)time(NULL)); - - for (i = 0; i < 4; i++) { - shadow_plb[i][0] = 0; - shadow_plb[i][1] = ~(unsigned long)0; - } -} - -long int __mpx_random(int line) -{ -#ifdef NOT_SO_RANDOM - static long fake = 722122311; - fake += 563792075; - return fakse; -#else - return random(); -#endif -} -#define mpx_random() __mpx_random(__LINE__) - -uint8_t *get_random_addr() -{ - uint8_t*addr = (uint8_t *)(unsigned long)(rand() % MAX_ADDR_TESTED); - return (addr - (unsigned long)addr % sizeof(uint8_t *)); -} - -static inline bool compare_context(void *__xsave_buffer) -{ - uint64_t *bounds = (uint64_t *)(__xsave_buffer + MPX_BOUNDS_OFFSET); - - int i; - for (i = 0; i < 4; i++) { - dprintf3("shadow[%d]{%016lx/%016lx}\nbounds[%d]{%016lx/%016lx}\n", - i, (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1], - i, (unsigned long)bounds[i*2], ~(unsigned long)bounds[i*2+1]); - if ((shadow_plb[i][0] != bounds[i*2]) || - (shadow_plb[i][1] != ~(unsigned long)bounds[i*2+1])) { - eprintf("ERROR comparing shadow to real bound register %d\n", i); - eprintf("shadow{0x%016lx/0x%016lx}\nbounds{0x%016lx/0x%016lx}\n", - (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1], - (unsigned long)bounds[i*2], (unsigned long)bounds[i*2+1]); - return false; - } - } - - return true; -} - -void mkbnd_shadow(uint8_t *ptr, int index, long offset) -{ - uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]); - uint64_t *upper = (uint64_t *)&(shadow_plb[index][1]); - *lower = (unsigned long)ptr; - *upper = (unsigned long)ptr + offset - 1; -} - -void check_lowerbound_shadow(uint8_t *ptr, int index) -{ - uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]); - if (*lower > (uint64_t)(unsigned long)ptr) - num_lower_brs++; - else - dprintf1("LowerBoundChk passed:%p\n", ptr); -} - -void check_upperbound_shadow(uint8_t *ptr, int index) -{ - uint64_t upper = *(uint64_t *)&(shadow_plb[index][1]); - if (upper < (uint64_t)(unsigned long)ptr) - num_upper_brs++; - else - dprintf1("UpperBoundChk passed:%p\n", ptr); -} - -__always_inline void movbndreg_shadow(int src, int dest) -{ - shadow_plb[dest][0] = shadow_plb[src][0]; - shadow_plb[dest][1] = shadow_plb[src][1]; -} - -__always_inline void movbnd2mem_shadow(int src, unsigned long *dest) -{ - unsigned long *lower = (unsigned long *)&(shadow_plb[src][0]); - unsigned long *upper = (unsigned long *)&(shadow_plb[src][1]); - *dest = *lower; - *(dest+1) = *upper; -} - -__always_inline void movbnd_from_mem_shadow(unsigned long *src, int dest) -{ - unsigned long *lower = (unsigned long *)&(shadow_plb[dest][0]); - unsigned long *upper = (unsigned long *)&(shadow_plb[dest][1]); - *lower = *src; - *upper = *(src+1); -} - -__always_inline void stdsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val) -{ - shadow_map[0] = (unsigned long)shadow_plb[index][0]; - shadow_map[1] = (unsigned long)shadow_plb[index][1]; - shadow_map[2] = (unsigned long)ptr_val; - dprintf3("%s(%d, %p, %p) set shadow map[2]: %p\n", __func__, - index, ptr, ptr_val, ptr_val); - /*ptr ignored */ -} - -void lddsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val) -{ - uint64_t lower = shadow_map[0]; - uint64_t upper = shadow_map[1]; - uint8_t *value = (uint8_t *)shadow_map[2]; - - if (value != ptr_val) { - dprintf2("%s(%d, %p, %p) init shadow bounds[%d] " - "because %p != %p\n", __func__, index, ptr, - ptr_val, index, value, ptr_val); - shadow_plb[index][0] = 0; - shadow_plb[index][1] = ~(unsigned long)0; - } else { - shadow_plb[index][0] = lower; - shadow_plb[index][1] = upper; - } - /* ptr ignored */ -} - -static __always_inline void mpx_test_helper0(uint8_t *buf, uint8_t *ptr) -{ - mpx_make_bound_helper((unsigned long)ptr, 0x1800); -} - -static __always_inline void mpx_test_helper0_shadow(uint8_t *buf, uint8_t *ptr) -{ - mkbnd_shadow(ptr, 0, 0x1800); -} - -static __always_inline void mpx_test_helper1(uint8_t *buf, uint8_t *ptr) -{ - /* these are hard-coded to check bnd0 */ - expected_bnd_index = 0; - mpx_check_lowerbound_helper((unsigned long)(ptr-1)); - mpx_check_upperbound_helper((unsigned long)(ptr+0x1800)); - /* reset this since we do not expect any more bounds exceptions */ - expected_bnd_index = -1; -} - -static __always_inline void mpx_test_helper1_shadow(uint8_t *buf, uint8_t *ptr) -{ - check_lowerbound_shadow(ptr-1, 0); - check_upperbound_shadow(ptr+0x1800, 0); -} - -static __always_inline void mpx_test_helper2(uint8_t *buf, uint8_t *ptr) -{ - mpx_make_bound_helper((unsigned long)ptr, 0x1800); - mpx_movbndreg_helper(); - mpx_movbnd2mem_helper(buf); - mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800); -} - -static __always_inline void mpx_test_helper2_shadow(uint8_t *buf, uint8_t *ptr) -{ - mkbnd_shadow(ptr, 0, 0x1800); - movbndreg_shadow(0, 2); - movbnd2mem_shadow(0, (unsigned long *)buf); - mkbnd_shadow(ptr+0x12, 0, 0x1800); -} - -static __always_inline void mpx_test_helper3(uint8_t *buf, uint8_t *ptr) -{ - mpx_movbnd_from_mem_helper(buf); -} - -static __always_inline void mpx_test_helper3_shadow(uint8_t *buf, uint8_t *ptr) -{ - movbnd_from_mem_shadow((unsigned long *)buf, 0); -} - -static __always_inline void mpx_test_helper4(uint8_t *buf, uint8_t *ptr) -{ - mpx_store_dsc_helper((unsigned long)buf, (unsigned long)ptr); - mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800); -} - -static __always_inline void mpx_test_helper4_shadow(uint8_t *buf, uint8_t *ptr) -{ - stdsc_shadow(0, buf, ptr); - mkbnd_shadow(ptr+0x12, 0, 0x1800); -} - -static __always_inline void mpx_test_helper5(uint8_t *buf, uint8_t *ptr) -{ - mpx_load_dsc_helper((unsigned long)buf, (unsigned long)ptr); -} - -static __always_inline void mpx_test_helper5_shadow(uint8_t *buf, uint8_t *ptr) -{ - lddsc_shadow(0, buf, ptr); -} - -#define NR_MPX_TEST_FUNCTIONS 6 - -/* - * For compatibility reasons, MPX will clear the bounds registers - * when you make function calls (among other things). We have to - * preserve the registers in between calls to the "helpers" since - * they build on each other. - * - * Be very careful not to make any function calls inside the - * helpers, or anywhere else beween the xrstor and xsave. - */ -#define run_helper(helper_nr, buf, buf_shadow, ptr) do { \ - xrstor_state(xsave_test_buf, flags); \ - mpx_test_helper##helper_nr(buf, ptr); \ - xsave_state(xsave_test_buf, flags); \ - mpx_test_helper##helper_nr##_shadow(buf_shadow, ptr); \ -} while (0) - -static void run_helpers(int nr, uint8_t *buf, uint8_t *buf_shadow, uint8_t *ptr) -{ - uint64_t flags = 0x18; - - dprint_context(xsave_test_buf); - switch (nr) { - case 0: - run_helper(0, buf, buf_shadow, ptr); - break; - case 1: - run_helper(1, buf, buf_shadow, ptr); - break; - case 2: - run_helper(2, buf, buf_shadow, ptr); - break; - case 3: - run_helper(3, buf, buf_shadow, ptr); - break; - case 4: - run_helper(4, buf, buf_shadow, ptr); - break; - case 5: - run_helper(5, buf, buf_shadow, ptr); - break; - default: - test_failed(); - break; - } - dprint_context(xsave_test_buf); -} - -unsigned long buf_shadow[1024]; /* used to check load / store descriptors */ -extern long inspect_me(struct mpx_bounds_dir *bounds_dir); - -long cover_buf_with_bt_entries(void *buf, long buf_len) -{ - int i; - long nr_to_fill; - int ratio = 1000; - unsigned long buf_len_in_ptrs; - - /* Fill about 1/100 of the space with bt entries */ - nr_to_fill = buf_len / (sizeof(unsigned long) * ratio); - - if (!nr_to_fill) - dprintf3("%s() nr_to_fill: %ld\n", __func__, nr_to_fill); - - /* Align the buffer to pointer size */ - while (((unsigned long)buf) % sizeof(void *)) { - buf++; - buf_len--; - } - /* We are storing pointers, so make */ - buf_len_in_ptrs = buf_len / sizeof(void *); - - for (i = 0; i < nr_to_fill; i++) { - long index = (mpx_random() % buf_len_in_ptrs); - void *ptr = buf + index * sizeof(unsigned long); - unsigned long ptr_addr = (unsigned long)ptr; - - /* ptr and size can be anything */ - mpx_make_bound_helper((unsigned long)ptr, 8); - - /* - * take bnd0 and put it in to bounds tables "buf + index" is an - * address inside the buffer where we are pretending that we - * are going to put a pointer We do not, though because we will - * never load entries from the table, so it doesn't matter. - */ - mpx_store_dsc_helper(ptr_addr, (unsigned long)ptr); - dprintf4("storing bound table entry for %lx (buf start @ %p)\n", - ptr_addr, buf); - } - return nr_to_fill; -} - -unsigned long align_down(unsigned long alignme, unsigned long align_to) -{ - return alignme & ~(align_to-1); -} - -unsigned long align_up(unsigned long alignme, unsigned long align_to) -{ - return (alignme + align_to - 1) & ~(align_to-1); -} - -/* - * Using 1MB alignment guarantees that each no allocation - * will overlap with another's bounds tables. - * - * We have to cook our own allocator here. malloc() can - * mix other allocation with ours which means that even - * if we free all of our allocations, there might still - * be bounds tables for the *areas* since there is other - * valid memory there. - * - * We also can't use malloc() because a free() of an area - * might not free it back to the kernel. We want it - * completely unmapped an malloc() does not guarantee - * that. - */ -#ifdef __i386__ -long alignment = 4096; -long sz_alignment = 4096; -#else -long alignment = 1 * MB; -long sz_alignment = 1 * MB; -#endif -void *mpx_mini_alloc(unsigned long sz) -{ - unsigned long long tries = 0; - static void *last; - void *ptr; - void *try_at; - - sz = align_up(sz, sz_alignment); - - try_at = last + alignment; - while (1) { - ptr = mmap(try_at, sz, PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if (ptr == (void *)-1) - return NULL; - if (ptr == try_at) - break; - - munmap(ptr, sz); - try_at += alignment; -#ifdef __i386__ - /* - * This isn't quite correct for 32-bit binaries - * on 64-bit kernels since they can use the - * entire 32-bit address space, but it's close - * enough. - */ - if (try_at > (void *)0xC0000000) -#else - if (try_at > (void *)0x0000800000000000) -#endif - try_at = (void *)0x0; - if (!(++tries % 10000)) - dprintf1("stuck in %s(), tries: %lld\n", __func__, tries); - continue; - } - last = ptr; - dprintf3("mpx_mini_alloc(0x%lx) returning: %p\n", sz, ptr); - return ptr; -} -void mpx_mini_free(void *ptr, long sz) -{ - dprintf2("%s() ptr: %p\n", __func__, ptr); - if ((unsigned long)ptr > 0x100000000000) { - dprintf1("uh oh !!!!!!!!!!!!!!! pointer too high: %p\n", ptr); - test_failed(); - } - sz = align_up(sz, sz_alignment); - dprintf3("%s() ptr: %p before munmap\n", __func__, ptr); - munmap(ptr, sz); - dprintf3("%s() ptr: %p DONE\n", __func__, ptr); -} - -#define NR_MALLOCS 100 -struct one_malloc { - char *ptr; - int nr_filled_btes; - unsigned long size; -}; -struct one_malloc mallocs[NR_MALLOCS]; - -void free_one_malloc(int index) -{ - unsigned long free_ptr; - unsigned long mask; - - if (!mallocs[index].ptr) - return; - - mpx_mini_free(mallocs[index].ptr, mallocs[index].size); - dprintf4("freed[%d]: %p\n", index, mallocs[index].ptr); - - free_ptr = (unsigned long)mallocs[index].ptr; - mask = alignment-1; - dprintf4("lowerbits: %lx / %lx mask: %lx\n", free_ptr, - (free_ptr & mask), mask); - assert((free_ptr & mask) == 0); - - mallocs[index].ptr = NULL; -} - -#ifdef __i386__ -#define MPX_BOUNDS_TABLE_COVERS 4096 -#else -#define MPX_BOUNDS_TABLE_COVERS (1 * MB) -#endif -void zap_everything(void) -{ - long after_zap; - long before_zap; - int i; - - before_zap = inspect_me(bounds_dir_ptr); - dprintf1("zapping everything start: %ld\n", before_zap); - for (i = 0; i < NR_MALLOCS; i++) - free_one_malloc(i); - - after_zap = inspect_me(bounds_dir_ptr); - dprintf1("zapping everything done: %ld\n", after_zap); - /* - * We only guarantee to empty the thing out if our allocations are - * exactly aligned on the boundaries of a boudns table. - */ - if ((alignment >= MPX_BOUNDS_TABLE_COVERS) && - (sz_alignment >= MPX_BOUNDS_TABLE_COVERS)) { - if (after_zap != 0) - test_failed(); - - assert(after_zap == 0); - } -} - -void do_one_malloc(void) -{ - static int malloc_counter; - long sz; - int rand_index = (mpx_random() % NR_MALLOCS); - void *ptr = mallocs[rand_index].ptr; - - dprintf3("%s() enter\n", __func__); - - if (ptr) { - dprintf3("freeing one malloc at index: %d\n", rand_index); - free_one_malloc(rand_index); - if (mpx_random() % (NR_MALLOCS*3) == 3) { - int i; - dprintf3("zapping some more\n"); - for (i = rand_index; i < NR_MALLOCS; i++) - free_one_malloc(i); - } - if ((mpx_random() % zap_all_every_this_many_mallocs) == 4) - zap_everything(); - } - - /* 1->~1M */ - sz = (1 + mpx_random() % 1000) * 1000; - ptr = mpx_mini_alloc(sz); - if (!ptr) { - /* - * If we are failing allocations, just assume we - * are out of memory and zap everything. - */ - dprintf3("zapping everything because out of memory\n"); - zap_everything(); - goto out; - } - - dprintf3("malloc: %p size: 0x%lx\n", ptr, sz); - mallocs[rand_index].nr_filled_btes = cover_buf_with_bt_entries(ptr, sz); - mallocs[rand_index].ptr = ptr; - mallocs[rand_index].size = sz; -out: - if ((++malloc_counter) % inspect_every_this_many_mallocs == 0) - inspect_me(bounds_dir_ptr); -} - -void run_timed_test(void (*test_func)(void)) -{ - int done = 0; - long iteration = 0; - static time_t last_print; - time_t now; - time_t start; - - time(&start); - while (!done) { - time(&now); - if ((now - start) > TEST_DURATION_SECS) - done = 1; - - test_func(); - iteration++; - - if ((now - last_print > 1) || done) { - printf("iteration %ld complete, OK so far\n", iteration); - last_print = now; - } - } -} - -void check_bounds_table_frees(void) -{ - printf("executing unmaptest\n"); - inspect_me(bounds_dir_ptr); - run_timed_test(&do_one_malloc); - printf("done with malloc() fun\n"); -} - -void insn_test_failed(int test_nr, int test_round, void *buf, - void *buf_shadow, void *ptr) -{ - print_context(xsave_test_buf); - eprintf("ERROR: test %d round %d failed\n", test_nr, test_round); - while (test_nr == 5) { - struct mpx_bt_entry *bte; - struct mpx_bounds_dir *bd = (void *)bounds_dir_ptr; - struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(buf, bd); - - printf(" bd: %p\n", bd); - printf("&bde: %p\n", bde); - printf("*bde: %lx\n", *(unsigned long *)bde); - if (!bd_entry_valid(bde)) - break; - - bte = mpx_vaddr_to_bt_entry(buf, bd); - printf(" te: %p\n", bte); - printf("bte[0]: %lx\n", bte->contents[0]); - printf("bte[1]: %lx\n", bte->contents[1]); - printf("bte[2]: %lx\n", bte->contents[2]); - printf("bte[3]: %lx\n", bte->contents[3]); - break; - } - test_failed(); -} - -void check_mpx_insns_and_tables(void) -{ - int successes = 0; - int failures = 0; - int buf_size = (1024*1024); - unsigned long *buf = malloc(buf_size); - const int total_nr_tests = NR_MPX_TEST_FUNCTIONS * TEST_ROUNDS; - int i, j; - - memset(buf, 0, buf_size); - memset(buf_shadow, 0, sizeof(buf_shadow)); - - for (i = 0; i < TEST_ROUNDS; i++) { - uint8_t *ptr = get_random_addr() + 8; - - for (j = 0; j < NR_MPX_TEST_FUNCTIONS; j++) { - if (0 && j != 5) { - successes++; - continue; - } - dprintf2("starting test %d round %d\n", j, i); - dprint_context(xsave_test_buf); - /* - * test5 loads an address from the bounds tables. - * The load will only complete if 'ptr' matches - * the load and the store, so with random addrs, - * the odds of this are very small. Make it - * higher by only moving 'ptr' 1/10 times. - */ - if (random() % 10 <= 0) - ptr = get_random_addr() + 8; - dprintf3("random ptr{%p}\n", ptr); - dprint_context(xsave_test_buf); - run_helpers(j, (void *)buf, (void *)buf_shadow, ptr); - dprint_context(xsave_test_buf); - if (!compare_context(xsave_test_buf)) { - insn_test_failed(j, i, buf, buf_shadow, ptr); - failures++; - goto exit; - } - successes++; - dprint_context(xsave_test_buf); - dprintf2("finished test %d round %d\n", j, i); - dprintf3("\n"); - dprint_context(xsave_test_buf); - } - } - -exit: - dprintf2("\nabout to free:\n"); - free(buf); - dprintf1("successes: %d\n", successes); - dprintf1(" failures: %d\n", failures); - dprintf1(" tests: %d\n", total_nr_tests); - dprintf1(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs); - dprintf1(" saw: %d #BRs\n", br_count); - if (failures) { - eprintf("ERROR: non-zero number of failures\n"); - exit(20); - } - if (successes != total_nr_tests) { - eprintf("ERROR: succeeded fewer than number of tries (%d != %d)\n", - successes, total_nr_tests); - exit(21); - } - if (num_upper_brs + num_lower_brs != br_count) { - eprintf("ERROR: unexpected number of #BRs: %jd %jd %d\n", - num_upper_brs, num_lower_brs, br_count); - eprintf("successes: %d\n", successes); - eprintf(" failures: %d\n", failures); - eprintf(" tests: %d\n", total_nr_tests); - eprintf(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs); - eprintf(" saw: %d #BRs\n", br_count); - exit(22); - } -} - -/* - * This is supposed to SIGSEGV nicely once the kernel - * can no longer allocate vaddr space. - */ -void exhaust_vaddr_space(void) -{ - unsigned long ptr; - /* Try to make sure there is no room for a bounds table anywhere */ - unsigned long skip = MPX_BOUNDS_TABLE_SIZE_BYTES - PAGE_SIZE; -#ifdef __i386__ - unsigned long max_vaddr = 0xf7788000UL; -#else - unsigned long max_vaddr = 0x800000000000UL; -#endif - - dprintf1("%s() start\n", __func__); - /* do not start at 0, we aren't allowed to map there */ - for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) { - void *ptr_ret; - int ret = madvise((void *)ptr, PAGE_SIZE, MADV_NORMAL); - - if (!ret) { - dprintf1("madvise() %lx ret: %d\n", ptr, ret); - continue; - } - ptr_ret = mmap((void *)ptr, PAGE_SIZE, PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if (ptr_ret != (void *)ptr) { - perror("mmap"); - dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret); - break; - } - if (!(ptr & 0xffffff)) - dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret); - } - for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) { - dprintf2("covering 0x%lx with bounds table entries\n", ptr); - cover_buf_with_bt_entries((void *)ptr, PAGE_SIZE); - } - dprintf1("%s() end\n", __func__); - printf("done with vaddr space fun\n"); -} - -void mpx_table_test(void) -{ - printf("starting mpx bounds table test\n"); - run_timed_test(check_mpx_insns_and_tables); - printf("done with mpx bounds table test\n"); -} - -int main(int argc, char **argv) -{ - int unmaptest = 0; - int vaddrexhaust = 0; - int tabletest = 0; - int i; - - check_mpx_support(); - mpx_prepare(); - srandom(11179); - - bd_incore(); - init(); - bd_incore(); - - trace_me(); - - xsave_state((void *)xsave_test_buf, 0x1f); - if (!compare_context(xsave_test_buf)) - printf("Init failed\n"); - - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "unmaptest")) - unmaptest = 1; - if (!strcmp(argv[i], "vaddrexhaust")) - vaddrexhaust = 1; - if (!strcmp(argv[i], "tabletest")) - tabletest = 1; - } - if (!(unmaptest || vaddrexhaust || tabletest)) { - unmaptest = 1; - /* vaddrexhaust = 1; */ - tabletest = 1; - } - if (unmaptest) - check_bounds_table_frees(); - if (tabletest) - mpx_table_test(); - if (vaddrexhaust) - exhaust_vaddr_space(); - printf("%s completed successfully\n", argv[0]); - exit(0); -} - -#include "mpx-dig.c" diff --git a/tools/testing/selftests/x86/mpx-mm.h b/tools/testing/selftests/x86/mpx-mm.h deleted file mode 100644 index 6dbdd66b8242..000000000000 --- a/tools/testing/selftests/x86/mpx-mm.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _MPX_MM_H -#define _MPX_MM_H - -#define PAGE_SIZE 4096 -#define MB (1UL<<20) - -extern long nr_incore(void *ptr, unsigned long size_bytes); - -#endif /* _MPX_MM_H */ -- GitLab From f240652b6032b48ad7fa35c5e701cc4c8d697c0b Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Fri, 5 Jul 2019 10:53:21 -0700 Subject: [PATCH 0104/7155] x86/mpx: Remove MPX APIs MPX is being removed from the kernel due to a lack of support in the toolchain going forward (gcc). The first step is to remove the userspace-visible ABIs so that applications will stop using it. The most visible one are the enable/disable prctl()s. Remove them first. This is the most minimal and least invasive change needed to ensure that apps stop using MPX with new kernels. Signed-off-by: Dave Hansen Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190705175321.DB42F0AD@viggo.jf.intel.com --- include/uapi/linux/prctl.h | 2 +- kernel/sys.c | 16 ++-------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 094bb03b9cc2..961e0a4a0f73 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -181,7 +181,7 @@ struct prctl_mm_map { #define PR_GET_THP_DISABLE 42 /* - * Tell the kernel to start/stop helping userspace manage bounds tables. + * No longer implemented, but left here to ensure the numbers stay reserved: */ #define PR_MPX_ENABLE_MANAGEMENT 43 #define PR_MPX_DISABLE_MANAGEMENT 44 diff --git a/kernel/sys.c b/kernel/sys.c index 2969304c29fe..384b000b7865 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -103,12 +103,6 @@ #ifndef SET_TSC_CTL # define SET_TSC_CTL(a) (-EINVAL) #endif -#ifndef MPX_ENABLE_MANAGEMENT -# define MPX_ENABLE_MANAGEMENT() (-EINVAL) -#endif -#ifndef MPX_DISABLE_MANAGEMENT -# define MPX_DISABLE_MANAGEMENT() (-EINVAL) -#endif #ifndef GET_FP_MODE # define GET_FP_MODE(a) (-EINVAL) #endif @@ -2456,15 +2450,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, up_write(&me->mm->mmap_sem); break; case PR_MPX_ENABLE_MANAGEMENT: - if (arg2 || arg3 || arg4 || arg5) - return -EINVAL; - error = MPX_ENABLE_MANAGEMENT(); - break; case PR_MPX_DISABLE_MANAGEMENT: - if (arg2 || arg3 || arg4 || arg5) - return -EINVAL; - error = MPX_DISABLE_MANAGEMENT(); - break; + /* No longer implemented: */ + return -EINVAL; case PR_SET_FP_MODE: error = SET_FP_MODE(me, arg2); break; -- GitLab From be261ffce6f13229dad50f59c5e491f933d3167f Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 4 Jul 2019 10:46:37 -0500 Subject: [PATCH 0105/7155] x86: Remove X86_FEATURE_MFENCE_RDTSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AMD and Intel both have serializing lfence (X86_FEATURE_LFENCE_RDTSC). They've both had it for a long time, and AMD has had it enabled in Linux since Spectre v1 was announced. Back then, there was a proposal to remove the serializing mfence feature bit (X86_FEATURE_MFENCE_RDTSC), since both AMD and Intel have serializing lfence. At the time, it was (ahem) speculated that some hypervisors might not yet support its removal, so it remained for the time being. Now a year-and-a-half later, it should be safe to remove. I asked Andrew Cooper about whether it's still needed: So if you're virtualised, you've got no choice in the matter.  lfence is either dispatch-serialising or not on AMD, and you won't be able to change it. Furthermore, you can't accurately tell what state the bit is in, because the MSR might not be virtualised at all, or may not reflect the true state in hardware.  Worse still, attempting to set the bit may not be successful even if there isn't a fault for doing so. Xen sets the DE_CFG bit unconditionally, as does Linux by the looks of things (see MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT).  ISTR other hypervisor vendors saying the same, but I don't have any information to hand. If you are running under a hypervisor which has been updated, then lfence will almost certainly be dispatch-serialising in practice, and you'll almost certainly see the bit already set in DE_CFG.  If you're running under a hypervisor which hasn't been patched since Spectre, you've already lost in many more ways. I'd argue that X86_FEATURE_MFENCE_RDTSC is not worth keeping. So remove it. This will reduce some code rot, and also make it easier to hook barrier_nospec() up to a cmdline disable for performance raisins, without having to need an alternative_3() macro. Signed-off-by: Josh Poimboeuf Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/d990aa51e40063acb9888e8c1b688e41355a9588.1562255067.git.jpoimboe@redhat.com --- arch/x86/include/asm/barrier.h | 3 +-- arch/x86/include/asm/cpufeatures.h | 1 - arch/x86/include/asm/msr.h | 3 +-- arch/x86/kernel/cpu/amd.c | 21 +++------------------ arch/x86/kernel/cpu/hygon.c | 21 +++------------------ tools/arch/x86/include/asm/cpufeatures.h | 1 - 6 files changed, 8 insertions(+), 42 deletions(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index 84f848c2541a..7f828fe49797 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -49,8 +49,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, #define array_index_mask_nospec array_index_mask_nospec /* Prevent speculative execution past this barrier. */ -#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \ - "lfence", X86_FEATURE_LFENCE_RDTSC) +#define barrier_nospec() alternative("", "lfence", X86_FEATURE_LFENCE_RDTSC) #define dma_rmb() barrier() #define dma_wmb() barrier() diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 56f53bf3bbbf..fcc70ffd88c2 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -96,7 +96,6 @@ #define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */ #define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */ #define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" MFENCE synchronizes RDTSC */ #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" LFENCE synchronizes RDTSC */ #define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 5cc3930cb465..86f20d520a07 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -233,8 +233,7 @@ static __always_inline unsigned long long rdtsc_ordered(void) * Thus, use the preferred barrier on the respective CPU, aiming for * RDTSCP as the default. */ - asm volatile(ALTERNATIVE_3("rdtsc", - "mfence; rdtsc", X86_FEATURE_MFENCE_RDTSC, + asm volatile(ALTERNATIVE_2("rdtsc", "lfence; rdtsc", X86_FEATURE_LFENCE_RDTSC, "rdtscp", X86_FEATURE_RDTSCP) : EAX_EDX_RET(val, low, high) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 8d4e50428b68..3afe07d602dd 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -879,12 +879,8 @@ static void init_amd(struct cpuinfo_x86 *c) init_amd_cacheinfo(c); if (cpu_has(c, X86_FEATURE_XMM2)) { - unsigned long long val; - int ret; - /* - * A serializing LFENCE has less overhead than MFENCE, so - * use it for execution serialization. On families which + * Use LFENCE for execution serialization. On families which * don't have that MSR, LFENCE is already serializing. * msr_set_bit() uses the safe accessors, too, even if the MSR * is not present. @@ -892,19 +888,8 @@ static void init_amd(struct cpuinfo_x86 *c) msr_set_bit(MSR_F10H_DECFG, MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT); - /* - * Verify that the MSR write was successful (could be running - * under a hypervisor) and only then assume that LFENCE is - * serializing. - */ - ret = rdmsrl_safe(MSR_F10H_DECFG, &val); - if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) { - /* A serializing LFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - } else { - /* MFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); - } + /* A serializing LFENCE stops RDTSC speculation */ + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); } /* diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c index 415621ddb8a2..4e28c1fc8749 100644 --- a/arch/x86/kernel/cpu/hygon.c +++ b/arch/x86/kernel/cpu/hygon.c @@ -330,12 +330,8 @@ static void init_hygon(struct cpuinfo_x86 *c) init_hygon_cacheinfo(c); if (cpu_has(c, X86_FEATURE_XMM2)) { - unsigned long long val; - int ret; - /* - * A serializing LFENCE has less overhead than MFENCE, so - * use it for execution serialization. On families which + * Use LFENCE for execution serialization. On families which * don't have that MSR, LFENCE is already serializing. * msr_set_bit() uses the safe accessors, too, even if the MSR * is not present. @@ -343,19 +339,8 @@ static void init_hygon(struct cpuinfo_x86 *c) msr_set_bit(MSR_F10H_DECFG, MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT); - /* - * Verify that the MSR write was successful (could be running - * under a hypervisor) and only then assume that LFENCE is - * serializing. - */ - ret = rdmsrl_safe(MSR_F10H_DECFG, &val); - if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) { - /* A serializing LFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - } else { - /* MFENCE stops RDTSC speculation */ - set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); - } + /* A serializing LFENCE stops RDTSC speculation */ + set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); } /* diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 998c2cc08363..9b98edb6b2d3 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -96,7 +96,6 @@ #define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */ #define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */ #define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" MFENCE synchronizes RDTSC */ #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" LFENCE synchronizes RDTSC */ #define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ -- GitLab From 6b0e42771795334bd24d089402d04d93bac048d3 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sun, 21 Jul 2019 19:01:34 -0400 Subject: [PATCH 0106/7155] locks: revise generic_add_lease tracepoint Now that check_conflicting_open uses inode->i_readcount instead of the dentry->d_count to detect opens for read, revise the tracepoint to display that value instead. Also, fl is never NULL, so no need to check for that in the fast assign section. Cc: Amir Goldstein Reported-by: Al Viro Signed-off-by: Jeff Layton --- include/trace/events/filelock.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/trace/events/filelock.h b/include/trace/events/filelock.h index 4b735923f2ff..c705e4944a50 100644 --- a/include/trace/events/filelock.h +++ b/include/trace/events/filelock.h @@ -176,7 +176,7 @@ TRACE_EVENT(generic_add_lease, TP_STRUCT__entry( __field(unsigned long, i_ino) __field(int, wcount) - __field(int, dcount) + __field(int, rcount) __field(int, icount) __field(dev_t, s_dev) __field(fl_owner_t, fl_owner) @@ -188,16 +188,16 @@ TRACE_EVENT(generic_add_lease, __entry->s_dev = inode->i_sb->s_dev; __entry->i_ino = inode->i_ino; __entry->wcount = atomic_read(&inode->i_writecount); - __entry->dcount = d_count(fl->fl_file->f_path.dentry); + __entry->rcount = atomic_read(&inode->i_readcount); __entry->icount = atomic_read(&inode->i_count); - __entry->fl_owner = fl ? fl->fl_owner : NULL; - __entry->fl_flags = fl ? fl->fl_flags : 0; - __entry->fl_type = fl ? fl->fl_type : 0; + __entry->fl_owner = fl->fl_owner; + __entry->fl_flags = fl->fl_flags; + __entry->fl_type = fl->fl_type; ), - TP_printk("dev=0x%x:0x%x ino=0x%lx wcount=%d dcount=%d icount=%d fl_owner=0x%p fl_flags=%s fl_type=%s", + TP_printk("dev=0x%x:0x%x ino=0x%lx wcount=%d rcount=%d icount=%d fl_owner=0x%p fl_flags=%s fl_type=%s", MAJOR(__entry->s_dev), MINOR(__entry->s_dev), - __entry->i_ino, __entry->wcount, __entry->dcount, + __entry->i_ino, __entry->wcount, __entry->rcount, __entry->icount, __entry->fl_owner, show_fl_flags(__entry->fl_flags), show_fl_type(__entry->fl_type)) -- GitLab From ef9bec27485fefb6b93168fea73fda0dc9638046 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 26 Jun 2019 00:04:50 -0700 Subject: [PATCH 0107/7155] ASoC: SOF: Intel: hda: Make hdac_device device-managed snd_hdac_ext_bus_device_exit() has been recently modified to no longer free the hdac device. SOF allocates memory for hdac_device and hda_hda_priv with kzalloc. Make them device-managed instead so that they will be freed when the SOF driver is unloaded. Because of the above change, hda_codec is device-managed and it will be freed when the ASoC device is removed. Freeing the codec in snd_hda_codec_dev_release() leads to kernel panic while unloading and reloading the ASoC driver. So, avoid freeing the hda_codec for ASoC driver. This is done in the same patch to avoid bisect failure. Signed-off-by: Libin Yang Signed-off-by: Ranjani Sridharan Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190626070450.7229-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/pci/hda/hda_codec.c | 8 +++++++- sound/soc/sof/intel/hda-codec.c | 6 ++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e30e86ca6b72..133200d31170 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev) snd_hda_sysfs_clear(codec); kfree(codec->modelname); kfree(codec->wcaps); - kfree(codec); + + /* + * In the case of ASoC HD-audio, hda_codec is device managed. + * It will be freed when the ASoC device is removed. + */ + if (codec->core.type == HDA_DEV_LEGACY) + kfree(codec); } #define DEV_NAME_LEN 31 diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index b8b37f082309..0d8437b080bf 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -62,8 +62,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) address, resp); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ - hda_priv = kzalloc(sizeof(*hda_priv), GFP_KERNEL); + hda_priv = devm_kzalloc(sdev->dev, sizeof(*hda_priv), GFP_KERNEL); if (!hda_priv) return -ENOMEM; @@ -82,8 +81,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) return 0; #else - /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); + hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); if (!hdev) return -ENOMEM; -- GitLab From f7408a3d5b5fd10571a653d1a81ce9167c62727f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Jul 2019 22:04:25 -0700 Subject: [PATCH 0108/7155] ASoC: wcd9335: Fix misuse of GENMASK macro Arguments are supposed to be ordered high then low. Signed-off-by: Joe Perches Link: https://lore.kernel.org/r/92e31a9f321fe731d428ec3ec9d4654ea8a16d1b.1562734889.git.joe@perches.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd-clsh-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd-clsh-v2.c b/sound/soc/codecs/wcd-clsh-v2.c index c397d713f01a..cc5a9c9b918b 100644 --- a/sound/soc/codecs/wcd-clsh-v2.c +++ b/sound/soc/codecs/wcd-clsh-v2.c @@ -65,7 +65,7 @@ struct wcd_clsh_ctrl { #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 #define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) -#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3) +#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(3, 0) #define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) #define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) #define WCD9XXX_HPH_CONST_SEL_BYPASS 0 -- GitLab From eaba5585944e6d692828bca701c9362f60172b8a Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Wed, 10 Jul 2019 13:51:19 +0300 Subject: [PATCH 0109/7155] ASoC: codecs: ad193x: Use regmap_multi_reg_write() when initializing Using regmap_multi_reg_write() when we set the default values for our registers makes the code smaller and easier to read. Suggested-by: Tzung-Bi Shih Signed-off-by: Codrin Ciubotariu Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190710105119.22987-1-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 80dab5df9633..fb04c9379b71 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { .ops = &ad193x_dai_ops, }; -struct ad193x_reg_default { - unsigned int reg; - unsigned int val; -}; - /* codec register values to set after reset */ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { - const struct ad193x_reg_default reg_init[] = { + const struct reg_sequence reg_init[] = { { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ @@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ }; - const struct ad193x_reg_default reg_adc_init[] = { + const struct reg_sequence reg_adc_init[] = { { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ { 16, 0x00 }, /* ADC_CTRL2: reset */ }; - int i; - for (i = 0; i < ARRAY_SIZE(reg_init); i++) - regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val); + regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init)); if (ad193x_has_adc(ad193x)) { - for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { - regmap_write(ad193x->regmap, reg_adc_init[i].reg, - reg_adc_init[i].val); - } + regmap_multi_reg_write(ad193x->regmap, reg_adc_init, + ARRAY_SIZE(reg_adc_init)); } } -- GitLab From 4dc057a786dc23fd1ed70e6bcab691c0f26daa1e Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 10 Jul 2019 17:28:38 -0700 Subject: [PATCH 0110/7155] ASoC: rt5677: remove superfluous set We define this variable with the same value, no need to set it twice Signed-off-by: Curtis Malainey Link: https://lore.kernel.org/r/20190711002838.35363-1-cujomalainey@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index c779dc3474f9..deaed5132dc9 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5098,7 +5098,6 @@ static irqreturn_t rt5677_irq(int unused, void *data) goto exit; } - irq_fired = false; for (i = 0; i < RT5677_IRQ_NUM; i++) { if (reg_irq & rt5677_irq_descs[i].status_mask) { irq_fired = true; -- GitLab From 5be6155b50bbf7083b4bfa219e4ce6d1491f42f0 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 11 Jul 2019 18:49:45 +0800 Subject: [PATCH 0111/7155] ASoC: fsl_esai: Wrap some operations to be functions Extract the operation to be functions, to improve the readability. In this patch, fsl_esai_hw_init, fsl_esai_register_restore, fsl_esai_trigger_start and fsl_esai_trigger_stop are extracted. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/804d7e75ae7e06a913479912b578b3538ca7cd3f.1562842206.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 188 ++++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 71 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 10d2210c91ef..ab460d6d7432 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -35,6 +35,7 @@ * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @slots: number of slots + * @channels: channel num for tx or rx * @hck_rate: clock rate of desired HCKx clock * @sck_rate: clock rate of desired SCKx clock * @hck_dir: the direction of HCKx pads @@ -57,6 +58,7 @@ struct fsl_esai { u32 slots; u32 tx_mask; u32 rx_mask; + u32 channels[2]; u32 hck_rate[2]; u32 sck_rate[2]; bool hck_dir[2]; @@ -543,64 +545,132 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, return 0; } +static int fsl_esai_hw_init(struct fsl_esai *esai_priv) +{ + struct platform_device *pdev = esai_priv->pdev; + int ret; + + /* Reset ESAI unit */ + ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, + ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, + ESAI_ECR_ESAIEN | ESAI_ECR_ERST); + if (ret) { + dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); + return ret; + } + + /* + * We need to enable ESAI so as to access some of its registers. + * Otherwise, we would fail to dump regmap from user space. + */ + ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, + ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, + ESAI_ECR_ESAIEN); + if (ret) { + dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); + return ret; + } + + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, + ESAI_PRRC_PDC_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, + ESAI_PCRC_PC_MASK, 0); + + return 0; +} + +static int fsl_esai_register_restore(struct fsl_esai *esai_priv) +{ + int ret; + + /* FIFO reset for safety */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, + ESAI_xFCR_xFR, ESAI_xFCR_xFR); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, + ESAI_xFCR_xFR, ESAI_xFCR_xFR); + + regcache_mark_dirty(esai_priv->regmap); + ret = regcache_sync(esai_priv->regmap); + if (ret) + return ret; + + /* FIFO reset done */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); + + return 0; +} + +static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) +{ + u8 i, channels = esai_priv->channels[tx]; + u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); + u32 mask; + + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); + + /* Write initial words reqiured by ESAI as normal procedure */ + for (i = 0; tx && i < channels; i++) + regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); + + /* + * When set the TE/RE in the end of enablement flow, there + * will be channel swap issue for multi data line case. + * In order to workaround this issue, we switch the bit + * enablement sequence to below sequence + * 1) clear the xSMB & xSMA: which is done in probe and + * stop state. + * 2) set TE/RE + * 3) set xSMB + * 4) set xSMA: xSMA is the last one in this flow, which + * will trigger esai to start. + */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, + tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); + mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; + + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), + ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), + ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); +} + +static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) +{ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), + ESAI_xSMA_xS_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), + ESAI_xSMB_xS_MASK, 0); + + /* Disable and reset FIFO */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), + ESAI_xFCR_xFR, 0); +} + static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - u8 i, channels = substream->runtime->channels; - u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); - u32 mask; + + esai_priv->channels[tx] = substream->runtime->channels; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); - - /* Write initial words reqiured by ESAI as normal procedure */ - for (i = 0; tx && i < channels; i++) - regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); - - /* - * When set the TE/RE in the end of enablement flow, there - * will be channel swap issue for multi data line case. - * In order to workaround this issue, we switch the bit - * enablement sequence to below sequence - * 1) clear the xSMB & xSMA: which is done in probe and - * stop state. - * 2) set TE/RE - * 3) set xSMB - * 4) set xSMA: xSMA is the last one in this flow, which - * will trigger esai to start. - */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), - tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, - tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); - mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; - - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), - ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), - ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); - + fsl_esai_trigger_start(esai_priv, tx); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), - tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), - ESAI_xSMA_xS_MASK, 0); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), - ESAI_xSMB_xS_MASK, 0); - - /* Disable and reset FIFO */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); - regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), - ESAI_xFCR_xFR, 0); + fsl_esai_trigger_stop(esai_priv, tx); break; default: return -EINVAL; @@ -866,22 +936,9 @@ static int fsl_esai_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, esai_priv); - /* Reset ESAI unit */ - ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); - if (ret) { - dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); - return ret; - } - - /* - * We need to enable ESAI so as to access some of its registers. - * Otherwise, we would fail to dump regmap from user space. - */ - ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); - if (ret) { - dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); + ret = fsl_esai_hw_init(esai_priv); + if (ret) return ret; - } esai_priv->tx_mask = 0xFFFFFFFF; esai_priv->rx_mask = 0xFFFFFFFF; @@ -955,20 +1012,10 @@ static int fsl_esai_runtime_resume(struct device *dev) regcache_cache_only(esai->regmap, false); - /* FIFO reset for safety */ - regmap_update_bits(esai->regmap, REG_ESAI_TFCR, - ESAI_xFCR_xFR, ESAI_xFCR_xFR); - regmap_update_bits(esai->regmap, REG_ESAI_RFCR, - ESAI_xFCR_xFR, ESAI_xFCR_xFR); - - ret = regcache_sync(esai->regmap); + ret = fsl_esai_register_restore(esai); if (ret) goto err_regcache_sync; - /* FIFO reset done */ - regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); - regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); - return 0; err_regcache_sync: @@ -991,7 +1038,6 @@ static int fsl_esai_runtime_suspend(struct device *dev) struct fsl_esai *esai = dev_get_drvdata(dev); regcache_cache_only(esai->regmap, true); - regcache_mark_dirty(esai->regmap); if (!IS_ERR(esai->fsysclk)) clk_disable_unprepare(esai->fsysclk); -- GitLab From 1d3dd532883be6167da5df6117efd6d4e8790456 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Tue, 9 Jul 2019 23:55:43 +0530 Subject: [PATCH 0112/7155] sound: soc: codecs: mt6358: change return type of mt6358_codec_init_reg As mt6358_codec_init_reg function always returns 0 , change return type from int to void. fixes below issue reported by coccicheck sound/soc/codecs/mt6358.c:2260:5-8: Unneeded variable: "ret". Return "0" on line 2289 Signed-off-by: Hariprasad Kelam Acked-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190709182543.GA6611@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 50b3fc5457ea..c17250aab2d0 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -2255,10 +2255,8 @@ static struct snd_soc_dai_driver mt6358_dai_driver[] = { }, }; -static int mt6358_codec_init_reg(struct mt6358_priv *priv) +static void mt6358_codec_init_reg(struct mt6358_priv *priv) { - int ret = 0; - /* Disable HeadphoneL/HeadphoneR short circuit protection */ regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0, RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, @@ -2285,8 +2283,6 @@ static int mt6358_codec_init_reg(struct mt6358_priv *priv) /* set gpio */ playback_gpio_reset(priv); capture_gpio_reset(priv); - - return ret; } static int mt6358_codec_probe(struct snd_soc_component *cmpnt) -- GitLab From 1e2cc8c5e0745b545d4974788dc606d678b6e564 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Jun 2019 21:26:31 +0800 Subject: [PATCH 0113/7155] regulator: lm363x: Fix off-by-one n_voltages for lm3632 ldo_vpos/ldo_vneg According to the datasheet https://www.ti.com/lit/ds/symlink/lm3632a.pdf Table 20. VPOS Bias Register Field Descriptions VPOS[5:0] Sets the Positive Display Bias (LDO) Voltage (50 mV per step) 000000: 4 V 000001: 4.05 V 000010: 4.1 V .................... 011101: 5.45 V 011110: 5.5 V (Default) 011111: 5.55 V .................... 100111: 5.95 V 101000: 6 V Note: Codes 101001 to 111111 map to 6 V The LM3632_LDO_VSEL_MAX should be 0b101000 (0x28), so the maximum voltage can match the datasheet. Fixes: 3a8d1a73a037 ("regulator: add LM363X driver") Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190626132632.32629-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/lm363x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index 5647e2f97ff8..e4a27d63bf90 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -30,7 +30,7 @@ /* LM3632 */ #define LM3632_BOOST_VSEL_MAX 0x26 -#define LM3632_LDO_VSEL_MAX 0x29 +#define LM3632_LDO_VSEL_MAX 0x28 #define LM3632_VBOOST_MIN 4500000 #define LM3632_VLDO_MIN 4000000 -- GitLab From 962f170d9344e5d9edb3903971c591f42d55e226 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Jun 2019 21:26:32 +0800 Subject: [PATCH 0114/7155] regulator: lm363x: Fix n_voltages setting for lm36274 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the datasheet http://www.ti.com/lit/ds/symlink/lm36274.pdf: Table 23. VPOS Bias Register Field Descriptions VPOS[5:0]: VPOS voltage (50-mV steps): VPOS = 4 V + (Code × 50 mV), 6.5 V max 000000 = 4 V 000001 = 4.05 V : 011110 = 5.5 V (Default) : 110010 = 6.5 V 110011 to 111111 map to 6.5 V So the LM36274_LDO_VSEL_MAX should be 0b110010 (0x32). The valid selectors are 0 ... LM36274_LDO_VSEL_MAX, n_voltages should be LM36274_LDO_VSEL_MAX + 1. Similarly, the n_voltages should be LM36274_BOOST_VSEL_MAX + 1 for LM36274_BOOST. Fixes: bff5e8071533 ("regulator: lm363x: Add support for LM36274") Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190626132632.32629-2-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/lm363x-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index e4a27d63bf90..4b9f618b07e9 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -36,7 +36,7 @@ /* LM36274 */ #define LM36274_BOOST_VSEL_MAX 0x3f -#define LM36274_LDO_VSEL_MAX 0x34 +#define LM36274_LDO_VSEL_MAX 0x32 #define LM36274_VOLTAGE_MIN 4000000 /* Common */ @@ -226,7 +226,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vboost", .id = LM36274_BOOST, .ops = &lm363x_boost_voltage_table_ops, - .n_voltages = LM36274_BOOST_VSEL_MAX, + .n_voltages = LM36274_BOOST_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, @@ -239,7 +239,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vpos", .id = LM36274_LDO_POS, .ops = &lm363x_regulator_voltage_table_ops, - .n_voltages = LM36274_LDO_VSEL_MAX, + .n_voltages = LM36274_LDO_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, @@ -254,7 +254,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vneg", .id = LM36274_LDO_NEG, .ops = &lm363x_regulator_voltage_table_ops, - .n_voltages = LM36274_LDO_VSEL_MAX, + .n_voltages = LM36274_LDO_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, -- GitLab From d850c6f5fad60b6edec08300977303aae855ffff Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Jul 2019 20:21:38 +0800 Subject: [PATCH 0115/7155] regulator: rk808: Return REGULATOR_MODE_INVALID for invalid mode -EINVAL is not a valid return value for .of_map_mode, return REGULATOR_MODE_INVALID instead. Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190711122138.5221-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index e7af0c53d449..61bd5ef0806c 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -606,7 +606,7 @@ static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode) case 2: return REGULATOR_MODE_NORMAL; default: - return -EINVAL; + return REGULATOR_MODE_INVALID; } } -- GitLab From 0521050215d0daae5d84b212fbe9fc16462f58f6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2019 14:42:30 +0300 Subject: [PATCH 0116/7155] spi: dw-mmio: Use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190710114230.30047-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 18c06568805e..1c1cac92a9de 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -138,7 +138,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio); struct dw_spi_mmio *dwsmmio; struct dw_spi *dws; - struct resource *mem; int ret; int num_cs; @@ -150,8 +149,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dws = &dwsmmio->dws; /* Get basic io resource and map it */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dws->regs = devm_ioremap_resource(&pdev->dev, mem); + dws->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dws->regs)) { dev_err(&pdev->dev, "SPI region map failed\n"); return PTR_ERR(dws->regs); -- GitLab From 3da9834d9381dd99273f2ad4e6d096c9187dc4f2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2019 14:42:43 +0300 Subject: [PATCH 0117/7155] spi: dw-mmio: Clock should be shut when error occurs When optional clock requesting fails, the main clock is still up and running, we should shut it down in such caee. Fixes: 560ee7e91009 ("spi: dw: Add support for an optional interface clock") Cc: Phil Edworthy Cc: Gareth Williams Signed-off-by: Andy Shevchenko Reviewed-by: Gareth Williams Link: https://lore.kernel.org/r/20190710114243.30101-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 1c1cac92a9de..4fa7e7a52ebd 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -170,8 +170,10 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) /* Optional clock needed to access the registers */ dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); - if (IS_ERR(dwsmmio->pclk)) - return PTR_ERR(dwsmmio->pclk); + if (IS_ERR(dwsmmio->pclk)) { + ret = PTR_ERR(dwsmmio->pclk); + goto out_clk; + } ret = clk_prepare_enable(dwsmmio->pclk); if (ret) goto out_clk; -- GitLab From e1fb714bddf452ef0ecf67c420957438977f107d Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 10 Jul 2019 00:12:37 +0530 Subject: [PATCH 0118/7155] ASoC: bcm: cygnus-pcm: Unneeded variable: "ret". This patch fixes below issues reported by coccicheck sound/soc/bcm/cygnus-pcm.c:642:5-8: Unneeded variable: "ret". Return "0" on line 650 sound/soc/bcm/cygnus-pcm.c:671:5-8: Unneeded variable: "ret". Return "0" on line 696 We cannot change return type of these functions as they are callback functions of snd_pcm_ops Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190709184236.GA7873@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 123ecf5479d7..8966b02844dc 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; - int ret = 0; aio = cygnus_dai_get_dma_data(substream); dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); @@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); - return ret; + return 0; } static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) @@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; unsigned long bufsize, periodsize; - int ret = 0; bool is_play; u32 start; struct ringbuf_regs *p_rbuf = NULL; @@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, periodsize, bufsize); - return ret; + return 0; } static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) -- GitLab From af62a3c8a872631e63833e2a99a8f43f81532fae Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 10 Jul 2019 07:46:27 +0530 Subject: [PATCH 0119/7155] ASoC: wcd9335: add irqflag IRQF_ONESHOT flag Add IRQF_ONESHOT to ensure "Interrupt is not reenabled after the hardirq handler finished". fixes below issue reported by coccicheck sound/soc/codecs/wcd9335.c:4068:8-33: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190710021627.GA13396@hari-Inspiron-1545 Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 1bbbe421b999..956602788d0e 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -4062,7 +4062,8 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd) ret = devm_request_threaded_irq(wcd->dev, irq, NULL, wcd9335_irqs[i].handler, - IRQF_TRIGGER_RISING, + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, wcd9335_irqs[i].name, wcd); if (ret) { dev_err(wcd->dev, "Failed to request %s\n", -- GitLab From a962a809e5e45715081fa247726a562b8dbd082a Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Tue, 16 Jul 2019 11:24:17 +0800 Subject: [PATCH 0120/7155] ASoC: mediatek: mt8183: make headset codec optional Make headset codec optional because some variant machines may not have an audio jack. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20190716032417.19015-1-tzungbi@google.com Signed-off-by: Mark Brown --- .../soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 887c932229d0..4c816c86844b 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -352,8 +352,6 @@ static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { .owner = THIS_MODULE, .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), - .aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev, - .num_aux_devs = 1, }; static int @@ -404,10 +402,9 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,headset-codec", 0); - if (!mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { - dev_err(&pdev->dev, - "Property 'mediatek,headset-codec' missing/invalid\n"); - return -EINVAL; + if (mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { + card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; + card->num_aux_devs = 1; } default_pins = -- GitLab From 89c9679f699d88986ce552738dc7c5c500c8fc67 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:56:33 +0200 Subject: [PATCH 0121/7155] ASoC: fsl_sai: add of_match data New revisions of the SAI IP block have even more differences that need be taken into account by the driver. To avoid sprinking compatible checks all over the driver move the current differences into of_match_data. Signed-off-by: Lucas Stach Tested-by: Angus Ainslie Reviewed-by: Angus Ainslie Reviewed-by: Daniel Baluta Link: https://lore.kernel.org/r/20190717105635.18514-2-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 22 ++++++++++++++-------- sound/soc/fsl/fsl_sai.h | 6 +++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index d58cc3ae90d8..ed0432e7327a 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -788,10 +789,7 @@ static int fsl_sai_probe(struct platform_device *pdev) return -ENOMEM; sai->pdev = pdev; - - if (of_device_is_compatible(np, "fsl,imx6sx-sai") || - of_device_is_compatible(np, "fsl,imx6ul-sai")) - sai->sai_on_imx = true; + sai->soc_data = of_device_get_match_data(&pdev->dev); sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); @@ -900,7 +898,7 @@ static int fsl_sai_probe(struct platform_device *pdev) if (ret) return ret; - if (sai->sai_on_imx) + if (sai->soc_data->use_imx_pcm) return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); else return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); @@ -913,10 +911,18 @@ static int fsl_sai_remove(struct platform_device *pdev) return 0; } +static const struct fsl_sai_soc_data fsl_sai_vf610_data = { + .use_imx_pcm = false, +}; + +static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { + .use_imx_pcm = true, +}; + static const struct of_device_id fsl_sai_ids[] = { - { .compatible = "fsl,vf610-sai", }, - { .compatible = "fsl,imx6sx-sai", }, - { .compatible = "fsl,imx6ul-sai", }, + { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data }, + { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data }, + { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 24cb156bf995..83e2bfe05b1b 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -126,6 +126,10 @@ #define FSL_SAI_MAXBURST_TX 6 #define FSL_SAI_MAXBURST_RX 6 +struct fsl_sai_soc_data { + bool use_imx_pcm; +}; + struct fsl_sai { struct platform_device *pdev; struct regmap *regmap; @@ -135,7 +139,6 @@ struct fsl_sai { bool is_slave_mode; bool is_lsb_first; bool is_dsp_mode; - bool sai_on_imx; bool synchronous[2]; unsigned int mclk_id[2]; @@ -143,6 +146,7 @@ struct fsl_sai { unsigned int slots; unsigned int slot_width; + const struct fsl_sai_soc_data *soc_data; struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; }; -- GitLab From bd517707d85f19a7339ea8b882fcbf0fd9976bd6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:56:34 +0200 Subject: [PATCH 0122/7155] ASoC: fsl_sai: derive TX FIFO watermark from FIFO depth The DMA request schould be triggered as soon as the FIFO has space for another burst. As different versions of the SAI block have different FIFO sizes, the watrmark level needs to be derived from version specific data. Signed-off-by: Lucas Stach Tested-by: Angus Ainslie Reviewed-by: Angus Ainslie Link: https://lore.kernel.org/r/20190717105635.18514-3-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 4 +++- sound/soc/fsl/fsl_sai.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index ed0432e7327a..1d1a447163e3 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -640,7 +640,7 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) regmap_write(sai->regmap, FSL_SAI_RCSR, 0); regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, - FSL_SAI_MAXBURST_TX * 2); + sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); @@ -913,10 +913,12 @@ static int fsl_sai_remove(struct platform_device *pdev) static const struct fsl_sai_soc_data fsl_sai_vf610_data = { .use_imx_pcm = false, + .fifo_depth = 32, }; static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { .use_imx_pcm = true, + .fifo_depth = 32, }; static const struct of_device_id fsl_sai_ids[] = { diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 83e2bfe05b1b..7c1ef671da28 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -128,6 +128,7 @@ struct fsl_sai_soc_data { bool use_imx_pcm; + unsigned int fifo_depth; }; struct fsl_sai { -- GitLab From 6d19d8a3cec74a9680947ecb6abdeda38583110e Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 17 Jul 2019 12:51:56 +0200 Subject: [PATCH 0123/7155] ASoC: fsl_sai: mark regmap as fast_io The regmap is only ever used to access MMIO registers, so it's fair to say that register access is fast. Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20190717105156.15721-1-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 1d1a447163e3..6d3c6c8d50ce 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -763,6 +763,7 @@ static const struct regmap_config fsl_sai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .fast_io = true, .max_register = FSL_SAI_RMR, .reg_defaults = fsl_sai_reg_defaults, -- GitLab From 96cd3b97bf32557ba722c2e96095cb6361b5dc42 Mon Sep 17 00:00:00 2001 From: fengchunguo Date: Mon, 15 Jul 2019 17:55:56 +0800 Subject: [PATCH 0124/7155] ASoC: max98383: fix i2c probe failure Added reset_gpio configuration for i2c probe successfully. If not,i2c address can't be found rightly. Error information: max98373 3-0031: Failed to read: 0x21FF Fixed: [3.761299@3] max98373 3-0031: MAX98373 revisionID: 0x43 [3.828911@3] asoc-aml-card auge_sound: max98373-aif1 <-> TDM-B mapping ok Signed-off-by: fengchunguo Link: https://lore.kernel.org/r/20190715095556.1614-1-chunguo.feng@amlogic.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 34 ++++++++++++++++++++++++++++++---- sound/soc/codecs/max98373.h | 1 + 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 528695cd6a1c..9a1eb7222357 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "max98373.h" @@ -895,6 +896,17 @@ static void max98373_slot_config(struct i2c_client *i2c, else max98373->i_slot = 1; + max98373->reset_gpio = of_get_named_gpio(dev->of_node, + "maxim,reset-gpio", 0); + if (!gpio_is_valid(max98373->reset_gpio)) { + dev_err(dev, "Looking up %s property in node %s failed %d\n", + "maxim,reset-gpio", dev->of_node->full_name, + max98373->reset_gpio); + } else { + dev_dbg(dev, "maxim,reset-gpio=%d", + max98373->reset_gpio); + } + if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) max98373->spkfb_slot = value & 0xF; else @@ -923,7 +935,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, else max98373->interleave_mode = false; - /* regmap initialization */ max98373->regmap = devm_regmap_init_i2c(i2c, &max98373_regmap); @@ -934,6 +945,24 @@ static int max98373_i2c_probe(struct i2c_client *i2c, return ret; } + /* voltage/current slot & gpio configuration */ + max98373_slot_config(i2c, max98373); + + /* Power on device */ + if (gpio_is_valid(max98373->reset_gpio)) { + ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET"); + if (ret) { + dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", + __func__, max98373->reset_gpio); + gpio_free(max98373->reset_gpio); + return -EINVAL; + } + gpio_direction_output(max98373->reset_gpio, 0); + msleep(50); + gpio_direction_output(max98373->reset_gpio, 1); + msleep(20); + } + /* Check Revision ID */ ret = regmap_read(max98373->regmap, MAX98373_R21FF_REV_ID, ®); @@ -944,9 +973,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, } dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); - /* voltage/current slot configuration */ - max98373_slot_config(i2c, max98373); - /* codec registeration */ ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, max98373_dai, ARRAY_SIZE(max98373_dai)); diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index f6a37aa02f26..533d2053f608 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -203,6 +203,7 @@ struct max98373_priv { struct regmap *regmap; + int reset_gpio; unsigned int v_slot; unsigned int i_slot; unsigned int spkfb_slot; -- GitLab From b7e814deae33eb30f8f8c6528e8e69b107978d88 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 19 Jul 2019 16:36:37 +0200 Subject: [PATCH 0125/7155] ASoC: tlv320aic31xx: suppress error message for EPROBE_DEFER Both the supplies and reset GPIO might need a probe deferral for the resource to be available. Don't print a error message in that case, as it is a normal operating condition. Signed-off-by: Lucas Stach Acked-by: Andrew F. Davis Link: https://lore.kernel.org/r/20190719143637.2018-1-l.stach@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 9b37e98da0db..26a4f6cd3288 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1553,7 +1553,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(aic31xx->gpio_reset)) { - dev_err(aic31xx->dev, "not able to acquire gpio\n"); + if (PTR_ERR(aic31xx->gpio_reset) != -EPROBE_DEFER) + dev_err(aic31xx->dev, "not able to acquire gpio\n"); return PTR_ERR(aic31xx->gpio_reset); } @@ -1564,7 +1565,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, ARRAY_SIZE(aic31xx->supplies), aic31xx->supplies); if (ret) { - dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(aic31xx->dev, + "Failed to request supplies: %d\n", ret); return ret; } -- GitLab From 980c10cda954770640d9d7cd7b793efa12cae0d9 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Fri, 19 Jul 2019 14:32:35 +0800 Subject: [PATCH 0126/7155] ASoC: rt1308: simplify the EFUSE read function The rt1308_efuse function contains many redundant settings. We remove the redundant settings and the function still works. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190719063235.18757-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index d673506c7c39..19d255e01827 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -808,33 +808,11 @@ static void rt1308_efuse(struct rt1308_priv *rt1308) { regmap_write(rt1308->regmap, RT1308_RESET, 0); - regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600); - regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000); - regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); - regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505); - regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000); - regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000); - regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200); - regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000); - regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000); - regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00); regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); - regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501); - - regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000); - regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00); msleep(100); regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); msleep(20); regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); - - regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000); - regmap_write(rt1308->regmap, RT1308_POWER, 0x0); - regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000); - regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); - regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00); } static int rt1308_i2c_probe(struct i2c_client *i2c, -- GitLab From 730e051c78b05f0ce87df06e0fc1ea002d722fe8 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Fri, 19 Jul 2019 14:32:49 +0800 Subject: [PATCH 0127/7155] ASoC: rt1308: add silence detection and manual PDB control We enable the silence detection function in initial settings. PDB control changes to manual mode, hence the driver could fully control the AMP output on/off. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190719063249.18806-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index 19d255e01827..cf3d72f99705 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -40,10 +40,10 @@ static const struct reg_sequence init_list[] = { { RT1308_VREF, 0x18100000 }, { RT1308_IV_SENSE, 0x87010000 }, { RT1308_DUMMY_REG, 0x00000200 }, - { RT1308_SIL_DET, 0x61c30000 }, + { RT1308_SIL_DET, 0xe1c30000 }, { RT1308_DC_CAL_2, 0x00ffff00 }, { RT1308_CLK_DET, 0x01000000 }, - { RT1308_POWER_STATUS, 0x00800000 }, + { RT1308_POWER_STATUS, 0x08800000 }, { RT1308_DAC_SET, 0xafaf0700 }, }; @@ -308,12 +308,13 @@ static int rt1308_classd_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: msleep(30); snd_soc_component_update_bits(component, RT1308_POWER_STATUS, - RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT); + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT); msleep(40); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_component_update_bits(component, RT1308_POWER_STATUS, - RT1308_POW_PDB_REG_BIT, 0); + RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0); usleep_range(150000, 200000); break; -- GitLab From 03b0deb6ba5f47d346fbb0783018c0d415203142 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:35:16 +0100 Subject: [PATCH 0128/7155] ASoC: cs47l35: Use define for DSPCLK enable bit Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722093516.12906-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index e3585c1dab3d..d396a8545d51 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6, +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), -- GitLab From 4aefb7387198740318c5e7bf7211701f4e0d849e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 19 Jul 2019 20:05:58 +0200 Subject: [PATCH 0129/7155] ASoC: rockchip-max98090: Remove MICBIAS as supply of input pin IN34 Commit ec0d23b295b9 ("ASoC: rockchip-max98090: Fix the Headset Mic route.") moved the MICBIAS widget to supply Headset Mic but forget to remove the MICBIAS widget to supply IN34 which is not really needed, so remove that path so we have: IN34 <==== Headset MIC <==== MICBIAS Signed-off-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20190719180558.11459-1-enric.balletbo@collabora.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index c5fc24675a33..d1c907631c2d 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -45,7 +45,6 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { static const struct snd_soc_dapm_route rk_audio_map[] = { {"IN34", NULL, "Headset Mic"}, - {"IN34", NULL, "MICBIAS"}, {"Headset Mic", NULL, "MICBIAS"}, {"DMICL", NULL, "Int Mic"}, {"Headphone", NULL, "HPL"}, -- GitLab From cfc8f568aada98f9608a0a62511ca18d647613e2 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:30 +0000 Subject: [PATCH 0130/7155] ASoC: Define a set of DAPM pre/post-up events Prepare to use SND_SOC_DAPM_PRE_POST_PMU definition to reduce coming code size and make it more readable. Cc: stable@vger.kernel.org Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-2-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c00a0b8ade08..6c6694160130 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -353,6 +353,8 @@ struct device; #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ #define SND_SOC_DAPM_PRE_POST_PMD \ (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) +#define SND_SOC_DAPM_PRE_POST_PMU \ + (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU) /* convenience event type detection */ #define SND_SOC_DAPM_EVENT_ON(e) \ -- GitLab From b1f373a11d25fc9a5f7679c9b85799fe09b0dc4a Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:31 +0000 Subject: [PATCH 0131/7155] ASoC: sgtl5000: Improve VAG power and mute control VAG power control is improved to fit the manual [1]. This patch fixes as minimum one bug: if customer muxes Headphone to Line-In right after boot, the VAG power remains off that leads to poor sound quality from line-in. I.e. after boot: - Connect sound source to Line-In jack; - Connect headphone to HP jack; - Run following commands: $ amixer set 'Headphone' 80% $ amixer set 'Headphone Mux' LINE_IN Change VAG power on/off control according to the following algorithm: - turn VAG power ON on the 1st incoming event. - keep it ON if there is any active VAG consumer (ADC/DAC/HP/Line-In). - turn VAG power OFF when there is the latest consumer's pre-down event come. - always delay after VAG power OFF to avoid pop. - delay after VAG power ON if the initiative consumer is Line-In, this prevents pop during line-in muxing. According to the data sheet [1], to avoid any pops/clicks, the outputs should be muted during input/output routing changes. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Cc: stable@vger.kernel.org Fixes: 9b34e6cc3bc2 ("ASoC: Add Freescale SGTL5000 codec support") Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Fabio Estevam Reviewed-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190719100524.23300-3-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 224 +++++++++++++++++++++++++++++++----- 1 file changed, 194 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index a6a4748c97f9..34cc85e49003 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -31,6 +31,13 @@ #define SGTL5000_DAP_REG_OFFSET 0x0100 #define SGTL5000_MAX_REG_OFFSET 0x013A +/* Delay for the VAG ramp up */ +#define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */ +/* Delay for the VAG ramp down */ +#define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */ + +#define SGTL5000_OUTPUTS_MUTE (SGTL5000_HP_MUTE | SGTL5000_LINE_OUT_MUTE) + /* default value of sgtl5000 registers */ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_CHIP_DIG_POWER, 0x0000 }, @@ -123,6 +130,13 @@ enum { I2S_SCLK_STRENGTH_HIGH, }; +enum { + HP_POWER_EVENT, + DAC_POWER_EVENT, + ADC_POWER_EVENT, + LAST_POWER_EVENT = ADC_POWER_EVENT +}; + /* sgtl5000 private structure in codec */ struct sgtl5000_priv { int sysclk; /* sysclk rate */ @@ -137,8 +151,109 @@ struct sgtl5000_priv { u8 micbias_voltage; u8 lrclk_strength; u8 sclk_strength; + u16 mute_state[LAST_POWER_EVENT + 1]; }; +static inline int hp_sel_input(struct snd_soc_component *component) +{ + return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) & + SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT; +} + +static inline u16 mute_output(struct snd_soc_component *component, + u16 mute_mask) +{ + u16 mute_reg = snd_soc_component_read32(component, + SGTL5000_CHIP_ANA_CTRL); + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + mute_mask, mute_mask); + return mute_reg; +} + +static inline void restore_output(struct snd_soc_component *component, + u16 mute_mask, u16 mute_reg) +{ + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + mute_mask, mute_reg); +} + +static void vag_power_on(struct snd_soc_component *component, u32 source) +{ + if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & + SGTL5000_VAG_POWERUP) + return; + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, + SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); + + /* When VAG powering on to get local loop from Line-In, the sleep + * is required to avoid loud pop. + */ + if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN && + source == HP_POWER_EVENT) + msleep(SGTL5000_VAG_POWERUP_DELAY); +} + +static int vag_power_consumers(struct snd_soc_component *component, + u16 ana_pwr_reg, u32 source) +{ + int consumers = 0; + + /* count dac/adc consumers unconditional */ + if (ana_pwr_reg & SGTL5000_DAC_POWERUP) + consumers++; + if (ana_pwr_reg & SGTL5000_ADC_POWERUP) + consumers++; + + /* + * If the event comes from HP and Line-In is selected, + * current action is 'DAC to be powered down'. + * As HP_POWERUP is not set when HP muxed to line-in, + * we need to keep VAG power ON. + */ + if (source == HP_POWER_EVENT) { + if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN) + consumers++; + } else { + if (ana_pwr_reg & SGTL5000_HP_POWERUP) + consumers++; + } + + return consumers; +} + +static void vag_power_off(struct snd_soc_component *component, u32 source) +{ + u16 ana_pwr = snd_soc_component_read32(component, + SGTL5000_CHIP_ANA_POWER); + + if (!(ana_pwr & SGTL5000_VAG_POWERUP)) + return; + + /* + * This function calls when any of VAG power consumers is disappearing. + * Thus, if there is more than one consumer at the moment, as minimum + * one consumer will definitely stay after the end of the current + * event. + * Don't clear VAG_POWERUP if 2 or more consumers of VAG present: + * - LINE_IN (for HP events) / HP (for DAC/ADC events) + * - DAC + * - ADC + * (the current consumer is disappearing right now) + */ + if (vag_power_consumers(component, ana_pwr, source) >= 2) + return; + + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, + SGTL5000_VAG_POWERUP, 0); + /* In power down case, we need wait 400-1000 ms + * when VAG fully ramped down. + * As longer we wait, as smaller pop we've got. + */ + msleep(SGTL5000_VAG_POWERDOWN_DELAY); +} + /* * mic_bias power on/off share the same register bits with * output impedance of mic bias, when power on mic bias, we @@ -170,36 +285,46 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, return 0; } -/* - * As manual described, ADC/DAC only works when VAG powerup, - * So enabled VAG before ADC/DAC up. - * In power down case, we need wait 400ms when vag fully ramped down. - */ -static int power_vag_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int vag_and_mute_control(struct snd_soc_component *component, + int event, int event_source) { - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; + static const u16 mute_mask[] = { + /* + * Mask for HP_POWER_EVENT. + * Muxing Headphones have to be wrapped with mute/unmute + * headphones only. + */ + SGTL5000_HP_MUTE, + /* + * Masks for DAC_POWER_EVENT/ADC_POWER_EVENT. + * Muxing DAC or ADC block have to wrapped with mute/unmute + * both headphones and line-out. + */ + SGTL5000_OUTPUTS_MUTE, + SGTL5000_OUTPUTS_MUTE + }; + + struct sgtl5000_priv *sgtl5000 = + snd_soc_component_get_drvdata(component); switch (event) { + case SND_SOC_DAPM_PRE_PMU: + sgtl5000->mute_state[event_source] = + mute_output(component, mute_mask[event_source]); + break; case SND_SOC_DAPM_POST_PMU: - snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); - msleep(400); + vag_power_on(component, event_source); + restore_output(component, mute_mask[event_source], + sgtl5000->mute_state[event_source]); break; - case SND_SOC_DAPM_PRE_PMD: - /* - * Don't clear VAG_POWERUP, when both DAC and ADC are - * operational to prevent inadvertently starving the - * other one of them. - */ - if ((snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & - mask) != mask) { - snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, 0); - msleep(400); - } + sgtl5000->mute_state[event_source] = + mute_output(component, mute_mask[event_source]); + vag_power_off(component, event_source); + break; + case SND_SOC_DAPM_POST_PMD: + restore_output(component, mute_mask[event_source], + sgtl5000->mute_state[event_source]); break; default: break; @@ -208,6 +333,41 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, return 0; } +/* + * Mute Headphone when power it up/down. + * Control VAG power on HP power path. + */ +static int headphone_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, HP_POWER_EVENT); +} + +/* As manual describes, ADC/DAC powering up/down requires + * to mute outputs to avoid pops. + * Control VAG power on ADC/DAC power path. + */ +static int adc_updown_depop(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, ADC_POWER_EVENT); +} + +static int dac_updown_depop(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + return vag_and_mute_control(component, event, DAC_POWER_EVENT); +} + /* input sources for ADC */ static const char *adc_mux_text[] = { "MIC_IN", "LINE_IN" @@ -280,7 +440,10 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { mic_bias_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0, + headphone_pga_event, + SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), @@ -301,11 +464,12 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { 0, SGTL5000_CHIP_DIG_POWER, 1, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), - SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), - - SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), - SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), + SND_SOC_DAPM_ADC_E("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0, + adc_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), + SND_SOC_DAPM_DAC_E("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0, + dac_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), }; /* routes for sgtl5000 */ -- GitLab From cadee10c983145c16d6c75af88f6a943b22ebeb2 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:33 +0000 Subject: [PATCH 0132/7155] ASoC: sgtl5000: Fix definition of VAG Ramp Control SGTL5000_SMALL_POP is a bit mask, not a value. Usage of correct definition makes device probing code more clear. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-4-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 2 +- sound/soc/codecs/sgtl5000.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 34cc85e49003..3f28e7862b5b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1460,7 +1460,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) /* enable small pop, introduce 400ms delay in turning off */ snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL, - SGTL5000_SMALL_POP, 1); + SGTL5000_SMALL_POP, SGTL5000_SMALL_POP); /* disable short cut detector */ snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0); diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 18cae08bbd3a..a4bf4bca95bf 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -273,7 +273,7 @@ #define SGTL5000_BIAS_CTRL_MASK 0x000e #define SGTL5000_BIAS_CTRL_SHIFT 1 #define SGTL5000_BIAS_CTRL_WIDTH 3 -#define SGTL5000_SMALL_POP 1 +#define SGTL5000_SMALL_POP 0x0001 /* * SGTL5000_CHIP_MIC_CTRL -- GitLab From 694b14554d75f2a1ae111202e71860d58b434a21 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:34 +0000 Subject: [PATCH 0133/7155] ASoC: sgtl5000: add ADC mute control This control mute/unmute the ADC input of SGTL5000 using its CHIP_ANA_CTRL register. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-5-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3f28e7862b5b..b65232521ea8 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -720,6 +720,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { SGTL5000_CHIP_ANA_ADC_CTRL, 8, 1, 0, capture_6db_attenuate), SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), + SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, 0, 1, 1), SOC_DOUBLE_TLV("Headphone Playback Volume", SGTL5000_CHIP_ANA_HP_CTRL, -- GitLab From 631bc8f0134ae9620d86a96b8c5f9445d91a2dca Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:35 +0000 Subject: [PATCH 0134/7155] ASoC: sgtl5000: Fix of unmute outputs on probe To enable "zero cross detect" for ADC/HP, change HP_ZCD_EN/ADC_ZCD_EN bits only instead of writing the whole CHIP_ANA_CTRL register. Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-6-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index b65232521ea8..23f4ae2f0723 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1453,6 +1453,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) int ret; u16 reg; struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component); + unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN; /* power up sgtl5000 */ ret = sgtl5000_set_power_regs(component); @@ -1480,9 +1481,8 @@ static int sgtl5000_probe(struct snd_soc_component *component) 0x1f); snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg); - snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL, - SGTL5000_HP_ZCD_EN | - SGTL5000_ADC_ZCD_EN); + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, + zcd_mask, zcd_mask); snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL, SGTL5000_BIAS_R_MASK, -- GitLab From b6319b061ba279577fd7030a9848fbd6a17151e3 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 19 Jul 2019 10:05:37 +0000 Subject: [PATCH 0135/7155] ASoC: sgtl5000: Fix charge pump source assignment If VDDA != VDDIO and any of them is greater than 3.1V, charge pump source can be assigned automatically [1]. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Signed-off-by: Oleksandr Suvorov Reviewed-by: Marcel Ziswiler Reviewed-by: Igor Opaniuk Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20190719100524.23300-7-oleksandr.suvorov@toradex.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 23f4ae2f0723..aa1f9637d895 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1338,12 +1338,17 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) SGTL5000_INT_OSC_EN); /* Enable VDDC charge pump */ ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; - } else if (vddio >= 3100 && vdda >= 3100) { + } else { ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; - /* VDDC use VDDIO rail */ - lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; - lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << - SGTL5000_VDDC_MAN_ASSN_SHIFT; + /* + * if vddio == vdda the source of charge pump should be + * assigned manually to VDDIO + */ + if (vddio == vdda) { + lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; + lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << + SGTL5000_VDDC_MAN_ASSN_SHIFT; + } } snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); -- GitLab From 66ad66293edeb2bcc27a329f35018b18601da452 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 11 Jul 2019 10:29:36 +0200 Subject: [PATCH 0136/7155] gpio: em: use a helper variable for &pdev->dev Instead of always dereferencing &pdev->dev, just assign a helper local variable of type struct device * and use it where applicable. Signed-off-by: Bartosz Golaszewski Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-em.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index a87951293aaa..620f25b7efb4 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev) struct resource *io[2], *irq[2]; struct gpio_chip *gpio_chip; struct irq_chip *irq_chip; - const char *name = dev_name(&pdev->dev); + struct device *dev = &pdev->dev; + const char *name = dev_name(dev); unsigned int ngpios; int ret; - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; @@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev) irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (!io[0] || !io[1] || !irq[0] || !irq[1]) { - dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); + dev_err(dev, "missing IRQ or IOMEM\n"); return -EINVAL; } - p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start, + p->base0 = devm_ioremap_nocache(dev, io[0]->start, resource_size(io[0])); if (!p->base0) return -ENOMEM; - p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start, + p->base1 = devm_ioremap_nocache(dev, io[1]->start, resource_size(io[1])); if (!p->base1) return -ENOMEM; - if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { - dev_err(&pdev->dev, "Missing ngpios OF property\n"); + if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) { + dev_err(dev, "Missing ngpios OF property\n"); return -EINVAL; } gpio_chip = &p->gpio_chip; - gpio_chip->of_node = pdev->dev.of_node; + gpio_chip->of_node = dev->of_node; gpio_chip->direction_input = em_gio_direction_input; gpio_chip->get = em_gio_get; gpio_chip->direction_output = em_gio_direction_output; @@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; - gpio_chip->parent = &pdev->dev; + gpio_chip->parent = dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = -1; gpio_chip->ngpio = ngpios; @@ -333,33 +334,33 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, + p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { - dev_err(&pdev->dev, "cannot initialize irq domain\n"); + dev_err(dev, "cannot initialize irq domain\n"); return -ENXIO; } - ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove, + ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove, p->irq_domain); if (ret) return ret; - if (devm_request_irq(&pdev->dev, irq[0]->start, + if (devm_request_irq(dev, irq[0]->start, em_gio_irq_handler, 0, name, p)) { - dev_err(&pdev->dev, "failed to request low IRQ\n"); + dev_err(dev, "failed to request low IRQ\n"); return -ENOENT; } - if (devm_request_irq(&pdev->dev, irq[1]->start, + if (devm_request_irq(dev, irq[1]->start, em_gio_irq_handler, 0, name, p)) { - dev_err(&pdev->dev, "failed to request high IRQ\n"); + dev_err(dev, "failed to request high IRQ\n"); return -ENOENT; } - ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p); + ret = devm_gpiochip_add_data(dev, gpio_chip, p); if (ret) { - dev_err(&pdev->dev, "failed to add GPIO controller\n"); + dev_err(dev, "failed to add GPIO controller\n"); return ret; } -- GitLab From 588f2e2caf6795ca29d50a45ea1e1438274e75e0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:51 +0900 Subject: [PATCH 0137/7155] ALSA: firewire-lib: obsolete ctx_data.tx.first_dbc with CIP_UNALIGHED_DBC flag Recent firmware for Fireworks board module have a quirk to start transmission of CIP with non-zero value for its data block counter. In current implementation of ALSA firewire stack, the quirk is handled by 'struct amdtp_stream.ctx_data.tx.first_dbc' with value 0x02. However, the value comes from reverse engineering. It's better to handle this quirk without the explicit value. In a process to parse CIP header, the quirk of data block counter affects decision of sequence index in sequence-multiplexed data channel; i.e. MIDI conformant data channel. In Fireworks, the index is decided by the number of data blocks from top of the same CIP, thus the value of data block counter is useless. This commit adds CIP_UNALIGHED_DBC flag and obsoletes the explicit value for this quirk. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 8 ++++++-- sound/firewire/amdtp-stream.c | 3 +-- sound/firewire/amdtp-stream.h | 5 +++-- sound/firewire/fireworks/fireworks_stream.c | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index fd5d6b8ac557..99c567ded7a3 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -315,12 +315,16 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, unsigned int frames) { struct amdtp_am824 *p = s->protocol; - unsigned int f, port; int len; u8 *b; + int f; for (f = 0; f < frames; f++) { - port = (8 - s->ctx_data.tx.first_dbc + s->data_block_counter + f) % 8; + unsigned int port = f; + + if (!(s->flags & CIP_UNALIGHED_DBC)) + port += s->data_block_counter; + port %= 8; b = (u8 *)&buffer[p->midi_position]; len = b[0] - 0x80; diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 4d71d74707cf..fc1e8e5b9429 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -584,8 +584,7 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, s->data_block_counter != UINT_MAX) *dbc = s->data_block_counter; - if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && - *dbc == s->ctx_data.tx.first_dbc) || + if ((*dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || s->data_block_counter == UINT_MAX) { lost = false; } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 3942894c11ac..5d611122312b 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -33,6 +33,8 @@ * @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include * valid EOH. * @CIP_NO_HEADERS: a lack of headers in packets + * @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to + * the value of current SYT_INTERVAL; e.g. initial value is not zero. */ enum cip_flags { CIP_NONBLOCKING = 0x00, @@ -45,6 +47,7 @@ enum cip_flags { CIP_JUMBO_PAYLOAD = 0x40, CIP_HEADER_WITHOUT_EOH = 0x80, CIP_NO_HEADER = 0x100, + CIP_UNALIGHED_DBC = 0x200, }; /** @@ -119,8 +122,6 @@ struct amdtp_stream { // Fixed interval of dbc between previos/current // packets. unsigned int dbc_interval; - // Indicate the value of dbc field in a first packet. - unsigned int first_dbc; } tx; struct { // To calculate CIP data blocks and tstamp. diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index e659a0b89ba5..385fc9686365 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -146,7 +146,7 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) (efw->firmware_version == 0x5070000 || efw->firmware_version == 0x5070300 || efw->firmware_version == 0x5080000)) - efw->tx_stream.ctx_data.tx.first_dbc = 0x02; + efw->tx_stream.flags |= CIP_UNALIGHED_DBC; /* AudioFire9 always reports wrong dbs. */ if (efw->is_af9) efw->tx_stream.flags |= CIP_WRONG_DBS; -- GitLab From cdefaa44d535a9d555ac4f1925d59ae4d0ef98e8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:52 +0900 Subject: [PATCH 0138/7155] ALSA: firewire-lib: pass data block count as an argument to tracepoints event This is a preparation for future commit that 'struct amdtp_stream.data_block_count' does not represent the value of data block count for current data block. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream-trace.h | 6 +++--- sound/firewire/amdtp-stream.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 4adbbf789cbe..16c7f6605511 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -14,8 +14,8 @@ #include TRACE_EVENT(amdtp_packet, - TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), - TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), + TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int data_block_counter, unsigned int index), + TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, data_block_counter, index), TP_STRUCT__entry( __field(unsigned int, second) __field(unsigned int, cycle) @@ -47,7 +47,7 @@ TRACE_EVENT(amdtp_packet, } __entry->payload_quadlets = payload_length / sizeof(__be32); __entry->data_blocks = data_blocks; - __entry->data_block_counter = s->data_block_counter, + __entry->data_block_counter = data_block_counter, __entry->packet_index = s->packet_index; __entry->irq = !!in_interrupt(); __entry->index = index; diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fc1e8e5b9429..fe1512905a43 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -511,7 +511,7 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, } trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, - index); + s->data_block_counter, index); if (!(s->flags & CIP_DBC_IS_END_EVENT)) { s->data_block_counter = @@ -653,7 +653,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, s->data_block_counter = dbc; trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, - index); + s->data_block_counter, index); return err; } -- GitLab From ab75481202d2925a017e4cb5407b0bb49c356de8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:53 +0900 Subject: [PATCH 0139/7155] ALSA: firewire-lib: pass data block counter to data block processing layer This is a preparation for future commit that 'struct amdtp_stream.data_block_count' does not represent the value of data block count for current data block. However, data block count is required for calculation of sequence index in sequence-multiplied data channel. Some of data block processing layer require it; e.g. for AM824 data block. This commit passes data block count to the processing layer. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 24 +++++++++++++----------- sound/firewire/amdtp-stream.c | 4 ++-- sound/firewire/amdtp-stream.h | 1 + sound/firewire/digi00x/amdtp-dot.c | 16 +++++++--------- sound/firewire/fireface/amdtp-ff.c | 10 ++++------ sound/firewire/motu/amdtp-motu.c | 8 ++++---- sound/firewire/tascam/amdtp-tascam.c | 10 ++++------ 7 files changed, 35 insertions(+), 38 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 99c567ded7a3..03a7e0533131 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -284,7 +284,7 @@ static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port) } static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, - unsigned int frames) + unsigned int frames, unsigned int data_block_counter) { struct amdtp_am824 *p = s->protocol; unsigned int f, port; @@ -293,7 +293,7 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, for (f = 0; f < frames; f++) { b = (u8 *)&buffer[p->midi_position]; - port = (s->data_block_counter + f) % 8; + port = (data_block_counter + f) % 8; if (f < MAX_MIDI_RX_BLOCKS && midi_ratelimit_per_packet(s, port) && p->midi[port] != NULL && @@ -311,8 +311,8 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, } } -static void read_midi_messages(struct amdtp_stream *s, - __be32 *buffer, unsigned int frames) +static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, + unsigned int frames, unsigned int data_block_counter) { struct amdtp_am824 *p = s->protocol; int len; @@ -323,7 +323,7 @@ static void read_midi_messages(struct amdtp_stream *s, unsigned int port = f; if (!(s->flags & CIP_UNALIGHED_DBC)) - port += s->data_block_counter; + port += data_block_counter; port %= 8; b = (u8 *)&buffer[p->midi_position]; @@ -335,8 +335,9 @@ static void read_midi_messages(struct amdtp_stream *s, } } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffer, - unsigned int data_blocks, unsigned int *syt) +static unsigned int process_rx_data_blocks(struct amdtp_stream *s, + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct amdtp_am824 *p = s->protocol; struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); @@ -351,13 +352,14 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffe } if (p->midi_ports) - write_midi_messages(s, buffer, data_blocks); + write_midi_messages(s, buffer, data_blocks, data_block_counter); return pcm_frames; } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffer, - unsigned int data_blocks, unsigned int *syt) +static unsigned int process_tx_data_blocks(struct amdtp_stream *s, + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct amdtp_am824 *p = s->protocol; struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); @@ -371,7 +373,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffe } if (p->midi_ports) - read_midi_messages(s, buffer, data_blocks); + read_midi_messages(s, buffer, data_blocks, data_block_counter); return pcm_frames; } diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fe1512905a43..40de9fc9d751 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -722,7 +722,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, data_blocks = calculate_data_blocks(s, syt); buffer = s->buffer.packets[s->packet_index].buffer; pcm_frames = s->process_data_blocks(s, buffer, data_blocks, - &syt); + s->data_block_counter, &syt); build_it_pkt_header(s, cycle, &template.params, data_blocks, syt, i); @@ -776,7 +776,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, if (err >= 0) { buffer = s->buffer.packets[s->packet_index].buffer; pcm_frames = s->process_data_blocks(s, buffer, - data_blocks, &syt); + data_blocks, s->data_block_counter, &syt); if (!(s->flags & CIP_DBC_IS_END_EVENT)) { s->data_block_counter += data_blocks; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 5d611122312b..762ac3c7e902 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -99,6 +99,7 @@ typedef unsigned int (*amdtp_stream_process_data_blocks_t)( struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt); struct amdtp_stream { struct fw_unit *unit; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index 45ff73d16074..5c12973c2652 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -234,7 +234,7 @@ static inline void midi_use_bytes(struct amdtp_stream *s, } static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, - unsigned int data_blocks) + unsigned int data_blocks, unsigned int data_block_counter) { struct amdtp_dot *p = s->protocol; unsigned int f, port; @@ -242,7 +242,7 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, u8 *b; for (f = 0; f < data_blocks; f++) { - port = (s->data_block_counter + f) % 8; + port = (data_block_counter + f) % 8; b = (u8 *)&buffer[0]; len = 0; @@ -330,9 +330,8 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm; unsigned int pcm_frames; @@ -351,9 +350,8 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm; unsigned int pcm_frames; @@ -367,7 +365,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, pcm_frames = 0; } - write_midi_messages(s, buffer, data_blocks); + write_midi_messages(s, buffer, data_blocks, data_block_counter); return pcm_frames; } diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index 2938489740b4..71879922ab39 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -103,9 +103,8 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; @@ -122,9 +121,8 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 7973dedd31ef..9693f37a0032 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -299,8 +299,8 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct amdtp_motu *p = s->protocol; struct snd_pcm_substream *pcm; @@ -361,8 +361,8 @@ static void write_sph(struct amdtp_stream *s, __be32 *buffer, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct amdtp_motu *p = (struct amdtp_motu *)s->protocol; struct snd_pcm_substream *pcm; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 95fb10b7a737..3a4d1f855f79 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -166,9 +166,8 @@ static void read_status_messages(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm; @@ -182,9 +181,8 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter, unsigned int *syt) { struct snd_pcm_substream *pcm; -- GitLab From 860d798c370409efbedf66bae2d41b3cbdf14a79 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:54 +0900 Subject: [PATCH 0140/7155] ALSA: firewire-lib: operate data block counter in top level of processing for IT context In ALSA IEC 61883-1/6 packet streaming engine, two types of data block counter are supported. This commit applies code refactoring to make it explicitly for IT context. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 39 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 40de9fc9d751..c89083ccd729 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -473,12 +473,12 @@ static inline int queue_in_packet(struct amdtp_stream *s, } static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], - unsigned int syt) + unsigned int data_block_counter, unsigned int syt) { cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | (s->data_block_quadlets << CIP_DBS_SHIFT) | ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | - s->data_block_counter); + data_block_counter); cip_header[1] = cpu_to_be32(CIP_EOH | ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | @@ -487,8 +487,9 @@ static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, struct fw_iso_packet *params, - unsigned int data_blocks, unsigned int syt, - unsigned int index) + unsigned int data_blocks, + unsigned int data_block_counter, + unsigned int syt, unsigned int index) { unsigned int payload_length; __be32 *cip_header; @@ -496,14 +497,9 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; params->payload_length = payload_length; - if (s->flags & CIP_DBC_IS_END_EVENT) { - s->data_block_counter = - (s->data_block_counter + data_blocks) & 0xff; - } - if (!(s->flags & CIP_NO_HEADER)) { cip_header = (__be32 *)params->header; - generate_cip_header(s, cip_header, syt); + generate_cip_header(s, cip_header, data_block_counter, syt); params->header_length = 2 * sizeof(__be32); payload_length += params->header_length; } else { @@ -511,12 +507,7 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, } trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, - s->data_block_counter, index); - - if (!(s->flags & CIP_DBC_IS_END_EVENT)) { - s->data_block_counter = - (s->data_block_counter + data_blocks) & 0xff; - } + data_block_counter, index); } static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, @@ -709,6 +700,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, u32 cycle; unsigned int syt; unsigned int data_blocks; + unsigned int dbc; __be32 *buffer; unsigned int pcm_frames; struct { @@ -721,11 +713,20 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, syt = calculate_syt(s, cycle); data_blocks = calculate_data_blocks(s, syt); buffer = s->buffer.packets[s->packet_index].buffer; - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, - s->data_block_counter, &syt); + dbc = s->data_block_counter; + pcm_frames = s->process_data_blocks(s, buffer, data_blocks, dbc, + &syt); + + if (s->flags & CIP_DBC_IS_END_EVENT) + dbc = (dbc + data_blocks) & 0xff; build_it_pkt_header(s, cycle, &template.params, data_blocks, - syt, i); + dbc, syt, i); + + if (!(s->flags & CIP_DBC_IS_END_EVENT)) + dbc = (dbc + data_blocks) & 0xff; + + s->data_block_counter = dbc; if (queue_out_packet(s, &template.params) < 0) { cancel_stream(s); -- GitLab From a35463d1f77d9e5244d6f4953d3c7f3a27c7625e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:55 +0900 Subject: [PATCH 0141/7155] ALSA: firewire-lib: operate data block counter in top level of processing for IR context In ALSA IEC 61883-1/6 packet streaming engine, two types of data block counter are supported. This commit applies code refactoring to make it explicitly for IR context. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 53 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index c89083ccd729..3435bef97a8b 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -512,13 +512,14 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, unsigned int payload_length, - unsigned int *data_blocks, unsigned int *dbc, - unsigned int *syt) + unsigned int *data_blocks, + unsigned int *data_block_counter, unsigned int *syt) { u32 cip_header[2]; unsigned int sph; unsigned int fmt; unsigned int fdf; + unsigned int dbc; bool lost; cip_header[0] = be32_to_cpu(buf[0]); @@ -570,16 +571,16 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, } /* Check data block counter continuity */ - *dbc = cip_header[0] & CIP_DBC_MASK; + dbc = cip_header[0] & CIP_DBC_MASK; if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && - s->data_block_counter != UINT_MAX) - *dbc = s->data_block_counter; + *data_block_counter != UINT_MAX) + dbc = *data_block_counter; - if ((*dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || - s->data_block_counter == UINT_MAX) { + if ((dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || + *data_block_counter == UINT_MAX) { lost = false; } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { - lost = *dbc != s->data_block_counter; + lost = dbc != *data_block_counter; } else { unsigned int dbc_interval; @@ -588,13 +589,13 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, else dbc_interval = *data_blocks; - lost = *dbc != ((s->data_block_counter + dbc_interval) & 0xff); + lost = dbc != ((*data_block_counter + dbc_interval) & 0xff); } if (lost) { dev_err(&s->unit->device, "Detect discontinuity of CIP: %02X %02X\n", - s->data_block_counter, *dbc); + *data_block_counter, dbc); return -EIO; } @@ -606,10 +607,10 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, unsigned int *payload_length, - unsigned int *data_blocks, unsigned int *syt, - unsigned int index) + unsigned int *data_blocks, + unsigned int *data_block_counter, + unsigned int *syt, unsigned int index) { - unsigned int dbc; const __be32 *cip_header; int err; @@ -625,7 +626,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, if (!(s->flags & CIP_NO_HEADER)) { cip_header = ctx_header + 2; err = check_cip_header(s, cip_header, *payload_length, - data_blocks, &dbc, syt); + data_blocks, data_block_counter, syt); if (err < 0) return err; } else { @@ -635,16 +636,12 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, s->data_block_quadlets; *syt = 0; - if (s->data_block_counter != UINT_MAX) - dbc = s->data_block_counter; - else - dbc = 0; + if (*data_block_counter == UINT_MAX) + *data_block_counter = 0; } - s->data_block_counter = dbc; - trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, - s->data_block_counter, index); + *data_block_counter, index); return err; } @@ -761,6 +758,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, u32 cycle; unsigned int payload_length; unsigned int data_blocks; + unsigned int dbc; unsigned int syt; __be32 *buffer; unsigned int pcm_frames = 0; @@ -769,22 +767,23 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, int err; cycle = compute_cycle_count(ctx_header[1]); + dbc = s->data_block_counter; err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, - &data_blocks, &syt, i); + &data_blocks, &dbc, &syt, i); if (err < 0 && err != -EAGAIN) break; if (err >= 0) { buffer = s->buffer.packets[s->packet_index].buffer; pcm_frames = s->process_data_blocks(s, buffer, - data_blocks, s->data_block_counter, &syt); + data_blocks, dbc, &syt); - if (!(s->flags & CIP_DBC_IS_END_EVENT)) { - s->data_block_counter += data_blocks; - s->data_block_counter &= 0xff; - } + if (!(s->flags & CIP_DBC_IS_END_EVENT)) + dbc = (dbc + data_blocks) & 0xff; } + s->data_block_counter = dbc; + if (queue_in_packet(s, ¶ms) < 0) break; -- GitLab From 3baf30532f94030244a31a275b546d042656c535 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:56 +0900 Subject: [PATCH 0142/7155] ALSA: firewire-lib: add syt_override member for some protocols Some protocols don't use syt field of CIP header to represent presentation timestamp. For such protocol, ALSA IEC 61883-1/6 packet streaming engine uses a pointer into local variable for the value of syt to call data block processing layer. However, it can decide the value when initializing packet streaming layer. This commit adds 'syt_override' member for packet streaming layer. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 6 ++++++ sound/firewire/amdtp-stream.h | 1 + sound/firewire/motu/amdtp-motu.c | 8 +++++++- sound/firewire/tascam/amdtp-tascam.c | 8 ++++++-- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 3435bef97a8b..6242240cd8ee 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -104,6 +104,9 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, s->fmt = fmt; s->process_data_blocks = process_data_blocks; + if (dir == AMDTP_OUT_STREAM) + s->ctx_data.rx.syt_override = -1; + return 0; } EXPORT_SYMBOL(amdtp_stream_init); @@ -717,6 +720,9 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, if (s->flags & CIP_DBC_IS_END_EVENT) dbc = (dbc + data_blocks) & 0xff; + if (s->ctx_data.rx.syt_override >= 0) + syt = s->ctx_data.rx.syt_override; + build_it_pkt_header(s, cycle, &template.params, data_blocks, dbc, syt, i); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 762ac3c7e902..5b9d4212e202 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -133,6 +133,7 @@ struct amdtp_stream { // To generate CIP header. unsigned int fdf; + int syt_override; } rx; } ctx_data; diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 9693f37a0032..683873699885 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -428,7 +428,13 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, return err; s->sph = 1; - s->ctx_data.rx.fdf = MOTU_FDF_AM824; + + if (dir == AMDTP_OUT_STREAM) { + // Use fixed value for FDF field. + s->ctx_data.rx.fdf = MOTU_FDF_AM824; + // Not used. + s->ctx_data.rx.syt_override = 0xffff; + } return 0; } diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 3a4d1f855f79..8fba6fb8ba8a 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -220,8 +220,12 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, if (err < 0) return 0; - /* Use fixed value for FDF field. */ - s->ctx_data.rx.fdf = 0x00; + if (dir == AMDTP_OUT_STREAM) { + // Use fixed value for FDF field. + s->ctx_data.rx.fdf = 0x00; + // Not used. + s->ctx_data.rx.syt_override = 0x0000; + } /* This protocol uses fixed number of data channels for PCM samples. */ p = s->protocol; -- GitLab From 600c8018df605a91575aef6811cf927e2d933d30 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:57 +0900 Subject: [PATCH 0143/7155] ALSA: firewire-lib: pass no syt information to data block processing layer In a previous commit, the variable passed from packet streaming layer for syt variable is useless. This commit obsoletes it. In my future work, the syt information is passed to data block processing layer by another way. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 8 ++++---- sound/firewire/amdtp-stream.c | 5 ++--- sound/firewire/amdtp-stream.h | 3 +-- sound/firewire/digi00x/amdtp-dot.c | 8 ++++---- sound/firewire/fireface/amdtp-ff.c | 8 ++++---- sound/firewire/motu/amdtp-motu.c | 11 ++++------- sound/firewire/tascam/amdtp-tascam.c | 11 ++++------- 7 files changed, 23 insertions(+), 31 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 03a7e0533131..21068b23d528 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -336,8 +336,8 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct amdtp_am824 *p = s->protocol; struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); @@ -358,8 +358,8 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct amdtp_am824 *p = s->protocol; struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 6242240cd8ee..c8543cdb3c8c 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -714,8 +714,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, data_blocks = calculate_data_blocks(s, syt); buffer = s->buffer.packets[s->packet_index].buffer; dbc = s->data_block_counter; - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, dbc, - &syt); + pcm_frames = s->process_data_blocks(s, buffer, data_blocks, dbc); if (s->flags & CIP_DBC_IS_END_EVENT) dbc = (dbc + data_blocks) & 0xff; @@ -782,7 +781,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, if (err >= 0) { buffer = s->buffer.packets[s->packet_index].buffer; pcm_frames = s->process_data_blocks(s, buffer, - data_blocks, dbc, &syt); + data_blocks, dbc); if (!(s->flags & CIP_DBC_IS_END_EVENT)) dbc = (dbc + data_blocks) & 0xff; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 5b9d4212e202..5996cc60f166 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -99,8 +99,7 @@ typedef unsigned int (*amdtp_stream_process_data_blocks_t)( struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, - unsigned int *syt); + unsigned int data_block_counter); struct amdtp_stream { struct fw_unit *unit; enum cip_flags flags; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index 5c12973c2652..c296d1017ed3 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -330,8 +330,8 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm; unsigned int pcm_frames; @@ -350,8 +350,8 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm; unsigned int pcm_frames; diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index 71879922ab39..31a60dff94ac 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -103,8 +103,8 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; @@ -121,8 +121,8 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 683873699885..30d5f87119cc 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -299,8 +299,8 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct amdtp_motu *p = s->protocol; struct snd_pcm_substream *pcm; @@ -361,15 +361,12 @@ static void write_sph(struct amdtp_stream *s, __be32 *buffer, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct amdtp_motu *p = (struct amdtp_motu *)s->protocol; struct snd_pcm_substream *pcm; - /* Not used. */ - *syt = 0xffff; - /* TODO: how to interact control messages between userspace? */ if (p->midi_ports) diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 8fba6fb8ba8a..bc1f2d2120b4 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -166,8 +166,8 @@ static void read_status_messages(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm; @@ -181,14 +181,11 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter, unsigned int *syt) + __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_counter) { struct snd_pcm_substream *pcm; - /* This field is not used. */ - *syt = 0x0000; - pcm = READ_ONCE(s->pcm); if (pcm) write_pcm_s32(s, pcm, buffer, data_blocks); -- GitLab From 04130cf8e296bfbd65d2673a5975bd0f200b941d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:58 +0900 Subject: [PATCH 0144/7155] ALSA: firewire-lib: add list of packet descriptor In current implementation of ALSA IEC 61883-1/6 packet streaming engine, 16 packets are handled in one interrupt of isochronous context of OHCI 1394. Overall packet processing runs for each. However, this is not better in a point to split the processing into several parts. This commit is an attempt to add intermediate representation for parameters required for the parts. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 15 ++++++++++++--- sound/firewire/amdtp-stream.h | 9 +++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index c8543cdb3c8c..2bea15151d4a 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -936,6 +936,13 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) else s->tag = TAG_CIP; + s->pkt_descs = kcalloc(INTERRUPT_INTERVAL, sizeof(*s->pkt_descs), + GFP_KERNEL); + if (!s->pkt_descs) { + err = -ENOMEM; + goto err_context; + } + s->packet_index = 0; do { struct fw_iso_packet params; @@ -947,7 +954,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) err = queue_out_packet(s, ¶ms); } if (err < 0) - goto err_context; + goto err_pkt_descs; } while (s->packet_index > 0); /* NOTE: TAG1 matches CIP. This just affects in stream. */ @@ -958,12 +965,13 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) s->callbacked = false; err = fw_iso_context_start(s->context, -1, 0, tag); if (err < 0) - goto err_context; + goto err_pkt_descs; mutex_unlock(&s->mutex); return 0; - +err_pkt_descs: + kfree(s->pkt_descs); err_context: fw_iso_context_destroy(s->context); s->context = ERR_PTR(-1); @@ -1059,6 +1067,7 @@ void amdtp_stream_stop(struct amdtp_stream *s) fw_iso_context_destroy(s->context); s->context = ERR_PTR(-1); iso_packets_buffer_destroy(&s->buffer, s->unit); + kfree(s->pkt_descs); s->callbacked = false; diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 5996cc60f166..73c492c9a5d5 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -94,6 +94,14 @@ enum amdtp_stream_direction { AMDTP_IN_STREAM }; +struct pkt_desc { + u32 cycle; + u32 syt; + unsigned int data_blocks; + unsigned int data_block_counter; + __be32 *ctx_payload; +}; + struct amdtp_stream; typedef unsigned int (*amdtp_stream_process_data_blocks_t)( struct amdtp_stream *s, @@ -110,6 +118,7 @@ struct amdtp_stream { struct fw_iso_context *context; struct iso_packets_buffer buffer; int packet_index; + struct pkt_desc *pkt_descs; int tag; union { struct { -- GitLab From f4f6ae7b7c1fdbaaaecafd183fabcf5314df2b59 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:36:59 +0900 Subject: [PATCH 0145/7155] ALSA: firewire-lib: use packet descriptor for IT context This commit uses packet descriptor to parse headers of IT context and generate timing information for ideal sequence. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 68 ++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 2bea15151d4a..463c7a340a45 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -676,6 +676,38 @@ static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp) return increment_cycle_count(cycle, QUEUE_LENGTH); } +static void generate_ideal_pkt_descs(struct amdtp_stream *s, + struct pkt_desc *descs, + const __be32 *ctx_header, + unsigned int packets) +{ + unsigned int dbc = s->data_block_counter; + int i; + + for (i = 0; i < packets; ++i) { + struct pkt_desc *desc = descs + i; + unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; + + desc->cycle = compute_cycle_count(*ctx_header); + desc->syt = calculate_syt(s, desc->cycle); + desc->data_blocks = calculate_data_blocks(s, desc->syt); + + if (s->flags & CIP_DBC_IS_END_EVENT) + dbc = (dbc + desc->data_blocks) & 0xff; + + desc->data_block_counter = dbc; + + if (!(s->flags & CIP_DBC_IS_END_EVENT)) + dbc = (dbc + desc->data_blocks) & 0xff; + + desc->ctx_payload = s->buffer.packets[index].buffer; + + ++ctx_header; + } + + s->data_block_counter = dbc; +} + static inline void cancel_stream(struct amdtp_stream *s) { s->packet_index = -1; @@ -696,39 +728,29 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, if (s->packet_index < 0) return; + generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); + for (i = 0; i < packets; ++i) { - u32 cycle; - unsigned int syt; - unsigned int data_blocks; - unsigned int dbc; - __be32 *buffer; + const struct pkt_desc *desc = s->pkt_descs + i; unsigned int pcm_frames; + unsigned int syt; struct { struct fw_iso_packet params; __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; } template = { {0}, {0} }; struct snd_pcm_substream *pcm; - cycle = compute_it_cycle(*ctx_header); - syt = calculate_syt(s, cycle); - data_blocks = calculate_data_blocks(s, syt); - buffer = s->buffer.packets[s->packet_index].buffer; - dbc = s->data_block_counter; - pcm_frames = s->process_data_blocks(s, buffer, data_blocks, dbc); + pcm_frames = s->process_data_blocks(s, desc->ctx_payload, + desc->data_blocks, desc->data_block_counter); - if (s->flags & CIP_DBC_IS_END_EVENT) - dbc = (dbc + data_blocks) & 0xff; - - if (s->ctx_data.rx.syt_override >= 0) + if (s->ctx_data.rx.syt_override < 0) + syt = desc->syt; + else syt = s->ctx_data.rx.syt_override; - build_it_pkt_header(s, cycle, &template.params, data_blocks, - dbc, syt, i); - - if (!(s->flags & CIP_DBC_IS_END_EVENT)) - dbc = (dbc + data_blocks) & 0xff; - - s->data_block_counter = dbc; + build_it_pkt_header(s, desc->cycle, &template.params, + desc->data_blocks, desc->data_block_counter, + syt, i); if (queue_out_packet(s, &template.params) < 0) { cancel_stream(s); @@ -738,8 +760,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, pcm = READ_ONCE(s->pcm); if (pcm && pcm_frames > 0) update_pcm_pointers(s, pcm, pcm_frames); - - ++ctx_header; } fw_iso_context_queue_flush(s->context); -- GitLab From 753e717986c24b60962367708479555212730b9f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:00 +0900 Subject: [PATCH 0146/7155] ALSA: firewire-lib: use packet descriptor for IR context This commit uses packet descriptor to parse headers of IR context and parse timing information for sequence transferred by target device. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 96 +++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 463c7a340a45..68502a8864b9 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -602,6 +602,8 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, return -EIO; } + *data_block_counter = dbc; + *syt = cip_header[1] & CIP_SYT_MASK; return 0; @@ -676,6 +678,48 @@ static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp) return increment_cycle_count(cycle, QUEUE_LENGTH); } +static int generate_device_pkt_descs(struct amdtp_stream *s, + struct pkt_desc *descs, + const __be32 *ctx_header, + unsigned int packets) +{ + unsigned int dbc = s->data_block_counter; + int i; + int err; + + for (i = 0; i < packets; ++i) { + struct pkt_desc *desc = descs + i; + unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; + unsigned int cycle; + unsigned int payload_length; + unsigned int data_blocks; + unsigned int syt; + + cycle = compute_cycle_count(ctx_header[1]); + + err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, + &data_blocks, &dbc, &syt, i); + if (err < 0) + return err; + + desc->cycle = cycle; + desc->syt = syt; + desc->data_blocks = data_blocks; + desc->data_block_counter = dbc; + desc->ctx_payload = s->buffer.packets[index].buffer; + + if (!(s->flags & CIP_DBC_IS_END_EVENT)) + dbc = (dbc + desc->data_blocks) & 0xff; + + ctx_header += + s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); + } + + s->data_block_counter = dbc; + + return 0; +} + static void generate_ideal_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, const __be32 *ctx_header, @@ -770,8 +814,10 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, void *private_data) { struct amdtp_stream *s = private_data; - unsigned int i, packets; + unsigned int packets; __be32 *ctx_header = header; + int i; + int err; if (s->packet_index < 0) return; @@ -779,50 +825,34 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, // The number of packets in buffer. packets = header_length / s->ctx_data.tx.ctx_header_size; + err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets); + if (err < 0) { + if (err != -EAGAIN) { + cancel_stream(s); + return; + } + } + for (i = 0; i < packets; i++) { - u32 cycle; - unsigned int payload_length; - unsigned int data_blocks; - unsigned int dbc; - unsigned int syt; - __be32 *buffer; + const struct pkt_desc *desc = s->pkt_descs; unsigned int pcm_frames = 0; struct fw_iso_packet params = {0}; struct snd_pcm_substream *pcm; - int err; - - cycle = compute_cycle_count(ctx_header[1]); - dbc = s->data_block_counter; - err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, - &data_blocks, &dbc, &syt, i); - if (err < 0 && err != -EAGAIN) - break; if (err >= 0) { - buffer = s->buffer.packets[s->packet_index].buffer; - pcm_frames = s->process_data_blocks(s, buffer, - data_blocks, dbc); - - if (!(s->flags & CIP_DBC_IS_END_EVENT)) - dbc = (dbc + data_blocks) & 0xff; + pcm_frames = s->process_data_blocks(s, + desc->ctx_payload, desc->data_blocks, + desc->data_block_counter); } - s->data_block_counter = dbc; - - if (queue_in_packet(s, ¶ms) < 0) - break; + if (queue_in_packet(s, ¶ms) < 0) { + cancel_stream(s); + return; + } pcm = READ_ONCE(s->pcm); if (pcm && pcm_frames > 0) update_pcm_pointers(s, pcm, pcm_frames); - - ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); - } - - /* Queueing error or detecting invalid payload. */ - if (i < packets) { - cancel_stream(s); - return; } fw_iso_context_queue_flush(s->context); -- GitLab From 5e2ece0fdceb02f6c47f53bef309395701a65393 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:01 +0900 Subject: [PATCH 0147/7155] ALSA: firewire-lib: code refactoring to process PCM substream This is code refactoring to separate PCM substream processing from packet queueing. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 68502a8864b9..99b89bd70bc5 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -776,16 +776,24 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = s->pkt_descs + i; + struct snd_pcm_substream *pcm; unsigned int pcm_frames; + + pcm_frames = s->process_data_blocks(s, desc->ctx_payload, + desc->data_blocks, desc->data_block_counter); + + pcm = READ_ONCE(s->pcm); + if (pcm && pcm_frames > 0) + update_pcm_pointers(s, pcm, pcm_frames); + } + + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = s->pkt_descs + i; unsigned int syt; struct { struct fw_iso_packet params; __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; } template = { {0}, {0} }; - struct snd_pcm_substream *pcm; - - pcm_frames = s->process_data_blocks(s, desc->ctx_payload, - desc->data_blocks, desc->data_block_counter); if (s->ctx_data.rx.syt_override < 0) syt = desc->syt; @@ -800,10 +808,6 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, cancel_stream(s); return; } - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); } fw_iso_context_queue_flush(s->context); @@ -831,28 +835,29 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, cancel_stream(s); return; } - } - - for (i = 0; i < packets; i++) { - const struct pkt_desc *desc = s->pkt_descs; - unsigned int pcm_frames = 0; - struct fw_iso_packet params = {0}; - struct snd_pcm_substream *pcm; + } else { + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = s->pkt_descs; + struct snd_pcm_substream *pcm; + unsigned int pcm_frames; - if (err >= 0) { pcm_frames = s->process_data_blocks(s, desc->ctx_payload, desc->data_blocks, desc->data_block_counter); + + pcm = READ_ONCE(s->pcm); + if (pcm && pcm_frames > 0) + update_pcm_pointers(s, pcm, pcm_frames); } + } + + for (i = 0; i < packets; ++i) { + struct fw_iso_packet params = {0}; if (queue_in_packet(s, ¶ms) < 0) { cancel_stream(s); return; } - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); } fw_iso_context_queue_flush(s->context); -- GitLab From 0f5cfcb24d9c931e4571e9995bbfc08cc76d5d4a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:02 +0900 Subject: [PATCH 0148/7155] ALSA: firewire-lib: code refactoring to process context payloads This is code refactoring for common processing for payloads of ishocornous context. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 47 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 99b89bd70bc5..573265113a6f 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -760,22 +760,14 @@ static inline void cancel_stream(struct amdtp_stream *s) WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); } -static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, - size_t header_length, void *header, - void *private_data) +static void process_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets) { - struct amdtp_stream *s = private_data; - const __be32 *ctx_header = header; - unsigned int packets = header_length / sizeof(*ctx_header); int i; - if (s->packet_index < 0) - return; - - generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); - for (i = 0; i < packets; ++i) { - const struct pkt_desc *desc = s->pkt_descs + i; + const struct pkt_desc *desc = descs + i; struct snd_pcm_substream *pcm; unsigned int pcm_frames; @@ -786,6 +778,23 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, if (pcm && pcm_frames > 0) update_pcm_pointers(s, pcm, pcm_frames); } +} + +static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, + void *private_data) +{ + struct amdtp_stream *s = private_data; + const __be32 *ctx_header = header; + unsigned int packets = header_length / sizeof(*ctx_header); + int i; + + if (s->packet_index < 0) + return; + + generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); + + process_ctx_payloads(s, s->pkt_descs, packets); for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = s->pkt_descs + i; @@ -836,19 +845,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, return; } } else { - for (i = 0; i < packets; ++i) { - const struct pkt_desc *desc = s->pkt_descs; - struct snd_pcm_substream *pcm; - unsigned int pcm_frames; - - pcm_frames = s->process_data_blocks(s, - desc->ctx_payload, desc->data_blocks, - desc->data_block_counter); - - pcm = READ_ONCE(s->pcm); - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - } + process_ctx_payloads(s, s->pkt_descs, packets); } for (i = 0; i < packets; ++i) { -- GitLab From d2c104a3426be9991b35c65f0f260a107c4b2942 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:03 +0900 Subject: [PATCH 0149/7155] ALSA: firewire-lib: pass packet descriptor to data block processing layer This commit changes signature of callback function to call data block processing layer with packet descriptor. At present, the layer is called per packet. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 32 +++++++++-------- sound/firewire/amdtp-stream.c | 6 ++-- sound/firewire/amdtp-stream.h | 5 ++- sound/firewire/digi00x/amdtp-dot.c | 27 +++++++------- sound/firewire/fireface/amdtp-ff.c | 23 ++++++------ sound/firewire/motu/amdtp-motu.c | 53 ++++++++++++++++------------ sound/firewire/tascam/amdtp-tascam.c | 39 +++++++++++--------- 7 files changed, 97 insertions(+), 88 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 21068b23d528..ff089ffa3374 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -336,44 +336,46 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; if (pcm) { - write_pcm_s32(s, pcm, buffer, data_blocks); - pcm_frames = data_blocks * p->frame_multiplier; + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks * p->frame_multiplier; } else { - write_pcm_silence(s, buffer, data_blocks); + write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); pcm_frames = 0; } - if (p->midi_ports) - write_midi_messages(s, buffer, data_blocks, data_block_counter); + if (p->midi_ports) { + write_midi_messages(s, desc->ctx_payload, desc->data_blocks, + desc->data_block_counter); + } return pcm_frames; } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; if (pcm) { - read_pcm_s32(s, pcm, buffer, data_blocks); - pcm_frames = data_blocks * p->frame_multiplier; + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks * p->frame_multiplier; } else { pcm_frames = 0; } - if (p->midi_ports) - read_midi_messages(s, buffer, data_blocks, data_block_counter); + if (p->midi_ports) { + read_midi_messages(s, desc->ctx_payload, desc->data_blocks, + desc->data_block_counter); + } return pcm_frames; } diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 573265113a6f..db2feb68105c 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -768,13 +768,11 @@ static void process_ctx_payloads(struct amdtp_stream *s, for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = descs + i; - struct snd_pcm_substream *pcm; + struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; - pcm_frames = s->process_data_blocks(s, desc->ctx_payload, - desc->data_blocks, desc->data_block_counter); + pcm_frames = s->process_data_blocks(s, desc, pcm); - pcm = READ_ONCE(s->pcm); if (pcm && pcm_frames > 0) update_pcm_pointers(s, pcm, pcm_frames); } diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 73c492c9a5d5..0e5b85100a04 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -105,9 +105,8 @@ struct pkt_desc { struct amdtp_stream; typedef unsigned int (*amdtp_stream_process_data_blocks_t)( struct amdtp_stream *s, - __be32 *buffer, - unsigned int data_blocks, - unsigned int data_block_counter); + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm); struct amdtp_stream { struct fw_unit *unit; enum cip_flags flags; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index c296d1017ed3..83ac4b37f26d 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -330,42 +330,39 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm; unsigned int pcm_frames; - pcm = READ_ONCE(s->pcm); if (pcm) { - read_pcm_s32(s, pcm, buffer, data_blocks); - pcm_frames = data_blocks; + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks; } else { pcm_frames = 0; } - read_midi_messages(s, buffer, data_blocks); + read_midi_messages(s, desc->ctx_payload, desc->data_blocks); return pcm_frames; } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm; unsigned int pcm_frames; - pcm = READ_ONCE(s->pcm); if (pcm) { - write_pcm_s32(s, pcm, buffer, data_blocks); - pcm_frames = data_blocks; + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks; } else { - write_pcm_silence(s, buffer, data_blocks); + write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); pcm_frames = 0; } - write_midi_messages(s, buffer, data_blocks, data_block_counter); + write_midi_messages(s, desc->ctx_payload, desc->data_blocks, + desc->data_block_counter); return pcm_frames; } diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index 31a60dff94ac..c36232fc4d3e 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -103,17 +103,18 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; if (pcm) { - write_pcm_s32(s, pcm, (__le32 *)buffer, data_blocks); - pcm_frames = data_blocks; + write_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, + desc->data_blocks); + pcm_frames = desc->data_blocks; } else { - write_pcm_silence(s, (__le32 *)buffer, data_blocks); + write_pcm_silence(s, (__le32 *)desc->ctx_payload, + desc->data_blocks); pcm_frames = 0; } @@ -121,15 +122,15 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); unsigned int pcm_frames; if (pcm) { - read_pcm_s32(s, pcm, (__le32 *)buffer, data_blocks); - pcm_frames = data_blocks; + read_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, + desc->data_blocks); + pcm_frames = desc->data_blocks; } else { pcm_frames = 0; } diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 30d5f87119cc..36ee2c1dd667 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -299,23 +299,27 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { struct amdtp_motu *p = s->protocol; - struct snd_pcm_substream *pcm; + unsigned int pcm_frames; - trace_data_block_sph(s, data_blocks, buffer); - trace_data_block_message(s, data_blocks, buffer); + trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload); + trace_data_block_message(s, desc->data_blocks, desc->ctx_payload); if (p->midi_ports) - read_midi_messages(s, buffer, data_blocks); + read_midi_messages(s, desc->ctx_payload, desc->data_blocks); - pcm = READ_ONCE(s->pcm); - if (data_blocks > 0 && pcm) - read_pcm_s32(s, pcm->runtime, buffer, data_blocks); + if (pcm) { + read_pcm_s32(s, pcm->runtime, desc->ctx_payload, + desc->data_blocks); + pcm_frames = desc->data_blocks; + } else { + pcm_frames = 0; + } - return data_blocks; + return pcm_frames; } static inline void compute_next_elapse_from_start(struct amdtp_motu *p) @@ -361,29 +365,32 @@ static void write_sph(struct amdtp_stream *s, __be32 *buffer, } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { struct amdtp_motu *p = (struct amdtp_motu *)s->protocol; - struct snd_pcm_substream *pcm; + unsigned int pcm_frames; /* TODO: how to interact control messages between userspace? */ if (p->midi_ports) - write_midi_messages(s, buffer, data_blocks); + write_midi_messages(s, desc->ctx_payload, desc->data_blocks); - pcm = READ_ONCE(s->pcm); - if (pcm) - write_pcm_s32(s, pcm->runtime, buffer, data_blocks); - else - write_pcm_silence(s, buffer, data_blocks); + if (pcm) { + write_pcm_s32(s, pcm->runtime, desc->ctx_payload, + desc->data_blocks); + pcm_frames = desc->data_blocks; + } else { + write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); + pcm_frames = 0; + } - write_sph(s, buffer, data_blocks); + write_sph(s, desc->ctx_payload, desc->data_blocks); - trace_data_block_sph(s, data_blocks, buffer); - trace_data_block_message(s, data_blocks, buffer); + trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload); + trace_data_block_message(s, desc->data_blocks, desc->ctx_payload); - return data_blocks; + return pcm_frames; } int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index bc1f2d2120b4..970b1c4a8ea6 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -166,33 +166,38 @@ static void read_status_messages(struct amdtp_stream *s, } static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm; + unsigned int pcm_frames; - pcm = READ_ONCE(s->pcm); - if (data_blocks > 0 && pcm) - read_pcm_s32(s, pcm, buffer, data_blocks); + if (pcm) { + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks; + } else { + pcm_frames = 0; + } - read_status_messages(s, buffer, data_blocks); + read_status_messages(s, desc->ctx_payload, desc->data_blocks); - return data_blocks; + return pcm_frames; } static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - __be32 *buffer, unsigned int data_blocks, - unsigned int data_block_counter) + const struct pkt_desc *desc, + struct snd_pcm_substream *pcm) { - struct snd_pcm_substream *pcm; + unsigned int pcm_frames; - pcm = READ_ONCE(s->pcm); - if (pcm) - write_pcm_s32(s, pcm, buffer, data_blocks); - else - write_pcm_silence(s, buffer, data_blocks); + if (pcm) { + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + pcm_frames = desc->data_blocks; + } else { + write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); + pcm_frames = 0; + } - return data_blocks; + return pcm_frames; } int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, -- GitLab From 9fc90644cae9c0abfcce0576ed0a14cca67f69b9 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:04 +0900 Subject: [PATCH 0150/7155] ALSA: firewire-lib: code refactoring for AM824 data block processing layer This is code refactoring for AM824 data block processing layer so that it can receive list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 51 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index ff089ffa3374..5d2952a1a9b2 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -146,19 +146,24 @@ void amdtp_am824_set_midi_position(struct amdtp_stream *s, } EXPORT_SYMBOL_GPL(amdtp_am824_set_midi_position); -static void write_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) +static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_am824 *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; const u32 *src; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < frames; ++i) { for (c = 0; c < channels; ++c) { @@ -172,19 +177,24 @@ static void write_pcm_s32(struct amdtp_stream *s, } } -static void read_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) +static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_am824 *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; u32 *dst; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; dst = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < frames; ++i) { for (c = 0; c < channels; ++c) { @@ -340,14 +350,14 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks * p->frame_multiplier; } else { write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - pcm_frames = 0; } if (p->midi_ports) { @@ -363,13 +373,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks * p->frame_multiplier; - } else { - pcm_frames = 0; } if (p->midi_ports) { -- GitLab From bb473966774a79ae9a826f721059496d9b393acc Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:05 +0900 Subject: [PATCH 0151/7155] ALSA: firewire-digi00x: code refactoring for DOT data block processing layer This is code refactoring for DOT data block processing layer so that it can receive list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/amdtp-dot.c | 45 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index 83ac4b37f26d..cef5caf97236 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -143,17 +143,23 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, } static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_dot *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; const u32 *src; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; buffer++; for (i = 0; i < frames; ++i) { @@ -169,17 +175,23 @@ static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, } static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_dot *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; u32 *dst; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; dst = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; buffer++; for (i = 0; i < frames; ++i) { @@ -333,13 +345,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks; - } else { - pcm_frames = 0; } read_midi_messages(s, desc->ctx_payload, desc->data_blocks); @@ -351,14 +362,14 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks; } else { write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - pcm_frames = 0; } write_midi_messages(s, desc->ctx_payload, desc->data_blocks, -- GitLab From 806653b70ee21b374d2844d144609b2e0070a86b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:06 +0900 Subject: [PATCH 0152/7155] ALSA: firewire-tascam: code refactoring for TASCAM data block processing layer This is code refactoring for TASCAM data block processing layer so that it can receive list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/amdtp-tascam.c | 55 ++++++++++++++++------------ 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 970b1c4a8ea6..3c9abf422f24 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -32,19 +32,24 @@ int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) return amdtp_stream_set_parameters(s, rate, data_channels); } -static void write_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) +static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_tscm *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; const u32 *src; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < frames; ++i) { for (c = 0; c < channels; ++c) { @@ -57,19 +62,24 @@ static void write_pcm_s32(struct amdtp_stream *s, } } -static void read_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) +static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_tscm *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; u32 *dst; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; dst = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; /* The first data channel is for event counter. */ buffer += 1; @@ -169,13 +179,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); - pcm_frames = desc->data_blocks; - } else { - pcm_frames = 0; + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); + pcm_frames += desc->data_blocks; } read_status_messages(s, desc->ctx_payload, desc->data_blocks); @@ -187,14 +196,14 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks); - pcm_frames = desc->data_blocks; + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); + pcm_frames += desc->data_blocks; } else { write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - pcm_frames = 0; } return pcm_frames; -- GitLab From 00d004db6493c62b8bbd7073a9b3b7290cbe0cea Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:07 +0900 Subject: [PATCH 0153/7155] ALSA: firewire-motu: code refactoring for MOTU data block processing layer This is code refactoring for MOTU data block processing layer so that it can receive list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/amdtp-motu.c | 57 ++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 36ee2c1dd667..21c6bfdf47c0 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -117,19 +117,25 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, return 0; } -static void read_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_runtime *runtime, - __be32 *buffer, unsigned int data_blocks) +static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int data_blocks, + unsigned int pcm_frames) { struct amdtp_motu *p = s->protocol; - unsigned int channels, remaining_frames, i, c; + unsigned int channels = p->pcm_chunks; + struct snd_pcm_runtime *runtime = pcm->runtime; + unsigned int pcm_buffer_pointer; + int remaining_frames; u8 *byte; u32 *dst; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_chunks; dst = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < data_blocks; ++i) { byte = (u8 *)buffer + p->pcm_byte_offset; @@ -147,19 +153,25 @@ static void read_pcm_s32(struct amdtp_stream *s, } } -static void write_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_runtime *runtime, - __be32 *buffer, unsigned int data_blocks) +static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __be32 *buffer, unsigned int data_blocks, + unsigned int pcm_frames) { struct amdtp_motu *p = s->protocol; - unsigned int channels, remaining_frames, i, c; + unsigned int channels = p->pcm_chunks; + struct snd_pcm_runtime *runtime = pcm->runtime; + unsigned int pcm_buffer_pointer; + int remaining_frames; u8 *byte; const u32 *src; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_chunks; src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < data_blocks; ++i) { byte = (u8 *)buffer + p->pcm_byte_offset; @@ -303,7 +315,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, struct snd_pcm_substream *pcm) { struct amdtp_motu *p = s->protocol; - unsigned int pcm_frames; + unsigned int pcm_frames = 0; trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload); trace_data_block_message(s, desc->data_blocks, desc->ctx_payload); @@ -312,11 +324,9 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, read_midi_messages(s, desc->ctx_payload, desc->data_blocks); if (pcm) { - read_pcm_s32(s, pcm->runtime, desc->ctx_payload, - desc->data_blocks); + read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks; - } else { - pcm_frames = 0; } return pcm_frames; @@ -368,8 +378,8 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - struct amdtp_motu *p = (struct amdtp_motu *)s->protocol; - unsigned int pcm_frames; + struct amdtp_motu *p = s->protocol; + unsigned int pcm_frames = 0; /* TODO: how to interact control messages between userspace? */ @@ -377,12 +387,11 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, write_midi_messages(s, desc->ctx_payload, desc->data_blocks); if (pcm) { - write_pcm_s32(s, pcm->runtime, desc->ctx_payload, - desc->data_blocks); + write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, + pcm_frames); pcm_frames = desc->data_blocks; } else { write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - pcm_frames = 0; } write_sph(s, desc->ctx_payload, desc->data_blocks); -- GitLab From 4731c672c930e490515f1747fb34d56d61ae57ac Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:08 +0900 Subject: [PATCH 0154/7155] ALSA: fireface: code refactoring for FF data block processing layer This is code refactoring for FF data block processing layer so that it can receive list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/amdtp-ff.c | 49 +++++++++++++++++------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index c36232fc4d3e..cb2073cf146b 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -27,19 +27,24 @@ int amdtp_ff_set_parameters(struct amdtp_stream *s, unsigned int rate, return amdtp_stream_set_parameters(s, rate, data_channels); } -static void write_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __le32 *buffer, unsigned int frames) +static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __le32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_ff *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; const u32 *src; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < frames; ++i) { for (c = 0; c < channels; ++c) { @@ -52,19 +57,24 @@ static void write_pcm_s32(struct amdtp_stream *s, } } -static void read_pcm_s32(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __le32 *buffer, unsigned int frames) +static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, + __le32 *buffer, unsigned int frames, + unsigned int pcm_frames) { struct amdtp_ff *p = s->protocol; + unsigned int channels = p->pcm_channels; struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; + unsigned int pcm_buffer_pointer; + int remaining_frames; u32 *dst; + int i, c; + + pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; + pcm_buffer_pointer %= runtime->buffer_size; - channels = p->pcm_channels; dst = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; + frames_to_bytes(runtime, pcm_buffer_pointer); + remaining_frames = runtime->buffer_size - pcm_buffer_pointer; for (i = 0; i < frames; ++i) { for (c = 0; c < channels; ++c) { @@ -106,16 +116,15 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { write_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, - desc->data_blocks); + desc->data_blocks, pcm_frames); pcm_frames = desc->data_blocks; } else { write_pcm_silence(s, (__le32 *)desc->ctx_payload, desc->data_blocks); - pcm_frames = 0; } return pcm_frames; @@ -125,14 +134,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, const struct pkt_desc *desc, struct snd_pcm_substream *pcm) { - unsigned int pcm_frames; + unsigned int pcm_frames = 0; if (pcm) { read_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, - desc->data_blocks); + desc->data_blocks, pcm_frames); pcm_frames = desc->data_blocks; - } else { - pcm_frames = 0; } return pcm_frames; -- GitLab From 9a738ad1b1a64ef6d8271d8d42d715b75db6eb0d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:09 +0900 Subject: [PATCH 0155/7155] ALSA: firewire-lib: process payload of isoc context according to packet descriptors This commit changes each of data block processing layer so that it receives list of packet descriptor. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-am824.c | 71 +++++++++++++++----------- sound/firewire/amdtp-stream.c | 25 ++++----- sound/firewire/amdtp-stream.h | 7 +-- sound/firewire/digi00x/amdtp-dot.c | 66 ++++++++++++++---------- sound/firewire/fireface/amdtp-ff.c | 55 ++++++++++++-------- sound/firewire/motu/amdtp-motu.c | 76 ++++++++++++++++------------ sound/firewire/tascam/amdtp-tascam.c | 60 +++++++++++++--------- 7 files changed, 212 insertions(+), 148 deletions(-) diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index 5d2952a1a9b2..67d735e9a6a4 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -345,45 +345,59 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, } } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; unsigned int pcm_frames = 0; + int i; - if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks * p->frame_multiplier; - } else { - write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - } + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - if (p->midi_ports) { - write_midi_messages(s, desc->ctx_payload, desc->data_blocks, - desc->data_block_counter); + if (pcm) { + write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks * p->frame_multiplier; + } else { + write_pcm_silence(s, buf, data_blocks); + } + + if (p->midi_ports) { + write_midi_messages(s, buf, data_blocks, + desc->data_block_counter); + } } return pcm_frames; } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { struct amdtp_am824 *p = s->protocol; unsigned int pcm_frames = 0; + int i; - if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks * p->frame_multiplier; - } + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; + + if (pcm) { + read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks * p->frame_multiplier; + } - if (p->midi_ports) { - read_midi_messages(s, desc->ctx_payload, desc->data_blocks, - desc->data_block_counter); + if (p->midi_ports) { + read_midi_messages(s, buf, data_blocks, + desc->data_block_counter); + } } return pcm_frames; @@ -400,15 +414,14 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, enum cip_flags flags) { - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; if (dir == AMDTP_IN_STREAM) - process_data_blocks = process_tx_data_blocks; + process_ctx_payloads = process_ir_ctx_payloads; else - process_data_blocks = process_rx_data_blocks; + process_ctx_payloads = process_it_ctx_payloads; return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, - process_data_blocks, - sizeof(struct amdtp_am824)); + process_ctx_payloads, sizeof(struct amdtp_am824)); } EXPORT_SYMBOL_GPL(amdtp_am824_init); diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index db2feb68105c..369e75e33120 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -74,16 +74,16 @@ static void pcm_period_tasklet(unsigned long data); * @dir: the direction of stream * @flags: the packet transmission method to use * @fmt: the value of fmt field in CIP header - * @process_data_blocks: callback handler to process data blocks + * @process_ctx_payloads: callback handler to process payloads of isoc context * @protocol_size: the size to allocate newly for protocol */ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, enum cip_flags flags, unsigned int fmt, - amdtp_stream_process_data_blocks_t process_data_blocks, + amdtp_stream_process_ctx_payloads_t process_ctx_payloads, unsigned int protocol_size) { - if (process_data_blocks == NULL) + if (process_ctx_payloads == NULL) return -EINVAL; s->protocol = kzalloc(protocol_size, GFP_KERNEL); @@ -102,7 +102,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, s->callbacked = false; s->fmt = fmt; - s->process_data_blocks = process_data_blocks; + s->process_ctx_payloads = process_ctx_payloads; if (dir == AMDTP_OUT_STREAM) s->ctx_data.rx.syt_override = -1; @@ -764,18 +764,13 @@ static void process_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *descs, unsigned int packets) { - int i; - - for (i = 0; i < packets; ++i) { - const struct pkt_desc *desc = descs + i; - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); - unsigned int pcm_frames; - - pcm_frames = s->process_data_blocks(s, desc, pcm); + struct snd_pcm_substream *pcm; + unsigned int pcm_frames; - if (pcm && pcm_frames > 0) - update_pcm_pointers(s, pcm, pcm_frames); - } + pcm = READ_ONCE(s->pcm); + pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm); + if (pcm) + update_pcm_pointers(s, pcm, pcm_frames); } static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 0e5b85100a04..50041fa884d9 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -103,9 +103,10 @@ struct pkt_desc { }; struct amdtp_stream; -typedef unsigned int (*amdtp_stream_process_data_blocks_t)( +typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)( struct amdtp_stream *s, const struct pkt_desc *desc, + unsigned int packets, struct snd_pcm_substream *pcm); struct amdtp_stream { struct fw_unit *unit; @@ -168,13 +169,13 @@ struct amdtp_stream { /* For backends to process data blocks. */ void *protocol; - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; }; int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, enum cip_flags flags, unsigned int fmt, - amdtp_stream_process_data_blocks_t process_data_blocks, + amdtp_stream_process_ctx_payloads_t process_ctx_payloads, unsigned int protocol_size); void amdtp_stream_destroy(struct amdtp_stream *s); diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index cef5caf97236..d613642a2ce3 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -341,39 +341,53 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, WRITE_ONCE(p->midi[port], midi); } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; + int i; - if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks; - } + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - read_midi_messages(s, desc->ctx_payload, desc->data_blocks); + if (pcm) { + read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } + + read_midi_messages(s, buf, data_blocks); + } return pcm_frames; } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; + int i; - if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks; - } else { - write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - } + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - write_midi_messages(s, desc->ctx_payload, desc->data_blocks, - desc->data_block_counter); + if (pcm) { + write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } else { + write_pcm_silence(s, buf, data_blocks); + } + + write_midi_messages(s, buf, data_blocks, + desc->data_block_counter); + } return pcm_frames; } @@ -381,20 +395,20 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir) { - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; enum cip_flags flags; - /* Use different mode between incoming/outgoing. */ + // Use different mode between incoming/outgoing. if (dir == AMDTP_IN_STREAM) { flags = CIP_NONBLOCKING; - process_data_blocks = process_tx_data_blocks; + process_ctx_payloads = process_ir_ctx_payloads; } else { flags = CIP_BLOCKING; - process_data_blocks = process_rx_data_blocks; + process_ctx_payloads = process_it_ctx_payloads; } return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, - process_data_blocks, sizeof(struct amdtp_dot)); + process_ctx_payloads, sizeof(struct amdtp_dot)); } void amdtp_dot_reset(struct amdtp_stream *s) diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index cb2073cf146b..119c0076b17a 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -112,34 +112,47 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, return amdtp_stream_add_pcm_hw_constraints(s, runtime); } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, +static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; - - if (pcm) { - write_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, - desc->data_blocks, pcm_frames); - pcm_frames = desc->data_blocks; - } else { - write_pcm_silence(s, (__le32 *)desc->ctx_payload, - desc->data_blocks); + int i; + + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __le32 *buf = (__le32 *)desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; + + if (pcm) { + write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } else { + write_pcm_silence(s, buf, data_blocks); + } } return pcm_frames; } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; + int i; - if (pcm) { - read_pcm_s32(s, pcm, (__le32 *)desc->ctx_payload, - desc->data_blocks, pcm_frames); - pcm_frames = desc->data_blocks; + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __le32 *buf = (__le32 *)desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; + + if (pcm) { + read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } } return pcm_frames; @@ -148,13 +161,13 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir) { - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; if (dir == AMDTP_IN_STREAM) - process_data_blocks = process_tx_data_blocks; + process_ctx_payloads = process_ir_ctx_payloads; else - process_data_blocks = process_rx_data_blocks; + process_ctx_payloads = process_it_ctx_payloads; return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0, - process_data_blocks, sizeof(struct amdtp_ff)); + process_ctx_payloads, sizeof(struct amdtp_ff)); } diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 21c6bfdf47c0..05a6e218b0ad 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -310,23 +310,30 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, } } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { struct amdtp_motu *p = s->protocol; unsigned int pcm_frames = 0; + int i; + + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload); - trace_data_block_message(s, desc->data_blocks, desc->ctx_payload); + trace_data_block_sph(s, data_blocks, buf); + trace_data_block_message(s, data_blocks, buf); - if (p->midi_ports) - read_midi_messages(s, desc->ctx_payload, desc->data_blocks); + if (p->midi_ports) + read_midi_messages(s, buf, data_blocks); - if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks; + if (pcm) { + read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } } return pcm_frames; @@ -374,30 +381,37 @@ static void write_sph(struct amdtp_stream *s, __be32 *buffer, } } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { struct amdtp_motu *p = s->protocol; unsigned int pcm_frames = 0; + int i; - /* TODO: how to interact control messages between userspace? */ + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - if (p->midi_ports) - write_midi_messages(s, desc->ctx_payload, desc->data_blocks); + // TODO: how to interact control messages between userspace? - if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames = desc->data_blocks; - } else { - write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); - } + if (p->midi_ports) + write_midi_messages(s, buf, data_blocks); - write_sph(s, desc->ctx_payload, desc->data_blocks); + if (pcm) { + write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } else { + write_pcm_silence(s, buf, data_blocks); + } - trace_data_block_sph(s, desc->data_blocks, desc->ctx_payload); - trace_data_block_message(s, desc->data_blocks, desc->ctx_payload); + write_sph(s, buf, data_blocks); + + trace_data_block_sph(s, data_blocks, buf); + trace_data_block_message(s, data_blocks, buf); + } return pcm_frames; } @@ -406,13 +420,13 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, const struct snd_motu_protocol *const protocol) { - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; int fmt = CIP_FMT_MOTU; int flags = CIP_BLOCKING; int err; if (dir == AMDTP_IN_STREAM) { - process_data_blocks = process_tx_data_blocks; + process_ctx_payloads = process_ir_ctx_payloads; /* * Units of version 3 transmits packets with invalid CIP header @@ -431,11 +445,11 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, CIP_SKIP_DBC_ZERO_CHECK; } } else { - process_data_blocks = process_rx_data_blocks; + process_ctx_payloads = process_it_ctx_payloads; flags |= CIP_DBC_IS_END_EVENT; } - err = amdtp_stream_init(s, unit, dir, flags, fmt, process_data_blocks, + err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads, sizeof(struct amdtp_motu)); if (err < 0) return err; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 3c9abf422f24..e80bb84c43f6 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -175,35 +175,49 @@ static void read_status_messages(struct amdtp_stream *s, } } -static unsigned int process_tx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; + int i; - if (pcm) { - read_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames += desc->data_blocks; - } + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; - read_status_messages(s, desc->ctx_payload, desc->data_blocks); + if (pcm) { + read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } + + read_status_messages(s, buf, data_blocks); + } return pcm_frames; } -static unsigned int process_rx_data_blocks(struct amdtp_stream *s, - const struct pkt_desc *desc, - struct snd_pcm_substream *pcm) +static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets, + struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; + int i; - if (pcm) { - write_pcm_s32(s, pcm, desc->ctx_payload, desc->data_blocks, - pcm_frames); - pcm_frames += desc->data_blocks; - } else { - write_pcm_silence(s, desc->ctx_payload, desc->data_blocks); + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; + + if (pcm) { + write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); + pcm_frames += data_blocks; + } else { + write_pcm_silence(s, buf, data_blocks); + } } return pcm_frames; @@ -212,22 +226,22 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, unsigned int pcm_channels) { - amdtp_stream_process_data_blocks_t process_data_blocks; + amdtp_stream_process_ctx_payloads_t process_ctx_payloads; struct amdtp_tscm *p; unsigned int fmt; int err; if (dir == AMDTP_IN_STREAM) { fmt = AMDTP_FMT_TSCM_TX; - process_data_blocks = process_tx_data_blocks; + process_ctx_payloads = process_ir_ctx_payloads; } else { fmt = AMDTP_FMT_TSCM_RX; - process_data_blocks = process_rx_data_blocks; + process_ctx_payloads = process_it_ctx_payloads; } err = amdtp_stream_init(s, unit, dir, - CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, - process_data_blocks, sizeof(struct amdtp_tscm)); + CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, + process_ctx_payloads, sizeof(struct amdtp_tscm)); if (err < 0) return 0; -- GitLab From d2d5a6b0253d30ef04d513447cdd00df4fa627c3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 22 Jul 2019 12:37:10 +0900 Subject: [PATCH 0156/7155] ALSA: firewire-motu: more code refactoring for MOTU data block processing layer MOTU data block processing layer has some tracepoints events. This commit is code refactoring to split probing the events from processing data blocks. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/amdtp-motu.c | 50 +++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 05a6e218b0ad..0fd36e469ad0 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -310,6 +310,22 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, } } +static void probe_tracepoints_events(struct amdtp_stream *s, + const struct pkt_desc *descs, + unsigned int packets) +{ + int i; + + for (i = 0; i < packets; ++i) { + const struct pkt_desc *desc = descs + i; + __be32 *buf = desc->ctx_payload; + unsigned int data_blocks = desc->data_blocks; + + trace_data_block_sph(s, data_blocks, buf); + trace_data_block_message(s, data_blocks, buf); + } +} + static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *descs, unsigned int packets, @@ -319,23 +335,26 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, unsigned int pcm_frames = 0; int i; + // For data block processing. for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = descs + i; __be32 *buf = desc->ctx_payload; unsigned int data_blocks = desc->data_blocks; - trace_data_block_sph(s, data_blocks, buf); - trace_data_block_message(s, data_blocks, buf); - - if (p->midi_ports) - read_midi_messages(s, buf, data_blocks); - if (pcm) { read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); pcm_frames += data_blocks; } + + if (p->midi_ports) + read_midi_messages(s, buf, data_blocks); } + // For tracepoints. + if (trace_data_block_sph_enabled() || + trace_data_block_message_enabled()) + probe_tracepoints_events(s, descs, packets); + return pcm_frames; } @@ -390,16 +409,12 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, unsigned int pcm_frames = 0; int i; + // For data block processing. for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = descs + i; __be32 *buf = desc->ctx_payload; unsigned int data_blocks = desc->data_blocks; - // TODO: how to interact control messages between userspace? - - if (p->midi_ports) - write_midi_messages(s, buf, data_blocks); - if (pcm) { write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); pcm_frames += data_blocks; @@ -407,12 +422,19 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, write_pcm_silence(s, buf, data_blocks); } - write_sph(s, buf, data_blocks); + if (p->midi_ports) + write_midi_messages(s, buf, data_blocks); - trace_data_block_sph(s, data_blocks, buf); - trace_data_block_message(s, data_blocks, buf); + // TODO: how to interact control messages between userspace? + + write_sph(s, buf, data_blocks); } + // For tracepoints. + if (trace_data_block_sph_enabled() || + trace_data_block_message_enabled()) + probe_tracepoints_events(s, descs, packets); + return pcm_frames; } -- GitLab From 5ea40f7106aaa4e2736d18075ca635389797fc16 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 16:08:16 +0200 Subject: [PATCH 0157/7155] ARM: dts: sunxi: Unify the DE2 bus clocks order The DE2 bus takes two clocks, named bus and mod according to the binding. However, the order of these clocks change from one SoC to another. Even though it might not be an issue in most cases, having consistency will help if we ever need to have some code to deal with deprecated bindings, and in general it's just better. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a83t.dtsi | 8 ++++---- arch/arm/boot/dts/sun8i-r40.dtsi | 8 ++++---- arch/arm/boot/dts/sun8i-v3s.dtsi | 8 ++++---- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 8 ++++---- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index ada6d08bc540..9d5ddb249596 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -314,10 +314,10 @@ display_clocks: clock@1000000 { compatible = "allwinner,sun8i-a83t-de2-clk"; reg = <0x01000000 0x100000>; - clocks = <&ccu CLK_PLL_DE>, - <&ccu CLK_BUS_DE>; - clock-names = "mod", - "bus"; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_PLL_DE>; + clock-names = "bus", + "mod"; resets = <&ccu RST_BUS_DE>; #clock-cells = <1>; #reset-cells = <1>; diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 6007d0cc252d..6323941b0f3e 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -119,10 +119,10 @@ compatible = "allwinner,sun8i-r40-de2-clk", "allwinner,sun8i-h3-de2-clk"; reg = <0x01000000 0x100000>; - clocks = <&ccu CLK_DE>, - <&ccu CLK_BUS_DE>; - clock-names = "mod", - "bus"; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_DE>; + clock-names = "bus", + "mod"; resets = <&ccu RST_BUS_DE>; #clock-cells = <1>; #reset-cells = <1>; diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index d7aef128acb3..20a3f11bddcc 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -106,10 +106,10 @@ display_clocks: clock@1000000 { compatible = "allwinner,sun8i-v3s-de2-clk"; reg = <0x01000000 0x100000>; - clocks = <&ccu CLK_DE>, - <&ccu CLK_BUS_DE>; - clock-names = "mod", - "bus"; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_DE>; + clock-names = "bus", + "mod"; resets = <&ccu RST_BUS_DE>; #clock-cells = <1>; #reset-cells = <1>; diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 84977d4eb97a..b1d8c8228a37 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -114,10 +114,10 @@ display_clocks: clock@1000000 { /* compatible is in per SoC .dtsi file */ reg = <0x01000000 0x100000>; - clocks = <&ccu CLK_DE>, - <&ccu CLK_BUS_DE>; - clock-names = "mod", - "bus"; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_DE>; + clock-names = "bus", + "mod"; resets = <&ccu RST_BUS_DE>; #clock-cells = <1>; #reset-cells = <1>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 9cc9bdde81ac..60afacfe141d 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -228,10 +228,10 @@ display_clocks: clock@0 { compatible = "allwinner,sun50i-a64-de2-clk"; reg = <0x0 0x100000>; - clocks = <&ccu CLK_DE>, - <&ccu CLK_BUS_DE>; - clock-names = "mod", - "bus"; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_DE>; + clock-names = "bus", + "mod"; resets = <&ccu RST_BUS_DE>; #clock-cells = <1>; #reset-cells = <1>; -- GitLab From 042c805545d04f8d358475c83a54178da14f60ed Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 16:08:17 +0200 Subject: [PATCH 0158/7155] arm64: dts: allwinner: h6: Fix SID node name The SID node one the H6 doesn't have a standard node name. Switch to the one we use for the other SoCs. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 7628a7c83096..0f571798fc95 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -215,7 +215,7 @@ #dma-cells = <1>; }; - sid: sid@3006000 { + sid: efuse@3006000 { compatible = "allwinner,sun50i-h6-sid"; reg = <0x03006000 0x400>; }; -- GitLab From 9c71b9eb3cb25856e29f0486eae9ee1ba864ba51 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Jul 2019 10:16:44 +0200 Subject: [PATCH 0159/7155] dmaengine: omap-dma: make omap_dma_filter_fn private With the audio driver no longer referring to this function, it can be made private to the dmaengine driver itself, and the header file removed. Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/lkml/20190307151646.1016966-1-arnd@arndb.de/ Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190722081705.2084961-1-arnd@arndb.de Signed-off-by: Vinod Koul --- drivers/dma/ti/omap-dma.c | 3 ++- include/linux/omap-dma.h | 2 -- include/linux/omap-dmaengine.h | 18 ------------------ 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 include/linux/omap-dmaengine.h diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index ba2489d4ea24..49da402a1927 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -202,6 +202,7 @@ static const unsigned es_bytes[] = { [CSDP_DATA_TYPE_32] = 4, }; +static bool omap_dma_filter_fn(struct dma_chan *chan, void *param); static struct of_dma_filter_info omap_dma_info = { .filter_fn = omap_dma_filter_fn, }; @@ -1637,7 +1638,7 @@ static struct platform_driver omap_dma_driver = { }, }; -bool omap_dma_filter_fn(struct dma_chan *chan, void *param) +static bool omap_dma_filter_fn(struct dma_chan *chan, void *param) { if (chan->device->dev->driver == &omap_dma_driver.driver) { struct omap_dmadev *od = to_omap_dma_dev(chan->device); diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 840ce551e773..ba3cfbb52312 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_OMAP_DMA_H #define __LINUX_OMAP_DMA_H -#include - /* * Legacy OMAP DMA handling defines and functions * diff --git a/include/linux/omap-dmaengine.h b/include/linux/omap-dmaengine.h deleted file mode 100644 index b6e42f933c40..000000000000 --- a/include/linux/omap-dmaengine.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * OMAP DMA Engine support - */ -#ifndef __LINUX_OMAP_DMAENGINE_H -#define __LINUX_OMAP_DMAENGINE_H - -struct dma_chan; - -#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE)) -bool omap_dma_filter_fn(struct dma_chan *, void *); -#else -static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) -{ - return false; -} -#endif -#endif /* __LINUX_OMAP_DMAENGINE_H */ -- GitLab From d2bfe7b5d182dad54aedb9dcdb736e8816ead1c3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Jul 2019 10:16:45 +0200 Subject: [PATCH 0160/7155] dmaengine: edma: make edma_filter_fn private With the audio driver no longer referring to this function, it can be made private to the dmaengine driver itself, and the header file removed. Acked-by: Peter Ujfalusi Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190722081705.2084961-2-arnd@arndb.de Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 5 +++-- include/linux/edma.h | 29 ----------------------------- 2 files changed, 3 insertions(+), 31 deletions(-) delete mode 100644 include/linux/edma.h diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index ceabdea40ae0..f2549ee3fb49 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -2185,6 +2184,8 @@ static struct dma_chan *of_edma_xlate(struct of_phandle_args *dma_spec, } #endif +static bool edma_filter_fn(struct dma_chan *chan, void *param); + static int edma_probe(struct platform_device *pdev) { struct edma_soc_info *info = pdev->dev.platform_data; @@ -2524,7 +2525,7 @@ static struct platform_driver edma_tptc_driver = { }, }; -bool edma_filter_fn(struct dma_chan *chan, void *param) +static bool edma_filter_fn(struct dma_chan *chan, void *param) { bool match = false; diff --git a/include/linux/edma.h b/include/linux/edma.h deleted file mode 100644 index a1307e7827e8..000000000000 --- a/include/linux/edma.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * TI EDMA DMA engine driver - * - * Copyright 2012 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __LINUX_EDMA_H -#define __LINUX_EDMA_H - -struct dma_chan; - -#if defined(CONFIG_TI_EDMA) || defined(CONFIG_TI_EDMA_MODULE) -bool edma_filter_fn(struct dma_chan *, void *); -#else -static inline bool edma_filter_fn(struct dma_chan *chan, void *param) -{ - return false; -} -#endif - -#endif -- GitLab From 72503b25ee363827aafffc3e8d872e6a92a7e422 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 16 Jul 2019 19:15:18 +0200 Subject: [PATCH 0161/7155] dmaengine: bcm2835: Print error in case setting DMA mask fails During enabling of the RPi 4, we found out that the driver doesn't provide a helpful error message in case setting DMA mask fails. So add one. Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1563297318-4900-1-git-send-email-wahrenst@gmx.net Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 8101ff2f05c1..970f654611bd 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -871,8 +871,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) + if (rc) { + dev_err(&pdev->dev, "Unable to set DMA mask\n"); return rc; + } od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); if (!od) -- GitLab From 849b384f92bcadf2bd967f81ceeff815c9cd6af9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Jun 2019 12:52:56 -0700 Subject: [PATCH 0162/7155] Documentation: DT: arm: add support for sockets defining package boundaries The current ARM DT topology description provides the operating system with a topological view of the system that is based on leaf nodes representing either cores or threads (in an SMT system) and a hierarchical set of cluster nodes that creates a hierarchical topology view of how those cores and threads are grouped. However this hierarchical representation of clusters does not allow to describe what topology level actually represents the physical package or the socket boundary, which is a key piece of information to be used by an operating system to optimize resource allocation and scheduling. Lets add a new "socket" node type in the cpu-map node to describe the same. Signed-off-by: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Paul Walmsley --- .../devicetree/bindings/arm/topology.txt | 172 ++++++++++-------- 1 file changed, 99 insertions(+), 73 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/topology.txt b/Documentation/devicetree/bindings/arm/topology.txt index b0d80c0fb265..3b8febb46dad 100644 --- a/Documentation/devicetree/bindings/arm/topology.txt +++ b/Documentation/devicetree/bindings/arm/topology.txt @@ -9,6 +9,7 @@ ARM topology binding description In an ARM system, the hierarchy of CPUs is defined through three entities that are used to describe the layout of physical CPUs in the system: +- socket - cluster - core - thread @@ -63,21 +64,23 @@ nodes are listed. The cpu-map node's child nodes can be: - - one or more cluster nodes + - one or more cluster nodes or + - one or more socket nodes in a multi-socket system Any other configuration is considered invalid. -The cpu-map node can only contain three types of child nodes: +The cpu-map node can only contain 4 types of child nodes: +- socket node - cluster node - core node - thread node whose bindings are described in paragraph 3. -The nodes describing the CPU topology (cluster/core/thread) can only -be defined within the cpu-map node and every core/thread in the system -must be defined within the topology. Any other configuration is +The nodes describing the CPU topology (socket/cluster/core/thread) can +only be defined within the cpu-map node and every core/thread in the +system must be defined within the topology. Any other configuration is invalid and therefore must be ignored. =========================================== @@ -85,26 +88,44 @@ invalid and therefore must be ignored. =========================================== cpu-map child nodes must follow a naming convention where the node name -must be "clusterN", "coreN", "threadN" depending on the node type (ie -cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes which -are siblings within a single common parent node must be given a unique and +must be "socketN", "clusterN", "coreN", "threadN" depending on the node type +(ie socket/cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes +which are siblings within a single common parent node must be given a unique and sequential N value, starting from 0). cpu-map child nodes which do not share a common parent node can have the same name (ie same number N as other cpu-map child nodes at different device tree levels) since name uniqueness will be guaranteed by the device tree hierarchy. =========================================== -3 - cluster/core/thread node bindings +3 - socket/cluster/core/thread node bindings =========================================== -Bindings for cluster/cpu/thread nodes are defined as follows: +Bindings for socket/cluster/cpu/thread nodes are defined as follows: + +- socket node + + Description: must be declared within a cpu-map node, one node + per physical socket in the system. A system can + contain single or multiple physical socket. + The association of sockets and NUMA nodes is beyond + the scope of this bindings, please refer [2] for + NUMA bindings. + + This node is optional for a single socket system. + + The socket node name must be "socketN" as described in 2.1 above. + A socket node can not be a leaf node. + + A socket node's child nodes must be one or more cluster nodes. + + Any other configuration is considered invalid. - cluster node Description: must be declared within a cpu-map node, one node per cluster. A system can contain several layers of - clustering and cluster nodes can be contained in parent - cluster nodes. + clustering within a single physical socket and cluster + nodes can be contained in parent cluster nodes. The cluster node name must be "clusterN" as described in 2.1 above. A cluster node can not be a leaf node. @@ -164,90 +185,93 @@ Bindings for cluster/cpu/thread nodes are defined as follows: 4 - Example dts =========================================== -Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters): +Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters in a single +physical socket): cpus { #size-cells = <0>; #address-cells = <2>; cpu-map { - cluster0 { + socket0 { cluster0 { - core0 { - thread0 { - cpu = <&CPU0>; - }; - thread1 { - cpu = <&CPU1>; + cluster0 { + core0 { + thread0 { + cpu = <&CPU0>; + }; + thread1 { + cpu = <&CPU1>; + }; }; - }; - core1 { - thread0 { - cpu = <&CPU2>; - }; - thread1 { - cpu = <&CPU3>; + core1 { + thread0 { + cpu = <&CPU2>; + }; + thread1 { + cpu = <&CPU3>; + }; }; }; - }; - cluster1 { - core0 { - thread0 { - cpu = <&CPU4>; - }; - thread1 { - cpu = <&CPU5>; + cluster1 { + core0 { + thread0 { + cpu = <&CPU4>; + }; + thread1 { + cpu = <&CPU5>; + }; }; - }; - - core1 { - thread0 { - cpu = <&CPU6>; - }; - thread1 { - cpu = <&CPU7>; - }; - }; - }; - }; - cluster1 { - cluster0 { - core0 { - thread0 { - cpu = <&CPU8>; - }; - thread1 { - cpu = <&CPU9>; - }; - }; - core1 { - thread0 { - cpu = <&CPU10>; - }; - thread1 { - cpu = <&CPU11>; + core1 { + thread0 { + cpu = <&CPU6>; + }; + thread1 { + cpu = <&CPU7>; + }; }; }; }; cluster1 { - core0 { - thread0 { - cpu = <&CPU12>; + cluster0 { + core0 { + thread0 { + cpu = <&CPU8>; + }; + thread1 { + cpu = <&CPU9>; + }; }; - thread1 { - cpu = <&CPU13>; + core1 { + thread0 { + cpu = <&CPU10>; + }; + thread1 { + cpu = <&CPU11>; + }; }; }; - core1 { - thread0 { - cpu = <&CPU14>; + + cluster1 { + core0 { + thread0 { + cpu = <&CPU12>; + }; + thread1 { + cpu = <&CPU13>; + }; }; - thread1 { - cpu = <&CPU15>; + core1 { + thread0 { + cpu = <&CPU14>; + }; + thread1 { + cpu = <&CPU15>; + }; }; }; }; @@ -473,3 +497,5 @@ cpus { =============================================================================== [1] ARM Linux kernel documentation Documentation/devicetree/bindings/arm/cpus.yaml +[2] Devicetree NUMA binding description + Documentation/devicetree/bindings/numa.txt -- GitLab From 6e37ccf78a53296c6c7bf426065762c27829eb84 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 17 May 2019 14:09:21 -0700 Subject: [PATCH 0163/7155] firmware: qcom_scm: Use proper types for dma mappings We need to use the proper types and convert between physical addresses and dma addresses here to avoid mismatch warnings. This is especially important on systems with a different size for dma addresses and physical addresses. Otherwise, we get the following warning: drivers/firmware/qcom_scm.c: In function "qcom_scm_assign_mem": drivers/firmware/qcom_scm.c:469:47: error: passing argument 3 of "dma_alloc_coherent" from incompatible pointer type [-Werror=incompatible-pointer-types] We also fix the size argument to dma_free_coherent() because that size doesn't need to be aligned after it's already aligned on the allocation size. In fact, dma debugging expects the same arguments to be passed to both the allocation and freeing sides of the functions so changing the size is incorrect regardless. Reported-by: Ian Jackson Cc: Ian Jackson Cc: Julien Grall Cc: Bjorn Andersson Cc: Avaneesh Kumar Dwivedi Tested-by: Bjorn Andersson Signed-off-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 2ddc118dba1b..74b84244a0db 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -440,6 +441,7 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, phys_addr_t mem_to_map_phys; phys_addr_t dest_phys; phys_addr_t ptr_phys; + dma_addr_t ptr_dma; size_t mem_to_map_sz; size_t dest_sz; size_t src_sz; @@ -457,9 +459,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(dest_sz, SZ_64); - ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL); + ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_dma, GFP_KERNEL); if (!ptr) return -ENOMEM; + ptr_phys = dma_to_phys(__scm->dev, ptr_dma); /* Fill source vmid detail */ src = ptr; @@ -489,7 +492,7 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz, ptr_phys, src_sz, dest_phys, dest_sz); - dma_free_coherent(__scm->dev, ALIGN(ptr_sz, SZ_64), ptr, ptr_phys); + dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_dma); if (ret) { dev_err(__scm->dev, "Assign memory protection call failed %d.\n", ret); -- GitLab From c8b08fc0d6f83427973b94694b7ec8855d2d1e37 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 17 May 2019 14:09:23 -0700 Subject: [PATCH 0164/7155] firmware: qcom_scm: Fix some typos in docs and printks Some words are misspelled and we put a full stop after a return value integer. Fix these things up so it doesn't look so odd. Cc: Ian Jackson Cc: Julien Grall Cc: Bjorn Andersson Cc: Avaneesh Kumar Dwivedi Signed-off-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 74b84244a0db..c7e63af91567 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -426,11 +426,11 @@ EXPORT_SYMBOL(qcom_scm_set_remote_state); * @mem_sz: size of the region. * @srcvm: vmid for current set of owners, each set bit in * flag indicate a unique owner - * @newvm: array having new owners and corrsponding permission + * @newvm: array having new owners and corresponding permission * flags * @dest_cnt: number of owners in next set. * - * Return negative errno on failure, 0 on success, with @srcvm updated. + * Return negative errno on failure or 0 on success with @srcvm updated. */ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *srcvm, @@ -495,7 +495,7 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_dma); if (ret) { dev_err(__scm->dev, - "Assign memory protection call failed %d.\n", ret); + "Assign memory protection call failed %d\n", ret); return -EINVAL; } -- GitLab From 748fd07e2b9ca4132e3d2aae25395aedc4d1aee8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 14:52:09 +0100 Subject: [PATCH 0165/7155] ASoC: madera: Read device tree configuration Read the configuration of the Madera ASoC driver from device tree. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722135209.30302-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/madera.c | 97 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 1b1be19a2f99..5f1e32a5a855 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -300,6 +300,100 @@ int madera_free_overheat(struct madera_priv *priv) } EXPORT_SYMBOL_GPL(madera_free_overheat); +static int madera_get_variable_u32_array(struct device *dev, + const char *propname, + u32 *dest, int n_max, + int multiple) +{ + int n, ret; + + n = device_property_count_u32(dev, propname); + if (n < 0) { + if (n == -EINVAL) + return 0; /* missing, ignore */ + + dev_warn(dev, "%s malformed (%d)\n", propname, n); + + return n; + } else if ((n % multiple) != 0) { + dev_warn(dev, "%s not a multiple of %d entries\n", + propname, multiple); + + return -EINVAL; + } + + if (n > n_max) + n = n_max; + + ret = device_property_read_u32_array(dev, propname, dest, n); + if (ret < 0) + return ret; + + return n; +} + +static void madera_prop_get_inmode(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + struct madera_codec_pdata *pdata = &madera->pdata.codec; + u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS]; + int n, i, in_idx, ch_idx; + + BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT); + BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS); + + n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode", + tmp, ARRAY_SIZE(tmp), + MADERA_MAX_MUXED_CHANNELS); + if (n < 0) + return; + + in_idx = 0; + ch_idx = 0; + for (i = 0; i < n; ++i) { + pdata->inmode[in_idx][ch_idx] = tmp[i]; + + if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) { + ch_idx = 0; + ++in_idx; + } + } +} + +static void madera_prop_get_pdata(struct madera_priv *priv) +{ + struct madera *madera = priv->madera; + struct madera_codec_pdata *pdata = &madera->pdata.codec; + u32 out_mono[ARRAY_SIZE(pdata->out_mono)]; + int i, n; + + madera_prop_get_inmode(priv); + + n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono", + out_mono, ARRAY_SIZE(out_mono), 1); + if (n > 0) + for (i = 0; i < n; ++i) + pdata->out_mono[i] = !!out_mono[i]; + + madera_get_variable_u32_array(madera->dev, + "cirrus,max-channels-clocked", + pdata->max_channels_clocked, + ARRAY_SIZE(pdata->max_channels_clocked), + 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt", + pdata->pdm_fmt, + ARRAY_SIZE(pdata->pdm_fmt), 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute", + pdata->pdm_mute, + ARRAY_SIZE(pdata->pdm_mute), 1); + + madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref", + pdata->dmic_ref, + ARRAY_SIZE(pdata->dmic_ref), 1); +} + int madera_core_init(struct madera_priv *priv) { int i; @@ -308,6 +402,9 @@ int madera_core_init(struct madera_priv *priv) BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); + if (!dev_get_platdata(priv->madera->dev)) + madera_prop_get_pdata(priv); + mutex_init(&priv->rate_lock); for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) -- GitLab From 124e46a86580c71e0eee8459c5da7649318118db Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 27 Jun 2019 12:52:57 -0700 Subject: [PATCH 0166/7155] dt-binding: cpu-topology: Move cpu-map to a common binding. cpu-map binding can be used to described cpu topology for both RISC-V & ARM. It makes more sense to move the binding to document to a common place. The relevant discussion can be found here. https://lkml.org/lkml/2018/11/6/19 Signed-off-by: Atish Patra Reviewed-by: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Paul Walmsley --- .../topology.txt => cpu/cpu-topology.txt} | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) rename Documentation/devicetree/bindings/{arm/topology.txt => cpu/cpu-topology.txt} (86%) diff --git a/Documentation/devicetree/bindings/arm/topology.txt b/Documentation/devicetree/bindings/cpu/cpu-topology.txt similarity index 86% rename from Documentation/devicetree/bindings/arm/topology.txt rename to Documentation/devicetree/bindings/cpu/cpu-topology.txt index 3b8febb46dad..99918189403c 100644 --- a/Documentation/devicetree/bindings/arm/topology.txt +++ b/Documentation/devicetree/bindings/cpu/cpu-topology.txt @@ -1,12 +1,12 @@ =========================================== -ARM topology binding description +CPU topology binding description =========================================== =========================================== 1 - Introduction =========================================== -In an ARM system, the hierarchy of CPUs is defined through three entities that +In a SMP system, the hierarchy of CPUs is defined through three entities that are used to describe the layout of physical CPUs in the system: - socket @@ -14,9 +14,6 @@ are used to describe the layout of physical CPUs in the system: - core - thread -The cpu nodes (bindings defined in [1]) represent the devices that -correspond to physical CPUs and are to be mapped to the hierarchy levels. - The bottom hierarchy level sits at core or thread level depending on whether symmetric multi-threading (SMT) is supported or not. @@ -25,33 +22,31 @@ threads existing in the system and map to the hierarchy level "thread" above. In systems where SMT is not supported "cpu" nodes represent all cores present in the system and map to the hierarchy level "core" above. -ARM topology bindings allow one to associate cpu nodes with hierarchical groups +CPU topology bindings allow one to associate cpu nodes with hierarchical groups corresponding to the system hierarchy; syntactically they are defined as device tree nodes. -The remainder of this document provides the topology bindings for ARM, based -on the Devicetree Specification, available from: +Currently, only ARM/RISC-V intend to use this cpu topology binding but it may be +used for any other architecture as well. -https://www.devicetree.org/specifications/ +The cpu nodes, as per bindings defined in [4], represent the devices that +correspond to physical CPUs and are to be mapped to the hierarchy levels. -If not stated otherwise, whenever a reference to a cpu node phandle is made its -value must point to a cpu node compliant with the cpu node bindings as -documented in [1]. A topology description containing phandles to cpu nodes that are not compliant -with bindings standardized in [1] is therefore considered invalid. +with bindings standardized in [4] is therefore considered invalid. =========================================== 2 - cpu-map node =========================================== -The ARM CPU topology is defined within the cpu-map node, which is a direct +The ARM/RISC-V CPU topology is defined within the cpu-map node, which is a direct child of the cpus node and provides a container where the actual topology nodes are listed. - cpu-map node - Usage: Optional - On ARM SMP systems provide CPUs topology to the OS. - ARM uniprocessor systems do not require a topology + Usage: Optional - On SMP systems provide CPUs topology to the OS. + Uniprocessor systems do not require a topology description and therefore should not define a cpu-map node. @@ -494,8 +489,65 @@ cpus { }; }; +Example 3: HiFive Unleashed (RISC-V 64 bit, 4 core system) + +{ + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,fu540g", "sifive,fu500"; + model = "sifive,hifive-unleashed-a00"; + + ... + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu-map { + socket0 { + cluster0 { + core0 { + cpu = <&CPU1>; + }; + core1 { + cpu = <&CPU2>; + }; + core2 { + cpu0 = <&CPU2>; + }; + core3 { + cpu0 = <&CPU3>; + }; + }; + }; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "sifive,rocket0", "riscv"; + reg = <0x1>; + } + + CPU2: cpu@2 { + device_type = "cpu"; + compatible = "sifive,rocket0", "riscv"; + reg = <0x2>; + } + CPU3: cpu@3 { + device_type = "cpu"; + compatible = "sifive,rocket0", "riscv"; + reg = <0x3>; + } + CPU4: cpu@4 { + device_type = "cpu"; + compatible = "sifive,rocket0", "riscv"; + reg = <0x4>; + } + } +}; =============================================================================== [1] ARM Linux kernel documentation Documentation/devicetree/bindings/arm/cpus.yaml [2] Devicetree NUMA binding description Documentation/devicetree/bindings/numa.txt +[3] RISC-V Linux kernel documentation + Documentation/devicetree/bindings/riscv/cpus.txt +[4] https://www.devicetree.org/specifications/ -- GitLab From 60c1b220d8bc6baeaf837cd60f94a331b25c26bc Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 27 Jun 2019 12:52:58 -0700 Subject: [PATCH 0167/7155] cpu-topology: Move cpu topology code to common code. Both RISC-V & ARM64 are using cpu-map device tree to describe their cpu topology. It's better to move the relevant code to a common place instead of duplicate code. To: Will Deacon To: Catalin Marinas Signed-off-by: Atish Patra [Tested on QDF2400] Tested-by: Jeffrey Hugo [Tested on Juno and other embedded platforms.] Tested-by: Sudeep Holla Reviewed-by: Sudeep Holla Acked-by: Will Deacon Acked-by: Greg Kroah-Hartman Signed-off-by: Paul Walmsley --- arch/arm64/include/asm/topology.h | 23 --- arch/arm64/kernel/topology.c | 303 +----------------------------- drivers/base/arch_topology.c | 296 +++++++++++++++++++++++++++++ include/linux/arch_topology.h | 28 +++ include/linux/topology.h | 1 + 5 files changed, 329 insertions(+), 322 deletions(-) diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 0524f2438649..a4d945db95a2 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -4,29 +4,6 @@ #include -struct cpu_topology { - int thread_id; - int core_id; - int package_id; - int llc_id; - cpumask_t thread_sibling; - cpumask_t core_sibling; - cpumask_t llc_sibling; -}; - -extern struct cpu_topology cpu_topology[NR_CPUS]; - -#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) -#define topology_core_id(cpu) (cpu_topology[cpu].core_id) -#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) -#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) -#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) - -void init_cpu_topology(void); -void store_cpu_topology(unsigned int cpuid); -void remove_cpu_topology(unsigned int cpuid); -const struct cpumask *cpu_coregroup_mask(int cpu); - #ifdef CONFIG_NUMA struct pci_bus; diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 0825c4a856e3..6b95c91e7d67 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -14,250 +14,13 @@ #include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include -static int __init get_cpu_for_node(struct device_node *node) -{ - struct device_node *cpu_node; - int cpu; - - cpu_node = of_parse_phandle(node, "cpu", 0); - if (!cpu_node) - return -1; - - cpu = of_cpu_node_to_id(cpu_node); - if (cpu >= 0) - topology_parse_cpu_capacity(cpu_node, cpu); - else - pr_crit("Unable to find CPU node for %pOF\n", cpu_node); - - of_node_put(cpu_node); - return cpu; -} - -static int __init parse_core(struct device_node *core, int package_id, - int core_id) -{ - char name[10]; - bool leaf = true; - int i = 0; - int cpu; - struct device_node *t; - - do { - snprintf(name, sizeof(name), "thread%d", i); - t = of_get_child_by_name(core, name); - if (t) { - leaf = false; - cpu = get_cpu_for_node(t); - if (cpu >= 0) { - cpu_topology[cpu].package_id = package_id; - cpu_topology[cpu].core_id = core_id; - cpu_topology[cpu].thread_id = i; - } else { - pr_err("%pOF: Can't get CPU for thread\n", - t); - of_node_put(t); - return -EINVAL; - } - of_node_put(t); - } - i++; - } while (t); - - cpu = get_cpu_for_node(core); - if (cpu >= 0) { - if (!leaf) { - pr_err("%pOF: Core has both threads and CPU\n", - core); - return -EINVAL; - } - - cpu_topology[cpu].package_id = package_id; - cpu_topology[cpu].core_id = core_id; - } else if (leaf) { - pr_err("%pOF: Can't get CPU for leaf core\n", core); - return -EINVAL; - } - - return 0; -} - -static int __init parse_cluster(struct device_node *cluster, int depth) -{ - char name[10]; - bool leaf = true; - bool has_cores = false; - struct device_node *c; - static int package_id __initdata; - int core_id = 0; - int i, ret; - - /* - * First check for child clusters; we currently ignore any - * information about the nesting of clusters and present the - * scheduler with a flat list of them. - */ - i = 0; - do { - snprintf(name, sizeof(name), "cluster%d", i); - c = of_get_child_by_name(cluster, name); - if (c) { - leaf = false; - ret = parse_cluster(c, depth + 1); - of_node_put(c); - if (ret != 0) - return ret; - } - i++; - } while (c); - - /* Now check for cores */ - i = 0; - do { - snprintf(name, sizeof(name), "core%d", i); - c = of_get_child_by_name(cluster, name); - if (c) { - has_cores = true; - - if (depth == 0) { - pr_err("%pOF: cpu-map children should be clusters\n", - c); - of_node_put(c); - return -EINVAL; - } - - if (leaf) { - ret = parse_core(c, package_id, core_id++); - } else { - pr_err("%pOF: Non-leaf cluster with core %s\n", - cluster, name); - ret = -EINVAL; - } - - of_node_put(c); - if (ret != 0) - return ret; - } - i++; - } while (c); - - if (leaf && !has_cores) - pr_warn("%pOF: empty cluster\n", cluster); - - if (leaf) - package_id++; - - return 0; -} - -static int __init parse_dt_topology(void) -{ - struct device_node *cn, *map; - int ret = 0; - int cpu; - - cn = of_find_node_by_path("/cpus"); - if (!cn) { - pr_err("No CPU information found in DT\n"); - return 0; - } - - /* - * When topology is provided cpu-map is essentially a root - * cluster with restricted subnodes. - */ - map = of_get_child_by_name(cn, "cpu-map"); - if (!map) - goto out; - - ret = parse_cluster(map, 0); - if (ret != 0) - goto out_map; - - topology_normalize_cpu_scale(); - - /* - * Check that all cores are in the topology; the SMP code will - * only mark cores described in the DT as possible. - */ - for_each_possible_cpu(cpu) - if (cpu_topology[cpu].package_id == -1) - ret = -EINVAL; - -out_map: - of_node_put(map); -out: - of_node_put(cn); - return ret; -} - -/* - * cpu topology table - */ -struct cpu_topology cpu_topology[NR_CPUS]; -EXPORT_SYMBOL_GPL(cpu_topology); - -const struct cpumask *cpu_coregroup_mask(int cpu) -{ - const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); - - /* Find the smaller of NUMA, core or LLC siblings */ - if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { - /* not numa in package, lets use the package siblings */ - core_mask = &cpu_topology[cpu].core_sibling; - } - if (cpu_topology[cpu].llc_id != -1) { - if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) - core_mask = &cpu_topology[cpu].llc_sibling; - } - - return core_mask; -} - -static void update_siblings_masks(unsigned int cpuid) -{ - struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; - int cpu; - - /* update core and thread sibling masks */ - for_each_online_cpu(cpu) { - cpu_topo = &cpu_topology[cpu]; - - if (cpuid_topo->llc_id == cpu_topo->llc_id) { - cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); - cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); - } - - if (cpuid_topo->package_id != cpu_topo->package_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id != cpu_topo->core_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); - cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); - } -} - void store_cpu_topology(unsigned int cpuid) { struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; @@ -296,59 +59,19 @@ void store_cpu_topology(unsigned int cpuid) update_siblings_masks(cpuid); } -static void clear_cpu_topology(int cpu) -{ - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; - - cpumask_clear(&cpu_topo->llc_sibling); - cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); - - cpumask_clear(&cpu_topo->core_sibling); - cpumask_set_cpu(cpu, &cpu_topo->core_sibling); - cpumask_clear(&cpu_topo->thread_sibling); - cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); -} - -static void __init reset_cpu_topology(void) -{ - unsigned int cpu; - - for_each_possible_cpu(cpu) { - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; - - cpu_topo->thread_id = -1; - cpu_topo->core_id = 0; - cpu_topo->package_id = -1; - cpu_topo->llc_id = -1; - - clear_cpu_topology(cpu); - } -} - -void remove_cpu_topology(unsigned int cpu) -{ - int sibling; - - for_each_cpu(sibling, topology_core_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); - for_each_cpu(sibling, topology_sibling_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); - for_each_cpu(sibling, topology_llc_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); - - clear_cpu_topology(cpu); -} - #ifdef CONFIG_ACPI /* * Propagate the topology information of the processor_topology_node tree to the * cpu_topology array. */ -static int __init parse_acpi_topology(void) +int __init parse_acpi_topology(void) { bool is_threaded; int cpu, topology_id; + if (acpi_disabled) + return 0; + is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; for_each_possible_cpu(cpu) { @@ -384,24 +107,6 @@ static int __init parse_acpi_topology(void) return 0; } - -#else -static inline int __init parse_acpi_topology(void) -{ - return -EINVAL; -} #endif -void __init init_cpu_topology(void) -{ - reset_cpu_topology(); - /* - * Discard anything that was parsed if we hit an error so we - * don't use partial information. - */ - if (!acpi_disabled && parse_acpi_topology()) - reset_cpu_topology(); - else if (of_have_populated_dt() && parse_dt_topology()) - reset_cpu_topology(); -} diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 63c1e76739f1..5dc0e1ddd080 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -15,6 +15,11 @@ #include #include #include +#include +#include +#include +#include +#include DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; @@ -241,3 +246,294 @@ static void parsing_done_workfn(struct work_struct *work) #else core_initcall(free_raw_capacity); #endif + +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) +static int __init get_cpu_for_node(struct device_node *node) +{ + struct device_node *cpu_node; + int cpu; + + cpu_node = of_parse_phandle(node, "cpu", 0); + if (!cpu_node) + return -1; + + cpu = of_cpu_node_to_id(cpu_node); + if (cpu >= 0) + topology_parse_cpu_capacity(cpu_node, cpu); + else + pr_crit("Unable to find CPU node for %pOF\n", cpu_node); + + of_node_put(cpu_node); + return cpu; +} + +static int __init parse_core(struct device_node *core, int package_id, + int core_id) +{ + char name[10]; + bool leaf = true; + int i = 0; + int cpu; + struct device_node *t; + + do { + snprintf(name, sizeof(name), "thread%d", i); + t = of_get_child_by_name(core, name); + if (t) { + leaf = false; + cpu = get_cpu_for_node(t); + if (cpu >= 0) { + cpu_topology[cpu].package_id = package_id; + cpu_topology[cpu].core_id = core_id; + cpu_topology[cpu].thread_id = i; + } else { + pr_err("%pOF: Can't get CPU for thread\n", + t); + of_node_put(t); + return -EINVAL; + } + of_node_put(t); + } + i++; + } while (t); + + cpu = get_cpu_for_node(core); + if (cpu >= 0) { + if (!leaf) { + pr_err("%pOF: Core has both threads and CPU\n", + core); + return -EINVAL; + } + + cpu_topology[cpu].package_id = package_id; + cpu_topology[cpu].core_id = core_id; + } else if (leaf) { + pr_err("%pOF: Can't get CPU for leaf core\n", core); + return -EINVAL; + } + + return 0; +} + +static int __init parse_cluster(struct device_node *cluster, int depth) +{ + char name[10]; + bool leaf = true; + bool has_cores = false; + struct device_node *c; + static int package_id __initdata; + int core_id = 0; + int i, ret; + + /* + * First check for child clusters; we currently ignore any + * information about the nesting of clusters and present the + * scheduler with a flat list of them. + */ + i = 0; + do { + snprintf(name, sizeof(name), "cluster%d", i); + c = of_get_child_by_name(cluster, name); + if (c) { + leaf = false; + ret = parse_cluster(c, depth + 1); + of_node_put(c); + if (ret != 0) + return ret; + } + i++; + } while (c); + + /* Now check for cores */ + i = 0; + do { + snprintf(name, sizeof(name), "core%d", i); + c = of_get_child_by_name(cluster, name); + if (c) { + has_cores = true; + + if (depth == 0) { + pr_err("%pOF: cpu-map children should be clusters\n", + c); + of_node_put(c); + return -EINVAL; + } + + if (leaf) { + ret = parse_core(c, package_id, core_id++); + } else { + pr_err("%pOF: Non-leaf cluster with core %s\n", + cluster, name); + ret = -EINVAL; + } + + of_node_put(c); + if (ret != 0) + return ret; + } + i++; + } while (c); + + if (leaf && !has_cores) + pr_warn("%pOF: empty cluster\n", cluster); + + if (leaf) + package_id++; + + return 0; +} + +static int __init parse_dt_topology(void) +{ + struct device_node *cn, *map; + int ret = 0; + int cpu; + + cn = of_find_node_by_path("/cpus"); + if (!cn) { + pr_err("No CPU information found in DT\n"); + return 0; + } + + /* + * When topology is provided cpu-map is essentially a root + * cluster with restricted subnodes. + */ + map = of_get_child_by_name(cn, "cpu-map"); + if (!map) + goto out; + + ret = parse_cluster(map, 0); + if (ret != 0) + goto out_map; + + topology_normalize_cpu_scale(); + + /* + * Check that all cores are in the topology; the SMP code will + * only mark cores described in the DT as possible. + */ + for_each_possible_cpu(cpu) + if (cpu_topology[cpu].package_id == -1) + ret = -EINVAL; + +out_map: + of_node_put(map); +out: + of_node_put(cn); + return ret; +} + +/* + * cpu topology table + */ +struct cpu_topology cpu_topology[NR_CPUS]; +EXPORT_SYMBOL_GPL(cpu_topology); + +const struct cpumask *cpu_coregroup_mask(int cpu) +{ + const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); + + /* Find the smaller of NUMA, core or LLC siblings */ + if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { + /* not numa in package, lets use the package siblings */ + core_mask = &cpu_topology[cpu].core_sibling; + } + if (cpu_topology[cpu].llc_id != -1) { + if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) + core_mask = &cpu_topology[cpu].llc_sibling; + } + + return core_mask; +} + +void update_siblings_masks(unsigned int cpuid) +{ + struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; + int cpu; + + /* update core and thread sibling masks */ + for_each_online_cpu(cpu) { + cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->llc_id == cpu_topo->llc_id) { + cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); + cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); + } + + if (cpuid_topo->package_id != cpu_topo->package_id) + continue; + + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id != cpu_topo->core_id) + continue; + + cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); + cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); + } +} + +static void clear_cpu_topology(int cpu) +{ + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + + cpumask_clear(&cpu_topo->llc_sibling); + cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); + + cpumask_clear(&cpu_topo->core_sibling); + cpumask_set_cpu(cpu, &cpu_topo->core_sibling); + cpumask_clear(&cpu_topo->thread_sibling); + cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); +} + +static void __init reset_cpu_topology(void) +{ + unsigned int cpu; + + for_each_possible_cpu(cpu) { + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + + cpu_topo->thread_id = -1; + cpu_topo->core_id = -1; + cpu_topo->package_id = -1; + cpu_topo->llc_id = -1; + + clear_cpu_topology(cpu); + } +} + +void remove_cpu_topology(unsigned int cpu) +{ + int sibling; + + for_each_cpu(sibling, topology_core_cpumask(cpu)) + cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); + for_each_cpu(sibling, topology_sibling_cpumask(cpu)) + cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); + for_each_cpu(sibling, topology_llc_cpumask(cpu)) + cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); + + clear_cpu_topology(cpu); +} + +__weak int __init parse_acpi_topology(void) +{ + return 0; +} + +void __init init_cpu_topology(void) +{ + reset_cpu_topology(); + + /* + * Discard anything that was parsed if we hit an error so we + * don't use partial information. + */ + if (parse_acpi_topology()) + reset_cpu_topology(); + else if (of_have_populated_dt() && parse_dt_topology()) + reset_cpu_topology(); +} +#endif diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 1cfe05ea1d89..ede0ce4623b4 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -33,4 +33,32 @@ unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); } +struct cpu_topology { + int thread_id; + int core_id; + int package_id; + int llc_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; + cpumask_t llc_sibling; +}; + +#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY +extern struct cpu_topology cpu_topology[NR_CPUS]; + +#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) +#define topology_core_id(cpu) (cpu_topology[cpu].core_id) +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) +#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) +#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) +void init_cpu_topology(void); +void store_cpu_topology(unsigned int cpuid); +const struct cpumask *cpu_coregroup_mask(int cpu); +#endif + +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) +void update_siblings_masks(unsigned int cpu); +#endif +void remove_cpu_topology(unsigned int cpuid); + #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ diff --git a/include/linux/topology.h b/include/linux/topology.h index 47a3e3c08036..2a19d196af28 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -27,6 +27,7 @@ #ifndef _LINUX_TOPOLOGY_H #define _LINUX_TOPOLOGY_H +#include #include #include #include -- GitLab From ca74b316df96d7c40ee3e8301065607c11c60c27 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 27 Jun 2019 12:52:59 -0700 Subject: [PATCH 0168/7155] arm: Use common cpu_topology structure and functions. Currently, ARM32 and ARM64 uses different data structures to represent their cpu topologies. Since, we are moving the ARM64 topology to common code to be used by other architectures, we can reuse that for ARM32 as well. Take this opprtunity to remove the redundant functions from ARM32 and reuse the common code instead. To: Russell King Signed-off-by: Atish Patra Tested-by: Sudeep Holla (on TC2) Reviewed-by: Sudeep Holla Signed-off-by: Paul Walmsley --- arch/arm/include/asm/topology.h | 20 ----------- arch/arm/kernel/topology.c | 60 ++++----------------------------- drivers/base/arch_topology.c | 4 ++- include/linux/arch_topology.h | 6 ++-- 4 files changed, 11 insertions(+), 79 deletions(-) diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index 2a786f54d8b8..8a0fae94d45e 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -5,26 +5,6 @@ #ifdef CONFIG_ARM_CPU_TOPOLOGY #include - -struct cputopo_arm { - int thread_id; - int core_id; - int socket_id; - cpumask_t thread_sibling; - cpumask_t core_sibling; -}; - -extern struct cputopo_arm cpu_topology[NR_CPUS]; - -#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) -#define topology_core_id(cpu) (cpu_topology[cpu].core_id) -#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) -#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) - -void init_cpu_topology(void); -void store_cpu_topology(unsigned int cpuid); -const struct cpumask *cpu_coregroup_mask(int cpu); - #include /* Replace task scheduler's default frequency-invariant accounting */ diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index d17cb1e6d679..5b9faba03afb 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -177,17 +177,6 @@ static inline void parse_dt_topology(void) {} static inline void update_cpu_capacity(unsigned int cpuid) {} #endif - /* - * cpu topology table - */ -struct cputopo_arm cpu_topology[NR_CPUS]; -EXPORT_SYMBOL_GPL(cpu_topology); - -const struct cpumask *cpu_coregroup_mask(int cpu) -{ - return &cpu_topology[cpu].core_sibling; -} - /* * The current assumption is that we can power gate each core independently. * This will be superseded by DT binding once available. @@ -197,32 +186,6 @@ const struct cpumask *cpu_corepower_mask(int cpu) return &cpu_topology[cpu].thread_sibling; } -static void update_siblings_masks(unsigned int cpuid) -{ - struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; - int cpu; - - /* update core and thread sibling masks */ - for_each_possible_cpu(cpu) { - cpu_topo = &cpu_topology[cpu]; - - if (cpuid_topo->socket_id != cpu_topo->socket_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id != cpu_topo->core_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); - } - smp_wmb(); -} - /* * store_cpu_topology is called at boot when only one cpu is running * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, @@ -230,7 +193,7 @@ static void update_siblings_masks(unsigned int cpuid) */ void store_cpu_topology(unsigned int cpuid) { - struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; unsigned int mpidr; /* If the cpu topology has been already set, just return */ @@ -250,12 +213,12 @@ void store_cpu_topology(unsigned int cpuid) /* core performance interdependency */ cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); - cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); } else { /* largely independent cores */ cpuid_topo->thread_id = -1; cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); - cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); } } else { /* @@ -265,7 +228,7 @@ void store_cpu_topology(unsigned int cpuid) */ cpuid_topo->thread_id = -1; cpuid_topo->core_id = 0; - cpuid_topo->socket_id = -1; + cpuid_topo->package_id = -1; } update_siblings_masks(cpuid); @@ -275,7 +238,7 @@ void store_cpu_topology(unsigned int cpuid) pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, cpu_topology[cpuid].core_id, - cpu_topology[cpuid].socket_id, mpidr); + cpu_topology[cpuid].package_id, mpidr); } static inline int cpu_corepower_flags(void) @@ -298,18 +261,7 @@ static struct sched_domain_topology_level arm_topology[] = { */ void __init init_cpu_topology(void) { - unsigned int cpu; - - /* init core mask and capacity */ - for_each_possible_cpu(cpu) { - struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); - - cpu_topo->thread_id = -1; - cpu_topo->core_id = -1; - cpu_topo->socket_id = -1; - cpumask_clear(&cpu_topo->core_sibling); - cpumask_clear(&cpu_topo->thread_sibling); - } + reset_cpu_topology(); smp_wmb(); parse_dt_topology(); diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 5dc0e1ddd080..b54d241a2ff5 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -423,6 +423,7 @@ static int __init parse_dt_topology(void) of_node_put(cn); return ret; } +#endif /* * cpu topology table @@ -488,7 +489,7 @@ static void clear_cpu_topology(int cpu) cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); } -static void __init reset_cpu_topology(void) +void __init reset_cpu_topology(void) { unsigned int cpu; @@ -523,6 +524,7 @@ __weak int __init parse_acpi_topology(void) return 0; } +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) void __init init_cpu_topology(void) { reset_cpu_topology(); diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index ede0ce4623b4..42f2b5126094 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -54,11 +54,9 @@ extern struct cpu_topology cpu_topology[NR_CPUS]; void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); const struct cpumask *cpu_coregroup_mask(int cpu); -#endif - -#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) void update_siblings_masks(unsigned int cpu); -#endif void remove_cpu_topology(unsigned int cpuid); +void reset_cpu_topology(void); +#endif #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ -- GitLab From 03f11f03dbfe37c0bff2768b8f2e277a29ac62b9 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 27 Jun 2019 12:53:00 -0700 Subject: [PATCH 0169/7155] RISC-V: Parse cpu topology during boot. Currently, there are no topology defined for RISC-V. Parse the cpu-map node from device tree and setup the cpu topology. CPU topology after applying the patch. $cat /sys/devices/system/cpu/cpu2/topology/core_siblings_list 0-3 $cat /sys/devices/system/cpu/cpu3/topology/core_siblings_list 0-3 $cat /sys/devices/system/cpu/cpu3/topology/physical_package_id 0 $cat /sys/devices/system/cpu/cpu3/topology/core_id 3 Signed-off-by: Atish Patra Acked-by: Sudeep Holla Signed-off-by: Paul Walmsley --- arch/riscv/Kconfig | 1 + arch/riscv/kernel/smpboot.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 59a4727ecd6c..86ee362a1375 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -48,6 +48,7 @@ config RISCV select PCI_MSI if PCI select RISCV_TIMER select GENERIC_IRQ_MULTI_HANDLER + select GENERIC_ARCH_TOPOLOGY if SMP select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_MMIOWB select HAVE_EBPF_JIT if 64BIT diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 7462a44304fe..18ae6da5115e 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -8,6 +8,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include @@ -35,6 +36,7 @@ static DECLARE_COMPLETION(cpu_running); void __init smp_prepare_boot_cpu(void) { + init_cpu_topology(); } void __init smp_prepare_cpus(unsigned int max_cpus) @@ -138,6 +140,7 @@ asmlinkage void __init smp_callin(void) trap_init(); notify_cpu_starting(smp_processor_id()); + update_siblings_masks(smp_processor_id()); set_cpu_online(smp_processor_id(), 1); /* * Remote TLB flushes are ignored while the CPU is offline, so emit -- GitLab From c181831f161c8da460b1ffa26632448323c3bfcc Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Jun 2019 12:53:01 -0700 Subject: [PATCH 0170/7155] base: arch_topology: update Kconfig help description Commit 5d777b185f6d ("arch_topology: Make cpu_capacity sysfs node as read-only") made cpu_capacity sysfs node read-only. Update the GENERIC_ARCH_TOPOLOGY Kconfig help section to reflect the same. Cc: Greg Kroah-Hartman Signed-off-by: Sudeep Holla Signed-off-by: Paul Walmsley --- drivers/base/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index dc404492381d..28b92e3cc570 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -202,7 +202,7 @@ config GENERIC_ARCH_TOPOLOGY help Enable support for architectures common topology code: e.g., parsing CPU capacity information from DT, usage of such information for - appropriate scaling, sysfs interface for changing capacity values at + appropriate scaling, sysfs interface for reading capacity values at runtime. endmenu -- GitLab From f51edcec5288556069d27ab7040a4ce8ca55b74e Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 27 Jun 2019 12:53:02 -0700 Subject: [PATCH 0171/7155] MAINTAINERS: Add an entry for generic architecture topology arm and arm64 shared lot of CPU topology related code. This was consolidated under driver/base/arch_topology.c by Juri. Now RISC-V is also started sharing the same code pulling more code from arm64 into arch_topology.c Since I was involved in the review from the beginning, I would like to assume maintenance for the same. Cc: Will Deacon Cc: Greg Kroah-Hartman Acked-by: Juri Lelli Signed-off-by: Sudeep Holla Acked-by: Greg Kroah-Hartman Signed-off-by: Paul Walmsley --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..1ed8f5c93bc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6719,6 +6719,13 @@ W: https://linuxtv.org S: Maintained F: drivers/media/radio/radio-gemtek* +GENERIC ARCHITECTURE TOPOLOGY +M: Sudeep Holla +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/base/arch_topology.c +F: include/linux/arch_topology.h + GENERIC GPIO I2C DRIVER M: Wolfram Sang S: Supported -- GitLab From 4747bd0f4179858d00498becc3b26c92c8e9724a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 07:07:45 -0400 Subject: [PATCH 0172/7155] media: v4l2-ioctl: add missing pixelformats The v4l_fill_fmtdesc() is supposed to be updated whenever a new pixelformat is added, but a bunch of recently added pixelformats were forgotten. Update the list. Also change a few lower case words to upper case to keep the same style. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart [hverkuil-cisco@xs4all.nl: changed 1-5-5-5 to 5-5-5-1 as per Laurent's suggestion] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 29 ++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index b1f4b991dba6..20cc23ef730e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1169,9 +1169,21 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_RGB444: descr = "16-bit A/XRGB 4-4-4-4"; break; case V4L2_PIX_FMT_ARGB444: descr = "16-bit ARGB 4-4-4-4"; break; case V4L2_PIX_FMT_XRGB444: descr = "16-bit XRGB 4-4-4-4"; break; + case V4L2_PIX_FMT_RGBA444: descr = "16-bit RGBA 4-4-4-4"; break; + case V4L2_PIX_FMT_RGBX444: descr = "16-bit RGBX 4-4-4-4"; break; + case V4L2_PIX_FMT_ABGR444: descr = "16-bit ABGR 4-4-4-4"; break; + case V4L2_PIX_FMT_XBGR444: descr = "16-bit XBGR 4-4-4-4"; break; + case V4L2_PIX_FMT_BGRA444: descr = "16-bit BGRA 4-4-4-4"; break; + case V4L2_PIX_FMT_BGRX444: descr = "16-bit BGRX 4-4-4-4"; break; case V4L2_PIX_FMT_RGB555: descr = "16-bit A/XRGB 1-5-5-5"; break; case V4L2_PIX_FMT_ARGB555: descr = "16-bit ARGB 1-5-5-5"; break; case V4L2_PIX_FMT_XRGB555: descr = "16-bit XRGB 1-5-5-5"; break; + case V4L2_PIX_FMT_ABGR555: descr = "16-bit ABGR 1-5-5-5"; break; + case V4L2_PIX_FMT_XBGR555: descr = "16-bit XBGR 1-5-5-5"; break; + case V4L2_PIX_FMT_RGBA555: descr = "16-bit RGBA 5-5-5-1"; break; + case V4L2_PIX_FMT_RGBX555: descr = "16-bit RGBX 5-5-5-1"; break; + case V4L2_PIX_FMT_BGRA555: descr = "16-bit BGRA 5-5-5-1"; break; + case V4L2_PIX_FMT_BGRX555: descr = "16-bit BGRX 5-5-5-1"; break; case V4L2_PIX_FMT_RGB565: descr = "16-bit RGB 5-6-5"; break; case V4L2_PIX_FMT_RGB555X: descr = "16-bit A/XRGB 1-5-5-5 BE"; break; case V4L2_PIX_FMT_ARGB555X: descr = "16-bit ARGB 1-5-5-5 BE"; break; @@ -1186,6 +1198,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_RGB32: descr = "32-bit A/XRGB 8-8-8-8"; break; case V4L2_PIX_FMT_ARGB32: descr = "32-bit ARGB 8-8-8-8"; break; case V4L2_PIX_FMT_XRGB32: descr = "32-bit XRGB 8-8-8-8"; break; + case V4L2_PIX_FMT_BGRA32: descr = "32-bit ABGR 8-8-8-8"; break; + case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break; case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; @@ -1301,13 +1317,14 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_SDR_FMT_PCU16BE: descr = "Planar Complex U16BE"; break; case V4L2_SDR_FMT_PCU18BE: descr = "Planar Complex U18BE"; break; case V4L2_SDR_FMT_PCU20BE: descr = "Planar Complex U20BE"; break; - case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit signed deltas"; break; - case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit signed deltas"; break; - case V4L2_TCH_FMT_TU16: descr = "16-bit unsigned touch data"; break; - case V4L2_TCH_FMT_TU08: descr = "8-bit unsigned touch data"; break; + case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit Signed Deltas"; break; + case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit Signed Deltas"; break; + case V4L2_TCH_FMT_TU16: descr = "16-bit Unsigned Touch Data"; break; + case V4L2_TCH_FMT_TU08: descr = "8-bit Unsigned Touch Data"; break; case V4L2_META_FMT_VSP1_HGO: descr = "R-Car VSP1 1-D Histogram"; break; case V4L2_META_FMT_VSP1_HGT: descr = "R-Car VSP1 2-D Histogram"; break; - case V4L2_META_FMT_UVC: descr = "UVC payload header metadata"; break; + case V4L2_META_FMT_UVC: descr = "UVC Payload Header Metadata"; break; + case V4L2_META_FMT_D4XX: descr = "Intel D4xx UVC Metadata"; break; default: /* Compressed formats */ @@ -1326,7 +1343,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_MPEG1: descr = "MPEG-1 ES"; break; case V4L2_PIX_FMT_MPEG2: descr = "MPEG-2 ES"; break; case V4L2_PIX_FMT_MPEG2_SLICE: descr = "MPEG-2 Parsed Slice Data"; break; - case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 part 2 ES"; break; + case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 Part 2 ES"; break; case V4L2_PIX_FMT_XVID: descr = "Xvid"; break; case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break; case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break; -- GitLab From 009cb7d5794aaf40b037857510c59847298747dd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 11 Jun 2019 09:48:54 -0400 Subject: [PATCH 0173/7155] media: media/usb: don't set description in ENUM_FMT The V4L2 core sets the description for the driver in order to ensure consistent naming. So drop the strscpy of the description in drivers. Also remove any description strings in driver-internal structures since those are no longer needed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 3 --- drivers/media/usb/airspy/airspy.c | 3 --- drivers/media/usb/au0828/au0828-video.c | 4 ---- drivers/media/usb/cpia2/cpia2_v4l.c | 23 ++++--------------- drivers/media/usb/cx231xx/cx231xx-417.c | 1 - drivers/media/usb/cx231xx/cx231xx-video.c | 2 -- drivers/media/usb/cx231xx/cx231xx.h | 1 - drivers/media/usb/em28xx/em28xx-video.c | 8 ------- drivers/media/usb/em28xx/em28xx.h | 2 -- drivers/media/usb/go7007/go7007-v4l2.c | 11 --------- drivers/media/usb/gspca/gspca.c | 9 -------- drivers/media/usb/hdpvr/hdpvr-video.c | 3 --- drivers/media/usb/msi2500/msi2500.c | 8 ------- drivers/media/usb/pwc/pwc-v4l.c | 5 ---- drivers/media/usb/s2255/s2255drv.c | 8 ------- drivers/media/usb/stk1160/stk1160-v4l.c | 2 -- drivers/media/usb/stk1160/stk1160.h | 1 - drivers/media/usb/stkwebcam/stk-webcam.c | 5 ---- drivers/media/usb/tm6000/tm6000-video.c | 4 ---- drivers/media/usb/tm6000/tm6000.h | 1 - drivers/media/usb/usbtv/usbtv-video.c | 2 -- drivers/media/usb/usbvision/usbvision-video.c | 18 +++++++-------- drivers/media/usb/usbvision/usbvision.h | 1 - drivers/media/usb/zr364xx/zr364xx.c | 7 +----- 24 files changed, 13 insertions(+), 119 deletions(-) diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index e05c21d35dc8..60d1e59d2292 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -81,11 +81,9 @@ struct rtl2832_sdr_format { static struct rtl2832_sdr_format formats[] = { { - .name = "Complex U8", .pixelformat = V4L2_SDR_FMT_CU8, .buffersize = BULK_BUFFER_SIZE, }, { - .name = "Complex U16LE (emulated)", .pixelformat = V4L2_SDR_FMT_CU16LE, .buffersize = BULK_BUFFER_SIZE * 2, }, @@ -1116,7 +1114,6 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= dev->num_formats) return -EINVAL; - strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index b35231ffe503..751703db06f5 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -71,7 +71,6 @@ static const struct v4l2_frequency_band bands_rf[] = { /* stream formats */ struct airspy_format { - char *name; u32 pixelformat; u32 buffersize; }; @@ -79,7 +78,6 @@ struct airspy_format { /* format descriptions for capture and preview */ static struct airspy_format formats[] = { { - .name = "Real U12LE", .pixelformat = V4L2_SDR_FMT_RU12LE, .buffersize = BULK_BUFFER_SIZE, }, @@ -622,7 +620,6 @@ static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= NUM_FORMATS) return -EINVAL; - strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 5e00019bce8a..e390ca57520a 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1207,10 +1207,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, dprintk(1, "%s called\n", __func__); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strscpy(f->description, "Packed YUV2", sizeof(f->description)); - - f->flags = 0; f->pixelformat = V4L2_PIX_FMT_UYVY; return 0; diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 0feae825cebb..ded7eb2dc40a 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -292,28 +292,13 @@ static int cpia2_s_input(struct file *file, void *fh, unsigned int i) static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - int index = f->index; - - if (index < 0 || index > 1) - return -EINVAL; + if (f->index > 1) + return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - switch(index) { - case 0: - strscpy(f->description, "MJPEG", sizeof(f->description)); + if (f->index == 0) f->pixelformat = V4L2_PIX_FMT_MJPEG; - break; - case 1: - strscpy(f->description, "JPEG", sizeof(f->description)); + else f->pixelformat = V4L2_PIX_FMT_JPEG; - break; - default: - return -EINVAL; - } - return 0; } diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 2475f69a2f1c..30624376679b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1592,7 +1592,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index b651ac7713ea..c77597917ca1 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -80,7 +80,6 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct cx231xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = 0, @@ -1578,7 +1577,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 3efa8ff93c1c..b007611abc37 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -121,7 +121,6 @@ #define CX23417_RESET 9 struct cx23417_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int depth; int flags; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 0512e1959394..82eb1550ec3b 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -102,37 +102,30 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct em28xx_fmt format[] = { { - .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, }, { - .name = "16 bpp RGB 565, LE", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .reg = EM28XX_OUTFMT_RGB_16_656, }, { - .name = "8 bpp Bayer RGRG..GBGB", .fourcc = V4L2_PIX_FMT_SRGGB8, .depth = 8, .reg = EM28XX_OUTFMT_RGB_8_RGRG, }, { - .name = "8 bpp Bayer BGBG..GRGR", .fourcc = V4L2_PIX_FMT_SBGGR8, .depth = 8, .reg = EM28XX_OUTFMT_RGB_8_BGBG, }, { - .name = "8 bpp Bayer GRGR..BGBG", .fourcc = V4L2_PIX_FMT_SGRBG8, .depth = 8, .reg = EM28XX_OUTFMT_RGB_8_GRGR, }, { - .name = "8 bpp Bayer GBGB..RGRG", .fourcc = V4L2_PIX_FMT_SGBRG8, .depth = 8, .reg = EM28XX_OUTFMT_RGB_8_GBGB, }, { - .name = "12 bpp YUV411", .fourcc = V4L2_PIX_FMT_YUV411P, .depth = 12, .reg = EM28XX_OUTFMT_YUV411, @@ -2011,7 +2004,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index a551072e62ed..c69e0bc46eb7 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -251,13 +251,11 @@ struct em28xx_usb_ctl { /** * struct em28xx_fmt - Struct to enumberate video formats * - * @name: Name for the video standard * @fourcc: v4l2 format id * @depth: mean number of bits to represent a pixel * @reg: em28xx register value to set it */ struct em28xx_fmt { - char *name; u32 fourcc; int depth; int reg; diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 88edfef80b40..0b3d185f3cb0 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -285,33 +285,22 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmt) { - char *desc = NULL; - switch (fmt->index) { case 0: fmt->pixelformat = V4L2_PIX_FMT_MJPEG; - desc = "Motion JPEG"; break; case 1: fmt->pixelformat = V4L2_PIX_FMT_MPEG1; - desc = "MPEG-1 ES"; break; case 2: fmt->pixelformat = V4L2_PIX_FMT_MPEG2; - desc = "MPEG-2 ES"; break; case 3: fmt->pixelformat = V4L2_PIX_FMT_MPEG4; - desc = "MPEG-4 ES"; break; default: return -EINVAL; } - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt->flags = V4L2_FMT_FLAG_COMPRESSED; - - strscpy(fmt->description, desc, sizeof(fmt->description)); - return 0; } diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index be11f7830bca..83b78a42414e 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1024,15 +1024,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; /* no more format */ fmtdesc->pixelformat = fmt_tb[index]; - if (gspca_dev->cam.cam_mode[i].sizeimage < - gspca_dev->cam.cam_mode[i].width * - gspca_dev->cam.cam_mode[i].height) - fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; - fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; - fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; - fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; - fmtdesc->description[3] = fmtdesc->pixelformat >> 24; - fmtdesc->description[4] = '\0'; return 0; } diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 5b3e67b80627..bad71d863d39 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -987,9 +987,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, if (f->index != 0) return -EINVAL; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strscpy(f->description, "MPEG2-TS with AVC/AAC streams", - sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 4c9b2a12acfb..65be6f140fe8 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -66,7 +66,6 @@ static const struct v4l2_frequency_band bands[] = { /* stream formats */ struct msi2500_format { - char *name; u32 pixelformat; u32 buffersize; }; @@ -74,27 +73,21 @@ struct msi2500_format { /* format descriptions for capture and preview */ static struct msi2500_format formats[] = { { - .name = "Complex S8", .pixelformat = V4L2_SDR_FMT_CS8, .buffersize = 3 * 1008, #if 0 }, { - .name = "10+2-bit signed", .pixelformat = MSI2500_PIX_FMT_SDR_MSI2500_384, }, { - .name = "12-bit signed", .pixelformat = MSI2500_PIX_FMT_SDR_S12, #endif }, { - .name = "Complex S14LE", .pixelformat = V4L2_SDR_FMT_CS14LE, .buffersize = 3 * 1008, }, { - .name = "Complex U8 (emulated)", .pixelformat = V4L2_SDR_FMT_CU8, .buffersize = 3 * 1008, }, { - .name = "Complex U16LE (emulated)", .pixelformat = V4L2_SDR_FMT_CU16LE, .buffersize = 3 * 1008, }, @@ -904,7 +897,6 @@ static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= dev->num_formats) return -EINVAL; - strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c index 76c498cccc49..2f135d533af6 100644 --- a/drivers/media/usb/pwc/pwc-v4l.c +++ b/drivers/media/usb/pwc/pwc-v4l.c @@ -873,14 +873,9 @@ static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc case 0: /* RAW format */ f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strscpy(f->description, "Raw Philips Webcam", - sizeof(f->description)); break; case 1: f->pixelformat = V4L2_PIX_FMT_YUV420; - strscpy(f->description, "4:2:0, planar, Y-Cb-Cr", - sizeof(f->description)); break; default: return -EINVAL; diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index aa90558479f7..533f7f064a44 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -273,7 +273,6 @@ static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) } struct s2255_fmt { - char *name; u32 fourcc; int depth; }; @@ -385,29 +384,23 @@ MODULE_DEVICE_TABLE(usb, s2255_table); /* JPEG formats must be defined last to support jpeg_enable parameter */ static const struct s2255_fmt formats[] = { { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16 }, { - .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16 }, { - .name = "4:2:2, planar, YUV422P", .fourcc = V4L2_PIX_FMT_YUV422P, .depth = 16 }, { - .name = "8bpp GREY", .fourcc = V4L2_PIX_FMT_GREY, .depth = 8 }, { - .name = "JPG", .fourcc = V4L2_PIX_FMT_JPEG, .depth = 24 }, { - .name = "MJPG", .fourcc = V4L2_PIX_FMT_MJPEG, .depth = 24 } @@ -737,7 +730,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) return -EINVAL; - strscpy(f->description, formats[index].name, sizeof(f->description)); f->pixelformat = formats[index].fourcc; return 0; } diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index b71a0f4b40b5..bcd14c66e8df 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -46,7 +46,6 @@ struct stk1160_decimate_ctrl { /* supported video standards */ static struct stk1160_fmt format[] = { { - .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, } @@ -346,7 +345,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; } diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h index 099ce2a2f021..a31ea1c80f25 100644 --- a/drivers/media/usb/stk1160/stk1160.h +++ b/drivers/media/usb/stk1160/stk1160.h @@ -102,7 +102,6 @@ struct stk1160_isoc_ctl { }; struct stk1160_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int depth; }; diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index be8041e3e6b8..cfca3c70599b 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -857,23 +857,18 @@ static int stk_vidioc_enum_fmt_vid_cap(struct file *filp, switch (fmtd->index) { case 0: fmtd->pixelformat = V4L2_PIX_FMT_RGB565; - strscpy(fmtd->description, "r5g6b5", sizeof(fmtd->description)); break; case 1: fmtd->pixelformat = V4L2_PIX_FMT_RGB565X; - strscpy(fmtd->description, "r5g6b5BE", sizeof(fmtd->description)); break; case 2: fmtd->pixelformat = V4L2_PIX_FMT_UYVY; - strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description)); break; case 3: fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; - strscpy(fmtd->description, "Raw bayer", sizeof(fmtd->description)); break; case 4: fmtd->pixelformat = V4L2_PIX_FMT_YUYV; - strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description)); break; default: return -EINVAL; diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 85fcddfb0202..c07a81a6cbe2 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -52,15 +52,12 @@ EXPORT_SYMBOL_GPL(tm6000_debug); static struct tm6000_fmt format[] = { { - .name = "4:2:2, packed, YVY2", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, }, { - .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, }, { - .name = "A/V + VBI mux packet", .fourcc = V4L2_PIX_FMT_TM6000, .depth = 16, } @@ -875,7 +872,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= ARRAY_SIZE(format)) return -EINVAL; - strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; } diff --git a/drivers/media/usb/tm6000/tm6000.h b/drivers/media/usb/tm6000/tm6000.h index 0864ed7314eb..bf396544da9a 100644 --- a/drivers/media/usb/tm6000/tm6000.h +++ b/drivers/media/usb/tm6000/tm6000.h @@ -64,7 +64,6 @@ struct tm6000_input { */ struct tm6000_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int depth; }; diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 51f784479e91..3d9284a09ee5 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -633,8 +633,6 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index > 0) return -EINVAL; - strscpy(f->description, "16 bpp YUY2, 4:2:2, packed", - sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; return 0; } diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 93750af82d98..0874526f599e 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -87,14 +87,14 @@ static int usbvision_nr; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { - { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, - { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, - { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, - { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, - { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, /* 1.5 ! */ - { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } + { 1, 1, 8, V4L2_PIX_FMT_GREY }, + { 1, 2, 16, V4L2_PIX_FMT_RGB565 }, + { 1, 3, 24, V4L2_PIX_FMT_RGB24 }, + { 1, 4, 32, V4L2_PIX_FMT_RGB32 }, + { 1, 2, 16, V4L2_PIX_FMT_RGB555 }, + { 1, 2, 16, V4L2_PIX_FMT_YUYV }, + { 1, 2, 12, V4L2_PIX_FMT_YVU420 }, /* 1.5 ! */ + { 1, 2, 16, V4L2_PIX_FMT_YUV422P } }; /* Function prototypes */ @@ -796,8 +796,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, { if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1) return -EINVAL; - strscpy(vfd->description, usbvision_v4l2_format[vfd->index].desc, - sizeof(vfd->description)); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; } diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h index 4198f972a47b..11539578e8d2 100644 --- a/drivers/media/usb/usbvision/usbvision.h +++ b/drivers/media/usb/usbvision/usbvision.h @@ -264,7 +264,6 @@ struct usbvision_v4l2_format_st { int bytes_per_pixel; int depth; int format; - char *desc; }; #define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index a9bcba4fa9c6..b8e89d550d29 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -141,7 +141,6 @@ struct zr364xx_pipeinfo { }; struct zr364xx_fmt { - char *name; u32 fourcc; int depth; }; @@ -149,7 +148,6 @@ struct zr364xx_fmt { /* image formats. */ static const struct zr364xx_fmt formats[] = { { - .name = "JPG", .fourcc = V4L2_PIX_FMT_JPEG, .depth = 24 } @@ -376,8 +374,7 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, vb); int rc; - DBG("%s, field=%d, fmt name = %s\n", __func__, field, - cam->fmt ? cam->fmt->name : ""); + DBG("%s, field=%d\n", __func__, field); if (!cam->fmt) return -EINVAL; @@ -751,8 +748,6 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, { if (f->index > 0) return -EINVAL; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strscpy(f->description, formats[0].name, sizeof(f->description)); f->pixelformat = formats[0].fourcc; return 0; } -- GitLab From 51251542c9688c399e14d852258a675b331e761b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:47:38 +0200 Subject: [PATCH 0174/7155] leds: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the LED sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 8a8e5c65b157..150421387534 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -143,3 +143,4 @@ module_platform_driver(max77650_led_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-led"); -- GitLab From 533016c870a8d0cc01478ed9e780a46e830b3b22 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 4 Jul 2019 16:57:42 -0700 Subject: [PATCH 0175/7155] leds: as3645a: Fix misuse of strlcpy Probable cut&paste typo - use the correct field size. Signed-off-by: Joe Perches Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-as3645a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index 14ab6b0e4de9..050088dff8dd 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -668,7 +668,7 @@ static int as3645a_v4l2_setup(struct as3645a *flash) }; strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name)); - strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfg.dev_name)); + strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfgind.dev_name)); flash->vf = v4l2_flash_init( &flash->client->dev, flash->flash_node, &flash->fled, NULL, -- GitLab From 730f693d79da8130c8ac18d1083cdb333fd8d7c8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 11 Jul 2019 13:24:05 +0530 Subject: [PATCH 0176/7155] leds: max77650: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence create a new label, err_node_put, which puts the previous node and returns variable rv. Modify the mid-loop return statements to instead store the return value in rv and jump to err_node_put. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Dan Murphy Acked-by: Bartosz Golaszewski Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 150421387534..04738324b3e6 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -91,8 +91,10 @@ static int max77650_led_probe(struct platform_device *pdev) for_each_child_of_node(of_node, child) { rv = of_property_read_u32(child, "reg", ®); - if (rv || reg >= MAX77650_LED_NUM_LEDS) - return -EINVAL; + if (rv || reg >= MAX77650_LED_NUM_LEDS) { + rv = -EINVAL; + goto err_node_put; + } led = &leds[reg]; led->map = map; @@ -107,8 +109,10 @@ static int max77650_led_probe(struct platform_device *pdev) } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, "max77650:%s", label); - if (!led->cdev.name) - return -ENOMEM; + if (!led->cdev.name) { + rv = -ENOMEM; + goto err_node_put; + } } of_property_read_string(child, "linux,default-trigger", @@ -116,20 +120,23 @@ static int max77650_led_probe(struct platform_device *pdev) rv = devm_of_led_classdev_register(dev, child, &led->cdev); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT); if (rv) - return rv; + goto err_node_put; } return regmap_write(map, MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); +err_node_put: + of_node_put(child); + return rv; } static struct platform_driver max77650_led_driver = { -- GitLab From 79937a4beeaeb3e2584db5dfe3a7c9ee3d5f97f6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 12:54:24 +0530 Subject: [PATCH 0177/7155] leds: ns2: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence create a new label, err_node_put, that puts the previous node before returning the required value. Edit the mid-loop return sites to instead go to this new label. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ns2.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index f92e2c07c1c6..7c500dfdcfa3 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -245,7 +245,7 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) struct device_node *np = dev->of_node; struct device_node *child; struct ns2_led *led, *leds; - int num_leds = 0; + int ret, num_leds = 0; num_leds = of_get_child_count(np); if (!num_leds) @@ -259,16 +259,16 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) led = leds; for_each_child_of_node(np, child) { const char *string; - int ret, i, num_modes; + int i, num_modes; struct ns2_led_modval *modval; ret = of_get_named_gpio(child, "cmd-gpio", 0); if (ret < 0) - return ret; + goto err_node_put; led->cmd = ret; ret = of_get_named_gpio(child, "slow-gpio", 0); if (ret < 0) - return ret; + goto err_node_put; led->slow = ret; ret = of_property_read_string(child, "label", &string); led->name = (ret == 0) ? string : child->name; @@ -281,7 +281,8 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) if (ret < 0 || ret % 3) { dev_err(dev, "Missing or malformed modes-map property\n"); - return -EINVAL; + ret = -EINVAL; + goto err_node_put; } num_modes = ret / 3; @@ -289,8 +290,10 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) num_modes, sizeof(struct ns2_led_modval), GFP_KERNEL); - if (!modval) - return -ENOMEM; + if (!modval) { + ret = -ENOMEM; + goto err_node_put; + } for (i = 0; i < num_modes; i++) { of_property_read_u32_index(child, @@ -314,6 +317,10 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) pdata->num_leds = num_leds; return 0; + +err_node_put: + of_node_put(child); + return ret; } static const struct of_device_id of_ns2_leds_match[] = { -- GitLab From ed2abfebb041473092b41527903f93390d38afa7 Mon Sep 17 00:00:00 2001 From: Nick Stoughton Date: Wed, 17 Jul 2019 14:56:06 -0700 Subject: [PATCH 0178/7155] leds: leds-lp5562 allow firmware files up to the maximum length Firmware files are in ASCII, using 2 hex characters per byte. The maximum length of a firmware string is therefore 16 (commands) * 2 (bytes per command) * 2 (characters per byte) = 64 Fixes: ff45262a85db ("leds: add new LP5562 LED driver") Signed-off-by: Nick Stoughton Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lp5562.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 37632fc63741..edb57c42e8b1 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -260,7 +260,11 @@ static void lp5562_firmware_loaded(struct lp55xx_chip *chip) { const struct firmware *fw = chip->fw; - if (fw->size > LP5562_PROGRAM_LENGTH) { + /* + * the firmware is encoded in ascii hex character, with 2 chars + * per byte + */ + if (fw->size > (LP5562_PROGRAM_LENGTH * 2)) { dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n", fw->size); return; -- GitLab From 2169e6daa1ffa6e9869fcc56ff7df23c9287f1ec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 11 Jun 2019 09:49:53 -0400 Subject: [PATCH 0179/7155] media: media/pci: don't set description for ENUM_FMT The V4L2 core sets the description for the driver in order to ensure consistent naming. So drop the strscpy of the description in drivers. Also remove any description strings in driver-internal structures since those are no longer needed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146/saa7146_video.c | 16 ++--------- drivers/media/pci/bt8xx/bttv-driver.c | 19 ------------- drivers/media/pci/bt8xx/bttv-risc.c | 8 +++--- drivers/media/pci/bt8xx/bttvp.h | 1 - drivers/media/pci/cobalt/cobalt-v4l2.c | 5 ---- drivers/media/pci/cx23885/cx23885-417.c | 1 - drivers/media/pci/cx23885/cx23885-video.c | 7 ++--- drivers/media/pci/cx23885/cx23885.h | 1 - drivers/media/pci/cx25821/cx25821-video.c | 7 ++--- drivers/media/pci/cx25821/cx25821.h | 1 - drivers/media/pci/cx88/cx88-blackbird.c | 2 -- drivers/media/pci/cx88/cx88-video.c | 17 ++--------- drivers/media/pci/cx88/cx88.h | 1 - drivers/media/pci/dt3155/dt3155.c | 1 - drivers/media/pci/meye/meye.c | 3 -- drivers/media/pci/saa7134/saa7134-empress.c | 2 -- drivers/media/pci/saa7134/saa7134-video.c | 28 +++---------------- drivers/media/pci/saa7134/saa7134.h | 1 - drivers/media/pci/saa7164/saa7164-encoder.c | 1 - .../media/pci/solo6x10/solo6x10-v4l2-enc.c | 7 ----- drivers/media/pci/solo6x10/solo6x10-v4l2.c | 2 -- drivers/media/pci/sta2x11/sta2x11_vip.c | 2 -- drivers/media/pci/tw68/tw68-video.c | 13 --------- drivers/media/pci/tw68/tw68.h | 1 - include/media/drv-intf/saa7146_vv.h | 1 - 25 files changed, 17 insertions(+), 131 deletions(-) diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 4c399a42e874..d16122039b0c 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -20,62 +20,52 @@ MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: /* format descriptions for capture and preview */ static struct saa7146_format formats[] = { { - .name = "RGB-8 (3-3-2)", .pixelformat = V4L2_PIX_FMT_RGB332, .trans = RGB08_COMPOSED, .depth = 8, .flags = 0, }, { - .name = "RGB-16 (5/B-6/G-5/R)", .pixelformat = V4L2_PIX_FMT_RGB565, .trans = RGB16_COMPOSED, .depth = 16, .flags = 0, }, { - .name = "RGB-24 (B-G-R)", .pixelformat = V4L2_PIX_FMT_BGR24, .trans = RGB24_COMPOSED, .depth = 24, .flags = 0, }, { - .name = "RGB-32 (B-G-R)", .pixelformat = V4L2_PIX_FMT_BGR32, .trans = RGB32_COMPOSED, .depth = 32, .flags = 0, }, { - .name = "RGB-32 (R-G-B)", .pixelformat = V4L2_PIX_FMT_RGB32, .trans = RGB32_COMPOSED, .depth = 32, .flags = 0, .swap = 0x2, }, { - .name = "Greyscale-8", .pixelformat = V4L2_PIX_FMT_GREY, .trans = Y8, .depth = 8, .flags = 0, }, { - .name = "YUV 4:2:2 planar (Y-Cb-Cr)", .pixelformat = V4L2_PIX_FMT_YUV422P, .trans = YUV422_DECOMPOSED, .depth = 16, .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, }, { - .name = "YVU 4:2:0 planar (Y-Cb-Cr)", .pixelformat = V4L2_PIX_FMT_YVU420, .trans = YUV420_DECOMPOSED, .depth = 12, .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, }, { - .name = "YUV 4:2:0 planar (Y-Cb-Cr)", .pixelformat = V4L2_PIX_FMT_YUV420, .trans = YUV420_DECOMPOSED, .depth = 12, .flags = FORMAT_IS_PLANAR, }, { - .name = "YUV 4:2:2 (U-Y-V-Y)", .pixelformat = V4L2_PIX_FMT_UYVY, .trans = YUV422_COMPOSED, .depth = 16, @@ -147,10 +137,10 @@ int saa7146_start_preview(struct saa7146_fh *fh) } vv->ov.win = fmt.fmt.win; - DEB_D("%dx%d+%d+%d %s field=%s\n", + DEB_D("%dx%d+%d+%d 0x%08x field=%s\n", vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.w.left, vv->ov.win.w.top, - vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]); + vv->ov_fmt->pixelformat, v4l2_field_names[vv->ov.win.field]); if (0 != (ret = saa7146_enable_overlay(fh))) { DEB_D("enabling overlay failed: %d\n", ret); @@ -515,8 +505,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd { if (f->index >= ARRAY_SIZE(formats)) return -EINVAL; - strscpy((char *)f->description, formats[f->index].name, - sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; } diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 612d1c0010c1..a359da7773a9 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -503,77 +503,65 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); packed pixel formats must come first */ static const struct bttv_format formats[] = { { - .name = "8 bpp, gray", .fourcc = V4L2_PIX_FMT_GREY, .btformat = BT848_COLOR_FMT_Y8, .depth = 8, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "8 bpp, dithered color", .fourcc = V4L2_PIX_FMT_HI240, .btformat = BT848_COLOR_FMT_RGB8, .depth = 8, .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER, },{ - .name = "15 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB555, .btformat = BT848_COLOR_FMT_RGB15, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "15 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB555X, .btformat = BT848_COLOR_FMT_RGB15, .btswap = 0x03, /* byteswap */ .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "16 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB565, .btformat = BT848_COLOR_FMT_RGB16, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "16 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB565X, .btformat = BT848_COLOR_FMT_RGB16, .btswap = 0x03, /* byteswap */ .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "24 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR24, .btformat = BT848_COLOR_FMT_RGB24, .depth = 24, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "32 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR32, .btformat = BT848_COLOR_FMT_RGB32, .depth = 32, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "32 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB32, .btformat = BT848_COLOR_FMT_RGB32, .btswap = 0x0f, /* byte+word swap */ .depth = 32, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .btformat = BT848_COLOR_FMT_YUY2, .btswap = 0x03, /* byteswap */ .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ - .name = "4:2:2, planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV422P, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 16, @@ -581,7 +569,6 @@ static const struct bttv_format formats[] = { .hshift = 1, .vshift = 0, },{ - .name = "4:2:0, planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -589,7 +576,6 @@ static const struct bttv_format formats[] = { .hshift = 1, .vshift = 1, },{ - .name = "4:2:0, planar, Y-Cr-Cb", .fourcc = V4L2_PIX_FMT_YVU420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -597,7 +583,6 @@ static const struct bttv_format formats[] = { .hshift = 1, .vshift = 1, },{ - .name = "4:1:1, planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV411P, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 12, @@ -605,7 +590,6 @@ static const struct bttv_format formats[] = { .hshift = 2, .vshift = 0, },{ - .name = "4:1:0, planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -613,7 +597,6 @@ static const struct bttv_format formats[] = { .hshift = 2, .vshift = 2, },{ - .name = "4:1:0, planar, Y-Cr-Cb", .fourcc = V4L2_PIX_FMT_YVU410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -621,7 +604,6 @@ static const struct bttv_format formats[] = { .hshift = 2, .vshift = 2, },{ - .name = "raw scanlines", .fourcc = -1, .btformat = BT848_COLOR_FMT_RAW, .depth = 8, @@ -2500,7 +2482,6 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) return -EINVAL; f->pixelformat = formats[i].fourcc; - strscpy(f->description, formats[i].name, sizeof(f->description)); return i; } diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 6b59ca337c7f..fc8708047be8 100644 --- a/drivers/media/pci/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c @@ -699,9 +699,9 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - dprintk("%d: buffer field: %s format: %s size: %dx%d\n", + dprintk("%d: buffer field: %s format: 0x%08x size: %dx%d\n", btv->c.nr, v4l2_field_names[buf->vb.field], - buf->fmt->name, buf->vb.width, buf->vb.height); + buf->fmt->fourcc, buf->vb.width, buf->vb.height); /* packed pixel modes */ if (buf->fmt->flags & FORMAT_FLAGS_PACKED) { @@ -860,9 +860,9 @@ bttv_overlay_risc(struct bttv *btv, struct bttv_buffer *buf) { /* check interleave, bottom+top fields */ - dprintk("%d: overlay fields: %s format: %s size: %dx%d\n", + dprintk("%d: overlay fields: %s format: 0x%08x size: %dx%d\n", btv->c.nr, v4l2_field_names[buf->vb.field], - fmt->name, ov->w.width, ov->w.height); + fmt->fourcc, ov->w.width, ov->w.height); /* calculate geometry */ bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index b159d6ddbfcf..4abf43657846 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -99,7 +99,6 @@ struct bttv_tvnorm { extern const struct bttv_tvnorm bttv_tvnorms[]; struct bttv_format { - char *name; int fourcc; /* video4linux 2 */ int btformat; /* BT848_COLOR_FMT_* */ int btswap; /* BT848_COLOR_CTL_* */ diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index 39dabd4da60f..ea96f333ee2b 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -688,15 +688,12 @@ static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh, { switch (f->index) { case 0: - strscpy(f->description, "YUV 4:2:2", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; break; case 1: - strscpy(f->description, "RGB24", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_RGB24; break; case 2: - strscpy(f->description, "RGB32", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_BGR32; break; default: @@ -893,11 +890,9 @@ static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh, { switch (f->index) { case 0: - strscpy(f->description, "YUV 4:2:2", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; break; case 1: - strscpy(f->description, "RGB32", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_BGR32; break; default: diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 82f96a4091ac..2327fe612610 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1339,7 +1339,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index b254473db9a3..8098b15493de 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -67,7 +67,6 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); #define FORMAT_FLAGS_PACKED 0x01 static struct cx23885_fmt formats[] = { { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .flags = FORMAT_FLAGS_PACKED, @@ -411,9 +410,9 @@ static int buffer_prepare(struct vb2_buffer *vb) default: BUG(); } - dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", + dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp 0x%08x - dma=0x%08lx\n", buf, buf->vb.vb2_buf.index, - dev->width, dev->height, dev->fmt->depth, dev->fmt->name, + dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc, (unsigned long)buf->risc.dma); return 0; } @@ -647,8 +646,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strscpy(f->description, formats[f->index].name, - sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0; diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 9da66fdd5a0d..a95a2e4c6a0d 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -127,7 +127,6 @@ V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK) struct cx23885_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int depth; int flags; diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index de7641170478..a10261da0db6 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -35,12 +35,10 @@ MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); static const struct cx25821_fmt formats[] = { { - .name = "4:1:1, packed, Y41P", .fourcc = V4L2_PIX_FMT_Y41P, .depth = 12, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .flags = FORMAT_FLAGS_PACKED, @@ -215,9 +213,9 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb) break; } - dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", + dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp 0x%08x - dma=0x%08lx\n", buf, buf->vb.vb2_buf.index, chan->width, chan->height, - chan->fmt->depth, chan->fmt->name, + chan->fmt->depth, chan->fmt->fourcc, (unsigned long)buf->risc.dma); return ret; @@ -311,7 +309,6 @@ static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0; diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 47dbaae78509..017307984094 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -83,7 +83,6 @@ #define VID_CHANNEL_NUM 8 struct cx25821_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int depth; int flags; diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 200d68827073..d3da7f4297af 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -805,9 +805,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; - f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; } diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index e59a74514c7c..dcc0f02aeb70 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -69,62 +69,52 @@ MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); static const struct cx8800_fmt formats[] = { { - .name = "8 bpp, gray", .fourcc = V4L2_PIX_FMT_GREY, .cxformat = ColorFormatY8, .depth = 8, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "15 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB555, .cxformat = ColorFormatRGB15, .depth = 16, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "15 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB555X, .cxformat = ColorFormatRGB15 | ColorFormatBSWAP, .depth = 16, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "16 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB565, .cxformat = ColorFormatRGB16, .depth = 16, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "16 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB565X, .cxformat = ColorFormatRGB16 | ColorFormatBSWAP, .depth = 16, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "24 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR24, .cxformat = ColorFormatRGB24, .depth = 24, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "32 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR32, .cxformat = ColorFormatRGB32, .depth = 32, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "32 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB32, .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP, .depth = 32, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .cxformat = ColorFormatYUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .cxformat = ColorFormatYUY2 | ColorFormatBSWAP, .depth = 16, @@ -489,9 +479,9 @@ static int buffer_prepare(struct vb2_buffer *vb) break; } dprintk(2, - "[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.vb2_buf.index, - core->width, core->height, dev->fmt->depth, dev->fmt->name, + "[%p/%d] %s - %dx%d %dbpp 0x%08x - dma=0x%08lx\n", + buf, buf->vb.vb2_buf.index, __func__, + core->width, core->height, dev->fmt->depth, dev->fmt->fourcc, (unsigned long)buf->risc.dma); return 0; } @@ -829,7 +819,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0; diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index a70a50dc3edf..744a22328ebc 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -99,7 +99,6 @@ static inline unsigned int norm_maxh(v4l2_std_id norm) /* static data */ struct cx8800_fmt { - const char *name; u32 fourcc; /* v4l2 format id */ int depth; int flags; diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c index b4cdda50e742..7480f0d3ad0f 100644 --- a/drivers/media/pci/dt3155/dt3155.c +++ b/drivers/media/pci/dt3155/dt3155.c @@ -306,7 +306,6 @@ static int dt3155_enum_fmt_vid_cap(struct file *filp, if (f->index) return -EINVAL; f->pixelformat = V4L2_PIX_FMT_GREY; - strscpy(f->description, "8-bit Greyscale", sizeof(f->description)); return 0; } diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 8218810c899e..0e61c81356ef 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1104,12 +1104,9 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index == 0) { /* standard YUV 422 capture */ f->flags = 0; - strscpy(f->description, "YUV422", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strscpy(f->description, "MJPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MJPEG; } diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 1a41a56afec6..cb65d345fd3e 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -91,9 +91,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "MPEG TS", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; - f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; } diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 606df51bb636..342cabf48064 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -90,70 +90,58 @@ static int video_out[][9] = { static struct saa7134_format formats[] = { { - .name = "8 bpp gray", .fourcc = V4L2_PIX_FMT_GREY, .depth = 8, .pm = 0x06, },{ - .name = "15 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB555, .depth = 16, .pm = 0x13 | 0x80, },{ - .name = "15 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB555X, .depth = 16, .pm = 0x13 | 0x80, .bswap = 1, },{ - .name = "16 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .pm = 0x10 | 0x80, },{ - .name = "16 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB565X, .depth = 16, .pm = 0x10 | 0x80, .bswap = 1, },{ - .name = "24 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR24, .depth = 24, .pm = 0x11, },{ - .name = "24 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB24, .depth = 24, .pm = 0x11, .bswap = 1, },{ - .name = "32 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR32, .depth = 32, .pm = 0x12, },{ - .name = "32 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .pm = 0x12, .bswap = 1, .wswap = 1, },{ - .name = "4:2:2 packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .pm = 0x00, .bswap = 1, .yuv = 1, },{ - .name = "4:2:2 packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, .pm = 0x00, .yuv = 1, },{ - .name = "4:2:2 planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV422P, .depth = 16, .pm = 0x09, @@ -162,7 +150,6 @@ static struct saa7134_format formats[] = { .hshift = 1, .vshift = 0, },{ - .name = "4:2:0 planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YUV420, .depth = 12, .pm = 0x0a, @@ -171,7 +158,6 @@ static struct saa7134_format formats[] = { .hshift = 1, .vshift = 1, },{ - .name = "4:2:0 planar, Y-Cb-Cr", .fourcc = V4L2_PIX_FMT_YVU420, .depth = 12, .pm = 0x0a, @@ -720,10 +706,10 @@ static int start_preview(struct saa7134_dev *dev) return err; dev->ovfield = dev->win.field; - video_dbg("start_preview %dx%d+%d+%d %s field=%s\n", - dev->win.w.width, dev->win.w.height, - dev->win.w.left, dev->win.w.top, - dev->ovfmt->name, v4l2_field_names[dev->ovfield]); + video_dbg("%s %dx%d+%d+%d 0x%08x field=%s\n", __func__, + dev->win.w.width, dev->win.w.height, + dev->win.w.left, dev->win.w.top, + dev->ovfmt->fourcc, v4l2_field_names[dev->ovfield]); /* setup window + clipping */ set_size(dev, TASK_B, dev->win.w.width, dev->win.w.height, @@ -1780,9 +1766,6 @@ static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= FORMATS) return -EINVAL; - strscpy(f->description, formats[f->index].name, - sizeof(f->description)); - f->pixelformat = formats[f->index].fourcc; return 0; @@ -1799,9 +1782,6 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv, if ((f->index >= FORMATS) || formats[f->index].planar) return -EINVAL; - strscpy(f->description, formats[f->index].name, - sizeof(f->description)); - f->pixelformat = formats[f->index].fourcc; return 0; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 6324f174c6f9..77c325e64a97 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -98,7 +98,6 @@ struct saa7134_tvaudio { }; struct saa7134_format { - char *name; unsigned int fourcc; unsigned int depth; unsigned int pm; diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 43fdaa2d32bd..3fca7257a720 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -503,7 +503,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 609100a46ff8..a02f08459e14 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -822,25 +822,18 @@ static int solo_enc_enum_fmt_cap(struct file *file, void *priv, switch (dev_type) { case SOLO_DEV_6010: f->pixelformat = V4L2_PIX_FMT_MPEG4; - strscpy(f->description, "MPEG-4 part 2", - sizeof(f->description)); break; case SOLO_DEV_6110: f->pixelformat = V4L2_PIX_FMT_H264; - strscpy(f->description, "H.264", sizeof(f->description)); break; } break; case 1: f->pixelformat = V4L2_PIX_FMT_MJPEG; - strscpy(f->description, "MJPEG", sizeof(f->description)); break; default: return -EINVAL; } - - f->flags = V4L2_FMT_FLAG_COMPRESSED; - return 0; } diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c index a968f75920b5..2efa539d6075 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c @@ -458,8 +458,6 @@ static int solo_enum_fmt_cap(struct file *file, void *priv, return -EINVAL; f->pixelformat = V4L2_PIX_FMT_UYVY; - strscpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description)); - return 0; } diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index e52e29814378..fd3de3bb0c89 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -560,9 +560,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strscpy(f->description, "4:2:2, packed, UYVY", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_UYVY; - f->flags = 0; return 0; } diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 8e0952d65ad4..99e74c22d3be 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -34,53 +34,43 @@ */ static const struct tw68_format formats[] = { { - .name = "15 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB555, .depth = 16, .twformat = ColorFormatRGB15, }, { - .name = "15 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB555X, .depth = 16, .twformat = ColorFormatRGB15 | ColorFormatBSWAP, }, { - .name = "16 bpp RGB, le", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .twformat = ColorFormatRGB16, }, { - .name = "16 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB565X, .depth = 16, .twformat = ColorFormatRGB16 | ColorFormatBSWAP, }, { - .name = "24 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR24, .depth = 24, .twformat = ColorFormatRGB24, }, { - .name = "24 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB24, .depth = 24, .twformat = ColorFormatRGB24 | ColorFormatBSWAP, }, { - .name = "32 bpp RGB, le", .fourcc = V4L2_PIX_FMT_BGR32, .depth = 32, .twformat = ColorFormatRGB32, }, { - .name = "32 bpp RGB, be", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .twformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP, }, { - .name = "4:2:2 packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .twformat = ColorFormatYUY2, }, { - .name = "4:2:2 packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, .twformat = ColorFormatYUY2 | ColorFormatBSWAP, @@ -774,9 +764,6 @@ static int tw68_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= FORMATS) return -EINVAL; - strscpy(f->description, formats[f->index].name, - sizeof(f->description)); - f->pixelformat = formats[f->index].fourcc; return 0; diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h index 7021290d726a..a1f422d6e600 100644 --- a/drivers/media/pci/tw68/tw68.h +++ b/drivers/media/pci/tw68/tw68.h @@ -85,7 +85,6 @@ struct tw68_tvnorm { }; struct tw68_format { - char *name; u32 fourcc; u32 depth; u32 twformat; diff --git a/include/media/drv-intf/saa7146_vv.h b/include/media/drv-intf/saa7146_vv.h index b34d86bb0664..635805fb35e8 100644 --- a/include/media/drv-intf/saa7146_vv.h +++ b/include/media/drv-intf/saa7146_vv.h @@ -32,7 +32,6 @@ struct saa7146_video_dma { #define FORMAT_IS_PLANAR 0x2 struct saa7146_format { - char *name; u32 pixelformat; u32 trans; u8 depth; -- GitLab From 642ac63d166d07e43396a4d8c48ab24cb072cb18 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 11 Jun 2019 10:02:43 -0400 Subject: [PATCH 0180/7155] media: drivers/staging/media: don't set description for ENUM_FMT The V4L2 core sets the format description and flags for the driver in order to ensure consistent naming. So drop the strscpy of the description in drivers. Also remove any description strings in driver-internal structures since those are no longer needed. Note that bcm2835-camera.c: the formats array still stores the flags field for compressed formats since that information is used elsewhere in the driver. But enum_fmt doesn't use it anymore, since the core will set the COMPRESSED flag correctly. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 40 +++++++++---------- drivers/staging/media/omap4iss/iss_video.h | 2 - drivers/staging/media/soc_camera/soc_camera.c | 2 - .../bcm2835-camera/bcm2835-camera.c | 29 -------------- .../bcm2835-camera/mmal-common.h | 1 - include/media/drv-intf/soc_mediabus.h | 2 - 6 files changed, 19 insertions(+), 57 deletions(-) diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index c307707480f7..54144dc9f509 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -31,61 +31,61 @@ static struct iss_format_info formats[] = { { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_GREY, 8, "Greyscale 8 bpp", }, + V4L2_PIX_FMT_GREY, 8, }, { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y10, 10, "Greyscale 10 bpp", }, + V4L2_PIX_FMT_Y10, 10, }, { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y12, 12, "Greyscale 12 bpp", }, + V4L2_PIX_FMT_Y12, 12, }, { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR8, 8, "BGGR Bayer 8 bpp", }, + V4L2_PIX_FMT_SBGGR8, 8, }, { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG8, 8, "GBRG Bayer 8 bpp", }, + V4L2_PIX_FMT_SGBRG8, 8, }, { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG8, 8, "GRBG Bayer 8 bpp", }, + V4L2_PIX_FMT_SGRBG8, 8, }, { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB8, 8, "RGGB Bayer 8 bpp", }, + V4L2_PIX_FMT_SRGGB8, 8, }, { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_1X10, 0, - V4L2_PIX_FMT_SGRBG10DPCM8, 8, "GRBG Bayer 10 bpp DPCM8", }, + V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR10, 10, "BGGR Bayer 10 bpp", }, + V4L2_PIX_FMT_SBGGR10, 10, }, { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG10, 10, "GBRG Bayer 10 bpp", }, + V4L2_PIX_FMT_SGBRG10, 10, }, { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG10, 10, "GRBG Bayer 10 bpp", }, + V4L2_PIX_FMT_SGRBG10, 10, }, { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB10, 10, "RGGB Bayer 10 bpp", }, + V4L2_PIX_FMT_SRGGB10, 10, }, { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR12, 12, "BGGR Bayer 12 bpp", }, + V4L2_PIX_FMT_SBGGR12, 12, }, { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG12, 12, "GBRG Bayer 12 bpp", }, + V4L2_PIX_FMT_SGBRG12, 12, }, { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG12, 12, "GRBG Bayer 12 bpp", }, + V4L2_PIX_FMT_SGRBG12, 12, }, { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB12, 12, "RGGB Bayer 12 bpp", }, + V4L2_PIX_FMT_SRGGB12, 12, }, { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16, 0, - V4L2_PIX_FMT_UYVY, 16, "YUV 4:2:2 (UYVY)", }, + V4L2_PIX_FMT_UYVY, 16, }, { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, 0, - V4L2_PIX_FMT_YUYV, 16, "YUV 4:2:2 (YUYV)", }, + V4L2_PIX_FMT_YUYV, 16, }, { MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, 0, - V4L2_PIX_FMT_NV12, 8, "YUV 4:2:0 (NV12)", }, + V4L2_PIX_FMT_NV12, 8, }, }; const struct iss_format_info * @@ -563,8 +563,6 @@ iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) if (index == 0) { f->pixelformat = info->pixelformat; - strscpy(f->description, info->description, - sizeof(f->description)); return 0; } diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index f22489edb562..8b3dd92021e1 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -36,7 +36,6 @@ struct v4l2_pix_format; * shifted to be 8 bits per pixel. =0 if format is not shiftable. * @pixelformat: V4L2 pixel format FCC identifier * @bpp: Bits per pixel - * @description: Human-readable format description */ struct iss_format_info { u32 code; @@ -45,7 +44,6 @@ struct iss_format_info { u32 flavor; u32 pixelformat; unsigned int bpp; - const char *description; }; enum iss_pipeline_stream_state { diff --git a/drivers/staging/media/soc_camera/soc_camera.c b/drivers/staging/media/soc_camera/soc_camera.c index a6232dcd59bc..7b9448e3c9ba 100644 --- a/drivers/staging/media/soc_camera/soc_camera.c +++ b/drivers/staging/media/soc_camera/soc_camera.c @@ -869,8 +869,6 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, format = icd->user_formats[f->index].host_fmt; - if (format->name) - strscpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; return 0; } diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index ea54cc27e645..d4d1e44b16b2 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -75,34 +75,27 @@ static const struct v4l2_fract /* video formats */ static struct mmal_fmt formats[] = { { - .name = "4:2:0, planar, YUV", .fourcc = V4L2_PIX_FMT_YUV420, - .flags = 0, .mmal = MMAL_ENCODING_I420, .depth = 12, .mmal_component = COMP_CAMERA, .ybbp = 1, .remove_padding = 1, }, { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, - .flags = 0, .mmal = MMAL_ENCODING_YUYV, .depth = 16, .mmal_component = COMP_CAMERA, .ybbp = 2, .remove_padding = 0, }, { - .name = "RGB24 (LE)", .fourcc = V4L2_PIX_FMT_RGB24, - .flags = 0, .mmal = MMAL_ENCODING_RGB24, .depth = 24, .mmal_component = COMP_CAMERA, .ybbp = 3, .remove_padding = 0, }, { - .name = "JPEG", .fourcc = V4L2_PIX_FMT_JPEG, .flags = V4L2_FMT_FLAG_COMPRESSED, .mmal = MMAL_ENCODING_JPEG, @@ -111,7 +104,6 @@ static struct mmal_fmt formats[] = { .ybbp = 0, .remove_padding = 0, }, { - .name = "H264", .fourcc = V4L2_PIX_FMT_H264, .flags = V4L2_FMT_FLAG_COMPRESSED, .mmal = MMAL_ENCODING_H264, @@ -120,7 +112,6 @@ static struct mmal_fmt formats[] = { .ybbp = 0, .remove_padding = 0, }, { - .name = "MJPEG", .fourcc = V4L2_PIX_FMT_MJPEG, .flags = V4L2_FMT_FLAG_COMPRESSED, .mmal = MMAL_ENCODING_MJPEG, @@ -129,72 +120,56 @@ static struct mmal_fmt formats[] = { .ybbp = 0, .remove_padding = 0, }, { - .name = "4:2:2, packed, YVYU", .fourcc = V4L2_PIX_FMT_YVYU, - .flags = 0, .mmal = MMAL_ENCODING_YVYU, .depth = 16, .mmal_component = COMP_CAMERA, .ybbp = 2, .remove_padding = 0, }, { - .name = "4:2:2, packed, VYUY", .fourcc = V4L2_PIX_FMT_VYUY, - .flags = 0, .mmal = MMAL_ENCODING_VYUY, .depth = 16, .mmal_component = COMP_CAMERA, .ybbp = 2, .remove_padding = 0, }, { - .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, - .flags = 0, .mmal = MMAL_ENCODING_UYVY, .depth = 16, .mmal_component = COMP_CAMERA, .ybbp = 2, .remove_padding = 0, }, { - .name = "4:2:0, planar, NV12", .fourcc = V4L2_PIX_FMT_NV12, - .flags = 0, .mmal = MMAL_ENCODING_NV12, .depth = 12, .mmal_component = COMP_CAMERA, .ybbp = 1, .remove_padding = 1, }, { - .name = "RGB24 (BE)", .fourcc = V4L2_PIX_FMT_BGR24, - .flags = 0, .mmal = MMAL_ENCODING_BGR24, .depth = 24, .mmal_component = COMP_CAMERA, .ybbp = 3, .remove_padding = 0, }, { - .name = "4:2:0, planar, YVU", .fourcc = V4L2_PIX_FMT_YVU420, - .flags = 0, .mmal = MMAL_ENCODING_YV12, .depth = 12, .mmal_component = COMP_CAMERA, .ybbp = 1, .remove_padding = 1, }, { - .name = "4:2:0, planar, NV21", .fourcc = V4L2_PIX_FMT_NV21, - .flags = 0, .mmal = MMAL_ENCODING_NV21, .depth = 12, .mmal_component = COMP_CAMERA, .ybbp = 1, .remove_padding = 1, }, { - .name = "RGB32 (BE)", .fourcc = V4L2_PIX_FMT_BGR32, - .flags = 0, .mmal = MMAL_ENCODING_BGRA, .depth = 32, .mmal_component = COMP_CAMERA, @@ -716,9 +691,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, fmt = &formats[f->index]; - strlcpy((char *)f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; - f->flags = fmt->flags; return 0; } @@ -919,9 +892,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, fmt = &formats[f->index]; - strlcpy((char *)f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; - f->flags = fmt->flags; return 0; } diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h index 6f56c517d850..ff5398737b4a 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h @@ -26,7 +26,6 @@ struct mmal_msg_context; /* mapping between v4l and mmal video modes */ struct mmal_fmt { - char *name; u32 fourcc; /* v4l2 format id */ int flags; /* v4l2 flags field */ u32 mmal; diff --git a/include/media/drv-intf/soc_mediabus.h b/include/media/drv-intf/soc_mediabus.h index 73de3bd0c605..361f8852c9fc 100644 --- a/include/media/drv-intf/soc_mediabus.h +++ b/include/media/drv-intf/soc_mediabus.h @@ -66,7 +66,6 @@ enum soc_mbus_layout { /** * struct soc_mbus_pixelfmt - Data format on the media bus - * @name: Name of the format * @fourcc: Fourcc code, that will be obtained if the data is * stored in memory in the following way: * @packing: Type of sample-packing, that has to be used @@ -74,7 +73,6 @@ enum soc_mbus_layout { * @bits_per_sample: How many bits the bridge has to sample */ struct soc_mbus_pixelfmt { - const char *name; u32 fourcc; enum soc_mbus_packing packing; enum soc_mbus_order order; -- GitLab From 59fe916c84f891aab35019adc45377a10f5690b1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 11 Jun 2019 10:25:15 -0400 Subject: [PATCH 0181/7155] media: media/platform: don't set description in ENUM_FMT The V4L2 core sets the format description and flags for the driver in order to ensure consistent naming. So drop the strscpy of the description in drivers. Also remove any description strings in driver-internal structures since those are no longer needed. And in am437x-vpfe.c drop an unnecessary f->type assignment in vpfe_enum_fmt(). Signed-off-by: Hans Verkuil Acked-by: Benoit Parrot Reviewed-by: Laurent Pinchart [hverkuil-cisco@xs4all.nl: addressed some small suggestions from Laurent] Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 18 ++----------- drivers/media/platform/davinci/vpbe_display.c | 14 ++-------- drivers/media/platform/davinci/vpif_capture.c | 11 ++------ drivers/media/platform/davinci/vpif_display.c | 4 --- drivers/media/platform/exynos-gsc/gsc-core.c | 22 --------------- drivers/media/platform/exynos-gsc/gsc-core.h | 2 -- .../media/platform/exynos4-is/fimc-capture.c | 3 --- drivers/media/platform/exynos4-is/fimc-core.c | 20 -------------- .../platform/exynos4-is/fimc-isp-video.c | 1 - drivers/media/platform/exynos4-is/fimc-isp.c | 3 --- drivers/media/platform/exynos4-is/fimc-lite.c | 8 ------ drivers/media/platform/exynos4-is/fimc-m2m.c | 1 - drivers/media/platform/m2m-deinterlace.c | 4 --- .../media/platform/marvell-ccic/mcam-core.c | 10 ------- drivers/media/platform/mx2_emmaprp.c | 4 --- drivers/media/platform/omap/omap_vout.c | 7 ----- .../media/platform/s3c-camif/camif-capture.c | 11 +++----- drivers/media/platform/s3c-camif/camif-core.c | 6 ----- drivers/media/platform/s3c-camif/camif-core.h | 1 - drivers/media/platform/s5p-g2d/g2d.c | 10 +------ drivers/media/platform/s5p-g2d/g2d.h | 1 - drivers/media/platform/s5p-jpeg/jpeg-core.c | 27 ------------------- drivers/media/platform/s5p-jpeg/jpeg-core.h | 2 -- .../media/platform/s5p-mfc/s5p_mfc_common.h | 1 - drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 19 +------------ drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 14 +--------- drivers/media/platform/sh_veu.c | 19 ++++++------- drivers/media/platform/sh_vou.c | 12 ++------- drivers/media/platform/ti-vpe/vpe.c | 12 --------- drivers/media/platform/via-camera.c | 4 --- drivers/media/platform/xilinx/xilinx-dma.c | 2 -- drivers/media/platform/xilinx/xilinx-vip.c | 16 +++++------ drivers/media/platform/xilinx/xilinx-vip.h | 2 -- include/media/drv-intf/exynos-fimc.h | 2 -- 34 files changed, 31 insertions(+), 262 deletions(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index fe7b937eb5f2..7582c26f8459 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -76,7 +76,6 @@ struct bus_format { /* * struct vpfe_fmt - VPFE media bus format information - * @name: V4L2 format description * @code: V4L2 media bus format code * @shifted: V4L2 media bus format code for the same pixel layout but * shifted to be 8 bits per pixel. =0 if format is not shiftable. @@ -86,7 +85,6 @@ struct bus_format { * @supported: Indicates format supported by subdev */ struct vpfe_fmt { - const char *name; u32 fourcc; u32 code; struct bus_format l; @@ -97,7 +95,6 @@ struct vpfe_fmt { static struct vpfe_fmt formats[] = { { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .code = MEDIA_BUS_FMT_YUYV8_2X8, .l.width = 10, @@ -106,7 +103,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 2, .supported = false, }, { - .name = "YUV 4:2:2 packed, CbYCrY", .fourcc = V4L2_PIX_FMT_UYVY, .code = MEDIA_BUS_FMT_UYVY8_2X8, .l.width = 10, @@ -115,7 +111,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 2, .supported = false, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, .code = MEDIA_BUS_FMT_YVYU8_2X8, .l.width = 10, @@ -124,7 +119,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 2, .supported = false, }, { - .name = "YUV 4:2:2 packed, CrYCbY", .fourcc = V4L2_PIX_FMT_VYUY, .code = MEDIA_BUS_FMT_VYUY8_2X8, .l.width = 10, @@ -133,7 +127,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 2, .supported = false, }, { - .name = "RAW8 BGGR", .fourcc = V4L2_PIX_FMT_SBGGR8, .code = MEDIA_BUS_FMT_SBGGR8_1X8, .l.width = 10, @@ -142,7 +135,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 1, .supported = false, }, { - .name = "RAW8 GBRG", .fourcc = V4L2_PIX_FMT_SGBRG8, .code = MEDIA_BUS_FMT_SGBRG8_1X8, .l.width = 10, @@ -151,7 +143,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 1, .supported = false, }, { - .name = "RAW8 GRBG", .fourcc = V4L2_PIX_FMT_SGRBG8, .code = MEDIA_BUS_FMT_SGRBG8_1X8, .l.width = 10, @@ -160,7 +151,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 1, .supported = false, }, { - .name = "RAW8 RGGB", .fourcc = V4L2_PIX_FMT_SRGGB8, .code = MEDIA_BUS_FMT_SRGGB8_1X8, .l.width = 10, @@ -169,7 +159,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 1, .supported = false, }, { - .name = "RGB565 (LE)", .fourcc = V4L2_PIX_FMT_RGB565, .code = MEDIA_BUS_FMT_RGB565_2X8_LE, .l.width = 10, @@ -178,7 +167,6 @@ static struct vpfe_fmt formats[] = { .s.bpp = 2, .supported = false, }, { - .name = "RGB565 (BE)", .fourcc = V4L2_PIX_FMT_RGB565X, .code = MEDIA_BUS_FMT_RGB565_2X8_BE, .l.width = 10, @@ -1540,12 +1528,10 @@ static int vpfe_enum_fmt(struct file *file, void *priv, if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; - f->type = vpfe->fmt.type; - vpfe_dbg(1, vpfe, "vpfe_enum_format: mbus index: %d code: %x pixelformat: %s [%s]\n", - f->index, fmt->code, print_fourcc(fmt->fourcc), fmt->name); + vpfe_dbg(1, vpfe, "vpfe_enum_format: mbus index: %d code: %x pixelformat: %s\n", + f->index, fmt->code, print_fourcc(fmt->fourcc)); return 0; } diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 000b191c42d8..ed10a9bbf96b 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -792,7 +792,6 @@ static int vpbe_display_enum_fmt(struct file *file, void *priv, { struct vpbe_layer *layer = video_drvdata(file); struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev; - unsigned int index = 0; v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_FMT, layer id = %d\n", @@ -803,19 +802,10 @@ static int vpbe_display_enum_fmt(struct file *file, void *priv, } /* Fill in the information about format */ - index = fmt->index; - memset(fmt, 0, sizeof(*fmt)); - fmt->index = index; - fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - if (index == 0) { - strscpy(fmt->description, "YUV 4:2:2 - UYVY", - sizeof(fmt->description)); + if (fmt->index == 0) fmt->pixelformat = V4L2_PIX_FMT_UYVY; - } else { - strscpy(fmt->description, "Y/CbCr 4:2:0", - sizeof(fmt->description)); + else fmt->pixelformat = V4L2_PIX_FMT_NV12; - } return 0; } diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index f0f7ef638c56..621d28470d2b 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -938,17 +938,10 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, } /* Fill in the information about format */ - if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) { - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strscpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb", - sizeof(fmt->description)); + if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) fmt->pixelformat = V4L2_PIX_FMT_SBGGR8; - } else { - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strscpy(fmt->description, "YCbCr4:2:2 Semi-Planar", - sizeof(fmt->description)); + else fmt->pixelformat = V4L2_PIX_FMT_NV16; - } return 0; } diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index a69897c68a50..be32f87001cd 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -601,11 +601,7 @@ static int vpif_enum_fmt_vid_out(struct file *file, void *priv, return -EINVAL; /* Fill in the information about format */ - fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - strscpy(fmt->description, "YCbCr4:2:2 YC Planar", - sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_YUV422P; - fmt->flags = 0; return 0; } diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 854869f0024e..f6650b45bc3d 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -27,21 +27,18 @@ static const struct gsc_fmt gsc_formats[] = { { - .name = "RGB565", .pixelformat = V4L2_PIX_FMT_RGB565X, .depth = { 16 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, }, { - .name = "BGRX-8-8-8-8, 32 bpp", .pixelformat = V4L2_PIX_FMT_BGR32, .depth = { 32 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, }, { - .name = "YUV 4:2:2 packed, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUYV, .depth = { 16 }, .color = GSC_YUV422, @@ -51,7 +48,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_comp = 1, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, }, { - .name = "YUV 4:2:2 packed, CbYCrY", .pixelformat = V4L2_PIX_FMT_UYVY, .depth = { 16 }, .color = GSC_YUV422, @@ -61,7 +57,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_comp = 1, .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, }, { - .name = "YUV 4:2:2 packed, CrYCbY", .pixelformat = V4L2_PIX_FMT_VYUY, .depth = { 16 }, .color = GSC_YUV422, @@ -71,7 +66,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_comp = 1, .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .pixelformat = V4L2_PIX_FMT_YVYU, .depth = { 16 }, .color = GSC_YUV422, @@ -81,7 +75,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_comp = 1, .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, }, { - .name = "YUV 4:4:4 planar, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUV32, .depth = { 32 }, .color = GSC_YUV444, @@ -90,7 +83,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 1, }, { - .name = "YUV 4:2:2 planar, Y/Cb/Cr", .pixelformat = V4L2_PIX_FMT_YUV422P, .depth = { 16 }, .color = GSC_YUV422, @@ -99,7 +91,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 3, }, { - .name = "YUV 4:2:2 planar, Y/CbCr", .pixelformat = V4L2_PIX_FMT_NV16, .depth = { 16 }, .color = GSC_YUV422, @@ -108,7 +99,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 2, }, { - .name = "YUV 4:2:2 non-contig, Y/CbCr", .pixelformat = V4L2_PIX_FMT_NV16M, .depth = { 8, 8 }, .color = GSC_YUV422, @@ -117,7 +107,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 2, .num_comp = 2, }, { - .name = "YUV 4:2:2 planar, Y/CrCb", .pixelformat = V4L2_PIX_FMT_NV61, .depth = { 16 }, .color = GSC_YUV422, @@ -126,7 +115,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 2, }, { - .name = "YUV 4:2:2 non-contig, Y/CrCb", .pixelformat = V4L2_PIX_FMT_NV61M, .depth = { 8, 8 }, .color = GSC_YUV422, @@ -135,7 +123,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 2, .num_comp = 2, }, { - .name = "YUV 4:2:0 planar, YCbCr", .pixelformat = V4L2_PIX_FMT_YUV420, .depth = { 12 }, .color = GSC_YUV420, @@ -144,7 +131,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 3, }, { - .name = "YUV 4:2:0 planar, YCrCb", .pixelformat = V4L2_PIX_FMT_YVU420, .depth = { 12 }, .color = GSC_YUV420, @@ -154,7 +140,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_comp = 3, }, { - .name = "YUV 4:2:0 planar, Y/CbCr", .pixelformat = V4L2_PIX_FMT_NV12, .depth = { 12 }, .color = GSC_YUV420, @@ -163,7 +148,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 2, }, { - .name = "YUV 4:2:0 planar, Y/CrCb", .pixelformat = V4L2_PIX_FMT_NV21, .depth = { 12 }, .color = GSC_YUV420, @@ -172,7 +156,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 1, .num_comp = 2, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CrCb", .pixelformat = V4L2_PIX_FMT_NV21M, .depth = { 8, 4 }, .color = GSC_YUV420, @@ -181,7 +164,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 2, .num_comp = 2, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", .pixelformat = V4L2_PIX_FMT_NV12M, .depth = { 8, 4 }, .color = GSC_YUV420, @@ -190,7 +172,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 2, .num_comp = 2, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", .pixelformat = V4L2_PIX_FMT_YUV420M, .depth = { 8, 2, 2 }, .color = GSC_YUV420, @@ -199,7 +180,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 3, .num_comp = 3, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", .pixelformat = V4L2_PIX_FMT_YVU420M, .depth = { 8, 2, 2 }, .color = GSC_YUV420, @@ -208,7 +188,6 @@ static const struct gsc_fmt gsc_formats[] = { .num_planes = 3, .num_comp = 3, }, { - .name = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled", .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, .depth = { 8, 4 }, .color = GSC_YUV420, @@ -335,7 +314,6 @@ int gsc_enum_fmt(struct v4l2_fmtdesc *f) if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->pixelformat; return 0; diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index 772183b090c2..8e5a9acb78aa 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -103,7 +103,6 @@ enum gsc_yuv_fmt { /** * struct gsc_fmt - the driver's internal color format data * @mbus_code: Media Bus pixel code, -1 if not applicable - * @name: format description * @pixelformat: the fourcc code for this format, 0 if not applicable * @yorder: Y/C order * @corder: Chrominance order control @@ -114,7 +113,6 @@ enum gsc_yuv_fmt { */ struct gsc_fmt { u32 mbus_code; - char *name; u32 pixelformat; u32 color; u32 yorder; diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 66510365dd5d..121d609ff856 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -738,10 +738,7 @@ static int fimc_cap_enum_fmt(struct file *file, void *priv, f->index); if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; - if (fmt->fourcc == MEDIA_BUS_FMT_JPEG_1X8) - f->flags |= V4L2_FMT_FLAG_COMPRESSED; return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 7006f54bfee2..cde60fbb23a8 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -36,7 +36,6 @@ static char *fimc_clocks[MAX_FIMC_CLOCKS] = { static struct fimc_fmt fimc_formats[] = { { - .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, .depth = { 16 }, .color = FIMC_FMT_RGB565, @@ -44,7 +43,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 1, .flags = FMT_FLAGS_M2M, }, { - .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666, .depth = { 32 }, .color = FIMC_FMT_RGB666, @@ -52,7 +50,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 1, .flags = FMT_FLAGS_M2M, }, { - .name = "BGRA8888, 32 bpp", .fourcc = V4L2_PIX_FMT_BGR32, .depth = { 32 }, .color = FIMC_FMT_RGB888, @@ -60,7 +57,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 1, .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA, }, { - .name = "ARGB1555", .fourcc = V4L2_PIX_FMT_RGB555, .depth = { 16 }, .color = FIMC_FMT_RGB555, @@ -68,7 +64,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 1, .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, }, { - .name = "ARGB4444", .fourcc = V4L2_PIX_FMT_RGB444, .depth = { 16 }, .color = FIMC_FMT_RGB444, @@ -76,11 +71,9 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 1, .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, }, { - .name = "YUV 4:4:4", .mbus_code = MEDIA_BUS_FMT_YUV10_1X30, .flags = FMT_FLAGS_WRITEBACK, }, { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, @@ -89,7 +82,6 @@ static struct fimc_fmt fimc_formats[] = { .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, }, { - .name = "YUV 4:2:2 packed, CbYCrY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = { 16 }, .color = FIMC_FMT_CBYCRY422, @@ -98,7 +90,6 @@ static struct fimc_fmt fimc_formats[] = { .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, }, { - .name = "YUV 4:2:2 packed, CrYCbY", .fourcc = V4L2_PIX_FMT_VYUY, .depth = { 16 }, .color = FIMC_FMT_CRYCBY422, @@ -107,7 +98,6 @@ static struct fimc_fmt fimc_formats[] = { .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, .depth = { 16 }, .color = FIMC_FMT_YCRYCB422, @@ -116,7 +106,6 @@ static struct fimc_fmt fimc_formats[] = { .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, }, { - .name = "YUV 4:2:2 planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV422P, .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, @@ -124,7 +113,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 3, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:2 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV16, .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, @@ -132,7 +120,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 2, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:2 planar, Y/CrCb", .fourcc = V4L2_PIX_FMT_NV61, .depth = { 16 }, .color = FIMC_FMT_YCRYCB422, @@ -140,7 +127,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 2, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:0 planar, YCbCr", .fourcc = V4L2_PIX_FMT_YUV420, .depth = { 12 }, .color = FIMC_FMT_YCBCR420, @@ -148,7 +134,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 3, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:0 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12, .depth = { 12 }, .color = FIMC_FMT_YCBCR420, @@ -156,7 +141,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 2, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12M, .color = FIMC_FMT_YCBCR420, .depth = { 8, 4 }, @@ -164,7 +148,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 2, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV420M, .color = FIMC_FMT_YCBCR420, .depth = { 8, 2, 2 }, @@ -172,7 +155,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 3, .flags = FMT_FLAGS_M2M, }, { - .name = "YUV 4:2:0 non-contig. 2p, tiled", .fourcc = V4L2_PIX_FMT_NV12MT, .color = FIMC_FMT_YCBCR420, .depth = { 8, 4 }, @@ -180,7 +162,6 @@ static struct fimc_fmt fimc_formats[] = { .colplanes = 2, .flags = FMT_FLAGS_M2M, }, { - .name = "JPEG encoded data", .fourcc = V4L2_PIX_FMT_JPEG, .color = FIMC_FMT_JPEG, .depth = { 8 }, @@ -189,7 +170,6 @@ static struct fimc_fmt fimc_formats[] = { .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED, }, { - .name = "S5C73MX interleaved UYVY/JPEG", .fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG, .color = FIMC_FMT_YUYV_JPEG, .depth = { 8 }, diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index a75f932a289a..378cc302e1f8 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -362,7 +362,6 @@ static int isp_video_enum_fmt(struct file *file, void *priv, if (WARN_ON(fmt == NULL)) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index 907b83e6649d..cde0d254ec1c 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -33,21 +33,18 @@ module_param_named(debug_isp, fimc_isp_debug, int, S_IRUGO | S_IWUSR); static const struct fimc_fmt fimc_isp_formats[FIMC_ISP_NUM_FORMATS] = { { - .name = "RAW8 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG8, .depth = { 8 }, .color = FIMC_FMT_RAW8, .memplanes = 1, .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, }, { - .name = "RAW10 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG10, .depth = { 10 }, .color = FIMC_FMT_RAW10, .memplanes = 1, .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, }, { - .name = "RAW12 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG12, .depth = { 12 }, .color = FIMC_FMT_RAW12, diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index c1f0aee02e5e..e87c6a09205b 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -39,7 +39,6 @@ module_param(debug, int, 0644); static const struct fimc_fmt fimc_lite_formats[] = { { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, @@ -48,7 +47,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .flags = FMT_FLAGS_YUV, }, { - .name = "YUV 4:2:2 packed, CbYCrY", .fourcc = V4L2_PIX_FMT_UYVY, .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, @@ -57,7 +55,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, .flags = FMT_FLAGS_YUV, }, { - .name = "YUV 4:2:2 packed, CrYCbY", .fourcc = V4L2_PIX_FMT_VYUY, .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, @@ -66,7 +63,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, .flags = FMT_FLAGS_YUV, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, @@ -75,7 +71,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, .flags = FMT_FLAGS_YUV, }, { - .name = "RAW8 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG8, .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 8 }, @@ -84,7 +79,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, .flags = FMT_FLAGS_RAW_BAYER, }, { - .name = "RAW10 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG10, .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 16 }, @@ -93,7 +87,6 @@ static const struct fimc_fmt fimc_lite_formats[] = { .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, .flags = FMT_FLAGS_RAW_BAYER, }, { - .name = "RAW12 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG12, .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 16 }, @@ -667,7 +660,6 @@ static int fimc_lite_enum_fmt(struct file *file, void *priv, return -EINVAL; fmt = &fimc_lite_formats[f->index]; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 62e876fc3555..c70c2cbe3eb1 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -247,7 +247,6 @@ static int fimc_m2m_enum_fmt(struct file *file, void *priv, if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index beb7fd7442fb..e9310eeec6cf 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -37,7 +37,6 @@ module_param(debug, bool, 0644); v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) struct deinterlace_fmt { - char *name; u32 fourcc; /* Types the format can be used for */ u32 types; @@ -45,12 +44,10 @@ struct deinterlace_fmt { static struct deinterlace_fmt formats[] = { { - .name = "YUV 4:2:0 Planar", .fourcc = V4L2_PIX_FMT_YUV420, .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, { - .name = "YUYV 4:2:2", .fourcc = V4L2_PIX_FMT_YUYV, .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, }, @@ -470,7 +467,6 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (i < NUM_FORMATS) { /* Format found */ fmt = &formats[i]; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index dc30c48d4671..30ac454e702e 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -98,56 +98,48 @@ MODULE_PARM_DESC(buffer_mode, container_of(notifier, struct mcam_camera, notifier) static struct mcam_format_struct { - __u8 *desc; __u32 pixelformat; int bpp; /* Bytes per pixel */ bool planar; u32 mbus_code; } mcam_formats[] = { { - .desc = "YUYV 4:2:2", .pixelformat = V4L2_PIX_FMT_YUYV, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 2, .planar = false, }, { - .desc = "YVYU 4:2:2", .pixelformat = V4L2_PIX_FMT_YVYU, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 2, .planar = false, }, { - .desc = "YUV 4:2:0 PLANAR", .pixelformat = V4L2_PIX_FMT_YUV420, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 1, .planar = true, }, { - .desc = "YVU 4:2:0 PLANAR", .pixelformat = V4L2_PIX_FMT_YVU420, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 1, .planar = true, }, { - .desc = "XRGB 444", .pixelformat = V4L2_PIX_FMT_XRGB444, .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, .bpp = 2, .planar = false, }, { - .desc = "RGB 565", .pixelformat = V4L2_PIX_FMT_RGB565, .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, .bpp = 2, .planar = false, }, { - .desc = "Raw RGB Bayer", .pixelformat = V4L2_PIX_FMT_SBGGR8, .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 1, @@ -1369,8 +1361,6 @@ static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp, { if (fmt->index >= N_MCAM_FMTS) return -EINVAL; - strscpy(fmt->description, mcam_formats[fmt->index].desc, - sizeof(fmt->description)); fmt->pixelformat = mcam_formats[fmt->index].pixelformat; return 0; } diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 333324c75027..4d4225ab1589 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -145,7 +145,6 @@ module_param(debug, bool, 0644); #define PRP_INTR_ST_CH2OVF (1 << 8) struct emmaprp_fmt { - char *name; u32 fourcc; /* Types the format can be used for */ u32 types; @@ -153,12 +152,10 @@ struct emmaprp_fmt { static struct emmaprp_fmt formats[] = { { - .name = "YUV 4:2:0 Planar", .fourcc = V4L2_PIX_FMT_YUV420, .types = MEM2MEM_CAPTURE, }, { - .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .types = MEM2MEM_OUTPUT, }, @@ -409,7 +406,6 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (i < NUM_FORMATS) { /* Format found */ fmt = &formats[i]; - strscpy(f->description, fmt->name, sizeof(f->description) - 1); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index cb6a9e3946b6..1f6742536c46 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -114,14 +114,12 @@ static const struct v4l2_fmtdesc omap_formats[] = { * Byte 0 Byte 1 * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 */ - .description = "RGB565, le", .pixelformat = V4L2_PIX_FMT_RGB565, }, { /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use * this for RGB24 unpack mode, the last 8 bits are ignored * */ - .description = "RGB32, le", .pixelformat = V4L2_PIX_FMT_RGB32, }, { @@ -129,15 +127,12 @@ static const struct v4l2_fmtdesc omap_formats[] = { * this for RGB24 packed mode * */ - .description = "RGB24, le", .pixelformat = V4L2_PIX_FMT_RGB24, }, { - .description = "YUYV (YUV 4:2:2), packed", .pixelformat = V4L2_PIX_FMT_YUYV, }, { - .description = "UYVY, packed", .pixelformat = V4L2_PIX_FMT_UYVY, }, }; @@ -1060,8 +1055,6 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, return -EINVAL; fmt->flags = omap_formats[index].flags; - strscpy(fmt->description, omap_formats[index].description, - sizeof(fmt->description)); fmt->pixelformat = omap_formats[index].pixelformat; return 0; diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index a876d0873ebc..2191fdded9da 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -685,10 +685,7 @@ static int s3c_camif_vidioc_enum_fmt(struct file *file, void *priv, if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; - - pr_debug("fmt(%d): %s\n", f->index, f->description); return 0; } @@ -802,10 +799,10 @@ static int s3c_camif_vidioc_s_fmt(struct file *file, void *priv, if (vp->owner == NULL) vp->owner = priv; - pr_debug("%ux%u. payload: %u. fmt: %s. %d %d. sizeimage: %d. bpl: %d\n", - out_frame->f_width, out_frame->f_height, vp->payload, fmt->name, - pix->width * pix->height * fmt->depth, fmt->depth, - pix->sizeimage, pix->bytesperline); + pr_debug("%ux%u. payload: %u. fmt: 0x%08x. %d %d. sizeimage: %d. bpl: %d\n", + out_frame->f_width, out_frame->f_height, vp->payload, + fmt->fourcc, pix->width * pix->height * fmt->depth, + fmt->depth, pix->sizeimage, pix->bytesperline); return 0; } diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index b05ce0149ca1..f0acd6edcbba 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -42,7 +42,6 @@ static char *camif_clocks[CLK_MAX_NUM] = { static const struct camif_fmt camif_formats[] = { { - .name = "YUV 4:2:2 planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV422P, .depth = 16, .ybpp = 1, @@ -51,7 +50,6 @@ static const struct camif_fmt camif_formats[] = { .flags = FMT_FL_S3C24XX_CODEC | FMT_FL_S3C64XX, }, { - .name = "YUV 4:2:0 planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV420, .depth = 12, .ybpp = 1, @@ -60,7 +58,6 @@ static const struct camif_fmt camif_formats[] = { .flags = FMT_FL_S3C24XX_CODEC | FMT_FL_S3C64XX, }, { - .name = "YVU 4:2:0 planar, Y/Cr/Cb", .fourcc = V4L2_PIX_FMT_YVU420, .depth = 12, .ybpp = 1, @@ -69,7 +66,6 @@ static const struct camif_fmt camif_formats[] = { .flags = FMT_FL_S3C24XX_CODEC | FMT_FL_S3C64XX, }, { - .name = "RGB565, 16 bpp", .fourcc = V4L2_PIX_FMT_RGB565X, .depth = 16, .ybpp = 2, @@ -78,7 +74,6 @@ static const struct camif_fmt camif_formats[] = { .flags = FMT_FL_S3C24XX_PREVIEW | FMT_FL_S3C64XX, }, { - .name = "XRGB8888, 32 bpp", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .ybpp = 4, @@ -87,7 +82,6 @@ static const struct camif_fmt camif_formats[] = { .flags = FMT_FL_S3C24XX_PREVIEW | FMT_FL_S3C64XX, }, { - .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666, .depth = 32, .ybpp = 4, diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h index efdc00b4ec6f..f937e638490f 100644 --- a/drivers/media/platform/s3c-camif/camif-core.h +++ b/drivers/media/platform/s3c-camif/camif-core.h @@ -89,7 +89,6 @@ enum img_fmt { * @ybpp: number of luminance bytes per pixel */ struct camif_fmt { - char *name; u32 fourcc; u32 color; u16 colplanes; diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 152d192d5c3f..b3fc0ff8a5ec 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -29,31 +29,26 @@ static struct g2d_fmt formats[] = { { - .name = "XRGB_8888", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888), }, { - .name = "RGB_565", .fourcc = V4L2_PIX_FMT_RGB565X, .depth = 16, .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565), }, { - .name = "XRGB_1555", .fourcc = V4L2_PIX_FMT_RGB555X, .depth = 16, .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555), }, { - .name = "XRGB_4444", .fourcc = V4L2_PIX_FMT_RGB444, .depth = 16, .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444), }, { - .name = "PACKED_RGB_888", .fourcc = V4L2_PIX_FMT_RGB24, .depth = 24, .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888), @@ -303,12 +298,9 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) { - struct g2d_fmt *fmt; if (f->index >= NUM_FORMATS) return -EINVAL; - fmt = &formats[f->index]; - f->pixelformat = fmt->fourcc; - strscpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; return 0; } diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h index def0ec0dabeb..c2309c1370da 100644 --- a/drivers/media/platform/s5p-g2d/g2d.h +++ b/drivers/media/platform/s5p-g2d/g2d.h @@ -61,7 +61,6 @@ struct g2d_ctx { }; struct g2d_fmt { - char *name; u32 fourcc; int depth; u32 hw; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index a3bc884b7df1..20cad061e908 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -35,7 +35,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { { - .name = "JPEG JFIF", .fourcc = V4L2_PIX_FMT_JPEG, .flags = SJPEG_FMT_FLAG_ENC_CAPTURE | SJPEG_FMT_FLAG_DEC_OUTPUT | @@ -44,7 +43,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { SJPEG_FMT_FLAG_EXYNOS4, }, { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .colplanes = 1, @@ -57,7 +55,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .colplanes = 1, @@ -70,7 +67,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .colplanes = 1, @@ -83,7 +79,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, .depth = 16, .colplanes = 1, @@ -96,7 +91,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, .depth = 16, .colplanes = 1, @@ -109,7 +103,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, .colplanes = 1, @@ -122,7 +115,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_VYUY, .depth = 16, .colplanes = 1, @@ -135,7 +127,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .colplanes = 1, @@ -148,7 +139,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .colplanes = 1, @@ -161,7 +151,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "RGB565X", .fourcc = V4L2_PIX_FMT_RGB565X, .depth = 16, .colplanes = 1, @@ -174,7 +163,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .colplanes = 1, @@ -186,7 +174,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "ARGB8888, 32 bpp", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .colplanes = 1, @@ -199,7 +186,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "ARGB8888, 32 bpp", .fourcc = V4L2_PIX_FMT_RGB32, .depth = 32, .colplanes = 1, @@ -212,7 +198,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "YUV 4:4:4 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV24, .depth = 24, .colplanes = 2, @@ -225,7 +210,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "YUV 4:4:4 planar, Y/CrCb", .fourcc = V4L2_PIX_FMT_NV42, .depth = 24, .colplanes = 2, @@ -238,7 +222,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, }, { - .name = "YUV 4:2:2 planar, Y/CrCb", .fourcc = V4L2_PIX_FMT_NV61, .depth = 16, .colplanes = 2, @@ -251,7 +234,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:2 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV16, .depth = 16, .colplanes = 2, @@ -264,7 +246,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, }, { - .name = "YUV 4:2:0 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12, .depth = 12, .colplanes = 2, @@ -277,7 +258,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12, .depth = 12, .colplanes = 2, @@ -290,7 +270,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 planar, Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12, .depth = 12, .colplanes = 2, @@ -303,7 +282,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 planar, Y/CrCb", .fourcc = V4L2_PIX_FMT_NV21, .depth = 12, .colplanes = 2, @@ -316,7 +294,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 planar, Y/CrCb", .fourcc = V4L2_PIX_FMT_NV21, .depth = 12, .colplanes = 2, @@ -330,7 +307,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV420, .depth = 12, .colplanes = 3, @@ -343,7 +319,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV420, .depth = 12, .colplanes = 3, @@ -356,7 +331,6 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, }, { - .name = "Gray", .fourcc = V4L2_PIX_FMT_GREY, .depth = 8, .colplanes = 1, @@ -1314,7 +1288,6 @@ static int enum_fmt(struct s5p_jpeg_ctx *ctx, if (i >= n) return -EINVAL; - strscpy(f->description, sjpeg_formats[i].name, sizeof(f->description)); f->pixelformat = sjpeg_formats[i].fourcc; return 0; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 34f87f6c02f2..3bc52f83f5bc 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h @@ -150,7 +150,6 @@ struct s5p_jpeg_variant { /** * struct jpeg_fmt - driver's internal color format data - * @name: format description * @fourcc: the fourcc code, 0 if not applicable * @depth: number of bits per pixel * @colplanes: number of color planes (1 for packed formats) @@ -159,7 +158,6 @@ struct s5p_jpeg_variant { * @flags: flags describing format applicability */ struct s5p_jpeg_fmt { - char *name; u32 fourcc; int depth; int colplanes; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 5dc086516360..96d1ecd1521b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -718,7 +718,6 @@ struct s5p_mfc_ctx { * used by the MFC */ struct s5p_mfc_fmt { - char *name; u32 fourcc; u32 codec_mode; enum s5p_mfc_fmt_type type; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 4017c8b471f4..61e144a35201 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -29,7 +29,6 @@ static struct s5p_mfc_fmt formats[] = { { - .name = "4:2:0 2 Planes 16x16 Tiles", .fourcc = V4L2_PIX_FMT_NV12MT_16X16, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -37,7 +36,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6_BIT | MFC_V7_BIT, }, { - .name = "4:2:0 2 Planes 64x32 Tiles", .fourcc = V4L2_PIX_FMT_NV12MT, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -45,7 +43,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5_BIT, }, { - .name = "4:2:0 2 Planes Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12M, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -53,7 +50,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6PLUS_BITS, }, { - .name = "4:2:0 2 Planes Y/CrCb", .fourcc = V4L2_PIX_FMT_NV21M, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -61,7 +57,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6PLUS_BITS, }, { - .name = "H264 Encoded Stream", .fourcc = V4L2_PIX_FMT_H264, .codec_mode = S5P_MFC_CODEC_H264_DEC, .type = MFC_FMT_DEC, @@ -69,7 +64,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "H264/MVC Encoded Stream", .fourcc = V4L2_PIX_FMT_H264_MVC, .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC, .type = MFC_FMT_DEC, @@ -77,7 +71,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6PLUS_BITS, }, { - .name = "H263 Encoded Stream", .fourcc = V4L2_PIX_FMT_H263, .codec_mode = S5P_MFC_CODEC_H263_DEC, .type = MFC_FMT_DEC, @@ -85,7 +78,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "MPEG1 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG1, .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, .type = MFC_FMT_DEC, @@ -93,7 +85,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "MPEG2 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG2, .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, .type = MFC_FMT_DEC, @@ -101,7 +92,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "MPEG4 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG4, .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, .type = MFC_FMT_DEC, @@ -109,7 +99,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "XviD Encoded Stream", .fourcc = V4L2_PIX_FMT_XVID, .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, .type = MFC_FMT_DEC, @@ -117,7 +106,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "VC1 Encoded Stream", .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, .codec_mode = S5P_MFC_CODEC_VC1_DEC, .type = MFC_FMT_DEC, @@ -125,7 +113,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "VC1 RCV Encoded Stream", .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC, .type = MFC_FMT_DEC, @@ -133,7 +120,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "VP8 Encoded Stream", .fourcc = V4L2_PIX_FMT_VP8, .codec_mode = S5P_MFC_CODEC_VP8_DEC, .type = MFC_FMT_DEC, @@ -279,7 +265,6 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool out) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_fmt *fmt; int i, j = 0; for (i = 0; i < ARRAY_SIZE(formats); ++i) { @@ -296,9 +281,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, } if (i == ARRAY_SIZE(formats)) return -EINVAL; - fmt = &formats[i]; - strscpy(f->description, fmt->name, sizeof(f->description)); - f->pixelformat = fmt->fourcc; + f->pixelformat = formats[i].fourcc; return 0; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 97e76480e942..912fe0c5ab18 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -32,7 +32,6 @@ static struct s5p_mfc_fmt formats[] = { { - .name = "4:2:0 2 Planes 16x16 Tiles", .fourcc = V4L2_PIX_FMT_NV12MT_16X16, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -40,7 +39,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6_BIT | MFC_V7_BIT, }, { - .name = "4:2:0 2 Planes 64x32 Tiles", .fourcc = V4L2_PIX_FMT_NV12MT, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -48,7 +46,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5_BIT, }, { - .name = "4:2:0 2 Planes Y/CbCr", .fourcc = V4L2_PIX_FMT_NV12M, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -56,7 +53,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "4:2:0 2 Planes Y/CrCb", .fourcc = V4L2_PIX_FMT_NV21M, .codec_mode = S5P_MFC_CODEC_NONE, .type = MFC_FMT_RAW, @@ -64,7 +60,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V6PLUS_BITS, }, { - .name = "H264 Encoded Stream", .fourcc = V4L2_PIX_FMT_H264, .codec_mode = S5P_MFC_CODEC_H264_ENC, .type = MFC_FMT_ENC, @@ -72,7 +67,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "MPEG4 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG4, .codec_mode = S5P_MFC_CODEC_MPEG4_ENC, .type = MFC_FMT_ENC, @@ -80,7 +74,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "H263 Encoded Stream", .fourcc = V4L2_PIX_FMT_H263, .codec_mode = S5P_MFC_CODEC_H263_ENC, .type = MFC_FMT_ENC, @@ -88,7 +81,6 @@ static struct s5p_mfc_fmt formats[] = { .versions = MFC_V5PLUS_BITS, }, { - .name = "VP8 Encoded Stream", .fourcc = V4L2_PIX_FMT_VP8, .codec_mode = S5P_MFC_CODEC_VP8_ENC, .type = MFC_FMT_ENC, @@ -1320,7 +1312,6 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool out) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_fmt *fmt; int i, j = 0; for (i = 0; i < ARRAY_SIZE(formats); ++i) { @@ -1332,10 +1323,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, continue; if (j == f->index) { - fmt = &formats[i]; - strscpy(f->description, fmt->name, - sizeof(f->description)); - f->pixelformat = fmt->fourcc; + f->pixelformat = formats[i].fourcc; return 0; } ++j; diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 5a9ba05c996e..26360af2325e 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -86,7 +86,6 @@ struct sh_veu_file { }; struct sh_veu_format { - char *name; u32 fourcc; unsigned int depth; unsigned int ydepth; @@ -144,14 +143,14 @@ enum sh_veu_fmt_idx { * aligned for NV24. */ static const struct sh_veu_format sh_veu_fmt[] = { - [SH_VEU_FMT_NV12] = { .ydepth = 8, .depth = 12, .name = "NV12", .fourcc = V4L2_PIX_FMT_NV12 }, - [SH_VEU_FMT_NV16] = { .ydepth = 8, .depth = 16, .name = "NV16", .fourcc = V4L2_PIX_FMT_NV16 }, - [SH_VEU_FMT_NV24] = { .ydepth = 8, .depth = 24, .name = "NV24", .fourcc = V4L2_PIX_FMT_NV24 }, - [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .name = "RGB332", .fourcc = V4L2_PIX_FMT_RGB332 }, - [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .name = "RGB444", .fourcc = V4L2_PIX_FMT_RGB444 }, - [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565 }, - [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666 }, - [SH_VEU_FMT_RGB24] = { .ydepth = 24, .depth = 24, .name = "RGB24", .fourcc = V4L2_PIX_FMT_RGB24 }, + [SH_VEU_FMT_NV12] = { .ydepth = 8, .depth = 12, .fourcc = V4L2_PIX_FMT_NV12 }, + [SH_VEU_FMT_NV16] = { .ydepth = 8, .depth = 16, .fourcc = V4L2_PIX_FMT_NV16 }, + [SH_VEU_FMT_NV24] = { .ydepth = 8, .depth = 24, .fourcc = V4L2_PIX_FMT_NV24 }, + [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .fourcc = V4L2_PIX_FMT_RGB332 }, + [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .fourcc = V4L2_PIX_FMT_RGB444 }, + [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .fourcc = V4L2_PIX_FMT_RGB565 }, + [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .fourcc = V4L2_PIX_FMT_BGR666 }, + [SH_VEU_FMT_RGB24] = { .ydepth = 24, .depth = 24, .fourcc = V4L2_PIX_FMT_RGB24 }, }; #define DEFAULT_IN_VFMT (struct sh_veu_vfmt){ \ @@ -359,8 +358,6 @@ static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num) if (f->index >= fmt_num) return -EINVAL; - strscpy(f->description, sh_veu_fmt[fmt[f->index]].name, - sizeof(f->description)); f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc; return 0; } diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 5799aa4b9323..4fc1b4e11b70 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -138,7 +138,6 @@ static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg, struct sh_vou_fmt { u32 pfmt; - char *desc; unsigned char bpp; unsigned char bpl; unsigned char rgb; @@ -152,7 +151,6 @@ static struct sh_vou_fmt vou_fmt[] = { .pfmt = V4L2_PIX_FMT_NV12, .bpp = 12, .bpl = 1, - .desc = "YVU420 planar", .yf = 0, .rgb = 0, }, @@ -160,7 +158,6 @@ static struct sh_vou_fmt vou_fmt[] = { .pfmt = V4L2_PIX_FMT_NV16, .bpp = 16, .bpl = 1, - .desc = "YVYU planar", .yf = 1, .rgb = 0, }, @@ -168,7 +165,6 @@ static struct sh_vou_fmt vou_fmt[] = { .pfmt = V4L2_PIX_FMT_RGB24, .bpp = 24, .bpl = 3, - .desc = "RGB24", .pkf = 2, .rgb = 1, }, @@ -176,7 +172,6 @@ static struct sh_vou_fmt vou_fmt[] = { .pfmt = V4L2_PIX_FMT_RGB565, .bpp = 16, .bpl = 2, - .desc = "RGB565", .pkf = 3, .rgb = 1, }, @@ -184,7 +179,6 @@ static struct sh_vou_fmt vou_fmt[] = { .pfmt = V4L2_PIX_FMT_RGB565X, .bpp = 16, .bpl = 2, - .desc = "RGB565 byteswapped", .pkf = 3, .rgb = 1, }, @@ -398,9 +392,6 @@ static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - strscpy(fmt->description, vou_fmt[fmt->index].desc, - sizeof(fmt->description)); fmt->pixelformat = vou_fmt[fmt->index].pfmt; return 0; @@ -494,7 +485,8 @@ static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev, if (h_idx) vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1]; - dev_dbg(vou_dev->v4l2_dev.dev, "%s: scaling 0x%x\n", fmt->desc, vouvcr); + dev_dbg(vou_dev->v4l2_dev.dev, "0x%08x: scaling 0x%x\n", + fmt->pfmt, vouvcr); /* To produce a colour bar for testing set bit 23 of VOUVCR */ sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr); diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index dda04498ac56..60b575bb44c4 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -224,7 +224,6 @@ static const struct vpe_port_data port_data[11] = { /* driver info for each of the supported video formats */ struct vpe_fmt { - char *name; /* human-readable name */ u32 fourcc; /* standard format identifier */ u8 types; /* CAPTURE and/or OUTPUT */ u8 coplanar; /* set for unpacked Luma and Chroma */ @@ -234,7 +233,6 @@ struct vpe_fmt { static struct vpe_fmt vpe_formats[] = { { - .name = "NV16 YUV 422 co-planar", .fourcc = V4L2_PIX_FMT_NV16, .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, .coplanar = 1, @@ -243,7 +241,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "NV12 YUV 420 co-planar", .fourcc = V4L2_PIX_FMT_NV12, .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, .coplanar = 1, @@ -252,7 +249,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "YUYV 422 packed", .fourcc = V4L2_PIX_FMT_YUYV, .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, .coplanar = 0, @@ -260,7 +256,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "UYVY 422 packed", .fourcc = V4L2_PIX_FMT_UYVY, .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, .coplanar = 0, @@ -268,7 +263,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "RGB888 packed", .fourcc = V4L2_PIX_FMT_RGB24, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -276,7 +270,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "ARGB32", .fourcc = V4L2_PIX_FMT_RGB32, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -284,7 +277,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "BGR888 packed", .fourcc = V4L2_PIX_FMT_BGR24, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -292,7 +284,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "ABGR32", .fourcc = V4L2_PIX_FMT_BGR32, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -300,7 +291,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -308,7 +298,6 @@ static struct vpe_fmt vpe_formats[] = { }, }, { - .name = "RGB5551", .fourcc = V4L2_PIX_FMT_RGB555, .types = VPE_FMT_TYPE_CAPTURE, .coplanar = 0, @@ -1514,7 +1503,6 @@ static int __enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (!fmt) return -EINVAL; - strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 038de7a2027a..d5f811820be9 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -142,13 +142,11 @@ static struct via_camera *via_cam_info; * now this information must be managed at this level too. */ static struct via_format { - __u8 *desc; __u32 pixelformat; int bpp; /* Bytes per pixel */ u32 mbus_code; } via_formats[] = { { - .desc = "YUYV 4:2:2", .pixelformat = V4L2_PIX_FMT_YUYV, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 2, @@ -860,8 +858,6 @@ static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv, { if (fmt->index >= N_VIA_FMTS) return -EINVAL; - strscpy(fmt->description, via_formats[fmt->index].desc, - sizeof(fmt->description)); fmt->pixelformat = via_formats[fmt->index].pixelformat; return 0; } diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index c9d5fdb2d407..7bd2600cdc9a 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -524,8 +524,6 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) return -EINVAL; f->pixelformat = dma->format.pixelformat; - strscpy(f->description, dma->fmtinfo->description, - sizeof(f->description)); return 0; } diff --git a/drivers/media/platform/xilinx/xilinx-vip.c b/drivers/media/platform/xilinx/xilinx-vip.c index 08a825c3a3f6..6ad61b08a31a 100644 --- a/drivers/media/platform/xilinx/xilinx-vip.c +++ b/drivers/media/platform/xilinx/xilinx-vip.c @@ -25,21 +25,21 @@ static const struct xvip_video_format xvip_video_formats[] = { { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16, - 2, V4L2_PIX_FMT_YUYV, "4:2:2, packed, YUYV" }, + 2, V4L2_PIX_FMT_YUYV }, { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24, - 3, V4L2_PIX_FMT_YUV444, "4:4:4, packed, YUYV" }, + 3, V4L2_PIX_FMT_YUV444 }, { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24, - 3, 0, NULL }, + 3, 0 }, { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8, - 1, V4L2_PIX_FMT_GREY, "Greyscale 8-bit" }, + 1, V4L2_PIX_FMT_GREY }, { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8, - 1, V4L2_PIX_FMT_SRGGB8, "Bayer 8-bit RGGB" }, + 1, V4L2_PIX_FMT_SRGGB8 }, { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8, - 1, V4L2_PIX_FMT_SGRBG8, "Bayer 8-bit GRBG" }, + 1, V4L2_PIX_FMT_SGRBG8 }, { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8, - 1, V4L2_PIX_FMT_SGBRG8, "Bayer 8-bit GBRG" }, + 1, V4L2_PIX_FMT_SGBRG8 }, { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8, - 1, V4L2_PIX_FMT_SBGGR8, "Bayer 8-bit BGGR" }, + 1, V4L2_PIX_FMT_SBGGR8 }, }; /** diff --git a/drivers/media/platform/xilinx/xilinx-vip.h b/drivers/media/platform/xilinx/xilinx-vip.h index ba939dd52818..47da39211ae4 100644 --- a/drivers/media/platform/xilinx/xilinx-vip.h +++ b/drivers/media/platform/xilinx/xilinx-vip.h @@ -108,7 +108,6 @@ struct xvip_device { * @code: media bus format code * @bpp: bytes per pixel (when stored in memory) * @fourcc: V4L2 pixel format FCC identifier - * @description: format description, suitable for userspace */ struct xvip_video_format { unsigned int vf_code; @@ -117,7 +116,6 @@ struct xvip_video_format { unsigned int code; unsigned int bpp; u32 fourcc; - const char *description; }; const struct xvip_video_format *xvip_get_format_by_code(unsigned int code); diff --git a/include/media/drv-intf/exynos-fimc.h b/include/media/drv-intf/exynos-fimc.h index 59703439bb37..6b9ef631d6bb 100644 --- a/include/media/drv-intf/exynos-fimc.h +++ b/include/media/drv-intf/exynos-fimc.h @@ -87,7 +87,6 @@ struct fimc_source_info { /** * struct fimc_fmt - color format data structure * @mbus_code: media bus pixel code, -1 if not applicable - * @name: format description * @fourcc: fourcc code for this format, 0 if not applicable * @color: the driver's private color format id * @memplanes: number of physically non-contiguous data planes @@ -99,7 +98,6 @@ struct fimc_source_info { */ struct fimc_fmt { u32 mbus_code; - char *name; u32 fourcc; u32 color; u16 memplanes; -- GitLab From b2778a30c73b25bfd276bc9e7fad7585f2e80dbd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 02:46:37 -0400 Subject: [PATCH 0182/7155] media: am437x/davinci: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 6 ++---- drivers/media/platform/davinci/vpbe_display.c | 3 +-- drivers/media/platform/davinci/vpfe_capture.c | 3 +-- drivers/media/platform/davinci/vpif_capture.c | 3 +-- drivers/media/platform/davinci/vpif_display.c | 3 +-- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 7582c26f8459..105237edbb58 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1400,10 +1400,6 @@ static int vpfe_querycap(struct file *file, void *priv, strscpy(cap->card, "TI AM437x VPFE", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vpfe->v4l2_dev.name); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -2379,6 +2375,8 @@ static int vpfe_probe_complete(struct vpfe_device *vpfe) vdev->vfl_dir = VFL_DIR_RX; vdev->queue = q; vdev->lock = &vpfe->lock; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; video_set_drvdata(vdev, vpfe); err = video_register_device(&vpfe->video_dev, VFL_TYPE_GRABBER, -1); if (err) { diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index ed10a9bbf96b..9f1417e4b744 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -633,8 +633,6 @@ static int vpbe_display_querycap(struct file *file, void *priv, struct vpbe_layer *layer = video_drvdata(file); struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev; - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpbe_dev->pdev)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", @@ -1309,6 +1307,7 @@ static int init_vpbe_layer(int i, struct vpbe_display *disp_dev, vbd->v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev; vbd->lock = &vpbe_display_layer->opslock; vbd->vfl_dir = VFL_DIR_TX; + vbd->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; if (disp_dev->vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 295fbf1a49cf..852fc357e19d 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -877,8 +877,6 @@ static int vpfe_querycap(struct file *file, void *priv, v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); @@ -1785,6 +1783,7 @@ static int vpfe_probe(struct platform_device *pdev) vfd->ioctl_ops = &vpfe_ioctl_ops; vfd->tvnorms = 0; vfd->v4l2_dev = &vpfe_dev->v4l2_dev; + vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; snprintf(vfd->name, sizeof(vfd->name), "%s_V%d.%d.%d", CAPTURE_DRV_NAME, diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 621d28470d2b..9fe7caf6aa13 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1078,8 +1078,6 @@ static int vpif_querycap(struct file *file, void *priv, { struct vpif_capture_config *config = vpif_dev->platform_data; - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vpif_dev)); @@ -1466,6 +1464,7 @@ static int vpif_probe_complete(void) vdev->vfl_dir = VFL_DIR_RX; vdev->queue = q; vdev->lock = &common->lock; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; video_set_drvdata(&ch->video_dev, ch); err = video_register_device(vdev, VFL_TYPE_GRABBER, (j ? 1 : 0)); diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index be32f87001cd..abbdbac08e6f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -584,8 +584,6 @@ static int vpif_querycap(struct file *file, void *priv, { struct vpif_display_config *config = vpif_dev->platform_data; - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vpif_dev)); @@ -1214,6 +1212,7 @@ static int vpif_probe_complete(void) vdev->vfl_dir = VFL_DIR_TX; vdev->queue = q; vdev->lock = &common->lock; + vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; video_set_drvdata(&ch->video_dev, ch); err = video_register_device(vdev, VFL_TYPE_GRABBER, (j ? 3 : 2)); -- GitLab From e7999846b9448a84083a913f0e882a93b4d9d123 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 02:48:20 -0400 Subject: [PATCH 0183/7155] media: coda: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 01428de2596e..73222c0615c0 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -390,9 +390,6 @@ static int coda_querycap(struct file *file, void *priv, strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), sizeof(cap->card)); strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -2699,6 +2696,7 @@ static int coda_register_device(struct coda_dev *dev, int i) vfd->lock = &dev->dev_mutex; vfd->v4l2_dev = &dev->v4l2_dev; vfd->vfl_dir = VFL_DIR_M2M; + vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; video_set_drvdata(vfd, dev); /* Not applicable, use the selection API instead */ -- GitLab From 994587c3b27615fd0309ce61fe2cc5695a64b934 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 02:51:41 -0400 Subject: [PATCH 0184/7155] media: s3c-camif/s5p-g2d/s5p-jpeg: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-capture.c | 5 +---- drivers/media/platform/s5p-g2d/g2d.c | 3 +-- drivers/media/platform/s5p-jpeg/jpeg-core.c | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 2191fdded9da..2fb45db8e4ba 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -641,10 +641,6 @@ static int s3c_camif_vidioc_querycap(struct file *file, void *priv, strscpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s.%d", dev_name(vp->camif->dev), vp->id); - - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -1160,6 +1156,7 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx) goto err_me_cleanup; vfd->ctrl_handler = &vp->ctrl_handler; + vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index b3fc0ff8a5ec..f5f05ea9f521 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -291,8 +291,6 @@ static int vidioc_querycap(struct file *file, void *priv, strscpy(cap->driver, G2D_NAME, sizeof(cap->driver)); strscpy(cap->card, G2D_NAME, sizeof(cap->card)); cap->bus_info[0] = 0; - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -696,6 +694,7 @@ static int g2d_probe(struct platform_device *pdev) set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags); vfd->lock = &dev->mutex; vfd->v4l2_dev = &dev->v4l2_dev; + vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 20cad061e908..8dbbd5f2a40a 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1259,8 +1259,6 @@ static int s5p_jpeg_querycap(struct file *file, void *priv, } snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(ctx->jpeg->dev)); - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -2947,6 +2945,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) jpeg->vfd_encoder->lock = &jpeg->lock; jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev; jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M; + jpeg->vfd_encoder->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1); if (ret) { @@ -2976,6 +2975,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) jpeg->vfd_decoder->lock = &jpeg->lock; jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev; jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M; + jpeg->vfd_decoder->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1); if (ret) { -- GitLab From b3322e3e1aae4705f0d3ca3478a5cf484255c0a7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:12:55 -0400 Subject: [PATCH 0185/7155] media: fsl-viu: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/fsl-viu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 691be788e38b..bf5392f0d61c 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -563,11 +563,6 @@ static int vidioc_querycap(struct file *file, void *priv, strscpy(cap->driver, "viu", sizeof(cap->driver)); strscpy(cap->card, "viu", sizeof(cap->card)); strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_VIDEO_OVERLAY | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1380,6 +1375,8 @@ static const struct video_device viu_template = { .release = video_device_release, .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE, }; static int viu_of_probe(struct platform_device *op) -- GitLab From f456ccc457cb2a141a5269e7fcfdaa8cbf641229 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:13:23 -0400 Subject: [PATCH 0186/7155] media: m2m-deinterlace: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/m2m-deinterlace.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index e9310eeec6cf..bbf664546697 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -434,15 +434,6 @@ static int vidioc_querycap(struct file *file, void *priv, strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card)); - /* - * This is only a mem-to-mem video device. The capture and output - * device capability flags are left only for backward compatibility - * and are scheduled for removal. - */ - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | - V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -968,6 +959,7 @@ static const struct video_device deinterlace_videodev = { .minor = -1, .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, + .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, }; static const struct v4l2_m2m_ops m2m_ops = { -- GitLab From bc6be26ed825ef7a9a131637627ab4719a586f4c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:13:50 -0400 Subject: [PATCH 0187/7155] media: mx2_emmaprp: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mx2_emmaprp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 4d4225ab1589..4dd32f4f1dda 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -380,8 +380,6 @@ static int vidioc_querycap(struct file *file, void *priv, { strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -862,6 +860,7 @@ static const struct video_device emmaprp_videodev = { .minor = -1, .release = video_device_release, .vfl_dir = VFL_DIR_M2M, + .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, }; static const struct v4l2_m2m_ops m2m_ops = { -- GitLab From 34828fad5ecc709bd76194a1ec89424973f70c48 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:14:15 -0400 Subject: [PATCH 0188/7155] media: marvell-ccic: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mcam-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 30ac454e702e..803baf97f06e 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -1349,9 +1349,6 @@ static int mcam_vidioc_querycap(struct file *file, void *priv, strscpy(cap->driver, "marvell_ccic", sizeof(cap->driver)); strscpy(cap->card, "marvell_ccic", sizeof(cap->card)); strscpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1688,6 +1685,8 @@ static const struct video_device mcam_v4l_template = { .fops = &mcam_v4l_fops, .ioctl_ops = &mcam_v4l_ioctl_ops, .release = video_device_release_empty, + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, }; /* ---------------------------------------------------------------------- */ -- GitLab From de5b9b71975927ca36441944e5f76126bf3e9d7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:14:39 -0400 Subject: [PATCH 0189/7155] media: pxa_camera: don't set caps in querycap The device_caps in struct video_device are already set correctly, so there is no need to set them in querycap again. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/pxa_camera.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index 1c9bfaabc54c..53682da099c5 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -1992,9 +1992,6 @@ static int pxac_vidioc_querycap(struct file *file, void *priv, strscpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info)); strscpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver)); strscpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } -- GitLab From 3c7812e7ef30d177fd6234d03d1c1612447fd9f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:15:02 -0400 Subject: [PATCH 0190/7155] media: bdisp: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Fabien Dessenne Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/bdisp/bdisp-v4l2.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 79f7db1a9d18..e90f1ba30574 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -692,11 +692,6 @@ static int bdisp_querycap(struct file *file, void *fh, strscpy(cap->card, bdisp->pdev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", BDISP_NAME, bdisp->id); - - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; - - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -1059,6 +1054,7 @@ static int bdisp_register_device(struct bdisp_dev *bdisp) bdisp->vdev.lock = &bdisp->lock; bdisp->vdev.vfl_dir = VFL_DIR_M2M; bdisp->vdev.v4l2_dev = &bdisp->v4l2_dev; + bdisp->vdev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; snprintf(bdisp->vdev.name, sizeof(bdisp->vdev.name), "%s.%d", BDISP_NAME, bdisp->id); -- GitLab From 0fe3331e07f0a09c10fd81e48976255b50b2e607 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:15:23 -0400 Subject: [PATCH 0191/7155] media: via-camera: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/via-camera.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index d5f811820be9..4110dc4c771e 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -988,9 +988,6 @@ static int viacam_querycap(struct file *filp, void *priv, { strscpy(cap->driver, "via-camera", sizeof(cap->driver)); strscpy(cap->card, "via-camera", sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1267,6 +1264,8 @@ static const struct video_device viacam_v4l_template = { .fops = &viacam_fops, .ioctl_ops = &viacam_ioctl_ops, .release = video_device_release_empty, /* Check this */ + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, }; /* -- GitLab From b1df3129b71979b1196935a1e29bfe9ac7f28ab6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:15:44 -0400 Subject: [PATCH 0192/7155] media: xilinx: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/xilinx/xilinx-dma.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index 7bd2600cdc9a..b211380a11f2 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -491,15 +491,8 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) struct v4l2_fh *vfh = file->private_data; struct xvip_dma *dma = to_xvip_dma(vfh->vdev); - cap->device_caps = V4L2_CAP_STREAMING; - - if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; - else - cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT; - - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS - | dma->xdev->v4l2_caps; + cap->capabilities = dma->xdev->v4l2_caps | V4L2_CAP_STREAMING | + V4L2_CAP_DEVICE_CAPS; strscpy(cap->driver, "xilinx-vipp", sizeof(cap->driver)); strscpy(cap->card, dma->video.name, sizeof(cap->card)); @@ -698,6 +691,11 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma, dma->video.release = video_device_release_empty; dma->video.ioctl_ops = &xvip_dma_ioctl_ops; dma->video.lock = &dma->lock; + dma->video.device_caps = V4L2_CAP_STREAMING; + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + dma->video.device_caps |= V4L2_CAP_VIDEO_CAPTURE; + else + dma->video.device_caps |= V4L2_CAP_VIDEO_OUTPUT; video_set_drvdata(&dma->video, dma); -- GitLab From 8defd70a9b2ffb49bd070dc2211d79f6cfb29d7e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:16:07 -0400 Subject: [PATCH 0193/7155] media: sh_veu/sh_vou: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_veu.c | 4 +--- drivers/media/platform/sh_vou.c | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 26360af2325e..4be6efd47d33 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -347,9 +347,6 @@ static int sh_veu_querycap(struct file *file, void *priv, strscpy(cap->driver, "sh-veu", sizeof(cap->driver)); strscpy(cap->card, "sh-mobile VEU", sizeof(cap->card)); strscpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -1036,6 +1033,7 @@ static const struct video_device sh_veu_videodev = { .minor = -1, .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, + .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, }; static const struct v4l2_m2m_ops sh_veu_m2m_ops = { diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 4fc1b4e11b70..2236702c21b4 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -375,9 +375,6 @@ static int sh_vou_querycap(struct file *file, void *priv, strscpy(cap->card, "SuperH VOU", sizeof(cap->card)); strscpy(cap->driver, "sh-vou", sizeof(cap->driver)); strscpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1210,6 +1207,8 @@ static const struct video_device sh_vou_video_template = { .ioctl_ops = &sh_vou_ioctl_ops, .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ .vfl_dir = VFL_DIR_TX, + .device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, }; static int sh_vou_probe(struct platform_device *pdev) -- GitLab From 4038b214b88e6962406bcc32e1056f3fb6eb11d7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:16:36 -0400 Subject: [PATCH 0194/7155] media: vsp1: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_histo.c | 3 +-- drivers/media/platform/vsp1/vsp1_video.c | 10 ++++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 8b01e99acd20..30d751f2cccf 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -426,8 +426,6 @@ static int histo_v4l2_querycap(struct file *file, void *fh, | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_META_CAPTURE; - cap->device_caps = V4L2_CAP_META_CAPTURE - | V4L2_CAP_STREAMING; strscpy(cap->driver, "vsp1", sizeof(cap->driver)); strscpy(cap->card, histo->video.name, sizeof(cap->card)); @@ -556,6 +554,7 @@ int vsp1_histogram_init(struct vsp1_device *vsp1, struct vsp1_histogram *histo, histo->video.vfl_type = VFL_TYPE_GRABBER; histo->video.release = video_device_release_empty; histo->video.ioctl_ops = &histo_v4l2_ioctl_ops; + histo->video.device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; video_set_drvdata(&histo->video, histo); diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index fd98e483b2f4..5e59ed2c3614 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -956,12 +956,6 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) | V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE; - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE - | V4L2_CAP_STREAMING; - else - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE - | V4L2_CAP_STREAMING; strscpy(cap->driver, "vsp1", sizeof(cap->driver)); strscpy(cap->card, video->video.name, sizeof(cap->card)); @@ -1268,11 +1262,15 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; video->pad.flags = MEDIA_PAD_FL_SOURCE; video->video.vfl_dir = VFL_DIR_TX; + video->video.device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_STREAMING; } else { direction = "output"; video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; video->pad.flags = MEDIA_PAD_FL_SINK; video->video.vfl_dir = VFL_DIR_RX; + video->video.device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_STREAMING; } mutex_init(&video->lock); -- GitLab From c7711aba06696c48343cb4616813f6de295a5573 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:16:54 -0400 Subject: [PATCH 0195/7155] media: omap_vout: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap/omap_vout.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 1f6742536c46..151752de0d02 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -1039,10 +1039,6 @@ static int vidioc_querycap(struct file *file, void *fh, strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); strscpy(cap->card, vout->vfd->name, sizeof(cap->card)); cap->bus_info[0] = '\0'; - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | - V4L2_CAP_VIDEO_OUTPUT_OVERLAY; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -1863,6 +1859,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) vfd->fops = &omap_vout_fops; vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; vfd->vfl_dir = VFL_DIR_TX; + vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_OUTPUT_OVERLAY; mutex_init(&vout->lock); vfd->minor = -1; -- GitLab From eefe332c15967f40df7cc0cbc054523e7d6b1fc9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:17:17 -0400 Subject: [PATCH 0196/7155] media: ti-vpe: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Acked-by: Benoit Parrot Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/cal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 9e86d761546b..78cdbd671dd5 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -913,9 +913,6 @@ static int cal_querycap(struct file *file, void *priv, snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ctx->v4l2_dev.name); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1419,6 +1416,8 @@ static const struct video_device cal_videodev = { .ioctl_ops = &cal_ioctl_ops, .minor = -1, .release = video_device_release_empty, + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE, }; /* ----------------------------------------------------------------- -- GitLab From 616cfb69b9848ad8dcb67f00c1914e69552325a2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 03:17:47 -0400 Subject: [PATCH 0197/7155] media: omap3isp: set device_caps in struct video_device Instead of filling in the struct v4l2_capability device_caps field, fill in the struct video_device device_caps field. That way the V4L2 core knows what the capabilities of the video device are. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 499a7284c5a8..b52c6fe825ac 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -658,10 +658,6 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - else - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; return 0; } @@ -1460,6 +1456,13 @@ int omap3isp_video_init(struct isp_video *video, const char *name) video->video.vfl_type = VFL_TYPE_GRABBER; video->video.release = video_device_release_empty; video->video.ioctl_ops = &isp_video_ioctl_ops; + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + video->video.device_caps = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_STREAMING; + else + video->video.device_caps = V4L2_CAP_VIDEO_OUTPUT + | V4L2_CAP_STREAMING; + video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED; video_set_drvdata(&video->video, video); -- GitLab From 66b5f1c439843bcbab01cc7f3854ae2742f3d1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 18 Jul 2019 23:30:03 -0700 Subject: [PATCH 0198/7155] net-ipv6-ndisc: add support for RFC7710 RA Captive Portal Identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is trivial since we already have support for the entirely identical (from the kernel's point of view) RDNSS and DNSSL that also contain opaque data that needs to be passed down to userspace. As specified in RFC7710, Captive Portal option contains a URL. 8-bit identifier of the option type as assigned by the IANA is 37. This option should also be treated as userland. Hence, treat ND option 37 as userland (Captive Portal support) See: https://tools.ietf.org/html/rfc7710 https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml Fixes: e35f30c131a56 Signed-off-by: Maciej Żenczykowski Cc: Lorenzo Colitti Cc: Remin Nguyen Van Cc: Alexey I. Froloff Signed-off-by: David S. Miller --- include/net/ndisc.h | 1 + net/ipv6/ndisc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 366150053043..b2f715ca0567 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -40,6 +40,7 @@ enum { ND_OPT_RDNSS = 25, /* RFC5006 */ ND_OPT_DNSSL = 31, /* RFC6106 */ ND_OPT_6CO = 34, /* RFC6775 */ + ND_OPT_CAPTIVE_PORTAL = 37, /* RFC7710 */ __ND_OPT_MAX }; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 083cc1c94cd3..53caf59c591e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -196,6 +196,7 @@ static inline int ndisc_is_useropt(const struct net_device *dev, { return opt->nd_opt_type == ND_OPT_RDNSS || opt->nd_opt_type == ND_OPT_DNSSL || + opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || ndisc_ops_is_useropt(dev, opt->nd_opt_type); } -- GitLab From de8145452eebe5510bd2b142b31560db548d6abb Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 11 Jul 2019 16:26:41 -0400 Subject: [PATCH 0199/7155] media: v4l2-ctrl: Move compound control validation Rework std_validate moving the compound controls to its own validation function. While here, fix the pointer math to account the index parameter. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 126 +++++++++++++++------------ 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 371537dd8cd3..739418aa9108 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1629,10 +1629,77 @@ static void std_log(const struct v4l2_ctrl *ctrl) }) /* Validate a new control */ +static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr) +{ + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + void *p = ptr.p + idx * ctrl->elem_size; + + switch ((u32)ctrl->type) { + case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: + p_mpeg2_slice_params = p; + + switch (p_mpeg2_slice_params->sequence.chroma_format) { + case 1: /* 4:2:0 */ + case 2: /* 4:2:2 */ + case 3: /* 4:4:4 */ + break; + default: + return -EINVAL; + } + + switch (p_mpeg2_slice_params->picture.intra_dc_precision) { + case 0: /* 8 bits */ + case 1: /* 9 bits */ + case 2: /* 10 bits */ + case 3: /* 11 bits */ + break; + default: + return -EINVAL; + } + + switch (p_mpeg2_slice_params->picture.picture_structure) { + case 1: /* interlaced top field */ + case 2: /* interlaced bottom field */ + case 3: /* progressive */ + break; + default: + return -EINVAL; + } + + switch (p_mpeg2_slice_params->picture.picture_coding_type) { + case V4L2_MPEG2_PICTURE_CODING_TYPE_I: + case V4L2_MPEG2_PICTURE_CODING_TYPE_P: + case V4L2_MPEG2_PICTURE_CODING_TYPE_B: + break; + default: + return -EINVAL; + } + + break; + + case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: + break; + + case V4L2_CTRL_TYPE_FWHT_PARAMS: + break; + + case V4L2_CTRL_TYPE_H264_SPS: + case V4L2_CTRL_TYPE_H264_PPS: + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: + break; + default: + return -EINVAL; + } + + return 0; +} + static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr) { - struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; size_t len; u64 offset; s64 val; @@ -1695,63 +1762,8 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, return -ERANGE; return 0; - case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: - p_mpeg2_slice_params = ptr.p; - - switch (p_mpeg2_slice_params->sequence.chroma_format) { - case 1: /* 4:2:0 */ - case 2: /* 4:2:2 */ - case 3: /* 4:4:4 */ - break; - default: - return -EINVAL; - } - - switch (p_mpeg2_slice_params->picture.intra_dc_precision) { - case 0: /* 8 bits */ - case 1: /* 9 bits */ - case 2: /* 10 bits */ - case 3: /* 11 bits */ - break; - default: - return -EINVAL; - } - - switch (p_mpeg2_slice_params->picture.picture_structure) { - case 1: /* interlaced top field */ - case 2: /* interlaced bottom field */ - case 3: /* progressive */ - break; - default: - return -EINVAL; - } - - switch (p_mpeg2_slice_params->picture.picture_coding_type) { - case V4L2_MPEG2_PICTURE_CODING_TYPE_I: - case V4L2_MPEG2_PICTURE_CODING_TYPE_P: - case V4L2_MPEG2_PICTURE_CODING_TYPE_B: - break; - default: - return -EINVAL; - } - - return 0; - - case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: - return 0; - - case V4L2_CTRL_TYPE_FWHT_PARAMS: - return 0; - - case V4L2_CTRL_TYPE_H264_SPS: - case V4L2_CTRL_TYPE_H264_PPS: - case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: - case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: - case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: - return 0; - default: - return -EINVAL; + return std_validate_compound(ctrl, idx, ptr); } } -- GitLab From bb448f8a60ea93722edb28418448e0008d148b0c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 19 Jul 2019 15:36:15 +0800 Subject: [PATCH 0200/7155] net: lan78xx: Merge memcpy + lexx_to_cpus to get_unaligned_lexx Merge the combo use of memcpy and lexx_to_cpus. Use get_unaligned_lexx instead. This simplifies the code. Signed-off-by: Chuhong Yuan Acked-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 3d92ea6fcc02..9c33b35bd155 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1258,8 +1258,7 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb) return; } - memcpy(&intdata, urb->transfer_buffer, 4); - le32_to_cpus(&intdata); + intdata = get_unaligned_le32(urb->transfer_buffer); if (intdata & INT_ENP_PHY_INT) { netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata); @@ -3105,16 +3104,13 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb) struct sk_buff *skb2; unsigned char *packet; - memcpy(&rx_cmd_a, skb->data, sizeof(rx_cmd_a)); - le32_to_cpus(&rx_cmd_a); + rx_cmd_a = get_unaligned_le32(skb->data); skb_pull(skb, sizeof(rx_cmd_a)); - memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b)); - le32_to_cpus(&rx_cmd_b); + rx_cmd_b = get_unaligned_le32(skb->data); skb_pull(skb, sizeof(rx_cmd_b)); - memcpy(&rx_cmd_c, skb->data, sizeof(rx_cmd_c)); - le16_to_cpus(&rx_cmd_c); + rx_cmd_c = get_unaligned_le16(skb->data); skb_pull(skb, sizeof(rx_cmd_c)); packet = skb->data; -- GitLab From 5864118b6a442ac947207489193319489911e7b3 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 19 Jul 2019 16:27:31 +0800 Subject: [PATCH 0201/7155] usbnet: smsc75xx: Merge memcpy + le32_to_cpus to get_unaligned_le32 Merge the combo use of memcpy and le32_to_cpus. Use get_unaligned_le32 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/usb/smsc75xx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 1417a22962a1..7fac9db5380d 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -661,8 +661,7 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb) return; } - memcpy(&intdata, urb->transfer_buffer, 4); - le32_to_cpus(&intdata); + intdata = get_unaligned_le32(urb->transfer_buffer); netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata); @@ -2181,12 +2180,10 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) struct sk_buff *ax_skb; unsigned char *packet; - memcpy(&rx_cmd_a, skb->data, sizeof(rx_cmd_a)); - le32_to_cpus(&rx_cmd_a); + rx_cmd_a = get_unaligned_le32(skb->data); skb_pull(skb, 4); - memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b)); - le32_to_cpus(&rx_cmd_b); + rx_cmd_b = get_unaligned_le32(skb->data); skb_pull(skb, 4 + RXW_PADDING); packet = skb->data; -- GitLab From d1854d509d61d36af44f2130423bff8836e1592e Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 19 Jul 2019 17:07:15 +0800 Subject: [PATCH 0202/7155] ax88179_178a: Merge memcpy + le32_to_cpus to get_unaligned_le32 Merge the combo use of memcpy and le32_to_cpus. Use get_unaligned_le32 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/usb/ax88179_178a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 0bc457ba8574..72d165114b67 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1366,8 +1366,7 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 0; skb_trim(skb, skb->len - 4); - memcpy(&rx_hdr, skb_tail_pointer(skb), 4); - le32_to_cpus(&rx_hdr); + rx_hdr = get_unaligned_le32(skb_tail_pointer(skb)); pkt_cnt = (u16)rx_hdr; hdr_off = (u16)(rx_hdr >> 16); -- GitLab From a57d6acaf352d91e52271704f45c72e14cd2d98a Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Thu, 11 Jul 2019 16:26:42 -0400 Subject: [PATCH 0203/7155] media: uapi: Add VP8 stateless decoder API Add the parsed VP8 frame pixel format and controls, to be used with the new stateless decoder API for VP8 to provide parameters for accelerator (aka stateless) codecs. Reviewed-by: Tomasz Figa Reviewed-by: Boris Brezillon Reviewed-by: Nicolas Dufresne Signed-off-by: Pawel Osciak Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/biblio.rst | 10 + .../media/uapi/v4l/ext-ctrls-codec.rst | 323 ++++++++++++++++++ .../media/uapi/v4l/pixfmt-compressed.rst | 20 ++ drivers/media/v4l2-core/v4l2-ctrls.c | 10 + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + include/media/v4l2-ctrls.h | 3 + include/media/vp8-ctrls.h | 110 ++++++ 7 files changed, 477 insertions(+) create mode 100644 include/media/vp8-ctrls.h diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst index 8f4eb8823d82..ad2ff258afa8 100644 --- a/Documentation/media/uapi/v4l/biblio.rst +++ b/Documentation/media/uapi/v4l/biblio.rst @@ -395,3 +395,13 @@ colimg :title: Color Imaging: Fundamentals and Applications :author: Erik Reinhard et al. + +.. _vp8: + +VP8 +=== + + +:title: RFC 6386: "VP8 Data Format and Decoding Guide" + +:author: J. Bankoski et al. diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst index d6ea2ffd65c5..c5f39dd50043 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst @@ -2234,6 +2234,329 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - Quantization parameter for a P frame for FWHT. Valid range: from 1 to 31. +.. _v4l2-mpeg-vp8: + +``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (struct)`` + Specifies the frame parameters for the associated VP8 parsed frame data. + This includes the necessary parameters for + configuring a stateless hardware decoding pipeline for VP8. + The bitstream parameters are defined according to :ref:`vp8`. + + .. note:: + + This compound control is not yet part of the public kernel API and + it is expected to change. + +.. c:type:: v4l2_ctrl_vp8_frame_header + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_vp8_frame_header + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - struct :c:type:`v4l2_vp8_segment_header` + - ``segment_header`` + - Structure with segment-based adjustments metadata. + * - struct :c:type:`v4l2_vp8_loopfilter_header` + - ``loopfilter_header`` + - Structure with loop filter level adjustments metadata. + * - struct :c:type:`v4l2_vp8_quantization_header` + - ``quant_header`` + - Structure with VP8 dequantization indices metadata. + * - struct :c:type:`v4l2_vp8_entropy_header` + - ``entropy_header`` + - Structure with VP8 entropy coder probabilities metadata. + * - struct :c:type:`v4l2_vp8_entropy_coder_state` + - ``coder_state`` + - Structure with VP8 entropy coder state. + * - __u16 + - ``width`` + - The width of the frame. Must be set for all frames. + * - __u16 + - ``height`` + - The height of the frame. Must be set for all frames. + * - __u8 + - ``horizontal_scale`` + - Horizontal scaling factor. + * - __u8 + - ``vertical_scaling factor`` + - Vertical scale. + * - __u8 + - ``version`` + - Bitstream version. + * - __u8 + - ``prob_skip_false`` + - Indicates the probability that the macroblock is not skipped. + * - __u8 + - ``prob_intra`` + - Indicates the probability that a macroblock is intra-predicted. + * - __u8 + - ``prob_last`` + - Indicates the probability that the last reference frame is used + for inter-prediction + * - __u8 + - ``prob_gf`` + - Indicates the probability that the golden reference frame is used + for inter-prediction + * - __u8 + - ``num_dct_parts`` + - Number of DCT coefficients partitions. Must be one of: 1, 2, 4, or 8. + * - __u32 + - ``first_part_size`` + - Size of the first partition, i.e. the control partition. + * - __u32 + - ``first_part_header_bits`` + - Size in bits of the first partition header portion. + * - __u32 + - ``dct_part_sizes[8]`` + - DCT coefficients sizes. + * - __u64 + - ``last_frame_ts`` + - Timestamp for the V4L2 capture buffer to use as last reference frame, used + with inter-coded frames. The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u64 + - ``golden_frame_ts`` + - Timestamp for the V4L2 capture buffer to use as last reference frame, used + with inter-coded frames. The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u64 + - ``alt_frame_ts`` + - Timestamp for the V4L2 capture buffer to use as alternate reference frame, used + with inter-coded frames. The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u64 + - ``flags`` + - See :ref:`Frame Header Flags ` + +.. _vp8_frame_header_flags: + +``Frame Header Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME`` + - 0x01 + - Indicates if the frame is a key frame. + * - ``V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL`` + - 0x02 + - Experimental bitstream. + * - ``V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME`` + - 0x04 + - Show frame flag, indicates if the frame is for display. + * - ``V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF`` + - 0x08 + - Enable/disable skipping of macroblocks with no non-zero coefficients. + * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN`` + - 0x10 + - Sign of motion vectors when the golden frame is referenced. + * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT`` + - 0x20 + - Sign of motion vectors when the alt frame is referenced. + +.. c:type:: v4l2_vp8_entropy_coder_state + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + +.. flat-table:: struct v4l2_vp8_entropy_coder_state + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``range`` + - + * - __u8 + - ``value`` + - + * - __u8 + - ``bit_count`` + - + * - __u8 + - ``padding`` + - Applications and drivers must set this to zero. + +.. c:type:: v4l2_vp8_segment_header + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + +.. flat-table:: struct v4l2_vp8_segment_header + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __s8 + - ``quant_update[4]`` + - Signed quantizer value update. + * - __s8 + - ``lf_update[4]`` + - Signed loop filter level value update. + * - __u8 + - ``segment_probs[3]`` + - Segment probabilities. + * - __u8 + - ``padding`` + - Applications and drivers must set this to zero. + * - __u32 + - ``flags`` + - See :ref:`Segment Header Flags ` + +.. _vp8_segment_header_flags: + +``Segment Header Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED`` + - 0x01 + - Enable/disable segment-based adjustments. + * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP`` + - 0x02 + - Indicates if the macroblock segmentation map is updated in this frame. + * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA`` + - 0x04 + - Indicates if the segment feature data is updated in this frame. + * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE`` + - 0x08 + - If is set, the segment feature data mode is delta-value. + If cleared, it's absolute-value. + +.. c:type:: v4l2_vp8_loopfilter_header + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + +.. flat-table:: struct v4l2_vp8_loopfilter_header + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __s8 + - ``ref_frm_delta[4]`` + - Reference adjustment (signed) delta value. + * - __s8 + - ``mb_mode_delta[4]`` + - Macroblock prediction mode adjustment (signed) delta value. + * - __u8 + - ``sharpness_level`` + - Sharpness level + * - __u8 + - ``level`` + - Filter level + * - __u16 + - ``padding`` + - Applications and drivers must set this to zero. + * - __u32 + - ``flags`` + - See :ref:`Loopfilter Header Flags ` + +.. _vp8_loopfilter_header_flags: + +``Loopfilter Header Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP8_LF_HEADER_ADJ_ENABLE`` + - 0x01 + - Enable/disable macroblock-level loop filter adjustment. + * - ``V4L2_VP8_LF_HEADER_DELTA_UPDATE`` + - 0x02 + - Indicates if the delta values used in an adjustment are updated. + * - ``V4L2_VP8_LF_FILTER_TYPE_SIMPLE`` + - 0x04 + - If set, indicates the filter type is simple. + If cleared, the filter type is normal. + +.. c:type:: v4l2_vp8_quantization_header + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + +.. flat-table:: struct v4l2_vp8_quantization_header + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``y_ac_qi`` + - Luma AC coefficient table index. + * - __s8 + - ``y_dc_delta`` + - Luma DC delta vaue. + * - __s8 + - ``y2_dc_delta`` + - Y2 block DC delta value. + * - __s8 + - ``y2_ac_delta`` + - Y2 block AC delta value. + * - __s8 + - ``uv_dc_delta`` + - Chroma DC delta value. + * - __s8 + - ``uv_ac_delta`` + - Chroma AC delta value. + * - __u16 + - ``padding`` + - Applications and drivers must set this to zero. + +.. c:type:: v4l2_vp8_entropy_header + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + +.. flat-table:: struct v4l2_vp8_entropy_header + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``coeff_probs[4][8][3][11]`` + - Coefficient update probabilities. + * - __u8 + - ``y_mode_probs[4]`` + - Luma mode update probabilities. + * - __u8 + - ``uv_mode_probs[3]`` + - Chroma mode update probabilities. + * - __u8 + - ``mv_probs[2][19]`` + - MV decoding update probabilities. + * - __u8 + - ``padding[3]`` + - Applications and drivers must set this to zero. + .. raw:: latex \normalsize diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst index 4b701fc7653e..f52a7b67023d 100644 --- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst +++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst @@ -133,6 +133,26 @@ Compressed Formats - ``V4L2_PIX_FMT_VP8`` - 'VP80' - VP8 video elementary stream. + * .. _V4L2-PIX-FMT-VP8-FRAME: + + - ``V4L2_PIX_FMT_VP8_FRAME`` + - 'VP8F' + - VP8 parsed frame, as extracted from the container. + This format is adapted for stateless video decoders that implement a + VP8 pipeline (using the :ref:`mem2mem` and :ref:`media-request-api`). + Metadata associated with the frame to decode is required to be passed + through the ``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER`` control. + See the :ref:`associated Codec Control IDs `. + Exactly one output and one capture buffer must be provided for use with + this pixel format. The output buffer must contain the appropriate number + of macroblocks to decode a full corresponding frame to the matching + capture buffer. + + .. note:: + + This format is not yet part of the public kernel API and it + is expected to change. + * .. _V4L2-PIX-FMT-VP9: - ``V4L2_PIX_FMT_VP9`` diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 739418aa9108..b2c9f5816c4a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -885,6 +885,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value"; case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; /* HEVC controls */ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; @@ -1345,6 +1346,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; break; + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; + break; default: *type = V4L2_CTRL_TYPE_INTEGER; break; @@ -1690,6 +1694,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: break; + + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + break; default: return -EINVAL; } @@ -2360,6 +2367,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); break; + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); + break; default: if (type < V4L2_CTRL_COMPOUND_TYPES) elem_size = sizeof(s32); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 20cc23ef730e..80efc581e3f9 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1348,6 +1348,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break; case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break; case V4L2_PIX_FMT_VP8: descr = "VP8"; break; + case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; case V4L2_PIX_FMT_VP9: descr = "VP9"; break; case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index b4433483af23..6e9dc9c44bb1 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -20,6 +20,7 @@ #include #include #include +#include /* forward references */ struct file; @@ -48,6 +49,7 @@ struct poll_table_struct; * @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix. * @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params. * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. + * @p_vp8_frame_header: Pointer to a VP8 frame header structure. * @p: Pointer to a compound value. */ union v4l2_ctrl_ptr { @@ -65,6 +67,7 @@ union v4l2_ctrl_ptr { struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; void *p; }; diff --git a/include/media/vp8-ctrls.h b/include/media/vp8-ctrls.h new file mode 100644 index 000000000000..6cc2eeea4c90 --- /dev/null +++ b/include/media/vp8-ctrls.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * These are the VP8 state controls for use with stateless VP8 + * codec drivers. + * + * It turns out that these structs are not stable yet and will undergo + * more changes. So keep them private until they are stable and ready to + * become part of the official public API. + */ + +#ifndef _VP8_CTRLS_H_ +#define _VP8_CTRLS_H_ + +#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') + +#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000) +#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301 + +#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01 +#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02 +#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04 +#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08 + +struct v4l2_vp8_segment_header { + __s8 quant_update[4]; + __s8 lf_update[4]; + __u8 segment_probs[3]; + __u8 padding; + __u32 flags; +}; + +#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01 +#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02 +#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04 +struct v4l2_vp8_loopfilter_header { + __s8 ref_frm_delta[4]; + __s8 mb_mode_delta[4]; + __u8 sharpness_level; + __u8 level; + __u16 padding; + __u32 flags; +}; + +struct v4l2_vp8_quantization_header { + __u8 y_ac_qi; + __s8 y_dc_delta; + __s8 y2_dc_delta; + __s8 y2_ac_delta; + __s8 uv_dc_delta; + __s8 uv_ac_delta; + __u16 padding; +}; + +struct v4l2_vp8_entropy_header { + __u8 coeff_probs[4][8][3][11]; + __u8 y_mode_probs[4]; + __u8 uv_mode_probs[3]; + __u8 mv_probs[2][19]; + __u8 padding[3]; +}; + +struct v4l2_vp8_entropy_coder_state { + __u8 range; + __u8 value; + __u8 bit_count; + __u8 padding; +}; + +#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01 +#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02 +#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04 +#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08 +#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10 +#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20 + +#define VP8_FRAME_IS_KEY_FRAME(hdr) \ + (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) + +struct v4l2_ctrl_vp8_frame_header { + struct v4l2_vp8_segment_header segment_header; + struct v4l2_vp8_loopfilter_header lf_header; + struct v4l2_vp8_quantization_header quant_header; + struct v4l2_vp8_entropy_header entropy_header; + struct v4l2_vp8_entropy_coder_state coder_state; + + __u16 width; + __u16 height; + + __u8 horizontal_scale; + __u8 vertical_scale; + + __u8 version; + __u8 prob_skip_false; + __u8 prob_intra; + __u8 prob_last; + __u8 prob_gf; + __u8 num_dct_parts; + + __u32 first_part_size; + __u32 first_part_header_bits; + __u32 dct_part_sizes[8]; + + __u64 last_frame_ts; + __u64 golden_frame_ts; + __u64 alt_frame_ts; + + __u64 flags; +}; + +#endif -- GitLab From 298c62d3856111e6ef41c9c00a233aecf2d19651 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 11 Jul 2019 16:26:43 -0400 Subject: [PATCH 0204/7155] media: v4l2-ctrl: Validate VP8 stateless decoder controls Only one field needs to be validated: 'num_dct_parts'. This field is used to iterate over the user-provided array 'dct_part_sizes'. Signed-off-by: Ezequiel Garcia [hverkuil-cisco@xs4all.nl: s -> (s) in zero_padding macro] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b2c9f5816c4a..13236c191796 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1633,10 +1633,15 @@ static void std_log(const struct v4l2_ctrl *ctrl) }) /* Validate a new control */ + +#define zero_padding(s) \ + memset(&(s).padding, 0, sizeof((s).padding)) + static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr) { struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; void *p = ptr.p + idx * ctrl->elem_size; switch ((u32)ctrl->type) { @@ -1696,6 +1701,22 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, break; case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: + p_vp8_frame_header = p; + + switch (p_vp8_frame_header->num_dct_parts) { + case 1: + case 2: + case 4: + case 8: + break; + default: + return -EINVAL; + } + zero_padding(p_vp8_frame_header->segment_header); + zero_padding(p_vp8_frame_header->lf_header); + zero_padding(p_vp8_frame_header->quant_header); + zero_padding(p_vp8_frame_header->entropy_header); + zero_padding(p_vp8_frame_header->coder_state); break; default: return -EINVAL; -- GitLab From bdd034050a46be32a9a68cc2cd1db8046efe5324 Mon Sep 17 00:00:00 2001 From: ZhiChao Yu Date: Thu, 11 Jul 2019 16:26:44 -0400 Subject: [PATCH 0205/7155] media: hantro: Add support for VP8 decoding on rk3288 Introduce VP8 decoding support in RK3288. Signed-off-by: ZhiChao Yu Signed-off-by: Tomasz Figa Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Makefile | 4 +- drivers/staging/media/hantro/hantro.h | 27 + drivers/staging/media/hantro/hantro_drv.c | 6 + .../staging/media/hantro/hantro_g1_vp8_dec.c | 526 ++++++++++++++++++ drivers/staging/media/hantro/hantro_hw.h | 17 + drivers/staging/media/hantro/hantro_v4l2.c | 1 + drivers/staging/media/hantro/hantro_vp8.c | 188 +++++++ drivers/staging/media/hantro/rk3288_vpu_hw.c | 22 +- 8 files changed, 789 insertions(+), 2 deletions(-) create mode 100644 drivers/staging/media/hantro/hantro_g1_vp8_dec.c create mode 100644 drivers/staging/media/hantro/hantro_vp8.c diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index 1584acdbf4a3..a627aee77f75 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -5,10 +5,12 @@ hantro-vpu-y += \ hantro_v4l2.o \ hantro_h1_jpeg_enc.o \ hantro_g1_mpeg2_dec.o \ + hantro_g1_vp8_dec.o \ rk3399_vpu_hw_jpeg_enc.o \ rk3399_vpu_hw_mpeg2_dec.o \ hantro_jpeg.o \ - hantro_mpeg2.o + hantro_mpeg2.o \ + hantro_vp8.o hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \ rk3288_vpu_hw.o \ diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 62dcca9ff19c..4d7cb7780bde 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -25,6 +25,10 @@ #include "hantro_hw.h" +#define VP8_MB_DIM 16 +#define VP8_MB_WIDTH(w) DIV_ROUND_UP(w, VP8_MB_DIM) +#define VP8_MB_HEIGHT(h) DIV_ROUND_UP(h, VP8_MB_DIM) + #define MPEG2_MB_DIM 16 #define MPEG2_MB_WIDTH(w) DIV_ROUND_UP(w, MPEG2_MB_DIM) #define MPEG2_MB_HEIGHT(h) DIV_ROUND_UP(h, MPEG2_MB_DIM) @@ -40,6 +44,7 @@ struct hantro_codec_ops; #define HANTRO_ENCODERS 0x0000ffff #define HANTRO_MPEG2_DECODER BIT(16) +#define HANTRO_VP8_DECODER BIT(17) #define HANTRO_DECODERS 0xffff0000 /** @@ -97,11 +102,13 @@ struct hantro_variant { * @HANTRO_MODE_NONE: No operating mode. Used for RAW video formats. * @HANTRO_MODE_JPEG_ENC: JPEG encoder. * @HANTRO_MODE_MPEG2_DEC: MPEG-2 decoder. + * @HANTRO_MODE_VP8_DEC: VP8 decoder. */ enum hantro_codec_mode { HANTRO_MODE_NONE = -1, HANTRO_MODE_JPEG_ENC, HANTRO_MODE_MPEG2_DEC, + HANTRO_MODE_VP8_DEC, }; /* @@ -215,6 +222,7 @@ struct hantro_dev { * @codec_ops: Set of operations related to codec mode. * @jpeg_enc: JPEG-encoding context. * @mpeg2_dec: MPEG-2-decoding context. + * @vp8_dec: VP8-decoding context. */ struct hantro_ctx { struct hantro_dev *dev; @@ -241,6 +249,7 @@ struct hantro_ctx { union { struct hantro_jpeg_enc_hw_ctx jpeg_enc; struct hantro_mpeg2_dec_hw_ctx mpeg2_dec; + struct hantro_vp8_dec_hw_ctx vp8_dec; }; }; @@ -265,6 +274,12 @@ struct hantro_fmt { struct v4l2_frmsize_stepwise frmsize; }; +struct hantro_reg { + u32 base; + u32 shift; + u32 mask; +}; + /* Logging helpers */ /** @@ -343,6 +358,18 @@ static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg) return val; } +static inline void hantro_reg_write(struct hantro_dev *vpu, + const struct hantro_reg *reg, + u32 val) +{ + u32 v; + + v = vdpu_read(vpu, reg->base); + v &= ~(reg->mask << reg->shift); + v |= ((val & reg->mask) << reg->shift); + vdpu_write_relaxed(vpu, v, reg->base); +} + bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx); void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id); diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index c3665f0e87a2..839f3f470811 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -284,6 +284,12 @@ static struct hantro_ctrl controls[] = { .cfg = { .elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization), }, + }, { + .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, + .codec = HANTRO_VP8_DECODER, + .cfg = { + .elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header), + }, }, }; diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c new file mode 100644 index 000000000000..72d983a11ca1 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VP8 codec driver + * + * Copyright (C) 2019 Rockchip Electronics Co., Ltd. + * ZhiChao Yu + * + * Copyright (C) 2019 Google, Inc. + * Tomasz Figa + */ + +#include +#include + +#include "hantro_hw.h" +#include "hantro.h" +#include "hantro_g1_regs.h" + +#define DEC_8190_ALIGN_MASK 0x07U + +/* DCT partition base address regs */ +static const struct hantro_reg vp8_dec_dct_base[8] = { + { G1_REG_ADDR_STR, 0, 0xffffffff }, + { G1_REG_ADDR_REF(8), 0, 0xffffffff }, + { G1_REG_ADDR_REF(9), 0, 0xffffffff }, + { G1_REG_ADDR_REF(10), 0, 0xffffffff }, + { G1_REG_ADDR_REF(11), 0, 0xffffffff }, + { G1_REG_ADDR_REF(12), 0, 0xffffffff }, + { G1_REG_ADDR_REF(14), 0, 0xffffffff }, + { G1_REG_ADDR_REF(15), 0, 0xffffffff }, +}; + +/* Loop filter level regs */ +static const struct hantro_reg vp8_dec_lf_level[4] = { + { G1_REG_REF_PIC(2), 18, 0x3f }, + { G1_REG_REF_PIC(2), 12, 0x3f }, + { G1_REG_REF_PIC(2), 6, 0x3f }, + { G1_REG_REF_PIC(2), 0, 0x3f }, +}; + +/* Macroblock loop filter level adjustment regs */ +static const struct hantro_reg vp8_dec_mb_adj[4] = { + { G1_REG_REF_PIC(0), 21, 0x7f }, + { G1_REG_REF_PIC(0), 14, 0x7f }, + { G1_REG_REF_PIC(0), 7, 0x7f }, + { G1_REG_REF_PIC(0), 0, 0x7f }, +}; + +/* Reference frame adjustment regs */ +static const struct hantro_reg vp8_dec_ref_adj[4] = { + { G1_REG_REF_PIC(1), 21, 0x7f }, + { G1_REG_REF_PIC(1), 14, 0x7f }, + { G1_REG_REF_PIC(1), 7, 0x7f }, + { G1_REG_REF_PIC(1), 0, 0x7f }, +}; + +/* Quantizer */ +static const struct hantro_reg vp8_dec_quant[4] = { + { G1_REG_REF_PIC(3), 11, 0x7ff }, + { G1_REG_REF_PIC(3), 0, 0x7ff }, + { G1_REG_BD_REF_PIC(4), 11, 0x7ff }, + { G1_REG_BD_REF_PIC(4), 0, 0x7ff }, +}; + +/* Quantizer delta regs */ +static const struct hantro_reg vp8_dec_quant_delta[5] = { + { G1_REG_REF_PIC(3), 27, 0x1f }, + { G1_REG_REF_PIC(3), 22, 0x1f }, + { G1_REG_BD_REF_PIC(4), 27, 0x1f }, + { G1_REG_BD_REF_PIC(4), 22, 0x1f }, + { G1_REG_BD_P_REF_PIC, 27, 0x1f }, +}; + +/* DCT partition start bits regs */ +static const struct hantro_reg vp8_dec_dct_start_bits[8] = { + { G1_REG_DEC_CTRL2, 26, 0x3f }, { G1_REG_DEC_CTRL4, 26, 0x3f }, + { G1_REG_DEC_CTRL4, 20, 0x3f }, { G1_REG_DEC_CTRL7, 24, 0x3f }, + { G1_REG_DEC_CTRL7, 18, 0x3f }, { G1_REG_DEC_CTRL7, 12, 0x3f }, + { G1_REG_DEC_CTRL7, 6, 0x3f }, { G1_REG_DEC_CTRL7, 0, 0x3f }, +}; + +/* Precision filter tap regs */ +static const struct hantro_reg vp8_dec_pred_bc_tap[8][4] = { + { + { G1_REG_PRED_FLT, 22, 0x3ff }, + { G1_REG_PRED_FLT, 12, 0x3ff }, + { G1_REG_PRED_FLT, 2, 0x3ff }, + { G1_REG_REF_PIC(4), 22, 0x3ff }, + }, + { + { G1_REG_REF_PIC(4), 12, 0x3ff }, + { G1_REG_REF_PIC(4), 2, 0x3ff }, + { G1_REG_REF_PIC(5), 22, 0x3ff }, + { G1_REG_REF_PIC(5), 12, 0x3ff }, + }, + { + { G1_REG_REF_PIC(5), 2, 0x3ff }, + { G1_REG_REF_PIC(6), 22, 0x3ff }, + { G1_REG_REF_PIC(6), 12, 0x3ff }, + { G1_REG_REF_PIC(6), 2, 0x3ff }, + }, + { + { G1_REG_REF_PIC(7), 22, 0x3ff }, + { G1_REG_REF_PIC(7), 12, 0x3ff }, + { G1_REG_REF_PIC(7), 2, 0x3ff }, + { G1_REG_LT_REF, 22, 0x3ff }, + }, + { + { G1_REG_LT_REF, 12, 0x3ff }, + { G1_REG_LT_REF, 2, 0x3ff }, + { G1_REG_VALID_REF, 22, 0x3ff }, + { G1_REG_VALID_REF, 12, 0x3ff }, + }, + { + { G1_REG_VALID_REF, 2, 0x3ff }, + { G1_REG_BD_REF_PIC(0), 22, 0x3ff }, + { G1_REG_BD_REF_PIC(0), 12, 0x3ff }, + { G1_REG_BD_REF_PIC(0), 2, 0x3ff }, + }, + { + { G1_REG_BD_REF_PIC(1), 22, 0x3ff }, + { G1_REG_BD_REF_PIC(1), 12, 0x3ff }, + { G1_REG_BD_REF_PIC(1), 2, 0x3ff }, + { G1_REG_BD_REF_PIC(2), 22, 0x3ff }, + }, + { + { G1_REG_BD_REF_PIC(2), 12, 0x3ff }, + { G1_REG_BD_REF_PIC(2), 2, 0x3ff }, + { G1_REG_BD_REF_PIC(3), 22, 0x3ff }, + { G1_REG_BD_REF_PIC(3), 12, 0x3ff }, + }, +}; + +/* + * filter taps taken to 7-bit precision, + * reference RFC6386#Page-16, filters[8][6] + */ +static const u32 vp8_dec_mc_filter[8][6] = { + { 0, 0, 128, 0, 0, 0 }, + { 0, -6, 123, 12, -1, 0 }, + { 2, -11, 108, 36, -8, 1 }, + { 0, -9, 93, 50, -6, 0 }, + { 3, -16, 77, 77, -16, 3 }, + { 0, -6, 50, 93, -9, 0 }, + { 1, -8, 36, 108, -11, 2 }, + { 0, -1, 12, 123, -6, 0 } +}; + +/* + * Set loop filters + */ +static void cfg_lf(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + const struct v4l2_vp8_loopfilter_header *lf = &hdr->lf_header; + struct hantro_dev *vpu = ctx->dev; + unsigned int i; + u32 reg; + + if (!(seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED)) { + hantro_reg_write(vpu, &vp8_dec_lf_level[0], lf->level); + } else if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE) { + for (i = 0; i < 4; i++) { + u32 lf_level = clamp(lf->level + seg->lf_update[i], + 0, 63); + + hantro_reg_write(vpu, &vp8_dec_lf_level[i], lf_level); + } + } else { + for (i = 0; i < 4; i++) + hantro_reg_write(vpu, &vp8_dec_lf_level[i], + seg->lf_update[i]); + } + + reg = G1_REG_REF_PIC_FILT_SHARPNESS(lf->sharpness_level); + if (lf->flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE) + reg |= G1_REG_REF_PIC_FILT_TYPE_E; + vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(0)); + + if (lf->flags & V4L2_VP8_LF_HEADER_ADJ_ENABLE) { + for (i = 0; i < 4; i++) { + hantro_reg_write(vpu, &vp8_dec_mb_adj[i], + lf->mb_mode_delta[i]); + hantro_reg_write(vpu, &vp8_dec_ref_adj[i], + lf->ref_frm_delta[i]); + } + } +} + +/* + * Set quantization parameters + */ +static void cfg_qp(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_quantization_header *q = &hdr->quant_header; + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + struct hantro_dev *vpu = ctx->dev; + unsigned int i; + + if (!(seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED)) { + hantro_reg_write(vpu, &vp8_dec_quant[0], q->y_ac_qi); + } else if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE) { + for (i = 0; i < 4; i++) { + u32 quant = clamp(q->y_ac_qi + seg->quant_update[i], + 0, 127); + + hantro_reg_write(vpu, &vp8_dec_quant[i], quant); + } + } else { + for (i = 0; i < 4; i++) + hantro_reg_write(vpu, &vp8_dec_quant[i], + seg->quant_update[i]); + } + + hantro_reg_write(vpu, &vp8_dec_quant_delta[0], q->y_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[1], q->y2_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[2], q->y2_ac_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[3], q->uv_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[4], q->uv_ac_delta); +} + +/* + * set control partition and DCT partition regs + * + * VP8 frame stream data layout: + * + * first_part_size parttion_sizes[0] + * ^ ^ + * src_dma | | + * ^ +--------+------+ +-----+-----+ + * | | control part | | | + * +--------+----------------+------------------+-----------+-----+-----------+ + * | tag 3B | extra 7B | hdr | mb_data | DCT sz | DCT part0 | ... | DCT partn | + * +--------+-----------------------------------+-----------+-----+-----------+ + * | | | | + * v +----+---+ v + * mb_start | src_dma_end + * v + * DCT size part + * (num_dct-1)*3B + * Note: + * 1. only key-frames have extra 7-bytes + * 2. all offsets are base on src_dma + * 3. number of DCT parts is 1, 2, 4 or 8 + * 4. the addresses set to the VPU must be 64-bits aligned + */ +static void cfg_parts(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_src; + u32 first_part_offset = VP8_FRAME_IS_KEY_FRAME(hdr) ? 10 : 3; + u32 mb_size, mb_offset_bytes, mb_offset_bits, mb_start_bits; + u32 dct_size_part_size, dct_part_offset; + struct hantro_reg reg; + dma_addr_t src_dma; + u32 dct_part_total_len = 0; + u32 count = 0; + unsigned int i; + + vb2_src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); + + /* + * Calculate control partition mb data info + * @first_part_header_bits: bits offset of mb data from first + * part start pos + * @mb_offset_bits: bits offset of mb data from src_dma + * base addr + * @mb_offset_byte: bytes offset of mb data from src_dma + * base addr + * @mb_start_bits: bits offset of mb data from mb data + * 64bits alignment addr + */ + mb_offset_bits = first_part_offset * 8 + + hdr->first_part_header_bits + 8; + mb_offset_bytes = mb_offset_bits / 8; + mb_start_bits = mb_offset_bits - + (mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) * 8; + mb_size = hdr->first_part_size - + (mb_offset_bytes - first_part_offset) + + (mb_offset_bytes & DEC_8190_ALIGN_MASK); + + /* Macroblock data aligned base addr */ + vdpu_write_relaxed(vpu, (mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) + + src_dma, G1_REG_ADDR_REF(13)); + + /* Macroblock data start bits */ + reg.base = G1_REG_DEC_CTRL2; + reg.mask = 0x3f; + reg.shift = 18; + hantro_reg_write(vpu, ®, mb_start_bits); + + /* Macroblock aligned data length */ + reg.base = G1_REG_DEC_CTRL6; + reg.mask = 0x3fffff; + reg.shift = 0; + hantro_reg_write(vpu, ®, mb_size + 1); + + /* + * Calculate DCT partition info + * @dct_size_part_size: Containing sizes of DCT part, every DCT part + * has 3 bytes to store its size, except the last + * DCT part + * @dct_part_offset: bytes offset of DCT parts from src_dma base addr + * @dct_part_total_len: total size of all DCT parts + */ + dct_size_part_size = (hdr->num_dct_parts - 1) * 3; + dct_part_offset = first_part_offset + hdr->first_part_size; + for (i = 0; i < hdr->num_dct_parts; i++) + dct_part_total_len += hdr->dct_part_sizes[i]; + dct_part_total_len += dct_size_part_size; + dct_part_total_len += (dct_part_offset & DEC_8190_ALIGN_MASK); + + /* Number of DCT partitions */ + reg.base = G1_REG_DEC_CTRL6; + reg.mask = 0xf; + reg.shift = 24; + hantro_reg_write(vpu, ®, hdr->num_dct_parts - 1); + + /* DCT partition length */ + vdpu_write_relaxed(vpu, + G1_REG_DEC_CTRL3_STREAM_LEN(dct_part_total_len), + G1_REG_DEC_CTRL3); + + /* DCT partitions base address */ + for (i = 0; i < hdr->num_dct_parts; i++) { + u32 byte_offset = dct_part_offset + dct_size_part_size + count; + u32 base_addr = byte_offset + src_dma; + + hantro_reg_write(vpu, &vp8_dec_dct_base[i], + base_addr & (~DEC_8190_ALIGN_MASK)); + + hantro_reg_write(vpu, &vp8_dec_dct_start_bits[i], + (byte_offset & DEC_8190_ALIGN_MASK) * 8); + + count += hdr->dct_part_sizes[i]; + } +} + +/* + * prediction filter taps + * normal 6-tap filters + */ +static void cfg_tap(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_reg reg; + u32 val = 0; + int i, j; + + reg.base = G1_REG_BD_REF_PIC(3); + reg.mask = 0xf; + + if ((hdr->version & 0x03) != 0) + return; /* Tap filter not used. */ + + for (i = 0; i < 8; i++) { + val = (vp8_dec_mc_filter[i][0] << 2) | vp8_dec_mc_filter[i][5]; + + for (j = 0; j < 4; j++) + hantro_reg_write(vpu, &vp8_dec_pred_bc_tap[i][j], + vp8_dec_mc_filter[i][j + 1]); + + switch (i) { + case 2: + reg.shift = 8; + break; + case 4: + reg.shift = 4; + break; + case 6: + reg.shift = 0; + break; + default: + continue; + } + + hantro_reg_write(vpu, ®, val); + } +} + +static void cfg_ref(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q; + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; + dma_addr_t ref; + + vb2_dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + ref = hantro_get_ref(cap_q, hdr->last_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(0)); + + ref = hantro_get_ref(cap_q, hdr->golden_frame_ts); + WARN_ON(!ref && hdr->golden_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + if (hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN) + ref |= G1_REG_ADDR_REF_TOPC_E; + vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(4)); + + ref = hantro_get_ref(cap_q, hdr->alt_frame_ts); + WARN_ON(!ref && hdr->alt_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + if (hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT) + ref |= G1_REG_ADDR_REF_TOPC_E; + vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(5)); +} + +static void cfg_buffers(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; + dma_addr_t dst_dma; + u32 reg; + + vb2_dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + /* Set probability table buffer address */ + vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma, + G1_REG_ADDR_QTABLE); + + /* Set segment map address */ + reg = G1_REG_FWD_PIC1_SEGMENT_BASE(ctx->vp8_dec.segment_map.dma); + if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED) { + reg |= G1_REG_FWD_PIC1_SEGMENT_E; + if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP) + reg |= G1_REG_FWD_PIC1_SEGMENT_UPD_E; + } + vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(0)); + + dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + vdpu_write_relaxed(vpu, dst_dma, G1_REG_ADDR_DST); +} + +void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) +{ + const struct v4l2_ctrl_vp8_frame_header *hdr; + struct hantro_dev *vpu = ctx->dev; + size_t height = ctx->dst_fmt.height; + size_t width = ctx->dst_fmt.width; + struct vb2_v4l2_buffer *vb2_src; + u32 mb_width, mb_height; + u32 reg; + + vb2_src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + v4l2_ctrl_request_setup(vb2_src->vb2_buf.req_obj.req, + &ctx->ctrl_handler); + + hdr = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER); + if (WARN_ON(!hdr)) + return; + + /* Reset segment_map buffer in keyframe */ + if (VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu) + memset(ctx->vp8_dec.segment_map.cpu, 0, + ctx->vp8_dec.segment_map.size); + + hantro_vp8_prob_update(ctx, hdr); + + reg = G1_REG_CONFIG_DEC_TIMEOUT_E | + G1_REG_CONFIG_DEC_STRENDIAN_E | + G1_REG_CONFIG_DEC_INSWAP32_E | + G1_REG_CONFIG_DEC_STRSWAP32_E | + G1_REG_CONFIG_DEC_OUTSWAP32_E | + G1_REG_CONFIG_DEC_CLK_GATE_E | + G1_REG_CONFIG_DEC_IN_ENDIAN | + G1_REG_CONFIG_DEC_OUT_ENDIAN | + G1_REG_CONFIG_DEC_MAX_BURST(16); + vdpu_write_relaxed(vpu, reg, G1_REG_CONFIG); + + reg = G1_REG_DEC_CTRL0_DEC_MODE(10); + if (!VP8_FRAME_IS_KEY_FRAME(hdr)) + reg |= G1_REG_DEC_CTRL0_PIC_INTER_E; + if (!(hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF)) + reg |= G1_REG_DEC_CTRL0_SKIP_MODE; + if (hdr->lf_header.level == 0) + reg |= G1_REG_DEC_CTRL0_FILTERING_DIS; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL0); + + /* Frame dimensions */ + mb_width = VP8_MB_WIDTH(width); + mb_height = VP8_MB_HEIGHT(height); + reg = G1_REG_DEC_CTRL1_PIC_MB_WIDTH(mb_width) | + G1_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(mb_height) | + G1_REG_DEC_CTRL1_PIC_MB_W_EXT(mb_width >> 9) | + G1_REG_DEC_CTRL1_PIC_MB_H_EXT(mb_height >> 8); + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL1); + + /* Boolean decoder */ + reg = G1_REG_DEC_CTRL2_BOOLEAN_RANGE(hdr->coder_state.range) + | G1_REG_DEC_CTRL2_BOOLEAN_VALUE(hdr->coder_state.value); + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL2); + + reg = 0; + if (hdr->version != 3) + reg |= G1_REG_DEC_CTRL4_VC1_HEIGHT_EXT; + if (hdr->version & 0x3) + reg |= G1_REG_DEC_CTRL4_BILIN_MC_E; + vdpu_write_relaxed(vpu, reg, G1_REG_DEC_CTRL4); + + cfg_lf(ctx, hdr); + cfg_qp(ctx, hdr); + cfg_parts(ctx, hdr); + cfg_tap(ctx, hdr); + cfg_ref(ctx, hdr); + cfg_buffers(ctx, hdr); + + /* Controls no longer in-use, we can complete them */ + v4l2_ctrl_request_complete(vb2_src->vb2_buf.req_obj.req, + &ctx->ctrl_handler); + + schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + + vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT); +} diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 3c361c2e9b88..7849852affde 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -12,6 +12,7 @@ #include #include #include +#include #include struct hantro_dev; @@ -47,6 +48,16 @@ struct hantro_mpeg2_dec_hw_ctx { struct hantro_aux_buf qtable; }; +/** + * struct hantro_vp8d_hw_ctx + * @segment_map: Segment map buffer. + * @prob_tbl: Probability table buffer. + */ +struct hantro_vp8_dec_hw_ctx { + struct hantro_aux_buf segment_map; + struct hantro_aux_buf prob_tbl; +}; + /** * struct hantro_codec_ops - codec mode specific operations * @@ -99,4 +110,10 @@ void hantro_mpeg2_dec_copy_qtable(u8 *qtable, int hantro_mpeg2_dec_init(struct hantro_ctx *ctx); void hantro_mpeg2_dec_exit(struct hantro_ctx *ctx); +void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx); +int hantro_vp8_dec_init(struct hantro_ctx *ctx); +void hantro_vp8_dec_exit(struct hantro_ctx *ctx); +void hantro_vp8_prob_update(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr); + #endif /* HANTRO_HW_H_ */ diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index 68f45ee66821..cd4eaa256e8b 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -344,6 +344,7 @@ hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc) ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = false; break; case V4L2_PIX_FMT_MPEG2_SLICE: + case V4L2_PIX_FMT_VP8_FRAME: ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = true; break; default: diff --git a/drivers/staging/media/hantro/hantro_vp8.c b/drivers/staging/media/hantro/hantro_vp8.c new file mode 100644 index 000000000000..66c45335d871 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_vp8.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VPU codec driver + * + * Copyright (C) 2018 Rockchip Electronics Co., Ltd. + */ + +#include "hantro.h" + +/* + * probs table with packed + */ +struct vp8_prob_tbl_packed { + u8 prob_mb_skip_false; + u8 prob_intra; + u8 prob_ref_last; + u8 prob_ref_golden; + u8 prob_segment[3]; + u8 padding0; + + u8 prob_luma_16x16_pred_mode[4]; + u8 prob_chroma_pred_mode[3]; + u8 padding1; + + /* mv prob */ + u8 prob_mv_context[2][19]; + u8 padding2[2]; + + /* coeff probs */ + u8 prob_coeffs[4][8][3][11]; + u8 padding3[96]; +}; + +void hantro_vp8_prob_update(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_entropy_header *entropy = &hdr->entropy_header; + u32 i, j, k; + u8 *dst; + + /* first probs */ + dst = ctx->vp8_dec.prob_tbl.cpu; + + dst[0] = hdr->prob_skip_false; + dst[1] = hdr->prob_intra; + dst[2] = hdr->prob_last; + dst[3] = hdr->prob_gf; + dst[4] = hdr->segment_header.segment_probs[0]; + dst[5] = hdr->segment_header.segment_probs[1]; + dst[6] = hdr->segment_header.segment_probs[2]; + dst[7] = 0; + + dst += 8; + dst[0] = entropy->y_mode_probs[0]; + dst[1] = entropy->y_mode_probs[1]; + dst[2] = entropy->y_mode_probs[2]; + dst[3] = entropy->y_mode_probs[3]; + dst[4] = entropy->uv_mode_probs[0]; + dst[5] = entropy->uv_mode_probs[1]; + dst[6] = entropy->uv_mode_probs[2]; + dst[7] = 0; /*unused */ + + /* mv probs */ + dst += 8; + dst[0] = entropy->mv_probs[0][0]; /* is short */ + dst[1] = entropy->mv_probs[1][0]; + dst[2] = entropy->mv_probs[0][1]; /* sign */ + dst[3] = entropy->mv_probs[1][1]; + dst[4] = entropy->mv_probs[0][8 + 9]; + dst[5] = entropy->mv_probs[0][9 + 9]; + dst[6] = entropy->mv_probs[1][8 + 9]; + dst[7] = entropy->mv_probs[1][9 + 9]; + dst += 8; + for (i = 0; i < 2; ++i) { + for (j = 0; j < 8; j += 4) { + dst[0] = entropy->mv_probs[i][j + 9 + 0]; + dst[1] = entropy->mv_probs[i][j + 9 + 1]; + dst[2] = entropy->mv_probs[i][j + 9 + 2]; + dst[3] = entropy->mv_probs[i][j + 9 + 3]; + dst += 4; + } + } + for (i = 0; i < 2; ++i) { + dst[0] = entropy->mv_probs[i][0 + 2]; + dst[1] = entropy->mv_probs[i][1 + 2]; + dst[2] = entropy->mv_probs[i][2 + 2]; + dst[3] = entropy->mv_probs[i][3 + 2]; + dst[4] = entropy->mv_probs[i][4 + 2]; + dst[5] = entropy->mv_probs[i][5 + 2]; + dst[6] = entropy->mv_probs[i][6 + 2]; + dst[7] = 0; /*unused */ + dst += 8; + } + + /* coeff probs (header part) */ + dst = ctx->vp8_dec.prob_tbl.cpu; + dst += (8 * 7); + for (i = 0; i < 4; ++i) { + for (j = 0; j < 8; ++j) { + for (k = 0; k < 3; ++k) { + dst[0] = entropy->coeff_probs[i][j][k][0]; + dst[1] = entropy->coeff_probs[i][j][k][1]; + dst[2] = entropy->coeff_probs[i][j][k][2]; + dst[3] = entropy->coeff_probs[i][j][k][3]; + dst += 4; + } + } + } + + /* coeff probs (footer part) */ + dst = ctx->vp8_dec.prob_tbl.cpu; + dst += (8 * 55); + for (i = 0; i < 4; ++i) { + for (j = 0; j < 8; ++j) { + for (k = 0; k < 3; ++k) { + dst[0] = entropy->coeff_probs[i][j][k][4]; + dst[1] = entropy->coeff_probs[i][j][k][5]; + dst[2] = entropy->coeff_probs[i][j][k][6]; + dst[3] = entropy->coeff_probs[i][j][k][7]; + dst[4] = entropy->coeff_probs[i][j][k][8]; + dst[5] = entropy->coeff_probs[i][j][k][9]; + dst[6] = entropy->coeff_probs[i][j][k][10]; + dst[7] = 0; /*unused */ + dst += 8; + } + } + } +} + +int hantro_vp8_dec_init(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_aux_buf *aux_buf; + unsigned int mb_width, mb_height; + size_t segment_map_size; + int ret; + + /* segment map table size calculation */ + mb_width = DIV_ROUND_UP(ctx->dst_fmt.width, 16); + mb_height = DIV_ROUND_UP(ctx->dst_fmt.height, 16); + segment_map_size = round_up(DIV_ROUND_UP(mb_width * mb_height, 4), 64); + + /* + * In context init the dma buffer for segment map must be allocated. + * And the data in segment map buffer must be set to all zero. + */ + aux_buf = &ctx->vp8_dec.segment_map; + aux_buf->size = segment_map_size; + aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size, + &aux_buf->dma, GFP_KERNEL); + if (!aux_buf->cpu) + return -ENOMEM; + + memset(aux_buf->cpu, 0, aux_buf->size); + + /* + * Allocate probability table buffer, + * total 1208 bytes, 4K page is far enough. + */ + aux_buf = &ctx->vp8_dec.prob_tbl; + aux_buf->size = sizeof(struct vp8_prob_tbl_packed); + aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size, + &aux_buf->dma, GFP_KERNEL); + if (!aux_buf->cpu) { + ret = -ENOMEM; + goto err_free_seg_map; + } + + return 0; + +err_free_seg_map: + dma_free_coherent(vpu->dev, ctx->vp8_dec.segment_map.size, + ctx->vp8_dec.segment_map.cpu, + ctx->vp8_dec.segment_map.dma); + + return ret; +} + +void hantro_vp8_dec_exit(struct hantro_ctx *ctx) +{ + struct hantro_vp8_dec_hw_ctx *vp8_dec = &ctx->vp8_dec; + struct hantro_dev *vpu = ctx->dev; + + dma_free_coherent(vpu->dev, vp8_dec->segment_map.size, + vp8_dec->segment_map.cpu, vp8_dec->segment_map.dma); + dma_free_coherent(vpu->dev, vp8_dec->prob_tbl.size, + vp8_dec->prob_tbl.cpu, vp8_dec->prob_tbl.dma); +} diff --git a/drivers/staging/media/hantro/rk3288_vpu_hw.c b/drivers/staging/media/hantro/rk3288_vpu_hw.c index bcacc4f51093..f1b573a006ae 100644 --- a/drivers/staging/media/hantro/rk3288_vpu_hw.c +++ b/drivers/staging/media/hantro/rk3288_vpu_hw.c @@ -74,6 +74,19 @@ static const struct hantro_fmt rk3288_vpu_dec_fmts[] = { .step_height = MPEG2_MB_DIM, }, }, + { + .fourcc = V4L2_PIX_FMT_VP8_FRAME, + .codec_mode = HANTRO_MODE_VP8_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = VP8_MB_DIM, + .min_height = 48, + .max_height = 2160, + .step_height = VP8_MB_DIM, + }, + }, }; static irqreturn_t rk3288_vepu_irq(int irq, void *dev_id) @@ -155,6 +168,12 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { .init = hantro_mpeg2_dec_init, .exit = hantro_mpeg2_dec_exit, }, + [HANTRO_MODE_VP8_DEC] = { + .run = hantro_g1_vp8_dec_run, + .reset = rk3288_vpu_dec_reset, + .init = hantro_vp8_dec_init, + .exit = hantro_vp8_dec_exit, + }, }; /* @@ -177,7 +196,8 @@ const struct hantro_variant rk3288_vpu_variant = { .dec_offset = 0x400, .dec_fmts = rk3288_vpu_dec_fmts, .num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts), - .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER, + .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | + HANTRO_VP8_DECODER, .codec_ops = rk3288_vpu_codec_ops, .irqs = rk3288_irqs, .num_irqs = ARRAY_SIZE(rk3288_irqs), -- GitLab From 56613e7153a53d6cc7eb8d1d6abf00e9fe71c6f1 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 29 May 2019 06:54:27 -0400 Subject: [PATCH 0206/7155] media: dt-bindings: rockchip: Document RK3328 VPU binding Update devicetree binding documentation for Rockchip VPU on RK3328. Signed-off-by: Jonas Karlman Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/rockchip-vpu.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.txt b/Documentation/devicetree/bindings/media/rockchip-vpu.txt index 35dc464ad7c8..339252d9c515 100644 --- a/Documentation/devicetree/bindings/media/rockchip-vpu.txt +++ b/Documentation/devicetree/bindings/media/rockchip-vpu.txt @@ -1,14 +1,17 @@ device-tree bindings for rockchip VPU codec Rockchip (Video Processing Unit) present in various Rockchip platforms, -such as RK3288 and RK3399. +such as RK3288, RK3328 and RK3399. Required properties: - compatible: value should be one of the following "rockchip,rk3288-vpu"; + "rockchip,rk3328-vpu"; "rockchip,rk3399-vpu"; - interrupts: encoding and decoding interrupt specifiers -- interrupt-names: should be "vepu" and "vdpu" +- interrupt-names: should be + "vepu", "vdpu" on RK3288 and RK3399, + "vdpu" on RK3328. - clocks: phandle to VPU aclk, hclk clocks - clock-names: should be "aclk" and "hclk" - power-domains: phandle to power domain node @@ -27,3 +30,14 @@ SoC-specific DT entry: power-domains = <&power RK3288_PD_VIDEO>; iommus = <&vpu_mmu>; }; + + vpu: video-codec@ff350000 { + compatible = "rockchip,rk3328-vpu"; + reg = <0x0 0xff350000 0x0 0x800>; + interrupts = ; + interrupt-names = "vdpu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "hclk"; + power-domains = <&power RK3328_PD_VPU>; + iommus = <&vpu_mmu>; + }; -- GitLab From d3bfed33e2d80ce5a25549c2f935c91775b2b3f3 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 12 Jun 2019 05:42:08 -0400 Subject: [PATCH 0207/7155] media: hantro: Add support for MPEG-2 decoding on RK3328 Add necessary bits to support MPEG2 decoding on RK3328. Signed-off-by: Jonas Karlman Signed-off-by: Ezequiel Garcia Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Kconfig | 2 +- drivers/staging/media/hantro/hantro_drv.c | 1 + drivers/staging/media/hantro/rk3399_vpu_hw.c | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig index be133bbaa68a..de77fe6554e7 100644 --- a/drivers/staging/media/hantro/Kconfig +++ b/drivers/staging/media/hantro/Kconfig @@ -20,4 +20,4 @@ config VIDEO_HANTRO_ROCKCHIP depends on ARCH_ROCKCHIP || COMPILE_TEST default y help - Enable support for RK3288 and RK3399 SoCs. + Enable support for RK3288, RK3328, and RK3399 SoCs. diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 839f3f470811..b71a06e9159e 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -425,6 +425,7 @@ static const struct v4l2_file_operations hantro_fops = { static const struct of_device_id of_hantro_match[] = { #ifdef CONFIG_VIDEO_HANTRO_ROCKCHIP { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, + { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, #endif { /* sentinel */ } diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c index 5718f8063542..f8400e49bc50 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c @@ -184,3 +184,20 @@ const struct hantro_variant rk3399_vpu_variant = { .clk_names = rk3399_clk_names, .num_clocks = ARRAY_SIZE(rk3399_clk_names) }; + +static const struct hantro_irq rk3328_irqs[] = { + { "vdpu", rk3399_vdpu_irq }, +}; + +const struct hantro_variant rk3328_vpu_variant = { + .dec_offset = 0x400, + .dec_fmts = rk3399_vpu_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), + .codec = HANTRO_MPEG2_DECODER, + .codec_ops = rk3399_vpu_codec_ops, + .irqs = rk3328_irqs, + .num_irqs = ARRAY_SIZE(rk3328_irqs), + .init = rk3399_vpu_hw_init, + .clk_names = rk3399_clk_names, + .num_clocks = ARRAY_SIZE(rk3399_clk_names), +}; -- GitLab From eab865203f405501f799e1d7b7b020746e6ea26e Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 12 Jul 2019 18:46:58 -0400 Subject: [PATCH 0208/7155] media: mtk-cir: only allow protocols that have software decoders RC_PROTO_BIT_ALL includes protocols like unknown and other that do not have IR decoders by definition. If these protocols are set in the allowed_protocols, they will show in the protocols sysfs file but cannot be enabled. Signed-off-by: Sean Young Acked-by: Sean Wang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mtk-cir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c index 50fb0aebb8d4..de4e411bd22a 100644 --- a/drivers/media/rc/mtk-cir.c +++ b/drivers/media/rc/mtk-cir.c @@ -340,7 +340,7 @@ static int mtk_ir_probe(struct platform_device *pdev) ir->rc->map_name = map_name ?: RC_MAP_EMPTY; ir->rc->dev.parent = dev; ir->rc->driver_name = MTK_IR_DEV; - ir->rc->allowed_protocols = RC_PROTO_BIT_ALL; + ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; ir->rc->rx_resolution = MTK_IR_SAMPLE; ir->rc->timeout = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1); -- GitLab From a81431e7d1077a84695fc7be487fc2b4930f8c3d Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 12 Jul 2019 18:46:59 -0400 Subject: [PATCH 0209/7155] media: rc: remove unused #define RC_PROTO_BIT_ALL This lists all the protocols that the kernel knows about, however there are no users. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- include/media/rc-map.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/include/media/rc-map.h b/include/media/rc-map.h index bebd3c4c6338..3a7f8728f6ec 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -38,22 +38,6 @@ #define RC_PROTO_BIT_RCMM32 BIT_ULL(RC_PROTO_RCMM32) #define RC_PROTO_BIT_XBOX_DVD BIT_ULL(RC_PROTO_XBOX_DVD) -#define RC_PROTO_BIT_ALL \ - (RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \ - RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ - RC_PROTO_BIT_RC5_SZ | RC_PROTO_BIT_JVC | \ - RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | \ - RC_PROTO_BIT_SONY20 | RC_PROTO_BIT_NEC | \ - RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32 | \ - RC_PROTO_BIT_SANYO | \ - RC_PROTO_BIT_MCIR2_KBD | RC_PROTO_BIT_MCIR2_MSE | \ - RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \ - RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \ - RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ - RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \ - RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM12 | \ - RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32 | \ - RC_PROTO_BIT_XBOX_DVD) /* All rc protocols for which we have decoders */ #define RC_PROTO_BIT_ALL_IR_DECODER \ (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ -- GitLab From 5dd4b89dc098bf22cd13e82a308f42a02c102b2b Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 12 Jul 2019 18:47:00 -0400 Subject: [PATCH 0210/7155] media: mtk-cir: lower de-glitch counter for rc-mm protocol The rc-mm protocol can't be decoded by the mtk-cir since the de-glitch filter removes pulses/spaces shorter than 294 microseconds. Tested on a BananaPi R2. Signed-off-by: Sean Young Acked-by: Sean Wang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mtk-cir.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c index de4e411bd22a..99a3f1e773c6 100644 --- a/drivers/media/rc/mtk-cir.c +++ b/drivers/media/rc/mtk-cir.c @@ -35,6 +35,11 @@ /* Fields containing pulse width data */ #define MTK_WIDTH_MASK (GENMASK(7, 0)) +/* IR threshold */ +#define MTK_IRTHD 0x14 +#define MTK_DG_CNT_MASK (GENMASK(12, 8)) +#define MTK_DG_CNT(x) ((x) << 8) + /* Bit to enable interrupt */ #define MTK_IRINT_EN BIT(0) @@ -398,6 +403,9 @@ static int mtk_ir_probe(struct platform_device *pdev) mtk_w32_mask(ir, val, ir->data->fields[MTK_HW_PERIOD].mask, ir->data->fields[MTK_HW_PERIOD].reg); + /* Set de-glitch counter */ + mtk_w32_mask(ir, MTK_DG_CNT(1), MTK_DG_CNT_MASK, MTK_IRTHD); + /* Enable IR and PWM */ val = mtk_r32(ir, MTK_CONFIG_HIGH_REG); val |= MTK_OK_COUNT(ir->data->ok_count) | MTK_PWM_EN | MTK_IR_EN; -- GitLab From 0c4df39e504bf925ab666132ac3c98d6cbbe380b Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 3 Jul 2019 10:52:39 -0400 Subject: [PATCH 0211/7155] media: technisat-usb2: break out of loop at end of buffer Ensure we do not access the buffer beyond the end if no 0xff byte is encountered. Reported-by: syzbot+eaaaf38a95427be88f4b@syzkaller.appspotmail.com Signed-off-by: Sean Young Reviewed-by: Kees Cook Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/technisat-usb2.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index c659e18b358b..676d233d46d5 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -608,10 +608,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) static int technisat_usb2_get_ir(struct dvb_usb_device *d) { struct technisat_usb2_state *state = d->priv; - u8 *buf = state->buf; - u8 *b; - int ret; struct ir_raw_event ev; + u8 *buf = state->buf; + int i, ret; buf[0] = GET_IR_DATA_VENDOR_REQUEST; buf[1] = 0x08; @@ -647,26 +646,25 @@ static int technisat_usb2_get_ir(struct dvb_usb_device *d) return 0; /* no key pressed */ /* decoding */ - b = buf+1; #if 0 deb_rc("RC: %d ", ret); - debug_dump(b, ret, deb_rc); + debug_dump(buf + 1, ret, deb_rc); #endif ev.pulse = 0; - while (1) { - ev.pulse = !ev.pulse; - ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; - ir_raw_event_store(d->rc_dev, &ev); - - b++; - if (*b == 0xff) { + for (i = 1; i < ARRAY_SIZE(state->buf); i++) { + if (buf[i] == 0xff) { ev.pulse = 0; ev.duration = 888888*2; ir_raw_event_store(d->rc_dev, &ev); break; } + + ev.pulse = !ev.pulse; + ev.duration = (buf[i] * FIRMWARE_CLOCK_DIVISOR * + FIRMWARE_CLOCK_TICK) / 1000; + ir_raw_event_store(d->rc_dev, &ev); } ir_raw_event_handle(d->rc_dev); -- GitLab From 765bb8610d305ee488b35d07e2a04ae52fb2df9c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Jun 2019 08:14:53 -0400 Subject: [PATCH 0212/7155] media: dib0700: fix link error for dibx000_i2c_set_speed When CONFIG_DVB_DIB9000 is disabled, we can still compile code that now fails to link against dibx000_i2c_set_speed: drivers/media/usb/dvb-usb/dib0700_devices.o: In function `dib01x0_pmu_update.constprop.7': dib0700_devices.c:(.text.unlikely+0x1c9c): undefined reference to `dibx000_i2c_set_speed' The call sites are both through dib01x0_pmu_update(), which gets passed an 'i2c' pointer from dib9000_get_i2c_master(), which has returned NULL. Checking this pointer seems to be a good idea anyway, and it avoids the link failure in most cases. Sean Young found another case that is not fixed by that, where certain gcc versions leave an unused function in place that causes the link error, but adding an explict IS_ENABLED() check also solves this. Fixes: b7f54910ce01 ("V4L/DVB (4647): Added module for DiB0700 based devices") Signed-off-by: Arnd Bergmann Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dib0700_devices.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 66d685065e06..ab7a100ec84f 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -2439,9 +2439,13 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap) 8, 0x0486, }; + if (!IS_ENABLED(CONFIG_DVB_DIB9000)) + return -ENODEV; if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL) return -ENODEV; i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); + if (!i2c) + return -ENODEV; if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0) return -ENODEV; dib0700_set_i2c_speed(adap->dev, 1500); @@ -2517,10 +2521,14 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap) 0, 0x00ef, 8, 0x0406, }; + if (!IS_ENABLED(CONFIG_DVB_DIB9000)) + return -ENODEV; i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe); if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL) return -ENODEV; i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); + if (!i2c) + return -ENODEV; if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0) return -ENODEV; -- GitLab From 19d41a2899dcca7862af453d62a8e61933f3252d Mon Sep 17 00:00:00 2001 From: A Sun Date: Sun, 14 Jul 2019 22:51:26 -0400 Subject: [PATCH 0213/7155] media: mceusb: USB reset device following USB clear halt error This patch schedules a USB reset device call following a USB clear halt error. The issues solved, and patch implementation, are similar to those found in drivers/hid/usbhid/hid-core.c. As seen on very rare occasions approximately one time per month (mceusb device 2304:0225 in this sample) Jul 27 2018 15:09:39 [59388.696941] mceusb 1-1.1.2:1.0: Error: urb status = -32 (RX HALT) [59388.698838] mceusb 1-1.1.2:1.0: rx clear halt error -32 the device can get into RX or TX HALT state where usb_clear_halt() also fails and also returns -EPIPE (HALT/STALL). After which, all further mceusb device control and data I/O always fail with HALT/STALL. Subsequently, the entire mceusb device no longer functions. Cause and problem replication conditions remain unknown. Further troubleshooting reveals usb_reset_device() restores mceusb device operation. Patch test 1: Hot unplugging the mceusb device triggers USB RX HALT and USB clear halt errors. A mceusb_dev_disconnect() call follows unplug. This patch's reset device call invokes an extra mceusb_dev_probe() mceusb_dev_disconnect() cycle, before the mceusb driver detaches. The additional probe/disconnect verifies the patch's device reset code executed. But note this patch is for USB clear halt error cases not caused by unplugging the mceusb device. Patch test 2: Simulate a RX HALT and a clear halt error with instrumented code in the driver. Jul 12 2019 19:41:18 [522745.263104] mceusb 1-1.3:1.0: set rx halt retval, 0 [522745.263943] mceusb 1-1.3:1.0: Error: rx urb status = -32 (RX HALT) [522745.263970] mceusb 1-1.3:1.0: kevent 1 scheduled [522745.264016] mceusb 1-1.3:1.0: kevent handler called (flags 0x2) [522745.272883] mceusb 1-1.3:1.0: rx clear halt status = 0 [522745.272917] mceusb 1-1.3:1.0: stuck RX HALT state requires USB Reset Device to clear [522745.273005] mceusb 1-1.3:1.0: mceusb_dev_disconnect called [522745.702815] usb 1-1.3: reset full-speed USB device number 14 using dwc_otg [522745.836812] mceusb 1-1.3:1.0: mceusb_dev_probe called [522745.836823] mceusb 1-1.3:1.0: acceptable bulk inbound endpoint found [522745.836832] mceusb 1-1.3:1.0: acceptable bulk outbound endpoint found ... The result matches what is expected when the device gets into a real rx clear halt error case by itself. This is the same sequence of messages when manually invoking the ./usbreset command line utility with an unpatched mceusb driver. Signed-off-by: A Sun Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 67 ++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 4d5351ebb940..bc74c09ddeb6 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -461,6 +461,7 @@ struct mceusb_dev { /* usb */ struct usb_device *usbdev; + struct usb_interface *usbintf; struct urb *urb_in; unsigned int pipe_in; struct usb_endpoint_descriptor *usb_ep_out; @@ -517,6 +518,7 @@ struct mceusb_dev { unsigned long kevent_flags; # define EVENT_TX_HALT 0 # define EVENT_RX_HALT 1 +# define EVENT_RST_PEND 31 }; /* MCE Device Command Strings, generally a port and command pair */ @@ -758,8 +760,15 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, static void mceusb_defer_kevent(struct mceusb_dev *ir, int kevent) { set_bit(kevent, &ir->kevent_flags); + + if (test_bit(EVENT_RST_PEND, &ir->kevent_flags)) { + dev_dbg(ir->dev, "kevent %d dropped pending USB Reset Device", + kevent); + return; + } + if (!schedule_work(&ir->kevent)) - dev_err(ir->dev, "kevent %d may have been dropped", kevent); + dev_dbg(ir->dev, "kevent %d already scheduled", kevent); else dev_dbg(ir->dev, "kevent %d scheduled", kevent); } @@ -1398,28 +1407,59 @@ static void mceusb_deferred_kevent(struct work_struct *work) container_of(work, struct mceusb_dev, kevent); int status; + dev_err(ir->dev, "kevent handler called (flags 0x%lx)", + ir->kevent_flags); + + if (test_bit(EVENT_RST_PEND, &ir->kevent_flags)) { + dev_err(ir->dev, "kevent handler canceled pending USB Reset Device"); + return; + } + if (test_bit(EVENT_RX_HALT, &ir->kevent_flags)) { usb_unlink_urb(ir->urb_in); status = usb_clear_halt(ir->usbdev, ir->pipe_in); + dev_err(ir->dev, "rx clear halt status = %d", status); if (status < 0) { - dev_err(ir->dev, "rx clear halt error %d", - status); + /* + * Unable to clear RX halt/stall. + * Will need to call usb_reset_device(). + */ + dev_err(ir->dev, + "stuck RX HALT state requires USB Reset Device to clear"); + usb_queue_reset_device(ir->usbintf); + set_bit(EVENT_RST_PEND, &ir->kevent_flags); + clear_bit(EVENT_RX_HALT, &ir->kevent_flags); + + /* Cancel all other error events and handlers */ + clear_bit(EVENT_TX_HALT, &ir->kevent_flags); + return; } clear_bit(EVENT_RX_HALT, &ir->kevent_flags); - if (status == 0) { - status = usb_submit_urb(ir->urb_in, GFP_KERNEL); - if (status < 0) { - dev_err(ir->dev, - "rx unhalt submit urb error %d", - status); - } + status = usb_submit_urb(ir->urb_in, GFP_KERNEL); + if (status < 0) { + dev_err(ir->dev, "rx unhalt submit urb error = %d", + status); } } if (test_bit(EVENT_TX_HALT, &ir->kevent_flags)) { status = usb_clear_halt(ir->usbdev, ir->pipe_out); - if (status < 0) - dev_err(ir->dev, "tx clear halt error %d", status); + dev_err(ir->dev, "tx clear halt status = %d", status); + if (status < 0) { + /* + * Unable to clear TX halt/stall. + * Will need to call usb_reset_device(). + */ + dev_err(ir->dev, + "stuck TX HALT state requires USB Reset Device to clear"); + usb_queue_reset_device(ir->usbintf); + set_bit(EVENT_RST_PEND, &ir->kevent_flags); + clear_bit(EVENT_TX_HALT, &ir->kevent_flags); + + /* Cancel all other error events and handlers */ + clear_bit(EVENT_RX_HALT, &ir->kevent_flags); + return; + } clear_bit(EVENT_TX_HALT, &ir->kevent_flags); } } @@ -1581,6 +1621,7 @@ static int mceusb_dev_probe(struct usb_interface *intf, if (!ir->urb_in) goto urb_in_alloc_fail; + ir->usbintf = intf; ir->usbdev = usb_get_dev(dev); ir->dev = &intf->dev; ir->len_in = maxp; @@ -1688,6 +1729,8 @@ static void mceusb_dev_disconnect(struct usb_interface *intf) struct usb_device *dev = interface_to_usbdev(intf); struct mceusb_dev *ir = usb_get_intfdata(intf); + dev_dbg(&intf->dev, "%s called", __func__); + usb_set_intfdata(intf, NULL); if (!ir) -- GitLab From bc28d36bf11acc5b7bbd1a6ffbe315d15e7c0d0d Mon Sep 17 00:00:00 2001 From: Jan Pieter van Woerkom Date: Wed, 17 Jul 2019 20:36:54 -0400 Subject: [PATCH 0214/7155] media: si2168: add support for Mygica T230C v2 The T230C v2 hardware needs a mode of the si2168 chip to be set for which the si2168 driver previously had no support. This patch uses a specific measure to configure this on the T230C v2 hardware only - see the flag passed via the ts_mode attribute and its dependency on USB_PID_MYGICA_T230C2. Signed-off-by: Jan Pieter van Woerkom Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 11 +++++++++++ drivers/media/dvb-frontends/si2168.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 168c503e9154..a574f1d77c56 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -82,8 +82,19 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire); + /* set manual value */ + if (dev->ts_mode & SI2168_TS_CLK_MANUAL) { + memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6); + cmd.wlen = 6; + cmd.rlen = 4; + ret = si2168_cmd_execute(client, &cmd); + if (ret) + return ret; + } /* set TS_MODE property */ memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); + if (dev->ts_mode & SI2168_TS_CLK_MANUAL) + cmd.args[4] = SI2168_TS_CLK_MANUAL; if (acquire) cmd.args[4] |= dev->ts_mode; else diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h index 3b04f84272d9..50dccb394efa 100644 --- a/drivers/media/dvb-frontends/si2168.h +++ b/drivers/media/dvb-frontends/si2168.h @@ -30,6 +30,7 @@ struct si2168_config { #define SI2168_TS_PARALLEL 0x06 #define SI2168_TS_SERIAL 0x03 #define SI2168_TS_TRISTATE 0x00 +#define SI2168_TS_CLK_MANUAL 0x20 u8 ts_mode; /* TS clock inverted */ -- GitLab From 66193b24514c91aeda88da744554b2665471aeae Mon Sep 17 00:00:00 2001 From: Jan Pieter van Woerkom Date: Wed, 17 Jul 2019 14:09:10 -0400 Subject: [PATCH 0215/7155] media: dvbsky: add support for Mygica T230C v2 Adds support for the "Mygica T230C v2" to the dvbsky driver. Signed-off-by: Jan Pieter van Woerkom Tested-by: Frank Rysanek Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvbsky.c | 5 +++++ include/media/dvb-usb-ids.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 8610487f2d72..bbfe1cfdc013 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -540,6 +540,8 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) si2168_config.i2c_adapter = &i2c_adapter; si2168_config.fe = &adap->fe[0]; si2168_config.ts_mode = SI2168_TS_PARALLEL; + if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2) + si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL; si2168_config.ts_clock_inv = 1; state->i2c_client_demod = dvb_module_probe("si2168", NULL, @@ -779,6 +781,9 @@ static const struct usb_device_id dvbsky_id_table[] = { { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C", RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, + { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2, + &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C v2", + RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, { } }; MODULE_DEVICE_TABLE(usb, dvbsky_id_table); diff --git a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h index 52875e3eee71..7ce4e8332421 100644 --- a/include/media/dvb-usb-ids.h +++ b/include/media/dvb-usb-ids.h @@ -388,6 +388,7 @@ #define USB_PID_MYGICA_D689 0xd811 #define USB_PID_MYGICA_T230 0xc688 #define USB_PID_MYGICA_T230C 0xc689 +#define USB_PID_MYGICA_T230C2 0xc68a #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_2 0x003f -- GitLab From f3b357c280738781df3b25c1cbb8166e11982eeb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 22:59:55 +0200 Subject: [PATCH 0216/7155] leds: an30259a: Fix typo All this file is about an30259a, including the reference to the datasheet at the top of the file. So change the 2 places where an32059a is used instead. Signed-off-by: Christophe JAILLET Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-an30259a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 1c1f0c8c56f4..37e7c7998972 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -353,7 +353,7 @@ MODULE_DEVICE_TABLE(i2c, an30259a_id); static struct i2c_driver an30259a_driver = { .driver = { - .name = "leds-an32059a", + .name = "leds-an30259a", .of_match_table = of_match_ptr(an30259a_match_table), }, .probe_new = an30259a_probe, @@ -364,5 +364,5 @@ static struct i2c_driver an30259a_driver = { module_i2c_driver(an30259a_driver); MODULE_AUTHOR("Simon Shields "); -MODULE_DESCRIPTION("AN32059A LED driver"); +MODULE_DESCRIPTION("AN30259A LED driver"); MODULE_LICENSE("GPL v2"); -- GitLab From bc986391c80decf6b5a16756f29400377833b1e9 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sat, 6 Jul 2019 15:07:50 +0200 Subject: [PATCH 0217/7155] batman-adv: Start new development cycle Signed-off-by: Simon Wunderlich --- net/batman-adv/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 3d4c04d87ff3..6967f2e4c3f4 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -13,7 +13,7 @@ #define BATADV_DRIVER_DEVICE "batman-adv" #ifndef BATADV_SOURCE_VERSION -#define BATADV_SOURCE_VERSION "2019.3" +#define BATADV_SOURCE_VERSION "2019.4" #endif /* B.A.T.M.A.N. parameters */ -- GitLab From 529a8f939a5fdbfa27d10bba728d9764212ab26f Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 6 Jul 2019 14:56:13 +0200 Subject: [PATCH 0218/7155] batman-adv: Replace usage of strlcpy with strscpy The strscpy was introduced to fix some API problems around strlcpy. And checkpatch started to report recently that strlcpy is deprecated and strscpy is preferred. The functionality introduced in commit 30035e45753b ("string: provide strscpy()") improves following points compared to strlcpy: * it doesn't read from memory beyond (src + size) * provides an easy way to check for destination buffer overflow * robust against asynchronous source buffer changes Since batman-adv doesn't depend on any of the previously mentioned behavior changes, the usage of strlcpy can simply be replaced by strscpy to silence checkpatch. Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/soft-interface.c | 8 ++++---- net/batman-adv/sysfs.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c7a2e77ca1da..a1146cb10919 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -943,10 +943,10 @@ static const struct net_device_ops batadv_netdev_ops = { static void batadv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver)); - strlcpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version)); - strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); - strlcpy(info->bus_info, "batman", sizeof(info->bus_info)); + strscpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver)); + strscpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version)); + strscpy(info->fw_version, "N/A", sizeof(info->fw_version)); + strscpy(info->bus_info, "batman", sizeof(info->bus_info)); } /* Inspired by drivers/net/ethernet/dlink/sundance.c:1702 diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 1efcb97039cd..e5bbc28ed12c 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -1070,7 +1070,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj, dev_hold(net_dev); INIT_WORK(&store_work->work, batadv_store_mesh_iface_work); store_work->net_dev = net_dev; - strlcpy(store_work->soft_iface_name, buff, + strscpy(store_work->soft_iface_name, buff, sizeof(store_work->soft_iface_name)); queue_work(batadv_event_workqueue, &store_work->work); -- GitLab From 967ea03cc345d86c8e134d7610e61a3012046407 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 23:05:39 +0200 Subject: [PATCH 0219/7155] leds: ktd2692: Fix a typo in the name of a constant There is a typo in KTD2962_MM_MIN_CURR_THRESHOLD_SCALE. 6 and 9 are switched in 2962. Define and use KTD2692_MM_MIN_CURR_THRESHOLD_SCALE instead. Signed-off-by: Christophe JAILLET Acked-by: Pavel Machek Reviewed-by: Enrico Weigelt Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ktd2692.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c index f63918206bfb..670efee9b131 100644 --- a/drivers/leds/leds-ktd2692.c +++ b/drivers/leds/leds-ktd2692.c @@ -19,7 +19,7 @@ /* Value related the movie mode */ #define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16 #define KTD2692_MM_TO_FL_RATIO(x) ((x) / 3) -#define KTD2962_MM_MIN_CURR_THRESHOLD_SCALE 8 +#define KTD2692_MM_MIN_CURR_THRESHOLD_SCALE 8 /* Value related the flash mode */ #define KTD2692_FLASH_MODE_TIMEOUT_LEVELS 8 @@ -250,7 +250,7 @@ static void ktd2692_setup(struct ktd2692_context *led) ktd2692_expresswire_reset(led); gpiod_direction_output(led->aux_gpio, KTD2692_LOW); - ktd2692_expresswire_write(led, (KTD2962_MM_MIN_CURR_THRESHOLD_SCALE - 1) + ktd2692_expresswire_write(led, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1) | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE); ktd2692_expresswire_write(led, KTD2692_FLASH_MODE_CURR_PERCENT(45) | KTD2692_REG_FLASH_CURRENT_BASE); -- GitLab From 0344e6166bbf90ad3fe05497ffe754bd65f9e7ac Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:28 +0200 Subject: [PATCH 0220/7155] leds: apu: drop superseeded apu2/3 led support This driver only supports gpio-attached LEDs on apu1/2/3 boards, but neither gpio's themselves, nor other gpio-attached devices (eg. front button). For apu2+ a newer, more complete driver exists, based on a generic driver for the AMD SOCs gpio-controller, supporting LEDs as well other devices. Therefore these boards don't need legacy support from this driver anymore. Both drivers claim the same device, so only one driver may exist in a system, putting distros in the position to decide between either apu2+ keys or apu1 led support. Therefore drop the apu2+ led support from the old driver, solve the conflict and reduce unnecessary code. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 5 +- drivers/leds/leds-apu.c | 124 ++-------------------------------------- 2 files changed, 10 insertions(+), 119 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index b0fdeef10bd9..f7a3dd7ecf3d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -74,9 +74,12 @@ config LEDS_APU depends on LEDS_CLASS depends on X86 && DMI help - This driver makes the PC Engines APU/APU2/APU3 front panel LEDs + This driver makes the PC Engines APU1 front panel LEDs accessible from userspace programs through the LED subsystem. + If you're looking for APU2/3, use the pcengines-apu2 driver. + (symbol CONFIG_PCENGINES_APU2) + To compile this driver as a module, choose M here: the module will be called leds-apu. diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 8d42e46e2de3..140093a0494d 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -47,12 +47,6 @@ #define APU1_NUM_GPIO 3 #define APU1_IOSIZE sizeof(u8) -#define APU2_FCH_ACPI_MMIO_BASE 0xFED80000 -#define APU2_FCH_GPIO_BASE (APU2_FCH_ACPI_MMIO_BASE + 0x1500) -#define APU2_GPIO_BIT_WRITE 22 -#define APU2_APU2_NUM_GPIO 4 -#define APU2_IOSIZE sizeof(u32) - /* LED access parameters */ struct apu_param { void __iomem *addr; /* for ioread/iowrite */ @@ -75,7 +69,6 @@ struct apu_led_profile { /* Supported platform types */ enum apu_led_platform_types { APU1_LED_PLATFORM, - APU2_LED_PLATFORM, }; struct apu_led_pdata { @@ -96,19 +89,6 @@ static const struct apu_led_profile apu1_led_profile[] = { { "apu:green:3", LED_OFF, APU1_FCH_GPIO_BASE + 2 * APU1_IOSIZE }, }; -static const struct apu_led_profile apu2_led_profile[] = { - { "apu2:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, - { "apu2:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, - { "apu2:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, -}; - -/* Same as apu2_led_profile, but with "3" in the LED names. */ -static const struct apu_led_profile apu3_led_profile[] = { - { "apu3:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, - { "apu3:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, - { "apu3:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, -}; - static const struct dmi_system_id apu_led_dmi_table[] __initconst = { { .ident = "apu", @@ -117,54 +97,6 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "APU") } }, - /* PC Engines APU2 with "Legacy" bios < 4.0.8 */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "APU2") - } - }, - /* PC Engines APU2 with "Legacy" bios >= 4.0.8 */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "apu2") - } - }, - /* PC Engines APU2 with "Mainline" bios */ - { - .ident = "apu2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") - } - }, - /* PC Engines APU3 with "Legacy" bios < 4.0.8 */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "APU3") - } - }, - /* PC Engines APU3 with "Legacy" bios >= 4.0.8 */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "apu3") - } - }, - /* PC Engines APU2 with "Mainline" bios */ - { - .ident = "apu3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), - DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3") - } - }, {} }; MODULE_DEVICE_TABLE(dmi, apu_led_dmi_table); @@ -178,25 +110,6 @@ static void apu1_led_brightness_set(struct led_classdev *led, enum led_brightnes spin_unlock(&apu_led->lock); } -static void apu2_led_brightness_set(struct led_classdev *led, enum led_brightness value) -{ - struct apu_led_priv *pled = cdev_to_priv(led); - u32 value_new; - - spin_lock(&apu_led->lock); - - value_new = ioread32(pled->param.addr); - - if (value) - value_new &= ~BIT(APU2_GPIO_BIT_WRITE); - else - value_new |= BIT(APU2_GPIO_BIT_WRITE); - - iowrite32(value_new, pled->param.addr); - - spin_unlock(&apu_led->lock); -} - static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) { int i; @@ -219,8 +132,6 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->flags = LED_CORE_SUSPENDRESUME; if (apu_led->platform == APU1_LED_PLATFORM) led_cdev->brightness_set = apu1_led_brightness_set; - else if (apu_led->platform == APU2_LED_PLATFORM) - led_cdev->brightness_set = apu2_led_brightness_set; pled->param.addr = devm_ioremap(dev, apu_led->profile[i].offset, apu_led->iosize); @@ -254,27 +165,10 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; - if (dmi_match(DMI_PRODUCT_NAME, "APU")) { - apu_led->profile = apu1_led_profile; - apu_led->platform = APU1_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - apu_led->iosize = APU1_IOSIZE; - } else if (dmi_match(DMI_BOARD_NAME, "APU2") || - dmi_match(DMI_BOARD_NAME, "apu2") || - dmi_match(DMI_BOARD_NAME, "PC Engines apu2")) { - apu_led->profile = apu2_led_profile; - apu_led->platform = APU2_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile); - apu_led->iosize = APU2_IOSIZE; - } else if (dmi_match(DMI_BOARD_NAME, "APU3") || - dmi_match(DMI_BOARD_NAME, "apu3") || - dmi_match(DMI_BOARD_NAME, "PC Engines apu3")) { - apu_led->profile = apu3_led_profile; - /* Otherwise identical to APU2. */ - apu_led->platform = APU2_LED_PLATFORM; - apu_led->num_led_instances = ARRAY_SIZE(apu3_led_profile); - apu_led->iosize = APU2_IOSIZE; - } + apu_led->profile = apu1_led_profile; + apu_led->platform = APU1_LED_PLATFORM; + apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); + apu_led->iosize = APU1_IOSIZE; spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); @@ -295,13 +189,7 @@ static int __init apu_led_init(void) pr_err("No PC Engines board detected\n"); return -ENODEV; } - if (!(dmi_match(DMI_PRODUCT_NAME, "APU") || - dmi_match(DMI_PRODUCT_NAME, "APU2") || - dmi_match(DMI_PRODUCT_NAME, "apu2") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2") || - dmi_match(DMI_PRODUCT_NAME, "APU3") || - dmi_match(DMI_PRODUCT_NAME, "apu3") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu3"))) { + if (!(dmi_match(DMI_PRODUCT_NAME, "APU"))) { pr_err("Unknown PC Engines board: %s\n", dmi_get_system_info(DMI_PRODUCT_NAME)); return -ENODEV; @@ -337,6 +225,6 @@ module_init(apu_led_init); module_exit(apu_led_exit); MODULE_AUTHOR("Alan Mizrahi"); -MODULE_DESCRIPTION("PC Engines APU family LED driver"); +MODULE_DESCRIPTION("PC Engines APU1 front LED driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:leds_apu"); -- GitLab From da97735cbdb44253b549d6acf8204124de8d72f0 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:29 +0200 Subject: [PATCH 0221/7155] leds: apu: drop enum_apu_led_platform_types As this driver now only supports the APU1 boards, we don't need to differenciate between board types anymore. Therefore optimize away the now obsolete code. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 140093a0494d..37b054f76e3d 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -66,16 +66,10 @@ struct apu_led_profile { unsigned long offset; /* for devm_ioremap */ }; -/* Supported platform types */ -enum apu_led_platform_types { - APU1_LED_PLATFORM, -}; - struct apu_led_pdata { struct platform_device *pdev; struct apu_led_priv *pled; const struct apu_led_profile *profile; - enum apu_led_platform_types platform; int num_led_instances; int iosize; /* for devm_ioremap() */ spinlock_t lock; @@ -130,8 +124,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->brightness = apu_led->profile[i].brightness; led_cdev->max_brightness = 1; led_cdev->flags = LED_CORE_SUSPENDRESUME; - if (apu_led->platform == APU1_LED_PLATFORM) - led_cdev->brightness_set = apu1_led_brightness_set; + led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, apu_led->profile[i].offset, apu_led->iosize); @@ -144,7 +137,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) if (err) goto error; - led_cdev->brightness_set(led_cdev, apu_led->profile[i].brightness); + apu1_led_brightness_set(led_cdev, apu_led->profile[i].brightness); } return 0; @@ -166,7 +159,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; apu_led->profile = apu1_led_profile; - apu_led->platform = APU1_LED_PLATFORM; apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); apu_led->iosize = APU1_IOSIZE; -- GitLab From 08e83826a5ebcaea099a999d4e9915148b78f00a Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:30 +0200 Subject: [PATCH 0222/7155] leds: apu: drop iosize field from priv data As this driver now only supports the APU1 boards, we don't need to handle different io sizes anymore. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 37b054f76e3d..f79146c67132 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -71,7 +71,6 @@ struct apu_led_pdata { struct apu_led_priv *pled; const struct apu_led_profile *profile; int num_led_instances; - int iosize; /* for devm_ioremap() */ spinlock_t lock; }; @@ -127,7 +126,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, - apu_led->profile[i].offset, apu_led->iosize); + apu_led->profile[i].offset, APU1_IOSIZE); if (!pled->param.addr) { err = -ENOMEM; goto error; @@ -160,7 +159,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->profile = apu1_led_profile; apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - apu_led->iosize = APU1_IOSIZE; spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); -- GitLab From cc92e3cce5db4efd6b555102dbf267c8c76bb811 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:31 +0200 Subject: [PATCH 0223/7155] leds: apu: drop profile field from priv data As this driver now only supports the APU1 boards, we don't need to handle profiles anymore and just can use the only one global array directly. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index f79146c67132..451cb9fe0653 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -69,8 +69,6 @@ struct apu_led_profile { struct apu_led_pdata { struct platform_device *pdev; struct apu_led_priv *pled; - const struct apu_led_profile *profile; - int num_led_instances; spinlock_t lock; }; @@ -109,24 +107,24 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) int err; apu_led->pled = devm_kcalloc(dev, - apu_led->num_led_instances, sizeof(struct apu_led_priv), + ARRAY_SIZE(apu1_led_profile), sizeof(struct apu_led_priv), GFP_KERNEL); if (!apu_led->pled) return -ENOMEM; - for (i = 0; i < apu_led->num_led_instances; i++) { + for (i = 0; i < ARRAY_SIZE(apu1_led_profile); i++) { struct apu_led_priv *pled = &apu_led->pled[i]; struct led_classdev *led_cdev = &pled->cdev; - led_cdev->name = apu_led->profile[i].name; - led_cdev->brightness = apu_led->profile[i].brightness; + led_cdev->name = apu1_led_profile[i].name; + led_cdev->brightness = apu1_led_profile[i].brightness; led_cdev->max_brightness = 1; led_cdev->flags = LED_CORE_SUSPENDRESUME; led_cdev->brightness_set = apu1_led_brightness_set; pled->param.addr = devm_ioremap(dev, - apu_led->profile[i].offset, APU1_IOSIZE); + apu1_led_profile[i].offset, APU1_IOSIZE); if (!pled->param.addr) { err = -ENOMEM; goto error; @@ -136,7 +134,7 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld) if (err) goto error; - apu1_led_brightness_set(led_cdev, apu_led->profile[i].brightness); + apu1_led_brightness_set(led_cdev, apu1_led_profile[i].brightness); } return 0; @@ -157,9 +155,6 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->pdev = pdev; - apu_led->profile = apu1_led_profile; - apu_led->num_led_instances = ARRAY_SIZE(apu1_led_profile); - spin_lock_init(&apu_led->lock); return apu_led_config(&pdev->dev, apu_led); } @@ -204,7 +199,7 @@ static void __exit apu_led_exit(void) { int i; - for (i = 0; i < apu_led->num_led_instances; i++) + for (i = 0; i < ARRAY_SIZE(apu1_led_profile); i++) led_classdev_unregister(&apu_led->pled[i].cdev); platform_device_unregister(apu_led->pdev); -- GitLab From 93562049a62c5519b3787a428cdd3cfa7fc9e7d4 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 22 Jul 2019 14:08:51 +0200 Subject: [PATCH 0224/7155] leds: apu: fix error message on probing failure The current error message on failed probing tends to be a bit misleading. Fix it to tell exactly that an APU v1 was not found. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 451cb9fe0653..d794f49f9838 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -170,13 +170,9 @@ static int __init apu_led_init(void) struct platform_device *pdev; int err; - if (!dmi_match(DMI_SYS_VENDOR, "PC Engines")) { - pr_err("No PC Engines board detected\n"); - return -ENODEV; - } - if (!(dmi_match(DMI_PRODUCT_NAME, "APU"))) { - pr_err("Unknown PC Engines board: %s\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); + if (!(dmi_match(DMI_SYS_VENDOR, "PC Engines") && + dmi_match(DMI_PRODUCT_NAME, "APU"))) { + pr_err("No PC Engines APUv1 board detected. For APUv2,3 support, enable CONFIG_PCENGINES_APU2\n"); return -ENODEV; } -- GitLab From 60439711b69b893e84d5bab56de66f9433e68a30 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 15 Jul 2019 16:57:33 +0200 Subject: [PATCH 0225/7155] leds: apu: add pr_fmt prefix for better log output Define pr_fmt() macro for prefixing the module name to all pr_*() outputs, in order to increase log message clarity. Signed-off-by: Enrico Weigelt Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-apu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index d794f49f9838..7fd557aceff6 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -31,6 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- GitLab From af311ff9a69189a03548efd5a47d4bb44644fd45 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 17 May 2019 14:09:22 -0700 Subject: [PATCH 0226/7155] firmware: qcom_scm: Cleanup code in qcom_scm_assign_mem() There are some questionable coding styles in this function. It looks quite odd to deref a pointer with array indexing that only uses the first element. Also, destroying an input/output variable halfway through the function and then overwriting it on success is not clear. It's better to use a local variable and the kernel macros to step through each bit set in a bitmask and clearly show where outputs are set. Cc: Ian Jackson Cc: Julien Grall Cc: Bjorn Andersson Cc: Avaneesh Kumar Dwivedi Tested-by: Bjorn Andersson Signed-off-by: Stephen Boyd [bjorn: Changed for_each_set_bit() size to BITS_PER_LONG] Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 34 ++++++++++++++++------------------ include/linux/qcom_scm.h | 9 +++++---- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index c7e63af91567..4802ab170fe5 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -434,7 +434,8 @@ EXPORT_SYMBOL(qcom_scm_set_remote_state); */ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *srcvm, - struct qcom_scm_vmperm *newvm, int dest_cnt) + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt) { struct qcom_scm_current_perm_info *destvm; struct qcom_scm_mem_map_info *mem_to_map; @@ -449,11 +450,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, int next_vm; __le32 *src; void *ptr; - int ret; - int len; - int i; + int ret, i, b; + unsigned long srcvm_bits = *srcvm; - src_sz = hweight_long(*srcvm) * sizeof(*src); + src_sz = hweight_long(srcvm_bits) * sizeof(*src); mem_to_map_sz = sizeof(*mem_to_map); dest_sz = dest_cnt * sizeof(*destvm); ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) + @@ -466,28 +466,26 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, /* Fill source vmid detail */ src = ptr; - len = hweight_long(*srcvm); - for (i = 0; i < len; i++) { - src[i] = cpu_to_le32(ffs(*srcvm) - 1); - *srcvm ^= 1 << (ffs(*srcvm) - 1); - } + i = 0; + for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG) + src[i++] = cpu_to_le32(b); /* Fill details of mem buff to map */ mem_to_map = ptr + ALIGN(src_sz, SZ_64); mem_to_map_phys = ptr_phys + ALIGN(src_sz, SZ_64); - mem_to_map[0].mem_addr = cpu_to_le64(mem_addr); - mem_to_map[0].mem_size = cpu_to_le64(mem_sz); + mem_to_map->mem_addr = cpu_to_le64(mem_addr); + mem_to_map->mem_size = cpu_to_le64(mem_sz); next_vm = 0; /* Fill details of next vmid detail */ destvm = ptr + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64); dest_phys = ptr_phys + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64); - for (i = 0; i < dest_cnt; i++) { - destvm[i].vmid = cpu_to_le32(newvm[i].vmid); - destvm[i].perm = cpu_to_le32(newvm[i].perm); - destvm[i].ctx = 0; - destvm[i].ctx_size = 0; - next_vm |= BIT(newvm[i].vmid); + for (i = 0; i < dest_cnt; i++, destvm++, newvm++) { + destvm->vmid = cpu_to_le32(newvm->vmid); + destvm->perm = cpu_to_le32(newvm->perm); + destvm->ctx = 0; + destvm->ctx_size = 0; + next_vm |= BIT(newvm->vmid); } ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz, diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 3f12cc77fb58..2d5eff506e13 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -49,8 +49,9 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *src, struct qcom_scm_vmperm *newvm, - int dest_cnt); + unsigned int *src, + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt); extern void qcom_scm_cpu_power_down(u32 flags); extern u32 qcom_scm_get_version(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); @@ -87,8 +88,8 @@ qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, - struct qcom_scm_vmperm *newvm, - int dest_cnt) { return -ENODEV; } + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt) { return -ENODEV; } static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline u32 qcom_scm_get_version(void) { return 0; } static inline u32 -- GitLab From 2c6d2d3a580a852fe0a694e13af502a862293e0e Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 21 Jun 2019 07:54:50 -0700 Subject: [PATCH 0227/7155] arm64: dts: qcom: Add Lenovo Miix 630 This adds the initial DT for the Lenovo Miix 630 laptop. Supported functionality includes USB (host), microSD-card, keyboard, and trackpad. Signed-off-by: Jeffrey Hugo Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/msm8998-clamshell.dtsi | 240 ++++++++++++++++++ .../boot/dts/qcom/msm8998-lenovo-miix-630.dts | 30 +++ 3 files changed, 271 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi create mode 100644 arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 0a7e5dfce6f7..c38ca859f2e0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi new file mode 100644 index 000000000000..9682d4dd7496 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */ + +/* + * Common include for MSM8998 clamshell devices, ie the Lenovo Miix 630, + * Asus NovaGo TP370QL, and HP Envy x2. All three devices are basically the + * same, with differences in peripherals. + */ + +#include "msm8998.dtsi" +#include "pm8998.dtsi" +#include "pm8005.dtsi" + +/ { + chosen { + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&qusb2phy { + status = "okay"; + + vdda-pll-supply = <&vreg_l12a_1p8>; + vdda-phy-dpdm-supply = <&vreg_l24a_3p075>; +}; + +&rpm_requests { + pm8998-regulators { + compatible = "qcom,rpm-pm8998-regulators"; + + vdd_s1-supply = <&vph_pwr>; + vdd_s2-supply = <&vph_pwr>; + vdd_s3-supply = <&vph_pwr>; + vdd_s4-supply = <&vph_pwr>; + vdd_s5-supply = <&vph_pwr>; + vdd_s6-supply = <&vph_pwr>; + vdd_s7-supply = <&vph_pwr>; + vdd_s8-supply = <&vph_pwr>; + vdd_s9-supply = <&vph_pwr>; + vdd_s10-supply = <&vph_pwr>; + vdd_s11-supply = <&vph_pwr>; + vdd_s12-supply = <&vph_pwr>; + vdd_s13-supply = <&vph_pwr>; + vdd_l1_l27-supply = <&vreg_s7a_1p025>; + vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>; + vdd_l3_l11-supply = <&vreg_s7a_1p025>; + vdd_l4_l5-supply = <&vreg_s7a_1p025>; + vdd_l6-supply = <&vreg_s5a_2p04>; + vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>; + vdd_l9-supply = <&vph_pwr>; + vdd_l10_l23_l25-supply = <&vph_pwr>; + vdd_l13_l19_l21-supply = <&vph_pwr>; + vdd_l16_l28-supply = <&vph_pwr>; + vdd_l18_l22-supply = <&vph_pwr>; + vdd_l20_l24-supply = <&vph_pwr>; + vdd_l26-supply = <&vreg_s3a_1p35>; + vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>; + + vreg_s3a_1p35: s3 { + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + }; + vreg_s4a_1p8: s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allow-set-load; + }; + vreg_s5a_2p04: s5 { + regulator-min-microvolt = <1904000>; + regulator-max-microvolt = <2040000>; + }; + vreg_s7a_1p025: s7 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1028000>; + }; + vreg_l1a_0p875: l1 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-allow-set-load; + }; + vreg_l2a_1p2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-allow-set-load; + }; + vreg_l3a_1p0: l3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l5a_0p8: l5 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + }; + vreg_l6a_1p8: l6 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + }; + vreg_l7a_1p8: l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l8a_1p2: l8 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l9a_1p8: l9 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l10a_1p8: l10 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l11a_1p0: l11 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l12a_1p8: l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l13a_2p95: l13 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l14a_1p88: l14 { + regulator-min-microvolt = <1880000>; + regulator-max-microvolt = <1880000>; + }; + vreg_15a_1p8: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l16a_2p7: l16 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + }; + vreg_l17a_1p3: l17 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + }; + vreg_l18a_2p7: l18 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + }; + vreg_l19a_3p0: l19 { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3008000>; + }; + vreg_l20a_2p95: l20 { + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-allow-set-load; + }; + vreg_l21a_2p95: l21 { + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-allow-set-load; + regulator-system-load = <800000>; + }; + vreg_l22a_2p85: l22 { + regulator-min-microvolt = <2864000>; + regulator-max-microvolt = <2864000>; + }; + vreg_l23a_3p3: l23 { + regulator-min-microvolt = <3312000>; + regulator-max-microvolt = <3312000>; + }; + vreg_l24a_3p075: l24 { + regulator-min-microvolt = <3088000>; + regulator-max-microvolt = <3088000>; + }; + vreg_l25a_3p3: l25 { + regulator-min-microvolt = <3104000>; + regulator-max-microvolt = <3312000>; + }; + vreg_l26a_1p2: l26 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l28_3p0: l28 { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3008000>; + }; + + vreg_lvs1a_1p8: lvs1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_lvs2a_1p8: lvs2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + }; +}; + +&tlmm { + gpio-reserved-ranges = <0 4>, <81 4>; + + touchpad: touchpad { + config { + pins = "gpio123"; + bias-pull-up; /* pull up */ + }; + }; +}; + +&sdhc2 { + status = "okay"; + + vmmc-supply = <&vreg_l21a_2p95>; + vqmmc-supply = <&vreg_l13a_2p95>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; +}; + +&usb3 { + status = "okay"; +}; + +&usb3_dwc3 { + dr_mode = "host"; /* Force to host until we have Type-C hooked up */ +}; + +&usb3phy { + status = "okay"; + + vdda-phy-supply = <&vreg_l1a_0p875>; + vdda-pll-supply = <&vreg_l2a_1p2>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts new file mode 100644 index 000000000000..407c6a32911c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */ + +/dts-v1/; + +#include "msm8998-clamshell.dtsi" + +/ { + model = "Lenovo Miix 630"; + compatible = "lenovo,miix-630", "qcom,msm8998"; +}; + +&blsp1_i2c6 { + status = "okay"; + + keyboard@3a { + compatible = "hid-over-i2c"; + interrupt-parent = <&tlmm>; + interrupts = <0x79 IRQ_TYPE_LEVEL_LOW>; + reg = <0x3a>; + hid-descr-addr = <0x0001>; + + pinctrl-names = "default"; + pinctrl-0 = <&touchpad>; + }; +}; + +&sdhc2 { + cd-gpios = <&tlmm 95 GPIO_ACTIVE_HIGH>; +}; -- GitLab From 3f527d311932791fde67ffec32536d22d5dd3030 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 21 Jun 2019 07:57:21 -0700 Subject: [PATCH 0228/7155] arm64: dts: qcom: Add HP Envy x2 This adds the initial DT for the HP Envy x2 laptop. Supported functionality includes USB (host), microSD-card, keyboard, and trackpad. Signed-off-by: Jeffrey Hugo Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/msm8998-hp-envy-x2.dts | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index c38ca859f2e0..28695e7c0cc3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts b/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts new file mode 100644 index 000000000000..24073127091f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */ + +/dts-v1/; + +#include "msm8998-clamshell.dtsi" + +/ { + model = "HP Envy x2"; + compatible = "hp,envy-x2", "qcom,msm8998"; +}; + +&blsp1_i2c6 { + status = "okay"; + + keyboard@3a { + compatible = "hid-over-i2c"; + interrupt-parent = <&tlmm>; + interrupts = <0x79 IRQ_TYPE_LEVEL_LOW>; + reg = <0x3a>; + hid-descr-addr = <0x0001>; + + pinctrl-names = "default"; + pinctrl-0 = <&touchpad>; + }; +}; + +&sdhc2 { + cd-gpios = <&tlmm 95 GPIO_ACTIVE_LOW>; +}; -- GitLab From 722eb2f65acc4cebeb710fc7cc98f51513e90f1f Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 21 Jun 2019 07:59:51 -0700 Subject: [PATCH 0229/7155] arm64: dts: qcom: Add Asus NovaGo TP370QL This adds the initial DT for the Asus NovaGo TP370QL laptop. Supported functionality includes USB (host), microSD-card, keyboard, and trackpad. Signed-off-by: Jeffrey Hugo Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../dts/qcom/msm8998-asus-novago-tp370ql.dts | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 28695e7c0cc3..954d75de617b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts b/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts new file mode 100644 index 000000000000..db5821be1e2f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dts @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Jeffrey Hugo. All rights reserved. */ + +/dts-v1/; + +#include "msm8998-clamshell.dtsi" + +/ { + model = "Asus NovaGo TP370QL"; + compatible = "asus,novago-tp370ql", "qcom,msm8998"; +}; + +&blsp1_i2c6 { + status = "okay"; + + touchpad@15 { + compatible = "hid-over-i2c"; + interrupt-parent = <&tlmm>; + interrupts = <0x7b IRQ_TYPE_LEVEL_LOW>; + reg = <0x15>; + hid-descr-addr = <0x0001>; + + pinctrl-names = "default"; + pinctrl-0 = <&touchpad>; + }; + + keyboard@3a { + compatible = "hid-over-i2c"; + interrupt-parent = <&tlmm>; + interrupts = <0x25 IRQ_TYPE_LEVEL_LOW>; + reg = <0x3a>; + hid-descr-addr = <0x0001>; + }; +}; + +&sdhc2 { + cd-gpios = <&tlmm 95 GPIO_ACTIVE_HIGH>; +}; + +&tlmm { + touchpad: touchpad { + config { + pins = "gpio123"; + bias-pull-up; + }; + }; +}; -- GitLab From fcd4e60885af969d190999a6c42454c5578d52f1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 22 Jul 2019 22:01:15 +0200 Subject: [PATCH 0230/7155] r8169: improve rtl_rx This patch improves few aspects of rtl_rx, no functional change intended. 1. inline rtl8169_try_rx_copy 2. make pkt_size unsigned 3. use constant ETH_FCS_LEN instead of value 4 4. We just created the skb, so we don't need the checks in skb_put. Also we don't need the return value of skb_put. Set skb->tail and skb->len directly. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 43 ++++++++--------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 6272115b2848..9c743d2fc29d 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5908,23 +5908,6 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) skb_checksum_none_assert(skb); } -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - struct device *d = tp_to_dev(tp); - - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = napi_alloc_skb(&tp->napi, pkt_size); - if (skb) - skb_copy_to_linear_data(skb, data, pkt_size); - - return skb; -} - static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) { unsigned int cur_rx, rx_left; @@ -5960,17 +5943,13 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget goto process_pkt; } } else { + unsigned int pkt_size; struct sk_buff *skb; - dma_addr_t addr; - int pkt_size; process_pkt: - addr = le64_to_cpu(desc->addr); + pkt_size = status & GENMASK(13, 0); if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - + pkt_size -= ETH_FCS_LEN; /* * The driver does not support incoming fragmented * frames. They are seen as a symptom of over-mtu @@ -5982,15 +5961,23 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget goto release_descriptor; } - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - if (!skb) { + dma_sync_single_for_cpu(tp_to_dev(tp), + le64_to_cpu(desc->addr), + pkt_size, DMA_FROM_DEVICE); + + skb = napi_alloc_skb(&tp->napi, pkt_size); + if (unlikely(!skb)) { dev->stats.rx_dropped++; goto release_descriptor; } + prefetch(tp->Rx_databuff[entry]); + skb_copy_to_linear_data(skb, tp->Rx_databuff[entry], + pkt_size); + skb->tail += pkt_size; + skb->len = pkt_size; + rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); rtl8169_rx_vlan_tag(desc, skb); -- GitLab From 1843f225625bb7c15109136ac870ff39e304fc42 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Thu, 4 Jul 2019 21:43:55 +0800 Subject: [PATCH 0231/7155] dt-bindings: serial: lpuart: add the clock requirement for imx8qxp Add the baud clock requirement for imx8qxp. Signed-off-by: Fugang Duan Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/serial/fsl-lpuart.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt index 21483ba820bc..3495eee81d53 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt @@ -13,7 +13,10 @@ Required properties: - reg : Address and length of the register set for the device - interrupts : Should contain uart interrupt - clocks : phandle + clock specifier pairs, one for each entry in clock-names -- clock-names : should contain: "ipg" - the uart clock +- clock-names : For vf610/ls1021a/imx7ulp, "ipg" clock is for uart bus/baud + clock. For imx8qxp lpuart, "ipg" clock is bus clock that is used to access + lpuart controller registers, it also requires "baud" clock for module to + receive/transmit data. Optional properties: - dmas: A list of two dma specifiers, one for each entry in dma-names. -- GitLab From da335d2bcb426bd016dd0be5263a25b60903c3d2 Mon Sep 17 00:00:00 2001 From: Tao Ren Date: Mon, 17 Jun 2019 21:24:21 -0700 Subject: [PATCH 0232/7155] ARM: dts: aspeed: Add Facebook Minipack BMC Add initial version of device tree for Facebook Minipack ast2500 BMC. Signed-off-by: Tao Ren Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/aspeed-bmc-facebook-minipack.dts | 429 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9159fa2cea90..af23dea7f0f0 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1271,6 +1271,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-arm-centriq2400-rep.dtb \ aspeed-bmc-arm-stardragon4800-rep2.dtb \ aspeed-bmc-facebook-cmm.dtb \ + aspeed-bmc-facebook-minipack.dtb \ aspeed-bmc-facebook-tiogapass.dtb \ aspeed-bmc-facebook-yamp.dtb \ aspeed-bmc-intel-s2600wf.dtb \ diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts new file mode 100644 index 000000000000..c05478296446 --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Facebook Inc. +/dts-v1/; + +#include "aspeed-g5.dtsi" + +/ { + model = "Facebook Minipack 100 BMC"; + compatible = "facebook,minipack-bmc", "aspeed,ast2500"; + + aliases { + /* + * Override the default serial aliases to avoid breaking + * the legacy applications. + */ + serial0 = &uart5; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + + /* + * i2c switch 2-0070, pca9548, 8 child channels assigned + * with bus number 16-23. + */ + i2c16 = &imux16; + i2c17 = &imux17; + i2c18 = &imux18; + i2c19 = &imux19; + i2c20 = &imux20; + i2c21 = &imux21; + i2c22 = &imux22; + i2c23 = &imux23; + + /* + * i2c switch 8-0070, pca9548, 8 child channels assigned + * with bus number 24-31. + */ + i2c24 = &imux24; + i2c25 = &imux25; + i2c26 = &imux26; + i2c27 = &imux27; + i2c28 = &imux28; + i2c29 = &imux29; + i2c30 = &imux30; + i2c31 = &imux31; + + /* + * i2c switch 9-0070, pca9548, 8 child channels assigned + * with bus number 32-39. + */ + i2c32 = &imux32; + i2c33 = &imux33; + i2c34 = &imux34; + i2c35 = &imux35; + i2c36 = &imux36; + i2c37 = &imux37; + i2c38 = &imux38; + i2c39 = &imux39; + + /* + * i2c switch 11-0070, pca9548, 8 child channels assigned + * with bus number 40-47. + */ + i2c40 = &imux40; + i2c41 = &imux41; + i2c42 = &imux42; + i2c43 = &imux43; + i2c44 = &imux44; + i2c45 = &imux45; + i2c46 = &imux46; + i2c47 = &imux47; + }; + + chosen { + stdout-path = &uart1; + bootargs = "debug console=ttyS1,9600n8 root=/dev/ram rw"; + }; + + memory@80000000 { + reg = <0x80000000 0x20000000>; + }; +}; + +&wdt1 { + status = "okay"; + aspeed,reset-type = "system"; +}; + +&wdt2 { + status = "okay"; + aspeed,reset-type = "system"; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "bmc"; +#include "facebook-bmc-flash-layout.dtsi" + }; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default + &pinctrl_ncts1_default + &pinctrl_ndsr1_default + &pinctrl_ndtr1_default + &pinctrl_nrts1_default>; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd2_default + &pinctrl_rxd2_default>; +}; + +&uart3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd3_default + &pinctrl_rxd3_default>; +}; + +&uart4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd4_default + &pinctrl_rxd4_default>; +}; + +&uart5 { + status = "okay"; +}; + +&mac1 { + status = "okay"; + no-hw-checksum; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; +}; + +&i2c0 { + status = "okay"; + bus-frequency = <400000>; + multi-master; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + imux16: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux17: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux18: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux19: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + imux20: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + + imux21: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + + imux22: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + + imux23: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + }; + }; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; + multi-master; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; +}; + +&i2c7 { + status = "okay"; +}; + +&i2c8 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + imux24: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux25: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux26: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux27: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + imux28: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + + imux29: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + + imux30: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + + imux31: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + }; + }; +}; + +&i2c9 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + imux32: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux33: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux34: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux35: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + imux36: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + + imux37: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + + imux38: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + + imux39: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + }; + }; +}; + +&i2c10 { + status = "okay"; +}; + +&i2c11 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + imux40: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux41: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux42: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux43: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + imux44: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + + imux45: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + + imux46: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + }; + + imux47: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + }; + }; +}; + +&i2c12 { + status = "okay"; +}; + +&i2c13 { + status = "okay"; +}; + +&vhub { + status = "okay"; +}; -- GitLab From dc4bea0b989cfa3e3dfd8fe79a18abcfaca19767 Mon Sep 17 00:00:00 2001 From: Andrew Peng Date: Tue, 25 Jun 2019 14:38:16 +0800 Subject: [PATCH 0233/7155] ARM: dts: aspeed: Add Lenovo Hr855xg2 BMC Initial introduction of Lenovo Hr855xg2 family equipped with Aspeed 2500 BMC SoC. Hr855xg2 is a x86 server development kit with a ASPEED ast2500 BMC manufactured by Lenovo. This adds the Hr855xg2 platform device tree file used by the Hr855xg2 BMC machines. Signed-off-by: Andrew Peng Signed-off-by: Yonghui Liu Signed-off-by: Lisa Liu Signed-off-by: Harry Sung Signed-off-by: Derek Lin Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/aspeed-bmc-lenovo-hr855xg2.dts | 663 ++++++++++++++++++ 2 files changed, 664 insertions(+) create mode 100644 arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index af23dea7f0f0..39a05a10a2a2 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1277,6 +1277,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-intel-s2600wf.dtb \ aspeed-bmc-inspur-fp5280g2.dtb \ aspeed-bmc-lenovo-hr630.dtb \ + aspeed-bmc-lenovo-hr855xg2.dtb \ aspeed-bmc-microsoft-olympus.dtb \ aspeed-bmc-opp-lanyang.dtb \ aspeed-bmc-opp-palmetto.dtb \ diff --git a/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts b/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts new file mode 100644 index 000000000000..118eb8bbbf1b --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree file for Lenovo Hr855xg2 platform + * + * Copyright (C) 2019-present Lenovo + */ + +/dts-v1/; + +#include "aspeed-g5.dtsi" +#include + +/ { + model = "HR855XG2 BMC"; + compatible = "lenovo,hr855xg2-bmc", "aspeed,ast2500"; + + aliases { + i2c14 = &i2c_riser1; + i2c15 = &i2c_riser2; + i2c16 = &i2c_riser3; + i2c17 = &i2c_M2; + i2c18 = &channel_0; + i2c19 = &channel_1; + i2c20 = &channel_2; + i2c21 = &channel_3; + }; + + chosen { + stdout-path = &uart5; + bootargs = "console=tty0 console=ttyS4,115200 earlyprintk"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x20000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + flash_memory: region@98000000 { + no-map; + reg = <0x98000000 0x00100000>; /* 1M */ + }; + + gfx_memory: framebuffer { + size = <0x01000000>; + alignment = <0x01000000>; + compatible = "shared-dma-pool"; + reusable; + }; + }; + + leds { + compatible = "gpio-leds"; + + heartbeat { + gpios = <&gpio ASPEED_GPIO(C, 7) GPIO_ACTIVE_LOW>; + }; + + fault { + gpios = <&gpio ASPEED_GPIO(G, 3) GPIO_ACTIVE_LOW>; + }; + }; + + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, + <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>, + <&adc 8>, <&adc 9>, <&adc 10>,<&adc 11>, + <&adc 12>,<&adc 13>,<&adc 14>; + }; + + iio-hwmon-battery { + compatible = "iio-hwmon"; + io-channels = <&adc 15>; + }; + +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "bmc"; + spi-max-frequency = <50000000>; +#include "openbmc-flash-layout.dtsi" + }; +}; + +&lpc_ctrl { + status = "okay"; + memory-region = <&flash_memory>; + flash = <&spi1>; +}; + +&lpc_snoop { + status = "okay"; + snoop-ports = <0x80>; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default>; +}; + +&uart2 { + /* Rear RS-232 connector */ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd2_default + &pinctrl_rxd2_default + &pinctrl_nrts2_default + &pinctrl_ndtr2_default + &pinctrl_ndsr2_default + &pinctrl_ncts2_default + &pinctrl_ndcd2_default + &pinctrl_nri2_default>; +}; + +&uart3 { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; + +&ibt { + status = "okay"; +}; + +&mac0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii1_default>; + use-ncsi; +}; + +&mac1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; +}; + +&adc{ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc0_default + &pinctrl_adc1_default + &pinctrl_adc2_default + &pinctrl_adc3_default + &pinctrl_adc4_default + &pinctrl_adc5_default + &pinctrl_adc6_default + &pinctrl_adc7_default + &pinctrl_adc8_default + &pinctrl_adc9_default + &pinctrl_adc10_default + &pinctrl_adc11_default + &pinctrl_adc12_default + &pinctrl_adc13_default + &pinctrl_adc14_default + &pinctrl_adc15_default>; +}; + +&i2c0 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9545"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c_riser1: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + i2c_riser2: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + i2c_riser3: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + i2c_M2: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; +}; + +&i2c1 { + status = "okay"; + bus-frequency = <90000>; + HotSwap@10 { + compatible = "adm1272"; + reg = <0x10>; + }; + + VR@45 { + compatible = "pmbus"; + reg = <0x45>; + }; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + i2c-switch@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + channel_0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + channel_1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + channel_2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + channel_3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; + /* temp1 */ + tmp75@49 { + compatible = "national,lm75"; + reg = <0x49>; + }; + + /* temp2 */ + tmp75@4d { + compatible = "national,lm75"; + reg = <0x4d>; + }; + + eeprom@54 { + compatible = "atmel,24c256"; + reg = <0x54>; + pagesize = <16>; + }; +}; + +&i2c7 { + status = "okay"; +}; + +&i2c8 { + status = "okay"; +}; + +&i2c9 { + status = "okay"; +}; + +&i2c10 { + status = "okay"; +}; + +&i2c11 { + status = "okay"; +}; + +&i2c13 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&uhci { + status = "okay"; +}; + +&gfx { + status = "okay"; + memory-region = <&gfx_memory>; +}; + +&pwm_tacho { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_default + &pinctrl_pwm1_default + &pinctrl_pwm2_default + &pinctrl_pwm3_default + &pinctrl_pwm4_default + &pinctrl_pwm5_default + &pinctrl_pwm6_default + &pinctrl_pwm7_default>; + + fan@0 { + reg = <0x00>; + aspeed,fan-tach-ch = /bits/ 8 <0x00>; + }; + + fan@1 { + reg = <0x00>; + aspeed,fan-tach-ch = /bits/ 8 <0x01>; + }; + + fan@2 { + reg = <0x01>; + aspeed,fan-tach-ch = /bits/ 8 <0x02>; + }; + + fan@3 { + reg = <0x01>; + aspeed,fan-tach-ch = /bits/ 8 <0x03>; + }; + + fan@4 { + reg = <0x02>; + aspeed,fan-tach-ch = /bits/ 8 <0x04>; + }; + + fan@5 { + reg = <0x02>; + aspeed,fan-tach-ch = /bits/ 8 <0x05>; + }; + + fan@6 { + reg = <0x03>; + aspeed,fan-tach-ch = /bits/ 8 <0x06>; + }; + + fan@7 { + reg = <0x03>; + aspeed,fan-tach-ch = /bits/ 8 <0x07>; + }; + + fan@8 { + reg = <0x04>; + aspeed,fan-tach-ch = /bits/ 8 <0x08>; + }; + + fan@9 { + reg = <0x04>; + aspeed,fan-tach-ch = /bits/ 8 <0x09>; + }; + + fan@10 { + reg = <0x05>; + aspeed,fan-tach-ch = /bits/ 8 <0x0a>; + }; + + fan@11 { + reg = <0x05>; + aspeed,fan-tach-ch = /bits/ 8 <0x0b>; + }; + + fan@12 { + reg = <0x06>; + aspeed,fan-tach-ch = /bits/ 8 <0x0c>; + }; + + fan@13 { + reg = <0x06>; + aspeed,fan-tach-ch = /bits/ 8 <0x0d>; + }; + + fan@14 { + reg = <0x07>; + aspeed,fan-tach-ch = /bits/ 8 <0x0e>; + }; + + fan@15 { + reg = <0x07>; + aspeed,fan-tach-ch = /bits/ 8 <0x0f>; + }; + + fan@16 { + reg = <0x07>; + aspeed,fan-tach-ch = /bits/ 8 <0x0f>; + }; +}; + +&gpio { + + pin_gpio_a1 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_EMMC_RST_N"; + }; + + pin_gpio_a3 { + gpio-hog; + gpios = ; + output-high; + line-name = "PCH_PWROK_BMC_FPGA"; + }; + + pin_gpio_b5 { + gpio-hog; + gpios = ; + output-high; + line-name = "IRQ_BMC_PCH_SMI_LPC_N"; + }; + + pin_gpio_b7 { + gpio-hog; + gpios = ; + output-low; + line-name = "CPU_SM_WP"; + }; + + pin_gpio_e0 { + gpio-hog; + gpios = ; + input; + line-name = "PDB_PSU_SEL"; + }; + + pin_gpio_e2 { + gpio-hog; + gpios = ; + output-high; + line-name = "LOCATOR_LED_N"; + }; + + pin_gpio_e5 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_BMC_DBP_PRESENT_R1_N"; + }; + + pin_gpio_e6 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_ME_SECURITY_OVERRIDE_N"; + }; + + pin_gpio_f0 { + gpio-hog; + gpios = ; + output-high; + line-name = "IRQ_BMC_PCH_NMI_R"; + }; + + pin_gpio_f1 { + gpio-hog; + gpios = ; + input; + line-name = "CPU2_PROCDIS_BMC_N"; + }; + + pin_gpio_f2 { + gpio-hog; + gpios = ; + output-high; + line-name = "RM_THROTTLE_EN_N"; + }; + + pin_gpio_f3 { + gpio-hog; + gpios = ; + output-low; + line-name = "FM_PMBUS_ALERT_B_EN"; + }; + + pin_gpio_f4 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_FORCE_NM_THROTTLE_N"; + }; + + pin_gpio_f6 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_BMC_CPU_PWR_DEBUG_N"; + }; + + pin_gpio_g7 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_PCIE_I2C_MUX_RST_N"; + }; + + pin_gpio_h6 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_BMC_DBP_PRESENT_R2_N"; + }; + + pin_gpio_i3 { + gpio-hog; + gpios = ; + output-high; + line-name = "SPI_BMC_BIOS_WP_N"; + }; + + pin_gpio_j1 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_USB_SEL"; + }; + + pin_gpio_j2 { + gpio-hog; + gpios = ; + output-high; + line-name = "PDB_SMB_RST_N"; + }; + + pin_gpio_j3 { + gpio-hog; + gpios = ; + output-high; + line-name = "SPI_BMC_BIOS_HOLD_N"; + }; + + pin_gpio_l0 { + gpio-hog; + gpios = ; + output-high; + line-name = "PDB_FAN_TACH_SEL"; + }; + + pin_gpio_l1 { + gpio-hog; + gpios = ; + output-high; + line-name = "SYS_RESET_BMC_FPGA_N"; + }; + + pin_gpio_l4 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_EFUSE_FAN_G1_EN"; + }; + + pin_gpio_l5 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_EFUSE_FAN_G2_EN"; + }; + + pin_gpio_r6 { + gpio-hog; + gpios = ; + input; + line-name = "CPU3_PROCDIS_BMC_N"; + }; + + pin_gpio_r7 { + gpio-hog; + gpios = ; + input; + line-name = "CPU4_PROCDIS_BMC_N"; + }; + + pin_gpio_s1 { + gpio-hog; + gpios = ; + output-low; + line-name = "DBP_SYSPWROK_BMC"; + }; + + pin_gpio_s2 { + gpio-hog; + gpios = ; + output-high; + line-name = "PCH_RST_RSMRST_N"; + }; + + pin_gpio_s6 { + gpio-hog; + gpios = ; + output-high; + line-name = "BMC_HW_STRAP_5"; + }; + + pin_gpio_z3 { + gpio-hog; + gpios = ; + output-high; + line-name = "FM_BMC_PCH_SCI_LPC_N"; + }; + + pin_gpio_aa0 { + gpio-hog; + gpios = ; + output-low; + line-name = "FW_PSU_ALERT_EN_N"; + }; + + pin_gpio_aa4 { + gpio-hog; + gpios = ; + output-high; + line-name = "DBP_CPU_PREQ_N"; + }; + + pin_gpio_ab3 { + gpio-hog; + gpios = ; + output-low; + line-name = "BMC_WDTRST"; + }; + + pin_gpio_ac6 { + gpio-hog; + gpios = ; + output-high; + line-name = "ESPI_BMC_ALERT_N"; + }; + +}; -- GitLab From b3b06766315e06e0655d334e3323da7eb21a7e39 Mon Sep 17 00:00:00 2001 From: Vijay Khemka Date: Mon, 22 Jul 2019 17:32:16 -0700 Subject: [PATCH 0234/7155] ARM: dts: aspeed: tiogapass: Add VR devices Adds voltage regulators Infineon pxe1610 devices to Facebook tiogapass platform. Signed-off-by: Vijay Khemka Acked-by: Andrew Jeffery Signed-off-by: Joel Stanley --- .../dts/aspeed-bmc-facebook-tiogapass.dts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts index c4521eda787c..e722e9aef907 100644 --- a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts @@ -144,6 +144,42 @@ &i2c5 { status = "okay"; // CPU Voltage regulators + regulator@48 { + compatible = "infineon,pxe1610"; + reg = <0x48>; + }; + regulator@4a { + compatible = "infineon,pxe1610"; + reg = <0x4a>; + }; + regulator@50 { + compatible = "infineon,pxe1610"; + reg = <0x50>; + }; + regulator@52 { + compatible = "infineon,pxe1610"; + reg = <0x52>; + }; + regulator@58 { + compatible = "infineon,pxe1610"; + reg = <0x58>; + }; + regulator@5a { + compatible = "infineon,pxe1610"; + reg = <0x5a>; + }; + regulator@68 { + compatible = "infineon,pxe1610"; + reg = <0x68>; + }; + regulator@70 { + compatible = "infineon,pxe1610"; + reg = <0x70>; + }; + regulator@72 { + compatible = "infineon,pxe1610"; + reg = <0x72>; + }; }; &i2c6 { -- GitLab From bb1dba7be1ee721b83a9cca24fb6d83f762b147b Mon Sep 17 00:00:00 2001 From: Hongwei Zhang Date: Tue, 4 Jun 2019 17:42:04 -0400 Subject: [PATCH 0235/7155] ARM: dts: aspeed: Add SGPM pinmux Add SGPM pinmux to ast2500-pinctrl function and group, to prepare for supporting SGPIO in AST2500 SoC. Signed-off-by: Hongwei Zhang Acked-by: Linus Walleij Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-g5.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index 5b1ca265c2ce..ca36d18d41f4 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -1346,6 +1346,11 @@ groups = "SDA2"; }; + pinctrl_sgpm_default: sgpm_default { + function = "SGPM"; + groups = "SGPM"; + }; + pinctrl_sgps1_default: sgps1_default { function = "SGPS1"; groups = "SGPS1"; -- GitLab From 2f90ec143af83146a4958d78b47d5220024c7713 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Wed, 16 Jan 2019 12:54:59 +1100 Subject: [PATCH 0236/7155] ARM: configs: aspeed: Enable commonly used network functionality This addresses some assumptions made by systemd about having multiple routing table support in the kernel. systemd-networkd will try and provision mutliple routing tables + policies and will silently break neighbor advertisement responses due to policy configurations on a single table. It also adds support for SLAAC based router settings and faster duplicate address detection. Signed-off-by: William A. Kennington III Signed-off-by: Joel Stanley --- arch/arm/configs/aspeed_g4_defconfig | 8 ++++++++ arch/arm/configs/aspeed_g5_defconfig | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index 019828d7b251..62912de4013d 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -50,14 +50,22 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=y CONFIG_INET=y CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y CONFIG_SYN_COOKIES=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set +CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y # CONFIG_NETFILTER_ADVANCED is not set CONFIG_VLAN_8021Q=y diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index 28fe392c7dfa..f02c30f235b7 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -50,14 +50,22 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=y CONFIG_INET=y CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y CONFIG_SYN_COOKIES=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set +CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y # CONFIG_NETFILTER_ADVANCED is not set CONFIG_VLAN_8021Q=y -- GitLab From 24183825c3c7a9378e5a3a5555c6504edd0a302b Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 23 Jul 2019 12:49:16 +0930 Subject: [PATCH 0237/7155] ARM: configs: aspeed: Refresh defconfigs A noop change to git rid of cruft. Signed-off-by: Joel Stanley --- arch/arm/configs/aspeed_g4_defconfig | 58 ++++++++++------------------ arch/arm/configs/aspeed_g5_defconfig | 49 +++++++++-------------- 2 files changed, 40 insertions(+), 67 deletions(-) diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index 62912de4013d..1857df992484 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -20,20 +20,11 @@ CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y CONFIG_SLAB_FREELIST_RANDOM=y -CONFIG_JUMP_LABEL=y -CONFIG_STRICT_KERNEL_RWX=y -CONFIG_GCC_PLUGINS=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEBUG_FS is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_MQ_IOSCHED_DEADLINE is not set -# CONFIG_MQ_IOSCHED_KYBER is not set # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_ASPEED=y CONFIG_MACH_ASPEED_G4=y CONFIG_VMSPLIT_2G=y CONFIG_AEABI=y -# CONFIG_COMPACTION is not set CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y # CONFIG_ATAGS is not set @@ -42,7 +33,15 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_KEXEC=y +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_JUMP_LABEL=y +CONFIG_STRICT_KERNEL_RWX=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEBUG_FS is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPACTION is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -50,27 +49,12 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=y CONFIG_INET=y CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET6_XFRM_MODE_TUNNEL is not set -# CONFIG_INET6_XFRM_MODE_BEET is not set -CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y # CONFIG_NETFILTER_ADVANCED is not set CONFIG_VLAN_8021Q=y CONFIG_NET_NCSI=y -CONFIG_BPF_STREAM_PARSER=y # CONFIG_WIRELESS is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -148,7 +132,6 @@ CONFIG_ASPEED_BT_IPMI_BMC=y CONFIG_HW_RANDOM_TIMERIOMEM=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA9541=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_ASPEED=y @@ -212,6 +195,7 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_EDAC=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_PCF8523=y @@ -226,13 +210,13 @@ CONFIG_IIO=y CONFIG_ASPEED_ADC=y CONFIG_MAX1363=y CONFIG_BMP280=y +CONFIG_RAS=y CONFIG_FSI=y CONFIG_FSI_MASTER_GPIO=y CONFIG_FSI_MASTER_HUB=y CONFIG_FSI_MASTER_AST_CF=y CONFIG_FSI_SCOM=y CONFIG_FSI_SBEFIFO=y -CONFIG_FIRMWARE_MEMMAP=y CONFIG_FANOTIFY=y CONFIG_OVERLAY_FS=y CONFIG_TMPFS=y @@ -245,6 +229,17 @@ CONFIG_SQUASHFS=y CONFIG_SQUASHFS_XZ=y CONFIG_SQUASHFS_ZSTD=y # CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y +# CONFIG_CRYPTO_ECHAINIV is not set +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_USER_API_HASH=y +# CONFIG_CRYPTO_HW is not set +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_SPARC is not set CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y @@ -263,14 +258,3 @@ CONFIG_FUNCTION_TRACER=y # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_DEBUG_WX=y CONFIG_DEBUG_USER=y -CONFIG_HARDENED_USERCOPY=y -CONFIG_FORTIFY_SOURCE=y -# CONFIG_CRYPTO_ECHAINIV is not set -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_USER_API_HASH=y -# CONFIG_CRYPTO_HW is not set -# CONFIG_XZ_DEC_X86 is not set -# CONFIG_XZ_DEC_POWERPC is not set -# CONFIG_XZ_DEC_IA64 is not set -# CONFIG_XZ_DEC_SPARC is not set diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index f02c30f235b7..426d8e0c9890 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -20,29 +20,28 @@ CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y CONFIG_SLAB_FREELIST_RANDOM=y -CONFIG_JUMP_LABEL=y -CONFIG_STRICT_KERNEL_RWX=y -CONFIG_GCC_PLUGINS=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEBUG_FS is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_MQ_IOSCHED_DEADLINE is not set -# CONFIG_MQ_IOSCHED_KYBER is not set CONFIG_ARCH_MULTI_V6=y # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_ASPEED=y CONFIG_MACH_ASPEED_G5=y # CONFIG_CACHE_L2X0 is not set CONFIG_VMSPLIT_2G=y -# CONFIG_COMPACTION is not set CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y # CONFIG_ATAGS is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_KEXEC=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SUSPEND is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_JUMP_LABEL=y +CONFIG_STRICT_KERNEL_RWX=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEBUG_FS is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPACTION is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -55,22 +54,15 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_MULTIPATH=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y -# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET6_XFRM_MODE_TUNNEL is not set -# CONFIG_INET6_XFRM_MODE_BEET is not set CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y # CONFIG_NETFILTER_ADVANCED is not set CONFIG_VLAN_8021Q=y CONFIG_NET_NCSI=y -CONFIG_BPF_STREAM_PARSER=y # CONFIG_WIRELESS is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -148,7 +140,6 @@ CONFIG_ASPEED_BT_IPMI_BMC=y CONFIG_HW_RANDOM_TIMERIOMEM=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA9541=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_ASPEED=y @@ -236,7 +227,6 @@ CONFIG_FSI_MASTER_HUB=y CONFIG_FSI_MASTER_AST_CF=y CONFIG_FSI_SCOM=y CONFIG_FSI_SBEFIFO=y -CONFIG_FIRMWARE_MEMMAP=y CONFIG_FANOTIFY=y CONFIG_OVERLAY_FS=y CONFIG_TMPFS=y @@ -249,6 +239,16 @@ CONFIG_SQUASHFS=y CONFIG_SQUASHFS_XZ=y CONFIG_SQUASHFS_ZSTD=y # CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_USER_API_HASH=y +# CONFIG_CRYPTO_HW is not set +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_SPARC is not set CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y @@ -267,14 +267,3 @@ CONFIG_FUNCTION_TRACER=y # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_DEBUG_WX=y CONFIG_DEBUG_USER=y -CONFIG_HARDENED_USERCOPY=y -CONFIG_FORTIFY_SOURCE=y -# CONFIG_CRYPTO_ECHAINIV is not set -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_USER_API_HASH=y -# CONFIG_CRYPTO_HW is not set -# CONFIG_XZ_DEC_X86 is not set -# CONFIG_XZ_DEC_POWERPC is not set -# CONFIG_XZ_DEC_IA64 is not set -# CONFIG_XZ_DEC_SPARC is not set -- GitLab From 7e24b4ed5ac4321e41415b0c6f0f8a8ac14852b2 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Mon, 22 Jul 2019 15:41:34 +0800 Subject: [PATCH 0238/7155] net: usb: Merge cpu_to_le32s + memcpy to put_unaligned_le32 Merge the combo uses of cpu_to_le32s and memcpy. Use put_unaligned_le32 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 9 ++++----- drivers/net/usb/ax88179_178a.c | 11 ++++------- drivers/net/usb/lan78xx.c | 11 ++++------- drivers/net/usb/smsc75xx.c | 11 ++++------- drivers/net/usb/sr9800.c | 9 ++++----- 5 files changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index b39ee714fb01..e39f41efda3e 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -221,6 +221,7 @@ struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, int tailroom = skb_tailroom(skb); u32 packet_len; u32 padbytes = 0xffff0000; + void *ptr; padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; @@ -256,13 +257,11 @@ struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len; - skb_push(skb, 4); - cpu_to_le32s(&packet_len); - skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); + ptr = skb_push(skb, 4); + put_unaligned_le32(packet_len, ptr); if (padlen) { - cpu_to_le32s(&padbytes); - memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); + put_unaligned_le32(padbytes, skb_tail_pointer(skb)); skb_put(skb, sizeof(padbytes)); } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 72d165114b67..daa54486ab09 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1421,6 +1421,7 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) int frame_size = dev->maxpacket; int mss = skb_shinfo(skb)->gso_size; int headroom; + void *ptr; tx_hdr1 = skb->len; tx_hdr2 = mss; @@ -1435,13 +1436,9 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) return NULL; } - skb_push(skb, 4); - cpu_to_le32s(&tx_hdr2); - skb_copy_to_linear_data(skb, &tx_hdr2, 4); - - skb_push(skb, 4); - cpu_to_le32s(&tx_hdr1); - skb_copy_to_linear_data(skb, &tx_hdr1, 4); + ptr = skb_push(skb, 8); + put_unaligned_le32(tx_hdr1, ptr); + put_unaligned_le32(tx_hdr2, ptr + 4); return skb; } diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 9c33b35bd155..769bb262fbec 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2729,6 +2729,7 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, struct sk_buff *skb, gfp_t flags) { u32 tx_cmd_a, tx_cmd_b; + void *ptr; if (skb_cow_head(skb, TX_OVERHEAD)) { dev_kfree_skb_any(skb); @@ -2757,13 +2758,9 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, tx_cmd_b |= skb_vlan_tag_get(skb) & TX_CMD_B_VTAG_MASK_; } - skb_push(skb, 4); - cpu_to_le32s(&tx_cmd_b); - memcpy(skb->data, &tx_cmd_b, 4); - - skb_push(skb, 4); - cpu_to_le32s(&tx_cmd_a); - memcpy(skb->data, &tx_cmd_a, 4); + ptr = skb_push(skb, 8); + put_unaligned_le32(tx_cmd_a, ptr); + put_unaligned_le32(tx_cmd_b, ptr + 4); return skb; } diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 7fac9db5380d..9556d431885f 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2255,6 +2255,7 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { u32 tx_cmd_a, tx_cmd_b; + void *ptr; if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { dev_kfree_skb_any(skb); @@ -2275,13 +2276,9 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, tx_cmd_b = 0; } - skb_push(skb, 4); - cpu_to_le32s(&tx_cmd_b); - memcpy(skb->data, &tx_cmd_b, 4); - - skb_push(skb, 4); - cpu_to_le32s(&tx_cmd_a); - memcpy(skb->data, &tx_cmd_a, 4); + ptr = skb_push(skb, 8); + put_unaligned_le32(tx_cmd_a, ptr); + put_unaligned_le32(tx_cmd_b, ptr + 4); return skb; } diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 35f39f23d881..c5d4a0060124 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -115,6 +115,7 @@ static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, u32 padbytes = 0xffff0000; u32 packet_len; int padlen; + void *ptr; padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4; @@ -133,14 +134,12 @@ static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, return NULL; } - skb_push(skb, 4); + ptr = skb_push(skb, 4); packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); - cpu_to_le32s(&packet_len); - skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); + put_unaligned_le32(packet_len, ptr); if (padlen) { - cpu_to_le32s(&padbytes); - memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); + put_unaligned_le32(padbytes, skb_tail_pointer(skb)); skb_put(skb, sizeof(padbytes)); } -- GitLab From d7840976e3915669382c62ddd1700960f348328e Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:25 -0700 Subject: [PATCH 0239/7155] net: Use skb accessors in network drivers In preparation for unifying the skb_frag and bio_vec, use the fine accessors which already exist and use skb_frag_t instead of struct skb_frag_struct. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- drivers/crypto/chelsio/chtls/chtls_io.c | 6 +++-- drivers/hsi/clients/ssi_protocol.c | 3 ++- drivers/infiniband/hw/hfi1/vnic_sdma.c | 2 +- drivers/net/ethernet/3com/3c59x.c | 2 +- drivers/net/ethernet/agere/et131x.c | 6 ++--- drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/apm/xgene/xgene_enet_main.c | 3 ++- drivers/net/ethernet/atheros/alx/main.c | 4 +--- .../net/ethernet/atheros/atl1c/atl1c_main.c | 4 +--- .../net/ethernet/atheros/atl1e/atl1e_main.c | 3 +-- drivers/net/ethernet/atheros/atlx/atl1.c | 3 +-- drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/brocade/bna/bnad.c | 2 +- drivers/net/ethernet/calxeda/xgmac.c | 2 +- .../net/ethernet/cavium/liquidio/lio_main.c | 23 +++++++++---------- .../ethernet/cavium/liquidio/lio_vf_main.c | 23 +++++++++---------- .../ethernet/cavium/thunder/nicvf_queues.c | 4 +--- drivers/net/ethernet/chelsio/cxgb3/sge.c | 2 +- drivers/net/ethernet/cortina/gemini.c | 5 ++-- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- drivers/net/ethernet/freescale/enetc/enetc.c | 2 +- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 ++-- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 8 +++---- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 2 +- drivers/net/ethernet/ibm/emac/core.c | 2 +- drivers/net/ethernet/intel/e1000/e1000_main.c | 3 +-- drivers/net/ethernet/intel/e1000e/netdev.c | 3 +-- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 5 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 +- drivers/net/ethernet/intel/iavf/iavf_txrx.c | 4 ++-- drivers/net/ethernet/intel/iavf/iavf_txrx.h | 2 +- drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++--- drivers/net/ethernet/intel/igb/igb_main.c | 5 ++-- drivers/net/ethernet/intel/igbvf/netdev.c | 2 +- drivers/net/ethernet/intel/igc/igc_main.c | 5 ++-- drivers/net/ethernet/intel/ixgb/ixgb_main.c | 4 +--- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 9 ++++---- .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/ethernet/jme.c | 5 ++-- drivers/net/ethernet/marvell/mvneta.c | 4 ++-- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 +++--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 4 +--- .../net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- drivers/net/ethernet/microchip/lan743x_main.c | 5 ++-- .../net/ethernet/myricom/myri10ge/myri10ge.c | 10 ++++---- .../ethernet/netronome/nfp/nfp_net_common.c | 6 ++--- .../ethernet/qlogic/netxen/netxen_nic_main.c | 4 ++-- .../net/ethernet/qlogic/qlcnic/qlcnic_io.c | 2 +- drivers/net/ethernet/qualcomm/emac/emac-mac.c | 12 ++++------ .../net/ethernet/synopsys/dwc-xlgmac-desc.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-net.c | 2 +- drivers/net/ethernet/tehuti/tehuti.c | 2 +- drivers/net/usb/usbnet.c | 4 ++-- drivers/net/vmxnet3/vmxnet3_drv.c | 7 +++--- drivers/net/wireless/ath/wil6210/debugfs.c | 3 +-- drivers/net/wireless/ath/wil6210/txrx.c | 9 ++++---- drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +- drivers/net/xen-netback/netback.c | 4 ++-- drivers/s390/net/qeth_core_main.c | 2 +- drivers/scsi/fcoe/fcoe_transport.c | 2 +- drivers/staging/octeon/ethernet-tx.c | 5 ++-- .../staging/unisys/visornic/visornic_main.c | 4 ++-- drivers/target/iscsi/cxgbit/cxgbit_target.c | 13 ++++++----- 69 files changed, 149 insertions(+), 164 deletions(-) diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c index 551bca6fef24..c70cb5f272cf 100644 --- a/drivers/crypto/chelsio/chtls/chtls_io.c +++ b/drivers/crypto/chelsio/chtls/chtls_io.c @@ -1134,7 +1134,9 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) } /* Update the skb. */ if (merge) { - skb_shinfo(skb)->frags[i - 1].size += copy; + skb_frag_size_add( + &skb_shinfo(skb)->frags[i - 1], + copy); } else { skb_fill_page_desc(skb, i, page, off, copy); if (off + copy < pg_size) { @@ -1247,7 +1249,7 @@ int chtls_sendpage(struct sock *sk, struct page *page, i = skb_shinfo(skb)->nr_frags; if (skb_can_coalesce(skb, i, page, offset)) { - skb_shinfo(skb)->frags[i - 1].size += copy; + skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); } else if (i < MAX_SKB_FRAGS) { get_page(page); skb_fill_page_desc(skb, i, page, offset, copy); diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 9aeed98b87a1..c9e3f928b93d 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -181,7 +181,8 @@ static void ssip_skb_to_msg(struct sk_buff *skb, struct hsi_msg *msg) sg = sg_next(sg); BUG_ON(!sg); frag = &skb_shinfo(skb)->frags[i]; - sg_set_page(sg, frag->page.p, frag->size, frag->page_offset); + sg_set_page(sg, skb_frag_page(frag), skb_frag_size(frag), + frag->page_offset); } } diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c index af1b1ffcb38e..05a140504a99 100644 --- a/drivers/infiniband/hw/hfi1/vnic_sdma.c +++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c @@ -102,7 +102,7 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde, goto bail_txadd; for (i = 0; i < skb_shinfo(tx->skb)->nr_frags; i++) { - struct skb_frag_struct *frag = &skb_shinfo(tx->skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(tx->skb)->frags[i]; /* combine physically continuous fragments later? */ ret = sdma_txadd_page(sde->dd, diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 147051404194..7be91e896f2d 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2175,7 +2175,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_addr = skb_frag_dma_map(vp->gendev, frag, 0, - frag->size, + skb_frag_size(frag), DMA_TO_DEVICE); if (dma_mapping_error(vp->gendev, dma_addr)) { for(i = i-1; i >= 0; i--) diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index ea34bcb868b5..e43d922f043e 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c @@ -2426,7 +2426,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) u32 thiscopy, remainder; struct sk_buff *skb = tcb->skb; u32 nr_frags = skb_shinfo(skb)->nr_frags + 1; - struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0]; + skb_frag_t *frags = &skb_shinfo(skb)->frags[0]; struct phy_device *phydev = adapter->netdev->phydev; dma_addr_t dma_addr; struct tx_ring *tx_ring = &adapter->tx_ring; @@ -2488,11 +2488,11 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) frag++; } } else { - desc[frag].len_vlan = frags[i - 1].size; + desc[frag].len_vlan = skb_frag_size(&frags[i - 1]); dma_addr = skb_frag_dma_map(&adapter->pdev->dev, &frags[i - 1], 0, - frags[i - 1].size, + desc[frag].len_vlan, DMA_TO_DEVICE); desc[frag].addr_lo = lower_32_bits(dma_addr); desc[frag].addr_hi = upper_32_bits(dma_addr); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index 533094233659..230726d7b74f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -526,7 +526,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb) struct xgbe_ring *ring = channel->tx_ring; struct xgbe_ring_data *rdata; struct xgbe_packet_data *packet; - struct skb_frag_struct *frag; + skb_frag_t *frag; dma_addr_t skb_dma; unsigned int start_index, cur_index; unsigned int offset, tso, vlan, datalen, len; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 3dd0cecddba8..98f8f2033154 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1833,7 +1833,7 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, struct xgbe_ring *ring, struct sk_buff *skb, struct xgbe_packet_data *packet) { - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned int context_desc; unsigned int len; unsigned int i; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 10b1c053e70a..949bff4d2921 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -340,7 +340,8 @@ static int xgene_enet_work_msg(struct sk_buff *skb, u64 *hopinfo) nr_frags = skb_shinfo(skb)->nr_frags; for (i = 0; i < 2 && i < nr_frags; i++) - len += skb_shinfo(skb)->frags[i].size; + len += skb_frag_size( + &skb_shinfo(skb)->frags[i]); /* HW requires header must reside in 3 buffer */ if (unlikely(hdr_len > len)) { diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index e3538ba7d0e7..a3ec738da336 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1465,9 +1465,7 @@ static int alx_map_tx_skb(struct alx_tx_queue *txq, struct sk_buff *skb) tpd->len = cpu_to_le16(maplen); for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; if (++txq->write_idx == txq->count) txq->write_idx = 0; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index be7f9cebb675..179ad62a2bd2 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2150,9 +2150,7 @@ static int atl1c_tx_map(struct atl1c_adapter *adapter, } for (f = 0; f < nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; use_tpd = atl1c_get_tpd(adapter, type); memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 7f14e010bfeb..4f7b65825c15 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1770,11 +1770,10 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter, } for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; u16 i; u16 seg_num; - frag = &skb_shinfo(skb)->frags[f]; buf_len = skb_frag_size(frag); seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index b5c6dc914720..5f420c17bf3e 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2256,10 +2256,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, } for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; u16 i, nseg; - frag = &skb_shinfo(skb)->frags[f]; buf_len = skb_frag_size(frag); nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) / diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 4632dd5dbad1..148734b166f0 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -172,7 +172,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, flags = 0; for (i = 0; i < nr_frags; i++) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; int len = skb_frag_size(frag); index = (index + 1) % BGMAC_TX_RING_SLOTS; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7134d2c3eb1c..74dd28b82105 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -888,7 +888,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, { unsigned int payload = offset_and_len >> 16; unsigned int len = offset_and_len & 0xffff; - struct skb_frag_struct *frag; + skb_frag_t *frag; struct page *page = data; u16 prod = rxr->rx_prod; struct sk_buff *skb; diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 7767ae6fa1fd..e338272931d1 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3032,7 +3032,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) head_unmap->nvecs++; for (i = 0, vect_id = 0; i < vectors - 1; i++) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; u32 size = skb_frag_size(frag); if (unlikely(size == 0)) { diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 99f49d059414..f96a42af1014 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -1104,7 +1104,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < nfrags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - len = frag->size; + len = skb_frag_size(frag); paddr = skb_frag_dma_map(priv->device, frag, 0, len, DMA_TO_DEVICE); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index eab805579f96..7f3b2e3b0868 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -1492,11 +1492,11 @@ static void free_netsgbuf(void *buf) i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -1535,11 +1535,11 @@ static void free_netsgbuf_with_resp(void *buf) i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -2424,7 +2424,7 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) } else { int i, frags; - struct skb_frag_struct *frag; + skb_frag_t *frag; struct octnic_gather *g; spin_lock(&lio->glist_lock[q_idx]); @@ -2462,11 +2462,9 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) frag = &skb_shinfo(skb)->frags[i - 1]; g->sg[(i >> 2)].ptr[(i & 3)] = - dma_map_page(&oct->pci_dev->dev, - frag->page.p, - frag->page_offset, - frag->size, - DMA_TO_DEVICE); + skb_frag_dma_map(&oct->pci_dev->dev, + frag, 0, skb_frag_size(frag), + DMA_TO_DEVICE); if (dma_mapping_error(&oct->pci_dev->dev, g->sg[i >> 2].ptr[i & 3])) { @@ -2478,7 +2476,7 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) frag = &skb_shinfo(skb)->frags[j - 1]; dma_unmap_page(&oct->pci_dev->dev, g->sg[j >> 2].ptr[j & 3], - frag->size, + skb_frag_size(frag), DMA_TO_DEVICE); } dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n", @@ -2486,7 +2484,8 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3)); + add_sg_size(&g->sg[(i >> 2)], skb_frag_size(frag), + (i & 3)); i++; } diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index db0b90555acb..370d76822ee0 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -837,11 +837,11 @@ static void free_netsgbuf(void *buf) i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -881,11 +881,11 @@ static void free_netsgbuf_with_resp(void *buf) i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -1497,7 +1497,7 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) ndata.reqtype = REQTYPE_NORESP_NET; } else { - struct skb_frag_struct *frag; + skb_frag_t *frag; struct octnic_gather *g; int i, frags; @@ -1535,11 +1535,9 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) frag = &skb_shinfo(skb)->frags[i - 1]; g->sg[(i >> 2)].ptr[(i & 3)] = - dma_map_page(&oct->pci_dev->dev, - frag->page.p, - frag->page_offset, - frag->size, - DMA_TO_DEVICE); + skb_frag_dma_map(&oct->pci_dev->dev, + frag, 0, skb_frag_size(frag), + DMA_TO_DEVICE); if (dma_mapping_error(&oct->pci_dev->dev, g->sg[i >> 2].ptr[i & 3])) { dma_unmap_single(&oct->pci_dev->dev, @@ -1550,7 +1548,7 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) frag = &skb_shinfo(skb)->frags[j - 1]; dma_unmap_page(&oct->pci_dev->dev, g->sg[j >> 2].ptr[j & 3], - frag->size, + skb_frag_size(frag), DMA_TO_DEVICE); } dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n", @@ -1558,7 +1556,8 @@ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3)); + add_sg_size(&g->sg[(i >> 2)], skb_frag_size(frag), + (i & 3)); i++; } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 192bc92da881..c0266a87794c 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1588,9 +1588,7 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq, goto doorbell; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; qentry = nicvf_get_nxt_sqentry(sq, qentry); size = skb_frag_size(frag); diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 89db739b7819..310a232e00f0 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2132,7 +2132,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct port_info *pi = netdev_priv(qs->netdev); struct sk_buff *skb = NULL; struct cpl_rx_pkt *cpl; - struct skb_frag_struct *rx_frag; + skb_frag_t *rx_frag; int nr_frags; int offset = 0; diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 9003eb6716cd..46dd6b4886b6 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -1182,9 +1182,8 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb, buflen = skb_headlen(skb); } else { skb_frag = skb_si->frags + frag; - buffer = page_address(skb_frag_page(skb_frag)) + - skb_frag->page_offset; - buflen = skb_frag->size; + buffer = skb_frag_address(skb_frag); + buflen = skb_frag_size(skb_frag); } if (frag == last_frag) { diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 2edb86ec9fe9..e00a94a03879 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1014,7 +1014,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; len = skb_frag_size(frag); busaddr = skb_frag_dma_map(dev, frag, 0, len, DMA_TO_DEVICE); diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 223709443ea4..b6ff89307409 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -110,7 +110,7 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb, int active_offloads) { struct enetc_tx_swbd *tx_swbd; - struct skb_frag_struct *frag; + skb_frag_t *frag; int len = skb_headlen(skb); union enetc_tx_bd temp_bd; union enetc_tx_bd *txbd; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index e5610a4da539..c01d3ec3e9af 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -365,7 +365,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); - frag_len = skb_shinfo(skb)->frags[frag].size; + frag_len = skb_frag_size(&skb_shinfo(skb)->frags[frag]); /* Handle the last BD specially */ if (frag == nr_frags - 1) { @@ -387,7 +387,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, ebdp->cbd_esc = cpu_to_fec32(estatus); } - bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; + bufaddr = skb_frag_address(this_frag); index = fec_enet_get_bd_index(bdp, &txq->bd); if (((unsigned long) bufaddr) & fep->tx_align || diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index 349970557c52..95a6b0926170 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -719,7 +719,7 @@ static int hix5hd2_fill_sg_desc(struct hix5hd2_priv *priv, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - int len = frag->size; + int len = skb_frag_size(frag); addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE); ret = dma_mapping_error(priv->dev, addr); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 2235dd55fab2..1545536ef769 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -245,7 +245,7 @@ static int hns_nic_maybe_stop_tso( int frag_num; struct sk_buff *skb = *out_skb; struct sk_buff *new_skb = NULL; - struct skb_frag_struct *frag; + skb_frag_t *frag; size = skb_headlen(skb); buf_num = (size + BD_MAX_SEND_SIZE - 1) / BD_MAX_SEND_SIZE; @@ -309,7 +309,7 @@ netdev_tx_t hns_nic_net_xmit_hw(struct net_device *ndev, struct hnae_ring *ring = ring_data->ring; struct device *dev = ring_to_dev(ring); struct netdev_queue *dev_queue; - struct skb_frag_struct *frag; + skb_frag_t *frag; int buf_num; int seg_num; dma_addr_t dma; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 310afa708831..69f7ef810654 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1033,7 +1033,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; struct hns3_desc *desc = &ring->desc[ring->next_to_use]; struct device *dev = ring_to_dev(ring); - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned int frag_buf_num; int k, sizeoflast; dma_addr_t dma; @@ -1086,7 +1086,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); } else { - frag = (struct skb_frag_struct *)priv; + frag = (skb_frag_t *)priv; dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); } @@ -1159,7 +1159,7 @@ static int hns3_nic_bd_num(struct sk_buff *skb) bd_num = hns3_tx_bd_count(size); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; int frag_bd_num; size = skb_frag_size(frag); @@ -1290,7 +1290,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) &tx_ring_data(priv, skb->queue_mapping); struct hns3_enet_ring *ring = ring_data->ring; struct netdev_queue *dev_queue; - struct skb_frag_struct *frag; + skb_frag_t *frag; int next_to_use_head; int buf_num; int seg_num; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index 9c78251f9c39..0e13d1c7e474 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -136,7 +136,7 @@ static int tx_map_skb(struct hinic_dev *nic_dev, struct sk_buff *skb, struct hinic_hwdev *hwdev = nic_dev->hwdev; struct hinic_hwif *hwif = hwdev->hwif; struct pci_dev *pdev = hwif->pdev; - struct skb_frag_struct *frag; + skb_frag_t *frag; dma_addr_t dma_addr; int i, j; diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 395dde444483..9e43c9ace9c2 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -1549,7 +1549,7 @@ emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev) ctrl); /* skb fragments */ for (i = 0; i < nr_frags; ++i) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; len = skb_frag_size(frag); if (unlikely(dev->tx_cnt + mal_tx_chunks(len) >= NUM_TX_BUFF)) diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index f703fa58458e..6b6ba1c38235 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -2889,9 +2889,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter, } for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; - frag = &skb_shinfo(skb)->frags[f]; len = skb_frag_size(frag); offset = 0; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index e4baa13b3cda..a0c001d6d9d2 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5579,9 +5579,8 @@ static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, } for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; - frag = &skb_shinfo(skb)->frags[f]; len = skb_frag_size(frag); offset = 0; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 90270b4a1682..9ffff7886085 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -946,7 +946,7 @@ static void fm10k_tx_map(struct fm10k_ring *tx_ring, struct sk_buff *skb = first->skb; struct fm10k_tx_buffer *tx_buffer; struct fm10k_tx_desc *tx_desc; - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned char *data; dma_addr_t dma; unsigned int data_len, size; @@ -1074,7 +1074,8 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); if (fm10k_maybe_stop_tx(tx_ring, count + 3)) { tx_ring->tx_stats.tx_busy++; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 2a2fe3ec7926..f162252f01b5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3262,7 +3262,7 @@ int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size) **/ bool __i40e_chk_linearize(struct sk_buff *skb) { - const struct skb_frag_struct *frag, *stale; + const skb_frag_t *frag, *stale; int nr_frags, sum; /* no need to check if number of frags is less than 7 */ @@ -3349,7 +3349,7 @@ static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, { unsigned int data_len = skb->data_len; unsigned int size = skb_headlen(skb); - struct skb_frag_struct *frag; + skb_frag_t *frag; struct i40e_tx_buffer *tx_bi; struct i40e_tx_desc *tx_desc; u16 i = tx_ring->next_to_use; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 100e92d2982f..36d37f31a287 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -521,7 +521,7 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring) **/ static inline int i40e_xmit_descriptor_count(struct sk_buff *skb) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; int count = 0, size = skb_headlen(skb); diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index 0cca1b589b56..fae7cd1c618a 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -2161,7 +2161,7 @@ static void iavf_create_tx_ctx(struct iavf_ring *tx_ring, **/ bool __iavf_chk_linearize(struct sk_buff *skb) { - const struct skb_frag_struct *frag, *stale; + const skb_frag_t *frag, *stale; int nr_frags, sum; /* no need to check if number of frags is less than 7 */ @@ -2269,7 +2269,7 @@ static inline void iavf_tx_map(struct iavf_ring *tx_ring, struct sk_buff *skb, { unsigned int data_len = skb->data_len; unsigned int size = skb_headlen(skb); - struct skb_frag_struct *frag; + skb_frag_t *frag; struct iavf_tx_buffer *tx_bi; struct iavf_tx_desc *tx_desc; u16 i = tx_ring->next_to_use; diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h index 71e7d090f8db..dd3348f9da9d 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h @@ -462,7 +462,7 @@ bool __iavf_chk_linearize(struct sk_buff *skb); **/ static inline int iavf_xmit_descriptor_count(struct sk_buff *skb) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; int count = 0, size = skb_headlen(skb); diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 3c83230434b6..dd7392f293bf 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1521,7 +1521,7 @@ ice_tx_map(struct ice_ring *tx_ring, struct ice_tx_buf *first, { u64 td_offset, td_tag, td_cmd; u16 i = tx_ring->next_to_use; - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned int data_len, size; struct ice_tx_desc *tx_desc; struct ice_tx_buf *tx_buf; @@ -1923,7 +1923,7 @@ static unsigned int ice_txd_use_count(unsigned int size) */ static unsigned int ice_xmit_desc_count(struct sk_buff *skb) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int count = 0, size = skb_headlen(skb); @@ -1954,7 +1954,7 @@ static unsigned int ice_xmit_desc_count(struct sk_buff *skb) */ static bool __ice_chk_linearize(struct sk_buff *skb) { - const struct skb_frag_struct *frag, *stale; + const skb_frag_t *frag, *stale; int nr_frags, sum; /* no need to check if number of frags is less than 7 */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b4df3e319467..749645d7f9b7 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5918,7 +5918,7 @@ static int igb_tx_map(struct igb_ring *tx_ring, struct sk_buff *skb = first->skb; struct igb_tx_buffer *tx_buffer; union e1000_adv_tx_desc *tx_desc; - struct skb_frag_struct *frag; + skb_frag_t *frag; dma_addr_t dma; unsigned int data_len, size; u32 tx_flags = first->tx_flags; @@ -6074,7 +6074,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); if (igb_maybe_stop_tx(tx_ring, count + 3)) { /* this is a hard error */ diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 34cd30d7162f..0f2b68f4bb0f 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2174,7 +2174,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, goto dma_error; for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag; count++; i++; diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index aa9323e55406..9ffe71424ece 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -861,7 +861,7 @@ static int igc_tx_map(struct igc_ring *tx_ring, struct igc_tx_buffer *tx_buffer; union igc_adv_tx_desc *tx_desc; u32 tx_flags = first->tx_flags; - struct skb_frag_struct *frag; + skb_frag_t *frag; u16 i = tx_ring->next_to_use; unsigned int data_len, size; dma_addr_t dma; @@ -1015,7 +1015,8 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); if (igc_maybe_stop_tx(tx_ring, count + 3)) { /* this is a hard error */ diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index e5ac2d3fd816..0940a0da16f2 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -1331,9 +1331,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, } for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; len = skb_frag_size(frag); offset = 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index cbaf712d6529..e12d23d1fa64 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1785,7 +1785,7 @@ static bool ixgbe_is_non_eop(struct ixgbe_ring *rx_ring, static void ixgbe_pull_tail(struct ixgbe_ring *rx_ring, struct sk_buff *skb) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; unsigned char *va; unsigned int pull_len; @@ -1840,7 +1840,7 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, skb_headlen(skb), DMA_FROM_DEVICE); } else { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; dma_sync_single_range_for_cpu(rx_ring->dev, IXGBE_CB(skb)->dma, @@ -8186,7 +8186,7 @@ static int ixgbe_tx_map(struct ixgbe_ring *tx_ring, struct sk_buff *skb = first->skb; struct ixgbe_tx_buffer *tx_buffer; union ixgbe_adv_tx_desc *tx_desc; - struct skb_frag_struct *frag; + skb_frag_t *frag; dma_addr_t dma; unsigned int data_len, size; u32 tx_flags = first->tx_flags; @@ -8605,7 +8605,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); if (ixgbe_maybe_stop_tx(tx_ring, count + 3)) { tx_ring->tx_stats.tx_busy++; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index d2b41f9f87f8..bdfccaf38edd 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3949,7 +3949,7 @@ static void ixgbevf_tx_map(struct ixgbevf_ring *tx_ring, struct sk_buff *skb = first->skb; struct ixgbevf_tx_buffer *tx_buffer; union ixgbe_adv_tx_desc *tx_desc; - struct skb_frag_struct *frag; + skb_frag_t *frag; dma_addr_t dma; unsigned int data_len, size; u32 tx_flags = first->tx_flags; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 0b668357db4d..ff6393fd64ac 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2030,12 +2030,12 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) bool hidma = jme->dev->features & NETIF_F_HIGHDMA; int i, nr_frags = skb_shinfo(skb)->nr_frags; int mask = jme->tx_ring_mask; - const struct skb_frag_struct *frag; u32 len; int ret = 0; for (i = 0 ; i < nr_frags ; ++i) { - frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + ctxdesc = txdesc + ((idx + i + 2) & (mask)); ctxbi = txbi + ((idx + i + 2) & (mask)); @@ -2046,7 +2046,6 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) jme_drop_tx_map(jme, idx, i); goto out; } - } len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 895bfed26a8a..15cc678f5e5b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2350,10 +2350,10 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb, for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - void *addr = page_address(frag->page.p) + frag->page_offset; + void *addr = skb_frag_address(frag); tx_desc = mvneta_txq_next_desc_get(txq); - tx_desc->data_size = frag->size; + tx_desc->data_size = skb_frag_size(frag); tx_desc->buf_phys_addr = dma_map_single(pp->dev->dev.parent, addr, diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index c51f1d5b550b..937e4b928b94 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -2911,14 +2911,15 @@ static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - void *addr = page_address(frag->page.p) + frag->page_offset; + void *addr = skb_frag_address(frag); tx_desc = mvpp2_txq_next_desc_get(aggr_txq); mvpp2_txdesc_txq_set(port, tx_desc, txq->id); - mvpp2_txdesc_size_set(port, tx_desc, frag->size); + mvpp2_txdesc_size_set(port, tx_desc, skb_frag_size(frag)); buf_dma_addr = dma_map_single(port->dev->dev.parent, addr, - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), + DMA_TO_DEVICE); if (dma_mapping_error(port->dev->dev.parent, buf_dma_addr)) { mvpp2_txq_desc_put(txq); goto cleanup; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index c39d7f4ab1d4..00991df44ed6 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -696,7 +696,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, txd = itxd; nr_frags = skb_shinfo(skb)->nr_frags; for (i = 0; i < nr_frags; i++) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; unsigned int offset = 0; int frag_size = skb_frag_size(frag); @@ -781,7 +781,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, static inline int mtk_cal_txd_req(struct sk_buff *skb) { int i, nfrags; - struct skb_frag_struct *frag; + skb_frag_t *frag; nfrags = 1; if (skb_is_gso(skb)) { diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 36a92b19e613..4d5ca302c067 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -772,9 +772,7 @@ static bool mlx4_en_build_dma_wqe(struct mlx4_en_priv *priv, /* Map fragments if any */ for (i_frag = shinfo->nr_frags - 1; i_frag >= 0; i_frag--) { - const struct skb_frag_struct *frag; - - frag = &shinfo->frags[i_frag]; + const skb_frag_t *frag = &shinfo->frags[i_frag]; byte_count = skb_frag_size(frag); dma = skb_frag_dma_map(ddev, frag, 0, byte_count, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 600e92cb629a..acf25cc38fa1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -210,7 +210,7 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; int fsz = skb_frag_size(frag); dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz, diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 13e6bf13ac4d..15a8be6bad27 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1434,7 +1434,7 @@ static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx, } static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx, - const struct skb_frag_struct *fragment, + const skb_frag_t *fragment, unsigned int frame_length) { /* called only from within lan743x_tx_xmit_frame @@ -1607,9 +1607,8 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, goto finish; for (j = 0; j < nr_frags; j++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag = &(skb_shinfo(skb)->frags[j]); - frag = &(skb_shinfo(skb)->frags[j]); if (lan743x_tx_frame_add_fragment(tx, frag, frame_length)) { /* upon error no need to call * lan743x_tx_frame_end diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index d8b7fba96d58..9ead6ecb7586 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -1286,7 +1286,7 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb) { u8 *va; struct vlan_ethhdr *veh; - struct skb_frag_struct *frag; + skb_frag_t *frag; __wsum vsum; va = addr; @@ -1318,7 +1318,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) { struct myri10ge_priv *mgp = ss->mgp; struct sk_buff *skb; - struct skb_frag_struct *rx_frags; + skb_frag_t *rx_frags; struct myri10ge_rx_buf *rx; int i, idx, remainder, bytes; struct pci_dev *pdev = mgp->pdev; @@ -1351,7 +1351,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) return 0; } rx_frags = skb_shinfo(skb)->frags; - /* Fill skb_frag_struct(s) with data from our receive */ + /* Fill skb_frag_t(s) with data from our receive */ for (i = 0, remainder = len; remainder > 0; i++) { myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); skb_fill_page_desc(skb, i, rx->info[idx].page, @@ -1365,7 +1365,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) /* remove padding */ rx_frags[0].page_offset += MXGEFW_PAD; - rx_frags[0].size -= MXGEFW_PAD; + skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD); len -= MXGEFW_PAD; skb->len = len; @@ -2628,7 +2628,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb, struct myri10ge_slice_state *ss; struct mcp_kreq_ether_send *req; struct myri10ge_tx_buf *tx; - struct skb_frag_struct *frag; + skb_frag_t *frag; struct netdev_queue *netdev_queue; dma_addr_t bus; u32 low; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 9903805717da..6f97b554f7da 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -975,7 +975,7 @@ static int nfp_net_prep_tx_meta(struct sk_buff *skb, u64 tls_handle) static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) { struct nfp_net *nn = netdev_priv(netdev); - const struct skb_frag_struct *frag; + const skb_frag_t *frag; int f, nr_frags, wr_idx, md_bytes; struct nfp_net_tx_ring *tx_ring; struct nfp_net_r_vector *r_vec; @@ -1155,7 +1155,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring, int budget) todo = D_IDX(tx_ring, qcp_rd_p - tx_ring->qcp_rd_p); while (todo--) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag; struct nfp_net_tx_buf *tx_buf; struct sk_buff *skb; int fidx, nr_frags; @@ -1270,7 +1270,7 @@ static bool nfp_net_xdp_complete(struct nfp_net_tx_ring *tx_ring) static void nfp_net_tx_ring_reset(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag; struct netdev_queue *nd_q; while (!tx_ring->is_xdp && tx_ring->rd_p != tx_ring->wr_p) { diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 58e2eaf77014..c692a41e4548 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1980,7 +1980,7 @@ netxen_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb, struct netxen_cmd_buffer *pbuf) { struct netxen_skb_frag *nf; - struct skb_frag_struct *frag; + skb_frag_t *frag; int i, nr_frags; dma_addr_t map; @@ -2043,7 +2043,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct pci_dev *pdev; int i, k; int delta = 0; - struct skb_frag_struct *frag; + skb_frag_t *frag; u32 producer; int frag_count; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 14f26bf3b388..ac61f614de37 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -581,7 +581,7 @@ static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf) { struct qlcnic_skb_frag *nf; - struct skb_frag_struct *frag; + skb_frag_t *frag; int i, nr_frags; dma_addr_t map; diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 707665b62eb7..bebe38d74d66 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -1385,15 +1385,13 @@ static void emac_tx_fill_tpd(struct emac_adapter *adpt, } for (i = 0; i < nr_frags; i++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; tpbuf = GET_TPD_BUFFER(tx_q, tx_q->tpd.produce_idx); - tpbuf->length = frag->size; - tpbuf->dma_addr = dma_map_page(adpt->netdev->dev.parent, - frag->page.p, frag->page_offset, - tpbuf->length, DMA_TO_DEVICE); + tpbuf->length = skb_frag_size(frag); + tpbuf->dma_addr = skb_frag_dma_map(adpt->netdev->dev.parent, + frag, 0, tpbuf->length, + DMA_TO_DEVICE); ret = dma_mapping_error(adpt->netdev->dev.parent, tpbuf->dma_addr); if (ret) diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c index 031cf9c3435a..8c4195a9a2cc 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c @@ -503,7 +503,7 @@ static int xlgmac_map_tx_skb(struct xlgmac_channel *channel, struct xlgmac_desc_data *desc_data; unsigned int offset, datalen, len; struct xlgmac_pkt_info *pkt_info; - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned int tso, vlan; dma_addr_t skb_dma; unsigned int i; diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c index 1f8e9601592a..a1f5a1e61040 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c @@ -116,7 +116,7 @@ static void xlgmac_prep_tx_pkt(struct xlgmac_pdata *pdata, struct sk_buff *skb, struct xlgmac_pkt_info *pkt_info) { - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned int context_desc; unsigned int len; unsigned int i; diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 5d6960fe3309..0f8a924fc60c 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1501,7 +1501,7 @@ bdx_tx_map_skb(struct bdx_priv *priv, struct sk_buff *skb, bdx_tx_db_inc_wptr(db); for (i = 0; i < nr_frags; i++) { - const struct skb_frag_struct *frag; + const skb_frag_t *frag; frag = &skb_shinfo(skb)->frags[i]; db->wptr->len = skb_frag_size(frag); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 72514c46b478..ace7ffaf3913 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1324,10 +1324,10 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) total_len += skb_headlen(skb); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *f = &skb_shinfo(skb)->frags[i]; + skb_frag_t *f = &skb_shinfo(skb)->frags[i]; total_len += skb_frag_size(f); - sg_set_page(&urb->sg[i + s], f->page.p, f->size, + sg_set_page(&urb->sg[i + s], skb_frag_page(f), skb_frag_size(f), f->page_offset); } urb->transfer_buffer_length = total_len; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 2a1918f25e47..03feaeae89cd 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -657,8 +657,7 @@ static void vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd, struct vmxnet3_rx_buf_info *rbi) { - struct skb_frag_struct *frag = skb_shinfo(skb)->frags + - skb_shinfo(skb)->nr_frags; + skb_frag_t *frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags; BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); @@ -755,7 +754,7 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; u32 buf_size; buf_offset = 0; @@ -956,7 +955,7 @@ static int txd_estimate(const struct sk_buff *skb) int i; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; count += VMXNET3_TXD_NEEDED(skb_frag_size(frag)); } diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 74834131cf7c..fd3b2b3d1b5c 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1052,8 +1052,7 @@ static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb) if (nr_frags) { seq_printf(s, " nr_frags = %d\n", nr_frags); for (i = 0; i < nr_frags; i++) { - const struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; len = skb_frag_size(frag); p = skb_frag_address_safe(frag); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index eae00aafaa88..8b01ef8269da 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1657,7 +1657,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, len); } else { frag = &skb_shinfo(skb)->frags[f]; - len = frag->size; + len = skb_frag_size(frag); wil_dbg_txrx(wil, "TSO: frag[%d]: len %u\n", f, len); } @@ -1678,8 +1678,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, if (!headlen) { pa = skb_frag_dma_map(dev, frag, - frag->size - len, lenmss, - DMA_TO_DEVICE); + skb_frag_size(frag) - len, + lenmss, DMA_TO_DEVICE); vring->ctx[i].mapped_as = wil_mapped_as_page; } else { pa = dma_map_single(dev, @@ -1900,8 +1900,7 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, /* middle segments */ for (; f < nr_frags; f++) { - const struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[f]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; int len = skb_frag_size(frag); *_d = *d; diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index dc040cd4ab06..71b7ad4b6454 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1471,7 +1471,7 @@ static int __wil_tx_ring_tso_edma(struct wil6210_priv *wil, /* Rest of the descriptors are from the SKB fragments */ for (f = 0; f < nr_frags; f++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; - int len = frag->size; + int len = skb_frag_size(frag); wil_dbg_txrx(wil, "TSO: frag[%d]: len %u, descs_used %d\n", f, len, descs_used); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 1d9940d4e8c7..a96c5c2a2c5a 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1055,7 +1055,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s int j; skb->truesize += skb->data_len; for (j = 0; j < i; j++) - put_page(frags[j].page.p); + put_page(skb_frag_page(&frags[j])); return -ENOMEM; } @@ -1067,7 +1067,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s BUG(); offset += len; - frags[i].page.p = page; + __skb_frag_set_page(&frags[i], page); frags[i].page_offset = 0; skb_frag_size_set(&frags[i], len); } diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4d0caeebc802..5aa0f1268bca 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3515,7 +3515,7 @@ static int qeth_get_elements_for_frags(struct sk_buff *skb) int cnt, elements = 0; for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[cnt]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[cnt]; elements += qeth_get_elements_for_range( (addr_t)skb_frag_address(frag), diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index ba4603d76284..d0550384cc38 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -308,7 +308,7 @@ EXPORT_SYMBOL_GPL(fcoe_get_wwn); u32 fcoe_fc_crc(struct fc_frame *fp) { struct sk_buff *skb = fp_skb(fp); - struct skb_frag_struct *frag; + skb_frag_t *frag; unsigned char *data; unsigned long off, len, clen; u32 crc; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 20f513fbaa85..cc12c78f73f1 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -280,11 +280,10 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) hw_buffer.s.size = skb_headlen(skb); CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i; + skb_frag_t *fs = skb_shinfo(skb)->frags + i; hw_buffer.s.addr = - XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + - fs->page_offset)); + XKPHYS_TO_PHYS((u64)skb_frag_address(fs)); hw_buffer.s.size = fs->size; CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 9d4f1dab0968..b889b04a6e25 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -285,8 +285,8 @@ static int visor_copy_fragsinfo_from_skb(struct sk_buff *skb, count = add_physinfo_entries(page_to_pfn( skb_frag_page(&skb_shinfo(skb)->frags[frag])), skb_shinfo(skb)->frags[frag].page_offset, - skb_shinfo(skb)->frags[frag].size, count, - frags_max, frags); + skb_frag_size(&skb_shinfo(skb)->frags[frag]), + count, frags_max, frags); /* add_physinfo_entries only returns * zero if the frags array is out of room * That should never happen because we diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 24309d937d8c..93212b9fd310 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -899,9 +899,9 @@ cxgbit_handle_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, skb_frag_t *dfrag = &ssi->frags[pdu_cb->dfrag_idx]; sg_init_table(&ccmd->sg, 1); - sg_set_page(&ccmd->sg, dfrag->page.p, skb_frag_size(dfrag), - dfrag->page_offset); - get_page(dfrag->page.p); + sg_set_page(&ccmd->sg, skb_frag_page(dfrag), + skb_frag_size(dfrag), dfrag->page_offset); + get_page(skb_frag_page(dfrag)); cmd->se_cmd.t_data_sg = &ccmd->sg; cmd->se_cmd.t_data_nents = 1; @@ -1403,7 +1403,8 @@ static void cxgbit_lro_skb_dump(struct sk_buff *skb) pdu_cb->ddigest, pdu_cb->frags); for (i = 0; i < ssi->nr_frags; i++) pr_info("skb 0x%p, frag %d, off %u, sz %u.\n", - skb, i, ssi->frags[i].page_offset, ssi->frags[i].size); + skb, i, ssi->frags[i].page_offset, + skb_frag_size(&ssi->frags[i])); } static void cxgbit_lro_hskb_reset(struct cxgbit_sock *csk) @@ -1447,7 +1448,7 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx) hpdu_cb->frags++; hpdu_cb->hfrag_idx = hfrag_idx; - len = hssi->frags[hfrag_idx].size; + len = skb_frag_size(&hssi->frags[hfrag_idx]);; hskb->len += len; hskb->data_len += len; hskb->truesize += len; @@ -1467,7 +1468,7 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx) get_page(skb_frag_page(&hssi->frags[dfrag_idx])); - len += hssi->frags[dfrag_idx].size; + len += skb_frag_size(&hssi->frags[dfrag_idx]); hssi->nr_frags++; hpdu_cb->frags++; -- GitLab From d8e18a516f8f67404c0d21af8c93d0474fba0876 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:26 -0700 Subject: [PATCH 0240/7155] net: Use skb accessors in network core In preparation for unifying the skb_frag and bio_vec, use the fine accessors which already exist and use skb_frag_t instead of struct skb_frag_struct. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- net/core/skbuff.c | 24 ++++++++++++++---------- net/core/tso.c | 8 ++++---- net/ipv4/tcp.c | 14 ++++++++------ net/kcm/kcmsock.c | 8 ++++---- net/tls/tls_device.c | 14 +++++++------- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d8af86d995d6..f9078e7edb53 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3166,7 +3166,7 @@ static inline bool skb_can_coalesce(struct sk_buff *skb, int i, if (skb_zcopy(skb)) return false; if (i) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; return page == skb_frag_page(frag) && off == frag->page_offset + skb_frag_size(frag); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0338820ee0ec..ba9a36903503 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2485,19 +2485,19 @@ int skb_send_sock_locked(struct sock *sk, struct sk_buff *skb, int offset, for (fragidx = 0; fragidx < skb_shinfo(skb)->nr_frags; fragidx++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx]; - if (offset < frag->size) + if (offset < skb_frag_size(frag)) break; - offset -= frag->size; + offset -= skb_frag_size(frag); } for (; len && fragidx < skb_shinfo(skb)->nr_frags; fragidx++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx]; - slen = min_t(size_t, len, frag->size - offset); + slen = min_t(size_t, len, skb_frag_size(frag) - offset); while (slen) { - ret = kernel_sendpage_locked(sk, frag->page.p, + ret = kernel_sendpage_locked(sk, skb_frag_page(frag), frag->page_offset + offset, slen, MSG_DONTWAIT); if (ret <= 0) @@ -2975,11 +2975,15 @@ skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) skb_zerocopy_clone(to, from, GFP_ATOMIC); for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { + int size; + if (!len) break; skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i]; - skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len); - len -= skb_shinfo(to)->frags[j].size; + size = min_t(int, skb_frag_size(&skb_shinfo(to)->frags[j]), + len); + skb_frag_size_set(&skb_shinfo(to)->frags[j], size); + len -= size; skb_frag_ref(to, j); j++; } @@ -3293,7 +3297,7 @@ static int skb_prepare_for_shift(struct sk_buff *skb) int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) { int from, to, merge, todo; - struct skb_frag_struct *fragfrom, *fragto; + skb_frag_t *fragfrom, *fragto; BUG_ON(shiftlen > skb->len); @@ -3625,10 +3629,10 @@ static inline skb_frag_t skb_head_frag_to_page_desc(struct sk_buff *frag_skb) struct page *page; page = virt_to_head_page(frag_skb->head); - head_frag.page.p = page; + __skb_frag_set_page(&head_frag, page); head_frag.page_offset = frag_skb->data - (unsigned char *)page_address(page); - head_frag.size = skb_headlen(frag_skb); + skb_frag_size_set(&head_frag, skb_headlen(frag_skb)); return head_frag; } @@ -4021,7 +4025,7 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb) pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags; - frag->page.p = page; + __skb_frag_set_page(frag, page); frag->page_offset = first_offset; skb_frag_size_set(frag, first_size); diff --git a/net/core/tso.c b/net/core/tso.c index 43f4eba61933..d4d5c077ad72 100644 --- a/net/core/tso.c +++ b/net/core/tso.c @@ -55,8 +55,8 @@ void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx]; /* Move to next segment */ - tso->size = frag->size; - tso->data = page_address(frag->page.p) + frag->page_offset; + tso->size = skb_frag_size(frag); + tso->data = skb_frag_address(frag); tso->next_frag_idx++; } } @@ -79,8 +79,8 @@ void tso_start(struct sk_buff *skb, struct tso_t *tso) skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx]; /* Move to next segment */ - tso->size = frag->size; - tso->data = page_address(frag->page.p) + frag->page_offset; + tso->size = skb_frag_size(frag); + tso->data = skb_frag_address(frag); tso->next_frag_idx++; } } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 776905899ac0..f62f0e7e3cdd 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1776,19 +1776,21 @@ static int tcp_zerocopy_receive(struct sock *sk, break; frags = skb_shinfo(skb)->frags; while (offset) { - if (frags->size > offset) + if (skb_frag_size(frags) > offset) goto out; - offset -= frags->size; + offset -= skb_frag_size(frags); frags++; } } - if (frags->size != PAGE_SIZE || frags->page_offset) { + if (skb_frag_size(frags) != PAGE_SIZE || frags->page_offset) { int remaining = zc->recv_skip_hint; + int size = skb_frag_size(frags); - while (remaining && (frags->size != PAGE_SIZE || + while (remaining && (size != PAGE_SIZE || frags->page_offset)) { - remaining -= frags->size; + remaining -= size; frags++; + size = skb_frag_size(frags); } zc->recv_skip_hint -= remaining; break; @@ -3781,7 +3783,7 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, return 1; for (i = 0; i < shi->nr_frags; ++i) { - const struct skb_frag_struct *f = &shi->frags[i]; + const skb_frag_t *f = &shi->frags[i]; unsigned int offset = f->page_offset; struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT); diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index 5dbc0c48f8cb..05f63c4300e9 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -635,15 +635,15 @@ static int kcm_write_msgs(struct kcm_sock *kcm) frag_offset = 0; do_frag: frag = &skb_shinfo(skb)->frags[fragidx]; - if (WARN_ON(!frag->size)) { + if (WARN_ON(!skb_frag_size(frag))) { ret = -EINVAL; goto out; } ret = kernel_sendpage(psock->sk->sk_socket, - frag->page.p, + skb_frag_page(frag), frag->page_offset + frag_offset, - frag->size - frag_offset, + skb_frag_size(frag) - frag_offset, MSG_DONTWAIT); if (ret <= 0) { if (ret == -EAGAIN) { @@ -678,7 +678,7 @@ static int kcm_write_msgs(struct kcm_sock *kcm) sent += ret; frag_offset += ret; KCM_STATS_ADD(psock->stats.tx_bytes, ret); - if (frag_offset < frag->size) { + if (frag_offset < skb_frag_size(frag)) { /* Not finished with this frag */ goto do_frag; } diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 7c0b2b778703..4ec8a06fa5d1 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -243,14 +243,14 @@ static void tls_append_frag(struct tls_record_info *record, skb_frag_t *frag; frag = &record->frags[record->num_frags - 1]; - if (frag->page.p == pfrag->page && - frag->page_offset + frag->size == pfrag->offset) { - frag->size += size; + if (skb_frag_page(frag) == pfrag->page && + frag->page_offset + skb_frag_size(frag) == pfrag->offset) { + skb_frag_size_add(frag, size); } else { ++frag; - frag->page.p = pfrag->page; + __skb_frag_set_page(frag, pfrag->page); frag->page_offset = pfrag->offset; - frag->size = size; + skb_frag_size_set(frag, size); ++record->num_frags; get_page(pfrag->page); } @@ -301,8 +301,8 @@ static int tls_push_record(struct sock *sk, frag = &record->frags[i]; sg_unmark_end(&offload_ctx->sg_tx_data[i]); sg_set_page(&offload_ctx->sg_tx_data[i], skb_frag_page(frag), - frag->size, frag->page_offset); - sk_mem_charge(sk, frag->size); + skb_frag_size(frag), frag->page_offset); + sk_mem_charge(sk, skb_frag_size(frag)); get_page(skb_frag_page(frag)); } sg_mark_end(&offload_ctx->sg_tx_data[record->num_frags - 1]); -- GitLab From b656722906efe434f0befe1d4ae4bb7a66fdc124 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:27 -0700 Subject: [PATCH 0241/7155] net: Increase the size of skb_frag_t To increase commonality between block and net, we are going to replace the skb_frag_t with the bio_vec. This patch increases the size of skb_frag_t on 32-bit machines from 8 bytes to 12 bytes. The size is unchanged on 64-bit machines. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f9078e7edb53..7910935410e6 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -314,13 +314,8 @@ struct skb_frag_struct { struct { struct page *p; } page; -#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) __u32 page_offset; __u32 size; -#else - __u16 page_offset; - __u16 size; -#endif }; /** -- GitLab From f58ecf1b7d58911921014ffd12c77a4ad33ade71 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:28 -0700 Subject: [PATCH 0242/7155] net: Reorder the contents of skb_frag_t Match the layout of bio_vec. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 7910935410e6..b9dc8b4f24b1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -314,8 +314,8 @@ struct skb_frag_struct { struct { struct page *p; } page; - __u32 page_offset; __u32 size; + __u32 page_offset; }; /** -- GitLab From 1dfa5bd38545c6f6a8b6c496e58db93f80da1076 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:29 -0700 Subject: [PATCH 0243/7155] net: Rename skb_frag page to bv_page One step closer to turning the skb_frag_t into a bio_vec. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 12 +++++------- net/core/skbuff.c | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b9dc8b4f24b1..8076e2ba8349 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -311,9 +311,7 @@ extern int sysctl_max_skb_frags; typedef struct skb_frag_struct skb_frag_t; struct skb_frag_struct { - struct { - struct page *p; - } page; + struct page *bv_page; __u32 size; __u32 page_offset; }; @@ -374,7 +372,7 @@ static inline bool skb_frag_must_loop(struct page *p) * skb_frag_foreach_page - loop over pages in a fragment * * @f: skb frag to operate on - * @f_off: offset from start of f->page.p + * @f_off: offset from start of f->bv_page * @f_len: length from f_off to loop over * @p: (temp var) current page * @p_off: (temp var) offset from start of current page, @@ -2084,7 +2082,7 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, * that not all callers have unique ownership of the page but rely * on page_is_pfmemalloc doing the right thing(tm). */ - frag->page.p = page; + frag->bv_page = page; frag->page_offset = off; skb_frag_size_set(frag, size); @@ -2872,7 +2870,7 @@ static inline void skb_propagate_pfmemalloc(struct page *page, */ static inline struct page *skb_frag_page(const skb_frag_t *frag) { - return frag->page.p; + return frag->bv_page; } /** @@ -2958,7 +2956,7 @@ static inline void *skb_frag_address_safe(const skb_frag_t *frag) */ static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page) { - frag->page.p = page; + frag->bv_page = page; } /** diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ba9a36903503..0b788df5a75b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3364,7 +3364,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) } else { __skb_frag_ref(fragfrom); - fragto->page = fragfrom->page; + fragto->bv_page = fragfrom->bv_page; fragto->page_offset = fragfrom->page_offset; skb_frag_size_set(fragto, todo); -- GitLab From b8b576a16f79efbdde49348147f491b176537d88 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:30 -0700 Subject: [PATCH 0244/7155] net: Rename skb_frag_t size to bv_len Improved compatibility with bvec Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 8076e2ba8349..e849e411d1f3 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -312,7 +312,7 @@ typedef struct skb_frag_struct skb_frag_t; struct skb_frag_struct { struct page *bv_page; - __u32 size; + unsigned int bv_len; __u32 page_offset; }; @@ -322,7 +322,7 @@ struct skb_frag_struct { */ static inline unsigned int skb_frag_size(const skb_frag_t *frag) { - return frag->size; + return frag->bv_len; } /** @@ -332,7 +332,7 @@ static inline unsigned int skb_frag_size(const skb_frag_t *frag) */ static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size) { - frag->size = size; + frag->bv_len = size; } /** @@ -342,7 +342,7 @@ static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size) */ static inline void skb_frag_size_add(skb_frag_t *frag, int delta) { - frag->size += delta; + frag->bv_len += delta; } /** @@ -352,7 +352,7 @@ static inline void skb_frag_size_add(skb_frag_t *frag, int delta) */ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta) { - frag->size -= delta; + frag->bv_len -= delta; } /** -- GitLab From 8842d285bafa9ff7719f4107b6545a11dcd41995 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Jul 2019 20:08:31 -0700 Subject: [PATCH 0245/7155] net: Convert skb_frag_t to bio_vec There are a lot of users of frag->page_offset, so use a union to avoid converting those users today. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- include/linux/bvec.h | 5 ++++- include/linux/skbuff.h | 9 ++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/linux/bvec.h b/include/linux/bvec.h index a032f01e928c..7f2b2ea9399c 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -18,7 +18,10 @@ struct bio_vec { struct page *bv_page; unsigned int bv_len; - unsigned int bv_offset; + union { + __u32 page_offset; + unsigned int bv_offset; + }; }; struct bvec_iter { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e849e411d1f3..718742b1c505 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -308,13 +309,7 @@ extern int sysctl_max_skb_frags; */ #define GSO_BY_FRAGS 0xFFFF -typedef struct skb_frag_struct skb_frag_t; - -struct skb_frag_struct { - struct page *bv_page; - unsigned int bv_len; - __u32 page_offset; -}; +typedef struct bio_vec skb_frag_t; /** * skb_frag_size - Returns the size of a skb fragment -- GitLab From 591c175076d71e58b9337385afe36a5ab0cf9e06 Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:18 +0200 Subject: [PATCH 0246/7155] ARM: dts: imx6ul: phyboard-segin: Rename dts to PHYTEC name scheme Use the same name scheme for the phyBOARD-Segin and the phyCORE-i.MX 6UL as is used for the PHYTEC phyBOARD-Mira and phyCORE-i.MX 6. This is only a cosmetic change and there is no functional change intended. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 2 +- ...-phytec-pcl063.dtsi => imx6ul-phytec-phycore-som.dtsi} | 2 +- ...oard-segin-full.dts => imx6ul-phytec-segin-ff-rdk.dts} | 8 ++++---- ...-eval-01.dtsi => imx6ul-phytec-segin-peb-eval-01.dtsi} | 0 ...hytec-phyboard-segin.dtsi => imx6ul-phytec-segin.dtsi} | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename arch/arm/boot/dts/{imx6ul-phytec-pcl063.dtsi => imx6ul-phytec-phycore-som.dtsi} (98%) rename arch/arm/boot/dts/{imx6ul-phytec-phyboard-segin-full.dts => imx6ul-phytec-segin-ff-rdk.dts} (84%) rename arch/arm/boot/dts/{imx6ul-phytec-peb-eval-01.dtsi => imx6ul-phytec-segin-peb-eval-01.dtsi} (100%) rename arch/arm/boot/dts/{imx6ul-phytec-phyboard-segin.dtsi => imx6ul-phytec-segin.dtsi} (99%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 4653ddc9d5fb..7dd2d78c2fc4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -573,7 +573,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-opos6uldev.dtb \ imx6ul-pico-hobbit.dtb \ imx6ul-pico-pi.dtb \ - imx6ul-phytec-phyboard-segin-full.dtb \ + imx6ul-phytec-segin-ff-rdk.dtb \ imx6ul-tx6ul-0010.dtb \ imx6ul-tx6ul-0011.dtb \ imx6ul-tx6ul-mainboard.dtb \ diff --git a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi similarity index 98% rename from arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi rename to arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index fc2997449b49..bff13d0eb064 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -10,7 +10,7 @@ #include "imx6ul.dtsi" / { - model = "Phytec phyCORE i.MX6 UltraLite"; + model = "PHYTEC phyCORE-i.MX6 UltraLite"; compatible = "phytec,imx6ul-pcl063", "fsl,imx6ul"; chosen { diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts similarity index 84% rename from arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts rename to arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts index b6a1407a9d44..1e59183a2f7c 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts @@ -5,12 +5,12 @@ */ /dts-v1/; -#include "imx6ul-phytec-pcl063.dtsi" -#include "imx6ul-phytec-phyboard-segin.dtsi" -#include "imx6ul-phytec-peb-eval-01.dtsi" +#include "imx6ul-phytec-phycore-som.dtsi" +#include "imx6ul-phytec-segin.dtsi" +#include "imx6ul-phytec-segin-peb-eval-01.dtsi" / { - model = "Phytec phyBOARD-Segin i.MX6 UltraLite Full Featured"; + model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite Full Featured"; compatible = "phytec,imx6ul-pbacd10", "phytec,imx6ul-pcl063", "fsl,imx6ul"; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi rename to arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi rename to arch/arm/boot/dts/imx6ul-phytec-segin.dtsi index 7bf439a77d2c..78425c3290a1 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi @@ -5,7 +5,7 @@ */ / { - model = "Phytec phyBOARD-Segin i.MX6 UltraLite"; + model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite"; compatible = "phytec,imx6ul-pbacd-10", "phytec,imx6ul-pcl063", "fsl,imx6ul"; aliases { -- GitLab From e37816bf9114ee1604a1511f7b4155b753ab36b9 Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:19 +0200 Subject: [PATCH 0247/7155] ARM: dts: imx6ul: segin: Add boot media to dts filename There is now a PHYTEC phyCORE-i.MX 6UL with eMMC instead of NAND flash available. The dts filename needs to reflect that to differentiate both. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 2 +- ...-segin-ff-rdk.dts => imx6ul-phytec-segin-ff-rdk-nand.dts} | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename arch/arm/boot/dts/{imx6ul-phytec-segin-ff-rdk.dts => imx6ul-phytec-segin-ff-rdk-nand.dts} (85%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7dd2d78c2fc4..2d6b2bf782e2 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -573,7 +573,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-opos6uldev.dtb \ imx6ul-pico-hobbit.dtb \ imx6ul-pico-pi.dtb \ - imx6ul-phytec-segin-ff-rdk.dtb \ + imx6ul-phytec-segin-ff-rdk-nand.dtb \ imx6ul-tx6ul-0010.dtb \ imx6ul-tx6ul-0011.dtb \ imx6ul-tx6ul-mainboard.dtb \ diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts similarity index 85% rename from arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts rename to arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts index 1e59183a2f7c..dc06029c5701 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts @@ -10,8 +10,9 @@ #include "imx6ul-phytec-segin-peb-eval-01.dtsi" / { - model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite Full Featured"; - compatible = "phytec,imx6ul-pbacd10", "phytec,imx6ul-pcl063", "fsl,imx6ul"; + model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite Full Featured with NAND"; + compatible = "phytec,imx6ul-pbacd10-nand", "phytec,imx6ul-pbacd10", + "phytec,imx6ul-pcl063", "fsl,imx6ul"; }; &adc1 { -- GitLab From 458264157b1044d242afa163ac407dc55fa8134e Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:20 +0200 Subject: [PATCH 0248/7155] ARM: dts: imx6ul: segin: Reduce eth drive strength Reduce the drive strength for the MDC, MDIO and TX pins of FEC1 and FEC2 on the phyBOARD-Segin to improve signal quality and EMC. Also disable internal pull-ups on the MDC and MDIO pins. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 12 ++++++------ arch/arm/boot/dts/imx6ul-phytec-segin.dtsi | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index bff13d0eb064..1b745582911c 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -93,16 +93,16 @@ &iomuxc { pinctrl_enet1: enet1grp { fsl,pins = < - MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0 - MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x10010 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x10010 MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 - MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 - MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 - MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 - MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b010 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b010 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b010 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b010 MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x17059 >; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi index 78425c3290a1..28ba3a4c4c74 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi @@ -230,10 +230,10 @@ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 - MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 - MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 - MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 - MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b010 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b010 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b010 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b010 >; }; -- GitLab From 783c10aa740f70e22833baf33b7a87f6f7d94696 Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:21 +0200 Subject: [PATCH 0249/7155] ARM: dts: imx6ul: segin: Fix LED naming for phyCORE and PEB-EVAL-01 Fix node name for the user LEDs to prevent the pinctrl of the phyCORE's leds node from being overwritten. Also use more generic names for user LEDs. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 3 +-- .../dts/imx6ul-phytec-segin-peb-eval-01.dtsi | 16 +++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index 1b745582911c..73266b4a889b 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -31,8 +31,7 @@ pinctrl-0 = <&pinctrl_gpioleds_som>; compatible = "gpio-leds"; - led_green { - label = "phycore:green"; + phycore-green { gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi index e2f38f39a6ad..2f3fd32a1167 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi @@ -21,20 +21,22 @@ }; }; - user_leds: leds { + user_leds: user-leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_user_leds>; status = "disabled"; - led_yellow { - gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "default-on"; + user-led1 { + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "gpio"; + default-state = "on"; }; - led_red { - gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "default-on"; + user-led2 { + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "gpio"; + default-state = "on"; }; }; }; -- GitLab From f1da57d8ea3a9eeb0986fea22389402505d132e7 Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:22 +0200 Subject: [PATCH 0250/7155] ARM: dts: imx6ul: segin: Make FEC and ethphy configurable in dts To disable Ethernet interfaces in case they are not populated make the FEC and Ethernet PHY status configurable in the dts files. Also change the Ethernet PHYs labels to make them correspond to the MDIO address. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 7 ++++--- .../arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts | 12 ++++++++++++ arch/arm/boot/dts/imx6ul-phytec-segin.dtsi | 5 +++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index 73266b4a889b..fee7a7e938ee 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -42,20 +42,21 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet1>; phy-mode = "rmii"; - phy-handle = <ðphy0>; - status = "okay"; + phy-handle = <ðphy1>; + status = "disabled"; mdio: mdio { #address-cells = <1>; #size-cells = <0>; - ethphy0: ethernet-phy@1 { + ethphy1: ethernet-phy@1 { reg = <1>; interrupt-parent = <&gpio1>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; clocks = <&clks IMX6UL_CLK_ENET_REF>; clock-names = "rmii-ref"; + status = "disabled"; }; }; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts index dc06029c5701..81a82dd65019 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts @@ -34,6 +34,18 @@ status = "okay"; }; +ðphy1 { + status = "okay"; +}; + +ðphy2 { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + &fec2 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi index 28ba3a4c4c74..7cd24ec40c36 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi @@ -107,7 +107,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet2>; phy-mode = "rmii"; - phy-handle = <ðphy1>; + phy-handle = <ðphy2>; status = "disabled"; }; @@ -160,11 +160,12 @@ }; &mdio { - ethphy1: ethernet-phy@2 { + ethphy2: ethernet-phy@2 { reg = <2>; micrel,led-mode = <1>; clocks = <&clks IMX6UL_CLK_ENET2_REF>; clock-names = "rmii-ref"; + status = "disabled"; }; }; -- GitLab From 87dc2cd47989892b2374b43eda0a5f28c679ff2b Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:23 +0200 Subject: [PATCH 0251/7155] ARM: dts: imx6ul: segin: Only enable NAND if it is populated The phyCORE-i.MX 6UL/ULL now comes either with NAND flash or eMMC. We have to configure the populated memory type in the device tree files. So the GPMI node gets disabled by default and only enabled if populated. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 2 +- arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index fee7a7e938ee..de6ffbb0183c 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -65,7 +65,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpmi_nand>; nand-on-flash-bbt; - status = "okay"; + status = "disabled"; }; &i2c1 { diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts index 81a82dd65019..c6ef13685a7c 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts @@ -50,6 +50,10 @@ status = "okay"; }; +&gpmi { + status = "okay"; +}; + &i2c_rtc { status = "okay"; }; -- GitLab From b349580a4caef6f1fc23c0bd5393d3557ccf467a Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:24 +0200 Subject: [PATCH 0252/7155] ARM: dts: imx6ul: phycore: Add eMMC at usdhc2 The phyCORE-i.MX 6UL/ULL now can have eMMC instead of the NAND flash memory. Add the eMMC node and disable it by default so it can be enabled in case it is populated. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- .../boot/dts/imx6ul-phytec-phycore-som.dtsi | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index de6ffbb0183c..09a313daedb8 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -90,6 +90,15 @@ status = "okay"; }; +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <8>; + no-1-8-v; + non-removable; + status = "disabled"; +}; + &iomuxc { pinctrl_enet1: enet1grp { fsl,pins = < @@ -145,4 +154,19 @@ >; }; + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9 + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9 + MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9 + MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9 + MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9 + MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9 + >; + }; + }; -- GitLab From f638e7fdbfdfd4411a917beff761720f97feff7f Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:25 +0200 Subject: [PATCH 0253/7155] ARM: dts: imx6ul: segin: Move ECSPI interface to board include file The ECSPI interface is available on the expansion connector of every PHYTEC phyBOARD-Segin. Move its definition to the board include file for better reuse. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- .../boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts | 14 -------------- arch/arm/boot/dts/imx6ul-phytec-segin.dtsi | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts index c6ef13685a7c..32d90c67a6f2 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts @@ -28,9 +28,6 @@ }; &ecspi3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ecspi3>; - cs-gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -93,14 +90,3 @@ &usdhc1 { status = "okay"; }; - -&iomuxc { - pinctrl_ecspi3: ecspi3grp { - fsl,pins = < - MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO 0x10b0 - MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0 - MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0 - MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x10b0 - >; - }; -}; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi index 7cd24ec40c36..8d5f8dc6ad58 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi @@ -103,6 +103,13 @@ assigned-clock-rates = <786432000>; }; +&ecspi3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + cs-gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + &fec2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet2>; @@ -225,6 +232,15 @@ >; }; + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO 0x10b0 + MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0 + MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0 + MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x10b0 + >; + }; + pinctrl_enet2: enet2grp { fsl,pins = < MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 -- GitLab From 9ae6390aa1079293a05e11b12a97ef6742993127 Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:26 +0200 Subject: [PATCH 0254/7155] ARM: dts: imx6ul: segin: Move machine include to dts files Move the imx6ul.dtsi include to the dts files so it is easier to reuse the SOM dtsi for e.g. an i.MX 6ULL SOM. Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 1 - arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index 09a313daedb8..92bf91674056 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -7,7 +7,6 @@ #include #include #include -#include "imx6ul.dtsi" / { model = "PHYTEC phyCORE-i.MX6 UltraLite"; diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts index 32d90c67a6f2..699dfcbf9a60 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts +++ b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts @@ -5,6 +5,7 @@ */ /dts-v1/; +#include "imx6ul.dtsi" #include "imx6ul-phytec-phycore-som.dtsi" #include "imx6ul-phytec-segin.dtsi" #include "imx6ul-phytec-segin-peb-eval-01.dtsi" -- GitLab From f4411786b39beafd7c52e2d7b3f2d5052901035a Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Tue, 9 Jul 2019 09:19:27 +0200 Subject: [PATCH 0255/7155] ARM: dts: imx6ull: Add support for PHYTEC phyBOARD-Segin with i.MX 6ULL In addition to the PHYTEC phyCORE-i.MX 6UL the PHYTEC phyBOARD-Segin is also available with the PHYTEC phyCORE-i.MX 6ULL. So this adds support for this SOM and its baseboards. It comes in a full featured option with either NAND flash or eMMC and in a low cost option only available with NAND flash. The hardware specs are: - Full featured with NAND or eMMC: * i.MX 6ULL Y2 * 512MB DDR3 memory * 512MB NAND flash or 4GB/8GB eMMC * Dual 10/100 Ethernet * USB Host and USB OTG * RS232 * MicroSD external storage * Audio, RS232, I2C, SPI, CAN headers * Further I/O options via A/V and Expansion headers - Low cost with NAND: * i.MX 6ULL Y0 * 256MB DDR3 memory * 128MB NAND flash * Single 10/100 Ethernet * USB OTG * RS232 * MicroSD external storage * I2C * Further I/O options via Expansion headers Signed-off-by: Stefan Riedmueller Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 3 + .../boot/dts/imx6ull-phytec-phycore-som.dtsi | 24 +++++ .../dts/imx6ull-phytec-segin-ff-rdk-emmc.dts | 93 +++++++++++++++++++ .../dts/imx6ull-phytec-segin-ff-rdk-nand.dts | 93 +++++++++++++++++++ .../dts/imx6ull-phytec-segin-lc-rdk-nand.dts | 45 +++++++++ .../dts/imx6ull-phytec-segin-peb-eval-01.dtsi | 19 ++++ arch/arm/boot/dts/imx6ull-phytec-segin.dtsi | 38 ++++++++ 7 files changed, 315 insertions(+) create mode 100644 arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi create mode 100644 arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts create mode 100644 arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts create mode 100644 arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts create mode 100644 arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi create mode 100644 arch/arm/boot/dts/imx6ull-phytec-segin.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 2d6b2bf782e2..7fe6667f466c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -580,6 +580,9 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ull-14x14-evk.dtb \ imx6ull-colibri-eval-v3.dtb \ imx6ull-colibri-wifi-eval-v3.dtb \ + imx6ull-phytec-segin-ff-rdk-nand.dtb \ + imx6ull-phytec-segin-ff-rdk-emmc.dtb \ + imx6ull-phytec-segin-lc-rdk-nand.dtb \ imx6ulz-14x14-evk.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ diff --git a/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi new file mode 100644 index 000000000000..56cd16e5a77f --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +#include "imx6ul-phytec-phycore-som.dtsi" + +/ { + model = "PHYTEC phyCORE-i.MX6 ULL"; + compatible = "phytec,imx6ull-pcl063", "fsl,imx6ull"; +}; + +&iomuxc { + /delete-node/ gpioledssomgrp; +}; + +&iomuxc_snvs { + pinctrl_gpioleds_som: gpioledssomgrp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x0b0b0 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts new file mode 100644 index 000000000000..9648d4ecaf58 --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +/dts-v1/; +#include "imx6ull.dtsi" +#include "imx6ull-phytec-phycore-som.dtsi" +#include "imx6ull-phytec-segin.dtsi" +#include "imx6ull-phytec-segin-peb-eval-01.dtsi" + +/ { + model = "PHYTEC phyBOARD-Segin i.MX6 ULL Full Featured with eMMC"; + compatible = "phytec,imx6ull-pbacd10-emmc", "phytec,imx6ull-pbacd10", + "phytec,imx6ull-pcl063","fsl,imx6ull"; +}; + +&adc1 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&tlv320 { + status = "okay"; +}; + +&ecspi3 { + status = "okay"; +}; + +ðphy1 { + status = "okay"; +}; + +ðphy2 { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +&fec2 { + status = "okay"; +}; + +&i2c_rtc { + status = "okay"; +}; + +®_can1_en { + status = "okay"; +}; + +®_sound_1v8 { + status = "okay"; +}; + +®_sound_3v3 { + status = "okay"; +}; + +&sai2 { + status = "okay"; +}; + +&sound { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usbotg2 { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +&usdhc2 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts new file mode 100644 index 000000000000..656baf846453 --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +/dts-v1/; +#include "imx6ull.dtsi" +#include "imx6ull-phytec-phycore-som.dtsi" +#include "imx6ull-phytec-segin.dtsi" +#include "imx6ull-phytec-segin-peb-eval-01.dtsi" + +/ { + model = "PHYTEC phyBOARD-Segin i.MX6 ULL Full Featured with NAND"; + compatible = "phytec,imx6ull-pbacd10-nand", "phytec,imx6ull-pbacd10", + "phytec,imx6ull-pcl063", "fsl,imx6ull"; +}; + +&adc1 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&tlv320 { + status = "okay"; +}; + +&ecspi3 { + status = "okay"; +}; + +ðphy1 { + status = "okay"; +}; + +ðphy2 { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +&fec2 { + status = "okay"; +}; + +&gpmi { + status = "okay"; +}; + +&i2c_rtc { + status = "okay"; +}; + +®_can1_en { + status = "okay"; +}; + +®_sound_1v8 { + status = "okay"; +}; + +®_sound_3v3 { + status = "okay"; +}; + +&sai2 { + status = "okay"; +}; + +&sound { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usbotg2 { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts b/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts new file mode 100644 index 000000000000..e168494e0a6d --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +/dts-v1/; +#include "imx6ull.dtsi" +#include "imx6ull-phytec-phycore-som.dtsi" +#include "imx6ull-phytec-segin.dtsi" +#include "imx6ull-phytec-segin-peb-eval-01.dtsi" + +/ { + model = "PHYTEC phyBOARD-Segin i.MX6 ULL Low Cost with NAND"; + compatible = "phytec,imx6ull-pbacd10-nand", "phytec,imx6ull-pbacd10", + "phytec,imx6ull-pcl063", "fsl,imx6ull"; +}; + +&adc1 { + status = "okay"; +}; + +ðphy1 { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +&gpmi { + status = "okay"; +}; + +&i2c_rtc { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi new file mode 100644 index 000000000000..ff08d95a1aa2 --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +#include "imx6ul-phytec-segin-peb-eval-01.dtsi" + +&iomuxc { + /delete-node/ gpio_keysgrp; +}; + +&iomuxc_snvs { + pinctrl_gpio_keys: gpio_keysgrp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x79 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi new file mode 100644 index 000000000000..c1595fc785f7 --- /dev/null +++ b/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller + */ + +#include "imx6ul-phytec-segin.dtsi" + +/ { + model = "PHYTEC phyBOARD-Segin i.MX6 ULL"; + compatible = "phytec,imx6ull-pbacd-10", "phytec,imx6ull-pcl063","fsl,imx6ull"; +}; + +&iomuxc { + /delete-node/ flexcan1engrp; + /delete-node/ rtcintgrp; + /delete-node/ stmpegrp; +}; + +&iomuxc_snvs { + princtrl_flexcan1_en: flexcan1engrp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x17059 + >; + }; + + pinctrl_rtc_int: rtcintgrp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x17059 + >; + }; + + pinctrl_stmpe: stmpegrp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x17059 + >; + }; +}; -- GitLab From 7a8689df21f425e77207b4245b0b89d3185866e7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 15 Jul 2019 10:06:35 +0200 Subject: [PATCH 0256/7155] ARM: ux500: Stop populating the PRCMU devices early The PRCMU devices are getting populated from the MFD driver and that is enough for them to come up. We already have an early quirk for the things that need to happen really early and the PRCMU timer that need to be registered really early will find its own node just fine as the timer/clocksource subsystem looks through the whole device tree for compatible nodes. Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/cpu-db8500.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 9580525102da..3875027ef8fc 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -110,7 +110,6 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd) static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, - { .compatible = "stericsson,db8500-prcmu", }, { .compatible = "simple-bus"}, { }, }; -- GitLab From 46269abf9720f1670b27158e4023b8e7f150cb84 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 8 May 2019 10:18:55 +0800 Subject: [PATCH 0257/7155] ARM: dts: ste: Update coresight DT bindings CoreSight DT bindings have been updated, thus the old compatible strings are obsolete and the drivers will report warning if DTS uses these obsolete strings. This patch switches to the new bindings for CoreSight dynamic funnel and static replicator, so can dismiss warning during initialisation. Cc: Linus Walleij Cc: Lee Jones Cc: Mathieu Poirier Cc: Suzuki K Poulose Signed-off-by: Leo Yan Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index b1a31134f860..339da70d4e83 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -92,7 +92,7 @@ }; funnel@801a6000 { - compatible = "arm,coresight-funnel", "arm,primecell"; + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; reg = <0x801a6000 0x1000>; clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; @@ -127,7 +127,7 @@ }; replicator { - compatible = "arm,coresight-replicator"; + compatible = "arm,coresight-static-replicator"; clocks = <&prcmu_clk PRCMU_APEATCLK>; clock-names = "atclk"; -- GitLab From aef41a4d88ef11a04b29d9f2ffdfd46eb317d7d8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 15 Jul 2019 10:05:02 +0200 Subject: [PATCH 0258/7155] ARM: dts: ux500: Fix up the thermal nodes The thermal driver for the DB8500 was never properly converted to device tree, the node should definitely be activated for all board variants so move this down into the main SoC DTSI, and default on. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 22 +++++++++++++++++++++- arch/arm/boot/dts/ste-snowball.dts | 29 ----------------------------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 339da70d4e83..90dcbc3a29c3 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -505,10 +505,30 @@ thermal@801573c0 { compatible = "stericsson,db8500-thermal"; reg = <0x801573c0 0x40>; + interrupt-parent = <&prcmu>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH>, <22 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "IRQ_HOTMON_LOW", "IRQ_HOTMON_HIGH"; - status = "disabled"; + num-trips = <4>; + + trip0-temp = <70000>; + trip0-type = "active"; + trip0-cdev-num = <1>; + trip0-cdev-name0 = "thermal-cpufreq-0"; + + trip1-temp = <75000>; + trip1-type = "active"; + trip1-cdev-num = <1>; + trip1-cdev-name0 = "thermal-cpufreq-0"; + + trip2-temp = <80000>; + trip2-type = "active"; + trip2-cdev-num = <1>; + trip2-cdev-name0 = "thermal-cpufreq-0"; + + trip3-temp = <85000>; + trip3-type = "critical"; + trip3-cdev-num = <0>; }; db8500-prcmu-regulators { diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index 3428290644ba..064e8abec954 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -376,40 +376,11 @@ pinctrl-0 = <&ssp0_snowball_mode>; }; - cpufreq-cooling { - status = "okay"; - }; - prcmu@80157000 { cpufreq { status = "okay"; }; - thermal@801573c0 { - num-trips = <4>; - - trip0-temp = <70000>; - trip0-type = "active"; - trip0-cdev-num = <1>; - trip0-cdev-name0 = "thermal-cpufreq-0"; - - trip1-temp = <75000>; - trip1-type = "active"; - trip1-cdev-num = <1>; - trip1-cdev-name0 = "thermal-cpufreq-0"; - - trip2-temp = <80000>; - trip2-type = "active"; - trip2-cdev-num = <1>; - trip2-cdev-name0 = "thermal-cpufreq-0"; - - trip3-temp = <85000>; - trip3-type = "critical"; - trip3-cdev-num = <0>; - - status = "okay"; - }; - ab8500 { ab8500-gpio { /* -- GitLab From 07523a6cb6f868dfb3202a7fd5c7db2a43194f24 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 25 Aug 2014 14:46:10 +0200 Subject: [PATCH 0259/7155] ARM: dts: ux500: set pull-up on STUIB STMPE IRQ line Set up the STMPE IRQ line to be in pull-up mode. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-href-stuib.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/ste-href-stuib.dtsi b/arch/arm/boot/dts/ste-href-stuib.dtsi index b17998f4f7ca..e32d0c36feb8 100644 --- a/arch/arm/boot/dts/ste-href-stuib.dtsi +++ b/arch/arm/boot/dts/ste-href-stuib.dtsi @@ -38,6 +38,8 @@ interrupt-controller; vcc-supply = <&db8500_vsmps2_reg>; vio-supply = <&db8500_vsmps2_reg>; + pinctrl-names = "default"; + pinctrl-0 = <&stmpe_stuib_mode>; wakeup-source; st,autosleep-timeout = <1024>; @@ -126,6 +128,15 @@ }; pinctrl { + /* Pull up this GPIO pin */ + stmpe { + stmpe_stuib_mode: stmpe_stuib { + stuib_cfg { + ste,pins = "GPIO218_AH11"; + ste,config = <&gpio_in_pu>; + }; + }; + }; prox { prox_stuib_mode: prox_stuib { stuib_cfg { -- GitLab From 6d234bc6a4b4dc818b7f9a77131a4994cc4d74b5 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 17 Jul 2019 08:02:51 -0700 Subject: [PATCH 0260/7155] ARM: dts: vf610-zii-spb4: Drop unused pinctrl_i2c1 pinmux config Pinctrl_i2c1 pinmux config is not used anywhere. Drop it. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Cory Tusar Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-spb4.dts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm/boot/dts/vf610-zii-spb4.dts b/arch/arm/boot/dts/vf610-zii-spb4.dts index 9dde83ccb9d1..77e1484211e4 100644 --- a/arch/arm/boot/dts/vf610-zii-spb4.dts +++ b/arch/arm/boot/dts/vf610-zii-spb4.dts @@ -316,13 +316,6 @@ >; }; - pinctrl_i2c1: i2c1grp { - fsl,pins = < - VF610_PAD_PTB16__I2C1_SCL 0x37ff - VF610_PAD_PTB17__I2C1_SDA 0x37ff - >; - }; - pinctrl_leds_debug: pinctrl-leds-debug { fsl,pins = < VF610_PAD_PTD3__GPIO_82 0x31c2 -- GitLab From aee2a02bcf55160f9ae891b703b0c3f81298c7b2 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 17 Jul 2019 08:02:52 -0700 Subject: [PATCH 0261/7155] ARM: dts: vf610-zii-scu4-aib: Fix pinctrl_i2c1's identation Fix pinctrl_i2c1's inconsistent identation. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Cory Tusar Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-scu4-aib.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts index d7019e89f588..a64de809299f 100644 --- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts +++ b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts @@ -777,7 +777,8 @@ VF610_PAD_PTB15__I2C0_SDA 0x37ff >; }; - pinctrl_i2c1: i2c1grp { + + pinctrl_i2c1: i2c1grp { fsl,pins = < VF610_PAD_PTB16__I2C1_SCL 0x37ff VF610_PAD_PTB17__I2C1_SDA 0x37ff -- GitLab From 9461e35f84184662e395ee4c0222687a8f121586 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 17 Jul 2019 08:02:53 -0700 Subject: [PATCH 0262/7155] ARM: dts: vf610-zii-scu4-aib: Drop unused pinctrl_i2c3 pinmux config Pinctrl_i2c3 pinmux config is not used anywhere. Drop it. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Cory Tusar Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-scu4-aib.dts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts index a64de809299f..666ec27a73e3 100644 --- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts +++ b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts @@ -792,13 +792,6 @@ >; }; - pinctrl_i2c3: i2c3grp { - fsl,pins = < - VF610_PAD_PTA30__I2C3_SCL 0x37ff - VF610_PAD_PTA31__I2C3_SDA 0x37ff - >; - }; - pinctrl_leds_debug: pinctrl-leds-debug { fsl,pins = < VF610_PAD_PTB26__GPIO_96 0x31c2 -- GitLab From 3a79bc63d90750f737ab9d7219bd3091d2fd6d84 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 13:03:20 +0200 Subject: [PATCH 0263/7155] PCI: irq: Introduce rearm_wake_irq() Introduce a new function, rearm_wake_irq(), allowing a wakeup IRQ to be armed for systen wakeup detection again without running any action handlers associated with it after it has been armed for wakeup detection and triggered. That is useful for IRQs, like ACPI SCI, that may deliver wakeup as well as non-wakeup interrupts when armed for systen wakeup detection. In those cases, it may be possible to determine whether or not the delivered interrupt is a systen wakeup one without running the entire action handler (or handlers, if the IRQ is shared) for the IRQ, and if the interrupt turns out to be a non-wakeup one, the IRQ can be rearmed with the help of the new function. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- include/linux/interrupt.h | 1 + kernel/irq/pm.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5b8328a99b2a..0e9cdb3efda7 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -238,6 +238,7 @@ extern void teardown_percpu_nmi(unsigned int irq); /* The following three functions are for the core kernel use only. */ extern void suspend_device_irqs(void); extern void resume_device_irqs(void); +extern void rearm_wake_irq(unsigned int irq); /** * struct irq_affinity_notify - context for notification of IRQ affinity changes diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index d6961d3c6f9e..8f557fa1f4fe 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -176,6 +176,26 @@ static void resume_irqs(bool want_early) } } +/** + * rearm_wake_irq - rearm a wakeup interrupt line after signaling wakeup + * @irq: Interrupt to rearm + */ +void rearm_wake_irq(unsigned int irq) +{ + unsigned long flags; + struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + + if (!desc || !(desc->istate & IRQS_SUSPENDED) || + !irqd_is_wakeup_set(&desc->irq_data)) + return; + + desc->istate &= ~IRQS_SUSPENDED; + irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED); + __enable_irq(desc); + + irq_put_desc_busunlock(desc, flags); +} + /** * irq_pm_syscore_ops - enable interrupt lines early * -- GitLab From 6921de898ba8f2ec91cfea70e7160b89c477382e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 13:03:28 +0200 Subject: [PATCH 0264/7155] ACPICA: Return u32 from acpi_dispatch_gpe() In some cases it is useful to know whether or not the acpi_ev_detect_gpe() called by acpi_dispatch_gpe() has found the GPE to be active, so return the return value of it (whose data type is u32) from latter. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/acpi/acpica/evxfgpe.c | 6 +++--- include/acpi/acpixf.h | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 710488ec59e9..04a40d563dd6 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -644,17 +644,17 @@ ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block * - * RETURN: None + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. * ******************************************************************************/ -void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) +u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) { ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); - acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); + return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); } ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 3845c8fcc94e..4ed603a3b448 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -297,6 +297,9 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running); #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ ACPI_EXTERNAL_RETURN_OK(prototype) +#define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \ + ACPI_EXTERNAL_RETURN_UINT32(prototype) + #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ ACPI_EXTERNAL_RETURN_VOID(prototype) @@ -307,6 +310,9 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running); #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ static ACPI_INLINE prototype {return(AE_OK);} +#define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \ + static ACPI_INLINE prototype {return(0);} + #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ static ACPI_INLINE prototype {return;} @@ -738,7 +744,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status u32 gpe_number, acpi_event_status *event_status)) -ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) +ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) -- GitLab From 9089f16e053afc5e18feaeb9f64cc7c90d6bd687 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 13:03:39 +0200 Subject: [PATCH 0265/7155] ACPI: EC: Return bool from acpi_ec_dispatch_gpe() On some systems, if suspend-to-idle is used, the EC may signal system wakeup events (power button events, for example) as well as events that should not cause the system to resume and acpi_ec_dispatch_gpe() needs to be called to determine whether or not the system should resume then. In particular, if acpi_ec_dispatch_gpe() doesn't detect any EC events at all, the system should remain suspended, so it is useful to know when that is the case. For this reason, make acpi_ec_dispatch_gpe() return a bool value indicating whether or not any EC events have been detected by it. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/acpi/ec.c | 11 ++++++++--- drivers/acpi/internal.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index c33756ed3304..58c7ad402d8d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1060,10 +1060,15 @@ void acpi_ec_set_gpe_wake_mask(u8 action) acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); } -void acpi_ec_dispatch_gpe(void) +bool acpi_ec_dispatch_gpe(void) { - if (first_ec) - acpi_dispatch_gpe(NULL, first_ec->gpe); + u32 ret; + + if (!first_ec) + return false; + + ret = acpi_dispatch_gpe(NULL, first_ec->gpe); + return ret == ACPI_INTERRUPT_HANDLED; } /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index f4c2fe6be4f2..1b5f9ac06ea8 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -196,7 +196,7 @@ void acpi_ec_block_transactions(void); void acpi_ec_unblock_transactions(void); void acpi_ec_mark_gpe_for_wake(void); void acpi_ec_set_gpe_wake_mask(u8 action); -void acpi_ec_dispatch_gpe(void); +bool acpi_ec_dispatch_gpe(void); int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, void *data); -- GitLab From 2933954b71f10d392764f95eec0f0aa2d103054b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 13:03:48 +0200 Subject: [PATCH 0266/7155] PM: sleep: Fix possible overflow in pm_system_cancel_wakeup() It is not actually guaranteed that pm_abort_suspend will be nonzero when pm_system_cancel_wakeup() is called which may lead to subtle issues, so make it use atomic_dec_if_positive() instead of atomic_dec() for the safety sake. Fixes: 33e4f80ee69b ("ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle") Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/base/power/wakeup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index ee31d4f8d856..b30c45aad10f 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -859,7 +859,7 @@ EXPORT_SYMBOL_GPL(pm_system_wakeup); void pm_system_cancel_wakeup(void) { - atomic_dec(&pm_abort_suspend); + atomic_dec_if_positive(&pm_abort_suspend); } void pm_wakeup_clear(bool reset) -- GitLab From 41275eb5c7181febdfaa63c3a0ad9b7acdadcd52 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 23:51:19 +0200 Subject: [PATCH 0267/7155] ACPI: PM: Set s2idle_wakeup earlier and clear it later The role of the s2idle_wakeup variable is to cause acpi_pm_wakeup_event() and acpi_pm_notify_handler() to increment pm_abort_suspend and trigger a wakeup from suspend-to-idle in case the ACPI SCI wakeup was canceled by acpi_s2idle_wake(). However, for this purpose it need not be set in acpi_s2idle_wake() and cleared in acpi_s2idle_sync(), respectively. In fact, it may be set as early as in acpi_s2idle_prepare() and cleared as late as in acpi_s2idle_restore(), so do that to allow subsequent changes to be simpler. This change is not expected to alter functionality. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/acpi/sleep.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index f0fe7c15d657..3debe1a42655 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -972,6 +972,8 @@ static int acpi_s2idle_prepare(void) /* Change the configuration of GPEs to avoid spurious wakeup. */ acpi_enable_all_wakeup_gpes(); acpi_os_wait_events_complete(); + + s2idle_wakeup = true; return 0; } @@ -991,7 +993,6 @@ static void acpi_s2idle_wake(void) if (acpi_sci_irq_valid() && !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { pm_system_cancel_wakeup(); - s2idle_wakeup = true; /* * On some platforms with the LPS0 _DSM device noirq resume * takes too much time for EC wakeup events to survive, so look @@ -1012,11 +1013,12 @@ static void acpi_s2idle_sync(void) acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */ acpi_ec_flush_work(); acpi_os_wait_events_complete(); /* synchronize Notify handling */ - s2idle_wakeup = false; } static void acpi_s2idle_restore(void) { + s2idle_wakeup = false; + acpi_enable_all_runtime_gpes(); acpi_disable_wakeup_devices(ACPI_STATE_S0); -- GitLab From 56b991849009f5def0443bfb2f48c8321d888e15 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 23:52:03 +0200 Subject: [PATCH 0268/7155] PM: sleep: Simplify suspend-to-idle control flow After commit 33e4f80ee69b ("ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle") the "noirq" phases of device suspend and resume may run for multiple times during suspend-to-idle, if there are spurious system wakeup events while suspended. However, this is complicated and fragile and actually unnecessary. The main reason for doing this is that on some systems the EC may signal system wakeup events (power button events, for example) as well as events that should not cause the system to resume (spurious system wakeup events). Thus, in order to determine whether or not a given event signaled by the EC while suspended is a proper system wakeup one, the EC GPE needs to be dispatched and to start with that was achieved by allowing the ACPI SCI action handler to run, which was only possible after calling resume_device_irqs(). However, dispatching the EC GPE this way turned out to take too much time in some cases and some EC events might be missed due to that, so commit 68e22011856f ("ACPI: EC: Dispatch the EC GPE directly on s2idle wake") started to dispatch the EC GPE right after a wakeup event has been detected, so in fact the full ACPI SCI action handler doesn't need to run any more to deal with the wakeups coming from the EC. Use this observation to simplify the suspend-to-idle control flow so that the "noirq" phases of device suspend and resume are each run only once in every suspend-to-idle cycle, which is reported to significantly reduce power drawn by some systems when suspended to idle (by allowing them to reach a deep platform-wide low-power state through the suspend-to-idle flow). [What appears to happen is that the "noirq" resume of devices after a spurious EC wakeup brings some devices into a state in which they prevent the platform from reaching the deep low-power state going forward, even after a subsequent "noirq" suspend phase, and on some systems the EC triggers such wakeups already when the "noirq" suspend of devices is running for the first time in the given suspend/resume cycle, so the platform cannot reach the deep low-power state at all.] First, make acpi_s2idle_wake() use the acpi_ec_dispatch_gpe() return value to determine whether or not the wakeup may have been triggered by the EC (in which case the system wakeup is canceled and ACPI events are processed in order to determine whether or not the event is a proper system wakeup one) and use rearm_wake_irq() (introduced by a previous change) in it to rearm the ACPI SCI for system wakeup detection in case the system will remain suspended. Second, drop acpi_s2idle_sync(), which is not needed any more, and the corresponding global platform suspend-to-idle callback. Next, drop the pm_wakeup_pending() check (which is an optimization only) from __device_suspend_noirq() to prevent it from returning errors on system wakeups occurring before the "noirq" phase of device suspend is complete (as in the case of suspend-to-idle it is not known whether or not these wakeups are suprious at that point), in order to avoid having to carry out a "noirq" resume of devices on a spurious system wakeup. Finally, change the code flow in s2idle_loop() to (1) run the "noirq" suspend of devices once before starting the loop, (2) check for spurious EC wakeups (via the platform ->wake callback) for the first time before calling s2idle_enter(), and (3) run the "noirq" resume of devices once after leaving the loop. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/acpi/sleep.c | 47 ++++++++++++++++++---------------- drivers/base/power/main.c | 5 ---- include/linux/suspend.h | 1 - kernel/power/suspend.c | 53 +++++++++++++++++---------------------- 4 files changed, 48 insertions(+), 58 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3debe1a42655..970ae7c7a3f7 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -986,33 +986,37 @@ static void acpi_s2idle_wake(void) lpi_check_constraints(); /* - * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means - * that the SCI has triggered while suspended, so cancel the wakeup in - * case it has not been a wakeup event (the GPEs will be checked later). + * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has + * not triggered while suspended, so bail out. */ - if (acpi_sci_irq_valid() && - !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { + if (!acpi_sci_irq_valid() || + irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) + return; + + /* + * If there are EC events to process, the wakeup may be a spurious one + * coming from the EC. + */ + if (acpi_ec_dispatch_gpe()) { + /* + * Cancel the wakeup and process all pending events in case + * there are any wakeup ones in there. + * + * Note that if any non-EC GPEs are active at this point, the + * SCI will retrigger after the rearming below, so no events + * should be missed by canceling the wakeup here. + */ pm_system_cancel_wakeup(); /* - * On some platforms with the LPS0 _DSM device noirq resume - * takes too much time for EC wakeup events to survive, so look - * for them now. + * The EC driver uses the system workqueue and an additional + * special one, so those need to be flushed too. */ - acpi_ec_dispatch_gpe(); + acpi_os_wait_events_complete(); /* synchronize EC GPE processing */ + acpi_ec_flush_work(); + acpi_os_wait_events_complete(); /* synchronize Notify handling */ } -} -static void acpi_s2idle_sync(void) -{ - /* - * Process all pending events in case there are any wakeup ones. - * - * The EC driver uses the system workqueue and an additional special - * one, so those need to be flushed too. - */ - acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */ - acpi_ec_flush_work(); - acpi_os_wait_events_complete(); /* synchronize Notify handling */ + rearm_wake_irq(acpi_sci_irq); } static void acpi_s2idle_restore(void) @@ -1044,7 +1048,6 @@ static const struct platform_s2idle_ops acpi_s2idle_ops = { .begin = acpi_s2idle_begin, .prepare = acpi_s2idle_prepare, .wake = acpi_s2idle_wake, - .sync = acpi_s2idle_sync, .restore = acpi_s2idle_restore, .end = acpi_s2idle_end, }; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7fb2c39bc725..f08332fab531 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1291,11 +1291,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a if (async_error) goto Complete; - if (pm_wakeup_pending()) { - async_error = -EBUSY; - goto Complete; - } - if (dev->power.syscore || dev->power.direct_complete) goto Complete; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 9c0ad1a3a727..66ce3871ed61 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -191,7 +191,6 @@ struct platform_s2idle_ops { int (*begin)(void); int (*prepare)(void); void (*wake)(void); - void (*sync)(void); void (*restore)(void); void (*end)(void); }; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c874a7026e24..907b2be0372f 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -119,48 +119,41 @@ static void s2idle_enter(void) static void s2idle_loop(void) { + int error; + + dpm_noirq_begin(); + error = dpm_noirq_suspend_devices(PMSG_SUSPEND); + if (error) + goto resume; + pm_pr_dbg("suspend-to-idle\n"); + /* + * Suspend-to-idle equals: + * frozen processes + suspended devices + idle processors. + * Thus s2idle_enter() should be called right after all devices have + * been suspended. + * + * Wakeups during the noirq suspend of devices may be spurious, so try + * to avoid them upfront. + */ for (;;) { - int error; - - dpm_noirq_begin(); - - /* - * Suspend-to-idle equals - * frozen processes + suspended devices + idle processors. - * Thus s2idle_enter() should be called right after - * all devices have been suspended. - * - * Wakeups during the noirq suspend of devices may be spurious, - * so prevent them from terminating the loop right away. - */ - error = dpm_noirq_suspend_devices(PMSG_SUSPEND); - if (!error) - s2idle_enter(); - else if (error == -EBUSY && pm_wakeup_pending()) - error = 0; - - if (!error && s2idle_ops && s2idle_ops->wake) + if (s2idle_ops && s2idle_ops->wake) s2idle_ops->wake(); - dpm_noirq_resume_devices(PMSG_RESUME); - - dpm_noirq_end(); - - if (error) - break; - - if (s2idle_ops && s2idle_ops->sync) - s2idle_ops->sync(); - if (pm_wakeup_pending()) break; pm_wakeup_clear(false); + + s2idle_enter(); } pm_pr_dbg("resume from suspend-to-idle\n"); + +resume: + dpm_noirq_resume_devices(PMSG_RESUME); + dpm_noirq_end(); } void s2idle_wake(void) -- GitLab From 8eb0fd3b55f084320ae511cd5a64d356cf497c83 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 23:52:12 +0200 Subject: [PATCH 0269/7155] PM: sleep: Integrate suspend-to-idle with generig suspend flow After previous changes the suspend-to-idle code flow can be integrated more tightly with the generic system suspend code flow by making suspend_enter() call s2idle_loop() later and removing the direct invocations of dpm_noirq_begin(), dpm_noirq_suspend_devices(), dpm_noirq_end(), and dpm_noirq_resume_devices() from the latter, so do that. This change is not expected to alter functionality. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- kernel/power/suspend.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 907b2be0372f..2b6057853b33 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -119,13 +119,6 @@ static void s2idle_enter(void) static void s2idle_loop(void) { - int error; - - dpm_noirq_begin(); - error = dpm_noirq_suspend_devices(PMSG_SUSPEND); - if (error) - goto resume; - pm_pr_dbg("suspend-to-idle\n"); /* @@ -150,10 +143,6 @@ static void s2idle_loop(void) } pm_pr_dbg("resume from suspend-to-idle\n"); - -resume: - dpm_noirq_resume_devices(PMSG_RESUME); - dpm_noirq_end(); } void s2idle_wake(void) @@ -408,11 +397,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (error) goto Devices_early_resume; - if (state == PM_SUSPEND_TO_IDLE && pm_test_level != TEST_PLATFORM) { - s2idle_loop(); - goto Platform_early_resume; - } - error = dpm_suspend_noirq(PMSG_SUSPEND); if (error) { pr_err("noirq suspend of devices failed\n"); @@ -425,6 +409,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (suspend_test(TEST_PLATFORM)) goto Platform_wake; + if (state == PM_SUSPEND_TO_IDLE) { + s2idle_loop(); + goto Platform_wake; + } + error = suspend_disable_secondary_cpus(); if (error || suspend_test(TEST_CPUS)) goto Enable_cpus; -- GitLab From b605c44c30b59990e806f930c37bd288b9d901a5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Jul 2019 23:52:18 +0200 Subject: [PATCH 0270/7155] PM: sleep: Drop dpm_noirq_begin() and dpm_noirq_end() Note that after previous changes dpm_noirq_begin() and dpm_noirq_end() each have only one caller, so move the code from them to their respective callers and drop them. Also note that dpm_noirq_resume_devices() and dpm_noirq_suspend_devices() need not be exported any more, so make them both static. This change is not expected to alter functionality. Signed-off-by: Rafael J. Wysocki Acked-by: Thomas Gleixner --- drivers/base/power/main.c | 30 ++++++++++++------------------ include/linux/pm.h | 4 ---- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f08332fab531..134a8af51511 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -716,7 +716,7 @@ static void async_resume_noirq(void *data, async_cookie_t cookie) put_device(dev); } -void dpm_noirq_resume_devices(pm_message_t state) +static void dpm_noirq_resume_devices(pm_message_t state) { struct device *dev; ktime_t starttime = ktime_get(); @@ -760,13 +760,6 @@ void dpm_noirq_resume_devices(pm_message_t state) trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false); } -void dpm_noirq_end(void) -{ - resume_device_irqs(); - device_wakeup_disarm_wake_irqs(); - cpuidle_resume(); -} - /** * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices. * @state: PM transition of the system being carried out. @@ -777,7 +770,11 @@ void dpm_noirq_end(void) void dpm_resume_noirq(pm_message_t state) { dpm_noirq_resume_devices(state); - dpm_noirq_end(); + + resume_device_irqs(); + device_wakeup_disarm_wake_irqs(); + + cpuidle_resume(); } static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev, @@ -1357,14 +1354,7 @@ static int device_suspend_noirq(struct device *dev) return __device_suspend_noirq(dev, pm_transition, false); } -void dpm_noirq_begin(void) -{ - cpuidle_pause(); - device_wakeup_arm_wake_irqs(); - suspend_device_irqs(); -} - -int dpm_noirq_suspend_devices(pm_message_t state) +static int dpm_noirq_suspend_devices(pm_message_t state) { ktime_t starttime = ktime_get(); int error = 0; @@ -1421,7 +1411,11 @@ int dpm_suspend_noirq(pm_message_t state) { int ret; - dpm_noirq_begin(); + cpuidle_pause(); + + device_wakeup_arm_wake_irqs(); + suspend_device_irqs(); + ret = dpm_noirq_suspend_devices(state); if (ret) dpm_resume_noirq(resume_event(state)); diff --git a/include/linux/pm.h b/include/linux/pm.h index 3619a870eaa4..4c441be03079 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -712,8 +712,6 @@ struct dev_pm_domain { extern void device_pm_lock(void); extern void dpm_resume_start(pm_message_t state); extern void dpm_resume_end(pm_message_t state); -extern void dpm_noirq_resume_devices(pm_message_t state); -extern void dpm_noirq_end(void); extern void dpm_resume_noirq(pm_message_t state); extern void dpm_resume_early(pm_message_t state); extern void dpm_resume(pm_message_t state); @@ -722,8 +720,6 @@ extern void dpm_complete(pm_message_t state); extern void device_pm_unlock(void); extern int dpm_suspend_end(pm_message_t state); extern int dpm_suspend_start(pm_message_t state); -extern void dpm_noirq_begin(void); -extern int dpm_noirq_suspend_devices(pm_message_t state); extern int dpm_suspend_noirq(pm_message_t state); extern int dpm_suspend_late(pm_message_t state); extern int dpm_suspend(pm_message_t state); -- GitLab From 211ded7861466dd443e61ad29ec34ce93e5a3e38 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 18 Jul 2019 17:15:05 +0800 Subject: [PATCH 0271/7155] ARM: dts: imx6sx: move GIC to right location in DT GIC is inside of SoC from architecture perspective, it should be located inside of soc node in DT. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index bb25add90f19..fe00f9a8accd 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -90,15 +90,6 @@ }; }; - intc: interrupt-controller@a01000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0x00a01000 0x1000>, - <0x00a00100 0x100>; - interrupt-parent = <&intc>; - }; - ckil: clock-ckil { compatible = "fixed-clock"; #clock-cells = <0>; @@ -181,6 +172,15 @@ clocks = <&clks IMX6SX_CLK_OCRAM>; }; + intc: interrupt-controller@a01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x00a01000 0x1000>, + <0x00a00100 0x100>; + interrupt-parent = <&intc>; + }; + L2: l2-cache@a02000 { compatible = "arm,pl310-cache"; reg = <0x00a02000 0x1000>; -- GitLab From b051589c69bf34371ebe04370685002b93ca00d1 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 18 Jul 2019 17:15:06 +0800 Subject: [PATCH 0272/7155] ARM: dts: imx6sl: move GIC to right location in DT GIC is inside of SoC from architecture perspective, it should be located inside of soc node in DT. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sl.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index b36fc012ff06..3a96b5538a2a 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -77,15 +77,6 @@ }; }; - intc: interrupt-controller@a01000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0x00a01000 0x1000>, - <0x00a00100 0x100>; - interrupt-parent = <&intc>; - }; - clocks { ckil { compatible = "fixed-clock"; @@ -133,6 +124,15 @@ clocks = <&clks IMX6SL_CLK_OCRAM>; }; + intc: interrupt-controller@a01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x00a01000 0x1000>, + <0x00a00100 0x100>; + interrupt-parent = <&intc>; + }; + L2: l2-cache@a02000 { compatible = "arm,pl310-cache"; reg = <0x00a02000 0x1000>; -- GitLab From 8c1a1f4879b608f6000f98d1ea3859d9a59a2b7e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 18 Jul 2019 17:15:07 +0800 Subject: [PATCH 0273/7155] ARM: dts: imx6ul: move GIC to right location in DT GIC is inside of SoC from architecture perspective, it should be located inside of soc node in DT. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul.dtsi | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 33d3468c0222..6dff2784abe6 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -93,18 +93,6 @@ }; }; - intc: interrupt-controller@a01000 { - compatible = "arm,gic-400", "arm,cortex-a7-gic"; - interrupts = ; - #interrupt-cells = <3>; - interrupt-controller; - interrupt-parent = <&intc>; - reg = <0x00a01000 0x1000>, - <0x00a02000 0x2000>, - <0x00a04000 0x2000>, - <0x00a06000 0x2000>; - }; - timer { compatible = "arm,armv7-timer"; interrupts = , @@ -171,6 +159,18 @@ reg = <0x00900000 0x20000>; }; + intc: interrupt-controller@a01000 { + compatible = "arm,gic-400", "arm,cortex-a7-gic"; + interrupts = ; + #interrupt-cells = <3>; + interrupt-controller; + interrupt-parent = <&intc>; + reg = <0x00a01000 0x1000>, + <0x00a02000 0x2000>, + <0x00a04000 0x2000>, + <0x00a06000 0x2000>; + }; + dma_apbh: dma-apbh@1804000 { compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x01804000 0x2000>; -- GitLab From df7126cc42105e9df9f0182794482dc137479727 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 18 Jul 2019 17:15:08 +0800 Subject: [PATCH 0274/7155] ARM: dts: imx6sll: move GIC to right location in DT GIC is inside of SoC from architecture perspective, it should be located inside of soc node in DT. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sll.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index 97bb1e7cb0cc..365e591e7878 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -75,15 +75,6 @@ }; }; - intc: interrupt-controller@a01000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0x00a01000 0x1000>, - <0x00a00100 0x100>; - interrupt-parent = <&intc>; - }; - ckil: clock-ckil { compatible = "fixed-clock"; #clock-cells = <0>; @@ -134,6 +125,15 @@ reg = <0x00900000 0x20000>; }; + intc: interrupt-controller@a01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x00a01000 0x1000>, + <0x00a00100 0x100>; + interrupt-parent = <&intc>; + }; + L2: l2-cache@a02000 { compatible = "arm,pl310-cache"; reg = <0x00a02000 0x1000>; -- GitLab From 6d9d21711b38c9cd5f70e04623151f498f3129ac Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 18 Jul 2019 13:25:17 +0300 Subject: [PATCH 0275/7155] firmware: imx: scu-pd: Rename mu PD range to mu_a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Messaging Unit module enables two processors within the SoC to communicate and coordinate by passing messages through the MU interface. MUs have 2 “sides” with independent programming interfaces. Rename mu PD range to mu_a because it's actually side A of MUs. Signed-off-by: Daniel Baluta Reviewed-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 480cec69e2c9..950d30238186 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -92,7 +92,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "gpt", IMX_SC_R_GPT_0, 5, true, 0 }, { "kpp", IMX_SC_R_KPP, 1, false, 0 }, { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 }, - { "mu", IMX_SC_R_MU_0A, 14, true, 0 }, + { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 }, /* CONN SS */ { "usb", IMX_SC_R_USB_0, 2, true, 0 }, -- GitLab From dbc3c6295195267ea7bc48d46030c7b244f8b11e Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 13 Apr 2019 09:14:21 +0200 Subject: [PATCH 0276/7155] ARM: ux500: add missing of_node_put() of_find_compatible_node() returns a pointer with refcount incremented so both in the error path as well as after usage in soc_info_populate() respectively actually b8500_read_soc_id() an explicit of_node_put is needed to release backupram. Signed-off-by: Nicholas Mc Guire Fixes: commit 18a992787896 ("ARM: ux500: move soc_id driver to drivers/soc") Acked-by: Ulf Hansson Signed-off-by: Linus Walleij --- drivers/soc/ux500/ux500-soc-id.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ux500/ux500-soc-id.c b/drivers/soc/ux500/ux500-soc-id.c index ea5fd2e5e340..d64feeb51a40 100644 --- a/drivers/soc/ux500/ux500-soc-id.c +++ b/drivers/soc/ux500/ux500-soc-id.c @@ -203,10 +203,13 @@ static int __init ux500_soc_device_init(void) ux500_setup_id(); soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) + if (!soc_dev_attr) { + of_node_put(backupram); return -ENOMEM; + } soc_info_populate(soc_dev_attr, backupram); + of_node_put(backupram); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { -- GitLab From 590b346b58badfe87cb13a64abdc8af25e907846 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 18 Jul 2019 13:25:18 +0300 Subject: [PATCH 0277/7155] firmware: imx: scu-pd: Add mu13 b side PD range LSIO subsystem contains 14 MU instances. 5 MUs to communicate between AP <-> SCU - side-A PD range managed by AP - side-B PD range managed by SCU 9 MUs to communicate between all cores (AP/M4/DSP). - side-A PD range managed by core-A (AP/M4/DSP) - side-B PD range managed by core-B (AP/M4/DSP). Communication between AP <-> DSP is done through the assigned MU number 13. So, we power up side-A by the AP and we decide to power up side-B also from AP. This is because powering it up from DSP would be painful. Powering up side B from DSP would require the DSP to communicate with SCU and to keep things simple we don't want that now. Signed-off-by: Daniel Baluta Reviewed-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 950d30238186..eb9700b66a76 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -93,6 +93,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "kpp", IMX_SC_R_KPP, 1, false, 0 }, { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 }, { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 }, + { "mu_b", IMX_SC_R_MU_13B, 1, true, 13 }, /* CONN SS */ { "usb", IMX_SC_R_USB_0, 2, true, 0 }, -- GitLab From d43dc52274d40a1543ca962008feb9ff784e3a49 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 18 Jul 2019 13:25:19 +0300 Subject: [PATCH 0278/7155] firmware: imx: scu-pd: Add IRQSTR_DSP PD range The DSP interrupt steer gathers interrupts from the system and can be used to steer them to DSP. Signed-off-by: Daniel Baluta Reviewed-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index eb9700b66a76..b556612207e5 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -131,6 +131,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 }, { "lpuart", IMX_SC_R_UART_0, 4, true, 0 }, { "lpspi", IMX_SC_R_SPI_0, 4, true, 0 }, + { "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 }, /* VPU SS */ { "vpu", IMX_SC_R_VPU, 1, false, 0 }, -- GitLab From 88574a24ea12b7b8d7399e3a6b6c165f1f375323 Mon Sep 17 00:00:00 2001 From: Pramod Kumar Date: Tue, 16 Jul 2019 13:43:27 +0000 Subject: [PATCH 0279/7155] dt-bindings: arm: nxp: Add device tree binding for ls1046a-frwy board Add "fsl,ls1046a-frwy" bindings for ls1046afrwy board based on ls1046a SoC Signed-off-by: Vabhav Sharma Signed-off-by: Pramod Kumar Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index fec6b07f8a23..8c179667ad42 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -284,6 +284,7 @@ properties: - description: LS1046A based Boards items: - enum: + - fsl,ls1046a-frwy - fsl,ls1046a-qds - fsl,ls1046a-rdb - const: fsl,ls1046a -- GitLab From 417393a5072f81cc009b00755f4ac23a9cf83987 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 19 Jul 2019 12:39:24 +0530 Subject: [PATCH 0280/7155] dt-bindings: Add Vendor prefix for Einfochips Add devicetree vendor prefix for Einfochips. https://www.einfochips.com/ Signed-off-by: Manivannan Sadhasivam Reviewed-by: Dong Aisheng Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6992bbbbffab..b01b6fe8a8ce 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -269,6 +269,8 @@ patternProperties: description: Emerging Display Technologies "^eeti,.*": description: eGalax_eMPIA Technology Inc + "^einfochips,.*": + description: Einfochips "^elan,.*": description: Elan Microelectronic Corp. "^elgin,.*": -- GitLab From c39eff747b845aadf0c75a3abde39d57205371b4 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 19 Jul 2019 12:39:25 +0530 Subject: [PATCH 0281/7155] dt-bindings: arm: Document i.MX8QXP AI_ML board binding Document devicetree binding of i.MX8QXP AI_ML board from Einfochips. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Dong Aisheng Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 8c179667ad42..4d93ad454028 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -225,6 +225,7 @@ properties: - description: i.MX8QXP based Boards items: - enum: + - einfochips,imx8qxp-ai_ml # i.MX8QXP AI_ML Board - fsl,imx8qxp-mek # i.MX8QXP MEK Board - const: fsl,imx8qxp -- GitLab From 1a47dc0240bf177878251fae10aabccbaa5a4f20 Mon Sep 17 00:00:00 2001 From: Andra Danciu Date: Mon, 22 Jul 2019 13:27:30 +0300 Subject: [PATCH 0282/7155] dt-bindings: arm: fsl: Add the pico-pi-imx8m board Add an entry for TechNexion PICO-PI-IMX8M board based on i.MX8MQ SoC Datasheet can be found at: https://s3.us-east-2.amazonaws.com/technexion/datasheets/picopiimx8m.pdf Cc: Daniel Baluta Signed-off-by: Andra Danciu Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 4d93ad454028..6847c925fa49 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -220,6 +220,7 @@ properties: - enum: - fsl,imx8mq-evk # i.MX8MQ EVK Board - purism,librem5-devkit # Purism Librem5 devkit + - technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk - const: fsl,imx8mq - description: i.MX8QXP based Boards -- GitLab From 428b504e84bc19aa14108186714d1f5928dcae16 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Jun 2015 12:05:46 +0200 Subject: [PATCH 0283/7155] ARM: ux500: simplify and move debug UART The debug UART code defined three different virtual addresses while only one is ever used. Get rid of this, and move the UART remapping to 0xfffe8000 where DTCM reside on some platforms but not on Ux500, so it can be reused moving the UART out of the vmalloc area. Signed-off-by: Linus Walleij --- arch/arm/include/debug/ux500.S | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/debug/ux500.S b/arch/arm/include/debug/ux500.S index c626f89b3e4a..c516900947bb 100644 --- a/arch/arm/include/debug/ux500.S +++ b/arch/arm/include/debug/ux500.S @@ -20,21 +20,16 @@ #define U8500_UART0_PHYS_BASE (0x80120000) #define U8500_UART1_PHYS_BASE (0x80121000) #define U8500_UART2_PHYS_BASE (0x80007000) -#define U8500_UART0_VIRT_BASE (0xf8120000) -#define U8500_UART1_VIRT_BASE (0xf8121000) -#define U8500_UART2_VIRT_BASE (0xf8007000) #define __UX500_PHYS_UART(n) U8500_UART##n##_PHYS_BASE -#define __UX500_VIRT_UART(n) U8500_UART##n##_VIRT_BASE #endif -#if !defined(__UX500_PHYS_UART) || !defined(__UX500_VIRT_UART) +#if !defined(__UX500_PHYS_UART) #error Unknown SOC #endif #define UX500_PHYS_UART(n) __UX500_PHYS_UART(n) -#define UX500_VIRT_UART(n) __UX500_VIRT_UART(n) #define UART_PHYS_BASE UX500_PHYS_UART(CONFIG_UX500_DEBUG_UART) -#define UART_VIRT_BASE UX500_VIRT_UART(CONFIG_UX500_DEBUG_UART) +#define UART_VIRT_BASE (0xfff07000) .macro addruart, rp, rv, tmp ldr \rp, =UART_PHYS_BASE @ no, physical address -- GitLab From 163ce24a435061f9ff7e1673fec5be0868bdb7d3 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Tue, 16 Apr 2019 06:22:42 +0200 Subject: [PATCH 0284/7155] MAINTAINERS: add soc/ux500 get_maintainer.pl only returns linux-kernel@vger.kernel.org for the drivers/soc/ux500/ files - fix it by adding drivers/soc/ux500/ entry Signed-off-by: Nicholas Mc Guire Suggested-by: Ulf Hansson Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..4bfbdd9ae77c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1968,6 +1968,7 @@ F: Documentation/devicetree/bindings/i2c/i2c-stu300.txt F: arch/arm/mach-nomadik/ F: arch/arm/mach-u300/ F: arch/arm/mach-ux500/ +F: drivers/soc/ux500/ F: arch/arm/boot/dts/ste-* F: drivers/clk/clk-nomadik.c F: drivers/clk/clk-u300.c -- GitLab From 6f21a03b07ce9480087138e588081ed3c3c0fa1e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 23 Jul 2019 10:44:06 +0200 Subject: [PATCH 0285/7155] ARM: dts: sunxi: Remove simple-panel compatible simple-panel based bindings need only the display compatible, and simple-panel isn't documented anywhere. Remove it. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-q8-tablet.dts | 2 +- arch/arm/boot/dts/sun8i-a23-q8-tablet.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts index fde559a8b61e..f9fc1c8b60b8 100644 --- a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts +++ b/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts @@ -49,7 +49,7 @@ compatible = "allwinner,q8-a13", "allwinner,sun5i-a13"; panel: panel { - compatible = "bananapi,s070wv20-ct16", "simple-panel"; + compatible = "bananapi,s070wv20-ct16"; power-supply = <®_vcc3v3>; enable-gpios = <&axp_gpio 0 GPIO_ACTIVE_HIGH>; /* AXP GPIO0 */ backlight = <&backlight>; diff --git a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts index 5659c63d7d77..51097c77a152 100644 --- a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts +++ b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts @@ -63,7 +63,7 @@ }; &panel { - compatible = "bananapi,s070wv20-ct16", "simple-panel"; + compatible = "bananapi,s070wv20-ct16"; }; &tcon0_out { -- GitLab From d40113fb5f7e632232546a74aae6e6d8ca2e70e2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 23 Jul 2019 10:44:07 +0200 Subject: [PATCH 0286/7155] ARM: dts: sunxi: Fix the HDMI PHY name Even though the binding mentions that the PHY name must be "phy", it turns out that all our DTs had "hdmi-phy" instead. The code doesn't care about the phy-names property, so we can just change our DTs to match the binding, without any side effect. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +- arch/arm/boot/dts/sun8i-r40.dtsi | 2 +- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 2 +- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 9d5ddb249596..8de139521451 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -1037,7 +1037,7 @@ resets = <&ccu RST_BUS_HDMI1>; reset-names = "ctrl"; phys = <&hdmi_phy>; - phy-names = "hdmi-phy"; + phy-names = "phy"; pinctrl-names = "default"; pinctrl-0 = <&hdmi_pins>; status = "disabled"; diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 6323941b0f3e..09e20768228c 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -808,7 +808,7 @@ resets = <&ccu RST_BUS_HDMI1>; reset-names = "ctrl"; phys = <&hdmi_phy>; - phy-names = "hdmi-phy"; + phy-names = "phy"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index b1d8c8228a37..b4a6035ae9f5 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -765,7 +765,7 @@ resets = <&ccu RST_BUS_HDMI1>; reset-names = "ctrl"; phys = <&hdmi_phy>; - phy-names = "hdmi-phy"; + phy-names = "phy"; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 60afacfe141d..aa9897f270ba 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1015,7 +1015,7 @@ resets = <&ccu RST_BUS_HDMI1>; reset-names = "ctrl"; phys = <&hdmi_phy>; - phy-names = "hdmi-phy"; + phy-names = "phy"; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 0f571798fc95..35942bae0a34 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -504,7 +504,7 @@ resets = <&ccu RST_BUS_HDMI_SUB>, <&ccu RST_BUS_HDCP>; reset-names = "ctrl", "hdcp"; phys = <&hdmi_phy>; - phy-names = "hdmi-phy"; + phy-names = "phy"; pinctrl-names = "default"; pinctrl-0 = <&hdmi_pins>; status = "disabled"; -- GitLab From f8f85216f8d309daadb37aba8a4b0826783d8747 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 22 Jul 2019 23:15:28 +0200 Subject: [PATCH 0287/7155] ASoC: pcm3168a: Fix a typo in the name of a constant There is a typo in PCM1368A_MAX_SYSCLK, it should be PCM3168A_MAX_SYSCLK (1 and 3 switched in 3168) Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190722211528.26600-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index f1104d7d6426..5d59ce254821 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -263,7 +263,7 @@ static unsigned int pcm3168a_scki_ratios[] = { #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) -#define PCM1368A_MAX_SYSCLK 36864000 +#define PCM3168A_MAX_SYSCLK 36864000 static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) { @@ -296,7 +296,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component); int ret; - if (freq > PCM1368A_MAX_SYSCLK) + if (freq > PCM3168A_MAX_SYSCLK) return -EINVAL; ret = clk_set_rate(pcm3168a->scki, freq); -- GitLab From f1b1b9b136827915624136624ff54aba5890a15b Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Mon, 22 Jul 2019 09:13:42 -0500 Subject: [PATCH 0288/7155] ASoC: SOF: pci: mark last_busy value at runtime PM init If last_busy value is not set at runtime PM enable, the device will be suspend immediately after usage counter is 0. Set the last_busy value to make sure delay is working at first boot up. Signed-off-by: Pan Xiuli Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 65d1bac4c6b8..6fd3df7c57a3 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -223,6 +223,9 @@ static void sof_pci_probe_complete(struct device *dev) */ pm_runtime_allow(dev); + /* mark last_busy for pm_runtime to make sure not suspend immediately */ + pm_runtime_mark_last_busy(dev); + /* follow recommendation in pci-driver.c to decrement usage counter */ pm_runtime_put_noidle(dev); } -- GitLab From 04c8027764bc82a325d3abc6f39a6a4642a937cb Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Jul 2019 09:13:43 -0500 Subject: [PATCH 0289/7155] ASoC: SOF: reset DMA state in prepare When application goes through SUSPEND/STOP->PREPARE->START cycle, we should always reprogram the SOF device to start DMA from a known state so that hw_ptr/appl_ptrs remain valid. This is expected by ALSA core as it resets the buffer state as part of prepare (see snd_pcm_do_prepare()). Fix the issue by forcing reconfiguration of the FW with STREAM_PCM_PARAMS in prepare(). Use combined logic to handle prepare and the existing flow to reprogram hw-params after system suspend. Without the fix, first call to pcm pointer() will return an invalid hw_ptr and application may immediately observe XRUN status, unless "start_threshold" SW parameter is set to maximum value by the application. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 27 +++++++++++++++------------ sound/soc/sof/pm.c | 2 +- sound/soc/sof/sof-priv.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 334e9d59b1ba..3b8955e755b2 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -208,12 +208,11 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + spcm->prepared[substream->stream] = true; + /* save pcm hw_params */ memcpy(&spcm->params[substream->stream], params, sizeof(*params)); - /* clear hw_params_upon_resume flag */ - spcm->hw_params_upon_resume[substream->stream] = 0; - return ret; } @@ -236,6 +235,9 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (!spcm) return -EINVAL; + if (!spcm->prepared[substream->stream]) + return 0; + dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); @@ -258,6 +260,8 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (ret < 0) dev_err(sdev->dev, "error: platform hw free failed\n"); + spcm->prepared[substream->stream] = false; + return ret; } @@ -278,11 +282,7 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream) if (!spcm) return -EINVAL; - /* - * check if hw_params needs to be set-up again. - * This is only needed when resuming from system sleep. - */ - if (!spcm->hw_params_upon_resume[substream->stream]) + if (spcm->prepared[substream->stream]) return 0; dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, @@ -311,6 +311,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_sof_pcm *spcm; struct sof_ipc_stream stream; struct sof_ipc_reply reply; + bool reset_hw_params = false; int ret; /* nothing to do for BE */ @@ -351,6 +352,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + reset_hw_params = true; break; default: dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd); @@ -363,17 +365,17 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply)); - if (ret < 0 || cmd != SNDRV_PCM_TRIGGER_SUSPEND) + if (ret < 0 || !reset_hw_params) return ret; /* - * The hw_free op is usually called when the pcm stream is closed. - * Since the stream is not closed during suspend, the DSP needs to be - * notified explicitly to free pcm to prevent errors upon resume. + * In case of stream is stopped, DSP must be reprogrammed upon + * restart, so free PCM here. */ stream.hdr.size = sizeof(stream); stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; stream.comp_id = spcm->stream[substream->stream].comp_id; + spcm->prepared[substream->stream] = false; /* send IPC to the DSP */ return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, @@ -481,6 +483,7 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) spcm->stream[substream->stream].posn.host_posn = 0; spcm->stream[substream->stream].posn.dai_posn = 0; spcm->stream[substream->stream].substream = substream; + spcm->prepared[substream->stream] = false; ret = snd_sof_pcm_platform_open(sdev, substream); if (ret < 0) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 278abfd10490..48c6d78d72e2 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -233,7 +233,7 @@ static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) state = substream->runtime->status->state; if (state == SNDRV_PCM_STATE_SUSPENDED) - spcm->hw_params_upon_resume[dir] = 1; + spcm->prepared[dir] = false; } } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index b8c0b2a22684..fa5cb7d2a660 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -297,7 +297,7 @@ struct snd_sof_pcm { struct snd_sof_pcm_stream stream[2]; struct list_head list; /* list in sdev pcm list */ struct snd_pcm_hw_params params[2]; - int hw_params_upon_resume[2]; /* set up hw_params upon resume */ + bool prepared[2]; /* PCM_PARAMS set successfully */ }; /* ALSA SOF Kcontrol device */ -- GitLab From a49b687192752bd373f33551520cc98389460ad0 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Jul 2019 09:13:44 -0500 Subject: [PATCH 0290/7155] ASoC: SOF: use common code to send PCM_FREE IPC Remove duplicated code by using a common helper function to send the PCM_FREE IPC message to FW. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 50 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 3b8955e755b2..8612896673a5 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -216,6 +216,27 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } +static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, + struct snd_sof_dev *sdev, + struct snd_sof_pcm *spcm) +{ + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + int ret; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; + stream.comp_id = spcm->stream[substream->stream].comp_id; + + /* send IPC to the DSP */ + ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, + sizeof(stream), &reply, sizeof(reply)); + if (!ret) + spcm->prepared[substream->stream] = false; + + return ret; +} + static int sof_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -223,8 +244,6 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; - struct sof_ipc_stream stream; - struct sof_ipc_reply reply; int ret; /* nothing to do for BE */ @@ -241,13 +260,7 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - stream.hdr.size = sizeof(stream); - stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; - stream.comp_id = spcm->stream[substream->stream].comp_id; - - /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, - sizeof(stream), &reply, sizeof(reply)); + ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); snd_pcm_lib_free_pages(substream); @@ -260,8 +273,6 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (ret < 0) dev_err(sdev->dev, "error: platform hw free failed\n"); - spcm->prepared[substream->stream] = false; - return ret; } @@ -365,21 +376,10 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply)); - if (ret < 0 || !reset_hw_params) - return ret; - - /* - * In case of stream is stopped, DSP must be reprogrammed upon - * restart, so free PCM here. - */ - stream.hdr.size = sizeof(stream); - stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; - stream.comp_id = spcm->stream[substream->stream].comp_id; - spcm->prepared[substream->stream] = false; + if (!ret && reset_hw_params) + ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); - /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, - sizeof(stream), &reply, sizeof(reply)); + return ret; } static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) -- GitLab From 6dd78b310b8d4ab5d0b851e369b5b3d46c6a32a9 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Jul 2019 09:13:45 -0500 Subject: [PATCH 0291/7155] ASoC: SOF: ipc: use timeout configured at probe Do not hardcode IPC timeout value in ipc.c, but rather use the timeout value configured during device probe. For platforms that do not override the IPC timeout, default value TIMEOUT_DEFAULT_IPC_MS has already been defined in core.c. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 20dfca9c93b7..b2f359d2f7e5 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -17,12 +17,6 @@ #include "sof-priv.h" #include "ops.h" -/* - * IPC message default size and timeout (ms). - * TODO: allow platforms to set size and timeout. - */ -#define IPC_TIMEOUT_MS 300 - static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id); static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd); @@ -211,7 +205,7 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, /* wait for DSP IPC completion */ ret = wait_event_timeout(msg->waitq, msg->ipc_complete, - msecs_to_jiffies(IPC_TIMEOUT_MS)); + msecs_to_jiffies(sdev->ipc_timeout)); if (ret == 0) { dev_err(sdev->dev, "error: ipc timed out for 0x%x size %d\n", -- GitLab From c9b54a3360166ca2fec11d55c86b5e685e56bab8 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Jul 2019 09:13:46 -0500 Subject: [PATCH 0292/7155] ASoC: SOF: core: increase default IPC timeouts Increase the default timeout values for boot (100ms to 2sec) and IPC message sending (5ms to 500ms). The values should be overridden with values from platform data. There is no functional need to have such short timeouts as both boot and IPC send errors are considered fatal errors. More relaxed timeouts are convenient when running the driver on top of emulation such as QEMU. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 5beda47cdf9f..81f28f7ff1a0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -17,8 +17,8 @@ #include "ops.h" /* SOF defaults if not provided by the platform in ms */ -#define TIMEOUT_DEFAULT_IPC_MS 5 -#define TIMEOUT_DEFAULT_BOOT_MS 100 +#define TIMEOUT_DEFAULT_IPC_MS 500 +#define TIMEOUT_DEFAULT_BOOT_MS 2000 /* * Generic object lookup APIs. -- GitLab From ce8234a6357ec8f81b977d8536ff941dbd4162f3 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 22 Jul 2019 09:13:47 -0500 Subject: [PATCH 0293/7155] ASoC: SOF: Introduce snd_sof_dsp_get_bar_index ops FW encapsulates information about section types (e.g DRAM, IRAM) inside module block header. This information can be used in order to correctly load the section to the appropriate place in memory. SOF Linux driver needs to know for each platform how to map the section type with the corresponding memory BAR. So, this patch introduces get_bar_index, a new operation inside snd_sof_dsp_ops. Intel platforms, usually load all the section in a contiguous memory area (usually denoted by sdev->mmio_bar) so things are relatively simple there. Anyhow, on i.MX8 IRAM and DRAM for example are mapped to distinct BARs. By default, if no get_bar function is provided the core implementation will always return sdev->mmio_bar so that there will be no need for a change to existing Intel code. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 19 +++++++++++++++++++ sound/soc/sof/sof-priv.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index b1c27615b805..8fda42748f39 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -100,6 +100,25 @@ static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev) return 0; } +/* misc */ + +/** + * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index + * + * @sdev: sof device + * @type: section type as described by snd_sof_fw_blk_type + * + * Returns the corresponding BAR index (a positive integer) or -EINVAL + * in case there is no mapping + */ +static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type) +{ + if (sof_ops(sdev)->get_bar_index) + return sof_ops(sdev)->get_bar_index(sdev, type); + + return sdev->mmio_bar; +} + /* power management */ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index fa5cb7d2a660..a6ec9115a9fb 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -196,6 +196,9 @@ struct snd_sof_dsp_ops { int (*trace_trigger)(struct snd_sof_dev *sdev, int cmd); /* optional */ + /* misc */ + int (*get_bar_index)(struct snd_sof_dev *sdev, + u32 type); /* optional */ /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; -- GitLab From 7198879ef57775df3b1a75c62bb9e313c56876d4 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 22 Jul 2019 09:13:48 -0500 Subject: [PATCH 0294/7155] ASoC: SOF: loader: Use the BAR provided by FW Make sure to use the newly introduced function snd_sof_dsp_get_bar_index that converts the section type to appropriate BAR index. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 952a19091c58..e75da8aa7d4a 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -92,7 +92,7 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, struct snd_sof_mod_hdr *module) { struct snd_sof_blk_hdr *block; - int count; + int count, bar; u32 offset; size_t remaining; @@ -128,6 +128,13 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, case SOF_FW_BLK_TYPE_IRAM: case SOF_FW_BLK_TYPE_DRAM: offset = block->offset; + bar = snd_sof_dsp_get_bar_index(sdev, block->type); + if (bar < 0) { + dev_err(sdev->dev, + "error: no BAR mapping for block type 0x%x\n", + block->type); + return bar; + } break; default: dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n", @@ -145,7 +152,7 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, block->size); return -EINVAL; } - snd_sof_dsp_block_write(sdev, sdev->mmio_bar, offset, + snd_sof_dsp_block_write(sdev, bar, offset, block + 1, block->size); if (remaining < block->size) { -- GitLab From 441c58cf8e5e0c594b3d1b489e7810ec7248820d Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 22 Jul 2019 09:13:49 -0500 Subject: [PATCH 0295/7155] ASoC: SOF: loader: Don't ignore SRAM block types On i.MX8 data/heap/stack is kept in System RAM so do not ignore SRAM block types received from FW. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index e75da8aa7d4a..93cb8fd0844f 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -123,10 +123,11 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, switch (block->type) { case SOF_FW_BLK_TYPE_RSRVD0: - case SOF_FW_BLK_TYPE_SRAM...SOF_FW_BLK_TYPE_RSRVD14: + case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14: continue; /* not handled atm */ case SOF_FW_BLK_TYPE_IRAM: case SOF_FW_BLK_TYPE_DRAM: + case SOF_FW_BLK_TYPE_SRAM: offset = block->offset; bar = snd_sof_dsp_get_bar_index(sdev, block->type); if (bar < 0) { -- GitLab From 1c38c9223da3af619d35f052ad6f4bbaa0f08ac2 Mon Sep 17 00:00:00 2001 From: Fred Oh Date: Mon, 22 Jul 2019 09:13:50 -0500 Subject: [PATCH 0296/7155] ASoC: SOF: remove unused state variable in suspend function Remove unused and no plan to use variable from suspend function. Signed-off-by: Fred Oh Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 10 +++++----- sound/soc/sof/intel/hda.h | 4 ++-- sound/soc/sof/ops.h | 9 ++++----- sound/soc/sof/pm.c | 4 ++-- sound/soc/sof/sof-priv.h | 5 ++--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 91de4785b6a3..4315896b3f07 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -282,7 +282,7 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); } -static int hda_suspend(struct snd_sof_dev *sdev, int state) +static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; @@ -431,19 +431,19 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) return 0; } -int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state) +int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) { /* stop hda controller and power dsp off */ - return hda_suspend(sdev, state); + return hda_suspend(sdev, true); } -int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) +int hda_dsp_suspend(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); int ret; /* stop hda controller and power dsp off */ - ret = hda_suspend(sdev, state); + ret = hda_suspend(sdev, false); if (ret < 0) { dev_err(bus->dev, "error: suspending dsp\n"); return ret; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index d9c17146200b..84d5fd021ccb 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -453,9 +453,9 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); -int hda_dsp_suspend(struct snd_sof_dev *sdev, int state); +int hda_dsp_suspend(struct snd_sof_dev *sdev); int hda_dsp_resume(struct snd_sof_dev *sdev); -int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state); +int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 8fda42748f39..793c1aea0c53 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -128,10 +128,10 @@ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) return 0; } -static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev, int state) +static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev) { if (sof_ops(sdev)->suspend) - return sof_ops(sdev)->suspend(sdev, state); + return sof_ops(sdev)->suspend(sdev); return 0; } @@ -144,11 +144,10 @@ static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev) return 0; } -static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, - int state) +static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev) { if (sof_ops(sdev)->runtime_suspend) - return sof_ops(sdev)->runtime_suspend(sdev, state); + return sof_ops(sdev)->runtime_suspend(sdev); return 0; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 48c6d78d72e2..e23beaeefe00 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -377,9 +377,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) /* power down all DSP cores */ if (runtime_suspend) - ret = snd_sof_dsp_runtime_suspend(sdev, 0); + ret = snd_sof_dsp_runtime_suspend(sdev); else - ret = snd_sof_dsp_suspend(sdev, 0); + ret = snd_sof_dsp_suspend(sdev); if (ret < 0) dev_err(sdev->dev, "error: failed to power down DSP during suspend %d\n", diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index a6ec9115a9fb..b8c9274ccf42 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -171,10 +171,9 @@ struct snd_sof_dsp_ops { int (*post_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ /* DSP PM */ - int (*suspend)(struct snd_sof_dev *sof_dev, int state); /* optional */ + int (*suspend)(struct snd_sof_dev *sof_dev); /* optional */ int (*resume)(struct snd_sof_dev *sof_dev); /* optional */ - int (*runtime_suspend)(struct snd_sof_dev *sof_dev, - int state); /* optional */ + int (*runtime_suspend)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ -- GitLab From 184fdfca4ba63d57a668564639a4dcf188fc9822 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 22 Jul 2019 09:13:51 -0500 Subject: [PATCH 0297/7155] ASoC: SOF: Intel: hda: correct ROM state mask The ROM state is represented by the 24 LSB bits in the ROM status register, so the mask should be 0xffffff instead of 0xf. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 84d5fd021ccb..70909debfeb5 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -175,7 +175,7 @@ #define HDA_DSP_STACK_DUMP_SIZE 32 /* ROM status/error values */ -#define HDA_DSP_ROM_STS_MASK 0xf +#define HDA_DSP_ROM_STS_MASK GENMASK(23, 0) #define HDA_DSP_ROM_INIT 0x1 #define HDA_DSP_ROM_FW_MANIFEST_LOADED 0x3 #define HDA_DSP_ROM_FW_FW_LOADED 0x4 -- GitLab From 6aa232e1ccfcd2b55306b86803dc547c36f8ad15 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 22 Jul 2019 09:13:52 -0500 Subject: [PATCH 0298/7155] ASoC: SOF: Intel: hda: reduce ifdef usage for hda Move the code for hda to one point Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 4315896b3f07..3d711d354fb9 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -359,6 +359,16 @@ static int hda_resume(struct snd_sof_dev *sdev) bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); hda_dsp_ctrl_misc_clock_gating(sdev, true); + + /* turn off the links that were off before suspend */ + list_for_each_entry(hlink, &bus->hlink_list, list) { + if (!hlink->ref_count) + snd_hdac_ext_bus_link_power_down(hlink); + } + + /* check dma status and clean up CORB/RIRB buffers */ + if (!bus->cmd_dma_state) + snd_hdac_bus_stop_cmd_io(bus); #else hda_dsp_ctrl_misc_clock_gating(sdev, false); @@ -391,18 +401,6 @@ static int hda_resume(struct snd_sof_dev *sdev) hda_dsp_ctrl_ppcap_enable(sdev, true); hda_dsp_ctrl_ppcap_int_enable(sdev, true); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* turn off the links that were off before suspend */ - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (!hlink->ref_count) - snd_hdac_ext_bus_link_power_down(hlink); - } - - /* check dma status and clean up CORB/RIRB buffers */ - if (!bus->cmd_dma_state) - snd_hdac_bus_stop_cmd_io(bus); -#endif - return 0; } -- GitLab From fd15f2f5e272145269bcbf834e0e0b560a575891 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 22 Jul 2019 09:13:53 -0500 Subject: [PATCH 0299/7155] ASoC: SOF: Intel: hda: Enable jack detection In commit 7d4f606c50ff ("ALSA: hda - WAKEEN feature enabling for runtime pm"), legacy HD-A driver sets hda controller in reset mode after entering runtime-suspend. And when resuming from suspend mode, it checks hda controller & codec status to detect headphone hotplug event. Now this patch does the same job in SOF runtime pm functions. And we need to check all the non-hdmi codecs for some cases like playback with HDMI or capture with DMIC connected to dsp. In these cases, only controller is active and codecs are suspended, so codecs can't send unsolicited event to controller. The jack polling operation will activate codecs and unsolicited event can work even codecs become suspended later. Tested on whiskylake with hda codecs. Signed-off-by: Rander Wang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 44 +++++++++++++++++++++++++++++++-- sound/soc/sof/intel/hda-dsp.c | 21 ++++++++-------- sound/soc/sof/intel/hda.h | 2 ++ 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 0d8437b080bf..3ca6795a89ba 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -37,16 +38,55 @@ static void hda_codec_load_module(struct hda_codec *codec) static void hda_codec_load_module(struct hda_codec *codec) {} #endif +/* enable controller wake up event for all codecs with jack connectors */ +void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) +{ + struct hda_bus *hbus = sof_to_hbus(sdev); + struct hdac_bus *bus = sof_to_bus(sdev); + struct hda_codec *codec; + unsigned int mask = 0; + + list_for_each_codec(codec, hbus) + if (codec->jacktbl.used) + mask |= BIT(codec->core.addr); + + snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); +} + +/* check jack status after resuming from suspend mode */ +void hda_codec_jack_check(struct snd_sof_dev *sdev) +{ + struct hda_bus *hbus = sof_to_hbus(sdev); + struct hdac_bus *bus = sof_to_bus(sdev); + struct hda_codec *codec; + + /* disable controller Wake Up event*/ + snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0); + + list_for_each_codec(codec, hbus) + /* + * Wake up all jack-detecting codecs regardless whether an event + * has been recorded in STATESTS + */ + if (codec->jacktbl.used) + schedule_delayed_work(&codec->jackpoll_work, + codec->jackpoll_interval); +} +#else +void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {} +void hda_codec_jack_check(struct snd_sof_dev *sdev) {} #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ +EXPORT_SYMBOL(hda_codec_jack_wake_enable); +EXPORT_SYMBOL(hda_codec_jack_check); /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) { - struct hda_bus *hbus = sof_to_hbus(sdev); - struct hdac_device *hdev; #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; #endif + struct hda_bus *hbus = sof_to_hbus(sdev); + struct hdac_device *hdev; u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; u32 resp = -1; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 3d711d354fb9..f9579edbca68 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -295,6 +295,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) hda_dsp_ipc_int_disable(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + if (runtime_suspend) + hda_codec_jack_wake_enable(sdev); + /* power down all hda link */ snd_hdac_ext_bus_link_power_down_all(bus); #endif @@ -329,7 +332,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) return 0; } -static int hda_resume(struct snd_sof_dev *sdev) +static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) struct hdac_bus *bus = sof_to_bus(sdev); @@ -343,7 +346,6 @@ static int hda_resume(struct snd_sof_dev *sdev) */ snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* reset and start hda controller */ ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { @@ -352,13 +354,10 @@ static int hda_resume(struct snd_sof_dev *sdev) return ret; } - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* Reset stream-to-link mapping */ - list_for_each_entry(hlink, &bus->hlink_list, list) - bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* check jack status */ + if (runtime_resume) + hda_codec_jack_check(sdev); /* turn off the links that were off before suspend */ list_for_each_entry(hlink, &bus->hlink_list, list) { @@ -407,13 +406,13 @@ static int hda_resume(struct snd_sof_dev *sdev) int hda_dsp_resume(struct snd_sof_dev *sdev) { /* init hda controller. DSP cores will be powered up during fw boot */ - return hda_resume(sdev); + return hda_resume(sdev, false); } int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) { /* init hda controller. DSP cores will be powered up during fw boot */ - return hda_resume(sdev); + return hda_resume(sdev, true); } int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 70909debfeb5..028e865d5e20 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -557,6 +557,8 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, * HDA Codec operations. */ int hda_codec_probe_bus(struct snd_sof_dev *sdev); +void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev); +void hda_codec_jack_check(struct snd_sof_dev *sdev); #endif /* CONFIG_SND_SOC_SOF_HDA */ -- GitLab From 061edb232505797aee53a955225af23fa30d45b8 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Mon, 22 Jul 2019 09:13:54 -0500 Subject: [PATCH 0300/7155] ASoC: SOF: Intel: hda: set position buffer in init chip Set the HDA stream position buffer during init chip. The position buffer needs to be set in both HDA codec and nocodec cases. Using SOF defined function and move it to common code. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index ea63f83a509b..015760284969 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -245,14 +245,13 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* program the position buffer */ if (bus->use_posbuf && bus->posbuf.addr) { - snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); - snd_hdac_chip_writel(bus, DPUBASE, - upper_32_bits(bus->posbuf.addr)); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE, + (u32)bus->posbuf.addr); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE, + upper_32_bits(bus->posbuf.addr)); } -#endif bus->chip_init = true; -- GitLab From d06973515f95ac74d68fb3e1f1fb4b055531296c Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Mon, 22 Jul 2019 09:13:55 -0500 Subject: [PATCH 0301/7155] ASoC: SOF: Intel: hda: use SOF defined init chip in resume Unify resume code by using SOF common function hda_dsp_ctrl_init_chip() which can handle both HDA and non-HDA cases. Move code to reset stream-to-link mapping into hda_dsp_ctrl_init_chip(). Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 9 +++++++++ sound/soc/sof/intel/hda-dsp.c | 26 -------------------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 015760284969..8b856dc35e20 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -164,6 +164,9 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) { struct hdac_bus *bus = sof_to_bus(sdev); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + struct hdac_ext_link *hlink; +#endif struct hdac_stream *stream; int sd_offset, ret = 0; @@ -253,6 +256,12 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) upper_32_bits(bus->posbuf.addr)); } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* Reset stream-to-link mapping */ + list_for_each_entry(hlink, &bus->hlink_list, list) + bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); +#endif + bus->chip_init = true; hda_dsp_ctrl_misc_clock_gating(sdev, true); diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index f9579edbca68..f08a5d649346 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -368,32 +368,6 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) /* check dma status and clean up CORB/RIRB buffers */ if (!bus->cmd_dma_state) snd_hdac_bus_stop_cmd_io(bus); -#else - - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* reset controller */ - ret = hda_dsp_ctrl_link_reset(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to reset controller during resume\n"); - return ret; - } - - /* take controller out of reset */ - ret = hda_dsp_ctrl_link_reset(sdev, false); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to ready controller during resume\n"); - return ret; - } - - /* enable hda bus irq */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); #endif /* enable ppcap interrupt */ -- GitLab From dc7a36f178a94604d29c5dd15c77187905d8e882 Mon Sep 17 00:00:00 2001 From: Zhu Yingjiang Date: Mon, 22 Jul 2019 09:13:56 -0500 Subject: [PATCH 0302/7155] ASoC: SOF: Intel: hda: remove duplicated clear WAKESTS Remove the first clear WAKESTS, only one clear is needed during init chip. Signed-off-by: Zhu Yingjiang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 8b856dc35e20..a7fee403cb90 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -176,11 +176,6 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) hda_dsp_ctrl_misc_clock_gating(sdev, false); if (full_reset) { - /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); - /* reset HDA controller */ ret = hda_dsp_ctrl_link_reset(sdev, true); if (ret < 0) { -- GitLab From 672ff5e3596ee27b64edcc73251f4ae1c8ab12ac Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 22 Jul 2019 09:13:57 -0500 Subject: [PATCH 0303/7155] ASoC: SOF: Intel: hda: add a parameter to disable MSI Enabling MSI on HDA can fail, in which case the legacy PCI IRQ mode will be used. To make testing this mode easier add an "enable_msi" module parameter, which is only enabled if debugging is enabled too. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 28 +++++++++++++++++----------- sound/soc/sof/sof-priv.h | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7f665392618f..79cce20666b6 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -46,6 +46,12 @@ struct hda_dsp_msg_code { const char *msg; }; +static bool hda_use_msi = IS_ENABLED(CONFIG_PCI); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) +module_param_named(use_msi, hda_use_msi, bool, 0444); +MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); +#endif + static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"}, {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"}, @@ -529,11 +535,18 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * register our IRQ * let's try to enable msi firstly * if it fails, use legacy interrupt mode - * TODO: support interrupt mode selection with kernel parameter - * support msi multiple vectors + * TODO: support msi multiple vectors */ - ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); - if (ret < 0) { + if (hda_use_msi && !pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI)) { + dev_info(sdev->dev, "use msi interrupt mode\n"); + hdev->irq = pci_irq_vector(pci, 0); + /* ipc irq number is the same of hda irq */ + sdev->ipc_irq = hdev->irq; + /* initialised to "false" by kzalloc() */ + sdev->msi_enabled = true; + } + + if (!sdev->msi_enabled) { dev_info(sdev->dev, "use legacy interrupt mode\n"); /* * in IO-APIC mode, hda->irq and ipc_irq are using the same @@ -541,13 +554,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) */ hdev->irq = pci->irq; sdev->ipc_irq = pci->irq; - sdev->msi_enabled = 0; - } else { - dev_info(sdev->dev, "use msi interrupt mode\n"); - hdev->irq = pci_irq_vector(pci, 0); - /* ipc irq number is the same of hda irq */ - sdev->ipc_irq = hdev->irq; - sdev->msi_enabled = 1; } dev_dbg(sdev->dev, "using HDA IRQ %d\n", hdev->irq); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index b8c9274ccf42..983eadef4b30 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -435,7 +435,7 @@ struct snd_sof_dev { u32 dtrace_error; u32 dtrace_draining; - u32 msi_enabled; + bool msi_enabled; void *private; /* core does not touch this */ }; -- GitLab From a3ebccb52efdfb3459fa51516238cc464ee310c9 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Jul 2019 09:13:58 -0500 Subject: [PATCH 0304/7155] ASoC: SOF: Intel: hda: reset link DMA state in prepare When application goes through SUSPEND/STOP->PREPARE->START cycle, we should always reprogram the DAI link DMA to ensure it is in sync with the host PCM DMA. Use same state tracking logic to handle both restart and system resume flows. Use link_prepared field of 'struct hdac_ext_stream' to store the state, instead of adding redundant fields to SOF specific structs. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 8 +++----- sound/soc/sof/intel/hda-dsp.c | 17 ++++++----------- sound/soc/sof/intel/hda.h | 1 - 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index a514f9cf5c9a..a448be60f6dd 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -226,8 +226,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); - hda_stream->hw_params_upon_resume = 0; - link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); if (!link) return -EINVAL; @@ -267,8 +265,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, hda_stream = hstream_to_sof_hda_stream(link_dev); - /* setup hw_params again only if resuming from system suspend */ - if (!hda_stream->hw_params_upon_resume) + if (link_dev->link_prepared) return 0; dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream); @@ -317,6 +314,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, snd_hdac_ext_link_stream_start(link_dev); break; case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: /* * clear and release link DMA channel. It will be assigned when * hw_params is set up again after resume. @@ -329,10 +327,10 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, snd_hdac_ext_link_clear_stream_id(link, stream_tag); snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); + link_dev->link_prepared = 0; /* fallthrough */ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_STOP: snd_hdac_ext_link_stream_clear(link_dev); break; default: diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index f08a5d649346..e82ecaad1763 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -425,25 +425,19 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev) int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) { - struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *hda_stream; - struct hdac_ext_stream *stream; - struct hdac_stream *s; - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + struct hdac_bus *bus = sof_to_bus(sdev); struct snd_soc_pcm_runtime *rtd; + struct hdac_ext_stream *stream; struct hdac_ext_link *link; + struct hdac_stream *s; const char *name; int stream_tag; -#endif /* set internal flag for BE */ list_for_each_entry(s, &bus->stream_list, list) { stream = stream_to_hdac_ext_stream(s); - hda_stream = container_of(stream, struct sof_intel_hda_stream, - hda_stream); - hda_stream->hw_params_upon_resume = 1; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* * clear and release stream. This should already be taken care * for running streams when the SUSPEND trigger is called. @@ -460,8 +454,9 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) snd_hdac_ext_link_clear_stream_id(link, stream_tag); snd_hdac_ext_stream_release(stream, HDAC_EXT_STREAM_TYPE_LINK); + stream->link_prepared = 0; } -#endif } +#endif return 0; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 028e865d5e20..ceaaa8d467f4 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -418,7 +418,6 @@ struct sof_intel_hda_stream { struct snd_sof_dev *sdev; struct hdac_ext_stream hda_stream; struct sof_intel_stream stream; - int hw_params_upon_resume; /* set up hw_params upon resume */ int host_reserved; /* reserve host DMA channel */ }; -- GitLab From 6298b78742be6593d372ed1b5bfa5397e1393595 Mon Sep 17 00:00:00 2001 From: Janusz Jankowski Date: Mon, 22 Jul 2019 09:14:02 -0500 Subject: [PATCH 0305/7155] ASoC: SOF: Intel: ssp: BCLK delay parameter Some codecs require BCLK to be on for some time, before sending any data. SOF can enable BCLK and then wait for guaranteed time, before starting DMA on SSP start. Signed-off-by: Janusz Jankowski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 3 +++ include/uapi/sound/sof/abi.h | 2 +- include/uapi/sound/sof/tokens.h | 1 + sound/soc/sof/topology.c | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4bb8ee138ba7..a81afd3fbd41 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -76,6 +76,9 @@ struct sof_ipc_dai_ssp_params { uint16_t tdm_per_slot_padding_flag; uint32_t clks_control; uint32_t quirks; + uint32_t bclk_delay; /* guaranteed time (ms) for which BCLK + * will be driven, before sending data + */ } __packed; /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 4a9c24434f42..dff70a42445a 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 8 +#define SOF_ABI_MINOR 9 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index dc1b27daaac6..6435240cef13 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -75,6 +75,7 @@ #define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503 #define SOF_TKN_INTEL_SSP_QUIRKS 504 #define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505 +#define SOF_TKN_INTEL_SSP_BCLK_DELAY 506 /* DMIC */ #define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600 diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 432ae343f960..12b7d900b9c2 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -748,6 +748,9 @@ static const struct sof_topology_token ssp_tokens[] = { get_token_u16, offsetof(struct sof_ipc_dai_ssp_params, tdm_per_slot_padding_flag), 0}, + {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, + get_token_u32, + offsetof(struct sof_ipc_dai_ssp_params, bclk_delay), 0}, }; -- GitLab From 7ccafa2b3879612ab9ed88bb6664bd4085957186 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 11 Jul 2019 18:49:46 +0800 Subject: [PATCH 0306/7155] ASoC: fsl_esai: recover the channel swap after xrun There is chip errata ERR008000, the reference doc is (https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf), The issue is "While using ESAI transmit or receive and an underrun/overrun happens, channel swap may occur. The only recovery mechanism is to reset the ESAI." This issue exist in imx3/imx5/imx6(partial) series. In this commit add a tasklet to handle reset of ESAI after xrun happens to recover the channel swap. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/326035cb99975361699d9ed748054b08bc06a341.1562842206.git.shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index ab460d6d7432..4ce8ac769244 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -32,6 +32,7 @@ * @extalclk: esai clock source to derive HCK, SCK and FS * @fsysclk: system clock source to derive HCK, SCK and FS * @spbaclk: SPBA clock (optional, depending on SoC design) + * @task: tasklet to handle the reset operation * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @slots: number of slots @@ -42,6 +43,7 @@ * @sck_div: if using PSR/PM dividers for SCKx clock * @slave_mode: if fully using DAI slave mode * @synchronous: if using tx/rx synchronous mode + * @reset_at_xrun: flags for enable reset operaton * @name: driver name */ struct fsl_esai { @@ -53,6 +55,7 @@ struct fsl_esai { struct clk *extalclk; struct clk *fsysclk; struct clk *spbaclk; + struct tasklet_struct task; u32 fifo_depth; u32 slot_width; u32 slots; @@ -65,6 +68,7 @@ struct fsl_esai { bool sck_div[2]; bool slave_mode; bool synchronous; + bool reset_at_xrun; char name[32]; }; @@ -73,8 +77,16 @@ static irqreturn_t esai_isr(int irq, void *devid) struct fsl_esai *esai_priv = (struct fsl_esai *)devid; struct platform_device *pdev = esai_priv->pdev; u32 esr; + u32 saisr; regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); + regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr); + + if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) && + esai_priv->reset_at_xrun) { + dev_dbg(&pdev->dev, "reset module for xrun\n"); + tasklet_schedule(&esai_priv->task); + } if (esr & ESAI_ESR_TINIT_MASK) dev_dbg(&pdev->dev, "isr: Transmission Initialized\n"); @@ -635,10 +647,17 @@ static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); + + /* Enable Exception interrupt */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + ESAI_xCR_xEIE_MASK, ESAI_xCR_xEIE); } static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) { + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), + ESAI_xCR_xEIE_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), @@ -653,6 +672,51 @@ static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) ESAI_xFCR_xFR, 0); } +static void fsl_esai_hw_reset(unsigned long arg) +{ + struct fsl_esai *esai_priv = (struct fsl_esai *)arg; + bool tx = true, rx = false, enabled[2]; + u32 tfcr, rfcr; + + /* Save the registers */ + regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &tfcr); + regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &rfcr); + enabled[tx] = tfcr & ESAI_xFCR_xFEN; + enabled[rx] = rfcr & ESAI_xFCR_xFEN; + + /* Stop the tx & rx */ + fsl_esai_trigger_stop(esai_priv, tx); + fsl_esai_trigger_stop(esai_priv, rx); + + /* Reset the esai, and ignore return value */ + fsl_esai_hw_init(esai_priv); + + /* Enforce ESAI personal resets for both TX and RX */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, + ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, + ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); + + /* Restore registers by regcache_sync, and ignore return value */ + fsl_esai_register_restore(esai_priv); + + /* Remove ESAI personal resets by configuring PCRC and PRRC also */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, + ESAI_xCR_xPR_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, + ESAI_xCR_xPR_MASK, 0); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, + ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, + ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); + + /* Restart tx / rx, if they already enabled */ + if (enabled[tx]) + fsl_esai_trigger_start(esai_priv, tx); + if (enabled[rx]) + fsl_esai_trigger_start(esai_priv, rx); +} + static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -857,6 +921,10 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); + if (of_device_is_compatible(np, "fsl,vf610-esai") || + of_device_is_compatible(np, "fsl,imx35-esai")) + esai_priv->reset_at_xrun = true; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); @@ -956,6 +1024,9 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } + tasklet_init(&esai_priv->task, fsl_esai_hw_reset, + (unsigned long)esai_priv); + pm_runtime_enable(&pdev->dev); regcache_cache_only(esai_priv->regmap, true); @@ -969,7 +1040,10 @@ static int fsl_esai_probe(struct platform_device *pdev) static int fsl_esai_remove(struct platform_device *pdev) { + struct fsl_esai *esai_priv = platform_get_drvdata(pdev); + pm_runtime_disable(&pdev->dev); + tasklet_kill(&esai_priv->task); return 0; } -- GitLab From 934bf82203d679a8f2ff22817e341bc059f5f7fc Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 22 Jul 2019 09:13:59 -0500 Subject: [PATCH 0307/7155] ASoC: SOF: Intel: hda: fix link DMA config For this bug, there are two capture pcm streams active, with one stream and its related stream tag released before suspend. Later when system suspend is done, the stream tag for the remaining active stream is released by SOF driver. After system resume, hda codec driver restores the stream tag for the active pcm stream, but SOF goes to assign a new one, which now doesn't match with the stream tag used by codec driver, and this causes DMA to fail receiving data, leading to unrecoverable XRUN condition in FW. For stream tag is stored in both hda codec and SOF driver, it shouldn't be released only in SOF driver. This patch just keeps the stream information in dma data and checks whether there is a stored DMA data for stream resuming from S3 and restores it. And it also removes DMA data when the stream is released. Tested on Whiskey Lake platform. GitHub issue: https://github.com/thesofproject/sof/issues/1594 Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 15 +++++++++------ sound/soc/sof/intel/hda-dsp.c | 10 ++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index a448be60f6dd..2b5e2b8c69c2 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -210,9 +210,13 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, int stream_tag; int ret; - link_dev = hda_link_stream_assign(bus, substream); - if (!link_dev) - return -EBUSY; + /* get stored dma data if resuming from system suspend */ + link_dev = snd_soc_dai_get_dma_data(dai, substream); + if (!link_dev) { + link_dev = hda_link_stream_assign(bus, substream); + if (!link_dev) + return -EBUSY; + } stream_tag = hdac_stream(link_dev)->stream_tag; @@ -316,7 +320,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: /* - * clear and release link DMA channel. It will be assigned when + * clear link DMA channel. It will be assigned when * hw_params is set up again after resume. */ ret = hda_link_config_ipc(hda_stream, dai->name, @@ -325,8 +329,6 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, return ret; stream_tag = hdac_stream(link_dev)->stream_tag; snd_hdac_ext_link_clear_stream_id(link, stream_tag); - snd_hdac_ext_stream_release(link_dev, - HDAC_EXT_STREAM_TYPE_LINK); link_dev->link_prepared = 0; /* fallthrough */ @@ -369,6 +371,7 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, stream_tag = hdac_stream(link_dev)->stream_tag; snd_hdac_ext_link_clear_stream_id(link, stream_tag); + snd_soc_dai_set_dma_data(dai, substream, NULL); snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); link_dev->link_prepared = 0; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index e82ecaad1763..e38008194574 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -439,10 +439,10 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) stream = stream_to_hdac_ext_stream(s); /* - * clear and release stream. This should already be taken care - * for running streams when the SUSPEND trigger is called. - * But paused streams do not get suspended, so this needs to be - * done explicitly during suspend. + * clear stream. This should already be taken care for running + * streams when the SUSPEND trigger is called. But paused + * streams do not get suspended, so this needs to be done + * explicitly during suspend. */ if (stream->link_substream) { rtd = snd_pcm_substream_chip(stream->link_substream); @@ -452,8 +452,6 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) return -EINVAL; stream_tag = hdac_stream(stream)->stream_tag; snd_hdac_ext_link_clear_stream_id(link, stream_tag); - snd_hdac_ext_stream_release(stream, - HDAC_EXT_STREAM_TYPE_LINK); stream->link_prepared = 0; } } -- GitLab From 810dbea3656912d6ad8db691a9a4b2ad97d4b736 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 22 Jul 2019 09:14:00 -0500 Subject: [PATCH 0308/7155] ASoC: SOF: Intel: hda: fix stream id setting snd_hdac_ext_link_clear_stream_id maps stream id to link output, which is for playback, not capture. Tested on Whiskey Lake platform. Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 15 +++++++++++---- sound/soc/sof/intel/hda-dsp.c | 8 +++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 2b5e2b8c69c2..8796f385be76 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -327,8 +327,12 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, DMA_CHAN_INVALID, substream->stream); if (ret < 0) return ret; - stream_tag = hdac_stream(link_dev)->stream_tag; - snd_hdac_ext_link_clear_stream_id(link, stream_tag); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + stream_tag = hdac_stream(link_dev)->stream_tag; + snd_hdac_ext_link_clear_stream_id(link, stream_tag); + } + link_dev->link_prepared = 0; /* fallthrough */ @@ -369,8 +373,11 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, if (!link) return -EINVAL; - stream_tag = hdac_stream(link_dev)->stream_tag; - snd_hdac_ext_link_clear_stream_id(link, stream_tag); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + stream_tag = hdac_stream(link_dev)->stream_tag; + snd_hdac_ext_link_clear_stream_id(link, stream_tag); + } + snd_soc_dai_set_dma_data(dai, substream, NULL); snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); link_dev->link_prepared = 0; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index e38008194574..fb55a3c5afd0 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -450,9 +450,15 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) link = snd_hdac_ext_bus_get_link(bus, name); if (!link) return -EINVAL; + + stream->link_prepared = 0; + + if (hdac_stream(stream)->direction == + SNDRV_PCM_STREAM_CAPTURE) + continue; + stream_tag = hdac_stream(stream)->stream_tag; snd_hdac_ext_link_clear_stream_id(link, stream_tag); - stream->link_prepared = 0; } } #endif -- GitLab From f90aa354be7bffaec2b440eb1831c429ecb1a5e2 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 22 Jul 2019 23:26:39 +0200 Subject: [PATCH 0309/7155] ASoC: rt5665: Fix a typo in the name of a function All function names start with rt5665_, except 'rt5655_set_verf()'. It is likely a typo. Fix it to be consistent. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190722212639.26954-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index c050d84a6916..68299ce26d3e 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -2566,7 +2566,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, return 0; } -static int rt5655_set_verf(struct snd_soc_dapm_widget *w, +static int rt5665_set_verf(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); @@ -2686,11 +2686,11 @@ static const struct snd_soc_dapm_widget rt5665_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL, RT5665_PWR_MIC_DET_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0, - rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0, - rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0, - rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), /* ASRC */ SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1, -- GitLab From a789adae592e3d28ae87902c0012a8b11c96eb79 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 23 Jul 2019 18:12:47 +0800 Subject: [PATCH 0310/7155] ASoC: rt1308: Convert headers to SPDX Convert include and source files to SPDX. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190723101247.19741-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 17 +++++++---------- sound/soc/codecs/rt1308.h | 6 ++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index cf3d72f99705..6f2ee6809dbb 100755 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -1,13 +1,10 @@ -/* - * rt1308.c -- RT1308 ALSA SoC amplifier component driver - * - * Copyright 2019 Realtek Semiconductor Corp. - * Author: Derek Fang - * - * 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. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// rt1308.c -- RT1308 ALSA SoC amplifier component driver +// +// Copyright 2019 Realtek Semiconductor Corp. +// Author: Derek Fang +// #include #include diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h index c330aae1d527..ff7c423e879e 100755 --- a/sound/soc/codecs/rt1308.h +++ b/sound/soc/codecs/rt1308.h @@ -1,12 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * RT1308.h -- RT1308 ALSA SoC amplifier component driver + * rt1308.h -- RT1308 ALSA SoC amplifier component driver * * Copyright 2019 Realtek Semiconductor Corp. * Author: Derek Fang * - * 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. */ #ifndef _RT1308_H_ -- GitLab From 2d09a79bf637f91d1bbfcfd4520e3639dd15897c Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Mon, 22 Jul 2019 21:14:18 -0400 Subject: [PATCH 0311/7155] regulator: act8865: Add support for act8600 charger This provides a way to monitor battery charge status via the power supply subsystem. Signed-off-by: Maarten ter Huurne Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20190723011418.29143-1-paul@crapouillou.net Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 84 +++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index cf72d7c6b8c9..e63285de485d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -118,6 +119,11 @@ #define ACT8600_LDO10_ENA 0x40 /* ON - [6] */ #define ACT8600_SUDCDC_VSEL_MASK 0xFF /* SUDCDC VSET - [7:0] */ +#define ACT8600_APCH_CHG_ACIN BIT(7) +#define ACT8600_APCH_CHG_USB BIT(6) +#define ACT8600_APCH_CSTATE0 BIT(5) +#define ACT8600_APCH_CSTATE1 BIT(4) + /* * ACT8865 voltage number */ @@ -372,6 +378,75 @@ static void act8865_power_off(void) while (1); } +static int act8600_charger_get_status(struct regmap *map) +{ + unsigned int val; + int ret; + u8 state0, state1; + + ret = regmap_read(map, ACT8600_APCH_STAT, &val); + if (ret < 0) + return ret; + + state0 = val & ACT8600_APCH_CSTATE0; + state1 = val & ACT8600_APCH_CSTATE1; + + if (state0 && !state1) + return POWER_SUPPLY_STATUS_CHARGING; + if (!state0 && state1) + return POWER_SUPPLY_STATUS_NOT_CHARGING; + if (!state0 && !state1) + return POWER_SUPPLY_STATUS_DISCHARGING; + + return POWER_SUPPLY_STATUS_UNKNOWN; +} + +static int act8600_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct regmap *map = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + ret = act8600_charger_get_status(map); + if (ret < 0) + return ret; + + val->intval = ret; + break; + default: + return -EINVAL; + } + + return 0; +} + +static enum power_supply_property act8600_charger_properties[] = { + POWER_SUPPLY_PROP_STATUS, +}; + +static const struct power_supply_desc act8600_charger_desc = { + .name = "act8600-charger", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = act8600_charger_properties, + .num_properties = ARRAY_SIZE(act8600_charger_properties), + .get_property = act8600_charger_get_property, +}; + +static int act8600_charger_probe(struct device *dev, struct regmap *regmap) +{ + struct power_supply *charger; + struct power_supply_config cfg = { + .drv_data = regmap, + .of_node = dev->of_node, + }; + + charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg); + + return IS_ERR(charger) ? PTR_ERR(charger) : 0; +} + static int act8865_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -483,6 +558,15 @@ static int act8865_pmic_probe(struct i2c_client *client, } } + if (type == ACT8600) { + ret = act8600_charger_probe(dev, act8865->regmap); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to probe charger"); + return ret; + } + } + i2c_set_clientdata(client, act8865); return 0; -- GitLab From 03b77f0b8587a9a0f9d2f1503da3d120aa6fe730 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 23 Jul 2019 09:41:02 +0800 Subject: [PATCH 0312/7155] regulator: stm32-booster: Remove .min_uV and .list_voltage for fixed regulator Setting .n_voltages = 1 and .fixed_uV is enough for fixed regulator, remove the redundant .min_uV and .list_voltage settings. Signed-off-by: Axel Lin Acked-by: Fabrice Gasnier Link: https://lore.kernel.org/r/20190723014102.25103-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/stm32-booster.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c index 2a897666c650..03f162ffd144 100644 --- a/drivers/regulator/stm32-booster.c +++ b/drivers/regulator/stm32-booster.c @@ -20,7 +20,6 @@ #define STM32MP1_SYSCFG_EN_BOOSTER_MASK BIT(8) static const struct regulator_ops stm32h7_booster_ops = { - .list_voltage = regulator_list_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -31,7 +30,6 @@ static const struct regulator_desc stm32h7_booster_desc = { .supply_name = "vdda", .n_voltages = 1, .type = REGULATOR_VOLTAGE, - .min_uV = 3300000, .fixed_uV = 3300000, .ramp_delay = 66000, /* up to 50us to stabilize */ .ops = &stm32h7_booster_ops, @@ -53,7 +51,6 @@ static int stm32mp1_booster_disable(struct regulator_dev *rdev) } static const struct regulator_ops stm32mp1_booster_ops = { - .list_voltage = regulator_list_voltage_linear, .enable = stm32mp1_booster_enable, .disable = stm32mp1_booster_disable, .is_enabled = regulator_is_enabled_regmap, @@ -64,7 +61,6 @@ static const struct regulator_desc stm32mp1_booster_desc = { .supply_name = "vdda", .n_voltages = 1, .type = REGULATOR_VOLTAGE, - .min_uV = 3300000, .fixed_uV = 3300000, .ramp_delay = 66000, .ops = &stm32mp1_booster_ops, -- GitLab From 701010532164eaacd415ec5683717da03f4b822d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 23 Jul 2019 20:26:45 +0900 Subject: [PATCH 0313/7155] x86/build: Remove unneeded uapi asm-generic wrappers These are listed in include/uapi/asm-generic/Kbuild, so Kbuild will automatically generate them. Signed-off-by: Masahiro Yamada Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190723112646.14046-1-yamada.masahiro@socionext.com --- arch/x86/include/uapi/asm/errno.h | 1 - arch/x86/include/uapi/asm/fcntl.h | 1 - arch/x86/include/uapi/asm/ioctl.h | 1 - arch/x86/include/uapi/asm/ioctls.h | 1 - arch/x86/include/uapi/asm/ipcbuf.h | 1 - arch/x86/include/uapi/asm/param.h | 1 - arch/x86/include/uapi/asm/resource.h | 1 - arch/x86/include/uapi/asm/termbits.h | 1 - arch/x86/include/uapi/asm/termios.h | 1 - arch/x86/include/uapi/asm/types.h | 7 ------- 10 files changed, 16 deletions(-) delete mode 100644 arch/x86/include/uapi/asm/errno.h delete mode 100644 arch/x86/include/uapi/asm/fcntl.h delete mode 100644 arch/x86/include/uapi/asm/ioctl.h delete mode 100644 arch/x86/include/uapi/asm/ioctls.h delete mode 100644 arch/x86/include/uapi/asm/ipcbuf.h delete mode 100644 arch/x86/include/uapi/asm/param.h delete mode 100644 arch/x86/include/uapi/asm/resource.h delete mode 100644 arch/x86/include/uapi/asm/termbits.h delete mode 100644 arch/x86/include/uapi/asm/termios.h delete mode 100644 arch/x86/include/uapi/asm/types.h diff --git a/arch/x86/include/uapi/asm/errno.h b/arch/x86/include/uapi/asm/errno.h deleted file mode 100644 index 4c82b503d92f..000000000000 --- a/arch/x86/include/uapi/asm/errno.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/fcntl.h b/arch/x86/include/uapi/asm/fcntl.h deleted file mode 100644 index 46ab12db5739..000000000000 --- a/arch/x86/include/uapi/asm/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/ioctl.h b/arch/x86/include/uapi/asm/ioctl.h deleted file mode 100644 index b279fe06dfe5..000000000000 --- a/arch/x86/include/uapi/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/ioctls.h b/arch/x86/include/uapi/asm/ioctls.h deleted file mode 100644 index ec34c760665e..000000000000 --- a/arch/x86/include/uapi/asm/ioctls.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/ipcbuf.h b/arch/x86/include/uapi/asm/ipcbuf.h deleted file mode 100644 index 84c7e51cb6d0..000000000000 --- a/arch/x86/include/uapi/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/param.h b/arch/x86/include/uapi/asm/param.h deleted file mode 100644 index 965d45427975..000000000000 --- a/arch/x86/include/uapi/asm/param.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/resource.h b/arch/x86/include/uapi/asm/resource.h deleted file mode 100644 index 04bc4db8921b..000000000000 --- a/arch/x86/include/uapi/asm/resource.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/termbits.h b/arch/x86/include/uapi/asm/termbits.h deleted file mode 100644 index 3935b106de79..000000000000 --- a/arch/x86/include/uapi/asm/termbits.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/termios.h b/arch/x86/include/uapi/asm/termios.h deleted file mode 100644 index 280d78a9d966..000000000000 --- a/arch/x86/include/uapi/asm/termios.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/include/uapi/asm/types.h b/arch/x86/include/uapi/asm/types.h deleted file mode 100644 index df55e1ddb0c9..000000000000 --- a/arch/x86/include/uapi/asm/types.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_X86_TYPES_H -#define _ASM_X86_TYPES_H - -#include - -#endif /* _ASM_X86_TYPES_H */ -- GitLab From bdd50d7421b2f8fd99f953e1f747e0cb3f3bed64 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 23 Jul 2019 16:44:15 +0900 Subject: [PATCH 0314/7155] x86/bitops: Use __builtin_constant_p() directly instead of IS_IMMEDIATE() __builtin_constant_p(nr) is used everywhere now. It does not make much sense to define IS_IMMEDIATE() as its alias. Signed-off-by: Masahiro Yamada Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190723074415.26811-1-yamada.masahiro@socionext.com --- arch/x86/include/asm/bitops.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index ba15d53c1ca7..7d1f6a49bfae 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -45,14 +45,13 @@ * We do the locked ops that don't return the old value as * a mask operation on a byte. */ -#define IS_IMMEDIATE(nr) (__builtin_constant_p(nr)) #define CONST_MASK_ADDR(nr, addr) WBYTE_ADDR((void *)(addr) + ((nr)>>3)) #define CONST_MASK(nr) (1 << ((nr) & 7)) static __always_inline void arch_set_bit(long nr, volatile unsigned long *addr) { - if (IS_IMMEDIATE(nr)) { + if (__builtin_constant_p(nr)) { asm volatile(LOCK_PREFIX "orb %1,%0" : CONST_MASK_ADDR(nr, addr) : "iq" ((u8)CONST_MASK(nr)) @@ -72,7 +71,7 @@ arch___set_bit(long nr, volatile unsigned long *addr) static __always_inline void arch_clear_bit(long nr, volatile unsigned long *addr) { - if (IS_IMMEDIATE(nr)) { + if (__builtin_constant_p(nr)) { asm volatile(LOCK_PREFIX "andb %1,%0" : CONST_MASK_ADDR(nr, addr) : "iq" ((u8)~CONST_MASK(nr))); @@ -123,7 +122,7 @@ arch___change_bit(long nr, volatile unsigned long *addr) static __always_inline void arch_change_bit(long nr, volatile unsigned long *addr) { - if (IS_IMMEDIATE(nr)) { + if (__builtin_constant_p(nr)) { asm volatile(LOCK_PREFIX "xorb %1,%0" : CONST_MASK_ADDR(nr, addr) : "iq" ((u8)CONST_MASK(nr))); -- GitLab From 967b109096b2c2b7ef45a3fce44908efe05779a9 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 23 Jul 2019 10:07:40 +1000 Subject: [PATCH 0315/7155] media: uapi: new file needs types.h Today's linux-next build (x86_64 allmodconfig) failed like this: include/media/vp8-ctrls.h:25:2: error: unknown type name '__s8' __s8 quant_update[4]; ^~~~ ... include/media/vp8-ctrls.h:107:2: error: unknown type name '__u64' __u64 flags; ^~~~~ Caused by commit a57d6acaf352 ("media: uapi: Add VP8 stateless decoder API") Fixes: a57d6acaf352 ("media: uapi: Add VP8 stateless decoder API") Signed-off-by: Stephen Rothwell Signed-off-by: Mauro Carvalho Chehab --- include/media/vp8-ctrls.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/media/vp8-ctrls.h b/include/media/vp8-ctrls.h index 6cc2eeea4c90..53cba826e482 100644 --- a/include/media/vp8-ctrls.h +++ b/include/media/vp8-ctrls.h @@ -11,6 +11,8 @@ #ifndef _VP8_CTRLS_H_ #define _VP8_CTRLS_H_ +#include + #define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') #define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000) -- GitLab From 20958f9d5c48bf1606cdd7f00d0c1c6cd653b758 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Jun 2019 11:01:20 -0400 Subject: [PATCH 0316/7155] media: meson/ao-cec: use cec_notifier_cec_adap_(un)register Use the new cec_notifier_cec_adap_(un)register() functions to (un)register the notifier for the CEC adapter. Signed-off-by: Hans Verkuil Cc: Neil Armstrong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/meson/ao-cec-g12a.c | 48 +++++++++++----------- drivers/media/platform/meson/ao-cec.c | 44 +++++++++----------- 2 files changed, 42 insertions(+), 50 deletions(-) diff --git a/drivers/media/platform/meson/ao-cec-g12a.c b/drivers/media/platform/meson/ao-cec-g12a.c index fb52e5dd044a..c99d01926673 100644 --- a/drivers/media/platform/meson/ao-cec-g12a.c +++ b/drivers/media/platform/meson/ao-cec-g12a.c @@ -635,17 +635,19 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev) spin_lock_init(&ao_cec->cec_reg_lock); ao_cec->pdev = pdev; - ao_cec->notify = cec_notifier_get(hdmi_dev); - if (!ao_cec->notify) - return -ENOMEM; - ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec, "meson_g12a_ao_cec", - CEC_CAP_DEFAULTS, + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, CEC_MAX_LOG_ADDRS); - if (IS_ERR(ao_cec->adap)) { - ret = PTR_ERR(ao_cec->adap); - goto out_probe_notify; + if (IS_ERR(ao_cec->adap)) + return PTR_ERR(ao_cec->adap); + + ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL, + ao_cec->adap); + if (!ao_cec->notify) { + ret = -ENOMEM; + goto out_probe_adapter; } ao_cec->adap->owner = THIS_MODULE; @@ -654,21 +656,21 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev) base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); - goto out_probe_adapter; + goto out_probe_notify; } ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base, &meson_ao_cec_g12a_regmap_conf); if (IS_ERR(ao_cec->regmap)) { ret = PTR_ERR(ao_cec->regmap); - goto out_probe_adapter; + goto out_probe_notify; } ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec, &meson_ao_cec_g12a_cec_regmap_conf); if (IS_ERR(ao_cec->regmap_cec)) { ret = PTR_ERR(ao_cec->regmap_cec); - goto out_probe_adapter; + goto out_probe_notify; } irq = platform_get_irq(pdev, 0); @@ -678,24 +680,24 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev) 0, NULL, ao_cec); if (ret) { dev_err(&pdev->dev, "irq request failed\n"); - goto out_probe_adapter; + goto out_probe_notify; } ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin"); if (IS_ERR(ao_cec->oscin)) { dev_err(&pdev->dev, "oscin clock request failed\n"); ret = PTR_ERR(ao_cec->oscin); - goto out_probe_adapter; + goto out_probe_notify; } ret = meson_ao_cec_g12a_setup_clk(ao_cec); if (ret) - goto out_probe_adapter; + goto out_probe_notify; ret = clk_prepare_enable(ao_cec->core); if (ret) { dev_err(&pdev->dev, "core clock enable failed\n"); - goto out_probe_adapter; + goto out_probe_notify; } device_reset_optional(&pdev->dev); @@ -703,27 +705,23 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ao_cec); ret = cec_register_adapter(ao_cec->adap, &pdev->dev); - if (ret < 0) { - cec_notifier_put(ao_cec->notify); + if (ret < 0) goto out_probe_core_clk; - } /* Setup Hardware */ regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET); - cec_register_cec_notifier(ao_cec->adap, ao_cec->notify); - return 0; out_probe_core_clk: clk_disable_unprepare(ao_cec->core); +out_probe_notify: + cec_notifier_cec_adap_unregister(ao_cec->notify); + out_probe_adapter: cec_delete_adapter(ao_cec->adap); -out_probe_notify: - cec_notifier_put(ao_cec->notify); - dev_err(&pdev->dev, "CEC controller registration failed\n"); return ret; @@ -735,9 +733,9 @@ static int meson_ao_cec_g12a_remove(struct platform_device *pdev) clk_disable_unprepare(ao_cec->core); - cec_unregister_adapter(ao_cec->adap); + cec_notifier_cec_adap_unregister(ao_cec->notify); - cec_notifier_put(ao_cec->notify); + cec_unregister_adapter(ao_cec->adap); return 0; } diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c index facf9b029e79..64ed549bf012 100644 --- a/drivers/media/platform/meson/ao-cec.c +++ b/drivers/media/platform/meson/ao-cec.c @@ -616,20 +616,19 @@ static int meson_ao_cec_probe(struct platform_device *pdev) spin_lock_init(&ao_cec->cec_reg_lock); - ao_cec->notify = cec_notifier_get(hdmi_dev); - if (!ao_cec->notify) - return -ENOMEM; - ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec, "meson_ao_cec", - CEC_CAP_LOG_ADDRS | - CEC_CAP_TRANSMIT | - CEC_CAP_RC | - CEC_CAP_PASSTHROUGH, + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, 1); /* Use 1 for now */ - if (IS_ERR(ao_cec->adap)) { - ret = PTR_ERR(ao_cec->adap); - goto out_probe_notify; + if (IS_ERR(ao_cec->adap)) + return PTR_ERR(ao_cec->adap); + + ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL, + ao_cec->adap); + if (!ao_cec->notify) { + ret = -ENOMEM; + goto out_probe_adapter; } ao_cec->adap->owner = THIS_MODULE; @@ -638,7 +637,7 @@ static int meson_ao_cec_probe(struct platform_device *pdev) ao_cec->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ao_cec->base)) { ret = PTR_ERR(ao_cec->base); - goto out_probe_adapter; + goto out_probe_notify; } irq = platform_get_irq(pdev, 0); @@ -648,20 +647,20 @@ static int meson_ao_cec_probe(struct platform_device *pdev) 0, NULL, ao_cec); if (ret) { dev_err(&pdev->dev, "irq request failed\n"); - goto out_probe_adapter; + goto out_probe_notify; } ao_cec->core = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(ao_cec->core)) { dev_err(&pdev->dev, "core clock request failed\n"); ret = PTR_ERR(ao_cec->core); - goto out_probe_adapter; + goto out_probe_notify; } ret = clk_prepare_enable(ao_cec->core); if (ret) { dev_err(&pdev->dev, "core clock enable failed\n"); - goto out_probe_adapter; + goto out_probe_notify; } ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE); @@ -676,28 +675,24 @@ static int meson_ao_cec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ao_cec); ret = cec_register_adapter(ao_cec->adap, &pdev->dev); - if (ret < 0) { - cec_notifier_put(ao_cec->notify); + if (ret < 0) goto out_probe_clk; - } /* Setup Hardware */ writel_relaxed(CEC_GEN_CNTL_RESET, ao_cec->base + CEC_GEN_CNTL_REG); - cec_register_cec_notifier(ao_cec->adap, ao_cec->notify); - return 0; out_probe_clk: clk_disable_unprepare(ao_cec->core); +out_probe_notify: + cec_notifier_cec_adap_unregister(ao_cec->notify); + out_probe_adapter: cec_delete_adapter(ao_cec->adap); -out_probe_notify: - cec_notifier_put(ao_cec->notify); - dev_err(&pdev->dev, "CEC controller registration failed\n"); return ret; @@ -709,10 +704,9 @@ static int meson_ao_cec_remove(struct platform_device *pdev) clk_disable_unprepare(ao_cec->core); + cec_notifier_cec_adap_unregister(ao_cec->notify); cec_unregister_adapter(ao_cec->adap); - cec_notifier_put(ao_cec->notify); - return 0; } -- GitLab From e6777689406545611d1bda4f716a56a3961bc7f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Jul 2019 06:04:30 -0400 Subject: [PATCH 0317/7155] media: cros-ec-cec: use cec_notifier_cec_adap_(un)register Use cec_notifier_cec_adap_(un)register instead of cec_notifier_get_conn, cec_notifier_put and cec_register_cec_notifier. Also enable the CEC_CAP_CONNECTOR_INFO capability. Signed-off-by: Hans Verkuil Cc: Neil Armstrong Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/cros-ec-cec/cros-ec-cec.c | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c index 068df9888dbf..76ab83f55cc0 100644 --- a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c +++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c @@ -206,10 +206,10 @@ static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, */ struct cec_dmi_match { - char *sys_vendor; - char *product_name; - char *devname; - char *conn; + const char *sys_vendor; + const char *product_name; + const char *devname; + const char *conn; }; static const struct cec_dmi_match cec_dmi_match_table[] = { @@ -217,8 +217,8 @@ static const struct cec_dmi_match cec_dmi_match_table[] = { { "Google", "Fizz", "0000:00:02.0", "Port B" }, }; -static int cros_ec_cec_get_notifier(struct device *dev, - struct cec_notifier **notify) +static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, + const char **conn) { int i; @@ -233,26 +233,25 @@ static int cros_ec_cec_get_notifier(struct device *dev, d = bus_find_device_by_name(&pci_bus_type, NULL, m->devname); if (!d) - return -EPROBE_DEFER; - - *notify = cec_notifier_get_conn(d, m->conn); + return ERR_PTR(-EPROBE_DEFER); put_device(d); - return 0; + *conn = m->conn; + return d; } } /* Hardware support must be added in the cec_dmi_match_table */ dev_warn(dev, "CEC notifier not configured for this hardware\n"); - return -ENODEV; + return ERR_PTR(-ENODEV); } #else -static int cros_ec_cec_get_notifier(struct device *dev, - struct cec_notifier **notify) +static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, + const char **conn) { - return -ENODEV; + return ERR_PTR(-ENODEV); } #endif @@ -262,8 +261,14 @@ static int cros_ec_cec_probe(struct platform_device *pdev) struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); struct cros_ec_device *cros_ec = ec_dev->ec_dev; struct cros_ec_cec *cros_ec_cec; + struct device *hdmi_dev; + const char *conn = NULL; int ret; + hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn); + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); + cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), GFP_KERNEL); if (!cros_ec_cec) @@ -272,10 +277,6 @@ static int cros_ec_cec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cros_ec_cec); cros_ec_cec->cros_ec = cros_ec; - ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify); - if (ret) - return ret; - ret = device_init_wakeup(&pdev->dev, 1); if (ret) { dev_err(&pdev->dev, "failed to initialize wakeup\n"); @@ -283,29 +284,39 @@ static int cros_ec_cec_probe(struct platform_device *pdev) } cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, - DRV_NAME, CEC_CAP_DEFAULTS, 1); + DRV_NAME, + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, 1); if (IS_ERR(cros_ec_cec->adap)) return PTR_ERR(cros_ec_cec->adap); + cros_ec_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, conn, + cros_ec_cec->adap); + if (!cros_ec_cec->notify) { + ret = -ENOMEM; + goto out_probe_adapter; + } + /* Get CEC events from the EC. */ cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; ret = blocking_notifier_chain_register(&cros_ec->event_notifier, &cros_ec_cec->notifier); if (ret) { dev_err(&pdev->dev, "failed to register notifier\n"); - cec_delete_adapter(cros_ec_cec->adap); - return ret; + goto out_probe_notify; } ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev); - if (ret < 0) { - cec_delete_adapter(cros_ec_cec->adap); - return ret; - } - - cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify); + if (ret < 0) + goto out_probe_notify; return 0; + +out_probe_notify: + cec_notifier_cec_adap_unregister(cros_ec_cec->notify); +out_probe_adapter: + cec_delete_adapter(cros_ec_cec->adap); + return ret; } static int cros_ec_cec_remove(struct platform_device *pdev) @@ -323,11 +334,9 @@ static int cros_ec_cec_remove(struct platform_device *pdev) return ret; } + cec_notifier_cec_adap_unregister(cros_ec_cec->notify); cec_unregister_adapter(cros_ec_cec->adap); - if (cros_ec_cec->notify) - cec_notifier_put(cros_ec_cec->notify); - return 0; } -- GitLab From 276c821f77317211fbf15c0ebf24e26ebf6bf985 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Jul 2019 06:07:07 -0400 Subject: [PATCH 0318/7155] media: seco-cec: use cec_notifier_cec_adap_(un)register Use cec_notifier_cec_adap_(un)register instead of cec_notifier_get_conn, cec_notifier_put and cec_register_cec_notifier. Also enable the CEC_CAP_CONNECTOR_INFO capability. Signed-off-by: Hans Verkuil Cc: Ettore Chimenti Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/seco-cec/seco-cec.c | 55 ++++++++++++---------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/seco-cec/seco-cec.c b/drivers/media/platform/seco-cec/seco-cec.c index 1d0133f01e00..9cd60fe1867c 100644 --- a/drivers/media/platform/seco-cec/seco-cec.c +++ b/drivers/media/platform/seco-cec/seco-cec.c @@ -507,10 +507,10 @@ static irqreturn_t secocec_irq_handler(int irq, void *priv) } struct cec_dmi_match { - char *sys_vendor; - char *product_name; - char *devname; - char *conn; + const char *sys_vendor; + const char *product_name; + const char *devname; + const char *conn; }; static const struct cec_dmi_match secocec_dmi_match_table[] = { @@ -518,7 +518,8 @@ static const struct cec_dmi_match secocec_dmi_match_table[] = { { "SECO", "UDOO x86", "0000:00:02.0", "Port B" }, }; -static int secocec_cec_get_notifier(struct cec_notifier **notify) +static struct device *secocec_cec_find_hdmi_dev(struct device *dev, + const char **conn) { int i; @@ -533,16 +534,15 @@ static int secocec_cec_get_notifier(struct cec_notifier **notify) d = bus_find_device_by_name(&pci_bus_type, NULL, m->devname); if (!d) - return -EPROBE_DEFER; + return ERR_PTR(-EPROBE_DEFER); - *notify = cec_notifier_get_conn(d, m->conn); put_device(d); - - return 0; + *conn = m->conn; + return d; } } - return -EINVAL; + return ERR_PTR(-EINVAL); } static int secocec_acpi_probe(struct secocec_data *sdev) @@ -573,9 +573,15 @@ static int secocec_probe(struct platform_device *pdev) { struct secocec_data *secocec; struct device *dev = &pdev->dev; + struct device *hdmi_dev; + const char *conn = NULL; int ret; u16 val; + hdmi_dev = secocec_cec_find_hdmi_dev(&pdev->dev, &conn); + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); + secocec = devm_kzalloc(dev, sizeof(*secocec), GFP_KERNEL); if (!secocec) return -ENOMEM; @@ -617,12 +623,6 @@ static int secocec_probe(struct platform_device *pdev) goto err; } - ret = secocec_cec_get_notifier(&secocec->notifier); - if (ret) { - dev_err(dev, "no CEC notifier available\n"); - goto err; - } - ret = devm_request_threaded_irq(dev, secocec->irq, NULL, @@ -640,7 +640,8 @@ static int secocec_probe(struct platform_device *pdev) secocec->cec_adap = cec_allocate_adapter(&secocec_cec_adap_ops, secocec, dev_name(dev), - CEC_CAP_DEFAULTS, + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, SECOCEC_MAX_ADDRS); if (IS_ERR(secocec->cec_adap)) { @@ -648,16 +649,20 @@ static int secocec_probe(struct platform_device *pdev) goto err; } - ret = cec_register_adapter(secocec->cec_adap, dev); - if (ret) + secocec->notifier = cec_notifier_cec_adap_register(hdmi_dev, conn, + secocec->cec_adap); + if (!secocec->notifier) { + ret = -ENOMEM; goto err_delete_adapter; + } - if (secocec->notifier) - cec_register_cec_notifier(secocec->cec_adap, secocec->notifier); + ret = cec_register_adapter(secocec->cec_adap, dev); + if (ret) + goto err_notifier; ret = secocec_ir_probe(secocec); if (ret) - goto err_delete_adapter; + goto err_notifier; platform_set_drvdata(pdev, secocec); @@ -665,6 +670,8 @@ static int secocec_probe(struct platform_device *pdev) return ret; +err_notifier: + cec_notifier_cec_adap_unregister(secocec->notifier); err_delete_adapter: cec_delete_adapter(secocec->cec_adap); err: @@ -685,11 +692,9 @@ static int secocec_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "IR disabled"); } + cec_notifier_cec_adap_unregister(secocec->notifier); cec_unregister_adapter(secocec->cec_adap); - if (secocec->notifier) - cec_notifier_put(secocec->notifier); - release_region(BRA_SMB_BASE_ADDR, 7); dev_dbg(&pdev->dev, "CEC device removed"); -- GitLab From ca3cc03b7138c4162895318e6ae915cf26eea763 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Jul 2019 06:08:35 -0400 Subject: [PATCH 0319/7155] media: s5p-cec: use cec_notifier_cec_adap_(un)register Use cec_notifier_cec_adap_(un)register instead of cec_notifier_get, cec_notifier_put and cec_register_cec_notifier. Also enable the CEC_CAP_CONNECTOR_INFO capability. Signed-off-by: Hans Verkuil Cc: Marek Szyprowski Cc: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-cec/s5p_cec.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c index ea6231b387ed..6ddcc35b0bbd 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.c +++ b/drivers/media/platform/s5p-cec/s5p_cec.c @@ -214,21 +214,23 @@ static int s5p_cec_probe(struct platform_device *pdev) if (IS_ERR(cec->reg)) return PTR_ERR(cec->reg); - cec->notifier = cec_notifier_get(hdmi_dev); - if (cec->notifier == NULL) - return -ENOMEM; - cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME, - CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0), 1); + CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0) | + CEC_CAP_CONNECTOR_INFO, 1); ret = PTR_ERR_OR_ZERO(cec->adap); if (ret) return ret; - ret = cec_register_adapter(cec->adap, &pdev->dev); - if (ret) + cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL, + cec->adap); + if (!cec->notifier) { + ret = -ENOMEM; goto err_delete_adapter; + } - cec_register_cec_notifier(cec->adap, cec->notifier); + ret = cec_register_adapter(cec->adap, &pdev->dev); + if (ret) + goto err_notifier; platform_set_drvdata(pdev, cec); pm_runtime_enable(dev); @@ -236,6 +238,9 @@ static int s5p_cec_probe(struct platform_device *pdev) dev_dbg(dev, "successfully probed\n"); return 0; +err_notifier: + cec_notifier_cec_adap_unregister(cec->notifier); + err_delete_adapter: cec_delete_adapter(cec->adap); return ret; @@ -245,8 +250,8 @@ static int s5p_cec_remove(struct platform_device *pdev) { struct s5p_cec_dev *cec = platform_get_drvdata(pdev); + cec_notifier_cec_adap_unregister(cec->notifier); cec_unregister_adapter(cec->adap); - cec_notifier_put(cec->notifier); pm_runtime_disable(&pdev->dev); return 0; } -- GitLab From 72a171d72aa66b3d0b52889a08effd73fb3e5c5f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Jul 2019 06:08:53 -0400 Subject: [PATCH 0320/7155] media: stih-cec: use cec_notifier_cec_adap_(un)register Use cec_notifier_cec_adap_(un)register instead of cec_notifier_get, cec_notifier_put and cec_register_cec_notifier. Also enable the CEC_CAP_CONNECTOR_INFO capability. Signed-off-by: Hans Verkuil Cc: Benjamin Gaignard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/cec/stih-cec.c | 32 ++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/sti/cec/stih-cec.c b/drivers/media/platform/sti/cec/stih-cec.c index fc37efe1d554..8118c7365d3f 100644 --- a/drivers/media/platform/sti/cec/stih-cec.c +++ b/drivers/media/platform/sti/cec/stih-cec.c @@ -313,10 +313,6 @@ static int stih_cec_probe(struct platform_device *pdev) if (!cec) return -ENOMEM; - cec->notifier = cec_notifier_get(hdmi_dev); - if (!cec->notifier) - return -ENOMEM; - cec->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -340,30 +336,42 @@ static int stih_cec_probe(struct platform_device *pdev) return PTR_ERR(cec->clk); } - cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, - CEC_NAME, CEC_CAP_DEFAULTS, CEC_MAX_LOG_ADDRS); + cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME, + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, + CEC_MAX_LOG_ADDRS); ret = PTR_ERR_OR_ZERO(cec->adap); if (ret) return ret; - ret = cec_register_adapter(cec->adap, &pdev->dev); - if (ret) { - cec_delete_adapter(cec->adap); - return ret; + cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL, + cec->adap); + if (!cec->notifier) { + ret = -ENOMEM; + goto err_delete_adapter; } - cec_register_cec_notifier(cec->adap, cec->notifier); + ret = cec_register_adapter(cec->adap, &pdev->dev); + if (ret) + goto err_notifier; platform_set_drvdata(pdev, cec); return 0; + +err_notifier: + cec_notifier_cec_adap_unregister(cec->notifier); + +err_delete_adapter: + cec_delete_adapter(cec->adap); + return ret; } static int stih_cec_remove(struct platform_device *pdev) { struct stih_cec *cec = platform_get_drvdata(pdev); + cec_notifier_cec_adap_unregister(cec->notifier); cec_unregister_adapter(cec->adap); - cec_notifier_put(cec->notifier); return 0; } -- GitLab From ebe15c7679680308268b99d911b1db15d514c7b8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Jul 2019 06:09:06 -0400 Subject: [PATCH 0321/7155] media: tegra-cec: use cec_notifier_cec_adap_(un)register Use cec_notifier_cec_adap_(un)register instead of cec_notifier_get, cec_notifier_put and cec_register_cec_notifier. Also enable the CEC_CAP_CONNECTOR_INFO capability. Signed-off-by: Hans Verkuil Cc: Thierry Reding Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/tegra-cec/tegra_cec.c | 35 ++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c index 6498b2d0492e..a632602131f2 100644 --- a/drivers/media/platform/tegra-cec/tegra_cec.c +++ b/drivers/media/platform/tegra-cec/tegra_cec.c @@ -380,38 +380,39 @@ static int tegra_cec_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Unable to request interrupt for device\n"); - goto clk_error; - } - - cec->notifier = cec_notifier_get(hdmi_dev); - if (!cec->notifier) { - ret = -ENOMEM; - goto clk_error; + goto err_clk; } cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME, - CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, + CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | + CEC_CAP_CONNECTOR_INFO, CEC_MAX_LOG_ADDRS); if (IS_ERR(cec->adap)) { ret = -ENOMEM; dev_err(&pdev->dev, "Couldn't create cec adapter\n"); - goto cec_error; + goto err_clk; + } + + cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL, + cec->adap); + if (!cec->notifier) { + ret = -ENOMEM; + goto err_adapter; } + ret = cec_register_adapter(cec->adap, &pdev->dev); if (ret) { dev_err(&pdev->dev, "Couldn't register device\n"); - goto cec_error; + goto err_notifier; } - cec_register_cec_notifier(cec->adap, cec->notifier); - return 0; -cec_error: - if (cec->notifier) - cec_notifier_put(cec->notifier); +err_notifier: + cec_notifier_cec_adap_unregister(cec->notifier); +err_adapter: cec_delete_adapter(cec->adap); -clk_error: +err_clk: clk_disable_unprepare(cec->clk); return ret; } @@ -422,8 +423,8 @@ static int tegra_cec_remove(struct platform_device *pdev) clk_disable_unprepare(cec->clk); + cec_notifier_cec_adap_unregister(cec->notifier); cec_unregister_adapter(cec->adap); - cec_notifier_put(cec->notifier); return 0; } -- GitLab From 999a4312e871d9674f2ac8734820b8a242a0783f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 05:48:18 -0400 Subject: [PATCH 0322/7155] media: v4l2-ioctl: call v4l_pix_format_touch() for TRY_FMT The function v4l_pix_format_touch() is called for S_FMT to set v4l2_pix_format fields to default values for a v4l-touch device, but it wasn't called for TRY_FMT. Add this. Signed-off-by: Hans Verkuil Reviewed-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 80efc581e3f9..e36629ae2203 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1663,6 +1663,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_format *p = arg; + struct video_device *vfd = video_devdata(file); int ret = check_fmt(file, p->type); unsigned int i; @@ -1679,6 +1680,8 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + if (vfd->vfl_type == VFL_TYPE_TOUCH) + v4l_pix_format_touch(&p->fmt.pix); return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) -- GitLab From 43266ad2b47db87b91f3198afa5ad61a4206c253 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 05:52:16 -0400 Subject: [PATCH 0323/7155] media: input/touchscreen/sur40: use COLORSPACE_RAW This driver set the colorspace to SRGB, but that makes no sense for a touchscreen. Use RAW instead. This also ensures consistency with the v4l_pix_format_touch() call that's used in v4l2-ioctl.c. Signed-off-by: Hans Verkuil Acked-by: Florian Echtler Acked-by: Dmitry Torokhov Signed-off-by: Mauro Carvalho Chehab --- drivers/input/touchscreen/sur40.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 00cb1ba2d364..3fd3e862269b 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -186,7 +186,7 @@ static const struct v4l2_pix_format sur40_pix_format[] = { .width = SENSOR_RES_X / 2, .height = SENSOR_RES_Y / 2, .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_SRGB, + .colorspace = V4L2_COLORSPACE_RAW, .bytesperline = SENSOR_RES_X / 2, .sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2), }, @@ -195,7 +195,7 @@ static const struct v4l2_pix_format sur40_pix_format[] = { .width = SENSOR_RES_X / 2, .height = SENSOR_RES_Y / 2, .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_SRGB, + .colorspace = V4L2_COLORSPACE_RAW, .bytesperline = SENSOR_RES_X / 2, .sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2), } -- GitLab From 8d86a15649957c182e90fa2b1267c16699bc12f1 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Thu, 27 Jun 2019 08:44:32 -0400 Subject: [PATCH 0324/7155] media: vb2: reorder checks in vb2_poll() When reaching the end of stream, V4L2 clients may expect the V4L2_EOS_EVENT before being able to dequeue the last buffer, which has the V4L2_BUF_FLAG_LAST flag set. If the vb2_poll() function first checks for events and afterwards if buffers are available, a driver can queue the V4L2_EOS_EVENT event and return the buffer after the check for events but before the check for buffers. This causes vb2_poll() to signal that the buffer with V4L2_BUF_FLAG_LAST can be read without the V4L2_EOS_EVENT being available. First, check for available buffers and afterwards for events to ensure that if vb2_poll() signals POLLIN | POLLRDNORM for the V4L2_BUF_FLAG_LAST buffer, it also signals POLLPRI for the V4L2_EOS_EVENT. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 40d76eb4c2fe..5a9ba3846f0a 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -872,17 +872,19 @@ EXPORT_SYMBOL_GPL(vb2_queue_release); __poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { struct video_device *vfd = video_devdata(file); - __poll_t res = 0; + __poll_t res; + + res = vb2_core_poll(q, file, wait); if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { struct v4l2_fh *fh = file->private_data; poll_wait(file, &fh->wait, wait); if (v4l2_event_pending(fh)) - res = EPOLLPRI; + res |= EPOLLPRI; } - return res | vb2_core_poll(q, file, wait); + return res; } EXPORT_SYMBOL_GPL(vb2_poll); -- GitLab From 7708065f5d51a9ae80df29d1257d91fc6a6e50a0 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Thu, 27 Jun 2019 08:44:33 -0400 Subject: [PATCH 0325/7155] media: v4l2-mem2mem: reorder checks in v4l2_m2m_poll() When reaching the end of stream, V4L2 m2m clients may expect the V4L2_EOS_EVENT. Although the V4L2_EOS_EVENT is deprecated behavior, drivers must signal that event before dequeuing the buffer that has the V4L2_BUF_FLAG_LAST flag set. If a driver queues the V4L2_EOS_EVENT event and returns the buffer after the check for events but before the check for buffers, vb2_m2m_poll() will signal that the buffer with V4L2_BUF_FLAG_LAST can be read but not that the V4L2_EOS_EVENT is available. Split the check for buffers into a separate function and check for available buffers before checking for events. This ensures that if vb2_m2m_poll() signals POLLIN | POLLRDNORM for the V4L2_BUF_FLAG_LAST buffer, it signals POLLPRI for the V4L2_EOS_EVENT, too. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix checkpatch alignment warning] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mem2mem.c | 47 +++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 4f5176702937..19937dd3c6f6 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -603,11 +603,10 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, } EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); -__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, - struct poll_table_struct *wait) +static __poll_t v4l2_m2m_poll_for_data(struct file *file, + struct v4l2_m2m_ctx *m2m_ctx, + struct poll_table_struct *wait) { - struct video_device *vfd = video_devdata(file); - __poll_t req_events = poll_requested_events(wait); struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; __poll_t rc = 0; @@ -619,16 +618,6 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, poll_wait(file, &src_q->done_wq, wait); poll_wait(file, &dst_q->done_wq, wait); - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { - struct v4l2_fh *fh = file->private_data; - - poll_wait(file, &fh->wait, wait); - if (v4l2_event_pending(fh)) - rc = EPOLLPRI; - if (!(req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | EPOLLRDNORM))) - return rc; - } - /* * There has to be at least one buffer queued on each queued_list, which * means either in driver already or waiting for driver to claim it @@ -637,10 +626,8 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, if ((!src_q->streaming || src_q->error || list_empty(&src_q->queued_list)) && (!dst_q->streaming || dst_q->error || - list_empty(&dst_q->queued_list))) { - rc |= EPOLLERR; - goto end; - } + list_empty(&dst_q->queued_list))) + return EPOLLERR; spin_lock_irqsave(&dst_q->done_lock, flags); if (list_empty(&dst_q->done_list)) { @@ -650,7 +637,7 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, */ if (dst_q->last_buffer_dequeued) { spin_unlock_irqrestore(&dst_q->done_lock, flags); - return rc | EPOLLIN | EPOLLRDNORM; + return EPOLLIN | EPOLLRDNORM; } } spin_unlock_irqrestore(&dst_q->done_lock, flags); @@ -673,7 +660,27 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, rc |= EPOLLIN | EPOLLRDNORM; spin_unlock_irqrestore(&dst_q->done_lock, flags); -end: + return rc; +} + +__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct poll_table_struct *wait) +{ + struct video_device *vfd = video_devdata(file); + __poll_t req_events = poll_requested_events(wait); + __poll_t rc = 0; + + if (req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | EPOLLRDNORM)) + rc = v4l2_m2m_poll_for_data(file, m2m_ctx, wait); + + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { + struct v4l2_fh *fh = file->private_data; + + poll_wait(file, &fh->wait, wait); + if (v4l2_event_pending(fh)) + rc |= EPOLLPRI; + } + return rc; } EXPORT_SYMBOL_GPL(v4l2_m2m_poll); -- GitLab From b61789f53d49db8ca1f6b8fed411b317b4e8f044 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Jun 2019 05:58:02 -0400 Subject: [PATCH 0326/7155] media: drivers/media: don't set pix->priv = 0 The priv field of struct v4l2_pix_format shouldn't be set by drivers, it's set by the v4l2 core instead to V4L2_PIX_FMT_PRIV_MAGIC. Drop this from the few media drivers that still do this. Note that the gspca patch is slightly more involved since some of the sub-gspca drivers use the priv field internally. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart [hverkuil-cisco@xs4all.nl: fix clash in gspca between priv arg and priv variable] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/cobalt-v4l2.c | 1 - .../media/pci/solo6x10/solo6x10-v4l2-enc.c | 2 -- drivers/media/pci/solo6x10/solo6x10-v4l2.c | 2 -- drivers/media/pci/tw68/tw68-video.c | 1 - drivers/media/platform/davinci/vpif_capture.c | 1 - drivers/media/usb/au0828/au0828-video.c | 2 -- drivers/media/usb/cpia2/cpia2_v4l.c | 2 -- drivers/media/usb/em28xx/em28xx-video.c | 1 - drivers/media/usb/gspca/gspca.c | 28 ++++++++++--------- drivers/media/usb/s2255/s2255drv.c | 2 -- drivers/media/usb/uvc/uvc_v4l2.c | 2 -- 11 files changed, 15 insertions(+), 29 deletions(-) diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index ea96f333ee2b..c5207501d5e0 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -785,7 +785,6 @@ static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh, pix->sizeimage = pix->bytesperline * pix->height; pix->field = V4L2_FIELD_NONE; - pix->priv = 0; return 0; } diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index a02f08459e14..476d7f3b32d6 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -879,7 +879,6 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv, pix->colorspace = V4L2_COLORSPACE_SMPTE170M; pix->sizeimage = FRAME_BUF_SIZE; pix->bytesperline = 0; - pix->priv = 0; return 0; } @@ -934,7 +933,6 @@ static int solo_enc_get_fmt_cap(struct file *file, void *priv, V4L2_FIELD_NONE; pix->sizeimage = FRAME_BUF_SIZE; pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->priv = 0; return 0; } diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c index 2efa539d6075..78792067e920 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c @@ -477,7 +477,6 @@ static int solo_try_fmt_cap(struct file *file, void *priv, pix->field = V4L2_FIELD_INTERLACED; pix->pixelformat = V4L2_PIX_FMT_UYVY; pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->priv = 0; return 0; } @@ -507,7 +506,6 @@ static int solo_get_fmt_cap(struct file *file, void *priv, pix->sizeimage = solo_image_size(solo_dev); pix->colorspace = V4L2_COLORSPACE_SMPTE170M; pix->bytesperline = solo_bytesperline(solo_dev); - pix->priv = 0; return 0; } diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 99e74c22d3be..2fb82d50c53e 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -582,7 +582,6 @@ static int tw68_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 9fe7caf6aa13..d5eadd451587 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -972,7 +972,6 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv, pixfmt->bytesperline = common->fmt.fmt.pix.width * 2; pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; } - pixfmt->priv = 0; dev_dbg(vpif_dev, "%s: %d x %d; pitch=%d pixelformat=0x%08x, field=%d, size=%d\n", __func__, pixfmt->width, pixfmt->height, diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index e390ca57520a..d1895334cbbf 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1153,7 +1153,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, format->fmt.pix.sizeimage = width * height * 2; format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - format->fmt.pix.priv = 0; if (cmd == VIDIOC_TRY_FMT) return 0; @@ -1227,7 +1226,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = dev->frame_size; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */ f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index ded7eb2dc40a..626264a56517 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -323,7 +323,6 @@ static int cpia2_try_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = cam->frame_size; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) { case VIDEOSIZE_VGA: @@ -434,7 +433,6 @@ static int cpia2_g_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = cam->frame_size; f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 82eb1550ec3b..fc6d37d76dc9 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1510,7 +1510,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, else f->fmt.pix.field = v4l2->interlaced_fieldmode ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - f->fmt.pix.priv = 0; return 0; } diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 83b78a42414e..4add2b12d330 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1027,15 +1027,15 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) +static int vidioc_g_fmt_vid_cap(struct file *file, void *_priv, + struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); + u32 priv = fmt->fmt.pix.priv; fmt->fmt.pix = gspca_dev->pixfmt; - /* some drivers use priv internally, zero it before giving it back to - the core */ - fmt->fmt.pix.priv = 0; + /* some drivers use priv internally, so keep the original value */ + fmt->fmt.pix.priv = priv; return 0; } @@ -1070,27 +1070,27 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, fmt->fmt.pix.height = h; gspca_dev->sd_desc->try_fmt(gspca_dev, fmt); } - /* some drivers use priv internally, zero it before giving it back to - the core */ - fmt->fmt.pix.priv = 0; return mode; /* used when s_fmt */ } -static int vidioc_try_fmt_vid_cap(struct file *file, - void *priv, - struct v4l2_format *fmt) +static int vidioc_try_fmt_vid_cap(struct file *file, void *_priv, + struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); + u32 priv = fmt->fmt.pix.priv; if (try_fmt_vid_cap(gspca_dev, fmt) < 0) return -EINVAL; + /* some drivers use priv internally, so keep the original value */ + fmt->fmt.pix.priv = priv; return 0; } -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) +static int vidioc_s_fmt_vid_cap(struct file *file, void *_priv, + struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); + u32 priv = fmt->fmt.pix.priv; int mode; if (vb2_is_busy(&gspca_dev->queue)) @@ -1106,6 +1106,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, gspca_dev->pixfmt = fmt->fmt.pix; else gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode]; + /* some drivers use priv internally, so keep the original value */ + fmt->fmt.pix.priv = priv; return 0; } diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 533f7f064a44..329ec8089592 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -751,7 +751,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = f->fmt.pix.width * (vc->fmt->depth >> 3); f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; return 0; } @@ -803,7 +802,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; dprintk(vc->dev, 50, "%s: set width %d height %d field %d\n", __func__, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); return 0; diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 203329cadbc4..0335e69b70ab 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -253,7 +253,6 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame); fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; fmt->fmt.pix.colorspace = format->colorspace; - fmt->fmt.pix.priv = 0; if (uvc_format != NULL) *uvc_format = format; @@ -290,7 +289,6 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream, fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame); fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize; fmt->fmt.pix.colorspace = format->colorspace; - fmt->fmt.pix.priv = 0; done: mutex_unlock(&stream->mutex); -- GitLab From b98fd3cb6db8dbba6377c41a66c6b673f9d93da3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Jun 2019 04:05:41 -0400 Subject: [PATCH 0327/7155] media: vivid: fix potential integer overflow on left shift There is a potential integer overflow when int 2 is left shifted as this is evaluated using 32 bit arithmetic but is being used in a context that expects an expression of type s64. Fix this by generating a mask using GENMASK to avoid a 32 bit overflow. Addresses-Coverity: ("Unintentional integer overflow") Fixes: 8a99e9faa131 ("media: vivid: add HDMI (dis)connect RX emulation") Fixes: 79a792dafac6 ("media: vivid: add HDMI (dis)connect TX emulation") Signed-off-by: Colin Ian King Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-ctrls.c | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index 3e916c8befb7..fb9220e4e640 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -1613,6 +1613,8 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, } if (dev->num_hdmi_inputs) { + s64 hdmi_input_mask = GENMASK(dev->num_hdmi_inputs - 1, 0); + dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_signal_mode, NULL); @@ -1633,12 +1635,13 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, 0, V4L2_DV_RGB_RANGE_AUTO); dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap, - NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, - (2 << (dev->num_hdmi_inputs - 1)) - 1, 0, - (2 << (dev->num_hdmi_inputs - 1)) - 1); + NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, hdmi_input_mask, + 0, hdmi_input_mask); } if (dev->num_hdmi_outputs) { + s64 hdmi_output_mask = GENMASK(dev->num_hdmi_outputs - 1, 0); + /* * We aren't doing anything with this at the moment, but * HDMI outputs typically have this controls. @@ -1652,17 +1655,14 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_display_present, NULL); dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out, - NULL, V4L2_CID_DV_TX_HOTPLUG, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1); + NULL, V4L2_CID_DV_TX_HOTPLUG, 0, hdmi_output_mask, + 0, hdmi_output_mask); dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out, - NULL, V4L2_CID_DV_TX_RXSENSE, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1); + NULL, V4L2_CID_DV_TX_RXSENSE, 0, hdmi_output_mask, + 0, hdmi_output_mask); dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out, - NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1, 0, - (2 << (dev->num_hdmi_outputs - 1)) - 1); + NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, hdmi_output_mask, + 0, hdmi_output_mask); } if ((dev->has_vid_cap && dev->has_vid_out) || (dev->has_vbi_cap && dev->has_vbi_out)) -- GitLab From aa9c2182c45421d54ed27c2a1765f7adedce291b Mon Sep 17 00:00:00 2001 From: Vandana BN Date: Thu, 27 Jun 2019 04:26:43 -0400 Subject: [PATCH 0328/7155] media: vivid:add sanity check to avoid divide error and set value to 1 if 0. Syzbot reported divide error in vivid_thread_vid_cap, which has been seen only once and does not have a reproducer. This patch adds sanity checks for the denominator value with WARN_ON if it is 0 and replaces it with 1. divide error: 0000 [#1] PREEMPT SMP KASAN kobject: 'tx-0' (0000000017161f7f): kobject_uevent_env CPU: 0 PID: 23689 Comm: vivid-003-vid-c Not tainted 5.0.0-rc4+ #58 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:vivid_cap_update_frame_period drivers/media/platform/vivid/vivid-kthread-cap.c:661 [inline] RIP: 0010:vivid_thread_vid_cap+0x221/0x284 drivers/media/platform/vivid/vivid-kthread-cap.c:789 Code: 48 c1 e9 03 0f b6 0c 11 48 89 f2 48 69 c0 00 ca 9a 3b 83 c2 03 38 ca 7c 08 84 c9 0f 85 f0 1e 00 00 41 8b 8f 24 64 00 00 31 d2 <48> f7 f1 49 89 c4 48 89 c3 49 8d 87 28 64 00 00 48 89 c2 48 89 45 RSP: 0018:ffff88808b4afd68 EFLAGS: 00010246 kobject: 'tx-0' (0000000017161f7f): fill_kobj_path: path = '/devices/virtual/net/gre0/queues/tx-0' RAX: 000000de5a6f8e00 RBX: 0000000100047b22 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000004 RBP: ffff88808b4aff00 R08: ffff88804862e1c0 R09: ffffffff89997008 R10: ffffffff89997010 R11: 0000000000000001 R12: 00000000fffffffc R13: ffff8880a17e0500 R14: ffff88803e40f760 R15: ffff8882182b0140 FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000004cdc90 CR3: 000000005d827000 CR4: 00000000001426f0 Call Trace: kobject: 'gretap0' (00000000d7549098): kobject_add_internal: parent: 'net', set: 'devices' kobject: 'loop2' (0000000094ed4ee4): kobject_uevent_env kobject: 'loop2' (0000000094ed4ee4): fill_kobj_path: path = '/devices/virtual/block/loop2' kthread+0x357/0x430 kernel/kthread.c:246 kobject: 'gretap0' (00000000d7549098): kobject_uevent_env ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352 Modules linked in: kobject: 'gretap0' (00000000d7549098): fill_kobj_path: path = '/devices/virtual/net/gretap0' ---[ end trace bc5c8b25b64d768f ]--- kobject: 'loop1' (0000000032036b86): kobject_uevent_env RIP: 0010:vivid_cap_update_frame_period drivers/media/platform/vivid/vivid-kthread-cap.c:661 [inline] RIP: 0010:vivid_thread_vid_cap+0x221/0x2840 drivers/media/platform/vivid/vivid-kthread-cap.c:789 kobject: 'loop1' (0000000032036b86): fill_kobj_path: path = '/devices/virtual/block/loop1' Code: 48 c1 e9 03 0f b6 0c 11 48 89 f2 48 69 c0 00 ca 9a 3b 83 c2 03 38 ca 7c 08 84 c9 0f 85 f0 1e 00 00 41 8b 8f 24 64 00 00 31 d2 <48> f7 f1 49 89 c4 48 89 c3 49 8d 87 28 64 00 00 48 89 c2 48 89 45 kobject: 'loop0' (00000000dd9927c3): kobject_uevent_env RSP: 0018:ffff88808b4afd68 EFLAGS: 00010246 RAX: 000000de5a6f8e00 RBX: 0000000100047b22 RCX: 0000000000000000 kobject: 'queues' (000000007ed20666): kobject_add_internal: parent: 'gretap0', set: '' RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000004 RBP: ffff88808b4aff00 R08: ffff88804862e1c0 R09: ffffffff89997008 kobject: 'loop0' (00000000dd9927c3): fill_kobj_path: path = '/devices/virtual/block/loop0' R10: ffffffff89997010 R11: 0000000000000001 R12: 00000000fffffffc kobject: 'queues' (000000007ed20666): kobject_uevent_env R13: ffff8880a17e0500 R14: ffff88803e40f760 R15: ffff8882182b0140 FS: 0000000000000000(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000 kobject: 'loop5' (00000000a41f9e79): kobject_uevent_env CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 kobject: 'queues' (000000007ed20666): kobject_uevent_env: filter function caused the event to drop! CR2: 00000000004cdc90 CR3: 000000005d827000 CR4: 00000000001426f0 kobject: 'loop5' (00000000a41f9e79): fill_kobj_path: path = '/devices/virtual/block/loop5' Reported-by: syz...@syzkaller.appspotmail.com Signed-off-by: Vandana BN Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-kthread-cap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index 6cf495a7d5cc..ed466d737a90 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -658,6 +658,8 @@ static void vivid_cap_update_frame_period(struct vivid_dev *dev) u64 f_period; f_period = (u64)dev->timeperframe_vid_cap.numerator * 1000000000; + if (WARN_ON(dev->timeperframe_vid_cap.denominator == 0)) + dev->timeperframe_vid_cap.denominator = 1; do_div(f_period, dev->timeperframe_vid_cap.denominator); if (dev->field_cap == V4L2_FIELD_ALTERNATE) f_period >>= 1; -- GitLab From 31bd0e5e61dce5cf4b95dd9f463d7f88f2df08b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Jun 2019 06:51:05 -0400 Subject: [PATCH 0329/7155] media: davinci-vpbe: remove obsolete includes The driver builds fine without these, and they cause build problems once davinci multiplatform support is enabled. Signed-off-by: Arnd Bergmann Acked-by: Lad, Prabhakar Acked-by: Sekhar Nori Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpbe_display.c | 4 ---- drivers/media/platform/davinci/vpbe_osd.c | 5 ----- drivers/media/platform/davinci/vpbe_venc.c | 5 ----- 3 files changed, 14 deletions(-) diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 9f1417e4b744..ae419958e420 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -19,10 +19,6 @@ #include -#ifdef CONFIG_ARCH_DAVINCI -#include -#endif - #include #include #include diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 491842ef33c5..91b571a0ac2c 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c @@ -16,11 +16,6 @@ #include #include -#ifdef CONFIG_ARCH_DAVINCI -#include -#include -#endif - #include #include #include diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 425f91f07165..8caa084e5704 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c @@ -14,11 +14,6 @@ #include #include -#ifdef CONFIG_ARCH_DAVINCI -#include -#include -#endif - #include #include -- GitLab From 9bef0d1d053de8db30bc07aa132c0ee94a05609c Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 1 Jul 2019 06:47:01 -0400 Subject: [PATCH 0330/7155] media: dt-bindings: media: meson-ao-cec: add SM1 compatible Add AO-CEC compatible string for the Amlogic SM1 SoC family, a derivate of the G12A AO-CECB controller. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/meson-ao-cec.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/media/meson-ao-cec.txt b/Documentation/devicetree/bindings/media/meson-ao-cec.txt index c67fc41d4aa2..ad92ee41c0dd 100644 --- a/Documentation/devicetree/bindings/media/meson-ao-cec.txt +++ b/Documentation/devicetree/bindings/media/meson-ao-cec.txt @@ -5,10 +5,12 @@ to handle communication between HDMI connected devices over the CEC bus. Required properties: - compatible : value should be following depending on the SoC : - For GXBB, GXL, GXM and G12A (AO_CEC_A module) : + For GXBB, GXL, GXM, G12A and SM1 (AO_CEC_A module) : "amlogic,meson-gx-ao-cec" For G12A (AO_CEC_B module) : "amlogic,meson-g12a-ao-cec" + For SM1 (AO_CEC_B module) : + "amlogic,meson-sm1-ao-cec" - reg : Physical base address of the IP registers and length of memory mapped region. @@ -16,9 +18,9 @@ Required properties: - interrupts : AO-CEC interrupt number to the CPU. - clocks : from common clock binding: handle to AO-CEC clock. - clock-names : from common clock binding, must contain : - For GXBB, GXL, GXM and G12A (AO_CEC_A module) : + For GXBB, GXL, GXM, G12A and SM1 (AO_CEC_A module) : - "core" - For G12A (AO_CEC_B module) : + For G12A, SM1 (AO_CEC_B module) : - "oscin" corresponding to entry in the clocks property. - hdmi-phandle: phandle to the HDMI controller -- GitLab From aef5f47c9907ed6bfe9245124279b9c049077fd7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 1 Jul 2019 06:47:02 -0400 Subject: [PATCH 0331/7155] media: platform: meson-ao-cec-g12a: add support for SM1 Add support for the Amlogic SM1 SoC Family to the G12A AO-CECB derivative. It only adds a single init register. Signed-off-by: Neil Armstrong [hverkuil-cisco@xs4all.nl: dropped spurious newline] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/meson/ao-cec-g12a.c | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/meson/ao-cec-g12a.c b/drivers/media/platform/meson/ao-cec-g12a.c index c99d01926673..3b39e875292e 100644 --- a/drivers/media/platform/meson/ao-cec-g12a.c +++ b/drivers/media/platform/meson/ao-cec-g12a.c @@ -121,6 +121,9 @@ #define CECB_CTRL_TYPE_NEXT 2 #define CECB_CTRL2 0x01 + +#define CECB_CTRL2_RISE_DEL_MAX GENMASK(4, 0) + #define CECB_INTR_MASK 0x02 #define CECB_LADD_LOW 0x05 #define CECB_LADD_HIGH 0x06 @@ -165,6 +168,11 @@ #define CECB_WAKEUPCTRL 0x31 +struct meson_ao_cec_g12a_data { + /* Setup the internal CECB_CTRL2 register */ + bool ctrl2_setup; +}; + struct meson_ao_cec_g12a_device { struct platform_device *pdev; struct regmap *regmap; @@ -175,6 +183,7 @@ struct meson_ao_cec_g12a_device { struct cec_msg rx_msg; struct clk *oscin; struct clk *core; + const struct meson_ao_cec_g12a_data *data; }; static const struct regmap_config meson_ao_cec_g12a_regmap_conf = { @@ -605,6 +614,10 @@ static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable) regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET, 0); + if (ao_cec->data->ctrl2_setup) + regmap_write(ao_cec->regmap_cec, CECB_CTRL2, + FIELD_PREP(CECB_CTRL2_RISE_DEL_MAX, 2)); + meson_ao_cec_g12a_irq_setup(ao_cec, true); return 0; @@ -632,6 +645,12 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev) if (!ao_cec) return -ENOMEM; + ao_cec->data = of_device_get_match_data(&pdev->dev); + if (!ao_cec->data) { + dev_err(&pdev->dev, "failed to get match data\n"); + return -ENODEV; + } + spin_lock_init(&ao_cec->cec_reg_lock); ao_cec->pdev = pdev; @@ -740,8 +759,23 @@ static int meson_ao_cec_g12a_remove(struct platform_device *pdev) return 0; } +static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = { + .ctrl2_setup = false, +}; + +static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = { + .ctrl2_setup = true, +}; + static const struct of_device_id meson_ao_cec_g12a_of_match[] = { - { .compatible = "amlogic,meson-g12a-ao-cec", }, + { + .compatible = "amlogic,meson-g12a-ao-cec", + .data = &ao_cec_g12a_data, + }, + { + .compatible = "amlogic,meson-sm1-ao-cec", + .data = &ao_cec_sm1_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match); -- GitLab From ed2cea4f95bf2d091061e2b89b22912fff575a14 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 3 Jul 2019 04:00:35 -0400 Subject: [PATCH 0332/7155] media: cobalt: remove redundant assignment to variable data The variable data is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/cobalt-flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cobalt/cobalt-flash.c b/drivers/media/pci/cobalt/cobalt-flash.c index ef96e0f956d2..1d3c64b4cf6d 100644 --- a/drivers/media/pci/cobalt/cobalt-flash.c +++ b/drivers/media/pci/cobalt/cobalt-flash.c @@ -69,7 +69,7 @@ static void flash_copy_to(struct map_info *map, unsigned long to, pr_info("%s: offset 0x%x: length %zu\n", __func__, dest, len); while (len) { - u16 data = 0xffff; + u16 data; do { data = *src << (8 * (dest & 1)); -- GitLab From f2180adfd7a3d0715726474411bdf925010d4c29 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 4 Jul 2019 19:57:43 -0400 Subject: [PATCH 0333/7155] media: m2m-deinterlace: Fix misuse of strscpy Probable cut&paste typo - use the correct field size. Signed-off-by: Joe Perches Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/m2m-deinterlace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index bbf664546697..d2c3926269e9 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -433,7 +433,7 @@ static int vidioc_querycap(struct file *file, void *priv, { strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); - strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card)); + strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); return 0; } -- GitLab From ba78170ef15371276c22255a88453c2f15529130 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 4 Jul 2019 19:57:44 -0400 Subject: [PATCH 0334/7155] media: go7007: Fix misuse of strscpy Probable cut&paste typo - use the correct field size. Signed-off-by: Joe Perches Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/go7007/snd-go7007.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c index 4a449c62fc32..b05fa227ffb2 100644 --- a/drivers/media/usb/go7007/snd-go7007.c +++ b/drivers/media/usb/go7007/snd-go7007.c @@ -253,7 +253,7 @@ int go7007_snd_init(struct go7007 *go) return ret; } strscpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); - strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); + strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->shortname)); strscpy(gosnd->card->longname, gosnd->card->shortname, sizeof(gosnd->card->longname)); -- GitLab From 9230a4cc316b241e641565c377a415cf5d911425 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:03:42 -0400 Subject: [PATCH 0335/7155] media: via-camera: call viafb_pm_unregister in remove() The power management hooks were never unregistered, which caused a crash when unloading the module. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/via-camera.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 4110dc4c771e..d080a263d975 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -1459,6 +1459,9 @@ static int viacam_remove(struct platform_device *pdev) video_unregister_device(&cam->vdev); v4l2_device_unregister(&cam->v4l2_dev); +#ifdef CONFIG_PM + viafb_pm_unregister(&viacam_pm_hooks); +#endif free_irq(viadev->pdev->irq, cam); via_sensor_power_release(cam); v4l2_ctrl_handler_free(&cam->ctrl_handler); -- GitLab From 4965bcd3c1f3d3fcade75bb8693fc1a97c7b2773 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:03:43 -0400 Subject: [PATCH 0336/7155] media: via-camera: use struct v4l2_fh Modern V4L2 drivers should use struct v4l2_fh to represent a filehandle. This driver was one of the few that didn't use it. Signed-off-by: Hans Verkuil Reviewed-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/via-camera.c | 47 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index d080a263d975..99c157b528df 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -658,19 +658,22 @@ static const struct videobuf_queue_ops viacam_vb_ops = { static int viacam_open(struct file *filp) { struct via_camera *cam = video_drvdata(filp); + int ret; - filp->private_data = cam; /* * Note the new user. If this is the first one, we'll also * need to power up the sensor. */ mutex_lock(&cam->lock); - if (cam->users == 0) { - int ret = viafb_request_dma(); + ret = v4l2_fh_open(filp); + if (ret) + goto out; + if (v4l2_fh_is_singular_file(filp)) { + ret = viafb_request_dma(); if (ret) { - mutex_unlock(&cam->lock); - return ret; + v4l2_fh_release(filp); + goto out; } via_sensor_power_up(cam); set_bit(CF_CONFIG_NEEDED, &cam->flags); @@ -683,16 +686,19 @@ static int viacam_open(struct file *filp) sizeof(struct videobuf_buffer), cam, NULL); } (cam->users)++; +out: mutex_unlock(&cam->lock); - return 0; + return ret; } static int viacam_release(struct file *filp) { struct via_camera *cam = video_drvdata(filp); + bool last_open; mutex_lock(&cam->lock); (cam->users)--; + last_open = v4l2_fh_is_singular_file(filp); /* * If the "owner" is closing, shut down any ongoing * operations. @@ -712,11 +718,12 @@ static int viacam_release(struct file *filp) /* * Last one out needs to turn out the lights. */ - if (cam->users == 0) { + if (last_open) { videobuf_mmap_free(&cam->vb_queue); via_sensor_power_down(cam); viafb_release_dma(); } + v4l2_fh_release(filp); mutex_unlock(&cam->lock); return 0; } @@ -923,7 +930,7 @@ static int viacam_do_try_fmt(struct via_camera *cam, static int viacam_try_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); struct v4l2_format sfmt; int ret; @@ -937,7 +944,7 @@ static int viacam_try_fmt_vid_cap(struct file *filp, void *priv, static int viacam_g_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); mutex_lock(&cam->lock); fmt->fmt.pix = cam->user_format; @@ -948,7 +955,7 @@ static int viacam_g_fmt_vid_cap(struct file *filp, void *priv, static int viacam_s_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); int ret; struct v4l2_format sfmt; struct via_format *f = via_find_format(fmt->fmt.pix.pixelformat); @@ -997,7 +1004,7 @@ static int viacam_querycap(struct file *filp, void *priv, static int viacam_reqbufs(struct file *filp, void *priv, struct v4l2_requestbuffers *rb) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); return videobuf_reqbufs(&cam->vb_queue, rb); } @@ -1005,28 +1012,28 @@ static int viacam_reqbufs(struct file *filp, void *priv, static int viacam_querybuf(struct file *filp, void *priv, struct v4l2_buffer *buf) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); return videobuf_querybuf(&cam->vb_queue, buf); } static int viacam_qbuf(struct file *filp, void *priv, struct v4l2_buffer *buf) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); return videobuf_qbuf(&cam->vb_queue, buf); } static int viacam_dqbuf(struct file *filp, void *priv, struct v4l2_buffer *buf) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); return videobuf_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK); } static int viacam_streamon(struct file *filp, void *priv, enum v4l2_buf_type t) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); int ret = 0; if (t != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1077,7 +1084,7 @@ static int viacam_streamon(struct file *filp, void *priv, enum v4l2_buf_type t) static int viacam_streamoff(struct file *filp, void *priv, enum v4l2_buf_type t) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); int ret; if (t != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1106,7 +1113,7 @@ static int viacam_streamoff(struct file *filp, void *priv, enum v4l2_buf_type t) static int viacam_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); int ret; mutex_lock(&cam->lock); @@ -1119,7 +1126,7 @@ static int viacam_g_parm(struct file *filp, void *priv, static int viacam_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); int ret; mutex_lock(&cam->lock); @@ -1146,7 +1153,7 @@ static int viacam_enum_framesizes(struct file *filp, void *priv, static int viacam_enum_frameintervals(struct file *filp, void *priv, struct v4l2_frmivalenum *interval) { - struct via_camera *cam = priv; + struct via_camera *cam = video_drvdata(filp); struct v4l2_subdev_frame_interval_enum fie = { .index = interval->index, .code = cam->mbus_code, @@ -1422,10 +1429,10 @@ static int viacam_probe(struct platform_device *pdev) */ cam->vdev = viacam_v4l_template; cam->vdev.v4l2_dev = &cam->v4l2_dev; + video_set_drvdata(&cam->vdev, cam); ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); if (ret) goto out_irq; - video_set_drvdata(&cam->vdev, cam); #ifdef CONFIG_PM /* -- GitLab From fa564e90257e5aa5b69a0c70fe59a91da3547897 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:03:44 -0400 Subject: [PATCH 0337/7155] media: ov7670: don't return ENOTTY if SUBDEV_API is not set If CONFIG_VIDEO_V4L2_SUBDEV_API is not set, then it is still possible to call set_fmt for V4L2_SUBDEV_FORMAT_TRY, the result is just not stored. So return 0 instead of -ENOTTY. Calling get_fmt with V4L2_SUBDEV_FORMAT_TRY should return -EINVAL instead of -ENOTTY, after all the get_fmt functionality is still present, just not supported for TRY. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov7670.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 53385c277792..b42b289faaef 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1110,10 +1110,8 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); *mbus_fmt = format->format; - return 0; -#else - return -ENOTTY; #endif + return 0; } ret = ov7670_try_fmt_internal(sd, &format->format, &info->fmt, &info->wsize); @@ -1146,7 +1144,7 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd, format->format = *mbus_fmt; return 0; #else - return -ENOTTY; + return -EINVAL; #endif } else { format->format = info->format; -- GitLab From ec8b22b4bd8e9d797bbafc5b2a941e215587c8b5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:03:45 -0400 Subject: [PATCH 0338/7155] media: via-camera: fix v4l2-compliance fails The patch fixes various v4l2-compliance failures: - missing support for control events - support of s/g_std even though this doesn't apply to a webcam - missing colorspace reporting - bus_info wasn't filled in by VIDIOC_QUERYCAP - parm.capture.readbuffers was overridden with wrong value - viacam_enum_framesizes/intervals didn't check the arguments Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/via-camera.c | 44 +++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 99c157b528df..24c5d2a7b91f 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -778,7 +779,7 @@ static __poll_t viacam_poll(struct file *filp, struct poll_table_struct *pt) { struct via_camera *cam = video_drvdata(filp); - return videobuf_poll_stream(filp, &cam->vb_queue, pt); + return v4l2_ctrl_poll(filp, pt) | videobuf_poll_stream(filp, &cam->vb_queue, pt); } @@ -816,7 +817,6 @@ static int viacam_enum_input(struct file *filp, void *priv, return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; - input->std = V4L2_STD_ALL; /* Not sure what should go here */ strscpy(input->name, "Camera", sizeof(input->name)); return 0; } @@ -834,17 +834,6 @@ static int viacam_s_input(struct file *filp, void *priv, unsigned int i) return 0; } -static int viacam_s_std(struct file *filp, void *priv, v4l2_std_id std) -{ - return 0; -} - -static int viacam_g_std(struct file *filp, void *priv, v4l2_std_id *std) -{ - *std = V4L2_STD_NTSC_M; - return 0; -} - /* * Video format stuff. Here is our default format until * user space messes with things. @@ -856,6 +845,7 @@ static const struct v4l2_pix_format viacam_def_pix_format = { .field = V4L2_FIELD_NONE, .bytesperline = VGA_WIDTH * 2, .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2, + .colorspace = V4L2_COLORSPACE_SRGB, }; static const u32 via_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; @@ -900,6 +890,10 @@ static void viacam_fmt_post(struct v4l2_pix_format *userfmt, userfmt->field = sensorfmt->field; userfmt->bytesperline = 2 * userfmt->width; userfmt->sizeimage = userfmt->bytesperline * userfmt->height; + userfmt->colorspace = sensorfmt->colorspace; + userfmt->ycbcr_enc = sensorfmt->ycbcr_enc; + userfmt->quantization = sensorfmt->quantization; + userfmt->xfer_func = sensorfmt->xfer_func; } @@ -995,6 +989,7 @@ static int viacam_querycap(struct file *filp, void *priv, { strscpy(cap->driver, "via-camera", sizeof(cap->driver)); strscpy(cap->card, "via-camera", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:via-camera", sizeof(cap->bus_info)); return 0; } @@ -1119,7 +1114,6 @@ static int viacam_g_parm(struct file *filp, void *priv, mutex_lock(&cam->lock); ret = v4l2_g_parm_cap(video_devdata(filp), cam->sensor, parm); mutex_unlock(&cam->lock); - parm->parm.capture.readbuffers = cam->n_cap_bufs; return ret; } @@ -1132,15 +1126,21 @@ static int viacam_s_parm(struct file *filp, void *priv, mutex_lock(&cam->lock); ret = v4l2_s_parm_cap(video_devdata(filp), cam->sensor, parm); mutex_unlock(&cam->lock); - parm->parm.capture.readbuffers = cam->n_cap_bufs; return ret; } static int viacam_enum_framesizes(struct file *filp, void *priv, struct v4l2_frmsizeenum *sizes) { + unsigned int i; + if (sizes->index != 0) return -EINVAL; + for (i = 0; i < N_VIA_FMTS; i++) + if (sizes->pixel_format == via_formats[i].pixelformat) + break; + if (i >= N_VIA_FMTS) + return -EINVAL; sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; sizes->stepwise.min_width = QCIF_WIDTH; sizes->stepwise.min_height = QCIF_HEIGHT; @@ -1161,8 +1161,17 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, .height = cam->sensor_format.height, .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; + unsigned int i; int ret; + for (i = 0; i < N_VIA_FMTS; i++) + if (interval->pixel_format == via_formats[i].pixelformat) + break; + if (i >= N_VIA_FMTS) + return -EINVAL; + if (interval->width < QCIF_WIDTH || interval->width > VGA_WIDTH || + interval->height < QCIF_HEIGHT || interval->height > VGA_HEIGHT) + return -EINVAL; mutex_lock(&cam->lock); ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie); mutex_unlock(&cam->lock); @@ -1179,8 +1188,6 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_enum_input = viacam_enum_input, .vidioc_g_input = viacam_g_input, .vidioc_s_input = viacam_s_input, - .vidioc_s_std = viacam_s_std, - .vidioc_g_std = viacam_g_std, .vidioc_enum_fmt_vid_cap = viacam_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap = viacam_try_fmt_vid_cap, .vidioc_g_fmt_vid_cap = viacam_g_fmt_vid_cap, @@ -1196,6 +1203,8 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_s_parm = viacam_s_parm, .vidioc_enum_framesizes = viacam_enum_framesizes, .vidioc_enum_frameintervals = viacam_enum_frameintervals, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /*----------------------------------------------------------------------------*/ @@ -1267,7 +1276,6 @@ static struct viafb_pm_hooks viacam_pm_hooks = { static const struct video_device viacam_v4l_template = { .name = "via-camera", .minor = -1, - .tvnorms = V4L2_STD_NTSC_M, .fops = &viacam_fops, .ioctl_ops = &viacam_ioctl_ops, .release = video_device_release_empty, /* Check this */ -- GitLab From 6732ecb335f5c8957ae319f50949b15f78d54621 Mon Sep 17 00:00:00 2001 From: Frederick Lawler Date: Wed, 17 Jul 2019 22:07:40 -0400 Subject: [PATCH 0339/7155] media: cobalt: Prefer pcie_capability_read_word() Commit 8c0d3a02c130 ("PCI: Add accessors for PCI Express Capability") added accessors for the PCI Express Capability so that drivers didn't need to be aware of differences between v1 and v2 of the PCI Express Capability. Replace pci_read_config_word() and pci_write_config_word() calls with pcie_capability_read_word() and pcie_capability_write_word(). Signed-off-by: Frederick Lawler Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/cobalt-driver.c | 38 ++++++++++-------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 4885e833c052..b92833f3d464 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -186,20 +186,16 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) { struct pci_dev *pci_dev = cobalt->pci_dev; struct pci_dev *pci_bus_dev = cobalt->pci_dev->bus->self; - int offset; - int bus_offset; u32 capa; u16 stat, ctrl; - offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); - bus_offset = pci_find_capability(pci_bus_dev, PCI_CAP_ID_EXP); - if (!offset || !bus_offset) + if (!pci_is_pcie(pci_dev) || !pci_is_pcie(pci_bus_dev)) return; /* Device */ - pci_read_config_dword(pci_dev, offset + PCI_EXP_DEVCAP, &capa); - pci_read_config_word(pci_dev, offset + PCI_EXP_DEVCTL, &ctrl); - pci_read_config_word(pci_dev, offset + PCI_EXP_DEVSTA, &stat); + pcie_capability_read_dword(pci_dev, PCI_EXP_DEVCAP, &capa); + pcie_capability_read_word(pci_dev, PCI_EXP_DEVCTL, &ctrl); + pcie_capability_read_word(pci_dev, PCI_EXP_DEVSTA, &stat); cobalt_info("PCIe device capability 0x%08x: Max payload %d\n", capa, get_payload_size(capa & PCI_EXP_DEVCAP_PAYLOAD)); cobalt_info("PCIe device control 0x%04x: Max payload %d. Max read request %d\n", @@ -209,9 +205,9 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) cobalt_info("PCIe device status 0x%04x\n", stat); /* Link */ - pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &capa); - pci_read_config_word(pci_dev, offset + PCI_EXP_LNKCTL, &ctrl); - pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &stat); + pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &capa); + pcie_capability_read_word(pci_dev, PCI_EXP_LNKCTL, &ctrl); + pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat); cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n", capa, get_link_speed(capa), (capa & PCI_EXP_LNKCAP_MLW) >> 4); @@ -221,15 +217,15 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) (stat & PCI_EXP_LNKSTA_NLW) >> 4); /* Bus */ - pci_read_config_dword(pci_bus_dev, bus_offset + PCI_EXP_LNKCAP, &capa); + pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa); cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n", capa, get_link_speed(capa), (capa & PCI_EXP_LNKCAP_MLW) >> 4); /* Slot */ - pci_read_config_dword(pci_dev, offset + PCI_EXP_SLTCAP, &capa); - pci_read_config_word(pci_dev, offset + PCI_EXP_SLTCTL, &ctrl); - pci_read_config_word(pci_dev, offset + PCI_EXP_SLTSTA, &stat); + pcie_capability_read_dword(pci_dev, PCI_EXP_SLTCAP, &capa); + pcie_capability_read_word(pci_dev, PCI_EXP_SLTCTL, &ctrl); + pcie_capability_read_word(pci_dev, PCI_EXP_SLTSTA, &stat); cobalt_info("PCIe slot capability 0x%08x\n", capa); cobalt_info("PCIe slot control 0x%04x\n", ctrl); cobalt_info("PCIe slot status 0x%04x\n", stat); @@ -238,26 +234,22 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) static unsigned pcie_link_get_lanes(struct cobalt *cobalt) { struct pci_dev *pci_dev = cobalt->pci_dev; - unsigned offset; u16 link; - offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); - if (!offset) + if (!pci_is_pcie(pci_dev)) return 0; - pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &link); + pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &link); return (link & PCI_EXP_LNKSTA_NLW) >> 4; } static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt) { struct pci_dev *pci_dev = cobalt->pci_dev->bus->self; - unsigned offset; u32 link; - offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); - if (!offset) + if (!pci_is_pcie(pci_dev)) return 0; - pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &link); + pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &link); return (link & PCI_EXP_LNKCAP_MLW) >> 4; } -- GitLab From 1a03f91c2c2419c3709c4554952c66695575e91c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 Jul 2019 10:16:43 -0400 Subject: [PATCH 0340/7155] media: vivid: work around high stack usage with clang Building a KASAN-enabled kernel with clang ends up in a case where too much is inlined into vivid_thread_vid_cap() and the stack usage grows a lot, possibly when the register allocation fails to produce efficient code and spills a lot of temporaries to the stack. This uses more than twice the amount of stack than the sum of the individual functions when they are not inlined: drivers/media/platform/vivid/vivid-kthread-cap.c:766:12: error: stack frame size of 2208 bytes in function 'vivid_thread_vid_cap' [-Werror,-Wframe-larger-than=] Marking two of the key functions in here as 'noinline_for_stack' avoids the pathological case in clang without any apparent downside for gcc. Signed-off-by: Arnd Bergmann Acked-by: Nick Desaulniers Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-kthread-cap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index ed466d737a90..003319d7816d 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -232,8 +232,8 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf, return vbuf; } -static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, - struct vivid_buffer *vid_cap_buf) +static noinline_for_stack int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, + u8 *vcapbuf, struct vivid_buffer *vid_cap_buf) { bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index]; struct tpg_data *tpg = &dev->tpg; @@ -672,7 +672,8 @@ static void vivid_cap_update_frame_period(struct vivid_dev *dev) dev->cap_frame_period = f_period; } -static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs) +static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev, + int dropped_bufs) { struct vivid_buffer *vid_cap_buf = NULL; struct vivid_buffer *vbi_cap_buf = NULL; -- GitLab From 02c25c003405776084d440c30041a33836b74710 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Wed, 26 Jun 2019 14:52:25 -0400 Subject: [PATCH 0341/7155] media: staging/imx: Fix NULL deref in find_pipeline_entity() Fix a cut&paste error in find_pipeline_entity(). The start entity must be passed to media_entity_to_video_device() in find_pipeline_entity(), not pad->entity. The pad is only put to use later, after determining the start entity is not the entity being searched for. Fixes: 3ef46bc97ca2 ("media: staging/imx: Improve pipeline searching") Reported-by: Colin Ian King Signed-off-by: Steve Longerbeam Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 9088c4b720a3..4cc6a7462ae2 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -841,7 +841,7 @@ find_pipeline_entity(struct media_entity *start, u32 grp_id, if (sd->grp_id & grp_id) return &sd->entity; } else if (buftype && is_media_entity_v4l2_video_device(start)) { - vfd = media_entity_to_video_device(pad->entity); + vfd = media_entity_to_video_device(start); if (buftype == vfd->queue->type) return &vfd->entity; } -- GitLab From da79bf41a4d170ca93cc8f3881a70d734a071c37 Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Thu, 27 Jun 2019 23:01:15 -0400 Subject: [PATCH 0342/7155] media: exynos4-is: fix leaked of_node references The call to of_get_child_by_name returns a node pointer with refcount incremented thus it must be explicitly decremented after the last usage. Detected by coccinelle with the following warnings: drivers/media/platform/exynos4-is/fimc-is.c:813:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 807, but without a corresponding object release within this function. drivers/media/platform/exynos4-is/fimc-is.c:870:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 807, but without a corresponding object release within this function. drivers/media/platform/exynos4-is/fimc-is.c:885:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 807, but without a corresponding object release within this function. drivers/media/platform/exynos4-is/media-dev.c:545:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 541, but without a corresponding object release within this function. drivers/media/platform/exynos4-is/media-dev.c:528:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 499, but without a corresponding object release within this function. drivers/media/platform/exynos4-is/media-dev.c:534:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 499, but without a corresponding object release within this function. Signed-off-by: Wen Yang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-is.c | 1 + drivers/media/platform/exynos4-is/media-dev.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index e043d55133a3..b7cc8e651e32 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -806,6 +806,7 @@ static int fimc_is_probe(struct platform_device *pdev) return -ENODEV; is->pmu_regs = of_iomap(node, 0); + of_node_put(node); if (!is->pmu_regs) return -ENOMEM; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index d53427a8db11..a838189d4490 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -501,6 +501,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) continue; ret = fimc_md_parse_port_node(fmd, port, index); + of_node_put(port); if (ret < 0) { of_node_put(node); goto cleanup; @@ -542,6 +543,7 @@ static int __of_get_csis_id(struct device_node *np) if (!np) return -EINVAL; of_property_read_u32(np, "reg", ®); + of_node_put(np); return reg - FIMC_INPUT_MIPI_CSI2_0; } -- GitLab From 094efbe748c204fb2e10ebf6f100da926e10fc2f Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Thu, 27 Jun 2019 23:01:16 -0400 Subject: [PATCH 0343/7155] media: ti-vpe: fix leaked of_node references The call to of_get_parent returns a node pointer with refcount incremented thus it must be explicitly decremented after the last usage. Detected by coccinelle with the following warnings: drivers/media/platform/ti-vpe/cal.c:1621:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 1607, but without a corresponding object release within this function. Signed-off-by: Wen Yang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/cal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 78cdbd671dd5..223161f9c403 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -1612,6 +1612,7 @@ of_get_next_port(const struct device_node *parent, } prev = port; } while (!of_node_name_eq(port, "port")); + of_node_put(ports); } return port; -- GitLab From 322b169476aaeeb96515d69baaee330e47ac10a0 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sat, 29 Jun 2019 15:31:27 -0400 Subject: [PATCH 0344/7155] media: staging/media/davinci_vpfe: Add null check post kmalloc Add NULL check post memory operations Signed-off-by: Hariprasad Kelam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/dm365_ipipe.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 52397ad0e3e2..5d8ba357906b 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1311,6 +1311,11 @@ static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) to = *(void **)((void *)cfg + module_if->config_offset); params = kmalloc(sizeof(*params), GFP_KERNEL); + if (!params) { + rval = -ENOMEM; + goto error; + } + from = (void *)params + module_if->param_offset; size = module_if->param_size; -- GitLab From 81f96ebc8a663869948c197c60f0356f247ac91c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 04:32:46 -0400 Subject: [PATCH 0345/7155] media: saa7134: remove redundant assignment to variable value The variable value is being assigned with a value that is never read and it is being updated later with a new value. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-tvaudio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c index 5beff534d5e1..79e1afb71075 100644 --- a/drivers/media/pci/saa7134/saa7134-tvaudio.c +++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c @@ -319,7 +319,6 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) __s32 left,right,value; if (!(dev->tvnorm->id & scan->std)) { - value = 0; audio_dbg(1, "skipping %d.%03d MHz [%4s]\n", scan->carr / 1000, scan->carr % 1000, scan->name); return 0; -- GitLab From 596a5a58e89a4bfe0d8a275ab552de990b18f0ac Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 8 Jul 2019 09:07:42 -0400 Subject: [PATCH 0346/7155] media: vb2-dc: skip CPU sync in map/unmap dma_buf This is rougly equivalent to ca0e68e21aae (drm/prime: skip CPU sync in map/unmap dma_buf). The contig memory allocated is already device coherent memory, so there is no point in doing a CPU sync when mapping it to another device. Also most importers currently cache the mapping so the CPU sync would only happen on the first import, so we are better off with not pretending to do a cache synchronization at all. This gets rid of a lot of CPU overhead in uses where those dma-bufs are regularily imported and detached again, like Weston is currently doing in the DRM compositor. Signed-off-by: Lucas Stach Acked-by: Marek Szyprowski Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix checkpatch warnings] Signed-off-by: Mauro Carvalho Chehab --- .../common/videobuf2/videobuf2-dma-contig.c | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c index 7d77e4d30c8a..44cd0e530bbd 100644 --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c @@ -267,8 +267,14 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf, /* release the scatterlist cache */ if (attach->dma_dir != DMA_NONE) - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - attach->dma_dir); + /* + * Cache sync can be skipped here, as the vb2_dc memory is + * allocated from device coherent memory, which means the + * memory locations do not require any explicit cache + * maintenance prior or after being used by the device. + */ + dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC); sg_free_table(sgt); kfree(attach); db_attach->priv = NULL; @@ -293,14 +299,17 @@ static struct sg_table *vb2_dc_dmabuf_ops_map( /* release any previous cache */ if (attach->dma_dir != DMA_NONE) { - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - attach->dma_dir); + dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC); attach->dma_dir = DMA_NONE; } - /* mapping to the client with new direction */ - sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - dma_dir); + /* + * mapping to the client with new direction, no cache sync + * required see comment in vb2_dc_dmabuf_ops_detach() + */ + sgt->nents = dma_map_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents, + dma_dir, DMA_ATTR_SKIP_CPU_SYNC); if (!sgt->nents) { pr_err("failed to map scatterlist\n"); mutex_unlock(lock); -- GitLab From 2dbcb6fb96f5faca146279d5fc8a3c7b803b25cb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:24:13 -0400 Subject: [PATCH 0347/7155] media: media/i2c: don't return ENOTTY if SUBDEV_API is not set If CONFIG_VIDEO_V4L2_SUBDEV_API is not set, then it is still possible to call set_fmt for V4L2_SUBDEV_FORMAT_TRY, the result is just not stored. So return 0 instead of -ENOTTY. Calling get_fmt with V4L2_SUBDEV_FORMAT_TRY should return -EINVAL instead of -ENOTTY, after all the get_fmt functionality is still present, just not supported for TRY. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Acked-by: Rui Miguel Silva Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9m111.c | 2 +- drivers/media/i2c/ov2640.c | 2 +- drivers/media/i2c/ov2659.c | 4 +--- drivers/media/i2c/ov2680.c | 5 +---- drivers/media/i2c/ov5695.c | 5 +---- drivers/media/i2c/ov7740.c | 8 ++------ 6 files changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index 12cb012d91f7..3e01d1b86a25 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -533,7 +533,7 @@ static int mt9m111_get_fmt(struct v4l2_subdev *sd, format->format = *mf; return 0; #else - return -ENOTTY; + return -EINVAL; #endif } diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c index ecd167d7c4d2..8fd17661dd78 100644 --- a/drivers/media/i2c/ov2640.c +++ b/drivers/media/i2c/ov2640.c @@ -929,7 +929,7 @@ static int ov2640_get_fmt(struct v4l2_subdev *sd, format->format = *mf; return 0; #else - return -ENOTTY; + return -EINVAL; #endif } diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 5ed2413eac8a..a71277e361ff 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1055,7 +1055,7 @@ static int ov2659_get_fmt(struct v4l2_subdev *sd, mutex_unlock(&ov2659->lock); return 0; #else - return -ENOTTY; + return -EINVAL; #endif } @@ -1131,8 +1131,6 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); *mf = fmt->format; -#else - ret = -ENOTTY; #endif } else { s64 val; diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index b10bcfabaeeb..164f983c1814 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -675,7 +675,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API fmt = v4l2_subdev_get_try_format(&sensor->sd, cfg, format->pad); #else - ret = -ENOTTY; + ret = -EINVAL; #endif } else { fmt = &sensor->fmt; @@ -723,10 +723,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API try_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); format->format = *try_fmt; -#else - ret = -ENOTTY; #endif - goto unlock; } diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index e65a94353175..34b7046d9702 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -823,9 +823,6 @@ static int ov5695_set_fmt(struct v4l2_subdev *sd, if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; -#else - mutex_unlock(&ov5695->mutex); - return -ENOTTY; #endif } else { ov5695->cur_mode = mode; @@ -856,7 +853,7 @@ static int ov5695_get_fmt(struct v4l2_subdev *sd, fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); #else mutex_unlock(&ov5695->mutex); - return -ENOTTY; + return -EINVAL; #endif } else { fmt->format.width = mode->width; diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index 70bb870b1d08..a2f8f19bca7c 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -827,13 +827,9 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); *mbus_fmt = format->format; - +#endif mutex_unlock(&ov7740->mutex); return 0; -#else - ret = -ENOTTY; - goto error; -#endif } ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize); @@ -868,7 +864,7 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd, format->format = *mbus_fmt; ret = 0; #else - ret = -ENOTTY; + ret = -EINVAL; #endif } else { format->format = ov7740->format; -- GitLab From b4133ad3a5c8fee195079bde0ed9fd470c49d3d8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 05:36:10 -0400 Subject: [PATCH 0348/7155] media: m2m-deinterlace: use struct v4l2_fh Convert this driver to use struct v4l2_fh and as a result switch to using vb2/v4l2_mem2mem helper functions as well. Signed-off-by: Hans Verkuil Reviewed-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/m2m-deinterlace.c | 124 +++++++---------------- 1 file changed, 36 insertions(+), 88 deletions(-) diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index d2c3926269e9..9ad24c86c5ab 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -132,13 +132,13 @@ struct deinterlace_dev { }; struct deinterlace_ctx { + struct v4l2_fh fh; struct deinterlace_dev *dev; /* Abort requested by m2m */ int aborting; enum v4l2_colorspace colorspace; dma_cookie_t cookie; - struct v4l2_m2m_ctx *m2m_ctx; struct dma_interleaved_template *xt; }; @@ -150,9 +150,9 @@ static int deinterlace_job_ready(void *priv) struct deinterlace_ctx *ctx = priv; struct deinterlace_dev *pcdev = ctx->dev; - if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) - && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0) - && (atomic_read(&ctx->dev->busy) == 0)) { + if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0 && + v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0 && + !atomic_read(&ctx->dev->busy)) { dprintk(pcdev, "Task ready\n"); return 1; } @@ -171,7 +171,7 @@ static void deinterlace_job_abort(void *priv) dprintk(pcdev, "Aborting task\n"); - v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); + v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx); } static void dma_callback(void *data) @@ -182,8 +182,8 @@ static void dma_callback(void *data) atomic_set(&pcdev->busy, 0); - src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; @@ -194,7 +194,7 @@ static void dma_callback(void *data) v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); - v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); + v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx); dprintk(pcdev, "dma transfers completed.\n"); } @@ -213,8 +213,8 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op, dma_addr_t p_in, p_out; enum dma_ctrl_flags flags; - src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT); s_width = s_q_data->width; @@ -483,7 +483,7 @@ static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) struct vb2_queue *vq; struct deinterlace_q_data *q_data; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -580,7 +580,7 @@ static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) struct deinterlace_q_data *q_data; struct vb2_queue *vq; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -653,36 +653,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, return ret; } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct deinterlace_ctx *ctx = priv; - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct deinterlace_ctx *ctx = priv; - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct deinterlace_ctx *ctx = priv; - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct deinterlace_ctx *ctx = priv; - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { @@ -723,15 +693,7 @@ static int vidioc_streamon(struct file *file, void *priv, return -EINVAL; } - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct deinterlace_ctx *ctx = priv; - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); + return v4l2_m2m_streamon(file, ctx->fh.m2m_ctx, type); } static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = { @@ -747,14 +709,15 @@ static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = { .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, }; @@ -818,7 +781,7 @@ static void deinterlace_buf_queue(struct vb2_buffer *vb) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static const struct vb2_ops deinterlace_qops = { @@ -836,7 +799,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &deinterlace_qops; @@ -855,7 +818,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &deinterlace_qops; @@ -884,12 +847,13 @@ static int deinterlace_open(struct file *file) if (!ctx) return -ENOMEM; - file->private_data = ctx; + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; ctx->dev = pcdev; - ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - int ret = PTR_ERR(ctx->m2m_ctx); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + int ret = PTR_ERR(ctx->fh.m2m_ctx); kfree(ctx); return ret; @@ -903,8 +867,10 @@ static int deinterlace_open(struct file *file) } ctx->colorspace = V4L2_COLORSPACE_REC709; + v4l2_fh_add(&ctx->fh); - dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); + dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", + ctx, ctx->fh.m2m_ctx); return 0; } @@ -916,40 +882,22 @@ static int deinterlace_release(struct file *file) dprintk(pcdev, "Releasing instance %p\n", ctx); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); kfree(ctx->xt); kfree(ctx); return 0; } -static __poll_t deinterlace_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct deinterlace_ctx *ctx = file->private_data; - __poll_t ret; - - mutex_lock(&ctx->dev->dev_mutex); - ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&ctx->dev->dev_mutex); - - return ret; -} - -static int deinterlace_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct deinterlace_ctx *ctx = file->private_data; - - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); -} - static const struct v4l2_file_operations deinterlace_fops = { .owner = THIS_MODULE, .open = deinterlace_open, .release = deinterlace_release, - .poll = deinterlace_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = deinterlace_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static const struct video_device deinterlace_videodev = { -- GitLab From 854aca6d3ad14e041c19ecaa98aa708261189ade Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 09:29:09 -0400 Subject: [PATCH 0349/7155] media: omap_vout: use struct v4l2_fh This driver is one of the few that is still not using struct v4l2_fh. Convert it. Tested on a Pandaboard. Signed-off-by: Hans Verkuil Reviewed-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap/omap_vout.c | 53 +++++++++++++------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 151752de0d02..b0f03c2ca65d 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -836,7 +836,7 @@ static void omap_vout_buffer_release(struct videobuf_queue *q, static __poll_t omap_vout_poll(struct file *file, struct poll_table_struct *wait) { - struct omap_vout_device *vout = file->private_data; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; return videobuf_poll_stream(file, q, wait); @@ -871,7 +871,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) void *pos; unsigned long start = vma->vm_start; unsigned long size = (vma->vm_end - vma->vm_start); - struct omap_vout_device *vout = file->private_data; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, @@ -930,7 +930,7 @@ static int omap_vout_release(struct file *file) unsigned int ret, i; struct videobuf_queue *q; struct omapvideo_info *ovid; - struct omap_vout_device *vout = file->private_data; + struct omap_vout_device *vout = video_drvdata(file); v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); ovid = &vout->vid_info; @@ -983,7 +983,7 @@ static int omap_vout_release(struct file *file) vout->mmap_count = 0; vout->opened -= 1; - file->private_data = NULL; + v4l2_fh_release(file); if (vout->buffer_allocated) videobuf_mmap_free(q); @@ -995,9 +995,8 @@ static int omap_vout_release(struct file *file) static int omap_vout_open(struct file *file) { struct videobuf_queue *q; - struct omap_vout_device *vout = NULL; - - vout = video_drvdata(file); + struct omap_vout_device *vout = video_drvdata(file); + int ret; if (vout == NULL) return -ENODEV; @@ -1008,9 +1007,11 @@ static int omap_vout_open(struct file *file) if (vout->opened) return -EBUSY; - vout->opened += 1; + ret = v4l2_fh_open(file); + if (ret) + return ret; - file->private_data = vout; + vout->opened += 1; vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; q = &vout->vbq; @@ -1034,7 +1035,7 @@ static int omap_vout_open(struct file *file) static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); strscpy(cap->card, vout->vfd->name, sizeof(cap->card)); @@ -1059,7 +1060,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, static int vidioc_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); f->fmt.pix = vout->pix; return 0; @@ -1072,7 +1073,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *fh, struct omap_overlay *ovl; struct omapvideo_info *ovid; struct omap_video_timings *timing; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_dss_device *dssdev; ovid = &vout->vid_info; @@ -1099,7 +1100,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, struct omap_overlay *ovl; struct omapvideo_info *ovid; struct omap_video_timings *timing; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_dss_device *dssdev; if (vout->streaming) @@ -1165,7 +1166,7 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) { int ret = 0; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_overlay *ovl; struct omapvideo_info *ovid; struct v4l2_window *win = &f->fmt.win; @@ -1191,7 +1192,7 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, int ret = 0; struct omap_overlay *ovl; struct omapvideo_info *ovid; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct v4l2_window *win = &f->fmt.win; mutex_lock(&vout->lock); @@ -1218,7 +1219,7 @@ static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, u32 key_value = 0; struct omap_overlay *ovl; struct omapvideo_info *ovid; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_overlay_manager_info info; struct v4l2_window *win = &f->fmt.win; @@ -1239,7 +1240,7 @@ static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct v4l2_pix_format *pix = &vout->pix; if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -1266,7 +1267,7 @@ static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel) { int ret = -EINVAL; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omapvideo_info *ovid; struct omap_overlay *ovl; struct omap_video_timings *timing; @@ -1408,7 +1409,7 @@ static int vidioc_reqbufs(struct file *file, void *fh, { int ret = 0; unsigned int i, num_buffers = 0; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -1473,7 +1474,7 @@ static int vidioc_reqbufs(struct file *file, void *fh, static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); return videobuf_querybuf(&vout->vbq, b); } @@ -1481,7 +1482,7 @@ static int vidioc_querybuf(struct file *file, void *fh, static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buffer) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) || @@ -1508,7 +1509,7 @@ static int vidioc_qbuf(struct file *file, void *fh, static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; int ret; @@ -1536,7 +1537,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) { int ret = 0, j; u32 addr = 0, mask = 0; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct videobuf_queue *q = &vout->vbq; struct omapvideo_info *ovid = &vout->vid_info; @@ -1621,7 +1622,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) { u32 mask = 0; int ret = 0, j; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omapvideo_info *ovid = &vout->vid_info; if (!vout->streaming) @@ -1659,7 +1660,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, int enable = 0; struct omap_overlay *ovl; struct omapvideo_info *ovid; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_overlay_manager_info info; enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; @@ -1730,7 +1731,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, { struct omap_overlay *ovl; struct omapvideo_info *ovid; - struct omap_vout_device *vout = fh; + struct omap_vout_device *vout = video_drvdata(file); struct omap_overlay_manager_info info; ovid = &vout->vid_info; -- GitLab From 65953018b30ca64a34a7c0141d8a415c74a9b5bf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 17 Jul 2019 09:43:51 -0400 Subject: [PATCH 0350/7155] media: mx2_emmaprp: use struct v4l2_fh Convert this driver to use struct v4l2_fh and as a result switch to using vb2/v4l2_mem2mem helper functions as well. Only compile-tested due to lack of hardware. This driver is however very similar to the m2m-deinterlace driver in this respect, and that v4l2_fh conversion has been properly tested. Signed-off-by: Hans Verkuil Reviewed-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mx2_emmaprp.c | 132 +++++++-------------------- 1 file changed, 32 insertions(+), 100 deletions(-) diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 4dd32f4f1dda..e6c7a616b599 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -207,11 +207,11 @@ struct emmaprp_dev { }; struct emmaprp_ctx { + struct v4l2_fh fh; struct emmaprp_dev *dev; /* Abort requested by m2m */ int aborting; struct emmaprp_q_data q_data[2]; - struct v4l2_m2m_ctx *m2m_ctx; }; static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, @@ -240,7 +240,7 @@ static void emmaprp_job_abort(void *priv) dprintk(pcdev, "Aborting task\n"); - v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); + v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx); } static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev) @@ -275,8 +275,8 @@ static void emmaprp_device_run(void *priv) dma_addr_t p_in, p_out; u32 tmp; - src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); s_width = s_q_data->width; @@ -350,8 +350,8 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data) pr_err("PrP bus error occurred, this transfer is probably corrupted\n"); writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */ - src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; dst_vb->flags &= @@ -368,7 +368,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data) } } - v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); + v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx); return IRQ_HANDLED; } @@ -429,7 +429,7 @@ static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) struct vb2_queue *vq; struct emmaprp_q_data *q_data; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -534,7 +534,7 @@ static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) struct vb2_queue *vq; int ret; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -590,52 +590,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, return vidioc_s_fmt(priv, f); } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct emmaprp_ctx *ctx = priv; - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { .vidioc_querycap = vidioc_querycap, @@ -649,14 +603,14 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, }; @@ -716,7 +670,7 @@ static void emmaprp_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } static const struct vb2_ops emmaprp_qops = { @@ -734,7 +688,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &emmaprp_qops; @@ -748,7 +702,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &emmaprp_qops; @@ -772,7 +726,8 @@ static int emmaprp_open(struct file *file) if (!ctx) return -ENOMEM; - file->private_data = ctx; + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; ctx->dev = pcdev; if (mutex_lock_interruptible(&pcdev->dev_mutex)) { @@ -780,10 +735,10 @@ static int emmaprp_open(struct file *file) return -ERESTARTSYS; } - ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - int ret = PTR_ERR(ctx->m2m_ctx); + if (IS_ERR(ctx->fh.m2m_ctx)) { + int ret = PTR_ERR(ctx->fh.m2m_ctx); mutex_unlock(&pcdev->dev_mutex); kfree(ctx); @@ -794,9 +749,10 @@ static int emmaprp_open(struct file *file) clk_prepare_enable(pcdev->clk_emma_ahb); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; + v4l2_fh_add(&ctx->fh); mutex_unlock(&pcdev->dev_mutex); - dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); + dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); return 0; } @@ -811,46 +767,22 @@ static int emmaprp_release(struct file *file) mutex_lock(&pcdev->dev_mutex); clk_disable_unprepare(pcdev->clk_emma_ahb); clk_disable_unprepare(pcdev->clk_emma_ipg); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&pcdev->dev_mutex); kfree(ctx); return 0; } -static __poll_t emmaprp_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct emmaprp_dev *pcdev = video_drvdata(file); - struct emmaprp_ctx *ctx = file->private_data; - __poll_t res; - - mutex_lock(&pcdev->dev_mutex); - res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&pcdev->dev_mutex); - return res; -} - -static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct emmaprp_dev *pcdev = video_drvdata(file); - struct emmaprp_ctx *ctx = file->private_data; - int ret; - - if (mutex_lock_interruptible(&pcdev->dev_mutex)) - return -ERESTARTSYS; - ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&pcdev->dev_mutex); - return ret; -} - static const struct v4l2_file_operations emmaprp_fops = { .owner = THIS_MODULE, .open = emmaprp_open, .release = emmaprp_release, - .poll = emmaprp_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = emmaprp_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static const struct video_device emmaprp_videodev = { -- GitLab From 7770f89b26ceb635e9e1b99e73c0d9e54dbda95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 24 Jun 2019 08:37:25 -0400 Subject: [PATCH 0351/7155] media: vimc: stream: remove obsolete function doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a more complete version of vimc_streamer_s_streamer comment was added at "media: vimc: stream: add missing function documentation" commit in .c file, remove the old documentation from .h file. Signed-off-by: André Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h index 2b3667408794..28c3706e3c21 100644 --- a/drivers/media/platform/vimc/vimc-streamer.h +++ b/drivers/media/platform/vimc/vimc-streamer.h @@ -43,14 +43,6 @@ struct vimc_stream { u32 producer_pixfmt; }; -/** - * vimc_streamer_s_streamer - start/stop the stream - * - * @stream: the pointer to the stream to start or stop - * @ved: The last entity of the streamer pipeline - * @enable: any non-zero number start the stream, zero stop - * - */ int vimc_streamer_s_stream(struct vimc_stream *stream, struct vimc_ent_device *ved, int enable); -- GitLab From 959f9c841b6b7935f5168e7ade7387bc6ec324a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 24 Jun 2019 08:37:26 -0400 Subject: [PATCH 0352/7155] media: vimc: stream: fix style of argument description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As in "Function parameters" at doc-guide/kernel-doc.rst, "the continuation of the description should start at the same column as the previous line". Make the @producer_pixfmt comply with that. Signed-off-by: André Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h index 28c3706e3c21..d744a787e0e7 100644 --- a/drivers/media/platform/vimc/vimc-streamer.h +++ b/drivers/media/platform/vimc/vimc-streamer.h @@ -26,10 +26,12 @@ * @pipe_size: size of @ved_pipeline * @kthread: thread that generates the frames of the stream. * @producer_pixfmt: the pixel format requested from the pipeline. This must - * be set just before calling vimc_streamer_s_stream(ent, 1). This value is - * propagated up to the source of the base image (usually a sensor node) and - * can be modified by entities during s_stream callback to request a different - * format from rest of the pipeline. + * be set just before calling + * vimc_streamer_s_stream(ent, 1). This value is propagated + * up to the source of the base image (usually a sensor + * node) and can be modified by entities during s_stream + * callback to request a differentformat from rest of + * the pipeline. * * When the user call stream_on in a video device, struct vimc_stream is * used to keep track of all entities and subdevices that generates and -- GitLab From ed391879dd73ced1b3e41a721154deb6ed79e147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 24 Jun 2019 08:37:27 -0400 Subject: [PATCH 0353/7155] media: vimc: stream: format comments as kernel-doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Format the current existing comments as kernel-doc comments, to be reused at kernel documention. Add opening marks (/**) and return values. Signed-off-by: André Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.c | 38 +++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 3b3f36357a0e..62dde7d74c24 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -20,6 +20,8 @@ * * Helper function that returns the media entity containing the source pad * linked with the first sink pad from the given media entity pad list. + * + * Return: The source pad or NULL, if it wasn't found. */ static struct media_entity *vimc_get_source_entity(struct media_entity *ent) { @@ -35,7 +37,7 @@ static struct media_entity *vimc_get_source_entity(struct media_entity *ent) return NULL; } -/* +/** * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream * * @stream: the pointer to the stream structure with the pipeline to be @@ -63,15 +65,18 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream) } } -/* - * vimc_streamer_pipeline_init - initializes the stream structure +/** + * vimc_streamer_pipeline_init - Initializes the stream structure * * @stream: the pointer to the stream structure to be initialized * @ved: the pointer to the vimc entity initializing the stream * * Initializes the stream structure. Walks through the entity graph to * construct the pipeline used later on the streamer thread. - * Calls s_stream to enable stream in all entities of the pipeline. + * Calls vimc_streamer_s_stream() to enable stream in all entities of + * the pipeline. + * + * Return: 0 if success, error code otherwise. */ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, struct vimc_ent_device *ved) @@ -122,13 +127,17 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, return -EINVAL; } -/* - * vimc_streamer_thread - process frames through the pipeline +/** + * vimc_streamer_thread - Process frames through the pipeline * * @data: vimc_stream struct of the current stream * * From the source to the sink, gets a frame from each subdevice and send to * the next one of the pipeline at a fixed framerate. + * + * Return: + * Always zero (created as ``int`` instead of ``void`` to comply with + * kthread API). */ static int vimc_streamer_thread(void *data) { @@ -157,19 +166,20 @@ static int vimc_streamer_thread(void *data) return 0; } -/* - * vimc_streamer_s_stream - start/stop the streaming on the media pipeline +/** + * vimc_streamer_s_stream - Start/stop the streaming on the media pipeline * * @stream: the pointer to the stream structure of the current stream * @ved: pointer to the vimc entity of the entity of the stream * @enable: flag to determine if stream should start/stop * - * When starting, check if there is no stream->kthread allocated. This should - * indicate that a stream is already running. Then, it initializes - * the pipeline, creates and runs a kthread to consume buffers through the - * pipeline. - * When stopping, analogously check if there is a stream running, stop - * the thread and terminates the pipeline. + * When starting, check if there is no ``stream->kthread`` allocated. This + * should indicate that a stream is already running. Then, it initializes the + * pipeline, creates and runs a kthread to consume buffers through the pipeline. + * When stopping, analogously check if there is a stream running, stop the + * thread and terminates the pipeline. + * + * Return: 0 if success, error code otherwise. */ int vimc_streamer_s_stream(struct vimc_stream *stream, struct vimc_ent_device *ved, -- GitLab From edb0b4e24baa2cd34ea142f8ffd479853e7e6710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 24 Jun 2019 08:37:28 -0400 Subject: [PATCH 0354/7155] media: vimc.rst: Add a proper alt attribute to vimc.dot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to W3C, "the content of the alt attribute is: use text that fulfills the same function as the image". While it's hard to describe the whole content of this image, replace the actual alt to something more useful to people with slow connection or that uses screen readers. Signed-off-by: André Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/v4l-drivers/vimc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/media/v4l-drivers/vimc.rst b/Documentation/media/v4l-drivers/vimc.rst index 4628b12d417f..bece85867424 100644 --- a/Documentation/media/v4l-drivers/vimc.rst +++ b/Documentation/media/v4l-drivers/vimc.rst @@ -15,7 +15,7 @@ recompile the driver to achieve your own topology. This is the default topology: .. _vimc_topology_graph: .. kernel-figure:: vimc.dot - :alt: vimc.dot + :alt: Diagram of the default media pipeline topology :align: center Media pipeline graph on vimc -- GitLab From e2727ec58c113c2c95cbb75f6a129bd1fa0bf761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 24 Jun 2019 08:37:29 -0400 Subject: [PATCH 0355/7155] media: vimc.rst: add vimc-streamer source documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since vimc-streamer.{c, h} are fully documented and conforming with the kernel-doc syntax, add those files to vimc.rst Signed-off-by: André Almeida Suggested-by: Mauro Carvalho Chehab Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/v4l-drivers/vimc.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/media/v4l-drivers/vimc.rst b/Documentation/media/v4l-drivers/vimc.rst index bece85867424..406417680db5 100644 --- a/Documentation/media/v4l-drivers/vimc.rst +++ b/Documentation/media/v4l-drivers/vimc.rst @@ -96,3 +96,14 @@ those arguments to each subdevice, not to the vimc module. For example:: Window size to calculate the mean. Note: the window size needs to be an odd number, as the main pixel stays in the center of the window, otherwise the next odd number is considered (the default value is 3). + +Source code documentation +------------------------- + +vimc-streamer +~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/media/platform/vimc/vimc-streamer.h + :internal: + +.. kernel-doc:: drivers/media/platform/vimc/vimc-streamer.c -- GitLab From a7db285664dda63e066b943e6ec3c5f69473bf77 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 16:39:24 +0800 Subject: [PATCH 0356/7155] gpio: pch: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Acked-by: Bartosz Golaszewski Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 1d99293096f2..3f3d9a94b709 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -409,8 +409,7 @@ static int pch_gpio_probe(struct pci_dev *pdev, static int __maybe_unused pch_gpio_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pch_gpio *chip = pci_get_drvdata(pdev); + struct pch_gpio *chip = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&chip->spinlock, flags); @@ -422,8 +421,7 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev) static int __maybe_unused pch_gpio_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pch_gpio *chip = pci_get_drvdata(pdev); + struct pch_gpio *chip = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&chip->spinlock, flags); -- GitLab From ca786b8db751c0dd980fccf2d65acb77a296f629 Mon Sep 17 00:00:00 2001 From: Shaokun Zhang Date: Tue, 2 Jul 2019 15:35:53 +0800 Subject: [PATCH 0357/7155] arm64: perf: Remove unused macro ARMV8_EVENT_ATTR_RESOLVE became unused after commit <4b1a9e6934ec> ("arm64/perf: Filter common events based on PMCEIDn_EL0"). Remove it. Cc: Will Deacon Cc: Mark Rutland Signed-off-by: Shaokun Zhang Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 96e90e270042..2d3bdebdf6df 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -157,7 +157,6 @@ armv8pmu_events_sysfs_show(struct device *dev, return sprintf(page, "event=0x%03llx\n", pmu_attr->id); } -#define ARMV8_EVENT_ATTR_RESOLVE(m) #m #define ARMV8_EVENT_ATTR(name, config) \ PMU_EVENT_ATTR(name, armv8_event_attr_##name, \ config, armv8pmu_events_sysfs_show) -- GitLab From cd81a91d04b8b869bbbf62ae80bd5e8c0e7a2b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 23 Jul 2019 18:32:06 +0200 Subject: [PATCH 0358/7155] regulator: act8865: rename fixed LDO ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename act8865_ldo_ops to act8865_fixed_ldo_ops to make room for variable-output LDO ops change. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/12b1fe419e93dfe663990009bf1b2fbf630e9934.1563898936.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index e63285de485d..672ed56448ca 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -233,7 +233,7 @@ static const struct regulator_ops act8865_ops = { .is_enabled = regulator_is_enabled_regmap, }; -static const struct regulator_ops act8865_ldo_ops = { +static const struct regulator_ops act8865_fixed_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -287,7 +287,7 @@ static const struct regulator_desc act8600_regulators[] = { .of_match = of_match_ptr("LDO_REG9"), .regulators_node = of_match_ptr("regulators"), .id = ACT8600_ID_LDO9, - .ops = &act8865_ldo_ops, + .ops = &act8865_fixed_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 1, .fixed_uV = 3300000, @@ -300,7 +300,7 @@ static const struct regulator_desc act8600_regulators[] = { .of_match = of_match_ptr("LDO_REG10"), .regulators_node = of_match_ptr("regulators"), .id = ACT8600_ID_LDO10, - .ops = &act8865_ldo_ops, + .ops = &act8865_fixed_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 1, .fixed_uV = 1200000, -- GitLab From a5f888c53db575e3b04e7b4597699da67b9cd2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 23 Jul 2019 18:32:07 +0200 Subject: [PATCH 0359/7155] regulator: act8865: support regulator-pull-down property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AC8865 has internal 1.5k pull-down resistor that can be enabled when LDO is shut down. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/d7338f0dfcac63eb958a6b5e42e2d540b3d3f54a.1563898936.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 41 ++++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 672ed56448ca..b515e0785d67 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -113,6 +113,8 @@ * Field Definitions. */ #define ACT8865_ENA 0x80 /* ON - [7] */ +#define ACT8865_DIS 0x40 /* DIS - [6] */ + #define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */ @@ -233,13 +235,24 @@ static const struct regulator_ops act8865_ops = { .is_enabled = regulator_is_enabled_regmap, }; +static const struct regulator_ops act8865_ldo_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_pull_down = regulator_set_pull_down_regmap, +}; + static const struct regulator_ops act8865_fixed_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; -#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \ +#define ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, _ops) \ [_family##_ID_##_id] = { \ .name = _name, \ .of_match = of_match_ptr(_name), \ @@ -247,7 +260,7 @@ static const struct regulator_ops act8865_fixed_ldo_ops = { .supply_name = _supply, \ .id = _family##_ID_##_id, \ .type = REGULATOR_VOLTAGE, \ - .ops = &act8865_ops, \ + .ops = _ops, \ .n_voltages = ACT8865_VOLTAGE_NUM, \ .linear_ranges = act8865_voltage_ranges, \ .n_linear_ranges = ARRAY_SIZE(act8865_voltage_ranges), \ @@ -255,9 +268,17 @@ static const struct regulator_ops act8865_fixed_ldo_ops = { .vsel_mask = ACT8865_VSEL_MASK, \ .enable_reg = _family##_##_id##_CTRL, \ .enable_mask = ACT8865_ENA, \ + .pull_down_reg = _family##_##_id##_CTRL, \ + .pull_down_mask = ACT8865_DIS, \ .owner = THIS_MODULE, \ } +#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \ + ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ops) + +#define ACT88xx_LDO(_name, _family, _id, _vsel_reg, _supply) \ + ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ldo_ops) + static const struct regulator_desc act8600_regulators[] = { ACT88xx_REG("DCDC1", ACT8600, DCDC1, VSET, "vp1"), ACT88xx_REG("DCDC2", ACT8600, DCDC2, VSET, "vp2"), @@ -329,20 +350,20 @@ static const struct regulator_desc act8865_regulators[] = { ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"), ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"), ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"), - ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), - ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), - ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), - ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), + ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), + ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), + ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), + ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), }; static const struct regulator_desc act8865_alt_regulators[] = { ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET2, "vp1"), ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET2, "vp2"), ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET2, "vp3"), - ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), - ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), - ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), - ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), + ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), + ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), + ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), + ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), }; #ifdef CONFIG_OF -- GitLab From 859fd6cbf1fb32b5428c26f837215c085b8a822e Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Mon, 22 Jul 2019 16:24:01 +0900 Subject: [PATCH 0360/7155] ASoC: rsnd: Support hw_free() callback at DAI level This patch provides the needed infrastructure to support calling hw_free() at the DAI level. This is for example required to free resources allocated in hw_params() callback. The modification of __rsnd_mod_add_hw_params does not have any side effects because rsnd_mod_ops::hw_params callback is not used by anyone until now. Signed-off-by: Timo Wischer Signed-off-by: Jiada Wang Link: https://lore.kernel.org/r/20190722072403.11008-2-jiada_wang@mentor.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 16 +++++++++++++++- sound/soc/sh/rcar/rsnd.h | 12 +++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 56e8dae9a15c..bda5b958d0dc 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1421,6 +1421,20 @@ static int rsnd_hw_params(struct snd_pcm_substream *substream, params_buffer_bytes(hw_params)); } +static int rsnd_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); + struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); + int ret; + + ret = rsnd_dai_call(hw_free, io, substream); + if (ret) + return ret; + + return snd_pcm_lib_free_pages(substream); +} + static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) { struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); @@ -1436,7 +1450,7 @@ static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) static const struct snd_pcm_ops rsnd_pcm_ops = { .ioctl = snd_pcm_lib_ioctl, .hw_params = rsnd_hw_params, - .hw_free = snd_pcm_lib_free_pages, + .hw_free = rsnd_hw_free, .pointer = rsnd_pointer, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 7727add3eb1a..ea6cbaa9743e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -327,6 +327,9 @@ struct rsnd_mod_ops { int (*cleanup)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv); + int (*hw_free)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct snd_pcm_substream *substream); u32 *(*get_status)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, enum rsnd_mod_type type); @@ -351,12 +354,12 @@ struct rsnd_mod { * * B 0: init 1: quit * C 0: start 1: stop + * D 0: hw_params 1: hw_free * * H is always called (see __rsnd_mod_call) * H 0: probe 1: remove * H 0: pcm_new * H 0: fallback - * H 0: hw_params * H 0: pointer * H 0: prepare * H 0: cleanup @@ -365,12 +368,13 @@ struct rsnd_mod { #define __rsnd_mod_shift_quit 4 #define __rsnd_mod_shift_start 8 #define __rsnd_mod_shift_stop 8 +#define __rsnd_mod_shift_hw_params 12 +#define __rsnd_mod_shift_hw_free 12 #define __rsnd_mod_shift_probe 28 /* always called */ #define __rsnd_mod_shift_remove 28 /* always called */ #define __rsnd_mod_shift_irq 28 /* always called */ #define __rsnd_mod_shift_pcm_new 28 /* always called */ #define __rsnd_mod_shift_fallback 28 /* always called */ -#define __rsnd_mod_shift_hw_params 28 /* always called */ #define __rsnd_mod_shift_pointer 28 /* always called */ #define __rsnd_mod_shift_prepare 28 /* always called */ #define __rsnd_mod_shift_cleanup 28 /* always called */ @@ -383,10 +387,11 @@ struct rsnd_mod { #define __rsnd_mod_add_quit -1 #define __rsnd_mod_add_start 1 #define __rsnd_mod_add_stop -1 +#define __rsnd_mod_add_hw_params 1 +#define __rsnd_mod_add_hw_free -1 #define __rsnd_mod_add_irq 0 #define __rsnd_mod_add_pcm_new 0 #define __rsnd_mod_add_fallback 0 -#define __rsnd_mod_add_hw_params 0 #define __rsnd_mod_add_pointer 0 #define __rsnd_mod_call_probe 0 @@ -402,6 +407,7 @@ struct rsnd_mod { #define __rsnd_mod_call_fallback 0 #define __rsnd_mod_call_hw_params 0 #define __rsnd_mod_call_pointer 0 +#define __rsnd_mod_call_hw_free 1 #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_power_on(mod) clk_enable((mod)->clk) -- GitLab From 06f6e1d41427f394ad3f67ecf06efcd28a46932c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:32:12 +0900 Subject: [PATCH 0361/7155] ASoC: add soc-dai.c Current ALSA SoC has many snd_soc_dai_xxx() function which is using dai->driver->ops->xxx. But, some of them are implemented as snd_soc_dai_xxx(), but others are directly using dai->driver->ops->xxx. Because of it, the code is not easy to read. This patch creats new soc-dai.c and moves snd_soc_dai_xxx() functions into it. One exception is snd_soc_dai_is_dummy() which is based on soc-utils local variable. We need to keep it as-is there. Others which is directly using dai->driver->ops->xxx will be implemented at soc-dai.c by incremental patches. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871ryij1r6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/Makefile | 2 +- sound/soc/soc-core.c | 243 ----------------------------------------- sound/soc/soc-dai.c | 254 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 244 deletions(-) create mode 100644 sound/soc/soc-dai.c diff --git a/sound/soc/Makefile b/sound/soc/Makefile index d90ce8a32887..919c3c027c62 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fd6eaae6c0ed..6e8c5c8eeaec 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2394,26 +2394,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); -/** - * snd_soc_dai_set_sysclk - configure DAI system or master clock. - * @dai: DAI - * @clk_id: DAI specific clock ID - * @freq: new clock frequency in Hz - * @dir: new clock direction - input/output. - * - * Configures the DAI master (MCLK) or system (SYSCLK) clocking. - */ -int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - if (dai->driver->ops->set_sysclk) - return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); - - return snd_soc_component_set_sysclk(dai->component, clk_id, 0, - freq, dir); -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); - /** * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. * @component: COMPONENT @@ -2436,48 +2416,6 @@ int snd_soc_component_set_sysclk(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); -/** - * snd_soc_dai_set_clkdiv - configure DAI clock dividers. - * @dai: DAI - * @div_id: DAI specific clock divider ID - * @div: new clock divisor. - * - * Configures the clock dividers. This is used to derive the best DAI bit and - * frame clocks from the system or master clock. It's best to set the DAI bit - * and frame clocks as low as possible to save system power. - */ -int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, - int div_id, int div) -{ - if (dai->driver->ops->set_clkdiv) - return dai->driver->ops->set_clkdiv(dai, div_id, div); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); - -/** - * snd_soc_dai_set_pll - configure DAI PLL. - * @dai: DAI - * @pll_id: DAI specific PLL ID - * @source: DAI specific source for the PLL - * @freq_in: PLL input clock frequency in Hz - * @freq_out: requested PLL output clock frequency in Hz - * - * Configures and enables PLL to generate output clock based on input clock. - */ -int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, - unsigned int freq_in, unsigned int freq_out) -{ - if (dai->driver->ops->set_pll) - return dai->driver->ops->set_pll(dai, pll_id, source, - freq_in, freq_out); - - return snd_soc_component_set_pll(dai->component, pll_id, source, - freq_in, freq_out); -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); - /* * snd_soc_component_set_pll - configure component PLL. * @component: COMPONENT @@ -2500,187 +2438,6 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, } EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); -/** - * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. - * @dai: DAI - * @ratio: Ratio of BCLK to Sample rate. - * - * Configures the DAI for a preset BCLK to sample rate ratio. - */ -int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) -{ - if (dai->driver->ops->set_bclk_ratio) - return dai->driver->ops->set_bclk_ratio(dai, ratio); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); - -/** - * snd_soc_dai_set_fmt - configure DAI hardware audio format. - * @dai: DAI - * @fmt: SND_SOC_DAIFMT_* format value. - * - * Configures the DAI hardware format and clocking. - */ -int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - if (dai->driver->ops->set_fmt == NULL) - return -ENOTSUPP; - return dai->driver->ops->set_fmt(dai, fmt); -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); - -/** - * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. - * @slots: Number of slots in use. - * @tx_mask: bitmask representing active TX slots. - * @rx_mask: bitmask representing active RX slots. - * - * Generates the TDM tx and rx slot default masks for DAI. - */ -static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, - unsigned int *tx_mask, - unsigned int *rx_mask) -{ - if (*tx_mask || *rx_mask) - return 0; - - if (!slots) - return -EINVAL; - - *tx_mask = (1 << slots) - 1; - *rx_mask = (1 << slots) - 1; - - return 0; -} - -/** - * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation - * @dai: The DAI to configure - * @tx_mask: bitmask representing active TX slots. - * @rx_mask: bitmask representing active RX slots. - * @slots: Number of slots in use. - * @slot_width: Width in bits for each slot. - * - * This function configures the specified DAI for TDM operation. @slot contains - * the total number of slots of the TDM stream and @slot_with the width of each - * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the - * active slots of the TDM stream for the specified DAI, i.e. which slots the - * DAI should write to or read from. If a bit is set the corresponding slot is - * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to - * the first slot, bit 1 to the second slot and so on. The first active slot - * maps to the first channel of the DAI, the second active slot to the second - * channel and so on. - * - * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, - * @rx_mask and @slot_width will be ignored. - * - * Returns 0 on success, a negative error code otherwise. - */ -int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) -{ - if (dai->driver->ops->xlate_tdm_slot_mask) - dai->driver->ops->xlate_tdm_slot_mask(slots, - &tx_mask, &rx_mask); - else - snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); - - dai->tx_mask = tx_mask; - dai->rx_mask = rx_mask; - - if (dai->driver->ops->set_tdm_slot) - return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, - slots, slot_width); - else - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); - -/** - * snd_soc_dai_set_channel_map - configure DAI audio channel map - * @dai: DAI - * @tx_num: how many TX channels - * @tx_slot: pointer to an array which imply the TX slot number channel - * 0~num-1 uses - * @rx_num: how many RX channels - * @rx_slot: pointer to an array which imply the RX slot number channel - * 0~num-1 uses - * - * configure the relationship between channel number and TDM slot number. - */ -int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot) -{ - if (dai->driver->ops->set_channel_map) - return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, - rx_num, rx_slot); - else - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); - -/** - * snd_soc_dai_get_channel_map - Get DAI audio channel map - * @dai: DAI - * @tx_num: how many TX channels - * @tx_slot: pointer to an array which imply the TX slot number channel - * 0~num-1 uses - * @rx_num: how many RX channels - * @rx_slot: pointer to an array which imply the RX slot number channel - * 0~num-1 uses - */ -int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, - unsigned int *tx_num, unsigned int *tx_slot, - unsigned int *rx_num, unsigned int *rx_slot) -{ - if (dai->driver->ops->get_channel_map) - return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, - rx_num, rx_slot); - else - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); - -/** - * snd_soc_dai_set_tristate - configure DAI system or master clock. - * @dai: DAI - * @tristate: tristate enable - * - * Tristates the DAI so that others can use it. - */ -int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - if (dai->driver->ops->set_tristate) - return dai->driver->ops->set_tristate(dai, tristate); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); - -/** - * snd_soc_dai_digital_mute - configure DAI system or master clock. - * @dai: DAI - * @mute: mute enable - * @direction: stream to mute - * - * Mutes the DAI DAC. - */ -int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, - int direction) -{ - if (dai->driver->ops->mute_stream) - return dai->driver->ops->mute_stream(dai, mute, direction); - else if (direction == SNDRV_PCM_STREAM_PLAYBACK && - dai->driver->ops->digital_mute) - return dai->driver->ops->digital_mute(dai, mute); - else - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); - static int snd_soc_bind_card(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c new file mode 100644 index 000000000000..a1009ead40de --- /dev/null +++ b/sound/soc/soc-dai.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-dai.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// + +#include +#include + +/** + * snd_soc_dai_set_sysclk - configure DAI system or master clock. + * @dai: DAI + * @clk_id: DAI specific clock ID + * @freq: new clock frequency in Hz + * @dir: new clock direction - input/output. + * + * Configures the DAI master (MCLK) or system (SYSCLK) clocking. + */ +int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + if (dai->driver->ops->set_sysclk) + return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); + + return snd_soc_component_set_sysclk(dai->component, clk_id, 0, + freq, dir); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); + +/** + * snd_soc_dai_set_clkdiv - configure DAI clock dividers. + * @dai: DAI + * @div_id: DAI specific clock divider ID + * @div: new clock divisor. + * + * Configures the clock dividers. This is used to derive the best DAI bit and + * frame clocks from the system or master clock. It's best to set the DAI bit + * and frame clocks as low as possible to save system power. + */ +int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, + int div_id, int div) +{ + if (dai->driver->ops->set_clkdiv) + return dai->driver->ops->set_clkdiv(dai, div_id, div); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); + +/** + * snd_soc_dai_set_pll - configure DAI PLL. + * @dai: DAI + * @pll_id: DAI specific PLL ID + * @source: DAI specific source for the PLL + * @freq_in: PLL input clock frequency in Hz + * @freq_out: requested PLL output clock frequency in Hz + * + * Configures and enables PLL to generate output clock based on input clock. + */ +int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + if (dai->driver->ops->set_pll) + return dai->driver->ops->set_pll(dai, pll_id, source, + freq_in, freq_out); + + return snd_soc_component_set_pll(dai->component, pll_id, source, + freq_in, freq_out); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); + +/** + * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. + * @dai: DAI + * @ratio: Ratio of BCLK to Sample rate. + * + * Configures the DAI for a preset BCLK to sample rate ratio. + */ +int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + if (dai->driver->ops->set_bclk_ratio) + return dai->driver->ops->set_bclk_ratio(dai, ratio); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); + +/** + * snd_soc_dai_set_fmt - configure DAI hardware audio format. + * @dai: DAI + * @fmt: SND_SOC_DAIFMT_* format value. + * + * Configures the DAI hardware format and clocking. + */ +int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + if (dai->driver->ops->set_fmt == NULL) + return -ENOTSUPP; + return dai->driver->ops->set_fmt(dai, fmt); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); + +/** + * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + +/** + * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation + * @dai: The DAI to configure + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * @slots: Number of slots in use. + * @slot_width: Width in bits for each slot. + * + * This function configures the specified DAI for TDM operation. @slot contains + * the total number of slots of the TDM stream and @slot_with the width of each + * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the + * active slots of the TDM stream for the specified DAI, i.e. which slots the + * DAI should write to or read from. If a bit is set the corresponding slot is + * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to + * the first slot, bit 1 to the second slot and so on. The first active slot + * maps to the first channel of the DAI, the second active slot to the second + * channel and so on. + * + * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, + * @rx_mask and @slot_width will be ignored. + * + * Returns 0 on success, a negative error code otherwise. + */ +int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + if (dai->driver->ops->xlate_tdm_slot_mask) + dai->driver->ops->xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + + dai->tx_mask = tx_mask; + dai->rx_mask = rx_mask; + + if (dai->driver->ops->set_tdm_slot) + return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, + slots, slot_width); + else + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); + +/** + * snd_soc_dai_set_channel_map - configure DAI audio channel map + * @dai: DAI + * @tx_num: how many TX channels + * @tx_slot: pointer to an array which imply the TX slot number channel + * 0~num-1 uses + * @rx_num: how many RX channels + * @rx_slot: pointer to an array which imply the RX slot number channel + * 0~num-1 uses + * + * configure the relationship between channel number and TDM slot number. + */ +int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot) +{ + if (dai->driver->ops->set_channel_map) + return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, + rx_num, rx_slot); + else + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); + +/** + * snd_soc_dai_get_channel_map - Get DAI audio channel map + * @dai: DAI + * @tx_num: how many TX channels + * @tx_slot: pointer to an array which imply the TX slot number channel + * 0~num-1 uses + * @rx_num: how many RX channels + * @rx_slot: pointer to an array which imply the RX slot number channel + * 0~num-1 uses + */ +int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + if (dai->driver->ops->get_channel_map) + return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, + rx_num, rx_slot); + else + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); + +/** + * snd_soc_dai_set_tristate - configure DAI system or master clock. + * @dai: DAI + * @tristate: tristate enable + * + * Tristates the DAI so that others can use it. + */ +int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + if (dai->driver->ops->set_tristate) + return dai->driver->ops->set_tristate(dai, tristate); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); + +/** + * snd_soc_dai_digital_mute - configure DAI system or master clock. + * @dai: DAI + * @mute: mute enable + * @direction: stream to mute + * + * Mutes the DAI DAC. + */ +int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, + int direction) +{ + if (dai->driver->ops->mute_stream) + return dai->driver->ops->mute_stream(dai, mute, direction); + else if (direction == SNDRV_PCM_STREAM_PLAYBACK && + dai->driver->ops->digital_mute) + return dai->driver->ops->digital_mute(dai, mute); + else + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); -- GitLab From aa6166c2ac28392d64f2d8b3acfb56c8fe657147 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:04 +0900 Subject: [PATCH 0362/7155] ASoC: soc-dai: mv soc_dai_hw_params() to soc-dai Sometimes ALSA SoC naming is very random. Current soc_dai_hw_params() should use snd_soc_dai_xxx() style. And then, 1st parameter should be dai. Otherwise it is confusable. - soc_dai_hw_params(..., dai); + snd_soc_dai_hw_params(dai, ...); Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zhl6hn5b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 4 ++++ include/sound/soc.h | 4 ---- sound/soc/soc-dai.c | 30 ++++++++++++++++++++++++++++++ sound/soc/soc-dapm.c | 4 ++-- sound/soc/soc-pcm.c | 35 +++-------------------------------- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index f5d70041108f..3773262a1b77 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -145,6 +145,10 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); +int snd_soc_dai_hw_params(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/include/sound/soc.h b/include/sound/soc.h index 4e8071269639..d770606732cd 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -505,10 +505,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); -int soc_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai); - /* Jack reporting */ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index a1009ead40de..f883d27d136f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -252,3 +252,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); + +int snd_soc_dai_hw_params(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int ret; + + /* perform any topology hw_params fixups before DAI */ + if (rtd->dai_link->be_hw_params_fixup) { + ret = rtd->dai_link->be_hw_params_fixup(rtd, params); + if (ret < 0) { + dev_err(rtd->dev, + "ASoC: hw_params topology fixup failed %d\n", + ret); + return ret; + } + } + + if (dai->driver->ops->hw_params) { + ret = dai->driver->ops->hw_params(substream, params, dai); + if (ret < 0) { + dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", + dai->name, ret); + return ret; + } + } + + return 0; +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f013b24c050a..8fc6a01f5d8b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3839,7 +3839,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, } } source->active++; - ret = soc_dai_hw_params(&substream, params, source); + ret = snd_soc_dai_hw_params(source, &substream, params); if (ret < 0) goto out; @@ -3861,7 +3861,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, } } sink->active++; - ret = soc_dai_hw_params(&substream, params, sink); + ret = snd_soc_dai_hw_params(sink, &substream, params); if (ret < 0) goto out; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4878d22ebd8c..420cc94e0a46 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -877,36 +877,6 @@ static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, interval->max = channels; } -int soc_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int ret; - - /* perform any topology hw_params fixups before DAI */ - if (rtd->dai_link->be_hw_params_fixup) { - ret = rtd->dai_link->be_hw_params_fixup(rtd, params); - if (ret < 0) { - dev_err(rtd->dev, - "ASoC: hw_params topology fixup failed %d\n", - ret); - return ret; - } - } - - if (dai->driver->ops->hw_params) { - ret = dai->driver->ops->hw_params(substream, params, dai); - if (ret < 0) { - dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", - dai->name, ret); - return ret; - } - } - - return 0; -} - static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *last) { @@ -989,7 +959,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, soc_pcm_codec_params_fixup(&codec_params, codec_dai->rx_mask); - ret = soc_dai_hw_params(substream, &codec_params, codec_dai); + ret = snd_soc_dai_hw_params(codec_dai, substream, + &codec_params); if(ret < 0) goto codec_err; @@ -1001,7 +972,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); } - ret = soc_dai_hw_params(substream, params, cpu_dai); + ret = snd_soc_dai_hw_params(cpu_dai, substream, params); if (ret < 0) goto interface_err; -- GitLab From 846faaed9df7899e74311db3aec0a41a2f6bc345 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:19 +0900 Subject: [PATCH 0363/7155] ASoC: soc-dai: add snd_soc_dai_hw_free() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_hw_free() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y30qhn4w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 7 +++++++ sound/soc/soc-dapm.c | 7 ++----- sound/soc/soc-pcm.c | 12 ++++-------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 3773262a1b77..5222b6a758f2 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -148,6 +148,8 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); +void snd_soc_dai_hw_free(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index f883d27d136f..39a685e6acd5 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -282,3 +282,10 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, return 0; } + +void snd_soc_dai_hw_free(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream) +{ + if (dai->driver->ops->hw_free) + dai->driver->ops->hw_free(substream, dai); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8fc6a01f5d8b..0783b05133ad 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3898,9 +3898,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; - if (source->driver->ops->hw_free) - source->driver->ops->hw_free(&substream, - source); + snd_soc_dai_hw_free(source, &substream); source->active--; if (source->driver->ops->shutdown) @@ -3912,8 +3910,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - if (sink->driver->ops->hw_free) - sink->driver->ops->hw_free(&substream, sink); + snd_soc_dai_hw_free(sink, &substream); sink->active--; if (sink->driver->ops->shutdown) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 420cc94e0a46..58fc4e98ab59 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1011,8 +1011,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, component_err: soc_pcm_components_hw_free(substream, component); - if (cpu_dai->driver->ops->hw_free) - cpu_dai->driver->ops->hw_free(substream, cpu_dai); + snd_soc_dai_hw_free(cpu_dai, substream); cpu_dai->rate = 0; interface_err: @@ -1023,8 +1022,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) continue; - if (codec_dai->driver->ops->hw_free) - codec_dai->driver->ops->hw_free(substream, codec_dai); + snd_soc_dai_hw_free(codec_dai, substream); codec_dai->rate = 0; } @@ -1083,12 +1081,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) continue; - if (codec_dai->driver->ops->hw_free) - codec_dai->driver->ops->hw_free(substream, codec_dai); + snd_soc_dai_hw_free(codec_dai, substream); } - if (cpu_dai->driver->ops->hw_free) - cpu_dai->driver->ops->hw_free(substream, cpu_dai); + snd_soc_dai_hw_free(cpu_dai, substream); mutex_unlock(&rtd->pcm_mutex); return 0; -- GitLab From 5a52a04531486e2ab069b7882432c8b266db36e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:32 +0900 Subject: [PATCH 0364/7155] ASoC: soc-dai: add snd_soc_dai_startup() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_startup() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wogahn4i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 11 +++++++++++ sound/soc/soc-dapm.c | 28 ++++++++++------------------ sound/soc/soc-pcm.c | 27 +++++++++++---------------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 5222b6a758f2..0d16c5bb20bb 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -150,6 +150,8 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_hw_params *params); void snd_soc_dai_hw_free(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); +int snd_soc_dai_startup(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 39a685e6acd5..6e196636e42f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -289,3 +289,14 @@ void snd_soc_dai_hw_free(struct snd_soc_dai *dai, if (dai->driver->ops->hw_free) dai->driver->ops->hw_free(substream, dai); } + +int snd_soc_dai_startup(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (dai->driver->ops->startup) + ret = dai->driver->ops->startup(substream, dai); + + return ret; +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 0783b05133ad..71bfd049480a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3828,15 +3828,11 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; - if (source->driver->ops->startup) { - ret = source->driver->ops->startup(&substream, - source); - if (ret < 0) { - dev_err(source->dev, - "ASoC: startup() failed: %d\n", - ret); - goto out; - } + ret = snd_soc_dai_startup(source, &substream); + if (ret < 0) { + dev_err(source->dev, + "ASoC: startup() failed: %d\n", ret); + goto out; } source->active++; ret = snd_soc_dai_hw_params(source, &substream, params); @@ -3850,15 +3846,11 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - if (sink->driver->ops->startup) { - ret = sink->driver->ops->startup(&substream, - sink); - if (ret < 0) { - dev_err(sink->dev, - "ASoC: startup() failed: %d\n", - ret); - goto out; - } + ret = snd_soc_dai_startup(sink, &substream); + if (ret < 0) { + dev_err(sink->dev, + "ASoC: startup() failed: %d\n", ret); + goto out; } sink->active++; ret = snd_soc_dai_hw_params(sink, &substream, params); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 58fc4e98ab59..9c8713a3eef1 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -535,13 +535,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); /* startup the audio subsystem */ - if (cpu_dai->driver->ops->startup) { - ret = cpu_dai->driver->ops->startup(substream, cpu_dai); - if (ret < 0) { - dev_err(cpu_dai->dev, "ASoC: can't open interface" - " %s: %d\n", cpu_dai->name, ret); - goto out; - } + ret = snd_soc_dai_startup(cpu_dai, substream); + if (ret < 0) { + dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", + cpu_dai->name, ret); + goto out; } ret = soc_pcm_components_open(substream, &component); @@ -549,15 +547,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) goto component_err; for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->startup) { - ret = codec_dai->driver->ops->startup(substream, - codec_dai); - if (ret < 0) { - dev_err(codec_dai->dev, - "ASoC: can't open codec %s: %d\n", - codec_dai->name, ret); - goto codec_dai_err; - } + ret = snd_soc_dai_startup(codec_dai, substream); + if (ret < 0) { + dev_err(codec_dai->dev, + "ASoC: can't open codec %s: %d\n", + codec_dai->name, ret); + goto codec_dai_err; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- GitLab From 330fcb5135e0588b1ea3b0bbab587d1317c1cf7b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:39 +0900 Subject: [PATCH 0365/7155] ASoC: soc-dai: add snd_soc_dai_shutdown() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_shutdown() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9vuhn4b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 7 +++++++ sound/soc/soc-dapm.c | 7 ++----- sound/soc/soc-pcm.c | 18 ++++++------------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 0d16c5bb20bb..32545d457b3d 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -152,6 +152,8 @@ void snd_soc_dai_hw_free(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); +void snd_soc_dai_shutdown(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 6e196636e42f..67ff6cc1fe02 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -300,3 +300,10 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, return ret; } + +void snd_soc_dai_shutdown(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream) +{ + if (dai->driver->ops->shutdown) + dai->driver->ops->shutdown(substream, dai); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 71bfd049480a..1d04612601ad 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3893,9 +3893,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dai_hw_free(source, &substream); source->active--; - if (source->driver->ops->shutdown) - source->driver->ops->shutdown(&substream, - source); + snd_soc_dai_shutdown(source, &substream); } substream.stream = SNDRV_PCM_STREAM_PLAYBACK; @@ -3905,8 +3903,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dai_hw_free(sink, &substream); sink->active--; - if (sink->driver->ops->shutdown) - sink->driver->ops->shutdown(&substream, sink); + snd_soc_dai_shutdown(sink, &substream); } break; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 9c8713a3eef1..ed5ae23c7104 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -641,16 +641,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) i = rtd->num_codecs; codec_dai_err: - for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { - if (codec_dai->driver->ops->shutdown) - codec_dai->driver->ops->shutdown(substream, codec_dai); - } + for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) + snd_soc_dai_shutdown(codec_dai, substream); component_err: soc_pcm_components_close(substream, component); - if (cpu_dai->driver->ops->shutdown) - cpu_dai->driver->ops->shutdown(substream, cpu_dai); + snd_soc_dai_shutdown(cpu_dai, substream); out: mutex_unlock(&rtd->pcm_mutex); @@ -728,13 +725,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); - if (cpu_dai->driver->ops->shutdown) - cpu_dai->driver->ops->shutdown(substream, cpu_dai); + snd_soc_dai_shutdown(cpu_dai, substream); - for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->shutdown) - codec_dai->driver->ops->shutdown(substream, codec_dai); - } + for_each_rtd_codec_dai(rtd, i, codec_dai) + snd_soc_dai_shutdown(codec_dai, substream); if (rtd->dai_link->ops->shutdown) rtd->dai_link->ops->shutdown(substream); -- GitLab From 4beb8e109d30d339d44308a767dd6f5614492f3e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:45 +0900 Subject: [PATCH 0366/7155] ASoC: soc-dai: add snd_soc_dai_prepare() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_prepare() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tvbehn46.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 11 +++++++++++ sound/soc/soc-pcm.c | 27 +++++++++++---------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 32545d457b3d..c7dff6a0b5b9 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,6 +154,8 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); +int snd_soc_dai_prepare(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 67ff6cc1fe02..cb810888c563 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -307,3 +307,14 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, if (dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); } + +int snd_soc_dai_prepare(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (dai->driver->ops->prepare) + ret = dai->driver->ops->prepare(substream, dai); + + return ret; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ed5ae23c7104..d7611af90dce 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -814,27 +814,22 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->prepare) { - ret = codec_dai->driver->ops->prepare(substream, - codec_dai); - if (ret < 0) { - dev_err(codec_dai->dev, - "ASoC: codec DAI prepare error: %d\n", - ret); - goto out; - } - } - } - - if (cpu_dai->driver->ops->prepare) { - ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); + ret = snd_soc_dai_prepare(codec_dai, substream); if (ret < 0) { - dev_err(cpu_dai->dev, - "ASoC: cpu DAI prepare error: %d\n", ret); + dev_err(codec_dai->dev, + "ASoC: codec DAI prepare error: %d\n", + ret); goto out; } } + ret = snd_soc_dai_prepare(cpu_dai, substream); + if (ret < 0) { + dev_err(cpu_dai->dev, + "ASoC: cpu DAI prepare error: %d\n", ret); + goto out; + } + /* cancel any delayed stream shutdown that is pending */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && rtd->pop_wait) { -- GitLab From 95aef35533844f35544851b0cdc1fc154b603307 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:51 +0900 Subject: [PATCH 0367/7155] ASoC: soc-dai: add snd_soc_dai_trigger() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_trigger() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sgqyhn40.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 12 ++++++++++++ sound/soc/soc-pcm.c | 17 ++++++----------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index c7dff6a0b5b9..72b8e76f1cc4 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -156,6 +156,8 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); int snd_soc_dai_prepare(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); +int snd_soc_dai_trigger(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index cb810888c563..18c447e169f6 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -318,3 +318,15 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, return ret; } + +int snd_soc_dai_trigger(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, + int cmd) +{ + int ret = 0; + + if (dai->driver->ops->trigger) + ret = dai->driver->ops->trigger(substream, cmd, dai); + + return ret; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d7611af90dce..a628b08f966e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1084,12 +1084,9 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) int i, ret; for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->trigger) { - ret = codec_dai->driver->ops->trigger(substream, - cmd, codec_dai); - if (ret < 0) - return ret; - } + ret = snd_soc_dai_trigger(codec_dai, substream, cmd); + if (ret < 0) + return ret; } for_each_rtdcom(rtd, rtdcom) { @@ -1104,11 +1101,9 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } - if (cpu_dai->driver->ops->trigger) { - ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); - if (ret < 0) - return ret; - } + snd_soc_dai_trigger(cpu_dai, substream, cmd); + if (ret < 0) + return ret; if (rtd->dai_link->ops->trigger) { ret = rtd->dai_link->ops->trigger(substream, cmd); -- GitLab From 5c0769af4caf8fbdad2e9c0051ab0081b8e22b0a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:33:56 +0900 Subject: [PATCH 0368/7155] ASoC: soc-dai: add snd_soc_dai_bespoke_trigger() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_bespoke_trigger() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r26ihn3u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 12 ++++++++++++ sound/soc/soc-pcm.c | 16 ++++++---------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 72b8e76f1cc4..6a5566d459ad 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -158,6 +158,8 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); +int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 18c447e169f6..6f466cfcbeef 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -330,3 +330,15 @@ int snd_soc_dai_trigger(struct snd_soc_dai *dai, return ret; } + +int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream, + int cmd) +{ + int ret = 0; + + if (dai->driver->ops->bespoke_trigger) + ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); + + return ret; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a628b08f966e..a10627f1ceff 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1123,19 +1123,15 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int i, ret; for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->bespoke_trigger) { - ret = codec_dai->driver->ops->bespoke_trigger(substream, - cmd, codec_dai); - if (ret < 0) - return ret; - } - } - - if (cpu_dai->driver->ops->bespoke_trigger) { - ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); + ret = snd_soc_dai_bespoke_trigger(codec_dai, substream, cmd); if (ret < 0) return ret; } + + snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); + if (ret < 0) + return ret; + return 0; } /* -- GitLab From 1dea80d4b2bd3b53c58f008ca2bcd73182583711 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:34:09 +0900 Subject: [PATCH 0369/7155] ASoC: soc-dai: add snd_soc_dai_delay() Current ALSA SoC is directly using dai->driver->ops->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_delay() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o91mhn3i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-dai.c | 11 +++++++++++ sound/soc/soc-pcm.c | 9 +++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 6a5566d459ad..7cfed3034511 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -160,6 +160,8 @@ int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); +snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 6f466cfcbeef..5b5b979cd1f3 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -342,3 +342,14 @@ int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, return ret; } + +snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream) +{ + int delay = 0; + + if (dai->driver->ops->delay) + delay = dai->driver->ops->delay(substream, dai); + + return delay; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a10627f1ceff..f3137723301c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1169,14 +1169,11 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) /* base delay if assigned in pointer callback */ delay = runtime->delay; - if (cpu_dai->driver->ops->delay) - delay += cpu_dai->driver->ops->delay(substream, cpu_dai); + delay += snd_soc_dai_delay(cpu_dai, substream); for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->ops->delay) - codec_delay = max(codec_delay, - codec_dai->driver->ops->delay(substream, - codec_dai)); + codec_delay = max(codec_delay, + snd_soc_dai_delay(codec_dai, substream)); } delay += codec_delay; -- GitLab From e0f2262292d0c8160cfd9a8c40425107fb65ab29 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:34:29 +0900 Subject: [PATCH 0370/7155] ASoC: soc-dai: add snd_soc_dai_suspend() Current ALSA SoC is directly using dai->driver->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_suspend() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87muh6hn2x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-core.c | 8 ++++---- sound/soc/soc-dai.c | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 7cfed3034511..6c5604a7dbc2 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -162,6 +162,7 @@ int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); +void snd_soc_dai_suspend(struct snd_soc_dai *dai); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6e8c5c8eeaec..7493afb2371c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -511,8 +511,8 @@ int snd_soc_suspend(struct device *dev) if (rtd->dai_link->ignore_suspend) continue; - if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) - cpu_dai->driver->suspend(cpu_dai); + if (!cpu_dai->driver->bus_control) + snd_soc_dai_suspend(cpu_dai); } /* close any waiting streams */ @@ -584,8 +584,8 @@ int snd_soc_suspend(struct device *dev) if (rtd->dai_link->ignore_suspend) continue; - if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) - cpu_dai->driver->suspend(cpu_dai); + if (cpu_dai->driver->bus_control) + snd_soc_dai_suspend(cpu_dai); /* deactivate pins to sleep state */ pinctrl_pm_select_sleep_state(cpu_dai->dev); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 5b5b979cd1f3..3373598e0682 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -353,3 +353,9 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, return delay; } + +void snd_soc_dai_suspend(struct snd_soc_dai *dai) +{ + if (dai->driver->suspend) + dai->driver->suspend(dai); +} -- GitLab From 24b09d051164680f0a1d1910efe21ce36ad5c1ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:34:43 +0900 Subject: [PATCH 0371/7155] ASoC: soc-dai: add snd_soc_dai_resume() Current ALSA SoC is directly using dai->driver->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_resume() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfwqhn2j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-core.c | 8 ++++---- sound/soc/soc-dai.c | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 6c5604a7dbc2..ed78e34a814e 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -163,6 +163,7 @@ int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); +void snd_soc_dai_resume(struct snd_soc_dai *dai); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7493afb2371c..5c02f90cea69 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -631,8 +631,8 @@ static void soc_resume_deferred(struct work_struct *work) if (rtd->dai_link->ignore_suspend) continue; - if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) - cpu_dai->driver->resume(cpu_dai); + if (cpu_dai->driver->bus_control) + snd_soc_dai_resume(cpu_dai); } for_each_card_components(card, component) { @@ -678,8 +678,8 @@ static void soc_resume_deferred(struct work_struct *work) if (rtd->dai_link->ignore_suspend) continue; - if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) - cpu_dai->driver->resume(cpu_dai); + if (!cpu_dai->driver->bus_control) + snd_soc_dai_resume(cpu_dai); } if (card->resume_post) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 3373598e0682..ddb6f217c0ed 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -359,3 +359,9 @@ void snd_soc_dai_suspend(struct snd_soc_dai *dai) if (dai->driver->suspend) dai->driver->suspend(dai); } + +void snd_soc_dai_resume(struct snd_soc_dai *dai) +{ + if (dai->driver->resume) + dai->driver->resume(dai); +} -- GitLab From cfd9b5fbfe1e8763018aea2600aa0d6ff015ebfc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:34:56 +0900 Subject: [PATCH 0372/7155] ASoC: soc-dai: add snd_soc_dai_probe() Current ALSA SoC is directly using dai->driver->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_probe() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k1cahn26.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-core.c | 15 +++++++-------- sound/soc/soc-dai.c | 7 +++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ed78e34a814e..da8d8b889089 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -164,6 +164,7 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); +int snd_soc_dai_probe(struct snd_soc_dai *dai); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5c02f90cea69..3e73468225f9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1434,18 +1434,17 @@ static int soc_probe_link_components(struct snd_soc_card *card, static int soc_probe_dai(struct snd_soc_dai *dai, int order) { + int ret; + if (dai->probed || dai->driver->probe_order != order) return 0; - if (dai->driver->probe) { - int ret = dai->driver->probe(dai); - - if (ret < 0) { - dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", - dai->name, ret); - return ret; - } + ret = snd_soc_dai_probe(dai); + if (ret < 0) { + dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", + dai->name, ret); + return ret; } dai->probed = 1; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index ddb6f217c0ed..55c1fac99613 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -365,3 +365,10 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai) if (dai->driver->resume) dai->driver->resume(dai); } + +int snd_soc_dai_probe(struct snd_soc_dai *dai) +{ + if (dai->driver->probe) + return dai->driver->probe(dai); + return 0; +} -- GitLab From dcdab5820edd6123911dbd767ee1e389008b6a83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:35:05 +0900 Subject: [PATCH 0373/7155] ASoC: soc-dai: add snd_soc_dai_remove() Current ALSA SoC is directly using dai->driver->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_remvoe() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87imruhn1x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-core.c | 13 ++++++------- sound/soc/soc-dai.c | 7 +++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index da8d8b889089..2a11f177ce01 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -165,6 +165,7 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_probe(struct snd_soc_dai *dai); +int snd_soc_dai_remove(struct snd_soc_dai *dai); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3e73468225f9..727fd342b3fb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -992,13 +992,12 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) dai->driver->remove_order != order) return; - if (dai->driver->remove) { - err = dai->driver->remove(dai); - if (err < 0) - dev_err(dai->dev, - "ASoC: failed to remove %s: %d\n", - dai->name, err); - } + err = snd_soc_dai_remove(dai); + if (err < 0) + dev_err(dai->dev, + "ASoC: failed to remove %s: %d\n", + dai->name, err); + dai->probed = 0; } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 55c1fac99613..384765c747da 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -372,3 +372,10 @@ int snd_soc_dai_probe(struct snd_soc_dai *dai) return dai->driver->probe(dai); return 0; } + +int snd_soc_dai_remove(struct snd_soc_dai *dai) +{ + if (dai->driver->remove) + return dai->driver->remove(dai); + return 0; +} -- GitLab From b423c4202135f7794e0a9c55a884f5933d8e7156 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:35:29 +0900 Subject: [PATCH 0374/7155] ASoC: soc-dai: add snd_soc_dai_compress_new() Current ALSA SoC is directly using dai->driver->xxx, thus, it has deep nested bracket, and it makes code unreadable. This patch adds new snd_soc_dai_compress_new() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h87ehn1a.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-core.c | 15 ++++++++------- sound/soc/soc-dai.c | 8 ++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2a11f177ce01..0f8b09520020 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -166,6 +166,8 @@ void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_probe(struct snd_soc_dai *dai); int snd_soc_dai_remove(struct snd_soc_dai *dai); +int snd_soc_dai_compress_new(struct snd_soc_dai *dai, + struct snd_soc_pcm_runtime *rtd, int num); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 727fd342b3fb..458b090f026a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1545,15 +1545,16 @@ static int soc_probe_link_dais(struct snd_soc_card *card, num = rtd->dai_link->id; } - if (cpu_dai->driver->compress_new) { - /* create compress_device" */ - ret = cpu_dai->driver->compress_new(rtd, num); - if (ret < 0) { + /* create compress_device if possible */ + ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); + if (ret != -ENOTSUPP) { + if (ret < 0) dev_err(card->dev, "ASoC: can't create compress %s\n", dai_link->stream_name); - return ret; - } - } else if (!dai_link->params) { + return ret; + } + + if (!dai_link->params) { /* create the pcm */ ret = soc_new_pcm(rtd, num); if (ret < 0) { diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 384765c747da..e6f161b9f975 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -379,3 +379,11 @@ int snd_soc_dai_remove(struct snd_soc_dai *dai) return dai->driver->remove(dai); return 0; } + +int snd_soc_dai_compress_new(struct snd_soc_dai *dai, + struct snd_soc_pcm_runtime *rtd, int num) +{ + if (dai->driver->compress_new) + return dai->driver->compress_new(rtd, num); + return -ENOTSUPP; +} -- GitLab From 88fdffa2eef45fc9f6009ee590741c44a57c49c7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:36:27 +0900 Subject: [PATCH 0375/7155] ASoC: soc-core: use existing snd_soc_dai_digital_mute() ALSA SoC already has snd_soc_dai_digital_mute() for digital_mute, let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ef2ihmzo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 458b090f026a..7ecfe641ca46 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -487,10 +487,9 @@ int snd_soc_suspend(struct device *dev) continue; for_each_rtd_codec_dai(rtd, i, dai) { - struct snd_soc_dai_driver *drv = dai->driver; - - if (drv->ops->digital_mute && dai->playback_active) - drv->ops->digital_mute(dai, 1); + if (dai->playback_active) + snd_soc_dai_digital_mute(dai, 1, + SNDRV_PCM_STREAM_PLAYBACK); } } @@ -665,10 +664,9 @@ static void soc_resume_deferred(struct work_struct *work) continue; for_each_rtd_codec_dai(rtd, i, dai) { - struct snd_soc_dai_driver *drv = dai->driver; - - if (drv->ops->digital_mute && dai->playback_active) - drv->ops->digital_mute(dai, 0); + if (dai->playback_active) + snd_soc_dai_digital_mute(dai, 0, + SNDRV_PCM_STREAM_PLAYBACK); } } -- GitLab From 467fece8fbc6774a3a3bd0981e1a342fb5022706 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Jul 2019 10:36:16 +0900 Subject: [PATCH 0376/7155] ASoC: soc-dai: move snd_soc_dai_stream_valid() to soc-dai.c snd_soc_dai_stream_valid() is function to check stream validity. But, some code is using it, some code are checking stream->channels_min directly. Doing samethings by different method is confusable. This patch uses same funcntion for same purpose. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ftmyhmzz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-compress.c | 9 ++++----- sound/soc/soc-dai.c | 18 ++++++++++++++++++ sound/soc/soc-pcm.c | 39 ++++++++++----------------------------- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 0f8b09520020..dc48fe081a20 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -168,6 +168,7 @@ int snd_soc_dai_probe(struct snd_soc_dai *dai); int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); +bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ddef4ff677ce..289211069a1e 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -872,14 +872,13 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) } /* check client and interface hw capabilities */ - if (codec_dai->driver->playback.channels_min) + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) playback = 1; - if (codec_dai->driver->capture.channels_min) + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && + snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) capture = 1; - capture = capture && cpu_dai->driver->capture.channels_min; - playback = playback && cpu_dai->driver->playback.channels_min; - /* * Compress devices are unidirectional so only one of the directions * should be set, check for that (xor) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index e6f161b9f975..1c7f63871c1d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -387,3 +387,21 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, return dai->driver->compress_new(rtd, num); return -ENOTSUPP; } + +/* + * snd_soc_dai_stream_valid() - check if a DAI supports the given stream + * + * Returns true if the DAI supports the indicated stream type. + */ +bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) +{ + struct snd_soc_pcm_stream *stream; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + stream = &dai->driver->playback; + else + stream = &dai->driver->capture; + + /* If the codec specifies any channels at all, it supports the stream */ + return stream->channels_min; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f3137723301c..fabeac164a6c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -29,24 +29,6 @@ #define DPCM_MAX_BE_USERS 8 -/* - * snd_soc_dai_stream_valid() - check if a DAI supports the given stream - * - * Returns true if the DAI supports the indicated stream type. - */ -static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) -{ - struct snd_soc_pcm_stream *codec_stream; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - codec_stream = &dai->driver->playback; - else - codec_stream = &dai->driver->capture; - - /* If the codec specifies any channels at all, it supports the stream */ - return codec_stream->channels_min; -} - /** * snd_soc_runtime_activate() - Increment active count for PCM runtime components * @rtd: ASoC PCM runtime that is activated @@ -2688,8 +2670,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) new ? "new" : "old", fe->dai_link->name); /* skip if FE doesn't have playback capability */ - if (!fe->cpu_dai->driver->playback.channels_min || - !fe->codec_dai->driver->playback.channels_min) + if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK) || + !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_PLAYBACK)) goto capture; /* skip if FE isn't currently playing */ @@ -2719,8 +2701,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) capture: /* skip if FE doesn't have capture capability */ - if (!fe->cpu_dai->driver->capture.channels_min || - !fe->codec_dai->driver->capture.channels_min) + if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE) || + !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_CAPTURE)) return 0; /* skip if FE isn't currently capturing */ @@ -3030,14 +3012,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) capture = rtd->dai_link->dpcm_capture; } else { for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->playback.channels_min) + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) playback = 1; - if (codec_dai->driver->capture.channels_min) + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && + snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) capture = 1; } - - capture = capture && cpu_dai->driver->capture.channels_min; - playback = playback && cpu_dai->driver->playback.channels_min; } if (rtd->dai_link->playback_only) { @@ -3375,11 +3356,11 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - if (fe->cpu_dai->driver->playback.channels_min) + if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK, buf + offset, out_count - offset); - if (fe->cpu_dai->driver->capture.channels_min) + if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE, buf + offset, out_count - offset); -- GitLab From 955315b0dc8c8641311430f40fbe53990ba40e33 Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Tue, 23 Jul 2019 15:14:13 +0900 Subject: [PATCH 0377/7155] qlge: Move drivers/net/ethernet/qlogic/qlge/ to drivers/staging/qlge/ The hardware has been declared EOL by the vendor more than 5 years ago. What's more relevant to the Linux kernel is that the quality of this driver is not on par with many other mainline drivers. Cc: Manish Chopra Message-id: <20190617074858.32467-1-bpoirier@suse.com> Signed-off-by: Benjamin Poirier Signed-off-by: David S. Miller --- Documentation/PCI/pci-error-recovery.rst | 1 - MAINTAINERS | 2 +- drivers/net/ethernet/qlogic/Kconfig | 9 ---- drivers/net/ethernet/qlogic/Makefile | 1 - drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/qlge/Kconfig | 10 ++++ .../ethernet/qlogic => staging}/qlge/Makefile | 0 drivers/staging/qlge/TODO | 46 +++++++++++++++++++ .../ethernet/qlogic => staging}/qlge/qlge.h | 0 .../qlogic => staging}/qlge/qlge_dbg.c | 0 .../qlogic => staging}/qlge/qlge_ethtool.c | 0 .../qlogic => staging}/qlge/qlge_main.c | 0 .../qlogic => staging}/qlge/qlge_mpi.c | 0 14 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 drivers/staging/qlge/Kconfig rename drivers/{net/ethernet/qlogic => staging}/qlge/Makefile (100%) create mode 100644 drivers/staging/qlge/TODO rename drivers/{net/ethernet/qlogic => staging}/qlge/qlge.h (100%) rename drivers/{net/ethernet/qlogic => staging}/qlge/qlge_dbg.c (100%) rename drivers/{net/ethernet/qlogic => staging}/qlge/qlge_ethtool.c (100%) rename drivers/{net/ethernet/qlogic => staging}/qlge/qlge_main.c (100%) rename drivers/{net/ethernet/qlogic => staging}/qlge/qlge_mpi.c (100%) diff --git a/Documentation/PCI/pci-error-recovery.rst b/Documentation/PCI/pci-error-recovery.rst index 83db42092935..7e30f43a9659 100644 --- a/Documentation/PCI/pci-error-recovery.rst +++ b/Documentation/PCI/pci-error-recovery.rst @@ -421,4 +421,3 @@ That is, the recovery API only requires that: - drivers/net/ixgbe - drivers/net/cxgb3 - drivers/net/s2io.c - - drivers/net/qlge diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..9bca7781d67e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13217,7 +13217,7 @@ M: Manish Chopra M: GR-Linux-NIC-Dev@marvell.com L: netdev@vger.kernel.org S: Supported -F: drivers/net/ethernet/qlogic/qlge/ +F: drivers/staging/qlge/ QM1D1B0004 MEDIA DRIVER M: Akihiro Tsukada diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index a391cf6ee4b2..55a29ec76680 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -66,15 +66,6 @@ config QLCNIC_HWMON This data is available via the hwmon sysfs interface. -config QLGE - tristate "QLogic QLGE 10Gb Ethernet Driver Support" - depends on PCI - ---help--- - This driver supports QLogic ISP8XXX 10Gb Ethernet cards. - - To compile this driver as a module, choose M here: the module - will be called qlge. - config NETXEN_NIC tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" depends on PCI diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile index 6cd2e333a5fc..1ae4a0743bd5 100644 --- a/drivers/net/ethernet/qlogic/Makefile +++ b/drivers/net/ethernet/qlogic/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_QLA3XXX) += qla3xxx.o obj-$(CONFIG_QLCNIC) += qlcnic/ -obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_NETXEN_NIC) += netxen/ obj-$(CONFIG_QED) += qed/ obj-$(CONFIG_QEDE)+= qede/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7c96a01eef6c..0b8a614be11e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -120,4 +120,6 @@ source "drivers/staging/kpc2000/Kconfig" source "drivers/staging/isdn/Kconfig" +source "drivers/staging/qlge/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fcaac9693b83..741152511a10 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -50,3 +50,4 @@ obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ +obj-$(CONFIG_QLGE) += qlge/ diff --git a/drivers/staging/qlge/Kconfig b/drivers/staging/qlge/Kconfig new file mode 100644 index 000000000000..ae9ed2c5300b --- /dev/null +++ b/drivers/staging/qlge/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +config QLGE + tristate "QLogic QLGE 10Gb Ethernet Driver Support" + depends on PCI + help + This driver supports QLogic ISP8XXX 10Gb Ethernet cards. + + To compile this driver as a module, choose M here. The module will be + called qlge. diff --git a/drivers/net/ethernet/qlogic/qlge/Makefile b/drivers/staging/qlge/Makefile similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/Makefile rename to drivers/staging/qlge/Makefile diff --git a/drivers/staging/qlge/TODO b/drivers/staging/qlge/TODO new file mode 100644 index 000000000000..51c509084e80 --- /dev/null +++ b/drivers/staging/qlge/TODO @@ -0,0 +1,46 @@ +* reception stalls permanently (until admin intervention) if the rx buffer + queues become empty because of allocation failures (ex. under memory + pressure) +* commit 7c734359d350 ("qlge: Size RX buffers based on MTU.", v2.6.33-rc1) + introduced dead code in the receive routines, which should be rewritten + anyways by the admission of the author himself, see the comment above + ql_build_rx_skb(). That function is now used exclusively to handle packets + that underwent header splitting but it still contains code to handle non + split cases. +* truesize accounting is incorrect (ex: a 9000B frame has skb->truesize 10280 + while containing two frags of order-1 allocations, ie. >16K) +* while in that area, using two 8k buffers to store one 9k frame is a poor + choice of buffer size. +* in the "chain of large buffers" case, the driver uses an skb allocated with + head room but only puts data in the frags. +* rename "rx" queues to "completion" queues. Calling tx completion queues "rx + queues" is confusing. +* struct rx_ring is used for rx and tx completions, with some members relevant + to one case only +* there is an inordinate amount of disparate debugging code, most of which is + of questionable value. In particular, qlge_dbg.c has hundreds of lines of + code bitrotting away in ifdef land (doesn't compile since commit + 18c49b91777c ("qlge: do vlan cleanup", v3.1-rc1), 8 years ago). +* triggering an ethtool regdump will hexdump a 176k struct to dmesg depending + on some module parameters. +* the flow control implementation in firmware is buggy (sends a flood of pause + frames, resets the link, device and driver buffer queues become + desynchronized), disable it by default +* some structures are initialized redundantly (ex. memset 0 after + alloc_etherdev()) +* the driver has a habit of using runtime checks where compile time checks are + possible (ex. ql_free_rx_buffers(), ql_alloc_rx_buffers()) +* reorder struct members to avoid holes if it doesn't impact performance +* in terms of namespace, the driver uses either qlge_, ql_ (used by + other qlogic drivers, with clashes, ex: ql_sem_spinlock) or nothing (with + clashes, ex: struct ob_mac_iocb_req). Rename everything to use the "qlge_" + prefix. +* avoid legacy/deprecated apis (ex. replace pci_dma_*, replace pci_enable_msi, + use pci_iomap) +* some "while" loops could be rewritten with simple "for", ex. + ql_wait_reg_rdy(), ql_start_rx_ring()) +* remove duplicate and useless comments +* fix weird line wrapping (all over, ex. the ql_set_routing_reg() calls in + qlge_set_multicast_list()). +* fix weird indentation (all over, ex. the for loops in qlge_get_stats()) +* fix checkpatch issues diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/staging/qlge/qlge.h similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/qlge.h rename to drivers/staging/qlge/qlge.h diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/qlge_dbg.c rename to drivers/staging/qlge/qlge_dbg.c diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c rename to drivers/staging/qlge/qlge_ethtool.c diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/qlge_main.c rename to drivers/staging/qlge/qlge_main.c diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c similarity index 100% rename from drivers/net/ethernet/qlogic/qlge/qlge_mpi.c rename to drivers/staging/qlge/qlge_mpi.c -- GitLab From 69ab285b682328ef7622f0567f8afebb00b404f3 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 11:56:33 +0200 Subject: [PATCH 0378/7155] percpu: fix typo in pcpu_setup_first_chunk() comment s/perpcu/percpu/ Signed-off-by: Christophe JAILLET Signed-off-by: Dennis Zhou [Dennis: updated title] --- mm/percpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/percpu.c b/mm/percpu.c index 5a918a4b1da0..7e2aa0305c27 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -2220,7 +2220,7 @@ static void pcpu_dump_alloc_info(const char *lvl, * @base_addr: mapped address * * Initialize the first percpu chunk which contains the kernel static - * perpcu area. This function is to be called from arch percpu area + * percpu area. This function is to be called from arch percpu area * setup path. * * @ai contains all information necessary to initialize the first -- GitLab From 084323f62b0b976c9fd931d86c5d2553af5eb9f7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Jul 2019 11:45:44 -0700 Subject: [PATCH 0379/7155] ftgmac100: Fix build. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/ethernet/faraday/ftgmac100.c:777:13: error: 'skb_frag_t {aka struct bio_vec}' has no member named 'size' Fallout from the skb_frag_t conversion to bio_vec, simply use skb_frag_size(). Fixes: b8b576a16f79 ("net: Rename skb_frag_t size to bv_len") Reported-by: René van Dorst Signed-off-by: David S. Miller --- drivers/net/ethernet/faraday/ftgmac100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 030fed65393e..dc8d3e726e75 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -774,7 +774,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, for (i = 0; i < nfrags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - len = frag->size; + len = skb_frag_size(frag); /* Map it */ map = skb_frag_dma_map(priv->dev, frag, 0, len, -- GitLab From 7d9d60bdfa45181e439b50bb067e97168b99f89e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 20:14:16 +0200 Subject: [PATCH 0380/7155] leds: is31fl319x: simplify getting the adapter of a client We have a dedicated pointer for that, so use it. Much easier to read and less computation involved. Signed-off-by: Wolfram Sang Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-is31fl319x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c index 2d077b8edd0e..ca6634b8683c 100644 --- a/drivers/leds/leds-is31fl319x.c +++ b/drivers/leds/leds-is31fl319x.c @@ -333,12 +333,11 @@ static int is31fl319x_probe(struct i2c_client *client, { struct is31fl319x_chip *is31; struct device *dev = &client->dev; - struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); int err; int i = 0; u32 aggregated_led_microamp = IS31FL319X_CURRENT_MAX; - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -EIO; is31 = devm_kzalloc(&client->dev, sizeof(*is31), GFP_KERNEL); -- GitLab From c349c0a28326c98ca145b59e0f7ba69e4eef3b80 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 16:13:14 +0800 Subject: [PATCH 0381/7155] atm: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/atm/solos-pci.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 5c4c6eeb505c..c32f7dd9879a 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -516,9 +516,8 @@ struct geos_gpio_attr { static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct pci_dev *pdev = to_pci_dev(dev); struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); - struct solos_card *card = pci_get_drvdata(pdev); + struct solos_card *card = dev_get_drvdata(dev); uint32_t data32; if (count != 1 && (count != 2 || buf[1] != '\n')) @@ -542,9 +541,8 @@ static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct pci_dev *pdev = to_pci_dev(dev); struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); - struct solos_card *card = pci_get_drvdata(pdev); + struct solos_card *card = dev_get_drvdata(dev); uint32_t data32; data32 = ioread32(card->config_regs + GPIO_STATUS); @@ -556,9 +554,8 @@ static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr, static ssize_t hardware_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct pci_dev *pdev = to_pci_dev(dev); struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); - struct solos_card *card = pci_get_drvdata(pdev); + struct solos_card *card = dev_get_drvdata(dev); uint32_t data32; data32 = ioread32(card->config_regs + GPIO_STATUS); -- GitLab From 9f293c9af856bc6b404759eedb9bc6ad8d9cf631 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 21:18:44 +0800 Subject: [PATCH 0382/7155] net: 3com: 3c59x: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c59x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 7be91e896f2d..8785c2ff3825 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -847,8 +847,7 @@ static void poll_vortex(struct net_device *dev) static int vortex_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *ndev = pci_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); if (!ndev || !netif_running(ndev)) return 0; @@ -861,8 +860,7 @@ static int vortex_suspend(struct device *dev) static int vortex_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *ndev = pci_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); int err; if (!ndev || !netif_running(ndev)) -- GitLab From f54b0fc86ce69fd923153b19604afbea1455c1b4 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 21:18:56 +0800 Subject: [PATCH 0383/7155] net: atheros: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/main.c | 6 ++---- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 8 +++----- drivers/net/ethernet/atheros/atlx/atl1.c | 8 +++----- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index a3ec738da336..d4bbcdfd691a 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1877,8 +1877,7 @@ static void alx_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int alx_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct alx_priv *alx = pci_get_drvdata(pdev); + struct alx_priv *alx = dev_get_drvdata(dev); if (!netif_running(alx->dev)) return 0; @@ -1889,8 +1888,7 @@ static int alx_suspend(struct device *dev) static int alx_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct alx_priv *alx = pci_get_drvdata(pdev); + struct alx_priv *alx = dev_get_drvdata(dev); struct alx_hw *hw = &alx->hw; int err; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 179ad62a2bd2..2b239ecea05f 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2420,8 +2420,7 @@ static int atl1c_close(struct net_device *netdev) static int atl1c_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct atl1c_adapter *adapter = netdev_priv(netdev); struct atl1c_hw *hw = &adapter->hw; u32 wufc = adapter->wol; @@ -2435,7 +2434,7 @@ static int atl1c_suspend(struct device *dev) if (wufc) if (atl1c_phy_to_ps_link(hw) != 0) - dev_dbg(&pdev->dev, "phy power saving failed"); + dev_dbg(dev, "phy power saving failed"); atl1c_power_saving(hw, wufc); @@ -2445,8 +2444,7 @@ static int atl1c_suspend(struct device *dev) #ifdef CONFIG_PM_SLEEP static int atl1c_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct atl1c_adapter *adapter = netdev_priv(netdev); AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 5f420c17bf3e..b498fd6a47d0 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2753,8 +2753,7 @@ static int atl1_close(struct net_device *netdev) #ifdef CONFIG_PM_SLEEP static int atl1_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct atl1_adapter *adapter = netdev_priv(netdev); struct atl1_hw *hw = &adapter->hw; u32 ctrl = 0; @@ -2779,7 +2778,7 @@ static int atl1_suspend(struct device *dev) val = atl1_get_speed_and_duplex(hw, &speed, &duplex); if (val) { if (netif_msg_ifdown(adapter)) - dev_printk(KERN_DEBUG, &pdev->dev, + dev_printk(KERN_DEBUG, dev, "error getting speed/duplex\n"); goto disable_wol; } @@ -2836,8 +2835,7 @@ static int atl1_suspend(struct device *dev) static int atl1_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct atl1_adapter *adapter = netdev_priv(netdev); iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); -- GitLab From f521eaa9d2ef6d85bc6c318148f019e9f40fc344 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 21:19:29 +0800 Subject: [PATCH 0384/7155] net: broadcom: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2.c | 6 ++---- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 ++---- drivers/net/ethernet/broadcom/tg3.c | 6 ++---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index dfdd14eadd57..fbc196b480b6 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -8673,8 +8673,7 @@ bnx2_remove_one(struct pci_dev *pdev) static int bnx2_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct bnx2 *bp = netdev_priv(dev); if (netif_running(dev)) { @@ -8693,8 +8692,7 @@ bnx2_suspend(struct device *device) static int bnx2_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct bnx2 *bp = netdev_priv(dev); if (!netif_running(dev)) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 74dd28b82105..1fedefd499ac 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -10920,8 +10920,7 @@ static void bnxt_shutdown(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int bnxt_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct bnxt *bp = netdev_priv(dev); int rc = 0; @@ -10937,8 +10936,7 @@ static int bnxt_suspend(struct device *device) static int bnxt_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct bnxt *bp = netdev_priv(dev); int rc = 0; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 4c404d2213f9..77f3511b97de 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -18041,8 +18041,7 @@ static void tg3_remove_one(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int tg3_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct tg3 *tp = netdev_priv(dev); int err = 0; @@ -18098,8 +18097,7 @@ static int tg3_suspend(struct device *device) static int tg3_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct tg3 *tp = netdev_priv(dev); int err = 0; -- GitLab From ee2e80c194628a0ba5cd0a5c37b46fa136e11004 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 22:15:13 +0800 Subject: [PATCH 0385/7155] e1000e: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000e/netdev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a0c001d6d9d2..8a3f035c3a5f 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6296,7 +6296,7 @@ static void e1000e_flush_lpic(struct pci_dev *pdev) static int e1000e_pm_freeze(struct device *dev) { - struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); + struct net_device *netdev = dev_get_drvdata(dev); struct e1000_adapter *adapter = netdev_priv(netdev); netif_device_detach(netdev); @@ -6629,7 +6629,7 @@ static int __e1000_resume(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int e1000e_pm_thaw(struct device *dev) { - struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); + struct net_device *netdev = dev_get_drvdata(dev); struct e1000_adapter *adapter = netdev_priv(netdev); e1000e_set_interrupt_capability(adapter); @@ -6678,8 +6678,7 @@ static int e1000e_pm_resume(struct device *dev) static int e1000e_pm_runtime_idle(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct e1000_adapter *adapter = netdev_priv(netdev); u16 eee_lp; -- GitLab From 7f53be6f6b8d339bfce34514e23bb8eb7057648c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 22:15:33 +0800 Subject: [PATCH 0386/7155] fm10k: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index e49fb51d3613..7bfc8a5b6f55 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2352,7 +2352,7 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface) **/ static int __maybe_unused fm10k_resume(struct device *dev) { - struct fm10k_intfc *interface = pci_get_drvdata(to_pci_dev(dev)); + struct fm10k_intfc *interface = dev_get_drvdata(dev); struct net_device *netdev = interface->netdev; struct fm10k_hw *hw = &interface->hw; int err; @@ -2379,7 +2379,7 @@ static int __maybe_unused fm10k_resume(struct device *dev) **/ static int __maybe_unused fm10k_suspend(struct device *dev) { - struct fm10k_intfc *interface = pci_get_drvdata(to_pci_dev(dev)); + struct fm10k_intfc *interface = dev_get_drvdata(dev); struct net_device *netdev = interface->netdev; netif_device_detach(netdev); -- GitLab From 1c8aa7b1f15bff91a9abef3f083770793ea2f773 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 22:15:51 +0800 Subject: [PATCH 0387/7155] i40e: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9ebbe3da61bb..44da407e0bf9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -15605,8 +15605,7 @@ static void i40e_shutdown(struct pci_dev *pdev) **/ static int __maybe_unused i40e_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct i40e_pf *pf = pci_get_drvdata(pdev); + struct i40e_pf *pf = dev_get_drvdata(dev); struct i40e_hw *hw = &pf->hw; /* If we're already suspended, then there is nothing to do */ @@ -15656,8 +15655,7 @@ static int __maybe_unused i40e_suspend(struct device *dev) **/ static int __maybe_unused i40e_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct i40e_pf *pf = pci_get_drvdata(pdev); + struct i40e_pf *pf = dev_get_drvdata(dev); int err; /* If we're not suspended, then there is nothing to do */ @@ -15674,7 +15672,7 @@ static int __maybe_unused i40e_resume(struct device *dev) */ err = i40e_restore_interrupt_scheme(pf); if (err) { - dev_err(&pdev->dev, "Cannot restore interrupt scheme: %d\n", + dev_err(dev, "Cannot restore interrupt scheme: %d\n", err); } -- GitLab From 5daab287c67d8008a01e4a0db8bcb92b386b8adc Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 22:16:24 +0800 Subject: [PATCH 0388/7155] igb: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igb/igb_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 749645d7f9b7..b63e77528a91 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -8880,8 +8880,7 @@ static int __maybe_unused igb_resume(struct device *dev) static int __maybe_unused igb_runtime_idle(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct igb_adapter *adapter = netdev_priv(netdev); if (!igb_has_link(adapter)) -- GitLab From c9b6c56d52bea8adbf10ae0b9e4a7b88017c6f27 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 22:16:42 +0800 Subject: [PATCH 0389/7155] net: jme: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index ff6393fd64ac..9c3ab00643bd 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -3192,8 +3192,7 @@ jme_shutdown(struct pci_dev *pdev) static int jme_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct jme_adapter *jme = netdev_priv(netdev); if (!netif_running(netdev)) @@ -3235,8 +3234,7 @@ jme_suspend(struct device *dev) static int jme_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct jme_adapter *jme = netdev_priv(netdev); if (!netif_running(netdev)) -- GitLab From 658688ce6c936254c34ea1f31549ec62439574aa Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Jul 2019 12:02:26 +0000 Subject: [PATCH 0390/7155] net/mlx5e: xsk: dynamically allocate mlx5e_channel_param The structure is too large to put on the stack, resulting in a warning on 32-bit ARM: drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c:59:5: error: stack frame size of 1344 bytes in function 'mlx5e_open_xsk' [-Werror,-Wframe-larger-than=] Use kvzalloc() instead. Fixes: a038e9794541 ("net/mlx5e: Add XSK zero-copy support") Signed-off-by: Arnd Bergmann Signed-off-by: Maxim Mikityanskiy Signed-off-by: David S. Miller --- .../mellanox/mlx5/core/en/xsk/setup.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c index aaffa6f68dc0..f701e4f3c076 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c @@ -60,24 +60,28 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params, struct mlx5e_xsk_param *xsk, struct xdp_umem *umem, struct mlx5e_channel *c) { - struct mlx5e_channel_param cparam = {}; + struct mlx5e_channel_param *cparam; struct dim_cq_moder icocq_moder = {}; int err; if (!mlx5e_validate_xsk_param(params, xsk, priv->mdev)) return -EINVAL; - mlx5e_build_xsk_cparam(priv, params, xsk, &cparam); + cparam = kvzalloc(sizeof(*cparam), GFP_KERNEL); + if (!cparam) + return -ENOMEM; - err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam.rx_cq, &c->xskrq.cq); + mlx5e_build_xsk_cparam(priv, params, xsk, cparam); + + err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rx_cq, &c->xskrq.cq); if (unlikely(err)) - return err; + goto err_free_cparam; - err = mlx5e_open_rq(c, params, &cparam.rq, xsk, umem, &c->xskrq); + err = mlx5e_open_rq(c, params, &cparam->rq, xsk, umem, &c->xskrq); if (unlikely(err)) goto err_close_rx_cq; - err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam.tx_cq, &c->xsksq.cq); + err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->tx_cq, &c->xsksq.cq); if (unlikely(err)) goto err_close_rq; @@ -87,21 +91,23 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params, * is disabled and then reenabled, but the SQ continues receiving CQEs * from the old UMEM. */ - err = mlx5e_open_xdpsq(c, params, &cparam.xdp_sq, umem, &c->xsksq, true); + err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, umem, &c->xsksq, true); if (unlikely(err)) goto err_close_tx_cq; - err = mlx5e_open_cq(c, icocq_moder, &cparam.icosq_cq, &c->xskicosq.cq); + err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->xskicosq.cq); if (unlikely(err)) goto err_close_sq; /* Create a dedicated SQ for posting NOPs whenever we need an IRQ to be * triggered and NAPI to be called on the correct CPU. */ - err = mlx5e_open_icosq(c, params, &cparam.icosq, &c->xskicosq); + err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->xskicosq); if (unlikely(err)) goto err_close_icocq; + kvfree(cparam); + spin_lock_init(&c->xskicosq_lock); set_bit(MLX5E_CHANNEL_STATE_XSK, c->state); @@ -123,6 +129,9 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params, err_close_rx_cq: mlx5e_close_cq(&c->xskrq.cq); +err_free_cparam: + kvfree(cparam); + return err; } -- GitLab From 6749d59016981bca6d7000e40bdb08eed78dfa6f Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 23 Jul 2019 15:33:59 +0100 Subject: [PATCH 0391/7155] net: sched: include mpls actions in hardware intermediate representation A recent addition to TC actions is the ability to manipulate the MPLS headers on packets. In preparation to offload such actions to hardware, update the IR code to accept and prepare the new actions. Note that no driver currently impliments the MPLS dec_ttl action so this is not included. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/flow_offload.h | 19 +++++++++ include/net/tc_act/tc_mpls.h | 75 ++++++++++++++++++++++++++++++++++++ net/sched/cls_api.c | 25 ++++++++++++ 3 files changed, 119 insertions(+) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index b16d21636d69..00b9aab5fdc1 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -131,6 +131,9 @@ enum flow_action_id { FLOW_ACTION_SAMPLE, FLOW_ACTION_POLICE, FLOW_ACTION_CT, + FLOW_ACTION_MPLS_PUSH, + FLOW_ACTION_MPLS_POP, + FLOW_ACTION_MPLS_MANGLE, }; /* This is mirroring enum pedit_header_type definition for easy mapping between @@ -184,6 +187,22 @@ struct flow_action_entry { int action; u16 zone; } ct; + struct { /* FLOW_ACTION_MPLS_PUSH */ + u32 label; + __be16 proto; + u8 tc; + u8 bos; + u8 ttl; + } mpls_push; + struct { /* FLOW_ACTION_MPLS_POP */ + __be16 proto; + } mpls_pop; + struct { /* FLOW_ACTION_MPLS_MANGLE */ + u32 label; + u8 tc; + u8 bos; + u8 ttl; + } mpls_mangle; }; }; diff --git a/include/net/tc_act/tc_mpls.h b/include/net/tc_act/tc_mpls.h index 4bc3d9250ef0..721de4f5733a 100644 --- a/include/net/tc_act/tc_mpls.h +++ b/include/net/tc_act/tc_mpls.h @@ -27,4 +27,79 @@ struct tcf_mpls { }; #define to_mpls(a) ((struct tcf_mpls *)a) +static inline bool is_tcf_mpls(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT + if (a->ops && a->ops->id == TCA_ID_MPLS) + return true; +#endif + return false; +} + +static inline u32 tcf_mpls_action(const struct tc_action *a) +{ + u32 tcfm_action; + + rcu_read_lock(); + tcfm_action = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_action; + rcu_read_unlock(); + + return tcfm_action; +} + +static inline __be16 tcf_mpls_proto(const struct tc_action *a) +{ + __be16 tcfm_proto; + + rcu_read_lock(); + tcfm_proto = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_proto; + rcu_read_unlock(); + + return tcfm_proto; +} + +static inline u32 tcf_mpls_label(const struct tc_action *a) +{ + u32 tcfm_label; + + rcu_read_lock(); + tcfm_label = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_label; + rcu_read_unlock(); + + return tcfm_label; +} + +static inline u8 tcf_mpls_tc(const struct tc_action *a) +{ + u8 tcfm_tc; + + rcu_read_lock(); + tcfm_tc = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_tc; + rcu_read_unlock(); + + return tcfm_tc; +} + +static inline u8 tcf_mpls_bos(const struct tc_action *a) +{ + u8 tcfm_bos; + + rcu_read_lock(); + tcfm_bos = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_bos; + rcu_read_unlock(); + + return tcfm_bos; +} + +static inline u8 tcf_mpls_ttl(const struct tc_action *a) +{ + u8 tcfm_ttl; + + rcu_read_lock(); + tcfm_ttl = rcu_dereference(to_mpls(a)->mpls_p)->tcfm_ttl; + rcu_read_unlock(); + + return tcfm_ttl; +} + #endif /* __NET_TC_MPLS_H */ diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index efd3cfb80a2a..3565d9aa09aa 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -36,6 +36,7 @@ #include #include #include +#include extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1]; @@ -3269,6 +3270,30 @@ int tc_setup_flow_action(struct flow_action *flow_action, entry->id = FLOW_ACTION_CT; entry->ct.action = tcf_ct_action(act); entry->ct.zone = tcf_ct_zone(act); + } else if (is_tcf_mpls(act)) { + switch (tcf_mpls_action(act)) { + case TCA_MPLS_ACT_PUSH: + entry->id = FLOW_ACTION_MPLS_PUSH; + entry->mpls_push.proto = tcf_mpls_proto(act); + entry->mpls_push.label = tcf_mpls_label(act); + entry->mpls_push.tc = tcf_mpls_tc(act); + entry->mpls_push.bos = tcf_mpls_bos(act); + entry->mpls_push.ttl = tcf_mpls_ttl(act); + break; + case TCA_MPLS_ACT_POP: + entry->id = FLOW_ACTION_MPLS_POP; + entry->mpls_pop.proto = tcf_mpls_proto(act); + break; + case TCA_MPLS_ACT_MODIFY: + entry->id = FLOW_ACTION_MPLS_MANGLE; + entry->mpls_mangle.label = tcf_mpls_label(act); + entry->mpls_mangle.tc = tcf_mpls_tc(act); + entry->mpls_mangle.bos = tcf_mpls_bos(act); + entry->mpls_mangle.ttl = tcf_mpls_ttl(act); + break; + default: + goto err_out; + } } else { goto err_out; } -- GitLab From a6eb1817fb9860cbd630ceb05dae0491993bfd85 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 23 Jul 2019 15:34:00 +0100 Subject: [PATCH 0392/7155] nfp: flower: offload MPLS push action Recent additions to the kernel include a TC action module to manipulate MPLS headers on packets. Such actions are available to offload via the flow_offload intermediate representation API. Modify the NFP driver to allow the offload of MPLS push actions to firmware. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/flower/action.c | 50 +++++++++++++++++++ .../net/ethernet/netronome/nfp/flower/cmsg.h | 7 +++ 2 files changed, 57 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 5a54fe848de4..9e18bec7b346 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -2,10 +2,12 @@ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ #include +#include #include #include #include #include +#include #include #include #include @@ -25,6 +27,38 @@ NFP_FL_TUNNEL_KEY | \ NFP_FL_TUNNEL_GENEVE_OPT) +static int +nfp_fl_push_mpls(struct nfp_fl_push_mpls *push_mpls, + const struct flow_action_entry *act, + struct netlink_ext_ack *extack) +{ + size_t act_size = sizeof(struct nfp_fl_push_mpls); + u32 mpls_lse = 0; + + push_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_MPLS; + push_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ; + + /* BOS is optional in the TC action but required for offload. */ + if (act->mpls_push.bos != ACT_MPLS_BOS_NOT_SET) { + mpls_lse |= act->mpls_push.bos << MPLS_LS_S_SHIFT; + } else { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: BOS field must explicitly be set for MPLS push"); + return -EOPNOTSUPP; + } + + /* Leave MPLS TC as a default value of 0 if not explicitly set. */ + if (act->mpls_push.tc != ACT_MPLS_TC_NOT_SET) + mpls_lse |= act->mpls_push.tc << MPLS_LS_TC_SHIFT; + + /* Proto, label and TTL are enforced and verified for MPLS push. */ + mpls_lse |= act->mpls_push.label << MPLS_LS_LABEL_SHIFT; + mpls_lse |= act->mpls_push.ttl << MPLS_LS_TTL_SHIFT; + push_mpls->ethtype = act->mpls_push.proto; + push_mpls->lse = cpu_to_be32(mpls_lse); + + return 0; +} + static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan) { size_t act_size = sizeof(struct nfp_fl_pop_vlan); @@ -869,6 +903,7 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, struct nfp_fl_set_ipv4_tun *set_tun; struct nfp_fl_pre_tunnel *pre_tun; struct nfp_fl_push_vlan *psh_v; + struct nfp_fl_push_mpls *psh_m; struct nfp_fl_pop_vlan *pop_v; int err; @@ -975,6 +1010,21 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, */ *csum_updated &= ~act->csum_flags; break; + case FLOW_ACTION_MPLS_PUSH: + if (*a_len + + sizeof(struct nfp_fl_push_mpls) > NFP_FL_MAX_A_SIZ) { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at push MPLS"); + return -EOPNOTSUPP; + } + + psh_m = (struct nfp_fl_push_mpls *)&nfp_fl->action_data[*a_len]; + nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); + + err = nfp_fl_push_mpls(psh_m, act, extack); + if (err) + return err; + *a_len += sizeof(struct nfp_fl_push_mpls); + break; default: /* Currently we do not handle any other actions. */ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list"); diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 0f1706ae5bfc..91af0fa99536 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -68,6 +68,7 @@ #define NFP_FL_ACTION_OPCODE_OUTPUT 0 #define NFP_FL_ACTION_OPCODE_PUSH_VLAN 1 #define NFP_FL_ACTION_OPCODE_POP_VLAN 2 +#define NFP_FL_ACTION_OPCODE_PUSH_MPLS 3 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6 #define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7 #define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9 @@ -232,6 +233,12 @@ struct nfp_fl_push_geneve { u8 opt_data[]; }; +struct nfp_fl_push_mpls { + struct nfp_fl_act_head head; + __be16 ethtype; + __be32 lse; +}; + /* Metadata with L2 (1W/4B) * ---------------------------------------------------------------- * 3 2 1 -- GitLab From 35b7c70cc3b82c159c181f297a54d4bea6f4fd47 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 23 Jul 2019 15:34:01 +0100 Subject: [PATCH 0393/7155] nfp: flower: offload MPLS pop action Recent additions to the kernel include a TC action module to manipulate MPLS headers on packets. Such actions are available to offload via the flow_offload intermediate representation API. Modify the NFP driver to allow the offload of MPLS pop actions to firmware. The act_mpls TC module enforces that the next protocol is supplied along with the pop action. Passing this to firmware allows it to properly rebuild the underlying packet after the pop. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/flower/action.c | 25 +++++++++++++++++++ .../net/ethernet/netronome/nfp/flower/cmsg.h | 6 +++++ 2 files changed, 31 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 9e18bec7b346..7f288ae4052b 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -59,6 +59,17 @@ nfp_fl_push_mpls(struct nfp_fl_push_mpls *push_mpls, return 0; } +static void +nfp_fl_pop_mpls(struct nfp_fl_pop_mpls *pop_mpls, + const struct flow_action_entry *act) +{ + size_t act_size = sizeof(struct nfp_fl_pop_mpls); + + pop_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_POP_MPLS; + pop_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ; + pop_mpls->ethtype = act->mpls_pop.proto; +} + static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan) { size_t act_size = sizeof(struct nfp_fl_pop_vlan); @@ -905,6 +916,7 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, struct nfp_fl_push_vlan *psh_v; struct nfp_fl_push_mpls *psh_m; struct nfp_fl_pop_vlan *pop_v; + struct nfp_fl_pop_mpls *pop_m; int err; switch (act->id) { @@ -1025,6 +1037,19 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, return err; *a_len += sizeof(struct nfp_fl_push_mpls); break; + case FLOW_ACTION_MPLS_POP: + if (*a_len + + sizeof(struct nfp_fl_pop_mpls) > NFP_FL_MAX_A_SIZ) { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at pop MPLS"); + return -EOPNOTSUPP; + } + + pop_m = (struct nfp_fl_pop_mpls *)&nfp_fl->action_data[*a_len]; + nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); + + nfp_fl_pop_mpls(pop_m, act); + *a_len += sizeof(struct nfp_fl_pop_mpls); + break; default: /* Currently we do not handle any other actions. */ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list"); diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 91af0fa99536..3198ad4af63b 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -69,6 +69,7 @@ #define NFP_FL_ACTION_OPCODE_PUSH_VLAN 1 #define NFP_FL_ACTION_OPCODE_POP_VLAN 2 #define NFP_FL_ACTION_OPCODE_PUSH_MPLS 3 +#define NFP_FL_ACTION_OPCODE_POP_MPLS 4 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6 #define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7 #define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9 @@ -239,6 +240,11 @@ struct nfp_fl_push_mpls { __be32 lse; }; +struct nfp_fl_pop_mpls { + struct nfp_fl_act_head head; + __be16 ethtype; +}; + /* Metadata with L2 (1W/4B) * ---------------------------------------------------------------- * 3 2 1 -- GitLab From e03e47a3dcecfa56420328b339f143a17499b414 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 23 Jul 2019 15:34:02 +0100 Subject: [PATCH 0394/7155] nfp: flower: offload MPLS set action Recent additions to the kernel include a TC action module to manipulate MPLS headers on packets. Such actions are available to offload via the flow_offload intermediate representation API. Modify the NFP driver to allow the offload of MPLS set actions to firmware. Set actions update the outermost MPLS header. The offload includes a mask to specify which fields should be set. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/flower/action.c | 45 +++++++++++++++++++ .../net/ethernet/netronome/nfp/flower/cmsg.h | 8 ++++ 2 files changed, 53 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 7f288ae4052b..ff2f419ae352 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -70,6 +70,37 @@ nfp_fl_pop_mpls(struct nfp_fl_pop_mpls *pop_mpls, pop_mpls->ethtype = act->mpls_pop.proto; } +static void +nfp_fl_set_mpls(struct nfp_fl_set_mpls *set_mpls, + const struct flow_action_entry *act) +{ + size_t act_size = sizeof(struct nfp_fl_set_mpls); + u32 mpls_lse = 0, mpls_mask = 0; + + set_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_SET_MPLS; + set_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ; + + if (act->mpls_mangle.label != ACT_MPLS_LABEL_NOT_SET) { + mpls_lse |= act->mpls_mangle.label << MPLS_LS_LABEL_SHIFT; + mpls_mask |= MPLS_LS_LABEL_MASK; + } + if (act->mpls_mangle.tc != ACT_MPLS_TC_NOT_SET) { + mpls_lse |= act->mpls_mangle.tc << MPLS_LS_TC_SHIFT; + mpls_mask |= MPLS_LS_TC_MASK; + } + if (act->mpls_mangle.bos != ACT_MPLS_BOS_NOT_SET) { + mpls_lse |= act->mpls_mangle.bos << MPLS_LS_S_SHIFT; + mpls_mask |= MPLS_LS_S_MASK; + } + if (act->mpls_mangle.ttl) { + mpls_lse |= act->mpls_mangle.ttl << MPLS_LS_TTL_SHIFT; + mpls_mask |= MPLS_LS_TTL_MASK; + } + + set_mpls->lse = cpu_to_be32(mpls_lse); + set_mpls->lse_mask = cpu_to_be32(mpls_mask); +} + static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan) { size_t act_size = sizeof(struct nfp_fl_pop_vlan); @@ -917,6 +948,7 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, struct nfp_fl_push_mpls *psh_m; struct nfp_fl_pop_vlan *pop_v; struct nfp_fl_pop_mpls *pop_m; + struct nfp_fl_set_mpls *set_m; int err; switch (act->id) { @@ -1050,6 +1082,19 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, nfp_fl_pop_mpls(pop_m, act); *a_len += sizeof(struct nfp_fl_pop_mpls); break; + case FLOW_ACTION_MPLS_MANGLE: + if (*a_len + + sizeof(struct nfp_fl_set_mpls) > NFP_FL_MAX_A_SIZ) { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at set MPLS"); + return -EOPNOTSUPP; + } + + set_m = (struct nfp_fl_set_mpls *)&nfp_fl->action_data[*a_len]; + nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); + + nfp_fl_set_mpls(set_m, act); + *a_len += sizeof(struct nfp_fl_set_mpls); + break; default: /* Currently we do not handle any other actions. */ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list"); diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 3198ad4af63b..332439400d85 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -72,6 +72,7 @@ #define NFP_FL_ACTION_OPCODE_POP_MPLS 4 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL 6 #define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7 +#define NFP_FL_ACTION_OPCODE_SET_MPLS 8 #define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS 10 #define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC 11 @@ -245,6 +246,13 @@ struct nfp_fl_pop_mpls { __be16 ethtype; }; +struct nfp_fl_set_mpls { + struct nfp_fl_act_head head; + __be16 reserved; + __be32 lse_mask; + __be32 lse; +}; + /* Metadata with L2 (1W/4B) * ---------------------------------------------------------------- * 3 2 1 -- GitLab From 4c6f5d4038af2c7332630bdd75cfdc0309e97242 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Wed, 12 Jun 2019 20:24:58 +0200 Subject: [PATCH 0395/7155] ARM: defconfig: enable cpufreq driver for RPi This enables on both multi_v7_defconfig and bcm2835_defconfig the new firmware based clock and cpufreq drivers for the Raspberry Pi platform. In the case of bcm2835_defconfig, as the cpufreq subsystem was disabled, the conservative governor was selected as default since it better handles the high frequency transition latency. Signed-off-by: Nicolas Saenz Julienne Acked-by: Stefan Wahren Signed-off-by: Stefan Wahren --- arch/arm/configs/bcm2835_defconfig | 9 +++++++++ arch/arm/configs/multi_v7_defconfig | 2 ++ 2 files changed, 11 insertions(+) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index dcf7610cfe55..519ff58e67b3 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -37,6 +37,14 @@ CONFIG_CMA=y CONFIG_SECCOMP=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_RASPBERRYPI_CPUFREQ=y CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SUSPEND is not set @@ -132,6 +140,7 @@ CONFIG_DMA_BCM2835=y CONFIG_STAGING=y CONFIG_SND_BCM2835=m CONFIG_VIDEO_BCM2835=m +CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y # CONFIG_IOMMU_SUPPORT is not set diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6a40bc2ef271..b0a05683f17a 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -102,6 +102,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPUFREQ_DT=y CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_ARM_RASPBERRYPI_CPUFREQ=y CONFIG_QORIQ_CPUFREQ=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y @@ -902,6 +903,7 @@ CONFIG_STAGING_BOARD=y CONFIG_COMMON_CLK_MAX77686=y CONFIG_COMMON_CLK_RK808=m CONFIG_COMMON_CLK_S2MPS11=m +CONFIG_CLK_RASPBERRYPI=y CONFIG_COMMON_CLK_QCOM=y CONFIG_QCOM_CLK_RPM=y CONFIG_APQ_MMCC_8084=y -- GitLab From ce103204cbe61f8d5d995f7a09a6b18e6b6ac3c4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 19:39:43 +0300 Subject: [PATCH 0396/7155] hv_sock: Use consistent types for UUIDs The rest of Hyper-V code is using new types for UUID handling. Convert hv_sock as well. Signed-off-by: Andy Shevchenko Reviewed-by: Dexuan Cui Signed-off-by: David S. Miller --- net/vmw_vsock/hyperv_transport.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index f2084e3f7aa4..2a1719c0f8d2 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c @@ -77,11 +77,11 @@ struct hvs_send_buf { VMBUS_PKT_TRAILER_SIZE) union hvs_service_id { - uuid_le srv_id; + guid_t srv_id; struct { unsigned int svm_port; - unsigned char b[sizeof(uuid_le) - sizeof(unsigned int)]; + unsigned char b[sizeof(guid_t) - sizeof(unsigned int)]; }; }; @@ -89,8 +89,8 @@ union hvs_service_id { struct hvsock { struct vsock_sock *vsk; - uuid_le vm_srv_id; - uuid_le host_srv_id; + guid_t vm_srv_id; + guid_t host_srv_id; struct vmbus_channel *chan; struct vmpacket_descriptor *recv_desc; @@ -159,21 +159,21 @@ struct hvsock { #define MIN_HOST_EPHEMERAL_PORT (MAX_HOST_LISTEN_PORT + 1) /* 00000000-facb-11e6-bd58-64006a7986d3 */ -static const uuid_le srv_id_template = - UUID_LE(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58, - 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3); +static const guid_t srv_id_template = + GUID_INIT(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58, + 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3); -static bool is_valid_srv_id(const uuid_le *id) +static bool is_valid_srv_id(const guid_t *id) { - return !memcmp(&id->b[4], &srv_id_template.b[4], sizeof(uuid_le) - 4); + return !memcmp(&id->b[4], &srv_id_template.b[4], sizeof(guid_t) - 4); } -static unsigned int get_port_by_srv_id(const uuid_le *svr_id) +static unsigned int get_port_by_srv_id(const guid_t *svr_id) { return *((unsigned int *)svr_id); } -static void hvs_addr_init(struct sockaddr_vm *addr, const uuid_le *svr_id) +static void hvs_addr_init(struct sockaddr_vm *addr, const guid_t *svr_id) { unsigned int port = get_port_by_srv_id(svr_id); @@ -316,7 +316,7 @@ static void hvs_close_connection(struct vmbus_channel *chan) static void hvs_open_connection(struct vmbus_channel *chan) { - uuid_le *if_instance, *if_type; + guid_t *if_instance, *if_type; unsigned char conn_from_host; struct sockaddr_vm addr; -- GitLab From 3e3bb69589e482e0783f28d4cd1d8e56fda0bcbb Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Tue, 23 Jul 2019 15:01:59 -0400 Subject: [PATCH 0397/7155] tc-testing: added tdc tests for [b|p]fifo qdisc Signed-off-by: Roman Mashak Signed-off-by: David S. Miller --- .../tc-testing/tc-tests/qdiscs/fifo.json | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 tools/testing/selftests/tc-testing/tc-tests/qdiscs/fifo.json diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fifo.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fifo.json new file mode 100644 index 000000000000..9de61fa10878 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/fifo.json @@ -0,0 +1,304 @@ +[ + { + "id": "a519", + "name": "Add bfifo qdisc with system default parameters on egress", + "__comment": "When omitted, queue size in bfifo is calculated as: txqueuelen * (MTU + LinkLayerHdrSize), where LinkLayerHdrSize=14 for Ethernet", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root bfifo", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root.*limit [0-9]+b", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root bfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "585c", + "name": "Add pfifo qdisc with system default parameters on egress", + "__comment": "When omitted, queue size in pfifo is defaulted to the interface's txqueuelen value.", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root pfifo", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc pfifo 1: root.*limit [0-9]+p", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root pfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "a86e", + "name": "Add bfifo qdisc with system default parameters on egress with handle of maximum value", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 root handle ffff: bfifo", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo ffff: root.*limit [0-9]+b", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle ffff: root bfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "9ac8", + "name": "Add bfifo qdisc on egress with queue size of 3000 bytes", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root bfifo limit 3000b", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root.*limit 3000b", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root bfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "f4e6", + "name": "Add pfifo qdisc on egress with queue size of 3000 packets", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 txqueuelen 3000 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root pfifo limit 3000", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc pfifo 1: root.*limit 3000p", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root pfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "b1b1", + "name": "Add bfifo qdisc with system default parameters on egress with invalid handle exceeding maximum value", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 root handle 10000: bfifo", + "expExitCode": "255", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 10000: root.*limit [0-9]+b", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "8d5e", + "name": "Add bfifo qdisc on egress with unsupported argument", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root bfifo foorbar", + "expExitCode": "1", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "7787", + "name": "Add pfifo qdisc on egress with unsupported argument", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root pfifo foorbar", + "expExitCode": "1", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc pfifo 1: root", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "c4b6", + "name": "Replace bfifo qdisc on egress with new queue size", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link del dev $DEV1 type dummy || /bin/true", + "$IP link add dev $DEV1 txqueuelen 1000 type dummy", + "$TC qdisc add dev $DEV1 handle 1: root bfifo" + ], + "cmdUnderTest": "$TC qdisc replace dev $DEV1 handle 1: root bfifo limit 3000b", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root.*limit 3000b", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root bfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "3df6", + "name": "Replace pfifo qdisc on egress with new queue size", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link del dev $DEV1 type dummy || /bin/true", + "$IP link add dev $DEV1 txqueuelen 1000 type dummy", + "$TC qdisc add dev $DEV1 handle 1: root pfifo" + ], + "cmdUnderTest": "$TC qdisc replace dev $DEV1 handle 1: root pfifo limit 30", + "expExitCode": "0", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc pfifo 1: root.*limit 30p", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root pfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "7a67", + "name": "Add bfifo qdisc on egress with queue size in invalid format", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root bfifo limit foo-bar", + "expExitCode": "1", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root.*limit foo-bar", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "1298", + "name": "Add duplicate bfifo qdisc on egress", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 handle 1: root bfifo" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 handle 1: root bfifo", + "expExitCode": "2", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 handle 1: root bfifo", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "45a0", + "name": "Delete nonexistent bfifo qdisc", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc del dev $DEV1 root handle 1: bfifo", + "expExitCode": "2", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "972b", + "name": "Add prio qdisc on egress with invalid format for handles", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true" + ], + "cmdUnderTest": "$TC qdisc add dev $DEV1 root handle 123^ bfifo limit 100b", + "expExitCode": "255", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 123 root", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "4d39", + "name": "Delete bfifo qdisc twice", + "category": [ + "qdisc", + "fifo" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: bfifo", + "$TC qdisc del dev $DEV1 root handle 1: bfifo" + ], + "cmdUnderTest": "$TC qdisc del dev $DEV1 handle 1: root bfifo", + "expExitCode": "2", + "verifyCmd": "$TC qdisc show dev $DEV1", + "matchPattern": "qdisc bfifo 1: root", + "matchCount": "0", + "teardown": [ + "$IP link del dev $DEV1 type dummy" + ] + } +] -- GitLab From e2dd73ac4440f7143e990e76bad9a46dc63a5951 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Wed, 12 Jun 2019 20:24:59 +0200 Subject: [PATCH 0398/7155] arm64: defconfig: enable cpufreq support for RPi3 This enables both the new firmware clock driver and cpufreq driver available for the RPi3 family of boards. Signed-off-by: Nicolas Saenz Julienne Acked-by: Stefan Wahren Signed-off-by: Stefan Wahren --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0e58ef02880c..e80b40327912 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -84,6 +84,7 @@ CONFIG_ACPI_CPPC_CPUFREQ=m CONFIG_ARM_ARMADA_37XX_CPUFREQ=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_IMX_CPUFREQ_DT=m +CONFIG_ARM_RASPBERRYPI_CPUFREQ=m CONFIG_ARM_TEGRA186_CPUFREQ=y CONFIG_ARM_SCPI_PROTOCOL=y CONFIG_RASPBERRYPI_FIRMWARE=y @@ -676,6 +677,7 @@ CONFIG_COMMON_CLK_CS2000_CP=y CONFIG_COMMON_CLK_S2MPS11=y CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_PWM=y +CONFIG_CLK_RASPBERRYPI=m CONFIG_CLK_IMX8MM=y CONFIG_CLK_IMX8MQ=y CONFIG_CLK_IMX8QXP=y -- GitLab From 85db0023376f529c477c6110043e069ccee16d9c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 2 Jul 2019 19:26:59 +0200 Subject: [PATCH 0399/7155] cgroup: Replace a seq_printf() call by seq_puts() in cgroup_print_ss_mask() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A string which did not contain a data format specification should be put into a sequence. Thus use the corresponding function “seq_puts”. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 753afbca549f..3c3d92d993e8 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -2894,7 +2894,7 @@ static void cgroup_print_ss_mask(struct seq_file *seq, u16 ss_mask) do_each_subsys_mask(ss, ssid, ss_mask) { if (printed) seq_putc(seq, ' '); - seq_printf(seq, "%s", ss->name); + seq_puts(seq, ss->name); printed = true; } while_each_subsys_mask(); if (printed) -- GitLab From a581563f1bef035e4c8d634a1df26dae9140b115 Mon Sep 17 00:00:00 2001 From: Peng Wang Date: Wed, 3 Jul 2019 10:07:49 +0800 Subject: [PATCH 0400/7155] cgroup: minor tweak for logic to get cgroup css We could only handle the case that css exists and css_try_get_online() fails. Signed-off-by: Peng Wang Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 3c3d92d993e8..21ddf3053235 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -488,7 +488,7 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp, rcu_read_lock(); css = cgroup_css(cgrp, ss); - if (!css || !css_tryget_online(css)) + if (css && !css_tryget_online(css)) css = NULL; rcu_read_unlock(); -- GitLab From f2a3e4e95f408314938d37fa3146a9f7b304ce74 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:11:33 -0700 Subject: [PATCH 0401/7155] libbpf: provide more helpful message on uninitialized global var When BPF program defines uninitialized global variable, it's put into a special COMMON section. Libbpf will reject such programs, but will provide very unhelpful message with garbage-looking section index. This patch detects special section cases and gives more explicit error message. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 794dd5064ae8..8741c39adb1c 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -1760,15 +1760,22 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, (long long) sym.st_value, sym.st_name, name); shdr_idx = sym.st_shndx; + insn_idx = rel.r_offset / sizeof(struct bpf_insn); + pr_debug("relocation: insn_idx=%u, shdr_idx=%u\n", + insn_idx, shdr_idx); + + if (shdr_idx >= SHN_LORESERVE) { + pr_warning("relocation: not yet supported relo for non-static global \'%s\' variable in special section (0x%x) found in insns[%d].code 0x%x\n", + name, shdr_idx, insn_idx, + insns[insn_idx].code); + return -LIBBPF_ERRNO__RELOC; + } if (!bpf_object__relo_in_known_section(obj, shdr_idx)) { pr_warning("Program '%s' contains unrecognized relo data pointing to section %u\n", prog->section_name, shdr_idx); return -LIBBPF_ERRNO__RELOC; } - insn_idx = rel.r_offset / sizeof(struct bpf_insn); - pr_debug("relocation: insn_idx=%u\n", insn_idx); - if (insns[insn_idx].code == (BPF_JMP | BPF_CALL)) { if (insns[insn_idx].src_reg != BPF_PSEUDO_CALL) { pr_warning("incorrect bpf_call opcode\n"); -- GitLab From 58b80815362ef18f528e17711f0abec842f56d59 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:34:41 -0700 Subject: [PATCH 0402/7155] selftests/bpf: convert test_get_stack_raw_tp to perf_buffer API Convert test_get_stack_raw_tp test to new perf_buffer API. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../bpf/prog_tests/get_stack_raw_tp.c | 78 ++++++++++--------- .../bpf/progs/test_get_stack_rawtp.c | 2 +- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c index c2a0a9d5591b..9d73a8f932ac 100644 --- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c +++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c @@ -1,8 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include #include #define MAX_CNT_RAWTP 10ull #define MAX_STACK_RAWTP 100 + +static int duration = 0; + struct get_stack_trace_t { int pid; int kern_stack_size; @@ -13,7 +20,7 @@ struct get_stack_trace_t { struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP]; }; -static int get_stack_print_output(void *data, int size) +static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size) { bool good_kern_stack = false, good_user_stack = false; const char *nonjit_func = "___bpf_prog_run"; @@ -65,75 +72,76 @@ static int get_stack_print_output(void *data, int size) if (e->user_stack_size > 0 && e->user_stack_buildid_size > 0) good_user_stack = true; } - if (!good_kern_stack || !good_user_stack) - return LIBBPF_PERF_EVENT_ERROR; - if (cnt == MAX_CNT_RAWTP) - return LIBBPF_PERF_EVENT_DONE; - - return LIBBPF_PERF_EVENT_CONT; + if (!good_kern_stack) + CHECK(!good_kern_stack, "kern_stack", "corrupted kernel stack\n"); + if (!good_user_stack) + CHECK(!good_user_stack, "user_stack", "corrupted user stack\n"); } void test_get_stack_raw_tp(void) { const char *file = "./test_get_stack_rawtp.o"; - int i, efd, err, prog_fd, pmu_fd, perfmap_fd; - struct perf_event_attr attr = {}; + const char *prog_name = "raw_tracepoint/sys_enter"; + int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP; + struct perf_buffer_opts pb_opts = {}; + struct perf_buffer *pb = NULL; + struct bpf_link *link = NULL; struct timespec tv = {0, 10}; - __u32 key = 0, duration = 0; + struct bpf_program *prog; struct bpf_object *obj; + struct bpf_map *map; + cpu_set_t cpu_set; err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd); if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno)) return; - efd = bpf_raw_tracepoint_open("sys_enter", prog_fd); - if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno)) + prog = bpf_object__find_program_by_title(obj, prog_name); + if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name)) goto close_prog; - perfmap_fd = bpf_find_map(__func__, obj, "perfmap"); - if (CHECK(perfmap_fd < 0, "bpf_find_map", "err %d errno %d\n", - perfmap_fd, errno)) + map = bpf_object__find_map_by_name(obj, "perfmap"); + if (CHECK(!map, "bpf_find_map", "not found\n")) goto close_prog; err = load_kallsyms(); if (CHECK(err < 0, "load_kallsyms", "err %d errno %d\n", err, errno)) goto close_prog; - attr.sample_type = PERF_SAMPLE_RAW; - attr.type = PERF_TYPE_SOFTWARE; - attr.config = PERF_COUNT_SW_BPF_OUTPUT; - pmu_fd = syscall(__NR_perf_event_open, &attr, getpid()/*pid*/, -1/*cpu*/, - -1/*group_fd*/, 0); - if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd, - errno)) + CPU_ZERO(&cpu_set); + CPU_SET(0, &cpu_set); + err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set); + if (CHECK(err, "set_affinity", "err %d, errno %d\n", err, errno)) goto close_prog; - err = bpf_map_update_elem(perfmap_fd, &key, &pmu_fd, BPF_ANY); - if (CHECK(err < 0, "bpf_map_update_elem", "err %d errno %d\n", err, - errno)) + link = bpf_program__attach_raw_tracepoint(prog, "sys_enter"); + if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", PTR_ERR(link))) goto close_prog; - err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); - if (CHECK(err < 0, "ioctl PERF_EVENT_IOC_ENABLE", "err %d errno %d\n", - err, errno)) - goto close_prog; - - err = perf_event_mmap(pmu_fd); - if (CHECK(err < 0, "perf_event_mmap", "err %d errno %d\n", err, errno)) + pb_opts.sample_cb = get_stack_print_output; + pb = perf_buffer__new(bpf_map__fd(map), 8, &pb_opts); + if (CHECK(IS_ERR(pb), "perf_buf__new", "err %ld\n", PTR_ERR(pb))) goto close_prog; /* trigger some syscall action */ for (i = 0; i < MAX_CNT_RAWTP; i++) nanosleep(&tv, NULL); - err = perf_event_poller(pmu_fd, get_stack_print_output); - if (CHECK(err < 0, "perf_event_poller", "err %d errno %d\n", err, errno)) - goto close_prog; + while (exp_cnt > 0) { + err = perf_buffer__poll(pb, 100); + if (err < 0 && CHECK(err < 0, "pb__poll", "err %d\n", err)) + goto close_prog; + exp_cnt -= err; + } goto close_prog_noerr; close_prog: error_cnt++; close_prog_noerr: + if (!IS_ERR_OR_NULL(link)) + bpf_link__destroy(link); + if (!IS_ERR_OR_NULL(pb)) + perf_buffer__free(pb); bpf_object__close(obj); } diff --git a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c index 33254b771384..f8ffa3f3d44b 100644 --- a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c +++ b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c @@ -55,7 +55,7 @@ struct { __type(value, raw_stack_trace_t); } rawdata_map SEC(".maps"); -SEC("tracepoint/raw_syscalls/sys_enter") +SEC("raw_tracepoint/sys_enter") int bpf_prog1(void *ctx) { int max_len, max_buildid_len, usize, ksize, total_size; -- GitLab From 898ca681cd78e57cec1f5d18df0829d35c464fe8 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:34:42 -0700 Subject: [PATCH 0403/7155] selftests/bpf: switch test_tcpnotify to perf_buffer API Switch test_tcpnotify test to use libbpf's perf_buffer API instead of re-implementing portion of it. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/test_tcpnotify_user.c | 90 ++++++++----------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/tools/testing/selftests/bpf/test_tcpnotify_user.c b/tools/testing/selftests/bpf/test_tcpnotify_user.c index 86152d9ae95b..f9765ddf0761 100644 --- a/tools/testing/selftests/bpf/test_tcpnotify_user.c +++ b/tools/testing/selftests/bpf/test_tcpnotify_user.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "bpf_rlimit.h" #include "bpf_util.h" @@ -30,28 +31,34 @@ pthread_t tid; int rx_callbacks; -static int dummyfn(void *data, int size) +static void dummyfn(void *ctx, int cpu, void *data, __u32 size) { struct tcp_notifier *t = data; if (t->type != 0xde || t->subtype != 0xad || t->source != 0xbe || t->hash != 0xef) - return 1; + return; rx_callbacks++; - return 0; } -void tcp_notifier_poller(int fd) +void tcp_notifier_poller(struct perf_buffer *pb) { - while (1) - perf_event_poller(fd, dummyfn); + int err; + + while (1) { + err = perf_buffer__poll(pb, 100); + if (err < 0 && err != -EINTR) { + printf("failed perf_buffer__poll: %d\n", err); + return; + } + } } static void *poller_thread(void *arg) { - int fd = *(int *)arg; + struct perf_buffer *pb = arg; - tcp_notifier_poller(fd); + tcp_notifier_poller(pb); return arg; } @@ -60,52 +67,20 @@ int verify_result(const struct tcpnotify_globals *result) return (result->ncalls > 0 && result->ncalls == rx_callbacks ? 0 : 1); } -static int bpf_find_map(const char *test, struct bpf_object *obj, - const char *name) -{ - struct bpf_map *map; - - map = bpf_object__find_map_by_name(obj, name); - if (!map) { - printf("%s:FAIL:map '%s' not found\n", test, name); - return -1; - } - return bpf_map__fd(map); -} - -static int setup_bpf_perf_event(int mapfd) -{ - struct perf_event_attr attr = { - .sample_type = PERF_SAMPLE_RAW, - .type = PERF_TYPE_SOFTWARE, - .config = PERF_COUNT_SW_BPF_OUTPUT, - }; - int key = 0; - int pmu_fd; - - pmu_fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, 0); - if (pmu_fd < 0) - return pmu_fd; - bpf_map_update_elem(mapfd, &key, &pmu_fd, BPF_ANY); - - ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); - return pmu_fd; -} - int main(int argc, char **argv) { const char *file = "test_tcpnotify_kern.o"; - int prog_fd, map_fd, perf_event_fd; + struct bpf_map *perf_map, *global_map; + struct perf_buffer_opts pb_opts = {}; struct tcpnotify_globals g = {0}; + struct perf_buffer *pb = NULL; const char *cg_path = "/foo"; + int prog_fd, rv, cg_fd = -1; int error = EXIT_FAILURE; struct bpf_object *obj; - int cg_fd = -1; - __u32 key = 0; - int rv; char test_script[80]; - int pmu_fd; cpu_set_t cpuset; + __u32 key = 0; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); @@ -133,19 +108,24 @@ int main(int argc, char **argv) goto err; } - perf_event_fd = bpf_find_map(__func__, obj, "perf_event_map"); - if (perf_event_fd < 0) + perf_map = bpf_object__find_map_by_name(obj, "perf_event_map"); + if (!perf_map) { + printf("FAIL:map '%s' not found\n", "perf_event_map"); goto err; + } - map_fd = bpf_find_map(__func__, obj, "global_map"); - if (map_fd < 0) - goto err; + global_map = bpf_object__find_map_by_name(obj, "global_map"); + if (!global_map) { + printf("FAIL:map '%s' not found\n", "global_map"); + return -1; + } - pmu_fd = setup_bpf_perf_event(perf_event_fd); - if (pmu_fd < 0 || perf_event_mmap(pmu_fd) < 0) + pb_opts.sample_cb = dummyfn; + pb = perf_buffer__new(bpf_map__fd(perf_map), 8, &pb_opts); + if (IS_ERR(pb)) goto err; - pthread_create(&tid, NULL, poller_thread, (void *)&pmu_fd); + pthread_create(&tid, NULL, poller_thread, pb); sprintf(test_script, "iptables -A INPUT -p tcp --dport %d -j DROP", @@ -162,7 +142,7 @@ int main(int argc, char **argv) TESTPORT); system(test_script); - rv = bpf_map_lookup_elem(map_fd, &key, &g); + rv = bpf_map_lookup_elem(bpf_map__fd(global_map), &key, &g); if (rv != 0) { printf("FAILED: bpf_map_lookup_elem returns %d\n", rv); goto err; @@ -182,5 +162,7 @@ int main(int argc, char **argv) bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS); close(cg_fd); cleanup_cgroup_environment(); + if (!IS_ERR_OR_NULL(pb)) + perf_buffer__free(pb); return error; } -- GitLab From f58a4d51d8da7b248d8796e9981feb3d5a43d3d2 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:34:43 -0700 Subject: [PATCH 0404/7155] samples/bpf: convert xdp_sample_pkts_user to perf_buffer API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert xdp_sample_pkts_user to libbpf's perf_buffer API. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Acked-by: Toke Høiland-Jørgensen Signed-off-by: Alexei Starovoitov --- samples/bpf/xdp_sample_pkts_user.c | 61 +++++++++--------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c index dc66345a929a..3002714e3cd5 100644 --- a/samples/bpf/xdp_sample_pkts_user.c +++ b/samples/bpf/xdp_sample_pkts_user.c @@ -17,14 +17,13 @@ #include #include "perf-sys.h" -#include "trace_helpers.h" #define MAX_CPUS 128 -static int pmu_fds[MAX_CPUS], if_idx; -static struct perf_event_mmap_page *headers[MAX_CPUS]; +static int if_idx; static char *if_name; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; static __u32 prog_id; +static struct perf_buffer *pb = NULL; static int do_attach(int idx, int fd, const char *name) { @@ -73,7 +72,7 @@ static int do_detach(int idx, const char *name) #define SAMPLE_SIZE 64 -static int print_bpf_output(void *data, int size) +static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) { struct { __u16 cookie; @@ -83,45 +82,20 @@ static int print_bpf_output(void *data, int size) int i; if (e->cookie != 0xdead) { - printf("BUG cookie %x sized %d\n", - e->cookie, size); - return LIBBPF_PERF_EVENT_ERROR; + printf("BUG cookie %x sized %d\n", e->cookie, size); + return; } printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len); for (i = 0; i < 14 && i < e->pkt_len; i++) printf("%02x ", e->pkt_data[i]); printf("\n"); - - return LIBBPF_PERF_EVENT_CONT; -} - -static void test_bpf_perf_event(int map_fd, int num) -{ - struct perf_event_attr attr = { - .sample_type = PERF_SAMPLE_RAW, - .type = PERF_TYPE_SOFTWARE, - .config = PERF_COUNT_SW_BPF_OUTPUT, - .wakeup_events = 1, /* get an fd notification for every event */ - }; - int i; - - for (i = 0; i < num; i++) { - int key = i; - - pmu_fds[i] = sys_perf_event_open(&attr, -1/*pid*/, i/*cpu*/, - -1/*group_fd*/, 0); - - assert(pmu_fds[i] >= 0); - assert(bpf_map_update_elem(map_fd, &key, - &pmu_fds[i], BPF_ANY) == 0); - ioctl(pmu_fds[i], PERF_EVENT_IOC_ENABLE, 0); - } } static void sig_handler(int signo) { do_detach(if_idx, if_name); + perf_buffer__free(pb); exit(0); } @@ -140,13 +114,13 @@ int main(int argc, char **argv) struct bpf_prog_load_attr prog_load_attr = { .prog_type = BPF_PROG_TYPE_XDP, }; + struct perf_buffer_opts pb_opts = {}; const char *optstr = "F"; int prog_fd, map_fd, opt; struct bpf_object *obj; struct bpf_map *map; char filename[256]; - int ret, err, i; - int numcpus; + int ret, err; while ((opt = getopt(argc, argv, optstr)) != -1) { switch (opt) { @@ -169,10 +143,6 @@ int main(int argc, char **argv) return 1; } - numcpus = get_nprocs(); - if (numcpus > MAX_CPUS) - numcpus = MAX_CPUS; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); prog_load_attr.file = filename; @@ -211,14 +181,17 @@ int main(int argc, char **argv) return 1; } - test_bpf_perf_event(map_fd, numcpus); + pb_opts.sample_cb = print_bpf_output; + pb = perf_buffer__new(map_fd, 8, &pb_opts); + err = libbpf_get_error(pb); + if (err) { + perror("perf_buffer setup failed"); + return 1; + } - for (i = 0; i < numcpus; i++) - if (perf_event_mmap_header(pmu_fds[i], &headers[i]) < 0) - return 1; + while ((ret = perf_buffer__poll(pb, 1000)) >= 0) { + } - ret = perf_event_poller_multi(pmu_fds, headers, numcpus, - print_bpf_output); kill(0, SIGINT); return ret; } -- GitLab From c17bec549c9dc969b4e725c56aa9ebb125378397 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:34:44 -0700 Subject: [PATCH 0405/7155] samples/bpf: switch trace_output sample to perf_buffer API Convert trace_output sample to libbpf's perf_buffer API. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- samples/bpf/trace_output_user.c | 43 +++++++++++---------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c index 2dd1d39b152a..8ee47699a870 100644 --- a/samples/bpf/trace_output_user.c +++ b/samples/bpf/trace_output_user.c @@ -18,9 +18,6 @@ #include #include "bpf_load.h" #include "perf-sys.h" -#include "trace_helpers.h" - -static int pmu_fd; static __u64 time_get_ns(void) { @@ -31,12 +28,12 @@ static __u64 time_get_ns(void) } static __u64 start_time; +static __u64 cnt; #define MAX_CNT 100000ll -static int print_bpf_output(void *data, int size) +static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) { - static __u64 cnt; struct { __u64 pid; __u64 cookie; @@ -45,7 +42,7 @@ static int print_bpf_output(void *data, int size) if (e->cookie != 0x12345678) { printf("BUG pid %llx cookie %llx sized %d\n", e->pid, e->cookie, size); - return LIBBPF_PERF_EVENT_ERROR; + return; } cnt++; @@ -53,30 +50,14 @@ static int print_bpf_output(void *data, int size) if (cnt == MAX_CNT) { printf("recv %lld events per sec\n", MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); - return LIBBPF_PERF_EVENT_DONE; + return; } - - return LIBBPF_PERF_EVENT_CONT; -} - -static void test_bpf_perf_event(void) -{ - struct perf_event_attr attr = { - .sample_type = PERF_SAMPLE_RAW, - .type = PERF_TYPE_SOFTWARE, - .config = PERF_COUNT_SW_BPF_OUTPUT, - }; - int key = 0; - - pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); - - assert(pmu_fd >= 0); - assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0); - ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); } int main(int argc, char **argv) { + struct perf_buffer_opts pb_opts = {}; + struct perf_buffer *pb; char filename[256]; FILE *f; int ret; @@ -88,16 +69,20 @@ int main(int argc, char **argv) return 1; } - test_bpf_perf_event(); - - if (perf_event_mmap(pmu_fd) < 0) + pb_opts.sample_cb = print_bpf_output; + pb = perf_buffer__new(map_fd[0], 8, &pb_opts); + ret = libbpf_get_error(pb); + if (ret) { + printf("failed to setup perf_buffer: %d\n", ret); return 1; + } f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r"); (void) f; start_time = time_get_ns(); - ret = perf_event_poller(pmu_fd, print_bpf_output); + while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) { + } kill(0, SIGINT); return ret; } -- GitLab From 47da6e4dc3d37fefd913233c71575666c96491b5 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jul 2019 14:34:45 -0700 Subject: [PATCH 0406/7155] selftests/bpf: remove perf buffer helpers libbpf's perf_buffer API supersedes trace_helper.h's helpers. Remove those helpers after all existing users were already moved to perf_buffer API. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/trace_helpers.c | 125 -------------------- tools/testing/selftests/bpf/trace_helpers.h | 9 -- 2 files changed, 134 deletions(-) diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c index b47f205f0310..7f989b3e4e22 100644 --- a/tools/testing/selftests/bpf/trace_helpers.c +++ b/tools/testing/selftests/bpf/trace_helpers.c @@ -86,128 +86,3 @@ long ksym_get_addr(const char *name) return 0; } - -static int page_size; -static int page_cnt = 8; -static struct perf_event_mmap_page *header; - -int perf_event_mmap_header(int fd, struct perf_event_mmap_page **header) -{ - void *base; - int mmap_size; - - page_size = getpagesize(); - mmap_size = page_size * (page_cnt + 1); - - base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) { - printf("mmap err\n"); - return -1; - } - - *header = base; - return 0; -} - -int perf_event_mmap(int fd) -{ - return perf_event_mmap_header(fd, &header); -} - -static int perf_event_poll(int fd) -{ - struct pollfd pfd = { .fd = fd, .events = POLLIN }; - - return poll(&pfd, 1, 1000); -} - -struct perf_event_sample { - struct perf_event_header header; - __u32 size; - char data[]; -}; - -static enum bpf_perf_event_ret -bpf_perf_event_print(struct perf_event_header *hdr, void *private_data) -{ - struct perf_event_sample *e = (struct perf_event_sample *)hdr; - perf_event_print_fn fn = private_data; - int ret; - - if (e->header.type == PERF_RECORD_SAMPLE) { - ret = fn(e->data, e->size); - if (ret != LIBBPF_PERF_EVENT_CONT) - return ret; - } else if (e->header.type == PERF_RECORD_LOST) { - struct { - struct perf_event_header header; - __u64 id; - __u64 lost; - } *lost = (void *) e; - printf("lost %lld events\n", lost->lost); - } else { - printf("unknown event type=%d size=%d\n", - e->header.type, e->header.size); - } - - return LIBBPF_PERF_EVENT_CONT; -} - -int perf_event_poller(int fd, perf_event_print_fn output_fn) -{ - enum bpf_perf_event_ret ret; - void *buf = NULL; - size_t len = 0; - - for (;;) { - perf_event_poll(fd); - ret = bpf_perf_event_read_simple(header, page_cnt * page_size, - page_size, &buf, &len, - bpf_perf_event_print, - output_fn); - if (ret != LIBBPF_PERF_EVENT_CONT) - break; - } - free(buf); - - return ret; -} - -int perf_event_poller_multi(int *fds, struct perf_event_mmap_page **headers, - int num_fds, perf_event_print_fn output_fn) -{ - enum bpf_perf_event_ret ret; - struct pollfd *pfds; - void *buf = NULL; - size_t len = 0; - int i; - - pfds = calloc(num_fds, sizeof(*pfds)); - if (!pfds) - return LIBBPF_PERF_EVENT_ERROR; - - for (i = 0; i < num_fds; i++) { - pfds[i].fd = fds[i]; - pfds[i].events = POLLIN; - } - - for (;;) { - poll(pfds, num_fds, 1000); - for (i = 0; i < num_fds; i++) { - if (!pfds[i].revents) - continue; - - ret = bpf_perf_event_read_simple(headers[i], - page_cnt * page_size, - page_size, &buf, &len, - bpf_perf_event_print, - output_fn); - if (ret != LIBBPF_PERF_EVENT_CONT) - break; - } - } - free(buf); - free(pfds); - - return ret; -} diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h index 18924f23db1b..aa4dcfe18050 100644 --- a/tools/testing/selftests/bpf/trace_helpers.h +++ b/tools/testing/selftests/bpf/trace_helpers.h @@ -3,7 +3,6 @@ #define __TRACE_HELPER_H #include -#include struct ksym { long addr; @@ -14,12 +13,4 @@ int load_kallsyms(void); struct ksym *ksym_search(long key); long ksym_get_addr(const char *name); -typedef enum bpf_perf_event_ret (*perf_event_print_fn)(void *data, int size); - -int perf_event_mmap(int fd); -int perf_event_mmap_header(int fd, struct perf_event_mmap_page **header); -/* return LIBBPF_PERF_EVENT_DONE or LIBBPF_PERF_EVENT_ERROR */ -int perf_event_poller(int fd, perf_event_print_fn output_fn); -int perf_event_poller_multi(int *fds, struct perf_event_mmap_page **headers, - int num_fds, perf_event_print_fn output_fn); #endif -- GitLab From 61670d62bd9eb3fa3d423b4f8f1d37bca853910d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 1 Jul 2019 15:42:46 +0200 Subject: [PATCH 0407/7155] MAINTAINERS: can: add missing files to CAN NETWORK DRIVERS and CAN NETWORK LAYER This patch adds missing files to the CAN NETWORK DRIVERS and CAN NETWORK LAYER entry. Reported-by: Robert P. J. Day Signed-off-by: Marc Kleine-Budde --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9bca7781d67e..9cc156c58f0c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3631,9 +3631,12 @@ S: Maintained F: Documentation/devicetree/bindings/net/can/ F: drivers/net/can/ F: include/linux/can/dev.h +F: include/linux/can/led.h +F: include/linux/can/rx-offload.h F: include/linux/can/platform/ F: include/uapi/linux/can/error.h F: include/uapi/linux/can/netlink.h +F: include/uapi/linux/can/vxcan.h CAN NETWORK LAYER M: Oliver Hartkopp @@ -3646,6 +3649,8 @@ S: Maintained F: Documentation/networking/can.rst F: net/can/ F: include/linux/can/core.h +F: include/linux/can/skb.h +F: include/net/netns/can.h F: include/uapi/linux/can.h F: include/uapi/linux/can/bcm.h F: include/uapi/linux/can/raw.h -- GitLab From 4dfc39e1b639c7220ac7275dc8684cd8e82f188a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 22 Jul 2019 11:36:08 +0200 Subject: [PATCH 0408/7155] can: sja1000: Makefile/Kconfig: sort alphabetically This patch sorts the drivers in the Makefile alphabetically and arranges the Kconfig file accordingly. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/Kconfig | 71 ++++++++++++++++---------------- drivers/net/can/sja1000/Makefile | 10 ++--- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 6b72da2f18a6..8bd6d7b88fcd 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -1,26 +1,18 @@ # SPDX-License-Identifier: GPL-2.0-only + menuconfig CAN_SJA1000 tristate "Philips/NXP SJA1000 devices" depends on HAS_IOMEM if CAN_SJA1000 -config CAN_SJA1000_ISA - tristate "ISA Bus based legacy SJA1000 driver" - ---help--- - This driver adds legacy support for SJA1000 chips connected to - the ISA bus using I/O port, memory mapped or indirect access. - -config CAN_SJA1000_PLATFORM - tristate "Generic Platform Bus based SJA1000 driver" +config CAN_EMS_PCI + tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card" + depends on PCI ---help--- - This driver adds support for the SJA1000 chips connected to - the "platform bus" (Linux abstraction for directly to the - processor attached devices). Which can be found on various - boards from Phytec (http://www.phytec.de) like the PCM027, - PCM038. It also provides the OpenFirmware "platform bus" found - on embedded systems with OpenFirmware bindings, e.g. if you - have a PowerPC based system you may want to enable this option. + This driver is for the one, two or four channel CPC-PCI, + CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche + (http://www.ems-wuensche.de). config CAN_EMS_PCMCIA tristate "EMS CPC-CARD Card" @@ -29,23 +21,12 @@ config CAN_EMS_PCMCIA This driver is for the one or two channel CPC-CARD cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). -config CAN_EMS_PCI - tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card" +config CAN_KVASER_PCI + tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" depends on PCI ---help--- - This driver is for the one, two or four channel CPC-PCI, - CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche - (http://www.ems-wuensche.de). - -config CAN_PEAK_PCMCIA - tristate "PEAK PCAN-PC Card" - depends on PCMCIA - depends on HAS_IOPORT_MAP - ---help--- - This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels) - from PEAK-System (http://www.peak-system.com). To compile this - driver as a module, choose M here: the module will be called - peak_pcmcia. + This driver is for the PCIcanx and PCIcan cards (1, 2 or + 4 channel) from Kvaser (http://www.kvaser.com). config CAN_PEAK_PCI tristate "PEAK PCAN-PCI/PCIe/miniPCI Cards" @@ -66,12 +47,15 @@ config CAN_PEAK_PCIEC Technik. This will also automatically select I2C and I2C_ALGO configuration options. -config CAN_KVASER_PCI - tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" - depends on PCI +config CAN_PEAK_PCMCIA + tristate "PEAK PCAN-PC Card" + depends on PCMCIA + depends on HAS_IOPORT_MAP ---help--- - This driver is for the PCIcanx and PCIcan cards (1, 2 or - 4 channel) from Kvaser (http://www.kvaser.com). + This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels) + from PEAK-System (http://www.peak-system.com). To compile this + driver as a module, choose M here: the module will be called + peak_pcmcia. config CAN_PLX_PCI tristate "PLX90xx PCI-bridge based Cards" @@ -91,6 +75,23 @@ config CAN_PLX_PCI - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com) - ASEM CAN raw - 2 isolated CAN channels (www.asem.it) +config CAN_SJA1000_ISA + tristate "ISA Bus based legacy SJA1000 driver" + ---help--- + This driver adds legacy support for SJA1000 chips connected to + the ISA bus using I/O port, memory mapped or indirect access. + +config CAN_SJA1000_PLATFORM + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. It also provides the OpenFirmware "platform bus" found + on embedded systems with OpenFirmware bindings, e.g. if you + have a PowerPC based system you may want to enable this option. + config CAN_TSCAN1 tristate "TS-CAN1 PC104 boards" depends on ISA diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 9253aaf9e739..62dad36b76af 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -3,13 +3,13 @@ # Makefile for the SJA1000 CAN controller drivers. # -obj-$(CONFIG_CAN_SJA1000) += sja1000.o -obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o -obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o -obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o +obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o -obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o +obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o +obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o obj-$(CONFIG_CAN_TSCAN1) += tscan1.o -- GitLab From 2a0dd1d7415a5aa61802a24555aeb41b947c9433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sat, 8 Jun 2019 01:11:00 +0200 Subject: [PATCH 0409/7155] arm64: defconfig: Enable IR SUNXI option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable CONFIG_IR_SUNXI option for ARM64, so that Allwinner A64/H6 SoCs can use their IR receiver controller. Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0e58ef02880c..c03618c17b04 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -489,6 +489,7 @@ CONFIG_RC_CORE=m CONFIG_RC_DECODERS=y CONFIG_RC_DEVICES=y CONFIG_IR_MESON=m +CONFIG_IR_SUNXI=m CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -- GitLab From 342d23a7dacf9c254c6b98b9b211e566820b7bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sat, 8 Jun 2019 01:10:52 +0200 Subject: [PATCH 0410/7155] ARM: dts: sunxi: Prefer A31 bindings for IR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since A31, memory mapping of the IR driver has changed. Prefer the A31 bindings instead of A13. Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 2 +- arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +- arch/arm/boot/dts/sun9i-a80.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index dcddc3392460..9ddde111f675 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -1364,7 +1364,7 @@ }; ir: ir@1f02000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; clocks = <&apb0_gates 1>, <&ir_clk>; clock-names = "apb", "ir"; resets = <&apb0_rst 1>; diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 8de139521451..13bc83191899 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -1096,7 +1096,7 @@ r_cir: ir@1f02000 { compatible = "allwinner,sun8i-a83t-ir", - "allwinner,sun5i-a13-ir"; + "allwinner,sun6i-a31-ir"; clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <&r_ccu RST_APB0_IR>; diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 0c1eec9000e3..310cd972ee5b 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -1167,7 +1167,7 @@ }; r_ir: ir@8002000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; interrupts = ; pinctrl-names = "default"; pinctrl-0 = <&r_ir_pins>; -- GitLab From 8fa345e711bfdb69a18f548b717d5eb502b9892a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sat, 8 Jun 2019 01:10:53 +0200 Subject: [PATCH 0411/7155] ARM: dts: sunxi: Prefer A31 bindings for IR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since A31, memory mapping of the IR driver has changed. Prefer the A31 bindings instead of A13. Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index b4a6035ae9f5..97550a40b6e1 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -822,7 +822,7 @@ }; ir: ir@1f02000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <&r_ccu RST_APB0_IR>; -- GitLab From 44a4f416c8388449fc5f9263788857d449e2a65f Mon Sep 17 00:00:00 2001 From: Igors Makejevs Date: Sat, 8 Jun 2019 01:10:55 +0200 Subject: [PATCH 0412/7155] arm64: dts: allwinner: a64: Add IR node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IR peripheral is completely compatible with A31 one. Signed-off-by: Igors Makejevs Signed-off-by: Jernej Skrabec Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index aa9897f270ba..ddb6f11e89df 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1094,6 +1094,19 @@ #size-cells = <0>; }; + r_ir: ir@1f02000 { + compatible = "allwinner,sun50i-a64-ir", + "allwinner,sun6i-a31-ir"; + reg = <0x01f02000 0x400>; + clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; + clock-names = "apb", "ir"; + resets = <&r_ccu RST_APB0_IR>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&r_ir_rx_pin>; + status = "disabled"; + }; + r_pwm: pwm@1f03800 { compatible = "allwinner,sun50i-a64-pwm", "allwinner,sun5i-a13-pwm"; @@ -1121,6 +1134,11 @@ function = "s_i2c"; }; + r_ir_rx_pin: r-ir-rx-pin { + pins = "PL11"; + function = "s_cir_rx"; + }; + r_pwm_pin: r-pwm-pin { pins = "PL10"; function = "s_pwm"; -- GitLab From 63eb1e149576294717e3e5de48e902ca9d2f080d Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 8 Jun 2019 01:10:56 +0200 Subject: [PATCH 0413/7155] arm64: dts: allwinner: a64: Enable IR on Orange Pi Win MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OrangePi Win board contains IR receiver. Enable it. Signed-off-by: Jernej Skrabec Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts index 5ef3c62c765e..04446e4716c4 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts @@ -190,6 +190,10 @@ status = "okay"; }; +&r_ir { + status = "okay"; +}; + &r_rsb { status = "okay"; -- GitLab From 9267811aad3524c857cf2e16bbadd8c569e15ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sat, 8 Jun 2019 01:10:58 +0200 Subject: [PATCH 0414/7155] arm64: dts: allwinner: h6: Add IR receiver node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner H6 IR is similar to A31 and can use same driver. Add support for it. Signed-off-by: Clément Péron Acked-by: Sean Young Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 35942bae0a34..e8bed58e7246 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -675,6 +675,25 @@ pins = "PL0", "PL1"; function = "s_i2c"; }; + + r_ir_rx_pin: r-ir-rx-pin { + pins = "PL9"; + function = "s_cir_rx"; + }; + }; + + r_ir: ir@7040000 { + compatible = "allwinner,sun50i-h6-ir", + "allwinner,sun6i-a31-ir"; + reg = <0x07040000 0x400>; + interrupts = ; + clocks = <&r_ccu CLK_R_APB1_IR>, + <&r_ccu CLK_IR>; + clock-names = "apb", "ir"; + resets = <&r_ccu RST_R_APB1_IR>; + pinctrl-names = "default"; + pinctrl-0 = <&r_ir_rx_pin>; + status = "disabled"; }; r_i2c: i2c@7081400 { -- GitLab From 86be740845e3811c4517de1a8a36121190155e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sat, 8 Jun 2019 01:10:59 +0200 Subject: [PATCH 0415/7155] arm64: dts: allwinner: h6: Enable IR on H6 boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beelink GS1, OrangePi H6 boards and Pine H64 have an IR receiver. Enable it in their device-tree. Signed-off-by: Clément Péron Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 4 ++++ arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 4 ++++ arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts index 0dc33c90dd60..680dc29cb089 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts @@ -232,6 +232,10 @@ }; }; +&r_ir { + status = "okay"; +}; + &r_pio { /* * PL0 and PL1 are used for PMIC I2C diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi index 62e27948a3fa..ec9b6a578e3f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi @@ -189,6 +189,10 @@ }; }; +&r_ir { + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index 189834518391..30102daf83cc 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -255,6 +255,10 @@ }; }; +&r_ir { + status = "okay"; +}; + &r_pio { vcc-pm-supply = <®_aldo1>; }; -- GitLab From 2d91fdccad4d3bd890e03775bcd7e8beed07c610 Mon Sep 17 00:00:00 2001 From: "Ji-Ze Hong (Peter Hong)" Date: Tue, 23 Jul 2019 17:03:06 +0800 Subject: [PATCH 0416/7155] can: sja1000: f81601: add Fintek F81601 support This patch add support for Fintek PCIE to 2 CAN controller support Signed-off-by: Ji-Ze Hong (Peter Hong) Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/Kconfig | 10 ++ drivers/net/can/sja1000/Makefile | 1 + drivers/net/can/sja1000/f81601.c | 212 +++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 drivers/net/can/sja1000/f81601.c diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 8bd6d7b88fcd..32d242dc0d9f 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -21,6 +21,16 @@ config CAN_EMS_PCMCIA This driver is for the one or two channel CPC-CARD cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). +config CAN_F81601 + tristate "Fintek F81601 PCIE to 2 CAN Controller" + depends on PCI + help + This driver adds support for Fintek F81601 PCIE to 2 CAN + Controller. It had internal 24MHz clock source, but it can + be changed by manufacturer. Use modinfo to get usage for + parameters. Visit http://www.fintek.com.tw to get more + information. + config CAN_KVASER_PCI tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" depends on PCI diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 62dad36b76af..500ce1dddaec 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o +obj-$(CONFIG_CAN_F81601) += f81601.o obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o diff --git a/drivers/net/can/sja1000/f81601.c b/drivers/net/can/sja1000/f81601.c new file mode 100644 index 000000000000..362a9d4f44d5 --- /dev/null +++ b/drivers/net/can/sja1000/f81601.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Fintek F81601 PCIE to 2 CAN controller driver + * + * Copyright (C) 2019 Peter Hong + * Copyright (C) 2019 Linux Foundation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +#define F81601_PCI_MAX_CHAN 2 + +#define F81601_DECODE_REG 0x209 +#define F81601_IO_MODE BIT(7) +#define F81601_MEM_MODE BIT(6) +#define F81601_CFG_MODE BIT(5) +#define F81601_CAN2_INTERNAL_CLK BIT(3) +#define F81601_CAN1_INTERNAL_CLK BIT(2) +#define F81601_CAN2_EN BIT(1) +#define F81601_CAN1_EN BIT(0) + +#define F81601_TRAP_REG 0x20a +#define F81601_CAN2_HAS_EN BIT(4) + +struct f81601_pci_card { + void __iomem *addr; + spinlock_t lock; /* use this spin lock only for write access */ + struct pci_dev *dev; + struct net_device *net_dev[F81601_PCI_MAX_CHAN]; +}; + +static const struct pci_device_id f81601_pci_tbl[] = { + { PCI_DEVICE(0x1c29, 0x1703) }, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(pci, f81601_pci_tbl); + +static bool internal_clk = true; +module_param(internal_clk, bool, 0444); +MODULE_PARM_DESC(internal_clk, "Use internal clock, default true (24MHz)"); + +static unsigned int external_clk; +module_param(external_clk, uint, 0444); +MODULE_PARM_DESC(external_clk, "External clock when internal_clk disabled"); + +static u8 f81601_pci_read_reg(const struct sja1000_priv *priv, int port) +{ + return readb(priv->reg_base + port); +} + +static void f81601_pci_write_reg(const struct sja1000_priv *priv, int port, + u8 val) +{ + struct f81601_pci_card *card = priv->priv; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); + writeb(val, priv->reg_base + port); + readb(priv->reg_base); + spin_unlock_irqrestore(&card->lock, flags); +} + +static void f81601_pci_remove(struct pci_dev *pdev) +{ + struct f81601_pci_card *card = pci_get_drvdata(pdev); + struct net_device *dev; + int i; + + for (i = 0; i < ARRAY_SIZE(card->net_dev); i++) { + dev = card->net_dev[i]; + if (!dev) + continue; + + dev_info(&pdev->dev, "%s: Removing %s\n", __func__, dev->name); + + unregister_sja1000dev(dev); + free_sja1000dev(dev); + } +} + +/* Probe F81601 based device for the SJA1000 chips and register each + * available CAN channel to SJA1000 Socket-CAN subsystem. + */ +static int f81601_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct sja1000_priv *priv; + struct net_device *dev; + struct f81601_pci_card *card; + int err, i, count; + u8 tmp; + + if (pcim_enable_device(pdev) < 0) { + dev_err(&pdev->dev, "Failed to enable PCI device\n"); + return -ENODEV; + } + + dev_info(&pdev->dev, "Detected card at slot #%i\n", + PCI_SLOT(pdev->devfn)); + + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->dev = pdev; + spin_lock_init(&card->lock); + + pci_set_drvdata(pdev, card); + + tmp = F81601_IO_MODE | F81601_MEM_MODE | F81601_CFG_MODE | + F81601_CAN2_EN | F81601_CAN1_EN; + + if (internal_clk) { + tmp |= F81601_CAN2_INTERNAL_CLK | F81601_CAN1_INTERNAL_CLK; + + dev_info(&pdev->dev, + "F81601 running with internal clock: 24Mhz\n"); + } else { + dev_info(&pdev->dev, + "F81601 running with external clock: %dMhz\n", + external_clk / 1000000); + } + + pci_write_config_byte(pdev, F81601_DECODE_REG, tmp); + + card->addr = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0)); + + if (!card->addr) { + err = -ENOMEM; + dev_err(&pdev->dev, "%s: Failed to remap BAR\n", __func__); + goto failure_cleanup; + } + + /* read CAN2_HW_EN strap pin to detect how many CANBUS do we have */ + count = ARRAY_SIZE(card->net_dev); + pci_read_config_byte(pdev, F81601_TRAP_REG, &tmp); + if (!(tmp & F81601_CAN2_HAS_EN)) + count = 1; + + for (i = 0; i < count; i++) { + dev = alloc_sja1000dev(0); + if (!dev) { + err = -ENOMEM; + goto failure_cleanup; + } + + priv = netdev_priv(dev); + priv->priv = card; + priv->irq_flags = IRQF_SHARED; + priv->reg_base = card->addr + 0x80 * i; + priv->read_reg = f81601_pci_read_reg; + priv->write_reg = f81601_pci_write_reg; + + if (internal_clk) + priv->can.clock.freq = 24000000 / 2; + else + priv->can.clock.freq = external_clk / 2; + + priv->ocr = OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL; + priv->cdr = CDR_CBP; + + SET_NETDEV_DEV(dev, &pdev->dev); + dev->dev_id = i; + dev->irq = pdev->irq; + + /* Register SJA1000 device */ + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, + "%s: Registering device failed: %x\n", __func__, + err); + free_sja1000dev(dev); + goto failure_cleanup; + } + + card->net_dev[i] = dev; + dev_info(&pdev->dev, "Channel #%d, %s at 0x%p, irq %d\n", i, + dev->name, priv->reg_base, dev->irq); + } + + return 0; + + failure_cleanup: + dev_err(&pdev->dev, "%s: failed: %d. Cleaning Up.\n", __func__, err); + f81601_pci_remove(pdev); + + return err; +} + +static struct pci_driver f81601_pci_driver = { + .name = "f81601", + .id_table = f81601_pci_tbl, + .probe = f81601_pci_probe, + .remove = f81601_pci_remove, +}; + +MODULE_DESCRIPTION("Fintek F81601 PCIE to 2 CANBUS adaptor driver"); +MODULE_AUTHOR("Peter Hong "); +MODULE_LICENSE("GPL v2"); + +module_pci_driver(f81601_pci_driver); -- GitLab From d9e5d174ad8b23ef3e9a2b76cce98548595f6e2b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:10:35 -0600 Subject: [PATCH 0417/7155] can: kvaser_usb: Use struct_size() in alloc_candev() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = alloc(sizeof(struct foo) + count * sizeof(void *)); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = alloc(struct_size(instance, entry, count)); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index c89c7d4900d7..0f1d3e807d63 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -643,8 +643,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, return err; } - netdev = alloc_candev(sizeof(*priv) + - dev->max_tx_urbs * sizeof(*priv->tx_contexts), + netdev = alloc_candev(struct_size(priv, tx_contexts, dev->max_tx_urbs), dev->max_tx_urbs); if (!netdev) { dev_err(&dev->intf->dev, "Cannot alloc candev\n"); -- GitLab From 26ad340e582d3d5958ed8456a1911d79cfb567b4 Mon Sep 17 00:00:00 2001 From: Henning Colliander Date: Tue, 28 May 2019 14:48:21 +0200 Subject: [PATCH 0418/7155] can: kvaser_pciefd: Add driver for Kvaser PCIEcan devices This patch adds support for Kvaser PCIEcan devices. This includes support for up to 4 CAN channels on a single card, depending on device. Signed-off-by: Henning Colliander Signed-off-by: Jimmy Assarsson Signed-off-by: Christer Beskow Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 13 + drivers/net/can/Makefile | 1 + drivers/net/can/kvaser_pciefd.c | 1912 +++++++++++++++++++++++++++++++ 3 files changed, 1926 insertions(+) create mode 100644 drivers/net/can/kvaser_pciefd.c diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index ab585900a057..17c166cc8482 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -120,6 +120,19 @@ config CAN_JANZ_ICAN3 This driver can also be built as a module. If so, the module will be called janz-ican3.ko. +config CAN_KVASER_PCIEFD + depends on PCI + tristate "Kvaser PCIe FD cards" + help + This is a driver for the Kvaser PCI Express CAN FD family. + + Supported devices: + Kvaser PCIEcan 4xHS + Kvaser PCIEcan 2xHS v2 + Kvaser PCIEcan HS v2 + Kvaser Mini PCI Express HS v2 + Kvaser Mini PCI Express 2xHS v2 + config CAN_SUN4I tristate "Allwinner A10 CAN controller" depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 44922bf29b6a..22164300122d 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o obj-$(CONFIG_CAN_GRCAN) += grcan.o obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/ obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o +obj-$(CONFIG_CAN_KVASER_PCIEFD) += kvaser_pciefd.o obj-$(CONFIG_CAN_MSCAN) += mscan/ obj-$(CONFIG_CAN_M_CAN) += m_can/ obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/ diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c new file mode 100644 index 000000000000..3af747cbbde4 --- /dev/null +++ b/drivers/net/can/kvaser_pciefd.c @@ -0,0 +1,1912 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved. + * Parts of this driver are based on the following: + * - Kvaser linux pciefd driver (version 5.25) + * - PEAK linux canfd driver + * - Altera Avalon EPCS flash controller driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Kvaser AB "); +MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); + +#define KVASER_PCIEFD_DRV_NAME "kvaser_pciefd" + +#define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000) +#define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) +#define KVASER_PCIEFD_MAX_ERR_REP 256 +#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17 +#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4 +#define KVASER_PCIEFD_DMA_COUNT 2 + +#define KVASER_PCIEFD_DMA_SIZE (4 * 1024) +#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) + +#define KVASER_PCIEFD_VENDOR 0x1a07 +#define KVASER_PCIEFD_4HS_ID 0x0d +#define KVASER_PCIEFD_2HS_ID 0x0e +#define KVASER_PCIEFD_HS_ID 0x0f +#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10 +#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11 + +/* PCIe IRQ registers */ +#define KVASER_PCIEFD_IRQ_REG 0x40 +#define KVASER_PCIEFD_IEN_REG 0x50 +/* DMA map */ +#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 +/* Kvaser KCAN CAN controller registers */ +#define KVASER_PCIEFD_KCAN0_BASE 0x10000 +#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 +#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 +#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 +#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 +#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 +#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 +#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 +#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414 +#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 +#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c +#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 +#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 +#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 +/* Loopback control register */ +#define KVASER_PCIEFD_LOOP_REG 0x1f000 +/* System identification and information registers */ +#define KVASER_PCIEFD_SYSID_BASE 0x1f020 +#define KVASER_PCIEFD_SYSID_VERSION_REG (KVASER_PCIEFD_SYSID_BASE + 0x8) +#define KVASER_PCIEFD_SYSID_CANFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0xc) +#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14) +/* Shared receive buffer registers */ +#define KVASER_PCIEFD_SRB_BASE 0x1f200 +#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200) +#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204) +#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c) +#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210) +#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218) +/* EPCS flash controller registers */ +#define KVASER_PCIEFD_SPI_BASE 0x1fc00 +#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE +#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4) +#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8) +#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc) +#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14) + +#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f +#define KVASER_PCIEFD_IRQ_SRB BIT(4) + +#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24 +#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16 +#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1 + +/* Reset DMA buffer 0, 1 and FIFO offset */ +#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) +#define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5) +#define KVASER_PCIEFD_SRB_CMD_FOR BIT(0) + +/* DMA packet done, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) +#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) +/* DMA overflow, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) +#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) +/* DMA underflow, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) +#define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13) + +/* DMA idle */ +#define KVASER_PCIEFD_SRB_STAT_DI BIT(15) +/* DMA support */ +#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) + +/* DMA Enable */ +#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0) + +/* EPCS flash controller definitions */ +#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024) +#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L) +#define KVASER_PCIEFD_CFG_MAX_PARAMS 256 +#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d +#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24 +#define KVASER_PCIEFD_CFG_SYS_VER 1 +#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130 +#define KVASER_PCIEFD_SPI_TMT BIT(5) +#define KVASER_PCIEFD_SPI_TRDY BIT(6) +#define KVASER_PCIEFD_SPI_RRDY BIT(7) +#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14 +/* Commands for controlling the onboard flash */ +#define KVASER_PCIEFD_FLASH_RES_CMD 0xab +#define KVASER_PCIEFD_FLASH_READ_CMD 0x3 +#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5 + +/* Kvaser KCAN definitions */ +#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29) +#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29) + +#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16 +/* Request status packet */ +#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) +/* Abort, flush and reset */ +#define KVASER_PCIEFD_KCAN_CMD_AT BIT(1) + +/* Tx FIFO unaligned read */ +#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) +/* Tx FIFO unaligned end */ +#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) +/* Bus parameter protection error */ +#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) +/* FDF bit when controller is in classic mode */ +#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) +/* Rx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) +/* Abort done */ +#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) +/* Tx buffer flush done */ +#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) +/* Tx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) +/* Tx FIFO empty */ +#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) +/* Transmitter unaligned */ +#define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17) + +#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16 + +#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24 +/* Abort request */ +#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) +/* Idle state. Controller in reset mode and no abort or flush pending */ +#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) +/* Bus off */ +#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) +/* Reset mode request */ +#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) +/* Controller in reset mode */ +#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) +/* Controller got one-shot capability */ +#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) +/* Controller got CAN FD capability */ +#define KVASER_PCIEFD_KCAN_STAT_FD BIT(19) +#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \ + KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \ + KVASER_PCIEFD_KCAN_STAT_IRM) + +/* Reset mode */ +#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) +/* Listen only mode */ +#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) +/* Error packet enable */ +#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) +/* CAN FD non-ISO */ +#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) +/* Acknowledgment packet type */ +#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) +/* Active error flag enable. Clear to force error passive */ +#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) +/* Classic CAN mode */ +#define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31) + +#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13 +#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17 +#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26 + +#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16 + +/* Kvaser KCAN packet types */ +#define KVASER_PCIEFD_PACK_TYPE_DATA 0 +#define KVASER_PCIEFD_PACK_TYPE_ACK 1 +#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2 +#define KVASER_PCIEFD_PACK_TYPE_ERROR 3 +#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4 +#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5 +#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6 +#define KVASER_PCIEFD_PACK_TYPE_STATUS 8 +#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9 + +/* Kvaser KCAN packet common definitions */ +#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff +#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25 +#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28 + +/* Kvaser KCAN TDATA and RDATA first word */ +#define KVASER_PCIEFD_RPACKET_IDE BIT(30) +#define KVASER_PCIEFD_RPACKET_RTR BIT(29) +/* Kvaser KCAN TDATA and RDATA second word */ +#define KVASER_PCIEFD_RPACKET_ESI BIT(13) +#define KVASER_PCIEFD_RPACKET_BRS BIT(14) +#define KVASER_PCIEFD_RPACKET_FDF BIT(15) +#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8 +/* Kvaser KCAN TDATA second word */ +#define KVASER_PCIEFD_TPACKET_SMS BIT(16) +#define KVASER_PCIEFD_TPACKET_AREQ BIT(31) + +/* Kvaser KCAN APACKET */ +#define KVASER_PCIEFD_APACKET_FLU BIT(8) +#define KVASER_PCIEFD_APACKET_CT BIT(9) +#define KVASER_PCIEFD_APACKET_ABL BIT(10) +#define KVASER_PCIEFD_APACKET_NACK BIT(11) + +/* Kvaser KCAN SPACK first word */ +#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8 +#define KVASER_PCIEFD_SPACK_BOFF BIT(16) +#define KVASER_PCIEFD_SPACK_IDET BIT(20) +#define KVASER_PCIEFD_SPACK_IRM BIT(21) +#define KVASER_PCIEFD_SPACK_RMCD BIT(22) +/* Kvaser KCAN SPACK second word */ +#define KVASER_PCIEFD_SPACK_AUTO BIT(21) +#define KVASER_PCIEFD_SPACK_EWLR BIT(23) +#define KVASER_PCIEFD_SPACK_EPLR BIT(24) + +struct kvaser_pciefd; + +struct kvaser_pciefd_can { + struct can_priv can; + struct kvaser_pciefd *kv_pcie; + void __iomem *reg_base; + struct can_berr_counter bec; + u8 cmd_seq; + int err_rep_cnt; + int echo_idx; + spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */ + spinlock_t echo_lock; /* Locks the message echo buffer */ + struct timer_list bec_poll_timer; + struct completion start_comp, flush_comp; +}; + +struct kvaser_pciefd { + struct pci_dev *pci; + void __iomem *reg_base; + struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS]; + void *dma_data[KVASER_PCIEFD_DMA_COUNT]; + u8 nr_channels; + u32 freq; + u32 freq_to_ticks_div; +}; + +struct kvaser_pciefd_rx_packet { + u32 header[2]; + u64 timestamp; +}; + +struct kvaser_pciefd_tx_packet { + u32 header[2]; + u8 data[64]; +}; + +static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { + .name = KVASER_PCIEFD_DRV_NAME, + .tseg1_min = 1, + .tseg1_max = 255, + .tseg2_min = 1, + .tseg2_max = 32, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 4096, + .brp_inc = 1, +}; + +struct kvaser_pciefd_cfg_param { + __le32 magic; + __le32 nr; + __le32 len; + u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ]; +}; + +struct kvaser_pciefd_cfg_img { + __le32 version; + __le32 magic; + __le32 crc; + struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS]; +}; + +static struct pci_device_id kvaser_pciefd_id_table[] = { + { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), }, + { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), }, + { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), }, + { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), }, + { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), }, + { 0,}, +}; +MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table); + +/* Onboard flash memory functions */ +static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk) +{ + u32 res; + int ret; + + ret = readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG, + res, res & msk, 0, 10); + + return ret; +} + +static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx, + u32 tx_len, u8 *rx, u32 rx_len) +{ + int c; + + iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG); + iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); + ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); + + c = tx_len; + while (c--) { + if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) + return -EIO; + + iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); + + if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) + return -EIO; + + ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); + } + + c = rx_len; + while (c-- > 0) { + if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) + return -EIO; + + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); + + if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) + return -EIO; + + *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); + } + + if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT)) + return -EIO; + + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); + + if (c != -1) { + dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n"); + return -EIO; + } + + return 0; +} + +static int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_cfg_img *img) +{ + int offset = KVASER_PCIEFD_CFG_IMG_OFFSET; + int res, crc; + u8 *crc_buff; + + u8 cmd[] = { + KVASER_PCIEFD_FLASH_READ_CMD, + (u8)((offset >> 16) & 0xff), + (u8)((offset >> 8) & 0xff), + (u8)(offset & 0xff) + }; + + res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img, + KVASER_PCIEFD_CFG_IMG_SZ); + if (res) + return res; + + crc_buff = (u8 *)img->params; + + if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) { + dev_err(&pcie->pci->dev, + "Config flash corrupted, version number is wrong\n"); + return -ENODEV; + } + + if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) { + dev_err(&pcie->pci->dev, + "Config flash corrupted, magic number is wrong\n"); + return -ENODEV; + } + + crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params)); + if (le32_to_cpu(img->crc) != crc) { + dev_err(&pcie->pci->dev, + "Stored CRC does not match flash image contents\n"); + return -EIO; + } + + return 0; +} + +static void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_cfg_img *img) +{ + struct kvaser_pciefd_cfg_param *param; + + param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN]; + memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len)); +} + +static int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie) +{ + int res; + struct kvaser_pciefd_cfg_img *img; + + /* Read electronic signature */ + u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0}; + + res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1); + if (res) + return -EIO; + + img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL); + if (!img) + return -ENOMEM; + + if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) { + dev_err(&pcie->pci->dev, + "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n", + cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16); + + res = -ENODEV; + goto image_free; + } + + cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD; + res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1); + if (res) { + goto image_free; + } else if (cmd[0] & 1) { + res = -EIO; + /* No write is ever done, the WIP should never be set */ + dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n"); + goto image_free; + } + + res = kvaser_pciefd_cfg_read_and_verify(pcie, img); + if (res) { + res = -EIO; + goto image_free; + } + + kvaser_pciefd_cfg_read_params(pcie, img); + +image_free: + kfree(img); + return res; +} + +static void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) +{ + u32 cmd; + + cmd = KVASER_PCIEFD_KCAN_CMD_SRQ; + cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; + iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); +} + +static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can) +{ + u32 mode; + unsigned long irq; + + spin_lock_irqsave(&can->lock, irq); + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) { + mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + } + spin_unlock_irqrestore(&can->lock, irq); +} + +static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can) +{ + u32 mode; + unsigned long irq; + + spin_lock_irqsave(&can->lock, irq); + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN; + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + spin_unlock_irqrestore(&can->lock, irq); +} + +static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) +{ + u32 msk; + + msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF | + KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD | + KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL | + KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP | + KVASER_PCIEFD_KCAN_IRQ_TAR | KVASER_PCIEFD_KCAN_IRQ_TFD; + + iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + + return 0; +} + +static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) +{ + u32 mode; + unsigned long irq; + + spin_lock_irqsave(&can->lock, irq); + + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + if (can->can.ctrlmode & CAN_CTRLMODE_FD) { + mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM; + if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) + mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN; + else + mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; + } else { + mode |= KVASER_PCIEFD_KCAN_MODE_CCM; + mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; + } + + if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + mode |= KVASER_PCIEFD_KCAN_MODE_LOM; + + mode |= KVASER_PCIEFD_KCAN_MODE_EEN; + mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; + /* Use ACK packet type */ + mode &= ~KVASER_PCIEFD_KCAN_MODE_APT; + mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + + spin_unlock_irqrestore(&can->lock, irq); +} + +static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) +{ + u32 status; + unsigned long irq; + + spin_lock_irqsave(&can->lock, irq); + iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + + status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); + if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) { + u32 cmd; + + /* If controller is already idle, run abort, flush and reset */ + cmd = KVASER_PCIEFD_KCAN_CMD_AT; + cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; + iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) { + u32 mode; + + /* Put controller in reset mode */ + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + mode |= KVASER_PCIEFD_KCAN_MODE_RM; + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + } + + spin_unlock_irqrestore(&can->lock, irq); +} + +static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) +{ + u32 mode; + unsigned long irq; + + del_timer(&can->bec_poll_timer); + + if (!completion_done(&can->flush_comp)) + kvaser_pciefd_start_controller_flush(can); + + if (!wait_for_completion_timeout(&can->flush_comp, + KVASER_PCIEFD_WAIT_TIMEOUT)) { + netdev_err(can->can.dev, "Timeout during bus on flush\n"); + return -ETIMEDOUT; + } + + spin_lock_irqsave(&can->lock, irq); + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + + iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + spin_unlock_irqrestore(&can->lock, irq); + + if (!wait_for_completion_timeout(&can->start_comp, + KVASER_PCIEFD_WAIT_TIMEOUT)) { + netdev_err(can->can.dev, "Timeout during bus on reset\n"); + return -ETIMEDOUT; + } + /* Reset interrupt handling */ + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + + kvaser_pciefd_set_tx_irq(can); + kvaser_pciefd_setup_controller(can); + + can->can.state = CAN_STATE_ERROR_ACTIVE; + netif_wake_queue(can->can.dev); + can->bec.txerr = 0; + can->bec.rxerr = 0; + can->err_rep_cnt = 0; + + return 0; +} + +static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) +{ + int top, trigger; + u32 pwm_ctrl; + unsigned long irq; + + spin_lock_irqsave(&can->lock, irq); + pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); + top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff; + + trigger = (100 * top + 50) / 100; + if (trigger < 0) + trigger = 0; + + pwm_ctrl = trigger & 0xff; + pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); + spin_unlock_irqrestore(&can->lock, irq); +} + +static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can) +{ + int top, trigger; + u32 pwm_ctrl; + unsigned long irq; + + kvaser_pciefd_pwm_stop(can); + spin_lock_irqsave(&can->lock, irq); + + /* Set frequency to 500 KHz*/ + top = can->can.clock.freq / (2 * 500000) - 1; + + pwm_ctrl = top & 0xff; + pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); + + /* Set duty cycle to 95 */ + trigger = (100 * top - 95 * (top + 1) + 50) / 100; + pwm_ctrl = trigger & 0xff; + pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); + spin_unlock_irqrestore(&can->lock, irq); +} + +static int kvaser_pciefd_open(struct net_device *netdev) +{ + int err; + struct kvaser_pciefd_can *can = netdev_priv(netdev); + + err = open_candev(netdev); + if (err) + return err; + + err = kvaser_pciefd_bus_on(can); + if (err) + return err; + + return 0; +} + +static int kvaser_pciefd_stop(struct net_device *netdev) +{ + struct kvaser_pciefd_can *can = netdev_priv(netdev); + int ret = 0; + + /* Don't interrupt ongoing flush */ + if (!completion_done(&can->flush_comp)) + kvaser_pciefd_start_controller_flush(can); + + if (!wait_for_completion_timeout(&can->flush_comp, + KVASER_PCIEFD_WAIT_TIMEOUT)) { + netdev_err(can->can.dev, "Timeout during stop\n"); + ret = -ETIMEDOUT; + } else { + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + del_timer(&can->bec_poll_timer); + } + close_candev(netdev); + + return ret; +} + +static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, + struct kvaser_pciefd_can *can, + struct sk_buff *skb) +{ + struct canfd_frame *cf = (struct canfd_frame *)skb->data; + int packet_size; + int seq = can->echo_idx; + + memset(p, 0, sizeof(*p)); + + if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + p->header[1] |= KVASER_PCIEFD_TPACKET_SMS; + + if (cf->can_id & CAN_RTR_FLAG) + p->header[0] |= KVASER_PCIEFD_RPACKET_RTR; + + if (cf->can_id & CAN_EFF_FLAG) + p->header[0] |= KVASER_PCIEFD_RPACKET_IDE; + + p->header[0] |= cf->can_id & CAN_EFF_MASK; + p->header[1] |= can_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT; + p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ; + + if (can_is_canfd_skb(skb)) { + p->header[1] |= KVASER_PCIEFD_RPACKET_FDF; + if (cf->flags & CANFD_BRS) + p->header[1] |= KVASER_PCIEFD_RPACKET_BRS; + if (cf->flags & CANFD_ESI) + p->header[1] |= KVASER_PCIEFD_RPACKET_ESI; + } + + p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK; + + packet_size = cf->len; + memcpy(p->data, cf->data, packet_size); + + return DIV_ROUND_UP(packet_size, 4); +} + +static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + struct kvaser_pciefd_can *can = netdev_priv(netdev); + unsigned long irq_flags; + struct kvaser_pciefd_tx_packet packet; + int nwords; + u8 count; + + if (can_dropped_invalid_skb(netdev, skb)) + return NETDEV_TX_OK; + + nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); + + spin_lock_irqsave(&can->echo_lock, irq_flags); + + /* Prepare and save echo skb in internal slot */ + can_put_echo_skb(skb, netdev, can->echo_idx); + + /* Move echo index to the next slot */ + can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max; + + /* Write header to fifo */ + iowrite32(packet.header[0], + can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); + iowrite32(packet.header[1], + can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); + + if (nwords) { + u32 data_last = ((u32 *)packet.data)[nwords - 1]; + + /* Write data to fifo, except last word */ + iowrite32_rep(can->reg_base + + KVASER_PCIEFD_KCAN_FIFO_REG, packet.data, + nwords - 1); + /* Write last word to end of fifo */ + __raw_writel(data_last, can->reg_base + + KVASER_PCIEFD_KCAN_FIFO_LAST_REG); + } else { + /* Complete write to fifo */ + __raw_writel(0, can->reg_base + + KVASER_PCIEFD_KCAN_FIFO_LAST_REG); + } + + count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); + /* No room for a new message, stop the queue until at least one + * successful transmit + */ + if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT || + can->can.echo_skb[can->echo_idx]) + netif_stop_queue(netdev); + + spin_unlock_irqrestore(&can->echo_lock, irq_flags); + + return NETDEV_TX_OK; +} + +static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) +{ + u32 mode, test, btrn; + unsigned long irq_flags; + int ret; + struct can_bittiming *bt; + + if (data) + bt = &can->can.data_bittiming; + else + bt = &can->can.bittiming; + + btrn = ((bt->phase_seg2 - 1) & 0x1f) << + KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT | + (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) << + KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT | + ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT | + ((bt->brp - 1) & 0x1fff); + + spin_lock_irqsave(&can->lock, irq_flags); + mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + + /* Put the circuit in reset mode */ + iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM, + can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + + /* Can only set bittiming if in reset mode */ + ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG, + test, test & KVASER_PCIEFD_KCAN_MODE_RM, + 0, 10); + + if (ret) { + spin_unlock_irqrestore(&can->lock, irq_flags); + return -EBUSY; + } + + if (data) + iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG); + else + iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG); + + /* Restore previous reset mode status */ + iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); + + spin_unlock_irqrestore(&can->lock, irq_flags); + return 0; +} + +static int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev) +{ + return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false); +} + +static int kvaser_pciefd_set_data_bittiming(struct net_device *ndev) +{ + return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true); +} + +static int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode) +{ + struct kvaser_pciefd_can *can = netdev_priv(ndev); + int ret = 0; + + switch (mode) { + case CAN_MODE_START: + if (!can->can.restart_ms) + ret = kvaser_pciefd_bus_on(can); + break; + default: + return -EOPNOTSUPP; + } + + return ret; +} + +static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev, + struct can_berr_counter *bec) +{ + struct kvaser_pciefd_can *can = netdev_priv(ndev); + + bec->rxerr = can->bec.rxerr; + bec->txerr = can->bec.txerr; + return 0; +} + +static void kvaser_pciefd_bec_poll_timer(struct timer_list *data) +{ + struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer); + + kvaser_pciefd_enable_err_gen(can); + kvaser_pciefd_request_status(can); + can->err_rep_cnt = 0; +} + +static const struct net_device_ops kvaser_pciefd_netdev_ops = { + .ndo_open = kvaser_pciefd_open, + .ndo_stop = kvaser_pciefd_stop, + .ndo_start_xmit = kvaser_pciefd_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) +{ + int i; + + for (i = 0; i < pcie->nr_channels; i++) { + struct net_device *netdev; + struct kvaser_pciefd_can *can; + u32 status, tx_npackets; + + netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), + KVASER_PCIEFD_CAN_TX_MAX_COUNT); + if (!netdev) + return -ENOMEM; + + can = netdev_priv(netdev); + netdev->netdev_ops = &kvaser_pciefd_netdev_ops; + can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + + i * KVASER_PCIEFD_KCAN_BASE_OFFSET; + + can->kv_pcie = pcie; + can->cmd_seq = 0; + can->err_rep_cnt = 0; + can->bec.txerr = 0; + can->bec.rxerr = 0; + + init_completion(&can->start_comp); + init_completion(&can->flush_comp); + timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, + 0); + + tx_npackets = ioread32(can->reg_base + + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); + if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) & + 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) { + dev_err(&pcie->pci->dev, + "Max Tx count is smaller than expected\n"); + + free_candev(netdev); + return -ENODEV; + } + + can->can.clock.freq = pcie->freq; + can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT; + can->echo_idx = 0; + spin_lock_init(&can->echo_lock); + spin_lock_init(&can->lock); + can->can.bittiming_const = &kvaser_pciefd_bittiming_const; + can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; + + can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; + can->can.do_set_data_bittiming = + kvaser_pciefd_set_data_bittiming; + + can->can.do_set_mode = kvaser_pciefd_set_mode; + can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; + + can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO; + + status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); + if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) { + dev_err(&pcie->pci->dev, + "CAN FD not supported as expected %d\n", i); + + free_candev(netdev); + return -ENODEV; + } + + if (status & KVASER_PCIEFD_KCAN_STAT_CAP) + can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; + + netdev->flags |= IFF_ECHO; + + SET_NETDEV_DEV(netdev, &pcie->pci->dev); + + iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | + KVASER_PCIEFD_KCAN_IRQ_TFD, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + + pcie->can[i] = can; + kvaser_pciefd_pwm_start(can); + } + + return 0; +} + +static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie) +{ + int i; + + for (i = 0; i < pcie->nr_channels; i++) { + int err = register_candev(pcie->can[i]->can.dev); + + if (err) { + int j; + + /* Unregister all successfully registered devices. */ + for (j = 0; j < i; j++) + unregister_candev(pcie->can[j]->can.dev); + return err; + } + } + + return 0; +} + +static void kvaser_pciefd_write_dma_map(struct kvaser_pciefd *pcie, + dma_addr_t addr, int offset) +{ + u32 word1, word2; + +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + word1 = addr | KVASER_PCIEFD_64BIT_DMA_BIT; + word2 = addr >> 32; +#else + word1 = addr; + word2 = 0; +#endif + iowrite32(word1, pcie->reg_base + offset); + iowrite32(word2, pcie->reg_base + offset + 4); +} + +static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) +{ + int i; + u32 srb_status; + dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT]; + + /* Disable the DMA */ + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { + unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i; + + pcie->dma_data[i] = + dmam_alloc_coherent(&pcie->pci->dev, + KVASER_PCIEFD_DMA_SIZE, + &dma_addr[i], + GFP_KERNEL); + + if (!pcie->dma_data[i] || !dma_addr[i]) { + dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n", + KVASER_PCIEFD_DMA_SIZE); + return -ENOMEM; + } + + kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); + } + + /* Reset Rx FIFO, and both DMA buffers */ + iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | + KVASER_PCIEFD_SRB_CMD_RDB1, + pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + + srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); + if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) { + dev_err(&pcie->pci->dev, "DMA not idle before enabling\n"); + return -EIO; + } + + /* Enable the DMA */ + iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE, + pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + + return 0; +} + +static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) +{ + u32 sysid, srb_status, build; + u8 sysid_nr_chan; + int ret; + + ret = kvaser_pciefd_read_cfg(pcie); + if (ret) + return ret; + + sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); + sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff; + if (pcie->nr_channels != sysid_nr_chan) { + dev_err(&pcie->pci->dev, + "Number of channels does not match: %u vs %u\n", + pcie->nr_channels, + sysid_nr_chan); + return -ENODEV; + } + + if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS) + pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS; + + build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); + dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n", + (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff, + sysid & 0xff, + (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff); + + srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); + if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { + dev_err(&pcie->pci->dev, + "Hardware without DMA is not supported\n"); + return -ENODEV; + } + + pcie->freq = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_CANFREQ_REG); + pcie->freq_to_ticks_div = pcie->freq / 1000000; + if (pcie->freq_to_ticks_div == 0) + pcie->freq_to_ticks_div = 1; + + /* Turn off all loopback functionality */ + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); + return ret; +} + +static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p, + __le32 *data) +{ + struct sk_buff *skb; + struct canfd_frame *cf; + struct can_priv *priv; + struct net_device_stats *stats; + struct skb_shared_hwtstamps *shhwtstamps; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + priv = &pcie->can[ch_id]->can; + stats = &priv->dev->stats; + + if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) { + skb = alloc_canfd_skb(priv->dev, &cf); + if (!skb) { + stats->rx_dropped++; + return -ENOMEM; + } + + if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS) + cf->flags |= CANFD_BRS; + + if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI) + cf->flags |= CANFD_ESI; + } else { + skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); + if (!skb) { + stats->rx_dropped++; + return -ENOMEM; + } + } + + cf->can_id = p->header[0] & CAN_EFF_MASK; + if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE) + cf->can_id |= CAN_EFF_FLAG; + + cf->len = can_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT); + + if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) + cf->can_id |= CAN_RTR_FLAG; + else + memcpy(cf->data, data, cf->len); + + shhwtstamps = skb_hwtstamps(skb); + + shhwtstamps->hwtstamp = + ns_to_ktime(div_u64(p->timestamp * 1000, + pcie->freq_to_ticks_div)); + + stats->rx_bytes += cf->len; + stats->rx_packets++; + + return netif_rx(skb); +} + +static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can, + struct can_frame *cf, + enum can_state new_state, + enum can_state tx_state, + enum can_state rx_state) +{ + can_change_state(can->can.dev, cf, tx_state, rx_state); + + if (new_state == CAN_STATE_BUS_OFF) { + struct net_device *ndev = can->can.dev; + unsigned long irq_flags; + + spin_lock_irqsave(&can->lock, irq_flags); + netif_stop_queue(can->can.dev); + spin_unlock_irqrestore(&can->lock, irq_flags); + + /* Prevent CAN controller from auto recover from bus off */ + if (!can->can.restart_ms) { + kvaser_pciefd_start_controller_flush(can); + can_bus_off(ndev); + } + } +} + +static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p, + struct can_berr_counter *bec, + enum can_state *new_state, + enum can_state *tx_state, + enum can_state *rx_state) +{ + if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF || + p->header[0] & KVASER_PCIEFD_SPACK_IRM) + *new_state = CAN_STATE_BUS_OFF; + else if (bec->txerr >= 255 || bec->rxerr >= 255) + *new_state = CAN_STATE_BUS_OFF; + else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR) + *new_state = CAN_STATE_ERROR_PASSIVE; + else if (bec->txerr >= 128 || bec->rxerr >= 128) + *new_state = CAN_STATE_ERROR_PASSIVE; + else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR) + *new_state = CAN_STATE_ERROR_WARNING; + else if (bec->txerr >= 96 || bec->rxerr >= 96) + *new_state = CAN_STATE_ERROR_WARNING; + else + *new_state = CAN_STATE_ERROR_ACTIVE; + + *tx_state = bec->txerr >= bec->rxerr ? *new_state : 0; + *rx_state = bec->txerr <= bec->rxerr ? *new_state : 0; +} + +static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, + struct kvaser_pciefd_rx_packet *p) +{ + struct can_berr_counter bec; + enum can_state old_state, new_state, tx_state, rx_state; + struct net_device *ndev = can->can.dev; + struct sk_buff *skb; + struct can_frame *cf = NULL; + struct skb_shared_hwtstamps *shhwtstamps; + struct net_device_stats *stats = &ndev->stats; + + old_state = can->can.state; + + bec.txerr = p->header[0] & 0xff; + bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; + + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, + &rx_state); + + skb = alloc_can_err_skb(ndev, &cf); + + if (new_state != old_state) { + kvaser_pciefd_change_state(can, cf, new_state, tx_state, + rx_state); + + if (old_state == CAN_STATE_BUS_OFF && + new_state == CAN_STATE_ERROR_ACTIVE && + can->can.restart_ms) { + can->can.can_stats.restarts++; + if (skb) + cf->can_id |= CAN_ERR_RESTARTED; + } + } + + can->err_rep_cnt++; + can->can.can_stats.bus_error++; + stats->rx_errors++; + + can->bec.txerr = bec.txerr; + can->bec.rxerr = bec.rxerr; + + if (!skb) { + stats->rx_dropped++; + return -ENOMEM; + } + + shhwtstamps = skb_hwtstamps(skb); + shhwtstamps->hwtstamp = + ns_to_ktime(div_u64(p->timestamp * 1000, + can->kv_pcie->freq_to_ticks_div)); + cf->can_id |= CAN_ERR_BUSERROR; + + cf->data[6] = bec.txerr; + cf->data[7] = bec.rxerr; + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + netif_rx(skb); + return 0; +} + +static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p) +{ + struct kvaser_pciefd_can *can; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + can = pcie->can[ch_id]; + + kvaser_pciefd_rx_error_frame(can, p); + if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP) + /* Do not report more errors, until bec_poll_timer expires */ + kvaser_pciefd_disable_err_gen(can); + /* Start polling the error counters */ + mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); + return 0; +} + +static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, + struct kvaser_pciefd_rx_packet *p) +{ + struct can_berr_counter bec; + enum can_state old_state, new_state, tx_state, rx_state; + + old_state = can->can.state; + + bec.txerr = p->header[0] & 0xff; + bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; + + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, + &rx_state); + + if (new_state != old_state) { + struct net_device *ndev = can->can.dev; + struct sk_buff *skb; + struct can_frame *cf; + struct skb_shared_hwtstamps *shhwtstamps; + + skb = alloc_can_err_skb(ndev, &cf); + if (!skb) { + struct net_device_stats *stats = &ndev->stats; + + stats->rx_dropped++; + return -ENOMEM; + } + + kvaser_pciefd_change_state(can, cf, new_state, tx_state, + rx_state); + + if (old_state == CAN_STATE_BUS_OFF && + new_state == CAN_STATE_ERROR_ACTIVE && + can->can.restart_ms) { + can->can.can_stats.restarts++; + cf->can_id |= CAN_ERR_RESTARTED; + } + + shhwtstamps = skb_hwtstamps(skb); + shhwtstamps->hwtstamp = + ns_to_ktime(div_u64(p->timestamp * 1000, + can->kv_pcie->freq_to_ticks_div)); + + cf->data[6] = bec.txerr; + cf->data[7] = bec.rxerr; + + netif_rx(skb); + } + can->bec.txerr = bec.txerr; + can->bec.rxerr = bec.rxerr; + /* Check if we need to poll the error counters */ + if (bec.txerr || bec.rxerr) + mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); + + return 0; +} + +static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p) +{ + struct kvaser_pciefd_can *can; + u8 cmdseq; + u32 status; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + can = pcie->can[ch_id]; + + status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); + cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff; + + /* Reset done, start abort and flush */ + if (p->header[0] & KVASER_PCIEFD_SPACK_IRM && + p->header[0] & KVASER_PCIEFD_SPACK_RMCD && + p->header[1] & KVASER_PCIEFD_SPACK_AUTO && + cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + status & KVASER_PCIEFD_KCAN_STAT_IDLE) { + u32 cmd; + + iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, + can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + cmd = KVASER_PCIEFD_KCAN_CMD_AT; + cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; + iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + + iowrite32(KVASER_PCIEFD_KCAN_IRQ_TFD, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET && + p->header[0] & KVASER_PCIEFD_SPACK_IRM && + cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + status & KVASER_PCIEFD_KCAN_STAT_IDLE) { + /* Reset detected, send end of flush if no packet are in FIFO */ + u8 count = ioread32(can->reg_base + + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + + if (!count) + iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, + can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); + } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) && + cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) { + /* Response to status request received */ + kvaser_pciefd_handle_status_resp(can, p); + if (can->can.state != CAN_STATE_BUS_OFF && + can->can.state != CAN_STATE_ERROR_ACTIVE) { + mod_timer(&can->bec_poll_timer, + KVASER_PCIEFD_BEC_POLL_FREQ); + } + } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD && + !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) { + /* Reset to bus on detected */ + if (!completion_done(&can->start_comp)) + complete(&can->start_comp); + } + + return 0; +} + +static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p) +{ + struct kvaser_pciefd_can *can; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + can = pcie->can[ch_id]; + + /* If this is the last flushed packet, send end of flush */ + if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { + u8 count = ioread32(can->reg_base + + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + + if (count == 0) + iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, + can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); + } else { + int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; + int dlc = can_get_echo_skb(can->can.dev, echo_idx); + struct net_device_stats *stats = &can->can.dev->stats; + + stats->tx_bytes += dlc; + stats->tx_packets++; + + if (netif_queue_stopped(can->can.dev)) + netif_wake_queue(can->can.dev); + } + + return 0; +} + +static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, + struct kvaser_pciefd_rx_packet *p) +{ + struct sk_buff *skb; + struct net_device_stats *stats = &can->can.dev->stats; + struct can_frame *cf; + + skb = alloc_can_err_skb(can->can.dev, &cf); + + stats->tx_errors++; + if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) { + if (skb) + cf->can_id |= CAN_ERR_LOSTARB; + can->can.can_stats.arbitration_lost++; + } else if (skb) { + cf->can_id |= CAN_ERR_ACK; + } + + if (skb) { + cf->can_id |= CAN_ERR_BUSERROR; + stats->rx_bytes += cf->can_dlc; + stats->rx_packets++; + netif_rx(skb); + } else { + stats->rx_dropped++; + netdev_warn(can->can.dev, "No memory left for err_skb\n"); + } +} + +static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p) +{ + struct kvaser_pciefd_can *can; + bool one_shot_fail = false; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + can = pcie->can[ch_id]; + /* Ignore control packet ACK */ + if (p->header[0] & KVASER_PCIEFD_APACKET_CT) + return 0; + + if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) { + kvaser_pciefd_handle_nack_packet(can, p); + one_shot_fail = true; + } + + if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { + netdev_dbg(can->can.dev, "Packet was flushed\n"); + } else { + int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; + int dlc = can_get_echo_skb(can->can.dev, echo_idx); + u8 count = ioread32(can->reg_base + + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + + if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT && + netif_queue_stopped(can->can.dev)) + netif_wake_queue(can->can.dev); + + if (!one_shot_fail) { + struct net_device_stats *stats = &can->can.dev->stats; + + stats->tx_bytes += dlc; + stats->tx_packets++; + } + } + + return 0; +} + +static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie, + struct kvaser_pciefd_rx_packet *p) +{ + struct kvaser_pciefd_can *can; + u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + + if (ch_id >= pcie->nr_channels) + return -EIO; + + can = pcie->can[ch_id]; + + if (!completion_done(&can->flush_comp)) + complete(&can->flush_comp); + + return 0; +} + +static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, + int dma_buf) +{ + __le32 *buffer = pcie->dma_data[dma_buf]; + __le64 timestamp; + struct kvaser_pciefd_rx_packet packet; + struct kvaser_pciefd_rx_packet *p = &packet; + u8 type; + int pos = *start_pos; + int size; + int ret = 0; + + size = le32_to_cpu(buffer[pos++]); + if (!size) { + *start_pos = 0; + return 0; + } + + p->header[0] = le32_to_cpu(buffer[pos++]); + p->header[1] = le32_to_cpu(buffer[pos++]); + + /* Read 64-bit timestamp */ + memcpy(×tamp, &buffer[pos], sizeof(__le64)); + pos += 2; + p->timestamp = le64_to_cpu(timestamp); + + type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf; + switch (type) { + case KVASER_PCIEFD_PACK_TYPE_DATA: + ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]); + if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) { + u8 data_len; + + data_len = can_dlc2len(p->header[1] >> + KVASER_PCIEFD_RPACKET_DLC_SHIFT); + pos += DIV_ROUND_UP(data_len, 4); + } + break; + + case KVASER_PCIEFD_PACK_TYPE_ACK: + ret = kvaser_pciefd_handle_ack_packet(pcie, p); + break; + + case KVASER_PCIEFD_PACK_TYPE_STATUS: + ret = kvaser_pciefd_handle_status_packet(pcie, p); + break; + + case KVASER_PCIEFD_PACK_TYPE_ERROR: + ret = kvaser_pciefd_handle_error_packet(pcie, p); + break; + + case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: + ret = kvaser_pciefd_handle_eack_packet(pcie, p); + break; + + case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK: + ret = kvaser_pciefd_handle_eflush_packet(pcie, p); + break; + + case KVASER_PCIEFD_PACK_TYPE_ACK_DATA: + case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD: + case KVASER_PCIEFD_PACK_TYPE_TXRQ: + dev_info(&pcie->pci->dev, + "Received unexpected packet type 0x%08X\n", type); + break; + + default: + dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type); + ret = -EIO; + break; + } + + if (ret) + return ret; + + /* Position does not point to the end of the package, + * corrupted packet size? + */ + if ((*start_pos + size) != pos) + return -EIO; + + /* Point to the next packet header, if any */ + *start_pos = pos; + + return ret; +} + +static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) +{ + int pos = 0; + int res = 0; + + do { + res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf); + } while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE); + + return res; +} + +static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) +{ + u32 irq; + + irq = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); + if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) { + kvaser_pciefd_read_buffer(pcie, 0); + /* Reset DMA buffer 0 */ + iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, + pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + } + + if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) { + kvaser_pciefd_read_buffer(pcie, 1); + /* Reset DMA buffer 1 */ + iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, + pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + } + + if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 || + irq & KVASER_PCIEFD_SRB_IRQ_DOF1 || + irq & KVASER_PCIEFD_SRB_IRQ_DUF0 || + irq & KVASER_PCIEFD_SRB_IRQ_DUF1) + dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); + + iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); + return 0; +} + +static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) +{ + u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + + if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF) + netdev_err(can->can.dev, "Tx FIFO overflow\n"); + + if (irq & KVASER_PCIEFD_KCAN_IRQ_TFD) { + u8 count = ioread32(can->reg_base + + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + + if (count == 0) + iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, + can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); + } + + if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP) + netdev_err(can->can.dev, + "Fail to change bittiming, when not in reset mode\n"); + + if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC) + netdev_err(can->can.dev, "CAN FD frame in CAN mode\n"); + + if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF) + netdev_err(can->can.dev, "Rx FIFO overflow\n"); + + iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + return 0; +} + +static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) +{ + struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev; + u32 board_irq; + int i; + + board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); + + if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK)) + return IRQ_NONE; + + if (board_irq & KVASER_PCIEFD_IRQ_SRB) + kvaser_pciefd_receive_irq(pcie); + + for (i = 0; i < pcie->nr_channels; i++) { + if (!pcie->can[i]) { + dev_err(&pcie->pci->dev, + "IRQ mask points to unallocated controller\n"); + break; + } + + /* Check that mask matches channel (i) IRQ mask */ + if (board_irq & (1 << i)) + kvaser_pciefd_transmit_irq(pcie->can[i]); + } + + iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG); + return IRQ_HANDLED; +} + +static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie) +{ + int i; + struct kvaser_pciefd_can *can; + + for (i = 0; i < pcie->nr_channels; i++) { + can = pcie->can[i]; + if (can) { + iowrite32(0, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + kvaser_pciefd_pwm_stop(can); + free_candev(can->can.dev); + } + } +} + +static int kvaser_pciefd_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int err; + struct kvaser_pciefd *pcie; + + pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + + pci_set_drvdata(pdev, pcie); + pcie->pci = pdev; + + err = pci_enable_device(pdev); + if (err) + return err; + + err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME); + if (err) + goto err_disable_pci; + + pcie->reg_base = pci_iomap(pdev, 0, 0); + if (!pcie->reg_base) { + err = -ENOMEM; + goto err_release_regions; + } + + err = kvaser_pciefd_setup_board(pcie); + if (err) + goto err_pci_iounmap; + + err = kvaser_pciefd_setup_dma(pcie); + if (err) + goto err_pci_iounmap; + + pci_set_master(pdev); + + err = kvaser_pciefd_setup_can_ctrls(pcie); + if (err) + goto err_teardown_can_ctrls; + + iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1, + pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); + + iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 | + KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 | + KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, + pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); + + /* Reset IRQ handling, expected to be off before */ + iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, + pcie->reg_base + KVASER_PCIEFD_IRQ_REG); + iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, + pcie->reg_base + KVASER_PCIEFD_IEN_REG); + + /* Ready the DMA buffers */ + iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, + pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, + pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + + err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler, + IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie); + if (err) + goto err_teardown_can_ctrls; + + err = kvaser_pciefd_reg_candev(pcie); + if (err) + goto err_free_irq; + + return 0; + +err_free_irq: + free_irq(pcie->pci->irq, pcie); + +err_teardown_can_ctrls: + kvaser_pciefd_teardown_can_ctrls(pcie); + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + pci_clear_master(pdev); + +err_pci_iounmap: + pci_iounmap(pdev, pcie->reg_base); + +err_release_regions: + pci_release_regions(pdev); + +err_disable_pci: + pci_disable_device(pdev); + + return err; +} + +static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) +{ + struct kvaser_pciefd_can *can; + int i; + + for (i = 0; i < pcie->nr_channels; i++) { + can = pcie->can[i]; + if (can) { + iowrite32(0, + can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + unregister_candev(can->can.dev); + del_timer(&can->bec_poll_timer); + kvaser_pciefd_pwm_stop(can); + free_candev(can->can.dev); + } + } +} + +static void kvaser_pciefd_remove(struct pci_dev *pdev) +{ + struct kvaser_pciefd *pcie = pci_get_drvdata(pdev); + + kvaser_pciefd_remove_all_ctrls(pcie); + + /* Turn off IRQ generation */ + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, + pcie->reg_base + KVASER_PCIEFD_IRQ_REG); + iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); + + free_irq(pcie->pci->irq, pcie); + + pci_clear_master(pdev); + pci_iounmap(pdev, pcie->reg_base); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static struct pci_driver kvaser_pciefd = { + .name = KVASER_PCIEFD_DRV_NAME, + .id_table = kvaser_pciefd_id_table, + .probe = kvaser_pciefd_probe, + .remove = kvaser_pciefd_remove, +}; + +module_pci_driver(kvaser_pciefd) -- GitLab From b07fbf239738f8ab380af15e1b0e1d27552695a9 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 29 Jan 2019 12:06:12 -0600 Subject: [PATCH 0419/7155] can: mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/net/can/peak_canfd/peak_pciefd_main.c:668:3: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/can/spi/mcp251x.c:875:7: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/can/usb/peak_usb/pcan_usb.c:422:6: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/can/at91_can.c:895:6: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/can/at91_can.c:953:15: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/can/usb/peak_usb/pcan_usb.c: In function ‘pcan_usb_decode_error’: drivers/net/can/usb/peak_usb/pcan_usb.c:422:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (n & PCAN_USB_ERROR_BUS_LIGHT) { ^ drivers/net/can/usb/peak_usb/pcan_usb.c:428:2: note: here case CAN_STATE_ERROR_WARNING: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Notice that in some cases spelling mistakes were fixed. In other cases, the /* fall through */ comment is placed at the bottom of the case statement, which is what GCC is expecting to find. Signed-off-by: Gustavo A. R. Silva Acked-by: Nicolas Ferre # for the at91_can.c Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 6 ++++-- drivers/net/can/peak_canfd/peak_pciefd_main.c | 2 +- drivers/net/can/spi/mcp251x.c | 3 ++- drivers/net/can/usb/peak_usb/pcan_usb.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 1d4075903971..c8e1a04ba384 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -898,7 +898,8 @@ static void at91_irq_err_state(struct net_device *dev, CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } - case CAN_STATE_ERROR_WARNING: /* fallthrough */ + /* fall through */ + case CAN_STATE_ERROR_WARNING: /* * from: ERROR_ACTIVE, ERROR_WARNING * to : ERROR_PASSIVE, BUS_OFF @@ -947,7 +948,8 @@ static void at91_irq_err_state(struct net_device *dev, netdev_dbg(dev, "Error Active\n"); cf->can_id |= CAN_ERR_PROT; cf->data[2] = CAN_ERR_PROT_ACTIVE; - case CAN_STATE_ERROR_WARNING: /* fallthrough */ + /* fall through */ + case CAN_STATE_ERROR_WARNING: reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF; reg_ier = AT91_IRQ_ERRP; break; diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c index 7f6a3b971da9..13b10cbf236a 100644 --- a/drivers/net/can/peak_canfd/peak_pciefd_main.c +++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c @@ -660,7 +660,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd) pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ, PCIEFD_REG_CAN_CLK_SEL); - /* fallthough */ + /* fall through */ case CANFD_CLK_SEL_80MHZ: priv->ucan.can.clock.freq = 80 * 1000 * 1000; break; diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 44e99e3d7134..234cf1042df6 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -860,7 +860,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) if (new_state >= CAN_STATE_ERROR_WARNING && new_state <= CAN_STATE_BUS_OFF) priv->can.can_stats.error_warning++; - case CAN_STATE_ERROR_WARNING: /* fallthrough */ + /* fall through */ + case CAN_STATE_ERROR_WARNING: if (new_state >= CAN_STATE_ERROR_PASSIVE && new_state <= CAN_STATE_BUS_OFF) priv->can.can_stats.error_passive++; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 15ce5ad1d632..617da295b6c1 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -415,7 +415,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, new_state = CAN_STATE_ERROR_WARNING; break; } - /* else: fall through */ + /* fall through */ case CAN_STATE_ERROR_WARNING: if (n & PCAN_USB_ERROR_BUS_HEAVY) { -- GitLab From 69652195b6e071d9adcd7c8129943d95813c42ea Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 9 May 2019 11:11:09 -0500 Subject: [PATCH 0420/7155] can: m_can: Fix checkpatch issues on existing code Fix checkpatch issues found during the m_can framework creation, before framework creation in the following patches. Fix these 4 check issues: CHECK: Unnecessary parentheses around 'cdev->can.state != CAN_STATE_ERROR_WARNING' if (psr & PSR_EW && (cdev->can.state != CAN_STATE_ERROR_WARNING)) { CHECK: Unnecessary parentheses around 'cdev->can.state != CAN_STATE_ERROR_PASSIVE' if ((psr & PSR_EP) && (cdev->can.state != CAN_STATE_ERROR_PASSIVE)) { CHECK: Unnecessary parentheses around 'cdev->can.state != CAN_STATE_BUS_OFF' if ((psr & PSR_BO) && (cdev->can.state != CAN_STATE_BUS_OFF)) { CHECK: Unnecessary parentheses around 'priv->version <= 31' if ((priv->version <= 31) && (irqstatus & IR_MRAF) && (m_can_read(priv, M_CAN_ECR) & ECR_RP)) { Signed-off-by: Dan Murphy Acked-by: Faiz Abbas Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/m_can.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index deb274a19ba0..d387d6d0a591 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -744,22 +744,19 @@ static int m_can_handle_state_errors(struct net_device *dev, u32 psr) struct m_can_priv *priv = netdev_priv(dev); int work_done = 0; - if ((psr & PSR_EW) && - (priv->can.state != CAN_STATE_ERROR_WARNING)) { + if (psr & PSR_EW && priv->can.state != CAN_STATE_ERROR_WARNING) { netdev_dbg(dev, "entered error warning state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_ERROR_WARNING); } - if ((psr & PSR_EP) && - (priv->can.state != CAN_STATE_ERROR_PASSIVE)) { + if (psr & PSR_EP && priv->can.state != CAN_STATE_ERROR_PASSIVE) { netdev_dbg(dev, "entered error passive state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_ERROR_PASSIVE); } - if ((psr & PSR_BO) && - (priv->can.state != CAN_STATE_BUS_OFF)) { + if (psr & PSR_BO && priv->can.state != CAN_STATE_BUS_OFF) { netdev_dbg(dev, "entered error bus off state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_BUS_OFF); @@ -832,8 +829,8 @@ static int m_can_poll(struct napi_struct *napi, int quota) * whether MCAN_ECR.RP = ’1’ and MCAN_ECR.REC = 127. * In this case, reset MCAN_IR.MRAF. No further action is required. */ - if ((priv->version <= 31) && (irqstatus & IR_MRAF) && - (m_can_read(priv, M_CAN_ECR) & ECR_RP)) { + if (priv->version <= 31 && irqstatus & IR_MRAF && + m_can_read(priv, M_CAN_ECR) & ECR_RP) { struct can_berr_counter bec; __m_can_get_berr_counter(dev, &bec); -- GitLab From f524f829b75a7d934f56f63f2ed4d42f4e1d06d9 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 9 May 2019 11:11:05 -0500 Subject: [PATCH 0421/7155] can: m_can: Create a m_can platform framework Create a m_can platform framework that peripheral devices can register to and use common code and register sets. The peripheral devices may provide read/write and configuration support of the IP. Acked-by: Wolfgang Grandegger Signed-off-by: Dan Murphy Acked-by: Faiz Abbas Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/Kconfig | 13 +- drivers/net/can/m_can/Makefile | 1 + drivers/net/can/m_can/m_can.c | 723 +++++++++++++------------ drivers/net/can/m_can/m_can.h | 110 ++++ drivers/net/can/m_can/m_can_platform.c | 202 +++++++ 5 files changed, 704 insertions(+), 345 deletions(-) create mode 100644 drivers/net/can/m_can/m_can.h create mode 100644 drivers/net/can/m_can/m_can_platform.c diff --git a/drivers/net/can/m_can/Kconfig b/drivers/net/can/m_can/Kconfig index ec4b2e117f66..306c75dc7913 100644 --- a/drivers/net/can/m_can/Kconfig +++ b/drivers/net/can/m_can/Kconfig @@ -1,6 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only config CAN_M_CAN + tristate "Bosch M_CAN support" + ---help--- + Say Y here if you want support for Bosch M_CAN controller framework. + This is common support for devices that embed the Bosch M_CAN IP. + +config CAN_M_CAN_PLATFORM + tristate "Bosch M_CAN support for io-mapped devices" depends on HAS_IOMEM - tristate "Bosch M_CAN devices" + depends on CAN_M_CAN ---help--- - Say Y here if you want to support for Bosch M_CAN controller. + Say Y here if you want support for IO Mapped Bosch M_CAN controller. + This support is for devices that have the Bosch M_CAN controller + IP embedded into the device and the IP is IO Mapped to the processor. diff --git a/drivers/net/can/m_can/Makefile b/drivers/net/can/m_can/Makefile index 599ae69cb4a1..ac568be3de98 100644 --- a/drivers/net/can/m_can/Makefile +++ b/drivers/net/can/m_can/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_CAN_M_CAN) += m_can.o +obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index d387d6d0a591..4ad8d97fa8e1 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1,20 +1,14 @@ -/* - * CAN bus driver for Bosch M_CAN controller - * - * Copyright (C) 2014 Freescale Semiconductor, Inc. - * Dong Aisheng - * - * Bosch M_CAN user manual can be obtained from: +// SPDX-License-Identifier: GPL-2.0 +// CAN bus driver for Bosch M_CAN controller +// Copyright (C) 2014 Freescale Semiconductor, Inc. +// Dong Aisheng +// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ + +/* Bosch M_CAN user manual can be obtained from: * http://www.bosch-semiconductors.de/media/pdf_1/ipmodules_1/m_can/ * mcan_users_manual_v302.pdf - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ -#include -#include #include #include #include @@ -28,11 +22,7 @@ #include #include -/* napi related */ -#define M_CAN_NAPI_WEIGHT 64 - -/* message ram configuration data length */ -#define MRAM_CFG_LEN 8 +#include "m_can.h" /* registers definition */ enum m_can_reg { @@ -86,28 +76,11 @@ enum m_can_reg { M_CAN_TXEFA = 0xf8, }; -/* m_can lec values */ -enum m_can_lec_type { - LEC_NO_ERROR = 0, - LEC_STUFF_ERROR, - LEC_FORM_ERROR, - LEC_ACK_ERROR, - LEC_BIT1_ERROR, - LEC_BIT0_ERROR, - LEC_CRC_ERROR, - LEC_UNUSED, -}; +/* napi related */ +#define M_CAN_NAPI_WEIGHT 64 -enum m_can_mram_cfg { - MRAM_SIDF = 0, - MRAM_XIDF, - MRAM_RXF0, - MRAM_RXF1, - MRAM_RXB, - MRAM_TXE, - MRAM_TXB, - MRAM_CFG_NUM, -}; +/* message ram configuration data length */ +#define MRAM_CFG_LEN 8 /* Core Release Register (CREL) */ #define CREL_REL_SHIFT 28 @@ -347,74 +320,69 @@ enum m_can_mram_cfg { #define TX_EVENT_MM_SHIFT TX_BUF_MM_SHIFT #define TX_EVENT_MM_MASK (0xff << TX_EVENT_MM_SHIFT) -/* address offset and element number for each FIFO/Buffer in the Message RAM */ -struct mram_cfg { - u16 off; - u8 num; -}; - -/* m_can private data structure */ -struct m_can_priv { - struct can_priv can; /* must be the first member */ - struct napi_struct napi; - struct net_device *dev; - struct device *device; - struct clk *hclk; - struct clk *cclk; - void __iomem *base; - u32 irqstatus; - int version; - - /* message ram configuration */ - void __iomem *mram_base; - struct mram_cfg mcfg[MRAM_CFG_NUM]; -}; +static inline u32 m_can_read(struct m_can_priv *priv, enum m_can_reg reg) +{ + return priv->ops->read_reg(priv, reg); +} -static inline u32 m_can_read(const struct m_can_priv *priv, enum m_can_reg reg) +static inline void m_can_write(struct m_can_priv *priv, enum m_can_reg reg, + u32 val) { - return readl(priv->base + reg); + priv->ops->write_reg(priv, reg, val); } -static inline void m_can_write(const struct m_can_priv *priv, - enum m_can_reg reg, u32 val) +static u32 m_can_fifo_read(struct m_can_priv *priv, + u32 fgi, unsigned int offset) { - writel(val, priv->base + reg); + u32 addr_offset = priv->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE + + offset; + + return priv->ops->read_fifo(priv, addr_offset); } -static inline u32 m_can_fifo_read(const struct m_can_priv *priv, - u32 fgi, unsigned int offset) +static void m_can_fifo_write(struct m_can_priv *priv, + u32 fpi, unsigned int offset, u32 val) { - return readl(priv->mram_base + priv->mcfg[MRAM_RXF0].off + - fgi * RXF0_ELEMENT_SIZE + offset); + u32 addr_offset = priv->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE + + offset; + + priv->ops->write_fifo(priv, addr_offset, val); } -static inline void m_can_fifo_write(const struct m_can_priv *priv, - u32 fpi, unsigned int offset, u32 val) +static inline void m_can_fifo_write_no_off(struct m_can_priv *priv, + u32 fpi, u32 val) { - writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off + - fpi * TXB_ELEMENT_SIZE + offset); + priv->ops->write_fifo(priv, fpi, val); } -static inline u32 m_can_txe_fifo_read(const struct m_can_priv *priv, - u32 fgi, - u32 offset) { - return readl(priv->mram_base + priv->mcfg[MRAM_TXE].off + - fgi * TXE_ELEMENT_SIZE + offset); +static u32 m_can_txe_fifo_read(struct m_can_priv *priv, u32 fgi, u32 offset) +{ + u32 addr_offset = priv->mcfg[MRAM_TXE].off + fgi * TXE_ELEMENT_SIZE + + offset; + + return priv->ops->read_fifo(priv, addr_offset); } -static inline bool m_can_tx_fifo_full(const struct m_can_priv *priv) +static inline bool m_can_tx_fifo_full(struct m_can_priv *priv) { return !!(m_can_read(priv, M_CAN_TXFQS) & TXFQS_TFQF); } -static inline void m_can_config_endisable(const struct m_can_priv *priv, - bool enable) +void m_can_config_endisable(struct m_can_priv *priv, bool enable) { u32 cccr = m_can_read(priv, M_CAN_CCCR); u32 timeout = 10; u32 val = 0; + /* Clear the Clock stop request if it was set */ + if (cccr & CCCR_CSR) + cccr &= ~CCCR_CSR; + if (enable) { + /* Clear the Clock stop request if it was set */ + if (cccr & CCCR_CSR) + cccr &= ~CCCR_CSR; + /* enable m_can configuration */ m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT); udelay(5); @@ -430,7 +398,7 @@ static inline void m_can_config_endisable(const struct m_can_priv *priv, while ((m_can_read(priv, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) { if (timeout == 0) { - netdev_warn(priv->dev, "Failed to init module\n"); + netdev_warn(priv->net, "Failed to init module\n"); return; } timeout--; @@ -438,17 +406,34 @@ static inline void m_can_config_endisable(const struct m_can_priv *priv, } } -static inline void m_can_enable_all_interrupts(const struct m_can_priv *priv) +static inline void m_can_enable_all_interrupts(struct m_can_priv *priv) { /* Only interrupt line 0 is used in this driver */ m_can_write(priv, M_CAN_ILE, ILE_EINT0); } -static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv) +static inline void m_can_disable_all_interrupts(struct m_can_priv *priv) { m_can_write(priv, M_CAN_ILE, 0x0); } +static void m_can_clean(struct net_device *net) +{ + struct m_can_priv *priv = netdev_priv(net); + + if (priv->tx_skb) { + int putidx = 0; + + net->stats.tx_errors++; + if (priv->version > 30) + putidx = ((m_can_read(priv, M_CAN_TXFQS) & + TXFQS_TFQPI_MASK) >> TXFQS_TFQPI_SHIFT); + + can_free_echo_skb(priv->net, putidx); + priv->tx_skb = NULL; + } +} + static void m_can_read_fifo(struct net_device *dev, u32 rxfs) { struct net_device_stats *stats = &dev->stats; @@ -633,9 +618,12 @@ static int m_can_clk_start(struct m_can_priv *priv) { int err; - err = pm_runtime_get_sync(priv->device); + if (priv->pm_clock_support == 0) + return 0; + + err = pm_runtime_get_sync(priv->dev); if (err < 0) { - pm_runtime_put_noidle(priv->device); + pm_runtime_put_noidle(priv->dev); return err; } @@ -644,7 +632,8 @@ static int m_can_clk_start(struct m_can_priv *priv) static void m_can_clk_stop(struct m_can_priv *priv) { - pm_runtime_put_sync(priv->device); + if (priv->pm_clock_support) + pm_runtime_put_sync(priv->dev); } static int m_can_get_berr_counter(const struct net_device *dev, @@ -808,9 +797,8 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, return work_done; } -static int m_can_poll(struct napi_struct *napi, int quota) +static int m_can_rx_handler(struct net_device *dev, int quota) { - struct net_device *dev = napi->dev; struct m_can_priv *priv = netdev_priv(dev); int work_done = 0; u32 irqstatus, psr; @@ -849,13 +837,33 @@ static int m_can_poll(struct napi_struct *napi, int quota) if (irqstatus & IR_RF0N) work_done += m_can_do_rx_poll(dev, (quota - work_done)); +end: + return work_done; +} +static int m_can_rx_peripheral(struct net_device *dev) +{ + struct m_can_priv *priv = netdev_priv(dev); + + m_can_rx_handler(dev, 1); + + m_can_enable_all_interrupts(priv); + + return 0; +} + +static int m_can_poll(struct napi_struct *napi, int quota) +{ + struct net_device *dev = napi->dev; + struct m_can_priv *priv = netdev_priv(dev); + int work_done; + + work_done = m_can_rx_handler(dev, quota); if (work_done < quota) { napi_complete_done(napi, work_done); m_can_enable_all_interrupts(priv); } -end: return work_done; } @@ -912,6 +920,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) if (ir & IR_ALL_INT) m_can_write(priv, M_CAN_IR, ir); + if (priv->ops->clear_interrupts) + priv->ops->clear_interrupts(priv); + /* schedule NAPI in case of * - rx IRQ * - state change IRQ @@ -920,7 +931,10 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) if ((ir & IR_RF0N) || (ir & IR_ERR_ALL_30X)) { priv->irqstatus = ir; m_can_disable_all_interrupts(priv); - napi_schedule(&priv->napi); + if (!priv->is_peripheral) + napi_schedule(&priv->napi); + else + m_can_rx_peripheral(dev); } if (priv->version == 30) { @@ -1173,6 +1187,9 @@ static void m_can_chip_config(struct net_device *dev) m_can_set_bittiming(dev); m_can_config_endisable(priv, false); + + if (priv->ops->init) + priv->ops->init(priv); } static void m_can_start(struct net_device *dev) @@ -1191,6 +1208,7 @@ static int m_can_set_mode(struct net_device *dev, enum can_mode mode) { switch (mode) { case CAN_MODE_START: + m_can_clean(dev); m_can_start(dev); netif_wake_queue(dev); break; @@ -1206,20 +1224,17 @@ static int m_can_set_mode(struct net_device *dev, enum can_mode mode) * else it returns the release and step coded as: * return value = 10 * + 1 * */ -static int m_can_check_core_release(void __iomem *m_can_base) +static int m_can_check_core_release(struct m_can_priv *priv) { u32 crel_reg; u8 rel; u8 step; int res; - struct m_can_priv temp_priv = { - .base = m_can_base - }; /* Read Core Release Version and split into version number * Example: Version 3.2.1 => rel = 3; step = 2; substep = 1; */ - crel_reg = m_can_read(&temp_priv, M_CAN_CREL); + crel_reg = m_can_read(priv, M_CAN_CREL); rel = (u8)((crel_reg & CREL_REL_MASK) >> CREL_REL_SHIFT); step = (u8)((crel_reg & CREL_STEP_MASK) >> CREL_STEP_SHIFT); @@ -1237,18 +1252,26 @@ static int m_can_check_core_release(void __iomem *m_can_base) /* Selectable Non ISO support only in version 3.2.x * This function checks if the bit is writable. */ -static bool m_can_niso_supported(const struct m_can_priv *priv) +static bool m_can_niso_supported(struct m_can_priv *priv) { - u32 cccr_reg, cccr_poll; - int niso_timeout; + u32 cccr_reg, cccr_poll = 0; + int niso_timeout = -ETIMEDOUT; + int i; m_can_config_endisable(priv, true); cccr_reg = m_can_read(priv, M_CAN_CCCR); cccr_reg |= CCCR_NISO; m_can_write(priv, M_CAN_CCCR, cccr_reg); - niso_timeout = readl_poll_timeout((priv->base + M_CAN_CCCR), cccr_poll, - (cccr_poll == cccr_reg), 0, 10); + for (i = 0; i <= 10; i++) { + cccr_poll = m_can_read(priv, M_CAN_CCCR); + if (cccr_poll == cccr_reg) { + niso_timeout = 0; + break; + } + + usleep_range(1, 5); + } /* Clear NISO */ cccr_reg &= ~(CCCR_NISO); @@ -1260,107 +1283,79 @@ static bool m_can_niso_supported(const struct m_can_priv *priv) return !niso_timeout; } -static int m_can_dev_setup(struct platform_device *pdev, struct net_device *dev, - void __iomem *addr) +static int m_can_dev_setup(struct m_can_priv *m_can_dev) { - struct m_can_priv *priv; + struct net_device *dev = m_can_dev->net; int m_can_version; - m_can_version = m_can_check_core_release(addr); + m_can_version = m_can_check_core_release(m_can_dev); /* return if unsupported version */ if (!m_can_version) { - dev_err(&pdev->dev, "Unsupported version number: %2d", + dev_err(m_can_dev->dev, "Unsupported version number: %2d", m_can_version); return -EINVAL; } - priv = netdev_priv(dev); - netif_napi_add(dev, &priv->napi, m_can_poll, M_CAN_NAPI_WEIGHT); + if (!m_can_dev->is_peripheral) + netif_napi_add(dev, &m_can_dev->napi, + m_can_poll, M_CAN_NAPI_WEIGHT); /* Shared properties of all M_CAN versions */ - priv->version = m_can_version; - priv->dev = dev; - priv->base = addr; - priv->can.do_set_mode = m_can_set_mode; - priv->can.do_get_berr_counter = m_can_get_berr_counter; + m_can_dev->version = m_can_version; + m_can_dev->can.do_set_mode = m_can_set_mode; + m_can_dev->can.do_get_berr_counter = m_can_get_berr_counter; /* Set M_CAN supported operations */ - priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | + m_can_dev->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_FD; /* Set properties depending on M_CAN version */ - switch (priv->version) { + switch (m_can_dev->version) { case 30: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - priv->can.bittiming_const = &m_can_bittiming_const_30X; - priv->can.data_bittiming_const = - &m_can_data_bittiming_const_30X; + m_can_dev->can.bittiming_const = m_can_dev->bit_timing ? + m_can_dev->bit_timing : &m_can_bittiming_const_30X; + + m_can_dev->can.data_bittiming_const = m_can_dev->data_timing ? + m_can_dev->data_timing : + &m_can_data_bittiming_const_30X; break; case 31: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - priv->can.bittiming_const = &m_can_bittiming_const_31X; - priv->can.data_bittiming_const = - &m_can_data_bittiming_const_31X; + m_can_dev->can.bittiming_const = m_can_dev->bit_timing ? + m_can_dev->bit_timing : &m_can_bittiming_const_31X; + + m_can_dev->can.data_bittiming_const = m_can_dev->data_timing ? + m_can_dev->data_timing : + &m_can_data_bittiming_const_31X; break; case 32: - priv->can.bittiming_const = &m_can_bittiming_const_31X; - priv->can.data_bittiming_const = - &m_can_data_bittiming_const_31X; - priv->can.ctrlmode_supported |= (m_can_niso_supported(priv) + m_can_dev->can.bittiming_const = m_can_dev->bit_timing ? + m_can_dev->bit_timing : &m_can_bittiming_const_31X; + + m_can_dev->can.data_bittiming_const = m_can_dev->data_timing ? + m_can_dev->data_timing : + &m_can_data_bittiming_const_31X; + + m_can_dev->can.ctrlmode_supported |= + (m_can_niso_supported(m_can_dev) ? CAN_CTRLMODE_FD_NON_ISO : 0); break; default: - dev_err(&pdev->dev, "Unsupported version number: %2d", - priv->version); + dev_err(m_can_dev->dev, "Unsupported version number: %2d", + m_can_dev->version); return -EINVAL; } - return 0; -} - -static int m_can_open(struct net_device *dev) -{ - struct m_can_priv *priv = netdev_priv(dev); - int err; - - err = m_can_clk_start(priv); - if (err) - return err; - - /* open the can device */ - err = open_candev(dev); - if (err) { - netdev_err(dev, "failed to open can device\n"); - goto exit_disable_clks; - } - - /* register interrupt handler */ - err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name, - dev); - if (err < 0) { - netdev_err(dev, "failed to request interrupt\n"); - goto exit_irq_fail; - } - - /* start the m_can controller */ - m_can_start(dev); - - can_led_event(dev, CAN_LED_EVENT_OPEN); - napi_enable(&priv->napi); - netif_start_queue(dev); + if (m_can_dev->ops->init) + m_can_dev->ops->init(m_can_dev); return 0; - -exit_irq_fail: - close_candev(dev); -exit_disable_clks: - m_can_clk_stop(priv); - return err; } static void m_can_stop(struct net_device *dev) @@ -1379,10 +1374,18 @@ static int m_can_close(struct net_device *dev) struct m_can_priv *priv = netdev_priv(dev); netif_stop_queue(dev); - napi_disable(&priv->napi); + if (!priv->is_peripheral) + napi_disable(&priv->napi); m_can_stop(dev); m_can_clk_stop(priv); free_irq(dev->irq, dev); + + if (priv->is_peripheral) { + priv->tx_skb = NULL; + destroy_workqueue(priv->tx_wq); + priv->tx_wq = NULL; + } + close_candev(dev); can_led_event(dev, CAN_LED_EVENT_STOP); @@ -1403,18 +1406,15 @@ static int m_can_next_echo_skb_occupied(struct net_device *dev, int putidx) return !!priv->can.echo_skb[next_idx]; } -static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, - struct net_device *dev) +static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) { - struct m_can_priv *priv = netdev_priv(dev); - struct canfd_frame *cf = (struct canfd_frame *)skb->data; + struct canfd_frame *cf = (struct canfd_frame *)priv->tx_skb->data; + struct net_device *dev = priv->net; + struct sk_buff *skb = priv->tx_skb; u32 id, cccr, fdflags; int i; int putidx; - if (can_dropped_invalid_skb(dev, skb)) - return NETDEV_TX_OK; - /* Generate ID field for TX buffer Element */ /* Common to all supported M_CAN versions */ if (cf->can_id & CAN_EFF_FLAG) { @@ -1469,7 +1469,13 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, netif_stop_queue(dev); netdev_warn(dev, "TX queue active although FIFO is full."); - return NETDEV_TX_BUSY; + if (priv->is_peripheral) { + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } else { + return NETDEV_TX_BUSY; + } } /* get put index for frame */ @@ -1510,14 +1516,119 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, m_can_write(priv, M_CAN_TXBAR, (1 << putidx)); /* stop network queue if fifo full */ - if (m_can_tx_fifo_full(priv) || - m_can_next_echo_skb_occupied(dev, putidx)) - netif_stop_queue(dev); + if (m_can_tx_fifo_full(priv) || + m_can_next_echo_skb_occupied(dev, putidx)) + netif_stop_queue(dev); } return NETDEV_TX_OK; } +static void m_can_tx_work_queue(struct work_struct *ws) +{ + struct m_can_priv *priv = container_of(ws, struct m_can_priv, + tx_work); + m_can_tx_handler(priv); + priv->tx_skb = NULL; +} + +static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct m_can_priv *priv = netdev_priv(dev); + + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + + if (priv->is_peripheral) { + if (priv->tx_skb) { + netdev_err(dev, "hard_xmit called while tx busy\n"); + return NETDEV_TX_BUSY; + } + + if (priv->can.state == CAN_STATE_BUS_OFF) { + m_can_clean(dev); + } else { + /* Need to stop the queue to avoid numerous requests + * from being sent. Suggested improvement is to create + * a queueing mechanism that will queue the skbs and + * process them in order. + */ + priv->tx_skb = skb; + netif_stop_queue(priv->net); + queue_work(priv->tx_wq, &priv->tx_work); + } + } else { + priv->tx_skb = skb; + return m_can_tx_handler(priv); + } + + return NETDEV_TX_OK; +} + +static int m_can_open(struct net_device *dev) +{ + struct m_can_priv *priv = netdev_priv(dev); + int err; + + err = m_can_clk_start(priv); + if (err) + return err; + + /* open the can device */ + err = open_candev(dev); + if (err) { + netdev_err(dev, "failed to open can device\n"); + goto exit_disable_clks; + } + + /* register interrupt handler */ + if (priv->is_peripheral) { + priv->tx_skb = NULL; + priv->tx_wq = alloc_workqueue("mcan_wq", + WQ_FREEZABLE | WQ_MEM_RECLAIM, 0); + if (!priv->tx_wq) { + err = -ENOMEM; + goto out_wq_fail; + } + + INIT_WORK(&priv->tx_work, m_can_tx_work_queue); + + err = request_threaded_irq(dev->irq, NULL, m_can_isr, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + dev->name, dev); + } else { + err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name, + dev); + } + + if (err < 0) { + netdev_err(dev, "failed to request interrupt\n"); + goto exit_irq_fail; + } + + /* start the m_can controller */ + m_can_start(dev); + + can_led_event(dev, CAN_LED_EVENT_OPEN); + + if (!priv->is_peripheral) + napi_enable(&priv->napi); + + netif_start_queue(dev); + + return 0; + +exit_irq_fail: + if (priv->is_peripheral) + destroy_workqueue(priv->tx_wq); +out_wq_fail: + close_candev(dev); +exit_disable_clks: + m_can_clk_stop(priv); + return err; +} + static const struct net_device_ops m_can_netdev_ops = { .ndo_open = m_can_open, .ndo_stop = m_can_close, @@ -1533,20 +1644,6 @@ static int register_m_can_dev(struct net_device *dev) return register_candev(dev); } -static void m_can_init_ram(struct m_can_priv *priv) -{ - int end, i, start; - - /* initialize the entire Message RAM in use to avoid possible - * ECC/parity checksum errors when reading an uninitialized buffer - */ - start = priv->mcfg[MRAM_SIDF].off; - end = priv->mcfg[MRAM_TXB].off + - priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; - for (i = start; i < end; i += 4) - writel(0x0, priv->mram_base + i); -} - static void m_can_of_parse_mram(struct m_can_priv *priv, const u32 *mram_config_vals) { @@ -1574,9 +1671,8 @@ static void m_can_of_parse_mram(struct m_can_priv *priv, priv->mcfg[MRAM_TXB].num = mram_config_vals[7] & (TXBC_NDTB_MASK >> TXBC_NDTB_SHIFT); - dev_dbg(priv->device, - "mram_base %p sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d rxb 0x%x %d txe 0x%x %d txb 0x%x %d\n", - priv->mram_base, + dev_dbg(priv->dev, + "sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d rxb 0x%x %d txe 0x%x %d txb 0x%x %d\n", priv->mcfg[MRAM_SIDF].off, priv->mcfg[MRAM_SIDF].num, priv->mcfg[MRAM_XIDF].off, priv->mcfg[MRAM_XIDF].num, priv->mcfg[MRAM_RXF0].off, priv->mcfg[MRAM_RXF0].num, @@ -1584,63 +1680,55 @@ static void m_can_of_parse_mram(struct m_can_priv *priv, priv->mcfg[MRAM_RXB].off, priv->mcfg[MRAM_RXB].num, priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); - - m_can_init_ram(priv); } -static int m_can_plat_probe(struct platform_device *pdev) +void m_can_init_ram(struct m_can_priv *priv) { - struct net_device *dev; - struct m_can_priv *priv; - struct resource *res; - void __iomem *addr; - void __iomem *mram_addr; - struct clk *hclk, *cclk; - int irq, ret; - struct device_node *np; - u32 mram_config_vals[MRAM_CFG_LEN]; - u32 tx_fifo_size; - - np = pdev->dev.of_node; + int end, i, start; - hclk = devm_clk_get(&pdev->dev, "hclk"); - cclk = devm_clk_get(&pdev->dev, "cclk"); + /* initialize the entire Message RAM in use to avoid possible + * ECC/parity checksum errors when reading an uninitialized buffer + */ + start = priv->mcfg[MRAM_SIDF].off; + end = priv->mcfg[MRAM_TXB].off + + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; - if (IS_ERR(hclk) || IS_ERR(cclk)) { - dev_err(&pdev->dev, "no clock found\n"); - ret = -ENODEV; - goto failed_ret; - } + for (i = start; i < end; i += 4) + m_can_fifo_write_no_off(priv, i, 0x0); +} +EXPORT_SYMBOL_GPL(m_can_init_ram); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); - addr = devm_ioremap_resource(&pdev->dev, res); - irq = platform_get_irq_byname(pdev, "int0"); +int m_can_class_get_clocks(struct m_can_priv *m_can_dev) +{ + int ret = 0; - if (IS_ERR(addr) || irq < 0) { - ret = -EINVAL; - goto failed_ret; - } + m_can_dev->hclk = devm_clk_get(m_can_dev->dev, "hclk"); + m_can_dev->cclk = devm_clk_get(m_can_dev->dev, "cclk"); - /* message ram could be shared */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); - if (!res) { + if (IS_ERR(m_can_dev->cclk)) { + dev_err(m_can_dev->dev, "no clock found\n"); ret = -ENODEV; - goto failed_ret; } - mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!mram_addr) { - ret = -ENOMEM; - goto failed_ret; - } + return ret; +} +EXPORT_SYMBOL_GPL(m_can_class_get_clocks); - /* get message ram configuration */ - ret = of_property_read_u32_array(np, "bosch,mram-cfg", - mram_config_vals, - sizeof(mram_config_vals) / 4); +struct m_can_priv *m_can_class_allocate_dev(struct device *dev) +{ + struct m_can_priv *class_dev = NULL; + u32 mram_config_vals[MRAM_CFG_LEN]; + struct net_device *net_dev; + u32 tx_fifo_size; + int ret; + + ret = fwnode_property_read_u32_array(dev_fwnode(dev), + "bosch,mram-cfg", + mram_config_vals, + sizeof(mram_config_vals) / 4); if (ret) { - dev_err(&pdev->dev, "Could not get Message RAM configuration."); - goto failed_ret; + dev_err(dev, "Could not get Message RAM configuration."); + goto out; } /* Get TX FIFO size @@ -1649,66 +1737,74 @@ static int m_can_plat_probe(struct platform_device *pdev) tx_fifo_size = mram_config_vals[7]; /* allocate the m_can device */ - dev = alloc_candev(sizeof(*priv), tx_fifo_size); - if (!dev) { - ret = -ENOMEM; - goto failed_ret; + net_dev = alloc_candev(sizeof(*class_dev), tx_fifo_size); + if (!net_dev) { + dev_err(dev, "Failed to allocate CAN device"); + goto out; } - priv = netdev_priv(dev); - dev->irq = irq; - priv->device = &pdev->dev; - priv->hclk = hclk; - priv->cclk = cclk; - priv->can.clock.freq = clk_get_rate(cclk); - priv->mram_base = mram_addr; + class_dev = netdev_priv(net_dev); + if (!class_dev) { + dev_err(dev, "Failed to init netdev private"); + goto out; + } - platform_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); + class_dev->net = net_dev; + class_dev->dev = dev; + SET_NETDEV_DEV(net_dev, dev); - /* Enable clocks. Necessary to read Core Release in order to determine - * M_CAN version - */ - pm_runtime_enable(&pdev->dev); - ret = m_can_clk_start(priv); - if (ret) - goto pm_runtime_fail; + m_can_of_parse_mram(class_dev, mram_config_vals); +out: + return class_dev; +} +EXPORT_SYMBOL_GPL(m_can_class_allocate_dev); + +int m_can_class_register(struct m_can_priv *m_can_dev) +{ + int ret; - ret = m_can_dev_setup(pdev, dev, addr); + if (m_can_dev->pm_clock_support) { + pm_runtime_enable(m_can_dev->dev); + ret = m_can_clk_start(m_can_dev); + if (ret) + goto pm_runtime_fail; + } + + ret = m_can_dev_setup(m_can_dev); if (ret) goto clk_disable; - ret = register_m_can_dev(dev); + ret = register_m_can_dev(m_can_dev->net); if (ret) { - dev_err(&pdev->dev, "registering %s failed (err=%d)\n", - KBUILD_MODNAME, ret); + dev_err(m_can_dev->dev, "registering %s failed (err=%d)\n", + m_can_dev->net->name, ret); goto clk_disable; } - m_can_of_parse_mram(priv, mram_config_vals); - - devm_can_led_init(dev); + devm_can_led_init(m_can_dev->net); - of_can_transceiver(dev); + of_can_transceiver(m_can_dev->net); - dev_info(&pdev->dev, "%s device registered (irq=%d, version=%d)\n", - KBUILD_MODNAME, dev->irq, priv->version); + dev_info(m_can_dev->dev, "%s device registered (irq=%d, version=%d)\n", + KBUILD_MODNAME, m_can_dev->net->irq, m_can_dev->version); /* Probe finished * Stop clocks. They will be reactivated once the M_CAN device is opened */ clk_disable: - m_can_clk_stop(priv); + m_can_clk_stop(m_can_dev); pm_runtime_fail: if (ret) { - pm_runtime_disable(&pdev->dev); - free_candev(dev); + if (m_can_dev->pm_clock_support) + pm_runtime_disable(m_can_dev->dev); + free_candev(m_can_dev->net); } -failed_ret: + return ret; } +EXPORT_SYMBOL_GPL(m_can_class_register); -static __maybe_unused int m_can_suspend(struct device *dev) +int m_can_class_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct m_can_priv *priv = netdev_priv(ndev); @@ -1726,8 +1822,9 @@ static __maybe_unused int m_can_suspend(struct device *dev) return 0; } +EXPORT_SYMBOL_GPL(m_can_class_suspend); -static __maybe_unused int m_can_resume(struct device *dev) +int m_can_class_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct m_can_priv *priv = netdev_priv(ndev); @@ -1751,79 +1848,19 @@ static __maybe_unused int m_can_resume(struct device *dev) return 0; } +EXPORT_SYMBOL_GPL(m_can_class_resume); -static void unregister_m_can_dev(struct net_device *dev) +void m_can_class_unregister(struct m_can_priv *m_can_dev) { - unregister_candev(dev); -} + unregister_candev(m_can_dev->net); -static int m_can_plat_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); + m_can_clk_stop(m_can_dev); - unregister_m_can_dev(dev); - - pm_runtime_disable(&pdev->dev); - - platform_set_drvdata(pdev, NULL); - - free_candev(dev); - - return 0; -} - -static int __maybe_unused m_can_runtime_suspend(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); - - clk_disable_unprepare(priv->cclk); - clk_disable_unprepare(priv->hclk); - - return 0; -} - -static int __maybe_unused m_can_runtime_resume(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); - int err; - - err = clk_prepare_enable(priv->hclk); - if (err) - return err; - - err = clk_prepare_enable(priv->cclk); - if (err) - clk_disable_unprepare(priv->hclk); - - return err; + free_candev(m_can_dev->net); } - -static const struct dev_pm_ops m_can_pmops = { - SET_RUNTIME_PM_OPS(m_can_runtime_suspend, - m_can_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume) -}; - -static const struct of_device_id m_can_of_table[] = { - { .compatible = "bosch,m_can", .data = NULL }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, m_can_of_table); - -static struct platform_driver m_can_plat_driver = { - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = m_can_of_table, - .pm = &m_can_pmops, - }, - .probe = m_can_plat_probe, - .remove = m_can_plat_remove, -}; - -module_platform_driver(m_can_plat_driver); +EXPORT_SYMBOL_GPL(m_can_class_unregister); MODULE_AUTHOR("Dong Aisheng "); +MODULE_AUTHOR("Dan Murphy "); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("CAN bus driver for Bosch M_CAN controller"); diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h new file mode 100644 index 000000000000..5671f5423887 --- /dev/null +++ b/drivers/net/can/m_can/m_can.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* CAN bus driver for Bosch M_CAN controller + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef _CAN_M_CAN_H_ +#define _CAN_M_CAN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* m_can lec values */ +enum m_can_lec_type { + LEC_NO_ERROR = 0, + LEC_STUFF_ERROR, + LEC_FORM_ERROR, + LEC_ACK_ERROR, + LEC_BIT1_ERROR, + LEC_BIT0_ERROR, + LEC_CRC_ERROR, + LEC_UNUSED, +}; + +enum m_can_mram_cfg { + MRAM_SIDF = 0, + MRAM_XIDF, + MRAM_RXF0, + MRAM_RXF1, + MRAM_RXB, + MRAM_TXE, + MRAM_TXB, + MRAM_CFG_NUM, +}; + +/* address offset and element number for each FIFO/Buffer in the Message RAM */ +struct mram_cfg { + u16 off; + u8 num; +}; + +struct m_can_priv; +struct m_can_ops { + /* Device specific call backs */ + int (*clear_interrupts)(struct m_can_priv *m_can_class); + u32 (*read_reg)(struct m_can_priv *m_can_class, int reg); + int (*write_reg)(struct m_can_priv *m_can_class, int reg, int val); + u32 (*read_fifo)(struct m_can_priv *m_can_class, int addr_offset); + int (*write_fifo)(struct m_can_priv *m_can_class, int addr_offset, + int val); + int (*init)(struct m_can_priv *m_can_class); +}; + +struct m_can_priv { + struct can_priv can; + struct napi_struct napi; + struct net_device *net; + struct device *dev; + struct clk *hclk; + struct clk *cclk; + + struct workqueue_struct *tx_wq; + struct work_struct tx_work; + struct sk_buff *tx_skb; + + struct can_bittiming_const *bit_timing; + struct can_bittiming_const *data_timing; + + struct m_can_ops *ops; + + void *device_data; + + int version; + int freq; + u32 irqstatus; + + int pm_clock_support; + int is_peripheral; + + struct mram_cfg mcfg[MRAM_CFG_NUM]; +}; + +struct m_can_priv *m_can_class_allocate_dev(struct device *dev); +int m_can_class_register(struct m_can_priv *m_can_dev); +void m_can_class_unregister(struct m_can_priv *m_can_dev); +int m_can_class_get_clocks(struct m_can_priv *m_can_dev); +void m_can_init_ram(struct m_can_priv *priv); +void m_can_config_endisable(struct m_can_priv *priv, bool enable); + +int m_can_class_suspend(struct device *dev); +int m_can_class_resume(struct device *dev); +#endif /* _CAN_M_H_ */ diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c new file mode 100644 index 000000000000..026053f62f77 --- /dev/null +++ b/drivers/net/can/m_can/m_can_platform.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +// IOMapped CAN bus driver for Bosch M_CAN controller +// Copyright (C) 2014 Freescale Semiconductor, Inc. +// Dong Aisheng +// +// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ + +#include + +#include "m_can.h" + +struct m_can_plat_priv { + void __iomem *base; + void __iomem *mram_base; +}; + +static u32 iomap_read_reg(struct m_can_priv *cdev, int reg) +{ + struct m_can_plat_priv *priv = + (struct m_can_plat_priv *)cdev->device_data; + + return readl(priv->base + reg); +} + +static u32 iomap_read_fifo(struct m_can_priv *cdev, int offset) +{ + struct m_can_plat_priv *priv = + (struct m_can_plat_priv *)cdev->device_data; + + return readl(priv->mram_base + offset); +} + +static int iomap_write_reg(struct m_can_priv *cdev, int reg, int val) +{ + struct m_can_plat_priv *priv = + (struct m_can_plat_priv *)cdev->device_data; + + writel(val, priv->base + reg); + + return 0; +} + +static int iomap_write_fifo(struct m_can_priv *cdev, int offset, int val) +{ + struct m_can_plat_priv *priv = + (struct m_can_plat_priv *)cdev->device_data; + + writel(val, priv->mram_base + offset); + + return 0; +} + +static struct m_can_ops m_can_plat_ops = { + .read_reg = iomap_read_reg, + .write_reg = iomap_write_reg, + .write_fifo = iomap_write_fifo, + .read_fifo = iomap_read_fifo, +}; + +static int m_can_plat_probe(struct platform_device *pdev) +{ + struct m_can_priv *mcan_class; + struct m_can_plat_priv *priv; + struct resource *res; + void __iomem *addr; + void __iomem *mram_addr; + int irq, ret = 0; + + mcan_class = m_can_class_allocate_dev(&pdev->dev); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mcan_class->device_data = priv; + + m_can_class_get_clocks(mcan_class); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); + addr = devm_ioremap_resource(&pdev->dev, res); + irq = platform_get_irq_byname(pdev, "int0"); + if (IS_ERR(addr) || irq < 0) { + ret = -EINVAL; + goto failed_ret; + } + + /* message ram could be shared */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); + if (!res) { + ret = -ENODEV; + goto failed_ret; + } + + mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!mram_addr) { + ret = -ENOMEM; + goto failed_ret; + } + + priv->base = addr; + priv->mram_base = mram_addr; + + mcan_class->net->irq = irq; + mcan_class->pm_clock_support = 1; + mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); + mcan_class->dev = &pdev->dev; + + mcan_class->ops = &m_can_plat_ops; + + mcan_class->is_peripheral = false; + + platform_set_drvdata(pdev, mcan_class->dev); + + m_can_init_ram(mcan_class); + + ret = m_can_class_register(mcan_class); + +failed_ret: + return ret; +} + +static __maybe_unused int m_can_suspend(struct device *dev) +{ + return m_can_class_suspend(dev); +} + +static __maybe_unused int m_can_resume(struct device *dev) +{ + return m_can_class_resume(dev); +} + +static int m_can_plat_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct m_can_priv *mcan_class = netdev_priv(dev); + + m_can_class_unregister(mcan_class); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int __maybe_unused m_can_runtime_suspend(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct m_can_priv *mcan_class = netdev_priv(ndev); + + m_can_class_suspend(dev); + + clk_disable_unprepare(mcan_class->cclk); + clk_disable_unprepare(mcan_class->hclk); + + return 0; +} + +static int __maybe_unused m_can_runtime_resume(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct m_can_priv *mcan_class = netdev_priv(ndev); + int err; + + err = clk_prepare_enable(mcan_class->hclk); + if (err) + return err; + + err = clk_prepare_enable(mcan_class->cclk); + if (err) + clk_disable_unprepare(mcan_class->hclk); + + m_can_class_resume(dev); + + return err; +} + +static const struct dev_pm_ops m_can_pmops = { + SET_RUNTIME_PM_OPS(m_can_runtime_suspend, + m_can_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume) +}; + +static const struct of_device_id m_can_of_table[] = { + { .compatible = "bosch,m_can", .data = NULL }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, m_can_of_table); + +static struct platform_driver m_can_plat_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = m_can_of_table, + .pm = &m_can_pmops, + }, + .probe = m_can_plat_probe, + .remove = m_can_plat_remove, +}; + +module_platform_driver(m_can_plat_driver); + +MODULE_AUTHOR("Dong Aisheng "); +MODULE_AUTHOR("Dan Murphy "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("M_CAN driver for IO Mapped Bosch controllers"); -- GitLab From 441ac340169b792bf3df274f062e4939abb93ce8 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 9 May 2019 11:11:06 -0500 Subject: [PATCH 0422/7155] can: m_can: Rename m_can_priv to m_can_classdev Rename the common m_can_priv class structure to m_can_classdev as this is more descriptive. Acked-by: Wolfgang Grandegger Signed-off-by: Dan Murphy Acked-by: Faiz Abbas Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/m_can.c | 539 +++++++++++++------------ drivers/net/can/m_can/m_can.h | 28 +- drivers/net/can/m_can/m_can_platform.c | 16 +- 3 files changed, 294 insertions(+), 289 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 4ad8d97fa8e1..562c8317e3aa 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -320,57 +320,57 @@ enum m_can_reg { #define TX_EVENT_MM_SHIFT TX_BUF_MM_SHIFT #define TX_EVENT_MM_MASK (0xff << TX_EVENT_MM_SHIFT) -static inline u32 m_can_read(struct m_can_priv *priv, enum m_can_reg reg) +static inline u32 m_can_read(struct m_can_classdev *cdev, enum m_can_reg reg) { - return priv->ops->read_reg(priv, reg); + return cdev->ops->read_reg(cdev, reg); } -static inline void m_can_write(struct m_can_priv *priv, enum m_can_reg reg, +static inline void m_can_write(struct m_can_classdev *cdev, enum m_can_reg reg, u32 val) { - priv->ops->write_reg(priv, reg, val); + cdev->ops->write_reg(cdev, reg, val); } -static u32 m_can_fifo_read(struct m_can_priv *priv, +static u32 m_can_fifo_read(struct m_can_classdev *cdev, u32 fgi, unsigned int offset) { - u32 addr_offset = priv->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE + + u32 addr_offset = cdev->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE + offset; - return priv->ops->read_fifo(priv, addr_offset); + return cdev->ops->read_fifo(cdev, addr_offset); } -static void m_can_fifo_write(struct m_can_priv *priv, +static void m_can_fifo_write(struct m_can_classdev *cdev, u32 fpi, unsigned int offset, u32 val) { - u32 addr_offset = priv->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE + + u32 addr_offset = cdev->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE + offset; - priv->ops->write_fifo(priv, addr_offset, val); + cdev->ops->write_fifo(cdev, addr_offset, val); } -static inline void m_can_fifo_write_no_off(struct m_can_priv *priv, +static inline void m_can_fifo_write_no_off(struct m_can_classdev *cdev, u32 fpi, u32 val) { - priv->ops->write_fifo(priv, fpi, val); + cdev->ops->write_fifo(cdev, fpi, val); } -static u32 m_can_txe_fifo_read(struct m_can_priv *priv, u32 fgi, u32 offset) +static u32 m_can_txe_fifo_read(struct m_can_classdev *cdev, u32 fgi, u32 offset) { - u32 addr_offset = priv->mcfg[MRAM_TXE].off + fgi * TXE_ELEMENT_SIZE + + u32 addr_offset = cdev->mcfg[MRAM_TXE].off + fgi * TXE_ELEMENT_SIZE + offset; - return priv->ops->read_fifo(priv, addr_offset); + return cdev->ops->read_fifo(cdev, addr_offset); } -static inline bool m_can_tx_fifo_full(struct m_can_priv *priv) +static inline bool m_can_tx_fifo_full(struct m_can_classdev *cdev) { - return !!(m_can_read(priv, M_CAN_TXFQS) & TXFQS_TFQF); + return !!(m_can_read(cdev, M_CAN_TXFQS) & TXFQS_TFQF); } -void m_can_config_endisable(struct m_can_priv *priv, bool enable) +void m_can_config_endisable(struct m_can_classdev *cdev, bool enable) { - u32 cccr = m_can_read(priv, M_CAN_CCCR); + u32 cccr = m_can_read(cdev, M_CAN_CCCR); u32 timeout = 10; u32 val = 0; @@ -384,21 +384,21 @@ void m_can_config_endisable(struct m_can_priv *priv, bool enable) cccr &= ~CCCR_CSR; /* enable m_can configuration */ - m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT); + m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT); udelay(5); /* CCCR.CCE can only be set/reset while CCCR.INIT = '1' */ - m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE); + m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE); } else { - m_can_write(priv, M_CAN_CCCR, cccr & ~(CCCR_INIT | CCCR_CCE)); + m_can_write(cdev, M_CAN_CCCR, cccr & ~(CCCR_INIT | CCCR_CCE)); } /* there's a delay for module initialization */ if (enable) val = CCCR_INIT | CCCR_CCE; - while ((m_can_read(priv, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) { + while ((m_can_read(cdev, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) { if (timeout == 0) { - netdev_warn(priv->net, "Failed to init module\n"); + netdev_warn(cdev->net, "Failed to init module\n"); return; } timeout--; @@ -406,38 +406,38 @@ void m_can_config_endisable(struct m_can_priv *priv, bool enable) } } -static inline void m_can_enable_all_interrupts(struct m_can_priv *priv) +static inline void m_can_enable_all_interrupts(struct m_can_classdev *cdev) { /* Only interrupt line 0 is used in this driver */ - m_can_write(priv, M_CAN_ILE, ILE_EINT0); + m_can_write(cdev, M_CAN_ILE, ILE_EINT0); } -static inline void m_can_disable_all_interrupts(struct m_can_priv *priv) +static inline void m_can_disable_all_interrupts(struct m_can_classdev *cdev) { - m_can_write(priv, M_CAN_ILE, 0x0); + m_can_write(cdev, M_CAN_ILE, 0x0); } static void m_can_clean(struct net_device *net) { - struct m_can_priv *priv = netdev_priv(net); + struct m_can_classdev *cdev = netdev_priv(net); - if (priv->tx_skb) { + if (cdev->tx_skb) { int putidx = 0; net->stats.tx_errors++; - if (priv->version > 30) - putidx = ((m_can_read(priv, M_CAN_TXFQS) & + if (cdev->version > 30) + putidx = ((m_can_read(cdev, M_CAN_TXFQS) & TXFQS_TFQPI_MASK) >> TXFQS_TFQPI_SHIFT); - can_free_echo_skb(priv->net, putidx); - priv->tx_skb = NULL; + can_free_echo_skb(cdev->net, putidx); + cdev->tx_skb = NULL; } } static void m_can_read_fifo(struct net_device *dev, u32 rxfs) { struct net_device_stats *stats = &dev->stats; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); struct canfd_frame *cf; struct sk_buff *skb; u32 id, fgi, dlc; @@ -445,7 +445,7 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs) /* calculate the fifo get index for where to read data */ fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_SHIFT; - dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); + dlc = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DLC); if (dlc & RX_BUF_FDF) skb = alloc_canfd_skb(dev, &cf); else @@ -460,7 +460,7 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs) else cf->len = get_can_dlc((dlc >> 16) & 0x0F); - id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID); + id = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_ID); if (id & RX_BUF_XTD) cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; else @@ -479,12 +479,12 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs) for (i = 0; i < cf->len; i += 4) *(u32 *)(cf->data + i) = - m_can_fifo_read(priv, fgi, + m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA(i / 4)); } /* acknowledge rx fifo 0 */ - m_can_write(priv, M_CAN_RXF0A, fgi); + m_can_write(cdev, M_CAN_RXF0A, fgi); stats->rx_packets++; stats->rx_bytes += cf->len; @@ -494,11 +494,11 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs) static int m_can_do_rx_poll(struct net_device *dev, int quota) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); u32 pkts = 0; u32 rxfs; - rxfs = m_can_read(priv, M_CAN_RXF0S); + rxfs = m_can_read(cdev, M_CAN_RXF0S); if (!(rxfs & RXFS_FFL_MASK)) { netdev_dbg(dev, "no messages in fifo0\n"); return 0; @@ -512,7 +512,7 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota) quota--; pkts++; - rxfs = m_can_read(priv, M_CAN_RXF0S); + rxfs = m_can_read(cdev, M_CAN_RXF0S); } if (pkts) @@ -547,12 +547,12 @@ static int m_can_handle_lost_msg(struct net_device *dev) static int m_can_handle_lec_err(struct net_device *dev, enum m_can_lec_type lec_type) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; - priv->can.can_stats.bus_error++; + cdev->can.can_stats.bus_error++; stats->rx_errors++; /* propagate the error condition to the CAN stack */ @@ -604,51 +604,51 @@ static int m_can_handle_lec_err(struct net_device *dev, static int __m_can_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); unsigned int ecr; - ecr = m_can_read(priv, M_CAN_ECR); + ecr = m_can_read(cdev, M_CAN_ECR); bec->rxerr = (ecr & ECR_REC_MASK) >> ECR_REC_SHIFT; bec->txerr = (ecr & ECR_TEC_MASK) >> ECR_TEC_SHIFT; return 0; } -static int m_can_clk_start(struct m_can_priv *priv) +static int m_can_clk_start(struct m_can_classdev *cdev) { int err; - if (priv->pm_clock_support == 0) + if (cdev->pm_clock_support == 0) return 0; - err = pm_runtime_get_sync(priv->dev); + err = pm_runtime_get_sync(cdev->dev); if (err < 0) { - pm_runtime_put_noidle(priv->dev); + pm_runtime_put_noidle(cdev->dev); return err; } return 0; } -static void m_can_clk_stop(struct m_can_priv *priv) +static void m_can_clk_stop(struct m_can_classdev *cdev) { - if (priv->pm_clock_support) - pm_runtime_put_sync(priv->dev); + if (cdev->pm_clock_support) + pm_runtime_put_sync(cdev->dev); } static int m_can_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int err; - err = m_can_clk_start(priv); + err = m_can_clk_start(cdev); if (err) return err; __m_can_get_berr_counter(dev, bec); - m_can_clk_stop(priv); + m_can_clk_stop(cdev); return 0; } @@ -656,7 +656,7 @@ static int m_can_get_berr_counter(const struct net_device *dev, static int m_can_handle_state_change(struct net_device *dev, enum can_state new_state) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; @@ -666,19 +666,19 @@ static int m_can_handle_state_change(struct net_device *dev, switch (new_state) { case CAN_STATE_ERROR_ACTIVE: /* error warning state */ - priv->can.can_stats.error_warning++; - priv->can.state = CAN_STATE_ERROR_WARNING; + cdev->can.can_stats.error_warning++; + cdev->can.state = CAN_STATE_ERROR_WARNING; break; case CAN_STATE_ERROR_PASSIVE: /* error passive state */ - priv->can.can_stats.error_passive++; - priv->can.state = CAN_STATE_ERROR_PASSIVE; + cdev->can.can_stats.error_passive++; + cdev->can.state = CAN_STATE_ERROR_PASSIVE; break; case CAN_STATE_BUS_OFF: /* bus-off state */ - priv->can.state = CAN_STATE_BUS_OFF; - m_can_disable_all_interrupts(priv); - priv->can.can_stats.bus_off++; + cdev->can.state = CAN_STATE_BUS_OFF; + m_can_disable_all_interrupts(cdev); + cdev->can.can_stats.bus_off++; can_bus_off(dev); break; default: @@ -705,7 +705,7 @@ static int m_can_handle_state_change(struct net_device *dev, case CAN_STATE_ERROR_PASSIVE: /* error passive state */ cf->can_id |= CAN_ERR_CRTL; - ecr = m_can_read(priv, M_CAN_ECR); + ecr = m_can_read(cdev, M_CAN_ECR); if (ecr & ECR_RP) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; if (bec.txerr > 127) @@ -730,22 +730,22 @@ static int m_can_handle_state_change(struct net_device *dev, static int m_can_handle_state_errors(struct net_device *dev, u32 psr) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int work_done = 0; - if (psr & PSR_EW && priv->can.state != CAN_STATE_ERROR_WARNING) { + if (psr & PSR_EW && cdev->can.state != CAN_STATE_ERROR_WARNING) { netdev_dbg(dev, "entered error warning state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_ERROR_WARNING); } - if (psr & PSR_EP && priv->can.state != CAN_STATE_ERROR_PASSIVE) { + if (psr & PSR_EP && cdev->can.state != CAN_STATE_ERROR_PASSIVE) { netdev_dbg(dev, "entered error passive state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_ERROR_PASSIVE); } - if (psr & PSR_BO && priv->can.state != CAN_STATE_BUS_OFF) { + if (psr & PSR_BO && cdev->can.state != CAN_STATE_BUS_OFF) { netdev_dbg(dev, "entered error bus off state\n"); work_done += m_can_handle_state_change(dev, CAN_STATE_BUS_OFF); @@ -780,14 +780,14 @@ static inline bool is_lec_err(u32 psr) static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, u32 psr) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int work_done = 0; if (irqstatus & IR_RF0L) work_done += m_can_handle_lost_msg(dev); /* handle lec errors on the bus */ - if ((priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && + if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && is_lec_err(psr)) work_done += m_can_handle_lec_err(dev, psr & LEC_UNUSED); @@ -799,11 +799,11 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, static int m_can_rx_handler(struct net_device *dev, int quota) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int work_done = 0; u32 irqstatus, psr; - irqstatus = priv->irqstatus | m_can_read(priv, M_CAN_IR); + irqstatus = cdev->irqstatus | m_can_read(cdev, M_CAN_IR); if (!irqstatus) goto end; @@ -817,18 +817,19 @@ static int m_can_rx_handler(struct net_device *dev, int quota) * whether MCAN_ECR.RP = ’1’ and MCAN_ECR.REC = 127. * In this case, reset MCAN_IR.MRAF. No further action is required. */ - if (priv->version <= 31 && irqstatus & IR_MRAF && - m_can_read(priv, M_CAN_ECR) & ECR_RP) { + if (cdev->version <= 31 && irqstatus & IR_MRAF && + m_can_read(cdev, M_CAN_ECR) & ECR_RP) { struct can_berr_counter bec; __m_can_get_berr_counter(dev, &bec); if (bec.rxerr == 127) { - m_can_write(priv, M_CAN_IR, IR_MRAF); + m_can_write(cdev, M_CAN_IR, IR_MRAF); irqstatus &= ~IR_MRAF; } } - psr = m_can_read(priv, M_CAN_PSR); + psr = m_can_read(cdev, M_CAN_PSR); + if (irqstatus & IR_ERR_STATE) work_done += m_can_handle_state_errors(dev, psr); @@ -843,11 +844,11 @@ static int m_can_rx_handler(struct net_device *dev, int quota) static int m_can_rx_peripheral(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); m_can_rx_handler(dev, 1); - m_can_enable_all_interrupts(priv); + m_can_enable_all_interrupts(cdev); return 0; } @@ -855,13 +856,13 @@ static int m_can_rx_peripheral(struct net_device *dev) static int m_can_poll(struct napi_struct *napi, int quota) { struct net_device *dev = napi->dev; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int work_done; work_done = m_can_rx_handler(dev, quota); if (work_done < quota) { napi_complete_done(napi, work_done); - m_can_enable_all_interrupts(priv); + m_can_enable_all_interrupts(cdev); } return work_done; @@ -875,11 +876,11 @@ static void m_can_echo_tx_event(struct net_device *dev) int i = 0; unsigned int msg_mark; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; /* read tx event fifo status */ - m_can_txefs = m_can_read(priv, M_CAN_TXEFS); + m_can_txefs = m_can_read(cdev, M_CAN_TXEFS); /* Get Tx Event fifo element count */ txe_count = (m_can_txefs & TXEFS_EFFL_MASK) @@ -888,15 +889,15 @@ static void m_can_echo_tx_event(struct net_device *dev) /* Get and process all sent elements */ for (i = 0; i < txe_count; i++) { /* retrieve get index */ - fgi = (m_can_read(priv, M_CAN_TXEFS) & TXEFS_EFGI_MASK) + fgi = (m_can_read(cdev, M_CAN_TXEFS) & TXEFS_EFGI_MASK) >> TXEFS_EFGI_SHIFT; /* get message marker */ - msg_mark = (m_can_txe_fifo_read(priv, fgi, 4) & + msg_mark = (m_can_txe_fifo_read(cdev, fgi, 4) & TX_EVENT_MM_MASK) >> TX_EVENT_MM_SHIFT; /* ack txe element */ - m_can_write(priv, M_CAN_TXEFA, (TXEFA_EFAI_MASK & + m_can_write(cdev, M_CAN_TXEFA, (TXEFA_EFAI_MASK & (fgi << TXEFA_EFAI_SHIFT))); /* update stats */ @@ -908,20 +909,20 @@ static void m_can_echo_tx_event(struct net_device *dev) static irqreturn_t m_can_isr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; u32 ir; - ir = m_can_read(priv, M_CAN_IR); + ir = m_can_read(cdev, M_CAN_IR); if (!ir) return IRQ_NONE; /* ACK all irqs */ if (ir & IR_ALL_INT) - m_can_write(priv, M_CAN_IR, ir); + m_can_write(cdev, M_CAN_IR, ir); - if (priv->ops->clear_interrupts) - priv->ops->clear_interrupts(priv); + if (cdev->ops->clear_interrupts) + cdev->ops->clear_interrupts(cdev); /* schedule NAPI in case of * - rx IRQ @@ -929,15 +930,15 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) * - bus error IRQ and bus error reporting */ if ((ir & IR_RF0N) || (ir & IR_ERR_ALL_30X)) { - priv->irqstatus = ir; - m_can_disable_all_interrupts(priv); - if (!priv->is_peripheral) - napi_schedule(&priv->napi); + cdev->irqstatus = ir; + m_can_disable_all_interrupts(cdev); + if (!cdev->is_peripheral) + napi_schedule(&cdev->napi); else m_can_rx_peripheral(dev); } - if (priv->version == 30) { + if (cdev->version == 30) { if (ir & IR_TC) { /* Transmission Complete Interrupt*/ stats->tx_bytes += can_get_echo_skb(dev, 0); @@ -951,7 +952,7 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) m_can_echo_tx_event(dev); can_led_event(dev, CAN_LED_EVENT_TX); if (netif_queue_stopped(dev) && - !m_can_tx_fifo_full(priv)) + !m_can_tx_fifo_full(cdev)) netif_wake_queue(dev); } } @@ -1009,9 +1010,9 @@ static const struct can_bittiming_const m_can_data_bittiming_const_31X = { static int m_can_set_bittiming(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); - const struct can_bittiming *bt = &priv->can.bittiming; - const struct can_bittiming *dbt = &priv->can.data_bittiming; + struct m_can_classdev *cdev = netdev_priv(dev); + const struct can_bittiming *bt = &cdev->can.bittiming; + const struct can_bittiming *dbt = &cdev->can.data_bittiming; u16 brp, sjw, tseg1, tseg2; u32 reg_btp; @@ -1021,9 +1022,9 @@ static int m_can_set_bittiming(struct net_device *dev) tseg2 = bt->phase_seg2 - 1; reg_btp = (brp << NBTP_NBRP_SHIFT) | (sjw << NBTP_NSJW_SHIFT) | (tseg1 << NBTP_NTSEG1_SHIFT) | (tseg2 << NBTP_NTSEG2_SHIFT); - m_can_write(priv, M_CAN_NBTP, reg_btp); + m_can_write(cdev, M_CAN_NBTP, reg_btp); - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) { reg_btp = 0; brp = dbt->brp - 1; sjw = dbt->sjw - 1; @@ -1045,7 +1046,7 @@ static int m_can_set_bittiming(struct net_device *dev) /* Equation based on Bosch's M_CAN User Manual's * Transmitter Delay Compensation Section */ - tdco = (priv->can.clock.freq / 1000) * + tdco = (cdev->can.clock.freq / 1000) * ssp / dbt->bitrate; /* Max valid TDCO value is 127 */ @@ -1056,7 +1057,7 @@ static int m_can_set_bittiming(struct net_device *dev) } reg_btp |= DBTP_TDC; - m_can_write(priv, M_CAN_TDCR, + m_can_write(cdev, M_CAN_TDCR, tdco << TDCR_TDCO_SHIFT); } @@ -1065,7 +1066,7 @@ static int m_can_set_bittiming(struct net_device *dev) (tseg1 << DBTP_DTSEG1_SHIFT) | (tseg2 << DBTP_DTSEG2_SHIFT); - m_can_write(priv, M_CAN_DBTP, reg_btp); + m_can_write(cdev, M_CAN_DBTP, reg_btp); } return 0; @@ -1082,63 +1083,63 @@ static int m_can_set_bittiming(struct net_device *dev) */ static void m_can_chip_config(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); u32 cccr, test; - m_can_config_endisable(priv, true); + m_can_config_endisable(cdev, true); /* RX Buffer/FIFO Element Size 64 bytes data field */ - m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_64BYTES); + m_can_write(cdev, M_CAN_RXESC, M_CAN_RXESC_64BYTES); /* Accept Non-matching Frames Into FIFO 0 */ - m_can_write(priv, M_CAN_GFC, 0x0); + m_can_write(cdev, M_CAN_GFC, 0x0); - if (priv->version == 30) { + if (cdev->version == 30) { /* only support one Tx Buffer currently */ - m_can_write(priv, M_CAN_TXBC, (1 << TXBC_NDTB_SHIFT) | - priv->mcfg[MRAM_TXB].off); + m_can_write(cdev, M_CAN_TXBC, (1 << TXBC_NDTB_SHIFT) | + cdev->mcfg[MRAM_TXB].off); } else { /* TX FIFO is used for newer IP Core versions */ - m_can_write(priv, M_CAN_TXBC, - (priv->mcfg[MRAM_TXB].num << TXBC_TFQS_SHIFT) | - (priv->mcfg[MRAM_TXB].off)); + m_can_write(cdev, M_CAN_TXBC, + (cdev->mcfg[MRAM_TXB].num << TXBC_TFQS_SHIFT) | + (cdev->mcfg[MRAM_TXB].off)); } /* support 64 bytes payload */ - m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_64BYTES); + m_can_write(cdev, M_CAN_TXESC, TXESC_TBDS_64BYTES); /* TX Event FIFO */ - if (priv->version == 30) { - m_can_write(priv, M_CAN_TXEFC, (1 << TXEFC_EFS_SHIFT) | - priv->mcfg[MRAM_TXE].off); + if (cdev->version == 30) { + m_can_write(cdev, M_CAN_TXEFC, (1 << TXEFC_EFS_SHIFT) | + cdev->mcfg[MRAM_TXE].off); } else { /* Full TX Event FIFO is used */ - m_can_write(priv, M_CAN_TXEFC, - ((priv->mcfg[MRAM_TXE].num << TXEFC_EFS_SHIFT) + m_can_write(cdev, M_CAN_TXEFC, + ((cdev->mcfg[MRAM_TXE].num << TXEFC_EFS_SHIFT) & TXEFC_EFS_MASK) | - priv->mcfg[MRAM_TXE].off); + cdev->mcfg[MRAM_TXE].off); } /* rx fifo configuration, blocking mode, fifo size 1 */ - m_can_write(priv, M_CAN_RXF0C, - (priv->mcfg[MRAM_RXF0].num << RXFC_FS_SHIFT) | - priv->mcfg[MRAM_RXF0].off); + m_can_write(cdev, M_CAN_RXF0C, + (cdev->mcfg[MRAM_RXF0].num << RXFC_FS_SHIFT) | + cdev->mcfg[MRAM_RXF0].off); - m_can_write(priv, M_CAN_RXF1C, - (priv->mcfg[MRAM_RXF1].num << RXFC_FS_SHIFT) | - priv->mcfg[MRAM_RXF1].off); + m_can_write(cdev, M_CAN_RXF1C, + (cdev->mcfg[MRAM_RXF1].num << RXFC_FS_SHIFT) | + cdev->mcfg[MRAM_RXF1].off); - cccr = m_can_read(priv, M_CAN_CCCR); - test = m_can_read(priv, M_CAN_TEST); + cccr = m_can_read(cdev, M_CAN_CCCR); + test = m_can_read(cdev, M_CAN_TEST); test &= ~TEST_LBCK; - if (priv->version == 30) { + if (cdev->version == 30) { /* Version 3.0.x */ cccr &= ~(CCCR_TEST | CCCR_MON | (CCCR_CMR_MASK << CCCR_CMR_SHIFT) | (CCCR_CME_MASK << CCCR_CME_SHIFT)); - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) + if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT; } else { @@ -1147,61 +1148,61 @@ static void m_can_chip_config(struct net_device *dev) CCCR_NISO); /* Only 3.2.x has NISO Bit implemented */ - if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) + if (cdev->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) cccr |= CCCR_NISO; - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) + if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) cccr |= (CCCR_BRSE | CCCR_FDOE); } /* Loopback Mode */ - if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { + if (cdev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { cccr |= CCCR_TEST | CCCR_MON; test |= TEST_LBCK; } /* Enable Monitoring (all versions) */ - if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + if (cdev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) cccr |= CCCR_MON; /* Write config */ - m_can_write(priv, M_CAN_CCCR, cccr); - m_can_write(priv, M_CAN_TEST, test); + m_can_write(cdev, M_CAN_CCCR, cccr); + m_can_write(cdev, M_CAN_TEST, test); /* Enable interrupts */ - m_can_write(priv, M_CAN_IR, IR_ALL_INT); - if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) - if (priv->version == 30) - m_can_write(priv, M_CAN_IE, IR_ALL_INT & + m_can_write(cdev, M_CAN_IR, IR_ALL_INT); + if (!(cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) + if (cdev->version == 30) + m_can_write(cdev, M_CAN_IE, IR_ALL_INT & ~(IR_ERR_LEC_30X)); else - m_can_write(priv, M_CAN_IE, IR_ALL_INT & + m_can_write(cdev, M_CAN_IE, IR_ALL_INT & ~(IR_ERR_LEC_31X)); else - m_can_write(priv, M_CAN_IE, IR_ALL_INT); + m_can_write(cdev, M_CAN_IE, IR_ALL_INT); /* route all interrupts to INT0 */ - m_can_write(priv, M_CAN_ILS, ILS_ALL_INT0); + m_can_write(cdev, M_CAN_ILS, ILS_ALL_INT0); /* set bittiming params */ m_can_set_bittiming(dev); - m_can_config_endisable(priv, false); + m_can_config_endisable(cdev, false); - if (priv->ops->init) - priv->ops->init(priv); + if (cdev->ops->init) + cdev->ops->init(cdev); } static void m_can_start(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); /* basic m_can configuration */ m_can_chip_config(dev); - priv->can.state = CAN_STATE_ERROR_ACTIVE; + cdev->can.state = CAN_STATE_ERROR_ACTIVE; - m_can_enable_all_interrupts(priv); + m_can_enable_all_interrupts(cdev); } static int m_can_set_mode(struct net_device *dev, enum can_mode mode) @@ -1224,7 +1225,7 @@ static int m_can_set_mode(struct net_device *dev, enum can_mode mode) * else it returns the release and step coded as: * return value = 10 * + 1 * */ -static int m_can_check_core_release(struct m_can_priv *priv) +static int m_can_check_core_release(struct m_can_classdev *cdev) { u32 crel_reg; u8 rel; @@ -1234,7 +1235,7 @@ static int m_can_check_core_release(struct m_can_priv *priv) /* Read Core Release Version and split into version number * Example: Version 3.2.1 => rel = 3; step = 2; substep = 1; */ - crel_reg = m_can_read(priv, M_CAN_CREL); + crel_reg = m_can_read(cdev, M_CAN_CREL); rel = (u8)((crel_reg & CREL_REL_MASK) >> CREL_REL_SHIFT); step = (u8)((crel_reg & CREL_STEP_MASK) >> CREL_STEP_SHIFT); @@ -1252,19 +1253,19 @@ static int m_can_check_core_release(struct m_can_priv *priv) /* Selectable Non ISO support only in version 3.2.x * This function checks if the bit is writable. */ -static bool m_can_niso_supported(struct m_can_priv *priv) +static bool m_can_niso_supported(struct m_can_classdev *cdev) { u32 cccr_reg, cccr_poll = 0; int niso_timeout = -ETIMEDOUT; int i; - m_can_config_endisable(priv, true); - cccr_reg = m_can_read(priv, M_CAN_CCCR); + m_can_config_endisable(cdev, true); + cccr_reg = m_can_read(cdev, M_CAN_CCCR); cccr_reg |= CCCR_NISO; - m_can_write(priv, M_CAN_CCCR, cccr_reg); + m_can_write(cdev, M_CAN_CCCR, cccr_reg); for (i = 0; i <= 10; i++) { - cccr_poll = m_can_read(priv, M_CAN_CCCR); + cccr_poll = m_can_read(cdev, M_CAN_CCCR); if (cccr_poll == cccr_reg) { niso_timeout = 0; break; @@ -1275,15 +1276,15 @@ static bool m_can_niso_supported(struct m_can_priv *priv) /* Clear NISO */ cccr_reg &= ~(CCCR_NISO); - m_can_write(priv, M_CAN_CCCR, cccr_reg); + m_can_write(cdev, M_CAN_CCCR, cccr_reg); - m_can_config_endisable(priv, false); + m_can_config_endisable(cdev, false); /* return false if time out (-ETIMEDOUT), else return true */ return !niso_timeout; } -static int m_can_dev_setup(struct m_can_priv *m_can_dev) +static int m_can_dev_setup(struct m_can_classdev *m_can_dev) { struct net_device *dev = m_can_dev->net; int m_can_version; @@ -1360,30 +1361,32 @@ static int m_can_dev_setup(struct m_can_priv *m_can_dev) static void m_can_stop(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); /* disable all interrupts */ - m_can_disable_all_interrupts(priv); + m_can_disable_all_interrupts(cdev); /* set the state as STOPPED */ - priv->can.state = CAN_STATE_STOPPED; + cdev->can.state = CAN_STATE_STOPPED; } static int m_can_close(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); netif_stop_queue(dev); - if (!priv->is_peripheral) - napi_disable(&priv->napi); + + if (!cdev->is_peripheral) + napi_disable(&cdev->napi); + m_can_stop(dev); - m_can_clk_stop(priv); + m_can_clk_stop(cdev); free_irq(dev->irq, dev); - if (priv->is_peripheral) { - priv->tx_skb = NULL; - destroy_workqueue(priv->tx_wq); - priv->tx_wq = NULL; + if (cdev->is_peripheral) { + cdev->tx_skb = NULL; + destroy_workqueue(cdev->tx_wq); + cdev->tx_wq = NULL; } close_candev(dev); @@ -1394,23 +1397,23 @@ static int m_can_close(struct net_device *dev) static int m_can_next_echo_skb_occupied(struct net_device *dev, int putidx) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); /*get wrap around for loopback skb index */ - unsigned int wrap = priv->can.echo_skb_max; + unsigned int wrap = cdev->can.echo_skb_max; int next_idx; /* calculate next index */ next_idx = (++putidx >= wrap ? 0 : putidx); /* check if occupied */ - return !!priv->can.echo_skb[next_idx]; + return !!cdev->can.echo_skb[next_idx]; } -static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) +static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev) { - struct canfd_frame *cf = (struct canfd_frame *)priv->tx_skb->data; - struct net_device *dev = priv->net; - struct sk_buff *skb = priv->tx_skb; + struct canfd_frame *cf = (struct canfd_frame *)cdev->tx_skb->data; + struct net_device *dev = cdev->net; + struct sk_buff *skb = cdev->tx_skb; u32 id, cccr, fdflags; int i; int putidx; @@ -1427,23 +1430,23 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) if (cf->can_id & CAN_RTR_FLAG) id |= TX_BUF_RTR; - if (priv->version == 30) { + if (cdev->version == 30) { netif_stop_queue(dev); /* message ram configuration */ - m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, + m_can_fifo_write(cdev, 0, M_CAN_FIFO_ID, id); + m_can_fifo_write(cdev, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16); for (i = 0; i < cf->len; i += 4) - m_can_fifo_write(priv, 0, + m_can_fifo_write(cdev, 0, M_CAN_FIFO_DATA(i / 4), *(u32 *)(cf->data + i)); can_put_echo_skb(skb, dev, 0); - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { - cccr = m_can_read(priv, M_CAN_CCCR); + if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) { + cccr = m_can_read(cdev, M_CAN_CCCR); cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT); if (can_is_canfd_skb(skb)) { if (cf->flags & CANFD_BRS) @@ -1455,21 +1458,22 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) } else { cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT; } - m_can_write(priv, M_CAN_CCCR, cccr); + m_can_write(cdev, M_CAN_CCCR, cccr); } - m_can_write(priv, M_CAN_TXBTIE, 0x1); - m_can_write(priv, M_CAN_TXBAR, 0x1); + m_can_write(cdev, M_CAN_TXBTIE, 0x1); + m_can_write(cdev, M_CAN_TXBAR, 0x1); /* End of xmit function for version 3.0.x */ } else { /* Transmit routine for version >= v3.1.x */ /* Check if FIFO full */ - if (m_can_tx_fifo_full(priv)) { + if (m_can_tx_fifo_full(cdev)) { /* This shouldn't happen */ netif_stop_queue(dev); netdev_warn(dev, "TX queue active although FIFO is full."); - if (priv->is_peripheral) { + + if (cdev->is_peripheral) { kfree_skb(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; @@ -1479,10 +1483,10 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) } /* get put index for frame */ - putidx = ((m_can_read(priv, M_CAN_TXFQS) & TXFQS_TFQPI_MASK) + putidx = ((m_can_read(cdev, M_CAN_TXFQS) & TXFQS_TFQPI_MASK) >> TXFQS_TFQPI_SHIFT); /* Write ID Field to FIFO Element */ - m_can_fifo_write(priv, putidx, M_CAN_FIFO_ID, id); + m_can_fifo_write(cdev, putidx, M_CAN_FIFO_ID, id); /* get CAN FD configuration of frame */ fdflags = 0; @@ -1497,14 +1501,14 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) * it is used in TX interrupt for * sending the correct echo frame */ - m_can_fifo_write(priv, putidx, M_CAN_FIFO_DLC, + m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DLC, ((putidx << TX_BUF_MM_SHIFT) & TX_BUF_MM_MASK) | (can_len2dlc(cf->len) << 16) | fdflags | TX_BUF_EFC); for (i = 0; i < cf->len; i += 4) - m_can_fifo_write(priv, putidx, M_CAN_FIFO_DATA(i / 4), + m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DATA(i / 4), *(u32 *)(cf->data + i)); /* Push loopback echo. @@ -1513,10 +1517,10 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) can_put_echo_skb(skb, dev, putidx); /* Enable TX FIFO element to start transfer */ - m_can_write(priv, M_CAN_TXBAR, (1 << putidx)); + m_can_write(cdev, M_CAN_TXBAR, (1 << putidx)); /* stop network queue if fifo full */ - if (m_can_tx_fifo_full(priv) || + if (m_can_tx_fifo_full(cdev) || m_can_next_echo_skb_occupied(dev, putidx)) netif_stop_queue(dev); } @@ -1526,27 +1530,28 @@ static netdev_tx_t m_can_tx_handler(struct m_can_priv *priv) static void m_can_tx_work_queue(struct work_struct *ws) { - struct m_can_priv *priv = container_of(ws, struct m_can_priv, + struct m_can_classdev *cdev = container_of(ws, struct m_can_classdev, tx_work); - m_can_tx_handler(priv); - priv->tx_skb = NULL; + + m_can_tx_handler(cdev); + cdev->tx_skb = NULL; } static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; - if (priv->is_peripheral) { - if (priv->tx_skb) { + if (cdev->is_peripheral) { + if (cdev->tx_skb) { netdev_err(dev, "hard_xmit called while tx busy\n"); return NETDEV_TX_BUSY; } - if (priv->can.state == CAN_STATE_BUS_OFF) { + if (cdev->can.state == CAN_STATE_BUS_OFF) { m_can_clean(dev); } else { /* Need to stop the queue to avoid numerous requests @@ -1554,13 +1559,13 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, * a queueing mechanism that will queue the skbs and * process them in order. */ - priv->tx_skb = skb; - netif_stop_queue(priv->net); - queue_work(priv->tx_wq, &priv->tx_work); + cdev->tx_skb = skb; + netif_stop_queue(cdev->net); + queue_work(cdev->tx_wq, &cdev->tx_work); } } else { - priv->tx_skb = skb; - return m_can_tx_handler(priv); + cdev->tx_skb = skb; + return m_can_tx_handler(cdev); } return NETDEV_TX_OK; @@ -1568,10 +1573,10 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, static int m_can_open(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *cdev = netdev_priv(dev); int err; - err = m_can_clk_start(priv); + err = m_can_clk_start(cdev); if (err) return err; @@ -1583,16 +1588,16 @@ static int m_can_open(struct net_device *dev) } /* register interrupt handler */ - if (priv->is_peripheral) { - priv->tx_skb = NULL; - priv->tx_wq = alloc_workqueue("mcan_wq", + if (cdev->is_peripheral) { + cdev->tx_skb = NULL; + cdev->tx_wq = alloc_workqueue("mcan_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, 0); - if (!priv->tx_wq) { + if (!cdev->tx_wq) { err = -ENOMEM; goto out_wq_fail; } - INIT_WORK(&priv->tx_work, m_can_tx_work_queue); + INIT_WORK(&cdev->tx_work, m_can_tx_work_queue); err = request_threaded_irq(dev->irq, NULL, m_can_isr, IRQF_ONESHOT | IRQF_TRIGGER_FALLING, @@ -1612,20 +1617,20 @@ static int m_can_open(struct net_device *dev) can_led_event(dev, CAN_LED_EVENT_OPEN); - if (!priv->is_peripheral) - napi_enable(&priv->napi); + if (!cdev->is_peripheral) + napi_enable(&cdev->napi); netif_start_queue(dev); return 0; exit_irq_fail: - if (priv->is_peripheral) - destroy_workqueue(priv->tx_wq); + if (cdev->is_peripheral) + destroy_workqueue(cdev->tx_wq); out_wq_fail: close_candev(dev); exit_disable_clks: - m_can_clk_stop(priv); + m_can_clk_stop(cdev); return err; } @@ -1644,61 +1649,61 @@ static int register_m_can_dev(struct net_device *dev) return register_candev(dev); } -static void m_can_of_parse_mram(struct m_can_priv *priv, +static void m_can_of_parse_mram(struct m_can_classdev *cdev, const u32 *mram_config_vals) { - priv->mcfg[MRAM_SIDF].off = mram_config_vals[0]; - priv->mcfg[MRAM_SIDF].num = mram_config_vals[1]; - priv->mcfg[MRAM_XIDF].off = priv->mcfg[MRAM_SIDF].off + - priv->mcfg[MRAM_SIDF].num * SIDF_ELEMENT_SIZE; - priv->mcfg[MRAM_XIDF].num = mram_config_vals[2]; - priv->mcfg[MRAM_RXF0].off = priv->mcfg[MRAM_XIDF].off + - priv->mcfg[MRAM_XIDF].num * XIDF_ELEMENT_SIZE; - priv->mcfg[MRAM_RXF0].num = mram_config_vals[3] & + cdev->mcfg[MRAM_SIDF].off = mram_config_vals[0]; + cdev->mcfg[MRAM_SIDF].num = mram_config_vals[1]; + cdev->mcfg[MRAM_XIDF].off = cdev->mcfg[MRAM_SIDF].off + + cdev->mcfg[MRAM_SIDF].num * SIDF_ELEMENT_SIZE; + cdev->mcfg[MRAM_XIDF].num = mram_config_vals[2]; + cdev->mcfg[MRAM_RXF0].off = cdev->mcfg[MRAM_XIDF].off + + cdev->mcfg[MRAM_XIDF].num * XIDF_ELEMENT_SIZE; + cdev->mcfg[MRAM_RXF0].num = mram_config_vals[3] & (RXFC_FS_MASK >> RXFC_FS_SHIFT); - priv->mcfg[MRAM_RXF1].off = priv->mcfg[MRAM_RXF0].off + - priv->mcfg[MRAM_RXF0].num * RXF0_ELEMENT_SIZE; - priv->mcfg[MRAM_RXF1].num = mram_config_vals[4] & + cdev->mcfg[MRAM_RXF1].off = cdev->mcfg[MRAM_RXF0].off + + cdev->mcfg[MRAM_RXF0].num * RXF0_ELEMENT_SIZE; + cdev->mcfg[MRAM_RXF1].num = mram_config_vals[4] & (RXFC_FS_MASK >> RXFC_FS_SHIFT); - priv->mcfg[MRAM_RXB].off = priv->mcfg[MRAM_RXF1].off + - priv->mcfg[MRAM_RXF1].num * RXF1_ELEMENT_SIZE; - priv->mcfg[MRAM_RXB].num = mram_config_vals[5]; - priv->mcfg[MRAM_TXE].off = priv->mcfg[MRAM_RXB].off + - priv->mcfg[MRAM_RXB].num * RXB_ELEMENT_SIZE; - priv->mcfg[MRAM_TXE].num = mram_config_vals[6]; - priv->mcfg[MRAM_TXB].off = priv->mcfg[MRAM_TXE].off + - priv->mcfg[MRAM_TXE].num * TXE_ELEMENT_SIZE; - priv->mcfg[MRAM_TXB].num = mram_config_vals[7] & + cdev->mcfg[MRAM_RXB].off = cdev->mcfg[MRAM_RXF1].off + + cdev->mcfg[MRAM_RXF1].num * RXF1_ELEMENT_SIZE; + cdev->mcfg[MRAM_RXB].num = mram_config_vals[5]; + cdev->mcfg[MRAM_TXE].off = cdev->mcfg[MRAM_RXB].off + + cdev->mcfg[MRAM_RXB].num * RXB_ELEMENT_SIZE; + cdev->mcfg[MRAM_TXE].num = mram_config_vals[6]; + cdev->mcfg[MRAM_TXB].off = cdev->mcfg[MRAM_TXE].off + + cdev->mcfg[MRAM_TXE].num * TXE_ELEMENT_SIZE; + cdev->mcfg[MRAM_TXB].num = mram_config_vals[7] & (TXBC_NDTB_MASK >> TXBC_NDTB_SHIFT); - dev_dbg(priv->dev, + dev_dbg(cdev->dev, "sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d rxb 0x%x %d txe 0x%x %d txb 0x%x %d\n", - priv->mcfg[MRAM_SIDF].off, priv->mcfg[MRAM_SIDF].num, - priv->mcfg[MRAM_XIDF].off, priv->mcfg[MRAM_XIDF].num, - priv->mcfg[MRAM_RXF0].off, priv->mcfg[MRAM_RXF0].num, - priv->mcfg[MRAM_RXF1].off, priv->mcfg[MRAM_RXF1].num, - priv->mcfg[MRAM_RXB].off, priv->mcfg[MRAM_RXB].num, - priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, - priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); + cdev->mcfg[MRAM_SIDF].off, cdev->mcfg[MRAM_SIDF].num, + cdev->mcfg[MRAM_XIDF].off, cdev->mcfg[MRAM_XIDF].num, + cdev->mcfg[MRAM_RXF0].off, cdev->mcfg[MRAM_RXF0].num, + cdev->mcfg[MRAM_RXF1].off, cdev->mcfg[MRAM_RXF1].num, + cdev->mcfg[MRAM_RXB].off, cdev->mcfg[MRAM_RXB].num, + cdev->mcfg[MRAM_TXE].off, cdev->mcfg[MRAM_TXE].num, + cdev->mcfg[MRAM_TXB].off, cdev->mcfg[MRAM_TXB].num); } -void m_can_init_ram(struct m_can_priv *priv) +void m_can_init_ram(struct m_can_classdev *cdev) { int end, i, start; /* initialize the entire Message RAM in use to avoid possible * ECC/parity checksum errors when reading an uninitialized buffer */ - start = priv->mcfg[MRAM_SIDF].off; - end = priv->mcfg[MRAM_TXB].off + - priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; + start = cdev->mcfg[MRAM_SIDF].off; + end = cdev->mcfg[MRAM_TXB].off + + cdev->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; for (i = start; i < end; i += 4) - m_can_fifo_write_no_off(priv, i, 0x0); + m_can_fifo_write_no_off(cdev, i, 0x0); } EXPORT_SYMBOL_GPL(m_can_init_ram); -int m_can_class_get_clocks(struct m_can_priv *m_can_dev) +int m_can_class_get_clocks(struct m_can_classdev *m_can_dev) { int ret = 0; @@ -1714,9 +1719,9 @@ int m_can_class_get_clocks(struct m_can_priv *m_can_dev) } EXPORT_SYMBOL_GPL(m_can_class_get_clocks); -struct m_can_priv *m_can_class_allocate_dev(struct device *dev) +struct m_can_classdev *m_can_class_allocate_dev(struct device *dev) { - struct m_can_priv *class_dev = NULL; + struct m_can_classdev *class_dev = NULL; u32 mram_config_vals[MRAM_CFG_LEN]; struct net_device *net_dev; u32 tx_fifo_size; @@ -1745,7 +1750,7 @@ struct m_can_priv *m_can_class_allocate_dev(struct device *dev) class_dev = netdev_priv(net_dev); if (!class_dev) { - dev_err(dev, "Failed to init netdev private"); + dev_err(dev, "Failed to init netdev cdevate"); goto out; } @@ -1759,7 +1764,7 @@ struct m_can_priv *m_can_class_allocate_dev(struct device *dev) } EXPORT_SYMBOL_GPL(m_can_class_allocate_dev); -int m_can_class_register(struct m_can_priv *m_can_dev) +int m_can_class_register(struct m_can_classdev *m_can_dev) { int ret; @@ -1807,18 +1812,18 @@ EXPORT_SYMBOL_GPL(m_can_class_register); int m_can_class_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *cdev = netdev_priv(ndev); if (netif_running(ndev)) { netif_stop_queue(ndev); netif_device_detach(ndev); m_can_stop(ndev); - m_can_clk_stop(priv); + m_can_clk_stop(cdev); } pinctrl_pm_select_sleep_state(dev); - priv->can.state = CAN_STATE_SLEEPING; + cdev->can.state = CAN_STATE_SLEEPING; return 0; } @@ -1827,20 +1832,20 @@ EXPORT_SYMBOL_GPL(m_can_class_suspend); int m_can_class_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *cdev = netdev_priv(ndev); pinctrl_pm_select_default_state(dev); - priv->can.state = CAN_STATE_ERROR_ACTIVE; + cdev->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(ndev)) { int ret; - ret = m_can_clk_start(priv); + ret = m_can_clk_start(cdev); if (ret) return ret; - m_can_init_ram(priv); + m_can_init_ram(cdev); m_can_start(ndev); netif_device_attach(ndev); netif_start_queue(ndev); @@ -1850,7 +1855,7 @@ int m_can_class_resume(struct device *dev) } EXPORT_SYMBOL_GPL(m_can_class_resume); -void m_can_class_unregister(struct m_can_priv *m_can_dev) +void m_can_class_unregister(struct m_can_classdev *m_can_dev) { unregister_candev(m_can_dev->net); diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index 5671f5423887..49f42b50627a 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -57,19 +57,19 @@ struct mram_cfg { u8 num; }; -struct m_can_priv; +struct m_can_classdev; struct m_can_ops { /* Device specific call backs */ - int (*clear_interrupts)(struct m_can_priv *m_can_class); - u32 (*read_reg)(struct m_can_priv *m_can_class, int reg); - int (*write_reg)(struct m_can_priv *m_can_class, int reg, int val); - u32 (*read_fifo)(struct m_can_priv *m_can_class, int addr_offset); - int (*write_fifo)(struct m_can_priv *m_can_class, int addr_offset, + int (*clear_interrupts)(struct m_can_classdev *cdev); + u32 (*read_reg)(struct m_can_classdev *cdev, int reg); + int (*write_reg)(struct m_can_classdev *cdev, int reg, int val); + u32 (*read_fifo)(struct m_can_classdev *cdev, int addr_offset); + int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset, int val); - int (*init)(struct m_can_priv *m_can_class); + int (*init)(struct m_can_classdev *cdev); }; -struct m_can_priv { +struct m_can_classdev { struct can_priv can; struct napi_struct napi; struct net_device *net; @@ -98,12 +98,12 @@ struct m_can_priv { struct mram_cfg mcfg[MRAM_CFG_NUM]; }; -struct m_can_priv *m_can_class_allocate_dev(struct device *dev); -int m_can_class_register(struct m_can_priv *m_can_dev); -void m_can_class_unregister(struct m_can_priv *m_can_dev); -int m_can_class_get_clocks(struct m_can_priv *m_can_dev); -void m_can_init_ram(struct m_can_priv *priv); -void m_can_config_endisable(struct m_can_priv *priv, bool enable); +struct m_can_classdev *m_can_class_allocate_dev(struct device *dev); +int m_can_class_register(struct m_can_classdev *cdev); +void m_can_class_unregister(struct m_can_classdev *cdev); +int m_can_class_get_clocks(struct m_can_classdev *cdev); +void m_can_init_ram(struct m_can_classdev *priv); +void m_can_config_endisable(struct m_can_classdev *priv, bool enable); int m_can_class_suspend(struct device *dev); int m_can_class_resume(struct device *dev); diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 026053f62f77..c2989e0431f2 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -14,7 +14,7 @@ struct m_can_plat_priv { void __iomem *mram_base; }; -static u32 iomap_read_reg(struct m_can_priv *cdev, int reg) +static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg) { struct m_can_plat_priv *priv = (struct m_can_plat_priv *)cdev->device_data; @@ -22,7 +22,7 @@ static u32 iomap_read_reg(struct m_can_priv *cdev, int reg) return readl(priv->base + reg); } -static u32 iomap_read_fifo(struct m_can_priv *cdev, int offset) +static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset) { struct m_can_plat_priv *priv = (struct m_can_plat_priv *)cdev->device_data; @@ -30,7 +30,7 @@ static u32 iomap_read_fifo(struct m_can_priv *cdev, int offset) return readl(priv->mram_base + offset); } -static int iomap_write_reg(struct m_can_priv *cdev, int reg, int val) +static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val) { struct m_can_plat_priv *priv = (struct m_can_plat_priv *)cdev->device_data; @@ -40,7 +40,7 @@ static int iomap_write_reg(struct m_can_priv *cdev, int reg, int val) return 0; } -static int iomap_write_fifo(struct m_can_priv *cdev, int offset, int val) +static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val) { struct m_can_plat_priv *priv = (struct m_can_plat_priv *)cdev->device_data; @@ -59,7 +59,7 @@ static struct m_can_ops m_can_plat_ops = { static int m_can_plat_probe(struct platform_device *pdev) { - struct m_can_priv *mcan_class; + struct m_can_classdev *mcan_class; struct m_can_plat_priv *priv; struct resource *res; void __iomem *addr; @@ -131,7 +131,7 @@ static __maybe_unused int m_can_resume(struct device *dev) static int m_can_plat_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); - struct m_can_priv *mcan_class = netdev_priv(dev); + struct m_can_classdev *mcan_class = netdev_priv(dev); m_can_class_unregister(mcan_class); @@ -143,7 +143,7 @@ static int m_can_plat_remove(struct platform_device *pdev) static int __maybe_unused m_can_runtime_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *mcan_class = netdev_priv(ndev); + struct m_can_classdev *mcan_class = netdev_priv(ndev); m_can_class_suspend(dev); @@ -156,7 +156,7 @@ static int __maybe_unused m_can_runtime_suspend(struct device *dev) static int __maybe_unused m_can_runtime_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *mcan_class = netdev_priv(ndev); + struct m_can_classdev *mcan_class = netdev_priv(ndev); int err; err = clk_prepare_enable(mcan_class->hclk); -- GitLab From 4edd396a1911222da7a5d4b2bc58ab546de02bd5 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 9 May 2019 11:11:07 -0500 Subject: [PATCH 0423/7155] dt-bindings: can: tcan4x5x: Add DT bindings for TCAN4x5X driver DT binding documentation for TI TCAN4x5x driver. Signed-off-by: Dan Murphy Signed-off-by: Marc Kleine-Budde --- .../devicetree/bindings/net/can/tcan4x5x.txt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/can/tcan4x5x.txt diff --git a/Documentation/devicetree/bindings/net/can/tcan4x5x.txt b/Documentation/devicetree/bindings/net/can/tcan4x5x.txt new file mode 100644 index 000000000000..c388f7d9feb1 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/tcan4x5x.txt @@ -0,0 +1,37 @@ +Texas Instruments TCAN4x5x CAN Controller +================================================ + +This file provides device node information for the TCAN4x5x interface contains. + +Required properties: + - compatible: "ti,tcan4x5x" + - reg: 0 + - #address-cells: 1 + - #size-cells: 0 + - spi-max-frequency: Maximum frequency of the SPI bus the chip can + operate at should be less than or equal to 18 MHz. + - data-ready-gpios: Interrupt GPIO for data and error reporting. + - device-wake-gpios: Wake up GPIO to wake up the TCAN device. + +See Documentation/devicetree/bindings/net/can/m_can.txt for additional +required property details. + +Optional properties: + - reset-gpios: Hardwired output GPIO. If not defined then software + reset. + - device-state-gpios: Input GPIO that indicates if the device is in + a sleep state or if the device is active. + +Example: +tcan4x5x: tcan4x5x@0 { + compatible = "ti,tcan4x5x"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <10000000>; + bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; + data-ready-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; + device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; +}; -- GitLab From 5443c226ba9166521360ed3148175d63cd5ab263 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 9 May 2019 11:11:08 -0500 Subject: [PATCH 0424/7155] can: tcan4x5x: Add tcan4x5x driver to the kernel Add the TCAN4x5x SPI CAN driver. This device uses the Bosch MCAN IP core along with a SPI interface map. Register to the MCAN common core code to manage the MCAN IP. This device has a special method to indicate a write/read operation on the data payload. Acked-by: Wolfgang Grandegger Signed-off-by: Dan Murphy Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/Kconfig | 9 + drivers/net/can/m_can/Makefile | 1 + drivers/net/can/m_can/tcan4x5x.c | 532 +++++++++++++++++++++++++++++++ 3 files changed, 542 insertions(+) create mode 100644 drivers/net/can/m_can/tcan4x5x.c diff --git a/drivers/net/can/m_can/Kconfig b/drivers/net/can/m_can/Kconfig index 306c75dc7913..1ff0b7fe81d6 100644 --- a/drivers/net/can/m_can/Kconfig +++ b/drivers/net/can/m_can/Kconfig @@ -13,3 +13,12 @@ config CAN_M_CAN_PLATFORM Say Y here if you want support for IO Mapped Bosch M_CAN controller. This support is for devices that have the Bosch M_CAN controller IP embedded into the device and the IP is IO Mapped to the processor. + +config CAN_M_CAN_TCAN4X5X + depends on CAN_M_CAN + depends on REGMAP_SPI + tristate "TCAN4X5X M_CAN device" + ---help--- + Say Y here if you want support for Texas Instruments TCAN4x5x + M_CAN controller. This device is a peripherial device that uses the + SPI bus for communication. diff --git a/drivers/net/can/m_can/Makefile b/drivers/net/can/m_can/Makefile index ac568be3de98..52a4a6fbe527 100644 --- a/drivers/net/can/m_can/Makefile +++ b/drivers/net/can/m_can/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_CAN_M_CAN) += m_can.o obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o +obj-$(CONFIG_CAN_M_CAN_TCAN4X5X) += tcan4x5x.o diff --git a/drivers/net/can/m_can/tcan4x5x.c b/drivers/net/can/m_can/tcan4x5x.c new file mode 100644 index 000000000000..b115b2e5333f --- /dev/null +++ b/drivers/net/can/m_can/tcan4x5x.c @@ -0,0 +1,532 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPI to CAN driver for the Texas Instruments TCAN4x5x +// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ + +#include +#include + +#include +#include + +#include "m_can.h" + +#define DEVICE_NAME "tcan4x5x" +#define TCAN4X5X_EXT_CLK_DEF 40000000 + +#define TCAN4X5X_DEV_ID0 0x00 +#define TCAN4X5X_DEV_ID1 0x04 +#define TCAN4X5X_REV 0x08 +#define TCAN4X5X_STATUS 0x0C +#define TCAN4X5X_ERROR_STATUS 0x10 +#define TCAN4X5X_CONTROL 0x14 + +#define TCAN4X5X_CONFIG 0x800 +#define TCAN4X5X_TS_PRESCALE 0x804 +#define TCAN4X5X_TEST_REG 0x808 +#define TCAN4X5X_INT_FLAGS 0x820 +#define TCAN4X5X_MCAN_INT_REG 0x824 +#define TCAN4X5X_INT_EN 0x830 + +/* Interrupt bits */ +#define TCAN4X5X_CANBUSTERMOPEN_INT_EN BIT(30) +#define TCAN4X5X_CANHCANL_INT_EN BIT(29) +#define TCAN4X5X_CANHBAT_INT_EN BIT(28) +#define TCAN4X5X_CANLGND_INT_EN BIT(27) +#define TCAN4X5X_CANBUSOPEN_INT_EN BIT(26) +#define TCAN4X5X_CANBUSGND_INT_EN BIT(25) +#define TCAN4X5X_CANBUSBAT_INT_EN BIT(24) +#define TCAN4X5X_UVSUP_INT_EN BIT(22) +#define TCAN4X5X_UVIO_INT_EN BIT(21) +#define TCAN4X5X_TSD_INT_EN BIT(19) +#define TCAN4X5X_ECCERR_INT_EN BIT(16) +#define TCAN4X5X_CANINT_INT_EN BIT(15) +#define TCAN4X5X_LWU_INT_EN BIT(14) +#define TCAN4X5X_CANSLNT_INT_EN BIT(10) +#define TCAN4X5X_CANDOM_INT_EN BIT(8) +#define TCAN4X5X_CANBUS_ERR_INT_EN BIT(5) +#define TCAN4X5X_BUS_FAULT BIT(4) +#define TCAN4X5X_MCAN_INT BIT(1) +#define TCAN4X5X_ENABLE_TCAN_INT \ + (TCAN4X5X_MCAN_INT | TCAN4X5X_BUS_FAULT | \ + TCAN4X5X_CANBUS_ERR_INT_EN | TCAN4X5X_CANINT_INT_EN) + +/* MCAN Interrupt bits */ +#define TCAN4X5X_MCAN_IR_ARA BIT(29) +#define TCAN4X5X_MCAN_IR_PED BIT(28) +#define TCAN4X5X_MCAN_IR_PEA BIT(27) +#define TCAN4X5X_MCAN_IR_WD BIT(26) +#define TCAN4X5X_MCAN_IR_BO BIT(25) +#define TCAN4X5X_MCAN_IR_EW BIT(24) +#define TCAN4X5X_MCAN_IR_EP BIT(23) +#define TCAN4X5X_MCAN_IR_ELO BIT(22) +#define TCAN4X5X_MCAN_IR_BEU BIT(21) +#define TCAN4X5X_MCAN_IR_BEC BIT(20) +#define TCAN4X5X_MCAN_IR_DRX BIT(19) +#define TCAN4X5X_MCAN_IR_TOO BIT(18) +#define TCAN4X5X_MCAN_IR_MRAF BIT(17) +#define TCAN4X5X_MCAN_IR_TSW BIT(16) +#define TCAN4X5X_MCAN_IR_TEFL BIT(15) +#define TCAN4X5X_MCAN_IR_TEFF BIT(14) +#define TCAN4X5X_MCAN_IR_TEFW BIT(13) +#define TCAN4X5X_MCAN_IR_TEFN BIT(12) +#define TCAN4X5X_MCAN_IR_TFE BIT(11) +#define TCAN4X5X_MCAN_IR_TCF BIT(10) +#define TCAN4X5X_MCAN_IR_TC BIT(9) +#define TCAN4X5X_MCAN_IR_HPM BIT(8) +#define TCAN4X5X_MCAN_IR_RF1L BIT(7) +#define TCAN4X5X_MCAN_IR_RF1F BIT(6) +#define TCAN4X5X_MCAN_IR_RF1W BIT(5) +#define TCAN4X5X_MCAN_IR_RF1N BIT(4) +#define TCAN4X5X_MCAN_IR_RF0L BIT(3) +#define TCAN4X5X_MCAN_IR_RF0F BIT(2) +#define TCAN4X5X_MCAN_IR_RF0W BIT(1) +#define TCAN4X5X_MCAN_IR_RF0N BIT(0) +#define TCAN4X5X_ENABLE_MCAN_INT \ + (TCAN4X5X_MCAN_IR_TC | TCAN4X5X_MCAN_IR_RF0N | \ + TCAN4X5X_MCAN_IR_RF1N | TCAN4X5X_MCAN_IR_RF0F | \ + TCAN4X5X_MCAN_IR_RF1F) + +#define TCAN4X5X_MRAM_START 0x8000 +#define TCAN4X5X_MCAN_OFFSET 0x1000 +#define TCAN4X5X_MAX_REGISTER 0x8fff + +#define TCAN4X5X_CLEAR_ALL_INT 0xffffffff +#define TCAN4X5X_SET_ALL_INT 0xffffffff + +#define TCAN4X5X_WRITE_CMD (0x61 << 24) +#define TCAN4X5X_READ_CMD (0x41 << 24) + +#define TCAN4X5X_MODE_SEL_MASK (BIT(7) | BIT(6)) +#define TCAN4X5X_MODE_SLEEP 0x00 +#define TCAN4X5X_MODE_STANDBY BIT(6) +#define TCAN4X5X_MODE_NORMAL BIT(7) + +#define TCAN4X5X_SW_RESET BIT(2) + +#define TCAN4X5X_MCAN_CONFIGURED BIT(5) +#define TCAN4X5X_WATCHDOG_EN BIT(3) +#define TCAN4X5X_WD_60_MS_TIMER 0 +#define TCAN4X5X_WD_600_MS_TIMER BIT(28) +#define TCAN4X5X_WD_3_S_TIMER BIT(29) +#define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29)) + +struct tcan4x5x_priv { + struct regmap *regmap; + struct spi_device *spi; + struct mutex tcan4x5x_lock; /* SPI device lock */ + + struct m_can_classdev *mcan_dev; + + struct gpio_desc *reset_gpio; + struct gpio_desc *interrupt_gpio; + struct gpio_desc *device_wake_gpio; + struct gpio_desc *device_state_gpio; + struct regulator *power; + + /* Register based ip */ + int mram_start; + int reg_offset; +}; + +static struct can_bittiming_const tcan4x5x_bittiming_const = { + .name = DEVICE_NAME, + .tseg1_min = 2, + .tseg1_max = 31, + .tseg2_min = 2, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + +static struct can_bittiming_const tcan4x5x_data_bittiming_const = { + .name = DEVICE_NAME, + .tseg1_min = 1, + .tseg1_max = 32, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + +static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv) +{ + int wake_state = 0; + + if (priv->device_state_gpio) + wake_state = gpiod_get_value(priv->device_state_gpio); + + if (priv->device_wake_gpio && wake_state) { + gpiod_set_value(priv->device_wake_gpio, 0); + usleep_range(5, 50); + gpiod_set_value(priv->device_wake_gpio, 1); + } +} + +static int regmap_spi_gather_write(void *context, const void *reg, + size_t reg_len, const void *val, + size_t val_len) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + struct spi_message m; + u32 addr; + struct spi_transfer t[2] = { + { .tx_buf = &addr, .len = reg_len, .cs_change = 0,}, + { .tx_buf = val, .len = val_len, }, + }; + + addr = TCAN4X5X_WRITE_CMD | (*((u16 *)reg) << 8) | val_len >> 3; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + return spi_sync(spi, &m); +} + +static int tcan4x5x_regmap_write(void *context, const void *data, size_t count) +{ + u16 *reg = (u16 *)(data); + const u32 *val = data + 4; + + return regmap_spi_gather_write(context, reg, 4, val, count); +} + +static int regmap_spi_async_write(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len, + struct regmap_async *a) +{ + return -ENOTSUPP; +} + +static struct regmap_async *regmap_spi_async_alloc(void) +{ + return NULL; +} + +static int tcan4x5x_regmap_read(void *context, + const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + + u32 addr = TCAN4X5X_READ_CMD | (*((u16 *)reg) << 8) | val_size >> 2; + + return spi_write_then_read(spi, &addr, reg_size, (u32 *)val, val_size); +} + +static struct regmap_bus tcan4x5x_bus = { + .write = tcan4x5x_regmap_write, + .gather_write = regmap_spi_gather_write, + .async_write = regmap_spi_async_write, + .async_alloc = regmap_spi_async_alloc, + .read = tcan4x5x_regmap_read, + .read_flag_mask = 0x00, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg) +{ + struct tcan4x5x_priv *priv = (struct tcan4x5x_priv *)cdev->device_data; + u32 val; + + tcan4x5x_check_wake(priv); + + regmap_read(priv->regmap, priv->reg_offset + reg, &val); + + return val; +} + +static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset) +{ + struct tcan4x5x_priv *priv = (struct tcan4x5x_priv *)cdev->device_data; + u32 val; + + tcan4x5x_check_wake(priv); + + regmap_read(priv->regmap, priv->mram_start + addr_offset, &val); + + return val; +} + +static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val) +{ + struct tcan4x5x_priv *priv = (struct tcan4x5x_priv *)cdev->device_data; + + tcan4x5x_check_wake(priv); + + return regmap_write(priv->regmap, priv->reg_offset + reg, val); +} + +static int tcan4x5x_write_fifo(struct m_can_classdev *cdev, + int addr_offset, int val) +{ + struct tcan4x5x_priv *priv = + (struct tcan4x5x_priv *)cdev->device_data; + + tcan4x5x_check_wake(priv); + + return regmap_write(priv->regmap, priv->mram_start + addr_offset, val); +} + +static int tcan4x5x_power_enable(struct regulator *reg, int enable) +{ + if (IS_ERR_OR_NULL(reg)) + return 0; + + if (enable) + return regulator_enable(reg); + else + return regulator_disable(reg); +} + +static int tcan4x5x_write_tcan_reg(struct m_can_classdev *cdev, + int reg, int val) +{ + struct tcan4x5x_priv *priv = + (struct tcan4x5x_priv *)cdev->device_data; + + tcan4x5x_check_wake(priv); + + return regmap_write(priv->regmap, reg, val); +} + +static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) +{ + struct tcan4x5x_priv *tcan4x5x = + (struct tcan4x5x_priv *)cdev->device_data; + int ret; + + tcan4x5x_check_wake(tcan4x5x); + + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_STATUS, + TCAN4X5X_CLEAR_ALL_INT); + if (ret) + return ret; + + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG, + TCAN4X5X_ENABLE_MCAN_INT); + if (ret) + return ret; + + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, + TCAN4X5X_CLEAR_ALL_INT); + if (ret) + return ret; + + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS, + TCAN4X5X_CLEAR_ALL_INT); + if (ret) + return ret; + + return ret; +} + +static int tcan4x5x_init(struct m_can_classdev *cdev) +{ + struct tcan4x5x_priv *tcan4x5x = + (struct tcan4x5x_priv *)cdev->device_data; + int ret; + + tcan4x5x_check_wake(tcan4x5x); + + ret = tcan4x5x_clear_interrupts(cdev); + if (ret) + return ret; + + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_EN, + TCAN4X5X_ENABLE_TCAN_INT); + if (ret) + return ret; + + ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, + TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL); + if (ret) + return ret; + + /* Zero out the MCAN buffers */ + m_can_init_ram(cdev); + + return ret; +} + +static int tcan4x5x_parse_config(struct m_can_classdev *cdev) +{ + struct tcan4x5x_priv *tcan4x5x = + (struct tcan4x5x_priv *)cdev->device_data; + + tcan4x5x->interrupt_gpio = devm_gpiod_get(cdev->dev, "data-ready", + GPIOD_IN); + if (IS_ERR(tcan4x5x->interrupt_gpio)) { + dev_err(cdev->dev, "data-ready gpio not defined\n"); + return -EINVAL; + } + + tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake", + GPIOD_OUT_HIGH); + if (IS_ERR(tcan4x5x->device_wake_gpio)) { + dev_err(cdev->dev, "device-wake gpio not defined\n"); + return -EINVAL; + } + + tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(tcan4x5x->reset_gpio)) + tcan4x5x->reset_gpio = NULL; + + tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, + "device-state", + GPIOD_IN); + if (IS_ERR(tcan4x5x->device_state_gpio)) + tcan4x5x->device_state_gpio = NULL; + + cdev->net->irq = gpiod_to_irq(tcan4x5x->interrupt_gpio); + + tcan4x5x->power = devm_regulator_get_optional(cdev->dev, + "vsup"); + if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + return 0; +} + +static const struct regmap_config tcan4x5x_regmap = { + .reg_bits = 32, + .val_bits = 32, + .cache_type = REGCACHE_NONE, + .max_register = TCAN4X5X_MAX_REGISTER, +}; + +static struct m_can_ops tcan4x5x_ops = { + .init = tcan4x5x_init, + .read_reg = tcan4x5x_read_reg, + .write_reg = tcan4x5x_write_reg, + .write_fifo = tcan4x5x_write_fifo, + .read_fifo = tcan4x5x_read_fifo, + .clear_interrupts = tcan4x5x_clear_interrupts, +}; + +static int tcan4x5x_can_probe(struct spi_device *spi) +{ + struct tcan4x5x_priv *priv; + struct m_can_classdev *mcan_class; + int freq, ret; + + mcan_class = m_can_class_allocate_dev(&spi->dev); + priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mcan_class->device_data = priv; + + m_can_class_get_clocks(mcan_class); + if (IS_ERR(mcan_class->cclk)) { + dev_err(&spi->dev, "no CAN clock source defined\n"); + freq = TCAN4X5X_EXT_CLK_DEF; + } else { + freq = clk_get_rate(mcan_class->cclk); + } + + /* Sanity check */ + if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) + return -ERANGE; + + priv->reg_offset = TCAN4X5X_MCAN_OFFSET; + priv->mram_start = TCAN4X5X_MRAM_START; + priv->spi = spi; + priv->mcan_dev = mcan_class; + + mcan_class->pm_clock_support = 0; + mcan_class->can.clock.freq = freq; + mcan_class->dev = &spi->dev; + mcan_class->ops = &tcan4x5x_ops; + mcan_class->is_peripheral = true; + mcan_class->bit_timing = &tcan4x5x_bittiming_const; + mcan_class->data_timing = &tcan4x5x_data_bittiming_const; + + spi_set_drvdata(spi, priv); + + ret = tcan4x5x_parse_config(mcan_class); + if (ret) + goto out_clk; + + /* Configure the SPI bus */ + spi->bits_per_word = 32; + ret = spi_setup(spi); + if (ret) + goto out_clk; + + priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus, + &spi->dev, &tcan4x5x_regmap); + + mutex_init(&priv->tcan4x5x_lock); + + tcan4x5x_power_enable(priv->power, 1); + + ret = m_can_class_register(mcan_class); + if (ret) + goto out_power; + + netdev_info(mcan_class->net, "TCAN4X5X successfully initialized.\n"); + return 0; + +out_power: + tcan4x5x_power_enable(priv->power, 0); +out_clk: + if (!IS_ERR(mcan_class->cclk)) { + clk_disable_unprepare(mcan_class->cclk); + clk_disable_unprepare(mcan_class->hclk); + } + + dev_err(&spi->dev, "Probe failed, err=%d\n", ret); + return ret; +} + +static int tcan4x5x_can_remove(struct spi_device *spi) +{ + struct tcan4x5x_priv *priv = spi_get_drvdata(spi); + + tcan4x5x_power_enable(priv->power, 0); + + m_can_class_unregister(priv->mcan_dev); + + return 0; +} + +static const struct of_device_id tcan4x5x_of_match[] = { + { .compatible = "ti,tcan4x5x", }, + { } +}; +MODULE_DEVICE_TABLE(of, tcan4x5x_of_match); + +static const struct spi_device_id tcan4x5x_id_table[] = { + { + .name = "tcan4x5x", + .driver_data = 0, + }, + { } +}; +MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table); + +static struct spi_driver tcan4x5x_can_driver = { + .driver = { + .name = DEVICE_NAME, + .of_match_table = tcan4x5x_of_match, + .pm = NULL, + }, + .id_table = tcan4x5x_id_table, + .probe = tcan4x5x_can_probe, + .remove = tcan4x5x_can_remove, +}; +module_spi_driver(tcan4x5x_can_driver); + +MODULE_AUTHOR("Dan Murphy "); +MODULE_DESCRIPTION("Texas Instruments TCAN4x5x CAN driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From d38f9180da881f130801f964339a98015f7e53da Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:41 +0530 Subject: [PATCH 0425/7155] can: xilinx_can: Fix style issues This patch fixes below checkpatch warnings and checks in the driver. CHECK: Alignment should match open parenthesis + void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val); CHECK: Alignment should match open parenthesis +static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val) CHECK: Alignment should match open parenthesis +static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val) CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", + priv->read_reg(priv, XCAN_BRPR_OFFSET), CHECK: Alignment should match open parenthesis + netdev_warn(ndev, + "timed out for correct mode\n"); CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "status:#x%08x\n", + priv->read_reg(priv, XCAN_SR_OFFSET)); CHECK: spaces preferred around that '-' (ctx:VxV) + (CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << ^ CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "%s: error status register:0x%x\n", + __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); WARNING: line over 80 characters + offset = XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); WARNING: line over 80 characters + offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); WARNING: line over 80 characters + while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) { WARNING: line over 80 characters + priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); CHECK: Alignment should match open parenthesis + ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, + ndev->name, ndev); CHECK: Alignment should match open parenthesis +static int xcan_get_berr_counter(const struct net_device *ndev, + struct can_berr_counter *bec) CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); CHECK: Please don't use multiple blank lines + + CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret);` Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 41 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 63203ff452b5..1823f4fc448a 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -183,7 +183,7 @@ struct xcan_priv { struct napi_struct napi; u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val); + u32 val); struct device *dev; void __iomem *reg_base; unsigned long irq_flags; @@ -238,7 +238,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { * Write data to the paricular CAN register */ static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val) + u32 val) { iowrite32(val, priv->reg_base + reg); } @@ -265,7 +265,7 @@ static u32 xcan_read_reg_le(const struct xcan_priv *priv, enum xcan_reg reg) * Write data to the paricular CAN register */ static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val) + u32 val) { iowrite32be(val, priv->reg_base + reg); } @@ -373,8 +373,8 @@ static int xcan_set_bittiming(struct net_device *ndev) priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", - priv->read_reg(priv, XCAN_BRPR_OFFSET), - priv->read_reg(priv, XCAN_BTR_OFFSET)); + priv->read_reg(priv, XCAN_BRPR_OFFSET), + priv->read_reg(priv, XCAN_BTR_OFFSET)); return 0; } @@ -439,12 +439,12 @@ static int xcan_chip_start(struct net_device *ndev) while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { if (time_after(jiffies, timeout)) { netdev_warn(ndev, - "timed out for correct mode\n"); + "timed out for correct mode\n"); return -ETIMEDOUT; } } netdev_dbg(ndev, "status:#x%08x\n", - priv->read_reg(priv, XCAN_SR_OFFSET)); + priv->read_reg(priv, XCAN_SR_OFFSET)); priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; @@ -498,7 +498,7 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) & XCAN_IDR_ID2_MASK; id |= (((cf->can_id & CAN_EFF_MASK) >> - (CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << + (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)) << XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK; /* The substibute remote TX request bit should be "1" @@ -934,7 +934,7 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) } netdev_dbg(ndev, "%s: error status register:0x%x\n", - __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); + __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); } /** @@ -982,9 +982,11 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) return -ENOENT; if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - offset = XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + offset = + XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); else - offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + offset = + XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); } else { /* check if RX FIFO is empty */ @@ -1094,8 +1096,10 @@ static void xcan_tx_interrupt(struct net_device *ndev, u32 isr) * via TXFEMP handling as we read TXFEMP *after* TXOK * clear to satisfy (1). */ - while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) { - priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); + while ((isr & XCAN_IXR_TXOK_MASK) && + !WARN_ON(++retries == 100)) { + priv->write_reg(priv, XCAN_ICR_OFFSET, + XCAN_IXR_TXOK_MASK); isr = priv->read_reg(priv, XCAN_ISR_OFFSET); } @@ -1208,12 +1212,12 @@ static int xcan_open(struct net_device *ndev) ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); return ret; } ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, - ndev->name, ndev); + ndev->name, ndev); if (ret < 0) { netdev_err(ndev, "irq allocation for CAN failed\n"); goto err; @@ -1284,7 +1288,7 @@ static int xcan_close(struct net_device *ndev) * Return: 0 on success and failure value on error */ static int xcan_get_berr_counter(const struct net_device *ndev, - struct can_berr_counter *bec) + struct can_berr_counter *bec) { struct xcan_priv *priv = netdev_priv(ndev); int ret; @@ -1292,7 +1296,7 @@ static int xcan_get_berr_counter(const struct net_device *ndev, ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); return ret; } @@ -1305,7 +1309,6 @@ static int xcan_get_berr_counter(const struct net_device *ndev, return 0; } - static const struct net_device_ops xcan_netdev_ops = { .ndo_open = xcan_open, .ndo_stop = xcan_close, @@ -1589,7 +1592,7 @@ static int xcan_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); goto err_pmdisable; } -- GitLab From c942a575b95f762dd8721487619d24068471af60 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:46 +0530 Subject: [PATCH 0426/7155] can: xilinx_can: Fix kernel doc warnings This patch fixes below kernel doc warnings warning: Function parameter or member 'priv' not described in 'xcan_write_frame' warning: Function parameter or member 'skb' not described in 'xcan_start_xmit_fifo' warning: Function parameter or member 'ndev' not described in 'xcan_start_xmit_fifo' warning: Function parameter or member 'skb' not described in 'xcan_start_xmit_mailbox' warning: Function parameter or member 'ndev' not described in 'xcan_start_xmit_mailbox' warning: Function parameter or member 'priv' not described in 'xcan_rx_fifo_get_next_frame' Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 1823f4fc448a..48a4c097a7d8 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -483,6 +483,7 @@ static int xcan_do_set_mode(struct net_device *ndev, enum can_mode mode) /** * xcan_write_frame - Write a frame to HW + * @priv: Driver private data structure * @skb: sk_buff pointer that contains data to be Txed * @frame_offset: Register offset to write the frame to */ @@ -544,6 +545,8 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, /** * xcan_start_xmit_fifo - Starts the transmission (FIFO mode) + * @skb: sk_buff pointer that contains data to be Txed + * @ndev: Pointer to net_device structure * * Return: 0 on success, -ENOSPC if FIFO is full. */ @@ -580,6 +583,8 @@ static int xcan_start_xmit_fifo(struct sk_buff *skb, struct net_device *ndev) /** * xcan_start_xmit_mailbox - Starts the transmission (mailbox mode) + * @skb: sk_buff pointer that contains data to be Txed + * @ndev: Pointer to net_device structure * * Return: 0 on success, -ENOSPC if there is no space */ @@ -960,6 +965,7 @@ static void xcan_state_interrupt(struct net_device *ndev, u32 isr) /** * xcan_rx_fifo_get_next_frame - Get register offset of next RX frame + * @priv: Driver private data structure * * Return: Register offset of the next frame in RX FIFO. */ -- GitLab From 3281b380ec9f8a9d89f58d5f5353c7e3b2046f93 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:42 +0530 Subject: [PATCH 0427/7155] can: xilinx_can: Fix flags field initialization for axi can and canps AXI CAN IP and CANPS IP supports tx fifo empty feature, this patch updates the flags field for the same. Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 48a4c097a7d8..0e3f3a536a1d 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1426,6 +1426,7 @@ static const struct dev_pm_ops xcan_dev_pm_ops = { }; static const struct xcan_devtype_data xcan_zynq_data = { + .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, .btr_sjw_shift = XCAN_BTR_SJW_SHIFT, @@ -1433,6 +1434,7 @@ static const struct xcan_devtype_data xcan_zynq_data = { }; static const struct xcan_devtype_data xcan_axi_data = { + .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, .btr_sjw_shift = XCAN_BTR_SJW_SHIFT, -- GitLab From 8dce7ea41a1e313cb1ba512b1098c7181ee0fd21 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:43 +0530 Subject: [PATCH 0428/7155] can: xilinx_can: Add cantype parameter in xcan_devtype_data struct To differentiate between different CAN IP's this patch adds cantype enum variable in the xcan_devtype_data structure Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 0e3f3a536a1d..e76418c94dae 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -149,7 +149,15 @@ enum xcan_reg { #define XCAN_FLAG_RX_FIFO_MULTI 0x0010 #define XCAN_FLAG_CANFD_2 0x0020 +enum xcan_ip_type { + XAXI_CAN = 0, + XZYNQ_CANPS, + XAXI_CANFD, + XAXI_CANFD_2_0, +}; + struct xcan_devtype_data { + enum xcan_ip_type cantype; unsigned int flags; const struct can_bittiming_const *bittiming_const; const char *bus_clk_name; @@ -1426,6 +1434,7 @@ static const struct dev_pm_ops xcan_dev_pm_ops = { }; static const struct xcan_devtype_data xcan_zynq_data = { + .cantype = XZYNQ_CANPS, .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, @@ -1434,6 +1443,7 @@ static const struct xcan_devtype_data xcan_zynq_data = { }; static const struct xcan_devtype_data xcan_axi_data = { + .cantype = XAXI_CAN, .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, @@ -1442,6 +1452,7 @@ static const struct xcan_devtype_data xcan_axi_data = { }; static const struct xcan_devtype_data xcan_canfd_data = { + .cantype = XAXI_CANFD, .flags = XCAN_FLAG_EXT_FILTERS | XCAN_FLAG_RXMNF | XCAN_FLAG_TX_MAILBOXES | @@ -1453,6 +1464,7 @@ static const struct xcan_devtype_data xcan_canfd_data = { }; static const struct xcan_devtype_data xcan_canfd2_data = { + .cantype = XAXI_CANFD_2_0, .flags = XCAN_FLAG_EXT_FILTERS | XCAN_FLAG_RXMNF | XCAN_FLAG_TX_MAILBOXES | -- GitLab From c223da689324f2ec669a3d10ac312a316410614b Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:44 +0530 Subject: [PATCH 0429/7155] can: xilinx_can: Add support for CANFD FD frames CANFD IP supports both CAN and CAN FD frames, Existing driver supports only CAN frames, This patch adds support for CAN FD frames. Signed-off-by: Naga Sureshkumar Relli Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 230 ++++++++++++++++++++++++++++++++--- 1 file changed, 214 insertions(+), 16 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index e76418c94dae..fadd54103c38 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -50,6 +50,10 @@ enum xcan_reg { XCAN_AFR_OFFSET = 0x60, /* Acceptance Filter */ /* only on CAN FD cores */ + XCAN_F_BRPR_OFFSET = 0x088, /* Data Phase Baud Rate + * Prescalar + */ + XCAN_F_BTR_OFFSET = 0x08C, /* Data Phase Bit Timing */ XCAN_TRR_OFFSET = 0x0090, /* TX Buffer Ready Request */ XCAN_AFR_EXT_OFFSET = 0x00E0, /* Acceptance Filter */ XCAN_FSR_OFFSET = 0x00E8, /* RX FIFO Status */ @@ -62,6 +66,8 @@ enum xcan_reg { #define XCAN_FRAME_DLC_OFFSET(frame_base) ((frame_base) + 0x04) #define XCAN_FRAME_DW1_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_FRAME_DW2_OFFSET(frame_base) ((frame_base) + 0x0C) +#define XCANFD_FRAME_DW_OFFSET(frame_base, n) (((frame_base) + 0x08) + \ + ((n) * XCAN_CANFD_FRAME_SIZE)) #define XCAN_CANFD_FRAME_SIZE 0x48 #define XCAN_TXMSG_FRAME_OFFSET(n) (XCAN_TXMSG_BASE_OFFSET + \ @@ -120,6 +126,8 @@ enum xcan_reg { #define XCAN_FSR_FL_MASK 0x00003F00 /* RX Fill Level */ #define XCAN_FSR_IRI_MASK 0x00000080 /* RX Increment Read Index */ #define XCAN_FSR_RI_MASK 0x0000001F /* RX Read Index */ +#define XCAN_DLCR_EDL_MASK 0x08000000 /* EDL Mask in DLC */ +#define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */ /* CAN register bit shift - XCAN___SHIFT */ #define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */ @@ -133,6 +141,7 @@ enum xcan_reg { /* CAN frame length constants */ #define XCAN_FRAME_MAX_DATA_LEN 8 +#define XCANFD_DW_BYTES 4 #define XCAN_TIMEOUT (1 * HZ) /* TX-FIFO-empty interrupt available */ @@ -213,6 +222,7 @@ static const struct can_bittiming_const xcan_bittiming_const = { .brp_inc = 1, }; +/* AXI CANFD Arbitration Bittiming constants as per AXI CANFD 1.0 spec */ static const struct can_bittiming_const xcan_bittiming_const_canfd = { .name = DRIVER_NAME, .tseg1_min = 1, @@ -225,6 +235,20 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd = { .brp_inc = 1, }; +/* AXI CANFD Data Bittiming constants as per AXI CANFD 1.0 specs */ +static struct can_bittiming_const xcan_data_bittiming_const_canfd = { + .name = DRIVER_NAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 8, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + +/* AXI CANFD 2.0 Arbitration Bittiming constants as per AXI CANFD 2.0 spec */ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { .name = DRIVER_NAME, .tseg1_min = 1, @@ -237,6 +261,19 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { .brp_inc = 1, }; +/* AXI CANFD 2.0 Data Bittiming constants as per AXI CANFD 2.0 spec */ +static struct can_bittiming_const xcan_data_bittiming_const_canfd2 = { + .name = DRIVER_NAME, + .tseg1_min = 1, + .tseg1_max = 32, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + /** * xcan_write_reg_le - Write a value to the device register little endian * @priv: Driver private data structure @@ -351,6 +388,7 @@ static int xcan_set_bittiming(struct net_device *ndev) { struct xcan_priv *priv = netdev_priv(ndev); struct can_bittiming *bt = &priv->can.bittiming; + struct can_bittiming *dbt = &priv->can.data_bittiming; u32 btr0, btr1; u32 is_config_mode; @@ -380,6 +418,24 @@ static int xcan_set_bittiming(struct net_device *ndev) priv->write_reg(priv, XCAN_BRPR_OFFSET, btr0); priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); + if (priv->devtype.cantype == XAXI_CANFD || + priv->devtype.cantype == XAXI_CANFD_2_0) { + /* Setting Baud Rate prescalar value in F_BRPR Register */ + btr0 = dbt->brp - 1; + + /* Setting Time Segment 1 in BTR Register */ + btr1 = dbt->prop_seg + bt->phase_seg1 - 1; + + /* Setting Time Segment 2 in BTR Register */ + btr1 |= (dbt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift; + + /* Setting Synchronous jump width in BTR Register */ + btr1 |= (dbt->sjw - 1) << priv->devtype.btr_sjw_shift; + + priv->write_reg(priv, XCAN_F_BRPR_OFFSET, btr0); + priv->write_reg(priv, XCAN_F_BTR_OFFSET, btr1); + } + netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", priv->read_reg(priv, XCAN_BRPR_OFFSET), priv->read_reg(priv, XCAN_BTR_OFFSET)); @@ -499,7 +555,8 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, int frame_offset) { u32 id, dlc, data[2] = {0, 0}; - struct can_frame *cf = (struct can_frame *)skb->data; + struct canfd_frame *cf = (struct canfd_frame *)skb->data; + u32 ramoff, dwindex = 0, i; /* Watch carefully on the bit sequence */ if (cf->can_id & CAN_EFF_FLAG) { @@ -528,26 +585,44 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, id |= XCAN_IDR_SRR_MASK; } - dlc = cf->can_dlc << XCAN_DLCR_DLC_SHIFT; - - if (cf->can_dlc > 0) - data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); - if (cf->can_dlc > 4) - data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); + dlc = can_len2dlc(cf->len) << XCAN_DLCR_DLC_SHIFT; + if (can_is_canfd_skb(skb)) { + if (cf->flags & CANFD_BRS) + dlc |= XCAN_DLCR_BRS_MASK; + dlc |= XCAN_DLCR_EDL_MASK; + } priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id); /* If the CAN frame is RTR frame this write triggers transmission * (not on CAN FD) */ priv->write_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_offset), dlc); - if (!(cf->can_id & CAN_RTR_FLAG)) { - priv->write_reg(priv, XCAN_FRAME_DW1_OFFSET(frame_offset), - data[0]); - /* If the CAN frame is Standard/Extended frame this - * write triggers transmission (not on CAN FD) - */ - priv->write_reg(priv, XCAN_FRAME_DW2_OFFSET(frame_offset), - data[1]); + if (priv->devtype.cantype == XAXI_CANFD || + priv->devtype.cantype == XAXI_CANFD_2_0) { + for (i = 0; i < cf->len; i += 4) { + ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset, dwindex) + + (dwindex * XCANFD_DW_BYTES); + priv->write_reg(priv, ramoff, + be32_to_cpup((__be32 *)(cf->data + i))); + dwindex++; + } + } else { + if (cf->len > 0) + data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); + if (cf->len > 4) + data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); + + if (!(cf->can_id & CAN_RTR_FLAG)) { + priv->write_reg(priv, + XCAN_FRAME_DW1_OFFSET(frame_offset), + data[0]); + /* If the CAN frame is Standard/Extended frame this + * write triggers transmission (not on CAN FD) + */ + priv->write_reg(priv, + XCAN_FRAME_DW2_OFFSET(frame_offset), + data[1]); + } } } @@ -724,6 +799,113 @@ static int xcan_rx(struct net_device *ndev, int frame_base) return 1; } +/** + * xcanfd_rx - Is called from CAN isr to complete the received + * frame processing + * @ndev: Pointer to net_device structure + * @frame_base: Register offset to the frame to be read + * + * This function is invoked from the CAN isr(poll) to process the Rx frames. It + * does minimal processing and invokes "netif_receive_skb" to complete further + * processing. + * Return: 1 on success and 0 on failure. + */ +static int xcanfd_rx(struct net_device *ndev, int frame_base) +{ + struct xcan_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &ndev->stats; + struct canfd_frame *cf; + struct sk_buff *skb; + u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; + + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + if (fsr & XCAN_FSR_FL_MASK) { + readindex = fsr & XCAN_FSR_RI_MASK; + id_xcan = priv->read_reg(priv, + XCAN_FRAME_ID_OFFSET(frame_base)); + dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); + if (dlc & XCAN_DLCR_EDL_MASK) + skb = alloc_canfd_skb(ndev, &cf); + else + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); + + if (unlikely(!skb)) { + stats->rx_dropped++; + return 0; + } + + /* Change Xilinx CANFD data length format to socketCAN data + * format + */ + if (dlc & XCAN_DLCR_EDL_MASK) + cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + else + cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + + /* Change Xilinx CAN ID format to socketCAN ID format */ + if (id_xcan & XCAN_IDR_IDE_MASK) { + /* The received frame is an Extended format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; + cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> + XCAN_IDR_ID2_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + if (id_xcan & XCAN_IDR_RTR_MASK) + cf->can_id |= CAN_RTR_FLAG; + } else { + /* The received frame is a standard format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> + XCAN_IDR_ID1_SHIFT; + if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & + XCAN_IDR_SRR_MASK)) + cf->can_id |= CAN_RTR_FLAG; + } + + /* Check the frame received is FD or not*/ + if (dlc & XCAN_DLCR_EDL_MASK) { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + + (dwindex * XCANFD_DW_BYTES))); + else + data[0] = priv->read_reg(priv, + (XCAN_RXMSG_FRAME_OFFSET(readindex) + + (dwindex * XCANFD_DW_BYTES))); + *(__be32 *)(cf->data + i) = + cpu_to_be32(data[0]); + dwindex++; + } + } else { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + XCAN_RXMSG_2_FRAME_OFFSET(readindex) + i); + else + data[0] = priv->read_reg(priv, + XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + *(__be32 *)(cf->data + i) = + cpu_to_be32(data[0]); + } + } + /* Update FSR Register so that next packet will save to + * buffer + */ + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + fsr |= XCAN_FSR_IRI_MASK; + priv->write_reg(priv, XCAN_FSR_OFFSET, fsr); + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + stats->rx_bytes += cf->len; + stats->rx_packets++; + netif_receive_skb(skb); + + return 1; + } + /* If FSR Register is not updated with fill level */ + return 0; +} + /** * xcan_current_error_state - Get current error state from HW * @ndev: Pointer to net_device structure @@ -1035,7 +1217,10 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) while ((frame_offset = xcan_rx_fifo_get_next_frame(priv)) >= 0 && (work_done < quota)) { - work_done += xcan_rx(ndev, frame_offset); + if (xcan_rx_int_mask(priv) & XCAN_IXR_RXOK_MASK) + work_done += xcanfd_rx(ndev, frame_offset); + else + work_done += xcan_rx(ndev, frame_offset); if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI) /* increment read index */ @@ -1577,6 +1762,19 @@ static int xcan_probe(struct platform_device *pdev) priv->can.do_get_berr_counter = xcan_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_BERR_REPORTING; + + if (devtype->cantype == XAXI_CANFD) + priv->can.data_bittiming_const = + &xcan_data_bittiming_const_canfd; + + if (devtype->cantype == XAXI_CANFD_2_0) + priv->can.data_bittiming_const = + &xcan_data_bittiming_const_canfd2; + + if (devtype->cantype == XAXI_CANFD || + devtype->cantype == XAXI_CANFD_2_0) + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + priv->reg_base = addr; priv->tx_max = tx_max; priv->devtype = *devtype; -- GitLab From 64d6ce8fe48e4768d3bcba7873a1a368162af334 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Jun 2019 17:45:17 +0100 Subject: [PATCH 0430/7155] can: xilinx_can: clean up indentation issue A statement is indented one level too deep, fix this. Signed-off-by: Colin Ian King Reviewed-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index fadd54103c38..bd95cfaff857 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1119,7 +1119,7 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; } } - priv->can.can_stats.bus_error++; + priv->can.can_stats.bus_error++; } if (skb) { -- GitLab From 26bca9fe5f1dcd9093f5ed17fcb78d1f6fb32e5e Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 12 Jun 2019 11:48:56 -0400 Subject: [PATCH 0431/7155] can: Kconfig: correct history of the CAN protocol Current history of CAN protocol is wrong, fix it in the Kconfig file. Signed-off-by: Robert P. J. Day Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/Kconfig | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/can/Kconfig b/net/can/Kconfig index 0f9fe846ddef..d4319aa3e1b1 100644 --- a/net/can/Kconfig +++ b/net/can/Kconfig @@ -8,11 +8,12 @@ menuconfig CAN tristate "CAN bus subsystem support" ---help--- Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial - communications protocol which was developed by Bosch in - 1991, mainly for automotive, but now widely used in marine - (NMEA2000), industrial, and medical applications. - More information on the CAN network protocol family PF_CAN - is contained in . + communications protocol. Development of the CAN bus started in + 1983 at Robert Bosch GmbH, and the protocol was officially + released in 1986. The CAN bus was originally mainly for automotive, + but is now widely used in marine (NMEA2000), industrial, and medical + applications. More information on the CAN network protocol family + PF_CAN is contained in . If you want CAN support you should say Y here and also to the specific driver for your controller(s) below. -- GitLab From ca10989632d8820749fad37e13843750198e450a Mon Sep 17 00:00:00 2001 From: Aisheng Dong Date: Fri, 30 Nov 2018 08:53:26 +0000 Subject: [PATCH 0432/7155] can: flexcan: implement can Runtime PM Flexcan will be disabled during suspend if no wakeup function required and enabled after resume accordingly. During this period, we could explicitly disable clocks. Since PM is optional, the clock is enabled at probe to guarante the clock is running when PM is not enabled in the kernel. Implement Runtime PM which will: 1) Without CONFIG_PM, clock is running whether Flexcan up or down. 2) With CONFIG_PM, clock enabled while Flexcan up and disabled when Flexcan down. 3) Disable clock when do system suspend and enable clock while system resume. 4) Make Power Domain framework be able to shutdown the corresponding power domain of this device. Signed-off-by: Aisheng Dong Signed-off-by: Joakim Zhang Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 119 ++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 38 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index f2fe344593d5..228ac5d1f3b4 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -266,6 +267,7 @@ struct flexcan_stop_mode { struct flexcan_priv { struct can_priv can; struct can_rx_offload offload; + struct device *dev; struct flexcan_regs __iomem *regs; struct flexcan_mb __iomem *tx_mb; @@ -444,6 +446,27 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv) priv->write(reg_ctrl, ®s->ctrl); } +static int flexcan_clks_enable(const struct flexcan_priv *priv) +{ + int err; + + err = clk_prepare_enable(priv->clk_ipg); + if (err) + return err; + + err = clk_prepare_enable(priv->clk_per); + if (err) + clk_disable_unprepare(priv->clk_ipg); + + return err; +} + +static void flexcan_clks_disable(const struct flexcan_priv *priv) +{ + clk_disable_unprepare(priv->clk_per); + clk_disable_unprepare(priv->clk_ipg); +} + static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) { if (!priv->reg_xceiver) @@ -570,19 +593,13 @@ static int flexcan_get_berr_counter(const struct net_device *dev, const struct flexcan_priv *priv = netdev_priv(dev); int err; - err = clk_prepare_enable(priv->clk_ipg); - if (err) + err = pm_runtime_get_sync(priv->dev); + if (err < 0) return err; - err = clk_prepare_enable(priv->clk_per); - if (err) - goto out_disable_ipg; - err = __flexcan_get_berr_counter(dev, bec); - clk_disable_unprepare(priv->clk_per); - out_disable_ipg: - clk_disable_unprepare(priv->clk_ipg); + pm_runtime_put(priv->dev); return err; } @@ -1215,17 +1232,13 @@ static int flexcan_open(struct net_device *dev) struct flexcan_priv *priv = netdev_priv(dev); int err; - err = clk_prepare_enable(priv->clk_ipg); - if (err) + err = pm_runtime_get_sync(priv->dev); + if (err < 0) return err; - err = clk_prepare_enable(priv->clk_per); - if (err) - goto out_disable_ipg; - err = open_candev(dev); if (err) - goto out_disable_per; + goto out_runtime_put; err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev); if (err) @@ -1288,10 +1301,8 @@ static int flexcan_open(struct net_device *dev) free_irq(dev->irq, dev); out_close: close_candev(dev); - out_disable_per: - clk_disable_unprepare(priv->clk_per); - out_disable_ipg: - clk_disable_unprepare(priv->clk_ipg); + out_runtime_put: + pm_runtime_put(priv->dev); return err; } @@ -1306,10 +1317,9 @@ static int flexcan_close(struct net_device *dev) can_rx_offload_del(&priv->offload); free_irq(dev->irq, dev); - clk_disable_unprepare(priv->clk_per); - clk_disable_unprepare(priv->clk_ipg); close_candev(dev); + pm_runtime_put(priv->dev); can_led_event(dev, CAN_LED_EVENT_STOP); @@ -1349,18 +1359,15 @@ static int register_flexcandev(struct net_device *dev) struct flexcan_regs __iomem *regs = priv->regs; u32 reg, err; - err = clk_prepare_enable(priv->clk_ipg); + err = flexcan_clks_enable(priv); if (err) return err; - err = clk_prepare_enable(priv->clk_per); - if (err) - goto out_disable_ipg; - /* select "bus clock", chip must be disabled */ err = flexcan_chip_disable(priv); if (err) - goto out_disable_per; + goto out_clks_disable; + reg = priv->read(®s->ctrl); reg |= FLEXCAN_CTRL_CLK_SRC; priv->write(reg, ®s->ctrl); @@ -1388,15 +1395,21 @@ static int register_flexcandev(struct net_device *dev) } err = register_candev(dev); + if (err) + goto out_chip_disable; - /* disable core and turn off clocks */ - out_chip_disable: + /* Disable core and let pm_runtime_put() disable the clocks. + * If CONFIG_PM is not enabled, the clocks will stay powered. + */ flexcan_chip_disable(priv); - out_disable_per: - clk_disable_unprepare(priv->clk_per); - out_disable_ipg: - clk_disable_unprepare(priv->clk_ipg); + pm_runtime_put(priv->dev); + + return 0; + out_chip_disable: + flexcan_chip_disable(priv); + out_clks_disable: + flexcan_clks_disable(priv); return err; } @@ -1556,6 +1569,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->write = flexcan_write_le; } + priv->dev = &pdev->dev; priv->can.clock.freq = clock_freq; priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.do_set_mode = flexcan_set_mode; @@ -1569,6 +1583,10 @@ static int flexcan_probe(struct platform_device *pdev) priv->devtype_data = devtype_data; priv->reg_xceiver = reg_xceiver; + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + err = register_flexcandev(dev); if (err) { dev_err(&pdev->dev, "registering netdev failed\n"); @@ -1595,6 +1613,7 @@ static int flexcan_remove(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); unregister_flexcandev(dev); + pm_runtime_disable(&pdev->dev); free_candev(dev); return 0; @@ -1604,7 +1623,7 @@ static int __maybe_unused flexcan_suspend(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); - int err; + int err = 0; if (netif_running(dev)) { /* if wakeup is enabled, enter stop mode @@ -1617,20 +1636,22 @@ static int __maybe_unused flexcan_suspend(struct device *device) err = flexcan_chip_disable(priv); if (err) return err; + + err = pm_runtime_force_suspend(device); } netif_stop_queue(dev); netif_device_detach(dev); } priv->can.state = CAN_STATE_SLEEPING; - return 0; + return err; } static int __maybe_unused flexcan_resume(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); - int err; + int err = 0; priv->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(dev)) { @@ -1639,14 +1660,35 @@ static int __maybe_unused flexcan_resume(struct device *device) if (device_may_wakeup(device)) { disable_irq_wake(dev->irq); } else { - err = flexcan_chip_enable(priv); + err = pm_runtime_force_resume(device); if (err) return err; + + err = flexcan_chip_enable(priv); } } + + return err; +} + +static int __maybe_unused flexcan_runtime_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct flexcan_priv *priv = netdev_priv(dev); + + flexcan_clks_disable(priv); + return 0; } +static int __maybe_unused flexcan_runtime_resume(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct flexcan_priv *priv = netdev_priv(dev); + + return flexcan_clks_enable(priv); +} + static int __maybe_unused flexcan_noirq_suspend(struct device *device) { struct net_device *dev = dev_get_drvdata(device); @@ -1673,6 +1715,7 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device) static const struct dev_pm_ops flexcan_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume) + SET_RUNTIME_PM_OPS(flexcan_runtime_suspend, flexcan_runtime_resume, NULL) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume) }; -- GitLab From 9d733992772dc04ce5e8839f867b4ff83ee75c34 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 13 Dec 2018 07:07:57 +0000 Subject: [PATCH 0433/7155] dt-bindings: can: flexcan: add PE clock source property to device tree The FlexCAN controller can parse clock source property from DTS file to select PE clock source. Signed-off-by: Dong Aisheng Signed-off-by: Joakim Zhang Signed-off-by: Marc Kleine-Budde --- Documentation/devicetree/bindings/net/can/fsl-flexcan.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index bc77477c6878..a04168605998 100644 --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -32,6 +32,13 @@ Optional properties: ack_gpr is the gpr register offset of CAN stop acknowledge. ack_bit is the bit offset of CAN stop acknowledge. +- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE). + It's SoC Implementation dependent. Refer to RM for detailed + definition. If this property is not set in device tree node + then driver selects clock source 1 by default. + 0: clock source 0 (oscillator clock) + 1: clock source 1 (peripheral clock) + Example: can@1c000 { @@ -40,4 +47,5 @@ Example: interrupts = <48 0x2>; interrupt-parent = <&mpic>; clock-frequency = <200000000>; // filled in by bootloader + fsl,clk-source = <0>; // select clock source 0 for PE }; -- GitLab From 8c306bec2d09c8436eea989b1be2a381cae93418 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 13 Dec 2018 07:08:00 +0000 Subject: [PATCH 0434/7155] can: flexcan: add support for PE clock source select Add support to select the clock source for CAN Protocol Engine (PE). It's SoC Implementation dependent. Refer to RM for detailed definition of each SoC. We select clock source 1 (peripheral clock) by default in driver now, this patch adds support to parse the clock source from the DT. Signed-off-by: Dong Aisheng Signed-off-by: Joakim Zhang Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 228ac5d1f3b4..bcc39512f342 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -275,6 +275,8 @@ struct flexcan_priv { u8 tx_mb_idx; u8 mb_count; u8 mb_size; + u8 clk_src; /* clock source of CAN Protocol Engine */ + u32 reg_ctrl_default; u32 reg_imask1_default; u32 reg_imask2_default; @@ -1369,7 +1371,10 @@ static int register_flexcandev(struct net_device *dev) goto out_clks_disable; reg = priv->read(®s->ctrl); - reg |= FLEXCAN_CTRL_CLK_SRC; + if (priv->clk_src) + reg |= FLEXCAN_CTRL_CLK_SRC; + else + reg &= ~FLEXCAN_CTRL_CLK_SRC; priv->write(reg, ®s->ctrl); err = flexcan_chip_enable(priv); @@ -1501,6 +1506,7 @@ static int flexcan_probe(struct platform_device *pdev) struct clk *clk_ipg = NULL, *clk_per = NULL; struct flexcan_regs __iomem *regs; int err, irq; + u8 clk_src = 1; u32 clock_freq = 0; reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); @@ -1509,9 +1515,12 @@ static int flexcan_probe(struct platform_device *pdev) else if (IS_ERR(reg_xceiver)) reg_xceiver = NULL; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_freq); + of_property_read_u8(pdev->dev.of_node, + "fsl,clk-source", &clk_src); + } if (!clock_freq) { clk_ipg = devm_clk_get(&pdev->dev, "ipg"); @@ -1580,6 +1589,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->regs = regs; priv->clk_ipg = clk_ipg; priv->clk_per = clk_per; + priv->clk_src = clk_src; priv->devtype_data = devtype_data; priv->reg_xceiver = reg_xceiver; -- GitLab From 10e0c525fc41c1a80d33e3075d6f7f5902e74bbd Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Tue, 9 Apr 2019 10:39:49 +0200 Subject: [PATCH 0435/7155] dt-bindings: can: flexcan: add can wakeup property This patch adds the wakeup-source boolean property. Signed-off-by: Sean Nyekjaer Reviewed-by: Rob Herring Signed-off-by: Marc Kleine-Budde --- Documentation/devicetree/bindings/net/can/fsl-flexcan.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index a04168605998..94c0f8bf4deb 100644 --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -39,6 +39,8 @@ Optional properties: 0: clock source 0 (oscillator clock) 1: clock source 1 (peripheral clock) +- wakeup-source: enable CAN remote wakeup + Example: can@1c000 { -- GitLab From 915f9666421cf65cc30668fd42760b6f78f9744d Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Tue, 9 Apr 2019 10:39:48 +0200 Subject: [PATCH 0436/7155] can: flexcan: add support for DT property 'wakeup-source' The flexcan controller can be forced as a wakeup source by stating that explicitly in the device's .dts file using the "wakeup-source" boolean property. Signed-off-by: Sean Nyekjaer Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index bcc39512f342..09d8e623dcf6 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1473,6 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); + if (of_property_read_bool(np, "wakeup-source")) + device_set_wakeup_enable(&pdev->dev, true); + return 0; } -- GitLab From 4c7f715485159ab8a55b9471fc6fd75db51fd623 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Mon, 29 Apr 2019 12:03:32 +0000 Subject: [PATCH 0437/7155] can: ti_hecc: use timestamp based rx-offloading As already mentioned in [1] and included in [2], there is an off by one issue since the high bank is already enabled when the _next_ mailbox to be read has index 12, so the mailbox being read was 13. The message can therefore go into mailbox 31 and the driver will be repolled until the mailbox 12 eventually receives a msg. Or the message might end up in the 12th mailbox, but then it would become disabled after reading it and only be enabled again in the next "round" after mailbox 13 was read, which can cause out of order messages, since the lower priority mailboxes can accept messages in the meantime. As mentioned in [3] there is a hardware race condition when changing the CANME register while messages are being received. Even when including a busy poll on reception, like in [2] there are still overflows and out of order messages at times, but less then without the busy loop polling. Unlike what the patch suggests, the polling time is not in the microsecond range, but takes as long as a current CAN bus reception needs to finish, so typically more in the fraction of millisecond range. Since the timeout is in jiffies it won't timeout. Even with these additional fixes the driver is still not able to provide a proper FIFO which doesn't drop packages. So change the driver to use rx-offload and base order on timestamp instead of message box numbers. As a side affect, this also fixes [4] and [5]. Before this change messages with a single byte counter were dropped / received out of order at a bitrate of 250kbit/s on an am3517. With this patch that no longer occurs up to and including 1Mbit/s. [1] https://linux-can.vger.kernel.narkive.com/zgO9inVi/patch-can-ti-hecc-fix-rx-wrong-sequence-issue#post6 [2] http://arago-project.org/git/projects/?p=linux-omap3.git;a=commit;h=02346892777f07245de4d5af692513ebd852dcb2 [3] https://linux-can.vger.kernel.narkive.com/zgO9inVi/patch-can-ti-hecc-fix-rx-wrong-sequence-issue#post5 [4] https://patchwork.ozlabs.org/patch/895956/ [5] https://www.spinics.net/lists/netdev/msg494971.html Cc: Anant Gole Cc: AnilKumar Ch Signed-off-by: Jeroen Hofstee Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 191 +++++++++++--------------------------- 1 file changed, 54 insertions(+), 137 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index db6ea936dc3f..b62f75fa03f0 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -5,6 +5,7 @@ * specs for the same is available at * * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2019 Jeroen Hofstee * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -34,6 +35,7 @@ #include #include #include +#include #define DRV_NAME "ti_hecc" #define HECC_MODULE_VERSION "0.7" @@ -63,29 +65,15 @@ MODULE_VERSION(HECC_MODULE_VERSION); #define HECC_TX_PRIO_MASK (MAX_TX_PRIO << HECC_MB_TX_SHIFT) #define HECC_TX_MB_MASK (HECC_MAX_TX_MBOX - 1) #define HECC_TX_MASK ((HECC_MAX_TX_MBOX - 1) | HECC_TX_PRIO_MASK) -#define HECC_TX_MBOX_MASK (~(BIT(HECC_MAX_TX_MBOX) - 1)) -#define HECC_DEF_NAPI_WEIGHT HECC_MAX_RX_MBOX -/* - * Important Note: RX mailbox configuration - * RX mailboxes are further logically split into two - main and buffer - * mailboxes. The goal is to get all packets into main mailboxes as - * driven by mailbox number and receive priority (higher to lower) and - * buffer mailboxes are used to receive pkts while main mailboxes are being - * processed. This ensures in-order packet reception. - * - * Here are the recommended values for buffer mailbox. Note that RX mailboxes - * start after TX mailboxes: +/* RX mailbox configuration * - * HECC_MAX_RX_MBOX HECC_RX_BUFFER_MBOX No of buffer mailboxes - * 28 12 8 - * 16 20 4 + * The remaining mailboxes are used for reception and are delivered + * based on their timestamp, to avoid a hardware race when CANME is + * changed while CAN-bus traffic is being received. */ - #define HECC_MAX_RX_MBOX (HECC_MAX_MAILBOXES - HECC_MAX_TX_MBOX) -#define HECC_RX_BUFFER_MBOX 12 /* as per table above */ #define HECC_RX_FIRST_MBOX (HECC_MAX_MAILBOXES - 1) -#define HECC_RX_HIGH_MBOX_MASK (~(BIT(HECC_RX_BUFFER_MBOX) - 1)) /* TI HECC module registers */ #define HECC_CANME 0x0 /* Mailbox enable */ @@ -117,6 +105,9 @@ MODULE_VERSION(HECC_MODULE_VERSION); #define HECC_CANTIOCE 0x68 /* SCC only:Enhanced TX I/O control */ #define HECC_CANRIOCE 0x6C /* SCC only:Enhanced RX I/O control */ +/* TI HECC RAM registers */ +#define HECC_CANMOTS 0x80 /* Message object time stamp */ + /* Mailbox registers */ #define HECC_CANMID 0x0 #define HECC_CANMCF 0x4 @@ -193,7 +184,7 @@ static const struct can_bittiming_const ti_hecc_bittiming_const = { struct ti_hecc_priv { struct can_priv can; /* MUST be first member/field */ - struct napi_struct napi; + struct can_rx_offload offload; struct net_device *ndev; struct clk *clk; void __iomem *base; @@ -203,7 +194,6 @@ struct ti_hecc_priv { spinlock_t mbx_lock; /* CANME register needs protection */ u32 tx_head; u32 tx_tail; - u32 rx_next; struct regulator *reg_xceiver; }; @@ -227,6 +217,11 @@ static inline void hecc_write_lam(struct ti_hecc_priv *priv, u32 mbxno, u32 val) __raw_writel(val, priv->hecc_ram + mbxno * 4); } +static inline u32 hecc_read_stamp(struct ti_hecc_priv *priv, u32 mbxno) +{ + return __raw_readl(priv->hecc_ram + HECC_CANMOTS + mbxno * 4); +} + static inline void hecc_write_mbx(struct ti_hecc_priv *priv, u32 mbxno, u32 reg, u32 val) { @@ -375,7 +370,6 @@ static void ti_hecc_start(struct net_device *ndev) ti_hecc_reset(ndev); priv->tx_head = priv->tx_tail = HECC_TX_MASK; - priv->rx_next = HECC_RX_FIRST_MBOX; /* Enable local and global acceptance mask registers */ hecc_write(priv, HECC_CANGAM, HECC_SET_REG); @@ -526,21 +520,17 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } -static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno) +static inline struct ti_hecc_priv *rx_offload_to_priv(struct can_rx_offload *offload) { - struct net_device_stats *stats = &priv->ndev->stats; - struct can_frame *cf; - struct sk_buff *skb; - u32 data, mbx_mask; - unsigned long flags; + return container_of(offload, struct ti_hecc_priv, offload); +} - skb = alloc_can_skb(priv->ndev, &cf); - if (!skb) { - if (printk_ratelimit()) - netdev_err(priv->ndev, - "ti_hecc_rx_pkt: alloc_can_skb() failed\n"); - return -ENOMEM; - } +static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload, + struct can_frame *cf, + u32 *timestamp, unsigned int mbxno) +{ + struct ti_hecc_priv *priv = rx_offload_to_priv(offload); + u32 data, mbx_mask; mbx_mask = BIT(mbxno); data = hecc_read_mbx(priv, mbxno, HECC_CANMID); @@ -558,100 +548,19 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno) data = hecc_read_mbx(priv, mbxno, HECC_CANMDH); *(__be32 *)(cf->data + 4) = cpu_to_be32(data); } - spin_lock_irqsave(&priv->mbx_lock, flags); - hecc_clear_bit(priv, HECC_CANME, mbx_mask); - hecc_write(priv, HECC_CANRMP, mbx_mask); - /* enable mailbox only if it is part of rx buffer mailboxes */ - if (priv->rx_next < HECC_RX_BUFFER_MBOX) - hecc_set_bit(priv, HECC_CANME, mbx_mask); - spin_unlock_irqrestore(&priv->mbx_lock, flags); - - stats->rx_bytes += cf->can_dlc; - can_led_event(priv->ndev, CAN_LED_EVENT_RX); - netif_receive_skb(skb); - stats->rx_packets++; - - return 0; -} - -/* - * ti_hecc_rx_poll - HECC receive pkts - * - * The receive mailboxes start from highest numbered mailbox till last xmit - * mailbox. On CAN frame reception the hardware places the data into highest - * numbered mailbox that matches the CAN ID filter. Since all receive mailboxes - * have same filtering (ALL CAN frames) packets will arrive in the highest - * available RX mailbox and we need to ensure in-order packet reception. - * - * To ensure the packets are received in the right order we logically divide - * the RX mailboxes into main and buffer mailboxes. Packets are received as per - * mailbox priotity (higher to lower) in the main bank and once it is full we - * disable further reception into main mailboxes. While the main mailboxes are - * processed in NAPI, further packets are received in buffer mailboxes. - * - * We maintain a RX next mailbox counter to process packets and once all main - * mailboxe packets are passed to the upper stack we enable all of them but - * continue to process packets received in buffer mailboxes. With each packet - * received from buffer mailbox we enable it immediately so as to handle the - * overflow from higher mailboxes. - */ -static int ti_hecc_rx_poll(struct napi_struct *napi, int quota) -{ - struct net_device *ndev = napi->dev; - struct ti_hecc_priv *priv = netdev_priv(ndev); - u32 num_pkts = 0; - u32 mbx_mask; - unsigned long pending_pkts, flags; - - if (!netif_running(ndev)) - return 0; - - while ((pending_pkts = hecc_read(priv, HECC_CANRMP)) && - num_pkts < quota) { - mbx_mask = BIT(priv->rx_next); /* next rx mailbox to process */ - if (mbx_mask & pending_pkts) { - if (ti_hecc_rx_pkt(priv, priv->rx_next) < 0) - return num_pkts; - ++num_pkts; - } else if (priv->rx_next > HECC_RX_BUFFER_MBOX) { - break; /* pkt not received yet */ - } - --priv->rx_next; - if (priv->rx_next == HECC_RX_BUFFER_MBOX) { - /* enable high bank mailboxes */ - spin_lock_irqsave(&priv->mbx_lock, flags); - mbx_mask = hecc_read(priv, HECC_CANME); - mbx_mask |= HECC_RX_HIGH_MBOX_MASK; - hecc_write(priv, HECC_CANME, mbx_mask); - spin_unlock_irqrestore(&priv->mbx_lock, flags); - } else if (priv->rx_next == HECC_MAX_TX_MBOX - 1) { - priv->rx_next = HECC_RX_FIRST_MBOX; - break; - } - } - /* Enable packet interrupt if all pkts are handled */ - if (hecc_read(priv, HECC_CANRMP) == 0) { - napi_complete(napi); - /* Re-enable RX mailbox interrupts */ - mbx_mask = hecc_read(priv, HECC_CANMIM); - mbx_mask |= HECC_TX_MBOX_MASK; - hecc_write(priv, HECC_CANMIM, mbx_mask); - } else { - /* repoll is done only if whole budget is used */ - num_pkts = quota; - } + *timestamp = hecc_read_stamp(priv, mbxno); - return num_pkts; + return 1; } static int ti_hecc_error(struct net_device *ndev, int int_status, int err_status) { struct ti_hecc_priv *priv = netdev_priv(ndev); - struct net_device_stats *stats = &ndev->stats; struct can_frame *cf; struct sk_buff *skb; + u32 timestamp; /* propagate the error condition to the can stack */ skb = alloc_can_err_skb(ndev, &cf); @@ -732,9 +641,8 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } } - stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; - netif_rx(skb); + timestamp = hecc_read(priv, HECC_CANLNT); + can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); return 0; } @@ -744,8 +652,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) struct net_device *ndev = (struct net_device *)dev_id; struct ti_hecc_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; - u32 mbxno, mbx_mask, int_status, err_status; - unsigned long ack, flags; + u32 mbxno, mbx_mask, int_status, err_status, stamp; + unsigned long flags, rx_pending; int_status = hecc_read(priv, (priv->use_hecc1int) ? HECC_CANGIF1 : HECC_CANGIF0); @@ -769,11 +677,11 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) spin_lock_irqsave(&priv->mbx_lock, flags); hecc_clear_bit(priv, HECC_CANME, mbx_mask); spin_unlock_irqrestore(&priv->mbx_lock, flags); - stats->tx_bytes += hecc_read_mbx(priv, mbxno, - HECC_CANMCF) & 0xF; + stamp = hecc_read_stamp(priv, mbxno); + stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload, + mbxno, stamp); stats->tx_packets++; can_led_event(ndev, CAN_LED_EVENT_TX); - can_get_echo_skb(ndev, mbxno); --priv->tx_tail; } @@ -784,12 +692,11 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) ((priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK))) netif_wake_queue(ndev); - /* Disable RX mailbox interrupts and let NAPI reenable them */ - if (hecc_read(priv, HECC_CANRMP)) { - ack = hecc_read(priv, HECC_CANMIM); - ack &= BIT(HECC_MAX_TX_MBOX) - 1; - hecc_write(priv, HECC_CANMIM, ack); - napi_schedule(&priv->napi); + /* offload RX mailboxes and let NAPI deliver them */ + while ((rx_pending = hecc_read(priv, HECC_CANRMP))) { + can_rx_offload_irq_offload_timestamp(&priv->offload, + rx_pending); + hecc_write(priv, HECC_CANRMP, rx_pending); } } @@ -831,7 +738,7 @@ static int ti_hecc_open(struct net_device *ndev) can_led_event(ndev, CAN_LED_EVENT_OPEN); ti_hecc_start(ndev); - napi_enable(&priv->napi); + can_rx_offload_enable(&priv->offload); netif_start_queue(ndev); return 0; @@ -842,7 +749,7 @@ static int ti_hecc_close(struct net_device *ndev) struct ti_hecc_priv *priv = netdev_priv(ndev); netif_stop_queue(ndev); - napi_disable(&priv->napi); + can_rx_offload_disable(&priv->offload); ti_hecc_stop(ndev); free_irq(ndev->irq, ndev); close_candev(ndev); @@ -962,8 +869,6 @@ static int ti_hecc_probe(struct platform_device *pdev) goto probe_exit_candev; } priv->can.clock.freq = clk_get_rate(priv->clk); - netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll, - HECC_DEF_NAPI_WEIGHT); err = clk_prepare_enable(priv->clk); if (err) { @@ -971,10 +876,19 @@ static int ti_hecc_probe(struct platform_device *pdev) goto probe_exit_clk; } + priv->offload.mailbox_read = ti_hecc_mailbox_read; + priv->offload.mb_first = HECC_RX_FIRST_MBOX; + priv->offload.mb_last = HECC_MAX_TX_MBOX; + err = can_rx_offload_add_timestamp(ndev, &priv->offload); + if (err) { + dev_err(&pdev->dev, "can_rx_offload_add_timestamp() failed\n"); + goto probe_exit_clk; + } + err = register_candev(ndev); if (err) { dev_err(&pdev->dev, "register_candev() failed\n"); - goto probe_exit_clk; + goto probe_exit_offload; } devm_can_led_init(ndev); @@ -984,6 +898,8 @@ static int ti_hecc_probe(struct platform_device *pdev) return 0; +probe_exit_offload: + can_rx_offload_del(&priv->offload); probe_exit_clk: clk_put(priv->clk); probe_exit_candev: @@ -1000,6 +916,7 @@ static int ti_hecc_remove(struct platform_device *pdev) unregister_candev(ndev); clk_disable_unprepare(priv->clk); clk_put(priv->clk); + can_rx_offload_del(&priv->offload); free_candev(ndev); return 0; -- GitLab From 60649d4e0af6c26b6c423dea9c57f39e823fc0c5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 23 Jul 2019 14:08:47 +0200 Subject: [PATCH 0438/7155] can: remove obsolete empty ioctl() handler With commit c7cbdbf29f488a ("net: rework SIOCGSTAMP ioctl handling") the only ioctl function in can_ioctl() has been removed. As this SIOCGSTAMP ioctl command is now handled in net/socket.c we can entirely remove the CAN specific ioctl functions. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/linux/can/core.h | 1 - net/can/af_can.c | 9 --------- net/can/bcm.c | 2 +- net/can/raw.c | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/include/linux/can/core.h b/include/linux/can/core.h index 6099bc18bd0c..f8284a94a13d 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -57,6 +57,5 @@ extern void can_rx_unregister(struct net *net, struct net_device *dev, void *data); extern int can_send(struct sk_buff *skb, int loop); -extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); #endif /* !_CAN_CORE_H */ diff --git a/net/can/af_can.c b/net/can/af_can.c index 80281ef2ccbd..9c86de2da45e 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -87,15 +87,6 @@ static atomic_t skbcounter = ATOMIC_INIT(0); * af_can socket functions */ -int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - default: - return -ENOIOCTLCMD; - } -} -EXPORT_SYMBOL(can_ioctl); - static void can_sock_destruct(struct sock *sk) { skb_queue_purge(&sk->sk_receive_queue); diff --git a/net/can/bcm.c b/net/can/bcm.c index a34ee52f19ea..1eecf4d3e8d2 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1688,7 +1688,7 @@ static const struct proto_ops bcm_ops = { .accept = sock_no_accept, .getname = sock_no_getname, .poll = datagram_poll, - .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ + .ioctl = sock_no_ioctl, .gettstamp = sock_gettstamp, .listen = sock_no_listen, .shutdown = sock_no_shutdown, diff --git a/net/can/raw.c b/net/can/raw.c index afcbff063a67..bbbe3dd0abe9 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -845,7 +845,7 @@ static const struct proto_ops raw_ops = { .accept = sock_no_accept, .getname = raw_getname, .poll = datagram_poll, - .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ + .ioctl = sock_no_ioctl, .gettstamp = sock_gettstamp, .listen = sock_no_listen, .shutdown = sock_no_shutdown, -- GitLab From fba76a58452694b9b13c07e48839fa84c75f57af Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 23 Jul 2019 15:17:55 +0200 Subject: [PATCH 0439/7155] can: Add SPDX license identifiers for CAN subsystem Add missing SPDX identifiers for the CAN network layer and correct the SPDX license for two of its include files to make sure the BSD-3-Clause applies for the entire subsystem. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/linux/can/core.h | 2 +- include/linux/can/skb.h | 2 +- net/can/af_can.c | 1 + net/can/af_can.h | 1 + net/can/bcm.c | 1 + net/can/gw.c | 1 + net/can/proc.c | 1 + net/can/raw.c | 1 + 8 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/can/core.h b/include/linux/can/core.h index f8284a94a13d..708c10d3417a 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * linux/can/core.h * diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index b3379a97245c..a954def26c0d 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * linux/can/skb.h * diff --git a/net/can/af_can.c b/net/can/af_can.c index 9c86de2da45e..76cf83b2bd40 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * af_can.c - Protocol family CAN core module * (used by different CAN protocol modules) diff --git a/net/can/af_can.h b/net/can/af_can.h index 9cb3719632bd..ef21f7c6bc80 100644 --- a/net/can/af_can.h +++ b/net/can/af_can.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. diff --git a/net/can/bcm.c b/net/can/bcm.c index 1eecf4d3e8d2..8da986b19d88 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) /* * bcm.c - Broadcast Manager to filter/send (cyclic) CAN content * diff --git a/net/can/gw.c b/net/can/gw.c index 5275ddf580bc..8abae841d504 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) /* * gw.c - CAN frame Gateway/Router/Bridge with netlink interface * diff --git a/net/can/proc.c b/net/can/proc.c index 70fea17bb04c..edb822c31902 100644 --- a/net/can/proc.c +++ b/net/can/proc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) /* * proc.c - procfs support for Protocol family CAN core module * diff --git a/net/can/raw.c b/net/can/raw.c index bbbe3dd0abe9..ff720272f7b7 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) /* * raw.c - Raw sockets for protocol family CAN * -- GitLab From a104dbc527551bda0d97db493a2d3d31e3076d4f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 20:40:21 +0300 Subject: [PATCH 0440/7155] extcon: arizona: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Charles Keepax Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 7e9f4c9ee87d..e970134c95fa 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1253,7 +1253,7 @@ static int arizona_extcon_get_micd_configs(struct device *dev, int i, j; u32 *vals; - nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0); + nconfs = device_property_count_u32(arizona->dev, prop); if (nconfs <= 0) return 0; -- GitLab From a6d9cfcb853f32cda972841dace0060e9508ac7a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:01 +0200 Subject: [PATCH 0441/7155] extcon: extcon-max77843: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77843.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index a343a6ef3506..e6b50ca83008 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -774,12 +774,12 @@ static int max77843_init_muic_regmap(struct max77693_dev *max77843) { int ret; - max77843->i2c_muic = i2c_new_dummy(max77843->i2c->adapter, + max77843->i2c_muic = i2c_new_dummy_device(max77843->i2c->adapter, I2C_ADDR_MUIC); - if (!max77843->i2c_muic) { + if (IS_ERR(max77843->i2c_muic)) { dev_err(&max77843->i2c->dev, "Cannot allocate I2C device for MUIC\n"); - return -ENOMEM; + return PTR_ERR(max77843->i2c_muic); } i2c_set_clientdata(max77843->i2c_muic, max77843); -- GitLab From 6527c6856faca69b3abcc2dbed0a00ea40ca8e16 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 23 Jul 2019 19:43:01 +0200 Subject: [PATCH 0442/7155] extcon: fsa9480: Support the FSA880 variant The older compatible variant of this chip is called FSA880 and works the same way, if we need some quirks in the future, it is good to let it have its own compatible string. Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Signed-off-by: Chanwoo Choi --- Documentation/devicetree/bindings/extcon/extcon-fsa9480.txt | 4 +++- drivers/extcon/extcon-fsa9480.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/extcon/extcon-fsa9480.txt b/Documentation/devicetree/bindings/extcon/extcon-fsa9480.txt index d592c21245f2..624bd76f468e 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-fsa9480.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-fsa9480.txt @@ -5,7 +5,9 @@ controlled using I2C and enables USB data, stereo and mono audio, video, microphone, and UART data to use a common connector port. Required properties: - - compatible : Must be "fcs,fsa9480" + - compatible : Must be one of + "fcs,fsa9480" + "fcs,fsa880" - reg : Specifies i2c slave address. Must be 0x25. - interrupts : Should contain one entry specifying interrupt signal of interrupt parent to which interrupt pin of the chip is connected. diff --git a/drivers/extcon/extcon-fsa9480.c b/drivers/extcon/extcon-fsa9480.c index 350fb34abfa0..8405512f5199 100644 --- a/drivers/extcon/extcon-fsa9480.c +++ b/drivers/extcon/extcon-fsa9480.c @@ -363,6 +363,7 @@ MODULE_DEVICE_TABLE(i2c, fsa9480_id); static const struct of_device_id fsa9480_of_match[] = { { .compatible = "fcs,fsa9480", }, + { .compatible = "fcs,fsa880", }, { }, }; MODULE_DEVICE_TABLE(of, fsa9480_of_match); -- GitLab From 7d2b02275e89d564ddb0ace09ef4aa9e2ac2973d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 24 Jul 2019 10:49:14 +0100 Subject: [PATCH 0443/7155] extcon: arizona: Update binding example to use available defines Signed-off-by: Charles Keepax Signed-off-by: Chanwoo Choi --- Documentation/devicetree/bindings/extcon/extcon-arizona.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt index 7f3d94ae81ff..208daaff0be4 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt @@ -72,5 +72,5 @@ codec: wm8280@0 { 1 2 1 /* MICDET2 MICBIAS2 GPIO=high */ >; - wlf,gpsw = <0>; + wlf,gpsw = ; }; -- GitLab From 8bc4810b435a3338346efd70e94c4d6fd0863635 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 30 May 2019 20:39:32 +0200 Subject: [PATCH 0444/7155] extcon: gpio: Request reasonable interrupts The only thing that makes sense is to request a falling edge interrupt if the line is active low and a rising edge interrupt if the line is active high, so just do that and get rid of the assignment from platform data. The GPIO descriptor knows if the line is active high or low. Also make irq a local variable in probe(), it's not used anywhere else. Signed-off-by: Linus Walleij [cw00.choi: Fix build error of data->irq_flags] Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-gpio.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index faddeac948db..c211222f5d0c 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -22,26 +22,22 @@ /** * struct gpio_extcon_data - A simple GPIO-controlled extcon device state container. * @edev: Extcon device. - * @irq: Interrupt line for the external connector. * @work: Work fired by the interrupt. * @debounce_jiffies: Number of jiffies to wait for the GPIO to stabilize, from the debounce * value. * @gpiod: GPIO descriptor for this external connector. * @extcon_id: The unique id of specific external connector. * @debounce: Debounce time for GPIO IRQ in ms. - * @irq_flags: IRQ Flags (e.g., IRQF_TRIGGER_LOW). * @check_on_resume: Boolean describing whether to check the state of gpio * while resuming from sleep. */ struct gpio_extcon_data { struct extcon_dev *edev; - int irq; struct delayed_work work; unsigned long debounce_jiffies; struct gpio_desc *gpiod; unsigned int extcon_id; unsigned long debounce; - unsigned long irq_flags; bool check_on_resume; }; @@ -69,6 +65,8 @@ static int gpio_extcon_probe(struct platform_device *pdev) { struct gpio_extcon_data *data; struct device *dev = &pdev->dev; + unsigned long irq_flags; + int irq; int ret; data = devm_kzalloc(dev, sizeof(struct gpio_extcon_data), GFP_KERNEL); @@ -82,15 +80,26 @@ static int gpio_extcon_probe(struct platform_device *pdev) * developed to get the extcon id from device-tree or others. * On later, it have to be solved. */ - if (!data->irq_flags || data->extcon_id > EXTCON_NONE) + if (data->extcon_id > EXTCON_NONE) return -EINVAL; data->gpiod = devm_gpiod_get(dev, "extcon", GPIOD_IN); if (IS_ERR(data->gpiod)) return PTR_ERR(data->gpiod); - data->irq = gpiod_to_irq(data->gpiod); - if (data->irq <= 0) - return data->irq; + irq = gpiod_to_irq(data->gpiod); + if (irq <= 0) + return irq; + + /* + * It is unlikely that this is an acknowledged interrupt that goes + * away after handling, what we are looking for are falling edges + * if the signal is active low, and rising edges if the signal is + * active high. + */ + if (gpiod_is_active_low(data->gpiod)) + irq_flags = IRQF_TRIGGER_FALLING; + else + irq_flags = IRQF_TRIGGER_RISING; /* Allocate the memory of extcon devie and register extcon device */ data->edev = devm_extcon_dev_allocate(dev, &data->extcon_id); @@ -109,8 +118,8 @@ static int gpio_extcon_probe(struct platform_device *pdev) * Request the interrupt of gpio to detect whether external connector * is attached or detached. */ - ret = devm_request_any_context_irq(dev, data->irq, - gpio_irq_handler, data->irq_flags, + ret = devm_request_any_context_irq(dev, irq, + gpio_irq_handler, irq_flags, pdev->name, data); if (ret < 0) return ret; -- GitLab From 005ad18727b489eb9fd6182f8941042e274387dc Mon Sep 17 00:00:00 2001 From: Vasyl Gomonovych Date: Fri, 19 Jul 2019 18:28:06 +0200 Subject: [PATCH 0445/7155] extcon: sm5502: Add IRQ_ONESHOT Do not fire irq again until thread done Signed-off-by: Vasyl Gomonovych Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-sm5502.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 98e4f616b8f1..dc43847ad2b0 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -597,7 +597,7 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c, ret = devm_request_threaded_irq(info->dev, virq, NULL, sm5502_muic_irq_handler, - IRQF_NO_SUSPEND, + IRQF_NO_SUSPEND | IRQF_ONESHOT, muic_irq->name, info); if (ret) { dev_err(info->dev, -- GitLab From 231e83fdcd03bce4f5c71fc318cbdbe65bd2b80b Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Thu, 27 Jun 2019 16:30:02 +0200 Subject: [PATCH 0446/7155] rsi: return explicit error values Explicitly return constants instead of variable (and rely on it to be explicitly initialized), if the value is supposed to be fixed anyways. Align it with the rest of the driver, which does it the same way. Signed-off-by: Enrico Weigelt Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index b42cd50b837e..2a3577d8fb61 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -844,11 +844,11 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter, struct sdio_func *pfunction) { struct rsi_91x_sdiodev *rsi_91x_dev; - int status = -ENOMEM; + int status; rsi_91x_dev = kzalloc(sizeof(*rsi_91x_dev), GFP_KERNEL); if (!rsi_91x_dev) - return status; + return -ENOMEM; adapter->rsi_dev = rsi_91x_dev; @@ -890,7 +890,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter, #ifdef CONFIG_RSI_DEBUGFS adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES; #endif - return status; + return 0; fail: sdio_disable_func(pfunction); sdio_release_host(pfunction); -- GitLab From 3b902fa811cf6bf7f9ad0ffb77d0a133e0b3bd61 Mon Sep 17 00:00:00 2001 From: Soeren Moch Date: Mon, 1 Jul 2019 12:53:14 +0200 Subject: [PATCH 0447/7155] rt2x00usb: remove unnecessary rx flag checks In contrast to the TX path, there is no need to separately read the transfer status from the device after receiving RX data. Consequently, there is no real STATUS_PENDING RX processing queue entry state. Remove the unnecessary ENTRY_DATA_STATUS_PENDING flag checks from the RX path. Also remove the misleading comment about reading RX status from device. Suggested-by: Stanislaw Gruszka Signed-off-by: Soeren Moch Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c index 7e3a621b9c0d..bc2dfef0de22 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c @@ -349,8 +349,7 @@ static void rt2x00usb_work_rxdone(struct work_struct *work) while (!rt2x00queue_empty(rt2x00dev->rx)) { entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || - !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) break; /* @@ -389,8 +388,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) rt2x00lib_dmadone(entry); /* - * Schedule the delayed work for reading the RX status - * from the device. + * Schedule the delayed work for processing RX data */ queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); } @@ -402,8 +400,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) struct queue_entry_priv_usb *entry_priv = entry->priv_data; int status; - if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || - test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) + if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return false; rt2x00lib_dmastart(entry); -- GitLab From 1dc244064c47d6df7925ca0895f8365e68d3abd1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 3 Jul 2019 13:39:56 +0200 Subject: [PATCH 0448/7155] rt2x00: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Because we don't need to save the individual debugfs files and directories, remove the local storage of them and just remove the entire debugfs directory in a single call, making things a lot simpler. Cc: Stanislaw Gruszka Cc: Helmut Schaa Cc: Kalle Valo Cc: "David S. Miller" Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- .../net/wireless/ralink/rt2x00/rt2x00debug.c | 136 +++++------------- 1 file changed, 35 insertions(+), 101 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index ef5f51512212..4d4e3888ef20 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -65,26 +65,6 @@ struct rt2x00debug_intf { * - crypto stats file */ struct dentry *driver_folder; - struct dentry *driver_entry; - struct dentry *chipset_entry; - struct dentry *dev_flags; - struct dentry *cap_flags; - struct dentry *restart_hw; - struct dentry *register_folder; - struct dentry *csr_off_entry; - struct dentry *csr_val_entry; - struct dentry *eeprom_off_entry; - struct dentry *eeprom_val_entry; - struct dentry *bbp_off_entry; - struct dentry *bbp_val_entry; - struct dentry *rf_off_entry; - struct dentry *rf_val_entry; - struct dentry *rfcsr_off_entry; - struct dentry *rfcsr_val_entry; - struct dentry *queue_folder; - struct dentry *queue_frame_dump_entry; - struct dentry *queue_stats_entry; - struct dentry *crypto_stats_entry; /* * The frame dump file only allows a single reader, @@ -596,39 +576,34 @@ static const struct file_operations rt2x00debug_restart_hw = { .llseek = generic_file_llseek, }; -static struct dentry *rt2x00debug_create_file_driver(const char *name, - struct rt2x00debug_intf - *intf, - struct debugfs_blob_wrapper - *blob) +static void rt2x00debug_create_file_driver(const char *name, + struct rt2x00debug_intf *intf, + struct debugfs_blob_wrapper *blob) { char *data; data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL); if (!data) - return NULL; + return; blob->data = data; data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); data += sprintf(data, "version:\t%s\n", DRV_VERSION); blob->size = strlen(blob->data); - return debugfs_create_blob(name, 0400, intf->driver_folder, blob); + debugfs_create_blob(name, 0400, intf->driver_folder, blob); } -static struct dentry *rt2x00debug_create_file_chipset(const char *name, - struct rt2x00debug_intf - *intf, - struct - debugfs_blob_wrapper - *blob) +static void rt2x00debug_create_file_chipset(const char *name, + struct rt2x00debug_intf *intf, + struct debugfs_blob_wrapper *blob) { const struct rt2x00debug *debug = intf->debug; char *data; data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL); if (!data) - return NULL; + return; blob->data = data; data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); @@ -654,13 +629,15 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, blob->size = strlen(blob->data); - return debugfs_create_blob(name, 0400, intf->driver_folder, blob); + debugfs_create_blob(name, 0400, intf->driver_folder, blob); } void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) { const struct rt2x00debug *debug = rt2x00dev->ops->debugfs; struct rt2x00debug_intf *intf; + struct dentry *queue_folder; + struct dentry *register_folder; intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL); if (!intf) { @@ -676,43 +653,27 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) debugfs_create_dir(intf->rt2x00dev->ops->name, rt2x00dev->hw->wiphy->debugfsdir); - intf->driver_entry = - rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); + rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); + rt2x00debug_create_file_chipset("chipset", intf, &intf->chipset_blob); + debugfs_create_file("dev_flags", 0400, intf->driver_folder, intf, + &rt2x00debug_fop_dev_flags); + debugfs_create_file("cap_flags", 0400, intf->driver_folder, intf, + &rt2x00debug_fop_cap_flags); + debugfs_create_file("restart_hw", 0200, intf->driver_folder, intf, + &rt2x00debug_restart_hw); - intf->chipset_entry = - rt2x00debug_create_file_chipset("chipset", - intf, &intf->chipset_blob); - - intf->dev_flags = debugfs_create_file("dev_flags", 0400, - intf->driver_folder, intf, - &rt2x00debug_fop_dev_flags); - - intf->cap_flags = debugfs_create_file("cap_flags", 0400, - intf->driver_folder, intf, - &rt2x00debug_fop_cap_flags); - - intf->restart_hw = debugfs_create_file("restart_hw", 0200, - intf->driver_folder, intf, - &rt2x00debug_restart_hw); - - intf->register_folder = - debugfs_create_dir("register", intf->driver_folder); + register_folder = debugfs_create_dir("register", intf->driver_folder); #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ ({ \ if (debug->__name.read) { \ - (__intf)->__name##_off_entry = \ - debugfs_create_u32(__stringify(__name) "_offset", \ - 0600, \ - (__intf)->register_folder, \ - &(__intf)->offset_##__name); \ + debugfs_create_u32(__stringify(__name) "_offset", 0600, \ + register_folder, \ + &(__intf)->offset_##__name); \ \ - (__intf)->__name##_val_entry = \ - debugfs_create_file(__stringify(__name) "_value", \ - 0600, \ - (__intf)->register_folder, \ - (__intf), \ - &rt2x00debug_fop_##__name); \ + debugfs_create_file(__stringify(__name) "_value", 0600, \ + register_folder, (__intf), \ + &rt2x00debug_fop_##__name); \ } \ }) @@ -724,26 +685,21 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY - intf->queue_folder = - debugfs_create_dir("queue", intf->driver_folder); + queue_folder = debugfs_create_dir("queue", intf->driver_folder); - intf->queue_frame_dump_entry = - debugfs_create_file("dump", 0400, intf->queue_folder, - intf, &rt2x00debug_fop_queue_dump); + debugfs_create_file("dump", 0400, queue_folder, intf, + &rt2x00debug_fop_queue_dump); skb_queue_head_init(&intf->frame_dump_skbqueue); init_waitqueue_head(&intf->frame_dump_waitqueue); - intf->queue_stats_entry = - debugfs_create_file("queue", 0400, intf->queue_folder, - intf, &rt2x00debug_fop_queue_stats); + debugfs_create_file("queue", 0400, queue_folder, intf, + &rt2x00debug_fop_queue_stats); #ifdef CONFIG_RT2X00_LIB_CRYPTO if (rt2x00_has_cap_hw_crypto(rt2x00dev)) - intf->crypto_stats_entry = - debugfs_create_file("crypto", 0444, intf->queue_folder, - intf, - &rt2x00debug_fop_crypto_stats); + debugfs_create_file("crypto", 0444, queue_folder, intf, + &rt2x00debug_fop_crypto_stats); #endif return; @@ -758,29 +714,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) skb_queue_purge(&intf->frame_dump_skbqueue); -#ifdef CONFIG_RT2X00_LIB_CRYPTO - debugfs_remove(intf->crypto_stats_entry); -#endif - debugfs_remove(intf->queue_stats_entry); - debugfs_remove(intf->queue_frame_dump_entry); - debugfs_remove(intf->queue_folder); - debugfs_remove(intf->rfcsr_val_entry); - debugfs_remove(intf->rfcsr_off_entry); - debugfs_remove(intf->rf_val_entry); - debugfs_remove(intf->rf_off_entry); - debugfs_remove(intf->bbp_val_entry); - debugfs_remove(intf->bbp_off_entry); - debugfs_remove(intf->eeprom_val_entry); - debugfs_remove(intf->eeprom_off_entry); - debugfs_remove(intf->csr_val_entry); - debugfs_remove(intf->csr_off_entry); - debugfs_remove(intf->register_folder); - debugfs_remove(intf->dev_flags); - debugfs_remove(intf->restart_hw); - debugfs_remove(intf->cap_flags); - debugfs_remove(intf->chipset_entry); - debugfs_remove(intf->driver_entry); - debugfs_remove(intf->driver_folder); + debugfs_remove_recursive(intf->driver_folder); kfree(intf->chipset_blob.data); kfree(intf->driver_blob.data); kfree(intf); -- GitLab From 18e714687bea7f9f5155625aec04e335c0022128 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Thu, 4 Jul 2019 18:55:28 +0800 Subject: [PATCH 0449/7155] rtl8xxxu: Fix wifi low signal strength issue of RTL8723BU The WiFi tx power of RTL8723BU is extremely low after booting. So the WiFi scan gives very limited AP list and it always fails to connect to the selected AP. This module only supports 1x1 antenna and the antenna is switched to bluetooth due to some incorrect register settings. Compare with the vendor driver https://github.com/lwfinger/rtl8723bu, we realized that the 8723bu's enable_rf() does the same thing as rtw_btcoex_HAL_Initialize() in vendor driver. And it by default sets the antenna path to BTC_ANT_PATH_BT which we verified it's the cause of the wifi weak tx power. The vendor driver will set the antenna path to BTC_ANT_PATH_PTA in the consequent btcoexist mechanism, by the function halbtc8723b1ant_PsTdma. This commit hand over the antenna control to PTA(Packet Traffic Arbitration), which compares the weight of bluetooth/wifi traffic then determine whether to continue current wifi traffic or not. After PTA take control, The wifi signal will be back to normal and the bluetooth scan can also work at the same time. However, the btcoexist still needs to be handled under different circumstances. If there's a BT connection established, the wifi still fails to connect until BT disconnected. Signed-off-by: Chris Chiu Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c | 11 ++++++++--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 3adb1d3d47ac..ceffe05bd65b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -1525,7 +1525,7 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) /* * WLAN action by PTA */ - rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x04); + rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x0c); /* * BT select S0/S1 controlled by WiFi @@ -1568,9 +1568,14 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.ant_sel_rsv)); /* - * 0x280, 0x00, 0x200, 0x80 - not clear + * Different settings per different antenna position. + * Antenna Position: | Normal Inverse + * -------------------------------------------------- + * Antenna switch to BT: | 0x280, 0x00 + * Antenna switch to WiFi: | 0x0, 0x280 + * Antenna switch to PTA: | 0x200, 0x80 */ - rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); + rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x80); /* * Software control, antenna at WiFi side diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 8136e268b4e6..c6c41fb962ff 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -3891,12 +3891,13 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* Check if MAC is already powered on */ val8 = rtl8xxxu_read8(priv, REG_CR); + val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); /* * Fix 92DU-VC S3 hang with the reason is that secondary mac is not * initialized. First MAC returns 0xea, second MAC returns 0x00 */ - if (val8 == 0xea) + if (val8 == 0xea || !(val16 & SYS_CLK_MAC_CLK_ENABLE)) macpower = false; else macpower = true; -- GitLab From 4c8a468510196ff0a2c5ea28e8c27cd543a95861 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 09:17:34 +0100 Subject: [PATCH 0450/7155] libertas: remove redundant assignment to variable ret The variable ret is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 5968852b65a7..2233b59cdf44 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -1046,7 +1046,7 @@ int lbs_rtap_supported(struct lbs_private *priv) int lbs_start_card(struct lbs_private *priv) { struct net_device *dev = priv->dev; - int ret = -1; + int ret; /* poke the firmware */ ret = lbs_setup_firmware(priv); -- GitLab From c032461936de82a3f4108cacc7c3d1b204c42eef Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 11:37:32 +0100 Subject: [PATCH 0451/7155] wl3501_cs: remove redundant variable rc The variable rc is being initialized with a value that is never read and it is being updated later with a new value that is returned. The variable is redundant and can be replaced with a return 0 as there are no other return points in this function. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/wl3501_cs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index a25b17932edb..007bf6803293 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1226,7 +1226,6 @@ static int wl3501_init_firmware(struct wl3501_card *this) static int wl3501_close(struct net_device *dev) { struct wl3501_card *this = netdev_priv(dev); - int rc = -ENODEV; unsigned long flags; struct pcmcia_device *link; link = this->p_dev; @@ -1241,10 +1240,9 @@ static int wl3501_close(struct net_device *dev) /* Mask interrupts from the SUTRO */ wl3501_block_interrupt(this); - rc = 0; printk(KERN_INFO "%s: WL3501 closed\n", dev->name); spin_unlock_irqrestore(&this->lock, flags); - return rc; + return 0; } /** -- GitLab From 5ff29d836d1beb347080bd96e6321c811a8e3f62 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Jul 2019 22:04:22 -0700 Subject: [PATCH 0452/7155] rtw88: Fix misuse of GENMASK macro Arguments are supposed to be ordered high then low. Signed-off-by: Joe Perches Acked-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/rtw8822b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 1172f6c0605b..d61d534396c7 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -997,7 +997,7 @@ static void rtw8822b_do_iqk(struct rtw_dev *rtwdev) rtw_write_rf(rtwdev, RF_PATH_A, RF_DTXLOK, RFREG_MASK, 0x0); reload = !!rtw_read32_mask(rtwdev, REG_IQKFAILMSK, BIT(16)); - iqk_fail_mask = rtw_read32_mask(rtwdev, REG_IQKFAILMSK, GENMASK(0, 7)); + iqk_fail_mask = rtw_read32_mask(rtwdev, REG_IQKFAILMSK, GENMASK(7, 0)); rtw_dbg(rtwdev, RTW_DBG_PHY, "iqk counter=%d reload=%d do_iqk_cnt=%d n_iqk_fail(mask)=0x%02x\n", counter, reload, ++do_iqk_cnt, iqk_fail_mask); -- GitLab From 764f3f1ecffc434096e0a2b02f1a6cc964a89df6 Mon Sep 17 00:00:00 2001 From: Kevin Easton Date: Wed, 10 Jul 2019 13:31:38 +0000 Subject: [PATCH 0453/7155] libertas: Add missing sentinel at end of if_usb.c fw_table This sentinel tells the firmware loading process when to stop. Reported-and-tested-by: syzbot+98156c174c5a2cad9f8f@syzkaller.appspotmail.com Signed-off-by: Kevin Easton Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/if_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index afac2481909b..20436a289d5c 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -50,7 +50,8 @@ static const struct lbs_fw_table fw_table[] = { { MODEL_8388, "libertas/usb8388_v5.bin", NULL }, { MODEL_8388, "libertas/usb8388.bin", NULL }, { MODEL_8388, "usb8388.bin", NULL }, - { MODEL_8682, "libertas/usb8682.bin", NULL } + { MODEL_8682, "libertas/usb8682.bin", NULL }, + { 0, NULL, NULL } }; static const struct usb_device_id if_usb_table[] = { -- GitLab From ee6db78f5db9bfe426c57a1ec9713827ebccd2d4 Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Thu, 11 Jul 2019 13:24:26 +0800 Subject: [PATCH 0454/7155] rtw88: pci: Rearrange the memory usage for skb in RX ISR Testing with RTL8822BE hardware, when available memory is low, we frequently see a kernel panic and system freeze. First, rtw_pci_rx_isr encounters a memory allocation failure (trimmed): rx routine starvation WARNING: CPU: 7 PID: 9871 at drivers/net/wireless/realtek/rtw88/pci.c:822 rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci] [ 2356.580313] RIP: 0010:rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci] Then we see a variety of different error conditions and kernel panics, such as this one (trimmed): rtw_pci 0000:02:00.0: pci bus timeout, check dma status skbuff: skb_over_panic: text:00000000091b6e66 len:415 put:415 head:00000000d2880c6f data:000000007a02b1ea tail:0x1df end:0xc0 dev: ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:105! invalid opcode: 0000 [#1] SMP NOPTI RIP: 0010:skb_panic+0x43/0x45 When skb allocation fails and the "rx routine starvation" is hit, the function returns immediately without updating the RX ring. At this point, the RX ring may continue referencing an old skb which was already handed off to ieee80211_rx_irqsafe(). When it comes to be used again, bad things happen. This patch allocates a new, data-sized skb first in RX ISR. After copying the data in, we pass it to the upper layers. However, if skb allocation fails, we effectively drop the frame. In both cases, the original, full size ring skb is reused. In addition, to fixing the kernel crash, the RX routine should now generally behave better under low memory conditions. Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204053 Signed-off-by: Jian-Hong Pan Cc: Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 49 +++++++++++------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 353871c27779..5da9e9e44024 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -765,6 +765,7 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, u32 pkt_offset; u32 pkt_desc_sz = chip->rx_pkt_desc_sz; u32 buf_desc_sz = chip->rx_buf_desc_sz; + u32 new_len; u8 *rx_desc; dma_addr_t dma; @@ -792,40 +793,34 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + pkt_stat.shift; - if (pkt_stat.is_c2h) { - /* keep rx_desc, halmac needs it */ - skb_put(skb, pkt_stat.pkt_len + pkt_offset); + /* allocate a new skb for this frame, + * discard the frame if none available + */ + new_len = pkt_stat.pkt_len + pkt_offset; + new = dev_alloc_skb(new_len); + if (WARN_ONCE(!new, "rx routine starvation\n")) + goto next_rp; + + /* put the DMA data including rx_desc from phy to new skb */ + skb_put_data(new, skb->data, new_len); - /* pass offset for further operation */ - *((u32 *)skb->cb) = pkt_offset; - skb_queue_tail(&rtwdev->c2h_queue, skb); + if (pkt_stat.is_c2h) { + /* pass rx_desc & offset for further operation */ + *((u32 *)new->cb) = pkt_offset; + skb_queue_tail(&rtwdev->c2h_queue, new); ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work); } else { - /* remove rx_desc, maybe use skb_pull? */ - skb_put(skb, pkt_stat.pkt_len); - skb_reserve(skb, pkt_offset); - - /* alloc a smaller skb to mac80211 */ - new = dev_alloc_skb(pkt_stat.pkt_len); - if (!new) { - new = skb; - } else { - skb_put_data(new, skb->data, skb->len); - dev_kfree_skb_any(skb); - } - /* TODO: merge into rx.c */ - rtw_rx_stats(rtwdev, pkt_stat.vif, skb); + /* remove rx_desc */ + skb_pull(new, pkt_offset); + + rtw_rx_stats(rtwdev, pkt_stat.vif, new); memcpy(new->cb, &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(rtwdev->hw, new); } - /* skb delivered to mac80211, alloc a new one in rx ring */ - new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE); - if (WARN(!new, "rx routine starvation\n")) - return; - - ring->buf[cur_rp] = new; - rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz); +next_rp: + /* new skb delivered to mac80211, re-enable original skb DMA */ + rtw_pci_reset_rx_desc(rtwdev, skb, ring, cur_rp, buf_desc_sz); /* host read next element in ring */ if (++cur_rp >= ring->r.len) -- GitLab From 29b68a920f6abb7b5ba21ab4b779f62d536bac9b Mon Sep 17 00:00:00 2001 From: Jian-Hong Pan Date: Thu, 11 Jul 2019 13:24:27 +0800 Subject: [PATCH 0455/7155] rtw88: pci: Use DMA sync instead of remapping in RX ISR Since each skb in RX ring is reused instead of new allocation, we can treat the DMA in a more efficient way by DMA synchronization. Signed-off-by: Jian-Hong Pan Cc: Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 5da9e9e44024..23dd06afef3d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -206,6 +206,23 @@ static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, return 0; } +static void rtw_pci_sync_rx_desc_device(struct rtw_dev *rtwdev, dma_addr_t dma, + struct rtw_pci_rx_ring *rx_ring, + u32 idx, u32 desc_sz) +{ + struct device *dev = rtwdev->dev; + struct rtw_pci_rx_buffer_desc *buf_desc; + int buf_sz = RTK_PCI_RX_BUF_SIZE; + + dma_sync_single_for_device(dev, dma, buf_sz, DMA_FROM_DEVICE); + + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + + idx * desc_sz); + memset(buf_desc, 0, sizeof(*buf_desc)); + buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE); + buf_desc->dma = cpu_to_le32(dma); +} + static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, struct rtw_pci_rx_ring *rx_ring, u8 desc_size, u32 len) @@ -784,8 +801,8 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, rtw_pci_dma_check(rtwdev, ring, cur_rp); skb = ring->buf[cur_rp]; dma = *((dma_addr_t *)skb->cb); - pci_unmap_single(rtwpci->pdev, dma, RTK_PCI_RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); + dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE, + DMA_FROM_DEVICE); rx_desc = skb->data; chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); @@ -820,7 +837,8 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, next_rp: /* new skb delivered to mac80211, re-enable original skb DMA */ - rtw_pci_reset_rx_desc(rtwdev, skb, ring, cur_rp, buf_desc_sz); + rtw_pci_sync_rx_desc_device(rtwdev, dma, ring, cur_rp, + buf_desc_sz); /* host read next element in ring */ if (++cur_rp >= ring->r.len) -- GitLab From f491645f039420fb7e14283e21b90772571c807c Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 10:45:30 +0200 Subject: [PATCH 0456/7155] brcmfmac: add 160MHz in chandef_to_chanspec() The function chandef_to_chanspec() was not handling 160MHz bandwidth resulting in wrong encoding of the channel. That resulting in firmware rejecting the provided channel specification. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b6d0df354b36..5168d42a331e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -276,8 +276,26 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, else ch_inf.sb = BRCMU_CHAN_SB_UU; break; - case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: + ch_inf.bw = BRCMU_CHAN_BW_160; + if (primary_offset == -70) + ch_inf.sb = BRCMU_CHAN_SB_LLL; + else if (primary_offset == -50) + ch_inf.sb = BRCMU_CHAN_SB_LLU; + else if (primary_offset == -30) + ch_inf.sb = BRCMU_CHAN_SB_LUL; + else if (primary_offset == -10) + ch_inf.sb = BRCMU_CHAN_SB_LUU; + else if (primary_offset == 10) + ch_inf.sb = BRCMU_CHAN_SB_ULL; + else if (primary_offset == 30) + ch_inf.sb = BRCMU_CHAN_SB_ULU; + else if (primary_offset == 50) + ch_inf.sb = BRCMU_CHAN_SB_UUL; + else + ch_inf.sb = BRCMU_CHAN_SB_UUU; + break; + case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: default: @@ -296,6 +314,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, } d11inf->encchspec(&ch_inf); + brcmf_dbg(TRACE, "chanspec: 0x%x\n", ch_inf.chspec); return ch_inf.chspec; } -- GitLab From 011a56a3336a5de9c3152c169cd52ff79b8c3f89 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 10:45:31 +0200 Subject: [PATCH 0457/7155] brcmfmac: enable DFS_OFFLOAD extended feature if supported If the firmware supports 802.11h and the device can operate in 5GHz band we can enable DFS_OFFLOAD extended feature. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 5168d42a331e..3f72dc1e1dd5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6733,6 +6733,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) } } + if (wiphy->bands[NL80211_BAND_5GHZ] && + brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DOT11H)) + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_DFS_OFFLOAD); + wiphy_read_of_freq_limits(wiphy); return 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 73aff4e4039d..2c3526aeca6f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -39,6 +39,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = { { BRCMF_FEAT_P2P, "p2p" }, { BRCMF_FEAT_MONITOR, "monitor" }, { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" }, + { BRCMF_FEAT_DOT11H, "802.11h" } }; #ifdef DEBUG diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index f127eb2030a6..736a8179f62f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h @@ -25,6 +25,7 @@ * MONITOR: firmware can pass monitor packets to host. * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header + * DOT11H: firmware supports 802.11h */ #define BRCMF_FEAT_LIST \ BRCMF_FEAT_DEF(MBSS) \ @@ -43,7 +44,8 @@ BRCMF_FEAT_DEF(FWSUP) \ BRCMF_FEAT_DEF(MONITOR) \ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \ - BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) + BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \ + BRCMF_FEAT_DEF(DOT11H) /* * Quirks: -- GitLab From fa9050927fa885410055ee03c948c2252693d296 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 10:45:32 +0200 Subject: [PATCH 0458/7155] brcmfmac: allow 160MHz in custom regulatory rules The driver has custom regulatory rules which had maximum bandwidth for 5GHz channels set to 80MHz. As a consequence the driver can not use 160MHz in AP mode even when the device supports it. So relax the rules allowing 160MHz. After wiphy_register() the channel flags are updated according what the device actually supports. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 3f72dc1e1dd5..b692689bce53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -189,9 +189,9 @@ static const struct ieee80211_regdomain brcmf_regdom = { */ REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), /* IEEE 802.11a, channel 36..64 */ - REG_RULE(5150-10, 5350+10, 80, 6, 20, 0), + REG_RULE(5150-10, 5350+10, 160, 6, 20, 0), /* IEEE 802.11a, channel 100..165 */ - REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), } + REG_RULE(5470-10, 5850+10, 160, 6, 20, 0), } }; /* Note: brcmf_cipher_suites is an array of int defining which cipher suites -- GitLab From a84a60ccdd65278485fb495f468a5ab91a75c649 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:06 +0200 Subject: [PATCH 0459/7155] Revert "brcmfmac: fix NULL pointer derefence during USB disconnect" This reverts commit 5cdb0ef6144f47440850553579aa923c20a63f23. Subsequent changes make rework the driver code fixing the issue differently. Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++--------- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.h | 6 ++---- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 4 +--- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 16 ++++------------ .../broadcom/brcm80211/brcmfmac/fwsignal.h | 3 +-- .../wireless/broadcom/brcm80211/brcmfmac/proto.c | 10 ++-------- .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 3 +-- 7 files changed, 13 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 322e913ca7aa..2c95a08a5871 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -479,18 +479,11 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) return -ENOMEM; } -void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) -{ - struct brcmf_bcdc *bcdc = drvr->proto->pd; - - brcmf_fws_detach_pre_delif(bcdc->fws); -} - -void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc = drvr->proto->pd; drvr->proto->pd = NULL; - brcmf_fws_detach_post_delif(bcdc->fws); + brcmf_fws_detach(bcdc->fws); kfree(bcdc); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h index 102e6938905c..b051d2860cd1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h @@ -7,16 +7,14 @@ #ifdef CONFIG_BRCMFMAC_PROTO_BCDC int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state); void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp, bool success); struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr); #else static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; } -static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {}; -static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {} +static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {} #endif #endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index bf18491a33a5..fda604426e46 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1314,8 +1314,6 @@ void brcmf_detach(struct device *dev) brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); - brcmf_proto_detach_pre_delif(drvr); - /* make sure primary interface removed last */ for (i = BRCMF_MAX_IFS-1; i > -1; i--) brcmf_remove_interface(drvr->iflist[i], false); @@ -1325,7 +1323,7 @@ void brcmf_detach(struct device *dev) brcmf_bus_stop(drvr->bus_if); - brcmf_proto_detach_post_delif(drvr); + brcmf_proto_detach(drvr); bus_if->drvr = NULL; wiphy_free(drvr->wiphy); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index b8452cb46297..2bd892df83cc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -2432,25 +2432,17 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) return fws; fail: - brcmf_fws_detach_pre_delif(fws); - brcmf_fws_detach_post_delif(fws); + brcmf_fws_detach(fws); return ERR_PTR(rc); } -void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws) +void brcmf_fws_detach(struct brcmf_fws_info *fws) { if (!fws) return; - if (fws->fws_wq) { - destroy_workqueue(fws->fws_wq); - fws->fws_wq = NULL; - } -} -void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws) -{ - if (!fws) - return; + if (fws->fws_wq) + destroy_workqueue(fws->fws_wq); /* cleanup */ brcmf_fws_lock(fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index 10184eeaad94..b486d578ec96 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -7,8 +7,7 @@ #define FWSIGNAL_H_ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr); -void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws); -void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws); +void brcmf_fws_detach(struct brcmf_fws_info *fws); void brcmf_fws_debugfs_create(struct brcmf_pub *drvr); bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index e3d1b075044b..2e911d4874af 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -56,22 +56,16 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) return -ENOMEM; } -void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr) +void brcmf_proto_detach(struct brcmf_pub *drvr) { brcmf_dbg(TRACE, "Enter\n"); if (drvr->proto) { if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) - brcmf_proto_bcdc_detach_post_delif(drvr); + brcmf_proto_bcdc_detach(drvr); else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) brcmf_proto_msgbuf_detach(drvr); kfree(drvr->proto); drvr->proto = NULL; } } - -void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr) -{ - if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) - brcmf_proto_bcdc_detach_pre_delif(drvr); -} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index 8d55fad531d0..bd08d3aaa8f4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -43,8 +43,7 @@ struct brcmf_proto { int brcmf_proto_attach(struct brcmf_pub *drvr); -void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr); -void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr); +void brcmf_proto_detach(struct brcmf_pub *drvr); static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, struct sk_buff *skb, -- GitLab From 14fcfd1cc0c05ea58f47dd693fdd13f25dfe995e Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:07 +0200 Subject: [PATCH 0460/7155] brcmfmac: change the order of things in brcmf_detach() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When brcmf_detach() from the bus layer upon rmmod we can no longer communicate. Hence we will set the bus state to DOWN and cleanup the event and protocol layer. The network interfaces need to be deleted before brcmf_cfg80211_detach() because the latter does the wiphy_unregister() which issues a warning if there are still network devices linked to the wiphy instance. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Tested-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/core.c | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index fda604426e46..80d54d236a75 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1307,25 +1307,26 @@ void brcmf_detach(struct device *dev) unregister_inet6addr_notifier(&drvr->inet6addr_notifier); #endif - /* stop firmware event handling */ - brcmf_fweh_detach(drvr); - if (drvr->config) - brcmf_p2p_detach(&drvr->config->p2p); - brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); - - /* make sure primary interface removed last */ - for (i = BRCMF_MAX_IFS-1; i > -1; i--) - brcmf_remove_interface(drvr->iflist[i], false); - - brcmf_cfg80211_detach(drvr->config); - drvr->config = NULL; - brcmf_bus_stop(drvr->bus_if); + brcmf_fweh_detach(drvr); brcmf_proto_detach(drvr); + /* make sure primary interface removed last */ + for (i = BRCMF_MAX_IFS - 1; i > -1; i--) { + if (drvr->iflist[i]) + brcmf_del_if(drvr, drvr->iflist[i]->bsscfgidx, false); + } + + if (drvr->config) { + brcmf_p2p_detach(&drvr->config->p2p); + brcmf_cfg80211_detach(drvr->config); + drvr->config = NULL; + } + bus_if->drvr = NULL; + wiphy_free(drvr->wiphy); } -- GitLab From c613085b74941024194e41b200601b9aa6ee388f Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:08 +0200 Subject: [PATCH 0461/7155] brcmfmac: avoid firmware command in brcmf_netdev_open() when bus is down No point in sending a firmware command when bus is down so make it conditional checking the state. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 80d54d236a75..705b8cc53c3e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -579,7 +579,8 @@ static int brcmf_netdev_stop(struct net_device *ndev) brcmf_cfg80211_down(ndev); - brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); + if (ifp->drvr->bus_if->state == BRCMF_BUS_UP) + brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); brcmf_net_setcarrier(ifp, false); -- GitLab From c33330ac06fe863289643e7a13ecdb6a2502dad7 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:09 +0200 Subject: [PATCH 0462/7155] brcmfmac: clear events in brcmf_fweh_detach() will always fail Clearing firmware events in brcmf_fweh_detach() is always failing because it is called only upon driver remove and communication with firmware is no longer possible. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index adedd4fac10b..79c8a858b6d6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -303,16 +303,7 @@ void brcmf_fweh_attach(struct brcmf_pub *drvr) void brcmf_fweh_detach(struct brcmf_pub *drvr) { struct brcmf_fweh_info *fweh = &drvr->fweh; - struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); - s8 eventmask[BRCMF_EVENTING_MASK_LEN]; - if (ifp) { - /* clear all events */ - memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN); - (void)brcmf_fil_iovar_data_set(ifp, "event_msgs", - eventmask, - BRCMF_EVENTING_MASK_LEN); - } /* cancel the worker */ cancel_work_sync(&fweh->event_work); WARN_ON(!list_empty(&fweh->event_q)); -- GitLab From 1ac11ae949dd883854f4523ef8e3a32aabfd6256 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:10 +0200 Subject: [PATCH 0463/7155] brcmfmac: avoid firmware commands when bus is down Upon rmmod a few attempts are made to inform firmware, but there is no point as the bus is down and these will fail. Avoid them to keep the logs clean. Reported-by: Stefan Wahren Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b692689bce53..a5447519e1ab 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -1286,17 +1286,21 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); struct brcmf_pub *drvr = cfg->pub; + bool bus_up = drvr->bus_if->state == BRCMF_BUS_UP; s32 err = 0; brcmf_dbg(TRACE, "Enter\n"); if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) { - brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n"); - err = brcmf_fil_cmd_data_set(vif->ifp, - BRCMF_C_DISASSOC, NULL, 0); - if (err) { - bphy_err(drvr, "WLC_DISASSOC failed (%d)\n", err); + if (bus_up) { + brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n"); + err = brcmf_fil_cmd_data_set(vif->ifp, + BRCMF_C_DISASSOC, NULL, 0); + if (err) + bphy_err(drvr, "WLC_DISASSOC failed (%d)\n", + err); } + if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) || (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0, @@ -1306,7 +1310,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0); if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { - brcmf_set_pmk(vif->ifp, NULL, 0); + if (bus_up) + brcmf_set_pmk(vif->ifp, NULL, 0); vif->profile.use_fwsup = BRCMF_PROFILE_FWSUP_NONE; } brcmf_dbg(TRACE, "Exit\n"); @@ -5004,18 +5009,16 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = wdev->netdev; struct brcmf_pub *drvr = cfg->pub; - struct brcmf_if *ifp; struct brcmu_chan ch; enum nl80211_band band = 0; enum nl80211_chan_width width = 0; u32 chanspec; int freq, err; - if (!ndev) + if (!ndev || drvr->bus_if->state != BRCMF_BUS_UP) return -ENODEV; - ifp = netdev_priv(ndev); - err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec); + err = brcmf_fil_iovar_int_get(netdev_priv(ndev), "chanspec", &chanspec); if (err) { bphy_err(drvr, "chanspec failed (%d)\n", err); return err; -- GitLab From e0bfb9601d4812719167cc4124a0d6db1e2f55e4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:11 +0200 Subject: [PATCH 0464/7155] brcmfmac: simply remove flowring if bus is down When the bus is down, eg. due to rmmod, there is no need to attempt to inform firmware about it. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 241747bd5cb2..8428be8b8d43 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1398,6 +1398,13 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) u8 ifidx; int err; + /* no need to submit if firmware can not be reached */ + if (drvr->bus_if->state != BRCMF_BUS_UP) { + brcmf_dbg(MSGBUF, "bus down, flowring will be removed\n"); + brcmf_msgbuf_remove_flowring(msgbuf, flowid); + return; + } + commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT]; brcmf_commonring_lock(commonring); ret_ptr = brcmf_commonring_reserve_for_write(commonring); -- GitLab From 4b11c915f00caeef3292ed0429acc579b9da762a Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 11 Jul 2019 11:05:12 +0200 Subject: [PATCH 0465/7155] brcmfmac: remove unnecessary strlcpy() upon obtaining "ver" iovar Recently a strcpy() was replaced by strlcpy(). However, the strcpy() was not needed in the first place. So removing that line of code. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index aa89d620ee5d..dec25e415619 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -258,7 +258,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); - strlcpy(buf, "ver", sizeof(buf)); err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); if (err < 0) { bphy_err(drvr, "Retrieving version information failed, %d\n", -- GitLab From f0248ec49bdeeba29ec2ec238ba54c4c287033a8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 12 Jul 2019 14:09:50 +0200 Subject: [PATCH 0466/7155] mt7601u: use params->ssn value directly There is no point to use pointer to params->ssn. Signed-off-by: Stanislaw Gruszka Acked-by: Jakub Kicinski Signed-off-by: Kalle Valo --- drivers/net/wireless/mediatek/mt7601u/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index 89a7b1234ffb..72e608cc53af 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -351,7 +351,7 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; - u16 *ssn = ¶ms->ssn; + u16 ssn = params->ssn; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; WARN_ON(msta->wcid.idx > GROUP_WCID(0)); @@ -371,7 +371,7 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: break; case IEEE80211_AMPDU_TX_START: - msta->agg_ssn[tid] = *ssn << 4; + msta->agg_ssn[tid] = ssn << 4; ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: -- GitLab From 9a29f7d8476c143ddbb9ecca614b66d2842c25d8 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sat, 13 Jul 2019 00:45:35 +0530 Subject: [PATCH 0467/7155] rtlwifi: btcoex: fix issue possible condition with no effect (if == else) fix below issue reported by coccicheck drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c:514:1-3: WARNING: possible condition with no effect (if == else) Signed-off-by: Hariprasad Kelam Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index 152242ac0aa5..191dafd03189 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -509,13 +509,7 @@ static u32 halbtc_get_wifi_link_status(struct btc_coexist *btcoexist) static s32 halbtc_get_wifi_rssi(struct rtl_priv *rtlpriv) { - int undec_sm_pwdb = 0; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - else /* associated entry pwdb */ - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - return undec_sm_pwdb; + return rtlpriv->dm.undec_sm_pwdb; } static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) -- GitLab From 8812022cb2fdaa1c6d7e0c3e028b45ca039650ea Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Tue, 16 Jul 2019 13:28:20 +0800 Subject: [PATCH 0468/7155] rtw88: debug: dump tx power indexes in use Add a read entry in debugfs to dump current tx power indexes in use for each path and each rate section. The corresponding power bases, power by rate, and power limit are also included. Also this patch fixes unused function warning. Fixes: b741422218ef ("rtw88: refine flow to get tx power index") Signed-off-by: Zong-Zhe Yang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/debug.c | 112 +++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index f0ae26018f97..383b04c16703 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -8,6 +8,7 @@ #include "sec.h" #include "fw.h" #include "debug.h" +#include "phy.h" #ifdef CONFIG_RTW88_DEBUGFS @@ -460,6 +461,112 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) return 0; } +static void rtw_print_cck_rate_txt(struct seq_file *m, u8 rate) +{ + static const char * const + cck_rate[] = {"1M", "2M", "5.5M", "11M"}; + u8 idx = rate - DESC_RATE1M; + + seq_printf(m, " CCK_%-5s", cck_rate[idx]); +} + +static void rtw_print_ofdm_rate_txt(struct seq_file *m, u8 rate) +{ + static const char * const + ofdm_rate[] = {"6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M"}; + u8 idx = rate - DESC_RATE6M; + + seq_printf(m, " OFDM_%-4s", ofdm_rate[idx]); +} + +static void rtw_print_ht_rate_txt(struct seq_file *m, u8 rate) +{ + u8 mcs_n = rate - DESC_RATEMCS0; + + seq_printf(m, " MCS%-6u", mcs_n); +} + +static void rtw_print_vht_rate_txt(struct seq_file *m, u8 rate) +{ + u8 idx = rate - DESC_RATEVHT1SS_MCS0; + u8 n_ss, mcs_n; + + /* n spatial stream */ + n_ss = 1 + idx / 10; + /* MCS n */ + mcs_n = idx % 10; + seq_printf(m, " VHT%uSMCS%u", n_ss, mcs_n); +} + +static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw_hal *hal = &rtwdev->hal; + void (*print_rate)(struct seq_file *, u8) = NULL; + u8 path, rate; + struct rtw_power_params pwr_param = {0}; + u8 bw = hal->current_band_width; + u8 ch = hal->current_channel; + u8 regd = rtwdev->regd.txpwr_regd; + + seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n", + "path", "rate", "pwr", "", "base", "", "byr", "lmt"); + + mutex_lock(&hal->tx_power_mutex); + for (path = RF_PATH_A; path <= RF_PATH_B; path++) { + /* there is no CCK rates used in 5G */ + if (hal->current_band_type == RTW_BAND_5G) + rate = DESC_RATE6M; + else + rate = DESC_RATE1M; + + /* now, not support vht 3ss and vht 4ss*/ + for (; rate <= DESC_RATEVHT2SS_MCS9; rate++) { + /* now, not support ht 3ss and ht 4ss*/ + if (rate > DESC_RATEMCS15 && + rate < DESC_RATEVHT1SS_MCS0) + continue; + + switch (rate) { + case DESC_RATE1M...DESC_RATE11M: + print_rate = rtw_print_cck_rate_txt; + break; + case DESC_RATE6M...DESC_RATE54M: + print_rate = rtw_print_ofdm_rate_txt; + break; + case DESC_RATEMCS0...DESC_RATEMCS15: + print_rate = rtw_print_ht_rate_txt; + break; + case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9: + print_rate = rtw_print_vht_rate_txt; + break; + default: + print_rate = NULL; + break; + } + + rtw_get_tx_power_params(rtwdev, path, rate, bw, + ch, regd, &pwr_param); + + seq_printf(m, "%4c ", path + 'A'); + if (print_rate) + print_rate(m, rate); + seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n", + hal->tx_pwr_tbl[path][rate], + hal->tx_pwr_tbl[path][rate], + pwr_param.pwr_base, + min_t(s8, pwr_param.pwr_offset, + pwr_param.pwr_limit), + pwr_param.pwr_offset, pwr_param.pwr_limit); + } + } + + mutex_unlock(&hal->tx_power_mutex); + + return 0; +} + #define rtw_debug_impl_mac(page, addr) \ static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \ .cb_read = rtw_debug_get_mac_page, \ @@ -514,6 +621,10 @@ static struct rtw_debugfs_priv rtw_debug_priv_rf_dump = { .cb_read = rtw_debug_get_rf_dump, }; +static struct rtw_debugfs_priv rtw_debug_priv_tx_pwr_tbl = { + .cb_read = rtw_debugfs_get_tx_pwr_tbl, +}; + static struct rtw_debugfs_priv rtw_debug_priv_write_reg = { .cb_write = rtw_debugfs_set_write_reg, }; @@ -610,6 +721,7 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev) rtw_debugfs_add_r(bb_41); } rtw_debugfs_add_r(rf_dump); + rtw_debugfs_add_r(tx_pwr_tbl); } #endif /* CONFIG_RTW88_DEBUGFS */ -- GitLab From 2ec4ad49b98e4a14147d04f914717135eca7c8b1 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 16 Jul 2019 22:42:18 +0800 Subject: [PATCH 0469/7155] libertas_tf: Use correct channel range in lbtf_geo_init It seems we should use 'range' instead of 'priv->range' in lbtf_geo_init(), because 'range' is the corret one related to current regioncode. Reported-by: Hulk Robot Fixes: 691cdb49388b ("libertas_tf: command helper functions for libertas_tf") Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c index 1eacca0d079b..a0b4c9debc11 100644 --- a/drivers/net/wireless/marvell/libertas_tf/cmd.c +++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c @@ -65,7 +65,7 @@ static void lbtf_geo_init(struct lbtf_private *priv) break; } - for (ch = priv->range.start; ch < priv->range.end; ch++) + for (ch = range->start; ch < range->end; ch++) priv->channels[CHAN_TO_IDX(ch)].flags = 0; } -- GitLab From e3b1d879ccda9ffd5332777bb1beeb2cc913faa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 21 Jul 2019 21:52:17 +0200 Subject: [PATCH 0470/7155] brcmfmac: don't net_ratelimit() CONSOLE messages on firmware crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firmware crash is a pretty rare event and can't happen too frequently as it has to be followed by a hardware reinitialization and config reload. It should be safe to don't use net_ratelimit() when it happens. For reporting & debugging purposes it's important to provide a complete log as the last lines are actually the most important. This change modifies brcmfmac to print all messages in an unlimited way in that specific case. With this change there should be finally a backtrace of firmware finally visible after a crash. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 4ea5401c4d6b..8d0e74416643 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -794,7 +794,8 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, if (ch == '\n') { console->log_str[console->log_idx] = 0; if (error) - brcmf_err(bus, "CONSOLE: %s", console->log_str); + __brcmf_err(bus, __func__, "CONSOLE: %s", + console->log_str); else pr_debug("CONSOLE: %s", console->log_str); console->log_idx = 0; -- GitLab From b43d6c8e8d7f19b44d4b40666fc38c8444b8143a Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 23 Jul 2019 11:10:23 +0800 Subject: [PATCH 0471/7155] rtlwifi: remove assignment to itself Module parameters of 'sw_crypto' and 'disable_watchdog' are false by default. If new value is desired, we can do it during inserting module, assignment existing in source code is not reasonable. Reported-by: David Binderman CC: Larry Finger Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 4 ---- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 2 -- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c | 2 -- drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 2 -- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 4 ---- drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 4 ---- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 4 ---- 7 files changed, 22 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index eab48fed61ed..a0eda51e833c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -115,10 +115,6 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; - rtlpriv->cfg->mod_params->disable_watchdog = - rtlpriv->cfg->mod_params->disable_watchdog; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); if (!rtlpriv->psc.inactiveps) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index a9c0111444bc..900788e4018c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -113,8 +113,6 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; if (!rtlpriv->psc.inactiveps) pr_info("rtl8192ce: Power Save off (module option)\n"); if (!rtlpriv->psc.fwctrl_lps) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index c1c34dca39d2..ab3e4aebad39 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -39,8 +39,6 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.dm_flag = 0; rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; /* for firmware buf */ rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index d1d84e7d47a4..1c7ee569f4bf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -161,8 +161,6 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; if (!rtlpriv->psc.inactiveps) pr_info("Power Save off (module option)\n"); if (!rtlpriv->psc.fwctrl_lps) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 4b370410c83c..5702ac6deebf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -129,10 +129,6 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; - rtlpriv->cfg->mod_params->disable_watchdog = - rtlpriv->cfg->mod_params->disable_watchdog; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); rtlpriv->psc.reg_fwctrl_lps = 3; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index 00e6254bf82b..3c8528f0ecb3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -128,10 +128,6 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; - rtlpriv->cfg->mod_params->disable_watchdog = - rtlpriv->cfg->mod_params->disable_watchdog; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); rtlpriv->psc.reg_fwctrl_lps = 2; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index eec7c4ecf3ad..3def6a2b3450 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -145,10 +145,6 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear; - rtlpriv->cfg->mod_params->sw_crypto = - rtlpriv->cfg->mod_params->sw_crypto; - rtlpriv->cfg->mod_params->disable_watchdog = - rtlpriv->cfg->mod_params->disable_watchdog; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); rtlpriv->psc.reg_fwctrl_lps = 2; -- GitLab From 15e830e90fde81b32c96490fb9ff1a26097609eb Mon Sep 17 00:00:00 2001 From: Mao Wenan Date: Wed, 24 Jul 2019 14:25:45 +0800 Subject: [PATCH 0472/7155] mwifiex: use eth_broadcast_addr() to assign broadcast address This patch is to use eth_broadcast_addr() to assign broadcast address insetad of memcpy(). Signed-off-by: Mao Wenan Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/tdls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 18e654dc34c6..09313047beed 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -731,7 +731,6 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u16 status_code, struct sk_buff *skb) { struct ieee80211_mgmt *mgmt; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int ret; u16 capab; struct ieee80211_ht_cap *ht_cap; @@ -765,7 +764,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, memmove(pos + ETH_ALEN, &mgmt->u.action.category, sizeof(mgmt->u.action.u.tdls_discover_resp)); /* init address 4 */ - memcpy(pos, bc_addr, ETH_ALEN); + eth_broadcast_addr(pos); ret = mwifiex_tdls_append_rates_ie(priv, skb); if (ret) { -- GitLab From 6d1bcb957be2850e0776f24c289e1f87c256baeb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:43:07 +0100 Subject: [PATCH 0473/7155] iommu: Remove empty iommu_tlb_range_add() callback from iommu_ops Commit add02cfdc9bc ("iommu: Introduce Interface for IOMMU TLB Flushing") added three new TLB flushing operations to the IOMMU API so that the underlying driver operations can be batched when unmapping large regions of IO virtual address space. However, the ->iotlb_range_add() callback has not been implemented by any IOMMU drivers (amd_iommu.c implements it as an empty function, which incurs the overhead of an indirect branch). Instead, drivers either flush the entire IOTLB in the ->iotlb_sync() callback or perform the necessary invalidation during ->unmap(). Attempting to implement ->iotlb_range_add() for arm-smmu-v3.c revealed two major issues: 1. The page size used to map the region in the page-table is not known, and so it is not generally possible to issue TLB flushes in the most efficient manner. 2. The only mutable state passed to the callback is a pointer to the iommu_domain, which can be accessed concurrently and therefore requires expensive synchronisation to keep track of the outstanding flushes. Remove the callback entirely in preparation for extending ->unmap() and ->iotlb_sync() to update a token on the caller's stack. Signed-off-by: Will Deacon --- drivers/iommu/amd_iommu.c | 6 ------ drivers/iommu/iommu.c | 3 --- drivers/vfio/vfio_iommu_type1.c | 1 - include/linux/iommu.h | 15 --------------- 4 files changed, 25 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index b607a92791d3..f93b148cf55e 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3196,11 +3196,6 @@ static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain) domain_flush_complete(dom); } -static void amd_iommu_iotlb_range_add(struct iommu_domain *domain, - unsigned long iova, size_t size) -{ -} - const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, @@ -3219,7 +3214,6 @@ const struct iommu_ops amd_iommu_ops = { .is_attach_deferred = amd_iommu_is_attach_deferred, .pgsize_bitmap = AMD_IOMMU_PGSIZES, .flush_iotlb_all = amd_iommu_flush_iotlb_all, - .iotlb_range_add = amd_iommu_iotlb_range_add, .iotlb_sync = amd_iommu_flush_iotlb_all, }; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 0c674d80c37f..6d7b25fe2474 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1903,9 +1903,6 @@ static size_t __iommu_unmap(struct iommu_domain *domain, if (!unmapped_page) break; - if (sync && ops->iotlb_range_add) - ops->iotlb_range_add(domain, iova, pgsize); - pr_debug("unmapped: iova 0x%lx size 0x%zx\n", iova, unmapped_page); diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 054391f30fa8..fad7fd8c167c 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -696,7 +696,6 @@ static size_t unmap_unpin_fast(struct vfio_domain *domain, if (!unmapped) { kfree(entry); } else { - iommu_tlb_range_add(domain->domain, *iova, unmapped); entry->iova = *iova; entry->phys = phys; entry->len = unmapped; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index fdc355ccc570..1e21431262d9 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -201,7 +201,6 @@ struct iommu_sva_ops { * @map: map a physically contiguous memory region to an iommu domain * @unmap: unmap a physically contiguous memory region from an iommu domain * @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain - * @iotlb_range_add: Add a given iova range to the flush queue for this domain * @iotlb_sync_map: Sync mappings created recently using @map to the hardware * @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush * queue @@ -244,8 +243,6 @@ struct iommu_ops { size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, size_t size); void (*flush_iotlb_all)(struct iommu_domain *domain); - void (*iotlb_range_add)(struct iommu_domain *domain, - unsigned long iova, size_t size); void (*iotlb_sync_map)(struct iommu_domain *domain); void (*iotlb_sync)(struct iommu_domain *domain); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); @@ -476,13 +473,6 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) domain->ops->flush_iotlb_all(domain); } -static inline void iommu_tlb_range_add(struct iommu_domain *domain, - unsigned long iova, size_t size) -{ - if (domain->ops->iotlb_range_add) - domain->ops->iotlb_range_add(domain, iova, size); -} - static inline void iommu_tlb_sync(struct iommu_domain *domain) { if (domain->ops->iotlb_sync) @@ -637,11 +627,6 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) { } -static inline void iommu_tlb_range_add(struct iommu_domain *domain, - unsigned long iova, size_t size) -{ -} - static inline void iommu_tlb_sync(struct iommu_domain *domain) { } -- GitLab From f71da46719460acd5afa411e52dc8cdf1cb9b0ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:43:24 +0100 Subject: [PATCH 0474/7155] iommu/io-pgtable-arm: Remove redundant call to io_pgtable_tlb_sync() Commit b6b65ca20bc9 ("iommu/io-pgtable-arm: Add support for non-strict mode") added an unconditional call to io_pgtable_tlb_sync() immediately after the case where we replace a block entry with a table entry during an unmap() call. This is redundant, since the IOMMU API will call iommu_tlb_sync() on this path and the patch in question mentions this: | To save having to reason about it too much, make sure the invalidation | in arm_lpae_split_blk_unmap() just performs its own unconditional sync | to minimise the window in which we're technically violating the break- | before-make requirement on a live mapping. This might work out redundant | with an outer-level sync for strict unmaps, but we'll never be splitting | blocks on a DMA fastpath anyway. However, this sync gets in the way of deferred TLB invalidation for leaf entries and is at best a questionable, unproven hack. Remove it. Signed-off-by: Will Deacon --- drivers/iommu/io-pgtable-arm-v7s.c | 1 - drivers/iommu/io-pgtable-arm.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 0fc8dfab2abf..a62733c6a632 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -587,7 +587,6 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data, } io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true); - io_pgtable_tlb_sync(&data->iop); return size; } diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 161a7d56264d..0d6633921c1e 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -583,7 +583,6 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data, tablep = iopte_deref(pte, data); } else if (unmap_idx >= 0) { io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true); - io_pgtable_tlb_sync(&data->iop); return size; } -- GitLab From 298f78895b081911e0b3605f07d79ebd3d4cf7b0 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:43:34 +0100 Subject: [PATCH 0475/7155] iommu/io-pgtable: Rename iommu_gather_ops to iommu_flush_ops In preparation for TLB flush gathering in the IOMMU API, rename the iommu_gather_ops structure in io-pgtable to iommu_flush_ops, which better describes its purpose and avoids the potential for confusion between different levels of the API. $ find linux/ -type f -name '*.[ch]' | xargs sed -i 's/gather_ops/flush_ops/g' Signed-off-by: Will Deacon --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- drivers/iommu/arm-smmu-v3.c | 4 ++-- drivers/iommu/arm-smmu.c | 8 ++++---- drivers/iommu/io-pgtable-arm-v7s.c | 2 +- drivers/iommu/io-pgtable-arm.c | 2 +- drivers/iommu/ipmmu-vmsa.c | 4 ++-- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 4 ++-- include/linux/io-pgtable.h | 6 +++--- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 92ac995dd9c6..17bceb11e708 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -257,7 +257,7 @@ static void mmu_tlb_sync_context(void *cookie) // TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X } -static const struct iommu_gather_ops mmu_tlb_ops = { +static const struct iommu_flush_ops mmu_tlb_ops = { .tlb_flush_all = mmu_tlb_inv_context_s1, .tlb_add_flush = mmu_tlb_inv_range_nosync, .tlb_sync = mmu_tlb_sync_context, diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index a9a9fabd3968..7e137e1e28f1 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1603,7 +1603,7 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, } while (size -= granule); } -static const struct iommu_gather_ops arm_smmu_gather_ops = { +static const struct iommu_flush_ops arm_smmu_flush_ops = { .tlb_flush_all = arm_smmu_tlb_inv_context, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync, @@ -1796,7 +1796,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain) .ias = ias, .oas = oas, .coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY, - .tlb = &arm_smmu_gather_ops, + .tlb = &arm_smmu_flush_ops, .iommu_dev = smmu->dev, }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 64977c131ee6..dc08db347ef3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -251,7 +251,7 @@ enum arm_smmu_domain_stage { struct arm_smmu_domain { struct arm_smmu_device *smmu; struct io_pgtable_ops *pgtbl_ops; - const struct iommu_gather_ops *tlb_ops; + const struct iommu_flush_ops *tlb_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; @@ -547,19 +547,19 @@ static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size, writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID); } -static const struct iommu_gather_ops arm_smmu_s1_tlb_ops = { +static const struct iommu_flush_ops arm_smmu_s1_tlb_ops = { .tlb_flush_all = arm_smmu_tlb_inv_context_s1, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync_context, }; -static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v2 = { +static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v2 = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync_context, }; -static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v1 = { +static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, .tlb_add_flush = arm_smmu_tlb_inv_vmid_nosync, .tlb_sync = arm_smmu_tlb_sync_vmid, diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index a62733c6a632..116f97ee991e 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -817,7 +817,7 @@ static void dummy_tlb_sync(void *cookie) WARN_ON(cookie != cfg_cookie); } -static const struct iommu_gather_ops dummy_tlb_ops = { +static const struct iommu_flush_ops dummy_tlb_ops = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_add_flush = dummy_tlb_add_flush, .tlb_sync = dummy_tlb_sync, diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 0d6633921c1e..402f913b6f6d 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -1081,7 +1081,7 @@ static void dummy_tlb_sync(void *cookie) WARN_ON(cookie != cfg_cookie); } -static const struct iommu_gather_ops dummy_tlb_ops __initconst = { +static const struct iommu_flush_ops dummy_tlb_ops __initconst = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_add_flush = dummy_tlb_add_flush, .tlb_sync = dummy_tlb_sync, diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index ad0098c0c87c..2c14a2c65b22 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -367,7 +367,7 @@ static void ipmmu_tlb_add_flush(unsigned long iova, size_t size, /* The hardware doesn't support selective TLB flush. */ } -static const struct iommu_gather_ops ipmmu_gather_ops = { +static const struct iommu_flush_ops ipmmu_flush_ops = { .tlb_flush_all = ipmmu_tlb_flush_all, .tlb_add_flush = ipmmu_tlb_add_flush, .tlb_sync = ipmmu_tlb_flush_all, @@ -480,7 +480,7 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain) domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K; domain->cfg.ias = 32; domain->cfg.oas = 40; - domain->cfg.tlb = &ipmmu_gather_ops; + domain->cfg.tlb = &ipmmu_flush_ops; domain->io_domain.geometry.aperture_end = DMA_BIT_MASK(32); domain->io_domain.geometry.force_aperture = true; /* diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index b25e2eb9e038..8b602384a385 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -178,7 +178,7 @@ static void __flush_iotlb_sync(void *cookie) */ } -static const struct iommu_gather_ops msm_iommu_gather_ops = { +static const struct iommu_flush_ops msm_iommu_flush_ops = { .tlb_flush_all = __flush_iotlb, .tlb_add_flush = __flush_iotlb_range, .tlb_sync = __flush_iotlb_sync, @@ -345,7 +345,7 @@ static int msm_iommu_domain_config(struct msm_priv *priv) .pgsize_bitmap = msm_iommu_ops.pgsize_bitmap, .ias = 32, .oas = 32, - .tlb = &msm_iommu_gather_ops, + .tlb = &msm_iommu_flush_ops, .iommu_dev = priv->dev, }; diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 82e4be4dfdaf..fed77658d67e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -188,7 +188,7 @@ static void mtk_iommu_tlb_sync(void *cookie) } } -static const struct iommu_gather_ops mtk_iommu_gather_ops = { +static const struct iommu_flush_ops mtk_iommu_flush_ops = { .tlb_flush_all = mtk_iommu_tlb_flush_all, .tlb_add_flush = mtk_iommu_tlb_add_flush_nosync, .tlb_sync = mtk_iommu_tlb_sync, @@ -267,7 +267,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom) .pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap, .ias = 32, .oas = 32, - .tlb = &mtk_iommu_gather_ops, + .tlb = &mtk_iommu_flush_ops, .iommu_dev = data->dev, }; diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 34d0b9783b3e..fd9d9f4da735 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -164,7 +164,7 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, } } -static const struct iommu_gather_ops qcom_gather_ops = { +static const struct iommu_flush_ops qcom_flush_ops = { .tlb_flush_all = qcom_iommu_tlb_inv_context, .tlb_add_flush = qcom_iommu_tlb_inv_range_nosync, .tlb_sync = qcom_iommu_tlb_sync, @@ -215,7 +215,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, .pgsize_bitmap = qcom_iommu_ops.pgsize_bitmap, .ias = 32, .oas = 40, - .tlb = &qcom_gather_ops, + .tlb = &qcom_flush_ops, .iommu_dev = qcom_iommu->dev, }; diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index b5a450a3bb47..6292ea15d674 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -17,7 +17,7 @@ enum io_pgtable_fmt { }; /** - * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management. + * struct iommu_flush_ops - IOMMU callbacks for TLB and page table management. * * @tlb_flush_all: Synchronously invalidate the entire TLB context. * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range. @@ -28,7 +28,7 @@ enum io_pgtable_fmt { * Note that these can all be called in atomic context and must therefore * not block. */ -struct iommu_gather_ops { +struct iommu_flush_ops { void (*tlb_flush_all)(void *cookie); void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie); @@ -84,7 +84,7 @@ struct io_pgtable_cfg { unsigned int ias; unsigned int oas; bool coherent_walk; - const struct iommu_gather_ops *tlb; + const struct iommu_flush_ops *tlb; struct device *iommu_dev; /* Low-level data specific to the table format */ -- GitLab From a7d20dc19d9ea7012227be5144353012ffa3ddc4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:43:48 +0100 Subject: [PATCH 0476/7155] iommu: Introduce struct iommu_iotlb_gather for batching TLB flushes To permit batching of TLB flushes across multiple calls to the IOMMU driver's ->unmap() implementation, introduce a new structure for tracking the address range to be flushed and the granularity at which the flushing is required. This is hooked into the IOMMU API and its caller are updated to make use of the new structure. Subsequent patches will plumb this into the IOMMU drivers as well, but for now the gathering information is ignored. Signed-off-by: Will Deacon --- drivers/iommu/dma-iommu.c | 9 +++++-- drivers/iommu/iommu.c | 19 +++++++++------ drivers/vfio/vfio_iommu_type1.c | 26 +++++++++++++------- include/linux/iommu.h | 43 ++++++++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 22 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index a7f9c3edbcb2..80beb1f5994a 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -444,13 +444,18 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr, struct iommu_dma_cookie *cookie = domain->iova_cookie; struct iova_domain *iovad = &cookie->iovad; size_t iova_off = iova_offset(iovad, dma_addr); + struct iommu_iotlb_gather iotlb_gather; + size_t unmapped; dma_addr -= iova_off; size = iova_align(iovad, size + iova_off); + iommu_iotlb_gather_init(&iotlb_gather); + + unmapped = iommu_unmap_fast(domain, dma_addr, size, &iotlb_gather); + WARN_ON(unmapped != size); - WARN_ON(iommu_unmap_fast(domain, dma_addr, size) != size); if (!cookie->fq_domain) - iommu_tlb_sync(domain); + iommu_tlb_sync(domain, &iotlb_gather); iommu_dma_free_iova(cookie, dma_addr, size); } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 6d7b25fe2474..d67222fdfe44 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1862,7 +1862,7 @@ EXPORT_SYMBOL_GPL(iommu_map); static size_t __iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size, - bool sync) + struct iommu_iotlb_gather *iotlb_gather) { const struct iommu_ops *ops = domain->ops; size_t unmapped_page, unmapped = 0; @@ -1910,9 +1910,6 @@ static size_t __iommu_unmap(struct iommu_domain *domain, unmapped += unmapped_page; } - if (sync && ops->iotlb_sync) - ops->iotlb_sync(domain); - trace_unmap(orig_iova, size, unmapped); return unmapped; } @@ -1920,14 +1917,22 @@ static size_t __iommu_unmap(struct iommu_domain *domain, size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) { - return __iommu_unmap(domain, iova, size, true); + struct iommu_iotlb_gather iotlb_gather; + size_t ret; + + iommu_iotlb_gather_init(&iotlb_gather); + ret = __iommu_unmap(domain, iova, size, &iotlb_gather); + iommu_tlb_sync(domain, &iotlb_gather); + + return ret; } EXPORT_SYMBOL_GPL(iommu_unmap); size_t iommu_unmap_fast(struct iommu_domain *domain, - unsigned long iova, size_t size) + unsigned long iova, size_t size, + struct iommu_iotlb_gather *iotlb_gather) { - return __iommu_unmap(domain, iova, size, false); + return __iommu_unmap(domain, iova, size, iotlb_gather); } EXPORT_SYMBOL_GPL(iommu_unmap_fast); diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index fad7fd8c167c..ad830abe1021 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -650,12 +650,13 @@ static int vfio_iommu_type1_unpin_pages(void *iommu_data, } static long vfio_sync_unpin(struct vfio_dma *dma, struct vfio_domain *domain, - struct list_head *regions) + struct list_head *regions, + struct iommu_iotlb_gather *iotlb_gather) { long unlocked = 0; struct vfio_regions *entry, *next; - iommu_tlb_sync(domain->domain); + iommu_tlb_sync(domain->domain, iotlb_gather); list_for_each_entry_safe(entry, next, regions, list) { unlocked += vfio_unpin_pages_remote(dma, @@ -685,13 +686,15 @@ static size_t unmap_unpin_fast(struct vfio_domain *domain, struct vfio_dma *dma, dma_addr_t *iova, size_t len, phys_addr_t phys, long *unlocked, struct list_head *unmapped_list, - int *unmapped_cnt) + int *unmapped_cnt, + struct iommu_iotlb_gather *iotlb_gather) { size_t unmapped = 0; struct vfio_regions *entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (entry) { - unmapped = iommu_unmap_fast(domain->domain, *iova, len); + unmapped = iommu_unmap_fast(domain->domain, *iova, len, + iotlb_gather); if (!unmapped) { kfree(entry); @@ -711,8 +714,8 @@ static size_t unmap_unpin_fast(struct vfio_domain *domain, * or in case of errors. */ if (*unmapped_cnt >= VFIO_IOMMU_TLB_SYNC_MAX || !unmapped) { - *unlocked += vfio_sync_unpin(dma, domain, - unmapped_list); + *unlocked += vfio_sync_unpin(dma, domain, unmapped_list, + iotlb_gather); *unmapped_cnt = 0; } @@ -743,6 +746,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, dma_addr_t iova = dma->iova, end = dma->iova + dma->size; struct vfio_domain *domain, *d; LIST_HEAD(unmapped_region_list); + struct iommu_iotlb_gather iotlb_gather; int unmapped_region_cnt = 0; long unlocked = 0; @@ -767,6 +771,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, cond_resched(); } + iommu_iotlb_gather_init(&iotlb_gather); while (iova < end) { size_t unmapped, len; phys_addr_t phys, next; @@ -795,7 +800,8 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, */ unmapped = unmap_unpin_fast(domain, dma, &iova, len, phys, &unlocked, &unmapped_region_list, - &unmapped_region_cnt); + &unmapped_region_cnt, + &iotlb_gather); if (!unmapped) { unmapped = unmap_unpin_slow(domain, dma, &iova, len, phys, &unlocked); @@ -806,8 +812,10 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, dma->iommu_mapped = false; - if (unmapped_region_cnt) - unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list); + if (unmapped_region_cnt) { + unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list, + &iotlb_gather); + } if (do_accounting) { vfio_lock_acct(dma, -unlocked, true); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 1e21431262d9..aaf073010a9a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -191,6 +191,23 @@ struct iommu_sva_ops { #ifdef CONFIG_IOMMU_API +/** + * struct iommu_iotlb_gather - Range information for a pending IOTLB flush + * + * @start: IOVA representing the start of the range to be flushed + * @end: IOVA representing the end of the range to be flushed (exclusive) + * @pgsize: The interval at which to perform the flush + * + * This structure is intended to be updated by multiple calls to the + * ->unmap() function in struct iommu_ops before eventually being passed + * into ->iotlb_sync(). + */ +struct iommu_iotlb_gather { + unsigned long start; + unsigned long end; + size_t pgsize; +}; + /** * struct iommu_ops - iommu ops and capabilities * @capable: check capability @@ -375,6 +392,13 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev) return (struct iommu_device *)dev_get_drvdata(dev); } +static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather) +{ + *gather = (struct iommu_iotlb_gather) { + .start = ULONG_MAX, + }; +} + #define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ #define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ #define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ @@ -399,7 +423,8 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova, extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); extern size_t iommu_unmap_fast(struct iommu_domain *domain, - unsigned long iova, size_t size); + unsigned long iova, size_t size, + struct iommu_iotlb_gather *iotlb_gather); extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg,unsigned int nents, int prot); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); @@ -473,10 +498,13 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) domain->ops->flush_iotlb_all(domain); } -static inline void iommu_tlb_sync(struct iommu_domain *domain) +static inline void iommu_tlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather) { if (domain->ops->iotlb_sync) domain->ops->iotlb_sync(domain); + + iommu_iotlb_gather_init(iotlb_gather); } /* PCI device grouping function */ @@ -557,6 +585,7 @@ struct iommu_group {}; struct iommu_fwspec {}; struct iommu_device {}; struct iommu_fault_param {}; +struct iommu_iotlb_gather {}; static inline bool iommu_present(struct bus_type *bus) { @@ -611,7 +640,8 @@ static inline size_t iommu_unmap(struct iommu_domain *domain, } static inline size_t iommu_unmap_fast(struct iommu_domain *domain, - unsigned long iova, int gfp_order) + unsigned long iova, int gfp_order, + struct iommu_iotlb_gather *iotlb_gather) { return 0; } @@ -627,7 +657,8 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) { } -static inline void iommu_tlb_sync(struct iommu_domain *domain) +static inline void iommu_tlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather) { } @@ -812,6 +843,10 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev) return NULL; } +static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather) +{ +} + static inline void iommu_device_unregister(struct iommu_device *iommu) { } -- GitLab From 4fcf8544fc677fc8af135f1d86b3ba69c4ad429d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:43:57 +0100 Subject: [PATCH 0477/7155] iommu: Introduce iommu_iotlb_gather_add_page() Introduce a helper function for drivers to use when updating an iommu_iotlb_gather structure in response to an ->unmap() call, rather than having to open-code the logic in every page-table implementation. Signed-off-by: Will Deacon --- include/linux/iommu.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index aaf073010a9a..ad41aee55bc6 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -507,6 +507,31 @@ static inline void iommu_tlb_sync(struct iommu_domain *domain, iommu_iotlb_gather_init(iotlb_gather); } +static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ + unsigned long start = iova, end = start + size; + + /* + * If the new page is disjoint from the current range or is mapped at + * a different granularity, then sync the TLB so that the gather + * structure can be rewritten. + */ + if (gather->pgsize != size || + end < gather->start || start > gather->end) { + if (gather->pgsize) + iommu_tlb_sync(domain, gather); + gather->pgsize = size; + } + + if (gather->end < end) + gather->end = end; + + if (gather->start > start) + gather->start = start; +} + /* PCI device grouping function */ extern struct iommu_group *pci_device_group(struct device *dev); /* Generic device grouping function */ @@ -847,6 +872,12 @@ static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather) { } +static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ +} + static inline void iommu_device_unregister(struct iommu_device *iommu) { } -- GitLab From 21e450d21ccad4cb7c7984c29ff145012b47736d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 18 Jun 2019 09:32:11 +0200 Subject: [PATCH 0478/7155] x86/mm: Avoid redundant interrupt disable in load_mm_cr4() load_mm_cr4() is always called with interrupts disabled from: - switch_mm_irqs_off() - refresh_pce(), which is a on_each_cpu() callback Thus, disabling interrupts in cr4_set/clear_bits() is redundant. Implement cr4_set/clear_bits_irqsoff() helpers, rename load_mm_cr4() to load_mm_cr4_irqsoff() and use the new helpers. The new helpers do not need a lockdep assert as __cr4_set() has one already. The renaming in combination with the checks in __cr4_set() ensure that any changes in the boundary conditions at the call sites will be detected. [ tglx: Massaged change log ] Signed-off-by: Jan Kiszka Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/0fbbcb64-5f26-4ffb-1bb9-4f5f48426893@siemens.com --- arch/x86/events/core.c | 2 +- arch/x86/include/asm/mmu_context.h | 8 ++++---- arch/x86/include/asm/tlbflush.h | 30 +++++++++++++++++++++++------- arch/x86/mm/tlb.c | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 81b005e4c7d9..cfe256ca76df 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2087,7 +2087,7 @@ static int x86_pmu_event_init(struct perf_event *event) static void refresh_pce(void *ignored) { - load_mm_cr4(this_cpu_read(cpu_tlbstate.loaded_mm)); + load_mm_cr4_irqsoff(this_cpu_read(cpu_tlbstate.loaded_mm)); } static void x86_pmu_event_mapped(struct perf_event *event, struct mm_struct *mm) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 9024236693d2..16ae821483c8 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -28,16 +28,16 @@ static inline void paravirt_activate_mm(struct mm_struct *prev, DECLARE_STATIC_KEY_FALSE(rdpmc_always_available_key); -static inline void load_mm_cr4(struct mm_struct *mm) +static inline void load_mm_cr4_irqsoff(struct mm_struct *mm) { if (static_branch_unlikely(&rdpmc_always_available_key) || atomic_read(&mm->context.perf_rdpmc_allowed)) - cr4_set_bits(X86_CR4_PCE); + cr4_set_bits_irqsoff(X86_CR4_PCE); else - cr4_clear_bits(X86_CR4_PCE); + cr4_clear_bits_irqsoff(X86_CR4_PCE); } #else -static inline void load_mm_cr4(struct mm_struct *mm) {} +static inline void load_mm_cr4_irqsoff(struct mm_struct *mm) {} #endif #ifdef CONFIG_MODIFY_LDT_SYSCALL diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index dee375831962..6f66d841262d 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -290,26 +290,42 @@ static inline void __cr4_set(unsigned long cr4) } /* Set in this cpu's CR4. */ -static inline void cr4_set_bits(unsigned long mask) +static inline void cr4_set_bits_irqsoff(unsigned long mask) { - unsigned long cr4, flags; + unsigned long cr4; - local_irq_save(flags); cr4 = this_cpu_read(cpu_tlbstate.cr4); if ((cr4 | mask) != cr4) __cr4_set(cr4 | mask); - local_irq_restore(flags); } /* Clear in this cpu's CR4. */ -static inline void cr4_clear_bits(unsigned long mask) +static inline void cr4_clear_bits_irqsoff(unsigned long mask) { - unsigned long cr4, flags; + unsigned long cr4; - local_irq_save(flags); cr4 = this_cpu_read(cpu_tlbstate.cr4); if ((cr4 & ~mask) != cr4) __cr4_set(cr4 & ~mask); +} + +/* Set in this cpu's CR4. */ +static inline void cr4_set_bits(unsigned long mask) +{ + unsigned long flags; + + local_irq_save(flags); + cr4_set_bits_irqsoff(mask); + local_irq_restore(flags); +} + +/* Clear in this cpu's CR4. */ +static inline void cr4_clear_bits(unsigned long mask) +{ + unsigned long flags; + + local_irq_save(flags); + cr4_clear_bits_irqsoff(mask); local_irq_restore(flags); } diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 4de9704c4aaf..e6a9edc5baaf 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -440,7 +440,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid); if (next != real_prev) { - load_mm_cr4(next); + load_mm_cr4_irqsoff(next); switch_ldt(real_prev, next); } } -- GitLab From a30f1743e4f57b359903fd679476b2903e7e5dac Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 24 Jul 2019 11:52:54 +0200 Subject: [PATCH 0479/7155] ALSA: line6: sizeof (byte) is always 1, use that fact. sizeof (byte) is always 1, use that fact and make interesting code explicit. Signed-off-by: Pavel Machek Signed-off-by: Takashi Iwai --- sound/usb/line6/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index ab2ec896f49c..b5a3f754a4f1 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -342,7 +342,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, if (address > 0xffff || datalen > 0xff) return -EINVAL; - len = kmalloc(sizeof(*len), GFP_KERNEL); + len = kmalloc(1, GFP_KERNEL); if (!len) return -ENOMEM; @@ -418,7 +418,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, if (address > 0xffff || datalen > 0xffff) return -EINVAL; - status = kmalloc(sizeof(*status), GFP_KERNEL); + status = kmalloc(1, GFP_KERNEL); if (!status) return -ENOMEM; -- GitLab From 4599c6671b8119ed5455e4ed6b967b461c27a9f7 Mon Sep 17 00:00:00 2001 From: Nikolas Nyby Date: Wed, 24 Jul 2019 00:13:37 -0400 Subject: [PATCH 0480/7155] x86/crash: Remove unnecessary comparison The ret comparison and return are unnecessary as of commit f296f2634920 ("x86/kexec: Remove walk_iomem_res() call with GART type") elf_header_exclude_ranges() returns ret in any case, with or without this comparison. [ tglx: Use a proper commit reference instead of full SHA ] Signed-off-by: Nikolas Nyby Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190724041337.8346-1-nikolas@gnu.org --- arch/x86/kernel/crash.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 2bf70a2fed90..eb651fbde92a 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -225,8 +225,6 @@ static int elf_header_exclude_ranges(struct crash_mem *cmem) if (crashk_low_res.end) { ret = crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end); - if (ret) - return ret; } return ret; -- GitLab From 511885d7061eda3eb1faf3f57dcc936ff75863f1 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 24 Jul 2019 08:23:23 -0700 Subject: [PATCH 0481/7155] lib/timerqueue: Rely on rbtree semantics for next timer Simplify the timerqueue code by using cached rbtrees and rely on the tree leftmost node semantics to get the timer with earliest expiration time. This is a drop in conversion, and therefore semantics remain untouched. The runtime overhead of cached rbtrees is be pretty much the same as the current head->next method, noting that when removing the leftmost node, a common operation for the timerqueue, the rb_next(leftmost) is O(1) as well, so the next timer will either be the right node or its parent. Therefore no extra pointer chasing. Finally, the size of the struct timerqueue_head remains the same. Passes several hours of rcutorture. Signed-off-by: Davidlohr Bueso Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190724152323.bojciei3muvfxalm@linux-r8p5 --- include/linux/timerqueue.h | 13 ++++++------- lib/timerqueue.c | 30 ++++++++++++------------------ 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h index 78b8cc73f12f..aff122f1062a 100644 --- a/include/linux/timerqueue.h +++ b/include/linux/timerqueue.h @@ -12,8 +12,7 @@ struct timerqueue_node { }; struct timerqueue_head { - struct rb_root head; - struct timerqueue_node *next; + struct rb_root_cached rb_root; }; @@ -29,13 +28,14 @@ extern struct timerqueue_node *timerqueue_iterate_next( * * @head: head of timerqueue * - * Returns a pointer to the timer node that has the - * earliest expiration time. + * Returns a pointer to the timer node that has the earliest expiration time. */ static inline struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) { - return head->next; + struct rb_node *leftmost = rb_first_cached(&head->rb_root); + + return rb_entry(leftmost, struct timerqueue_node, node); } static inline void timerqueue_init(struct timerqueue_node *node) @@ -45,7 +45,6 @@ static inline void timerqueue_init(struct timerqueue_node *node) static inline void timerqueue_init_head(struct timerqueue_head *head) { - head->head = RB_ROOT; - head->next = NULL; + head->rb_root = RB_ROOT_CACHED; } #endif /* _LINUX_TIMERQUEUE_H */ diff --git a/lib/timerqueue.c b/lib/timerqueue.c index bc7e64df27df..c52710964593 100644 --- a/lib/timerqueue.c +++ b/lib/timerqueue.c @@ -26,9 +26,10 @@ */ bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node) { - struct rb_node **p = &head->head.rb_node; + struct rb_node **p = &head->rb_root.rb_root.rb_node; struct rb_node *parent = NULL; - struct timerqueue_node *ptr; + struct timerqueue_node *ptr; + bool leftmost = true; /* Make sure we don't add nodes that are already added */ WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node)); @@ -36,19 +37,17 @@ bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node) while (*p) { parent = *p; ptr = rb_entry(parent, struct timerqueue_node, node); - if (node->expires < ptr->expires) + if (node->expires < ptr->expires) { p = &(*p)->rb_left; - else + } else { p = &(*p)->rb_right; + leftmost = false; + } } rb_link_node(&node->node, parent, p); - rb_insert_color(&node->node, &head->head); + rb_insert_color_cached(&node->node, &head->rb_root, leftmost); - if (!head->next || node->expires < head->next->expires) { - head->next = node; - return true; - } - return false; + return leftmost; } EXPORT_SYMBOL_GPL(timerqueue_add); @@ -65,15 +64,10 @@ bool timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node) { WARN_ON_ONCE(RB_EMPTY_NODE(&node->node)); - /* update next pointer */ - if (head->next == node) { - struct rb_node *rbn = rb_next(&node->node); - - head->next = rb_entry_safe(rbn, struct timerqueue_node, node); - } - rb_erase(&node->node, &head->head); + rb_erase_cached(&node->node, &head->rb_root); RB_CLEAR_NODE(&node->node); - return head->next != NULL; + + return !RB_EMPTY_ROOT(&head->rb_root.rb_root); } EXPORT_SYMBOL_GPL(timerqueue_del); -- GitLab From e8758a5ed2783c417be1f5aab5af9fe4be60956f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 24 Jul 2019 07:26:32 +0200 Subject: [PATCH 0482/7155] ASoC: wm8955: Fix a typo in 'wm8995_pll_factors()' function name This should be 'wm8955_pll_factors()' instead. Fix it and use it. Signed-off-by: Christophe JAILLET Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20190724052632.30476-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 66a5f1827aa9..9c7e2892c8cb 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -140,7 +140,7 @@ struct pll_factors { * to allow rounding later */ #define FIXED_FLL_SIZE ((1 << 22) * 10) -static int wm8995_pll_factors(struct device *dev, +static int wm8955_pll_factors(struct device *dev, int Fref, int Fout, struct pll_factors *pll) { u64 Kpart; @@ -279,7 +279,7 @@ static int wm8955_configure_clocking(struct snd_soc_component *component) /* Use the last divider configuration we saw for the * sample rate. */ - ret = wm8995_pll_factors(component->dev, wm8955->mclk_rate, + ret = wm8955_pll_factors(component->dev, wm8955->mclk_rate, clock_cfgs[sr].mclk, &pll); if (ret != 0) { dev_err(component->dev, -- GitLab From 2a3b6f7b02cd141c990c6f5aed41070b5b7f4a7d Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 20:23:31 +0800 Subject: [PATCH 0483/7155] spi: dw-pci: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190724122331.21856-1-hslester96@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 9651679ee7f7..c1e2401cace0 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -98,16 +98,14 @@ static void spi_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int spi_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_suspend_host(dws); } static int spi_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_resume_host(dws); } -- GitLab From 570d785ba46b947e0ded0c38955c43d1d7867c12 Mon Sep 17 00:00:00 2001 From: Kelsey Skunberg Date: Wed, 24 Jul 2019 00:06:59 -0600 Subject: [PATCH 0484/7155] drivers: net: xgene: Remove acpi_has_method() calls acpi_evaluate_object will already return an error if the needed method does not exist. Remove unnecessary acpi_has_method() calls and check the returned acpi_status for failure instead. Signed-off-by: Kelsey Skunberg Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 9 ++++----- drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 9 +++++---- drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 9 ++++----- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 61a465097cb8..79924efd4ab7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -694,6 +694,7 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; + acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -712,11 +713,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI - if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) { - acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), - "_RST", NULL, NULL); - } else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), - "_INI")) { + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), + "_RST", NULL, NULL); + if (ACPI_FAILURE(status)) { acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_INI", NULL, NULL); } diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index 6453fc2ebb1f..3b3dc5b25b29 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -437,6 +437,7 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *p) { struct device *dev = &p->pdev->dev; + acpi_status status; if (!xgene_ring_mgr_init(p)) return -ENODEV; @@ -460,12 +461,12 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p) } } else { #ifdef CONFIG_ACPI - if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_RST")) - acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev), - "_RST", NULL, NULL); - else if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_INI")) + status = acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev), + "_RST", NULL, NULL); + if (ACPI_FAILURE(status)) { acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev), "_INI", NULL, NULL); + } #endif } diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 133eb91c542e..78584089d76d 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -380,6 +380,7 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; + acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -393,11 +394,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI - if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) { - acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), - "_RST", NULL, NULL); - } else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), - "_INI")) { + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), + "_RST", NULL, NULL); + if (ACPI_FAILURE(status)) { acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_INI", NULL, NULL); } -- GitLab From bcc2a2dc3ba8c3a7aed856f840afa6a47e3cb8e0 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:58:48 +0200 Subject: [PATCH 0485/7155] ASoC: Intel: Skylake: Merge skl_sst and skl into skl_dev struct Skylake driver is divided into two modules: - snd_soc_skl - snd_soc_skl_ipc and nothing would be wrong if not for the fact that both cannot exist without one another. IPC module is not some kind of extension, as it is the case for snd_hda_ext_core which is separated from snd_hda_core - legacy hda interface. It's as much core Skylake module as snd_soc_skl is. Statement backed up by existence of circular dependency between this two. To eliminate said problem, struct skl_sst has been created. From that very momment, Skylake has been plagued by header errors (incomplete structs, unknown references etc.) whenever something new is to be added or code is cleaned up. As this design is being corrected, struct skl_sst is no longer needed, so combine it with struct skl. To avoid ambiguity when searching for skl stuff (struct skl *skl) it has also been renamed to skl_dev. No functional changes. Signed-off-by: Piotr Maziarz Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/sst-ipc.h | 1 + sound/soc/intel/skylake/bxt-sst.c | 50 ++-- sound/soc/intel/skylake/cnl-sst-dsp.h | 7 +- sound/soc/intel/skylake/cnl-sst.c | 37 ++- sound/soc/intel/skylake/skl-debug.c | 8 +- sound/soc/intel/skylake/skl-messages.c | 229 +++++++++-------- sound/soc/intel/skylake/skl-nhlt.c | 18 +- sound/soc/intel/skylake/skl-pcm.c | 75 +++--- sound/soc/intel/skylake/skl-ssp-clk.c | 4 +- sound/soc/intel/skylake/skl-sst-dsp.c | 10 +- sound/soc/intel/skylake/skl-sst-dsp.h | 30 +-- sound/soc/intel/skylake/skl-sst-ipc.c | 8 +- sound/soc/intel/skylake/skl-sst-ipc.h | 52 +--- sound/soc/intel/skylake/skl-sst-utils.c | 37 ++- sound/soc/intel/skylake/skl-sst.c | 51 ++-- sound/soc/intel/skylake/skl-topology.c | 320 ++++++++++++------------ sound/soc/intel/skylake/skl-topology.h | 32 +-- sound/soc/intel/skylake/skl.c | 54 ++-- sound/soc/intel/skylake/skl.h | 94 +++++-- 19 files changed, 545 insertions(+), 572 deletions(-) diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index c6779e2ac830..ef38600e88f7 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -35,6 +35,7 @@ struct ipc_message { }; struct sst_generic_ipc; +struct sst_dsp; struct sst_plat_ipc_ops { void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *); diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 46d5159cf905..92a82e6b5fe6 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -14,7 +14,7 @@ #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" -#include "skl-sst-ipc.h" +#include "skl.h" #define BXT_BASEFW_TIMEOUT 3000 #define BXT_INIT_TIMEOUT 300 @@ -49,7 +49,7 @@ static int bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) { struct snd_dma_buffer dmab; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct firmware stripped_fw; int ret = 0, i, dma_id, stream_tag; @@ -184,7 +184,7 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) static int bxt_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int ret, i; if (ctx->fw == NULL) { @@ -268,7 +268,7 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) */ static int bxt_d0i3_target_state(struct sst_dsp *ctx) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct skl_d0i3_data *d0i3 = &skl->d0i3; if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING) @@ -288,8 +288,8 @@ static void bxt_set_dsp_D0i3(struct work_struct *work) { int ret; struct skl_ipc_d0ix_msg msg; - struct skl_sst *skl = container_of(work, - struct skl_sst, d0i3.work.work); + struct skl_dev *skl = container_of(work, + struct skl_dev, d0i3.work.work); struct sst_dsp *ctx = skl->dsp; struct skl_d0i3_data *d0i3 = &skl->d0i3; int target_state; @@ -331,7 +331,7 @@ static void bxt_set_dsp_D0i3(struct work_struct *work) static int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct skl_d0i3_data *d0i3 = &skl->d0i3; /* Schedule D0i3 only if the usecase ref counts are appropriate */ @@ -350,7 +350,7 @@ static int bxt_set_dsp_D0i0(struct sst_dsp *ctx) { int ret; struct skl_ipc_d0ix_msg msg; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; dev_dbg(ctx->dev, "In %s:\n", __func__); @@ -389,7 +389,7 @@ static int bxt_set_dsp_D0i0(struct sst_dsp *ctx) static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int ret; struct skl_ipc_dxstate_info dx; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); @@ -486,7 +486,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) { int ret; struct skl_ipc_dxstate_info dx; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); dx.core_mask = core_mask; @@ -548,9 +548,9 @@ static struct sst_dsp_device skl_dev = { int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_sst **dsp) + struct skl_dev **dsp) { - struct skl_sst *skl; + struct skl_dev *skl; struct sst_dsp *sst; int ret; @@ -591,10 +591,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, } EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); -int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) +int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl) { int ret; - struct sst_dsp *sst = ctx->dsp; + struct sst_dsp *sst = skl->dsp; ret = sst->fw_ops.load_fw(sst); if (ret < 0) { @@ -604,29 +604,29 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) skl_dsp_init_core_state(sst); - if (ctx->lib_count > 1) { - ret = sst->fw_ops.load_library(sst, ctx->lib_info, - ctx->lib_count); + if (skl->lib_count > 1) { + ret = sst->fw_ops.load_library(sst, skl->lib_info, + skl->lib_count); if (ret < 0) { dev_err(dev, "Load Library failed : %x\n", ret); return ret; } } - ctx->is_first_boot = false; + skl->is_first_boot = false; return 0; } EXPORT_SYMBOL_GPL(bxt_sst_init_fw); -void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) { - skl_release_library(ctx->lib_info, ctx->lib_count); - if (ctx->dsp->fw) - release_firmware(ctx->dsp->fw); - skl_freeup_uuid_list(ctx); - skl_ipc_free(&ctx->ipc); - ctx->dsp->ops->free(ctx->dsp); + skl_release_library(skl->lib_info, skl->lib_count); + if (skl->dsp->fw) + release_firmware(skl->dsp->fw); + skl_freeup_uuid_list(skl); + skl_ipc_free(&skl->ipc); + skl->dsp->ops->free(skl->dsp); } EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 426515faab52..7bd4d2a8fdfa 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -9,7 +9,6 @@ #define __CNL_SST_DSP_H__ struct sst_dsp; -struct skl_sst; struct sst_dsp_device; struct sst_generic_ipc; @@ -97,8 +96,8 @@ void cnl_ipc_free(struct sst_generic_ipc *ipc); int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_sst **dsp); -int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); -void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); + struct skl_dev **dsp); +int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl); +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); #endif /*__CNL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index f2c09fa6ea40..2d748a335bcf 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -24,8 +24,7 @@ #include "../common/sst-dsp-priv.h" #include "../common/sst-ipc.h" #include "cnl-sst-dsp.h" -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" +#include "skl.h" #define CNL_FW_ROM_INIT 0x1 #define CNL_FW_INIT 0x5 @@ -109,7 +108,7 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) static int cnl_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; - struct skl_sst *cnl = ctx->thread_context; + struct skl_dev *cnl = ctx->thread_context; int ret; if (!ctx->fw) { @@ -167,7 +166,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) { - struct skl_sst *cnl = ctx->thread_context; + struct skl_dev *cnl = ctx->thread_context; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); struct skl_ipc_dxstate_info dx; int ret; @@ -229,7 +228,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) { - struct skl_sst *cnl = ctx->thread_context; + struct skl_dev *cnl = ctx->thread_context; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); struct skl_ipc_dxstate_info dx; int ret; @@ -293,7 +292,7 @@ static struct sst_ops cnl_ops = { static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) { struct sst_dsp *dsp = context; - struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); + struct skl_dev *cnl = sst_dsp_get_thread_context(dsp); struct sst_generic_ipc *ipc = &cnl->ipc; struct skl_ipc_header header = {0}; u32 hipcida, hipctdr, hipctdd; @@ -386,7 +385,7 @@ static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); } -static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) +static int cnl_ipc_init(struct device *dev, struct skl_dev *cnl) { struct sst_generic_ipc *ipc; int err; @@ -415,9 +414,9 @@ static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_sst **dsp) + struct skl_dev **dsp) { - struct skl_sst *cnl; + struct skl_dev *cnl; struct sst_dsp *sst; int ret; @@ -454,12 +453,12 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, } EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); -int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl) { int ret; - struct sst_dsp *sst = ctx->dsp; + struct sst_dsp *sst = skl->dsp; - ret = ctx->dsp->fw_ops.load_fw(sst); + ret = skl->dsp->fw_ops.load_fw(sst); if (ret < 0) { dev_err(dev, "load base fw failed: %d", ret); return ret; @@ -467,21 +466,21 @@ int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) skl_dsp_init_core_state(sst); - ctx->is_first_boot = false; + skl->is_first_boot = false; return 0; } EXPORT_SYMBOL_GPL(cnl_sst_init_fw); -void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) { - if (ctx->dsp->fw) - release_firmware(ctx->dsp->fw); + if (skl->dsp->fw) + release_firmware(skl->dsp->fw); - skl_freeup_uuid_list(ctx); - cnl_ipc_free(&ctx->ipc); + skl_freeup_uuid_list(skl); + cnl_ipc_free(&skl->ipc); - ctx->dsp->ops->free(ctx->dsp); + skl->dsp->ops->free(skl->dsp); } EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index b9b4a72a4334..c43aa4081232 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -20,7 +20,7 @@ #define FW_REG_SIZE 0x60 struct skl_debug { - struct skl *skl; + struct skl_dev *skl; struct device *dev; struct dentry *fs; @@ -172,7 +172,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct skl_debug *d = file->private_data; - struct sst_dsp *sst = d->skl->skl_sst->dsp; + struct sst_dsp *sst = d->skl->dsp; size_t w0_stat_sz = sst->addr.w0_stat_sz; void __iomem *in_base = sst->mailbox.in_base; void __iomem *fw_reg_addr; @@ -213,7 +213,7 @@ static const struct file_operations soft_regs_ctrl_fops = { .llseek = default_llseek, }; -struct skl_debug *skl_debugfs_init(struct skl *skl) +struct skl_debug *skl_debugfs_init(struct skl_dev *skl) { struct skl_debug *d; @@ -252,7 +252,7 @@ struct skl_debug *skl_debugfs_init(struct skl *skl) return NULL; } -void skl_debugfs_exit(struct skl *skl) +void skl_debugfs_exit(struct skl_dev *skl) { struct skl_debug *d = skl->debugfs; diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index febc070839e0..f604d9c6824d 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -47,7 +47,7 @@ static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) #define SKL_ASTATE_PARAM_ID 4 -void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data) +void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data) { struct skl_ipc_large_config_msg msg = {0}; @@ -55,14 +55,14 @@ void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data) msg.param_data_size = (cnt * sizeof(struct skl_astate_param) + sizeof(cnt)); - skl_ipc_set_large_config(&ctx->ipc, &msg, data); + skl_ipc_set_large_config(&skl->ipc, &msg, data); } #define NOTIFICATION_PARAM_ID 3 #define NOTIFICATION_MASK 0xf /* disable notfication for underruns/overruns from firmware module */ -void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) +void skl_dsp_enable_notification(struct skl_dev *skl, bool enable) { struct notification_mask mask; struct skl_ipc_large_config_msg msg = {0}; @@ -73,7 +73,7 @@ void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) msg.large_param_id = NOTIFICATION_PARAM_ID; msg.param_data_size = sizeof(mask); - skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); + skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)&mask); } static int skl_dsp_setup_spib(struct device *dev, unsigned int size, @@ -277,7 +277,7 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) return NULL; } -int skl_init_dsp(struct skl *skl) +int skl_init_dsp(struct skl_dev *skl) { void __iomem *mmio_base; struct hdac_bus *bus = skl_to_bus(skl); @@ -307,13 +307,13 @@ int skl_init_dsp(struct skl *skl) loader_ops = ops->loader_ops(); ret = ops->init(bus->dev, mmio_base, irq, skl->fw_name, loader_ops, - &skl->skl_sst); + &skl); if (ret < 0) goto unmap_mmio; - skl->skl_sst->dsp_ops = ops; - cores = &skl->skl_sst->cores; + skl->dsp_ops = ops; + cores = &skl->cores; cores->count = ops->num_cores; cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); @@ -342,21 +342,20 @@ int skl_init_dsp(struct skl *skl) return ret; } -int skl_free_dsp(struct skl *skl) +int skl_free_dsp(struct skl_dev *skl) { struct hdac_bus *bus = skl_to_bus(skl); - struct skl_sst *ctx = skl->skl_sst; /* disable ppcap interrupt */ snd_hdac_ext_bus_ppcap_int_enable(bus, false); - ctx->dsp_ops->cleanup(bus->dev, ctx); + skl->dsp_ops->cleanup(bus->dev, skl); - kfree(ctx->cores.state); - kfree(ctx->cores.usage_count); + kfree(skl->cores.state); + kfree(skl->cores.usage_count); - if (ctx->dsp->addr.lpe) - iounmap(ctx->dsp->addr.lpe); + if (skl->dsp->addr.lpe) + iounmap(skl->dsp->addr.lpe); return 0; } @@ -368,15 +367,14 @@ int skl_free_dsp(struct skl *skl) * mode during system suspend. In the case of normal suspend, cancel * any pending D0i3 work. */ -int skl_suspend_late_dsp(struct skl *skl) +int skl_suspend_late_dsp(struct skl_dev *skl) { - struct skl_sst *ctx = skl->skl_sst; struct delayed_work *dwork; - if (!ctx) + if (!skl) return 0; - dwork = &ctx->d0i3.work; + dwork = &skl->d0i3.work; if (dwork->work.func) { if (skl->supend_active) @@ -388,9 +386,8 @@ int skl_suspend_late_dsp(struct skl *skl) return 0; } -int skl_suspend_dsp(struct skl *skl) +int skl_suspend_dsp(struct skl_dev *skl) { - struct skl_sst *ctx = skl->skl_sst; struct hdac_bus *bus = skl_to_bus(skl); int ret; @@ -398,7 +395,7 @@ int skl_suspend_dsp(struct skl *skl) if (!bus->ppcap) return 0; - ret = skl_dsp_sleep(ctx->dsp); + ret = skl_dsp_sleep(skl->dsp); if (ret < 0) return ret; @@ -409,9 +406,8 @@ int skl_suspend_dsp(struct skl *skl) return 0; } -int skl_resume_dsp(struct skl *skl) +int skl_resume_dsp(struct skl_dev *skl) { - struct skl_sst *ctx = skl->skl_sst; struct hdac_bus *bus = skl_to_bus(skl); int ret; @@ -424,26 +420,26 @@ int skl_resume_dsp(struct skl *skl) snd_hdac_ext_bus_ppcap_int_enable(bus, true); /* check if DSP 1st boot is done */ - if (skl->skl_sst->is_first_boot) + if (skl->is_first_boot) return 0; /* * Disable dynamic clock and power gating during firmware * and library download */ - ctx->enable_miscbdcge(ctx->dev, false); - ctx->clock_power_gating(ctx->dev, false); + skl->enable_miscbdcge(skl->dev, false); + skl->clock_power_gating(skl->dev, false); - ret = skl_dsp_wake(ctx->dsp); - ctx->enable_miscbdcge(ctx->dev, true); - ctx->clock_power_gating(ctx->dev, true); + ret = skl_dsp_wake(skl->dsp); + skl->enable_miscbdcge(skl->dev, true); + skl->clock_power_gating(skl->dev, true); if (ret < 0) return ret; - skl_dsp_enable_notification(skl->skl_sst, false); + skl_dsp_enable_notification(skl, false); if (skl->cfg.astate_cfg != NULL) { - skl_dsp_set_astate_cfg(skl->skl_sst, skl->cfg.astate_cfg->count, + skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count, skl->cfg.astate_cfg); } return ret; @@ -476,7 +472,7 @@ enum skl_bitdepth skl_get_bit_depth(int params) * which are read from widget information passed through topology binary * This is send when we create a module with INIT_INSTANCE IPC msg */ -static void skl_set_base_module_format(struct skl_sst *ctx, +static void skl_set_base_module_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_base_cfg *base_cfg) { @@ -493,7 +489,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx, base_cfg->audio_fmt.ch_cfg = format->ch_cfg; base_cfg->audio_fmt.sample_type = format->sample_type; - dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", + dev_dbg(skl->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", format->bit_depth, format->valid_bit_depth, format->ch_cfg); @@ -530,7 +526,7 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, * Calculate the gatewat settings required for copier module, type of * gateway and index of gateway to use */ -static u32 skl_get_node_id(struct skl_sst *ctx, +static u32 skl_get_node_id(struct skl_dev *skl, struct skl_module_cfg *mconfig) { union skl_connector_node_id node_id = {0}; @@ -587,16 +583,15 @@ static u32 skl_get_node_id(struct skl_sst *ctx, return node_id.val; } -static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, +static void skl_setup_cpr_gateway_cfg(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_cpr_cfg *cpr_mconfig) { u32 dma_io_buf; struct skl_module_res *res; int res_idx = mconfig->res_idx; - struct skl *skl = get_skl_ctx(ctx->dev); - cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); + cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(skl, mconfig); if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { cpr_mconfig->cpr_feature_mask = 0; @@ -627,7 +622,7 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, break; default: - dev_warn(ctx->dev, "wrong connection type: %d\n", + dev_warn(skl->dev, "wrong connection type: %d\n", mconfig->hw_conn_type); return; } @@ -653,7 +648,7 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, #define DMA_CONTROL_ID 5 #define DMA_I2S_BLOB_SIZE 21 -int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, +int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, u32 caps_size, u32 node_id) { struct skl_dma_control *dma_ctrl; @@ -686,14 +681,14 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, memcpy(dma_ctrl->config_data, caps, caps_size); - err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl); + err = skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)dma_ctrl); kfree(dma_ctrl); return err; } EXPORT_SYMBOL_GPL(skl_dsp_set_dma_control); -static void skl_setup_out_format(struct skl_sst *ctx, +static void skl_setup_out_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_audio_data_format *out_fmt) { @@ -711,7 +706,7 @@ static void skl_setup_out_format(struct skl_sst *ctx, out_fmt->interleaving = format->interleaving_style; out_fmt->sample_type = format->sample_type; - dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", + dev_dbg(skl->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", out_fmt->number_of_channels, format->s_freq, format->bit_depth); } @@ -720,7 +715,7 @@ static void skl_setup_out_format(struct skl_sst *ctx, * configuration and the target frequency as extra parameter passed as src * config */ -static void skl_set_src_format(struct skl_sst *ctx, +static void skl_set_src_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_src_module_cfg *src_mconfig) { @@ -728,7 +723,7 @@ static void skl_set_src_format(struct skl_sst *ctx, struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; struct skl_module_fmt *fmt = &iface->outputs[0].fmt; - skl_set_base_module_format(ctx, mconfig, + skl_set_base_module_format(skl, mconfig, (struct skl_base_cfg *)src_mconfig); src_mconfig->src_cfg = fmt->s_freq; @@ -739,7 +734,7 @@ static void skl_set_src_format(struct skl_sst *ctx, * module configuration and channel configuration * It also take coefficients and now we have defaults applied here */ -static void skl_set_updown_mixer_format(struct skl_sst *ctx, +static void skl_set_updown_mixer_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_up_down_mixer_cfg *mixer_mconfig) { @@ -747,7 +742,7 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; struct skl_module_fmt *fmt = &iface->outputs[0].fmt; - skl_set_base_module_format(ctx, mconfig, + skl_set_base_module_format(skl, mconfig, (struct skl_base_cfg *)mixer_mconfig); mixer_mconfig->out_ch_cfg = fmt->ch_cfg; mixer_mconfig->ch_map = fmt->ch_map; @@ -760,17 +755,17 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, * format, gateway settings * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg */ -static void skl_set_copier_format(struct skl_sst *ctx, +static void skl_set_copier_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_cpr_cfg *cpr_mconfig) { struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; - skl_set_base_module_format(ctx, mconfig, base_cfg); + skl_set_base_module_format(skl, mconfig, base_cfg); - skl_setup_out_format(ctx, mconfig, out_fmt); - skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); + skl_setup_out_format(skl, mconfig, out_fmt); + skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig); } /* @@ -778,13 +773,13 @@ static void skl_set_copier_format(struct skl_sst *ctx, * configuration and params */ -static void skl_set_algo_format(struct skl_sst *ctx, +static void skl_set_algo_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_algo_cfg *algo_mcfg) { struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; - skl_set_base_module_format(ctx, mconfig, base_cfg); + skl_set_base_module_format(skl, mconfig, base_cfg); if (mconfig->formats_config.caps_size == 0) return; @@ -802,7 +797,7 @@ static void skl_set_algo_format(struct skl_sst *ctx, * Mic select module take base module configuration and out-format * configuration */ -static void skl_set_base_outfmt_format(struct skl_sst *ctx, +static void skl_set_base_outfmt_format(struct skl_dev *skl, struct skl_module_cfg *mconfig, struct skl_base_outfmt_cfg *base_outfmt_mcfg) { @@ -810,11 +805,11 @@ static void skl_set_base_outfmt_format(struct skl_sst *ctx, struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)base_outfmt_mcfg; - skl_set_base_module_format(ctx, mconfig, base_cfg); - skl_setup_out_format(ctx, mconfig, out_fmt); + skl_set_base_module_format(skl, mconfig, base_cfg); + skl_setup_out_format(skl, mconfig, out_fmt); } -static u16 skl_get_module_param_size(struct skl_sst *ctx, +static u16 skl_get_module_param_size(struct skl_dev *skl, struct skl_module_cfg *mconfig) { u16 param_size; @@ -859,14 +854,14 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, * base module format configuration */ -static int skl_set_module_format(struct skl_sst *ctx, +static int skl_set_module_format(struct skl_dev *skl, struct skl_module_cfg *module_config, u16 *module_config_size, void **param_data) { u16 param_size; - param_size = skl_get_module_param_size(ctx, module_config); + param_size = skl_get_module_param_size(skl, module_config); *param_data = kzalloc(param_size, GFP_KERNEL); if (NULL == *param_data) @@ -876,34 +871,34 @@ static int skl_set_module_format(struct skl_sst *ctx, switch (module_config->m_type) { case SKL_MODULE_TYPE_COPIER: - skl_set_copier_format(ctx, module_config, *param_data); + skl_set_copier_format(skl, module_config, *param_data); break; case SKL_MODULE_TYPE_SRCINT: - skl_set_src_format(ctx, module_config, *param_data); + skl_set_src_format(skl, module_config, *param_data); break; case SKL_MODULE_TYPE_UPDWMIX: - skl_set_updown_mixer_format(ctx, module_config, *param_data); + skl_set_updown_mixer_format(skl, module_config, *param_data); break; case SKL_MODULE_TYPE_ALGO: - skl_set_algo_format(ctx, module_config, *param_data); + skl_set_algo_format(skl, module_config, *param_data); break; case SKL_MODULE_TYPE_BASE_OUTFMT: case SKL_MODULE_TYPE_MIC_SELECT: case SKL_MODULE_TYPE_KPB: - skl_set_base_outfmt_format(ctx, module_config, *param_data); + skl_set_base_outfmt_format(skl, module_config, *param_data); break; default: - skl_set_base_module_format(ctx, module_config, *param_data); + skl_set_base_module_format(skl, module_config, *param_data); break; } - dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", + dev_dbg(skl->dev, "Module type=%d config size: %d bytes\n", module_config->id.module_id, param_size); print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4, *param_data, param_size, false); @@ -1004,7 +999,7 @@ static void skl_clear_module_state(struct skl_module_pin *mpin, int max, * We first calculate the module format, based on module type and then * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper */ -int skl_init_module(struct skl_sst *ctx, +int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *mconfig) { u16 module_config_size = 0; @@ -1012,19 +1007,19 @@ int skl_init_module(struct skl_sst *ctx, int ret; struct skl_ipc_init_instance_msg msg; - dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, + dev_dbg(skl->dev, "%s: module_id = %d instance=%d\n", __func__, mconfig->id.module_id, mconfig->id.pvt_id); if (mconfig->pipe->state != SKL_PIPE_CREATED) { - dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", + dev_err(skl->dev, "Pipe not created state= %d pipe_id= %d\n", mconfig->pipe->state, mconfig->pipe->ppl_id); return -EIO; } - ret = skl_set_module_format(ctx, mconfig, + ret = skl_set_module_format(skl, mconfig, &module_config_size, ¶m_data); if (ret < 0) { - dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); + dev_err(skl->dev, "Failed to set module format ret=%d\n", ret); return ret; } @@ -1035,9 +1030,9 @@ int skl_init_module(struct skl_sst *ctx, msg.core_id = mconfig->core_id; msg.domain = mconfig->domain; - ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); + ret = skl_ipc_init_instance(&skl->ipc, &msg, param_data); if (ret < 0) { - dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); + dev_err(skl->dev, "Failed to init instance ret=%d\n", ret); kfree(param_data); return ret; } @@ -1046,15 +1041,15 @@ int skl_init_module(struct skl_sst *ctx, return ret; } -static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg +static void skl_dump_bind_info(struct skl_dev *skl, struct skl_module_cfg *src_module, struct skl_module_cfg *dst_module) { - dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", + dev_dbg(skl->dev, "%s: src module_id = %d src_instance=%d\n", __func__, src_module->id.module_id, src_module->id.pvt_id); - dev_dbg(ctx->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, + dev_dbg(skl->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, dst_module->id.module_id, dst_module->id.pvt_id); - dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", + dev_dbg(skl->dev, "src_module state = %d dst module state = %d\n", src_module->m_state, dst_module->m_state); } @@ -1063,7 +1058,7 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg * it is already bind. * Find the pin allocated and unbind then using bind_unbind IPC */ -int skl_unbind_modules(struct skl_sst *ctx, +int skl_unbind_modules(struct skl_dev *skl, struct skl_module_cfg *src_mcfg, struct skl_module_cfg *dst_mcfg) { @@ -1075,7 +1070,7 @@ int skl_unbind_modules(struct skl_sst *ctx, int out_max = src_mcfg->module->max_output_pins; int src_index, dst_index, src_pin_state, dst_pin_state; - skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); + skl_dump_bind_info(skl, src_mcfg, dst_mcfg); /* get src queue index */ src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); @@ -1104,7 +1099,7 @@ int skl_unbind_modules(struct skl_sst *ctx, msg.dst_instance_id = dst_mcfg->id.pvt_id; msg.bind = false; - ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); + ret = skl_ipc_bind_unbind(&skl->ipc, &msg); if (!ret) { /* free queue only if unbind is success */ skl_free_queue(src_mcfg->m_out_pin, src_index); @@ -1142,7 +1137,7 @@ static void fill_pin_params(struct skl_audio_data_format *pin_fmt, * This function finds the pins and then sends bund_unbind IPC message to * DSP using IPC helper */ -int skl_bind_modules(struct skl_sst *ctx, +int skl_bind_modules(struct skl_dev *skl, struct skl_module_cfg *src_mcfg, struct skl_module_cfg *dst_mcfg) { @@ -1156,7 +1151,7 @@ int skl_bind_modules(struct skl_sst *ctx, struct skl_module *module; struct skl_module_iface *fmt; - skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); + skl_dump_bind_info(skl, src_mcfg, dst_mcfg); if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || dst_mcfg->m_state < SKL_MODULE_INIT_DONE) @@ -1188,7 +1183,7 @@ int skl_bind_modules(struct skl_sst *ctx, format = &fmt->outputs[src_index].fmt; fill_pin_params(&(pin_fmt.dst_fmt), format); - ret = skl_set_module_params(ctx, (void *)&pin_fmt, + ret = skl_set_module_params(skl, (void *)&pin_fmt, sizeof(struct skl_cpr_pin_fmt), CPR_SINK_FMT_PARAM_ID, src_mcfg); @@ -1198,7 +1193,7 @@ int skl_bind_modules(struct skl_sst *ctx, msg.dst_queue = dst_index; - dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", + dev_dbg(skl->dev, "src queue = %d dst queue =%d\n", msg.src_queue, msg.dst_queue); msg.module_id = src_mcfg->id.module_id; @@ -1207,7 +1202,7 @@ int skl_bind_modules(struct skl_sst *ctx, msg.dst_instance_id = dst_mcfg->id.pvt_id; msg.bind = true; - ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); + ret = skl_ipc_bind_unbind(&skl->ipc, &msg); if (!ret) { src_mcfg->m_state = SKL_MODULE_BIND_DONE; @@ -1223,12 +1218,12 @@ int skl_bind_modules(struct skl_sst *ctx, return ret; } -static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, +static int skl_set_pipe_state(struct skl_dev *skl, struct skl_pipe *pipe, enum skl_ipc_pipeline_state state) { - dev_dbg(ctx->dev, "%s: pipe_state = %d\n", __func__, state); + dev_dbg(skl->dev, "%s: pipe_state = %d\n", __func__, state); - return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); + return skl_ipc_set_pipeline_state(&skl->ipc, pipe->ppl_id, state); } /* @@ -1237,17 +1232,17 @@ static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, * This function creates pipeline, by sending create pipeline IPC messages * to FW */ -int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) +int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe) { int ret; - dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); + dev_dbg(skl->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); - ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, + ret = skl_ipc_create_pipeline(&skl->ipc, pipe->memory_pages, pipe->pipe_priority, pipe->ppl_id, pipe->lp_mode); if (ret < 0) { - dev_err(ctx->dev, "Failed to create pipeline\n"); + dev_err(skl->dev, "Failed to create pipeline\n"); return ret; } @@ -1262,11 +1257,11 @@ int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) * reset state. Finish the procedure by sending delete pipeline IPC. * DSP will stop the DMA engines and release resources */ -int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe) { int ret; - dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); + dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); /* If pipe was not created in FW, do not try to delete it */ if (pipe->state < SKL_PIPE_CREATED) @@ -1274,9 +1269,9 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) /* If pipe is started, do stop the pipe in FW. */ if (pipe->state >= SKL_PIPE_STARTED) { - ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); if (ret < 0) { - dev_err(ctx->dev, "Failed to stop pipeline\n"); + dev_err(skl->dev, "Failed to stop pipeline\n"); return ret; } @@ -1284,17 +1279,17 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) } /* reset pipe state before deletion */ - ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); + ret = skl_set_pipe_state(skl, pipe, PPL_RESET); if (ret < 0) { - dev_err(ctx->dev, "Failed to reset pipe ret=%d\n", ret); + dev_err(skl->dev, "Failed to reset pipe ret=%d\n", ret); return ret; } pipe->state = SKL_PIPE_RESET; - ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); + ret = skl_ipc_delete_pipeline(&skl->ipc, pipe->ppl_id); if (ret < 0) { - dev_err(ctx->dev, "Failed to delete pipeline\n"); + dev_err(skl->dev, "Failed to delete pipeline\n"); return ret; } @@ -1308,28 +1303,28 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) * For processing data the pipe need to be run by sending IPC set pipe state * to DSP */ -int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe) { int ret; - dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); + dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); /* If pipe was not created in FW, do not try to pause or delete */ if (pipe->state < SKL_PIPE_CREATED) return 0; /* Pipe has to be paused before it is started */ - ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); if (ret < 0) { - dev_err(ctx->dev, "Failed to pause pipe\n"); + dev_err(skl->dev, "Failed to pause pipe\n"); return ret; } pipe->state = SKL_PIPE_PAUSED; - ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); + ret = skl_set_pipe_state(skl, pipe, PPL_RUNNING); if (ret < 0) { - dev_err(ctx->dev, "Failed to start pipe\n"); + dev_err(skl->dev, "Failed to start pipe\n"); return ret; } @@ -1342,19 +1337,19 @@ int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) * Stop the pipeline by sending set pipe state IPC * DSP doesnt implement stop so we always send pause message */ -int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe) { int ret; - dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); + dev_dbg(skl->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); /* If pipe was not created in FW, do not try to pause or delete */ if (pipe->state < SKL_PIPE_PAUSED) return 0; - ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); if (ret < 0) { - dev_dbg(ctx->dev, "Failed to stop pipe\n"); + dev_dbg(skl->dev, "Failed to stop pipe\n"); return ret; } @@ -1367,7 +1362,7 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) * Reset the pipeline by sending set pipe state IPC this will reset the DMA * from the DSP side */ -int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe) { int ret; @@ -1375,9 +1370,9 @@ int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) if (pipe->state < SKL_PIPE_PAUSED) return 0; - ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); + ret = skl_set_pipe_state(skl, pipe, PPL_RESET); if (ret < 0) { - dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret); + dev_dbg(skl->dev, "Failed to reset pipe ret=%d\n", ret); return ret; } @@ -1387,7 +1382,7 @@ int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) } /* Algo parameter set helper function */ -int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, +int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg) { struct skl_ipc_large_config_msg msg; @@ -1397,10 +1392,10 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, msg.param_data_size = size; msg.large_param_id = param_id; - return skl_ipc_set_large_config(&ctx->ipc, &msg, params); + return skl_ipc_set_large_config(&skl->ipc, &msg, params); } -int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, +int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg) { struct skl_ipc_large_config_msg msg; @@ -1410,5 +1405,5 @@ int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, msg.param_data_size = size; msg.large_param_id = param_id; - return skl_ipc_get_large_config(&ctx->ipc, &msg, params); + return skl_ipc_get_large_config(&skl->ipc, &msg, params); } diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 1132109cb992..6fc3a190067e 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -126,7 +126,7 @@ static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, } struct nhlt_specific_cfg -*skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, +*skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type, u8 s_fmt, u8 num_ch, u32 s_rate, u8 dirn, u8 dev_type) { @@ -162,7 +162,7 @@ struct nhlt_specific_cfg return NULL; } -int skl_get_dmic_geo(struct skl *skl) +int skl_get_dmic_geo(struct skl_dev *skl) { struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; struct nhlt_endpoint *epnt; @@ -219,7 +219,7 @@ static void skl_nhlt_trim_space(char *trim) s[cnt] = '\0'; } -int skl_nhlt_update_topology_bin(struct skl *skl) +int skl_nhlt_update_topology_bin(struct skl_dev *skl) { struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; struct hdac_bus *bus = skl_to_bus(skl); @@ -243,7 +243,7 @@ static ssize_t skl_nhlt_platform_id_show(struct device *dev, { struct pci_dev *pci = to_pci_dev(dev); struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; char platform_id[32]; @@ -257,7 +257,7 @@ static ssize_t skl_nhlt_platform_id_show(struct device *dev, static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); -int skl_nhlt_create_sysfs(struct skl *skl) +int skl_nhlt_create_sysfs(struct skl_dev *skl) { struct device *dev = &skl->pci->dev; @@ -267,7 +267,7 @@ int skl_nhlt_create_sysfs(struct skl *skl) return 0; } -void skl_nhlt_remove_sysfs(struct skl *skl) +void skl_nhlt_remove_sysfs(struct skl_dev *skl) { struct device *dev = &skl->pci->dev; @@ -279,7 +279,7 @@ void skl_nhlt_remove_sysfs(struct skl *skl) * stores all possible rates supported in a rate table for the corresponding * sclk/sclkfs. */ -static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks, +static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, struct nhlt_fmt *fmt, u8 id) { struct skl_i2s_config_blob_ext *i2s_config_ext; @@ -377,7 +377,7 @@ static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks, } } -static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk, +static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, struct nhlt_fmt *fmt, u8 id) { struct skl_i2s_config_blob_ext *i2s_config_ext; @@ -421,7 +421,7 @@ static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk, mclk[id].parent_name = parent->name; } -void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks) +void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks) { struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; struct nhlt_endpoint *epnt; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 760bbcf9a469..2ae5d09d7228 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -116,7 +116,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, { struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct snd_soc_dapm_widget *w; - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) w = dai->playback_widget; @@ -132,7 +132,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) { struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); unsigned int format_val; struct hdac_stream *hstream; struct hdac_ext_stream *stream; @@ -224,7 +224,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, struct hdac_ext_stream *stream; struct snd_pcm_runtime *runtime = substream->runtime; struct skl_dma_params *dma_params; - struct skl *skl = get_skl_ctx(dai->dev); + struct skl_dev *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); @@ -271,7 +271,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, static int skl_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct skl *skl = get_skl_ctx(dai->dev); + struct skl_dev *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig; int ret; @@ -288,7 +288,7 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream, mconfig->pipe->state == SKL_PIPE_CREATED || mconfig->pipe->state == SKL_PIPE_PAUSED)) { - ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); + ret = skl_reset_pipe(skl, mconfig->pipe); if (ret < 0) return ret; @@ -350,7 +350,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct skl_dma_params *dma_params = NULL; - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct skl_module_cfg *mconfig; dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); @@ -370,9 +370,9 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, * CGCTL.MISCBDCGE if disabled by driver */ if (!strncmp(dai->name, "Reference Pin", 13) && - skl->skl_sst->miscbdcg_disabled) { - skl->skl_sst->enable_miscbdcge(dai->dev, true); - skl->skl_sst->miscbdcg_disabled = false; + skl->miscbdcg_disabled) { + skl->enable_miscbdcge(dai->dev, true); + skl->miscbdcg_disabled = false; } mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); @@ -387,7 +387,7 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, { struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct skl *skl = get_skl_ctx(dai->dev); + struct skl_dev *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig; int ret; @@ -396,7 +396,7 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); if (mconfig) { - ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); + ret = skl_reset_pipe(skl, mconfig->pipe); if (ret < 0) dev_err(dai->dev, "%s:Reset failed ret =%d", __func__, ret); @@ -471,8 +471,7 @@ static int skl_decoupled_trigger(struct snd_pcm_substream *substream, static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct skl *skl = get_skl_ctx(dai->dev); - struct skl_sst *ctx = skl->skl_sst; + struct skl_dev *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig; struct hdac_bus *bus = get_bus_ctx(substream); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); @@ -515,7 +514,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, ret = skl_decoupled_trigger(substream, cmd); if (ret < 0) return ret; - return skl_run_pipe(ctx, mconfig->pipe); + return skl_run_pipe(skl, mconfig->pipe); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -526,7 +525,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, * there are no underrun/overrun in the case if there is a delay * between the two operations. */ - ret = skl_stop_pipe(ctx, mconfig->pipe); + ret = skl_stop_pipe(skl, mconfig->pipe); if (ret < 0) return ret; @@ -602,14 +601,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct skl *skl = get_skl_ctx(dai->dev); + struct skl_dev *skl = get_skl_ctx(dai->dev); struct skl_module_cfg *mconfig = NULL; /* In case of XRUN recovery, reset the FW pipe to clean state */ mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); if (mconfig && !mconfig->pipe->passthru && (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) - skl_reset_pipe(skl->skl_sst, mconfig->pipe); + skl_reset_pipe(skl, mconfig->pipe); return 0; } @@ -1301,7 +1300,7 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct snd_pcm *pcm = rtd->pcm; unsigned int size; - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { @@ -1318,9 +1317,9 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) return 0; } -static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) +static int skl_get_module_info(struct skl_dev *skl, + struct skl_module_cfg *mconfig) { - struct skl_sst *ctx = skl->skl_sst; struct skl_module_inst_id *pin_id; guid_t *uuid_mod, *uuid_tplg; struct skl_module *skl_module; @@ -1329,12 +1328,12 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) uuid_mod = (guid_t *)mconfig->guid; - if (list_empty(&ctx->uuid_list)) { - dev_err(ctx->dev, "Module list is empty\n"); + if (list_empty(&skl->uuid_list)) { + dev_err(skl->dev, "Module list is empty\n"); return -EIO; } - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { if (guid_equal(uuid_mod, &module->uuid)) { mconfig->id.module_id = module->id; if (mconfig->module) @@ -1361,7 +1360,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) if (skl->nr_modules && ret) return ret; - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { for (i = 0; i < MAX_IN_QUEUE; i++) { pin_id = &mconfig->m_in_pin[i].id; if (guid_equal(&pin_id->mod_uuid, &module->uuid)) @@ -1378,7 +1377,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) return 0; } -static int skl_populate_modules(struct skl *skl) +static int skl_populate_modules(struct skl_dev *skl) { struct skl_pipeline *p; struct skl_pipe_module *m; @@ -1393,7 +1392,7 @@ static int skl_populate_modules(struct skl *skl) ret = skl_get_module_info(skl, mconfig); if (ret < 0) { - dev_err(skl->skl_sst->dev, + dev_err(skl->dev, "query module info failed\n"); return ret; } @@ -1408,7 +1407,7 @@ static int skl_populate_modules(struct skl *skl) static int skl_platform_soc_probe(struct snd_soc_component *component) { struct hdac_bus *bus = dev_get_drvdata(component->dev); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); const struct skl_dsp_ops *ops; int ret; @@ -1434,22 +1433,22 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) * Disable dynamic clock and power gating during firmware * and library download */ - skl->skl_sst->enable_miscbdcge(component->dev, false); - skl->skl_sst->clock_power_gating(component->dev, false); + skl->enable_miscbdcge(component->dev, false); + skl->clock_power_gating(component->dev, false); - ret = ops->init_fw(component->dev, skl->skl_sst); - skl->skl_sst->enable_miscbdcge(component->dev, true); - skl->skl_sst->clock_power_gating(component->dev, true); + ret = ops->init_fw(component->dev, skl); + skl->enable_miscbdcge(component->dev, true); + skl->clock_power_gating(component->dev, true); if (ret < 0) { dev_err(component->dev, "Failed to boot first fw: %d\n", ret); return ret; } skl_populate_modules(skl); - skl->skl_sst->update_d0i3c = skl_update_d0i3c; - skl_dsp_enable_notification(skl->skl_sst, false); + skl->update_d0i3c = skl_update_d0i3c; + skl_dsp_enable_notification(skl, false); if (skl->cfg.astate_cfg != NULL) { - skl_dsp_set_astate_cfg(skl->skl_sst, + skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count, skl->cfg.astate_cfg); } @@ -1463,7 +1462,7 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) static void skl_pcm_remove(struct snd_soc_component *component) { struct hdac_bus *bus = dev_get_drvdata(component->dev); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); skl_tplg_exit(component, bus); @@ -1486,7 +1485,7 @@ int skl_platform_register(struct device *dev) struct snd_soc_dai_driver *dais; int num_dais = ARRAY_SIZE(skl_platform_dai); struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), GFP_KERNEL); @@ -1520,7 +1519,7 @@ int skl_platform_register(struct device *dev) int skl_platform_unregister(struct device *dev) { struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct skl_module_deferred_bind *modules, *tmp; if (!list_empty(&skl->bind_list)) { diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index 5bb6e40d4d3e..1608d21bcba1 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -101,7 +101,7 @@ static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type) } /* Sends dma control IPC to turn the clock ON/OFF */ -static int skl_send_clk_dma_control(struct skl *skl, +static int skl_send_clk_dma_control(struct skl_dev *skl, struct skl_clk_rate_cfg_table *rcfg, u32 vbus_id, u8 clk_type, bool enable) @@ -152,7 +152,7 @@ static int skl_send_clk_dma_control(struct skl *skl, memcpy(i2s_config + sp_cfg->size, data, size); node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4)); - ret = skl_dsp_set_dma_control(skl->skl_sst, (u32 *)i2s_config, + ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config, i2s_config_size, node_id); kfree(i2s_config); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 36590c5b4673..225706d148d8 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -12,7 +12,7 @@ #include "../common/sst-dsp.h" #include "../common/sst-ipc.h" #include "../common/sst-dsp-priv.h" -#include "skl-sst-ipc.h" +#include "skl.h" /* various timeout values */ #define SKL_DSP_PU_TO 50 @@ -33,7 +33,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) */ void skl_dsp_init_core_state(struct sst_dsp *ctx) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int i; skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; @@ -48,7 +48,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) /* Get the mask for all enabled cores */ unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; unsigned int core_mask, en_cores_mask; u32 val; @@ -335,7 +335,7 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) */ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int ret = 0; if (core_id >= skl->cores.count) { @@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(skl_dsp_get_core); int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int ret = 0; if (core_id >= skl->cores.count) { diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index a80219562036..ed968f1042c7 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -15,9 +15,9 @@ #include "skl-sst-cldma.h" struct sst_dsp; -struct skl_sst; struct sst_dsp_device; struct skl_lib_info; +struct skl_dev; /* Intel HD Audio General DSP Registers */ #define SKL_ADSP_GEN_BASE 0x0 @@ -222,32 +222,32 @@ int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id); int skl_dsp_boot(struct sst_dsp *ctx); int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_sst **dsp); + struct skl_dev **dsp); int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_sst **dsp); -int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx); -int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx); -void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); -void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); + struct skl_dev **dsp); +int skl_sst_init_fw(struct device *dev, struct skl_dev *skl); +int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl); +void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, unsigned int offset, int index); -int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id); -int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id); -int skl_get_pvt_instance_id_map(struct skl_sst *ctx, +int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id); +int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id); +int skl_get_pvt_instance_id_map(struct skl_dev *skl, int module_id, int instance_id); -void skl_freeup_uuid_list(struct skl_sst *ctx); +void skl_freeup_uuid_list(struct skl_dev *skl); int skl_dsp_strip_extended_manifest(struct firmware *fw); -void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable); +void skl_dsp_enable_notification(struct skl_dev *skl, bool enable); -void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data); +void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data); int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, - struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, + struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, struct sst_dsp_device *skl_dev); -int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, +int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, struct firmware *stripped_fw, unsigned int hdr_offset, int index); void skl_release_library(struct skl_lib_info *linfo, int lib_count); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 2cc8f7d2d319..ee1493acc9a8 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -345,7 +345,7 @@ static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { - struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); + struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { @@ -436,7 +436,7 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, struct ipc_message *msg; u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; u64 *ipc_header = (u64 *)(&header); - struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); + struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); unsigned long flags; spin_lock_irqsave(&ipc->dsp->spinlock, flags); @@ -488,7 +488,7 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) { struct sst_dsp *dsp = context; - struct skl_sst *skl = sst_dsp_get_thread_context(dsp); + struct skl_dev *skl = sst_dsp_get_thread_context(dsp); struct sst_generic_ipc *ipc = &skl->ipc; struct skl_ipc_header header = {0}; u32 hipcie, hipct, hipcte; @@ -595,7 +595,7 @@ bool skl_ipc_int_status(struct sst_dsp *ctx) SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; } -int skl_ipc_init(struct device *dev, struct skl_sst *skl) +int skl_ipc_init(struct device *dev, struct skl_dev *skl) { struct sst_generic_ipc *ipc; int err; diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 9c31a48e99dd..93af08cf41d2 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -10,9 +10,9 @@ #include #include "../common/sst-ipc.h" +#include "skl-sst-dsp.h" struct sst_dsp; -struct skl_sst; struct sst_generic_ipc; enum skl_ipc_pipeline_state { @@ -67,54 +67,6 @@ struct skl_lib_info { const struct firmware *fw; }; -struct skl_sst { - struct device *dev; - struct sst_dsp *dsp; - - /* boot */ - wait_queue_head_t boot_wait; - bool boot_complete; - - /* module load */ - wait_queue_head_t mod_load_wait; - bool mod_load_complete; - bool mod_load_status; - - /* IPC messaging */ - struct sst_generic_ipc ipc; - - /* callback for miscbdge */ - void (*enable_miscbdcge)(struct device *dev, bool enable); - /* Is CGCTL.MISCBDCGE disabled */ - bool miscbdcg_disabled; - - /* Populate module information */ - struct list_head uuid_list; - - /* Is firmware loaded */ - bool fw_loaded; - - /* first boot ? */ - bool is_first_boot; - - /* multi-core */ - struct skl_dsp_cores cores; - - /* library info */ - struct skl_lib_info lib_info[SKL_MAX_LIB]; - int lib_count; - - /* Callback to update D0i3C register */ - void (*update_d0i3c)(struct device *dev, bool enable); - - struct skl_d0i3_data d0i3; - - const struct skl_dsp_ops *dsp_ops; - - /* Callback to update dynamic clock and power gating registers */ - void (*clock_power_gating)(struct device *dev, bool enable); -}; - struct skl_ipc_init_instance_msg { u32 module_id; u32 instance_id; @@ -204,7 +156,7 @@ void skl_ipc_int_disable(struct sst_dsp *dsp); bool skl_ipc_int_status(struct sst_dsp *dsp); void skl_ipc_free(struct sst_generic_ipc *ipc); -int skl_ipc_init(struct device *dev, struct skl_sst *skl); +int skl_ipc_init(struct device *dev, struct skl_dev *skl); void skl_clear_module_cnt(struct sst_dsp *ctx); void skl_ipc_process_reply(struct sst_generic_ipc *ipc, diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 928c677b506c..d43cbf4a71ef 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -8,10 +8,9 @@ #include #include #include -#include "skl-sst-dsp.h" #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" -#include "skl-sst-ipc.h" +#include "skl.h" #define DEFAULT_HASH_SHA256_LEN 32 @@ -99,12 +98,12 @@ static int skl_get_pvtid_map(struct uuid_module *module, int instance_id) return -EINVAL; } -int skl_get_pvt_instance_id_map(struct skl_sst *ctx, +int skl_get_pvt_instance_id_map(struct skl_dev *skl, int module_id, int instance_id) { struct uuid_module *module; - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { if (module->id == module_id) return skl_get_pvtid_map(module, instance_id); } @@ -163,19 +162,19 @@ static inline int skl_pvtid_128(struct uuid_module *module) /** * skl_get_pvt_id: generate a private id for use as module id * - * @ctx: driver context + * @skl: driver context * @uuid_mod: module's uuid * @instance_id: module's instance id * * This generates a 128 bit private unique id for a module TYPE so that * module instance is unique */ -int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id) +int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id) { struct uuid_module *module; int pvt_id; - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { if (guid_equal(uuid_mod, &module->uuid)) { pvt_id = skl_pvtid_128(module); @@ -194,18 +193,18 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id); /** * skl_put_pvt_id: free up the private id allocated * - * @ctx: driver context + * @skl: driver context * @uuid_mod: module's uuid * @pvt_id: module pvt id * * This frees a 128 bit private unique id previously generated */ -int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id) +int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id) { int i; struct uuid_module *module; - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { if (guid_equal(uuid_mod, &module->uuid)) { if (*pvt_id != 0) @@ -234,7 +233,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, struct adsp_module_entry *mod_entry; int i, num_entry, size; const char *buf; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct uuid_module *module; struct firmware stripped_fw; unsigned int safe_file; @@ -317,11 +316,11 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, return ret; } -void skl_freeup_uuid_list(struct skl_sst *ctx) +void skl_freeup_uuid_list(struct skl_dev *skl) { struct uuid_module *uuid, *_uuid; - list_for_each_entry_safe(uuid, _uuid, &ctx->uuid_list, list) { + list_for_each_entry_safe(uuid, _uuid, &skl->uuid_list, list) { list_del(&uuid->list); kfree(uuid); } @@ -355,16 +354,12 @@ int skl_dsp_strip_extended_manifest(struct firmware *fw) } int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, - struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, + struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, struct sst_dsp_device *skl_dev) { - struct skl_sst *skl; + struct skl_dev *skl = *dsp; struct sst_dsp *sst; - skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); - if (skl == NULL) - return -ENOMEM; - skl->dev = dev; skl_dev->thread_context = skl; INIT_LIST_HEAD(&skl->uuid_list); @@ -381,13 +376,11 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, INIT_LIST_HEAD(&sst->module_list); skl->is_first_boot = true; - if (dsp) - *dsp = skl; return 0; } -int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, +int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, struct firmware *stripped_fw, unsigned int hdr_offset, int index) { diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 70c3a604c381..8af7546def1f 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -16,7 +16,7 @@ #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" #include "../common/sst-ipc.h" -#include "skl-sst-ipc.h" +#include "skl.h" #define SKL_BASEFW_TIMEOUT 300 #define SKL_INIT_TIMEOUT 1000 @@ -66,7 +66,7 @@ static int skl_transfer_firmware(struct sst_dsp *ctx, static int skl_load_base_firmware(struct sst_dsp *ctx) { int ret = 0, i; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct firmware stripped_fw; u32 reg; @@ -161,7 +161,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) { int ret; struct skl_ipc_dxstate_info dx; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); /* If core0 is being turned on, we need to load the FW */ @@ -215,7 +215,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) { int ret; struct skl_ipc_dxstate_info dx; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); dx.core_mask = core_mask; @@ -332,7 +332,7 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, u32 size, u16 mod_id, u8 table_id, bool is_module) { int ret, bytes_left, curr_pos; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; skl->mod_load_complete = false; bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false); @@ -384,7 +384,7 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, static int skl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) { - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; struct firmware stripped_fw; int ret, i; @@ -443,7 +443,7 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) { int usage_cnt; - struct skl_sst *skl = ctx->thread_context; + struct skl_dev *skl = ctx->thread_context; int ret = 0; usage_cnt = skl_put_module(ctx, mod_id); @@ -518,9 +518,10 @@ static struct sst_dsp_device skl_dev = { }; int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp) + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_dev **dsp) { - struct skl_sst *skl; + struct skl_dev *skl; struct sst_dsp *sst; int ret; @@ -554,10 +555,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, } EXPORT_SYMBOL_GPL(skl_sst_dsp_init); -int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +int skl_sst_init_fw(struct device *dev, struct skl_dev *skl) { int ret; - struct sst_dsp *sst = ctx->dsp; + struct sst_dsp *sst = skl->dsp; ret = sst->fw_ops.load_fw(sst); if (ret < 0) { @@ -567,32 +568,32 @@ int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) skl_dsp_init_core_state(sst); - if (ctx->lib_count > 1) { - ret = sst->fw_ops.load_library(sst, ctx->lib_info, - ctx->lib_count); + if (skl->lib_count > 1) { + ret = sst->fw_ops.load_library(sst, skl->lib_info, + skl->lib_count); if (ret < 0) { dev_err(dev, "Load Library failed : %x\n", ret); return ret; } } - ctx->is_first_boot = false; + skl->is_first_boot = false; return 0; } EXPORT_SYMBOL_GPL(skl_sst_init_fw); -void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) { - if (ctx->dsp->fw) - release_firmware(ctx->dsp->fw); - skl_clear_module_table(ctx->dsp); - skl_freeup_uuid_list(ctx); - skl_ipc_free(&ctx->ipc); - ctx->dsp->ops->free(ctx->dsp); - if (ctx->boot_complete) { - ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); - skl_cldma_int_disable(ctx->dsp); + if (skl->dsp->fw) + release_firmware(skl->dsp->fw); + skl_clear_module_table(skl->dsp); + skl_freeup_uuid_list(skl); + skl_ipc_free(&skl->ipc); + skl->dsp->ops->free(skl->dsp); + if (skl->boot_complete) { + skl->dsp->cl_dev.ops.cl_cleanup_controller(skl->dsp); + skl_cldma_int_disable(skl->dsp); } } EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup); diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 6241e35213af..abf860109607 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -45,9 +45,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = { #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) -void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) +void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps) { - struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; + struct skl_d0i3_data *d0i3 = &skl->d0i3; switch (caps) { case SKL_D0I3_NONE: @@ -64,9 +64,9 @@ void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) } } -void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps) +void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps) { - struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; + struct skl_d0i3_data *d0i3 = &skl->d0i3; switch (caps) { case SKL_D0I3_NONE: @@ -113,18 +113,16 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, * Each pipelines needs memory to be allocated. Check if we have free memory * from available pool. */ -static bool skl_is_pipe_mem_avail(struct skl *skl, +static bool skl_is_pipe_mem_avail(struct skl_dev *skl, struct skl_module_cfg *mconfig) { - struct skl_sst *ctx = skl->skl_sst; - if (skl->resource.mem + mconfig->pipe->memory_pages > skl->resource.max_mem) { - dev_err(ctx->dev, + dev_err(skl->dev, "%s: module_id %d instance %d\n", __func__, mconfig->id.module_id, mconfig->id.instance_id); - dev_err(ctx->dev, + dev_err(skl->dev, "exceeds ppl memory available %d mem %d\n", skl->resource.max_mem, skl->resource.mem); return false; @@ -138,7 +136,7 @@ static bool skl_is_pipe_mem_avail(struct skl *skl, * Note: DSP does actual memory management we only keep track for complete * pool */ -static void skl_tplg_alloc_pipe_mem(struct skl *skl, +static void skl_tplg_alloc_pipe_mem(struct skl_dev *skl, struct skl_module_cfg *mconfig) { skl->resource.mem += mconfig->pipe->memory_pages; @@ -152,18 +150,17 @@ static void skl_tplg_alloc_pipe_mem(struct skl *skl, * pipe. */ -static bool skl_is_pipe_mcps_avail(struct skl *skl, +static bool skl_is_pipe_mcps_avail(struct skl_dev *skl, struct skl_module_cfg *mconfig) { - struct skl_sst *ctx = skl->skl_sst; u8 res_idx = mconfig->res_idx; struct skl_module_res *res = &mconfig->module->resources[res_idx]; if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { - dev_err(ctx->dev, + dev_err(skl->dev, "%s: module_id %d instance %d\n", __func__, mconfig->id.module_id, mconfig->id.instance_id); - dev_err(ctx->dev, + dev_err(skl->dev, "exceeds ppl mcps available %d > mem %d\n", skl->resource.max_mcps, skl->resource.mcps); return false; @@ -172,7 +169,7 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl, } } -static void skl_tplg_alloc_pipe_mcps(struct skl *skl, +static void skl_tplg_alloc_pipe_mcps(struct skl_dev *skl, struct skl_module_cfg *mconfig) { u8 res_idx = mconfig->res_idx; @@ -185,7 +182,7 @@ static void skl_tplg_alloc_pipe_mcps(struct skl *skl, * Free the mcps when tearing down */ static void -skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) +skl_tplg_free_pipe_mcps(struct skl_dev *skl, struct skl_module_cfg *mconfig) { u8 res_idx = mconfig->res_idx; struct skl_module_res *res = &mconfig->module->resources[res_idx]; @@ -197,30 +194,29 @@ skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) * Free the memory when tearing down */ static void -skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) +skl_tplg_free_pipe_mem(struct skl_dev *skl, struct skl_module_cfg *mconfig) { skl->resource.mem -= mconfig->pipe->memory_pages; } -static void skl_dump_mconfig(struct skl_sst *ctx, - struct skl_module_cfg *mcfg) +static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) { struct skl_module_iface *iface = &mcfg->module->formats[0]; - dev_dbg(ctx->dev, "Dumping config\n"); - dev_dbg(ctx->dev, "Input Format:\n"); - dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels); - dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); - dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); - dev_dbg(ctx->dev, "valid bit depth = %d\n", + dev_dbg(skl->dev, "Dumping config\n"); + dev_dbg(skl->dev, "Input Format:\n"); + dev_dbg(skl->dev, "channels = %d\n", iface->inputs[0].fmt.channels); + dev_dbg(skl->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); + dev_dbg(skl->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); + dev_dbg(skl->dev, "valid bit depth = %d\n", iface->inputs[0].fmt.valid_bit_depth); - dev_dbg(ctx->dev, "Output Format:\n"); - dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels); - dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); - dev_dbg(ctx->dev, "valid bit depth = %d\n", + dev_dbg(skl->dev, "Output Format:\n"); + dev_dbg(skl->dev, "channels = %d\n", iface->outputs[0].fmt.channels); + dev_dbg(skl->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); + dev_dbg(skl->dev, "valid bit depth = %d\n", iface->outputs[0].fmt.valid_bit_depth); - dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); + dev_dbg(skl->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); } static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) @@ -322,7 +318,7 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, * params, so once we have calculate params, we need buffer calculation as * well. */ -static void skl_tplg_update_buffer_size(struct skl_sst *ctx, +static void skl_tplg_update_buffer_size(struct skl_dev *skl, struct skl_module_cfg *mcfg) { int multiplier = 1; @@ -374,13 +370,12 @@ static u8 skl_tplg_be_dev_type(int dev_type) } static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, - struct skl_sst *ctx) + struct skl_dev *skl) { struct skl_module_cfg *m_cfg = w->priv; int link_type, dir; u32 ch, s_freq, s_fmt; struct nhlt_specific_cfg *cfg; - struct skl *skl = get_skl_ctx(ctx->dev); u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); int fmt_idx = m_cfg->fmt_idx; struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; @@ -389,7 +384,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, if (m_cfg->formats_config.caps_size > 0) return 0; - dev_dbg(ctx->dev, "Applying default cfg blob\n"); + dev_dbg(skl->dev, "Applying default cfg blob\n"); switch (m_cfg->dev_type) { case SKL_DEVICE_DMIC: link_type = NHLT_LINK_DMIC; @@ -425,9 +420,9 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, m_cfg->formats_config.caps_size = cfg->size; m_cfg->formats_config.caps = (u32 *) &cfg->caps; } else { - dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n", + dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", m_cfg->vbus_id, link_type, dir); - dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n", + dev_err(skl->dev, "PCM: ch %d, freq %d, fmt %d\n", ch, s_freq, s_fmt); return -EIO; } @@ -436,7 +431,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, } static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, - struct skl_sst *ctx) + struct skl_dev *skl) { struct skl_module_cfg *m_cfg = w->priv; struct skl_pipe_params *params = m_cfg->pipe->p_params; @@ -446,10 +441,10 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, if (!m_cfg->params_fixup) return; - dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n", + dev_dbg(skl->dev, "Mconfig for widget=%s BEFORE updation\n", w->name); - skl_dump_mconfig(ctx, m_cfg); + skl_dump_mconfig(skl, m_cfg); if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) is_fe = true; @@ -457,12 +452,12 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, is_fe = false; skl_tplg_update_params_fixup(m_cfg, params, is_fe); - skl_tplg_update_buffer_size(ctx, m_cfg); + skl_tplg_update_buffer_size(skl, m_cfg); - dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n", + dev_dbg(skl->dev, "Mconfig for widget=%s AFTER updation\n", w->name); - skl_dump_mconfig(ctx, m_cfg); + skl_dump_mconfig(skl, m_cfg); } /* @@ -471,7 +466,7 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, * set module params will be done after module is initialised. */ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, - struct skl_sst *ctx) + struct skl_dev *skl) { int i, ret; struct skl_module_cfg *mconfig = w->priv; @@ -483,7 +478,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, if (mconfig->formats_config.caps_size > 0 && mconfig->formats_config.set_params == SKL_PARAM_SET) { sp_cfg = &mconfig->formats_config; - ret = skl_set_module_params(ctx, sp_cfg->caps, + ret = skl_set_module_params(skl, sp_cfg->caps, sp_cfg->caps_size, sp_cfg->param_id, mconfig); if (ret < 0) @@ -497,7 +492,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, bc = (struct skl_algo_data *)sb->dobj.private; if (bc->set_params == SKL_PARAM_SET) { - ret = skl_set_module_params(ctx, + ret = skl_set_module_params(skl, (u32 *)bc->params, bc->size, bc->param_id, mconfig); if (ret < 0) @@ -542,15 +537,15 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) return 0; } -static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, +static int skl_tplg_module_prepare(struct skl_dev *skl, struct skl_pipe *pipe, struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) { switch (mcfg->dev_type) { case SKL_DEVICE_HDAHOST: - return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); + return skl_pcm_host_dma_prepare(skl->dev, pipe->p_params); case SKL_DEVICE_HDALINK: - return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); + return skl_pcm_link_dma_prepare(skl->dev, pipe->p_params); } return 0; @@ -562,12 +557,11 @@ static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, * skl_init_module() routine, so invoke that for all modules in a pipeline */ static int -skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) +skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) { struct skl_pipe_module *w_module; struct snd_soc_dapm_widget *w; struct skl_module_cfg *mconfig; - struct skl_sst *ctx = skl->skl_sst; u8 cfg_idx; int ret = 0; @@ -578,7 +572,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) /* check if module ids are populated */ if (mconfig->id.module_id < 0) { - dev_err(skl->skl_sst->dev, + dev_err(skl->dev, "module %pUL id not populated\n", (guid_t *)mconfig->guid); return -EIO; @@ -592,8 +586,8 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (!skl_is_pipe_mcps_avail(skl, mconfig)) return -ENOMEM; - if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) { - ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, + if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { + ret = skl->dsp->fw_ops.load_mod(skl->dsp, mconfig->id.module_id, mconfig->guid); if (ret < 0) return ret; @@ -602,50 +596,50 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) } /* prepare the DMA if the module is gateway cpr */ - ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); + ret = skl_tplg_module_prepare(skl, pipe, w, mconfig); if (ret < 0) return ret; /* update blob if blob is null for be with default value */ - skl_tplg_update_be_blob(w, ctx); + skl_tplg_update_be_blob(w, skl); /* * apply fix/conversion to module params based on * FE/BE params */ - skl_tplg_update_module_params(w, ctx); + skl_tplg_update_module_params(w, skl); uuid_mod = (guid_t *)mconfig->guid; - mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, + mconfig->id.pvt_id = skl_get_pvt_id(skl, uuid_mod, mconfig->id.instance_id); if (mconfig->id.pvt_id < 0) return ret; skl_tplg_set_module_init_data(w); - ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); + ret = skl_dsp_get_core(skl->dsp, mconfig->core_id); if (ret < 0) { - dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", + dev_err(skl->dev, "Failed to wake up core %d ret=%d\n", mconfig->core_id, ret); return ret; } - ret = skl_init_module(ctx, mconfig); + ret = skl_init_module(skl, mconfig); if (ret < 0) { - skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); + skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); goto err; } skl_tplg_alloc_pipe_mcps(skl, mconfig); - ret = skl_tplg_set_module_params(w, ctx); + ret = skl_tplg_set_module_params(w, skl); if (ret < 0) goto err; } return 0; err: - skl_dsp_put_core(ctx->dsp, mconfig->core_id); + skl_dsp_put_core(skl->dsp, mconfig->core_id); return ret; } -static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, +static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) { int ret = 0; @@ -657,19 +651,19 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, mconfig = w_module->w->priv; uuid_mod = (guid_t *)mconfig->guid; - if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && + if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod && mconfig->m_state > SKL_MODULE_UNINIT) { - ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, + ret = skl->dsp->fw_ops.unload_mod(skl->dsp, mconfig->id.module_id); if (ret < 0) return -EIO; } - skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); + skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); - ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); + ret = skl_dsp_put_core(skl->dsp, mconfig->core_id); if (ret < 0) { /* don't return; continue with other modules */ - dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", + dev_err(skl->dev, "Failed to sleep core %d ret=%d\n", mconfig->core_id, ret); } } @@ -686,9 +680,8 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, * 0th configuratation by default for such pipes. */ static int -skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) +skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) { - struct skl_sst *ctx = skl->skl_sst; struct skl_pipe *pipe = mconfig->pipe; struct skl_pipe_params *params = pipe->p_params; struct skl_path_config *pconfig = &pipe->configs[0]; @@ -702,7 +695,7 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) } if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { - dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n"); + dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); pipe->cur_config_idx = 0; pipe->memory_pages = pconfig->mem_pages; @@ -726,13 +719,13 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) fmt->channels, fmt->freq, fmt->bps)) { pipe->cur_config_idx = i; pipe->memory_pages = pconfig->mem_pages; - dev_dbg(ctx->dev, "Using pipe config: %d\n", i); + dev_dbg(skl->dev, "Using pipe config: %d\n", i); return 0; } } - dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", + dev_err(skl->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); return -EINVAL; } @@ -746,14 +739,13 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) * - finally bind all modules together */ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { int ret; struct skl_module_cfg *mconfig = w->priv; struct skl_pipe_module *w_module; struct skl_pipe *s_pipe = mconfig->pipe; struct skl_module_cfg *src_module = NULL, *dst_module, *module; - struct skl_sst *ctx = skl->skl_sst; struct skl_module_deferred_bind *modules; ret = skl_tplg_get_pipe_config(skl, mconfig); @@ -771,7 +763,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, * Create a list of modules for pipe. * This list contains modules from source to sink */ - ret = skl_create_pipeline(ctx, mconfig->pipe); + ret = skl_create_pipeline(skl, mconfig->pipe); if (ret < 0) return ret; @@ -792,7 +784,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, continue; } - ret = skl_bind_modules(ctx, src_module, dst_module); + ret = skl_bind_modules(skl, src_module, dst_module); if (ret < 0) return ret; @@ -810,7 +802,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, list_for_each_entry(modules, &skl->bind_list, node) { module = w_module->w->priv; if (modules->dst == module) - skl_bind_modules(ctx, modules->src, + skl_bind_modules(skl, modules->src, modules->dst); } } @@ -818,7 +810,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, return 0; } -static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, +static int skl_fill_sink_instance_id(struct skl_dev *skl, u32 *params, int size, struct skl_module_cfg *mcfg) { int i, pvt_id; @@ -829,7 +821,7 @@ static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, struct skl_mod_inst_map *inst = kpb_params->u.map; for (i = 0; i < kpb_params->num_modules; i++) { - pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id, + pvt_id = skl_get_pvt_instance_id_map(skl, inst->mod_id, inst->inst_id); if (pvt_id < 0) return -EINVAL; @@ -849,7 +841,7 @@ static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, * send params after binding */ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, - struct skl_module_cfg *mcfg, struct skl_sst *ctx) + struct skl_module_cfg *mcfg, struct skl_dev *skl) { int i, ret; struct skl_module_cfg *mconfig = w->priv; @@ -876,7 +868,7 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, if (mconfig->formats_config.caps_size > 0 && mconfig->formats_config.set_params == SKL_PARAM_BIND) { sp_cfg = &mconfig->formats_config; - ret = skl_set_module_params(ctx, sp_cfg->caps, + ret = skl_set_module_params(skl, sp_cfg->caps, sp_cfg->caps_size, sp_cfg->param_id, mconfig); if (ret < 0) @@ -894,10 +886,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, if (!params) return -ENOMEM; - skl_fill_sink_instance_id(ctx, params, bc->max, + skl_fill_sink_instance_id(skl, params, bc->max, mconfig); - ret = skl_set_module_params(ctx, params, + ret = skl_set_module_params(skl, params, bc->max, bc->param_id, mconfig); kfree(params); @@ -910,11 +902,11 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, return 0; } -static int skl_get_module_id(struct skl_sst *ctx, guid_t *uuid) +static int skl_get_module_id(struct skl_dev *skl, guid_t *uuid) { struct uuid_module *module; - list_for_each_entry(module, &ctx->uuid_list, list) { + list_for_each_entry(module, &skl->uuid_list, list) { if (guid_equal(uuid, &module->uuid)) return module->id; } @@ -922,7 +914,7 @@ static int skl_get_module_id(struct skl_sst *ctx, guid_t *uuid) return -EINVAL; } -static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, +static int skl_tplg_find_moduleid_from_uuid(struct skl_dev *skl, const struct snd_kcontrol_new *k) { struct soc_bytes_ext *sb = (void *) k->private_value; @@ -942,7 +934,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, params->num_modules = uuid_params->num_modules; for (i = 0; i < uuid_params->num_modules; i++) { - module_id = skl_get_module_id(skl->skl_sst, + module_id = skl_get_module_id(skl, &uuid_params->u.map_uuid[i].mod_uuid); if (module_id < 0) { devm_kfree(bus->dev, params); @@ -966,7 +958,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, * Retrieve the module id from UUID mentioned in the * post bind params */ -void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, +void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, struct snd_soc_dapm_widget *w) { struct skl_module_cfg *mconfig = w->priv; @@ -985,12 +977,12 @@ void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && (skl_tplg_find_moduleid_from_uuid(skl, &w->kcontrol_news[i]) < 0)) - dev_err(skl->skl_sst->dev, + dev_err(skl->dev, "%s: invalid kpb post bind params\n", __func__); } -static int skl_tplg_module_add_deferred_bind(struct skl *skl, +static int skl_tplg_module_add_deferred_bind(struct skl_dev *skl, struct skl_module_cfg *src, struct skl_module_cfg *dst) { struct skl_module_deferred_bind *m_list, *modules; @@ -1028,26 +1020,27 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl, } static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, - struct skl *skl, + struct skl_dev *skl, struct snd_soc_dapm_widget *src_w, struct skl_module_cfg *src_mconfig) { struct snd_soc_dapm_path *p; struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; struct skl_module_cfg *sink_mconfig; - struct skl_sst *ctx = skl->skl_sst; int ret; snd_soc_dapm_widget_for_each_sink_path(w, p) { if (!p->connect) continue; - dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); - dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); + dev_dbg(skl->dev, + "%s: src widget=%s\n", __func__, w->name); + dev_dbg(skl->dev, + "%s: sink widget=%s\n", __func__, p->sink->name); next_sink = p->sink; - if (!is_skl_dsp_widget_type(p->sink, ctx->dev)) + if (!is_skl_dsp_widget_type(p->sink, skl->dev)) return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); /* @@ -1056,7 +1049,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, * they are ones used for SKL so check that first */ if ((p->sink->priv != NULL) && - is_skl_dsp_widget_type(p->sink, ctx->dev)) { + is_skl_dsp_widget_type(p->sink, skl->dev)) { sink = p->sink; sink_mconfig = sink->priv; @@ -1088,19 +1081,21 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, continue; /* Bind source to sink, mixin is always source */ - ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); + ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); if (ret) return ret; /* set module params after bind */ - skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx); - skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); + skl_tplg_set_module_bind_params(src_w, + src_mconfig, skl); + skl_tplg_set_module_bind_params(sink, + sink_mconfig, skl); /* Start sinks pipe first */ if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) - ret = skl_run_pipe(ctx, + ret = skl_run_pipe(skl, sink_mconfig->pipe); if (ret) return ret; @@ -1125,10 +1120,9 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, * - Then run current pipe */ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { struct skl_module_cfg *src_mconfig; - struct skl_sst *ctx = skl->skl_sst; int ret = 0; src_mconfig = w->priv; @@ -1144,25 +1138,24 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, /* Start source pipe last after starting all sinks */ if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) - return skl_run_pipe(ctx, src_mconfig->pipe); + return skl_run_pipe(skl, src_mconfig->pipe); return 0; } static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( - struct snd_soc_dapm_widget *w, struct skl *skl) + struct snd_soc_dapm_widget *w, struct skl_dev *skl) { struct snd_soc_dapm_path *p; struct snd_soc_dapm_widget *src_w = NULL; - struct skl_sst *ctx = skl->skl_sst; snd_soc_dapm_widget_for_each_source_path(w, p) { src_w = p->source; if (!p->connect) continue; - dev_dbg(ctx->dev, "sink widget=%s\n", w->name); - dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); + dev_dbg(skl->dev, "sink widget=%s\n", w->name); + dev_dbg(skl->dev, "src widget=%s\n", p->source->name); /* * here we will check widgets in sink pipelines, so that can @@ -1170,7 +1163,7 @@ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( * ones used for SKL so check that first */ if ((p->source->priv != NULL) && - is_skl_dsp_widget_type(p->source, ctx->dev)) { + is_skl_dsp_widget_type(p->source, skl->dev)) { return p->source; } } @@ -1191,12 +1184,11 @@ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( * - start this pipeline */ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { int ret = 0; struct snd_soc_dapm_widget *source, *sink; struct skl_module_cfg *src_mconfig, *sink_mconfig; - struct skl_sst *ctx = skl->skl_sst; int src_pipe_started = 0; sink = w; @@ -1222,16 +1214,16 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, } if (src_pipe_started) { - ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); + ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); if (ret) return ret; /* set module params after bind */ - skl_tplg_set_module_bind_params(source, src_mconfig, ctx); - skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); + skl_tplg_set_module_bind_params(source, src_mconfig, skl); + skl_tplg_set_module_bind_params(sink, sink_mconfig, skl); if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) - ret = skl_run_pipe(ctx, sink_mconfig->pipe); + ret = skl_run_pipe(skl, sink_mconfig->pipe); } return ret; @@ -1244,16 +1236,15 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, * - unbind with source pipelines if still connected */ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { struct skl_module_cfg *src_mconfig, *sink_mconfig; int ret = 0, i; - struct skl_sst *ctx = skl->skl_sst; sink_mconfig = w->priv; /* Stop the pipe */ - ret = skl_stop_pipe(ctx, sink_mconfig->pipe); + ret = skl_stop_pipe(skl, sink_mconfig->pipe); if (ret) return ret; @@ -1263,7 +1254,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, if (!src_mconfig) continue; - ret = skl_unbind_modules(ctx, + ret = skl_unbind_modules(skl, src_mconfig, sink_mconfig); } } @@ -1280,12 +1271,11 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, * deleted, pipeline delete is enough here */ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { struct skl_module_cfg *mconfig = w->priv; struct skl_pipe_module *w_module; struct skl_module_cfg *src_module = NULL, *dst_module; - struct skl_sst *ctx = skl->skl_sst; struct skl_pipe *s_pipe = mconfig->pipe; struct skl_module_deferred_bind *modules, *tmp; @@ -1307,7 +1297,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, * modules from deferred bind list. */ if (modules->dst == src_module) { - skl_unbind_modules(ctx, modules->src, + skl_unbind_modules(skl, modules->src, modules->dst); } @@ -1334,18 +1324,18 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, continue; } - skl_unbind_modules(ctx, src_module, dst_module); + skl_unbind_modules(skl, src_module, dst_module); src_module = dst_module; } - skl_delete_pipe(ctx, mconfig->pipe); + skl_delete_pipe(skl, mconfig->pipe); list_for_each_entry(w_module, &s_pipe->w_list, node) { src_module = w_module->w->priv; src_module->m_state = SKL_MODULE_UNINIT; } - return skl_tplg_unload_pipe_modules(ctx, s_pipe); + return skl_tplg_unload_pipe_modules(skl, s_pipe); } /* @@ -1355,16 +1345,15 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, * - In source pipe is connected, unbind with source pipelines */ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, - struct skl *skl) + struct skl_dev *skl) { struct skl_module_cfg *src_mconfig, *sink_mconfig; int ret = 0, i; - struct skl_sst *ctx = skl->skl_sst; src_mconfig = w->priv; /* Stop the pipe since this is a mixin module */ - ret = skl_stop_pipe(ctx, src_mconfig->pipe); + ret = skl_stop_pipe(skl, src_mconfig->pipe); if (ret) return ret; @@ -1377,7 +1366,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, * This is a connecter and if path is found that means * unbind between source and sink has not happened yet */ - ret = skl_unbind_modules(ctx, src_mconfig, + ret = skl_unbind_modules(skl, src_mconfig, sink_mconfig); } } @@ -1395,7 +1384,7 @@ static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct snd_soc_dapm_context *dapm = w->dapm; - struct skl *skl = get_skl_ctx(dapm->dev); + struct skl_dev *skl = get_skl_ctx(dapm->dev); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1425,7 +1414,7 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, { struct snd_soc_dapm_context *dapm = w->dapm; - struct skl *skl = get_skl_ctx(dapm->dev); + struct skl_dev *skl = get_skl_ctx(dapm->dev); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1446,10 +1435,10 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); struct skl_module_cfg *mconfig = w->priv; - struct skl *skl = get_skl_ctx(w->dapm->dev); + struct skl_dev *skl = get_skl_ctx(w->dapm->dev); if (w->power) - skl_get_module_params(skl->skl_sst, (u32 *)bc->params, + skl_get_module_params(skl, (u32 *)bc->params, bc->size, bc->param_id, mconfig); /* decrement size for TLV header */ @@ -1481,7 +1470,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, struct soc_bytes_ext *sb = (struct soc_bytes_ext *)kcontrol->private_value; struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; - struct skl *skl = get_skl_ctx(w->dapm->dev); + struct skl_dev *skl = get_skl_ctx(w->dapm->dev); if (ac->params) { /* @@ -1498,7 +1487,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, return -EFAULT; if (w->power) - return skl_set_module_params(skl->skl_sst, + return skl_set_module_params(skl, (u32 *)ac->params, ac->size, ac->param_id, mconfig); } @@ -1659,7 +1648,7 @@ int skl_tplg_update_pipe_params(struct device *dev, struct skl_pipe_params *params) { struct skl_module_res *res = &mconfig->module->resources[0]; - struct skl *skl = get_skl_ctx(dev); + struct skl_dev *skl = get_skl_ctx(dev); struct skl_module_fmt *format = NULL; u8 cfg_idx = mconfig->pipe->cur_config_idx; @@ -1856,7 +1845,7 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, struct skl_pipe_params *params) { struct nhlt_specific_cfg *cfg; - struct skl *skl = get_skl_ctx(dai->dev); + struct skl_dev *skl = get_skl_ctx(dai->dev); int link_type = skl_tplg_be_link_type(mconfig->dev_type); u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); @@ -2070,7 +2059,7 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev, * Return an existing pipe if the pipe already exists. */ static int skl_tplg_add_pipe(struct device *dev, - struct skl_module_cfg *mconfig, struct skl *skl, + struct skl_module_cfg *mconfig, struct skl_dev *skl, struct snd_soc_tplg_vendor_value_elem *tkn_elem) { struct skl_pipeline *ppl; @@ -2381,7 +2370,7 @@ static int skl_tplg_fill_res_tkn(struct device *dev, */ static int skl_tplg_get_token(struct device *dev, struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl *skl, struct skl_module_cfg *mconfig) + struct skl_dev *skl, struct skl_module_cfg *mconfig) { int tkn_count = 0; int ret; @@ -2631,7 +2620,7 @@ static int skl_tplg_get_token(struct device *dev, * module private data */ static int skl_tplg_get_tokens(struct device *dev, - char *pvt_data, struct skl *skl, + char *pvt_data, struct skl_dev *skl, struct skl_module_cfg *mconfig, int block_size) { struct snd_soc_tplg_vendor_array *array; @@ -2727,8 +2716,8 @@ static int skl_tplg_get_desc_blocks(struct device *dev, * Otherwise we create a new instance and add into driver list */ static int skl_tplg_add_pipe_v4(struct device *dev, - struct skl_module_cfg *mconfig, struct skl *skl, - struct skl_dfw_v4_pipe *dfw_pipe) + struct skl_module_cfg *mconfig, struct skl_dev *skl, + struct skl_dfw_v4_pipe *dfw_pipe) { struct skl_pipeline *ppl; struct skl_pipe *pipe; @@ -2804,7 +2793,7 @@ static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt, } static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, - struct skl *skl, struct device *dev, + struct skl_dev *skl, struct device *dev, struct skl_module_cfg *mconfig) { struct skl_dfw_v4_module *dfw = @@ -2886,7 +2875,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, * for the type and size of the suceeding data block. */ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, - struct skl *skl, struct device *dev, + struct skl_dev *skl, struct device *dev, struct skl_module_cfg *mconfig) { struct snd_soc_tplg_vendor_array *array; @@ -2981,9 +2970,8 @@ static void skl_clear_pin_config(struct snd_soc_component *component, } } -void skl_cleanup_resources(struct skl *skl) +void skl_cleanup_resources(struct skl_dev *skl) { - struct skl_sst *ctx = skl->skl_sst; struct snd_soc_component *soc_component = skl->component; struct snd_soc_dapm_widget *w; struct snd_soc_card *card; @@ -2999,11 +2987,11 @@ void skl_cleanup_resources(struct skl *skl) skl->resource.mcps = 0; list_for_each_entry(w, &card->widgets, list) { - if (is_skl_dsp_widget_type(w, ctx->dev) && w->priv != NULL) + if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) skl_clear_pin_config(soc_component, w); } - skl_clear_module_cnt(ctx->dsp); + skl_clear_module_cnt(skl->dsp); } /* @@ -3019,7 +3007,7 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, { int ret; struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct skl_module_cfg *mconfig; if (!tplg_w->priv.size) @@ -3163,21 +3151,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, static int skl_tplg_fill_str_mfest_tkn(struct device *dev, struct snd_soc_tplg_vendor_string_elem *str_elem, - struct skl *skl) + struct skl_dev *skl) { int tkn_count = 0; static int ref_count; switch (str_elem->token) { case SKL_TKN_STR_LIB_NAME: - if (ref_count > skl->skl_sst->lib_count - 1) { + if (ref_count > skl->lib_count - 1) { ref_count = 0; return -EINVAL; } - strncpy(skl->skl_sst->lib_info[ref_count].name, + strncpy(skl->lib_info[ref_count].name, str_elem->string, - ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); + ARRAY_SIZE(skl->lib_info[ref_count].name)); ref_count++; break; @@ -3192,7 +3180,7 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, static int skl_tplg_get_str_tkn(struct device *dev, struct snd_soc_tplg_vendor_array *array, - struct skl *skl) + struct skl_dev *skl) { int tkn_count = 0, ret; struct snd_soc_tplg_vendor_string_elem *str_elem; @@ -3299,7 +3287,7 @@ static int skl_tplg_fill_mod_info(struct device *dev, static int skl_tplg_get_int_tkn(struct device *dev, struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl *skl) + struct skl_dev *skl) { int tkn_count = 0, ret; static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; @@ -3319,7 +3307,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, switch (tkn_elem->token) { case SKL_TKN_U32_LIB_COUNT: - skl->skl_sst->lib_count = tkn_elem->value; + skl->lib_count = tkn_elem->value; break; case SKL_TKN_U8_NUM_MOD: @@ -3466,7 +3454,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, } static int skl_tplg_get_manifest_uuid(struct device *dev, - struct skl *skl, + struct skl_dev *skl, struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) { static int ref_count; @@ -3489,7 +3477,7 @@ static int skl_tplg_get_manifest_uuid(struct device *dev, * type. */ static int skl_tplg_get_manifest_tkn(struct device *dev, - char *pvt_data, struct skl *skl, + char *pvt_data, struct skl_dev *skl, int block_size) { int tkn_count = 0, ret; @@ -3550,7 +3538,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, * preceded by descriptors for type and size of data block. */ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, - struct device *dev, struct skl *skl) + struct device *dev, struct skl_dev *skl) { struct snd_soc_tplg_vendor_array *array; int num_blocks, block_size = 0, block_type, off = 0; @@ -3612,7 +3600,7 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, struct snd_soc_tplg_manifest *manifest) { struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); /* proceed only if we have private data defined */ if (manifest->priv.size == 0) @@ -3620,9 +3608,9 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, skl_tplg_get_manifest_data(manifest, bus->dev, skl); - if (skl->skl_sst->lib_count > SKL_MAX_LIB) { + if (skl->lib_count > SKL_MAX_LIB) { dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", - skl->skl_sst->lib_count); + skl->lib_count); return -EINVAL; } @@ -3671,7 +3659,7 @@ static int skl_tplg_create_pipe_widget_list(struct snd_soc_component *component) return 0; } -static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) +static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) { struct skl_pipe_module *w_module; struct snd_soc_dapm_widget *w; @@ -3705,7 +3693,7 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) { int ret; const struct firmware *fw; - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct skl_pipeline *ppl; ret = request_firmware(&fw, skl->tplg_name, bus->dev); @@ -3748,7 +3736,7 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct skl_pipeline *ppl, *tmp; if (!list_empty(&skl->ppl_list)) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 665e35cee50d..0a4d89cdaa4c 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -447,7 +447,7 @@ enum skl_channel { SKL_CH_QUATRO = 4, }; -static inline struct skl *get_skl_ctx(struct device *dev) +static inline struct skl_dev *get_skl_ctx(struct device *dev) { struct hdac_bus *bus = dev_get_drvdata(dev); @@ -456,7 +456,7 @@ static inline struct skl *get_skl_ctx(struct device *dev) int skl_tplg_be_update_params(struct snd_soc_dai *dai, struct skl_pipe_params *params); -int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, +int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, u32 caps_size, u32 node_id); void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, struct skl_pipe_params *params, int stream); @@ -469,32 +469,32 @@ struct skl_module_cfg *skl_tplg_fe_get_cpr_module( int skl_tplg_update_pipe_params(struct device *dev, struct skl_module_cfg *mconfig, struct skl_pipe_params *params); -void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps); -void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps); +void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps); +void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps); -int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_pause_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_pause_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); +int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); +int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *module_config); -int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg +int skl_bind_modules(struct skl_dev *skl, struct skl_module_cfg *src_module, struct skl_module_cfg *dst_module); -int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg +int skl_unbind_modules(struct skl_dev *skl, struct skl_module_cfg *src_module, struct skl_module_cfg *dst_module); -int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, +int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg); -int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, +int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg); struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, @@ -508,6 +508,6 @@ int skl_pcm_link_dma_prepare(struct device *dev, int skl_dai_load(struct snd_soc_component *cmp, int index, struct snd_soc_dai_driver *dai_drv, struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai); -void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, +void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, struct snd_soc_dapm_widget *w); #endif diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 3362e71b4563..6be25e617c21 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -50,7 +50,7 @@ static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, pci_write_config_byte(pci, reg, data); } -static void skl_init_pci(struct skl *skl) +static void skl_init_pci(struct skl_dev *skl) { struct hdac_bus *bus = skl_to_bus(skl); @@ -252,7 +252,7 @@ static irqreturn_t skl_threaded_handler(int irq, void *dev_id) static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); int ret; ret = request_threaded_irq(skl->pci->irq, skl_interrupt, @@ -276,7 +276,7 @@ static int skl_suspend_late(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); return skl_suspend_late_dsp(skl); } @@ -284,7 +284,7 @@ static int skl_suspend_late(struct device *dev) #ifdef CONFIG_PM static int _skl_suspend(struct hdac_bus *bus) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct pci_dev *pci = to_pci_dev(bus->dev); int ret; @@ -307,7 +307,7 @@ static int _skl_suspend(struct hdac_bus *bus) static int _skl_resume(struct hdac_bus *bus) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); skl_init_pci(skl); skl_dum_set(bus); @@ -325,7 +325,7 @@ static int skl_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); int ret; /* @@ -345,7 +345,7 @@ static int skl_suspend(struct device *dev) ret = _skl_suspend(bus); if (ret < 0) return ret; - skl->skl_sst->fw_loaded = false; + skl->fw_loaded = false; } return 0; @@ -355,7 +355,7 @@ static int skl_resume(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct hdac_ext_link *hlink = NULL; int ret; @@ -430,7 +430,7 @@ static const struct dev_pm_ops skl_pm = { */ static int skl_free(struct hdac_bus *bus) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); skl->init_done = 0; /* to be sure */ @@ -475,7 +475,7 @@ static struct skl_ssp_clk skl_ssp_clks[] = { {.name = "ssp5_sclkfs"}, }; -static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl, +static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl, struct snd_soc_acpi_mach *machines) { struct hdac_bus *bus = skl_to_bus(skl); @@ -494,7 +494,7 @@ static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl, return mach; } -static int skl_find_machine(struct skl *skl, void *driver_data) +static int skl_find_machine(struct skl_dev *skl, void *driver_data) { struct hdac_bus *bus = skl_to_bus(skl); struct snd_soc_acpi_mach *mach = driver_data; @@ -522,7 +522,7 @@ static int skl_find_machine(struct skl *skl, void *driver_data) return 0; } -static int skl_machine_device_register(struct skl *skl) +static int skl_machine_device_register(struct skl_dev *skl) { struct snd_soc_acpi_mach *mach = skl->mach; struct hdac_bus *bus = skl_to_bus(skl); @@ -558,13 +558,13 @@ static int skl_machine_device_register(struct skl *skl) return 0; } -static void skl_machine_device_unregister(struct skl *skl) +static void skl_machine_device_unregister(struct skl_dev *skl) { if (skl->i2s_dev) platform_device_unregister(skl->i2s_dev); } -static int skl_dmic_device_register(struct skl *skl) +static int skl_dmic_device_register(struct skl_dev *skl) { struct hdac_bus *bus = skl_to_bus(skl); struct platform_device *pdev; @@ -588,7 +588,7 @@ static int skl_dmic_device_register(struct skl *skl) return 0; } -static void skl_dmic_device_unregister(struct skl *skl) +static void skl_dmic_device_unregister(struct skl_dev *skl) { if (skl->dmic_dev) platform_device_unregister(skl->dmic_dev); @@ -626,7 +626,7 @@ static void init_skl_xtal_rate(int pci_id) } } -static int skl_clock_device_register(struct skl *skl) +static int skl_clock_device_register(struct skl_dev *skl) { struct platform_device_info pdevinfo = {NULL}; struct skl_clk_pdata *clk_pdata; @@ -656,7 +656,7 @@ static int skl_clock_device_register(struct skl *skl) return PTR_ERR_OR_ZERO(skl->clk_dev); } -static void skl_clock_device_unregister(struct skl *skl) +static void skl_clock_device_unregister(struct skl_dev *skl) { if (skl->clk_dev) platform_device_unregister(skl->clk_dev); @@ -692,7 +692,7 @@ static int probe_codec(struct hdac_bus *bus, int addr) unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res = -1; - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) struct hdac_hda_priv *hda_codec; int err; @@ -792,7 +792,7 @@ static int skl_i915_init(struct hdac_bus *bus) static void skl_probe_work(struct work_struct *work) { - struct skl *skl = container_of(work, struct skl, probe_work); + struct skl_dev *skl = container_of(work, struct skl_dev, probe_work); struct hdac_bus *bus = skl_to_bus(skl); struct hdac_ext_link *hlink = NULL; int err; @@ -855,10 +855,10 @@ static void skl_probe_work(struct work_struct *work) */ static int skl_create(struct pci_dev *pci, const struct hdac_io_ops *io_ops, - struct skl **rskl) + struct skl_dev **rskl) { struct hdac_ext_bus_ops *ext_ops = NULL; - struct skl *skl; + struct skl_dev *skl; struct hdac_bus *bus; struct hda_bus *hbus; int err; @@ -902,7 +902,7 @@ static int skl_create(struct pci_dev *pci, static int skl_first_init(struct hdac_bus *bus) { - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); struct pci_dev *pci = skl->pci; int err; unsigned short gcap; @@ -978,7 +978,7 @@ static int skl_first_init(struct hdac_bus *bus) static int skl_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct skl *skl; + struct skl_dev *skl; struct hdac_bus *bus = NULL; int err; @@ -1071,8 +1071,8 @@ static int skl_probe(struct pci_dev *pci, dev_dbg(bus->dev, "error failed to register dsp\n"); goto out_nhlt_free; } - skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge; - skl->skl_sst->clock_power_gating = skl_clock_power_gating; + skl->enable_miscbdcge = skl_enable_miscbdcge; + skl->clock_power_gating = skl_clock_power_gating; if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); @@ -1107,7 +1107,7 @@ static void skl_shutdown(struct pci_dev *pci) struct hdac_bus *bus = pci_get_drvdata(pci); struct hdac_stream *s; struct hdac_ext_stream *stream; - struct skl *skl; + struct skl_dev *skl; if (!bus) return; @@ -1129,7 +1129,7 @@ static void skl_shutdown(struct pci_dev *pci) static void skl_remove(struct pci_dev *pci) { struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl *skl = bus_to_skl(bus); + struct skl_dev *skl = bus_to_skl(bus); cancel_work_sync(&skl->probe_work); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 6070666a6392..d3d84f4125d9 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -18,6 +18,7 @@ #include #include "skl-nhlt.h" #include "skl-ssp-clk.h" +#include "skl-sst-ipc.h" #define SKL_SUSPEND_DELAY 2000 @@ -63,7 +64,7 @@ struct skl_fw_config { struct skl_astate_config *astate_cfg; }; -struct skl { +struct skl_dev { struct hda_bus hbus; struct pci_dev *pci; @@ -75,7 +76,6 @@ struct skl { struct snd_soc_dai_driver *dais; struct nhlt_acpi_table *nhlt; /* nhlt ptr */ - struct skl_sst *skl_sst; /* sst skl ctx */ struct skl_dsp_resource resource; struct list_head ppl_list; @@ -96,13 +96,59 @@ struct skl { bool use_tplg_pcm; struct skl_fw_config cfg; struct snd_soc_acpi_mach *mach; + + struct device *dev; + struct sst_dsp *dsp; + + /* boot */ + wait_queue_head_t boot_wait; + bool boot_complete; + + /* module load */ + wait_queue_head_t mod_load_wait; + bool mod_load_complete; + bool mod_load_status; + + /* IPC messaging */ + struct sst_generic_ipc ipc; + + /* callback for miscbdge */ + void (*enable_miscbdcge)(struct device *dev, bool enable); + /* Is CGCTL.MISCBDCGE disabled */ + bool miscbdcg_disabled; + + /* Populate module information */ + struct list_head uuid_list; + + /* Is firmware loaded */ + bool fw_loaded; + + /* first boot ? */ + bool is_first_boot; + + /* multi-core */ + struct skl_dsp_cores cores; + + /* library info */ + struct skl_lib_info lib_info[SKL_MAX_LIB]; + int lib_count; + + /* Callback to update D0i3C register */ + void (*update_d0i3c)(struct device *dev, bool enable); + + struct skl_d0i3_data d0i3; + + const struct skl_dsp_ops *dsp_ops; + + /* Callback to update dynamic clock and power gating registers */ + void (*clock_power_gating)(struct device *dev, bool enable); }; #define skl_to_bus(s) (&(s)->hbus.core) -#define bus_to_skl(bus) container_of(bus, struct skl, hbus.core) +#define bus_to_skl(bus) container_of(bus, struct skl_dev, hbus.core) #define skl_to_hbus(s) (&(s)->hbus) -#define hbus_to_skl(hbus) container_of((hbus), struct skl, (hbus)) +#define hbus_to_skl(hbus) container_of((hbus), struct skl_dev, (hbus)) /* to pass dai dma data */ struct skl_dma_params { @@ -121,9 +167,9 @@ struct skl_dsp_ops { int (*init)(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops loader_ops, - struct skl_sst **skl_sst); - int (*init_fw)(struct device *dev, struct skl_sst *ctx); - void (*cleanup)(struct device *dev, struct skl_sst *ctx); + struct skl_dev **skl_sst); + int (*init_fw)(struct device *dev, struct skl_dev *skl); + void (*cleanup)(struct device *dev, struct skl_dev *skl); }; int skl_platform_unregister(struct device *dev); @@ -131,42 +177,42 @@ int skl_platform_register(struct device *dev); struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); void skl_nhlt_free(struct nhlt_acpi_table *addr); -struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, +struct nhlt_specific_cfg *skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn, u8 dev_type); -int skl_get_dmic_geo(struct skl *skl); -int skl_nhlt_update_topology_bin(struct skl *skl); -int skl_init_dsp(struct skl *skl); -int skl_free_dsp(struct skl *skl); -int skl_suspend_late_dsp(struct skl *skl); -int skl_suspend_dsp(struct skl *skl); -int skl_resume_dsp(struct skl *skl); -void skl_cleanup_resources(struct skl *skl); +int skl_get_dmic_geo(struct skl_dev *skl); +int skl_nhlt_update_topology_bin(struct skl_dev *skl); +int skl_init_dsp(struct skl_dev *skl); +int skl_free_dsp(struct skl_dev *skl); +int skl_suspend_late_dsp(struct skl_dev *skl); +int skl_suspend_dsp(struct skl_dev *skl); +int skl_resume_dsp(struct skl_dev *skl); +void skl_cleanup_resources(struct skl_dev *skl); const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); void skl_update_d0i3c(struct device *dev, bool enable); -int skl_nhlt_create_sysfs(struct skl *skl); -void skl_nhlt_remove_sysfs(struct skl *skl); -void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks); +int skl_nhlt_create_sysfs(struct skl_dev *skl); +void skl_nhlt_remove_sysfs(struct skl_dev *skl); +void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks); struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id); -int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, +int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, u32 caps_size, u32 node_id); struct skl_module_cfg; #ifdef CONFIG_DEBUG_FS -struct skl_debug *skl_debugfs_init(struct skl *skl); -void skl_debugfs_exit(struct skl *skl); +struct skl_debug *skl_debugfs_init(struct skl_dev *skl); +void skl_debugfs_exit(struct skl_dev *skl); void skl_debug_init_module(struct skl_debug *d, struct snd_soc_dapm_widget *w, struct skl_module_cfg *mconfig); #else -static inline struct skl_debug *skl_debugfs_init(struct skl *skl) +static inline struct skl_debug *skl_debugfs_init(struct skl_dev *skl) { return NULL; } -static inline void skl_debugfs_exit(struct skl *skl) +static inline void skl_debugfs_exit(struct skl_dev *skl) {} static inline void skl_debug_init_module(struct skl_debug *d, -- GitLab From 88abcc90cb04cbabcc3e384e8d3431a49f56a2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Tue, 23 Jul 2019 16:58:49 +0200 Subject: [PATCH 0486/7155] ASoC: Intel: Skylake: Combine snd_soc_skl_ipc and snd_soc_skl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As both modules are core part of Skylake driver and none can live without the other, combine snd_soc_skl_ipc and snd_soc_skl. It's highly probable IPC module was to be treated as an interface for platform specific code implementations e.g.: possibility of existence of BXT specific code without SKL one. However, most funtionalities are being inherited from one DSP firmware to another, and thus this assumption fails. skl-sst, bxt-sst and cnl-sst are not individuals pointing respectively to SKL (cAVS 1.5), BXT (cAVS 1.5+) & CNL (cAVS 1.8) standalone implementations. Code found within these is shared among all platforms whenever necessary to avoid code duplication and reduce development burden. Merge also helps in cleaning up internal code in future changes. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/Makefile | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 86f6e1d801af..48544ff1a3e6 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ -skl-topology.o +snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ + skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ + skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o ifdef CONFIG_DEBUG_FS snd-soc-skl-objs += skl-debug.o @@ -8,13 +9,6 @@ endif obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o -# Skylake IPC Support -snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ - skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ - skl-sst-utils.o - -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o - #Skylake Clock device support snd-soc-skl-ssp-clk-objs := skl-ssp-clk.o -- GitLab From f2a167ca681d21aa46f127032cc005879c328823 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:58:50 +0200 Subject: [PATCH 0487/7155] ASoC: Intel: Skylake: Remove MCPS available check The entire logic for MCPS calculation and DSP scheduling is found within DSP firmware. Currently driver implements simplistic, inaccurate logic itself which may prevent pipeline creation despite firmware being completely fine its parameters. Remove that logic and leave the MCPS calculation to DSP alone. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 67 +------------------------- sound/soc/intel/skylake/skl.h | 2 - 2 files changed, 1 insertion(+), 68 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index abf860109607..2af311150543 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -142,54 +142,6 @@ static void skl_tplg_alloc_pipe_mem(struct skl_dev *skl, skl->resource.mem += mconfig->pipe->memory_pages; } -/* - * Pipeline needs needs DSP CPU resources for computation, this is - * quantified in MCPS (Million Clocks Per Second) required for module/pipe - * - * Each pipelines needs mcps to be allocated. Check if we have mcps for this - * pipe. - */ - -static bool skl_is_pipe_mcps_avail(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - u8 res_idx = mconfig->res_idx; - struct skl_module_res *res = &mconfig->module->resources[res_idx]; - - if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { - dev_err(skl->dev, - "%s: module_id %d instance %d\n", __func__, - mconfig->id.module_id, mconfig->id.instance_id); - dev_err(skl->dev, - "exceeds ppl mcps available %d > mem %d\n", - skl->resource.max_mcps, skl->resource.mcps); - return false; - } else { - return true; - } -} - -static void skl_tplg_alloc_pipe_mcps(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - u8 res_idx = mconfig->res_idx; - struct skl_module_res *res = &mconfig->module->resources[res_idx]; - - skl->resource.mcps += res->cps; -} - -/* - * Free the mcps when tearing down - */ -static void -skl_tplg_free_pipe_mcps(struct skl_dev *skl, struct skl_module_cfg *mconfig) -{ - u8 res_idx = mconfig->res_idx; - struct skl_module_res *res = &mconfig->module->resources[res_idx]; - - skl->resource.mcps -= res->cps; -} - /* * Free the memory when tearing down */ @@ -582,10 +534,6 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; - /* check resource available */ - if (!skl_is_pipe_mcps_avail(skl, mconfig)) - return -ENOMEM; - if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { ret = skl->dsp->fw_ops.load_mod(skl->dsp, mconfig->id.module_id, mconfig->guid); @@ -627,7 +575,7 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); goto err; } - skl_tplg_alloc_pipe_mcps(skl, mconfig); + ret = skl_tplg_set_module_params(w, skl); if (ret < 0) goto err; @@ -752,10 +700,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, if (ret < 0) return ret; - /* check resource available */ - if (!skl_is_pipe_mcps_avail(skl, mconfig)) - return -EBUSY; - if (!skl_is_pipe_mem_avail(skl, mconfig)) return -ENOMEM; @@ -768,7 +712,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, return ret; skl_tplg_alloc_pipe_mem(skl, mconfig); - skl_tplg_alloc_pipe_mcps(skl, mconfig); /* Init all pipe modules from source to sink */ ret = skl_tplg_init_pipe_modules(skl, s_pipe); @@ -1264,7 +1207,6 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, /* * in the Post-PMD event of mixer we need to do following: - * - Free the mcps used * - Free the mem used * - Unbind the modules within the pipeline * - Delete the pipeline (modules are not required to be explicitly @@ -1282,7 +1224,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, if (s_pipe->state == SKL_PIPE_INVALID) return -EINVAL; - skl_tplg_free_pipe_mcps(skl, mconfig); skl_tplg_free_pipe_mem(skl, mconfig); list_for_each_entry(w_module, &s_pipe->w_list, node) { @@ -1317,8 +1258,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, list_for_each_entry(w_module, &s_pipe->w_list, node) { dst_module = w_module->w->priv; - if (mconfig->m_state >= SKL_MODULE_INIT_DONE) - skl_tplg_free_pipe_mcps(skl, dst_module); if (src_module == NULL) { src_module = dst_module; continue; @@ -1340,7 +1279,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, /* * in the Post-PMD event of PGA we need to do following: - * - Free the mcps used * - Stop the pipeline * - In source pipe is connected, unbind with source pipelines */ @@ -2984,7 +2922,6 @@ void skl_cleanup_resources(struct skl_dev *skl) return; skl->resource.mem = 0; - skl->resource.mcps = 0; list_for_each_entry(w, &card->widgets, list) { if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) @@ -3683,7 +3620,6 @@ static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) } /* This will be read from topology manifest, currently defined here */ -#define SKL_MAX_MCPS 30000000 #define SKL_FW_MAX_MEM 1000000 /* @@ -3720,7 +3656,6 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) return -EINVAL; } - skl->resource.max_mcps = SKL_MAX_MCPS; skl->resource.max_mem = SKL_FW_MAX_MEM; skl->tplg = fw; diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index d3d84f4125d9..21c33c1af934 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -42,9 +42,7 @@ #define AZX_REG_VS_EM2_L1SEN BIT(13) struct skl_dsp_resource { - u32 max_mcps; u32 max_mem; - u32 mcps; u32 mem; }; -- GitLab From e5c29dc5221c328b6e54c5b2aba1feca4003c051 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:58:51 +0200 Subject: [PATCH 0488/7155] ASoC: Intel: Skylake: Remove memory available check Current memory availability check is a stub, while actual memory management takes place in firmware. Leave this task to firmware entirely and remove redundant code. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 59 -------------------------- sound/soc/intel/skylake/skl.h | 6 --- 2 files changed, 65 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 2af311150543..53a024c0464d 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -109,49 +109,6 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, } } -/* - * Each pipelines needs memory to be allocated. Check if we have free memory - * from available pool. - */ -static bool skl_is_pipe_mem_avail(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - if (skl->resource.mem + mconfig->pipe->memory_pages > - skl->resource.max_mem) { - dev_err(skl->dev, - "%s: module_id %d instance %d\n", __func__, - mconfig->id.module_id, - mconfig->id.instance_id); - dev_err(skl->dev, - "exceeds ppl memory available %d mem %d\n", - skl->resource.max_mem, skl->resource.mem); - return false; - } else { - return true; - } -} - -/* - * Add the mem to the mem pool. This is freed when pipe is deleted. - * Note: DSP does actual memory management we only keep track for complete - * pool - */ -static void skl_tplg_alloc_pipe_mem(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - skl->resource.mem += mconfig->pipe->memory_pages; -} - -/* - * Free the memory when tearing down - */ -static void -skl_tplg_free_pipe_mem(struct skl_dev *skl, struct skl_module_cfg *mconfig) -{ - skl->resource.mem -= mconfig->pipe->memory_pages; -} - - static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) { struct skl_module_iface *iface = &mcfg->module->formats[0]; @@ -681,7 +638,6 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) /* * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we * need create the pipeline. So we do following: - * - check the resources * - Create the pipeline * - Initialize the modules in pipeline * - finally bind all modules together @@ -700,9 +656,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, if (ret < 0) return ret; - if (!skl_is_pipe_mem_avail(skl, mconfig)) - return -ENOMEM; - /* * Create a list of modules for pipe. * This list contains modules from source to sink @@ -711,8 +664,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, if (ret < 0) return ret; - skl_tplg_alloc_pipe_mem(skl, mconfig); - /* Init all pipe modules from source to sink */ ret = skl_tplg_init_pipe_modules(skl, s_pipe); if (ret < 0) @@ -1207,7 +1158,6 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, /* * in the Post-PMD event of mixer we need to do following: - * - Free the mem used * - Unbind the modules within the pipeline * - Delete the pipeline (modules are not required to be explicitly * deleted, pipeline delete is enough here @@ -1224,8 +1174,6 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, if (s_pipe->state == SKL_PIPE_INVALID) return -EINVAL; - skl_tplg_free_pipe_mem(skl, mconfig); - list_for_each_entry(w_module, &s_pipe->w_list, node) { if (list_empty(&skl->bind_list)) break; @@ -2921,8 +2869,6 @@ void skl_cleanup_resources(struct skl_dev *skl) if (!card || !card->instantiated) return; - skl->resource.mem = 0; - list_for_each_entry(w, &card->widgets, list) { if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) skl_clear_pin_config(soc_component, w); @@ -3619,9 +3565,6 @@ static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) pipe->passthru = false; } -/* This will be read from topology manifest, currently defined here */ -#define SKL_FW_MAX_MEM 1000000 - /* * SKL topology init routine */ @@ -3656,8 +3599,6 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) return -EINVAL; } - skl->resource.max_mem = SKL_FW_MAX_MEM; - skl->tplg = fw; ret = skl_tplg_create_pipe_widget_list(component); if (ret < 0) diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 21c33c1af934..600a61f79b0a 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -41,11 +41,6 @@ #define AZX_VS_EM2_DUM BIT(23) #define AZX_REG_VS_EM2_L1SEN BIT(13) -struct skl_dsp_resource { - u32 max_mem; - u32 mem; -}; - struct skl_debug; struct skl_astate_param { @@ -75,7 +70,6 @@ struct skl_dev { struct nhlt_acpi_table *nhlt; /* nhlt ptr */ - struct skl_dsp_resource resource; struct list_head ppl_list; struct list_head bind_list; -- GitLab From d4e23b7c87e3439f6d0ec0c65ad7f919d6f4c124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Tue, 23 Jul 2019 16:58:52 +0200 Subject: [PATCH 0489/7155] ASoC: Intel: Skylake: Do not disable FW notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per FW team recommendation we should not disable notifications. By default, all notifications are enabled in DSP firmware. These notifications provide a vital information whenever an error occurs. Currently, driver disables them during boot sequences. By doing so, Skylake may silently ignore severe stream errors. Correct that by removing permissive code. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 20 -------------------- sound/soc/intel/skylake/skl-pcm.c | 1 - sound/soc/intel/skylake/skl-sst-dsp.h | 1 - sound/soc/intel/skylake/skl-topology.h | 5 ----- 4 files changed, 27 deletions(-) diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index f604d9c6824d..07762543fb13 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -58,24 +58,6 @@ void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data) skl_ipc_set_large_config(&skl->ipc, &msg, data); } -#define NOTIFICATION_PARAM_ID 3 -#define NOTIFICATION_MASK 0xf - -/* disable notfication for underruns/overruns from firmware module */ -void skl_dsp_enable_notification(struct skl_dev *skl, bool enable) -{ - struct notification_mask mask; - struct skl_ipc_large_config_msg msg = {0}; - - mask.notify = NOTIFICATION_MASK; - mask.enable = enable; - - msg.large_param_id = NOTIFICATION_PARAM_ID; - msg.param_data_size = sizeof(mask); - - skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)&mask); -} - static int skl_dsp_setup_spib(struct device *dev, unsigned int size, int stream_tag, int enable) { @@ -436,8 +418,6 @@ int skl_resume_dsp(struct skl_dev *skl) if (ret < 0) return ret; - skl_dsp_enable_notification(skl, false); - if (skl->cfg.astate_cfg != NULL) { skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count, skl->cfg.astate_cfg); diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 2ae5d09d7228..7f287424af9b 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1445,7 +1445,6 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) } skl_populate_modules(skl); skl->update_d0i3c = skl_update_d0i3c; - skl_dsp_enable_notification(skl, false); if (skl->cfg.astate_cfg != NULL) { skl_dsp_set_astate_cfg(skl, diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index ed968f1042c7..cdfec0fca577 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -240,7 +240,6 @@ int skl_get_pvt_instance_id_map(struct skl_dev *skl, void skl_freeup_uuid_list(struct skl_dev *skl); int skl_dsp_strip_extended_manifest(struct firmware *fw); -void skl_dsp_enable_notification(struct skl_dev *skl, bool enable); void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 0a4d89cdaa4c..e2a2fc5c5545 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -140,11 +140,6 @@ struct skl_src_module_cfg { enum skl_s_freq src_cfg; } __packed; -struct notification_mask { - u32 notify; - u32 enable; -} __packed; - struct skl_up_down_mixer_cfg { struct skl_base_cfg base_cfg; enum skl_ch_cfg out_ch_cfg; -- GitLab From 84b71067ea840fadee32588aa3967d0d8c4e0b9a Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:58:53 +0200 Subject: [PATCH 0490/7155] ASoC: Intel: Skylake: Make MCPS and CPS params obsolete As per FW Interface Modules Configuration, init instance IPC request requires base initial module configuration. This configuration structure is made of: - cpc (chunks per cycle) - ibs (input buffer size) - obs (output buffer size) - is_pages (memory pages required) - audio_fmt (self explanatory) Skylake topology accepts following tokens: MCPS, CPS and CPC. All of these are directly connected. Moreover, assigning one of these allows to calculate the remaining two. In simplest scenario and assuming 1ms scheduling, following is true: CPS = CPC times 1000 MCPS = CPS times 1000 000 Note: these calculations vary depending on scenario and scheduling requirements. Given the current implementation, userspace is allowed to provide different values for all three causing informational chaos. On top of that, struct skl_base_cfg which represents base module configuration, incorrectly takes CPS param instead of CPC. This ambiguity may lead to user unintentionally providing improper values to DSP firmware and thus impacting module scheduling in unexpected fashion. Fix by making MCPS and CPS topology params obsolete and relying solely on CPC value. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-debug.c | 6 ++++-- sound/soc/intel/skylake/skl-messages.c | 2 +- sound/soc/intel/skylake/skl-topology.c | 15 ++++++--------- sound/soc/intel/skylake/skl-topology.h | 4 +--- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index c43aa4081232..fb232428109f 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -66,6 +66,8 @@ static ssize_t module_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct skl_module_cfg *mconfig = file->private_data; + struct skl_module *module = mconfig->module; + struct skl_module_res *res = &module->resources[mconfig->res_idx]; char *buf; ssize_t ret; @@ -79,8 +81,8 @@ static ssize_t module_read(struct file *file, char __user *user_buf, mconfig->id.pvt_id); ret += snprintf(buf + ret, MOD_BUF - ret, - "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n", - mconfig->mcps, mconfig->ibs, mconfig->obs); + "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n", + res->cpc, res->ibs, res->obs); ret += snprintf(buf + ret, MOD_BUF - ret, "Module data:\n\tCore %d\n\tIn queue %d\n\t" diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 07762543fb13..e8cc710f092b 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -477,7 +477,7 @@ static void skl_set_base_module_format(struct skl_dev *skl, base_cfg->audio_fmt.interleaving = format->interleaving_style; - base_cfg->cps = res->cps; + base_cfg->cpc = res->cpc; base_cfg->ibs = res->ibs; base_cfg->obs = res->obs; base_cfg->is_pages = res->is_pages; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 53a024c0464d..118866cd5075 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2205,10 +2205,6 @@ static int skl_tplg_fill_res_tkn(struct device *dev, return -EINVAL; switch (tkn_elem->token) { - case SKL_TKN_MM_U32_CPS: - res->cps = tkn_elem->value; - break; - case SKL_TKN_MM_U32_DMA_SIZE: res->dma_buffer_size = tkn_elem->value; break; @@ -2229,10 +2225,6 @@ static int skl_tplg_fill_res_tkn(struct device *dev, res->ibs = tkn_elem->value; break; - case SKL_TKN_U32_MAX_MCPS: - res->cps = tkn_elem->value; - break; - case SKL_TKN_MM_U32_RES_PIN_ID: case SKL_TKN_MM_U32_PIN_BUF: ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, @@ -2241,6 +2233,11 @@ static int skl_tplg_fill_res_tkn(struct device *dev, return ret; break; + case SKL_TKN_MM_U32_CPS: + case SKL_TKN_U32_MAX_MCPS: + /* ignore unused tokens */ + break; + default: dev_err(dev, "Not a res type token: %d", tkn_elem->token); return -EINVAL; @@ -2693,7 +2690,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, return ret; mconfig->id.module_id = -1; mconfig->id.instance_id = dfw->instance_id; - mconfig->module->resources[0].cps = dfw->max_mcps; + mconfig->module->resources[0].cpc = dfw->max_mcps / 1000; mconfig->module->resources[0].ibs = dfw->ibs; mconfig->module->resources[0].obs = dfw->obs; mconfig->core_id = dfw->core_id; diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index e2a2fc5c5545..99a0277191ca 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -101,7 +101,7 @@ struct skl_audio_data_format { } __packed; struct skl_base_cfg { - u32 cps; + u32 cpc; u32 ibs; u32 obs; u32 is_pages; @@ -343,7 +343,6 @@ struct skl_module_pin_resources { struct skl_module_res { u8 id; u32 is_pages; - u32 cps; u32 ibs; u32 obs; u32 dma_buffer_size; @@ -384,7 +383,6 @@ struct skl_module_cfg { u8 out_queue_mask; u8 in_queue; u8 out_queue; - u32 mcps; u32 ibs; u32 obs; u8 is_loadable; -- GitLab From bdc873feec900005d52f9afd3a63290531c0c1f4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:58:54 +0200 Subject: [PATCH 0491/7155] ASoC: Intel: Skylake: Cleanup skl_module_cfg declaration With removal of MCPS, CPS and CPC ambiguity, ibs and obs params for struct skl_module_cfg have been left unused. Update struct declaration by removing these two. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723145854.8527-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 99a0277191ca..e967800dbb62 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -383,8 +383,6 @@ struct skl_module_cfg { u8 out_queue_mask; u8 in_queue; u8 out_queue; - u32 ibs; - u32 obs; u8 is_loadable; u8 core_id; u8 dev_type; -- GitLab From 7bdb9234952b08b1f86927eab4adbf6609d4444a Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:26:34 +0800 Subject: [PATCH 0492/7155] net: marvell: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/skge.c | 6 ++---- drivers/net/ethernet/marvell/sky2.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9ac854c2b371..06dffee81e02 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4078,8 +4078,7 @@ static void skge_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int skge_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); + struct skge_hw *hw = dev_get_drvdata(dev); int i; if (!hw) @@ -4103,8 +4102,7 @@ static int skge_suspend(struct device *dev) static int skge_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); + struct skge_hw *hw = dev_get_drvdata(dev); int i, err; if (!hw) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index f518312ffe69..762fe0821923 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -5160,8 +5160,7 @@ static void sky2_remove(struct pci_dev *pdev) static int sky2_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct sky2_hw *hw = pci_get_drvdata(pdev); + struct sky2_hw *hw = dev_get_drvdata(dev); int i; if (!hw) -- GitLab From dfa56f83153f08c73e7adfacefd93750da2266ad Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:26:48 +0800 Subject: [PATCH 0493/7155] forcedeth: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/nvidia/forcedeth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index b327b29f5d57..ecca794c55e2 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -6126,8 +6126,7 @@ static void nv_remove(struct pci_dev *pci_dev) #ifdef CONFIG_PM_SLEEP static int nv_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); int i; -- GitLab From 3e03a8ba8e1d6c9940a032992f4da2bfba391fdf Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:26:58 +0800 Subject: [PATCH 0494/7155] sfc: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 4 ++-- drivers/net/ethernet/sfc/efx.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 16d6952c312a..0ec13f520e90 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -508,7 +508,7 @@ static ssize_t efx_ef10_show_link_control_flag(struct device *dev, struct device_attribute *attr, char *buf) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); return sprintf(buf, "%d\n", ((efx->mcdi->fn_flags) & @@ -520,7 +520,7 @@ static ssize_t efx_ef10_show_primary_flag(struct device *dev, struct device_attribute *attr, char *buf) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); return sprintf(buf, "%d\n", ((efx->mcdi->fn_flags) & diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index ab58b837df47..2fef7402233e 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2517,7 +2517,7 @@ static struct notifier_block efx_netdev_notifier = { static ssize_t show_phy_type(struct device *dev, struct device_attribute *attr, char *buf) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); return sprintf(buf, "%d\n", efx->phy_type); } static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL); @@ -2526,7 +2526,7 @@ static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL); static ssize_t show_mcdi_log(struct device *dev, struct device_attribute *attr, char *buf) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); struct efx_mcdi_iface *mcdi = efx_mcdi(efx); return scnprintf(buf, PAGE_SIZE, "%d\n", mcdi->logging_enabled); @@ -2534,7 +2534,7 @@ static ssize_t show_mcdi_log(struct device *dev, struct device_attribute *attr, static ssize_t set_mcdi_log(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); struct efx_mcdi_iface *mcdi = efx_mcdi(efx); bool enable = count > 0 && *buf != '0'; @@ -3654,7 +3654,7 @@ static int efx_pci_sriov_configure(struct pci_dev *dev, int num_vfs) static int efx_pm_freeze(struct device *dev) { - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); rtnl_lock(); @@ -3675,7 +3675,7 @@ static int efx_pm_freeze(struct device *dev) static int efx_pm_thaw(struct device *dev) { int rc; - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct efx_nic *efx = dev_get_drvdata(dev); rtnl_lock(); -- GitLab From 8f75ec1a220e0a4b0f1abbc564987fe754cdc6f0 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:27:06 +0800 Subject: [PATCH 0495/7155] sfc-falcon: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/falcon/efx.c | 6 +++--- drivers/net/ethernet/sfc/falcon/falcon_boards.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 9b15c39ac670..eecc348b1c32 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2256,7 +2256,7 @@ static struct notifier_block ef4_netdev_notifier = { static ssize_t show_phy_type(struct device *dev, struct device_attribute *attr, char *buf) { - struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct ef4_nic *efx = dev_get_drvdata(dev); return sprintf(buf, "%d\n", efx->phy_type); } static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL); @@ -2999,7 +2999,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, static int ef4_pm_freeze(struct device *dev) { - struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct ef4_nic *efx = dev_get_drvdata(dev); rtnl_lock(); @@ -3020,7 +3020,7 @@ static int ef4_pm_freeze(struct device *dev) static int ef4_pm_thaw(struct device *dev) { int rc; - struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct ef4_nic *efx = dev_get_drvdata(dev); rtnl_lock(); diff --git a/drivers/net/ethernet/sfc/falcon/falcon_boards.c b/drivers/net/ethernet/sfc/falcon/falcon_boards.c index 839189dab98e..2d85d1386ed9 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon_boards.c +++ b/drivers/net/ethernet/sfc/falcon/falcon_boards.c @@ -357,7 +357,7 @@ static int sfe4001_poweron(struct ef4_nic *efx) static ssize_t show_phy_flash_cfg(struct device *dev, struct device_attribute *attr, char *buf) { - struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct ef4_nic *efx = dev_get_drvdata(dev); return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL)); } @@ -365,7 +365,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ef4_nic *efx = pci_get_drvdata(to_pci_dev(dev)); + struct ef4_nic *efx = dev_get_drvdata(dev); enum ef4_phy_mode old_mode, new_mode; int err; -- GitLab From 92493a2f8a8d5a5bc1188fc71ef02df859ebd932 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Wed, 24 Jul 2019 04:36:15 -0700 Subject: [PATCH 0496/7155] Build fixes for skb_frag_size conversion I missed a few places. One is in some ifdeffed code which will probably never be re-enabled; the others are in drivers which can't currently be compiled on x86. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: David S. Miller --- drivers/atm/he.c | 7 +++---- drivers/net/ethernet/aeroflex/greth.c | 2 +- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++- drivers/staging/octeon/ethernet-tx.c | 2 +- drivers/target/iscsi/cxgbit/cxgbit_target.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 211607986134..70b00ae4ec38 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -2580,10 +2580,9 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) slot = 0; } - tpd->iovec[slot].addr = dma_map_single(&he_dev->pci_dev->dev, - (void *) page_address(frag->page) + frag->page_offset, - frag->size, DMA_TO_DEVICE); - tpd->iovec[slot].len = frag->size; + tpd->iovec[slot].addr = skb_frag_dma_map(&he_dev->pci_dev->dev, + frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); + tpd->iovec[slot].len = skb_frag_size(frag); ++slot; } diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 010a2f48aea5..2a9f8643629c 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -110,7 +110,7 @@ static void greth_print_tx_packet(struct sk_buff *skb) print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1, skb_frag_address(&skb_shinfo(skb)->frags[i]), - skb_shinfo(skb)->frags[i].size, true); + skb_frag_size(&skb_shinfo(skb)->frags[i]), true); } } diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index f38c3fa7d705..9c4d1afa34e5 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -1958,7 +1958,7 @@ static int skb_to_sg_fd(struct dpaa_priv *priv, /* populate the rest of SGT entries */ for (i = 0; i < nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; - frag_len = frag->size; + frag_len = skb_frag_size(frag); WARN_ON(!skb_frag_page(frag)); addr = skb_frag_dma_map(dev, frag, 0, frag_len, dma_dir); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 00991df44ed6..e529d86468b8 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -787,7 +787,8 @@ static inline int mtk_cal_txd_req(struct sk_buff *skb) if (skb_is_gso(skb)) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; - nfrags += DIV_ROUND_UP(frag->size, MTK_TX_DMA_BUF_LEN); + nfrags += DIV_ROUND_UP(skb_frag_size(frag), + MTK_TX_DMA_BUF_LEN); } } else { nfrags += skb_shinfo(skb)->nr_frags; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index cc12c78f73f1..46a6fcf1414d 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -284,7 +284,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb_frag_address(fs)); - hw_buffer.s.size = fs->size; + hw_buffer.s.size = skb_drag_size(fs); CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb)); diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 93212b9fd310..c25315431ad0 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -1448,7 +1448,7 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx) hpdu_cb->frags++; hpdu_cb->hfrag_idx = hfrag_idx; - len = skb_frag_size(&hssi->frags[hfrag_idx]);; + len = skb_frag_size(&hssi->frags[hfrag_idx]); hskb->len += len; hskb->data_len += len; hskb->truesize += len; -- GitLab From 939b482a6411bd5a798662389efb9b8eb814ee5a Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 19 May 2019 12:20:00 +0200 Subject: [PATCH 0497/7155] ARM: bcm283x: Reduce register ranges for UART, SPI and I2C The assigned register ranges for UART, SPI and I2C were too wasteful. In order to avoid overlapping with the new functions on BCM2711 reduce the ranges. Signed-off-by: Stefan Wahren Acked-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 4b21ddb26aa5..2d191fcbc2cc 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -397,7 +397,7 @@ uart0: serial@7e201000 { compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; - reg = <0x7e201000 0x1000>; + reg = <0x7e201000 0x200>; interrupts = <2 25>; clocks = <&clocks BCM2835_CLOCK_UART>, <&clocks BCM2835_CLOCK_VPU>; @@ -428,7 +428,7 @@ spi: spi@7e204000 { compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; + reg = <0x7e204000 0x200>; interrupts = <2 22>; clocks = <&clocks BCM2835_CLOCK_VPU>; dmas = <&dma 6>, <&dma 7>; @@ -440,7 +440,7 @@ i2c0: i2c@7e205000 { compatible = "brcm,bcm2835-i2c"; - reg = <0x7e205000 0x1000>; + reg = <0x7e205000 0x200>; interrupts = <2 21>; clocks = <&clocks BCM2835_CLOCK_VPU>; #address-cells = <1>; -- GitLab From 2b69286dbd999516b67147bd48360808d0abdfc1 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Sun, 23 Jun 2019 13:42:31 +0300 Subject: [PATCH 0498/7155] igc: Remove the polarity field from a PHY information structure Polarity and cable length fields is not applicable for the i225 device. This patch comes to clean up PHY information structure. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_hw.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index 1039a224ac80..f689f0a02b5d 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h @@ -151,16 +151,10 @@ struct igc_phy_info { u16 autoneg_advertised; u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - u16 pair_length[4]; u8 mdix; - bool disable_polarity_correction; bool is_mdix; - bool polarity_correction; bool reset_disable; bool speed_downgraded; bool autoneg_wait_to_complete; -- GitLab From 6145787d5e2eb973fa9f73d228d7a6a13650b1d1 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Sun, 23 Jun 2019 13:42:32 +0300 Subject: [PATCH 0499/7155] igc: Remove the unused field from a device specification structure This patch comes to clean up the device specification structure. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_hw.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index f689f0a02b5d..9a338fbf671c 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h @@ -184,12 +184,7 @@ struct igc_fc_info { }; struct igc_dev_spec_base { - bool global_device_reset; - bool eee_disable; bool clear_semaphore_once; - bool module_plugged; - u8 media_port; - bool mas_capable; }; struct igc_hw { -- GitLab From bb4265ec24c13aacf3a613e64c701294b122beb7 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Wed, 26 Jun 2019 08:53:47 +0300 Subject: [PATCH 0500/7155] igc: Update the MAC reset flow Use Device Reset flow instead of Port Reset flow. This flow performs a reset of the entire controller device, resulting in a state nearly approximating the state following a power-up reset or internal PCIe reset, except for system PCI configuration. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 2 +- drivers/net/ethernet/intel/igc/igc_defines.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index 59258d791106..46206b3dabfb 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -40,7 +40,7 @@ static s32 igc_reset_hw_base(struct igc_hw *hw) ctrl = rd32(IGC_CTRL); hw_dbg("Issuing a global reset to MAC\n"); - wr32(IGC_CTRL, ctrl | IGC_CTRL_RST); + wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST); ret_val = igc_get_auto_rd_done(hw); if (ret_val) { diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index fc0ccfe38a20..11b99acf4abe 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -54,7 +54,7 @@ #define IGC_ERR_SWFW_SYNC 13 /* Device Control */ -#define IGC_CTRL_RST 0x04000000 /* Global reset */ +#define IGC_CTRL_DEV_RST 0x20000000 /* Device reset */ #define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */ #define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -- GitLab From 6d37a38243bc4bb3336b9771961e2904500fb3a9 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 2 Jul 2019 14:39:55 +0300 Subject: [PATCH 0501/7155] igc: Add more SKUs for i225 device Add support for more SKUs. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 3 +++ drivers/net/ethernet/intel/igc/igc_hw.h | 3 +++ drivers/net/ethernet/intel/igc/igc_main.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index 46206b3dabfb..db289bcce21d 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -209,6 +209,9 @@ static s32 igc_get_invariants_base(struct igc_hw *hw) switch (hw->device_id) { case IGC_DEV_ID_I225_LM: case IGC_DEV_ID_I225_V: + case IGC_DEV_ID_I225_I: + case IGC_DEV_ID_I220_V: + case IGC_DEV_ID_I225_K: mac->type = igc_i225; break; default: diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index 9a338fbf671c..abb2d72911ff 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h @@ -18,6 +18,9 @@ #define IGC_DEV_ID_I225_LM 0x15F2 #define IGC_DEV_ID_I225_V 0x15F3 +#define IGC_DEV_ID_I225_I 0x15F8 +#define IGC_DEV_ID_I220_V 0x15F7 +#define IGC_DEV_ID_I225_K 0x3100 #define IGC_FUNC_0 0 diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 9ffe71424ece..e5114bebd30b 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -36,6 +36,9 @@ static const struct igc_info *igc_info_tbl[] = { static const struct pci_device_id igc_pci_tbl[] = { { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LM), board_base }, { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_I), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I220_V), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_K), board_base }, /* required last entry */ {0, } }; -- GitLab From e5e9a2ecfe780975820e157b922edee715710b66 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Mon, 8 Jul 2019 12:55:45 +0800 Subject: [PATCH 0502/7155] e1000e: add workaround for possible stalled packet This works around a possible stalled packet issue, which may occur due to clock recovery from the PCH being too slow, when the LAN is transitioning from K1 at 1G link speed. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204057 Signed-off-by: Kai-Heng Feng Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/ich8lan.c | 10 ++++++++++ drivers/net/ethernet/intel/e1000e/ich8lan.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 395b05701480..a1fab77b2096 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1429,6 +1429,16 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) else phy_reg |= 0xFA; e1e_wphy_locked(hw, I217_PLL_CLOCK_GATE_REG, phy_reg); + + if (speed == SPEED_1000) { + hw->phy.ops.read_reg_locked(hw, HV_PM_CTRL, + &phy_reg); + + phy_reg |= HV_PM_CTRL_K1_CLK_REQ; + + hw->phy.ops.write_reg_locked(hw, HV_PM_CTRL, + phy_reg); + } } hw->phy.ops.release(hw); diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index eb09c755fa17..1502895eb45d 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h @@ -210,7 +210,7 @@ /* PHY Power Management Control */ #define HV_PM_CTRL PHY_REG(770, 17) -#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 +#define HV_PM_CTRL_K1_CLK_REQ 0x200 #define HV_PM_CTRL_K1_ENABLE 0x4000 #define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) -- GitLab From 998c1de56dac7ff6bad4f810259cc25c7d6d2843 Mon Sep 17 00:00:00 2001 From: Carlos A Petry Date: Wed, 7 Nov 2018 23:13:12 -0200 Subject: [PATCH 0503/7155] fpga: altera-cvp: Fix function definition argument Fix the following checkpatch warning: WARNING: function definition argument 'struct altera_cvp_conf *' Signed-off-by: Carlos A Petry Signed-off-by: Moritz Fischer --- drivers/fpga/altera-cvp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 770915fb97f9..53b963071c7b 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -57,7 +57,8 @@ struct altera_cvp_conf { struct fpga_manager *mgr; struct pci_dev *pci_dev; void __iomem *map; - void (*write_data)(struct altera_cvp_conf *, u32); + void (*write_data)(struct altera_cvp_conf *conf, + u32 data); char mgr_name[64]; u8 numclks; }; -- GitLab From ed72a9bb9af06c9eb06ff2e8640faac44f8da94a Mon Sep 17 00:00:00 2001 From: Corentin Musard Date: Wed, 24 Jul 2019 14:34:43 +0200 Subject: [PATCH 0504/7155] r8169: fix a typo in a comment Replace "additonal" by "additional" in a comment. Typo found by checkpatch.pl. Signed-off-by: Corentin Musard Reviewed-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 9c743d2fc29d..58feb234fb10 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -6321,7 +6321,7 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->multicast = dev->stats.multicast; /* - * Fetch additonal counter values missing in stats collected by driver + * Fetch additional counter values missing in stats collected by driver * from tally counters. */ if (pm_runtime_active(&pdev->dev)) -- GitLab From 71d8e94dabee7fceac473d87445a03e848469a71 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 26 Jun 2019 17:33:09 -0700 Subject: [PATCH 0505/7155] fpga: altera-pr-ip: Make alt_pr_unregister function void Make alt_pr_unregister function void, since it always returns 0, and nothing would act on the value anyways. Signed-off-by: Moritz Fischer --- drivers/fpga/altera-pr-ip-core-plat.c | 4 +++- drivers/fpga/altera-pr-ip-core.c | 4 +--- include/linux/fpga/altera-pr-ip-core.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/fpga/altera-pr-ip-core-plat.c b/drivers/fpga/altera-pr-ip-core-plat.c index b293d83143f1..99b9cc0e70f0 100644 --- a/drivers/fpga/altera-pr-ip-core-plat.c +++ b/drivers/fpga/altera-pr-ip-core-plat.c @@ -32,7 +32,9 @@ static int alt_pr_platform_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - return alt_pr_unregister(dev); + alt_pr_unregister(dev); + + return 0; } static const struct of_device_id alt_pr_of_match[] = { diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index a7a3bf0b5202..2cf25fd5e897 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -201,15 +201,13 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) } EXPORT_SYMBOL_GPL(alt_pr_register); -int alt_pr_unregister(struct device *dev) +void alt_pr_unregister(struct device *dev) { struct fpga_manager *mgr = dev_get_drvdata(dev); dev_dbg(dev, "%s\n", __func__); fpga_mgr_unregister(mgr); - - return 0; } EXPORT_SYMBOL_GPL(alt_pr_unregister); diff --git a/include/linux/fpga/altera-pr-ip-core.h b/include/linux/fpga/altera-pr-ip-core.h index 7d4664730d60..0b08ac20ab16 100644 --- a/include/linux/fpga/altera-pr-ip-core.h +++ b/include/linux/fpga/altera-pr-ip-core.h @@ -13,6 +13,6 @@ #include int alt_pr_register(struct device *dev, void __iomem *reg_base); -int alt_pr_unregister(struct device *dev); +void alt_pr_unregister(struct device *dev); #endif /* _ALT_PR_IP_CORE_H */ -- GitLab From 2ec0a8909189cb801ded3428d66cdc1ea7e4578b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 24 Jul 2019 21:01:26 +0800 Subject: [PATCH 0506/7155] qlge: Fix build error without CONFIG_ETHERNET Now if CONFIG_ETHERNET is not set, QLGE driver building fails: drivers/staging/qlge/qlge_main.o: In function `qlge_remove': drivers/staging/qlge/qlge_main.c:4831: undefined reference to `unregister_netdev' Reported-by: Hulk Robot Fixes: 955315b0dc8c ("qlge: Move drivers/net/ethernet/qlogic/qlge/ to drivers/staging/qlge/") Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/staging/qlge/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/qlge/Kconfig b/drivers/staging/qlge/Kconfig index ae9ed2c5300b..a3cb25a3ab80 100644 --- a/drivers/staging/qlge/Kconfig +++ b/drivers/staging/qlge/Kconfig @@ -2,7 +2,7 @@ config QLGE tristate "QLogic QLGE 10Gb Ethernet Driver Support" - depends on PCI + depends on ETHERNET && PCI help This driver supports QLogic ISP8XXX 10Gb Ethernet cards. -- GitLab From 2949dc443116a66fd1a92d9ef107be16cdd197cd Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 21 Feb 2018 09:33:06 -0800 Subject: [PATCH 0507/7155] dt-bindings: fpga: Consolidate bridge properties Consolidate bridge properties in a single file, instead of duplicating the same optional property over and over again. Acked-by: Alan Tull Acked-by: Michal Simek Reviewed-by: Rob Herring Signed-off-by: Moritz Fischer --- .../bindings/fpga/altera-fpga2sdram-bridge.txt | 5 +---- .../bindings/fpga/altera-freeze-bridge.txt | 5 +---- .../bindings/fpga/altera-hps2fpga-bridge.txt | 5 +---- .../devicetree/bindings/fpga/fpga-bridge.txt | 13 +++++++++++++ .../bindings/fpga/xilinx-pr-decoupler.txt | 8 ++------ 5 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/fpga/fpga-bridge.txt diff --git a/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt index 817a8d4bf903..5dd0ff0f7b4e 100644 --- a/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt +++ b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt @@ -3,10 +3,7 @@ Altera FPGA To SDRAM Bridge Driver Required properties: - compatible : Should contain "altr,socfpga-fpga2sdram-bridge" -Optional properties: -- bridge-enable : 0 if driver should disable bridge at startup - 1 if driver should enable bridge at startup - Default is to leave bridge in current state. +See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings. Example: fpga_bridge3: fpga-bridge@ffc25080 { diff --git a/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt index f8e288c71b2d..8b26fbcff3c6 100644 --- a/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt +++ b/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt @@ -10,10 +10,7 @@ Required properties: - compatible : Should contain "altr,freeze-bridge-controller" - regs : base address and size for freeze bridge module -Optional properties: -- bridge-enable : 0 if driver should disable bridge at startup - 1 if driver should enable bridge at startup - Default is to leave bridge in current state. +See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings. Example: freeze-controller@100000450 { diff --git a/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt index 6406f9337eeb..68cce3945b10 100644 --- a/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt +++ b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt @@ -9,10 +9,7 @@ Required properties: - resets : Phandle and reset specifier for this bridge's reset - clocks : Clocks used by this module. -Optional properties: -- bridge-enable : 0 if driver should disable bridge at startup. - 1 if driver should enable bridge at startup. - Default is to leave bridge in its current state. +See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings. Example: fpga_bridge0: fpga-bridge@ff400000 { diff --git a/Documentation/devicetree/bindings/fpga/fpga-bridge.txt b/Documentation/devicetree/bindings/fpga/fpga-bridge.txt new file mode 100644 index 000000000000..72e06917288a --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/fpga-bridge.txt @@ -0,0 +1,13 @@ +FPGA Bridge Device Tree Binding + +Optional properties: +- bridge-enable : 0 if driver should disable bridge at startup + 1 if driver should enable bridge at startup + Default is to leave bridge in current state. + +Example: + fpga_bridge3: fpga-bridge@ffc25080 { + compatible = "altr,socfpga-fpga2sdram-bridge"; + reg = <0xffc25080 0x4>; + bridge-enable = <0>; + }; diff --git a/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt b/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt index 8dcfba926bc7..4284d293fa61 100644 --- a/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt +++ b/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt @@ -18,12 +18,8 @@ Required properties: - clocks : input clock to IP - clock-names : should contain "aclk" -Optional properties: -- bridge-enable : 0 if driver should disable bridge at startup - 1 if driver should enable bridge at startup - Default is to leave bridge in current state. - -See Documentation/devicetree/bindings/fpga/fpga-region.txt for generic bindings. +See Documentation/devicetree/bindings/fpga/fpga-region.txt and +Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings. Example: fpga-bridge@100000450 { -- GitLab From e62088ea6a20c3517c490d94bcc437ab4c24c9d1 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 25 Jul 2019 00:29:51 +0900 Subject: [PATCH 0508/7155] selftests: mlxsw: Fix typo in qos_mc_aware.sh This patch fix some spelling typo in qos_mc_aware.sh Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh index 71231ad2dbfb..47315fe48d5a 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh @@ -262,7 +262,7 @@ test_mc_aware() stop_traffic - log_test "UC performace under MC overload" + log_test "UC performance under MC overload" echo "UC-only throughput $(humanize $ucth1)" echo "UC+MC throughput $(humanize $ucth2)" @@ -316,7 +316,7 @@ test_uc_aware() stop_traffic - log_test "MC performace under UC overload" + log_test "MC performance under UC overload" echo " ingress UC throughput $(humanize ${uc_ir})" echo " egress UC throughput $(humanize ${uc_er})" echo " sent $attempts BC ARPs, got $passes responses" -- GitLab From d601be97126e9736db4f3528c66792178fcf1796 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Wed, 24 Jul 2019 12:17:59 -0400 Subject: [PATCH 0509/7155] net/ixgbevf: fix a compilation error of skb_frag_t The linux-next commit "net: Rename skb_frag_t size to bv_len" [1] introduced a compilation error on powerpc as it forgot to deal with the renaming from "size" to "bv_len" for ixgbevf. [1] https://lore.kernel.org/netdev/20190723030831.11879-1-willy@infradead.org/T/#md052f1c7de965ccd1bdcb6f92e1990a52298eac5 In file included from ./include/linux/cache.h:5, from ./include/linux/printk.h:9, from ./include/linux/kernel.h:15, from ./include/linux/list.h:9, from ./include/linux/module.h:9, from drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:12: drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: In function 'ixgbevf_xmit_frame_ring': drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:4138:51: error: 'skb_frag_t' {aka 'struct bio_vec'} has no member named 'size' count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); ^ ./include/uapi/linux/kernel.h:13:40: note: in definition of macro '__KERNEL_DIV_ROUND_UP' #define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ^ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:4138:12: note: in expansion of macro 'TXD_USE_COUNT' count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); Signed-off-by: Qian Cai Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index bdfccaf38edd..8c011d4ce7a9 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -4134,8 +4134,11 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ #if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD - for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; + + count += TXD_USE_COUNT(skb_frag_size(frag)); + } #else count += skb_shinfo(skb)->nr_frags; #endif -- GitLab From 81cd17a4121d7dc7cad28e51251f31ff12b1de2b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 24 Jul 2019 23:34:45 +0200 Subject: [PATCH 0510/7155] r8169: improve rtl_set_rx_mode This patch improves and simplifies rtl_set_rx_mode a little. No functional change intended. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 52 ++++++++++------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 58feb234fb10..e1e1c89fbe3d 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -61,7 +61,7 @@ /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; +#define MC_FILTER_LIMIT 32 #define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -4146,54 +4146,46 @@ static void rtl8169_set_magic_reg(struct rtl8169_private *tp, unsigned mac_versi static void rtl_set_rx_mode(struct net_device *dev) { + u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast; + /* Multicast hash filter */ + u32 mc_filter[2] = { 0xffffffff, 0xffffffff }; struct rtl8169_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; + u32 tmp; if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; + rx_mode |= AcceptAllPhys; + } else if (netdev_mc_count(dev) > MC_FILTER_LIMIT || + dev->flags & IFF_ALLMULTI || + tp->mac_version == RTL_GIGA_MAC_VER_35) { + /* accept all multicasts */ + } else if (netdev_mc_empty(dev)) { + rx_mode &= ~AcceptMulticast; } else { struct netdev_hw_addr *ha; - rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; + u32 bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= BIT(bit_nr & 31); + } + + if (tp->mac_version > RTL_GIGA_MAC_VER_06) { + tmp = mc_filter[0]; + mc_filter[0] = swab32(mc_filter[1]); + mc_filter[1] = swab32(tmp); } } if (dev->features & NETIF_F_RXALL) rx_mode |= (AcceptErr | AcceptRunt); - tmp = (RTL_R32(tp, RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_35) - mc_filter[1] = mc_filter[0] = 0xffffffff; - RTL_W32(tp, MAR0 + 4, mc_filter[1]); RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, RxConfig, tmp); + tmp = RTL_R32(tp, RxConfig); + RTL_W32(tp, RxConfig, (tmp & ~RX_CONFIG_ACCEPT_MASK) | rx_mode); } DECLARE_RTL_COND(rtl_csiar_cond) -- GitLab From 7c116e02a4a7575c8c62bfd2106e3e3ec8fb99dc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Jul 2019 17:01:23 +0200 Subject: [PATCH 0511/7155] qed: reduce maximum stack frame size clang warns about an overly large stack frame in one function when it decides to inline all __qed_get_vport_*() functions into __qed_get_vport_stats(): drivers/net/ethernet/qlogic/qed/qed_l2.c:1889:13: error: stack frame size of 1128 bytes in function '_qed_get_vport_stats' [-Werror,-Wframe-larger-than=] Use a noinline_for_stack annotation to prevent clang from inlining these, which keeps the maximum stack usage at around half of that in the worst case, similar to what we get with gcc. Fixes: 86622ee75312 ("qed: Move statistics to L2 code") Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 34 +++++++++++------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 9f36e7948222..1a5fc2ae351c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1631,10 +1631,9 @@ static void __qed_get_vport_pstats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_pstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_pstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_pstorm_per_queue_stat pstats; u32 pstats_addr = 0, pstats_len = 0; @@ -1661,10 +1660,9 @@ static void __qed_get_vport_pstats(struct qed_hwfn *p_hwfn, HILO_64_REGPAIR(pstats.error_drop_pkts); } -static void __qed_get_vport_tstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_tstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct tstorm_per_port_stat tstats; u32 tstats_addr, tstats_len; @@ -1709,10 +1707,9 @@ static void __qed_get_vport_ustats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack +void __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_ustorm_per_queue_stat ustats; u32 ustats_addr = 0, ustats_len = 0; @@ -1751,10 +1748,9 @@ static void __qed_get_vport_mstats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_mstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_mstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_mstorm_per_queue_stat mstats; u32 mstats_addr = 0, mstats_len = 0; @@ -1780,9 +1776,9 @@ static void __qed_get_vport_mstats(struct qed_hwfn *p_hwfn, HILO_64_REGPAIR(mstats.tpa_coalesced_bytes); } -static void __qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats) +static noinline_for_stack void +__qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats) { struct qed_eth_stats_common *p_common = &p_stats->common; struct port_stats port_stats; -- GitLab From 9eed21c01c7827f029000f77d59b61d1b16cb024 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Jul 2019 17:01:55 +0200 Subject: [PATCH 0512/7155] mlx4: avoid large stack usage in mlx4_init_hca() The mlx4_dev_cap and mlx4_init_hca_param are really too large to be put on the kernel stack, as shown by this clang warning: drivers/net/ethernet/mellanox/mlx4/main.c:3304:12: error: stack frame size of 1088 bytes in function 'mlx4_load_one' [-Werror,-Wframe-larger-than=] With gcc, the problem is the same, but it does not warn because it does not inline this function, and therefore stays just below the warning limit, while clang is just above it. Use kzalloc for dynamic allocation instead of putting them on stack. This gets the combined stack frame down to 424 bytes. Signed-off-by: Arnd Bergmann Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 66 +++++++++++++---------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 1f6e16d5ea6b..07c204bd3fc4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2292,23 +2292,31 @@ static int mlx4_init_fw(struct mlx4_dev *dev) static int mlx4_init_hca(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_init_hca_param *init_hca = NULL; + struct mlx4_dev_cap *dev_cap = NULL; struct mlx4_adapter adapter; - struct mlx4_dev_cap dev_cap; struct mlx4_profile profile; - struct mlx4_init_hca_param init_hca; u64 icm_size; struct mlx4_config_dev_params params; int err; if (!mlx4_is_slave(dev)) { - err = mlx4_dev_cap(dev, &dev_cap); + dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL); + init_hca = kzalloc(sizeof(*init_hca), GFP_KERNEL); + + if (!dev_cap || !init_hca) { + err = -ENOMEM; + goto out_free; + } + + err = mlx4_dev_cap(dev, dev_cap); if (err) { mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting\n"); - return err; + goto out_free; } - choose_steering_mode(dev, &dev_cap); - choose_tunnel_offload_mode(dev, &dev_cap); + choose_steering_mode(dev, dev_cap); + choose_tunnel_offload_mode(dev, dev_cap); if (dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_STATIC && mlx4_is_master(dev)) @@ -2331,48 +2339,48 @@ static int mlx4_init_hca(struct mlx4_dev *dev) MLX4_STEERING_MODE_DEVICE_MANAGED) profile.num_mcg = MLX4_FS_NUM_MCG; - icm_size = mlx4_make_profile(dev, &profile, &dev_cap, - &init_hca); + icm_size = mlx4_make_profile(dev, &profile, dev_cap, + init_hca); if ((long long) icm_size < 0) { err = icm_size; - return err; + goto out_free; } dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1; if (enable_4k_uar || !dev->persist->num_vfs) { - init_hca.log_uar_sz = ilog2(dev->caps.num_uars) + + init_hca->log_uar_sz = ilog2(dev->caps.num_uars) + PAGE_SHIFT - DEFAULT_UAR_PAGE_SHIFT; - init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12; + init_hca->uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12; } else { - init_hca.log_uar_sz = ilog2(dev->caps.num_uars); - init_hca.uar_page_sz = PAGE_SHIFT - 12; + init_hca->log_uar_sz = ilog2(dev->caps.num_uars); + init_hca->uar_page_sz = PAGE_SHIFT - 12; } - init_hca.mw_enabled = 0; + init_hca->mw_enabled = 0; if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW || dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN) - init_hca.mw_enabled = INIT_HCA_TPT_MW_ENABLE; + init_hca->mw_enabled = INIT_HCA_TPT_MW_ENABLE; - err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); + err = mlx4_init_icm(dev, dev_cap, init_hca, icm_size); if (err) - return err; + goto out_free; - err = mlx4_INIT_HCA(dev, &init_hca); + err = mlx4_INIT_HCA(dev, init_hca); if (err) { mlx4_err(dev, "INIT_HCA command failed, aborting\n"); goto err_free_icm; } - if (dev_cap.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) { - err = mlx4_query_func(dev, &dev_cap); + if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) { + err = mlx4_query_func(dev, dev_cap); if (err < 0) { mlx4_err(dev, "QUERY_FUNC command failed, aborting.\n"); goto err_close; } else if (err & MLX4_QUERY_FUNC_NUM_SYS_EQS) { - dev->caps.num_eqs = dev_cap.max_eqs; - dev->caps.reserved_eqs = dev_cap.reserved_eqs; - dev->caps.reserved_uars = dev_cap.reserved_uars; + dev->caps.num_eqs = dev_cap->max_eqs; + dev->caps.reserved_eqs = dev_cap->reserved_eqs; + dev->caps.reserved_uars = dev_cap->reserved_uars; } } @@ -2381,14 +2389,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev) * read HCA frequency by QUERY_HCA command */ if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) { - memset(&init_hca, 0, sizeof(init_hca)); - err = mlx4_QUERY_HCA(dev, &init_hca); + err = mlx4_QUERY_HCA(dev, init_hca); if (err) { mlx4_err(dev, "QUERY_HCA command failed, disable timestamp\n"); dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; } else { dev->caps.hca_core_clock = - init_hca.hca_core_clock; + init_hca->hca_core_clock; } /* In case we got HCA frequency 0 - disable timestamping @@ -2464,7 +2471,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev) priv->eq_table.inta_pin = adapter.inta_pin; memcpy(dev->board_id, adapter.board_id, sizeof(dev->board_id)); - return 0; + err = 0; + goto out_free; unmap_bf: unmap_internal_clock(dev); @@ -2483,6 +2491,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev) if (!mlx4_is_slave(dev)) mlx4_free_icms(dev); +out_free: + kfree(dev_cap); + kfree(init_hca); + return err; } -- GitLab From 3e6998b17f36ab4f8f5608b3599df7b3c17d97a5 Mon Sep 17 00:00:00 2001 From: Lecopzer Chen Date: Fri, 12 Jul 2019 16:47:17 +0800 Subject: [PATCH 0513/7155] staging: android: ion: Remove unused rbtree for ion_buffer ion_buffer_add() insert ion_buffer into rbtree every time creating an ion_buffer but never use it after ION reworking. Also, buffer_lock protects only rbtree operation, remove it together. Signed-off-by: Lecopzer Chen Cc: YJ Chiang Cc: Lecopzer Chen Acked-by: Laura Abbott Link: https://lore.kernel.org/r/20190712084717.12441-1-lecopzer.chen@mediatek.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 36 ------------------------------- drivers/staging/android/ion/ion.h | 10 +-------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 92c2914239e3..e6b1ca141b93 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -29,32 +29,6 @@ static struct ion_device *internal_dev; static int heap_id; -/* this function should only be called while dev->lock is held */ -static void ion_buffer_add(struct ion_device *dev, - struct ion_buffer *buffer) -{ - struct rb_node **p = &dev->buffers.rb_node; - struct rb_node *parent = NULL; - struct ion_buffer *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_buffer, node); - - if (buffer < entry) { - p = &(*p)->rb_left; - } else if (buffer > entry) { - p = &(*p)->rb_right; - } else { - pr_err("%s: buffer already found.", __func__); - BUG(); - } - } - - rb_link_node(&buffer->node, parent, p); - rb_insert_color(&buffer->node, &dev->buffers); -} - /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -100,9 +74,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); - mutex_lock(&dev->buffer_lock); - ion_buffer_add(dev, buffer); - mutex_unlock(&dev->buffer_lock); return buffer; err1: @@ -131,11 +102,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer) static void _ion_buffer_destroy(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct ion_device *dev = buffer->dev; - - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_freelist_add(heap, buffer); @@ -694,8 +660,6 @@ static int ion_device_create(void) } idev->debug_root = debugfs_create_dir("ion", NULL); - idev->buffers = RB_ROOT; - mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e291299fd35f..74914a266e25 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -23,7 +23,6 @@ /** * struct ion_buffer - metadata for a particular buffer - * @node: node in the ion_device buffers tree * @list: element in list of deferred freeable buffers * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from @@ -39,10 +38,7 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { - union { - struct rb_node node; - struct list_head list; - }; + struct list_head list; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; @@ -61,14 +57,10 @@ void ion_buffer_destroy(struct ion_buffer *buffer); /** * struct ion_device - the metadata of the ion device node * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers * @lock: rwsem protecting the tree of heaps and clients */ struct ion_device { struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps; struct dentry *debug_root; -- GitLab From 28771088953f548a637c01cd59b62f9ee3018824 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:53:59 +0530 Subject: [PATCH 0514/7155] staging: comedi: daqboard2000: Remove function db2k_initialize_dac() Remove function db2k_initialize_dac as all it does is call db2k_dac_disarm. Modify call site accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052359.2308-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index aabcda3f9fc8..28603dfadce2 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -665,11 +665,6 @@ static void db2k_initialize_adc(struct comedi_device *dev) db2k_initialize_tmrs(dev); } -static void db2k_initialize_dac(struct comedi_device *dev) -{ - db2k_dac_disarm(dev); -} - static int db2k_8255_cb(struct comedi_device *dev, int dir, int port, int data, unsigned long iobase) { @@ -719,7 +714,7 @@ static int db2k_auto_attach(struct comedi_device *dev, unsigned long context) return result; db2k_initialize_adc(dev); - db2k_initialize_dac(dev); + db2k_dac_disarm(dev); s = &dev->subdevices[0]; /* ai subdevice */ -- GitLab From 7a047abbb6ef8ac0050f8f0aa6a668985fb75a2c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 25 Jul 2019 10:52:03 +0800 Subject: [PATCH 0515/7155] staging: wilc1000: Merge memcpy + le32_to_cpus to get_unaligned_le32 Merge the combo use of memcpy and le32_to_cpus. Use get_unaligned_le32 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190725025203.8772-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_mon.c | 3 +-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 +-- drivers/staging/wilc1000/wilc_wlan.c | 9 +++------ 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c index 7d7933d40924..d6f14f69ad64 100644 --- a/drivers/staging/wilc1000/wilc_mon.c +++ b/drivers/staging/wilc1000/wilc_mon.c @@ -35,8 +35,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size) return; /* Get WILC header */ - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); /* * The packet offset field contain info about what type of management * the frame we are dealing with and ack status diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d72fdd333050..12fb4add05ec 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1038,8 +1038,7 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size) s32 freq; __le16 fc; - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 2cbdbf0090e4..8ca0a7a4fa3f 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -703,8 +703,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) do { buff_ptr = buffer + offset; - memcpy(&header, buff_ptr, 4); - le32_to_cpus(&header); + header = get_unaligned_le32(buff_ptr); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -874,10 +873,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, offset = 0; do { - memcpy(&addr, &buffer[offset], 4); - memcpy(&size, &buffer[offset + 4], 4); - le32_to_cpus(&addr); - le32_to_cpus(&size); + addr = get_unaligned_le32(&buffer[offset]); + size = get_unaligned_le32(&buffer[offset + 4]); acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); offset += 8; while (((int)size) && (offset < buffer_size)) { -- GitLab From 814b75b4ed9c1a7633bfec7bab33c96db87a39db Mon Sep 17 00:00:00 2001 From: Christian L Moreno Date: Tue, 16 Jul 2019 16:09:15 -0300 Subject: [PATCH 0516/7155] staging: rtl8712: recv_linux.c: Align * on block comment Block comments should align the * on each line. This warning was reported by checkpatch.pl Signed-off-by: Christian L Moreno Link: https://lore.kernel.org/r/20190716190915.30869-1-christianluciano.m@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 84c4c8580f9a..70a4dcd4a1e5 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -115,8 +115,8 @@ void r8712_recv_indicatepkt(struct _adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->pnetdev); netif_rx(skb); recvframe->u.hdr.pkt = NULL; /* pointers to NULL before - * r8712_free_recvframe() - */ + * r8712_free_recvframe() + */ r8712_free_recvframe(recvframe, free_recv_queue); return; _recv_indicatepkt_drop: -- GitLab From ec2b26f712610a85aab933c9cb4dfa3250aa4f58 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 19 Jul 2019 15:09:22 +0800 Subject: [PATCH 0517/7155] staging: rtl8712: Merge memcpy + be16_to_cpus to get_unaligned_be16 Merge the combo of memcpy and be16_to_cpus. Use get_unaligned_be16 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190719070921.27749-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_recv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 5298fe603437..9969e5265a40 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -245,8 +245,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, if (auth_alg == 2) { /* get ether_type */ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; - memcpy(ðer_type, ptr, 2); - be16_to_cpus(ðer_type); + ether_type = get_unaligned_be16(ptr); if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked -- GitLab From 3e67274a41b29dc93915afe857fe27eb1a851d61 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:34 +0530 Subject: [PATCH 0518/7155] staging: rtl8712: r8712_init_mlme_priv(): Change return values Change return values of r8712_init_mlme_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify call site accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 2 +- drivers/staging/rtl8712/rtl871x_mlme.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b554cf8bd679..b4059ea17e5c 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -302,7 +302,7 @@ u8 r8712_init_drv_sw(struct _adapter *padapter) padapter->cmdpriv.padapter = padapter; if (r8712_init_evt_priv(&padapter->evtpriv)) return _FAIL; - if (r8712_init_mlme_priv(padapter) == _FAIL) + if (r8712_init_mlme_priv(padapter)) return _FAIL; _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); _r8712_init_recv_priv(&padapter->recvpriv, padapter); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 0cc879a4d43f..a4922af61acd 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -53,7 +53,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network), GFP_ATOMIC); if (!pbuf) - return _FAIL; + return -ENOMEM; pmlmepriv->free_bss_buf = pbuf; pnetwork = (struct wlan_network *)pbuf; for (i = 0; i < MAX_BSS_CNT; i++) { @@ -67,7 +67,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pmlmepriv->sitesurveyctrl.traffic_busy = false; /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ r8712_init_mlme_timer(padapter); - return _SUCCESS; + return 0; } struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) -- GitLab From 33972d48c2de0a77a5f482bb0728e62cb8420ca3 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:35 +0530 Subject: [PATCH 0519/7155] staging: rtl8712: r8712_set_auth(): Change return values Change return values of r8712_set_auth from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify call site accordingly. Also change return type of the function from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 6 +++--- drivers/staging/rtl8712/rtl871x_mlme.c | 10 +++++----- drivers/staging/rtl8712/rtl871x_mlme.h | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index f3c0a9348f56..c12adb9a6c37 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -320,10 +320,10 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, psecuritypriv->ndisauthtype = authmode; if (psecuritypriv->ndisauthtype > 3) psecuritypriv->AuthAlgrthm = 2; /* 802.1x */ - if (r8712_set_auth(padapter, psecuritypriv) == _SUCCESS) - ret = true; - else + if (r8712_set_auth(padapter, psecuritypriv)) ret = false; + else + ret = true; return ret; } diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index a4922af61acd..9c373a84ca0d 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1144,8 +1144,8 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv) return r8712_joinbss_cmd(adapter, pnetwork); } -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv) +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; @@ -1153,12 +1153,12 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC); if (!psetauthparm) { kfree(pcmd); - return _FAIL; + return -ENOMEM; } psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm; pcmd->cmdcode = _SetAuth_CMD_; @@ -1168,7 +1168,7 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return _SUCCESS; + return 0; } sint r8712_set_key(struct _adapter *adapter, diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index a160107e9801..47499e879688 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -175,8 +175,8 @@ void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); sint r8712_set_key(struct _adapter *adapter, struct security_priv *psecuritypriv, sint keyid); -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv); +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv); uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); void r8712_generate_random_ibss(u8 *pibss); u8 *r8712_get_capability_from_ie(u8 *ie); -- GitLab From 8a73a8c4657013e02bd9e6db975e6c3584c158f8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:36 +0530 Subject: [PATCH 0520/7155] staging: rtl8712: r8712_set_key(): Change return values Change return values of r8712_set_key from _SUCCESS and _FAIL to 0 and -ENOMEM or -EINVAL, as the case may require. Modify return statements and return variable accordingly. Change return type from sint to int. As there is only one site where the return value is used, update that call site according to the change in the return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 2 +- drivers/staging/rtl8712/rtl871x_mlme.c | 20 ++++++++++---------- drivers/staging/rtl8712/rtl871x_mlme.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index c12adb9a6c37..54b16bc41465 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -351,7 +351,7 @@ u8 r8712_set_802_11_add_wep(struct _adapter *padapter, wep->KeyLength); psecuritypriv->DefKeylen[keyid] = wep->KeyLength; psecuritypriv->PrivacyKeyIndex = keyid; - if (r8712_set_key(padapter, psecuritypriv, keyid) == _FAIL) + if (r8712_set_key(padapter, psecuritypriv, keyid)) return false; return _SUCCESS; } diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 9c373a84ca0d..cabdb3549a5a 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1171,22 +1171,22 @@ int r8712_set_auth(struct _adapter *adapter, return 0; } -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, - sint keyid) +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, + sint keyid) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; struct setkey_parm *psetkeyparm; u8 keylen; - sint ret = _SUCCESS; + int ret; pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC); if (!psetkeyparm) { - ret = _FAIL; + ret = -ENOMEM; goto err_free_cmd; } if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */ @@ -1211,7 +1211,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _TKIP_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1221,7 +1221,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _AES_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1230,7 +1230,7 @@ sint r8712_set_key(struct _adapter *adapter, psetkeyparm->grpkey = 1; break; default: - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } pcmd->cmdcode = _SetKey_CMD_; @@ -1240,7 +1240,7 @@ sint r8712_set_key(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return ret; + return 0; err_free_parm: kfree(psetkeyparm); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 47499e879688..46effb469fd4 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -173,8 +173,8 @@ void r8712_free_network_queue(struct _adapter *adapter); int r8712_init_mlme_priv(struct _adapter *adapter); void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, sint keyid); +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, sint keyid); int r8712_set_auth(struct _adapter *adapter, struct security_priv *psecuritypriv); uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); -- GitLab From 7c93fdf090dfed579bbb40aae0cef0853286848c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:37 +0530 Subject: [PATCH 0521/7155] staging: rtl8712: r8712_register_cmd_alive(): Change return values Change return values of r8712_register_cmd_alive from _SUCCESS and _FAIL to 0 and -EINVAL. Change the return type of this function from sint to int. Modify its call site to check for 0 instead of _SUCCESS. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_cmd.c | 2 +- drivers/staging/rtl8712/rtl871x_pwrctrl.c | 10 +++++----- drivers/staging/rtl8712/rtl871x_pwrctrl.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 6a72a4ad176a..f99fd7cfa445 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -311,7 +311,7 @@ int r8712_cmd_thread(void *context) break; if (padapter->driver_stopped || padapter->surprise_removed) break; - if (r8712_register_cmd_alive(padapter) != _SUCCESS) + if (r8712_register_cmd_alive(padapter)) continue; _next: pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue); diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 2beafc7742b3..23cff43437e2 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -184,19 +184,19 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter) * will raise the cpwm to be greater than or equal to P2. * Calling Context: Passive * Return Value: - * _SUCCESS: r8712_cmd_thread can issue cmds to firmware afterwards. - * _FAIL: r8712_cmd_thread can not do anything. + * 0: r8712_cmd_thread can issue cmds to firmware afterwards. + * -EINVAL: r8712_cmd_thread can not do anything. */ -sint r8712_register_cmd_alive(struct _adapter *padapter) +int r8712_register_cmd_alive(struct _adapter *padapter) { - uint res = _SUCCESS; + int res = 0; struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; mutex_lock(&pwrctrl->mutex_lock); register_task_alive(pwrctrl, CMD_ALIVE); if (pwrctrl->cpwm < PS_STATE_S2) { r8712_set_rpwm(padapter, PS_STATE_S3); - res = _FAIL; + res = -EINVAL; } mutex_unlock(&pwrctrl->mutex_lock); return res; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 11b5034f203d..dd5a79f90b1a 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -104,7 +104,7 @@ struct pwrctrl_priv { }; void r8712_init_pwrctrl_priv(struct _adapter *adapter); -sint r8712_register_cmd_alive(struct _adapter *padapter); +int r8712_register_cmd_alive(struct _adapter *padapter); void r8712_unregister_cmd_alive(struct _adapter *padapter); void r8712_cpwm_int_hdl(struct _adapter *padapter, struct reportpwrstate_parm *preportpwrstate); -- GitLab From 42ceb6731d781e6a9134ee73bbe85988395e0895 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:38 +0530 Subject: [PATCH 0522/7155] staging: rtl8712: init_mp_priv(): Change return values Change return values of init_mp_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Remove label that returns the required value and return the values directly as they are set. Consequently remove now-unnecessary return variable. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_mp.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c index edd3da05fc06..1a39a96b726f 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ b/drivers/staging/rtl8712/rtl871x_mp.c @@ -35,7 +35,7 @@ static void _init_mp_priv_(struct mp_priv *pmp_priv) static int init_mp_priv(struct mp_priv *pmp_priv) { - int i, res; + int i; struct mp_xmit_frame *pmp_xmitframe; _init_mp_priv_(pmp_priv); @@ -45,8 +45,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) sizeof(struct mp_xmit_frame) + 4, GFP_ATOMIC); if (!pmp_priv->pallocated_mp_xmitframe_buf) { - res = _FAIL; - goto _exit_init_mp_priv; + return -ENOMEM; } pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf + 4 - @@ -62,9 +61,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) pmp_xmitframe++; } pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME; - res = _SUCCESS; -_exit_init_mp_priv: - return res; + return 0; } static int free_mp_priv(struct mp_priv *pmp_priv) -- GitLab From 34ef8dbe02f403b03999ccefd489ca3a7a5e08f1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:39 +0530 Subject: [PATCH 0523/7155] staging: rtl8712: r8712_set_802_11_add_wep(): Change return values Change call sites of r8712_set_802_11_add_wep to check for 0 and non-zero values (e.g -EINVAL, -ENOMEM) instead of for _SUCCESS and _FAIL. Change return values of r8712_set_802_11_add_wep from true and false and _SUCCESS to -EINVAL and the return value of r8712_set_key. Change return type from u8 to int to accommodate these new return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 5 ++--- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 10 ++++------ drivers/staging/rtl8712/rtl871x_ioctl_set.h | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index b08b9a191a34..944336e0d2e2 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -419,8 +419,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, pwep->KeyIndex |= 0x80000000; memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); if (param->u.crypt.set_tx) { - if (r8712_set_802_11_add_wep(padapter, pwep) == - (u8)_FAIL) + if (r8712_set_802_11_add_wep(padapter, pwep)) ret = -EOPNOTSUPP; } else { /* don't update "psecuritypriv->PrivacyAlgrthm" and @@ -1585,7 +1584,7 @@ static int r8711_wx_set_enc(struct net_device *dev, } wep.KeyIndex |= 0x80000000; /* transmit key */ memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); - if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL) + if (r8712_set_802_11_add_wep(padapter, &wep)) return -EOPNOTSUPP; return 0; } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index 54b16bc41465..6cdc6f1a6bc6 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -327,15 +327,15 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, return ret; } -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep) +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep) { sint keyid; struct security_priv *psecuritypriv = &padapter->securitypriv; keyid = wep->KeyIndex & 0x3fffffff; if (keyid >= WEP_KEYS) - return false; + return -EINVAL; switch (wep->KeyLength) { case 5: psecuritypriv->PrivacyAlgrthm = _WEP40_; @@ -351,7 +351,5 @@ u8 r8712_set_802_11_add_wep(struct _adapter *padapter, wep->KeyLength); psecuritypriv->DefKeylen[keyid] = wep->KeyLength; psecuritypriv->PrivacyKeyIndex = keyid; - if (r8712_set_key(padapter, psecuritypriv, keyid)) - return false; - return _SUCCESS; + return r8712_set_key(padapter, psecuritypriv, keyid); } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h index 8b1085aea962..e2de820f61d9 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.h @@ -28,8 +28,8 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter, u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid); -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep); +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep); u8 r8712_set_802_11_disassociate(struct _adapter *padapter); -- GitLab From 606c5cf07b7907294e74eb5344fcf489b93983a5 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:40 +0530 Subject: [PATCH 0524/7155] staging: rtl8712: r8712_init_recvbuf(): Change return type Change return type of r8712_init_recvbuf from int to void as it always returned _SUCCESS and this return value was never used at any call site. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- drivers/staging/rtl8712/rtl8712_recv.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 82ddc0c3ecd4..892ea71c3718 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -107,7 +107,7 @@ void r8712_free_recv_priv(struct recv_priv *precvpriv) skb_queue_len(&precvpriv->free_recv_skb_queue)); } -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) { precvbuf->transfer_len = 0; precvbuf->len = 0; @@ -118,7 +118,6 @@ int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) precvbuf->ptail = precvbuf->pbuf; precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ; } - return _SUCCESS; } int r8712_free_recvframe(union recv_frame *precvframe, diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index 6954c5bfbcaf..3e385b2242d8 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -136,7 +136,7 @@ union recv_frame { } u; }; -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf); s32 r8712_signal_scale_mapping(s32 cur_sig); void r8712_reordering_ctrl_timeout_handler(void *pcontext); -- GitLab From caecc46bf4e78bada4e3f6df3156c711c5ef6b78 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:41 +0530 Subject: [PATCH 0525/7155] staging: rtl8712: r8712_free_recvframe(): Change return type Change return type of r8712_free_recvframe from int to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- drivers/staging/rtl8712/rtl871x_recv.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 892ea71c3718..d9574ea3ffb2 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -120,7 +120,7 @@ void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) } } -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue) { unsigned long irqL; @@ -139,7 +139,6 @@ int r8712_free_recvframe(union recv_frame *precvframe, precvpriv->free_recvframe_cnt++; } spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL); - return _SUCCESS; } static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index f87b2ff5de1c..0146a774e19d 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -128,7 +128,7 @@ struct sta_recv_priv { /* get a free recv_frame from pfree_recv_queue */ union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue); -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue); void r8712_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue); -- GitLab From 8143be90aaab5848b570aa6b706727f8ffe68960 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 17 Jul 2019 22:20:14 +0800 Subject: [PATCH 0526/7155] staging: rtl8723bs: remove set but not used variable 'cck_highpwr' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/odm_HWConfig.c: In function odm_RxPhyStatus92CSeries_Parsing: drivers/staging/rtl8723bs/hal/odm_HWConfig.c:92:5: warning: variable cck_highpwr set but not used [-Wunused-but-set-variable] It is never used and can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190717142014.43216-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm_HWConfig.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c index 49fa814068b8..71919a3d81ab 100644 --- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c @@ -89,7 +89,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( u8 RSSI, total_rssi = 0; bool isCCKrate = false; u8 rf_rx_num = 0; - u8 cck_highpwr = 0; u8 LNA_idx, VGA_idx; PPHY_STATUS_RPT_8192CD_T pPhyStaRpt = (PPHY_STATUS_RPT_8192CD_T)pPhyStatus; @@ -107,16 +106,10 @@ static void odm_RxPhyStatus92CSeries_Parsing( /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ /* */ - /* if (pHalData->eRFPowerState == eRfOn) */ - cck_highpwr = pDM_Odm->bCckHighPower; - /* else */ - /* cck_highpwr = false; */ - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */ /* The RSSI formula should be modified according to the gain table */ - /* In 88E, cck_highpwr is always set to 1 */ LNA_idx = ((cck_agc_rpt & 0xE0)>>5); VGA_idx = (cck_agc_rpt & 0x1F); rx_pwr_all = odm_CCKRSSI_8723B(LNA_idx, VGA_idx); -- GitLab From fee0cc591ae4e887c1b4304b7d69a7c209b2f24a Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 17 Jul 2019 23:26:43 +0530 Subject: [PATCH 0527/7155] staging: rtl8723bs: os_dep: change return type of rtw_suspend_ap_wow Change return type of rtw_suspend_ap_wow as its always return SUCCCESS. Issue found with coccicheck Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190717175642.GA10582@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 50928b2000b9..2ddafb07d5b6 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -1354,13 +1354,12 @@ void rtw_suspend_wow(struct adapter *padapter) #endif /* ifdef CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN -int rtw_suspend_ap_wow(struct adapter *padapter) +void rtw_suspend_ap_wow(struct adapter *padapter) { u8 ch, bw, offset; struct net_device *pnetdev = padapter->pnetdev; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct wowlan_ioctl_param poidparam; - int ret = _SUCCESS; DBG_871X("==> " FUNC_ADPT_FMT " entry....\n", FUNC_ADPT_ARG(padapter)); @@ -1402,7 +1401,6 @@ int rtw_suspend_ap_wow(struct adapter *padapter) rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, 0, "AP-WOWLAN"); DBG_871X("<== " FUNC_ADPT_FMT " exit....\n", FUNC_ADPT_ARG(padapter)); - return ret; } #endif /* ifdef CONFIG_AP_WOWLAN */ -- GitLab From 1c4bfacf1d70c3daba4733eb1a6450d27422e087 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 17 Jul 2019 23:36:35 +0530 Subject: [PATCH 0528/7155] staging: rtl8723bs: core: Remove Unneeded variable ret Remove Unneeded variable ret . Return _FAIL . We cannot change return type of on_action_spct as its callback function. Issue identified with coccicheck. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190717180635.GA11412@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 6d0014251f86..2128886c9924 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -1874,7 +1874,6 @@ unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) { - unsigned int ret = _FAIL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->u.hdr.rx_data; @@ -1906,7 +1905,7 @@ unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_fr } exit: - return ret; + return _FAIL; } unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) -- GitLab From 8638eeed74817358280d8d393503d50f60788527 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 21 Jul 2019 19:57:35 +0200 Subject: [PATCH 0529/7155] staging: rtl8723bs: remove unused file hal_phy.c Remove the unused file hal_phy.c. No function from this file is used in the driver code and it is not listed in the Makefile. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190721175735.24173-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_phy.c | 157 ------------------------ 1 file changed, 157 deletions(-) delete mode 100644 drivers/staging/rtl8723bs/hal/hal_phy.c diff --git a/drivers/staging/rtl8723bs/hal/hal_phy.c b/drivers/staging/rtl8723bs/hal/hal_phy.c deleted file mode 100644 index 24a9d8f783f0..000000000000 --- a/drivers/staging/rtl8723bs/hal/hal_phy.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#define _HAL_PHY_C_ - -#include - -/* */ -/* ==> RF shadow Operation API Code Section!!! */ -/* */ -/*----------------------------------------------------------------------------- - * Function: PHY_RFShadowRead - * PHY_RFShadowWrite - * PHY_RFShadowCompare - * PHY_RFShadowRecorver - * PHY_RFShadowCompareAll - * PHY_RFShadowRecorverAll - * PHY_RFShadowCompareFlagSet - * PHY_RFShadowRecorverFlagSet - * - * Overview: When we set RF register, we must write shadow at first. - * When we are running, we must compare shadow abd locate error addr. - * Decide to recorver or not. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/20/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -u32 PHY_RFShadowRead(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - return RF_Shadow[eRFPath][Offset].Value; - -} /* PHY_RFShadowRead */ - - -void PHY_RFShadowWrite( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u32 Data -) -{ - RF_Shadow[eRFPath][Offset].Value = (Data & bRFRegOffsetMask); - RF_Shadow[eRFPath][Offset].Driver_Write = true; - -} /* PHY_RFShadowWrite */ - - -bool PHY_RFShadowCompare(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - u32 reg; - /* Check if we need to check the register */ - if (RF_Shadow[eRFPath][Offset].Compare == true) { - reg = rtw_hal_read_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask); - /* Compare shadow and real rf register for 20bits!! */ - if (RF_Shadow[eRFPath][Offset].Value != reg) { - /* Locate error position. */ - RF_Shadow[eRFPath][Offset].ErrorOrNot = true; - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowCompare RF-%d Addr%02lx Err = %05lx\n", */ - /* eRFPath, Offset, reg)); */ - } - return RF_Shadow[eRFPath][Offset].ErrorOrNot; - } - return false; -} /* PHY_RFShadowCompare */ - - -void PHY_RFShadowRecorver(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - /* Check if the address is error */ - if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true) { - /* Check if we need to recorver the register. */ - if (RF_Shadow[eRFPath][Offset].Recorver == true) { - rtw_hal_write_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask, - RF_Shadow[eRFPath][Offset].Value); - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowRecorver RF-%d Addr%02lx=%05lx", */ - /* eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value)); */ - } - } - -} /* PHY_RFShadowRecorver */ - - -void PHY_RFShadowCompareAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowCompare(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowCompareAll */ - - -void PHY_RFShadowRecorverAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowRecorver(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowRecorverAll */ - - -void -PHY_RFShadowCompareFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Compare = Type; - -} /* PHY_RFShadowCompareFlagSet */ - - -void PHY_RFShadowRecorverFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Recorver = Type; - -} /* PHY_RFShadowRecorverFlagSet */ - - -void PHY_RFShadowCompareFlagSetAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - /* 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!! */ - if (Offset != 0x26 && Offset != 0x27) - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, false); - else - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, true); - } - } - -} /* PHY_RFShadowCompareFlagSetAll */ -- GitLab From 3774fb6bd2b99858f37d9559bf0e3f9a9649f3f3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Jul 2019 15:59:05 +0100 Subject: [PATCH 0530/7155] staging: rtl8723bs: hal: remove redundant assignment to variable n The variable n is being assigned a value that is never read, the assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190723145905.13514-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index e23b39ab16c5..032d01834f3f 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -486,7 +486,6 @@ s32 rtl8723bs_init_recv_priv(struct adapter *padapter) } if (precvpriv->pallocated_recv_buf) { - n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; kfree(precvpriv->pallocated_recv_buf); precvpriv->pallocated_recv_buf = NULL; } -- GitLab From 756e4624ddcfdc2792fe389262ba7447f22d8913 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 17 Jul 2019 22:35:51 +0800 Subject: [PATCH 0531/7155] staging: rtl8192e: remove set but not used variable 'payload ' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8192e/rtllib_rx.c: In function rtllib_rx_InfraAdhoc: drivers/staging/rtl8192e/rtllib_rx.c:1303:6: warning: variable payload set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190717143551.29200-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 0c19ac2bc3bf..0bae0a0a4cbe 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1300,7 +1300,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, struct rx_ts_record *pTS = NULL; u16 fc, sc, SeqNum = 0; u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; - u8 *payload; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; u8 bssid[ETH_ALEN] = {0}; @@ -1412,7 +1411,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, /* Parse rx data frame (For AMSDU) */ /* skb: hdr + (possible reassembled) full plaintext payload */ - payload = skb->data + hdrlen; rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC); if (!rxb) goto rx_dropped; -- GitLab From 7f9b583358a4fe31cdbde61e5f50d568be4cc69e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sat, 20 Jul 2019 09:29:08 +0200 Subject: [PATCH 0532/7155] staging: mt7621-pci: avoid use 'err' local variable Function 'mt7621_pcie_request_resources' is using 'err' local variable to get value returned from 'devm_request_pci_bus_resources' and returning after that. This is not needed at all. Instead of that just directly return returned value by the function which is also returning zero on success. Signed-off-by: Sergio Paracuellos Link: https://lore.kernel.org/r/20190720072908.16795-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 2e37fd136ab8..6b98827da57f 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -617,17 +617,12 @@ static int mt7621_pcie_request_resources(struct mt7621_pcie *pcie, struct list_head *res) { struct device *dev = pcie->dev; - int err; pci_add_resource_offset(res, &pcie->io, pcie->offset.io); pci_add_resource_offset(res, &pcie->mem, pcie->offset.mem); pci_add_resource(res, &pcie->busn); - err = devm_request_pci_bus_resources(dev, res); - if (err < 0) - return err; - - return 0; + return devm_request_pci_bus_resources(dev, res); } static int mt7621_pcie_register_host(struct pci_host_bridge *host, -- GitLab From 4b2c85cacde3f92c2214af60ff89dd6bd93289ca Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Jul 2019 15:50:22 +0100 Subject: [PATCH 0533/7155] drivers/staging/rtl8192u: fix indentation issue, remove extra tab A statement is indented one level too deeply; clean this up by removing a tab. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190723145022.11608-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index ade14ef05730..c23e43b095d9 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -1334,7 +1334,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) return; } /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ - queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); TM_Trigger = 0; } -- GitLab From 2e20a5ac67f8a589ad2ba56717b8419298064354 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:37 +0530 Subject: [PATCH 0534/7155] staging: rtl8723bs: rtw_pwrctrl: Change true/false checks Change comparisons to true to the variable itself. Change comparisons to false to the negation of the variable. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_pwrctrl.c | 117 +++++++++---------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index ae7fb7046c93..62b42e29e4fd 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -103,7 +103,7 @@ static bool rtw_pwr_unassociated_idle(struct adapter *adapter) bool ret = false; - if (adapter_to_pwrctl(adapter)->bpower_saving == true) { + if (adapter_to_pwrctl(adapter)->bpower_saving) { /* DBG_871X("%s: already in LPS or IPS mode\n", __func__); */ goto exit; } @@ -167,7 +167,7 @@ void rtw_ps_processor(struct adapter *padapter) goto exit; } - if (pwrpriv->bInSuspend == true) {/* system suspend or autosuspend */ + if (pwrpriv->bInSuspend) {/* system suspend or autosuspend */ pdbgpriv->dbg_ps_insuspend_cnt++; DBG_871X("%s, pwrpriv->bInSuspend == true ignore this process\n", __func__); return; @@ -219,10 +219,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets if (jiffies_to_msecs(jiffies - start_time) > 2000) { /* 2 sec == watch dog timer */ if (xmit_cnt > 8) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Tx = %d\n", xmit_cnt); bLeaveLPS = true; } @@ -234,10 +233,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets } else { /* from rx path */ if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); bLeaveLPS = true; } @@ -267,7 +265,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) pslv = PS_STATE(pslv); - if (pwrpriv->brpwmtimeout == true) { + if (pwrpriv->brpwmtimeout) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __func__, pslv); } else { if ((pwrpriv->rpwm == pslv) @@ -278,8 +276,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) } } - if ((padapter->bSurpriseRemoved == true) || - (padapter->hw_init_completed == false)) { + if ((padapter->bSurpriseRemoved) || !(padapter->hw_init_completed)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); @@ -289,7 +286,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) return; } - if (padapter->bDriverStopped == true) { + if (padapter->bDriverStopped) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv)); @@ -355,14 +352,14 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_mode) + if (pwrpriv->bInSuspend && pwrpriv->wowlan_mode) return true; - else if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) + else if (pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) return true; - else if (true == pwrpriv->bInSuspend) + else if (pwrpriv->bInSuspend) return false; #else - if (true == pwrpriv->bInSuspend) + if (pwrpriv->bInSuspend) return false; #endif @@ -381,7 +378,7 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) ) return false; - if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) { + if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && !(padapter->securitypriv.binstallGrpkey)) { DBG_871X("Group handshake still in progress !!!\n"); return false; } @@ -417,13 +414,9 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */ if (ps_mode == PS_MODE_ACTIVE) { - if (1 - && (((hal_btcoex_IsBtControlLps(padapter) == false) - ) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == false)) - ) - ) { + if (!(hal_btcoex_IsBtControlLps(padapter)) + || (hal_btcoex_IsBtControlLps(padapter) + && !(hal_btcoex_IsLpsOn(padapter)))) { DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n", FUNC_ADPT_ARG(padapter), msg); @@ -431,8 +424,7 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a rtw_set_rpwm(padapter, PS_STATE_S4); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (pwrpriv->wowlan_mode == true || - pwrpriv->wowlan_ap_mode == true) { + if (pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode) { unsigned long start_time; u32 delay_ms; u8 val8; @@ -461,8 +453,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a } } else { if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == true)) + || ((hal_btcoex_IsBtControlLps(padapter)) + && (hal_btcoex_IsLpsOn(padapter))) ) { u8 pslv; @@ -481,8 +473,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a if (pwrpriv->alives == 0) pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && (hal_btcoex_IsBtControlLps(padapter))) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -513,10 +505,10 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) start_time = jiffies; while (1) { rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake); - if (true == bAwake) + if (bAwake) break; - if (true == padapter->bSurpriseRemoved) { + if (padapter->bSurpriseRemoved) { err = -2; DBG_871X("%s: device surprise removed!!\n", __func__); break; @@ -544,7 +536,7 @@ void LPS_Enter(struct adapter *padapter, const char *msg) int n_assoc_iface = 0; char buf[32] = {0}; - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; /* Skip lps enter request if number of assocated adapters is not 1 */ @@ -557,8 +549,8 @@ void LPS_Enter(struct adapter *padapter, const char *msg) if (get_iface_type(padapter) != IFACE_PORT0) return; - if (PS_RDY_CHECK(dvobj->padapters) == false) - return; + if (!PS_RDY_CHECK(dvobj->padapters)) + return; if (pwrpriv->bLeisurePs) { /* Idle for a while if we connect to AP a while ago. */ @@ -589,7 +581,7 @@ void LPS_Leave(struct adapter *padapter, const char *msg) /* DBG_871X("+LeisurePSLeave\n"); */ - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; if (pwrpriv->bLeisurePs) { @@ -615,13 +607,13 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) DBG_871X("%s.....\n", __func__); - if (true == Adapter->bSurpriseRemoved) { + if (Adapter->bSurpriseRemoved) { DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n", FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved); return; } - if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)) { /* connect */ + if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { DBG_871X("%s: Driver Already Leave LPS\n", __func__); @@ -637,7 +629,7 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0); } else { if (pwrpriv->rf_pwrstate == rf_off) - if (false == ips_leave(pri_padapter)) + if (!ips_leave(pri_padapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -675,7 +667,7 @@ void LeaveAllPowerSaveMode(struct adapter *Adapter) LPS_Leave_check(Adapter); } else { if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) { - if (false == ips_leave(Adapter)) + if (!ips_leave(Adapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -698,15 +690,14 @@ void LPS_Leave_check( while (1) { mutex_lock(&pwrpriv->lock); - if ((padapter->bSurpriseRemoved == true) - || (padapter->hw_init_completed == false) - || (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - ) + if (padapter->bSurpriseRemoved + || !(padapter->hw_init_completed) + || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)) bReady = true; mutex_unlock(&pwrpriv->lock); - if (true == bReady) + if (bReady) break; if (jiffies_to_msecs(jiffies - start_time) > 100) { @@ -870,7 +861,7 @@ s32 rtw_register_task_alive(struct adapter *padapter, u32 task) register_task_alive(pwrctrl, task); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n", __func__, task, pwrctrl->cpwm, pwrctrl->alives)); @@ -910,8 +901,8 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -924,7 +915,7 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) unregister_task_alive(pwrctrl, task); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -965,7 +956,7 @@ s32 rtw_register_tx_alive(struct adapter *padapter) register_task_alive(pwrctrl, XMIT_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1014,7 +1005,7 @@ s32 rtw_register_cmd_alive(struct adapter *padapter) register_task_alive(pwrctrl, CMD_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1051,8 +1042,8 @@ void rtw_unregister_tx_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1065,7 +1056,7 @@ void rtw_unregister_tx_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, XMIT_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1093,8 +1084,8 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1107,7 +1098,7 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, CMD_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1237,7 +1228,7 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal DBG_871X("%s wait ps_processing done\n", __func__); } - if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { DBG_871X("%s wait bInSuspend...\n", __func__); while (pwrpriv->bInSuspend && jiffies_to_msecs(jiffies - start) <= 3000 @@ -1251,19 +1242,19 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal } /* System suspend is not allowed to wakeup */ - if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { ret = _FAIL; goto exit; } /* block??? */ - if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) { + if (pwrpriv->bInternalAutoSuspend && padapter->net_closed) { ret = _FAIL; goto exit; } /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + if (check_fwstate(pmlmepriv, _FW_LINKED)) { ret = _SUCCESS; goto exit; } -- GitLab From fe2ffeb5fdd297ad90f6252defbd635ca3037367 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:38 +0530 Subject: [PATCH 0535/7155] staging: rtl8723bs: hal: Replace function PHY_SetTxPowerIndex() Remove function PHY_SetTxPowerIndex as it does nothing except call PHY_SetTxPowerIndex_8723B. Rename PHY_SetTxPowerIndex_8723B to PHY_SetTxPowerIndex to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com_phycfg.c | 7 ------- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 2 +- drivers/staging/rtl8723bs/include/hal_com_phycfg.h | 8 -------- drivers/staging/rtl8723bs/include/hal_phy_cfg.h | 2 +- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 336764464e7d..7b1e6c4a2e8d 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -2051,13 +2051,6 @@ u8 PHY_GetTxPowerIndex( return PHY_GetTxPowerIndex_8723B(padapter, RFPath, Rate, BandWidth, Channel); } -void PHY_SetTxPowerIndex( - struct adapter *padapter, u32 PowerIndex, u8 RFPath, u8 Rate -) -{ - PHY_SetTxPowerIndex_8723B(padapter, PowerIndex, RFPath, Rate); -} - void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index 25c75b977666..b02ff10fedbf 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -585,7 +585,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter) * <20120830, Kordan> **************************************************************************************************************/ -void PHY_SetTxPowerIndex_8723B( +void PHY_SetTxPowerIndex( struct adapter *Adapter, u32 PowerIndex, u8 RFPath, diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index f841546584a7..f3521b7ae295 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -222,14 +222,6 @@ enum CHANNEL_WIDTH BandWidth, u8 Channel ); -void -PHY_SetTxPowerIndex( -struct adapter * padapter, -u32 PowerIndex, -u8 RFPath, -u8 Rate - ); - void Hal_ChannelPlanToRegulation( struct adapter * Adapter, diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 640427f407e3..1ebd7094705f 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -65,7 +65,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter ); s32 PHY_MACConfig8723B(struct adapter *padapter); void -PHY_SetTxPowerIndex_8723B( +PHY_SetTxPowerIndex( struct adapter * Adapter, u32 PowerIndex, u8 RFPath, -- GitLab From 9dd2f1d9a1580717605a8f2ce882105710966b7a Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:39 +0530 Subject: [PATCH 0536/7155] staging: rtl8723bs: hal: Replace function PHY_GetTxPowerIndex() Remove function PHY_GetTxPowerIndex as it does nothing except call PHY_GetTxPowerIndex_8723B. Rename PHY_GetTxPowerIndex_8723B to PHY_GetTxPowerIndex to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com_phycfg.c | 11 ----------- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 2 +- drivers/staging/rtl8723bs/include/hal_com_phycfg.h | 9 --------- drivers/staging/rtl8723bs/include/hal_phy_cfg.h | 2 +- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 7b1e6c4a2e8d..6539bee9b5ba 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -2040,17 +2040,6 @@ void PHY_SetTxPowerLimit( } } -u8 PHY_GetTxPowerIndex( - struct adapter *padapter, - u8 RFPath, - u8 Rate, - enum CHANNEL_WIDTH BandWidth, - u8 Channel -) -{ - return PHY_GetTxPowerIndex_8723B(padapter, RFPath, Rate, BandWidth, Channel); -} - void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index b02ff10fedbf..cb3ec085faa5 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -668,7 +668,7 @@ void PHY_SetTxPowerIndex( } } -u8 PHY_GetTxPowerIndex_8723B( +u8 PHY_GetTxPowerIndex( struct adapter *padapter, u8 RFPath, u8 Rate, diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index f3521b7ae295..9167f1e7827f 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -213,15 +213,6 @@ PHY_GetTxPowerTrackingOffset( u8 RFPath ); -u8 -PHY_GetTxPowerIndex( -struct adapter * padapter, -u8 RFPath, -u8 Rate, -enum CHANNEL_WIDTH BandWidth, -u8 Channel - ); - void Hal_ChannelPlanToRegulation( struct adapter * Adapter, diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 1ebd7094705f..b40868b2e76f 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -73,7 +73,7 @@ u8 Rate ); u8 -PHY_GetTxPowerIndex_8723B( +PHY_GetTxPowerIndex( struct adapter * padapter, u8 RFPath, u8 Rate, -- GitLab From 0528096df3778c51a99ae14ee36e1c13f6fd76e8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:40 +0530 Subject: [PATCH 0537/7155] staging: rtl8723bs: hal: Replace function rtl8723b_set_wowlan_cmd() Remove function rtl8723b_set_wowlan_cmd as all it does is call rtl8723b_set_FwWoWlanRelated_cmd. Rename rtl8723b_set_FwWoWlanRelated_cmd to rtl8723b_set_wowlan_cmd to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 080e974914b6..0f2767c0454c 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1300,7 +1300,7 @@ static void rtl8723b_set_FwScanOffloadInfo_cmd(struct adapter *padapter, PRSVDPA } #endif /* CONFIG_PNO_SUPPORT */ -static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) { struct security_priv *psecpriv = &padapter->securitypriv; struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter); @@ -1346,11 +1346,6 @@ static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); } - -void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_FwWoWlanRelated_cmd(padapter, enable); -} #endif /* CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN -- GitLab From 7a9a7332b62b802ca1a71f3e1351767129f3b53e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:41 +0530 Subject: [PATCH 0538/7155] staging: rtl8723bs: hal: Replace function rtl8723b_set_ap_wowlan_cmd() Remove function rtl8723b_set_ap_wowlan_cmd as all it does is call rtl8723b_set_AP_FwWoWlanRelated_cmd. Rename rtl8723b_set_AP_FwWoWlanRelated_cmd to rtl8723b_set_ap_wowlan_cmd to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 0f2767c0454c..79c1e3edb189 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1393,7 +1393,7 @@ static void rtl8723b_set_Fw_AP_Offload_Cmd(struct adapter *padapter, u8 bFuncEn) H2C_AP_OFFLOAD_LEN, u1H2CAPOffloadCtrlParm); } -static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) { DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable); if (enable) { @@ -1408,11 +1408,6 @@ static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); return ; } - -void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_AP_FwWoWlan_cmd(padapter, enable); -} #endif /* CONFIG_AP_WOWLAN */ /* */ -- GitLab From d40e29d7e219cd214eef295149fd2678871ac982 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:42 +0530 Subject: [PATCH 0539/7155] staging: rtl8723bs: Replace function beacon_timing_control() Remove function beacon_timing_control as it does nothing except call rtw_hal_bcn_related_reg_setting. Rename rtw_hal_bcn_related_reg_setting to beacon_timing_control to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 5 ----- drivers/staging/rtl8723bs/hal/hal_intf.c | 2 +- drivers/staging/rtl8723bs/include/hal_intf.h | 2 +- drivers/staging/rtl8723bs/include/rtw_mlme_ext.h | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index 76c50377f0fe..d78fbbc98fa2 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -1996,11 +1996,6 @@ void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) } } -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} - void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta) { int i; diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index acb25978a46c..7d8f21f32fb9 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -369,7 +369,7 @@ void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter) } } -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter) +void beacon_timing_control(struct adapter *padapter) { if (padapter->HalFunc.SetBeaconRelatedRegistersHandler) padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter); diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h index 3a0c3d079d50..24926ebaf950 100644 --- a/drivers/staging/rtl8723bs/include/hal_intf.h +++ b/drivers/staging/rtl8723bs/include/hal_intf.h @@ -362,7 +362,7 @@ void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_l void rtw_hal_start_thread(struct adapter *padapter); void rtw_hal_stop_thread(struct adapter *padapter); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask); void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data); diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 70cd8c0e3641..fd3cf955c9f8 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -650,7 +650,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char* MacAddr, unsi void report_add_sta_event(struct adapter *padapter, unsigned char* MacAddr, int cam_idx); void report_wmm_edca_update(struct adapter *padapter); -void beacon_timing_control(struct adapter *padapter); u8 chk_bmc_sleepq_cmd(struct adapter *padapter); extern u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); -- GitLab From 4e8cc1c2df86f4245a37708bc007f8d530e235a1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:43 +0530 Subject: [PATCH 0540/7155] staging: rtl8723bs: Replace function odm_TXPowerTrackingInit() Remove function odm_TXPowerTrackingInit as all it does is call odm_TXPowerTrackingThermalMeterInit. Rename odm_TXPowerTrackingThermalMeterInit to odm_TXPowerTrackingInit to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index e3f4307f3d20..01f732853689 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -339,8 +339,6 @@ void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm); void odm_RateAdaptiveMaskInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm); - void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm); @@ -1324,11 +1322,6 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) /* 3 Tx Power Tracking */ /* 3 ============================================================ */ -void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) -{ - odm_TXPowerTrackingThermalMeterInit(pDM_Odm); -} - static u8 getSwingIndex(PDM_ODM_T pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; @@ -1353,7 +1346,7 @@ static u8 getSwingIndex(PDM_ODM_T pDM_Odm) return i; } -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm) +void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) { u8 defaultSwingIndex = getSwingIndex(pDM_Odm); u8 p = 0; -- GitLab From f79670abd541d6abeda238ce91ac5859aa309515 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:44 +0530 Subject: [PATCH 0541/7155] staging: rtl8723bs: Replace function ODM_TXPowerTrackingCheck() Remove function ODM_TXPowerTrackingCheck as all it does is call odm_TXPowerTrackingCheckCE. Rename odm_TXPowerTrackingCheckCE to ODM_TXPowerTrackingCheck to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index 01f732853689..dd9a16fb83a4 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -342,8 +342,6 @@ void odm_RateAdaptiveMaskInit(PDM_ODM_T pDM_Odm); void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm); - /* Remove Edca by Yu Chen */ @@ -1390,13 +1388,7 @@ void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) } - void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm) -{ - odm_TXPowerTrackingCheckCE(pDM_Odm); -} - -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; -- GitLab From 4da947b27cdb71b1e5718d202e0028c0aeb9bdfe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:45 +0530 Subject: [PATCH 0542/7155] staging: rtl8723bs: Remove unused function prototype ODM_SetAntenna() Remove unused function prototype ODM_SetAntenna. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index 6ba77bb70889..fba3b9e1491b 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -1365,10 +1365,6 @@ extern u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE]; #define SWAW_STEP_PEAK 0 #define SWAW_STEP_DETERMINE 1 -/* Remove DIG by yuchen */ - -void ODM_SetAntenna(PDM_ODM_T pDM_Odm, u8 Antenna); - /* Remove BB power saving by Yuchen */ #define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck -- GitLab From 0f073df7e731b7b6c30c473dfdd28e0fd3cd489d Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Thu, 25 Jul 2019 08:53:25 +0530 Subject: [PATCH 0543/7155] staging: rtl8723bs: hal: Remove unneeded variable pU1Tmp Both pu8 and pU1Tmp are of same data type u8. So replace pU1Tmp with u8. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190725032325.GA16473@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 5257287b4f4d..8987b5f892c0 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -389,7 +389,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) u8 *pu8; s32 *pS4Tmp; u32 *pU4Tmp; - u8 *pU1Tmp; u8 ret; @@ -403,7 +402,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) pu8 = pOutBuf; pS4Tmp = pOutBuf; pU4Tmp = pOutBuf; - pU1Tmp = pOutBuf; ret = true; switch (getType) { @@ -516,32 +514,32 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) break; case BTC_GET_U1_WIFI_DOT11_CHNL: - *pU1Tmp = padapter->mlmeextpriv.cur_channel; + *pu8 = padapter->mlmeextpriv.cur_channel; break; case BTC_GET_U1_WIFI_CENTRAL_CHNL: - *pU1Tmp = pHalData->CurrentChannel; + *pu8 = pHalData->CurrentChannel; break; case BTC_GET_U1_WIFI_HS_CHNL: - *pU1Tmp = 0; + *pu8 = 0; ret = false; break; case BTC_GET_U1_MAC_PHY_MODE: - *pU1Tmp = BTC_SMSP; + *pu8 = BTC_SMSP; /* *pU1Tmp = BTC_DMSP; */ /* *pU1Tmp = BTC_DMDP; */ /* *pU1Tmp = BTC_MP_UNKNOWN; */ break; case BTC_GET_U1_AP_NUM: - *pU1Tmp = halbtcoutsrc_GetWifiScanAPNum(padapter); + *pu8 = halbtcoutsrc_GetWifiScanAPNum(padapter); break; /* 1Ant =========== */ case BTC_GET_U1_LPS_MODE: - *pU1Tmp = padapter->dvobj->pwrctl_priv.pwr_mode; + *pu8 = padapter->dvobj->pwrctl_priv.pwr_mode; break; default: -- GitLab From 80257121f435a4b8cb9b1e976ebeab186c2357eb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:15 +0200 Subject: [PATCH 0544/7155] misc: eeprom: ee1004: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190722172616.3982-2-wsa+renesas@sang-engineering.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/ee1004.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index 6f00c33cfe22..b081c67416d7 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -195,13 +195,13 @@ static int ee1004_probe(struct i2c_client *client, mutex_lock(&ee1004_bus_lock); if (++ee1004_dev_count == 1) { for (cnr = 0; cnr < 2; cnr++) { - ee1004_set_page[cnr] = i2c_new_dummy(client->adapter, + ee1004_set_page[cnr] = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); - if (!ee1004_set_page[cnr]) { + if (IS_ERR(ee1004_set_page[cnr])) { dev_err(&client->dev, "address 0x%02x unavailable\n", EE1004_ADDR_SET_PAGE + cnr); - err = -EADDRINUSE; + err = PTR_ERR(ee1004_set_page[cnr]); goto err_clients; } } -- GitLab From 2495aeeca24df3dac97ebd9722862b0d96aee852 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:16 +0200 Subject: [PATCH 0545/7155] misc: eeprom: max6875: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20190722172616.3982-3-wsa+renesas@sang-engineering.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/max6875.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c index 4d0cb90f4aeb..9da81f6d4a1c 100644 --- a/drivers/misc/eeprom/max6875.c +++ b/drivers/misc/eeprom/max6875.c @@ -150,9 +150,9 @@ static int max6875_probe(struct i2c_client *client, return -ENOMEM; /* A fake client is created on the odd address */ - data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); - if (!data->fake_client) { - err = -ENOMEM; + data->fake_client = i2c_new_dummy_device(client->adapter, client->addr + 1); + if (IS_ERR(data->fake_client)) { + err = PTR_ERR(data->fake_client); goto exit_kfree; } -- GitLab From db4ad308a50620c8a24419dcc6556fabaf594c0e Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 20:46:49 +0800 Subject: [PATCH 0546/7155] misc: alcor_pci: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190723124649.24728-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cardreader/alcor_pci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c index bcb10fa4bc3a..259fe1dfec03 100644 --- a/drivers/misc/cardreader/alcor_pci.c +++ b/drivers/misc/cardreader/alcor_pci.c @@ -334,8 +334,7 @@ static void alcor_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int alcor_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct alcor_pci_priv *priv = pci_get_drvdata(pdev); + struct alcor_pci_priv *priv = dev_get_drvdata(dev); alcor_pci_aspm_ctrl(priv, 1); return 0; @@ -344,8 +343,7 @@ static int alcor_suspend(struct device *dev) static int alcor_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct alcor_pci_priv *priv = pci_get_drvdata(pdev); + struct alcor_pci_priv *priv = dev_get_drvdata(dev); alcor_pci_aspm_ctrl(priv, 0); return 0; -- GitLab From 57cd166afc4b430d7b98dca71911bfef478d236b Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 21:18:38 +0800 Subject: [PATCH 0547/7155] USB: core: hcd-pci: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190724131838.1931-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 03432467b05f..03bee698d7eb 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -407,8 +407,7 @@ static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable) static int check_root_hub_suspended(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct usb_hcd *hcd = pci_get_drvdata(pci_dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); if (HCD_RH_RUNNING(hcd)) { dev_warn(dev, "Root hub is not suspended\n"); -- GitLab From 07e803ec9f6be4b216b89f8530ea30d2a397696d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:16:39 +0300 Subject: [PATCH 0548/7155] usb: dwc2: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Minas Harutyunyan Link: https://lore.kernel.org/r/20190723191639.67883-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/params.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 55f841a54015..31e090ac9f1e 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -404,10 +404,7 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) device_property_read_u32(hsotg->dev, "g-np-tx-fifo-size", &p->g_np_tx_fifo_size); - num = device_property_read_u32_array(hsotg->dev, - "g-tx-fifo-size", - NULL, 0); - + num = device_property_count_u32(hsotg->dev, "g-tx-fifo-size"); if (num > 0) { num = min(num, 15); memset(p->g_tx_fifo_size, 0, -- GitLab From 41b57327b270935de8023f5473520dd6a81bd013 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:17:04 +0300 Subject: [PATCH 0549/7155] usb: dwc3: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190723191704.67945-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c9bb93a2c81e..98bce85c29d0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -813,8 +813,7 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) * result = 1, means INCRx burst mode supported. * result > 1, means undefined length burst mode supported. */ - ntype = device_property_read_u32_array(dev, - "snps,incr-burst-type-adjustment", NULL, 0); + ntype = device_property_count_u32(dev, "snps,incr-burst-type-adjustment"); if (ntype <= 0) return; -- GitLab From bc7514925cf50bf81f514d0f2d7521b25973a639 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:37:50 +0300 Subject: [PATCH 0550/7155] usb: typec: tcpm: Switch to use fwnode_property_count_uXX() Use use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20190723193750.69038-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index fba32d84e578..ec525811a9eb 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4410,8 +4410,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, goto sink; /* Get source pdos */ - ret = fwnode_property_read_u32_array(fwnode, "source-pdos", - NULL, 0); + ret = fwnode_property_count_u32(fwnode, "source-pdos"); if (ret <= 0) return -EINVAL; @@ -4435,8 +4434,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, return -EINVAL; sink: /* Get sink pdos */ - ret = fwnode_property_read_u32_array(fwnode, "sink-pdos", - NULL, 0); + ret = fwnode_property_count_u32(fwnode, "sink-pdos"); if (ret <= 0) return -EINVAL; -- GitLab From 6ce9ba07b1b78ca3412eac808cd59eea09c80468 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:47:26 +0300 Subject: [PATCH 0551/7155] usb: typec: mux: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190723194726.69545-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index 61b7bc58dd81..57907f26f681 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -215,7 +215,7 @@ static void *typec_mux_match(struct device_connection *con, int ep, void *data) } /* Alternate Mode muxes */ - nval = fwnode_property_read_u16_array(con->fwnode, "svid", NULL, 0); + nval = fwnode_property_count_u16(con->fwnode, "svid"); if (nval <= 0) return NULL; -- GitLab From 110f87a6a5f65e825852632b9557f463e65251d7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 21 Jul 2019 23:49:08 +0900 Subject: [PATCH 0552/7155] usb: host: oxu210hp-hcd: remove include/linux/oxu210hp.h struct oxu210hp_platform_data is defined, but not used at all. $ git grep oxu210hp_platform_data include/linux/oxu210hp.h:struct oxu210hp_platform_data { include/linux/oxu210hp.h exists just for defining an unused structure, so it can go away. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190721144909.5295-1-yamada.masahiro@socionext.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp.h | 2 -- include/linux/oxu210hp.h | 8 -------- 2 files changed, 10 deletions(-) delete mode 100644 include/linux/oxu210hp.h diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h index 437044147862..67ebea4993b6 100644 --- a/drivers/usb/host/oxu210hp.h +++ b/drivers/usb/host/oxu210hp.h @@ -444,5 +444,3 @@ enum ehci_timer_action { TIMER_ASYNC_SHRINK, TIMER_ASYNC_OFF, }; - -#include diff --git a/include/linux/oxu210hp.h b/include/linux/oxu210hp.h deleted file mode 100644 index 94cd25165c08..000000000000 --- a/include/linux/oxu210hp.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* platform data for the OXU210HP HCD */ - -struct oxu210hp_platform_data { - unsigned int bus16:1; - unsigned int use_hcd_otg:1; - unsigned int use_hcd_sph:1; -}; -- GitLab From 6443c671d5cbc60932b31f19f48091cddb2285eb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 21 Jul 2019 23:49:09 +0900 Subject: [PATCH 0553/7155] usb: host: oxu210hp-hcd: squash oxu210hp.h into oxu210hp-hcd.c The header, oxu210hp.h is only included from oxu210hp-hcd.c so squash it. When I moved the code, I also fixed the following warnings from scripts/checkpatch.pl: drivers/usb/host/oxu210hp-hcd.c:117: warning: __packed is preferred over __attribute__((packed)) drivers/usb/host/oxu210hp-hcd.c:196: warning: __packed is preferred over __attribute__((packed)) drivers/usb/host/oxu210hp-hcd.c:221: warning: __packed is preferred over __attribute__((packed)) drivers/usb/host/oxu210hp-hcd.c:266: warning: __aligned(size) is preferred over __attribute__((aligned(size))) drivers/usb/host/oxu210hp-hcd.c:336: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:354: warning: __aligned(size) is preferred over __attribute__((aligned(size))) drivers/usb/host/oxu210hp-hcd.c:385: warning: __aligned(size) is preferred over __attribute__((aligned(size))) drivers/usb/host/oxu210hp-hcd.c:393: warning: __aligned(size) is preferred over __attribute__((aligned(size))) drivers/usb/host/oxu210hp-hcd.c:429: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:432: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:436: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:451: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:461: warning: Prefer 'unsigned int' to bare use of 'unsigned' drivers/usb/host/oxu210hp-hcd.c:467: warning: please, no space before tabs Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190721144909.5295-2-yamada.masahiro@socionext.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 443 ++++++++++++++++++++++++++++++- drivers/usb/host/oxu210hp.h | 446 -------------------------------- 2 files changed, 441 insertions(+), 448 deletions(-) delete mode 100644 drivers/usb/host/oxu210hp.h diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 47c5515a9ce4..09cc19df798e 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -31,10 +31,449 @@ #include #include -#include "oxu210hp.h" - #define DRIVER_VERSION "0.0.50" +#define OXU_DEVICEID 0x00 + #define OXU_REV_MASK 0xffff0000 + #define OXU_REV_SHIFT 16 + #define OXU_REV_2100 0x2100 + #define OXU_BO_SHIFT 8 + #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) + #define OXU_MAJ_REV_SHIFT 4 + #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) + #define OXU_MIN_REV_SHIFT 0 + #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) +#define OXU_HOSTIFCONFIG 0x04 +#define OXU_SOFTRESET 0x08 + #define OXU_SRESET (1 << 0) + +#define OXU_PIOBURSTREADCTRL 0x0C + +#define OXU_CHIPIRQSTATUS 0x10 +#define OXU_CHIPIRQEN_SET 0x14 +#define OXU_CHIPIRQEN_CLR 0x18 + #define OXU_USBSPHLPWUI 0x00000080 + #define OXU_USBOTGLPWUI 0x00000040 + #define OXU_USBSPHI 0x00000002 + #define OXU_USBOTGI 0x00000001 + +#define OXU_CLKCTRL_SET 0x1C + #define OXU_SYSCLKEN 0x00000008 + #define OXU_USBSPHCLKEN 0x00000002 + #define OXU_USBOTGCLKEN 0x00000001 + +#define OXU_ASO 0x68 + #define OXU_SPHPOEN 0x00000100 + #define OXU_OVRCCURPUPDEN 0x00000800 + #define OXU_ASO_OP (1 << 10) + #define OXU_COMPARATOR 0x000004000 + +#define OXU_USBMODE 0x1A8 + #define OXU_VBPS 0x00000020 + #define OXU_ES_LITTLE 0x00000000 + #define OXU_CM_HOST_ONLY 0x00000003 + +/* + * Proper EHCI structs & defines + */ + +/* Magic numbers that can affect system performance */ +#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ +#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ +#define EHCI_TUNE_RL_TT 0 +#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ +#define EHCI_TUNE_MULT_TT 1 +#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ + +struct oxu_hcd; + +/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ + +/* Section 2.2 Host Controller Capability Registers */ +struct ehci_caps { + /* these fields are specified as 8 and 16 bit registers, + * but some hosts can't perform 8 or 16 bit PCI accesses. + */ + u32 hc_capbase; +#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ +#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ + u32 hcs_params; /* HCSPARAMS - offset 0x4 */ +#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ +#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ +#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ +#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ +#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ +#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ +#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ + + u32 hcc_params; /* HCCPARAMS - offset 0x8 */ +#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ +#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ +#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ +#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ +#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ +#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ + u8 portroute[8]; /* nibbles for routing - offset 0xC */ +} __packed; + + +/* Section 2.3 Host Controller Operational Registers */ +struct ehci_regs { + /* USBCMD: offset 0x00 */ + u32 command; +/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ +#define CMD_PARK (1<<11) /* enable "park" on async qh */ +#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ +#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ +#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ +#define CMD_ASE (1<<5) /* async schedule enable */ +#define CMD_PSE (1<<4) /* periodic schedule enable */ +/* 3:2 is periodic frame list size */ +#define CMD_RESET (1<<1) /* reset HC not bus */ +#define CMD_RUN (1<<0) /* start/stop HC */ + + /* USBSTS: offset 0x04 */ + u32 status; +#define STS_ASS (1<<15) /* Async Schedule Status */ +#define STS_PSS (1<<14) /* Periodic Schedule Status */ +#define STS_RECL (1<<13) /* Reclamation */ +#define STS_HALT (1<<12) /* Not running (any reason) */ +/* some bits reserved */ + /* these STS_* flags are also intr_enable bits (USBINTR) */ +#define STS_IAA (1<<5) /* Interrupted on async advance */ +#define STS_FATAL (1<<4) /* such as some PCI access errors */ +#define STS_FLR (1<<3) /* frame list rolled over */ +#define STS_PCD (1<<2) /* port change detect */ +#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ +#define STS_INT (1<<0) /* "normal" completion (short, ...) */ + +#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) + + /* USBINTR: offset 0x08 */ + u32 intr_enable; + + /* FRINDEX: offset 0x0C */ + u32 frame_index; /* current microframe number */ + /* CTRLDSSEGMENT: offset 0x10 */ + u32 segment; /* address bits 63:32 if needed */ + /* PERIODICLISTBASE: offset 0x14 */ + u32 frame_list; /* points to periodic list */ + /* ASYNCLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + + u32 reserved[9]; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ + + /* PORTSC: offset 0x44 */ + u32 port_status[0]; /* up to N_PORTS */ +/* 31:23 reserved */ +#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ +#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ +#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ +/* 19:16 for port testing */ +#define PORT_LED_OFF (0<<14) +#define PORT_LED_AMBER (1<<14) +#define PORT_LED_GREEN (2<<14) +#define PORT_LED_MASK (3<<14) +#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ +#define PORT_POWER (1<<12) /* true: has power (see PPC) */ +#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ +/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ +/* 9 reserved */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_OCC (1<<5) /* over current change */ +#define PORT_OC (1<<4) /* over current active */ +#define PORT_PEC (1<<3) /* port enable change */ +#define PORT_PE (1<<2) /* port enable */ +#define PORT_CSC (1<<1) /* connect status change */ +#define PORT_CONNECT (1<<0) /* device connected */ +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) +} __packed; + +/* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) + */ +struct ehci_dbg_port { + u32 control; +#define DBGP_OWNER (1<<30) +#define DBGP_ENABLED (1<<28) +#define DBGP_DONE (1<<16) +#define DBGP_INUSE (1<<10) +#define DBGP_ERRCODE(x) (((x)>>7)&0x07) +# define DBGP_ERR_BAD 1 +# define DBGP_ERR_SIGNAL 2 +#define DBGP_ERROR (1<<6) +#define DBGP_GO (1<<5) +#define DBGP_OUT (1<<4) +#define DBGP_LEN(x) (((x)>>0)&0x0f) + u32 pids; +#define DBGP_PID_GET(x) (((x)>>16)&0xff) +#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) + u32 data03; + u32 data47; + u32 address; +#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) +} __packed; + +#define QTD_NEXT(dma) cpu_to_le32((u32)dma) + +/* + * EHCI Specification 0.95 Section 3.5 + * QTD: describe data transfer components (buffer, direction, ...) + * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". + * + * These are associated only with "QH" (Queue Head) structures, + * used with control, bulk, and interrupt transfers. + */ +struct ehci_qtd { + /* first part defined by EHCI spec */ + __le32 hw_next; /* see EHCI 3.5.1 */ + __le32 hw_alt_next; /* see EHCI 3.5.2 */ + __le32 hw_token; /* see EHCI 3.5.3 */ +#define QTD_TOGGLE (1 << 31) /* data toggle */ +#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define QTD_IOC (1 << 15) /* interrupt on complete */ +#define QTD_CERR(tok) (((tok)>>10) & 0x3) +#define QTD_PID(tok) (((tok)>>8) & 0x3) +#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define QTD_STS_HALT (1 << 6) /* halted on error */ +#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ +#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ +#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define QTD_STS_STS (1 << 1) /* split transaction state */ +#define QTD_STS_PING (1 << 0) /* issue PING? */ + __le32 hw_buf[5]; /* see EHCI 3.5.4 */ + __le32 hw_buf_hi[5]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t qtd_dma; /* qtd address */ + struct list_head qtd_list; /* sw qtd list */ + struct urb *urb; /* qtd's urb */ + size_t length; /* length of buffer */ + + u32 qtd_buffer_len; + void *buffer; + dma_addr_t buffer_dma; + void *transfer_buffer; + void *transfer_dma; +} __aligned(32); + +/* mask NakCnt+T in qh->hw_alt_next */ +#define QTD_MASK cpu_to_le32 (~0x1f) + +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) + +/* Type tag from {qh, itd, sitd, fstn}->hw_next */ +#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) + +/* values for that type tag */ +#define Q_TYPE_QH cpu_to_le32 (1 << 1) + +/* next async queue entry, or pointer to interrupt/periodic QH */ +#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) + +/* for periodic/async schedules and qtd lists, mark end of list */ +#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ + +/* + * Entries in periodic shadow table are pointers to one of four kinds + * of data structure. That's dictated by the hardware; a type tag is + * encoded in the low bits of the hardware's periodic schedule. Use + * Q_NEXT_TYPE to get the tag. + * + * For entries in the async schedule, the type tag always says "qh". + */ +union ehci_shadow { + struct ehci_qh *qh; /* Q_TYPE_QH */ + __le32 *hw_next; /* (all types) */ + void *ptr; +}; + +/* + * EHCI Specification 0.95 Section 3.6 + * QH: describes control/bulk/interrupt endpoints + * See Fig 3-7 "Queue Head Structure Layout". + * + * These appear in both the async and (for interrupt) periodic schedules. + */ + +struct ehci_qh { + /* first part defined by EHCI spec */ + __le32 hw_next; /* see EHCI 3.6.1 */ + __le32 hw_info1; /* see EHCI 3.6.2 */ +#define QH_HEAD 0x00008000 + __le32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 + __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ + + /* qtd overlay (hardware parts of a struct ehci_qtd) */ + __le32 hw_qtd_next; + __le32 hw_alt_next; + __le32 hw_token; + __le32 hw_buf[5]; + __le32 hw_buf_hi[5]; + + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union ehci_shadow qh_next; /* ptr to qh; or periodic */ + struct list_head qtd_list; /* sw qtd list */ + struct ehci_qtd *dummy; + struct ehci_qh *reclaim; /* next to reclaim */ + + struct oxu_hcd *oxu; + struct kref kref; + unsigned int stamp; + + u8 qh_state; +#define QH_STATE_LINKED 1 /* HC sees this */ +#define QH_STATE_UNLINK 2 /* HC may still see this */ +#define QH_STATE_IDLE 3 /* HC doesn't see this */ +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ +#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + + /* periodic schedule info */ + u8 usecs; /* intr bandwidth */ + u8 gap_uf; /* uframes split/csplit gap */ + u8 c_usecs; /* ... split completion bw */ + u16 tt_usecs; /* tt downstream bandwidth */ + unsigned short period; /* polling interval */ + unsigned short start; /* where polling starts */ +#define NO_FRAME ((unsigned short)~0) /* pick new start */ + struct usb_device *dev; /* access to TT */ +} __aligned(32); + +/* + * Proper OXU210HP structs + */ + +#define OXU_OTG_CORE_OFFSET 0x00400 +#define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) +#define OXU_SPH_CORE_OFFSET 0x00800 +#define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) + +#define OXU_OTG_MEM 0xE000 +#define OXU_SPH_MEM 0x16000 + +/* Only how many elements & element structure are specifies here. */ +/* 2 host controllers are enabled - total size <= 28 kbytes */ +#define DEFAULT_I_TDPS 1024 +#define QHEAD_NUM 16 +#define QTD_NUM 32 +#define SITD_NUM 8 +#define MURB_NUM 8 + +#define BUFFER_NUM 8 +#define BUFFER_SIZE 512 + +struct oxu_info { + struct usb_hcd *hcd[2]; +}; + +struct oxu_buf { + u8 buffer[BUFFER_SIZE]; +} __aligned(BUFFER_SIZE); + +struct oxu_onchip_mem { + struct oxu_buf db_pool[BUFFER_NUM]; + + u32 frame_list[DEFAULT_I_TDPS]; + struct ehci_qh qh_pool[QHEAD_NUM]; + struct ehci_qtd qtd_pool[QTD_NUM]; +} __aligned(4 << 10); + +#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ + +struct oxu_murb { + struct urb urb; + struct urb *main; + u8 last; +}; + +struct oxu_hcd { /* one per controller */ + unsigned int is_otg:1; + + u8 qh_used[QHEAD_NUM]; + u8 qtd_used[QTD_NUM]; + u8 db_used[BUFFER_NUM]; + u8 murb_used[MURB_NUM]; + + struct oxu_onchip_mem __iomem *mem; + spinlock_t mem_lock; + + struct timer_list urb_timer; + + struct ehci_caps __iomem *caps; + struct ehci_regs __iomem *regs; + + u32 hcs_params; /* cached register copy */ + spinlock_t lock; + + /* async schedule support */ + struct ehci_qh *async; + struct ehci_qh *reclaim; + unsigned int reclaim_ready:1; + unsigned int scanning:1; + + /* periodic schedule support */ + unsigned int periodic_size; + __le32 *periodic; /* hw periodic table */ + dma_addr_t periodic_dma; + unsigned int i_thresh; /* uframes HC might cache */ + + union ehci_shadow *pshadow; /* mirror hw periodic table */ + int next_uframe; /* scan periodic, start here */ + unsigned int periodic_sched; /* periodic activity count */ + + /* per root hub port */ + unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; + /* bit vectors (one bit per port) */ + unsigned long bus_suspended; /* which ports were + * already suspended at the + * start of a bus suspend + */ + unsigned long companion_ports;/* which ports are dedicated + * to the companion controller + */ + + struct timer_list watchdog; + unsigned long actions; + unsigned int stamp; + unsigned long next_statechange; + u32 command; + + /* SILICON QUIRKS */ + struct list_head urb_list; /* this is the head to urb + * queue that didn't get enough + * resources + */ + struct oxu_murb *murb_pool; /* murb per split big urb */ + unsigned int urb_len; + + u8 sbrn; /* packed release number */ +}; + +#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ +#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ +#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ + +enum ehci_timer_action { + TIMER_IO_WATCHDOG, + TIMER_IAA_WATCHDOG, + TIMER_ASYNC_SHRINK, + TIMER_ASYNC_OFF, +}; + /* * Main defines */ diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h deleted file mode 100644 index 67ebea4993b6..000000000000 --- a/drivers/usb/host/oxu210hp.h +++ /dev/null @@ -1,446 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Host interface registers - */ - -#define OXU_DEVICEID 0x00 - #define OXU_REV_MASK 0xffff0000 - #define OXU_REV_SHIFT 16 - #define OXU_REV_2100 0x2100 - #define OXU_BO_SHIFT 8 - #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) - #define OXU_MAJ_REV_SHIFT 4 - #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) - #define OXU_MIN_REV_SHIFT 0 - #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) -#define OXU_HOSTIFCONFIG 0x04 -#define OXU_SOFTRESET 0x08 - #define OXU_SRESET (1 << 0) - -#define OXU_PIOBURSTREADCTRL 0x0C - -#define OXU_CHIPIRQSTATUS 0x10 -#define OXU_CHIPIRQEN_SET 0x14 -#define OXU_CHIPIRQEN_CLR 0x18 - #define OXU_USBSPHLPWUI 0x00000080 - #define OXU_USBOTGLPWUI 0x00000040 - #define OXU_USBSPHI 0x00000002 - #define OXU_USBOTGI 0x00000001 - -#define OXU_CLKCTRL_SET 0x1C - #define OXU_SYSCLKEN 0x00000008 - #define OXU_USBSPHCLKEN 0x00000002 - #define OXU_USBOTGCLKEN 0x00000001 - -#define OXU_ASO 0x68 - #define OXU_SPHPOEN 0x00000100 - #define OXU_OVRCCURPUPDEN 0x00000800 - #define OXU_ASO_OP (1 << 10) - #define OXU_COMPARATOR 0x000004000 - -#define OXU_USBMODE 0x1A8 - #define OXU_VBPS 0x00000020 - #define OXU_ES_LITTLE 0x00000000 - #define OXU_CM_HOST_ONLY 0x00000003 - -/* - * Proper EHCI structs & defines - */ - -/* Magic numbers that can affect system performance */ -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 -#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ - -struct oxu_hcd; - -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - */ - u32 hc_capbase; -#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute[8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - /* USBCMD: offset 0x00 */ - u32 command; -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - -#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved[9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status[0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -} __attribute__ ((packed)); - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) -} __attribute__ ((packed)); - - -#define QTD_NEXT(dma) cpu_to_le32((u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -struct ehci_qtd { - /* first part defined by EHCI spec */ - __le32 hw_next; /* see EHCI 3.5.1 */ - __le32 hw_alt_next; /* see EHCI 3.5.2 */ - __le32 hw_token; /* see EHCI 3.5.3 */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - __le32 hw_buf[5]; /* see EHCI 3.5.4 */ - __le32 hw_buf_hi[5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct list_head qtd_list; /* sw qtd list */ - struct urb *urb; /* qtd's urb */ - size_t length; /* length of buffer */ - - u32 qtd_buffer_len; - void *buffer; - dma_addr_t buffer_dma; - void *transfer_buffer; - void *transfer_dma; -} __attribute__ ((aligned(32))); - -/* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK cpu_to_le32 (~0x1f) - -#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) - -/* Type tag from {qh, itd, sitd, fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) - -/* values for that type tag */ -#define Q_TYPE_QH cpu_to_le32 (1 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union ehci_shadow { - struct ehci_qh *qh; /* Q_TYPE_QH */ - __le32 *hw_next; /* (all types) */ - void *ptr; -}; - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -struct ehci_qh { - /* first part defined by EHCI spec */ - __le32 hw_next; /* see EHCI 3.6.1 */ - __le32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_HEAD 0x00008000 - __le32 hw_info2; /* see EHCI 3.6.2 */ -#define QH_SMASK 0x000000ff -#define QH_CMASK 0x0000ff00 -#define QH_HUBADDR 0x007f0000 -#define QH_HUBPORT 0x3f800000 -#define QH_MULT 0xc0000000 - __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - __le32 hw_qtd_next; - __le32 hw_alt_next; - __le32 hw_token; - __le32 hw_buf[5]; - __le32 hw_buf_hi[5]; - - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - union ehci_shadow qh_next; /* ptr to qh; or periodic */ - struct list_head qtd_list; /* sw qtd list */ - struct ehci_qtd *dummy; - struct ehci_qh *reclaim; /* next to reclaim */ - - struct oxu_hcd *oxu; - struct kref kref; - unsigned stamp; - - u8 qh_state; -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ -#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ -#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ - - /* periodic schedule info */ - u8 usecs; /* intr bandwidth */ - u8 gap_uf; /* uframes split/csplit gap */ - u8 c_usecs; /* ... split completion bw */ - u16 tt_usecs; /* tt downstream bandwidth */ - unsigned short period; /* polling interval */ - unsigned short start; /* where polling starts */ -#define NO_FRAME ((unsigned short)~0) /* pick new start */ - struct usb_device *dev; /* access to TT */ -} __attribute__ ((aligned(32))); - -/* - * Proper OXU210HP structs - */ - -#define OXU_OTG_CORE_OFFSET 0x00400 -#define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) -#define OXU_SPH_CORE_OFFSET 0x00800 -#define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) - -#define OXU_OTG_MEM 0xE000 -#define OXU_SPH_MEM 0x16000 - -/* Only how many elements & element structure are specifies here. */ -/* 2 host controllers are enabled - total size <= 28 kbytes */ -#define DEFAULT_I_TDPS 1024 -#define QHEAD_NUM 16 -#define QTD_NUM 32 -#define SITD_NUM 8 -#define MURB_NUM 8 - -#define BUFFER_NUM 8 -#define BUFFER_SIZE 512 - -struct oxu_info { - struct usb_hcd *hcd[2]; -}; - -struct oxu_buf { - u8 buffer[BUFFER_SIZE]; -} __attribute__ ((aligned(BUFFER_SIZE))); - -struct oxu_onchip_mem { - struct oxu_buf db_pool[BUFFER_NUM]; - - u32 frame_list[DEFAULT_I_TDPS]; - struct ehci_qh qh_pool[QHEAD_NUM]; - struct ehci_qtd qtd_pool[QTD_NUM]; -} __attribute__ ((aligned(4 << 10))); - -#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ - -struct oxu_murb { - struct urb urb; - struct urb *main; - u8 last; -}; - -struct oxu_hcd { /* one per controller */ - unsigned int is_otg:1; - - u8 qh_used[QHEAD_NUM]; - u8 qtd_used[QTD_NUM]; - u8 db_used[BUFFER_NUM]; - u8 murb_used[MURB_NUM]; - - struct oxu_onchip_mem __iomem *mem; - spinlock_t mem_lock; - - struct timer_list urb_timer; - - struct ehci_caps __iomem *caps; - struct ehci_regs __iomem *regs; - - __u32 hcs_params; /* cached register copy */ - spinlock_t lock; - - /* async schedule support */ - struct ehci_qh *async; - struct ehci_qh *reclaim; - unsigned reclaim_ready:1; - unsigned scanning:1; - - /* periodic schedule support */ - unsigned periodic_size; - __le32 *periodic; /* hw periodic table */ - dma_addr_t periodic_dma; - unsigned i_thresh; /* uframes HC might cache */ - - union ehci_shadow *pshadow; /* mirror hw periodic table */ - int next_uframe; /* scan periodic, start here */ - unsigned periodic_sched; /* periodic activity count */ - - /* per root hub port */ - unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; - /* bit vectors (one bit per port) */ - unsigned long bus_suspended; /* which ports were - * already suspended at the - * start of a bus suspend - */ - unsigned long companion_ports;/* which ports are dedicated - * to the companion controller - */ - - struct timer_list watchdog; - unsigned long actions; - unsigned stamp; - unsigned long next_statechange; - u32 command; - - /* SILICON QUIRKS */ - struct list_head urb_list; /* this is the head to urb - * queue that didn't get enough - * resources - */ - struct oxu_murb *murb_pool; /* murb per split big urb */ - unsigned urb_len; - - u8 sbrn; /* packed release number */ -}; - -#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ -#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ -#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ -#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ - -enum ehci_timer_action { - TIMER_IO_WATCHDOG, - TIMER_IAA_WATCHDOG, - TIMER_ASYNC_SHRINK, - TIMER_ASYNC_OFF, -}; -- GitLab From 3114bc89c0217254d3df10a42eab6b6ca00f547c Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 15 Jul 2019 11:20:10 +0800 Subject: [PATCH 0554/7155] usb: host: Remove call to memset after dma_alloc_coherent In commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*"), dma_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Link: https://lore.kernel.org/r/20190715032010.7258-1-huangfq.daxian@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbgcap.c | 1 - drivers/usb/host/xhci-mem.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 52e32644a4b2..93e2cca5262d 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -22,7 +22,6 @@ dbc_dma_alloc_coherent(struct xhci_hcd *xhci, size_t size, vaddr = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev, size, dma_handle, flags); - memset(vaddr, 0, size); return vaddr; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index cf5e17962179..e16eda6e2b8b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2399,7 +2399,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) flags); if (!xhci->dcbaa) goto fail; - memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); xhci->dcbaa->dma = dma; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Device context base array address = 0x%llx (DMA), %p (virt)", -- GitLab From 6269e4c76eacabaea0d0099200ae1a455768d208 Mon Sep 17 00:00:00 2001 From: Ruslan Bilovol Date: Sun, 7 Jul 2019 15:17:19 +0300 Subject: [PATCH 0555/7155] usb: host: xhci-hub: fix extra endianness conversion Don't do extra cpu_to_le32 conversion for put_unaligned_le32 because it is already implemented in this function. Fixes sparse error: xhci-hub.c:1152:44: warning: incorrect type in argument 1 (different base types) xhci-hub.c:1152:44: expected unsigned int [usertype] val xhci-hub.c:1152:44: got restricted __le32 [usertype] Fixes: 395f540 "xhci: support new USB 3.1 hub request to get extended port status" Cc: Mathias Nyman Signed-off-by: Ruslan Bilovol Link: https://lore.kernel.org/r/1562501839-26522-1-git-send-email-ruslan.bilovol@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 3abe70ff1b1e..b7d23c438756 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1149,7 +1149,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } port_li = readl(ports[wIndex]->addr + PORTLI); status = xhci_get_ext_port_status(temp, port_li); - put_unaligned_le32(cpu_to_le32(status), &buf[4]); + put_unaligned_le32(status, &buf[4]); } break; case SetPortFeature: -- GitLab From ed7fe551575cd6dbbe31282a0869682aeea2627c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 4 Jul 2019 16:03:41 +0100 Subject: [PATCH 0556/7155] usb: chipidea: udc: remove redundant assignment to variable retval The variable retval is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Also remove a blank line. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190704150341.759-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 6a5ee8e6da10..053432d79bf7 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1746,12 +1746,11 @@ static int ci_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); - int retval = -ENOMEM; + int retval; if (driver->disconnect == NULL) return -EINVAL; - ci->ep0out->ep.desc = &ctrl_endpt_out_desc; retval = usb_ep_enable(&ci->ep0out->ep); if (retval) -- GitLab From 34d0545978b65f0a4ced613eb99cd75b2a6132e9 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 12 Jun 2019 13:55:17 +0800 Subject: [PATCH 0557/7155] dt-bindings: usb: mtu3: fix typo of DMA clock name Fix typo of dma_ck Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/5e06482a0be15476c7b5825f155accf98275afa8.1560246390.git.chunfeng.yun@mediatek.com Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..5d740e9d4525 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -16,7 +16,7 @@ Required properties: entry in clock-names - clock-names : must contain "sys_ck" for clock of controller, the following clocks are optional: - "ref_ck", "mcu_ck" and "dam_ck"; + "ref_ck", "mcu_ck" and "dma_ck"; - phys : see usb-hcd.txt in the current directory - dr_mode : should be one of "host", "peripheral" or "otg", refer to usb/generic.txt -- GitLab From 2fa278e32b9f9489c85659c7da6fd1e76851ba9b Mon Sep 17 00:00:00 2001 From: Ludovic Barre Date: Thu, 27 Jun 2019 14:09:05 +0200 Subject: [PATCH 0558/7155] ARM: dts: stm32: activate dma for qspi on stm32mp157 This patch activates dma for qspi on stm32mp157. Signed-off-by: Ludovic Barre Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index 0c4e6ebc3529..58f3cd34f8aa 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -1244,6 +1244,9 @@ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; reg-names = "qspi", "qspi_mm"; interrupts = ; + dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>, + <&mdma1 22 0x10 0x100008 0x0 0x0>; + dma-names = "tx", "rx"; clocks = <&rcc QSPI_K>; resets = <&rcc QSPI_R>; status = "disabled"; -- GitLab From aafa0ae33586a2e3efcd76cfe5acaf292e95b9e1 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Fri, 21 Jun 2019 16:49:47 +0200 Subject: [PATCH 0559/7155] ARM: dts: stm32: add FMC2 NAND controller support on stm32mp157c This patch adds FMC2 NAND controller support used by stm32mp157c SOC. Signed-off-by: Christophe Kerello Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index 58f3cd34f8aa..247334a6c144 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -1239,6 +1239,25 @@ dma-requests = <48>; }; + fmc: nand-controller@58002000 { + compatible = "st,stm32mp15-fmc2"; + reg = <0x58002000 0x1000>, + <0x80000000 0x1000>, + <0x88010000 0x1000>, + <0x88020000 0x1000>, + <0x81000000 0x1000>, + <0x89010000 0x1000>, + <0x89020000 0x1000>; + interrupts = ; + dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>, + <&mdma1 20 0x10 0x12000a08 0x0 0x0>, + <&mdma1 21 0x10 0x12000a0a 0x0 0x0>; + dma-names = "tx", "rx", "ecc"; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + }; + qspi: spi@58003000 { compatible = "st,stm32f469-qspi"; reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; -- GitLab From 52ded6f9ce84f15275a9b583bee55bd0361f9911 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Fri, 21 Jun 2019 16:49:48 +0200 Subject: [PATCH 0560/7155] ARM: dts: stm32: add FMC2 NAND controller pins muxing on stm32mp157c-ev1 This patch adds FMC2 NAND controller pins muxing used on stm32mp157c-ev1. Signed-off-by: Christophe Kerello Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi index df6470133574..c4f2b23f307f 100644 --- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi @@ -276,6 +276,50 @@ }; }; + fmc_pins_a: fmc-0 { + pins1 { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + ; /* FMC_NE2_FMC_NCE */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* FMC_NWAIT */ + bias-pull-up; + }; + }; + + fmc_sleep_pins_a: fmc-sleep-0 { + pins { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + , /* FMC_NWAIT */ + ; /* FMC_NE2_FMC_NCE */ + }; + }; + i2c1_pins_a: i2c1-0 { pins { pinmux = , /* I2C1_SCL */ -- GitLab From 978946e428409bc1530fd80df5e63ffae9508273 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Fri, 21 Jun 2019 16:49:49 +0200 Subject: [PATCH 0561/7155] ARM: dts: stm32: enable FMC2 NAND controller on stm32mp157c-ev1 This patch enables FMC2 NAND controller used on stm32mp157c-ev1. Signed-off-by: Christophe Kerello Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ev1.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts index feb8f7727270..9ab25dabcff7 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -157,6 +157,22 @@ }; }; +&fmc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&fmc_pins_a>; + pinctrl-1 = <&fmc_sleep_pins_a>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; -- GitLab From 78b3e86b5a75b6fb3122b11d507023f1b194f663 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 23 Jun 2019 13:07:26 -0400 Subject: [PATCH 0562/7155] media: dt: bindings: tegra-vde: Document new optional IOMMU property All NVIDIA Tegra SoC generations provide IOMMU support for the video decoder engine. Document new optional device-tree property that connects VDE with the IOMMU provider. Signed-off-by: Dmitry Osipenko Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt index 7302e949e662..602169b8aa19 100644 --- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt +++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt @@ -35,6 +35,7 @@ Optional properties: - resets : Must contain an entry for each entry in reset-names. - reset-names : Must include the following entries: - mc +- iommus: Must contain phandle to the IOMMU device node. Example: @@ -59,4 +60,5 @@ video-codec@6001a000 { clocks = <&tegra_car TEGRA20_CLK_VDE>; reset-names = "vde", "mc"; resets = <&tegra_car 61>, <&mc TEGRA20_MC_RESET_VDE>; + iommus = <&mc TEGRA_SWGROUP_VDE>; }; -- GitLab From 0bd465765f8d1300040de627f0a0971a8849d654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 2 Jul 2019 13:42:58 -0400 Subject: [PATCH 0563/7155] media: rcar-vin: Clean up correct notifier in error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parallel input initialization error path cleans up the wrong async notifier, fix this by cleaning up the correct notifier. Fixes: 9863bc8695bc36e3 ("media: rcar-vin: Cleanup notifier in error path") Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Tested-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 64f9cf790445..a6efe1a8099a 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -633,7 +633,7 @@ static int rvin_parallel_init(struct rvin_dev *vin) ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier); if (ret < 0) { vin_err(vin, "Notifier registration failed\n"); - v4l2_async_notifier_cleanup(&vin->group->notifier); + v4l2_async_notifier_cleanup(&vin->notifier); return ret; } -- GitLab From 21a816e7ee5d4b217da14374af1c91eb725e665c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Fri, 5 Jul 2019 00:43:50 -0400 Subject: [PATCH 0564/7155] media: rcar-vin: Centralize black listing of pixel formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of scattering black listing of pixel formats who are not supported on particular platforms move it to a central location. Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 2 +- drivers/media/platform/rcar-vin/rcar-v4l2.c | 23 +++++++++++---------- drivers/media/platform/rcar-vin/rcar-vin.h | 4 +++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 91ab064404a1..372d6b106b99 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -794,7 +794,7 @@ static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr) int offsetx, offsety; dma_addr_t offset; - fmt = rvin_format_from_pixel(vin->format.pixelformat); + fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); /* * There is no HW support for composition do the beast we can diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 0936bcd98df1..04d798d8070f 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -56,10 +56,14 @@ static const struct rvin_video_format rvin_formats[] = { }, }; -const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat) +const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin, + u32 pixelformat) { int i; + if (vin->info->model == RCAR_M1 && pixelformat == V4L2_PIX_FMT_XBGR32) + return NULL; + for (i = 0; i < ARRAY_SIZE(rvin_formats); i++) if (rvin_formats[i].fourcc == pixelformat) return rvin_formats + i; @@ -67,11 +71,12 @@ const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat) return NULL; } -static u32 rvin_format_bytesperline(struct v4l2_pix_format *pix) +static u32 rvin_format_bytesperline(struct rvin_dev *vin, + struct v4l2_pix_format *pix) { const struct rvin_video_format *fmt; - fmt = rvin_format_from_pixel(pix->pixelformat); + fmt = rvin_format_from_pixel(vin, pix->pixelformat); if (WARN_ON(!fmt)) return -EINVAL; @@ -91,9 +96,7 @@ static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix) { u32 walign; - if (!rvin_format_from_pixel(pix->pixelformat) || - (vin->info->model == RCAR_M1 && - pix->pixelformat == V4L2_PIX_FMT_XBGR32)) + if (!rvin_format_from_pixel(vin, pix->pixelformat)) pix->pixelformat = RVIN_DEFAULT_FORMAT; switch (pix->field) { @@ -125,7 +128,7 @@ static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix) v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign, &pix->height, 4, vin->info->max_height, 2, 0); - pix->bytesperline = rvin_format_bytesperline(pix); + pix->bytesperline = rvin_format_bytesperline(vin, pix); pix->sizeimage = rvin_format_sizeimage(pix); vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n", @@ -181,9 +184,7 @@ static int rvin_try_format(struct rvin_dev *vin, u32 which, if (pad_cfg == NULL) return -ENOMEM; - if (!rvin_format_from_pixel(pix->pixelformat) || - (vin->info->model == RCAR_M1 && - pix->pixelformat == V4L2_PIX_FMT_XBGR32)) + if (!rvin_format_from_pixel(vin, pix->pixelformat)) pix->pixelformat = RVIN_DEFAULT_FORMAT; v4l2_fill_mbus_format(&format.format, pix, vin->mbus_code); @@ -384,7 +385,7 @@ static int rvin_s_selection(struct file *file, void *fh, while ((r.top * vin->format.bytesperline) & HW_BUFFER_MASK) r.top--; - fmt = rvin_format_from_pixel(vin->format.pixelformat); + fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); while ((r.left * fmt->bpp) & HW_BUFFER_MASK) r.left--; diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 0b13b34d03e3..ac1a6fe90015 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -260,7 +260,9 @@ void rvin_dma_unregister(struct rvin_dev *vin); int rvin_v4l2_register(struct rvin_dev *vin); void rvin_v4l2_unregister(struct rvin_dev *vin); -const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat); +const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin, + u32 pixelformat); + /* Cropping, composing and scaling */ void rvin_crop_scale_comp(struct rvin_dev *vin); -- GitLab From 9e037bdf743cc081858423ad4123824e846b2358 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 10 Jul 2019 01:04:24 -0400 Subject: [PATCH 0565/7155] media: staging: media: cedrus: Fix misuse of GENMASK macro Arguments are supposed to be ordered high then low. Signed-off-by: Joe Perches Acked-by: Paul Kocialkowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h index 3e9931416e45..ddd29788d685 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h @@ -110,7 +110,7 @@ #define VE_DEC_MPEG_MBADDR (VE_ENGINE_DEC_MPEG + 0x10) #define VE_DEC_MPEG_MBADDR_X(w) (((w) << 8) & GENMASK(15, 8)) -#define VE_DEC_MPEG_MBADDR_Y(h) (((h) << 0) & GENMASK(0, 7)) +#define VE_DEC_MPEG_MBADDR_Y(h) (((h) << 0) & GENMASK(7, 0)) #define VE_DEC_MPEG_CTRL (VE_ENGINE_DEC_MPEG + 0x14) -- GitLab From d4a6a9537bc32811486282206ecfb7c53754b74d Mon Sep 17 00:00:00 2001 From: Luke Nowakowski-Krijger Date: Wed, 17 Jul 2019 10:19:46 -0400 Subject: [PATCH 0566/7155] media: hdpvr: Add device num check and handling Add hdpvr device num check and error handling We need to increment the device count atomically before we checkout a device to make sure that we do not reach the max count, otherwise we get out-of-bounds errors as reported by syzbot. Reported-and-tested-by: syzbot+aac8d0d7205f112045d2@syzkaller.appspotmail.com Signed-off-by: Luke Nowakowski-Krijger Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 9b9d894d29bc..a0905c81d2cb 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -271,6 +271,7 @@ static int hdpvr_probe(struct usb_interface *interface, #endif size_t buffer_size; int i; + int dev_num; int retval = -ENOMEM; /* allocate memory for our device state and initialize it */ @@ -368,8 +369,17 @@ static int hdpvr_probe(struct usb_interface *interface, } #endif + dev_num = atomic_inc_return(&dev_nr); + if (dev_num >= HDPVR_MAX) { + v4l2_err(&dev->v4l2_dev, + "max device number reached, device register failed\n"); + atomic_dec(&dev_nr); + retval = -ENODEV; + goto reg_fail; + } + retval = hdpvr_register_videodev(dev, &interface->dev, - video_nr[atomic_inc_return(&dev_nr)]); + video_nr[dev_num]); if (retval < 0) { v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); goto reg_fail; -- GitLab From 156a599b0716ab3ee3869ff26119e3b5d46d91c8 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 5 Jul 2019 18:05:19 +0300 Subject: [PATCH 0567/7155] dmaengine: tegra-apb: Support per-burst residue granularity Tegra's APB DMA engine updates words counter after each transferred burst of data, hence it can report transfer's residual with more fidelity which may be required in cases like audio playback. In particular this fixes audio stuttering during playback in a chromium web browser. The patch is based on the original work that was made by Ben Dooks and a patch from downstream kernel. It was tested on Tegra20 and Tegra30 devices. Link: https://lore.kernel.org/lkml/20190424162348.23692-1-ben.dooks@codethink.co.uk/ Link: https://nv-tegra.nvidia.com/gitweb/?p=linux-4.4.git;a=commit;h=c7bba40c6846fbf3eaad35c4472dcc7d8bbc02e5 Inspired-by: Ben Dooks Reviewed-by: Jon Hunter Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20190705150519.18171-1-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 75 +++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 79e9593815f1..3a45079d11ec 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -152,6 +152,7 @@ struct tegra_dma_sg_req { bool last_sg; struct list_head node; struct tegra_dma_desc *dma_desc; + unsigned int words_xferred; }; /* @@ -496,6 +497,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); nsg_req->configured = true; + nsg_req->words_xferred = 0; tegra_dma_resume(tdc); } @@ -511,6 +513,7 @@ static void tdc_start_head_req(struct tegra_dma_channel *tdc) typeof(*sg_req), node); tegra_dma_start(tdc, sg_req); sg_req->configured = true; + sg_req->words_xferred = 0; tdc->busy = true; } @@ -638,6 +641,8 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, list_add_tail(&dma_desc->cb_node, &tdc->cb_desc); dma_desc->cb_count++; + sgreq->words_xferred = 0; + /* If not last req then put at end of pending list */ if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) { list_move_tail(&sgreq->node, &tdc->pending_sg_req); @@ -797,6 +802,65 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) return 0; } +static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *sg_req) +{ + unsigned long status, wcount = 0; + + if (!list_is_first(&sg_req->node, &tdc->pending_sg_req)) + return 0; + + if (tdc->tdma->chip_data->support_separate_wcount_reg) + wcount = tdc_read(tdc, TEGRA_APBDMA_CHAN_WORD_TRANSFER); + + status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); + + if (!tdc->tdma->chip_data->support_separate_wcount_reg) + wcount = status; + + if (status & TEGRA_APBDMA_STATUS_ISE_EOC) + return sg_req->req_len; + + wcount = get_current_xferred_count(tdc, sg_req, wcount); + + if (!wcount) { + /* + * If wcount wasn't ever polled for this SG before, then + * simply assume that transfer hasn't started yet. + * + * Otherwise it's the end of the transfer. + * + * The alternative would be to poll the status register + * until EOC bit is set or wcount goes UP. That's so + * because EOC bit is getting set only after the last + * burst's completion and counter is less than the actual + * transfer size by 4 bytes. The counter value wraps around + * in a cyclic mode before EOC is set(!), so we can't easily + * distinguish start of transfer from its end. + */ + if (sg_req->words_xferred) + wcount = sg_req->req_len - 4; + + } else if (wcount < sg_req->words_xferred) { + /* + * This case will never happen for a non-cyclic transfer. + * + * For a cyclic transfer, although it is possible for the + * next transfer to have already started (resetting the word + * count), this case should still not happen because we should + * have detected that the EOC bit is set and hence the transfer + * was completed. + */ + WARN_ON_ONCE(1); + + wcount = sg_req->req_len - 4; + } else { + sg_req->words_xferred = wcount; + } + + return wcount; +} + static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, dma_cookie_t cookie, struct dma_tx_state *txstate) { @@ -806,6 +870,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, enum dma_status ret; unsigned long flags; unsigned int residual; + unsigned int bytes = 0; ret = dma_cookie_status(dc, cookie, txstate); if (ret == DMA_COMPLETE) @@ -825,6 +890,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, list_for_each_entry(sg_req, &tdc->pending_sg_req, node) { dma_desc = sg_req->dma_desc; if (dma_desc->txd.cookie == cookie) { + bytes = tegra_dma_sg_bytes_xferred(tdc, sg_req); ret = dma_desc->dma_status; goto found; } @@ -836,7 +902,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, found: if (dma_desc && txstate) { residual = dma_desc->bytes_requested - - (dma_desc->bytes_transferred % + ((dma_desc->bytes_transferred + bytes) % dma_desc->bytes_requested); dma_set_residue(txstate, residual); } @@ -1441,12 +1507,7 @@ static int tegra_dma_probe(struct platform_device *pdev) BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES); tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - /* - * XXX The hardware appears to support - * DMA_RESIDUE_GRANULARITY_BURST-level reporting, but it's - * only used by this driver during tegra_dma_terminate_all() - */ - tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; tdma->dma_dev.device_config = tegra_dma_slave_config; tdma->dma_dev.device_terminate_all = tegra_dma_terminate_all; tdma->dma_dev.device_tx_status = tegra_dma_tx_status; -- GitLab From 173f6eacc8a89ae4b08b166735930e6c46951a81 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sat, 20 Jul 2019 07:47:07 -0400 Subject: [PATCH 0568/7155] media: v4l: ctrls: Add debug messages Currently, the v4l2 control code is a bit silent on errors. Add debug messages on (hopefully) most of the error paths. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/kapi/v4l2-dev.rst | 1 + drivers/media/platform/omap3isp/ispvideo.c | 4 +- drivers/media/v4l2-core/v4l2-ctrls.c | 126 ++++++++++++++++----- drivers/media/v4l2-core/v4l2-ioctl.c | 18 ++- drivers/media/v4l2-core/v4l2-subdev.c | 6 +- include/media/v4l2-ctrls.h | 9 +- include/media/v4l2-ioctl.h | 2 + 7 files changed, 127 insertions(+), 39 deletions(-) diff --git a/Documentation/media/kapi/v4l2-dev.rst b/Documentation/media/kapi/v4l2-dev.rst index b359f1804bbe..4c5a15c53dbf 100644 --- a/Documentation/media/kapi/v4l2-dev.rst +++ b/Documentation/media/kapi/v4l2-dev.rst @@ -288,6 +288,7 @@ Mask Description 0x08 Log the read and write file operations and the VIDIOC_QBUF and VIDIOC_DQBUF ioctls. 0x10 Log the poll file operation. +0x20 Log error and messages in the control operations. ===== ================================================================ Video device cleanup diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index b52c6fe825ac..ee183c35ff3b 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -1020,8 +1020,8 @@ static int isp_video_check_external_subdevs(struct isp_video *video, ctrls.count = 1; ctrls.controls = &ctrl; - - ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls); + ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &video->video, + NULL, &ctrls); if (ret < 0) { dev_warn(isp->dev, "no pixel rate control in subdev %s\n", pipe->external->name); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 13236c191796..76fa2db0e8fb 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -6,6 +6,8 @@ */ +#define pr_fmt(fmt) "v4l2-ctrls: " fmt + #include #include #include @@ -16,6 +18,12 @@ #include #include +#define dprintk(vdev, fmt, arg...) do { \ + if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \ + printk(KERN_DEBUG pr_fmt("%s: %s: " fmt), \ + __func__, video_device_node_name(vdev), ##arg); \ +} while (0) + #define has_op(master, op) \ (master->ops && master->ops->op) #define call_op(master, op) \ @@ -3260,6 +3268,7 @@ static int v4l2_ctrl_request_bind(struct media_request *req, static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs, struct v4l2_ctrl_helper *helpers, + struct video_device *vdev, bool get) { struct v4l2_ctrl_helper *h; @@ -3277,20 +3286,31 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, if (cs->which && cs->which != V4L2_CTRL_WHICH_DEF_VAL && cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && - V4L2_CTRL_ID2WHICH(id) != cs->which) + V4L2_CTRL_ID2WHICH(id) != cs->which) { + dprintk(vdev, + "invalid which 0x%x or control id 0x%x\n", + cs->which, id); return -EINVAL; + } /* Old-style private controls are not allowed for extended controls */ - if (id >= V4L2_CID_PRIVATE_BASE) + if (id >= V4L2_CID_PRIVATE_BASE) { + dprintk(vdev, + "old-style private controls not allowed\n"); return -EINVAL; + } ref = find_ref_lock(hdl, id); - if (ref == NULL) + if (ref == NULL) { + dprintk(vdev, "cannot find control id 0x%x\n", id); return -EINVAL; + } h->ref = ref; ctrl = ref->ctrl; - if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) + if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { + dprintk(vdev, "control id 0x%x is disabled\n", id); return -EINVAL; + } if (ctrl->cluster[0]->ncontrols > 1) have_clusters = true; @@ -3300,10 +3320,17 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, unsigned tot_size = ctrl->elems * ctrl->elem_size; if (c->size < tot_size) { + /* + * In the get case the application first + * queries to obtain the size of the control. + */ if (get) { c->size = tot_size; return -ENOSPC; } + dprintk(vdev, + "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n", + id, c->size, tot_size); return -EFAULT; } c->size = tot_size; @@ -3364,7 +3391,8 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) /* Get extended controls. Allocates the helpers array if needed. */ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, - struct v4l2_ext_controls *cs) + struct v4l2_ext_controls *cs, + struct video_device *vdev) { struct v4l2_ctrl_helper helper[4]; struct v4l2_ctrl_helper *helpers = helper; @@ -3390,7 +3418,7 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, return -ENOMEM; } - ret = prepare_ext_ctrls(hdl, cs, helpers, true); + ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true); cs->error_idx = cs->count; for (i = 0; !ret && i < cs->count; i++) @@ -3483,8 +3511,8 @@ v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl, return obj; } -int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev, - struct v4l2_ext_controls *cs) +int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, + struct media_device *mdev, struct v4l2_ext_controls *cs) { struct media_request_object *obj = NULL; struct media_request *req = NULL; @@ -3520,7 +3548,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev, req_obj); } - ret = v4l2_g_ext_ctrls_common(hdl, cs); + ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev); if (obj) { media_request_unlock_for_access(req); @@ -3663,7 +3691,9 @@ static int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master, /* Validate controls. */ static int validate_ctrls(struct v4l2_ext_controls *cs, - struct v4l2_ctrl_helper *helpers, bool set) + struct v4l2_ctrl_helper *helpers, + struct video_device *vdev, + bool set) { unsigned i; int ret = 0; @@ -3675,16 +3705,24 @@ static int validate_ctrls(struct v4l2_ext_controls *cs, cs->error_idx = i; - if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) + if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) { + dprintk(vdev, + "control id 0x%x is read-only\n", + ctrl->id); return -EACCES; + } /* This test is also done in try_set_control_cluster() which is called in atomic context, so that has the final say, but it makes sense to do an up-front check as well. Once an error occurs in try_set_control_cluster() some other controls may have been set already and we want to do a best-effort to avoid that. */ - if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) + if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) { + dprintk(vdev, + "control id 0x%x is grabbed, cannot set\n", + ctrl->id); return -EBUSY; + } /* * Skip validation for now if the payload needs to be copied * from userspace into kernelspace. We'll validate those later. @@ -3719,7 +3757,8 @@ static void update_from_auto_cluster(struct v4l2_ctrl *master) /* Try or try-and-set controls */ static int try_set_ext_ctrls_common(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, - struct v4l2_ext_controls *cs, bool set) + struct v4l2_ext_controls *cs, + struct video_device *vdev, bool set) { struct v4l2_ctrl_helper helper[4]; struct v4l2_ctrl_helper *helpers = helper; @@ -3729,13 +3768,19 @@ static int try_set_ext_ctrls_common(struct v4l2_fh *fh, cs->error_idx = cs->count; /* Default value cannot be changed */ - if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) + if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { + dprintk(vdev, "%s: cannot change default value\n", + video_device_node_name(vdev)); return -EINVAL; + } cs->which = V4L2_CTRL_ID2WHICH(cs->which); - if (hdl == NULL) + if (hdl == NULL) { + dprintk(vdev, "%s: invalid null control handler\n", + video_device_node_name(vdev)); return -EINVAL; + } if (cs->count == 0) return class_check(hdl, cs->which); @@ -3746,9 +3791,9 @@ static int try_set_ext_ctrls_common(struct v4l2_fh *fh, if (!helpers) return -ENOMEM; } - ret = prepare_ext_ctrls(hdl, cs, helpers, false); + ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false); if (!ret) - ret = validate_ctrls(cs, helpers, set); + ret = validate_ctrls(cs, helpers, vdev, set); if (ret && set) cs->error_idx = cs->count; for (i = 0; !ret && i < cs->count; i++) { @@ -3833,7 +3878,9 @@ static int try_set_ext_ctrls_common(struct v4l2_fh *fh, } static int try_set_ext_ctrls(struct v4l2_fh *fh, - struct v4l2_ctrl_handler *hdl, struct media_device *mdev, + struct v4l2_ctrl_handler *hdl, + struct video_device *vdev, + struct media_device *mdev, struct v4l2_ext_controls *cs, bool set) { struct media_request_object *obj = NULL; @@ -3841,21 +3888,39 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, int ret; if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) { - if (!mdev || cs->request_fd < 0) + if (!mdev) { + dprintk(vdev, "%s: missing media device\n", + video_device_node_name(vdev)); + return -EINVAL; + } + + if (cs->request_fd < 0) { + dprintk(vdev, "%s: invalid request fd %d\n", + video_device_node_name(vdev), cs->request_fd); return -EINVAL; + } req = media_request_get_by_fd(mdev, cs->request_fd); - if (IS_ERR(req)) + if (IS_ERR(req)) { + dprintk(vdev, "%s: cannot find request fd %d\n", + video_device_node_name(vdev), cs->request_fd); return PTR_ERR(req); + } ret = media_request_lock_for_update(req); if (ret) { + dprintk(vdev, "%s: cannot lock request fd %d\n", + video_device_node_name(vdev), cs->request_fd); media_request_put(req); return ret; } obj = v4l2_ctrls_find_req_obj(hdl, req, set); if (IS_ERR(obj)) { + dprintk(vdev, + "%s: cannot find request object for request fd %d\n", + video_device_node_name(vdev), + cs->request_fd); media_request_unlock_for_update(req); media_request_put(req); return PTR_ERR(obj); @@ -3864,7 +3929,11 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, req_obj); } - ret = try_set_ext_ctrls_common(fh, hdl, cs, set); + ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set); + if (ret) + dprintk(vdev, + "%s: try_set_ext_ctrls_common failed (%d)\n", + video_device_node_name(vdev), ret); if (obj) { media_request_unlock_for_update(req); @@ -3875,17 +3944,22 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, return ret; } -int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev, +int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, + struct video_device *vdev, + struct media_device *mdev, struct v4l2_ext_controls *cs) { - return try_set_ext_ctrls(NULL, hdl, mdev, cs, false); + return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false); } EXPORT_SYMBOL(v4l2_try_ext_ctrls); -int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, - struct media_device *mdev, struct v4l2_ext_controls *cs) +int v4l2_s_ext_ctrls(struct v4l2_fh *fh, + struct v4l2_ctrl_handler *hdl, + struct video_device *vdev, + struct media_device *mdev, + struct v4l2_ext_controls *cs) { - return try_set_ext_ctrls(fh, hdl, mdev, cs, true); + return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true); } EXPORT_SYMBOL(v4l2_s_ext_ctrls); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e36629ae2203..38765af9ad2d 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2186,9 +2186,11 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, p->error_idx = p->count; if (vfh && vfh->ctrl_handler) - return v4l2_g_ext_ctrls(vfh->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_g_ext_ctrls(vfh->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (vfd->ctrl_handler) - return v4l2_g_ext_ctrls(vfd->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_g_ext_ctrls(vfd->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_g_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : @@ -2205,9 +2207,11 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, p->error_idx = p->count; if (vfh && vfh->ctrl_handler) - return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (vfd->ctrl_handler) - return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_s_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : @@ -2224,9 +2228,11 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, p->error_idx = p->count; if (vfh && vfh->ctrl_handler) - return v4l2_try_ext_ctrls(vfh->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_try_ext_ctrls(vfh->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (vfd->ctrl_handler) - return v4l2_try_ext_ctrls(vfd->ctrl_handler, vfd->v4l2_dev->mdev, p); + return v4l2_try_ext_ctrls(vfd->ctrl_handler, + vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_try_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 25c73c13cc7e..f725cd9b66b9 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -372,19 +372,19 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!vfh->ctrl_handler) return -ENOTTY; return v4l2_g_ext_ctrls(vfh->ctrl_handler, - sd->v4l2_dev->mdev, arg); + vdev, sd->v4l2_dev->mdev, arg); case VIDIOC_S_EXT_CTRLS: if (!vfh->ctrl_handler) return -ENOTTY; return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, - sd->v4l2_dev->mdev, arg); + vdev, sd->v4l2_dev->mdev, arg); case VIDIOC_TRY_EXT_CTRLS: if (!vfh->ctrl_handler) return -ENOTTY; return v4l2_try_ext_ctrls(vfh->ctrl_handler, - sd->v4l2_dev->mdev, arg); + vdev, sd->v4l2_dev->mdev, arg); case VIDIOC_DQEVENT: if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 6e9dc9c44bb1..570ff4b0205a 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -1268,25 +1268,28 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, * :ref:`VIDIOC_G_EXT_CTRLS ` ioctl * * @hdl: pointer to &struct v4l2_ctrl_handler + * @vdev: pointer to &struct video_device * @mdev: pointer to &struct media_device * @c: pointer to &struct v4l2_ext_controls * * If hdl == NULL then they will all return -EINVAL. */ -int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev, - struct v4l2_ext_controls *c); +int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, + struct media_device *mdev, struct v4l2_ext_controls *c); /** * v4l2_try_ext_ctrls - Helper function to implement * :ref:`VIDIOC_TRY_EXT_CTRLS ` ioctl * * @hdl: pointer to &struct v4l2_ctrl_handler + * @vdev: pointer to &struct video_device * @mdev: pointer to &struct media_device * @c: pointer to &struct v4l2_ext_controls * * If hdl == NULL then they will all return -EINVAL. */ int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, + struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c); @@ -1296,12 +1299,14 @@ int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, * * @fh: pointer to &struct v4l2_fh * @hdl: pointer to &struct v4l2_ctrl_handler + * @vdev: pointer to &struct video_device * @mdev: pointer to &struct media_device * @c: pointer to &struct v4l2_ext_controls * * If hdl == NULL then they will all return -EINVAL. */ int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, + struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c); diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 400f2e46c108..4bba65a59d46 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -602,6 +602,8 @@ struct v4l2_ioctl_ops { #define V4L2_DEV_DEBUG_STREAMING 0x08 /* Log poll() */ #define V4L2_DEV_DEBUG_POLL 0x10 +/* Log controls */ +#define V4L2_DEV_DEBUG_CTRL 0x20 /* Video standard functions */ -- GitLab From 08aac0e32fe44b0afe67da96b01c5c0aa27c7b67 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 22 Jul 2019 07:33:10 -0400 Subject: [PATCH 0569/7155] media: marvell-ccic: mmp: add MODULE_DEVICE_TABLE This fixes autoloading the module by the OF compatible string. Fixes: 83c40e6611ec ("media: marvell-ccic/mmp: add devicetree support") Signed-off-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mmp-driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 10559492e09e..92b92255dac6 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -372,6 +372,7 @@ static const struct of_device_id mmpcam_of_match[] = { { .compatible = "marvell,mmp2-ccic", }, {}, }; +MODULE_DEVICE_TABLE(of, mmpcam_of_match); static struct platform_driver mmpcam_driver = { .probe = mmpcam_probe, -- GitLab From 3c1350501c21db8e3b1a38d9e97db29694305c3b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Jul 2019 04:21:25 -0400 Subject: [PATCH 0570/7155] media: v4l2-dev/ioctl: require non-zero device_caps, verify sane querycap results Now that all V4L2 drivers set device_caps in struct video_device, we can add a check for this to ensure all future drivers fill this in. Also verify that when the querycap ioctl is called the driver didn't mess with the device_caps value and that capabilities is a superset of device_caps. Signed-off-by: Hans Verkuil Reviewed-by: Sakari Ailus [hverkuil-cisco@xs4all.nl: fix too-long line] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 3 +++ drivers/media/v4l2-core/v4l2-ioctl.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index cbb74f748555..3af72e3bbd65 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -859,6 +859,9 @@ int __video_register_device(struct video_device *vdev, /* the v4l2_dev pointer MUST be present */ if (WARN_ON(!vdev->v4l2_dev)) return -EINVAL; + /* the device_caps field MUST be set */ + if (WARN_ON(!vdev->device_caps)) + return -EINVAL; /* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 38765af9ad2d..9484cc2619e4 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1057,14 +1057,19 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops, ret = ops->vidioc_querycap(file, fh, cap); - cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; /* - * Drivers MUST fill in device_caps, so check for this and - * warn if it was forgotten. + * Drivers must not change device_caps, so check for this and + * warn if this happened. + */ + WARN_ON(cap->device_caps != vfd->device_caps); + /* + * Check that capabilities is a superset of + * vfd->device_caps | V4L2_CAP_DEVICE_CAPS */ - WARN(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) || - !cap->device_caps, "Bad caps for driver %s, %x %x", - cap->driver, cap->capabilities, cap->device_caps); + WARN_ON((cap->capabilities & + (vfd->device_caps | V4L2_CAP_DEVICE_CAPS)) != + (vfd->device_caps | V4L2_CAP_DEVICE_CAPS)); + cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; return ret; -- GitLab From 610fce5372216652cdcf6854c48d2876d1eeaad3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Jul 2019 08:25:49 -0400 Subject: [PATCH 0571/7155] media: sh_veu: convert to struct v4l2_fh This driver didn't use struct v4l2_fh, so add it. This is a very basic conversion. I can't test this on real hardware, so I didn't dare to also convert the driver to start using the v4l2-mem2mem ioctl/fop helpers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_veu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 4be6efd47d33..2b4c0d9d6928 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -81,6 +81,7 @@ struct sh_veu_dev; struct sh_veu_file { + struct v4l2_fh fh; struct sh_veu_dev *veu_dev; bool cfg_needed; }; @@ -961,12 +962,14 @@ static int sh_veu_open(struct file *file) if (!veu_file) return -ENOMEM; + v4l2_fh_init(&veu_file->fh, video_devdata(file)); veu_file->veu_dev = veu; veu_file->cfg_needed = true; file->private_data = veu_file; pm_runtime_get_sync(veu->dev); + v4l2_fh_add(&veu_file->fh); dev_dbg(veu->dev, "Created instance %p\n", veu_file); @@ -996,6 +999,8 @@ static int sh_veu_release(struct file *file) } pm_runtime_put(veu->dev); + v4l2_fh_del(&veu_file->fh); + v4l2_fh_exit(&veu_file->fh); kfree(veu_file); -- GitLab From ee484875af0080a0c8621e58facf06f92c658a4b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Jul 2019 08:58:01 -0400 Subject: [PATCH 0572/7155] media: davinci/vpfe_capture.c: drop unused format descriptions Simplify vpfe_pixel_format to just contain the pixelformat and bpp fields. All others are unused. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpfe_capture.c | 51 ++++--------------- include/media/davinci/vpfe_capture.h | 2 +- 2 files changed, 10 insertions(+), 43 deletions(-) diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 852fc357e19d..916ed743d716 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -119,57 +119,27 @@ static const struct vpfe_standard vpfe_standards[] = { /* Used when raw Bayer image from ccdc is directly captured to SDRAM */ static const struct vpfe_pixel_format vpfe_pix_fmts[] = { { - .fmtdesc = { - .index = 0, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb 8bit A-Law compr.", - .pixelformat = V4L2_PIX_FMT_SBGGR8, - }, + .pixelformat = V4L2_PIX_FMT_SBGGR8, .bpp = 1, }, { - .fmtdesc = { - .index = 1, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb - 16bit", - .pixelformat = V4L2_PIX_FMT_SBGGR16, - }, + .pixelformat = V4L2_PIX_FMT_SBGGR16, .bpp = 2, }, { - .fmtdesc = { - .index = 2, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb 8bit DPCM compr.", - .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, - }, + .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, .bpp = 1, }, { - .fmtdesc = { - .index = 3, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "YCbCr 4:2:2 Interleaved UYVY", - .pixelformat = V4L2_PIX_FMT_UYVY, - }, + .pixelformat = V4L2_PIX_FMT_UYVY, .bpp = 2, }, { - .fmtdesc = { - .index = 4, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "YCbCr 4:2:2 Interleaved YUYV", - .pixelformat = V4L2_PIX_FMT_YUYV, - }, + .pixelformat = V4L2_PIX_FMT_YUYV, .bpp = 2, }, { - .fmtdesc = { - .index = 5, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Y/CbCr 4:2:0 - Semi planar", - .pixelformat = V4L2_PIX_FMT_NV12, - }, + .pixelformat = V4L2_PIX_FMT_NV12, .bpp = 1, }, }; @@ -183,7 +153,7 @@ static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format) int i; for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) { - if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat) + if (pix_format == vpfe_pix_fmts[i].pixelformat) return &vpfe_pix_fmts[i]; } return NULL; @@ -782,7 +752,7 @@ static const struct vpfe_pixel_format * temp = 0; found = 0; while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) { - if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) { + if (vpfe_pix_fmt->pixelformat == pix) { found = 1; break; } @@ -899,7 +869,6 @@ static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv, { struct vpfe_device *vpfe_dev = video_drvdata(file); const struct vpfe_pixel_format *pix_fmt; - int temp_index; u32 pix; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n"); @@ -910,9 +879,7 @@ static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv, /* Fill in the information about format */ pix_fmt = vpfe_lookup_pix_format(pix); if (pix_fmt) { - temp_index = fmt->index; - *fmt = pix_fmt->fmtdesc; - fmt->index = temp_index; + fmt->pixelformat = fmt->pixelformat; return 0; } return -EINVAL; diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h index 2c5b3eacf527..4ad53031e2f7 100644 --- a/include/media/davinci/vpfe_capture.h +++ b/include/media/davinci/vpfe_capture.h @@ -32,7 +32,7 @@ #define CAPTURE_DRV_NAME "vpfe-capture" struct vpfe_pixel_format { - struct v4l2_fmtdesc fmtdesc; + u32 pixelformat; /* bytes per pixel */ int bpp; }; -- GitLab From 8baf50109929c9b407be756c52f4f80a659cb705 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Jul 2019 08:59:47 -0400 Subject: [PATCH 0573/7155] media: am437x: remove unused struct vpfe_pixel_format struct vpfe_pixel_format was defined, but never used. Remove it. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h index 17d7aa426788..4678285f34c6 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.h +++ b/drivers/media/platform/am437x/am437x-vpfe.h @@ -65,12 +65,6 @@ struct vpfe_hw_if_param { #define VPFE_MAX_SUBDEV 1 #define VPFE_MAX_INPUTS 1 -struct vpfe_pixel_format { - struct v4l2_fmtdesc fmtdesc; - /* bytes per pixel */ - int bpp; -}; - struct vpfe_std_info { int active_pixels; int active_lines; -- GitLab From 79e85d1d2c16ba4907bb9d6a4381516b729ff341 Mon Sep 17 00:00:00 2001 From: Guillaume Tucker Date: Wed, 24 Jul 2019 11:19:22 -0400 Subject: [PATCH 0574/7155] media: vivid: fix device init when no_error_inj=1 and fb disabled Add an extra condition to add the video output control class when the device has some hdmi outputs defined. This is required to then always be able to add the display present control, which is enabled when there are some hdmi outputs. This fixes the corner case where no_error_inj is enabled and the device has no frame buffer but some hdmi outputs, as otherwise the video output control class would be added anyway. Without this fix, the sanity checks fail in v4l2_ctrl_new() as name is NULL. Fixes: c533435ffb91 ("media: vivid: add display present control") Cc: stable@vger.kernel.org # for 5.3 Signed-off-by: Guillaume Tucker Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-ctrls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index fb9220e4e640..cb19a9a73092 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -1473,7 +1473,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, v4l2_ctrl_handler_init(hdl_vid_cap, 55); v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_vid_out, 26); - if (!no_error_inj || dev->has_fb) + if (!no_error_inj || dev->has_fb || dev->num_hdmi_outputs) v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL); v4l2_ctrl_handler_init(hdl_vbi_cap, 21); v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL); -- GitLab From 757c2bf597a8e9f859f8efceda9c5108607fd98d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 25 Jul 2019 02:31:53 -0400 Subject: [PATCH 0575/7155] media: staging/media/bcm2048: remove driver This driver has seen no substantial effort to move it out of staging for 6 years. And after asking around nobody stepped up to do the remaining work. So remove it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/bcm2048/Kconfig | 14 - drivers/staging/media/bcm2048/Makefile | 2 - drivers/staging/media/bcm2048/TODO | 24 - drivers/staging/media/bcm2048/radio-bcm2048.c | 2689 ----------------- drivers/staging/media/bcm2048/radio-bcm2048.h | 26 - 7 files changed, 2758 deletions(-) delete mode 100644 drivers/staging/media/bcm2048/Kconfig delete mode 100644 drivers/staging/media/bcm2048/Makefile delete mode 100644 drivers/staging/media/bcm2048/TODO delete mode 100644 drivers/staging/media/bcm2048/radio-bcm2048.c delete mode 100644 drivers/staging/media/bcm2048/radio-bcm2048.h diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 534d85d6c5e3..45075f977f1b 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -22,8 +22,6 @@ if STAGING_MEDIA && MEDIA_SUPPORT # Please keep them in alphabetic order source "drivers/staging/media/allegro-dvt/Kconfig" -source "drivers/staging/media/bcm2048/Kconfig" - source "drivers/staging/media/davinci_vpfe/Kconfig" source "drivers/staging/media/hantro/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index c486298194da..c19cfed0b059 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro-dvt/ -obj-$(CONFIG_I2C_BCM2048) += bcm2048/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ diff --git a/drivers/staging/media/bcm2048/Kconfig b/drivers/staging/media/bcm2048/Kconfig deleted file mode 100644 index ab2d50cac140..000000000000 --- a/drivers/staging/media/bcm2048/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Multimedia Video device configuration -# - -config I2C_BCM2048 - tristate "Broadcom BCM2048 FM Radio Receiver support" - depends on I2C && VIDEO_V4L2 && RADIO_ADAPTERS - help - Say Y here if you want support to BCM2048 FM Radio Receiver. - This device driver supports only i2c bus. - - To compile this driver as a module, choose M here: the - module will be called radio-bcm2048. diff --git a/drivers/staging/media/bcm2048/Makefile b/drivers/staging/media/bcm2048/Makefile deleted file mode 100644 index f42056848dc6..000000000000 --- a/drivers/staging/media/bcm2048/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_I2C_BCM2048) += radio-bcm2048.o diff --git a/drivers/staging/media/bcm2048/TODO b/drivers/staging/media/bcm2048/TODO deleted file mode 100644 index 6bee2a2dad68..000000000000 --- a/drivers/staging/media/bcm2048/TODO +++ /dev/null @@ -1,24 +0,0 @@ -TODO: - -From the initial code review: - -The main thing you need to do is to implement all the controls using the -control framework (see Documentation/media/kapi/v4l2-controls.rst). -Most drivers are by now converted to the control framework, so you will -find many examples of how to do this in drivers/media/radio. - -The sysfs stuff should be replaced by controls as well. A lot of the RDS -support is now available as controls (although there may well be some -missing features, but that is easy enough to add). Since the RDS data is -actually read() from the device I am not sure whether the RDS -properties/controls should be there at all. - -Correct Coding Style, as this driver also violates several Style -rules, and do evil tricks, like returning from a function inside a -macro. - -Finally this driver should probably be split up into two parts: one -v4l2_subdev-based core driver and one platform driver. See e.g. -radio-si4713/si4713-i2c.c as a good example. But I would wait with that -until the rest of the driver is cleaned up. Then I have a better idea of -whether this is necessary or not. diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c deleted file mode 100644 index 2c60a1fb6350..000000000000 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ /dev/null @@ -1,2689 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * drivers/staging/media/radio-bcm2048.c - * - * Driver for I2C Broadcom BCM2048 FM Radio Receiver: - * - * Copyright (C) Nokia Corporation - * Contact: Eero Nurkkala - * - * Copyright (C) Nils Faerber - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -/* - * History: - * Eero Nurkkala - * Version 0.0.1 - * - Initial implementation - * 2010-02-21 Nils Faerber - * Version 0.0.2 - * - Add support for interrupt driven rds data reading - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "radio-bcm2048.h" - -/* driver definitions */ -#define BCM2048_DRIVER_AUTHOR "Eero Nurkkala " -#define BCM2048_DRIVER_NAME BCM2048_NAME -#define BCM2048_DRIVER_CARD "Broadcom bcm2048 FM Radio Receiver" -#define BCM2048_DRIVER_DESC "I2C driver for BCM2048 FM Radio Receiver" - -/* I2C Control Registers */ -#define BCM2048_I2C_FM_RDS_SYSTEM 0x00 -#define BCM2048_I2C_FM_CTRL 0x01 -#define BCM2048_I2C_RDS_CTRL0 0x02 -#define BCM2048_I2C_RDS_CTRL1 0x03 -#define BCM2048_I2C_FM_AUDIO_PAUSE 0x04 -#define BCM2048_I2C_FM_AUDIO_CTRL0 0x05 -#define BCM2048_I2C_FM_AUDIO_CTRL1 0x06 -#define BCM2048_I2C_FM_SEARCH_CTRL0 0x07 -#define BCM2048_I2C_FM_SEARCH_CTRL1 0x08 -#define BCM2048_I2C_FM_SEARCH_TUNE_MODE 0x09 -#define BCM2048_I2C_FM_FREQ0 0x0a -#define BCM2048_I2C_FM_FREQ1 0x0b -#define BCM2048_I2C_FM_AF_FREQ0 0x0c -#define BCM2048_I2C_FM_AF_FREQ1 0x0d -#define BCM2048_I2C_FM_CARRIER 0x0e -#define BCM2048_I2C_FM_RSSI 0x0f -#define BCM2048_I2C_FM_RDS_MASK0 0x10 -#define BCM2048_I2C_FM_RDS_MASK1 0x11 -#define BCM2048_I2C_FM_RDS_FLAG0 0x12 -#define BCM2048_I2C_FM_RDS_FLAG1 0x13 -#define BCM2048_I2C_RDS_WLINE 0x14 -#define BCM2048_I2C_RDS_BLKB_MATCH0 0x16 -#define BCM2048_I2C_RDS_BLKB_MATCH1 0x17 -#define BCM2048_I2C_RDS_BLKB_MASK0 0x18 -#define BCM2048_I2C_RDS_BLKB_MASK1 0x19 -#define BCM2048_I2C_RDS_PI_MATCH0 0x1a -#define BCM2048_I2C_RDS_PI_MATCH1 0x1b -#define BCM2048_I2C_RDS_PI_MASK0 0x1c -#define BCM2048_I2C_RDS_PI_MASK1 0x1d -#define BCM2048_I2C_SPARE1 0x20 -#define BCM2048_I2C_SPARE2 0x21 -#define BCM2048_I2C_FM_RDS_REV 0x28 -#define BCM2048_I2C_SLAVE_CONFIGURATION 0x29 -#define BCM2048_I2C_RDS_DATA 0x80 -#define BCM2048_I2C_FM_BEST_TUNE_MODE 0x90 - -/* BCM2048_I2C_FM_RDS_SYSTEM */ -#define BCM2048_FM_ON 0x01 -#define BCM2048_RDS_ON 0x02 - -/* BCM2048_I2C_FM_CTRL */ -#define BCM2048_BAND_SELECT 0x01 -#define BCM2048_STEREO_MONO_AUTO_SELECT 0x02 -#define BCM2048_STEREO_MONO_MANUAL_SELECT 0x04 -#define BCM2048_STEREO_MONO_BLEND_SWITCH 0x08 -#define BCM2048_HI_LO_INJECTION 0x10 - -/* BCM2048_I2C_RDS_CTRL0 */ -#define BCM2048_RBDS_RDS_SELECT 0x01 -#define BCM2048_FLUSH_FIFO 0x02 - -/* BCM2048_I2C_FM_AUDIO_PAUSE */ -#define BCM2048_AUDIO_PAUSE_RSSI_TRESH 0x0f -#define BCM2048_AUDIO_PAUSE_DURATION 0xf0 - -/* BCM2048_I2C_FM_AUDIO_CTRL0 */ -#define BCM2048_RF_MUTE 0x01 -#define BCM2048_MANUAL_MUTE 0x02 -#define BCM2048_DAC_OUTPUT_LEFT 0x04 -#define BCM2048_DAC_OUTPUT_RIGHT 0x08 -#define BCM2048_AUDIO_ROUTE_DAC 0x10 -#define BCM2048_AUDIO_ROUTE_I2S 0x20 -#define BCM2048_DE_EMPHASIS_SELECT 0x40 -#define BCM2048_AUDIO_BANDWIDTH_SELECT 0x80 - -/* BCM2048_I2C_FM_SEARCH_CTRL0 */ -#define BCM2048_SEARCH_RSSI_THRESHOLD 0x7f -#define BCM2048_SEARCH_DIRECTION 0x80 - -/* BCM2048_I2C_FM_SEARCH_TUNE_MODE */ -#define BCM2048_FM_AUTO_SEARCH 0x03 - -/* BCM2048_I2C_FM_RSSI */ -#define BCM2048_RSSI_VALUE 0xff - -/* BCM2048_I2C_FM_RDS_MASK0 */ -/* BCM2048_I2C_FM_RDS_MASK1 */ -#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED 0x01 -#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL 0x02 -#define BCM2048_FM_FLAG_RSSI_LOW 0x04 -#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH 0x08 -#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10 -#define BCM2048_FLAG_STEREO_DETECTED 0x20 -#define BCM2048_FLAG_STEREO_ACTIVE 0x40 - -/* BCM2048_I2C_RDS_DATA */ -#define BCM2048_SLAVE_ADDRESS 0x3f -#define BCM2048_SLAVE_ENABLE 0x80 - -/* BCM2048_I2C_FM_BEST_TUNE_MODE */ -#define BCM2048_BEST_TUNE_MODE 0x80 - -#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED 0x01 -#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL 0x02 -#define BCM2048_FM_FLAG_RSSI_LOW 0x04 -#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH 0x08 -#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10 -#define BCM2048_FLAG_STEREO_DETECTED 0x20 -#define BCM2048_FLAG_STEREO_ACTIVE 0x40 - -#define BCM2048_RDS_FLAG_FIFO_WLINE 0x02 -#define BCM2048_RDS_FLAG_B_BLOCK_MATCH 0x08 -#define BCM2048_RDS_FLAG_SYNC_LOST 0x10 -#define BCM2048_RDS_FLAG_PI_MATCH 0x20 - -#define BCM2048_RDS_MARK_END_BYTE0 0x7C -#define BCM2048_RDS_MARK_END_BYTEN 0xFF - -#define BCM2048_FM_FLAGS_ALL (FM_FLAG_SEARCH_TUNE_FINISHED | \ - FM_FLAG_SEARCH_TUNE_FAIL | \ - FM_FLAG_RSSI_LOW | \ - FM_FLAG_CARRIER_ERROR_HIGH | \ - FM_FLAG_AUDIO_PAUSE_INDICATION | \ - FLAG_STEREO_DETECTED | FLAG_STEREO_ACTIVE) - -#define BCM2048_RDS_FLAGS_ALL (RDS_FLAG_FIFO_WLINE | \ - RDS_FLAG_B_BLOCK_MATCH | \ - RDS_FLAG_SYNC_LOST | RDS_FLAG_PI_MATCH) - -#define BCM2048_DEFAULT_TIMEOUT 1500 -#define BCM2048_AUTO_SEARCH_TIMEOUT 3000 - -#define BCM2048_FREQDEV_UNIT 10000 -#define BCM2048_FREQV4L2_MULTI 625 -#define dev_to_v4l2(f) (((f) * BCM2048_FREQDEV_UNIT) / BCM2048_FREQV4L2_MULTI) -#define v4l2_to_dev(f) (((f) * BCM2048_FREQV4L2_MULTI) / BCM2048_FREQDEV_UNIT) - -#define msb(x) ((u8)((u16)(x) >> 8)) -#define lsb(x) ((u8)((u16)(x) & 0x00FF)) -#define compose_u16(msb, lsb) (((u16)(msb) << 8) | (lsb)) - -#define BCM2048_DEFAULT_POWERING_DELAY 20 -#define BCM2048_DEFAULT_REGION 0x02 -#define BCM2048_DEFAULT_MUTE 0x01 -#define BCM2048_DEFAULT_RSSI_THRESHOLD 0x64 -#define BCM2048_DEFAULT_RDS_WLINE 0x7E - -#define BCM2048_FM_SEARCH_INACTIVE 0x00 -#define BCM2048_FM_PRE_SET_MODE 0x01 -#define BCM2048_FM_AUTO_SEARCH_MODE 0x02 -#define BCM2048_FM_AF_JUMP_MODE 0x03 - -#define BCM2048_FREQUENCY_BASE 64000 - -#define BCM2048_POWER_ON 0x01 -#define BCM2048_POWER_OFF 0x00 - -#define BCM2048_ITEM_ENABLED 0x01 -#define BCM2048_SEARCH_DIRECTION_UP 0x01 - -#define BCM2048_DE_EMPHASIS_75us 75 -#define BCM2048_DE_EMPHASIS_50us 50 - -#define BCM2048_SCAN_FAIL 0x00 -#define BCM2048_SCAN_OK 0x01 - -#define BCM2048_FREQ_ERROR_FLOOR -20 -#define BCM2048_FREQ_ERROR_ROOF 20 - -/* -60 dB is reported as full signal strength */ -#define BCM2048_RSSI_LEVEL_BASE -60 -#define BCM2048_RSSI_LEVEL_ROOF -100 -#define BCM2048_RSSI_LEVEL_ROOF_NEG 100 -#define BCM2048_SIGNAL_MULTIPLIER (0xFFFF / \ - (BCM2048_RSSI_LEVEL_ROOF_NEG + \ - BCM2048_RSSI_LEVEL_BASE)) - -#define BCM2048_RDS_FIFO_DUPLE_SIZE 0x03 -#define BCM2048_RDS_CRC_MASK 0x0F -#define BCM2048_RDS_CRC_NONE 0x00 -#define BCM2048_RDS_CRC_MAX_2BITS 0x04 -#define BCM2048_RDS_CRC_LEAST_2BITS 0x08 -#define BCM2048_RDS_CRC_UNRECOVARABLE 0x0C - -#define BCM2048_RDS_BLOCK_MASK 0xF0 -#define BCM2048_RDS_BLOCK_A 0x00 -#define BCM2048_RDS_BLOCK_B 0x10 -#define BCM2048_RDS_BLOCK_C 0x20 -#define BCM2048_RDS_BLOCK_D 0x30 -#define BCM2048_RDS_BLOCK_C_SCORED 0x40 -#define BCM2048_RDS_BLOCK_E 0x60 - -#define BCM2048_RDS_RT 0x20 -#define BCM2048_RDS_PS 0x00 - -#define BCM2048_RDS_GROUP_AB_MASK 0x08 -#define BCM2048_RDS_GROUP_A 0x00 -#define BCM2048_RDS_GROUP_B 0x08 - -#define BCM2048_RDS_RT_AB_MASK 0x10 -#define BCM2048_RDS_RT_A 0x00 -#define BCM2048_RDS_RT_B 0x10 -#define BCM2048_RDS_RT_INDEX 0x0F - -#define BCM2048_RDS_PS_INDEX 0x03 - -struct rds_info { - u16 rds_pi; -#define BCM2048_MAX_RDS_RT (64 + 1) - u8 rds_rt[BCM2048_MAX_RDS_RT]; - u8 rds_rt_group_b; - u8 rds_rt_ab; -#define BCM2048_MAX_RDS_PS (8 + 1) - u8 rds_ps[BCM2048_MAX_RDS_PS]; - u8 rds_ps_group; - u8 rds_ps_group_cnt; -#define BCM2048_MAX_RDS_RADIO_TEXT 255 - u8 radio_text[BCM2048_MAX_RDS_RADIO_TEXT + 3]; - u8 text_len; -}; - -struct region_info { - u32 bottom_frequency; - u32 top_frequency; - u8 deemphasis; - u8 channel_spacing; - u8 region; -}; - -struct bcm2048_device { - struct i2c_client *client; - struct video_device videodev; - struct work_struct work; - struct completion compl; - struct mutex mutex; - struct bcm2048_platform_data *platform_data; - struct rds_info rds_info; - struct region_info region_info; - u16 frequency; - u8 cache_fm_rds_system; - u8 cache_fm_ctrl; - u8 cache_fm_audio_ctrl0; - u8 cache_fm_search_ctrl0; - u8 power_state; - u8 rds_state; - u8 fifo_size; - u8 scan_state; - u8 mute_state; - - /* for rds data device read */ - wait_queue_head_t read_queue; - unsigned int users; - unsigned char rds_data_available; - unsigned int rd_index; -}; - -static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ -module_param(radio_nr, int, 0000); -MODULE_PARM_DESC(radio_nr, - "Minor number for radio device (-1 ==> auto assign)"); - -static const struct region_info region_configs[] = { - /* USA */ - { - .channel_spacing = 20, - .bottom_frequency = 87500, - .top_frequency = 108000, - .deemphasis = 75, - .region = 0, - }, - /* Australia */ - { - .channel_spacing = 20, - .bottom_frequency = 87500, - .top_frequency = 108000, - .deemphasis = 50, - .region = 1, - }, - /* Europe */ - { - .channel_spacing = 10, - .bottom_frequency = 87500, - .top_frequency = 108000, - .deemphasis = 50, - .region = 2, - }, - /* Japan */ - { - .channel_spacing = 10, - .bottom_frequency = 76000, - .top_frequency = 90000, - .deemphasis = 50, - .region = 3, - }, -}; - -/* - * I2C Interface read / write - */ -static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg, - unsigned int value) -{ - struct i2c_client *client = bdev->client; - u8 data[2]; - - if (!bdev->power_state) { - dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); - return -EIO; - } - - data[0] = reg & 0xff; - data[1] = value & 0xff; - - if (i2c_master_send(client, data, 2) == 2) - return 0; - - dev_err(&bdev->client->dev, "BCM I2C error!\n"); - dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n"); - return -EIO; -} - -static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg, - u8 *value) -{ - struct i2c_client *client = bdev->client; - - if (!bdev->power_state) { - dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); - return -EIO; - } - - value[0] = i2c_smbus_read_byte_data(client, reg & 0xff); - - return 0; -} - -static int bcm2048_recv_duples(struct bcm2048_device *bdev, unsigned int reg, - u8 *value, u8 duples) -{ - struct i2c_client *client = bdev->client; - struct i2c_adapter *adap = client->adapter; - struct i2c_msg msg[2]; - u8 buf; - - if (!bdev->power_state) { - dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); - return -EIO; - } - - buf = reg & 0xff; - - msg[0].addr = client->addr; - msg[0].flags = client->flags & I2C_M_TEN; - msg[0].len = 1; - msg[0].buf = &buf; - - msg[1].addr = client->addr; - msg[1].flags = client->flags & I2C_M_TEN; - msg[1].flags |= I2C_M_RD; - msg[1].len = duples; - msg[1].buf = value; - - return i2c_transfer(adap, msg, 2); -} - -/* - * BCM2048 - I2C register programming helpers - */ -static int bcm2048_set_power_state(struct bcm2048_device *bdev, u8 power) -{ - int err = 0; - - mutex_lock(&bdev->mutex); - - if (power) { - bdev->power_state = BCM2048_POWER_ON; - bdev->cache_fm_rds_system |= BCM2048_FM_ON; - } else { - bdev->cache_fm_rds_system &= ~BCM2048_FM_ON; - } - - /* - * Warning! FM cannot be turned off because then - * the I2C communications get ruined! - * Comment off the "if (power)" when the chip works! - */ - if (power) - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, - bdev->cache_fm_rds_system); - msleep(BCM2048_DEFAULT_POWERING_DELAY); - - if (!power) - bdev->power_state = BCM2048_POWER_OFF; - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_power_state(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value); - - mutex_unlock(&bdev->mutex); - - if (!err && (value & BCM2048_FM_ON)) - return BCM2048_POWER_ON; - - return err; -} - -static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) -{ - int err; - u8 flags; - - bdev->cache_fm_rds_system &= ~BCM2048_RDS_ON; - - if (rds_on) { - bdev->cache_fm_rds_system |= BCM2048_RDS_ON; - bdev->rds_state = BCM2048_RDS_ON; - flags = BCM2048_RDS_FLAG_FIFO_WLINE; - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, - flags); - } else { - flags = 0; - bdev->rds_state = 0; - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, - flags); - memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); - } - if (err) - return err; - - return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, - bdev->cache_fm_rds_system); -} - -static int bcm2048_get_rds_no_lock(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value); - - if (!err && (value & BCM2048_RDS_ON)) - return BCM2048_ITEM_ENABLED; - - return err; -} - -static int bcm2048_set_rds(struct bcm2048_device *bdev, u8 rds_on) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_set_rds_no_lock(bdev, rds_on); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds(struct bcm2048_device *bdev) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_get_rds_no_lock(bdev); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_pi(struct bcm2048_device *bdev) -{ - return bdev->rds_info.rds_pi; -} - -static int bcm2048_set_fm_automatic_stereo_mono(struct bcm2048_device *bdev, - u8 enabled) -{ - int err; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_ctrl &= ~BCM2048_STEREO_MONO_AUTO_SELECT; - - if (enabled) - bdev->cache_fm_ctrl |= BCM2048_STEREO_MONO_AUTO_SELECT; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL, - bdev->cache_fm_ctrl); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_set_fm_hi_lo_injection(struct bcm2048_device *bdev, - u8 hi_lo) -{ - int err; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_ctrl &= ~BCM2048_HI_LO_INJECTION; - - if (hi_lo) - bdev->cache_fm_ctrl |= BCM2048_HI_LO_INJECTION; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL, - bdev->cache_fm_ctrl); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_hi_lo_injection(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CTRL, &value); - - mutex_unlock(&bdev->mutex); - - if (!err && (value & BCM2048_HI_LO_INJECTION)) - return BCM2048_ITEM_ENABLED; - - return err; -} - -static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency) -{ - int err; - - if (frequency < bdev->region_info.bottom_frequency || - frequency > bdev->region_info.top_frequency) - return -EDOM; - - frequency -= BCM2048_FREQUENCY_BASE; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ0, lsb(frequency)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ1, - msb(frequency)); - - if (!err) - bdev->frequency = frequency; - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_frequency(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ1, &msb); - - mutex_unlock(&bdev->mutex); - - if (err) - return err; - - err = compose_u16(msb, lsb); - err += BCM2048_FREQUENCY_BASE; - - return err; -} - -static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev, - u32 frequency) -{ - int err; - - if (frequency < bdev->region_info.bottom_frequency || - frequency > bdev->region_info.top_frequency) - return -EDOM; - - frequency -= BCM2048_FREQUENCY_BASE; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ0, - lsb(frequency)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ1, - msb(frequency)); - if (!err) - bdev->frequency = frequency; - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_af_frequency(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ1, &msb); - - mutex_unlock(&bdev->mutex); - - if (err) - return err; - - err = compose_u16(msb, lsb); - err += BCM2048_FREQUENCY_BASE; - - return err; -} - -static int bcm2048_set_fm_deemphasis(struct bcm2048_device *bdev, int d) -{ - int err; - u8 deemphasis; - - if (d == BCM2048_DE_EMPHASIS_75us) - deemphasis = BCM2048_DE_EMPHASIS_SELECT; - else - deemphasis = 0; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_audio_ctrl0 &= ~BCM2048_DE_EMPHASIS_SELECT; - bdev->cache_fm_audio_ctrl0 |= deemphasis; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, - bdev->cache_fm_audio_ctrl0); - - if (!err) - bdev->region_info.deemphasis = d; - - mutex_unlock(&bdev->mutex); - - return err; -} - -static int bcm2048_get_fm_deemphasis(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); - - mutex_unlock(&bdev->mutex); - - if (!err) { - if (value & BCM2048_DE_EMPHASIS_SELECT) - return BCM2048_DE_EMPHASIS_75us; - - return BCM2048_DE_EMPHASIS_50us; - } - - return err; -} - -static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region) -{ - int err; - u32 new_frequency = 0; - - if (region >= ARRAY_SIZE(region_configs)) - return -EINVAL; - - mutex_lock(&bdev->mutex); - bdev->region_info = region_configs[region]; - - if (region_configs[region].bottom_frequency < 87500) - bdev->cache_fm_ctrl |= BCM2048_BAND_SELECT; - else - bdev->cache_fm_ctrl &= ~BCM2048_BAND_SELECT; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL, - bdev->cache_fm_ctrl); - if (err) { - mutex_unlock(&bdev->mutex); - goto done; - } - mutex_unlock(&bdev->mutex); - - if (bdev->frequency < region_configs[region].bottom_frequency || - bdev->frequency > region_configs[region].top_frequency) - new_frequency = region_configs[region].bottom_frequency; - - if (new_frequency > 0) { - err = bcm2048_set_fm_frequency(bdev, new_frequency); - - if (err) - goto done; - } - - err = bcm2048_set_fm_deemphasis(bdev, - region_configs[region].deemphasis); - -done: - return err; -} - -static int bcm2048_get_region(struct bcm2048_device *bdev) -{ - int err; - - mutex_lock(&bdev->mutex); - err = bdev->region_info.region; - mutex_unlock(&bdev->mutex); - - return err; -} - -static int bcm2048_set_mute(struct bcm2048_device *bdev, u16 mute) -{ - int err; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE); - - if (mute) - bdev->cache_fm_audio_ctrl0 |= (BCM2048_RF_MUTE | - BCM2048_MANUAL_MUTE); - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, - bdev->cache_fm_audio_ctrl0); - - if (!err) - bdev->mute_state = mute; - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_mute(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - if (bdev->power_state) { - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, - &value); - if (!err) - err = value & (BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE); - } else { - err = bdev->mute_state; - } - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_set_audio_route(struct bcm2048_device *bdev, u8 route) -{ - int err; - - mutex_lock(&bdev->mutex); - - route &= (BCM2048_AUDIO_ROUTE_DAC | BCM2048_AUDIO_ROUTE_I2S); - bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_AUDIO_ROUTE_DAC | - BCM2048_AUDIO_ROUTE_I2S); - bdev->cache_fm_audio_ctrl0 |= route; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, - bdev->cache_fm_audio_ctrl0); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_audio_route(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); - - mutex_unlock(&bdev->mutex); - - if (!err) - return value & (BCM2048_AUDIO_ROUTE_DAC | - BCM2048_AUDIO_ROUTE_I2S); - - return err; -} - -static int bcm2048_set_dac_output(struct bcm2048_device *bdev, u8 channels) -{ - int err; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_DAC_OUTPUT_LEFT | - BCM2048_DAC_OUTPUT_RIGHT); - bdev->cache_fm_audio_ctrl0 |= channels; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, - bdev->cache_fm_audio_ctrl0); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_dac_output(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); - - mutex_unlock(&bdev->mutex); - - if (!err) - return value & (BCM2048_DAC_OUTPUT_LEFT | - BCM2048_DAC_OUTPUT_RIGHT); - - return err; -} - -static int bcm2048_set_fm_search_rssi_threshold(struct bcm2048_device *bdev, - u8 threshold) -{ - int err; - - mutex_lock(&bdev->mutex); - - threshold &= BCM2048_SEARCH_RSSI_THRESHOLD; - bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_RSSI_THRESHOLD; - bdev->cache_fm_search_ctrl0 |= threshold; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, - bdev->cache_fm_search_ctrl0); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_search_rssi_threshold(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value); - - mutex_unlock(&bdev->mutex); - - if (!err) - return value & BCM2048_SEARCH_RSSI_THRESHOLD; - - return err; -} - -static int bcm2048_set_fm_search_mode_direction(struct bcm2048_device *bdev, - u8 direction) -{ - int err; - - mutex_lock(&bdev->mutex); - - bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_DIRECTION; - - if (direction) - bdev->cache_fm_search_ctrl0 |= BCM2048_SEARCH_DIRECTION; - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, - bdev->cache_fm_search_ctrl0); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_search_mode_direction(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value); - - mutex_unlock(&bdev->mutex); - - if (!err && (value & BCM2048_SEARCH_DIRECTION)) - return BCM2048_SEARCH_DIRECTION_UP; - - return err; -} - -static int bcm2048_set_fm_search_tune_mode(struct bcm2048_device *bdev, - u8 mode) -{ - int err, timeout, restart_rds = 0; - u8 value, flags; - - value = mode & BCM2048_FM_AUTO_SEARCH; - - flags = BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED | - BCM2048_FM_FLAG_SEARCH_TUNE_FAIL; - - mutex_lock(&bdev->mutex); - - /* - * If RDS is enabled, and frequency is changed, RDS quits working. - * Thus, always restart RDS if it's enabled. Moreover, RDS must - * not be enabled while changing the frequency because it can - * provide a race to the mutex from the workqueue handler if RDS - * IRQ occurs while waiting for frequency changed IRQ. - */ - if (bcm2048_get_rds_no_lock(bdev)) { - err = bcm2048_set_rds_no_lock(bdev, 0); - if (err) - goto unlock; - restart_rds = 1; - } - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK0, flags); - - if (err) - goto unlock; - - bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE, value); - - if (mode != BCM2048_FM_AUTO_SEARCH_MODE) - timeout = BCM2048_DEFAULT_TIMEOUT; - else - timeout = BCM2048_AUTO_SEARCH_TIMEOUT; - - if (!wait_for_completion_timeout(&bdev->compl, - msecs_to_jiffies(timeout))) - dev_err(&bdev->client->dev, "IRQ timeout.\n"); - - if (value) - if (!bdev->scan_state) - err = -EIO; - -unlock: - if (restart_rds) - err |= bcm2048_set_rds_no_lock(bdev, 1); - - mutex_unlock(&bdev->mutex); - - return err; -} - -static int bcm2048_get_fm_search_tune_mode(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE, - &value); - - mutex_unlock(&bdev->mutex); - - if (!err) - return value & BCM2048_FM_AUTO_SEARCH; - - return err; -} - -static int bcm2048_set_rds_b_block_mask(struct bcm2048_device *bdev, u16 mask) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MASK0, - lsb(mask)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MASK1, - msb(mask)); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_b_block_mask(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MASK0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MASK1, &msb); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(msb, lsb); - - return err; -} - -static int bcm2048_set_rds_b_block_match(struct bcm2048_device *bdev, - u16 match) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH0, - lsb(match)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH1, - msb(match)); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_b_block_match(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_BLKB_MATCH1, &msb); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(msb, lsb); - - return err; -} - -static int bcm2048_set_rds_pi_mask(struct bcm2048_device *bdev, u16 mask) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MASK0, lsb(mask)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MASK1, msb(mask)); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_pi_mask(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MASK0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MASK1, &msb); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(msb, lsb); - - return err; -} - -static int bcm2048_set_rds_pi_match(struct bcm2048_device *bdev, u16 match) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MATCH0, - lsb(match)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_RDS_PI_MATCH1, - msb(match)); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_pi_match(struct bcm2048_device *bdev) -{ - int err; - u8 lsb = 0, msb = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MATCH0, &lsb); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_RDS_PI_MATCH1, &msb); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(msb, lsb); - - return err; -} - -static int bcm2048_set_fm_rds_mask(struct bcm2048_device *bdev, u16 mask) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK0, lsb(mask)); - err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, msb(mask)); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_rds_mask(struct bcm2048_device *bdev) -{ - int err; - u8 value0 = 0, value1 = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK0, &value0); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK1, &value1); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(value1, value0); - - return err; -} - -static int bcm2048_get_fm_rds_flags(struct bcm2048_device *bdev) -{ - int err; - u8 value0 = 0, value1 = 0; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &value0); - err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &value1); - - mutex_unlock(&bdev->mutex); - - if (!err) - return compose_u16(value1, value0); - - return err; -} - -static int bcm2048_get_region_bottom_frequency(struct bcm2048_device *bdev) -{ - return bdev->region_info.bottom_frequency; -} - -static int bcm2048_get_region_top_frequency(struct bcm2048_device *bdev) -{ - return bdev->region_info.top_frequency; -} - -static int bcm2048_set_fm_best_tune_mode(struct bcm2048_device *bdev, u8 mode) -{ - int err; - u8 value = 0; - - mutex_lock(&bdev->mutex); - - /* Perform read as the manual indicates */ - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, - &value); - value &= ~BCM2048_BEST_TUNE_MODE; - - if (mode) - value |= BCM2048_BEST_TUNE_MODE; - err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, - value); - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_fm_best_tune_mode(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, - &value); - - mutex_unlock(&bdev->mutex); - - if (!err && (value & BCM2048_BEST_TUNE_MODE)) - return BCM2048_ITEM_ENABLED; - - return err; -} - -static int bcm2048_get_fm_carrier_error(struct bcm2048_device *bdev) -{ - int err = 0; - s8 value; - - mutex_lock(&bdev->mutex); - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CARRIER, &value); - mutex_unlock(&bdev->mutex); - - if (!err) - return value; - - return err; -} - -static int bcm2048_get_fm_rssi(struct bcm2048_device *bdev) -{ - int err; - s8 value; - - mutex_lock(&bdev->mutex); - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RSSI, &value); - mutex_unlock(&bdev->mutex); - - if (!err) - return value; - - return err; -} - -static int bcm2048_set_rds_wline(struct bcm2048_device *bdev, u8 wline) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_WLINE, wline); - - if (!err) - bdev->fifo_size = wline; - - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_wline(struct bcm2048_device *bdev) -{ - int err; - u8 value; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_WLINE, &value); - - mutex_unlock(&bdev->mutex); - - if (!err) { - bdev->fifo_size = value; - return value; - } - - return err; -} - -static int bcm2048_checkrev(struct bcm2048_device *bdev) -{ - int err; - u8 version; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_REV, &version); - - mutex_unlock(&bdev->mutex); - - if (!err) { - dev_info(&bdev->client->dev, "BCM2048 Version 0x%x\n", - version); - return version; - } - - return err; -} - -static int bcm2048_get_rds_rt(struct bcm2048_device *bdev, char *data) -{ - int err = 0, i, j = 0, ce = 0, cr = 0; - char data_buffer[BCM2048_MAX_RDS_RT + 1]; - - mutex_lock(&bdev->mutex); - - if (!bdev->rds_info.text_len) { - err = -EINVAL; - goto unlock; - } - - for (i = 0; i < BCM2048_MAX_RDS_RT; i++) { - if (bdev->rds_info.rds_rt[i]) { - ce = i; - /* Skip the carriage return */ - if (bdev->rds_info.rds_rt[i] != 0x0d) { - data_buffer[j++] = bdev->rds_info.rds_rt[i]; - } else { - cr = i; - break; - } - } - } - - if (j <= BCM2048_MAX_RDS_RT) - data_buffer[j] = 0; - - for (i = 0; i < BCM2048_MAX_RDS_RT; i++) { - if (!bdev->rds_info.rds_rt[i]) { - if (cr && (i < cr)) { - err = -EBUSY; - goto unlock; - } - if (i < ce) { - if (cr && (i >= cr)) - break; - err = -EBUSY; - goto unlock; - } - } - } - - memcpy(data, data_buffer, sizeof(data_buffer)); - -unlock: - mutex_unlock(&bdev->mutex); - return err; -} - -static int bcm2048_get_rds_ps(struct bcm2048_device *bdev, char *data) -{ - int err = 0, i, j = 0; - char data_buffer[BCM2048_MAX_RDS_PS + 1]; - - mutex_lock(&bdev->mutex); - - if (!bdev->rds_info.text_len) { - err = -EINVAL; - goto unlock; - } - - for (i = 0; i < BCM2048_MAX_RDS_PS; i++) { - if (bdev->rds_info.rds_ps[i]) { - data_buffer[j++] = bdev->rds_info.rds_ps[i]; - } else { - if (i < (BCM2048_MAX_RDS_PS - 1)) { - err = -EBUSY; - goto unlock; - } - } - } - - if (j <= BCM2048_MAX_RDS_PS) - data_buffer[j] = 0; - - memcpy(data, data_buffer, sizeof(data_buffer)); - -unlock: - mutex_unlock(&bdev->mutex); - return err; -} - -static void bcm2048_parse_rds_pi(struct bcm2048_device *bdev) -{ - int i, cnt = 0; - u16 pi; - - for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { - /* Block A match, only data without crc errors taken */ - if (bdev->rds_info.radio_text[i] == BCM2048_RDS_BLOCK_A) { - pi = (bdev->rds_info.radio_text[i + 1] << 8) + - bdev->rds_info.radio_text[i + 2]; - - if (!bdev->rds_info.rds_pi) { - bdev->rds_info.rds_pi = pi; - return; - } - if (pi != bdev->rds_info.rds_pi) { - cnt++; - if (cnt > 3) { - bdev->rds_info.rds_pi = pi; - cnt = 0; - } - } else { - cnt = 0; - } - } - } -} - -static int bcm2048_rds_block_crc(struct bcm2048_device *bdev, int i) -{ - return bdev->rds_info.radio_text[i] & BCM2048_RDS_CRC_MASK; -} - -static void bcm2048_parse_rds_rt_block(struct bcm2048_device *bdev, int i, - int index, int crc) -{ - /* Good data will overwrite poor data */ - if (crc) { - if (!bdev->rds_info.rds_rt[index]) - bdev->rds_info.rds_rt[index] = - bdev->rds_info.radio_text[i + 1]; - if (!bdev->rds_info.rds_rt[index + 1]) - bdev->rds_info.rds_rt[index + 1] = - bdev->rds_info.radio_text[i + 2]; - } else { - bdev->rds_info.rds_rt[index] = - bdev->rds_info.radio_text[i + 1]; - bdev->rds_info.rds_rt[index + 1] = - bdev->rds_info.radio_text[i + 2]; - } -} - -static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i) -{ - int crc, rt_id, rt_group_b, rt_ab, index = 0; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return -EIO; - - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_B) { - rt_id = bdev->rds_info.radio_text[i + 1] & - BCM2048_RDS_BLOCK_MASK; - rt_group_b = bdev->rds_info.radio_text[i + 1] & - BCM2048_RDS_GROUP_AB_MASK; - rt_ab = bdev->rds_info.radio_text[i + 2] & - BCM2048_RDS_RT_AB_MASK; - - if (rt_group_b != bdev->rds_info.rds_rt_group_b) { - memset(bdev->rds_info.rds_rt, 0, - sizeof(bdev->rds_info.rds_rt)); - bdev->rds_info.rds_rt_group_b = rt_group_b; - } - - if (rt_id == BCM2048_RDS_RT) { - /* A to B or (vice versa), means: clear screen */ - if (rt_ab != bdev->rds_info.rds_rt_ab) { - memset(bdev->rds_info.rds_rt, 0, - sizeof(bdev->rds_info.rds_rt)); - bdev->rds_info.rds_rt_ab = rt_ab; - } - - index = bdev->rds_info.radio_text[i + 2] & - BCM2048_RDS_RT_INDEX; - - if (bdev->rds_info.rds_rt_group_b) - index <<= 1; - else - index <<= 2; - - return index; - } - } - - return -EIO; -} - -static int bcm2048_parse_rt_match_c(struct bcm2048_device *bdev, int i, - int index) -{ - int crc; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return 0; - - if ((index + 2) >= BCM2048_MAX_RDS_RT) { - dev_err(&bdev->client->dev, - "Incorrect index = %d\n", index); - return 0; - } - - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_C) { - if (bdev->rds_info.rds_rt_group_b) - return 1; - bcm2048_parse_rds_rt_block(bdev, i, index, crc); - return 1; - } - - return 0; -} - -static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i, - int index) -{ - int crc; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return; - - if ((index + 4) >= BCM2048_MAX_RDS_RT) { - dev_err(&bdev->client->dev, - "Incorrect index = %d\n", index); - return; - } - - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_D) - bcm2048_parse_rds_rt_block(bdev, i, index + 2, crc); -} - -static void bcm2048_parse_rds_rt(struct bcm2048_device *bdev) -{ - int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0; - - for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { - if (match_b) { - match_b = 0; - index = bcm2048_parse_rt_match_b(bdev, i); - if (index >= 0 && index <= (BCM2048_MAX_RDS_RT - 5)) - match_c = 1; - continue; - } else if (match_c) { - match_c = 0; - if (bcm2048_parse_rt_match_c(bdev, i, index)) - match_d = 1; - continue; - } else if (match_d) { - match_d = 0; - bcm2048_parse_rt_match_d(bdev, i, index); - continue; - } - - /* Skip erroneous blocks due to messed up A block altogether */ - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_A) { - crc = bcm2048_rds_block_crc(bdev, i); - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - continue; - /* Synchronize to a good RDS PI */ - if (((bdev->rds_info.radio_text[i + 1] << 8) + - bdev->rds_info.radio_text[i + 2]) == - bdev->rds_info.rds_pi) - match_b = 1; - } - } -} - -static void bcm2048_parse_rds_ps_block(struct bcm2048_device *bdev, int i, - int index, int crc) -{ - /* Good data will overwrite poor data */ - if (crc) { - if (!bdev->rds_info.rds_ps[index]) - bdev->rds_info.rds_ps[index] = - bdev->rds_info.radio_text[i + 1]; - if (!bdev->rds_info.rds_ps[index + 1]) - bdev->rds_info.rds_ps[index + 1] = - bdev->rds_info.radio_text[i + 2]; - } else { - bdev->rds_info.rds_ps[index] = - bdev->rds_info.radio_text[i + 1]; - bdev->rds_info.rds_ps[index + 1] = - bdev->rds_info.radio_text[i + 2]; - } -} - -static int bcm2048_parse_ps_match_c(struct bcm2048_device *bdev, int i, - int index) -{ - int crc; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return 0; - - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_C) - return 1; - - return 0; -} - -static void bcm2048_parse_ps_match_d(struct bcm2048_device *bdev, int i, - int index) -{ - int crc; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return; - - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_D) - bcm2048_parse_rds_ps_block(bdev, i, index, crc); -} - -static int bcm2048_parse_ps_match_b(struct bcm2048_device *bdev, int i) -{ - int crc, index, ps_id, ps_group; - - crc = bcm2048_rds_block_crc(bdev, i); - - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - return -EIO; - - /* Block B Radio PS match */ - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_B) { - ps_id = bdev->rds_info.radio_text[i + 1] & - BCM2048_RDS_BLOCK_MASK; - ps_group = bdev->rds_info.radio_text[i + 1] & - BCM2048_RDS_GROUP_AB_MASK; - - /* - * Poor RSSI will lead to RDS data corruption - * So using 3 (same) sequential values to justify major changes - */ - if (ps_group != bdev->rds_info.rds_ps_group) { - if (crc == BCM2048_RDS_CRC_NONE) { - bdev->rds_info.rds_ps_group_cnt++; - if (bdev->rds_info.rds_ps_group_cnt > 2) { - bdev->rds_info.rds_ps_group = ps_group; - bdev->rds_info.rds_ps_group_cnt = 0; - dev_err(&bdev->client->dev, - "RDS PS Group change!\n"); - } else { - return -EIO; - } - } else { - bdev->rds_info.rds_ps_group_cnt = 0; - } - } - - if (ps_id == BCM2048_RDS_PS) { - index = bdev->rds_info.radio_text[i + 2] & - BCM2048_RDS_PS_INDEX; - index <<= 1; - return index; - } - } - - return -EIO; -} - -static void bcm2048_parse_rds_ps(struct bcm2048_device *bdev) -{ - int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0; - - for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { - if (match_b) { - match_b = 0; - index = bcm2048_parse_ps_match_b(bdev, i); - if (index >= 0 && index < (BCM2048_MAX_RDS_PS - 1)) - match_c = 1; - continue; - } else if (match_c) { - match_c = 0; - if (bcm2048_parse_ps_match_c(bdev, i, index)) - match_d = 1; - continue; - } else if (match_d) { - match_d = 0; - bcm2048_parse_ps_match_d(bdev, i, index); - continue; - } - - /* Skip erroneous blocks due to messed up A block altogether */ - if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == - BCM2048_RDS_BLOCK_A) { - crc = bcm2048_rds_block_crc(bdev, i); - if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) - continue; - /* Synchronize to a good RDS PI */ - if (((bdev->rds_info.radio_text[i + 1] << 8) + - bdev->rds_info.radio_text[i + 2]) == - bdev->rds_info.rds_pi) - match_b = 1; - } - } -} - -static void bcm2048_rds_fifo_receive(struct bcm2048_device *bdev) -{ - int err; - - mutex_lock(&bdev->mutex); - - err = bcm2048_recv_duples(bdev, BCM2048_I2C_RDS_DATA, - bdev->rds_info.radio_text, bdev->fifo_size); - if (err != 2) { - dev_err(&bdev->client->dev, "RDS Read problem\n"); - mutex_unlock(&bdev->mutex); - return; - } - - bdev->rds_info.text_len = bdev->fifo_size; - - bcm2048_parse_rds_pi(bdev); - bcm2048_parse_rds_rt(bdev); - bcm2048_parse_rds_ps(bdev); - - mutex_unlock(&bdev->mutex); - - wake_up_interruptible(&bdev->read_queue); -} - -static int bcm2048_get_rds_data(struct bcm2048_device *bdev, char *data) -{ - int err = 0, i, p = 0; - char *data_buffer; - - mutex_lock(&bdev->mutex); - - if (!bdev->rds_info.text_len) { - err = -EINVAL; - goto unlock; - } - - data_buffer = kcalloc(BCM2048_MAX_RDS_RADIO_TEXT, 5, GFP_KERNEL); - if (!data_buffer) { - err = -ENOMEM; - goto unlock; - } - - for (i = 0; i < bdev->rds_info.text_len; i++) { - p += sprintf(data_buffer + p, "%x ", - bdev->rds_info.radio_text[i]); - } - - memcpy(data, data_buffer, p); - kfree(data_buffer); - -unlock: - mutex_unlock(&bdev->mutex); - return err; -} - -/* - * BCM2048 default initialization sequence - */ -static int bcm2048_init(struct bcm2048_device *bdev) -{ - int err; - - err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON); - if (err < 0) - goto exit; - - err = bcm2048_set_audio_route(bdev, BCM2048_AUDIO_ROUTE_DAC); - if (err < 0) - goto exit; - - err = bcm2048_set_dac_output(bdev, BCM2048_DAC_OUTPUT_LEFT | - BCM2048_DAC_OUTPUT_RIGHT); - -exit: - return err; -} - -/* - * BCM2048 default deinitialization sequence - */ -static int bcm2048_deinit(struct bcm2048_device *bdev) -{ - int err; - - err = bcm2048_set_audio_route(bdev, 0); - if (err < 0) - return err; - - err = bcm2048_set_dac_output(bdev, 0); - if (err < 0) - return err; - - return bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); -} - -/* - * BCM2048 probe sequence - */ -static int bcm2048_probe(struct bcm2048_device *bdev) -{ - int err; - - err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON); - if (err < 0) - goto unlock; - - err = bcm2048_checkrev(bdev); - if (err < 0) - goto unlock; - - err = bcm2048_set_mute(bdev, BCM2048_DEFAULT_MUTE); - if (err < 0) - goto unlock; - - err = bcm2048_set_region(bdev, BCM2048_DEFAULT_REGION); - if (err < 0) - goto unlock; - - err = bcm2048_set_fm_search_rssi_threshold(bdev, - BCM2048_DEFAULT_RSSI_THRESHOLD); - if (err < 0) - goto unlock; - - err = bcm2048_set_fm_automatic_stereo_mono(bdev, BCM2048_ITEM_ENABLED); - if (err < 0) - goto unlock; - - err = bcm2048_get_rds_wline(bdev); - if (err < BCM2048_DEFAULT_RDS_WLINE) - err = bcm2048_set_rds_wline(bdev, BCM2048_DEFAULT_RDS_WLINE); - if (err < 0) - goto unlock; - - err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); - - init_waitqueue_head(&bdev->read_queue); - bdev->rds_data_available = 0; - bdev->rd_index = 0; - bdev->users = 0; - -unlock: - return err; -} - -/* - * BCM2048 workqueue handler - */ -static void bcm2048_work(struct work_struct *work) -{ - struct bcm2048_device *bdev; - u8 flag_lsb = 0, flag_msb = 0, flags; - - bdev = container_of(work, struct bcm2048_device, work); - bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &flag_lsb); - bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &flag_msb); - - if (flag_lsb & (BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED | - BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)) { - if (flag_lsb & BCM2048_FM_FLAG_SEARCH_TUNE_FAIL) - bdev->scan_state = BCM2048_SCAN_FAIL; - else - bdev->scan_state = BCM2048_SCAN_OK; - - complete(&bdev->compl); - } - - if (flag_msb & BCM2048_RDS_FLAG_FIFO_WLINE) { - bcm2048_rds_fifo_receive(bdev); - if (bdev->rds_state) { - flags = BCM2048_RDS_FLAG_FIFO_WLINE; - bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, - flags); - } - bdev->rds_data_available = 1; - bdev->rd_index = 0; /* new data, new start */ - } -} - -/* - * BCM2048 interrupt handler - */ -static irqreturn_t bcm2048_handler(int irq, void *dev) -{ - struct bcm2048_device *bdev = dev; - - dev_dbg(&bdev->client->dev, "IRQ called, queuing work\n"); - if (bdev->power_state) - schedule_work(&bdev->work); - - return IRQ_HANDLED; -} - -/* - * BCM2048 sysfs interface definitions - */ -#define property_write(prop, type, mask, check) \ -static ssize_t bcm2048_##prop##_write(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, \ - size_t count) \ -{ \ - struct bcm2048_device *bdev = dev_get_drvdata(dev); \ - type value; \ - int err; \ - \ - if (!bdev) \ - return -ENODEV; \ - \ - if (sscanf(buf, mask, &value) != 1) \ - return -EINVAL; \ - \ - if (check) \ - return -EDOM; \ - \ - err = bcm2048_set_##prop(bdev, value); \ - \ - return err < 0 ? err : count; \ -} - -#define property_read(prop, mask) \ -static ssize_t bcm2048_##prop##_read(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct bcm2048_device *bdev = dev_get_drvdata(dev); \ - int value; \ - \ - if (!bdev) \ - return -ENODEV; \ - \ - value = bcm2048_get_##prop(bdev); \ - \ - if (value >= 0) \ - value = sprintf(buf, mask "\n", value); \ - \ - return value; \ -} - -#define property_signed_read(prop, size, mask) \ -static ssize_t bcm2048_##prop##_read(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct bcm2048_device *bdev = dev_get_drvdata(dev); \ - size value; \ - \ - if (!bdev) \ - return -ENODEV; \ - \ - value = bcm2048_get_##prop(bdev); \ - \ - return sprintf(buf, mask "\n", value); \ -} - -#define DEFINE_SYSFS_PROPERTY(prop, prop_type, mask, check) \ -property_write(prop, prop_type, mask, check) \ -property_read(prop, mask) \ - -#define property_str_read(prop, size) \ -static ssize_t bcm2048_##prop##_read(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct bcm2048_device *bdev = dev_get_drvdata(dev); \ - int count; \ - u8 *out; \ - \ - if (!bdev) \ - return -ENODEV; \ - \ - out = kzalloc((size) + 1, GFP_KERNEL); \ - if (!out) \ - return -ENOMEM; \ - \ - bcm2048_get_##prop(bdev, out); \ - count = sprintf(buf, "%s\n", out); \ - \ - kfree(out); \ - \ - return count; \ -} - -DEFINE_SYSFS_PROPERTY(power_state, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(mute, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(audio_route, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(dac_output, unsigned int, "%u", 0) - -DEFINE_SYSFS_PROPERTY(fm_hi_lo_injection, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_frequency, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_af_frequency, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_deemphasis, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_rds_mask, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_best_tune_mode, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_search_rssi_threshold, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_search_mode_direction, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(fm_search_tune_mode, unsigned int, "%u", value > 3) - -DEFINE_SYSFS_PROPERTY(rds, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(rds_b_block_mask, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(rds_b_block_match, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(rds_pi_mask, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(rds_pi_match, unsigned int, "%u", 0) -DEFINE_SYSFS_PROPERTY(rds_wline, unsigned int, "%u", 0) -property_read(rds_pi, "%x") -property_str_read(rds_rt, (BCM2048_MAX_RDS_RT + 1)) -property_str_read(rds_ps, (BCM2048_MAX_RDS_PS + 1)) - -property_read(fm_rds_flags, "%u") -property_str_read(rds_data, BCM2048_MAX_RDS_RADIO_TEXT * 5) - -property_read(region_bottom_frequency, "%u") -property_read(region_top_frequency, "%u") -property_signed_read(fm_carrier_error, int, "%d") -property_signed_read(fm_rssi, int, "%d") -DEFINE_SYSFS_PROPERTY(region, unsigned int, "%u", 0) - -static struct device_attribute attrs[] = { - __ATTR(power_state, 0644, bcm2048_power_state_read, - bcm2048_power_state_write), - __ATTR(mute, 0644, bcm2048_mute_read, - bcm2048_mute_write), - __ATTR(audio_route, 0644, bcm2048_audio_route_read, - bcm2048_audio_route_write), - __ATTR(dac_output, 0644, bcm2048_dac_output_read, - bcm2048_dac_output_write), - __ATTR(fm_hi_lo_injection, 0644, - bcm2048_fm_hi_lo_injection_read, - bcm2048_fm_hi_lo_injection_write), - __ATTR(fm_frequency, 0644, bcm2048_fm_frequency_read, - bcm2048_fm_frequency_write), - __ATTR(fm_af_frequency, 0644, - bcm2048_fm_af_frequency_read, - bcm2048_fm_af_frequency_write), - __ATTR(fm_deemphasis, 0644, bcm2048_fm_deemphasis_read, - bcm2048_fm_deemphasis_write), - __ATTR(fm_rds_mask, 0644, bcm2048_fm_rds_mask_read, - bcm2048_fm_rds_mask_write), - __ATTR(fm_best_tune_mode, 0644, - bcm2048_fm_best_tune_mode_read, - bcm2048_fm_best_tune_mode_write), - __ATTR(fm_search_rssi_threshold, 0644, - bcm2048_fm_search_rssi_threshold_read, - bcm2048_fm_search_rssi_threshold_write), - __ATTR(fm_search_mode_direction, 0644, - bcm2048_fm_search_mode_direction_read, - bcm2048_fm_search_mode_direction_write), - __ATTR(fm_search_tune_mode, 0644, - bcm2048_fm_search_tune_mode_read, - bcm2048_fm_search_tune_mode_write), - __ATTR(rds, 0644, bcm2048_rds_read, - bcm2048_rds_write), - __ATTR(rds_b_block_mask, 0644, - bcm2048_rds_b_block_mask_read, - bcm2048_rds_b_block_mask_write), - __ATTR(rds_b_block_match, 0644, - bcm2048_rds_b_block_match_read, - bcm2048_rds_b_block_match_write), - __ATTR(rds_pi_mask, 0644, bcm2048_rds_pi_mask_read, - bcm2048_rds_pi_mask_write), - __ATTR(rds_pi_match, 0644, bcm2048_rds_pi_match_read, - bcm2048_rds_pi_match_write), - __ATTR(rds_wline, 0644, bcm2048_rds_wline_read, - bcm2048_rds_wline_write), - __ATTR(rds_pi, 0444, bcm2048_rds_pi_read, NULL), - __ATTR(rds_rt, 0444, bcm2048_rds_rt_read, NULL), - __ATTR(rds_ps, 0444, bcm2048_rds_ps_read, NULL), - __ATTR(fm_rds_flags, 0444, bcm2048_fm_rds_flags_read, NULL), - __ATTR(region_bottom_frequency, 0444, - bcm2048_region_bottom_frequency_read, NULL), - __ATTR(region_top_frequency, 0444, - bcm2048_region_top_frequency_read, NULL), - __ATTR(fm_carrier_error, 0444, - bcm2048_fm_carrier_error_read, NULL), - __ATTR(fm_rssi, 0444, - bcm2048_fm_rssi_read, NULL), - __ATTR(region, 0644, bcm2048_region_read, - bcm2048_region_write), - __ATTR(rds_data, 0444, bcm2048_rds_data_read, NULL), -}; - -static int bcm2048_sysfs_unregister_properties(struct bcm2048_device *bdev, - int size) -{ - int i; - - for (i = 0; i < size; i++) - device_remove_file(&bdev->client->dev, &attrs[i]); - - return 0; -} - -static int bcm2048_sysfs_register_properties(struct bcm2048_device *bdev) -{ - int err = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(attrs); i++) { - if (device_create_file(&bdev->client->dev, &attrs[i]) != 0) { - dev_err(&bdev->client->dev, - "could not register sysfs entry\n"); - err = -EBUSY; - bcm2048_sysfs_unregister_properties(bdev, i); - break; - } - } - - return err; -} - -static int bcm2048_fops_open(struct file *file) -{ - struct bcm2048_device *bdev = video_drvdata(file); - - bdev->users++; - bdev->rd_index = 0; - bdev->rds_data_available = 0; - - return 0; -} - -static int bcm2048_fops_release(struct file *file) -{ - struct bcm2048_device *bdev = video_drvdata(file); - - bdev->users--; - - return 0; -} - -static __poll_t bcm2048_fops_poll(struct file *file, - struct poll_table_struct *pts) -{ - struct bcm2048_device *bdev = video_drvdata(file); - __poll_t retval = 0; - - poll_wait(file, &bdev->read_queue, pts); - - if (bdev->rds_data_available) - retval = EPOLLIN | EPOLLRDNORM; - - return retval; -} - -static ssize_t bcm2048_fops_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct bcm2048_device *bdev = video_drvdata(file); - int i; - int retval = 0; - - /* we return at least 3 bytes, one block */ - count = (count / 3) * 3; /* only multiples of 3 */ - if (count < 3) - return -ENOBUFS; - - while (!bdev->rds_data_available) { - if (file->f_flags & O_NONBLOCK) { - retval = -EWOULDBLOCK; - goto done; - } - /* interruptible_sleep_on(&bdev->read_queue); */ - if (wait_event_interruptible(bdev->read_queue, - bdev->rds_data_available) < 0) { - retval = -EINTR; - goto done; - } - } - - mutex_lock(&bdev->mutex); - /* copy data to userspace */ - i = bdev->fifo_size - bdev->rd_index; - if (count > i) - count = (i / 3) * 3; - - i = 0; - while (i < count) { - unsigned char tmpbuf[3]; - - tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index + i + 2]; - tmpbuf[i + 1] = - bdev->rds_info.radio_text[bdev->rd_index + i + 1]; - tmpbuf[i + 2] = - (bdev->rds_info.radio_text[bdev->rd_index + i] & - 0xf0) >> 4; - if ((bdev->rds_info.radio_text[bdev->rd_index + i] & - BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE) - tmpbuf[i + 2] |= 0x80; - if (copy_to_user(buf + i, tmpbuf, 3)) { - retval = -EFAULT; - break; - } - i += 3; - } - - bdev->rd_index += i; - if (bdev->rd_index >= bdev->fifo_size) - bdev->rds_data_available = 0; - - mutex_unlock(&bdev->mutex); - if (retval == 0) - retval = i; - -done: - return retval; -} - -/* - * bcm2048_fops - file operations interface - */ -static const struct v4l2_file_operations bcm2048_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, - /* for RDS read support */ - .open = bcm2048_fops_open, - .release = bcm2048_fops_release, - .read = bcm2048_fops_read, - .poll = bcm2048_fops_poll -}; - -/* - * Video4Linux Interface - */ -static struct v4l2_queryctrl bcm2048_v4l2_queryctrl[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BALANCE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BASS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_TREBLE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, - { - .id = V4L2_CID_AUDIO_LOUDNESS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, -}; - -static int bcm2048_vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *capability) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - - strscpy(capability->driver, BCM2048_DRIVER_NAME, - sizeof(capability->driver)); - strscpy(capability->card, BCM2048_DRIVER_CARD, - sizeof(capability->card)); - snprintf(capability->bus_info, 32, "I2C: 0x%X", bdev->client->addr); - return 0; -} - -static int bcm2048_vidioc_g_input(struct file *filp, void *priv, - unsigned int *i) -{ - *i = 0; - - return 0; -} - -static int bcm2048_vidioc_s_input(struct file *filp, void *priv, - unsigned int i) -{ - if (i) - return -EINVAL; - - return 0; -} - -static int bcm2048_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bcm2048_v4l2_queryctrl); i++) { - if (qc->id && qc->id == bcm2048_v4l2_queryctrl[i].id) { - *qc = bcm2048_v4l2_queryctrl[i]; - return 0; - } - } - - return -EINVAL; -} - -static int bcm2048_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - int err = 0; - - if (!bdev) - return -ENODEV; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - err = bcm2048_get_mute(bdev); - if (err >= 0) - ctrl->value = err; - break; - } - - return err; -} - -static int bcm2048_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - int err = 0; - - if (!bdev) - return -ENODEV; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - if (bdev->power_state) { - err = bcm2048_set_mute(bdev, ctrl->value); - err |= bcm2048_deinit(bdev); - } - } else { - if (!bdev->power_state) { - err = bcm2048_init(bdev); - err |= bcm2048_set_mute(bdev, ctrl->value); - } - } - break; - } - - return err; -} - -static int bcm2048_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - if (audio->index > 1) - return -EINVAL; - - strscpy(audio->name, "Radio", sizeof(audio->name)); - audio->capability = V4L2_AUDCAP_STEREO; - - return 0; -} - -static int bcm2048_vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *audio) -{ - if (audio->index != 0) - return -EINVAL; - - return 0; -} - -static int bcm2048_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - s8 f_error; - s8 rssi; - - if (!bdev) - return -ENODEV; - - if (tuner->index > 0) - return -EINVAL; - - strscpy(tuner->name, "FM Receiver", sizeof(tuner->name)); - tuner->type = V4L2_TUNER_RADIO; - tuner->rangelow = - dev_to_v4l2(bcm2048_get_region_bottom_frequency(bdev)); - tuner->rangehigh = - dev_to_v4l2(bcm2048_get_region_top_frequency(bdev)); - tuner->rxsubchans = V4L2_TUNER_SUB_STEREO; - tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; - tuner->audmode = V4L2_TUNER_MODE_STEREO; - tuner->afc = 0; - if (bdev->power_state) { - /* - * Report frequencies with high carrier errors to have zero - * signal level - */ - f_error = bcm2048_get_fm_carrier_error(bdev); - if (f_error < BCM2048_FREQ_ERROR_FLOOR || - f_error > BCM2048_FREQ_ERROR_ROOF) { - tuner->signal = 0; - } else { - /* - * RSSI level -60 dB is defined to report full - * signal strength - */ - rssi = bcm2048_get_fm_rssi(bdev); - if (rssi >= BCM2048_RSSI_LEVEL_BASE) { - tuner->signal = 0xFFFF; - } else if (rssi > BCM2048_RSSI_LEVEL_ROOF) { - tuner->signal = (rssi + - BCM2048_RSSI_LEVEL_ROOF_NEG) - * BCM2048_SIGNAL_MULTIPLIER; - } else { - tuner->signal = 0; - } - } - } else { - tuner->signal = 0; - } - - return 0; -} - -static int bcm2048_vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *tuner) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - - if (!bdev) - return -ENODEV; - - if (tuner->index > 0) - return -EINVAL; - - return 0; -} - -static int bcm2048_vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - int err = 0; - int f; - - if (!bdev->power_state) - return -ENODEV; - - freq->type = V4L2_TUNER_RADIO; - f = bcm2048_get_fm_frequency(bdev); - - if (f < 0) - err = f; - else - freq->frequency = dev_to_v4l2(f); - - return err; -} - -static int bcm2048_vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *freq) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - int err; - - if (freq->type != V4L2_TUNER_RADIO) - return -EINVAL; - - if (!bdev->power_state) - return -ENODEV; - - err = bcm2048_set_fm_frequency(bdev, v4l2_to_dev(freq->frequency)); - err |= bcm2048_set_fm_search_tune_mode(bdev, BCM2048_FM_PRE_SET_MODE); - - return err; -} - -static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv, - const struct v4l2_hw_freq_seek *seek) -{ - struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - int err; - - if (!bdev->power_state) - return -ENODEV; - - if ((seek->tuner != 0) || (seek->type != V4L2_TUNER_RADIO)) - return -EINVAL; - - err = bcm2048_set_fm_search_mode_direction(bdev, seek->seek_upward); - err |= bcm2048_set_fm_search_tune_mode(bdev, - BCM2048_FM_AUTO_SEARCH_MODE); - - return err; -} - -static const struct v4l2_ioctl_ops bcm2048_ioctl_ops = { - .vidioc_querycap = bcm2048_vidioc_querycap, - .vidioc_g_input = bcm2048_vidioc_g_input, - .vidioc_s_input = bcm2048_vidioc_s_input, - .vidioc_queryctrl = bcm2048_vidioc_queryctrl, - .vidioc_g_ctrl = bcm2048_vidioc_g_ctrl, - .vidioc_s_ctrl = bcm2048_vidioc_s_ctrl, - .vidioc_g_audio = bcm2048_vidioc_g_audio, - .vidioc_s_audio = bcm2048_vidioc_s_audio, - .vidioc_g_tuner = bcm2048_vidioc_g_tuner, - .vidioc_s_tuner = bcm2048_vidioc_s_tuner, - .vidioc_g_frequency = bcm2048_vidioc_g_frequency, - .vidioc_s_frequency = bcm2048_vidioc_s_frequency, - .vidioc_s_hw_freq_seek = bcm2048_vidioc_s_hw_freq_seek, -}; - -/* - * bcm2048_viddev_template - video device interface - */ -static const struct video_device bcm2048_viddev_template = { - .fops = &bcm2048_fops, - .name = BCM2048_DRIVER_NAME, - .release = video_device_release_empty, - .ioctl_ops = &bcm2048_ioctl_ops, - .device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | - V4L2_CAP_HW_FREQ_SEEK, -}; - -/* - * I2C driver interface - */ -static int bcm2048_i2c_driver_probe(struct i2c_client *client) -{ - struct bcm2048_device *bdev; - int err; - - bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); - if (!bdev) { - err = -ENOMEM; - goto exit; - } - - bdev->client = client; - i2c_set_clientdata(client, bdev); - mutex_init(&bdev->mutex); - init_completion(&bdev->compl); - INIT_WORK(&bdev->work, bcm2048_work); - - if (client->irq) { - err = request_irq(client->irq, - bcm2048_handler, IRQF_TRIGGER_FALLING, - client->name, bdev); - if (err < 0) { - dev_err(&client->dev, "Could not request IRQ\n"); - goto free_bdev; - } - dev_dbg(&client->dev, "IRQ requested.\n"); - } else { - dev_dbg(&client->dev, "IRQ not configured. Using timeouts.\n"); - } - - bdev->videodev = bcm2048_viddev_template; - video_set_drvdata(&bdev->videodev, bdev); - if (video_register_device(&bdev->videodev, VFL_TYPE_RADIO, radio_nr)) { - dev_dbg(&client->dev, "Could not register video device.\n"); - err = -EIO; - goto free_irq; - } - - err = bcm2048_sysfs_register_properties(bdev); - if (err < 0) { - dev_dbg(&client->dev, "Could not register sysfs interface.\n"); - goto free_registration; - } - - err = bcm2048_probe(bdev); - if (err < 0) { - dev_dbg(&client->dev, "Failed to probe device information.\n"); - goto free_sysfs; - } - - return 0; - -free_sysfs: - bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs)); -free_registration: - video_unregister_device(&bdev->videodev); -free_irq: - if (client->irq) - free_irq(client->irq, bdev); -free_bdev: - i2c_set_clientdata(client, NULL); - kfree(bdev); -exit: - return err; -} - -static int bcm2048_i2c_driver_remove(struct i2c_client *client) -{ - struct bcm2048_device *bdev = i2c_get_clientdata(client); - - if (!client->adapter) - return -ENODEV; - - if (bdev) { - bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs)); - video_unregister_device(&bdev->videodev); - - if (bdev->power_state) - bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); - - if (client->irq > 0) - free_irq(client->irq, bdev); - - cancel_work_sync(&bdev->work); - - kfree(bdev); - } - - return 0; -} - -/* - * bcm2048_i2c_driver - i2c driver interface - */ -static const struct i2c_device_id bcm2048_id[] = { - { "bcm2048", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, bcm2048_id); - -static struct i2c_driver bcm2048_i2c_driver = { - .driver = { - .name = BCM2048_DRIVER_NAME, - }, - .probe_new = bcm2048_i2c_driver_probe, - .remove = bcm2048_i2c_driver_remove, - .id_table = bcm2048_id, -}; - -module_i2c_driver(bcm2048_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR(BCM2048_DRIVER_AUTHOR); -MODULE_DESCRIPTION(BCM2048_DRIVER_DESC); -MODULE_VERSION("0.0.2"); diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.h b/drivers/staging/media/bcm2048/radio-bcm2048.h deleted file mode 100644 index 22887a075257..000000000000 --- a/drivers/staging/media/bcm2048/radio-bcm2048.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * drivers/staging/media/radio-bcm2048.h - * - * Property and command definitions for bcm2048 radio receiver chip. - * - * Copyright (C) Nokia Corporation - * Contact: Eero Nurkkala - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef BCM2048_H -#define BCM2048_H - -#define BCM2048_NAME "bcm2048" -#define BCM2048_I2C_ADDR 0x22 - -#endif /* ifndef BCM2048_H */ -- GitLab From 4ee222406740f0c39e00b12f51eda8133e35ee83 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 25 Jul 2019 03:30:23 -0400 Subject: [PATCH 0576/7155] media: staging: davinci: remove vpfe driver The davinci_vpfe driver was merged into staging back in 2012 by Manjunath Hadli from TI, with a long TODO list. For all I can tell, since then it has only seen fixes for compile-time issues and global cleanups, but nobody has actually worked on the items on the TODO list. To make things worse, the driver in its current form is incompatible with the platform code in arch/arm/mach-davinci, i.e. the driver expects to get its platform_data passed to the device as a 'struct vpfe_config', but uses a differnet definition for that structure compared to what the platform uses. Finally, there is another driver for the same device in drivers/media/platform/davinci/vpfe_capture.c. From all I can tell, the staging version was originally a copy of a more featureful driver in TI's downstream kernels. However, that kernel no longer supports dm365 after linux-2.6.37, and the mainline version moved in a different direction. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/davinci_vpfe/Kconfig | 13 - drivers/staging/media/davinci_vpfe/Makefile | 11 - drivers/staging/media/davinci_vpfe/TODO | 38 - .../media/davinci_vpfe/davinci-vpfe-mc.txt | 154 -- .../media/davinci_vpfe/davinci_vpfe_user.h | 1287 ---------- .../staging/media/davinci_vpfe/dm365_ipipe.c | 1857 --------------- .../staging/media/davinci_vpfe/dm365_ipipe.h | 174 -- .../media/davinci_vpfe/dm365_ipipe_hw.c | 1038 -------- .../media/davinci_vpfe/dm365_ipipe_hw.h | 556 ----- .../media/davinci_vpfe/dm365_ipipeif.c | 1070 --------- .../media/davinci_vpfe/dm365_ipipeif.h | 228 -- .../media/davinci_vpfe/dm365_ipipeif_user.h | 90 - .../staging/media/davinci_vpfe/dm365_isif.c | 2097 ----------------- .../staging/media/davinci_vpfe/dm365_isif.h | 200 -- .../media/davinci_vpfe/dm365_isif_regs.h | 291 --- .../media/davinci_vpfe/dm365_resizer.c | 1995 ---------------- .../media/davinci_vpfe/dm365_resizer.h | 241 -- drivers/staging/media/davinci_vpfe/vpfe.h | 83 - .../media/davinci_vpfe/vpfe_mc_capture.c | 716 ------ .../media/davinci_vpfe/vpfe_mc_capture.h | 90 - .../staging/media/davinci_vpfe/vpfe_video.c | 1646 ------------- .../staging/media/davinci_vpfe/vpfe_video.h | 150 -- 24 files changed, 14028 deletions(-) delete mode 100644 drivers/staging/media/davinci_vpfe/Kconfig delete mode 100644 drivers/staging/media/davinci_vpfe/Makefile delete mode 100644 drivers/staging/media/davinci_vpfe/TODO delete mode 100644 drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt delete mode 100644 drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipe.c delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipe.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipeif.c delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipeif.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif.c delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_isif_regs.h delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_resizer.c delete mode 100644 drivers/staging/media/davinci_vpfe/dm365_resizer.h delete mode 100644 drivers/staging/media/davinci_vpfe/vpfe.h delete mode 100644 drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c delete mode 100644 drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h delete mode 100644 drivers/staging/media/davinci_vpfe/vpfe_video.c delete mode 100644 drivers/staging/media/davinci_vpfe/vpfe_video.h diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 45075f977f1b..642adc4c24d2 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -22,8 +22,6 @@ if STAGING_MEDIA && MEDIA_SUPPORT # Please keep them in alphabetic order source "drivers/staging/media/allegro-dvt/Kconfig" -source "drivers/staging/media/davinci_vpfe/Kconfig" - source "drivers/staging/media/hantro/Kconfig" source "drivers/staging/media/imx/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index c19cfed0b059..2f1711a8aeed 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro-dvt/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ -obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ diff --git a/drivers/staging/media/davinci_vpfe/Kconfig b/drivers/staging/media/davinci_vpfe/Kconfig deleted file mode 100644 index 94bf6746c03f..000000000000 --- a/drivers/staging/media/davinci_vpfe/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VIDEO_DM365_VPFE - tristate "DM365 VPFE Media Controller Capture Driver" - depends on VIDEO_V4L2 - depends on (ARCH_DAVINCI_DM365 && !VIDEO_DM365_ISIF) || (COMPILE_TEST && !ARCH_OMAP1) - depends on VIDEO_V4L2_SUBDEV_API - depends on VIDEO_DAVINCI_VPBE_DISPLAY - select VIDEOBUF2_DMA_CONTIG - help - Support for DM365 VPFE based Media Controller Capture driver. - - To compile this driver as a module, choose M here: the - module will be called vpfe-mc-capture. diff --git a/drivers/staging/media/davinci_vpfe/Makefile b/drivers/staging/media/davinci_vpfe/Makefile deleted file mode 100644 index 0ae8c5014f74..000000000000 --- a/drivers/staging/media/davinci_vpfe/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci-vfpe.o - -davinci-vfpe-objs := \ - dm365_isif.o dm365_ipipe_hw.o dm365_ipipe.o \ - dm365_resizer.o dm365_ipipeif.o vpfe_mc_capture.o vpfe_video.o - -# Allow building it with COMPILE_TEST on other archs -ifndef CONFIG_ARCH_DAVINCI -ccflags-y += -I $(srctree)/arch/arm/mach-davinci/include/ -endif diff --git a/drivers/staging/media/davinci_vpfe/TODO b/drivers/staging/media/davinci_vpfe/TODO deleted file mode 100644 index cc8bd9306f2a..000000000000 --- a/drivers/staging/media/davinci_vpfe/TODO +++ /dev/null @@ -1,38 +0,0 @@ -TODO (general): -================================== - -- User space interface refinement - - Controls should be used when possible rather than private ioctl - - No enums should be used - - Use of MC and V4L2 subdev APIs when applicable - - Single interface header might suffice - - Current interface forces to configure everything at once -- Get rid of the dm365_ipipe_hw.[ch] layer -- Active external sub-devices defined by link configuration; no strcmp - needed -- More generic platform data (i2c adapters) -- The driver should have no knowledge of possible external subdevs; see - struct vpfe_subdev_id -- Some of the hardware control should be refactorede -- Check proper serialisation (through mutexes and spinlocks) -- Names that are visible in kernel global namespace should have a common - prefix (or a few) -- While replacing the older driver in media folder, provide a compatibility - layer and compatibility tests that warrants (using the libv4l's LD_PRELOAD - approach) there is no regression for the users using the older driver. -- make it independent of arch-specific APIs (mach/mux.h). - -Building of uImage and Applications: -================================== - -As of now since the interface will undergo few changes all the include -files are present in staging itself, to build for dm365 follow below steps, - -- copy vpfe.h from drivers/staging/media/davinci_vpfe/ to - include/media/davinci/ folder for building the uImage. -- copy davinci_vpfe_user.h from drivers/staging/media/davinci_vpfe/ to - include/uapi/linux/davinci_vpfe.h, and add a entry in Kbuild (required - for building application). -- copy dm365_ipipeif_user.h from drivers/staging/media/davinci_vpfe/ to - include/uapi/linux/dm365_ipipeif.h and a entry in Kbuild (required - for building application). diff --git a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt b/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt deleted file mode 100644 index a1e91778aa9b..000000000000 --- a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt +++ /dev/null @@ -1,154 +0,0 @@ -Davinci Video processing Front End (VPFE) driver - -Copyright (C) 2012 Texas Instruments Inc - -Contacts: Manjunath Hadli - Prabhakar Lad - - -Introduction -============ - -This file documents the Texas Instruments Davinci Video processing Front End -(VPFE) driver located under drivers/media/platform/davinci. The original driver -exists for Davinci VPFE, which is now being changed to Media Controller -Framework. - -Currently the driver has been successfully used on the following -version of Davinci: - - DM365/DM368 - -The driver implements V4L2, Media controller and v4l2_subdev interfaces. Sensor, -lens and flash drivers using the v4l2_subdev interface in the kernel are -supported. - - -Split to subdevs -================ - -The Davinci VPFE is split into V4L2 subdevs, each of the blocks inside the VPFE -having one subdev to represent it. Each of the subdevs provide a V4L2 subdev -interface to userspace. - - DAVINCI ISIF - DAVINCI IPIPEIF - DAVINCI IPIPE - DAVINCI CROP RESIZER - DAVINCI RESIZER A - DAVINCI RESIZER B - -Each possible link in the VPFE is modelled by a link in the Media controller -interface. For an example program see [1]. - - -ISIF, IPIPE, and RESIZER block IOCTLs -====================================== - -The Davinci Video processing Front End (VPFE) driver supports standard V4L2 -IOCTLs and controls where possible and practical. Much of the functions provided -by the VPFE, however, does not fall under the standard IOCTL's. - -In general, there is a private ioctl for configuring each of the blocks -containing hardware-dependent functions. - -The following private IOCTLs are supported: - - VIDIOC_VPFE_ISIF_[S/G]_RAW_PARAMS - VIDIOC_VPFE_IPIPE_[S/G]_CONFIG - VIDIOC_VPFE_RSZ_[S/G]_CONFIG - -The parameter structures used by these ioctl's are described in -include/uapi/linux/davinci_vpfe.h. - -The VIDIOC_VPFE_ISIF_S_RAW_PARAMS, VIDIOC_VPFE_IPIPE_S_CONFIG and -VIDIOC_VPFE_RSZ_S_CONFIG are used to configure, enable and disable functions in -the isif, ipipe and resizer blocks respectively. These IOCTL's control several -functions in the blocks they control. VIDIOC_VPFE_ISIF_S_RAW_PARAMS IOCTL -accepts a pointer to struct vpfe_isif_raw_config as its argument. Similarly -VIDIOC_VPFE_IPIPE_S_CONFIG accepts a pointer to struct vpfe_ipipe_config. And -VIDIOC_VPFE_RSZ_S_CONFIG accepts a pointer to struct vpfe_rsz_config as its -argument. Similarly VIDIOC_VPFE_ISIF_G_RAW_PARAMS, VIDIOC_VPFE_IPIPE_G_CONFIG -and VIDIOC_VPFE_RSZ_G_CONFIG are used to get the current configuration set in -the isif, ipipe and resizer blocks respectively. - -The detailed functions of the VPFE itself related to a given VPFE block is -described in the Technical Reference Manuals (TRMs) --- see the end of the -document for those. - - -IPIPEIF block IOCTLs -====================================== - -The following private IOCTLs are supported: - - VIDIOC_VPFE_IPIPEIF_[S/G]_CONFIG - -The parameter structures used by these ioctl's are described in -include/uapi/linux/dm365_ipipeif.h - -The VIDIOC_VPFE_IPIPEIF_S_CONFIG is used to configure the ipipeif -hardware block. The VIDIOC_VPFE_IPIPEIF_S_CONFIG and -VIDIOC_VPFE_IPIPEIF_G_CONFIG accepts a pointer to struct ipipeif_params -as its argument. - - -VPFE Operating Modes -========================================== - -a: Continuous Modes ------------------------- - -1: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> SDRAM - -2: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->| - | - <--------------------<----------------<---------------------<---| - | - V - DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM - -3: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->| - | - <--------------------<----------------<---------------------<---| - | - V - DAVINCI IPIPE---> DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM - -a: Single Shot Modes ------------------------- - -1: SDRAM---> DAVINCI IPIPEIF---> DAVINCI IPIPE---> DAVINCI CROP RESIZER--->| - | - <----------------<----------------<------------------<---------------<--| - | - V -DAVINCI RESIZER [A/B]---> SDRAM - -2: SDRAM---> DAVINCI IPIPEIF---> DAVINCI CROP RESIZER--->| - | - <----------------<----------------<---------------<---| - | - V -DAVINCI RESIZER [A/B]---> SDRAM - - -Technical reference manuals (TRMs) and other documentation -========================================================== - -Davinci DM365 TRM: - -Referenced MARCH 2009-REVISED JUNE 2011 - -Davinci DM368 TRM: - -Referenced APRIL 2010-REVISED JUNE 2011 - -Davinci Video Processing Front End (VPFE) DM36x - - - -References -========== - -[1] http://git.ideasonboard.org/?p=media-ctl.git;a=summary diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h deleted file mode 100644 index 8d772029c91d..000000000000 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ /dev/null @@ -1,1287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_USER_H -#define _DAVINCI_VPFE_USER_H - -#include -#include - -/* - * Private IOCTL - * - * VIDIOC_VPFE_ISIF_S_RAW_PARAMS: Set raw params in isif - * VIDIOC_VPFE_ISIF_G_RAW_PARAMS: Get raw params from isif - * VIDIOC_VPFE_PRV_S_CONFIG: Set ipipe engine configuration - * VIDIOC_VPFE_PRV_G_CONFIG: Get ipipe engine configuration - * VIDIOC_VPFE_RSZ_S_CONFIG: Set resizer engine configuration - * VIDIOC_VPFE_RSZ_G_CONFIG: Get resizer engine configuration - */ - -#define VIDIOC_VPFE_ISIF_S_RAW_PARAMS \ - _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct vpfe_isif_raw_config) -#define VIDIOC_VPFE_ISIF_G_RAW_PARAMS \ - _IOR('V', BASE_VIDIOC_PRIVATE + 2, struct vpfe_isif_raw_config) -#define VIDIOC_VPFE_IPIPE_S_CONFIG \ - _IOWR('P', BASE_VIDIOC_PRIVATE + 3, struct vpfe_ipipe_config) -#define VIDIOC_VPFE_IPIPE_G_CONFIG \ - _IOWR('P', BASE_VIDIOC_PRIVATE + 4, struct vpfe_ipipe_config) -#define VIDIOC_VPFE_RSZ_S_CONFIG \ - _IOWR('R', BASE_VIDIOC_PRIVATE + 5, struct vpfe_rsz_config) -#define VIDIOC_VPFE_RSZ_G_CONFIG \ - _IOWR('R', BASE_VIDIOC_PRIVATE + 6, struct vpfe_rsz_config) - -/* - * Private Control's for ISIF - */ -#define VPFE_ISIF_CID_CRGAIN (V4L2_CID_USER_BASE | 0xa001) -#define VPFE_ISIF_CID_CGRGAIN (V4L2_CID_USER_BASE | 0xa002) -#define VPFE_ISIF_CID_CGBGAIN (V4L2_CID_USER_BASE | 0xa003) -#define VPFE_ISIF_CID_CBGAIN (V4L2_CID_USER_BASE | 0xa004) -#define VPFE_ISIF_CID_GAIN_OFFSET (V4L2_CID_USER_BASE | 0xa005) - -/* - * Private Control's for ISIF and IPIPEIF - */ -#define VPFE_CID_DPCM_PREDICTOR (V4L2_CID_USER_BASE | 0xa006) - -/************************************************************************ - * Vertical Defect Correction parameters - ***********************************************************************/ - -/** - * vertical defect correction methods - */ -enum vpfe_isif_vdfc_corr_mode { - /* Defect level subtraction. Just fed through if saturating */ - VPFE_ISIF_VDFC_NORMAL, - /** - * Defect level subtraction. Horizontal interpolation ((i-2)+(i+2))/2 - * if data saturating - */ - VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT, - /* Horizontal interpolation (((i-2)+(i+2))/2) */ - VPFE_ISIF_VDFC_HORZ_INTERPOL -}; - -/** - * Max Size of the Vertical Defect Correction table - */ -#define VPFE_ISIF_VDFC_TABLE_SIZE 8 - -/** - * Values used for shifting up the vdfc defect level - */ -enum vpfe_isif_vdfc_shift { - /* No Shift */ - VPFE_ISIF_VDFC_NO_SHIFT, - /* Shift by 1 bit */ - VPFE_ISIF_VDFC_SHIFT_1, - /* Shift by 2 bit */ - VPFE_ISIF_VDFC_SHIFT_2, - /* Shift by 3 bit */ - VPFE_ISIF_VDFC_SHIFT_3, - /* Shift by 4 bit */ - VPFE_ISIF_VDFC_SHIFT_4 -}; - -/** - * Defect Correction (DFC) table entry - */ -struct vpfe_isif_vdfc_entry { - /* vertical position of defect */ - unsigned short pos_vert; - /* horizontal position of defect */ - unsigned short pos_horz; - /** - * Defect level of Vertical line defect position. This is subtracted - * from the data at the defect position - */ - unsigned char level_at_pos; - /** - * Defect level of the pixels upper than the vertical line defect. - * This is subtracted from the data - */ - unsigned char level_up_pixels; - /** - * Defect level of the pixels lower than the vertical line defect. - * This is subtracted from the data - */ - unsigned char level_low_pixels; -}; - -/** - * Structure for Defect Correction (DFC) parameter - */ -struct vpfe_isif_dfc { - /* enable vertical defect correction */ - unsigned char en; - /* Correction methods */ - enum vpfe_isif_vdfc_corr_mode corr_mode; - /** - * 0 - whole line corrected, 1 - not - * pixels upper than the defect - */ - unsigned char corr_whole_line; - /** - * defect level shift value. level_at_pos, level_upper_pos, - * and level_lower_pos can be shifted up by this value - */ - enum vpfe_isif_vdfc_shift def_level_shift; - /* defect saturation level */ - unsigned short def_sat_level; - /* number of vertical defects. Max is VPFE_ISIF_VDFC_TABLE_SIZE */ - short num_vdefects; - /* VDFC table ptr */ - struct vpfe_isif_vdfc_entry table[VPFE_ISIF_VDFC_TABLE_SIZE]; -}; - -/************************************************************************ - * Digital/Black clamp or DC Subtract parameters - ************************************************************************/ -/** - * Horizontal Black Clamp modes - */ -enum vpfe_isif_horz_bc_mode { - /** - * Horizontal clamp disabled. Only vertical clamp - * value is subtracted - */ - VPFE_ISIF_HORZ_BC_DISABLE, - /** - * Horizontal clamp value is calculated and subtracted - * from image data along with vertical clamp value - */ - VPFE_ISIF_HORZ_BC_CLAMP_CALC_ENABLED, - /** - * Horizontal clamp value calculated from previous image - * is subtracted from image data along with vertical clamp - * value. How the horizontal clamp value for the first image - * is calculated in this case ??? - */ - VPFE_ISIF_HORZ_BC_CLAMP_NOT_UPDATED -}; - -/** - * Base window selection for Horizontal Black Clamp calculations - */ -enum vpfe_isif_horz_bc_base_win_sel { - /* Select Most left window for bc calculation */ - VPFE_ISIF_SEL_MOST_LEFT_WIN, - - /* Select Most right window for bc calculation */ - VPFE_ISIF_SEL_MOST_RIGHT_WIN, -}; - -/* Size of window in horizontal direction for horizontal bc */ -enum vpfe_isif_horz_bc_sz_h { - VPFE_ISIF_HORZ_BC_SZ_H_2PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_4PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_8PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_16PIXELS -}; - -/* Size of window in vertcal direction for vertical bc */ -enum vpfe_isif_horz_bc_sz_v { - VPFE_ISIF_HORZ_BC_SZ_H_32PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_64PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_128PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_256PIXELS -}; - -/** - * Structure for Horizontal Black Clamp config params - */ -struct vpfe_isif_horz_bclamp { - /* horizontal clamp mode */ - enum vpfe_isif_horz_bc_mode mode; - /** - * pixel value limit enable. - * 0 - limit disabled - * 1 - pixel value limited to 1023 - */ - unsigned char clamp_pix_limit; - /** - * Select most left or right window for clamp val - * calculation - */ - enum vpfe_isif_horz_bc_base_win_sel base_win_sel_calc; - /* Window count per color for calculation. range 1-32 */ - unsigned char win_count_calc; - /* Window start position - horizontal for calculation. 0 - 8191 */ - unsigned short win_start_h_calc; - /* Window start position - vertical for calculation 0 - 8191 */ - unsigned short win_start_v_calc; - /* Width of the sample window in pixels for calculation */ - enum vpfe_isif_horz_bc_sz_h win_h_sz_calc; - /* Height of the sample window in pixels for calculation */ - enum vpfe_isif_horz_bc_sz_v win_v_sz_calc; -}; - -/** - * Black Clamp vertical reset values - */ -enum vpfe_isif_vert_bc_reset_val_sel { - /* Reset value used is the clamp value calculated */ - VPFE_ISIF_VERT_BC_USE_HORZ_CLAMP_VAL, - /* Reset value used is reset_clamp_val configured */ - VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL, - /* No update, previous image value is used */ - VPFE_ISIF_VERT_BC_NO_UPDATE -}; - -enum vpfe_isif_vert_bc_sz_h { - VPFE_ISIF_VERT_BC_SZ_H_2PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_4PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_8PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_16PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_32PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_64PIXELS -}; - -/** - * Structure for Vertical Black Clamp configuration params - */ -struct vpfe_isif_vert_bclamp { - /* Reset value selection for vertical clamp calculation */ - enum vpfe_isif_vert_bc_reset_val_sel reset_val_sel; - /* U12 value if reset_sel = ISIF_BC_VERT_USE_CONFIG_CLAMP_VAL */ - unsigned short reset_clamp_val; - /** - * U8Q8. Line average coefficient used in vertical clamp - * calculation - */ - unsigned char line_ave_coef; - /* Width in pixels of the optical black region used for calculation. */ - enum vpfe_isif_vert_bc_sz_h ob_h_sz_calc; - /* Height of the optical black region for calculation */ - unsigned short ob_v_sz_calc; - /* Optical black region start position - horizontal. 0 - 8191 */ - unsigned short ob_start_h; - /* Optical black region start position - vertical 0 - 8191 */ - unsigned short ob_start_v; -}; - -/** - * Structure for Black Clamp configuration params - */ -struct vpfe_isif_black_clamp { - /** - * this offset value is added irrespective of the clamp - * enable status. S13 - */ - unsigned short dc_offset; - /** - * Enable black/digital clamp value to be subtracted - * from the image data - */ - unsigned char en; - /** - * black clamp mode. same/separate clamp for 4 colors - * 0 - disable - same clamp value for all colors - * 1 - clamp value calculated separately for all colors - */ - unsigned char bc_mode_color; - /* Vertical start position for bc subtraction */ - unsigned short vert_start_sub; - /* Black clamp for horizontal direction */ - struct vpfe_isif_horz_bclamp horz; - /* Black clamp for vertical direction */ - struct vpfe_isif_vert_bclamp vert; -}; - -/************************************************************************* - ** Color Space Conversion (CSC) - *************************************************************************/ -/** - * Number of Coefficient values used for CSC - */ -#define VPFE_ISIF_CSC_NUM_COEFF 16 - -struct float_8_bit { - /* 8 bit integer part */ - __u8 integer; - /* 8 bit decimal part */ - __u8 decimal; -}; - -struct float_16_bit { - /* 16 bit integer part */ - __u16 integer; - /* 16 bit decimal part */ - __u16 decimal; -}; - -/************************************************************************* - ** Color Space Conversion parameters - *************************************************************************/ -/** - * Structure used for CSC config params - */ -struct vpfe_isif_color_space_conv { - /* Enable color space conversion */ - unsigned char en; - /** - * csc coefficient table. S8Q5, M00 at index 0, M01 at index 1, and - * so forth - */ - struct float_8_bit coeff[VPFE_ISIF_CSC_NUM_COEFF]; -}; - -enum vpfe_isif_datasft { - /* No Shift */ - VPFE_ISIF_NO_SHIFT, - /* 1 bit Shift */ - VPFE_ISIF_1BIT_SHIFT, - /* 2 bit Shift */ - VPFE_ISIF_2BIT_SHIFT, - /* 3 bit Shift */ - VPFE_ISIF_3BIT_SHIFT, - /* 4 bit Shift */ - VPFE_ISIF_4BIT_SHIFT, - /* 5 bit Shift */ - VPFE_ISIF_5BIT_SHIFT, - /* 6 bit Shift */ - VPFE_ISIF_6BIT_SHIFT -}; - -#define VPFE_ISIF_LINEAR_TAB_SIZE 192 -/************************************************************************* - ** Linearization parameters - *************************************************************************/ -/** - * Structure for Sensor data linearization - */ -struct vpfe_isif_linearize { - /* Enable or Disable linearization of data */ - unsigned char en; - /* Shift value applied */ - enum vpfe_isif_datasft corr_shft; - /* scale factor applied U11Q10 */ - struct float_16_bit scale_fact; - /* Size of the linear table */ - unsigned short table[VPFE_ISIF_LINEAR_TAB_SIZE]; -}; - -/************************************************************************* - ** ISIF Raw configuration parameters - *************************************************************************/ -enum vpfe_isif_fmt_mode { - VPFE_ISIF_SPLIT, - VPFE_ISIF_COMBINE -}; - -enum vpfe_isif_lnum { - VPFE_ISIF_1LINE, - VPFE_ISIF_2LINES, - VPFE_ISIF_3LINES, - VPFE_ISIF_4LINES -}; - -enum vpfe_isif_line { - VPFE_ISIF_1STLINE, - VPFE_ISIF_2NDLINE, - VPFE_ISIF_3RDLINE, - VPFE_ISIF_4THLINE -}; - -struct vpfe_isif_fmtplen { - /** - * number of program entries for SET0, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen0; - /** - * number of program entries for SET1, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen1; - /** - * number of program entries for SET2, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen2; - /** - * number of program entries for SET3, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen3; -}; - -struct vpfe_isif_fmt_cfg { - /* Split or combine or line alternate */ - enum vpfe_isif_fmt_mode fmtmode; - /* enable or disable line alternating mode */ - unsigned char ln_alter_en; - /* Split/combine line number */ - enum vpfe_isif_lnum lnum; - /* Address increment Range 1 - 16 */ - unsigned int addrinc; -}; - -struct vpfe_isif_fmt_addr_ptr { - /* Initial address */ - unsigned int init_addr; - /* output line number */ - enum vpfe_isif_line out_line; -}; - -struct vpfe_isif_fmtpgm_ap { - /* program address pointer */ - unsigned char pgm_aptr; - /* program address increment or decrement */ - unsigned char pgmupdt; -}; - -struct vpfe_isif_data_formatter { - /* Enable/Disable data formatter */ - unsigned char en; - /* data formatter configuration */ - struct vpfe_isif_fmt_cfg cfg; - /* Formatter program entries length */ - struct vpfe_isif_fmtplen plen; - /* first pixel in a line fed to formatter */ - unsigned short fmtrlen; - /* HD interval for output line. Only valid when split line */ - unsigned short fmthcnt; - /* formatter address pointers */ - struct vpfe_isif_fmt_addr_ptr fmtaddr_ptr[16]; - /* program enable/disable */ - unsigned char pgm_en[32]; - /* program address pointers */ - struct vpfe_isif_fmtpgm_ap fmtpgm_ap[32]; -}; - -struct vpfe_isif_df_csc { - /* Color Space Conversion configuration, 0 - csc, 1 - df */ - unsigned int df_or_csc; - /* csc configuration valid if df_or_csc is 0 */ - struct vpfe_isif_color_space_conv csc; - /* data formatter configuration valid if df_or_csc is 1 */ - struct vpfe_isif_data_formatter df; - /* start pixel in a line at the input */ - unsigned int start_pix; - /* number of pixels in input line */ - unsigned int num_pixels; - /* start line at the input */ - unsigned int start_line; - /* number of lines at the input */ - unsigned int num_lines; -}; - -struct vpfe_isif_gain_offsets_adj { - /* Enable or Disable Gain adjustment for SDRAM data */ - unsigned char gain_sdram_en; - /* Enable or Disable Gain adjustment for IPIPE data */ - unsigned char gain_ipipe_en; - /* Enable or Disable Gain adjustment for H3A data */ - unsigned char gain_h3a_en; - /* Enable or Disable Gain adjustment for SDRAM data */ - unsigned char offset_sdram_en; - /* Enable or Disable Gain adjustment for IPIPE data */ - unsigned char offset_ipipe_en; - /* Enable or Disable Gain adjustment for H3A data */ - unsigned char offset_h3a_en; -}; - -struct vpfe_isif_cul { - /* Horizontal Cull pattern for odd lines */ - unsigned char hcpat_odd; - /* Horizontal Cull pattern for even lines */ - unsigned char hcpat_even; - /* Vertical Cull pattern */ - unsigned char vcpat; - /* Enable or disable lpf. Apply when cull is enabled */ - unsigned char en_lpf; -}; - -/* all the stuff in this struct will be provided by userland */ -struct vpfe_isif_raw_config { - /* Linearization parameters for image sensor data input */ - struct vpfe_isif_linearize linearize; - /* Data formatter or CSC */ - struct vpfe_isif_df_csc df_csc; - /* Defect Pixel Correction (DFC) confguration */ - struct vpfe_isif_dfc dfc; - /* Black/Digital Clamp configuration */ - struct vpfe_isif_black_clamp bclamp; - /* Gain, offset adjustments */ - struct vpfe_isif_gain_offsets_adj gain_offset; - /* Culling */ - struct vpfe_isif_cul culling; - /* horizontal offset for Gain/LSC/DFC */ - unsigned short horz_offset; - /* vertical offset for Gain/LSC/DFC */ - unsigned short vert_offset; -}; - -/********************************************************************** - * IPIPE API Structures - **********************************************************************/ - -/* IPIPE module configurations */ - -/* IPIPE input configuration */ -#define VPFE_IPIPE_INPUT_CONFIG BIT(0) -/* LUT based Defect Pixel Correction */ -#define VPFE_IPIPE_LUTDPC BIT(1) -/* On the fly (OTF) Defect Pixel Correction */ -#define VPFE_IPIPE_OTFDPC BIT(2) -/* Noise Filter - 1 */ -#define VPFE_IPIPE_NF1 BIT(3) -/* Noise Filter - 2 */ -#define VPFE_IPIPE_NF2 BIT(4) -/* White Balance. Also a control ID */ -#define VPFE_IPIPE_WB BIT(5) -/* 1st RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_1 BIT(6) -/* 2nd RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_2 BIT(7) -/* Gamma Correction */ -#define VPFE_IPIPE_GAMMA BIT(8) -/* 3D LUT color conversion */ -#define VPFE_IPIPE_3D_LUT BIT(9) -/* RGB to YCbCr module */ -#define VPFE_IPIPE_RGB2YUV BIT(10) -/* YUV 422 conversion module */ -#define VPFE_IPIPE_YUV422_CONV BIT(11) -/* Edge Enhancement */ -#define VPFE_IPIPE_YEE BIT(12) -/* Green Imbalance Correction */ -#define VPFE_IPIPE_GIC BIT(13) -/* CFA Interpolation */ -#define VPFE_IPIPE_CFA BIT(14) -/* Chroma Artifact Reduction */ -#define VPFE_IPIPE_CAR BIT(15) -/* Chroma Gain Suppression */ -#define VPFE_IPIPE_CGS BIT(16) -/* Global brightness and contrast control */ -#define VPFE_IPIPE_GBCE BIT(17) - -#define VPFE_IPIPE_MAX_MODULES 18 - -struct ipipe_float_u16 { - unsigned short integer; - unsigned short decimal; -}; - -struct ipipe_float_s16 { - short integer; - unsigned short decimal; -}; - -struct ipipe_float_u8 { - unsigned char integer; - unsigned char decimal; -}; - -/* Copy method selection for vertical correction - * Used when ipipe_dfc_corr_meth is IPIPE_DPC_CTORB_AFTER_HINT - */ -enum vpfe_ipipe_dpc_corr_meth { - /* replace by black or white dot specified by repl_white */ - VPFE_IPIPE_DPC_REPL_BY_DOT = 0, - /* Copy from left */ - VPFE_IPIPE_DPC_CL = 1, - /* Copy from right */ - VPFE_IPIPE_DPC_CR = 2, - /* Horizontal interpolation */ - VPFE_IPIPE_DPC_H_INTP = 3, - /* Vertical interpolation */ - VPFE_IPIPE_DPC_V_INTP = 4, - /* Copy from top */ - VPFE_IPIPE_DPC_CT = 5, - /* Copy from bottom */ - VPFE_IPIPE_DPC_CB = 6, - /* 2D interpolation */ - VPFE_IPIPE_DPC_2D_INTP = 7, -}; - -struct vpfe_ipipe_lutdpc_entry { - /* Horizontal position */ - unsigned short horz_pos; - /* vertical position */ - unsigned short vert_pos; - enum vpfe_ipipe_dpc_corr_meth method; -}; - -#define VPFE_IPIPE_MAX_SIZE_DPC 256 - -/* Structure for configuring DPC module */ -struct vpfe_ipipe_lutdpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* 0 - replace with black dot, 1 - white dot when correction - * method is IPIPE_DFC_REPL_BY_DOT=0, - */ - unsigned char repl_white; - /* number of entries in the correction table. Currently only - * support up-to 256 entries. infinite mode is not supported - */ - unsigned short dpc_size; - struct vpfe_ipipe_lutdpc_entry table[VPFE_IPIPE_MAX_SIZE_DPC]; -}; - -enum vpfe_ipipe_otfdpc_det_meth { - VPFE_IPIPE_DPC_OTF_MIN_MAX, - VPFE_IPIPE_DPC_OTF_MIN_MAX2 -}; - -struct vpfe_ipipe_otfdpc_thr { - unsigned short r; - unsigned short gr; - unsigned short gb; - unsigned short b; -}; - -enum vpfe_ipipe_otfdpc_alg { - VPFE_IPIPE_OTFDPC_2_0, - VPFE_IPIPE_OTFDPC_3_0 -}; - -struct vpfe_ipipe_otfdpc_2_0_cfg { - /* defect detection threshold for MIN_MAX2 method (DPC 2.0 alg) */ - struct vpfe_ipipe_otfdpc_thr det_thr; - /* defect correction threshold for MIN_MAX2 method (DPC 2.0 alg) or - * maximum value for MIN_MAX method - */ - struct vpfe_ipipe_otfdpc_thr corr_thr; -}; - -struct vpfe_ipipe_otfdpc_3_0_cfg { - /* DPC3.0 activity adj shf. activity = (max2-min2) >> (6 -shf) - */ - unsigned char act_adj_shf; - /* DPC3.0 detection threshold, THR */ - unsigned short det_thr; - /* DPC3.0 detection threshold slope, SLP */ - unsigned short det_slp; - /* DPC3.0 detection threshold min, MIN */ - unsigned short det_thr_min; - /* DPC3.0 detection threshold max, MAX */ - unsigned short det_thr_max; - /* DPC3.0 correction threshold, THR */ - unsigned short corr_thr; - /* DPC3.0 correction threshold slope, SLP */ - unsigned short corr_slp; - /* DPC3.0 correction threshold min, MIN */ - unsigned short corr_thr_min; - /* DPC3.0 correction threshold max, MAX */ - unsigned short corr_thr_max; -}; - -struct vpfe_ipipe_otfdpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - union { - /* if alg is IPIPE_OTFDPC_2_0 */ - struct vpfe_ipipe_otfdpc_2_0_cfg dpc_2_0; - /* if alg is IPIPE_OTFDPC_3_0 */ - struct vpfe_ipipe_otfdpc_3_0_cfg dpc_3_0; - } alg_cfg; -}; - -/* Threshold values table size */ -#define VPFE_IPIPE_NF_THR_TABLE_SIZE 8 -/* Intensity values table size */ -#define VPFE_IPIPE_NF_STR_TABLE_SIZE 8 - -/* NF, sampling method for green pixels */ -enum vpfe_ipipe_nf_sampl_meth { - /* Same as R or B */ - VPFE_IPIPE_NF_BOX, - /* Diamond mode */ - VPFE_IPIPE_NF_DIAMOND -}; - -/* Structure for configuring NF module */ -struct vpfe_ipipe_nf { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* Sampling method for green pixels */ - enum vpfe_ipipe_nf_sampl_meth gr_sample_meth; - /* Down shift value in LUT reference address - */ - unsigned char shft_val; - /* Spread value in NF algorithm - */ - unsigned char spread_val; - /* Apply LSC gain to threshold. Enable this only if - * LSC is enabled in ISIF - */ - unsigned char apply_lsc_gain; - /* Threshold values table */ - unsigned short thr[VPFE_IPIPE_NF_THR_TABLE_SIZE]; - /* intensity values table */ - unsigned char str[VPFE_IPIPE_NF_STR_TABLE_SIZE]; - /* Edge detection minimum threshold */ - unsigned short edge_det_min_thr; - /* Edge detection maximum threshold */ - unsigned short edge_det_max_thr; -}; - -enum vpfe_ipipe_gic_alg { - VPFE_IPIPE_GIC_ALG_CONST_GAIN, - VPFE_IPIPE_GIC_ALG_ADAPT_GAIN -}; - -enum vpfe_ipipe_gic_thr_sel { - VPFE_IPIPE_GIC_THR_REG, - VPFE_IPIPE_GIC_THR_NF -}; - -enum vpfe_ipipe_gic_wt_fn_type { - /* Use difference as index */ - VPFE_IPIPE_GIC_WT_FN_TYP_DIF, - /* Use weight function as index */ - VPFE_IPIPE_GIC_WT_FN_TYP_HP_VAL -}; - -/* structure for Green Imbalance Correction */ -struct vpfe_ipipe_gic { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* 0 - Constant gain , 1 - Adaptive gain algorithm */ - enum vpfe_ipipe_gic_alg gic_alg; - /* GIC gain or weight. Used for Constant gain and Adaptive algorithms - */ - unsigned short gain; - /* Threshold selection. GIC register values or NF2 thr table */ - enum vpfe_ipipe_gic_thr_sel thr_sel; - /* thr1. Used when thr_sel is IPIPE_GIC_THR_REG */ - unsigned short thr; - /* this value is used for thr2-thr1, thr3-thr2 or - * thr4-thr3 when wt_fn_type is index. Otherwise it - * is the - */ - unsigned short slope; - /* Apply LSC gain to threshold. Enable this only if - * LSC is enabled in ISIF & thr_sel is IPIPE_GIC_THR_REG - */ - unsigned char apply_lsc_gain; - /* Multiply Nf2 threshold by this gain. Use this when thr_sel - * is IPIPE_GIC_THR_NF - */ - struct ipipe_float_u8 nf2_thr_gain; - /* Weight function uses difference as index or high pass value. - * Used for adaptive gain algorithm - */ - enum vpfe_ipipe_gic_wt_fn_type wt_fn_type; -}; - -/* Structure for configuring WB module */ -struct vpfe_ipipe_wb { - /* Offset (S12) for R */ - short ofst_r; - /* Offset (S12) for Gr */ - short ofst_gr; - /* Offset (S12) for Gb */ - short ofst_gb; - /* Offset (S12) for B */ - short ofst_b; - /* Gain (U13Q9) for Red */ - struct ipipe_float_u16 gain_r; - /* Gain (U13Q9) for Gr */ - struct ipipe_float_u16 gain_gr; - /* Gain (U13Q9) for Gb */ - struct ipipe_float_u16 gain_gb; - /* Gain (U13Q9) for Blue */ - struct ipipe_float_u16 gain_b; -}; - -enum vpfe_ipipe_cfa_alg { - /* Algorithm is 2DirAC */ - VPFE_IPIPE_CFA_ALG_2DIRAC, - /* Algorithm is 2DirAC + Digital Antialiasing (DAA) */ - VPFE_IPIPE_CFA_ALG_2DIRAC_DAA, - /* Algorithm is DAA */ - VPFE_IPIPE_CFA_ALG_DAA -}; - -/* Structure for CFA Interpolation */ -struct vpfe_ipipe_cfa { - /* 2DirAC or 2DirAC + DAA */ - enum vpfe_ipipe_cfa_alg alg; - /* 2Dir CFA HP value Low Threshold */ - unsigned short hpf_thr_2dir; - /* 2Dir CFA HP value slope */ - unsigned short hpf_slp_2dir; - /* 2Dir CFA HP mix threshold */ - unsigned short hp_mix_thr_2dir; - /* 2Dir CFA HP mix slope */ - unsigned short hp_mix_slope_2dir; - /* 2Dir Direction threshold */ - unsigned short dir_thr_2dir; - /* 2Dir Direction slope */ - unsigned short dir_slope_2dir; - /* 2Dir Non Directional Weight */ - unsigned short nd_wt_2dir; - /* DAA Mono Hue Fraction */ - unsigned short hue_fract_daa; - /* DAA Mono Edge threshold */ - unsigned short edge_thr_daa; - /* DAA Mono threshold minimum */ - unsigned short thr_min_daa; - /* DAA Mono threshold slope */ - unsigned short thr_slope_daa; - /* DAA Mono slope minimum */ - unsigned short slope_min_daa; - /* DAA Mono slope slope */ - unsigned short slope_slope_daa; - /* DAA Mono LP wight */ - unsigned short lp_wt_daa; -}; - -/* Struct for configuring RGB2RGB blending module */ -struct vpfe_ipipe_rgb2rgb { - /* Matrix coefficient for RR S12Q8 for ID = 1 and S11Q8 for ID = 2 */ - struct ipipe_float_s16 coef_rr; - /* Matrix coefficient for GR S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gr; - /* Matrix coefficient for BR S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_br; - /* Matrix coefficient for RG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_rg; - /* Matrix coefficient for GG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gg; - /* Matrix coefficient for BG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_bg; - /* Matrix coefficient for RB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_rb; - /* Matrix coefficient for GB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gb; - /* Matrix coefficient for BB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_bb; - /* Output offset for R S13/S11 */ - int out_ofst_r; - /* Output offset for G S13/S11 */ - int out_ofst_g; - /* Output offset for B S13/S11 */ - int out_ofst_b; -}; - -#define VPFE_IPIPE_MAX_SIZE_GAMMA 512 - -enum vpfe_ipipe_gamma_tbl_size { - VPFE_IPIPE_GAMMA_TBL_SZ_64 = 64, - VPFE_IPIPE_GAMMA_TBL_SZ_128 = 128, - VPFE_IPIPE_GAMMA_TBL_SZ_256 = 256, - VPFE_IPIPE_GAMMA_TBL_SZ_512 = 512, -}; - -enum vpfe_ipipe_gamma_tbl_sel { - VPFE_IPIPE_GAMMA_TBL_RAM = 0, - VPFE_IPIPE_GAMMA_TBL_ROM = 1, -}; - -struct vpfe_ipipe_gamma_entry { - /* 10 bit slope */ - short slope; - /* 10 bit offset */ - unsigned short offset; -}; - -/* Structure for configuring Gamma correction module */ -struct vpfe_ipipe_gamma { - /* 0 - Enable Gamma correction for Red - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_r; - /* 0 - Enable Gamma correction for Blue - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_b; - /* 0 - Enable Gamma correction for Green - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_g; - /* IPIPE_GAMMA_TBL_RAM or IPIPE_GAMMA_TBL_ROM */ - enum vpfe_ipipe_gamma_tbl_sel tbl_sel; - /* Table size for RAM gamma table. - */ - enum vpfe_ipipe_gamma_tbl_size tbl_size; - /* R table */ - struct vpfe_ipipe_gamma_entry table_r[VPFE_IPIPE_MAX_SIZE_GAMMA]; - /* Blue table */ - struct vpfe_ipipe_gamma_entry table_b[VPFE_IPIPE_MAX_SIZE_GAMMA]; - /* Green table */ - struct vpfe_ipipe_gamma_entry table_g[VPFE_IPIPE_MAX_SIZE_GAMMA]; -}; - -#define VPFE_IPIPE_MAX_SIZE_3D_LUT 729 - -struct vpfe_ipipe_3d_lut_entry { - /* 10 bit entry for red */ - unsigned short r; - /* 10 bit entry for green */ - unsigned short g; - /* 10 bit entry for blue */ - unsigned short b; -}; - -/* structure for 3D-LUT */ -struct vpfe_ipipe_3d_lut { - /* enable/disable 3D lut */ - unsigned char en; - /* 3D - LUT table entry */ - struct vpfe_ipipe_3d_lut_entry table[VPFE_IPIPE_MAX_SIZE_3D_LUT]; -}; - -/* Struct for configuring rgb2ycbcr module */ -struct vpfe_ipipe_rgb2yuv { - /* Matrix coefficient for RY S12Q8 */ - struct ipipe_float_s16 coef_ry; - /* Matrix coefficient for GY S12Q8 */ - struct ipipe_float_s16 coef_gy; - /* Matrix coefficient for BY S12Q8 */ - struct ipipe_float_s16 coef_by; - /* Matrix coefficient for RCb S12Q8 */ - struct ipipe_float_s16 coef_rcb; - /* Matrix coefficient for GCb S12Q8 */ - struct ipipe_float_s16 coef_gcb; - /* Matrix coefficient for BCb S12Q8 */ - struct ipipe_float_s16 coef_bcb; - /* Matrix coefficient for RCr S12Q8 */ - struct ipipe_float_s16 coef_rcr; - /* Matrix coefficient for GCr S12Q8 */ - struct ipipe_float_s16 coef_gcr; - /* Matrix coefficient for BCr S12Q8 */ - struct ipipe_float_s16 coef_bcr; - /* Output offset for R S11 */ - int out_ofst_y; - /* Output offset for Cb S11 */ - int out_ofst_cb; - /* Output offset for Cr S11 */ - int out_ofst_cr; -}; - -enum vpfe_ipipe_gbce_type { - VPFE_IPIPE_GBCE_Y_VAL_TBL = 0, - VPFE_IPIPE_GBCE_GAIN_TBL = 1, -}; - -#define VPFE_IPIPE_MAX_SIZE_GBCE_LUT 1024 - -/* structure for Global brightness and Contrast */ -struct vpfe_ipipe_gbce { - /* enable/disable GBCE */ - unsigned char en; - /* Y - value table or Gain table */ - enum vpfe_ipipe_gbce_type type; - /* ptr to LUT for GBCE with 1024 entries */ - unsigned short table[VPFE_IPIPE_MAX_SIZE_GBCE_LUT]; -}; - -/* Chrominance position. Applicable only for YCbCr input - * Applied after edge enhancement - */ -enum vpfe_chr_pos { - /* Co-siting, same position with luminance */ - VPFE_IPIPE_YUV422_CHR_POS_COSITE = 0, - /* Centering, In the middle of luminance */ - VPFE_IPIPE_YUV422_CHR_POS_CENTRE = 1, -}; - -/* Structure for configuring yuv422 conversion module */ -struct vpfe_ipipe_yuv422_conv { - /* Max Chrominance value */ - unsigned char en_chrom_lpf; - /* 1 - enable LPF for chrminance, 0 - disable */ - enum vpfe_chr_pos chrom_pos; -}; - -#define VPFE_IPIPE_MAX_SIZE_YEE_LUT 1024 - -enum vpfe_ipipe_yee_merge_meth { - VPFE_IPIPE_YEE_ABS_MAX = 0, - VPFE_IPIPE_YEE_EE_ES = 1, -}; - -/* Structure for configuring YUV Edge Enhancement module */ -struct vpfe_ipipe_yee { - /* 1 - enable enhancement, 0 - disable */ - unsigned char en; - /* enable/disable halo reduction in edge sharpner */ - unsigned char en_halo_red; - /* Merge method between Edge Enhancer and Edge sharpner */ - enum vpfe_ipipe_yee_merge_meth merge_meth; - /* HPF Shift length */ - unsigned char hpf_shft; - /* HPF Coefficient 00, S10 */ - short hpf_coef_00; - /* HPF Coefficient 01, S10 */ - short hpf_coef_01; - /* HPF Coefficient 02, S10 */ - short hpf_coef_02; - /* HPF Coefficient 10, S10 */ - short hpf_coef_10; - /* HPF Coefficient 11, S10 */ - short hpf_coef_11; - /* HPF Coefficient 12, S10 */ - short hpf_coef_12; - /* HPF Coefficient 20, S10 */ - short hpf_coef_20; - /* HPF Coefficient 21, S10 */ - short hpf_coef_21; - /* HPF Coefficient 22, S10 */ - short hpf_coef_22; - /* Lower threshold before referring to LUT */ - unsigned short yee_thr; - /* Edge sharpener Gain */ - unsigned short es_gain; - /* Edge sharpener lower threshold */ - unsigned short es_thr1; - /* Edge sharpener upper threshold */ - unsigned short es_thr2; - /* Edge sharpener gain on gradient */ - unsigned short es_gain_grad; - /* Edge sharpener offset on gradient */ - unsigned short es_ofst_grad; - /* Ptr to EE table. Must have 1024 entries */ - short table[VPFE_IPIPE_MAX_SIZE_YEE_LUT]; -}; - -enum vpfe_ipipe_car_meth { - /* Chromatic Gain Control */ - VPFE_IPIPE_CAR_CHR_GAIN_CTRL = 0, - /* Dynamic switching between CHR_GAIN_CTRL - * and MED_FLTR - */ - VPFE_IPIPE_CAR_DYN_SWITCH = 1, - /* Median Filter */ - VPFE_IPIPE_CAR_MED_FLTR = 2, -}; - -enum vpfe_ipipe_car_hpf_type { - VPFE_IPIPE_CAR_HPF_Y = 0, - VPFE_IPIPE_CAR_HPF_H = 1, - VPFE_IPIPE_CAR_HPF_V = 2, - VPFE_IPIPE_CAR_HPF_2D = 3, - /* 2D HPF from YUV Edge Enhancement */ - VPFE_IPIPE_CAR_HPF_2D_YEE = 4, -}; - -struct vpfe_ipipe_car_gain { - /* csup_gain */ - unsigned char gain; - /* csup_shf. */ - unsigned char shft; - /* gain minimum */ - unsigned short gain_min; -}; - -/* Structure for Chromatic Artifact Reduction */ -struct vpfe_ipipe_car { - /* enable/disable */ - unsigned char en; - /* Gain control or Dynamic switching */ - enum vpfe_ipipe_car_meth meth; - /* Gain1 function configuration for Gain control */ - struct vpfe_ipipe_car_gain gain1; - /* Gain2 function configuration for Gain control */ - struct vpfe_ipipe_car_gain gain2; - /* HPF type used for CAR */ - enum vpfe_ipipe_car_hpf_type hpf; - /* csup_thr: HPF threshold for Gain control */ - unsigned char hpf_thr; - /* Down shift value for hpf. 2 bits */ - unsigned char hpf_shft; - /* switch limit for median filter */ - unsigned char sw0; - /* switch coefficient for Gain control */ - unsigned char sw1; -}; - -/* structure for Chromatic Gain Suppression */ -struct vpfe_ipipe_cgs { - /* enable/disable */ - unsigned char en; - /* gain1 bright side threshold */ - unsigned char h_thr; - /* gain1 bright side slope */ - unsigned char h_slope; - /* gain1 down shift value for bright side */ - unsigned char h_shft; - /* gain1 bright side minimum gain */ - unsigned char h_min; -}; - -/* Max pixels allowed in the input. If above this either decimation - * or frame division mode to be enabled - */ -#define VPFE_IPIPE_MAX_INPUT_WIDTH 2600 - -struct vpfe_ipipe_input_config { - unsigned int vst; - unsigned int hst; -}; - -/** - * struct vpfe_ipipe_config - IPIPE engine configuration (user) - * @input_config: Pointer to structure for ipipe configuration. - * @flag: Specifies which ISP IPIPE functions should be enabled. - * @lutdpc: Pointer to luma enhancement structure. - * @otfdpc: Pointer to structure for defect correction. - * @nf1: Pointer to structure for Noise Filter. - * @nf2: Pointer to structure for Noise Filter. - * @gic: Pointer to structure for Green Imbalance. - * @wbal: Pointer to structure for White Balance. - * @cfa: Pointer to structure containing the CFA interpolation. - * @rgb2rgb1: Pointer to structure for RGB to RGB Blending. - * @rgb2rgb2: Pointer to structure for RGB to RGB Blending. - * @gamma: Pointer to gamma structure. - * @lut: Pointer to structure for 3D LUT. - * @rgb2yuv: Pointer to structure for RGB-YCbCr conversion. - * @gbce: Pointer to structure for Global Brightness,Contrast Control. - * @yuv422_conv: Pointer to structure for YUV 422 conversion. - * @yee: Pointer to structure for Edge Enhancer. - * @car: Pointer to structure for Chromatic Artifact Reduction. - * @cgs: Pointer to structure for Chromatic Gain Suppression. - */ -struct vpfe_ipipe_config { - __u32 flag; - struct vpfe_ipipe_input_config __user *input_config; - struct vpfe_ipipe_lutdpc __user *lutdpc; - struct vpfe_ipipe_otfdpc __user *otfdpc; - struct vpfe_ipipe_nf __user *nf1; - struct vpfe_ipipe_nf __user *nf2; - struct vpfe_ipipe_gic __user *gic; - struct vpfe_ipipe_wb __user *wbal; - struct vpfe_ipipe_cfa __user *cfa; - struct vpfe_ipipe_rgb2rgb __user *rgb2rgb1; - struct vpfe_ipipe_rgb2rgb __user *rgb2rgb2; - struct vpfe_ipipe_gamma __user *gamma; - struct vpfe_ipipe_3d_lut __user *lut; - struct vpfe_ipipe_rgb2yuv __user *rgb2yuv; - struct vpfe_ipipe_gbce __user *gbce; - struct vpfe_ipipe_yuv422_conv __user *yuv422_conv; - struct vpfe_ipipe_yee __user *yee; - struct vpfe_ipipe_car __user *car; - struct vpfe_ipipe_cgs __user *cgs; -}; - -/******************************************************************* - ** Resizer API structures - *******************************************************************/ -/* Interpolation types used for horizontal rescale */ -enum vpfe_rsz_intp_t { - VPFE_RSZ_INTP_CUBIC, - VPFE_RSZ_INTP_LINEAR -}; - -/* Horizontal LPF intensity selection */ -enum vpfe_rsz_h_lpf_lse_t { - VPFE_RSZ_H_LPF_LSE_INTERN, - VPFE_RSZ_H_LPF_LSE_USER_VAL -}; - -enum vpfe_rsz_down_scale_ave_sz { - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - VPFE_IPIPE_DWN_SCALE_1_OVER_4, - VPFE_IPIPE_DWN_SCALE_1_OVER_8, - VPFE_IPIPE_DWN_SCALE_1_OVER_16, - VPFE_IPIPE_DWN_SCALE_1_OVER_32, - VPFE_IPIPE_DWN_SCALE_1_OVER_64, - VPFE_IPIPE_DWN_SCALE_1_OVER_128, - VPFE_IPIPE_DWN_SCALE_1_OVER_256 -}; - -struct vpfe_rsz_output_spec { - /* enable horizontal flip */ - unsigned char h_flip; - /* enable vertical flip */ - unsigned char v_flip; - /* line start offset for y. */ - unsigned int vst_y; - /* line start offset for c. Only for 420 */ - unsigned int vst_c; - /* vertical rescale interpolation type, YCbCr or Luminance */ - enum vpfe_rsz_intp_t v_typ_y; - /* vertical rescale interpolation type for Chrominance */ - enum vpfe_rsz_intp_t v_typ_c; - /* vertical lpf intensity - Luminance */ - unsigned char v_lpf_int_y; - /* vertical lpf intensity - Chrominance */ - unsigned char v_lpf_int_c; - /* horizontal rescale interpolation types, YCbCr or Luminance */ - enum vpfe_rsz_intp_t h_typ_y; - /* horizontal rescale interpolation types, Chrominance */ - enum vpfe_rsz_intp_t h_typ_c; - /* horizontal lpf intensity - Luminance */ - unsigned char h_lpf_int_y; - /* horizontal lpf intensity - Chrominance */ - unsigned char h_lpf_int_c; - /* Use down scale mode for scale down */ - unsigned char en_down_scale; - /* if downscale, set the downscale more average size for horizontal - * direction. Used only if output width and height is less than - * input sizes - */ - enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz; - /* if downscale, set the downscale more average size for vertical - * direction. Used only if output width and height is less than - * input sizes - */ - enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz; - /* Y offset. If set, the offset would be added to the base address - */ - unsigned int user_y_ofst; - /* C offset. If set, the offset would be added to the base address - */ - unsigned int user_c_ofst; -}; - -struct vpfe_rsz_config_params { - unsigned int vst; - /* horizontal start position of the image - * data to IPIPE - */ - unsigned int hst; - /* output spec of the image data coming out of resizer - 0(UYVY). - */ - struct vpfe_rsz_output_spec output1; - /* output spec of the image data coming out of resizer - 1(UYVY). - */ - struct vpfe_rsz_output_spec output2; - /* 0 , chroma sample at odd pixel, 1 - even pixel */ - unsigned char chroma_sample_even; - unsigned char frame_div_mode_en; - unsigned char yuv_y_min; - unsigned char yuv_y_max; - unsigned char yuv_c_min; - unsigned char yuv_c_max; - enum vpfe_chr_pos out_chr_pos; - unsigned char bypass; -}; - -/* Structure for VIDIOC_VPFE_RSZ_[S/G]_CONFIG IOCTLs */ -struct vpfe_rsz_config { - struct vpfe_rsz_config_params *config; -}; - -#endif /* _DAVINCI_VPFE_USER_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c deleted file mode 100644 index 5d8ba357906b..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ /dev/null @@ -1,1857 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - * - * - * IPIPE allows fine tuning of the input image using different - * tuning modules in IPIPE. Some examples :- Noise filter, Defect - * pixel correction etc. It essentially operate on Bayer Raw data - * or YUV raw data. To do image tuning, application call, - * - */ - -#include -#include - -#include "dm365_ipipe.h" -#include "dm365_ipipe_hw.h" -#include "vpfe_mc_capture.h" - -#define MIN_OUT_WIDTH 32 -#define MIN_OUT_HEIGHT 32 - -/* ipipe input format's */ -static const unsigned int ipipe_input_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, -}; - -/* ipipe output format's */ -static const unsigned int ipipe_output_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, -}; - -static int ipipe_validate_lutdpc_params(struct vpfe_ipipe_lutdpc *lutdpc) -{ - int i; - - if (lutdpc->en > 1 || lutdpc->repl_white > 1 || - lutdpc->dpc_size > LUT_DPC_MAX_SIZE) - return -EINVAL; - - if (lutdpc->en) - return -EINVAL; - - for (i = 0; i < lutdpc->dpc_size; i++) - if (lutdpc->table[i].horz_pos > LUT_DPC_H_POS_MASK || - lutdpc->table[i].vert_pos > LUT_DPC_V_POS_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc; - struct vpfe_ipipe_lutdpc *dpc_param; - - if (!param) { - memset((void *)lutdpc, 0, sizeof(struct vpfe_ipipe_lutdpc)); - goto success; - } - - dpc_param = param; - lutdpc->en = dpc_param->en; - lutdpc->repl_white = dpc_param->repl_white; - lutdpc->dpc_size = dpc_param->dpc_size; - memcpy(&lutdpc->table, &dpc_param->table, - (dpc_param->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry))); - if (ipipe_validate_lutdpc_params(lutdpc) < 0) - return -EINVAL; - -success: - ipipe_set_lutdpc_regs(ipipe->base_addr, ipipe->isp5_base_addr, lutdpc); - - return 0; -} - -static int ipipe_get_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_lutdpc *lut_param = param; - struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc; - - lut_param->en = lutdpc->en; - lut_param->repl_white = lutdpc->repl_white; - lut_param->dpc_size = lutdpc->dpc_size; - memcpy(&lut_param->table, &lutdpc->table, - (lutdpc->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry))); - - return 0; -} - -static int ipipe_set_input_config(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - - if (!param) - memset(config, 0, sizeof(struct vpfe_ipipe_input_config)); - else - memcpy(config, param, sizeof(struct vpfe_ipipe_input_config)); - return 0; -} - -static int ipipe_get_input_config(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - - if (!param) - return -EINVAL; - - memcpy(param, config, sizeof(struct vpfe_ipipe_input_config)); - - return 0; -} - -static int ipipe_validate_otfdpc_params(struct vpfe_ipipe_otfdpc *dpc_param) -{ - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0; - struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0; - - if (dpc_param->en > 1) - return -EINVAL; - - if (dpc_param->alg == VPFE_IPIPE_OTFDPC_2_0) { - dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0; - if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK) - return -EINVAL; - return 0; - } - - dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0; - - if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK || - dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK || - dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK || - dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK || - dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK || - dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK || - dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK || - dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK || - dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_otfdpc *dpc_param = param; - struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc; - struct device *dev; - - if (!param) { - memset((void *)otfdpc, 0, sizeof(struct ipipe_otfdpc_2_0)); - goto success; - } - dev = ipipe->subdev.v4l2_dev->dev; - memcpy(otfdpc, dpc_param, sizeof(struct vpfe_ipipe_otfdpc)); - if (ipipe_validate_otfdpc_params(otfdpc) < 0) { - dev_err(dev, "Invalid otfdpc params\n"); - return -EINVAL; - } - -success: - ipipe_set_otfdpc_regs(ipipe->base_addr, otfdpc); - - return 0; -} - -static int ipipe_get_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_otfdpc *dpc_param = param; - struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc; - - memcpy(dpc_param, otfdpc, sizeof(struct vpfe_ipipe_otfdpc)); - return 0; -} - -static int ipipe_validate_nf_params(struct vpfe_ipipe_nf *nf_param) -{ - int i; - - if (nf_param->en > 1 || nf_param->shft_val > D2F_SHFT_VAL_MASK || - nf_param->spread_val > D2F_SPR_VAL_MASK || - nf_param->apply_lsc_gain > 1 || - nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK || - nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_NF_THR_TABLE_SIZE; i++) - if (nf_param->thr[i] > D2F_THR_VAL_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_NF_STR_TABLE_SIZE; i++) - if (nf_param->str[i] > D2F_STR_VAL_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_nf_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_nf *nf_param = param; - struct vpfe_ipipe_nf *nf = &ipipe->config.nf1; - struct device *dev; - - if (id == IPIPE_D2F_2ND) - nf = &ipipe->config.nf2; - - if (!nf_param) { - memset((void *)nf, 0, sizeof(struct vpfe_ipipe_nf)); - goto success; - } - - dev = ipipe->subdev.v4l2_dev->dev; - memcpy(nf, nf_param, sizeof(struct vpfe_ipipe_nf)); - if (ipipe_validate_nf_params(nf) < 0) { - dev_err(dev, "Invalid nf params\n"); - return -EINVAL; - } - -success: - ipipe_set_d2f_regs(ipipe->base_addr, id, nf); - - return 0; -} - -static int ipipe_set_nf1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_nf_params(ipipe, IPIPE_D2F_1ST, param); -} - -static int ipipe_set_nf2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_nf_params(ipipe, IPIPE_D2F_2ND, param); -} - -static int ipipe_get_nf_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_nf *nf_param = param; - struct vpfe_ipipe_nf *nf = &ipipe->config.nf1; - - if (id == IPIPE_D2F_2ND) - nf = &ipipe->config.nf2; - - memcpy(nf_param, nf, sizeof(struct vpfe_ipipe_nf)); - - return 0; -} - -static int ipipe_get_nf1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_nf_params(ipipe, IPIPE_D2F_1ST, param); -} - -static int ipipe_get_nf2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_nf_params(ipipe, IPIPE_D2F_2ND, param); -} - -static int ipipe_validate_gic_params(struct vpfe_ipipe_gic *gic) -{ - if (gic->en > 1 || gic->gain > GIC_GAIN_MASK || - gic->thr > GIC_THR_MASK || gic->slope > GIC_SLOPE_MASK || - gic->apply_lsc_gain > 1 || - gic->nf2_thr_gain.integer > GIC_NFGAN_INT_MASK || - gic->nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_gic_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gic *gic_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_gic *gic = &ipipe->config.gic; - - if (!gic_param) { - memset((void *)gic, 0, sizeof(struct vpfe_ipipe_gic)); - goto success; - } - - memcpy(gic, gic_param, sizeof(struct vpfe_ipipe_gic)); - if (ipipe_validate_gic_params(gic) < 0) { - dev_err(dev, "Invalid gic params\n"); - return -EINVAL; - } - -success: - ipipe_set_gic_regs(ipipe->base_addr, gic); - - return 0; -} - -static int ipipe_get_gic_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gic *gic_param = param; - struct vpfe_ipipe_gic *gic = &ipipe->config.gic; - - memcpy(gic_param, gic, sizeof(struct vpfe_ipipe_gic)); - - return 0; -} - -static int ipipe_validate_wb_params(struct vpfe_ipipe_wb *wbal) -{ - if (wbal->ofst_r > WB_OFFSET_MASK || - wbal->ofst_gr > WB_OFFSET_MASK || - wbal->ofst_gb > WB_OFFSET_MASK || - wbal->ofst_b > WB_OFFSET_MASK || - wbal->gain_r.integer > WB_GAIN_INT_MASK || - wbal->gain_r.decimal > WB_GAIN_DECI_MASK || - wbal->gain_gr.integer > WB_GAIN_INT_MASK || - wbal->gain_gr.decimal > WB_GAIN_DECI_MASK || - wbal->gain_gb.integer > WB_GAIN_INT_MASK || - wbal->gain_gb.decimal > WB_GAIN_DECI_MASK || - wbal->gain_b.integer > WB_GAIN_INT_MASK || - wbal->gain_b.decimal > WB_GAIN_DECI_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_wb_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_wb *wb_param = param; - struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal; - - if (!wb_param) { - const struct vpfe_ipipe_wb wb_defaults = { - .gain_r = {2, 0x0}, - .gain_gr = {2, 0x0}, - .gain_gb = {2, 0x0}, - .gain_b = {2, 0x0} - }; - memcpy(wbal, &wb_defaults, sizeof(struct vpfe_ipipe_wb)); - goto success; - } - - memcpy(wbal, wb_param, sizeof(struct vpfe_ipipe_wb)); - if (ipipe_validate_wb_params(wbal) < 0) - return -EINVAL; - -success: - ipipe_set_wb_regs(ipipe->base_addr, wbal); - - return 0; -} - -static int ipipe_get_wb_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_wb *wb_param = param; - struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal; - - memcpy(wb_param, wbal, sizeof(struct vpfe_ipipe_wb)); - return 0; -} - -static int ipipe_validate_cfa_params(struct vpfe_ipipe_cfa *cfa) -{ - if (cfa->hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK || - cfa->hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK || - cfa->hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK || - cfa->hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK || - cfa->dir_thr_2dir > CFA_DIR_THR_2DIR_MASK || - cfa->dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK || - cfa->nd_wt_2dir > CFA_ND_WT_2DIR_MASK || - cfa->hue_fract_daa > CFA_DAA_HUE_FRA_MASK || - cfa->edge_thr_daa > CFA_DAA_EDG_THR_MASK || - cfa->thr_min_daa > CFA_DAA_THR_MIN_MASK || - cfa->thr_slope_daa > CFA_DAA_THR_SLP_MASK || - cfa->slope_min_daa > CFA_DAA_SLP_MIN_MASK || - cfa->slope_slope_daa > CFA_DAA_SLP_SLP_MASK || - cfa->lp_wt_daa > CFA_DAA_LP_WT_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_cfa_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cfa *cfa_param = param; - struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa; - - if (!cfa_param) { - memset(cfa, 0, sizeof(struct vpfe_ipipe_cfa)); - cfa->alg = VPFE_IPIPE_CFA_ALG_2DIRAC; - goto success; - } - - memcpy(cfa, cfa_param, sizeof(struct vpfe_ipipe_cfa)); - if (ipipe_validate_cfa_params(cfa) < 0) - return -EINVAL; - -success: - ipipe_set_cfa_regs(ipipe->base_addr, cfa); - - return 0; -} - -static int ipipe_get_cfa_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cfa *cfa_param = param; - struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa; - - memcpy(cfa_param, cfa, sizeof(struct vpfe_ipipe_cfa)); - return 0; -} - -static int -ipipe_validate_rgb2rgb_params(struct vpfe_ipipe_rgb2rgb *rgb2rgb, - unsigned int id) -{ - u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK; - u32 offset_upper = RGB2RGB_1_OFST_MASK; - - if (id == IPIPE_RGB2RGB_2) { - offset_upper = RGB2RGB_2_OFST_MASK; - gain_int_upper = RGB2RGB_2_GAIN_INT_MASK; - } - - if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rr.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gr.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_br.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_bg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_bb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->out_ofst_r > offset_upper || - rgb2rgb->out_ofst_g > offset_upper || - rgb2rgb->out_ofst_b > offset_upper) - return -EINVAL; - - return 0; -} - -static int ipipe_set_rgb2rgb_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_rgb2rgb *rgb2rgb_param; - - rgb2rgb_param = param; - - if (id == IPIPE_RGB2RGB_2) - rgb2rgb = &ipipe->config.rgb2rgb2; - - if (!rgb2rgb_param) { - const struct vpfe_ipipe_rgb2rgb rgb2rgb_defaults = { - .coef_rr = {1, 0}, /* 256 */ - .coef_gr = {0, 0}, - .coef_br = {0, 0}, - .coef_rg = {0, 0}, - .coef_gg = {1, 0}, /* 256 */ - .coef_bg = {0, 0}, - .coef_rb = {0, 0}, - .coef_gb = {0, 0}, - .coef_bb = {1, 0}, /* 256 */ - }; - /* Copy defaults for rgb2rgb conversion */ - memcpy(rgb2rgb, &rgb2rgb_defaults, - sizeof(struct vpfe_ipipe_rgb2rgb)); - goto success; - } - - memcpy(rgb2rgb, rgb2rgb_param, sizeof(struct vpfe_ipipe_rgb2rgb)); - if (ipipe_validate_rgb2rgb_params(rgb2rgb, id) < 0) { - dev_err(dev, "Invalid rgb2rgb params\n"); - return -EINVAL; - } - -success: - ipipe_set_rgb2rgb_regs(ipipe->base_addr, id, rgb2rgb); - - return 0; -} - -static int -ipipe_set_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param); -} - -static int -ipipe_set_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param); -} - -static int ipipe_get_rgb2rgb_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1; - struct vpfe_ipipe_rgb2rgb *rgb2rgb_param; - - rgb2rgb_param = param; - - if (id == IPIPE_RGB2RGB_2) - rgb2rgb = &ipipe->config.rgb2rgb2; - - memcpy(rgb2rgb_param, rgb2rgb, sizeof(struct vpfe_ipipe_rgb2rgb)); - - return 0; -} - -static int -ipipe_get_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param); -} - -static int -ipipe_get_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param); -} - -static int -ipipe_validate_gamma_entry(struct vpfe_ipipe_gamma_entry *table, int size) -{ - int i; - - if (!table) - return -EINVAL; - - for (i = 0; i < size; i++) - if (table[i].slope > GAMMA_MASK || - table[i].offset > GAMMA_MASK) - return -EINVAL; - - return 0; -} - -static int -ipipe_validate_gamma_params(struct vpfe_ipipe_gamma *gamma, struct device *dev) -{ - int table_size; - int err; - - if (gamma->bypass_r > 1 || - gamma->bypass_b > 1 || - gamma->bypass_g > 1) - return -EINVAL; - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return 0; - - table_size = gamma->tbl_size; - if (!gamma->bypass_r) { - err = ipipe_validate_gamma_entry(gamma->table_r, table_size); - if (err) { - dev_err(dev, "GAMMA R - table entry invalid\n"); - return err; - } - } - - if (!gamma->bypass_b) { - err = ipipe_validate_gamma_entry(gamma->table_b, table_size); - if (err) { - dev_err(dev, "GAMMA B - table entry invalid\n"); - return err; - } - } - - if (!gamma->bypass_g) { - err = ipipe_validate_gamma_entry(gamma->table_g, table_size); - if (err) { - dev_err(dev, "GAMMA G - table entry invalid\n"); - return err; - } - } - - return 0; -} - -static int -ipipe_set_gamma_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gamma *gamma_param = param; - struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - int table_size; - - if (!gamma_param) { - memset(gamma, 0, sizeof(struct vpfe_ipipe_gamma)); - gamma->tbl_sel = VPFE_IPIPE_GAMMA_TBL_ROM; - goto success; - } - - gamma->bypass_r = gamma_param->bypass_r; - gamma->bypass_b = gamma_param->bypass_b; - gamma->bypass_g = gamma_param->bypass_g; - gamma->tbl_sel = gamma_param->tbl_sel; - gamma->tbl_size = gamma_param->tbl_size; - - if (ipipe_validate_gamma_params(gamma, dev) < 0) - return -EINVAL; - - if (gamma_param->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - goto success; - - table_size = gamma->tbl_size; - if (!gamma_param->bypass_r) - memcpy(&gamma->table_r, &gamma_param->table_r, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma_param->bypass_b) - memcpy(&gamma->table_b, &gamma_param->table_b, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma_param->bypass_g) - memcpy(&gamma->table_g, &gamma_param->table_g, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - -success: - ipipe_set_gamma_regs(ipipe->base_addr, ipipe->isp5_base_addr, gamma); - - return 0; -} - -static int ipipe_get_gamma_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gamma *gamma_param = param; - struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - int table_size; - - gamma_param->bypass_r = gamma->bypass_r; - gamma_param->bypass_g = gamma->bypass_g; - gamma_param->bypass_b = gamma->bypass_b; - gamma_param->tbl_sel = gamma->tbl_sel; - gamma_param->tbl_size = gamma->tbl_size; - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return 0; - - table_size = gamma->tbl_size; - - if (!gamma->bypass_r) { - dev_err(dev, - "%s: table ptr empty for R\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_r, gamma->table_r, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma->bypass_g) { - dev_err(dev, "%s: table ptr empty for G\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_g, gamma->table_g, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma->bypass_b) { - dev_err(dev, "%s: table ptr empty for B\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_b, gamma->table_b, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - return 0; -} - -static int ipipe_validate_3d_lut_params(struct vpfe_ipipe_3d_lut *lut) -{ - int i; - - if (!lut->en) - return 0; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) - if (lut->table[i].r > D3_LUT_ENTRY_MASK || - lut->table[i].g > D3_LUT_ENTRY_MASK || - lut->table[i].b > D3_LUT_ENTRY_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_get_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_3d_lut *lut_param = param; - struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut; - - lut_param->en = lut->en; - - memcpy(lut_param->table, &lut->table, - (VPFE_IPIPE_MAX_SIZE_3D_LUT * - sizeof(struct vpfe_ipipe_3d_lut_entry))); - - return 0; -} - -static int -ipipe_set_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_3d_lut *lut_param = param; - struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - if (!lut_param) { - memset(lut, 0, sizeof(struct vpfe_ipipe_3d_lut)); - goto success; - } - - memcpy(lut, lut_param, sizeof(struct vpfe_ipipe_3d_lut)); - if (ipipe_validate_3d_lut_params(lut) < 0) { - dev_err(dev, "Invalid 3D-LUT Params\n"); - return -EINVAL; - } - -success: - ipipe_set_3d_lut_regs(ipipe->base_addr, ipipe->isp5_base_addr, lut); - - return 0; -} - -static int ipipe_validate_rgb2yuv_params(struct vpfe_ipipe_rgb2yuv *rgb2yuv) -{ - if (rgb2yuv->coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_ry.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gy.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_by.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->out_ofst_y > RGB2YCBCR_OFST_MASK || - rgb2yuv->out_ofst_cb > RGB2YCBCR_OFST_MASK || - rgb2yuv->out_ofst_cr > RGB2YCBCR_OFST_MASK) - return -EINVAL; - - return 0; -} - -static int -ipipe_set_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_rgb2yuv *rgb2yuv_param; - - rgb2yuv_param = param; - if (!rgb2yuv_param) { - /* Defaults for rgb2yuv conversion */ - const struct vpfe_ipipe_rgb2yuv rgb2yuv_defaults = { - .coef_ry = {0, 0x4d}, - .coef_gy = {0, 0x96}, - .coef_by = {0, 0x1d}, - .coef_rcb = {0xf, 0xd5}, - .coef_gcb = {0xf, 0xab}, - .coef_bcb = {0, 0x80}, - .coef_rcr = {0, 0x80}, - .coef_gcr = {0xf, 0x95}, - .coef_bcr = {0xf, 0xeb}, - .out_ofst_cb = 0x80, - .out_ofst_cr = 0x80, - }; - /* Copy defaults for rgb2yuv conversion */ - memcpy(rgb2yuv, &rgb2yuv_defaults, - sizeof(struct vpfe_ipipe_rgb2yuv)); - goto success; - } - - memcpy(rgb2yuv, rgb2yuv_param, sizeof(struct vpfe_ipipe_rgb2yuv)); - if (ipipe_validate_rgb2yuv_params(rgb2yuv) < 0) { - dev_err(dev, "Invalid rgb2yuv params\n"); - return -EINVAL; - } - -success: - ipipe_set_rgb2ycbcr_regs(ipipe->base_addr, rgb2yuv); - - return 0; -} - -static int -ipipe_get_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv; - struct vpfe_ipipe_rgb2yuv *rgb2yuv_param; - - rgb2yuv_param = param; - memcpy(rgb2yuv_param, rgb2yuv, sizeof(struct vpfe_ipipe_rgb2yuv)); - return 0; -} - -static int ipipe_validate_gbce_params(struct vpfe_ipipe_gbce *gbce) -{ - u32 max = GBCE_Y_VAL_MASK; - int i; - - if (!gbce->en) - return 0; - - if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL) - max = GBCE_GAIN_VAL_MASK; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; i++) - if (gbce->table[i] > max) - return -EINVAL; - - return 0; -} - -static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gbce *gbce_param = param; - struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - if (!gbce_param) { - memset(gbce, 0, sizeof(struct vpfe_ipipe_gbce)); - } else { - memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce)); - if (ipipe_validate_gbce_params(gbce) < 0) { - dev_err(dev, "Invalid gbce params\n"); - return -EINVAL; - } - } - - ipipe_set_gbce_regs(ipipe->base_addr, ipipe->isp5_base_addr, gbce); - - return 0; -} - -static int ipipe_get_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gbce *gbce_param = param; - struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce; - - gbce_param->en = gbce->en; - gbce_param->type = gbce->type; - - memcpy(gbce_param->table, gbce->table, - (VPFE_IPIPE_MAX_SIZE_GBCE_LUT * sizeof(unsigned short))); - - return 0; -} - -static int -ipipe_validate_yuv422_conv_params(struct vpfe_ipipe_yuv422_conv *yuv422_conv) -{ - if (yuv422_conv->en_chrom_lpf > 1) - return -EINVAL; - - return 0; -} - -static int -ipipe_set_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv; - struct vpfe_ipipe_yuv422_conv *yuv422_conv_param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - yuv422_conv_param = param; - if (!yuv422_conv_param) { - memset(yuv422_conv, 0, sizeof(struct vpfe_ipipe_yuv422_conv)); - yuv422_conv->chrom_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE; - } else { - memcpy(yuv422_conv, yuv422_conv_param, - sizeof(struct vpfe_ipipe_yuv422_conv)); - if (ipipe_validate_yuv422_conv_params(yuv422_conv) < 0) { - dev_err(dev, "Invalid yuv422 params\n"); - return -EINVAL; - } - } - - ipipe_set_yuv422_conv_regs(ipipe->base_addr, yuv422_conv); - - return 0; -} - -static int -ipipe_get_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv; - struct vpfe_ipipe_yuv422_conv *yuv422_conv_param; - - yuv422_conv_param = param; - memcpy(yuv422_conv_param, yuv422_conv, - sizeof(struct vpfe_ipipe_yuv422_conv)); - - return 0; -} - -static int ipipe_validate_yee_params(struct vpfe_ipipe_yee *yee) -{ - int i; - - if (yee->en > 1 || - yee->en_halo_red > 1 || - yee->hpf_shft > YEE_HPF_SHIFT_MASK) - return -EINVAL; - - if (yee->hpf_coef_00 > YEE_COEF_MASK || - yee->hpf_coef_01 > YEE_COEF_MASK || - yee->hpf_coef_02 > YEE_COEF_MASK || - yee->hpf_coef_10 > YEE_COEF_MASK || - yee->hpf_coef_11 > YEE_COEF_MASK || - yee->hpf_coef_12 > YEE_COEF_MASK || - yee->hpf_coef_20 > YEE_COEF_MASK || - yee->hpf_coef_21 > YEE_COEF_MASK || - yee->hpf_coef_22 > YEE_COEF_MASK) - return -EINVAL; - - if (yee->yee_thr > YEE_THR_MASK || - yee->es_gain > YEE_ES_GAIN_MASK || - yee->es_thr1 > YEE_ES_THR1_MASK || - yee->es_thr2 > YEE_THR_MASK || - yee->es_gain_grad > YEE_THR_MASK || - yee->es_ofst_grad > YEE_THR_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT; i++) - if (yee->table[i] > YEE_ENTRY_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_yee_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yee *yee_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_yee *yee = &ipipe->config.yee; - - if (!yee_param) { - memset(yee, 0, sizeof(struct vpfe_ipipe_yee)); - } else { - memcpy(yee, yee_param, sizeof(struct vpfe_ipipe_yee)); - if (ipipe_validate_yee_params(yee) < 0) { - dev_err(dev, "Invalid yee params\n"); - return -EINVAL; - } - } - - ipipe_set_ee_regs(ipipe->base_addr, ipipe->isp5_base_addr, yee); - - return 0; -} - -static int ipipe_get_yee_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yee *yee_param = param; - struct vpfe_ipipe_yee *yee = &ipipe->config.yee; - - yee_param->en = yee->en; - yee_param->en_halo_red = yee->en_halo_red; - yee_param->merge_meth = yee->merge_meth; - yee_param->hpf_shft = yee->hpf_shft; - yee_param->hpf_coef_00 = yee->hpf_coef_00; - yee_param->hpf_coef_01 = yee->hpf_coef_01; - yee_param->hpf_coef_02 = yee->hpf_coef_02; - yee_param->hpf_coef_10 = yee->hpf_coef_10; - yee_param->hpf_coef_11 = yee->hpf_coef_11; - yee_param->hpf_coef_12 = yee->hpf_coef_12; - yee_param->hpf_coef_20 = yee->hpf_coef_20; - yee_param->hpf_coef_21 = yee->hpf_coef_21; - yee_param->hpf_coef_22 = yee->hpf_coef_22; - yee_param->yee_thr = yee->yee_thr; - yee_param->es_gain = yee->es_gain; - yee_param->es_thr1 = yee->es_thr1; - yee_param->es_thr2 = yee->es_thr2; - yee_param->es_gain_grad = yee->es_gain_grad; - yee_param->es_ofst_grad = yee->es_ofst_grad; - memcpy(yee_param->table, &yee->table, - (VPFE_IPIPE_MAX_SIZE_YEE_LUT * sizeof(short))); - - return 0; -} - -static int ipipe_validate_car_params(struct vpfe_ipipe_car *car) -{ - if (car->en > 1 || car->hpf_shft > CAR_HPF_SHIFT_MASK || - car->gain1.shft > CAR_GAIN1_SHFT_MASK || - car->gain1.gain_min > CAR_GAIN_MIN_MASK || - car->gain2.shft > CAR_GAIN2_SHFT_MASK || - car->gain2.gain_min > CAR_GAIN_MIN_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_car *car_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_car *car = &ipipe->config.car; - - if (!car_param) { - memset(car, 0, sizeof(struct vpfe_ipipe_car)); - } else { - memcpy(car, car_param, sizeof(struct vpfe_ipipe_car)); - if (ipipe_validate_car_params(car) < 0) { - dev_err(dev, "Invalid car params\n"); - return -EINVAL; - } - } - - ipipe_set_car_regs(ipipe->base_addr, car); - - return 0; -} - -static int ipipe_get_car_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_car *car_param = param; - struct vpfe_ipipe_car *car = &ipipe->config.car; - - memcpy(car_param, car, sizeof(struct vpfe_ipipe_car)); - return 0; -} - -static int ipipe_validate_cgs_params(struct vpfe_ipipe_cgs *cgs) -{ - if (cgs->en > 1 || cgs->h_shft > CAR_SHIFT_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_cgs_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cgs *cgs_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs; - - if (!cgs_param) { - memset(cgs, 0, sizeof(struct vpfe_ipipe_cgs)); - } else { - memcpy(cgs, cgs_param, sizeof(struct vpfe_ipipe_cgs)); - if (ipipe_validate_cgs_params(cgs) < 0) { - dev_err(dev, "Invalid cgs params\n"); - return -EINVAL; - } - } - - ipipe_set_cgs_regs(ipipe->base_addr, cgs); - - return 0; -} - -static int ipipe_get_cgs_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cgs *cgs_param = param; - struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs; - - memcpy(cgs_param, cgs, sizeof(struct vpfe_ipipe_cgs)); - - return 0; -} - -static const struct ipipe_module_if ipipe_modules[VPFE_IPIPE_MAX_MODULES] = { - /* VPFE_IPIPE_INPUT_CONFIG */ { - offsetof(struct ipipe_module_params, input_config), - FIELD_SIZEOF(struct ipipe_module_params, input_config), - offsetof(struct vpfe_ipipe_config, input_config), - ipipe_set_input_config, - ipipe_get_input_config, - }, /* VPFE_IPIPE_LUTDPC */ { - offsetof(struct ipipe_module_params, lutdpc), - FIELD_SIZEOF(struct ipipe_module_params, lutdpc), - offsetof(struct vpfe_ipipe_config, lutdpc), - ipipe_set_lutdpc_params, - ipipe_get_lutdpc_params, - }, /* VPFE_IPIPE_OTFDPC */ { - offsetof(struct ipipe_module_params, otfdpc), - FIELD_SIZEOF(struct ipipe_module_params, otfdpc), - offsetof(struct vpfe_ipipe_config, otfdpc), - ipipe_set_otfdpc_params, - ipipe_get_otfdpc_params, - }, /* VPFE_IPIPE_NF1 */ { - offsetof(struct ipipe_module_params, nf1), - FIELD_SIZEOF(struct ipipe_module_params, nf1), - offsetof(struct vpfe_ipipe_config, nf1), - ipipe_set_nf1_params, - ipipe_get_nf1_params, - }, /* VPFE_IPIPE_NF2 */ { - offsetof(struct ipipe_module_params, nf2), - FIELD_SIZEOF(struct ipipe_module_params, nf2), - offsetof(struct vpfe_ipipe_config, nf2), - ipipe_set_nf2_params, - ipipe_get_nf2_params, - }, /* VPFE_IPIPE_WB */ { - offsetof(struct ipipe_module_params, wbal), - FIELD_SIZEOF(struct ipipe_module_params, wbal), - offsetof(struct vpfe_ipipe_config, wbal), - ipipe_set_wb_params, - ipipe_get_wb_params, - }, /* VPFE_IPIPE_RGB2RGB_1 */ { - offsetof(struct ipipe_module_params, rgb2rgb1), - FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb1), - offsetof(struct vpfe_ipipe_config, rgb2rgb1), - ipipe_set_rgb2rgb_1_params, - ipipe_get_rgb2rgb_1_params, - }, /* VPFE_IPIPE_RGB2RGB_2 */ { - offsetof(struct ipipe_module_params, rgb2rgb2), - FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb2), - offsetof(struct vpfe_ipipe_config, rgb2rgb2), - ipipe_set_rgb2rgb_2_params, - ipipe_get_rgb2rgb_2_params, - }, /* VPFE_IPIPE_GAMMA */ { - offsetof(struct ipipe_module_params, gamma), - FIELD_SIZEOF(struct ipipe_module_params, gamma), - offsetof(struct vpfe_ipipe_config, gamma), - ipipe_set_gamma_params, - ipipe_get_gamma_params, - }, /* VPFE_IPIPE_3D_LUT */ { - offsetof(struct ipipe_module_params, lut), - FIELD_SIZEOF(struct ipipe_module_params, lut), - offsetof(struct vpfe_ipipe_config, lut), - ipipe_set_3d_lut_params, - ipipe_get_3d_lut_params, - }, /* VPFE_IPIPE_RGB2YUV */ { - offsetof(struct ipipe_module_params, rgb2yuv), - FIELD_SIZEOF(struct ipipe_module_params, rgb2yuv), - offsetof(struct vpfe_ipipe_config, rgb2yuv), - ipipe_set_rgb2yuv_params, - ipipe_get_rgb2yuv_params, - }, /* VPFE_IPIPE_YUV422_CONV */ { - offsetof(struct ipipe_module_params, yuv422_conv), - FIELD_SIZEOF(struct ipipe_module_params, yuv422_conv), - offsetof(struct vpfe_ipipe_config, yuv422_conv), - ipipe_set_yuv422_conv_params, - ipipe_get_yuv422_conv_params, - }, /* VPFE_IPIPE_YEE */ { - offsetof(struct ipipe_module_params, yee), - FIELD_SIZEOF(struct ipipe_module_params, yee), - offsetof(struct vpfe_ipipe_config, yee), - ipipe_set_yee_params, - ipipe_get_yee_params, - }, /* VPFE_IPIPE_GIC */ { - offsetof(struct ipipe_module_params, gic), - FIELD_SIZEOF(struct ipipe_module_params, gic), - offsetof(struct vpfe_ipipe_config, gic), - ipipe_set_gic_params, - ipipe_get_gic_params, - }, /* VPFE_IPIPE_CFA */ { - offsetof(struct ipipe_module_params, cfa), - FIELD_SIZEOF(struct ipipe_module_params, cfa), - offsetof(struct vpfe_ipipe_config, cfa), - ipipe_set_cfa_params, - ipipe_get_cfa_params, - }, /* VPFE_IPIPE_CAR */ { - offsetof(struct ipipe_module_params, car), - FIELD_SIZEOF(struct ipipe_module_params, car), - offsetof(struct vpfe_ipipe_config, car), - ipipe_set_car_params, - ipipe_get_car_params, - }, /* VPFE_IPIPE_CGS */ { - offsetof(struct ipipe_module_params, cgs), - FIELD_SIZEOF(struct ipipe_module_params, cgs), - offsetof(struct vpfe_ipipe_config, cgs), - ipipe_set_cgs_params, - ipipe_get_cgs_params, - }, /* VPFE_IPIPE_GBCE */ { - offsetof(struct ipipe_module_params, gbce), - FIELD_SIZEOF(struct ipipe_module_params, gbce), - offsetof(struct vpfe_ipipe_config, gbce), - ipipe_set_gbce_params, - ipipe_get_gbce_params, - }, -}; - -static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - unsigned int i; - int rval = 0; - struct ipipe_module_params *params; - - for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) { - const struct ipipe_module_if *module_if; - void *from, *to; - size_t size; - - if (!(cfg->flag & BIT(i))) - continue; - - module_if = &ipipe_modules[i]; - from = *(void **)((void *)cfg + module_if->config_offset); - - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - to = (void *)params + module_if->param_offset; - size = module_if->param_size; - - if (to && from && size) { - if (copy_from_user(to, (void __user *)from, size)) { - rval = -EFAULT; - goto error_free; - } - rval = module_if->set(ipipe, to); - if (rval) - goto error_free; - } else if (to && !from && size) { - rval = module_if->set(ipipe, NULL); - if (rval) - goto error_free; - } - kfree(params); - } - return rval; - -error_free: - kfree(params); - return rval; -} - -static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - unsigned int i; - int rval = 0; - - for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) { - const struct ipipe_module_if *module_if; - struct ipipe_module_params *params; - void *from, *to; - size_t size; - - if (!(cfg->flag & BIT(i))) - continue; - - module_if = &ipipe_modules[i]; - to = *(void **)((void *)cfg + module_if->config_offset); - - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - rval = -ENOMEM; - goto error; - } - - from = (void *)params + module_if->param_offset; - size = module_if->param_size; - - if (to && from && size) { - rval = module_if->get(ipipe, from); - if (rval) - goto error; - if (copy_to_user((void __user *)to, from, size)) { - rval = -EFAULT; - break; - } - } - kfree(params); - } -error: - return rval; -} - -/* - * ipipe_ioctl() - Handle ipipe module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long ipipe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_VPFE_IPIPE_S_CONFIG: - return ipipe_s_config(sd, arg); - - case VIDIOC_VPFE_IPIPE_G_CONFIG: - return ipipe_g_config(sd, arg); - - default: - return -ENOIOCTLCMD; - } -} - -void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - struct vpfe_ipipe_device *ipipe = &vpfe_dev->vpfe_ipipe; - unsigned char val; - - if (ipipe->input == IPIPE_INPUT_NONE) - return; - - /* ipipe is set to single shot */ - if (ipipeif->input == IPIPEIF_INPUT_MEMORY && en) { - /* for single-shot mode, need to wait for h/w to - * reset many register bits - */ - do { - val = regr_ip(vpfe_dev->vpfe_ipipe.base_addr, - IPIPE_SRC_EN); - } while (val); - } - regw_ip(vpfe_dev->vpfe_ipipe.base_addr, en, IPIPE_SRC_EN); -} - -/* - * ipipe_set_stream() - Enable/Disable streaming on the ipipe subdevice - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - - if (enable && ipipe->input != IPIPE_INPUT_NONE && - ipipe->output != IPIPE_OUTPUT_NONE) { - if (config_ipipe_hw(ipipe) < 0) - return -EINVAL; - } - - vpfe_ipipe_enable(vpfe_dev, enable); - - return 0; -} - -/* - * __ipipe_get_format() - helper function for getting ipipe format - * @ipipe: pointer to ipipe private structure. - * @pad: pad number. - * @cfg: V4L2 subdev pad config - * @which: wanted subdev format. - * - */ -static struct v4l2_mbus_framefmt * -__ipipe_get_format(struct vpfe_ipipe_device *ipipe, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad); - - return &ipipe->formats[pad]; -} - -/* - * ipipe_try_format() - Handle try format by pad subdev method - * @ipipe: VPFE ipipe device. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which : wanted subdev format - */ -static void -ipipe_try_format(struct vpfe_ipipe_device *ipipe, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - if (pad == IPIPE_PAD_SINK) { - for (i = 0; i < ARRAY_SIZE(ipipe_input_fmts); i++) - if (fmt->code == ipipe_input_fmts[i]) - break; - - /* If not found, use SBGGR10 as default */ - if (i >= ARRAY_SIZE(ipipe_input_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG12_1X12; - } else if (pad == IPIPE_PAD_SOURCE) { - for (i = 0; i < ARRAY_SIZE(ipipe_output_fmts); i++) - if (fmt->code == ipipe_output_fmts[i]) - break; - - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(ipipe_output_fmts)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - } - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width); - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height); -} - -/* - * ipipe_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int -ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == IPIPE_PAD_SINK && - (ipipe->input == IPIPE_INPUT_CCDC || - ipipe->input == IPIPE_INPUT_MEMORY)) - ipipe->formats[fmt->pad] = fmt->format; - else if (fmt->pad == IPIPE_PAD_SOURCE && - ipipe->output == IPIPE_OUTPUT_RESIZER) - ipipe->formats[fmt->pad] = fmt->format; - else - return -EINVAL; - - return 0; -} - -/* - * ipipe_get_format() - Handle get format by pads subdev method. - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure. - */ -static int -ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - fmt->format = ipipe->formats[fmt->pad]; - else - fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad)); - - return 0; -} - -/* - * ipipe_enum_frame_size() - enum frame sizes on pads - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fse: pointer to v4l2_subdev_frame_size_enum structure. - */ -static int -ipipe_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * ipipe_enum_mbus_code() - enum mbus codes for pads - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int -ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case IPIPE_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipe_input_fmts)) - return -EINVAL; - code->code = ipipe_input_fmts[code->index]; - break; - - case IPIPE_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(ipipe_output_fmts)) - return -EINVAL; - code->code = ipipe_output_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipe_s_ctrl() - Handle set control subdev method - * @ctrl: pointer to v4l2 control structure - */ -static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_ipipe_device *ipipe = - container_of(ctrl->handler, struct vpfe_ipipe_device, ctrls); - struct ipipe_lum_adj *lum_adj = &ipipe->config.lum_adj; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - lum_adj->brightness = ctrl->val; - ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj); - break; - - case V4L2_CID_CONTRAST: - lum_adj->contrast = ctrl->val; - ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipe_init_formats() - Initialize formats on all pads - * @sd: pointer to v4l2 subdev structure. - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPE_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipe_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = IPIPE_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipe_set_format(sd, fh->pad, &format); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops ipipe_v4l2_core_ops = { - .ioctl = ipipe_ioctl, -}; - -static const struct v4l2_ctrl_ops ipipe_ctrl_ops = { - .s_ctrl = ipipe_s_ctrl, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = { - .open = ipipe_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = { - .s_stream = ipipe_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = { - .enum_mbus_code = ipipe_enum_mbus_code, - .enum_frame_size = ipipe_enum_frame_size, - .get_fmt = ipipe_get_format, - .set_fmt = ipipe_set_format, -}; - -/* v4l2 subdev operation */ -static const struct v4l2_subdev_ops ipipe_v4l2_ops = { - .core = &ipipe_v4l2_core_ops, - .video = &ipipe_v4l2_video_ops, - .pad = &ipipe_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * ipipe_link_setup() - Setup ipipe connections - * @entity: ipipe media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int -ipipe_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - - if (!is_media_entity_v4l2_subdev(remote->entity)) - return -EINVAL; - - switch (local->index) { - case IPIPE_PAD_SINK: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipe->input = IPIPE_INPUT_NONE; - break; - } - if (ipipe->input != IPIPE_INPUT_NONE) - return -EBUSY; - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY) - ipipe->input = IPIPE_INPUT_MEMORY; - else - ipipe->input = IPIPE_INPUT_CCDC; - break; - - case IPIPE_PAD_SOURCE: - /* out to RESIZER */ - if (flags & MEDIA_LNK_FL_ENABLED) - ipipe->output = IPIPE_OUTPUT_RESIZER; - else - ipipe->output = IPIPE_OUTPUT_NONE; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations ipipe_media_ops = { - .link_setup = ipipe_link_setup, -}; - -/* - * vpfe_ipipe_unregister_entities() - ipipe unregister entity - * @vpfe_ipipe: pointer to ipipe subdevice structure. - */ -void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe) -{ - /* unregister subdev */ - v4l2_device_unregister_subdev(&vpfe_ipipe->subdev); - /* cleanup entity */ - media_entity_cleanup(&vpfe_ipipe->subdev.entity); -} - -/* - * vpfe_ipipe_register_entities() - ipipe register entity - * @ipipe: pointer to ipipe subdevice structure. - * @vdev: pointer to v4l2 device structure. - */ -int -vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &ipipe->subdev); - if (ret) { - pr_err("Failed to register ipipe as v4l2 subdevice\n"); - return ret; - } - - return ret; -} - -#define IPIPE_CONTRAST_HIGH 0xff -#define IPIPE_BRIGHT_HIGH 0xff - -/* - * vpfe_ipipe_init() - ipipe module initialization. - * @ipipe: pointer to ipipe subdevice structure. - * @pdev: platform device pointer. - */ -int -vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev) -{ - struct media_pad *pads = &ipipe->pads[0]; - struct v4l2_subdev *sd = &ipipe->subdev; - struct media_entity *me = &sd->entity; - struct resource *res, *res2, *memres; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - if (!res) - return -ENOENT; - - memres = request_mem_region(res->start, resource_size(res), res->name); - if (!memres) - return -EBUSY; - ipipe->base_addr = ioremap_nocache(memres->start, - resource_size(memres)); - if (!ipipe->base_addr) - goto error_release; - - res2 = platform_get_resource(pdev, IORESOURCE_MEM, 6); - if (!res2) - goto error_unmap; - ipipe->isp5_base_addr = ioremap_nocache(res2->start, - resource_size(res2)); - if (!ipipe->isp5_base_addr) - goto error_unmap; - - v4l2_subdev_init(sd, &ipipe_v4l2_ops); - sd->internal_ops = &ipipe_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, ipipe); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - ipipe->input = IPIPE_INPUT_NONE; - ipipe->output = IPIPE_OUTPUT_NONE; - - me->ops = &ipipe_media_ops; - v4l2_ctrl_handler_init(&ipipe->ctrls, 2); - v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, - IPIPE_BRIGHT_HIGH, 1, 16); - v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops, - V4L2_CID_CONTRAST, 0, - IPIPE_CONTRAST_HIGH, 1, 16); - v4l2_ctrl_handler_setup(&ipipe->ctrls); - sd->ctrl_handler = &ipipe->ctrls; - - return media_entity_pads_init(me, IPIPE_PADS_NUM, pads); - -error_unmap: - iounmap(ipipe->base_addr); -error_release: - release_mem_region(memres->start, resource_size(memres)); - return -ENOMEM; -} - -/* - * vpfe_ipipe_cleanup() - ipipe subdevice cleanup. - * @ipipe: pointer to ipipe subdevice - * @dev: pointer to platform device - */ -void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev) -{ - struct resource *res; - - v4l2_ctrl_handler_free(&ipipe->ctrls); - - iounmap(ipipe->base_addr); - iounmap(ipipe->isp5_base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - if (res) - release_mem_region(res->start, resource_size(res)); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe.h deleted file mode 100644 index 866ae12aeb07..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPE_H -#define _DAVINCI_VPFE_DM365_IPIPE_H - -#include - -#include -#include - -#include "davinci_vpfe_user.h" -#include "vpfe_video.h" - -enum ipipe_noise_filter { - IPIPE_D2F_1ST = 0, - IPIPE_D2F_2ND = 1, -}; - -/* Used for driver storage */ -struct ipipe_otfdpc_2_0 { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - struct vpfe_ipipe_otfdpc_2_0_cfg otfdpc_2_0; -}; - -struct ipipe_otfdpc_3_0 { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - struct vpfe_ipipe_otfdpc_3_0_cfg otfdpc_3_0; -}; - -/* Structure for configuring Luminance Adjustment module */ -struct ipipe_lum_adj { - /* Brightness adjustments */ - unsigned char brightness; - /* contrast adjustments */ - unsigned char contrast; -}; - -enum ipipe_rgb2rgb { - IPIPE_RGB2RGB_1 = 0, - IPIPE_RGB2RGB_2 = 1, -}; - -struct ipipe_module_params { - __u32 flag; - struct vpfe_ipipe_input_config input_config; - struct vpfe_ipipe_lutdpc lutdpc; - struct vpfe_ipipe_otfdpc otfdpc; - struct vpfe_ipipe_nf nf1; - struct vpfe_ipipe_nf nf2; - struct vpfe_ipipe_gic gic; - struct vpfe_ipipe_wb wbal; - struct vpfe_ipipe_cfa cfa; - struct vpfe_ipipe_rgb2rgb rgb2rgb1; - struct vpfe_ipipe_rgb2rgb rgb2rgb2; - struct vpfe_ipipe_gamma gamma; - struct vpfe_ipipe_3d_lut lut; - struct vpfe_ipipe_rgb2yuv rgb2yuv; - struct vpfe_ipipe_gbce gbce; - struct vpfe_ipipe_yuv422_conv yuv422_conv; - struct vpfe_ipipe_yee yee; - struct vpfe_ipipe_car car; - struct vpfe_ipipe_cgs cgs; - struct ipipe_lum_adj lum_adj; -}; - -#define IPIPE_PAD_SINK 0 -#define IPIPE_PAD_SOURCE 1 - -#define IPIPE_PADS_NUM 2 - -#define IPIPE_OUTPUT_NONE 0 -#define IPIPE_OUTPUT_RESIZER (1 << 0) - -enum ipipe_input_entity { - IPIPE_INPUT_NONE = 0, - IPIPE_INPUT_MEMORY = 1, - IPIPE_INPUT_CCDC = 2, -}; - - -struct vpfe_ipipe_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPE_PADS_NUM]; - struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM]; - enum ipipe_input_entity input; - unsigned int output; - struct v4l2_ctrl_handler ctrls; - void __iomem *base_addr; - void __iomem *isp5_base_addr; - struct ipipe_module_params config; -}; - -struct ipipe_module_if { - unsigned int param_offset; - unsigned int param_size; - unsigned int config_offset; - int (*set)(struct vpfe_ipipe_device *ipipe, void *param); - int (*get)(struct vpfe_ipipe_device *ipipe, void *param); -}; - -/* data paths */ -enum ipipe_data_paths { - IPIPE_RAW2YUV, - /* Bayer RAW input to YCbCr output */ - IPIPE_RAW2RAW, - /* Bayer Raw to Bayer output */ - IPIPE_RAW2BOX, - /* Bayer Raw to Boxcar output */ - IPIPE_YUV2YUV - /* YUV Raw to YUV Raw output */ -}; - -#define IPIPE_COLPTN_R_Ye 0x0 -#define IPIPE_COLPTN_Gr_Cy 0x1 -#define IPIPE_COLPTN_Gb_G 0x2 -#define IPIPE_COLPTN_B_Mg 0x3 - -#define COLPAT_EE_SHIFT 0 -#define COLPAT_EO_SHIFT 2 -#define COLPAT_OE_SHIFT 4 -#define COLPAT_OO_SHIFT 6 - -#define ipipe_sgrbg_pattern \ - (IPIPE_COLPTN_Gr_Cy << COLPAT_EE_SHIFT | \ - IPIPE_COLPTN_R_Ye << COLPAT_EO_SHIFT | \ - IPIPE_COLPTN_B_Mg << COLPAT_OE_SHIFT | \ - IPIPE_COLPTN_Gb_G << COLPAT_OO_SHIFT) - -#define ipipe_srggb_pattern \ - (IPIPE_COLPTN_R_Ye << COLPAT_EE_SHIFT | \ - IPIPE_COLPTN_Gr_Cy << COLPAT_EO_SHIFT | \ - IPIPE_COLPTN_Gb_G << COLPAT_OE_SHIFT | \ - IPIPE_COLPTN_B_Mg << COLPAT_OO_SHIFT) - -int vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe, - struct v4l2_device *v4l2_dev); -int vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev); -void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *ipipe); -void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev); -void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en); - -#endif /* _DAVINCI_VPFE_DM365_IPIPE_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c deleted file mode 100644 index 110473c30577..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c +++ /dev/null @@ -1,1038 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#include "dm365_ipipe_hw.h" - -#define IPIPE_MODE_CONTINUOUS 0 -#define IPIPE_MODE_SINGLE_SHOT 1 - -static void ipipe_clock_enable(void __iomem *base_addr) -{ - /* enable IPIPE MMR for register write access */ - regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR); - - /* enable the clock wb,cfa,dfc,d2f,pre modules */ - regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX); -} - -static void -rsz_set_common_params(void __iomem *rsz_base, struct resizer_params *params) -{ - struct rsz_common_params *rsz_common = ¶ms->rsz_common; - u32 val; - - /* Set mode */ - regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE); - - /* data source selection and bypass */ - val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) | - rsz_common->source; - regw_rsz(rsz_base, val, RSZ_SRC_FMT0); - - /* src image selection */ - val = (rsz_common->raw_flip & 1) | - (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) | - ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT); - regw_rsz(rsz_base, val, RSZ_SRC_FMT1); - - regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS); - regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS); - regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ); - regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ); - regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN); - regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX); - regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN); - regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX); - /* chromatic position */ - regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS); -} - -static void -rsz_set_rsz_regs(void __iomem *rsz_base, unsigned int rsz_id, - struct resizer_params *params) -{ - struct resizer_scale_param *rsc_params; - struct rsz_ext_mem_param *ext_mem; - struct resizer_rgb *rgb; - u32 reg_base; - u32 val; - - rsc_params = ¶ms->rsz_rsc_param[rsz_id]; - rgb = ¶ms->rsz2rgb[rsz_id]; - ext_mem = ¶ms->ext_mem_param[rsz_id]; - - if (rsz_id == RSZ_A) { - val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT; - val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT; - reg_base = RSZ_EN_A; - } else { - val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT; - val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT; - reg_base = RSZ_EN_B; - } - /* update flip settings */ - regw_rsz(rsz_base, val, RSZ_SEQ); - - regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE); - - val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen; - regw_rsz(rsz_base, val, reg_base + RSZ_420); - - regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK, - reg_base + RSZ_I_VPS); - regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK, - reg_base + RSZ_I_HPS); - regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK, - reg_base + RSZ_O_VSZ); - regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK, - reg_base + RSZ_O_HSZ); - regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK, - reg_base + RSZ_V_PHS_Y); - regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK, - reg_base + RSZ_V_PHS_C); - - /* keep this additional adjustment to zero for now */ - regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK, - reg_base + RSZ_V_DIF); - - val = (rsc_params->v_typ_y & 1) | - ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP); - - val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) | - ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) << - RSZ_LPF_INT_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF); - - regw_rsz(rsz_base, rsc_params->h_phs & - RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS); - - regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ); - regw_rsz(rsz_base, rsc_params->h_dif & - RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF); - - val = (rsc_params->h_typ_y & 1) | - ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP); - - val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) | - ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) << - RSZ_LPF_INT_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF); - - regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN); - - val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) | - ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) << - RSZ_DWN_SCALE_AV_SZ_V_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV); - - /* setting rgb conversion parameters */ - regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN); - - val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) | - (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) | - (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP); - - regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK, - reg_base + RSZ_RGB_BLD); - - /* setting external memory parameters */ - regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y, - reg_base + RSZ_SDR_Y_PTR_S); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y, - reg_base + RSZ_SDR_Y_PTR_E); - regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c, - reg_base + RSZ_SDR_C_PTR_S); - regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1), - reg_base + RSZ_SDR_C_PTR_E); -} - -/*set the registers of either RSZ0 or RSZ1 */ -static void -ipipe_setup_resizer(void __iomem *rsz_base, struct resizer_params *params) -{ - /* enable MMR gate to write to Resizer */ - regw_rsz(rsz_base, 1, RSZ_GCK_MMR); - - /* Enable resizer if it is not in bypass mode */ - if (params->rsz_common.passthrough) - regw_rsz(rsz_base, 0, RSZ_GCK_SDR); - else - regw_rsz(rsz_base, 1, RSZ_GCK_SDR); - - rsz_set_common_params(rsz_base, params); - - regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A); - - if (params->rsz_en[RSZ_A]) - /*setting rescale parameters */ - rsz_set_rsz_regs(rsz_base, RSZ_A, params); - - regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B); - - if (params->rsz_en[RSZ_B]) - rsz_set_rsz_regs(rsz_base, RSZ_B, params); -} - -static u32 ipipe_get_color_pat(u32 pix) -{ - switch (pix) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return ipipe_sgrbg_pattern; - - default: - return ipipe_srggb_pattern; - } -} - -static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe) -{ - u32 temp_pix_fmt; - - switch (ipipe->formats[IPIPE_PAD_SINK].code) { - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - temp_pix_fmt = MEDIA_BUS_FMT_SGRBG12_1X12; - break; - - default: - temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8; - } - - if (temp_pix_fmt == MEDIA_BUS_FMT_SGRBG12_1X12) { - if (ipipe->formats[IPIPE_PAD_SOURCE].code == - MEDIA_BUS_FMT_SGRBG12_1X12) - return IPIPE_RAW2RAW; - return IPIPE_RAW2YUV; - } - - return IPIPE_YUV2YUV; -} - -static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY) - return IPIPE_MODE_SINGLE_SHOT; - if (ipipeif_sink == IPIPEIF_INPUT_ISIF) - return IPIPE_MODE_CONTINUOUS; - - return -EINVAL; -} - -int config_ipipe_hw(struct vpfe_ipipe_device *ipipe) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - void __iomem *ipipe_base = ipipe->base_addr; - struct v4l2_mbus_framefmt *outformat; - u32 color_pat; - int ipipe_mode; - u32 data_path; - - /* enable clock to IPIPE */ - vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); - ipipe_clock_enable(ipipe_base); - - if (ipipe->input == IPIPE_INPUT_NONE) { - regw_ip(ipipe_base, 0, IPIPE_SRC_EN); - return 0; - } - - ipipe_mode = get_ipipe_mode(ipipe); - if (ipipe_mode < 0) { - pr_err("Failed to get ipipe mode"); - return -EINVAL; - } - regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE); - - data_path = ipipe_get_data_path(ipipe); - regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT); - - regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS); - regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS); - - outformat = &ipipe->formats[IPIPE_PAD_SOURCE]; - regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK, - IPIPE_SRC_VSZ); - regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK, - IPIPE_SRC_HSZ); - - if (data_path == IPIPE_RAW2YUV || - data_path == IPIPE_RAW2RAW) { - color_pat = - ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code); - regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL); - } - - return 0; -} - -/* - * config_rsz_hw() - Performs hardware setup of resizer. - */ -int config_rsz_hw(struct vpfe_resizer_device *resizer, - struct resizer_params *config) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - void __iomem *ipipe_base = vpfe_dev->vpfe_ipipe.base_addr; - void __iomem *rsz_base = vpfe_dev->vpfe_resizer.base_addr; - - /* enable VPSS clock */ - vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); - ipipe_clock_enable(ipipe_base); - - ipipe_setup_resizer(rsz_base, config); - - return 0; -} - -static void -rsz_set_y_address(void __iomem *rsz_base, unsigned int address, - unsigned int offset) -{ - u32 val; - - val = address & SET_LOW_ADDR; - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L); - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L); - - val = (address & SET_HIGH_ADDR) >> 16; - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H); - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H); -} - -static void -rsz_set_c_address(void __iomem *rsz_base, unsigned int address, - unsigned int offset) -{ - u32 val; - - val = address & SET_LOW_ADDR; - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L); - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L); - - val = (address & SET_HIGH_ADDR) >> 16; - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H); - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H); -} - -/* - * resizer_set_outaddr() - set the address for given resize_no - * @rsz_base: resizer base address - * @params: pointer to ipipe_params structure - * @resize_no: 0 - Resizer-A, 1 - Resizer B - * @address: the address to set - */ -int -resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params, - int resize_no, unsigned int address) -{ - struct resizer_scale_param *rsc_param; - struct rsz_ext_mem_param *mem_param; - struct rsz_common_params *rsz_common; - unsigned int rsz_start_add; - unsigned int val; - - if (resize_no != RSZ_A && resize_no != RSZ_B) - return -EINVAL; - - mem_param = ¶ms->ext_mem_param[resize_no]; - rsc_param = ¶ms->rsz_rsc_param[resize_no]; - rsz_common = ¶ms->rsz_common; - - if (resize_no == RSZ_A) - rsz_start_add = RSZ_EN_A; - else - rsz_start_add = RSZ_EN_B; - - /* y_c = 0 for y, = 1 for c */ - if (rsz_common->src_img_fmt == RSZ_IMG_420) { - if (rsz_common->y_c) { - /* C channel */ - val = address + mem_param->flip_ofst_c; - rsz_set_c_address(rsz_base, val, rsz_start_add); - } else { - val = address + mem_param->flip_ofst_y; - rsz_set_y_address(rsz_base, val, rsz_start_add); - } - } else { - if (rsc_param->cen && rsc_param->yen) { - /* 420 */ - val = address + mem_param->c_offset + - mem_param->flip_ofst_c + - mem_param->user_y_ofst + - mem_param->user_c_ofst; - if (resize_no == RSZ_B) - val += - params->ext_mem_param[RSZ_A].user_y_ofst + - params->ext_mem_param[RSZ_A].user_c_ofst; - /* set C address */ - rsz_set_c_address(rsz_base, val, rsz_start_add); - } - val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst; - if (resize_no == RSZ_B) - val += params->ext_mem_param[RSZ_A].user_y_ofst + - params->ext_mem_param[RSZ_A].user_c_ofst; - /* set Y address */ - rsz_set_y_address(rsz_base, val, rsz_start_add); - } - /* resizer must be enabled */ - regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add); - - return 0; -} - -void -ipipe_set_lutdpc_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_lutdpc *dpc) -{ - u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1; - u32 lut_start_addr = DPC_TB0_START_ADDR; - u32 val; - u32 count; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, dpc->en, DPC_LUT_EN); - - if (dpc->en != 1) - return; - - val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1); - regw_ip(base_addr, val, DPC_LUT_SEL); - regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR); - regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK); - - for (count = 0; count < dpc->dpc_size; count++) { - if (count >= max_tbl_size) - lut_start_addr = DPC_TB1_START_ADDR; - val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) | - ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) << - LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method << - LUT_DPC_CORR_METH_SHIFT); - w_ip_table(isp5_base_addr, val, (lut_start_addr + - ((count % max_tbl_size) << 2))); - } -} - -static void -set_dpc_thresholds(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr) -{ - regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_R); - regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_GR); - regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_GB); - regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_B); - regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_R); - regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_GR); - regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_GB); - regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_B); -} - -void ipipe_set_otfdpc_regs(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc *otfdpc) -{ - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0; - struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0; - u32 val; - - ipipe_clock_enable(base_addr); - - regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN); - if (!otfdpc->en) - return; - - /* dpc enabled */ - val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg; - regw_ip(base_addr, val, DPC_OTF_TYP); - - if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) { - /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0 - * DPC_OTF_2C_THR_[x] = Maximum thresohld - * MinMax method - */ - dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb = - dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0; - set_dpc_thresholds(base_addr, dpc_2_0); - return; - } - /* MinMax2 */ - if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) { - set_dpc_thresholds(base_addr, dpc_2_0); - return; - } - regw_ip(base_addr, dpc_3_0->act_adj_shf & - OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF); - /* Detection thresholds */ - regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) << - OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR); - regw_ip(base_addr, dpc_3_0->det_slp & - OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP); - regw_ip(base_addr, dpc_3_0->det_thr_min & - OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN); - regw_ip(base_addr, dpc_3_0->det_thr_max & - OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX); - /* Correction thresholds */ - regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) << - OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR); - regw_ip(base_addr, dpc_3_0->corr_slp & - OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP); - regw_ip(base_addr, dpc_3_0->corr_thr_min & - OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN); - regw_ip(base_addr, dpc_3_0->corr_thr_max & - OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX); -} - -/* 2D Noise filter */ -void -ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_nf *noise_filter) -{ - - u32 offset = D2F_1ST; - int count; - u32 val; - - if (id == IPIPE_D2F_2ND) - offset = D2F_2ND; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN); - if (!noise_filter->en) - return; - - /*noise filter enabled */ - /* Combine all the fields to make D2F_CFG register of IPIPE */ - val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) << - D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val & - D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) | - (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) | - ((noise_filter->apply_lsc_gain & 1) << - D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL; - regw_ip(base_addr, val, offset + D2F_TYP); - - /* edge detection minimum */ - regw_ip(base_addr, noise_filter->edge_det_min_thr & - D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN); - - /* edge detection maximum */ - regw_ip(base_addr, noise_filter->edge_det_max_thr & - D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX); - - for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++) - regw_ip(base_addr, - (noise_filter->str[count] & D2F_STR_VAL_MASK), - offset + D2F_STR + count * 4); - - for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++) - regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK, - offset + D2F_THR + count * 4); -} - -#define IPIPE_U8Q5(decimal, integer) \ - (((decimal & 0x1f) | ((integer & 0x7) << 5))) - -/* Green Imbalance Correction */ -void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic) -{ - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, gic->en & 1, GIC_EN); - - if (!gic->en) - return; - - /*gic enabled */ - val = (gic->wt_fn_type << GIC_TYP_SHIFT) | - (gic->thr_sel << GIC_THR_SEL_SHIFT) | - ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT); - regw_ip(base_addr, val, GIC_TYP); - - regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN); - - if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) { - /* Constant Gain. Set threshold to maximum */ - regw_ip(base_addr, GIC_THR_MASK, GIC_THR); - return; - } - - if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) { - regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR); - regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP); - } else { - /* Use NF thresholds */ - val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal, - gic->nf2_thr_gain.integer); - regw_ip(base_addr, val, GIC_NFGAN); - } -} - -#define IPIPE_U13Q9(decimal, integer) \ - (((decimal & 0x1ff) | ((integer & 0xf) << 9))) -/* White balance */ -void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb) -{ - u32 val; - - ipipe_clock_enable(base_addr); - /* Ofsets. S12 */ - regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R); - regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR); - regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB); - regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B); - - /* Gains. U13Q9 */ - val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer); - regw_ip(base_addr, val, WB2_WGN_R); - - val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer); - regw_ip(base_addr, val, WB2_WGN_GR); - - val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer); - regw_ip(base_addr, val, WB2_WGN_GB); - - val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer); - regw_ip(base_addr, val, WB2_WGN_B); -} - -/* CFA */ -void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa) -{ - ipipe_clock_enable(base_addr); - - regw_ip(base_addr, cfa->alg, CFA_MODE); - regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK, - CFA_2DIR_HPF_THR); - regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK, - CFA_2DIR_HPF_SLP); - regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK, - CFA_2DIR_MIX_THR); - regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK, - CFA_2DIR_MIX_SLP); - regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK, - CFA_2DIR_DIR_THR); - regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK, - CFA_2DIR_DIR_SLP); - regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK, - CFA_2DIR_NDWT); - regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK, - CFA_MONO_HUE_FRA); - regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK, - CFA_MONO_EDG_THR); - regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK, - CFA_MONO_THR_MIN); - regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK, - CFA_MONO_THR_SLP); - regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK, - CFA_MONO_SLP_MIN); - regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK, - CFA_MONO_SLP_SLP); - regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK, - CFA_MONO_LPWT); -} - -void -ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_rgb2rgb *rgb) -{ - u32 offset_mask = RGB2RGB_1_OFST_MASK; - u32 offset = RGB1_MUL_BASE; - u32 integ_mask = 0xf; - u32 val; - - ipipe_clock_enable(base_addr); - - if (id == IPIPE_RGB2RGB_2) { - /* - * For second RGB module, gain integer is 3 bits instead - * of 4, offset has 11 bits insread of 13 - */ - offset = RGB2_MUL_BASE; - integ_mask = 0x7; - offset_mask = RGB2RGB_2_OFST_MASK; - } - /* Gains */ - val = (rgb->coef_rr.decimal & 0xff) | - ((rgb->coef_rr.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RR); - val = (rgb->coef_gr.decimal & 0xff) | - ((rgb->coef_gr.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GR); - val = (rgb->coef_br.decimal & 0xff) | - ((rgb->coef_br.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BR); - val = (rgb->coef_rg.decimal & 0xff) | - ((rgb->coef_rg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RG); - val = (rgb->coef_gg.decimal & 0xff) | - ((rgb->coef_gg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GG); - val = (rgb->coef_bg.decimal & 0xff) | - ((rgb->coef_bg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BG); - val = (rgb->coef_rb.decimal & 0xff) | - ((rgb->coef_rb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RB); - val = (rgb->coef_gb.decimal & 0xff) | - ((rgb->coef_gb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GB); - val = (rgb->coef_bb.decimal & 0xff) | - ((rgb->coef_bb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BB); - - /* Offsets */ - regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR); - regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG); - regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB); -} - -static void -ipipe_update_gamma_tbl(void __iomem *isp5_base_addr, - struct vpfe_ipipe_gamma_entry *table, int size, u32 addr) -{ - int count; - u32 val; - - for (count = 0; count < size; count++) { - val = table[count].slope & GAMMA_MASK; - val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT; - w_ip_table(isp5_base_addr, val, (addr + (count * 4))); - } -} - -void -ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_gamma *gamma) -{ - int table_size; - u32 val; - - ipipe_clock_enable(base_addr); - val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) | - (gamma->bypass_b << GAMMA_BYPG_SHIFT) | - (gamma->bypass_g << GAMMA_BYPB_SHIFT) | - (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) | - (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT); - - regw_ip(base_addr, val, GMM_CFG); - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return; - - table_size = gamma->tbl_size; - - if (!gamma->bypass_r) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r, - table_size, GAMMA_R_START_ADDR); - if (!gamma->bypass_b) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b, - table_size, GAMMA_B_START_ADDR); - if (!gamma->bypass_g) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g, - table_size, GAMMA_G_START_ADDR); -} - -void -ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_3d_lut *lut_3d) -{ - struct vpfe_ipipe_3d_lut_entry *tbl; - u32 bnk_index; - u32 tbl_index; - u32 val; - u32 i; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, lut_3d->en, D3LUT_EN); - - if (!lut_3d->en) - return; - - /* valid table */ - tbl = lut_3d->table; - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { - /* - * Each entry has 0-9 (B), 10-19 (G) and - * 20-29 R values - */ - val = tbl[i].b & D3_LUT_ENTRY_MASK; - val |= (tbl[i].g & D3_LUT_ENTRY_MASK) << - D3_LUT_ENTRY_G_SHIFT; - val |= (tbl[i].r & D3_LUT_ENTRY_MASK) << - D3_LUT_ENTRY_R_SHIFT; - bnk_index = i % 4; - tbl_index = i >> 2; - tbl_index <<= 2; - if (bnk_index == 0) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB0_START_ADDR); - else if (bnk_index == 1) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB1_START_ADDR); - else if (bnk_index == 2) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB2_START_ADDR); - else - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB3_START_ADDR); - } -} - -/* Lumina adjustments */ -void -ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj) -{ - u32 val; - - ipipe_clock_enable(base_addr); - - /* combine fields of YUV_ADJ to set brightness and contrast */ - val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT | - lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT; - regw_ip(base_addr, val, YUV_ADJ); -} - -inline u32 ipipe_s12q8(unsigned short decimal, short integer) -{ - return (decimal & 0xff) | ((integer & 0xf) << 8); -} - -void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr, - struct vpfe_ipipe_rgb2yuv *yuv) -{ - u32 val; - - /* S10Q8 */ - ipipe_clock_enable(base_addr); - val = ipipe_s12q8(yuv->coef_ry.decimal, yuv->coef_ry.integer); - regw_ip(base_addr, val, YUV_MUL_RY); - val = ipipe_s12q8(yuv->coef_gy.decimal, yuv->coef_gy.integer); - regw_ip(base_addr, val, YUV_MUL_GY); - val = ipipe_s12q8(yuv->coef_by.decimal, yuv->coef_by.integer); - regw_ip(base_addr, val, YUV_MUL_BY); - val = ipipe_s12q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer); - regw_ip(base_addr, val, YUV_MUL_RCB); - val = ipipe_s12q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer); - regw_ip(base_addr, val, YUV_MUL_GCB); - val = ipipe_s12q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer); - regw_ip(base_addr, val, YUV_MUL_BCB); - val = ipipe_s12q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer); - regw_ip(base_addr, val, YUV_MUL_RCR); - val = ipipe_s12q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer); - regw_ip(base_addr, val, YUV_MUL_GCR); - val = ipipe_s12q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer); - regw_ip(base_addr, val, YUV_MUL_BCR); - regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y); - regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB); - regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR); -} - -/* YUV 422 conversion */ -void -ipipe_set_yuv422_conv_regs(void __iomem *base_addr, - struct vpfe_ipipe_yuv422_conv *conv) -{ - u32 val; - - ipipe_clock_enable(base_addr); - - /* Combine all the fields to make YUV_PHS register of IPIPE */ - val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1); - regw_ip(base_addr, val, YUV_PHS); -} - -void -ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_gbce *gbce) -{ - unsigned int count; - u32 mask = GBCE_Y_VAL_MASK; - - if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL) - mask = GBCE_GAIN_VAL_MASK; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, gbce->en & 1, GBCE_EN); - - if (!gbce->en) - return; - - regw_ip(base_addr, gbce->type, GBCE_TYP); - - for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2) - w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) << - GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask), - ((count/2) << 2) + GBCE_TB_START_ADDR); -} - -void -ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_yee *ee) -{ - unsigned int count; - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, ee->en, YEE_EN); - - if (!ee->en) - return; - - val = ee->en_halo_red & 1; - val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT; - regw_ip(base_addr, val, YEE_TYP); - - regw_ip(base_addr, ee->hpf_shft, YEE_SHF); - regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00); - regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01); - regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02); - regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10); - regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11); - regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12); - regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20); - regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21); - regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22); - regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR); - regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN); - regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1); - regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2); - regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN); - regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT); - - for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2) - w_ip_table(isp5_base_addr, ((ee->table[count + 1] & - YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) | - (ee->table[count] & YEE_ENTRY_MASK), - ((count/2) << 2) + YEE_TB_START_ADDR); -} - -/* Chromatic Artifact Correction. CAR */ -static void ipipe_set_mf(void __iomem *base_addr) -{ - /* typ to dynamic switch */ - regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); - /* Set SW0 to maximum */ - regw_ip(base_addr, CAR_MF_THR, CAR_SW); -} - -static void -ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car) -{ - regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP); - regw_ip(base_addr, car->hpf, CAR_HPF_TYP); - regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF); - regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR); - regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN); - regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF); - regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK, - CAR_GN1_MIN); - regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN); - regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF); - regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK, - CAR_GN2_MIN); -} - -void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car) -{ - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, car->en, CAR_EN); - - if (!car->en) - return; - - switch (car->meth) { - case VPFE_IPIPE_CAR_MED_FLTR: - ipipe_set_mf(base_addr); - break; - - case VPFE_IPIPE_CAR_CHR_GAIN_CTRL: - ipipe_set_gain_ctrl(base_addr, car); - break; - - default: - /* Dynamic switch between MF and Gain Ctrl. */ - ipipe_set_mf(base_addr); - ipipe_set_gain_ctrl(base_addr, car); - /* Set the threshold for switching between - * the two Here we overwrite the MF SW0 value - */ - regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); - val = car->sw1; - val <<= CAR_SW1_SHIFT; - val |= car->sw0; - regw_ip(base_addr, val, CAR_SW); - } -} - -/* Chromatic Gain Suppression */ -void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs) -{ - ipipe_clock_enable(base_addr); - regw_ip(base_addr, cgs->en, CGS_EN); - - if (!cgs->en) - return; - - /* Set the bright side parameters */ - regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR); - regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN); - regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF); - regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN); -} - -void rsz_src_enable(void __iomem *rsz_base, int enable) -{ - regw_rsz(rsz_base, enable, RSZ_SRC_EN); -} - -int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable) -{ - if (rsz_id == RSZ_A) { - regw_rsz(rsz_base, enable, RSZ_EN_A); - /* We always enable RSZ_A. RSZ_B is enable upon request from - * application. So enable RSZ_SRC_EN along with RSZ_A - */ - regw_rsz(rsz_base, enable, RSZ_SRC_EN); - } else if (rsz_id == RSZ_B) { - regw_rsz(rsz_base, enable, RSZ_EN_B); - } else { - BUG(); - } - - return 0; -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h deleted file mode 100644 index 16b6a14b7058..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h +++ /dev/null @@ -1,556 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPE_HW_H -#define _DAVINCI_VPFE_DM365_IPIPE_HW_H - -#include "vpfe_mc_capture.h" - -#define SET_LOW_ADDR 0x0000ffff -#define SET_HIGH_ADDR 0xffff0000 - -/* Below are the internal tables */ -#define DPC_TB0_START_ADDR 0x8000 -#define DPC_TB1_START_ADDR 0x8400 - -#define GAMMA_R_START_ADDR 0xa800 -#define GAMMA_G_START_ADDR 0xb000 -#define GAMMA_B_START_ADDR 0xb800 - -/* RAM table addresses for edge enhancement correction*/ -#define YEE_TB_START_ADDR 0x8800 - -/* RAM table address for GBC LUT */ -#define GBCE_TB_START_ADDR 0x9000 - -/* RAM table for 3D NF LUT */ -#define D3L_TB0_START_ADDR 0x9800 -#define D3L_TB1_START_ADDR 0x9c00 -#define D3L_TB2_START_ADDR 0xa000 -#define D3L_TB3_START_ADDR 0xa400 - -/* IPIPE Register Offsets from the base address */ -#define IPIPE_SRC_EN 0x0000 -#define IPIPE_SRC_MODE 0x0004 -#define IPIPE_SRC_FMT 0x0008 -#define IPIPE_SRC_COL 0x000c -#define IPIPE_SRC_VPS 0x0010 -#define IPIPE_SRC_VSZ 0x0014 -#define IPIPE_SRC_HPS 0x0018 -#define IPIPE_SRC_HSZ 0x001c - -#define IPIPE_SEL_SBU 0x0020 - -#define IPIPE_DMA_STA 0x0024 -#define IPIPE_GCK_MMR 0x0028 -#define IPIPE_GCK_PIX 0x002c -#define IPIPE_RESERVED0 0x0030 - -/* Defect Correction */ -#define DPC_LUT_EN 0x0034 -#define DPC_LUT_SEL 0x0038 -#define DPC_LUT_ADR 0x003c -#define DPC_LUT_SIZ 0x0040 -#define DPC_OTF_EN 0x0044 -#define DPC_OTF_TYP 0x0048 -#define DPC_OTF_2D_THR_R 0x004c -#define DPC_OTF_2D_THR_GR 0x0050 -#define DPC_OTF_2D_THR_GB 0x0054 -#define DPC_OTF_2D_THR_B 0x0058 -#define DPC_OTF_2C_THR_R 0x005c -#define DPC_OTF_2C_THR_GR 0x0060 -#define DPC_OTF_2C_THR_GB 0x0064 -#define DPC_OTF_2C_THR_B 0x0068 -#define DPC_OTF_3_SHF 0x006c -#define DPC_OTF_3D_THR 0x0070 -#define DPC_OTF_3D_SLP 0x0074 -#define DPC_OTF_3D_MIN 0x0078 -#define DPC_OTF_3D_MAX 0x007c -#define DPC_OTF_3C_THR 0x0080 -#define DPC_OTF_3C_SLP 0x0084 -#define DPC_OTF_3C_MIN 0x0088 -#define DPC_OTF_3C_MAX 0x008c - -/* Lense Shading Correction */ -#define LSC_VOFT 0x90 -#define LSC_VA2 0x94 -#define LSC_VA1 0x98 -#define LSC_VS 0x9c -#define LSC_HOFT 0xa0 -#define LSC_HA2 0xa4 -#define LSC_HA1 0xa8 -#define LSC_HS 0xac -#define LSC_GAIN_R 0xb0 -#define LSC_GAIN_GR 0xb4 -#define LSC_GAIN_GB 0xb8 -#define LSC_GAIN_B 0xbc -#define LSC_OFT_R 0xc0 -#define LSC_OFT_GR 0xc4 -#define LSC_OFT_GB 0xc8 -#define LSC_OFT_B 0xcc -#define LSC_SHF 0xd0 -#define LSC_MAX 0xd4 - -/* Noise Filter 1. Ofsets from start address given */ -#define D2F_1ST 0xd8 -#define D2F_EN 0x0 -#define D2F_TYP 0x4 -#define D2F_THR 0x8 -#define D2F_STR 0x28 -#define D2F_SPR 0x48 -#define D2F_EDG_MIN 0x68 -#define D2F_EDG_MAX 0x6c - -/* Noise Filter 2 */ -#define D2F_2ND 0x148 - -/* GIC */ -#define GIC_EN 0x1b8 -#define GIC_TYP 0x1bc -#define GIC_GAN 0x1c0 -#define GIC_NFGAN 0x1c4 -#define GIC_THR 0x1c8 -#define GIC_SLP 0x1cc - -/* White Balance */ -#define WB2_OFT_R 0x1d0 -#define WB2_OFT_GR 0x1d4 -#define WB2_OFT_GB 0x1d8 -#define WB2_OFT_B 0x1dc -#define WB2_WGN_R 0x1e0 -#define WB2_WGN_GR 0x1e4 -#define WB2_WGN_GB 0x1e8 -#define WB2_WGN_B 0x1ec - -/* CFA interpolation */ -#define CFA_MODE 0x1f0 -#define CFA_2DIR_HPF_THR 0x1f4 -#define CFA_2DIR_HPF_SLP 0x1f8 -#define CFA_2DIR_MIX_THR 0x1fc -#define CFA_2DIR_MIX_SLP 0x200 -#define CFA_2DIR_DIR_THR 0x204 -#define CFA_2DIR_DIR_SLP 0x208 -#define CFA_2DIR_NDWT 0x20c -#define CFA_MONO_HUE_FRA 0x210 -#define CFA_MONO_EDG_THR 0x214 -#define CFA_MONO_THR_MIN 0x218 -#define CFA_MONO_THR_SLP 0x21c -#define CFA_MONO_SLP_MIN 0x220 -#define CFA_MONO_SLP_SLP 0x224 -#define CFA_MONO_LPWT 0x228 - -/* RGB to RGB conversiona - 1st */ -#define RGB1_MUL_BASE 0x22c -/* Offsets from base */ -#define RGB_MUL_RR 0x0 -#define RGB_MUL_GR 0x4 -#define RGB_MUL_BR 0x8 -#define RGB_MUL_RG 0xc -#define RGB_MUL_GG 0x10 -#define RGB_MUL_BG 0x14 -#define RGB_MUL_RB 0x18 -#define RGB_MUL_GB 0x1c -#define RGB_MUL_BB 0x20 -#define RGB_OFT_OR 0x24 -#define RGB_OFT_OG 0x28 -#define RGB_OFT_OB 0x2c - -/* Gamma */ -#define GMM_CFG 0x25c - -/* RGB to RGB conversiona - 2nd */ -#define RGB2_MUL_BASE 0x260 - -/* 3D LUT */ -#define D3LUT_EN 0x290 - -/* RGB to YUV(YCbCr) conversion */ -#define YUV_ADJ 0x294 -#define YUV_MUL_RY 0x298 -#define YUV_MUL_GY 0x29c -#define YUV_MUL_BY 0x2a0 -#define YUV_MUL_RCB 0x2a4 -#define YUV_MUL_GCB 0x2a8 -#define YUV_MUL_BCB 0x2ac -#define YUV_MUL_RCR 0x2b0 -#define YUV_MUL_GCR 0x2b4 -#define YUV_MUL_BCR 0x2b8 -#define YUV_OFT_Y 0x2bc -#define YUV_OFT_CB 0x2c0 -#define YUV_OFT_CR 0x2c4 -#define YUV_PHS 0x2c8 - -/* Global Brightness and Contrast */ -#define GBCE_EN 0x2cc -#define GBCE_TYP 0x2d0 - -/* Edge Enhancer */ -#define YEE_EN 0x2d4 -#define YEE_TYP 0x2d8 -#define YEE_SHF 0x2dc -#define YEE_MUL_00 0x2e0 -#define YEE_MUL_01 0x2e4 -#define YEE_MUL_02 0x2e8 -#define YEE_MUL_10 0x2ec -#define YEE_MUL_11 0x2f0 -#define YEE_MUL_12 0x2f4 -#define YEE_MUL_20 0x2f8 -#define YEE_MUL_21 0x2fc -#define YEE_MUL_22 0x300 -#define YEE_THR 0x304 -#define YEE_E_GAN 0x308 -#define YEE_E_THR1 0x30c -#define YEE_E_THR2 0x310 -#define YEE_G_GAN 0x314 -#define YEE_G_OFT 0x318 - -/* Chroma Artifact Reduction */ -#define CAR_EN 0x31c -#define CAR_TYP 0x320 -#define CAR_SW 0x324 -#define CAR_HPF_TYP 0x328 -#define CAR_HPF_SHF 0x32c -#define CAR_HPF_THR 0x330 -#define CAR_GN1_GAN 0x334 -#define CAR_GN1_SHF 0x338 -#define CAR_GN1_MIN 0x33c -#define CAR_GN2_GAN 0x340 -#define CAR_GN2_SHF 0x344 -#define CAR_GN2_MIN 0x348 - -/* Chroma Gain Suppression */ -#define CGS_EN 0x34c -#define CGS_GN1_L_THR 0x350 -#define CGS_GN1_L_GAN 0x354 -#define CGS_GN1_L_SHF 0x358 -#define CGS_GN1_L_MIN 0x35c -#define CGS_GN1_H_THR 0x360 -#define CGS_GN1_H_GAN 0x364 -#define CGS_GN1_H_SHF 0x368 -#define CGS_GN1_H_MIN 0x36c -#define CGS_GN2_L_THR 0x370 -#define CGS_GN2_L_GAN 0x374 -#define CGS_GN2_L_SHF 0x378 -#define CGS_GN2_L_MIN 0x37c - -/* Resizer */ -#define RSZ_SRC_EN 0x0 -#define RSZ_SRC_MODE 0x4 -#define RSZ_SRC_FMT0 0x8 -#define RSZ_SRC_FMT1 0xc -#define RSZ_SRC_VPS 0x10 -#define RSZ_SRC_VSZ 0x14 -#define RSZ_SRC_HPS 0x18 -#define RSZ_SRC_HSZ 0x1c -#define RSZ_DMA_RZA 0x20 -#define RSZ_DMA_RZB 0x24 -#define RSZ_DMA_STA 0x28 -#define RSZ_GCK_MMR 0x2c -#define RSZ_RESERVED0 0x30 -#define RSZ_GCK_SDR 0x34 -#define RSZ_IRQ_RZA 0x38 -#define RSZ_IRQ_RZB 0x3c -#define RSZ_YUV_Y_MIN 0x40 -#define RSZ_YUV_Y_MAX 0x44 -#define RSZ_YUV_C_MIN 0x48 -#define RSZ_YUV_C_MAX 0x4c -#define RSZ_YUV_PHS 0x50 -#define RSZ_SEQ 0x54 - -/* Resizer Rescale Parameters */ -#define RSZ_EN_A 0x58 -#define RSZ_EN_B 0xe8 -/* - * offset of the registers to be added with base register of - * either RSZ0 or RSZ1 - */ -#define RSZ_MODE 0x4 -#define RSZ_420 0x8 -#define RSZ_I_VPS 0xc -#define RSZ_I_HPS 0x10 -#define RSZ_O_VSZ 0x14 -#define RSZ_O_HSZ 0x18 -#define RSZ_V_PHS_Y 0x1c -#define RSZ_V_PHS_C 0x20 -#define RSZ_V_DIF 0x24 -#define RSZ_V_TYP 0x28 -#define RSZ_V_LPF 0x2c -#define RSZ_H_PHS 0x30 -#define RSZ_H_PHS_ADJ 0x34 -#define RSZ_H_DIF 0x38 -#define RSZ_H_TYP 0x3c -#define RSZ_H_LPF 0x40 -#define RSZ_DWN_EN 0x44 -#define RSZ_DWN_AV 0x48 - -/* Resizer RGB Conversion Parameters */ -#define RSZ_RGB_EN 0x4c -#define RSZ_RGB_TYP 0x50 -#define RSZ_RGB_BLD 0x54 - -/* Resizer External Memory Parameters */ -#define RSZ_SDR_Y_BAD_H 0x58 -#define RSZ_SDR_Y_BAD_L 0x5c -#define RSZ_SDR_Y_SAD_H 0x60 -#define RSZ_SDR_Y_SAD_L 0x64 -#define RSZ_SDR_Y_OFT 0x68 -#define RSZ_SDR_Y_PTR_S 0x6c -#define RSZ_SDR_Y_PTR_E 0x70 -#define RSZ_SDR_C_BAD_H 0x74 -#define RSZ_SDR_C_BAD_L 0x78 -#define RSZ_SDR_C_SAD_H 0x7c -#define RSZ_SDR_C_SAD_L 0x80 -#define RSZ_SDR_C_OFT 0x84 -#define RSZ_SDR_C_PTR_S 0x88 -#define RSZ_SDR_C_PTR_E 0x8c - -/* Macro for resizer */ -#define RSZ_YUV_Y_MIN 0x40 -#define RSZ_YUV_Y_MAX 0x44 -#define RSZ_YUV_C_MIN 0x48 -#define RSZ_YUV_C_MAX 0x4c - -#define IPIPE_GCK_MMR_DEFAULT 1 -#define IPIPE_GCK_PIX_DEFAULT 0xe -#define RSZ_GCK_MMR_DEFAULT 1 -#define RSZ_GCK_SDR_DEFAULT 1 - -/* LUTDPC */ -#define LUTDPC_TBL_256_EN 0 -#define LUTDPC_INF_TBL_EN 1 -#define LUT_DPC_START_ADDR 0 -#define LUT_DPC_H_POS_MASK 0x1fff -#define LUT_DPC_V_POS_MASK 0x1fff -#define LUT_DPC_V_POS_SHIFT 13 -#define LUT_DPC_CORR_METH_SHIFT 26 -#define LUT_DPC_MAX_SIZE 256 -#define LUT_DPC_SIZE_MASK 0x3ff - -/* OTFDPC */ -#define OTFDPC_DPC2_THR_MASK 0xfff -#define OTF_DET_METHOD_SHIFT 1 -#define OTF_DPC3_0_SHF_MASK 3 -#define OTF_DPC3_0_THR_SHIFT 6 -#define OTF_DPC3_0_THR_MASK 0x3f -#define OTF_DPC3_0_SLP_MASK 0x3f -#define OTF_DPC3_0_DET_MASK 0xfff -#define OTF_DPC3_0_CORR_MASK 0xfff - -/* NF (D2F) */ -#define D2F_SPR_VAL_MASK 0x1f -#define D2F_SPR_VAL_SHIFT 0 -#define D2F_SHFT_VAL_MASK 3 -#define D2F_SHFT_VAL_SHIFT 5 -#define D2F_SAMPLE_METH_SHIFT 7 -#define D2F_APPLY_LSC_GAIN_SHIFT 8 -#define D2F_USE_SPR_REG_VAL 0 -#define D2F_STR_VAL_MASK 0x1f -#define D2F_THR_VAL_MASK 0x3ff -#define D2F_EDGE_DET_THR_MASK 0x7ff - -/* Green Imbalance Correction */ -#define GIC_TYP_SHIFT 0 -#define GIC_THR_SEL_SHIFT 1 -#define GIC_APPLY_LSC_GAIN_SHIFT 2 -#define GIC_GAIN_MASK 0xff -#define GIC_THR_MASK 0xfff -#define GIC_SLOPE_MASK 0xfff -#define GIC_NFGAN_INT_MASK 7 -#define GIC_NFGAN_DECI_MASK 0x1f - -/* WB */ -#define WB_OFFSET_MASK 0xfff -#define WB_GAIN_INT_MASK 0xf -#define WB_GAIN_DECI_MASK 0x1ff - -/* CFA */ -#define CFA_HPF_THR_2DIR_MASK 0x1fff -#define CFA_HPF_SLOPE_2DIR_MASK 0x3ff -#define CFA_HPF_MIX_THR_2DIR_MASK 0x1fff -#define CFA_HPF_MIX_SLP_2DIR_MASK 0x3ff -#define CFA_DIR_THR_2DIR_MASK 0x3ff -#define CFA_DIR_SLP_2DIR_MASK 0x7f -#define CFA_ND_WT_2DIR_MASK 0x3f -#define CFA_DAA_HUE_FRA_MASK 0x3f -#define CFA_DAA_EDG_THR_MASK 0xff -#define CFA_DAA_THR_MIN_MASK 0x3ff -#define CFA_DAA_THR_SLP_MASK 0x3ff -#define CFA_DAA_SLP_MIN_MASK 0x3ff -#define CFA_DAA_SLP_SLP_MASK 0x3ff -#define CFA_DAA_LP_WT_MASK 0x3f - -/* RGB2RGB */ -#define RGB2RGB_1_OFST_MASK 0x1fff -#define RGB2RGB_1_GAIN_INT_MASK 0xf -#define RGB2RGB_GAIN_DECI_MASK 0xff -#define RGB2RGB_2_OFST_MASK 0x7ff -#define RGB2RGB_2_GAIN_INT_MASK 0x7 - -/* Gamma */ -#define GAMMA_BYPR_SHIFT 0 -#define GAMMA_BYPG_SHIFT 1 -#define GAMMA_BYPB_SHIFT 2 -#define GAMMA_TBL_SEL_SHIFT 4 -#define GAMMA_TBL_SIZE_SHIFT 5 -#define GAMMA_MASK 0x3ff -#define GAMMA_SHIFT 10 - -/* 3D LUT */ -#define D3_LUT_ENTRY_MASK 0x3ff -#define D3_LUT_ENTRY_R_SHIFT 20 -#define D3_LUT_ENTRY_G_SHIFT 10 -#define D3_LUT_ENTRY_B_SHIFT 0 - -/* Lumina adj */ -#define LUM_ADJ_CONTR_SHIFT 0 -#define LUM_ADJ_BRIGHT_SHIFT 8 - -/* RGB2YCbCr */ -#define RGB2YCBCR_OFST_MASK 0x7ff -#define RGB2YCBCR_COEF_INT_MASK 0xf -#define RGB2YCBCR_COEF_DECI_MASK 0xff - -/* GBCE */ -#define GBCE_Y_VAL_MASK 0xff -#define GBCE_GAIN_VAL_MASK 0x3ff -#define GBCE_ENTRY_SHIFT 10 - -/* Edge Enhancements */ -#define YEE_HALO_RED_EN_SHIFT 1 -#define YEE_HPF_SHIFT_MASK 0xf -#define YEE_COEF_MASK 0x3ff -#define YEE_THR_MASK 0x3f -#define YEE_ES_GAIN_MASK 0xfff -#define YEE_ES_THR1_MASK 0xfff -#define YEE_ENTRY_SHIFT 9 -#define YEE_ENTRY_MASK 0x1ff - -/* CAR */ -#define CAR_MF_THR 0xff -#define CAR_SW1_SHIFT 8 -#define CAR_GAIN1_SHFT_MASK 7 -#define CAR_GAIN_MIN_MASK 0x1ff -#define CAR_GAIN2_SHFT_MASK 0xf -#define CAR_HPF_SHIFT_MASK 3 - -/* CGS */ -#define CAR_SHIFT_MASK 3 - -/* Resizer */ -#define RSZ_BYPASS_SHIFT 1 -#define RSZ_SRC_IMG_FMT_SHIFT 1 -#define RSZ_SRC_Y_C_SEL_SHIFT 2 -#define IPIPE_RSZ_VPS_MASK 0xffff -#define IPIPE_RSZ_HPS_MASK 0xffff -#define IPIPE_RSZ_VSZ_MASK 0x1fff -#define IPIPE_RSZ_HSZ_MASK 0x1fff -#define RSZ_HPS_MASK 0x1fff -#define RSZ_VPS_MASK 0x1fff -#define RSZ_O_HSZ_MASK 0x1fff -#define RSZ_O_VSZ_MASK 0x1fff -#define RSZ_V_PHS_MASK 0x3fff -#define RSZ_V_DIF_MASK 0x3fff - -#define RSZA_H_FLIP_SHIFT 0 -#define RSZA_V_FLIP_SHIFT 1 -#define RSZB_H_FLIP_SHIFT 2 -#define RSZB_V_FLIP_SHIFT 3 -#define RSZ_A 0 -#define RSZ_B 1 -#define RSZ_CEN_SHIFT 1 -#define RSZ_YEN_SHIFT 0 -#define RSZ_TYP_Y_SHIFT 0 -#define RSZ_TYP_C_SHIFT 1 -#define RSZ_LPF_INT_MASK 0x3f -#define RSZ_LPF_INT_C_SHIFT 6 -#define RSZ_H_PHS_MASK 0x3fff -#define RSZ_H_DIF_MASK 0x3fff -#define RSZ_DIFF_DOWN_THR 256 -#define RSZ_DWN_SCALE_AV_SZ_V_SHIFT 3 -#define RSZ_DWN_SCALE_AV_SZ_MASK 7 -#define RSZ_RGB_MSK1_SHIFT 2 -#define RSZ_RGB_MSK0_SHIFT 1 -#define RSZ_RGB_TYP_SHIFT 0 -#define RSZ_RGB_ALPHA_MASK 0xff - -static inline u32 regr_ip(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline void regw_ip(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); -} - -static inline u32 w_ip_table(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); - - return val; -} - -static inline u32 regr_rsz(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline u32 regw_rsz(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); - - return val; -} - -int config_ipipe_hw(struct vpfe_ipipe_device *ipipe); -int resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params, - int resize_no, unsigned int address); -int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable); -void rsz_src_enable(void __iomem *rsz_base, int enable); -void rsz_set_in_pix_format(unsigned char y_c); -int config_rsz_hw(struct vpfe_resizer_device *resizer, - struct resizer_params *config); -void ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_nf *noise_filter); -void ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_rgb2rgb *rgb); -void ipipe_set_yuv422_conv_regs(void __iomem *base_addr, - struct vpfe_ipipe_yuv422_conv *conv); -void ipipe_set_lum_adj_regs(void __iomem *base_addr, - struct ipipe_lum_adj *lum_adj); -void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr, - struct vpfe_ipipe_rgb2yuv *yuv); -void ipipe_set_lutdpc_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_lutdpc *lutdpc); -void ipipe_set_otfdpc_regs(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc *otfdpc); -void ipipe_set_3d_lut_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_3d_lut *lut_3d); -void ipipe_set_gamma_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_gamma *gamma); -void ipipe_set_ee_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_yee *ee); -void ipipe_set_gbce_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_gbce *gbce); -void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic); -void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa); -void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car); -void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs); -void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb); - -#endif /* _DAVINCI_VPFE_DM365_IPIPE_HW_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c deleted file mode 100644 index 51d4cd1bdb97..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ /dev/null @@ -1,1070 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#include "dm365_ipipeif.h" -#include "vpfe_mc_capture.h" - -static const unsigned int ipipeif_input_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SBGGR8_1X8, -}; - -static const unsigned int ipipeif_output_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, -}; - -static int -ipipeif_get_pack_mode(u32 in_pix_fmt) -{ - switch (in_pix_fmt) { - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - return IPIPEIF_5_1_PACK_8_BIT; - - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - return IPIPEIF_5_1_PACK_8_BIT_A_LAW; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - return IPIPEIF_5_1_PACK_16_BIT; - - case MEDIA_BUS_FMT_SBGGR12_1X12: - return IPIPEIF_5_1_PACK_12_BIT; - - default: - return IPIPEIF_5_1_PACK_16_BIT; - } -} - -static inline u32 ipipeif_read(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline void ipipeif_write(u32 val, void __iomem *addr, u32 offset) -{ - writel(val, addr + offset); -} - -static void ipipeif_config_dpc(void __iomem *addr, struct ipipeif_dpc *dpc) -{ - u32 val = 0; - - if (dpc->en) { - val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT; - val |= dpc->thr & IPIPEIF_DPC2_THR_MASK; - } - ipipeif_write(val, addr, IPIPEIF_DPC2); -} - -#define IPIPEIF_MODE_CONTINUOUS 0 -#define IPIPEIF_MODE_ONE_SHOT 1 - -static int get_oneshot_mode(enum ipipeif_input_entity input) -{ - if (input == IPIPEIF_INPUT_MEMORY) - return IPIPEIF_MODE_ONE_SHOT; - if (input == IPIPEIF_INPUT_ISIF) - return IPIPEIF_MODE_CONTINUOUS; - - return -EINVAL; -} - -static int -ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - if (ipipeif->input == IPIPEIF_INPUT_MEMORY && - (informat->code == MEDIA_BUS_FMT_Y8_1X8 || - informat->code == MEDIA_BUS_FMT_UV8_1X8)) - return IPIPEIF_CCDC; - - return IPIPEIF_SRC1_PARALLEL_PORT; -} - -static int -ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - - switch (informat->code) { - case MEDIA_BUS_FMT_SGRBG12_1X12: - return IPIPEIF_5_1_BITS11_0; - - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - return IPIPEIF_5_1_BITS11_0; - - default: - return IPIPEIF_5_1_BITS7_0; - } -} - -static enum ipipeif_input_source -ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - if (ipipeif->input == IPIPEIF_INPUT_ISIF) - return IPIPEIF_CCDC; - - if (informat->code == MEDIA_BUS_FMT_UYVY8_2X8) - return IPIPEIF_SDRAM_YUV; - - return IPIPEIF_SDRAM_RAW; -} - -void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif) -{ - struct vpfe_video_device *video_in = &ipipeif->video_in; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return; - - spin_lock(&video_in->dma_queue_lock); - vpfe_video_process_buffer_complete(video_in); - video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_in); - spin_unlock(&video_in->dma_queue_lock); -} - -int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - - return ipipeif->config.decimation; -} - -int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - - return ipipeif->config.rsz; -} - -#define RD_DATA_15_2 0x7 - -/* - * ipipeif_hw_setup() - This function sets up IPIPEIF - * @sd: pointer to v4l2 subdev structure - * return -EINVAL or zero on success - */ -static int ipipeif_hw_setup(struct v4l2_subdev *sd) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *informat, *outformat; - struct ipipeif_params params = ipipeif->config; - enum ipipeif_input_source ipipeif_source; - u32 isif_port_if; - void __iomem *ipipeif_base_addr; - unsigned long val; - int data_shift; - int pack_mode; - int source1; - int tmp; - - ipipeif_base_addr = ipipeif->ipipeif_base_addr; - - /* Enable clock to IPIPEIF and IPIPE */ - vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE]; - - /* Combine all the fields to make CFG1 register of IPIPEIF */ - tmp = val = get_oneshot_mode(ipipeif->input); - if (tmp < 0) { - dev_err(&sd->devnode->dev, "ipipeif: links setup required"); - return -EINVAL; - } - val <<= ONESHOT_SHIFT; - - ipipeif_source = ipipeif_get_source(ipipeif); - val |= ipipeif_source << INPSRC_SHIFT; - - val |= params.clock_select << CLKSEL_SHIFT; - val |= params.avg_filter << AVGFILT_SHIFT; - val |= params.decimation << DECIM_SHIFT; - - pack_mode = ipipeif_get_pack_mode(informat->code); - val |= pack_mode << PACK8IN_SHIFT; - - source1 = ipipeif_get_cfg_src1(ipipeif); - val |= source1 << INPSRC1_SHIFT; - - data_shift = ipipeif_get_data_shift(ipipeif); - if (ipipeif_source != IPIPEIF_SDRAM_YUV) - val |= data_shift << DATASFT_SHIFT; - else - val &= ~(RD_DATA_15_2 << DATASFT_SHIFT); - - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG1); - - switch (ipipeif_source) { - case IPIPEIF_CCDC: - ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN); - break; - - case IPIPEIF_SDRAM_RAW: - case IPIPEIF_CCDC_DARKFM: - ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN); - /* fall through */ - case IPIPEIF_SDRAM_YUV: - val |= data_shift << DATASFT_SHIFT; - ipipeif_write(params.ppln, ipipeif_base_addr, IPIPEIF_PPLN); - ipipeif_write(params.lpfr, ipipeif_base_addr, IPIPEIF_LPFR); - ipipeif_write(informat->width, ipipeif_base_addr, IPIPEIF_HNUM); - ipipeif_write(informat->height, - ipipeif_base_addr, IPIPEIF_VNUM); - break; - - default: - return -EINVAL; - } - - /*check if decimation is enable or not */ - if (params.decimation) - ipipeif_write(params.rsz, ipipeif_base_addr, IPIPEIF_RSZ); - - /* Setup sync alignment and initial rsz position */ - val = params.if_5_1.align_sync & 1; - val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT; - val |= params.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_INIRSZ); - isif_port_if = informat->code; - - if (isif_port_if == MEDIA_BUS_FMT_Y8_1X8) - isif_port_if = MEDIA_BUS_FMT_YUYV8_1X16; - else if (isif_port_if == MEDIA_BUS_FMT_UV8_1X8) - isif_port_if = MEDIA_BUS_FMT_SGRBG12_1X12; - - /* Enable DPCM decompression */ - switch (ipipeif_source) { - case IPIPEIF_SDRAM_RAW: - val = 0; - if (outformat->code == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8) { - val = 1; - val |= (IPIPEIF_DPCM_8BIT_10BIT & 1) << - IPIPEIF_DPCM_BITS_SHIFT; - val |= (ipipeif->dpcm_predictor & 1) << - IPIPEIF_DPCM_PRED_SHIFT; - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DPCM); - - /* set DPC */ - ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc); - - ipipeif_write(params.if_5_1.clip, - ipipeif_base_addr, IPIPEIF_OCLIP); - - /* fall through for SDRAM YUV mode */ - /* configure CFG2 */ - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CFG2); - switch (isif_port_if) { - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_Y8_1X8: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - - default: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - clear_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - } - /* fall through */ - - case IPIPEIF_SDRAM_YUV: - /* Set clock divider */ - if (params.clock_select == IPIPEIF_SDRAM_CLK) { - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV); - val |= (params.if_5_1.clk_div.m - 1) << - IPIPEIF_CLKDIV_M_SHIFT; - val |= (params.if_5_1.clk_div.n - 1); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV); - } - break; - - case IPIPEIF_CCDC: - case IPIPEIF_CCDC_DARKFM: - /* set DPC */ - ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc); - - /* Set DF gain & threshold control */ - val = 0; - if (params.if_5_1.df_gain_en) { - val = params.if_5_1.df_gain_thr & - IPIPEIF_DF_GAIN_THR_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH); - val = (params.if_5_1.df_gain_en & 1) << - IPIPEIF_DF_GAIN_EN_SHIFT; - val |= params.if_5_1.df_gain & - IPIPEIF_DF_GAIN_MASK; - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL); - /* configure CFG2 */ - val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT; - val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT; - - switch (isif_port_if) { - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - break; - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - set_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT; - break; - - default: - /* Bayer */ - ipipeif_write(params.if_5_1.clip, ipipeif_base_addr, - IPIPEIF_OCLIP); - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int -ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct device *dev = ipipeif->subdev.v4l2_dev->dev; - - if (!config) { - dev_err(dev, "Invalid configuration pointer\n"); - return -EINVAL; - } - - ipipeif->config.clock_select = config->clock_select; - ipipeif->config.ppln = config->ppln; - ipipeif->config.lpfr = config->lpfr; - ipipeif->config.rsz = config->rsz; - ipipeif->config.decimation = config->decimation; - if (ipipeif->config.decimation && - (ipipeif->config.rsz < IPIPEIF_RSZ_MIN || - ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) { - dev_err(dev, "rsz range is %d to %d\n", - IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX); - return -EINVAL; - } - - ipipeif->config.avg_filter = config->avg_filter; - - ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr; - ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain; - ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en; - - ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start; - ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync; - ipipeif->config.if_5_1.clip = config->if_5_1.clip; - - ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en; - ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr; - - ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m; - ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n; - - return 0; -} - -static int -ipipeif_get_config(struct v4l2_subdev *sd, void *arg) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct ipipeif_params *config = arg; - struct device *dev = ipipeif->subdev.v4l2_dev->dev; - - if (!arg) { - dev_err(dev, "Invalid configuration pointer\n"); - return -EINVAL; - } - - config->clock_select = ipipeif->config.clock_select; - config->ppln = ipipeif->config.ppln; - config->lpfr = ipipeif->config.lpfr; - config->rsz = ipipeif->config.rsz; - config->decimation = ipipeif->config.decimation; - config->avg_filter = ipipeif->config.avg_filter; - - config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr; - config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain; - config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en; - - config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start; - config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync; - config->if_5_1.clip = ipipeif->config.if_5_1.clip; - - config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en; - config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr; - - config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m; - config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n; - - return 0; -} - -/* - * ipipeif_ioctl() - Handle ipipeif module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long ipipeif_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct ipipeif_params *config = arg; - int ret = -ENOIOCTLCMD; - - switch (cmd) { - case VIDIOC_VPFE_IPIPEIF_S_CONFIG: - ret = ipipeif_set_config(sd, config); - break; - - case VIDIOC_VPFE_IPIPEIF_G_CONFIG: - ret = ipipeif_get_config(sd, arg); - break; - } - return ret; -} - -/* - * ipipeif_s_ctrl() - Handle set control subdev method - * @ctrl: pointer to v4l2 control structure - */ -static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_ipipeif_device *ipipeif = - container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls); - - switch (ctrl->id) { - case VPFE_CID_DPCM_PREDICTOR: - ipipeif->dpcm_predictor = ctrl->val; - break; - - case V4L2_CID_GAIN: - ipipeif->gain = ctrl->val; - break; - - default: - return -EINVAL; - } - - return 0; -} - -#define ENABLE_IPIPEIF 0x1 - -void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - void __iomem *ipipeif_base_addr = ipipeif->ipipeif_base_addr; - unsigned char val; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return; - - do { - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE); - } while (val & 0x1); - - ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE); -} - -/* - * ipipeif_set_stream() - Enable/Disable streaming on ipipeif subdev - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif); - int ret = 0; - - if (!enable) - return ret; - - ret = ipipeif_hw_setup(sd); - if (!ret) - vpfe_ipipeif_enable(vpfe_dev); - - return ret; -} - -/* - * ipipeif_enum_mbus_code() - Handle pixel format enumeration - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case IPIPEIF_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipeif_input_fmts)) - return -EINVAL; - - code->code = ipipeif_input_fmts[code->index]; - break; - - case IPIPEIF_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(ipipeif_output_fmts)) - return -EINVAL; - - code->code = ipipeif_output_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipeif_get_format() - Handle get format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - */ -static int -ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - fmt->format = ipipeif->formats[fmt->pad]; - else - fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad)); - - return 0; -} - -#define MIN_OUT_WIDTH 32 -#define MIN_OUT_HEIGHT 32 - -/* - * ipipeif_try_format() - Handle try format by pad subdev method - * @ipipeif: VPFE ipipeif device. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which : wanted subdev format - */ -static void -ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - if (pad == IPIPEIF_PAD_SINK) { - for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++) - if (fmt->code == ipipeif_input_fmts[i]) - break; - - /* If not found, use SBGGR10 as default */ - if (i >= ARRAY_SIZE(ipipeif_input_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG12_1X12; - } else if (pad == IPIPEIF_PAD_SOURCE) { - for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++) - if (fmt->code == ipipeif_output_fmts[i]) - break; - - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(ipipeif_output_fmts)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - } - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width); - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height); -} - -static int -ipipeif_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * __ipipeif_get_format() - helper function for getting ipipeif format - * @ipipeif: pointer to ipipeif private structure. - * @cfg: V4L2 subdev pad config - * @pad: pad number. - * @which: wanted subdev format. - * - */ -static struct v4l2_mbus_framefmt * -__ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad); - - return &ipipeif->formats[pad]; -} - -/* - * ipipeif_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int -ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == IPIPEIF_PAD_SINK && - ipipeif->input != IPIPEIF_INPUT_NONE) - ipipeif->formats[fmt->pad] = fmt->format; - else if (fmt->pad == IPIPEIF_PAD_SOURCE && - ipipeif->output != IPIPEIF_OUTPUT_NONE) - ipipeif->formats[fmt->pad] = fmt->format; - else - return -EINVAL; - - return 0; -} - -static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif) -{ -#define WIDTH_I 640 -#define HEIGHT_I 480 - - const struct ipipeif_params ipipeif_defaults = { - .clock_select = IPIPEIF_SDRAM_CLK, - .ppln = WIDTH_I + 8, - .lpfr = HEIGHT_I + 10, - .rsz = 16, /* resize ratio 16/rsz */ - .decimation = IPIPEIF_DECIMATION_OFF, - .avg_filter = IPIPEIF_AVG_OFF, - .if_5_1 = { - .clk_div = { - .m = 1, /* clock = sdram clock * (m/n) */ - .n = 6 - }, - .clip = 4095, - }, - }; - memcpy(&ipipeif->config, &ipipeif_defaults, - sizeof(struct ipipeif_params)); -} - -/* - * ipipeif_init_formats() - Initialize formats on all pads - * @sd: VPFE ipipeif V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPEIF_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipeif_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = IPIPEIF_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipeif_set_format(sd, fh->pad, &format); - - ipipeif_set_default_config(ipipeif); - - return 0; -} - -/* - * ipipeif_video_in_queue() - ipipeif video in queue - * @vpfe_dev: vpfe device pointer - * @addr: buffer address - */ -static int -ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - void __iomem *ipipeif_base_addr = ipipeif->ipipeif_base_addr; - unsigned int adofs; - u32 val; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return -EINVAL; - - switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) { - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - case MEDIA_BUS_FMT_YDYUYDYV8_1X16: - adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width; - break; - - default: - adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1; - break; - } - - /* adjust the line len to be a multiple of 32 */ - adofs += 31; - adofs &= ~0x1f; - val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS); - - /* lower sixteen bit */ - val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL); - - /* upper next seven bit */ - val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = { - .ioctl = ipipeif_ioctl, -}; - -static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = { - .s_ctrl = ipipeif_s_ctrl, -}; - -static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = { - .ops = &ipipeif_ctrl_ops, - .id = VPFE_CID_DPCM_PREDICTOR, - .name = "DPCM Predictor", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = 1, - .step = 1, - .def = 0, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = { - .open = ipipeif_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = { - .s_stream = ipipeif_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = { - .enum_mbus_code = ipipeif_enum_mbus_code, - .enum_frame_size = ipipeif_enum_frame_size, - .get_fmt = ipipeif_get_format, - .set_fmt = ipipeif_set_format, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops ipipeif_v4l2_ops = { - .core = &ipipeif_v4l2_core_ops, - .video = &ipipeif_v4l2_video_ops, - .pad = &ipipeif_v4l2_pad_ops, -}; - -static const struct vpfe_video_operations video_in_ops = { - .queue = ipipeif_video_in_queue, -}; - -static int -ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe = to_vpfe_device(ipipeif); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case IPIPEIF_PAD_SINK: - /* Single shot mode */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->input = IPIPEIF_INPUT_NONE; - break; - } - ipipeif->input = IPIPEIF_INPUT_MEMORY; - break; - - case IPIPEIF_PAD_SINK | 2 << 16: - /* read from isif */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->input = IPIPEIF_INPUT_NONE; - break; - } - if (ipipeif->input != IPIPEIF_INPUT_NONE) - return -EBUSY; - - ipipeif->input = IPIPEIF_INPUT_ISIF; - break; - - case IPIPEIF_PAD_SOURCE | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->output = IPIPEIF_OUTPUT_NONE; - break; - } - if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity) - /* connencted to ipipe */ - ipipeif->output = IPIPEIF_OUTPUT_IPIPE; - else if (remote->entity == &vpfe->vpfe_resizer.crop_resizer.subdev.entity) - /* connected to resizer */ - ipipeif->output = IPIPEIF_OUTPUT_RESIZER; - else - return -EINVAL; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations ipipeif_media_ops = { - .link_setup = ipipeif_link_setup, -}; - -/* - * vpfe_ipipeif_unregister_entities() - Unregister entity - * @ipipeif - pointer to ipipeif subdevice structure. - */ -void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif) -{ - /* unregister video device */ - vpfe_video_unregister(&ipipeif->video_in); - - /* unregister subdev */ - v4l2_device_unregister_subdev(&ipipeif->subdev); - /* cleanup entity */ - media_entity_cleanup(&ipipeif->subdev.entity); -} - -int -vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif); - unsigned int flags; - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev); - if (ret < 0) - return ret; - - ret = vpfe_video_register(&ipipeif->video_in, vdev); - if (ret) { - pr_err("Failed to register ipipeif video-in device\n"); - goto fail; - } - ipipeif->video_in.vpfe_dev = vpfe_dev; - - flags = 0; - ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0, - &ipipeif->subdev.entity, 0, flags); - if (ret < 0) - goto fail; - - return 0; -fail: - v4l2_device_unregister_subdev(&ipipeif->subdev); - - return ret; -} - -#define IPIPEIF_GAIN_HIGH 0x3ff -#define IPIPEIF_DEFAULT_GAIN 0x200 - -int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &ipipeif->subdev; - struct media_pad *pads = &ipipeif->pads[0]; - struct media_entity *me = &sd->entity; - static resource_size_t res_len; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len); - if (!ipipeif->ipipeif_base_addr) { - ret = -EBUSY; - goto fail; - } - - v4l2_subdev_init(sd, &ipipeif_v4l2_ops); - - sd->internal_ops = &ipipeif_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - - v4l2_set_subdevdata(sd, ipipeif); - - sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ipipeif->input = IPIPEIF_INPUT_NONE; - ipipeif->output = IPIPEIF_OUTPUT_NONE; - me->ops = &ipipeif_media_ops; - - ret = media_entity_pads_init(me, IPIPEIF_NUM_PADS, pads); - if (ret) - goto fail; - - v4l2_ctrl_handler_init(&ipipeif->ctrls, 2); - v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops, - V4L2_CID_GAIN, 0, - IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN); - v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL); - v4l2_ctrl_handler_setup(&ipipeif->ctrls); - sd->ctrl_handler = &ipipeif->ctrls; - - ipipeif->video_in.ops = &video_in_ops; - ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF"); - if (ret) { - pr_err("Failed to init IPIPEIF video-in device\n"); - goto fail; - } - ipipeif_set_default_config(ipipeif); - return 0; -fail: - release_mem_region(res->start, res_len); - return ret; -} - -void -vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev) -{ - struct resource *res; - - v4l2_ctrl_handler_free(&ipipeif->ctrls); - iounmap(ipipeif->ipipeif_base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - if (res) - release_mem_region(res->start, resource_size(res)); - -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h deleted file mode 100644 index 4d126fc871f3..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_H -#define _DAVINCI_VPFE_DM365_IPIPEIF_H - -#include - -#include -#include -#include - -#include "dm365_ipipeif_user.h" -#include "vpfe_video.h" - -/* IPIPE base specific types */ -enum ipipeif_data_shift { - IPIPEIF_BITS15_2 = 0, - IPIPEIF_BITS14_1 = 1, - IPIPEIF_BITS13_0 = 2, - IPIPEIF_BITS12_0 = 3, - IPIPEIF_BITS11_0 = 4, - IPIPEIF_BITS10_0 = 5, - IPIPEIF_BITS9_0 = 6, -}; - -enum ipipeif_clkdiv { - IPIPEIF_DIVIDE_HALF = 0, - IPIPEIF_DIVIDE_THIRD = 1, - IPIPEIF_DIVIDE_FOURTH = 2, - IPIPEIF_DIVIDE_FIFTH = 3, - IPIPEIF_DIVIDE_SIXTH = 4, - IPIPEIF_DIVIDE_EIGHTH = 5, - IPIPEIF_DIVIDE_SIXTEENTH = 6, - IPIPEIF_DIVIDE_THIRTY = 7, -}; - -enum ipipeif_pack_mode { - IPIPEIF_PACK_16_BIT = 0, - IPIPEIF_PACK_8_BIT = 1, -}; - -enum ipipeif_5_1_pack_mode { - IPIPEIF_5_1_PACK_16_BIT = 0, - IPIPEIF_5_1_PACK_8_BIT = 1, - IPIPEIF_5_1_PACK_8_BIT_A_LAW = 2, - IPIPEIF_5_1_PACK_12_BIT = 3 -}; - -enum ipipeif_input_source { - IPIPEIF_CCDC = 0, - IPIPEIF_SDRAM_RAW = 1, - IPIPEIF_CCDC_DARKFM = 2, - IPIPEIF_SDRAM_YUV = 3, -}; - -enum ipipeif_ialaw { - IPIPEIF_ALAW_OFF = 0, - IPIPEIF_ALAW_ON = 1, -}; - -enum ipipeif_input_src1 { - IPIPEIF_SRC1_PARALLEL_PORT = 0, - IPIPEIF_SRC1_SDRAM_RAW = 1, - IPIPEIF_SRC1_ISIF_DARKFM = 2, - IPIPEIF_SRC1_SDRAM_YUV = 3, -}; - -enum ipipeif_dfs_dir { - IPIPEIF_PORT_MINUS_SDRAM = 0, - IPIPEIF_SDRAM_MINUS_PORT = 1, -}; - -enum ipipeif_chroma_phase { - IPIPEIF_CBCR_Y = 0, - IPIPEIF_Y_CBCR = 1, -}; - -enum ipipeif_dpcm_type { - IPIPEIF_DPCM_8BIT_10BIT = 0, - IPIPEIF_DPCM_8BIT_12BIT = 1, -}; - -/* data shift for IPIPE 5.1 */ -enum ipipeif_5_1_data_shift { - IPIPEIF_5_1_BITS11_0 = 0, - IPIPEIF_5_1_BITS10_0 = 1, - IPIPEIF_5_1_BITS9_0 = 2, - IPIPEIF_5_1_BITS8_0 = 3, - IPIPEIF_5_1_BITS7_0 = 4, - IPIPEIF_5_1_BITS15_4 = 5, -}; - -#define IPIPEIF_PAD_SINK 0 -#define IPIPEIF_PAD_SOURCE 1 - -#define IPIPEIF_NUM_PADS 2 - -enum ipipeif_input_entity { - IPIPEIF_INPUT_NONE = 0, - IPIPEIF_INPUT_ISIF = 1, - IPIPEIF_INPUT_MEMORY = 2, -}; - -enum ipipeif_output_entity { - IPIPEIF_OUTPUT_NONE = 0, - IPIPEIF_OUTPUT_IPIPE = 1, - IPIPEIF_OUTPUT_RESIZER = 2, -}; - -struct vpfe_ipipeif_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPEIF_NUM_PADS]; - struct v4l2_mbus_framefmt formats[IPIPEIF_NUM_PADS]; - enum ipipeif_input_entity input; - unsigned int output; - struct vpfe_video_device video_in; - struct v4l2_ctrl_handler ctrls; - void __iomem *ipipeif_base_addr; - struct ipipeif_params config; - int dpcm_predictor; - int gain; -}; - -/* IPIPEIF Register Offsets from the base address */ -#define IPIPEIF_ENABLE 0x00 -#define IPIPEIF_CFG1 0x04 -#define IPIPEIF_PPLN 0x08 -#define IPIPEIF_LPFR 0x0c -#define IPIPEIF_HNUM 0x10 -#define IPIPEIF_VNUM 0x14 -#define IPIPEIF_ADDRU 0x18 -#define IPIPEIF_ADDRL 0x1c -#define IPIPEIF_ADOFS 0x20 -#define IPIPEIF_RSZ 0x24 -#define IPIPEIF_GAIN 0x28 - -/* Below registers are available only on IPIPE 5.1 */ -#define IPIPEIF_DPCM 0x2c -#define IPIPEIF_CFG2 0x30 -#define IPIPEIF_INIRSZ 0x34 -#define IPIPEIF_OCLIP 0x38 -#define IPIPEIF_DTUDF 0x3c -#define IPIPEIF_CLKDIV 0x40 -#define IPIPEIF_DPC1 0x44 -#define IPIPEIF_DPC2 0x48 -#define IPIPEIF_DFSGVL 0x4c -#define IPIPEIF_DFSGTH 0x50 -#define IPIPEIF_RSZ3A 0x54 -#define IPIPEIF_INIRSZ3A 0x58 -#define IPIPEIF_RSZ_MIN 16 -#define IPIPEIF_RSZ_MAX 112 -#define IPIPEIF_RSZ_CONST 16 - -#define IPIPEIF_ADOFS_LSB_MASK 0x1ff -#define IPIPEIF_ADOFS_LSB_SHIFT 5 -#define IPIPEIF_ADOFS_MSB_MASK 0x200 -#define IPIPEIF_ADDRU_MASK 0x7ff -#define IPIPEIF_ADDRL_SHIFT 5 -#define IPIPEIF_ADDRL_MASK 0xffff -#define IPIPEIF_ADDRU_SHIFT 21 -#define IPIPEIF_ADDRMSB_SHIFT 31 -#define IPIPEIF_ADDRMSB_LEFT_SHIFT 10 - -/* CFG1 Masks and shifts */ -#define ONESHOT_SHIFT 0 -#define DECIM_SHIFT 1 -#define INPSRC_SHIFT 2 -#define CLKDIV_SHIFT 4 -#define AVGFILT_SHIFT 7 -#define PACK8IN_SHIFT 8 -#define IALAW_SHIFT 9 -#define CLKSEL_SHIFT 10 -#define DATASFT_SHIFT 11 -#define INPSRC1_SHIFT 14 - -/* DPC2 */ -#define IPIPEIF_DPC2_EN_SHIFT 12 -#define IPIPEIF_DPC2_THR_MASK 0xfff -/* Applicable for IPIPE 5.1 */ -#define IPIPEIF_DF_GAIN_EN_SHIFT 10 -#define IPIPEIF_DF_GAIN_MASK 0x3ff -#define IPIPEIF_DF_GAIN_THR_MASK 0xfff -/* DPCM */ -#define IPIPEIF_DPCM_BITS_SHIFT 2 -#define IPIPEIF_DPCM_PRED_SHIFT 1 -/* CFG2 */ -#define IPIPEIF_CFG2_HDPOL_SHIFT 1 -#define IPIPEIF_CFG2_VDPOL_SHIFT 2 -#define IPIPEIF_CFG2_YUV8_SHIFT 6 -#define IPIPEIF_CFG2_YUV16_SHIFT 3 -#define IPIPEIF_CFG2_YUV8P_SHIFT 7 - -/* INIRSZ */ -#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT 13 -#define IPIPEIF_INIRSZ_MASK 0x1fff - -/* CLKDIV */ -#define IPIPEIF_CLKDIV_M_SHIFT 8 - -void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev); -void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif); -int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev); -int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev); -void vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev); -int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev); -int vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_device *vdev); -void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif); - -#endif /* _DAVINCI_VPFE_DM365_IPIPEIF_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h deleted file mode 100644 index 046dbdec67d8..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_USER_H -#define _DAVINCI_VPFE_DM365_IPIPEIF_USER_H - -/* clockdiv for IPIPE 5.1 */ -struct ipipeif_5_1_clkdiv { - unsigned char m; - unsigned char n; -}; - -enum ipipeif_decimation { - IPIPEIF_DECIMATION_OFF, - IPIPEIF_DECIMATION_ON -}; - -/* DPC at the if for IPIPE 5.1 */ -struct ipipeif_dpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* threshold */ - unsigned short thr; -}; - -enum ipipeif_clock { - IPIPEIF_PIXCEL_CLK, - IPIPEIF_SDRAM_CLK -}; - -enum ipipeif_avg_filter { - IPIPEIF_AVG_OFF, - IPIPEIF_AVG_ON -}; - -struct ipipeif_5_1 { - struct ipipeif_5_1_clkdiv clk_div; - /* Defect pixel correction */ - struct ipipeif_dpc dpc; - /* clipped to this value */ - unsigned short clip; - /* Align HSync and VSync to rsz_start */ - unsigned char align_sync; - /* resizer start position */ - unsigned int rsz_start; - /* DF gain enable */ - unsigned char df_gain_en; - /* DF gain value */ - unsigned short df_gain; - /* DF gain threshold value */ - unsigned short df_gain_thr; -}; - -struct ipipeif_params { - enum ipipeif_clock clock_select; - unsigned int ppln; - unsigned int lpfr; - unsigned char rsz; - enum ipipeif_decimation decimation; - enum ipipeif_avg_filter avg_filter; - /* IPIPE 5.1 */ - struct ipipeif_5_1 if_5_1; -}; - -/* - * Private IOCTL - * VIDIOC_VPFE_IPIPEIF_S_CONFIG: Set IPIEIF configuration - * VIDIOC_VPFE_IPIPEIF_G_CONFIG: Get IPIEIF configuration - */ -#define VIDIOC_VPFE_IPIPEIF_S_CONFIG \ - _IOWR('I', BASE_VIDIOC_PRIVATE + 1, struct ipipeif_params) -#define VIDIOC_VPFE_IPIPEIF_G_CONFIG \ - _IOWR('I', BASE_VIDIOC_PRIVATE + 2, struct ipipeif_params) - -#endif /* _DAVINCI_VPFE_DM365_IPIPEIF_USER_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c deleted file mode 100644 index 05a997f7aa5d..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ /dev/null @@ -1,2097 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#include -#include "dm365_isif.h" -#include "vpfe_mc_capture.h" - -#define MAX_WIDTH 4096 -#define MAX_HEIGHT 4096 - -static const unsigned int isif_fmts[] = { - MEDIA_BUS_FMT_YUYV8_2X8, - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_YUYV8_1X16, - MEDIA_BUS_FMT_YUYV10_1X20, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, -}; - -#define ISIF_COLPTN_R_Ye 0x0 -#define ISIF_COLPTN_Gr_Cy 0x1 -#define ISIF_COLPTN_Gb_G 0x2 -#define ISIF_COLPTN_B_Mg 0x3 - -#define ISIF_CCOLP_CP01_0 0 -#define ISIF_CCOLP_CP03_2 2 -#define ISIF_CCOLP_CP05_4 4 -#define ISIF_CCOLP_CP07_6 6 -#define ISIF_CCOLP_CP11_0 8 -#define ISIF_CCOLP_CP13_2 10 -#define ISIF_CCOLP_CP15_4 12 -#define ISIF_CCOLP_CP17_6 14 - -static const u32 isif_sgrbg_pattern = - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP01_0 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP03_2 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP05_4 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP07_6 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP11_0 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP13_2 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP15_4 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP17_6; - -static const u32 isif_srggb_pattern = - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP01_0 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP03_2 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP05_4 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP07_6 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP11_0 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP13_2 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP15_4 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP17_6; - -static inline u32 isif_read(void __iomem *base_addr, u32 offset) -{ - return readl(base_addr + offset); -} - -static inline void isif_write(void __iomem *base_addr, u32 val, u32 offset) -{ - writel(val, base_addr + offset); -} - -static inline u32 isif_merge(void __iomem *base_addr, u32 mask, u32 val, - u32 offset) -{ - u32 new_val = (isif_read(base_addr, offset) & ~mask) | (val & mask); - - isif_write(base_addr, new_val, offset); - - return new_val; -} - -static void isif_enable_output_to_sdram(struct vpfe_isif_device *isif, int en) -{ - isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_WEN_MASK, - en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN); -} - -static inline void -isif_regw_lin_tbl(struct vpfe_isif_device *isif, u32 val, u32 offset, int i) -{ - if (!i) - writel(val, isif->isif_cfg.linear_tbl0_addr + offset); - else - writel(val, isif->isif_cfg.linear_tbl1_addr + offset); -} - -static void isif_disable_all_modules(struct vpfe_isif_device *isif) -{ - /* disable BC */ - isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG); - /* disable vdfc */ - isif_write(isif->isif_cfg.base_addr, 0, DFCCTL); - /* disable CSC */ - isif_write(isif->isif_cfg.base_addr, 0, CSCCTL); - /* disable linearization */ - isif_write(isif->isif_cfg.base_addr, 0, LINCFG0); -} - -static void isif_enable(struct vpfe_isif_device *isif, int en) -{ - if (!en) - /* Before disable isif, disable all ISIF modules */ - isif_disable_all_modules(isif); - - /* - * wait for next VD. Assume lowest scan rate is 12 Hz. So - * 100 msec delay is good enough - */ - msleep(100); - isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK, - en, SYNCEN); -} - -/* - * ISIF helper functions - */ - -#define DM365_ISIF_MDFS_OFFSET 15 -#define DM365_ISIF_MDFS_MASK 0x1 - -/* get field id in isif hardware */ -enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev) -{ - struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif; - u32 field_status; - - field_status = isif_read(isif->isif_cfg.base_addr, MODESET); - return (field_status >> DM365_ISIF_MDFS_OFFSET) & - DM365_ISIF_MDFS_MASK; -} - -static int -isif_set_pixel_format(struct vpfe_isif_device *isif, unsigned int pixfmt) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) { - if (pixfmt == V4L2_PIX_FMT_SBGGR16) - isif->isif_cfg.data_pack = ISIF_PACK_16BIT; - else if ((pixfmt == V4L2_PIX_FMT_SGRBG10DPCM8) || - (pixfmt == V4L2_PIX_FMT_SGRBG10ALAW8)) - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; - else - return -EINVAL; - - isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW; - isif->isif_cfg.bayer.v4l2_pix_fmt = pixfmt; - } else { - if (pixfmt == V4L2_PIX_FMT_YUYV) - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_YCBYCR; - else if (pixfmt == V4L2_PIX_FMT_UYVY) - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY; - else - return -EINVAL; - - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; - isif->isif_cfg.ycbcr.v4l2_pix_fmt = pixfmt; - } - - return 0; -} - -static int -isif_set_frame_format(struct vpfe_isif_device *isif, - enum isif_frmfmt frm_fmt) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) - isif->isif_cfg.bayer.frm_fmt = frm_fmt; - else - isif->isif_cfg.ycbcr.frm_fmt = frm_fmt; - - return 0; -} - -static int isif_set_image_window(struct vpfe_isif_device *isif) -{ - struct v4l2_rect *win = &isif->crop; - - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) { - isif->isif_cfg.bayer.win.top = win->top; - isif->isif_cfg.bayer.win.left = win->left; - isif->isif_cfg.bayer.win.width = win->width; - isif->isif_cfg.bayer.win.height = win->height; - return 0; - } - isif->isif_cfg.ycbcr.win.top = win->top; - isif->isif_cfg.ycbcr.win.left = win->left; - isif->isif_cfg.ycbcr.win.width = win->width; - isif->isif_cfg.ycbcr.win.height = win->height; - - return 0; -} - -static int -isif_set_buftype(struct vpfe_isif_device *isif, enum isif_buftype buf_type) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) - isif->isif_cfg.bayer.buf_type = buf_type; - else - isif->isif_cfg.ycbcr.buf_type = buf_type; - - return 0; -} - -/* configure format in isif hardware */ -static int -isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad) -{ - struct vpfe_isif_device *vpfe_isif = &vpfe_dev->vpfe_isif; - enum isif_frmfmt frm_fmt = ISIF_FRMFMT_INTERLACED; - struct v4l2_pix_format format; - int ret = 0; - - v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_isif.formats[pad]); - mbus_to_pix(&vpfe_dev->vpfe_isif.formats[pad], &format); - - if (isif_set_pixel_format(vpfe_isif, format.pixelformat) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Failed to set pixel format in isif\n"); - return -EINVAL; - } - - /* call for s_crop will override these values */ - vpfe_isif->crop.left = 0; - vpfe_isif->crop.top = 0; - vpfe_isif->crop.width = format.width; - vpfe_isif->crop.height = format.height; - - /* configure the image window */ - isif_set_image_window(vpfe_isif); - - switch (vpfe_dev->vpfe_isif.formats[pad].field) { - case V4L2_FIELD_INTERLACED: - /* do nothing, since it is default */ - ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_INTERLEAVED); - break; - - case V4L2_FIELD_NONE: - frm_fmt = ISIF_FRMFMT_PROGRESSIVE; - /* buffer type only applicable for interlaced scan */ - break; - - case V4L2_FIELD_SEQ_TB: - ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_SEPARATED); - break; - - default: - return -EINVAL; - } - - /* set the frame format */ - if (!ret) - ret = isif_set_frame_format(vpfe_isif, frm_fmt); - - return ret; -} - -/* - * isif_try_format() - Try video format on a pad - * @isif: VPFE isif device - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - */ -static void -isif_try_format(struct vpfe_isif_device *isif, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - unsigned int width = fmt->format.width; - unsigned int height = fmt->format.height; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(isif_fmts); i++) { - if (fmt->format.code == isif_fmts[i]) - break; - } - - /* If not found, use YUYV8_2x8 as default */ - if (i >= ARRAY_SIZE(isif_fmts)) - fmt->format.code = MEDIA_BUS_FMT_YUYV8_2X8; - - /* Clamp the size. */ - fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH); - fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT); - - /* The data formatter truncates the number of horizontal output - * pixels to a multiple of 16. To avoid clipping data, allow - * callers to request an output size bigger than the input size - * up to the nearest multiple of 16. - */ - if (fmt->pad == ISIF_PAD_SOURCE) - fmt->format.width &= ~15; -} - -/* - * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr - * @isif: Pointer to isif subdevice. - */ -void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - struct vpfe_video_device *video = &isif->video_out; - enum v4l2_field field; - int fid; - - if (!video->started) - return; - - field = video->fmt.fmt.pix.field; - - if (field == V4L2_FIELD_NONE) { - /* handle progressive frame capture */ - if (video->cur_frm != video->next_frm) - vpfe_video_process_buffer_complete(video); - return; - } - - /* interlaced or TB capture check which field we - * are in hardware - */ - fid = vpfe_isif_get_fid(vpfe_dev); - - /* switch the software maintained field id */ - video->field_id ^= 1; - if (fid == video->field_id) { - /* we are in-sync here,continue */ - if (fid == 0) { - /* - * One frame is just being captured. If the - * next frame is available, release the current - * frame and move on - */ - if (video->cur_frm != video->next_frm) - vpfe_video_process_buffer_complete(video); - /* - * based on whether the two fields are stored - * interleavely or separately in memory, - * reconfigure the ISIF memory address - */ - if (field == V4L2_FIELD_SEQ_TB) - vpfe_video_schedule_bottom_field(video); - return; - } - /* - * if one field is just being captured configure - * the next frame get the next frame from the - * empty queue if no frame is available hold on - * to the current buffer - */ - spin_lock(&video->dma_queue_lock); - if (!list_empty(&video->dma_queue) && - video->cur_frm == video->next_frm) - vpfe_video_schedule_next_buffer(video); - spin_unlock(&video->dma_queue_lock); - } else if (fid == 0) { - /* - * out of sync. Recover from any hardware out-of-sync. - * May loose one frame - */ - video->field_id = fid; - } -} - -/* - * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr - * @isif: Pointer to isif subdevice. - */ -void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif) -{ - struct vpfe_video_device *video = &isif->video_out; - - if (!video->started) - return; - - spin_lock(&video->dma_queue_lock); - if (video->fmt.fmt.pix.field == V4L2_FIELD_NONE && - !list_empty(&video->dma_queue) && video->cur_frm == video->next_frm) - vpfe_video_schedule_next_buffer(video); - - spin_unlock(&video->dma_queue_lock); -} - -/* - * VPFE video operations - */ - -static int isif_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr) -{ - struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif; - - isif_write(isif->isif_cfg.base_addr, (addr >> 21) & - ISIF_CADU_BITS, CADU); - isif_write(isif->isif_cfg.base_addr, (addr >> 5) & - ISIF_CADL_BITS, CADL); - - return 0; -} - -static const struct vpfe_video_operations isif_video_ops = { - .queue = isif_video_queue, -}; - -/* - * V4L2 subdev operations - */ - -/* Parameter operations */ -static int isif_get_params(struct v4l2_subdev *sd, void *params) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - - /* only raw module parameters can be set through the IOCTL */ - if (isif->formats[ISIF_PAD_SINK].code != MEDIA_BUS_FMT_SGRBG12_1X12) - return -EINVAL; - memcpy(params, &isif->isif_cfg.bayer.config_params, - sizeof(isif->isif_cfg.bayer.config_params)); - return 0; -} - -static int isif_validate_df_csc_params(const struct vpfe_isif_df_csc *df_csc) -{ - const struct vpfe_isif_color_space_conv *csc; - int err = -EINVAL; - int i; - - if (!df_csc->df_or_csc) { - /* csc configuration */ - csc = &df_csc->csc; - if (csc->en) { - for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) - if (csc->coeff[i].integer > - ISIF_CSC_COEF_INTEG_MASK || - csc->coeff[i].decimal > - ISIF_CSC_COEF_DECIMAL_MASK) { - pr_err("Invalid CSC coefficients\n"); - return err; - } - } - } - if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) { - pr_err("Invalid df_csc start pix value\n"); - return err; - } - - if (df_csc->num_pixels > ISIF_DF_NUMPIX) { - pr_err("Invalid df_csc num pixels value\n"); - return err; - } - - if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) { - pr_err("Invalid df_csc start_line value\n"); - return err; - } - - if (df_csc->num_lines > ISIF_DF_NUMLINES) { - pr_err("Invalid df_csc num_lines value\n"); - return err; - } - - return 0; -} - -#define DM365_ISIF_MAX_VDFLSFT 4 -#define DM365_ISIF_MAX_VDFSLV 4095 -#define DM365_ISIF_MAX_DFCMEM0 0x1fff -#define DM365_ISIF_MAX_DFCMEM1 0x1fff - -static int isif_validate_dfc_params(const struct vpfe_isif_dfc *dfc) -{ - int err = -EINVAL; - int i; - - if (!dfc->en) - return 0; - - if (dfc->corr_whole_line > 1) { - pr_err("Invalid corr_whole_line value\n"); - return err; - } - - if (dfc->def_level_shift > DM365_ISIF_MAX_VDFLSFT) { - pr_err("Invalid def_level_shift value\n"); - return err; - } - - if (dfc->def_sat_level > DM365_ISIF_MAX_VDFSLV) { - pr_err("Invalid def_sat_level value\n"); - return err; - } - - if (!dfc->num_vdefects || - dfc->num_vdefects > VPFE_ISIF_VDFC_TABLE_SIZE) { - pr_err("Invalid num_vdefects value\n"); - return err; - } - - for (i = 0; i < VPFE_ISIF_VDFC_TABLE_SIZE; i++) { - if (dfc->table[i].pos_vert > DM365_ISIF_MAX_DFCMEM0) { - pr_err("Invalid pos_vert value\n"); - return err; - } - if (dfc->table[i].pos_horz > DM365_ISIF_MAX_DFCMEM1) { - pr_err("Invalid pos_horz value\n"); - return err; - } - } - - return 0; -} - -#define DM365_ISIF_MAX_CLVRV 0xfff -#define DM365_ISIF_MAX_CLDC 0x1fff -#define DM365_ISIF_MAX_CLHSH 0x1fff -#define DM365_ISIF_MAX_CLHSV 0x1fff -#define DM365_ISIF_MAX_CLVSH 0x1fff -#define DM365_ISIF_MAX_CLVSV 0x1fff -#define DM365_ISIF_MAX_HEIGHT_BLACK_REGION 0x1fff - -static int isif_validate_bclamp_params(const struct vpfe_isif_black_clamp *bclamp) -{ - int err = -EINVAL; - - if (bclamp->dc_offset > DM365_ISIF_MAX_CLDC) { - pr_err("Invalid bclamp dc_offset value\n"); - return err; - } - if (!bclamp->en) - return 0; - if (bclamp->horz.clamp_pix_limit > 1) { - pr_err("Invalid bclamp horz clamp_pix_limit value\n"); - return err; - } - if (bclamp->horz.win_count_calc < 1 || - bclamp->horz.win_count_calc > 32) { - pr_err("Invalid bclamp horz win_count_calc value\n"); - return err; - } - if (bclamp->horz.win_start_h_calc > DM365_ISIF_MAX_CLHSH) { - pr_err("Invalid bclamp win_start_v_calc value\n"); - return err; - } - - if (bclamp->horz.win_start_v_calc > DM365_ISIF_MAX_CLHSV) { - pr_err("Invalid bclamp win_start_v_calc value\n"); - return err; - } - if (bclamp->vert.reset_clamp_val > DM365_ISIF_MAX_CLVRV) { - pr_err("Invalid bclamp reset_clamp_val value\n"); - return err; - } - if (bclamp->vert.ob_v_sz_calc > DM365_ISIF_MAX_HEIGHT_BLACK_REGION) { - pr_err("Invalid bclamp ob_v_sz_calc value\n"); - return err; - } - if (bclamp->vert.ob_start_h > DM365_ISIF_MAX_CLVSH) { - pr_err("Invalid bclamp ob_start_h value\n"); - return err; - } - if (bclamp->vert.ob_start_v > DM365_ISIF_MAX_CLVSV) { - pr_err("Invalid bclamp ob_start_h value\n"); - return err; - } - return 0; -} - -static int -isif_validate_raw_params(const struct vpfe_isif_raw_config *params) -{ - int ret; - - ret = isif_validate_df_csc_params(¶ms->df_csc); - if (ret) - return ret; - ret = isif_validate_dfc_params(¶ms->dfc); - if (ret) - return ret; - return isif_validate_bclamp_params(¶ms->bclamp); -} - -static int isif_set_params(struct v4l2_subdev *sd, const struct vpfe_isif_raw_config *params) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - int ret = -EINVAL; - - /* only raw module parameters can be set through the IOCTL */ - if (isif->formats[ISIF_PAD_SINK].code != MEDIA_BUS_FMT_SGRBG12_1X12) - return ret; - - if (!isif_validate_raw_params(params)) { - memcpy(&isif->isif_cfg.bayer.config_params, params, - sizeof(*params)); - ret = 0; - } - return ret; -} -/* - * isif_ioctl() - isif module private ioctl's - * @sd: VPFE isif V4L2 subdevice - * @cmd: ioctl command - * @arg: ioctl argument - * - * Return 0 on success or a negative error code otherwise. - */ -static long isif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_VPFE_ISIF_S_RAW_PARAMS: - return isif_set_params(sd, arg); - - case VIDIOC_VPFE_ISIF_G_RAW_PARAMS: - return isif_get_params(sd, arg); - - default: - return -ENOIOCTLCMD; - } -} - -static void isif_config_gain_offset(struct vpfe_isif_device *isif) -{ - struct vpfe_isif_gain_offsets_adj *gain_off_ptr = - &isif->isif_cfg.bayer.config_params.gain_offset; - void __iomem *base = isif->isif_cfg.base_addr; - u32 val; - - val = ((gain_off_ptr->gain_sdram_en & 1) << GAIN_SDRAM_EN_SHIFT) | - ((gain_off_ptr->gain_ipipe_en & 1) << GAIN_IPIPE_EN_SHIFT) | - ((gain_off_ptr->gain_h3a_en & 1) << GAIN_H3A_EN_SHIFT) | - ((gain_off_ptr->offset_sdram_en & 1) << OFST_SDRAM_EN_SHIFT) | - ((gain_off_ptr->offset_ipipe_en & 1) << OFST_IPIPE_EN_SHIFT) | - ((gain_off_ptr->offset_h3a_en & 1) << OFST_H3A_EN_SHIFT); - isif_merge(base, GAIN_OFFSET_EN_MASK, val, CGAMMAWD); - - isif_write(base, isif->isif_cfg.isif_gain_params.cr_gain, CRGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cgr_gain, CGRGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cgb_gain, CGBGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cb_gain, CBGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.offset & OFFSET_MASK, - COFSTA); - -} - -static void isif_config_bclamp(struct vpfe_isif_device *isif, - struct vpfe_isif_black_clamp *bc) -{ - u32 val; - - /** - * DC Offset is always added to image data irrespective of bc enable - * status - */ - val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLDCOFST); - - if (!bc->en) - return; - - val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) << - ISIF_BC_MODE_COLOR_SHIFT; - - /* Enable BC and horizontal clamp calculation parameters */ - val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) << - ISIF_HORZ_BC_MODE_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CLAMPCFG); - - if (bc->horz.mode != VPFE_ISIF_HORZ_BC_DISABLE) { - /* - * Window count for calculation - * Base window selection - * pixel limit - * Horizontal size of window - * vertical size of the window - * Horizontal start position of the window - * Vertical start position of the window - */ - val = (bc->horz.win_count_calc & ISIF_HORZ_BC_WIN_COUNT_MASK) | - ((bc->horz.base_win_sel_calc & 1) << - ISIF_HORZ_BC_WIN_SEL_SHIFT) | - ((bc->horz.clamp_pix_limit & 1) << - ISIF_HORZ_BC_PIX_LIMIT_SHIFT) | - ((bc->horz.win_h_sz_calc & - ISIF_HORZ_BC_WIN_H_SIZE_MASK) << - ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) | - ((bc->horz.win_v_sz_calc & - ISIF_HORZ_BC_WIN_V_SIZE_MASK) << - ISIF_HORZ_BC_WIN_V_SIZE_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CLHWIN0); - - val = bc->horz.win_start_h_calc & ISIF_HORZ_BC_WIN_START_H_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLHWIN1); - - val = bc->horz.win_start_v_calc & ISIF_HORZ_BC_WIN_START_V_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLHWIN2); - } - - /* vertical clamp calculation parameters */ - /* OB H Valid */ - val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK; - - /* Reset clamp value sel for previous line */ - val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) << - ISIF_VERT_BC_RST_VAL_SEL_SHIFT; - - /* Line average coefficient */ - val |= bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN0); - - /* Configured reset value */ - if (bc->vert.reset_val_sel == VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) { - val = bc->vert.reset_clamp_val & ISIF_VERT_BC_RST_VAL_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVRV); - } - - /* Optical Black horizontal start position */ - val = bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN1); - - /* Optical Black vertical start position */ - val = bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN2); - - val = bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN3); - - /* Vertical start position for BC subtraction */ - val = bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLSV); -} - -/* This function will configure the window size to be capture in ISIF reg */ -static void -isif_setwin(struct vpfe_isif_device *isif, struct v4l2_rect *image_win, - enum isif_frmfmt frm_fmt, int ppc, int mode) -{ - int horz_nr_pixels; - int vert_nr_lines; - int horz_start; - int vert_start; - int mid_img; - - /* - * ppc - per pixel count. indicates how many pixels per cell - * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. - * raw capture this is 1 - */ - horz_start = image_win->left << (ppc - 1); - horz_nr_pixels = (image_win->width << (ppc - 1)) - 1; - - /* Writing the horizontal info into the registers */ - isif_write(isif->isif_cfg.base_addr, - horz_start & START_PX_HOR_MASK, SPH); - isif_write(isif->isif_cfg.base_addr, - horz_nr_pixels & NUM_PX_HOR_MASK, LNH); - vert_start = image_win->top; - - if (frm_fmt == ISIF_FRMFMT_INTERLACED) { - vert_nr_lines = (image_win->height >> 1) - 1; - vert_start >>= 1; - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - } else { - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - vert_nr_lines = image_win->height - 1; - /* configure VDINT0 and VDINT1 */ - mid_img = vert_start + (image_win->height / 2); - isif_write(isif->isif_cfg.base_addr, mid_img, VDINT1); - } - - if (!mode) - isif_write(isif->isif_cfg.base_addr, 0, VDINT0); - else - isif_write(isif->isif_cfg.base_addr, vert_nr_lines, VDINT0); - isif_write(isif->isif_cfg.base_addr, - vert_start & START_VER_ONE_MASK, SLV0); - isif_write(isif->isif_cfg.base_addr, - vert_start & START_VER_TWO_MASK, SLV1); - isif_write(isif->isif_cfg.base_addr, - vert_nr_lines & NUM_LINES_VER, LNV); -} - -#define DM365_ISIF_DFCMWR_MEMORY_WRITE 1 -#define DM365_ISIF_DFCMRD_MEMORY_READ 0x2 - -static void -isif_config_dfc(struct vpfe_isif_device *isif, struct vpfe_isif_dfc *vdfc) -{ -#define DFC_WRITE_WAIT_COUNT 1000 - u32 count = DFC_WRITE_WAIT_COUNT; - u32 val; - int i; - - if (!vdfc->en) - return; - - /* Correction mode */ - val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) << - ISIF_VDFC_CORR_MOD_SHIFT; - - /* Correct whole line or partial */ - if (vdfc->corr_whole_line) - val |= BIT(ISIF_VDFC_CORR_WHOLE_LN_SHIFT); - - /* level shift value */ - val |= (vdfc->def_level_shift & ISIF_VDFC_LEVEL_SHFT_MASK) << - ISIF_VDFC_LEVEL_SHFT_SHIFT; - - isif_write(isif->isif_cfg.base_addr, val, DFCCTL); - - /* Defect saturation level */ - val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK; - isif_write(isif->isif_cfg.base_addr, val, VDFSATLV); - - isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_vert & - ISIF_VDFC_POS_MASK, DFCMEM0); - isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_horz & - ISIF_VDFC_POS_MASK, DFCMEM1); - if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL || - vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_at_pos, DFCMEM2); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_up_pixels, DFCMEM3); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_low_pixels, DFCMEM4); - } - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - /* set DFCMARST and set DFCMWR */ - val |= BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL); - - while (count && (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x01)) - count--; - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - - for (i = 1; i < vdfc->num_vdefects; i++) { - isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_vert & - ISIF_VDFC_POS_MASK, DFCMEM0); - - isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_horz & - ISIF_VDFC_POS_MASK, DFCMEM1); - - if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL || - vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_at_pos, DFCMEM2); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_up_pixels, DFCMEM3); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_low_pixels, DFCMEM4); - } - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - /* clear DFCMARST and set DFCMWR */ - val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL); - - count = DFC_WRITE_WAIT_COUNT; - while (count && (isif_read(isif->isif_cfg.base_addr, - DFCMEMCTL) & 0x01)) - count--; - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - } - if (vdfc->num_vdefects < VPFE_ISIF_VDFC_TABLE_SIZE) { - /* Extra cycle needed */ - isif_write(isif->isif_cfg.base_addr, 0, DFCMEM0); - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_MAX_DFCMEM1, DFCMEM1); - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_DFCMWR_MEMORY_WRITE, DFCMEMCTL); - } - /* enable VDFC */ - isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT), - (1 << ISIF_VDFC_EN_SHIFT), DFCCTL); - - isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT), - (0 << ISIF_VDFC_EN_SHIFT), DFCCTL); - - isif_write(isif->isif_cfg.base_addr, 0x6, DFCMEMCTL); - for (i = 0; i < vdfc->num_vdefects; i++) { - count = DFC_WRITE_WAIT_COUNT; - while (count && - (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x2)) - count--; - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_DFCMRD_MEMORY_READ, DFCMEMCTL); - } -} - -static void -isif_config_csc(struct vpfe_isif_device *isif, struct vpfe_isif_df_csc *df_csc) -{ - u32 val1; - u32 val2; - u32 i; - - if (!df_csc->csc.en) { - isif_write(isif->isif_cfg.base_addr, 0, CSCCTL); - return; - } - /* initialize all bits to 0 */ - val1 = 0; - for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) { - if ((i % 2) == 0) { - /* CSCM - LSB */ - val1 = ((df_csc->csc.coeff[i].integer & - ISIF_CSC_COEF_INTEG_MASK) << - ISIF_CSC_COEF_INTEG_SHIFT) | - ((df_csc->csc.coeff[i].decimal & - ISIF_CSC_COEF_DECIMAL_MASK)); - } else { - - /* CSCM - MSB */ - val2 = ((df_csc->csc.coeff[i].integer & - ISIF_CSC_COEF_INTEG_MASK) << - ISIF_CSC_COEF_INTEG_SHIFT) | - ((df_csc->csc.coeff[i].decimal & - ISIF_CSC_COEF_DECIMAL_MASK)); - val2 <<= ISIF_CSCM_MSB_SHIFT; - val2 |= val1; - isif_write(isif->isif_cfg.base_addr, val2, - (CSCM0 + ((i-1) << 1))); - } - } - /* program the active area */ - isif_write(isif->isif_cfg.base_addr, df_csc->start_pix & - ISIF_DF_CSC_SPH_MASK, FMTSPH); - /* - * one extra pixel as required for CSC. Actually number of - * pixel - 1 should be configured in this register. So we - * need to subtract 1 before writing to FMTSPH, but we will - * not do this since csc requires one extra pixel - */ - isif_write(isif->isif_cfg.base_addr, df_csc->num_pixels & - ISIF_DF_CSC_SPH_MASK, FMTLNH); - isif_write(isif->isif_cfg.base_addr, df_csc->start_line & - ISIF_DF_CSC_SPH_MASK, FMTSLV); - /* - * one extra line as required for CSC. See reason documented for - * num_pixels - */ - isif_write(isif->isif_cfg.base_addr, df_csc->num_lines & - ISIF_DF_CSC_SPH_MASK, FMTLNV); - /* Enable CSC */ - isif_write(isif->isif_cfg.base_addr, 1, CSCCTL); -} - -static void -isif_config_linearization(struct vpfe_isif_device *isif, - struct vpfe_isif_linearize *linearize) -{ - u32 val; - u32 i; - - if (!linearize->en) { - isif_write(isif->isif_cfg.base_addr, 0, LINCFG0); - return; - } - /* shift value for correction */ - val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) << - ISIF_LIN_CORRSFT_SHIFT; - /* enable */ - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, LINCFG0); - /* Scale factor */ - val = (linearize->scale_fact.integer & 1) << - ISIF_LIN_SCALE_FACT_INTEG_SHIFT; - val |= linearize->scale_fact.decimal & ISIF_LIN_SCALE_FACT_DECIMAL_MASK; - isif_write(isif->isif_cfg.base_addr, val, LINCFG1); - - for (i = 0; i < VPFE_ISIF_LINEAR_TAB_SIZE; i++) { - val = linearize->table[i] & ISIF_LIN_ENTRY_MASK; - if (i%2) - isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 1); - else - isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 0); - } -} - -static void -isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul) -{ - u32 val; - - /* Horizontal pattern */ - val = cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT; - val |= cul->hcpat_odd; - isif_write(isif->isif_cfg.base_addr, val, CULH); - /* vertical pattern */ - isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV); - /* LPF */ - isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT, - cul->en_lpf << ISIF_LPF_SHIFT, MODESET); -} - -static int isif_get_pix_fmt(u32 mbus_code) -{ - switch (mbus_code) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return ISIF_PIXFMT_RAW; - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - case MEDIA_BUS_FMT_Y8_1X8: - return ISIF_PIXFMT_YCBCR_8BIT; - - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - return ISIF_PIXFMT_YCBCR_16BIT; - - default: - break; - } - return -EINVAL; -} - -#define ISIF_INTERLACE_INVERSE_MODE 0x4b6d -#define ISIF_INTERLACE_NON_INVERSE_MODE 0x0b6d -#define ISIF_PROGRESSIVE_INVERSE_MODE 0x4000 -#define ISIF_PROGRESSIVE_NON_INVERSE_MODE 0x0000 - -static int isif_config_raw(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct isif_params_raw *params = &isif->isif_cfg.bayer; - struct vpfe_isif_raw_config *module_params = - &isif->isif_cfg.bayer.config_params; - struct v4l2_mbus_framefmt *format; - int pix_fmt; - u32 val; - - format = &isif->formats[ISIF_PAD_SINK]; - - /* In case of user has set BT656IF earlier, it should be reset - * when configuring for raw input. - */ - isif_write(isif->isif_cfg.base_addr, 0, REC656IF); - /* Configure CCDCFG register - * Set CCD Not to swap input since input is RAW data - * Set FID detection function to Latch at V-Sync - * Set WENLOG - isif valid area - * Set TRGSEL - * Set EXTRG - * Packed to 8 or 16 bits - */ - val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC | - ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN | - ISIF_CCDCFG_EXTRG_DISABLE | (isif->isif_cfg.data_pack & - ISIF_DATA_PACK_MASK); - isif_write(isif->isif_cfg.base_addr, val, CCDCFG); - - pix_fmt = isif_get_pix_fmt(format->code); - if (pix_fmt < 0) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* - * Configure the vertical sync polarity(MODESET.VDPOL) - * Configure the horizontal sync polarity (MODESET.HDPOL) - * Configure frame id polarity (MODESET.FLDPOL) - * Configure data polarity - * Configure External WEN Selection - * Configure frame format(progressive or interlace) - * Configure pixel format (Input mode) - * Configure the data shift - */ - val = ISIF_VDHDOUT_INPUT | ((params->vd_pol & ISIF_VD_POL_MASK) << - ISIF_VD_POL_SHIFT) | ((params->hd_pol & ISIF_HD_POL_MASK) << - ISIF_HD_POL_SHIFT) | ((params->fid_pol & ISIF_FID_POL_MASK) << - ISIF_FID_POL_SHIFT) | ((ISIF_DATAPOL_NORMAL & - ISIF_DATAPOL_MASK) << ISIF_DATAPOL_SHIFT) | ((ISIF_EXWEN_DISABLE & - ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) | ((params->frm_fmt & - ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) | ((pix_fmt & - ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT); - - /* currently only MEDIA_BUS_FMT_SGRBG12_1X12 is - * supported. shift appropriately depending on - * different MBUS fmt's added - */ - if (format->code == MEDIA_BUS_FMT_SGRBG12_1X12) - val |= ((VPFE_ISIF_NO_SHIFT & - ISIF_DATASFT_MASK) << ISIF_DATASFT_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, MODESET); - /* - * Configure GAMMAWD register - * CFA pattern setting - */ - val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) << - ISIF_GAMMAWD_CFA_SHIFT; - /* Gamma msb */ - if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10ALAW8) - val = val | ISIF_ALAW_ENABLE; - - val = val | ((params->data_msb & ISIF_ALAW_GAMA_WD_MASK) << - ISIF_ALAW_GAMA_WD_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CGAMMAWD); - /* Configure DPCM compression settings */ - if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10DPCM8) { - val = BIT(ISIF_DPCM_EN_SHIFT); - val |= (params->dpcm_predictor & - ISIF_DPCM_PREDICTOR_MASK) << ISIF_DPCM_PREDICTOR_SHIFT; - } - isif_write(isif->isif_cfg.base_addr, val, MISC); - /* Configure Gain & Offset */ - isif_config_gain_offset(isif); - /* Configure Color pattern */ - if (format->code == MEDIA_BUS_FMT_SGRBG12_1X12) - val = isif_sgrbg_pattern; - else - /* default set to rggb */ - val = isif_srggb_pattern; - - isif_write(isif->isif_cfg.base_addr, val, CCOLP); - - /* Configure HSIZE register */ - val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) << - ISIF_HSIZE_FLIP_SHIFT; - - /* calculate line offset in 32 bytes based on pack value */ - if (isif->isif_cfg.data_pack == ISIF_PACK_8BIT) - val |= ((params->win.width + 31) >> 5) & ISIF_LINEOFST_MASK; - else if (isif->isif_cfg.data_pack == ISIF_PACK_12BIT) - val |= ((((params->win.width + (params->win.width >> 2)) + - 31) >> 5) & ISIF_LINEOFST_MASK); - else - val |= (((params->win.width * 2) + 31) >> 5) & - ISIF_LINEOFST_MASK; - isif_write(isif->isif_cfg.base_addr, val, HSIZE); - /* Configure SDOFST register */ - if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) { - if (params->image_invert_en) - /* For interlace inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_INTERLACE_INVERSE_MODE, SDOFST); - else - /* For interlace non inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_INTERLACE_NON_INVERSE_MODE, SDOFST); - } else if (params->frm_fmt == ISIF_FRMFMT_PROGRESSIVE) { - if (params->image_invert_en) - isif_write(isif->isif_cfg.base_addr, - ISIF_PROGRESSIVE_INVERSE_MODE, SDOFST); - else - /* For progessive non inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST); - } - /* Configure video window */ - isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode); - /* Configure Black Clamp */ - isif_config_bclamp(isif, &module_params->bclamp); - /* Configure Vertical Defection Pixel Correction */ - isif_config_dfc(isif, &module_params->dfc); - if (!module_params->df_csc.df_or_csc) - /* Configure Color Space Conversion */ - isif_config_csc(isif, &module_params->df_csc); - - isif_config_linearization(isif, &module_params->linearize); - /* Configure Culling */ - isif_config_culling(isif, &module_params->culling); - /* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */ - val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, DATAHOFST); - - val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, DATAVOFST); - - return 0; -} - -#define DM365_ISIF_HSIZE_MASK 0xffffffe0 -#define DM365_ISIF_SDOFST_2_LINES 0x00000249 - -/* This function will configure ISIF for YCbCr parameters. */ -static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct isif_ycbcr_config *params = &isif->isif_cfg.ycbcr; - struct v4l2_mbus_framefmt *format; - int pix_fmt; - u32 modeset; - u32 ccdcfg; - - format = &isif->formats[ISIF_PAD_SINK]; - /* - * first reset the ISIF - * all registers have default values after reset - * This is important since we assume default values to be set in - * a lot of registers that we didn't touch - */ - /* start with all bits zero */ - ccdcfg = 0; - modeset = 0; - pix_fmt = isif_get_pix_fmt(format->code); - if (pix_fmt < 0) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* configure pixel format or input mode */ - modeset = modeset | ((pix_fmt & ISIF_INPUT_MASK) << - ISIF_INPUT_SHIFT) | ((params->frm_fmt & ISIF_FRM_FMT_MASK) << - ISIF_FRM_FMT_SHIFT) | (((params->fid_pol & - ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT)) | - (((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) | - (((params->vd_pol & ISIF_VD_POL_MASK) << ISIF_VD_POL_SHIFT)); - /* pack the data to 8-bit CCDCCFG */ - switch (format->code) { - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - modeset |= ((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK) << - ISIF_VD_POL_SHIFT); - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR; - break; - - case MEDIA_BUS_FMT_YUYV10_2X10: - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* setup BT.656, embedded sync */ - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - /* enable 10 bit mode in ccdcfg */ - ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR | - ISIF_BW656_ENABLE; - break; - - case MEDIA_BUS_FMT_YUYV10_1X20: - if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - break; - - case MEDIA_BUS_FMT_Y8_1X8: - ccdcfg |= ISIF_PACK_8BIT; - ccdcfg |= ISIF_YCINSWP_YCBCR; - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - - case MEDIA_BUS_FMT_YUYV8_1X16: - if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - - default: - /* should never come here */ - pr_debug("Invalid interface type\n"); - return -EINVAL; - } - isif_write(isif->isif_cfg.base_addr, modeset, MODESET); - /* Set up pix order */ - ccdcfg |= (params->pix_order & ISIF_PIX_ORDER_MASK) << - ISIF_PIX_ORDER_SHIFT; - isif_write(isif->isif_cfg.base_addr, ccdcfg, CCDCFG); - /* configure video window */ - if (format->code == MEDIA_BUS_FMT_YUYV10_1X20 || - format->code == MEDIA_BUS_FMT_YUYV8_1X16) - isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode); - else - isif_setwin(isif, ¶ms->win, params->frm_fmt, 2, mode); - - /* - * configure the horizontal line offset - * this is done by rounding up width to a multiple of 16 pixels - * and multiply by two to account for y:cb:cr 4:2:2 data - */ - isif_write(isif->isif_cfg.base_addr, - ((((params->win.width * 2) + 31) & - DM365_ISIF_HSIZE_MASK) >> 5), HSIZE); - - /* configure the memory line offset */ - if (params->frm_fmt == ISIF_FRMFMT_INTERLACED && - params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED) - /* two fields are interleaved in memory */ - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_SDOFST_2_LINES, SDOFST); - return 0; -} - -static int isif_configure(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = &isif->formats[ISIF_PAD_SINK]; - - switch (format->code) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return isif_config_raw(sd, mode); - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - return isif_config_ycbcr(sd, mode); - - default: - break; - } - return -EINVAL; -} - -/* - * isif_set_stream() - Enable/Disable streaming on the ISIF module - * @sd: VPFE ISIF V4L2 subdevice - * @enable: Enable/disable stream - */ -static int isif_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - int ret; - - if (enable) { - ret = isif_configure(sd, - (isif->output == ISIF_OUTPUT_MEMORY) ? 0 : 1); - if (ret) - return ret; - if (isif->output == ISIF_OUTPUT_MEMORY) - isif_enable_output_to_sdram(isif, 1); - isif_enable(isif, 1); - } else { - isif_enable(isif, 0); - isif_enable_output_to_sdram(isif, 0); - } - - return 0; -} - -/* - * __isif_get_format() - helper function for getting isif format - * @isif: pointer to isif private structure. - * @pad: pad number. - * @cfg: V4L2 subdev pad config - * @which: wanted subdev format. - */ -static struct v4l2_mbus_framefmt * -__isif_get_format(struct vpfe_isif_device *isif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&isif->subdev, cfg, pad); - - return &isif->formats[pad]; -} - -/* - * isif_set_format() - set format on pad - * @sd : VPFE ISIF device - * @cfg : V4L2 subdev pad config - * @fmt : pointer to v4l2 subdev format structure - * - * Return 0 on success or -EINVAL if format or pad is invalid - */ -static int -isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - struct v4l2_mbus_framefmt *format; - - format = __isif_get_format(isif, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - isif_try_format(isif, cfg, fmt); - memcpy(format, &fmt->format, sizeof(*format)); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == ISIF_PAD_SOURCE) - return isif_config_format(vpfe_dev, fmt->pad); - - return 0; -} - -/* - * isif_get_format() - Retrieve the video format on a pad - * @sd: VPFE ISIF V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int -isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __isif_get_format(vpfe_isif, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - memcpy(&fmt->format, format, sizeof(fmt->format)); - - return 0; -} - -/* - * isif_enum_frame_size() - enum frame sizes on pads - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_frame_size_enum structure - */ -static int -isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - if (fse->index != 0) - return -EINVAL; - - format.pad = fse->pad; - format.format.code = fse->code; - format.format.width = 1; - format.format.height = 1; - format.which = fse->which; - isif_try_format(isif, cfg, &format); - fse->min_width = format.format.width; - fse->min_height = format.format.height; - - if (format.format.code != fse->code) - return -EINVAL; - - format.pad = fse->pad; - format.format.code = fse->code; - format.format.width = -1; - format.format.height = -1; - format.which = fse->which; - isif_try_format(isif, cfg, &format); - fse->max_width = format.format.width; - fse->max_height = format.format.height; - - return 0; -} - -/* - * isif_enum_mbus_code() - enum mbus codes for pads - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int -isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case ISIF_PAD_SINK: - case ISIF_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(isif_fmts)) - return -EINVAL; - code->code = isif_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * isif_pad_set_selection() - set crop rectangle on pad - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * - * Return 0 on success, -EINVAL if pad is invalid - */ -static int -isif_pad_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - /* check whether it's a valid pad and target */ - if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - format = __isif_get_format(vpfe_isif, cfg, sel->pad, sel->which); - if (format == NULL) - return -EINVAL; - - /* check wether crop rect is within limits */ - if (sel->r.top < 0 || sel->r.left < 0 || - (sel->r.left + sel->r.width > - vpfe_isif->formats[ISIF_PAD_SINK].width) || - (sel->r.top + sel->r.height > - vpfe_isif->formats[ISIF_PAD_SINK].height)) { - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = format->width; - sel->r.height = format->height; - } - /* adjust the width to 16 pixel boundary */ - sel->r.width = (sel->r.width + 15) & ~0xf; - vpfe_isif->crop = sel->r; - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - isif_set_image_window(vpfe_isif); - } else { - struct v4l2_rect *rect; - - rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK); - memcpy(rect, &vpfe_isif->crop, sizeof(*rect)); - } - return 0; -} - -/* - * isif_pad_get_selection() - get crop rectangle on pad - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * - * Return 0 on success, -EINVAL if pad is invalid - */ -static int -isif_pad_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - - /* check whether it's a valid pad and target */ - if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_rect *rect; - - rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK); - memcpy(&sel->r, rect, sizeof(*rect)); - } else { - sel->r = vpfe_isif->crop; - } - - return 0; -} - -/* - * isif_init_formats() - Initialize formats on all pads - * @sd: VPFE isif V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -isif_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - struct v4l2_subdev_selection sel; - - memset(&format, 0, sizeof(format)); - format.pad = ISIF_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = MAX_WIDTH; - format.format.height = MAX_HEIGHT; - isif_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = ISIF_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = MAX_WIDTH; - format.format.height = MAX_HEIGHT; - isif_set_format(sd, fh->pad, &format); - - memset(&sel, 0, sizeof(sel)); - sel.pad = ISIF_PAD_SINK; - sel.which = V4L2_SUBDEV_FORMAT_TRY; - sel.target = V4L2_SEL_TGT_CROP; - sel.r.width = MAX_WIDTH; - sel.r.height = MAX_HEIGHT; - isif_pad_set_selection(sd, fh->pad, &sel); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = { - .ioctl = isif_ioctl, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = { - .open = isif_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = { - .s_stream = isif_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = { - .enum_mbus_code = isif_enum_mbus_code, - .enum_frame_size = isif_enum_frame_size, - .get_fmt = isif_get_format, - .set_fmt = isif_set_format, - .set_selection = isif_pad_set_selection, - .get_selection = isif_pad_get_selection, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops isif_v4l2_ops = { - .core = &isif_v4l2_core_ops, - .video = &isif_v4l2_video_ops, - .pad = &isif_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * isif_link_setup() - Setup isif connections - * @entity: isif media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int -isif_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case ISIF_PAD_SINK | 2 << 16: - /* read from decoder/sensor */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - isif->input = ISIF_INPUT_NONE; - break; - } - if (isif->input != ISIF_INPUT_NONE) - return -EBUSY; - isif->input = ISIF_INPUT_PARALLEL; - break; - - case ISIF_PAD_SOURCE: - /* write to memory */ - if (flags & MEDIA_LNK_FL_ENABLED) - isif->output = ISIF_OUTPUT_MEMORY; - else - isif->output = ISIF_OUTPUT_NONE; - break; - - case ISIF_PAD_SOURCE | 2 << 16: - if (flags & MEDIA_LNK_FL_ENABLED) - isif->output = ISIF_OUTPUT_IPIPEIF; - else - isif->output = ISIF_OUTPUT_NONE; - break; - - default: - return -EINVAL; - } - - return 0; -} -static const struct media_entity_operations isif_media_ops = { - .link_setup = isif_link_setup, -}; - -/* - * vpfe_isif_unregister_entities() - isif unregister entity - * @isif - pointer to isif subdevice structure. - */ -void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif) -{ - vpfe_video_unregister(&isif->video_out); - /* unregister subdev */ - v4l2_device_unregister_subdev(&isif->subdev); - /* cleanup entity */ - media_entity_cleanup(&isif->subdev.entity); -} - -static void isif_restore_defaults(struct vpfe_isif_device *isif) -{ - enum vpss_ccdc_source_sel source = VPSS_CCDCIN; - int i; - - memset(&isif->isif_cfg.bayer.config_params, 0, - sizeof(struct vpfe_isif_raw_config)); - - isif->isif_cfg.bayer.config_params.linearize.corr_shft = - VPFE_ISIF_NO_SHIFT; - isif->isif_cfg.bayer.config_params.linearize.scale_fact.integer = 1; - isif->isif_cfg.bayer.config_params.culling.hcpat_odd = - ISIF_CULLING_HCAPT_ODD; - isif->isif_cfg.bayer.config_params.culling.hcpat_even = - ISIF_CULLING_HCAPT_EVEN; - isif->isif_cfg.bayer.config_params.culling.vcpat = ISIF_CULLING_VCAPT; - /* Enable clock to ISIF, IPIPEIF and BL */ - vpss_enable_clock(VPSS_CCDC_CLOCK, 1); - vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); - vpss_enable_clock(VPSS_BL_CLOCK, 1); - - /* set all registers to default value */ - for (i = 0; i <= 0x1f8; i += 4) - isif_write(isif->isif_cfg.base_addr, 0, i); - /* no culling support */ - isif_write(isif->isif_cfg.base_addr, 0xffff, CULH); - isif_write(isif->isif_cfg.base_addr, 0xff, CULV); - - /* Set default offset and gain */ - isif_config_gain_offset(isif); - vpss_select_ccdc_source(source); -} - -/* - * vpfe_isif_register_entities() - isif register entity - * @isif - pointer to isif subdevice structure. - * @vdev: pointer to v4l2 device structure. - */ -int vpfe_isif_register_entities(struct vpfe_isif_device *isif, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - unsigned int flags; - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &isif->subdev); - if (ret < 0) - return ret; - - isif_restore_defaults(isif); - ret = vpfe_video_register(&isif->video_out, vdev); - if (ret) { - pr_err("Failed to register isif video out device\n"); - goto out_video_register; - } - isif->video_out.vpfe_dev = vpfe_dev; - flags = 0; - /* connect isif to video node */ - ret = media_create_pad_link(&isif->subdev.entity, 1, - &isif->video_out.video_dev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - return 0; -out_create_link: - vpfe_video_unregister(&isif->video_out); -out_video_register: - v4l2_device_unregister_subdev(&isif->subdev); - return ret; -} - -/* ------------------------------------------------------------------- - * V4L2 subdev control operations - */ - -static int vpfe_isif_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_isif_device *isif = - container_of(ctrl->handler, struct vpfe_isif_device, ctrls); - struct isif_oper_config *config = &isif->isif_cfg; - - switch (ctrl->id) { - case VPFE_CID_DPCM_PREDICTOR: - config->bayer.dpcm_predictor = ctrl->val; - break; - - case VPFE_ISIF_CID_CRGAIN: - config->isif_gain_params.cr_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CGRGAIN: - config->isif_gain_params.cgr_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CGBGAIN: - config->isif_gain_params.cgb_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CBGAIN: - config->isif_gain_params.cb_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_GAIN_OFFSET: - config->isif_gain_params.offset = ctrl->val; - break; - - default: - return -EINVAL; - } - return 0; -} - -static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = { - .s_ctrl = vpfe_isif_s_ctrl, -}; - -static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_CID_DPCM_PREDICTOR, - .name = "DPCM Predictor", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_crgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CRGAIN, - .name = "CRGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cgrgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CGRGAIN, - .name = "CGRGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cgbgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CGBGAIN, - .name = "CGBGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cbgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CBGAIN, - .name = "CBGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_gain_offset = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_GAIN_OFFSET, - .name = "Gain Offset", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static void isif_remove(struct vpfe_isif_device *isif, - struct platform_device *pdev) -{ - struct resource *res; - int i = 0; - - iounmap(isif->isif_cfg.base_addr); - iounmap(isif->isif_cfg.linear_tbl0_addr); - iounmap(isif->isif_cfg.linear_tbl1_addr); - - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (res) - release_mem_region(res->start, - resource_size(res)); - i++; - } -} - -static void isif_config_defaults(struct vpfe_isif_device *isif) -{ - isif->isif_cfg.ycbcr.v4l2_pix_fmt = V4L2_PIX_FMT_UYVY; - isif->isif_cfg.ycbcr.pix_fmt = ISIF_PIXFMT_YCBCR_8BIT; - isif->isif_cfg.ycbcr.frm_fmt = ISIF_FRMFMT_INTERLACED; - isif->isif_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY; - isif->isif_cfg.ycbcr.buf_type = ISIF_BUFTYPE_FLD_INTERLEAVED; - - isif->isif_cfg.bayer.v4l2_pix_fmt = V4L2_PIX_FMT_SGRBG10ALAW8; - isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW; - isif->isif_cfg.bayer.frm_fmt = ISIF_FRMFMT_PROGRESSIVE; - isif->isif_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.cfa_pat = ISIF_CFA_PAT_MOSAIC; - isif->isif_cfg.bayer.data_msb = ISIF_BIT_MSB_11; - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; -} -/* - * vpfe_isif_init() - Initialize V4L2 subdev and media entity - * @isif: VPFE isif module - * @pdev: Pointer to platform device structure. - * Return 0 on success and a negative error code on failure. - */ -int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &isif->subdev; - struct media_pad *pads = &isif->pads[0]; - struct media_entity *me = &sd->entity; - static resource_size_t res_len; - struct resource *res; - void __iomem *addr; - int status; - int i = 0; - - /* Get the ISIF base address, linearization table0 and table1 addr. */ - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) { - status = -ENOENT; - goto fail_nobase_res; - } - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) { - status = -EBUSY; - goto fail_nobase_res; - } - addr = ioremap_nocache(res->start, res_len); - if (!addr) { - status = -EBUSY; - goto fail_base_iomap; - } - switch (i) { - case 0: - /* ISIF base address */ - isif->isif_cfg.base_addr = addr; - break; - case 1: - /* ISIF linear tbl0 address */ - isif->isif_cfg.linear_tbl0_addr = addr; - break; - default: - /* ISIF linear tbl0 address */ - isif->isif_cfg.linear_tbl1_addr = addr; - break; - } - i++; - } - davinci_cfg_reg(DM365_VIN_CAM_WEN); - davinci_cfg_reg(DM365_VIN_CAM_VD); - davinci_cfg_reg(DM365_VIN_CAM_HD); - davinci_cfg_reg(DM365_VIN_YIN4_7_EN); - davinci_cfg_reg(DM365_VIN_YIN0_3_EN); - - /* queue ops */ - isif->video_out.ops = &isif_video_ops; - v4l2_subdev_init(sd, &isif_v4l2_ops); - sd->internal_ops = &isif_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI ISIF", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, isif); - sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[ISIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[ISIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - isif->input = ISIF_INPUT_NONE; - isif->output = ISIF_OUTPUT_NONE; - me->ops = &isif_media_ops; - status = media_entity_pads_init(me, ISIF_PADS_NUM, pads); - if (status) - goto isif_fail; - isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - status = vpfe_video_init(&isif->video_out, "ISIF"); - if (status) { - pr_err("Failed to init isif-out video device\n"); - goto isif_fail; - } - v4l2_ctrl_handler_init(&isif->ctrls, 6); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_crgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgrgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgbgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cbgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_gain_offset, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_dpcm_pred, NULL); - - v4l2_ctrl_handler_setup(&isif->ctrls); - sd->ctrl_handler = &isif->ctrls; - isif_config_defaults(isif); - return 0; -fail_base_iomap: - release_mem_region(res->start, res_len); - i--; -fail_nobase_res: - if (isif->isif_cfg.base_addr) - iounmap(isif->isif_cfg.base_addr); - if (isif->isif_cfg.linear_tbl0_addr) - iounmap(isif->isif_cfg.linear_tbl0_addr); - - while (i >= 0) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - release_mem_region(res->start, res_len); - i--; - } - return status; -isif_fail: - v4l2_ctrl_handler_free(&isif->ctrls); - isif_remove(isif, pdev); - return status; -} - -/* - * vpfe_isif_cleanup - isif module cleanup - * @isif: pointer to isif subdevice - * @dev: pointer to platform device structure - */ -void -vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev) -{ - isif_remove(isif, pdev); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.h b/drivers/staging/media/davinci_vpfe/dm365_isif.h deleted file mode 100644 index 0e1fe472fb2b..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.h +++ /dev/null @@ -1,200 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_ISIF_H -#define _DAVINCI_VPFE_DM365_ISIF_H - -#include - -#include - -#include -#include -#include - -#include "davinci_vpfe_user.h" -#include "dm365_isif_regs.h" -#include "vpfe_video.h" - -#define ISIF_CULLING_HCAPT_ODD 0xff -#define ISIF_CULLING_HCAPT_EVEN 0xff -#define ISIF_CULLING_VCAPT 0xff - -#define ISIF_CADU_BITS 0x07ff -#define ISIF_CADL_BITS 0x0ffff - -enum isif_pixfmt { - ISIF_PIXFMT_RAW = 0, - ISIF_PIXFMT_YCBCR_16BIT = 1, - ISIF_PIXFMT_YCBCR_8BIT = 2, -}; - -enum isif_frmfmt { - ISIF_FRMFMT_PROGRESSIVE = 0, - ISIF_FRMFMT_INTERLACED = 1, -}; - -/* PIXEL ORDER IN MEMORY from LSB to MSB */ -/* only applicable for 8-bit input mode */ -enum isif_pixorder { - ISIF_PIXORDER_YCBYCR = 0, - ISIF_PIXORDER_CBYCRY = 1, -}; - -enum isif_buftype { - ISIF_BUFTYPE_FLD_INTERLEAVED = 0, - ISIF_BUFTYPE_FLD_SEPARATED = 1, -}; - -struct isif_ycbcr_config { - /* v4l2 pixel format */ - unsigned long v4l2_pix_fmt; - /* isif pixel format */ - enum isif_pixfmt pix_fmt; - /* isif frame format */ - enum isif_frmfmt frm_fmt; - /* isif crop window */ - struct v4l2_rect win; - /* field polarity */ - enum vpfe_pin_pol fid_pol; - /* interface VD polarity */ - enum vpfe_pin_pol vd_pol; - /* interface HD polarity */ - enum vpfe_pin_pol hd_pol; - /* isif pix order. Only used for ycbcr capture */ - enum isif_pixorder pix_order; - /* isif buffer type. Only used for ycbcr capture */ - enum isif_buftype buf_type; -}; - -enum isif_cfa_pattern { - ISIF_CFA_PAT_MOSAIC = 0, - ISIF_CFA_PAT_STRIPE = 1, -}; - -enum isif_data_msb { - /* MSB b15 */ - ISIF_BIT_MSB_15 = 0, - /* MSB b14 */ - ISIF_BIT_MSB_14 = 1, - /* MSB b13 */ - ISIF_BIT_MSB_13 = 2, - /* MSB b12 */ - ISIF_BIT_MSB_12 = 3, - /* MSB b11 */ - ISIF_BIT_MSB_11 = 4, - /* MSB b10 */ - ISIF_BIT_MSB_10 = 5, - /* MSB b9 */ - ISIF_BIT_MSB_9 = 6, - /* MSB b8 */ - ISIF_BIT_MSB_8 = 7, - /* MSB b7 */ - ISIF_BIT_MSB_7 = 8, -}; - -struct isif_params_raw { - /* v4l2 pixel format */ - unsigned long v4l2_pix_fmt; - /* isif pixel format */ - enum isif_pixfmt pix_fmt; - /* isif frame format */ - enum isif_frmfmt frm_fmt; - /* video window */ - struct v4l2_rect win; - /* field polarity */ - enum vpfe_pin_pol fid_pol; - /* interface VD polarity */ - enum vpfe_pin_pol vd_pol; - /* interface HD polarity */ - enum vpfe_pin_pol hd_pol; - /* buffer type. Applicable for interlaced mode */ - enum isif_buftype buf_type; - /* cfa pattern */ - enum isif_cfa_pattern cfa_pat; - /* Data MSB position */ - enum isif_data_msb data_msb; - /* Enable horizontal flip */ - unsigned char horz_flip_en; - /* Enable image invert vertically */ - unsigned char image_invert_en; - unsigned char dpcm_predictor; - struct vpfe_isif_raw_config config_params; -}; - -enum isif_data_pack { - ISIF_PACK_16BIT = 0, - ISIF_PACK_12BIT = 1, - ISIF_PACK_8BIT = 2, -}; - -struct isif_gain_values { - unsigned int cr_gain; - unsigned int cgr_gain; - unsigned int cgb_gain; - unsigned int cb_gain; - unsigned int offset; -}; - -struct isif_oper_config { - struct isif_ycbcr_config ycbcr; - struct isif_params_raw bayer; - enum isif_data_pack data_pack; - struct isif_gain_values isif_gain_params; - void __iomem *base_addr; - void __iomem *linear_tbl0_addr; - void __iomem *linear_tbl1_addr; -}; - -#define ISIF_PAD_SINK 0 -#define ISIF_PAD_SOURCE 1 - -#define ISIF_PADS_NUM 2 - -enum isif_input_entity { - ISIF_INPUT_NONE = 0, - ISIF_INPUT_PARALLEL = 1, -}; - -#define ISIF_OUTPUT_NONE (0) -#define ISIF_OUTPUT_MEMORY (1 << 0) -#define ISIF_OUTPUT_IPIPEIF (1 << 1) - -struct vpfe_isif_device { - struct v4l2_subdev subdev; - struct media_pad pads[ISIF_PADS_NUM]; - struct v4l2_mbus_framefmt formats[ISIF_PADS_NUM]; - enum isif_input_entity input; - unsigned int output; - struct v4l2_ctrl_handler ctrls; - struct v4l2_rect crop; - struct isif_oper_config isif_cfg; - struct vpfe_video_device video_out; -}; - -enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev); -void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif); -int vpfe_isif_register_entities(struct vpfe_isif_device *isif, - struct v4l2_device *dev); -int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev); -void vpfe_isif_cleanup(struct vpfe_isif_device *vpfe_isif, - struct platform_device *pdev); -void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif); -void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif); - -#endif /* _DAVINCI_VPFE_DM365_ISIF_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h b/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h deleted file mode 100644 index 6695680817b9..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h +++ /dev/null @@ -1,291 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_ISIF_REGS_H -#define _DAVINCI_VPFE_DM365_ISIF_REGS_H - -/* ISIF registers relative offsets */ -#define SYNCEN 0x00 -#define MODESET 0x04 -#define HDW 0x08 -#define VDW 0x0c -#define PPLN 0x10 -#define LPFR 0x14 -#define SPH 0x18 -#define LNH 0x1c -#define SLV0 0x20 -#define SLV1 0x24 -#define LNV 0x28 -#define CULH 0x2c -#define CULV 0x30 -#define HSIZE 0x34 -#define SDOFST 0x38 -#define CADU 0x3c -#define CADL 0x40 -#define LINCFG0 0x44 -#define LINCFG1 0x48 -#define CCOLP 0x4c -#define CRGAIN 0x50 -#define CGRGAIN 0x54 -#define CGBGAIN 0x58 -#define CBGAIN 0x5c -#define COFSTA 0x60 -#define FLSHCFG0 0x64 -#define FLSHCFG1 0x68 -#define FLSHCFG2 0x6c -#define VDINT0 0x70 -#define VDINT1 0x74 -#define VDINT2 0x78 -#define MISC 0x7c -#define CGAMMAWD 0x80 -#define REC656IF 0x84 -#define CCDCFG 0x88 -/***************************************************** - * Defect Correction registers - *****************************************************/ -#define DFCCTL 0x8c -#define VDFSATLV 0x90 -#define DFCMEMCTL 0x94 -#define DFCMEM0 0x98 -#define DFCMEM1 0x9c -#define DFCMEM2 0xa0 -#define DFCMEM3 0xa4 -#define DFCMEM4 0xa8 -/**************************************************** - * Black Clamp registers - ****************************************************/ -#define CLAMPCFG 0xac -#define CLDCOFST 0xb0 -#define CLSV 0xb4 -#define CLHWIN0 0xb8 -#define CLHWIN1 0xbc -#define CLHWIN2 0xc0 -#define CLVRV 0xc4 -#define CLVWIN0 0xc8 -#define CLVWIN1 0xcc -#define CLVWIN2 0xd0 -#define CLVWIN3 0xd4 -/**************************************************** - * Lense Shading Correction - ****************************************************/ -#define DATAHOFST 0xd8 -#define DATAVOFST 0xdc -#define LSCHVAL 0xe0 -#define LSCVVAL 0xe4 -#define TWODLSCCFG 0xe8 -#define TWODLSCOFST 0xec -#define TWODLSCINI 0xf0 -#define TWODLSCGRBU 0xf4 -#define TWODLSCGRBL 0xf8 -#define TWODLSCGROF 0xfc -#define TWODLSCORBU 0x100 -#define TWODLSCORBL 0x104 -#define TWODLSCOROF 0x108 -#define TWODLSCIRQEN 0x10c -#define TWODLSCIRQST 0x110 -/**************************************************** - * Data formatter - ****************************************************/ -#define FMTCFG 0x114 -#define FMTPLEN 0x118 -#define FMTSPH 0x11c -#define FMTLNH 0x120 -#define FMTSLV 0x124 -#define FMTLNV 0x128 -#define FMTRLEN 0x12c -#define FMTHCNT 0x130 -#define FMTAPTR_BASE 0x134 -/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */ -#define FMTAPTR(i) (FMTAPTR_BASE + (i * 4)) -#define FMTPGMVF0 0x174 -#define FMTPGMVF1 0x178 -#define FMTPGMAPU0 0x17c -#define FMTPGMAPU1 0x180 -#define FMTPGMAPS0 0x184 -#define FMTPGMAPS1 0x188 -#define FMTPGMAPS2 0x18c -#define FMTPGMAPS3 0x190 -#define FMTPGMAPS4 0x194 -#define FMTPGMAPS5 0x198 -#define FMTPGMAPS6 0x19c -#define FMTPGMAPS7 0x1a0 -/************************************************ - * Color Space Converter - ************************************************/ -#define CSCCTL 0x1a4 -#define CSCM0 0x1a8 -#define CSCM1 0x1ac -#define CSCM2 0x1b0 -#define CSCM3 0x1b4 -#define CSCM4 0x1b8 -#define CSCM5 0x1bc -#define CSCM6 0x1c0 -#define CSCM7 0x1c4 -#define OBWIN0 0x1c8 -#define OBWIN1 0x1cc -#define OBWIN2 0x1d0 -#define OBWIN3 0x1d4 -#define OBVAL0 0x1d8 -#define OBVAL1 0x1dc -#define OBVAL2 0x1e0 -#define OBVAL3 0x1e4 -#define OBVAL4 0x1e8 -#define OBVAL5 0x1ec -#define OBVAL6 0x1f0 -#define OBVAL7 0x1f4 -#define CLKCTL 0x1f8 - -/* Masks & Shifts below */ -#define START_PX_HOR_MASK 0x7fff -#define NUM_PX_HOR_MASK 0x7fff -#define START_VER_ONE_MASK 0x7fff -#define START_VER_TWO_MASK 0x7fff -#define NUM_LINES_VER 0x7fff - -/* gain - offset masks */ -#define OFFSET_MASK 0xfff -#define GAIN_SDRAM_EN_SHIFT 12 -#define GAIN_IPIPE_EN_SHIFT 13 -#define GAIN_H3A_EN_SHIFT 14 -#define OFST_SDRAM_EN_SHIFT 8 -#define OFST_IPIPE_EN_SHIFT 9 -#define OFST_H3A_EN_SHIFT 10 -#define GAIN_OFFSET_EN_MASK 0x7700 - -/* Culling */ -#define CULL_PAT_EVEN_LINE_SHIFT 8 - -/* CCDCFG register */ -#define ISIF_YCINSWP_RAW (0x00 << 4) -#define ISIF_YCINSWP_YCBCR (0x01 << 4) -#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6) -#define ISIF_CCDCFG_WENLOG_AND (0x00 << 8) -#define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9) -#define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10) -#define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15) -#define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15) -#define ISIF_DATA_PACK_MASK 0x03 -#define ISIF_PIX_ORDER_SHIFT 11 -#define ISIF_PIX_ORDER_MASK 0x01 -#define ISIF_BW656_ENABLE (0x01 << 5) - -/* MODESET registers */ -#define ISIF_VDHDOUT_INPUT (0x00 << 0) -#define ISIF_INPUT_MASK 0x03 -#define ISIF_INPUT_SHIFT 12 -#define ISIF_FID_POL_MASK 0x01 -#define ISIF_FID_POL_SHIFT 4 -#define ISIF_HD_POL_MASK 0x01 -#define ISIF_HD_POL_SHIFT 3 -#define ISIF_VD_POL_MASK 0x01 -#define ISIF_VD_POL_SHIFT 2 -#define ISIF_DATAPOL_NORMAL 0x00 -#define ISIF_DATAPOL_MASK 0x01 -#define ISIF_DATAPOL_SHIFT 6 -#define ISIF_EXWEN_DISABLE 0x00 -#define ISIF_EXWEN_MASK 0x01 -#define ISIF_EXWEN_SHIFT 5 -#define ISIF_FRM_FMT_MASK 0x01 -#define ISIF_FRM_FMT_SHIFT 7 -#define ISIF_DATASFT_MASK 0x07 -#define ISIF_DATASFT_SHIFT 8 -#define ISIF_LPF_SHIFT 14 -#define ISIF_LPF_MASK 0x1 - -/* GAMMAWD registers */ -#define ISIF_ALAW_GAMA_WD_MASK 0xf -#define ISIF_ALAW_GAMA_WD_SHIFT 1 -#define ISIF_ALAW_ENABLE 0x01 -#define ISIF_GAMMAWD_CFA_MASK 0x01 -#define ISIF_GAMMAWD_CFA_SHIFT 5 - -/* HSIZE registers */ -#define ISIF_HSIZE_FLIP_MASK 0x01 -#define ISIF_HSIZE_FLIP_SHIFT 12 -#define ISIF_LINEOFST_MASK 0xfff - -/* MISC registers */ -#define ISIF_DPCM_EN_SHIFT 12 -#define ISIF_DPCM_PREDICTOR_SHIFT 13 -#define ISIF_DPCM_PREDICTOR_MASK 1 - -/* Black clamp related */ -#define ISIF_BC_DCOFFSET_MASK 0x1fff -#define ISIF_BC_MODE_COLOR_MASK 1 -#define ISIF_BC_MODE_COLOR_SHIFT 4 -#define ISIF_HORZ_BC_MODE_MASK 3 -#define ISIF_HORZ_BC_MODE_SHIFT 1 -#define ISIF_HORZ_BC_WIN_COUNT_MASK 0x1f -#define ISIF_HORZ_BC_WIN_SEL_SHIFT 5 -#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6 -#define ISIF_HORZ_BC_WIN_H_SIZE_MASK 3 -#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8 -#define ISIF_HORZ_BC_WIN_V_SIZE_MASK 3 -#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12 -#define ISIF_HORZ_BC_WIN_START_H_MASK 0x1fff -#define ISIF_HORZ_BC_WIN_START_V_MASK 0x1fff -#define ISIF_VERT_BC_OB_H_SZ_MASK 7 -#define ISIF_VERT_BC_RST_VAL_SEL_MASK 3 -#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4 -#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8 -#define ISIF_VERT_BC_OB_START_HORZ_MASK 0x1fff -#define ISIF_VERT_BC_OB_START_VERT_MASK 0x1fff -#define ISIF_VERT_BC_OB_VERT_SZ_MASK 0x1fff -#define ISIF_VERT_BC_RST_VAL_MASK 0xfff -#define ISIF_BC_VERT_START_SUB_V_MASK 0x1fff - -/* VDFC registers */ -#define ISIF_VDFC_EN_SHIFT 4 -#define ISIF_VDFC_CORR_MOD_MASK 3 -#define ISIF_VDFC_CORR_MOD_SHIFT 5 -#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7 -#define ISIF_VDFC_LEVEL_SHFT_MASK 7 -#define ISIF_VDFC_LEVEL_SHFT_SHIFT 8 -#define ISIF_VDFC_SAT_LEVEL_MASK 0xfff -#define ISIF_VDFC_POS_MASK 0x1fff -#define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2 - -/* CSC registers */ -#define ISIF_CSC_COEF_INTEG_MASK 7 -#define ISIF_CSC_COEF_DECIMAL_MASK 0x1f -#define ISIF_CSC_COEF_INTEG_SHIFT 5 -#define ISIF_CSCM_MSB_SHIFT 8 -#define ISIF_DF_CSC_SPH_MASK 0x1fff -#define ISIF_DF_CSC_LNH_MASK 0x1fff -#define ISIF_DF_CSC_SLV_MASK 0x1fff -#define ISIF_DF_CSC_LNV_MASK 0x1fff -#define ISIF_DF_NUMLINES 0x7fff -#define ISIF_DF_NUMPIX 0x1fff - -/* Offsets for LSC/DFC/Gain */ -#define ISIF_DATA_H_OFFSET_MASK 0x1fff -#define ISIF_DATA_V_OFFSET_MASK 0x1fff - -/* Linearization */ -#define ISIF_LIN_CORRSFT_MASK 7 -#define ISIF_LIN_CORRSFT_SHIFT 4 -#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10 -#define ISIF_LIN_SCALE_FACT_DECIMAL_MASK 0x3ff -#define ISIF_LIN_ENTRY_MASK 0x3ff - -/* masks and shifts*/ -#define ISIF_SYNCEN_VDHDEN_MASK (1 << 0) -#define ISIF_SYNCEN_WEN_MASK (1 << 1) -#define ISIF_SYNCEN_WEN_SHIFT 1 - -#endif /* _DAVINCI_VPFE_DM365_ISIF_REGS_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c deleted file mode 100644 index 7adf1fae43f6..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ /dev/null @@ -1,1995 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - * - * - * Resizer allows upscaling or downscaling a image to a desired - * resolution. There are 2 resizer modules. both operating on the - * same input image, but can have different output resolution. - */ - -#include "dm365_ipipe_hw.h" -#include "dm365_resizer.h" - -#define MIN_IN_WIDTH 32 -#define MIN_IN_HEIGHT 32 -#define MAX_IN_WIDTH 4095 -#define MAX_IN_HEIGHT 4095 -#define MIN_OUT_WIDTH 16 -#define MIN_OUT_HEIGHT 2 - -static const unsigned int resizer_input_formats[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_SGRBG12_1X12, -}; - -static const unsigned int resizer_output_formats[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SGRBG12_1X12, -}; - -/* resizer_calculate_line_length() - This function calculates the line length of - * various image planes at the input and - * output. - */ -static void -resizer_calculate_line_length(u32 pix, int width, int height, - int *line_len, int *line_len_c) -{ - *line_len = 0; - *line_len_c = 0; - - if (pix == MEDIA_BUS_FMT_UYVY8_2X8 || - pix == MEDIA_BUS_FMT_SGRBG12_1X12) { - *line_len = width << 1; - } else { - *line_len = width; - *line_len_c = width; - } - - /* adjust the line len to be a multiple of 32 */ - *line_len += 31; - *line_len &= ~0x1f; - *line_len_c += 31; - *line_len_c &= ~0x1f; -} - -static inline int -resizer_validate_output_image_format(struct device *dev, - struct v4l2_mbus_framefmt *format, - int *in_line_len, int *in_line_len_c) -{ - if (format->code != MEDIA_BUS_FMT_UYVY8_2X8 && - format->code != MEDIA_BUS_FMT_Y8_1X8 && - format->code != MEDIA_BUS_FMT_UV8_1X8 && - format->code != MEDIA_BUS_FMT_YDYUYDYV8_1X16 && - format->code != MEDIA_BUS_FMT_SGRBG12_1X12) { - dev_err(dev, "Invalid Mbus format, %d\n", format->code); - return -EINVAL; - } - if (!format->width || !format->height) { - dev_err(dev, "invalid width or height\n"); - return -EINVAL; - } - resizer_calculate_line_length(format->code, format->width, - format->height, in_line_len, in_line_len_c); - return 0; -} - -static void -resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass) -{ - struct resizer_params *param = &resizer->config; - - param->rsz_rsc_param[RSZ_A].cen = DISABLE; - param->rsz_rsc_param[RSZ_A].yen = DISABLE; - param->rsz_rsc_param[RSZ_A].v_phs_y = 0; - param->rsz_rsc_param[RSZ_A].v_phs_c = 0; - param->rsz_rsc_param[RSZ_A].v_dif = 256; - param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0; - param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0; - param->rsz_rsc_param[RSZ_A].h_phs = 0; - param->rsz_rsc_param[RSZ_A].h_dif = 256; - param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0; - param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0; - param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE; - param->rsz2rgb[RSZ_A].rgb_en = DISABLE; - param->rsz_en[RSZ_A] = ENABLE; - param->rsz_en[RSZ_B] = DISABLE; - if (bypass) { - param->rsz_rsc_param[RSZ_A].i_vps = 0; - param->rsz_rsc_param[RSZ_A].i_hps = 0; - /* Raw Bypass */ - param->rsz_common.passthrough = BYPASS_ON; - } -} - -static void -configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index, - void *output_spec, unsigned char partial, - unsigned int flag) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *outformat; - struct vpfe_rsz_output_spec *output; - - if (index == RSZ_A && - resizer->resizer_a.output == RESIZER_OUTPUT_NONE) { - param->rsz_en[index] = DISABLE; - return; - } - if (index == RSZ_B && - resizer->resizer_b.output == RESIZER_OUTPUT_NONE) { - param->rsz_en[index] = DISABLE; - return; - } - output = output_spec; - param->rsz_en[index] = ENABLE; - if (partial) { - param->rsz_rsc_param[index].h_flip = output->h_flip; - param->rsz_rsc_param[index].v_flip = output->v_flip; - param->rsz_rsc_param[index].v_typ_y = output->v_typ_y; - param->rsz_rsc_param[index].v_typ_c = output->v_typ_c; - param->rsz_rsc_param[index].v_lpf_int_y = - output->v_lpf_int_y; - param->rsz_rsc_param[index].v_lpf_int_c = - output->v_lpf_int_c; - param->rsz_rsc_param[index].h_typ_y = output->h_typ_y; - param->rsz_rsc_param[index].h_typ_c = output->h_typ_c; - param->rsz_rsc_param[index].h_lpf_int_y = - output->h_lpf_int_y; - param->rsz_rsc_param[index].h_lpf_int_c = - output->h_lpf_int_c; - param->rsz_rsc_param[index].dscale_en = - output->en_down_scale; - param->rsz_rsc_param[index].h_dscale_ave_sz = - output->h_dscale_ave_sz; - param->rsz_rsc_param[index].v_dscale_ave_sz = - output->v_dscale_ave_sz; - param->ext_mem_param[index].user_y_ofst = - (output->user_y_ofst + 31) & ~0x1f; - param->ext_mem_param[index].user_c_ofst = - (output->user_c_ofst + 31) & ~0x1f; - return; - } - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - param->rsz_rsc_param[index].o_vsz = outformat->height - 1; - param->rsz_rsc_param[index].o_hsz = outformat->width - 1; - param->ext_mem_param[index].rsz_sdr_ptr_s_y = output->vst_y; - param->ext_mem_param[index].rsz_sdr_ptr_e_y = outformat->height; - param->ext_mem_param[index].rsz_sdr_ptr_s_c = output->vst_c; - param->ext_mem_param[index].rsz_sdr_ptr_e_c = outformat->height; - - if (!flag) - return; - /* update common parameters */ - param->rsz_rsc_param[index].h_flip = output->h_flip; - param->rsz_rsc_param[index].v_flip = output->v_flip; - param->rsz_rsc_param[index].v_typ_y = output->v_typ_y; - param->rsz_rsc_param[index].v_typ_c = output->v_typ_c; - param->rsz_rsc_param[index].v_lpf_int_y = output->v_lpf_int_y; - param->rsz_rsc_param[index].v_lpf_int_c = output->v_lpf_int_c; - param->rsz_rsc_param[index].h_typ_y = output->h_typ_y; - param->rsz_rsc_param[index].h_typ_c = output->h_typ_c; - param->rsz_rsc_param[index].h_lpf_int_y = output->h_lpf_int_y; - param->rsz_rsc_param[index].h_lpf_int_c = output->h_lpf_int_c; - param->rsz_rsc_param[index].dscale_en = output->en_down_scale; - param->rsz_rsc_param[index].h_dscale_ave_sz = output->h_dscale_ave_sz; - param->rsz_rsc_param[index].v_dscale_ave_sz = output->h_dscale_ave_sz; - param->ext_mem_param[index].user_y_ofst = - (output->user_y_ofst + 31) & ~0x1f; - param->ext_mem_param[index].user_c_ofst = - (output->user_c_ofst + 31) & ~0x1f; -} - -/* - * resizer_calculate_resize_ratios() - Calculates resize ratio for resizer - * A or B. This is called after setting - * the input size or output size. - * @resizer: Pointer to VPFE resizer subdevice. - * @index: index RSZ_A-resizer-A RSZ_B-resizer-B. - */ -static void -resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *informat, *outformat; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - if (outformat->field != V4L2_FIELD_INTERLACED) - param->rsz_rsc_param[index].v_dif = - ((informat->height) * 256) / (outformat->height); - else - param->rsz_rsc_param[index].v_dif = - ((informat->height >> 1) * 256) / (outformat->height); - param->rsz_rsc_param[index].h_dif = - ((informat->width) * 256) / (outformat->width); -} - -static void resizer_enable_422_420_conversion(struct resizer_params *param, - int index, bool en) -{ - param->rsz_rsc_param[index].cen = en; - param->rsz_rsc_param[index].yen = en; -} - -/* resizer_calculate_sdram_offsets() - This function calculates the offsets from - * start of buffer for the C plane when - * output format is YUV420SP. It also - * calculates the offsets from the start of - * the buffer when the image is flipped - * vertically or horizontally for ycbcr/y/c - * planes. - * @resizer: Pointer to resizer subdevice. - * @index: index RSZ_A-resizer-A RSZ_B-resizer-B. - */ -static int -resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *outformat; - int bytesperpixel = 2; - int image_height; - int image_width; - int yuv_420 = 0; - int offset = 0; - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - image_height = outformat->height + 1; - image_width = outformat->width + 1; - param->ext_mem_param[index].c_offset = 0; - param->ext_mem_param[index].flip_ofst_y = 0; - param->ext_mem_param[index].flip_ofst_c = 0; - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) { - /* YUV 420 */ - yuv_420 = 1; - bytesperpixel = 1; - } - - if (param->rsz_rsc_param[index].h_flip) - /* width * bytesperpixel - 1 */ - offset = (image_width * bytesperpixel) - 1; - if (param->rsz_rsc_param[index].v_flip) - offset += (image_height - 1) * - param->ext_mem_param[index].rsz_sdr_oft_y; - param->ext_mem_param[index].flip_ofst_y = offset; - if (!yuv_420) - return 0; - offset = 0; - /* half height for c-plane */ - if (param->rsz_rsc_param[index].h_flip) - /* width * bytesperpixel - 1 */ - offset = image_width - 1; - if (param->rsz_rsc_param[index].v_flip) - offset += (((image_height >> 1) - 1) * - param->ext_mem_param[index].rsz_sdr_oft_c); - param->ext_mem_param[index].flip_ofst_c = offset; - param->ext_mem_param[index].c_offset = - param->ext_mem_param[index].rsz_sdr_oft_y * image_height; - return 0; -} - -static int resizer_configure_output_win(struct vpfe_resizer_device *resizer) -{ - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_output_spec output_specs; - struct v4l2_mbus_framefmt *outformat; - int line_len_c; - int line_len; - int ret; - - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - - memset(&output_specs, 0x0, sizeof(struct vpfe_rsz_output_spec)); - output_specs.vst_y = param->user_config.vst; - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - output_specs.vst_c = param->user_config.vst; - - configure_resizer_out_params(resizer, RSZ_A, &output_specs, 0, 0); - resizer_calculate_line_length(outformat->code, - param->rsz_rsc_param[0].o_hsz + 1, - param->rsz_rsc_param[0].o_vsz + 1, - &line_len, &line_len_c); - param->ext_mem_param[0].rsz_sdr_oft_y = line_len; - param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c; - resizer_calculate_resize_ratios(resizer, RSZ_A); - if (param->rsz_en[RSZ_B]) - resizer_calculate_resize_ratios(resizer, RSZ_B); - - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, RSZ_A, ENABLE); - else - resizer_enable_422_420_conversion(param, RSZ_A, DISABLE); - - ret = resizer_calculate_sdram_offsets(resizer, RSZ_A); - if (!ret && param->rsz_en[RSZ_B]) - ret = resizer_calculate_sdram_offsets(resizer, RSZ_B); - - if (ret) - pr_err("Error in calculating sdram offsets\n"); - return ret; -} - -static int -resizer_calculate_down_scale_f_div_param(struct device *dev, - int input_width, int output_width, - struct resizer_scale_param *param) -{ - /* rsz = R, input_width = H, output width = h in the equation */ - unsigned int two_power; - unsigned int upper_h1; - unsigned int upper_h2; - unsigned int val1; - unsigned int val; - unsigned int rsz; - unsigned int h1; - unsigned int h2; - unsigned int o; - unsigned int n; - - upper_h1 = input_width >> 1; - n = param->h_dscale_ave_sz; - /* 2 ^ (scale+1) */ - two_power = 1 << (n + 1); - upper_h1 = (upper_h1 >> (n + 1)) << (n + 1); - upper_h2 = input_width - upper_h1; - if (upper_h2 % two_power) { - dev_err(dev, "frame halves to be a multiple of 2 power n+1\n"); - return -EINVAL; - } - two_power = 1 << n; - rsz = (input_width << 8) / output_width; - val = rsz * two_power; - val = ((upper_h1 << 8) / val) + 1; - if (!(val % 2)) { - h1 = val; - } else { - val = upper_h1 << 8; - val >>= n + 1; - val -= rsz >> 1; - val /= rsz << 1; - val <<= 1; - val += 2; - h1 = val; - } - o = 10 + (two_power << 2); - if (((input_width << 7) / rsz) % 2) - o += ((DIV_ROUND_UP(rsz, 1024) << 1) << n); - h2 = output_width - h1; - /* phi */ - val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8); - /* skip */ - val1 = ((val - 1024) >> 9) << 1; - param->f_div.num_passes = MAX_PASSES; - param->f_div.pass[0].o_hsz = h1 - 1; - param->f_div.pass[0].i_hps = 0; - param->f_div.pass[0].h_phs = 0; - param->f_div.pass[0].src_hps = 0; - param->f_div.pass[0].src_hsz = upper_h1 + o; - param->f_div.pass[1].o_hsz = h2 - 1; - param->f_div.pass[1].i_hps = 10 + (val1 * two_power); - param->f_div.pass[1].h_phs = val - (val1 << 8); - param->f_div.pass[1].src_hps = upper_h1 - o; - param->f_div.pass[1].src_hsz = upper_h2 + o; - - return 0; -} - -static int -resizer_configure_common_in_params(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_config_params *user_config; - struct v4l2_mbus_framefmt *informat; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - user_config = &resizer->config.user_config; - param->rsz_common.vps = param->user_config.vst; - param->rsz_common.hps = param->user_config.hst; - - if (vpfe_ipipeif_decimation_enabled(vpfe_dev)) - param->rsz_common.hsz = ((informat->width - 1) * - IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev); - else - param->rsz_common.hsz = informat->width - 1; - - if (informat->field == V4L2_FIELD_INTERLACED) - param->rsz_common.vsz = (informat->height - 1) >> 1; - else - param->rsz_common.vsz = informat->height - 1; - - param->rsz_common.raw_flip = 0; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF) - param->rsz_common.source = IPIPEIF_DATA; - else - param->rsz_common.source = IPIPE_DATA; - - switch (informat->code) { - case MEDIA_BUS_FMT_UYVY8_2X8: - param->rsz_common.src_img_fmt = RSZ_IMG_422; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_Y8_1X8: - param->rsz_common.src_img_fmt = RSZ_IMG_420; - /* Select y */ - param->rsz_common.y_c = 0; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_UV8_1X8: - param->rsz_common.src_img_fmt = RSZ_IMG_420; - /* Select y */ - param->rsz_common.y_c = 1; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - param->rsz_common.raw_flip = 1; - break; - - default: - param->rsz_common.src_img_fmt = RSZ_IMG_422; - param->rsz_common.source = IPIPE_DATA; - } - - param->rsz_common.yuv_y_min = user_config->yuv_y_min; - param->rsz_common.yuv_y_max = user_config->yuv_y_max; - param->rsz_common.yuv_c_min = user_config->yuv_c_min; - param->rsz_common.yuv_c_max = user_config->yuv_c_max; - param->rsz_common.out_chr_pos = user_config->out_chr_pos; - param->rsz_common.rsz_seq_crv = user_config->chroma_sample_even; - - return 0; -} -static int -resizer_configure_in_continuous_mode(struct vpfe_resizer_device *resizer) -{ - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_config_params *cont_config; - int line_len_c; - int line_len; - int ret; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY) { - dev_err(dev, "enable resizer - Resizer-A\n"); - return -EINVAL; - } - - cont_config = &resizer->config.user_config; - param->rsz_en[RSZ_A] = ENABLE; - configure_resizer_out_params(resizer, RSZ_A, - &cont_config->output1, 1, 0); - param->rsz_en[RSZ_B] = DISABLE; - param->oper_mode = RESIZER_MODE_CONTINUOUS; - - if (resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) { - struct v4l2_mbus_framefmt *outformat2; - - param->rsz_en[RSZ_B] = ENABLE; - outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - ret = resizer_validate_output_image_format(dev, outformat2, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_B, - &cont_config->output2, 0, 1); - if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_B, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_B, DISABLE); - } - resizer_configure_common_in_params(resizer); - ret = resizer_configure_output_win(resizer); - if (ret) - return ret; - - param->rsz_common.passthrough = cont_config->bypass; - if (cont_config->bypass) - resizer_configure_passthru(resizer, 1); - - return 0; -} - -static inline int -resizer_validate_input_image_format(struct device *dev, - u32 pix, - int width, int height, int *line_len) -{ - int val; - - if (pix != MEDIA_BUS_FMT_UYVY8_2X8 && - pix != MEDIA_BUS_FMT_Y8_1X8 && - pix != MEDIA_BUS_FMT_UV8_1X8 && - pix != MEDIA_BUS_FMT_SGRBG12_1X12) { - dev_err(dev, - "resizer validate output: pix format not supported, %d\n", pix); - return -EINVAL; - } - - if (!width || !height) { - dev_err(dev, - "resizer validate input: invalid width or height\n"); - return -EINVAL; - } - - if (pix == MEDIA_BUS_FMT_UV8_1X8) - resizer_calculate_line_length(pix, width, - height, &val, line_len); - else - resizer_calculate_line_length(pix, width, - height, line_len, &val); - - return 0; -} - -static int -resizer_validate_decimation(struct device *dev, enum ipipeif_decimation dec_en, - unsigned char rsz, unsigned char frame_div_mode_en, - int width) -{ - if (dec_en && frame_div_mode_en) { - dev_err(dev, - "dec_en & frame_div_mode_en can not enabled simultaneously\n"); - return -EINVAL; - } - - if (frame_div_mode_en) { - dev_err(dev, "frame_div_mode mode not supported\n"); - return -EINVAL; - } - - if (!dec_en) - return 0; - - if (width <= VPFE_IPIPE_MAX_INPUT_WIDTH) { - dev_err(dev, - "image width to be more than %d for decimation\n", - VPFE_IPIPE_MAX_INPUT_WIDTH); - return -EINVAL; - } - - if (rsz < IPIPEIF_RSZ_MIN || rsz > IPIPEIF_RSZ_MAX) { - dev_err(dev, "rsz range is %d to %d\n", - IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX); - return -EINVAL; - } - - return 0; -} - -/* resizer_calculate_normal_f_div_param() - Algorithm to calculate the frame - * division parameters for resizer. - * in normal mode. - */ -static int -resizer_calculate_normal_f_div_param(struct device *dev, int input_width, - int output_width, struct resizer_scale_param *param) -{ - /* rsz = R, input_width = H, output width = h in the equation */ - unsigned int val1; - unsigned int rsz; - unsigned int val; - unsigned int h1; - unsigned int h2; - unsigned int o; - - if (output_width > input_width) { - dev_err(dev, "frame div mode is used for scale down only\n"); - return -EINVAL; - } - - rsz = (input_width << 8) / output_width; - val = rsz << 1; - val = ((input_width << 8) / val) + 1; - o = 14; - if (!(val % 2)) { - h1 = val; - } else { - val = input_width << 7; - val -= rsz >> 1; - val /= rsz << 1; - val <<= 1; - val += 2; - o += (DIV_ROUND_UP(rsz, 1024) << 1); - h1 = val; - } - h2 = output_width - h1; - /* phi */ - val = (h1 * rsz) - (((input_width >> 1) - o) << 8); - /* skip */ - val1 = ((val - 1024) >> 9) << 1; - param->f_div.num_passes = MAX_PASSES; - param->f_div.pass[0].o_hsz = h1 - 1; - param->f_div.pass[0].i_hps = 0; - param->f_div.pass[0].h_phs = 0; - param->f_div.pass[0].src_hps = 0; - param->f_div.pass[0].src_hsz = (input_width >> 2) + o; - param->f_div.pass[1].o_hsz = h2 - 1; - param->f_div.pass[1].i_hps = val1; - param->f_div.pass[1].h_phs = val - (val1 << 8); - param->f_div.pass[1].src_hps = (input_width >> 2) - o; - param->f_div.pass[1].src_hsz = (input_width >> 2) + o; - - return 0; -} - -static int -resizer_configure_in_single_shot_mode(struct vpfe_resizer_device *resizer) -{ - struct vpfe_rsz_config_params *config = &resizer->config.user_config; - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct v4l2_mbus_framefmt *outformat1, *outformat2; - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *informat; - int decimation; - int line_len_c; - int line_len; - int rsz; - int ret; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - outformat1 = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - decimation = vpfe_ipipeif_decimation_enabled(vpfe_dev); - rsz = vpfe_ipipeif_get_rsz(vpfe_dev); - if (decimation && param->user_config.frame_div_mode_en) { - dev_err(dev, - "dec_en & frame_div_mode_en cannot enabled simultaneously\n"); - return -EINVAL; - } - - ret = resizer_validate_decimation(dev, decimation, rsz, - param->user_config.frame_div_mode_en, informat->width); - if (ret) - return -EINVAL; - - ret = resizer_validate_input_image_format(dev, informat->code, - informat->width, informat->height, &line_len); - if (ret) - return -EINVAL; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - param->rsz_en[RSZ_A] = ENABLE; - ret = resizer_validate_output_image_format(dev, outformat1, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_A, - ¶m->user_config.output1, 0, 1); - - if (outformat1->code == MEDIA_BUS_FMT_SGRBG12_1X12) - param->rsz_common.raw_flip = 1; - else - param->rsz_common.raw_flip = 0; - - if (outformat1->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_A, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_A, DISABLE); - } - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - param->rsz_en[RSZ_B] = ENABLE; - ret = resizer_validate_output_image_format(dev, outformat2, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_B, - ¶m->user_config.output2, 0, 1); - if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_B, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_B, DISABLE); - } - - resizer_configure_common_in_params(resizer); - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - resizer_calculate_resize_ratios(resizer, RSZ_A); - resizer_calculate_sdram_offsets(resizer, RSZ_A); - /* Overriding resize ratio calculation */ - if (informat->code == MEDIA_BUS_FMT_UV8_1X8) { - param->rsz_rsc_param[RSZ_A].v_dif = - (((informat->height + 1) * 2) * 256) / - (param->rsz_rsc_param[RSZ_A].o_vsz + 1); - } - } - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - resizer_calculate_resize_ratios(resizer, RSZ_B); - resizer_calculate_sdram_offsets(resizer, RSZ_B); - /* Overriding resize ratio calculation */ - if (informat->code == MEDIA_BUS_FMT_UV8_1X8) { - param->rsz_rsc_param[RSZ_B].v_dif = - (((informat->height + 1) * 2) * 256) / - (param->rsz_rsc_param[RSZ_B].o_vsz + 1); - } - } - if (param->user_config.frame_div_mode_en && - param->rsz_en[RSZ_A]) { - if (!param->rsz_rsc_param[RSZ_A].dscale_en) - ret = resizer_calculate_normal_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_A].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_A]); - else - ret = resizer_calculate_down_scale_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_A].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_A]); - if (ret) - return -EINVAL; - } - if (param->user_config.frame_div_mode_en && - param->rsz_en[RSZ_B]) { - if (!param->rsz_rsc_param[RSZ_B].dscale_en) - ret = resizer_calculate_normal_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_B].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_B]); - else - ret = resizer_calculate_down_scale_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_B].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_B]); - if (ret) - return -EINVAL; - } - param->rsz_common.passthrough = config->bypass; - if (config->bypass) - resizer_configure_passthru(resizer, 1); - return 0; -} - -static void -resizer_set_default_configuration(struct vpfe_resizer_device *resizer) -{ -#define WIDTH_I 640 -#define HEIGHT_I 480 -#define WIDTH_O 640 -#define HEIGHT_O 480 - const struct resizer_params rsz_default_config = { - .oper_mode = RESIZER_MODE_ONE_SHOT, - .rsz_common = { - .vsz = HEIGHT_I - 1, - .hsz = WIDTH_I - 1, - .src_img_fmt = RSZ_IMG_422, - .raw_flip = 1, /* flip preserve Raw format */ - .source = IPIPE_DATA, - .passthrough = BYPASS_OFF, - .yuv_y_max = 255, - .yuv_c_max = 255, - .rsz_seq_crv = DISABLE, - .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE, - }, - .rsz_rsc_param = { - { - .h_flip = DISABLE, - .v_flip = DISABLE, - .cen = DISABLE, - .yen = DISABLE, - .o_vsz = HEIGHT_O - 1, - .o_hsz = WIDTH_O - 1, - .v_dif = 256, - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dif = 256, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - { - .h_flip = DISABLE, - .v_flip = DISABLE, - .cen = DISABLE, - .yen = DISABLE, - .o_vsz = HEIGHT_O - 1, - .o_hsz = WIDTH_O - 1, - .v_dif = 256, - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dif = 256, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - }, - .rsz2rgb = { - { - .rgb_en = DISABLE - }, - { - .rgb_en = DISABLE - } - }, - .ext_mem_param = { - { - .rsz_sdr_oft_y = WIDTH_O << 1, - .rsz_sdr_ptr_e_y = HEIGHT_O, - .rsz_sdr_oft_c = WIDTH_O, - .rsz_sdr_ptr_e_c = HEIGHT_O >> 1, - }, - { - .rsz_sdr_oft_y = WIDTH_O << 1, - .rsz_sdr_ptr_e_y = HEIGHT_O, - .rsz_sdr_oft_c = WIDTH_O, - .rsz_sdr_ptr_e_c = HEIGHT_O, - }, - }, - .rsz_en[0] = ENABLE, - .rsz_en[1] = DISABLE, - .user_config = { - .output1 = { - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - .output2 = { - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - .yuv_y_max = 255, - .yuv_c_max = 255, - .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE, - }, - }; - memcpy(&resizer->config, &rsz_default_config, - sizeof(struct resizer_params)); -} - -/* - * resizer_set_configuration() - set resizer config - * @resizer: vpfe resizer device pointer. - * @chan_config: resizer channel configuration. - */ -static int -resizer_set_configuration(struct vpfe_resizer_device *resizer, - struct vpfe_rsz_config *chan_config) -{ - if (!chan_config->config) - resizer_set_default_configuration(resizer); - else - if (copy_from_user(&resizer->config.user_config, - (void __user *)chan_config->config, - sizeof(struct vpfe_rsz_config_params))) - return -EFAULT; - - return 0; -} - -/* - * resizer_get_configuration() - get resizer config - * @resizer: vpfe resizer device pointer. - * @channel: image processor logical channel. - * @chan_config: resizer channel configuration. - */ -static int -resizer_get_configuration(struct vpfe_resizer_device *resizer, - struct vpfe_rsz_config *chan_config) -{ - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - - if (!chan_config->config) { - dev_err(dev, "Resizer channel invalid pointer\n"); - return -EINVAL; - } - - if (copy_to_user((void __user *)chan_config->config, - (void *)&resizer->config.user_config, - sizeof(struct vpfe_rsz_config_params))) { - dev_err(dev, "resizer_get_configuration: Error in copy to user\n"); - return -EFAULT; - } - - return 0; -} - -/* - * VPFE video operations - */ - -/* - * resizer_a_video_out_queue() - RESIZER-A video out queue - * @vpfe_dev: vpfe device pointer. - * @addr: buffer address. - */ -static int resizer_a_video_out_queue(struct vpfe_device *vpfe_dev, - unsigned long addr) -{ - struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer; - - return resizer_set_outaddr(resizer->base_addr, - &resizer->config, RSZ_A, addr); -} - -/* - * resizer_b_video_out_queue() - RESIZER-B video out queue - * @vpfe_dev: vpfe device pointer. - * @addr: buffer address. - */ -static int resizer_b_video_out_queue(struct vpfe_device *vpfe_dev, - unsigned long addr) -{ - struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer; - - return resizer_set_outaddr(resizer->base_addr, - &resizer->config, RSZ_B, addr); -} - -static const struct vpfe_video_operations resizer_a_video_ops = { - .queue = resizer_a_video_out_queue, -}; - -static const struct vpfe_video_operations resizer_b_video_ops = { - .queue = resizer_b_video_out_queue, -}; - -static void resizer_enable(struct vpfe_resizer_device *resizer, int en) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - unsigned char val; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE) - return; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF && - ipipeif_sink == IPIPEIF_INPUT_MEMORY) { - do { - val = regr_rsz(resizer->base_addr, RSZ_SRC_EN); - } while (val); - - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - do { - val = regr_rsz(resizer->base_addr, RSZ_A); - } while (val); - } - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - do { - val = regr_rsz(resizer->base_addr, RSZ_B); - } while (val); - } - } - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) - rsz_enable(resizer->base_addr, RSZ_A, en); - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) - rsz_enable(resizer->base_addr, RSZ_B, en); -} - - -/* - * resizer_ss_isr() - resizer module single-shot buffer scheduling isr - * @resizer: vpfe resizer device pointer. - */ -static void resizer_ss_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_pipeline *pipe = &video_out->pipe; - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - u32 val; - - if (ipipeif_sink != IPIPEIF_INPUT_MEMORY) - return; - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - val = vpss_dma_complete_interrupt(); - if (val != 0 && val != 2) - return; - } - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - spin_lock(&video_out->dma_queue_lock); - vpfe_video_process_buffer_complete(video_out); - video_out->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_out); - spin_unlock(&video_out->dma_queue_lock); - } - - /* If resizer B is enabled */ - if (pipe->output_num > 1 && resizer->resizer_b.output == - RESIZER_OUTPUT_MEMORY) { - spin_lock(&video_out2->dma_queue_lock); - vpfe_video_process_buffer_complete(video_out2); - video_out2->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_out2); - spin_unlock(&video_out2->dma_queue_lock); - } - - /* start HW if buffers are queued */ - if (vpfe_video_is_pipe_ready(pipe) && - resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - resizer_enable(resizer, 1); - vpfe_ipipe_enable(vpfe_dev, 1); - vpfe_ipipeif_enable(vpfe_dev); - } -} - -/* - * vpfe_resizer_buffer_isr() - resizer module buffer scheduling isr - * @resizer: vpfe resizer device pointer. - */ -void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_pipeline *pipe = &resizer->resizer_a.video_out.pipe; - enum v4l2_field field; - int fid; - - if (!video_out->started) - return; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE) - return; - - field = video_out->fmt.fmt.pix.field; - if (field == V4L2_FIELD_NONE) { - /* handle progressive frame capture */ - if (video_out->cur_frm != video_out->next_frm) { - vpfe_video_process_buffer_complete(video_out); - if (pipe->output_num > 1) - vpfe_video_process_buffer_complete(video_out2); - } - - video_out->skip_frame_count--; - if (!video_out->skip_frame_count) { - video_out->skip_frame_count = - video_out->skip_frame_count_init; - rsz_src_enable(resizer->base_addr, 1); - } else { - rsz_src_enable(resizer->base_addr, 0); - } - return; - } - - /* handle interlaced frame capture */ - fid = vpfe_isif_get_fid(vpfe_dev); - - /* switch the software maintained field id */ - video_out->field_id ^= 1; - if (fid == video_out->field_id) { - /* - * we are in-sync here,continue. - * One frame is just being captured. If the - * next frame is available, release the current - * frame and move on - */ - if (fid == 0 && video_out->cur_frm != video_out->next_frm) { - vpfe_video_process_buffer_complete(video_out); - if (pipe->output_num > 1) - vpfe_video_process_buffer_complete(video_out2); - } - } else if (fid == 0) { - /* - * out of sync. Recover from any hardware out-of-sync. - * May loose one frame - */ - video_out->field_id = fid; - } -} - -/* - * vpfe_resizer_dma_isr() - resizer module dma isr - * @resizer: vpfe resizer device pointer. - */ -void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_pipeline *pipe = &video_out->pipe; - int schedule_capture = 0; - enum v4l2_field field; - int fid; - - if (!video_out->started) - return; - - if (pipe->state == VPFE_PIPELINE_STREAM_SINGLESHOT) { - resizer_ss_isr(resizer); - return; - } - - field = video_out->fmt.fmt.pix.field; - if (field == V4L2_FIELD_NONE) { - if (!list_empty(&video_out->dma_queue) && - video_out->cur_frm == video_out->next_frm) - schedule_capture = 1; - } else { - fid = vpfe_isif_get_fid(vpfe_dev); - if (fid == video_out->field_id) { - /* we are in-sync here,continue */ - if (fid == 1 && !list_empty(&video_out->dma_queue) && - video_out->cur_frm == video_out->next_frm) - schedule_capture = 1; - } - } - - if (!schedule_capture) - return; - - spin_lock(&video_out->dma_queue_lock); - vpfe_video_schedule_next_buffer(video_out); - spin_unlock(&video_out->dma_queue_lock); - if (pipe->output_num > 1) { - spin_lock(&video_out2->dma_queue_lock); - vpfe_video_schedule_next_buffer(video_out2); - spin_unlock(&video_out2->dma_queue_lock); - } -} - -/* - * V4L2 subdev operations - */ - -/* - * resizer_ioctl() - Handle resizer module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long resizer_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct vpfe_rsz_config *user_config; - int ret = -ENOIOCTLCMD; - - if (&resizer->crop_resizer.subdev != sd) - return ret; - - switch (cmd) { - case VIDIOC_VPFE_RSZ_S_CONFIG: - user_config = arg; - ret = resizer_set_configuration(resizer, user_config); - break; - - case VIDIOC_VPFE_RSZ_G_CONFIG: - user_config = arg; - if (!user_config->config) { - dev_err(dev, "error in VIDIOC_VPFE_RSZ_G_CONFIG\n"); - return -EINVAL; - } - ret = resizer_get_configuration(resizer, user_config); - break; - } - return ret; -} - -static int resizer_do_hw_setup(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; - struct resizer_params *param = &resizer->config; - int ret = 0; - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY || - resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) { - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY && - ipipeif_source == IPIPEIF_OUTPUT_RESIZER) - ret = resizer_configure_in_single_shot_mode(resizer); - else - ret = resizer_configure_in_continuous_mode(resizer); - if (ret) - return ret; - ret = config_rsz_hw(resizer, param); - } - return ret; -} - -/* - * resizer_set_stream() - Enable/Disable streaming on resizer subdev - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int resizer_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - - if (&resizer->crop_resizer.subdev != sd) - return 0; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY) - return 0; - - switch (enable) { - case 1: - if (resizer_do_hw_setup(resizer) < 0) - return -EINVAL; - resizer_enable(resizer, enable); - break; - - case 0: - resizer_enable(resizer, enable); - break; - } - - return 0; -} - -/* - * __resizer_get_format() - helper function for getting resizer format - * @sd: pointer to subdev. - * @cfg: V4L2 subdev pad config - * @pad: pad number. - * @which: wanted subdev format. - * Return wanted mbus frame format. - */ -static struct v4l2_mbus_framefmt * -__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, enum v4l2_subdev_format_whence which) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(sd, cfg, pad); - if (&resizer->crop_resizer.subdev == sd) - return &resizer->crop_resizer.formats[pad]; - if (&resizer->resizer_a.subdev == sd) - return &resizer->resizer_a.formats[pad]; - if (&resizer->resizer_b.subdev == sd) - return &resizer->resizer_b.formats[pad]; - return NULL; -} - -/* - * resizer_try_format() - Handle try format by pad subdev method - * @sd: pointer to subdev. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which: wanted subdev format. - */ -static void -resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - if ((&resizer->resizer_a.subdev == sd && pad == RESIZER_PAD_SINK) || - (&resizer->resizer_b.subdev == sd && pad == RESIZER_PAD_SINK) || - (&resizer->crop_resizer.subdev == sd && - (pad == RESIZER_CROP_PAD_SOURCE || - pad == RESIZER_CROP_PAD_SOURCE2 || pad == RESIZER_CROP_PAD_SINK))) { - for (i = 0; i < ARRAY_SIZE(resizer_input_formats); i++) { - if (fmt->code == resizer_input_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_input_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH, - MAX_IN_WIDTH); - fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT, - MAX_IN_HEIGHT); - } else if (&resizer->resizer_a.subdev == sd && - pad == RESIZER_PAD_SOURCE) { - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) { - if (fmt->code == resizer_output_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_output_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH, - max_out_width); - fmt->width &= ~15; - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT, - max_out_height); - } else if (&resizer->resizer_b.subdev == sd && - pad == RESIZER_PAD_SOURCE) { - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_B; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_B; - - for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) { - if (fmt->code == resizer_output_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_output_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH, - max_out_width); - fmt->width &= ~15; - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT, - max_out_height); - } -} - -/* - * resizer_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int resizer_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - resizer_try_format(sd, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (&resizer->crop_resizer.subdev == sd) { - if (fmt->pad == RESIZER_CROP_PAD_SINK) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE && - resizer->crop_resizer.output == RESIZER_A) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - resizer->crop_resizer. - formats[RESIZER_CROP_PAD_SOURCE2] = fmt->format; - } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE2 && - resizer->crop_resizer.output2 == RESIZER_B) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - resizer->crop_resizer. - formats[RESIZER_CROP_PAD_SOURCE] = fmt->format; - } else { - return -EINVAL; - } - } else if (&resizer->resizer_a.subdev == sd) { - if (fmt->pad == RESIZER_PAD_SINK) - resizer->resizer_a.formats[fmt->pad] = fmt->format; - else if (fmt->pad == RESIZER_PAD_SOURCE) - resizer->resizer_a.formats[fmt->pad] = fmt->format; - else - return -EINVAL; - } else if (&resizer->resizer_b.subdev == sd) { - if (fmt->pad == RESIZER_PAD_SINK) - resizer->resizer_b.formats[fmt->pad] = fmt->format; - else if (fmt->pad == RESIZER_PAD_SOURCE) - resizer->resizer_b.formats[fmt->pad] = fmt->format; - else - return -EINVAL; - } else { - return -EINVAL; - } - - return 0; -} - -/* - * resizer_get_format() - Retrieve the video format on a pad - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int resizer_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - fmt->format = *format; - - return 0; -} - -/* - * resizer_enum_frame_size() - enum frame sizes on pads - * @sd: Pointer to subdevice. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_frame_size_enum structure. - */ -static int resizer_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - resizer_try_format(sd, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - resizer_try_format(sd, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * resizer_enum_mbus_code() - enum mbus codes for pads - * @sd: Pointer to subdevice. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int resizer_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad == RESIZER_PAD_SINK) { - if (code->index >= ARRAY_SIZE(resizer_input_formats)) - return -EINVAL; - - code->code = resizer_input_formats[code->index]; - } else if (code->pad == RESIZER_PAD_SOURCE) { - if (code->index >= ARRAY_SIZE(resizer_output_formats)) - return -EINVAL; - - code->code = resizer_output_formats[code->index]; - } - - return 0; -} - -/* - * resizer_init_formats() - Initialize formats on all pads - * @sd: Pointer to subdevice. - * @fh: V4L2 subdev file handle. - * - * Initialize all pad formats with default values. Try formats are - * initialized on the file handle. - */ -static int resizer_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - __u32 which = V4L2_SUBDEV_FORMAT_TRY; - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - if (&resizer->crop_resizer.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_WIDTH; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SOURCE2; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_WIDTH; - resizer_set_format(sd, fh->pad, &format); - } else if (&resizer->resizer_a.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - resizer_set_format(sd, fh->pad, &format); - } else if (&resizer->resizer_b.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_B; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_B; - resizer_set_format(sd, fh->pad, &format); - } - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops = { - .ioctl = resizer_ioctl, -}; - -/* subdev internal operations */ -static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = { - .open = resizer_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = { - .s_stream = resizer_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { - .enum_mbus_code = resizer_enum_mbus_code, - .enum_frame_size = resizer_enum_frame_size, - .get_fmt = resizer_get_format, - .set_fmt = resizer_set_format, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops resizer_v4l2_ops = { - .core = &resizer_v4l2_core_ops, - .video = &resizer_v4l2_video_ops, - .pad = &resizer_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * resizer_link_setup() - Setup resizer connections - * @entity: Pointer to media entity structure - * @local: Pointer to local pad array - * @remote: Pointer to remote pad array - * @flags: Link flags - * return -EINVAL or zero on success - */ -static int resizer_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; - u16 ipipe_source = vpfe_dev->vpfe_ipipe.output; - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - if (&resizer->crop_resizer.subdev == sd) { - switch (index) { - case RESIZER_CROP_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_NONE; - break; - } - - if (resizer->crop_resizer.input != - RESIZER_CROP_INPUT_NONE) - return -EBUSY; - if (ipipeif_source == IPIPEIF_OUTPUT_RESIZER) - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_IPIPEIF; - else if (ipipe_source == IPIPE_OUTPUT_RESIZER) - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_IPIPE; - else - return -EINVAL; - break; - - case RESIZER_CROP_PAD_SOURCE | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.output = - RESIZER_CROP_OUTPUT_NONE; - break; - } - if (resizer->crop_resizer.output != - RESIZER_CROP_OUTPUT_NONE) - return -EBUSY; - resizer->crop_resizer.output = RESIZER_A; - break; - - case RESIZER_CROP_PAD_SOURCE2 | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.output2 = - RESIZER_CROP_OUTPUT_NONE; - break; - } - if (resizer->crop_resizer.output2 != - RESIZER_CROP_OUTPUT_NONE) - return -EBUSY; - resizer->crop_resizer.output2 = RESIZER_B; - break; - - default: - return -EINVAL; - } - } else if (&resizer->resizer_a.subdev == sd) { - switch (index) { - case RESIZER_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_a.input = RESIZER_INPUT_NONE; - break; - } - if (resizer->resizer_a.input != RESIZER_INPUT_NONE) - return -EBUSY; - resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER; - break; - - case RESIZER_PAD_SOURCE: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_a.output = RESIZER_OUTPUT_NONE; - break; - } - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) - return -EBUSY; - resizer->resizer_a.output = RESIZER_OUTPUT_MEMORY; - break; - - default: - return -EINVAL; - } - } else if (&resizer->resizer_b.subdev == sd) { - switch (index) { - case RESIZER_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_b.input = RESIZER_INPUT_NONE; - break; - } - if (resizer->resizer_b.input != RESIZER_INPUT_NONE) - return -EBUSY; - resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER; - break; - - case RESIZER_PAD_SOURCE: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_b.output = RESIZER_OUTPUT_NONE; - break; - } - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) - return -EBUSY; - resizer->resizer_b.output = RESIZER_OUTPUT_MEMORY; - break; - - default: - return -EINVAL; - } - } else { - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations resizer_media_ops = { - .link_setup = resizer_link_setup, -}; - -/* - * vpfe_resizer_unregister_entities() - Unregister entity - * @vpfe_rsz - pointer to resizer subdevice structure. - */ -void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz) -{ - /* unregister video devices */ - vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out); - vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out); - - /* unregister subdev */ - v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev); - v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev); - v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev); - /* cleanup entity */ - media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); -} - -/* - * vpfe_resizer_register_entities() - Register entity - * @resizer - pointer to resizer device. - * @vdev: pointer to v4l2 device structure. - */ -int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - unsigned int flags = 0; - int ret; - - /* Register the crop resizer subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->crop_resizer.subdev); - if (ret < 0) { - pr_err("Failed to register crop resizer as v4l2-subdev\n"); - return ret; - } - /* Register Resizer-A subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->resizer_a.subdev); - if (ret < 0) { - pr_err("Failed to register resizer-a as v4l2-subdev\n"); - return ret; - } - /* Register Resizer-B subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->resizer_b.subdev); - if (ret < 0) { - pr_err("Failed to register resizer-b as v4l2-subdev\n"); - return ret; - } - /* Register video-out device for resizer-a */ - ret = vpfe_video_register(&resizer->resizer_a.video_out, vdev); - if (ret) { - pr_err("Failed to register RSZ-A video-out device\n"); - goto out_video_out2_register; - } - resizer->resizer_a.video_out.vpfe_dev = vpfe_dev; - - /* Register video-out device for resizer-b */ - ret = vpfe_video_register(&resizer->resizer_b.video_out, vdev); - if (ret) { - pr_err("Failed to register RSZ-B video-out device\n"); - goto out_video_out2_register; - } - resizer->resizer_b.video_out.vpfe_dev = vpfe_dev; - - /* create link between Resizer Crop----> Resizer A*/ - ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1, - &resizer->resizer_a.subdev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer Crop----> Resizer B*/ - ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2, - &resizer->resizer_b.subdev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer A ----> video out */ - ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1, - &resizer->resizer_a.video_out.video_dev.entity, 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer B ----> video out */ - ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1, - &resizer->resizer_b.video_out.video_dev.entity, 0, flags); - if (ret < 0) - goto out_create_link; - - return 0; - -out_create_link: - vpfe_video_unregister(&resizer->resizer_b.video_out); -out_video_out2_register: - vpfe_video_unregister(&resizer->resizer_a.video_out); - v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev); - v4l2_device_unregister_subdev(&resizer->resizer_a.subdev); - v4l2_device_unregister_subdev(&resizer->resizer_b.subdev); - media_entity_cleanup(&resizer->crop_resizer.subdev.entity); - media_entity_cleanup(&resizer->resizer_a.subdev.entity); - media_entity_cleanup(&resizer->resizer_b.subdev.entity); - return ret; -} - -/* - * vpfe_resizer_init() - resizer device initialization. - * @vpfe_rsz - pointer to resizer device - * @pdev: platform device pointer. - */ -int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &vpfe_rsz->crop_resizer.subdev; - struct media_pad *pads = &vpfe_rsz->crop_resizer.pads[0]; - struct media_entity *me = &sd->entity; - resource_size_t res_len; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 5); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - vpfe_rsz->base_addr = ioremap_nocache(res->start, res_len); - if (!vpfe_rsz->base_addr) - return -EBUSY; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_CROP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_CROP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - pads[RESIZER_CROP_PAD_SOURCE2].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->crop_resizer.input = RESIZER_CROP_INPUT_NONE; - vpfe_rsz->crop_resizer.output = RESIZER_CROP_OUTPUT_NONE; - vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE; - vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_CROP_PADS_NUM, pads); - if (ret) - return ret; - - sd = &vpfe_rsz->resizer_a.subdev; - pads = &vpfe_rsz->resizer_a.pads[0]; - me = &sd->entity; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->resizer_a.input = RESIZER_INPUT_NONE; - vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE; - vpfe_rsz->resizer_a.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); - if (ret) - return ret; - - sd = &vpfe_rsz->resizer_b.subdev; - pads = &vpfe_rsz->resizer_b.pads[0]; - me = &sd->entity; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->resizer_b.input = RESIZER_INPUT_NONE; - vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE; - vpfe_rsz->resizer_b.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); - if (ret) - return ret; - - vpfe_rsz->resizer_a.video_out.ops = &resizer_a_video_ops; - vpfe_rsz->resizer_a.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ret = vpfe_video_init(&vpfe_rsz->resizer_a.video_out, "RSZ-A"); - if (ret) { - pr_err("Failed to init RSZ video-out device\n"); - return ret; - } - vpfe_rsz->resizer_b.video_out.ops = &resizer_b_video_ops; - vpfe_rsz->resizer_b.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ret = vpfe_video_init(&vpfe_rsz->resizer_b.video_out, "RSZ-B"); - if (ret) { - pr_err("Failed to init RSZ video-out2 device\n"); - return ret; - } - memset(&vpfe_rsz->config, 0, sizeof(struct resizer_params)); - - return 0; -} - -void -vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev) -{ - struct resource *res; - - iounmap(vpfe_rsz->base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 5); - if (res) - release_mem_region(res->start, - resource_size(res)); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.h b/drivers/staging/media/davinci_vpfe/dm365_resizer.h deleted file mode 100644 index 5e31de96b2c9..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.h +++ /dev/null @@ -1,241 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_DM365_RESIZER_H -#define _DAVINCI_VPFE_DM365_RESIZER_H - -enum resizer_oper_mode { - RESIZER_MODE_CONTINUOUS = 0, - RESIZER_MODE_ONE_SHOT = 1, -}; - -struct f_div_pass { - unsigned int o_hsz; - unsigned int i_hps; - unsigned int h_phs; - unsigned int src_hps; - unsigned int src_hsz; -}; - -#define MAX_PASSES 2 - -struct f_div_param { - unsigned char en; - unsigned int num_passes; - struct f_div_pass pass[MAX_PASSES]; -}; - -/* Resizer Rescale Parameters*/ -struct resizer_scale_param { - bool h_flip; - bool v_flip; - bool cen; - bool yen; - unsigned short i_vps; - unsigned short i_hps; - unsigned short o_vsz; - unsigned short o_hsz; - unsigned short v_phs_y; - unsigned short v_phs_c; - unsigned short v_dif; - /* resize method - Luminance */ - enum vpfe_rsz_intp_t v_typ_y; - /* resize method - Chrominance */ - enum vpfe_rsz_intp_t v_typ_c; - /* vertical lpf intensity - Luminance */ - unsigned char v_lpf_int_y; - /* vertical lpf intensity - Chrominance */ - unsigned char v_lpf_int_c; - unsigned short h_phs; - unsigned short h_dif; - /* resize method - Luminance */ - enum vpfe_rsz_intp_t h_typ_y; - /* resize method - Chrominance */ - enum vpfe_rsz_intp_t h_typ_c; - /* horizontal lpf intensity - Luminance */ - unsigned char h_lpf_int_y; - /* horizontal lpf intensity - Chrominance */ - unsigned char h_lpf_int_c; - bool dscale_en; - enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz; - enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz; - /* store the calculated frame division parameter */ - struct f_div_param f_div; -}; - -enum resizer_rgb_t { - OUTPUT_32BIT, - OUTPUT_16BIT -}; - -enum resizer_rgb_msk_t { - NOMASK = 0, - MASKLAST2 = 1, -}; - -/* Resizer RGB Conversion Parameters */ -struct resizer_rgb { - bool rgb_en; - enum resizer_rgb_t rgb_typ; - enum resizer_rgb_msk_t rgb_msk0; - enum resizer_rgb_msk_t rgb_msk1; - unsigned int rgb_alpha_val; -}; - -/* Resizer External Memory Parameters */ -struct rsz_ext_mem_param { - unsigned int rsz_sdr_oft_y; - unsigned int rsz_sdr_ptr_s_y; - unsigned int rsz_sdr_ptr_e_y; - unsigned int rsz_sdr_oft_c; - unsigned int rsz_sdr_ptr_s_c; - unsigned int rsz_sdr_ptr_e_c; - /* offset to be added to buffer start when flipping for y/ycbcr */ - unsigned int flip_ofst_y; - /* offset to be added to buffer start when flipping for c */ - unsigned int flip_ofst_c; - /* c offset for YUV 420SP */ - unsigned int c_offset; - /* User Defined Y offset for YUV 420SP or YUV420ILE data */ - unsigned int user_y_ofst; - /* User Defined C offset for YUV 420SP data */ - unsigned int user_c_ofst; -}; - -enum rsz_data_source { - IPIPE_DATA, - IPIPEIF_DATA -}; - -enum rsz_src_img_fmt { - RSZ_IMG_422, - RSZ_IMG_420 -}; - -enum rsz_dpaths_bypass_t { - BYPASS_OFF = 0, - BYPASS_ON = 1, -}; - -struct rsz_common_params { - unsigned int vps; - unsigned int vsz; - unsigned int hps; - unsigned int hsz; - /* 420 or 422 */ - enum rsz_src_img_fmt src_img_fmt; - /* Y or C when src_fmt is 420, 0 - y, 1 - c */ - unsigned char y_c; - /* flip raw or ycbcr */ - unsigned char raw_flip; - /* IPIPE or IPIPEIF data */ - enum rsz_data_source source; - enum rsz_dpaths_bypass_t passthrough; - unsigned char yuv_y_min; - unsigned char yuv_y_max; - unsigned char yuv_c_min; - unsigned char yuv_c_max; - bool rsz_seq_crv; - enum vpfe_chr_pos out_chr_pos; -}; - -struct resizer_params { - enum resizer_oper_mode oper_mode; - struct rsz_common_params rsz_common; - struct resizer_scale_param rsz_rsc_param[2]; - struct resizer_rgb rsz2rgb[2]; - struct rsz_ext_mem_param ext_mem_param[2]; - bool rsz_en[2]; - struct vpfe_rsz_config_params user_config; -}; - -#define ENABLE 1 -#define DISABLE (!ENABLE) - -#define RESIZER_CROP_PAD_SINK 0 -#define RESIZER_CROP_PAD_SOURCE 1 -#define RESIZER_CROP_PAD_SOURCE2 2 - -#define RESIZER_CROP_PADS_NUM 3 - -enum resizer_crop_input_entity { - RESIZER_CROP_INPUT_NONE = 0, - RESIZER_CROP_INPUT_IPIPEIF = 1, - RESIZER_CROP_INPUT_IPIPE = 2, -}; - -enum resizer_crop_output_entity { - RESIZER_CROP_OUTPUT_NONE, - RESIZER_A, - RESIZER_B, -}; - -struct dm365_crop_resizer_device { - struct v4l2_subdev subdev; - struct media_pad pads[RESIZER_CROP_PADS_NUM]; - struct v4l2_mbus_framefmt formats[RESIZER_CROP_PADS_NUM]; - enum resizer_crop_input_entity input; - enum resizer_crop_output_entity output; - enum resizer_crop_output_entity output2; - struct vpfe_resizer_device *rsz_device; -}; - -#define RESIZER_PAD_SINK 0 -#define RESIZER_PAD_SOURCE 1 - -#define RESIZER_PADS_NUM 2 - -enum resizer_input_entity { - RESIZER_INPUT_NONE = 0, - RESIZER_INPUT_CROP_RESIZER = 1, -}; - -enum resizer_output_entity { - RESIZER_OUTPUT_NONE = 0, - RESIZER_OUTPUT_MEMORY = 1, -}; - -struct dm365_resizer_device { - struct v4l2_subdev subdev; - struct media_pad pads[RESIZER_PADS_NUM]; - struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM]; - enum resizer_input_entity input; - enum resizer_output_entity output; - struct vpfe_video_device video_out; - struct vpfe_resizer_device *rsz_device; -}; - -struct vpfe_resizer_device { - struct dm365_crop_resizer_device crop_resizer; - struct dm365_resizer_device resizer_a; - struct dm365_resizer_device resizer_b; - struct resizer_params config; - void __iomem *base_addr; -}; - -int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev); -int vpfe_resizer_register_entities(struct vpfe_resizer_device *vpfe_rsz, - struct v4l2_device *v4l2_dev); -void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz); -void vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev); -void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer); -void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer); - -#endif /* _DAVINCI_VPFE_DM365_RESIZER_H */ diff --git a/drivers/staging/media/davinci_vpfe/vpfe.h b/drivers/staging/media/davinci_vpfe/vpfe.h deleted file mode 100644 index 1f8e011fc162..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _VPFE_H -#define _VPFE_H - -#ifdef __KERNEL__ -#include -#include -#include - -#include - -#define CAPTURE_DRV_NAME "vpfe-capture" - -struct vpfe_route { - __u32 input; - __u32 output; -}; - -enum vpfe_subdev_id { - VPFE_SUBDEV_TVP5146 = 1, - VPFE_SUBDEV_MT9T031 = 2, - VPFE_SUBDEV_TVP7002 = 3, - VPFE_SUBDEV_MT9P031 = 4, -}; - -struct vpfe_ext_subdev_info { - /* v4l2 subdev */ - struct v4l2_subdev *subdev; - /* Sub device module name */ - char module_name[32]; - /* Sub device group id */ - int grp_id; - /* Number of inputs supported */ - int num_inputs; - /* inputs available at the sub device */ - struct v4l2_input *inputs; - /* Sub dev routing information for each input */ - struct vpfe_route *routes; - /* ccdc bus/interface configuration */ - struct vpfe_hw_if_param ccdc_if_params; - /* i2c subdevice board info */ - struct i2c_board_info board_info; - /* Is this a camera sub device ? */ - unsigned is_camera:1; - /* check if sub dev supports routing */ - unsigned can_route:1; - /* registered ? */ - unsigned registered:1; -}; - -struct vpfe_config { - /* Number of sub devices connected to vpfe */ - int num_subdevs; - /* information about each subdev */ - struct vpfe_ext_subdev_info *sub_devs; - /* evm card info */ - char *card_name; - /* setup function for the input path */ - int (*setup_input)(enum vpfe_subdev_id id); - /* number of clocks */ - int num_clocks; - /* clocks used for vpfe capture */ - char *clocks[]; -}; -#endif -#endif diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c deleted file mode 100644 index 9dc28ffe38d5..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c +++ /dev/null @@ -1,716 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - * - * - * Driver name : VPFE Capture driver - * VPFE Capture driver allows applications to capture and stream video - * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as - * TVP5146 or Raw Bayer RGB image data from an image sensor - * such as Microns' MT9T001, MT9T031 etc. - * - * These SoCs have, in common, a Video Processing Subsystem (VPSS) that - * consists of a Video Processing Front End (VPFE) for capturing - * video/raw image data and Video Processing Back End (VPBE) for displaying - * YUV data through an in-built analog encoder or Digital LCD port. This - * driver is for capture through VPFE. A typical EVM using these SoCs have - * following high level configuration. - * - * decoder(TVP5146/ YUV/ - * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF) - * data input | | - * V | - * SDRAM | - * V - * Image Processor - * | - * V - * SDRAM - * The data flow happens from a decoder connected to the VPFE over a - * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface - * and to the input of VPFE through an optional MUX (if more inputs are - * to be interfaced on the EVM). The input data is first passed through - * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC - * does very little or no processing on YUV data and does pre-process Raw - * Bayer RGB data through modules such as Defect Pixel Correction (DFC) - * Color Space Conversion (CSC), data gain/offset etc. After this, data - * can be written to SDRAM or can be connected to the image processing - * block such as IPIPE (on DM355/DM365 only). - * - * Features supported - * - MMAP IO - * - USERPTR IO - * - Capture using TVP5146 over BT.656 - * - Support for interfacing decoders using sub device model - * - Work with DM365 or DM355 or DM6446 CCDC to do Raw Bayer - * RGB/YUV data capture to SDRAM. - * - Chaining of Image Processor - * - SINGLE-SHOT mode - */ - -#include -#include -#include - -#include "vpfe.h" -#include "vpfe_mc_capture.h" - -static bool debug; -static bool interface; - -module_param(interface, bool, 0444); -module_param(debug, bool, 0644); - -/* - * VPFE capture can be used for capturing video such as from TVP5146 or TVP7002 - * and for capture raw bayer data from camera sensors such as mt9p031. At this - * point there is problem in co-existence of mt9p031 and tvp5146 due to i2c - * address collision. So set the variable below from bootargs to do either video - * capture or camera capture. - * interface = 0 - video capture (from TVP514x or such), - * interface = 1 - Camera capture (from mt9p031 or such) - * Re-visit this when we fix the co-existence issue - */ -MODULE_PARM_DESC(interface, "interface 0-1 (default:0)"); -MODULE_PARM_DESC(debug, "Debug level 0-1"); - -MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Texas Instruments"); - -/* map mbus_fmt to pixelformat */ -void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus, - struct v4l2_pix_format *pix) -{ - switch (mbus->code) { - case MEDIA_BUS_FMT_UYVY8_2X8: - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_YUYV8_2X8: - pix->pixelformat = V4L2_PIX_FMT_YUYV; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_YUYV10_1X20: - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - pix->pixelformat = V4L2_PIX_FMT_SBGGR16; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - pix->pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - pix->pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_YDYUYDYV8_1X16: - pix->pixelformat = V4L2_PIX_FMT_NV12; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_Y8_1X8: - pix->pixelformat = V4L2_PIX_FMT_GREY; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_UV8_1X8: - pix->pixelformat = V4L2_PIX_FMT_UV8; - pix->bytesperline = pix->width; - break; - - default: - pr_err("Invalid mbus code set\n"); - } - /* pitch should be 32 bytes aligned */ - pix->bytesperline = ALIGN(pix->bytesperline, 32); - if (pix->pixelformat == V4L2_PIX_FMT_NV12) - pix->sizeimage = pix->bytesperline * pix->height + - ((pix->bytesperline * pix->height) >> 1); - else - pix->sizeimage = pix->bytesperline * pix->height; -} - -/* ISR for VINT0*/ -static irqreturn_t vpfe_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_isif_buffer_isr(&vpfe_dev->vpfe_isif); - vpfe_resizer_buffer_isr(&vpfe_dev->vpfe_resizer); - return IRQ_HANDLED; -} - -/* vpfe_vdint1_isr() - isr handler for VINT1 interrupt */ -static irqreturn_t vpfe_vdint1_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_isif_vidint1_isr(&vpfe_dev->vpfe_isif); - return IRQ_HANDLED; -} - -/* vpfe_imp_dma_isr() - ISR for ipipe dma completion */ -static irqreturn_t vpfe_imp_dma_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_ipipeif_ss_buffer_isr(&vpfe_dev->vpfe_ipipeif); - vpfe_resizer_dma_isr(&vpfe_dev->vpfe_resizer); - return IRQ_HANDLED; -} - -/* - * vpfe_disable_clock() - Disable clocks for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Disables clocks defined in vpfe configuration. The function - * assumes that at least one clock is to be defined which is - * true as of now. - */ -static void vpfe_disable_clock(struct vpfe_device *vpfe_dev) -{ - struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; - int i; - - for (i = 0; i < vpfe_cfg->num_clocks; i++) { - clk_disable_unprepare(vpfe_dev->clks[i]); - clk_put(vpfe_dev->clks[i]); - } - kzfree(vpfe_dev->clks); - v4l2_info(vpfe_dev->pdev->driver, "vpfe capture clocks disabled\n"); -} - -/* - * vpfe_enable_clock() - Enable clocks for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Enables clocks defined in vpfe configuration. The function - * assumes that at least one clock is to be defined which is - * true as of now. - */ -static int vpfe_enable_clock(struct vpfe_device *vpfe_dev) -{ - struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; - int ret = -EFAULT; - int i; - - if (!vpfe_cfg->num_clocks) - return 0; - - vpfe_dev->clks = kcalloc(vpfe_cfg->num_clocks, - sizeof(*vpfe_dev->clks), GFP_KERNEL); - if (!vpfe_dev->clks) - return -ENOMEM; - - for (i = 0; i < vpfe_cfg->num_clocks; i++) { - if (vpfe_cfg->clocks[i] == NULL) { - v4l2_err(vpfe_dev->pdev->driver, - "clock %s is not defined in vpfe config\n", - vpfe_cfg->clocks[i]); - goto out; - } - - vpfe_dev->clks[i] = - clk_get(vpfe_dev->pdev, vpfe_cfg->clocks[i]); - if (IS_ERR(vpfe_dev->clks[i])) { - v4l2_err(vpfe_dev->pdev->driver, - "Failed to get clock %s\n", - vpfe_cfg->clocks[i]); - goto out; - } - - if (clk_prepare_enable(vpfe_dev->clks[i])) { - v4l2_err(vpfe_dev->pdev->driver, - "vpfe clock %s not enabled\n", - vpfe_cfg->clocks[i]); - goto out; - } - - v4l2_info(vpfe_dev->pdev->driver, "vpss clock %s enabled", - vpfe_cfg->clocks[i]); - } - - return 0; -out: - for (i = 0; i < vpfe_cfg->num_clocks; i++) - if (!IS_ERR(vpfe_dev->clks[i])) { - clk_disable_unprepare(vpfe_dev->clks[i]); - clk_put(vpfe_dev->clks[i]); - } - - v4l2_err(vpfe_dev->pdev->driver, "Failed to enable clocks\n"); - kzfree(vpfe_dev->clks); - - return ret; -} - -/* - * vpfe_detach_irq() - Detach IRQs for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Detach all IRQs defined in vpfe configuration. - */ -static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) -{ - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); - free_irq(vpfe_dev->imp_dma_irq, vpfe_dev); -} - -/* - * vpfe_attach_irq() - Attach IRQs for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Attach all IRQs defined in vpfe configuration. - */ -static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) -{ - int ret; - - ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, 0, - "vpfe_capture0", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting VINT0 interrupt\n"); - return ret; - } - - ret = request_irq(vpfe_dev->ccdc_irq1, vpfe_vdint1_isr, 0, - "vpfe_capture1", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting VINT1 interrupt\n"); - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - return ret; - } - - ret = request_irq(vpfe_dev->imp_dma_irq, vpfe_imp_dma_isr, - 0, "Imp_Sdram_Irq", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting IMP IRQ interrupt\n"); - free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - return ret; - } - - return 0; -} - -/* - * register_i2c_devices() - register all i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * - * register all i2c v4l2 subdevs - */ -static int register_i2c_devices(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ext_subdev_info *sdinfo; - struct vpfe_config *vpfe_cfg; - struct i2c_adapter *i2c_adap; - unsigned int num_subdevs; - int ret; - int i; - int k; - - vpfe_cfg = vpfe_dev->cfg; - i2c_adap = i2c_get_adapter(1); - num_subdevs = vpfe_cfg->num_subdevs; - vpfe_dev->sd = - kcalloc(num_subdevs, sizeof(struct v4l2_subdev *), - GFP_KERNEL); - if (!vpfe_dev->sd) - return -ENOMEM; - - for (i = 0, k = 0; i < num_subdevs; i++) { - sdinfo = &vpfe_cfg->sub_devs[i]; - /* - * register subdevices based on interface setting. Currently - * tvp5146 and mt9p031 cannot co-exists due to i2c address - * conflicts. So only one of them is registered. Re-visit this - * once we have support for i2c switch handling in i2c driver - * framework - */ - if (interface == sdinfo->is_camera) { - /* setup input path */ - if (vpfe_cfg->setup_input && - vpfe_cfg->setup_input(sdinfo->grp_id) < 0) { - ret = -EFAULT; - v4l2_info(&vpfe_dev->v4l2_dev, - "could not setup input for %s\n", - sdinfo->module_name); - goto probe_sd_out; - } - /* Load up the subdevice */ - vpfe_dev->sd[k] = - v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, - i2c_adap, &sdinfo->board_info, - NULL); - if (vpfe_dev->sd[k]) { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s registered\n", - sdinfo->module_name); - - vpfe_dev->sd[k]->grp_id = sdinfo->grp_id; - k++; - - sdinfo->registered = 1; - } - } else { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s is not registered\n", - sdinfo->module_name); - } - } - vpfe_dev->num_ext_subdevs = k; - - return 0; - -probe_sd_out: - kzfree(vpfe_dev->sd); - - return ret; -} - -/* - * vpfe_register_entities() - register all v4l2 subdevs and media entities - * @vpfe_dev - ptr to vpfe capture device - * - * register all v4l2 subdevs, media entities, and creates links - * between entities - */ -static int vpfe_register_entities(struct vpfe_device *vpfe_dev) -{ - unsigned int flags = 0; - int ret; - int i; - - /* register i2c devices first */ - ret = register_i2c_devices(vpfe_dev); - if (ret) - return ret; - - /* register rest of the sub-devs */ - ret = vpfe_isif_register_entities(&vpfe_dev->vpfe_isif, - &vpfe_dev->v4l2_dev); - if (ret) - return ret; - - ret = vpfe_ipipeif_register_entities(&vpfe_dev->vpfe_ipipeif, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_isif_register; - - ret = vpfe_ipipe_register_entities(&vpfe_dev->vpfe_ipipe, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_ipipeif_register; - - ret = vpfe_resizer_register_entities(&vpfe_dev->vpfe_resizer, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_ipipe_register; - - /* create links now, starting with external(i2c) entities */ - for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) - /* - * if entity has no pads (ex: amplifier), - * can't establish link - */ - if (vpfe_dev->sd[i]->entity.num_pads) { - ret = media_create_pad_link(&vpfe_dev->sd[i]->entity, - 0, &vpfe_dev->vpfe_isif.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - } - - ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1, - &vpfe_dev->vpfe_ipipeif.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, - &vpfe_dev->vpfe_ipipe.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity, - 1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, - &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = v4l2_device_register_subdev_nodes(&vpfe_dev->v4l2_dev); - if (ret < 0) - goto out_resizer_register; - - return 0; - -out_resizer_register: - vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer); -out_ipipe_register: - vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe); -out_ipipeif_register: - vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif); -out_isif_register: - vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif); - - return ret; -} - -/* - * vpfe_unregister_entities() - unregister all v4l2 subdevs and media entities - * @vpfe_dev - ptr to vpfe capture device - * - * unregister all v4l2 subdevs and media entities - */ -static void vpfe_unregister_entities(struct vpfe_device *vpfe_dev) -{ - vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif); - vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif); - vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe); - vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer); -} - -/* - * vpfe_cleanup_modules() - cleanup all non-i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * @pdev - pointer to platform device - * - * cleanup all v4l2 subdevs - */ -static void vpfe_cleanup_modules(struct vpfe_device *vpfe_dev, - struct platform_device *pdev) -{ - vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev); - vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev); - vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev); - vpfe_resizer_cleanup(&vpfe_dev->vpfe_resizer, pdev); -} - -/* - * vpfe_initialize_modules() - initialize all non-i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * @pdev - pointer to platform device - * - * initialize all v4l2 subdevs and media entities - */ -static int vpfe_initialize_modules(struct vpfe_device *vpfe_dev, - struct platform_device *pdev) -{ - int ret; - - ret = vpfe_isif_init(&vpfe_dev->vpfe_isif, pdev); - if (ret) - return ret; - - ret = vpfe_ipipeif_init(&vpfe_dev->vpfe_ipipeif, pdev); - if (ret) - goto out_isif_init; - - ret = vpfe_ipipe_init(&vpfe_dev->vpfe_ipipe, pdev); - if (ret) - goto out_ipipeif_init; - - ret = vpfe_resizer_init(&vpfe_dev->vpfe_resizer, pdev); - if (ret) - goto out_ipipe_init; - - return 0; - -out_ipipe_init: - vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev); -out_ipipeif_init: - vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev); -out_isif_init: - vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev); - - return ret; -} - -/* - * vpfe_probe() : vpfe probe function - * @pdev: platform device pointer - * - * This function creates device entries by register itself to the V4L2 driver - * and initializes fields of each device objects - */ -static int vpfe_probe(struct platform_device *pdev) -{ - struct vpfe_device *vpfe_dev; - struct resource *res1; - int ret = -ENOMEM; - - vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL); - if (!vpfe_dev) - return ret; - - if (pdev->dev.platform_data == NULL) { - v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - - vpfe_dev->cfg = pdev->dev.platform_data; - if (vpfe_dev->cfg->card_name == NULL || - vpfe_dev->cfg->sub_devs == NULL) { - v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - - /* Get VINT0 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT0\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->ccdc_irq0 = res1->start; - - /* Get VINT1 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT1\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->ccdc_irq1 = res1->start; - - /* Get DMA irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 2); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for DMA\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->imp_dma_irq = res1->start; - - vpfe_dev->pdev = &pdev->dev; - - /* enable vpss clocks */ - ret = vpfe_enable_clock(vpfe_dev); - if (ret) - goto probe_free_dev_mem; - - ret = vpfe_initialize_modules(vpfe_dev, pdev); - if (ret) - goto probe_disable_clock; - - vpfe_dev->media_dev.dev = vpfe_dev->pdev; - strscpy((char *)&vpfe_dev->media_dev.model, "davinci-media", - sizeof(vpfe_dev->media_dev.model)); - - ret = media_device_register(&vpfe_dev->media_dev); - if (ret) { - v4l2_err(pdev->dev.driver, - "Unable to register media device.\n"); - goto probe_out_entities_cleanup; - } - - vpfe_dev->v4l2_dev.mdev = &vpfe_dev->media_dev; - ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev); - if (ret) { - v4l2_err(pdev->dev.driver, "Unable to register v4l2 device.\n"); - goto probe_out_media_unregister; - } - - v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n"); - /* set the driver data in platform device */ - platform_set_drvdata(pdev, vpfe_dev); - /* register subdevs/entities */ - ret = vpfe_register_entities(vpfe_dev); - if (ret) - goto probe_out_v4l2_unregister; - - ret = vpfe_attach_irq(vpfe_dev); - if (ret) - goto probe_out_entities_unregister; - - return 0; - -probe_out_entities_unregister: - vpfe_unregister_entities(vpfe_dev); - kzfree(vpfe_dev->sd); -probe_out_v4l2_unregister: - v4l2_device_unregister(&vpfe_dev->v4l2_dev); -probe_out_media_unregister: - media_device_unregister(&vpfe_dev->media_dev); -probe_out_entities_cleanup: - vpfe_cleanup_modules(vpfe_dev, pdev); -probe_disable_clock: - vpfe_disable_clock(vpfe_dev); -probe_free_dev_mem: - kzfree(vpfe_dev); - - return ret; -} - -/* - * vpfe_remove : This function un-registers device from V4L2 driver - */ -static int vpfe_remove(struct platform_device *pdev) -{ - struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); - - v4l2_info(pdev->dev.driver, "%s\n", __func__); - - kzfree(vpfe_dev->sd); - vpfe_detach_irq(vpfe_dev); - vpfe_unregister_entities(vpfe_dev); - vpfe_cleanup_modules(vpfe_dev, pdev); - v4l2_device_unregister(&vpfe_dev->v4l2_dev); - media_device_unregister(&vpfe_dev->media_dev); - vpfe_disable_clock(vpfe_dev); - kzfree(vpfe_dev); - - return 0; -} - -static struct platform_driver vpfe_driver = { - .driver = { - .name = CAPTURE_DRV_NAME, - }, - .probe = vpfe_probe, - .remove = vpfe_remove, -}; - -module_platform_driver(vpfe_driver); diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h deleted file mode 100644 index fe4a421b5dba..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_MC_CAPTURE_H -#define _DAVINCI_VPFE_MC_CAPTURE_H - -#include "dm365_ipipe.h" -#include "dm365_ipipeif.h" -#include "dm365_isif.h" -#include "dm365_resizer.h" -#include "vpfe_video.h" - -#define VPFE_MAJOR_RELEASE 0 -#define VPFE_MINOR_RELEASE 0 -#define VPFE_BUILD 1 -#define VPFE_CAPTURE_VERSION_CODE ((VPFE_MAJOR_RELEASE << 16) | \ - (VPFE_MINOR_RELEASE << 8) | \ - VPFE_BUILD) - -/* IPIPE hardware limits */ -#define IPIPE_MAX_OUTPUT_WIDTH_A 2176 -#define IPIPE_MAX_OUTPUT_WIDTH_B 640 - -/* Based on max resolution supported. QXGA */ -#define IPIPE_MAX_OUTPUT_HEIGHT_A 1536 -/* Based on max resolution supported. VGA */ -#define IPIPE_MAX_OUTPUT_HEIGHT_B 480 - -#define to_vpfe_device(ptr_module) \ - container_of(ptr_module, struct vpfe_device, vpfe_##ptr_module) -#define to_device(ptr_module) \ - (to_vpfe_device(ptr_module)->dev) - -struct vpfe_device { - /* external registered sub devices */ - struct v4l2_subdev **sd; - /* number of registered external subdevs */ - unsigned int num_ext_subdevs; - /* vpfe cfg */ - struct vpfe_config *cfg; - /* clock ptrs for vpfe capture */ - struct clk **clks; - /* V4l2 device */ - struct v4l2_device v4l2_dev; - /* parent device */ - struct device *pdev; - /* IRQ number for DMA transfer completion at the image processor */ - unsigned int imp_dma_irq; - /* CCDC IRQs used when CCDC/ISIF output to SDRAM */ - unsigned int ccdc_irq0; - unsigned int ccdc_irq1; - /* media device */ - struct media_device media_dev; - /* ccdc subdevice */ - struct vpfe_isif_device vpfe_isif; - /* ipipeif subdevice */ - struct vpfe_ipipeif_device vpfe_ipipeif; - /* ipipe subdevice */ - struct vpfe_ipipe_device vpfe_ipipe; - /* resizer subdevice */ - struct vpfe_resizer_device vpfe_resizer; -}; - -/* File handle structure */ -struct vpfe_fh { - struct v4l2_fh vfh; - struct vpfe_video_device *video; - /* Indicates whether this file handle is doing IO */ - u8 io_allowed; -}; - -void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus, - struct v4l2_pix_format *pix); - -#endif /* _DAVINCI_VPFE_MC_CAPTURE_H */ diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c deleted file mode 100644 index ab6bc452d9f6..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ /dev/null @@ -1,1646 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#include -#include - -#include - -#include "vpfe.h" -#include "vpfe_mc_capture.h" - -static int debug; - -/* get v4l2 subdev pointer to external subdev which is active */ -static struct media_entity *vpfe_get_input_entity - (struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct media_pad *remote; - - remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (!remote) { - pr_err("Invalid media connection to isif/ccdc\n"); - return NULL; - } - return remote->entity; -} - -/* updates external subdev(sensor/decoder) which is active */ -static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_config *vpfe_cfg; - struct v4l2_subdev *subdev; - struct media_pad *remote; - int i; - - remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (!remote) { - pr_err("Invalid media connection to isif/ccdc\n"); - return -EINVAL; - } - - subdev = media_entity_to_v4l2_subdev(remote->entity); - vpfe_cfg = vpfe_dev->pdev->platform_data; - for (i = 0; i < vpfe_cfg->num_subdevs; i++) { - if (!strcmp(vpfe_cfg->sub_devs[i].module_name, subdev->name)) { - video->current_ext_subdev = &vpfe_cfg->sub_devs[i]; - break; - } - } - - /* if user not linked decoder/sensor to isif/ccdc */ - if (i == vpfe_cfg->num_subdevs) { - pr_err("Invalid media chain connection to isif/ccdc\n"); - return -EINVAL; - } - /* find the v4l2 subdev pointer */ - for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) { - if (!strcmp(video->current_ext_subdev->module_name, - vpfe_dev->sd[i]->name)) - video->current_ext_subdev->subdev = vpfe_dev->sd[i]; - } - return 0; -} - -/* get the subdev which is connected to the output video node */ -static struct v4l2_subdev * -vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad) -{ - struct media_pad *remote = media_entity_remote_pad(&video->pad); - - if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) - return NULL; - if (pad) - *pad = remote->index; - return media_entity_to_v4l2_subdev(remote->entity); -} - -/* get the format set at output pad of the adjacent subdev */ -static int -__vpfe_video_get_format(struct vpfe_video_device *video, - struct v4l2_format *format) -{ - struct v4l2_subdev_format fmt; - struct v4l2_subdev *subdev; - struct media_pad *remote; - u32 pad; - int ret; - - subdev = vpfe_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - remote = media_entity_remote_pad(&video->pad); - fmt.pad = remote->index; - - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - if (ret == -ENOIOCTLCMD) - return -EINVAL; - - format->type = video->type; - /* convert mbus_format to v4l2_format */ - v4l2_fill_pix_format(&format->fmt.pix, &fmt.format); - mbus_to_pix(&fmt.format, &format->fmt.pix); - - return 0; -} - -/* make a note of pipeline details */ -static int vpfe_prepare_pipeline(struct vpfe_video_device *video) -{ - struct media_graph graph; - struct media_entity *entity = &video->video_dev.entity; - struct media_device *mdev = entity->graph_obj.mdev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_video_device *far_end = NULL; - int ret; - - pipe->input_num = 0; - pipe->output_num = 0; - - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - pipe->inputs[pipe->input_num++] = video; - else - pipe->outputs[pipe->output_num++] = video; - - mutex_lock(&mdev->graph_mutex); - ret = media_graph_walk_init(&graph, mdev); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - return -ENOMEM; - } - media_graph_walk_start(&graph, entity); - while ((entity = media_graph_walk_next(&graph))) { - if (entity == &video->video_dev.entity) - continue; - if (!is_media_entity_v4l2_video_device(entity)) - continue; - far_end = to_vpfe_video(media_entity_to_video_device(entity)); - if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - pipe->inputs[pipe->input_num++] = far_end; - else - pipe->outputs[pipe->output_num++] = far_end; - } - media_graph_walk_cleanup(&graph); - mutex_unlock(&mdev->graph_mutex); - - return 0; -} - -/* update pipe state selected by user */ -static int vpfe_update_pipe_state(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int ret; - - ret = vpfe_prepare_pipeline(video); - if (ret) - return ret; - - /* - * Find out if there is any input video - * if yes, it is single shot. - */ - if (pipe->input_num == 0) { - pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS; - ret = vpfe_update_current_ext_subdev(video); - if (ret) { - pr_err("Invalid external subdev\n"); - return ret; - } - } else { - pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT; - } - video->initialized = 1; - video->skip_frame_count = 1; - video->skip_frame_count_init = 1; - return 0; -} - -/* checks whether pipeline is ready for enabling */ -int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe) -{ - int i; - - for (i = 0; i < pipe->input_num; i++) - if (!pipe->inputs[i]->started || - pipe->inputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED) - return 0; - for (i = 0; i < pipe->output_num; i++) - if (!pipe->outputs[i]->started || - pipe->outputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED) - return 0; - return 1; -} - -/* - * Validate a pipeline by checking both ends of all links for format - * discrepancies. - * - * Return 0 if all formats match, or -EPIPE if at least one link is found with - * different formats on its two ends. - */ -static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) -{ - struct v4l2_subdev_format fmt_source; - struct v4l2_subdev_format fmt_sink; - struct v4l2_subdev *subdev; - struct media_pad *pad; - int ret; - - /* - * Should not matter if it is output[0] or 1 as - * the general ideas is to traverse backwards and - * the fact that the out video node always has the - * format of the connected pad. - */ - subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL); - if (!subdev) - return -EPIPE; - - while (1) { - /* Retrieve the sink format */ - pad = &subdev->entity.pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE; - fmt_sink.pad = pad->index; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, - &fmt_sink); - - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - - /* Retrieve the source format */ - pad = media_entity_remote_pad(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - - subdev = media_entity_to_v4l2_subdev(pad->entity); - - fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE; - fmt_source.pad = pad->index; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source); - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - - /* Check if the two ends match */ - if (fmt_source.format.code != fmt_sink.format.code || - fmt_source.format.width != fmt_sink.format.width || - fmt_source.format.height != fmt_sink.format.height) - return -EPIPE; - } - return 0; -} - -/* - * vpfe_pipeline_enable() - Enable streaming on a pipeline - * @vpfe_dev: vpfe device - * @pipe: vpfe pipeline - * - * Walk the entities chain starting at the pipeline output video node and start - * all modules in the chain in the given mode. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. - */ -static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe) -{ - struct media_entity *entity; - struct v4l2_subdev *subdev; - struct media_device *mdev; - int ret; - - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - entity = vpfe_get_input_entity(pipe->outputs[0]); - else - entity = &pipe->inputs[0]->video_dev.entity; - - mdev = entity->graph_obj.mdev; - mutex_lock(&mdev->graph_mutex); - ret = media_graph_walk_init(&pipe->graph, mdev); - if (ret) - goto out; - media_graph_walk_start(&pipe->graph, entity); - while ((entity = media_graph_walk_next(&pipe->graph))) { - - if (!is_media_entity_v4l2_subdev(entity)) - continue; - subdev = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(subdev, video, s_stream, 1); - if (ret < 0 && ret != -ENOIOCTLCMD) - break; - } -out: - if (ret) - media_graph_walk_cleanup(&pipe->graph); - mutex_unlock(&mdev->graph_mutex); - return ret; -} - -/* - * vpfe_pipeline_disable() - Disable streaming on a pipeline - * @vpfe_dev: vpfe device - * @pipe: VPFE pipeline - * - * Walk the entities chain starting at the pipeline output video node and stop - * all modules in the chain. - * - * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module - * can't be stopped. - */ -static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) -{ - struct media_entity *entity; - struct v4l2_subdev *subdev; - struct media_device *mdev; - int ret = 0; - - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - entity = vpfe_get_input_entity(pipe->outputs[0]); - else - entity = &pipe->inputs[0]->video_dev.entity; - - mdev = entity->graph_obj.mdev; - mutex_lock(&mdev->graph_mutex); - media_graph_walk_start(&pipe->graph, entity); - - while ((entity = media_graph_walk_next(&pipe->graph))) { - - if (!is_media_entity_v4l2_subdev(entity)) - continue; - subdev = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (ret < 0 && ret != -ENOIOCTLCMD) - break; - } - mutex_unlock(&mdev->graph_mutex); - - media_graph_walk_cleanup(&pipe->graph); - return ret ? -ETIMEDOUT : 0; -} - -/* - * vpfe_pipeline_set_stream() - Enable/disable streaming on a pipeline - * @vpfe_dev: VPFE device - * @pipe: VPFE pipeline - * @state: Stream state (stopped or active) - * - * Set the pipeline to the given stream state. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. - */ -static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe, - enum vpfe_pipeline_stream_state state) -{ - if (state == VPFE_PIPELINE_STREAM_STOPPED) - return vpfe_pipeline_disable(pipe); - - return vpfe_pipeline_enable(pipe); -} - -static int all_videos_stopped(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int i; - - for (i = 0; i < pipe->input_num; i++) - if (pipe->inputs[i]->started) - return 0; - for (i = 0; i < pipe->output_num; i++) - if (pipe->outputs[i]->started) - return 0; - return 1; -} - -/* - * vpfe_open() - open video device - * @file: file pointer - * - * initialize media pipeline state, allocate memory for file handle - * - * Return 0 if successful, or the return -ENODEV otherwise. - */ -static int vpfe_open(struct file *file) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_fh *handle; - - /* Allocate memory for the file handle object */ - handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL); - - if (!handle) - return -ENOMEM; - - v4l2_fh_init(&handle->vfh, &video->video_dev); - v4l2_fh_add(&handle->vfh); - - mutex_lock(&video->lock); - /* If decoder is not initialized. initialize it */ - if (!video->initialized && vpfe_update_pipe_state(video)) { - mutex_unlock(&video->lock); - v4l2_fh_del(&handle->vfh); - v4l2_fh_exit(&handle->vfh); - kfree(handle); - return -ENODEV; - } - /* Increment device users counter */ - video->usrs++; - /* Set io_allowed member to false */ - handle->io_allowed = 0; - handle->video = video; - file->private_data = &handle->vfh; - mutex_unlock(&video->lock); - - return 0; -} - -/* get the next buffer available from dma queue */ -static unsigned long -vpfe_video_get_next_buffer(struct vpfe_video_device *video) -{ - video->cur_frm = video->next_frm = - list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - - list_del(&video->next_frm->list); - video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0); -} - -/* schedule the next buffer which is available on dma queue */ -void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - if (list_empty(&video->dma_queue)) - return; - - video->next_frm = list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - - if (video->pipe.state == VPFE_PIPELINE_STREAM_SINGLESHOT) - video->cur_frm = video->next_frm; - - list_del(&video->next_frm->list); - video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0); - video->ops->queue(vpfe_dev, addr); - video->state = VPFE_VIDEO_BUFFER_QUEUED; -} - -/* schedule the buffer for capturing bottom field */ -void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0); - addr += video->field_off; - video->ops->queue(vpfe_dev, addr); -} - -/* make buffer available for dequeue */ -void vpfe_video_process_buffer_complete(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - - video->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - video->cur_frm = video->next_frm; -} - -/* vpfe_stop_capture() - stop streaming */ -static void vpfe_stop_capture(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - - video->started = 0; - - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - return; - if (all_videos_stopped(video)) - vpfe_pipeline_set_stream(pipe, - VPFE_PIPELINE_STREAM_STOPPED); -} - -/* - * vpfe_release() - release video device - * @file: file pointer - * - * deletes buffer queue, frees the buffers and the vpfe file handle - * - * Return 0 - */ -static int vpfe_release(struct file *file) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct v4l2_fh *vfh = file->private_data; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = container_of(vfh, struct vpfe_fh, vfh); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n"); - - /* Get the device lock */ - mutex_lock(&video->lock); - /* if this instance is doing IO */ - if (fh->io_allowed) { - if (video->started) { - vpfe_stop_capture(video); - /* - * mark pipe state as stopped in vpfe_release(), - * as app might call streamon() after streamoff() - * in which case driver has to start streaming. - */ - video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED; - vb2_streamoff(&video->buffer_queue, - video->buffer_queue.type); - } - video->io_usrs = 0; - /* Free buffers allocated */ - vb2_queue_release(&video->buffer_queue); - } - /* Decrement device users counter */ - video->usrs--; - v4l2_fh_del(&fh->vfh); - v4l2_fh_exit(&fh->vfh); - /* If this is the last file handle */ - if (!video->usrs) - video->initialized = 0; - mutex_unlock(&video->lock); - file->private_data = NULL; - /* Free memory allocated to file handle object */ - v4l2_fh_del(vfh); - kzfree(fh); - return 0; -} - -/* - * vpfe_mmap() - It is used to map kernel space buffers - * into user spaces - */ -static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n"); - return vb2_mmap(&video->buffer_queue, vma); -} - -/* - * vpfe_poll() - It is used for select/poll system call - */ -static __poll_t vpfe_poll(struct file *file, poll_table *wait) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n"); - if (video->started) - return vb2_poll(&video->buffer_queue, file, wait); - return 0; -} - -/* vpfe capture driver file operations */ -static const struct v4l2_file_operations vpfe_fops = { - .owner = THIS_MODULE, - .open = vpfe_open, - .release = vpfe_release, - .unlocked_ioctl = video_ioctl2, - .mmap = vpfe_mmap, - .poll = vpfe_poll -}; - -/* - * vpfe_querycap() - query capabilities of video device - * @file: file pointer - * @priv: void pointer - * @cap: pointer to v4l2_capability structure - * - * fills v4l2 capabilities structure - * - * Return 0 - */ -static int vpfe_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); - - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | - V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; - strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); - strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); - - return 0; -} - -/* - * vpfe_g_fmt() - get the format which is active on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * fills v4l2 format structure with active format - * - * Return 0 - */ -static int vpfe_g_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n"); - /* Fill in the information about format */ - *fmt = video->fmt; - return 0; -} - -/* - * vpfe_enum_fmt() - enum formats supported on media chain - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_fmtdesc structure - * - * fills v4l2_fmtdesc structure with output format set on adjacent subdev, - * only one format is enumearted as subdevs are already configured - * - * Return 0 if successful, error code otherwise - */ -static int vpfe_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev_format sd_fmt; - struct v4l2_mbus_framefmt mbus; - struct v4l2_subdev *subdev; - struct v4l2_format format; - struct media_pad *remote; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n"); - - /* - * since already subdev pad format is set, - * only one pixel format is available - */ - if (fmt->index > 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n"); - return -EINVAL; - } - /* get the remote pad */ - remote = media_entity_remote_pad(&video->pad); - if (!remote) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote pad for video node\n"); - return -EINVAL; - } - /* get the remote subdev */ - subdev = vpfe_video_remote_subdev(video, NULL); - if (!subdev) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote subdev for video node\n"); - return -EINVAL; - } - sd_fmt.pad = remote->index; - sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - /* get output format of remote subdev */ - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt); - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote subdev for video node\n"); - return ret; - } - /* convert to pix format */ - mbus.code = sd_fmt.format.code; - mbus_to_pix(&mbus, &format.fmt.pix); - /* copy the result */ - fmt->pixelformat = format.fmt.pix.pixelformat; - - return 0; -} - -/* - * vpfe_s_fmt() - set the format on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * validate and set the format on video device - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_format format; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n"); - /* If streaming is started, return error */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n"); - return -EBUSY; - } - /* get adjacent subdev's output pad format */ - ret = __vpfe_video_get_format(video, &format); - if (ret) - return ret; - *fmt = format; - video->fmt = *fmt; - return 0; -} - -/* - * vpfe_try_fmt() - try the format on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * validate the format, update with correct format - * based on output format set on adjacent subdev - * - * Return 0 on success, error code otherwise - */ -static int vpfe_try_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_format format; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n"); - /* get adjacent subdev's output pad format */ - ret = __vpfe_video_get_format(video, &format); - if (ret) - return ret; - - *fmt = format; - return 0; -} - -/* - * vpfe_enum_input() - enum inputs supported on media chain - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_fmtdesc structure - * - * fills v4l2_input structure with input available on media chain, - * only one input is enumearted as media chain is setup by this time - * - * Return 0 if successful, -EINVAL is media chain is invalid - */ -static int vpfe_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n"); - /* enumerate from the subdev user has chosen through mc */ - if (inp->index < sdinfo->num_inputs) { - memcpy(inp, &sdinfo->inputs[inp->index], - sizeof(struct v4l2_input)); - return 0; - } - return -EINVAL; -} - -/* - * vpfe_g_input() - get index of the input which is active - * @file: file pointer - * @priv: void pointer - * @index: pointer to unsigned int - * - * set index with input index which is active - */ -static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n"); - - *index = video->current_input; - return 0; -} - -/* - * vpfe_s_input() - set input which is pointed by input index - * @file: file pointer - * @priv: void pointer - * @index: pointer to unsigned int - * - * set input on external subdev - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_input(struct file *file, void *priv, unsigned int index) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - struct vpfe_route *route; - struct v4l2_input *inps; - u32 output; - u32 input; - int ret; - int i; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - /* - * If streaming is started return device busy - * error - */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n"); - ret = -EBUSY; - goto unlock_out; - } - - sdinfo = video->current_ext_subdev; - if (!sdinfo->registered) { - ret = -EINVAL; - goto unlock_out; - } - if (vpfe_dev->cfg->setup_input && - vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) { - ret = -EFAULT; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "couldn't setup input for %s\n", - sdinfo->module_name); - goto unlock_out; - } - route = &sdinfo->routes[index]; - if (route && sdinfo->can_route) { - input = route->input; - output = route->output; - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - sdinfo->grp_id, video, - s_routing, input, output, 0); - if (ret) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "s_input:error in setting input in decoder\n"); - ret = -EINVAL; - goto unlock_out; - } - } - /* set standards set by subdev in video device */ - for (i = 0; i < sdinfo->num_inputs; i++) { - inps = &sdinfo->inputs[i]; - video->video_dev.tvnorms |= inps->std; - } - video->current_input = index; -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_querystd() - query std which is being input on external subdev - * @file: file pointer - * @priv: void pointer - * @std_id: pointer to v4l2_std_id structure - * - * call external subdev through v4l2_device_call_until_err to - * get the std that is being active. - * - * Return 0 on success, error code otherwise - */ -static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n"); - - ret = mutex_lock_interruptible(&video->lock); - sdinfo = video->current_ext_subdev; - if (ret) - return ret; - /* Call querystd function of decoder device */ - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, querystd, std_id); - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_s_std() - set std on external subdev - * @file: file pointer - * @priv: void pointer - * @std_id: pointer to v4l2_std_id structure - * - * set std pointed by std_id on external subdev by calling it using - * v4l2_device_call_until_err - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); - - /* Call decoder driver function to set the standard */ - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - sdinfo = video->current_ext_subdev; - /* If streaming is started, return device busy error */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n"); - ret = -EBUSY; - goto unlock_out; - } - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, s_std, std_id); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); - video->stdid = V4L2_STD_UNKNOWN; - goto unlock_out; - } - video->stdid = std_id; -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n"); - *tvnorm = video->stdid; - return 0; -} - -/* - * vpfe_enum_dv_timings() - enumerate dv_timings which are supported by - * to external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_enum_dv_timings structure - * - * enum dv_timings's which are supported by external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_enum_dv_timings(struct file *file, void *fh, - struct v4l2_enum_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - timings->pad = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n"); - return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings); -} - -/* - * vpfe_query_dv_timings() - query the dv_timings which is being input - * to external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * get dv_timings which is being input on external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_query_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_dv_timings\n"); - return v4l2_subdev_call(subdev, video, query_dv_timings, timings); -} - -/* - * vpfe_s_dv_timings() - set dv_timings on external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * set dv_timings pointed by timings on external subdev through - * v4l2_device_call_until_err, this configures amplifier also - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_s_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_dv_timings\n"); - - video->stdid = V4L2_STD_UNKNOWN; - return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - video->current_ext_subdev->grp_id, - video, s_dv_timings, timings); -} - -/* - * vpfe_g_dv_timings() - get dv_timings which is set on external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * get dv_timings which is set on external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_g_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_dv_timings\n"); - return v4l2_subdev_call(subdev, video, g_dv_timings, timings); -} - -/* - * Videobuf operations - */ -/* - * vpfe_buffer_queue_setup : Callback function for buffer setup. - * @vq: vb2_queue ptr - * @fmt: v4l2 format - * @nbuffers: ptr to number of buffers requested by application - * @nplanes:: contains number of distinct video planes needed to hold a frame - * @sizes[]: contains the size (in bytes) of each plane. - * @alloc_devs: ptr to allocation context - * - * This callback function is called when reqbuf() is called to adjust - * the buffer nbuffers and buffer size - */ -static int -vpfe_buffer_queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long size; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue_setup\n"); - size = video->fmt.fmt.pix.sizeimage; - - if (vq->num_buffers + *nbuffers < 3) - *nbuffers = 3 - vq->num_buffers; - - *nplanes = 1; - sizes[0] = size; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "nbuffers=%d, size=%lu\n", *nbuffers, size); - return 0; -} - -/* - * vpfe_buffer_prepare : callback function for buffer prepare - * @vb: ptr to vb2_buffer - * - * This is the callback function for buffer prepare when vb2_qbuf() - * function is called. The buffer is prepared and user space virtual address - * or user address is converted into physical address - */ -static int vpfe_buffer_prepare(struct vb2_buffer *vb) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); - - /* Initialize buffer */ - vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage); - if (vb2_plane_vaddr(vb, 0) && - vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) - return -EINVAL; - - addr = vb2_dma_contig_plane_dma_addr(vb, 0); - /* Make sure user addresses are aligned to 32 bytes */ - if (!ALIGN(addr, 32)) - return -EINVAL; - - return 0; -} - -static void vpfe_buffer_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - /* Get the file handle object and device object */ - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - unsigned long flags; - unsigned long empty; - unsigned long addr; - - spin_lock_irqsave(&video->dma_queue_lock, flags); - empty = list_empty(&video->dma_queue); - /* add the buffer to the DMA queue */ - list_add_tail(&buf->list, &video->dma_queue); - spin_unlock_irqrestore(&video->dma_queue_lock, flags); - /* this case happens in case of single shot */ - if (empty && video->started && pipe->state == - VPFE_PIPELINE_STREAM_SINGLESHOT && - video->state == VPFE_VIDEO_BUFFER_NOT_QUEUED) { - spin_lock(&video->dma_queue_lock); - addr = vpfe_video_get_next_buffer(video); - video->ops->queue(vpfe_dev, addr); - - video->state = VPFE_VIDEO_BUFFER_QUEUED; - spin_unlock(&video->dma_queue_lock); - - /* enable h/w each time in single shot */ - if (vpfe_video_is_pipe_ready(pipe)) - vpfe_pipeline_set_stream(pipe, - VPFE_PIPELINE_STREAM_SINGLESHOT); - } -} - -/* vpfe_start_capture() - start streaming on all the subdevs */ -static int vpfe_start_capture(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int ret = 0; - - video->started = 1; - if (vpfe_video_is_pipe_ready(pipe)) - ret = vpfe_pipeline_set_stream(pipe, pipe->state); - - return ret; -} - -static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - int ret; - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - goto streamoff; - - /* Get the next frame from the buffer queue */ - video->cur_frm = video->next_frm = - list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list); - /* Remove buffer from the buffer queue */ - list_del(&video->cur_frm->list); - /* Mark state of the current frame to active */ - video->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - /* Initialize field_id and started member */ - video->field_id = 0; - addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0); - video->ops->queue(vpfe_dev, addr); - video->state = VPFE_VIDEO_BUFFER_QUEUED; - - ret = vpfe_start_capture(video); - if (ret) { - struct vpfe_cap_buffer *buf, *tmp; - - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); - list_for_each_entry_safe(buf, tmp, &video->dma_queue, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); - } - goto unlock_out; - } - - mutex_unlock(&video->lock); - - return ret; -unlock_out: - mutex_unlock(&video->lock); -streamoff: - ret = vb2_streamoff(&video->buffer_queue, video->buffer_queue.type); - return 0; -} - -static int vpfe_buffer_init(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - - INIT_LIST_HEAD(&buf->list); - return 0; -} - -/* abort streaming and wait for last buffer */ -static void vpfe_stop_streaming(struct vb2_queue *vq) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - - /* release all active buffers */ - if (video->cur_frm == video->next_frm) { - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } else { - if (video->cur_frm != NULL) - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - if (video->next_frm != NULL) - vb2_buffer_done(&video->next_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } - - while (!list_empty(&video->dma_queue)) { - video->next_frm = list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - list_del(&video->next_frm->list); - vb2_buffer_done(&video->next_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } -} - -static void vpfe_buf_cleanup(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n"); - if (vb->state == VB2_BUF_STATE_ACTIVE) - list_del_init(&buf->list); -} - -static const struct vb2_ops video_qops = { - .queue_setup = vpfe_buffer_queue_setup, - .buf_init = vpfe_buffer_init, - .buf_prepare = vpfe_buffer_prepare, - .start_streaming = vpfe_start_streaming, - .stop_streaming = vpfe_stop_streaming, - .buf_cleanup = vpfe_buf_cleanup, - .buf_queue = vpfe_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* - * vpfe_reqbufs() - supported REQBUF only once opening - * the device. - */ -static int vpfe_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *req_buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - struct vb2_queue *q; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n"); - - if (req_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - req_buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT){ - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - - if (video->io_usrs != 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); - ret = -EBUSY; - goto unlock_out; - } - video->memory = req_buf->memory; - - /* Initialize videobuf2 queue as per the buffer type */ - q = &video->buffer_queue; - q->type = req_buf->type; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->drv_priv = fh; - q->min_buffers_needed = 1; - q->ops = &video_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct vpfe_cap_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->dev = vpfe_dev->pdev; - q->lock = &video->lock; - - ret = vb2_queue_init(q); - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n"); - goto unlock_out; - } - - fh->io_allowed = 1; - video->io_usrs = 1; - INIT_LIST_HEAD(&video->dma_queue); - ret = vb2_reqbufs(&video->buffer_queue, req_buf); - -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_querybuf() - query buffers for exchange - */ -static int vpfe_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n"); - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - if (video->memory != V4L2_MEMORY_MMAP) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n"); - return -EINVAL; - } - - /* Call vb2_querybuf to get information */ - return vb2_querybuf(&video->buffer_queue, buf); -} - -/* - * vpfe_qbuf() - queue buffers for capture or processing - */ -static int vpfe_qbuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n"); - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - p->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - /* - * If this file handle is not allowed to do IO, - * return error - */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - return vb2_qbuf(&video->buffer_queue, - video->video_dev.v4l2_dev->mdev, p); -} - -/* - * vpfe_dqbuf() - deque buffer which is done with processing - */ -static int vpfe_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n"); - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - return vb2_dqbuf(&video->buffer_queue, - buf, (file->f_flags & O_NONBLOCK)); -} - -/* - * vpfe_streamon() - start streaming - * @file: file pointer - * @priv: void pointer - * @buf_type: enum v4l2_buf_type - * - * queue buffer onto hardware for capture/processing and - * start all the subdevs which are in media chain - * - * Return 0 on success, error code otherwise - */ -static int vpfe_streamon(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_fh *fh = file->private_data; - int ret = -EINVAL; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n"); - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return ret; - } - /* If file handle is not allowed IO, return error */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - /* If buffer queue is empty, return error */ - if (list_empty(&video->buffer_queue.queued_list)) { - v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n"); - return -EIO; - } - /* Validate the pipeline */ - if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret = vpfe_video_validate_pipeline(pipe); - if (ret < 0) - return ret; - } - /* Call vb2_streamon to start streaming */ - return vb2_streamon(&video->buffer_queue, buf_type); -} - -/* - * vpfe_streamoff() - stop streaming - * @file: file pointer - * @priv: void pointer - * @buf_type: enum v4l2_buf_type - * - * stop all the subdevs which are in media chain - * - * Return 0 on success, error code otherwise - */ -static int vpfe_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n"); - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - /* If io is allowed for this file handle, return error */ - if (!fh->io_allowed) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - /* If streaming is not started, return error */ - if (!video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - - vpfe_stop_capture(video); - ret = vb2_streamoff(&video->buffer_queue, buf_type); - mutex_unlock(&video->lock); - - return ret; -} - -/* vpfe capture ioctl operations */ -static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { - .vidioc_querycap = vpfe_querycap, - .vidioc_g_fmt_vid_cap = vpfe_g_fmt, - .vidioc_s_fmt_vid_cap = vpfe_s_fmt, - .vidioc_try_fmt_vid_cap = vpfe_try_fmt, - .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt, - .vidioc_g_fmt_vid_out = vpfe_g_fmt, - .vidioc_s_fmt_vid_out = vpfe_s_fmt, - .vidioc_try_fmt_vid_out = vpfe_try_fmt, - .vidioc_enum_fmt_vid_out = vpfe_enum_fmt, - .vidioc_enum_input = vpfe_enum_input, - .vidioc_g_input = vpfe_g_input, - .vidioc_s_input = vpfe_s_input, - .vidioc_querystd = vpfe_querystd, - .vidioc_s_std = vpfe_s_std, - .vidioc_g_std = vpfe_g_std, - .vidioc_enum_dv_timings = vpfe_enum_dv_timings, - .vidioc_query_dv_timings = vpfe_query_dv_timings, - .vidioc_s_dv_timings = vpfe_s_dv_timings, - .vidioc_g_dv_timings = vpfe_g_dv_timings, - .vidioc_reqbufs = vpfe_reqbufs, - .vidioc_querybuf = vpfe_querybuf, - .vidioc_qbuf = vpfe_qbuf, - .vidioc_dqbuf = vpfe_dqbuf, - .vidioc_streamon = vpfe_streamon, - .vidioc_streamoff = vpfe_streamoff, -}; - -/* VPFE video init function */ -int vpfe_video_init(struct vpfe_video_device *video, const char *name) -{ - const char *direction; - int ret; - - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - direction = "input"; - video->pad.flags = MEDIA_PAD_FL_SOURCE; - video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - break; - - default: - return -EINVAL; - } - /* Initialize field of video device */ - mutex_init(&video->lock); - video->video_dev.release = video_device_release; - video->video_dev.fops = &vpfe_fops; - video->video_dev.ioctl_ops = &vpfe_ioctl_ops; - video->video_dev.minor = -1; - video->video_dev.tvnorms = 0; - video->video_dev.lock = &video->lock; - snprintf(video->video_dev.name, sizeof(video->video_dev.name), - "DAVINCI VIDEO %s %s", name, direction); - - spin_lock_init(&video->irqlock); - spin_lock_init(&video->dma_queue_lock); - ret = media_entity_pads_init(&video->video_dev.entity, - 1, &video->pad); - if (ret < 0) - return ret; - - video_set_drvdata(&video->video_dev, video); - - return 0; -} - -/* vpfe video device register function */ -int vpfe_video_register(struct vpfe_video_device *video, - struct v4l2_device *vdev) -{ - int ret; - - video->video_dev.v4l2_dev = vdev; - - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - video->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE; - else - video->video_dev.device_caps = V4L2_CAP_VIDEO_OUTPUT; - video->video_dev.device_caps |= V4L2_CAP_STREAMING; - ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1); - if (ret < 0) - pr_err("%s: could not register video device (%d)\n", - __func__, ret); - return ret; -} - -/* vpfe video device unregister function */ -void vpfe_video_unregister(struct vpfe_video_device *video) -{ - if (video_is_registered(&video->video_dev)) { - video_unregister_device(&video->video_dev); - media_entity_cleanup(&video->video_dev.entity); - } -} diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h deleted file mode 100644 index 5d01c4883ab4..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.h +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli - * Prabhakar Lad - */ - -#ifndef _DAVINCI_VPFE_VIDEO_H -#define _DAVINCI_VPFE_VIDEO_H - -#include -#include - -struct vpfe_device; - -/* - * struct vpfe_video_operations - VPFE video operations - * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF - * if there was no buffer previously queued. - */ -struct vpfe_video_operations { - int (*queue)(struct vpfe_device *vpfe_dev, unsigned long addr); -}; - -enum vpfe_pipeline_stream_state { - VPFE_PIPELINE_STREAM_STOPPED = 0, - VPFE_PIPELINE_STREAM_CONTINUOUS = 1, - VPFE_PIPELINE_STREAM_SINGLESHOT = 2, -}; - -enum vpfe_video_state { - /* indicates that buffer is not queued */ - VPFE_VIDEO_BUFFER_NOT_QUEUED = 0, - /* indicates that buffer is queued */ - VPFE_VIDEO_BUFFER_QUEUED = 1, -}; - -struct vpfe_pipeline { - /* media pipeline */ - struct media_pipeline *pipe; - struct media_graph graph; - /* state of the pipeline, continuous, - * single-shot or stopped - */ - enum vpfe_pipeline_stream_state state; - /* number of active input video entities */ - unsigned int input_num; - /* number of active output video entities */ - unsigned int output_num; - /* input video nodes in case of single-shot mode */ - struct vpfe_video_device *inputs[10]; - /* capturing video nodes */ - struct vpfe_video_device *outputs[10]; -}; - -#define to_vpfe_pipeline(__e) \ - container_of((__e)->pipe, struct vpfe_pipeline, pipe) - -#define to_vpfe_video(vdev) \ - container_of(vdev, struct vpfe_video_device, video_dev) - -struct vpfe_cap_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; -}; - -struct vpfe_video_device { - /* vpfe device */ - struct vpfe_device *vpfe_dev; - /* video dev */ - struct video_device video_dev; - /* media pad of video entity */ - struct media_pad pad; - /* video operations supported by video device */ - const struct vpfe_video_operations *ops; - /* type of the video buffers used by user */ - enum v4l2_buf_type type; - /* Indicates id of the field which is being captured */ - u32 field_id; - /* pipeline for which video device is part of */ - struct vpfe_pipeline pipe; - /* Indicates whether streaming started */ - u8 started; - /* Indicates state of the stream */ - unsigned int state; - /* current input at the sub device */ - int current_input; - /* - * This field keeps track of type of buffer exchange mechanism - * user has selected - */ - enum v4l2_memory memory; - /* number of open instances of the channel */ - u32 usrs; - /* flag to indicate whether decoder is initialized */ - u8 initialized; - /* skip frame count */ - u8 skip_frame_count; - /* skip frame count init value */ - u8 skip_frame_count_init; - /* time per frame for skipping */ - struct v4l2_fract timeperframe; - /* ptr to currently selected sub device */ - struct vpfe_ext_subdev_info *current_ext_subdev; - /* Pointer pointing to current vpfe_cap_buffer */ - struct vpfe_cap_buffer *cur_frm; - /* Pointer pointing to next vpfe_cap_buffer */ - struct vpfe_cap_buffer *next_frm; - /* Used to store pixel format */ - struct v4l2_format fmt; - struct vb2_queue buffer_queue; - /* Queue of filled frames */ - struct list_head dma_queue; - spinlock_t irqlock; - /* IRQ lock for DMA queue */ - spinlock_t dma_queue_lock; - /* lock used to serialize all video4linux ioctls */ - struct mutex lock; - /* number of users performing IO */ - u32 io_usrs; - /* Currently selected or default standard */ - v4l2_std_id stdid; - /* - * offset where second field starts from the starting of the - * buffer for field separated YCbCr formats - */ - u32 field_off; -}; - -int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe); -void vpfe_video_unregister(struct vpfe_video_device *video); -int vpfe_video_register(struct vpfe_video_device *video, - struct v4l2_device *vdev); -int vpfe_video_init(struct vpfe_video_device *video, const char *name); -void vpfe_video_process_buffer_complete(struct vpfe_video_device *video); -void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video); -void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video); - -#endif /* _DAVINCI_VPFE_VIDEO_H */ -- GitLab From f61c0ca4b402af1ee619e989efadcf678051ee47 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 25 Jul 2019 03:52:19 -0400 Subject: [PATCH 0577/7155] media: vivid: fix typo: use -> user Fix typo in two comments. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index bc2a176937a4..8e1ebc94943e 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -792,7 +792,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (no_error_inj && ccs_cap == -1) ccs_cap = 7; - /* if ccs_cap == -1, then the use can select it using controls */ + /* if ccs_cap == -1, then the user can select it using controls */ if (ccs_cap != -1) { dev->has_crop_cap = ccs_cap & 1; dev->has_compose_cap = ccs_cap & 2; @@ -807,7 +807,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (no_error_inj && ccs_out == -1) ccs_out = 7; - /* if ccs_out == -1, then the use can select it using controls */ + /* if ccs_out == -1, then the user can select it using controls */ if (ccs_out != -1) { dev->has_crop_out = ccs_out & 1; dev->has_compose_out = ccs_out & 2; -- GitLab From 45ffbd15ede6add6e4fb150e4bab7a27cfe62552 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 27 Jun 2019 14:22:30 -0400 Subject: [PATCH 0578/7155] media: ov5645: Remove unneeded regulator_set_voltage() There is no need to call regulator_set_voltage() for each regulator that powers the camera. The voltage value for each regulator should be retrieved from the device tree, so remove the unneeded regulator_set_voltage(). Signed-off-by: Fabio Estevam Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5645.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 124c8df04633..4e302dc15177 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -34,10 +34,6 @@ #include #include -#define OV5645_VOLTAGE_ANALOG 2800000 -#define OV5645_VOLTAGE_DIGITAL_CORE 1500000 -#define OV5645_VOLTAGE_DIGITAL_IO 1800000 - #define OV5645_SYSTEM_CTRL0 0x3008 #define OV5645_SYSTEM_CTRL0_START 0x02 #define OV5645_SYSTEM_CTRL0_STOP 0x42 @@ -1156,42 +1152,18 @@ static int ov5645_probe(struct i2c_client *client, return PTR_ERR(ov5645->io_regulator); } - ret = regulator_set_voltage(ov5645->io_regulator, - OV5645_VOLTAGE_DIGITAL_IO, - OV5645_VOLTAGE_DIGITAL_IO); - if (ret < 0) { - dev_err(dev, "cannot set io voltage\n"); - return ret; - } - ov5645->core_regulator = devm_regulator_get(dev, "vddd"); if (IS_ERR(ov5645->core_regulator)) { dev_err(dev, "cannot get core regulator\n"); return PTR_ERR(ov5645->core_regulator); } - ret = regulator_set_voltage(ov5645->core_regulator, - OV5645_VOLTAGE_DIGITAL_CORE, - OV5645_VOLTAGE_DIGITAL_CORE); - if (ret < 0) { - dev_err(dev, "cannot set core voltage\n"); - return ret; - } - ov5645->analog_regulator = devm_regulator_get(dev, "vdda"); if (IS_ERR(ov5645->analog_regulator)) { dev_err(dev, "cannot get analog regulator\n"); return PTR_ERR(ov5645->analog_regulator); } - ret = regulator_set_voltage(ov5645->analog_regulator, - OV5645_VOLTAGE_ANALOG, - OV5645_VOLTAGE_ANALOG); - if (ret < 0) { - dev_err(dev, "cannot set analog voltage\n"); - return ret; - } - ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(ov5645->enable_gpio)) { dev_err(dev, "cannot get enable gpio\n"); -- GitLab From 4962bb38fb61518c3c5e9c8f4aedcf2e3486fc4b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 27 Jun 2019 14:22:31 -0400 Subject: [PATCH 0579/7155] media: ov5645: Use regulator_bulk() functions The code can be simplified by using the regulator_bulk() functions, so switch to it. Signed-off-by: Fabio Estevam Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5645.c | 94 +++++++++----------------------------- 1 file changed, 21 insertions(+), 73 deletions(-) diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 4e302dc15177..9602b9201b3e 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -58,6 +58,15 @@ #define OV5645_SDE_SAT_U 0x5583 #define OV5645_SDE_SAT_V 0x5584 +/* regulator supplies */ +static const char * const ov5645_supply_name[] = { + "vdddo", /* Digital I/O (1.8V) supply */ + "vdda", /* Analog (2.8V) supply */ + "vddd", /* Digital Core (1.5V) supply */ +}; + +#define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name) + struct reg_value { u16 reg; u8 val; @@ -82,9 +91,7 @@ struct ov5645 { struct v4l2_rect crop; struct clk *xclk; - struct regulator *io_regulator; - struct regulator *core_regulator; - struct regulator *analog_regulator; + struct regulator_bulk_data supplies[OV5645_NUM_SUPPLIES]; const struct ov5645_mode_info *current_mode; @@ -529,55 +536,6 @@ static const struct ov5645_mode_info ov5645_mode_info_data[] = { }, }; -static int ov5645_regulators_enable(struct ov5645 *ov5645) -{ - int ret; - - ret = regulator_enable(ov5645->io_regulator); - if (ret < 0) { - dev_err(ov5645->dev, "set io voltage failed\n"); - return ret; - } - - ret = regulator_enable(ov5645->analog_regulator); - if (ret) { - dev_err(ov5645->dev, "set analog voltage failed\n"); - goto err_disable_io; - } - - ret = regulator_enable(ov5645->core_regulator); - if (ret) { - dev_err(ov5645->dev, "set core voltage failed\n"); - goto err_disable_analog; - } - - return 0; - -err_disable_analog: - regulator_disable(ov5645->analog_regulator); -err_disable_io: - regulator_disable(ov5645->io_regulator); - - return ret; -} - -static void ov5645_regulators_disable(struct ov5645 *ov5645) -{ - int ret; - - ret = regulator_disable(ov5645->core_regulator); - if (ret < 0) - dev_err(ov5645->dev, "core regulator disable failed\n"); - - ret = regulator_disable(ov5645->analog_regulator); - if (ret < 0) - dev_err(ov5645->dev, "analog regulator disable failed\n"); - - ret = regulator_disable(ov5645->io_regulator); - if (ret < 0) - dev_err(ov5645->dev, "io regulator disable failed\n"); -} - static int ov5645_write_reg(struct ov5645 *ov5645, u16 reg, u8 val) { u8 regbuf[3]; @@ -676,15 +634,14 @@ static int ov5645_set_power_on(struct ov5645 *ov5645) { int ret; - ret = ov5645_regulators_enable(ov5645); - if (ret < 0) { + ret = regulator_bulk_enable(OV5645_NUM_SUPPLIES, ov5645->supplies); + if (ret < 0) return ret; - } ret = clk_prepare_enable(ov5645->xclk); if (ret < 0) { dev_err(ov5645->dev, "clk prepare enable failed\n"); - ov5645_regulators_disable(ov5645); + regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies); return ret; } @@ -704,7 +661,7 @@ static void ov5645_set_power_off(struct ov5645 *ov5645) gpiod_set_value_cansleep(ov5645->rst_gpio, 1); gpiod_set_value_cansleep(ov5645->enable_gpio, 0); clk_disable_unprepare(ov5645->xclk); - ov5645_regulators_disable(ov5645); + regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies); } static int ov5645_s_power(struct v4l2_subdev *sd, int on) @@ -1089,6 +1046,7 @@ static int ov5645_probe(struct i2c_client *client, struct device_node *endpoint; struct ov5645 *ov5645; u8 chip_id_high, chip_id_low; + unsigned int i; u32 xclk_freq; int ret; @@ -1146,23 +1104,13 @@ static int ov5645_probe(struct i2c_client *client, return ret; } - ov5645->io_regulator = devm_regulator_get(dev, "vdddo"); - if (IS_ERR(ov5645->io_regulator)) { - dev_err(dev, "cannot get io regulator\n"); - return PTR_ERR(ov5645->io_regulator); - } - - ov5645->core_regulator = devm_regulator_get(dev, "vddd"); - if (IS_ERR(ov5645->core_regulator)) { - dev_err(dev, "cannot get core regulator\n"); - return PTR_ERR(ov5645->core_regulator); - } + for (i = 0; i < OV5645_NUM_SUPPLIES; i++) + ov5645->supplies[i].supply = ov5645_supply_name[i]; - ov5645->analog_regulator = devm_regulator_get(dev, "vdda"); - if (IS_ERR(ov5645->analog_regulator)) { - dev_err(dev, "cannot get analog regulator\n"); - return PTR_ERR(ov5645->analog_regulator); - } + ret = devm_regulator_bulk_get(dev, OV5645_NUM_SUPPLIES, + ov5645->supplies); + if (ret < 0) + return ret; ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(ov5645->enable_gpio)) { -- GitLab From 8791a102ce579346cea9d2f911afef1c1985213c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2019 07:00:34 -0400 Subject: [PATCH 0580/7155] media: i2c: ov5640: Check for devm_gpiod_get_optional() error The power down and reset GPIO are optional, but the return value from devm_gpiod_get_optional() needs to be checked and propagated in the case of error, so that probe deferral can work. Signed-off-by: Fabio Estevam Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5640.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 759d60c6d630..afe7920557a8 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -3022,9 +3022,14 @@ static int ov5640_probe(struct i2c_client *client, /* request optional power down pin */ sensor->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); + if (IS_ERR(sensor->pwdn_gpio)) + return PTR_ERR(sensor->pwdn_gpio); + /* request optional reset pin */ sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(sensor->reset_gpio)) + return PTR_ERR(sensor->reset_gpio); v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops); -- GitLab From 24c8ac890130fda9aa0368dabba1b08d57d3d99e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2019 07:00:35 -0400 Subject: [PATCH 0581/7155] media: i2c: ov5640: Fix the order for enabling regulators According to the OV5640 datasheet the following sequence needs to be followed when powering the OV5640 supplies: - DOVDD - AVDD - DVDD So follow this order inside the ov5640_supply_name[] array, so that the regulator_bulk() functions can enable the regulator in the correct sequence. Signed-off-by: Fabio Estevam Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5640.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index afe7920557a8..4cd246812ae2 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -158,8 +158,8 @@ static const int ov5640_framerates[] = { /* regulator supplies */ static const char * const ov5640_supply_name[] = { "DOVDD", /* Digital I/O (1.8V) supply */ - "DVDD", /* Digital Core (1.5V) supply */ "AVDD", /* Analog (2.8V) supply */ + "DVDD", /* Digital Core (1.5V) supply */ }; #define OV5640_NUM_SUPPLIES ARRAY_SIZE(ov5640_supply_name) -- GitLab From c0a7c0025369b3f3c3d18be76d250024faac6459 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 22 Jul 2019 04:22:20 -0400 Subject: [PATCH 0582/7155] media: dt-bindings: Update bindings for Cadence CSI2TX version 2.1 This patch adds a DT bindings documentation for Cadence CSI2TX v2.1 controller. Signed-off-by: Jan Kotas Acked-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/cdns,csi2tx.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/cdns,csi2tx.txt b/Documentation/devicetree/bindings/media/cdns,csi2tx.txt index 459c6e332f52..751b9edf1247 100644 --- a/Documentation/devicetree/bindings/media/cdns,csi2tx.txt +++ b/Documentation/devicetree/bindings/media/cdns,csi2tx.txt @@ -5,7 +5,8 @@ The Cadence MIPI-CSI2 TX controller is a CSI-2 bridge supporting up to 4 CSI lanes in output, and up to 4 different pixel streams in input. Required properties: - - compatible: must be set to "cdns,csi2tx" + - compatible: must be set to "cdns,csi2tx" or "cdns,csi2tx-1.3" + for version 1.3 of the controller, "cdns,csi2tx-2.1" for v2.1 - reg: base address and size of the memory mapped region - clocks: phandles to the clocks driving the controller - clock-names: must contain: -- GitLab From bf9df90b3557ec6d5d92914da6a61453741d3e13 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 22 Jul 2019 04:22:21 -0400 Subject: [PATCH 0583/7155] media: Add lane checks for Cadence CSI2TX This patch adds lane checks for CSI2TX, to prevent clock lane being used as a data lane. Signed-off-by: Jan Kotas Acked-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/cadence/cdns-csi2tx.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c index 5042d053b94e..232259c71adf 100644 --- a/drivers/media/platform/cadence/cdns-csi2tx.c +++ b/drivers/media/platform/cadence/cdns-csi2tx.c @@ -2,7 +2,7 @@ /* * Driver for Cadence MIPI-CSI2 TX Controller * - * Copyright (C) 2017-2018 Cadence Design Systems Inc. + * Copyright (C) 2017-2019 Cadence Design Systems Inc. */ #include @@ -434,7 +434,7 @@ static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx) { struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; struct device_node *ep; - int ret; + int ret, i; ep = of_graph_get_endpoint_by_regs(csi2tx->dev->of_node, 0, 0); if (!ep) @@ -461,6 +461,15 @@ static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx) goto out; } + for (i = 0; i < csi2tx->num_lanes; i++) { + if (v4l2_ep.bus.mipi_csi2.data_lanes[i] < 1) { + dev_err(csi2tx->dev, "Invalid lane[%d] number: %u\n", + i, v4l2_ep.bus.mipi_csi2.data_lanes[i]); + ret = -EINVAL; + goto out; + } + } + memcpy(csi2tx->lanes, v4l2_ep.bus.mipi_csi2.data_lanes, sizeof(csi2tx->lanes)); -- GitLab From 6ded416d4ac4ecbf104b897661cdfa2cdacf022a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 22 Jul 2019 04:22:22 -0400 Subject: [PATCH 0584/7155] media: Fix Lane mapping in Cadence CSI2TX This patch fixes mapping of lanes in DPHY_CFG register of the controller. In the register, bit 0 means first data lane. In Linux we currently assume lane 0 is clock. Signed-off-by: Jan Kotas Acked-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/cadence/cdns-csi2tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c index 232259c71adf..c72c8a065428 100644 --- a/drivers/media/platform/cadence/cdns-csi2tx.c +++ b/drivers/media/platform/cadence/cdns-csi2tx.c @@ -236,7 +236,7 @@ static int csi2tx_start(struct csi2tx_priv *csi2tx) /* Put our lanes (clock and data) out of reset */ reg = CSI2TX_DPHY_CFG_CLK_RESET | CSI2TX_DPHY_CFG_MODE_LPDT; for (i = 0; i < csi2tx->num_lanes; i++) - reg |= CSI2TX_DPHY_CFG_LANE_RESET(csi2tx->lanes[i]); + reg |= CSI2TX_DPHY_CFG_LANE_RESET(csi2tx->lanes[i] - 1); writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG); udelay(10); @@ -244,7 +244,7 @@ static int csi2tx_start(struct csi2tx_priv *csi2tx) /* Enable our (clock and data) lanes */ reg |= CSI2TX_DPHY_CFG_CLK_ENABLE; for (i = 0; i < csi2tx->num_lanes; i++) - reg |= CSI2TX_DPHY_CFG_LANE_ENABLE(csi2tx->lanes[i]); + reg |= CSI2TX_DPHY_CFG_LANE_ENABLE(csi2tx->lanes[i] - 1); writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG); udelay(10); -- GitLab From 050ff2ad1cca6fe6fcb6edde6e3b91f7e47d1c9c Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 22 Jul 2019 04:22:23 -0400 Subject: [PATCH 0585/7155] media: Add support for Cadence CSI2TX 2.1 This patch adds support for CSI2TX v2.1 version of the controller. Signed-off-by: Jan Kotas Acked-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/cadence/cdns-csi2tx.c | 140 +++++++++++++++---- 1 file changed, 111 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c index c72c8a065428..e4d08acfbb49 100644 --- a/drivers/media/platform/cadence/cdns-csi2tx.c +++ b/drivers/media/platform/cadence/cdns-csi2tx.c @@ -52,6 +52,17 @@ #define CSI2TX_STREAM_IF_CFG_REG(n) (0x100 + (n) * 4) #define CSI2TX_STREAM_IF_CFG_FILL_LEVEL(n) ((n) & 0x1f) +/* CSI2TX V2 Registers */ +#define CSI2TX_V2_DPHY_CFG_REG 0x28 +#define CSI2TX_V2_DPHY_CFG_RESET BIT(16) +#define CSI2TX_V2_DPHY_CFG_CLOCK_MODE BIT(10) +#define CSI2TX_V2_DPHY_CFG_MODE_MASK GENMASK(9, 8) +#define CSI2TX_V2_DPHY_CFG_MODE_LPDT (2 << 8) +#define CSI2TX_V2_DPHY_CFG_MODE_HS (1 << 8) +#define CSI2TX_V2_DPHY_CFG_MODE_ULPS (0 << 8) +#define CSI2TX_V2_DPHY_CFG_CLK_ENABLE BIT(4) +#define CSI2TX_V2_DPHY_CFG_LANE_ENABLE(n) BIT(n) + #define CSI2TX_LANES_MAX 4 #define CSI2TX_STREAMS_MAX 4 @@ -70,6 +81,13 @@ struct csi2tx_fmt { u32 bpp; }; +struct csi2tx_priv; + +/* CSI2TX Variant Operations */ +struct csi2tx_vops { + void (*dphy_setup)(struct csi2tx_priv *csi2tx); +}; + struct csi2tx_priv { struct device *dev; unsigned int count; @@ -82,6 +100,8 @@ struct csi2tx_priv { void __iomem *base; + struct csi2tx_vops *vops; + struct clk *esc_clk; struct clk *p_clk; struct clk *pixel_clk[CSI2TX_STREAMS_MAX]; @@ -209,29 +229,44 @@ static const struct v4l2_subdev_pad_ops csi2tx_pad_ops = { .set_fmt = csi2tx_set_pad_format, }; -static void csi2tx_reset(struct csi2tx_priv *csi2tx) +/* Set Wake Up value in the D-PHY */ +static void csi2tx_dphy_set_wakeup(struct csi2tx_priv *csi2tx) { - writel(CSI2TX_CONFIG_SRST_REQ, csi2tx->base + CSI2TX_CONFIG_REG); - - udelay(10); + writel(CSI2TX_DPHY_CLK_WAKEUP_ULPS_CYCLES(32), + csi2tx->base + CSI2TX_DPHY_CLK_WAKEUP_REG); } -static int csi2tx_start(struct csi2tx_priv *csi2tx) +/* + * Finishes the D-PHY initialization + * reg dphy cfg value to be used + */ +static void csi2tx_dphy_init_finish(struct csi2tx_priv *csi2tx, u32 reg) { - struct media_entity *entity = &csi2tx->subdev.entity; - struct media_link *link; unsigned int i; - u32 reg; - csi2tx_reset(csi2tx); + udelay(10); - writel(CSI2TX_CONFIG_CFG_REQ, csi2tx->base + CSI2TX_CONFIG_REG); + /* Enable our (clock and data) lanes */ + reg |= CSI2TX_DPHY_CFG_CLK_ENABLE; + for (i = 0; i < csi2tx->num_lanes; i++) + reg |= CSI2TX_DPHY_CFG_LANE_ENABLE(csi2tx->lanes[i] - 1); + writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG); udelay(10); - /* Configure our PPI interface with the D-PHY */ - writel(CSI2TX_DPHY_CLK_WAKEUP_ULPS_CYCLES(32), - csi2tx->base + CSI2TX_DPHY_CLK_WAKEUP_REG); + /* Switch to HS mode */ + reg &= ~CSI2TX_DPHY_CFG_MODE_MASK; + writel(reg | CSI2TX_DPHY_CFG_MODE_HS, + csi2tx->base + CSI2TX_DPHY_CFG_REG); +} + +/* Configures D-PHY in CSIv1.3 */ +static void csi2tx_dphy_setup(struct csi2tx_priv *csi2tx) +{ + u32 reg; + unsigned int i; + + csi2tx_dphy_set_wakeup(csi2tx); /* Put our lanes (clock and data) out of reset */ reg = CSI2TX_DPHY_CFG_CLK_RESET | CSI2TX_DPHY_CFG_MODE_LPDT; @@ -239,23 +274,47 @@ static int csi2tx_start(struct csi2tx_priv *csi2tx) reg |= CSI2TX_DPHY_CFG_LANE_RESET(csi2tx->lanes[i] - 1); writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG); - udelay(10); + csi2tx_dphy_init_finish(csi2tx, reg); +} - /* Enable our (clock and data) lanes */ - reg |= CSI2TX_DPHY_CFG_CLK_ENABLE; - for (i = 0; i < csi2tx->num_lanes; i++) - reg |= CSI2TX_DPHY_CFG_LANE_ENABLE(csi2tx->lanes[i] - 1); - writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG); +/* Configures D-PHY in CSIv2 */ +static void csi2tx_v2_dphy_setup(struct csi2tx_priv *csi2tx) +{ + u32 reg; + + csi2tx_dphy_set_wakeup(csi2tx); + + /* Put our lanes (clock and data) out of reset */ + reg = CSI2TX_V2_DPHY_CFG_RESET | CSI2TX_V2_DPHY_CFG_MODE_LPDT; + writel(reg, csi2tx->base + CSI2TX_V2_DPHY_CFG_REG); + + csi2tx_dphy_init_finish(csi2tx, reg); +} + +static void csi2tx_reset(struct csi2tx_priv *csi2tx) +{ + writel(CSI2TX_CONFIG_SRST_REQ, csi2tx->base + CSI2TX_CONFIG_REG); udelay(10); +} - /* Switch to HS mode */ - reg &= ~CSI2TX_DPHY_CFG_MODE_MASK; - writel(reg | CSI2TX_DPHY_CFG_MODE_HS, - csi2tx->base + CSI2TX_DPHY_CFG_REG); +static int csi2tx_start(struct csi2tx_priv *csi2tx) +{ + struct media_entity *entity = &csi2tx->subdev.entity; + struct media_link *link; + unsigned int i; + + csi2tx_reset(csi2tx); + + writel(CSI2TX_CONFIG_CFG_REQ, csi2tx->base + CSI2TX_CONFIG_REG); udelay(10); + if (csi2tx->vops && csi2tx->vops->dphy_setup) { + csi2tx->vops->dphy_setup(csi2tx); + udelay(10); + } + /* * Create a static mapping between the CSI virtual channels * and the input streams. @@ -478,9 +537,35 @@ static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx) return ret; } +static const struct csi2tx_vops csi2tx_vops = { + .dphy_setup = csi2tx_dphy_setup, +}; + +static const struct csi2tx_vops csi2tx_v2_vops = { + .dphy_setup = csi2tx_v2_dphy_setup, +}; + +static const struct of_device_id csi2tx_of_table[] = { + { + .compatible = "cdns,csi2tx", + .data = &csi2tx_vops + }, + { + .compatible = "cdns,csi2tx-1.3", + .data = &csi2tx_vops + }, + { + .compatible = "cdns,csi2tx-2.1", + .data = &csi2tx_v2_vops + }, + { } +}; +MODULE_DEVICE_TABLE(of, csi2tx_of_table); + static int csi2tx_probe(struct platform_device *pdev) { struct csi2tx_priv *csi2tx; + const struct of_device_id *of_id; unsigned int i; int ret; @@ -495,6 +580,9 @@ static int csi2tx_probe(struct platform_device *pdev) if (ret) goto err_free_priv; + of_id = of_match_node(csi2tx_of_table, pdev->dev.of_node); + csi2tx->vops = (struct csi2tx_vops *)of_id->data; + v4l2_subdev_init(&csi2tx->subdev, &csi2tx_subdev_ops); csi2tx->subdev.owner = THIS_MODULE; csi2tx->subdev.dev = &pdev->dev; @@ -552,12 +640,6 @@ static int csi2tx_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id csi2tx_of_table[] = { - { .compatible = "cdns,csi2tx" }, - { }, -}; -MODULE_DEVICE_TABLE(of, csi2tx_of_table); - static struct platform_driver csi2tx_driver = { .probe = csi2tx_probe, .remove = csi2tx_remove, -- GitLab From 913c55a86400e0b3c99164a71a826ffb860c26c4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 15:04:23 -0400 Subject: [PATCH 0586/7155] media: ov2680: fix a typo in a function name All functions in this file starts with 'ov2680_', except ov2860_parse_dt(). This is likely a typo. rename it to 'ov2680_parse_dt()' (6 and 8) Signed-off-by: Christophe JAILLET Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2680.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 164f983c1814..59cdbc33658c 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -1020,7 +1020,7 @@ static int ov2680_check_id(struct ov2680_dev *sensor) return 0; } -static int ov2860_parse_dt(struct ov2680_dev *sensor) +static int ov2680_parse_dt(struct ov2680_dev *sensor) { struct device *dev = ov2680_to_dev(sensor); int ret; @@ -1061,7 +1061,7 @@ static int ov2680_probe(struct i2c_client *client) sensor->i2c_client = client; - ret = ov2860_parse_dt(sensor); + ret = ov2680_parse_dt(sensor); if (ret < 0) return -EINVAL; -- GitLab From bfe655d159af96632f4930c718e0fc5689460f98 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 07:50:14 -0400 Subject: [PATCH 0587/7155] media: pci: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 3 +-- drivers/media/pci/pt1/pt1.c | 6 ++---- drivers/media/pci/pt3/pt3.c | 6 ++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index c1d133e17e4b..50a34bcd4d14 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -2000,8 +2000,7 @@ static int __maybe_unused cio2_suspend(struct device *dev) static int __maybe_unused cio2_resume(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + struct cio2_device *cio2 = dev_get_drvdata(dev); int r = 0; struct cio2_queue *q = cio2->cur_queue; diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index e51c80bc4646..72b191cfeb54 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -1217,8 +1217,7 @@ static void pt1_i2c_init(struct pt1 *pt1) static int pt1_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pt1 *pt1 = pci_get_drvdata(pdev); + struct pt1 *pt1 = dev_get_drvdata(dev); pt1_init_streams(pt1); pt1_disable_ram(pt1); @@ -1230,8 +1229,7 @@ static int pt1_suspend(struct device *dev) static int pt1_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pt1 *pt1 = pci_get_drvdata(pdev); + struct pt1 *pt1 = dev_get_drvdata(dev); int ret; int i; diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c index 7a7afae4c84c..c0bc86793355 100644 --- a/drivers/media/pci/pt3/pt3.c +++ b/drivers/media/pci/pt3/pt3.c @@ -626,8 +626,7 @@ static void pt3_cleanup_adapter(struct pt3_board *pt3, int index) static int pt3_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pt3_board *pt3 = pci_get_drvdata(pdev); + struct pt3_board *pt3 = dev_get_drvdata(dev); int i; struct pt3_adapter *adap; @@ -646,8 +645,7 @@ static int pt3_suspend(struct device *dev) static int pt3_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pt3_board *pt3 = pci_get_drvdata(pdev); + struct pt3_board *pt3 = dev_get_drvdata(dev); int i, ret; struct pt3_adapter *adap; -- GitLab From 3be9cc6ad3faaf403550aea3879743be7d1c307d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 16:21:28 -0400 Subject: [PATCH 0588/7155] media: v4l2-fwnode: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-fwnode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 7e740d332a54..6972c5af25c6 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -163,7 +163,7 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, pr_debug("no lane mapping given, using defaults\n"); } - rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); + rval = fwnode_property_count_u32(fwnode, "data-lanes"); if (rval > 0) { num_data_lanes = min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval); @@ -191,8 +191,7 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, pr_debug("lane %u position %u\n", i, array[i]); } - rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL, - 0); + rval = fwnode_property_count_u32(fwnode, "lane-polarities"); if (rval > 0) { if (rval != 1 + num_data_lanes /* clock+data */) { pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n", @@ -525,8 +524,7 @@ int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode, if (rval < 0) return rval; - rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", - NULL, 0); + rval = fwnode_property_count_u64(fwnode, "link-frequencies"); if (rval > 0) { unsigned int i; -- GitLab From 6ddb094a9f8c451c42bc7c58cfed22275e8a1e38 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 08:22:19 -0400 Subject: [PATCH 0589/7155] media: staging/intel-ipu3: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c index a7372395a101..06a61f31ca50 100644 --- a/drivers/staging/media/ipu3/ipu3.c +++ b/drivers/staging/media/ipu3/ipu3.c @@ -778,8 +778,7 @@ static int __maybe_unused imgu_suspend(struct device *dev) static int __maybe_unused imgu_resume(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct imgu_device *imgu = pci_get_drvdata(pci_dev); + struct imgu_device *imgu = dev_get_drvdata(dev); int r = 0; unsigned int pipe; -- GitLab From 615c164da0eb42cbfb1688cb429cc4d5039db5d8 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 5 Jul 2019 17:14:21 +0300 Subject: [PATCH 0590/7155] intel_th: msu: Introduce buffer interface Introduces a concept of external buffers, which is a mechanism for creating trace sinks that would receive trace data from MSC buffers and transfer it elsewhere. A external buffer can implement its own window allocation/deallocation if it has to. It must provide a callback that's used to notify it when a window fills up, so that it can then start a DMA transaction from that window 'elsewhere'. This window remains in a 'locked' state and won't be used for storing new trace data until the buffer 'unlocks' it with a provided API call, at which point the window can be used again for storing trace data. This relies on a functional "last block" interrupt, so not all versions of Trace Hub can use this feature, which does not reflect on existing users. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190705141425.19894-2-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- .../testing/sysfs-bus-intel_th-devices-msc | 3 +- MAINTAINERS | 1 + drivers/hwtracing/intel_th/msu.c | 388 +++++++++++++++++- drivers/hwtracing/intel_th/msu.h | 20 +- include/linux/intel_th.h | 79 ++++ 5 files changed, 461 insertions(+), 30 deletions(-) create mode 100644 include/linux/intel_th.h diff --git a/Documentation/ABI/testing/sysfs-bus-intel_th-devices-msc b/Documentation/ABI/testing/sysfs-bus-intel_th-devices-msc index f54ae244f3f1..456cb62b384c 100644 --- a/Documentation/ABI/testing/sysfs-bus-intel_th-devices-msc +++ b/Documentation/ABI/testing/sysfs-bus-intel_th-devices-msc @@ -12,7 +12,8 @@ Description: (RW) Configure MSC operating mode: - "single", for contiguous buffer mode (high-order alloc); - "multi", for multiblock mode; - "ExI", for DCI handler mode; - - "debug", for debug mode. + - "debug", for debug mode; + - any of the currently loaded buffer sinks. If operating mode changes, existing buffer is deallocated, provided there are no active users and tracing is not enabled, otherwise the write will fail. diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..c8c506b8423b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8360,6 +8360,7 @@ M: Alexander Shishkin S: Supported F: Documentation/trace/intel_th.rst F: drivers/hwtracing/intel_th/ +F: include/linux/intel_th.h INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) M: Ning Sun diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 8ab28e5fb366..08413e6a075f 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -17,21 +17,48 @@ #include #include #include +#include #include #ifdef CONFIG_X86 #include #endif +#include #include "intel_th.h" #include "msu.h" #define msc_dev(x) (&(x)->thdev->dev) +/* + * Lockout state transitions: + * READY -> INUSE -+-> LOCKED -+-> READY -> etc. + * \-----------/ + * WIN_READY: window can be used by HW + * WIN_INUSE: window is in use + * WIN_LOCKED: window is filled up and is being processed by the buffer + * handling code + * + * All state transitions happen automatically, except for the LOCKED->READY, + * which needs to be signalled by the buffer code by calling + * intel_th_msc_window_unlock(). + * + * When the interrupt handler has to switch to the next window, it checks + * whether it's READY, and if it is, it performs the switch and tracing + * continues. If it's LOCKED, it stops the trace. + */ +enum lockout_state { + WIN_READY = 0, + WIN_INUSE, + WIN_LOCKED +}; + /** * struct msc_window - multiblock mode window descriptor * @entry: window list linkage (msc::win_list) * @pgoff: page offset into the buffer that this window starts at + * @lockout: lockout state, see comment below + * @lo_lock: lockout state serialization * @nr_blocks: number of blocks (pages) in this window * @nr_segs: number of segments in this window (<= @nr_blocks) * @_sgt: array of block descriptors @@ -40,6 +67,8 @@ struct msc_window { struct list_head entry; unsigned long pgoff; + enum lockout_state lockout; + spinlock_t lo_lock; unsigned int nr_blocks; unsigned int nr_segs; struct msc *msc; @@ -77,6 +106,8 @@ struct msc_iter { * struct msc - MSC device representation * @reg_base: register window base address * @thdev: intel_th_device pointer + * @mbuf: MSU buffer, if assigned + * @mbuf_priv MSU buffer's private data, if @mbuf * @win_list: list of windows in multiblock mode * @single_sgt: single mode buffer * @cur_win: current window @@ -100,6 +131,10 @@ struct msc { void __iomem *msu_base; struct intel_th_device *thdev; + const struct msu_buffer *mbuf; + void *mbuf_priv; + + struct work_struct work; struct list_head win_list; struct sg_table single_sgt; struct msc_window *cur_win; @@ -126,6 +161,101 @@ struct msc { unsigned int index; }; +static LIST_HEAD(msu_buffer_list); +static struct mutex msu_buffer_mutex; + +/** + * struct msu_buffer_entry - internal MSU buffer bookkeeping + * @entry: link to msu_buffer_list + * @mbuf: MSU buffer object + * @owner: module that provides this MSU buffer + */ +struct msu_buffer_entry { + struct list_head entry; + const struct msu_buffer *mbuf; + struct module *owner; +}; + +static struct msu_buffer_entry *__msu_buffer_entry_find(const char *name) +{ + struct msu_buffer_entry *mbe; + + lockdep_assert_held(&msu_buffer_mutex); + + list_for_each_entry(mbe, &msu_buffer_list, entry) { + if (!strcmp(mbe->mbuf->name, name)) + return mbe; + } + + return NULL; +} + +static const struct msu_buffer * +msu_buffer_get(const char *name) +{ + struct msu_buffer_entry *mbe; + + mutex_lock(&msu_buffer_mutex); + mbe = __msu_buffer_entry_find(name); + if (mbe && !try_module_get(mbe->owner)) + mbe = NULL; + mutex_unlock(&msu_buffer_mutex); + + return mbe ? mbe->mbuf : NULL; +} + +static void msu_buffer_put(const struct msu_buffer *mbuf) +{ + struct msu_buffer_entry *mbe; + + mutex_lock(&msu_buffer_mutex); + mbe = __msu_buffer_entry_find(mbuf->name); + if (mbe) + module_put(mbe->owner); + mutex_unlock(&msu_buffer_mutex); +} + +int intel_th_msu_buffer_register(const struct msu_buffer *mbuf, + struct module *owner) +{ + struct msu_buffer_entry *mbe; + int ret = 0; + + mbe = kzalloc(sizeof(*mbe), GFP_KERNEL); + if (!mbe) + return -ENOMEM; + + mutex_lock(&msu_buffer_mutex); + if (__msu_buffer_entry_find(mbuf->name)) { + ret = -EEXIST; + kfree(mbe); + goto unlock; + } + + mbe->mbuf = mbuf; + mbe->owner = owner; + list_add_tail(&mbe->entry, &msu_buffer_list); +unlock: + mutex_unlock(&msu_buffer_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(intel_th_msu_buffer_register); + +void intel_th_msu_buffer_unregister(const struct msu_buffer *mbuf) +{ + struct msu_buffer_entry *mbe; + + mutex_lock(&msu_buffer_mutex); + mbe = __msu_buffer_entry_find(mbuf->name); + if (mbe) { + list_del(&mbe->entry); + kfree(mbe); + } + mutex_unlock(&msu_buffer_mutex); +} +EXPORT_SYMBOL_GPL(intel_th_msu_buffer_unregister); + static inline bool msc_block_is_empty(struct msc_block_desc *bdesc) { /* header hasn't been written */ @@ -188,6 +318,25 @@ static struct msc_window *msc_next_window(struct msc_window *win) return list_next_entry(win, entry); } +static size_t msc_win_total_sz(struct msc_window *win) +{ + unsigned int blk; + size_t size = 0; + + for (blk = 0; blk < win->nr_segs; blk++) { + struct msc_block_desc *bdesc = msc_win_block(win, blk); + + if (msc_block_wrapped(bdesc)) + return win->nr_blocks << PAGE_SHIFT; + + size += msc_total_sz(bdesc); + if (msc_block_last_written(bdesc)) + break; + } + + return size; +} + /** * msc_find_window() - find a window matching a given sg_table * @msc: MSC device @@ -527,6 +676,9 @@ static int intel_th_msu_init(struct msc *msc) if (!msc->do_irq) return 0; + if (!msc->mbuf) + return 0; + mintctl = ioread32(msc->msu_base + REG_MSU_MINTCTL); mintctl |= msc->index ? M1BLIE : M0BLIE; iowrite32(mintctl, msc->msu_base + REG_MSU_MINTCTL); @@ -554,6 +706,44 @@ static void intel_th_msu_deinit(struct msc *msc) iowrite32(mintctl, msc->msu_base + REG_MSU_MINTCTL); } +static int msc_win_set_lockout(struct msc_window *win, + enum lockout_state expect, + enum lockout_state new) +{ + enum lockout_state old; + unsigned long flags; + int ret = 0; + + if (!win->msc->mbuf) + return 0; + + spin_lock_irqsave(&win->lo_lock, flags); + old = win->lockout; + + if (old != expect) { + ret = -EINVAL; + dev_warn_ratelimited(msc_dev(win->msc), + "expected lockout state %d, got %d\n", + expect, old); + goto unlock; + } + + win->lockout = new; + +unlock: + spin_unlock_irqrestore(&win->lo_lock, flags); + + if (ret) { + if (expect == WIN_READY && old == WIN_LOCKED) + return -EBUSY; + + /* from intel_th_msc_window_unlock(), don't warn if not locked */ + if (expect == WIN_LOCKED && old == new) + return 0; + } + + return ret; +} /** * msc_configure() - set up MSC hardware * @msc: the MSC device to configure @@ -571,8 +761,12 @@ static int msc_configure(struct msc *msc) if (msc->mode > MSC_MODE_MULTI) return -ENOTSUPP; - if (msc->mode == MSC_MODE_MULTI) + if (msc->mode == MSC_MODE_MULTI) { + if (msc_win_set_lockout(msc->cur_win, WIN_READY, WIN_INUSE)) + return -EBUSY; + msc_buffer_clear_hw_header(msc); + } reg = msc->base_addr >> PAGE_SHIFT; iowrite32(reg, msc->reg_base + REG_MSU_MSC0BAR); @@ -594,10 +788,14 @@ static int msc_configure(struct msc *msc) iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL); + intel_th_msu_init(msc); + msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI; intel_th_trace_enable(msc->thdev); msc->enabled = 1; + if (msc->mbuf && msc->mbuf->activate) + msc->mbuf->activate(msc->mbuf_priv); return 0; } @@ -611,10 +809,17 @@ static int msc_configure(struct msc *msc) */ static void msc_disable(struct msc *msc) { + struct msc_window *win = msc->cur_win; u32 reg; lockdep_assert_held(&msc->buf_mutex); + if (msc->mode == MSC_MODE_MULTI) + msc_win_set_lockout(win, WIN_INUSE, WIN_LOCKED); + + if (msc->mbuf && msc->mbuf->deactivate) + msc->mbuf->deactivate(msc->mbuf_priv); + intel_th_msu_deinit(msc); intel_th_trace_disable(msc->thdev); if (msc->mode == MSC_MODE_SINGLE) { @@ -630,6 +835,11 @@ static void msc_disable(struct msc *msc) reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL); reg &= ~MSC_EN; iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL); + + if (msc->mbuf && msc->mbuf->ready) + msc->mbuf->ready(msc->mbuf_priv, win->sgt, + msc_win_total_sz(win)); + msc->enabled = 0; iowrite32(0, msc->reg_base + REG_MSU_MSC0BAR); @@ -640,6 +850,10 @@ static void msc_disable(struct msc *msc) reg = ioread32(msc->reg_base + REG_MSU_MSC0STS); dev_dbg(msc_dev(msc), "MSCnSTS: %08x\n", reg); + + reg = ioread32(msc->reg_base + REG_MSU_MSUSTS); + reg &= msc->index ? MSUSTS_MSC1BLAST : MSUSTS_MSC0BLAST; + iowrite32(reg, msc->reg_base + REG_MSU_MSUSTS); } static int intel_th_msc_activate(struct intel_th_device *thdev) @@ -856,6 +1070,8 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) win->msc = msc; win->sgt = &win->_sgt; + win->lockout = WIN_READY; + spin_lock_init(&win->lo_lock); if (!list_empty(&msc->win_list)) { struct msc_window *prev = list_last_entry(&msc->win_list, @@ -865,8 +1081,13 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) win->pgoff = prev->pgoff + prev->nr_blocks; } - ret = __msc_buffer_win_alloc(win, nr_blocks); - if (ret < 0) + if (msc->mbuf && msc->mbuf->alloc_window) + ret = msc->mbuf->alloc_window(msc->mbuf_priv, &win->sgt, + nr_blocks << PAGE_SHIFT); + else + ret = __msc_buffer_win_alloc(win, nr_blocks); + + if (ret <= 0) goto err_nomem; msc_buffer_set_uc(win, ret); @@ -925,7 +1146,10 @@ static void msc_buffer_win_free(struct msc *msc, struct msc_window *win) msc_buffer_set_wb(win); - __msc_buffer_win_free(msc, win); + if (msc->mbuf && msc->mbuf->free_window) + msc->mbuf->free_window(msc->mbuf_priv, win->sgt); + else + __msc_buffer_win_free(msc, win); kfree(win); } @@ -1462,18 +1686,77 @@ static void msc_win_switch(struct msc *msc) intel_th_trace_switch(msc->thdev); } +/** + * intel_th_msc_window_unlock - put the window back in rotation + * @dev: MSC device to which this relates + * @sgt: buffer's sg_table for the window, does nothing if NULL + */ +void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt) +{ + struct msc *msc = dev_get_drvdata(dev); + struct msc_window *win; + + if (!sgt) + return; + + win = msc_find_window(msc, sgt, false); + if (!win) + return; + + msc_win_set_lockout(win, WIN_LOCKED, WIN_READY); +} +EXPORT_SYMBOL_GPL(intel_th_msc_window_unlock); + +static void msc_work(struct work_struct *work) +{ + struct msc *msc = container_of(work, struct msc, work); + + intel_th_msc_deactivate(msc->thdev); +} + static irqreturn_t intel_th_msc_interrupt(struct intel_th_device *thdev) { struct msc *msc = dev_get_drvdata(&thdev->dev); u32 msusts = ioread32(msc->msu_base + REG_MSU_MSUSTS); u32 mask = msc->index ? MSUSTS_MSC1BLAST : MSUSTS_MSC0BLAST; + struct msc_window *win, *next_win; - if (!(msusts & mask)) { - if (msc->enabled) - return IRQ_HANDLED; + if (!msc->do_irq || !msc->mbuf) return IRQ_NONE; + + msusts &= mask; + + if (!msusts) + return msc->enabled ? IRQ_HANDLED : IRQ_NONE; + + iowrite32(msusts, msc->msu_base + REG_MSU_MSUSTS); + + if (!msc->enabled) + return IRQ_NONE; + + /* grab the window before we do the switch */ + win = msc->cur_win; + if (!win) + return IRQ_HANDLED; + next_win = msc_next_window(win); + if (!next_win) + return IRQ_HANDLED; + + /* next window: if READY, proceed, if LOCKED, stop the trace */ + if (msc_win_set_lockout(next_win, WIN_READY, WIN_INUSE)) { + schedule_work(&msc->work); + return IRQ_HANDLED; } + /* current window: INUSE -> LOCKED */ + msc_win_set_lockout(win, WIN_INUSE, WIN_LOCKED); + + msc_win_switch(msc); + + if (msc->mbuf && msc->mbuf->ready) + msc->mbuf->ready(msc->mbuf_priv, win->sgt, + msc_win_total_sz(win)); + return IRQ_HANDLED; } @@ -1511,21 +1794,43 @@ wrap_store(struct device *dev, struct device_attribute *attr, const char *buf, static DEVICE_ATTR_RW(wrap); +static void msc_buffer_unassign(struct msc *msc) +{ + lockdep_assert_held(&msc->buf_mutex); + + if (!msc->mbuf) + return; + + msc->mbuf->unassign(msc->mbuf_priv); + msu_buffer_put(msc->mbuf); + msc->mbuf_priv = NULL; + msc->mbuf = NULL; +} + static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct msc *msc = dev_get_drvdata(dev); + const char *mode = msc_mode[msc->mode]; + ssize_t ret; + + mutex_lock(&msc->buf_mutex); + if (msc->mbuf) + mode = msc->mbuf->name; + ret = scnprintf(buf, PAGE_SIZE, "%s\n", mode); + mutex_unlock(&msc->buf_mutex); - return scnprintf(buf, PAGE_SIZE, "%s\n", msc_mode[msc->mode]); + return ret; } static ssize_t mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { + const struct msu_buffer *mbuf = NULL; struct msc *msc = dev_get_drvdata(dev); size_t len = size; - char *cp; + char *cp, *mode; int i, ret; if (!capable(CAP_SYS_RAWIO)) @@ -1535,17 +1840,59 @@ mode_store(struct device *dev, struct device_attribute *attr, const char *buf, if (cp) len = cp - buf; - for (i = 0; i < ARRAY_SIZE(msc_mode); i++) - if (!strncmp(msc_mode[i], buf, len)) - goto found; + mode = kstrndup(buf, len, GFP_KERNEL); + i = match_string(msc_mode, ARRAY_SIZE(msc_mode), mode); + if (i >= 0) + goto found; + + /* Buffer sinks only work with a usable IRQ */ + if (!msc->do_irq) { + kfree(mode); + return -EINVAL; + } + + mbuf = msu_buffer_get(mode); + kfree(mode); + if (mbuf) + goto found; return -EINVAL; found: mutex_lock(&msc->buf_mutex); + ret = 0; + + /* Same buffer: do nothing */ + if (mbuf && mbuf == msc->mbuf) { + /* put the extra reference we just got */ + msu_buffer_put(mbuf); + goto unlock; + } + ret = msc_buffer_unlocked_free_unless_used(msc); - if (!ret) - msc->mode = i; + if (ret) + goto unlock; + + if (mbuf) { + void *mbuf_priv = mbuf->assign(dev, &i); + + if (!mbuf_priv) { + ret = -ENOMEM; + goto unlock; + } + + msc_buffer_unassign(msc); + msc->mbuf_priv = mbuf_priv; + msc->mbuf = mbuf; + } else { + msc_buffer_unassign(msc); + } + + msc->mode = i; + +unlock: + if (ret && mbuf) + msu_buffer_put(mbuf); mutex_unlock(&msc->buf_mutex); return ret ? ret : size; @@ -1667,7 +2014,12 @@ win_switch_store(struct device *dev, struct device_attribute *attr, return -EINVAL; mutex_lock(&msc->buf_mutex); - if (msc->mode != MSC_MODE_MULTI) + /* + * Window switch can only happen in the "multi" mode. + * If a external buffer is engaged, they have the full + * control over window switching. + */ + if (msc->mode != MSC_MODE_MULTI || msc->mbuf) ret = -ENOTSUPP; else msc_win_switch(msc); @@ -1720,10 +2072,7 @@ static int intel_th_msc_probe(struct intel_th_device *thdev) msc->reg_base = base + msc->index * 0x100; msc->msu_base = base; - err = intel_th_msu_init(msc); - if (err) - return err; - + INIT_WORK(&msc->work, msc_work); err = intel_th_msc_init(msc); if (err) return err; @@ -1739,7 +2088,6 @@ static void intel_th_msc_remove(struct intel_th_device *thdev) int ret; intel_th_msc_deactivate(thdev); - intel_th_msu_deinit(msc); /* * Buffers should not be used at this point except if the diff --git a/drivers/hwtracing/intel_th/msu.h b/drivers/hwtracing/intel_th/msu.h index 574c16004cb2..3f527dd4d727 100644 --- a/drivers/hwtracing/intel_th/msu.h +++ b/drivers/hwtracing/intel_th/msu.h @@ -44,14 +44,6 @@ enum { #define M0BLIE BIT(16) #define M1BLIE BIT(24) -/* MSC operating modes (MSC_MODE) */ -enum { - MSC_MODE_SINGLE = 0, - MSC_MODE_MULTI, - MSC_MODE_EXI, - MSC_MODE_DEBUG, -}; - /* MSCnSTS bits */ #define MSCSTS_WRAPSTAT BIT(1) /* Wrap occurred */ #define MSCSTS_PLE BIT(2) /* Pipeline Empty */ @@ -93,6 +85,16 @@ static inline unsigned long msc_data_sz(struct msc_block_desc *bdesc) return bdesc->valid_dw * 4 - MSC_BDESC; } +static inline unsigned long msc_total_sz(struct msc_block_desc *bdesc) +{ + return bdesc->valid_dw * 4; +} + +static inline unsigned long msc_block_sz(struct msc_block_desc *bdesc) +{ + return bdesc->block_sz * 64 - MSC_BDESC; +} + static inline bool msc_block_wrapped(struct msc_block_desc *bdesc) { if (bdesc->hw_tag & (MSC_HW_TAG_BLOCKWRAP | MSC_HW_TAG_WINWRAP)) @@ -104,7 +106,7 @@ static inline bool msc_block_wrapped(struct msc_block_desc *bdesc) static inline bool msc_block_last_written(struct msc_block_desc *bdesc) { if ((bdesc->hw_tag & MSC_HW_TAG_ENDBIT) || - (msc_data_sz(bdesc) != DATA_IN_PAGE)) + (msc_data_sz(bdesc) != msc_block_sz(bdesc))) return true; return false; diff --git a/include/linux/intel_th.h b/include/linux/intel_th.h new file mode 100644 index 000000000000..9b7f4c22499c --- /dev/null +++ b/include/linux/intel_th.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Intel(R) Trace Hub data structures for implementing buffer sinks. + * + * Copyright (C) 2019 Intel Corporation. + */ + +#ifndef _INTEL_TH_H_ +#define _INTEL_TH_H_ + +#include + +/* MSC operating modes (MSC_MODE) */ +enum { + MSC_MODE_SINGLE = 0, + MSC_MODE_MULTI, + MSC_MODE_EXI, + MSC_MODE_DEBUG, +}; + +struct msu_buffer { + const char *name; + /* + * ->assign() called when buffer 'mode' is set to this driver + * (aka mode_store()) + * @device: struct device * of the msc + * @mode: allows the driver to set HW mode (see the enum above) + * Returns: a pointer to a private structure associated with this + * msc or NULL in case of error. This private structure + * will then be passed into all other callbacks. + */ + void *(*assign)(struct device *dev, int *mode); + /* ->unassign(): some other mode is selected, clean up */ + void (*unassign)(void *priv); + /* + * ->alloc_window(): allocate memory for the window of a given + * size + * @sgt: pointer to sg_table, can be overridden by the buffer + * driver, or kept intact + * Returns: number of sg table entries <= number of pages; + * 0 is treated as an allocation failure. + */ + int (*alloc_window)(void *priv, struct sg_table **sgt, + size_t size); + void (*free_window)(void *priv, struct sg_table *sgt); + /* ->activate(): trace has started */ + void (*activate)(void *priv); + /* ->deactivate(): trace is about to stop */ + void (*deactivate)(void *priv); + /* + * ->ready(): window @sgt is filled up to the last block OR + * tracing is stopped by the user; this window contains + * @bytes data. The window in question transitions into + * the "LOCKED" state, indicating that it can't be used + * by hardware. To clear this state and make the window + * available to the hardware again, call + * intel_th_msc_window_unlock(). + */ + int (*ready)(void *priv, struct sg_table *sgt, size_t bytes); +}; + +int intel_th_msu_buffer_register(const struct msu_buffer *mbuf, + struct module *owner); +void intel_th_msu_buffer_unregister(const struct msu_buffer *mbuf); +void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt); + +#define module_intel_th_msu_buffer(__buffer) \ +static int __init __buffer##_init(void) \ +{ \ + return intel_th_msu_buffer_register(&(__buffer), THIS_MODULE); \ +} \ +module_init(__buffer##_init); \ +static void __exit __buffer##_exit(void) \ +{ \ + intel_th_msu_buffer_unregister(&(__buffer)); \ +} \ +module_exit(__buffer##_exit); + +#endif /* _INTEL_TH_H_ */ -- GitLab From f220df66f67684246ae1bf4a4e479efc7c2f325a Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 5 Jul 2019 17:14:22 +0300 Subject: [PATCH 0591/7155] intel_th: msu-sink: An example msu buffer "sink" This patch adds an example MSU buffer "sink", which consumes trace data from MSC buffers. Functionally, it acts similarly to "multi" mode with automatic window switching. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190705141425.19894-3-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/Makefile | 3 + drivers/hwtracing/intel_th/msu-sink.c | 116 ++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 drivers/hwtracing/intel_th/msu-sink.c diff --git a/drivers/hwtracing/intel_th/Makefile b/drivers/hwtracing/intel_th/Makefile index d9252fa8d9ca..b63eb8f309ad 100644 --- a/drivers/hwtracing/intel_th/Makefile +++ b/drivers/hwtracing/intel_th/Makefile @@ -20,3 +20,6 @@ intel_th_msu-y := msu.o obj-$(CONFIG_INTEL_TH_PTI) += intel_th_pti.o intel_th_pti-y := pti.o + +obj-$(CONFIG_INTEL_TH_MSU) += intel_th_msu_sink.o +intel_th_msu_sink-y := msu-sink.o diff --git a/drivers/hwtracing/intel_th/msu-sink.c b/drivers/hwtracing/intel_th/msu-sink.c new file mode 100644 index 000000000000..2c7f5116be12 --- /dev/null +++ b/drivers/hwtracing/intel_th/msu-sink.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * An example software sink buffer for Intel TH MSU. + * + * Copyright (C) 2019 Intel Corporation. + */ + +#include +#include +#include +#include +#include + +#define MAX_SGTS 16 + +struct msu_sink_private { + struct device *dev; + struct sg_table **sgts; + unsigned int nr_sgts; +}; + +static void *msu_sink_assign(struct device *dev, int *mode) +{ + struct msu_sink_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + + priv->sgts = kcalloc(MAX_SGTS, sizeof(void *), GFP_KERNEL); + if (!priv->sgts) { + kfree(priv); + return NULL; + } + + priv->dev = dev; + *mode = MSC_MODE_MULTI; + + return priv; +} + +static void msu_sink_unassign(void *data) +{ + struct msu_sink_private *priv = data; + + kfree(priv->sgts); + kfree(priv); +} + +/* See also: msc.c: __msc_buffer_win_alloc() */ +static int msu_sink_alloc_window(void *data, struct sg_table **sgt, size_t size) +{ + struct msu_sink_private *priv = data; + unsigned int nents; + struct scatterlist *sg_ptr; + void *block; + int ret, i; + + if (priv->nr_sgts == MAX_SGTS) + return -ENOMEM; + + nents = DIV_ROUND_UP(size, PAGE_SIZE); + + ret = sg_alloc_table(*sgt, nents, GFP_KERNEL); + if (ret) + return -ENOMEM; + + priv->sgts[priv->nr_sgts++] = *sgt; + + for_each_sg((*sgt)->sgl, sg_ptr, nents, i) { + block = dma_alloc_coherent(priv->dev->parent->parent, + PAGE_SIZE, &sg_dma_address(sg_ptr), + GFP_KERNEL); + sg_set_buf(sg_ptr, block, PAGE_SIZE); + } + + return nents; +} + +/* See also: msc.c: __msc_buffer_win_free() */ +static void msu_sink_free_window(void *data, struct sg_table *sgt) +{ + struct msu_sink_private *priv = data; + struct scatterlist *sg_ptr; + int i; + + for_each_sg(sgt->sgl, sg_ptr, sgt->nents, i) { + dma_free_coherent(priv->dev->parent->parent, PAGE_SIZE, + sg_virt(sg_ptr), sg_dma_address(sg_ptr)); + } + + sg_free_table(sgt); + priv->nr_sgts--; +} + +static int msu_sink_ready(void *data, struct sg_table *sgt, size_t bytes) +{ + struct msu_sink_private *priv = data; + + intel_th_msc_window_unlock(priv->dev, sgt); + + return 0; +} + +static const struct msu_buffer sink_mbuf = { + .name = "sink", + .assign = msu_sink_assign, + .unassign = msu_sink_unassign, + .alloc_window = msu_sink_alloc_window, + .free_window = msu_sink_free_window, + .ready = msu_sink_ready, +}; + +module_intel_th_msu_buffer(sink_mbuf); + +MODULE_LICENSE("GPL v2"); -- GitLab From 57b69a1f66486d632e188fb167950fb4bdf84221 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 5 Jul 2019 17:14:23 +0300 Subject: [PATCH 0592/7155] intel_th: msu: Get rid of the window size limit Currently, the window size is limited to the maximum number of sg entries in one table. This is because the code addresses individual blocks within the window by their numeric index. In reality, though, the blocks most often are iterated through sequentially. By rewriting the logic to use sg pointers instead of block indices we loose the necessity to dereference them directly and gain the ability to use multiple chained tables if necessary. Get rid of the limitation by replacing index-based block accesses with sequential block accesses. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190705141425.19894-4-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/msu.c | 139 +++++++++++++++---------------- 1 file changed, 68 insertions(+), 71 deletions(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 08413e6a075f..a6c0eb09c515 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -95,8 +95,8 @@ struct msc_iter { struct msc_window *start_win; struct msc_window *win; unsigned long offset; - int start_block; - int block; + struct scatterlist *start_block; + struct scatterlist *block; unsigned int block_off; unsigned int wrap_count; unsigned int eof; @@ -269,28 +269,25 @@ static inline bool msc_block_is_empty(struct msc_block_desc *bdesc) return false; } -static inline struct msc_block_desc * -msc_win_block(struct msc_window *win, unsigned int block) +static inline struct scatterlist *msc_win_base_sg(struct msc_window *win) { - return sg_virt(&win->sgt->sgl[block]); + return win->sgt->sgl; } -static inline size_t -msc_win_actual_bsz(struct msc_window *win, unsigned int block) +static inline struct msc_block_desc *msc_win_base(struct msc_window *win) { - return win->sgt->sgl[block].length; + return sg_virt(msc_win_base_sg(win)); } -static inline dma_addr_t -msc_win_baddr(struct msc_window *win, unsigned int block) +static inline dma_addr_t msc_win_base_dma(struct msc_window *win) { - return sg_dma_address(&win->sgt->sgl[block]); + return sg_dma_address(msc_win_base_sg(win)); } static inline unsigned long -msc_win_bpfn(struct msc_window *win, unsigned int block) +msc_win_base_pfn(struct msc_window *win) { - return msc_win_baddr(win, block) >> PAGE_SHIFT; + return PFN_DOWN(msc_win_base_dma(win)); } /** @@ -320,11 +317,12 @@ static struct msc_window *msc_next_window(struct msc_window *win) static size_t msc_win_total_sz(struct msc_window *win) { + struct scatterlist *sg; unsigned int blk; size_t size = 0; - for (blk = 0; blk < win->nr_segs; blk++) { - struct msc_block_desc *bdesc = msc_win_block(win, blk); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { + struct msc_block_desc *bdesc = sg_virt(sg); if (msc_block_wrapped(bdesc)) return win->nr_blocks << PAGE_SHIFT; @@ -365,7 +363,7 @@ msc_find_window(struct msc *msc, struct sg_table *sgt, bool nonempty) found++; /* skip the empty ones */ - if (nonempty && msc_block_is_empty(msc_win_block(win, 0))) + if (nonempty && msc_block_is_empty(msc_win_base(win))) continue; if (found) @@ -399,44 +397,38 @@ static struct msc_window *msc_oldest_window(struct msc *msc) } /** - * msc_win_oldest_block() - locate the oldest block in a given window + * msc_win_oldest_sg() - locate the oldest block in a given window * @win: window to look at * * Return: index of the block with the oldest data */ -static unsigned int msc_win_oldest_block(struct msc_window *win) +static struct scatterlist *msc_win_oldest_sg(struct msc_window *win) { unsigned int blk; - struct msc_block_desc *bdesc = msc_win_block(win, 0); + struct scatterlist *sg; + struct msc_block_desc *bdesc = msc_win_base(win); /* without wrapping, first block is the oldest */ if (!msc_block_wrapped(bdesc)) - return 0; + return msc_win_base_sg(win); /* * with wrapping, last written block contains both the newest and the * oldest data for this window. */ - for (blk = 0; blk < win->nr_segs; blk++) { - bdesc = msc_win_block(win, blk); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { + struct msc_block_desc *bdesc = sg_virt(sg); if (msc_block_last_written(bdesc)) - return blk; + return sg; } - return 0; + return msc_win_base_sg(win); } static struct msc_block_desc *msc_iter_bdesc(struct msc_iter *iter) { - return msc_win_block(iter->win, iter->block); -} - -static void msc_iter_init(struct msc_iter *iter) -{ - memset(iter, 0, sizeof(*iter)); - iter->start_block = -1; - iter->block = -1; + return sg_virt(iter->block); } static struct msc_iter *msc_iter_install(struct msc *msc) @@ -461,7 +453,6 @@ static struct msc_iter *msc_iter_install(struct msc *msc) goto unlock; } - msc_iter_init(iter); iter->msc = msc; list_add_tail(&iter->entry, &msc->iter_list); @@ -482,10 +473,10 @@ static void msc_iter_remove(struct msc_iter *iter, struct msc *msc) static void msc_iter_block_start(struct msc_iter *iter) { - if (iter->start_block != -1) + if (iter->start_block) return; - iter->start_block = msc_win_oldest_block(iter->win); + iter->start_block = msc_win_oldest_sg(iter->win); iter->block = iter->start_block; iter->wrap_count = 0; @@ -509,7 +500,7 @@ static int msc_iter_win_start(struct msc_iter *iter, struct msc *msc) return -EINVAL; iter->win = iter->start_win; - iter->start_block = -1; + iter->start_block = NULL; msc_iter_block_start(iter); @@ -519,7 +510,7 @@ static int msc_iter_win_start(struct msc_iter *iter, struct msc *msc) static int msc_iter_win_advance(struct msc_iter *iter) { iter->win = msc_next_window(iter->win); - iter->start_block = -1; + iter->start_block = NULL; if (iter->win == iter->start_win) { iter->eof++; @@ -549,8 +540,10 @@ static int msc_iter_block_advance(struct msc_iter *iter) return msc_iter_win_advance(iter); /* block advance */ - if (++iter->block == iter->win->nr_segs) - iter->block = 0; + if (sg_is_last(iter->block)) + iter->block = msc_win_base_sg(iter->win); + else + iter->block = sg_next(iter->block); /* no wrapping, sanity check in case there is no last written block */ if (!iter->wrap_count && iter->block == iter->start_block) @@ -655,14 +648,15 @@ msc_buffer_iterate(struct msc_iter *iter, size_t size, void *data, static void msc_buffer_clear_hw_header(struct msc *msc) { struct msc_window *win; + struct scatterlist *sg; list_for_each_entry(win, &msc->win_list, entry) { unsigned int blk; size_t hw_sz = sizeof(struct msc_block_desc) - offsetof(struct msc_block_desc, hw_tag); - for (blk = 0; blk < win->nr_segs; blk++) { - struct msc_block_desc *bdesc = msc_win_block(win, blk); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { + struct msc_block_desc *bdesc = sg_virt(sg); memset(&bdesc->hw_tag, 0, hw_sz); } @@ -1005,10 +999,9 @@ static int __msc_buffer_win_alloc(struct msc_window *win, return nr_segs; err_nomem: - for (i--; i >= 0; i--) + for_each_sg(win->sgt->sgl, sg_ptr, i, ret) dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE, - msc_win_block(win, i), - msc_win_baddr(win, i)); + sg_virt(sg_ptr), sg_dma_address(sg_ptr)); sg_free_table(win->sgt); @@ -1018,20 +1011,26 @@ static int __msc_buffer_win_alloc(struct msc_window *win, #ifdef CONFIG_X86 static void msc_buffer_set_uc(struct msc_window *win, unsigned int nr_segs) { + struct scatterlist *sg_ptr; int i; - for (i = 0; i < nr_segs; i++) + for_each_sg(win->sgt->sgl, sg_ptr, nr_segs, i) { /* Set the page as uncached */ - set_memory_uc((unsigned long)msc_win_block(win, i), 1); + set_memory_uc((unsigned long)sg_virt(sg_ptr), + PFN_DOWN(sg_ptr->length)); + } } static void msc_buffer_set_wb(struct msc_window *win) { + struct scatterlist *sg_ptr; int i; - for (i = 0; i < win->nr_segs; i++) + for_each_sg(win->sgt->sgl, sg_ptr, win->nr_segs, i) { /* Reset the page to write-back */ - set_memory_wb((unsigned long)msc_win_block(win, i), 1); + set_memory_wb((unsigned long)sg_virt(sg_ptr), + PFN_DOWN(sg_ptr->length)); + } } #else /* !X86 */ static inline void @@ -1057,13 +1056,6 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) if (!nr_blocks) return 0; - /* - * This limitation hold as long as we need random access to the - * block. When that changes, this can go away. - */ - if (nr_blocks > SG_MAX_SINGLE_ALLOC) - return -EINVAL; - win = kzalloc(sizeof(*win), GFP_KERNEL); if (!win) return -ENOMEM; @@ -1096,8 +1088,8 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) win->nr_blocks = nr_blocks; if (list_empty(&msc->win_list)) { - msc->base = msc_win_block(win, 0); - msc->base_addr = msc_win_baddr(win, 0); + msc->base = msc_win_base(win); + msc->base_addr = msc_win_base_dma(win); msc->cur_win = win; } @@ -1114,14 +1106,15 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win) { + struct scatterlist *sg; int i; - for (i = 0; i < win->nr_segs; i++) { - struct page *page = sg_page(&win->sgt->sgl[i]); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) { + struct page *page = sg_page(sg); page->mapping = NULL; dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE, - msc_win_block(win, i), msc_win_baddr(win, i)); + sg_virt(sg), sg_dma_address(sg)); } sg_free_table(win->sgt); } @@ -1167,6 +1160,7 @@ static void msc_buffer_relink(struct msc *msc) /* call with msc::mutex locked */ list_for_each_entry(win, &msc->win_list, entry) { + struct scatterlist *sg; unsigned int blk; u32 sw_tag = 0; @@ -1182,12 +1176,12 @@ static void msc_buffer_relink(struct msc *msc) next_win = list_next_entry(win, entry); } - for (blk = 0; blk < win->nr_segs; blk++) { - struct msc_block_desc *bdesc = msc_win_block(win, blk); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { + struct msc_block_desc *bdesc = sg_virt(sg); memset(bdesc, 0, sizeof(*bdesc)); - bdesc->next_win = msc_win_bpfn(next_win, 0); + bdesc->next_win = msc_win_base_pfn(next_win); /* * Similarly to last window, last block should point @@ -1195,13 +1189,15 @@ static void msc_buffer_relink(struct msc *msc) */ if (blk == win->nr_segs - 1) { sw_tag |= MSC_SW_TAG_LASTBLK; - bdesc->next_blk = msc_win_bpfn(win, 0); + bdesc->next_blk = msc_win_base_pfn(win); } else { - bdesc->next_blk = msc_win_bpfn(win, blk + 1); + dma_addr_t addr = sg_dma_address(sg_next(sg)); + + bdesc->next_blk = PFN_DOWN(addr); } bdesc->sw_tag = sw_tag; - bdesc->block_sz = msc_win_actual_bsz(win, blk) / 64; + bdesc->block_sz = sg->length / 64; } } @@ -1360,6 +1356,7 @@ static int msc_buffer_free_unless_used(struct msc *msc) static struct page *msc_buffer_get_page(struct msc *msc, unsigned long pgoff) { struct msc_window *win; + struct scatterlist *sg; unsigned int blk; if (msc->mode == MSC_MODE_SINGLE) @@ -1374,9 +1371,9 @@ static struct page *msc_buffer_get_page(struct msc *msc, unsigned long pgoff) found: pgoff -= win->pgoff; - for (blk = 0; blk < win->nr_segs; blk++) { - struct page *page = sg_page(&win->sgt->sgl[blk]); - size_t pgsz = PFN_DOWN(msc_win_actual_bsz(win, blk)); + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { + struct page *page = sg_page(sg); + size_t pgsz = PFN_DOWN(sg->length); if (pgoff < pgsz) return page + pgoff; @@ -1680,8 +1677,8 @@ static void msc_win_switch(struct msc *msc) else msc->cur_win = list_next_entry(msc->cur_win, entry); - msc->base = msc_win_block(msc->cur_win, 0); - msc->base_addr = msc_win_baddr(msc->cur_win, 0); + msc->base = msc_win_base(msc->cur_win); + msc->base_addr = msc_win_base_dma(msc->cur_win); intel_th_trace_switch(msc->thdev); } -- GitLab From ed5207afc580937cd6cc671357fe1119f1b5b0f5 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 5 Jul 2019 17:14:24 +0300 Subject: [PATCH 0593/7155] intel_th: msu: Prevent freeing buffers while locked windows exist We already prevent freeing buffers via sysfs interface in case there are existing users or if trace is active. Treat the existence of locked windows similarly and return -EBUSY on attempts to free the buffer. When the last window is unlocked, the freeing will succeed. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190705141425.19894-5-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/msu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index a6c0eb09c515..b200d9d1c7a0 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -724,6 +724,11 @@ static int msc_win_set_lockout(struct msc_window *win, win->lockout = new; + if (old == expect && new == WIN_LOCKED) + atomic_inc(&win->msc->user_count); + else if (old == expect && old == WIN_LOCKED) + atomic_dec(&win->msc->user_count); + unlock: spin_unlock_irqrestore(&win->lo_lock, flags); -- GitLab From 092f47c383adbff4d873dcb7f0887954bd407a08 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 5 Jul 2019 17:14:25 +0300 Subject: [PATCH 0594/7155] intel_th: msu: Preserve pre-existing buffer configuration The MSU configuration registers may contain buffer address/size set by the BIOS or an external hardware debugger, which may want to take over tracing from the driver when the driver is not actively tracing. Preserve these settings when not actively tracing. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190705141425.19894-6-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/msu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index b200d9d1c7a0..fc9f15f36ad4 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -143,6 +143,8 @@ struct msc { unsigned int single_wrap : 1; void *base; dma_addr_t base_addr; + u32 orig_addr; + u32 orig_sz; /* <0: no buffer, 0: no users, >0: active users */ atomic_t user_count; @@ -767,6 +769,9 @@ static int msc_configure(struct msc *msc) msc_buffer_clear_hw_header(msc); } + msc->orig_addr = ioread32(msc->reg_base + REG_MSU_MSC0BAR); + msc->orig_sz = ioread32(msc->reg_base + REG_MSU_MSC0SIZE); + reg = msc->base_addr >> PAGE_SHIFT; iowrite32(reg, msc->reg_base + REG_MSU_MSC0BAR); @@ -841,8 +846,8 @@ static void msc_disable(struct msc *msc) msc->enabled = 0; - iowrite32(0, msc->reg_base + REG_MSU_MSC0BAR); - iowrite32(0, msc->reg_base + REG_MSU_MSC0SIZE); + iowrite32(msc->orig_addr, msc->reg_base + REG_MSU_MSC0BAR); + iowrite32(msc->orig_sz, msc->reg_base + REG_MSU_MSC0SIZE); dev_dbg(msc_dev(msc), "MSCnNWSA: %08x\n", ioread32(msc->reg_base + REG_MSU_MSC0NWSA)); -- GitLab From 7bdd9695970eb8cd5b987e08f99cb8f0c84f30fd Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 24 Jul 2019 17:04:26 +0800 Subject: [PATCH 0595/7155] char: ppdev: Fix a possible null-pointer dereference in pp_release() In pp_release(), there is an if statement on line 730 to check whether pp->pdev is NULL: else if ((pp->flags & PP_CLAIMED) && pp->pdev && ...) When pp->pdev is NULL, it is used on line 743: info = &pp->pdev->port->ieee1284; and on line 748: parport_release(pp->pdev); Thus, a possible null-pointer dereference may occur. To fix this bug, pp->pdev is checked on line 740. This bug is found by a static analysis tool STCheck written by us. Signed-off-by: Jia-Ju Bai Link: https://lore.kernel.org/r/20190724090426.1401-1-baijiaju1990@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index f0a8adca1eee..c86f18aa8985 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -737,7 +737,7 @@ static int pp_release(struct inode *inode, struct file *file) "negotiated back to compatibility mode because user-space forgot\n"); } - if (pp->flags & PP_CLAIMED) { + if ((pp->flags & PP_CLAIMED) && pp->pdev) { struct ieee1284_info *info; info = &pp->pdev->port->ieee1284; -- GitLab From 515db266a9dace92b0cbaed9a6044dd5304b8ca9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 16 Jul 2019 17:21:06 +0200 Subject: [PATCH 0596/7155] driver core: Remove device link creation limitation If device_link_add() is called for a consumer/supplier pair with an existing device link between them and the existing link's type is not in agreement with the flags passed to that function by its caller, NULL will be returned. That is seriously inconvenient, because it forces the callers of device_link_add() to worry about what others may or may not do even if that is not relevant to them for any other reasons. It turns out, however, that this limitation can be made go away relatively easily. The underlying observation is that if DL_FLAG_STATELESS has been passed to device_link_add() in flags for the given consumer/supplier pair at least once, calling either device_link_del() or device_link_remove() to release the link returned by it should work, but there are no other requirements associated with that flag. In turn, if at least one of the callers of device_link_add() for the given consumer/supplier pair has not passed DL_FLAG_STATELESS to it in flags, the driver core should track the status of the link and act on it as appropriate (ie. the link should be treated as "managed"). This means that DL_FLAG_STATELESS needs to be set for managed device links and it should be valid to call device_link_del() or device_link_remove() to drop references to them in certain sutiations. To allow that to happen, introduce a new (internal) device link flag called DL_FLAG_MANAGED and make device_link_add() set it automatically whenever DL_FLAG_STATELESS is not passed to it. Also make it take additional references to existing device links that were previously stateless (that is, with DL_FLAG_STATELESS set and DL_FLAG_MANAGED unset) and will need to be managed going forward and initialize their status (which has been DL_STATE_NONE so far). Accordingly, when a managed device link is dropped automatically by the driver core, make it clear DL_FLAG_MANAGED, reset the link's status back to DL_STATE_NONE and drop the reference to it associated with DL_FLAG_MANAGED instead of just deleting it right away (to allow it to stay around in case it still needs to be released explicitly by someone). With that, since setting DL_FLAG_STATELESS doesn't mean that the device link in question is not managed any more, replace all of the status-tracking checks against DL_FLAG_STATELESS with analogous checks against DL_FLAG_MANAGED and update the documentation to reflect these changes. While at it, make device_link_add() reject flags that it does not recognize, including DL_FLAG_MANAGED. Signed-off-by: Rafael J. Wysocki Reviewed-by: Saravana Kannan Tested-by: Marek Szyprowski Review-by: Saravana Kannan Link: https://lore.kernel.org/r/2305283.AStDPdUUnE@kreacher Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/device_link.rst | 4 +- drivers/base/core.c | 176 +++++++++++++---------- drivers/base/power/runtime.c | 4 +- include/linux/device.h | 4 +- 4 files changed, 106 insertions(+), 82 deletions(-) diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst index ae1e3d0394b0..1b5020ec6517 100644 --- a/Documentation/driver-api/device_link.rst +++ b/Documentation/driver-api/device_link.rst @@ -78,8 +78,8 @@ typically deleted in its ``->remove`` callback for symmetry. That way, if the driver is compiled as a module, the device link is added on module load and orderly deleted on unload. The same restrictions that apply to device link addition (e.g. exclusion of a parallel suspend/resume transition) apply equally -to deletion. Device links with ``DL_FLAG_STATELESS`` unset (i.e. managed -device links) are deleted automatically by the driver core. +to deletion. Device links managed by the driver core are deleted automatically +by it. Several flags may be specified on device link addition, two of which have already been mentioned above: ``DL_FLAG_STATELESS`` to express that no diff --git a/drivers/base/core.c b/drivers/base/core.c index da84a73f2ba6..21cd08162219 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -124,6 +124,50 @@ static int device_is_dependent(struct device *dev, void *target) return ret; } +static void device_link_init_status(struct device_link *link, + struct device *consumer, + struct device *supplier) +{ + switch (supplier->links.status) { + case DL_DEV_PROBING: + switch (consumer->links.status) { + case DL_DEV_PROBING: + /* + * A consumer driver can create a link to a supplier + * that has not completed its probing yet as long as it + * knows that the supplier is already functional (for + * example, it has just acquired some resources from the + * supplier). + */ + link->status = DL_STATE_CONSUMER_PROBE; + break; + default: + link->status = DL_STATE_DORMANT; + break; + } + break; + case DL_DEV_DRIVER_BOUND: + switch (consumer->links.status) { + case DL_DEV_PROBING: + link->status = DL_STATE_CONSUMER_PROBE; + break; + case DL_DEV_DRIVER_BOUND: + link->status = DL_STATE_ACTIVE; + break; + default: + link->status = DL_STATE_AVAILABLE; + break; + } + break; + case DL_DEV_UNBINDING: + link->status = DL_STATE_SUPPLIER_UNBIND; + break; + default: + link->status = DL_STATE_DORMANT; + break; + } +} + static int device_reorder_to_tail(struct device *dev, void *not_used) { struct device_link *link; @@ -165,6 +209,10 @@ void device_pm_move_to_tail(struct device *dev) device_links_read_unlock(idx); } +#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ + DL_FLAG_AUTOREMOVE_SUPPLIER | \ + DL_FLAG_AUTOPROBE_CONSUMER) + /** * device_link_add - Create a link between two devices. * @consumer: Consumer end of the link. @@ -179,9 +227,9 @@ void device_pm_move_to_tail(struct device *dev) * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * ignored. * - * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by - * the driver core and, in particular, the caller of this function is expected - * to drop the reference to the link acquired by it directly. + * If DL_FLAG_STATELESS is set in @flags, the caller of this function is + * expected to release the link returned by it directly with the help of either + * device_link_del() or device_link_remove(). * * If that flag is not set, however, the caller of this function is handing the * management of the link over to the driver core entirely and its return value @@ -201,9 +249,16 @@ void device_pm_move_to_tail(struct device *dev) * be used to request the driver core to automaticall probe for a consmer * driver after successfully binding a driver to the supplier device. * - * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER - * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and - * will cause NULL to be returned upfront. + * The combination of DL_FLAG_STATELESS and one of DL_FLAG_AUTOREMOVE_CONSUMER, + * DL_FLAG_AUTOREMOVE_SUPPLIER, or DL_FLAG_AUTOPROBE_CONSUMER set in @flags at + * the same time is invalid and will cause NULL to be returned upfront. + * However, if a device link between the given @consumer and @supplier pair + * exists already when this function is called for them, the existing link will + * be returned regardless of its current type and status (the link's flags may + * be modified then). The caller of this function is then expected to treat + * the link as though it has just been created, so (in particular) if + * DL_FLAG_STATELESS was passed in @flags, the link needs to be released + * explicitly when not needed any more (as stated above). * * A side effect of the link creation is re-ordering of dpm_list and the * devices_kset list by moving the consumer device and all devices depending @@ -220,10 +275,8 @@ struct device_link *device_link_add(struct device *consumer, struct device_link *link; if (!consumer || !supplier || - (flags & DL_FLAG_STATELESS && - flags & (DL_FLAG_AUTOREMOVE_CONSUMER | - DL_FLAG_AUTOREMOVE_SUPPLIER | - DL_FLAG_AUTOPROBE_CONSUMER)) || + (flags & ~(DL_FLAG_STATELESS | DL_MANAGED_LINK_FLAGS)) || + (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) @@ -236,6 +289,9 @@ struct device_link *device_link_add(struct device *consumer, } } + if (!(flags & DL_FLAG_STATELESS)) + flags |= DL_FLAG_MANAGED; + device_links_write_lock(); device_pm_lock(); @@ -262,15 +318,6 @@ struct device_link *device_link_add(struct device *consumer, if (link->consumer != consumer) continue; - /* - * Don't return a stateless link if the caller wants a stateful - * one and vice versa. - */ - if (WARN_ON((flags & DL_FLAG_STATELESS) != (link->flags & DL_FLAG_STATELESS))) { - link = NULL; - goto out; - } - if (flags & DL_FLAG_PM_RUNTIME) { if (!(link->flags & DL_FLAG_PM_RUNTIME)) { pm_runtime_new_link(consumer); @@ -281,6 +328,7 @@ struct device_link *device_link_add(struct device *consumer, } if (flags & DL_FLAG_STATELESS) { + link->flags |= DL_FLAG_STATELESS; kref_get(&link->kref); goto out; } @@ -299,6 +347,11 @@ struct device_link *device_link_add(struct device *consumer, link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER); } + if (!(link->flags & DL_FLAG_MANAGED)) { + kref_get(&link->kref); + link->flags |= DL_FLAG_MANAGED; + device_link_init_status(link, consumer, supplier); + } goto out; } @@ -325,48 +378,10 @@ struct device_link *device_link_add(struct device *consumer, kref_init(&link->kref); /* Determine the initial link state. */ - if (flags & DL_FLAG_STATELESS) { + if (flags & DL_FLAG_STATELESS) link->status = DL_STATE_NONE; - } else { - switch (supplier->links.status) { - case DL_DEV_PROBING: - switch (consumer->links.status) { - case DL_DEV_PROBING: - /* - * A consumer driver can create a link to a - * supplier that has not completed its probing - * yet as long as it knows that the supplier is - * already functional (for example, it has just - * acquired some resources from the supplier). - */ - link->status = DL_STATE_CONSUMER_PROBE; - break; - default: - link->status = DL_STATE_DORMANT; - break; - } - break; - case DL_DEV_DRIVER_BOUND: - switch (consumer->links.status) { - case DL_DEV_PROBING: - link->status = DL_STATE_CONSUMER_PROBE; - break; - case DL_DEV_DRIVER_BOUND: - link->status = DL_STATE_ACTIVE; - break; - default: - link->status = DL_STATE_AVAILABLE; - break; - } - break; - case DL_DEV_UNBINDING: - link->status = DL_STATE_SUPPLIER_UNBIND; - break; - default: - link->status = DL_STATE_DORMANT; - break; - } - } + else + device_link_init_status(link, consumer, supplier); /* * Some callers expect the link creation during consumer driver probe to @@ -528,7 +543,7 @@ static void device_links_missing_supplier(struct device *dev) * mark the link as "consumer probe in progress" to make the supplier removal * wait for us to complete (or bad things may happen). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ int device_links_check_suppliers(struct device *dev) { @@ -538,7 +553,7 @@ int device_links_check_suppliers(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->status != DL_STATE_AVAILABLE) { @@ -563,7 +578,7 @@ int device_links_check_suppliers(struct device *dev) * * Also change the status of @dev's links to suppliers to "active". * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_driver_bound(struct device *dev) { @@ -572,7 +587,7 @@ void device_links_driver_bound(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; /* @@ -593,7 +608,7 @@ void device_links_driver_bound(struct device *dev) } list_for_each_entry(link, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); @@ -605,6 +620,13 @@ void device_links_driver_bound(struct device *dev) device_links_write_unlock(); } +static void device_link_drop_managed(struct device_link *link) +{ + link->flags &= ~DL_FLAG_MANAGED; + WRITE_ONCE(link->status, DL_STATE_NONE); + kref_put(&link->kref, __device_link_del); +} + /** * __device_links_no_driver - Update links of a device without a driver. * @dev: Device without a drvier. @@ -615,18 +637,18 @@ void device_links_driver_bound(struct device *dev) * unless they already are in the "supplier unbind in progress" state in which * case they need not be updated. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ static void __device_links_no_driver(struct device *dev) { struct device_link *link, *ln; list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) - __device_link_del(&link->kref); + device_link_drop_managed(link); else if (link->status == DL_STATE_CONSUMER_PROBE || link->status == DL_STATE_ACTIVE) WRITE_ONCE(link->status, DL_STATE_AVAILABLE); @@ -643,7 +665,7 @@ static void __device_links_no_driver(struct device *dev) * %__device_links_no_driver() to update links to suppliers for it as * appropriate. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_no_driver(struct device *dev) { @@ -652,7 +674,7 @@ void device_links_no_driver(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; /* @@ -680,7 +702,7 @@ void device_links_no_driver(struct device *dev) * invoke %__device_links_no_driver() to update links to suppliers for it as * appropriate. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_driver_cleanup(struct device *dev) { @@ -689,7 +711,7 @@ void device_links_driver_cleanup(struct device *dev) device_links_write_lock(); list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); @@ -702,7 +724,7 @@ void device_links_driver_cleanup(struct device *dev) */ if (link->status == DL_STATE_SUPPLIER_UNBIND && link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) - __device_link_del(&link->kref); + device_link_drop_managed(link); WRITE_ONCE(link->status, DL_STATE_DORMANT); } @@ -724,7 +746,7 @@ void device_links_driver_cleanup(struct device *dev) * * Return 'false' if there are no probing or active consumers. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ bool device_links_busy(struct device *dev) { @@ -734,7 +756,7 @@ bool device_links_busy(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->status == DL_STATE_CONSUMER_PROBE @@ -764,7 +786,7 @@ bool device_links_busy(struct device *dev) * driver to unbind and start over (the consumer will not re-probe as we have * changed the state of the link already). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_unbind_consumers(struct device *dev) { @@ -776,7 +798,7 @@ void device_links_unbind_consumers(struct device *dev) list_for_each_entry(link, &dev->links.consumers, s_node) { enum device_link_state status; - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; status = link->status; diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index b75335508d2c..45a8fbe6987a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1624,7 +1624,7 @@ void pm_runtime_remove(struct device *dev) * runtime PM references to the device, drop the usage counter of the device * (as many times as needed). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links with the DL_FLAG_MANAGED flag unset are ignored. * * Since the device is guaranteed to be runtime-active at the point this is * called, nothing else needs to be done here. @@ -1641,7 +1641,7 @@ void pm_runtime_clean_up_links(struct device *dev) idx = device_links_read_lock(); list_for_each_entry_rcu(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; while (refcount_dec_not_one(&link->rpm_active)) diff --git a/include/linux/device.h b/include/linux/device.h index c330b75c6c57..c1c489921e4c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -833,12 +833,13 @@ enum device_link_state { /* * Device link flags. * - * STATELESS: The core won't track the presence of supplier/consumer drivers. + * STATELESS: The core will not remove this link automatically. * AUTOREMOVE_CONSUMER: Remove the link automatically on consumer driver unbind. * PM_RUNTIME: If set, the runtime PM framework will use this link. * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. + * MANAGED: The core tracks presence of supplier/consumer drivers (internal). */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) @@ -846,6 +847,7 @@ enum device_link_state { #define DL_FLAG_RPM_ACTIVE BIT(3) #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) +#define DL_FLAG_MANAGED BIT(6) /** * struct device_link - Device link representation. -- GitLab From 43e4cb942e88e756b41ea4d30249a47973880508 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 24 Jul 2019 20:16:31 +0300 Subject: [PATCH 0597/7155] locks: Fix procfs output for file leases Since commit 778fc546f749c588aa2f ("locks: fix tracking of inprogress lease breaks"), leases break don't change @fl_type but modifies @fl_flags. However, procfs's part haven't been updated. Previously, for a breaking lease the target type was printed (see target_leasetype()), as returns fcntl(F_GETLEASE). But now it's always "READ", as F_UNLCK no longer means "breaking". Unlike the previous one, this behaviour don't provide a complete description of the lease. There are /proc/pid/fdinfo/ outputs for a lease (the same for READ and WRITE) breaked by O_WRONLY. -- before: lock: 1: LEASE BREAKING READ 2558 08:03:815793 0 EOF -- after: lock: 1: LEASE BREAKING UNLCK 2558 08:03:815793 0 EOF Signed-off-by: Pavel Begunkov Signed-off-by: Jeff Layton --- fs/locks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 686eae21daf6..24d1db632f6c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2784,10 +2784,10 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ " : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE "); } else { - seq_printf(f, "%s ", - (lease_breaking(fl)) - ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ " - : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ "); + int type = IS_LEASE(fl) ? target_leasetype(fl) : fl->fl_type; + + seq_printf(f, "%s ", (type == F_WRLCK) ? "WRITE" : + (type == F_RDLCK) ? "READ" : "UNLCK"); } if (inode) { /* userspace relies on this representation of dev_t */ -- GitLab From 6a76404b13ba7101216967dc447b77cf69e56adf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 4 Apr 2019 18:41:19 -0400 Subject: [PATCH 0598/7155] media: davinci-vpif: Don't dereference endpoint after putting it, fix refcounting The davinci-vpif driver dereferences its local endpoints after releasing the reference to them. The driver also puts its endpoints explicitly while the of_graph_get_next_endpoint() does that, too, leading to obtaining a reference once and releasing it twice. Both are fixed by this patch. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index d5eadd451587..4bbb4fdeae92 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1545,7 +1545,6 @@ vpif_capture_get_pdata(struct platform_device *pdev) if (!rem) { dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", endpoint); - of_node_put(endpoint); goto done; } @@ -1557,7 +1556,6 @@ vpif_capture_get_pdata(struct platform_device *pdev) GFP_KERNEL); if (!chan->inputs) { of_node_put(rem); - of_node_put(endpoint); goto err_cleanup; } @@ -1568,7 +1566,6 @@ vpif_capture_get_pdata(struct platform_device *pdev) err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); - of_node_put(endpoint); if (err) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); of_node_put(rem); @@ -1599,6 +1596,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) } done: + of_node_put(endpoint); pdata->asd_sizes[0] = i; pdata->subdev_count = i; pdata->card_name = "DA850/OMAP-L138 Video Capture"; @@ -1606,6 +1604,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) return pdata; err_cleanup: + of_node_put(endpoint); v4l2_async_notifier_cleanup(&vpif_obj.notifier); return NULL; -- GitLab From 016413d967061fc2eb6798a487b3022bef7698a6 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 4 Apr 2019 19:43:29 -0400 Subject: [PATCH 0599/7155] media: v4l2-async: Get fwnode reference when putting it to the notifier's list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v4l2_async_notifier_add_fwnode_subdev() did not take a reference of the added fwnode, relying on the caller to handle that instead, in essence putting the fwnode to be added if there was an error. As the reference is eventually released during the notifier cleanup, this is not intuitive nor logical. Improve this by always getting a reference when the function succeeds, and the caller releasing the reference when it does not *itself* need it anymore. Luckily, perhaps, there were just a handful of callers using the function. Signed-off-by: Sakari Ailus Reviewed-by: Jacopo Mondi Tested-by: Niklas Söderlund Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 5 ++-- drivers/media/platform/davinci/vpif_capture.c | 13 +++++------ drivers/media/platform/qcom/camss/camss.c | 2 +- drivers/media/platform/xilinx/xilinx-vipp.c | 2 +- drivers/media/v4l2-core/v4l2-async.c | 3 ++- drivers/media/v4l2-core/v4l2-fwnode.c | 23 +++++-------------- include/media/v4l2-async.h | 5 ++-- 7 files changed, 21 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 105237edbb58..3b1d60ca859b 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2489,10 +2489,9 @@ vpfe_get_pdata(struct vpfe_device *vpfe) pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( &vpfe->notifier, of_fwnode_handle(rem), sizeof(struct v4l2_async_subdev)); - if (IS_ERR(pdata->asd[i])) { - of_node_put(rem); + of_node_put(rem); + if (IS_ERR(pdata->asd[i])) goto cleanup; - } } of_node_put(endpoint); diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 4bbb4fdeae92..71f4fe882d13 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1502,6 +1502,7 @@ static struct vpif_capture_config * vpif_capture_get_pdata(struct platform_device *pdev) { struct device_node *endpoint = NULL; + struct device_node *rem = NULL; struct vpif_capture_config *pdata; struct vpif_subdev_info *sdinfo; struct vpif_capture_chan_config *chan; @@ -1532,7 +1533,6 @@ vpif_capture_get_pdata(struct platform_device *pdev) for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; - struct device_node *rem; unsigned int flags; int err; @@ -1554,10 +1554,8 @@ vpif_capture_get_pdata(struct platform_device *pdev) VPIF_CAPTURE_NUM_CHANNELS, sizeof(*chan->inputs), GFP_KERNEL); - if (!chan->inputs) { - of_node_put(rem); + if (!chan->inputs) goto err_cleanup; - } chan->input_count++; chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA; @@ -1589,10 +1587,10 @@ vpif_capture_get_pdata(struct platform_device *pdev) pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( &vpif_obj.notifier, of_fwnode_handle(rem), sizeof(struct v4l2_async_subdev)); - if (IS_ERR(pdata->asd[i])) { - of_node_put(rem); + if (IS_ERR(pdata->asd[i])) goto err_cleanup; - } + + of_node_put(rem); } done: @@ -1604,6 +1602,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) return pdata; err_cleanup: + of_node_put(rem); of_node_put(endpoint); v4l2_async_notifier_cleanup(&vpif_obj.notifier); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 63da18773d24..3fdc9f964a3c 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -486,9 +486,9 @@ static int camss_of_parse_ports(struct camss *camss) asd = v4l2_async_notifier_add_fwnode_subdev( &camss->notifier, of_fwnode_handle(remote), sizeof(*csd)); + of_node_put(remote); if (IS_ERR(asd)) { ret = PTR_ERR(asd); - of_node_put(remote); goto err_cleanup; } diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index edce0402155d..cc2856efea59 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -385,9 +385,9 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev, asd = v4l2_async_notifier_add_fwnode_subdev( &xdev->notifier, remote, sizeof(struct xvip_graph_entity)); + fwnode_handle_put(remote); if (IS_ERR(asd)) { ret = PTR_ERR(asd); - fwnode_handle_put(remote); goto err_notifier_cleanup; } } diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 8d307b538f52..7d364c545a40 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -593,10 +593,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, return ERR_PTR(-ENOMEM); asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - asd->match.fwnode = fwnode; + asd->match.fwnode = fwnode_handle_get(fwnode); ret = v4l2_async_notifier_add_subdev(notifier, asd); if (ret) { + fwnode_handle_put(fwnode); kfree(asd); return ERR_PTR(ret); } diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 6972c5af25c6..3bd1888787eb 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -775,23 +775,17 @@ static int v4l2_fwnode_reference_parse(struct device *dev, asd = v4l2_async_notifier_add_fwnode_subdev(notifier, args.fwnode, sizeof(*asd)); + fwnode_handle_put(args.fwnode); if (IS_ERR(asd)) { - ret = PTR_ERR(asd); /* not an error if asd already exists */ - if (ret == -EEXIST) { - fwnode_handle_put(args.fwnode); + if (PTR_ERR(asd) == -EEXIST) continue; - } - goto error; + return PTR_ERR(asd); } } return 0; - -error: - fwnode_handle_put(args.fwnode); - return ret; } /* @@ -1081,23 +1075,18 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev, asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode, sizeof(*asd)); + fwnode_handle_put(fwnode); if (IS_ERR(asd)) { ret = PTR_ERR(asd); /* not an error if asd already exists */ - if (ret == -EEXIST) { - fwnode_handle_put(fwnode); + if (ret == -EEXIST) continue; - } - goto error; + return PTR_ERR(asd); } } return !fwnode || PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode); - -error: - fwnode_handle_put(fwnode); - return ret; } int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev, diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 2e3d93f742a3..a95f7fd8969e 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -172,8 +172,9 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier, * the driver's async sub-device struct, i.e. both * begin at the same memory address. * - * Allocate a fwnode-matched asd of size asd_struct_size, and add it - * to the notifiers @asd_list. + * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the + * notifiers @asd_list. The function also gets a reference of the fwnode which + * is released later at notifier cleanup time. */ struct v4l2_async_subdev * v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, -- GitLab From 820342aca05188c9af4b468d6c41b3327161f7ad Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 28 Feb 2019 08:25:28 -0500 Subject: [PATCH 0600/7155] media: v4l2-async: Add v4l2_async_notifier_add_fwnode_remote_subdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4l2_async_notifier_add_fwnode_remote_subdev is a convenience function for parsing information on V4L2 fwnode subdevs. Signed-off-by: Sakari Ailus Tested-by: Niklas Söderlund Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 23 +++++++++++++++++++++++ include/media/v4l2-async.h | 25 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 7d364c545a40..dc4f470ea6a7 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -606,6 +606,29 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, } EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev); +int +v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif, + struct fwnode_handle *endpoint, + struct v4l2_async_subdev *asd) +{ + struct fwnode_handle *remote; + int ret; + + remote = fwnode_graph_get_remote_port_parent(endpoint); + if (!remote) + return -ENOTCONN; + + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + asd->match.fwnode = remote; + + ret = v4l2_async_notifier_add_subdev(notif, asd); + if (ret) + fwnode_handle_put(remote); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev); + struct v4l2_async_subdev * v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier, int adapter_id, unsigned short address, diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index a95f7fd8969e..8319284c93cb 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -181,6 +181,31 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, unsigned int asd_struct_size); +/** + * v4l2_async_notifier_add_fwnode_remote_subdev - Allocate and add a fwnode + * remote async subdev to the + * notifier's master asd_list. + * + * @notif: pointer to &struct v4l2_async_notifier + * @endpoint: local endpoint pointing to the remote sub-device to be matched + * @asd: Async sub-device struct allocated by the caller. The &struct + * v4l2_async_subdev shall be the first member of the driver's async + * sub-device struct, i.e. both begin at the same memory address. + * + * Gets the remote endpoint of a given local endpoint, set it up for fwnode + * matching and adds the async sub-device to the notifier's @asd_list. The + * function also gets a reference of the fwnode which is released later at + * notifier cleanup time. + * + * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the + * exception that the fwnode refers to a local endpoint, not the remote one, and + * the function relies on the caller to allocate the async sub-device struct. + */ +int +v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif, + struct fwnode_handle *endpoint, + struct v4l2_async_subdev *asd); + /** * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async * subdev to the notifier's master asd_list. -- GitLab From dcfecd4d7a551906595351a26e1db91774b8563d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 4 Jul 2019 07:56:45 +0200 Subject: [PATCH 0601/7155] fpga: dfl: use driver core functions, not sysfs ones. This is a driver, do not call "raw" sysfs functions, instead call driver core ones. Specifically convert the use of sysfs_create_files() and sysfs_remove_files() to use device_add_groups() and device_remove_groups() Cc: Wu Hao Cc: Alan Tull Cc: Moritz Fischer Cc: linux-fpga@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190704055645.GA15471@kroah.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl-afu-main.c | 14 ++++++++------ drivers/fpga/dfl-fme-main.c | 7 ++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 02baa6a227c0..68b4d0874b93 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -141,10 +141,11 @@ id_show(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR_RO(id); -static const struct attribute *port_hdr_attrs[] = { +static struct attribute *port_hdr_attrs[] = { &dev_attr_id.attr, NULL, }; +ATTRIBUTE_GROUPS(port_hdr); static int port_hdr_init(struct platform_device *pdev, struct dfl_feature *feature) @@ -153,7 +154,7 @@ static int port_hdr_init(struct platform_device *pdev, port_reset(pdev); - return sysfs_create_files(&pdev->dev.kobj, port_hdr_attrs); + return device_add_groups(&pdev->dev, port_hdr_groups); } static void port_hdr_uinit(struct platform_device *pdev, @@ -161,7 +162,7 @@ static void port_hdr_uinit(struct platform_device *pdev, { dev_dbg(&pdev->dev, "PORT HDR UInit.\n"); - sysfs_remove_files(&pdev->dev.kobj, port_hdr_attrs); + device_remove_groups(&pdev->dev, port_hdr_groups); } static long @@ -214,10 +215,11 @@ afu_id_show(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR_RO(afu_id); -static const struct attribute *port_afu_attrs[] = { +static struct attribute *port_afu_attrs[] = { &dev_attr_afu_id.attr, NULL }; +ATTRIBUTE_GROUPS(port_afu); static int port_afu_init(struct platform_device *pdev, struct dfl_feature *feature) @@ -234,7 +236,7 @@ static int port_afu_init(struct platform_device *pdev, if (ret) return ret; - return sysfs_create_files(&pdev->dev.kobj, port_afu_attrs); + return device_add_groups(&pdev->dev, port_afu_groups); } static void port_afu_uinit(struct platform_device *pdev, @@ -242,7 +244,7 @@ static void port_afu_uinit(struct platform_device *pdev, { dev_dbg(&pdev->dev, "PORT AFU UInit.\n"); - sysfs_remove_files(&pdev->dev.kobj, port_afu_attrs); + device_remove_groups(&pdev->dev, port_afu_groups); } static const struct dfl_feature_ops port_afu_ops = { diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index 086ad2420ade..0be4635583d5 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -72,12 +72,13 @@ static ssize_t bitstream_metadata_show(struct device *dev, } static DEVICE_ATTR_RO(bitstream_metadata); -static const struct attribute *fme_hdr_attrs[] = { +static struct attribute *fme_hdr_attrs[] = { &dev_attr_ports_num.attr, &dev_attr_bitstream_id.attr, &dev_attr_bitstream_metadata.attr, NULL, }; +ATTRIBUTE_GROUPS(fme_hdr); static int fme_hdr_init(struct platform_device *pdev, struct dfl_feature *feature) @@ -89,7 +90,7 @@ static int fme_hdr_init(struct platform_device *pdev, dev_dbg(&pdev->dev, "FME cap %llx.\n", (unsigned long long)readq(base + FME_HDR_CAP)); - ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs); + ret = device_add_groups(&pdev->dev, fme_hdr_groups); if (ret) return ret; @@ -100,7 +101,7 @@ static void fme_hdr_uinit(struct platform_device *pdev, struct dfl_feature *feature) { dev_dbg(&pdev->dev, "FME HDR UInit.\n"); - sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs); + device_remove_groups(&pdev->dev, fme_hdr_groups); } static const struct dfl_feature_ops fme_hdr_ops = { -- GitLab From bc83f79bd2119230888fb8574639d5a51b38f903 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 12 Jul 2019 11:24:09 +0200 Subject: [PATCH 0602/7155] mic: avoid statically declaring a 'struct device'. Generally, declaring a platform device as a static variable is a bad idea and can cause all kinds of problems, in particular with the DMA configuration and lifetime rules. A specific problem we hit here is from a bug in clang that warns about certain (otherwise valid) macros when used in static variables: drivers/misc/mic/card/mic_x100.c:285:27: warning: shift count >= width of type [-Wshift-count-overflow] static u64 mic_dma_mask = DMA_BIT_MASK(64); ^~~~~~~~~~~~~~~~ include/linux/dma-mapping.h:141:54: note: expanded from macro 'DMA_BIT_MASK' #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) ^ ~~~ A slightly better way here is to create the platform device dynamically and set the dma mask in the probe function. This avoids the warning and some other problems, but is still not ideal because the device creation should really be separated from the driver, and the fact that the device has no parent means we have to force the dma mask rather than having it set up from the bus that the device is actually on. Fixes: dd8d8d44df64 ("misc: mic: MIC card driver specific changes to enable SCIF") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190712092426.872625-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/card/mic_x100.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c index 266ffb6f6c44..c8bff2916d3d 100644 --- a/drivers/misc/mic/card/mic_x100.c +++ b/drivers/misc/mic/card/mic_x100.c @@ -237,6 +237,9 @@ static int __init mic_probe(struct platform_device *pdev) mdrv->dev = &pdev->dev; snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name); + /* FIXME: use dma_set_mask_and_coherent() and check result */ + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + mdev->mmio.pa = MIC_X100_MMIO_BASE; mdev->mmio.len = MIC_X100_MMIO_LEN; mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE, @@ -282,18 +285,6 @@ static void mic_platform_shutdown(struct platform_device *pdev) mic_remove(pdev); } -static u64 mic_dma_mask = DMA_BIT_MASK(64); - -static struct platform_device mic_platform_dev = { - .name = mic_driver_name, - .id = 0, - .num_resources = 0, - .dev = { - .dma_mask = &mic_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(64), - }, -}; - static struct platform_driver __refdata mic_platform_driver = { .probe = mic_probe, .remove = mic_remove, @@ -303,6 +294,8 @@ static struct platform_driver __refdata mic_platform_driver = { }, }; +static struct platform_device *mic_platform_dev; + static int __init mic_init(void) { int ret; @@ -316,9 +309,12 @@ static int __init mic_init(void) request_module("mic_x100_dma"); mic_init_card_debugfs(); - ret = platform_device_register(&mic_platform_dev); + + mic_platform_dev = platform_device_register_simple(mic_driver_name, + 0, NULL, 0); + ret = PTR_ERR_OR_ZERO(mic_platform_dev); if (ret) { - pr_err("platform_device_register ret %d\n", ret); + pr_err("platform_device_register_full ret %d\n", ret); goto cleanup_debugfs; } ret = platform_driver_register(&mic_platform_driver); @@ -329,7 +325,7 @@ static int __init mic_init(void) return ret; device_unregister: - platform_device_unregister(&mic_platform_dev); + platform_device_unregister(mic_platform_dev); cleanup_debugfs: mic_exit_card_debugfs(); done: @@ -339,7 +335,7 @@ static int __init mic_init(void) static void __exit mic_exit(void) { platform_driver_unregister(&mic_platform_driver); - platform_device_unregister(&mic_platform_dev); + platform_device_unregister(mic_platform_dev); mic_exit_card_debugfs(); } -- GitLab From 0854d589aa91c68f676f55e087be549eacaaa408 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Jul 2019 07:34:37 -0300 Subject: [PATCH 0603/7155] docs: ABI: remove extension from sysfs-class-mic.txt Files under ABI doesn't end with a .txt extension. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5113d1ae9d2dd3bc685bbb65655abd67e26f48c4.1562668471.git.mchehab+samsung@kernel.org Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/{sysfs-class-mic.txt => sysfs-class-mic} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/ABI/testing/{sysfs-class-mic.txt => sysfs-class-mic} (100%) diff --git a/Documentation/ABI/testing/sysfs-class-mic.txt b/Documentation/ABI/testing/sysfs-class-mic similarity index 100% rename from Documentation/ABI/testing/sysfs-class-mic.txt rename to Documentation/ABI/testing/sysfs-class-mic -- GitLab From e59fc52529118aaad9aa666f25530dde6e2180e9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 10 Jul 2019 18:59:34 -0400 Subject: [PATCH 0604/7155] staging: rtl8192*: display ESSIDs using %pE Everywhere else in the kernel ESSIDs are printed using %pE, and I can't see why there should be an exception here. Signed-off-by: J. Bruce Fields Link: https://lore.kernel.org/r/1562799574-13315-1-git-send-email-bfields@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 2dd57e88276e..096254e422b3 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -2132,7 +2132,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index d36963469015..3963a08b9eb2 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2426,7 +2426,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } -- GitLab From 41db5f8397eee75afff82655a4884b5786a1d302 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 5 Jul 2019 10:13:03 +0200 Subject: [PATCH 0605/7155] misc: fastrpc: fix memory leak when out of memory Do the necessary house-keeping if the allocated memory wont be used Signed-off-by: Jorge Ramirez-Ortiz Link: https://lore.kernel.org/r/20190705081303.14170-1-jorge.ramirez-ortiz@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 98603e235cf0..c790585da14c 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -279,8 +279,11 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, buf->virt = dma_alloc_coherent(dev, buf->size, (dma_addr_t *)&buf->phys, GFP_KERNEL); - if (!buf->virt) + if (!buf->virt) { + mutex_destroy(&buf->lock); + kfree(buf); return -ENOMEM; + } if (fl->sctx && fl->sctx->sid) buf->phys += ((u64)fl->sctx->sid << 32); -- GitLab From b6297d9e078a4127fb608ede4d0944855dde667d Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Fri, 24 May 2019 11:15:32 +0200 Subject: [PATCH 0606/7155] clk: meson: g12a: fix hifi typo in mali parent_names Replace hihi by hifi in the mali parent_names of the g12a SoC family. Fixes: 085a4ea93d54 ("clk: meson: g12a: add peripheral clock controller") Signed-off-by: Alexandre Mergnat Acked-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index db1c4ed9d54e..7bc5566b66f7 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -2888,7 +2888,7 @@ static struct clk_regmap g12a_hdmi = { */ static const char * const g12a_mali_0_1_parent_names[] = { - IN_PREFIX "xtal", "gp0_pll", "hihi_pll", "fclk_div2p5", + IN_PREFIX "xtal", "gp0_pll", "hifi_pll", "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7" }; -- GitLab From f2c8b57014038ae064a0f918f939af510f0aed02 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 25 Jul 2019 11:33:21 +0300 Subject: [PATCH 0607/7155] ASoC: pcm3168a: Allow all channels in case of parallel DIN/DOUT setup If multi DIN/DOUT mode is selected (tdm_slots == 2) then configure the channel constraint to allow all channels. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190725083321.6776-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 5d59ce254821..e84a1509fe65 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -599,6 +599,10 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, sample_min, 32); + /* Allow all channels in multi DIN/DOUT mode */ + if (pcm3168a->tdm_slots == 2) + channel_max = channel_maxs[tx]; + snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, channel_max); -- GitLab From 816fe206138a7e3895c3a74fbd326a51df003f70 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 25 Jul 2019 11:34:11 +0300 Subject: [PATCH 0608/7155] ASoC: ti: davinci-mcasp: Add support for RIGHT_J format The formater unit's rotation needs to be programmed differently for right aligned bus format to have the data moved to the correct place. Take the opportunity and simplify the formater unit setup code. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190725083411.7211-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 43 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index ac59b509ead5..09ba3d3c70a0 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -465,6 +465,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* FS need to be inverted */ inv_fs = true; break; + case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_LEFT_J: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); @@ -758,34 +759,28 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, int sample_width) { u32 fmt; - u32 tx_rotate = (sample_width / 4) & 0x7; + u32 tx_rotate, rx_rotate, slot_width; u32 mask = (1ULL << sample_width) - 1; - u32 slot_width = sample_width; - - /* - * For captured data we should not rotate, inversion and masking is - * enoguh to get the data to the right position: - * Format data from bus after reverse (XRBUF) - * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| - * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| - * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| - * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| - */ - u32 rx_rotate = 0; + if (mcasp->slot_width) + slot_width = mcasp->slot_width; + else + slot_width = sample_width; /* - * Setting the tdm slot width either with set_clkdiv() or - * set_tdm_slot() allows us to for example send 32 bits per - * channel to the codec, while only 16 of them carry audio - * payload. + * TX rotation: + * right aligned formats: rotate w/ slot_width + * left aligned formats: rotate w/ sample_width + * + * RX rotation: + * right aligned formats: no rotation needed + * left aligned formats: rotate w/ (slot_width - sample_width) */ - if (mcasp->slot_width) { - /* - * When we have more bclk then it is needed for the - * data, we need to use the rotation to move the - * received samples to have correct alignment. - */ - slot_width = mcasp->slot_width; + if ((mcasp->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) == + SND_SOC_DAIFMT_RIGHT_J) { + tx_rotate = (slot_width / 4) & 0x7; + rx_rotate = 0; + } else { + tx_rotate = (sample_width / 4) & 0x7; rx_rotate = (slot_width - sample_width) / 4; } -- GitLab From b7989e271e9f7fd4edb4166cd2a79b980c4b6136 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 25 Jul 2019 11:34:32 +0300 Subject: [PATCH 0609/7155] ASoC: ti: davinci-mcasp: Improve serializer handling in multi AXR setups When multiple serializers are used we need to track the number of serializers used by the other stream direction to avoid killing data lines when the first stream used more serializers than the second would need. We are still protected against the case when the second stream uses more serializers which had affected the running stream as well. To take advantage of the improved serializer logic we need to modify the channel constraints rule as well to allow the use of multiple serializers for the second stream as additional ones will not affect the FS/BCLK on the bus. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190725083432.7419-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 92 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 09ba3d3c70a0..c3a2c53fdb3a 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -109,6 +109,7 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels; + u8 active_serializers[2]; #ifdef CONFIG_GPIOLIB struct gpio_chip gpio_chip; @@ -813,6 +814,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, u8 rx_ser = 0; u8 slots = mcasp->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; + u8 max_rx_serializers, max_tx_serializers; int active_serializers, numevt; u32 reg; /* Default configuration */ @@ -822,22 +824,28 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (stream == SNDRV_PCM_STREAM_PLAYBACK) { mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); + max_tx_serializers = max_active_serializers; + max_rx_serializers = + mcasp->active_serializers[SNDRV_PCM_STREAM_CAPTURE]; } else { mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS); + max_tx_serializers = + mcasp->active_serializers[SNDRV_PCM_STREAM_PLAYBACK]; + max_rx_serializers = max_active_serializers; } for (i = 0; i < mcasp->num_serializer; i++) { mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), mcasp->serial_dir[i]); if (mcasp->serial_dir[i] == TX_MODE && - tx_ser < max_active_serializers) { + tx_ser < max_tx_serializers) { mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), mcasp->dismod, DISMOD_MASK); set_bit(PIN_BIT_AXR(i), &mcasp->pdir); tx_ser++; } else if (mcasp->serial_dir[i] == RX_MODE && - rx_ser < max_active_serializers) { + rx_ser < max_rx_serializers) { clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); rx_ser++; } else { @@ -884,7 +892,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, } else { dma_data->maxburst = 0; } - return 0; + + goto out; } if (period_words % active_serializers) { @@ -914,6 +923,9 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, numevt = 0; dma_data->maxburst = numevt; +out: + mcasp->active_serializers[stream] = active_serializers; + return 0; } @@ -1153,6 +1165,37 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int period_size = params_period_size(params); int ret; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + word_length = 8; + break; + + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_S16_LE: + word_length = 16; + break; + + case SNDRV_PCM_FORMAT_U24_3LE: + case SNDRV_PCM_FORMAT_S24_3LE: + word_length = 24; + break; + + case SNDRV_PCM_FORMAT_U24_LE: + case SNDRV_PCM_FORMAT_S24_LE: + word_length = 24; + break; + + case SNDRV_PCM_FORMAT_U32_LE: + case SNDRV_PCM_FORMAT_S32_LE: + word_length = 32; + break; + + default: + printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); + return -EINVAL; + } + ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); if (ret) return ret; @@ -1187,37 +1230,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: - word_length = 8; - break; - - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_S16_LE: - word_length = 16; - break; - - case SNDRV_PCM_FORMAT_U24_3LE: - case SNDRV_PCM_FORMAT_S24_3LE: - word_length = 24; - break; - - case SNDRV_PCM_FORMAT_U24_LE: - case SNDRV_PCM_FORMAT_S24_LE: - word_length = 24; - break; - - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_length = 32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - davinci_config_channel_size(mcasp, word_length); if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) @@ -1404,12 +1416,13 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, max_channels *= tdm_slots; /* * If the already active stream has less channels than the calculated - * limnit based on the seirializers * tdm_slots, we need to use that as - * a constraint for the second stream. - * Otherwise (first stream or less allowed channels) we use the - * calculated constraint. + * limit based on the seirializers * tdm_slots, and only one serializer + * is in use we need to use that as a constraint for the second stream. + * Otherwise (first stream or less allowed channels or more than one + * serializer in use) we use the calculated constraint. */ - if (mcasp->channels && mcasp->channels < max_channels) + if (mcasp->channels && mcasp->channels < max_channels && + ruledata->serializers == 1) max_channels = mcasp->channels; /* * But we can always allow channels upto the amount of @@ -1470,6 +1483,7 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream, struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); mcasp->substreams[substream->stream] = NULL; + mcasp->active_serializers[substream->stream] = 0; if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) return; -- GitLab From f4c255f1a747497a21748619d909cadabcfa060e Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 14 Jul 2019 17:55:04 -0400 Subject: [PATCH 0610/7155] dmaengine: dma-jz4780: Break descriptor chains on JZ4740 The current driver works perfectly fine on every generation of the JZ47xx SoCs, except on the JZ4740. There, when hardware descriptors are chained together (with the LINK bit set), the next descriptor isn't automatically fetched as it should - instead, an interrupt is raised, even if the TIE bit (Transfer Interrupt Enable) bit is cleared. When it happens, the DMA transfer seems to be stopped (it doesn't chain), and it's uncertain how many bytes have actually been transferred. Until somebody smarter than me can figure out how to make chained descriptors work on the JZ4740, we now disable chained descriptors on that particular SoC. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20190714215504.10877-1-paul@crapouillou.net Signed-off-by: Vinod Koul --- drivers/dma/dma-jz4780.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 7fe9309a876b..9a985a9710aa 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -92,6 +92,7 @@ #define JZ_SOC_DATA_PROGRAMMABLE_DMA BIT(1) #define JZ_SOC_DATA_PER_CHAN_PM BIT(2) #define JZ_SOC_DATA_NO_DCKES_DCKEC BIT(3) +#define JZ_SOC_DATA_BREAK_LINKS BIT(4) /** * struct jz4780_dma_hwdesc - descriptor structure read by the DMA controller. @@ -355,6 +356,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg( void *context) { struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan); + struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan); struct jz4780_dma_desc *desc; unsigned int i; int err; @@ -375,7 +377,8 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg( desc->desc[i].dcm |= JZ_DMA_DCM_TIE; - if (i != (sg_len - 1)) { + if (i != (sg_len - 1) && + !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) { /* Automatically proceeed to the next descriptor. */ desc->desc[i].dcm |= JZ_DMA_DCM_LINK; @@ -664,6 +667,8 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, struct jz4780_dma_chan *jzchan) { + const unsigned int soc_flags = jzdma->soc_data->flags; + struct jz4780_dma_desc *desc = jzchan->desc; uint32_t dcs; bool ack = true; @@ -691,8 +696,11 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, jz4780_dma_begin(jzchan); } else if (dcs & JZ_DMA_DCS_TT) { - vchan_cookie_complete(&jzchan->desc->vdesc); - jzchan->desc = NULL; + if (!(soc_flags & JZ_SOC_DATA_BREAK_LINKS) || + (jzchan->curr_hwdesc + 1 == desc->count)) { + vchan_cookie_complete(&desc->vdesc); + jzchan->desc = NULL; + } jz4780_dma_begin(jzchan); } else { @@ -992,6 +1000,7 @@ static int jz4780_dma_remove(struct platform_device *pdev) static const struct jz4780_dma_soc_data jz4740_dma_soc_data = { .nb_channels = 6, .transfer_ord_max = 5, + .flags = JZ_SOC_DATA_BREAK_LINKS, }; static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = { -- GitLab From 2fd60da46da76948b8cc561ae8cc902209686253 Mon Sep 17 00:00:00 2001 From: Peng Wang Date: Mon, 8 Jul 2019 23:16:11 +0800 Subject: [PATCH 0611/7155] kernfs: fix potential null pointer dereference Get root safely after kn is ensureed to be not null. Signed-off-by: Peng Wang Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20190708151611.13242-1-rocking@whu.edu.cn Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/dir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index a387534c9577..ddf537923a0a 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -430,7 +430,6 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) */ void kernfs_put_active(struct kernfs_node *kn) { - struct kernfs_root *root = kernfs_root(kn); int v; if (unlikely(!kn)) @@ -442,7 +441,7 @@ void kernfs_put_active(struct kernfs_node *kn) if (likely(v != KN_DEACTIVATED_BIAS)) return; - wake_up_all(&root->deactivate_waitq); + wake_up_all(&kernfs_root(kn)->deactivate_waitq); } /** -- GitLab From bbe70e4e421116db0af3acf84cbce3c3f6cac53e Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 24 Jul 2019 10:22:42 +0800 Subject: [PATCH 0612/7155] fs: kernfs: Fix possible null-pointer dereferences in kernfs_path_from_node_locked() In kernfs_path_from_node_locked(), there is an if statement on line 147 to check whether buf is NULL: if (buf) When buf is NULL, it is used on line 151: len += strlcpy(buf + len, parent_str, ...) and line 158: len += strlcpy(buf + len, "/", ...) and line 160: len += strlcpy(buf + len, kn->name, ...) Thus, possible null-pointer dereferences may occur. To fix these possible bugs, buf is checked before being used. If it is NULL, -EINVAL is returned. These bugs are found by a static analysis tool STCheck written by us. Signed-off-by: Jia-Ju Bai Link: https://lore.kernel.org/r/20190724022242.27505-1-baijiaju1990@gmail.com Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index ddf537923a0a..6ebae6bbe6a5 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -137,6 +137,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, if (kn_from == kn_to) return strlcpy(buf, "/", buflen); + if (!buf) + return -EINVAL; + common = kernfs_common_ancestor(kn_from, kn_to); if (WARN_ON(!common)) return -EINVAL; @@ -144,8 +147,7 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, depth_to = kernfs_depth(common, kn_to); depth_from = kernfs_depth(common, kn_from); - if (buf) - buf[0] = '\0'; + buf[0] = '\0'; for (i = 0; i < depth_from; i++) len += strlcpy(buf + len, parent_str, -- GitLab From 364f6afc4f5537b79cf454eb35cae92920676075 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 22 Jul 2019 11:24:40 -0700 Subject: [PATCH 0613/7155] locking/lockdep: Make it clear that what lock_class::key points at is not modified This patch does not change the behavior of the lockdep code. Signed-off-by: Bart Van Assche Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Waiman Long Cc: Will Deacon Link: https://lkml.kernel.org/r/20190722182443.216015-2-bvanassche@acm.org Signed-off-by: Ingo Molnar --- include/linux/lockdep.h | 2 +- kernel/locking/lockdep.c | 2 +- kernel/locking/lockdep_internals.h | 3 ++- kernel/locking/lockdep_proc.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 0b0d7259276d..cdb3c2f06092 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -97,7 +97,7 @@ struct lock_class { */ struct list_head locks_after, locks_before; - struct lockdep_subclass_key *key; + const struct lockdep_subclass_key *key; unsigned int subclass; unsigned int dep_gen_id; diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 4861cf8e274b..af6627866191 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -511,7 +511,7 @@ static const char *usage_str[] = }; #endif -const char * __get_key_name(struct lockdep_subclass_key *key, char *str) +const char *__get_key_name(const struct lockdep_subclass_key *key, char *str) { return kallsyms_lookup((unsigned long)key, NULL, NULL, NULL, str); } diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h index cc83568d5012..2e518369add4 100644 --- a/kernel/locking/lockdep_internals.h +++ b/kernel/locking/lockdep_internals.h @@ -116,7 +116,8 @@ extern struct lock_chain lock_chains[]; extern void get_usage_chars(struct lock_class *class, char usage[LOCK_USAGE_CHARS]); -extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); +extern const char *__get_key_name(const struct lockdep_subclass_key *key, + char *str); struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i); diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c index bda006f8a88b..ed9842425cac 100644 --- a/kernel/locking/lockdep_proc.c +++ b/kernel/locking/lockdep_proc.c @@ -399,7 +399,7 @@ static void seq_lock_time(struct seq_file *m, struct lock_time *lt) static void seq_stats(struct seq_file *m, struct lock_stat_data *data) { - struct lockdep_subclass_key *ckey; + const struct lockdep_subclass_key *ckey; struct lock_class_stats *stats; struct lock_class *class; const char *cname; -- GitLab From a2970421640bd9b6a78f2685d7750a791abdfd4e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 22 Jul 2019 11:24:41 -0700 Subject: [PATCH 0614/7155] stacktrace: Constify 'entries' arguments Make it clear to humans and to the compiler that the stack trace ('entries') arguments are not modified. Signed-off-by: Bart Van Assche Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Waiman Long Cc: Will Deacon Link: https://lkml.kernel.org/r/20190722182443.216015-3-bvanassche@acm.org Signed-off-by: Ingo Molnar --- include/linux/stacktrace.h | 4 ++-- kernel/stacktrace.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h index f0cfd12cb45e..83bd8cb475d7 100644 --- a/include/linux/stacktrace.h +++ b/include/linux/stacktrace.h @@ -9,9 +9,9 @@ struct task_struct; struct pt_regs; #ifdef CONFIG_STACKTRACE -void stack_trace_print(unsigned long *trace, unsigned int nr_entries, +void stack_trace_print(const unsigned long *trace, unsigned int nr_entries, int spaces); -int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, +int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, unsigned int nr_entries, int spaces); unsigned int stack_trace_save(unsigned long *store, unsigned int size, unsigned int skipnr); diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c index f5440abb7532..6d1f68b7e528 100644 --- a/kernel/stacktrace.c +++ b/kernel/stacktrace.c @@ -20,7 +20,7 @@ * @nr_entries: Number of entries in the storage array * @spaces: Number of leading spaces to print */ -void stack_trace_print(unsigned long *entries, unsigned int nr_entries, +void stack_trace_print(const unsigned long *entries, unsigned int nr_entries, int spaces) { unsigned int i; @@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(stack_trace_print); * * Return: Number of bytes printed. */ -int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, +int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, unsigned int nr_entries, int spaces) { unsigned int generated, i, total = 0; -- GitLab From 12593b7467f9130b64a6d4b6a26ed4ec217b6784 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 22 Jul 2019 11:24:42 -0700 Subject: [PATCH 0615/7155] locking/lockdep: Reduce space occupied by stack traces Although commit 669de8bda87b ("kernel/workqueue: Use dynamic lockdep keys for workqueues") unregisters dynamic lockdep keys when a workqueue is destroyed, a side effect of that commit is that all stack traces associated with the lockdep key are leaked when a workqueue is destroyed. Fix this by storing each unique stack trace once. Other changes in this patch are: - Use NULL instead of { .nr_entries = 0 } to represent 'no trace'. - Store a pointer to a stack trace in struct lock_class and struct lock_list instead of storing 'nr_entries' and 'offset'. This patch avoids that the following program triggers the "BUG: MAX_STACK_TRACE_ENTRIES too low!" complaint: #include #include int main() { for (;;) { int fd = open("/dev/infiniband/rdma_cm", O_RDWR); close(fd); } } Suggested-by: Peter Zijlstra Reported-by: Eric Biggers Signed-off-by: Bart Van Assche Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Waiman Long Cc: Will Deacon Cc: Yuyang Du Link: https://lkml.kernel.org/r/20190722182443.216015-4-bvanassche@acm.org Signed-off-by: Ingo Molnar --- include/linux/lockdep.h | 9 +- kernel/locking/lockdep.c | 128 ++++++++++++++++++++--------- kernel/locking/lockdep_internals.h | 2 + 3 files changed, 95 insertions(+), 44 deletions(-) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index cdb3c2f06092..b8a835fd611b 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -66,10 +66,7 @@ struct lock_class_key { extern struct lock_class_key __lockdep_no_validate__; -struct lock_trace { - unsigned int nr_entries; - unsigned int offset; -}; +struct lock_trace; #define LOCKSTAT_POINTS 4 @@ -105,7 +102,7 @@ struct lock_class { * IRQ/softirq usage tracking bits: */ unsigned long usage_mask; - struct lock_trace usage_traces[XXX_LOCK_USAGE_STATES]; + const struct lock_trace *usage_traces[XXX_LOCK_USAGE_STATES]; /* * Generation counter, when doing certain classes of graph walking, @@ -193,7 +190,7 @@ struct lock_list { struct list_head entry; struct lock_class *class; struct lock_class *links_to; - struct lock_trace trace; + const struct lock_trace *trace; int distance; /* diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index af6627866191..1a96869cb2f0 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -449,33 +449,72 @@ static void print_lockdep_off(const char *bug_msg) unsigned long nr_stack_trace_entries; #ifdef CONFIG_PROVE_LOCKING +/** + * struct lock_trace - single stack backtrace + * @hash_entry: Entry in a stack_trace_hash[] list. + * @hash: jhash() of @entries. + * @nr_entries: Number of entries in @entries. + * @entries: Actual stack backtrace. + */ +struct lock_trace { + struct hlist_node hash_entry; + u32 hash; + u32 nr_entries; + unsigned long entries[0] __aligned(sizeof(unsigned long)); +}; +#define LOCK_TRACE_SIZE_IN_LONGS \ + (sizeof(struct lock_trace) / sizeof(unsigned long)) /* - * Stack-trace: tightly packed array of stack backtrace - * addresses. Protected by the graph_lock. + * Stack-trace: sequence of lock_trace structures. Protected by the graph_lock. */ static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; +static struct hlist_head stack_trace_hash[STACK_TRACE_HASH_SIZE]; + +static bool traces_identical(struct lock_trace *t1, struct lock_trace *t2) +{ + return t1->hash == t2->hash && t1->nr_entries == t2->nr_entries && + memcmp(t1->entries, t2->entries, + t1->nr_entries * sizeof(t1->entries[0])) == 0; +} -static int save_trace(struct lock_trace *trace) +static struct lock_trace *save_trace(void) { - unsigned long *entries = stack_trace + nr_stack_trace_entries; + struct lock_trace *trace, *t2; + struct hlist_head *hash_head; + u32 hash; unsigned int max_entries; - trace->offset = nr_stack_trace_entries; - max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries; - trace->nr_entries = stack_trace_save(entries, max_entries, 3); - nr_stack_trace_entries += trace->nr_entries; + BUILD_BUG_ON_NOT_POWER_OF_2(STACK_TRACE_HASH_SIZE); + BUILD_BUG_ON(LOCK_TRACE_SIZE_IN_LONGS >= MAX_STACK_TRACE_ENTRIES); + + trace = (struct lock_trace *)(stack_trace + nr_stack_trace_entries); + max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries - + LOCK_TRACE_SIZE_IN_LONGS; + trace->nr_entries = stack_trace_save(trace->entries, max_entries, 3); - if (nr_stack_trace_entries >= MAX_STACK_TRACE_ENTRIES-1) { + if (nr_stack_trace_entries >= MAX_STACK_TRACE_ENTRIES - + LOCK_TRACE_SIZE_IN_LONGS - 1) { if (!debug_locks_off_graph_unlock()) - return 0; + return NULL; print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!"); dump_stack(); - return 0; + return NULL; } - return 1; + hash = jhash(trace->entries, trace->nr_entries * + sizeof(trace->entries[0]), 0); + trace->hash = hash; + hash_head = stack_trace_hash + (hash & (STACK_TRACE_HASH_SIZE - 1)); + hlist_for_each_entry(t2, hash_head, hash_entry) { + if (traces_identical(trace, t2)) + return t2; + } + nr_stack_trace_entries += LOCK_TRACE_SIZE_IN_LONGS + trace->nr_entries; + hlist_add_head(&trace->hash_entry, hash_head); + + return trace; } #endif @@ -1235,7 +1274,7 @@ static struct lock_list *alloc_list_entry(void) static int add_lock_to_list(struct lock_class *this, struct lock_class *links_to, struct list_head *head, unsigned long ip, int distance, - struct lock_trace *trace) + const struct lock_trace *trace) { struct lock_list *entry; /* @@ -1249,7 +1288,7 @@ static int add_lock_to_list(struct lock_class *this, entry->class = this; entry->links_to = links_to; entry->distance = distance; - entry->trace = *trace; + entry->trace = trace; /* * Both allocation and removal are done under the graph lock; but * iteration is under RCU-sched; see look_up_lock_class() and @@ -1470,11 +1509,10 @@ static inline int __bfs_backwards(struct lock_list *src_entry, } -static void print_lock_trace(struct lock_trace *trace, unsigned int spaces) +static void print_lock_trace(const struct lock_trace *trace, + unsigned int spaces) { - unsigned long *entries = stack_trace + trace->offset; - - stack_trace_print(entries, trace->nr_entries, spaces); + stack_trace_print(trace->entries, trace->nr_entries, spaces); } /* @@ -1489,7 +1527,7 @@ print_circular_bug_entry(struct lock_list *target, int depth) printk("\n-> #%u", depth); print_lock_name(target->class); printk(KERN_CONT ":\n"); - print_lock_trace(&target->trace, 6); + print_lock_trace(target->trace, 6); } static void @@ -1592,7 +1630,8 @@ static noinline void print_circular_bug(struct lock_list *this, if (!debug_locks_off_graph_unlock() || debug_locks_silent) return; - if (!save_trace(&this->trace)) + this->trace = save_trace(); + if (!this->trace) return; depth = get_lock_depth(target); @@ -1715,7 +1754,7 @@ check_path(struct lock_class *target, struct lock_list *src_entry, */ static noinline int check_noncircular(struct held_lock *src, struct held_lock *target, - struct lock_trace *trace) + struct lock_trace **const trace) { int ret; struct lock_list *uninitialized_var(target_entry); @@ -1729,13 +1768,13 @@ check_noncircular(struct held_lock *src, struct held_lock *target, ret = check_path(hlock_class(target), &src_entry, &target_entry); if (unlikely(!ret)) { - if (!trace->nr_entries) { + if (!*trace) { /* * If save_trace fails here, the printing might * trigger a WARN but because of the !nr_entries it * should not do bad things. */ - save_trace(trace); + *trace = save_trace(); } print_circular_bug(&src_entry, target_entry, src, target); @@ -1859,7 +1898,7 @@ static void print_lock_class_header(struct lock_class *class, int depth) len += printk("%*s %s", depth, "", usage_str[bit]); len += printk(KERN_CONT " at:\n"); - print_lock_trace(class->usage_traces + bit, len); + print_lock_trace(class->usage_traces[bit], len); } } printk("%*s }\n", depth, ""); @@ -1884,7 +1923,7 @@ print_shortest_lock_dependencies(struct lock_list *leaf, do { print_lock_class_header(entry->class, depth); printk("%*s ... acquired at:\n", depth, ""); - print_lock_trace(&entry->trace, 2); + print_lock_trace(entry->trace, 2); printk("\n"); if (depth == 0 && (entry != root)) { @@ -1995,14 +2034,14 @@ print_bad_irq_dependency(struct task_struct *curr, print_lock_name(backwards_entry->class); pr_warn("\n... which became %s-irq-safe at:\n", irqclass); - print_lock_trace(backwards_entry->class->usage_traces + bit1, 1); + print_lock_trace(backwards_entry->class->usage_traces[bit1], 1); pr_warn("\nto a %s-irq-unsafe lock:\n", irqclass); print_lock_name(forwards_entry->class); pr_warn("\n... which became %s-irq-unsafe at:\n", irqclass); pr_warn("..."); - print_lock_trace(forwards_entry->class->usage_traces + bit2, 1); + print_lock_trace(forwards_entry->class->usage_traces[bit2], 1); pr_warn("\nother info that might help us debug this:\n\n"); print_irq_lock_scenario(backwards_entry, forwards_entry, @@ -2011,13 +2050,15 @@ print_bad_irq_dependency(struct task_struct *curr, lockdep_print_held_locks(curr); pr_warn("\nthe dependencies between %s-irq-safe lock and the holding lock:\n", irqclass); - if (!save_trace(&prev_root->trace)) + prev_root->trace = save_trace(); + if (!prev_root->trace) return; print_shortest_lock_dependencies(backwards_entry, prev_root); pr_warn("\nthe dependencies between the lock to be acquired"); pr_warn(" and %s-irq-unsafe lock:\n", irqclass); - if (!save_trace(&next_root->trace)) + next_root->trace = save_trace(); + if (!next_root->trace) return; print_shortest_lock_dependencies(forwards_entry, next_root); @@ -2369,7 +2410,8 @@ check_deadlock(struct task_struct *curr, struct held_lock *next) */ static int check_prev_add(struct task_struct *curr, struct held_lock *prev, - struct held_lock *next, int distance, struct lock_trace *trace) + struct held_lock *next, int distance, + struct lock_trace **const trace) { struct lock_list *entry; int ret; @@ -2444,8 +2486,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, return ret; #endif - if (!trace->nr_entries && !save_trace(trace)) - return 0; + if (!*trace) { + *trace = save_trace(); + if (!*trace) + return 0; + } /* * Ok, all validations passed, add the new lock @@ -2453,14 +2498,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, */ ret = add_lock_to_list(hlock_class(next), hlock_class(prev), &hlock_class(prev)->locks_after, - next->acquire_ip, distance, trace); + next->acquire_ip, distance, *trace); if (!ret) return 0; ret = add_lock_to_list(hlock_class(prev), hlock_class(next), &hlock_class(next)->locks_before, - next->acquire_ip, distance, trace); + next->acquire_ip, distance, *trace); if (!ret) return 0; @@ -2476,7 +2521,7 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, static int check_prevs_add(struct task_struct *curr, struct held_lock *next) { - struct lock_trace trace = { .nr_entries = 0 }; + struct lock_trace *trace = NULL; int depth = curr->lockdep_depth; struct held_lock *hlock; @@ -3015,7 +3060,7 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this, print_lock(this); pr_warn("{%s} state was registered at:\n", usage_str[prev_bit]); - print_lock_trace(hlock_class(this)->usage_traces + prev_bit, 1); + print_lock_trace(hlock_class(this)->usage_traces[prev_bit], 1); print_irqtrace_events(curr); pr_warn("\nother info that might help us debug this:\n"); @@ -3096,7 +3141,8 @@ print_irq_inversion_bug(struct task_struct *curr, lockdep_print_held_locks(curr); pr_warn("\nthe shortest dependencies between 2nd lock and 1st lock:\n"); - if (!save_trace(&root->trace)) + root->trace = save_trace(); + if (!root->trace) return; print_shortest_lock_dependencies(other, root); @@ -3580,7 +3626,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, hlock_class(this)->usage_mask |= new_mask; - if (!save_trace(hlock_class(this)->usage_traces + new_bit)) + if (!(hlock_class(this)->usage_traces[new_bit] = save_trace())) return 0; switch (new_bit) { @@ -5157,6 +5203,12 @@ void __init lockdep_init(void) ) / 1024 ); +#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) + printk(" memory used for stack traces: %zu kB\n", + (sizeof(stack_trace) + sizeof(stack_trace_hash)) / 1024 + ); +#endif + printk(" per task-struct memory footprint: %zu bytes\n", sizeof(((struct task_struct *)NULL)->held_locks)); } diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h index 2e518369add4..93a008bf77db 100644 --- a/kernel/locking/lockdep_internals.h +++ b/kernel/locking/lockdep_internals.h @@ -92,6 +92,7 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ = #define MAX_LOCKDEP_ENTRIES 16384UL #define MAX_LOCKDEP_CHAINS_BITS 15 #define MAX_STACK_TRACE_ENTRIES 262144UL +#define STACK_TRACE_HASH_SIZE 8192 #else #define MAX_LOCKDEP_ENTRIES 32768UL @@ -102,6 +103,7 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ = * addresses. Protected by the hash_lock. */ #define MAX_STACK_TRACE_ENTRIES 524288UL +#define STACK_TRACE_HASH_SIZE 16384 #endif #define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) -- GitLab From 8c779229d0f4fe83ead90bdcbbf08b02989aa200 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 22 Jul 2019 11:24:43 -0700 Subject: [PATCH 0616/7155] locking/lockdep: Report more stack trace statistics Report the number of stack traces and the number of stack trace hash chains. These two numbers are useful because these allow to estimate the number of stack trace hash collisions. Signed-off-by: Bart Van Assche Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Waiman Long Cc: Will Deacon Link: https://lkml.kernel.org/r/20190722182443.216015-5-bvanassche@acm.org Signed-off-by: Ingo Molnar --- kernel/locking/lockdep.c | 29 +++++++++++++++++++++++++++++ kernel/locking/lockdep_internals.h | 4 ++++ kernel/locking/lockdep_proc.c | 6 ++++++ 3 files changed, 39 insertions(+) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 1a96869cb2f0..3c3902c40a0e 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -516,6 +516,35 @@ static struct lock_trace *save_trace(void) return trace; } + +/* Return the number of stack traces in the stack_trace[] array. */ +u64 lockdep_stack_trace_count(void) +{ + struct lock_trace *trace; + u64 c = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(stack_trace_hash); i++) { + hlist_for_each_entry(trace, &stack_trace_hash[i], hash_entry) { + c++; + } + } + + return c; +} + +/* Return the number of stack hash chains that have at least one stack trace. */ +u64 lockdep_stack_hash_count(void) +{ + u64 c = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(stack_trace_hash); i++) + if (!hlist_empty(&stack_trace_hash[i])) + c++; + + return c; +} #endif unsigned int nr_hardirq_chains; diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h index 93a008bf77db..18d85aebbb57 100644 --- a/kernel/locking/lockdep_internals.h +++ b/kernel/locking/lockdep_internals.h @@ -140,6 +140,10 @@ extern unsigned int max_bfs_queue_depth; #ifdef CONFIG_PROVE_LOCKING extern unsigned long lockdep_count_forward_deps(struct lock_class *); extern unsigned long lockdep_count_backward_deps(struct lock_class *); +#ifdef CONFIG_TRACE_IRQFLAGS +u64 lockdep_stack_trace_count(void); +u64 lockdep_stack_hash_count(void); +#endif #else static inline unsigned long lockdep_count_forward_deps(struct lock_class *class) diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c index ed9842425cac..dadb7b7fba37 100644 --- a/kernel/locking/lockdep_proc.c +++ b/kernel/locking/lockdep_proc.c @@ -285,6 +285,12 @@ static int lockdep_stats_show(struct seq_file *m, void *v) nr_process_chains); seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n", nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES); +#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) + seq_printf(m, " number of stack traces: %llu\n", + lockdep_stack_trace_count()); + seq_printf(m, " number of stack hash chains: %llu\n", + lockdep_stack_hash_count()); +#endif seq_printf(m, " combined max dependencies: %11u\n", (nr_hardirq_chains + 1) * (nr_softirq_chains + 1) * -- GitLab From e797bda3fd29137f6c151dfa10ea6a61c17895ce Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:16 +0200 Subject: [PATCH 0617/7155] smp/hotplug: Track booted once CPUs in a cpumask The booted once information which is required to deal with the MCE broadcast issue on X86 correctly is stored in the per cpu hotplug state, which is perfectly fine for the intended purpose. X86 needs that information for supporting NMI broadcasting via shortcuts, but retrieving it from per cpu data is cumbersome. Move it to a cpumask so the information can be checked against the cpu_present_mask quickly. No functional change intended. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.818822855@linutronix.de --- include/linux/cpumask.h | 2 ++ kernel/cpu.c | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 21755471b1c3..693124900f0a 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -115,6 +115,8 @@ extern struct cpumask __cpu_active_mask; #define cpu_active(cpu) ((cpu) == 0) #endif +extern cpumask_t cpus_booted_once_mask; + static inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bits) { #ifdef CONFIG_DEBUG_PER_CPU_MAPS diff --git a/kernel/cpu.c b/kernel/cpu.c index e84c0873559e..05778e32674a 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -62,7 +62,6 @@ struct cpuhp_cpu_state { bool rollback; bool single; bool bringup; - bool booted_once; struct hlist_node *node; struct hlist_node *last; enum cpuhp_state cb_state; @@ -76,6 +75,10 @@ static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = { .fail = CPUHP_INVALID, }; +#ifdef CONFIG_SMP +cpumask_t cpus_booted_once_mask; +#endif + #if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP) static struct lockdep_map cpuhp_state_up_map = STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map); @@ -433,7 +436,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu) * CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any * core will shutdown the machine. */ - return !per_cpu(cpuhp_state, cpu).booted_once; + return !cpumask_test_cpu(cpu, &cpus_booted_once_mask); } #else static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } @@ -1066,7 +1069,7 @@ void notify_cpu_starting(unsigned int cpu) int ret; rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */ - st->booted_once = true; + cpumask_set_cpu(cpu, &cpus_booted_once_mask); while (st->state < target) { st->state++; ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); @@ -2334,7 +2337,7 @@ void __init boot_cpu_init(void) void __init boot_cpu_hotplug_init(void) { #ifdef CONFIG_SMP - this_cpu_write(cpuhp_state.booted_once, true); + cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask); #endif this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); } -- GitLab From b9fa6442f7043e2cdd247905d4f3b80f2e9605cb Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:24 +0200 Subject: [PATCH 0618/7155] cpumask: Implement cpumask_or_equal() The IPI code of x86 needs to evaluate whether the target cpumask is equal to the cpu_online_mask or equal except for the calling CPU. To replace the current implementation which requires the usage of a temporary cpumask, which might involve allocations, add a new function which compares a cpumask to the result of two other cpumasks which are or'ed together before comparison. This allows to make the required decision in one go and the calling code then can check for the calling CPU being set in the target mask with cpumask_test_cpu(). Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.585449120@linutronix.de --- include/linux/bitmap.h | 23 +++++++++++++++++++++++ include/linux/cpumask.h | 14 ++++++++++++++ lib/bitmap.c | 20 ++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index f58e97446abc..90528f12bdfa 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -120,6 +120,10 @@ extern int __bitmap_empty(const unsigned long *bitmap, unsigned int nbits); extern int __bitmap_full(const unsigned long *bitmap, unsigned int nbits); extern int __bitmap_equal(const unsigned long *bitmap1, const unsigned long *bitmap2, unsigned int nbits); +extern bool __pure __bitmap_or_equal(const unsigned long *src1, + const unsigned long *src2, + const unsigned long *src3, + unsigned int nbits); extern void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int nbits); extern void __bitmap_shift_right(unsigned long *dst, const unsigned long *src, @@ -321,6 +325,25 @@ static inline int bitmap_equal(const unsigned long *src1, return __bitmap_equal(src1, src2, nbits); } +/** + * bitmap_or_equal - Check whether the or of two bitnaps is equal to a third + * @src1: Pointer to bitmap 1 + * @src2: Pointer to bitmap 2 will be or'ed with bitmap 1 + * @src3: Pointer to bitmap 3. Compare to the result of *@src1 | *@src2 + * + * Returns: True if (*@src1 | *@src2) == *@src3, false otherwise + */ +static inline bool bitmap_or_equal(const unsigned long *src1, + const unsigned long *src2, + const unsigned long *src3, + unsigned int nbits) +{ + if (!small_const_nbits(nbits)) + return __bitmap_or_equal(src1, src2, src3, nbits); + + return !(((*src1 | *src2) ^ *src3) & BITMAP_LAST_WORD_MASK(nbits)); +} + static inline int bitmap_intersects(const unsigned long *src1, const unsigned long *src2, unsigned int nbits) { diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 693124900f0a..0c7db5efe66c 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -475,6 +475,20 @@ static inline bool cpumask_equal(const struct cpumask *src1p, nr_cpumask_bits); } +/** + * cpumask_or_equal - *src1p | *src2p == *src3p + * @src1p: the first input + * @src2p: the second input + * @src3p: the third input + */ +static inline bool cpumask_or_equal(const struct cpumask *src1p, + const struct cpumask *src2p, + const struct cpumask *src3p) +{ + return bitmap_or_equal(cpumask_bits(src1p), cpumask_bits(src2p), + cpumask_bits(src3p), nr_cpumask_bits); +} + /** * cpumask_intersects - (*src1p & *src2p) != 0 * @src1p: the first input diff --git a/lib/bitmap.c b/lib/bitmap.c index bbe2589e8497..f9e834841e94 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -59,6 +59,26 @@ int __bitmap_equal(const unsigned long *bitmap1, } EXPORT_SYMBOL(__bitmap_equal); +bool __bitmap_or_equal(const unsigned long *bitmap1, + const unsigned long *bitmap2, + const unsigned long *bitmap3, + unsigned int bits) +{ + unsigned int k, lim = bits / BITS_PER_LONG; + unsigned long tmp; + + for (k = 0; k < lim; ++k) { + if ((bitmap1[k] | bitmap2[k]) != bitmap3[k]) + return false; + } + + if (!(bits % BITS_PER_LONG)) + return true; + + tmp = (bitmap1[k] | bitmap2[k]) ^ bitmap3[k]; + return (tmp & BITMAP_LAST_WORD_MASK(bits)) == 0; +} + void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int bits) { unsigned int k, lim = BITS_TO_LONGS(bits); -- GitLab From 0c09ab96fc820109d63097a2adcbbd20836b655f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 9 Jul 2019 16:23:40 +0200 Subject: [PATCH 0619/7155] cpu/hotplug: Cache number of online CPUs Re-evaluating the bitmap wheight of the online cpus bitmap in every invocation of num_online_cpus() over and over is a pretty useless exercise. Especially when num_online_cpus() is used in code paths like the IPI delivery of x86 or the membarrier code. Cache the number of online CPUs in the core and just return the cached variable. The accessor function provides only a snapshot when used without protection against concurrent CPU hotplug. The storage needs to use an atomic_t because the kexec and reboot code (ab)use set_cpu_online() in their 'shutdown' handlers without any form of serialization as pointed out by Mathieu. Regular CPU hotplug usage is properly serialized. Signed-off-by: Thomas Gleixner Reviewed-by: Mathieu Desnoyers Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1907091622590.1634@nanos.tec.linutronix.de --- include/linux/cpumask.h | 25 ++++++++++++++++--------- kernel/cpu.c | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 0c7db5efe66c..b5a5a1ed9efd 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -10,6 +10,7 @@ #include #include #include +#include #include /* Don't assign or return these: may not be this big! */ @@ -95,8 +96,21 @@ extern struct cpumask __cpu_active_mask; #define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask) #define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask) +extern atomic_t __num_online_cpus; + #if NR_CPUS > 1 -#define num_online_cpus() cpumask_weight(cpu_online_mask) +/** + * num_online_cpus() - Read the number of online CPUs + * + * Despite the fact that __num_online_cpus is of type atomic_t, this + * interface gives only a momentary snapshot and is not protected against + * concurrent CPU hotplug operations unless invoked from a cpuhp_lock held + * region. + */ +static inline unsigned int num_online_cpus(void) +{ + return atomic_read(&__num_online_cpus); +} #define num_possible_cpus() cpumask_weight(cpu_possible_mask) #define num_present_cpus() cpumask_weight(cpu_present_mask) #define num_active_cpus() cpumask_weight(cpu_active_mask) @@ -821,14 +835,7 @@ set_cpu_present(unsigned int cpu, bool present) cpumask_clear_cpu(cpu, &__cpu_present_mask); } -static inline void -set_cpu_online(unsigned int cpu, bool online) -{ - if (online) - cpumask_set_cpu(cpu, &__cpu_online_mask); - else - cpumask_clear_cpu(cpu, &__cpu_online_mask); -} +void set_cpu_online(unsigned int cpu, bool online); static inline void set_cpu_active(unsigned int cpu, bool active) diff --git a/kernel/cpu.c b/kernel/cpu.c index 05778e32674a..e1967e9eddc2 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2298,6 +2298,9 @@ EXPORT_SYMBOL(__cpu_present_mask); struct cpumask __cpu_active_mask __read_mostly; EXPORT_SYMBOL(__cpu_active_mask); +atomic_t __num_online_cpus __read_mostly; +EXPORT_SYMBOL(__num_online_cpus); + void init_cpu_present(const struct cpumask *src) { cpumask_copy(&__cpu_present_mask, src); @@ -2313,6 +2316,27 @@ void init_cpu_online(const struct cpumask *src) cpumask_copy(&__cpu_online_mask, src); } +void set_cpu_online(unsigned int cpu, bool online) +{ + /* + * atomic_inc/dec() is required to handle the horrid abuse of this + * function by the reboot and kexec code which invoke it from + * IPI/NMI broadcasts when shutting down CPUs. Invocation from + * regular CPU hotplug is properly serialized. + * + * Note, that the fact that __num_online_cpus is of type atomic_t + * does not protect readers which are not serialized against + * concurrent hotplug operations. + */ + if (online) { + if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask)) + atomic_inc(&__num_online_cpus); + } else { + if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask)) + atomic_dec(&__num_online_cpus); + } +} + /* * Activate the first processor. */ -- GitLab From d35927a144641700c8328d707d1c89d305b4ecb8 Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Mon, 15 Jul 2019 11:25:06 +0100 Subject: [PATCH 0620/7155] sched/fair: Move init_numa_balancing() below task_numa_work() To reference task_numa_work() from within init_numa_balancing(), we need the former to be declared before the latter. Do just that. This is a pure code movement. Signed-off-by: Valentin Schneider Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: mgorman@suse.de Cc: riel@surriel.com Link: https://lkml.kernel.org/r/20190715102508.32434-2-valentin.schneider@arm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 82 ++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index bc9cfeaac8bd..f0c488015649 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1188,47 +1188,6 @@ static unsigned int task_scan_max(struct task_struct *p) return max(smin, smax); } -void init_numa_balancing(unsigned long clone_flags, struct task_struct *p) -{ - int mm_users = 0; - struct mm_struct *mm = p->mm; - - if (mm) { - mm_users = atomic_read(&mm->mm_users); - if (mm_users == 1) { - mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay); - mm->numa_scan_seq = 0; - } - } - p->node_stamp = 0; - p->numa_scan_seq = mm ? mm->numa_scan_seq : 0; - p->numa_scan_period = sysctl_numa_balancing_scan_delay; - p->numa_work.next = &p->numa_work; - p->numa_faults = NULL; - RCU_INIT_POINTER(p->numa_group, NULL); - p->last_task_numa_placement = 0; - p->last_sum_exec_runtime = 0; - - /* New address space, reset the preferred nid */ - if (!(clone_flags & CLONE_VM)) { - p->numa_preferred_nid = NUMA_NO_NODE; - return; - } - - /* - * New thread, keep existing numa_preferred_nid which should be copied - * already by arch_dup_task_struct but stagger when scans start. - */ - if (mm) { - unsigned int delay; - - delay = min_t(unsigned int, task_scan_max(current), - current->numa_scan_period * mm_users * NSEC_PER_MSEC); - delay += 2 * TICK_NSEC; - p->node_stamp = delay; - } -} - static void account_numa_enqueue(struct rq *rq, struct task_struct *p) { rq->nr_numa_running += (p->numa_preferred_nid != NUMA_NO_NODE); @@ -2665,6 +2624,47 @@ void task_numa_work(struct callback_head *work) } } +void init_numa_balancing(unsigned long clone_flags, struct task_struct *p) +{ + int mm_users = 0; + struct mm_struct *mm = p->mm; + + if (mm) { + mm_users = atomic_read(&mm->mm_users); + if (mm_users == 1) { + mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay); + mm->numa_scan_seq = 0; + } + } + p->node_stamp = 0; + p->numa_scan_seq = mm ? mm->numa_scan_seq : 0; + p->numa_scan_period = sysctl_numa_balancing_scan_delay; + p->numa_work.next = &p->numa_work; + p->numa_faults = NULL; + RCU_INIT_POINTER(p->numa_group, NULL); + p->last_task_numa_placement = 0; + p->last_sum_exec_runtime = 0; + + /* New address space, reset the preferred nid */ + if (!(clone_flags & CLONE_VM)) { + p->numa_preferred_nid = NUMA_NO_NODE; + return; + } + + /* + * New thread, keep existing numa_preferred_nid which should be copied + * already by arch_dup_task_struct but stagger when scans start. + */ + if (mm) { + unsigned int delay; + + delay = min_t(unsigned int, task_scan_max(current), + current->numa_scan_period * mm_users * NSEC_PER_MSEC); + delay += 2 * TICK_NSEC; + p->node_stamp = delay; + } +} + /* * Drive the periodic memory faults.. */ -- GitLab From b34920d4ce6e6fc9424c20a4be98676eb543122f Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Mon, 15 Jul 2019 11:25:07 +0100 Subject: [PATCH 0621/7155] sched/fair: Move task_numa_work() init to init_numa_balancing() We only need to set the callback_head worker function once, do it during sched_fork(). While at it, move the comment regarding double task_work addition to init_numa_balancing(), since the double add sentinel is first set there. Suggested-by: Peter Zijlstra Signed-off-by: Valentin Schneider Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Thomas Gleixner Cc: mgorman@suse.de Cc: riel@surriel.com Link: https://lkml.kernel.org/r/20190715102508.32434-3-valentin.schneider@arm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f0c488015649..fd391fc00ed8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2495,7 +2495,7 @@ void task_numa_work(struct callback_head *work) SCHED_WARN_ON(p != container_of(work, struct task_struct, numa_work)); - work->next = work; /* protect against double add */ + work->next = work; /* * Who cares about NUMA placement when they're dying. * @@ -2639,12 +2639,15 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p) p->node_stamp = 0; p->numa_scan_seq = mm ? mm->numa_scan_seq : 0; p->numa_scan_period = sysctl_numa_balancing_scan_delay; + /* Protect against double add, see task_tick_numa and task_numa_work */ p->numa_work.next = &p->numa_work; p->numa_faults = NULL; RCU_INIT_POINTER(p->numa_group, NULL); p->last_task_numa_placement = 0; p->last_sum_exec_runtime = 0; + init_task_work(&p->numa_work, task_numa_work); + /* New address space, reset the preferred nid */ if (!(clone_flags & CLONE_VM)) { p->numa_preferred_nid = NUMA_NO_NODE; @@ -2693,10 +2696,8 @@ static void task_tick_numa(struct rq *rq, struct task_struct *curr) curr->numa_scan_period = task_scan_start(curr); curr->node_stamp += period; - if (!time_before(jiffies, curr->mm->numa_next_scan)) { - init_task_work(work, task_numa_work); /* TODO: move this into sched_fork() */ + if (!time_before(jiffies, curr->mm->numa_next_scan)) task_work_add(curr, work, true); - } } } -- GitLab From 9434f9f5d117302cc7ddf038e7879f6871dc7a81 Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Mon, 15 Jul 2019 11:25:08 +0100 Subject: [PATCH 0622/7155] sched/fair: Change task_numa_work() storage to static There are no callers outside of fair.c. Signed-off-by: Valentin Schneider Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: mgorman@suse.de Cc: riel@surriel.com Link: https://lkml.kernel.org/r/20190715102508.32434-4-valentin.schneider@arm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index fd391fc00ed8..b5546a15206c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2482,7 +2482,7 @@ static void reset_ptenuma_scan(struct task_struct *p) * The expensive part of numa migration is done from task_work context. * Triggered from task_tick_numa(). */ -void task_numa_work(struct callback_head *work) +static void task_numa_work(struct callback_head *work) { unsigned long migrate, next_scan, now = jiffies; struct task_struct *p = current; -- GitLab From f6cad8df6b30a5d2bbbd2e698f74b4cafb9fb82b Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Mon, 1 Jul 2019 17:47:02 +0200 Subject: [PATCH 0623/7155] sched/fair: Fix imbalance due to CPU affinity The load_balance() has a dedicated mecanism to detect when an imbalance is due to CPU affinity and must be handled at parent level. In this case, the imbalance field of the parent's sched_group is set. The description of sg_imbalanced() gives a typical example of two groups of 4 CPUs each and 4 tasks each with a cpumask covering 1 CPU of the first group and 3 CPUs of the second group. Something like: { 0 1 2 3 } { 4 5 6 7 } * * * * But the load_balance fails to fix this UC on my octo cores system made of 2 clusters of quad cores. Whereas the load_balance is able to detect that the imbalanced is due to CPU affinity, it fails to fix it because the imbalance field is cleared before letting parent level a chance to run. In fact, when the imbalance is detected, the load_balance reruns without the CPU with pinned tasks. But there is no other running tasks in the situation described above and everything looks balanced this time so the imbalance field is immediately cleared. The imbalance field should not be cleared if there is no other task to move when the imbalance is detected. Signed-off-by: Vincent Guittot Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/1561996022-28829-1-git-send-email-vincent.guittot@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index b5546a15206c..9be36ffb5689 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -9048,9 +9048,10 @@ static int load_balance(int this_cpu, struct rq *this_rq, out_balanced: /* * We reach balance although we may have faced some affinity - * constraints. Clear the imbalance flag if it was set. + * constraints. Clear the imbalance flag only if other tasks got + * a chance to move and fix the imbalance. */ - if (sd_parent) { + if (sd_parent && !(env.flags & LBF_ALL_PINNED)) { int *group_imbalance = &sd_parent->groups->sgc->imbalance; if (*group_imbalance) -- GitLab From 84ec3a0787086fcd25f284f59b3aa01fd6fc0a5d Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 25 Jun 2019 09:52:38 -0700 Subject: [PATCH 0624/7155] time/tick-broadcast: Fix tick_broadcast_offline() lockdep complaint time/tick-broadcast: Fix tick_broadcast_offline() lockdep complaint The TASKS03 and TREE04 rcutorture scenarios produce the following lockdep complaint: WARNING: inconsistent lock state 5.2.0-rc1+ #513 Not tainted -------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. migration/1/14 [HC0[0]:SC0[0]:HE1:SE1] takes: (____ptrval____) (tick_broadcast_lock){?...}, at: tick_broadcast_offline+0xf/0x70 {IN-HARDIRQ-W} state was registered at: lock_acquire+0xb0/0x1c0 _raw_spin_lock_irqsave+0x3c/0x50 tick_broadcast_switch_to_oneshot+0xd/0x40 tick_switch_to_oneshot+0x4f/0xd0 hrtimer_run_queues+0xf3/0x130 run_local_timers+0x1c/0x50 update_process_times+0x1c/0x50 tick_periodic+0x26/0xc0 tick_handle_periodic+0x1a/0x60 smp_apic_timer_interrupt+0x80/0x2a0 apic_timer_interrupt+0xf/0x20 _raw_spin_unlock_irqrestore+0x4e/0x60 rcu_nocb_gp_kthread+0x15d/0x590 kthread+0xf3/0x130 ret_from_fork+0x3a/0x50 irq event stamp: 171 hardirqs last enabled at (171): [] trace_hardirqs_on_thunk+0x1a/0x1c hardirqs last disabled at (170): [] trace_hardirqs_off_thunk+0x1a/0x1c softirqs last enabled at (0): [] copy_process.part.56+0x650/0x1cb0 softirqs last disabled at (0): [<0000000000000000>] 0x0 [...] To reproduce, run the following rcutorture test: $ tools/testing/selftests/rcutorture/bin/kvm.sh --duration 5 --kconfig "CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y" --configs "TASKS03 TREE04" It turns out that tick_broadcast_offline() was an innocent bystander. After all, interrupts are supposed to be disabled throughout take_cpu_down(), and therefore should have been disabled upon entry to tick_offline_cpu() and thus to tick_broadcast_offline(). This suggests that one of the CPU-hotplug notifiers was incorrectly enabling interrupts, and leaving them enabled on return. Some debugging code showed that the culprit was sched_cpu_dying(). It had irqs enabled after return from sched_tick_stop(). Which in turn had irqs enabled after return from cancel_delayed_work_sync(). Which is a wrapper around __cancel_work_timer(). Which can sleep in the case where something else is concurrently trying to cancel the same delayed work, and as Thomas Gleixner pointed out on IRC, sleeping is a decidedly bad idea when you are invoked from take_cpu_down(), regardless of the state you leave interrupts in upon return. Code inspection located no reason why the delayed work absolutely needed to be canceled from sched_tick_stop(): The work is not bound to the outgoing CPU by design, given that the whole point is to collect statistics without disturbing the outgoing CPU. This commit therefore simply drops the cancel_delayed_work_sync() from sched_tick_stop(). Instead, a new ->state field is added to the tick_work structure so that the delayed-work handler function sched_tick_remote() can avoid reposting itself. A cpu_is_offline() check is also added to sched_tick_remote() to avoid mucking with the state of an offlined CPU (though it does appear safe to do so). The sched_tick_start() and sched_tick_stop() functions also update ->state, and sched_tick_start() also schedules the delayed work if ->state indicates that it is not already in flight. Signed-off-by: Paul E. McKenney [ paulmck: Apply Peter Zijlstra and Frederic Weisbecker atomics feedback. ] Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Frederic Weisbecker Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20190625165238.GJ26519@linux.ibm.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 57 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b037f195473..0b22e55cebe8 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3486,8 +3486,36 @@ void scheduler_tick(void) struct tick_work { int cpu; + atomic_t state; struct delayed_work work; }; +/* Values for ->state, see diagram below. */ +#define TICK_SCHED_REMOTE_OFFLINE 0 +#define TICK_SCHED_REMOTE_OFFLINING 1 +#define TICK_SCHED_REMOTE_RUNNING 2 + +/* + * State diagram for ->state: + * + * + * TICK_SCHED_REMOTE_OFFLINE + * | ^ + * | | + * | | sched_tick_remote() + * | | + * | | + * +--TICK_SCHED_REMOTE_OFFLINING + * | ^ + * | | + * sched_tick_start() | | sched_tick_stop() + * | | + * V | + * TICK_SCHED_REMOTE_RUNNING + * + * + * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote() + * and sched_tick_start() are happy to leave the state in RUNNING. + */ static struct tick_work __percpu *tick_work_cpu; @@ -3500,6 +3528,7 @@ static void sched_tick_remote(struct work_struct *work) struct task_struct *curr; struct rq_flags rf; u64 delta; + int os; /* * Handle the tick only if it appears the remote CPU is running in full @@ -3513,7 +3542,7 @@ static void sched_tick_remote(struct work_struct *work) rq_lock_irq(rq, &rf); curr = rq->curr; - if (is_idle_task(curr)) + if (is_idle_task(curr) || cpu_is_offline(cpu)) goto out_unlock; update_rq_clock(rq); @@ -3533,13 +3562,18 @@ static void sched_tick_remote(struct work_struct *work) /* * Run the remote tick once per second (1Hz). This arbitrary * frequency is large enough to avoid overload but short enough - * to keep scheduler internal stats reasonably up to date. + * to keep scheduler internal stats reasonably up to date. But + * first update state to reflect hotplug activity if required. */ - queue_delayed_work(system_unbound_wq, dwork, HZ); + os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING); + WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE); + if (os == TICK_SCHED_REMOTE_RUNNING) + queue_delayed_work(system_unbound_wq, dwork, HZ); } static void sched_tick_start(int cpu) { + int os; struct tick_work *twork; if (housekeeping_cpu(cpu, HK_FLAG_TICK)) @@ -3548,15 +3582,20 @@ static void sched_tick_start(int cpu) WARN_ON_ONCE(!tick_work_cpu); twork = per_cpu_ptr(tick_work_cpu, cpu); - twork->cpu = cpu; - INIT_DELAYED_WORK(&twork->work, sched_tick_remote); - queue_delayed_work(system_unbound_wq, &twork->work, HZ); + os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING); + WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING); + if (os == TICK_SCHED_REMOTE_OFFLINE) { + twork->cpu = cpu; + INIT_DELAYED_WORK(&twork->work, sched_tick_remote); + queue_delayed_work(system_unbound_wq, &twork->work, HZ); + } } #ifdef CONFIG_HOTPLUG_CPU static void sched_tick_stop(int cpu) { struct tick_work *twork; + int os; if (housekeeping_cpu(cpu, HK_FLAG_TICK)) return; @@ -3564,7 +3603,10 @@ static void sched_tick_stop(int cpu) WARN_ON_ONCE(!tick_work_cpu); twork = per_cpu_ptr(tick_work_cpu, cpu); - cancel_delayed_work_sync(&twork->work); + /* There cannot be competing actions, but don't rely on stop-machine. */ + os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING); + WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING); + /* Don't cancel, as this would mess up the state machine. */ } #endif /* CONFIG_HOTPLUG_CPU */ @@ -3572,7 +3614,6 @@ int __init sched_tick_offload_init(void) { tick_work_cpu = alloc_percpu(struct tick_work); BUG_ON(!tick_work_cpu); - return 0; } -- GitLab From 43e9f7f231e40e4534fc3a735da152911a085c16 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 26 Jun 2019 10:36:29 +0530 Subject: [PATCH 0625/7155] sched/fair: Start tracking SCHED_IDLE tasks count in cfs_rq Track how many tasks are present with SCHED_IDLE policy in each cfs_rq. This will be used by later commits. Signed-off-by: Viresh Kumar Signed-off-by: Peter Zijlstra (Intel) Cc: Daniel Lezcano Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vincent Guittot Cc: chris.redpath@arm.com Cc: quentin.perret@linaro.org Cc: songliubraving@fb.com Cc: steven.sistare@oracle.com Cc: subhra.mazumdar@oracle.com Cc: tkjos@google.com Link: https://lkml.kernel.org/r/0d3cdc427fc68808ad5bccc40e86ed0bf9da8bb4.1561523542.git.viresh.kumar@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 14 ++++++++++++-- kernel/sched/sched.h | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 9be36ffb5689..9ed5ab53872f 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4555,7 +4555,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq) struct rq *rq = rq_of(cfs_rq); struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg); struct sched_entity *se; - long task_delta, dequeue = 1; + long task_delta, idle_task_delta, dequeue = 1; bool empty; se = cfs_rq->tg->se[cpu_of(rq_of(cfs_rq))]; @@ -4566,6 +4566,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq) rcu_read_unlock(); task_delta = cfs_rq->h_nr_running; + idle_task_delta = cfs_rq->idle_h_nr_running; for_each_sched_entity(se) { struct cfs_rq *qcfs_rq = cfs_rq_of(se); /* throttled entity or throttle-on-deactivate */ @@ -4575,6 +4576,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq) if (dequeue) dequeue_entity(qcfs_rq, se, DEQUEUE_SLEEP); qcfs_rq->h_nr_running -= task_delta; + qcfs_rq->idle_h_nr_running -= idle_task_delta; if (qcfs_rq->load.weight) dequeue = 0; @@ -4614,7 +4616,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg); struct sched_entity *se; int enqueue = 1; - long task_delta; + long task_delta, idle_task_delta; se = cfs_rq->tg->se[cpu_of(rq)]; @@ -4634,6 +4636,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) return; task_delta = cfs_rq->h_nr_running; + idle_task_delta = cfs_rq->idle_h_nr_running; for_each_sched_entity(se) { if (se->on_rq) enqueue = 0; @@ -4642,6 +4645,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) if (enqueue) enqueue_entity(cfs_rq, se, ENQUEUE_WAKEUP); cfs_rq->h_nr_running += task_delta; + cfs_rq->idle_h_nr_running += idle_task_delta; if (cfs_rq_throttled(cfs_rq)) break; @@ -5255,6 +5259,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) { struct cfs_rq *cfs_rq; struct sched_entity *se = &p->se; + int idle_h_nr_running = task_has_idle_policy(p); /* * The code below (indirectly) updates schedutil which looks at @@ -5287,6 +5292,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) if (cfs_rq_throttled(cfs_rq)) break; cfs_rq->h_nr_running++; + cfs_rq->idle_h_nr_running += idle_h_nr_running; flags = ENQUEUE_WAKEUP; } @@ -5294,6 +5300,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); cfs_rq->h_nr_running++; + cfs_rq->idle_h_nr_running += idle_h_nr_running; if (cfs_rq_throttled(cfs_rq)) break; @@ -5355,6 +5362,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) struct cfs_rq *cfs_rq; struct sched_entity *se = &p->se; int task_sleep = flags & DEQUEUE_SLEEP; + int idle_h_nr_running = task_has_idle_policy(p); for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); @@ -5369,6 +5377,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) if (cfs_rq_throttled(cfs_rq)) break; cfs_rq->h_nr_running--; + cfs_rq->idle_h_nr_running -= idle_h_nr_running; /* Don't dequeue parent if it has other entities besides us */ if (cfs_rq->load.weight) { @@ -5388,6 +5397,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); cfs_rq->h_nr_running--; + cfs_rq->idle_h_nr_running -= idle_h_nr_running; if (cfs_rq_throttled(cfs_rq)) break; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 802b1f3405f2..aaca0e743776 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -483,7 +483,8 @@ struct cfs_rq { struct load_weight load; unsigned long runnable_weight; unsigned int nr_running; - unsigned int h_nr_running; + unsigned int h_nr_running; /* SCHED_{NORMAL,BATCH,IDLE} */ + unsigned int idle_h_nr_running; /* SCHED_IDLE */ u64 exec_clock; u64 min_vruntime; -- GitLab From 3c29e651e16dd3b3179cfb2d055ee9538e37515c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 26 Jun 2019 10:36:30 +0530 Subject: [PATCH 0626/7155] sched/fair: Fall back to sched-idle CPU if idle CPU isn't found We try to find an idle CPU to run the next task, but in case we don't find an idle CPU it is better to pick a CPU which will run the task the soonest, for performance reason. A CPU which isn't idle but has only SCHED_IDLE activity queued on it should be a good target based on this criteria as any normal fair task will most likely preempt the currently running SCHED_IDLE task immediately. In fact, choosing a SCHED_IDLE CPU over a fully idle one shall give better results as it should be able to run the task sooner than an idle CPU (which requires to be woken up from an idle state). This patch updates both fast and slow paths with this optimization. Signed-off-by: Viresh Kumar Signed-off-by: Peter Zijlstra (Intel) Cc: Daniel Lezcano Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vincent Guittot Cc: chris.redpath@arm.com Cc: quentin.perret@linaro.org Cc: songliubraving@fb.com Cc: steven.sistare@oracle.com Cc: subhra.mazumdar@oracle.com Cc: tkjos@google.com Link: https://lkml.kernel.org/r/eeafa25fdeb6f6edd5b2da716bc8f0ba7708cbcf.1561523542.git.viresh.kumar@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 9ed5ab53872f..52564e050062 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5431,6 +5431,15 @@ static struct { #endif /* CONFIG_NO_HZ_COMMON */ +/* CPU only has SCHED_IDLE tasks enqueued */ +static int sched_idle_cpu(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + return unlikely(rq->nr_running == rq->cfs.idle_h_nr_running && + rq->nr_running); +} + static unsigned long cpu_runnable_load(struct rq *rq) { return cfs_rq_runnable_load_avg(&rq->cfs); @@ -5753,7 +5762,7 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this unsigned int min_exit_latency = UINT_MAX; u64 latest_idle_timestamp = 0; int least_loaded_cpu = this_cpu; - int shallowest_idle_cpu = -1; + int shallowest_idle_cpu = -1, si_cpu = -1; int i; /* Check if we have any choice: */ @@ -5784,7 +5793,12 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this latest_idle_timestamp = rq->idle_stamp; shallowest_idle_cpu = i; } - } else if (shallowest_idle_cpu == -1) { + } else if (shallowest_idle_cpu == -1 && si_cpu == -1) { + if (sched_idle_cpu(i)) { + si_cpu = i; + continue; + } + load = cpu_runnable_load(cpu_rq(i)); if (load < min_load) { min_load = load; @@ -5793,7 +5807,11 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this } } - return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu; + if (shallowest_idle_cpu != -1) + return shallowest_idle_cpu; + if (si_cpu != -1) + return si_cpu; + return least_loaded_cpu; } static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p, @@ -5946,7 +5964,7 @@ static int select_idle_core(struct task_struct *p, struct sched_domain *sd, int */ static int select_idle_smt(struct task_struct *p, int target) { - int cpu; + int cpu, si_cpu = -1; if (!static_branch_likely(&sched_smt_present)) return -1; @@ -5956,9 +5974,11 @@ static int select_idle_smt(struct task_struct *p, int target) continue; if (available_idle_cpu(cpu)) return cpu; + if (si_cpu == -1 && sched_idle_cpu(cpu)) + si_cpu = cpu; } - return -1; + return si_cpu; } #else /* CONFIG_SCHED_SMT */ @@ -5986,8 +6006,8 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t u64 avg_cost, avg_idle; u64 time, cost; s64 delta; - int cpu, nr = INT_MAX; int this = smp_processor_id(); + int cpu, nr = INT_MAX, si_cpu = -1; this_sd = rcu_dereference(*this_cpu_ptr(&sd_llc)); if (!this_sd) @@ -6015,11 +6035,13 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t for_each_cpu_wrap(cpu, sched_domain_span(sd), target) { if (!--nr) - return -1; + return si_cpu; if (!cpumask_test_cpu(cpu, p->cpus_ptr)) continue; if (available_idle_cpu(cpu)) break; + if (si_cpu == -1 && sched_idle_cpu(cpu)) + si_cpu = cpu; } time = cpu_clock(this) - time; @@ -6038,13 +6060,14 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) struct sched_domain *sd; int i, recent_used_cpu; - if (available_idle_cpu(target)) + if (available_idle_cpu(target) || sched_idle_cpu(target)) return target; /* * If the previous CPU is cache affine and idle, don't be stupid: */ - if (prev != target && cpus_share_cache(prev, target) && available_idle_cpu(prev)) + if (prev != target && cpus_share_cache(prev, target) && + (available_idle_cpu(prev) || sched_idle_cpu(prev))) return prev; /* Check a recently used CPU as a potential idle candidate: */ @@ -6052,7 +6075,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) if (recent_used_cpu != prev && recent_used_cpu != target && cpus_share_cache(recent_used_cpu, target) && - available_idle_cpu(recent_used_cpu) && + (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) { /* * Replace recent_used_cpu with prev as it is a potential -- GitLab From 7b3c92b85a65c2db1f542265bc98e1f9e3056eba Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Thu, 4 Jul 2019 15:13:23 -0700 Subject: [PATCH 0627/7155] sched/core: Convert get_task_struct() to return the task Returning the pointer that was passed in allows us to write slightly more idiomatic code. Convert a few users. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20190704221323.24290-1-willy@infradead.org Signed-off-by: Ingo Molnar --- include/linux/sched/task.h | 6 +++++- kernel/events/core.c | 9 +++------ kernel/irq/manage.c | 3 +-- kernel/locking/rtmutex.c | 6 ++---- kernel/trace/trace_sched_wakeup.c | 3 +-- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 0497091e40c1..3d90ed8f75f0 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -105,7 +105,11 @@ extern void sched_exec(void); #define sched_exec() {} #endif -#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0) +static inline struct task_struct *get_task_struct(struct task_struct *t) +{ + refcount_inc(&t->usage); + return t; +} extern void __put_task_struct(struct task_struct *t); diff --git a/kernel/events/core.c b/kernel/events/core.c index 026a14541a38..ea5e8139fe62 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4089,10 +4089,8 @@ alloc_perf_context(struct pmu *pmu, struct task_struct *task) return NULL; __perf_event_init_context(ctx); - if (task) { - ctx->task = task; - get_task_struct(task); - } + if (task) + ctx->task = get_task_struct(task); ctx->pmu = pmu; return ctx; @@ -10355,8 +10353,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, * and we cannot use the ctx information because we need the * pmu before we get a ctx. */ - get_task_struct(task); - event->hw.target = task; + event->hw.target = get_task_struct(task); } event->clock = &local_clock; diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e8f7f179bf77..9d50fbe5531a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1255,8 +1255,7 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) * the thread dies to avoid that the interrupt code * references an already freed task_struct. */ - get_task_struct(t); - new->thread = t; + new->thread = get_task_struct(t); /* * Tell the thread to set its affinity. This is * important for shared interrupt handlers as we do diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index fa83d36e30c6..2874bf556162 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -628,8 +628,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, } /* [10] Grab the next task, i.e. owner of @lock */ - task = rt_mutex_owner(lock); - get_task_struct(task); + task = get_task_struct(rt_mutex_owner(lock)); raw_spin_lock(&task->pi_lock); /* @@ -709,8 +708,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, } /* [10] Grab the next task, i.e. the owner of @lock */ - task = rt_mutex_owner(lock); - get_task_struct(task); + task = get_task_struct(rt_mutex_owner(lock)); raw_spin_lock(&task->pi_lock); /* [11] requeue the pi waiters if necessary */ diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 743b2b520d34..5e43b9664eca 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -579,8 +579,7 @@ probe_wakeup(void *ignore, struct task_struct *p) else tracing_dl = 0; - wakeup_task = p; - get_task_struct(wakeup_task); + wakeup_task = get_task_struct(p); local_save_flags(flags); -- GitLab From 65d74e91694e1afac40c96fb64a9ef120757729e Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Fri, 5 Jul 2019 12:35:07 +0800 Subject: [PATCH 0628/7155] sched/stats: Fix unlikely() use of sched_info_on() sched_info_on() is called with unlikely hint, however, the test is to be a constant(1) on which compiler will do nothing when make defconfig, so remove the hint. Also, fix a lack of {}. Signed-off-by: Yi Wang Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: up2wing@gmail.com Cc: wang.liang82@zte.com.cn Cc: xue.zhihong@zte.com.cn Link: https://lkml.kernel.org/r/1562301307-43002-1-git-send-email-wang.yi59@zte.com.cn Signed-off-by: Ingo Molnar --- kernel/sched/stats.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h index aa0de240fb41..ba683fe81a6e 100644 --- a/kernel/sched/stats.h +++ b/kernel/sched/stats.h @@ -157,9 +157,10 @@ static inline void sched_info_dequeued(struct rq *rq, struct task_struct *t) { unsigned long long now = rq_clock(rq), delta = 0; - if (unlikely(sched_info_on())) + if (sched_info_on()) { if (t->sched_info.last_queued) delta = now - t->sched_info.last_queued; + } sched_info_reset_dequeued(t); t->sched_info.run_delay += delta; @@ -192,7 +193,7 @@ static void sched_info_arrive(struct rq *rq, struct task_struct *t) */ static inline void sched_info_queued(struct rq *rq, struct task_struct *t) { - if (unlikely(sched_info_on())) { + if (sched_info_on()) { if (!t->sched_info.last_queued) t->sched_info.last_queued = rq_clock(rq); } @@ -239,7 +240,7 @@ __sched_info_switch(struct rq *rq, struct task_struct *prev, struct task_struct static inline void sched_info_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { - if (unlikely(sched_info_on())) + if (sched_info_on()) __sched_info_switch(rq, prev, next); } -- GitLab From e0e8d4911ed2695b12c3a01c15634000ede9bc73 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Fri, 28 Jun 2019 16:51:41 +0800 Subject: [PATCH 0629/7155] sched/isolation: Prefer housekeeping CPU in local node In real product setup, there will be houseeking CPUs in each nodes, it is prefer to do housekeeping from local node, fallback to global online cpumask if failed to find houseeking CPU from local node. Signed-off-by: Wanpeng Li Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Frederic Weisbecker Reviewed-by: Srikar Dronamraju Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/1561711901-4755-2-git-send-email-wanpengli@tencent.com Signed-off-by: Ingo Molnar --- kernel/sched/isolation.c | 12 ++++++++++-- kernel/sched/sched.h | 8 +++++--- kernel/sched/topology.c | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c index ccb28085b114..9fcb2a695a41 100644 --- a/kernel/sched/isolation.c +++ b/kernel/sched/isolation.c @@ -22,9 +22,17 @@ EXPORT_SYMBOL_GPL(housekeeping_enabled); int housekeeping_any_cpu(enum hk_flags flags) { - if (static_branch_unlikely(&housekeeping_overridden)) - if (housekeeping_flags & flags) + int cpu; + + if (static_branch_unlikely(&housekeeping_overridden)) { + if (housekeeping_flags & flags) { + cpu = sched_numa_find_closest(housekeeping_mask, smp_processor_id()); + if (cpu < nr_cpu_ids) + return cpu; + return cpumask_any_and(housekeeping_mask, cpu_online_mask); + } + } return smp_processor_id(); } EXPORT_SYMBOL_GPL(housekeeping_any_cpu); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index aaca0e743776..16126efd14ed 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1262,16 +1262,18 @@ enum numa_topology_type { extern enum numa_topology_type sched_numa_topology_type; extern int sched_max_numa_distance; extern bool find_numa_distance(int distance); -#endif - -#ifdef CONFIG_NUMA extern void sched_init_numa(void); extern void sched_domains_numa_masks_set(unsigned int cpu); extern void sched_domains_numa_masks_clear(unsigned int cpu); +extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu); #else static inline void sched_init_numa(void) { } static inline void sched_domains_numa_masks_set(unsigned int cpu) { } static inline void sched_domains_numa_masks_clear(unsigned int cpu) { } +static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu) +{ + return nr_cpu_ids; +} #endif #ifdef CONFIG_NUMA_BALANCING diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index f751ce0b783e..4eea2c9bc732 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1724,6 +1724,26 @@ void sched_domains_numa_masks_clear(unsigned int cpu) } } +/* + * sched_numa_find_closest() - given the NUMA topology, find the cpu + * closest to @cpu from @cpumask. + * cpumask: cpumask to find a cpu from + * cpu: cpu to be close to + * + * returns: cpu, or nr_cpu_ids when nothing found. + */ +int sched_numa_find_closest(const struct cpumask *cpus, int cpu) +{ + int i, j = cpu_to_node(cpu); + + for (i = 0; i < sched_domains_numa_levels; i++) { + cpu = cpumask_any_and(cpus, sched_domains_numa_masks[i][j]); + if (cpu < nr_cpu_ids) + return cpu; + } + return nr_cpu_ids; +} + #endif /* CONFIG_NUMA */ static int __sdt_alloc(const struct cpumask *cpu_map) -- GitLab From 60e17f5cef838e9ca7946ced208ceddcec6c315d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 4 Jun 2019 12:31:52 +0530 Subject: [PATCH 0630/7155] sched/fair: Introduce fits_capacity() The same formula to check utilization against capacity (after considering capacity_margin) is already used at 5 different locations. This patch creates a new macro, fits_capacity(), which can be used from all these locations without exposing the details of it and hence simplify code. All the 5 code locations are updated as well to use it.. Signed-off-by: Viresh Kumar Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vincent Guittot Link: https://lkml.kernel.org/r/b477ac75a2b163048bdaeb37f57b4c3f04f75a31.1559631700.git.viresh.kumar@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 52564e050062..fb75c0bea80f 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -96,12 +96,12 @@ int __weak arch_asym_cpu_priority(int cpu) } /* - * The margin used when comparing utilization with CPU capacity: - * util * margin < capacity * 1024 + * The margin used when comparing utilization with CPU capacity. * * (default: ~20%) */ -static unsigned int capacity_margin = 1280; +#define fits_capacity(cap, max) ((cap) * 1280 < (max) * 1024) + #endif #ifdef CONFIG_CFS_BANDWIDTH @@ -3808,7 +3808,7 @@ util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) static inline int task_fits_capacity(struct task_struct *p, long capacity) { - return capacity * 1024 > task_util_est(p) * capacity_margin; + return fits_capacity(task_util_est(p), capacity); } static inline void update_misfit_status(struct task_struct *p, struct rq *rq) @@ -5235,7 +5235,7 @@ static inline unsigned long cpu_util(int cpu); static inline bool cpu_overutilized(int cpu) { - return (capacity_of(cpu) * 1024) < (cpu_util(cpu) * capacity_margin); + return !fits_capacity(cpu_util(cpu), capacity_of(cpu)); } static inline void update_overutilized_status(struct rq *rq) @@ -6456,7 +6456,7 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) /* Skip CPUs that will be overutilized. */ util = cpu_util_next(cpu, p, cpu); cpu_cap = capacity_of(cpu); - if (cpu_cap * 1024 < util * capacity_margin) + if (!fits_capacity(util, cpu_cap)) continue; /* Always use prev_cpu as a candidate. */ @@ -8011,8 +8011,7 @@ group_is_overloaded(struct lb_env *env, struct sg_lb_stats *sgs) static inline bool group_smaller_min_cpu_capacity(struct sched_group *sg, struct sched_group *ref) { - return sg->sgc->min_capacity * capacity_margin < - ref->sgc->min_capacity * 1024; + return fits_capacity(sg->sgc->min_capacity, ref->sgc->min_capacity); } /* @@ -8022,8 +8021,7 @@ group_smaller_min_cpu_capacity(struct sched_group *sg, struct sched_group *ref) static inline bool group_smaller_max_cpu_capacity(struct sched_group *sg, struct sched_group *ref) { - return sg->sgc->max_capacity * capacity_margin < - ref->sgc->max_capacity * 1024; + return fits_capacity(sg->sgc->max_capacity, ref->sgc->max_capacity); } static inline enum -- GitLab From c22645f4c8f021fb1c5e7189eb1f968132cc0844 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Fri, 19 Jul 2019 15:59:53 +0200 Subject: [PATCH 0631/7155] sched/topology: Add partition_sched_domains_locked() Introduce the partition_sched_domains_locked() function by taking the mutex locking code out of the original function. That way the work done by partition_sched_domains_locked() can be reused without dropping the mutex lock. No change of functionality is introduced by this patch. Tested-by: Dietmar Eggemann Signed-off-by: Mathieu Poirier Signed-off-by: Peter Zijlstra (Intel) Acked-by: Tejun Heo Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: rostedt@goodmis.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-2-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- include/linux/sched/topology.h | 10 ++++++++++ kernel/sched/topology.c | 17 +++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h index 7863bb62d2ab..f341163fedc9 100644 --- a/include/linux/sched/topology.h +++ b/include/linux/sched/topology.h @@ -150,6 +150,10 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd) return to_cpumask(sd->span); } +extern void partition_sched_domains_locked(int ndoms_new, + cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new); + extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], struct sched_domain_attr *dattr_new); @@ -194,6 +198,12 @@ extern void set_sched_topology(struct sched_domain_topology_level *tl); struct sched_domain_attr; +static inline void +partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) +{ +} + static inline void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], struct sched_domain_attr *dattr_new) diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 4eea2c9bc732..5a174ae6ecf3 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -2169,16 +2169,16 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, * ndoms_new == 0 is a special case for destroying existing domains, * and it will not create the default domain. * - * Call with hotplug lock held + * Call with hotplug lock and sched_domains_mutex held */ -void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], - struct sched_domain_attr *dattr_new) +void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) { bool __maybe_unused has_eas = false; int i, j, n; int new_topology; - mutex_lock(&sched_domains_mutex); + lockdep_assert_held(&sched_domains_mutex); /* Always unregister in case we don't destroy any domains: */ unregister_sched_domain_sysctl(); @@ -2261,6 +2261,15 @@ void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], ndoms_cur = ndoms_new; register_sched_domain_sysctl(); +} +/* + * Call with hotplug lock held + */ +void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) +{ + mutex_lock(&sched_domains_mutex); + partition_sched_domains_locked(ndoms_new, doms_new, dattr_new); mutex_unlock(&sched_domains_mutex); } -- GitLab From 4b211f2b129dd1f6a6956bbc76e2f232c1ec3ad8 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Fri, 19 Jul 2019 15:59:54 +0200 Subject: [PATCH 0632/7155] sched/core: Streamle calls to task_rq_unlock() Calls to task_rq_unlock() are done several times in the __sched_setscheduler() function. This is fine when only the rq lock needs to be handled but not so much when other locks come into play. This patch streamlines the release of the rq lock so that only one location need to be modified when dealing with more than one lock. No change of functionality is introduced by this patch. Tested-by: Dietmar Eggemann Signed-off-by: Mathieu Poirier Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Steven Rostedt (VMware) Acked-by: Tejun Heo Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-3-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0b22e55cebe8..1af3d2dc6b29 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4712,8 +4712,8 @@ static int __sched_setscheduler(struct task_struct *p, * Changing the policy of the stop threads its a very bad idea: */ if (p == rq->stop) { - task_rq_unlock(rq, p, &rf); - return -EINVAL; + retval = -EINVAL; + goto unlock; } /* @@ -4731,8 +4731,8 @@ static int __sched_setscheduler(struct task_struct *p, goto change; p->sched_reset_on_fork = reset_on_fork; - task_rq_unlock(rq, p, &rf); - return 0; + retval = 0; + goto unlock; } change: @@ -4745,8 +4745,8 @@ static int __sched_setscheduler(struct task_struct *p, if (rt_bandwidth_enabled() && rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0 && !task_group_is_autogroup(task_group(p))) { - task_rq_unlock(rq, p, &rf); - return -EPERM; + retval = -EPERM; + goto unlock; } #endif #ifdef CONFIG_SMP @@ -4761,8 +4761,8 @@ static int __sched_setscheduler(struct task_struct *p, */ if (!cpumask_subset(span, p->cpus_ptr) || rq->rd->dl_bw.bw == 0) { - task_rq_unlock(rq, p, &rf); - return -EPERM; + retval = -EPERM; + goto unlock; } } #endif @@ -4781,8 +4781,8 @@ static int __sched_setscheduler(struct task_struct *p, * is available. */ if ((dl_policy(policy) || dl_task(p)) && sched_dl_overflow(p, policy, attr)) { - task_rq_unlock(rq, p, &rf); - return -EBUSY; + retval = -EBUSY; + goto unlock; } p->sched_reset_on_fork = reset_on_fork; @@ -4840,6 +4840,10 @@ static int __sched_setscheduler(struct task_struct *p, preempt_enable(); return 0; + +unlock: + task_rq_unlock(rq, p, &rf); + return retval; } static int _sched_setscheduler(struct task_struct *p, int policy, -- GitLab From f9a25f776d780bfa3279f0b6e5f5cf3224997976 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Fri, 19 Jul 2019 15:59:55 +0200 Subject: [PATCH 0633/7155] cpusets: Rebuild root domain deadline accounting information When the topology of root domains is modified by CPUset or CPUhotplug operations information about the current deadline bandwidth held in the root domain is lost. This patch addresses the issue by recalculating the lost deadline bandwidth information by circling through the deadline tasks held in CPUsets and adding their current load to the root domain they are associated with. Tested-by: Dietmar Eggemann Signed-off-by: Mathieu Poirier Signed-off-by: Juri Lelli [ Various additional modifications. ] Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-4-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- include/linux/cgroup.h | 1 + include/linux/sched.h | 5 +++ include/linux/sched/deadline.h | 8 +++++ kernel/cgroup/cgroup.c | 2 +- kernel/cgroup/cpuset.c | 64 +++++++++++++++++++++++++++++++++- kernel/sched/deadline.c | 30 ++++++++++++++++ kernel/sched/sched.h | 3 -- kernel/sched/topology.c | 13 ++++++- 8 files changed, 120 insertions(+), 6 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index f6b048902d6c..3ba3e6da13a6 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -150,6 +150,7 @@ struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset, struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset, struct cgroup_subsys_state **dst_cssp); +void cgroup_enable_task_cg_lists(void); void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags, struct css_task_iter *it); struct task_struct *css_task_iter_next(struct css_task_iter *it); diff --git a/include/linux/sched.h b/include/linux/sched.h index 9f51932bd543..b94ad92dfbe6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -295,6 +295,11 @@ enum uclamp_id { UCLAMP_CNT }; +#ifdef CONFIG_SMP +extern struct root_domain def_root_domain; +extern struct mutex sched_domains_mutex; +#endif + struct sched_info { #ifdef CONFIG_SCHED_INFO /* Cumulative counters: */ diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h index 0cb034331cbb..1aff00b65f3c 100644 --- a/include/linux/sched/deadline.h +++ b/include/linux/sched/deadline.h @@ -24,3 +24,11 @@ static inline bool dl_time_before(u64 a, u64 b) { return (s64)(a - b) < 0; } + +#ifdef CONFIG_SMP + +struct root_domain; +extern void dl_add_task_root_domain(struct task_struct *p); +extern void dl_clear_root_domain(struct root_domain *rd); + +#endif /* CONFIG_SMP */ diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 753afbca549f..4b5bc452176c 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -1891,7 +1891,7 @@ static int cgroup_reconfigure(struct fs_context *fc) */ static bool use_task_css_set_links __read_mostly; -static void cgroup_enable_task_cg_lists(void) +void cgroup_enable_task_cg_lists(void) { struct task_struct *p, *g; diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 5aa37531ce76..846cbdb68566 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -894,6 +895,67 @@ static int generate_sched_domains(cpumask_var_t **domains, return ndoms; } +static void update_tasks_root_domain(struct cpuset *cs) +{ + struct css_task_iter it; + struct task_struct *task; + + css_task_iter_start(&cs->css, 0, &it); + + while ((task = css_task_iter_next(&it))) + dl_add_task_root_domain(task); + + css_task_iter_end(&it); +} + +static void rebuild_root_domains(void) +{ + struct cpuset *cs = NULL; + struct cgroup_subsys_state *pos_css; + + lockdep_assert_held(&cpuset_mutex); + lockdep_assert_cpus_held(); + lockdep_assert_held(&sched_domains_mutex); + + cgroup_enable_task_cg_lists(); + + rcu_read_lock(); + + /* + * Clear default root domain DL accounting, it will be computed again + * if a task belongs to it. + */ + dl_clear_root_domain(&def_root_domain); + + cpuset_for_each_descendant_pre(cs, pos_css, &top_cpuset) { + + if (cpumask_empty(cs->effective_cpus)) { + pos_css = css_rightmost_descendant(pos_css); + continue; + } + + css_get(&cs->css); + + rcu_read_unlock(); + + update_tasks_root_domain(cs); + + rcu_read_lock(); + css_put(&cs->css); + } + rcu_read_unlock(); +} + +static void +partition_and_rebuild_sched_domains(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) +{ + mutex_lock(&sched_domains_mutex); + partition_sched_domains_locked(ndoms_new, doms_new, dattr_new); + rebuild_root_domains(); + mutex_unlock(&sched_domains_mutex); +} + /* * Rebuild scheduler domains. * @@ -931,7 +993,7 @@ static void rebuild_sched_domains_locked(void) ndoms = generate_sched_domains(&doms, &attr); /* Have scheduler rebuild the domains */ - partition_sched_domains(ndoms, doms, attr); + partition_and_rebuild_sched_domains(ndoms, doms, attr); out: put_online_cpus(); } diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index ef5b9f6b1d42..0f9d2180be23 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -2283,6 +2283,36 @@ void __init init_sched_dl_class(void) GFP_KERNEL, cpu_to_node(i)); } +void dl_add_task_root_domain(struct task_struct *p) +{ + struct rq_flags rf; + struct rq *rq; + struct dl_bw *dl_b; + + rq = task_rq_lock(p, &rf); + if (!dl_task(p)) + goto unlock; + + dl_b = &rq->rd->dl_bw; + raw_spin_lock(&dl_b->lock); + + __dl_add(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span)); + + raw_spin_unlock(&dl_b->lock); + +unlock: + task_rq_unlock(rq, p, &rf); +} + +void dl_clear_root_domain(struct root_domain *rd) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&rd->dl_bw.lock, flags); + rd->dl_bw.total_bw = 0; + raw_spin_unlock_irqrestore(&rd->dl_bw.lock, flags); +} + #endif /* CONFIG_SMP */ static void switched_from_dl(struct rq *rq, struct task_struct *p) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 16126efd14ed..7583faddba33 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -778,9 +778,6 @@ struct root_domain { struct perf_domain __rcu *pd; }; -extern struct root_domain def_root_domain; -extern struct mutex sched_domains_mutex; - extern void init_defrootdomain(void); extern int sched_init_domains(const struct cpumask *cpu_map); extern void rq_attach_root(struct rq *rq, struct root_domain *rd); diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 5a174ae6ecf3..8f83e8e3ea9a 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -2203,8 +2203,19 @@ void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], for (i = 0; i < ndoms_cur; i++) { for (j = 0; j < n && !new_topology; j++) { if (cpumask_equal(doms_cur[i], doms_new[j]) && - dattrs_equal(dattr_cur, i, dattr_new, j)) + dattrs_equal(dattr_cur, i, dattr_new, j)) { + struct root_domain *rd; + + /* + * This domain won't be destroyed and as such + * its dl_bw->total_bw needs to be cleared. It + * will be recomputed in function + * update_tasks_root_domain(). + */ + rd = cpu_rq(cpumask_any(doms_cur[i]))->rd; + dl_clear_root_domain(rd); goto match1; + } } /* No match - a current sched domain not in new doms_new[] */ detach_destroy_domains(doms_cur[i]); -- GitLab From 59d06cea1198d665ba11f7e8c5f45b00ff2e4812 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 15:59:56 +0200 Subject: [PATCH 0634/7155] sched/deadline: Fix bandwidth accounting at all levels after offline migration If a task happens to be throttled while the CPU it was running on gets hotplugged off, the bandwidth associated with the task is not correctly migrated with it when the replenishment timer fires (offline_migration). Fix things up, for this_bw, running_bw and total_bw, when replenishment timer fires and task is migrated (dl_task_offline_migration()). Tested-by: Dietmar Eggemann Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: mathieu.poirier@linaro.org Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-5-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- kernel/sched/deadline.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 0f9d2180be23..039dde2b1dac 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -529,6 +529,7 @@ static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq); static struct rq *dl_task_offline_migration(struct rq *rq, struct task_struct *p) { struct rq *later_rq = NULL; + struct dl_bw *dl_b; later_rq = find_lock_later_rq(p, rq); if (!later_rq) { @@ -557,6 +558,38 @@ static struct rq *dl_task_offline_migration(struct rq *rq, struct task_struct *p double_lock_balance(rq, later_rq); } + if (p->dl.dl_non_contending || p->dl.dl_throttled) { + /* + * Inactive timer is armed (or callback is running, but + * waiting for us to release rq locks). In any case, when it + * will fire (or continue), it will see running_bw of this + * task migrated to later_rq (and correctly handle it). + */ + sub_running_bw(&p->dl, &rq->dl); + sub_rq_bw(&p->dl, &rq->dl); + + add_rq_bw(&p->dl, &later_rq->dl); + add_running_bw(&p->dl, &later_rq->dl); + } else { + sub_rq_bw(&p->dl, &rq->dl); + add_rq_bw(&p->dl, &later_rq->dl); + } + + /* + * And we finally need to fixup root_domain(s) bandwidth accounting, + * since p is still hanging out in the old (now moved to default) root + * domain. + */ + dl_b = &rq->rd->dl_bw; + raw_spin_lock(&dl_b->lock); + __dl_sub(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span)); + raw_spin_unlock(&dl_b->lock); + + dl_b = &later_rq->rd->dl_bw; + raw_spin_lock(&dl_b->lock); + __dl_add(dl_b, p->dl.dl_bw, cpumask_weight(later_rq->rd->span)); + raw_spin_unlock(&dl_b->lock); + set_task_cpu(p, later_rq->cpu); double_unlock_balance(later_rq, rq); -- GitLab From 1243dc518c9da467da6635313a2dbb41b8ffc275 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 15:59:57 +0200 Subject: [PATCH 0635/7155] cgroup/cpuset: Convert cpuset_mutex to percpu_rwsem Holding cpuset_mutex means that cpusets are stable (only the holder can make changes) and this is required for fixing a synchronization issue between cpusets and scheduler core. However, grabbing cpuset_mutex from setscheduler() hotpath (as implemented in a later patch) is a no-go, as it would create a bottleneck for tasks concurrently calling setscheduler(). Convert cpuset_mutex to be a percpu_rwsem (cpuset_rwsem), so that setscheduler() will then be able to read lock it and avoid concurrency issues. Tested-by: Dietmar Eggemann Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: mathieu.poirier@linaro.org Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-6-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- kernel/cgroup/cpuset.c | 68 ++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 846cbdb68566..e1a8d168c5e9 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -333,7 +333,7 @@ static struct cpuset top_cpuset = { * guidelines for accessing subsystem state in kernel/cgroup.c */ -static DEFINE_MUTEX(cpuset_mutex); +DEFINE_STATIC_PERCPU_RWSEM(cpuset_rwsem); static DEFINE_SPINLOCK(callback_lock); static struct workqueue_struct *cpuset_migrate_mm_wq; @@ -913,7 +913,7 @@ static void rebuild_root_domains(void) struct cpuset *cs = NULL; struct cgroup_subsys_state *pos_css; - lockdep_assert_held(&cpuset_mutex); + percpu_rwsem_assert_held(&cpuset_rwsem); lockdep_assert_cpus_held(); lockdep_assert_held(&sched_domains_mutex); @@ -973,7 +973,7 @@ static void rebuild_sched_domains_locked(void) cpumask_var_t *doms; int ndoms; - lockdep_assert_held(&cpuset_mutex); + percpu_rwsem_assert_held(&cpuset_rwsem); get_online_cpus(); /* @@ -1005,9 +1005,9 @@ static void rebuild_sched_domains_locked(void) void rebuild_sched_domains(void) { - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); rebuild_sched_domains_locked(); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } /** @@ -1113,7 +1113,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd, int deleting; /* Moving cpus from subparts_cpus to effective_cpus */ bool part_error = false; /* Partition error? */ - lockdep_assert_held(&cpuset_mutex); + percpu_rwsem_assert_held(&cpuset_rwsem); /* * The parent must be a partition root. @@ -2101,7 +2101,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css)); cs = css_cs(css); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); /* allow moving tasks into an empty cpuset if on default hierarchy */ ret = -ENOSPC; @@ -2125,7 +2125,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) cs->attach_in_progress++; ret = 0; out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); return ret; } @@ -2135,9 +2135,9 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset) cgroup_taskset_first(tset, &css); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); css_cs(css)->attach_in_progress--; - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } /* @@ -2160,7 +2160,7 @@ static void cpuset_attach(struct cgroup_taskset *tset) cgroup_taskset_first(tset, &css); cs = css_cs(css); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); /* prepare for attach */ if (cs == &top_cpuset) @@ -2214,7 +2214,7 @@ static void cpuset_attach(struct cgroup_taskset *tset) if (!cs->attach_in_progress) wake_up(&cpuset_attach_wq); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } /* The various types of files and directories in a cpuset file system */ @@ -2245,7 +2245,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft, cpuset_filetype_t type = cft->private; int retval = 0; - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) { retval = -ENODEV; goto out_unlock; @@ -2281,7 +2281,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft, break; } out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); return retval; } @@ -2292,7 +2292,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft, cpuset_filetype_t type = cft->private; int retval = -ENODEV; - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; @@ -2305,7 +2305,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft, break; } out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); return retval; } @@ -2344,7 +2344,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of, kernfs_break_active_protection(of->kn); flush_work(&cpuset_hotplug_work); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; @@ -2368,7 +2368,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of, free_cpuset(trialcs); out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); kernfs_unbreak_active_protection(of->kn); css_put(&cs->css); flush_workqueue(cpuset_migrate_mm_wq); @@ -2499,13 +2499,13 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf, return -EINVAL; css_get(&cs->css); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; retval = update_prstate(cs, val); out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); css_put(&cs->css); return retval ?: nbytes; } @@ -2711,7 +2711,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) if (!parent) return 0; - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); set_bit(CS_ONLINE, &cs->flags); if (is_spread_page(parent)) @@ -2762,7 +2762,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) cpumask_copy(cs->effective_cpus, parent->cpus_allowed); spin_unlock_irq(&callback_lock); out_unlock: - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); return 0; } @@ -2781,7 +2781,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) { struct cpuset *cs = css_cs(css); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); if (is_partition_root(cs)) update_prstate(cs, 0); @@ -2800,7 +2800,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) cpuset_dec(); clear_bit(CS_ONLINE, &cs->flags); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } static void cpuset_css_free(struct cgroup_subsys_state *css) @@ -2812,7 +2812,7 @@ static void cpuset_css_free(struct cgroup_subsys_state *css) static void cpuset_bind(struct cgroup_subsys_state *root_css) { - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); spin_lock_irq(&callback_lock); if (is_in_v2_mode()) { @@ -2825,7 +2825,7 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css) } spin_unlock_irq(&callback_lock); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } /* @@ -2867,6 +2867,8 @@ struct cgroup_subsys cpuset_cgrp_subsys = { int __init cpuset_init(void) { + BUG_ON(percpu_init_rwsem(&cpuset_rwsem)); + BUG_ON(!alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_KERNEL)); BUG_ON(!alloc_cpumask_var(&top_cpuset.effective_cpus, GFP_KERNEL)); BUG_ON(!zalloc_cpumask_var(&top_cpuset.subparts_cpus, GFP_KERNEL)); @@ -2938,7 +2940,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs, is_empty = cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); /* * Move tasks to the nearest ancestor with execution resources, @@ -2948,7 +2950,7 @@ hotplug_update_tasks_legacy(struct cpuset *cs, if (is_empty) remove_tasks_in_empty_cpuset(cs); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); } static void @@ -2998,14 +3000,14 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp) retry: wait_event(cpuset_attach_wq, cs->attach_in_progress == 0); - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); /* * We have raced with task attaching. We wait until attaching * is finished, so we won't attach a task to an empty cpuset. */ if (cs->attach_in_progress) { - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); goto retry; } @@ -3073,7 +3075,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp) hotplug_update_tasks_legacy(cs, &new_cpus, &new_mems, cpus_updated, mems_updated); - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); } /** @@ -3103,7 +3105,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work) if (on_dfl && !alloc_cpumasks(NULL, &tmp)) ptmp = &tmp; - mutex_lock(&cpuset_mutex); + percpu_down_write(&cpuset_rwsem); /* fetch the available cpus/mems and find out which changed how */ cpumask_copy(&new_cpus, cpu_active_mask); @@ -3153,7 +3155,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work) update_tasks_nodemask(&top_cpuset); } - mutex_unlock(&cpuset_mutex); + percpu_up_write(&cpuset_rwsem); /* if cpus or mems changed, we need to propagate to descendants */ if (cpus_updated || mems_updated) { -- GitLab From d74b27d63a8bebe2fe634944e4ebdc7b10db7a39 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 15:59:58 +0200 Subject: [PATCH 0636/7155] cgroup/cpuset: Change cpuset_rwsem and hotplug lock order cpuset_rwsem is going to be acquired from sched_setscheduler() with a following patch. There are however paths (e.g., spawn_ksoftirqd) in which sched_scheduler() is eventually called while holding hotplug lock; this creates a dependecy between hotplug lock (to be always acquired first) and cpuset_rwsem (to be always acquired after hotplug lock). Fix paths which currently take the two locks in the wrong order (after a following patch is applied). Tested-by: Dietmar Eggemann Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: mathieu.poirier@linaro.org Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-7-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- include/linux/cpuset.h | 8 ++++---- kernel/cgroup/cpuset.c | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 934633a05d20..7f1478c26a33 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -40,14 +40,14 @@ static inline bool cpusets_enabled(void) static inline void cpuset_inc(void) { - static_branch_inc(&cpusets_pre_enable_key); - static_branch_inc(&cpusets_enabled_key); + static_branch_inc_cpuslocked(&cpusets_pre_enable_key); + static_branch_inc_cpuslocked(&cpusets_enabled_key); } static inline void cpuset_dec(void) { - static_branch_dec(&cpusets_enabled_key); - static_branch_dec(&cpusets_pre_enable_key); + static_branch_dec_cpuslocked(&cpusets_enabled_key); + static_branch_dec_cpuslocked(&cpusets_pre_enable_key); } extern int cpuset_init(void); diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index e1a8d168c5e9..5c5014caa23c 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -973,8 +973,8 @@ static void rebuild_sched_domains_locked(void) cpumask_var_t *doms; int ndoms; + lockdep_assert_cpus_held(); percpu_rwsem_assert_held(&cpuset_rwsem); - get_online_cpus(); /* * We have raced with CPU hotplug. Don't do anything to avoid @@ -983,19 +983,17 @@ static void rebuild_sched_domains_locked(void) */ if (!top_cpuset.nr_subparts_cpus && !cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask)) - goto out; + return; if (top_cpuset.nr_subparts_cpus && !cpumask_subset(top_cpuset.effective_cpus, cpu_active_mask)) - goto out; + return; /* Generate domain masks and attrs */ ndoms = generate_sched_domains(&doms, &attr); /* Have scheduler rebuild the domains */ partition_and_rebuild_sched_domains(ndoms, doms, attr); -out: - put_online_cpus(); } #else /* !CONFIG_SMP */ static void rebuild_sched_domains_locked(void) @@ -1005,9 +1003,11 @@ static void rebuild_sched_domains_locked(void) void rebuild_sched_domains(void) { + get_online_cpus(); percpu_down_write(&cpuset_rwsem); rebuild_sched_domains_locked(); percpu_up_write(&cpuset_rwsem); + put_online_cpus(); } /** @@ -2245,6 +2245,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft, cpuset_filetype_t type = cft->private; int retval = 0; + get_online_cpus(); percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) { retval = -ENODEV; @@ -2282,6 +2283,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft, } out_unlock: percpu_up_write(&cpuset_rwsem); + put_online_cpus(); return retval; } @@ -2292,6 +2294,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft, cpuset_filetype_t type = cft->private; int retval = -ENODEV; + get_online_cpus(); percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; @@ -2306,6 +2309,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft, } out_unlock: percpu_up_write(&cpuset_rwsem); + put_online_cpus(); return retval; } @@ -2344,6 +2348,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of, kernfs_break_active_protection(of->kn); flush_work(&cpuset_hotplug_work); + get_online_cpus(); percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; @@ -2369,6 +2374,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of, free_cpuset(trialcs); out_unlock: percpu_up_write(&cpuset_rwsem); + put_online_cpus(); kernfs_unbreak_active_protection(of->kn); css_put(&cs->css); flush_workqueue(cpuset_migrate_mm_wq); @@ -2499,6 +2505,7 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf, return -EINVAL; css_get(&cs->css); + get_online_cpus(); percpu_down_write(&cpuset_rwsem); if (!is_cpuset_online(cs)) goto out_unlock; @@ -2506,6 +2513,7 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf, retval = update_prstate(cs, val); out_unlock: percpu_up_write(&cpuset_rwsem); + put_online_cpus(); css_put(&cs->css); return retval ?: nbytes; } @@ -2711,6 +2719,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) if (!parent) return 0; + get_online_cpus(); percpu_down_write(&cpuset_rwsem); set_bit(CS_ONLINE, &cs->flags); @@ -2763,6 +2772,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) spin_unlock_irq(&callback_lock); out_unlock: percpu_up_write(&cpuset_rwsem); + put_online_cpus(); return 0; } @@ -2781,6 +2791,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) { struct cpuset *cs = css_cs(css); + get_online_cpus(); percpu_down_write(&cpuset_rwsem); if (is_partition_root(cs)) @@ -2801,6 +2812,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) clear_bit(CS_ONLINE, &cs->flags); percpu_up_write(&cpuset_rwsem); + put_online_cpus(); } static void cpuset_css_free(struct cgroup_subsys_state *css) -- GitLab From 1a763fd7c6335e3122c1cc09576ef6c99ada4267 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 15:59:59 +0200 Subject: [PATCH 0637/7155] rcu/tree: Call setschedule() gp ktread to SCHED_FIFO outside of atomic region sched_setscheduler() needs to acquire cpuset_rwsem, but it is currently called from an invalid (atomic) context by rcu_spawn_gp_kthread(). Fix that by simply moving sched_setscheduler_nocheck() call outside of the atomic region, as it doesn't actually require to be guarded by rcu_node lock. Suggested-by: Peter Zijlstra Tested-by: Dietmar Eggemann Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: mathieu.poirier@linaro.org Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-8-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- kernel/rcu/tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a14e5fbbea46..eb764c24bc4d 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3234,13 +3234,13 @@ static int __init rcu_spawn_gp_kthread(void) t = kthread_create(rcu_gp_kthread, NULL, "%s", rcu_state.name); if (WARN_ONCE(IS_ERR(t), "%s: Could not start grace-period kthread, OOM is now expected behavior\n", __func__)) return 0; + if (kthread_prio) + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); rnp = rcu_get_root(); raw_spin_lock_irqsave_rcu_node(rnp, flags); rcu_state.gp_kthread = t; - if (kthread_prio) { + if (kthread_prio) sp.sched_priority = kthread_prio; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - } raw_spin_unlock_irqrestore_rcu_node(rnp, flags); wake_up_process(t); rcu_spawn_nocb_kthreads(); -- GitLab From 710da3c8ea7dfbd327920afd3831d8c82c42789d Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 16:00:00 +0200 Subject: [PATCH 0638/7155] sched/core: Prevent race condition between cpuset and __sched_setscheduler() No synchronisation mechanism exists between the cpuset subsystem and calls to function __sched_setscheduler(). As such, it is possible that new root domains are created on the cpuset side while a deadline acceptance test is carried out in __sched_setscheduler(), leading to a potential oversell of CPU bandwidth. Grab cpuset_rwsem read lock from core scheduler, so to prevent situations such as the one described above from happening. The only exception is normalize_rt_tasks() which needs to work under tasklist_lock and can't therefore grab cpuset_rwsem. We are fine with this, as this function is only called by sysrq and, if that gets triggered, DEADLINE guarantees are already gone out of the window anyway. Tested-by: Dietmar Eggemann Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bristot@redhat.com Cc: claudio@evidence.eu.com Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: mathieu.poirier@linaro.org Cc: rostedt@goodmis.org Cc: tj@kernel.org Cc: tommaso.cucinotta@santannapisa.it Link: https://lkml.kernel.org/r/20190719140000.31694-9-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- include/linux/cpuset.h | 5 +++++ kernel/cgroup/cpuset.c | 11 +++++++++++ kernel/sched/core.c | 20 +++++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 7f1478c26a33..04c20de66afc 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -55,6 +55,8 @@ extern void cpuset_init_smp(void); extern void cpuset_force_rebuild(void); extern void cpuset_update_active_cpus(void); extern void cpuset_wait_for_hotplug(void); +extern void cpuset_read_lock(void); +extern void cpuset_read_unlock(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); extern void cpuset_cpus_allowed_fallback(struct task_struct *p); extern nodemask_t cpuset_mems_allowed(struct task_struct *p); @@ -176,6 +178,9 @@ static inline void cpuset_update_active_cpus(void) static inline void cpuset_wait_for_hotplug(void) { } +static inline void cpuset_read_lock(void) { } +static inline void cpuset_read_unlock(void) { } + static inline void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask) { diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 5c5014caa23c..c52bc91f882b 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -334,6 +334,17 @@ static struct cpuset top_cpuset = { */ DEFINE_STATIC_PERCPU_RWSEM(cpuset_rwsem); + +void cpuset_read_lock(void) +{ + percpu_down_read(&cpuset_rwsem); +} + +void cpuset_read_unlock(void) +{ + percpu_up_read(&cpuset_rwsem); +} + static DEFINE_SPINLOCK(callback_lock); static struct workqueue_struct *cpuset_migrate_mm_wq; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1af3d2dc6b29..1bceb22dac18 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4698,6 +4698,9 @@ static int __sched_setscheduler(struct task_struct *p, return retval; } + if (pi) + cpuset_read_lock(); + /* * Make sure no PI-waiters arrive (or leave) while we are * changing the priority of the task: @@ -4772,6 +4775,8 @@ static int __sched_setscheduler(struct task_struct *p, if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { policy = oldpolicy = -1; task_rq_unlock(rq, p, &rf); + if (pi) + cpuset_read_unlock(); goto recheck; } @@ -4832,8 +4837,10 @@ static int __sched_setscheduler(struct task_struct *p, preempt_disable(); task_rq_unlock(rq, p, &rf); - if (pi) + if (pi) { + cpuset_read_unlock(); rt_mutex_adjust_pi(p); + } /* Run balance callbacks after we've adjusted the PI chain: */ balance_callback(rq); @@ -4843,6 +4850,8 @@ static int __sched_setscheduler(struct task_struct *p, unlock: task_rq_unlock(rq, p, &rf); + if (pi) + cpuset_read_unlock(); return retval; } @@ -4927,10 +4936,15 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) rcu_read_lock(); retval = -ESRCH; p = find_process_by_pid(pid); - if (p != NULL) - retval = sched_setscheduler(p, policy, &lparam); + if (likely(p)) + get_task_struct(p); rcu_read_unlock(); + if (likely(p)) { + retval = sched_setscheduler(p, policy, &lparam); + put_task_struct(p); + } + return retval; } -- GitLab From a07db5c0865799ebed1f88be0df50c581fb65029 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 19 Jul 2019 08:34:55 +0200 Subject: [PATCH 0639/7155] sched/core: Fix CPU controller for !RT_GROUP_SCHED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On !CONFIG_RT_GROUP_SCHED configurations it is currently not possible to move RT tasks between cgroups to which CPU controller has been attached; but it is oddly possible to first move tasks around and then make them RT (setschedule to FIFO/RR). E.g.: # mkdir /sys/fs/cgroup/cpu,cpuacct/group1 # chrt -fp 10 $$ # echo $$ > /sys/fs/cgroup/cpu,cpuacct/group1/tasks bash: echo: write error: Invalid argument # chrt -op 0 $$ # echo $$ > /sys/fs/cgroup/cpu,cpuacct/group1/tasks # chrt -fp 10 $$ # cat /sys/fs/cgroup/cpu,cpuacct/group1/tasks 2345 2598 # chrt -p 2345 pid 2345's current scheduling policy: SCHED_FIFO pid 2345's current scheduling priority: 10 Also, as Michal noted, it is currently not possible to enable CPU controller on unified hierarchy with !CONFIG_RT_GROUP_SCHED (if there are any kernel RT threads in root cgroup, they can't be migrated to the newly created CPU controller's root in cgroup_update_dfl_csses()). Existing code comes with a comment saying the "we don't support RT-tasks being in separate groups". Such comment is however stale and belongs to pre-RT_GROUP_SCHED times. Also, it doesn't make much sense for !RT_GROUP_ SCHED configurations, since checks related to RT bandwidth are not performed at all in these cases. Make moving RT tasks between CPU controller groups viable by removing special case check for RT (and DEADLINE) tasks. Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Michal Koutný Reviewed-by: Daniel Bristot de Oliveira Acked-by: Tejun Heo Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: lizefan@huawei.com Cc: longman@redhat.com Cc: luca.abeni@santannapisa.it Cc: rostedt@goodmis.org Link: https://lkml.kernel.org/r/20190719063455.27328-1-juri.lelli@redhat.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1bceb22dac18..042c736b2b73 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6995,10 +6995,6 @@ static int cpu_cgroup_can_attach(struct cgroup_taskset *tset) #ifdef CONFIG_RT_GROUP_SCHED if (!sched_rt_can_attach(css_tg(css), task)) return -EINVAL; -#else - /* We don't support RT-tasks being in separate groups */ - if (task->sched_class != &fair_sched_class) - return -EINVAL; #endif /* * Serialize against wake_up_new_task() such that if its -- GitLab From a1dc0446d64966dc0ae756aebdc449f335742c13 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Fri, 19 Jul 2019 21:23:19 -0400 Subject: [PATCH 0640/7155] sched/core: Silence a warning in sched_init() Compiling a kernel with both FAIR_GROUP_SCHED=n and RT_GROUP_SCHED=n will generate a compiler warning: kernel/sched/core.c: In function 'sched_init': kernel/sched/core.c:5906:32: warning: variable 'ptr' set but not used It is unnecessary to have both "alloc_size" and "ptr", so just combine them. Signed-off-by: Qian Cai Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: valentin.schneider@arm.com Link: https://lkml.kernel.org/r/20190720012319.884-1-cai@lca.pw Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 042c736b2b73..46f3ca9e392a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6430,19 +6430,19 @@ DECLARE_PER_CPU(cpumask_var_t, select_idle_mask); void __init sched_init(void) { - unsigned long alloc_size = 0, ptr; + unsigned long ptr = 0; int i; wait_bit_init(); #ifdef CONFIG_FAIR_GROUP_SCHED - alloc_size += 2 * nr_cpu_ids * sizeof(void **); + ptr += 2 * nr_cpu_ids * sizeof(void **); #endif #ifdef CONFIG_RT_GROUP_SCHED - alloc_size += 2 * nr_cpu_ids * sizeof(void **); + ptr += 2 * nr_cpu_ids * sizeof(void **); #endif - if (alloc_size) { - ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT); + if (ptr) { + ptr = (unsigned long)kzalloc(ptr, GFP_NOWAIT); #ifdef CONFIG_FAIR_GROUP_SCHED root_task_group.se = (struct sched_entity **)ptr; -- GitLab From 747d5a1bf293dcb33af755a6d285d41b8c1ea010 Mon Sep 17 00:00:00 2001 From: Grzegorz Halat Date: Fri, 28 Jun 2019 14:28:13 +0200 Subject: [PATCH 0641/7155] x86/reboot: Always use NMI fallback when shutdown via reboot vector IPI fails A reboot request sends an IPI via the reboot vector and waits for all other CPUs to stop. If one or more CPUs are in critical regions with interrupts disabled then the IPI is not handled on those CPUs and the shutdown hangs if native_stop_other_cpus() is called with the wait argument set. Such a situation can happen when one CPU was stopped within a lock held section and another CPU is trying to acquire that lock with interrupts disabled. There are other scenarios which can cause such a lockup as well. In theory the shutdown should be attempted by an NMI IPI after the timeout period elapsed. Though the wait loop after sending the reboot vector IPI prevents this. It checks the wait request argument and the timeout. If wait is set, which is true for sys_reboot() then it won't fall through to the NMI shutdown method after the timeout period has finished. This was an oversight when the NMI shutdown mechanism was added to handle the 'reboot IPI is not working' situation. The mechanism was added to deal with stuck panic shutdowns, which do not have the wait request set, so the 'wait request' case was probably not considered. Remove the wait check from the post reboot vector IPI wait loop and enforce that the wait loop in the NMI fallback path is invoked even if NMI IPIs are disabled or the registration of the NMI handler fails. That second wait loop will then hang if not all CPUs shutdown and the wait argument is set. [ tglx: Avoid the hard to parse line break in the NMI fallback path, add comments and massage the changelog ] Fixes: 7d007d21e539 ("x86/reboot: Use NMI to assist in shutting down if IRQ fails") Signed-off-by: Grzegorz Halat Signed-off-by: Thomas Gleixner Cc: Don Zickus Link: https://lkml.kernel.org/r/20190628122813.15500-1-ghalat@redhat.com --- arch/x86/kernel/smp.c | 46 +++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 96421f97e75c..231fa230ebc7 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -179,6 +179,12 @@ asmlinkage __visible void smp_reboot_interrupt(void) irq_exit(); } +static int register_stop_handler(void) +{ + return register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback, + NMI_FLAG_FIRST, "smp_stop"); +} + static void native_stop_other_cpus(int wait) { unsigned long flags; @@ -212,39 +218,41 @@ static void native_stop_other_cpus(int wait) apic->send_IPI_allbutself(REBOOT_VECTOR); /* - * Don't wait longer than a second if the caller - * didn't ask us to wait. + * Don't wait longer than a second for IPI completion. The + * wait request is not checked here because that would + * prevent an NMI shutdown attempt in case that not all + * CPUs reach shutdown state. */ timeout = USEC_PER_SEC; - while (num_online_cpus() > 1 && (wait || timeout--)) + while (num_online_cpus() > 1 && timeout--) udelay(1); } - - /* if the REBOOT_VECTOR didn't work, try with the NMI */ - if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) { - if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback, - NMI_FLAG_FIRST, "smp_stop")) - /* Note: we ignore failures here */ - /* Hope the REBOOT_IRQ is good enough */ - goto finish; - - /* sync above data before sending IRQ */ - wmb(); - pr_emerg("Shutting down cpus with NMI\n"); + /* if the REBOOT_VECTOR didn't work, try with the NMI */ + if (num_online_cpus() > 1) { + /* + * If NMI IPI is enabled, try to register the stop handler + * and send the IPI. In any case try to wait for the other + * CPUs to stop. + */ + if (!smp_no_nmi_ipi && !register_stop_handler()) { + /* Sync above data before sending IRQ */ + wmb(); - apic->send_IPI_allbutself(NMI_VECTOR); + pr_emerg("Shutting down cpus with NMI\n"); + apic->send_IPI_allbutself(NMI_VECTOR); + } /* - * Don't wait longer than a 10 ms if the caller - * didn't ask us to wait. + * Don't wait longer than 10 ms if the caller didn't + * reqeust it. If wait is true, the machine hangs here if + * one or more CPUs do not reach shutdown state. */ timeout = USEC_PER_MSEC * 10; while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } -finish: local_irq_save(flags); disable_local_APIC(); mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); -- GitLab From 2591bc4e8d70b4e1330d327fb7e3921f4e070a51 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:06 +0200 Subject: [PATCH 0642/7155] x86/kgbd: Use NMI_VECTOR not APIC_DM_NMI apic->send_IPI_allbutself() takes a vector number as argument. APIC_DM_NMI is clearly not a vector number. It's defined to 0x400 which is outside the vector space. Use NMI_VECTOR instead as that's what it is intended to be. Fixes: 82da3ff89dc2 ("x86: kgdb support") Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105218.855189979@linutronix.de --- arch/x86/kernel/kgdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 23297ea64f5f..a53dfb09880f 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -416,7 +416,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs) */ void kgdb_roundup_cpus(void) { - apic->send_IPI_allbutself(APIC_DM_NMI); + apic->send_IPI_allbutself(NMI_VECTOR); } #endif -- GitLab From 39c89dff9c366ad98d2e5598db41ff9b1bdb9e88 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:07 +0200 Subject: [PATCH 0643/7155] x86/apic: Invoke perf_events_lapic_init() after enabling APIC If the APIC is soft disabled then unmasking an LVT entry does not work and the write is ignored. perf_events_lapic_init() tries to do so. Move the invocation after the point where the APIC has been enabled. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105218.962517234@linutronix.de --- arch/x86/kernel/apic/apic.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 84032bf81476..fa0846d4e000 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1517,7 +1517,6 @@ static void setup_local_APIC(void) int logical_apicid, ldr_apicid; #endif - if (disable_apic) { disable_ioapic_support(); return; @@ -1532,8 +1531,6 @@ static void setup_local_APIC(void) apic_write(APIC_ESR, 0); } #endif - perf_events_lapic_init(); - /* * Double-check whether this APIC is really registered. * This is meaningless in clustered apic mode, so we skip it. @@ -1617,6 +1614,8 @@ static void setup_local_APIC(void) value |= SPURIOUS_APIC_VECTOR; apic_write(APIC_SPIV, value); + perf_events_lapic_init(); + /* * Set up LVT0, LVT1: * -- GitLab From 2640da4cccf5cc613bf26f0998b9e340f4b5f69c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:08 +0200 Subject: [PATCH 0644/7155] x86/apic: Soft disable APIC before initializing it If the APIC was already enabled on entry of setup_local_APIC() then disabling it soft via the SPIV register makes a lot of sense. That masks all LVT entries and brings it into a well defined state. Otherwise previously enabled LVTs which are not touched in the setup function stay unmasked and might surprise the just booting kernel. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.068290579@linutronix.de --- arch/x86/kernel/apic/apic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fa0846d4e000..621992de49ee 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1522,6 +1522,14 @@ static void setup_local_APIC(void) return; } + /* + * If this comes from kexec/kcrash the APIC might be enabled in + * SPIV. Soft disable it before doing further initialization. + */ + value = apic_read(APIC_SPIV); + value &= ~APIC_SPIV_APIC_ENABLED; + apic_write(APIC_SPIV, value); + #ifdef CONFIG_X86_32 /* Pound the ESR really hard over the head with a big hammer - mbligh */ if (lapic_is_integrated() && apic->disable_esr) { -- GitLab From cc8bf191378c1da8ad2b99cf470ee70193ace84e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:09 +0200 Subject: [PATCH 0645/7155] x86/apic: Make apic_pending_intr_clear() more robust In course of developing shorthand based IPI support issues with the function which tries to clear eventually pending ISR bits in the local APIC were observed. 1) O-day testing triggered the WARN_ON() in apic_pending_intr_clear(). This warning is emitted when the function fails to clear pending ISR bits or observes pending IRR bits which are not delivered to the CPU after the stale ISR bit(s) are ACK'ed. Unfortunately the function only emits a WARN_ON() and fails to dump the IRR/ISR content. That's useless for debugging. Feng added spot on debug printk's which revealed that the stale IRR bit belonged to the APIC timer interrupt vector, but adding ad hoc debug code does not help with sporadic failures in the field. Rework the loop so the full IRR/ISR contents are saved and on failure dumped. 2) The loop termination logic is interesting at best. If the machine has no TSC or cpu_khz is not known yet it tries 1 million times to ack stale IRR/ISR bits. What? With TSC it uses the TSC to calculate the loop termination. It takes a timestamp at entry and terminates the loop when: (rdtsc() - start_timestamp) >= (cpu_hkz << 10) That's roughly one second. Both methods are problematic. The APIC has 256 vectors, which means that in theory max. 256 IRR/ISR bits can be set. In practice this is impossible and the chance that more than a few bits are set is close to zero. With the pure loop based approach the 1 million retries are complete overkill. With TSC this can terminate too early in a guest which is running on a heavily loaded host even with only a couple of IRR/ISR bits set. The reason is that after acknowledging the highest priority ISR bit, pending IRRs must get serviced first before the next round of acknowledge can take place as the APIC (real and virtualized) does not honour EOI without a preceeding interrupt on the CPU. And every APIC read/write takes a VMEXIT if the APIC is virtualized. While trying to reproduce the issue 0-day reported it was observed that the guest was scheduled out long enough under heavy load that it terminated after 8 iterations. Make the loop terminate after 512 iterations. That's plenty enough in any case and does not take endless time to complete. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.158847694@linutronix.de --- arch/x86/kernel/apic/apic.c | 107 +++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 621992de49ee..fe30d1854a4e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1453,54 +1453,72 @@ static void lapic_setup_esr(void) oldvalue, value); } -static void apic_pending_intr_clear(void) +#define APIC_IR_REGS APIC_ISR_NR +#define APIC_IR_BITS (APIC_IR_REGS * 32) +#define APIC_IR_MAPSIZE (APIC_IR_BITS / BITS_PER_LONG) + +union apic_ir { + unsigned long map[APIC_IR_MAPSIZE]; + u32 regs[APIC_IR_REGS]; +}; + +static bool apic_check_and_ack(union apic_ir *irr, union apic_ir *isr) { - long long max_loops = cpu_khz ? cpu_khz : 1000000; - unsigned long long tsc = 0, ntsc; - unsigned int queued; - unsigned long value; - int i, j, acked = 0; + int i, bit; + + /* Read the IRRs */ + for (i = 0; i < APIC_IR_REGS; i++) + irr->regs[i] = apic_read(APIC_IRR + i * 0x10); + + /* Read the ISRs */ + for (i = 0; i < APIC_IR_REGS; i++) + isr->regs[i] = apic_read(APIC_ISR + i * 0x10); - if (boot_cpu_has(X86_FEATURE_TSC)) - tsc = rdtsc(); /* - * After a crash, we no longer service the interrupts and a pending - * interrupt from previous kernel might still have ISR bit set. - * - * Most probably by now CPU has serviced that pending interrupt and - * it might not have done the ack_APIC_irq() because it thought, - * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it - * does not clear the ISR bit and cpu thinks it has already serivced - * the interrupt. Hence a vector might get locked. It was noticed - * for timer irq (vector 0x31). Issue an extra EOI to clear ISR. + * If the ISR map is not empty. ACK the APIC and run another round + * to verify whether a pending IRR has been unblocked and turned + * into a ISR. */ - do { - queued = 0; - for (i = APIC_ISR_NR - 1; i >= 0; i--) - queued |= apic_read(APIC_IRR + i*0x10); - - for (i = APIC_ISR_NR - 1; i >= 0; i--) { - value = apic_read(APIC_ISR + i*0x10); - for_each_set_bit(j, &value, 32) { - ack_APIC_irq(); - acked++; - } - } - if (acked > 256) { - pr_err("LAPIC pending interrupts after %d EOI\n", acked); - break; - } - if (queued) { - if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) { - ntsc = rdtsc(); - max_loops = (long long)cpu_khz << 10; - max_loops -= ntsc - tsc; - } else { - max_loops--; - } - } - } while (queued && max_loops > 0); - WARN_ON(max_loops <= 0); + if (!bitmap_empty(isr->map, APIC_IR_BITS)) { + /* + * There can be multiple ISR bits set when a high priority + * interrupt preempted a lower priority one. Issue an ACK + * per set bit. + */ + for_each_set_bit(bit, isr->map, APIC_IR_BITS) + ack_APIC_irq(); + return true; + } + + return !bitmap_empty(irr->map, APIC_IR_BITS); +} + +/* + * After a crash, we no longer service the interrupts and a pending + * interrupt from previous kernel might still have ISR bit set. + * + * Most probably by now the CPU has serviced that pending interrupt and it + * might not have done the ack_APIC_irq() because it thought, interrupt + * came from i8259 as ExtInt. LAPIC did not get EOI so it does not clear + * the ISR bit and cpu thinks it has already serivced the interrupt. Hence + * a vector might get locked. It was noticed for timer irq (vector + * 0x31). Issue an extra EOI to clear ISR. + * + * If there are pending IRR bits they turn into ISR bits after a higher + * priority ISR bit has been acked. + */ +static void apic_pending_intr_clear(void) +{ + union apic_ir irr, isr; + unsigned int i; + + /* 512 loops are way oversized and give the APIC a chance to obey. */ + for (i = 0; i < 512; i++) { + if (!apic_check_and_ack(&irr, &isr)) + return; + } + /* Dump the IRR/ISR content if that failed */ + pr_warn("APIC: Stale IRR: %256pb ISR: %256pb\n", irr.map, isr.map); } /** @@ -1576,6 +1594,7 @@ static void setup_local_APIC(void) value |= 0x10; apic_write(APIC_TASKPRI, value); + /* Clear eventually stale ISR/IRR bits */ apic_pending_intr_clear(); /* -- GitLab From cdc86c9d1f825d13cef85d9ebd3e73572602fb48 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:10 +0200 Subject: [PATCH 0646/7155] x86/apic: Move IPI inlines into ipi.c No point in having them in an header file. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.252225936@linutronix.de --- arch/x86/include/asm/ipi.h | 19 ------------------- arch/x86/kernel/apic/ipi.c | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index f73076be546a..8d4911b122f3 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h @@ -71,27 +71,8 @@ extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector); -/* Avoid include hell */ -#define NMI_VECTOR 0x02 - extern int no_broadcast; -static inline void __default_local_send_IPI_allbutself(int vector) -{ - if (no_broadcast || vector == NMI_VECTOR) - apic->send_IPI_mask_allbutself(cpu_online_mask, vector); - else - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->dest_logical); -} - -static inline void __default_local_send_IPI_all(int vector) -{ - if (no_broadcast || vector == NMI_VECTOR) - apic->send_IPI_mask(cpu_online_mask, vector); - else - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical); -} - #ifdef CONFIG_X86_32 extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector); diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 82f9244fe61f..de9764605d31 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -198,15 +198,25 @@ void default_send_IPI_allbutself(int vector) * if there are no other CPUs in the system then we get an APIC send * error if we try to broadcast, thus avoid sending IPIs in this case. */ - if (!(num_online_cpus() > 1)) + if (num_online_cpus() < 2) return; - __default_local_send_IPI_allbutself(vector); + if (no_broadcast || vector == NMI_VECTOR) { + apic->send_IPI_mask_allbutself(cpu_online_mask, vector); + } else { + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, + apic->dest_logical); + } } void default_send_IPI_all(int vector) { - __default_local_send_IPI_all(vector); + if (no_broadcast || vector == NMI_VECTOR) { + apic->send_IPI_mask(cpu_online_mask, vector); + } else { + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector, + apic->dest_logical); + } } void default_send_IPI_self(int vector) -- GitLab From 521b82fee98c1e334ba3a2459ba3739d459e9e4e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:11 +0200 Subject: [PATCH 0647/7155] x86/apic: Cleanup the include maze All of these APIC files include the world and some more. Remove the unneeded cruft. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.342631201@linutronix.de --- arch/x86/kernel/apic/apic_flat_64.c | 15 ++++---------- arch/x86/kernel/apic/apic_noop.c | 18 +---------------- arch/x86/kernel/apic/apic_numachip.c | 6 +++--- arch/x86/kernel/apic/ipi.c | 17 ++-------------- arch/x86/kernel/apic/probe_32.c | 18 ++--------------- arch/x86/kernel/apic/probe_64.c | 11 ----------- arch/x86/kernel/apic/x2apic_cluster.c | 16 +++++++-------- arch/x86/kernel/apic/x2apic_phys.c | 9 +++------ arch/x86/kernel/apic/x2apic_uv_x.c | 28 ++++----------------------- 9 files changed, 26 insertions(+), 112 deletions(-) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index bbdca603f94a..8d7242df1fd6 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -8,21 +8,14 @@ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. */ -#include -#include -#include #include -#include -#include -#include -#include #include +#include -#include -#include -#include -#include #include +#include +#include +#include static struct apic apic_physflat; static struct apic apic_flat; diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 5078b5ce63a7..98c9bb75d185 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -9,25 +9,9 @@ * to not uglify the caller's code and allow to call (some) apic routines * like self-ipi, etc... */ - -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include static void noop_init_apic_ldr(void) { } static void noop_send_IPI(int cpu, int vector) { } diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index a5464b8b6c46..e071e8dcb097 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -10,15 +10,15 @@ * Send feedback to * */ - +#include #include #include #include -#include + #include #include -#include +#include u8 numachip_system __read_mostly; static const struct apic apic_numachip1; diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index de9764605d31..dad523bbe701 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -1,21 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 + #include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include + #include -#include #include void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 1492799b8f43..8f3c7f50b0a9 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -6,26 +6,12 @@ * * Generic x86 APIC driver probe layer. */ -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include +#include #include -#include +#include #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index e6560a02eb46..f7bd3f48deb2 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -8,19 +8,8 @@ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include #include -#include /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 609e499387a1..ebde731dc4cf 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -1,14 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 -#include + +#include #include -#include -#include -#include -#include -#include -#include - -#include +#include +#include + +#include + #include "x2apic.h" struct cluster_mask { diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index b5cf9e7b3830..e5289a0c595b 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -1,13 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 -#include + #include -#include -#include -#include -#include +#include -#include #include + #include "x2apic.h" int x2apic_phys; diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 1e225528f0d7..73a652093820 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -7,40 +7,20 @@ * * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved. */ +#include +#include #include -#include #include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include #include #include #include -#include -#include -#include -#include -#include DEFINE_PER_CPU(int, x2apic_extra_bits); -- GitLab From 8b542da372875373db9688477671151df3418acb Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:12 +0200 Subject: [PATCH 0648/7155] x86/apic: Move ipi header into apic directory Only used locally. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.434738036@linutronix.de --- arch/x86/kernel/apic/apic_flat_64.c | 3 ++- arch/x86/kernel/apic/apic_numachip.c | 3 ++- arch/x86/kernel/apic/bigsmp_32.c | 9 ++------- arch/x86/kernel/apic/ipi.c | 3 ++- arch/x86/{include/asm => kernel/apic}/ipi.h | 0 arch/x86/kernel/apic/probe_32.c | 3 ++- arch/x86/kernel/apic/probe_64.c | 3 ++- arch/x86/kernel/apic/x2apic_phys.c | 3 +-- 8 files changed, 13 insertions(+), 14 deletions(-) rename arch/x86/{include/asm => kernel/apic}/ipi.h (100%) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 8d7242df1fd6..a38b1ecc018d 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -15,7 +15,8 @@ #include #include #include -#include + +#include "ipi.h" static struct apic apic_physflat; static struct apic apic_flat; diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index e071e8dcb097..7d4c00f4e984 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -18,7 +18,8 @@ #include #include -#include + +#include "ipi.h" u8 numachip_system __read_mostly; static const struct apic apic_numachip1; diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index afee386ff711..2c031b75dfce 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -4,18 +4,13 @@ * * Drives the local APIC in "clustered mode". */ -#include #include -#include -#include #include #include -#include -#include -#include #include -#include + +#include "ipi.h" static unsigned bigsmp_get_apic_id(unsigned long x) { diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index dad523bbe701..0f26141d479c 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -3,7 +3,8 @@ #include #include -#include + +#include "ipi.h" void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) { diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/kernel/apic/ipi.h similarity index 100% rename from arch/x86/include/asm/ipi.h rename to arch/x86/kernel/apic/ipi.h diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 8f3c7f50b0a9..40b786e3427a 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -11,7 +11,8 @@ #include #include -#include + +#include "ipi.h" #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index f7bd3f48deb2..6268c487f963 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -9,7 +9,8 @@ * James Cleverdon. */ #include -#include + +#include "ipi.h" /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index e5289a0c595b..3bde4724c1c7 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -3,9 +3,8 @@ #include #include -#include - #include "x2apic.h" +#include "ipi.h" int x2apic_phys; -- GitLab From ba77b2a02e0099ab0021bc3169b8f674c6be19f0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:13 +0200 Subject: [PATCH 0649/7155] x86/apic: Move apic_flat_64 header into apic directory Only used locally. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.526508168@linutronix.de --- arch/x86/kernel/apic/apic_flat_64.c | 2 +- arch/x86/{include/asm => kernel/apic}/apic_flat_64.h | 0 arch/x86/kernel/apic/apic_numachip.c | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename arch/x86/{include/asm => kernel/apic}/apic_flat_64.h (100%) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index a38b1ecc018d..cfee2e546531 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -13,9 +13,9 @@ #include #include -#include #include +#include "apic_flat_64.h" #include "ipi.h" static struct apic apic_physflat; diff --git a/arch/x86/include/asm/apic_flat_64.h b/arch/x86/kernel/apic/apic_flat_64.h similarity index 100% rename from arch/x86/include/asm/apic_flat_64.h rename to arch/x86/kernel/apic/apic_flat_64.h diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 7d4c00f4e984..09ec9ffb268e 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -16,9 +16,9 @@ #include #include -#include #include +#include "apic_flat_64.h" #include "ipi.h" u8 numachip_system __read_mostly; -- GitLab From c94f0718fb1c171d6dfdd69cb6001fa0d8206710 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:14 +0200 Subject: [PATCH 0650/7155] x86/apic: Consolidate the apic local headers Now there are three small local headers. Some contain functions which are only used in one source file. Move all the inlines and declarations into a single local header and the inlines which are only used in one source file into that. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.618612624@linutronix.de --- arch/x86/kernel/apic/apic_flat_64.c | 3 +- arch/x86/kernel/apic/apic_flat_64.h | 8 --- arch/x86/kernel/apic/apic_numachip.c | 3 +- arch/x86/kernel/apic/bigsmp_32.c | 2 +- arch/x86/kernel/apic/ipi.c | 14 ++++- arch/x86/kernel/apic/ipi.h | 90 --------------------------- arch/x86/kernel/apic/local.h | 63 +++++++++++++++++++ arch/x86/kernel/apic/probe_32.c | 3 +- arch/x86/kernel/apic/probe_64.c | 2 +- arch/x86/kernel/apic/x2apic.h | 9 --- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- arch/x86/kernel/apic/x2apic_phys.c | 3 +- 12 files changed, 83 insertions(+), 119 deletions(-) delete mode 100644 arch/x86/kernel/apic/apic_flat_64.h delete mode 100644 arch/x86/kernel/apic/ipi.h create mode 100644 arch/x86/kernel/apic/local.h delete mode 100644 arch/x86/kernel/apic/x2apic.h diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index cfee2e546531..f8594b844637 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -15,8 +15,7 @@ #include #include -#include "apic_flat_64.h" -#include "ipi.h" +#include "local.h" static struct apic apic_physflat; static struct apic apic_flat; diff --git a/arch/x86/kernel/apic/apic_flat_64.h b/arch/x86/kernel/apic/apic_flat_64.h deleted file mode 100644 index d3a2b3876ce6..000000000000 --- a/arch/x86/kernel/apic/apic_flat_64.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_X86_APIC_FLAT_64_H -#define _ASM_X86_APIC_FLAT_64_H - -extern void flat_init_apic_ldr(void); - -#endif - diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 09ec9ffb268e..cdf45b4700f2 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -18,8 +18,7 @@ #include -#include "apic_flat_64.h" -#include "ipi.h" +#include "local.h" u8 numachip_system __read_mostly; static const struct apic apic_numachip1; diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 2c031b75dfce..9703b552f25a 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -10,7 +10,7 @@ #include -#include "ipi.h" +#include "local.h" static unsigned bigsmp_get_apic_id(unsigned long x) { diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 0f26141d479c..6fa9f6ca7eef 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -1,10 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include -#include +#include "local.h" -#include "ipi.h" +static inline int __prepare_ICR2(unsigned int mask) +{ + return SET_APIC_DEST_FIELD(mask); +} + +static inline void __xapic_wait_icr_idle(void) +{ + while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY) + cpu_relax(); +} void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) { diff --git a/arch/x86/kernel/apic/ipi.h b/arch/x86/kernel/apic/ipi.h deleted file mode 100644 index 8d4911b122f3..000000000000 --- a/arch/x86/kernel/apic/ipi.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _ASM_X86_IPI_H -#define _ASM_X86_IPI_H - -#ifdef CONFIG_X86_LOCAL_APIC - -/* - * Copyright 2004 James Cleverdon, IBM. - * - * Generic APIC InterProcessor Interrupt code. - * - * Moved to include file by James Cleverdon from - * arch/x86-64/kernel/smp.c - * - * Copyrights from kernel/smp.c: - * - * (c) 1995 Alan Cox, Building #3 - * (c) 1998-99, 2000 Ingo Molnar - * (c) 2002,2003 Andi Kleen, SuSE Labs. - */ - -#include -#include -#include - -/* - * the following functions deal with sending IPIs between CPUs. - * - * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. - */ - -static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector, - unsigned int dest) -{ - unsigned int icr = shortcut | dest; - - switch (vector) { - default: - icr |= APIC_DM_FIXED | vector; - break; - case NMI_VECTOR: - icr |= APIC_DM_NMI; - break; - } - return icr; -} - -static inline int __prepare_ICR2(unsigned int mask) -{ - return SET_APIC_DEST_FIELD(mask); -} - -static inline void __xapic_wait_icr_idle(void) -{ - while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY) - cpu_relax(); -} - -void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest); - -/* - * This is used to send an IPI with no shorthand notation (the destination is - * specified in bits 56 to 63 of the ICR). - */ -void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest); - -extern void default_send_IPI_single(int cpu, int vector); -extern void default_send_IPI_single_phys(int cpu, int vector); -extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, - int vector); -extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, - int vector); - -extern int no_broadcast; - -#ifdef CONFIG_X86_32 -extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, - int vector); -extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, - int vector); -extern void default_send_IPI_mask_logical(const struct cpumask *mask, - int vector); -extern void default_send_IPI_allbutself(int vector); -extern void default_send_IPI_all(int vector); -extern void default_send_IPI_self(int vector); -#endif - -#endif - -#endif /* _ASM_X86_IPI_H */ diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h new file mode 100644 index 000000000000..95adac0e785b --- /dev/null +++ b/arch/x86/kernel/apic/local.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Historical copyright notices: + * + * Copyright 2004 James Cleverdon, IBM. + * (c) 1995 Alan Cox, Building #3 + * (c) 1998-99, 2000 Ingo Molnar + * (c) 2002,2003 Andi Kleen, SuSE Labs. + */ +#include + +/* APIC flat 64 */ +void flat_init_apic_ldr(void); + +/* X2APIC */ +int x2apic_apic_id_valid(u32 apicid); +int x2apic_apic_id_registered(void); +void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest); +unsigned int x2apic_get_apic_id(unsigned long id); +u32 x2apic_set_apic_id(unsigned int id); +int x2apic_phys_pkg_id(int initial_apicid, int index_msb); +void x2apic_send_IPI_self(int vector); + +/* IPI */ +static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector, + unsigned int dest) +{ + unsigned int icr = shortcut | dest; + + switch (vector) { + default: + icr |= APIC_DM_FIXED | vector; + break; + case NMI_VECTOR: + icr |= APIC_DM_NMI; + break; + } + return icr; +} + +void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest); + +/* + * This is used to send an IPI with no shorthand notation (the destination is + * specified in bits 56 to 63 of the ICR). + */ +void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest); + +void default_send_IPI_single(int cpu, int vector); +void default_send_IPI_single_phys(int cpu, int vector); +void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector); + +extern int no_broadcast; + +#ifdef CONFIG_X86_32 +void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector); +void default_send_IPI_mask_logical(const struct cpumask *mask, int vector); +void default_send_IPI_allbutself(int vector); +void default_send_IPI_all(int vector); +void default_send_IPI_self(int vector); +#endif diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 40b786e3427a..7cc961d4f51f 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -8,11 +8,12 @@ */ #include #include +#include #include #include -#include "ipi.h" +#include "local.h" #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index 6268c487f963..e0e1e3380ea2 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -10,7 +10,7 @@ */ #include -#include "ipi.h" +#include "local.h" /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. diff --git a/arch/x86/kernel/apic/x2apic.h b/arch/x86/kernel/apic/x2apic.h deleted file mode 100644 index a49b3604027f..000000000000 --- a/arch/x86/kernel/apic/x2apic.h +++ /dev/null @@ -1,9 +0,0 @@ -/* Common bits for X2APIC cluster/physical modes. */ - -int x2apic_apic_id_valid(u32 apicid); -int x2apic_apic_id_registered(void); -void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest); -unsigned int x2apic_get_apic_id(unsigned long id); -u32 x2apic_set_apic_id(unsigned int id); -int x2apic_phys_pkg_id(int initial_apicid, int index_msb); -void x2apic_send_IPI_self(int vector); diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index ebde731dc4cf..d0a13c88f777 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -7,7 +7,7 @@ #include -#include "x2apic.h" +#include "local.h" struct cluster_mask { unsigned int clusterid; diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 3bde4724c1c7..5d50e1f9d4bf 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -3,8 +3,7 @@ #include #include -#include "x2apic.h" -#include "ipi.h" +#include "local.h" int x2apic_phys; -- GitLab From 82e574782345aa634e1544e80da85d71a9dbde19 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:15 +0200 Subject: [PATCH 0651/7155] x86/apic/uv: Make x2apic_extra_bits static Not used outside of the UV apic source. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.725264153@linutronix.de --- arch/x86/include/asm/apic.h | 2 -- arch/x86/kernel/apic/x2apic_uv_x.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index e647aa095867..f53eda2c986b 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -467,8 +467,6 @@ static inline unsigned default_get_apic_id(unsigned long x) #ifdef CONFIG_X86_64 extern void apic_send_IPI_self(int vector); - -DECLARE_PER_CPU(int, x2apic_extra_bits); #endif extern void generic_bigsmp_probe(void); diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 73a652093820..e6230af19864 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -22,7 +22,7 @@ #include #include -DEFINE_PER_CPU(int, x2apic_extra_bits); +static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; static bool uv_hubless_system; -- GitLab From 9c92374b631d233abf5bd355cb4253d3d83d5578 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:17 +0200 Subject: [PATCH 0652/7155] x86/cpu: Move arch_smt_update() to a neutral place arch_smt_update() will be used to control IPI/NMI broadcasting via the shorthand mechanism. Keeping it in the bugs file and calling the apic function from there is possible, but not really intuitive. Move it to a neutral place and invoke the bugs function from there. No functional change. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105219.910317273@linutronix.de --- arch/x86/include/asm/bugs.h | 2 ++ arch/x86/kernel/cpu/bugs.c | 2 +- arch/x86/kernel/cpu/common.c | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/bugs.h b/arch/x86/include/asm/bugs.h index 542509b53e0f..794eb2129bc6 100644 --- a/arch/x86/include/asm/bugs.h +++ b/arch/x86/include/asm/bugs.h @@ -18,4 +18,6 @@ int ppro_with_ram_bug(void); static inline int ppro_with_ram_bug(void) { return 0; } #endif +extern void cpu_bugs_smt_update(void); + #endif /* _ASM_X86_BUGS_H */ diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 66ca906aa790..6d9636c2ca51 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -700,7 +700,7 @@ static void update_mds_branch_idle(void) #define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n" -void arch_smt_update(void) +void cpu_bugs_smt_update(void) { /* Enhanced IBRS implies STIBP. No update required. */ if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 11472178e17f..1ee6598c5d83 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1945,3 +1945,12 @@ void microcode_check(void) pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n"); pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); } + +/* + * Invoked from core CPU hotplug code after hotplug operations + */ +void arch_smt_update(void) +{ + /* Handle the speculative execution misfeatures */ + cpu_bugs_smt_update(); +} -- GitLab From 60dcaad5736faff5a6b1abba5a292499f57197fe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 24 Jul 2019 17:25:52 +0200 Subject: [PATCH 0653/7155] x86/hotplug: Silence APIC and NMI when CPU is dead In order to support IPI/NMI broadcasting via the shorthand mechanism side effects of shorthands need to be mitigated: Shorthand IPIs and NMIs hit all CPUs including unplugged CPUs Neither of those can be handled on unplugged CPUs for obvious reasons. It would be trivial to just fully disable the APIC via the enable bit in MSR_APICBASE. But that's not possible because clearing that bit on systems based on the 3 wire APIC bus would require a hardware reset to bring it back as the APIC would lose track of bus arbitration. On systems with FSB delivery APICBASE could be disabled, but it has to be guaranteed that no interrupt is sent to the APIC while in that state and it's not clear from the SDM whether it still responds to INIT/SIPI messages. Therefore stay on the safe side and switch the APIC into soft disabled mode so it won't deliver any regular vector to the CPU. NMIs are still propagated to the 'dead' CPUs. To mitigate that add a check for the CPU being offline on early nmi entry and if so bail. Note, this cannot use the stop/restart_nmi() magic which is used in the alternatives code. A dead CPU cannot invoke nmi_enter() or anything else due to RCU and other reasons. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1907241723290.1791@nanos.tec.linutronix.de --- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/apic/apic.c | 35 ++++++++++++++++++++++++----------- arch/x86/kernel/nmi.c | 3 +++ arch/x86/kernel/smpboot.c | 7 ++++++- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index f53eda2c986b..cae7e0d02476 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -136,6 +136,7 @@ extern int lapic_get_maxlvt(void); extern void clear_local_APIC(void); extern void disconnect_bsp_APIC(int virt_wire_setup); extern void disable_local_APIC(void); +extern void apic_soft_disable(void); extern void lapic_shutdown(void); extern void sync_Arb_IDs(void); extern void init_bsp_APIC(void); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fe30d1854a4e..831274e3c09f 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1182,25 +1182,38 @@ void clear_local_APIC(void) } /** - * disable_local_APIC - clear and disable the local APIC + * apic_soft_disable - Clears and software disables the local APIC on hotplug + * + * Contrary to disable_local_APIC() this does not touch the enable bit in + * MSR_IA32_APICBASE. Clearing that bit on systems based on the 3 wire APIC + * bus would require a hardware reset as the APIC would lose track of bus + * arbitration. On systems with FSB delivery APICBASE could be disabled, + * but it has to be guaranteed that no interrupt is sent to the APIC while + * in that state and it's not clear from the SDM whether it still responds + * to INIT/SIPI messages. Stay on the safe side and use software disable. */ -void disable_local_APIC(void) +void apic_soft_disable(void) { - unsigned int value; - - /* APIC hasn't been mapped yet */ - if (!x2apic_mode && !apic_phys) - return; + u32 value; clear_local_APIC(); - /* - * Disable APIC (implies clearing of registers - * for 82489DX!). - */ + /* Soft disable APIC (implies clearing of registers for 82489DX!). */ value = apic_read(APIC_SPIV); value &= ~APIC_SPIV_APIC_ENABLED; apic_write(APIC_SPIV, value); +} + +/** + * disable_local_APIC - clear and disable the local APIC + */ +void disable_local_APIC(void) +{ + /* APIC hasn't been mapped yet */ + if (!x2apic_mode && !apic_phys) + return; + + apic_soft_disable(); #ifdef CONFIG_X86_32 /* diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 4df7705022b9..e676a9916c49 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -512,6 +512,9 @@ NOKPROBE_SYMBOL(is_debug_stack); dotraplinkage notrace void do_nmi(struct pt_regs *regs, long error_code) { + if (IS_ENABLED(CONFIG_SMP) && cpu_is_offline(smp_processor_id())) + return; + if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) { this_cpu_write(nmi_state, NMI_LATCHED); return; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fdbd47ceb84d..c19f8e21b748 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1596,7 +1596,12 @@ int native_cpu_disable(void) if (ret) return ret; - clear_local_APIC(); + /* + * Disable the local APIC. Otherwise IPI broadcasts will reach + * it. It still responds normally to INIT, NMI, SMI, and SIPI + * messages. + */ + apic_soft_disable(); cpu_disable_common(); return 0; -- GitLab From 3994ff90acc3b115734fe532720c37a499c502ce Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:19 +0200 Subject: [PATCH 0654/7155] x86/apic: Remove dest argument from __default_send_IPI_shortcut() The SDM states: "The destination shorthand field of the ICR allows the delivery mode to be by-passed in favor of broadcasting the IPI to all the processors on the system bus and/or back to itself (see Section 10.6.1, Interrupt Command Register (ICR)). Three destination shorthands are supported: self, all excluding self, and all including self. The destination mode is ignored when a destination shorthand is used." So there is no point to supply the destination mode to the shorthand delivery function. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.094613426@linutronix.de --- arch/x86/kernel/apic/apic_flat_64.c | 6 ++---- arch/x86/kernel/apic/ipi.c | 15 +++++++-------- arch/x86/kernel/apic/local.h | 2 +- arch/x86/kernel/apic/probe_64.c | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index f8594b844637..004611a44962 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -90,8 +90,7 @@ static void flat_send_IPI_allbutself(int vector) _flat_send_IPI_mask(mask, vector); } } else if (num_online_cpus() > 1) { - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, - vector, apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); } } @@ -100,8 +99,7 @@ static void flat_send_IPI_all(int vector) if (vector == NMI_VECTOR) { flat_send_IPI_mask(cpu_online_mask, vector); } else { - __default_send_IPI_shortcut(APIC_DEST_ALLINC, - vector, apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); } } diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 6fa9f6ca7eef..50c9dcc6f60e 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -16,7 +16,7 @@ static inline void __xapic_wait_icr_idle(void) cpu_relax(); } -void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) +void __default_send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -33,9 +33,10 @@ void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int __xapic_wait_icr_idle(); /* - * No need to touch the target chip field + * No need to touch the target chip field. Also the destination + * mode is ignored when a shorthand is used. */ - cfg = __prepare_ICR(shortcut, vector, dest); + cfg = __prepare_ICR(shortcut, vector, 0); /* * Send the IPI. The write to APIC_ICR fires this off. @@ -202,8 +203,7 @@ void default_send_IPI_allbutself(int vector) if (no_broadcast || vector == NMI_VECTOR) { apic->send_IPI_mask_allbutself(cpu_online_mask, vector); } else { - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, - apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); } } @@ -212,14 +212,13 @@ void default_send_IPI_all(int vector) if (no_broadcast || vector == NMI_VECTOR) { apic->send_IPI_mask(cpu_online_mask, vector); } else { - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector, - apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); } } void default_send_IPI_self(int vector) { - __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_SELF, vector); } /* must come after the send_IPI functions above for inlining */ diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h index 95adac0e785b..47c43381b444 100644 --- a/arch/x86/kernel/apic/local.h +++ b/arch/x86/kernel/apic/local.h @@ -38,7 +38,7 @@ static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector, return icr; } -void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest); +void __default_send_IPI_shortcut(unsigned int shortcut, int vector); /* * This is used to send an IPI with no shorthand notation (the destination is diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index e0e1e3380ea2..fb457b540e78 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -40,7 +40,7 @@ void __init default_setup_apic_routing(void) void apic_send_IPI_self(int vector) { - __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); + __default_send_IPI_shortcut(APIC_DEST_SELF, vector); } int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -- GitLab From bd82dba2fa6ae91061e5d31399d61fe65028f714 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:20 +0200 Subject: [PATCH 0655/7155] x86/apic: Add NMI_VECTOR wait to IPI shorthand To support NMI shorthand broadcasts add the safe wait for ICR idle for NMI vector delivery. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.185838026@linutronix.de --- arch/x86/kernel/apic/ipi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 50c9dcc6f60e..7236fefde396 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -30,7 +30,10 @@ void __default_send_IPI_shortcut(unsigned int shortcut, int vector) /* * Wait for idle. */ - __xapic_wait_icr_idle(); + if (unlikely(vector == NMI_VECTOR)) + safe_apic_wait_icr_idle(); + else + __xapic_wait_icr_idle(); /* * No need to touch the target chip field. Also the destination -- GitLab From bdda3b93e66085abf0b2c16bcdf471176e3c816a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:21 +0200 Subject: [PATCH 0656/7155] x86/apic: Move no_ipi_broadcast() out of 32bit For the upcoming shorthand support for all APIC incarnations the command line option needs to be available for 64 bit as well. While at it, rename the control variable, make it static and mark it __ro_after_init. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.278327940@linutronix.de --- arch/x86/kernel/apic/ipi.c | 29 +++++++++++++++++++++++++++-- arch/x86/kernel/apic/local.h | 2 -- arch/x86/kernel/apic/probe_32.c | 25 ------------------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 7236fefde396..ca3bcdb7c4a8 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -5,6 +5,31 @@ #include "local.h" +#ifdef CONFIG_SMP +#ifdef CONFIG_HOTPLUG_CPU +#define DEFAULT_SEND_IPI (1) +#else +#define DEFAULT_SEND_IPI (0) +#endif + +static int apic_ipi_shorthand_off __ro_after_init = DEFAULT_SEND_IPI; + +static __init int apic_ipi_shorthand(char *str) +{ + get_option(&str, &apic_ipi_shorthand_off); + return 1; +} +__setup("no_ipi_broadcast=", apic_ipi_shorthand); + +static int __init print_ipi_mode(void) +{ + pr_info("IPI shorthand broadcast: %s\n", + apic_ipi_shorthand_off ? "disabled" : "enabled"); + return 0; +} +late_initcall(print_ipi_mode); +#endif + static inline int __prepare_ICR2(unsigned int mask) { return SET_APIC_DEST_FIELD(mask); @@ -203,7 +228,7 @@ void default_send_IPI_allbutself(int vector) if (num_online_cpus() < 2) return; - if (no_broadcast || vector == NMI_VECTOR) { + if (apic_ipi_shorthand_off || vector == NMI_VECTOR) { apic->send_IPI_mask_allbutself(cpu_online_mask, vector); } else { __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); @@ -212,7 +237,7 @@ void default_send_IPI_allbutself(int vector) void default_send_IPI_all(int vector) { - if (no_broadcast || vector == NMI_VECTOR) { + if (apic_ipi_shorthand_off || vector == NMI_VECTOR) { apic->send_IPI_mask(cpu_online_mask, vector); } else { __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h index 47c43381b444..bd074e5997b0 100644 --- a/arch/x86/kernel/apic/local.h +++ b/arch/x86/kernel/apic/local.h @@ -51,8 +51,6 @@ void default_send_IPI_single_phys(int cpu, int vector); void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector); void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector); -extern int no_broadcast; - #ifdef CONFIG_X86_32 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector); void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector); diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 7cc961d4f51f..0ac9fd667c99 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -15,31 +15,6 @@ #include "local.h" -#ifdef CONFIG_HOTPLUG_CPU -#define DEFAULT_SEND_IPI (1) -#else -#define DEFAULT_SEND_IPI (0) -#endif - -int no_broadcast = DEFAULT_SEND_IPI; - -static __init int no_ipi_broadcast(char *str) -{ - get_option(&str, &no_broadcast); - pr_info("Using %s mode\n", - no_broadcast ? "No IPI Broadcast" : "IPI Broadcast"); - return 1; -} -__setup("no_ipi_broadcast=", no_ipi_broadcast); - -static int __init print_ipi_mode(void) -{ - pr_info("Using IPI %s mode\n", - no_broadcast ? "No-Shortcut" : "Shortcut"); - return 0; -} -late_initcall(print_ipi_mode); - static int default_x86_32_early_logical_apicid(int cpu) { return 1 << cpu; -- GitLab From 6a1cb5f5c6413222b8532722562dd1edb5fdfd38 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:22 +0200 Subject: [PATCH 0657/7155] x86/apic: Add static key to Control IPI shorthands The IPI shorthand functionality delivers IPI/NMI broadcasts to all CPUs in the system. This can have similar side effects as the MCE broadcasting when CPUs are waiting in the BIOS or are offlined. The kernel tracks already the state of offlined CPUs whether they have been brought up at least once so that the CR4 MCE bit is set to make sure that MCE broadcasts can't brick the machine. Utilize that information and compare it to the cpu_present_mask. If all present CPUs have been brought up at least once then the broadcast side effect is mitigated by disabling regular interrupt/IPI delivery in the APIC itself and by the cpu offline check at the begin of the NMI handler. Use a static key to switch between broadcasting via shorthands or sending the IPI/NMI one by one. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.386410643@linutronix.de --- arch/x86/include/asm/apic.h | 2 ++ arch/x86/kernel/apic/ipi.c | 24 +++++++++++++++++++++++- arch/x86/kernel/apic/local.h | 6 ++++++ arch/x86/kernel/cpu/common.c | 2 ++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index cae7e0d02476..4a0d349ab44d 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -505,8 +505,10 @@ extern int default_check_phys_apicid_present(int phys_apicid); #ifdef CONFIG_SMP bool apic_id_is_primary_thread(unsigned int id); +void apic_smt_update(void); #else static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } +static inline void apic_smt_update(void) { } #endif extern void irq_enter(void); diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index ca3bcdb7c4a8..5bd8a001a887 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -5,6 +5,8 @@ #include "local.h" +DEFINE_STATIC_KEY_FALSE(apic_use_ipi_shorthand); + #ifdef CONFIG_SMP #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) @@ -28,7 +30,27 @@ static int __init print_ipi_mode(void) return 0; } late_initcall(print_ipi_mode); -#endif + +void apic_smt_update(void) +{ + /* + * Do not switch to broadcast mode if: + * - Disabled on the command line + * - Only a single CPU is online + * - Not all present CPUs have been at least booted once + * + * The latter is important as the local APIC might be in some + * random state and a broadcast might cause havoc. That's + * especially true for NMI broadcasting. + */ + if (apic_ipi_shorthand_off || num_online_cpus() == 1 || + !cpumask_equal(cpu_present_mask, &cpus_booted_once_mask)) { + static_branch_disable(&apic_use_ipi_shorthand); + } else { + static_branch_enable(&apic_use_ipi_shorthand); + } +} +#endif /* CONFIG_SMP */ static inline int __prepare_ICR2(unsigned int mask) { diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h index bd074e5997b0..391594cd5ca9 100644 --- a/arch/x86/kernel/apic/local.h +++ b/arch/x86/kernel/apic/local.h @@ -7,6 +7,9 @@ * (c) 1998-99, 2000 Ingo Molnar * (c) 2002,2003 Andi Kleen, SuSE Labs. */ + +#include + #include /* APIC flat 64 */ @@ -22,6 +25,9 @@ int x2apic_phys_pkg_id(int initial_apicid, int index_msb); void x2apic_send_IPI_self(int vector); /* IPI */ + +DECLARE_STATIC_KEY_FALSE(apic_use_ipi_shorthand); + static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector, unsigned int dest) { diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 1ee6598c5d83..e0489d2860d3 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1953,4 +1953,6 @@ void arch_smt_update(void) { /* Handle the speculative execution misfeatures */ cpu_bugs_smt_update(); + /* Check whether IPI broadcasting can be enabled */ + apic_smt_update(); } -- GitLab From 22ca7ee933a39f542ff6f81fc64f8036eff56519 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:23 +0200 Subject: [PATCH 0658/7155] x86/apic: Provide and use helper for send_IPI_allbutself() To support IPI shorthands wrap invocations of apic->send_IPI_allbutself() in a helper function, so the static key controlling the shorthand mode is only in one place. Fixup all callers. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.492691679@linutronix.de --- arch/x86/include/asm/apic.h | 2 ++ arch/x86/kernel/apic/ipi.c | 12 ++++++++++++ arch/x86/kernel/kgdb.c | 2 +- arch/x86/kernel/reboot.c | 7 +------ arch/x86/kernel/smp.c | 4 ++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 4a0d349ab44d..de86c6c15228 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -177,6 +177,8 @@ extern void lapic_online(void); extern void lapic_offline(void); extern bool apic_needs_pit(void); +extern void apic_send_IPI_allbutself(unsigned int vector); + #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } #define local_apic_timer_c2_ok 1 diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 5bd8a001a887..f53de3e0145e 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -50,6 +50,18 @@ void apic_smt_update(void) static_branch_enable(&apic_use_ipi_shorthand); } } + +void apic_send_IPI_allbutself(unsigned int vector) +{ + if (num_online_cpus() < 2) + return; + + if (static_branch_likely(&apic_use_ipi_shorthand)) + apic->send_IPI_allbutself(vector); + else + apic->send_IPI_mask_allbutself(cpu_online_mask, vector); +} + #endif /* CONFIG_SMP */ static inline int __prepare_ICR2(unsigned int mask) diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index a53dfb09880f..c44fe7d8d9a4 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -416,7 +416,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs) */ void kgdb_roundup_cpus(void) { - apic->send_IPI_allbutself(NMI_VECTOR); + apic_send_IPI_allbutself(NMI_VECTOR); } #endif diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 09d6bded3c1e..0cc7c0b106bb 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -828,11 +828,6 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) return NMI_HANDLED; } -static void smp_send_nmi_allbutself(void) -{ - apic->send_IPI_allbutself(NMI_VECTOR); -} - /* * Halt all other CPUs, calling the specified function on each of them * @@ -861,7 +856,7 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) */ wmb(); - smp_send_nmi_allbutself(); + apic_send_IPI_allbutself(NMI_VECTOR); /* Kick CPUs looping in NMI context. */ WRITE_ONCE(crash_ipi_issued, 1); diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 231fa230ebc7..b8ad1876a081 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -215,7 +215,7 @@ static void native_stop_other_cpus(int wait) /* sync above data before sending IRQ */ wmb(); - apic->send_IPI_allbutself(REBOOT_VECTOR); + apic_send_IPI_allbutself(REBOOT_VECTOR); /* * Don't wait longer than a second for IPI completion. The @@ -241,7 +241,7 @@ static void native_stop_other_cpus(int wait) pr_emerg("Shutting down cpus with NMI\n"); - apic->send_IPI_allbutself(NMI_VECTOR); + apic_send_IPI_allbutself(NMI_VECTOR); } /* * Don't wait longer than 10 ms if the caller didn't -- GitLab From d0a7166bc7ac4feac5c482ebe8b2417aa3302ef4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:25 +0200 Subject: [PATCH 0659/7155] x86/smp: Move smp_function_call implementations into IPI code Move it where it belongs. That allows to keep all the shorthand logic in one place. No functional change. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.677835995@linutronix.de --- arch/x86/include/asm/smp.h | 1 + arch/x86/kernel/apic/ipi.c | 40 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/smp.c | 40 -------------------------------------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index e1356a3b8223..e15f364efbcc 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -143,6 +143,7 @@ void play_dead_common(void); void wbinvd_on_cpu(int cpu); int wbinvd_on_all_cpus(void); +void native_smp_send_reschedule(int cpu); void native_send_call_func_ipi(const struct cpumask *mask); void native_send_call_func_single_ipi(int cpu); void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle); diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index f53de3e0145e..eaac65bf58f0 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -62,6 +62,46 @@ void apic_send_IPI_allbutself(unsigned int vector) apic->send_IPI_mask_allbutself(cpu_online_mask, vector); } +/* + * Send a 'reschedule' IPI to another CPU. It goes straight through and + * wastes no time serializing anything. Worst case is that we lose a + * reschedule ... + */ +void native_smp_send_reschedule(int cpu) +{ + if (unlikely(cpu_is_offline(cpu))) { + WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu); + return; + } + apic->send_IPI(cpu, RESCHEDULE_VECTOR); +} + +void native_send_call_func_single_ipi(int cpu) +{ + apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR); +} + +void native_send_call_func_ipi(const struct cpumask *mask) +{ + cpumask_var_t allbutself; + + if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) { + apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); + return; + } + + cpumask_copy(allbutself, cpu_online_mask); + __cpumask_clear_cpu(smp_processor_id(), allbutself); + + if (cpumask_equal(mask, allbutself) && + cpumask_equal(cpu_online_mask, cpu_callout_mask)) + apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); + else + apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); + + free_cpumask_var(allbutself); +} + #endif /* CONFIG_SMP */ static inline int __prepare_ICR2(unsigned int mask) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index b8ad1876a081..b8d4e9c3c070 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -115,46 +115,6 @@ static atomic_t stopping_cpu = ATOMIC_INIT(-1); static bool smp_no_nmi_ipi = false; -/* - * this function sends a 'reschedule' IPI to another CPU. - * it goes straight through and wastes no time serializing - * anything. Worst case is that we lose a reschedule ... - */ -static void native_smp_send_reschedule(int cpu) -{ - if (unlikely(cpu_is_offline(cpu))) { - WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu); - return; - } - apic->send_IPI(cpu, RESCHEDULE_VECTOR); -} - -void native_send_call_func_single_ipi(int cpu) -{ - apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR); -} - -void native_send_call_func_ipi(const struct cpumask *mask) -{ - cpumask_var_t allbutself; - - if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) { - apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); - return; - } - - cpumask_copy(allbutself, cpu_online_mask); - __cpumask_clear_cpu(smp_processor_id(), allbutself); - - if (cpumask_equal(mask, allbutself) && - cpumask_equal(cpu_online_mask, cpu_callout_mask)) - apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); - else - apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); - - free_cpumask_var(allbutself); -} - static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) { /* We are registered on stopping cpu too, avoid spurious NMI */ -- GitLab From 832df3d47badcbc860aef617105b6bc1c9459304 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:26 +0200 Subject: [PATCH 0660/7155] x86/smp: Enhance native_send_call_func_ipi() Nadav noticed that the cpumask allocations in native_send_call_func_ipi() are noticeable in microbenchmarks. Use the new cpumask_or_equal() function to simplify the decision whether the supplied target CPU mask is either equal to cpu_online_mask or equal to cpu_online_mask except for the CPU on which the function is invoked. cpumask_or_equal() or's the target mask and the cpumask of the current CPU together and compares it to cpu_online_mask. If the result is false, use the mask based IPI function, otherwise check whether the current CPU is set in the target mask and invoke either the send_IPI_all() or the send_IPI_allbutselt() APIC callback. Make the shorthand decision also depend on the static key which enables shorthand mode. That allows to remove the extra cpumask comparison with cpu_callout_mask. Reported-by: Nadav Amit Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.768238809@linutronix.de --- arch/x86/kernel/apic/ipi.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index eaac65bf58f0..117ee2323f59 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -83,23 +83,21 @@ void native_send_call_func_single_ipi(int cpu) void native_send_call_func_ipi(const struct cpumask *mask) { - cpumask_var_t allbutself; + if (static_branch_likely(&apic_use_ipi_shorthand)) { + unsigned int cpu = smp_processor_id(); - if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) { - apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); + if (!cpumask_or_equal(mask, cpumask_of(cpu), cpu_online_mask)) + goto sendmask; + + if (cpumask_test_cpu(cpu, mask)) + apic->send_IPI_all(CALL_FUNCTION_VECTOR); + else if (num_online_cpus() > 1) + apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); return; } - cpumask_copy(allbutself, cpu_online_mask); - __cpumask_clear_cpu(smp_processor_id(), allbutself); - - if (cpumask_equal(mask, allbutself) && - cpumask_equal(cpu_online_mask, cpu_callout_mask)) - apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); - else - apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); - - free_cpumask_var(allbutself); +sendmask: + apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); } #endif /* CONFIG_SMP */ -- GitLab From 1f0ad660488b8eb2450d1834af6a156104281194 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:27 +0200 Subject: [PATCH 0661/7155] x86/apic: Remove the shorthand decision logic All callers of apic->send_IPI_all() and apic->send_IPI_allbutself() contain the decision logic for shorthand invocation already and invoke send_IPI_mask() if the prereqisites are not satisfied. Remove the now redundant decision logic in the 32bit implementation. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.860244707@linutronix.de --- arch/x86/kernel/apic/ipi.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 117ee2323f59..71363b0d4a67 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -8,13 +8,7 @@ DEFINE_STATIC_KEY_FALSE(apic_use_ipi_shorthand); #ifdef CONFIG_SMP -#ifdef CONFIG_HOTPLUG_CPU -#define DEFAULT_SEND_IPI (1) -#else -#define DEFAULT_SEND_IPI (0) -#endif - -static int apic_ipi_shorthand_off __ro_after_init = DEFAULT_SEND_IPI; +static int apic_ipi_shorthand_off __ro_after_init; static __init int apic_ipi_shorthand(char *str) { @@ -293,27 +287,12 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector) void default_send_IPI_allbutself(int vector) { - /* - * if there are no other CPUs in the system then we get an APIC send - * error if we try to broadcast, thus avoid sending IPIs in this case. - */ - if (num_online_cpus() < 2) - return; - - if (apic_ipi_shorthand_off || vector == NMI_VECTOR) { - apic->send_IPI_mask_allbutself(cpu_online_mask, vector); - } else { - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); - } + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); } void default_send_IPI_all(int vector) { - if (apic_ipi_shorthand_off || vector == NMI_VECTOR) { - apic->send_IPI_mask(cpu_online_mask, vector); - } else { - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); - } + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); } void default_send_IPI_self(int vector) -- GitLab From dea978632e8400b84888bad20df0cd91c18f0aec Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:28 +0200 Subject: [PATCH 0662/7155] x86/apic: Share common IPI helpers The 64bit implementations need the same wrappers around __default_send_IPI_shortcut() as 32bit. Move them out of the 32bit section. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105220.951534451@linutronix.de --- arch/x86/kernel/apic/ipi.c | 30 +++++++++++++++--------------- arch/x86/kernel/apic/local.h | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 71363b0d4a67..6ca0f91372fd 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -226,6 +226,21 @@ void default_send_IPI_single(int cpu, int vector) apic->send_IPI_mask(cpumask_of(cpu), vector); } +void default_send_IPI_allbutself(int vector) +{ + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); +} + +void default_send_IPI_all(int vector) +{ + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); +} + +void default_send_IPI_self(int vector) +{ + __default_send_IPI_shortcut(APIC_DEST_SELF, vector); +} + #ifdef CONFIG_X86_32 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, @@ -285,21 +300,6 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector) local_irq_restore(flags); } -void default_send_IPI_allbutself(int vector) -{ - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); -} - -void default_send_IPI_all(int vector) -{ - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); -} - -void default_send_IPI_self(int vector) -{ - __default_send_IPI_shortcut(APIC_DEST_SELF, vector); -} - /* must come after the send_IPI functions above for inlining */ static int convert_apicid_to_cpu(int apic_id) { diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h index 391594cd5ca9..69ba777cef98 100644 --- a/arch/x86/kernel/apic/local.h +++ b/arch/x86/kernel/apic/local.h @@ -56,12 +56,12 @@ void default_send_IPI_single(int cpu, int vector); void default_send_IPI_single_phys(int cpu, int vector); void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector); void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector); +void default_send_IPI_allbutself(int vector); +void default_send_IPI_all(int vector); +void default_send_IPI_self(int vector); #ifdef CONFIG_X86_32 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector); void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector); void default_send_IPI_mask_logical(const struct cpumask *mask, int vector); -void default_send_IPI_allbutself(int vector); -void default_send_IPI_all(int vector); -void default_send_IPI_self(int vector); #endif -- GitLab From 2510d09e9dabc265341f164e0b45b2dfdcb7ef36 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:29 +0200 Subject: [PATCH 0663/7155] x86/apic/flat64: Remove the IPI shorthand decision logic All callers of apic->send_IPI_all() and apic->send_IPI_allbutself() contain the decision logic for shorthand invocation already and invoke send_IPI_mask() if the prereqisites are not satisfied. Remove the now redundant decision logic in the APIC code and the duplicate helper in probe_64.c. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105221.042964120@linutronix.de --- arch/x86/include/asm/apic.h | 4 --- arch/x86/kernel/apic/apic_flat_64.c | 49 ++++------------------------- arch/x86/kernel/apic/probe_64.c | 7 ----- 3 files changed, 6 insertions(+), 54 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index de86c6c15228..2ebc17d9c72c 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -468,10 +468,6 @@ static inline unsigned default_get_apic_id(unsigned long x) #define TRAMPOLINE_PHYS_LOW 0x467 #define TRAMPOLINE_PHYS_HIGH 0x469 -#ifdef CONFIG_X86_64 -extern void apic_send_IPI_self(int vector); -#endif - extern void generic_bigsmp_probe(void); #ifdef CONFIG_X86_LOCAL_APIC diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 004611a44962..7862b152a052 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -76,33 +76,6 @@ flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) _flat_send_IPI_mask(mask, vector); } -static void flat_send_IPI_allbutself(int vector) -{ - int cpu = smp_processor_id(); - - if (IS_ENABLED(CONFIG_HOTPLUG_CPU) || vector == NMI_VECTOR) { - if (!cpumask_equal(cpu_online_mask, cpumask_of(cpu))) { - unsigned long mask = cpumask_bits(cpu_online_mask)[0]; - - if (cpu < BITS_PER_LONG) - __clear_bit(cpu, &mask); - - _flat_send_IPI_mask(mask, vector); - } - } else if (num_online_cpus() > 1) { - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); - } -} - -static void flat_send_IPI_all(int vector) -{ - if (vector == NMI_VECTOR) { - flat_send_IPI_mask(cpu_online_mask, vector); - } else { - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); - } -} - static unsigned int flat_get_apic_id(unsigned long x) { return (x >> 24) & 0xFF; @@ -164,9 +137,9 @@ static struct apic apic_flat __ro_after_init = { .send_IPI = default_send_IPI_single, .send_IPI_mask = flat_send_IPI_mask, .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, - .send_IPI_allbutself = flat_send_IPI_allbutself, - .send_IPI_all = flat_send_IPI_all, - .send_IPI_self = apic_send_IPI_self, + .send_IPI_allbutself = default_send_IPI_allbutself, + .send_IPI_all = default_send_IPI_all, + .send_IPI_self = default_send_IPI_self, .inquire_remote_apic = default_inquire_remote_apic, @@ -216,16 +189,6 @@ static void physflat_init_apic_ldr(void) */ } -static void physflat_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); -} - -static void physflat_send_IPI_all(int vector) -{ - default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); -} - static int physflat_probe(void) { if (apic == &apic_physflat || num_possible_cpus() > 8 || @@ -267,9 +230,9 @@ static struct apic apic_physflat __ro_after_init = { .send_IPI = default_send_IPI_single_phys, .send_IPI_mask = default_send_IPI_mask_sequence_phys, .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_phys, - .send_IPI_allbutself = physflat_send_IPI_allbutself, - .send_IPI_all = physflat_send_IPI_all, - .send_IPI_self = apic_send_IPI_self, + .send_IPI_allbutself = default_send_IPI_allbutself, + .send_IPI_all = default_send_IPI_all, + .send_IPI_self = default_send_IPI_self, .inquire_remote_apic = default_inquire_remote_apic, diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index fb457b540e78..29f0e0984557 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -36,13 +36,6 @@ void __init default_setup_apic_routing(void) x86_platform.apic_post_init(); } -/* Same for both flat and physical. */ - -void apic_send_IPI_self(int vector) -{ - __default_send_IPI_shortcut(APIC_DEST_SELF, vector); -} - int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { struct apic **drv; -- GitLab From 43931d350f30c6cd8c2f498d54ef7d65750abc92 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Jul 2019 20:47:30 +0200 Subject: [PATCH 0664/7155] x86/apic/x2apic: Implement IPI shorthands support All callers of apic->send_IPI_all() and apic->send_IPI_allbutself() contain the decision logic for shorthand invocation already and invoke send_IPI_mask() if the prereqisites are not satisfied. Implement shorthand support for x2apic. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190722105221.134696837@linutronix.de --- arch/x86/kernel/apic/local.h | 1 + arch/x86/kernel/apic/x2apic_cluster.c | 4 ++-- arch/x86/kernel/apic/x2apic_phys.c | 12 ++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h index 69ba777cef98..04797f05ce94 100644 --- a/arch/x86/kernel/apic/local.h +++ b/arch/x86/kernel/apic/local.h @@ -23,6 +23,7 @@ unsigned int x2apic_get_apic_id(unsigned long id); u32 x2apic_set_apic_id(unsigned int id); int x2apic_phys_pkg_id(int initial_apicid, int index_msb); void x2apic_send_IPI_self(int vector); +void __x2apic_send_IPI_shorthand(int vector, u32 which); /* IPI */ diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index d0a13c88f777..45e92cba92f5 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -82,12 +82,12 @@ x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) static void x2apic_send_IPI_allbutself(int vector) { - __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT); + __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT); } static void x2apic_send_IPI_all(int vector) { - __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); + __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC); } static u32 x2apic_calc_apicid(unsigned int cpu) diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 5d50e1f9d4bf..bc9693841353 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -75,12 +75,12 @@ static void static void x2apic_send_IPI_allbutself(int vector) { - __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT); + __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT); } static void x2apic_send_IPI_all(int vector) { - __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); + __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC); } static void init_x2apic_ldr(void) @@ -112,6 +112,14 @@ void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest) native_x2apic_icr_write(cfg, apicid); } +void __x2apic_send_IPI_shorthand(int vector, u32 which) +{ + unsigned long cfg = __prepare_ICR(which, vector, 0); + + x2apic_wrmsr_fence(); + native_x2apic_icr_write(cfg, 0); +} + unsigned int x2apic_get_apic_id(unsigned long id) { return id; -- GitLab From 36a80df44b6f06f33b0ba10ff01bc87e352257fa Mon Sep 17 00:00:00 2001 From: Malathi Gottam Date: Tue, 2 Jul 2019 17:42:29 +0530 Subject: [PATCH 0665/7155] arm64: dts: sdm845: Add video nodes This adds video nodes to sdm845 based on the examples in the bindings. Tested-by: An\355bal Lim\363n Reviewed-by: Rajendra Nayak Signed-off-by: Malathi Gottam Co-developed-by: Aniket Masule Signed-off-by: Aniket Masule Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 4babff5f19b5..0323e3da190a 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2027,6 +2027,36 @@ }; }; + video-codec@aa00000 { + compatible = "qcom,sdm845-venus"; + reg = <0 0x0aa00000 0 0xff000>; + interrupts = ; + power-domains = <&videocc VENUS_GDSC>; + clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>, + <&videocc VIDEO_CC_VENUS_AHB_CLK>, + <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>; + clock-names = "core", "iface", "bus"; + iommus = <&apps_smmu 0x10a0 0x8>, + <&apps_smmu 0x10b0 0x0>; + memory-region = <&venus_mem>; + + video-core0 { + compatible = "venus-decoder"; + clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC0_AXI_CLK>; + clock-names = "core", "bus"; + power-domains = <&videocc VCODEC0_GDSC>; + }; + + video-core1 { + compatible = "venus-encoder"; + clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC1_AXI_CLK>; + clock-names = "core", "bus"; + power-domains = <&videocc VCODEC1_GDSC>; + }; + }; + videocc: clock-controller@ab00000 { compatible = "qcom,sdm845-videocc"; reg = <0 0x0ab00000 0 0x10000>; -- GitLab From a1875bf98290e538de2484c4db957ace5a8ac578 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 10:19:02 +0530 Subject: [PATCH 0666/7155] arm64: dts: qcom: sdm845: Add unit name to soc node We get a warning about missing unit name for soc node, so add it. arch/arm64/boot/dts/qcom/sdm845.dtsi:623.11-2814.4: Warning (unit_address_vs_reg): /soc: node has a reg or ranges property, but no unit name Signed-off-by: Vinod Koul Reviewed-by: Stephen Boyd Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 0323e3da190a..b305c694589d 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -620,7 +620,7 @@ method = "smc"; }; - soc: soc { + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; ranges = <0 0 0 0 0x10 0>; -- GitLab From 81a7b51177fc864a5c6bab885deae7b8f4103f21 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 10:19:03 +0530 Subject: [PATCH 0667/7155] arm64: dts: qcom: sdm845: remove unnecessary properties for dsi nodes We get a warning about unnecessary properties of arch/arm64/boot/dts/qcom/sdm845.dtsi:2211.22-2257.6: Warning (avoid_unnecessary_addr_size): /soc/mdss@ae00000/dsi@ae94000: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property arch/arm64/boot/dts/qcom/sdm845.dtsi:2278.22-2324.6: Warning (avoid_unnecessary_addr_size): /soc/mdss@ae00000/dsi@ae96000: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property So, remove these properties Signed-off-by: Vinod Koul Reviewed-by: Stephen Boyd Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index b305c694589d..d61e94286ea7 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2161,9 +2161,6 @@ status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - ports { #address-cells = <1>; #size-cells = <0>; @@ -2228,9 +2225,6 @@ status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - ports { #address-cells = <1>; #size-cells = <0>; -- GitLab From 19e684e835f6321b7c1d633f22cb4c4889f50747 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 10:19:04 +0530 Subject: [PATCH 0668/7155] arm64: dts: qcom: sdm845: remove unit name for thermal trip points The thermal trip points have unit name but no reg property, so we can remove them arch/arm64/boot/dts/qcom/sdm845.dtsi:2824.31-2828.7: Warning (unit_address_vs_reg): /thermal-zones/cpu0-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2830.31-2834.7: Warning (unit_address_vs_reg): /thermal-zones/cpu0-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2868.31-2872.7: Warning (unit_address_vs_reg): /thermal-zones/cpu1-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2874.31-2878.7: Warning (unit_address_vs_reg): /thermal-zones/cpu1-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2912.31-2916.7: Warning (unit_address_vs_reg): /thermal-zones/cpu2-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2918.31-2922.7: Warning (unit_address_vs_reg): /thermal-zones/cpu2-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2956.31-2960.7: Warning (unit_address_vs_reg): /thermal-zones/cpu3-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:2962.31-2966.7: Warning (unit_address_vs_reg): /thermal-zones/cpu3-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3000.31-3004.7: Warning (unit_address_vs_reg): /thermal-zones/cpu4-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3006.31-3010.7: Warning (unit_address_vs_reg): /thermal-zones/cpu4-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3044.31-3048.7: Warning (unit_address_vs_reg): /thermal-zones/cpu5-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3050.31-3054.7: Warning (unit_address_vs_reg): /thermal-zones/cpu5-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3088.31-3092.7: Warning (unit_address_vs_reg): /thermal-zones/cpu6-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3094.31-3098.7: Warning (unit_address_vs_reg): /thermal-zones/cpu6-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3132.31-3136.7: Warning (unit_address_vs_reg): /thermal-zones/cpu7-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3138.31-3142.7: Warning (unit_address_vs_reg): /thermal-zones/cpu7-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3176.32-3180.7: Warning (unit_address_vs_reg): /thermal-zones/aoss0-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3191.35-3195.7: Warning (unit_address_vs_reg): /thermal-zones/cluster0-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3211.35-3215.7: Warning (unit_address_vs_reg): /thermal-zones/cluster1-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3231.31-3235.7: Warning (unit_address_vs_reg): /thermal-zones/gpu-thermal-top/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3246.31-3250.7: Warning (unit_address_vs_reg): /thermal-zones/gpu-thermal-bottom/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3261.32-3265.7: Warning (unit_address_vs_reg): /thermal-zones/aoss1-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3276.35-3280.7: Warning (unit_address_vs_reg): /thermal-zones/q6-modem-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3291.30-3295.7: Warning (unit_address_vs_reg): /thermal-zones/mem-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3306.31-3310.7: Warning (unit_address_vs_reg): /thermal-zones/wlan-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3321.33-3325.7: Warning (unit_address_vs_reg): /thermal-zones/q6-hvx-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3336.33-3340.7: Warning (unit_address_vs_reg): /thermal-zones/camera-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3351.32-3355.7: Warning (unit_address_vs_reg): /thermal-zones/video-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/sdm845.dtsi:3366.32-3370.7: Warning (unit_address_vs_reg): /thermal-zones/modem-thermal/trips/trip-point@0: node has a unit name, but no reg property Signed-off-by: Vinod Koul Reviewed-by: Stephen Boyd Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 58 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index d61e94286ea7..c8ebe21f7673 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2742,13 +2742,13 @@ thermal-sensors = <&tsens0 1>; trips { - cpu0_alert0: trip-point@0 { + cpu0_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu0_alert1: trip-point@1 { + cpu0_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -2786,13 +2786,13 @@ thermal-sensors = <&tsens0 2>; trips { - cpu1_alert0: trip-point@0 { + cpu1_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu1_alert1: trip-point@1 { + cpu1_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -2830,13 +2830,13 @@ thermal-sensors = <&tsens0 3>; trips { - cpu2_alert0: trip-point@0 { + cpu2_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu2_alert1: trip-point@1 { + cpu2_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -2874,13 +2874,13 @@ thermal-sensors = <&tsens0 4>; trips { - cpu3_alert0: trip-point@0 { + cpu3_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu3_alert1: trip-point@1 { + cpu3_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -2918,13 +2918,13 @@ thermal-sensors = <&tsens0 7>; trips { - cpu4_alert0: trip-point@0 { + cpu4_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu4_alert1: trip-point@1 { + cpu4_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -2962,13 +2962,13 @@ thermal-sensors = <&tsens0 8>; trips { - cpu5_alert0: trip-point@0 { + cpu5_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu5_alert1: trip-point@1 { + cpu5_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -3006,13 +3006,13 @@ thermal-sensors = <&tsens0 9>; trips { - cpu6_alert0: trip-point@0 { + cpu6_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu6_alert1: trip-point@1 { + cpu6_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -3050,13 +3050,13 @@ thermal-sensors = <&tsens0 10>; trips { - cpu7_alert0: trip-point@0 { + cpu7_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "passive"; }; - cpu7_alert1: trip-point@1 { + cpu7_alert1: trip-point1 { temperature = <95000>; hysteresis = <2000>; type = "passive"; @@ -3094,7 +3094,7 @@ thermal-sensors = <&tsens0 0>; trips { - aoss0_alert0: trip-point@0 { + aoss0_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3109,7 +3109,7 @@ thermal-sensors = <&tsens0 5>; trips { - cluster0_alert0: trip-point@0 { + cluster0_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3129,7 +3129,7 @@ thermal-sensors = <&tsens0 6>; trips { - cluster1_alert0: trip-point@0 { + cluster1_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3149,7 +3149,7 @@ thermal-sensors = <&tsens0 11>; trips { - gpu1_alert0: trip-point@0 { + gpu1_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3164,7 +3164,7 @@ thermal-sensors = <&tsens0 12>; trips { - gpu2_alert0: trip-point@0 { + gpu2_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3179,7 +3179,7 @@ thermal-sensors = <&tsens1 0>; trips { - aoss1_alert0: trip-point@0 { + aoss1_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3194,7 +3194,7 @@ thermal-sensors = <&tsens1 1>; trips { - q6_modem_alert0: trip-point@0 { + q6_modem_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3209,7 +3209,7 @@ thermal-sensors = <&tsens1 2>; trips { - mem_alert0: trip-point@0 { + mem_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3224,7 +3224,7 @@ thermal-sensors = <&tsens1 3>; trips { - wlan_alert0: trip-point@0 { + wlan_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3239,7 +3239,7 @@ thermal-sensors = <&tsens1 4>; trips { - q6_hvx_alert0: trip-point@0 { + q6_hvx_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3254,7 +3254,7 @@ thermal-sensors = <&tsens1 5>; trips { - camera_alert0: trip-point@0 { + camera_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3269,7 +3269,7 @@ thermal-sensors = <&tsens1 6>; trips { - video_alert0: trip-point@0 { + video_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; @@ -3284,7 +3284,7 @@ thermal-sensors = <&tsens1 7>; trips { - modem_alert0: trip-point@0 { + modem_alert0: trip-point0 { temperature = <90000>; hysteresis = <2000>; type = "hot"; -- GitLab From 2833d79c28b8c7687fd5d2974f84bbadf2dbe1a1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 10:19:06 +0530 Subject: [PATCH 0669/7155] arm64: dts: qcom: sdm845-cheza: remove macro from unit name Unit address is supposed to be a number, using a macro with hex value is not recommended, so add the value in unit name. arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi:966.16-969.4: Warning (unit_address_format): /soc@0/spmi@c440000/pmic@0/adc@3100/adc-chan@0x4d: unit name should not have leading "0x" arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi:971.16-974.4: Warning (unit_address_format): /soc@0/spmi@c440000/pmic@0/adc@3100/adc-chan@0x4e: unit name should not have leading "0x" arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi:976.16-979.4: Warning (unit_address_format): /soc@0/spmi@c440000/pmic@0/adc@3100/adc-chan@0x4f: unit name should not have leading "0x" arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi:981.16-984.4: Warning (unit_address_format): /soc@0/spmi@c440000/pmic@0/adc@3100/adc-chan@0x50: unit name should not have leading "0x" arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi:986.16-989.4: Warning (unit_address_format): /soc@0/spmi@c440000/pmic@0/adc@3100/adc-chan@0x51: unit name should not have leading "0x" Signed-off-by: Vinod Koul Reviewed-by: Stephen Boyd Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi index 1ebbd568dfd7..9b27b8346ba1 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi @@ -963,27 +963,27 @@ ap_ts_i2c: &i2c14 { }; &pm8998_adc { - adc-chan@ADC5_AMUX_THM1_100K_PU { + adc-chan@4d { reg = ; label = "sdm_temp"; }; - adc-chan@ADC5_AMUX_THM2_100K_PU { + adc-chan@4e { reg = ; label = "quiet_temp"; }; - adc-chan@ADC5_AMUX_THM3_100K_PU { + adc-chan@4f { reg = ; label = "lte_temp_1"; }; - adc-chan@ADC5_AMUX_THM4_100K_PU { + adc-chan@50 { reg = ; label = "lte_temp_2"; }; - adc-chan@ADC5_AMUX_THM5_100K_PU { + adc-chan@51 { reg = ; label = "charger_temp"; }; -- GitLab From e77cc85ee3902303c71b3923f772680f4cb3de99 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 10:19:05 +0530 Subject: [PATCH 0670/7155] arm64: dts: qcom: sdm845: remove macro from unit name Unit name is supposed to be a number, using a macro with hex value is not recommended, so add the value in unit name. arch/arm64/boot/dts/qcom/pm8998.dtsi:81.18-84.6: Warning (unit_address_format): /soc/spmi@c440000/pmic@0/adc@3100/adc-chan@0x06: unit name should not have leading "0x" arch/arm64/boot/dts/qcom/pm8998.dtsi:81.18-84.6: Warning (unit_address_format): /soc/spmi@c440000/pmic@0/adc@3100/adc-chan@0x06: unit name should not have leading 0s Reviewed-by: Amit Kucheria Reviewed-by: Stephen Boyd Signed-off-by: Vinod Koul Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm8998.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi index 051a52df80f9..dc2ce23cde05 100644 --- a/arch/arm64/boot/dts/qcom/pm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi @@ -78,7 +78,7 @@ #size-cells = <0>; #io-channel-cells = <1>; - adc-chan@ADC5_DIE_TEMP { + adc-chan@6 { reg = ; label = "die_temp"; }; -- GitLab From 2ea4cfc9a7163b48514361cb02d46b0546dfcc86 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 1 Mar 2019 08:08:02 -0500 Subject: [PATCH 0671/7155] media: omap3isp: Rework OF endpoint parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework OF endpoint parsing for the omap3isp driver. This does add some lines of code. The benefits are still clear: - the great complication related to callbacks in endpoint parsing is gone; instead endpoints are obtained port by port and - endpoints may now have a default bus configuration which was not possible while using callbacks. This driver does not benefit from that feature, but as the omap3isp is one of the exemplary drivers, this works as an example for driver developers. Signed-off-by: Sakari Ailus Tested-by: Niklas Söderlund Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 331 +++++++++++++++----------- 1 file changed, 197 insertions(+), 134 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 83216fc7156b..3b9c82b63433 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2014,136 +2014,6 @@ enum isp_of_phy { ISP_OF_PHY_CSIPHY2, }; -static int isp_fwnode_parse(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd) -{ - struct isp_async_subdev *isd = - container_of(asd, struct isp_async_subdev, asd); - struct isp_bus_cfg *buscfg = &isd->bus; - bool csi1 = false; - unsigned int i; - - dev_dbg(dev, "parsing endpoint %pOF, interface %u\n", - to_of_node(vep->base.local_fwnode), vep->base.port); - - switch (vep->base.port) { - case ISP_OF_PHY_PARALLEL: - buscfg->interface = ISP_INTERFACE_PARALLEL; - buscfg->bus.parallel.data_lane_shift = - vep->bus.parallel.data_shift; - buscfg->bus.parallel.clk_pol = - !!(vep->bus.parallel.flags - & V4L2_MBUS_PCLK_SAMPLE_FALLING); - buscfg->bus.parallel.hs_pol = - !!(vep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); - buscfg->bus.parallel.vs_pol = - !!(vep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); - buscfg->bus.parallel.fld_pol = - !!(vep->bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); - buscfg->bus.parallel.data_pol = - !!(vep->bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); - buscfg->bus.parallel.bt656 = vep->bus_type == V4L2_MBUS_BT656; - break; - - case ISP_OF_PHY_CSIPHY1: - case ISP_OF_PHY_CSIPHY2: - switch (vep->bus_type) { - case V4L2_MBUS_CCP2: - case V4L2_MBUS_CSI1: - dev_dbg(dev, "CSI-1/CCP-2 configuration\n"); - csi1 = true; - break; - case V4L2_MBUS_CSI2_DPHY: - dev_dbg(dev, "CSI-2 configuration\n"); - csi1 = false; - break; - default: - dev_err(dev, "unsupported bus type %u\n", - vep->bus_type); - return -EINVAL; - } - - switch (vep->base.port) { - case ISP_OF_PHY_CSIPHY1: - if (csi1) - buscfg->interface = ISP_INTERFACE_CCP2B_PHY1; - else - buscfg->interface = ISP_INTERFACE_CSI2C_PHY1; - break; - case ISP_OF_PHY_CSIPHY2: - if (csi1) - buscfg->interface = ISP_INTERFACE_CCP2B_PHY2; - else - buscfg->interface = ISP_INTERFACE_CSI2A_PHY2; - break; - } - if (csi1) { - buscfg->bus.ccp2.lanecfg.clk.pos = - vep->bus.mipi_csi1.clock_lane; - buscfg->bus.ccp2.lanecfg.clk.pol = - vep->bus.mipi_csi1.lane_polarity[0]; - dev_dbg(dev, "clock lane polarity %u, pos %u\n", - buscfg->bus.ccp2.lanecfg.clk.pol, - buscfg->bus.ccp2.lanecfg.clk.pos); - - buscfg->bus.ccp2.lanecfg.data[0].pos = - vep->bus.mipi_csi1.data_lane; - buscfg->bus.ccp2.lanecfg.data[0].pol = - vep->bus.mipi_csi1.lane_polarity[1]; - - dev_dbg(dev, "data lane polarity %u, pos %u\n", - buscfg->bus.ccp2.lanecfg.data[0].pol, - buscfg->bus.ccp2.lanecfg.data[0].pos); - - buscfg->bus.ccp2.strobe_clk_pol = - vep->bus.mipi_csi1.clock_inv; - buscfg->bus.ccp2.phy_layer = vep->bus.mipi_csi1.strobe; - buscfg->bus.ccp2.ccp2_mode = - vep->bus_type == V4L2_MBUS_CCP2; - buscfg->bus.ccp2.vp_clk_pol = 1; - - buscfg->bus.ccp2.crc = 1; - } else { - buscfg->bus.csi2.lanecfg.clk.pos = - vep->bus.mipi_csi2.clock_lane; - buscfg->bus.csi2.lanecfg.clk.pol = - vep->bus.mipi_csi2.lane_polarities[0]; - dev_dbg(dev, "clock lane polarity %u, pos %u\n", - buscfg->bus.csi2.lanecfg.clk.pol, - buscfg->bus.csi2.lanecfg.clk.pos); - - buscfg->bus.csi2.num_data_lanes = - vep->bus.mipi_csi2.num_data_lanes; - - for (i = 0; i < buscfg->bus.csi2.num_data_lanes; i++) { - buscfg->bus.csi2.lanecfg.data[i].pos = - vep->bus.mipi_csi2.data_lanes[i]; - buscfg->bus.csi2.lanecfg.data[i].pol = - vep->bus.mipi_csi2.lane_polarities[i + 1]; - dev_dbg(dev, - "data lane %u polarity %u, pos %u\n", i, - buscfg->bus.csi2.lanecfg.data[i].pol, - buscfg->bus.csi2.lanecfg.data[i].pos); - } - /* - * FIXME: now we assume the CRC is always there. - * Implement a way to obtain this information from the - * sensor. Frame descriptors, perhaps? - */ - buscfg->bus.csi2.crc = 1; - } - break; - - default: - dev_warn(dev, "%pOF: invalid interface %u\n", - to_of_node(vep->base.local_fwnode), vep->base.port); - return -EINVAL; - } - - return 0; -} - static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) { struct isp_device *isp = container_of(async, struct isp_device, @@ -2173,6 +2043,201 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) return media_device_register(&isp->media_dev); } +static void isp_parse_of_parallel_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct isp_bus_cfg *buscfg) +{ + buscfg->interface = ISP_INTERFACE_PARALLEL; + buscfg->bus.parallel.data_lane_shift = vep->bus.parallel.data_shift; + buscfg->bus.parallel.clk_pol = + !!(vep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING); + buscfg->bus.parallel.hs_pol = + !!(vep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); + buscfg->bus.parallel.vs_pol = + !!(vep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); + buscfg->bus.parallel.fld_pol = + !!(vep->bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); + buscfg->bus.parallel.data_pol = + !!(vep->bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); + buscfg->bus.parallel.bt656 = vep->bus_type == V4L2_MBUS_BT656; +} + +static void isp_parse_of_csi2_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct isp_bus_cfg *buscfg) +{ + unsigned int i; + + buscfg->bus.csi2.lanecfg.clk.pos = vep->bus.mipi_csi2.clock_lane; + buscfg->bus.csi2.lanecfg.clk.pol = + vep->bus.mipi_csi2.lane_polarities[0]; + dev_dbg(dev, "clock lane polarity %u, pos %u\n", + buscfg->bus.csi2.lanecfg.clk.pol, + buscfg->bus.csi2.lanecfg.clk.pos); + + buscfg->bus.csi2.num_data_lanes = vep->bus.mipi_csi2.num_data_lanes; + + for (i = 0; i < buscfg->bus.csi2.num_data_lanes; i++) { + buscfg->bus.csi2.lanecfg.data[i].pos = + vep->bus.mipi_csi2.data_lanes[i]; + buscfg->bus.csi2.lanecfg.data[i].pol = + vep->bus.mipi_csi2.lane_polarities[i + 1]; + dev_dbg(dev, + "data lane %u polarity %u, pos %u\n", i, + buscfg->bus.csi2.lanecfg.data[i].pol, + buscfg->bus.csi2.lanecfg.data[i].pos); + } + /* + * FIXME: now we assume the CRC is always there. Implement a way to + * obtain this information from the sensor. Frame descriptors, perhaps? + */ + buscfg->bus.csi2.crc = 1; +} + +static void isp_parse_of_csi1_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct isp_bus_cfg *buscfg) +{ + buscfg->bus.ccp2.lanecfg.clk.pos = vep->bus.mipi_csi1.clock_lane; + buscfg->bus.ccp2.lanecfg.clk.pol = vep->bus.mipi_csi1.lane_polarity[0]; + dev_dbg(dev, "clock lane polarity %u, pos %u\n", + buscfg->bus.ccp2.lanecfg.clk.pol, + buscfg->bus.ccp2.lanecfg.clk.pos); + + buscfg->bus.ccp2.lanecfg.data[0].pos = vep->bus.mipi_csi1.data_lane; + buscfg->bus.ccp2.lanecfg.data[0].pol = + vep->bus.mipi_csi1.lane_polarity[1]; + + dev_dbg(dev, "data lane polarity %u, pos %u\n", + buscfg->bus.ccp2.lanecfg.data[0].pol, + buscfg->bus.ccp2.lanecfg.data[0].pos); + + buscfg->bus.ccp2.strobe_clk_pol = vep->bus.mipi_csi1.clock_inv; + buscfg->bus.ccp2.phy_layer = vep->bus.mipi_csi1.strobe; + buscfg->bus.ccp2.ccp2_mode = vep->bus_type == V4L2_MBUS_CCP2; + buscfg->bus.ccp2.vp_clk_pol = 1; + + buscfg->bus.ccp2.crc = 1; +} + +static int isp_alloc_isd(struct isp_async_subdev **isd, + struct isp_bus_cfg **buscfg) +{ + struct isp_async_subdev *__isd; + + __isd = kzalloc(sizeof(*__isd), GFP_KERNEL); + if (!__isd) + return -ENOMEM; + + *isd = __isd; + *buscfg = &__isd->bus; + + return 0; +} + +static struct { + u32 phy; + u32 csi2_if; + u32 csi1_if; +} isp_bus_interfaces[2] = { + { ISP_OF_PHY_CSIPHY1, + ISP_INTERFACE_CSI2C_PHY1, ISP_INTERFACE_CCP2B_PHY1 }, + { ISP_OF_PHY_CSIPHY2, + ISP_INTERFACE_CSI2A_PHY2, ISP_INTERFACE_CCP2B_PHY2 }, +}; + +static int isp_parse_of_endpoints(struct isp_device *isp) +{ + struct fwnode_handle *ep; + struct isp_async_subdev *isd = NULL; + struct isp_bus_cfg *buscfg; + unsigned int i; + + ep = fwnode_graph_get_endpoint_by_id( + dev_fwnode(isp->dev), ISP_OF_PHY_PARALLEL, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + + if (ep) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_PARALLEL + }; + int ret; + + dev_dbg(isp->dev, "parsing parallel interface\n"); + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + + if (!ret) { + ret = isp_alloc_isd(&isd, &buscfg); + if (ret) + return ret; + } + + if (!ret) { + isp_parse_of_parallel_endpoint(isp->dev, &vep, buscfg); + ret = v4l2_async_notifier_add_fwnode_remote_subdev( + &isp->notifier, ep, &isd->asd); + } + + fwnode_handle_put(ep); + if (ret) + kfree(isd); + } + + for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + int ret; + + ep = fwnode_graph_get_endpoint_by_id( + dev_fwnode(isp->dev), isp_bus_interfaces[i].phy, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + + if (!ep) + continue; + + dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i, + to_of_node(ep)); + + ret = isp_alloc_isd(&isd, &buscfg); + if (ret) + return ret; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (!ret) { + buscfg->interface = isp_bus_interfaces[i].csi2_if; + isp_parse_of_csi2_endpoint(isp->dev, &vep, buscfg); + } else if (ret == -ENXIO) { + vep = (struct v4l2_fwnode_endpoint) + { .bus_type = V4L2_MBUS_CSI1 }; + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + + if (ret == -ENXIO) { + vep = (struct v4l2_fwnode_endpoint) + { .bus_type = V4L2_MBUS_CCP2 }; + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + } + if (!ret) { + buscfg->interface = + isp_bus_interfaces[i].csi1_if; + isp_parse_of_csi1_endpoint(isp->dev, &vep, + buscfg); + } + } + + if (!ret) + ret = v4l2_async_notifier_add_fwnode_remote_subdev( + &isp->notifier, ep, &isd->asd); + + fwnode_handle_put(ep); + if (ret) + kfree(isd); + } + + return 0; +} + static const struct v4l2_async_notifier_operations isp_subdev_notifier_ops = { .complete = isp_subdev_notifier_complete, }; @@ -2223,14 +2288,12 @@ static int isp_probe(struct platform_device *pdev) mutex_init(&isp->isp_mutex); spin_lock_init(&isp->stat_lock); v4l2_async_notifier_init(&isp->notifier); + isp->dev = &pdev->dev; - ret = v4l2_async_notifier_parse_fwnode_endpoints( - &pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev), - isp_fwnode_parse); + ret = isp_parse_of_endpoints(isp); if (ret < 0) goto error; - isp->dev = &pdev->dev; isp->ref_count = 0; ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32)); -- GitLab From d1e164289e55de90fcc5680f459a43972430a28d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 4 Mar 2019 04:29:49 -0500 Subject: [PATCH 0672/7155] media: v4l2-async: Safely clean up an uninitialised notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the V4L2 async framework a bit more robust by allowing to clean up an uninitialised notifier. Otherwise the result would be a (close to) NULL pointer dereference. Signed-off-by: Sakari Ailus Tested-by: Niklas Söderlund Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index dc4f470ea6a7..8bde33c21ce4 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -534,7 +534,7 @@ static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier) { struct v4l2_async_subdev *asd, *tmp; - if (!notifier) + if (!notifier || !notifier->asd_list.next) return; list_for_each_entry_safe(asd, tmp, ¬ifier->asd_list, asd_list) { -- GitLab From f6a5242b7cf20bf34e5362896df310a35ba3b90b Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 4 Mar 2019 04:36:40 -0500 Subject: [PATCH 0673/7155] media: ipu3-cio2: Clean up notifier's subdev list if parsing endpoints fails The notifier must be cleaned up whenever parsing endpoints fails. Do that to avoid a memory leak in that case. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 50a34bcd4d14..52bd35c240dd 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1504,7 +1504,7 @@ static int cio2_notifier_init(struct cio2_device *cio2) sizeof(struct sensor_async_subdev), cio2_fwnode_parse); if (ret < 0) - return ret; + goto out; if (list_empty(&cio2->notifier.asd_list)) return -ENODEV; /* no endpoint */ @@ -1514,9 +1514,13 @@ static int cio2_notifier_init(struct cio2_device *cio2) if (ret) { dev_err(&cio2->pci_dev->dev, "failed to register async notifier : %d\n", ret); - v4l2_async_notifier_cleanup(&cio2->notifier); + goto out; } +out: + if (ret) + v4l2_async_notifier_cleanup(&cio2->notifier); + return ret; } -- GitLab From 706c0cffaf2a1b5844fc99e62c09a21f7a7acfdf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 4 Mar 2019 04:45:57 -0500 Subject: [PATCH 0674/7155] media: ipu3-cio2: Proceed with notifier init even if there are no subdevs The notifier may be registered even if there are no subdevs. Do that to simplify the code. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 52bd35c240dd..6041d9e261de 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1506,9 +1506,10 @@ static int cio2_notifier_init(struct cio2_device *cio2) if (ret < 0) goto out; - if (list_empty(&cio2->notifier.asd_list)) - return -ENODEV; /* no endpoint */ - + /* + * Proceed even without sensors connected to allow the device to + * suspend. + */ cio2->notifier.ops = &cio2_async_ops; ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier); if (ret) { @@ -1815,8 +1816,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, /* Register notifier for subdevices we care */ r = cio2_notifier_init(cio2); - /* Proceed without sensors connected to allow the device to suspend. */ - if (r && r != -ENODEV) + if (r) goto fail_cio2_queue_exit; r = devm_request_irq(&pci_dev->dev, pci_dev->irq, cio2_irq, -- GitLab From 2c93346698bacd5e1a7fb59b7a5ab84cae1cc5da Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 4 Mar 2019 06:29:43 -0500 Subject: [PATCH 0675/7155] media: ipu3-cio2: Parse information from firmware without using callbacks Instead of using the convenience function v4l2_async_notifier_parse_fwnode_endpoints(), parse the endpoints and set up the async sub-devices without using callbacks. While this adds a little bit of code, it makes parsing the endpoints quite a bit more simple and gives more control to the driver over the process. The parsing assumes D-PHY instead of letting the V4L2 fwnode framework guess it. Signed-off-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 93 +++++++++++++----------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 6041d9e261de..1adfdc7ab0db 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1475,36 +1475,52 @@ static const struct v4l2_async_notifier_operations cio2_async_ops = { .complete = cio2_notifier_complete, }; -static int cio2_fwnode_parse(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd) +static int cio2_parse_firmware(struct cio2_device *cio2) { - struct sensor_async_subdev *s_asd = - container_of(asd, struct sensor_async_subdev, asd); + unsigned int i; + int ret; - if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { - dev_err(dev, "Only CSI2 bus type is currently supported\n"); - return -EINVAL; - } + for (i = 0; i < CIO2_NUM_PORTS; i++) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct sensor_async_subdev *s_asd = NULL; + struct fwnode_handle *ep; - s_asd->csi2.port = vep->base.port; - s_asd->csi2.lanes = vep->bus.mipi_csi2.num_data_lanes; + ep = fwnode_graph_get_endpoint_by_id( + dev_fwnode(&cio2->pci_dev->dev), i, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); - return 0; -} + if (!ep) + continue; -static int cio2_notifier_init(struct cio2_device *cio2) -{ - int ret; + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; - v4l2_async_notifier_init(&cio2->notifier); + s_asd = kzalloc(sizeof(*s_asd), GFP_KERNEL); + if (!s_asd) { + ret = -ENOMEM; + goto err_parse; + } - ret = v4l2_async_notifier_parse_fwnode_endpoints( - &cio2->pci_dev->dev, &cio2->notifier, - sizeof(struct sensor_async_subdev), - cio2_fwnode_parse); - if (ret < 0) - goto out; + s_asd->csi2.port = vep.base.port; + s_asd->csi2.lanes = vep.bus.mipi_csi2.num_data_lanes; + + ret = v4l2_async_notifier_add_fwnode_remote_subdev( + &cio2->notifier, ep, &s_asd->asd); + if (ret) + goto err_parse; + + fwnode_handle_put(ep); + + continue; + +err_parse: + fwnode_handle_put(ep); + kfree(s_asd); + return ret; + } /* * Proceed even without sensors connected to allow the device to @@ -1512,25 +1528,13 @@ static int cio2_notifier_init(struct cio2_device *cio2) */ cio2->notifier.ops = &cio2_async_ops; ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier); - if (ret) { + if (ret) dev_err(&cio2->pci_dev->dev, "failed to register async notifier : %d\n", ret); - goto out; - } - -out: - if (ret) - v4l2_async_notifier_cleanup(&cio2->notifier); return ret; } -static void cio2_notifier_exit(struct cio2_device *cio2) -{ - v4l2_async_notifier_unregister(&cio2->notifier); - v4l2_async_notifier_cleanup(&cio2->notifier); -} - /**************** Queue initialization ****************/ static const struct media_entity_operations cio2_media_ops = { .link_validate = v4l2_subdev_link_validate, @@ -1814,16 +1818,18 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, if (r) goto fail_v4l2_device_unregister; + v4l2_async_notifier_init(&cio2->notifier); + /* Register notifier for subdevices we care */ - r = cio2_notifier_init(cio2); + r = cio2_parse_firmware(cio2); if (r) - goto fail_cio2_queue_exit; + goto fail_clean_notifier; r = devm_request_irq(&pci_dev->dev, pci_dev->irq, cio2_irq, IRQF_SHARED, CIO2_NAME, cio2); if (r) { dev_err(&pci_dev->dev, "failed to request IRQ (%d)\n", r); - goto fail; + goto fail_clean_notifier; } pm_runtime_put_noidle(&pci_dev->dev); @@ -1831,9 +1837,9 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, return 0; -fail: - cio2_notifier_exit(cio2); -fail_cio2_queue_exit: +fail_clean_notifier: + v4l2_async_notifier_unregister(&cio2->notifier); + v4l2_async_notifier_cleanup(&cio2->notifier); cio2_queues_exit(cio2); fail_v4l2_device_unregister: v4l2_device_unregister(&cio2->v4l2_dev); @@ -1852,7 +1858,8 @@ static void cio2_pci_remove(struct pci_dev *pci_dev) struct cio2_device *cio2 = pci_get_drvdata(pci_dev); media_device_unregister(&cio2->media_dev); - cio2_notifier_exit(cio2); + v4l2_async_notifier_unregister(&cio2->notifier); + v4l2_async_notifier_cleanup(&cio2->notifier); cio2_queues_exit(cio2); cio2_fbpt_exit_dummy(cio2); v4l2_device_unregister(&cio2->v4l2_dev); -- GitLab From 049e684f2de9daa31a32423e16d2d3bd6bbd286f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 25 Jul 2019 08:48:21 -0400 Subject: [PATCH 0676/7155] media: v4l2-dev: fix WARN_ON(!vdev->device_caps) Device nodes of type VFL_TYPE_SUBDEV have a 0 device_caps, so they trigger this warning. Add a check against VFL_TYPE_SUBDEV. Signed-off-by: Hans Verkuil Fixes: 3c1350501c21 ("media: v4l2-dev/ioctl: require non-zero device_caps, verify sane querycap results") Reported-by: Jan Kotas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 3af72e3bbd65..a1c61d6f3b9b 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -859,8 +859,8 @@ int __video_register_device(struct video_device *vdev, /* the v4l2_dev pointer MUST be present */ if (WARN_ON(!vdev->v4l2_dev)) return -EINVAL; - /* the device_caps field MUST be set */ - if (WARN_ON(!vdev->device_caps)) + /* the device_caps field MUST be set for all but subdevs */ + if (WARN_ON(type != VFL_TYPE_SUBDEV && !vdev->device_caps)) return -EINVAL; /* v4l2_fh support */ -- GitLab From 19ab1f649ca43bd16042389fa06524c3c58d7bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 4 Jul 2019 13:15:59 -0400 Subject: [PATCH 0677/7155] media: rcar-vin: Rename VNDMR_DTMD_ARGB1555 to VNDMR_DTMD_ARGB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value have nothing to do with ARGB1555, it controls if the alpha component should be filled in for ARGB1555 or ARGB888. Rename it to reflect this. Signed-off-by: Niklas Söderlund Reviewed-by: Ulrich Hecht Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 372d6b106b99..44be73b78197 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -114,7 +114,7 @@ #define VNDMR_EXRGB (1 << 8) #define VNDMR_BPSM (1 << 4) #define VNDMR_DTMD_YCSEP (1 << 1) -#define VNDMR_DTMD_ARGB1555 (1 << 0) +#define VNDMR_DTMD_ARGB (1 << 0) /* Video n Data Mode Register 2 bits */ #define VNDMR2_VPS (1 << 30) @@ -721,7 +721,7 @@ static int rvin_setup(struct rvin_dev *vin) output_is_yuv = true; break; case V4L2_PIX_FMT_XRGB555: - dmr = VNDMR_DTMD_ARGB1555; + dmr = VNDMR_DTMD_ARGB; break; case V4L2_PIX_FMT_RGB565: dmr = 0; -- GitLab From 5720c7331ff7e376a6d612eb8c2920d1789d78f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 4 Jul 2019 13:16:00 -0400 Subject: [PATCH 0678/7155] media: rcar-vin: Add control for alpha component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to adding support for RGB pixel formats with an alpha component add a control to allow the user to control which alpha value should be used. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 53 ++++++++++++++++++++- drivers/media/platform/rcar-vin/rcar-dma.c | 5 ++ drivers/media/platform/rcar-vin/rcar-vin.h | 5 ++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index a6efe1a8099a..6993484ff0f3 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -389,6 +389,28 @@ static void rvin_group_put(struct rvin_dev *vin) kref_put(&group->refcount, rvin_group_release); } +/* ----------------------------------------------------------------------------- + * Controls + */ + +static int rvin_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct rvin_dev *vin = + container_of(ctrl->handler, struct rvin_dev, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_ALPHA_COMPONENT: + rvin_set_alpha(vin, ctrl->val); + break; + } + + return 0; +} + +static const struct v4l2_ctrl_ops rvin_ctrl_ops = { + .s_ctrl = rvin_s_ctrl, +}; + /* ----------------------------------------------------------------------------- * Async notifier */ @@ -478,6 +500,15 @@ static int rvin_parallel_subdevice_attach(struct rvin_dev *vin, if (ret < 0) return ret; + v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops, + V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); + + if (vin->ctrl_handler.error) { + ret = vin->ctrl_handler.error; + v4l2_ctrl_handler_free(&vin->ctrl_handler); + return ret; + } + ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler, NULL, true); if (ret < 0) { @@ -870,6 +901,21 @@ static int rvin_mc_init(struct rvin_dev *vin) if (ret) rvin_group_put(vin); + ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1); + if (ret < 0) + return ret; + + v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops, + V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); + + if (vin->ctrl_handler.error) { + ret = vin->ctrl_handler.error; + v4l2_ctrl_handler_free(&vin->ctrl_handler); + return ret; + } + + vin->vdev.ctrl_handler = &vin->ctrl_handler; + return ret; } @@ -1245,6 +1291,7 @@ static int rcar_vin_probe(struct platform_device *pdev) vin->dev = &pdev->dev; vin->info = of_device_get_match_data(&pdev->dev); + vin->alpha = 0xff; /* * Special care is needed on r8a7795 ES1.x since it @@ -1288,6 +1335,8 @@ static int rcar_vin_probe(struct platform_device *pdev) return 0; error_group_unregister: + v4l2_ctrl_handler_free(&vin->ctrl_handler); + if (vin->info->use_mc) { mutex_lock(&vin->group->lock); if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) { @@ -1323,10 +1372,10 @@ static int rcar_vin_remove(struct platform_device *pdev) } mutex_unlock(&vin->group->lock); rvin_group_put(vin); - } else { - v4l2_ctrl_handler_free(&vin->ctrl_handler); } + v4l2_ctrl_handler_free(&vin->ctrl_handler); + rvin_dma_unregister(vin); return 0; diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 44be73b78197..99deed70dc67 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1343,3 +1343,8 @@ int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) return 0; } + +void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha) +{ + vin->alpha = alpha; +} diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index ac1a6fe90015..e562c2ff21ec 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -178,6 +178,8 @@ struct rvin_info { * @compose: active composing * @source: active size of the video source * @std: active video standard of the video source + * + * @alpha: Alpha component to fill in for supported pixel formats */ struct rvin_dev { struct device *dev; @@ -215,6 +217,8 @@ struct rvin_dev { struct v4l2_rect compose; struct v4l2_rect source; v4l2_std_id std; + + unsigned int alpha; }; #define vin_to_source(vin) ((vin)->parallel->subdev) @@ -268,5 +272,6 @@ const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin, void rvin_crop_scale_comp(struct rvin_dev *vin); int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel); +void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha); #endif -- GitLab From 1d99e68ce7fd9b5f5ab01d72455e8acd699e49cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 4 Jul 2019 13:16:01 -0400 Subject: [PATCH 0679/7155] media: rcar-vin: Add support for RGB formats with alpha component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The R-Car VIN module supports V4L2_PIX_FMT_ARGB555 and V4L2_PIX_FMT_ABGR32 pixel formats. Add the hardware register setup and allow the alpha component to be changed while streaming using the V4L2_CID_ALPHA_COMPONENT control. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix checkpatch warning for macro VNDMR_A8BIT] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 35 +++++++++++++++++++++ drivers/media/platform/rcar-vin/rcar-v4l2.c | 8 +++++ 2 files changed, 43 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 99deed70dc67..f16f2966f962 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -111,8 +111,11 @@ #define VNIE_EFE (1 << 1) /* Video n Data Mode Register bits */ +#define VNDMR_A8BIT(n) (((n) & 0xff) << 24) +#define VNDMR_A8BIT_MASK (0xff << 24) #define VNDMR_EXRGB (1 << 8) #define VNDMR_BPSM (1 << 4) +#define VNDMR_ABIT (1 << 2) #define VNDMR_DTMD_YCSEP (1 << 1) #define VNDMR_DTMD_ARGB (1 << 0) @@ -730,6 +733,12 @@ static int rvin_setup(struct rvin_dev *vin) /* Note: not supported on M1 */ dmr = VNDMR_EXRGB; break; + case V4L2_PIX_FMT_ARGB555: + dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB; + break; + case V4L2_PIX_FMT_ABGR32: + dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB; + break; default: vin_err(vin, "Invalid pixelformat (0x%x)\n", vin->format.pixelformat); @@ -1346,5 +1355,31 @@ int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha) { + unsigned long flags; + u32 dmr; + + spin_lock_irqsave(&vin->qlock, flags); + vin->alpha = alpha; + + if (vin->state == STOPPED) + goto out; + + switch (vin->format.pixelformat) { + case V4L2_PIX_FMT_ARGB555: + dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT; + if (vin->alpha) + dmr |= VNDMR_ABIT; + break; + case V4L2_PIX_FMT_ABGR32: + dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK; + dmr |= VNDMR_A8BIT(vin->alpha); + break; + default: + goto out; + } + + rvin_write(vin, dmr, VNDMR_REG); +out: + spin_unlock_irqrestore(&vin->qlock, flags); } diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 04d798d8070f..192390c784f7 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -54,6 +54,14 @@ static const struct rvin_video_format rvin_formats[] = { .fourcc = V4L2_PIX_FMT_XBGR32, .bpp = 4, }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + .bpp = 2, + }, + { + .fourcc = V4L2_PIX_FMT_ABGR32, + .bpp = 4, + }, }; const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin, -- GitLab From 6b4633310ae8a10f8ffacdc3eb6272b013c2adef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 4 Jul 2019 13:16:02 -0400 Subject: [PATCH 0680/7155] media: rcar-vin: Always setup controls when opening video device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that both Gen2 (video device centric) and Gen3 (media device centric) modes of the driver have controls it is required to always setup the controls when opening the devices. Remove the check which only calls v4l2_ctrl_handler_setup() for Gen2 and call it unconditionally. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-v4l2.c | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 192390c784f7..cfed0a260413 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -790,26 +790,26 @@ static int rvin_open(struct file *file) if (ret) goto err_unlock; - if (vin->info->use_mc) { + if (vin->info->use_mc) ret = v4l2_pipeline_pm_use(&vin->vdev.entity, 1); - if (ret < 0) - goto err_open; - } else { - if (v4l2_fh_is_singular_file(file)) { - ret = rvin_power_parallel(vin, true); - if (ret < 0) - goto err_open; - - ret = v4l2_ctrl_handler_setup(&vin->ctrl_handler); - if (ret) - goto err_parallel; - } - } + else if (v4l2_fh_is_singular_file(file)) + ret = rvin_power_parallel(vin, true); + + if (ret < 0) + goto err_open; + + ret = v4l2_ctrl_handler_setup(&vin->ctrl_handler); + if (ret) + goto err_power; + mutex_unlock(&vin->lock); return 0; -err_parallel: - rvin_power_parallel(vin, false); +err_power: + if (vin->info->use_mc) + v4l2_pipeline_pm_use(&vin->vdev.entity, 0); + else if (v4l2_fh_is_singular_file(file)) + rvin_power_parallel(vin, false); err_open: v4l2_fh_release(file); err_unlock: -- GitLab From 24f6f93a19e86779da94d97f4adccf3ab2662a77 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 15 Jul 2019 17:23:15 -0400 Subject: [PATCH 0681/7155] media: Don't default-enable "ancillary driver autoselect" if EMBEDDED Admittedly, it's not easy to say what CONFIG_EMBEDDED really should be doing, just as it's not easy to say what is "embedded". In any case, the very description of MEDIA_SUBDRV_AUTOSELECT specifies that embedded systems usually don't want to enable this autoselect option. Therefore, drop the default-yes, when the CONFIG_EMBEDDED is chosen. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 21cd9c02960b..8404e80aa38e 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -190,7 +190,7 @@ config MEDIA_SUBDRV_AUTOSELECT depends on HAS_IOMEM select I2C select I2C_MUX - default y + default y if !EMBEDDED help By default, a media driver auto-selects all possible ancillary devices such as tuners, sensors, video encoders/decoders and -- GitLab From 5e291a908869dd4fe70832a89678c6b0c1b8c481 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 25 Jul 2019 10:09:24 +0800 Subject: [PATCH 0682/7155] ALSA: echoaudio: Replace kmalloc + memcpy with kmemdup Instead of using kmalloc + memcpy, use kmemdup to simplify the code. Signed-off-by: Chuhong Yuan Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index b612a536a5a1..ca9125726be2 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2189,11 +2189,10 @@ static int snd_echo_resume(struct device *dev) u32 pipe_alloc_mask; int err; - commpage_bak = kmalloc(sizeof(*commpage), GFP_KERNEL); + commpage = chip->comm_page; + commpage_bak = kmemdup(commpage, sizeof(*commpage), GFP_KERNEL); if (commpage_bak == NULL) return -ENOMEM; - commpage = chip->comm_page; - memcpy(commpage_bak, commpage, sizeof(*commpage)); err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); if (err < 0) { -- GitLab From aa0e9e72733b069a655a3fe9167f69de103830cc Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 24 Jul 2019 23:06:02 -0400 Subject: [PATCH 0683/7155] media: staging: media: hantro: Remove call to memset after dma_alloc_coherent fix below issue reported by coccicheck /drivers/staging/media/hantro/hantro_vp8.c:149:16-34: WARNING: dma_alloc_coherent use in aux_buf -> cpu already zeroes out memory, so memset is not needed Signed-off-by: Hariprasad Kelam Reviewed-by: Boris Brezillon Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_vp8.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_vp8.c b/drivers/staging/media/hantro/hantro_vp8.c index 66c45335d871..363dddaac794 100644 --- a/drivers/staging/media/hantro/hantro_vp8.c +++ b/drivers/staging/media/hantro/hantro_vp8.c @@ -151,8 +151,6 @@ int hantro_vp8_dec_init(struct hantro_ctx *ctx) if (!aux_buf->cpu) return -ENOMEM; - memset(aux_buf->cpu, 0, aux_buf->size); - /* * Allocate probability table buffer, * total 1208 bytes, 4K page is far enough. -- GitLab From c3c3509b86810293df5c524ef61421d8affc8bf0 Mon Sep 17 00:00:00 2001 From: Francois Buergisser Date: Thu, 25 Jul 2019 10:17:50 -0400 Subject: [PATCH 0684/7155] media: hantro: Set DMA max segment size The Hantro codec is typically used in platforms with an IOMMU, so we need to set a proper DMA segment size. Devices without an IOMMU will still fallback to default 64KiB segments. Cc: stable@vger.kernel.org Fixes: 775fec69008d3 ("media: add Rockchip VPU JPEG encoder driver") Signed-off-by: Francois Buergisser Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index b71a06e9159e..4eae1dbb1ac8 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -731,6 +731,7 @@ static int hantro_probe(struct platform_device *pdev) dev_err(vpu->dev, "Could not set DMA coherent mask.\n"); return ret; } + vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); for (i = 0; i < vpu->variant->num_irqs; i++) { const char *irq_name = vpu->variant->irqs[i].name; -- GitLab From 9530bbe726a14fea2acd972a13b5d526edc94e87 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 25 Jul 2019 10:17:51 -0400 Subject: [PATCH 0685/7155] media: hantro: Simplify the controls creation logic v4l2_ctrl_new_custom() should work for any kind of control, including standard ones. With that change, we automatically get support for menu controls. Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 2 -- drivers/staging/media/hantro/hantro_drv.c | 28 +++++++---------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 4d7cb7780bde..81e25dfc98b7 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -113,12 +113,10 @@ enum hantro_codec_mode { /* * struct hantro_ctrl - helper type to declare supported controls - * @id: V4L2 control ID (V4L2_CID_xxx) * @codec: codec id this control belong to (HANTRO_JPEG_ENCODER, etc.) * @cfg: control configuration */ struct hantro_ctrl { - unsigned int id; unsigned int codec; struct v4l2_ctrl_config cfg; }; diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 4eae1dbb1ac8..ff2dcbf43e81 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -264,31 +264,29 @@ static const struct v4l2_ctrl_ops hantro_ctrl_ops = { static struct hantro_ctrl controls[] = { { - .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, .codec = HANTRO_JPEG_ENCODER, .cfg = { + .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, .min = 5, .max = 100, .step = 1, .def = 50, + .ops = &hantro_ctrl_ops, }, }, { - .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, .codec = HANTRO_MPEG2_DECODER, .cfg = { - .elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params), + .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, }, }, { - .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION, .codec = HANTRO_MPEG2_DECODER, .cfg = { - .elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization), + .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION, }, }, { - .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, .codec = HANTRO_VP8_DECODER, .cfg = { - .elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header), + .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, }, }, }; @@ -304,22 +302,12 @@ static int hantro_ctrls_setup(struct hantro_dev *vpu, for (i = 0; i < num_ctrls; i++) { if (!(allowed_codecs & controls[i].codec)) continue; - if (!controls[i].cfg.elem_size) { - v4l2_ctrl_new_std(&ctx->ctrl_handler, - &hantro_ctrl_ops, - controls[i].id, controls[i].cfg.min, - controls[i].cfg.max, - controls[i].cfg.step, - controls[i].cfg.def); - } else { - controls[i].cfg.id = controls[i].id; - v4l2_ctrl_new_custom(&ctx->ctrl_handler, - &controls[i].cfg, NULL); - } + v4l2_ctrl_new_custom(&ctx->ctrl_handler, + &controls[i].cfg, NULL); if (ctx->ctrl_handler.error) { vpu_err("Adding control (%d) failed %d\n", - controls[i].id, + controls[i].cfg.id, ctx->ctrl_handler.error); v4l2_ctrl_handler_free(&ctx->ctrl_handler); return ctx->ctrl_handler.error; -- GitLab From 61e95d81aa28f411ff1238f56702dc2add2fac00 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 25 Jul 2019 10:17:52 -0400 Subject: [PATCH 0686/7155] media: hantro: Constify the control array controls[] is not supposed to be modified at runtime, let's make it explicit by adding a const specifier. Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index ff2dcbf43e81..398618b0d586 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -262,7 +262,7 @@ static const struct v4l2_ctrl_ops hantro_ctrl_ops = { .s_ctrl = hantro_s_ctrl, }; -static struct hantro_ctrl controls[] = { +static const struct hantro_ctrl controls[] = { { .codec = HANTRO_JPEG_ENCODER, .cfg = { -- GitLab From deff5c37c88921e61a336f1c4eba1f7ad438cebe Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 25 Jul 2019 10:17:53 -0400 Subject: [PATCH 0687/7155] media: hantro: Add hantro_get_{src, dst}_buf() helpers And replace all calls to v4l2_m2m_next_{src,dst}_buf() by hantro_get_{src,dst}_buf() one. Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 13 +++++++++++++ drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c | 4 ++-- drivers/staging/media/hantro/hantro_g1_vp8_dec.c | 8 ++++---- drivers/staging/media/hantro/hantro_h1_jpeg_enc.c | 4 ++-- .../staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c | 4 ++-- .../staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c | 4 ++-- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 81e25dfc98b7..c4c86c32ea2d 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -373,4 +374,16 @@ bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx); void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id); dma_addr_t hantro_get_ref(struct vb2_queue *q, u64 ts); +static inline struct vb2_v4l2_buffer * +hantro_get_src_buf(struct hantro_ctx *ctx) +{ + return v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +} + +static inline struct vb2_v4l2_buffer * +hantro_get_dst_buf(struct hantro_ctx *ctx) +{ + return v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +} + #endif /* HANTRO_H_ */ diff --git a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c index e592c1b66375..55f861e96108 100644 --- a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c @@ -167,8 +167,8 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx) const struct v4l2_mpeg2_picture *picture; u32 reg; - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + src_buf = hantro_get_src_buf(ctx); + dst_buf = hantro_get_dst_buf(ctx); /* Apply request controls if any */ v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index 72d983a11ca1..6032cbbecb06 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -260,7 +260,7 @@ static void cfg_parts(struct hantro_ctx *ctx, u32 count = 0; unsigned int i; - vb2_src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + vb2_src = hantro_get_src_buf(ctx); src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); /* @@ -391,7 +391,7 @@ static void cfg_ref(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *vb2_dst; dma_addr_t ref; - vb2_dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + vb2_dst = hantro_get_dst_buf(ctx); ref = hantro_get_ref(cap_q, hdr->last_frame_ts); if (!ref) @@ -424,7 +424,7 @@ static void cfg_buffers(struct hantro_ctx *ctx, dma_addr_t dst_dma; u32 reg; - vb2_dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + vb2_dst = hantro_get_dst_buf(ctx); /* Set probability table buffer address */ vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma, @@ -453,7 +453,7 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) u32 mb_width, mb_height; u32 reg; - vb2_src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + vb2_src = hantro_get_src_buf(ctx); v4l2_ctrl_request_setup(vb2_src->vb2_buf.req_obj.req, &ctx->ctrl_handler); diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c index 0c1e3043dc7e..f5adb5cbde50 100644 --- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c @@ -84,8 +84,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) struct hantro_jpeg_ctx jpeg_ctx; u32 reg; - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + src_buf = hantro_get_src_buf(ctx); + dst_buf = hantro_get_dst_buf(ctx); memset(&jpeg_ctx, 0, sizeof(jpeg_ctx)); jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c index ae66354d2d93..82c5af822766 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c @@ -116,8 +116,8 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx) struct media_request *src_req; u32 reg; - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + src_buf = hantro_get_src_buf(ctx); + dst_buf = hantro_get_dst_buf(ctx); src_req = src_buf->vb2_buf.req_obj.req; v4l2_ctrl_request_setup(src_req, &ctx->ctrl_handler); diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c index 8685bddfbcab..451bfcceadba 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c @@ -169,8 +169,8 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx) const struct v4l2_mpeg2_picture *picture; u32 reg; - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + src_buf = hantro_get_src_buf(ctx); + dst_buf = hantro_get_dst_buf(ctx); /* Apply request controls if any */ v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, -- GitLab From 932a9317ac492d4b93227357db4e3e2af28f0fbb Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 25 Jul 2019 10:17:54 -0400 Subject: [PATCH 0688/7155] media: hantro: Add helpers to prepare/finish a run And use them where appropriate. We might want to move hantro_{prepare,finish}_run() calls to device_run() and have a 2-step approach similar to cedrus (prepare + trigger) at some point, but let's keep that for later. Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_drv.c | 22 +++++++++++++++++++ .../media/hantro/hantro_g1_mpeg2_dec.c | 10 ++------- .../staging/media/hantro/hantro_g1_vp8_dec.c | 11 ++-------- .../staging/media/hantro/hantro_h1_jpeg_enc.c | 7 ++++-- drivers/staging/media/hantro/hantro_hw.h | 2 ++ .../media/hantro/rk3399_vpu_hw_jpeg_enc.c | 8 ++----- .../media/hantro/rk3399_vpu_hw_mpeg2_dec.c | 10 ++------- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 398618b0d586..4af6ee80229e 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -153,6 +153,28 @@ void hantro_watchdog(struct work_struct *work) } } +void hantro_prepare_run(struct hantro_ctx *ctx) +{ + struct vb2_v4l2_buffer *src_buf; + + src_buf = hantro_get_src_buf(ctx); + v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, + &ctx->ctrl_handler); +} + +void hantro_finish_run(struct hantro_ctx *ctx) +{ + struct vb2_v4l2_buffer *src_buf; + + src_buf = hantro_get_src_buf(ctx); + v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, + &ctx->ctrl_handler); + + /* Kick the watchdog. */ + schedule_delayed_work(&ctx->dev->watchdog_work, + msecs_to_jiffies(2000)); +} + static void device_run(void *priv) { struct hantro_ctx *ctx = priv; diff --git a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c index 55f861e96108..80f0e94f8afa 100644 --- a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c @@ -171,8 +171,7 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx) dst_buf = hantro_get_dst_buf(ctx); /* Apply request controls if any */ - v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, - &ctx->ctrl_handler); + hantro_prepare_run(ctx); slice_params = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS); @@ -248,12 +247,7 @@ void hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx) &dst_buf->vb2_buf, sequence, picture, slice_params); - /* Controls no longer in-use, we can complete them */ - v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, - &ctx->ctrl_handler); - - /* Kick the watchdog and start decoding */ - schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + hantro_finish_run(ctx); reg = G1_REG_DEC_E(1); vdpu_write(vpu, reg, G1_SWREG(1)); diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index 6032cbbecb06..cd1fbd3a0d5f 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -449,13 +449,10 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) struct hantro_dev *vpu = ctx->dev; size_t height = ctx->dst_fmt.height; size_t width = ctx->dst_fmt.width; - struct vb2_v4l2_buffer *vb2_src; u32 mb_width, mb_height; u32 reg; - vb2_src = hantro_get_src_buf(ctx); - v4l2_ctrl_request_setup(vb2_src->vb2_buf.req_obj.req, - &ctx->ctrl_handler); + hantro_prepare_run(ctx); hdr = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER); if (WARN_ON(!hdr)) @@ -516,11 +513,7 @@ void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) cfg_ref(ctx, hdr); cfg_buffers(ctx, hdr); - /* Controls no longer in-use, we can complete them */ - v4l2_ctrl_request_complete(vb2_src->vb2_buf.req_obj.req, - &ctx->ctrl_handler); - - schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + hantro_finish_run(ctx); vdpu_write(vpu, G1_REG_INTERRUPT_DEC_E, G1_REG_INTERRUPT); } diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c index f5adb5cbde50..ecd34a7db190 100644 --- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c @@ -87,6 +87,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) src_buf = hantro_get_src_buf(ctx); dst_buf = hantro_get_dst_buf(ctx); + hantro_prepare_run(ctx); + memset(&jpeg_ctx, 0, sizeof(jpeg_ctx)); jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); jpeg_ctx.width = ctx->dst_fmt.width; @@ -119,7 +121,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) | H1_REG_ENC_CTRL_ENC_MODE_JPEG | H1_REG_ENC_PIC_INTRA | H1_REG_ENC_CTRL_EN_BIT; - /* Kick the watchdog and start encoding */ - schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + + hantro_finish_run(ctx); + vepu_write(vpu, reg, H1_REG_ENC_CTRL); } diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 7849852affde..34ef24e3a9ef 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -97,6 +97,8 @@ void hantro_watchdog(struct work_struct *work); void hantro_run(struct hantro_ctx *ctx); void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, enum vb2_buffer_state result); +void hantro_prepare_run(struct hantro_ctx *ctx); +void hantro_finish_run(struct hantro_ctx *ctx); void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx); void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx); diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c index 82c5af822766..06162f569b5e 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c @@ -113,14 +113,12 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx) struct hantro_dev *vpu = ctx->dev; struct vb2_v4l2_buffer *src_buf, *dst_buf; struct hantro_jpeg_ctx jpeg_ctx; - struct media_request *src_req; u32 reg; src_buf = hantro_get_src_buf(ctx); dst_buf = hantro_get_dst_buf(ctx); - src_req = src_buf->vb2_buf.req_obj.req; - v4l2_ctrl_request_setup(src_req, &ctx->ctrl_handler); + hantro_prepare_run(ctx); memset(&jpeg_ctx, 0, sizeof(jpeg_ctx)); jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); @@ -157,9 +155,7 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx) | VEPU_REG_ENCODE_FORMAT_JPEG | VEPU_REG_ENCODE_ENABLE; - v4l2_ctrl_request_complete(src_req, &ctx->ctrl_handler); - /* Kick the watchdog and start encoding */ - schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + hantro_finish_run(ctx); vepu_write(vpu, reg, VEPU_REG_ENCODE_START); } diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c index 451bfcceadba..e7ba5c0441cc 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c @@ -172,9 +172,7 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx) src_buf = hantro_get_src_buf(ctx); dst_buf = hantro_get_dst_buf(ctx); - /* Apply request controls if any */ - v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, - &ctx->ctrl_handler); + hantro_prepare_run(ctx); slice_params = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS); @@ -254,12 +252,8 @@ void rk3399_vpu_mpeg2_dec_run(struct hantro_ctx *ctx) &dst_buf->vb2_buf, sequence, picture, slice_params); - /* Controls no longer in-use, we can complete them */ - v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, - &ctx->ctrl_handler); - /* Kick the watchdog and start decoding */ - schedule_delayed_work(&vpu->watchdog_work, msecs_to_jiffies(2000)); + hantro_finish_run(ctx); reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1); vdpu_write(vpu, reg, VDPU_SWREG(57)); -- GitLab From 6389a62ff798e781567645c0b0ca3dd7b8a4289d Mon Sep 17 00:00:00 2001 From: "Liu, Changcheng" Date: Thu, 25 Jul 2019 21:22:09 +0800 Subject: [PATCH 0689/7155] usbip: tools: fix GCC8 warning for strncpy GCC8 started emitting warning about using strncpy with number of bytes exactly equal destination size which could lead to non-zero terminated string being copied. Use "SYSFS_PATH_MAX - 1" & "SYSFS_BUS_ID_SIZE - 1" as number of bytes to ensure name is always zero-terminated. Signed-off-by: Changcheng Liu Acked-by: Shuah Khan Link: https://lore.kernel.org/r/20190725132209.GA27590@jerryopenix Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/libsrc/usbip_common.c | 6 ++++-- tools/usb/usbip/libsrc/usbip_device_driver.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c index bb424638d75b..b8d7d480595a 100644 --- a/tools/usb/usbip/libsrc/usbip_common.c +++ b/tools/usb/usbip/libsrc/usbip_common.c @@ -226,8 +226,10 @@ int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev) path = udev_device_get_syspath(sdev); name = udev_device_get_sysname(sdev); - strncpy(udev->path, path, SYSFS_PATH_MAX); - strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE); + strncpy(udev->path, path, SYSFS_PATH_MAX - 1); + udev->path[SYSFS_PATH_MAX - 1] = '\0'; + strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE - 1); + udev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0'; sscanf(name, "%u-%u", &busnum, &devnum); udev->busnum = busnum; diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c index 5a3726eb44ab..051d7d3f443b 100644 --- a/tools/usb/usbip/libsrc/usbip_device_driver.c +++ b/tools/usb/usbip/libsrc/usbip_device_driver.c @@ -91,7 +91,8 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) copy_descr_attr16(dev, &descr, idProduct); copy_descr_attr16(dev, &descr, bcdDevice); - strncpy(dev->path, path, SYSFS_PATH_MAX); + strncpy(dev->path, path, SYSFS_PATH_MAX - 1); + dev->path[SYSFS_PATH_MAX - 1] = '\0'; dev->speed = USB_SPEED_UNKNOWN; speed = udev_device_get_sysattr_value(sdev, "current_speed"); @@ -110,7 +111,8 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) dev->busnum = 0; name = udev_device_get_sysname(plat); - strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE); + strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE - 1); + dev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0'; return 0; err: fclose(fd); -- GitLab From 613326d62f7975e4f7899ffbf745f7cb52882461 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 25 Jul 2019 10:17:55 -0400 Subject: [PATCH 0690/7155] media: hantro: Move VP8 common code In order to introduce support for RK3399 VP8 decoding, move some common VP8 code. This will be reused by the RK3399 implementation, reducing code duplication. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_g1_vp8_dec.c | 17 ----------------- drivers/staging/media/hantro/hantro_hw.h | 4 ++++ drivers/staging/media/hantro/hantro_vp8.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index cd1fbd3a0d5f..181e2f76d8cb 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -16,8 +16,6 @@ #include "hantro.h" #include "hantro_g1_regs.h" -#define DEC_8190_ALIGN_MASK 0x07U - /* DCT partition base address regs */ static const struct hantro_reg vp8_dec_dct_base[8] = { { G1_REG_ADDR_STR, 0, 0xffffffff }, @@ -131,21 +129,6 @@ static const struct hantro_reg vp8_dec_pred_bc_tap[8][4] = { }, }; -/* - * filter taps taken to 7-bit precision, - * reference RFC6386#Page-16, filters[8][6] - */ -static const u32 vp8_dec_mc_filter[8][6] = { - { 0, 0, 128, 0, 0, 0 }, - { 0, -6, 123, 12, -1, 0 }, - { 2, -11, 108, 36, -8, 1 }, - { 0, -9, 93, 50, -6, 0 }, - { 3, -16, 77, 77, -16, 3 }, - { 0, -6, 50, 93, -9, 0 }, - { 1, -8, 36, 108, -11, 2 }, - { 0, -1, 12, 123, -6, 0 } -}; - /* * Set loop filters */ diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 34ef24e3a9ef..185e27d47e47 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -15,6 +15,8 @@ #include #include +#define DEC_8190_ALIGN_MASK 0x07U + struct hantro_dev; struct hantro_ctx; struct hantro_buf; @@ -93,6 +95,8 @@ extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3288_vpu_variant; +extern const u32 vp8_dec_mc_filter[8][6]; + void hantro_watchdog(struct work_struct *work); void hantro_run(struct hantro_ctx *ctx); void hantro_irq_done(struct hantro_dev *vpu, unsigned int bytesused, diff --git a/drivers/staging/media/hantro/hantro_vp8.c b/drivers/staging/media/hantro/hantro_vp8.c index 363dddaac794..cd01661cac21 100644 --- a/drivers/staging/media/hantro/hantro_vp8.c +++ b/drivers/staging/media/hantro/hantro_vp8.c @@ -31,6 +31,21 @@ struct vp8_prob_tbl_packed { u8 padding3[96]; }; +/* + * filter taps taken to 7-bit precision, + * reference RFC6386#Page-16, filters[8][6] + */ +const u32 vp8_dec_mc_filter[8][6] = { + { 0, 0, 128, 0, 0, 0 }, + { 0, -6, 123, 12, -1, 0 }, + { 2, -11, 108, 36, -8, 1 }, + { 0, -9, 93, 50, -6, 0 }, + { 3, -16, 77, 77, -16, 3 }, + { 0, -6, 50, 93, -9, 0 }, + { 1, -8, 36, 108, -11, 2 }, + { 0, -1, 12, 123, -6, 0 } +}; + void hantro_vp8_prob_update(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp8_frame_header *hdr) { -- GitLab From 73fb5bfa53e972f4fcf53c1c230fcc07a8cf6801 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Thu, 25 Jul 2019 10:17:56 -0400 Subject: [PATCH 0691/7155] media: hantro: Support RK3399 VP8 decoding Rockchip RK3399 SoC has the same Hantro G1 IP block as RK3288, but the registers are entirely different. In a similar fashion as MPEG-2 decoding, it's simpler to just add a separate implementation. Signed-off-by: Jeffy Chen Signed-off-by: Tomasz Figa Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Makefile | 1 + drivers/staging/media/hantro/hantro_hw.h | 1 + drivers/staging/media/hantro/rk3399_vpu_hw.c | 22 +- .../media/hantro/rk3399_vpu_hw_vp8_dec.c | 595 ++++++++++++++++++ 4 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index a627aee77f75..f5ec597d9e08 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -8,6 +8,7 @@ hantro-vpu-y += \ hantro_g1_vp8_dec.o \ rk3399_vpu_hw_jpeg_enc.o \ rk3399_vpu_hw_mpeg2_dec.o \ + rk3399_vpu_hw_vp8_dec.o \ hantro_jpeg.o \ hantro_mpeg2.o \ hantro_vp8.o diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 185e27d47e47..e86c84fbfe1a 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -117,6 +117,7 @@ int hantro_mpeg2_dec_init(struct hantro_ctx *ctx); void hantro_mpeg2_dec_exit(struct hantro_ctx *ctx); void hantro_g1_vp8_dec_run(struct hantro_ctx *ctx); +void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx); int hantro_vp8_dec_init(struct hantro_ctx *ctx); void hantro_vp8_dec_exit(struct hantro_ctx *ctx); void hantro_vp8_prob_update(struct hantro_ctx *ctx, diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw.c b/drivers/staging/media/hantro/rk3399_vpu_hw.c index f8400e49bc50..414b1d3fbb1f 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw.c @@ -73,6 +73,19 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = { .step_height = MPEG2_MB_DIM, }, }, + { + .fourcc = V4L2_PIX_FMT_VP8_FRAME, + .codec_mode = HANTRO_MODE_VP8_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = VP8_MB_DIM, + .min_height = 48, + .max_height = 2160, + .step_height = VP8_MB_DIM, + }, + }, }; static irqreturn_t rk3399_vepu_irq(int irq, void *dev_id) @@ -154,6 +167,12 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = { .init = hantro_mpeg2_dec_init, .exit = hantro_mpeg2_dec_exit, }, + [HANTRO_MODE_VP8_DEC] = { + .run = rk3399_vpu_vp8_dec_run, + .reset = rk3399_vpu_dec_reset, + .init = hantro_vp8_dec_init, + .exit = hantro_vp8_dec_exit, + }, }; /* @@ -176,7 +195,8 @@ const struct hantro_variant rk3399_vpu_variant = { .dec_offset = 0x400, .dec_fmts = rk3399_vpu_dec_fmts, .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), - .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER, + .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | + HANTRO_VP8_DECODER, .codec_ops = rk3399_vpu_codec_ops, .irqs = rk3399_irqs, .num_irqs = ARRAY_SIZE(rk3399_irqs), diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c new file mode 100644 index 000000000000..c5e9f8befe9c --- /dev/null +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip VPU codec vp8 decode driver + * + * Copyright (C) 2014 Rockchip Electronics Co., Ltd. + * ZhiChao Yu + * + * Copyright (C) 2014 Google LLC. + * Tomasz Figa + * + * Copyright (C) 2015 Rockchip Electronics Co., Ltd. + * Alpha Lin + */ + +#include +#include + +#include "hantro_hw.h" +#include "hantro.h" +#include "hantro_g1_regs.h" + +#define VDPU_REG_DEC_CTRL0 0x0c8 +#define VDPU_REG_STREAM_LEN 0x0cc +#define VDPU_REG_DEC_FORMAT 0x0d4 +#define VDPU_REG_DEC_CTRL0_DEC_MODE(x) (((x) & 0xf) << 0) +#define VDPU_REG_DATA_ENDIAN 0x0d8 +#define VDPU_REG_CONFIG_DEC_STRENDIAN_E BIT(5) +#define VDPU_REG_CONFIG_DEC_STRSWAP32_E BIT(4) +#define VDPU_REG_CONFIG_DEC_OUTSWAP32_E BIT(3) +#define VDPU_REG_CONFIG_DEC_INSWAP32_E BIT(2) +#define VDPU_REG_CONFIG_DEC_OUT_ENDIAN BIT(1) +#define VDPU_REG_CONFIG_DEC_IN_ENDIAN BIT(0) +#define VDPU_REG_AXI_CTRL 0x0e0 +#define VDPU_REG_CONFIG_DEC_MAX_BURST(x) (((x) & 0x1f) << 16) +#define VDPU_REG_EN_FLAGS 0x0e4 +#define VDPU_REG_DEC_CTRL0_PIC_INTER_E BIT(14) +#define VDPU_REG_CONFIG_DEC_TIMEOUT_E BIT(5) +#define VDPU_REG_CONFIG_DEC_CLK_GATE_E BIT(4) +#define VDPU_REG_PRED_FLT 0x0ec +#define VDPU_REG_ADDR_QTABLE 0x0f4 +#define VDPU_REG_ADDR_DST 0x0fc +#define VDPU_REG_ADDR_STR 0x100 +#define VDPU_REG_VP8_PIC_MB_SIZE 0x1e0 +#define VDPU_REG_VP8_DCT_START_BIT 0x1e4 +#define VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT BIT(13) +#define VDPU_REG_DEC_CTRL4_BILIN_MC_E BIT(12) +#define VDPU_REG_VP8_CTRL0 0x1e8 +#define VDPU_REG_VP8_DATA_VAL 0x1f0 +#define VDPU_REG_PRED_FLT7 0x1f4 +#define VDPU_REG_PRED_FLT8 0x1f8 +#define VDPU_REG_PRED_FLT9 0x1fc +#define VDPU_REG_PRED_FLT10 0x200 +#define VDPU_REG_FILTER_LEVEL 0x204 +#define VDPU_REG_VP8_QUANTER0 0x208 +#define VDPU_REG_VP8_ADDR_REF0 0x20c +#define VDPU_REG_FILTER_MB_ADJ 0x210 +#define VDPU_REG_REF_PIC_FILT_TYPE_E BIT(31) +#define VDPU_REG_REF_PIC_FILT_SHARPNESS(x) (((x) & 0x7) << 28) +#define VDPU_REG_FILTER_REF_ADJ 0x214 +#define VDPU_REG_VP8_ADDR_REF2_5(i) (0x218 + ((i) * 0x4)) +#define VDPU_REG_VP8_GREF_SIGN_BIAS BIT(0) +#define VDPU_REG_VP8_AREF_SIGN_BIAS BIT(0) +#define VDPU_REG_VP8_DCT_BASE(i) \ + (0x230 + ((((i) < 5) ? (i) : ((i) + 1)) * 0x4)) +#define VDPU_REG_VP8_ADDR_CTRL_PART 0x244 +#define VDPU_REG_VP8_SEGMENT_VAL 0x254 +#define VDPU_REG_FWD_PIC1_SEGMENT_BASE(x) ((x) << 0) +#define VDPU_REG_FWD_PIC1_SEGMENT_UPD_E BIT(1) +#define VDPU_REG_FWD_PIC1_SEGMENT_E BIT(0) +#define VDPU_REG_VP8_DCT_START_BIT2 0x258 +#define VDPU_REG_VP8_QUANTER1 0x25c +#define VDPU_REG_VP8_QUANTER2 0x260 +#define VDPU_REG_PRED_FLT1 0x264 +#define VDPU_REG_PRED_FLT2 0x268 +#define VDPU_REG_PRED_FLT3 0x26c +#define VDPU_REG_PRED_FLT4 0x270 +#define VDPU_REG_PRED_FLT5 0x274 +#define VDPU_REG_PRED_FLT6 0x278 + +static const struct hantro_reg vp8_dec_dct_base[8] = { + { VDPU_REG_ADDR_STR, 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(0), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(1), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(2), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(3), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(4), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(5), 0, 0xffffffff }, + { VDPU_REG_VP8_DCT_BASE(6), 0, 0xffffffff }, +}; + +static const struct hantro_reg vp8_dec_lf_level[4] = { + { VDPU_REG_FILTER_LEVEL, 18, 0x3f }, + { VDPU_REG_FILTER_LEVEL, 12, 0x3f }, + { VDPU_REG_FILTER_LEVEL, 6, 0x3f }, + { VDPU_REG_FILTER_LEVEL, 0, 0x3f }, +}; + +static const struct hantro_reg vp8_dec_mb_adj[4] = { + { VDPU_REG_FILTER_MB_ADJ, 21, 0x7f }, + { VDPU_REG_FILTER_MB_ADJ, 14, 0x7f }, + { VDPU_REG_FILTER_MB_ADJ, 7, 0x7f }, + { VDPU_REG_FILTER_MB_ADJ, 0, 0x7f }, +}; + +static const struct hantro_reg vp8_dec_ref_adj[4] = { + { VDPU_REG_FILTER_REF_ADJ, 21, 0x7f }, + { VDPU_REG_FILTER_REF_ADJ, 14, 0x7f }, + { VDPU_REG_FILTER_REF_ADJ, 7, 0x7f }, + { VDPU_REG_FILTER_REF_ADJ, 0, 0x7f }, +}; + +static const struct hantro_reg vp8_dec_quant[4] = { + { VDPU_REG_VP8_QUANTER0, 11, 0x7ff }, + { VDPU_REG_VP8_QUANTER0, 0, 0x7ff }, + { VDPU_REG_VP8_QUANTER1, 11, 0x7ff }, + { VDPU_REG_VP8_QUANTER1, 0, 0x7ff }, +}; + +static const struct hantro_reg vp8_dec_quant_delta[5] = { + { VDPU_REG_VP8_QUANTER0, 27, 0x1f }, + { VDPU_REG_VP8_QUANTER0, 22, 0x1f }, + { VDPU_REG_VP8_QUANTER1, 27, 0x1f }, + { VDPU_REG_VP8_QUANTER1, 22, 0x1f }, + { VDPU_REG_VP8_QUANTER2, 27, 0x1f }, +}; + +static const struct hantro_reg vp8_dec_dct_start_bits[8] = { + { VDPU_REG_VP8_CTRL0, 26, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT, 26, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT, 20, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT2, 24, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT2, 18, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT2, 12, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT2, 6, 0x3f }, + { VDPU_REG_VP8_DCT_START_BIT2, 0, 0x3f }, +}; + +static const struct hantro_reg vp8_dec_pred_bc_tap[8][6] = { + { + { 0, 0, 0}, + { VDPU_REG_PRED_FLT, 22, 0x3ff }, + { VDPU_REG_PRED_FLT, 12, 0x3ff }, + { VDPU_REG_PRED_FLT, 2, 0x3ff }, + { VDPU_REG_PRED_FLT1, 22, 0x3ff }, + { 0, 0, 0}, + }, { + { 0, 0, 0}, + { VDPU_REG_PRED_FLT1, 12, 0x3ff }, + { VDPU_REG_PRED_FLT1, 2, 0x3ff }, + { VDPU_REG_PRED_FLT2, 22, 0x3ff }, + { VDPU_REG_PRED_FLT2, 12, 0x3ff }, + { 0, 0, 0}, + }, { + { VDPU_REG_PRED_FLT10, 10, 0x3 }, + { VDPU_REG_PRED_FLT2, 2, 0x3ff }, + { VDPU_REG_PRED_FLT3, 22, 0x3ff }, + { VDPU_REG_PRED_FLT3, 12, 0x3ff }, + { VDPU_REG_PRED_FLT3, 2, 0x3ff }, + { VDPU_REG_PRED_FLT10, 8, 0x3}, + }, { + { 0, 0, 0}, + { VDPU_REG_PRED_FLT4, 22, 0x3ff }, + { VDPU_REG_PRED_FLT4, 12, 0x3ff }, + { VDPU_REG_PRED_FLT4, 2, 0x3ff }, + { VDPU_REG_PRED_FLT5, 22, 0x3ff }, + { 0, 0, 0}, + }, { + { VDPU_REG_PRED_FLT10, 6, 0x3 }, + { VDPU_REG_PRED_FLT5, 12, 0x3ff }, + { VDPU_REG_PRED_FLT5, 2, 0x3ff }, + { VDPU_REG_PRED_FLT6, 22, 0x3ff }, + { VDPU_REG_PRED_FLT6, 12, 0x3ff }, + { VDPU_REG_PRED_FLT10, 4, 0x3 }, + }, { + { 0, 0, 0}, + { VDPU_REG_PRED_FLT6, 2, 0x3ff }, + { VDPU_REG_PRED_FLT7, 22, 0x3ff }, + { VDPU_REG_PRED_FLT7, 12, 0x3ff }, + { VDPU_REG_PRED_FLT7, 2, 0x3ff }, + { 0, 0, 0}, + }, { + { VDPU_REG_PRED_FLT10, 2, 0x3 }, + { VDPU_REG_PRED_FLT8, 22, 0x3ff }, + { VDPU_REG_PRED_FLT8, 12, 0x3ff }, + { VDPU_REG_PRED_FLT8, 2, 0x3ff }, + { VDPU_REG_PRED_FLT9, 22, 0x3ff }, + { VDPU_REG_PRED_FLT10, 0, 0x3 }, + }, { + { 0, 0, 0}, + { VDPU_REG_PRED_FLT9, 12, 0x3ff }, + { VDPU_REG_PRED_FLT9, 2, 0x3ff }, + { VDPU_REG_PRED_FLT10, 22, 0x3ff }, + { VDPU_REG_PRED_FLT10, 12, 0x3ff }, + { 0, 0, 0}, + }, +}; + +static const struct hantro_reg vp8_dec_mb_start_bit = { + .base = VDPU_REG_VP8_CTRL0, + .shift = 18, + .mask = 0x3f +}; + +static const struct hantro_reg vp8_dec_mb_aligned_data_len = { + .base = VDPU_REG_VP8_DATA_VAL, + .shift = 0, + .mask = 0x3fffff +}; + +static const struct hantro_reg vp8_dec_num_dct_partitions = { + .base = VDPU_REG_VP8_DATA_VAL, + .shift = 24, + .mask = 0xf +}; + +static const struct hantro_reg vp8_dec_stream_len = { + .base = VDPU_REG_STREAM_LEN, + .shift = 0, + .mask = 0xffffff +}; + +static const struct hantro_reg vp8_dec_mb_width = { + .base = VDPU_REG_VP8_PIC_MB_SIZE, + .shift = 23, + .mask = 0x1ff +}; + +static const struct hantro_reg vp8_dec_mb_height = { + .base = VDPU_REG_VP8_PIC_MB_SIZE, + .shift = 11, + .mask = 0xff +}; + +static const struct hantro_reg vp8_dec_mb_width_ext = { + .base = VDPU_REG_VP8_PIC_MB_SIZE, + .shift = 3, + .mask = 0x7 +}; + +static const struct hantro_reg vp8_dec_mb_height_ext = { + .base = VDPU_REG_VP8_PIC_MB_SIZE, + .shift = 0, + .mask = 0x7 +}; + +static const struct hantro_reg vp8_dec_bool_range = { + .base = VDPU_REG_VP8_CTRL0, + .shift = 0, + .mask = 0xff +}; + +static const struct hantro_reg vp8_dec_bool_value = { + .base = VDPU_REG_VP8_CTRL0, + .shift = 8, + .mask = 0xff +}; + +static const struct hantro_reg vp8_dec_filter_disable = { + .base = VDPU_REG_DEC_CTRL0, + .shift = 8, + .mask = 1 +}; + +static const struct hantro_reg vp8_dec_skip_mode = { + .base = VDPU_REG_DEC_CTRL0, + .shift = 9, + .mask = 1 +}; + +static const struct hantro_reg vp8_dec_start_dec = { + .base = VDPU_REG_EN_FLAGS, + .shift = 0, + .mask = 1 +}; + +static void cfg_lf(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + const struct v4l2_vp8_loopfilter_header *lf = &hdr->lf_header; + struct hantro_dev *vpu = ctx->dev; + unsigned int i; + u32 reg; + + if (!(seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED)) { + hantro_reg_write(vpu, &vp8_dec_lf_level[0], lf->level); + } else if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE) { + for (i = 0; i < 4; i++) { + u32 lf_level = clamp(lf->level + seg->lf_update[i], + 0, 63); + + hantro_reg_write(vpu, &vp8_dec_lf_level[i], lf_level); + } + } else { + for (i = 0; i < 4; i++) + hantro_reg_write(vpu, &vp8_dec_lf_level[i], + seg->lf_update[i]); + } + + reg = VDPU_REG_REF_PIC_FILT_SHARPNESS(lf->sharpness_level); + if (lf->flags & V4L2_VP8_LF_FILTER_TYPE_SIMPLE) + reg |= VDPU_REG_REF_PIC_FILT_TYPE_E; + vdpu_write_relaxed(vpu, reg, VDPU_REG_FILTER_MB_ADJ); + + if (lf->flags & V4L2_VP8_LF_HEADER_ADJ_ENABLE) { + for (i = 0; i < 4; i++) { + hantro_reg_write(vpu, &vp8_dec_mb_adj[i], + lf->mb_mode_delta[i]); + hantro_reg_write(vpu, &vp8_dec_ref_adj[i], + lf->ref_frm_delta[i]); + } + } +} + +static void cfg_qp(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_quantization_header *q = &hdr->quant_header; + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + struct hantro_dev *vpu = ctx->dev; + unsigned int i; + + if (!(seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED)) { + hantro_reg_write(vpu, &vp8_dec_quant[0], q->y_ac_qi); + } else if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE) { + for (i = 0; i < 4; i++) { + u32 quant = clamp(q->y_ac_qi + seg->quant_update[i], + 0, 127); + + hantro_reg_write(vpu, &vp8_dec_quant[i], quant); + } + } else { + for (i = 0; i < 4; i++) + hantro_reg_write(vpu, &vp8_dec_quant[i], + seg->quant_update[i]); + } + + hantro_reg_write(vpu, &vp8_dec_quant_delta[0], q->y_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[1], q->y2_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[2], q->y2_ac_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[3], q->uv_dc_delta); + hantro_reg_write(vpu, &vp8_dec_quant_delta[4], q->uv_ac_delta); +} + +static void cfg_parts(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_src; + u32 first_part_offset = VP8_FRAME_IS_KEY_FRAME(hdr) ? 10 : 3; + u32 mb_size, mb_offset_bytes, mb_offset_bits, mb_start_bits; + u32 dct_size_part_size, dct_part_offset; + dma_addr_t src_dma; + u32 dct_part_total_len = 0; + u32 count = 0; + unsigned int i; + + vb2_src = hantro_get_src_buf(ctx); + src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); + + /* + * Calculate control partition mb data info + * @first_part_header_bits: bits offset of mb data from first + * part start pos + * @mb_offset_bits: bits offset of mb data from src_dma + * base addr + * @mb_offset_byte: bytes offset of mb data from src_dma + * base addr + * @mb_start_bits: bits offset of mb data from mb data + * 64bits alignment addr + */ + mb_offset_bits = first_part_offset * 8 + + hdr->first_part_header_bits + 8; + mb_offset_bytes = mb_offset_bits / 8; + mb_start_bits = mb_offset_bits - + (mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) * 8; + mb_size = hdr->first_part_size - + (mb_offset_bytes - first_part_offset) + + (mb_offset_bytes & DEC_8190_ALIGN_MASK); + + /* Macroblock data aligned base addr */ + vdpu_write_relaxed(vpu, (mb_offset_bytes & (~DEC_8190_ALIGN_MASK)) + + src_dma, VDPU_REG_VP8_ADDR_CTRL_PART); + hantro_reg_write(vpu, &vp8_dec_mb_start_bit, mb_start_bits); + hantro_reg_write(vpu, &vp8_dec_mb_aligned_data_len, mb_size); + + /* + * Calculate DCT partition info + * @dct_size_part_size: Containing sizes of DCT part, every DCT part + * has 3 bytes to store its size, except the last + * DCT part + * @dct_part_offset: bytes offset of DCT parts from src_dma base addr + * @dct_part_total_len: total size of all DCT parts + */ + dct_size_part_size = (hdr->num_dct_parts - 1) * 3; + dct_part_offset = first_part_offset + hdr->first_part_size; + for (i = 0; i < hdr->num_dct_parts; i++) + dct_part_total_len += hdr->dct_part_sizes[i]; + dct_part_total_len += dct_size_part_size; + dct_part_total_len += (dct_part_offset & DEC_8190_ALIGN_MASK); + + /* Number of DCT partitions */ + hantro_reg_write(vpu, &vp8_dec_num_dct_partitions, + hdr->num_dct_parts - 1); + + /* DCT partition length */ + hantro_reg_write(vpu, &vp8_dec_stream_len, dct_part_total_len); + + /* DCT partitions base address */ + for (i = 0; i < hdr->num_dct_parts; i++) { + u32 byte_offset = dct_part_offset + dct_size_part_size + count; + u32 base_addr = byte_offset + src_dma; + + hantro_reg_write(vpu, &vp8_dec_dct_base[i], + base_addr & (~DEC_8190_ALIGN_MASK)); + + hantro_reg_write(vpu, &vp8_dec_dct_start_bits[i], + (byte_offset & DEC_8190_ALIGN_MASK) * 8); + + count += hdr->dct_part_sizes[i]; + } +} + +/* + * prediction filter taps + * normal 6-tap filters + */ +static void cfg_tap(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct hantro_dev *vpu = ctx->dev; + int i, j; + + if ((hdr->version & 0x03) != 0) + return; /* Tap filter not used. */ + + for (i = 0; i < 8; i++) { + for (j = 0; j < 6; j++) { + if (vp8_dec_pred_bc_tap[i][j].base != 0) + hantro_reg_write(vpu, + &vp8_dec_pred_bc_tap[i][j], + vp8_dec_mc_filter[i][j]); + } + } +} + +static void cfg_ref(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; + struct vb2_queue *cap_q; + dma_addr_t ref; + + cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + vb2_dst = hantro_get_dst_buf(ctx); + + ref = hantro_get_ref(cap_q, hdr->last_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF0); + + ref = hantro_get_ref(cap_q, hdr->golden_frame_ts); + WARN_ON(!ref && hdr->golden_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + if (hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN) + ref |= VDPU_REG_VP8_GREF_SIGN_BIAS; + vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(2)); + + ref = hantro_get_ref(cap_q, hdr->alt_frame_ts); + WARN_ON(!ref && hdr->alt_frame_ts); + if (!ref) + ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + if (hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT) + ref |= VDPU_REG_VP8_AREF_SIGN_BIAS; + vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(3)); +} + +static void cfg_buffers(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp8_frame_header *hdr) +{ + const struct v4l2_vp8_segment_header *seg = &hdr->segment_header; + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; + dma_addr_t dst_dma; + u32 reg; + + vb2_dst = hantro_get_dst_buf(ctx); + + /* Set probability table buffer address */ + vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma, + VDPU_REG_ADDR_QTABLE); + + /* Set segment map address */ + reg = VDPU_REG_FWD_PIC1_SEGMENT_BASE(ctx->vp8_dec.segment_map.dma); + if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED) { + reg |= VDPU_REG_FWD_PIC1_SEGMENT_E; + if (seg->flags & V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP) + reg |= VDPU_REG_FWD_PIC1_SEGMENT_UPD_E; + } + vdpu_write_relaxed(vpu, reg, VDPU_REG_VP8_SEGMENT_VAL); + + /* set output frame buffer address */ + dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + vdpu_write_relaxed(vpu, dst_dma, VDPU_REG_ADDR_DST); +} + +void rk3399_vpu_vp8_dec_run(struct hantro_ctx *ctx) +{ + const struct v4l2_ctrl_vp8_frame_header *hdr; + struct hantro_dev *vpu = ctx->dev; + size_t height = ctx->dst_fmt.height; + size_t width = ctx->dst_fmt.width; + u32 mb_width, mb_height; + u32 reg; + + hantro_prepare_run(ctx); + + hdr = hantro_get_ctrl(ctx, V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER); + if (WARN_ON(!hdr)) + return; + + /* Reset segment_map buffer in keyframe */ + if (VP8_FRAME_IS_KEY_FRAME(hdr) && ctx->vp8_dec.segment_map.cpu) + memset(ctx->vp8_dec.segment_map.cpu, 0, + ctx->vp8_dec.segment_map.size); + + hantro_vp8_prob_update(ctx, hdr); + + /* + * Extensive testing shows that the hardware does not properly + * clear the internal state from previous a decoding run. This + * causes corruption in decoded frames for multi-instance use cases. + * A soft reset before programming the registers has been found + * to resolve those problems. + */ + ctx->codec_ops->reset(ctx); + + reg = VDPU_REG_CONFIG_DEC_TIMEOUT_E + | VDPU_REG_CONFIG_DEC_CLK_GATE_E; + if (!VP8_FRAME_IS_KEY_FRAME(hdr)) + reg |= VDPU_REG_DEC_CTRL0_PIC_INTER_E; + vdpu_write_relaxed(vpu, reg, VDPU_REG_EN_FLAGS); + + reg = VDPU_REG_CONFIG_DEC_STRENDIAN_E + | VDPU_REG_CONFIG_DEC_INSWAP32_E + | VDPU_REG_CONFIG_DEC_STRSWAP32_E + | VDPU_REG_CONFIG_DEC_OUTSWAP32_E + | VDPU_REG_CONFIG_DEC_IN_ENDIAN + | VDPU_REG_CONFIG_DEC_OUT_ENDIAN; + vdpu_write_relaxed(vpu, reg, VDPU_REG_DATA_ENDIAN); + + reg = VDPU_REG_CONFIG_DEC_MAX_BURST(16); + vdpu_write_relaxed(vpu, reg, VDPU_REG_AXI_CTRL); + + reg = VDPU_REG_DEC_CTRL0_DEC_MODE(10); + vdpu_write_relaxed(vpu, reg, VDPU_REG_DEC_FORMAT); + + if (!(hdr->flags & V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF)) + hantro_reg_write(vpu, &vp8_dec_skip_mode, 1); + if (hdr->lf_header.level == 0) + hantro_reg_write(vpu, &vp8_dec_filter_disable, 1); + + /* Frame dimensions */ + mb_width = VP8_MB_WIDTH(width); + mb_height = VP8_MB_HEIGHT(height); + + hantro_reg_write(vpu, &vp8_dec_mb_width, mb_width); + hantro_reg_write(vpu, &vp8_dec_mb_height, mb_height); + hantro_reg_write(vpu, &vp8_dec_mb_width_ext, mb_width >> 9); + hantro_reg_write(vpu, &vp8_dec_mb_height_ext, mb_height >> 8); + + /* Boolean decoder */ + hantro_reg_write(vpu, &vp8_dec_bool_range, hdr->coder_state.range); + hantro_reg_write(vpu, &vp8_dec_bool_value, hdr->coder_state.value); + + reg = vdpu_read(vpu, VDPU_REG_VP8_DCT_START_BIT); + if (hdr->version != 3) + reg |= VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT; + if (hdr->version & 0x3) + reg |= VDPU_REG_DEC_CTRL4_BILIN_MC_E; + vdpu_write_relaxed(vpu, reg, VDPU_REG_VP8_DCT_START_BIT); + + cfg_lf(ctx, hdr); + cfg_qp(ctx, hdr); + cfg_parts(ctx, hdr); + cfg_tap(ctx, hdr); + cfg_ref(ctx, hdr); + cfg_buffers(ctx, hdr); + + hantro_finish_run(ctx); + + hantro_reg_write(vpu, &vp8_dec_start_dec, 1); +} -- GitLab From 620428820d0d76de5b29314457a3b27c0634b4f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Jul 2019 12:25:52 -0400 Subject: [PATCH 0692/7155] media: staging: hantro: avoid future namespace collisions Rename: vp8_dec_mc_filter -> hantro_vp8_dec_mc_filter As other drivers may end implementing something with the same name. So, prepend driver's name here, in order to make symbol namespace cleaner. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_g1_vp8_dec.c | 5 +++-- drivers/staging/media/hantro/hantro_hw.h | 2 +- drivers/staging/media/hantro/hantro_vp8.c | 2 +- drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index 181e2f76d8cb..6d99c2be01cf 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -342,11 +342,12 @@ static void cfg_tap(struct hantro_ctx *ctx, return; /* Tap filter not used. */ for (i = 0; i < 8; i++) { - val = (vp8_dec_mc_filter[i][0] << 2) | vp8_dec_mc_filter[i][5]; + val = (hantro_vp8_dec_mc_filter[i][0] << 2) | + hantro_vp8_dec_mc_filter[i][5]; for (j = 0; j < 4; j++) hantro_reg_write(vpu, &vp8_dec_pred_bc_tap[i][j], - vp8_dec_mc_filter[i][j + 1]); + hantro_vp8_dec_mc_filter[i][j + 1]); switch (i) { case 2: diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index e86c84fbfe1a..2b8029674a75 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -95,7 +95,7 @@ extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3288_vpu_variant; -extern const u32 vp8_dec_mc_filter[8][6]; +extern const u32 hantro_vp8_dec_mc_filter[8][6]; void hantro_watchdog(struct work_struct *work); void hantro_run(struct hantro_ctx *ctx); diff --git a/drivers/staging/media/hantro/hantro_vp8.c b/drivers/staging/media/hantro/hantro_vp8.c index cd01661cac21..0e02d147b189 100644 --- a/drivers/staging/media/hantro/hantro_vp8.c +++ b/drivers/staging/media/hantro/hantro_vp8.c @@ -35,7 +35,7 @@ struct vp8_prob_tbl_packed { * filter taps taken to 7-bit precision, * reference RFC6386#Page-16, filters[8][6] */ -const u32 vp8_dec_mc_filter[8][6] = { +const u32 hantro_vp8_dec_mc_filter[8][6] = { { 0, 0, 128, 0, 0, 0 }, { 0, -6, 123, 12, -1, 0 }, { 2, -11, 108, 36, -8, 1 }, diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c index c5e9f8befe9c..f17e32620b08 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_vp8_dec.c @@ -439,7 +439,7 @@ static void cfg_tap(struct hantro_ctx *ctx, if (vp8_dec_pred_bc_tap[i][j].base != 0) hantro_reg_write(vpu, &vp8_dec_pred_bc_tap[i][j], - vp8_dec_mc_filter[i][j]); + hantro_vp8_dec_mc_filter[i][j]); } } } -- GitLab From a8f910ec66583bfb61558c3f333195b3960d832d Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 15 Jul 2019 17:06:42 -0400 Subject: [PATCH 0693/7155] media: v4l2-core: Cleanup Makefile Use the videodev-$(CONFIG_FOO) syntax to simplify the Makefile. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 9ee57e1efefe..4d42418e603e 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -8,15 +8,11 @@ tuner-objs := tuner-core.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \ v4l2-async.o -ifeq ($(CONFIG_COMPAT),y) - videodev-objs += v4l2-compat-ioctl32.o -endif -obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o -ifeq ($(CONFIG_TRACEPOINTS),y) - videodev-objs += v4l2-trace.o -endif +videodev-$(CONFIG_COMPAT) += v4l2-compat-ioctl32.o +videodev-$(CONFIG_TRACEPOINTS) += v4l2-trace.o videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o +obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o obj-$(CONFIG_VIDEO_V4L2) += videodev.o obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o obj-$(CONFIG_VIDEO_V4L2) += v4l2-dv-timings.o -- GitLab From 5af9e972ac72b1c9f13cd35ccfb4687741c53f3e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 25 Jul 2019 15:37:43 +0200 Subject: [PATCH 0694/7155] ASoC: SOF: Makefile - fix the top-level kernel module names (add snd- prefix) Use the proper module name. The objs assignments are already there. Signed-off-by: Jaroslav Kysela Cc: Liam Girdwood Cc: Pierre-Louis Bossart Cc: Takashi Iwai Cc: Mark Brown 0 Link: https://lore.kernel.org/r/20190725133743.22145-1-perex@perex.cz Signed-off-by: Mark Brown --- sound/soc/sof/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 8f14c9d2950b..585fb6917489 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -11,8 +11,8 @@ obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o -obj-$(CONFIG_SND_SOC_SOF_ACPI) += sof-acpi-dev.o -obj-$(CONFIG_SND_SOC_SOF_PCI) += sof-pci-dev.o +obj-$(CONFIG_SND_SOC_SOF_ACPI) += snd-sof-acpi.o +obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ -- GitLab From 01ec57a4371e573bfcfa898307af098a8c6f9dcf Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 25 Jul 2019 17:39:29 +0100 Subject: [PATCH 0695/7155] ASoC: wm_adsp: Allow bus error handler to be called directly There is no need for end drivers to add helper functions to allow the bus error handler to be called, simply update the prototype so it can be called directly. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190725163931.24964-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l90.c | 9 +-------- sound/soc/codecs/wm_adsp.c | 6 ++++-- sound/soc/codecs/wm_adsp.h | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index c4ecb0e6911a..67cac60a859d 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2402,13 +2402,6 @@ static irqreturn_t cs47l90_adsp2_irq(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t cs47l90_dsp_bus_error(int irq, void *data) -{ - struct wm_adsp *dsp = (struct wm_adsp *)data; - - return wm_adsp2_bus_error(dsp); -} - static int cs47l90_component_probe(struct snd_soc_component *component) { struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); @@ -2558,7 +2551,7 @@ static int cs47l90_probe(struct platform_device *pdev) if (ret == 0) { ret = madera_init_bus_error_irq(&cs47l90->core, i, - cs47l90_dsp_bus_error); + wm_adsp2_bus_error); if (ret != 0) wm_adsp2_remove(&cs47l90->core.adsp[i]); } diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f5fbadc5e7e2..ae28d9907c30 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -4242,8 +4242,9 @@ static void wm_adsp_fatal_error(struct wm_adsp *dsp) } } -irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) +irqreturn_t wm_adsp2_bus_error(int irq, void *data) { + struct wm_adsp *dsp = (struct wm_adsp *)data; unsigned int val; struct regmap *regmap = dsp->regmap; int ret = 0; @@ -4307,8 +4308,9 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) } EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); -irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp) +irqreturn_t wm_halo_bus_error(int irq, void *data) { + struct wm_adsp *dsp = (struct wm_adsp *)data; struct regmap *regmap = dsp->regmap; unsigned int fault[6]; struct reg_sequence clear[] = { diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 3b03d1eb986f..aa634ef6c9f5 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -171,8 +171,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, int wm_adsp_early_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -irqreturn_t wm_adsp2_bus_error(struct wm_adsp *adsp); -irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp); +irqreturn_t wm_adsp2_bus_error(int irq, void *data); +irqreturn_t wm_halo_bus_error(int irq, void *data); irqreturn_t wm_halo_wdt_expire(int irq, void *data); int wm_adsp_event(struct snd_soc_dapm_widget *w, -- GitLab From 9cba2d6a144741ad99bfa379337bb984a8ed94bd Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 25 Jul 2019 17:39:30 +0100 Subject: [PATCH 0696/7155] ASoC: cs47l15: Add codec driver for Cirrus Logic CS47L15 Adds the codec driver for the CS47L15 SmartCodec. This is a multi-functional codec based on the Cirrus Logic Madera platform. Signed-off-by: Richard Fitzgerald Signed-off-by: Jaswinder Jassal Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190725163931.24964-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs47l15.c | 1490 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/madera.c | 4 + 4 files changed, 1502 insertions(+) create mode 100644 sound/soc/codecs/cs47l15.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f89a5346299..dc23476d2eea 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS43130 if I2C select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI select SND_SOC_CS4349 if I2C + select SND_SOC_CS47L15 if MFD_CS47L15 select SND_SOC_CS47L24 if MFD_CS47L24 select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS47L85 if MFD_CS47L85 @@ -581,6 +582,9 @@ config SND_SOC_CS4349 tristate "Cirrus Logic CS4349 CODEC" depends on I2C +config SND_SOC_CS47L15 + tristate + config SND_SOC_CS47L24 tristate @@ -722,9 +726,11 @@ config SND_SOC_LOCHNAGAR_SC config SND_SOC_MADERA tristate + default y if SND_SOC_CS47L15=y default y if SND_SOC_CS47L35=y default y if SND_SOC_CS47L85=y default y if SND_SOC_CS47L90=y + default m if SND_SOC_CS47L15=m default m if SND_SOC_CS47L35=m default m if SND_SOC_CS47L85=m default m if SND_SOC_CS47L90=m diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5b4bb8cf4325..174346b1418a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,6 +64,7 @@ snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cs43130-objs := cs43130.o snd-soc-cs4341-objs := cs4341.o snd-soc-cs4349-objs := cs4349.o +snd-soc-cs47l15-objs := cs47l15.o snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs47l85-objs := cs47l85.o @@ -346,6 +347,7 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o +obj-$(CONFIG_SND_SOC_CS47L15) += snd-soc-cs47l15.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c new file mode 100644 index 000000000000..ece1276f38eb --- /dev/null +++ b/sound/soc/codecs/cs47l15.c @@ -0,0 +1,1490 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// ALSA SoC Audio driver for CS47L15 codec +// +// Copyright (C) 2016-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "madera.h" +#include "wm_adsp.h" + +#define CS47L15_NUM_ADSP 1 +#define CS47L15_MONO_OUTPUTS 1 + +/* Mid-mode registers */ +#define CS47L15_ADC_INT_BIAS_MASK 0x3800 +#define CS47L15_ADC_INT_BIAS_SHIFT 11 +#define CS47L15_PGA_BIAS_SEL_MASK 0x03 +#define CS47L15_PGA_BIAS_SEL_SHIFT 0 + +#define DRV_NAME "cs47l15-codec" + +struct cs47l15 { + struct madera_priv core; + struct madera_fll fll[2]; + + bool in1_lp_mode; +}; + +static const struct wm_adsp_region cs47l15_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const char * const cs47l15_outdemux_texts[] = { + "HPOUT", + "EPOUT", +}; + +static SOC_ENUM_SINGLE_DECL(cs47l15_outdemux_enum, SND_SOC_NOPM, 0, + cs47l15_outdemux_texts); + +static const struct snd_kcontrol_new cs47l15_outdemux = + SOC_DAPM_ENUM_EXT("HPOUT1 Demux", cs47l15_outdemux_enum, + madera_out1_demux_get, madera_out1_demux_put); + +static int cs47l15_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l15->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); + return ret; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l15->core, w->shift, freq); + if (ret) + return ret; + break; + default: + break; + } + + return wm_adsp_early_event(w, kcontrol, event); +} + +#define CS47L15_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG SPKOUTL Switch", base, 6, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) + +static int cs47l15_in1_adc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !!cs47l15->in1_lp_mode; + + return 0; +} + +static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + + switch (ucontrol->value.integer.value[0]) { + case 0: + /* Set IN1 to normal mode */ + snd_soc_component_update_bits(component, MADERA_DMIC1L_CONTROL, + MADERA_IN1_OSR_MASK, + 5 << MADERA_IN1_OSR_SHIFT); + snd_soc_component_update_bits(component, CS47L15_ADC_INT_BIAS, + CS47L15_ADC_INT_BIAS_MASK, + 4 << CS47L15_ADC_INT_BIAS_SHIFT); + snd_soc_component_update_bits(component, CS47L15_PGA_BIAS_SEL, + CS47L15_PGA_BIAS_SEL_MASK, 0); + cs47l15->in1_lp_mode = false; + break; + default: + /* Set IN1 to LP mode */ + snd_soc_component_update_bits(component, MADERA_DMIC1L_CONTROL, + MADERA_IN1_OSR_MASK, + 4 << MADERA_IN1_OSR_SHIFT); + snd_soc_component_update_bits(component, CS47L15_ADC_INT_BIAS, + CS47L15_ADC_INT_BIAS_MASK, + 1 << CS47L15_ADC_INT_BIAS_SHIFT); + snd_soc_component_update_bits(component, CS47L15_PGA_BIAS_SEL, + CS47L15_PGA_BIAS_SEL_MASK, + 3 << CS47L15_PGA_BIAS_SEL_SHIFT); + cs47l15->in1_lp_mode = true; + break; + } + + return 0; +} + +static const struct snd_kcontrol_new cs47l15_snd_controls[] = { +SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, + MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, + MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), + +SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, MADERA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, MADERA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, MADERA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, MADERA_IN2R_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), + +SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), +SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), + +MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), + +MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), +SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), +SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), +SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), +SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, + MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, + MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), + +MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), + +MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), +MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), +MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), +MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), + +SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), + +MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), +MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), +MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), +MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), + +WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), + +MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), + +MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKOUTL", MADERA_OUT4LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, + MADERA_HP1_SC_ENA_SHIFT, 1, 0), + +SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_SINGLE("Speaker Digital Switch", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_OUT4L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("Speaker Digital Volume", MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_OUT4L_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, + MADERA_SPK1R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), +SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), +SOC_ENUM("Noise Gate Hold", madera_ng_hold), + +SOC_SINGLE_BOOL_EXT("IN1 LP Mode Switch", 0, + cs47l15_in1_adc_get, cs47l15_in1_adc_put), + +CS47L15_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), +CS47L15_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), +CS47L15_NG_SRC("SPKOUTL", MADERA_NOISE_GATE_SELECT_4L), +CS47L15_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), +CS47L15_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), + +MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), + +MADERA_GAINMUX_CONTROLS("SPDIF1TX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), +MADERA_GAINMUX_CONTROLS("SPDIF1TX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +}; + +MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKOUTL, MADERA_OUT4LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT3, MADERA_ISRC1INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT4, MADERA_ISRC1INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC3, MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC4, MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT3, MADERA_ISRC2INT3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT4, MADERA_ISRC2INT4MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC3, MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC4, MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE); + +static const char * const cs47l15_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "SPKOUTL", "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int cs47l15_aec_loopback_values[] = { + 0, 1, 6, 8, 9, +}; + +static const struct soc_enum cs47l15_aec1_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l15_aec_loopback_texts), + cs47l15_aec_loopback_texts, + cs47l15_aec_loopback_values); + +static const struct soc_enum cs47l15_aec2_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l15_aec_loopback_texts), + cs47l15_aec_loopback_texts, + cs47l15_aec_loopback_values); + +static const struct snd_kcontrol_new cs47l15_aec_loopback_mux[] = { + SOC_DAPM_ENUM("AEC1 Loopback", cs47l15_aec1_loopback), + SOC_DAPM_ENUM("AEC2 Loopback", cs47l15_aec2_loopback), +}; + +static const struct snd_soc_dapm_widget cs47l15_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, + 0, madera_sysclk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, + MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, + MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), +SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1C", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1C_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_FX, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_OUT, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SPD, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_PWM, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1ALN"), +SND_SOC_DAPM_INPUT("IN1ALP"), +SND_SOC_DAPM_INPUT("IN1BLN"), +SND_SOC_DAPM_INPUT("IN1BLP"), +SND_SOC_DAPM_INPUT("IN1ARN"), +SND_SOC_DAPM_INPUT("IN1ARP"), +SND_SOC_DAPM_INPUT("IN1BRN"), +SND_SOC_DAPM_INPUT("IN1BRP"), +SND_SOC_DAPM_INPUT("IN2N"), +SND_SOC_DAPM_INPUT("IN2P"), +SND_SOC_DAPM_INPUT("SPKRXDAT"), + +SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), +SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), + +SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), +SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), + +SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), +SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), +SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), + +SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), + +SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux), + +SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, + MADERA_OUT4L_ENA_SHIFT, 0, NULL, 0, madera_spk_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), + +/* + * mux_in widgets : arranged in the order of sources + * specified in MADERA_MIXER_INPUT_ROUTES + */ + +SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, + MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, + MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, + &cs47l15_aec_loopback_mux[0]), +SND_SOC_DAPM_MUX("AEC2 Loopback", MADERA_DAC_AEC_CONTROL_2, + MADERA_AEC2_LOOPBACK_ENA_SHIFT, 0, + &cs47l15_aec_loopback_mux[1]), + +SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT3", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT4", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT3", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT4", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT4_ENA_SHIFT, 0, NULL, 0), + +WM_ADSP2("DSP1", 0, cs47l15_adsp_power_ev), + +/* end of ordered widget list */ + +MADERA_MIXER_WIDGETS(EQ1, "EQ1"), +MADERA_MIXER_WIDGETS(EQ2, "EQ2"), +MADERA_MIXER_WIDGETS(EQ3, "EQ3"), +MADERA_MIXER_WIDGETS(EQ4, "EQ4"), + +MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), +MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), +MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), +MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[0]), +SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[1]), + +MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), +MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), +MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), +MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +MADERA_MIXER_WIDGETS(PWM1, "PWM1"), +MADERA_MIXER_WIDGETS(PWM2, "PWM2"), + +MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +MADERA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), +MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), + +MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), + +MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), +MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), +MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), + +MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), + +MADERA_MUX_WIDGETS(SPD1TX1, "SPDIF1TX1"), +MADERA_MUX_WIDGETS(SPD1TX2, "SPDIF1TX2"), + +MADERA_DSP_WIDGETS(DSP1, "DSP1"), + +SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, + &madera_dsp_trigger_output_mux[0]), + +MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), +MADERA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), +MADERA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), + +MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), +MADERA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), +MADERA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), + +MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), +MADERA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), +MADERA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), + +MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), +MADERA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), +MADERA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), + +SND_SOC_DAPM_OUTPUT("HPOUTL"), +SND_SOC_DAPM_OUTPUT("HPOUTR"), +SND_SOC_DAPM_OUTPUT("EPOUTP"), +SND_SOC_DAPM_OUTPUT("EPOUTN"), +SND_SOC_DAPM_OUTPUT("SPKOUTN"), +SND_SOC_DAPM_OUTPUT("SPKOUTP"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPDIF1"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define MADERA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC1", "AEC1 Loopback" }, \ + { name, "AEC2", "AEC2 Loopback" }, \ + { name, "IN1L", "IN1L" }, \ + { name, "IN1R", "IN1R" }, \ + { name, "IN2L", "IN2L" }, \ + { name, "IN2R", "IN2R" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF2RX3", "AIF2RX3" }, \ + { name, "AIF2RX4", "AIF2RX4" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC1INT3", "ISRC1INT3" }, \ + { name, "ISRC1INT4", "ISRC1INT4" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2DEC3", "ISRC2DEC3" }, \ + { name, "ISRC2DEC4", "ISRC2DEC4" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" }, \ + { name, "ISRC2INT3", "ISRC2INT3" }, \ + { name, "ISRC2INT4", "ISRC2INT4" }, \ + { name, "DSP1.1", "DSP1" }, \ + { name, "DSP1.2", "DSP1" }, \ + { name, "DSP1.3", "DSP1" }, \ + { name, "DSP1.4", "DSP1" }, \ + { name, "DSP1.5", "DSP1" }, \ + { name, "DSP1.6", "DSP1" } + +static const struct snd_soc_dapm_route cs47l15_dapm_routes[] = { + /* Internal clock domains */ + { "EQ1", NULL, "FXCLK" }, + { "EQ2", NULL, "FXCLK" }, + { "EQ3", NULL, "FXCLK" }, + { "EQ4", NULL, "FXCLK" }, + { "DRC1L", NULL, "FXCLK" }, + { "DRC1R", NULL, "FXCLK" }, + { "DRC2L", NULL, "FXCLK" }, + { "DRC2R", NULL, "FXCLK" }, + { "LHPF1", NULL, "FXCLK" }, + { "LHPF2", NULL, "FXCLK" }, + { "LHPF3", NULL, "FXCLK" }, + { "LHPF4", NULL, "FXCLK" }, + { "PWM1 Mixer", NULL, "PWMCLK" }, + { "PWM2 Mixer", NULL, "PWMCLK" }, + { "OUT1L", NULL, "OUTCLK" }, + { "OUT1R", NULL, "OUTCLK" }, + { "OUT4L", NULL, "OUTCLK" }, + { "OUT5L", NULL, "OUTCLK" }, + { "OUT5R", NULL, "OUTCLK" }, + { "AIF1TX1", NULL, "AIF1TXCLK" }, + { "AIF1TX2", NULL, "AIF1TXCLK" }, + { "AIF1TX3", NULL, "AIF1TXCLK" }, + { "AIF1TX4", NULL, "AIF1TXCLK" }, + { "AIF1TX5", NULL, "AIF1TXCLK" }, + { "AIF1TX6", NULL, "AIF1TXCLK" }, + { "AIF2TX1", NULL, "AIF2TXCLK" }, + { "AIF2TX2", NULL, "AIF2TXCLK" }, + { "AIF2TX3", NULL, "AIF2TXCLK" }, + { "AIF2TX4", NULL, "AIF2TXCLK" }, + { "AIF3TX1", NULL, "AIF3TXCLK" }, + { "AIF3TX2", NULL, "AIF3TXCLK" }, + { "SPD1TX1", NULL, "SPDCLK" }, + { "SPD1TX2", NULL, "SPDCLK" }, + { "DSP1", NULL, "DSP1CLK" }, + { "ISRC1DEC1", NULL, "ISRC1CLK" }, + { "ISRC1DEC2", NULL, "ISRC1CLK" }, + { "ISRC1DEC3", NULL, "ISRC1CLK" }, + { "ISRC1DEC4", NULL, "ISRC1CLK" }, + { "ISRC1INT1", NULL, "ISRC1CLK" }, + { "ISRC1INT2", NULL, "ISRC1CLK" }, + { "ISRC1INT3", NULL, "ISRC1CLK" }, + { "ISRC1INT4", NULL, "ISRC1CLK" }, + { "ISRC2DEC1", NULL, "ISRC2CLK" }, + { "ISRC2DEC2", NULL, "ISRC2CLK" }, + { "ISRC2DEC3", NULL, "ISRC2CLK" }, + { "ISRC2DEC4", NULL, "ISRC2CLK" }, + { "ISRC2INT1", NULL, "ISRC2CLK" }, + { "ISRC2INT2", NULL, "ISRC2CLK" }, + { "ISRC2INT3", NULL, "ISRC2CLK" }, + { "ISRC2INT4", NULL, "ISRC2CLK" }, + + { "OUT1L", NULL, "CPVDD1" }, + { "OUT1R", NULL, "CPVDD1" }, + { "OUT4L", NULL, "SPKVDD" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT4L", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + + { "MICBIAS1A", NULL, "MICBIAS1" }, + { "MICBIAS1B", NULL, "MICBIAS1" }, + { "MICBIAS1C", NULL, "MICBIAS1" }, + + { "Noise Generator", NULL, "SYSCLK" }, + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + { "AIF2 Capture", NULL, "AIF2TX3" }, + { "AIF2 Capture", NULL, "AIF2TX4" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + { "AIF2RX3", NULL, "AIF2 Playback" }, + { "AIF2RX4", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + + { "Audio Trace DSP", NULL, "DSP1" }, + + { "IN1L Analog Mux", "A", "IN1ALN" }, + { "IN1L Analog Mux", "A", "IN1ALP" }, + { "IN1L Analog Mux", "B", "IN1BLN" }, + { "IN1L Analog Mux", "B", "IN1BLP" }, + { "IN1R Analog Mux", "A", "IN1ARN" }, + { "IN1R Analog Mux", "A", "IN1ARP" }, + { "IN1R Analog Mux", "B", "IN1BRN" }, + { "IN1R Analog Mux", "B", "IN1BRP" }, + + { "IN1L Mode", "Analog", "IN1L Analog Mux" }, + { "IN1R Mode", "Analog", "IN1R Analog Mux" }, + + { "IN1L Mode", "Digital", "IN1ALN" }, + { "IN1L Mode", "Digital", "IN1ALP" }, + { "IN1R Mode", "Digital", "IN1ALN" }, + { "IN1R Mode", "Digital", "IN1ALP" }, + + { "IN1L", NULL, "IN1L Mode" }, + { "IN1R", NULL, "IN1R Mode" }, + + { "IN2L Mode", "Analog", "IN2N" }, + { "IN2L Mode", "Analog", "IN2P" }, + + { "IN2L Mode", "Digital", "SPKRXDAT" }, + { "IN2R Mode", "Digital", "SPKRXDAT" }, + + { "IN2L", NULL, "IN2L Mode" }, + { "IN2R", NULL, "IN2R Mode" }, + + MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + MADERA_MIXER_ROUTES("OUT4L", "SPKOUTL"), + MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + + MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + + MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), + MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), + + MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + + MADERA_MUX_ROUTES("SPD1TX1", "SPDIF1TX1"), + MADERA_MUX_ROUTES("SPD1TX2", "SPDIF1TX2"), + + MADERA_MIXER_ROUTES("EQ1", "EQ1"), + MADERA_MIXER_ROUTES("EQ2", "EQ2"), + MADERA_MIXER_ROUTES("EQ3", "EQ3"), + MADERA_MIXER_ROUTES("EQ4", "EQ4"), + + MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), + MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), + MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), + MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), + + MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), + MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), + MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), + MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), + + MADERA_DSP_ROUTES("DSP1"), + + { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, + + { "DSP1 Trigger Output", "Switch", "DSP1" }, + + MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + MADERA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), + MADERA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), + + MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + MADERA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), + MADERA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), + + MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + MADERA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), + MADERA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), + + MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + MADERA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), + MADERA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), + + { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, + { "AEC2 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC2 Loopback", "HPOUT1R", "OUT1R" }, + { "HPOUT1 Demux", NULL, "OUT1L" }, + { "HPOUT1 Demux", NULL, "OUT1R" }, + { "HPOUTL", "HPOUT", "HPOUT1 Demux" }, + { "HPOUTR", "HPOUT", "HPOUT1 Demux" }, + { "EPOUTP", "EPOUT", "HPOUT1 Demux" }, + { "EPOUTN", "EPOUT", "HPOUT1 Demux" }, + + { "AEC1 Loopback", "SPKOUTL", "OUT4L" }, + { "AEC2 Loopback", "SPKOUTL", "OUT4L" }, + { "SPKOUTN", NULL, "OUT4L" }, + { "SPKOUTP", NULL, "OUT4L" }, + + { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, + { "AEC2 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC2 Loopback", "SPKDAT1R", "OUT5R" }, + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + { "SPDIF1", NULL, "SPD1" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, + { "DRC1 Activity Output", "Switch", "DRC1L" }, + { "DRC1 Activity Output", "Switch", "DRC1R" }, + { "DRC2 Activity Output", "Switch", "DRC2L" }, + { "DRC2 Activity Output", "Switch", "DRC2R" }, +}; + +static int cs47l15_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + + switch (fll_id) { + case MADERA_FLL1_REFCLK: + return madera_set_fll_refclk(&cs47l15->fll[0], source, fref, + fout); + case MADERA_FLLAO_REFCLK: + return madera_set_fll_ao_refclk(&cs47l15->fll[1], source, fref, + fout); + case MADERA_FLL1_SYNCCLK: + return madera_set_fll_syncclk(&cs47l15->fll[0], source, fref, + fout); + default: + return -EINVAL; + } +} + +static struct snd_soc_dai_driver cs47l15_dai[] = { + { + .name = "cs47l15-aif1", + .id = 1, + .base = MADERA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l15-aif2", + .id = 2, + .base = MADERA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l15-aif3", + .id = 3, + .base = MADERA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l15-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "cs47l15-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, +}; + +static int cs47l15_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l15->core; + struct madera *madera = priv->madera; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l15-dsp-trace") == 0) { + n_adsp = 0; + } else { + dev_err(madera->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); +} + +static irqreturn_t cs47l15_adsp2_irq(int irq, void *data) +{ + struct cs47l15 *cs47l15 = data; + struct madera_priv *priv = &cs47l15->core; + struct madera *madera = priv->madera; + int ret; + + ret = wm_adsp_compr_handle_irq(&priv->adsp[0]); + if (ret == -ENODEV) { + dev_err(madera->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static int cs47l15_component_probe(struct snd_soc_component *component) +{ + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l15->core.madera; + int ret; + + snd_soc_component_init_regmap(component, madera->regmap); + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = snd_soc_component_get_dapm(component); + mutex_unlock(&madera->dapm_ptr_lock); + + ret = madera_init_inputs(component); + if (ret) + return ret; + + ret = madera_init_outputs(component, CS47L15_MONO_OUTPUTS); + if (ret) + return ret; + + snd_soc_component_disable_pin(component, "HAPTICS"); + + ret = snd_soc_add_component_controls(component, + madera_adsp_rate_controls, + CS47L15_NUM_ADSP); + if (ret) + return ret; + + wm_adsp2_component_probe(&cs47l15->core.adsp[0], component); + + return 0; +} + +static void cs47l15_component_remove(struct snd_soc_component *component) +{ + struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l15->core.madera; + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = NULL; + mutex_unlock(&madera->dapm_ptr_lock); + + wm_adsp2_component_remove(&cs47l15->core.adsp[0], component); +} + +#define CS47L15_DIG_VU 0x0200 + +static unsigned int cs47l15_digital_vu[] = { + MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, + MADERA_DAC_DIGITAL_VOLUME_4L, + MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, +}; + +static const struct snd_compr_ops cs47l15_compr_ops = { + .open = &cs47l15_open, + .free = &wm_adsp_compr_free, + .set_params = &wm_adsp_compr_set_params, + .get_caps = &wm_adsp_compr_get_caps, + .trigger = &wm_adsp_compr_trigger, + .pointer = &wm_adsp_compr_pointer, + .copy = &wm_adsp_compr_copy, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs47l15 = { + .probe = &cs47l15_component_probe, + .remove = &cs47l15_component_remove, + .set_sysclk = &madera_set_sysclk, + .set_pll = &cs47l15_set_fll, + .name = DRV_NAME, + .compr_ops = &cs47l15_compr_ops, + .controls = cs47l15_snd_controls, + .num_controls = ARRAY_SIZE(cs47l15_snd_controls), + .dapm_widgets = cs47l15_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l15_dapm_widgets), + .dapm_routes = cs47l15_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l15_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int cs47l15_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct cs47l15 *cs47l15; + int i, ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs47l15_dai) > MADERA_MAX_DAI); + + /* quick exit if Madera irqchip driver hasn't completed probe */ + if (!madera->irq_dev) { + dev_dbg(&pdev->dev, "irqchip driver not ready\n"); + return -EPROBE_DEFER; + } + + cs47l15 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l15), + GFP_KERNEL); + if (!cs47l15) + return -ENOMEM; + + platform_set_drvdata(pdev, cs47l15); + + cs47l15->core.madera = madera; + cs47l15->core.dev = &pdev->dev; + cs47l15->core.num_inputs = 4; + + ret = madera_core_init(&cs47l15->core); + if (ret) + return ret; + + ret = madera_init_overheat(&cs47l15->core); + if (ret) + goto error_core; + + ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l15_adsp2_irq, + cs47l15); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); + goto error_overheat; + } + + ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); + if (ret) + dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); + + cs47l15->core.adsp[0].part = "cs47l15"; + cs47l15->core.adsp[0].num = 1; + cs47l15->core.adsp[0].type = WMFW_ADSP2; + cs47l15->core.adsp[0].rev = 2; + cs47l15->core.adsp[0].dev = madera->dev; + cs47l15->core.adsp[0].regmap = madera->regmap_32bit; + + cs47l15->core.adsp[0].base = MADERA_DSP1_CONFIG_1; + cs47l15->core.adsp[0].mem = cs47l15_dsp1_regions; + cs47l15->core.adsp[0].num_mems = ARRAY_SIZE(cs47l15_dsp1_regions); + + cs47l15->core.adsp[0].lock_regions = + WM_ADSP2_REGION_1 | WM_ADSP2_REGION_2 | WM_ADSP2_REGION_3; + + ret = wm_adsp2_init(&cs47l15->core.adsp[0]); + if (ret != 0) + goto error_dsp_irq; + + ret = madera_init_bus_error_irq(&cs47l15->core, 0, wm_adsp2_bus_error); + if (ret) + goto error_adsp; + + madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, + &cs47l15->fll[0]); + madera_init_fll(madera, 4, MADERA_FLLAO_CONTROL_1 - 1, + &cs47l15->fll[1]); + + for (i = 0; i < ARRAY_SIZE(cs47l15_dai); i++) + madera_init_dai(&cs47l15->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(cs47l15_digital_vu); i++) + regmap_update_bits(madera->regmap, cs47l15_digital_vu[i], + CS47L15_DIG_VU, CS47L15_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_cs47l15, + cs47l15_dai, + ARRAY_SIZE(cs47l15_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + goto error_pm_runtime; + } + + return ret; + +error_pm_runtime: + pm_runtime_disable(&pdev->dev); + madera_free_bus_error_irq(&cs47l15->core, 0); +error_adsp: + wm_adsp2_remove(&cs47l15->core.adsp[0]); +error_dsp_irq: + madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l15); +error_overheat: + madera_free_overheat(&cs47l15->core); +error_core: + madera_core_free(&cs47l15->core); + + return ret; +} + +static int cs47l15_remove(struct platform_device *pdev) +{ + struct cs47l15 *cs47l15 = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + + madera_free_bus_error_irq(&cs47l15->core, 0); + + wm_adsp2_remove(&cs47l15->core.adsp[0]); + + madera_set_irq_wake(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l15); + madera_free_overheat(&cs47l15->core); + madera_core_free(&cs47l15->core); + + return 0; +} + +static struct platform_driver cs47l15_codec_driver = { + .driver = { + .name = "cs47l15-codec", + }, + .probe = &cs47l15_probe, + .remove = &cs47l15_remove, +}; + +module_platform_driver(cs47l15_codec_driver); + +MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); +MODULE_DESCRIPTION("ASoC CS47L15 driver"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Jaswinder Jassal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:cs47l15-codec"); diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 5f1e32a5a855..1c00e2a115bc 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -1041,6 +1041,10 @@ static void madera_configure_input_mode(struct madera *madera) int max_analogue_inputs, max_dmic_sup, i; switch (madera->type) { + case CS47L15: + max_analogue_inputs = 1; + max_dmic_sup = 2; + break; case CS47L35: max_analogue_inputs = 2; max_dmic_sup = 2; -- GitLab From 6535e831b4c867467d838f2c7866b4dce1d74679 Mon Sep 17 00:00:00 2001 From: Stuart Henderson Date: Thu, 25 Jul 2019 17:39:31 +0100 Subject: [PATCH 0697/7155] ASoC: cs47l92: Add codec driver for Cirrus Logic CS47L92 Adds the codec driver for the CS47L92 SmartCodec. This is a multi-functional codec based on the Cirrus Logic Madera platform. Signed-off-by: Stuart Henderson Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190725163931.24964-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/cs47l92.c | 2039 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/madera.c | 430 +++++++- sound/soc/codecs/madera.h | 10 + 5 files changed, 2478 insertions(+), 9 deletions(-) create mode 100644 sound/soc/codecs/cs47l92.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index dc23476d2eea..da4c1ae89742 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS47L35 if MFD_CS47L35 select SND_SOC_CS47L85 if MFD_CS47L85 select SND_SOC_CS47L90 if MFD_CS47L90 + select SND_SOC_CS47L92 if MFD_CS47L92 select SND_SOC_CS53L30 if I2C select SND_SOC_CX20442 if TTY select SND_SOC_CX2072X if I2C @@ -597,6 +598,9 @@ config SND_SOC_CS47L85 config SND_SOC_CS47L90 tristate +config SND_SOC_CS47L92 + tristate + # Cirrus Logic Quad-Channel ADC config SND_SOC_CS53L30 tristate "Cirrus Logic CS53L30 CODEC" @@ -730,10 +734,12 @@ config SND_SOC_MADERA default y if SND_SOC_CS47L35=y default y if SND_SOC_CS47L85=y default y if SND_SOC_CS47L90=y + default y if SND_SOC_CS47L92=y default m if SND_SOC_CS47L15=m default m if SND_SOC_CS47L35=m default m if SND_SOC_CS47L85=m default m if SND_SOC_CS47L90=m + default m if SND_SOC_CS47L92=m config SND_SOC_MAX98088 tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 174346b1418a..9230016b0f9f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -69,6 +69,7 @@ snd-soc-cs47l24-objs := cs47l24.o snd-soc-cs47l35-objs := cs47l35.o snd-soc-cs47l85-objs := cs47l85.o snd-soc-cs47l90-objs := cs47l90.o +snd-soc-cs47l92-objs := cs47l92.o snd-soc-cs53l30-objs := cs53l30.o snd-soc-cx20442-objs := cx20442.o snd-soc-cx2072x-objs := cx2072x.o @@ -351,6 +352,7 @@ obj-$(CONFIG_SND_SOC_CS47L15) += snd-soc-cs47l15.o obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o +obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c new file mode 100644 index 000000000000..d50f75f3b3e4 --- /dev/null +++ b/sound/soc/codecs/cs47l92.c @@ -0,0 +1,2039 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// ALSA SoC Audio driver for CS47L92 codec +// +// Copyright (C) 2016-2019 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "madera.h" +#include "wm_adsp.h" + +#define CS47L92_NUM_ADSP 1 +#define CS47L92_MONO_OUTPUTS 3 + +#define DRV_NAME "cs47l92-codec" + +struct cs47l92 { + struct madera_priv core; + struct madera_fll fll[2]; +}; + +static const struct wm_adsp_region cs47l92_dsp1_regions[] = { + { .type = WMFW_ADSP2_PM, .base = 0x080000 }, + { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, + { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, + { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, +}; + +static const char * const cs47l92_outdemux_texts[] = { + "HPOUT3", + "HPOUT4", +}; + +static int cs47l92_put_demux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int ep_sel, mux, change, cur; + bool out_mono; + int ret; + + if (ucontrol->value.enumerated.item[0] > e->items - 1) + return -EINVAL; + + mux = ucontrol->value.enumerated.item[0]; + + snd_soc_dapm_mutex_lock(dapm); + + ep_sel = mux << e->shift_l; + + change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1, + MADERA_EP_SEL_MASK, + ep_sel); + if (!change) + goto end; + + ret = regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &cur); + if (ret != 0) + dev_warn(madera->dev, "Failed to read outputs: %d\n", ret); + + /* EP_SEL should not be modified while HPOUT3 or 4 is enabled */ + ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, 0); + if (ret) + dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret); + + usleep_range(2000, 3000); /* wait for wseq to complete */ + + ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + MADERA_EP_SEL, ep_sel); + if (ret) { + dev_err(madera->dev, "Failed to set OUT3 demux: %d\n", ret); + } else { + out_mono = madera->pdata.codec.out_mono[2 + mux]; + + ret = madera_set_output_mode(component, 3, out_mono); + if (ret < 0) + dev_warn(madera->dev, + "Failed to set output mode: %d\n", ret); + } + + ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, cur); + if (ret) { + dev_warn(madera->dev, "Failed to restore outputs: %d\n", ret); + } else { + /* wait for wseq */ + if (cur & (MADERA_OUT3L_ENA | MADERA_OUT3R_ENA)) + msleep(34); /* enable delay */ + else + usleep_range(2000, 3000); /* disable delay */ + } + +end: + snd_soc_dapm_mutex_unlock(dapm); + + return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); +} + +static SOC_ENUM_SINGLE_DECL(cs47l92_outdemux_enum, + MADERA_OUTPUT_ENABLES_1, + MADERA_EP_SEL_SHIFT, + cs47l92_outdemux_texts); + +static const struct snd_kcontrol_new cs47l92_outdemux = + SOC_DAPM_ENUM_EXT("OUT3 Demux", cs47l92_outdemux_enum, + snd_soc_dapm_get_enum_double, cs47l92_put_demux); + +static int cs47l92_adsp_power_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + unsigned int freq; + int ret; + + ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); + if (ret != 0) { + dev_err(madera->dev, + "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); + return ret; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = madera_set_adsp_clk(&cs47l92->core, w->shift, freq); + if (ret) + return ret; + break; + default: + break; + } + + return wm_adsp_early_event(w, kcontrol, event); +} + +#define CS47L92_NG_SRC(name, base) \ + SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ + SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2L Switch", base, 2, 1, 0), \ + SOC_SINGLE(name " NG HPOUT2R Switch", base, 3, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3L Switch", base, 4, 1, 0), \ + SOC_SINGLE(name " NG HPOUT3R Switch", base, 5, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ + SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) + +static const struct snd_kcontrol_new cs47l92_snd_controls[] = { +SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), +SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), +SOC_ENUM("IN3 OSR", madera_in_dmic_osr[2]), +SOC_ENUM("IN4 OSR", madera_in_dmic_osr[3]), + +SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, + MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, + MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2L Volume", MADERA_IN2L_CONTROL, + MADERA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), +SOC_SINGLE_RANGE_TLV("IN2R Volume", MADERA_IN2R_CONTROL, + MADERA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), + +SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), + +SOC_SINGLE_EXT("IN1L LP Switch", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN1R LP Switch", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN2L LP Switch", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN1L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), +SOC_SINGLE_EXT("IN2R LP Switch", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN1L_LP_MODE_SHIFT, 1, 0, + snd_soc_get_volsw, madera_lp_mode_put), + +SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, + MADERA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, + MADERA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, + MADERA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, + MADERA_IN2R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3L HPF Switch", MADERA_IN3L_CONTROL, + MADERA_IN3L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3R HPF Switch", MADERA_IN3R_CONTROL, + MADERA_IN3R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4L HPF Switch", MADERA_IN4L_CONTROL, + MADERA_IN4L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4R HPF Switch", MADERA_IN4R_CONTROL, + MADERA_IN4R_HPF_SHIFT, 1, 0), + +SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, + MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, + MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, + MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, + MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3L, + MADERA_IN3L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN3R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3R, + MADERA_IN3R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4L, + MADERA_IN4L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), +SOC_SINGLE_TLV("IN4R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4R, + MADERA_IN4R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), + +SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), +SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), + +MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), + +MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), +SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), +SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), +SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), +SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, + 24, 0, madera_eq_tlv), +SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, + 24, 0, madera_eq_tlv), + +SOC_SINGLE("DAC High Performance Mode Switch", MADERA_OUTPUT_RATE_1, + MADERA_CP_DAC_MODE_SHIFT, 1, 0), + +MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), + +SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, + MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), +SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, + MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), + +MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), + +MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), +MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), +MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), +MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), + +SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), +SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), +SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), +SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), + +MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), +MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), +MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), +MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), +MADERA_RATE_ENUM("ASRC1 Rate 1", madera_asrc1_bidir_rate[0]), +MADERA_RATE_ENUM("ASRC1 Rate 2", madera_asrc1_bidir_rate[1]), + +WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), + +MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), + +SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), + +MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2L", MADERA_OUT2LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT2R", MADERA_OUT2RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3L", MADERA_OUT3LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("HPOUT3R", MADERA_OUT3RMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), + +SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, + MADERA_HP1_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT2 SC Protect Switch", MADERA_HP2_SHORT_CIRCUIT_CTRL, + MADERA_HP2_SC_ENA_SHIFT, 1, 0), +SOC_SINGLE("HPOUT3 SC Protect Switch", MADERA_HP3_SHORT_CIRCUIT_CTRL, + MADERA_HP3_SC_ENA_SHIFT, 1, 0), + +SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, + MADERA_OUT5_OSR_SHIFT, 1, 0), + +SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT2 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("HPOUT3 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_MUTE_SHIFT, 1, 1), +SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), + +SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), +SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, + 0xbf, 0, madera_digital_tlv), + +SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, + MADERA_SPK1R_MUTE_SHIFT, 1, 1), + +SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), +SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), + +SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_ENA_SHIFT, 1, 0), +SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, + MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), +SOC_ENUM("Noise Gate Hold", madera_ng_hold), + +SOC_ENUM_EXT("DFC1RX Width", madera_dfc_width[0], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1RX Type", madera_dfc_type[0], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1TX Width", madera_dfc_width[1], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC1TX Type", madera_dfc_type[1], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2RX Width", madera_dfc_width[2], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2RX Type", madera_dfc_type[2], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2TX Width", madera_dfc_width[3], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC2TX Type", madera_dfc_type[3], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3RX Width", madera_dfc_width[4], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3RX Type", madera_dfc_type[4], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3TX Width", madera_dfc_width[5], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC3TX Type", madera_dfc_type[5], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4RX Width", madera_dfc_width[6], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4RX Type", madera_dfc_type[6], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4TX Width", madera_dfc_width[7], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC4TX Type", madera_dfc_type[7], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5RX Width", madera_dfc_width[8], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5RX Type", madera_dfc_type[8], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5TX Width", madera_dfc_width[9], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC5TX Type", madera_dfc_type[9], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6RX Width", madera_dfc_width[10], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6RX Type", madera_dfc_type[10], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6TX Width", madera_dfc_width[11], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC6TX Type", madera_dfc_type[11], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7RX Width", madera_dfc_width[12], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7RX Type", madera_dfc_type[12], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7TX Width", madera_dfc_width[13], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC7TX Type", madera_dfc_type[13], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8RX Width", madera_dfc_width[14], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8RX Type", madera_dfc_type[14], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8TX Width", madera_dfc_width[15], + snd_soc_get_enum_double, madera_dfc_put), +SOC_ENUM_EXT("DFC8TX Type", madera_dfc_type[15], + snd_soc_get_enum_double, madera_dfc_put), + +CS47L92_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), +CS47L92_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), +CS47L92_NG_SRC("HPOUT2L", MADERA_NOISE_GATE_SELECT_2L), +CS47L92_NG_SRC("HPOUT2R", MADERA_NOISE_GATE_SELECT_2R), +CS47L92_NG_SRC("HPOUT3L", MADERA_NOISE_GATE_SELECT_3L), +CS47L92_NG_SRC("HPOUT3R", MADERA_NOISE_GATE_SELECT_3R), +CS47L92_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), +CS47L92_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), + +MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX7", MADERA_AIF1TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF1TX8", MADERA_AIF1TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX5", MADERA_AIF2TX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX6", MADERA_AIF2TX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX7", MADERA_AIF2TX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF2TX8", MADERA_AIF2TX8MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX3", MADERA_AIF3TX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("AIF3TX4", MADERA_AIF3TX4MIX_INPUT_1_SOURCE), + +MADERA_MIXER_CONTROLS("SLIMTX1", MADERA_SLIMTX1MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX2", MADERA_SLIMTX2MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX3", MADERA_SLIMTX3MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX4", MADERA_SLIMTX4MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX5", MADERA_SLIMTX5MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX6", MADERA_SLIMTX6MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX7", MADERA_SLIMTX7MIX_INPUT_1_SOURCE), +MADERA_MIXER_CONTROLS("SLIMTX8", MADERA_SLIMTX8MIX_INPUT_1_SOURCE), + +MADERA_GAINMUX_CONTROLS("SPDIFTX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), +MADERA_GAINMUX_CONTROLS("SPDIFTX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), + +WM_ADSP_FW_CONTROL("DSP1", 0), +}; + +MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); +MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2L, MADERA_OUT2LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT2R, MADERA_OUT2RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3L, MADERA_OUT3LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(OUT3R, MADERA_OUT3RMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX7, MADERA_AIF1TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF1TX8, MADERA_AIF1TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX5, MADERA_AIF2TX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX6, MADERA_AIF2TX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX7, MADERA_AIF2TX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF2TX8, MADERA_AIF2TX8MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX3, MADERA_AIF3TX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(AIF3TX4, MADERA_AIF3TX4MIX_INPUT_1_SOURCE); + +MADERA_MIXER_ENUMS(SLIMTX1, MADERA_SLIMTX1MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX2, MADERA_SLIMTX2MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX3, MADERA_SLIMTX3MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX4, MADERA_SLIMTX4MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX5, MADERA_SLIMTX5MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX6, MADERA_SLIMTX6MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX7, MADERA_SLIMTX7MIX_INPUT_1_SOURCE); +MADERA_MIXER_ENUMS(SLIMTX8, MADERA_SLIMTX8MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ASRC1IN1L, MADERA_ASRC1_1LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN1R, MADERA_ASRC1_1RMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2L, MADERA_ASRC1_2LMIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ASRC1IN2R, MADERA_ASRC1_2RMIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); + +MADERA_MUX_ENUMS(DFC1, MADERA_DFC1MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC2, MADERA_DFC2MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC3, MADERA_DFC3MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC4, MADERA_DFC4MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC5, MADERA_DFC5MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC6, MADERA_DFC6MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC7, MADERA_DFC7MIX_INPUT_1_SOURCE); +MADERA_MUX_ENUMS(DFC8, MADERA_DFC8MIX_INPUT_1_SOURCE); + +static const char * const cs47l92_aec_loopback_texts[] = { + "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", + "SPKDAT1L", "SPKDAT1R", +}; + +static const unsigned int cs47l92_aec_loopback_values[] = { + 0, 1, 2, 3, 4, 5, 8, 9 +}; + +static const struct soc_enum cs47l92_aec_loopback = + SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, + ARRAY_SIZE(cs47l92_aec_loopback_texts), + cs47l92_aec_loopback_texts, + cs47l92_aec_loopback_values); + +static const struct snd_kcontrol_new cs47l92_aec_loopback_mux = + SOC_DAPM_ENUM("AEC1 Loopback", cs47l92_aec_loopback); + +static const struct snd_soc_dapm_widget cs47l92_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, + 0, madera_sysclk_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, + MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, + MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, + MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, + MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), +SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), + +SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2", MADERA_MIC_BIAS_CTRL_2, + MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1C", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1C_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS1D", MADERA_MIC_BIAS_CTRL_5, + MADERA_MICB1D_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("MICBIAS2A", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2A_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("MICBIAS2B", MADERA_MIC_BIAS_CTRL_6, + MADERA_MICB2B_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_FX, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ASRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ASRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_ISRC2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_OUT, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SPD, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DSP1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF1, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF2, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_AIF3, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("SLIMBUSCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_SLIMBUS, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_PWM, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("DFCCLK", SND_SOC_NOPM, + MADERA_DOM_GRP_DFC, 0, + madera_domain_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_SIGGEN("TONE"), +SND_SOC_DAPM_SIGGEN("NOISE"), + +SND_SOC_DAPM_INPUT("IN1ALN"), +SND_SOC_DAPM_INPUT("IN1ALP"), +SND_SOC_DAPM_INPUT("IN1BLN"), +SND_SOC_DAPM_INPUT("IN1BLP"), +SND_SOC_DAPM_INPUT("IN1ARN"), +SND_SOC_DAPM_INPUT("IN1ARP"), +SND_SOC_DAPM_INPUT("IN1BR"), +SND_SOC_DAPM_INPUT("IN2ALN"), +SND_SOC_DAPM_INPUT("IN2ALP"), +SND_SOC_DAPM_INPUT("IN2BL"), +SND_SOC_DAPM_INPUT("IN2ARN"), +SND_SOC_DAPM_INPUT("IN2ARP"), +SND_SOC_DAPM_INPUT("IN2BR"), + +SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), +SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), +SND_SOC_DAPM_MUX("IN2L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[2]), +SND_SOC_DAPM_MUX("IN2R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[3]), + +SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), +SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), + +SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), +SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), + +SND_SOC_DAPM_DEMUX("OUT3 Demux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux), + +SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), +SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), + +SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, + 0, NULL, 0), +SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, + 0, NULL, 0), + +SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, + MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, + MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, + MADERA_SLIMBUS_TX_CHANNEL_ENABLE, + MADERA_SLIMTX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 0, + MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX4_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, + MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, + MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2L", SND_SOC_NOPM, + MADERA_OUT2L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT2R", SND_SOC_NOPM, + MADERA_OUT2R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT3R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT3R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, + MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, + MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), + +/* + * mux_in widgets : arranged in the order of sources + * specified in MADERA_MIXER_INPUT_ROUTES + */ + +SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, + MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, + MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, + MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_SIGGEN("HAPTICS"), + +SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, + MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, + &cs47l92_aec_loopback_mux), + +SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3L", MADERA_INPUT_ENABLES, MADERA_IN3L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN3R", MADERA_INPUT_ENABLES, MADERA_IN3R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4L", MADERA_INPUT_ENABLES, MADERA_IN4L_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, + 0, NULL, 0, madera_in_ev, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + +SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, + MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, + MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 0, + MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX4_ENA_SHIFT, 0), + +SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX1_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX2_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX3_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX4_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX5_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX6_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX7_ENA_SHIFT, 0), +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, + MADERA_SLIMRX8_ENA_SHIFT, 0), + +SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, + NULL, 0), +SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, + NULL, 0), + +SND_SOC_DAPM_PGA("ASRC1IN1L", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN1L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN1R", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN1R_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2L", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN2L_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ASRC1IN2R", MADERA_ASRC1_ENABLE, + MADERA_ASRC1_IN2R_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, + MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), + +SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, + MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), + +WM_ADSP2("DSP1", 0, cs47l92_adsp_power_ev), + +/* end of ordered widget list */ + +SND_SOC_DAPM_PGA("DFC1", MADERA_DFC1_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC2", MADERA_DFC2_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC3", MADERA_DFC3_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC4", MADERA_DFC4_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC5", MADERA_DFC5_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC6", MADERA_DFC6_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC7", MADERA_DFC7_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_PGA("DFC8", MADERA_DFC8_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), + +MADERA_MIXER_WIDGETS(EQ1, "EQ1"), +MADERA_MIXER_WIDGETS(EQ2, "EQ2"), +MADERA_MIXER_WIDGETS(EQ3, "EQ3"), +MADERA_MIXER_WIDGETS(EQ4, "EQ4"), + +MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), +MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), +MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), +MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), + +SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[0]), +SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, + &madera_drc_activity_output_mux[1]), + +MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), +MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), +MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), +MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), + +MADERA_MIXER_WIDGETS(PWM1, "PWM1"), +MADERA_MIXER_WIDGETS(PWM2, "PWM2"), + +MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), +MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), +MADERA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), +MADERA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), +MADERA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), +MADERA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), +MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), +MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), + +MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), +MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), +MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), +MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), +MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), +MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), +MADERA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), +MADERA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), + +MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), +MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), +MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), +MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), +MADERA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), +MADERA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), +MADERA_MIXER_WIDGETS(AIF2TX7, "AIF2TX7"), +MADERA_MIXER_WIDGETS(AIF2TX8, "AIF2TX8"), + +MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), +MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), +MADERA_MIXER_WIDGETS(AIF3TX3, "AIF3TX3"), +MADERA_MIXER_WIDGETS(AIF3TX4, "AIF3TX4"), + +MADERA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), +MADERA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), +MADERA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), +MADERA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), +MADERA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), +MADERA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), +MADERA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), +MADERA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), + +MADERA_MUX_WIDGETS(SPD1TX1, "SPDIFTX1"), +MADERA_MUX_WIDGETS(SPD1TX2, "SPDIFTX2"), + +MADERA_MUX_WIDGETS(ASRC1IN1L, "ASRC1IN1L"), +MADERA_MUX_WIDGETS(ASRC1IN1R, "ASRC1IN1R"), +MADERA_MUX_WIDGETS(ASRC1IN2L, "ASRC1IN2L"), +MADERA_MUX_WIDGETS(ASRC1IN2R, "ASRC1IN2R"), + +MADERA_DSP_WIDGETS(DSP1, "DSP1"), + +MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), +MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), + +MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), +MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), + +MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), +MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), + +MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), +MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), + +MADERA_MUX_WIDGETS(DFC1, "DFC1"), +MADERA_MUX_WIDGETS(DFC2, "DFC2"), +MADERA_MUX_WIDGETS(DFC3, "DFC3"), +MADERA_MUX_WIDGETS(DFC4, "DFC4"), +MADERA_MUX_WIDGETS(DFC5, "DFC5"), +MADERA_MUX_WIDGETS(DFC6, "DFC6"), +MADERA_MUX_WIDGETS(DFC7, "DFC7"), +MADERA_MUX_WIDGETS(DFC8, "DFC8"), + +SND_SOC_DAPM_OUTPUT("HPOUT1L"), +SND_SOC_DAPM_OUTPUT("HPOUT1R"), +SND_SOC_DAPM_OUTPUT("HPOUT2L"), +SND_SOC_DAPM_OUTPUT("HPOUT2R"), +SND_SOC_DAPM_OUTPUT("HPOUT3L"), +SND_SOC_DAPM_OUTPUT("HPOUT3R"), +SND_SOC_DAPM_OUTPUT("HPOUT4L"), +SND_SOC_DAPM_OUTPUT("HPOUT4R"), +SND_SOC_DAPM_OUTPUT("SPKDAT1L"), +SND_SOC_DAPM_OUTPUT("SPKDAT1R"), +SND_SOC_DAPM_OUTPUT("SPDIF1"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"), +}; + +#define MADERA_MIXER_INPUT_ROUTES(name) \ + { name, "Noise Generator", "Noise Generator" }, \ + { name, "Tone Generator 1", "Tone Generator 1" }, \ + { name, "Tone Generator 2", "Tone Generator 2" }, \ + { name, "Haptics", "HAPTICS" }, \ + { name, "AEC1", "AEC1 Loopback" }, \ + { name, "IN1L", "IN1L" }, \ + { name, "IN1R", "IN1R" }, \ + { name, "IN2L", "IN2L" }, \ + { name, "IN2R", "IN2R" }, \ + { name, "IN3L", "IN3L" }, \ + { name, "IN3R", "IN3R" }, \ + { name, "IN4L", "IN4L" }, \ + { name, "IN4R", "IN4R" }, \ + { name, "AIF1RX1", "AIF1RX1" }, \ + { name, "AIF1RX2", "AIF1RX2" }, \ + { name, "AIF1RX3", "AIF1RX3" }, \ + { name, "AIF1RX4", "AIF1RX4" }, \ + { name, "AIF1RX5", "AIF1RX5" }, \ + { name, "AIF1RX6", "AIF1RX6" }, \ + { name, "AIF1RX7", "AIF1RX7" }, \ + { name, "AIF1RX8", "AIF1RX8" }, \ + { name, "AIF2RX1", "AIF2RX1" }, \ + { name, "AIF2RX2", "AIF2RX2" }, \ + { name, "AIF2RX3", "AIF2RX3" }, \ + { name, "AIF2RX4", "AIF2RX4" }, \ + { name, "AIF2RX5", "AIF2RX5" }, \ + { name, "AIF2RX6", "AIF2RX6" }, \ + { name, "AIF2RX7", "AIF2RX7" }, \ + { name, "AIF2RX8", "AIF2RX8" }, \ + { name, "AIF3RX1", "AIF3RX1" }, \ + { name, "AIF3RX2", "AIF3RX2" }, \ + { name, "AIF3RX3", "AIF3RX3" }, \ + { name, "AIF3RX4", "AIF3RX4" }, \ + { name, "SLIMRX1", "SLIMRX1" }, \ + { name, "SLIMRX2", "SLIMRX2" }, \ + { name, "SLIMRX3", "SLIMRX3" }, \ + { name, "SLIMRX4", "SLIMRX4" }, \ + { name, "SLIMRX5", "SLIMRX5" }, \ + { name, "SLIMRX6", "SLIMRX6" }, \ + { name, "SLIMRX7", "SLIMRX7" }, \ + { name, "SLIMRX8", "SLIMRX8" }, \ + { name, "EQ1", "EQ1" }, \ + { name, "EQ2", "EQ2" }, \ + { name, "EQ3", "EQ3" }, \ + { name, "EQ4", "EQ4" }, \ + { name, "DRC1L", "DRC1L" }, \ + { name, "DRC1R", "DRC1R" }, \ + { name, "DRC2L", "DRC2L" }, \ + { name, "DRC2R", "DRC2R" }, \ + { name, "LHPF1", "LHPF1" }, \ + { name, "LHPF2", "LHPF2" }, \ + { name, "LHPF3", "LHPF3" }, \ + { name, "LHPF4", "LHPF4" }, \ + { name, "ASRC1IN1L", "ASRC1IN1L" }, \ + { name, "ASRC1IN1R", "ASRC1IN1R" }, \ + { name, "ASRC1IN2L", "ASRC1IN2L" }, \ + { name, "ASRC1IN2R", "ASRC1IN2R" }, \ + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ + { name, "ISRC1INT1", "ISRC1INT1" }, \ + { name, "ISRC1INT2", "ISRC1INT2" }, \ + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ + { name, "ISRC2INT1", "ISRC2INT1" }, \ + { name, "ISRC2INT2", "ISRC2INT2" }, \ + { name, "DSP1.1", "DSP1" }, \ + { name, "DSP1.2", "DSP1" }, \ + { name, "DSP1.3", "DSP1" }, \ + { name, "DSP1.4", "DSP1" }, \ + { name, "DSP1.5", "DSP1" }, \ + { name, "DSP1.6", "DSP1" }, \ + { name, "DFC1", "DFC1" }, \ + { name, "DFC2", "DFC2" }, \ + { name, "DFC3", "DFC3" }, \ + { name, "DFC4", "DFC4" }, \ + { name, "DFC5", "DFC5" }, \ + { name, "DFC6", "DFC6" }, \ + { name, "DFC7", "DFC7" }, \ + { name, "DFC8", "DFC8" } + +static const struct snd_soc_dapm_route cs47l92_dapm_routes[] = { + /* Internal clock domains */ + { "EQ1", NULL, "FXCLK" }, + { "EQ2", NULL, "FXCLK" }, + { "EQ3", NULL, "FXCLK" }, + { "EQ4", NULL, "FXCLK" }, + { "DRC1L", NULL, "FXCLK" }, + { "DRC1R", NULL, "FXCLK" }, + { "DRC2L", NULL, "FXCLK" }, + { "DRC2R", NULL, "FXCLK" }, + { "LHPF1", NULL, "FXCLK" }, + { "LHPF2", NULL, "FXCLK" }, + { "LHPF3", NULL, "FXCLK" }, + { "LHPF4", NULL, "FXCLK" }, + { "PWM1 Mixer", NULL, "PWMCLK" }, + { "PWM2 Mixer", NULL, "PWMCLK" }, + { "OUT1L", NULL, "OUTCLK" }, + { "OUT1R", NULL, "OUTCLK" }, + { "OUT2L", NULL, "OUTCLK" }, + { "OUT2R", NULL, "OUTCLK" }, + { "OUT3L", NULL, "OUTCLK" }, + { "OUT3R", NULL, "OUTCLK" }, + { "OUT5L", NULL, "OUTCLK" }, + { "OUT5R", NULL, "OUTCLK" }, + { "AIF1TX1", NULL, "AIF1TXCLK" }, + { "AIF1TX2", NULL, "AIF1TXCLK" }, + { "AIF1TX3", NULL, "AIF1TXCLK" }, + { "AIF1TX4", NULL, "AIF1TXCLK" }, + { "AIF1TX5", NULL, "AIF1TXCLK" }, + { "AIF1TX6", NULL, "AIF1TXCLK" }, + { "AIF1TX7", NULL, "AIF1TXCLK" }, + { "AIF1TX8", NULL, "AIF1TXCLK" }, + { "AIF2TX1", NULL, "AIF2TXCLK" }, + { "AIF2TX2", NULL, "AIF2TXCLK" }, + { "AIF2TX3", NULL, "AIF2TXCLK" }, + { "AIF2TX4", NULL, "AIF2TXCLK" }, + { "AIF2TX5", NULL, "AIF2TXCLK" }, + { "AIF2TX6", NULL, "AIF2TXCLK" }, + { "AIF2TX7", NULL, "AIF2TXCLK" }, + { "AIF2TX8", NULL, "AIF2TXCLK" }, + { "AIF3TX1", NULL, "AIF3TXCLK" }, + { "AIF3TX2", NULL, "AIF3TXCLK" }, + { "AIF3TX3", NULL, "AIF3TXCLK" }, + { "AIF3TX4", NULL, "AIF3TXCLK" }, + { "SLIMTX1", NULL, "SLIMBUSCLK" }, + { "SLIMTX2", NULL, "SLIMBUSCLK" }, + { "SLIMTX3", NULL, "SLIMBUSCLK" }, + { "SLIMTX4", NULL, "SLIMBUSCLK" }, + { "SLIMTX5", NULL, "SLIMBUSCLK" }, + { "SLIMTX6", NULL, "SLIMBUSCLK" }, + { "SLIMTX7", NULL, "SLIMBUSCLK" }, + { "SLIMTX8", NULL, "SLIMBUSCLK" }, + { "SPD1TX1", NULL, "SPDCLK" }, + { "SPD1TX2", NULL, "SPDCLK" }, + { "DSP1", NULL, "DSP1CLK" }, + { "ISRC1DEC1", NULL, "ISRC1CLK" }, + { "ISRC1DEC2", NULL, "ISRC1CLK" }, + { "ISRC1INT1", NULL, "ISRC1CLK" }, + { "ISRC1INT2", NULL, "ISRC1CLK" }, + { "ISRC2DEC1", NULL, "ISRC2CLK" }, + { "ISRC2DEC2", NULL, "ISRC2CLK" }, + { "ISRC2INT1", NULL, "ISRC2CLK" }, + { "ISRC2INT2", NULL, "ISRC2CLK" }, + { "ASRC1IN1L", NULL, "ASRC1CLK" }, + { "ASRC1IN1R", NULL, "ASRC1CLK" }, + { "ASRC1IN2L", NULL, "ASRC1CLK" }, + { "ASRC1IN2R", NULL, "ASRC1CLK" }, + { "DFC1", NULL, "DFCCLK" }, + { "DFC2", NULL, "DFCCLK" }, + { "DFC3", NULL, "DFCCLK" }, + { "DFC4", NULL, "DFCCLK" }, + { "DFC5", NULL, "DFCCLK" }, + { "DFC6", NULL, "DFCCLK" }, + { "DFC7", NULL, "DFCCLK" }, + { "DFC8", NULL, "DFCCLK" }, + + { "OUT1L", NULL, "CPVDD1" }, + { "OUT1L", NULL, "CPVDD2" }, + { "OUT1R", NULL, "CPVDD1" }, + { "OUT1R", NULL, "CPVDD2" }, + { "OUT2L", NULL, "CPVDD1" }, + { "OUT2L", NULL, "CPVDD2" }, + { "OUT2R", NULL, "CPVDD1" }, + { "OUT2R", NULL, "CPVDD2" }, + { "OUT3L", NULL, "CPVDD1" }, + { "OUT3L", NULL, "CPVDD2" }, + { "OUT3R", NULL, "CPVDD1" }, + { "OUT3R", NULL, "CPVDD2" }, + + { "OUT1L", NULL, "SYSCLK" }, + { "OUT1R", NULL, "SYSCLK" }, + { "OUT2L", NULL, "SYSCLK" }, + { "OUT2R", NULL, "SYSCLK" }, + { "OUT3L", NULL, "SYSCLK" }, + { "OUT3R", NULL, "SYSCLK" }, + { "OUT5L", NULL, "SYSCLK" }, + { "OUT5R", NULL, "SYSCLK" }, + + { "SPD1", NULL, "SYSCLK" }, + { "SPD1", NULL, "SPD1TX1" }, + { "SPD1", NULL, "SPD1TX2" }, + + { "IN1L", NULL, "SYSCLK" }, + { "IN1R", NULL, "SYSCLK" }, + { "IN2L", NULL, "SYSCLK" }, + { "IN2R", NULL, "SYSCLK" }, + { "IN3L", NULL, "SYSCLK" }, + { "IN3R", NULL, "SYSCLK" }, + { "IN4L", NULL, "SYSCLK" }, + { "IN4R", NULL, "SYSCLK" }, + + { "ASRC1IN1L", NULL, "SYSCLK" }, + { "ASRC1IN1R", NULL, "SYSCLK" }, + { "ASRC1IN2L", NULL, "SYSCLK" }, + { "ASRC1IN2R", NULL, "SYSCLK" }, + + { "ASRC1IN1L", NULL, "ASYNCCLK" }, + { "ASRC1IN1R", NULL, "ASYNCCLK" }, + { "ASRC1IN2L", NULL, "ASYNCCLK" }, + { "ASRC1IN2R", NULL, "ASYNCCLK" }, + + { "MICBIAS1", NULL, "MICVDD" }, + { "MICBIAS2", NULL, "MICVDD" }, + + { "MICBIAS1A", NULL, "MICBIAS1" }, + { "MICBIAS1B", NULL, "MICBIAS1" }, + { "MICBIAS1C", NULL, "MICBIAS1" }, + { "MICBIAS1D", NULL, "MICBIAS1" }, + + { "MICBIAS2A", NULL, "MICBIAS2" }, + { "MICBIAS2B", NULL, "MICBIAS2" }, + + { "Noise Generator", NULL, "SYSCLK" }, + { "Tone Generator 1", NULL, "SYSCLK" }, + { "Tone Generator 2", NULL, "SYSCLK" }, + + { "Noise Generator", NULL, "NOISE" }, + { "Tone Generator 1", NULL, "TONE" }, + { "Tone Generator 2", NULL, "TONE" }, + + { "AIF1 Capture", NULL, "AIF1TX1" }, + { "AIF1 Capture", NULL, "AIF1TX2" }, + { "AIF1 Capture", NULL, "AIF1TX3" }, + { "AIF1 Capture", NULL, "AIF1TX4" }, + { "AIF1 Capture", NULL, "AIF1TX5" }, + { "AIF1 Capture", NULL, "AIF1TX6" }, + { "AIF1 Capture", NULL, "AIF1TX7" }, + { "AIF1 Capture", NULL, "AIF1TX8" }, + + { "AIF1RX1", NULL, "AIF1 Playback" }, + { "AIF1RX2", NULL, "AIF1 Playback" }, + { "AIF1RX3", NULL, "AIF1 Playback" }, + { "AIF1RX4", NULL, "AIF1 Playback" }, + { "AIF1RX5", NULL, "AIF1 Playback" }, + { "AIF1RX6", NULL, "AIF1 Playback" }, + { "AIF1RX7", NULL, "AIF1 Playback" }, + { "AIF1RX8", NULL, "AIF1 Playback" }, + + { "AIF2 Capture", NULL, "AIF2TX1" }, + { "AIF2 Capture", NULL, "AIF2TX2" }, + { "AIF2 Capture", NULL, "AIF2TX3" }, + { "AIF2 Capture", NULL, "AIF2TX4" }, + { "AIF2 Capture", NULL, "AIF2TX5" }, + { "AIF2 Capture", NULL, "AIF2TX6" }, + { "AIF2 Capture", NULL, "AIF2TX7" }, + { "AIF2 Capture", NULL, "AIF2TX8" }, + + { "AIF2RX1", NULL, "AIF2 Playback" }, + { "AIF2RX2", NULL, "AIF2 Playback" }, + { "AIF2RX3", NULL, "AIF2 Playback" }, + { "AIF2RX4", NULL, "AIF2 Playback" }, + { "AIF2RX5", NULL, "AIF2 Playback" }, + { "AIF2RX6", NULL, "AIF2 Playback" }, + { "AIF2RX7", NULL, "AIF2 Playback" }, + { "AIF2RX8", NULL, "AIF2 Playback" }, + + { "AIF3 Capture", NULL, "AIF3TX1" }, + { "AIF3 Capture", NULL, "AIF3TX2" }, + { "AIF3 Capture", NULL, "AIF3TX3" }, + { "AIF3 Capture", NULL, "AIF3TX4" }, + + { "AIF3RX1", NULL, "AIF3 Playback" }, + { "AIF3RX2", NULL, "AIF3 Playback" }, + { "AIF3RX3", NULL, "AIF3 Playback" }, + { "AIF3RX4", NULL, "AIF3 Playback" }, + + { "Slim1 Capture", NULL, "SLIMTX1" }, + { "Slim1 Capture", NULL, "SLIMTX2" }, + { "Slim1 Capture", NULL, "SLIMTX3" }, + { "Slim1 Capture", NULL, "SLIMTX4" }, + + { "SLIMRX1", NULL, "Slim1 Playback" }, + { "SLIMRX2", NULL, "Slim1 Playback" }, + { "SLIMRX3", NULL, "Slim1 Playback" }, + { "SLIMRX4", NULL, "Slim1 Playback" }, + + { "Slim2 Capture", NULL, "SLIMTX5" }, + { "Slim2 Capture", NULL, "SLIMTX6" }, + + { "SLIMRX5", NULL, "Slim2 Playback" }, + { "SLIMRX6", NULL, "Slim2 Playback" }, + + { "Slim3 Capture", NULL, "SLIMTX7" }, + { "Slim3 Capture", NULL, "SLIMTX8" }, + + { "SLIMRX7", NULL, "Slim3 Playback" }, + { "SLIMRX8", NULL, "Slim3 Playback" }, + + { "AIF1 Playback", NULL, "SYSCLK" }, + { "AIF2 Playback", NULL, "SYSCLK" }, + { "AIF3 Playback", NULL, "SYSCLK" }, + { "Slim1 Playback", NULL, "SYSCLK" }, + { "Slim2 Playback", NULL, "SYSCLK" }, + { "Slim3 Playback", NULL, "SYSCLK" }, + + { "AIF1 Capture", NULL, "SYSCLK" }, + { "AIF2 Capture", NULL, "SYSCLK" }, + { "AIF3 Capture", NULL, "SYSCLK" }, + { "Slim1 Capture", NULL, "SYSCLK" }, + { "Slim2 Capture", NULL, "SYSCLK" }, + { "Slim3 Capture", NULL, "SYSCLK" }, + + { "Audio Trace DSP", NULL, "DSP1" }, + + { "IN1L Analog Mux", "A", "IN1ALN" }, + { "IN1L Analog Mux", "A", "IN1ALP" }, + { "IN1L Analog Mux", "B", "IN1BLN" }, + { "IN1L Analog Mux", "B", "IN1BLP" }, + { "IN1R Analog Mux", "A", "IN1ARN" }, + { "IN1R Analog Mux", "A", "IN1ARP" }, + { "IN1R Analog Mux", "B", "IN1BR" }, + { "IN1R Analog Mux", "B", "IN1ALN" }, + + { "IN1L Mode", "Analog", "IN1L Analog Mux" }, + { "IN1R Mode", "Analog", "IN1R Analog Mux" }, + + { "IN1L Mode", "Digital", "IN1ALN" }, + { "IN1L Mode", "Digital", "IN1ALP" }, + { "IN1R Mode", "Digital", "IN1ALN" }, + { "IN1R Mode", "Digital", "IN1ALP" }, + + { "IN1L", NULL, "IN1L Mode" }, + { "IN1R", NULL, "IN1R Mode" }, + + { "IN2L Analog Mux", "A", "IN2ALN" }, + { "IN2L Analog Mux", "A", "IN2ALP" }, + { "IN2L Analog Mux", "B", "IN2ALN" }, + { "IN2L Analog Mux", "B", "IN2BL" }, + { "IN2R Analog Mux", "A", "IN2ARN" }, + { "IN2R Analog Mux", "A", "IN2ARP" }, + { "IN2R Analog Mux", "B", "IN2ARN" }, + { "IN2R Analog Mux", "B", "IN2BR" }, + + { "IN2L Mode", "Analog", "IN2L Analog Mux" }, + { "IN2R Mode", "Analog", "IN2R Analog Mux" }, + + { "IN2L Mode", "Digital", "IN2ALN" }, + { "IN2L Mode", "Digital", "IN2ALP" }, + { "IN2R Mode", "Digital", "IN2ALN" }, + { "IN2R Mode", "Digital", "IN2ALP" }, + + { "IN2L", NULL, "IN2L Mode" }, + { "IN2R", NULL, "IN2R Mode" }, + + { "IN3L", NULL, "IN1ARN" }, + { "IN3L", NULL, "IN1ARP" }, + { "IN3R", NULL, "IN1ARN" }, + { "IN3R", NULL, "IN1ARP" }, + + { "IN4L", NULL, "IN2ARN" }, + { "IN4L", NULL, "IN2ARP" }, + { "IN4R", NULL, "IN2ARN" }, + { "IN4R", NULL, "IN2ARP" }, + + MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), + MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), + MADERA_MIXER_ROUTES("OUT2L", "HPOUT2L"), + MADERA_MIXER_ROUTES("OUT2R", "HPOUT2R"), + MADERA_MIXER_ROUTES("OUT3L", "HPOUT3L"), + MADERA_MIXER_ROUTES("OUT3R", "HPOUT3R"), + + MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), + MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), + + MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), + MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), + + MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), + MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), + MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), + MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), + MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), + MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), + MADERA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), + MADERA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), + + MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), + MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), + MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), + MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), + MADERA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), + MADERA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), + MADERA_MIXER_ROUTES("AIF2TX7", "AIF2TX7"), + MADERA_MIXER_ROUTES("AIF2TX8", "AIF2TX8"), + + MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), + MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), + MADERA_MIXER_ROUTES("AIF3TX3", "AIF3TX3"), + MADERA_MIXER_ROUTES("AIF3TX4", "AIF3TX4"), + + MADERA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), + MADERA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), + MADERA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), + MADERA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), + MADERA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), + MADERA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), + MADERA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), + MADERA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), + + MADERA_MUX_ROUTES("SPD1TX1", "SPDIFTX1"), + MADERA_MUX_ROUTES("SPD1TX2", "SPDIFTX2"), + + MADERA_MIXER_ROUTES("EQ1", "EQ1"), + MADERA_MIXER_ROUTES("EQ2", "EQ2"), + MADERA_MIXER_ROUTES("EQ3", "EQ3"), + MADERA_MIXER_ROUTES("EQ4", "EQ4"), + + MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), + MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), + MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), + MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), + + MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), + MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), + MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), + MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), + + MADERA_MUX_ROUTES("ASRC1IN1L", "ASRC1IN1L"), + MADERA_MUX_ROUTES("ASRC1IN1R", "ASRC1IN1R"), + MADERA_MUX_ROUTES("ASRC1IN2L", "ASRC1IN2L"), + MADERA_MUX_ROUTES("ASRC1IN2R", "ASRC1IN2R"), + + MADERA_DSP_ROUTES("DSP1"), + + MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), + MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), + + MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), + MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), + + MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), + MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), + + MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), + MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), + + { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, + { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, + { "HPOUT1L", NULL, "OUT1L" }, + { "HPOUT1R", NULL, "OUT1R" }, + + { "AEC1 Loopback", "HPOUT2L", "OUT2L" }, + { "AEC1 Loopback", "HPOUT2R", "OUT2R" }, + { "HPOUT2L", NULL, "OUT2L" }, + { "HPOUT2R", NULL, "OUT2R" }, + + { "AEC1 Loopback", "HPOUT3L", "OUT3L" }, + { "AEC1 Loopback", "HPOUT3R", "OUT3R" }, + { "OUT3 Demux", NULL, "OUT3L" }, + { "OUT3 Demux", NULL, "OUT3R" }, + + { "HPOUT3L", "HPOUT3", "OUT3 Demux" }, + { "HPOUT3R", "HPOUT3", "OUT3 Demux" }, + { "HPOUT4L", "HPOUT4", "OUT3 Demux" }, + { "HPOUT4R", "HPOUT4", "OUT3 Demux" }, + + { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, + { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, + { "SPKDAT1L", NULL, "OUT5L" }, + { "SPKDAT1R", NULL, "OUT5R" }, + + { "SPDIF1", NULL, "SPD1" }, + + { "MICSUPP", NULL, "SYSCLK" }, + + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, + { "DRC1 Activity Output", "Switch", "DRC1L" }, + { "DRC1 Activity Output", "Switch", "DRC1R" }, + { "DRC2 Activity Output", "Switch", "DRC2L" }, + { "DRC2 Activity Output", "Switch", "DRC2R" }, + + MADERA_MUX_ROUTES("DFC1", "DFC1"), + MADERA_MUX_ROUTES("DFC2", "DFC2"), + MADERA_MUX_ROUTES("DFC3", "DFC3"), + MADERA_MUX_ROUTES("DFC4", "DFC4"), + MADERA_MUX_ROUTES("DFC5", "DFC5"), + MADERA_MUX_ROUTES("DFC6", "DFC6"), + MADERA_MUX_ROUTES("DFC7", "DFC7"), + MADERA_MUX_ROUTES("DFC8", "DFC8"), +}; + +static int cs47l92_set_fll(struct snd_soc_component *component, int fll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + + switch (fll_id) { + case MADERA_FLL1_REFCLK: + return madera_fllhj_set_refclk(&cs47l92->fll[0], source, fref, + fout); + case MADERA_FLL2_REFCLK: + return madera_fllhj_set_refclk(&cs47l92->fll[1], source, fref, + fout); + default: + return -EINVAL; + } +} + +static struct snd_soc_dai_driver cs47l92_dai[] = { + { + .name = "cs47l92-aif1", + .id = 1, + .base = MADERA_AIF1_BCLK_CTRL, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l92-aif2", + .id = 2, + .base = MADERA_AIF2_BCLK_CTRL, + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l92-aif3", + .id = 3, + .base = MADERA_AIF3_BCLK_CTRL, + .playback = { + .stream_name = "AIF3 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "AIF3 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_dai_ops, + .symmetric_rates = 1, + .symmetric_samplebits = 1, + }, + { + .name = "cs47l92-slim1", + .id = 5, + .playback = { + .stream_name = "Slim1 Playback", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l92-slim2", + .id = 6, + .playback = { + .stream_name = "Slim2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l92-slim3", + .id = 7, + .playback = { + .stream_name = "Slim3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .capture = { + .stream_name = "Slim3 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .ops = &madera_simple_dai_ops, + }, + { + .name = "cs47l92-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "cs47l92-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 2, + .rates = MADERA_RATES, + .formats = MADERA_FORMATS, + }, + }, +}; + +static int cs47l92_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l92-dsp-trace") == 0) { + n_adsp = 0; + } else { + dev_err(madera->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); +} + +static irqreturn_t cs47l92_adsp2_irq(int irq, void *data) +{ + struct cs47l92 *cs47l92 = data; + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + int ret; + + ret = wm_adsp_compr_handle_irq(&priv->adsp[0]); + if (ret == -ENODEV) { + dev_err(madera->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +static int cs47l92_component_probe(struct snd_soc_component *component) +{ + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l92->core.madera; + int ret; + + snd_soc_component_init_regmap(component, madera->regmap); + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = snd_soc_component_get_dapm(component); + mutex_unlock(&madera->dapm_ptr_lock); + + ret = madera_init_inputs(component); + if (ret) + return ret; + + ret = madera_init_outputs(component, CS47L92_MONO_OUTPUTS); + if (ret) + return ret; + + snd_soc_component_disable_pin(component, "HAPTICS"); + + ret = snd_soc_add_component_controls(component, + madera_adsp_rate_controls, + CS47L92_NUM_ADSP); + if (ret) + return ret; + + return wm_adsp2_component_probe(&cs47l92->core.adsp[0], component); +} + +static void cs47l92_component_remove(struct snd_soc_component *component) +{ + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera *madera = cs47l92->core.madera; + + mutex_lock(&madera->dapm_ptr_lock); + madera->dapm = NULL; + mutex_unlock(&madera->dapm_ptr_lock); + + wm_adsp2_component_remove(&cs47l92->core.adsp[0], component); +} + +#define CS47L92_DIG_VU 0x0200 + +static unsigned int cs47l92_digital_vu[] = { + MADERA_DAC_DIGITAL_VOLUME_1L, + MADERA_DAC_DIGITAL_VOLUME_1R, + MADERA_DAC_DIGITAL_VOLUME_2L, + MADERA_DAC_DIGITAL_VOLUME_2R, + MADERA_DAC_DIGITAL_VOLUME_3L, + MADERA_DAC_DIGITAL_VOLUME_3R, + MADERA_DAC_DIGITAL_VOLUME_5L, + MADERA_DAC_DIGITAL_VOLUME_5R, +}; + +static const struct snd_compr_ops cs47l92_compr_ops = { + .open = &cs47l92_open, + .free = &wm_adsp_compr_free, + .set_params = &wm_adsp_compr_set_params, + .get_caps = &wm_adsp_compr_get_caps, + .trigger = &wm_adsp_compr_trigger, + .pointer = &wm_adsp_compr_pointer, + .copy = &wm_adsp_compr_copy, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs47l92 = { + .probe = &cs47l92_component_probe, + .remove = &cs47l92_component_remove, + .set_sysclk = &madera_set_sysclk, + .set_pll = &cs47l92_set_fll, + .name = DRV_NAME, + .compr_ops = &cs47l92_compr_ops, + .controls = cs47l92_snd_controls, + .num_controls = ARRAY_SIZE(cs47l92_snd_controls), + .dapm_widgets = cs47l92_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l92_dapm_widgets), + .dapm_routes = cs47l92_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l92_dapm_routes), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int cs47l92_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct cs47l92 *cs47l92; + int i, ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs47l92_dai) > MADERA_MAX_DAI); + + /* quick exit if Madera irqchip driver hasn't completed probe */ + if (!madera->irq_dev) { + dev_dbg(&pdev->dev, "irqchip driver not ready\n"); + return -EPROBE_DEFER; + } + + cs47l92 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l92), GFP_KERNEL); + if (!cs47l92) + return -ENOMEM; + + platform_set_drvdata(pdev, cs47l92); + + cs47l92->core.madera = madera; + cs47l92->core.dev = &pdev->dev; + cs47l92->core.num_inputs = 8; + + ret = madera_core_init(&cs47l92->core); + if (ret) + return ret; + + ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l92_adsp2_irq, + cs47l92); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); + goto error_core; + } + + ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); + if (ret) + dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); + + cs47l92->core.adsp[0].part = "cs47l92"; + cs47l92->core.adsp[0].num = 1; + cs47l92->core.adsp[0].type = WMFW_ADSP2; + cs47l92->core.adsp[0].rev = 2; + cs47l92->core.adsp[0].dev = madera->dev; + cs47l92->core.adsp[0].regmap = madera->regmap_32bit; + + cs47l92->core.adsp[0].base = MADERA_DSP1_CONFIG_1; + cs47l92->core.adsp[0].mem = cs47l92_dsp1_regions; + cs47l92->core.adsp[0].num_mems = ARRAY_SIZE(cs47l92_dsp1_regions); + + cs47l92->core.adsp[0].lock_regions = WM_ADSP2_REGION_1_9; + + ret = wm_adsp2_init(&cs47l92->core.adsp[0]); + if (ret != 0) + goto error_dsp_irq; + + ret = madera_init_bus_error_irq(&cs47l92->core, 0, wm_adsp2_bus_error); + if (ret != 0) { + wm_adsp2_remove(&cs47l92->core.adsp[0]); + goto error_adsp; + } + + madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, + &cs47l92->fll[0]); + madera_init_fll(madera, 2, MADERA_FLL2_CONTROL_1 - 1, + &cs47l92->fll[1]); + + for (i = 0; i < ARRAY_SIZE(cs47l92_dai); i++) + madera_init_dai(&cs47l92->core, i); + + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(cs47l92_digital_vu); i++) + regmap_update_bits(madera->regmap, cs47l92_digital_vu[i], + CS47L92_DIG_VU, CS47L92_DIG_VU); + + pm_runtime_enable(&pdev->dev); + pm_runtime_idle(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_cs47l92, + cs47l92_dai, + ARRAY_SIZE(cs47l92_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + goto error_pm_runtime; + } + + return ret; + +error_pm_runtime: + pm_runtime_disable(&pdev->dev); + madera_free_bus_error_irq(&cs47l92->core, 0); +error_adsp: + wm_adsp2_remove(&cs47l92->core.adsp[0]); +error_dsp_irq: + madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l92); +error_core: + madera_core_free(&cs47l92->core); + + return ret; +} + +static int cs47l92_remove(struct platform_device *pdev) +{ + struct cs47l92 *cs47l92 = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + + madera_free_bus_error_irq(&cs47l92->core, 0); + wm_adsp2_remove(&cs47l92->core.adsp[0]); + + madera_set_irq_wake(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, 0); + madera_free_irq(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l92); + + madera_core_free(&cs47l92->core); + + return 0; +} + +static struct platform_driver cs47l92_codec_driver = { + .driver = { + .name = "cs47l92-codec", + }, + .probe = &cs47l92_probe, + .remove = &cs47l92_remove, +}; + +module_platform_driver(cs47l92_codec_driver); + +MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); +MODULE_DESCRIPTION("ASoC CS47L92 driver"); +MODULE_AUTHOR("Stuart Henderson "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:cs47l92-codec"); diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 1c00e2a115bc..52639811cc52 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -87,6 +87,16 @@ #define MADERA_FLLAO_MIN_N 4 #define MADERA_FLLAO_MAX_N 1023 #define MADERA_FLLAO_MAX_FBDIV 254 +#define MADERA_FLLHJ_INT_MAX_N 1023 +#define MADERA_FLLHJ_INT_MIN_N 1 +#define MADERA_FLLHJ_FRAC_MAX_N 255 +#define MADERA_FLLHJ_FRAC_MIN_N 4 +#define MADERA_FLLHJ_LOW_THRESH 192000 +#define MADERA_FLLHJ_MID_THRESH 1152000 +#define MADERA_FLLHJ_MAX_THRESH 13000000 +#define MADERA_FLLHJ_LOW_GAINS 0x23f0 +#define MADERA_FLLHJ_MID_GAINS 0x22f2 +#define MADERA_FLLHJ_HIGH_GAINS 0x21f0 #define MADERA_FLL_SYNCHRONISER_OFFS 0x10 #define CS47L35_FLL_SYNCHRONISER_OFFS 0xE @@ -96,6 +106,7 @@ #define MADERA_FLL_CONTROL_4_OFFS 0x4 #define MADERA_FLL_CONTROL_5_OFFS 0x5 #define MADERA_FLL_CONTROL_6_OFFS 0x6 +#define MADERA_FLL_GAIN_OFFS 0x8 #define MADERA_FLL_CONTROL_7_OFFS 0x9 #define MADERA_FLL_EFS_2_OFFS 0xA #define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1 @@ -107,6 +118,9 @@ #define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7 #define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9 #define MADERA_FLL_GPIO_CLOCK_OFFS 0xA +#define MADERA_FLL_CONTROL_10_OFFS 0xA +#define MADERA_FLL_CONTROL_11_OFFS 0xB +#define MADERA_FLL1_DIGITAL_TEST_1_OFFS 0xD #define MADERA_FLLAO_CONTROL_1_OFFS 0x1 #define MADERA_FLLAO_CONTROL_2_OFFS 0x2 @@ -1871,6 +1885,18 @@ const struct soc_enum madera_asrc1_rate[] = { }; EXPORT_SYMBOL_GPL(madera_asrc1_rate); +const struct soc_enum madera_asrc1_bidir_rate[] = { + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1, + MADERA_ASRC1_RATE1_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), + SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2, + MADERA_ASRC1_RATE2_SHIFT, 0xf, + MADERA_RATE_ENUM_SIZE, + madera_rate_text, madera_rate_val), +}; +EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate); + const struct soc_enum madera_asrc2_rate[] = { SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1, MADERA_ASRC2_RATE1_SHIFT, 0xf, @@ -2250,6 +2276,9 @@ int madera_out_ev(struct snd_soc_dapm_widget *w, switch (madera->type) { case CS47L90: case CS47L91: + case CS42L92: + case CS47L92: + case CS47L93: out_up_delay = 6; break; default: @@ -2365,9 +2394,17 @@ int madera_hp_ev(struct snd_soc_dapm_widget *w, madera->hp_ena &= ~mask; madera->hp_ena |= val; - /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ - regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); - ep_sel &= MADERA_EP_SEL_MASK; + switch (madera->type) { + case CS42L92: + case CS47L92: + case CS47L93: + break; + default: + /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ + regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); + ep_sel &= MADERA_EP_SEL_MASK; + break; + } /* Force off if HPDET has disabled the clamp for this output */ if (!ep_sel && @@ -2543,6 +2580,58 @@ static int madera_get_dspclk_setting(struct madera *madera, } } +static int madera_set_outclk(struct snd_soc_component *component, + unsigned int source, unsigned int freq) +{ + int div, div_inc, rate; + + switch (source) { + case MADERA_OUTCLK_SYSCLK: + dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n"); + snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1, + MADERA_OUT_CLK_SRC_MASK, source); + return 0; + case MADERA_OUTCLK_ASYNCCLK: + dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n"); + snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1, + MADERA_OUT_CLK_SRC_MASK, source); + return 0; + case MADERA_OUTCLK_MCLK1: + case MADERA_OUTCLK_MCLK2: + case MADERA_OUTCLK_MCLK3: + break; + default: + return -EINVAL; + } + + if (freq % 4000) + rate = 5644800; + else + rate = 6144000; + + div = 1; + div_inc = 0; + while (div <= 8) { + if (freq / div == rate && !(freq % div)) { + dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate); + snd_soc_component_update_bits(component, + MADERA_OUTPUT_RATE_1, + MADERA_OUT_EXT_CLK_DIV_MASK | + MADERA_OUT_CLK_SRC_MASK, + (div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) | + source); + return 0; + } + div_inc++; + div *= 2; + } + + dev_err(component->dev, + "Unable to generate %dHz OUTCLK from %dHz MCLK\n", + rate, freq); + return -EINVAL; +} + int madera_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { @@ -2579,6 +2668,8 @@ int madera_set_sysclk(struct snd_soc_component *component, int clk_id, case MADERA_CLK_OPCLK: case MADERA_CLK_ASYNC_OPCLK: return madera_set_opclk(component, clk_id, freq); + case MADERA_CLK_OUTCLK: + return madera_set_outclk(component, source, freq); default: return -EINVAL; } @@ -2792,6 +2883,10 @@ static const unsigned int madera_sr_vals[] = { #define MADERA_192K_44K1_RATE_MASK 0x003E00 #define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \ MADERA_192K_44K1_RATE_MASK) +#define MADERA_384K_48K_RATE_MASK 0x0F007E +#define MADERA_384K_44K1_RATE_MASK 0x007E00 +#define MADERA_384K_RATE_MASK (MADERA_384K_48K_RATE_MASK | \ + MADERA_384K_44K1_RATE_MASK) static const struct snd_pcm_hw_constraint_list madera_constraint = { .count = ARRAY_SIZE(madera_sr_vals), @@ -2804,6 +2899,7 @@ static int madera_startup(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct madera_priv *priv = snd_soc_component_get_drvdata(component); struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; + struct madera *madera = priv->madera; unsigned int base_rate; if (!substream->runtime) @@ -2823,12 +2919,26 @@ static int madera_startup(struct snd_pcm_substream *substream, return 0; } - if (base_rate == 0) - dai_priv->constraint.mask = MADERA_192K_RATE_MASK; - else if (base_rate % 4000) - dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; - else - dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; + switch (madera->type) { + case CS42L92: + case CS47L92: + case CS47L93: + if (base_rate == 0) + dai_priv->constraint.mask = MADERA_384K_RATE_MASK; + else if (base_rate % 4000) + dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK; + else + dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK; + break; + default: + if (base_rate == 0) + dai_priv->constraint.mask = MADERA_192K_RATE_MASK; + else if (base_rate % 4000) + dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; + else + dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; + break; + } return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, @@ -4149,6 +4259,308 @@ int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, } EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk); +static int madera_fllhj_disable(struct madera_fll *fll) +{ + struct madera *madera = fll->madera; + bool change; + + madera_fll_dbg(fll, "Disabling FLL\n"); + + /* Disable lockdet, but don't set ctrl_upd update but. This allows the + * lock status bit to clear as normal, but should the FLL be enabled + * again due to a control clock being required, the lock won't re-assert + * as the FLL config registers are automatically applied when the FLL + * enables. + */ + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_11_OFFS, + MADERA_FLL1_LOCKDET_MASK, 0); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK); + regmap_update_bits_check(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_ENA_MASK, 0, &change); + + madera_wait_for_fll(fll, false); + + /* ctrl_up gates the writes to all the fll's registers, setting it to 0 + * here ensures that after a runtime suspend/resume cycle when one + * enables the fll then ctrl_up is the last bit that is configured + * by the fll enable code rather than the cache sync operation which + * would have updated it much earlier before writing out all fll + * registers + */ + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_2_OFFS, + MADERA_FLL1_CTRL_UPD_MASK, 0); + + if (change) + pm_runtime_put_autosuspend(madera->dev); + + return 0; +} + +static int madera_fllhj_apply(struct madera_fll *fll, int fin) +{ + struct madera *madera = fll->madera; + int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd; + bool frac = false; + unsigned int fll_n, min_n, max_n, ratio, theta, lambda; + unsigned int gains, val, num; + + madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout); + + for (refdiv = 0; refdiv < 4; refdiv++) + if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH) + break; + + fref = fin / (1 << refdiv); + + /* Use simple heuristic approach to find a configuration that + * should work for most input clocks. + */ + fast_clk = 0; + fout = fll->fout; + frac = fout % fref; + + if (fref < MADERA_FLLHJ_LOW_THRESH) { + lockdet_thr = 2; + gains = MADERA_FLLHJ_LOW_GAINS; + if (frac) + fbdiv = 256; + else + fbdiv = 4; + } else if (fref < MADERA_FLLHJ_MID_THRESH) { + lockdet_thr = 8; + gains = MADERA_FLLHJ_MID_GAINS; + fbdiv = 1; + } else { + lockdet_thr = 8; + gains = MADERA_FLLHJ_HIGH_GAINS; + fbdiv = 1; + /* For high speed input clocks, enable 300MHz fast oscillator + * when we're in fractional divider mode. + */ + if (frac) { + fast_clk = 0x3; + fout = fll->fout * 6; + } + } + /* Use high performance mode for fractional configurations. */ + if (frac) { + hp = 0x3; + min_n = MADERA_FLLHJ_FRAC_MIN_N; + max_n = MADERA_FLLHJ_FRAC_MAX_N; + } else { + hp = 0x0; + min_n = MADERA_FLLHJ_INT_MIN_N; + max_n = MADERA_FLLHJ_INT_MAX_N; + } + + ratio = fout / fref; + + madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n", + refdiv, fref, frac); + + while (ratio / fbdiv < min_n) { + fbdiv /= 2; + if (fbdiv < 1) { + madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv); + return -EINVAL; + } + } + while (frac && (ratio / fbdiv > max_n)) { + fbdiv *= 2; + if (fbdiv >= 1024) { + madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv); + return -EINVAL; + } + } + + madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n", + lockdet_thr, hp, fbdiv); + + /* Calculate N.K values */ + fllgcd = gcd(fout, fbdiv * fref); + num = fout / fllgcd; + lambda = (fref * fbdiv) / fllgcd; + fll_n = num / lambda; + theta = num % lambda; + + madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n", + fll_n, fllgcd, theta, lambda); + + /* Some sanity checks before any registers are written. */ + if (fll_n < min_n || fll_n > max_n) { + madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n", + frac ? "fractional" : "integer", min_n, max_n, + fll_n); + return -EINVAL; + } + if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) { + madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n", + frac ? "fractional" : "integer", fbdiv); + return -EINVAL; + } + + /* clear the ctrl_upd bit to guarantee we write to it later. */ + regmap_write(madera->regmap, + fll->base + MADERA_FLL_CONTROL_2_OFFS, + fll_n << MADERA_FLL1_N_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_3_OFFS, + MADERA_FLL1_THETA_MASK, + theta << MADERA_FLL1_THETA_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_4_OFFS, + MADERA_FLL1_LAMBDA_MASK, + lambda << MADERA_FLL1_LAMBDA_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_5_OFFS, + MADERA_FLL1_FB_DIV_MASK, + fbdiv << MADERA_FLL1_FB_DIV_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_6_OFFS, + MADERA_FLL1_REFCLK_DIV_MASK, + refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_GAIN_OFFS, + 0xffff, + gains); + val = hp << MADERA_FLL1_HP_SHIFT; + val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT; + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_10_OFFS, + MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK, + val); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_11_OFFS, + MADERA_FLL1_LOCKDET_THR_MASK, + lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT); + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS, + MADERA_FLL1_SYNC_EFS_ENA_MASK | + MADERA_FLL1_CLK_VCO_FAST_SRC_MASK, + fast_clk); + + return 0; +} + +static int madera_fllhj_enable(struct madera_fll *fll) +{ + struct madera *madera = fll->madera; + int already_enabled = madera_is_enabled_fll(fll, fll->base); + int ret; + + if (already_enabled < 0) + return already_enabled; + + if (!already_enabled) + pm_runtime_get_sync(madera->dev); + + madera_fll_dbg(fll, "Enabling FLL, initially %s\n", + already_enabled ? "enabled" : "disabled"); + + /* FLLn_HOLD must be set before configuring any registers */ + regmap_update_bits(fll->madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_HOLD_MASK, + MADERA_FLL1_HOLD_MASK); + + /* Apply refclk */ + ret = madera_fllhj_apply(fll, fll->ref_freq); + if (ret) { + madera_fll_err(fll, "Failed to set FLL: %d\n", ret); + goto out; + } + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + CS47L92_FLL1_REFCLK_SRC_MASK, + fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT); + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_ENA_MASK, + MADERA_FLL1_ENA_MASK); + +out: + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_11_OFFS, + MADERA_FLL1_LOCKDET_MASK, + MADERA_FLL1_LOCKDET_MASK); + + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_2_OFFS, + MADERA_FLL1_CTRL_UPD_MASK, + MADERA_FLL1_CTRL_UPD_MASK); + + /* Release the hold so that flln locks to external frequency */ + regmap_update_bits(madera->regmap, + fll->base + MADERA_FLL_CONTROL_1_OFFS, + MADERA_FLL1_HOLD_MASK, + 0); + + if (!already_enabled) + madera_wait_for_fll(fll, true); + + return 0; +} + +static int madera_fllhj_validate(struct madera_fll *fll, + unsigned int ref_in, + unsigned int fout) +{ + if (fout && !ref_in) { + madera_fll_err(fll, "fllout set without valid input clk\n"); + return -EINVAL; + } + + if (fll->fout && fout != fll->fout) { + madera_fll_err(fll, "Can't change output on active FLL\n"); + return -EINVAL; + } + + if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) { + madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in); + return -EINVAL; + } + + return 0; +} + +int madera_fllhj_set_refclk(struct madera_fll *fll, int source, + unsigned int fin, unsigned int fout) +{ + int ret = 0; + + /* To remain consistent with previous FLLs, we expect fout to be + * provided in the form of the required sysclk rate, which is + * 2x the calculated fll out. + */ + if (fout) + fout /= 2; + + if (fll->ref_src == source && fll->ref_freq == fin && + fll->fout == fout) + return 0; + + if (fin && fout && madera_fllhj_validate(fll, fin, fout)) + return -EINVAL; + + fll->ref_src = source; + fll->ref_freq = fin; + fll->fout = fout; + + if (fout) + ret = madera_fllhj_enable(fll); + else + madera_fllhj_disable(fll); + + return ret; +} +EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk); + /** * madera_set_output_mode - Set the mode of the specified output * diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index 0af66f280770..1f3e8e230cf2 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h @@ -47,6 +47,7 @@ #define MADERA_CLK_SYSCLK_3 6 #define MADERA_CLK_ASYNCCLK_2 7 #define MADERA_CLK_DSPCLK 8 +#define MADERA_CLK_OUTCLK 9 #define MADERA_CLK_SRC_MCLK1 0x0 #define MADERA_CLK_SRC_MCLK2 0x1 @@ -61,6 +62,12 @@ #define MADERA_CLK_SRC_AIF4BCLK 0xB #define MADERA_CLK_SRC_FLLAO 0xF +#define MADERA_OUTCLK_SYSCLK 0 +#define MADERA_OUTCLK_ASYNCCLK 1 +#define MADERA_OUTCLK_MCLK1 4 +#define MADERA_OUTCLK_MCLK2 5 +#define MADERA_OUTCLK_MCLK3 6 + #define MADERA_MIXER_VOL_MASK 0x00FE #define MADERA_MIXER_VOL_SHIFT 1 #define MADERA_MIXER_VOL_WIDTH 7 @@ -326,6 +333,7 @@ extern const struct soc_enum madera_sample_rate[]; extern const struct soc_enum madera_isrc_fsl[]; extern const struct soc_enum madera_isrc_fsh[]; extern const struct soc_enum madera_asrc1_rate[]; +extern const struct soc_enum madera_asrc1_bidir_rate[]; extern const struct soc_enum madera_asrc2_rate[]; extern const struct soc_enum madera_dfc_width[]; extern const struct soc_enum madera_dfc_type[]; @@ -403,6 +411,8 @@ int madera_set_fll_syncclk(struct madera_fll *fll, int source, unsigned int fref, unsigned int fout); int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, unsigned int fin, unsigned int fout); +int madera_fllhj_set_refclk(struct madera_fll *fll, int source, + unsigned int fin, unsigned int fout); int madera_core_init(struct madera_priv *priv); int madera_core_free(struct madera_priv *priv); -- GitLab From 1889c6e6ac6e15b3631d7e320f740219aa46504a Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Wed, 24 Jul 2019 17:22:36 +0800 Subject: [PATCH 0698/7155] regulator: act8865: fix ptr_ret.cocci warnings drivers/regulator/act8865-regulator.c:447:8-14: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci Fixes: 2d09a79bf637 ("regulator: act8865: Add support for act8600 charger") CC: Maarten ter Huurne Signed-off-by: kbuild test robot Link: https://lore.kernel.org/r/20190724092236.witxtfmubun25l2t@1905cc33b6dd Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index b515e0785d67..6a90d3c7a452 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -465,7 +465,7 @@ static int act8600_charger_probe(struct device *dev, struct regmap *regmap) charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg); - return IS_ERR(charger) ? PTR_ERR(charger) : 0; + return PTR_ERR_OR_ZERO(charger); } static int act8865_pmic_probe(struct i2c_client *client, -- GitLab From 1c38bdc96941fcf8ce9c32d1c45eca5547abd45e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Jul 2019 12:13:11 -0400 Subject: [PATCH 0699/7155] MAINTAINERS: update EDAC entry to reflect current tree and maintainers Tony will start to officially maintain EDAC trees. Also, we'll be using a single tree for the EDAC development. Signed-off-by: Mauro Carvalho Chehab Acked-by: Borislav Petkov Acked-by: Tony Luck --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..7c22905b5aba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5781,10 +5781,10 @@ F: drivers/edac/thunderx_edac* EDAC-CORE M: Borislav Petkov M: Mauro Carvalho Chehab +M: Tony Luck R: James Morse L: linux-edac@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras.git edac-for-next S: Supported F: Documentation/admin-guide/ras.rst F: Documentation/driver-api/edac.rst -- GitLab From 68c907f10cd816cad2287167a1a1d77914a6d466 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:44 +0200 Subject: [PATCH 0700/7155] ASoC: codec2codec: run callbacks in order When handling dai_link events on codec to codec links, run all .startup() callbacks on sinks and sources before running any .hw_params(). Same goes for hw_free() and shutdown(). This is closer to the behavior of regular dai links Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1d04612601ad..034b31fd2ecb 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3835,11 +3835,6 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, goto out; } source->active++; - ret = snd_soc_dai_hw_params(source, &substream, params); - if (ret < 0) - goto out; - - dapm_update_dai_unlocked(&substream, params, source); } substream.stream = SNDRV_PCM_STREAM_PLAYBACK; @@ -3853,6 +3848,23 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, goto out; } sink->active++; + } + + substream.stream = SNDRV_PCM_STREAM_CAPTURE; + snd_soc_dapm_widget_for_each_source_path(w, path) { + source = path->source->priv; + + ret = snd_soc_dai_hw_params(source, &substream, params); + if (ret < 0) + goto out; + + dapm_update_dai_unlocked(&substream, params, source); + } + + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + snd_soc_dapm_widget_for_each_sink_path(w, path) { + sink = path->sink->priv; + ret = snd_soc_dai_hw_params(sink, &substream, params); if (ret < 0) goto out; @@ -3889,9 +3901,18 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, substream.stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; - snd_soc_dai_hw_free(source, &substream); + } + + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + snd_soc_dapm_widget_for_each_sink_path(w, path) { + sink = path->sink->priv; + snd_soc_dai_hw_free(sink, &substream); + } + substream.stream = SNDRV_PCM_STREAM_CAPTURE; + snd_soc_dapm_widget_for_each_source_path(w, path) { + source = path->source->priv; source->active--; snd_soc_dai_shutdown(source, &substream); } @@ -3899,9 +3920,6 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, substream.stream = SNDRV_PCM_STREAM_PLAYBACK; snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - - snd_soc_dai_hw_free(sink, &substream); - sink->active--; snd_soc_dai_shutdown(sink, &substream); } -- GitLab From 054d65004c6a008dfefbdae4fc1b46a3ad4e94c1 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:45 +0200 Subject: [PATCH 0701/7155] ASoC: codec2codec: name link using stream direction At the moment, codec to codec dai link widgets are named after the cpu dai and the 1st codec valid on the link. This might be confusing if there is multiple valid codecs on the link for one stream direction. Instead, use the dai link name and the stream direction to name the the dai link widget Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 034b31fd2ecb..7db4abd9a0a5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4056,8 +4056,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, static struct snd_soc_dapm_widget * snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, - struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) + char *id) { struct snd_soc_dapm_widget template; struct snd_soc_dapm_widget *w; @@ -4067,7 +4066,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, int ret; link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s", - source->name, sink->name); + rtd->dai_link->name, id); if (!link_name) return ERR_PTR(-ENOMEM); @@ -4247,15 +4246,13 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, } for_each_rtd_codec_dai(rtd, i, codec_dai) { - /* connect BE DAI playback if widgets are valid */ codec = codec_dai->playback_widget; if (playback_cpu && codec) { if (!playback) { playback = snd_soc_dapm_new_dai(card, rtd, - playback_cpu, - codec); + "playback"); if (IS_ERR(playback)) { dev_err(rtd->dev, "ASoC: Failed to create DAI %s: %ld\n", @@ -4284,8 +4281,7 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, if (codec && capture_cpu) { if (!capture) { capture = snd_soc_dapm_new_dai(card, rtd, - codec, - capture_cpu); + "capture"); if (IS_ERR(capture)) { dev_err(rtd->dev, "ASoC: Failed to create DAI %s: %ld\n", -- GitLab From 3dcfb397dad2ad55bf50de3c5d5a57090d35a18a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:46 +0200 Subject: [PATCH 0702/7155] ASoC: codec2codec: deal with params when necessary When there is an event on codec to codec dai_link, we only need to deal with params if the event is SND_SOC_DAPM_PRE_PMU, when .hw_params() is called. For the other events, it is useless. Also, dealing with the codec to codec params just before calling .hw_params() callbacks give change to either party on the link to alter params content in .startup(), which might be useful in some cases Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-4-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 159 +++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7db4abd9a0a5..6dcaf9ff6eb5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3764,25 +3764,59 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); -static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int +snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, + struct snd_pcm_substream *substream) { struct snd_soc_dapm_path *path; struct snd_soc_dai *source, *sink; - struct snd_soc_pcm_runtime *rtd = w->priv; - const struct snd_soc_pcm_stream *config; - struct snd_pcm_substream substream; + struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_hw_params *params = NULL; - struct snd_pcm_runtime *runtime = NULL; + const struct snd_soc_pcm_stream *config = NULL; unsigned int fmt; - int ret = 0; + int ret; - config = rtd->dai_link->params + rtd->params_select; + params = kzalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; - if (WARN_ON(!config) || - WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || - list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) - return -EINVAL; + substream->stream = SNDRV_PCM_STREAM_CAPTURE; + snd_soc_dapm_widget_for_each_source_path(w, path) { + source = path->source->priv; + + ret = snd_soc_dai_startup(source, substream); + if (ret < 0) { + dev_err(source->dev, + "ASoC: startup() failed: %d\n", ret); + goto out; + } + source->active++; + } + + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; + snd_soc_dapm_widget_for_each_sink_path(w, path) { + sink = path->sink->priv; + + ret = snd_soc_dai_startup(sink, substream); + if (ret < 0) { + dev_err(sink->dev, + "ASoC: startup() failed: %d\n", ret); + goto out; + } + sink->active++; + } + + /* + * Note: getting the config after .startup() gives a chance to + * either party on the link to alter the configuration if + * necessary + */ + config = rtd->dai_link->params + rtd->params_select; + if (WARN_ON(!config)) { + dev_err(w->dapm->dev, "ASoC: link config missing\n"); + ret = -EINVAL; + goto out; + } /* Be a little careful as we don't want to overflow the mask array */ if (config->formats) { @@ -3790,27 +3824,62 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, } else { dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n", config->formats); - fmt = 0; - } - /* Currently very limited parameter selection */ - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - ret = -ENOMEM; + ret = -EINVAL; goto out; } - snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); + snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = config->rate_min; hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = config->rate_max; - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min = config->channels_min; hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max = config->channels_max; + substream->stream = SNDRV_PCM_STREAM_CAPTURE; + snd_soc_dapm_widget_for_each_source_path(w, path) { + source = path->source->priv; + + ret = snd_soc_dai_hw_params(source, substream, params); + if (ret < 0) + goto out; + + dapm_update_dai_unlocked(substream, params, source); + } + + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; + snd_soc_dapm_widget_for_each_sink_path(w, path) { + sink = path->sink->priv; + + ret = snd_soc_dai_hw_params(sink, substream, params); + if (ret < 0) + goto out; + + dapm_update_dai_unlocked(substream, params, sink); + } + +out: + kfree(params); + return 0; +} + +static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_dapm_path *path; + struct snd_soc_dai *source, *sink; + struct snd_soc_pcm_runtime *rtd = w->priv; + struct snd_pcm_substream substream; + struct snd_pcm_runtime *runtime = NULL; + int ret = 0; + + if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || + list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) + return -EINVAL; + memset(&substream, 0, sizeof(substream)); /* Allocate a dummy snd_pcm_runtime for startup() and other ops() */ @@ -3824,53 +3893,10 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - substream.stream = SNDRV_PCM_STREAM_CAPTURE; - snd_soc_dapm_widget_for_each_source_path(w, path) { - source = path->source->priv; - - ret = snd_soc_dai_startup(source, &substream); - if (ret < 0) { - dev_err(source->dev, - "ASoC: startup() failed: %d\n", ret); - goto out; - } - source->active++; - } - - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - snd_soc_dapm_widget_for_each_sink_path(w, path) { - sink = path->sink->priv; - - ret = snd_soc_dai_startup(sink, &substream); - if (ret < 0) { - dev_err(sink->dev, - "ASoC: startup() failed: %d\n", ret); - goto out; - } - sink->active++; - } - - substream.stream = SNDRV_PCM_STREAM_CAPTURE; - snd_soc_dapm_widget_for_each_source_path(w, path) { - source = path->source->priv; - - ret = snd_soc_dai_hw_params(source, &substream, params); - if (ret < 0) - goto out; - - dapm_update_dai_unlocked(&substream, params, source); - } - - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - snd_soc_dapm_widget_for_each_sink_path(w, path) { - sink = path->sink->priv; - - ret = snd_soc_dai_hw_params(sink, &substream, params); - if (ret < 0) - goto out; + ret = snd_soc_dai_link_event_pre_pmu(w, &substream); + if (ret < 0) + goto out; - dapm_update_dai_unlocked(&substream, params, sink); - } break; case SND_SOC_DAPM_POST_PMU: @@ -3932,7 +3958,6 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, out: kfree(runtime); - kfree(params); return ret; } -- GitLab From b2b998c0f944993c9ef435569651e407d607af41 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:03 +0200 Subject: [PATCH 0703/7155] leds: class: Improve LED and LED flash class registration API Replace of_led_classdev_register() with led_classdev_register_ext(), which accepts easily extendable struct led_init_data, instead of the fixed struct device_node argument. The latter can be now passed in an fwnode property of the struct led_init_data. The modification is driven by the need for passing additional arguments required for the forthcoming generic mechanism for composing LED names. Currently the LED name is conveyed in the "name" char pointer property of the struct led_classdev. This is redundant since LED class device name is accessible throughout the whole LED class device life time via associated struct device's kobj->name property. The change will not break any existing clients since the patch alters also existing led_classdev{_flash}_register() macro wrappers, that pass NULL in place of init_data, which leads to using legacy name initialization path basing on the struct led_classdev's "name" property. Three existing users of devm_of_led_classdev_registers() are modified to use devm_led_classdev_register(), which will not impact their operation since they in fact didn't need to pass struct device_node on registration from the beginning. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Acked-by: Pavel Machek --- drivers/leds/led-class-flash.c | 9 +++++---- drivers/leds/led-class.c | 29 ++++++++++++++++------------ drivers/leds/leds-cr0014114.c | 3 +-- drivers/leds/leds-gpio.c | 2 +- drivers/leds/leds-max77650.c | 2 +- drivers/leds/leds-pwm.c | 3 +-- include/linux/led-class-flash.h | 15 ++++++++++----- include/linux/leds.h | 34 +++++++++++++++++++++++---------- 8 files changed, 60 insertions(+), 37 deletions(-) diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c index 94980c654d89..60c3de5c6b9f 100644 --- a/drivers/leds/led-class-flash.c +++ b/drivers/leds/led-class-flash.c @@ -282,8 +282,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev) led_cdev->groups = flash_groups; } -int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev) +int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data) { struct led_classdev *led_cdev; const struct led_flash_ops *ops; @@ -309,13 +310,13 @@ int led_classdev_flash_register(struct device *parent, } /* Register led class device */ - ret = led_classdev_register(parent, led_cdev); + ret = led_classdev_register_ext(parent, led_cdev, init_data); if (ret < 0) return ret; return 0; } -EXPORT_SYMBOL_GPL(led_classdev_flash_register); +EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext); void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev) { diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..242122f49333 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -242,14 +243,16 @@ static int led_classdev_next_name(const char *init_name, char *name, } /** - * of_led_classdev_register - register a new object of led_classdev class. + * led_classdev_register_ext - register a new object of led_classdev class + * with init data. * * @parent: parent of LED device * @led_cdev: the led_classdev structure for this device. - * @np: DT node describing this LED + * @init_data: LED class device initialization data */ -int of_led_classdev_register(struct device *parent, struct device_node *np, - struct led_classdev *led_cdev) +int led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data) { char name[LED_MAX_NAME_SIZE]; int ret; @@ -266,7 +269,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np, mutex_unlock(&led_cdev->led_access); return PTR_ERR(led_cdev->dev); } - led_cdev->dev->of_node = np; + if (init_data && init_data->fwnode) + led_cdev->dev->of_node = to_of_node(init_data->fwnode); if (ret) dev_warn(parent, "Led %s renamed to %s due to name collision", @@ -311,7 +315,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np, return 0; } -EXPORT_SYMBOL_GPL(of_led_classdev_register); +EXPORT_SYMBOL_GPL(led_classdev_register_ext); /** * led_classdev_unregister - unregisters a object of led_properties class. @@ -356,14 +360,15 @@ static void devm_led_classdev_release(struct device *dev, void *res) } /** - * devm_of_led_classdev_register - resource managed led_classdev_register() + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext() * * @parent: parent of LED device * @led_cdev: the led_classdev structure for this device. + * @init_data: LED class device initialization data */ -int devm_of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev) +int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data) { struct led_classdev **dr; int rc; @@ -372,7 +377,7 @@ int devm_of_led_classdev_register(struct device *parent, if (!dr) return -ENOMEM; - rc = of_led_classdev_register(parent, np, led_cdev); + rc = led_classdev_register_ext(parent, led_cdev, init_data); if (rc) { devres_free(dr); return rc; @@ -383,7 +388,7 @@ int devm_of_led_classdev_register(struct device *parent, return 0; } -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register); +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext); static int devm_led_classdev_match(struct device *dev, void *res, void *data) { diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index 0e4262462cb9..1c82152764d2 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) led->ldev.max_brightness = CR_MAX_BRIGHTNESS; led->ldev.brightness_set_blocking = cr0014114_set_sync; - ret = devm_of_led_classdev_register(priv->dev, np, - &led->ldev); + ret = devm_led_classdev_register(priv->dev, &led->ldev); if (ret) { dev_err(priv->dev, "failed to register LED device %s, err %d", diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index bdc98ddca1dc..8f463c912db8 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -108,7 +108,7 @@ static int create_gpio_led(const struct gpio_led *template, if (ret < 0) return ret; - return devm_of_led_classdev_register(parent, np, &led_dat->cdev); + return devm_led_classdev_register(parent, &led_dat->cdev); } struct gpio_leds_priv { diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 04738324b3e6..5a14f9775b0e 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -118,7 +118,7 @@ static int max77650_led_probe(struct platform_device *pdev) of_property_read_string(child, "linux,default-trigger", &led->cdev.default_trigger); - rv = devm_of_led_classdev_register(dev, child, &led->cdev); + rv = devm_led_classdev_register(dev, &led->cdev); if (rv) goto err_node_put; diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 48d068f80f11..d0e1f2710351 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -111,8 +111,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, if (!led_data->period && (led->pwm_period_ns > 0)) led_data->period = led->pwm_period_ns; - ret = devm_of_led_classdev_register(dev, to_of_node(fwnode), - &led_data->cdev); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret == 0) { priv->num_leds++; led_pwm_set(&led_data->cdev, led_data->cdev.brightness); diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h index f52713f0a269..1e824963af17 100644 --- a/include/linux/led-class-flash.h +++ b/include/linux/led-class-flash.h @@ -86,15 +86,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev( } /** - * led_classdev_flash_register - register a new object of led_classdev class - * with support for flash LEDs - * @parent: the flash LED to register + * led_classdev_flash_register_ext - register a new object of LED class with + * init data and with support for flash LEDs + * @parent: LED flash controller device this flash LED is driven by * @fled_cdev: the led_classdev_flash structure for this device + * @init_data: the LED class flash device initialization data * * Returns: 0 on success or negative error value on failure */ -extern int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev); +extern int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data); + +#define led_classdev_flash_register(parent, fled_cdev) \ + led_classdev_flash_register_ext(parent, fled_cdev, NULL) /** * led_classdev_flash_unregister - unregisters an object of led_classdev class diff --git a/include/linux/leds.h b/include/linux/leds.h index 9b2bf574a17a..2bbe8a38fe39 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -30,6 +30,11 @@ enum led_brightness { LED_FULL = 255, }; +struct led_init_data { + /* device fwnode handle */ + struct fwnode_handle *fwnode; +}; + struct led_classdev { const char *name; enum led_brightness brightness; @@ -125,16 +130,25 @@ struct led_classdev { struct mutex led_access; }; -extern int of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define led_classdev_register(parent, led_cdev) \ - of_led_classdev_register(parent, NULL, led_cdev) -extern int devm_of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define devm_led_classdev_register(parent, led_cdev) \ - devm_of_led_classdev_register(parent, NULL, led_cdev) +/** + * led_classdev_register_ext - register a new object of LED class with + * init data + * @parent: LED controller device this LED is driven by + * @led_cdev: the led_classdev structure for this device + * @init_data: the LED class device initialization data + * + * Returns: 0 on success or negative error value on failure + */ +extern int led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); +#define led_classdev_register(parent, led_cdev) \ + led_classdev_register_ext(parent, led_cdev, NULL) +extern int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); +#define devm_led_classdev_register(parent, led_cdev) \ + devm_led_classdev_register_ext(parent, led_cdev, NULL) extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void devm_led_classdev_unregister(struct device *parent, struct led_classdev *led_cdev); -- GitLab From 853a78a7d6c7734f5aaa9c2a866cbd1f2a658892 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0704/7155] dt-bindings: leds: Add LED_COLOR_ID definitions Add common LED color identifiers. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Reviewed-by: Rob Herring Acked-by: Pavel Machek Reviewed-by: Dan Murphy --- include/dt-bindings/leds/common.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h index e171d0a6beb2..217ee9e0dd6c 100644 --- a/include/dt-bindings/leds/common.h +++ b/include/dt-bindings/leds/common.h @@ -19,4 +19,15 @@ #define LEDS_BOOST_ADAPTIVE 1 #define LEDS_BOOST_FIXED 2 +/* Standard LED colors */ +#define LED_COLOR_ID_WHITE 0 +#define LED_COLOR_ID_RED 1 +#define LED_COLOR_ID_GREEN 2 +#define LED_COLOR_ID_BLUE 3 +#define LED_COLOR_ID_AMBER 4 +#define LED_COLOR_ID_VIOLET 5 +#define LED_COLOR_ID_YELLOW 6 +#define LED_COLOR_ID_IR 7 +#define LED_COLOR_ID_MAX 8 + #endif /* __DT_BINDINGS_LEDS_H */ -- GitLab From 2f430310f7b4216408aaae57c55a596091c47846 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0705/7155] dt-bindings: leds: Add LED_FUNCTION definitions Add initial set of common LED function definitions. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Reviewed-by: Rob Herring Acked-by: Pavel Machek Reviewed-by: Dan Murphy --- include/dt-bindings/leds/common.h | 44 ++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h index 217ee9e0dd6c..9e1256a7c1bf 100644 --- a/include/dt-bindings/leds/common.h +++ b/include/dt-bindings/leds/common.h @@ -3,8 +3,9 @@ * This header provides macros for the common LEDs device tree bindings. * * Copyright (C) 2015, Samsung Electronics Co., Ltd. - * * Author: Jacek Anaszewski + * + * Copyright (C) 2019 Jacek Anaszewski */ #ifndef __DT_BINDINGS_LEDS_H @@ -30,4 +31,45 @@ #define LED_COLOR_ID_IR 7 #define LED_COLOR_ID_MAX 8 +/* Standard LED functions */ +#define LED_FUNCTION_ACTIVITY "activity" +#define LED_FUNCTION_ALARM "alarm" +#define LED_FUNCTION_BACKLIGHT "backlight" +#define LED_FUNCTION_BLUETOOTH "bluetooth" +#define LED_FUNCTION_BOOT "boot" +#define LED_FUNCTION_CPU "cpu" +#define LED_FUNCTION_CAPSLOCK "capslock" +#define LED_FUNCTION_CHARGING "charging" +#define LED_FUNCTION_DEBUG "debug" +#define LED_FUNCTION_DISK "disk" +#define LED_FUNCTION_DISK_ACTIVITY "disk-activity" +#define LED_FUNCTION_DISK_ERR "disk-err" +#define LED_FUNCTION_DISK_READ "disk-read" +#define LED_FUNCTION_DISK_WRITE "disk-write" +#define LED_FUNCTION_FAULT "fault" +#define LED_FUNCTION_FLASH "flash" +#define LED_FUNCTION_HEARTBEAT "heartbeat" +#define LED_FUNCTION_INDICATOR "indicator" +#define LED_FUNCTION_KBD_BACKLIGHT "kbd_backlight" +#define LED_FUNCTION_LAN "lan" +#define LED_FUNCTION_MAIL "mail" +#define LED_FUNCTION_MTD "mtd" +#define LED_FUNCTION_MICMUTE "micmute" +#define LED_FUNCTION_MUTE "mute" +#define LED_FUNCTION_NUMLOCK "numlock" +#define LED_FUNCTION_PANIC "panic" +#define LED_FUNCTION_PROGRAMMING "programming" +#define LED_FUNCTION_POWER "power" +#define LED_FUNCTION_RX "rx" +#define LED_FUNCTION_SD "sd" +#define LED_FUNCTION_SCROLLLOCK "scrolllock" +#define LED_FUNCTION_STANDBY "standby" +#define LED_FUNCTION_STATUS "status" +#define LED_FUNCTION_TORCH "torch" +#define LED_FUNCTION_TX "tx" +#define LED_FUNCTION_USB "usb" +#define LED_FUNCTION_WAN "wan" +#define LED_FUNCTION_WLAN "wlan" +#define LED_FUNCTION_WPS "wps" + #endif /* __DT_BINDINGS_LEDS_H */ -- GitLab From c5d18dd6b64e09dd6984bda9bdd55160af537a8c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0706/7155] dt-bindings: leds: Add properties for LED name construction Introduce dedicated properties for conveying information about LED function and color. Mark old "label" property as deprecated. Additionally function-enumerator property is being provided for the cases when neither function nor color can be used for LED differentiation. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Pavel Machek Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/common.txt | 62 ++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt index 70876ac11367..9fa6f9795d50 100644 --- a/Documentation/devicetree/bindings/leds/common.txt +++ b/Documentation/devicetree/bindings/leds/common.txt @@ -10,14 +10,30 @@ can influence the way of the LED device initialization, the LED components have to be tightly coupled with the LED device binding. They are represented by child nodes of the parent LED device binding. + Optional properties for child nodes: - led-sources : List of device current outputs the LED is connected to. The outputs are identified by the numbers that must be defined in the LED device binding documentation. + +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions + from the header include/dt-bindings/leds/common.h. + If there is no matching LED_FUNCTION available, add a new one. + +- color : Color of the LED. Use one of the LED_COLOR_ID_* prefixed definitions + from the header include/dt-bindings/leds/common.h. + If there is no matching LED_COLOR_ID available, add a new one. + +- function-enumerator: Integer to be used when more than one instance + of the same function is needed, differing only with + an ordinal number. + - label : The label for this LED. If omitted, the label is taken from the node name (excluding the unit address). It has to uniquely identify a device, i.e. no other LED class device can be assigned the same - label. + label. This property is deprecated - use 'function' and 'color' + properties instead. function-enumerator has no effect when this + property is present. - default-state : The initial state of the LED. Valid values are "on", "off", and "keep". If the LED is already on or off and the default-state property is @@ -99,29 +115,59 @@ Required properties for trigger source: * Examples -gpio-leds { +#include + +led-controller@0 { compatible = "gpio-leds"; - system-status { - label = "Status"; + led0 { + function = LED_FUNCTION_STATUS; linux,default-trigger = "heartbeat"; gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; - usb { + led1 { + function = LED_FUNCTION_USB; gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; trigger-sources = <&ohci_port1>, <&ehci_port1>; }; }; -max77693-led { +led-controller@0 { compatible = "maxim,max77693-led"; - camera-flash { - label = "Flash"; + led { + function = LED_FUNCTION_FLASH; + color = ; led-sources = <0>, <1>; led-max-microamp = <50000>; flash-max-microamp = <320000>; flash-max-timeout-us = <500000>; }; }; + +led-controller@30 { + compatible = "panasonic,an30259a"; + reg = <0x30>; + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <1>; + }; + + led@2 { + reg = <2>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <2>; + }; + + led@3 { + reg = <3>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <3>; + }; +}; -- GitLab From bb4e9af0348dfeafd66c7e7f82e8a0983fe5390c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0707/7155] leds: core: Add support for composing LED class device names Add generic support for composing LED class device name. The newly introduced led_compose_name() function composes device name according to either or pattern, depending on the configuration of initialization data. Backward compatibility with in-driver hard-coded LED class device names is assured thanks to the default_label and devicename properties of newly introduced struct led_init_data. In case none of the aforementioned properties was found, then, for OF nodes, the node name is adopted for LED class device name. At the occassion of amending the Documentation/leds/leds-class.txt unify spelling: colour -> color. Alongside these changes added is a new tool - tools/leds/get_led_device_info.sh. The tool allows retrieving details of a LED class device's parent device, which proves that using vendor or product name for devicename part of LED name doesn't convey any added value since that information had been already available in sysfs. The script performs also basic validation of a LED class device name. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Reviewed-by: Linus Walleij Acked-by: Pavel Machek --- Documentation/leds/leds-class.rst | 70 ++++++++++- drivers/leds/led-class.c | 20 ++- drivers/leds/led-core.c | 127 +++++++++++++++++++ drivers/leds/leds.h | 1 + include/linux/leds.h | 45 +++++++ tools/leds/get_led_device_info.sh | 201 ++++++++++++++++++++++++++++++ 6 files changed, 458 insertions(+), 6 deletions(-) create mode 100755 tools/leds/get_led_device_info.sh diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst index df0120a1ee3c..a0708d3f3d0b 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -43,9 +43,73 @@ LED Device Naming Is currently of the form: - "devicename:colour:function" - -There have been calls for LED properties such as colour to be exported as + "devicename:color:function" + +- devicename: + it should refer to a unique identifier created by the kernel, + like e.g. phyN for network devices or inputN for input devices, rather + than to the hardware; the information related to the product and the bus + to which given device is hooked is available in sysfs and can be + retrieved using get_led_device_info.sh script from tools/leds; generally + this section is expected mostly for LEDs that are somehow associated with + other devices. + +- color: + one of LED_COLOR_ID_* definitions from the header + include/dt-bindings/leds/common.h. + +- function: + one of LED_FUNCTION_* definitions from the header + include/dt-bindings/leds/common.h. + +If required color or function is missing, please submit a patch +to linux-leds@vger.kernel.org. + +It is possible that more than one LED with the same color and function will +be required for given platform, differing only with an ordinal number. +In this case it is preferable to just concatenate the predefined LED_FUNCTION_* +name with required "-N" suffix in the driver. fwnode based drivers can use +function-enumerator property for that and then the concatenation will be handled +automatically by the LED core upon LED class device registration. + +LED subsystem has also a protection against name clash, that may occur +when LED class device is created by a driver of hot-pluggable device and +it doesn't provide unique devicename section. In this case numerical +suffix (e.g. "_1", "_2", "_3" etc.) is added to the requested LED class +device name. + +There might be still LED class drivers around using vendor or product name +for devicename, but this approach is now deprecated as it doesn't convey +any added value. Product information can be found in other places in sysfs +(see tools/leds/get_led_device_info.sh). + +Examples of proper LED names: + + - "red:disk" + - "white:flash" + - "red:indicator" + - "phy1:green:wlan" + - "phy3::wlan" + - ":kbd_backlight" + - "input5::kbd_backlight" + - "input3::numlock" + - "input3::scrolllock" + - "input3::capslock" + - "mmc1::status" + - "white:status" + +get_led_device_info.sh script can be used for verifying if the LED name +meets the requirements pointed out here. It performs validation of the LED class +devicename sections and gives hints on expected value for a section in case +the validation fails for it. So far the script supports validation +of associations between LEDs and following types of devices: + + - input devices + - ieee80211 compliant USB devices + +The script is open to extensions. + +There have been calls for LED properties such as color to be exported as individual led class attributes. As a solution which doesn't incur as much overhead, I suggest these become part of the device name. The naming scheme above leaves scope for further attributes should they be needed. If sections diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 242122f49333..508d6477d0b8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -254,17 +254,31 @@ int led_classdev_register_ext(struct device *parent, struct led_classdev *led_cdev, struct led_init_data *init_data) { - char name[LED_MAX_NAME_SIZE]; + char composed_name[LED_MAX_NAME_SIZE]; + char final_name[LED_MAX_NAME_SIZE]; + const char *proposed_name = composed_name; int ret; - ret = led_classdev_next_name(led_cdev->name, name, sizeof(name)); + if (init_data) { + if (init_data->devname_mandatory && !init_data->devicename) { + dev_err(parent, "Mandatory device name is missing"); + return -EINVAL; + } + ret = led_compose_name(parent, init_data, composed_name); + if (ret < 0) + return ret; + } else { + proposed_name = led_cdev->name; + } + + ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name)); if (ret < 0) return ret; mutex_init(&led_cdev->led_access); mutex_lock(&led_cdev->led_access); led_cdev->dev = device_create_with_groups(leds_class, parent, 0, - led_cdev, led_cdev->groups, "%s", name); + led_cdev, led_cdev->groups, "%s", final_name); if (IS_ERR(led_cdev->dev)) { mutex_unlock(&led_cdev->led_access); return PTR_ERR(led_cdev->dev); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 7107cd7e87cf..f0c1c403f678 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include "leds.h" DECLARE_RWSEM(leds_list_lock); @@ -23,6 +25,18 @@ EXPORT_SYMBOL_GPL(leds_list_lock); LIST_HEAD(leds_list); EXPORT_SYMBOL_GPL(leds_list); +const char * const led_colors[LED_COLOR_ID_MAX] = { + [LED_COLOR_ID_WHITE] = "white", + [LED_COLOR_ID_RED] = "red", + [LED_COLOR_ID_GREEN] = "green", + [LED_COLOR_ID_BLUE] = "blue", + [LED_COLOR_ID_AMBER] = "amber", + [LED_COLOR_ID_VIOLET] = "violet", + [LED_COLOR_ID_YELLOW] = "yellow", + [LED_COLOR_ID_IR] = "ir", +}; +EXPORT_SYMBOL_GPL(led_colors); + static int __led_set_brightness(struct led_classdev *led_cdev, enum led_brightness value) { @@ -353,3 +367,116 @@ void led_sysfs_enable(struct led_classdev *led_cdev) led_cdev->flags &= ~LED_SYSFS_DISABLE; } EXPORT_SYMBOL_GPL(led_sysfs_enable); + +static void led_parse_fwnode_props(struct device *dev, + struct fwnode_handle *fwnode, + struct led_properties *props) +{ + int ret; + + if (!fwnode) + return; + + if (fwnode_property_present(fwnode, "label")) { + ret = fwnode_property_read_string(fwnode, "label", &props->label); + if (ret) + dev_err(dev, "Error parsing 'label' property (%d)\n", ret); + return; + } + + if (fwnode_property_present(fwnode, "color")) { + ret = fwnode_property_read_u32(fwnode, "color", &props->color); + if (ret) + dev_err(dev, "Error parsing 'color' property (%d)\n", ret); + else if (props->color >= LED_COLOR_ID_MAX) + dev_err(dev, "LED color identifier out of range\n"); + else + props->color_present = true; + } + + + if (!fwnode_property_present(fwnode, "function")) + return; + + ret = fwnode_property_read_string(fwnode, "function", &props->function); + if (ret) { + dev_err(dev, + "Error parsing 'function' property (%d)\n", + ret); + } + + if (!fwnode_property_present(fwnode, "function-enumerator")) + return; + + ret = fwnode_property_read_u32(fwnode, "function-enumerator", + &props->func_enum); + if (ret) { + dev_err(dev, + "Error parsing 'function-enumerator' property (%d)\n", + ret); + } else { + props->func_enum_present = true; + } +} + +int led_compose_name(struct device *dev, struct led_init_data *init_data, + char *led_classdev_name) +{ + struct led_properties props = {}; + struct fwnode_handle *fwnode = init_data->fwnode; + const char *devicename = init_data->devicename; + + if (!led_classdev_name) + return -EINVAL; + + led_parse_fwnode_props(dev, fwnode, &props); + + if (props.label) { + /* + * If init_data.devicename is NULL, then it indicates that + * DT label should be used as-is for LED class device name. + * Otherwise the label is prepended with devicename to compose + * the final LED class device name. + */ + if (!devicename) { + strscpy(led_classdev_name, props.label, + LED_MAX_NAME_SIZE); + } else { + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, props.label); + } + } else if (props.function || props.color_present) { + char tmp_buf[LED_MAX_NAME_SIZE]; + + if (props.func_enum_present) { + snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d", + props.color_present ? led_colors[props.color] : "", + props.function ?: "", props.func_enum); + } else { + snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s", + props.color_present ? led_colors[props.color] : "", + props.function ?: ""); + } + if (init_data->devname_mandatory) { + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, tmp_buf); + } else { + strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE); + + } + } else if (init_data->default_label) { + if (!devicename) { + dev_err(dev, "Legacy LED naming requires devicename segment"); + return -EINVAL; + } + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", + devicename, init_data->default_label); + } else if (is_of_node(fwnode)) { + strscpy(led_classdev_name, to_of_node(fwnode)->name, + LED_MAX_NAME_SIZE); + } else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL_GPL(led_compose_name); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 47b229469069..0b577cece8f7 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -27,5 +27,6 @@ void led_set_brightness_nosleep(struct led_classdev *led_cdev, extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; extern struct list_head trigger_list; +extern const char * const led_colors[LED_COLOR_ID_MAX]; #endif /* __LEDS_H_INCLUDED */ diff --git a/include/linux/leds.h b/include/linux/leds.h index 2bbe8a38fe39..d101fd13e18e 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -8,6 +8,7 @@ #ifndef __LINUX_LEDS_H_INCLUDED #define __LINUX_LEDS_H_INCLUDED +#include #include #include #include @@ -33,6 +34,25 @@ enum led_brightness { struct led_init_data { /* device fwnode handle */ struct fwnode_handle *fwnode; + /* + * default tuple, for backward compatibility + * with in-driver hard-coded LED names used as a fallback when + * DT "label" property is absent; it should be set to NULL + * in new LED class drivers. + */ + const char *default_label; + /* + * string to be used for devicename section of LED class device + * either for label based LED name composition path or for fwnode + * based when devname_mandatory is true + */ + const char *devicename; + /* + * indicates if LED name should always comprise devicename section; + * only LEDs exposed by drivers of hot-pluggable devices should + * set it to true + */ + bool devname_mandatory; }; struct led_classdev { @@ -257,6 +277,22 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev); */ extern void led_sysfs_enable(struct led_classdev *led_cdev); +/** + * led_compose_name - compose LED class device name + * @dev: LED controller device object + * @child: child fwnode_handle describing a LED or a group of synchronized LEDs; + * it must be provided only for fwnode based LEDs + * @led_classdev_name: composed LED class device name + * + * Create LED class device name basing on the provided init_data argument. + * The name can have or . + * form, depending on the init_data configuration. + * + * Returns: 0 on success or negative error value on failure + */ +extern int led_compose_name(struct device *dev, struct led_init_data *init_data, + char *led_classdev_name); + /** * led_sysfs_is_disabled - check if LED sysfs interface is disabled * @led_cdev: the LED to query @@ -434,6 +470,15 @@ struct led_platform_data { struct led_info *leds; }; +struct led_properties { + u32 color; + bool color_present; + const char *function; + u32 func_enum; + bool func_enum_present; + const char *label; +}; + struct gpio_desc; typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state, unsigned long *delay_on, diff --git a/tools/leds/get_led_device_info.sh b/tools/leds/get_led_device_info.sh new file mode 100755 index 000000000000..ccfa442db5fe --- /dev/null +++ b/tools/leds/get_led_device_info.sh @@ -0,0 +1,201 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +led_common_defs_path="include/dt-bindings/leds/common.h" + +num_args=$# +if [ $num_args -eq 1 ]; then + linux_top=$(dirname `realpath $0` | awk -F/ \ + '{ \ + i=1; \ + while (i <= NF - 2) { \ + printf $i"/"; \ + i++; \ + }; \ + }') + led_defs_path=$linux_top/$led_common_defs_path +elif [ $num_args -eq 2 ]; then + led_defs_path=`realpath $2` +else + echo "Usage: get_led_device_info.sh LED_CDEV_PATH [LED_COMMON_DEFS_PATH]" + exit 1 +fi + +if [ ! -f $led_defs_path ]; then + echo "$led_defs_path doesn't exist" + exit 1 +fi + +led_cdev_path=`echo $1 | sed s'/\/$//'` + +ls "$led_cdev_path/brightness" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Device \"$led_cdev_path\" does not exist." + exit 1 +fi + +bus=`readlink $led_cdev_path/device/subsystem | sed s'/.*\///'` +usb_subdev=`readlink $led_cdev_path | grep usb | sed s'/\(.*usb[0-9]*\/[0-9]*-[0-9]*\)\/.*/\1/'` +ls "$led_cdev_path/device/of_node/compatible" > /dev/null 2>&1 +of_node_missing=$? + +if [ "$bus" = "input" ]; then + input_node=`readlink $led_cdev_path/device | sed s'/.*\///'` + if [ ! -z "$usb_subdev" ]; then + bus="usb" + fi +fi + +if [ "$bus" = "usb" ]; then + usb_interface=`readlink $led_cdev_path | sed s'/.*\(usb[0-9]*\)/\1/' | cut -d\/ -f3` + cd $led_cdev_path/../$usb_subdev + driver=`readlink $usb_interface/driver | sed s'/.*\///'` + if [ -d "$usb_interface/ieee80211" ]; then + wifi_phy=`ls -l $usb_interface/ieee80211 | grep phy | awk '{print $9}'` + fi + idVendor=`cat idVendor` + idProduct=`cat idProduct` + manufacturer=`cat manufacturer` + product=`cat product` +elif [ "$bus" = "input" ]; then + cd $led_cdev_path + product=`cat device/name` + driver=`cat device/device/driver/description` +elif [ $of_node_missing -eq 0 ]; then + cd $led_cdev_path + compatible=`cat device/of_node/compatible` + if [ "$compatible" = "gpio-leds" ]; then + driver="leds-gpio" + elif [ "$compatible" = "pwm-leds" ]; then + driver="leds-pwm" + else + manufacturer=`echo $compatible | awk -F, '{print $1}'` + product=`echo $compatible | awk -F, '{print $2}'` + fi +else + echo "Unknown device type." + exit 1 +fi + +printf "\n#####################################\n" +printf "# LED class device hardware details #\n" +printf "#####################################\n\n" + +printf "bus:\t\t\t$bus\n" + +if [ ! -z "$idVendor" ]; then + printf "idVendor:\t\t$idVendor\n" +fi + +if [ ! -z "$idProduct" ]; then + printf "idProduct:\t\t$idProduct\n" +fi + +if [ ! -z "$manufacturer" ]; then + printf "manufacturer:\t\t$manufacturer\n" +fi + +if [ ! -z "$product" ]; then + printf "product:\t\t$product\n" +fi + +if [ ! -z "$driver" ]; then + printf "driver:\t\t\t$driver\n" +fi + +if [ ! -z "$input_node" ]; then + printf "associated input node:\t$input_node\n" +fi + +printf "\n####################################\n" +printf "# LED class device name validation #\n" +printf "####################################\n\n" + +led_name=`echo $led_cdev_path | sed s'/.*\///'` + +num_sections=`echo $led_name | awk -F: '{print NF}'` + +if [ $num_sections -eq 1 ]; then + printf "\":\" delimiter not detected.\t[ FAILED ]\n" + exit 1 +elif [ $num_sections -eq 2 ]; then + color=`echo $led_name | cut -d: -f1` + function=`echo $led_name | cut -d: -f2` +elif [ $num_sections -eq 3 ]; then + devicename=`echo $led_name | cut -d: -f1` + color=`echo $led_name | cut -d: -f2` + function=`echo $led_name | cut -d: -f3` +else + printf "Detected %d sections in the LED class device name - should the script be updated?\n" $num_sections + exit 1 +fi + +S_DEV="devicename" +S_CLR="color " +S_FUN="function " +status_tab=20 + +print_msg_ok() +{ + local section_name="$1" + local section_val="$2" + local msg="$3" + printf "$section_name :\t%-${status_tab}.${status_tab}s %s %s\n" "$section_val" "[ OK ] " "$msg" +} + +print_msg_failed() +{ + local section_name="$1" + local section_val="$2" + local msg="$3" + printf "$section_name :\t%-${status_tab}.${status_tab}s %s %s\n" "$section_val" "[ FAILED ]" "$msg" +} + +if [ ! -z "$input_node" ]; then + expected_devname=$input_node +elif [ ! -z "$wifi_phy" ]; then + expected_devname=$wifi_phy +fi + +if [ ! -z "$devicename" ]; then + if [ ! -z "$expected_devname" ]; then + if [ "$devicename" = "$expected_devname" ]; then + print_msg_ok "$S_DEV" "$devicename" + else + print_msg_failed "$S_DEV" "$devicename" "Expected: $expected_devname" + fi + else + if [ "$devicename" = "$manufacturer" ]; then + print_msg_failed "$S_DEV" "$devicename" "Redundant: use of vendor name is discouraged" + elif [ "$devicename" = "$product" ]; then + print_msg_failed "$S_DEV" "$devicename" "Redundant: use of product name is discouraged" + else + print_msg_failed "$S_DEV" "$devicename" "Unknown devicename - should the script be updated?" + fi + fi +elif [ ! -z "$expected_devname" ]; then + print_msg_failed "$S_DEV" "blank" "Expected: $expected_devname" +fi + +if [ ! -z "$color" ]; then + color_upper=`echo $color | tr [:lower:] [:upper:]` + color_id_definition=$(cat $led_defs_path | grep "_$color_upper\s" | awk '{print $2}') + if [ ! -z "$color_id_definition" ]; then + print_msg_ok "$S_CLR" "$color" "Matching definition: $color_id_definition" + else + print_msg_failed "$S_CLR" "$color" "Definition not found in $led_defs_path" + fi + +fi + +if [ ! -z "$function" ]; then + # strip optional enumerator + function=`echo $function | sed s'/\(.*\)-[0-9]*$/\1/'` + fun_definition=$(cat $led_defs_path | grep "\"$function\"" | awk '{print $2}') + if [ ! -z "$fun_definition" ]; then + print_msg_ok "$S_FUN" "$function" "Matching definition: $fun_definition" + else + print_msg_failed "$S_FUN" "$function" "Definition not found in $led_defs_path" + fi + +fi -- GitLab From 0f0f25797a7d20e9d969a46ba952a329b270cf09 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0708/7155] dt-bindings: sc27xx-blt: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/leds-sc27xx-bltc.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt b/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt index dddf84f9c7ea..df2b4e1c492b 100644 --- a/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt +++ b/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt @@ -14,7 +14,9 @@ Required child properties: - reg: Port this LED is connected to. Optional child properties: -- label: See Documentation/devicetree/bindings/leds/common.txt. +- function: See Documentation/devicetree/bindings/leds/common.txt. +- color: See Documentation/devicetree/bindings/leds/common.txt. +- label: See Documentation/devicetree/bindings/leds/common.txt (deprecated). Examples: @@ -25,17 +27,17 @@ led-controller@200 { reg = <0x200>; led@0 { - label = "red"; + color = ; reg = <0x0>; }; led@1 { - label = "green"; + color = ; reg = <0x1>; }; led@2 { - label = "blue"; + color = ; reg = <0x2>; }; }; -- GitLab From 5fdf85a0911a4109abbb2c006da7d8407cb60078 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0709/7155] leds: sc27xx-blt: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Reviewed-by: Baolin Wang Acked-by: Pavel Machek --- drivers/leds/leds-sc27xx-bltc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c index fecf27fb1cdc..0ede87420bfc 100644 --- a/drivers/leds/leds-sc27xx-bltc.c +++ b/drivers/leds/leds-sc27xx-bltc.c @@ -6,7 +6,6 @@ #include #include #include -#include /* PMIC global control register definition */ #define SC27XX_MODULE_EN0 0xc08 @@ -46,7 +45,7 @@ #define SC27XX_DELTA_T_MAX (SC27XX_LEDS_STEP * 255) struct sc27xx_led { - char name[LED_MAX_NAME_SIZE]; + struct fwnode_handle *fwnode; struct led_classdev ldev; struct sc27xx_led_priv *priv; u8 line; @@ -249,19 +248,24 @@ static int sc27xx_led_register(struct device *dev, struct sc27xx_led_priv *priv) for (i = 0; i < SC27XX_LEDS_MAX; i++) { struct sc27xx_led *led = &priv->leds[i]; + struct led_init_data init_data = {}; if (!led->active) continue; led->line = i; led->priv = priv; - led->ldev.name = led->name; led->ldev.brightness_set_blocking = sc27xx_led_set; led->ldev.pattern_set = sc27xx_led_pattern_set; led->ldev.pattern_clear = sc27xx_led_pattern_clear; led->ldev.default_trigger = "pattern"; - err = devm_led_classdev_register(dev, &led->ldev); + init_data.fwnode = led->fwnode; + init_data.devicename = "sc27xx"; + init_data.default_label = ":"; + + err = devm_led_classdev_register_ext(dev, &led->ldev, + &init_data); if (err) return err; } @@ -274,7 +278,6 @@ static int sc27xx_led_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node, *child; struct sc27xx_led_priv *priv; - const char *str; u32 base, count, reg; int err; @@ -316,15 +319,8 @@ static int sc27xx_led_probe(struct platform_device *pdev) return -EINVAL; } + priv->leds[reg].fwnode = of_fwnode_handle(child); priv->leds[reg].active = true; - - err = of_property_read_string(child, "label", &str); - if (err) - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE, - "sc27xx::"); - else - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE, - "sc27xx:%s", str); } err = sc27xx_led_register(dev, priv); -- GitLab From e12e91a4129be7a11e7b6912910c6fb1a71a0fb3 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0710/7155] dt-bindings: lt3593: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Cc: Daniel Mack Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/leds-lt3593.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lt3593.txt b/Documentation/devicetree/bindings/leds/leds-lt3593.txt index 6b2cabc36c0c..24eccdaa6322 100644 --- a/Documentation/devicetree/bindings/leds/leds-lt3593.txt +++ b/Documentation/devicetree/bindings/leds/leds-lt3593.txt @@ -9,8 +9,10 @@ The hardware supports only one LED. The properties of this LED are configured in a sub-node in the device node. Optional sub-node properties: -- label: A label for the LED. If none is given, the LED will be - named "lt3595::". +- function: See Documentation/devicetree/bindings/leds/common.txt +- color: See Documentation/devicetree/bindings/leds/common.txt +- label: A label for the LED. If none is given, the LED will be + named "lt3595::" (deprecated) - linux,default-trigger: The default trigger for the LED. See Documentation/devicetree/bindings/leds/common.txt - default-state: The initial state of the LED. @@ -21,12 +23,15 @@ be handled by its own device node. Example: +#include + led-controller { compatible = "lltc,lt3593"; lltc,ctrl-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; led { - label = "white:backlight"; + function = LED_FUNCTION_BACKLIGHT; + color = ; default-state = "on"; }; }; -- GitLab From 68e192078e022b8dc0cec57cfdd0e369f62d7ea5 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0711/7155] leds: lt3593: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Daniel Mack Acked-by: Pavel Machek --- drivers/leds/leds-lt3593.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 83e8e58d81cb..c94995f0daa2 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -10,10 +10,10 @@ #include #include #include -#include + +#define LED_LT3593_NAME "lt3593" struct lt3593_led_data { - char name[LED_MAX_NAME_SIZE]; struct led_classdev cdev; struct gpio_desc *gpiod; }; @@ -66,6 +66,7 @@ static int lt3593_led_probe(struct platform_device *pdev) struct lt3593_led_data *led_data; struct fwnode_handle *child; int ret, state = LEDS_GPIO_DEFSTATE_OFF; + struct led_init_data init_data = {}; const char *tmp; if (!dev->of_node) @@ -86,14 +87,6 @@ static int lt3593_led_probe(struct platform_device *pdev) child = device_get_next_child_node(dev, NULL); - ret = fwnode_property_read_string(child, "label", &tmp); - if (ret < 0) - snprintf(led_data->name, sizeof(led_data->name), - "lt3593::"); - else - snprintf(led_data->name, sizeof(led_data->name), - "lt3593:%s", tmp); - fwnode_property_read_string(child, "linux,default-trigger", &led_data->cdev.default_trigger); @@ -102,11 +95,14 @@ static int lt3593_led_probe(struct platform_device *pdev) state = LEDS_GPIO_DEFSTATE_ON; } - led_data->cdev.name = led_data->name; led_data->cdev.brightness_set_blocking = lt3593_led_set; led_data->cdev.brightness = state ? LED_FULL : LED_OFF; - ret = devm_led_classdev_register(dev, &led_data->cdev); + init_data.fwnode = child; + init_data.devicename = LED_LT3593_NAME; + init_data.default_label = ":"; + + ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data); if (ret < 0) { fwnode_handle_put(child); return ret; -- GitLab From 0ec39e8cd8f60fa0b93c298a48c3a9279f70375b Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0712/7155] dt-bindings: lp8860: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Reviewed-by: Rob Herring Reviewed-by: Dan Murphy --- Documentation/devicetree/bindings/leds/leds-lp8860.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lp8860.txt b/Documentation/devicetree/bindings/leds/leds-lp8860.txt index 5f0e892ad759..9863220db4ba 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp8860.txt +++ b/Documentation/devicetree/bindings/leds/leds-lp8860.txt @@ -20,12 +20,16 @@ Required child properties: - reg : 0 Optional child properties: - - label : see Documentation/devicetree/bindings/leds/common.txt + - function : see Documentation/devicetree/bindings/leds/common.txt + - color : see Documentation/devicetree/bindings/leds/common.txt + - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated) - linux,default-trigger : see Documentation/devicetree/bindings/leds/common.txt Example: +#include + led-controller@2d { compatible = "ti,lp8860"; #address-cells = <1>; @@ -36,7 +40,8 @@ led-controller@2d { led@0 { reg = <0>; - label = "white:backlight"; + function = LED_FUNCTION_BACKLIGHT; + color = ; linux,default-trigger = "backlight"; }; } -- GitLab From 99ca0ea5730971035caa847e5cacf324a2b5598a Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0713/7155] leds: lp8860: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. While at it, avoid iterating through available child of nodes in favor of obtaining single expected child node using single call to of_get_next_available_child(). Signed-off-by: Jacek Anaszewski Acked-by: Pavel Machek Tested-by: Dan Murphy --- drivers/leds/leds-lp8860.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c index ed680d0c15b0..ac2f5d6272dc 100644 --- a/drivers/leds/leds-lp8860.c +++ b/drivers/leds/leds-lp8860.c @@ -18,7 +18,6 @@ #include #include #include -#include #define LP8860_DISP_CL1_BRT_MSB 0x00 #define LP8860_DISP_CL1_BRT_LSB 0x01 @@ -83,6 +82,8 @@ #define LP8860_CLEAR_FAULTS 0x01 +#define LP8860_NAME "lp8860" + /** * struct lp8860_led - * @lock - Lock for reading/writing the device @@ -92,7 +93,6 @@ * @eeprom_regmap - EEPROM register map * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer - * @label - LED label */ struct lp8860_led { struct mutex lock; @@ -102,7 +102,6 @@ struct lp8860_led { struct regmap *eeprom_regmap; struct gpio_desc *enable_gpio; struct regulator *regulator; - char label[LED_MAX_NAME_SIZE]; }; struct lp8860_eeprom_reg { @@ -383,25 +382,19 @@ static int lp8860_probe(struct i2c_client *client, struct lp8860_led *led; struct device_node *np = client->dev.of_node; struct device_node *child_node; - const char *name; + struct led_init_data init_data = {}; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; - for_each_available_child_of_node(np, child_node) { - led->led_dev.default_trigger = of_get_property(child_node, - "linux,default-trigger", - NULL); - - ret = of_property_read_string(child_node, "label", &name); - if (!ret) - snprintf(led->label, sizeof(led->label), "%s:%s", - id->name, name); - else - snprintf(led->label, sizeof(led->label), - "%s::display_cluster", id->name); - } + child_node = of_get_next_available_child(np, NULL); + if (!child_node) + return -EINVAL; + + led->led_dev.default_trigger = of_get_property(child_node, + "linux,default-trigger", + NULL); led->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); @@ -416,7 +409,6 @@ static int lp8860_probe(struct i2c_client *client, led->regulator = NULL; led->client = client; - led->led_dev.name = led->label; led->led_dev.brightness_set_blocking = lp8860_brightness_set; mutex_init(&led->lock); @@ -443,7 +435,12 @@ static int lp8860_probe(struct i2c_client *client, if (ret) return ret; - ret = devm_led_classdev_register(&client->dev, &led->led_dev); + init_data.fwnode = of_fwnode_handle(child_node); + init_data.devicename = LP8860_NAME; + init_data.default_label = ":display_cluster"; + + ret = devm_led_classdev_register_ext(&client->dev, &led->led_dev, + &init_data); if (ret) { dev_err(&client->dev, "led register err: %d\n", ret); return ret; -- GitLab From 4dcbc8f8c59f4b618d651f5ba884ee5bf562c8de Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0714/7155] dt-bindings: lm3692x: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Reviewed-by: Dan Murphy A Reviewed-by: Rob Herring --- Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt index 08b352840bd7..4c2d923f8758 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt @@ -26,12 +26,16 @@ Required child properties: 3 - Will enable the LED3 sync (LM36923 only) Optional child properties: - - label : see Documentation/devicetree/bindings/leds/common.txt + - function : see Documentation/devicetree/bindings/leds/common.txt + - color : see Documentation/devicetree/bindings/leds/common.txt + - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated) - linux,default-trigger : see Documentation/devicetree/bindings/leds/common.txt Example: +#include + led-controller@36 { compatible = "ti,lm3692x"; reg = <0x36>; @@ -43,7 +47,8 @@ led-controller@36 { led@0 { reg = <0>; - label = "white:backlight_cluster"; + function = LED_FUNCTION_BACKLIGHT; + color = ; linux,default-trigger = "backlight"; }; } -- GitLab From a50ff28348934913c46feb7945571329e46c70b3 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0715/7155] leds: lm3692x: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. At this occassion remove initialization of struct led_classdev's dev->of_node property in the driver, since now it will be taken from fwnode assigned to struct led_init_data and passed to the new devm_led_classdev_register_ext() API. Signed-off-by: Jacek Anaszewski Tested-by: Dan Murphy Acked-by: Pavel Machek --- drivers/leds/leds-lm3692x.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 4f413a7c5f05..3d381f2f73d0 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -13,7 +13,6 @@ #include #include #include -#include #define LM36922_MODEL 0 #define LM36923_MODEL 1 @@ -103,7 +102,6 @@ * @regmap - Devices register map * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer - * @label - LED label * @led_enable - LED sync to be enabled * @model_id - Current device model ID enumerated */ @@ -114,7 +112,6 @@ struct lm3692x_led { struct regmap *regmap; struct gpio_desc *enable_gpio; struct regulator *regulator; - char label[LED_MAX_NAME_SIZE]; int led_enable; int model_id; }; @@ -325,7 +322,7 @@ static int lm3692x_init(struct lm3692x_led *led) static int lm3692x_probe_dt(struct lm3692x_led *led) { struct fwnode_handle *child = NULL; - const char *name; + struct led_init_data init_data = {}; int ret; led->enable_gpio = devm_gpiod_get_optional(&led->client->dev, @@ -350,30 +347,23 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) fwnode_property_read_string(child, "linux,default-trigger", &led->led_dev.default_trigger); - ret = fwnode_property_read_string(child, "label", &name); - if (ret) - snprintf(led->label, sizeof(led->label), - "%s::", led->client->name); - else - snprintf(led->label, sizeof(led->label), - "%s:%s", led->client->name, name); - ret = fwnode_property_read_u32(child, "reg", &led->led_enable); if (ret) { dev_err(&led->client->dev, "reg DT property missing\n"); return ret; } - led->led_dev.name = led->label; + init_data.fwnode = child; + init_data.devicename = led->client->name; + init_data.default_label = ":"; - ret = devm_led_classdev_register(&led->client->dev, &led->led_dev); + ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev, + &init_data); if (ret) { dev_err(&led->client->dev, "led register err: %d\n", ret); return ret; } - led->led_dev.dev->of_node = to_of_node(child); - return 0; } -- GitLab From 28e12cf498ec39f23cd719b37f123301ab7ab7aa Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0716/7155] dt-bindings: lm36010: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Reviewed-by: Dan Murphy Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/leds-lm3601x.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lm3601x.txt b/Documentation/devicetree/bindings/leds/leds-lm3601x.txt index a88b2c41e75b..095dafb6ec7f 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3601x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3601x.txt @@ -22,9 +22,14 @@ Required properties for flash LED child nodes: - led-max-microamp : Range from 2.4mA - 376mA Optional child properties: - - label : see Documentation/devicetree/bindings/leds/common.txt + - function : see Documentation/devicetree/bindings/leds/common.txt + - color : see Documentation/devicetree/bindings/leds/common.txt + - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated) Example: + +#include + led-controller@64 { compatible = "ti,lm36010"; #address-cells = <1>; @@ -33,7 +38,8 @@ led-controller@64 { led@0 { reg = <1>; - label = "white:torch"; + function = LED_FUNCTION_TORCH; + color = ; led-max-microamp = <376000>; flash-max-microamp = <1500000>; flash-max-timeout-us = <1600000>; -- GitLab From e322b75a301b8cc3915f1e1cbd0e48958b717f6c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0717/7155] leds: lm3601x: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Tested-by: Dan Murphy Acked-by: Pavel Machek --- drivers/leds/leds-lm3601x.c | 38 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/leds-lm3601x.c index 081aa71e43a3..b02972f1a341 100644 --- a/drivers/leds/leds-lm3601x.c +++ b/drivers/leds/leds-lm3601x.c @@ -10,7 +10,6 @@ #include #include #include -#include #define LM3601X_LED_IR 0x0 #define LM3601X_LED_TORCH 0x1 @@ -90,8 +89,6 @@ struct lm3601x_led { struct regmap *regmap; struct mutex lock; - char led_name[LED_MAX_NAME_SIZE]; - unsigned int flash_timeout; unsigned int last_flag; @@ -322,10 +319,12 @@ static const struct led_flash_ops flash_ops = { .fault_get = lm3601x_flash_fault_get, }; -static int lm3601x_register_leds(struct lm3601x_led *led) +static int lm3601x_register_leds(struct lm3601x_led *led, + struct fwnode_handle *fwnode) { struct led_classdev *led_cdev; struct led_flash_setting *setting; + struct led_init_data init_data = {}; led->fled_cdev.ops = &flash_ops; @@ -342,20 +341,25 @@ static int lm3601x_register_leds(struct lm3601x_led *led) setting->val = led->flash_current_max; led_cdev = &led->fled_cdev.led_cdev; - led_cdev->name = led->led_name; led_cdev->brightness_set_blocking = lm3601x_brightness_set; led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max, LM3601X_TORCH_REG_DIV); led_cdev->flags |= LED_DEV_CAP_FLASH; - return led_classdev_flash_register(&led->client->dev, &led->fled_cdev); + init_data.fwnode = fwnode; + init_data.devicename = led->client->name; + init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ? + "torch" : "infrared"; + + return led_classdev_flash_register_ext(&led->client->dev, + &led->fled_cdev, &init_data); } -static int lm3601x_parse_node(struct lm3601x_led *led) +static int lm3601x_parse_node(struct lm3601x_led *led, + struct fwnode_handle **fwnode) { struct fwnode_handle *child = NULL; int ret = -ENODEV; - const char *name; child = device_get_next_child_node(&led->client->dev, child); if (!child) { @@ -376,17 +380,6 @@ static int lm3601x_parse_node(struct lm3601x_led *led) goto out_err; } - ret = fwnode_property_read_string(child, "label", &name); - if (ret) { - if (led->led_mode == LM3601X_LED_TORCH) - name = "torch"; - else - name = "infrared"; - } - - snprintf(led->led_name, sizeof(led->led_name), - "%s:%s", led->client->name, name); - ret = fwnode_property_read_u32(child, "led-max-microamp", &led->torch_current_max); if (ret) { @@ -411,6 +404,8 @@ static int lm3601x_parse_node(struct lm3601x_led *led) goto out_err; } + *fwnode = child; + out_err: fwnode_handle_put(child); return ret; @@ -419,6 +414,7 @@ static int lm3601x_parse_node(struct lm3601x_led *led) static int lm3601x_probe(struct i2c_client *client) { struct lm3601x_led *led; + struct fwnode_handle *fwnode; int ret; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); @@ -428,7 +424,7 @@ static int lm3601x_probe(struct i2c_client *client) led->client = client; i2c_set_clientdata(client, led); - ret = lm3601x_parse_node(led); + ret = lm3601x_parse_node(led, &fwnode); if (ret) return -ENODEV; @@ -442,7 +438,7 @@ static int lm3601x_probe(struct i2c_client *client) mutex_init(&led->lock); - return lm3601x_register_leds(led); + return lm3601x_register_leds(led, fwnode); } static int lm3601x_remove(struct i2c_client *client) -- GitLab From 6c01a5cc36ea9245816df8bd89245116f34fc0cb Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0718/7155] dt-bindings: cr0014114: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Cc: Oleh Kravchenko Reviewed-by: Rob Herring --- .../bindings/leds/leds-cr0014114.txt | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-cr0014114.txt b/Documentation/devicetree/bindings/leds/leds-cr0014114.txt index 4255b19ad25c..f8de7516a39b 100644 --- a/Documentation/devicetree/bindings/leds/leds-cr0014114.txt +++ b/Documentation/devicetree/bindings/leds/leds-cr0014114.txt @@ -11,14 +11,20 @@ Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt apply. In particular, "reg" and "spi-max-frequency" properties must be given. LED sub-node properties: -- label : +- function : + see Documentation/devicetree/bindings/leds/common.txt +- color : see Documentation/devicetree/bindings/leds/common.txt +- label : + see Documentation/devicetree/bindings/leds/common.txt (deprecated) - linux,default-trigger : (optional) see Documentation/devicetree/bindings/leds/common.txt Example ------- +#include + led-controller@0 { compatible = "crane,cr0014114"; reg = <0>; @@ -28,27 +34,33 @@ led-controller@0 { led@0 { reg = <0>; - label = "red:coin"; + function = "coin"; + color = ; }; led@1 { reg = <1>; - label = "green:coin"; + function = "coin"; + color = ; }; led@2 { reg = <2>; - label = "blue:coin"; + function = "coin"; + color = ; }; led@3 { reg = <3>; - label = "red:bill"; + function = "bill"; + color = ; }; led@4 { reg = <4>; - label = "green:bill"; + function = "bill"; + color = ; }; led@5 { reg = <5>; - label = "blue:bill"; + function = "bill"; + color = ; }; ... }; -- GitLab From 889003c20602bbebc82a6f32e24e7d0785a7b324 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0719/7155] leds: cr0014114: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. At this occassion remove initialization of struct led_classdev's dev->of_node property in the driver, since now it will be taken from fwnode assigned to struct led_init_data and passed to the new devm_led_classdev_register_ext() API. Signed-off-by: Jacek Anaszewski Cc: Oleh Kravchenko Acked-by: Pavel Machek --- drivers/leds/leds-cr0014114.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index 1c82152764d2..2da448ae718e 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -8,7 +8,6 @@ #include #include #include -#include /* * CR0014114 SPI protocol descrtiption: @@ -40,8 +39,9 @@ #define CR_FW_DELAY_MSEC 10 #define CR_RECOUNT_DELAY (HZ * 3600) +#define CR_DEV_NAME "cr0014114" + struct cr0014114_led { - char name[LED_MAX_NAME_SIZE]; struct cr0014114 *priv; struct led_classdev ldev; u8 brightness; @@ -167,8 +167,7 @@ static int cr0014114_set_sync(struct led_classdev *ldev, struct cr0014114_led, ldev); - dev_dbg(led->priv->dev, "Set brightness of %s to %d\n", - led->name, brightness); + dev_dbg(led->priv->dev, "Set brightness to %d\n", brightness); mutex_lock(&led->priv->lock); led->brightness = (u8)brightness; @@ -183,41 +182,32 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) size_t i = 0; struct cr0014114_led *led; struct fwnode_handle *child; - struct device_node *np; + struct led_init_data init_data = {}; int ret; - const char *str; device_for_each_child_node(priv->dev, child) { - np = to_of_node(child); led = &priv->leds[i]; - ret = fwnode_property_read_string(child, "label", &str); - if (ret) - snprintf(led->name, sizeof(led->name), - "cr0014114::"); - else - snprintf(led->name, sizeof(led->name), - "cr0014114:%s", str); - fwnode_property_read_string(child, "linux,default-trigger", &led->ldev.default_trigger); led->priv = priv; - led->ldev.name = led->name; led->ldev.max_brightness = CR_MAX_BRIGHTNESS; led->ldev.brightness_set_blocking = cr0014114_set_sync; - ret = devm_led_classdev_register(priv->dev, &led->ldev); + init_data.fwnode = child; + init_data.devicename = CR_DEV_NAME; + init_data.default_label = ":"; + + ret = devm_led_classdev_register_ext(priv->dev, &led->ldev, + &init_data); if (ret) { dev_err(priv->dev, - "failed to register LED device %s, err %d", - led->name, ret); + "failed to register LED device, err %d", ret); fwnode_handle_put(child); return ret; } - led->ldev.dev->of_node = np; - i++; } -- GitLab From d60a3d30c2858872ba97093689a741f1966b4b00 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0720/7155] dt-bindings: aat1290: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/leds-aat1290.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-aat1290.txt b/Documentation/devicetree/bindings/leds/leds-aat1290.txt index 85c0c58617f6..62ed17ec075b 100644 --- a/Documentation/devicetree/bindings/leds/leds-aat1290.txt +++ b/Documentation/devicetree/bindings/leds/leds-aat1290.txt @@ -32,15 +32,18 @@ Required properties of the LED child node: formula: T = 8.82 * 10^9 * Ct. Optional properties of the LED child node: -- label : see Documentation/devicetree/bindings/leds/common.txt +- function : see Documentation/devicetree/bindings/leds/common.txt +- color : see Documentation/devicetree/bindings/leds/common.txt +- label : see Documentation/devicetree/bindings/leds/common.txt (deprecated) Example (by Ct = 220nF, Rset = 160kohm and exynos4412-trats2 board with a switch that allows for routing strobe signal either from the host or from the camera sensor): #include "exynos4412.dtsi" +#include -aat1290 { +led-controller { compatible = "skyworks,aat1290"; flen-gpios = <&gpj1 1 GPIO_ACTIVE_HIGH>; enset-gpios = <&gpj1 2 GPIO_ACTIVE_HIGH>; @@ -50,8 +53,9 @@ aat1290 { pinctrl-1 = <&camera_flash_host>; pinctrl-2 = <&camera_flash_isp>; - camera_flash: flash-led { - label = "aat1290-flash"; + camera_flash: led { + function = LED_FUNCTION_FLASH; + color = ; led-max-microamp = <520833>; flash-max-microamp = <1012500>; flash-max-timeout-us = <1940000>; -- GitLab From 8103f558527f77e7d36e11cddfbef8bf8c4bae13 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0721/7155] leds: aat1290: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. After switching to new led_classdev_register_ext() the validity of struct led_classdev's name property is no longer guaranteed, and therefore rely on struct device's kobj.name instead. Signed-off-by: Jacek Anaszewski Acked-by: Pavel Machek --- drivers/leds/leds-aat1290.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c index bf26f5bed1f0..5a0fe7b7b8bc 100644 --- a/drivers/leds/leds-aat1290.c +++ b/drivers/leds/leds-aat1290.c @@ -42,6 +42,8 @@ #define AAT1290_FLASH_TM_NUM_LEVELS 16 #define AAT1290_MM_CURRENT_SCALE_SIZE 15 +#define AAT1290_NAME "aat1290" + struct aat1290_led_config_data { /* maximum LED current in movie mode */ @@ -75,7 +77,6 @@ struct aat1290_led { int *mm_current_scale; /* device mode */ bool movie_mode; - /* brightness cache */ unsigned int torch_brightness; }; @@ -215,7 +216,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led, struct aat1290_led_config_data *cfg, struct device_node **sub_node) { - struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; struct device *dev = &led->pdev->dev; struct device_node *child_node; #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) @@ -254,9 +254,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led, return -EINVAL; } - led_cdev->name = of_get_property(child_node, "label", NULL) ? : - child_node->name; - ret = of_property_read_u32(child_node, "led-max-microamp", &cfg->max_mm_current); /* @@ -428,7 +425,7 @@ static void aat1290_init_v4l2_flash_config(struct aat1290_led *led, struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; struct led_flash_setting *s; - strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name, + strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name, sizeof(v4l2_sd_cfg->dev_name)); s = &v4l2_sd_cfg->intensity; @@ -466,6 +463,7 @@ static int aat1290_led_probe(struct platform_device *pdev) struct aat1290_led *led; struct led_classdev *led_cdev; struct led_classdev_flash *fled_cdev; + struct led_init_data init_data = {}; struct aat1290_led_config_data led_cfg = {}; struct v4l2_flash_config v4l2_sd_cfg = {}; int ret; @@ -494,8 +492,12 @@ static int aat1290_led_probe(struct platform_device *pdev) aat1290_init_flash_timeout(led, &led_cfg); + init_data.fwnode = of_fwnode_handle(sub_node); + init_data.devicename = AAT1290_NAME; + /* Register LED Flash class device */ - ret = led_classdev_flash_register(&pdev->dev, fled_cdev); + ret = led_classdev_flash_register_ext(&pdev->dev, fled_cdev, + &init_data); if (ret < 0) goto err_flash_register; -- GitLab From 5b95cb0cbf6451d80c1385e1e3198e2730a3a59c Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0722/7155] dt-bindings: as3645a: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Also, fix malformed syntax of address-cells and size-cells in the example. Signed-off-by: Jacek Anaszewski Cc: Sakari Ailus Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/ams,as3645a.txt | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/ams,as3645a.txt b/Documentation/devicetree/bindings/leds/ams,as3645a.txt index fdc40e354a64..4af2987b25e9 100644 --- a/Documentation/devicetree/bindings/leds/ams,as3645a.txt +++ b/Documentation/devicetree/bindings/leds/ams,as3645a.txt @@ -39,7 +39,9 @@ ams,input-max-microamp: Maximum flash controller input current. The Optional properties of the flash child node =========================================== -label : The label of the flash LED. +function : See Documentation/devicetree/bindings/leds/common.txt. +color : See Documentation/devicetree/bindings/leds/common.txt. +label : See Documentation/devicetree/bindings/leds/common.txt (deprecated). Required properties of the indicator child node (1) @@ -52,28 +54,32 @@ led-max-microamp: Maximum indicator current. The allowed values are Optional properties of the indicator child node =============================================== -label : The label of the indicator LED. +function : See Documentation/devicetree/bindings/leds/common.txt. +color : See Documentation/devicetree/bindings/leds/common.txt. +label : See Documentation/devicetree/bindings/leds/common.txt (deprecated). Example ======= +#include + as3645a@30 { - #address-cells: 1 - #size-cells: 0 + #address-cells = <1>; + #size-cells = <0>; reg = <0x30>; compatible = "ams,as3645a"; - flash@0 { + led@0 { reg = <0x0>; flash-timeout-us = <150000>; flash-max-microamp = <320000>; led-max-microamp = <60000>; ams,input-max-microamp = <1750000>; - label = "as3645a:flash"; + function = LED_FUNCTION_FLASH; }; - indicator@1 { + led@1 { reg = <0x1>; led-max-microamp = <10000>; - label = "as3645a:indicator"; + function = LED_FUNCTION_INDICATOR; }; }; -- GitLab From b1f24498f187cf807faf3b677ffee183a6579a20 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0723/7155] leds: as3645a: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. After switching to new led_classdev_register_ext() the validity of struct led_classdev's name property is no longer guaranteed, and therefore rely on struct device's kobj.name instead. Signed-off-by: Jacek Anaszewski Cc: Sakari Ailus Acked-by: Pavel Machek --- drivers/leds/leds-as3645a.c | 74 ++++++++++++++----------------------- 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index 050088dff8dd..b7e0ae1af8fa 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -124,11 +124,6 @@ struct as3645a_config { u32 peak; }; -struct as3645a_names { - char flash[32]; - char indicator[32]; -}; - struct as3645a { struct i2c_client *client; @@ -484,12 +479,10 @@ static int as3645a_detect(struct as3645a *flash) } static int as3645a_parse_node(struct as3645a *flash, - struct as3645a_names *names, struct fwnode_handle *fwnode) { struct as3645a_config *cfg = &flash->cfg; struct fwnode_handle *child; - const char *name; int rval; fwnode_for_each_child_node(fwnode, child) { @@ -517,17 +510,6 @@ static int as3645a_parse_node(struct as3645a *flash, return -ENODEV; } - rval = fwnode_property_read_string(flash->flash_node, "label", &name); - if (!rval) { - strlcpy(names->flash, name, sizeof(names->flash)); - } else if (is_of_node(fwnode)) { - snprintf(names->flash, sizeof(names->flash), - "%pOFn:flash", to_of_node(fwnode)); - } else { - dev_err(&flash->client->dev, "flash node has no label!\n"); - return -EINVAL; - } - rval = fwnode_property_read_u32(flash->flash_node, "flash-timeout-us", &cfg->flash_timeout_us); if (rval < 0) { @@ -565,17 +547,6 @@ static int as3645a_parse_node(struct as3645a *flash, goto out_err; } - rval = fwnode_property_read_string(flash->indicator_node, "label", - &name); - if (!rval) { - strlcpy(names->indicator, name, sizeof(names->indicator)); - } else if (is_of_node(fwnode)) { - snprintf(names->indicator, sizeof(names->indicator), - "%pOFn:indicator", to_of_node(fwnode)); - } else { - dev_err(&flash->client->dev, "indicator node has no label!\n"); - return -EINVAL; - } rval = fwnode_property_read_u32(flash->indicator_node, "led-max-microamp", @@ -595,21 +566,25 @@ static int as3645a_parse_node(struct as3645a *flash, return rval; } -static int as3645a_led_class_setup(struct as3645a *flash, - struct as3645a_names *names) +static int as3645a_led_class_setup(struct as3645a *flash) { struct led_classdev *fled_cdev = &flash->fled.led_cdev; struct led_classdev *iled_cdev = &flash->iled_cdev; + struct led_init_data init_data = {}; struct led_flash_setting *cfg; int rval; - iled_cdev->name = names->indicator; iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness; iled_cdev->max_brightness = flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP; iled_cdev->flags = LED_CORE_SUSPENDRESUME; - rval = led_classdev_register(&flash->client->dev, iled_cdev); + init_data.fwnode = flash->indicator_node; + init_data.devicename = AS_NAME; + init_data.default_label = "indicator"; + + rval = led_classdev_register_ext(&flash->client->dev, iled_cdev, + &init_data); if (rval < 0) return rval; @@ -627,7 +602,6 @@ static int as3645a_led_class_setup(struct as3645a *flash, flash->fled.ops = &as3645a_led_flash_ops; - fled_cdev->name = names->flash; fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness; /* Value 0 is off in LED class. */ fled_cdev->max_brightness = @@ -635,15 +609,23 @@ static int as3645a_led_class_setup(struct as3645a *flash, flash->cfg.assist_max_ua) + 1; fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME; - rval = led_classdev_flash_register(&flash->client->dev, &flash->fled); - if (rval) { - led_classdev_unregister(iled_cdev); - dev_err(&flash->client->dev, - "led_classdev_flash_register() failed, error %d\n", - rval); - } + init_data.fwnode = flash->flash_node; + init_data.devicename = AS_NAME; + init_data.default_label = "flash"; + + rval = led_classdev_flash_register_ext(&flash->client->dev, + &flash->fled, &init_data); + if (rval) + goto out_err; return rval; + +out_err: + led_classdev_unregister(iled_cdev); + dev_err(&flash->client->dev, + "led_classdev_flash_register() failed, error %d\n", + rval); + return rval; } static int as3645a_v4l2_setup(struct as3645a *flash) @@ -667,8 +649,9 @@ static int as3645a_v4l2_setup(struct as3645a *flash) }, }; - strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name)); - strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfgind.dev_name)); + strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name)); + strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name, + sizeof(cfgind.dev_name)); flash->vf = v4l2_flash_init( &flash->client->dev, flash->flash_node, &flash->fled, NULL, @@ -689,7 +672,6 @@ static int as3645a_v4l2_setup(struct as3645a *flash) static int as3645a_probe(struct i2c_client *client) { - struct as3645a_names names; struct as3645a *flash; int rval; @@ -702,7 +684,7 @@ static int as3645a_probe(struct i2c_client *client) flash->client = client; - rval = as3645a_parse_node(flash, &names, dev_fwnode(&client->dev)); + rval = as3645a_parse_node(flash, dev_fwnode(&client->dev)); if (rval < 0) return rval; @@ -717,7 +699,7 @@ static int as3645a_probe(struct i2c_client *client) if (rval) goto out_mutex_destroy; - rval = as3645a_led_class_setup(flash, &names); + rval = as3645a_led_class_setup(flash); if (rval) goto out_mutex_destroy; -- GitLab From a1c60ec95d15e50aef47e22197181dc6fd1dd01f Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0724/7155] dt-bindings: leds-gpio: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Cc: Linus Walleij Reviewed-by: Rob Herring --- .../devicetree/bindings/leds/leds-gpio.txt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt index a48dda268f81..d21281b63d38 100644 --- a/Documentation/devicetree/bindings/leds/leds-gpio.txt +++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt @@ -10,8 +10,12 @@ LED sub-node properties: - gpios : Should specify the LED's GPIO, see "gpios property" in Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be indicated using flags in the GPIO specifier. -- label : (optional) +- function : (optional) + see Documentation/devicetree/bindings/leds/common.txt +- color : (optional) see Documentation/devicetree/bindings/leds/common.txt +- label : (optional) + see Documentation/devicetree/bindings/leds/common.txt (deprecated) - linux,default-trigger : (optional) see Documentation/devicetree/bindings/leds/common.txt - default-state: (optional) The initial state of the LED. @@ -27,30 +31,34 @@ LED sub-node properties: Examples: #include +#include leds { compatible = "gpio-leds"; - hdd { - label = "Disk Activity"; + led0 { gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>; linux,default-trigger = "disk-activity"; + function = LED_FUNCTION_DISK; }; - fault { + led1 { gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>; /* Keep LED on if BIOS detected hardware fault */ default-state = "keep"; + function = LED_FUNCTION_FAULT; }; }; run-control { compatible = "gpio-leds"; - red { + led0 { gpios = <&mpc8572 6 GPIO_ACTIVE_HIGH>; + color = ; default-state = "off"; }; - green { + led1 { gpios = <&mpc8572 7 GPIO_ACTIVE_HIGH>; + color = ; default-state = "on"; }; }; @@ -58,9 +66,10 @@ run-control { leds { compatible = "gpio-leds"; - charger-led { + led0 { gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; linux,default-trigger = "max8903-charger-charging"; retain-state-suspended; + function = LED_FUNCTION_CHARGE; }; }; -- GitLab From d7235f5feaa0d53e27a369a3198827c921103c24 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0725/7155] leds: gpio: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Linus Walleij Acked-by: Pavel Machek --- drivers/leds/leds-gpio.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 8f463c912db8..a5c73f3d5f79 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -73,11 +73,11 @@ static int gpio_blink_set(struct led_classdev *led_cdev, static int create_gpio_led(const struct gpio_led *template, struct gpio_led_data *led_dat, struct device *parent, - struct device_node *np, gpio_blink_set_t blink_set) + struct fwnode_handle *fwnode, gpio_blink_set_t blink_set) { + struct led_init_data init_data = {}; int ret, state; - led_dat->cdev.name = template->name; led_dat->cdev.default_trigger = template->default_trigger; led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); if (!led_dat->can_sleep) @@ -108,7 +108,16 @@ static int create_gpio_led(const struct gpio_led *template, if (ret < 0) return ret; - return devm_led_classdev_register(parent, &led_dat->cdev); + if (template->name) { + led_dat->cdev.name = template->name; + ret = devm_led_classdev_register(parent, &led_dat->cdev); + } else { + init_data.fwnode = fwnode; + ret = devm_led_classdev_register_ext(parent, &led_dat->cdev, + &init_data); + } + + return ret; } struct gpio_leds_priv { @@ -141,15 +150,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) struct gpio_led_data *led_dat = &priv->leds[priv->num_leds]; struct gpio_led led = {}; const char *state = NULL; - struct device_node *np = to_of_node(child); - - ret = fwnode_property_read_string(child, "label", &led.name); - if (ret && IS_ENABLED(CONFIG_OF) && np) - led.name = np->name; - if (!led.name) { - fwnode_handle_put(child); - return ERR_PTR(-EINVAL); - } led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child, GPIOD_ASIS, @@ -181,7 +181,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) if (fwnode_property_present(child, "panic-indicator")) led.panic_indicator = 1; - ret = create_gpio_led(&led, led_dat, dev, np, NULL); + ret = create_gpio_led(&led, led_dat, dev, child, NULL); if (ret < 0) { fwnode_handle_put(child); return ERR_PTR(ret); -- GitLab From 91f1be8a83273cd9069e07a7f65955c6d5dfad6a Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0726/7155] dt-bindings: an30259a: Add function and color properties Refer to new "function" and "color" properties and mark "label" as deprecated. Signed-off-by: Jacek Anaszewski Cc: Simon Shields Reviewed-by: Rob Herring --- .../bindings/leds/leds-an30259a.txt | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-an30259a.txt b/Documentation/devicetree/bindings/leds/leds-an30259a.txt index 6ffb861083c0..cbd833906b2b 100644 --- a/Documentation/devicetree/bindings/leds/leds-an30259a.txt +++ b/Documentation/devicetree/bindings/leds/leds-an30259a.txt @@ -15,10 +15,19 @@ Required sub-node properties: - reg: Pin that the LED is connected to. Must be 1, 2, or 3. Optional sub-node properties: - - label: see Documentation/devicetree/bindings/leds/common.txt - - linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt + - function : + see Documentation/devicetree/bindings/leds/common.txt + - color : + see Documentation/devicetree/bindings/leds/common.txt + - label : + see Documentation/devicetree/bindings/leds/common.txt (deprecated) + - linux,default-trigger : + see Documentation/devicetree/bindings/leds/common.txt Example: + +#include + led-controller@30 { compatible = "panasonic,an30259a"; reg = <0x30>; @@ -28,16 +37,19 @@ led-controller@30 { led@1 { reg = <1>; linux,default-trigger = "heartbeat"; - label = "red:indicator"; + function = LED_FUNCTION_INDICATOR; + color = ; }; led@2 { reg = <2>; - label = "green:indicator"; + function = LED_FUNCTION_INDICATOR; + color = ; }; led@3 { reg = <3>; - label = "blue:indicator"; + function = LED_FUNCTION_INDICATOR; + color = ; }; }; -- GitLab From 1817208e14c6f7b451c64d7127e130e5ed926f54 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:04 +0200 Subject: [PATCH 0727/7155] leds: an30259a: Use generic support for composing LED names Switch to using generic LED support for composing LED class device name. Signed-off-by: Jacek Anaszewski Cc: Simon Shields Acked-by: Pavel Machek --- drivers/leds/leds-an30259a.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 37e7c7998972..250dc9d6f635 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -13,7 +13,6 @@ #include #include #include -#include #define AN30259A_MAX_LEDS 3 @@ -54,6 +53,8 @@ #define AN30259A_BLINK_MAX_TIME 7500 /* ms */ #define AN30259A_SLOPE_RESOLUTION 500 /* ms */ +#define AN30259A_NAME "an30259a" + #define STATE_OFF 0 #define STATE_KEEP 1 #define STATE_ON 2 @@ -62,11 +63,11 @@ struct an30259a; struct an30259a_led { struct an30259a *chip; + struct fwnode_handle *fwnode; struct led_classdev cdev; u32 num; u32 default_state; bool sloping; - char label[LED_MAX_NAME_SIZE]; }; struct an30259a { @@ -226,14 +227,7 @@ static int an30259a_dt_init(struct i2c_client *client, led->num = source; led->chip = chip; - - if (of_property_read_string(child, "label", &str)) - snprintf(led->label, sizeof(led->label), "an30259a::"); - else - snprintf(led->label, sizeof(led->label), "an30259a:%s", - str); - - led->cdev.name = led->label; + led->fwnode = of_fwnode_handle(child); if (!of_property_read_string(child, "default-state", &str)) { if (!strcmp(str, "on")) @@ -312,13 +306,20 @@ static int an30259a_probe(struct i2c_client *client) chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config); for (i = 0; i < chip->num_leds; i++) { + struct led_init_data init_data = {}; + an30259a_init_default_state(&chip->leds[i]); chip->leds[i].cdev.brightness_set_blocking = an30259a_brightness_set; chip->leds[i].cdev.blink_set = an30259a_blink_set; - err = devm_led_classdev_register(&client->dev, - &chip->leds[i].cdev); + init_data.fwnode = chip->leds[i].fwnode; + init_data.devicename = AN30259A_NAME; + init_data.default_label = ":"; + + err = devm_led_classdev_register_ext(&client->dev, + &chip->leds[i].cdev, + &init_data); if (err < 0) goto exit; } -- GitLab From cc93c86370086519f69aefbbac18375f0b489a0e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:57 +0300 Subject: [PATCH 0728/7155] leds: lm3532: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3532.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 180895b83b88..646100724971 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -549,10 +549,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) lm3532_als_configure(priv, led); } - led->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); - + led->num_leds = fwnode_property_count_u32(child, "led-sources"); if (led->num_leds > LM3532_MAX_LED_STRINGS) { dev_err(&priv->client->dev, "To many LED string defined\n"); continue; -- GitLab From ebefec8d9fc07eafa7434df1a1c2447b0ea96e50 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:58 +0300 Subject: [PATCH 0729/7155] leds: lm36274: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm36274.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c index ed9dc857ec8f..836b60c9a2b8 100644 --- a/drivers/leds/leds-lm36274.c +++ b/drivers/leds/leds-lm36274.c @@ -90,9 +90,7 @@ static int lm36274_parse_dt(struct lm36274 *lm36274_data) snprintf(label, sizeof(label), "%s:%s", lm36274_data->pdev->name, name); - lm36274_data->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); + lm36274_data->num_leds = fwnode_property_count_u32(child, "led-sources"); if (lm36274_data->num_leds <= 0) return -ENODEV; -- GitLab From 246eab59eefc26706e59520cf20d2315377efa08 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:14:59 +0300 Subject: [PATCH 0730/7155] leds: lm3697: Switch to use fwnode_property_count_uXX() Use fwnode_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3697.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 54e0e35df824..b71711aff8a3 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -244,10 +244,7 @@ static int lm3697_probe_dt(struct lm3697 *priv) led->lmu_data.lsb_brightness_reg = LM3697_CTRL_A_BRT_LSB + led->control_bank * 2; - led->num_leds = fwnode_property_read_u32_array(child, - "led-sources", - NULL, 0); - + led->num_leds = fwnode_property_count_u32(child, "led-sources"); if (led->num_leds > LM3697_MAX_LED_STRINGS) { dev_err(&priv->client->dev, "To many LED strings defined\n"); continue; -- GitLab From c93496e9f7680741c25bab866e729e9606bfae3e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:35 +0200 Subject: [PATCH 0731/7155] net: sfc: falcon: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(). So, we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/falcon/falcon_boards.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/sfc/falcon/falcon_boards.c b/drivers/net/ethernet/sfc/falcon/falcon_boards.c index 2d85d1386ed9..605f486fa675 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon_boards.c +++ b/drivers/net/ethernet/sfc/falcon/falcon_boards.c @@ -454,13 +454,13 @@ static int sfe4001_init(struct ef4_nic *efx) #if IS_ENABLED(CONFIG_SENSORS_LM90) board->hwmon_client = - i2c_new_device(&board->i2c_adap, &sfe4001_hwmon_info); + i2c_new_client_device(&board->i2c_adap, &sfe4001_hwmon_info); #else board->hwmon_client = - i2c_new_dummy(&board->i2c_adap, sfe4001_hwmon_info.addr); + i2c_new_dummy_device(&board->i2c_adap, sfe4001_hwmon_info.addr); #endif - if (!board->hwmon_client) - return -EIO; + if (IS_ERR(board->hwmon_client)) + return PTR_ERR(board->hwmon_client); /* Raise board/PHY high limit from 85 to 90 degrees Celsius */ rc = i2c_smbus_write_byte_data(board->hwmon_client, @@ -468,9 +468,9 @@ static int sfe4001_init(struct ef4_nic *efx) if (rc) goto fail_hwmon; - board->ioexp_client = i2c_new_dummy(&board->i2c_adap, PCA9539); - if (!board->ioexp_client) { - rc = -EIO; + board->ioexp_client = i2c_new_dummy_device(&board->i2c_adap, PCA9539); + if (IS_ERR(board->ioexp_client)) { + rc = PTR_ERR(board->ioexp_client); goto fail_hwmon; } -- GitLab From 3123c5c4ca157edc518102ee5385f60cb90f93f5 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Fri, 12 Jul 2019 13:28:43 -0500 Subject: [PATCH 0732/7155] edac: altera: Move Stratix10 SDRAM ECC to peripheral ARM32 SoCFPGAs had separate IRQs for SDRAM. ARM64 SoCFPGAs send all DBEs to SError so filtering by source is necessary. The Stratix10 SDRAM ECC is a better match with the generic Altera peripheral ECC framework because the linked list can be searched to find the ECC block offset and printout the DBE Address. Signed-off-by: Thor Thayer Acked-by: James Morse Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/altera_edac.c | 54 +++++++++++++++++++++++++++++++++++--- drivers/edac/altera_edac.h | 25 +++++++++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index c2e693e34d43..09a80b53acea 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -222,7 +222,6 @@ static unsigned long get_total_mem(void) static const struct of_device_id altr_sdram_ctrl_of_match[] = { { .compatible = "altr,sdram-edac", .data = &c5_data}, { .compatible = "altr,sdram-edac-a10", .data = &a10_data}, - { .compatible = "altr,sdram-edac-s10", .data = &a10_data}, {}, }; MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); @@ -1170,6 +1169,24 @@ static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat) return 0; } +/*********************** SDRAM EDAC Device Functions *********************/ + +#ifdef CONFIG_EDAC_ALTERA_SDRAM + +static const struct edac_device_prv_data s10_sdramecc_data = { + .setup = altr_check_ecc_deps, + .ce_clear_mask = ALTR_S10_ECC_SERRPENA, + .ue_clear_mask = ALTR_S10_ECC_DERRPENA, + .ecc_enable_mask = ALTR_S10_ECC_EN, + .ecc_en_ofst = ALTR_S10_ECC_CTRL_SDRAM_OFST, + .ce_set_mask = ALTR_S10_ECC_TSERRA, + .ue_set_mask = ALTR_S10_ECC_TDERRA, + .set_err_ofst = ALTR_S10_ECC_INTTEST_OFST, + .ecc_irq_handler = altr_edac_a10_ecc_irq, + .inject_fops = &altr_edac_a10_device_inject_fops, +}; +#endif /* CONFIG_EDAC_ALTERA_SDRAM */ + /*********************** OCRAM EDAC Device Functions *********************/ #ifdef CONFIG_EDAC_ALTERA_OCRAM @@ -1758,6 +1775,9 @@ static const struct of_device_id altr_edac_a10_device_of_match[] = { #endif #ifdef CONFIG_EDAC_ALTERA_SDMMC { .compatible = "altr,socfpga-sdmmc-ecc", .data = &a10_sdmmcecca_data }, +#endif +#ifdef CONFIG_EDAC_ALTERA_SDRAM + { .compatible = "altr,sdram-edac-s10", .data = &s10_sdramecc_data }, #endif {}, }; @@ -1889,6 +1909,10 @@ static int validate_parent_available(struct device_node *np) struct device_node *parent; int ret = 0; + /* SDRAM must be present for Linux (implied parent) */ + if (of_device_is_compatible(np, "altr,sdram-edac-s10")) + return 0; + /* Ensure parent device is enabled if parent node exists */ parent = of_parse_phandle(np, "altr,ecc-parent", 0); if (parent && !of_device_is_available(parent)) @@ -1898,6 +1922,22 @@ static int validate_parent_available(struct device_node *np) return ret; } +static int get_s10_sdram_edac_resource(struct device_node *np, + struct resource *res) +{ + struct device_node *parent; + int ret; + + parent = of_parse_phandle(np, "altr,sdr-syscon", 0); + if (!parent) + return -ENODEV; + + ret = of_address_to_resource(parent, 0, res); + of_node_put(parent); + + return ret; +} + static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, struct device_node *np) { @@ -1925,7 +1965,11 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL)) return -ENOMEM; - rc = of_address_to_resource(np, 0, &res); + if (of_device_is_compatible(np, "altr,sdram-edac-s10")) + rc = get_s10_sdram_edac_resource(np, &res); + else + rc = of_address_to_resource(np, 0, &res); + if (rc < 0) { edac_printk(KERN_ERR, EDAC_DEVICE, "%s: no resource address\n", ecc_name); @@ -2231,13 +2275,15 @@ static int altr_edac_a10_probe(struct platform_device *pdev) of_device_is_compatible(child, "altr,socfpga-dma-ecc") || of_device_is_compatible(child, "altr,socfpga-usb-ecc") || of_device_is_compatible(child, "altr,socfpga-qspi-ecc") || +#ifdef CONFIG_EDAC_ALTERA_SDRAM + of_device_is_compatible(child, "altr,sdram-edac-s10") || +#endif of_device_is_compatible(child, "altr,socfpga-sdmmc-ecc")) altr_edac_a10_device_add(edac, child); #ifdef CONFIG_EDAC_ALTERA_SDRAM - else if ((of_device_is_compatible(child, "altr,sdram-edac-a10")) || - (of_device_is_compatible(child, "altr,sdram-edac-s10"))) + else if (of_device_is_compatible(child, "altr,sdram-edac-a10")) of_platform_populate(pdev->dev.of_node, altr_sdram_ctrl_of_match, NULL, &pdev->dev); diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index 55654cc4bcdf..3727e72c8c2e 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -289,6 +289,29 @@ struct altr_sdram_mc_data { #define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000 /************* Stratix10 Defines **************/ +#define ALTR_S10_ECC_CTRL_SDRAM_OFST 0x00 +#define ALTR_S10_ECC_EN BIT(0) + +#define ALTR_S10_ECC_ERRINTEN_OFST 0x10 +#define ALTR_S10_ECC_ERRINTENS_OFST 0x14 +#define ALTR_S10_ECC_ERRINTENR_OFST 0x18 +#define ALTR_S10_ECC_SERRINTEN BIT(0) + +#define ALTR_S10_ECC_INTMODE_OFST 0x1C +#define ALTR_S10_ECC_INTMODE BIT(0) + +#define ALTR_S10_ECC_INTSTAT_OFST 0x20 +#define ALTR_S10_ECC_SERRPENA BIT(0) +#define ALTR_S10_ECC_DERRPENA BIT(8) +#define ALTR_S10_ECC_ERRPENA_MASK (ALTR_S10_ECC_SERRPENA | \ + ALTR_S10_ECC_DERRPENA) + +#define ALTR_S10_ECC_INTTEST_OFST 0x24 +#define ALTR_S10_ECC_TSERRA BIT(0) +#define ALTR_S10_ECC_TDERRA BIT(8) +#define ALTR_S10_ECC_TSERRB BIT(16) +#define ALTR_S10_ECC_TDERRB BIT(24) + #define ALTR_S10_DERR_ADDRA_OFST 0x2C /* Stratix10 ECC Manager Defines */ @@ -300,7 +323,7 @@ struct altr_sdram_mc_data { #define S10_SYSMGR_UE_ADDR_OFST 0x224 #define S10_DDR0_IRQ_MASK BIT(16) -#define S10_DBE_IRQ_MASK 0x3FE +#define S10_DBE_IRQ_MASK 0x3FFFE /* Define ECC Block Offsets for peripherals */ #define ECC_BLK_ADDRESS_OFST 0x40 -- GitLab From b06689cc1b0446b959ed1a41b4f8dd892aa6b331 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Tue, 23 Jul 2019 10:57:41 +0300 Subject: [PATCH 0733/7155] mlxsw: spectrum: Expose KVD size for Spectrum-2 Unlike Spectrum-1, the KVD (Key-value database) of Spectrum-2 is not partitioned, so only expose the entire KVD size. This enables users to query the total size of the KVD. Signed-off-by: Amit Cohen Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 650638152bbc..7e8a54068d92 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -5026,6 +5026,26 @@ static int mlxsw_sp1_resources_kvd_register(struct mlxsw_core *mlxsw_core) return 0; } +static int mlxsw_sp2_resources_kvd_register(struct mlxsw_core *mlxsw_core) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + struct devlink_resource_size_params kvd_size_params; + u32 kvd_size; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE)) + return -EIO; + + kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE); + devlink_resource_size_params_init(&kvd_size_params, kvd_size, kvd_size, + MLXSW_SP_KVD_GRANULARITY, + DEVLINK_RESOURCE_UNIT_ENTRY); + + return devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD, + kvd_size, MLXSW_SP_RESOURCE_KVD, + DEVLINK_RESOURCE_ID_PARENT_TOP, + &kvd_size_params); +} + static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) { return mlxsw_sp1_resources_kvd_register(mlxsw_core); @@ -5033,7 +5053,7 @@ static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core) { - return 0; + return mlxsw_sp2_resources_kvd_register(mlxsw_core); } static int mlxsw_sp_kvd_sizes_get(struct mlxsw_core *mlxsw_core, -- GitLab From fc25996e6f46ac05378f45691d9c6ea08c2037b9 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 23 Jul 2019 10:57:42 +0300 Subject: [PATCH 0734/7155] mlxsw: spectrum_router: Increase scale of IPv6 nexthop groups Unlike IPv4, the kernel does not consolidate IPv6 nexthop groups. To avoid exhausting the device's adjacency table - where nexthops are stored - the driver does this consolidation instead. Each nexthop group is hashed by XOR-ing the interface indexes of all the member nexthop devices. However, the ifindex itself is not hashed, which can result in identical keys used for different groups and finally an -EBUSY error from rhashtable due to too long objects list. Improve the situation by hashing the ifindex itself. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index e618be7ce6c6..a330b369e899 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2943,7 +2943,7 @@ static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed) val = nh_grp->count; for (i = 0; i < nh_grp->count; i++) { nh = &nh_grp->nexthops[i]; - val ^= nh->ifindex; + val ^= jhash(&nh->ifindex, sizeof(nh->ifindex), seed); } return jhash(&val, sizeof(val), seed); default: @@ -2961,7 +2961,7 @@ mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed) list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { dev = mlxsw_sp_rt6->rt->fib6_nh->fib_nh_dev; - val ^= dev->ifindex; + val ^= jhash(&dev->ifindex, sizeof(dev->ifindex), seed); } return jhash(&val, sizeof(val), seed); -- GitLab From 37f7c66f4560b154cfa7a8d8f1902e222e38adba Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Tue, 23 Jul 2019 16:54:05 +0800 Subject: [PATCH 0735/7155] ptp: ptp_dte: remove redundant dev_err message devm_ioremap_resource already contains error message, so remove the redundant dev_err message Signed-off-by: Ding Xiang Signed-off-by: David S. Miller --- drivers/ptp/ptp_dte.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/ptp/ptp_dte.c b/drivers/ptp/ptp_dte.c index 5b6393e3ea27..0dcfdc806f57 100644 --- a/drivers/ptp/ptp_dte.c +++ b/drivers/ptp/ptp_dte.c @@ -248,11 +248,8 @@ static int ptp_dte_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ptp_dte->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(ptp_dte->regs)) { - dev_err(dev, - "%s: io remap failed\n", __func__); + if (IS_ERR(ptp_dte->regs)) return PTR_ERR(ptp_dte->regs); - } spin_lock_init(&ptp_dte->lock); -- GitLab From 5882d65c169152178e6fb2fa2e5e3a72fcb08248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 24 Jul 2019 20:17:15 +0100 Subject: [PATCH 0736/7155] arm64: dts: rockchip: Add PWM fan for RockPro64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RockPro64 has a dedicated circuit for driving a 12V fan from PWM1. At the moment this makes fan spin at full speed. fancontrol can be used to control fan speed. E.g. the following config file works well: INTERVAL=10 DEVPATH=hwmon0=devices/platform/pwm-fan DEVNAME=hwmon0=pwmfan FCTEMPS=hwmon0/device/pwm1=../thermal/thermal_zone0/temp MINTEMP=hwmon0/device/pwm1=40 MAXTEMP=hwmon0/device/pwm1=60 MINSTART=hwmon0/device/pwm1=100 MINSTOP=hwmon0/device/pwm1=70 In the future it would be nice to define trip points in dts file, so that kernel could adjust fan speed itself. Signed-off-by: Andrius Štikonas Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts index eb5594062006..076fa0fd103c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts @@ -58,6 +58,13 @@ }; }; + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + fan-supply = <&vcc12v_dcin>; + pwms = <&pwm1 0 50000 0>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; clocks = <&rk808 1>; @@ -602,6 +609,10 @@ status = "okay"; }; +&pwm1 { + status = "okay"; +}; + &pwm2 { status = "okay"; }; -- GitLab From 31ed9d9d71ec396d38090a85f5b3dbd6936650b4 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 23 Jul 2019 15:52:58 -0700 Subject: [PATCH 0737/7155] ARM: dts: rockchip: Limit WiFi TX power on rk3288-veyron-jerry The downstream Chrome OS 3.14 kernel for jerry limits WiFi TX power through calibration data in the device tree [1]. Add a DT node for the WiFi chip and use the downstream calibration data. Not all calibration data entries have the length specified in the binding (Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt), however this is the data used by the downstream ('official') kernel and the binding mentions that "the length can vary between hw versions". [1] https://crrev.com/c/271237 Signed-off-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-jerry.dts | 149 ++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts index 164561f04c1d..5abb9d228b6c 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts @@ -82,6 +82,155 @@ }; }; +&sdio0 { + #address-cells = <1>; + #size-cells = <0>; + + mwifiex: wifi@1 { + compatible = "marvell,sd8897"; + reg = <1>; + + marvell,caldata-txpwrlimit-2g = /bits/ 8 < +0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x01 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x02 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x03 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x04 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x05 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x06 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x07 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x08 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x09 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x0a 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x0b 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 0x24 0x00 0x67 0x09 0x14 0x0c 0x00 0x0f +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c 0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x89 0x01 +0x24 0x00 0x67 0x09 0x14 0x0d 0x00 0x0f 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0c +0x05 0x0c 0x06 0x0c 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0c 0x0b 0x0c 0x0c 0x0c +0x0d 0x09 0x0e 0x09 0x0f 0x09>; + + marvell,caldata-txpwrlimit-5g-sub0 = /bits/ 8 < +0x01 0x00 0x06 0x00 0xf0 0x01 0x89 0x01 +0x3a 0x00 0x88 0x13 0x14 0x24 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a +0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 +0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 +0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 +0x88 0x13 0x14 0x28 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a +0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 +0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 +0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 +0x14 0x2c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 +0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 +0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 +0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x30 +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 +0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 +0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x34 0x01 0x0c +0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 +0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 +0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 +0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x38 0x01 0x0c 0x02 0x0c +0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a +0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 +0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 +0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x3c 0x01 0x0c 0x02 0x0c 0x03 0x0c +0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a +0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 +0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 +0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x40 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a +0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 +0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05>; + + marvell,caldata-txpwrlimit-5g-sub1 = /bits/ 8 < +0x01 0x00 0x06 0x00 0xaa 0x02 0x89 0x01 +0x3a 0x00 0x88 0x13 0x14 0x64 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a +0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 +0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 +0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 +0x88 0x13 0x14 0x68 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a +0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 +0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 +0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 +0x14 0x6c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 +0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 +0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 +0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x70 +0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 +0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 +0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 +0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x74 0x01 0x0c +0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 +0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 +0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 +0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x78 0x01 0x0c 0x02 0x0c +0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a +0x0b 0x0a 0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 +0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 +0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x7c 0x01 0x0c 0x02 0x0c 0x03 0x0c +0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a +0x0c 0x0a 0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 +0x14 0x05 0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 +0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0x80 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a +0x05 0x0a 0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a +0x0d 0x09 0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 +0x15 0x05 0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 +0x3a 0x00 0x88 0x13 0x14 0x84 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a +0x06 0x0a 0x07 0x09 0x08 0x09 0x09 0x09 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x09 +0x0e 0x09 0x0f 0x09 0x10 0x05 0x11 0x05 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 +0x16 0x05 0x17 0x05 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 +0x88 0x13 0x14 0x88 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a +0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 +0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 +0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 +0x14 0x8c 0x01 0x0c 0x02 0x0c 0x03 0x0c 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 +0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 +0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 +0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05>; + + marvell,caldata-txpwrlimit-5g-sub2 = /bits/ 8 < +0x01 0x00 0x06 0x00 0x36 0x01 0x89 0x01 +0x3a 0x00 0x88 0x13 0x14 0x95 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a +0x06 0x0a 0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 +0x0e 0x08 0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 +0x16 0x04 0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 +0x88 0x13 0x14 0x99 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a +0x07 0x08 0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 +0x0f 0x08 0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 +0x17 0x04 0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 +0x14 0x9d 0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 +0x08 0x08 0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 +0x10 0x04 0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 +0x18 0x05 0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0xa1 +0x01 0x0b 0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 0x08 0x08 +0x09 0x08 0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 0x10 0x04 +0x11 0x04 0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 0x18 0x05 +0x19 0x05 0x1a 0x05 0x1b 0x05 0x89 0x01 0x3a 0x00 0x88 0x13 0x14 0xa5 0x01 0x0b +0x02 0x0b 0x03 0x0b 0x04 0x0a 0x05 0x0a 0x06 0x0a 0x07 0x08 0x08 0x08 0x09 0x08 +0x0a 0x0a 0x0b 0x0a 0x0c 0x0a 0x0d 0x08 0x0e 0x08 0x0f 0x08 0x10 0x04 0x11 0x04 +0x12 0x05 0x13 0x05 0x14 0x05 0x15 0x05 0x16 0x04 0x17 0x04 0x18 0x05 0x19 0x05 +0x1a 0x05 0x1b 0x05>; + }; +}; + &sdmmc { disable-wp; pinctrl-names = "default"; -- GitLab From ab9640000d92d29a342656424d763c138d1dd66b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 25 Jul 2019 09:26:38 -0700 Subject: [PATCH 0738/7155] ARM: dts: rockchip: move rk3288-veryon display settings into a separate file The chromebook .dtsi file contains common settings for veyron Chromebooks with eDP displays. Some veyron devices with a display aren't Chromebooks (e.g. 'tiger' aka 'AOpen Chromebase Mini'), move display related bits from the chromebook .dtsi into a separate file to avoid redundant DT settings. The new file is included from the chromebook .dtsi and can be included by non-Chromebook devices with a display. Signed-off-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- .../boot/dts/rk3288-veyron-chromebook.dtsi | 115 +--------------- arch/arm/boot/dts/rk3288-veyron-edp.dtsi | 124 ++++++++++++++++++ 2 files changed, 125 insertions(+), 114 deletions(-) create mode 100644 arch/arm/boot/dts/rk3288-veyron-edp.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi index 6a28ce345ba0..ffb60f880b39 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi @@ -10,6 +10,7 @@ #include #include "rk3288-veyron.dtsi" #include "rk3288-veyron-analog-audio.dtsi" +#include "rk3288-veyron-edp.dtsi" #include "rk3288-veyron-sdmmc.dtsi" / { @@ -18,50 +19,6 @@ i2c20 = &i2c_tunnel; }; - backlight: backlight { - compatible = "pwm-backlight"; - brightness-levels = < - 0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30 31 - 32 33 34 35 36 37 38 39 - 40 41 42 43 44 45 46 47 - 48 49 50 51 52 53 54 55 - 56 57 58 59 60 61 62 63 - 64 65 66 67 68 69 70 71 - 72 73 74 75 76 77 78 79 - 80 81 82 83 84 85 86 87 - 88 89 90 91 92 93 94 95 - 96 97 98 99 100 101 102 103 - 104 105 106 107 108 109 110 111 - 112 113 114 115 116 117 118 119 - 120 121 122 123 124 125 126 127 - 128 129 130 131 132 133 134 135 - 136 137 138 139 140 141 142 143 - 144 145 146 147 148 149 150 151 - 152 153 154 155 156 157 158 159 - 160 161 162 163 164 165 166 167 - 168 169 170 171 172 173 174 175 - 176 177 178 179 180 181 182 183 - 184 185 186 187 188 189 190 191 - 192 193 194 195 196 197 198 199 - 200 201 202 203 204 205 206 207 - 208 209 210 211 212 213 214 215 - 216 217 218 219 220 221 222 223 - 224 225 226 227 228 229 230 231 - 232 233 234 235 236 237 238 239 - 240 241 242 243 244 245 246 247 - 248 249 250 251 252 253 254 255>; - default-brightness-level = <128>; - enable-gpios = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&bl_en>; - pwms = <&pwm0 0 1000000 0>; - post-pwm-on-delay-ms = <10>; - pwm-off-delay-ms = <10>; - }; - gpio-charger { compatible = "gpio-charger"; charger-type = "mains"; @@ -85,35 +42,6 @@ }; }; - panel: panel { - compatible ="innolux,n116bge", "simple-panel"; - status = "okay"; - power-supply = <&vcc33_lcd>; - backlight = <&backlight>; - - panel-timing { - clock-frequency = <74250000>; - hactive = <1366>; - hfront-porch = <136>; - hback-porch = <60>; - hsync-len = <30>; - hsync-active = <0>; - vactive = <768>; - vfront-porch = <8>; - vback-porch = <12>; - vsync-len = <12>; - vsync-active = <0>; - }; - - ports { - panel_in: port { - panel_in_edp: endpoint { - remote-endpoint = <&edp_out_panel>; - }; - }; - }; - }; - /* A non-regulated voltage from power supply or battery */ vccsys: vccsys { compatible = "regulator-fixed"; @@ -155,33 +83,6 @@ }; }; -&edp { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&edp_hpd>; - - ports { - edp_out: port@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - edp_out_panel: endpoint@0 { - reg = <0>; - remote-endpoint = <&panel_in_edp>; - }; - }; - }; -}; - -&edp_phy { - status = "okay"; -}; - -&pwm0 { - status = "okay"; -}; - &rk808 { vcc11-supply = <&vcc_5v>; @@ -234,14 +135,6 @@ }; }; -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - &pinctrl { pinctrl-0 = < /* Common for sleep and wake, but no owners */ @@ -264,12 +157,6 @@ &bt_dev_wake_sleep >; - backlight { - bl_en: bl-en { - rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - buttons { ap_lid_int_l: ap-lid-int-l { rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; diff --git a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi new file mode 100644 index 000000000000..c36fb0940478 --- /dev/null +++ b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Google Veyron (and derivatives) fragment for the edp displays + * + * Copyright 2019 Google LLC + */ + +/ { + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + enable-gpios = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en>; + pwms = <&pwm0 0 1000000 0>; + post-pwm-on-delay-ms = <10>; + pwm-off-delay-ms = <10>; + }; + + panel: panel { + compatible ="innolux,n116bge", "simple-panel"; + status = "okay"; + power-supply = <&vcc33_lcd>; + backlight = <&backlight>; + + panel-timing { + clock-frequency = <74250000>; + hactive = <1366>; + hfront-porch = <136>; + hback-porch = <60>; + hsync-len = <30>; + hsync-active = <0>; + vactive = <768>; + vfront-porch = <8>; + vback-porch = <12>; + vsync-len = <12>; + vsync-active = <0>; + }; + + ports { + panel_in: port { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + }; +}; + +&edp { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&edp_hpd>; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + +&edp_phy { + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + +&pinctrl { + backlight { + bl_en: bl-en { + rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; -- GitLab From 6b381a8e2c5f9667918cc1ed0e3daeec869b76b1 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 25 Jul 2019 09:26:39 -0700 Subject: [PATCH 0739/7155] ARM: dts: rockchip: consolidate veyron panel and backlight settings veyron jaq, jerry, minnie and speedy have mostly redundant regulator and pinctrl configurations for the panel/backlight. Consolidate these pieces in the eDP .dtsi. Also change the default power supply for the panel to 'panel_regulator', instead of overriding it in all the board files. pinky is the only device that uses 'vcc33_lcd' (the prior default), so overwrite it in this case. pinky doesn't have a complete display configuration, to keep things as they were delete the common nodes that didn't exist previously in pinky's board file. Reviewed-by: Douglas Anderson Signed-off-by: Matthias Kaehlcke Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-edp.dtsi | 51 ++++++++++++++++++- arch/arm/boot/dts/rk3288-veyron-jaq.dts | 55 -------------------- arch/arm/boot/dts/rk3288-veyron-jerry.dts | 58 ---------------------- arch/arm/boot/dts/rk3288-veyron-minnie.dts | 52 ------------------- arch/arm/boot/dts/rk3288-veyron-pinky.dts | 17 +++++++ arch/arm/boot/dts/rk3288-veyron-speedy.dts | 58 ---------------------- 6 files changed, 67 insertions(+), 224 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi index c36fb0940478..719d936b7822 100644 --- a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi @@ -6,6 +6,40 @@ */ / { + backlight_regulator: backlight-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&bl_pwr_en>; + regulator-name = "backlight_regulator"; + vin-supply = <&vcc33_sys>; + startup-delay-us = <15000>; + }; + + panel_regulator: panel-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_enable_h>; + regulator-name = "panel_regulator"; + startup-delay-us = <100000>; + vin-supply = <&vcc33_sys>; + }; + + vcc18_lcd: vcc18-lcd { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&avdd_1v8_disp_en>; + regulator-name = "vcc18_lcd"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc18_wl>; + }; + backlight: backlight { compatible = "pwm-backlight"; brightness-levels = < @@ -48,12 +82,13 @@ pwms = <&pwm0 0 1000000 0>; post-pwm-on-delay-ms = <10>; pwm-off-delay-ms = <10>; + power-supply = <&backlight_regulator>; }; panel: panel { compatible ="innolux,n116bge", "simple-panel"; status = "okay"; - power-supply = <&vcc33_lcd>; + power-supply = <&panel_regulator>; backlight = <&backlight>; panel-timing { @@ -117,8 +152,22 @@ &pinctrl { backlight { + bl_pwr_en: bl_pwr_en { + rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + bl_en: bl-en { rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + lcd { + lcd_enable_h: lcd-en { + rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + avdd_1v8_disp_en: avdd-1v8-disp-en { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; }; diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts index fcd119168cb6..80386203e85b 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts @@ -16,40 +16,6 @@ "google,veyron-jaq-rev3", "google,veyron-jaq-rev2", "google,veyron-jaq-rev1", "google,veyron-jaq", "google,veyron", "rockchip,rk3288"; - - panel_regulator: panel-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&lcd_enable_h>; - regulator-name = "panel_regulator"; - startup-delay-us = <100000>; - vin-supply = <&vcc33_sys>; - }; - - vcc18_lcd: vcc18-lcd { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&avdd_1v8_disp_en>; - regulator-name = "vcc18_lcd"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc18_wl>; - }; - - backlight_regulator: backlight-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&bl_pwr_en>; - regulator-name = "backlight_regulator"; - vin-supply = <&vcc33_sys>; - startup-delay-us = <15000>; - }; }; &backlight { @@ -87,11 +53,6 @@ 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255>; - power-supply = <&backlight_regulator>; -}; - -&panel { - power-supply = <&panel_regulator>; }; &rk808 { @@ -343,12 +304,6 @@ }; &pinctrl { - backlight { - bl_pwr_en: bl_pwr_en { - rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - buck-5v { drv_5v: drv-5v { rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; @@ -361,16 +316,6 @@ }; }; - lcd { - lcd_enable_h: lcd-en { - rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - avdd_1v8_disp_en: avdd-1v8-disp-en { - rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - pmic { dvs_1: dvs-1 { rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts index 5abb9d228b6c..a6ee44f0fe13 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts @@ -18,48 +18,6 @@ "google,veyron-jerry-rev5", "google,veyron-jerry-rev4", "google,veyron-jerry-rev3", "google,veyron-jerry", "google,veyron", "rockchip,rk3288"; - - panel_regulator: panel-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&lcd_enable_h>; - regulator-name = "panel_regulator"; - startup-delay-us = <100000>; - vin-supply = <&vcc33_sys>; - }; - - vcc18_lcd: vcc18-lcd { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&avdd_1v8_disp_en>; - regulator-name = "vcc18_lcd"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc18_wl>; - }; - - backlight_regulator: backlight-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&bl_pwr_en>; - regulator-name = "backlight_regulator"; - vin-supply = <&vcc33_sys>; - startup-delay-us = <15000>; - }; -}; - -&backlight { - power-supply = <&backlight_regulator>; -}; - -&panel { - power-supply= <&panel_regulator>; }; &rk808 { @@ -460,12 +418,6 @@ }; &pinctrl { - backlight { - bl_pwr_en: bl_pwr_en { - rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - buck-5v { drv_5v: drv-5v { rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; @@ -478,16 +430,6 @@ }; }; - lcd { - lcd_enable_h: lcd-en { - rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - avdd_1v8_disp_en: avdd-1v8-disp-en { - rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - pmic { dvs_1: dvs-1 { rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts index 4cc7d3659484..55955b082501 100644 --- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts +++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts @@ -15,40 +15,6 @@ "google,veyron-minnie-rev0", "google,veyron-minnie", "google,veyron", "rockchip,rk3288"; - backlight_regulator: backlight-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&bl_pwr_en>; - regulator-name = "backlight_regulator"; - vin-supply = <&vcc33_sys>; - startup-delay-us = <15000>; - }; - - panel_regulator: panel-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&lcd_enable_h>; - regulator-name = "panel_regulator"; - startup-delay-us = <100000>; - vin-supply = <&vcc33_sys>; - }; - - vcc18_lcd: vcc18-lcd { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&avdd_1v8_disp_en>; - regulator-name = "vcc18_lcd"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc18_wl>; - }; - volume_buttons: volume-buttons { compatible = "gpio-keys"; pinctrl-names = "default"; @@ -105,7 +71,6 @@ 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255>; - power-supply = <&backlight_regulator>; }; &i2c_tunnel { @@ -137,7 +102,6 @@ &panel { compatible = "auo,b101ean01", "simple-panel"; - power-supply= <&panel_regulator>; /delete-node/ panel-timing; @@ -411,12 +375,6 @@ }; &pinctrl { - backlight { - bl_pwr_en: bl_pwr_en { - rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - buck-5v { drv_5v: drv-5v { rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; @@ -439,16 +397,6 @@ }; }; - lcd { - lcd_enable_h: lcd-en { - rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - avdd_1v8_disp_en: avdd-1v8-disp-en { - rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - pmic { dvs_1: dvs-1 { rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rk3288-veyron-pinky.dts index 9b6f4d9b03b6..f420499f300a 100644 --- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts +++ b/arch/arm/boot/dts/rk3288-veyron-pinky.dts @@ -14,7 +14,14 @@ compatible = "google,veyron-pinky-rev2", "google,veyron-pinky", "google,veyron", "rockchip,rk3288"; + /delete-node/backlight-regulator; + /delete-node/panel-regulator; /delete-node/emmc-pwrseq; + /delete-node/vcc18-lcd; +}; + +&backlight { + /delete-property/power-supply; }; &emmc { @@ -52,7 +59,17 @@ i2c-scl-rising-time-ns = <300>; }; +&panel { + power-supply = <&vcc33_lcd>; +}; + &pinctrl { + /delete-node/ lcd; + + backlight { + /delete-node/ bl_pwr_en; + }; + buttons { pwr_key_h: pwr-key-h { rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts index 9b140db04456..2f2989bc3f9c 100644 --- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts +++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts @@ -16,44 +16,6 @@ "google,veyron-speedy-rev5", "google,veyron-speedy-rev4", "google,veyron-speedy-rev3", "google,veyron-speedy-rev2", "google,veyron-speedy", "google,veyron", "rockchip,rk3288"; - - panel_regulator: panel-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&lcd_enable_h>; - regulator-name = "panel_regulator"; - startup-delay-us = <100000>; - vin-supply = <&vcc33_sys>; - }; - - vcc18_lcd: vcc18-lcd { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&avdd_1v8_disp_en>; - regulator-name = "vcc18_lcd"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc18_wl>; - }; - - backlight_regulator: backlight-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&bl_pwr_en>; - regulator-name = "backlight_regulator"; - vin-supply = <&vcc33_sys>; - startup-delay-us = <15000>; - }; -}; - -&backlight { - power-supply = <&backlight_regulator>; }; &cpu_alert0 { @@ -83,10 +45,6 @@ temperature = <90000>; }; -&panel { - power-supply= <&panel_regulator>; -}; - &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l>; @@ -321,12 +279,6 @@ }; &pinctrl { - backlight { - bl_pwr_en: bl_pwr_en { - rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - buck-5v { drv_5v: drv-5v { rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; @@ -339,16 +291,6 @@ }; }; - lcd { - lcd_enable_h: lcd-en { - rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - avdd_1v8_disp_en: avdd-1v8-disp-en { - rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - pmic { dvs_1: dvs-1 { rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; -- GitLab From c6855f7bb66b6c0c53acc15d2012ebd15a681159 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 25 Jul 2019 09:26:40 -0700 Subject: [PATCH 0740/7155] dt-bindings: ARM: dts: rockchip: Add bindings for rk3288-veyron-{fievel,tiger} Fievel is a Chromebox and Tiger a Chromebase with a 10" display and touchscreen. Tiger and Fievel are based on the same board. Signed-off-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/arm/rockchip.yaml | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 34865042f4e4..01eb1e107ea6 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -128,6 +128,21 @@ properties: - const: google,veyron - const: rockchip,rk3288 + - description: Google Fievel (AOPEN Chromebox Mini) + items: + - const: google,veyron-fievel-rev8 + - const: google,veyron-fievel-rev7 + - const: google,veyron-fievel-rev6 + - const: google,veyron-fievel-rev5 + - const: google,veyron-fievel-rev4 + - const: google,veyron-fievel-rev3 + - const: google,veyron-fievel-rev2 + - const: google,veyron-fievel-rev1 + - const: google,veyron-fievel-rev0 + - const: google,veyron-fievel + - const: google,veyron + - const: rockchip,rk3288 + - description: Google Gru (dev-board) items: - const: google,gru-rev15 @@ -311,6 +326,21 @@ properties: - const: google,veyron - const: rockchip,rk3288 + - description: Google Tiger (AOpen Chromebase Mini) + items: + - const: google,veyron-tiger-rev8 + - const: google,veyron-tiger-rev7 + - const: google,veyron-tiger-rev6 + - const: google,veyron-tiger-rev5 + - const: google,veyron-tiger-rev4 + - const: google,veyron-tiger-rev3 + - const: google,veyron-tiger-rev2 + - const: google,veyron-tiger-rev1 + - const: google,veyron-tiger-rev0 + - const: google,veyron-tiger + - const: google,veyron + - const: rockchip,rk3288 + - description: Haoyu MarsBoard RK3066 items: - const: haoyu,marsboard-rk3066 -- GitLab From 0067692b662e7dd99afa2f871e79e3e5aa5c3c5b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 25 Jul 2019 09:26:41 -0700 Subject: [PATCH 0741/7155] ARM: dts: rockchip: add veyron-fievel board Also known as AOpen Chromebox Mini. Signed-off-by: Matthias Kaehlcke Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rk3288-veyron-fievel.dts | 298 +++++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 arch/arm/boot/dts/rk3288-veyron-fievel.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9159fa2cea90..9fd1e075c624 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -919,6 +919,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-tinker.dtb \ rk3288-tinker-s.dtb \ rk3288-veyron-brain.dtb \ + rk3288-veyron-fievel.dtb \ rk3288-veyron-jaq.dtb \ rk3288-veyron-jerry.dtb \ rk3288-veyron-mickey.dtb \ diff --git a/arch/arm/boot/dts/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rk3288-veyron-fievel.dts new file mode 100644 index 000000000000..696566f72d30 --- /dev/null +++ b/arch/arm/boot/dts/rk3288-veyron-fievel.dts @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Google Veyron Fievel Rev 0+ board device tree source + * + * Copyright 2016 Google, Inc + */ + +/dts-v1/; +#include "rk3288-veyron.dtsi" +#include "rk3288-veyron-analog-audio.dtsi" + +/ { + model = "Google Fievel"; + compatible = "google,veyron-fievel-rev8", "google,veyron-fievel-rev7", + "google,veyron-fievel-rev6", "google,veyron-fievel-rev5", + "google,veyron-fievel-rev4", "google,veyron-fievel-rev3", + "google,veyron-fievel-rev2", "google,veyron-fievel-rev1", + "google,veyron-fievel-rev0", "google,veyron-fievel", + "google,veyron", "rockchip,rk3288"; + + /delete-node/ bt-activity; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + }; + + /* + * vcc33_pmuio and vcc33_io is sourced directly from vcc33_sys, + * enabled by vcc_18 + */ + vcc33_io: vcc33-io { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc33_io"; + }; + + vcc5_host1: vcc5-host1-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio5 RK_PC1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hub_usb1_pwr_en>; + regulator-name = "vcc5_host1"; + regulator-always-on; + regulator-boot-on; + }; + + vcc5_host2: vcc5-host2-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio5 RK_PC2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hub_usb2_pwr_en>; + regulator-name = "vcc5_host2"; + regulator-always-on; + regulator-boot-on; + }; + + vcc5v_otg: vcc5v-otg-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_otg_pwr_en>; + regulator-name = "vcc5_otg"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&gmac { + status = "okay"; + + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + clock_in_out = "input"; + phy-handle = <ðphy>; + phy-mode = "rgmii"; + phy-supply = <&vcc33_lan>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>; + resets = <&cru SRST_MAC>; + reset-names = "stmmaceth"; + rx_delay = <0x10>; + tx_delay = <0x30>; + + /* Reset for the RTL8211 PHY which requires a 10-ms reset pulse (low) + * with a 30ms settling time. */ + snps,reset-gpio = <&gpio4 RK_PB0 0>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 30000>; + wakeup-source; + + mdio0 { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy: ethernet-phy@1 { + reg = <1>; + }; + }; +}; + +&rk808 { + dvs-gpios = <&gpio7 RK_PB4 GPIO_ACTIVE_HIGH>, + <&gpio7 RK_PB7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>; + + vcc6-supply = <&vcc33_sys>; + vcc10-supply = <&vcc33_sys>; + vcc11-supply = <&vcc_5v>; + vcc12-supply = <&vcc33_sys>; + + regulators { + /delete-node/ LDO_REG1; + + /* According to the schematic, vcc18_lcdt is for + * HDMI_AVDD_1V8 + */ + vcc18_lcdt: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vdd18_lcdt"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + /* This is not a pwren anymore, but the real power supply, + * vdd10_lcd for HDMI_AVDD_1V0 + */ + vdd10_lcd: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + /* for usb camera */ + vcc33_ccd: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33_ccd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc33_lan: SWITCH_REG2 { + regulator-name = "vcc33_lan"; + }; + }; +}; + +&sdio0 { + #address-cells = <1>; + #size-cells = <0>; + + btmrvl: btmrvl@2 { + compatible = "marvell,sd8897-bt"; + reg = <2>; + interrupt-parent = <&gpio4>; + interrupts = ; + marvell,wakeup-pin = /bits/ 16 <13>; + pinctrl-names = "default"; + pinctrl-0 = <&bt_host_wake>; + }; +}; + +&vcc50_hdmi { + enable-active-high; + gpio = <&gpio5 RK_PC3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc50_hdmi_en>; +}; + +&vcc_5v { + enable-active-high; + gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&drv_5v>; +}; + +&pinctrl { + pinctrl-names = "default", "sleep"; + pinctrl-0 = < + /* Common for sleep and wake, but no owners */ + &ddr0_retention + &ddrio_pwroff + &global_pwroff + + /* Wake only */ + &bt_dev_wake_awake + &pwr_led1_on + + /* For usb bc1.2 */ + &usb_otg_ilim_sel + &usb_usb_ilim_sel + >; + + pinctrl-1 = < + /* Common for sleep and wake, but no owners */ + &ddr0_retention + &ddrio_pwroff + &global_pwroff + + /* Sleep only */ + &bt_dev_wake_sleep + &pwr_led1_blink + >; + + buck-5v { + drv_5v: drv-5v { + rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac { + phy_rst: phy-rst { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>; + }; + + phy_pmeb: phy-pmeb { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_int: phy-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + hdmi { + vcc50_hdmi_en: vcc50-hdmi-en { + rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + pwr_led1_on: pwr-led1-on { + rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_output_low>; + }; + + pwr_led1_blink: pwr-led1-blink { + rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; + + pmic { + dvs_1: dvs-1 { + rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + dvs_2: dvs-2 { + rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + usb-bc12 { + usb_otg_ilim_sel: usb-otg-ilim-sel { + rockchip,pins = <6 RK_PC1 RK_FUNC_GPIO &pcfg_output_low>; + }; + + usb_usb_ilim_sel: usb-usb-ilim-sel { + rockchip,pins = <5 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>; + }; + }; + + usb-host { + hub_usb1_pwr_en: hub_usb1_pwr_en { + rockchip,pins = <5 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + hub_usb2_pwr_en: hub_usb2_pwr_en { + rockchip,pins = <5 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usb_otg_pwr_en: usb_otg_pwr_en { + rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; -- GitLab From 4a11458611fb17b4f21e5e7b2f24445c00e900e1 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 25 Jul 2019 09:26:42 -0700 Subject: [PATCH 0742/7155] ARM: dts: rockchip: add veyron-tiger board Also known as the AOpen Chromebase Mini. tiger and fievel are share the same board, tiger has a display and touchscreen, fievel not. Use the fievel .dts as base and add the extra bits. Signed-off-by: Matthias Kaehlcke Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rk3288-veyron-tiger.dts | 125 ++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 arch/arm/boot/dts/rk3288-veyron-tiger.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9fd1e075c624..64b08922e75d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -927,6 +927,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-veyron-minnie.dtb \ rk3288-veyron-pinky.dtb \ rk3288-veyron-speedy.dtb \ + rk3288-veyron-tiger.dtb \ rk3288-vyasa.dtb dtb-$(CONFIG_ARCH_S3C24XX) += \ s3c2416-smdk2416.dtb diff --git a/arch/arm/boot/dts/rk3288-veyron-tiger.dts b/arch/arm/boot/dts/rk3288-veyron-tiger.dts new file mode 100644 index 000000000000..fae26d530841 --- /dev/null +++ b/arch/arm/boot/dts/rk3288-veyron-tiger.dts @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Google Veyron Tiger Rev 0+ board device tree source + * + * Copyright 2016 Google, Inc + */ + +/dts-v1/; +#include "rk3288-veyron-fievel.dts" +#include "rk3288-veyron-edp.dtsi" + +/ { + model = "Google Tiger"; + compatible = "google,veyron-tiger-rev8", "google,veyron-tiger-rev7", + "google,veyron-tiger-rev6", "google,veyron-tiger-rev5", + "google,veyron-tiger-rev4", "google,veyron-tiger-rev3", + "google,veyron-tiger-rev2", "google,veyron-tiger-rev1", + "google,veyron-tiger-rev0", "google,veyron-tiger", + "google,veyron", "rockchip,rk3288"; + + /delete-node/ vcc18-lcd; + + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vccsys"; + regulator-boot-on; + regulator-always-on; + }; +}; + +&backlight { + /* Tiger panel PWM must be >= 1%, so start non-zero brightness at 3 */ + brightness-levels = < + 0 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; +}; + +&backlight_regulator { + vin-supply = <&vccsys>; +}; + +&i2c3 { + status = "okay"; + + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <50>; + i2c-scl-rising-time-ns = <300>; + + touchscreen@10 { + compatible = "elan,ekth3500"; + reg = <0x10>; + interrupt-parent = <&gpio2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&touch_int &touch_rst>; + reset-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>; + vcc33-supply = <&vcc33_io>; + vccio-supply = <&vcc33_io>; + wakeup-source; + }; +}; + +&panel { + compatible = "auo,b101ean01", "simple-panel"; + + /delete-node/ panel-timing; + + panel-timing { + clock-frequency = <66666667>; + hactive = <1280>; + hfront-porch = <18>; + hback-porch = <21>; + hsync-len = <32>; + vactive = <800>; + vfront-porch = <4>; + vback-porch = <8>; + vsync-len = <18>; + }; +}; + +&pinctrl { + lcd { + /delete-node/ avdd-1v8-disp-en; + }; + + touchscreen { + touch_int: touch-int { + rockchip,pins = <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + touch_rst: touch-rst { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; -- GitLab From 4929a932be334d68d333089872bc67e4f1d97475 Mon Sep 17 00:00:00 2001 From: Tuong Lien Date: Wed, 24 Jul 2019 08:56:11 +0700 Subject: [PATCH 0743/7155] tipc: optimize link synching mechanism This commit along with the next one are to resolve the issues with the link changeover mechanism. See that commit for details. Basically, for the link synching, from now on, we will send only one single ("dummy") SYNCH message to peer. The SYNCH message does not contain any data, just a header conveying the synch point to the peer. A new node capability flag ("TIPC_TUNNEL_ENHANCED") is introduced for backward compatible! Acked-by: Ying Xue Acked-by: Jon Maloy Suggested-by: Jon Maloy Signed-off-by: Tuong Lien Signed-off-by: David S. Miller --- net/tipc/link.c | 26 ++++++++++++++++++++++++++ net/tipc/msg.h | 10 ++++++++++ net/tipc/node.c | 6 ++++-- net/tipc/node.h | 6 ++++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 66d3a07bc571..e215b4ba6a4b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1665,6 +1665,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, struct sk_buff_head *queue = &l->transmq; struct sk_buff_head tmpxq, tnlq; u16 pktlen, pktcnt, seqno = l->snd_nxt; + u16 syncpt; if (!tnl) return; @@ -1684,6 +1685,31 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, tipc_link_xmit(l, &tnlq, &tmpxq); __skb_queue_purge(&tmpxq); + /* Link Synching: + * From now on, send only one single ("dummy") SYNCH message + * to peer. The SYNCH message does not contain any data, just + * a header conveying the synch point to the peer. + */ + if (mtyp == SYNCH_MSG && (tnl->peer_caps & TIPC_TUNNEL_ENHANCED)) { + tnlskb = tipc_msg_create(TUNNEL_PROTOCOL, SYNCH_MSG, + INT_H_SIZE, 0, l->addr, + tipc_own_addr(l->net), + 0, 0, 0); + if (!tnlskb) { + pr_warn("%sunable to create dummy SYNCH_MSG\n", + link_co_err); + return; + } + + hdr = buf_msg(tnlskb); + syncpt = l->snd_nxt + skb_queue_len(&l->backlogq) - 1; + msg_set_syncpt(hdr, syncpt); + msg_set_bearer_id(hdr, l->peer_bearer_id); + __skb_queue_tail(&tnlq, tnlskb); + tipc_link_xmit(tnl, &tnlq, xmitq); + return; + } + /* Initialize reusable tunnel packet header */ tipc_msg_init(tipc_own_addr(l->net), &tnlhdr, TUNNEL_PROTOCOL, mtyp, INT_H_SIZE, l->addr); diff --git a/net/tipc/msg.h b/net/tipc/msg.h index da509f0eb9ca..fca042cdff88 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -877,6 +877,16 @@ static inline void msg_set_msgcnt(struct tipc_msg *m, u16 n) msg_set_bits(m, 9, 16, 0xffff, n); } +static inline u16 msg_syncpt(struct tipc_msg *m) +{ + return msg_bits(m, 9, 16, 0xffff); +} + +static inline void msg_set_syncpt(struct tipc_msg *m, u16 n) +{ + msg_set_bits(m, 9, 16, 0xffff, n); +} + static inline u32 msg_conn_ack(struct tipc_msg *m) { return msg_bits(m, 9, 16, 0xffff); diff --git a/net/tipc/node.c b/net/tipc/node.c index 3a5be1d7e572..7ca019001f7c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1649,7 +1649,6 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, int usr = msg_user(hdr); int mtyp = msg_type(hdr); u16 oseqno = msg_seqno(hdr); - u16 iseqno = msg_seqno(msg_inner_hdr(hdr)); u16 exp_pkts = msg_msgcnt(hdr); u16 rcv_nxt, syncpt, dlv_nxt, inputq_len; int state = n->state; @@ -1748,7 +1747,10 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, /* Initiate synch mode if applicable */ if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG) && (oseqno == 1)) { - syncpt = iseqno + exp_pkts - 1; + if (n->capabilities & TIPC_TUNNEL_ENHANCED) + syncpt = msg_syncpt(hdr); + else + syncpt = msg_seqno(msg_inner_hdr(hdr)) + exp_pkts - 1; if (!tipc_link_is_up(l)) __tipc_node_link_up(n, bearer_id, xmitq); if (n->state == SELF_UP_PEER_UP) { diff --git a/net/tipc/node.h b/net/tipc/node.h index c0bf49ea3de4..291d0ecd4101 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -53,7 +53,8 @@ enum { TIPC_NODE_ID128 = (1 << 5), TIPC_LINK_PROTO_SEQNO = (1 << 6), TIPC_MCAST_RBCTL = (1 << 7), - TIPC_GAP_ACK_BLOCK = (1 << 8) + TIPC_GAP_ACK_BLOCK = (1 << 8), + TIPC_TUNNEL_ENHANCED = (1 << 9) }; #define TIPC_NODE_CAPABILITIES (TIPC_SYN_BIT | \ @@ -64,7 +65,8 @@ enum { TIPC_NODE_ID128 | \ TIPC_LINK_PROTO_SEQNO | \ TIPC_MCAST_RBCTL | \ - TIPC_GAP_ACK_BLOCK) + TIPC_GAP_ACK_BLOCK | \ + TIPC_TUNNEL_ENHANCED) #define INVALID_BEARER_ID -1 void tipc_node_stop(struct net *net); -- GitLab From 2320bcdae62887555701ea78a46b640ff6b63868 Mon Sep 17 00:00:00 2001 From: Tuong Lien Date: Wed, 24 Jul 2019 08:56:12 +0700 Subject: [PATCH 0744/7155] tipc: fix changeover issues due to large packet In conjunction with changing the interfaces' MTU (e.g. especially in the case of a bonding) where the TIPC links are brought up and down in a short time, a couple of issues were detected with the current link changeover mechanism: 1) When one link is up but immediately forced down again, the failover procedure will be carried out in order to failover all the messages in the link's transmq queue onto the other working link. The link and node state is also set to FAILINGOVER as part of the process. The message will be transmited in form of a FAILOVER_MSG, so its size is plus of 40 bytes (= the message header size). There is no problem if the original message size is not larger than the link's MTU - 40, and indeed this is the max size of a normal payload messages. However, in the situation above, because the link has just been up, the messages in the link's transmq are almost SYNCH_MSGs which had been generated by the link synching procedure, then their size might reach the max value already! When the FAILOVER_MSG is built on the top of such a SYNCH_MSG, its size will exceed the link's MTU. As a result, the messages are dropped silently and the failover procedure will never end up, the link will not be able to exit the FAILINGOVER state, so cannot be re-established. 2) The same scenario above can happen more easily in case the MTU of the links is set differently or when changing. In that case, as long as a large message in the failure link's transmq queue was built and fragmented with its link's MTU > the other link's one, the issue will happen (there is no need of a link synching in advance). 3) The link synching procedure also faces with the same issue but since the link synching is only started upon receipt of a SYNCH_MSG, dropping the message will not result in a state deadlock, but it is not expected as design. The 1) & 3) issues are resolved by the last commit that only a dummy SYNCH_MSG (i.e. without data) is generated at the link synching, so the size of a FAILOVER_MSG if any then will never exceed the link's MTU. For the 2) issue, the only solution is trying to fragment the messages in the failure link's transmq queue according to the working link's MTU so they can be failovered then. A new function is made to accomplish this, it will still be a TUNNEL PROTOCOL/FAILOVER MSG but if the original message size is too large, it will be fragmented & reassembled at the receiving side. Acked-by: Ying Xue Acked-by: Jon Maloy Signed-off-by: Tuong Lien Signed-off-by: David S. Miller --- net/tipc/link.c | 93 +++++++++++++++++++++++++++++++++++++++++-------- net/tipc/msg.c | 59 +++++++++++++++++++++++++++++++ net/tipc/msg.h | 18 +++++++++- 3 files changed, 155 insertions(+), 15 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index e215b4ba6a4b..2c274777b2dd 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -180,6 +180,7 @@ struct tipc_link { /* Fragmentation/reassembly */ struct sk_buff *reasm_buf; + struct sk_buff *reasm_tnlmsg; /* Broadcast */ u16 ackers; @@ -897,8 +898,10 @@ void tipc_link_reset(struct tipc_link *l) l->backlog[TIPC_CRITICAL_IMPORTANCE].len = 0; l->backlog[TIPC_SYSTEM_IMPORTANCE].len = 0; kfree_skb(l->reasm_buf); + kfree_skb(l->reasm_tnlmsg); kfree_skb(l->failover_reasm_skb); l->reasm_buf = NULL; + l->reasm_tnlmsg = NULL; l->failover_reasm_skb = NULL; l->rcv_unacked = 0; l->snd_nxt = 1; @@ -940,6 +943,9 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, int rc = 0; if (unlikely(msg_size(hdr) > mtu)) { + pr_warn("Too large msg, purging xmit list %d %d %d %d %d!\n", + skb_queue_len(list), msg_user(hdr), + msg_type(hdr), msg_size(hdr), mtu); skb_queue_purge(list); return -EMSGSIZE; } @@ -1233,6 +1239,7 @@ static int tipc_link_tnl_rcv(struct tipc_link *l, struct sk_buff *skb, struct sk_buff_head *inputq) { struct sk_buff **reasm_skb = &l->failover_reasm_skb; + struct sk_buff **reasm_tnlmsg = &l->reasm_tnlmsg; struct sk_buff_head *fdefq = &l->failover_deferdq; struct tipc_msg *hdr = buf_msg(skb); struct sk_buff *iskb; @@ -1240,40 +1247,56 @@ static int tipc_link_tnl_rcv(struct tipc_link *l, struct sk_buff *skb, int rc = 0; u16 seqno; - /* SYNCH_MSG */ - if (msg_type(hdr) == SYNCH_MSG) - goto drop; + if (msg_type(hdr) == SYNCH_MSG) { + kfree_skb(skb); + return 0; + } - /* FAILOVER_MSG */ - if (!tipc_msg_extract(skb, &iskb, &ipos)) { - pr_warn_ratelimited("Cannot extract FAILOVER_MSG, defq: %d\n", - skb_queue_len(fdefq)); - return rc; + /* Not a fragment? */ + if (likely(!msg_nof_fragms(hdr))) { + if (unlikely(!tipc_msg_extract(skb, &iskb, &ipos))) { + pr_warn_ratelimited("Unable to extract msg, defq: %d\n", + skb_queue_len(fdefq)); + return 0; + } + kfree_skb(skb); + } else { + /* Set fragment type for buf_append */ + if (msg_fragm_no(hdr) == 1) + msg_set_type(hdr, FIRST_FRAGMENT); + else if (msg_fragm_no(hdr) < msg_nof_fragms(hdr)) + msg_set_type(hdr, FRAGMENT); + else + msg_set_type(hdr, LAST_FRAGMENT); + + if (!tipc_buf_append(reasm_tnlmsg, &skb)) { + /* Successful but non-complete reassembly? */ + if (*reasm_tnlmsg || link_is_bc_rcvlink(l)) + return 0; + pr_warn_ratelimited("Unable to reassemble tunnel msg\n"); + return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); + } + iskb = skb; } do { seqno = buf_seqno(iskb); - if (unlikely(less(seqno, l->drop_point))) { kfree_skb(iskb); continue; } - if (unlikely(seqno != l->drop_point)) { __tipc_skb_queue_sorted(fdefq, seqno, iskb); continue; } l->drop_point++; - if (!tipc_data_input(l, iskb, inputq)) rc |= tipc_link_input(l, iskb, inputq, reasm_skb); if (unlikely(rc)) break; } while ((iskb = __tipc_skb_dequeue(fdefq, l->drop_point))); -drop: - kfree_skb(skb); return rc; } @@ -1663,15 +1686,18 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, struct sk_buff *skb, *tnlskb; struct tipc_msg *hdr, tnlhdr; struct sk_buff_head *queue = &l->transmq; - struct sk_buff_head tmpxq, tnlq; + struct sk_buff_head tmpxq, tnlq, frags; u16 pktlen, pktcnt, seqno = l->snd_nxt; + bool pktcnt_need_update = false; u16 syncpt; + int rc; if (!tnl) return; skb_queue_head_init(&tnlq); skb_queue_head_init(&tmpxq); + skb_queue_head_init(&frags); /* At least one packet required for safe algorithm => add dummy */ skb = tipc_msg_create(TIPC_LOW_IMPORTANCE, TIPC_DIRECT_MSG, @@ -1727,6 +1753,39 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, if (queue == &l->backlogq) msg_set_seqno(hdr, seqno++); pktlen = msg_size(hdr); + + /* Tunnel link MTU is not large enough? This could be + * due to: + * 1) Link MTU has just changed or set differently; + * 2) Or FAILOVER on the top of a SYNCH message + * + * The 2nd case should not happen if peer supports + * TIPC_TUNNEL_ENHANCED + */ + if (pktlen > tnl->mtu - INT_H_SIZE) { + if (mtyp == FAILOVER_MSG && + (tnl->peer_caps & TIPC_TUNNEL_ENHANCED)) { + rc = tipc_msg_fragment(skb, &tnlhdr, tnl->mtu, + &frags); + if (rc) { + pr_warn("%sunable to frag msg: rc %d\n", + link_co_err, rc); + return; + } + pktcnt += skb_queue_len(&frags) - 1; + pktcnt_need_update = true; + skb_queue_splice_tail_init(&frags, &tnlq); + continue; + } + /* Unluckily, peer doesn't have TIPC_TUNNEL_ENHANCED + * => Just warn it and return! + */ + pr_warn_ratelimited("%stoo large msg <%d, %d>: %d!\n", + link_co_err, msg_user(hdr), + msg_type(hdr), msg_size(hdr)); + return; + } + msg_set_size(&tnlhdr, pktlen + INT_H_SIZE); tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE, GFP_ATOMIC); if (!tnlskb) { @@ -1742,6 +1801,12 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, goto tnl; } + if (pktcnt_need_update) + skb_queue_walk(&tnlq, skb) { + hdr = buf_msg(skb); + msg_set_msgcnt(hdr, pktcnt); + } + tipc_link_xmit(tnl, &tnlq, xmitq); if (mtyp == FAILOVER_MSG) { diff --git a/net/tipc/msg.c b/net/tipc/msg.c index f48e5857210f..e6d49cdc61b4 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -243,6 +243,65 @@ bool tipc_msg_validate(struct sk_buff **_skb) return true; } +/** + * tipc_msg_fragment - build a fragment skb list for TIPC message + * + * @skb: TIPC message skb + * @hdr: internal msg header to be put on the top of the fragments + * @pktmax: max size of a fragment incl. the header + * @frags: returned fragment skb list + * + * Returns 0 if the fragmentation is successful, otherwise: -EINVAL + * or -ENOMEM + */ +int tipc_msg_fragment(struct sk_buff *skb, const struct tipc_msg *hdr, + int pktmax, struct sk_buff_head *frags) +{ + int pktno, nof_fragms, dsz, dmax, eat; + struct tipc_msg *_hdr; + struct sk_buff *_skb; + u8 *data; + + /* Non-linear buffer? */ + if (skb_linearize(skb)) + return -ENOMEM; + + data = (u8 *)skb->data; + dsz = msg_size(buf_msg(skb)); + dmax = pktmax - INT_H_SIZE; + if (dsz <= dmax || !dmax) + return -EINVAL; + + nof_fragms = dsz / dmax + 1; + for (pktno = 1; pktno <= nof_fragms; pktno++) { + if (pktno < nof_fragms) + eat = dmax; + else + eat = dsz % dmax; + /* Allocate a new fragment */ + _skb = tipc_buf_acquire(INT_H_SIZE + eat, GFP_ATOMIC); + if (!_skb) + goto error; + skb_orphan(_skb); + __skb_queue_tail(frags, _skb); + /* Copy header & data to the fragment */ + skb_copy_to_linear_data(_skb, hdr, INT_H_SIZE); + skb_copy_to_linear_data_offset(_skb, INT_H_SIZE, data, eat); + data += eat; + /* Update the fragment's header */ + _hdr = buf_msg(_skb); + msg_set_fragm_no(_hdr, pktno); + msg_set_nof_fragms(_hdr, nof_fragms); + msg_set_size(_hdr, INT_H_SIZE + eat); + } + return 0; + +error: + __skb_queue_purge(frags); + __skb_queue_head_init(frags); + return -ENOMEM; +} + /** * tipc_msg_build - create buffer chain containing specified header and data * @mhdr: Message header, to be prepended to data diff --git a/net/tipc/msg.h b/net/tipc/msg.h index fca042cdff88..1c8c8dd32a4e 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -721,12 +721,26 @@ static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) msg_set_bits(m, 4, 16, 0xffff, n); } +static inline u32 msg_nof_fragms(struct tipc_msg *m) +{ + return msg_bits(m, 4, 0, 0xffff); +} + +static inline void msg_set_nof_fragms(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 0, 0xffff, n); +} + +static inline u32 msg_fragm_no(struct tipc_msg *m) +{ + return msg_bits(m, 4, 16, 0xffff); +} + static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) { msg_set_bits(m, 4, 16, 0xffff, n); } - static inline u16 msg_next_sent(struct tipc_msg *m) { return msg_bits(m, 4, 0, 0xffff); @@ -1045,6 +1059,8 @@ bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu); bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, u32 mtu, u32 dnode); bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); +int tipc_msg_fragment(struct sk_buff *skb, const struct tipc_msg *hdr, + int pktmax, struct sk_buff_head *frags); int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, int dsz, int mtu, struct sk_buff_head *list); bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err); -- GitLab From 00c33afbf9dd06f77a2f15117cd4bdc2a54b51d7 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 25 Jul 2019 07:48:04 +0000 Subject: [PATCH 0745/7155] net: mvneta: use devm_platform_ioremap_resource() to simplify code devm_platform_ioremap_resource() wraps platform_get_resource() and devm_ioremap_resource() in a single helper, let's use that helper to simplify the code. Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 15cc678f5e5b..e49820675c8c 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4469,7 +4469,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *bm_node; struct mvneta_port *pp; @@ -4553,8 +4552,7 @@ static int mvneta_probe(struct platform_device *pdev) if (!IS_ERR(pp->clk_bus)) clk_prepare_enable(pp->clk_bus); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pp->base = devm_ioremap_resource(&pdev->dev, res); + pp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pp->base)) { err = PTR_ERR(pp->base); goto err_clk; -- GitLab From 7c4b90d79d0f4ee6f2c01a114ef0a83a09dfc900 Mon Sep 17 00:00:00 2001 From: Allan Zhang Date: Tue, 23 Jul 2019 17:07:24 -0700 Subject: [PATCH 0746/7155] bpf: Allow bpf_skb_event_output for a few prog types Software event output is only enabled by a few prog types right now (TC, LWT out, XDP, sockops). Many other skb based prog types need bpf_skb_event_output to produce software event. Added socket_filter, cg_skb, sk_skb prog types to generate sw event. Test bpf code is generated from code snippet: struct TMP { uint64_t tmp; } tt; tt.tmp = 5; bpf_perf_event_output(skb, &connection_tracking_event_map, 0, &tt, sizeof(tt)); return 1; the bpf assembly from llvm is: 0: b7 02 00 00 05 00 00 00 r2 = 5 1: 7b 2a f8 ff 00 00 00 00 *(u64 *)(r10 - 8) = r2 2: bf a4 00 00 00 00 00 00 r4 = r10 3: 07 04 00 00 f8 ff ff ff r4 += -8 4: 18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0ll 6: b7 03 00 00 00 00 00 00 r3 = 0 7: b7 05 00 00 08 00 00 00 r5 = 8 8: 85 00 00 00 19 00 00 00 call 25 9: b7 00 00 00 01 00 00 00 r0 = 1 10: 95 00 00 00 00 00 00 00 exit Signed-off-by: Allan Zhang Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- net/core/filter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index 4e2a79b2fd77..3961437ccc50 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5999,6 +5999,8 @@ sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_get_socket_cookie_proto; case BPF_FUNC_get_socket_uid: return &bpf_get_socket_uid_proto; + case BPF_FUNC_perf_event_output: + return &bpf_skb_event_output_proto; default: return bpf_base_func_proto(func_id); } @@ -6019,6 +6021,8 @@ cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_sk_storage_get_proto; case BPF_FUNC_sk_storage_delete: return &bpf_sk_storage_delete_proto; + case BPF_FUNC_perf_event_output: + return &bpf_skb_event_output_proto; #ifdef CONFIG_SOCK_CGROUP_DATA case BPF_FUNC_skb_cgroup_id: return &bpf_skb_cgroup_id_proto; @@ -6267,6 +6271,8 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_sk_redirect_map_proto; case BPF_FUNC_sk_redirect_hash: return &bpf_sk_redirect_hash_proto; + case BPF_FUNC_perf_event_output: + return &bpf_skb_event_output_proto; #ifdef CONFIG_INET case BPF_FUNC_sk_lookup_tcp: return &bpf_sk_lookup_tcp_proto; -- GitLab From 03cd1d1a493e92a80d60040d6aa8160aff239942 Mon Sep 17 00:00:00 2001 From: Allan Zhang Date: Tue, 23 Jul 2019 17:07:25 -0700 Subject: [PATCH 0747/7155] selftests/bpf: Add selftests for bpf_perf_event_output Software event output is only enabled by a few prog types. This test is to ensure that all supported types are enabled for bpf_perf_event_output successfully. Signed-off-by: Allan Zhang Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_verifier.c | 12 ++- .../selftests/bpf/verifier/event_output.c | 94 +++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/verifier/event_output.c diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 84135d5f4b35..44e2d640b088 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -50,7 +50,7 @@ #define MAX_INSNS BPF_MAXINSNS #define MAX_TEST_INSNS 1000000 #define MAX_FIXUPS 8 -#define MAX_NR_MAPS 18 +#define MAX_NR_MAPS 19 #define MAX_TEST_RUNS 8 #define POINTER_VALUE 0xcafe4all #define TEST_DATA_LEN 64 @@ -84,6 +84,7 @@ struct bpf_test { int fixup_map_array_wo[MAX_FIXUPS]; int fixup_map_array_small[MAX_FIXUPS]; int fixup_sk_storage_map[MAX_FIXUPS]; + int fixup_map_event_output[MAX_FIXUPS]; const char *errstr; const char *errstr_unpriv; uint32_t insn_processed; @@ -632,6 +633,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, int *fixup_map_array_wo = test->fixup_map_array_wo; int *fixup_map_array_small = test->fixup_map_array_small; int *fixup_sk_storage_map = test->fixup_sk_storage_map; + int *fixup_map_event_output = test->fixup_map_event_output; if (test->fill_helper) { test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn)); @@ -793,6 +795,14 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, fixup_sk_storage_map++; } while (*fixup_sk_storage_map); } + if (*fixup_map_event_output) { + map_fds[18] = __create_map(BPF_MAP_TYPE_PERF_EVENT_ARRAY, + sizeof(int), sizeof(int), 1, 0); + do { + prog[*fixup_map_event_output].imm = map_fds[18]; + fixup_map_event_output++; + } while (*fixup_map_event_output); + } } static int set_admin(bool admin) diff --git a/tools/testing/selftests/bpf/verifier/event_output.c b/tools/testing/selftests/bpf/verifier/event_output.c new file mode 100644 index 000000000000..130553e19eca --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/event_output.c @@ -0,0 +1,94 @@ +/* instructions used to output a skb based software event, produced + * from code snippet: + * struct TMP { + * uint64_t tmp; + * } tt; + * tt.tmp = 5; + * bpf_perf_event_output(skb, &connection_tracking_event_map, 0, + * &tt, sizeof(tt)); + * return 1; + * + * the bpf assembly from llvm is: + * 0: b7 02 00 00 05 00 00 00 r2 = 5 + * 1: 7b 2a f8 ff 00 00 00 00 *(u64 *)(r10 - 8) = r2 + * 2: bf a4 00 00 00 00 00 00 r4 = r10 + * 3: 07 04 00 00 f8 ff ff ff r4 += -8 + * 4: 18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0ll + * 6: b7 03 00 00 00 00 00 00 r3 = 0 + * 7: b7 05 00 00 08 00 00 00 r5 = 8 + * 8: 85 00 00 00 19 00 00 00 call 25 + * 9: b7 00 00 00 01 00 00 00 r0 = 1 + * 10: 95 00 00 00 00 00 00 00 exit + * + * The reason I put the code here instead of fill_helpers is that map fixup + * is against the insns, instead of filled prog. + */ + +#define __PERF_EVENT_INSNS__ \ + BPF_MOV64_IMM(BPF_REG_2, 5), \ + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -8), \ + BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), \ + BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), \ + BPF_LD_MAP_FD(BPF_REG_2, 0), \ + BPF_MOV64_IMM(BPF_REG_3, 0), \ + BPF_MOV64_IMM(BPF_REG_5, 8), \ + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, \ + BPF_FUNC_perf_event_output), \ + BPF_MOV64_IMM(BPF_REG_0, 1), \ + BPF_EXIT_INSN(), +{ + "perfevent for sockops", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_SOCK_OPS, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for tc", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for lwt out", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_LWT_OUT, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for xdp", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_XDP, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for socket filter", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for sk_skb", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_SK_SKB, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "perfevent for cgroup skb", + .insns = { __PERF_EVENT_INSNS__ }, + .prog_type = BPF_PROG_TYPE_CGROUP_SKB, + .fixup_map_event_output = { 4 }, + .result = ACCEPT, + .retval = 1, +}, -- GitLab From 086f95682114fd2d1790bd3226e76cbae9a2d192 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:25 -0700 Subject: [PATCH 0748/7155] bpf/flow_dissector: pass input flags to BPF flow dissector program C flow dissector supports input flags that tell it to customize parsing by either stopping early or trying to parse as deep as possible. Pass those flags to the BPF flow dissector so it can make the same decisions. In the next commits I'll add support for those flags to our reference bpf_flow.c v3: * Export copy of flow dissector flags instead of moving (Alexei Starovoitov) Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- include/linux/skbuff.h | 2 +- include/uapi/linux/bpf.h | 5 +++++ net/bpf/test_run.c | 2 +- net/core/flow_dissector.c | 12 ++++++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 718742b1c505..9b7a8038beec 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1271,7 +1271,7 @@ static inline int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr) struct bpf_flow_dissector; bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, - __be16 proto, int nhoff, int hlen); + __be16 proto, int nhoff, int hlen, unsigned int flags); bool __skb_flow_dissect(const struct net *net, const struct sk_buff *skb, diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index fa1c753dcdbc..88b9d743036f 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -3507,6 +3507,10 @@ enum bpf_task_fd_type { BPF_FD_TYPE_URETPROBE, /* filename + offset */ }; +#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2) + struct bpf_flow_keys { __u16 nhoff; __u16 thoff; @@ -3528,6 +3532,7 @@ struct bpf_flow_keys { __u32 ipv6_dst[4]; /* in6_addr; network order */ }; }; + __u32 flags; }; struct bpf_func_info { diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 80e6f3a6864d..4e41d15a1098 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -419,7 +419,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, time_start = ktime_get_ns(); for (i = 0; i < repeat; i++) { retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, - size); + size, 0); if (signal_pending(current)) { preempt_enable(); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 3e6fedb57bc1..50ed1a688709 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -784,7 +784,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, } bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, - __be16 proto, int nhoff, int hlen) + __be16 proto, int nhoff, int hlen, unsigned int flags) { struct bpf_flow_keys *flow_keys = ctx->flow_keys; u32 result; @@ -795,6 +795,14 @@ bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, flow_keys->nhoff = nhoff; flow_keys->thoff = flow_keys->nhoff; + BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG != + (int)FLOW_DISSECTOR_F_PARSE_1ST_FRAG); + BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL != + (int)FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); + BUILD_BUG_ON((int)BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP != + (int)FLOW_DISSECTOR_F_STOP_AT_ENCAP); + flow_keys->flags = flags; + preempt_disable(); result = BPF_PROG_RUN(prog, ctx); preempt_enable(); @@ -914,7 +922,7 @@ bool __skb_flow_dissect(const struct net *net, } ret = bpf_flow_dissect(attached, &ctx, n_proto, nhoff, - hlen); + hlen, flags); __skb_flow_bpf_to_target(&flow_keys, flow_dissector, target_container); rcu_read_unlock(); -- GitLab From 1ac6b126dbe8108c1fe6e29d023a0f2989cd3fea Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:26 -0700 Subject: [PATCH 0749/7155] bpf/flow_dissector: document flags Describe what each input flag does and who uses it. Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- Documentation/bpf/prog_flow_dissector.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/bpf/prog_flow_dissector.rst b/Documentation/bpf/prog_flow_dissector.rst index ed343abe541e..a78bf036cadd 100644 --- a/Documentation/bpf/prog_flow_dissector.rst +++ b/Documentation/bpf/prog_flow_dissector.rst @@ -26,6 +26,7 @@ The inputs are: * ``nhoff`` - initial offset of the networking header * ``thoff`` - initial offset of the transport header, initialized to nhoff * ``n_proto`` - L3 protocol type, parsed out of L2 header + * ``flags`` - optional flags Flow dissector BPF program should fill out the rest of the ``struct bpf_flow_keys`` fields. Input arguments ``nhoff/thoff/n_proto`` should be @@ -101,6 +102,23 @@ can be called for both cases and would have to be written carefully to handle both cases. +Flags +===== + +``flow_keys->flags`` might contain optional input flags that work as follows: + +* ``BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG`` - tells BPF flow dissector to + continue parsing first fragment; the default expected behavior is that + flow dissector returns as soon as it finds out that the packet is fragmented; + used by ``eth_get_headlen`` to estimate length of all headers for GRO. +* ``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL`` - tells BPF flow dissector to + stop parsing as soon as it reaches IPv6 flow label; used by + ``___skb_get_hash`` and ``__skb_get_hash_symmetric`` to get flow hash. +* ``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP`` - tells BPF flow dissector to stop + parsing as soon as it reaches encapsulated headers; used by routing + infrastructure. + + Reference Implementation ======================== -- GitLab From b2ca4e1cfa7d3d755e1ec637d1235f89af9bd01f Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:27 -0700 Subject: [PATCH 0750/7155] bpf/flow_dissector: support flags in BPF_PROG_TEST_RUN This will allow us to write tests for those flags. v2: * Swap kfree(data) and kfree(user_ctx) (Song Liu) Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- net/bpf/test_run.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 4e41d15a1098..1153bbcdff72 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -377,6 +377,22 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, return ret; } +static int verify_user_bpf_flow_keys(struct bpf_flow_keys *ctx) +{ + /* make sure the fields we don't use are zeroed */ + if (!range_is_zero(ctx, 0, offsetof(struct bpf_flow_keys, flags))) + return -EINVAL; + + /* flags is allowed */ + + if (!range_is_zero(ctx, offsetof(struct bpf_flow_keys, flags) + + FIELD_SIZEOF(struct bpf_flow_keys, flags), + sizeof(struct bpf_flow_keys))) + return -EINVAL; + + return 0; +} + int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr) @@ -384,9 +400,11 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, u32 size = kattr->test.data_size_in; struct bpf_flow_dissector ctx = {}; u32 repeat = kattr->test.repeat; + struct bpf_flow_keys *user_ctx; struct bpf_flow_keys flow_keys; u64 time_start, time_spent = 0; const struct ethhdr *eth; + unsigned int flags = 0; u32 retval, duration; void *data; int ret; @@ -395,9 +413,6 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) return -EINVAL; - if (kattr->test.ctx_in || kattr->test.ctx_out) - return -EINVAL; - if (size < ETH_HLEN) return -EINVAL; @@ -410,6 +425,18 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, if (!repeat) repeat = 1; + user_ctx = bpf_ctx_init(kattr, sizeof(struct bpf_flow_keys)); + if (IS_ERR(user_ctx)) { + kfree(data); + return PTR_ERR(user_ctx); + } + if (user_ctx) { + ret = verify_user_bpf_flow_keys(user_ctx); + if (ret) + goto out; + flags = user_ctx->flags; + } + ctx.flow_keys = &flow_keys; ctx.data = data; ctx.data_end = (__u8 *)data + size; @@ -419,7 +446,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, time_start = ktime_get_ns(); for (i = 0; i < repeat; i++) { retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, - size, 0); + size, flags); if (signal_pending(current)) { preempt_enable(); @@ -450,8 +477,12 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys), retval, duration); + if (!ret) + ret = bpf_ctx_finish(kattr, uattr, user_ctx, + sizeof(struct bpf_flow_keys)); out: + kfree(user_ctx); kfree(data); return ret; } -- GitLab From 57debff23c4cd47f25850a5f42a903aebe535e95 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:28 -0700 Subject: [PATCH 0751/7155] tools/bpf: sync bpf_flow_keys flags Export bpf_flow_keys flags to tools/libbpf/selftests. Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- tools/include/uapi/linux/bpf.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 4e455018da65..2e4b0848d795 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -3504,6 +3504,10 @@ enum bpf_task_fd_type { BPF_FD_TYPE_URETPROBE, /* filename + offset */ }; +#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2) + struct bpf_flow_keys { __u16 nhoff; __u16 thoff; @@ -3525,6 +3529,7 @@ struct bpf_flow_keys { __u32 ipv6_dst[4]; /* in6_addr; network order */ }; }; + __u32 flags; }; struct bpf_func_info { -- GitLab From ae173a915785e55574c1fc54edf58b9b87b28c22 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:29 -0700 Subject: [PATCH 0752/7155] selftests/bpf: support BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG bpf_flow.c: exit early unless BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG is passed in flags. Also, set ip_proto earlier, this makes sure we have correct value with fragmented packets. Add selftest cases to test ipv4/ipv6 fragments and skip eth_get_headlen tests that don't have BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG flag. eth_get_headlen calls flow dissector with BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG flag so we can't run tests that have different set of input flags against it. v2: * sefltests -> selftests (Willem de Bruijn) * Reword a comment about eth_get_headlen flags (Song Liu) Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/flow_dissector.c | 133 +++++++++++++++++- tools/testing/selftests/bpf/progs/bpf_flow.c | 29 +++- 2 files changed, 155 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c index c938283ac232..8e8c18aced9b 100644 --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c @@ -5,6 +5,10 @@ #include #include +#ifndef IP_MF +#define IP_MF 0x2000 +#endif + #define CHECK_FLOW_KEYS(desc, got, expected) \ CHECK_ATTR(memcmp(&got, &expected, sizeof(got)) != 0, \ desc, \ @@ -49,6 +53,18 @@ struct ipv6_pkt { struct tcphdr tcp; } __packed; +struct ipv6_frag_pkt { + struct ethhdr eth; + struct ipv6hdr iph; + struct frag_hdr { + __u8 nexthdr; + __u8 reserved; + __be16 frag_off; + __be32 identification; + } ipf; + struct tcphdr tcp; +} __packed; + struct dvlan_ipv6_pkt { struct ethhdr eth; __u16 vlan_tci; @@ -65,9 +81,11 @@ struct test { struct ipv4_pkt ipv4; struct svlan_ipv4_pkt svlan_ipv4; struct ipv6_pkt ipv6; + struct ipv6_frag_pkt ipv6_frag; struct dvlan_ipv6_pkt dvlan_ipv6; } pkt; struct bpf_flow_keys keys; + __u32 flags; }; #define VLAN_HLEN 4 @@ -143,6 +161,102 @@ struct test tests[] = { .n_proto = __bpf_constant_htons(ETH_P_IPV6), }, }, + { + .name = "ipv4-frag", + .pkt.ipv4 = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), + .iph.ihl = 5, + .iph.protocol = IPPROTO_TCP, + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), + .iph.frag_off = __bpf_constant_htons(IP_MF), + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .flags = BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG, + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct iphdr), + .addr_proto = ETH_P_IP, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IP), + .is_frag = true, + .is_first_frag = true, + .sport = 80, + .dport = 8080, + }, + .flags = BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG, + }, + { + .name = "ipv4-no-frag", + .pkt.ipv4 = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), + .iph.ihl = 5, + .iph.protocol = IPPROTO_TCP, + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), + .iph.frag_off = __bpf_constant_htons(IP_MF), + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct iphdr), + .addr_proto = ETH_P_IP, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IP), + .is_frag = true, + .is_first_frag = true, + }, + }, + { + .name = "ipv6-frag", + .pkt.ipv6_frag = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), + .iph.nexthdr = IPPROTO_FRAGMENT, + .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), + .ipf.nexthdr = IPPROTO_TCP, + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .flags = BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG, + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct ipv6hdr) + + sizeof(struct frag_hdr), + .addr_proto = ETH_P_IPV6, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .is_frag = true, + .is_first_frag = true, + .sport = 80, + .dport = 8080, + }, + .flags = BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG, + }, + { + .name = "ipv6-no-frag", + .pkt.ipv6_frag = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), + .iph.nexthdr = IPPROTO_FRAGMENT, + .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), + .ipf.nexthdr = IPPROTO_TCP, + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct ipv6hdr) + + sizeof(struct frag_hdr), + .addr_proto = ETH_P_IPV6, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .is_frag = true, + .is_first_frag = true, + }, + }, }; static int create_tap(const char *ifname) @@ -225,6 +339,13 @@ void test_flow_dissector(void) .data_size_in = sizeof(tests[i].pkt), .data_out = &flow_keys, }; + static struct bpf_flow_keys ctx = {}; + + if (tests[i].flags) { + tattr.ctx_in = &ctx; + tattr.ctx_size_in = sizeof(ctx); + ctx.flags = tests[i].flags; + } err = bpf_prog_test_run_xattr(&tattr); CHECK_ATTR(tattr.data_size_out != sizeof(flow_keys) || @@ -251,10 +372,20 @@ void test_flow_dissector(void) CHECK(err, "ifup", "err %d errno %d\n", err, errno); for (i = 0; i < ARRAY_SIZE(tests); i++) { - struct bpf_flow_keys flow_keys = {}; + /* Keep in sync with 'flags' from eth_get_headlen. */ + __u32 eth_get_headlen_flags = + BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG; struct bpf_prog_test_run_attr tattr = {}; + struct bpf_flow_keys flow_keys = {}; __u32 key = 0; + /* For skb-less case we can't pass input flags; run + * only the tests that have a matching set of flags. + */ + + if (tests[i].flags != eth_get_headlen_flags) + continue; + err = tx_tap(tap_fd, &tests[i].pkt, sizeof(tests[i].pkt)); CHECK(err < 0, "tx_tap", "err %d errno %d\n", err, errno); diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c index 5ae485a6af3f..f931cd3db9d4 100644 --- a/tools/testing/selftests/bpf/progs/bpf_flow.c +++ b/tools/testing/selftests/bpf/progs/bpf_flow.c @@ -153,7 +153,6 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) struct tcphdr *tcp, _tcp; struct udphdr *udp, _udp; - keys->ip_proto = proto; switch (proto) { case IPPROTO_ICMP: icmp = bpf_flow_dissect_get_header(skb, sizeof(*icmp), &_icmp); @@ -231,7 +230,6 @@ static __always_inline int parse_ipv6_proto(struct __sk_buff *skb, __u8 nexthdr) { struct bpf_flow_keys *keys = skb->flow_keys; - keys->ip_proto = nexthdr; switch (nexthdr) { case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: @@ -266,6 +264,7 @@ PROG(IP)(struct __sk_buff *skb) keys->addr_proto = ETH_P_IP; keys->ipv4_src = iph->saddr; keys->ipv4_dst = iph->daddr; + keys->ip_proto = iph->protocol; keys->thoff += iph->ihl << 2; if (data + keys->thoff > data_end) @@ -273,13 +272,20 @@ PROG(IP)(struct __sk_buff *skb) if (iph->frag_off & bpf_htons(IP_MF | IP_OFFSET)) { keys->is_frag = true; - if (iph->frag_off & bpf_htons(IP_OFFSET)) + if (iph->frag_off & bpf_htons(IP_OFFSET)) { /* From second fragment on, packets do not have headers * we can parse. */ done = true; - else + } else { keys->is_first_frag = true; + /* No need to parse fragmented packet unless + * explicitly asked for. + */ + if (!(keys->flags & + BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG)) + done = true; + } } if (done) @@ -301,6 +307,7 @@ PROG(IPV6)(struct __sk_buff *skb) memcpy(&keys->ipv6_src, &ip6h->saddr, 2*sizeof(ip6h->saddr)); keys->thoff += sizeof(struct ipv6hdr); + keys->ip_proto = ip6h->nexthdr; return parse_ipv6_proto(skb, ip6h->nexthdr); } @@ -317,7 +324,8 @@ PROG(IPV6OP)(struct __sk_buff *skb) /* hlen is in 8-octets and does not include the first 8 bytes * of the header */ - skb->flow_keys->thoff += (1 + ip6h->hdrlen) << 3; + keys->thoff += (1 + ip6h->hdrlen) << 3; + keys->ip_proto = ip6h->nexthdr; return parse_ipv6_proto(skb, ip6h->nexthdr); } @@ -333,9 +341,18 @@ PROG(IPV6FR)(struct __sk_buff *skb) keys->thoff += sizeof(*fragh); keys->is_frag = true; - if (!(fragh->frag_off & bpf_htons(IP6_OFFSET))) + keys->ip_proto = fragh->nexthdr; + + if (!(fragh->frag_off & bpf_htons(IP6_OFFSET))) { keys->is_first_frag = true; + /* No need to parse fragmented packet unless + * explicitly asked for. + */ + if (!(keys->flags & BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG)) + return export_flow_keys(keys, BPF_OK); + } + return parse_ipv6_proto(skb, fragh->nexthdr); } -- GitLab From 71c99e32b926159ea628352751f66383d7d04d17 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:30 -0700 Subject: [PATCH 0753/7155] bpf/flow_dissector: support ipv6 flow_label and BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL Add support for exporting ipv6 flow label via bpf_flow_keys. Export flow label from bpf_flow.c and also return early when BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL is passed. Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- include/uapi/linux/bpf.h | 1 + net/core/flow_dissector.c | 9 ++++ tools/include/uapi/linux/bpf.h | 1 + .../selftests/bpf/prog_tests/flow_dissector.c | 46 +++++++++++++++++++ tools/testing/selftests/bpf/progs/bpf_flow.c | 10 ++++ 5 files changed, 67 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 88b9d743036f..e985f07a98ed 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -3533,6 +3533,7 @@ struct bpf_flow_keys { }; }; __u32 flags; + __be32 flow_label; }; struct bpf_func_info { diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 50ed1a688709..9741b593ea53 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -737,6 +737,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, struct flow_dissector_key_basic *key_basic; struct flow_dissector_key_addrs *key_addrs; struct flow_dissector_key_ports *key_ports; + struct flow_dissector_key_tags *key_tags; key_control = skb_flow_dissector_target(flow_dissector, FLOW_DISSECTOR_KEY_CONTROL, @@ -781,6 +782,14 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, key_ports->src = flow_keys->sport; key_ports->dst = flow_keys->dport; } + + if (dissector_uses_key(flow_dissector, + FLOW_DISSECTOR_KEY_FLOW_LABEL)) { + key_tags = skb_flow_dissector_target(flow_dissector, + FLOW_DISSECTOR_KEY_FLOW_LABEL, + target_container); + key_tags->flow_label = ntohl(flow_keys->flow_label); + } } bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 2e4b0848d795..3d7fc67ec1b8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -3530,6 +3530,7 @@ struct bpf_flow_keys { }; }; __u32 flags; + __be32 flow_label; }; struct bpf_func_info { diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c index 8e8c18aced9b..ef83f145a6f1 100644 --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c @@ -20,6 +20,7 @@ "is_encap=%u/%u " \ "ip_proto=0x%x/0x%x " \ "n_proto=0x%x/0x%x " \ + "flow_label=0x%x/0x%x " \ "sport=%u/%u " \ "dport=%u/%u\n", \ got.nhoff, expected.nhoff, \ @@ -30,6 +31,7 @@ got.is_encap, expected.is_encap, \ got.ip_proto, expected.ip_proto, \ got.n_proto, expected.n_proto, \ + got.flow_label, expected.flow_label, \ got.sport, expected.sport, \ got.dport, expected.dport) @@ -257,6 +259,50 @@ struct test tests[] = { .is_first_frag = true, }, }, + { + .name = "ipv6-flow-label", + .pkt.ipv6 = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), + .iph.nexthdr = IPPROTO_TCP, + .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), + .iph.flow_lbl = { 0xb, 0xee, 0xef }, + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct ipv6hdr), + .addr_proto = ETH_P_IPV6, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .sport = 80, + .dport = 8080, + .flow_label = __bpf_constant_htonl(0xbeeef), + }, + }, + { + .name = "ipv6-no-flow-label", + .pkt.ipv6 = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), + .iph.nexthdr = IPPROTO_TCP, + .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), + .iph.flow_lbl = { 0xb, 0xee, 0xef }, + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct ipv6hdr), + .addr_proto = ETH_P_IPV6, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .flow_label = __bpf_constant_htonl(0xbeeef), + }, + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, + }, }; static int create_tap(const char *ifname) diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c index f931cd3db9d4..7fbfa22f33df 100644 --- a/tools/testing/selftests/bpf/progs/bpf_flow.c +++ b/tools/testing/selftests/bpf/progs/bpf_flow.c @@ -83,6 +83,12 @@ static __always_inline int export_flow_keys(struct bpf_flow_keys *keys, return ret; } +#define IPV6_FLOWLABEL_MASK __bpf_constant_htonl(0x000FFFFF) +static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) +{ + return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; +} + static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb, __u16 hdr_size, void *buffer) @@ -308,6 +314,10 @@ PROG(IPV6)(struct __sk_buff *skb) keys->thoff += sizeof(struct ipv6hdr); keys->ip_proto = ip6h->nexthdr; + keys->flow_label = ip6_flowlabel(ip6h); + + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL) + return export_flow_keys(keys, BPF_OK); return parse_ipv6_proto(skb, ip6h->nexthdr); } -- GitLab From e853ae776a58633492b59badab04f53a6b730d62 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 25 Jul 2019 15:52:31 -0700 Subject: [PATCH 0754/7155] selftests/bpf: support BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP Exit as soon as we found that packet is encapped when BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP is passed. Add appropriate selftest cases. v2: * Subtract sizeof(struct iphdr) from .iph_inner.tot_len (Willem de Bruijn) Acked-by: Petar Penkov Acked-by: Willem de Bruijn Acked-by: Song Liu Cc: Song Liu Cc: Willem de Bruijn Cc: Petar Penkov Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/flow_dissector.c | 64 +++++++++++++++++++ tools/testing/selftests/bpf/progs/bpf_flow.c | 8 +++ 2 files changed, 72 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c index ef83f145a6f1..700d73d2f22a 100644 --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c @@ -41,6 +41,13 @@ struct ipv4_pkt { struct tcphdr tcp; } __packed; +struct ipip_pkt { + struct ethhdr eth; + struct iphdr iph; + struct iphdr iph_inner; + struct tcphdr tcp; +} __packed; + struct svlan_ipv4_pkt { struct ethhdr eth; __u16 vlan_tci; @@ -82,6 +89,7 @@ struct test { union { struct ipv4_pkt ipv4; struct svlan_ipv4_pkt svlan_ipv4; + struct ipip_pkt ipip; struct ipv6_pkt ipv6; struct ipv6_frag_pkt ipv6_frag; struct dvlan_ipv6_pkt dvlan_ipv6; @@ -303,6 +311,62 @@ struct test tests[] = { }, .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, }, + { + .name = "ipip-encap", + .pkt.ipip = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), + .iph.ihl = 5, + .iph.protocol = IPPROTO_IPIP, + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), + .iph_inner.ihl = 5, + .iph_inner.protocol = IPPROTO_TCP, + .iph_inner.tot_len = + __bpf_constant_htons(MAGIC_BYTES) - + sizeof(struct iphdr), + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .nhoff = 0, + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct iphdr) + + sizeof(struct iphdr), + .addr_proto = ETH_P_IP, + .ip_proto = IPPROTO_TCP, + .n_proto = __bpf_constant_htons(ETH_P_IP), + .is_encap = true, + .sport = 80, + .dport = 8080, + }, + }, + { + .name = "ipip-no-encap", + .pkt.ipip = { + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), + .iph.ihl = 5, + .iph.protocol = IPPROTO_IPIP, + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), + .iph_inner.ihl = 5, + .iph_inner.protocol = IPPROTO_TCP, + .iph_inner.tot_len = + __bpf_constant_htons(MAGIC_BYTES) - + sizeof(struct iphdr), + .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, + }, + .keys = { + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP, + .nhoff = ETH_HLEN, + .thoff = ETH_HLEN + sizeof(struct iphdr), + .addr_proto = ETH_P_IP, + .ip_proto = IPPROTO_IPIP, + .n_proto = __bpf_constant_htons(ETH_P_IP), + .is_encap = true, + }, + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP, + }, }; static int create_tap(const char *ifname) diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c index 7fbfa22f33df..08bd8b9d58d0 100644 --- a/tools/testing/selftests/bpf/progs/bpf_flow.c +++ b/tools/testing/selftests/bpf/progs/bpf_flow.c @@ -167,9 +167,15 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) return export_flow_keys(keys, BPF_OK); case IPPROTO_IPIP: keys->is_encap = true; + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) + return export_flow_keys(keys, BPF_OK); + return parse_eth_proto(skb, bpf_htons(ETH_P_IP)); case IPPROTO_IPV6: keys->is_encap = true; + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) + return export_flow_keys(keys, BPF_OK); + return parse_eth_proto(skb, bpf_htons(ETH_P_IPV6)); case IPPROTO_GRE: gre = bpf_flow_dissect_get_header(skb, sizeof(*gre), &_gre); @@ -189,6 +195,8 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) keys->thoff += 4; /* Step over sequence number */ keys->is_encap = true; + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) + return export_flow_keys(keys, BPF_OK); if (gre->proto == bpf_htons(ETH_P_TEB)) { eth = bpf_flow_dissect_get_header(skb, sizeof(*eth), -- GitLab From aca24d48cee232a88839c8895ac6fcd2fcad6588 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 1 Jul 2019 14:08:14 +0100 Subject: [PATCH 0755/7155] crypto: ccree - fix spelling mistake "configration" -> "configuration" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 980aa04b655b..eeb803f40623 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -421,7 +421,7 @@ static int init_cc_resources(struct platform_device *plat_dev) } break; default: - dev_err(dev, "Unsupported engines configration.\n"); + dev_err(dev, "Unsupported engines configuration.\n"); rc = -EINVAL; goto post_clk_err; } -- GitLab From e6e6600c001c3aa3760aeb83dbd4630063e926ee Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 2 Jul 2019 14:39:18 +0300 Subject: [PATCH 0756/7155] crypto: ccree - drop legacy ivgen support ccree had a mechanism for IV generation which was not compatible with the Linux seqiv or echainiv iv generator and was never used in any of the upstream versions so drop all the code implementing it. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- drivers/crypto/ccree/Makefile | 2 +- drivers/crypto/ccree/cc_aead.c | 76 +------ drivers/crypto/ccree/cc_aead.h | 3 +- drivers/crypto/ccree/cc_driver.c | 12 +- drivers/crypto/ccree/cc_driver.h | 10 - drivers/crypto/ccree/cc_ivgen.c | 276 -------------------------- drivers/crypto/ccree/cc_ivgen.h | 55 ----- drivers/crypto/ccree/cc_pm.c | 2 - drivers/crypto/ccree/cc_request_mgr.c | 47 +---- 9 files changed, 17 insertions(+), 466 deletions(-) delete mode 100644 drivers/crypto/ccree/cc_ivgen.c delete mode 100644 drivers/crypto/ccree/cc_ivgen.h diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile index 145e50bdbf16..5cfda508ee41 100644 --- a/drivers/crypto/ccree/Makefile +++ b/drivers/crypto/ccree/Makefile @@ -2,7 +2,7 @@ # Copyright (C) 2012-2019 ARM Limited (or its affiliates). obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o -ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_aead.o cc_ivgen.o cc_sram_mgr.o +ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_aead.o cc_sram_mgr.o ccree-$(CONFIG_CRYPTO_FIPS) += cc_fips.o ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index 7aa4cbe19a86..a9914ea6c95f 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -239,28 +239,13 @@ static void cc_aead_complete(struct device *dev, void *cc_req, int err) cc_zero_sgl(areq->dst, areq_ctx->cryptlen); err = -EBADMSG; } - } else { /*ENCRYPT*/ - if (areq_ctx->is_icv_fragmented) { - u32 skip = areq->cryptlen + areq_ctx->dst_offset; - - cc_copy_sg_portion(dev, areq_ctx->mac_buf, - areq_ctx->dst_sgl, skip, - (skip + ctx->authsize), - CC_SG_FROM_BUF); - } + /*ENCRYPT*/ + } else if (areq_ctx->is_icv_fragmented) { + u32 skip = areq->cryptlen + areq_ctx->dst_offset; - /* If an IV was generated, copy it back to the user provided - * buffer. - */ - if (areq_ctx->backup_giv) { - if (ctx->cipher_mode == DRV_CIPHER_CTR) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + - CTR_RFC3686_NONCE_SIZE, - CTR_RFC3686_IV_SIZE); - else if (ctx->cipher_mode == DRV_CIPHER_CCM) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + - CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE); - } + cc_copy_sg_portion(dev, areq_ctx->mac_buf, areq_ctx->dst_sgl, + skip, (skip + ctx->authsize), + CC_SG_FROM_BUF); } done: aead_request_complete(areq, err); @@ -1975,9 +1960,8 @@ static int cc_proc_aead(struct aead_request *req, */ memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, CTR_RFC3686_NONCE_SIZE); - if (!areq_ctx->backup_giv) /*User none-generated IV*/ - memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, - req->iv, CTR_RFC3686_IV_SIZE); + memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, req->iv, + CTR_RFC3686_IV_SIZE); /* Initialize counter portion of counter block */ *(__be32 *)(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); @@ -2023,40 +2007,6 @@ static int cc_proc_aead(struct aead_request *req, goto exit; } - /* do we need to generate IV? */ - if (areq_ctx->backup_giv) { - /* set the DMA mapped IV address*/ - if (ctx->cipher_mode == DRV_CIPHER_CTR) { - cc_req.ivgen_dma_addr[0] = - areq_ctx->gen_ctx.iv_dma_addr + - CTR_RFC3686_NONCE_SIZE; - cc_req.ivgen_dma_addr_len = 1; - } else if (ctx->cipher_mode == DRV_CIPHER_CCM) { - /* In ccm, the IV needs to exist both inside B0 and - * inside the counter.It is also copied to iv_dma_addr - * for other reasons (like returning it to the user). - * So, using 3 (identical) IV outputs. - */ - cc_req.ivgen_dma_addr[0] = - areq_ctx->gen_ctx.iv_dma_addr + - CCM_BLOCK_IV_OFFSET; - cc_req.ivgen_dma_addr[1] = - sg_dma_address(&areq_ctx->ccm_adata_sg) + - CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET; - cc_req.ivgen_dma_addr[2] = - sg_dma_address(&areq_ctx->ccm_adata_sg) + - CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET; - cc_req.ivgen_dma_addr_len = 3; - } else { - cc_req.ivgen_dma_addr[0] = - areq_ctx->gen_ctx.iv_dma_addr; - cc_req.ivgen_dma_addr_len = 1; - } - - /* set the IV size (8/16 B long)*/ - cc_req.ivgen_size = crypto_aead_ivsize(tfm); - } - /* STAT_PHASE_2: Create sequence */ /* Load MLLI tables to SRAM if necessary */ @@ -2107,7 +2057,6 @@ static int cc_aead_encrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = false; areq_ctx->plaintext_authenticate_only = false; @@ -2139,7 +2088,6 @@ static int cc_rfc4309_ccm_encrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = true; cc_proc_rfc4309_ccm(req); @@ -2161,7 +2109,6 @@ static int cc_aead_decrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = false; areq_ctx->plaintext_authenticate_only = false; @@ -2191,7 +2138,6 @@ static int cc_rfc4309_ccm_decrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = true; cc_proc_rfc4309_ccm(req); @@ -2311,8 +2257,6 @@ static int cc_rfc4106_gcm_encrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; - areq_ctx->plaintext_authenticate_only = false; cc_proc_rfc4_gcm(req); @@ -2340,7 +2284,6 @@ static int cc_rfc4543_gcm_encrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; @@ -2372,8 +2315,6 @@ static int cc_rfc4106_gcm_decrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; - areq_ctx->plaintext_authenticate_only = false; cc_proc_rfc4_gcm(req); @@ -2401,7 +2342,6 @@ static int cc_rfc4543_gcm_decrypt(struct aead_request *req) /* No generated IV required */ areq_ctx->backup_iv = req->iv; areq_ctx->assoclen = req->assoclen; - areq_ctx->backup_giv = NULL; cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; diff --git a/drivers/crypto/ccree/cc_aead.h b/drivers/crypto/ccree/cc_aead.h index e51724b96c56..f12169b57f9d 100644 --- a/drivers/crypto/ccree/cc_aead.h +++ b/drivers/crypto/ccree/cc_aead.h @@ -65,8 +65,7 @@ struct aead_req_ctx { unsigned int hw_iv_size ____cacheline_aligned; /* used to prevent cache coherence problem */ u8 backup_mac[MAX_MAC_SIZE]; - u8 *backup_iv; /*store iv for generated IV flow*/ - u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/ + u8 *backup_iv; /* store orig iv */ u32 assoclen; /* internal assoclen */ dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */ /* buffer for internal ccm configurations */ diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index eeb803f40623..196e3d140355 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -22,7 +22,6 @@ #include "cc_cipher.h" #include "cc_aead.h" #include "cc_hash.h" -#include "cc_ivgen.h" #include "cc_sram_mgr.h" #include "cc_pm.h" #include "cc_fips.h" @@ -503,17 +502,11 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_buf_mgr_err; } - rc = cc_ivgen_init(new_drvdata); - if (rc) { - dev_err(dev, "cc_ivgen_init failed\n"); - goto post_buf_mgr_err; - } - /* Allocate crypto algs */ rc = cc_cipher_alloc(new_drvdata); if (rc) { dev_err(dev, "cc_cipher_alloc failed\n"); - goto post_ivgen_err; + goto post_buf_mgr_err; } /* hash must be allocated before aead since hash exports APIs */ @@ -544,8 +537,6 @@ static int init_cc_resources(struct platform_device *plat_dev) cc_hash_free(new_drvdata); post_cipher_err: cc_cipher_free(new_drvdata); -post_ivgen_err: - cc_ivgen_fini(new_drvdata); post_buf_mgr_err: cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: @@ -577,7 +568,6 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) cc_aead_free(drvdata); cc_hash_free(drvdata); cc_cipher_free(drvdata); - cc_ivgen_fini(drvdata); cc_pm_fini(drvdata); cc_buffer_mgr_fini(drvdata); cc_req_mgr_fini(drvdata); diff --git a/drivers/crypto/ccree/cc_driver.h b/drivers/crypto/ccree/cc_driver.h index 7cd99380bf1f..ab31d4a68c80 100644 --- a/drivers/crypto/ccree/cc_driver.h +++ b/drivers/crypto/ccree/cc_driver.h @@ -126,15 +126,6 @@ struct cc_cpp_req { struct cc_crypto_req { void (*user_cb)(struct device *dev, void *req, int err); void *user_arg; - dma_addr_t ivgen_dma_addr[CC_MAX_IVGEN_DMA_ADDRESSES]; - /* For the first 'ivgen_dma_addr_len' addresses of this array, - * generated IV would be placed in it by send_request(). - * Same generated IV for all addresses! - */ - /* Amount of 'ivgen_dma_addr' elements to be filled. */ - unsigned int ivgen_dma_addr_len; - /* The generated IV size required, 8/16 B allowed. */ - unsigned int ivgen_size; struct completion seq_compl; /* request completion */ struct cc_cpp_req cpp; }; @@ -158,7 +149,6 @@ struct cc_drvdata { void *aead_handle; void *request_mgr_handle; void *fips_handle; - void *ivgen_handle; void *sram_mgr_handle; void *debugfs; struct clk *clk; diff --git a/drivers/crypto/ccree/cc_ivgen.c b/drivers/crypto/ccree/cc_ivgen.c deleted file mode 100644 index 99dc69383e20..000000000000 --- a/drivers/crypto/ccree/cc_ivgen.c +++ /dev/null @@ -1,276 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ - -#include -#include "cc_driver.h" -#include "cc_ivgen.h" -#include "cc_request_mgr.h" -#include "cc_sram_mgr.h" -#include "cc_buffer_mgr.h" - -/* The max. size of pool *MUST* be <= SRAM total size */ -#define CC_IVPOOL_SIZE 1024 -/* The first 32B fraction of pool are dedicated to the - * next encryption "key" & "IV" for pool regeneration - */ -#define CC_IVPOOL_META_SIZE (CC_AES_IV_SIZE + AES_KEYSIZE_128) -#define CC_IVPOOL_GEN_SEQ_LEN 4 - -/** - * struct cc_ivgen_ctx -IV pool generation context - * @pool: the start address of the iv-pool resides in internal RAM - * @ctr_key_dma: address of pool's encryption key material in internal RAM - * @ctr_iv_dma: address of pool's counter iv in internal RAM - * @next_iv_ofs: the offset to the next available IV in pool - * @pool_meta: virt. address of the initial enc. key/IV - * @pool_meta_dma: phys. address of the initial enc. key/IV - */ -struct cc_ivgen_ctx { - cc_sram_addr_t pool; - cc_sram_addr_t ctr_key; - cc_sram_addr_t ctr_iv; - u32 next_iv_ofs; - u8 *pool_meta; - dma_addr_t pool_meta_dma; -}; - -/*! - * Generates CC_IVPOOL_SIZE of random bytes by - * encrypting 0's using AES128-CTR. - * - * \param ivgen iv-pool context - * \param iv_seq IN/OUT array to the descriptors sequence - * \param iv_seq_len IN/OUT pointer to the sequence length - */ -static int cc_gen_iv_pool(struct cc_ivgen_ctx *ivgen_ctx, - struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len) -{ - unsigned int idx = *iv_seq_len; - - if ((*iv_seq_len + CC_IVPOOL_GEN_SEQ_LEN) > CC_IVPOOL_SEQ_LEN) { - /* The sequence will be longer than allowed */ - return -EINVAL; - } - /* Setup key */ - hw_desc_init(&iv_seq[idx]); - set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128); - set_setup_mode(&iv_seq[idx], SETUP_LOAD_KEY0); - set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_flow_mode(&iv_seq[idx], S_DIN_to_AES); - set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE); - set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR); - idx++; - - /* Setup cipher state */ - hw_desc_init(&iv_seq[idx]); - set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE); - set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); - set_flow_mode(&iv_seq[idx], S_DIN_to_AES); - set_setup_mode(&iv_seq[idx], SETUP_LOAD_STATE1); - set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE); - set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR); - idx++; - - /* Perform dummy encrypt to skip first block */ - hw_desc_init(&iv_seq[idx]); - set_din_const(&iv_seq[idx], 0, CC_AES_IV_SIZE); - set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE); - set_flow_mode(&iv_seq[idx], DIN_AES_DOUT); - idx++; - - /* Generate IV pool */ - hw_desc_init(&iv_seq[idx]); - set_din_const(&iv_seq[idx], 0, CC_IVPOOL_SIZE); - set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_IVPOOL_SIZE); - set_flow_mode(&iv_seq[idx], DIN_AES_DOUT); - idx++; - - *iv_seq_len = idx; /* Update sequence length */ - - /* queue ordering assures pool readiness */ - ivgen_ctx->next_iv_ofs = CC_IVPOOL_META_SIZE; - - return 0; -} - -/*! - * Generates the initial pool in SRAM. - * This function should be invoked when resuming driver. - * - * \param drvdata - * - * \return int Zero for success, negative value otherwise. - */ -int cc_init_iv_sram(struct cc_drvdata *drvdata) -{ - struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle; - struct cc_hw_desc iv_seq[CC_IVPOOL_SEQ_LEN]; - unsigned int iv_seq_len = 0; - int rc; - - /* Generate initial enc. key/iv */ - get_random_bytes(ivgen_ctx->pool_meta, CC_IVPOOL_META_SIZE); - - /* The first 32B reserved for the enc. Key/IV */ - ivgen_ctx->ctr_key = ivgen_ctx->pool; - ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128; - - /* Copy initial enc. key and IV to SRAM at a single descriptor */ - hw_desc_init(&iv_seq[iv_seq_len]); - set_din_type(&iv_seq[iv_seq_len], DMA_DLLI, ivgen_ctx->pool_meta_dma, - CC_IVPOOL_META_SIZE, NS_BIT); - set_dout_sram(&iv_seq[iv_seq_len], ivgen_ctx->pool, - CC_IVPOOL_META_SIZE); - set_flow_mode(&iv_seq[iv_seq_len], BYPASS); - iv_seq_len++; - - /* Generate initial pool */ - rc = cc_gen_iv_pool(ivgen_ctx, iv_seq, &iv_seq_len); - if (rc) - return rc; - - /* Fire-and-forget */ - return send_request_init(drvdata, iv_seq, iv_seq_len); -} - -/*! - * Free iv-pool and ivgen context. - * - * \param drvdata - */ -void cc_ivgen_fini(struct cc_drvdata *drvdata) -{ - struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle; - struct device *device = &drvdata->plat_dev->dev; - - if (!ivgen_ctx) - return; - - if (ivgen_ctx->pool_meta) { - memset(ivgen_ctx->pool_meta, 0, CC_IVPOOL_META_SIZE); - dma_free_coherent(device, CC_IVPOOL_META_SIZE, - ivgen_ctx->pool_meta, - ivgen_ctx->pool_meta_dma); - } - - ivgen_ctx->pool = NULL_SRAM_ADDR; -} - -/*! - * Allocates iv-pool and maps resources. - * This function generates the first IV pool. - * - * \param drvdata Driver's private context - * - * \return int Zero for success, negative value otherwise. - */ -int cc_ivgen_init(struct cc_drvdata *drvdata) -{ - struct cc_ivgen_ctx *ivgen_ctx; - struct device *device = &drvdata->plat_dev->dev; - int rc; - - /* Allocate "this" context */ - ivgen_ctx = devm_kzalloc(device, sizeof(*ivgen_ctx), GFP_KERNEL); - if (!ivgen_ctx) - return -ENOMEM; - - drvdata->ivgen_handle = ivgen_ctx; - - /* Allocate pool's header for initial enc. key/IV */ - ivgen_ctx->pool_meta = dma_alloc_coherent(device, CC_IVPOOL_META_SIZE, - &ivgen_ctx->pool_meta_dma, - GFP_KERNEL); - if (!ivgen_ctx->pool_meta) { - dev_err(device, "Not enough memory to allocate DMA of pool_meta (%u B)\n", - CC_IVPOOL_META_SIZE); - rc = -ENOMEM; - goto out; - } - /* Allocate IV pool in SRAM */ - ivgen_ctx->pool = cc_sram_alloc(drvdata, CC_IVPOOL_SIZE); - if (ivgen_ctx->pool == NULL_SRAM_ADDR) { - dev_err(device, "SRAM pool exhausted\n"); - rc = -ENOMEM; - goto out; - } - - return cc_init_iv_sram(drvdata); - -out: - cc_ivgen_fini(drvdata); - return rc; -} - -/*! - * Acquires 16 Bytes IV from the iv-pool - * - * \param drvdata Driver private context - * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements - * of iv_out_dma array are ignore) - * \param iv_out_size May be 8 or 16 bytes long - * \param iv_seq IN/OUT array to the descriptors sequence - * \param iv_seq_len IN/OUT pointer to the sequence length - * - * \return int Zero for success, negative value otherwise. - */ -int cc_get_iv(struct cc_drvdata *drvdata, dma_addr_t iv_out_dma[], - unsigned int iv_out_dma_len, unsigned int iv_out_size, - struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len) -{ - struct cc_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle; - unsigned int idx = *iv_seq_len; - struct device *dev = drvdata_to_dev(drvdata); - unsigned int t; - - if (iv_out_size != CC_AES_IV_SIZE && - iv_out_size != CTR_RFC3686_IV_SIZE) { - return -EINVAL; - } - if ((iv_out_dma_len + 1) > CC_IVPOOL_SEQ_LEN) { - /* The sequence will be longer than allowed */ - return -EINVAL; - } - - /* check that number of generated IV is limited to max dma address - * iv buffer size - */ - if (iv_out_dma_len > CC_MAX_IVGEN_DMA_ADDRESSES) { - /* The sequence will be longer than allowed */ - return -EINVAL; - } - - for (t = 0; t < iv_out_dma_len; t++) { - /* Acquire IV from pool */ - hw_desc_init(&iv_seq[idx]); - set_din_sram(&iv_seq[idx], (ivgen_ctx->pool + - ivgen_ctx->next_iv_ofs), - iv_out_size); - set_dout_dlli(&iv_seq[idx], iv_out_dma[t], iv_out_size, - NS_BIT, 0); - set_flow_mode(&iv_seq[idx], BYPASS); - idx++; - } - - /* Bypass operation is proceeded by crypto sequence, hence must - * assure bypass-write-transaction by a memory barrier - */ - hw_desc_init(&iv_seq[idx]); - set_din_no_dma(&iv_seq[idx], 0, 0xfffff0); - set_dout_no_dma(&iv_seq[idx], 0, 0, 1); - idx++; - - *iv_seq_len = idx; /* update seq length */ - - /* Update iv index */ - ivgen_ctx->next_iv_ofs += iv_out_size; - - if ((CC_IVPOOL_SIZE - ivgen_ctx->next_iv_ofs) < CC_AES_IV_SIZE) { - dev_dbg(dev, "Pool exhausted, regenerating iv-pool\n"); - /* pool is drained -regenerate it! */ - return cc_gen_iv_pool(ivgen_ctx, iv_seq, iv_seq_len); - } - - return 0; -} diff --git a/drivers/crypto/ccree/cc_ivgen.h b/drivers/crypto/ccree/cc_ivgen.h deleted file mode 100644 index a9f5e8bba4f1..000000000000 --- a/drivers/crypto/ccree/cc_ivgen.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ - -#ifndef __CC_IVGEN_H__ -#define __CC_IVGEN_H__ - -#include "cc_hw_queue_defs.h" - -#define CC_IVPOOL_SEQ_LEN 8 - -/*! - * Allocates iv-pool and maps resources. - * This function generates the first IV pool. - * - * \param drvdata Driver's private context - * - * \return int Zero for success, negative value otherwise. - */ -int cc_ivgen_init(struct cc_drvdata *drvdata); - -/*! - * Free iv-pool and ivgen context. - * - * \param drvdata - */ -void cc_ivgen_fini(struct cc_drvdata *drvdata); - -/*! - * Generates the initial pool in SRAM. - * This function should be invoked when resuming DX driver. - * - * \param drvdata - * - * \return int Zero for success, negative value otherwise. - */ -int cc_init_iv_sram(struct cc_drvdata *drvdata); - -/*! - * Acquires 16 Bytes IV from the iv-pool - * - * \param drvdata Driver private context - * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements of - * iv_out_dma array are ignore) - * \param iv_out_size May be 8 or 16 bytes long - * \param iv_seq IN/OUT array to the descriptors sequence - * \param iv_seq_len IN/OUT pointer to the sequence length - * - * \return int Zero for success, negative value otherwise. - */ -int cc_get_iv(struct cc_drvdata *drvdata, dma_addr_t iv_out_dma[], - unsigned int iv_out_dma_len, unsigned int iv_out_size, - struct cc_hw_desc iv_seq[], unsigned int *iv_seq_len); - -#endif /*__CC_IVGEN_H__*/ diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c index 899a52f05b7a..dbc508fb719b 100644 --- a/drivers/crypto/ccree/cc_pm.c +++ b/drivers/crypto/ccree/cc_pm.c @@ -8,7 +8,6 @@ #include "cc_buffer_mgr.h" #include "cc_request_mgr.h" #include "cc_sram_mgr.h" -#include "cc_ivgen.h" #include "cc_hash.h" #include "cc_pm.h" #include "cc_fips.h" @@ -73,7 +72,6 @@ int cc_pm_resume(struct device *dev) /* must be after the queue resuming as it uses the HW queue*/ cc_init_hash_sram(drvdata); - cc_init_iv_sram(drvdata); return 0; } diff --git a/drivers/crypto/ccree/cc_request_mgr.c b/drivers/crypto/ccree/cc_request_mgr.c index 0bc6ccb0b899..a947d5a2cf35 100644 --- a/drivers/crypto/ccree/cc_request_mgr.c +++ b/drivers/crypto/ccree/cc_request_mgr.c @@ -6,7 +6,6 @@ #include "cc_driver.h" #include "cc_buffer_mgr.h" #include "cc_request_mgr.h" -#include "cc_ivgen.h" #include "cc_pm.h" #define CC_MAX_POLL_ITER 10 @@ -281,36 +280,12 @@ static int cc_queues_status(struct cc_drvdata *drvdata, static int cc_do_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req, struct cc_hw_desc *desc, unsigned int len, - bool add_comp, bool ivgen) + bool add_comp) { struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle; unsigned int used_sw_slots; - unsigned int iv_seq_len = 0; unsigned int total_seq_len = len; /*initial sequence length*/ - struct cc_hw_desc iv_seq[CC_IVPOOL_SEQ_LEN]; struct device *dev = drvdata_to_dev(drvdata); - int rc; - - if (ivgen) { - dev_dbg(dev, "Acquire IV from pool into %d DMA addresses %pad, %pad, %pad, IV-size=%u\n", - cc_req->ivgen_dma_addr_len, - &cc_req->ivgen_dma_addr[0], - &cc_req->ivgen_dma_addr[1], - &cc_req->ivgen_dma_addr[2], - cc_req->ivgen_size); - - /* Acquire IV from pool */ - rc = cc_get_iv(drvdata, cc_req->ivgen_dma_addr, - cc_req->ivgen_dma_addr_len, - cc_req->ivgen_size, iv_seq, &iv_seq_len); - - if (rc) { - dev_err(dev, "Failed to generate IV (rc=%d)\n", rc); - return rc; - } - - total_seq_len += iv_seq_len; - } used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & @@ -334,8 +309,6 @@ static int cc_do_send_request(struct cc_drvdata *drvdata, wmb(); /* STAT_PHASE_4: Push sequence */ - if (ivgen) - enqueue_seq(drvdata, iv_seq, iv_seq_len); enqueue_seq(drvdata, desc, len); @@ -380,8 +353,6 @@ static void cc_proc_backlog(struct cc_drvdata *drvdata) struct cc_bl_item *bli; struct cc_crypto_req *creq; void *req; - bool ivgen; - unsigned int total_len; struct device *dev = drvdata_to_dev(drvdata); int rc; @@ -406,12 +377,9 @@ static void cc_proc_backlog(struct cc_drvdata *drvdata) bli->notif = true; } - ivgen = !!creq->ivgen_dma_addr_len; - total_len = bli->len + (ivgen ? CC_IVPOOL_SEQ_LEN : 0); - spin_lock(&mgr->hw_lock); - rc = cc_queues_status(drvdata, mgr, total_len); + rc = cc_queues_status(drvdata, mgr, bli->len); if (rc) { /* * There is still not room in the FIFO for @@ -423,7 +391,7 @@ static void cc_proc_backlog(struct cc_drvdata *drvdata) } rc = cc_do_send_request(drvdata, &bli->creq, bli->desc, - bli->len, false, ivgen); + bli->len, false); spin_unlock(&mgr->hw_lock); @@ -447,8 +415,6 @@ int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req, { int rc; struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle; - bool ivgen = !!cc_req->ivgen_dma_addr_len; - unsigned int total_len = len + (ivgen ? CC_IVPOOL_SEQ_LEN : 0); struct device *dev = drvdata_to_dev(drvdata); bool backlog_ok = req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG; gfp_t flags = cc_gfp_flags(req); @@ -461,7 +427,7 @@ int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req, } spin_lock_bh(&mgr->hw_lock); - rc = cc_queues_status(drvdata, mgr, total_len); + rc = cc_queues_status(drvdata, mgr, len); #ifdef CC_DEBUG_FORCE_BACKLOG if (backlog_ok) @@ -486,8 +452,7 @@ int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req, } if (!rc) - rc = cc_do_send_request(drvdata, cc_req, desc, len, false, - ivgen); + rc = cc_do_send_request(drvdata, cc_req, desc, len, false); spin_unlock_bh(&mgr->hw_lock); return rc; @@ -527,7 +492,7 @@ int cc_send_sync_request(struct cc_drvdata *drvdata, reinit_completion(&drvdata->hw_queue_avail); } - rc = cc_do_send_request(drvdata, cc_req, desc, len, true, false); + rc = cc_do_send_request(drvdata, cc_req, desc, len, true); spin_unlock_bh(&mgr->hw_lock); if (rc != -EINPROGRESS) { -- GitLab From 76a95bd8f9e10cade9c4c8df93b5c20ff45dc0f5 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 2 Jul 2019 14:39:19 +0300 Subject: [PATCH 0757/7155] crypto: ccree - account for TEE not ready to report When ccree driver runs it checks the state of the Trusted Execution Environment CryptoCell driver before proceeding. We did not account for cases where the TEE side is not ready or not available at all. Fix it by only considering TEE error state after sync with the TEE side driver. Signed-off-by: Gilad Ben-Yossef Fixes: ab8ec9658f5a ("crypto: ccree - add FIPS support") CC: stable@vger.kernel.org # v4.17+ Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_fips.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccree/cc_fips.c b/drivers/crypto/ccree/cc_fips.c index 5ad3ffb7acaa..040e09c0e1af 100644 --- a/drivers/crypto/ccree/cc_fips.c +++ b/drivers/crypto/ccree/cc_fips.c @@ -21,7 +21,13 @@ static bool cc_get_tee_fips_status(struct cc_drvdata *drvdata) u32 reg; reg = cc_ioread(drvdata, CC_REG(GPR_HOST)); - return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)); + /* Did the TEE report status? */ + if (reg & CC_FIPS_SYNC_TEE_STATUS) + /* Yes. Is it OK? */ + return (reg & CC_FIPS_SYNC_MODULE_OK); + + /* No. It's either not in use or will be reported later */ + return true; } /* -- GitLab From 9552389c465ed1ded39edf4a5642a861b53c2955 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 2 Jul 2019 14:39:20 +0300 Subject: [PATCH 0758/7155] crypto: fips - add FIPS test failure notification chain Crypto test failures in FIPS mode cause an immediate panic, but on some system the cryptographic boundary extends beyond just the Linux controlled domain. Add a simple atomic notification chain to allow interested parties to register to receive notification prior to us kicking the bucket. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/fips.c | 11 +++++++++++ crypto/testmgr.c | 4 +++- include/linux/fips.h | 7 +++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crypto/fips.c b/crypto/fips.c index c0b3a3c3452d..7b1d8caee669 100644 --- a/crypto/fips.c +++ b/crypto/fips.c @@ -11,10 +11,14 @@ #include #include #include +#include int fips_enabled; EXPORT_SYMBOL_GPL(fips_enabled); +ATOMIC_NOTIFIER_HEAD(fips_fail_notif_chain); +EXPORT_SYMBOL_GPL(fips_fail_notif_chain); + /* Process kernel command-line parameter at boot time. fips=0 or fips=1 */ static int fips_enable(char *str) { @@ -58,6 +62,13 @@ static void crypto_proc_fips_exit(void) unregister_sysctl_table(crypto_sysctls); } +void fips_fail_notify(void) +{ + if (fips_enabled) + atomic_notifier_call_chain(&fips_fail_notif_chain, 0, NULL); +} +EXPORT_SYMBOL_GPL(fips_fail_notify); + static int __init fips_init(void) { crypto_proc_fips_init(); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d0b5b33806a6..8ba1e75cd973 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -5240,9 +5240,11 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) type, mask); test_done: - if (rc && (fips_enabled || panic_on_fail)) + if (rc && (fips_enabled || panic_on_fail)) { + fips_fail_notify(); panic("alg: self-tests for %s (%s) failed in %s mode!\n", driver, alg, fips_enabled ? "fips" : "panic_on_fail"); + } if (fips_enabled && !rc) pr_info("alg: self-tests for %s (%s) passed\n", driver, alg); diff --git a/include/linux/fips.h b/include/linux/fips.h index afeeece92302..c6961e932fef 100644 --- a/include/linux/fips.h +++ b/include/linux/fips.h @@ -4,8 +4,15 @@ #ifdef CONFIG_CRYPTO_FIPS extern int fips_enabled; +extern struct atomic_notifier_head fips_fail_notif_chain; + +void fips_fail_notify(void); + #else #define fips_enabled 0 + +static inline void fips_fail_notify(void) {} + #endif #endif -- GitLab From 452c53d7868b3f95658ebb2f346acca96eaa2aed Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 2 Jul 2019 14:39:21 +0300 Subject: [PATCH 0759/7155] crypto: ccree - notify TEE on FIPS tests errors Register a FIPS test failure notifier and use it to notify TEE side of FIPS test failures on our side prior to panic. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_fips.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/crypto/ccree/cc_fips.c b/drivers/crypto/ccree/cc_fips.c index 040e09c0e1af..4c8bce33abcf 100644 --- a/drivers/crypto/ccree/cc_fips.c +++ b/drivers/crypto/ccree/cc_fips.c @@ -3,6 +3,7 @@ #include #include +#include #include "cc_driver.h" #include "cc_fips.h" @@ -11,6 +12,8 @@ static void fips_dsr(unsigned long devarg); struct cc_fips_handle { struct tasklet_struct tasklet; + struct notifier_block nb; + struct cc_drvdata *drvdata; }; /* The function called once at driver entry point to check @@ -46,6 +49,21 @@ void cc_set_ree_fips_status(struct cc_drvdata *drvdata, bool status) cc_iowrite(drvdata, CC_REG(HOST_GPR0), val); } +/* Push REE side FIPS test failure to TEE side */ +static int cc_ree_fips_failure(struct notifier_block *nb, unsigned long unused1, + void *unused2) +{ + struct cc_fips_handle *fips_h = + container_of(nb, struct cc_fips_handle, nb); + struct cc_drvdata *drvdata = fips_h->drvdata; + struct device *dev = drvdata_to_dev(drvdata); + + cc_set_ree_fips_status(drvdata, false); + dev_info(dev, "Notifying TEE of FIPS test failure...\n"); + + return NOTIFY_OK; +} + void cc_fips_fini(struct cc_drvdata *drvdata) { struct cc_fips_handle *fips_h = drvdata->fips_handle; @@ -53,6 +71,8 @@ void cc_fips_fini(struct cc_drvdata *drvdata) if (drvdata->hw_rev < CC_HW_REV_712 || !fips_h) return; + atomic_notifier_chain_unregister(&fips_fail_notif_chain, &fips_h->nb); + /* Kill tasklet */ tasklet_kill(&fips_h->tasklet); drvdata->fips_handle = NULL; @@ -124,6 +144,9 @@ int cc_fips_init(struct cc_drvdata *p_drvdata) dev_dbg(dev, "Initializing fips tasklet\n"); tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata); + fips_h->drvdata = p_drvdata; + fips_h->nb.notifier_call = cc_ree_fips_failure; + atomic_notifier_chain_register(&fips_fail_notif_chain, &fips_h->nb); cc_tee_handle_fips_error(p_drvdata); -- GitLab From 36160aadb1034787d4d30b6af7805cb3dd636aac Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:52 +0200 Subject: [PATCH 0760/7155] crypto: inside-secure - keep ivsize for DES ECB modes at 0 The driver incorrectly advertised the IV size for DES and 3DES ECB mode as being the DES blocksize of 8. This is incorrect as ECB mode does not need any IV. Signed-off-by: Pascal van Leeuwen Acked-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_cipher.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 8cdbdbe35681..82f293caf68a 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -1037,7 +1037,6 @@ struct safexcel_alg_template safexcel_alg_ecb_des = { .decrypt = safexcel_ecb_des_decrypt, .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, - .ivsize = DES_BLOCK_SIZE, .base = { .cra_name = "ecb(des)", .cra_driver_name = "safexcel-ecb-des", @@ -1140,7 +1139,6 @@ struct safexcel_alg_template safexcel_alg_ecb_des3_ede = { .decrypt = safexcel_ecb_des3_ede_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, .base = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "safexcel-ecb-des3_ede", -- GitLab From 384ce433884af04c2063ec8a0ec0464b3fb6f1d2 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:53 +0200 Subject: [PATCH 0761/7155] crypto: inside-secure - silently return -EINVAL for input error cases Driver was printing an error message for certain input error cases that should just return -EINVAL, which caused the related testmgr extra tests to flood the kernel message log. Ensured those cases remain silent while making some other device-specific errors a bit more verbose. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index df43a2c6933b..045919651272 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -589,16 +589,31 @@ void safexcel_dequeue(struct safexcel_crypto_priv *priv, int ring) inline int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, struct safexcel_result_desc *rdesc) { - if (likely(!rdesc->result_data.error_code)) + if (likely((!rdesc->descriptor_overflow) && + (!rdesc->buffer_overflow) && + (!rdesc->result_data.error_code))) return 0; - if (rdesc->result_data.error_code & 0x407f) { - /* Fatal error (bits 0-7, 14) */ + if (rdesc->descriptor_overflow) + dev_err(priv->dev, "Descriptor overflow detected"); + + if (rdesc->buffer_overflow) + dev_err(priv->dev, "Buffer overflow detected"); + + if (rdesc->result_data.error_code & 0x4067) { + /* Fatal error (bits 0,1,2,5,6 & 14) */ dev_err(priv->dev, - "cipher: result: result descriptor error (0x%x)\n", + "result descriptor error (%x)", rdesc->result_data.error_code); + return -EIO; + } else if (rdesc->result_data.error_code & + (BIT(7) | BIT(4) | BIT(3))) { + /* + * Give priority over authentication fails: + * Blocksize & overflow errors, something wrong with the input! + */ return -EINVAL; - } else if (rdesc->result_data.error_code == BIT(9)) { + } else if (rdesc->result_data.error_code & BIT(9)) { /* Authentication failed */ return -EBADMSG; } -- GitLab From 5bdb6e6aa53bf5c6e6082a4bb44e1106a22d68b8 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:54 +0200 Subject: [PATCH 0762/7155] crypto: inside-secure - fix incorrect skcipher output IV This patch fixes corruption issues with the skcipher output IV witnessed on x86+EIP197-FPGA (devboard). The original fix, commit 57660b11d5ad ("crypto: inside-secure - implement IV retrieval"), attempted to write out the result IV through the context record. However, this is not a reliable mechanism as there is no way of knowing the hardware context update actually arrived in memory, so it is possible to read the old contents instead of the updated IV. (and indeed, this failed for the x86/FPGA case) The alternative approach used here recognises the fact that the result IV for CBC is actually the last cipher block, which is the last input block in case of decryption and the last output block in case of encryption. So the result IV is taken from the input data buffer respectively the output data buffer instead, which *is* reliable. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- .../crypto/inside-secure/safexcel_cipher.c | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 82f293caf68a..f03640cc2095 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -92,25 +92,6 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, token[0].instructions = EIP197_TOKEN_INS_LAST | EIP197_TOKEN_INS_TYPE_CRYTO | EIP197_TOKEN_INS_TYPE_OUTPUT; - - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { - u32 last = (EIP197_MAX_TOKENS - 1) - offset; - - token[last].opcode = EIP197_TOKEN_OPCODE_CTX_ACCESS; - token[last].packet_length = EIP197_TOKEN_DIRECTION_EXTERNAL | - EIP197_TOKEN_EXEC_IF_SUCCESSFUL| - EIP197_TOKEN_CTX_OFFSET(0x2); - token[last].stat = EIP197_TOKEN_STAT_LAST_HASH | - EIP197_TOKEN_STAT_LAST_PACKET; - token[last].instructions = - EIP197_TOKEN_INS_ORIGIN_LEN(block_sz / sizeof(u32)) | - EIP197_TOKEN_INS_ORIGIN_IV0; - - /* Store the updated IV values back in the internal context - * registers. - */ - cdesc->control_data.control1 |= CONTEXT_CONTROL_CRYPTO_STORE; - } } static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, @@ -348,6 +329,9 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin struct safexcel_cipher_req *sreq, bool *should_complete, int *ret) { + struct skcipher_request *areq = skcipher_request_cast(async); + struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq); + struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(skcipher); struct safexcel_result_desc *rdesc; int ndesc = 0; @@ -380,6 +364,18 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin dma_unmap_sg(priv->dev, dst, sg_nents(dst), DMA_FROM_DEVICE); } + /* + * Update IV in req from last crypto output word for CBC modes + */ + if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) && + (sreq->direction == SAFEXCEL_ENCRYPT)) { + /* For encrypt take the last output word */ + sg_pcopy_to_buffer(dst, sg_nents(dst), areq->iv, + crypto_skcipher_ivsize(skcipher), + (cryptlen - + crypto_skcipher_ivsize(skcipher))); + } + *should_complete = true; return ndesc; @@ -392,6 +388,8 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, unsigned int digestsize, u8 *iv, int *commands, int *results) { + struct skcipher_request *areq = skcipher_request_cast(base); + struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(areq); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); struct safexcel_crypto_priv *priv = ctx->priv; struct safexcel_command_desc *cdesc; @@ -401,6 +399,19 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = totlen; int i, ret = 0; + if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) && + (sreq->direction == SAFEXCEL_DECRYPT)) { + /* + * Save IV from last crypto input word for CBC modes in decrypt + * direction. Need to do this first in case of inplace operation + * as it will be overwritten. + */ + sg_pcopy_to_buffer(src, sg_nents(src), areq->iv, + crypto_skcipher_ivsize(skcipher), + (totlen - + crypto_skcipher_ivsize(skcipher))); + } + if (src == dst) { nr_src = dma_map_sg(priv->dev, src, sg_nents(src), DMA_BIDIRECTIONAL); @@ -570,7 +581,6 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv, { struct skcipher_request *req = skcipher_request_cast(async); struct safexcel_cipher_req *sreq = skcipher_request_ctx(req); - struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(async->tfm); int err; if (sreq->needs_inv) { @@ -581,24 +591,6 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv, err = safexcel_handle_req_result(priv, ring, async, req->src, req->dst, req->cryptlen, sreq, should_complete, ret); - - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { - u32 block_sz = 0; - - switch (ctx->alg) { - case SAFEXCEL_DES: - block_sz = DES_BLOCK_SIZE; - break; - case SAFEXCEL_3DES: - block_sz = DES3_EDE_BLOCK_SIZE; - break; - case SAFEXCEL_AES: - block_sz = AES_BLOCK_SIZE; - break; - } - - memcpy(req->iv, ctx->base.ctxr->data, block_sz); - } } return err; @@ -656,12 +648,22 @@ static int safexcel_skcipher_send(struct crypto_async_request *async, int ring, BUG_ON(!(priv->flags & EIP197_TRC_CACHE) && sreq->needs_inv); - if (sreq->needs_inv) + if (sreq->needs_inv) { ret = safexcel_cipher_send_inv(async, ring, commands, results); - else + } else { + struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); + u8 input_iv[AES_BLOCK_SIZE]; + + /* + * Save input IV in case of CBC decrypt mode + * Will be overwritten with output IV prior to use! + */ + memcpy(input_iv, req->iv, crypto_skcipher_ivsize(skcipher)); + ret = safexcel_send_req(async, ring, sreq, req->src, - req->dst, req->cryptlen, 0, 0, req->iv, + req->dst, req->cryptlen, 0, 0, input_iv, commands, results); + } sreq->rdescs = *results; return ret; -- GitLab From 19b347b32bb195c50aea56b1ebf524e461e39827 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:55 +0200 Subject: [PATCH 0763/7155] crypto: inside-secure - fix scatter/gather list to descriptor conversion Fixed issues with the skcipher and AEAD scatter/gather list to engine descriptor conversion code which caused either too much or too little buffer space to be provided to the hardware. This caused errors with the testmgr extra tests, either kernel panics (on x86-EIP197-FPGA) or engine descriptor errors 0x1, 0x8 or 0x9 (on Macchiatobin e.g. Marvell A8K). With this patch in place, all skcipher and AEAD (extra) tests pass. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- .../crypto/inside-secure/safexcel_cipher.c | 182 +++++++++++++----- 1 file changed, 136 insertions(+), 46 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index f03640cc2095..4f25f5c9dfd6 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -54,6 +54,7 @@ struct safexcel_cipher_req { /* Number of result descriptors associated to the request */ unsigned int rdescs; bool needs_inv; + int nr_src, nr_dst; }; static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, @@ -358,10 +359,10 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin safexcel_complete(priv, ring); if (src == dst) { - dma_unmap_sg(priv->dev, src, sg_nents(src), DMA_BIDIRECTIONAL); + dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL); } else { - dma_unmap_sg(priv->dev, src, sg_nents(src), DMA_TO_DEVICE); - dma_unmap_sg(priv->dev, dst, sg_nents(dst), DMA_FROM_DEVICE); + dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE); + dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE); } /* @@ -370,7 +371,7 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) && (sreq->direction == SAFEXCEL_ENCRYPT)) { /* For encrypt take the last output word */ - sg_pcopy_to_buffer(dst, sg_nents(dst), areq->iv, + sg_pcopy_to_buffer(dst, sreq->nr_dst, areq->iv, crypto_skcipher_ivsize(skcipher), (cryptlen - crypto_skcipher_ivsize(skcipher))); @@ -393,63 +394,99 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(base->tfm); struct safexcel_crypto_priv *priv = ctx->priv; struct safexcel_command_desc *cdesc; + struct safexcel_command_desc *first_cdesc = NULL; struct safexcel_result_desc *rdesc, *first_rdesc = NULL; struct scatterlist *sg; - unsigned int totlen = cryptlen + assoclen; - int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = totlen; - int i, ret = 0; + unsigned int totlen; + unsigned int totlen_src = cryptlen + assoclen; + unsigned int totlen_dst = totlen_src; + int n_cdesc = 0, n_rdesc = 0; + int queued, i, ret = 0; + bool first = true; - if ((!ctx->aead) && (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) && - (sreq->direction == SAFEXCEL_DECRYPT)) { + sreq->nr_src = sg_nents_for_len(src, totlen_src); + + if (ctx->aead) { + /* + * AEAD has auth tag appended to output for encrypt and + * removed from the output for decrypt! + */ + if (sreq->direction == SAFEXCEL_DECRYPT) + totlen_dst -= digestsize; + else + totlen_dst += digestsize; + + memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32), + ctx->ipad, ctx->state_sz); + memcpy(ctx->base.ctxr->data + (ctx->key_len + ctx->state_sz) / + sizeof(u32), + ctx->opad, ctx->state_sz); + } else if ((ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) && + (sreq->direction == SAFEXCEL_DECRYPT)) { /* * Save IV from last crypto input word for CBC modes in decrypt * direction. Need to do this first in case of inplace operation * as it will be overwritten. */ - sg_pcopy_to_buffer(src, sg_nents(src), areq->iv, + sg_pcopy_to_buffer(src, sreq->nr_src, areq->iv, crypto_skcipher_ivsize(skcipher), - (totlen - + (totlen_src - crypto_skcipher_ivsize(skcipher))); } + sreq->nr_dst = sg_nents_for_len(dst, totlen_dst); + + /* + * Remember actual input length, source buffer length may be + * updated in case of inline operation below. + */ + totlen = totlen_src; + queued = totlen_src; + if (src == dst) { - nr_src = dma_map_sg(priv->dev, src, sg_nents(src), - DMA_BIDIRECTIONAL); - nr_dst = nr_src; - if (!nr_src) + sreq->nr_src = max(sreq->nr_src, sreq->nr_dst); + sreq->nr_dst = sreq->nr_src; + if (unlikely((totlen_src || totlen_dst) && + (sreq->nr_src <= 0))) { + dev_err(priv->dev, "In-place buffer not large enough (need %d bytes)!", + max(totlen_src, totlen_dst)); return -EINVAL; + } + dma_map_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL); } else { - nr_src = dma_map_sg(priv->dev, src, sg_nents(src), - DMA_TO_DEVICE); - if (!nr_src) + if (unlikely(totlen_src && (sreq->nr_src <= 0))) { + dev_err(priv->dev, "Source buffer not large enough (need %d bytes)!", + totlen_src); return -EINVAL; + } + dma_map_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE); - nr_dst = dma_map_sg(priv->dev, dst, sg_nents(dst), - DMA_FROM_DEVICE); - if (!nr_dst) { - dma_unmap_sg(priv->dev, src, nr_src, DMA_TO_DEVICE); + if (unlikely(totlen_dst && (sreq->nr_dst <= 0))) { + dev_err(priv->dev, "Dest buffer not large enough (need %d bytes)!", + totlen_dst); + dma_unmap_sg(priv->dev, src, sreq->nr_src, + DMA_TO_DEVICE); return -EINVAL; } + dma_map_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE); } memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len); - if (ctx->aead) { - memcpy(ctx->base.ctxr->data + ctx->key_len / sizeof(u32), - ctx->ipad, ctx->state_sz); - memcpy(ctx->base.ctxr->data + (ctx->key_len + ctx->state_sz) / sizeof(u32), - ctx->opad, ctx->state_sz); - } + /* The EIP cannot deal with zero length input packets! */ + if (totlen == 0) + totlen = 1; /* command descriptors */ - for_each_sg(src, sg, nr_src, i) { + for_each_sg(src, sg, sreq->nr_src, i) { int len = sg_dma_len(sg); /* Do not overflow the request */ if (queued - len < 0) len = queued; - cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, !(queued - len), + cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, + !(queued - len), sg_dma_address(sg), len, totlen, ctx->base.ctxr_dma); if (IS_ERR(cdesc)) { @@ -460,14 +497,7 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, n_cdesc++; if (n_cdesc == 1) { - safexcel_context_control(ctx, base, sreq, cdesc); - if (ctx->aead) - safexcel_aead_token(ctx, iv, cdesc, - sreq->direction, cryptlen, - assoclen, digestsize); - else - safexcel_skcipher_token(ctx, iv, cdesc, - cryptlen); + first_cdesc = cdesc; } queued -= len; @@ -475,23 +505,83 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, break; } + if (unlikely(!n_cdesc)) { + /* + * Special case: zero length input buffer. + * The engine always needs the 1st command descriptor, however! + */ + first_cdesc = safexcel_add_cdesc(priv, ring, 1, 1, 0, 0, totlen, + ctx->base.ctxr_dma); + n_cdesc = 1; + } + + /* Add context control words and token to first command descriptor */ + safexcel_context_control(ctx, base, sreq, first_cdesc); + if (ctx->aead) + safexcel_aead_token(ctx, iv, first_cdesc, + sreq->direction, cryptlen, + assoclen, digestsize); + else + safexcel_skcipher_token(ctx, iv, first_cdesc, + cryptlen); + /* result descriptors */ - for_each_sg(dst, sg, nr_dst, i) { - bool first = !i, last = sg_is_last(sg); + for_each_sg(dst, sg, sreq->nr_dst, i) { + bool last = (i == sreq->nr_dst - 1); u32 len = sg_dma_len(sg); - rdesc = safexcel_add_rdesc(priv, ring, first, last, - sg_dma_address(sg), len); + /* only allow the part of the buffer we know we need */ + if (len > totlen_dst) + len = totlen_dst; + if (unlikely(!len)) + break; + totlen_dst -= len; + + /* skip over AAD space in buffer - not written */ + if (assoclen) { + if (assoclen >= len) { + assoclen -= len; + continue; + } + rdesc = safexcel_add_rdesc(priv, ring, first, last, + sg_dma_address(sg) + + assoclen, + len - assoclen); + assoclen = 0; + } else { + rdesc = safexcel_add_rdesc(priv, ring, first, last, + sg_dma_address(sg), + len); + } if (IS_ERR(rdesc)) { /* No space left in the result descriptor ring */ ret = PTR_ERR(rdesc); goto rdesc_rollback; } - if (first) + if (first) { first_rdesc = rdesc; + first = false; + } n_rdesc++; } + if (unlikely(first)) { + /* + * Special case: AEAD decrypt with only AAD data. + * In this case there is NO output data from the engine, + * but the engine still needs a result descriptor! + * Create a dummy one just for catching the result token. + */ + rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0); + if (IS_ERR(rdesc)) { + /* No space left in the result descriptor ring */ + ret = PTR_ERR(rdesc); + goto rdesc_rollback; + } + first_rdesc = rdesc; + n_rdesc = 1; + } + safexcel_rdr_req_set(priv, ring, first_rdesc, base); *commands = n_cdesc; @@ -506,10 +596,10 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring, safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); if (src == dst) { - dma_unmap_sg(priv->dev, src, nr_src, DMA_BIDIRECTIONAL); + dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_BIDIRECTIONAL); } else { - dma_unmap_sg(priv->dev, src, nr_src, DMA_TO_DEVICE); - dma_unmap_sg(priv->dev, dst, nr_dst, DMA_FROM_DEVICE); + dma_unmap_sg(priv->dev, src, sreq->nr_src, DMA_TO_DEVICE); + dma_unmap_sg(priv->dev, dst, sreq->nr_dst, DMA_FROM_DEVICE); } return ret; -- GitLab From a74d850f787ef9578fa2829bfaecb222269cb754 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:56 +0200 Subject: [PATCH 0764/7155] crypto: inside-secure - fix EINVAL error (buf overflow) for AEAD decrypt This patch fixes a buffer overflow error returning -EINVAL for AEAD decrypt operations by NOT appending the (already verified) ICV to the output packet (which is not expected by the API anyway). With this fix, all testmgr AEAD (extra) tests now pass. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.h | 2 +- drivers/crypto/inside-secure/safexcel_cipher.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index e0c202f33674..91d221b421fd 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -458,7 +458,7 @@ static inline void eip197_noop_token(struct safexcel_token *token) #define EIP197_TOKEN_INS_ORIGIN_LEN(x) ((x) << 5) #define EIP197_TOKEN_INS_TYPE_OUTPUT BIT(5) #define EIP197_TOKEN_INS_TYPE_HASH BIT(6) -#define EIP197_TOKEN_INS_TYPE_CRYTO BIT(7) +#define EIP197_TOKEN_INS_TYPE_CRYPTO BIT(7) #define EIP197_TOKEN_INS_LAST BIT(8) /* Processing Engine Control Data */ diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 4f25f5c9dfd6..e87428733671 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -91,7 +91,7 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET | EIP197_TOKEN_STAT_LAST_HASH; token[0].instructions = EIP197_TOKEN_INS_LAST | - EIP197_TOKEN_INS_TYPE_CRYTO | + EIP197_TOKEN_INS_TYPE_CRYPTO | EIP197_TOKEN_INS_TYPE_OUTPUT; } @@ -117,14 +117,13 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; token[0].packet_length = assoclen; - token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH | - EIP197_TOKEN_INS_TYPE_OUTPUT; + token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; token[1].packet_length = cryptlen; token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; token[1].instructions = EIP197_TOKEN_INS_LAST | - EIP197_TOKEN_INS_TYPE_CRYTO | + EIP197_TOKEN_INS_TYPE_CRYPTO | EIP197_TOKEN_INS_TYPE_HASH | EIP197_TOKEN_INS_TYPE_OUTPUT; -- GitLab From dc5268b65dfc147850e0d2c49b000cb385d7b026 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:57 +0200 Subject: [PATCH 0765/7155] crypto: inside-secure: back out parts of earlier HMAC update workaround This patch backs out some changes done with commit 082ec2d48467 - "add support for HMAC updates" as that update just works around the issue for the basic tests by providing twice the amount of buffering, but this does not solve the case of much larger data blocks such as those performed by the extra tests. This is in preparation of an actual solution in the next patch(es), which does not actually require any extra buffering at all. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_hash.c | 32 ++++++++------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index a80a5e757b1f..ab972227ed90 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -41,11 +41,11 @@ struct safexcel_ahash_req { u64 len[2]; u64 processed[2]; - u8 cache[SHA512_BLOCK_SIZE << 1] __aligned(sizeof(u32)); + u8 cache[SHA512_BLOCK_SIZE] __aligned(sizeof(u32)); dma_addr_t cache_dma; unsigned int cache_sz; - u8 cache_next[SHA512_BLOCK_SIZE << 1] __aligned(sizeof(u32)); + u8 cache_next[SHA512_BLOCK_SIZE] __aligned(sizeof(u32)); }; static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) @@ -89,9 +89,6 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, cdesc->control_data.control0 |= ctx->alg; cdesc->control_data.control0 |= req->digest; - if (!req->finish) - cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH; - if (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) { if (req->processed[0] || req->processed[1]) { if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) @@ -110,6 +107,9 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, cdesc->control_data.control0 |= CONTEXT_CONTROL_RESTART_HASH; } + if (!req->finish) + cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH; + /* * Copy the input digest if needed, and setup the context * fields. Do this now as we need it to setup the first command @@ -216,8 +216,6 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, u64 queued, len, cache_len, cache_max; cache_max = crypto_ahash_blocksize(ahash); - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) - cache_max <<= 1; queued = len = safexcel_queued_len(req); if (queued <= cache_max) @@ -229,17 +227,13 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, /* If this is not the last request and the queued data does not * fit into full blocks, cache it for the next send() call. */ - extra = queued & (crypto_ahash_blocksize(ahash) - 1); - - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC && - extra < crypto_ahash_blocksize(ahash)) - extra += crypto_ahash_blocksize(ahash); + extra = queued & (cache_max - 1); /* If this is not the last request and the queued data * is a multiple of a block, cache the last one for now. */ if (!extra) - extra = crypto_ahash_blocksize(ahash); + extra = cache_max; sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), req->cache_next, extra, @@ -247,6 +241,12 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, queued -= extra; len -= extra; + + if (!queued) { + *commands = 0; + *results = 0; + return 0; + } } /* Add a command descriptor for the cached data, if any */ @@ -613,8 +613,6 @@ static int safexcel_ahash_update(struct ahash_request *areq) req->len[1]++; cache_max = crypto_ahash_blocksize(ahash); - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) - cache_max <<= 1; safexcel_ahash_cache(areq, cache_max); @@ -689,8 +687,6 @@ static int safexcel_ahash_export(struct ahash_request *areq, void *out) u32 cache_sz; cache_sz = crypto_ahash_blocksize(ahash); - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) - cache_sz <<= 1; export->len[0] = req->len[0]; export->len[1] = req->len[1]; @@ -718,8 +714,6 @@ static int safexcel_ahash_import(struct ahash_request *areq, const void *in) return ret; cache_sz = crypto_ahash_blocksize(ahash); - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) - cache_sz <<= 1; req->len[0] = export->len[0]; req->len[1] = export->len[1]; -- GitLab From 85695b093d559bcd2393a65373355390ac62d67b Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:58 +0200 Subject: [PATCH 0766/7155] crypto: inside-secure - let HW deal with initial hash digest The driver was loading the initial digest for hash operations into the hardware explicitly, but this is not needed as the hardware can handle that by itself, which is more efficient and avoids any context record coherence issues. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_hash.c | 71 ++------------------ 1 file changed, 6 insertions(+), 65 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index ab972227ed90..d3c64901e2a9 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -641,8 +641,12 @@ static int safexcel_ahash_final(struct ahash_request *areq) req->last_req = true; req->finish = true; - /* If we have an overall 0 length request */ - if (!req->len[0] && !req->len[1] && !areq->nbytes) { + if (unlikely(!req->len[0] && !req->len[1] && !areq->nbytes)) { + /* + * If we have an overall 0 length *hash* request: + * The HW cannot do 0 length hash, so we provide the correct + * result directly here. + */ if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) memcpy(areq->result, md5_zero_message_hash, MD5_DIGEST_SIZE); @@ -751,12 +755,6 @@ static int safexcel_sha1_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = SHA1_H0; - req->state[1] = SHA1_H1; - req->state[2] = SHA1_H2; - req->state[3] = SHA1_H3; - req->state[4] = SHA1_H4; - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA1_DIGEST_SIZE; @@ -1065,15 +1063,6 @@ static int safexcel_sha256_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = SHA256_H0; - req->state[1] = SHA256_H1; - req->state[2] = SHA256_H2; - req->state[3] = SHA256_H3; - req->state[4] = SHA256_H4; - req->state[5] = SHA256_H5; - req->state[6] = SHA256_H6; - req->state[7] = SHA256_H7; - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA256_DIGEST_SIZE; @@ -1128,15 +1117,6 @@ static int safexcel_sha224_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = SHA224_H0; - req->state[1] = SHA224_H1; - req->state[2] = SHA224_H2; - req->state[3] = SHA224_H3; - req->state[4] = SHA224_H4; - req->state[5] = SHA224_H5; - req->state[6] = SHA224_H6; - req->state[7] = SHA224_H7; - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA256_DIGEST_SIZE; @@ -1305,23 +1285,6 @@ static int safexcel_sha512_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = lower_32_bits(SHA512_H0); - req->state[1] = upper_32_bits(SHA512_H0); - req->state[2] = lower_32_bits(SHA512_H1); - req->state[3] = upper_32_bits(SHA512_H1); - req->state[4] = lower_32_bits(SHA512_H2); - req->state[5] = upper_32_bits(SHA512_H2); - req->state[6] = lower_32_bits(SHA512_H3); - req->state[7] = upper_32_bits(SHA512_H3); - req->state[8] = lower_32_bits(SHA512_H4); - req->state[9] = upper_32_bits(SHA512_H4); - req->state[10] = lower_32_bits(SHA512_H5); - req->state[11] = upper_32_bits(SHA512_H5); - req->state[12] = lower_32_bits(SHA512_H6); - req->state[13] = upper_32_bits(SHA512_H6); - req->state[14] = lower_32_bits(SHA512_H7); - req->state[15] = upper_32_bits(SHA512_H7); - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA512_DIGEST_SIZE; @@ -1376,23 +1339,6 @@ static int safexcel_sha384_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = lower_32_bits(SHA384_H0); - req->state[1] = upper_32_bits(SHA384_H0); - req->state[2] = lower_32_bits(SHA384_H1); - req->state[3] = upper_32_bits(SHA384_H1); - req->state[4] = lower_32_bits(SHA384_H2); - req->state[5] = upper_32_bits(SHA384_H2); - req->state[6] = lower_32_bits(SHA384_H3); - req->state[7] = upper_32_bits(SHA384_H3); - req->state[8] = lower_32_bits(SHA384_H4); - req->state[9] = upper_32_bits(SHA384_H4); - req->state[10] = lower_32_bits(SHA384_H5); - req->state[11] = upper_32_bits(SHA384_H5); - req->state[12] = lower_32_bits(SHA384_H6); - req->state[13] = upper_32_bits(SHA384_H6); - req->state[14] = lower_32_bits(SHA384_H7); - req->state[15] = upper_32_bits(SHA384_H7); - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA512_DIGEST_SIZE; @@ -1561,11 +1507,6 @@ static int safexcel_md5_init(struct ahash_request *areq) memset(req, 0, sizeof(*req)); - req->state[0] = MD5_H0; - req->state[1] = MD5_H1; - req->state[2] = MD5_H2; - req->state[3] = MD5_H3; - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = MD5_DIGEST_SIZE; -- GitLab From 41abed7d72c93fd31b0c1d51f42606216f1ea882 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:39:59 +0200 Subject: [PATCH 0767/7155] crypto: inside-secure - add support for arbitrary size hash/HMAC updates This patch fixes an issue with hash and HMAC operations that perform "large" intermediate updates (i.e. combined size > 2 hash blocks) by actually making use of the hardware's hash continue capabilities. The original implementation would cache these updates in a buffer that was 2 hash blocks in size and fail if all update calls combined would overflow that buffer. Which caused the cryptomgr extra tests to fail. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.h | 4 +- drivers/crypto/inside-secure/safexcel_hash.c | 423 ++++++++++++------- 2 files changed, 269 insertions(+), 158 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index 91d221b421fd..b73b17dcb8b1 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -637,6 +637,8 @@ struct safexcel_context { bool exit_inv; }; +#define HASH_CACHE_SIZE SHA512_BLOCK_SIZE + struct safexcel_ahash_export_state { u64 len[2]; u64 processed[2]; @@ -644,7 +646,7 @@ struct safexcel_ahash_export_state { u32 digest; u32 state[SHA512_DIGEST_SIZE / sizeof(u32)]; - u8 cache[SHA512_BLOCK_SIZE << 1]; + u8 cache[HASH_CACHE_SIZE]; }; /* diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index d3c64901e2a9..1476574b346e 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -35,17 +35,18 @@ struct safexcel_ahash_req { u32 digest; - u8 state_sz; /* expected sate size, only set once */ + u8 state_sz; /* expected state size, only set once */ + u8 block_sz; /* block size, only set once */ u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); u64 len[2]; u64 processed[2]; - u8 cache[SHA512_BLOCK_SIZE] __aligned(sizeof(u32)); + u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); dma_addr_t cache_dma; unsigned int cache_sz; - u8 cache_next[SHA512_BLOCK_SIZE] __aligned(sizeof(u32)); + u8 cache_next[HASH_CACHE_SIZE] __aligned(sizeof(u32)); }; static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) @@ -79,75 +80,99 @@ static void safexcel_hash_token(struct safexcel_command_desc *cdesc, static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, struct safexcel_ahash_req *req, - struct safexcel_command_desc *cdesc, - unsigned int digestsize) + struct safexcel_command_desc *cdesc) { struct safexcel_crypto_priv *priv = ctx->priv; - int i; + u64 count = 0; - cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_HASH_OUT; cdesc->control_data.control0 |= ctx->alg; - cdesc->control_data.control0 |= req->digest; - - if (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) { - if (req->processed[0] || req->processed[1]) { - if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5) - cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(5); - else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA1) - cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(6); - else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA224 || - ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA256) - cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(9); - else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA384 || - ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) - cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(17); - - cdesc->control_data.control1 |= CONTEXT_CONTROL_DIGEST_CNT; + + /* + * Copy the input digest if needed, and setup the context + * fields. Do this now as we need it to setup the first command + * descriptor. + */ + if ((!req->processed[0]) && (!req->processed[1])) { + /* First - and possibly only - block of basic hash only */ + if (req->finish) { + cdesc->control_data.control0 |= + CONTEXT_CONTROL_TYPE_HASH_OUT | + CONTEXT_CONTROL_RESTART_HASH | + /* ensure its not 0! */ + CONTEXT_CONTROL_SIZE(1); } else { - cdesc->control_data.control0 |= CONTEXT_CONTROL_RESTART_HASH; + cdesc->control_data.control0 |= + CONTEXT_CONTROL_TYPE_HASH_OUT | + CONTEXT_CONTROL_RESTART_HASH | + CONTEXT_CONTROL_NO_FINISH_HASH | + /* ensure its not 0! */ + CONTEXT_CONTROL_SIZE(1); } + return; + } - if (!req->finish) - cdesc->control_data.control0 |= CONTEXT_CONTROL_NO_FINISH_HASH; - - /* - * Copy the input digest if needed, and setup the context - * fields. Do this now as we need it to setup the first command - * descriptor. - */ - if (req->processed[0] || req->processed[1]) { - for (i = 0; i < digestsize / sizeof(u32); i++) - ctx->base.ctxr->data[i] = cpu_to_le32(req->state[i]); - - if (req->finish) { - u64 count = req->processed[0] / EIP197_COUNTER_BLOCK_SIZE; - count += ((0xffffffff / EIP197_COUNTER_BLOCK_SIZE) * - req->processed[1]); - - /* This is a haredware limitation, as the - * counter must fit into an u32. This represents - * a farily big amount of input data, so we - * shouldn't see this. - */ - if (unlikely(count & 0xffff0000)) { - dev_warn(priv->dev, - "Input data is too big\n"); - return; - } - - ctx->base.ctxr->data[i] = cpu_to_le32(count); + /* Hash continuation or HMAC, setup (inner) digest from state */ + memcpy(ctx->base.ctxr->data, req->state, req->state_sz); + + if (req->finish) { + /* Compute digest count for hash/HMAC finish operations */ + if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || + req->processed[1] || + (req->processed[0] != req->block_sz)) { + count = req->processed[0] / EIP197_COUNTER_BLOCK_SIZE; + count += ((0x100000000ULL / EIP197_COUNTER_BLOCK_SIZE) * + req->processed[1]); + + /* This is a hardware limitation, as the + * counter must fit into an u32. This represents + * a fairly big amount of input data, so we + * shouldn't see this. + */ + if (unlikely(count & 0xffffffff00000000ULL)) { + dev_warn(priv->dev, + "Input data is too big\n"); + return; } } - } else if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) { - cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(2 * req->state_sz / sizeof(u32)); - memcpy(ctx->base.ctxr->data, ctx->ipad, req->state_sz); - memcpy(ctx->base.ctxr->data + req->state_sz / sizeof(u32), - ctx->opad, req->state_sz); + if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || + /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ + ((req->processed[1] || + (req->processed[0] != req->block_sz)))) { + /* Basic hash continue operation, need digest + cnt */ + cdesc->control_data.control0 |= + CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | + CONTEXT_CONTROL_TYPE_HASH_OUT | + CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + cdesc->control_data.control1 |= + CONTEXT_CONTROL_DIGEST_CNT; + ctx->base.ctxr->data[req->state_sz >> 2] = + cpu_to_le32(count); + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + } else { /* HMAC */ + /* Need outer digest for HMAC finalization */ + memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), + ctx->opad, req->state_sz); + + /* Single pass HMAC - no digest count */ + cdesc->control_data.control0 |= + CONTEXT_CONTROL_SIZE(req->state_sz >> 1) | + CONTEXT_CONTROL_TYPE_HASH_OUT | + CONTEXT_CONTROL_DIGEST_HMAC; + } + } else { /* Hash continuation, do not finish yet */ + cdesc->control_data.control0 |= + CONTEXT_CONTROL_SIZE(req->state_sz >> 2) | + CONTEXT_CONTROL_DIGEST_PRECOMPUTED | + CONTEXT_CONTROL_TYPE_HASH_OUT | + CONTEXT_CONTROL_NO_FINISH_HASH; } } -static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int ring, +static int safexcel_ahash_enqueue(struct ahash_request *areq); + +static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, + int ring, struct crypto_async_request *async, bool *should_complete, int *ret) { @@ -155,6 +180,7 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin struct ahash_request *areq = ahash_request_cast(async); struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); struct safexcel_ahash_req *sreq = ahash_request_ctx(areq); + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(ahash); u64 cache_len; *ret = 0; @@ -188,9 +214,33 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, int rin sreq->cache_sz = 0; } - if (sreq->finish) + if (sreq->finish) { + if (sreq->hmac && + (sreq->digest != CONTEXT_CONTROL_DIGEST_HMAC)) { + /* Faking HMAC using hash - need to do outer hash */ + memcpy(sreq->cache, sreq->state, + crypto_ahash_digestsize(ahash)); + + memcpy(sreq->state, ctx->opad, sreq->state_sz); + + sreq->len[0] = sreq->block_sz + + crypto_ahash_digestsize(ahash); + sreq->len[1] = 0; + sreq->processed[0] = sreq->block_sz; + sreq->processed[1] = 0; + sreq->hmac = 0; + + ctx->base.needs_inv = true; + areq->nbytes = 0; + safexcel_ahash_enqueue(areq); + + *should_complete = false; /* Not done yet */ + return 1; + } + memcpy(areq->result, sreq->state, crypto_ahash_digestsize(ahash)); + } cache_len = safexcel_queued_len(sreq); if (cache_len) @@ -205,7 +255,6 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, int *commands, int *results) { struct ahash_request *areq = ahash_request_cast(async); - struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); struct safexcel_ahash_req *req = ahash_request_ctx(areq); struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_crypto_priv *priv = ctx->priv; @@ -213,27 +262,25 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, struct safexcel_result_desc *rdesc; struct scatterlist *sg; int i, extra = 0, n_cdesc = 0, ret = 0; - u64 queued, len, cache_len, cache_max; - - cache_max = crypto_ahash_blocksize(ahash); + u64 queued, len, cache_len; queued = len = safexcel_queued_len(req); - if (queued <= cache_max) + if (queued <= HASH_CACHE_SIZE) cache_len = queued; else cache_len = queued - areq->nbytes; - if (!req->last_req) { + if (!req->finish && !req->last_req) { /* If this is not the last request and the queued data does not - * fit into full blocks, cache it for the next send() call. + * fit into full cache blocks, cache it for the next send call. */ - extra = queued & (cache_max - 1); + extra = queued & (HASH_CACHE_SIZE - 1); /* If this is not the last request and the queued data * is a multiple of a block, cache the last one for now. */ if (!extra) - extra = cache_max; + extra = HASH_CACHE_SIZE; sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), req->cache_next, extra, @@ -272,8 +319,14 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, goto send_command; } + /* Skip descriptor generation for zero-length requests */ + if (!areq->nbytes) + goto send_command; + /* Now handle the current ahash request buffer(s) */ - req->nents = dma_map_sg(priv->dev, areq->src, sg_nents(areq->src), + req->nents = dma_map_sg(priv->dev, areq->src, + sg_nents_for_len(areq->src, + areq->nbytes), DMA_TO_DEVICE); if (!req->nents) { ret = -ENOMEM; @@ -288,7 +341,8 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, sglen = queued; cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, - !(queued - sglen), sg_dma_address(sg), + !(queued - sglen), + sg_dma_address(sg), sglen, len, ctx->base.ctxr_dma); if (IS_ERR(cdesc)) { ret = PTR_ERR(cdesc); @@ -306,7 +360,7 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, send_command: /* Setup the context options */ - safexcel_context_control(ctx, req, first_cdesc, req->state_sz); + safexcel_context_control(ctx, req, first_cdesc); /* Add the token */ safexcel_hash_token(first_cdesc, len, req->state_sz); @@ -355,27 +409,6 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, return ret; } -static inline bool safexcel_ahash_needs_inv_get(struct ahash_request *areq) -{ - struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); - struct safexcel_ahash_req *req = ahash_request_ctx(areq); - unsigned int state_w_sz = req->state_sz / sizeof(u32); - u64 processed; - int i; - - processed = req->processed[0] / EIP197_COUNTER_BLOCK_SIZE; - processed += (0xffffffff / EIP197_COUNTER_BLOCK_SIZE) * req->processed[1]; - - for (i = 0; i < state_w_sz; i++) - if (ctx->base.ctxr->data[i] != cpu_to_le32(req->state[i])) - return true; - - if (ctx->base.ctxr->data[state_w_sz] != cpu_to_le32(processed)) - return true; - - return false; -} - static int safexcel_handle_inv_result(struct safexcel_crypto_priv *priv, int ring, struct crypto_async_request *async, @@ -523,30 +556,25 @@ static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm) /* safexcel_ahash_cache: cache data until at least one request can be sent to * the engine, aka. when there is at least 1 block size in the pipe. */ -static int safexcel_ahash_cache(struct ahash_request *areq, u32 cache_max) +static int safexcel_ahash_cache(struct ahash_request *areq) { struct safexcel_ahash_req *req = ahash_request_ctx(areq); - u64 queued, cache_len; + u64 cache_len; - /* queued: everything accepted by the driver which will be handled by - * the next send() calls. - * tot sz handled by update() - tot sz handled by send() - */ - queued = safexcel_queued_len(req); /* cache_len: everything accepted by the driver but not sent yet, * tot sz handled by update() - last req sz - tot sz handled by send() */ - cache_len = queued - areq->nbytes; + cache_len = safexcel_queued_len(req); /* * In case there isn't enough bytes to proceed (less than a * block size), cache the data until we have enough. */ - if (cache_len + areq->nbytes <= cache_max) { + if (cache_len + areq->nbytes <= HASH_CACHE_SIZE) { sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), req->cache + cache_len, areq->nbytes, 0); - return areq->nbytes; + return 0; } /* We couldn't cache all the data */ @@ -565,13 +593,25 @@ static int safexcel_ahash_enqueue(struct ahash_request *areq) if (ctx->base.ctxr) { if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && (req->processed[0] || req->processed[1]) && - req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) - /* We're still setting needs_inv here, even though it is + (/* invalidate for basic hash continuation finish */ + (req->finish && + (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) || + /* invalidate if (i)digest changed */ + memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || + /* invalidate for HMAC continuation finish */ + (req->finish && (req->processed[1] || + (req->processed[0] != req->block_sz))) || + /* invalidate for HMAC finish with odigest changed */ + (req->finish && + memcmp(ctx->base.ctxr->data + (req->state_sz>>2), + ctx->opad, req->state_sz)))) + /* + * We're still setting needs_inv here, even though it is * cleared right away, because the needs_inv flag can be * set in other functions and we want to keep the same * logic. */ - ctx->base.needs_inv = safexcel_ahash_needs_inv_get(areq); + ctx->base.needs_inv = true; if (ctx->base.needs_inv) { ctx->base.needs_inv = false; @@ -601,33 +641,25 @@ static int safexcel_ahash_enqueue(struct ahash_request *areq) static int safexcel_ahash_update(struct ahash_request *areq) { struct safexcel_ahash_req *req = ahash_request_ctx(areq); - struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); - u32 cache_max; + int ret; /* If the request is 0 length, do nothing */ if (!areq->nbytes) return 0; + /* Add request to the cache if it fits */ + ret = safexcel_ahash_cache(areq); + + /* Update total request length */ req->len[0] += areq->nbytes; if (req->len[0] < areq->nbytes) req->len[1]++; - cache_max = crypto_ahash_blocksize(ahash); - - safexcel_ahash_cache(areq, cache_max); - - /* - * We're not doing partial updates when performing an hmac request. - * Everything will be handled by the final() call. + /* If not all data could fit into the cache, go process the excess. + * Also go process immediately for an HMAC IV precompute, which + * will never be finished at all, but needs to be processed anyway. */ - if (req->digest == CONTEXT_CONTROL_DIGEST_HMAC) - return 0; - - if (req->hmac) - return safexcel_ahash_enqueue(areq); - - if (!req->last_req && - safexcel_queued_len(req) > cache_max) + if ((ret && !req->finish) || req->last_req) return safexcel_ahash_enqueue(areq); return 0; @@ -638,7 +670,6 @@ static int safexcel_ahash_final(struct ahash_request *areq) struct safexcel_ahash_req *req = ahash_request_ctx(areq); struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); - req->last_req = true; req->finish = true; if (unlikely(!req->len[0] && !req->len[1] && !areq->nbytes)) { @@ -667,6 +698,14 @@ static int safexcel_ahash_final(struct ahash_request *areq) SHA512_DIGEST_SIZE); return 0; + } else if (unlikely(req->hmac && !req->len[1] && + (req->len[0] == req->block_sz) && + !areq->nbytes)) { + /* TODO: add support for zero length HMAC */ + return 0; + } else if (req->hmac) { + /* Finalize HMAC */ + req->digest = CONTEXT_CONTROL_DIGEST_HMAC; } return safexcel_ahash_enqueue(areq); @@ -676,7 +715,6 @@ static int safexcel_ahash_finup(struct ahash_request *areq) { struct safexcel_ahash_req *req = ahash_request_ctx(areq); - req->last_req = true; req->finish = true; safexcel_ahash_update(areq); @@ -685,12 +723,8 @@ static int safexcel_ahash_finup(struct ahash_request *areq) static int safexcel_ahash_export(struct ahash_request *areq, void *out) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); struct safexcel_ahash_req *req = ahash_request_ctx(areq); struct safexcel_ahash_export_state *export = out; - u32 cache_sz; - - cache_sz = crypto_ahash_blocksize(ahash); export->len[0] = req->len[0]; export->len[1] = req->len[1]; @@ -700,25 +734,21 @@ static int safexcel_ahash_export(struct ahash_request *areq, void *out) export->digest = req->digest; memcpy(export->state, req->state, req->state_sz); - memcpy(export->cache, req->cache, cache_sz); + memcpy(export->cache, req->cache, HASH_CACHE_SIZE); return 0; } static int safexcel_ahash_import(struct ahash_request *areq, const void *in) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); struct safexcel_ahash_req *req = ahash_request_ctx(areq); const struct safexcel_ahash_export_state *export = in; - u32 cache_sz; int ret; ret = crypto_ahash_init(areq); if (ret) return ret; - cache_sz = crypto_ahash_blocksize(ahash); - req->len[0] = export->len[0]; req->len[1] = export->len[1]; req->processed[0] = export->processed[0]; @@ -726,7 +756,7 @@ static int safexcel_ahash_import(struct ahash_request *areq, const void *in) req->digest = export->digest; - memcpy(req->cache, export->cache, cache_sz); + memcpy(req->cache, export->cache, HASH_CACHE_SIZE); memcpy(req->state, export->state, req->state_sz); return 0; @@ -758,6 +788,7 @@ static int safexcel_sha1_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA1_DIGEST_SIZE; + req->block_sz = SHA1_BLOCK_SIZE; return 0; } @@ -824,10 +855,23 @@ struct safexcel_alg_template safexcel_alg_sha1 = { static int safexcel_hmac_sha1_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_sha1_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = SHA1_BLOCK_SIZE; + req->processed[0] = SHA1_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = SHA1_DIGEST_SIZE; + req->block_sz = SHA1_BLOCK_SIZE; + req->hmac = true; + return 0; } @@ -996,21 +1040,16 @@ static int safexcel_hmac_alg_setkey(struct crypto_ahash *tfm, const u8 *key, struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); struct safexcel_crypto_priv *priv = ctx->priv; struct safexcel_ahash_export_state istate, ostate; - int ret, i; + int ret; ret = safexcel_hmac_setkey(alg, key, keylen, &istate, &ostate); if (ret) return ret; - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr) { - for (i = 0; i < state_sz / sizeof(u32); i++) { - if (ctx->ipad[i] != le32_to_cpu(istate.state[i]) || - ctx->opad[i] != le32_to_cpu(ostate.state[i])) { - ctx->base.needs_inv = true; - break; - } - } - } + if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr && + (memcmp(ctx->ipad, istate.state, state_sz) || + memcmp(ctx->opad, ostate.state, state_sz))) + ctx->base.needs_inv = true; memcpy(ctx->ipad, &istate.state, state_sz); memcpy(ctx->opad, &ostate.state, state_sz); @@ -1066,6 +1105,7 @@ static int safexcel_sha256_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA256_DIGEST_SIZE; + req->block_sz = SHA256_BLOCK_SIZE; return 0; } @@ -1120,6 +1160,7 @@ static int safexcel_sha224_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA256_DIGEST_SIZE; + req->block_sz = SHA256_BLOCK_SIZE; return 0; } @@ -1173,10 +1214,23 @@ static int safexcel_hmac_sha224_setkey(struct crypto_ahash *tfm, const u8 *key, static int safexcel_hmac_sha224_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_sha224_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = SHA256_BLOCK_SIZE; + req->processed[0] = SHA256_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = SHA256_DIGEST_SIZE; + req->block_sz = SHA256_BLOCK_SIZE; + req->hmac = true; + return 0; } @@ -1230,10 +1284,23 @@ static int safexcel_hmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, static int safexcel_hmac_sha256_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_sha256_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = SHA256_BLOCK_SIZE; + req->processed[0] = SHA256_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = SHA256_DIGEST_SIZE; + req->block_sz = SHA256_BLOCK_SIZE; + req->hmac = true; + return 0; } @@ -1288,6 +1355,7 @@ static int safexcel_sha512_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA512_DIGEST_SIZE; + req->block_sz = SHA512_BLOCK_SIZE; return 0; } @@ -1342,6 +1410,7 @@ static int safexcel_sha384_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = SHA512_DIGEST_SIZE; + req->block_sz = SHA512_BLOCK_SIZE; return 0; } @@ -1395,10 +1464,23 @@ static int safexcel_hmac_sha512_setkey(struct crypto_ahash *tfm, const u8 *key, static int safexcel_hmac_sha512_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_sha512_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = SHA512_BLOCK_SIZE; + req->processed[0] = SHA512_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = SHA512_DIGEST_SIZE; + req->block_sz = SHA512_BLOCK_SIZE; + req->hmac = true; + return 0; } @@ -1452,10 +1534,23 @@ static int safexcel_hmac_sha384_setkey(struct crypto_ahash *tfm, const u8 *key, static int safexcel_hmac_sha384_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_sha384_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = SHA512_BLOCK_SIZE; + req->processed[0] = SHA512_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = SHA512_DIGEST_SIZE; + req->block_sz = SHA512_BLOCK_SIZE; + req->hmac = true; + return 0; } @@ -1510,6 +1605,7 @@ static int safexcel_md5_init(struct ahash_request *areq) ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = MD5_DIGEST_SIZE; + req->block_sz = MD5_HMAC_BLOCK_SIZE; return 0; } @@ -1556,10 +1652,23 @@ struct safexcel_alg_template safexcel_alg_md5 = { static int safexcel_hmac_md5_init(struct ahash_request *areq) { + struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct safexcel_ahash_req *req = ahash_request_ctx(areq); - safexcel_md5_init(areq); - req->digest = CONTEXT_CONTROL_DIGEST_HMAC; + memset(req, 0, sizeof(*req)); + + /* Start from ipad precompute */ + memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE); + /* Already processed the key^ipad part now! */ + req->len[0] = MD5_HMAC_BLOCK_SIZE; + req->processed[0] = MD5_HMAC_BLOCK_SIZE; + + ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; + req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + req->state_sz = MD5_DIGEST_SIZE; + req->block_sz = MD5_HMAC_BLOCK_SIZE; + req->hmac = true; + return 0; } -- GitLab From 85b36ee8e9a8b18b3c09b8a8b6ac3dc694584bab Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 2 Jul 2019 16:40:00 +0200 Subject: [PATCH 0768/7155] crypto: inside-secure - add support for 0 length HMAC messages This patch adds support for the specific corner case of performing HMAC on an empty string (i.e. payload length is zero). This solves the last failing cryptomgr extratests for HMAC. Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_hash.c | 47 ++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index 1476574b346e..a777dec5f41f 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -29,6 +29,8 @@ struct safexcel_ahash_req { bool finish; bool hmac; bool needs_inv; + bool hmac_zlen; + bool len_is_le; int nents; dma_addr_t result_dma; @@ -117,7 +119,7 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, if (req->finish) { /* Compute digest count for hash/HMAC finish operations */ if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || - req->processed[1] || + req->hmac_zlen || req->processed[1] || (req->processed[0] != req->block_sz)) { count = req->processed[0] / EIP197_COUNTER_BLOCK_SIZE; count += ((0x100000000ULL / EIP197_COUNTER_BLOCK_SIZE) * @@ -136,6 +138,8 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, } if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || + /* Special case: zero length HMAC */ + req->hmac_zlen || /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ ((req->processed[1] || (req->processed[0] != req->block_sz)))) { @@ -144,11 +148,18 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | CONTEXT_CONTROL_TYPE_HASH_OUT | CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + /* For zero-len HMAC, don't finalize, already padded! */ + if (req->hmac_zlen) + cdesc->control_data.control0 |= + CONTEXT_CONTROL_NO_FINISH_HASH; cdesc->control_data.control1 |= CONTEXT_CONTROL_DIGEST_CNT; ctx->base.ctxr->data[req->state_sz >> 2] = cpu_to_le32(count); req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; + + /* Clear zero-length HMAC flag for next operation! */ + req->hmac_zlen = false; } else { /* HMAC */ /* Need outer digest for HMAC finalization */ memcpy(ctx->base.ctxr->data + (req->state_sz >> 2), @@ -701,8 +712,37 @@ static int safexcel_ahash_final(struct ahash_request *areq) } else if (unlikely(req->hmac && !req->len[1] && (req->len[0] == req->block_sz) && !areq->nbytes)) { - /* TODO: add support for zero length HMAC */ - return 0; + /* + * If we have an overall 0 length *HMAC* request: + * For HMAC, we need to finalize the inner digest + * and then perform the outer hash. + */ + + /* generate pad block in the cache */ + /* start with a hash block of all zeroes */ + memset(req->cache, 0, req->block_sz); + /* set the first byte to 0x80 to 'append a 1 bit' */ + req->cache[0] = 0x80; + /* add the length in bits in the last 2 bytes */ + if (req->len_is_le) { + /* Little endian length word (e.g. MD5) */ + req->cache[req->block_sz-8] = (req->block_sz << 3) & + 255; + req->cache[req->block_sz-7] = (req->block_sz >> 5); + } else { + /* Big endian length word (e.g. any SHA) */ + req->cache[req->block_sz-2] = (req->block_sz >> 5); + req->cache[req->block_sz-1] = (req->block_sz << 3) & + 255; + } + + req->len[0] += req->block_sz; /* plus 1 hash block */ + + /* Set special zero-length HMAC flag */ + req->hmac_zlen = true; + + /* Finalize HMAC */ + req->digest = CONTEXT_CONTROL_DIGEST_HMAC; } else if (req->hmac) { /* Finalize HMAC */ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; @@ -1667,6 +1707,7 @@ static int safexcel_hmac_md5_init(struct ahash_request *areq) req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; req->state_sz = MD5_DIGEST_SIZE; req->block_sz = MD5_HMAC_BLOCK_SIZE; + req->len_is_le = true; /* MD5 is little endian! ... */ req->hmac = true; return 0; -- GitLab From 20bb4ef038a97b8bb5c07d2a1125019a93f618b3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:19 +0200 Subject: [PATCH 0769/7155] crypto: arm/aes-ce - cosmetic/whitespace cleanup Rearrange the aes_algs[] array for legibility. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-ce-glue.c | 116 ++++++++++++++++------------------ 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index 620aacf0d128..e4139a0b0d75 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -334,69 +334,65 @@ static int xts_decrypt(struct skcipher_request *req) } static struct skcipher_alg aes_algs[] = { { - .base = { - .cra_name = "__ecb(aes)", - .cra_driver_name = "__ecb-aes-ce", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - }, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = ce_aes_setkey, - .encrypt = ecb_encrypt, - .decrypt = ecb_decrypt, + .base.cra_name = "__ecb(aes)", + .base.cra_driver_name = "__ecb-aes-ce", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct crypto_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = ce_aes_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, }, { - .base = { - .cra_name = "__cbc(aes)", - .cra_driver_name = "__cbc-aes-ce", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - }, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = ce_aes_setkey, - .encrypt = cbc_encrypt, - .decrypt = cbc_decrypt, + .base.cra_name = "__cbc(aes)", + .base.cra_driver_name = "__cbc-aes-ce", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct crypto_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = ce_aes_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, }, { - .base = { - .cra_name = "__ctr(aes)", - .cra_driver_name = "__ctr-aes-ce", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - }, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .chunksize = AES_BLOCK_SIZE, - .setkey = ce_aes_setkey, - .encrypt = ctr_encrypt, - .decrypt = ctr_encrypt, + .base.cra_name = "__ctr(aes)", + .base.cra_driver_name = "__ctr-aes-ce", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct crypto_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .chunksize = AES_BLOCK_SIZE, + .setkey = ce_aes_setkey, + .encrypt = ctr_encrypt, + .decrypt = ctr_encrypt, }, { - .base = { - .cra_name = "__xts(aes)", - .cra_driver_name = "__xts-aes-ce", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), - .cra_module = THIS_MODULE, - }, - .min_keysize = 2 * AES_MIN_KEY_SIZE, - .max_keysize = 2 * AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = xts_set_key, - .encrypt = xts_encrypt, - .decrypt = xts_decrypt, + .base.cra_name = "__xts(aes)", + .base.cra_driver_name = "__xts-aes-ce", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_INTERNAL, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = 2 * AES_MIN_KEY_SIZE, + .max_keysize = 2 * AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = xts_set_key, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, } }; static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)]; -- GitLab From 724ecd3c0eb7040d423b22332a60d097e2666820 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:20 +0200 Subject: [PATCH 0770/7155] crypto: aes - rename local routines to prevent future clashes Rename some local AES encrypt/decrypt routines so they don't clash with the names we are about to introduce for the routines exposed by the generic AES library. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-cipher-glue.c | 8 ++++---- arch/arm64/crypto/aes-cipher-glue.c | 8 ++++---- arch/sparc/crypto/aes_glue.c | 8 ++++---- arch/x86/crypto/aesni-intel_glue.c | 8 ++++---- crypto/aes_generic.c | 8 ++++---- drivers/crypto/padlock-aes.c | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/crypto/aes-cipher-glue.c b/arch/arm/crypto/aes-cipher-glue.c index 128d0a1ac068..6efb3c04353f 100644 --- a/arch/arm/crypto/aes-cipher-glue.c +++ b/arch/arm/crypto/aes-cipher-glue.c @@ -16,7 +16,7 @@ EXPORT_SYMBOL(__aes_arm_encrypt); asmlinkage void __aes_arm_decrypt(u32 *rk, int rounds, const u8 *in, u8 *out); EXPORT_SYMBOL(__aes_arm_decrypt); -static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void aes_arm_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); int rounds = 6 + ctx->key_length / 4; @@ -24,7 +24,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) __aes_arm_encrypt(ctx->key_enc, rounds, in, out); } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void aes_arm_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); int rounds = 6 + ctx->key_length / 4; @@ -44,8 +44,8 @@ static struct crypto_alg aes_alg = { .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, .cra_cipher.cia_setkey = crypto_aes_set_key, - .cra_cipher.cia_encrypt = aes_encrypt, - .cra_cipher.cia_decrypt = aes_decrypt, + .cra_cipher.cia_encrypt = aes_arm_encrypt, + .cra_cipher.cia_decrypt = aes_arm_decrypt, #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS .cra_alignmask = 3, diff --git a/arch/arm64/crypto/aes-cipher-glue.c b/arch/arm64/crypto/aes-cipher-glue.c index 0913966aa6fa..cc7a6dad7c2e 100644 --- a/arch/arm64/crypto/aes-cipher-glue.c +++ b/arch/arm64/crypto/aes-cipher-glue.c @@ -15,7 +15,7 @@ EXPORT_SYMBOL(__aes_arm64_encrypt); asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); EXPORT_SYMBOL(__aes_arm64_decrypt); -static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void aes_arm64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); int rounds = 6 + ctx->key_length / 4; @@ -23,7 +23,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) __aes_arm64_encrypt(ctx->key_enc, out, in, rounds); } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void aes_arm64_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); int rounds = 6 + ctx->key_length / 4; @@ -43,8 +43,8 @@ static struct crypto_alg aes_alg = { .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, .cra_cipher.cia_setkey = crypto_aes_set_key, - .cra_cipher.cia_encrypt = aes_encrypt, - .cra_cipher.cia_decrypt = aes_decrypt + .cra_cipher.cia_encrypt = aes_arm64_encrypt, + .cra_cipher.cia_decrypt = aes_arm64_decrypt }; static int __init aes_init(void) diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 57b474113168..7b946b3dee9d 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -197,14 +197,14 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, return 0; } -static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); ctx->ops->encrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst); } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); @@ -396,8 +396,8 @@ static struct crypto_alg algs[] = { { .cia_min_keysize = AES_MIN_KEY_SIZE, .cia_max_keysize = AES_MAX_KEY_SIZE, .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt + .cia_encrypt = crypto_aes_encrypt, + .cia_decrypt = crypto_aes_decrypt } } }, { diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 73c0ccb009a0..6c1be5b6134a 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -345,7 +345,7 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, return aes_set_key_common(tfm, crypto_tfm_ctx(tfm), in_key, key_len); } -static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void aesni_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); @@ -358,7 +358,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) } } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void aesni_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); @@ -919,8 +919,8 @@ static struct crypto_alg aesni_cipher_alg = { .cia_min_keysize = AES_MIN_KEY_SIZE, .cia_max_keysize = AES_MAX_KEY_SIZE, .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt + .cia_encrypt = aesni_encrypt, + .cia_decrypt = aesni_decrypt } } }; diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c index f217568917e4..3aa4a715c216 100644 --- a/crypto/aes_generic.c +++ b/crypto/aes_generic.c @@ -1332,7 +1332,7 @@ EXPORT_SYMBOL_GPL(crypto_aes_set_key); f_rl(bo, bi, 3, k); \ } while (0) -static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); u32 b0[4], b1[4]; @@ -1402,7 +1402,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) i_rl(bo, bi, 3, k); \ } while (0) -static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); u32 b0[4], b1[4]; @@ -1454,8 +1454,8 @@ static struct crypto_alg aes_alg = { .cia_min_keysize = AES_MIN_KEY_SIZE, .cia_max_keysize = AES_MAX_KEY_SIZE, .cia_setkey = crypto_aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt + .cia_encrypt = crypto_aes_encrypt, + .cia_decrypt = crypto_aes_decrypt } } }; diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index ad020133da19..fbba32e8cb26 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -300,7 +300,7 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, return iv; } -static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void padlock_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); @@ -309,7 +309,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) padlock_store_cword(&ctx->cword.encrypt); } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void padlock_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct aes_ctx *ctx = aes_ctx(tfm); @@ -332,8 +332,8 @@ static struct crypto_alg aes_alg = { .cia_min_keysize = AES_MIN_KEY_SIZE, .cia_max_keysize = AES_MAX_KEY_SIZE, .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt, + .cia_encrypt = padlock_aes_encrypt, + .cia_decrypt = padlock_aes_decrypt, } } }; -- GitLab From b158fcbba857c71ffb05ab254aff3b32b5e3cfc3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:21 +0200 Subject: [PATCH 0771/7155] crypto: aes/fixed-time - align key schedule with other implementations The fixed time AES code mangles the key schedule so that xoring the first round key with values at fixed offsets across the Sbox produces the correct value. This primes the D-cache with the entire Sbox before any data dependent lookups are done, making it more difficult to infer key bits from timing variances when the plaintext is known. The downside of this approach is that it renders the key schedule incompatible with other implementations of AES in the kernel, which makes it cumbersome to use this implementation as a fallback for SIMD based AES in contexts where this is not allowed. So let's tweak the fixed Sbox indexes so that they add up to zero under the xor operation. While at it, increase the granularity to 16 bytes so we cover the entire Sbox even on systems with 16 byte cachelines. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/aes_ti.c | 52 ++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/crypto/aes_ti.c b/crypto/aes_ti.c index 798fc9a2c8d6..b3ebdc5679cb 100644 --- a/crypto/aes_ti.c +++ b/crypto/aes_ti.c @@ -234,30 +234,8 @@ static int aesti_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - int err; - err = aesti_expand_key(ctx, in_key, key_len); - if (err) - return err; - - /* - * In order to force the compiler to emit data independent Sbox lookups - * at the start of each block, xor the first round key with values at - * fixed indexes in the Sbox. This will need to be repeated each time - * the key is used, which will pull the entire Sbox into the D-cache - * before any data dependent Sbox lookups are performed. - */ - ctx->key_enc[0] ^= __aesti_sbox[ 0] ^ __aesti_sbox[128]; - ctx->key_enc[1] ^= __aesti_sbox[32] ^ __aesti_sbox[160]; - ctx->key_enc[2] ^= __aesti_sbox[64] ^ __aesti_sbox[192]; - ctx->key_enc[3] ^= __aesti_sbox[96] ^ __aesti_sbox[224]; - - ctx->key_dec[0] ^= __aesti_inv_sbox[ 0] ^ __aesti_inv_sbox[128]; - ctx->key_dec[1] ^= __aesti_inv_sbox[32] ^ __aesti_inv_sbox[160]; - ctx->key_dec[2] ^= __aesti_inv_sbox[64] ^ __aesti_inv_sbox[192]; - ctx->key_dec[3] ^= __aesti_inv_sbox[96] ^ __aesti_inv_sbox[224]; - - return 0; + return aesti_expand_key(ctx, in_key, key_len); } static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) @@ -280,10 +258,16 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ local_irq_save(flags); - st0[0] ^= __aesti_sbox[ 0] ^ __aesti_sbox[128]; - st0[1] ^= __aesti_sbox[32] ^ __aesti_sbox[160]; - st0[2] ^= __aesti_sbox[64] ^ __aesti_sbox[192]; - st0[3] ^= __aesti_sbox[96] ^ __aesti_sbox[224]; + /* + * Force the compiler to emit data independent Sbox references, + * by xoring the input with Sbox values that are known to add up + * to zero. This pulls the entire Sbox into the D-cache before any + * data dependent lookups are done. + */ + st0[0] ^= __aesti_sbox[ 0] ^ __aesti_sbox[ 64] ^ __aesti_sbox[134] ^ __aesti_sbox[195]; + st0[1] ^= __aesti_sbox[16] ^ __aesti_sbox[ 82] ^ __aesti_sbox[158] ^ __aesti_sbox[221]; + st0[2] ^= __aesti_sbox[32] ^ __aesti_sbox[ 96] ^ __aesti_sbox[160] ^ __aesti_sbox[234]; + st0[3] ^= __aesti_sbox[48] ^ __aesti_sbox[112] ^ __aesti_sbox[186] ^ __aesti_sbox[241]; for (round = 0;; round += 2, rkp += 8) { st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0]; @@ -328,10 +312,16 @@ static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ local_irq_save(flags); - st0[0] ^= __aesti_inv_sbox[ 0] ^ __aesti_inv_sbox[128]; - st0[1] ^= __aesti_inv_sbox[32] ^ __aesti_inv_sbox[160]; - st0[2] ^= __aesti_inv_sbox[64] ^ __aesti_inv_sbox[192]; - st0[3] ^= __aesti_inv_sbox[96] ^ __aesti_inv_sbox[224]; + /* + * Force the compiler to emit data independent Sbox references, + * by xoring the input with Sbox values that are known to add up + * to zero. This pulls the entire Sbox into the D-cache before any + * data dependent lookups are done. + */ + st0[0] ^= __aesti_inv_sbox[ 0] ^ __aesti_inv_sbox[ 64] ^ __aesti_inv_sbox[129] ^ __aesti_inv_sbox[200]; + st0[1] ^= __aesti_inv_sbox[16] ^ __aesti_inv_sbox[ 83] ^ __aesti_inv_sbox[150] ^ __aesti_inv_sbox[212]; + st0[2] ^= __aesti_inv_sbox[32] ^ __aesti_inv_sbox[ 96] ^ __aesti_inv_sbox[160] ^ __aesti_inv_sbox[236]; + st0[3] ^= __aesti_inv_sbox[48] ^ __aesti_inv_sbox[112] ^ __aesti_inv_sbox[187] ^ __aesti_inv_sbox[247]; for (round = 0;; round += 2, rkp += 8) { st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0]; -- GitLab From e59c1c98745637796df824c0177f279b6e9cad94 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:22 +0200 Subject: [PATCH 0772/7155] crypto: aes - create AES library based on the fixed time AES code Take the existing small footprint and mostly time invariant C code and turn it into a AES library that can be used for non-performance critical, casual use of AES, and as a fallback for, e.g., SIMD code that needs a secondary path that can be taken in contexts where the SIMD unit is off limits (e.g., in hard interrupts taken from kernel context) Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 4 + crypto/aes_ti.c | 303 +------------------------------------ include/crypto/aes.h | 34 +++++ lib/crypto/Makefile | 3 + lib/crypto/aes.c | 350 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 394 insertions(+), 300 deletions(-) create mode 100644 lib/crypto/aes.c diff --git a/crypto/Kconfig b/crypto/Kconfig index e801450bcb1c..091ebbbc9655 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1066,6 +1066,9 @@ config CRYPTO_GHASH_CLMUL_NI_INTEL comment "Ciphers" +config CRYPTO_LIB_AES + tristate + config CRYPTO_AES tristate "AES cipher algorithms" select CRYPTO_ALGAPI @@ -1089,6 +1092,7 @@ config CRYPTO_AES config CRYPTO_AES_TI tristate "Fixed time AES cipher" select CRYPTO_ALGAPI + select CRYPTO_LIB_AES help This is a generic implementation of AES that attempts to eliminate data dependent latencies as much as possible without affecting diff --git a/crypto/aes_ti.c b/crypto/aes_ti.c index b3ebdc5679cb..205c2c257d49 100644 --- a/crypto/aes_ti.c +++ b/crypto/aes_ti.c @@ -8,249 +8,19 @@ #include #include #include -#include - -/* - * Emit the sbox as volatile const to prevent the compiler from doing - * constant folding on sbox references involving fixed indexes. - */ -static volatile const u8 __cacheline_aligned __aesti_sbox[] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -}; - -static volatile const u8 __cacheline_aligned __aesti_inv_sbox[] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, - 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, - 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, - 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, - 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, - 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, - 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, - 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, - 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, - 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, - 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, - 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, -}; - -static u32 mul_by_x(u32 w) -{ - u32 x = w & 0x7f7f7f7f; - u32 y = w & 0x80808080; - - /* multiply by polynomial 'x' (0b10) in GF(2^8) */ - return (x << 1) ^ (y >> 7) * 0x1b; -} - -static u32 mul_by_x2(u32 w) -{ - u32 x = w & 0x3f3f3f3f; - u32 y = w & 0x80808080; - u32 z = w & 0x40404040; - - /* multiply by polynomial 'x^2' (0b100) in GF(2^8) */ - return (x << 2) ^ (y >> 7) * 0x36 ^ (z >> 6) * 0x1b; -} - -static u32 mix_columns(u32 x) -{ - /* - * Perform the following matrix multiplication in GF(2^8) - * - * | 0x2 0x3 0x1 0x1 | | x[0] | - * | 0x1 0x2 0x3 0x1 | | x[1] | - * | 0x1 0x1 0x2 0x3 | x | x[2] | - * | 0x3 0x1 0x1 0x2 | | x[3] | - */ - u32 y = mul_by_x(x) ^ ror32(x, 16); - - return y ^ ror32(x ^ y, 8); -} - -static u32 inv_mix_columns(u32 x) -{ - /* - * Perform the following matrix multiplication in GF(2^8) - * - * | 0xe 0xb 0xd 0x9 | | x[0] | - * | 0x9 0xe 0xb 0xd | | x[1] | - * | 0xd 0x9 0xe 0xb | x | x[2] | - * | 0xb 0xd 0x9 0xe | | x[3] | - * - * which can conveniently be reduced to - * - * | 0x2 0x3 0x1 0x1 | | 0x5 0x0 0x4 0x0 | | x[0] | - * | 0x1 0x2 0x3 0x1 | | 0x0 0x5 0x0 0x4 | | x[1] | - * | 0x1 0x1 0x2 0x3 | x | 0x4 0x0 0x5 0x0 | x | x[2] | - * | 0x3 0x1 0x1 0x2 | | 0x0 0x4 0x0 0x5 | | x[3] | - */ - u32 y = mul_by_x2(x); - - return mix_columns(x ^ y ^ ror32(y, 16)); -} - -static __always_inline u32 subshift(u32 in[], int pos) -{ - return (__aesti_sbox[in[pos] & 0xff]) ^ - (__aesti_sbox[(in[(pos + 1) % 4] >> 8) & 0xff] << 8) ^ - (__aesti_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ - (__aesti_sbox[(in[(pos + 3) % 4] >> 24) & 0xff] << 24); -} - -static __always_inline u32 inv_subshift(u32 in[], int pos) -{ - return (__aesti_inv_sbox[in[pos] & 0xff]) ^ - (__aesti_inv_sbox[(in[(pos + 3) % 4] >> 8) & 0xff] << 8) ^ - (__aesti_inv_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ - (__aesti_inv_sbox[(in[(pos + 1) % 4] >> 24) & 0xff] << 24); -} - -static u32 subw(u32 in) -{ - return (__aesti_sbox[in & 0xff]) ^ - (__aesti_sbox[(in >> 8) & 0xff] << 8) ^ - (__aesti_sbox[(in >> 16) & 0xff] << 16) ^ - (__aesti_sbox[(in >> 24) & 0xff] << 24); -} - -static int aesti_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len) -{ - u32 kwords = key_len / sizeof(u32); - u32 rc, i, j; - - if (key_len != AES_KEYSIZE_128 && - key_len != AES_KEYSIZE_192 && - key_len != AES_KEYSIZE_256) - return -EINVAL; - - ctx->key_length = key_len; - - for (i = 0; i < kwords; i++) - ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32)); - - for (i = 0, rc = 1; i < 10; i++, rc = mul_by_x(rc)) { - u32 *rki = ctx->key_enc + (i * kwords); - u32 *rko = rki + kwords; - - rko[0] = ror32(subw(rki[kwords - 1]), 8) ^ rc ^ rki[0]; - rko[1] = rko[0] ^ rki[1]; - rko[2] = rko[1] ^ rki[2]; - rko[3] = rko[2] ^ rki[3]; - - if (key_len == 24) { - if (i >= 7) - break; - rko[4] = rko[3] ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - } else if (key_len == 32) { - if (i >= 6) - break; - rko[4] = subw(rko[3]) ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - rko[6] = rko[5] ^ rki[6]; - rko[7] = rko[6] ^ rki[7]; - } - } - - /* - * Generate the decryption keys for the Equivalent Inverse Cipher. - * This involves reversing the order of the round keys, and applying - * the Inverse Mix Columns transformation to all but the first and - * the last one. - */ - ctx->key_dec[0] = ctx->key_enc[key_len + 24]; - ctx->key_dec[1] = ctx->key_enc[key_len + 25]; - ctx->key_dec[2] = ctx->key_enc[key_len + 26]; - ctx->key_dec[3] = ctx->key_enc[key_len + 27]; - - for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) { - ctx->key_dec[i] = inv_mix_columns(ctx->key_enc[j]); - ctx->key_dec[i + 1] = inv_mix_columns(ctx->key_enc[j + 1]); - ctx->key_dec[i + 2] = inv_mix_columns(ctx->key_enc[j + 2]); - ctx->key_dec[i + 3] = inv_mix_columns(ctx->key_enc[j + 3]); - } - - ctx->key_dec[i] = ctx->key_enc[0]; - ctx->key_dec[i + 1] = ctx->key_enc[1]; - ctx->key_dec[i + 2] = ctx->key_enc[2]; - ctx->key_dec[i + 3] = ctx->key_enc[3]; - - return 0; -} static int aesti_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - return aesti_expand_key(ctx, in_key, key_len); + return aes_expandkey(ctx, in_key, key_len); } static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - const u32 *rkp = ctx->key_enc + 4; - int rounds = 6 + ctx->key_length / 4; - u32 st0[4], st1[4]; unsigned long flags; - int round; - - st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in); - st0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4); - st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8); - st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12); /* * Temporarily disable interrupts to avoid races where cachelines are @@ -258,36 +28,7 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ local_irq_save(flags); - /* - * Force the compiler to emit data independent Sbox references, - * by xoring the input with Sbox values that are known to add up - * to zero. This pulls the entire Sbox into the D-cache before any - * data dependent lookups are done. - */ - st0[0] ^= __aesti_sbox[ 0] ^ __aesti_sbox[ 64] ^ __aesti_sbox[134] ^ __aesti_sbox[195]; - st0[1] ^= __aesti_sbox[16] ^ __aesti_sbox[ 82] ^ __aesti_sbox[158] ^ __aesti_sbox[221]; - st0[2] ^= __aesti_sbox[32] ^ __aesti_sbox[ 96] ^ __aesti_sbox[160] ^ __aesti_sbox[234]; - st0[3] ^= __aesti_sbox[48] ^ __aesti_sbox[112] ^ __aesti_sbox[186] ^ __aesti_sbox[241]; - - for (round = 0;; round += 2, rkp += 8) { - st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0]; - st1[1] = mix_columns(subshift(st0, 1)) ^ rkp[1]; - st1[2] = mix_columns(subshift(st0, 2)) ^ rkp[2]; - st1[3] = mix_columns(subshift(st0, 3)) ^ rkp[3]; - - if (round == rounds - 2) - break; - - st0[0] = mix_columns(subshift(st1, 0)) ^ rkp[4]; - st0[1] = mix_columns(subshift(st1, 1)) ^ rkp[5]; - st0[2] = mix_columns(subshift(st1, 2)) ^ rkp[6]; - st0[3] = mix_columns(subshift(st1, 3)) ^ rkp[7]; - } - - put_unaligned_le32(subshift(st1, 0) ^ rkp[4], out); - put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4); - put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8); - put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12); + aes_encrypt(ctx, out, in); local_irq_restore(flags); } @@ -295,16 +36,7 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - const u32 *rkp = ctx->key_dec + 4; - int rounds = 6 + ctx->key_length / 4; - u32 st0[4], st1[4]; unsigned long flags; - int round; - - st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in); - st0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4); - st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8); - st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12); /* * Temporarily disable interrupts to avoid races where cachelines are @@ -312,36 +44,7 @@ static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ local_irq_save(flags); - /* - * Force the compiler to emit data independent Sbox references, - * by xoring the input with Sbox values that are known to add up - * to zero. This pulls the entire Sbox into the D-cache before any - * data dependent lookups are done. - */ - st0[0] ^= __aesti_inv_sbox[ 0] ^ __aesti_inv_sbox[ 64] ^ __aesti_inv_sbox[129] ^ __aesti_inv_sbox[200]; - st0[1] ^= __aesti_inv_sbox[16] ^ __aesti_inv_sbox[ 83] ^ __aesti_inv_sbox[150] ^ __aesti_inv_sbox[212]; - st0[2] ^= __aesti_inv_sbox[32] ^ __aesti_inv_sbox[ 96] ^ __aesti_inv_sbox[160] ^ __aesti_inv_sbox[236]; - st0[3] ^= __aesti_inv_sbox[48] ^ __aesti_inv_sbox[112] ^ __aesti_inv_sbox[187] ^ __aesti_inv_sbox[247]; - - for (round = 0;; round += 2, rkp += 8) { - st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0]; - st1[1] = inv_mix_columns(inv_subshift(st0, 1)) ^ rkp[1]; - st1[2] = inv_mix_columns(inv_subshift(st0, 2)) ^ rkp[2]; - st1[3] = inv_mix_columns(inv_subshift(st0, 3)) ^ rkp[3]; - - if (round == rounds - 2) - break; - - st0[0] = inv_mix_columns(inv_subshift(st1, 0)) ^ rkp[4]; - st0[1] = inv_mix_columns(inv_subshift(st1, 1)) ^ rkp[5]; - st0[2] = inv_mix_columns(inv_subshift(st1, 2)) ^ rkp[6]; - st0[3] = inv_mix_columns(inv_subshift(st1, 3)) ^ rkp[7]; - } - - put_unaligned_le32(inv_subshift(st1, 0) ^ rkp[4], out); - put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4); - put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8); - put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12); + aes_decrypt(ctx, out, in); local_irq_restore(flags); } diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 0fdb542c70cd..d0067fca0cd0 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -37,4 +37,38 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len); int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); + +/** + * aes_expandkey - Expands the AES key as described in FIPS-197 + * @ctx: The location where the computed key will be stored. + * @in_key: The supplied key. + * @key_len: The length of the supplied key. + * + * Returns 0 on success. The function fails only if an invalid key size (or + * pointer) is supplied. + * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes + * key schedule plus a 16 bytes key which is used before the first round). + * The decryption key is prepared for the "Equivalent Inverse Cipher" as + * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is + * for the initial combination, the second slot for the first round and so on. + */ +int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, + unsigned int key_len); + +/** + * aes_encrypt - Encrypt a single AES block + * @ctx: Context struct containing the key schedule + * @out: Buffer to store the ciphertext + * @in: Buffer containing the plaintext + */ +void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); + +/** + * aes_decrypt - Decrypt a single AES block + * @ctx: Context struct containing the key schedule + * @out: Buffer to store the plaintext + * @in: Buffer containing the ciphertext + */ +void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); + #endif diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 88195c34932d..42a91c62d96d 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o +libaes-y := aes.o + obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o libarc4-y := arc4.o diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c new file mode 100644 index 000000000000..9928b23e0a8a --- /dev/null +++ b/lib/crypto/aes.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017-2019 Linaro Ltd + */ + +#include +#include +#include +#include + +/* + * Emit the sbox as volatile const to prevent the compiler from doing + * constant folding on sbox references involving fixed indexes. + */ +static volatile const u8 __cacheline_aligned aes_sbox[] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +}; + +static volatile const u8 __cacheline_aligned aes_inv_sbox[] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, + 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, + 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, + 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, + 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, + 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, + 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, + 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, + 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, + 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, + 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, + 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +}; + +static u32 mul_by_x(u32 w) +{ + u32 x = w & 0x7f7f7f7f; + u32 y = w & 0x80808080; + + /* multiply by polynomial 'x' (0b10) in GF(2^8) */ + return (x << 1) ^ (y >> 7) * 0x1b; +} + +static u32 mul_by_x2(u32 w) +{ + u32 x = w & 0x3f3f3f3f; + u32 y = w & 0x80808080; + u32 z = w & 0x40404040; + + /* multiply by polynomial 'x^2' (0b100) in GF(2^8) */ + return (x << 2) ^ (y >> 7) * 0x36 ^ (z >> 6) * 0x1b; +} + +static u32 mix_columns(u32 x) +{ + /* + * Perform the following matrix multiplication in GF(2^8) + * + * | 0x2 0x3 0x1 0x1 | | x[0] | + * | 0x1 0x2 0x3 0x1 | | x[1] | + * | 0x1 0x1 0x2 0x3 | x | x[2] | + * | 0x3 0x1 0x1 0x2 | | x[3] | + */ + u32 y = mul_by_x(x) ^ ror32(x, 16); + + return y ^ ror32(x ^ y, 8); +} + +static u32 inv_mix_columns(u32 x) +{ + /* + * Perform the following matrix multiplication in GF(2^8) + * + * | 0xe 0xb 0xd 0x9 | | x[0] | + * | 0x9 0xe 0xb 0xd | | x[1] | + * | 0xd 0x9 0xe 0xb | x | x[2] | + * | 0xb 0xd 0x9 0xe | | x[3] | + * + * which can conveniently be reduced to + * + * | 0x2 0x3 0x1 0x1 | | 0x5 0x0 0x4 0x0 | | x[0] | + * | 0x1 0x2 0x3 0x1 | | 0x0 0x5 0x0 0x4 | | x[1] | + * | 0x1 0x1 0x2 0x3 | x | 0x4 0x0 0x5 0x0 | x | x[2] | + * | 0x3 0x1 0x1 0x2 | | 0x0 0x4 0x0 0x5 | | x[3] | + */ + u32 y = mul_by_x2(x); + + return mix_columns(x ^ y ^ ror32(y, 16)); +} + +static __always_inline u32 subshift(u32 in[], int pos) +{ + return (aes_sbox[in[pos] & 0xff]) ^ + (aes_sbox[(in[(pos + 1) % 4] >> 8) & 0xff] << 8) ^ + (aes_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ + (aes_sbox[(in[(pos + 3) % 4] >> 24) & 0xff] << 24); +} + +static __always_inline u32 inv_subshift(u32 in[], int pos) +{ + return (aes_inv_sbox[in[pos] & 0xff]) ^ + (aes_inv_sbox[(in[(pos + 3) % 4] >> 8) & 0xff] << 8) ^ + (aes_inv_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ + (aes_inv_sbox[(in[(pos + 1) % 4] >> 24) & 0xff] << 24); +} + +static u32 subw(u32 in) +{ + return (aes_sbox[in & 0xff]) ^ + (aes_sbox[(in >> 8) & 0xff] << 8) ^ + (aes_sbox[(in >> 16) & 0xff] << 16) ^ + (aes_sbox[(in >> 24) & 0xff] << 24); +} + +/** + * aes_expandkey - Expands the AES key as described in FIPS-197 + * @ctx: The location where the computed key will be stored. + * @in_key: The supplied key. + * @key_len: The length of the supplied key. + * + * Returns 0 on success. The function fails only if an invalid key size (or + * pointer) is supplied. + * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes + * key schedule plus a 16 bytes key which is used before the first round). + * The decryption key is prepared for the "Equivalent Inverse Cipher" as + * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is + * for the initial combination, the second slot for the first round and so on. + */ +int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, + unsigned int key_len) +{ + u32 kwords = key_len / sizeof(u32); + u32 rc, i, j; + + if (key_len != AES_KEYSIZE_128 && + key_len != AES_KEYSIZE_192 && + key_len != AES_KEYSIZE_256) + return -EINVAL; + + ctx->key_length = key_len; + + for (i = 0; i < kwords; i++) + ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32)); + + for (i = 0, rc = 1; i < 10; i++, rc = mul_by_x(rc)) { + u32 *rki = ctx->key_enc + (i * kwords); + u32 *rko = rki + kwords; + + rko[0] = ror32(subw(rki[kwords - 1]), 8) ^ rc ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + + if (key_len == AES_KEYSIZE_192) { + if (i >= 7) + break; + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + } else if (key_len == AES_KEYSIZE_256) { + if (i >= 6) + break; + rko[4] = subw(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + } + } + + /* + * Generate the decryption keys for the Equivalent Inverse Cipher. + * This involves reversing the order of the round keys, and applying + * the Inverse Mix Columns transformation to all but the first and + * the last one. + */ + ctx->key_dec[0] = ctx->key_enc[key_len + 24]; + ctx->key_dec[1] = ctx->key_enc[key_len + 25]; + ctx->key_dec[2] = ctx->key_enc[key_len + 26]; + ctx->key_dec[3] = ctx->key_enc[key_len + 27]; + + for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) { + ctx->key_dec[i] = inv_mix_columns(ctx->key_enc[j]); + ctx->key_dec[i + 1] = inv_mix_columns(ctx->key_enc[j + 1]); + ctx->key_dec[i + 2] = inv_mix_columns(ctx->key_enc[j + 2]); + ctx->key_dec[i + 3] = inv_mix_columns(ctx->key_enc[j + 3]); + } + + ctx->key_dec[i] = ctx->key_enc[0]; + ctx->key_dec[i + 1] = ctx->key_enc[1]; + ctx->key_dec[i + 2] = ctx->key_enc[2]; + ctx->key_dec[i + 3] = ctx->key_enc[3]; + + return 0; +} +EXPORT_SYMBOL(aes_expandkey); + +/** + * aes_encrypt - Encrypt a single AES block + * @ctx: Context struct containing the key schedule + * @out: Buffer to store the ciphertext + * @in: Buffer containing the plaintext + */ +void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) +{ + const u32 *rkp = ctx->key_enc + 4; + int rounds = 6 + ctx->key_length / 4; + u32 st0[4], st1[4]; + int round; + + st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in); + st0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4); + st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8); + st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12); + + /* + * Force the compiler to emit data independent Sbox references, + * by xoring the input with Sbox values that are known to add up + * to zero. This pulls the entire Sbox into the D-cache before any + * data dependent lookups are done. + */ + st0[0] ^= aes_sbox[ 0] ^ aes_sbox[ 64] ^ aes_sbox[134] ^ aes_sbox[195]; + st0[1] ^= aes_sbox[16] ^ aes_sbox[ 82] ^ aes_sbox[158] ^ aes_sbox[221]; + st0[2] ^= aes_sbox[32] ^ aes_sbox[ 96] ^ aes_sbox[160] ^ aes_sbox[234]; + st0[3] ^= aes_sbox[48] ^ aes_sbox[112] ^ aes_sbox[186] ^ aes_sbox[241]; + + for (round = 0;; round += 2, rkp += 8) { + st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0]; + st1[1] = mix_columns(subshift(st0, 1)) ^ rkp[1]; + st1[2] = mix_columns(subshift(st0, 2)) ^ rkp[2]; + st1[3] = mix_columns(subshift(st0, 3)) ^ rkp[3]; + + if (round == rounds - 2) + break; + + st0[0] = mix_columns(subshift(st1, 0)) ^ rkp[4]; + st0[1] = mix_columns(subshift(st1, 1)) ^ rkp[5]; + st0[2] = mix_columns(subshift(st1, 2)) ^ rkp[6]; + st0[3] = mix_columns(subshift(st1, 3)) ^ rkp[7]; + } + + put_unaligned_le32(subshift(st1, 0) ^ rkp[4], out); + put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4); + put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8); + put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12); +} +EXPORT_SYMBOL(aes_encrypt); + +/** + * aes_decrypt - Decrypt a single AES block + * @ctx: Context struct containing the key schedule + * @out: Buffer to store the plaintext + * @in: Buffer containing the ciphertext + */ +void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) +{ + const u32 *rkp = ctx->key_dec + 4; + int rounds = 6 + ctx->key_length / 4; + u32 st0[4], st1[4]; + int round; + + st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in); + st0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4); + st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8); + st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12); + + /* + * Force the compiler to emit data independent Sbox references, + * by xoring the input with Sbox values that are known to add up + * to zero. This pulls the entire Sbox into the D-cache before any + * data dependent lookups are done. + */ + st0[0] ^= aes_inv_sbox[ 0] ^ aes_inv_sbox[ 64] ^ aes_inv_sbox[129] ^ aes_inv_sbox[200]; + st0[1] ^= aes_inv_sbox[16] ^ aes_inv_sbox[ 83] ^ aes_inv_sbox[150] ^ aes_inv_sbox[212]; + st0[2] ^= aes_inv_sbox[32] ^ aes_inv_sbox[ 96] ^ aes_inv_sbox[160] ^ aes_inv_sbox[236]; + st0[3] ^= aes_inv_sbox[48] ^ aes_inv_sbox[112] ^ aes_inv_sbox[187] ^ aes_inv_sbox[247]; + + for (round = 0;; round += 2, rkp += 8) { + st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0]; + st1[1] = inv_mix_columns(inv_subshift(st0, 1)) ^ rkp[1]; + st1[2] = inv_mix_columns(inv_subshift(st0, 2)) ^ rkp[2]; + st1[3] = inv_mix_columns(inv_subshift(st0, 3)) ^ rkp[3]; + + if (round == rounds - 2) + break; + + st0[0] = inv_mix_columns(inv_subshift(st1, 0)) ^ rkp[4]; + st0[1] = inv_mix_columns(inv_subshift(st1, 1)) ^ rkp[5]; + st0[2] = inv_mix_columns(inv_subshift(st1, 2)) ^ rkp[6]; + st0[3] = inv_mix_columns(inv_subshift(st1, 3)) ^ rkp[7]; + } + + put_unaligned_le32(inv_subshift(st1, 0) ^ rkp[4], out); + put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4); + put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8); + put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12); +} +EXPORT_SYMBOL(aes_decrypt); + +MODULE_DESCRIPTION("Generic AES library"); +MODULE_AUTHOR("Ard Biesheuvel "); +MODULE_LICENSE("GPL v2"); -- GitLab From 2c53fd11f7624658222d175ec27e6c07b20b63d0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:23 +0200 Subject: [PATCH 0773/7155] crypto: x86/aes-ni - switch to generic for fallback and key routines The AES-NI code contains fallbacks for invocations that occur from a context where the SIMD unit is unavailable, which really only occurs when running in softirq context that was entered from a hard IRQ that was taken while running kernel code that was already using the FPU. That means performance is not really a consideration, and we can just use the new library code for this use case, which has a smaller footprint and is believed to be time invariant. This will allow us to drop the non-SIMD asm routines in a subsequent patch. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/aesni-intel_glue.c | 15 +++++++-------- arch/x86/include/asm/crypto/aes.h | 12 ------------ crypto/Kconfig | 3 +-- 3 files changed, 8 insertions(+), 22 deletions(-) delete mode 100644 arch/x86/include/asm/crypto/aes.h diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 6c1be5b6134a..ef165d8cf443 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -329,7 +328,7 @@ static int aes_set_key_common(struct crypto_tfm *tfm, void *raw_ctx, } if (!crypto_simd_usable()) - err = crypto_aes_expand_key(ctx, in_key, key_len); + err = aes_expandkey(ctx, in_key, key_len); else { kernel_fpu_begin(); err = aesni_set_key(ctx, in_key, key_len); @@ -349,9 +348,9 @@ static void aesni_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); - if (!crypto_simd_usable()) - crypto_aes_encrypt_x86(ctx, dst, src); - else { + if (!crypto_simd_usable()) { + aes_encrypt(ctx, dst, src); + } else { kernel_fpu_begin(); aesni_enc(ctx, dst, src); kernel_fpu_end(); @@ -362,9 +361,9 @@ static void aesni_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); - if (!crypto_simd_usable()) - crypto_aes_decrypt_x86(ctx, dst, src); - else { + if (!crypto_simd_usable()) { + aes_decrypt(ctx, dst, src); + } else { kernel_fpu_begin(); aesni_dec(ctx, dst, src); kernel_fpu_end(); diff --git a/arch/x86/include/asm/crypto/aes.h b/arch/x86/include/asm/crypto/aes.h deleted file mode 100644 index c508521dd190..000000000000 --- a/arch/x86/include/asm/crypto/aes.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef ASM_X86_AES_H -#define ASM_X86_AES_H - -#include -#include - -void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, - const u8 *src); -void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, - const u8 *src); -#endif diff --git a/crypto/Kconfig b/crypto/Kconfig index 091ebbbc9655..20af58068e6b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1156,8 +1156,7 @@ config CRYPTO_AES_NI_INTEL tristate "AES cipher algorithms (AES-NI)" depends on X86 select CRYPTO_AEAD - select CRYPTO_AES_X86_64 if 64BIT - select CRYPTO_AES_586 if !64BIT + select CRYPTO_LIB_AES select CRYPTO_ALGAPI select CRYPTO_BLKCIPHER select CRYPTO_GLUE_HELPER_X86 if 64BIT -- GitLab From 1d2c3279311e4f03fcf164e1366f2fda9f4bfccf Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:24 +0200 Subject: [PATCH 0774/7155] crypto: x86/aes - drop scalar assembler implementations The AES assembler code for x86 isn't actually faster than code generated by the compiler from aes_generic.c, and considering the disproportionate maintenance burden of assembler code on x86, it is better just to drop it entirely. Modern x86 systems will use AES-NI anyway, and given that the modules being removed have a dependency on aes_generic already, we can remove them without running the risk of regressions. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 4 - arch/x86/crypto/aes-i586-asm_32.S | 362 ---------------------------- arch/x86/crypto/aes-x86_64-asm_64.S | 185 -------------- arch/x86/crypto/aes_glue.c | 70 ------ crypto/Kconfig | 44 ---- 5 files changed, 665 deletions(-) delete mode 100644 arch/x86/crypto/aes-i586-asm_32.S delete mode 100644 arch/x86/crypto/aes-x86_64-asm_64.S diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 45734e1cf967..b96a14e67ab0 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -14,11 +14,9 @@ sha256_ni_supported :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,yes,no) obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o -obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o -obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o obj-$(CONFIG_CRYPTO_DES3_EDE_X86_64) += des3_ede-x86_64.o obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o @@ -68,11 +66,9 @@ ifeq ($(avx2_supported),yes) obj-$(CONFIG_CRYPTO_MORUS1280_AVX2) += morus1280-avx2.o endif -aes-i586-y := aes-i586-asm_32.o aes_glue.o twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o -aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o des3_ede-x86_64-y := des3_ede-asm_64.o des3_ede_glue.o camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S deleted file mode 100644 index 2849dbc59e11..000000000000 --- a/arch/x86/crypto/aes-i586-asm_32.S +++ /dev/null @@ -1,362 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (c) 2001, Dr Brian Gladman < >, Worcester, UK. -// All rights reserved. -// -// LICENSE TERMS -// -// The free distribution and use of this software in both source and binary -// form is allowed (with or without changes) provided that: -// -// 1. distributions of this source code include the above copyright -// notice, this list of conditions and the following disclaimer// -// -// 2. distributions in binary form include the above copyright -// notice, this list of conditions and the following disclaimer -// in the documentation and/or other associated materials// -// -// 3. the copyright holder's name is not used to endorse products -// built using this software without specific written permission. -// -// -// ALTERNATIVELY, provided that this notice is retained in full, this product -// may be distributed under the terms of the GNU General Public License (GPL), -// in which case the provisions of the GPL apply INSTEAD OF those given above. -// -// Copyright (c) 2004 Linus Torvalds -// Copyright (c) 2004 Red Hat, Inc., James Morris - -// DISCLAIMER -// -// This software is provided 'as is' with no explicit or implied warranties -// in respect of its properties including, but not limited to, correctness -// and fitness for purpose. -// ------------------------------------------------------------------------- -// Issue Date: 29/07/2002 - -.file "aes-i586-asm.S" -.text - -#include -#include - -#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) - -/* offsets to parameters with one register pushed onto stack */ -#define ctx 8 -#define out_blk 12 -#define in_blk 16 - -/* offsets in crypto_aes_ctx structure */ -#define klen (480) -#define ekey (0) -#define dkey (240) - -// register mapping for encrypt and decrypt subroutines - -#define r0 eax -#define r1 ebx -#define r2 ecx -#define r3 edx -#define r4 esi -#define r5 edi - -#define eaxl al -#define eaxh ah -#define ebxl bl -#define ebxh bh -#define ecxl cl -#define ecxh ch -#define edxl dl -#define edxh dh - -#define _h(reg) reg##h -#define h(reg) _h(reg) - -#define _l(reg) reg##l -#define l(reg) _l(reg) - -// This macro takes a 32-bit word representing a column and uses -// each of its four bytes to index into four tables of 256 32-bit -// words to obtain values that are then xored into the appropriate -// output registers r0, r1, r4 or r5. - -// Parameters: -// table table base address -// %1 out_state[0] -// %2 out_state[1] -// %3 out_state[2] -// %4 out_state[3] -// idx input register for the round (destroyed) -// tmp scratch register for the round -// sched key schedule - -#define do_col(table, a1,a2,a3,a4, idx, tmp) \ - movzx %l(idx),%tmp; \ - xor table(,%tmp,4),%a1; \ - movzx %h(idx),%tmp; \ - shr $16,%idx; \ - xor table+tlen(,%tmp,4),%a2; \ - movzx %l(idx),%tmp; \ - movzx %h(idx),%idx; \ - xor table+2*tlen(,%tmp,4),%a3; \ - xor table+3*tlen(,%idx,4),%a4; - -// initialise output registers from the key schedule -// NB1: original value of a3 is in idx on exit -// NB2: original values of a1,a2,a4 aren't used -#define do_fcol(table, a1,a2,a3,a4, idx, tmp, sched) \ - mov 0 sched,%a1; \ - movzx %l(idx),%tmp; \ - mov 12 sched,%a2; \ - xor table(,%tmp,4),%a1; \ - mov 4 sched,%a4; \ - movzx %h(idx),%tmp; \ - shr $16,%idx; \ - xor table+tlen(,%tmp,4),%a2; \ - movzx %l(idx),%tmp; \ - movzx %h(idx),%idx; \ - xor table+3*tlen(,%idx,4),%a4; \ - mov %a3,%idx; \ - mov 8 sched,%a3; \ - xor table+2*tlen(,%tmp,4),%a3; - -// initialise output registers from the key schedule -// NB1: original value of a3 is in idx on exit -// NB2: original values of a1,a2,a4 aren't used -#define do_icol(table, a1,a2,a3,a4, idx, tmp, sched) \ - mov 0 sched,%a1; \ - movzx %l(idx),%tmp; \ - mov 4 sched,%a2; \ - xor table(,%tmp,4),%a1; \ - mov 12 sched,%a4; \ - movzx %h(idx),%tmp; \ - shr $16,%idx; \ - xor table+tlen(,%tmp,4),%a2; \ - movzx %l(idx),%tmp; \ - movzx %h(idx),%idx; \ - xor table+3*tlen(,%idx,4),%a4; \ - mov %a3,%idx; \ - mov 8 sched,%a3; \ - xor table+2*tlen(,%tmp,4),%a3; - - -// original Gladman had conditional saves to MMX regs. -#define save(a1, a2) \ - mov %a2,4*a1(%esp) - -#define restore(a1, a2) \ - mov 4*a2(%esp),%a1 - -// These macros perform a forward encryption cycle. They are entered with -// the first previous round column values in r0,r1,r4,r5 and -// exit with the final values in the same registers, using stack -// for temporary storage. - -// round column values -// on entry: r0,r1,r4,r5 -// on exit: r2,r1,r4,r5 -#define fwd_rnd1(arg, table) \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_fcol(table, r2,r5,r4,r1, r0,r3, arg); /* idx=r0 */ \ - do_col (table, r4,r1,r2,r5, r0,r3); /* idx=r4 */ \ - restore(r0,0); \ - do_col (table, r1,r2,r5,r4, r0,r3); /* idx=r1 */ \ - restore(r0,1); \ - do_col (table, r5,r4,r1,r2, r0,r3); /* idx=r5 */ - -// round column values -// on entry: r2,r1,r4,r5 -// on exit: r0,r1,r4,r5 -#define fwd_rnd2(arg, table) \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_fcol(table, r0,r5,r4,r1, r2,r3, arg); /* idx=r2 */ \ - do_col (table, r4,r1,r0,r5, r2,r3); /* idx=r4 */ \ - restore(r2,0); \ - do_col (table, r1,r0,r5,r4, r2,r3); /* idx=r1 */ \ - restore(r2,1); \ - do_col (table, r5,r4,r1,r0, r2,r3); /* idx=r5 */ - -// These macros performs an inverse encryption cycle. They are entered with -// the first previous round column values in r0,r1,r4,r5 and -// exit with the final values in the same registers, using stack -// for temporary storage - -// round column values -// on entry: r0,r1,r4,r5 -// on exit: r2,r1,r4,r5 -#define inv_rnd1(arg, table) \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_icol(table, r2,r1,r4,r5, r0,r3, arg); /* idx=r0 */ \ - do_col (table, r4,r5,r2,r1, r0,r3); /* idx=r4 */ \ - restore(r0,0); \ - do_col (table, r1,r4,r5,r2, r0,r3); /* idx=r1 */ \ - restore(r0,1); \ - do_col (table, r5,r2,r1,r4, r0,r3); /* idx=r5 */ - -// round column values -// on entry: r2,r1,r4,r5 -// on exit: r0,r1,r4,r5 -#define inv_rnd2(arg, table) \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_icol(table, r0,r1,r4,r5, r2,r3, arg); /* idx=r2 */ \ - do_col (table, r4,r5,r0,r1, r2,r3); /* idx=r4 */ \ - restore(r2,0); \ - do_col (table, r1,r4,r5,r0, r2,r3); /* idx=r1 */ \ - restore(r2,1); \ - do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */ - -// AES (Rijndael) Encryption Subroutine -/* void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out_blk, const u8 *in_blk) */ - -.extern crypto_ft_tab -.extern crypto_fl_tab - -ENTRY(aes_enc_blk) - push %ebp - mov ctx(%esp),%ebp - -// CAUTION: the order and the values used in these assigns -// rely on the register mappings - -1: push %ebx - mov in_blk+4(%esp),%r2 - push %esi - mov klen(%ebp),%r3 // key size - push %edi -#if ekey != 0 - lea ekey(%ebp),%ebp // key pointer -#endif - -// input four columns and xor in first round key - - mov (%r2),%r0 - mov 4(%r2),%r1 - mov 8(%r2),%r4 - mov 12(%r2),%r5 - xor (%ebp),%r0 - xor 4(%ebp),%r1 - xor 8(%ebp),%r4 - xor 12(%ebp),%r5 - - sub $8,%esp // space for register saves on stack - add $16,%ebp // increment to next round key - cmp $24,%r3 - jb 4f // 10 rounds for 128-bit key - lea 32(%ebp),%ebp - je 3f // 12 rounds for 192-bit key - lea 32(%ebp),%ebp - -2: fwd_rnd1( -64(%ebp), crypto_ft_tab) // 14 rounds for 256-bit key - fwd_rnd2( -48(%ebp), crypto_ft_tab) -3: fwd_rnd1( -32(%ebp), crypto_ft_tab) // 12 rounds for 192-bit key - fwd_rnd2( -16(%ebp), crypto_ft_tab) -4: fwd_rnd1( (%ebp), crypto_ft_tab) // 10 rounds for 128-bit key - fwd_rnd2( +16(%ebp), crypto_ft_tab) - fwd_rnd1( +32(%ebp), crypto_ft_tab) - fwd_rnd2( +48(%ebp), crypto_ft_tab) - fwd_rnd1( +64(%ebp), crypto_ft_tab) - fwd_rnd2( +80(%ebp), crypto_ft_tab) - fwd_rnd1( +96(%ebp), crypto_ft_tab) - fwd_rnd2(+112(%ebp), crypto_ft_tab) - fwd_rnd1(+128(%ebp), crypto_ft_tab) - fwd_rnd2(+144(%ebp), crypto_fl_tab) // last round uses a different table - -// move final values to the output array. CAUTION: the -// order of these assigns rely on the register mappings - - add $8,%esp - mov out_blk+12(%esp),%ebp - mov %r5,12(%ebp) - pop %edi - mov %r4,8(%ebp) - pop %esi - mov %r1,4(%ebp) - pop %ebx - mov %r0,(%ebp) - pop %ebp - ret -ENDPROC(aes_enc_blk) - -// AES (Rijndael) Decryption Subroutine -/* void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out_blk, const u8 *in_blk) */ - -.extern crypto_it_tab -.extern crypto_il_tab - -ENTRY(aes_dec_blk) - push %ebp - mov ctx(%esp),%ebp - -// CAUTION: the order and the values used in these assigns -// rely on the register mappings - -1: push %ebx - mov in_blk+4(%esp),%r2 - push %esi - mov klen(%ebp),%r3 // key size - push %edi -#if dkey != 0 - lea dkey(%ebp),%ebp // key pointer -#endif - -// input four columns and xor in first round key - - mov (%r2),%r0 - mov 4(%r2),%r1 - mov 8(%r2),%r4 - mov 12(%r2),%r5 - xor (%ebp),%r0 - xor 4(%ebp),%r1 - xor 8(%ebp),%r4 - xor 12(%ebp),%r5 - - sub $8,%esp // space for register saves on stack - add $16,%ebp // increment to next round key - cmp $24,%r3 - jb 4f // 10 rounds for 128-bit key - lea 32(%ebp),%ebp - je 3f // 12 rounds for 192-bit key - lea 32(%ebp),%ebp - -2: inv_rnd1( -64(%ebp), crypto_it_tab) // 14 rounds for 256-bit key - inv_rnd2( -48(%ebp), crypto_it_tab) -3: inv_rnd1( -32(%ebp), crypto_it_tab) // 12 rounds for 192-bit key - inv_rnd2( -16(%ebp), crypto_it_tab) -4: inv_rnd1( (%ebp), crypto_it_tab) // 10 rounds for 128-bit key - inv_rnd2( +16(%ebp), crypto_it_tab) - inv_rnd1( +32(%ebp), crypto_it_tab) - inv_rnd2( +48(%ebp), crypto_it_tab) - inv_rnd1( +64(%ebp), crypto_it_tab) - inv_rnd2( +80(%ebp), crypto_it_tab) - inv_rnd1( +96(%ebp), crypto_it_tab) - inv_rnd2(+112(%ebp), crypto_it_tab) - inv_rnd1(+128(%ebp), crypto_it_tab) - inv_rnd2(+144(%ebp), crypto_il_tab) // last round uses a different table - -// move final values to the output array. CAUTION: the -// order of these assigns rely on the register mappings - - add $8,%esp - mov out_blk+12(%esp),%ebp - mov %r5,12(%ebp) - pop %edi - mov %r4,8(%ebp) - pop %esi - mov %r1,4(%ebp) - pop %ebx - mov %r0,(%ebp) - pop %ebp - ret -ENDPROC(aes_dec_blk) diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S deleted file mode 100644 index 8739cf7795de..000000000000 --- a/arch/x86/crypto/aes-x86_64-asm_64.S +++ /dev/null @@ -1,185 +0,0 @@ -/* AES (Rijndael) implementation (FIPS PUB 197) for x86_64 - * - * Copyright (C) 2005 Andreas Steinmetz, - * - * License: - * This code can be distributed under the terms of the GNU General Public - * License (GPL) Version 2 provided that the above header down to and - * including this sentence is retained in full. - */ - -.extern crypto_ft_tab -.extern crypto_it_tab -.extern crypto_fl_tab -.extern crypto_il_tab - -.text - -#include -#include - -#define R1 %rax -#define R1E %eax -#define R1X %ax -#define R1H %ah -#define R1L %al -#define R2 %rbx -#define R2E %ebx -#define R2X %bx -#define R2H %bh -#define R2L %bl -#define R3 %rcx -#define R3E %ecx -#define R3X %cx -#define R3H %ch -#define R3L %cl -#define R4 %rdx -#define R4E %edx -#define R4X %dx -#define R4H %dh -#define R4L %dl -#define R5 %rsi -#define R5E %esi -#define R6 %rdi -#define R6E %edi -#define R7 %r9 /* don't use %rbp; it breaks stack traces */ -#define R7E %r9d -#define R8 %r8 -#define R10 %r10 -#define R11 %r11 - -#define prologue(FUNC,KEY,B128,B192,r1,r2,r5,r6,r7,r8,r9,r10,r11) \ - ENTRY(FUNC); \ - movq r1,r2; \ - leaq KEY+48(r8),r9; \ - movq r10,r11; \ - movl (r7),r5 ## E; \ - movl 4(r7),r1 ## E; \ - movl 8(r7),r6 ## E; \ - movl 12(r7),r7 ## E; \ - movl 480(r8),r10 ## E; \ - xorl -48(r9),r5 ## E; \ - xorl -44(r9),r1 ## E; \ - xorl -40(r9),r6 ## E; \ - xorl -36(r9),r7 ## E; \ - cmpl $24,r10 ## E; \ - jb B128; \ - leaq 32(r9),r9; \ - je B192; \ - leaq 32(r9),r9; - -#define epilogue(FUNC,r1,r2,r5,r6,r7,r8,r9) \ - movq r1,r2; \ - movl r5 ## E,(r9); \ - movl r6 ## E,4(r9); \ - movl r7 ## E,8(r9); \ - movl r8 ## E,12(r9); \ - ret; \ - ENDPROC(FUNC); - -#define round(TAB,OFFSET,r1,r2,r3,r4,r5,r6,r7,r8,ra,rb,rc,rd) \ - movzbl r2 ## H,r5 ## E; \ - movzbl r2 ## L,r6 ## E; \ - movl TAB+1024(,r5,4),r5 ## E;\ - movw r4 ## X,r2 ## X; \ - movl TAB(,r6,4),r6 ## E; \ - roll $16,r2 ## E; \ - shrl $16,r4 ## E; \ - movzbl r4 ## L,r7 ## E; \ - movzbl r4 ## H,r4 ## E; \ - xorl OFFSET(r8),ra ## E; \ - xorl OFFSET+4(r8),rb ## E; \ - xorl TAB+3072(,r4,4),r5 ## E;\ - xorl TAB+2048(,r7,4),r6 ## E;\ - movzbl r1 ## L,r7 ## E; \ - movzbl r1 ## H,r4 ## E; \ - movl TAB+1024(,r4,4),r4 ## E;\ - movw r3 ## X,r1 ## X; \ - roll $16,r1 ## E; \ - shrl $16,r3 ## E; \ - xorl TAB(,r7,4),r5 ## E; \ - movzbl r3 ## L,r7 ## E; \ - movzbl r3 ## H,r3 ## E; \ - xorl TAB+3072(,r3,4),r4 ## E;\ - xorl TAB+2048(,r7,4),r5 ## E;\ - movzbl r1 ## L,r7 ## E; \ - movzbl r1 ## H,r3 ## E; \ - shrl $16,r1 ## E; \ - xorl TAB+3072(,r3,4),r6 ## E;\ - movl TAB+2048(,r7,4),r3 ## E;\ - movzbl r1 ## L,r7 ## E; \ - movzbl r1 ## H,r1 ## E; \ - xorl TAB+1024(,r1,4),r6 ## E;\ - xorl TAB(,r7,4),r3 ## E; \ - movzbl r2 ## H,r1 ## E; \ - movzbl r2 ## L,r7 ## E; \ - shrl $16,r2 ## E; \ - xorl TAB+3072(,r1,4),r3 ## E;\ - xorl TAB+2048(,r7,4),r4 ## E;\ - movzbl r2 ## H,r1 ## E; \ - movzbl r2 ## L,r2 ## E; \ - xorl OFFSET+8(r8),rc ## E; \ - xorl OFFSET+12(r8),rd ## E; \ - xorl TAB+1024(,r1,4),r3 ## E;\ - xorl TAB(,r2,4),r4 ## E; - -#define move_regs(r1,r2,r3,r4) \ - movl r3 ## E,r1 ## E; \ - movl r4 ## E,r2 ## E; - -#define entry(FUNC,KEY,B128,B192) \ - prologue(FUNC,KEY,B128,B192,R2,R8,R1,R3,R4,R6,R10,R5,R11) - -#define return(FUNC) epilogue(FUNC,R8,R2,R5,R6,R3,R4,R11) - -#define encrypt_round(TAB,OFFSET) \ - round(TAB,OFFSET,R1,R2,R3,R4,R5,R6,R7,R10,R5,R6,R3,R4) \ - move_regs(R1,R2,R5,R6) - -#define encrypt_final(TAB,OFFSET) \ - round(TAB,OFFSET,R1,R2,R3,R4,R5,R6,R7,R10,R5,R6,R3,R4) - -#define decrypt_round(TAB,OFFSET) \ - round(TAB,OFFSET,R2,R1,R4,R3,R6,R5,R7,R10,R5,R6,R3,R4) \ - move_regs(R1,R2,R5,R6) - -#define decrypt_final(TAB,OFFSET) \ - round(TAB,OFFSET,R2,R1,R4,R3,R6,R5,R7,R10,R5,R6,R3,R4) - -/* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */ - - entry(aes_enc_blk,0,.Le128,.Le192) - encrypt_round(crypto_ft_tab,-96) - encrypt_round(crypto_ft_tab,-80) -.Le192: encrypt_round(crypto_ft_tab,-64) - encrypt_round(crypto_ft_tab,-48) -.Le128: encrypt_round(crypto_ft_tab,-32) - encrypt_round(crypto_ft_tab,-16) - encrypt_round(crypto_ft_tab, 0) - encrypt_round(crypto_ft_tab, 16) - encrypt_round(crypto_ft_tab, 32) - encrypt_round(crypto_ft_tab, 48) - encrypt_round(crypto_ft_tab, 64) - encrypt_round(crypto_ft_tab, 80) - encrypt_round(crypto_ft_tab, 96) - encrypt_final(crypto_fl_tab,112) - return(aes_enc_blk) - -/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ - - entry(aes_dec_blk,240,.Ld128,.Ld192) - decrypt_round(crypto_it_tab,-96) - decrypt_round(crypto_it_tab,-80) -.Ld192: decrypt_round(crypto_it_tab,-64) - decrypt_round(crypto_it_tab,-48) -.Ld128: decrypt_round(crypto_it_tab,-32) - decrypt_round(crypto_it_tab,-16) - decrypt_round(crypto_it_tab, 0) - decrypt_round(crypto_it_tab, 16) - decrypt_round(crypto_it_tab, 32) - decrypt_round(crypto_it_tab, 48) - decrypt_round(crypto_it_tab, 64) - decrypt_round(crypto_it_tab, 80) - decrypt_round(crypto_it_tab, 96) - decrypt_final(crypto_il_tab,112) - return(aes_dec_blk) diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c index 9e9d819e8bc3..7b7dc05fa1a4 100644 --- a/arch/x86/crypto/aes_glue.c +++ b/arch/x86/crypto/aes_glue.c @@ -1,71 +1 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * Glue Code for the asm optimized version of the AES Cipher Algorithm - * - */ - -#include -#include -#include - -asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); -asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); - -void crypto_aes_encrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) -{ - aes_enc_blk(ctx, dst, src); -} -EXPORT_SYMBOL_GPL(crypto_aes_encrypt_x86); - -void crypto_aes_decrypt_x86(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src) -{ - aes_dec_blk(ctx, dst, src); -} -EXPORT_SYMBOL_GPL(crypto_aes_decrypt_x86); - -static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - aes_enc_blk(crypto_tfm_ctx(tfm), dst, src); -} - -static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - aes_dec_blk(crypto_tfm_ctx(tfm), dst, src); -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-asm", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = crypto_aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt - } - } -}; - -static int __init aes_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CRYPTO("aes"); -MODULE_ALIAS_CRYPTO("aes-asm"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 20af58068e6b..df6f0be66574 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1108,50 +1108,6 @@ config CRYPTO_AES_TI block. Interrupts are also disabled to avoid races where cachelines are evicted when the CPU is interrupted to do something else. -config CRYPTO_AES_586 - tristate "AES cipher algorithms (i586)" - depends on (X86 || UML_X86) && !64BIT - select CRYPTO_ALGAPI - select CRYPTO_AES - help - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - The AES specifies three key sizes: 128, 192 and 256 bits - - See for more information. - -config CRYPTO_AES_X86_64 - tristate "AES cipher algorithms (x86_64)" - depends on (X86 || UML_X86) && 64BIT - select CRYPTO_ALGAPI - select CRYPTO_AES - help - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - The AES specifies three key sizes: 128, 192 and 256 bits - - See for more information. - config CRYPTO_AES_NI_INTEL tristate "AES cipher algorithms (AES-NI)" depends on X86 -- GitLab From 8131878db76c2bd3065bd3b75cb6615390a393e6 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:25 +0200 Subject: [PATCH 0775/7155] crypto: padlock/aes - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- drivers/crypto/padlock-aes.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 603413f28fa3..27121e530ca4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -27,7 +27,7 @@ config CRYPTO_DEV_PADLOCK_AES tristate "PadLock driver for AES algorithm" depends on CRYPTO_DEV_PADLOCK select CRYPTO_BLKCIPHER - select CRYPTO_AES + select CRYPTO_LIB_AES help Use VIA PadLock for AES algorithm. diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index fbba32e8cb26..8a0661250078 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -145,7 +145,7 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, ctx->cword.encrypt.keygen = 1; ctx->cword.decrypt.keygen = 1; - if (crypto_aes_expand_key(&gen_aes, in_key, key_len)) { + if (aes_expandkey(&gen_aes, in_key, key_len)) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } -- GitLab From 18d8b96daded4123d6f1ec00a390b16e4cf1d40c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:26 +0200 Subject: [PATCH 0776/7155] crypto: cesa/aes - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- drivers/crypto/marvell/cipher.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 27121e530ca4..cfb4c2a42b35 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -214,7 +214,7 @@ config CRYPTO_CRC32_S390 config CRYPTO_DEV_MARVELL_CESA tristate "Marvell's Cryptographic Engine driver" depends on PLAT_ORION || ARCH_MVEBU - select CRYPTO_AES + select CRYPTO_LIB_AES select CRYPTO_DES select CRYPTO_BLKCIPHER select CRYPTO_HASH diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index f4321f3c0777..fa1997e70b63 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -254,7 +254,7 @@ static int mv_cesa_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, int ret; int i; - ret = crypto_aes_expand_key(&ctx->aes, key, len); + ret = aes_expandkey(&ctx->aes, key, len); if (ret) { crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); return ret; -- GitLab From 363a90c2d517e69776dcf71cc3d6fcaee9fef868 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:27 +0200 Subject: [PATCH 0777/7155] crypto: safexcel/aes - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- drivers/crypto/inside-secure/safexcel_cipher.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index cfb4c2a42b35..72d6c2ca0809 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -719,7 +719,7 @@ config CRYPTO_DEV_SAFEXCEL tristate "Inside Secure's SafeXcel cryptographic engine driver" depends on OF depends on (ARM64 && ARCH_MVEBU) || (COMPILE_TEST && 64BIT) - select CRYPTO_AES + select CRYPTO_LIB_AES select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER select CRYPTO_DES diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index e87428733671..ee3a90f028b5 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -159,7 +159,7 @@ static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, struct crypto_aes_ctx aes; int ret, i; - ret = crypto_aes_expand_key(&aes, key, len); + ret = aes_expandkey(&aes, key, len); if (ret) { crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return ret; -- GitLab From fe3b99b64909e8994f2606120e4703c9a1e8c080 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:28 +0200 Subject: [PATCH 0778/7155] crypto: arm64/ghash - switch to AES library The GHASH code uses the generic AES key expansion routines, and calls directly into the scalar table based AES cipher for arm64 from the fallback path, and since this implementation is known to be non-time invariant, doing so from a time invariant SIMD cipher is a bit nasty. So let's switch to the AES library - this makes the code more robust, and drops the dependency on the generic AES cipher, allowing us to omit it entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/Kconfig | 3 +-- arch/arm64/crypto/ghash-ce-glue.c | 30 ++++++++++-------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index d9a523ecdd83..1762055e7093 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -58,8 +58,7 @@ config CRYPTO_GHASH_ARM64_CE depends on KERNEL_MODE_NEON select CRYPTO_HASH select CRYPTO_GF128MUL - select CRYPTO_AES - select CRYPTO_AES_ARM64 + select CRYPTO_LIB_AES config CRYPTO_CRCT10DIF_ARM64_CE tristate "CRCT10DIF digest algorithm using PMULL instructions" diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c index 16c5da9be9fb..70b1469783f9 100644 --- a/arch/arm64/crypto/ghash-ce-glue.c +++ b/arch/arm64/crypto/ghash-ce-glue.c @@ -70,8 +70,6 @@ asmlinkage void pmull_gcm_decrypt(int blocks, u64 dg[], u8 dst[], asmlinkage void pmull_gcm_encrypt_block(u8 dst[], u8 const src[], u32 const rk[], int rounds); -asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - static int ghash_init(struct shash_desc *desc) { struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); @@ -309,14 +307,13 @@ static int gcm_setkey(struct crypto_aead *tfm, const u8 *inkey, u8 key[GHASH_BLOCK_SIZE]; int ret; - ret = crypto_aes_expand_key(&ctx->aes_key, inkey, keylen); + ret = aes_expandkey(&ctx->aes_key, inkey, keylen); if (ret) { tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } - __aes_arm64_encrypt(ctx->aes_key.key_enc, key, (u8[AES_BLOCK_SIZE]){}, - num_rounds(&ctx->aes_key)); + aes_encrypt(&ctx->aes_key, key, (u8[AES_BLOCK_SIZE]){}); return __ghash_setkey(&ctx->ghash_key, key, sizeof(be128)); } @@ -467,7 +464,7 @@ static int gcm_encrypt(struct aead_request *req) rk = ctx->aes_key.key_enc; } while (walk.nbytes >= 2 * AES_BLOCK_SIZE); } else { - __aes_arm64_encrypt(ctx->aes_key.key_enc, tag, iv, nrounds); + aes_encrypt(&ctx->aes_key, tag, iv); put_unaligned_be32(2, iv + GCM_IV_SIZE); while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) { @@ -478,8 +475,7 @@ static int gcm_encrypt(struct aead_request *req) int remaining = blocks; do { - __aes_arm64_encrypt(ctx->aes_key.key_enc, - ks, iv, nrounds); + aes_encrypt(&ctx->aes_key, ks, iv); crypto_xor_cpy(dst, src, ks, AES_BLOCK_SIZE); crypto_inc(iv, AES_BLOCK_SIZE); @@ -495,13 +491,10 @@ static int gcm_encrypt(struct aead_request *req) walk.nbytes % (2 * AES_BLOCK_SIZE)); } if (walk.nbytes) { - __aes_arm64_encrypt(ctx->aes_key.key_enc, ks, iv, - nrounds); + aes_encrypt(&ctx->aes_key, ks, iv); if (walk.nbytes > AES_BLOCK_SIZE) { crypto_inc(iv, AES_BLOCK_SIZE); - __aes_arm64_encrypt(ctx->aes_key.key_enc, - ks + AES_BLOCK_SIZE, iv, - nrounds); + aes_encrypt(&ctx->aes_key, ks + AES_BLOCK_SIZE, iv); } } } @@ -605,7 +598,7 @@ static int gcm_decrypt(struct aead_request *req) rk = ctx->aes_key.key_enc; } while (walk.nbytes >= 2 * AES_BLOCK_SIZE); } else { - __aes_arm64_encrypt(ctx->aes_key.key_enc, tag, iv, nrounds); + aes_encrypt(&ctx->aes_key, tag, iv); put_unaligned_be32(2, iv + GCM_IV_SIZE); while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) { @@ -618,8 +611,7 @@ static int gcm_decrypt(struct aead_request *req) pmull_ghash_update_p64); do { - __aes_arm64_encrypt(ctx->aes_key.key_enc, - buf, iv, nrounds); + aes_encrypt(&ctx->aes_key, buf, iv); crypto_xor_cpy(dst, src, buf, AES_BLOCK_SIZE); crypto_inc(iv, AES_BLOCK_SIZE); @@ -637,11 +629,9 @@ static int gcm_decrypt(struct aead_request *req) memcpy(iv2, iv, AES_BLOCK_SIZE); crypto_inc(iv2, AES_BLOCK_SIZE); - __aes_arm64_encrypt(ctx->aes_key.key_enc, iv2, - iv2, nrounds); + aes_encrypt(&ctx->aes_key, iv2, iv2); } - __aes_arm64_encrypt(ctx->aes_key.key_enc, iv, iv, - nrounds); + aes_encrypt(&ctx->aes_key, iv, iv); } } -- GitLab From aa6e2d2b355f89e22c30b41d7e6653c8189235b8 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:29 +0200 Subject: [PATCH 0779/7155] crypto: arm/aes-neonbs - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/Kconfig | 2 +- arch/arm/crypto/aes-neonbs-glue.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index a95322b59799..b24df84a1d7a 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -82,8 +82,8 @@ config CRYPTO_AES_ARM_BS tristate "Bit sliced AES using NEON instructions" depends on KERNEL_MODE_NEON select CRYPTO_BLKCIPHER + select CRYPTO_LIB_AES select CRYPTO_SIMD - select CRYPTO_AES help Use a faster and more secure NEON based implementation of AES in CBC, CTR and XTS modes diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index bd0bee9c8f7b..8c22d10bd909 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -61,7 +61,7 @@ static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, struct crypto_aes_ctx rk; int err; - err = crypto_aes_expand_key(&rk, in_key, key_len); + err = aes_expandkey(&rk, in_key, key_len); if (err) return err; @@ -120,7 +120,7 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key, struct crypto_aes_ctx rk; int err; - err = crypto_aes_expand_key(&rk, in_key, key_len); + err = aes_expandkey(&rk, in_key, key_len); if (err) return err; -- GitLab From c59a6dffa3cdf826cba92f1b967f8dba2fafec53 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:30 +0200 Subject: [PATCH 0780/7155] crypto: arm64/aes-ccm - switch to AES library The CCM code calls directly into the scalar table based AES cipher for arm64 from the fallback path, and since this implementation is known to be non-time invariant, doing so from a time invariant SIMD cipher is a bit nasty. So let's switch to the AES library - this makes the code more robust, and drops the dependency on the generic AES cipher, allowing us to omit it entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/Kconfig | 2 +- arch/arm64/crypto/aes-ce-ccm-glue.c | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 1762055e7093..c6032bfb44fb 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -80,8 +80,8 @@ config CRYPTO_AES_ARM64_CE_CCM depends on ARM64 && KERNEL_MODE_NEON select CRYPTO_ALGAPI select CRYPTO_AES_ARM64_CE - select CRYPTO_AES_ARM64 select CRYPTO_AEAD + select CRYPTO_LIB_AES config CRYPTO_AES_ARM64_CE_BLK tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions" diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c index 827e5473e5de..541cf9165748 100644 --- a/arch/arm64/crypto/aes-ce-ccm-glue.c +++ b/arch/arm64/crypto/aes-ce-ccm-glue.c @@ -43,8 +43,6 @@ asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[], u32 rounds); -asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key, unsigned int key_len) { @@ -124,8 +122,7 @@ static void ccm_update_mac(struct crypto_aes_ctx *key, u8 mac[], u8 const in[], } while (abytes >= AES_BLOCK_SIZE) { - __aes_arm64_encrypt(key->key_enc, mac, mac, - num_rounds(key)); + aes_encrypt(key, mac, mac); crypto_xor(mac, in, AES_BLOCK_SIZE); in += AES_BLOCK_SIZE; @@ -133,8 +130,7 @@ static void ccm_update_mac(struct crypto_aes_ctx *key, u8 mac[], u8 const in[], } if (abytes > 0) { - __aes_arm64_encrypt(key->key_enc, mac, mac, - num_rounds(key)); + aes_encrypt(key, mac, mac); crypto_xor(mac, in, abytes); *macp = abytes; } @@ -206,10 +202,8 @@ static int ccm_crypt_fallback(struct skcipher_walk *walk, u8 mac[], u8 iv0[], bsize = nbytes; crypto_inc(walk->iv, AES_BLOCK_SIZE); - __aes_arm64_encrypt(ctx->key_enc, buf, walk->iv, - num_rounds(ctx)); - __aes_arm64_encrypt(ctx->key_enc, mac, mac, - num_rounds(ctx)); + aes_encrypt(ctx, buf, walk->iv); + aes_encrypt(ctx, mac, mac); if (enc) crypto_xor(mac, src, bsize); crypto_xor_cpy(dst, src, buf, bsize); @@ -224,8 +218,8 @@ static int ccm_crypt_fallback(struct skcipher_walk *walk, u8 mac[], u8 iv0[], } if (!err) { - __aes_arm64_encrypt(ctx->key_enc, buf, iv0, num_rounds(ctx)); - __aes_arm64_encrypt(ctx->key_enc, mac, mac, num_rounds(ctx)); + aes_encrypt(ctx, buf, iv0); + aes_encrypt(ctx, mac, mac); crypto_xor(mac, buf, AES_BLOCK_SIZE); } return err; -- GitLab From f68df54307aaae01df66977511ea719158201188 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:31 +0200 Subject: [PATCH 0781/7155] crypto: arm64/aes-neonbs - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/Kconfig | 1 + arch/arm64/crypto/aes-neonbs-glue.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index c6032bfb44fb..17bf5dc10aad 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -116,6 +116,7 @@ config CRYPTO_AES_ARM64_BS select CRYPTO_BLKCIPHER select CRYPTO_AES_ARM64_NEON_BLK select CRYPTO_AES_ARM64 + select CRYPTO_LIB_AES select CRYPTO_SIMD endif diff --git a/arch/arm64/crypto/aes-neonbs-glue.c b/arch/arm64/crypto/aes-neonbs-glue.c index 281d23087697..25fe51eedc98 100644 --- a/arch/arm64/crypto/aes-neonbs-glue.c +++ b/arch/arm64/crypto/aes-neonbs-glue.c @@ -74,7 +74,7 @@ static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, struct crypto_aes_ctx rk; int err; - err = crypto_aes_expand_key(&rk, in_key, key_len); + err = aes_expandkey(&rk, in_key, key_len); if (err) return err; @@ -133,7 +133,7 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key, struct crypto_aes_ctx rk; int err; - err = crypto_aes_expand_key(&rk, in_key, key_len); + err = aes_expandkey(&rk, in_key, key_len); if (err) return err; @@ -205,7 +205,7 @@ static int aesbs_ctr_setkey_sync(struct crypto_skcipher *tfm, const u8 *in_key, struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); int err; - err = crypto_aes_expand_key(&ctx->fallback, in_key, key_len); + err = aes_expandkey(&ctx->fallback, in_key, key_len); if (err) return err; @@ -271,7 +271,7 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return err; key_len /= 2; - err = crypto_aes_expand_key(&rk, in_key + key_len, key_len); + err = aes_expandkey(&rk, in_key + key_len, key_len); if (err) return err; -- GitLab From c184472902d87189082e5a349051197e252ae9af Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:32 +0200 Subject: [PATCH 0782/7155] crypto: arm64/aes-ce - switch to library version of key expansion routine Switch to the new AES library that also provides an implementation of the AES key expansion routine. This removes the dependency on the generic AES cipher, allowing it to be omitted entirely in the future. While at it, remove some references to the table based arm64 version of AES and replace them with AES library calls as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/Kconfig | 2 +- arch/arm64/crypto/aes-glue.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 17bf5dc10aad..66dea518221c 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -96,7 +96,7 @@ config CRYPTO_AES_ARM64_NEON_BLK depends on KERNEL_MODE_NEON select CRYPTO_BLKCIPHER select CRYPTO_AES_ARM64 - select CRYPTO_AES + select CRYPTO_LIB_AES select CRYPTO_SIMD config CRYPTO_CHACHA20_NEON diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 8d6c8932c841..843fb27c4961 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -23,7 +23,6 @@ #ifdef USE_V8_CRYPTO_EXTENSIONS #define MODE "ce" #define PRIO 300 -#define aes_setkey ce_aes_setkey #define aes_expandkey ce_aes_expandkey #define aes_ecb_encrypt ce_aes_ecb_encrypt #define aes_ecb_decrypt ce_aes_ecb_decrypt @@ -39,8 +38,6 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); #else #define MODE "neon" #define PRIO 200 -#define aes_setkey crypto_aes_set_key -#define aes_expandkey crypto_aes_expand_key #define aes_ecb_encrypt neon_aes_ecb_encrypt #define aes_ecb_decrypt neon_aes_ecb_decrypt #define aes_cbc_encrypt neon_aes_cbc_encrypt @@ -118,7 +115,14 @@ struct mac_desc_ctx { static int skcipher_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { - return aes_setkey(crypto_skcipher_tfm(tfm), in_key, key_len); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + int ret; + + ret = aes_expandkey(ctx, in_key, key_len); + if (ret) + crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + + return ret; } static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key, @@ -646,15 +650,14 @@ static void mac_do_update(struct crypto_aes_ctx *ctx, u8 const in[], int blocks, kernel_neon_end(); } else { if (enc_before) - __aes_arm64_encrypt(ctx->key_enc, dg, dg, rounds); + aes_encrypt(ctx, dg, dg); while (blocks--) { crypto_xor(dg, in, AES_BLOCK_SIZE); in += AES_BLOCK_SIZE; if (blocks || enc_after) - __aes_arm64_encrypt(ctx->key_enc, dg, dg, - rounds); + aes_encrypt(ctx, dg, dg); } } } -- GitLab From 5bb12d7825adf0e80b849a273834f3131a6cc4e1 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:33 +0200 Subject: [PATCH 0783/7155] crypto: aes-generic - drop key expansion routine in favor of library version Drop aes-generic's version of crypto_aes_expand_key(), and switch to the key expansion routine provided by the AES library. AES key expansion is not performance critical, and it is better to have a single version shared by all AES implementations. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 1 + crypto/aes_generic.c | 153 +------------------------------------------ include/crypto/aes.h | 2 - 3 files changed, 3 insertions(+), 153 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index df6f0be66574..80ea118600ab 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1072,6 +1072,7 @@ config CRYPTO_LIB_AES config CRYPTO_AES tristate "AES cipher algorithms" select CRYPTO_ALGAPI + select CRYPTO_LIB_AES help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c index 3aa4a715c216..426deb437f19 100644 --- a/crypto/aes_generic.c +++ b/crypto/aes_generic.c @@ -1125,155 +1125,6 @@ EXPORT_SYMBOL_GPL(crypto_fl_tab); EXPORT_SYMBOL_GPL(crypto_it_tab); EXPORT_SYMBOL_GPL(crypto_il_tab); -/* initialise the key schedule from the user supplied key */ - -#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) - -#define imix_col(y, x) do { \ - u = star_x(x); \ - v = star_x(u); \ - w = star_x(v); \ - t = w ^ (x); \ - (y) = u ^ v ^ w; \ - (y) ^= ror32(u ^ t, 8) ^ \ - ror32(v ^ t, 16) ^ \ - ror32(t, 24); \ -} while (0) - -#define ls_box(x) \ - crypto_fl_tab[0][byte(x, 0)] ^ \ - crypto_fl_tab[1][byte(x, 1)] ^ \ - crypto_fl_tab[2][byte(x, 2)] ^ \ - crypto_fl_tab[3][byte(x, 3)] - -#define loop4(i) do { \ - t = ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[4 * i]; \ - ctx->key_enc[4 * i + 4] = t; \ - t ^= ctx->key_enc[4 * i + 1]; \ - ctx->key_enc[4 * i + 5] = t; \ - t ^= ctx->key_enc[4 * i + 2]; \ - ctx->key_enc[4 * i + 6] = t; \ - t ^= ctx->key_enc[4 * i + 3]; \ - ctx->key_enc[4 * i + 7] = t; \ -} while (0) - -#define loop6(i) do { \ - t = ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[6 * i]; \ - ctx->key_enc[6 * i + 6] = t; \ - t ^= ctx->key_enc[6 * i + 1]; \ - ctx->key_enc[6 * i + 7] = t; \ - t ^= ctx->key_enc[6 * i + 2]; \ - ctx->key_enc[6 * i + 8] = t; \ - t ^= ctx->key_enc[6 * i + 3]; \ - ctx->key_enc[6 * i + 9] = t; \ - t ^= ctx->key_enc[6 * i + 4]; \ - ctx->key_enc[6 * i + 10] = t; \ - t ^= ctx->key_enc[6 * i + 5]; \ - ctx->key_enc[6 * i + 11] = t; \ -} while (0) - -#define loop8tophalf(i) do { \ - t = ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[8 * i]; \ - ctx->key_enc[8 * i + 8] = t; \ - t ^= ctx->key_enc[8 * i + 1]; \ - ctx->key_enc[8 * i + 9] = t; \ - t ^= ctx->key_enc[8 * i + 2]; \ - ctx->key_enc[8 * i + 10] = t; \ - t ^= ctx->key_enc[8 * i + 3]; \ - ctx->key_enc[8 * i + 11] = t; \ -} while (0) - -#define loop8(i) do { \ - loop8tophalf(i); \ - t = ctx->key_enc[8 * i + 4] ^ ls_box(t); \ - ctx->key_enc[8 * i + 12] = t; \ - t ^= ctx->key_enc[8 * i + 5]; \ - ctx->key_enc[8 * i + 13] = t; \ - t ^= ctx->key_enc[8 * i + 6]; \ - ctx->key_enc[8 * i + 14] = t; \ - t ^= ctx->key_enc[8 * i + 7]; \ - ctx->key_enc[8 * i + 15] = t; \ -} while (0) - -/** - * crypto_aes_expand_key - Expands the AES key as described in FIPS-197 - * @ctx: The location where the computed key will be stored. - * @in_key: The supplied key. - * @key_len: The length of the supplied key. - * - * Returns 0 on success. The function fails only if an invalid key size (or - * pointer) is supplied. - * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes - * key schedule plus a 16 bytes key which is used before the first round). - * The decryption key is prepared for the "Equivalent Inverse Cipher" as - * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is - * for the initial combination, the second slot for the first round and so on. - */ -int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len) -{ - u32 i, t, u, v, w, j; - - if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 && - key_len != AES_KEYSIZE_256) - return -EINVAL; - - ctx->key_length = key_len; - - ctx->key_enc[0] = get_unaligned_le32(in_key); - ctx->key_enc[1] = get_unaligned_le32(in_key + 4); - ctx->key_enc[2] = get_unaligned_le32(in_key + 8); - ctx->key_enc[3] = get_unaligned_le32(in_key + 12); - - ctx->key_dec[key_len + 24] = ctx->key_enc[0]; - ctx->key_dec[key_len + 25] = ctx->key_enc[1]; - ctx->key_dec[key_len + 26] = ctx->key_enc[2]; - ctx->key_dec[key_len + 27] = ctx->key_enc[3]; - - switch (key_len) { - case AES_KEYSIZE_128: - t = ctx->key_enc[3]; - for (i = 0; i < 10; ++i) - loop4(i); - break; - - case AES_KEYSIZE_192: - ctx->key_enc[4] = get_unaligned_le32(in_key + 16); - t = ctx->key_enc[5] = get_unaligned_le32(in_key + 20); - for (i = 0; i < 8; ++i) - loop6(i); - break; - - case AES_KEYSIZE_256: - ctx->key_enc[4] = get_unaligned_le32(in_key + 16); - ctx->key_enc[5] = get_unaligned_le32(in_key + 20); - ctx->key_enc[6] = get_unaligned_le32(in_key + 24); - t = ctx->key_enc[7] = get_unaligned_le32(in_key + 28); - for (i = 0; i < 6; ++i) - loop8(i); - loop8tophalf(i); - break; - } - - ctx->key_dec[0] = ctx->key_enc[key_len + 24]; - ctx->key_dec[1] = ctx->key_enc[key_len + 25]; - ctx->key_dec[2] = ctx->key_enc[key_len + 26]; - ctx->key_dec[3] = ctx->key_enc[key_len + 27]; - - for (i = 4; i < key_len + 24; ++i) { - j = key_len + 24 - (i & ~3) + (i & 3); - imix_col(ctx->key_dec[j], ctx->key_enc[i]); - } - return 0; -} -EXPORT_SYMBOL_GPL(crypto_aes_expand_key); - /** * crypto_aes_set_key - Set the AES key. * @tfm: The %crypto_tfm that is used in the context. @@ -1281,7 +1132,7 @@ EXPORT_SYMBOL_GPL(crypto_aes_expand_key); * @key_len: The size of the key. * * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm - * is set. The function uses crypto_aes_expand_key() to expand the key. + * is set. The function uses aes_expand_key() to expand the key. * &crypto_aes_ctx _must_ be the private data embedded in @tfm which is * retrieved with crypto_tfm_ctx(). */ @@ -1292,7 +1143,7 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, u32 *flags = &tfm->crt_flags; int ret; - ret = crypto_aes_expand_key(ctx, in_key, key_len); + ret = aes_expandkey(ctx, in_key, key_len); if (!ret) return 0; diff --git a/include/crypto/aes.h b/include/crypto/aes.h index d0067fca0cd0..0a64a977f9b3 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -35,8 +35,6 @@ extern const u32 crypto_il_tab[4][256] ____cacheline_aligned; int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len); -int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len); /** * aes_expandkey - Expands the AES key as described in FIPS-197 -- GitLab From d9ec772d9550b6e513c51bc4e6fa1e3ffb50181c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:34 +0200 Subject: [PATCH 0784/7155] crypto: ctr - add helper for performing a CTR encryption walk Add a static inline helper modeled after crypto_cbc_encrypt_walk() that can be reused for SIMD algorithms that need to implement a non-SIMD fallback for performing CTR encryption. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- include/crypto/ctr.h | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/crypto/ctr.h b/include/crypto/ctr.h index 06984a26c8cf..a1c66d1001af 100644 --- a/include/crypto/ctr.h +++ b/include/crypto/ctr.h @@ -8,8 +8,58 @@ #ifndef _CRYPTO_CTR_H #define _CRYPTO_CTR_H +#include +#include +#include +#include + #define CTR_RFC3686_NONCE_SIZE 4 #define CTR_RFC3686_IV_SIZE 8 #define CTR_RFC3686_BLOCK_SIZE 16 +static inline int crypto_ctr_encrypt_walk(struct skcipher_request *req, + void (*fn)(struct crypto_skcipher *, + const u8 *, u8 *)) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + int blocksize = crypto_skcipher_chunksize(tfm); + u8 buf[MAX_CIPHER_BLOCKSIZE]; + struct skcipher_walk walk; + int err; + + /* avoid integer division due to variable blocksize parameter */ + if (WARN_ON_ONCE(!is_power_of_2(blocksize))) + return -EINVAL; + + err = skcipher_walk_virt(&walk, req, false); + + while (walk.nbytes > 0) { + u8 *dst = walk.dst.virt.addr; + u8 *src = walk.src.virt.addr; + int nbytes = walk.nbytes; + int tail = 0; + + if (nbytes < walk.total) { + tail = walk.nbytes & (blocksize - 1); + nbytes -= tail; + } + + do { + int bsize = min(nbytes, blocksize); + + fn(tfm, walk.iv, buf); + + crypto_xor_cpy(dst, src, buf, bsize); + crypto_inc(walk.iv, blocksize); + + dst += bsize; + src += bsize; + nbytes -= bsize; + } while (nbytes > 0); + + err = skcipher_walk_done(&walk, tail); + } + return err; +} + #endif /* _CRYPTO_CTR_H */ -- GitLab From ff6f4115cb953c5be8d7a76b2ec1877df2f4c2c0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:35 +0200 Subject: [PATCH 0785/7155] crypto: aes - move sync ctr(aes) to AES library and generic helper In preparation of duplicating the sync ctr(aes) functionality to modules under arch/arm, move the helper function from a inline .h file to the AES library, which is already depended upon by the drivers that use this fallback. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/aes-ctr-fallback.h | 50 ---------------------------- arch/arm64/crypto/aes-glue.c | 22 +++++++++--- arch/arm64/crypto/aes-neonbs-glue.c | 21 +++++++++--- 3 files changed, 33 insertions(+), 60 deletions(-) delete mode 100644 arch/arm64/crypto/aes-ctr-fallback.h diff --git a/arch/arm64/crypto/aes-ctr-fallback.h b/arch/arm64/crypto/aes-ctr-fallback.h deleted file mode 100644 index 3ac911990ec7..000000000000 --- a/arch/arm64/crypto/aes-ctr-fallback.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Fallback for sync aes(ctr) in contexts where kernel mode NEON - * is not allowed - * - * Copyright (C) 2017 Linaro Ltd - */ - -#include -#include - -asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - -static inline int aes_ctr_encrypt_fallback(struct crypto_aes_ctx *ctx, - struct skcipher_request *req) -{ - struct skcipher_walk walk; - u8 buf[AES_BLOCK_SIZE]; - int err; - - err = skcipher_walk_virt(&walk, req, true); - - while (walk.nbytes > 0) { - u8 *dst = walk.dst.virt.addr; - u8 *src = walk.src.virt.addr; - int nbytes = walk.nbytes; - int tail = 0; - - if (nbytes < walk.total) { - nbytes = round_down(nbytes, AES_BLOCK_SIZE); - tail = walk.nbytes % AES_BLOCK_SIZE; - } - - do { - int bsize = min(nbytes, AES_BLOCK_SIZE); - - __aes_arm64_encrypt(ctx->key_enc, buf, walk.iv, - 6 + ctx->key_length / 4); - crypto_xor_cpy(dst, src, buf, bsize); - crypto_inc(walk.iv, AES_BLOCK_SIZE); - - dst += AES_BLOCK_SIZE; - src += AES_BLOCK_SIZE; - nbytes -= AES_BLOCK_SIZE; - } while (nbytes > 0); - - err = skcipher_walk_done(&walk, tail); - } - return err; -} diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 843fb27c4961..55d6d4838708 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include "aes-ce-setkey.h" -#include "aes-ctr-fallback.h" #ifdef USE_V8_CRYPTO_EXTENSIONS #define MODE "ce" @@ -401,13 +401,25 @@ static int ctr_encrypt(struct skcipher_request *req) return err; } -static int ctr_encrypt_sync(struct skcipher_request *req) +static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) { - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + const struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + unsigned long flags; + + /* + * Temporarily disable interrupts to avoid races where + * cachelines are evicted when the CPU is interrupted + * to do something else. + */ + local_irq_save(flags); + aes_encrypt(ctx, dst, src); + local_irq_restore(flags); +} +static int ctr_encrypt_sync(struct skcipher_request *req) +{ if (!crypto_simd_usable()) - return aes_ctr_encrypt_fallback(ctx, req); + return crypto_ctr_encrypt_walk(req, ctr_encrypt_one); return ctr_encrypt(req); } diff --git a/arch/arm64/crypto/aes-neonbs-glue.c b/arch/arm64/crypto/aes-neonbs-glue.c index 25fe51eedc98..bafd2ebef8f1 100644 --- a/arch/arm64/crypto/aes-neonbs-glue.c +++ b/arch/arm64/crypto/aes-neonbs-glue.c @@ -8,13 +8,12 @@ #include #include #include +#include #include #include #include #include -#include "aes-ctr-fallback.h" - MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); @@ -280,13 +279,25 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return aesbs_setkey(tfm, in_key, key_len); } -static int ctr_encrypt_sync(struct skcipher_request *req) +static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) { - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); + unsigned long flags; + + /* + * Temporarily disable interrupts to avoid races where + * cachelines are evicted when the CPU is interrupted + * to do something else. + */ + local_irq_save(flags); + aes_encrypt(&ctx->fallback, dst, src); + local_irq_restore(flags); +} +static int ctr_encrypt_sync(struct skcipher_request *req) +{ if (!crypto_simd_usable()) - return aes_ctr_encrypt_fallback(&ctx->fallback, req); + return crypto_ctr_encrypt_walk(req, ctr_encrypt_one); return ctr_encrypt(req); } -- GitLab From 4d3f9d89c745ea5494ea23e545385af1b6f81363 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:36 +0200 Subject: [PATCH 0786/7155] crypto: arm64/aes-ce-cipher - use AES library as fallback Instead of calling into the table based scalar AES code in situations where the SIMD unit may not be used, use the generic AES code, which is more appropriate since it is less likely to be susceptible to timing attacks. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/Kconfig | 2 +- arch/arm64/crypto/aes-ce-glue.c | 7 ++----- arch/arm64/crypto/aes-cipher-glue.c | 3 --- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 66dea518221c..4922c4451e7c 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -73,7 +73,7 @@ config CRYPTO_AES_ARM64_CE tristate "AES core cipher using ARMv8 Crypto Extensions" depends on ARM64 && KERNEL_MODE_NEON select CRYPTO_ALGAPI - select CRYPTO_AES_ARM64 + select CRYPTO_LIB_AES config CRYPTO_AES_ARM64_CE_CCM tristate "AES in CCM mode using ARMv8 Crypto Extensions" diff --git a/arch/arm64/crypto/aes-ce-glue.c b/arch/arm64/crypto/aes-ce-glue.c index d3bc97afde20..6d085dc56c51 100644 --- a/arch/arm64/crypto/aes-ce-glue.c +++ b/arch/arm64/crypto/aes-ce-glue.c @@ -20,9 +20,6 @@ MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); -asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); -asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - struct aes_block { u8 b[AES_BLOCK_SIZE]; }; @@ -51,7 +48,7 @@ static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); if (!crypto_simd_usable()) { - __aes_arm64_encrypt(ctx->key_enc, dst, src, num_rounds(ctx)); + aes_encrypt(ctx, dst, src); return; } @@ -65,7 +62,7 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); if (!crypto_simd_usable()) { - __aes_arm64_decrypt(ctx->key_dec, dst, src, num_rounds(ctx)); + aes_decrypt(ctx, dst, src); return; } diff --git a/arch/arm64/crypto/aes-cipher-glue.c b/arch/arm64/crypto/aes-cipher-glue.c index cc7a6dad7c2e..8caf6dfefce8 100644 --- a/arch/arm64/crypto/aes-cipher-glue.c +++ b/arch/arm64/crypto/aes-cipher-glue.c @@ -10,10 +10,7 @@ #include asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); -EXPORT_SYMBOL(__aes_arm64_encrypt); - asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); -EXPORT_SYMBOL(__aes_arm64_decrypt); static void aes_arm64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { -- GitLab From fafb1dca6fad0efeeaaaeae5067cf7e194a47027 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:37 +0200 Subject: [PATCH 0787/7155] crypto: arm/aes - use native endiannes for key schedule Align ARM's hw instruction based AES implementation with other versions that keep the key schedule in native endianness. This will allow us to merge the various implementations going forward. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-ce-core.S | 20 ++++++++++---------- arch/arm/crypto/aes-ce-glue.c | 9 +++------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/arch/arm/crypto/aes-ce-core.S b/arch/arm/crypto/aes-ce-core.S index caac519d6249..425000232d49 100644 --- a/arch/arm/crypto/aes-ce-core.S +++ b/arch/arm/crypto/aes-ce-core.S @@ -88,19 +88,19 @@ .macro do_block, dround, fround cmp r3, #12 @ which key size? - vld1.8 {q10-q11}, [ip]! + vld1.32 {q10-q11}, [ip]! \dround q8, q9 - vld1.8 {q12-q13}, [ip]! + vld1.32 {q12-q13}, [ip]! \dround q10, q11 - vld1.8 {q10-q11}, [ip]! + vld1.32 {q10-q11}, [ip]! \dround q12, q13 - vld1.8 {q12-q13}, [ip]! + vld1.32 {q12-q13}, [ip]! \dround q10, q11 blo 0f @ AES-128: 10 rounds - vld1.8 {q10-q11}, [ip]! + vld1.32 {q10-q11}, [ip]! \dround q12, q13 beq 1f @ AES-192: 12 rounds - vld1.8 {q12-q13}, [ip] + vld1.32 {q12-q13}, [ip] \dround q10, q11 0: \fround q12, q13, q14 bx lr @@ -149,8 +149,8 @@ ENDPROC(aes_decrypt_3x) .macro prepare_key, rk, rounds add ip, \rk, \rounds, lsl #4 - vld1.8 {q8-q9}, [\rk] @ load first 2 round keys - vld1.8 {q14}, [ip] @ load last round key + vld1.32 {q8-q9}, [\rk] @ load first 2 round keys + vld1.32 {q14}, [ip] @ load last round key .endm /* @@ -505,8 +505,8 @@ ENDPROC(ce_aes_sub) * operation on round key *src */ ENTRY(ce_aes_invert) - vld1.8 {q0}, [r1] + vld1.32 {q0}, [r1] aesimc.8 q0, q0 - vst1.8 {q0}, [r0] + vst1.32 {q0}, [r0] bx lr ENDPROC(ce_aes_invert) diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index e4139a0b0d75..36d1a5301284 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -77,21 +78,17 @@ static int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, key_len != AES_KEYSIZE_256) return -EINVAL; - memcpy(ctx->key_enc, in_key, key_len); ctx->key_length = key_len; + for (i = 0; i < kwords; i++) + ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32)); kernel_neon_begin(); for (i = 0; i < sizeof(rcon); i++) { u32 *rki = ctx->key_enc + (i * kwords); u32 *rko = rki + kwords; -#ifndef CONFIG_CPU_BIG_ENDIAN rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8); rko[0] = rko[0] ^ rki[0] ^ rcon[i]; -#else - rko[0] = rol32(ce_aes_sub(rki[kwords - 1]), 8); - rko[0] = rko[0] ^ rki[0] ^ (rcon[i] << 24); -#endif rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; -- GitLab From 5eedf315f27d3990f4d00c7cd3b9751e184a83b1 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:38 +0200 Subject: [PATCH 0788/7155] crypto: arm/aes-ce - provide a synchronous version of ctr(aes) AES in CTR mode is used by modes such as GCM and CCM, which are often used in contexts where only synchronous ciphers are permitted. So provide a synchronous version of ctr(aes) based on the existing code. This requires a non-SIMD fallback to deal with invocations occurring from a context where SIMD instructions may not be used. We have a helper for this now in the AES library, so wire that up. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-ce-glue.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index 36d1a5301284..a7265d0a7063 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -286,6 +288,29 @@ static int ctr_encrypt(struct skcipher_request *req) return err; } +static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) +{ + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + unsigned long flags; + + /* + * Temporarily disable interrupts to avoid races where + * cachelines are evicted when the CPU is interrupted + * to do something else. + */ + local_irq_save(flags); + aes_encrypt(ctx, dst, src); + local_irq_restore(flags); +} + +static int ctr_encrypt_sync(struct skcipher_request *req) +{ + if (!crypto_simd_usable()) + return crypto_ctr_encrypt_walk(req, ctr_encrypt_one); + + return ctr_encrypt(req); +} + static int xts_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -375,6 +400,21 @@ static struct skcipher_alg aes_algs[] = { { .setkey = ce_aes_setkey, .encrypt = ctr_encrypt, .decrypt = ctr_encrypt, +}, { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "ctr-aes-ce-sync", + .base.cra_priority = 300 - 1, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct crypto_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .chunksize = AES_BLOCK_SIZE, + .setkey = ce_aes_setkey, + .encrypt = ctr_encrypt_sync, + .decrypt = ctr_encrypt_sync, }, { .base.cra_name = "__xts(aes)", .base.cra_driver_name = "__xts-aes-ce", @@ -418,6 +458,9 @@ static int __init aes_init(void) return err; for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { + if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL)) + continue; + algname = aes_algs[i].base.cra_name + 2; drvname = aes_algs[i].base.cra_driver_name + 2; basename = aes_algs[i].base.cra_driver_name; -- GitLab From e5f050402f1870317826990e968493e4411a0d53 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:39 +0200 Subject: [PATCH 0789/7155] crypto: arm/aes-neonbs - provide a synchronous version of ctr(aes) AES in CTR mode is used by modes such as GCM and CCM, which are often used in contexts where only synchronous ciphers are permitted. So provide a synchronous version of ctr(aes) based on the existing code. This requires a non-SIMD fallback to deal with invocations occurring from a context where SIMD instructions may not be used. We have a helper for this now in the AES library, so wire that up. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-neonbs-glue.c | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index 8c22d10bd909..45cd9818791e 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -6,8 +6,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -54,6 +56,11 @@ struct aesbs_xts_ctx { struct crypto_cipher *tweak_tfm; }; +struct aesbs_ctr_ctx { + struct aesbs_ctx key; /* must be first member */ + struct crypto_aes_ctx fallback; +}; + static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { @@ -189,6 +196,25 @@ static void cbc_exit(struct crypto_tfm *tfm) crypto_free_cipher(ctx->enc_tfm); } +static int aesbs_ctr_setkey_sync(struct crypto_skcipher *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); + int err; + + err = aes_expandkey(&ctx->fallback, in_key, key_len); + if (err) + return err; + + ctx->key.rounds = 6 + key_len / 4; + + kernel_neon_begin(); + aesbs_convert_key(ctx->key.rk, ctx->fallback.key_enc, ctx->key.rounds); + kernel_neon_end(); + + return 0; +} + static int ctr_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -231,6 +257,29 @@ static int ctr_encrypt(struct skcipher_request *req) return err; } +static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) +{ + struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); + unsigned long flags; + + /* + * Temporarily disable interrupts to avoid races where + * cachelines are evicted when the CPU is interrupted + * to do something else. + */ + local_irq_save(flags); + aes_encrypt(&ctx->fallback, dst, src); + local_irq_restore(flags); +} + +static int ctr_encrypt_sync(struct skcipher_request *req) +{ + if (!crypto_simd_usable()) + return crypto_ctr_encrypt_walk(req, ctr_encrypt_one); + + return ctr_encrypt(req); +} + static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { @@ -358,6 +407,22 @@ static struct skcipher_alg aes_algs[] = { { .setkey = aesbs_setkey, .encrypt = ctr_encrypt, .decrypt = ctr_encrypt, +}, { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "ctr-aes-neonbs-sync", + .base.cra_priority = 250 - 1, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct aesbs_ctr_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .chunksize = AES_BLOCK_SIZE, + .walksize = 8 * AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = aesbs_ctr_setkey_sync, + .encrypt = ctr_encrypt_sync, + .decrypt = ctr_encrypt_sync, }, { .base.cra_name = "__xts(aes)", .base.cra_driver_name = "__xts-aes-neonbs", -- GitLab From 0a5dff9882e56f80ff021e039aee93e167f16b9e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:40 +0200 Subject: [PATCH 0790/7155] crypto: arm/ghash - provide a synchronous version GHASH is used by the GCM mode, which is often used in contexts where only synchronous ciphers are permitted. So provide a synchronous version of GHASH based on the existing code. This requires a non-SIMD fallback to deal with invocations occurring from a context where SIMD instructions may not be used. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/ghash-ce-glue.c | 78 ++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c index 52d472a050e6..bb906b5f1eb3 100644 --- a/arch/arm/crypto/ghash-ce-glue.c +++ b/arch/arm/crypto/ghash-ce-glue.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ struct ghash_key { u64 h2[2]; u64 h3[2]; u64 h4[2]; + + be128 k; }; struct ghash_desc_ctx { @@ -62,6 +65,36 @@ static int ghash_init(struct shash_desc *desc) return 0; } +static void ghash_do_update(int blocks, u64 dg[], const char *src, + struct ghash_key *key, const char *head) +{ + if (likely(crypto_simd_usable())) { + kernel_neon_begin(); + pmull_ghash_update(blocks, dg, src, key, head); + kernel_neon_end(); + } else { + be128 dst = { cpu_to_be64(dg[1]), cpu_to_be64(dg[0]) }; + + do { + const u8 *in = src; + + if (head) { + in = head; + blocks++; + head = NULL; + } else { + src += GHASH_BLOCK_SIZE; + } + + crypto_xor((u8 *)&dst, in, GHASH_BLOCK_SIZE); + gf128mul_lle(&dst, &key->k); + } while (--blocks); + + dg[0] = be64_to_cpu(dst.b); + dg[1] = be64_to_cpu(dst.a); + } +} + static int ghash_update(struct shash_desc *desc, const u8 *src, unsigned int len) { @@ -85,10 +118,8 @@ static int ghash_update(struct shash_desc *desc, const u8 *src, blocks = len / GHASH_BLOCK_SIZE; len %= GHASH_BLOCK_SIZE; - kernel_neon_begin(); - pmull_ghash_update(blocks, ctx->digest, src, key, - partial ? ctx->buf : NULL); - kernel_neon_end(); + ghash_do_update(blocks, ctx->digest, src, key, + partial ? ctx->buf : NULL); src += blocks * GHASH_BLOCK_SIZE; partial = 0; } @@ -106,9 +137,7 @@ static int ghash_final(struct shash_desc *desc, u8 *dst) struct ghash_key *key = crypto_shash_ctx(desc->tfm); memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial); - kernel_neon_begin(); - pmull_ghash_update(1, ctx->digest, ctx->buf, key, NULL); - kernel_neon_end(); + ghash_do_update(1, ctx->digest, ctx->buf, key, NULL); } put_unaligned_be64(ctx->digest[1], dst); put_unaligned_be64(ctx->digest[0], dst + 8); @@ -132,24 +161,25 @@ static int ghash_setkey(struct crypto_shash *tfm, const u8 *inkey, unsigned int keylen) { struct ghash_key *key = crypto_shash_ctx(tfm); - be128 h, k; + be128 h; if (keylen != GHASH_BLOCK_SIZE) { crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } - memcpy(&k, inkey, GHASH_BLOCK_SIZE); - ghash_reflect(key->h, &k); + /* needed for the fallback */ + memcpy(&key->k, inkey, GHASH_BLOCK_SIZE); + ghash_reflect(key->h, &key->k); - h = k; - gf128mul_lle(&h, &k); + h = key->k; + gf128mul_lle(&h, &key->k); ghash_reflect(key->h2, &h); - gf128mul_lle(&h, &k); + gf128mul_lle(&h, &key->k); ghash_reflect(key->h3, &h); - gf128mul_lle(&h, &k); + gf128mul_lle(&h, &key->k); ghash_reflect(key->h4, &h); return 0; @@ -162,15 +192,13 @@ static struct shash_alg ghash_alg = { .final = ghash_final, .setkey = ghash_setkey, .descsize = sizeof(struct ghash_desc_ctx), - .base = { - .cra_name = "__ghash", - .cra_driver_name = "__driver-ghash-ce", - .cra_priority = 0, - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = GHASH_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct ghash_key), - .cra_module = THIS_MODULE, - }, + + .base.cra_name = "ghash", + .base.cra_driver_name = "ghash-ce-sync", + .base.cra_priority = 300 - 1, + .base.cra_blocksize = GHASH_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct ghash_key), + .base.cra_module = THIS_MODULE, }; static int ghash_async_init(struct ahash_request *req) @@ -285,9 +313,7 @@ static int ghash_async_init_tfm(struct crypto_tfm *tfm) struct cryptd_ahash *cryptd_tfm; struct ghash_async_ctx *ctx = crypto_tfm_ctx(tfm); - cryptd_tfm = cryptd_alloc_ahash("__driver-ghash-ce", - CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL); + cryptd_tfm = cryptd_alloc_ahash("ghash-ce-sync", 0, 0); if (IS_ERR(cryptd_tfm)) return PTR_ERR(cryptd_tfm); ctx->cryptd_tfm = cryptd_tfm; -- GitLab From 28a220aac596ff37b564b2d6dd6a9b7e2be29217 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:41 +0200 Subject: [PATCH 0791/7155] bluetooth: switch to AES library The bluetooth code uses a bare AES cipher for the encryption operations. Given that it carries out a set_key() operation right before every encryption operation, this is clearly not a hot path, and so the use of the cipher interface (which provides the best implementation available on the system) is not really required. In fact, when using a cipher like AES-NI or AES-CE, both the set_key() and the encrypt() operations involve en/disabling preemption as well as stacking and unstacking the SIMD context, and this is most certainly not worth it for encrypting 16 bytes of data. So let's switch to the new lightweight library interface instead. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- net/bluetooth/Kconfig | 3 +- net/bluetooth/smp.c | 103 +++++++++++++----------------------------- 2 files changed, 33 insertions(+), 73 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 2efac049ad4c..3803135c88ff 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -10,7 +10,8 @@ menuconfig BT select CRC16 select CRYPTO select CRYPTO_BLKCIPHER - select CRYPTO_AES + select CRYPTO_LIB_AES + imply CRYPTO_AES select CRYPTO_CMAC select CRYPTO_ECB select CRYPTO_SHA256 diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 6c2b4e6e87ba..26e8cfad22b8 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -88,7 +89,6 @@ struct smp_dev { u8 local_rand[16]; bool debug_key; - struct crypto_cipher *tfm_aes; struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; }; @@ -127,7 +127,6 @@ struct smp_chan { u8 dhkey[32]; u8 mackey[16]; - struct crypto_cipher *tfm_aes; struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; }; @@ -377,22 +376,18 @@ static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16], * s1 and ah. */ -static int smp_e(struct crypto_cipher *tfm, const u8 *k, u8 *r) +static int smp_e(const u8 *k, u8 *r) { + struct crypto_aes_ctx ctx; uint8_t tmp[16], data[16]; int err; SMP_DBG("k %16phN r %16phN", k, r); - if (!tfm) { - BT_ERR("tfm %p", tfm); - return -EINVAL; - } - /* The most significant octet of key corresponds to k[0] */ swap_buf(k, tmp, 16); - err = crypto_cipher_setkey(tfm, tmp, 16); + err = aes_expandkey(&ctx, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; @@ -401,17 +396,18 @@ static int smp_e(struct crypto_cipher *tfm, const u8 *k, u8 *r) /* Most significant octet of plaintextData corresponds to data[0] */ swap_buf(r, data, 16); - crypto_cipher_encrypt_one(tfm, data, data); + aes_encrypt(&ctx, data, data); /* Most significant octet of encryptedData corresponds to data[0] */ swap_buf(data, r, 16); SMP_DBG("r %16phN", r); + memzero_explicit(&ctx, sizeof (ctx)); return err; } -static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16], +static int smp_c1(const u8 k[16], const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat, const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16]) { @@ -436,7 +432,7 @@ static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16], u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); /* res = e(k, res) */ - err = smp_e(tfm_aes, k, res); + err = smp_e(k, res); if (err) { BT_ERR("Encrypt data error"); return err; @@ -453,14 +449,14 @@ static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16], u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); /* res = e(k, res) */ - err = smp_e(tfm_aes, k, res); + err = smp_e(k, res); if (err) BT_ERR("Encrypt data error"); return err; } -static int smp_s1(struct crypto_cipher *tfm_aes, const u8 k[16], +static int smp_s1(const u8 k[16], const u8 r1[16], const u8 r2[16], u8 _r[16]) { int err; @@ -469,15 +465,14 @@ static int smp_s1(struct crypto_cipher *tfm_aes, const u8 k[16], memcpy(_r, r2, 8); memcpy(_r + 8, r1, 8); - err = smp_e(tfm_aes, k, _r); + err = smp_e(k, _r); if (err) BT_ERR("Encrypt data error"); return err; } -static int smp_ah(struct crypto_cipher *tfm, const u8 irk[16], - const u8 r[3], u8 res[3]) +static int smp_ah(const u8 irk[16], const u8 r[3], u8 res[3]) { u8 _res[16]; int err; @@ -486,7 +481,7 @@ static int smp_ah(struct crypto_cipher *tfm, const u8 irk[16], memcpy(_res, r, 3); memset(_res + 3, 0, 13); - err = smp_e(tfm, irk, _res); + err = smp_e(irk, _res); if (err) { BT_ERR("Encrypt error"); return err; @@ -518,7 +513,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk); - err = smp_ah(smp->tfm_aes, irk, &bdaddr->b[3], hash); + err = smp_ah(irk, &bdaddr->b[3], hash); if (err) return false; @@ -541,7 +536,7 @@ int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) rpa->b[5] &= 0x3f; /* Clear two most significant bits */ rpa->b[5] |= 0x40; /* Set second most significant bit */ - err = smp_ah(smp->tfm_aes, irk, &rpa->b[3], rpa->b); + err = smp_ah(irk, &rpa->b[3], rpa->b); if (err < 0) return err; @@ -768,7 +763,6 @@ static void smp_chan_destroy(struct l2cap_conn *conn) kzfree(smp->slave_csrk); kzfree(smp->link_key); - crypto_free_cipher(smp->tfm_aes); crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); @@ -957,7 +951,7 @@ static u8 smp_confirm(struct smp_chan *smp) BT_DBG("conn %p", conn); - ret = smp_c1(smp->tfm_aes, smp->tk, smp->prnd, smp->preq, smp->prsp, + ret = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp, conn->hcon->init_addr_type, &conn->hcon->init_addr, conn->hcon->resp_addr_type, &conn->hcon->resp_addr, cp.confirm_val); @@ -983,12 +977,9 @@ static u8 smp_random(struct smp_chan *smp) u8 confirm[16]; int ret; - if (IS_ERR_OR_NULL(smp->tfm_aes)) - return SMP_UNSPECIFIED; - BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); - ret = smp_c1(smp->tfm_aes, smp->tk, smp->rrnd, smp->preq, smp->prsp, + ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, hcon->init_addr_type, &hcon->init_addr, hcon->resp_addr_type, &hcon->resp_addr, confirm); if (ret) @@ -1005,7 +996,7 @@ static u8 smp_random(struct smp_chan *smp) __le64 rand = 0; __le16 ediv = 0; - smp_s1(smp->tfm_aes, smp->tk, smp->rrnd, smp->prnd, stk); + smp_s1(smp->tk, smp->rrnd, smp->prnd, stk); if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) return SMP_UNSPECIFIED; @@ -1021,7 +1012,7 @@ static u8 smp_random(struct smp_chan *smp) smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), smp->prnd); - smp_s1(smp->tfm_aes, smp->tk, smp->prnd, smp->rrnd, stk); + smp_s1(smp->tk, smp->prnd, smp->rrnd, stk); if (hcon->pending_sec_level == BT_SECURITY_HIGH) auth = 1; @@ -1389,16 +1380,10 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) if (!smp) return NULL; - smp->tfm_aes = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(smp->tfm_aes)) { - BT_ERR("Unable to create AES crypto context"); - goto zfree_smp; - } - smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(smp->tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - goto free_cipher; + goto zfree_smp; } smp->tfm_ecdh = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); @@ -1420,8 +1405,6 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) free_shash: crypto_free_shash(smp->tfm_cmac); -free_cipher: - crypto_free_cipher(smp->tfm_aes); zfree_smp: kzfree(smp); return NULL; @@ -3232,7 +3215,6 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) { struct l2cap_chan *chan; struct smp_dev *smp; - struct crypto_cipher *tfm_aes; struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; @@ -3245,17 +3227,9 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) if (!smp) return ERR_PTR(-ENOMEM); - tfm_aes = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(tfm_aes)) { - BT_ERR("Unable to create AES crypto context"); - kzfree(smp); - return ERR_CAST(tfm_aes); - } - tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - crypto_free_cipher(tfm_aes); kzfree(smp); return ERR_CAST(tfm_cmac); } @@ -3264,13 +3238,11 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) if (IS_ERR(tfm_ecdh)) { BT_ERR("Unable to create ECDH crypto context"); crypto_free_shash(tfm_cmac); - crypto_free_cipher(tfm_aes); kzfree(smp); return ERR_CAST(tfm_ecdh); } smp->local_oob = false; - smp->tfm_aes = tfm_aes; smp->tfm_cmac = tfm_cmac; smp->tfm_ecdh = tfm_ecdh; @@ -3278,7 +3250,6 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) chan = l2cap_chan_create(); if (!chan) { if (smp) { - crypto_free_cipher(smp->tfm_aes); crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); kzfree(smp); @@ -3326,7 +3297,6 @@ static void smp_del_chan(struct l2cap_chan *chan) smp = chan->data; if (smp) { chan->data = NULL; - crypto_free_cipher(smp->tfm_aes); crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); kzfree(smp); @@ -3582,7 +3552,7 @@ static int __init test_debug_key(struct crypto_kpp *tfm_ecdh) return 0; } -static int __init test_ah(struct crypto_cipher *tfm_aes) +static int __init test_ah(void) { const u8 irk[16] = { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, @@ -3592,7 +3562,7 @@ static int __init test_ah(struct crypto_cipher *tfm_aes) u8 res[3]; int err; - err = smp_ah(tfm_aes, irk, r, res); + err = smp_ah(irk, r, res); if (err) return err; @@ -3602,7 +3572,7 @@ static int __init test_ah(struct crypto_cipher *tfm_aes) return 0; } -static int __init test_c1(struct crypto_cipher *tfm_aes) +static int __init test_c1(void) { const u8 k[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3622,7 +3592,7 @@ static int __init test_c1(struct crypto_cipher *tfm_aes) u8 res[16]; int err; - err = smp_c1(tfm_aes, k, r, preq, pres, _iat, &ia, _rat, &ra, res); + err = smp_c1(k, r, preq, pres, _iat, &ia, _rat, &ra, res); if (err) return err; @@ -3632,7 +3602,7 @@ static int __init test_c1(struct crypto_cipher *tfm_aes) return 0; } -static int __init test_s1(struct crypto_cipher *tfm_aes) +static int __init test_s1(void) { const u8 k[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3647,7 +3617,7 @@ static int __init test_s1(struct crypto_cipher *tfm_aes) u8 res[16]; int err; - err = smp_s1(tfm_aes, k, r1, r2, res); + err = smp_s1(k, r1, r2, res); if (err) return err; @@ -3828,8 +3798,7 @@ static const struct file_operations test_smp_fops = { .llseek = default_llseek, }; -static int __init run_selftests(struct crypto_cipher *tfm_aes, - struct crypto_shash *tfm_cmac, +static int __init run_selftests(struct crypto_shash *tfm_cmac, struct crypto_kpp *tfm_ecdh) { ktime_t calltime, delta, rettime; @@ -3844,19 +3813,19 @@ static int __init run_selftests(struct crypto_cipher *tfm_aes, goto done; } - err = test_ah(tfm_aes); + err = test_ah(); if (err) { BT_ERR("smp_ah test failed"); goto done; } - err = test_c1(tfm_aes); + err = test_c1(); if (err) { BT_ERR("smp_c1 test failed"); goto done; } - err = test_s1(tfm_aes); + err = test_s1(); if (err) { BT_ERR("smp_s1 test failed"); goto done; @@ -3913,21 +3882,13 @@ static int __init run_selftests(struct crypto_cipher *tfm_aes, int __init bt_selftest_smp(void) { - struct crypto_cipher *tfm_aes; struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; int err; - tfm_aes = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(tfm_aes)) { - BT_ERR("Unable to create AES crypto context"); - return PTR_ERR(tfm_aes); - } - tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - crypto_free_cipher(tfm_aes); return PTR_ERR(tfm_cmac); } @@ -3935,14 +3896,12 @@ int __init bt_selftest_smp(void) if (IS_ERR(tfm_ecdh)) { BT_ERR("Unable to create ECDH crypto context"); crypto_free_shash(tfm_cmac); - crypto_free_cipher(tfm_aes); return PTR_ERR(tfm_ecdh); } - err = run_selftests(tfm_aes, tfm_cmac, tfm_ecdh); + err = run_selftests(tfm_cmac, tfm_ecdh); crypto_free_shash(tfm_cmac); - crypto_free_cipher(tfm_aes); crypto_free_kpp(tfm_ecdh); return err; -- GitLab From da3e7a9715ea041299a9e1eae1e73405b110a333 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:42 +0200 Subject: [PATCH 0792/7155] crypto: amcc - switch to AES library for GCM key derivation The AMCC code for GCM key derivation allocates a AES cipher to perform a single block encryption. So let's switch to the new and more lightweight AES library instead. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- drivers/crypto/amcc/crypto4xx_alg.c | 24 ++++++++---------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 72d6c2ca0809..69d1bbd5d9bf 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -312,7 +312,7 @@ config CRYPTO_DEV_PPC4XX depends on PPC && 4xx select CRYPTO_HASH select CRYPTO_AEAD - select CRYPTO_AES + select CRYPTO_LIB_AES select CRYPTO_CCM select CRYPTO_CTR select CRYPTO_GCM diff --git a/drivers/crypto/amcc/crypto4xx_alg.c b/drivers/crypto/amcc/crypto4xx_alg.c index cbfc607282f4..a42f8619589d 100644 --- a/drivers/crypto/amcc/crypto4xx_alg.c +++ b/drivers/crypto/amcc/crypto4xx_alg.c @@ -527,28 +527,20 @@ static int crypto4xx_aes_gcm_validate_keylen(unsigned int keylen) static int crypto4xx_compute_gcm_hash_key_sw(__le32 *hash_start, const u8 *key, unsigned int keylen) { - struct crypto_cipher *aes_tfm = NULL; + struct crypto_aes_ctx ctx; uint8_t src[16] = { 0 }; - int rc = 0; - - aes_tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(aes_tfm)) { - rc = PTR_ERR(aes_tfm); - pr_warn("could not load aes cipher driver: %d\n", rc); - return rc; - } + int rc; - rc = crypto_cipher_setkey(aes_tfm, key, keylen); + rc = aes_expandkey(&ctx, key, keylen); if (rc) { - pr_err("setkey() failed: %d\n", rc); - goto out; + pr_err("aes_expandkey() failed: %d\n", rc); + return rc; } - crypto_cipher_encrypt_one(aes_tfm, src, src); + aes_encrypt(&ctx, src, src); crypto4xx_memcpy_to_le32(hash_start, src, 16); -out: - crypto_free_cipher(aes_tfm); - return rc; + memzero_explicit(&ctx, sizeof(ctx)); + return 0; } int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher, -- GitLab From 6273fd7a5a99549bc5b90ce8a70df88cc6b570c3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:43 +0200 Subject: [PATCH 0793/7155] crypto: ccp - move to AES library for CMAC key derivation Use the AES library instead of the cipher interface to perform the single block of AES processing involved in updating the key of the cmac(aes) hash. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/ccp/Kconfig | 1 + drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 25 ++++-------------------- drivers/crypto/ccp/ccp-crypto.h | 3 --- 3 files changed, 5 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig index 48f3edc1e3fb..ce1c47286fc6 100644 --- a/drivers/crypto/ccp/Kconfig +++ b/drivers/crypto/ccp/Kconfig @@ -30,6 +30,7 @@ config CRYPTO_DEV_CCP_CRYPTO select CRYPTO_BLKCIPHER select CRYPTO_AUTHENC select CRYPTO_RSA + select CRYPTO_LIB_AES help Support for using the cryptographic API with the AMD Cryptographic Coprocessor. This module supports offload of SHA and AES algorithms. diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index bb7219d36b2c..32f19f402073 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -261,6 +261,7 @@ static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo; u64 rb_hi = 0x00, rb_lo = 0x87; + struct crypto_aes_ctx aes; __be64 *gk; int ret; @@ -284,14 +285,14 @@ static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ctx->u.aes.key_len = 0; /* Set the key for the AES cipher used to generate the keys */ - ret = crypto_cipher_setkey(ctx->u.aes.tfm_cipher, key, key_len); + ret = aes_expandkey(&aes, key, key_len); if (ret) return ret; /* Encrypt a block of zeroes - use key area in context */ memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); - crypto_cipher_encrypt_one(ctx->u.aes.tfm_cipher, ctx->u.aes.key, - ctx->u.aes.key); + aes_encrypt(&aes, ctx->u.aes.key, ctx->u.aes.key); + memzero_explicit(&aes, sizeof(aes)); /* Generate K1 and K2 */ k0_hi = be64_to_cpu(*((__be64 *)ctx->u.aes.key)); @@ -336,32 +337,15 @@ static int ccp_aes_cmac_cra_init(struct crypto_tfm *tfm) { struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); - struct crypto_cipher *cipher_tfm; ctx->complete = ccp_aes_cmac_complete; ctx->u.aes.key_len = 0; crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_aes_cmac_req_ctx)); - cipher_tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(cipher_tfm)) { - pr_warn("could not load aes cipher driver\n"); - return PTR_ERR(cipher_tfm); - } - ctx->u.aes.tfm_cipher = cipher_tfm; - return 0; } -static void ccp_aes_cmac_cra_exit(struct crypto_tfm *tfm) -{ - struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); - - if (ctx->u.aes.tfm_cipher) - crypto_free_cipher(ctx->u.aes.tfm_cipher); - ctx->u.aes.tfm_cipher = NULL; -} - int ccp_register_aes_cmac_algs(struct list_head *head) { struct ccp_crypto_ahash_alg *ccp_alg; @@ -401,7 +385,6 @@ int ccp_register_aes_cmac_algs(struct list_head *head) base->cra_ctxsize = sizeof(struct ccp_ctx); base->cra_priority = CCP_CRA_PRIORITY; base->cra_init = ccp_aes_cmac_cra_init; - base->cra_exit = ccp_aes_cmac_cra_exit; base->cra_module = THIS_MODULE; ret = crypto_register_ahash(alg); diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 622b34c17643..25409cea8465 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -87,9 +87,6 @@ struct ccp_aes_ctx { /* Fallback cipher for XTS with unsupported unit sizes */ struct crypto_sync_skcipher *tfm_skcipher; - /* Cipher used to generate CMAC K1/K2 keys */ - struct crypto_cipher *tfm_cipher; - enum ccp_engine engine; enum ccp_aes_type type; enum ccp_aes_mode mode; -- GitLab From 571c47ab98ad8c85e44b28f2f0c41b0e27312a9b Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:44 +0200 Subject: [PATCH 0794/7155] crypto: chelsio - replace AES cipher calls with library calls Replace a couple of occurrences where the "aes-generic" cipher is instantiated explicitly and only used for encryption of a single block. Use AES library calls instead. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/chelsio/Kconfig | 1 + drivers/crypto/chelsio/chcr_algo.c | 46 +++++++------------------ drivers/crypto/chelsio/chcr_crypto.h | 1 - drivers/crypto/chelsio/chcr_ipsec.c | 19 ++++------ drivers/crypto/chelsio/chtls/chtls_hw.c | 20 ++++------- 5 files changed, 26 insertions(+), 61 deletions(-) diff --git a/drivers/crypto/chelsio/Kconfig b/drivers/crypto/chelsio/Kconfig index 4b9b37a130d3..250150560e68 100644 --- a/drivers/crypto/chelsio/Kconfig +++ b/drivers/crypto/chelsio/Kconfig @@ -2,6 +2,7 @@ config CRYPTO_DEV_CHELSIO tristate "Chelsio Crypto Co-processor Driver" depends on CHELSIO_T4 + select CRYPTO_LIB_AES select CRYPTO_SHA1 select CRYPTO_SHA256 select CRYPTO_SHA512 diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index 177f572b9589..38ee38b37ae6 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -1023,22 +1023,21 @@ static int chcr_update_tweak(struct ablkcipher_request *req, u8 *iv, struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); struct chcr_blkcipher_req_ctx *reqctx = ablkcipher_request_ctx(req); - struct crypto_cipher *cipher; + struct crypto_aes_ctx aes; int ret, i; u8 *key; unsigned int keylen; int round = reqctx->last_req_len / AES_BLOCK_SIZE; int round8 = round / 8; - cipher = ablkctx->aes_generic; memcpy(iv, reqctx->iv, AES_BLOCK_SIZE); keylen = ablkctx->enckey_len / 2; key = ablkctx->key + keylen; - ret = crypto_cipher_setkey(cipher, key, keylen); + ret = aes_expandkey(&aes, key, keylen); if (ret) - goto out; - crypto_cipher_encrypt_one(cipher, iv, iv); + return ret; + aes_encrypt(&aes, iv, iv); for (i = 0; i < round8; i++) gf128mul_x8_ble((le128 *)iv, (le128 *)iv); @@ -1046,9 +1045,10 @@ static int chcr_update_tweak(struct ablkcipher_request *req, u8 *iv, gf128mul_x_ble((le128 *)iv, (le128 *)iv); if (!isfinal) - crypto_cipher_decrypt_one(cipher, iv, iv); -out: - return ret; + aes_decrypt(&aes, iv, iv); + + memzero_explicit(&aes, sizeof(aes)); + return 0; } static int chcr_update_cipher_iv(struct ablkcipher_request *req, @@ -1411,16 +1411,6 @@ static int chcr_cra_init(struct crypto_tfm *tfm) return PTR_ERR(ablkctx->sw_cipher); } - if (get_cryptoalg_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_XTS) { - /* To update tweak*/ - ablkctx->aes_generic = crypto_alloc_cipher("aes-generic", 0, 0); - if (IS_ERR(ablkctx->aes_generic)) { - pr_err("failed to allocate aes cipher for tweak\n"); - return PTR_ERR(ablkctx->aes_generic); - } - } else - ablkctx->aes_generic = NULL; - tfm->crt_ablkcipher.reqsize = sizeof(struct chcr_blkcipher_req_ctx); return chcr_device_init(crypto_tfm_ctx(tfm)); } @@ -1451,8 +1441,6 @@ static void chcr_cra_exit(struct crypto_tfm *tfm) struct ablk_ctx *ablkctx = ABLK_CTX(ctx); crypto_free_sync_skcipher(ablkctx->sw_cipher); - if (ablkctx->aes_generic) - crypto_free_cipher(ablkctx->aes_generic); } static int get_alg_config(struct algo_param *params, @@ -3364,9 +3352,9 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, { struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx); - struct crypto_cipher *cipher; unsigned int ck_size; int ret = 0, key_ctx_size = 0; + struct crypto_aes_ctx aes; aeadctx->enckey_len = 0; crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); @@ -3409,23 +3397,15 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - cipher = crypto_alloc_cipher("aes-generic", 0, 0); - if (IS_ERR(cipher)) { - aeadctx->enckey_len = 0; - ret = -ENOMEM; - goto out; - } - - ret = crypto_cipher_setkey(cipher, key, keylen); + ret = aes_expandkey(&aes, key, keylen); if (ret) { aeadctx->enckey_len = 0; - goto out1; + goto out; } memset(gctx->ghash_h, 0, AEAD_H_SIZE); - crypto_cipher_encrypt_one(cipher, gctx->ghash_h, gctx->ghash_h); + aes_encrypt(&aes, gctx->ghash_h, gctx->ghash_h); + memzero_explicit(&aes, sizeof(aes)); -out1: - crypto_free_cipher(cipher); out: return ret; } diff --git a/drivers/crypto/chelsio/chcr_crypto.h b/drivers/crypto/chelsio/chcr_crypto.h index 655606f2e4d0..993c97e70565 100644 --- a/drivers/crypto/chelsio/chcr_crypto.h +++ b/drivers/crypto/chelsio/chcr_crypto.h @@ -172,7 +172,6 @@ static inline struct chcr_context *h_ctx(struct crypto_ahash *tfm) struct ablk_ctx { struct crypto_sync_skcipher *sw_cipher; - struct crypto_cipher *aes_generic; __be32 key_ctx_hdr; unsigned int enckey_len; unsigned char ciph_mode; diff --git a/drivers/crypto/chelsio/chcr_ipsec.c b/drivers/crypto/chelsio/chcr_ipsec.c index f429aae72542..24355680f30a 100644 --- a/drivers/crypto/chelsio/chcr_ipsec.c +++ b/drivers/crypto/chelsio/chcr_ipsec.c @@ -132,11 +132,11 @@ static inline int chcr_ipsec_setauthsize(struct xfrm_state *x, static inline int chcr_ipsec_setkey(struct xfrm_state *x, struct ipsec_sa_entry *sa_entry) { - struct crypto_cipher *cipher; int keylen = (x->aead->alg_key_len + 7) / 8; unsigned char *key = x->aead->alg_key; int ck_size, key_ctx_size = 0; unsigned char ghash_h[AEAD_H_SIZE]; + struct crypto_aes_ctx aes; int ret = 0; if (keylen > 3) { @@ -170,26 +170,19 @@ static inline int chcr_ipsec_setkey(struct xfrm_state *x, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - cipher = crypto_alloc_cipher("aes-generic", 0, 0); - if (IS_ERR(cipher)) { - sa_entry->enckey_len = 0; - ret = -ENOMEM; - goto out; - } - - ret = crypto_cipher_setkey(cipher, key, keylen); + ret = aes_expandkey(&aes, key, keylen); if (ret) { sa_entry->enckey_len = 0; - goto out1; + goto out; } memset(ghash_h, 0, AEAD_H_SIZE); - crypto_cipher_encrypt_one(cipher, ghash_h, ghash_h); + aes_encrypt(&aes, ghash_h, ghash_h); + memzero_explicit(&aes, sizeof(aes)); + memcpy(sa_entry->key + (DIV_ROUND_UP(sa_entry->enckey_len, 16) * 16), ghash_h, AEAD_H_SIZE); sa_entry->kctx_len = ((DIV_ROUND_UP(sa_entry->enckey_len, 16)) << 4) + AEAD_H_SIZE; -out1: - crypto_free_cipher(cipher); out: return ret; } diff --git a/drivers/crypto/chelsio/chtls/chtls_hw.c b/drivers/crypto/chelsio/chtls/chtls_hw.c index f2424f4c5f78..2a34035d3cfb 100644 --- a/drivers/crypto/chelsio/chtls/chtls_hw.c +++ b/drivers/crypto/chelsio/chtls/chtls_hw.c @@ -213,8 +213,8 @@ static int chtls_key_info(struct chtls_sock *csk, unsigned char key[AES_KEYSIZE_128]; struct tls12_crypto_info_aes_gcm_128 *gcm_ctx; unsigned char ghash_h[AEAD_H_SIZE]; - struct crypto_cipher *cipher; int ck_size, key_ctx_size; + struct crypto_aes_ctx aes; int ret; gcm_ctx = (struct tls12_crypto_info_aes_gcm_128 *) @@ -234,18 +234,13 @@ static int chtls_key_info(struct chtls_sock *csk, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - cipher = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(cipher)) { - ret = -ENOMEM; - goto out; - } - - ret = crypto_cipher_setkey(cipher, key, keylen); + ret = aes_expandkey(&aes, key, keylen); if (ret) - goto out1; + return ret; memset(ghash_h, 0, AEAD_H_SIZE); - crypto_cipher_encrypt_one(cipher, ghash_h, ghash_h); + aes_encrypt(&aes, ghash_h, ghash_h); + memzero_explicit(&aes, sizeof(aes)); csk->tlshws.keylen = key_ctx_size; /* Copy the Key context */ @@ -269,10 +264,7 @@ static int chtls_key_info(struct chtls_sock *csk, /* erase key info from driver */ memset(gcm_ctx->key, 0, keylen); -out1: - crypto_free_cipher(cipher); -out: - return ret; + return 0; } static void chtls_set_scmd(struct chtls_sock *csk) -- GitLab From 1e25ca02a0619c10bc0eae975846926902381ce5 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:45 +0200 Subject: [PATCH 0795/7155] crypto: aes-generic - unexport last-round AES tables The versions of the AES lookup tables that are only used during the last round are never used outside of the driver, so there is no need to export their symbols. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/aes_generic.c | 6 ++---- include/crypto/aes.h | 2 -- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c index 426deb437f19..71a5c190d360 100644 --- a/crypto/aes_generic.c +++ b/crypto/aes_generic.c @@ -328,7 +328,7 @@ __visible const u32 crypto_ft_tab[4][256] ____cacheline_aligned = { } }; -__visible const u32 crypto_fl_tab[4][256] ____cacheline_aligned = { +static const u32 crypto_fl_tab[4][256] ____cacheline_aligned = { { 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5, @@ -856,7 +856,7 @@ __visible const u32 crypto_it_tab[4][256] ____cacheline_aligned = { } }; -__visible const u32 crypto_il_tab[4][256] ____cacheline_aligned = { +static const u32 crypto_il_tab[4][256] ____cacheline_aligned = { { 0x00000052, 0x00000009, 0x0000006a, 0x000000d5, 0x00000030, 0x00000036, 0x000000a5, 0x00000038, @@ -1121,9 +1121,7 @@ __visible const u32 crypto_il_tab[4][256] ____cacheline_aligned = { }; EXPORT_SYMBOL_GPL(crypto_ft_tab); -EXPORT_SYMBOL_GPL(crypto_fl_tab); EXPORT_SYMBOL_GPL(crypto_it_tab); -EXPORT_SYMBOL_GPL(crypto_il_tab); /** * crypto_aes_set_key - Set the AES key. diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 0a64a977f9b3..df8426fd8051 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -29,9 +29,7 @@ struct crypto_aes_ctx { }; extern const u32 crypto_ft_tab[4][256] ____cacheline_aligned; -extern const u32 crypto_fl_tab[4][256] ____cacheline_aligned; extern const u32 crypto_it_tab[4][256] ____cacheline_aligned; -extern const u32 crypto_il_tab[4][256] ____cacheline_aligned; int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len); -- GitLab From 9467a3150cf4afca638673e099af71e8c493a3a0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:46 +0200 Subject: [PATCH 0796/7155] crypto: lib/aes - export sbox and inverse sbox There are a few copies of the AES S-boxes floating around, so export the ones from the AES library so that we can reuse them in other modules. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- include/crypto/aes.h | 3 +++ lib/crypto/aes.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/include/crypto/aes.h b/include/crypto/aes.h index df8426fd8051..8e0f4cf948e5 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -67,4 +67,7 @@ void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); */ void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); +extern const u8 crypto_aes_sbox[]; +extern const u8 crypto_aes_inv_sbox[]; + #endif diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index 9928b23e0a8a..4e100af38c51 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -82,6 +82,12 @@ static volatile const u8 __cacheline_aligned aes_inv_sbox[] = { 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, }; +extern const u8 crypto_aes_sbox[256] __alias(aes_sbox); +extern const u8 crypto_aes_inv_sbox[256] __alias(aes_inv_sbox); + +EXPORT_SYMBOL(crypto_aes_sbox); +EXPORT_SYMBOL(crypto_aes_inv_sbox); + static u32 mul_by_x(u32 w) { u32 x = w & 0x7f7f7f7f; -- GitLab From 58144b8d03fca6209a5097e85bcd63a6a956e75f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:47 +0200 Subject: [PATCH 0797/7155] crypto: arm64/aes-neon - switch to shared AES Sboxes Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/aes-neon.S | 74 ++---------------------------------- 1 file changed, 3 insertions(+), 71 deletions(-) diff --git a/arch/arm64/crypto/aes-neon.S b/arch/arm64/crypto/aes-neon.S index 2bebccc73869..0cac5df6c901 100644 --- a/arch/arm64/crypto/aes-neon.S +++ b/arch/arm64/crypto/aes-neon.S @@ -49,7 +49,7 @@ /* do preload for encryption */ .macro enc_prepare, ignore0, ignore1, temp - prepare .LForward_Sbox, .LForward_ShiftRows, \temp + prepare crypto_aes_sbox, .LForward_ShiftRows, \temp .endm .macro enc_switch_key, ignore0, ignore1, temp @@ -58,7 +58,7 @@ /* do preload for decryption */ .macro dec_prepare, ignore0, ignore1, temp - prepare .LReverse_Sbox, .LReverse_ShiftRows, \temp + prepare crypto_aes_inv_sbox, .LReverse_ShiftRows, \temp .endm /* apply SubBytes transformation using the the preloaded Sbox */ @@ -234,75 +234,7 @@ #include "aes-modes.S" .section ".rodata", "a" - .align 6 -.LForward_Sbox: - .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 - .byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 - .byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 - .byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 - .byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc - .byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 - .byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a - .byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 - .byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 - .byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 - .byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b - .byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf - .byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 - .byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 - .byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 - .byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 - .byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 - .byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 - .byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 - .byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb - .byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c - .byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 - .byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 - .byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 - .byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 - .byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a - .byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e - .byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e - .byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 - .byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf - .byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 - .byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 - -.LReverse_Sbox: - .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 - .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb - .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 - .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb - .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d - .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e - .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 - .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 - .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 - .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 - .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda - .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 - .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a - .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 - .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 - .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b - .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea - .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 - .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 - .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e - .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 - .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b - .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 - .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 - .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 - .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f - .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d - .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef - .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 - .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 - .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 - .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - + .align 4 .LForward_ShiftRows: .octa 0x0b06010c07020d08030e09040f0a0500 -- GitLab From 8de6dd3386003a3fe4509304494061b3554fe516 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:48 +0200 Subject: [PATCH 0798/7155] crypto: arm/aes-cipher - switch to shared AES inverse Sbox Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-cipher-core.S | 40 +------------------------------ 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/arch/arm/crypto/aes-cipher-core.S b/arch/arm/crypto/aes-cipher-core.S index 4460ed05d6ff..472e56d09eea 100644 --- a/arch/arm/crypto/aes-cipher-core.S +++ b/arch/arm/crypto/aes-cipher-core.S @@ -219,43 +219,5 @@ ENDPROC(__aes_arm_encrypt) .align 5 ENTRY(__aes_arm_decrypt) - do_crypt iround, crypto_it_tab, __aes_arm_inverse_sbox, 0 + do_crypt iround, crypto_it_tab, crypto_aes_inv_sbox, 0 ENDPROC(__aes_arm_decrypt) - - .section ".rodata", "a" - .align L1_CACHE_SHIFT - .type __aes_arm_inverse_sbox, %object -__aes_arm_inverse_sbox: - .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 - .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb - .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 - .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb - .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d - .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e - .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 - .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 - .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 - .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 - .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda - .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 - .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a - .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 - .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 - .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b - .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea - .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 - .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 - .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e - .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 - .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b - .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 - .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 - .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 - .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f - .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d - .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef - .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 - .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 - .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 - .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - .size __aes_arm_inverse_sbox, . - __aes_arm_inverse_sbox -- GitLab From 642a88fbe94441de7f2c807263599d5ef61b70fb Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:49 +0200 Subject: [PATCH 0799/7155] crypto: arm64/aes-cipher - switch to shared AES inverse Sbox Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/aes-cipher-core.S | 40 +---------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/arch/arm64/crypto/aes-cipher-core.S b/arch/arm64/crypto/aes-cipher-core.S index f06df0d2080c..423d0aebc570 100644 --- a/arch/arm64/crypto/aes-cipher-core.S +++ b/arch/arm64/crypto/aes-cipher-core.S @@ -128,43 +128,5 @@ ENDPROC(__aes_arm64_encrypt) .align 5 ENTRY(__aes_arm64_decrypt) - do_crypt iround, crypto_it_tab, __aes_arm64_inverse_sbox, 0 + do_crypt iround, crypto_it_tab, crypto_aes_inv_sbox, 0 ENDPROC(__aes_arm64_decrypt) - - .section ".rodata", "a" - .align L1_CACHE_SHIFT - .type __aes_arm64_inverse_sbox, %object -__aes_arm64_inverse_sbox: - .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 - .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb - .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 - .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb - .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d - .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e - .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 - .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 - .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 - .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 - .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda - .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 - .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a - .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 - .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 - .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b - .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea - .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 - .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 - .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e - .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 - .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b - .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 - .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 - .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 - .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f - .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d - .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef - .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 - .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 - .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 - .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - .size __aes_arm64_inverse_sbox, . - __aes_arm64_inverse_sbox -- GitLab From b46033fdd25abb30b253cd283b551323b723a2db Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 2 Jul 2019 21:41:50 +0200 Subject: [PATCH 0800/7155] crypto: arm/aes-scalar - unexport en/decryption routines The scalar table based AES routines are not used by other drivers, so let's keep it that way and unexport the symbols. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-cipher-glue.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/crypto/aes-cipher-glue.c b/arch/arm/crypto/aes-cipher-glue.c index 6efb3c04353f..8cd00f56800e 100644 --- a/arch/arm/crypto/aes-cipher-glue.c +++ b/arch/arm/crypto/aes-cipher-glue.c @@ -11,10 +11,7 @@ #include asmlinkage void __aes_arm_encrypt(u32 *rk, int rounds, const u8 *in, u8 *out); -EXPORT_SYMBOL(__aes_arm_encrypt); - asmlinkage void __aes_arm_decrypt(u32 *rk, int rounds, const u8 *in, u8 *out); -EXPORT_SYMBOL(__aes_arm_decrypt); static void aes_arm_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { -- GitLab From f248caf9a5ccda733456baddb234bce7431152ba Mon Sep 17 00:00:00 2001 From: Hannah Pan Date: Tue, 2 Jul 2019 15:16:02 -0700 Subject: [PATCH 0801/7155] crypto: testmgr - add tests for lzo-rle Add self-tests for the lzo-rle algorithm. Signed-off-by: Hannah Pan Signed-off-by: Herbert Xu --- crypto/testmgr.c | 10 ++++++ crypto/testmgr.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 8ba1e75cd973..5fe90ea46319 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4740,6 +4740,16 @@ static const struct alg_test_desc alg_test_descs[] = { .decomp = __VECS(lzo_decomp_tv_template) } } + }, { + .alg = "lzo-rle", + .test = alg_test_comp, + .fips_allowed = 1, + .suite = { + .comp = { + .comp = __VECS(lzorle_comp_tv_template), + .decomp = __VECS(lzorle_decomp_tv_template) + } + } }, { .alg = "md4", .test = alg_test_hash, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 073bd2efafca..b743ca6d12cc 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -32454,6 +32454,86 @@ static const struct comp_testvec lzo_decomp_tv_template[] = { }, }; +static const struct comp_testvec lzorle_comp_tv_template[] = { + { + .inlen = 70, + .outlen = 59, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = "\x11\x01\x00\x0d\x4a\x6f\x69\x6e" + "\x20\x75\x73\x20\x6e\x6f\x77\x20" + "\x61\x6e\x64\x20\x73\x68\x61\x72" + "\x65\x20\x74\x68\x65\x20\x73\x6f" + "\x66\x74\x77\x70\x01\x32\x88\x00" + "\x0c\x65\x20\x74\x68\x65\x20\x73" + "\x6f\x66\x74\x77\x61\x72\x65\x20" + "\x11\x00\x00", + }, { + .inlen = 159, + .outlen = 133, + .input = "This document describes a compression method based on the LZO " + "compression algorithm. This document defines the application of " + "the LZO algorithm used in UBIFS.", + .output = "\x11\x01\x00\x2c\x54\x68\x69\x73" + "\x20\x64\x6f\x63\x75\x6d\x65\x6e" + "\x74\x20\x64\x65\x73\x63\x72\x69" + "\x62\x65\x73\x20\x61\x20\x63\x6f" + "\x6d\x70\x72\x65\x73\x73\x69\x6f" + "\x6e\x20\x6d\x65\x74\x68\x6f\x64" + "\x20\x62\x61\x73\x65\x64\x20\x6f" + "\x6e\x20\x74\x68\x65\x20\x4c\x5a" + "\x4f\x20\x2a\x8c\x00\x09\x61\x6c" + "\x67\x6f\x72\x69\x74\x68\x6d\x2e" + "\x20\x20\x2e\x54\x01\x03\x66\x69" + "\x6e\x65\x73\x20\x74\x06\x05\x61" + "\x70\x70\x6c\x69\x63\x61\x74\x76" + "\x0a\x6f\x66\x88\x02\x60\x09\x27" + "\xf0\x00\x0c\x20\x75\x73\x65\x64" + "\x20\x69\x6e\x20\x55\x42\x49\x46" + "\x53\x2e\x11\x00\x00", + }, +}; + +static const struct comp_testvec lzorle_decomp_tv_template[] = { + { + .inlen = 133, + .outlen = 159, + .input = "\x00\x2b\x54\x68\x69\x73\x20\x64" + "\x6f\x63\x75\x6d\x65\x6e\x74\x20" + "\x64\x65\x73\x63\x72\x69\x62\x65" + "\x73\x20\x61\x20\x63\x6f\x6d\x70" + "\x72\x65\x73\x73\x69\x6f\x6e\x20" + "\x6d\x65\x74\x68\x6f\x64\x20\x62" + "\x61\x73\x65\x64\x20\x6f\x6e\x20" + "\x74\x68\x65\x20\x4c\x5a\x4f\x2b" + "\x8c\x00\x0d\x61\x6c\x67\x6f\x72" + "\x69\x74\x68\x6d\x2e\x20\x20\x54" + "\x68\x69\x73\x2a\x54\x01\x02\x66" + "\x69\x6e\x65\x73\x94\x06\x05\x61" + "\x70\x70\x6c\x69\x63\x61\x74\x76" + "\x0a\x6f\x66\x88\x02\x60\x09\x27" + "\xf0\x00\x0c\x20\x75\x73\x65\x64" + "\x20\x69\x6e\x20\x55\x42\x49\x46" + "\x53\x2e\x11\x00\x00", + .output = "This document describes a compression method based on the LZO " + "compression algorithm. This document defines the application of " + "the LZO algorithm used in UBIFS.", + }, { + .inlen = 59, + .outlen = 70, + .input = "\x11\x01\x00\x0d\x4a\x6f\x69\x6e" + "\x20\x75\x73\x20\x6e\x6f\x77\x20" + "\x61\x6e\x64\x20\x73\x68\x61\x72" + "\x65\x20\x74\x68\x65\x20\x73\x6f" + "\x66\x74\x77\x70\x01\x32\x88\x00" + "\x0c\x65\x20\x74\x68\x65\x20\x73" + "\x6f\x66\x74\x77\x61\x72\x65\x20" + "\x11\x00\x00", + .output = "Join us now and share the software " + "Join us now and share the software ", + }, +}; + /* * Michael MIC test vectors from IEEE 802.11i */ -- GitLab From 5cb97700beaa005ceb2a127b6f53536a4544c9d8 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:06 +0200 Subject: [PATCH 0802/7155] crypto: morus - remove generic and x86 implementations MORUS was not selected as a winner in the CAESAR competition, which is not surprising since it is considered to be cryptographically broken [0]. (Note that this is not an implementation defect, but a flaw in the underlying algorithm). Since it is unlikely to be in use currently, let's remove it before we're stuck with it. [0] https://eprint.iacr.org/2019/172.pdf Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 13 - arch/x86/crypto/morus1280-avx2-asm.S | 619 --------- arch/x86/crypto/morus1280-avx2-glue.c | 62 - arch/x86/crypto/morus1280-sse2-asm.S | 893 ------------- arch/x86/crypto/morus1280-sse2-glue.c | 61 - arch/x86/crypto/morus1280_glue.c | 205 --- arch/x86/crypto/morus640-sse2-asm.S | 612 --------- arch/x86/crypto/morus640-sse2-glue.c | 61 - arch/x86/crypto/morus640_glue.c | 200 --- crypto/Kconfig | 56 - crypto/Makefile | 2 - crypto/morus1280.c | 542 -------- crypto/morus640.c | 533 -------- crypto/testmgr.c | 12 - crypto/testmgr.h | 1707 ------------------------- include/crypto/morus1280_glue.h | 97 -- include/crypto/morus640_glue.h | 97 -- include/crypto/morus_common.h | 18 - 18 files changed, 5790 deletions(-) delete mode 100644 arch/x86/crypto/morus1280-avx2-asm.S delete mode 100644 arch/x86/crypto/morus1280-avx2-glue.c delete mode 100644 arch/x86/crypto/morus1280-sse2-asm.S delete mode 100644 arch/x86/crypto/morus1280-sse2-glue.c delete mode 100644 arch/x86/crypto/morus1280_glue.c delete mode 100644 arch/x86/crypto/morus640-sse2-asm.S delete mode 100644 arch/x86/crypto/morus640-sse2-glue.c delete mode 100644 arch/x86/crypto/morus640_glue.c delete mode 100644 crypto/morus1280.c delete mode 100644 crypto/morus640.c delete mode 100644 include/crypto/morus1280_glue.h delete mode 100644 include/crypto/morus640_glue.h delete mode 100644 include/crypto/morus_common.h diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index b96a14e67ab0..6f1d825fbb09 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -39,12 +39,6 @@ obj-$(CONFIG_CRYPTO_AEGIS128_AESNI_SSE2) += aegis128-aesni.o obj-$(CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2) += aegis128l-aesni.o obj-$(CONFIG_CRYPTO_AEGIS256_AESNI_SSE2) += aegis256-aesni.o -obj-$(CONFIG_CRYPTO_MORUS640_GLUE) += morus640_glue.o -obj-$(CONFIG_CRYPTO_MORUS1280_GLUE) += morus1280_glue.o - -obj-$(CONFIG_CRYPTO_MORUS640_SSE2) += morus640-sse2.o -obj-$(CONFIG_CRYPTO_MORUS1280_SSE2) += morus1280-sse2.o - obj-$(CONFIG_CRYPTO_NHPOLY1305_SSE2) += nhpoly1305-sse2.o obj-$(CONFIG_CRYPTO_NHPOLY1305_AVX2) += nhpoly1305-avx2.o @@ -62,8 +56,6 @@ endif ifeq ($(avx2_supported),yes) obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o - - obj-$(CONFIG_CRYPTO_MORUS1280_AVX2) += morus1280-avx2.o endif twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o @@ -81,9 +73,6 @@ aegis128-aesni-y := aegis128-aesni-asm.o aegis128-aesni-glue.o aegis128l-aesni-y := aegis128l-aesni-asm.o aegis128l-aesni-glue.o aegis256-aesni-y := aegis256-aesni-asm.o aegis256-aesni-glue.o -morus640-sse2-y := morus640-sse2-asm.o morus640-sse2-glue.o -morus1280-sse2-y := morus1280-sse2-asm.o morus1280-sse2-glue.o - nhpoly1305-sse2-y := nh-sse2-x86_64.o nhpoly1305-sse2-glue.o ifeq ($(avx_supported),yes) @@ -102,8 +91,6 @@ ifeq ($(avx2_supported),yes) chacha-x86_64-y += chacha-avx2-x86_64.o serpent-avx2-y := serpent-avx2-asm_64.o serpent_avx2_glue.o - morus1280-avx2-y := morus1280-avx2-asm.o morus1280-avx2-glue.o - nhpoly1305-avx2-y := nh-avx2-x86_64.o nhpoly1305-avx2-glue.o endif diff --git a/arch/x86/crypto/morus1280-avx2-asm.S b/arch/x86/crypto/morus1280-avx2-asm.S deleted file mode 100644 index 5413fee33481..000000000000 --- a/arch/x86/crypto/morus1280-avx2-asm.S +++ /dev/null @@ -1,619 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * AVX2 implementation of MORUS-1280 - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include - -#define SHUFFLE_MASK(i0, i1, i2, i3) \ - (i0 | (i1 << 2) | (i2 << 4) | (i3 << 6)) - -#define MASK1 SHUFFLE_MASK(3, 0, 1, 2) -#define MASK2 SHUFFLE_MASK(2, 3, 0, 1) -#define MASK3 SHUFFLE_MASK(1, 2, 3, 0) - -#define STATE0 %ymm0 -#define STATE0_LOW %xmm0 -#define STATE1 %ymm1 -#define STATE2 %ymm2 -#define STATE3 %ymm3 -#define STATE4 %ymm4 -#define KEY %ymm5 -#define MSG %ymm5 -#define MSG_LOW %xmm5 -#define T0 %ymm6 -#define T0_LOW %xmm6 -#define T1 %ymm7 - -.section .rodata.cst32.morus1280_const, "aM", @progbits, 32 -.align 32 -.Lmorus1280_const: - .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d - .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62 - .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 - .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd - -.section .rodata.cst32.morus1280_counter, "aM", @progbits, 32 -.align 32 -.Lmorus1280_counter: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 - .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - -.text - -.macro morus1280_round s0, s1, s2, s3, s4, b, w - vpand \s1, \s2, T0 - vpxor T0, \s0, \s0 - vpxor \s3, \s0, \s0 - vpsllq $\b, \s0, T0 - vpsrlq $(64 - \b), \s0, \s0 - vpxor T0, \s0, \s0 - vpermq $\w, \s3, \s3 -.endm - -/* - * __morus1280_update: internal ABI - * input: - * STATE[0-4] - input state - * MSG - message block - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus1280_update: - morus1280_round STATE0, STATE1, STATE2, STATE3, STATE4, 13, MASK1 - vpxor MSG, STATE1, STATE1 - morus1280_round STATE1, STATE2, STATE3, STATE4, STATE0, 46, MASK2 - vpxor MSG, STATE2, STATE2 - morus1280_round STATE2, STATE3, STATE4, STATE0, STATE1, 38, MASK3 - vpxor MSG, STATE3, STATE3 - morus1280_round STATE3, STATE4, STATE0, STATE1, STATE2, 7, MASK2 - vpxor MSG, STATE4, STATE4 - morus1280_round STATE4, STATE0, STATE1, STATE2, STATE3, 4, MASK1 - ret -ENDPROC(__morus1280_update) - -/* - * __morus1280_update_zero: internal ABI - * input: - * STATE[0-4] - input state - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus1280_update_zero: - morus1280_round STATE0, STATE1, STATE2, STATE3, STATE4, 13, MASK1 - morus1280_round STATE1, STATE2, STATE3, STATE4, STATE0, 46, MASK2 - morus1280_round STATE2, STATE3, STATE4, STATE0, STATE1, 38, MASK3 - morus1280_round STATE3, STATE4, STATE0, STATE1, STATE2, 7, MASK2 - morus1280_round STATE4, STATE0, STATE1, STATE2, STATE3, 4, MASK1 - ret -ENDPROC(__morus1280_update_zero) - -/* - * __load_partial: internal ABI - * input: - * %rsi - src - * %rcx - bytes - * output: - * MSG - message block - * changed: - * %r8 - * %r9 - */ -__load_partial: - xor %r9d, %r9d - vpxor MSG, MSG, MSG - - mov %rcx, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov %rcx, %r8 - and $0x1E, %r8 - add %rsi, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov %rcx, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov %rcx, %r8 - and $0x1C, %r8 - add %rsi, %r8 - shl $16, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov %rcx, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov %rcx, %r8 - and $0x18, %r8 - add %rsi, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG_LOW - - mov %rcx, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov %rcx, %r8 - and $0x10, %r8 - add %rsi, %r8 - pshufd $MASK2, MSG_LOW, MSG_LOW - pinsrq $0, (%r8), MSG_LOW - -.Lld_partial_8: - mov %rcx, %r8 - and $0x10, %r8 - jz .Lld_partial_16 - - vpermq $MASK2, MSG, MSG - movdqu (%rsi), MSG_LOW - -.Lld_partial_16: - ret -ENDPROC(__load_partial) - -/* - * __store_partial: internal ABI - * input: - * %rdx - dst - * %rcx - bytes - * output: - * T0 - message block - * changed: - * %r8 - * %r9 - * %r10 - */ -__store_partial: - mov %rcx, %r8 - mov %rdx, %r9 - - cmp $16, %r8 - jl .Lst_partial_16 - - movdqu T0_LOW, (%r9) - vpermq $MASK2, T0, T0 - - sub $16, %r8 - add $16, %r9 - -.Lst_partial_16: - movq T0_LOW, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - pextrq $1, T0_LOW, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $16, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - ret -ENDPROC(__store_partial) - -/* - * void crypto_morus1280_avx2_init(void *state, const void *key, - * const void *iv); - */ -ENTRY(crypto_morus1280_avx2_init) - FRAME_BEGIN - - /* load IV: */ - vpxor STATE0, STATE0, STATE0 - movdqu (%rdx), STATE0_LOW - /* load key: */ - vmovdqu (%rsi), KEY - vmovdqa KEY, STATE1 - /* load all ones: */ - vpcmpeqd STATE2, STATE2, STATE2 - /* load all zeros: */ - vpxor STATE3, STATE3, STATE3 - /* load the constant: */ - vmovdqa .Lmorus1280_const, STATE4 - - /* update 16 times with zero: */ - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - - /* xor-in the key again after updates: */ - vpxor KEY, STATE1, STATE1 - - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_init) - -/* - * void crypto_morus1280_avx2_ad(void *state, const void *data, - * unsigned int length); - */ -ENTRY(crypto_morus1280_avx2_ad) - FRAME_BEGIN - - cmp $32, %rdx - jb .Lad_out - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - mov %rsi, %r8 - and $0x1F, %r8 - jnz .Lad_u_loop - -.align 4 -.Lad_a_loop: - vmovdqa (%rsi), MSG - call __morus1280_update - sub $32, %rdx - add $32, %rsi - cmp $32, %rdx - jge .Lad_a_loop - - jmp .Lad_cont -.align 4 -.Lad_u_loop: - vmovdqu (%rsi), MSG - call __morus1280_update - sub $32, %rdx - add $32, %rsi - cmp $32, %rdx - jge .Lad_u_loop - -.Lad_cont: - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - -.Lad_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_ad) - -/* - * void crypto_morus1280_avx2_enc(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_avx2_enc) - FRAME_BEGIN - - cmp $32, %rcx - jb .Lenc_out - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - mov %rsi, %r8 - or %rdx, %r8 - and $0x1F, %r8 - jnz .Lenc_u_loop - -.align 4 -.Lenc_a_loop: - vmovdqa (%rsi), MSG - vmovdqa MSG, T0 - vpxor STATE0, T0, T0 - vpermq $MASK3, STATE1, T1 - vpxor T1, T0, T0 - vpand STATE2, STATE3, T1 - vpxor T1, T0, T0 - vmovdqa T0, (%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Lenc_a_loop - - jmp .Lenc_cont -.align 4 -.Lenc_u_loop: - vmovdqu (%rsi), MSG - vmovdqa MSG, T0 - vpxor STATE0, T0, T0 - vpermq $MASK3, STATE1, T1 - vpxor T1, T0, T0 - vpand STATE2, STATE3, T1 - vpxor T1, T0, T0 - vmovdqu T0, (%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Lenc_u_loop - -.Lenc_cont: - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - -.Lenc_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_enc) - -/* - * void crypto_morus1280_avx2_enc_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_avx2_enc_tail) - FRAME_BEGIN - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - /* encrypt message: */ - call __load_partial - - vmovdqa MSG, T0 - vpxor STATE0, T0, T0 - vpermq $MASK3, STATE1, T1 - vpxor T1, T0, T0 - vpand STATE2, STATE3, T1 - vpxor T1, T0, T0 - - call __store_partial - - call __morus1280_update - - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_enc_tail) - -/* - * void crypto_morus1280_avx2_dec(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_avx2_dec) - FRAME_BEGIN - - cmp $32, %rcx - jb .Ldec_out - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - mov %rsi, %r8 - or %rdx, %r8 - and $0x1F, %r8 - jnz .Ldec_u_loop - -.align 4 -.Ldec_a_loop: - vmovdqa (%rsi), MSG - vpxor STATE0, MSG, MSG - vpermq $MASK3, STATE1, T0 - vpxor T0, MSG, MSG - vpand STATE2, STATE3, T0 - vpxor T0, MSG, MSG - vmovdqa MSG, (%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Ldec_a_loop - - jmp .Ldec_cont -.align 4 -.Ldec_u_loop: - vmovdqu (%rsi), MSG - vpxor STATE0, MSG, MSG - vpermq $MASK3, STATE1, T0 - vpxor T0, MSG, MSG - vpand STATE2, STATE3, T0 - vpxor T0, MSG, MSG - vmovdqu MSG, (%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Ldec_u_loop - -.Ldec_cont: - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - -.Ldec_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_dec) - -/* - * void crypto_morus1280_avx2_dec_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_avx2_dec_tail) - FRAME_BEGIN - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - /* decrypt message: */ - call __load_partial - - vpxor STATE0, MSG, MSG - vpermq $MASK3, STATE1, T0 - vpxor T0, MSG, MSG - vpand STATE2, STATE3, T0 - vpxor T0, MSG, MSG - vmovdqa MSG, T0 - - call __store_partial - - /* mask with byte count: */ - movq %rcx, T0_LOW - vpbroadcastb T0_LOW, T0 - vmovdqa .Lmorus1280_counter, T1 - vpcmpgtb T1, T0, T0 - vpand T0, MSG, MSG - - call __morus1280_update - - /* store the state: */ - vmovdqu STATE0, (0 * 32)(%rdi) - vmovdqu STATE1, (1 * 32)(%rdi) - vmovdqu STATE2, (2 * 32)(%rdi) - vmovdqu STATE3, (3 * 32)(%rdi) - vmovdqu STATE4, (4 * 32)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_dec_tail) - -/* - * void crypto_morus1280_avx2_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); - */ -ENTRY(crypto_morus1280_avx2_final) - FRAME_BEGIN - - /* load the state: */ - vmovdqu (0 * 32)(%rdi), STATE0 - vmovdqu (1 * 32)(%rdi), STATE1 - vmovdqu (2 * 32)(%rdi), STATE2 - vmovdqu (3 * 32)(%rdi), STATE3 - vmovdqu (4 * 32)(%rdi), STATE4 - - /* xor state[0] into state[4]: */ - vpxor STATE0, STATE4, STATE4 - - /* prepare length block: */ - vpxor MSG, MSG, MSG - vpinsrq $0, %rdx, MSG_LOW, MSG_LOW - vpinsrq $1, %rcx, MSG_LOW, MSG_LOW - vpsllq $3, MSG, MSG /* multiply by 8 (to get bit count) */ - - /* update state: */ - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - - /* xor tag: */ - vmovdqu (%rsi), MSG - - vpxor STATE0, MSG, MSG - vpermq $MASK3, STATE1, T0 - vpxor T0, MSG, MSG - vpand STATE2, STATE3, T0 - vpxor T0, MSG, MSG - vmovdqu MSG, (%rsi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_avx2_final) diff --git a/arch/x86/crypto/morus1280-avx2-glue.c b/arch/x86/crypto/morus1280-avx2-glue.c deleted file mode 100644 index 2d000d66ba4c..000000000000 --- a/arch/x86/crypto/morus1280-avx2-glue.c +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-1280 Authenticated-Encryption Algorithm - * Glue for AVX2 implementation - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void crypto_morus1280_avx2_init(void *state, const void *key, - const void *iv); -asmlinkage void crypto_morus1280_avx2_ad(void *state, const void *data, - unsigned int length); - -asmlinkage void crypto_morus1280_avx2_enc(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus1280_avx2_dec(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus1280_avx2_enc_tail(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus1280_avx2_dec_tail(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus1280_avx2_final(void *state, void *tag_xor, - u64 assoclen, u64 cryptlen); - -MORUS1280_DECLARE_ALG(avx2, "morus1280-avx2", 400); - -static struct simd_aead_alg *simd_alg; - -static int __init crypto_morus1280_avx2_module_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_AVX2) || - !boot_cpu_has(X86_FEATURE_OSXSAVE) || - !cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) - return -ENODEV; - - return simd_register_aeads_compat(&crypto_morus1280_avx2_alg, 1, - &simd_alg); -} - -static void __exit crypto_morus1280_avx2_module_exit(void) -{ - simd_unregister_aeads(&crypto_morus1280_avx2_alg, 1, &simd_alg); -} - -module_init(crypto_morus1280_avx2_module_init); -module_exit(crypto_morus1280_avx2_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-1280 AEAD algorithm -- AVX2 implementation"); -MODULE_ALIAS_CRYPTO("morus1280"); -MODULE_ALIAS_CRYPTO("morus1280-avx2"); diff --git a/arch/x86/crypto/morus1280-sse2-asm.S b/arch/x86/crypto/morus1280-sse2-asm.S deleted file mode 100644 index 0eece772866b..000000000000 --- a/arch/x86/crypto/morus1280-sse2-asm.S +++ /dev/null @@ -1,893 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * SSE2 implementation of MORUS-1280 - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include - -#define SHUFFLE_MASK(i0, i1, i2, i3) \ - (i0 | (i1 << 2) | (i2 << 4) | (i3 << 6)) - -#define MASK2 SHUFFLE_MASK(2, 3, 0, 1) - -#define STATE0_LO %xmm0 -#define STATE0_HI %xmm1 -#define STATE1_LO %xmm2 -#define STATE1_HI %xmm3 -#define STATE2_LO %xmm4 -#define STATE2_HI %xmm5 -#define STATE3_LO %xmm6 -#define STATE3_HI %xmm7 -#define STATE4_LO %xmm8 -#define STATE4_HI %xmm9 -#define KEY_LO %xmm10 -#define KEY_HI %xmm11 -#define MSG_LO %xmm10 -#define MSG_HI %xmm11 -#define T0_LO %xmm12 -#define T0_HI %xmm13 -#define T1_LO %xmm14 -#define T1_HI %xmm15 - -.section .rodata.cst16.morus640_const, "aM", @progbits, 16 -.align 16 -.Lmorus640_const_0: - .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d - .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62 -.Lmorus640_const_1: - .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 - .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd - -.section .rodata.cst16.morus640_counter, "aM", @progbits, 16 -.align 16 -.Lmorus640_counter_0: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f -.Lmorus640_counter_1: - .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 - .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - -.text - -.macro rol1 hi, lo - /* - * HI_1 | HI_0 || LO_1 | LO_0 - * ==> - * HI_0 | HI_1 || LO_1 | LO_0 - * ==> - * HI_0 | LO_1 || LO_0 | HI_1 - */ - pshufd $MASK2, \hi, \hi - movdqa \hi, T0_LO - punpcklqdq \lo, T0_LO - punpckhqdq \hi, \lo - movdqa \lo, \hi - movdqa T0_LO, \lo -.endm - -.macro rol2 hi, lo - movdqa \lo, T0_LO - movdqa \hi, \lo - movdqa T0_LO, \hi -.endm - -.macro rol3 hi, lo - /* - * HI_1 | HI_0 || LO_1 | LO_0 - * ==> - * HI_0 | HI_1 || LO_1 | LO_0 - * ==> - * LO_0 | HI_1 || HI_0 | LO_1 - */ - pshufd $MASK2, \hi, \hi - movdqa \lo, T0_LO - punpckhqdq \hi, T0_LO - punpcklqdq \lo, \hi - movdqa T0_LO, \lo -.endm - -.macro morus1280_round s0_l, s0_h, s1_l, s1_h, s2_l, s2_h, s3_l, s3_h, s4_l, s4_h, b, w - movdqa \s1_l, T0_LO - pand \s2_l, T0_LO - pxor T0_LO, \s0_l - - movdqa \s1_h, T0_LO - pand \s2_h, T0_LO - pxor T0_LO, \s0_h - - pxor \s3_l, \s0_l - pxor \s3_h, \s0_h - - movdqa \s0_l, T0_LO - psllq $\b, T0_LO - psrlq $(64 - \b), \s0_l - pxor T0_LO, \s0_l - - movdqa \s0_h, T0_LO - psllq $\b, T0_LO - psrlq $(64 - \b), \s0_h - pxor T0_LO, \s0_h - - \w \s3_h, \s3_l -.endm - -/* - * __morus1280_update: internal ABI - * input: - * STATE[0-4] - input state - * MSG - message block - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus1280_update: - morus1280_round \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - 13, rol1 - pxor MSG_LO, STATE1_LO - pxor MSG_HI, STATE1_HI - morus1280_round \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - 46, rol2 - pxor MSG_LO, STATE2_LO - pxor MSG_HI, STATE2_HI - morus1280_round \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - 38, rol3 - pxor MSG_LO, STATE3_LO - pxor MSG_HI, STATE3_HI - morus1280_round \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - 7, rol2 - pxor MSG_LO, STATE4_LO - pxor MSG_HI, STATE4_HI - morus1280_round \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - 4, rol1 - ret -ENDPROC(__morus1280_update) - -/* - * __morus1280_update_zero: internal ABI - * input: - * STATE[0-4] - input state - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus1280_update_zero: - morus1280_round \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - 13, rol1 - morus1280_round \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - 46, rol2 - morus1280_round \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - 38, rol3 - morus1280_round \ - STATE3_LO, STATE3_HI, \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - 7, rol2 - morus1280_round \ - STATE4_LO, STATE4_HI, \ - STATE0_LO, STATE0_HI, \ - STATE1_LO, STATE1_HI, \ - STATE2_LO, STATE2_HI, \ - STATE3_LO, STATE3_HI, \ - 4, rol1 - ret -ENDPROC(__morus1280_update_zero) - -/* - * __load_partial: internal ABI - * input: - * %rsi - src - * %rcx - bytes - * output: - * MSG - message block - * changed: - * %r8 - * %r9 - */ -__load_partial: - xor %r9d, %r9d - pxor MSG_LO, MSG_LO - pxor MSG_HI, MSG_HI - - mov %rcx, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov %rcx, %r8 - and $0x1E, %r8 - add %rsi, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov %rcx, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov %rcx, %r8 - and $0x1C, %r8 - add %rsi, %r8 - shl $16, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov %rcx, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov %rcx, %r8 - and $0x18, %r8 - add %rsi, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG_LO - - mov %rcx, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov %rcx, %r8 - and $0x10, %r8 - add %rsi, %r8 - pslldq $8, MSG_LO - movq (%r8), T0_LO - pxor T0_LO, MSG_LO - -.Lld_partial_8: - mov %rcx, %r8 - and $0x10, %r8 - jz .Lld_partial_16 - - movdqa MSG_LO, MSG_HI - movdqu (%rsi), MSG_LO - -.Lld_partial_16: - ret -ENDPROC(__load_partial) - -/* - * __store_partial: internal ABI - * input: - * %rdx - dst - * %rcx - bytes - * output: - * T0 - message block - * changed: - * %r8 - * %r9 - * %r10 - */ -__store_partial: - mov %rcx, %r8 - mov %rdx, %r9 - - cmp $16, %r8 - jl .Lst_partial_16 - - movdqu T0_LO, (%r9) - movdqa T0_HI, T0_LO - - sub $16, %r8 - add $16, %r9 - -.Lst_partial_16: - movq T0_LO, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - psrldq $8, T0_LO - movq T0_LO, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $16, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - ret -ENDPROC(__store_partial) - -/* - * void crypto_morus1280_sse2_init(void *state, const void *key, - * const void *iv); - */ -ENTRY(crypto_morus1280_sse2_init) - FRAME_BEGIN - - /* load IV: */ - pxor STATE0_HI, STATE0_HI - movdqu (%rdx), STATE0_LO - /* load key: */ - movdqu 0(%rsi), KEY_LO - movdqu 16(%rsi), KEY_HI - movdqa KEY_LO, STATE1_LO - movdqa KEY_HI, STATE1_HI - /* load all ones: */ - pcmpeqd STATE2_LO, STATE2_LO - pcmpeqd STATE2_HI, STATE2_HI - /* load all zeros: */ - pxor STATE3_LO, STATE3_LO - pxor STATE3_HI, STATE3_HI - /* load the constant: */ - movdqa .Lmorus640_const_0, STATE4_LO - movdqa .Lmorus640_const_1, STATE4_HI - - /* update 16 times with zero: */ - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - call __morus1280_update_zero - - /* xor-in the key again after updates: */ - pxor KEY_LO, STATE1_LO - pxor KEY_HI, STATE1_HI - - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_init) - -/* - * void crypto_morus1280_sse2_ad(void *state, const void *data, - * unsigned int length); - */ -ENTRY(crypto_morus1280_sse2_ad) - FRAME_BEGIN - - cmp $32, %rdx - jb .Lad_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - mov %rsi, %r8 - and $0xF, %r8 - jnz .Lad_u_loop - -.align 4 -.Lad_a_loop: - movdqa 0(%rsi), MSG_LO - movdqa 16(%rsi), MSG_HI - call __morus1280_update - sub $32, %rdx - add $32, %rsi - cmp $32, %rdx - jge .Lad_a_loop - - jmp .Lad_cont -.align 4 -.Lad_u_loop: - movdqu 0(%rsi), MSG_LO - movdqu 16(%rsi), MSG_HI - call __morus1280_update - sub $32, %rdx - add $32, %rsi - cmp $32, %rdx - jge .Lad_u_loop - -.Lad_cont: - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - -.Lad_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_ad) - -/* - * void crypto_morus1280_sse2_enc(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_sse2_enc) - FRAME_BEGIN - - cmp $32, %rcx - jb .Lenc_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - mov %rsi, %r8 - or %rdx, %r8 - and $0xF, %r8 - jnz .Lenc_u_loop - -.align 4 -.Lenc_a_loop: - movdqa 0(%rsi), MSG_LO - movdqa 16(%rsi), MSG_HI - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - movdqa MSG_LO, T0_LO - movdqa MSG_HI, T0_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - pxor STATE0_LO, T0_LO - pxor STATE0_HI, T0_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - movdqa T0_LO, 0(%rdx) - movdqa T0_HI, 16(%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Lenc_a_loop - - jmp .Lenc_cont -.align 4 -.Lenc_u_loop: - movdqu 0(%rsi), MSG_LO - movdqu 16(%rsi), MSG_HI - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - movdqa MSG_LO, T0_LO - movdqa MSG_HI, T0_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - pxor STATE0_LO, T0_LO - pxor STATE0_HI, T0_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - movdqu T0_LO, 0(%rdx) - movdqu T0_HI, 16(%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Lenc_u_loop - -.Lenc_cont: - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - -.Lenc_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_enc) - -/* - * void crypto_morus1280_sse2_enc_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_sse2_enc_tail) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - /* encrypt message: */ - call __load_partial - - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - movdqa MSG_LO, T0_LO - movdqa MSG_HI, T0_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - pxor STATE0_LO, T0_LO - pxor STATE0_HI, T0_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, T0_LO - pxor T1_HI, T0_HI - - call __store_partial - - call __morus1280_update - - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_enc_tail) - -/* - * void crypto_morus1280_sse2_dec(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_sse2_dec) - FRAME_BEGIN - - cmp $32, %rcx - jb .Ldec_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - mov %rsi, %r8 - or %rdx, %r8 - and $0xF, %r8 - jnz .Ldec_u_loop - -.align 4 -.Ldec_a_loop: - movdqa 0(%rsi), MSG_LO - movdqa 16(%rsi), MSG_HI - pxor STATE0_LO, MSG_LO - pxor STATE0_HI, MSG_HI - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqa MSG_LO, 0(%rdx) - movdqa MSG_HI, 16(%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Ldec_a_loop - - jmp .Ldec_cont -.align 4 -.Ldec_u_loop: - movdqu 0(%rsi), MSG_LO - movdqu 16(%rsi), MSG_HI - pxor STATE0_LO, MSG_LO - pxor STATE0_HI, MSG_HI - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqu MSG_LO, 0(%rdx) - movdqu MSG_HI, 16(%rdx) - - call __morus1280_update - sub $32, %rcx - add $32, %rsi - add $32, %rdx - cmp $32, %rcx - jge .Ldec_u_loop - -.Ldec_cont: - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - -.Ldec_out: - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_dec) - -/* - * void crypto_morus1280_sse2_dec_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus1280_sse2_dec_tail) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - /* decrypt message: */ - call __load_partial - - pxor STATE0_LO, MSG_LO - pxor STATE0_HI, MSG_HI - movdqa STATE1_LO, T1_LO - movdqa STATE1_HI, T1_HI - rol3 T1_HI, T1_LO - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqa STATE2_LO, T1_LO - movdqa STATE2_HI, T1_HI - pand STATE3_LO, T1_LO - pand STATE3_HI, T1_HI - pxor T1_LO, MSG_LO - pxor T1_HI, MSG_HI - movdqa MSG_LO, T0_LO - movdqa MSG_HI, T0_HI - - call __store_partial - - /* mask with byte count: */ - movq %rcx, T0_LO - punpcklbw T0_LO, T0_LO - punpcklbw T0_LO, T0_LO - punpcklbw T0_LO, T0_LO - punpcklbw T0_LO, T0_LO - movdqa T0_LO, T0_HI - movdqa .Lmorus640_counter_0, T1_LO - movdqa .Lmorus640_counter_1, T1_HI - pcmpgtb T1_LO, T0_LO - pcmpgtb T1_HI, T0_HI - pand T0_LO, MSG_LO - pand T0_HI, MSG_HI - - call __morus1280_update - - /* store the state: */ - movdqu STATE0_LO, (0 * 16)(%rdi) - movdqu STATE0_HI, (1 * 16)(%rdi) - movdqu STATE1_LO, (2 * 16)(%rdi) - movdqu STATE1_HI, (3 * 16)(%rdi) - movdqu STATE2_LO, (4 * 16)(%rdi) - movdqu STATE2_HI, (5 * 16)(%rdi) - movdqu STATE3_LO, (6 * 16)(%rdi) - movdqu STATE3_HI, (7 * 16)(%rdi) - movdqu STATE4_LO, (8 * 16)(%rdi) - movdqu STATE4_HI, (9 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_dec_tail) - -/* - * void crypto_morus1280_sse2_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); - */ -ENTRY(crypto_morus1280_sse2_final) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0_LO - movdqu (1 * 16)(%rdi), STATE0_HI - movdqu (2 * 16)(%rdi), STATE1_LO - movdqu (3 * 16)(%rdi), STATE1_HI - movdqu (4 * 16)(%rdi), STATE2_LO - movdqu (5 * 16)(%rdi), STATE2_HI - movdqu (6 * 16)(%rdi), STATE3_LO - movdqu (7 * 16)(%rdi), STATE3_HI - movdqu (8 * 16)(%rdi), STATE4_LO - movdqu (9 * 16)(%rdi), STATE4_HI - - /* xor state[0] into state[4]: */ - pxor STATE0_LO, STATE4_LO - pxor STATE0_HI, STATE4_HI - - /* prepare length block: */ - movq %rdx, MSG_LO - movq %rcx, T0_LO - pslldq $8, T0_LO - pxor T0_LO, MSG_LO - psllq $3, MSG_LO /* multiply by 8 (to get bit count) */ - pxor MSG_HI, MSG_HI - - /* update state: */ - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - call __morus1280_update - - /* xor tag: */ - movdqu 0(%rsi), MSG_LO - movdqu 16(%rsi), MSG_HI - - pxor STATE0_LO, MSG_LO - pxor STATE0_HI, MSG_HI - movdqa STATE1_LO, T0_LO - movdqa STATE1_HI, T0_HI - rol3 T0_HI, T0_LO - pxor T0_LO, MSG_LO - pxor T0_HI, MSG_HI - movdqa STATE2_LO, T0_LO - movdqa STATE2_HI, T0_HI - pand STATE3_LO, T0_LO - pand STATE3_HI, T0_HI - pxor T0_LO, MSG_LO - pxor T0_HI, MSG_HI - - movdqu MSG_LO, 0(%rsi) - movdqu MSG_HI, 16(%rsi) - - FRAME_END - ret -ENDPROC(crypto_morus1280_sse2_final) diff --git a/arch/x86/crypto/morus1280-sse2-glue.c b/arch/x86/crypto/morus1280-sse2-glue.c deleted file mode 100644 index aada9d774293..000000000000 --- a/arch/x86/crypto/morus1280-sse2-glue.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-1280 Authenticated-Encryption Algorithm - * Glue for SSE2 implementation - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void crypto_morus1280_sse2_init(void *state, const void *key, - const void *iv); -asmlinkage void crypto_morus1280_sse2_ad(void *state, const void *data, - unsigned int length); - -asmlinkage void crypto_morus1280_sse2_enc(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus1280_sse2_dec(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus1280_sse2_enc_tail(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus1280_sse2_dec_tail(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus1280_sse2_final(void *state, void *tag_xor, - u64 assoclen, u64 cryptlen); - -MORUS1280_DECLARE_ALG(sse2, "morus1280-sse2", 350); - -static struct simd_aead_alg *simd_alg; - -static int __init crypto_morus1280_sse2_module_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_XMM2) || - !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) - return -ENODEV; - - return simd_register_aeads_compat(&crypto_morus1280_sse2_alg, 1, - &simd_alg); -} - -static void __exit crypto_morus1280_sse2_module_exit(void) -{ - simd_unregister_aeads(&crypto_morus1280_sse2_alg, 1, &simd_alg); -} - -module_init(crypto_morus1280_sse2_module_init); -module_exit(crypto_morus1280_sse2_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-1280 AEAD algorithm -- SSE2 implementation"); -MODULE_ALIAS_CRYPTO("morus1280"); -MODULE_ALIAS_CRYPTO("morus1280-sse2"); diff --git a/arch/x86/crypto/morus1280_glue.c b/arch/x86/crypto/morus1280_glue.c deleted file mode 100644 index ffbde8b22838..000000000000 --- a/arch/x86/crypto/morus1280_glue.c +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-1280 Authenticated-Encryption Algorithm - * Common x86 SIMD glue skeleton - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct morus1280_state { - struct morus1280_block s[MORUS_STATE_BLOCKS]; -}; - -struct morus1280_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_blocks)(void *state, const void *src, void *dst, - unsigned int length); - void (*crypt_tail)(void *state, const void *src, void *dst, - unsigned int length); -}; - -static void crypto_morus1280_glue_process_ad( - struct morus1280_state *state, - const struct morus1280_glue_ops *ops, - struct scatterlist *sg_src, unsigned int assoclen) -{ - struct scatter_walk walk; - struct morus1280_block buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= MORUS1280_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = MORUS1280_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - ops->ad(state, buf.bytes, MORUS1280_BLOCK_SIZE); - pos = 0; - left -= fill; - src += fill; - } - - ops->ad(state, src, left); - src += left & ~(MORUS1280_BLOCK_SIZE - 1); - left &= MORUS1280_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, MORUS1280_BLOCK_SIZE - pos); - ops->ad(state, buf.bytes, MORUS1280_BLOCK_SIZE); - } -} - -static void crypto_morus1280_glue_process_crypt(struct morus1280_state *state, - struct morus1280_ops ops, - struct skcipher_walk *walk) -{ - while (walk->nbytes >= MORUS1280_BLOCK_SIZE) { - ops.crypt_blocks(state, walk->src.virt.addr, - walk->dst.virt.addr, - round_down(walk->nbytes, - MORUS1280_BLOCK_SIZE)); - skcipher_walk_done(walk, walk->nbytes % MORUS1280_BLOCK_SIZE); - } - - if (walk->nbytes) { - ops.crypt_tail(state, walk->src.virt.addr, walk->dst.virt.addr, - walk->nbytes); - skcipher_walk_done(walk, 0); - } -} - -int crypto_morus1280_glue_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct morus1280_ctx *ctx = crypto_aead_ctx(aead); - - if (keylen == MORUS1280_BLOCK_SIZE) { - memcpy(ctx->key.bytes, key, MORUS1280_BLOCK_SIZE); - } else if (keylen == MORUS1280_BLOCK_SIZE / 2) { - memcpy(ctx->key.bytes, key, keylen); - memcpy(ctx->key.bytes + keylen, key, keylen); - } else { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(crypto_morus1280_glue_setkey); - -int crypto_morus1280_glue_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - return (authsize <= MORUS_MAX_AUTH_SIZE) ? 0 : -EINVAL; -} -EXPORT_SYMBOL_GPL(crypto_morus1280_glue_setauthsize); - -static void crypto_morus1280_glue_crypt(struct aead_request *req, - struct morus1280_ops ops, - unsigned int cryptlen, - struct morus1280_block *tag_xor) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus1280_ctx *ctx = crypto_aead_ctx(tfm); - struct morus1280_state state; - struct skcipher_walk walk; - - ops.skcipher_walk_init(&walk, req, true); - - kernel_fpu_begin(); - - ctx->ops->init(&state, &ctx->key, req->iv); - crypto_morus1280_glue_process_ad(&state, ctx->ops, req->src, req->assoclen); - crypto_morus1280_glue_process_crypt(&state, ops, &walk); - ctx->ops->final(&state, tag_xor, req->assoclen, cryptlen); - - kernel_fpu_end(); -} - -int crypto_morus1280_glue_encrypt(struct aead_request *req) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus1280_ctx *ctx = crypto_aead_ctx(tfm); - struct morus1280_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_blocks = ctx->ops->enc, - .crypt_tail = ctx->ops->enc_tail, - }; - - struct morus1280_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_morus1280_glue_crypt(req, OPS, cryptlen, &tag); - - scatterwalk_map_and_copy(tag.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_morus1280_glue_encrypt); - -int crypto_morus1280_glue_decrypt(struct aead_request *req) -{ - static const u8 zeros[MORUS1280_BLOCK_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus1280_ctx *ctx = crypto_aead_ctx(tfm); - struct morus1280_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_blocks = ctx->ops->dec, - .crypt_tail = ctx->ops->dec_tail, - }; - - struct morus1280_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_morus1280_glue_crypt(req, OPS, cryptlen, &tag); - - return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; -} -EXPORT_SYMBOL_GPL(crypto_morus1280_glue_decrypt); - -void crypto_morus1280_glue_init_ops(struct crypto_aead *aead, - const struct morus1280_glue_ops *ops) -{ - struct morus1280_ctx *ctx = crypto_aead_ctx(aead); - ctx->ops = ops; -} -EXPORT_SYMBOL_GPL(crypto_morus1280_glue_init_ops); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-1280 AEAD mode -- glue for x86 optimizations"); diff --git a/arch/x86/crypto/morus640-sse2-asm.S b/arch/x86/crypto/morus640-sse2-asm.S deleted file mode 100644 index a60891101bbd..000000000000 --- a/arch/x86/crypto/morus640-sse2-asm.S +++ /dev/null @@ -1,612 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * SSE2 implementation of MORUS-640 - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include - -#define SHUFFLE_MASK(i0, i1, i2, i3) \ - (i0 | (i1 << 2) | (i2 << 4) | (i3 << 6)) - -#define MASK1 SHUFFLE_MASK(3, 0, 1, 2) -#define MASK2 SHUFFLE_MASK(2, 3, 0, 1) -#define MASK3 SHUFFLE_MASK(1, 2, 3, 0) - -#define STATE0 %xmm0 -#define STATE1 %xmm1 -#define STATE2 %xmm2 -#define STATE3 %xmm3 -#define STATE4 %xmm4 -#define KEY %xmm5 -#define MSG %xmm5 -#define T0 %xmm6 -#define T1 %xmm7 - -.section .rodata.cst16.morus640_const, "aM", @progbits, 32 -.align 16 -.Lmorus640_const_0: - .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d - .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62 -.Lmorus640_const_1: - .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 - .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd - -.section .rodata.cst16.morus640_counter, "aM", @progbits, 16 -.align 16 -.Lmorus640_counter: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - -.text - -.macro morus640_round s0, s1, s2, s3, s4, b, w - movdqa \s1, T0 - pand \s2, T0 - pxor T0, \s0 - pxor \s3, \s0 - movdqa \s0, T0 - pslld $\b, T0 - psrld $(32 - \b), \s0 - pxor T0, \s0 - pshufd $\w, \s3, \s3 -.endm - -/* - * __morus640_update: internal ABI - * input: - * STATE[0-4] - input state - * MSG - message block - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus640_update: - morus640_round STATE0, STATE1, STATE2, STATE3, STATE4, 5, MASK1 - pxor MSG, STATE1 - morus640_round STATE1, STATE2, STATE3, STATE4, STATE0, 31, MASK2 - pxor MSG, STATE2 - morus640_round STATE2, STATE3, STATE4, STATE0, STATE1, 7, MASK3 - pxor MSG, STATE3 - morus640_round STATE3, STATE4, STATE0, STATE1, STATE2, 22, MASK2 - pxor MSG, STATE4 - morus640_round STATE4, STATE0, STATE1, STATE2, STATE3, 13, MASK1 - ret -ENDPROC(__morus640_update) - - -/* - * __morus640_update_zero: internal ABI - * input: - * STATE[0-4] - input state - * output: - * STATE[0-4] - output state - * changed: - * T0 - */ -__morus640_update_zero: - morus640_round STATE0, STATE1, STATE2, STATE3, STATE4, 5, MASK1 - morus640_round STATE1, STATE2, STATE3, STATE4, STATE0, 31, MASK2 - morus640_round STATE2, STATE3, STATE4, STATE0, STATE1, 7, MASK3 - morus640_round STATE3, STATE4, STATE0, STATE1, STATE2, 22, MASK2 - morus640_round STATE4, STATE0, STATE1, STATE2, STATE3, 13, MASK1 - ret -ENDPROC(__morus640_update_zero) - -/* - * __load_partial: internal ABI - * input: - * %rsi - src - * %rcx - bytes - * output: - * MSG - message block - * changed: - * T0 - * %r8 - * %r9 - */ -__load_partial: - xor %r9d, %r9d - pxor MSG, MSG - - mov %rcx, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov %rcx, %r8 - and $0x1E, %r8 - add %rsi, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov %rcx, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov %rcx, %r8 - and $0x1C, %r8 - add %rsi, %r8 - shl $16, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov %rcx, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov %rcx, %r8 - and $0x18, %r8 - add %rsi, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG - - mov %rcx, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov %rcx, %r8 - and $0x10, %r8 - add %rsi, %r8 - pslldq $8, MSG - movq (%r8), T0 - pxor T0, MSG - -.Lld_partial_8: - ret -ENDPROC(__load_partial) - -/* - * __store_partial: internal ABI - * input: - * %rdx - dst - * %rcx - bytes - * output: - * T0 - message block - * changed: - * %r8 - * %r9 - * %r10 - */ -__store_partial: - mov %rcx, %r8 - mov %rdx, %r9 - - movq T0, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - psrldq $8, T0 - movq T0, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $16, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - ret -ENDPROC(__store_partial) - -/* - * void crypto_morus640_sse2_init(void *state, const void *key, const void *iv); - */ -ENTRY(crypto_morus640_sse2_init) - FRAME_BEGIN - - /* load IV: */ - movdqu (%rdx), STATE0 - /* load key: */ - movdqu (%rsi), KEY - movdqa KEY, STATE1 - /* load all ones: */ - pcmpeqd STATE2, STATE2 - /* load the constants: */ - movdqa .Lmorus640_const_0, STATE3 - movdqa .Lmorus640_const_1, STATE4 - - /* update 16 times with zero: */ - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - call __morus640_update_zero - - /* xor-in the key again after updates: */ - pxor KEY, STATE1 - - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_init) - -/* - * void crypto_morus640_sse2_ad(void *state, const void *data, - * unsigned int length); - */ -ENTRY(crypto_morus640_sse2_ad) - FRAME_BEGIN - - cmp $16, %rdx - jb .Lad_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - mov %rsi, %r8 - and $0xF, %r8 - jnz .Lad_u_loop - -.align 4 -.Lad_a_loop: - movdqa (%rsi), MSG - call __morus640_update - sub $16, %rdx - add $16, %rsi - cmp $16, %rdx - jge .Lad_a_loop - - jmp .Lad_cont -.align 4 -.Lad_u_loop: - movdqu (%rsi), MSG - call __morus640_update - sub $16, %rdx - add $16, %rsi - cmp $16, %rdx - jge .Lad_u_loop - -.Lad_cont: - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - -.Lad_out: - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_ad) - -/* - * void crypto_morus640_sse2_enc(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus640_sse2_enc) - FRAME_BEGIN - - cmp $16, %rcx - jb .Lenc_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - mov %rsi, %r8 - or %rdx, %r8 - and $0xF, %r8 - jnz .Lenc_u_loop - -.align 4 -.Lenc_a_loop: - movdqa (%rsi), MSG - movdqa MSG, T0 - pxor STATE0, T0 - pshufd $MASK3, STATE1, T1 - pxor T1, T0 - movdqa STATE2, T1 - pand STATE3, T1 - pxor T1, T0 - movdqa T0, (%rdx) - - call __morus640_update - sub $16, %rcx - add $16, %rsi - add $16, %rdx - cmp $16, %rcx - jge .Lenc_a_loop - - jmp .Lenc_cont -.align 4 -.Lenc_u_loop: - movdqu (%rsi), MSG - movdqa MSG, T0 - pxor STATE0, T0 - pshufd $MASK3, STATE1, T1 - pxor T1, T0 - movdqa STATE2, T1 - pand STATE3, T1 - pxor T1, T0 - movdqu T0, (%rdx) - - call __morus640_update - sub $16, %rcx - add $16, %rsi - add $16, %rdx - cmp $16, %rcx - jge .Lenc_u_loop - -.Lenc_cont: - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - -.Lenc_out: - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_enc) - -/* - * void crypto_morus640_sse2_enc_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus640_sse2_enc_tail) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - /* encrypt message: */ - call __load_partial - - movdqa MSG, T0 - pxor STATE0, T0 - pshufd $MASK3, STATE1, T1 - pxor T1, T0 - movdqa STATE2, T1 - pand STATE3, T1 - pxor T1, T0 - - call __store_partial - - call __morus640_update - - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_enc_tail) - -/* - * void crypto_morus640_sse2_dec(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus640_sse2_dec) - FRAME_BEGIN - - cmp $16, %rcx - jb .Ldec_out - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - mov %rsi, %r8 - or %rdx, %r8 - and $0xF, %r8 - jnz .Ldec_u_loop - -.align 4 -.Ldec_a_loop: - movdqa (%rsi), MSG - pxor STATE0, MSG - pshufd $MASK3, STATE1, T0 - pxor T0, MSG - movdqa STATE2, T0 - pand STATE3, T0 - pxor T0, MSG - movdqa MSG, (%rdx) - - call __morus640_update - sub $16, %rcx - add $16, %rsi - add $16, %rdx - cmp $16, %rcx - jge .Ldec_a_loop - - jmp .Ldec_cont -.align 4 -.Ldec_u_loop: - movdqu (%rsi), MSG - pxor STATE0, MSG - pshufd $MASK3, STATE1, T0 - pxor T0, MSG - movdqa STATE2, T0 - pand STATE3, T0 - pxor T0, MSG - movdqu MSG, (%rdx) - - call __morus640_update - sub $16, %rcx - add $16, %rsi - add $16, %rdx - cmp $16, %rcx - jge .Ldec_u_loop - -.Ldec_cont: - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - -.Ldec_out: - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_dec) - -/* - * void crypto_morus640_sse2_dec_tail(void *state, const void *src, void *dst, - * unsigned int length); - */ -ENTRY(crypto_morus640_sse2_dec_tail) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - /* decrypt message: */ - call __load_partial - - pxor STATE0, MSG - pshufd $MASK3, STATE1, T0 - pxor T0, MSG - movdqa STATE2, T0 - pand STATE3, T0 - pxor T0, MSG - movdqa MSG, T0 - - call __store_partial - - /* mask with byte count: */ - movq %rcx, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - movdqa .Lmorus640_counter, T1 - pcmpgtb T1, T0 - pand T0, MSG - - call __morus640_update - - /* store the state: */ - movdqu STATE0, (0 * 16)(%rdi) - movdqu STATE1, (1 * 16)(%rdi) - movdqu STATE2, (2 * 16)(%rdi) - movdqu STATE3, (3 * 16)(%rdi) - movdqu STATE4, (4 * 16)(%rdi) - - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_dec_tail) - -/* - * void crypto_morus640_sse2_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); - */ -ENTRY(crypto_morus640_sse2_final) - FRAME_BEGIN - - /* load the state: */ - movdqu (0 * 16)(%rdi), STATE0 - movdqu (1 * 16)(%rdi), STATE1 - movdqu (2 * 16)(%rdi), STATE2 - movdqu (3 * 16)(%rdi), STATE3 - movdqu (4 * 16)(%rdi), STATE4 - - /* xor state[0] into state[4]: */ - pxor STATE0, STATE4 - - /* prepare length block: */ - movq %rdx, MSG - movq %rcx, T0 - pslldq $8, T0 - pxor T0, MSG - psllq $3, MSG /* multiply by 8 (to get bit count) */ - - /* update state: */ - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - call __morus640_update - - /* xor tag: */ - movdqu (%rsi), MSG - - pxor STATE0, MSG - pshufd $MASK3, STATE1, T0 - pxor T0, MSG - movdqa STATE2, T0 - pand STATE3, T0 - pxor T0, MSG - - movdqu MSG, (%rsi) - - FRAME_END - ret -ENDPROC(crypto_morus640_sse2_final) diff --git a/arch/x86/crypto/morus640-sse2-glue.c b/arch/x86/crypto/morus640-sse2-glue.c deleted file mode 100644 index 8ef68134aef4..000000000000 --- a/arch/x86/crypto/morus640-sse2-glue.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-640 Authenticated-Encryption Algorithm - * Glue for SSE2 implementation - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void crypto_morus640_sse2_init(void *state, const void *key, - const void *iv); -asmlinkage void crypto_morus640_sse2_ad(void *state, const void *data, - unsigned int length); - -asmlinkage void crypto_morus640_sse2_enc(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus640_sse2_dec(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus640_sse2_enc_tail(void *state, const void *src, - void *dst, unsigned int length); -asmlinkage void crypto_morus640_sse2_dec_tail(void *state, const void *src, - void *dst, unsigned int length); - -asmlinkage void crypto_morus640_sse2_final(void *state, void *tag_xor, - u64 assoclen, u64 cryptlen); - -MORUS640_DECLARE_ALG(sse2, "morus640-sse2", 400); - -static struct simd_aead_alg *simd_alg; - -static int __init crypto_morus640_sse2_module_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_XMM2) || - !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) - return -ENODEV; - - return simd_register_aeads_compat(&crypto_morus640_sse2_alg, 1, - &simd_alg); -} - -static void __exit crypto_morus640_sse2_module_exit(void) -{ - simd_unregister_aeads(&crypto_morus640_sse2_alg, 1, &simd_alg); -} - -module_init(crypto_morus640_sse2_module_init); -module_exit(crypto_morus640_sse2_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-640 AEAD algorithm -- SSE2 implementation"); -MODULE_ALIAS_CRYPTO("morus640"); -MODULE_ALIAS_CRYPTO("morus640-sse2"); diff --git a/arch/x86/crypto/morus640_glue.c b/arch/x86/crypto/morus640_glue.c deleted file mode 100644 index d8b5fd6cef29..000000000000 --- a/arch/x86/crypto/morus640_glue.c +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-640 Authenticated-Encryption Algorithm - * Common x86 SIMD glue skeleton - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct morus640_state { - struct morus640_block s[MORUS_STATE_BLOCKS]; -}; - -struct morus640_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_blocks)(void *state, const void *src, void *dst, - unsigned int length); - void (*crypt_tail)(void *state, const void *src, void *dst, - unsigned int length); -}; - -static void crypto_morus640_glue_process_ad( - struct morus640_state *state, - const struct morus640_glue_ops *ops, - struct scatterlist *sg_src, unsigned int assoclen) -{ - struct scatter_walk walk; - struct morus640_block buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= MORUS640_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = MORUS640_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - ops->ad(state, buf.bytes, MORUS640_BLOCK_SIZE); - pos = 0; - left -= fill; - src += fill; - } - - ops->ad(state, src, left); - src += left & ~(MORUS640_BLOCK_SIZE - 1); - left &= MORUS640_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, MORUS640_BLOCK_SIZE - pos); - ops->ad(state, buf.bytes, MORUS640_BLOCK_SIZE); - } -} - -static void crypto_morus640_glue_process_crypt(struct morus640_state *state, - struct morus640_ops ops, - struct skcipher_walk *walk) -{ - while (walk->nbytes >= MORUS640_BLOCK_SIZE) { - ops.crypt_blocks(state, walk->src.virt.addr, - walk->dst.virt.addr, - round_down(walk->nbytes, MORUS640_BLOCK_SIZE)); - skcipher_walk_done(walk, walk->nbytes % MORUS640_BLOCK_SIZE); - } - - if (walk->nbytes) { - ops.crypt_tail(state, walk->src.virt.addr, walk->dst.virt.addr, - walk->nbytes); - skcipher_walk_done(walk, 0); - } -} - -int crypto_morus640_glue_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct morus640_ctx *ctx = crypto_aead_ctx(aead); - - if (keylen != MORUS640_BLOCK_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - memcpy(ctx->key.bytes, key, MORUS640_BLOCK_SIZE); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_morus640_glue_setkey); - -int crypto_morus640_glue_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - return (authsize <= MORUS_MAX_AUTH_SIZE) ? 0 : -EINVAL; -} -EXPORT_SYMBOL_GPL(crypto_morus640_glue_setauthsize); - -static void crypto_morus640_glue_crypt(struct aead_request *req, - struct morus640_ops ops, - unsigned int cryptlen, - struct morus640_block *tag_xor) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus640_ctx *ctx = crypto_aead_ctx(tfm); - struct morus640_state state; - struct skcipher_walk walk; - - ops.skcipher_walk_init(&walk, req, true); - - kernel_fpu_begin(); - - ctx->ops->init(&state, &ctx->key, req->iv); - crypto_morus640_glue_process_ad(&state, ctx->ops, req->src, req->assoclen); - crypto_morus640_glue_process_crypt(&state, ops, &walk); - ctx->ops->final(&state, tag_xor, req->assoclen, cryptlen); - - kernel_fpu_end(); -} - -int crypto_morus640_glue_encrypt(struct aead_request *req) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus640_ctx *ctx = crypto_aead_ctx(tfm); - struct morus640_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_blocks = ctx->ops->enc, - .crypt_tail = ctx->ops->enc_tail, - }; - - struct morus640_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_morus640_glue_crypt(req, OPS, cryptlen, &tag); - - scatterwalk_map_and_copy(tag.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_morus640_glue_encrypt); - -int crypto_morus640_glue_decrypt(struct aead_request *req) -{ - static const u8 zeros[MORUS640_BLOCK_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus640_ctx *ctx = crypto_aead_ctx(tfm); - struct morus640_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_blocks = ctx->ops->dec, - .crypt_tail = ctx->ops->dec_tail, - }; - - struct morus640_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_morus640_glue_crypt(req, OPS, cryptlen, &tag); - - return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; -} -EXPORT_SYMBOL_GPL(crypto_morus640_glue_decrypt); - -void crypto_morus640_glue_init_ops(struct crypto_aead *aead, - const struct morus640_glue_ops *ops) -{ - struct morus640_ctx *ctx = crypto_aead_ctx(aead); - ctx->ops = ops; -} -EXPORT_SYMBOL_GPL(crypto_morus640_glue_init_ops); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-640 AEAD mode -- glue for x86 optimizations"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 80ea118600ab..160dc1a9c7ec 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -344,62 +344,6 @@ config CRYPTO_AEGIS256_AESNI_SSE2 help AESNI+SSE2 implementation of the AEGIS-256 dedicated AEAD algorithm. -config CRYPTO_MORUS640 - tristate "MORUS-640 AEAD algorithm" - select CRYPTO_AEAD - help - Support for the MORUS-640 dedicated AEAD algorithm. - -config CRYPTO_MORUS640_GLUE - tristate - depends on X86 - select CRYPTO_AEAD - select CRYPTO_SIMD - help - Common glue for SIMD optimizations of the MORUS-640 dedicated AEAD - algorithm. - -config CRYPTO_MORUS640_SSE2 - tristate "MORUS-640 AEAD algorithm (x86_64 SSE2 implementation)" - depends on X86 && 64BIT - select CRYPTO_AEAD - select CRYPTO_MORUS640_GLUE - help - SSE2 implementation of the MORUS-640 dedicated AEAD algorithm. - -config CRYPTO_MORUS1280 - tristate "MORUS-1280 AEAD algorithm" - select CRYPTO_AEAD - help - Support for the MORUS-1280 dedicated AEAD algorithm. - -config CRYPTO_MORUS1280_GLUE - tristate - depends on X86 - select CRYPTO_AEAD - select CRYPTO_SIMD - help - Common glue for SIMD optimizations of the MORUS-1280 dedicated AEAD - algorithm. - -config CRYPTO_MORUS1280_SSE2 - tristate "MORUS-1280 AEAD algorithm (x86_64 SSE2 implementation)" - depends on X86 && 64BIT - select CRYPTO_AEAD - select CRYPTO_MORUS1280_GLUE - help - SSE2 optimizedimplementation of the MORUS-1280 dedicated AEAD - algorithm. - -config CRYPTO_MORUS1280_AVX2 - tristate "MORUS-1280 AEAD algorithm (x86_64 AVX2 implementation)" - depends on X86 && 64BIT - select CRYPTO_AEAD - select CRYPTO_MORUS1280_GLUE - help - AVX2 optimized implementation of the MORUS-1280 dedicated AEAD - algorithm. - config CRYPTO_SEQIV tristate "Sequence Number IV Generator" select CRYPTO_AEAD diff --git a/crypto/Makefile b/crypto/Makefile index 9479e1a45d8c..4bc1951d3787 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -92,8 +92,6 @@ obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o obj-$(CONFIG_CRYPTO_AEGIS128L) += aegis128l.o obj-$(CONFIG_CRYPTO_AEGIS256) += aegis256.o -obj-$(CONFIG_CRYPTO_MORUS640) += morus640.o -obj-$(CONFIG_CRYPTO_MORUS1280) += morus1280.o obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o obj-$(CONFIG_CRYPTO_DES) += des_generic.o diff --git a/crypto/morus1280.c b/crypto/morus1280.c deleted file mode 100644 index f8734c6576af..000000000000 --- a/crypto/morus1280.c +++ /dev/null @@ -1,542 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-1280 Authenticated-Encryption Algorithm - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MORUS1280_WORD_SIZE 8 -#define MORUS1280_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS1280_WORD_SIZE) -#define MORUS1280_BLOCK_ALIGN (__alignof__(__le64)) -#define MORUS1280_ALIGNED(p) IS_ALIGNED((uintptr_t)p, MORUS1280_BLOCK_ALIGN) - -struct morus1280_block { - u64 words[MORUS_BLOCK_WORDS]; -}; - -union morus1280_block_in { - __le64 words[MORUS_BLOCK_WORDS]; - u8 bytes[MORUS1280_BLOCK_SIZE]; -}; - -struct morus1280_state { - struct morus1280_block s[MORUS_STATE_BLOCKS]; -}; - -struct morus1280_ctx { - struct morus1280_block key; -}; - -struct morus1280_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_chunk)(struct morus1280_state *state, - u8 *dst, const u8 *src, unsigned int size); -}; - -static const struct morus1280_block crypto_morus1280_const[1] = { - { .words = { - U64_C(0x0d08050302010100), - U64_C(0x6279e99059372215), - U64_C(0xf12fc26d55183ddb), - U64_C(0xdd28b57342311120), - } }, -}; - -static void crypto_morus1280_round(struct morus1280_block *b0, - struct morus1280_block *b1, - struct morus1280_block *b2, - struct morus1280_block *b3, - struct morus1280_block *b4, - const struct morus1280_block *m, - unsigned int b, unsigned int w) -{ - unsigned int i; - struct morus1280_block tmp; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - b0->words[i] ^= b1->words[i] & b2->words[i]; - b0->words[i] ^= b3->words[i]; - b0->words[i] ^= m->words[i]; - b0->words[i] = rol64(b0->words[i], b); - } - - tmp = *b3; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - b3->words[(i + w) % MORUS_BLOCK_WORDS] = tmp.words[i]; -} - -static void crypto_morus1280_update(struct morus1280_state *state, - const struct morus1280_block *m) -{ - static const struct morus1280_block z = {}; - - struct morus1280_block *s = state->s; - - crypto_morus1280_round(&s[0], &s[1], &s[2], &s[3], &s[4], &z, 13, 1); - crypto_morus1280_round(&s[1], &s[2], &s[3], &s[4], &s[0], m, 46, 2); - crypto_morus1280_round(&s[2], &s[3], &s[4], &s[0], &s[1], m, 38, 3); - crypto_morus1280_round(&s[3], &s[4], &s[0], &s[1], &s[2], m, 7, 2); - crypto_morus1280_round(&s[4], &s[0], &s[1], &s[2], &s[3], m, 4, 1); -} - -static void crypto_morus1280_load_a(struct morus1280_block *dst, const u8 *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - dst->words[i] = le64_to_cpu(*(const __le64 *)src); - src += MORUS1280_WORD_SIZE; - } -} - -static void crypto_morus1280_load_u(struct morus1280_block *dst, const u8 *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - dst->words[i] = get_unaligned_le64(src); - src += MORUS1280_WORD_SIZE; - } -} - -static void crypto_morus1280_load(struct morus1280_block *dst, const u8 *src) -{ - if (MORUS1280_ALIGNED(src)) - crypto_morus1280_load_a(dst, src); - else - crypto_morus1280_load_u(dst, src); -} - -static void crypto_morus1280_store_a(u8 *dst, const struct morus1280_block *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - *(__le64 *)dst = cpu_to_le64(src->words[i]); - dst += MORUS1280_WORD_SIZE; - } -} - -static void crypto_morus1280_store_u(u8 *dst, const struct morus1280_block *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - put_unaligned_le64(src->words[i], dst); - dst += MORUS1280_WORD_SIZE; - } -} - -static void crypto_morus1280_store(u8 *dst, const struct morus1280_block *src) -{ - if (MORUS1280_ALIGNED(dst)) - crypto_morus1280_store_a(dst, src); - else - crypto_morus1280_store_u(dst, src); -} - -static void crypto_morus1280_ad(struct morus1280_state *state, const u8 *src, - unsigned int size) -{ - struct morus1280_block m; - - if (MORUS1280_ALIGNED(src)) { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_a(&m, src); - crypto_morus1280_update(state, &m); - - size -= MORUS1280_BLOCK_SIZE; - src += MORUS1280_BLOCK_SIZE; - } - } else { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_u(&m, src); - crypto_morus1280_update(state, &m); - - size -= MORUS1280_BLOCK_SIZE; - src += MORUS1280_BLOCK_SIZE; - } - } -} - -static void crypto_morus1280_core(const struct morus1280_state *state, - struct morus1280_block *blk) -{ - unsigned int i; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - blk->words[(i + 3) % MORUS_BLOCK_WORDS] ^= state->s[1].words[i]; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - blk->words[i] ^= state->s[0].words[i]; - blk->words[i] ^= state->s[2].words[i] & state->s[3].words[i]; - } -} - -static void crypto_morus1280_encrypt_chunk(struct morus1280_state *state, - u8 *dst, const u8 *src, - unsigned int size) -{ - struct morus1280_block c, m; - - if (MORUS1280_ALIGNED(src) && MORUS1280_ALIGNED(dst)) { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_a(&m, src); - c = m; - crypto_morus1280_core(state, &c); - crypto_morus1280_store_a(dst, &c); - crypto_morus1280_update(state, &m); - - src += MORUS1280_BLOCK_SIZE; - dst += MORUS1280_BLOCK_SIZE; - size -= MORUS1280_BLOCK_SIZE; - } - } else { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_u(&m, src); - c = m; - crypto_morus1280_core(state, &c); - crypto_morus1280_store_u(dst, &c); - crypto_morus1280_update(state, &m); - - src += MORUS1280_BLOCK_SIZE; - dst += MORUS1280_BLOCK_SIZE; - size -= MORUS1280_BLOCK_SIZE; - } - } - - if (size > 0) { - union morus1280_block_in tail; - - memcpy(tail.bytes, src, size); - memset(tail.bytes + size, 0, MORUS1280_BLOCK_SIZE - size); - - crypto_morus1280_load_a(&m, tail.bytes); - c = m; - crypto_morus1280_core(state, &c); - crypto_morus1280_store_a(tail.bytes, &c); - crypto_morus1280_update(state, &m); - - memcpy(dst, tail.bytes, size); - } -} - -static void crypto_morus1280_decrypt_chunk(struct morus1280_state *state, - u8 *dst, const u8 *src, - unsigned int size) -{ - struct morus1280_block m; - - if (MORUS1280_ALIGNED(src) && MORUS1280_ALIGNED(dst)) { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_a(&m, src); - crypto_morus1280_core(state, &m); - crypto_morus1280_store_a(dst, &m); - crypto_morus1280_update(state, &m); - - src += MORUS1280_BLOCK_SIZE; - dst += MORUS1280_BLOCK_SIZE; - size -= MORUS1280_BLOCK_SIZE; - } - } else { - while (size >= MORUS1280_BLOCK_SIZE) { - crypto_morus1280_load_u(&m, src); - crypto_morus1280_core(state, &m); - crypto_morus1280_store_u(dst, &m); - crypto_morus1280_update(state, &m); - - src += MORUS1280_BLOCK_SIZE; - dst += MORUS1280_BLOCK_SIZE; - size -= MORUS1280_BLOCK_SIZE; - } - } - - if (size > 0) { - union morus1280_block_in tail; - - memcpy(tail.bytes, src, size); - memset(tail.bytes + size, 0, MORUS1280_BLOCK_SIZE - size); - - crypto_morus1280_load_a(&m, tail.bytes); - crypto_morus1280_core(state, &m); - crypto_morus1280_store_a(tail.bytes, &m); - memset(tail.bytes + size, 0, MORUS1280_BLOCK_SIZE - size); - crypto_morus1280_load_a(&m, tail.bytes); - crypto_morus1280_update(state, &m); - - memcpy(dst, tail.bytes, size); - } -} - -static void crypto_morus1280_init(struct morus1280_state *state, - const struct morus1280_block *key, - const u8 *iv) -{ - static const struct morus1280_block z = {}; - - union morus1280_block_in tmp; - unsigned int i; - - memcpy(tmp.bytes, iv, MORUS_NONCE_SIZE); - memset(tmp.bytes + MORUS_NONCE_SIZE, 0, - MORUS1280_BLOCK_SIZE - MORUS_NONCE_SIZE); - - crypto_morus1280_load(&state->s[0], tmp.bytes); - state->s[1] = *key; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[2].words[i] = U64_C(0xFFFFFFFFFFFFFFFF); - state->s[3] = z; - state->s[4] = crypto_morus1280_const[0]; - - for (i = 0; i < 16; i++) - crypto_morus1280_update(state, &z); - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[1].words[i] ^= key->words[i]; -} - -static void crypto_morus1280_process_ad(struct morus1280_state *state, - struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - struct morus1280_block m; - union morus1280_block_in buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= MORUS1280_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = MORUS1280_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - - crypto_morus1280_load_a(&m, buf.bytes); - crypto_morus1280_update(state, &m); - - pos = 0; - left -= fill; - src += fill; - } - - crypto_morus1280_ad(state, src, left); - src += left & ~(MORUS1280_BLOCK_SIZE - 1); - left &= MORUS1280_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, MORUS1280_BLOCK_SIZE - pos); - - crypto_morus1280_load_a(&m, buf.bytes); - crypto_morus1280_update(state, &m); - } -} - -static void crypto_morus1280_process_crypt(struct morus1280_state *state, - struct aead_request *req, - const struct morus1280_ops *ops) -{ - struct skcipher_walk walk; - - ops->skcipher_walk_init(&walk, req, false); - - while (walk.nbytes) { - unsigned int nbytes = walk.nbytes; - - if (nbytes < walk.total) - nbytes = round_down(nbytes, walk.stride); - - ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr, - nbytes); - - skcipher_walk_done(&walk, walk.nbytes - nbytes); - } -} - -static void crypto_morus1280_final(struct morus1280_state *state, - struct morus1280_block *tag_xor, - u64 assoclen, u64 cryptlen) -{ - struct morus1280_block tmp; - unsigned int i; - - tmp.words[0] = assoclen * 8; - tmp.words[1] = cryptlen * 8; - tmp.words[2] = 0; - tmp.words[3] = 0; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[4].words[i] ^= state->s[0].words[i]; - - for (i = 0; i < 10; i++) - crypto_morus1280_update(state, &tmp); - - crypto_morus1280_core(state, tag_xor); -} - -static int crypto_morus1280_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct morus1280_ctx *ctx = crypto_aead_ctx(aead); - union morus1280_block_in tmp; - - if (keylen == MORUS1280_BLOCK_SIZE) - crypto_morus1280_load(&ctx->key, key); - else if (keylen == MORUS1280_BLOCK_SIZE / 2) { - memcpy(tmp.bytes, key, keylen); - memcpy(tmp.bytes + keylen, key, keylen); - - crypto_morus1280_load(&ctx->key, tmp.bytes); - } else { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - return 0; -} - -static int crypto_morus1280_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - return (authsize <= MORUS_MAX_AUTH_SIZE) ? 0 : -EINVAL; -} - -static void crypto_morus1280_crypt(struct aead_request *req, - struct morus1280_block *tag_xor, - unsigned int cryptlen, - const struct morus1280_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus1280_ctx *ctx = crypto_aead_ctx(tfm); - struct morus1280_state state; - - crypto_morus1280_init(&state, &ctx->key, req->iv); - crypto_morus1280_process_ad(&state, req->src, req->assoclen); - crypto_morus1280_process_crypt(&state, req, ops); - crypto_morus1280_final(&state, tag_xor, req->assoclen, cryptlen); -} - -static int crypto_morus1280_encrypt(struct aead_request *req) -{ - static const struct morus1280_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_chunk = crypto_morus1280_encrypt_chunk, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus1280_block tag = {}; - union morus1280_block_in tag_out; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_morus1280_crypt(req, &tag, cryptlen, &ops); - crypto_morus1280_store(tag_out.bytes, &tag); - - scatterwalk_map_and_copy(tag_out.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} - -static int crypto_morus1280_decrypt(struct aead_request *req) -{ - static const struct morus1280_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_chunk = crypto_morus1280_decrypt_chunk, - }; - static const u8 zeros[MORUS1280_BLOCK_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union morus1280_block_in tag_in; - struct morus1280_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag_in.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_morus1280_load(&tag, tag_in.bytes); - crypto_morus1280_crypt(req, &tag, cryptlen, &ops); - crypto_morus1280_store(tag_in.bytes, &tag); - - return crypto_memneq(tag_in.bytes, zeros, authsize) ? -EBADMSG : 0; -} - -static int crypto_morus1280_init_tfm(struct crypto_aead *tfm) -{ - return 0; -} - -static void crypto_morus1280_exit_tfm(struct crypto_aead *tfm) -{ -} - -static struct aead_alg crypto_morus1280_alg = { - .setkey = crypto_morus1280_setkey, - .setauthsize = crypto_morus1280_setauthsize, - .encrypt = crypto_morus1280_encrypt, - .decrypt = crypto_morus1280_decrypt, - .init = crypto_morus1280_init_tfm, - .exit = crypto_morus1280_exit_tfm, - - .ivsize = MORUS_NONCE_SIZE, - .maxauthsize = MORUS_MAX_AUTH_SIZE, - .chunksize = MORUS1280_BLOCK_SIZE, - - .base = { - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct morus1280_ctx), - .cra_alignmask = 0, - - .cra_priority = 100, - - .cra_name = "morus1280", - .cra_driver_name = "morus1280-generic", - - .cra_module = THIS_MODULE, - } -}; - - -static int __init crypto_morus1280_module_init(void) -{ - return crypto_register_aead(&crypto_morus1280_alg); -} - -static void __exit crypto_morus1280_module_exit(void) -{ - crypto_unregister_aead(&crypto_morus1280_alg); -} - -subsys_initcall(crypto_morus1280_module_init); -module_exit(crypto_morus1280_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-1280 AEAD algorithm"); -MODULE_ALIAS_CRYPTO("morus1280"); -MODULE_ALIAS_CRYPTO("morus1280-generic"); diff --git a/crypto/morus640.c b/crypto/morus640.c deleted file mode 100644 index ae5aa9482cb4..000000000000 --- a/crypto/morus640.c +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The MORUS-640 Authenticated-Encryption Algorithm - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MORUS640_WORD_SIZE 4 -#define MORUS640_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS640_WORD_SIZE) -#define MORUS640_BLOCK_ALIGN (__alignof__(__le32)) -#define MORUS640_ALIGNED(p) IS_ALIGNED((uintptr_t)p, MORUS640_BLOCK_ALIGN) - -struct morus640_block { - u32 words[MORUS_BLOCK_WORDS]; -}; - -union morus640_block_in { - __le32 words[MORUS_BLOCK_WORDS]; - u8 bytes[MORUS640_BLOCK_SIZE]; -}; - -struct morus640_state { - struct morus640_block s[MORUS_STATE_BLOCKS]; -}; - -struct morus640_ctx { - struct morus640_block key; -}; - -struct morus640_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_chunk)(struct morus640_state *state, - u8 *dst, const u8 *src, unsigned int size); -}; - -static const struct morus640_block crypto_morus640_const[2] = { - { .words = { - U32_C(0x02010100), - U32_C(0x0d080503), - U32_C(0x59372215), - U32_C(0x6279e990), - } }, - { .words = { - U32_C(0x55183ddb), - U32_C(0xf12fc26d), - U32_C(0x42311120), - U32_C(0xdd28b573), - } }, -}; - -static void crypto_morus640_round(struct morus640_block *b0, - struct morus640_block *b1, - struct morus640_block *b2, - struct morus640_block *b3, - struct morus640_block *b4, - const struct morus640_block *m, - unsigned int b, unsigned int w) -{ - unsigned int i; - struct morus640_block tmp; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - b0->words[i] ^= b1->words[i] & b2->words[i]; - b0->words[i] ^= b3->words[i]; - b0->words[i] ^= m->words[i]; - b0->words[i] = rol32(b0->words[i], b); - } - - tmp = *b3; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - b3->words[(i + w) % MORUS_BLOCK_WORDS] = tmp.words[i]; -} - -static void crypto_morus640_update(struct morus640_state *state, - const struct morus640_block *m) -{ - static const struct morus640_block z = {}; - - struct morus640_block *s = state->s; - - crypto_morus640_round(&s[0], &s[1], &s[2], &s[3], &s[4], &z, 5, 1); - crypto_morus640_round(&s[1], &s[2], &s[3], &s[4], &s[0], m, 31, 2); - crypto_morus640_round(&s[2], &s[3], &s[4], &s[0], &s[1], m, 7, 3); - crypto_morus640_round(&s[3], &s[4], &s[0], &s[1], &s[2], m, 22, 2); - crypto_morus640_round(&s[4], &s[0], &s[1], &s[2], &s[3], m, 13, 1); -} - -static void crypto_morus640_load_a(struct morus640_block *dst, const u8 *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - dst->words[i] = le32_to_cpu(*(const __le32 *)src); - src += MORUS640_WORD_SIZE; - } -} - -static void crypto_morus640_load_u(struct morus640_block *dst, const u8 *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - dst->words[i] = get_unaligned_le32(src); - src += MORUS640_WORD_SIZE; - } -} - -static void crypto_morus640_load(struct morus640_block *dst, const u8 *src) -{ - if (MORUS640_ALIGNED(src)) - crypto_morus640_load_a(dst, src); - else - crypto_morus640_load_u(dst, src); -} - -static void crypto_morus640_store_a(u8 *dst, const struct morus640_block *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - *(__le32 *)dst = cpu_to_le32(src->words[i]); - dst += MORUS640_WORD_SIZE; - } -} - -static void crypto_morus640_store_u(u8 *dst, const struct morus640_block *src) -{ - unsigned int i; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - put_unaligned_le32(src->words[i], dst); - dst += MORUS640_WORD_SIZE; - } -} - -static void crypto_morus640_store(u8 *dst, const struct morus640_block *src) -{ - if (MORUS640_ALIGNED(dst)) - crypto_morus640_store_a(dst, src); - else - crypto_morus640_store_u(dst, src); -} - -static void crypto_morus640_ad(struct morus640_state *state, const u8 *src, - unsigned int size) -{ - struct morus640_block m; - - if (MORUS640_ALIGNED(src)) { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_a(&m, src); - crypto_morus640_update(state, &m); - - size -= MORUS640_BLOCK_SIZE; - src += MORUS640_BLOCK_SIZE; - } - } else { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_u(&m, src); - crypto_morus640_update(state, &m); - - size -= MORUS640_BLOCK_SIZE; - src += MORUS640_BLOCK_SIZE; - } - } -} - -static void crypto_morus640_core(const struct morus640_state *state, - struct morus640_block *blk) -{ - unsigned int i; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - blk->words[(i + 3) % MORUS_BLOCK_WORDS] ^= state->s[1].words[i]; - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) { - blk->words[i] ^= state->s[0].words[i]; - blk->words[i] ^= state->s[2].words[i] & state->s[3].words[i]; - } -} - -static void crypto_morus640_encrypt_chunk(struct morus640_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - struct morus640_block c, m; - - if (MORUS640_ALIGNED(src) && MORUS640_ALIGNED(dst)) { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_a(&m, src); - c = m; - crypto_morus640_core(state, &c); - crypto_morus640_store_a(dst, &c); - crypto_morus640_update(state, &m); - - src += MORUS640_BLOCK_SIZE; - dst += MORUS640_BLOCK_SIZE; - size -= MORUS640_BLOCK_SIZE; - } - } else { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_u(&m, src); - c = m; - crypto_morus640_core(state, &c); - crypto_morus640_store_u(dst, &c); - crypto_morus640_update(state, &m); - - src += MORUS640_BLOCK_SIZE; - dst += MORUS640_BLOCK_SIZE; - size -= MORUS640_BLOCK_SIZE; - } - } - - if (size > 0) { - union morus640_block_in tail; - - memcpy(tail.bytes, src, size); - memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size); - - crypto_morus640_load_a(&m, tail.bytes); - c = m; - crypto_morus640_core(state, &c); - crypto_morus640_store_a(tail.bytes, &c); - crypto_morus640_update(state, &m); - - memcpy(dst, tail.bytes, size); - } -} - -static void crypto_morus640_decrypt_chunk(struct morus640_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - struct morus640_block m; - - if (MORUS640_ALIGNED(src) && MORUS640_ALIGNED(dst)) { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_a(&m, src); - crypto_morus640_core(state, &m); - crypto_morus640_store_a(dst, &m); - crypto_morus640_update(state, &m); - - src += MORUS640_BLOCK_SIZE; - dst += MORUS640_BLOCK_SIZE; - size -= MORUS640_BLOCK_SIZE; - } - } else { - while (size >= MORUS640_BLOCK_SIZE) { - crypto_morus640_load_u(&m, src); - crypto_morus640_core(state, &m); - crypto_morus640_store_u(dst, &m); - crypto_morus640_update(state, &m); - - src += MORUS640_BLOCK_SIZE; - dst += MORUS640_BLOCK_SIZE; - size -= MORUS640_BLOCK_SIZE; - } - } - - if (size > 0) { - union morus640_block_in tail; - - memcpy(tail.bytes, src, size); - memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size); - - crypto_morus640_load_a(&m, tail.bytes); - crypto_morus640_core(state, &m); - crypto_morus640_store_a(tail.bytes, &m); - memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size); - crypto_morus640_load_a(&m, tail.bytes); - crypto_morus640_update(state, &m); - - memcpy(dst, tail.bytes, size); - } -} - -static void crypto_morus640_init(struct morus640_state *state, - const struct morus640_block *key, - const u8 *iv) -{ - static const struct morus640_block z = {}; - - unsigned int i; - - crypto_morus640_load(&state->s[0], iv); - state->s[1] = *key; - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[2].words[i] = U32_C(0xFFFFFFFF); - state->s[3] = crypto_morus640_const[0]; - state->s[4] = crypto_morus640_const[1]; - - for (i = 0; i < 16; i++) - crypto_morus640_update(state, &z); - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[1].words[i] ^= key->words[i]; -} - -static void crypto_morus640_process_ad(struct morus640_state *state, - struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - struct morus640_block m; - union morus640_block_in buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= MORUS640_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = MORUS640_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - - crypto_morus640_load_a(&m, buf.bytes); - crypto_morus640_update(state, &m); - - pos = 0; - left -= fill; - src += fill; - } - - crypto_morus640_ad(state, src, left); - src += left & ~(MORUS640_BLOCK_SIZE - 1); - left &= MORUS640_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, MORUS640_BLOCK_SIZE - pos); - - crypto_morus640_load_a(&m, buf.bytes); - crypto_morus640_update(state, &m); - } -} - -static void crypto_morus640_process_crypt(struct morus640_state *state, - struct aead_request *req, - const struct morus640_ops *ops) -{ - struct skcipher_walk walk; - - ops->skcipher_walk_init(&walk, req, false); - - while (walk.nbytes) { - unsigned int nbytes = walk.nbytes; - - if (nbytes < walk.total) - nbytes = round_down(nbytes, walk.stride); - - ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr, - nbytes); - - skcipher_walk_done(&walk, walk.nbytes - nbytes); - } -} - -static void crypto_morus640_final(struct morus640_state *state, - struct morus640_block *tag_xor, - u64 assoclen, u64 cryptlen) -{ - struct morus640_block tmp; - unsigned int i; - - tmp.words[0] = lower_32_bits(assoclen * 8); - tmp.words[1] = upper_32_bits(assoclen * 8); - tmp.words[2] = lower_32_bits(cryptlen * 8); - tmp.words[3] = upper_32_bits(cryptlen * 8); - - for (i = 0; i < MORUS_BLOCK_WORDS; i++) - state->s[4].words[i] ^= state->s[0].words[i]; - - for (i = 0; i < 10; i++) - crypto_morus640_update(state, &tmp); - - crypto_morus640_core(state, tag_xor); -} - -static int crypto_morus640_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct morus640_ctx *ctx = crypto_aead_ctx(aead); - - if (keylen != MORUS640_BLOCK_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - crypto_morus640_load(&ctx->key, key); - return 0; -} - -static int crypto_morus640_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - return (authsize <= MORUS_MAX_AUTH_SIZE) ? 0 : -EINVAL; -} - -static void crypto_morus640_crypt(struct aead_request *req, - struct morus640_block *tag_xor, - unsigned int cryptlen, - const struct morus640_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus640_ctx *ctx = crypto_aead_ctx(tfm); - struct morus640_state state; - - crypto_morus640_init(&state, &ctx->key, req->iv); - crypto_morus640_process_ad(&state, req->src, req->assoclen); - crypto_morus640_process_crypt(&state, req, ops); - crypto_morus640_final(&state, tag_xor, req->assoclen, cryptlen); -} - -static int crypto_morus640_encrypt(struct aead_request *req) -{ - static const struct morus640_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_chunk = crypto_morus640_encrypt_chunk, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct morus640_block tag = {}; - union morus640_block_in tag_out; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_morus640_crypt(req, &tag, cryptlen, &ops); - crypto_morus640_store(tag_out.bytes, &tag); - - scatterwalk_map_and_copy(tag_out.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} - -static int crypto_morus640_decrypt(struct aead_request *req) -{ - static const struct morus640_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_chunk = crypto_morus640_decrypt_chunk, - }; - static const u8 zeros[MORUS640_BLOCK_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union morus640_block_in tag_in; - struct morus640_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag_in.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_morus640_load(&tag, tag_in.bytes); - crypto_morus640_crypt(req, &tag, cryptlen, &ops); - crypto_morus640_store(tag_in.bytes, &tag); - - return crypto_memneq(tag_in.bytes, zeros, authsize) ? -EBADMSG : 0; -} - -static int crypto_morus640_init_tfm(struct crypto_aead *tfm) -{ - return 0; -} - -static void crypto_morus640_exit_tfm(struct crypto_aead *tfm) -{ -} - -static struct aead_alg crypto_morus640_alg = { - .setkey = crypto_morus640_setkey, - .setauthsize = crypto_morus640_setauthsize, - .encrypt = crypto_morus640_encrypt, - .decrypt = crypto_morus640_decrypt, - .init = crypto_morus640_init_tfm, - .exit = crypto_morus640_exit_tfm, - - .ivsize = MORUS_NONCE_SIZE, - .maxauthsize = MORUS_MAX_AUTH_SIZE, - .chunksize = MORUS640_BLOCK_SIZE, - - .base = { - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct morus640_ctx), - .cra_alignmask = 0, - - .cra_priority = 100, - - .cra_name = "morus640", - .cra_driver_name = "morus640-generic", - - .cra_module = THIS_MODULE, - } -}; - -static int __init crypto_morus640_module_init(void) -{ - return crypto_register_aead(&crypto_morus640_alg); -} - -static void __exit crypto_morus640_module_exit(void) -{ - crypto_unregister_aead(&crypto_morus640_alg); -} - -subsys_initcall(crypto_morus640_module_init); -module_exit(crypto_morus640_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("MORUS-640 AEAD algorithm"); -MODULE_ALIAS_CRYPTO("morus640"); -MODULE_ALIAS_CRYPTO("morus640-generic"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5fe90ea46319..6258581aa628 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4768,18 +4768,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .hash = __VECS(michael_mic_tv_template) } - }, { - .alg = "morus1280", - .test = alg_test_aead, - .suite = { - .aead = __VECS(morus1280_tv_template) - } - }, { - .alg = "morus640", - .test = alg_test_aead, - .suite = { - .aead = __VECS(morus640_tv_template) - } }, { .alg = "nhpoly1305", .test = alg_test_hash, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index b743ca6d12cc..fca03fa018fc 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -20472,1713 +20472,6 @@ static const struct aead_testvec aegis256_tv_template[] = { }, }; -/* - * MORUS-640 test vectors - generated via reference implementation from - * SUPERCOP (https://bench.cr.yp.to/supercop.html): - * - * https://bench.cr.yp.to/supercop/supercop-20170228.tar.xz - * (see crypto_aead/morus640128v2/) - */ -static const struct aead_testvec morus640_tv_template[] = { - { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .iv = "\x0f\xc9\x8e\x67\x44\x9e\xaa\x86" - "\x20\x36\x2c\x24\xfe\xc9\x30\x81", - .assoc = "", - .alen = 0, - .ptext = "", - .plen = 0, - .ctext = "\x89\x62\x7d\xf3\x07\x9d\x52\x05" - "\x53\xc3\x04\x60\x93\xb4\x37\x9a", - .clen = 16, - }, { - .key = "\x3c\x24\x39\x9f\x10\x7b\xa8\x1b" - "\x80\xda\xb2\x91\xf9\x24\xc2\x06", - .klen = 16, - .iv = "\x4b\xed\xc8\x07\x54\x1a\x52\xa2" - "\xa1\x10\xde\xb5\xf8\xed\xf3\x87", - .assoc = "", - .alen = 0, - .ptext = "\x69", - .plen = 1, - .ctext = "\xa8\x8d\xe4\x90\xb5\x50\x8f\x78" - "\xb6\x10\x9a\x59\x5f\x61\x37\x70" - "\x09", - .clen = 17, - }, { - .key = "\x79\x49\x73\x3e\x20\xf7\x51\x37" - "\x01\xb4\x64\x22\xf3\x48\x85\x0c", - .klen = 16, - .iv = "\x88\x12\x01\xa6\x64\x96\xfb\xbe" - "\x22\xea\x90\x47\xf2\x11\xb5\x8e", - .assoc = "", - .alen = 0, - .ptext = "\xa6\xa4\x1e\x76\xec\xd4\x50\xcc" - "\x62\x58\xe9\x8f\xef\xa4\x17", - .plen = 15, - .ctext = "\x76\xdd\xb9\x05\x3d\xce\x61\x38" - "\xf3\xef\xf7\xe5\xd7\xfd\x70\xa5" - "\xcf\x9d\x64\xb8\x0a\x9f\xfd\x8b" - "\xd4\x6e\xfe\xd9\xc8\x63\x4b", - .clen = 31, - }, { - .key = "\xb5\x6e\xad\xdd\x30\x72\xfa\x53" - "\x82\x8e\x16\xb4\xed\x6d\x47\x12", - .klen = 16, - .iv = "\xc4\x37\x3b\x45\x74\x11\xa4\xda" - "\xa2\xc5\x42\xd8\xec\x36\x78\x94", - .assoc = "", - .alen = 0, - .ptext = "\xe2\xc9\x58\x15\xfc\x4f\xf8\xe8" - "\xe3\x32\x9b\x21\xe9\xc8\xd9\x97", - .plen = 16, - .ctext = "\xdc\x72\xe8\x14\xfb\x63\xad\x72" - "\x1f\x57\x9a\x1f\x88\x81\xdb\xd6" - "\xc1\x91\x9d\xb9\x25\xc4\x99\x4c" - "\x97\xcd\x8a\x0c\x9d\x68\x00\x1c", - .clen = 32, - }, { - .key = "\xf2\x92\xe6\x7d\x40\xee\xa3\x6f" - "\x03\x68\xc8\x45\xe7\x91\x0a\x18", - .klen = 16, - .iv = "\x01\x5c\x75\xe5\x84\x8d\x4d\xf6" - "\x23\x9f\xf4\x6a\xe6\x5a\x3b\x9a", - .assoc = "", - .alen = 0, - .ptext = "\x1f\xee\x92\xb4\x0c\xcb\xa1\x04" - "\x64\x0c\x4d\xb2\xe3\xec\x9c\x9d" - "\x09", - .plen = 17, - .ctext = "\x6b\x4f\x3b\x90\x9a\xa2\xb3\x82" - "\x0a\xb8\x55\xee\xeb\x73\x4d\x7f" - "\x54\x11\x3a\x8a\x31\xa3\xb5\xf2" - "\xcd\x49\xdb\xf3\xee\x26\xbd\xa2" - "\x0d", - .clen = 33, - }, { - .key = "\x2e\xb7\x20\x1c\x50\x6a\x4b\x8b" - "\x84\x42\x7a\xd7\xe1\xb5\xcd\x1f", - .klen = 16, - .iv = "\x3d\x80\xae\x84\x94\x09\xf6\x12" - "\xa4\x79\xa6\xfb\xe0\x7f\xfd\xa0", - .assoc = "", - .alen = 0, - .ptext = "\x5c\x13\xcb\x54\x1c\x47\x4a\x1f" - "\xe5\xe6\xff\x44\xdd\x11\x5f\xa3" - "\x33\xdd\xc2\xf8\xdd\x18\x2b\x93" - "\x57\x05\x01\x1c\x66\x22\xd3", - .plen = 31, - .ctext = "\x59\xd1\x0f\x6b\xee\x27\x84\x92" - "\xb7\xa9\xb5\xdd\x02\xa4\x12\xa5" - "\x50\x32\xb4\x9a\x2e\x35\x83\x55" - "\x36\x12\x12\xed\xa3\x31\xc5\x30" - "\xa7\xe2\x4a\x6d\x05\x59\x43\x91" - "\x75\xfa\x6c\x17\xc6\x73\xca", - .clen = 47, - }, { - .key = "\x6b\xdc\x5a\xbb\x60\xe5\xf4\xa6" - "\x05\x1d\x2c\x68\xdb\xda\x8f\x25", - .klen = 16, - .iv = "\x7a\xa5\xe8\x23\xa4\x84\x9e\x2d" - "\x25\x53\x58\x8c\xda\xa3\xc0\xa6", - .assoc = "", - .alen = 0, - .ptext = "\x98\x37\x05\xf3\x2c\xc2\xf3\x3b" - "\x66\xc0\xb1\xd5\xd7\x35\x21\xaa" - "\x5d\x9f\xce\x7c\xe2\xb8\xad\xad" - "\x19\x33\xe0\xf4\x40\x81\x72\x28", - .plen = 32, - .ctext = "\xdb\x49\x68\x0f\x91\x5b\x21\xb1" - "\xcf\x50\xb2\x4c\x32\xe1\xa6\x69" - "\xc0\xfb\x44\x1f\xa0\x9a\xeb\x39" - "\x1b\xde\x68\x38\xcc\x27\x52\xc5" - "\xf6\x3e\x74\xea\x66\x5b\x5f\x0c" - "\x65\x9e\x58\xe6\x52\xa2\xfe\x59", - .clen = 48, - }, { - .key = "\xa7\x00\x93\x5b\x70\x61\x9d\xc2" - "\x86\xf7\xde\xfa\xd5\xfe\x52\x2b", - .klen = 16, - .iv = "\xb6\xca\x22\xc3\xb4\x00\x47\x49" - "\xa6\x2d\x0a\x1e\xd4\xc7\x83\xad", - .assoc = "\xc5", - .alen = 1, - .ptext = "", - .plen = 0, - .ctext = "\x56\xe7\x24\x52\xdd\x95\x60\x5b" - "\x09\x48\x39\x69\x9c\xb3\x62\x46", - .clen = 16, - }, { - .key = "\xe4\x25\xcd\xfa\x80\xdd\x46\xde" - "\x07\xd1\x90\x8b\xcf\x23\x15\x31", - .klen = 16, - .iv = "\xf3\xee\x5c\x62\xc4\x7c\xf0\x65" - "\x27\x08\xbd\xaf\xce\xec\x45\xb3", - .assoc = "\x02\xb8\xea\xca\x09\x1b\x9a\xec" - "\x47\x3e\xe9\xd4\xcc\xb5\x76", - .alen = 15, - .ptext = "", - .plen = 0, - .ctext = "\xdd\xfa\x6c\x1f\x5d\x86\x87\x01" - "\x13\xe5\x73\x46\x46\xf2\x5c\xe1", - .clen = 16, - }, { - .key = "\x20\x4a\x07\x99\x91\x58\xee\xfa" - "\x88\xab\x42\x1c\xc9\x47\xd7\x38", - .klen = 16, - .iv = "\x2f\x13\x95\x01\xd5\xf7\x99\x81" - "\xa8\xe2\x6f\x41\xc8\x10\x08\xb9", - .assoc = "\x3f\xdc\x24\x69\x19\x96\x43\x08" - "\xc8\x18\x9b\x65\xc6\xd9\x39\x3b", - .alen = 16, - .ptext = "", - .plen = 0, - .ctext = "\xa6\x1b\xb9\xd7\x5e\x3c\xcf\xac" - "\xa9\x21\x45\x0b\x16\x52\xf7\xe1", - .clen = 16, - }, { - .key = "\x5d\x6f\x41\x39\xa1\xd4\x97\x16" - "\x09\x85\xf4\xae\xc3\x6b\x9a\x3e", - .klen = 16, - .iv = "\x6c\x38\xcf\xa1\xe5\x73\x41\x9d" - "\x29\xbc\x21\xd2\xc2\x35\xcb\xbf", - .assoc = "\x7b\x01\x5d\x08\x29\x12\xec\x24" - "\x49\xf3\x4d\xf7\xc0\xfe\xfb\x41" - "\x3c", - .alen = 17, - .ptext = "", - .plen = 0, - .ctext = "\x15\xff\xde\x3b\x34\xfc\xf6\xf9" - "\xbb\xa8\x62\xad\x0a\xf5\x48\x60", - .clen = 16, - }, { - .key = "\x99\x93\x7a\xd8\xb1\x50\x40\x31" - "\x8a\x60\xa6\x3f\xbd\x90\x5d\x44", - .klen = 16, - .iv = "\xa8\x5c\x09\x40\xf5\xef\xea\xb8" - "\xaa\x96\xd3\x64\xbc\x59\x8d\xc6", - .assoc = "\xb8\x26\x97\xa8\x39\x8e\x94\x3f" - "\xca\xcd\xff\x88\xba\x22\xbe\x47" - "\x67\xba\x85\xf1\xbb\x30\x56\x26" - "\xaf\x0b\x02\x38\xcc\x44\xa7", - .alen = 31, - .ptext = "", - .plen = 0, - .ctext = "\xd2\x9d\xf8\x3b\xd7\x84\xe9\x2d" - "\x4b\xef\x75\x16\x0a\x99\xae\x6b", - .clen = 16, - }, { - .key = "\xd6\xb8\xb4\x77\xc1\xcb\xe9\x4d" - "\x0a\x3a\x58\xd1\xb7\xb4\x1f\x4a", - .klen = 16, - .iv = "\xe5\x81\x42\xdf\x05\x6a\x93\xd4" - "\x2b\x70\x85\xf5\xb6\x7d\x50\xcc", - .assoc = "\xf4\x4a\xd1\x47\x49\x09\x3d\x5b" - "\x4b\xa7\xb1\x19\xb4\x46\x81\x4d" - "\x91\x7c\x91\x75\xc0\xd0\xd8\x40" - "\x71\x39\xe1\x10\xa6\xa3\x46\x7a", - .alen = 32, - .ptext = "", - .plen = 0, - .ctext = "\xe4\x8d\xa7\xa7\x45\xc1\x31\x4f" - "\xce\xfb\xaf\xd6\xc2\xe6\xee\xc0", - .clen = 16, - }, { - .key = "\x12\xdd\xee\x17\xd1\x47\x92\x69" - "\x8b\x14\x0a\x62\xb1\xd9\xe2\x50", - .klen = 16, - .iv = "\x22\xa6\x7c\x7f\x15\xe6\x3c\xf0" - "\xac\x4b\x37\x86\xb0\xa2\x13\xd2", - .assoc = "\x31", - .alen = 1, - .ptext = "\x40", - .plen = 1, - .ctext = "\xe2\x67\x38\x4f\xb9\xad\x7d\x38" - "\x01\xfe\x84\x14\x85\xf8\xd1\xe3" - "\x22", - .clen = 17, - }, { - .key = "\x4f\x01\x27\xb6\xe1\xc3\x3a\x85" - "\x0c\xee\xbc\xf4\xab\xfd\xa5\x57", - .klen = 16, - .iv = "\x5e\xcb\xb6\x1e\x25\x62\xe4\x0c" - "\x2d\x25\xe9\x18\xaa\xc6\xd5\xd8", - .assoc = "\x6d\x94\x44\x86\x69\x00\x8f\x93" - "\x4d\x5b\x15\x3c\xa8\x8f\x06", - .alen = 15, - .ptext = "\x7c\x5d\xd3\xee\xad\x9f\x39\x1a" - "\x6d\x92\x42\x61\xa7\x58\x37", - .plen = 15, - .ctext = "\x77\x32\x61\xeb\xb4\x33\x29\x92" - "\x29\x95\xc5\x8e\x85\x76\xab\xfc" - "\x07\x95\xa7\x44\x74\xf7\x22\xff" - "\xd8\xd8\x36\x3d\x8a\x7f\x9e", - .clen = 31, - }, { - .key = "\x8b\x26\x61\x55\xf1\x3e\xe3\xa1" - "\x8d\xc8\x6e\x85\xa5\x21\x67\x5d", - .klen = 16, - .iv = "\x9b\xef\xf0\xbd\x35\xdd\x8d\x28" - "\xad\xff\x9b\xa9\xa4\xeb\x98\xdf", - .assoc = "\xaa\xb8\x7e\x25\x79\x7c\x37\xaf" - "\xce\x36\xc7\xce\xa2\xb4\xc9\x60", - .alen = 16, - .ptext = "\xb9\x82\x0c\x8d\xbd\x1b\xe2\x36" - "\xee\x6c\xf4\xf2\xa1\x7d\xf9\xe2", - .plen = 16, - .ctext = "\xd8\xfd\x44\x45\xf6\x42\x12\x38" - "\xf2\x0b\xea\x4f\x9e\x11\x61\x07" - "\x48\x67\x98\x18\x9b\xd0\x0c\x59" - "\x67\xa4\x11\xb3\x2b\xd6\xc1\x70", - .clen = 32, - }, { - .key = "\xc8\x4b\x9b\xf5\x01\xba\x8c\xbd" - "\x0e\xa3\x21\x16\x9f\x46\x2a\x63", - .klen = 16, - .iv = "\xd7\x14\x29\x5d\x45\x59\x36\x44" - "\x2e\xd9\x4d\x3b\x9e\x0f\x5b\xe5", - .assoc = "\xe6\xdd\xb8\xc4\x89\xf8\xe0\xca" - "\x4f\x10\x7a\x5f\x9c\xd8\x8b\x66" - "\x3b", - .alen = 17, - .ptext = "\xf5\xa6\x46\x2c\xce\x97\x8a\x51" - "\x6f\x46\xa6\x83\x9b\xa1\xbc\xe8" - "\x05", - .plen = 17, - .ctext = "\xb1\xab\x53\x4e\xc7\x40\x16\xb6" - "\x71\x3a\x00\x9f\x41\x88\xb0\xb2" - "\x71\x83\x85\x5f\xc8\x79\x0a\x99" - "\x99\xdc\x89\x1c\x88\xd2\x3e\xf9" - "\x83", - .clen = 33, - }, { - .key = "\x05\x70\xd5\x94\x12\x36\x35\xd8" - "\x8f\x7d\xd3\xa8\x99\x6a\xed\x69", - .klen = 16, - .iv = "\x14\x39\x63\xfc\x56\xd5\xdf\x5f" - "\xaf\xb3\xff\xcc\x98\x33\x1d\xeb", - .assoc = "\x23\x02\xf1\x64\x9a\x73\x89\xe6" - "\xd0\xea\x2c\xf1\x96\xfc\x4e\x6d" - "\x65\x48\xcb\x0a\xda\xf0\x62\xc0" - "\x38\x1d\x3b\x4a\xe9\x7e\x62", - .alen = 31, - .ptext = "\x32\xcb\x80\xcc\xde\x12\x33\x6d" - "\xf0\x20\x58\x15\x95\xc6\x7f\xee" - "\x2f\xf9\x4e\x2c\x1b\x98\x43\xc7" - "\x68\x28\x73\x40\x9f\x96\x4a", - .plen = 31, - .ctext = "\x29\xc4\xf0\x03\xc1\x86\xdf\x06" - "\x5c\x7b\xef\x64\x87\x00\xd1\x37" - "\xa7\x08\xbc\x7f\x8f\x41\x54\xd0" - "\x3e\xf1\xc3\xa2\x96\x84\xdd\x2a" - "\x2d\x21\x30\xf9\x02\xdb\x06\x0c" - "\xf1\x5a\x66\x69\xe0\xca\x83", - .clen = 47, - }, { - .key = "\x41\x94\x0e\x33\x22\xb1\xdd\xf4" - "\x10\x57\x85\x39\x93\x8f\xaf\x70", - .klen = 16, - .iv = "\x50\x5d\x9d\x9b\x66\x50\x88\x7b" - "\x30\x8e\xb1\x5e\x92\x58\xe0\xf1", - .assoc = "\x5f\x27\x2b\x03\xaa\xef\x32\x02" - "\x50\xc4\xde\x82\x90\x21\x11\x73" - "\x8f\x0a\xd6\x8f\xdf\x90\xe4\xda" - "\xf9\x4a\x1a\x23\xc3\xdd\x02\x81", - .alen = 32, - .ptext = "\x6e\xf0\xba\x6b\xee\x8e\xdc\x89" - "\x71\xfb\x0a\xa6\x8f\xea\x41\xf4" - "\x5a\xbb\x59\xb0\x20\x38\xc5\xe0" - "\x29\x56\x52\x19\x79\xf5\xe9\x37", - .plen = 32, - .ctext = "\xe2\x2e\x44\xdf\xd3\x60\x6d\xb2" - "\x70\x57\x37\xc5\xc2\x4f\x8d\x14" - "\xc6\xbf\x8b\xec\xf5\x62\x67\xf2" - "\x2f\xa1\xe6\xd6\xa7\xb1\x8c\x54" - "\xe5\x6b\x49\xf9\x6e\x90\xc3\xaa" - "\x7a\x00\x2e\x4d\x7f\x31\x2e\x81", - .clen = 48, - }, { - .key = "\x7e\xb9\x48\xd3\x32\x2d\x86\x10" - "\x91\x31\x37\xcb\x8d\xb3\x72\x76", - .klen = 16, - .iv = "\x8d\x82\xd6\x3b\x76\xcc\x30\x97" - "\xb1\x68\x63\xef\x8c\x7c\xa3\xf7", - .assoc = "\x9c\x4b\x65\xa2\xba\x6b\xdb\x1e" - "\xd1\x9e\x90\x13\x8a\x45\xd3\x79" - "\xba\xcd\xe2\x13\xe4\x30\x66\xf4" - "\xba\x78\xf9\xfb\x9d\x3c\xa1\x58" - "\x1a", - .alen = 33, - .ptext = "\xab\x14\xf3\x0a\xfe\x0a\x85\xa5" - "\xf2\xd5\xbc\x38\x89\x0e\x04\xfb" - "\x84\x7d\x65\x34\x25\xd8\x47\xfa" - "\xeb\x83\x31\xf1\x54\x54\x89\x0d" - "\x9d\x4d\x54\x51\x84\x61\xf6\x8e" - "\x03\x31\xf2\x25\x16\xcc\xaa\xc6" - "\x75\x73\x20\x30\x59\x54\xb2\xf0" - "\x3a\x4b\xe0\x23\x8e\xa6\x08\x35" - "\x8a", - .plen = 65, - .ctext = "\xc7\xca\x26\x61\x57\xee\xa2\xb9" - "\xb1\x37\xde\x95\x06\x90\x11\x08" - "\x4d\x30\x9f\x24\xc0\x56\xb7\xe1" - "\x0b\x9f\xd2\x57\xe9\xd2\xb1\x76" - "\x56\x9a\xb4\x58\xc5\x08\xfc\xb5" - "\xf2\x31\x9b\xc9\xcd\xb3\x64\xdb" - "\x6f\x50\xbf\xf4\x73\x9d\xfb\x6b" - "\xef\x35\x25\x48\xed\xcf\x29\xa8" - "\xac\xc3\xb9\xcb\x61\x8f\x73\x92" - "\x2c\x7a\x6f\xda\xf9\x09\x6f\xe1" - "\xc4", - .clen = 81, - }, { - .key = "\xba\xde\x82\x72\x42\xa9\x2f\x2c" - "\x12\x0b\xe9\x5c\x87\xd7\x35\x7c", - .klen = 16, - .iv = "\xc9\xa7\x10\xda\x86\x48\xd9\xb3" - "\x32\x42\x15\x80\x85\xa1\x65\xfe", - .assoc = "\xd8\x70\x9f\x42\xca\xe6\x83\x3a" - "\x52\x79\x42\xa5\x84\x6a\x96\x7f" - "\xe4\x8f\xed\x97\xe9\xd0\xe8\x0d" - "\x7c\xa6\xd8\xd4\x77\x9b\x40\x2e" - "\x28\xce\x57\x34\xcd\x6e\x84\x4c" - "\x17\x3c\xe1\xb2\xa8\x0b\xbb\xf1" - "\x96\x41\x0d\x69\xe8\x54\x0a\xc8" - "\x15\x4e\x91\x92\x89\x4b\xb7\x9b" - "\x21", - .alen = 65, - .ptext = "\xe8\x39\x2d\xaa\x0e\x85\x2d\xc1" - "\x72\xaf\x6e\xc9\x82\x33\xc7\x01" - "\xaf\x40\x70\xb8\x2a\x78\xc9\x14" - "\xac\xb1\x10\xca\x2e\xb3\x28\xe4" - "\xac", - .plen = 33, - .ctext = "\x57\xcd\x3d\x46\xc5\xf9\x68\x3b" - "\x2c\x0f\xb4\x7e\x7b\x64\x3e\x40" - "\xf3\x78\x63\x34\x89\x79\x39\x6b" - "\x61\x64\x4a\x9a\xfa\x70\xa4\xd3" - "\x54\x0b\xea\x05\xa6\x95\x64\xed" - "\x3d\x69\xa2\x0c\x27\x56\x2f\x34" - "\x66", - .clen = 49, - }, { - .key = "\xf7\x02\xbb\x11\x52\x24\xd8\x48" - "\x93\xe6\x9b\xee\x81\xfc\xf7\x82", - .klen = 16, - .iv = "\x06\xcc\x4a\x79\x96\xc3\x82\xcf" - "\xb3\x1c\xc7\x12\x7f\xc5\x28\x04", - .assoc = "\x15\x95\xd8\xe1\xda\x62\x2c\x56" - "\xd3\x53\xf4\x36\x7e\x8e\x59\x85", - .alen = 16, - .ptext = "\x24\x5e\x67\x49\x1e\x01\xd6\xdd" - "\xf3\x89\x20\x5b\x7c\x57\x89\x07", - .plen = 16, - .ctext = "\xfc\x85\x06\x28\x8f\xe8\x23\x1f" - "\x33\x98\x87\xde\x08\xb6\xb6\xae" - "\x3e\xa4\xf8\x19\xf1\x92\x60\x39" - "\xb9\x6b\x3f\xdf\xc8\xcb\x30", - .clen = 31, - }, { - .key = "\x33\x27\xf5\xb1\x62\xa0\x80\x63" - "\x14\xc0\x4d\x7f\x7b\x20\xba\x89", - .klen = 16, - .iv = "\x42\xf0\x84\x19\xa6\x3f\x2b\xea" - "\x34\xf6\x79\xa3\x79\xe9\xeb\x0a", - .assoc = "\x51\xb9\x12\x80\xea\xde\xd5\x71" - "\x54\x2d\xa6\xc8\x78\xb2\x1b\x8c", - .alen = 16, - .ptext = "\x61\x83\xa0\xe8\x2e\x7d\x7f\xf8" - "\x74\x63\xd2\xec\x76\x7c\x4c\x0d", - .plen = 16, - .ctext = "\x74\x7d\x70\x07\xe9\xba\x01\xee" - "\x6c\xc6\x6f\x50\x25\x33\xbe\x50" - "\x17\xb8\x17\x62\xed\x80\xa2\xf5" - "\x03\xde\x85\x71\x5d\x34", - .clen = 30, - }, { - .key = "\x70\x4c\x2f\x50\x72\x1c\x29\x7f" - "\x95\x9a\xff\x10\x75\x45\x7d\x8f", - .klen = 16, - .iv = "\x7f\x15\xbd\xb8\xb6\xba\xd3\x06" - "\xb5\xd1\x2b\x35\x73\x0e\xad\x10", - .assoc = "\x8e\xde\x4c\x20\xfa\x59\x7e\x8d" - "\xd5\x07\x58\x59\x72\xd7\xde\x92", - .alen = 16, - .ptext = "\x9d\xa7\xda\x88\x3e\xf8\x28\x14" - "\xf5\x3e\x85\x7d\x70\xa0\x0f\x13", - .plen = 16, - .ctext = "\xf4\xb3\x85\xf9\xac\xde\xb1\x38" - "\x29\xfd\x6c\x7c\x49\xe5\x1d\xaf" - "\xba\xea\xd4\xfa\x3f\x11\x33\x98", - .clen = 24, - }, { - .key = "\xac\x70\x69\xef\x82\x97\xd2\x9b" - "\x15\x74\xb1\xa2\x6f\x69\x3f\x95", - .klen = 16, - .iv = "\xbb\x3a\xf7\x57\xc6\x36\x7c\x22" - "\x36\xab\xde\xc6\x6d\x32\x70\x17", - .assoc = "\xcb\x03\x85\xbf\x0a\xd5\x26\xa9" - "\x56\xe1\x0a\xeb\x6c\xfb\xa1\x98", - .alen = 16, - .ptext = "\xda\xcc\x14\x27\x4e\x74\xd1\x30" - "\x76\x18\x37\x0f\x6a\xc4\xd1\x1a", - .plen = 16, - .ctext = "\xe6\x5c\x49\x4f\x78\xf3\x62\x86" - "\xe1\xb7\xa5\xc3\x32\x88\x3c\x8c" - "\x6e", - .clen = 17, - }, -}; - -/* - * MORUS-1280 test vectors - generated via reference implementation from - * SUPERCOP (https://bench.cr.yp.to/supercop.html): - * - * https://bench.cr.yp.to/supercop/supercop-20170228.tar.xz - * (see crypto_aead/morus1280128v2/ and crypto_aead/morus1280256v2/ ) - */ -static const struct aead_testvec morus1280_tv_template[] = { - { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .iv = "\x0f\xc9\x8e\x67\x44\x9e\xaa\x86" - "\x20\x36\x2c\x24\xfe\xc9\x30\x81", - .assoc = "", - .alen = 0, - .ptext = "", - .plen = 0, - .ctext = "\x91\x85\x0f\xf5\x52\x9e\xce\xce" - "\x65\x99\xc7\xbf\xd3\x76\xe8\x98", - .clen = 16, - }, { - .key = "\x3c\x24\x39\x9f\x10\x7b\xa8\x1b" - "\x80\xda\xb2\x91\xf9\x24\xc2\x06", - .klen = 16, - .iv = "\x4b\xed\xc8\x07\x54\x1a\x52\xa2" - "\xa1\x10\xde\xb5\xf8\xed\xf3\x87", - .assoc = "", - .alen = 0, - .ptext = "\x69", - .plen = 1, - .ctext = "\x88\xc3\x4c\xf0\x2f\x43\x76\x13" - "\x96\xda\x76\x34\x33\x4e\xd5\x39" - "\x73", - .clen = 17, - }, { - .key = "\x79\x49\x73\x3e\x20\xf7\x51\x37" - "\x01\xb4\x64\x22\xf3\x48\x85\x0c", - .klen = 16, - .iv = "\x88\x12\x01\xa6\x64\x96\xfb\xbe" - "\x22\xea\x90\x47\xf2\x11\xb5\x8e", - .assoc = "", - .alen = 0, - .ptext = "\xa6\xa4\x1e\x76\xec\xd4\x50\xcc" - "\x62\x58\xe9\x8f\xef\xa4\x17\x91" - "\xb4\x96\x9f\x6b\xce\x38\xa5\x46" - "\x13\x7d\x64\x93\xd7\x05\xf5", - .plen = 31, - .ctext = "\x3e\x5c\x3b\x58\x3b\x7d\x2a\x22" - "\x75\x0b\x24\xa6\x0e\xc3\xde\x52" - "\x97\x0b\x64\xd4\xce\x90\x52\xf7" - "\xef\xdb\x6a\x38\xd2\xa8\xa1\x0d" - "\xe0\x61\x33\x24\xc6\x4d\x51\xbc" - "\xa4\x21\x74\xcf\x19\x16\x59", - .clen = 47, - }, { - .key = "\xb5\x6e\xad\xdd\x30\x72\xfa\x53" - "\x82\x8e\x16\xb4\xed\x6d\x47\x12", - .klen = 16, - .iv = "\xc4\x37\x3b\x45\x74\x11\xa4\xda" - "\xa2\xc5\x42\xd8\xec\x36\x78\x94", - .assoc = "", - .alen = 0, - .ptext = "\xe2\xc9\x58\x15\xfc\x4f\xf8\xe8" - "\xe3\x32\x9b\x21\xe9\xc8\xd9\x97" - "\xde\x58\xab\xf0\xd3\xd8\x27\x60" - "\xd5\xaa\x43\x6b\xb1\x64\x95\xa4", - .plen = 32, - .ctext = "\x30\x82\x9c\x2b\x67\xcb\xf9\x1f" - "\xde\x9f\x77\xb2\xda\x92\x61\x5c" - "\x09\x0b\x2d\x9a\x26\xaa\x1c\x06" - "\xab\x74\xb7\x2b\x95\x5f\x9f\xa1" - "\x9a\xff\x50\xa0\xa2\xff\xc5\xad" - "\x21\x8e\x84\x5c\x12\x61\xb2\xae", - .clen = 48, - }, { - .key = "\xf2\x92\xe6\x7d\x40\xee\xa3\x6f" - "\x03\x68\xc8\x45\xe7\x91\x0a\x18", - .klen = 16, - .iv = "\x01\x5c\x75\xe5\x84\x8d\x4d\xf6" - "\x23\x9f\xf4\x6a\xe6\x5a\x3b\x9a", - .assoc = "", - .alen = 0, - .ptext = "\x1f\xee\x92\xb4\x0c\xcb\xa1\x04" - "\x64\x0c\x4d\xb2\xe3\xec\x9c\x9d" - "\x09\x1a\xb7\x74\xd8\x78\xa9\x79" - "\x96\xd8\x22\x43\x8c\xc3\x34\x7b" - "\xc4", - .plen = 33, - .ctext = "\x67\x5d\x8e\x45\xc8\x39\xf5\x17" - "\xc1\x1d\x2a\xdd\x88\x67\xda\x1f" - "\x6d\xe8\x37\x28\x5a\xc1\x5e\x9f" - "\xa6\xec\xc6\x92\x05\x4b\xc0\xa3" - "\x63\xef\x88\xa4\x9b\x0a\x5c\xed" - "\x2b\x6a\xac\x63\x52\xaa\x10\x94" - "\xd0", - .clen = 49, - }, { - .key = "\x2e\xb7\x20\x1c\x50\x6a\x4b\x8b" - "\x84\x42\x7a\xd7\xe1\xb5\xcd\x1f", - .klen = 16, - .iv = "\x3d\x80\xae\x84\x94\x09\xf6\x12" - "\xa4\x79\xa6\xfb\xe0\x7f\xfd\xa0", - .assoc = "", - .alen = 0, - .ptext = "\x5c\x13\xcb\x54\x1c\x47\x4a\x1f" - "\xe5\xe6\xff\x44\xdd\x11\x5f\xa3" - "\x33\xdd\xc2\xf8\xdd\x18\x2b\x93" - "\x57\x05\x01\x1c\x66\x22\xd3\x51" - "\xd3\xdf\x18\xc9\x30\x66\xed\xb1" - "\x96\x58\xd5\x8c\x64\x8c\x7c\xf5" - "\x01\xd0\x74\x5f\x9b\xaa\xf6\xd1" - "\xe6\x16\xa2\xac\xde\x47\x40", - .plen = 63, - .ctext = "\x7d\x61\x1a\x35\x20\xcc\x07\x88" - "\x03\x98\x87\xcf\xc0\x6e\x4d\x19" - "\xe3\xd4\x0b\xfb\x29\x8f\x49\x1a" - "\x3a\x06\x77\xce\x71\x2c\xcd\xdd" - "\xed\xf6\xc9\xbe\xa6\x3b\xb8\xfc" - "\x6c\xbe\x77\xed\x74\x0e\x20\x85" - "\xd0\x65\xde\x24\x6f\xe3\x25\xc5" - "\xdf\x5b\x0f\xbd\x8a\x88\x78\xc9" - "\xe5\x81\x37\xde\x84\x7a\xf6\x84" - "\x99\x7a\x72\x9c\x54\x31\xa1", - .clen = 79, - }, { - .key = "\x6b\xdc\x5a\xbb\x60\xe5\xf4\xa6" - "\x05\x1d\x2c\x68\xdb\xda\x8f\x25", - .klen = 16, - .iv = "\x7a\xa5\xe8\x23\xa4\x84\x9e\x2d" - "\x25\x53\x58\x8c\xda\xa3\xc0\xa6", - .assoc = "", - .alen = 0, - .ptext = "\x98\x37\x05\xf3\x2c\xc2\xf3\x3b" - "\x66\xc0\xb1\xd5\xd7\x35\x21\xaa" - "\x5d\x9f\xce\x7c\xe2\xb8\xad\xad" - "\x19\x33\xe0\xf4\x40\x81\x72\x28" - "\xe1\x8b\x1c\xf8\x91\x78\xff\xaf" - "\xb0\x68\x69\xf2\x27\x35\x91\x84" - "\x2e\x37\x5b\x00\x04\xff\x16\x9c" - "\xb5\x19\x39\xeb\xd9\xcd\x29\x9a", - .plen = 64, - .ctext = "\x05\xc5\xb1\xf9\x1b\xb9\xab\x2c" - "\xa5\x07\x12\xa7\x12\x39\x60\x66" - "\x30\x81\x4a\x03\x78\x28\x45\x52" - "\xd2\x2b\x24\xfd\x8b\xa5\xb7\x66" - "\x6f\x45\xd7\x3b\x67\x6f\x51\xb9" - "\xc0\x3d\x6c\xca\x1e\xae\xff\xb6" - "\x79\xa9\xe4\x82\x5d\x4c\x2d\xdf" - "\xeb\x71\x40\xc9\x2c\x40\x45\x6d" - "\x73\x77\x01\xf3\x4f\xf3\x9d\x2a" - "\x5d\x57\xa8\xa1\x18\xa2\xad\xcb", - .clen = 80, - }, { - .key = "\xa7\x00\x93\x5b\x70\x61\x9d\xc2" - "\x86\xf7\xde\xfa\xd5\xfe\x52\x2b", - .klen = 16, - .iv = "\xb6\xca\x22\xc3\xb4\x00\x47\x49" - "\xa6\x2d\x0a\x1e\xd4\xc7\x83\xad", - .assoc = "\xc5", - .alen = 1, - .ptext = "", - .plen = 0, - .ctext = "\x4d\xbf\x11\xac\x7f\x97\x0b\x2e" - "\x89\x3b\x9d\x0f\x83\x1c\x08\xc3", - .clen = 16, - }, { - .key = "\xe4\x25\xcd\xfa\x80\xdd\x46\xde" - "\x07\xd1\x90\x8b\xcf\x23\x15\x31", - .klen = 16, - .iv = "\xf3\xee\x5c\x62\xc4\x7c\xf0\x65" - "\x27\x08\xbd\xaf\xce\xec\x45\xb3", - .assoc = "\x02\xb8\xea\xca\x09\x1b\x9a\xec" - "\x47\x3e\xe9\xd4\xcc\xb5\x76\x34" - "\xe8\x73\x62\x64\xab\x50\xd0\xda" - "\x6b\x83\x66\xaf\x3e\x27\xc9", - .alen = 31, - .ptext = "", - .plen = 0, - .ctext = "\x5b\xc0\x8d\x54\xe4\xec\xbe\x38" - "\x03\x12\xf9\xcc\x9e\x46\x42\x92", - .clen = 16, - }, { - .key = "\x20\x4a\x07\x99\x91\x58\xee\xfa" - "\x88\xab\x42\x1c\xc9\x47\xd7\x38", - .klen = 16, - .iv = "\x2f\x13\x95\x01\xd5\xf7\x99\x81" - "\xa8\xe2\x6f\x41\xc8\x10\x08\xb9", - .assoc = "\x3f\xdc\x24\x69\x19\x96\x43\x08" - "\xc8\x18\x9b\x65\xc6\xd9\x39\x3b" - "\x12\x35\x6e\xe8\xb0\xf0\x52\xf3" - "\x2d\xb0\x45\x87\x18\x86\x68\xf6", - .alen = 32, - .ptext = "", - .plen = 0, - .ctext = "\x48\xc5\xc3\x4c\x40\x2e\x2f\xc2" - "\x6d\x65\xe0\x67\x9c\x1d\xa0\xf0", - .clen = 16, - }, { - .key = "\x5d\x6f\x41\x39\xa1\xd4\x97\x16" - "\x09\x85\xf4\xae\xc3\x6b\x9a\x3e", - .klen = 16, - .iv = "\x6c\x38\xcf\xa1\xe5\x73\x41\x9d" - "\x29\xbc\x21\xd2\xc2\x35\xcb\xbf", - .assoc = "\x7b\x01\x5d\x08\x29\x12\xec\x24" - "\x49\xf3\x4d\xf7\xc0\xfe\xfb\x41" - "\x3c\xf8\x79\x6c\xb6\x90\xd4\x0d" - "\xee\xde\x23\x60\xf2\xe5\x08\xcc" - "\x97", - .alen = 33, - .ptext = "", - .plen = 0, - .ctext = "\x28\x64\x78\x51\x55\xd8\x56\x4a" - "\x58\x3e\xf7\xbe\xee\x21\xfe\x94", - .clen = 16, - }, { - .key = "\x99\x93\x7a\xd8\xb1\x50\x40\x31" - "\x8a\x60\xa6\x3f\xbd\x90\x5d\x44", - .klen = 16, - .iv = "\xa8\x5c\x09\x40\xf5\xef\xea\xb8" - "\xaa\x96\xd3\x64\xbc\x59\x8d\xc6", - .assoc = "\xb8\x26\x97\xa8\x39\x8e\x94\x3f" - "\xca\xcd\xff\x88\xba\x22\xbe\x47" - "\x67\xba\x85\xf1\xbb\x30\x56\x26" - "\xaf\x0b\x02\x38\xcc\x44\xa7\xa3" - "\xa6\xbf\x31\x93\x60\xcd\xda\x63" - "\x2c\xb1\xaa\x19\xc8\x19\xf8\xeb" - "\x03\xa1\xe8\xbe\x37\x54\xec\xa2" - "\xcd\x2c\x45\x58\xbd\x8e\x80", - .alen = 63, - .ptext = "", - .plen = 0, - .ctext = "\xb3\xa6\x00\x4e\x09\x20\xac\x21" - "\x77\x72\x69\x76\x2d\x36\xe5\xc8", - .clen = 16, - }, { - .key = "\xd6\xb8\xb4\x77\xc1\xcb\xe9\x4d" - "\x0a\x3a\x58\xd1\xb7\xb4\x1f\x4a", - .klen = 16, - .iv = "\xe5\x81\x42\xdf\x05\x6a\x93\xd4" - "\x2b\x70\x85\xf5\xb6\x7d\x50\xcc", - .assoc = "\xf4\x4a\xd1\x47\x49\x09\x3d\x5b" - "\x4b\xa7\xb1\x19\xb4\x46\x81\x4d" - "\x91\x7c\x91\x75\xc0\xd0\xd8\x40" - "\x71\x39\xe1\x10\xa6\xa3\x46\x7a" - "\xb4\x6b\x35\xc2\xc1\xdf\xed\x60" - "\x46\xc1\x3e\x7f\x8c\xc2\x0e\x7a" - "\x30\x08\xd0\x5f\xa0\xaa\x0c\x6d" - "\x9c\x2f\xdb\x97\xb8\x15\x69\x01", - .alen = 64, - .ptext = "", - .plen = 0, - .ctext = "\x65\x33\x7b\xa1\x63\xf4\x20\xdd" - "\xe4\xb9\x4a\xaa\x9a\x21\xaa\x14", - .clen = 16, - }, { - .key = "\x12\xdd\xee\x17\xd1\x47\x92\x69" - "\x8b\x14\x0a\x62\xb1\xd9\xe2\x50", - .klen = 16, - .iv = "\x22\xa6\x7c\x7f\x15\xe6\x3c\xf0" - "\xac\x4b\x37\x86\xb0\xa2\x13\xd2", - .assoc = "\x31", - .alen = 1, - .ptext = "\x40", - .plen = 1, - .ctext = "\x1d\x47\x17\x34\x86\xf5\x54\x1a" - "\x6d\x28\xb8\x5d\x6c\xcf\xa0\xb9" - "\xbf", - .clen = 17, - }, { - .key = "\x4f\x01\x27\xb6\xe1\xc3\x3a\x85" - "\x0c\xee\xbc\xf4\xab\xfd\xa5\x57", - .klen = 16, - .iv = "\x5e\xcb\xb6\x1e\x25\x62\xe4\x0c" - "\x2d\x25\xe9\x18\xaa\xc6\xd5\xd8", - .assoc = "\x6d\x94\x44\x86\x69\x00\x8f\x93" - "\x4d\x5b\x15\x3c\xa8\x8f\x06\x5a" - "\xe6\x01\xa8\x7e\xca\x10\xdc\x73" - "\xf4\x94\x9f\xc1\x5a\x61\x85", - .alen = 31, - .ptext = "\x7c\x5d\xd3\xee\xad\x9f\x39\x1a" - "\x6d\x92\x42\x61\xa7\x58\x37\xdb" - "\xb0\xb2\x2b\x9f\x0b\xb8\xbd\x7a" - "\x24\xa0\xd6\xb7\x11\x79\x6c", - .plen = 31, - .ctext = "\x78\x90\x52\xae\x0f\xf7\x2e\xef" - "\x63\x09\x08\x58\xb5\x56\xbd\x72" - "\x6e\x42\xcf\x27\x04\x7c\xdb\x92" - "\x18\xe9\xa4\x33\x90\xba\x62\xb5" - "\x70\xd3\x88\x9b\x4f\x05\xa7\x51" - "\x85\x87\x17\x09\x42\xed\x4e", - .clen = 47, - }, { - .key = "\x8b\x26\x61\x55\xf1\x3e\xe3\xa1" - "\x8d\xc8\x6e\x85\xa5\x21\x67\x5d", - .klen = 16, - .iv = "\x9b\xef\xf0\xbd\x35\xdd\x8d\x28" - "\xad\xff\x9b\xa9\xa4\xeb\x98\xdf", - .assoc = "\xaa\xb8\x7e\x25\x79\x7c\x37\xaf" - "\xce\x36\xc7\xce\xa2\xb4\xc9\x60" - "\x10\xc3\xb3\x02\xcf\xb0\x5e\x8d" - "\xb5\xc2\x7e\x9a\x35\xc0\x24\xfd", - .alen = 32, - .ptext = "\xb9\x82\x0c\x8d\xbd\x1b\xe2\x36" - "\xee\x6c\xf4\xf2\xa1\x7d\xf9\xe2" - "\xdb\x74\x36\x23\x11\x58\x3f\x93" - "\xe5\xcd\xb5\x90\xeb\xd8\x0c\xb3", - .plen = 32, - .ctext = "\x1d\x2c\x57\xe0\x50\x38\x3d\x41" - "\x2e\x71\xc8\x3b\x92\x43\x58\xaf" - "\x5a\xfb\xad\x8f\xd9\xd5\x8a\x5e" - "\xdb\xf3\xcd\x3a\x2b\xe1\x2c\x1a" - "\xb0\xed\xe3\x0c\x6e\xf9\xf2\xd6" - "\x90\xe6\xb1\x0e\xa5\x8a\xac\xb7", - .clen = 48, - }, { - .key = "\xc8\x4b\x9b\xf5\x01\xba\x8c\xbd" - "\x0e\xa3\x21\x16\x9f\x46\x2a\x63", - .klen = 16, - .iv = "\xd7\x14\x29\x5d\x45\x59\x36\x44" - "\x2e\xd9\x4d\x3b\x9e\x0f\x5b\xe5", - .assoc = "\xe6\xdd\xb8\xc4\x89\xf8\xe0\xca" - "\x4f\x10\x7a\x5f\x9c\xd8\x8b\x66" - "\x3b\x86\xbf\x86\xd4\x50\xe0\xa7" - "\x76\xef\x5c\x72\x0f\x1f\xc3\xd4" - "\xee", - .alen = 33, - .ptext = "\xf5\xa6\x46\x2c\xce\x97\x8a\x51" - "\x6f\x46\xa6\x83\x9b\xa1\xbc\xe8" - "\x05\x36\x42\xa7\x16\xf8\xc1\xad" - "\xa7\xfb\x94\x68\xc5\x37\xab\x8a" - "\x72", - .plen = 33, - .ctext = "\x59\x10\x84\x1c\x83\x4c\x8b\xfc" - "\xfd\x2e\x4b\x46\x84\xff\x78\x4e" - "\x50\xda\x5c\xb9\x61\x1d\xf5\xb9" - "\xfe\xbb\x7f\xae\x8c\xc1\x24\xbd" - "\x8c\x6f\x1f\x9b\xce\xc6\xc1\x37" - "\x08\x06\x5a\xe5\x96\x10\x95\xc2" - "\x5e", - .clen = 49, - }, { - .key = "\x05\x70\xd5\x94\x12\x36\x35\xd8" - "\x8f\x7d\xd3\xa8\x99\x6a\xed\x69", - .klen = 16, - .iv = "\x14\x39\x63\xfc\x56\xd5\xdf\x5f" - "\xaf\xb3\xff\xcc\x98\x33\x1d\xeb", - .assoc = "\x23\x02\xf1\x64\x9a\x73\x89\xe6" - "\xd0\xea\x2c\xf1\x96\xfc\x4e\x6d" - "\x65\x48\xcb\x0a\xda\xf0\x62\xc0" - "\x38\x1d\x3b\x4a\xe9\x7e\x62\xaa" - "\xfd\xc9\x4a\xa9\xa9\x39\x4b\x54" - "\xc8\x0e\x24\x7f\x5e\x10\x7a\x45" - "\x10\x0b\x56\x85\xad\x54\xaa\x66" - "\xa8\x43\xcd\xd4\x9b\xb7\xfa", - .alen = 63, - .ptext = "\x32\xcb\x80\xcc\xde\x12\x33\x6d" - "\xf0\x20\x58\x15\x95\xc6\x7f\xee" - "\x2f\xf9\x4e\x2c\x1b\x98\x43\xc7" - "\x68\x28\x73\x40\x9f\x96\x4a\x60" - "\x80\xf4\x4b\xf4\xc1\x3d\xd0\x93" - "\xcf\x12\xc9\x59\x8f\x7a\x7f\xa8" - "\x1b\xa5\x50\xed\x87\xa9\x72\x59" - "\x9c\x44\xb2\xa4\x99\x98\x34", - .plen = 63, - .ctext = "\x9a\x12\xbc\xdf\x72\xa8\x56\x22" - "\x49\x2d\x07\x92\xfc\x3d\x6d\x5f" - "\xef\x36\x19\xae\x91\xfa\xd6\x63" - "\x46\xea\x8a\x39\x14\x21\xa6\x37" - "\x18\xfc\x97\x3e\x16\xa5\x4d\x39" - "\x45\x2e\x69\xcc\x9c\x5f\xdf\x6d" - "\x5e\xa2\xbf\xac\x83\x32\x72\x52" - "\x58\x58\x23\x40\xfd\xa5\xc2\xe6" - "\xe9\x5a\x50\x98\x00\x58\xc9\x86" - "\x4f\x20\x37\xdb\x7b\x22\xa3", - .clen = 79, - }, { - .key = "\x41\x94\x0e\x33\x22\xb1\xdd\xf4" - "\x10\x57\x85\x39\x93\x8f\xaf\x70", - .klen = 16, - .iv = "\x50\x5d\x9d\x9b\x66\x50\x88\x7b" - "\x30\x8e\xb1\x5e\x92\x58\xe0\xf1", - .assoc = "\x5f\x27\x2b\x03\xaa\xef\x32\x02" - "\x50\xc4\xde\x82\x90\x21\x11\x73" - "\x8f\x0a\xd6\x8f\xdf\x90\xe4\xda" - "\xf9\x4a\x1a\x23\xc3\xdd\x02\x81" - "\x0b\x76\x4f\xd7\x0a\x4b\x5e\x51" - "\xe3\x1d\xb9\xe5\x21\xb9\x8f\xd4" - "\x3d\x72\x3e\x26\x16\xa9\xca\x32" - "\x77\x47\x63\x14\x95\x3d\xe4\x34", - .alen = 64, - .ptext = "\x6e\xf0\xba\x6b\xee\x8e\xdc\x89" - "\x71\xfb\x0a\xa6\x8f\xea\x41\xf4" - "\x5a\xbb\x59\xb0\x20\x38\xc5\xe0" - "\x29\x56\x52\x19\x79\xf5\xe9\x37" - "\x8f\xa1\x50\x23\x22\x4f\xe3\x91" - "\xe9\x21\x5e\xbf\x52\x23\x95\x37" - "\x48\x0c\x38\x8f\xf0\xff\x92\x24" - "\x6b\x47\x49\xe3\x94\x1f\x1e\x01", - .plen = 64, - .ctext = "\xe6\xeb\x92\x5a\x5b\xf0\x2d\xbb" - "\x23\xec\x35\xe3\xae\xc9\xfb\x0b" - "\x90\x14\x46\xeb\xa8\x8d\xb0\x9b" - "\x39\xda\x8b\x48\xec\xb2\x00\x4e" - "\x80\x6f\x46\x4f\x9b\x1e\xbb\x35" - "\xea\x5a\xbc\xa2\x36\xa5\x89\x45" - "\xc2\xd6\xd7\x15\x0b\xf6\x6c\x56" - "\xec\x99\x7d\x61\xb3\x15\x93\xed" - "\x83\x1e\xd9\x48\x84\x0b\x37\xfe" - "\x95\x74\x44\xd5\x54\xa6\x27\x06", - .clen = 80, - }, { - .key = "\x7e\xb9\x48\xd3\x32\x2d\x86\x10" - "\x91\x31\x37\xcb\x8d\xb3\x72\x76", - .klen = 16, - .iv = "\x8d\x82\xd6\x3b\x76\xcc\x30\x97" - "\xb1\x68\x63\xef\x8c\x7c\xa3\xf7", - .assoc = "\x9c\x4b\x65\xa2\xba\x6b\xdb\x1e" - "\xd1\x9e\x90\x13\x8a\x45\xd3\x79" - "\xba\xcd\xe2\x13\xe4\x30\x66\xf4" - "\xba\x78\xf9\xfb\x9d\x3c\xa1\x58" - "\x1a\x22\x53\x05\x6b\x5c\x71\x4f" - "\xfd\x2d\x4d\x4c\xe5\x62\xa5\x63" - "\x6a\xda\x26\xc8\x7f\xff\xea\xfd" - "\x46\x4a\xfa\x53\x8f\xc4\xcd\x68" - "\x58", - .alen = 65, - .ptext = "\xab\x14\xf3\x0a\xfe\x0a\x85\xa5" - "\xf2\xd5\xbc\x38\x89\x0e\x04\xfb" - "\x84\x7d\x65\x34\x25\xd8\x47\xfa" - "\xeb\x83\x31\xf1\x54\x54\x89\x0d" - "\x9d\x4d\x54\x51\x84\x61\xf6\x8e" - "\x03\x31\xf2\x25\x16\xcc\xaa\xc6" - "\x75\x73\x20\x30\x59\x54\xb2\xf0" - "\x3a\x4b\xe0\x23\x8e\xa6\x08\x35" - "\x8a\xdf\x27\xa0\xe4\x60\x99\xae" - "\x8e\x43\xd9\x39\x7b\x10\x40\x67" - "\x5c\x7e\xc9\x70\x63\x34\xca\x59" - "\xfe\x86\xbc\xb7\x9c\x39\xf3\x6d" - "\x6a\x41\x64\x6f\x16\x7f\x65\x7e" - "\x89\x84\x68\xeb\xb0\x51\xbe\x55" - "\x33\x16\x59\x6c\x3b\xef\x88\xad" - "\x2f\xab\xbc\x25\x76\x87\x41\x2f" - "\x36", - .plen = 129, - .ctext = "\x89\x24\x27\x86\xdc\xd7\x6b\xd9" - "\xd1\xcd\xdc\x16\xdd\x2c\xc1\xfb" - "\x52\xb5\xb3\xab\x50\x99\x3f\xa0" - "\x38\xa4\x74\xa5\x04\x15\x63\x05" - "\x8f\x54\x81\x06\x5a\x6b\xa4\x63" - "\x6d\xa7\x21\xcb\xff\x42\x30\x8e" - "\x3b\xd1\xca\x3f\x4b\x1a\xb8\xc3" - "\x42\x01\xe6\xbc\x75\x15\x87\xee" - "\xc9\x8e\x65\x01\xd9\xd8\xb5\x9f" - "\x48\x86\xa6\x5f\x2c\xc7\xb5\xb0" - "\xed\x5d\x14\x7c\x3f\x40\xb1\x0b" - "\x72\xef\x94\x8d\x7a\x85\x56\xe5" - "\x56\x08\x15\x56\xba\xaf\xbd\xf0" - "\x20\xef\xa0\xf6\xa9\xad\xa2\xc9" - "\x1c\x3b\x28\x51\x7e\x77\xb2\x18" - "\x4f\x61\x64\x37\x22\x36\x6d\x78" - "\xed\xed\x35\xe8\x83\xa5\xec\x25" - "\x6b\xff\x5f\x1a\x09\x96\x3d\xdc" - "\x20", - .clen = 145, - }, { - .key = "\xba\xde\x82\x72\x42\xa9\x2f\x2c" - "\x12\x0b\xe9\x5c\x87\xd7\x35\x7c", - .klen = 16, - .iv = "\xc9\xa7\x10\xda\x86\x48\xd9\xb3" - "\x32\x42\x15\x80\x85\xa1\x65\xfe", - .assoc = "\xd8\x70\x9f\x42\xca\xe6\x83\x3a" - "\x52\x79\x42\xa5\x84\x6a\x96\x7f" - "\xe4\x8f\xed\x97\xe9\xd0\xe8\x0d" - "\x7c\xa6\xd8\xd4\x77\x9b\x40\x2e" - "\x28\xce\x57\x34\xcd\x6e\x84\x4c" - "\x17\x3c\xe1\xb2\xa8\x0b\xbb\xf1" - "\x96\x41\x0d\x69\xe8\x54\x0a\xc8" - "\x15\x4e\x91\x92\x89\x4b\xb7\x9b" - "\x21\xf7\x42\x89\xac\x12\x2a\x54" - "\x69\xee\x18\xc7\x8d\xed\xe8\xfd" - "\xbb\x04\x28\xe6\x8a\x3c\x98\xc1" - "\x04\x2d\xa9\xa1\x24\x83\xff\xe9" - "\x55\x7a\xf0\xd1\xf6\x63\x05\xe1" - "\xd9\x1e\x75\x72\xc1\x9f\xae\x32" - "\xe1\x6b\xcd\x9e\x61\x19\x23\x86" - "\xd9\xd2\xaf\x8e\xd5\xd3\xa8\xa9" - "\x51", - .alen = 129, - .ptext = "\xe8\x39\x2d\xaa\x0e\x85\x2d\xc1" - "\x72\xaf\x6e\xc9\x82\x33\xc7\x01" - "\xaf\x40\x70\xb8\x2a\x78\xc9\x14" - "\xac\xb1\x10\xca\x2e\xb3\x28\xe4" - "\xac\xfa\x58\x7f\xe5\x73\x09\x8c" - "\x1d\x40\x87\x8c\xd9\x75\xc0\x55" - "\xa2\xda\x07\xd1\xc2\xa9\xd1\xbb" - "\x09\x4f\x77\x62\x88\x2d\xf2\x68" - "\x54", - .plen = 65, - .ctext = "\x36\x78\xb9\x22\xde\x62\x35\x55" - "\x1a\x7a\xf5\x45\xbc\xd7\x15\x82" - "\x01\xe9\x5a\x07\xea\x46\xaf\x91" - "\xcb\x73\xa5\xee\xe1\xb4\xbf\xc2" - "\xdb\xd2\x9d\x59\xde\xfc\x83\x00" - "\xf5\x46\xac\x97\xd5\x57\xa9\xb9" - "\x1f\x8c\xe8\xca\x68\x8b\x91\x0c" - "\x01\xbe\x0a\xaf\x7c\xf6\x67\xa4" - "\xbf\xbc\x88\x3f\x5d\xd1\xf9\x19" - "\x0f\x9d\xb2\xaf\xb9\x6e\x17\xdf" - "\xa2", - .clen = 81, - }, { - .key = "\xf7\x02\xbb\x11\x52\x24\xd8\x48" - "\x93\xe6\x9b\xee\x81\xfc\xf7\x82", - .klen = 16, - .iv = "\x06\xcc\x4a\x79\x96\xc3\x82\xcf" - "\xb3\x1c\xc7\x12\x7f\xc5\x28\x04", - .assoc = "\x15\x95\xd8\xe1\xda\x62\x2c\x56" - "\xd3\x53\xf4\x36\x7e\x8e\x59\x85" - "\x0e\x51\xf9\x1c\xee\x70\x6a\x27" - "\x3d\xd3\xb7\xac\x51\xfa\xdf\x05", - .alen = 32, - .ptext = "\x24\x5e\x67\x49\x1e\x01\xd6\xdd" - "\xf3\x89\x20\x5b\x7c\x57\x89\x07" - "\xd9\x02\x7c\x3d\x2f\x18\x4b\x2d" - "\x6e\xde\xee\xa2\x08\x12\xc7\xba", - .plen = 32, - .ctext = "\x08\x1b\x95\x0e\x41\x95\x02\x4b" - "\x9c\xbb\xa8\xd0\x7c\xd3\x44\x6e" - "\x89\x14\x33\x70\x0a\xbc\xea\x39" - "\x88\xaa\x2b\xd5\x73\x11\x55\xf5" - "\x33\x33\x9c\xd7\x42\x34\x49\x8e" - "\x2f\x03\x30\x05\x47\xaf\x34", - .clen = 47, - }, { - .key = "\x33\x27\xf5\xb1\x62\xa0\x80\x63" - "\x14\xc0\x4d\x7f\x7b\x20\xba\x89", - .klen = 16, - .iv = "\x42\xf0\x84\x19\xa6\x3f\x2b\xea" - "\x34\xf6\x79\xa3\x79\xe9\xeb\x0a", - .assoc = "\x51\xb9\x12\x80\xea\xde\xd5\x71" - "\x54\x2d\xa6\xc8\x78\xb2\x1b\x8c" - "\x39\x14\x05\xa0\xf3\x10\xec\x41" - "\xff\x01\x95\x84\x2b\x59\x7f\xdb", - .alen = 32, - .ptext = "\x61\x83\xa0\xe8\x2e\x7d\x7f\xf8" - "\x74\x63\xd2\xec\x76\x7c\x4c\x0d" - "\x03\xc4\x88\xc1\x35\xb8\xcd\x47" - "\x2f\x0c\xcd\x7a\xe2\x71\x66\x91", - .plen = 32, - .ctext = "\x97\xca\xf4\xe0\x8d\x89\xbf\x68" - "\x0c\x60\xb9\x27\xdf\xaa\x41\xc6" - "\x25\xd8\xf7\x1f\x10\x15\x48\x61" - "\x4c\x95\x00\xdf\x51\x9b\x7f\xe6" - "\x24\x40\x9e\xbe\x3b\xeb\x1b\x98" - "\xb9\x9c\xe5\xef\xf2\x05", - .clen = 46, - }, { - .key = "\x70\x4c\x2f\x50\x72\x1c\x29\x7f" - "\x95\x9a\xff\x10\x75\x45\x7d\x8f", - .klen = 16, - .iv = "\x7f\x15\xbd\xb8\xb6\xba\xd3\x06" - "\xb5\xd1\x2b\x35\x73\x0e\xad\x10", - .assoc = "\x8e\xde\x4c\x20\xfa\x59\x7e\x8d" - "\xd5\x07\x58\x59\x72\xd7\xde\x92" - "\x63\xd6\x10\x24\xf8\xb0\x6e\x5a" - "\xc0\x2e\x74\x5d\x06\xb8\x1e\xb2", - .alen = 32, - .ptext = "\x9d\xa7\xda\x88\x3e\xf8\x28\x14" - "\xf5\x3e\x85\x7d\x70\xa0\x0f\x13" - "\x2e\x86\x93\x45\x3a\x58\x4f\x61" - "\xf0\x3a\xac\x53\xbc\xd0\x06\x68", - .plen = 32, - .ctext = "\x63\x4c\x2a\x8e\xb4\x6b\x63\x0d" - "\xb5\xec\x9b\x4e\x12\x23\xa3\xcf" - "\x1a\x5a\x70\x15\x5a\x10\x40\x51" - "\xca\x47\x4c\x9d\xc9\x97\xf4\x77" - "\xdb\xc8\x10\x2d\xdc\x65\x20\x3f", - .clen = 40, - }, { - .key = "\xac\x70\x69\xef\x82\x97\xd2\x9b" - "\x15\x74\xb1\xa2\x6f\x69\x3f\x95", - .klen = 16, - .iv = "\xbb\x3a\xf7\x57\xc6\x36\x7c\x22" - "\x36\xab\xde\xc6\x6d\x32\x70\x17", - .assoc = "\xcb\x03\x85\xbf\x0a\xd5\x26\xa9" - "\x56\xe1\x0a\xeb\x6c\xfb\xa1\x98" - "\x8d\x98\x1c\xa8\xfe\x50\xf0\x74" - "\x81\x5c\x53\x35\xe0\x17\xbd\x88", - .alen = 32, - .ptext = "\xda\xcc\x14\x27\x4e\x74\xd1\x30" - "\x76\x18\x37\x0f\x6a\xc4\xd1\x1a" - "\x58\x49\x9f\xc9\x3f\xf8\xd1\x7a" - "\xb2\x67\x8b\x2b\x96\x2f\xa5\x3e", - .plen = 32, - .ctext = "\xf1\x62\x44\xc7\x5f\x19\xca\x43" - "\x47\x2c\xaf\x68\x82\xbd\x51\xef" - "\x3d\x65\xd8\x45\x2d\x06\x07\x78" - "\x08\x2e\xb3\x23\xcd\x81\x12\x55" - "\x1a", - .clen = 33, - }, { - .key = "\xe9\x95\xa2\x8f\x93\x13\x7b\xb7" - "\x96\x4e\x63\x33\x69\x8d\x02\x9b" - "\x23\xf9\x22\xeb\x80\xa0\xb1\x81" - "\xe2\x73\xc3\x21\x4d\x47\x8d\xf4", - .klen = 32, - .iv = "\xf8\x5e\x31\xf7\xd7\xb2\x25\x3e" - "\xb7\x85\x90\x58\x67\x57\x33\x1d", - .assoc = "", - .alen = 0, - .ptext = "", - .plen = 0, - .ctext = "\xdf\x2f\x83\xc0\x45\x4a\x2c\xcf" - "\xb9\xd2\x41\xf6\x80\xa1\x52\x70", - .clen = 16, - }, { - .key = "\x25\xba\xdc\x2e\xa3\x8f\x24\xd3" - "\x17\x29\x15\xc5\x63\xb2\xc5\xa1" - "\x4d\xbc\x2d\x6f\x85\x40\x33\x9a" - "\xa3\xa0\xa1\xfa\x27\xa6\x2c\xca", - .klen = 32, - .iv = "\x34\x83\x6a\x96\xe7\x2d\xce\x5a" - "\x38\x5f\x42\xe9\x61\x7b\xf5\x23", - .assoc = "", - .alen = 0, - .ptext = "\x53", - .plen = 1, - .ctext = "\x01\xd8\x55\x3c\xc0\x5a\x4b\xc7" - "\x01\xf4\x08\xe3\x0d\xf7\xf0\x78" - "\x53", - .clen = 17, - }, { - .key = "\x62\xdf\x16\xcd\xb3\x0a\xcc\xef" - "\x98\x03\xc7\x56\x5d\xd6\x87\xa8" - "\x77\x7e\x39\xf3\x8a\xe0\xb5\xb4" - "\x65\xce\x80\xd2\x01\x05\xcb\xa1", - .klen = 32, - .iv = "\x71\xa8\xa4\x35\xf7\xa9\x76\x75" - "\xb8\x39\xf4\x7a\x5b\x9f\xb8\x29", - .assoc = "", - .alen = 0, - .ptext = "\x8f\x3a\xc1\x05\x7f\xe7\xcb\x83" - "\xf9\xa6\x4d\xc3\x58\x31\x19\x2c" - "\xd7\x90\xc2\x56\x4e\xd8\x57\xc7" - "\xf6\xf0\x27\xb4\x25\x4c\x83", - .plen = 31, - .ctext = "\xc2\x4b\x41\x0f\x2d\xb9\x62\x07" - "\xff\x8e\x74\xf8\xa1\xa6\xd5\x37" - "\xa5\x64\x31\x5c\xca\x73\x9b\x43" - "\xe6\x70\x63\x46\x95\xcb\xf7\xb5" - "\x20\x8c\x75\x7a\x2a\x17\x2f\xa9" - "\xb8\x4d\x11\x42\xd1\xf8\xf1", - .clen = 47, - }, { - .key = "\x9e\x03\x4f\x6d\xc3\x86\x75\x0a" - "\x19\xdd\x79\xe8\x57\xfb\x4a\xae" - "\xa2\x40\x45\x77\x90\x80\x37\xce" - "\x26\xfb\x5f\xaa\xdb\x64\x6b\x77", - .klen = 32, - .iv = "\xae\xcc\xde\xd5\x07\x25\x1f\x91" - "\x39\x14\xa6\x0c\x55\xc4\x7b\x30", - .assoc = "", - .alen = 0, - .ptext = "\xcc\x5f\xfb\xa4\x8f\x63\x74\x9f" - "\x7a\x81\xff\x55\x52\x56\xdc\x33" - "\x01\x52\xcd\xdb\x53\x78\xd9\xe1" - "\xb7\x1d\x06\x8d\xff\xab\x22\x98", - .plen = 32, - .ctext = "\xbb\x01\x7c\xd1\x2c\x33\x7b\x37" - "\x0a\xee\xc4\x30\x19\xd7\x3a\x6f" - "\xf8\x2b\x67\xf5\x3b\x84\x87\x2a" - "\xfb\x07\x7a\x82\xb5\xe4\x85\x26" - "\x1e\xa8\xe5\x04\x54\xce\xe5\x5f" - "\xb5\x3f\xc1\xd5\x7f\xbd\xd2\xa6", - .clen = 48, - }, { - .key = "\xdb\x28\x89\x0c\xd3\x01\x1e\x26" - "\x9a\xb7\x2b\x79\x51\x1f\x0d\xb4" - "\xcc\x03\x50\xfc\x95\x20\xb9\xe7" - "\xe8\x29\x3e\x83\xb5\xc3\x0a\x4e", - .klen = 32, - .iv = "\xea\xf1\x18\x74\x17\xa0\xc8\xad" - "\xba\xee\x58\x9d\x4f\xe8\x3d\x36", - .assoc = "", - .alen = 0, - .ptext = "\x08\x84\x34\x44\x9f\xde\x1c\xbb" - "\xfb\x5b\xb1\xe6\x4c\x7a\x9f\x39" - "\x2c\x14\xd9\x5f\x59\x18\x5b\xfb" - "\x79\x4b\xe5\x65\xd9\x0a\xc1\x6f" - "\x2e", - .plen = 33, - .ctext = "\xc2\xf4\x40\x55\xf9\x59\xff\x73" - "\x08\xf5\x98\x92\x0c\x7b\x35\x9a" - "\xa8\xf4\x42\x7e\x6f\x93\xca\x22" - "\x23\x06\x1e\xf8\x89\x22\xf4\x46" - "\x7c\x7c\x67\x75\xab\xe5\x75\xaa" - "\x15\xd7\x83\x19\xfd\x31\x59\x5b" - "\x32", - .clen = 49, - }, { - .key = "\x17\x4d\xc3\xab\xe3\x7d\xc7\x42" - "\x1b\x91\xdd\x0a\x4b\x43\xcf\xba" - "\xf6\xc5\x5c\x80\x9a\xc0\x3b\x01" - "\xa9\x56\x1d\x5b\x8f\x22\xa9\x25", - .klen = 32, - .iv = "\x27\x16\x51\x13\x27\x1c\x71\xc9" - "\x3b\xc8\x0a\x2f\x49\x0c\x00\x3c", - .assoc = "", - .alen = 0, - .ptext = "\x45\xa8\x6e\xe3\xaf\x5a\xc5\xd7" - "\x7c\x35\x63\x77\x46\x9f\x61\x3f" - "\x56\xd7\xe4\xe3\x5e\xb8\xdc\x14" - "\x3a\x79\xc4\x3e\xb3\x69\x61\x46" - "\x3c\xb6\x83\x4e\xb4\x26\xc7\x73" - "\x22\xda\x52\x8b\x7d\x11\x98\xea" - "\x62\xe1\x14\x1e\xdc\xfe\x0f\xad" - "\x20\x76\x5a\xdc\x4e\x71\x13", - .plen = 63, - .ctext = "\xc9\x82\x3b\x4b\x87\x84\xa5\xdb" - "\xa0\x8c\xd3\x3e\x7f\x8d\xe8\x28" - "\x2a\xdc\xfa\x01\x84\x87\x9a\x70" - "\x81\x75\x37\x0a\xd2\x75\xa9\xb6" - "\x21\x72\xee\x7e\x65\x95\xe5\xcc" - "\x01\xb7\x39\xa6\x51\x15\xca\xff" - "\x61\xdc\x97\x38\xcc\xf4\xca\xc7" - "\x83\x9b\x05\x11\x72\x60\xf0\xb4" - "\x7e\x06\xab\x0a\xc0\xbb\x59\x23" - "\xaa\x2d\xfc\x4e\x35\x05\x59", - .clen = 79, - }, { - .key = "\x54\x71\xfd\x4b\xf3\xf9\x6f\x5e" - "\x9c\x6c\x8f\x9c\x45\x68\x92\xc1" - "\x21\x87\x67\x04\x9f\x60\xbd\x1b" - "\x6a\x84\xfc\x34\x6a\x81\x48\xfb", - .klen = 32, - .iv = "\x63\x3b\x8b\xb3\x37\x98\x1a\xe5" - "\xbc\xa2\xbc\xc0\x43\x31\xc2\x42", - .assoc = "", - .alen = 0, - .ptext = "\x81\xcd\xa8\x82\xbf\xd6\x6e\xf3" - "\xfd\x0f\x15\x09\x40\xc3\x24\x45" - "\x81\x99\xf0\x67\x63\x58\x5e\x2e" - "\xfb\xa6\xa3\x16\x8d\xc8\x00\x1c" - "\x4b\x62\x87\x7c\x15\x38\xda\x70" - "\x3d\xea\xe7\xf2\x40\xba\xae\x79" - "\x8f\x48\xfc\xbf\x45\x53\x2e\x78" - "\xef\x79\xf0\x1b\x49\xf7\xfd\x9c", - .plen = 64, - .ctext = "\x11\x7c\x7d\xef\xce\x29\x95\xec" - "\x7e\x9f\x42\xa6\x26\x07\xa1\x75" - "\x2f\x4e\x09\x9a\xf6\x6b\xc2\xfa" - "\x0d\xd0\x17\xdc\x25\x1e\x9b\xdc" - "\x5f\x8c\x1c\x60\x15\x4f\x9b\x20" - "\x7b\xff\xcd\x82\x60\x84\xf4\xa5" - "\x20\x9a\x05\x19\x5b\x02\x0a\x72" - "\x43\x11\x26\x58\xcf\xc5\x41\xcf" - "\x13\xcc\xde\x32\x92\xfa\x86\xf2" - "\xaf\x16\xe8\x8f\xca\xb6\xfd\x54", - .clen = 80, - }, { - .key = "\x90\x96\x36\xea\x03\x74\x18\x7a" - "\x1d\x46\x42\x2d\x3f\x8c\x54\xc7" - "\x4b\x4a\x73\x89\xa4\x00\x3f\x34" - "\x2c\xb1\xdb\x0c\x44\xe0\xe8\xd2", - .klen = 32, - .iv = "\xa0\x5f\xc5\x52\x47\x13\xc2\x01" - "\x3d\x7c\x6e\x52\x3d\x55\x85\x48", - .assoc = "\xaf", - .alen = 1, - .ptext = "", - .plen = 0, - .ctext = "\x9b\xc5\x3b\x20\x0a\x88\x56\xbe" - "\x69\xdf\xc4\xc4\x02\x46\x3a\xf0", - .clen = 16, - }, { - .key = "\xcd\xbb\x70\x89\x13\xf0\xc1\x95" - "\x9e\x20\xf4\xbf\x39\xb1\x17\xcd" - "\x76\x0c\x7f\x0d\xa9\xa0\xc1\x4e" - "\xed\xdf\xb9\xe4\x1e\x3f\x87\xa8", - .klen = 32, - .iv = "\xdc\x84\xfe\xf1\x58\x8f\x6b\x1c" - "\xbe\x57\x20\xe3\x37\x7a\x48\x4f", - .assoc = "\xeb\x4d\x8d\x59\x9c\x2e\x15\xa3" - "\xde\x8d\x4d\x07\x36\x43\x78\xd0" - "\x0b\x6d\x84\x4f\x2c\xf0\x82\x5b" - "\x4e\xf6\x29\xd1\x8b\x6f\x56", - .alen = 31, - .ptext = "", - .plen = 0, - .ctext = "\xe0\x6d\xa1\x07\x98\x2f\x40\x2d" - "\x2e\x9a\xd6\x61\x43\xc0\x74\x69", - .clen = 16, - }, { - .key = "\x0a\xe0\xaa\x29\x24\x6c\x6a\xb1" - "\x1f\xfa\xa6\x50\x33\xd5\xda\xd3" - "\xa0\xce\x8a\x91\xae\x40\x43\x68" - "\xae\x0d\x98\xbd\xf8\x9e\x26\x7f", - .klen = 32, - .iv = "\x19\xa9\x38\x91\x68\x0b\x14\x38" - "\x3f\x31\xd2\x74\x31\x9e\x0a\x55", - .assoc = "\x28\x72\xc7\xf8\xac\xaa\xbe\xbf" - "\x5f\x67\xff\x99\x30\x67\x3b\xd6" - "\x35\x2f\x90\xd3\x31\x90\x04\x74" - "\x0f\x23\x08\xa9\x65\xce\xf6\xea", - .alen = 32, - .ptext = "", - .plen = 0, - .ctext = "\xb9\x57\x13\x3e\x82\x31\x61\x65" - "\x0d\x7f\x6c\x96\x93\x5c\x50\xe2", - .clen = 16, - }, { - .key = "\x46\x04\xe3\xc8\x34\xe7\x12\xcd" - "\xa0\xd4\x58\xe2\x2d\xf9\x9c\xda" - "\xca\x91\x96\x15\xb4\xe0\xc5\x81" - "\x70\x3a\x77\x95\xd2\xfd\xc5\x55", - .klen = 32, - .iv = "\x55\xcd\x72\x30\x78\x86\xbd\x54" - "\xc0\x0b\x84\x06\x2b\xc2\xcd\x5b", - .assoc = "\x64\x97\x00\x98\xbc\x25\x67\xdb" - "\xe0\x41\xb1\x2a\x2a\x8c\xfe\xdd" - "\x5f\xf2\x9c\x58\x36\x30\x86\x8e" - "\xd1\x51\xe6\x81\x3f\x2d\x95\xc1" - "\x01", - .alen = 33, - .ptext = "", - .plen = 0, - .ctext = "\x81\x96\x34\xde\xbb\x36\xdd\x3e" - "\x4e\x5e\xcb\x44\x21\xb8\x3f\xf1", - .clen = 16, - }, { - .key = "\x83\x29\x1d\x67\x44\x63\xbb\xe9" - "\x20\xaf\x0a\x73\x27\x1e\x5f\xe0" - "\xf5\x53\xa1\x9a\xb9\x80\x47\x9b" - "\x31\x68\x56\x6e\xac\x5c\x65\x2c", - .klen = 32, - .iv = "\x92\xf2\xac\xcf\x88\x02\x65\x70" - "\x41\xe5\x36\x97\x25\xe7\x90\x61", - .assoc = "\xa1\xbb\x3a\x37\xcc\xa1\x10\xf7" - "\x61\x1c\x63\xbc\x24\xb0\xc0\xe3" - "\x8a\xb4\xa7\xdc\x3b\xd0\x08\xa8" - "\x92\x7f\xc5\x5a\x19\x8c\x34\x97" - "\x0f\x95\x9b\x18\xe4\x8d\xb4\x24" - "\xb9\x33\x28\x18\xe1\x9d\x14\xe0" - "\x64\xb2\x89\x7d\x78\xa8\x05\x7e" - "\x07\x8c\xfc\x88\x2d\xb8\x53", - .alen = 63, - .ptext = "", - .plen = 0, - .ctext = "\x2e\x99\xb6\x79\x57\x56\x80\x36" - "\x8e\xc4\x1c\x12\x7d\x71\x36\x0c", - .clen = 16, - }, { - .key = "\xbf\x4e\x57\x07\x54\xdf\x64\x05" - "\xa1\x89\xbc\x04\x21\x42\x22\xe6" - "\x1f\x15\xad\x1e\xbe\x20\xc9\xb4" - "\xf3\x95\x35\x46\x86\xbb\x04\x03", - .klen = 32, - .iv = "\xce\x17\xe5\x6f\x98\x7e\x0e\x8c" - "\xc2\xbf\xe8\x29\x1f\x0b\x52\x68", - .assoc = "\xdd\xe0\x74\xd6\xdc\x1d\xb8\x13" - "\xe2\xf6\x15\x4d\x1e\xd4\x83\xe9" - "\xb4\x76\xb3\x60\x40\x70\x8a\xc1" - "\x53\xac\xa4\x32\xf3\xeb\xd3\x6e" - "\x1e\x42\xa0\x46\x45\x9f\xc7\x22" - "\xd3\x43\xbc\x7e\xa5\x47\x2a\x6f" - "\x91\x19\x70\x1e\xe1\xfe\x25\x49" - "\xd6\x8f\x93\xc7\x28\x3f\x3d\x03", - .alen = 64, - .ptext = "", - .plen = 0, - .ctext = "\x7b\x25\x3d\x47\xd4\xa7\x08\xce" - "\x3b\x89\x40\x36\xba\x6d\x0e\xa2", - .clen = 16, - }, { - .key = "\xfc\x72\x90\xa6\x64\x5a\x0d\x21" - "\x22\x63\x6e\x96\x1b\x67\xe4\xec" - "\x49\xd7\xb9\xa2\xc3\xc0\x4b\xce" - "\xb4\xc3\x14\x1e\x61\x1a\xa3\xd9", - .klen = 32, - .iv = "\x0b\x3c\x1f\x0e\xa8\xf9\xb7\xa7" - "\x42\x9a\x9a\xba\x19\x30\x15\x6e", - .assoc = "\x1a", - .alen = 1, - .ptext = "\x29", - .plen = 1, - .ctext = "\xe6\x09\x6f\x95\x9a\x18\xc8\xf6" - "\x17\x75\x81\x16\xdf\x26\xff\x67" - "\x92", - .clen = 17, - }, { - .key = "\x38\x97\xca\x45\x74\xd6\xb6\x3c" - "\xa3\x3d\x20\x27\x15\x8b\xa7\xf2" - "\x74\x9a\xc4\x27\xc8\x60\xcd\xe8" - "\x75\xf0\xf2\xf7\x3b\x79\x42\xb0", - .klen = 32, - .iv = "\x47\x60\x59\xad\xb8\x75\x60\xc3" - "\xc3\x74\x4c\x4c\x13\x54\xd8\x74", - .assoc = "\x56\x29\xe7\x15\xfc\x14\x0a\x4a" - "\xe4\xaa\x79\x70\x12\x1d\x08\xf6" - "\x09\xfb\xca\x69\x4b\xb0\x8e\xf5" - "\xd6\x07\x62\xe3\xa8\xa9\x12", - .alen = 31, - .ptext = "\x66\xf3\x75\x7d\x40\xb3\xb4\xd1" - "\x04\xe1\xa6\x94\x10\xe6\x39\x77" - "\xd3\xac\x4d\x8a\x8c\x58\x6e\xfb" - "\x06\x13\x9a\xd9\x5e\xc0\xfa", - .plen = 31, - .ctext = "\x82\xc0\x56\xf0\xd7\xc4\xc9\xfd" - "\x3c\xd1\x2a\xd4\x15\x86\x9d\xda" - "\xea\x6c\x6f\xa1\x33\xb0\x7a\x01" - "\x57\xe7\xf3\x7b\x73\xe7\x54\x10" - "\xc6\x91\xe2\xc6\xa0\x69\xe7\xe6" - "\x76\xc3\xf5\x3a\x76\xfd\x4a", - .clen = 47, - }, { - .key = "\x75\xbc\x04\xe5\x84\x52\x5e\x58" - "\x24\x17\xd2\xb9\x0e\xaf\x6a\xf9" - "\x9e\x5c\xd0\xab\xcd\x00\x4f\x01" - "\x37\x1e\xd1\xcf\x15\xd8\xe2\x86", - .klen = 32, - .iv = "\x84\x85\x92\x4d\xc8\xf1\x08\xdf" - "\x44\x4e\xff\xdd\x0d\x78\x9a\x7a", - .assoc = "\x93\x4e\x21\xb4\x0c\x90\xb3\x66" - "\x65\x84\x2b\x01\x0b\x42\xcb\xfc" - "\x33\xbd\xd6\xed\x50\x50\x10\x0e" - "\x97\x35\x41\xbb\x82\x08\xb1\xf2", - .alen = 32, - .ptext = "\xa2\x17\xaf\x1c\x50\x2e\x5d\xed" - "\x85\xbb\x58\x26\x0a\x0b\xfc\x7d" - "\xfe\x6e\x59\x0e\x91\xf8\xf0\x15" - "\xc8\x40\x78\xb1\x38\x1f\x99\xa7", - .plen = 32, - .ctext = "\x01\x47\x8e\x6c\xf6\x64\x89\x3a" - "\x71\xce\xe4\xaa\x45\x70\xe6\x84" - "\x62\x48\x08\x64\x86\x6a\xdf\xec" - "\xb4\xa0\xfb\x34\x03\x0c\x19\xf4" - "\x2b\x7b\x36\x73\xec\x54\xa9\x1e" - "\x30\x85\xdb\xe4\xac\xe9\x2c\xca", - .clen = 48, - }, { - .key = "\xb1\xe1\x3e\x84\x94\xcd\x07\x74" - "\xa5\xf2\x84\x4a\x08\xd4\x2c\xff" - "\xc8\x1e\xdb\x2f\xd2\xa0\xd1\x1b" - "\xf8\x4c\xb0\xa8\xef\x37\x81\x5d", - .klen = 32, - .iv = "\xc0\xaa\xcc\xec\xd8\x6c\xb1\xfb" - "\xc5\x28\xb1\x6e\x07\x9d\x5d\x81", - .assoc = "\xd0\x73\x5a\x54\x1d\x0b\x5b\x82" - "\xe5\x5f\xdd\x93\x05\x66\x8e\x02" - "\x5e\x80\xe1\x71\x55\xf0\x92\x28" - "\x59\x62\x20\x94\x5c\x67\x50\xc8" - "\x58", - .alen = 33, - .ptext = "\xdf\x3c\xe9\xbc\x61\xaa\x06\x09" - "\x06\x95\x0a\xb7\x04\x2f\xbe\x84" - "\x28\x30\x64\x92\x96\x98\x72\x2e" - "\x89\x6e\x57\x8a\x13\x7e\x38\x7e" - "\xdb", - .plen = 33, - .ctext = "\x85\xe0\xf8\x0f\x8e\x49\xe3\x60" - "\xcb\x4a\x54\x94\xcf\xf5\x7e\x34" - "\xe9\xf8\x80\x65\x53\xd0\x72\x70" - "\x4f\x7d\x9d\xd1\x15\x6f\xb9\x2c" - "\xfa\xe8\xdd\xac\x2e\xe1\x3f\x67" - "\x63\x0f\x1a\x59\xb7\x89\xdb\xf4" - "\xc3", - .clen = 49, - }, { - .key = "\xee\x05\x77\x23\xa5\x49\xb0\x90" - "\x26\xcc\x36\xdc\x02\xf8\xef\x05" - "\xf3\xe1\xe7\xb3\xd8\x40\x53\x35" - "\xb9\x79\x8f\x80\xc9\x96\x20\x33", - .klen = 32, - .iv = "\xfd\xce\x06\x8b\xe9\xe8\x5a\x17" - "\x46\x02\x63\x00\x01\xc1\x20\x87", - .assoc = "\x0c\x98\x94\xf3\x2d\x87\x04\x9e" - "\x66\x39\x8f\x24\xff\x8a\x50\x08" - "\x88\x42\xed\xf6\x5a\x90\x14\x42" - "\x1a\x90\xfe\x6c\x36\xc6\xf0\x9f" - "\x66\xa0\xb5\x2d\x2c\xf8\x25\x15" - "\x55\x90\xa2\x7e\x77\x94\x96\x3a" - "\x71\x1c\xf7\x44\xee\xa8\xc3\x42" - "\xe2\xa3\x84\x04\x0b\xe1\xce", - .alen = 63, - .ptext = "\x1b\x61\x23\x5b\x71\x26\xae\x25" - "\x87\x6f\xbc\x49\xfe\x53\x81\x8a" - "\x53\xf2\x70\x17\x9b\x38\xf4\x48" - "\x4b\x9b\x36\x62\xed\xdd\xd8\x54" - "\xea\xcb\xb6\x79\x45\xfc\xaa\x54" - "\x5c\x94\x47\x58\xa7\xff\x9c\x9e" - "\x7c\xb6\xf1\xac\xc8\xfd\x8b\x35" - "\xd5\xa4\x6a\xd4\x09\xc2\x08", - .plen = 63, - .ctext = "\x00\xe5\x5b\x87\x5c\x20\x22\x8a" - "\xda\x1f\xd3\xff\xbb\xb2\xb0\xf8" - "\xef\xe9\xeb\x9e\x7c\x80\xf4\x2b" - "\x59\xc0\x79\xbc\x17\xa0\x15\x01" - "\xf5\x72\xfb\x5a\xe7\xaf\x07\xe3" - "\x1b\x49\x21\x34\x23\x63\x55\x5e" - "\xee\x4f\x34\x17\xfa\xfe\xa5\x0c" - "\xed\x0b\x23\xea\x9b\xda\x57\x2f" - "\xf6\xa9\xae\x0d\x4e\x40\x96\x45" - "\x7f\xfa\xf0\xbf\xc4\x98\x78", - .clen = 79, - }, { - .key = "\x2a\x2a\xb1\xc3\xb5\xc5\x59\xac" - "\xa7\xa6\xe8\x6d\xfc\x1d\xb2\x0b" - "\x1d\xa3\xf3\x38\xdd\xe0\xd5\x4e" - "\x7b\xa7\x6e\x58\xa3\xf5\xbf\x0a", - .klen = 32, - .iv = "\x39\xf3\x3f\x2b\xf9\x64\x03\x33" - "\xc7\xdd\x15\x91\xfb\xe6\xe2\x8d", - .assoc = "\x49\xbc\xce\x92\x3d\x02\xad\xba" - "\xe7\x13\x41\xb6\xf9\xaf\x13\x0f" - "\xb2\x04\xf8\x7a\x5f\x30\x96\x5b" - "\xdc\xbd\xdd\x44\x10\x25\x8f\x75" - "\x75\x4d\xb9\x5b\x8e\x0a\x38\x13" - "\x6f\x9f\x36\xe4\x3a\x3e\xac\xc9" - "\x9d\x83\xde\xe5\x57\xfd\xe3\x0e" - "\xb1\xa7\x1b\x44\x05\x67\xb7\x37", - .alen = 64, - .ptext = "\x58\x85\x5c\xfa\x81\xa1\x57\x40" - "\x08\x4a\x6e\xda\xf8\x78\x44\x90" - "\x7d\xb5\x7b\x9b\xa1\xd8\x76\x62" - "\x0c\xc9\x15\x3b\xc7\x3c\x77\x2b" - "\xf8\x78\xba\xa7\xa6\x0e\xbd\x52" - "\x76\xa3\xdc\xbe\x6b\xa8\xb1\x2d" - "\xa9\x1d\xd8\x4e\x31\x53\xab\x00" - "\xa5\xa7\x01\x13\x04\x49\xf2\x04", - .plen = 64, - .ctext = "\x28\xdd\xb9\x4a\x12\xc7\x0a\xe1" - "\x58\x06\x1a\x9b\x8c\x67\xdf\xeb" - "\x35\x35\x60\x9d\x06\x40\x65\xc1" - "\x93\xe8\xb3\x82\x50\x29\xdd\xb5" - "\x2b\xcb\xde\x18\x78\x6b\x42\xbe" - "\x6d\x24\xd0\xb2\x7d\xd7\x08\x8f" - "\x4a\x18\x98\xad\x8c\xf2\x97\xb4" - "\xf4\x77\xe4\xbf\x41\x3b\xc4\x06" - "\xce\x9e\x34\x81\xf0\x89\x11\x13" - "\x02\x65\xa1\x7c\xdf\x07\x33\x06", - .clen = 80, - }, { - .key = "\x67\x4f\xeb\x62\xc5\x40\x01\xc7" - "\x28\x80\x9a\xfe\xf6\x41\x74\x12" - "\x48\x65\xfe\xbc\xe2\x80\x57\x68" - "\x3c\xd4\x4d\x31\x7d\x54\x5f\xe1", - .klen = 32, - .iv = "\x76\x18\x79\xca\x09\xdf\xac\x4e" - "\x48\xb7\xc7\x23\xf5\x0a\xa5\x93", - .assoc = "\x85\xe1\x08\x32\x4d\x7e\x56\xd5" - "\x68\xed\xf3\x47\xf3\xd3\xd6\x15" - "\xdd\xc7\x04\xfe\x64\xd0\x18\x75" - "\x9d\xeb\xbc\x1d\xea\x84\x2e\x4c" - "\x83\xf9\xbe\x8a\xef\x1c\x4b\x10" - "\x89\xaf\xcb\x4b\xfe\xe7\xc1\x58" - "\xca\xea\xc6\x87\xc0\x53\x03\xd9" - "\x80\xaa\xb2\x83\xff\xee\xa1\x6a" - "\x04", - .alen = 65, - .ptext = "\x94\xaa\x96\x9a\x91\x1d\x00\x5c" - "\x88\x24\x20\x6b\xf2\x9c\x06\x96" - "\xa7\x77\x87\x1f\xa6\x78\xf8\x7b" - "\xcd\xf6\xf4\x13\xa1\x9b\x16\x02" - "\x07\x24\xbf\xd5\x08\x20\xd0\x4f" - "\x90\xb3\x70\x24\x2f\x51\xc7\xbb" - "\xd6\x84\xc0\xef\x9a\xa8\xca\xcc" - "\x74\xab\x97\x53\xfe\xd0\xdb\x37" - "\x37\x6a\x0e\x9f\x3f\xa3\x2a\xe3" - "\x1b\x34\x6d\x51\x72\x2b\x17\xe7" - "\x4d\xaa\x2c\x18\xda\xa3\x33\x89" - "\x2a\x9f\xf4\xd2\xed\x76\x3d\x3f" - "\x3c\x15\x9d\x8e\x4f\x3c\x27\xb0" - "\x42\x3f\x2f\x8a\xd4\xc2\x10\xb2" - "\x27\x7f\xe3\x34\x80\x02\x49\x4b" - "\x07\x68\x22\x2a\x88\x25\x53\xb2" - "\x2f", - .plen = 129, - .ctext = "\x85\x39\x69\x35\xfb\xf9\xb0\xa6" - "\x85\x43\x88\xd0\xd7\x78\x60\x19" - "\x3e\x1f\xb1\xa4\xd6\xc5\x96\xec" - "\xf7\x84\x85\xc7\x27\x0f\x74\x57" - "\x28\x9e\xdd\x90\x3c\x43\x12\xc5" - "\x51\x3d\x39\x8f\xa5\xf4\xe0\x0b" - "\x57\x04\xf1\x6d\xfe\x9b\x84\x27" - "\xe8\xeb\x4d\xda\x02\x0a\xc5\x49" - "\x1a\x55\x5e\x50\x56\x4d\x94\xda" - "\x20\xf8\x12\x54\x50\xb3\x11\xda" - "\xed\x44\x27\x67\xd5\xd1\x8b\x4b" - "\x38\x67\x56\x65\x59\xda\xe6\x97" - "\x81\xae\x2f\x92\x3b\xae\x22\x1c" - "\x91\x59\x38\x18\x00\xe8\xba\x92" - "\x04\x19\x56\xdf\xb0\x82\xeb\x6f" - "\x2e\xdb\x54\x3c\x4b\xbb\x60\x90" - "\x4c\x50\x10\x62\xba\x7a\xb1\x68" - "\x37\xd7\x87\x4e\xe4\x66\x09\x1f" - "\xa5", - .clen = 145, - }, { - .key = "\xa3\x73\x24\x01\xd5\xbc\xaa\xe3" - "\xa9\x5a\x4c\x90\xf0\x65\x37\x18" - "\x72\x28\x0a\x40\xe7\x20\xd9\x82" - "\xfe\x02\x2b\x09\x57\xb3\xfe\xb7", - .klen = 32, - .iv = "\xb3\x3d\xb3\x69\x19\x5b\x54\x6a" - "\xc9\x91\x79\xb4\xef\x2e\x68\x99", - .assoc = "\xc2\x06\x41\xd1\x5d\xfa\xff\xf1" - "\xe9\xc7\xa5\xd9\xed\xf8\x98\x1b" - "\x07\x89\x10\x82\x6a\x70\x9a\x8f" - "\x5e\x19\x9b\xf5\xc5\xe3\xcd\x22" - "\x92\xa5\xc2\xb8\x51\x2e\x5e\x0e" - "\xa4\xbe\x5f\xb1\xc1\x90\xd7\xe7" - "\xf7\x52\xae\x28\x29\xa8\x22\xa4" - "\x4f\xae\x48\xc2\xfa\x75\x8b\x9e" - "\xce\x83\x2a\x88\x07\x55\xbb\x89" - "\xf6\xdf\xac\xdf\x83\x08\xbf\x7d" - "\xac\x30\x8b\x8e\x02\xac\x00\xf1" - "\x30\x46\xe1\xbc\x75\xbf\x49\xbb" - "\x26\x4e\x29\xf0\x2f\x21\xc6\x13" - "\x92\xd9\x3d\x11\xe4\x10\x00\x8e" - "\xd4\xd4\x58\x65\xa6\x2b\xe3\x25" - "\xb1\x8f\x15\x93\xe7\x71\xb9\x2c" - "\x4b", - .alen = 129, - .ptext = "\xd1\xcf\xd0\x39\xa1\x99\xa9\x78" - "\x09\xfe\xd2\xfd\xec\xc1\xc9\x9d" - "\xd2\x39\x93\xa3\xab\x18\x7a\x95" - "\x8f\x24\xd3\xeb\x7b\xfa\xb5\xd8" - "\x15\xd1\xc3\x04\x69\x32\xe3\x4d" - "\xaa\xc2\x04\x8b\xf2\xfa\xdc\x4a" - "\x02\xeb\xa8\x90\x03\xfd\xea\x97" - "\x43\xaf\x2e\x92\xf8\x57\xc5\x6a" - "\x00", - .plen = 65, - .ctext = "\x7d\xde\x53\x22\xe4\x23\x3b\x30" - "\x78\xde\x35\x90\x7a\xd9\x0b\x93" - "\xf6\x0e\x0b\xed\x40\xee\x10\x9c" - "\x96\x3a\xd3\x34\xb2\xd0\x67\xcf" - "\x63\x7f\x2d\x0c\xcf\x96\xec\x64" - "\x1a\x87\xcc\x7d\x2c\x5e\x81\x4b" - "\xd2\x8f\x4c\x7c\x00\xb1\xb4\xe0" - "\x87\x4d\xb1\xbc\xd8\x78\x2c\x17" - "\xf2\x3b\xd8\x28\x40\xe2\x76\xf6" - "\x20\x13\x83\x46\xaf\xff\xe3\x0f" - "\x72", - .clen = 81, - }, { - .key = "\xe0\x98\x5e\xa1\xe5\x38\x53\xff" - "\x2a\x35\xfe\x21\xea\x8a\xfa\x1e" - "\x9c\xea\x15\xc5\xec\xc0\x5b\x9b" - "\xbf\x2f\x0a\xe1\x32\x12\x9d\x8e", - .klen = 32, - .iv = "\xef\x61\xed\x08\x29\xd7\xfd\x86" - "\x4a\x6b\x2b\x46\xe9\x53\x2a\xa0", - .assoc = "\xfe\x2a\x7b\x70\x6d\x75\xa7\x0d" - "\x6a\xa2\x57\x6a\xe7\x1c\x5b\x21" - "\x31\x4b\x1b\x07\x6f\x10\x1c\xa8" - "\x20\x46\x7a\xce\x9f\x42\x6d\xf9", - .alen = 32, - .ptext = "\x0d\xf4\x09\xd8\xb1\x14\x51\x94" - "\x8a\xd8\x84\x8e\xe6\xe5\x8c\xa3" - "\xfc\xfc\x9e\x28\xb0\xb8\xfc\xaf" - "\x50\x52\xb1\xc4\x55\x59\x55\xaf", - .plen = 32, - .ctext = "\x5a\xcd\x8c\x57\xf2\x6a\xb6\xbe" - "\x53\xc7\xaa\x9a\x60\x74\x9c\xc4" - "\xa2\xc2\xd0\x6d\xe1\x03\x63\xdc" - "\xbb\x51\x7e\x9c\x89\x73\xde\x4e" - "\x24\xf8\x52\x7c\x15\x41\x0e\xba" - "\x69\x0e\x36\x5f\x2f\x22\x8c", - .clen = 47, - }, { - .key = "\x1c\xbd\x98\x40\xf5\xb3\xfc\x1b" - "\xaa\x0f\xb0\xb3\xe4\xae\xbc\x24" - "\xc7\xac\x21\x49\xf1\x60\xdd\xb5" - "\x80\x5d\xe9\xba\x0c\x71\x3c\x64", - .klen = 32, - .iv = "\x2c\x86\x26\xa8\x39\x52\xa6\xa2" - "\xcb\x45\xdd\xd7\xe3\x77\xed\xa6", - .assoc = "\x3b\x4f\xb5\x10\x7d\xf1\x50\x29" - "\xeb\x7c\x0a\xfb\xe1\x40\x1e\x27" - "\x5c\x0d\x27\x8b\x74\xb0\x9e\xc2" - "\xe1\x74\x59\xa6\x79\xa1\x0c\xd0", - .alen = 32, - .ptext = "\x4a\x18\x43\x77\xc1\x90\xfa\xb0" - "\x0b\xb2\x36\x20\xe0\x09\x4e\xa9" - "\x26\xbe\xaa\xac\xb5\x58\x7e\xc8" - "\x11\x7f\x90\x9c\x2f\xb8\xf4\x85", - .plen = 32, - .ctext = "\x47\xd6\xce\x78\xd6\xbf\x4a\x51" - "\xb8\xda\x92\x3c\xfd\xda\xac\x8e" - "\x8d\x88\xd7\x4d\x90\xe5\xeb\xa1" - "\xab\xd6\x7c\x76\xad\xea\x7d\x76" - "\x53\xee\xb0\xcd\xd0\x02\xbb\x70" - "\x5b\x6f\x7b\xe2\x8c\xe8", - .clen = 46, - }, { - .key = "\x59\xe1\xd2\xdf\x05\x2f\xa4\x37" - "\x2b\xe9\x63\x44\xde\xd3\x7f\x2b" - "\xf1\x6f\x2d\xcd\xf6\x00\x5f\xcf" - "\x42\x8a\xc8\x92\xe6\xd0\xdc\x3b", - .klen = 32, - .iv = "\x68\xab\x60\x47\x49\xce\x4f\xbe" - "\x4c\x20\x8f\x68\xdd\x9c\xb0\xac", - .assoc = "\x77\x74\xee\xaf\x8d\x6d\xf9\x45" - "\x6c\x56\xbc\x8d\xdb\x65\xe0\x2e" - "\x86\xd0\x32\x0f\x79\x50\x20\xdb" - "\xa2\xa1\x37\x7e\x53\x00\xab\xa6", - .alen = 32, - .ptext = "\x86\x3d\x7d\x17\xd1\x0c\xa3\xcc" - "\x8c\x8d\xe8\xb1\xda\x2e\x11\xaf" - "\x51\x80\xb5\x30\xba\xf8\x00\xe2" - "\xd3\xad\x6f\x75\x09\x18\x93\x5c", - .plen = 32, - .ctext = "\x9f\xa9\x2b\xa4\x8f\x00\x05\x2b" - "\xe7\x68\x81\x51\xbb\xfb\xdf\x60" - "\xbb\xac\xe8\xc1\xdc\x68\xae\x68" - "\x3a\xcd\x7a\x06\x49\xfe\x80\x11" - "\xe6\x61\x99\xe2\xdd\xbe\x2c\xbf", - .clen = 40, - }, { - .key = "\x96\x06\x0b\x7f\x15\xab\x4d\x53" - "\xac\xc3\x15\xd6\xd8\xf7\x42\x31" - "\x1b\x31\x38\x51\xfc\xa0\xe1\xe8" - "\x03\xb8\xa7\x6b\xc0\x2f\x7b\x11", - .klen = 32, - .iv = "\xa5\xcf\x9a\xe6\x59\x4a\xf7\xd9" - "\xcd\xfa\x41\xfa\xd7\xc0\x72\xb2", - .assoc = "\xb4\x99\x28\x4e\x9d\xe8\xa2\x60" - "\xed\x30\x6e\x1e\xd5\x89\xa3\x34" - "\xb1\x92\x3e\x93\x7e\xf0\xa2\xf5" - "\x64\xcf\x16\x57\x2d\x5f\x4a\x7d", - .alen = 32, - .ptext = "\xc3\x62\xb7\xb6\xe2\x87\x4c\xe7" - "\x0d\x67\x9a\x43\xd4\x52\xd4\xb5" - "\x7b\x43\xc1\xb5\xbf\x98\x82\xfc" - "\x94\xda\x4e\x4d\xe4\x77\x32\x32", - .plen = 32, - .ctext = "\xe2\x34\xfa\x25\xfd\xfb\x89\x5e" - "\x5b\x4e\x0b\x15\x6e\x39\xfb\x0c" - "\x73\xc7\xd9\x6b\xbe\xce\x9b\x70" - "\xc7\x4f\x96\x16\x03\xfc\xea\xfb" - "\x56", - .clen = 33, - }, -}; - /* * All key wrapping test vectors taken from * http://csrc.nist.gov/groups/STM/cavp/documents/mac/kwtestvectors.zip diff --git a/include/crypto/morus1280_glue.h b/include/crypto/morus1280_glue.h deleted file mode 100644 index 5cefddb1991f..000000000000 --- a/include/crypto/morus1280_glue.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * The MORUS-1280 Authenticated-Encryption Algorithm - * Common glue skeleton -- header file - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#ifndef _CRYPTO_MORUS1280_GLUE_H -#define _CRYPTO_MORUS1280_GLUE_H - -#include -#include -#include -#include -#include - -#define MORUS1280_WORD_SIZE 8 -#define MORUS1280_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS1280_WORD_SIZE) - -struct morus1280_block { - u8 bytes[MORUS1280_BLOCK_SIZE]; -}; - -struct morus1280_glue_ops { - void (*init)(void *state, const void *key, const void *iv); - void (*ad)(void *state, const void *data, unsigned int length); - void (*enc)(void *state, const void *src, void *dst, unsigned int length); - void (*dec)(void *state, const void *src, void *dst, unsigned int length); - void (*enc_tail)(void *state, const void *src, void *dst, unsigned int length); - void (*dec_tail)(void *state, const void *src, void *dst, unsigned int length); - void (*final)(void *state, void *tag_xor, u64 assoclen, u64 cryptlen); -}; - -struct morus1280_ctx { - const struct morus1280_glue_ops *ops; - struct morus1280_block key; -}; - -void crypto_morus1280_glue_init_ops(struct crypto_aead *aead, - const struct morus1280_glue_ops *ops); -int crypto_morus1280_glue_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen); -int crypto_morus1280_glue_setauthsize(struct crypto_aead *tfm, - unsigned int authsize); -int crypto_morus1280_glue_encrypt(struct aead_request *req); -int crypto_morus1280_glue_decrypt(struct aead_request *req); - -#define MORUS1280_DECLARE_ALG(id, driver_name, priority) \ - static const struct morus1280_glue_ops crypto_morus1280_##id##_ops = {\ - .init = crypto_morus1280_##id##_init, \ - .ad = crypto_morus1280_##id##_ad, \ - .enc = crypto_morus1280_##id##_enc, \ - .enc_tail = crypto_morus1280_##id##_enc_tail, \ - .dec = crypto_morus1280_##id##_dec, \ - .dec_tail = crypto_morus1280_##id##_dec_tail, \ - .final = crypto_morus1280_##id##_final, \ - }; \ - \ - static int crypto_morus1280_##id##_init_tfm(struct crypto_aead *tfm) \ - { \ - crypto_morus1280_glue_init_ops(tfm, &crypto_morus1280_##id##_ops); \ - return 0; \ - } \ - \ - static void crypto_morus1280_##id##_exit_tfm(struct crypto_aead *tfm) \ - { \ - } \ - \ - static struct aead_alg crypto_morus1280_##id##_alg = { \ - .setkey = crypto_morus1280_glue_setkey, \ - .setauthsize = crypto_morus1280_glue_setauthsize, \ - .encrypt = crypto_morus1280_glue_encrypt, \ - .decrypt = crypto_morus1280_glue_decrypt, \ - .init = crypto_morus1280_##id##_init_tfm, \ - .exit = crypto_morus1280_##id##_exit_tfm, \ - \ - .ivsize = MORUS_NONCE_SIZE, \ - .maxauthsize = MORUS_MAX_AUTH_SIZE, \ - .chunksize = MORUS1280_BLOCK_SIZE, \ - \ - .base = { \ - .cra_flags = CRYPTO_ALG_INTERNAL, \ - .cra_blocksize = 1, \ - .cra_ctxsize = sizeof(struct morus1280_ctx), \ - .cra_alignmask = 0, \ - .cra_priority = priority, \ - \ - .cra_name = "__morus1280", \ - .cra_driver_name = "__"driver_name, \ - \ - .cra_module = THIS_MODULE, \ - } \ - } - -#endif /* _CRYPTO_MORUS1280_GLUE_H */ diff --git a/include/crypto/morus640_glue.h b/include/crypto/morus640_glue.h deleted file mode 100644 index 0ee6266cb26c..000000000000 --- a/include/crypto/morus640_glue.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * The MORUS-640 Authenticated-Encryption Algorithm - * Common glue skeleton -- header file - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#ifndef _CRYPTO_MORUS640_GLUE_H -#define _CRYPTO_MORUS640_GLUE_H - -#include -#include -#include -#include -#include - -#define MORUS640_WORD_SIZE 4 -#define MORUS640_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS640_WORD_SIZE) - -struct morus640_block { - u8 bytes[MORUS640_BLOCK_SIZE]; -}; - -struct morus640_glue_ops { - void (*init)(void *state, const void *key, const void *iv); - void (*ad)(void *state, const void *data, unsigned int length); - void (*enc)(void *state, const void *src, void *dst, unsigned int length); - void (*dec)(void *state, const void *src, void *dst, unsigned int length); - void (*enc_tail)(void *state, const void *src, void *dst, unsigned int length); - void (*dec_tail)(void *state, const void *src, void *dst, unsigned int length); - void (*final)(void *state, void *tag_xor, u64 assoclen, u64 cryptlen); -}; - -struct morus640_ctx { - const struct morus640_glue_ops *ops; - struct morus640_block key; -}; - -void crypto_morus640_glue_init_ops(struct crypto_aead *aead, - const struct morus640_glue_ops *ops); -int crypto_morus640_glue_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen); -int crypto_morus640_glue_setauthsize(struct crypto_aead *tfm, - unsigned int authsize); -int crypto_morus640_glue_encrypt(struct aead_request *req); -int crypto_morus640_glue_decrypt(struct aead_request *req); - -#define MORUS640_DECLARE_ALG(id, driver_name, priority) \ - static const struct morus640_glue_ops crypto_morus640_##id##_ops = {\ - .init = crypto_morus640_##id##_init, \ - .ad = crypto_morus640_##id##_ad, \ - .enc = crypto_morus640_##id##_enc, \ - .enc_tail = crypto_morus640_##id##_enc_tail, \ - .dec = crypto_morus640_##id##_dec, \ - .dec_tail = crypto_morus640_##id##_dec_tail, \ - .final = crypto_morus640_##id##_final, \ - }; \ - \ - static int crypto_morus640_##id##_init_tfm(struct crypto_aead *tfm) \ - { \ - crypto_morus640_glue_init_ops(tfm, &crypto_morus640_##id##_ops); \ - return 0; \ - } \ - \ - static void crypto_morus640_##id##_exit_tfm(struct crypto_aead *tfm) \ - { \ - } \ - \ - static struct aead_alg crypto_morus640_##id##_alg = {\ - .setkey = crypto_morus640_glue_setkey, \ - .setauthsize = crypto_morus640_glue_setauthsize, \ - .encrypt = crypto_morus640_glue_encrypt, \ - .decrypt = crypto_morus640_glue_decrypt, \ - .init = crypto_morus640_##id##_init_tfm, \ - .exit = crypto_morus640_##id##_exit_tfm, \ - \ - .ivsize = MORUS_NONCE_SIZE, \ - .maxauthsize = MORUS_MAX_AUTH_SIZE, \ - .chunksize = MORUS640_BLOCK_SIZE, \ - \ - .base = { \ - .cra_flags = CRYPTO_ALG_INTERNAL, \ - .cra_blocksize = 1, \ - .cra_ctxsize = sizeof(struct morus640_ctx), \ - .cra_alignmask = 0, \ - .cra_priority = priority, \ - \ - .cra_name = "__morus640", \ - .cra_driver_name = "__"driver_name, \ - \ - .cra_module = THIS_MODULE, \ - } \ - } - -#endif /* _CRYPTO_MORUS640_GLUE_H */ diff --git a/include/crypto/morus_common.h b/include/crypto/morus_common.h deleted file mode 100644 index 969510a9a56c..000000000000 --- a/include/crypto/morus_common.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * The MORUS Authenticated-Encryption Algorithm - * Common definitions - * - * Copyright (c) 2016-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#ifndef _CRYPTO_MORUS_COMMON_H -#define _CRYPTO_MORUS_COMMON_H - -#define MORUS_BLOCK_WORDS 4 -#define MORUS_STATE_BLOCKS 5 -#define MORUS_NONCE_SIZE 16 -#define MORUS_MAX_AUTH_SIZE 16 - -#endif /* _CRYPTO_MORUS_COMMON_H */ -- GitLab From 520c1993bbe620e39fd93de1a01b9e0dc0b97aa6 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:07 +0200 Subject: [PATCH 0803/7155] crypto: aegis128l/aegis256 - remove x86 and generic implementations Three variants of AEGIS were proposed for the CAESAR competition, and only one was selected for the final portfolio: AEGIS128. The other variants, AEGIS128L and AEGIS256, are not likely to ever turn up in networking protocols or other places where interoperability between Linux and other systems is a concern, nor are they likely to be subjected to further cryptanalysis. However, uninformed users may think that AEGIS128L (which is faster) is equally fit for use. So let's remove them now, before anyone starts using them and we are forced to support them forever. Note that there are no known flaws in the algorithms or in any of these implementations, but they have simply outlived their usefulness. Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/Makefile | 4 - arch/x86/crypto/aegis128l-aesni-asm.S | 823 --------------------- arch/x86/crypto/aegis128l-aesni-glue.c | 293 -------- arch/x86/crypto/aegis256-aesni-asm.S | 700 ------------------ arch/x86/crypto/aegis256-aesni-glue.c | 293 -------- crypto/Kconfig | 30 - crypto/Makefile | 2 - crypto/aegis128l.c | 522 ------------- crypto/aegis256.c | 473 ------------ crypto/testmgr.c | 12 - crypto/testmgr.h | 984 ------------------------- 11 files changed, 4136 deletions(-) delete mode 100644 arch/x86/crypto/aegis128l-aesni-asm.S delete mode 100644 arch/x86/crypto/aegis128l-aesni-glue.c delete mode 100644 arch/x86/crypto/aegis256-aesni-asm.S delete mode 100644 arch/x86/crypto/aegis256-aesni-glue.c delete mode 100644 crypto/aegis128l.c delete mode 100644 crypto/aegis256.c diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 6f1d825fbb09..759b1a927826 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -36,8 +36,6 @@ obj-$(CONFIG_CRYPTO_CRCT10DIF_PCLMUL) += crct10dif-pclmul.o obj-$(CONFIG_CRYPTO_POLY1305_X86_64) += poly1305-x86_64.o obj-$(CONFIG_CRYPTO_AEGIS128_AESNI_SSE2) += aegis128-aesni.o -obj-$(CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2) += aegis128l-aesni.o -obj-$(CONFIG_CRYPTO_AEGIS256_AESNI_SSE2) += aegis256-aesni.o obj-$(CONFIG_CRYPTO_NHPOLY1305_SSE2) += nhpoly1305-sse2.o obj-$(CONFIG_CRYPTO_NHPOLY1305_AVX2) += nhpoly1305-avx2.o @@ -70,8 +68,6 @@ chacha-x86_64-y := chacha-ssse3-x86_64.o chacha_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o aegis128-aesni-y := aegis128-aesni-asm.o aegis128-aesni-glue.o -aegis128l-aesni-y := aegis128l-aesni-asm.o aegis128l-aesni-glue.o -aegis256-aesni-y := aegis256-aesni-asm.o aegis256-aesni-glue.o nhpoly1305-sse2-y := nh-sse2-x86_64.o nhpoly1305-sse2-glue.o diff --git a/arch/x86/crypto/aegis128l-aesni-asm.S b/arch/x86/crypto/aegis128l-aesni-asm.S deleted file mode 100644 index 1461ef00c0e8..000000000000 --- a/arch/x86/crypto/aegis128l-aesni-asm.S +++ /dev/null @@ -1,823 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * AES-NI + SSE2 implementation of AEGIS-128L - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include - -#define STATE0 %xmm0 -#define STATE1 %xmm1 -#define STATE2 %xmm2 -#define STATE3 %xmm3 -#define STATE4 %xmm4 -#define STATE5 %xmm5 -#define STATE6 %xmm6 -#define STATE7 %xmm7 -#define MSG0 %xmm8 -#define MSG1 %xmm9 -#define T0 %xmm10 -#define T1 %xmm11 -#define T2 %xmm12 -#define T3 %xmm13 - -#define STATEP %rdi -#define LEN %rsi -#define SRC %rdx -#define DST %rcx - -.section .rodata.cst16.aegis128l_const, "aM", @progbits, 32 -.align 16 -.Laegis128l_const_0: - .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d - .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62 -.Laegis128l_const_1: - .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 - .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd - -.section .rodata.cst16.aegis128l_counter, "aM", @progbits, 16 -.align 16 -.Laegis128l_counter0: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f -.Laegis128l_counter1: - .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 - .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - -.text - -/* - * __load_partial: internal ABI - * input: - * LEN - bytes - * SRC - src - * output: - * MSG0 - first message block - * MSG1 - second message block - * changed: - * T0 - * %r8 - * %r9 - */ -__load_partial: - xor %r9d, %r9d - pxor MSG0, MSG0 - pxor MSG1, MSG1 - - mov LEN, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov LEN, %r8 - and $0x1E, %r8 - add SRC, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov LEN, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov LEN, %r8 - and $0x1C, %r8 - add SRC, %r8 - shl $0x10, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov LEN, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov LEN, %r8 - and $0x18, %r8 - add SRC, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG0 - - mov LEN, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov LEN, %r8 - and $0x10, %r8 - add SRC, %r8 - pslldq $8, MSG0 - movq (%r8), T0 - pxor T0, MSG0 - -.Lld_partial_8: - mov LEN, %r8 - and $0x10, %r8 - jz .Lld_partial_16 - - movdqa MSG0, MSG1 - movdqu (SRC), MSG0 - -.Lld_partial_16: - ret -ENDPROC(__load_partial) - -/* - * __store_partial: internal ABI - * input: - * LEN - bytes - * DST - dst - * output: - * T0 - first message block - * T1 - second message block - * changed: - * %r8 - * %r9 - * %r10 - */ -__store_partial: - mov LEN, %r8 - mov DST, %r9 - - cmp $16, %r8 - jl .Lst_partial_16 - - movdqu T0, (%r9) - movdqa T1, T0 - - sub $16, %r8 - add $16, %r9 - -.Lst_partial_16: - movq T0, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - psrldq $8, T0 - movq T0, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $0x10, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - ret -ENDPROC(__store_partial) - -.macro update - movdqa STATE7, T0 - aesenc STATE0, STATE7 - aesenc STATE1, STATE0 - aesenc STATE2, STATE1 - aesenc STATE3, STATE2 - aesenc STATE4, STATE3 - aesenc STATE5, STATE4 - aesenc STATE6, STATE5 - aesenc T0, STATE6 -.endm - -.macro update0 - update - pxor MSG0, STATE7 - pxor MSG1, STATE3 -.endm - -.macro update1 - update - pxor MSG0, STATE6 - pxor MSG1, STATE2 -.endm - -.macro update2 - update - pxor MSG0, STATE5 - pxor MSG1, STATE1 -.endm - -.macro update3 - update - pxor MSG0, STATE4 - pxor MSG1, STATE0 -.endm - -.macro update4 - update - pxor MSG0, STATE3 - pxor MSG1, STATE7 -.endm - -.macro update5 - update - pxor MSG0, STATE2 - pxor MSG1, STATE6 -.endm - -.macro update6 - update - pxor MSG0, STATE1 - pxor MSG1, STATE5 -.endm - -.macro update7 - update - pxor MSG0, STATE0 - pxor MSG1, STATE4 -.endm - -.macro state_load - movdqu 0x00(STATEP), STATE0 - movdqu 0x10(STATEP), STATE1 - movdqu 0x20(STATEP), STATE2 - movdqu 0x30(STATEP), STATE3 - movdqu 0x40(STATEP), STATE4 - movdqu 0x50(STATEP), STATE5 - movdqu 0x60(STATEP), STATE6 - movdqu 0x70(STATEP), STATE7 -.endm - -.macro state_store s0 s1 s2 s3 s4 s5 s6 s7 - movdqu \s7, 0x00(STATEP) - movdqu \s0, 0x10(STATEP) - movdqu \s1, 0x20(STATEP) - movdqu \s2, 0x30(STATEP) - movdqu \s3, 0x40(STATEP) - movdqu \s4, 0x50(STATEP) - movdqu \s5, 0x60(STATEP) - movdqu \s6, 0x70(STATEP) -.endm - -.macro state_store0 - state_store STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 -.endm - -.macro state_store1 - state_store STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 -.endm - -.macro state_store2 - state_store STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 -.endm - -.macro state_store3 - state_store STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 -.endm - -.macro state_store4 - state_store STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 -.endm - -.macro state_store5 - state_store STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 -.endm - -.macro state_store6 - state_store STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 -.endm - -.macro state_store7 - state_store STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 -.endm - -/* - * void crypto_aegis128l_aesni_init(void *state, const void *key, const void *iv); - */ -ENTRY(crypto_aegis128l_aesni_init) - FRAME_BEGIN - - /* load key: */ - movdqa (%rsi), MSG1 - movdqa MSG1, STATE0 - movdqa MSG1, STATE4 - movdqa MSG1, STATE5 - movdqa MSG1, STATE6 - movdqa MSG1, STATE7 - - /* load IV: */ - movdqu (%rdx), MSG0 - pxor MSG0, STATE0 - pxor MSG0, STATE4 - - /* load the constants: */ - movdqa .Laegis128l_const_0, STATE2 - movdqa .Laegis128l_const_1, STATE1 - movdqa STATE1, STATE3 - pxor STATE2, STATE5 - pxor STATE1, STATE6 - pxor STATE2, STATE7 - - /* update 10 times with IV and KEY: */ - update0 - update1 - update2 - update3 - update4 - update5 - update6 - update7 - update0 - update1 - - state_store1 - - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_init) - -.macro ad_block a i - movdq\a (\i * 0x20 + 0x00)(SRC), MSG0 - movdq\a (\i * 0x20 + 0x10)(SRC), MSG1 - update\i - sub $0x20, LEN - cmp $0x20, LEN - jl .Lad_out_\i -.endm - -/* - * void crypto_aegis128l_aesni_ad(void *state, unsigned int length, - * const void *data); - */ -ENTRY(crypto_aegis128l_aesni_ad) - FRAME_BEGIN - - cmp $0x20, LEN - jb .Lad_out - - state_load - - mov SRC, %r8 - and $0xf, %r8 - jnz .Lad_u_loop - -.align 8 -.Lad_a_loop: - ad_block a 0 - ad_block a 1 - ad_block a 2 - ad_block a 3 - ad_block a 4 - ad_block a 5 - ad_block a 6 - ad_block a 7 - - add $0x100, SRC - jmp .Lad_a_loop - -.align 8 -.Lad_u_loop: - ad_block u 0 - ad_block u 1 - ad_block u 2 - ad_block u 3 - ad_block u 4 - ad_block u 5 - ad_block u 6 - ad_block u 7 - - add $0x100, SRC - jmp .Lad_u_loop - -.Lad_out_0: - state_store0 - FRAME_END - ret - -.Lad_out_1: - state_store1 - FRAME_END - ret - -.Lad_out_2: - state_store2 - FRAME_END - ret - -.Lad_out_3: - state_store3 - FRAME_END - ret - -.Lad_out_4: - state_store4 - FRAME_END - ret - -.Lad_out_5: - state_store5 - FRAME_END - ret - -.Lad_out_6: - state_store6 - FRAME_END - ret - -.Lad_out_7: - state_store7 - FRAME_END - ret - -.Lad_out: - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_ad) - -.macro crypt m0 m1 s0 s1 s2 s3 s4 s5 s6 s7 - pxor \s1, \m0 - pxor \s6, \m0 - movdqa \s2, T3 - pand \s3, T3 - pxor T3, \m0 - - pxor \s2, \m1 - pxor \s5, \m1 - movdqa \s6, T3 - pand \s7, T3 - pxor T3, \m1 -.endm - -.macro crypt0 m0 m1 - crypt \m0 \m1 STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 -.endm - -.macro crypt1 m0 m1 - crypt \m0 \m1 STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 -.endm - -.macro crypt2 m0 m1 - crypt \m0 \m1 STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 -.endm - -.macro crypt3 m0 m1 - crypt \m0 \m1 STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 STATE4 -.endm - -.macro crypt4 m0 m1 - crypt \m0 \m1 STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 STATE3 -.endm - -.macro crypt5 m0 m1 - crypt \m0 \m1 STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 STATE2 -.endm - -.macro crypt6 m0 m1 - crypt \m0 \m1 STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 STATE1 -.endm - -.macro crypt7 m0 m1 - crypt \m0 \m1 STATE1 STATE2 STATE3 STATE4 STATE5 STATE6 STATE7 STATE0 -.endm - -.macro encrypt_block a i - movdq\a (\i * 0x20 + 0x00)(SRC), MSG0 - movdq\a (\i * 0x20 + 0x10)(SRC), MSG1 - movdqa MSG0, T0 - movdqa MSG1, T1 - crypt\i T0, T1 - movdq\a T0, (\i * 0x20 + 0x00)(DST) - movdq\a T1, (\i * 0x20 + 0x10)(DST) - - update\i - - sub $0x20, LEN - cmp $0x20, LEN - jl .Lenc_out_\i -.endm - -.macro decrypt_block a i - movdq\a (\i * 0x20 + 0x00)(SRC), MSG0 - movdq\a (\i * 0x20 + 0x10)(SRC), MSG1 - crypt\i MSG0, MSG1 - movdq\a MSG0, (\i * 0x20 + 0x00)(DST) - movdq\a MSG1, (\i * 0x20 + 0x10)(DST) - - update\i - - sub $0x20, LEN - cmp $0x20, LEN - jl .Ldec_out_\i -.endm - -/* - * void crypto_aegis128l_aesni_enc(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis128l_aesni_enc) - FRAME_BEGIN - - cmp $0x20, LEN - jb .Lenc_out - - state_load - - mov SRC, %r8 - or DST, %r8 - and $0xf, %r8 - jnz .Lenc_u_loop - -.align 8 -.Lenc_a_loop: - encrypt_block a 0 - encrypt_block a 1 - encrypt_block a 2 - encrypt_block a 3 - encrypt_block a 4 - encrypt_block a 5 - encrypt_block a 6 - encrypt_block a 7 - - add $0x100, SRC - add $0x100, DST - jmp .Lenc_a_loop - -.align 8 -.Lenc_u_loop: - encrypt_block u 0 - encrypt_block u 1 - encrypt_block u 2 - encrypt_block u 3 - encrypt_block u 4 - encrypt_block u 5 - encrypt_block u 6 - encrypt_block u 7 - - add $0x100, SRC - add $0x100, DST - jmp .Lenc_u_loop - -.Lenc_out_0: - state_store0 - FRAME_END - ret - -.Lenc_out_1: - state_store1 - FRAME_END - ret - -.Lenc_out_2: - state_store2 - FRAME_END - ret - -.Lenc_out_3: - state_store3 - FRAME_END - ret - -.Lenc_out_4: - state_store4 - FRAME_END - ret - -.Lenc_out_5: - state_store5 - FRAME_END - ret - -.Lenc_out_6: - state_store6 - FRAME_END - ret - -.Lenc_out_7: - state_store7 - FRAME_END - ret - -.Lenc_out: - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_enc) - -/* - * void crypto_aegis128l_aesni_enc_tail(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis128l_aesni_enc_tail) - FRAME_BEGIN - - state_load - - /* encrypt message: */ - call __load_partial - - movdqa MSG0, T0 - movdqa MSG1, T1 - crypt0 T0, T1 - - call __store_partial - - update0 - - state_store0 - - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_enc_tail) - -/* - * void crypto_aegis128l_aesni_dec(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis128l_aesni_dec) - FRAME_BEGIN - - cmp $0x20, LEN - jb .Ldec_out - - state_load - - mov SRC, %r8 - or DST, %r8 - and $0xF, %r8 - jnz .Ldec_u_loop - -.align 8 -.Ldec_a_loop: - decrypt_block a 0 - decrypt_block a 1 - decrypt_block a 2 - decrypt_block a 3 - decrypt_block a 4 - decrypt_block a 5 - decrypt_block a 6 - decrypt_block a 7 - - add $0x100, SRC - add $0x100, DST - jmp .Ldec_a_loop - -.align 8 -.Ldec_u_loop: - decrypt_block u 0 - decrypt_block u 1 - decrypt_block u 2 - decrypt_block u 3 - decrypt_block u 4 - decrypt_block u 5 - decrypt_block u 6 - decrypt_block u 7 - - add $0x100, SRC - add $0x100, DST - jmp .Ldec_u_loop - -.Ldec_out_0: - state_store0 - FRAME_END - ret - -.Ldec_out_1: - state_store1 - FRAME_END - ret - -.Ldec_out_2: - state_store2 - FRAME_END - ret - -.Ldec_out_3: - state_store3 - FRAME_END - ret - -.Ldec_out_4: - state_store4 - FRAME_END - ret - -.Ldec_out_5: - state_store5 - FRAME_END - ret - -.Ldec_out_6: - state_store6 - FRAME_END - ret - -.Ldec_out_7: - state_store7 - FRAME_END - ret - -.Ldec_out: - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_dec) - -/* - * void crypto_aegis128l_aesni_dec_tail(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis128l_aesni_dec_tail) - FRAME_BEGIN - - state_load - - /* decrypt message: */ - call __load_partial - - crypt0 MSG0, MSG1 - - movdqa MSG0, T0 - movdqa MSG1, T1 - call __store_partial - - /* mask with byte count: */ - movq LEN, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - movdqa T0, T1 - movdqa .Laegis128l_counter0, T2 - movdqa .Laegis128l_counter1, T3 - pcmpgtb T2, T0 - pcmpgtb T3, T1 - pand T0, MSG0 - pand T1, MSG1 - - update0 - - state_store0 - - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_dec_tail) - -/* - * void crypto_aegis128l_aesni_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); - */ -ENTRY(crypto_aegis128l_aesni_final) - FRAME_BEGIN - - state_load - - /* prepare length block: */ - movq %rdx, MSG0 - movq %rcx, T0 - pslldq $8, T0 - pxor T0, MSG0 - psllq $3, MSG0 /* multiply by 8 (to get bit count) */ - - pxor STATE2, MSG0 - movdqa MSG0, MSG1 - - /* update state: */ - update0 - update1 - update2 - update3 - update4 - update5 - update6 - - /* xor tag: */ - movdqu (%rsi), T0 - - pxor STATE1, T0 - pxor STATE2, T0 - pxor STATE3, T0 - pxor STATE4, T0 - pxor STATE5, T0 - pxor STATE6, T0 - pxor STATE7, T0 - - movdqu T0, (%rsi) - - FRAME_END - ret -ENDPROC(crypto_aegis128l_aesni_final) diff --git a/arch/x86/crypto/aegis128l-aesni-glue.c b/arch/x86/crypto/aegis128l-aesni-glue.c deleted file mode 100644 index 19eb28b316f0..000000000000 --- a/arch/x86/crypto/aegis128l-aesni-glue.c +++ /dev/null @@ -1,293 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The AEGIS-128L Authenticated-Encryption Algorithm - * Glue for AES-NI + SSE2 implementation - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define AEGIS128L_BLOCK_ALIGN 16 -#define AEGIS128L_BLOCK_SIZE 32 -#define AEGIS128L_NONCE_SIZE 16 -#define AEGIS128L_STATE_BLOCKS 8 -#define AEGIS128L_KEY_SIZE 16 -#define AEGIS128L_MIN_AUTH_SIZE 8 -#define AEGIS128L_MAX_AUTH_SIZE 16 - -asmlinkage void crypto_aegis128l_aesni_init(void *state, void *key, void *iv); - -asmlinkage void crypto_aegis128l_aesni_ad( - void *state, unsigned int length, const void *data); - -asmlinkage void crypto_aegis128l_aesni_enc( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128l_aesni_dec( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128l_aesni_enc_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128l_aesni_dec_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128l_aesni_final( - void *state, void *tag_xor, unsigned int cryptlen, - unsigned int assoclen); - -struct aegis_block { - u8 bytes[AEGIS128L_BLOCK_SIZE] __aligned(AEGIS128L_BLOCK_ALIGN); -}; - -struct aegis_state { - struct aegis_block blocks[AEGIS128L_STATE_BLOCKS]; -}; - -struct aegis_ctx { - struct aegis_block key; -}; - -struct aegis_crypt_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_blocks)(void *state, unsigned int length, const void *src, - void *dst); - void (*crypt_tail)(void *state, unsigned int length, const void *src, - void *dst); -}; - -static void crypto_aegis128l_aesni_process_ad( - struct aegis_state *state, struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - struct aegis_block buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= AEGIS128L_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = AEGIS128L_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - crypto_aegis128l_aesni_ad(state, - AEGIS128L_BLOCK_SIZE, - buf.bytes); - pos = 0; - left -= fill; - src += fill; - } - - crypto_aegis128l_aesni_ad(state, left, src); - - src += left & ~(AEGIS128L_BLOCK_SIZE - 1); - left &= AEGIS128L_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - pos += left; - assoclen -= size; - - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, AEGIS128L_BLOCK_SIZE - pos); - crypto_aegis128l_aesni_ad(state, AEGIS128L_BLOCK_SIZE, buf.bytes); - } -} - -static void crypto_aegis128l_aesni_process_crypt( - struct aegis_state *state, struct skcipher_walk *walk, - const struct aegis_crypt_ops *ops) -{ - while (walk->nbytes >= AEGIS128L_BLOCK_SIZE) { - ops->crypt_blocks(state, round_down(walk->nbytes, - AEGIS128L_BLOCK_SIZE), - walk->src.virt.addr, walk->dst.virt.addr); - skcipher_walk_done(walk, walk->nbytes % AEGIS128L_BLOCK_SIZE); - } - - if (walk->nbytes) { - ops->crypt_tail(state, walk->nbytes, walk->src.virt.addr, - walk->dst.virt.addr); - skcipher_walk_done(walk, 0); - } -} - -static struct aegis_ctx *crypto_aegis128l_aesni_ctx(struct crypto_aead *aead) -{ - u8 *ctx = crypto_aead_ctx(aead); - ctx = PTR_ALIGN(ctx, __alignof__(struct aegis_ctx)); - return (void *)ctx; -} - -static int crypto_aegis128l_aesni_setkey(struct crypto_aead *aead, - const u8 *key, unsigned int keylen) -{ - struct aegis_ctx *ctx = crypto_aegis128l_aesni_ctx(aead); - - if (keylen != AEGIS128L_KEY_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - memcpy(ctx->key.bytes, key, AEGIS128L_KEY_SIZE); - - return 0; -} - -static int crypto_aegis128l_aesni_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - if (authsize > AEGIS128L_MAX_AUTH_SIZE) - return -EINVAL; - if (authsize < AEGIS128L_MIN_AUTH_SIZE) - return -EINVAL; - return 0; -} - -static void crypto_aegis128l_aesni_crypt(struct aead_request *req, - struct aegis_block *tag_xor, - unsigned int cryptlen, - const struct aegis_crypt_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_ctx *ctx = crypto_aegis128l_aesni_ctx(tfm); - struct skcipher_walk walk; - struct aegis_state state; - - ops->skcipher_walk_init(&walk, req, true); - - kernel_fpu_begin(); - - crypto_aegis128l_aesni_init(&state, ctx->key.bytes, req->iv); - crypto_aegis128l_aesni_process_ad(&state, req->src, req->assoclen); - crypto_aegis128l_aesni_process_crypt(&state, &walk, ops); - crypto_aegis128l_aesni_final(&state, tag_xor, req->assoclen, cryptlen); - - kernel_fpu_end(); -} - -static int crypto_aegis128l_aesni_encrypt(struct aead_request *req) -{ - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_blocks = crypto_aegis128l_aesni_enc, - .crypt_tail = crypto_aegis128l_aesni_enc_tail, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_aegis128l_aesni_crypt(req, &tag, cryptlen, &OPS); - - scatterwalk_map_and_copy(tag.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} - -static int crypto_aegis128l_aesni_decrypt(struct aead_request *req) -{ - static const struct aegis_block zeros = {}; - - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_blocks = crypto_aegis128l_aesni_dec, - .crypt_tail = crypto_aegis128l_aesni_dec_tail, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_aegis128l_aesni_crypt(req, &tag, cryptlen, &OPS); - - return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0; -} - -static int crypto_aegis128l_aesni_init_tfm(struct crypto_aead *aead) -{ - return 0; -} - -static void crypto_aegis128l_aesni_exit_tfm(struct crypto_aead *aead) -{ -} - -static struct aead_alg crypto_aegis128l_aesni_alg = { - .setkey = crypto_aegis128l_aesni_setkey, - .setauthsize = crypto_aegis128l_aesni_setauthsize, - .encrypt = crypto_aegis128l_aesni_encrypt, - .decrypt = crypto_aegis128l_aesni_decrypt, - .init = crypto_aegis128l_aesni_init_tfm, - .exit = crypto_aegis128l_aesni_exit_tfm, - - .ivsize = AEGIS128L_NONCE_SIZE, - .maxauthsize = AEGIS128L_MAX_AUTH_SIZE, - .chunksize = AEGIS128L_BLOCK_SIZE, - - .base = { - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct aegis_ctx) + - __alignof__(struct aegis_ctx), - .cra_alignmask = 0, - .cra_priority = 400, - - .cra_name = "__aegis128l", - .cra_driver_name = "__aegis128l-aesni", - - .cra_module = THIS_MODULE, - } -}; - -static struct simd_aead_alg *simd_alg; - -static int __init crypto_aegis128l_aesni_module_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_XMM2) || - !boot_cpu_has(X86_FEATURE_AES) || - !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) - return -ENODEV; - - return simd_register_aeads_compat(&crypto_aegis128l_aesni_alg, 1, - &simd_alg); -} - -static void __exit crypto_aegis128l_aesni_module_exit(void) -{ - simd_unregister_aeads(&crypto_aegis128l_aesni_alg, 1, &simd_alg); -} - -module_init(crypto_aegis128l_aesni_module_init); -module_exit(crypto_aegis128l_aesni_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("AEGIS-128L AEAD algorithm -- AESNI+SSE2 implementation"); -MODULE_ALIAS_CRYPTO("aegis128l"); -MODULE_ALIAS_CRYPTO("aegis128l-aesni"); diff --git a/arch/x86/crypto/aegis256-aesni-asm.S b/arch/x86/crypto/aegis256-aesni-asm.S deleted file mode 100644 index 37d9b13dfd85..000000000000 --- a/arch/x86/crypto/aegis256-aesni-asm.S +++ /dev/null @@ -1,700 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * AES-NI + SSE2 implementation of AEGIS-128L - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include - -#define STATE0 %xmm0 -#define STATE1 %xmm1 -#define STATE2 %xmm2 -#define STATE3 %xmm3 -#define STATE4 %xmm4 -#define STATE5 %xmm5 -#define MSG %xmm6 -#define T0 %xmm7 -#define T1 %xmm8 -#define T2 %xmm9 -#define T3 %xmm10 - -#define STATEP %rdi -#define LEN %rsi -#define SRC %rdx -#define DST %rcx - -.section .rodata.cst16.aegis256_const, "aM", @progbits, 32 -.align 16 -.Laegis256_const_0: - .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d - .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62 -.Laegis256_const_1: - .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 - .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd - -.section .rodata.cst16.aegis256_counter, "aM", @progbits, 16 -.align 16 -.Laegis256_counter: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - -.text - -/* - * __load_partial: internal ABI - * input: - * LEN - bytes - * SRC - src - * output: - * MSG - message block - * changed: - * T0 - * %r8 - * %r9 - */ -__load_partial: - xor %r9d, %r9d - pxor MSG, MSG - - mov LEN, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov LEN, %r8 - and $0x1E, %r8 - add SRC, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov LEN, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov LEN, %r8 - and $0x1C, %r8 - add SRC, %r8 - shl $0x10, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov LEN, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov LEN, %r8 - and $0x18, %r8 - add SRC, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG - - mov LEN, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov LEN, %r8 - and $0x10, %r8 - add SRC, %r8 - pslldq $8, MSG - movq (%r8), T0 - pxor T0, MSG - -.Lld_partial_8: - ret -ENDPROC(__load_partial) - -/* - * __store_partial: internal ABI - * input: - * LEN - bytes - * DST - dst - * output: - * T0 - message block - * changed: - * %r8 - * %r9 - * %r10 - */ -__store_partial: - mov LEN, %r8 - mov DST, %r9 - - movq T0, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - psrldq $8, T0 - movq T0, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $0x10, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - ret -ENDPROC(__store_partial) - -.macro update - movdqa STATE5, T0 - aesenc STATE0, STATE5 - aesenc STATE1, STATE0 - aesenc STATE2, STATE1 - aesenc STATE3, STATE2 - aesenc STATE4, STATE3 - aesenc T0, STATE4 -.endm - -.macro update0 m - update - pxor \m, STATE5 -.endm - -.macro update1 m - update - pxor \m, STATE4 -.endm - -.macro update2 m - update - pxor \m, STATE3 -.endm - -.macro update3 m - update - pxor \m, STATE2 -.endm - -.macro update4 m - update - pxor \m, STATE1 -.endm - -.macro update5 m - update - pxor \m, STATE0 -.endm - -.macro state_load - movdqu 0x00(STATEP), STATE0 - movdqu 0x10(STATEP), STATE1 - movdqu 0x20(STATEP), STATE2 - movdqu 0x30(STATEP), STATE3 - movdqu 0x40(STATEP), STATE4 - movdqu 0x50(STATEP), STATE5 -.endm - -.macro state_store s0 s1 s2 s3 s4 s5 - movdqu \s5, 0x00(STATEP) - movdqu \s0, 0x10(STATEP) - movdqu \s1, 0x20(STATEP) - movdqu \s2, 0x30(STATEP) - movdqu \s3, 0x40(STATEP) - movdqu \s4, 0x50(STATEP) -.endm - -.macro state_store0 - state_store STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 -.endm - -.macro state_store1 - state_store STATE5 STATE0 STATE1 STATE2 STATE3 STATE4 -.endm - -.macro state_store2 - state_store STATE4 STATE5 STATE0 STATE1 STATE2 STATE3 -.endm - -.macro state_store3 - state_store STATE3 STATE4 STATE5 STATE0 STATE1 STATE2 -.endm - -.macro state_store4 - state_store STATE2 STATE3 STATE4 STATE5 STATE0 STATE1 -.endm - -.macro state_store5 - state_store STATE1 STATE2 STATE3 STATE4 STATE5 STATE0 -.endm - -/* - * void crypto_aegis256_aesni_init(void *state, const void *key, const void *iv); - */ -ENTRY(crypto_aegis256_aesni_init) - FRAME_BEGIN - - /* load key: */ - movdqa 0x00(%rsi), MSG - movdqa 0x10(%rsi), T1 - movdqa MSG, STATE4 - movdqa T1, STATE5 - - /* load IV: */ - movdqu 0x00(%rdx), T2 - movdqu 0x10(%rdx), T3 - pxor MSG, T2 - pxor T1, T3 - movdqa T2, STATE0 - movdqa T3, STATE1 - - /* load the constants: */ - movdqa .Laegis256_const_0, STATE3 - movdqa .Laegis256_const_1, STATE2 - pxor STATE3, STATE4 - pxor STATE2, STATE5 - - /* update 10 times with IV and KEY: */ - update0 MSG - update1 T1 - update2 T2 - update3 T3 - update4 MSG - update5 T1 - update0 T2 - update1 T3 - update2 MSG - update3 T1 - update4 T2 - update5 T3 - update0 MSG - update1 T1 - update2 T2 - update3 T3 - - state_store3 - - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_init) - -.macro ad_block a i - movdq\a (\i * 0x10)(SRC), MSG - update\i MSG - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_\i -.endm - -/* - * void crypto_aegis256_aesni_ad(void *state, unsigned int length, - * const void *data); - */ -ENTRY(crypto_aegis256_aesni_ad) - FRAME_BEGIN - - cmp $0x10, LEN - jb .Lad_out - - state_load - - mov SRC, %r8 - and $0xf, %r8 - jnz .Lad_u_loop - -.align 8 -.Lad_a_loop: - ad_block a 0 - ad_block a 1 - ad_block a 2 - ad_block a 3 - ad_block a 4 - ad_block a 5 - - add $0x60, SRC - jmp .Lad_a_loop - -.align 8 -.Lad_u_loop: - ad_block u 0 - ad_block u 1 - ad_block u 2 - ad_block u 3 - ad_block u 4 - ad_block u 5 - - add $0x60, SRC - jmp .Lad_u_loop - -.Lad_out_0: - state_store0 - FRAME_END - ret - -.Lad_out_1: - state_store1 - FRAME_END - ret - -.Lad_out_2: - state_store2 - FRAME_END - ret - -.Lad_out_3: - state_store3 - FRAME_END - ret - -.Lad_out_4: - state_store4 - FRAME_END - ret - -.Lad_out_5: - state_store5 - FRAME_END - ret - -.Lad_out: - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_ad) - -.macro crypt m s0 s1 s2 s3 s4 s5 - pxor \s1, \m - pxor \s4, \m - pxor \s5, \m - movdqa \s2, T3 - pand \s3, T3 - pxor T3, \m -.endm - -.macro crypt0 m - crypt \m STATE0 STATE1 STATE2 STATE3 STATE4 STATE5 -.endm - -.macro crypt1 m - crypt \m STATE5 STATE0 STATE1 STATE2 STATE3 STATE4 -.endm - -.macro crypt2 m - crypt \m STATE4 STATE5 STATE0 STATE1 STATE2 STATE3 -.endm - -.macro crypt3 m - crypt \m STATE3 STATE4 STATE5 STATE0 STATE1 STATE2 -.endm - -.macro crypt4 m - crypt \m STATE2 STATE3 STATE4 STATE5 STATE0 STATE1 -.endm - -.macro crypt5 m - crypt \m STATE1 STATE2 STATE3 STATE4 STATE5 STATE0 -.endm - -.macro encrypt_block a i - movdq\a (\i * 0x10)(SRC), MSG - movdqa MSG, T0 - crypt\i T0 - movdq\a T0, (\i * 0x10)(DST) - - update\i MSG - - sub $0x10, LEN - cmp $0x10, LEN - jl .Lenc_out_\i -.endm - -.macro decrypt_block a i - movdq\a (\i * 0x10)(SRC), MSG - crypt\i MSG - movdq\a MSG, (\i * 0x10)(DST) - - update\i MSG - - sub $0x10, LEN - cmp $0x10, LEN - jl .Ldec_out_\i -.endm - -/* - * void crypto_aegis256_aesni_enc(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis256_aesni_enc) - FRAME_BEGIN - - cmp $0x10, LEN - jb .Lenc_out - - state_load - - mov SRC, %r8 - or DST, %r8 - and $0xf, %r8 - jnz .Lenc_u_loop - -.align 8 -.Lenc_a_loop: - encrypt_block a 0 - encrypt_block a 1 - encrypt_block a 2 - encrypt_block a 3 - encrypt_block a 4 - encrypt_block a 5 - - add $0x60, SRC - add $0x60, DST - jmp .Lenc_a_loop - -.align 8 -.Lenc_u_loop: - encrypt_block u 0 - encrypt_block u 1 - encrypt_block u 2 - encrypt_block u 3 - encrypt_block u 4 - encrypt_block u 5 - - add $0x60, SRC - add $0x60, DST - jmp .Lenc_u_loop - -.Lenc_out_0: - state_store0 - FRAME_END - ret - -.Lenc_out_1: - state_store1 - FRAME_END - ret - -.Lenc_out_2: - state_store2 - FRAME_END - ret - -.Lenc_out_3: - state_store3 - FRAME_END - ret - -.Lenc_out_4: - state_store4 - FRAME_END - ret - -.Lenc_out_5: - state_store5 - FRAME_END - ret - -.Lenc_out: - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_enc) - -/* - * void crypto_aegis256_aesni_enc_tail(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis256_aesni_enc_tail) - FRAME_BEGIN - - state_load - - /* encrypt message: */ - call __load_partial - - movdqa MSG, T0 - crypt0 T0 - - call __store_partial - - update0 MSG - - state_store0 - - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_enc_tail) - -/* - * void crypto_aegis256_aesni_dec(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis256_aesni_dec) - FRAME_BEGIN - - cmp $0x10, LEN - jb .Ldec_out - - state_load - - mov SRC, %r8 - or DST, %r8 - and $0xF, %r8 - jnz .Ldec_u_loop - -.align 8 -.Ldec_a_loop: - decrypt_block a 0 - decrypt_block a 1 - decrypt_block a 2 - decrypt_block a 3 - decrypt_block a 4 - decrypt_block a 5 - - add $0x60, SRC - add $0x60, DST - jmp .Ldec_a_loop - -.align 8 -.Ldec_u_loop: - decrypt_block u 0 - decrypt_block u 1 - decrypt_block u 2 - decrypt_block u 3 - decrypt_block u 4 - decrypt_block u 5 - - add $0x60, SRC - add $0x60, DST - jmp .Ldec_u_loop - -.Ldec_out_0: - state_store0 - FRAME_END - ret - -.Ldec_out_1: - state_store1 - FRAME_END - ret - -.Ldec_out_2: - state_store2 - FRAME_END - ret - -.Ldec_out_3: - state_store3 - FRAME_END - ret - -.Ldec_out_4: - state_store4 - FRAME_END - ret - -.Ldec_out_5: - state_store5 - FRAME_END - ret - -.Ldec_out: - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_dec) - -/* - * void crypto_aegis256_aesni_dec_tail(void *state, unsigned int length, - * const void *src, void *dst); - */ -ENTRY(crypto_aegis256_aesni_dec_tail) - FRAME_BEGIN - - state_load - - /* decrypt message: */ - call __load_partial - - crypt0 MSG - - movdqa MSG, T0 - call __store_partial - - /* mask with byte count: */ - movq LEN, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - movdqa .Laegis256_counter, T1 - pcmpgtb T1, T0 - pand T0, MSG - - update0 MSG - - state_store0 - - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_dec_tail) - -/* - * void crypto_aegis256_aesni_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); - */ -ENTRY(crypto_aegis256_aesni_final) - FRAME_BEGIN - - state_load - - /* prepare length block: */ - movq %rdx, MSG - movq %rcx, T0 - pslldq $8, T0 - pxor T0, MSG - psllq $3, MSG /* multiply by 8 (to get bit count) */ - - pxor STATE3, MSG - - /* update state: */ - update0 MSG - update1 MSG - update2 MSG - update3 MSG - update4 MSG - update5 MSG - update0 MSG - - /* xor tag: */ - movdqu (%rsi), MSG - - pxor STATE0, MSG - pxor STATE1, MSG - pxor STATE2, MSG - pxor STATE3, MSG - pxor STATE4, MSG - pxor STATE5, MSG - - movdqu MSG, (%rsi) - - FRAME_END - ret -ENDPROC(crypto_aegis256_aesni_final) diff --git a/arch/x86/crypto/aegis256-aesni-glue.c b/arch/x86/crypto/aegis256-aesni-glue.c deleted file mode 100644 index f84da27171d3..000000000000 --- a/arch/x86/crypto/aegis256-aesni-glue.c +++ /dev/null @@ -1,293 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The AEGIS-256 Authenticated-Encryption Algorithm - * Glue for AES-NI + SSE2 implementation - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define AEGIS256_BLOCK_ALIGN 16 -#define AEGIS256_BLOCK_SIZE 16 -#define AEGIS256_NONCE_SIZE 32 -#define AEGIS256_STATE_BLOCKS 6 -#define AEGIS256_KEY_SIZE 32 -#define AEGIS256_MIN_AUTH_SIZE 8 -#define AEGIS256_MAX_AUTH_SIZE 16 - -asmlinkage void crypto_aegis256_aesni_init(void *state, void *key, void *iv); - -asmlinkage void crypto_aegis256_aesni_ad( - void *state, unsigned int length, const void *data); - -asmlinkage void crypto_aegis256_aesni_enc( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis256_aesni_dec( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis256_aesni_enc_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis256_aesni_dec_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis256_aesni_final( - void *state, void *tag_xor, unsigned int cryptlen, - unsigned int assoclen); - -struct aegis_block { - u8 bytes[AEGIS256_BLOCK_SIZE] __aligned(AEGIS256_BLOCK_ALIGN); -}; - -struct aegis_state { - struct aegis_block blocks[AEGIS256_STATE_BLOCKS]; -}; - -struct aegis_ctx { - struct aegis_block key[AEGIS256_KEY_SIZE / AEGIS256_BLOCK_SIZE]; -}; - -struct aegis_crypt_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_blocks)(void *state, unsigned int length, const void *src, - void *dst); - void (*crypt_tail)(void *state, unsigned int length, const void *src, - void *dst); -}; - -static void crypto_aegis256_aesni_process_ad( - struct aegis_state *state, struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - struct aegis_block buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= AEGIS256_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = AEGIS256_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - crypto_aegis256_aesni_ad(state, - AEGIS256_BLOCK_SIZE, - buf.bytes); - pos = 0; - left -= fill; - src += fill; - } - - crypto_aegis256_aesni_ad(state, left, src); - - src += left & ~(AEGIS256_BLOCK_SIZE - 1); - left &= AEGIS256_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - pos += left; - assoclen -= size; - - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, AEGIS256_BLOCK_SIZE - pos); - crypto_aegis256_aesni_ad(state, AEGIS256_BLOCK_SIZE, buf.bytes); - } -} - -static void crypto_aegis256_aesni_process_crypt( - struct aegis_state *state, struct skcipher_walk *walk, - const struct aegis_crypt_ops *ops) -{ - while (walk->nbytes >= AEGIS256_BLOCK_SIZE) { - ops->crypt_blocks(state, - round_down(walk->nbytes, AEGIS256_BLOCK_SIZE), - walk->src.virt.addr, walk->dst.virt.addr); - skcipher_walk_done(walk, walk->nbytes % AEGIS256_BLOCK_SIZE); - } - - if (walk->nbytes) { - ops->crypt_tail(state, walk->nbytes, walk->src.virt.addr, - walk->dst.virt.addr); - skcipher_walk_done(walk, 0); - } -} - -static struct aegis_ctx *crypto_aegis256_aesni_ctx(struct crypto_aead *aead) -{ - u8 *ctx = crypto_aead_ctx(aead); - ctx = PTR_ALIGN(ctx, __alignof__(struct aegis_ctx)); - return (void *)ctx; -} - -static int crypto_aegis256_aesni_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct aegis_ctx *ctx = crypto_aegis256_aesni_ctx(aead); - - if (keylen != AEGIS256_KEY_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - memcpy(ctx->key, key, AEGIS256_KEY_SIZE); - - return 0; -} - -static int crypto_aegis256_aesni_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - if (authsize > AEGIS256_MAX_AUTH_SIZE) - return -EINVAL; - if (authsize < AEGIS256_MIN_AUTH_SIZE) - return -EINVAL; - return 0; -} - -static void crypto_aegis256_aesni_crypt(struct aead_request *req, - struct aegis_block *tag_xor, - unsigned int cryptlen, - const struct aegis_crypt_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_ctx *ctx = crypto_aegis256_aesni_ctx(tfm); - struct skcipher_walk walk; - struct aegis_state state; - - ops->skcipher_walk_init(&walk, req, true); - - kernel_fpu_begin(); - - crypto_aegis256_aesni_init(&state, ctx->key, req->iv); - crypto_aegis256_aesni_process_ad(&state, req->src, req->assoclen); - crypto_aegis256_aesni_process_crypt(&state, &walk, ops); - crypto_aegis256_aesni_final(&state, tag_xor, req->assoclen, cryptlen); - - kernel_fpu_end(); -} - -static int crypto_aegis256_aesni_encrypt(struct aead_request *req) -{ - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_blocks = crypto_aegis256_aesni_enc, - .crypt_tail = crypto_aegis256_aesni_enc_tail, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_aegis256_aesni_crypt(req, &tag, cryptlen, &OPS); - - scatterwalk_map_and_copy(tag.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); - return 0; -} - -static int crypto_aegis256_aesni_decrypt(struct aead_request *req) -{ - static const struct aegis_block zeros = {}; - - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_blocks = crypto_aegis256_aesni_dec, - .crypt_tail = crypto_aegis256_aesni_dec_tail, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - - crypto_aegis256_aesni_crypt(req, &tag, cryptlen, &OPS); - - return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0; -} - -static int crypto_aegis256_aesni_init_tfm(struct crypto_aead *aead) -{ - return 0; -} - -static void crypto_aegis256_aesni_exit_tfm(struct crypto_aead *aead) -{ -} - -static struct aead_alg crypto_aegis256_aesni_alg = { - .setkey = crypto_aegis256_aesni_setkey, - .setauthsize = crypto_aegis256_aesni_setauthsize, - .encrypt = crypto_aegis256_aesni_encrypt, - .decrypt = crypto_aegis256_aesni_decrypt, - .init = crypto_aegis256_aesni_init_tfm, - .exit = crypto_aegis256_aesni_exit_tfm, - - .ivsize = AEGIS256_NONCE_SIZE, - .maxauthsize = AEGIS256_MAX_AUTH_SIZE, - .chunksize = AEGIS256_BLOCK_SIZE, - - .base = { - .cra_flags = CRYPTO_ALG_INTERNAL, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct aegis_ctx) + - __alignof__(struct aegis_ctx), - .cra_alignmask = 0, - .cra_priority = 400, - - .cra_name = "__aegis256", - .cra_driver_name = "__aegis256-aesni", - - .cra_module = THIS_MODULE, - } -}; - -static struct simd_aead_alg *simd_alg; - -static int __init crypto_aegis256_aesni_module_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_XMM2) || - !boot_cpu_has(X86_FEATURE_AES) || - !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) - return -ENODEV; - - return simd_register_aeads_compat(&crypto_aegis256_aesni_alg, 1, - &simd_alg); -} - -static void __exit crypto_aegis256_aesni_module_exit(void) -{ - simd_unregister_aeads(&crypto_aegis256_aesni_alg, 1, &simd_alg); -} - -module_init(crypto_aegis256_aesni_module_init); -module_exit(crypto_aegis256_aesni_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("AEGIS-256 AEAD algorithm -- AESNI+SSE2 implementation"); -MODULE_ALIAS_CRYPTO("aegis256"); -MODULE_ALIAS_CRYPTO("aegis256-aesni"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 160dc1a9c7ec..559494bbc0db 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -306,20 +306,6 @@ config CRYPTO_AEGIS128 help Support for the AEGIS-128 dedicated AEAD algorithm. -config CRYPTO_AEGIS128L - tristate "AEGIS-128L AEAD algorithm" - select CRYPTO_AEAD - select CRYPTO_AES # for AES S-box tables - help - Support for the AEGIS-128L dedicated AEAD algorithm. - -config CRYPTO_AEGIS256 - tristate "AEGIS-256 AEAD algorithm" - select CRYPTO_AEAD - select CRYPTO_AES # for AES S-box tables - help - Support for the AEGIS-256 dedicated AEAD algorithm. - config CRYPTO_AEGIS128_AESNI_SSE2 tristate "AEGIS-128 AEAD algorithm (x86_64 AESNI+SSE2 implementation)" depends on X86 && 64BIT @@ -328,22 +314,6 @@ config CRYPTO_AEGIS128_AESNI_SSE2 help AESNI+SSE2 implementation of the AEGIS-128 dedicated AEAD algorithm. -config CRYPTO_AEGIS128L_AESNI_SSE2 - tristate "AEGIS-128L AEAD algorithm (x86_64 AESNI+SSE2 implementation)" - depends on X86 && 64BIT - select CRYPTO_AEAD - select CRYPTO_SIMD - help - AESNI+SSE2 implementation of the AEGIS-128L dedicated AEAD algorithm. - -config CRYPTO_AEGIS256_AESNI_SSE2 - tristate "AEGIS-256 AEAD algorithm (x86_64 AESNI+SSE2 implementation)" - depends on X86 && 64BIT - select CRYPTO_AEAD - select CRYPTO_SIMD - help - AESNI+SSE2 implementation of the AEGIS-256 dedicated AEAD algorithm. - config CRYPTO_SEQIV tristate "Sequence Number IV Generator" select CRYPTO_AEAD diff --git a/crypto/Makefile b/crypto/Makefile index 4bc1951d3787..93375e124ff7 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -90,8 +90,6 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o -obj-$(CONFIG_CRYPTO_AEGIS128L) += aegis128l.o -obj-$(CONFIG_CRYPTO_AEGIS256) += aegis256.o obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o obj-$(CONFIG_CRYPTO_DES) += des_generic.o diff --git a/crypto/aegis128l.c b/crypto/aegis128l.c deleted file mode 100644 index 9bca3d619a22..000000000000 --- a/crypto/aegis128l.c +++ /dev/null @@ -1,522 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The AEGIS-128L Authenticated-Encryption Algorithm - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aegis.h" - -#define AEGIS128L_CHUNK_BLOCKS 2 -#define AEGIS128L_CHUNK_SIZE (AEGIS128L_CHUNK_BLOCKS * AEGIS_BLOCK_SIZE) -#define AEGIS128L_NONCE_SIZE 16 -#define AEGIS128L_STATE_BLOCKS 8 -#define AEGIS128L_KEY_SIZE 16 -#define AEGIS128L_MIN_AUTH_SIZE 8 -#define AEGIS128L_MAX_AUTH_SIZE 16 - -union aegis_chunk { - union aegis_block blocks[AEGIS128L_CHUNK_BLOCKS]; - u8 bytes[AEGIS128L_CHUNK_SIZE]; -}; - -struct aegis_state { - union aegis_block blocks[AEGIS128L_STATE_BLOCKS]; -}; - -struct aegis_ctx { - union aegis_block key; -}; - -struct aegis128l_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_chunk)(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size); -}; - -static void crypto_aegis128l_update(struct aegis_state *state) -{ - union aegis_block tmp; - unsigned int i; - - tmp = state->blocks[AEGIS128L_STATE_BLOCKS - 1]; - for (i = AEGIS128L_STATE_BLOCKS - 1; i > 0; i--) - crypto_aegis_aesenc(&state->blocks[i], &state->blocks[i - 1], - &state->blocks[i]); - crypto_aegis_aesenc(&state->blocks[0], &tmp, &state->blocks[0]); -} - -static void crypto_aegis128l_update_a(struct aegis_state *state, - const union aegis_chunk *msg) -{ - crypto_aegis128l_update(state); - crypto_aegis_block_xor(&state->blocks[0], &msg->blocks[0]); - crypto_aegis_block_xor(&state->blocks[4], &msg->blocks[1]); -} - -static void crypto_aegis128l_update_u(struct aegis_state *state, - const void *msg) -{ - crypto_aegis128l_update(state); - crypto_xor(state->blocks[0].bytes, msg + 0 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - crypto_xor(state->blocks[4].bytes, msg + 1 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); -} - -static void crypto_aegis128l_init(struct aegis_state *state, - const union aegis_block *key, - const u8 *iv) -{ - union aegis_block key_iv; - union aegis_chunk chunk; - unsigned int i; - - memcpy(chunk.blocks[0].bytes, iv, AEGIS_BLOCK_SIZE); - chunk.blocks[1] = *key; - - key_iv = *key; - crypto_aegis_block_xor(&key_iv, &chunk.blocks[0]); - - state->blocks[0] = key_iv; - state->blocks[1] = crypto_aegis_const[1]; - state->blocks[2] = crypto_aegis_const[0]; - state->blocks[3] = crypto_aegis_const[1]; - state->blocks[4] = key_iv; - state->blocks[5] = *key; - state->blocks[6] = *key; - state->blocks[7] = *key; - - crypto_aegis_block_xor(&state->blocks[5], &crypto_aegis_const[0]); - crypto_aegis_block_xor(&state->blocks[6], &crypto_aegis_const[1]); - crypto_aegis_block_xor(&state->blocks[7], &crypto_aegis_const[0]); - - for (i = 0; i < 10; i++) { - crypto_aegis128l_update_a(state, &chunk); - } -} - -static void crypto_aegis128l_ad(struct aegis_state *state, - const u8 *src, unsigned int size) -{ - if (AEGIS_ALIGNED(src)) { - const union aegis_chunk *src_chunk = - (const union aegis_chunk *)src; - - while (size >= AEGIS128L_CHUNK_SIZE) { - crypto_aegis128l_update_a(state, src_chunk); - - size -= AEGIS128L_CHUNK_SIZE; - src_chunk += 1; - } - } else { - while (size >= AEGIS128L_CHUNK_SIZE) { - crypto_aegis128l_update_u(state, src); - - size -= AEGIS128L_CHUNK_SIZE; - src += AEGIS128L_CHUNK_SIZE; - } - } -} - -static void crypto_aegis128l_encrypt_chunk(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - union aegis_chunk tmp; - union aegis_block *tmp0 = &tmp.blocks[0]; - union aegis_block *tmp1 = &tmp.blocks[1]; - - if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) { - while (size >= AEGIS128L_CHUNK_SIZE) { - union aegis_chunk *dst_blk = - (union aegis_chunk *)dst; - const union aegis_chunk *src_blk = - (const union aegis_chunk *)src; - - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - crypto_aegis_block_xor(tmp0, &src_blk->blocks[0]); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - crypto_aegis_block_xor(tmp1, &src_blk->blocks[1]); - - crypto_aegis128l_update_a(state, src_blk); - - *dst_blk = tmp; - - size -= AEGIS128L_CHUNK_SIZE; - src += AEGIS128L_CHUNK_SIZE; - dst += AEGIS128L_CHUNK_SIZE; - } - } else { - while (size >= AEGIS128L_CHUNK_SIZE) { - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - crypto_xor(tmp0->bytes, src + 0 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - crypto_xor(tmp1->bytes, src + 1 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - - crypto_aegis128l_update_u(state, src); - - memcpy(dst, tmp.bytes, AEGIS128L_CHUNK_SIZE); - - size -= AEGIS128L_CHUNK_SIZE; - src += AEGIS128L_CHUNK_SIZE; - dst += AEGIS128L_CHUNK_SIZE; - } - } - - if (size > 0) { - union aegis_chunk msg = {}; - memcpy(msg.bytes, src, size); - - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - - crypto_aegis128l_update_a(state, &msg); - - crypto_aegis_block_xor(&msg.blocks[0], tmp0); - crypto_aegis_block_xor(&msg.blocks[1], tmp1); - - memcpy(dst, msg.bytes, size); - } -} - -static void crypto_aegis128l_decrypt_chunk(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - union aegis_chunk tmp; - union aegis_block *tmp0 = &tmp.blocks[0]; - union aegis_block *tmp1 = &tmp.blocks[1]; - - if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) { - while (size >= AEGIS128L_CHUNK_SIZE) { - union aegis_chunk *dst_blk = - (union aegis_chunk *)dst; - const union aegis_chunk *src_blk = - (const union aegis_chunk *)src; - - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - crypto_aegis_block_xor(tmp0, &src_blk->blocks[0]); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - crypto_aegis_block_xor(tmp1, &src_blk->blocks[1]); - - crypto_aegis128l_update_a(state, &tmp); - - *dst_blk = tmp; - - size -= AEGIS128L_CHUNK_SIZE; - src += AEGIS128L_CHUNK_SIZE; - dst += AEGIS128L_CHUNK_SIZE; - } - } else { - while (size >= AEGIS128L_CHUNK_SIZE) { - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - crypto_xor(tmp0->bytes, src + 0 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - crypto_xor(tmp1->bytes, src + 1 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - - crypto_aegis128l_update_a(state, &tmp); - - memcpy(dst, tmp.bytes, AEGIS128L_CHUNK_SIZE); - - size -= AEGIS128L_CHUNK_SIZE; - src += AEGIS128L_CHUNK_SIZE; - dst += AEGIS128L_CHUNK_SIZE; - } - } - - if (size > 0) { - union aegis_chunk msg = {}; - memcpy(msg.bytes, src, size); - - *tmp0 = state->blocks[2]; - crypto_aegis_block_and(tmp0, &state->blocks[3]); - crypto_aegis_block_xor(tmp0, &state->blocks[6]); - crypto_aegis_block_xor(tmp0, &state->blocks[1]); - crypto_aegis_block_xor(&msg.blocks[0], tmp0); - - *tmp1 = state->blocks[6]; - crypto_aegis_block_and(tmp1, &state->blocks[7]); - crypto_aegis_block_xor(tmp1, &state->blocks[5]); - crypto_aegis_block_xor(tmp1, &state->blocks[2]); - crypto_aegis_block_xor(&msg.blocks[1], tmp1); - - memset(msg.bytes + size, 0, AEGIS128L_CHUNK_SIZE - size); - - crypto_aegis128l_update_a(state, &msg); - - memcpy(dst, msg.bytes, size); - } -} - -static void crypto_aegis128l_process_ad(struct aegis_state *state, - struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - union aegis_chunk buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= AEGIS128L_CHUNK_SIZE) { - if (pos > 0) { - unsigned int fill = AEGIS128L_CHUNK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - crypto_aegis128l_update_a(state, &buf); - pos = 0; - left -= fill; - src += fill; - } - - crypto_aegis128l_ad(state, src, left); - src += left & ~(AEGIS128L_CHUNK_SIZE - 1); - left &= AEGIS128L_CHUNK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, AEGIS128L_CHUNK_SIZE - pos); - crypto_aegis128l_update_a(state, &buf); - } -} - -static void crypto_aegis128l_process_crypt(struct aegis_state *state, - struct aead_request *req, - const struct aegis128l_ops *ops) -{ - struct skcipher_walk walk; - - ops->skcipher_walk_init(&walk, req, false); - - while (walk.nbytes) { - unsigned int nbytes = walk.nbytes; - - if (nbytes < walk.total) - nbytes = round_down(nbytes, walk.stride); - - ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr, - nbytes); - - skcipher_walk_done(&walk, walk.nbytes - nbytes); - } -} - -static void crypto_aegis128l_final(struct aegis_state *state, - union aegis_block *tag_xor, - u64 assoclen, u64 cryptlen) -{ - u64 assocbits = assoclen * 8; - u64 cryptbits = cryptlen * 8; - - union aegis_chunk tmp; - unsigned int i; - - tmp.blocks[0].words64[0] = cpu_to_le64(assocbits); - tmp.blocks[0].words64[1] = cpu_to_le64(cryptbits); - - crypto_aegis_block_xor(&tmp.blocks[0], &state->blocks[2]); - - tmp.blocks[1] = tmp.blocks[0]; - for (i = 0; i < 7; i++) - crypto_aegis128l_update_a(state, &tmp); - - for (i = 0; i < 7; i++) - crypto_aegis_block_xor(tag_xor, &state->blocks[i]); -} - -static int crypto_aegis128l_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct aegis_ctx *ctx = crypto_aead_ctx(aead); - - if (keylen != AEGIS128L_KEY_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - memcpy(ctx->key.bytes, key, AEGIS128L_KEY_SIZE); - return 0; -} - -static int crypto_aegis128l_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - if (authsize > AEGIS128L_MAX_AUTH_SIZE) - return -EINVAL; - if (authsize < AEGIS128L_MIN_AUTH_SIZE) - return -EINVAL; - return 0; -} - -static void crypto_aegis128l_crypt(struct aead_request *req, - union aegis_block *tag_xor, - unsigned int cryptlen, - const struct aegis128l_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_ctx *ctx = crypto_aead_ctx(tfm); - struct aegis_state state; - - crypto_aegis128l_init(&state, &ctx->key, req->iv); - crypto_aegis128l_process_ad(&state, req->src, req->assoclen); - crypto_aegis128l_process_crypt(&state, req, ops); - crypto_aegis128l_final(&state, tag_xor, req->assoclen, cryptlen); -} - -static int crypto_aegis128l_encrypt(struct aead_request *req) -{ - static const struct aegis128l_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_chunk = crypto_aegis128l_encrypt_chunk, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union aegis_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_aegis128l_crypt(req, &tag, cryptlen, &ops); - - scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, - authsize, 1); - return 0; -} - -static int crypto_aegis128l_decrypt(struct aead_request *req) -{ - static const struct aegis128l_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_chunk = crypto_aegis128l_decrypt_chunk, - }; - static const u8 zeros[AEGIS128L_MAX_AUTH_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union aegis_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, - authsize, 0); - - crypto_aegis128l_crypt(req, &tag, cryptlen, &ops); - - return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; -} - -static int crypto_aegis128l_init_tfm(struct crypto_aead *tfm) -{ - return 0; -} - -static void crypto_aegis128l_exit_tfm(struct crypto_aead *tfm) -{ -} - -static struct aead_alg crypto_aegis128l_alg = { - .setkey = crypto_aegis128l_setkey, - .setauthsize = crypto_aegis128l_setauthsize, - .encrypt = crypto_aegis128l_encrypt, - .decrypt = crypto_aegis128l_decrypt, - .init = crypto_aegis128l_init_tfm, - .exit = crypto_aegis128l_exit_tfm, - - .ivsize = AEGIS128L_NONCE_SIZE, - .maxauthsize = AEGIS128L_MAX_AUTH_SIZE, - .chunksize = AEGIS128L_CHUNK_SIZE, - - .base = { - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct aegis_ctx), - .cra_alignmask = 0, - - .cra_priority = 100, - - .cra_name = "aegis128l", - .cra_driver_name = "aegis128l-generic", - - .cra_module = THIS_MODULE, - } -}; - -static int __init crypto_aegis128l_module_init(void) -{ - return crypto_register_aead(&crypto_aegis128l_alg); -} - -static void __exit crypto_aegis128l_module_exit(void) -{ - crypto_unregister_aead(&crypto_aegis128l_alg); -} - -subsys_initcall(crypto_aegis128l_module_init); -module_exit(crypto_aegis128l_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("AEGIS-128L AEAD algorithm"); -MODULE_ALIAS_CRYPTO("aegis128l"); -MODULE_ALIAS_CRYPTO("aegis128l-generic"); diff --git a/crypto/aegis256.c b/crypto/aegis256.c deleted file mode 100644 index b47fd39595ad..000000000000 --- a/crypto/aegis256.c +++ /dev/null @@ -1,473 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * The AEGIS-256 Authenticated-Encryption Algorithm - * - * Copyright (c) 2017-2018 Ondrej Mosnacek - * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aegis.h" - -#define AEGIS256_NONCE_SIZE 32 -#define AEGIS256_STATE_BLOCKS 6 -#define AEGIS256_KEY_SIZE 32 -#define AEGIS256_MIN_AUTH_SIZE 8 -#define AEGIS256_MAX_AUTH_SIZE 16 - -struct aegis_state { - union aegis_block blocks[AEGIS256_STATE_BLOCKS]; -}; - -struct aegis_ctx { - union aegis_block key[AEGIS256_KEY_SIZE / AEGIS_BLOCK_SIZE]; -}; - -struct aegis256_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); - - void (*crypt_chunk)(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size); -}; - -static void crypto_aegis256_update(struct aegis_state *state) -{ - union aegis_block tmp; - unsigned int i; - - tmp = state->blocks[AEGIS256_STATE_BLOCKS - 1]; - for (i = AEGIS256_STATE_BLOCKS - 1; i > 0; i--) - crypto_aegis_aesenc(&state->blocks[i], &state->blocks[i - 1], - &state->blocks[i]); - crypto_aegis_aesenc(&state->blocks[0], &tmp, &state->blocks[0]); -} - -static void crypto_aegis256_update_a(struct aegis_state *state, - const union aegis_block *msg) -{ - crypto_aegis256_update(state); - crypto_aegis_block_xor(&state->blocks[0], msg); -} - -static void crypto_aegis256_update_u(struct aegis_state *state, const void *msg) -{ - crypto_aegis256_update(state); - crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE); -} - -static void crypto_aegis256_init(struct aegis_state *state, - const union aegis_block *key, - const u8 *iv) -{ - union aegis_block key_iv[2]; - unsigned int i; - - key_iv[0] = key[0]; - key_iv[1] = key[1]; - crypto_xor(key_iv[0].bytes, iv + 0 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - crypto_xor(key_iv[1].bytes, iv + 1 * AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - - state->blocks[0] = key_iv[0]; - state->blocks[1] = key_iv[1]; - state->blocks[2] = crypto_aegis_const[1]; - state->blocks[3] = crypto_aegis_const[0]; - state->blocks[4] = key[0]; - state->blocks[5] = key[1]; - - crypto_aegis_block_xor(&state->blocks[4], &crypto_aegis_const[0]); - crypto_aegis_block_xor(&state->blocks[5], &crypto_aegis_const[1]); - - for (i = 0; i < 4; i++) { - crypto_aegis256_update_a(state, &key[0]); - crypto_aegis256_update_a(state, &key[1]); - crypto_aegis256_update_a(state, &key_iv[0]); - crypto_aegis256_update_a(state, &key_iv[1]); - } -} - -static void crypto_aegis256_ad(struct aegis_state *state, - const u8 *src, unsigned int size) -{ - if (AEGIS_ALIGNED(src)) { - const union aegis_block *src_blk = - (const union aegis_block *)src; - - while (size >= AEGIS_BLOCK_SIZE) { - crypto_aegis256_update_a(state, src_blk); - - size -= AEGIS_BLOCK_SIZE; - src_blk++; - } - } else { - while (size >= AEGIS_BLOCK_SIZE) { - crypto_aegis256_update_u(state, src); - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - } - } -} - -static void crypto_aegis256_encrypt_chunk(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - union aegis_block tmp; - - if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) { - while (size >= AEGIS_BLOCK_SIZE) { - union aegis_block *dst_blk = - (union aegis_block *)dst; - const union aegis_block *src_blk = - (const union aegis_block *)src; - - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - crypto_aegis_block_xor(&tmp, src_blk); - - crypto_aegis256_update_a(state, src_blk); - - *dst_blk = tmp; - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - } else { - while (size >= AEGIS_BLOCK_SIZE) { - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - crypto_xor(tmp.bytes, src, AEGIS_BLOCK_SIZE); - - crypto_aegis256_update_u(state, src); - - memcpy(dst, tmp.bytes, AEGIS_BLOCK_SIZE); - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - } - - if (size > 0) { - union aegis_block msg = {}; - memcpy(msg.bytes, src, size); - - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - - crypto_aegis256_update_a(state, &msg); - - crypto_aegis_block_xor(&msg, &tmp); - - memcpy(dst, msg.bytes, size); - } -} - -static void crypto_aegis256_decrypt_chunk(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size) -{ - union aegis_block tmp; - - if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) { - while (size >= AEGIS_BLOCK_SIZE) { - union aegis_block *dst_blk = - (union aegis_block *)dst; - const union aegis_block *src_blk = - (const union aegis_block *)src; - - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - crypto_aegis_block_xor(&tmp, src_blk); - - crypto_aegis256_update_a(state, &tmp); - - *dst_blk = tmp; - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - } else { - while (size >= AEGIS_BLOCK_SIZE) { - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - crypto_xor(tmp.bytes, src, AEGIS_BLOCK_SIZE); - - crypto_aegis256_update_a(state, &tmp); - - memcpy(dst, tmp.bytes, AEGIS_BLOCK_SIZE); - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - } - - if (size > 0) { - union aegis_block msg = {}; - memcpy(msg.bytes, src, size); - - tmp = state->blocks[2]; - crypto_aegis_block_and(&tmp, &state->blocks[3]); - crypto_aegis_block_xor(&tmp, &state->blocks[5]); - crypto_aegis_block_xor(&tmp, &state->blocks[4]); - crypto_aegis_block_xor(&tmp, &state->blocks[1]); - crypto_aegis_block_xor(&msg, &tmp); - - memset(msg.bytes + size, 0, AEGIS_BLOCK_SIZE - size); - - crypto_aegis256_update_a(state, &msg); - - memcpy(dst, msg.bytes, size); - } -} - -static void crypto_aegis256_process_ad(struct aegis_state *state, - struct scatterlist *sg_src, - unsigned int assoclen) -{ - struct scatter_walk walk; - union aegis_block buf; - unsigned int pos = 0; - - scatterwalk_start(&walk, sg_src); - while (assoclen != 0) { - unsigned int size = scatterwalk_clamp(&walk, assoclen); - unsigned int left = size; - void *mapped = scatterwalk_map(&walk); - const u8 *src = (const u8 *)mapped; - - if (pos + size >= AEGIS_BLOCK_SIZE) { - if (pos > 0) { - unsigned int fill = AEGIS_BLOCK_SIZE - pos; - memcpy(buf.bytes + pos, src, fill); - crypto_aegis256_update_a(state, &buf); - pos = 0; - left -= fill; - src += fill; - } - - crypto_aegis256_ad(state, src, left); - src += left & ~(AEGIS_BLOCK_SIZE - 1); - left &= AEGIS_BLOCK_SIZE - 1; - } - - memcpy(buf.bytes + pos, src, left); - - pos += left; - assoclen -= size; - scatterwalk_unmap(mapped); - scatterwalk_advance(&walk, size); - scatterwalk_done(&walk, 0, assoclen); - } - - if (pos > 0) { - memset(buf.bytes + pos, 0, AEGIS_BLOCK_SIZE - pos); - crypto_aegis256_update_a(state, &buf); - } -} - -static void crypto_aegis256_process_crypt(struct aegis_state *state, - struct aead_request *req, - const struct aegis256_ops *ops) -{ - struct skcipher_walk walk; - - ops->skcipher_walk_init(&walk, req, false); - - while (walk.nbytes) { - unsigned int nbytes = walk.nbytes; - - if (nbytes < walk.total) - nbytes = round_down(nbytes, walk.stride); - - ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr, - nbytes); - - skcipher_walk_done(&walk, walk.nbytes - nbytes); - } -} - -static void crypto_aegis256_final(struct aegis_state *state, - union aegis_block *tag_xor, - u64 assoclen, u64 cryptlen) -{ - u64 assocbits = assoclen * 8; - u64 cryptbits = cryptlen * 8; - - union aegis_block tmp; - unsigned int i; - - tmp.words64[0] = cpu_to_le64(assocbits); - tmp.words64[1] = cpu_to_le64(cryptbits); - - crypto_aegis_block_xor(&tmp, &state->blocks[3]); - - for (i = 0; i < 7; i++) - crypto_aegis256_update_a(state, &tmp); - - for (i = 0; i < AEGIS256_STATE_BLOCKS; i++) - crypto_aegis_block_xor(tag_xor, &state->blocks[i]); -} - -static int crypto_aegis256_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) -{ - struct aegis_ctx *ctx = crypto_aead_ctx(aead); - - if (keylen != AEGIS256_KEY_SIZE) { - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - memcpy(ctx->key[0].bytes, key, AEGIS_BLOCK_SIZE); - memcpy(ctx->key[1].bytes, key + AEGIS_BLOCK_SIZE, - AEGIS_BLOCK_SIZE); - return 0; -} - -static int crypto_aegis256_setauthsize(struct crypto_aead *tfm, - unsigned int authsize) -{ - if (authsize > AEGIS256_MAX_AUTH_SIZE) - return -EINVAL; - if (authsize < AEGIS256_MIN_AUTH_SIZE) - return -EINVAL; - return 0; -} - -static void crypto_aegis256_crypt(struct aead_request *req, - union aegis_block *tag_xor, - unsigned int cryptlen, - const struct aegis256_ops *ops) -{ - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct aegis_ctx *ctx = crypto_aead_ctx(tfm); - struct aegis_state state; - - crypto_aegis256_init(&state, ctx->key, req->iv); - crypto_aegis256_process_ad(&state, req->src, req->assoclen); - crypto_aegis256_process_crypt(&state, req, ops); - crypto_aegis256_final(&state, tag_xor, req->assoclen, cryptlen); -} - -static int crypto_aegis256_encrypt(struct aead_request *req) -{ - static const struct aegis256_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_chunk = crypto_aegis256_encrypt_chunk, - }; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union aegis_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; - - crypto_aegis256_crypt(req, &tag, cryptlen, &ops); - - scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, - authsize, 1); - return 0; -} - -static int crypto_aegis256_decrypt(struct aead_request *req) -{ - static const struct aegis256_ops ops = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_chunk = crypto_aegis256_decrypt_chunk, - }; - static const u8 zeros[AEGIS256_MAX_AUTH_SIZE] = {}; - - struct crypto_aead *tfm = crypto_aead_reqtfm(req); - union aegis_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; - - scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, - authsize, 0); - - crypto_aegis256_crypt(req, &tag, cryptlen, &ops); - - return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; -} - -static int crypto_aegis256_init_tfm(struct crypto_aead *tfm) -{ - return 0; -} - -static void crypto_aegis256_exit_tfm(struct crypto_aead *tfm) -{ -} - -static struct aead_alg crypto_aegis256_alg = { - .setkey = crypto_aegis256_setkey, - .setauthsize = crypto_aegis256_setauthsize, - .encrypt = crypto_aegis256_encrypt, - .decrypt = crypto_aegis256_decrypt, - .init = crypto_aegis256_init_tfm, - .exit = crypto_aegis256_exit_tfm, - - .ivsize = AEGIS256_NONCE_SIZE, - .maxauthsize = AEGIS256_MAX_AUTH_SIZE, - .chunksize = AEGIS_BLOCK_SIZE, - - .base = { - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct aegis_ctx), - .cra_alignmask = 0, - - .cra_priority = 100, - - .cra_name = "aegis256", - .cra_driver_name = "aegis256-generic", - - .cra_module = THIS_MODULE, - } -}; - -static int __init crypto_aegis256_module_init(void) -{ - return crypto_register_aead(&crypto_aegis256_alg); -} - -static void __exit crypto_aegis256_module_exit(void) -{ - crypto_unregister_aead(&crypto_aegis256_alg); -} - -subsys_initcall(crypto_aegis256_module_init); -module_exit(crypto_aegis256_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ondrej Mosnacek "); -MODULE_DESCRIPTION("AEGIS-256 AEAD algorithm"); -MODULE_ALIAS_CRYPTO("aegis256"); -MODULE_ALIAS_CRYPTO("aegis256-generic"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 6258581aa628..d990eba723cd 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3886,18 +3886,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .aead = __VECS(aegis128_tv_template) } - }, { - .alg = "aegis128l", - .test = alg_test_aead, - .suite = { - .aead = __VECS(aegis128l_tv_template) - } - }, { - .alg = "aegis256", - .test = alg_test_aead, - .suite = { - .aead = __VECS(aegis256_tv_template) - } }, { .alg = "ansi_cprng", .test = alg_test_cprng, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index fca03fa018fc..154052d07818 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -19488,990 +19488,6 @@ static const struct aead_testvec aegis128_tv_template[] = { }, }; -/* - * AEGIS-128L test vectors - generated via reference implementation from - * SUPERCOP (https://bench.cr.yp.to/supercop.html): - * - * https://bench.cr.yp.to/supercop/supercop-20170228.tar.xz - * (see crypto_aead/aegis128l/) - */ -static const struct aead_testvec aegis128l_tv_template[] = { - { - .key = "\x0f\xc9\x8e\x67\x44\x9e\xaa\x86" - "\x20\x36\x2c\x24\xfe\xc9\x30\x81", - .klen = 16, - .iv = "\x1e\x92\x1c\xcf\x88\x3d\x54\x0d" - "\x40\x6d\x59\x48\xfc\x92\x61\x03", - .assoc = "", - .alen = 0, - .ptext = "", - .plen = 0, - .ctext = "\x30\x4f\xf3\xe9\xb1\xfa\x81\xa6" - "\x20\x72\x78\xdd\x93\xc8\x57\xef", - .clen = 16, - }, { - .key = "\x4b\xed\xc8\x07\x54\x1a\x52\xa2" - "\xa1\x10\xde\xb5\xf8\xed\xf3\x87", - .klen = 16, - .iv = "\x5a\xb7\x56\x6e\x98\xb9\xfd\x29" - "\xc1\x47\x0b\xda\xf6\xb6\x23\x09", - .assoc = "", - .alen = 0, - .ptext = "\x79", - .plen = 1, - .ctext = "\xa9\x24\xa0\xb6\x2d\xdd\x29\xdb" - "\x40\xb3\x71\xc5\x22\x58\x31\x77" - "\x6d", - .clen = 17, - }, { - .key = "\x88\x12\x01\xa6\x64\x96\xfb\xbe" - "\x22\xea\x90\x47\xf2\x11\xb5\x8e", - .klen = 16, - .iv = "\x97\xdb\x90\x0e\xa8\x35\xa5\x45" - "\x42\x21\xbd\x6b\xf0\xda\xe6\x0f", - .assoc = "", - .alen = 0, - .ptext = "\xb5\x6e\xad\xdd\x30\x72\xfa\x53" - "\x82\x8e\x16\xb4\xed\x6d\x47", - .plen = 15, - .ctext = "\xbb\x0a\x53\xc4\xaa\x7e\xa4\x03" - "\x2b\xee\x62\x99\x7b\x98\x13\x1f" - "\xe0\x76\x4c\x2e\x53\x99\x4f\xbe" - "\xe1\xa8\x04\x7f\xe1\x71\xbe", - .clen = 31, - }, { - .key = "\xc4\x37\x3b\x45\x74\x11\xa4\xda" - "\xa2\xc5\x42\xd8\xec\x36\x78\x94", - .klen = 16, - .iv = "\xd3\x00\xc9\xad\xb8\xb0\x4e\x61" - "\xc3\xfb\x6f\xfd\xea\xff\xa9\x15", - .assoc = "", - .alen = 0, - .ptext = "\xf2\x92\xe6\x7d\x40\xee\xa3\x6f" - "\x03\x68\xc8\x45\xe7\x91\x0a\x18", - .plen = 16, - .ctext = "\x66\xdf\x6e\x71\xc0\x6e\xa4\x4c" - "\x9d\xb7\x8c\x9a\xdb\x1f\xd2\x2e" - "\x23\xb6\xa4\xfb\xd3\x86\xdd\xbb" - "\xde\x54\x9b\xf5\x92\x8b\x93\xc5", - .clen = 32, - }, { - .key = "\x01\x5c\x75\xe5\x84\x8d\x4d\xf6" - "\x23\x9f\xf4\x6a\xe6\x5a\x3b\x9a", - .klen = 16, - .iv = "\x10\x25\x03\x4c\xc8\x2c\xf7\x7d" - "\x44\xd5\x21\x8e\xe4\x23\x6b\x1c", - .assoc = "", - .alen = 0, - .ptext = "\x2e\xb7\x20\x1c\x50\x6a\x4b\x8b" - "\x84\x42\x7a\xd7\xe1\xb5\xcd\x1f" - "\xd3", - .plen = 17, - .ctext = "\x4f\xc3\x69\xb6\xd3\xa4\x64\x8b" - "\x71\xc3\x8a\x91\x22\x4f\x1b\xd2" - "\x33\x6d\x86\xbc\xf8\x2f\x06\xf9" - "\x82\x64\xc7\x72\x00\x30\xfc\xf0" - "\xf8", - .clen = 33, - }, { - .key = "\x3d\x80\xae\x84\x94\x09\xf6\x12" - "\xa4\x79\xa6\xfb\xe0\x7f\xfd\xa0", - .klen = 16, - .iv = "\x4c\x49\x3d\xec\xd8\xa8\xa0\x98" - "\xc5\xb0\xd3\x1f\xde\x48\x2e\x22", - .assoc = "", - .alen = 0, - .ptext = "\x6b\xdc\x5a\xbb\x60\xe5\xf4\xa6" - "\x05\x1d\x2c\x68\xdb\xda\x8f\x25" - "\xfe\x8d\x45\x19\x1e\xc0\x0b\x99" - "\x88\x11\x39\x12\x1c\x3a\xbb", - .plen = 31, - .ctext = "\xe3\x93\x15\xae\x5f\x9d\x3c\xb5" - "\xd6\x9d\xee\xee\xcf\xaa\xaf\xe1" - "\x45\x10\x96\xe0\xbf\x55\x0f\x4c" - "\x1a\xfd\xf4\xda\x4e\x10\xde\xc9" - "\x0e\x6f\xc7\x3c\x49\x94\x41\xfc" - "\x59\x28\x88\x3c\x79\x10\x6b", - .clen = 47, - }, { - .key = "\x7a\xa5\xe8\x23\xa4\x84\x9e\x2d" - "\x25\x53\x58\x8c\xda\xa3\xc0\xa6", - .klen = 16, - .iv = "\x89\x6e\x77\x8b\xe8\x23\x49\xb4" - "\x45\x8a\x85\xb1\xd8\x6c\xf1\x28", - .assoc = "", - .alen = 0, - .ptext = "\xa7\x00\x93\x5b\x70\x61\x9d\xc2" - "\x86\xf7\xde\xfa\xd5\xfe\x52\x2b" - "\x28\x50\x51\x9d\x24\x60\x8d\xb3" - "\x49\x3e\x17\xea\xf6\x99\x5a\xdd", - .plen = 32, - .ctext = "\x1c\x8e\x22\x34\xfd\xab\xe6\x0d" - "\x1c\x9f\x06\x54\x8b\x0b\xb4\x40" - "\xde\x11\x59\x3e\xfd\x74\xf6\x42" - "\x97\x17\xf7\x24\xb6\x7e\xc4\xc6" - "\x06\xa3\x94\xda\x3d\x7f\x55\x0a" - "\x92\x07\x2f\xa6\xf3\x6b\x2c\xfc", - .clen = 48, - }, { - .key = "\xb6\xca\x22\xc3\xb4\x00\x47\x49" - "\xa6\x2d\x0a\x1e\xd4\xc7\x83\xad", - .klen = 16, - .iv = "\xc5\x93\xb0\x2a\xf8\x9f\xf1\xd0" - "\xc6\x64\x37\x42\xd2\x90\xb3\x2e", - .assoc = "\xd5", - .alen = 1, - .ptext = "", - .plen = 0, - .ctext = "\xa0\x2a\xb4\x9a\x91\x00\x15\xb8" - "\x0f\x9a\x15\x60\x0e\x9b\x13\x8f", - .clen = 16, - }, { - .key = "\xf3\xee\x5c\x62\xc4\x7c\xf0\x65" - "\x27\x08\xbd\xaf\xce\xec\x45\xb3", - .klen = 16, - .iv = "\x02\xb8\xea\xca\x09\x1b\x9a\xec" - "\x47\x3e\xe9\xd4\xcc\xb5\x76\x34", - .assoc = "\x11\x81\x78\x32\x4d\xb9\x44\x73" - "\x68\x75\x16\xf8\xcb\x7e\xa7", - .alen = 15, - .ptext = "", - .plen = 0, - .ctext = "\x4c\x26\xad\x9c\x14\xfd\x9c\x8c" - "\x84\xfb\x26\xfb\xd5\xca\x62\x39", - .clen = 16, - }, { - .key = "\x2f\x13\x95\x01\xd5\xf7\x99\x81" - "\xa8\xe2\x6f\x41\xc8\x10\x08\xb9", - .klen = 16, - .iv = "\x3f\xdc\x24\x69\x19\x96\x43\x08" - "\xc8\x18\x9b\x65\xc6\xd9\x39\x3b", - .assoc = "\x4e\xa5\xb2\xd1\x5d\x35\xed\x8f" - "\xe8\x4f\xc8\x89\xc5\xa2\x69\xbc", - .alen = 16, - .ptext = "", - .plen = 0, - .ctext = "\x45\x85\x0e\x0f\xf4\xae\x96\xa1" - "\x99\x4d\x6d\xb4\x67\x32\xb0\x3a", - .clen = 16, - }, { - .key = "\x6c\x38\xcf\xa1\xe5\x73\x41\x9d" - "\x29\xbc\x21\xd2\xc2\x35\xcb\xbf", - .klen = 16, - .iv = "\x7b\x01\x5d\x08\x29\x12\xec\x24" - "\x49\xf3\x4d\xf7\xc0\xfe\xfb\x41", - .assoc = "\x8a\xca\xec\x70\x6d\xb1\x96\xab" - "\x69\x29\x7a\x1b\xbf\xc7\x2c\xc2" - "\x07", - .alen = 17, - .ptext = "", - .plen = 0, - .ctext = "\x33\xb1\x42\x97\x8e\x16\x7b\x63" - "\x06\xba\x5b\xcb\xae\x6d\x8b\x56", - .clen = 16, - }, { - .key = "\xa8\x5c\x09\x40\xf5\xef\xea\xb8" - "\xaa\x96\xd3\x64\xbc\x59\x8d\xc6", - .klen = 16, - .iv = "\xb8\x26\x97\xa8\x39\x8e\x94\x3f" - "\xca\xcd\xff\x88\xba\x22\xbe\x47", - .assoc = "\xc7\xef\x26\x10\x7d\x2c\x3f\xc6" - "\xea\x03\x2c\xac\xb9\xeb\xef\xc9" - "\x31\x6b\x08\x12\xfc\xd8\x37\x2d" - "\xe0\x17\x3a\x2e\x83\x5c\x8f", - .alen = 31, - .ptext = "", - .plen = 0, - .ctext = "\xda\x44\x08\x8c\x2a\xa5\x07\x35" - "\x0b\x54\x4e\x6d\xe3\xfd\xc4\x5f", - .clen = 16, - }, { - .key = "\xe5\x81\x42\xdf\x05\x6a\x93\xd4" - "\x2b\x70\x85\xf5\xb6\x7d\x50\xcc", - .klen = 16, - .iv = "\xf4\x4a\xd1\x47\x49\x09\x3d\x5b" - "\x4b\xa7\xb1\x19\xb4\x46\x81\x4d", - .assoc = "\x03\x14\x5f\xaf\x8d\xa8\xe7\xe2" - "\x6b\xde\xde\x3e\xb3\x10\xb1\xcf" - "\x5c\x2d\x14\x96\x01\x78\xb9\x47" - "\xa1\x44\x19\x06\x5d\xbb\x2e\x2f", - .alen = 32, - .ptext = "", - .plen = 0, - .ctext = "\x1b\xb1\xf1\xa8\x9e\xc2\xb2\x88" - "\x40\x7f\x7b\x19\x7a\x52\x8c\xf0", - .clen = 16, - }, { - .key = "\x22\xa6\x7c\x7f\x15\xe6\x3c\xf0" - "\xac\x4b\x37\x86\xb0\xa2\x13\xd2", - .klen = 16, - .iv = "\x31\x6f\x0b\xe6\x59\x85\xe6\x77" - "\xcc\x81\x63\xab\xae\x6b\x43\x54", - .assoc = "\x40", - .alen = 1, - .ptext = "\x4f", - .plen = 1, - .ctext = "\x6e\xc8\xfb\x15\x9d\x98\x49\xc9" - "\xa0\x98\x09\x85\xbe\x56\x8e\x79" - "\xf4", - .clen = 17, - }, { - .key = "\x5e\xcb\xb6\x1e\x25\x62\xe4\x0c" - "\x2d\x25\xe9\x18\xaa\xc6\xd5\xd8", - .klen = 16, - .iv = "\x6d\x94\x44\x86\x69\x00\x8f\x93" - "\x4d\x5b\x15\x3c\xa8\x8f\x06\x5a", - .assoc = "\x7c\x5d\xd3\xee\xad\x9f\x39\x1a" - "\x6d\x92\x42\x61\xa7\x58\x37", - .alen = 15, - .ptext = "\x8b\x26\x61\x55\xf1\x3e\xe3\xa1" - "\x8d\xc8\x6e\x85\xa5\x21\x67", - .plen = 15, - .ctext = "\x99\x2e\x84\x50\x64\x5c\xab\x29" - "\x20\xba\xb9\x2f\x62\x3a\xce\x2a" - "\x75\x25\x3b\xe3\x40\xe0\x1d\xfc" - "\x20\x63\x0b\x49\x7e\x97\x08", - .clen = 31, - }, { - .key = "\x9b\xef\xf0\xbd\x35\xdd\x8d\x28" - "\xad\xff\x9b\xa9\xa4\xeb\x98\xdf", - .klen = 16, - .iv = "\xaa\xb8\x7e\x25\x79\x7c\x37\xaf" - "\xce\x36\xc7\xce\xa2\xb4\xc9\x60", - .assoc = "\xb9\x82\x0c\x8d\xbd\x1b\xe2\x36" - "\xee\x6c\xf4\xf2\xa1\x7d\xf9\xe2", - .alen = 16, - .ptext = "\xc8\x4b\x9b\xf5\x01\xba\x8c\xbd" - "\x0e\xa3\x21\x16\x9f\x46\x2a\x63", - .plen = 16, - .ctext = "\xd9\x8e\xfd\x50\x8f\x02\x9f\xee" - "\x78\x08\x12\xec\x09\xaf\x53\x14" - "\x90\x3e\x3d\x76\xad\x71\x21\x08" - "\x77\xe5\x4b\x15\xc2\xe6\xbc\xdb", - .clen = 32, - }, { - .key = "\xd7\x14\x29\x5d\x45\x59\x36\x44" - "\x2e\xd9\x4d\x3b\x9e\x0f\x5b\xe5", - .klen = 16, - .iv = "\xe6\xdd\xb8\xc4\x89\xf8\xe0\xca" - "\x4f\x10\x7a\x5f\x9c\xd8\x8b\x66", - .assoc = "\xf5\xa6\x46\x2c\xce\x97\x8a\x51" - "\x6f\x46\xa6\x83\x9b\xa1\xbc\xe8" - "\x05", - .alen = 17, - .ptext = "\x05\x70\xd5\x94\x12\x36\x35\xd8" - "\x8f\x7d\xd3\xa8\x99\x6a\xed\x69" - "\xd0", - .plen = 17, - .ctext = "\xf3\xe7\x95\x86\xcf\x34\x95\x96" - "\x17\xfe\x1b\xae\x1b\x31\xf2\x1a" - "\xbd\xbc\xc9\x4e\x11\x29\x09\x5c" - "\x05\xd3\xb4\x2e\x4a\x74\x59\x49" - "\x7d", - .clen = 33, - }, { - .key = "\x14\x39\x63\xfc\x56\xd5\xdf\x5f" - "\xaf\xb3\xff\xcc\x98\x33\x1d\xeb", - .klen = 16, - .iv = "\x23\x02\xf1\x64\x9a\x73\x89\xe6" - "\xd0\xea\x2c\xf1\x96\xfc\x4e\x6d", - .assoc = "\x32\xcb\x80\xcc\xde\x12\x33\x6d" - "\xf0\x20\x58\x15\x95\xc6\x7f\xee" - "\x2f\xf9\x4e\x2c\x1b\x98\x43\xc7" - "\x68\x28\x73\x40\x9f\x96\x4a", - .alen = 31, - .ptext = "\x41\x94\x0e\x33\x22\xb1\xdd\xf4" - "\x10\x57\x85\x39\x93\x8f\xaf\x70" - "\xfa\xa9\xd0\x4d\x5c\x40\x23\xcd" - "\x98\x34\xab\x37\x56\xae\x32", - .plen = 31, - .ctext = "\x06\x96\xb2\xbf\x63\xf4\x1e\x24" - "\x0d\x19\x15\x61\x65\x3b\x06\x26" - "\x71\xe8\x7e\x16\xdb\x96\x01\x01" - "\x52\xcd\x49\x5b\x07\x33\x4e\xe7" - "\xaa\x91\xf5\xd5\xc6\xfe\x41\xb5" - "\xed\x90\xce\xb9\xcd\xcc\xa1", - .clen = 47, - }, { - .key = "\x50\x5d\x9d\x9b\x66\x50\x88\x7b" - "\x30\x8e\xb1\x5e\x92\x58\xe0\xf1", - .klen = 16, - .iv = "\x5f\x27\x2b\x03\xaa\xef\x32\x02" - "\x50\xc4\xde\x82\x90\x21\x11\x73", - .assoc = "\x6e\xf0\xba\x6b\xee\x8e\xdc\x89" - "\x71\xfb\x0a\xa6\x8f\xea\x41\xf4" - "\x5a\xbb\x59\xb0\x20\x38\xc5\xe0" - "\x29\x56\x52\x19\x79\xf5\xe9\x37", - .alen = 32, - .ptext = "\x7e\xb9\x48\xd3\x32\x2d\x86\x10" - "\x91\x31\x37\xcb\x8d\xb3\x72\x76" - "\x24\x6b\xdc\xd1\x61\xe0\xa5\xe7" - "\x5a\x61\x8a\x0f\x30\x0d\xd1\xec", - .plen = 32, - .ctext = "\xf9\xd7\xee\x17\xfd\x24\xcd\xf1" - "\xbc\x0f\x35\x97\x97\x0c\x4b\x18" - "\xce\x58\xc8\x3b\xd4\x85\x93\x79" - "\xcc\x9c\xea\xc1\x73\x13\x0b\x4c" - "\xcc\x6f\x28\xf8\xa4\x4e\xb8\x56" - "\x64\x4e\x47\xce\xb2\xb4\x92\xb4", - .clen = 48, - }, { - .key = "\x8d\x82\xd6\x3b\x76\xcc\x30\x97" - "\xb1\x68\x63\xef\x8c\x7c\xa3\xf7", - .klen = 16, - .iv = "\x9c\x4b\x65\xa2\xba\x6b\xdb\x1e" - "\xd1\x9e\x90\x13\x8a\x45\xd3\x79", - .assoc = "\xab\x14\xf3\x0a\xfe\x0a\x85\xa5" - "\xf2\xd5\xbc\x38\x89\x0e\x04\xfb" - "\x84\x7d\x65\x34\x25\xd8\x47\xfa" - "\xeb\x83\x31\xf1\x54\x54\x89\x0d" - "\x9d", - .alen = 33, - .ptext = "\xba\xde\x82\x72\x42\xa9\x2f\x2c" - "\x12\x0b\xe9\x5c\x87\xd7\x35\x7c" - "\x4f\x2e\xe8\x55\x66\x80\x27\x00" - "\x1b\x8f\x68\xe7\x0a\x6c\x71\xc3" - "\x21\x78\x55\x9d\x9c\x65\x7b\xcd" - "\x0a\x34\x97\xff\x47\x37\xb0\x2a" - "\x80\x0d\x19\x98\x33\xa9\x7a\xe3" - "\x2e\x4c\xc6\xf3\x8c\x88\x42\x01" - "\xbd", - .plen = 65, - .ctext = "\x58\xfa\x3a\x3d\xd9\x88\x63\xe8" - "\xc5\x78\x50\x8b\x4a\xc9\xdf\x7f" - "\x4b\xfa\xc8\x2e\x67\x43\xf3\x63" - "\x42\x8e\x99\x5a\x9c\x0b\x84\x77" - "\xbc\x46\x76\x48\x82\xc7\x57\x96" - "\xe1\x65\xd1\xed\x1d\xdd\x80\x24" - "\xa6\x4d\xa9\xf1\x53\x8b\x5e\x0e" - "\x26\xb9\xcc\x37\xe5\x43\xe1\x5a" - "\x8a\xd6\x8c\x5a\xe4\x95\xd1\x8d" - "\xf7\x33\x64\xc1\xd3\xf2\xfc\x35" - "\x01", - .clen = 81, - }, { - .key = "\xc9\xa7\x10\xda\x86\x48\xd9\xb3" - "\x32\x42\x15\x80\x85\xa1\x65\xfe", - .klen = 16, - .iv = "\xd8\x70\x9f\x42\xca\xe6\x83\x3a" - "\x52\x79\x42\xa5\x84\x6a\x96\x7f", - .assoc = "\xe8\x39\x2d\xaa\x0e\x85\x2d\xc1" - "\x72\xaf\x6e\xc9\x82\x33\xc7\x01" - "\xaf\x40\x70\xb8\x2a\x78\xc9\x14" - "\xac\xb1\x10\xca\x2e\xb3\x28\xe4" - "\xac\xfa\x58\x7f\xe5\x73\x09\x8c" - "\x1d\x40\x87\x8c\xd9\x75\xc0\x55" - "\xa2\xda\x07\xd1\xc2\xa9\xd1\xbb" - "\x09\x4f\x77\x62\x88\x2d\xf2\x68" - "\x54", - .alen = 65, - .ptext = "\xf7\x02\xbb\x11\x52\x24\xd8\x48" - "\x93\xe6\x9b\xee\x81\xfc\xf7\x82" - "\x79\xf0\xf3\xd9\x6c\x20\xa9\x1a" - "\xdc\xbc\x47\xc0\xe4\xcb\x10\x99" - "\x2f", - .plen = 33, - .ctext = "\x4c\xa9\xac\x71\xed\x10\xa6\x24" - "\xb7\xa7\xdf\x8b\xf5\xc2\x41\xcb" - "\x05\xc9\xd6\x97\xb6\x10\x7f\x17" - "\xc2\xc0\x93\xcf\xe0\x94\xfd\x99" - "\xf2\x62\x25\x28\x01\x23\x6f\x8b" - "\x04\x52\xbc\xb0\x3e\x66\x52\x90" - "\x9f", - .clen = 49, - }, { - .key = "\x06\xcc\x4a\x79\x96\xc3\x82\xcf" - "\xb3\x1c\xc7\x12\x7f\xc5\x28\x04", - .klen = 16, - .iv = "\x15\x95\xd8\xe1\xda\x62\x2c\x56" - "\xd3\x53\xf4\x36\x7e\x8e\x59\x85", - .assoc = "\x24\x5e\x67\x49\x1e\x01\xd6\xdd" - "\xf3\x89\x20\x5b\x7c\x57\x89\x07", - .alen = 16, - .ptext = "\x33\x27\xf5\xb1\x62\xa0\x80\x63" - "\x14\xc0\x4d\x7f\x7b\x20\xba\x89", - .plen = 16, - .ctext = "\x6d\xed\x04\x7a\x2f\x0c\x30\xa5" - "\x96\xe6\x97\xe4\x10\xeb\x40\x95" - "\xc5\x9a\xdf\x31\xd5\xa5\xa6\xec" - "\x05\xa8\x31\x50\x11\x19\x44", - .clen = 31, - }, { - .key = "\x42\xf0\x84\x19\xa6\x3f\x2b\xea" - "\x34\xf6\x79\xa3\x79\xe9\xeb\x0a", - .klen = 16, - .iv = "\x51\xb9\x12\x80\xea\xde\xd5\x71" - "\x54\x2d\xa6\xc8\x78\xb2\x1b\x8c", - .assoc = "\x61\x83\xa0\xe8\x2e\x7d\x7f\xf8" - "\x74\x63\xd2\xec\x76\x7c\x4c\x0d", - .alen = 16, - .ptext = "\x70\x4c\x2f\x50\x72\x1c\x29\x7f" - "\x95\x9a\xff\x10\x75\x45\x7d\x8f", - .plen = 16, - .ctext = "\x30\x95\x7d\xea\xdc\x62\xc0\x88" - "\xa1\xe3\x8d\x8c\xac\x04\x10\xa7" - "\xfa\xfa\x07\xbd\xa0\xf0\x36\xeb" - "\x21\x93\x2e\x31\x84\x83", - .clen = 30, - }, { - .key = "\x7f\x15\xbd\xb8\xb6\xba\xd3\x06" - "\xb5\xd1\x2b\x35\x73\x0e\xad\x10", - .klen = 16, - .iv = "\x8e\xde\x4c\x20\xfa\x59\x7e\x8d" - "\xd5\x07\x58\x59\x72\xd7\xde\x92", - .assoc = "\x9d\xa7\xda\x88\x3e\xf8\x28\x14" - "\xf5\x3e\x85\x7d\x70\xa0\x0f\x13", - .alen = 16, - .ptext = "\xac\x70\x69\xef\x82\x97\xd2\x9b" - "\x15\x74\xb1\xa2\x6f\x69\x3f\x95", - .plen = 16, - .ctext = "\x93\xcd\xee\xd4\xcb\x9d\x8d\x16" - "\x63\x0d\x43\xd5\x49\xca\xa8\x85" - "\x49\xc0\xae\x13\xbc\x26\x1d\x4b", - .clen = 24, - }, -}; - -/* - * AEGIS-256 test vectors - generated via reference implementation from - * SUPERCOP (https://bench.cr.yp.to/supercop.html): - * - * https://bench.cr.yp.to/supercop/supercop-20170228.tar.xz - * (see crypto_aead/aegis256/) - */ -static const struct aead_testvec aegis256_tv_template[] = { - { - .key = "\x0f\xc9\x8e\x67\x44\x9e\xaa\x86" - "\x20\x36\x2c\x24\xfe\xc9\x30\x81" - "\xca\xb0\x82\x21\x41\xa8\xe0\x06" - "\x30\x0b\x37\xf6\xb6\x17\xe7\xb5", - .klen = 32, - .iv = "\x1e\x92\x1c\xcf\x88\x3d\x54\x0d" - "\x40\x6d\x59\x48\xfc\x92\x61\x03" - "\x95\x61\x05\x42\x82\x50\xc0\x0c" - "\x60\x16\x6f\xec\x6d\x2f\xcf\x6b", - .assoc = "", - .alen = 0, - .ptext = "", - .plen = 0, - .ctext = "\xd5\x65\x3a\xa9\x03\x51\xd7\xaa" - "\xfa\x4b\xd8\xa2\x41\x9b\xc1\xb2", - .clen = 16, - }, { - .key = "\x4b\xed\xc8\x07\x54\x1a\x52\xa2" - "\xa1\x10\xde\xb5\xf8\xed\xf3\x87" - "\xf4\x72\x8e\xa5\x46\x48\x62\x20" - "\xf1\x38\x16\xce\x90\x76\x87\x8c", - .klen = 32, - .iv = "\x5a\xb7\x56\x6e\x98\xb9\xfd\x29" - "\xc1\x47\x0b\xda\xf6\xb6\x23\x09" - "\xbf\x23\x11\xc6\x87\xf0\x42\x26" - "\x22\x44\x4e\xc4\x47\x8e\x6e\x41", - .assoc = "", - .alen = 0, - .ptext = "\x79", - .plen = 1, - .ctext = "\x84\xa2\x8f\xad\xdb\x8d\x2c\x16" - "\x9e\x89\xd9\x06\xa6\xa8\x14\x29" - "\x8b", - .clen = 17, - }, { - .key = "\x88\x12\x01\xa6\x64\x96\xfb\xbe" - "\x22\xea\x90\x47\xf2\x11\xb5\x8e" - "\x1f\x35\x9a\x29\x4b\xe8\xe4\x39" - "\xb3\x66\xf5\xa6\x6a\xd5\x26\x62", - .klen = 32, - .iv = "\x97\xdb\x90\x0e\xa8\x35\xa5\x45" - "\x42\x21\xbd\x6b\xf0\xda\xe6\x0f" - "\xe9\xe5\x1d\x4a\x8c\x90\xc4\x40" - "\xe3\x71\x2d\x9c\x21\xed\x0e\x18", - .assoc = "", - .alen = 0, - .ptext = "\xb5\x6e\xad\xdd\x30\x72\xfa\x53" - "\x82\x8e\x16\xb4\xed\x6d\x47", - .plen = 15, - .ctext = "\x09\x94\x1f\xa6\x13\xc3\x74\x75" - "\x17\xad\x8a\x0e\xd8\x66\x9a\x28" - "\xd7\x30\x66\x09\x2a\xdc\xfa\x2a" - "\x9f\x3b\xd7\xdd\x66\xd1\x2b", - .clen = 31, - }, { - .key = "\xc4\x37\x3b\x45\x74\x11\xa4\xda" - "\xa2\xc5\x42\xd8\xec\x36\x78\x94" - "\x49\xf7\xa5\xad\x50\x88\x66\x53" - "\x74\x94\xd4\x7f\x44\x34\xc5\x39", - .klen = 32, - .iv = "\xd3\x00\xc9\xad\xb8\xb0\x4e\x61" - "\xc3\xfb\x6f\xfd\xea\xff\xa9\x15" - "\x14\xa8\x28\xce\x92\x30\x46\x59" - "\xa4\x9f\x0b\x75\xfb\x4c\xad\xee", - .assoc = "", - .alen = 0, - .ptext = "\xf2\x92\xe6\x7d\x40\xee\xa3\x6f" - "\x03\x68\xc8\x45\xe7\x91\x0a\x18", - .plen = 16, - .ctext = "\x8a\x46\xa2\x22\x8c\x03\xab\x6f" - "\x54\x63\x4e\x7f\xc9\x8e\xfa\x70" - "\x7b\xe5\x8d\x78\xbc\xe9\xb6\xa1" - "\x29\x17\xc8\x3b\x52\xa4\x98\x72", - .clen = 32, - }, { - .key = "\x01\x5c\x75\xe5\x84\x8d\x4d\xf6" - "\x23\x9f\xf4\x6a\xe6\x5a\x3b\x9a" - "\x74\xb9\xb1\x32\x55\x28\xe8\x6d" - "\x35\xc1\xb3\x57\x1f\x93\x64\x0f", - .klen = 32, - .iv = "\x10\x25\x03\x4c\xc8\x2c\xf7\x7d" - "\x44\xd5\x21\x8e\xe4\x23\x6b\x1c" - "\x3e\x6a\x34\x53\x97\xd0\xc8\x73" - "\x66\xcd\xea\x4d\xd5\xab\x4c\xc5", - .assoc = "", - .alen = 0, - .ptext = "\x2e\xb7\x20\x1c\x50\x6a\x4b\x8b" - "\x84\x42\x7a\xd7\xe1\xb5\xcd\x1f" - "\xd3", - .plen = 17, - .ctext = "\x71\x6b\x37\x0b\x02\x61\x28\x12" - "\x83\xab\x66\x90\x84\xc7\xd1\xc5" - "\xb2\x7a\xb4\x7b\xb4\xfe\x02\xb2" - "\xc0\x00\x39\x13\xb5\x51\x68\x44" - "\xad", - .clen = 33, - }, { - .key = "\x3d\x80\xae\x84\x94\x09\xf6\x12" - "\xa4\x79\xa6\xfb\xe0\x7f\xfd\xa0" - "\x9e\x7c\xbc\xb6\x5b\xc8\x6a\x86" - "\xf7\xef\x91\x30\xf9\xf2\x04\xe6", - .klen = 32, - .iv = "\x4c\x49\x3d\xec\xd8\xa8\xa0\x98" - "\xc5\xb0\xd3\x1f\xde\x48\x2e\x22" - "\x69\x2c\x3f\xd7\x9c\x70\x4a\x8d" - "\x27\xfa\xc9\x26\xaf\x0a\xeb\x9c", - .assoc = "", - .alen = 0, - .ptext = "\x6b\xdc\x5a\xbb\x60\xe5\xf4\xa6" - "\x05\x1d\x2c\x68\xdb\xda\x8f\x25" - "\xfe\x8d\x45\x19\x1e\xc0\x0b\x99" - "\x88\x11\x39\x12\x1c\x3a\xbb", - .plen = 31, - .ctext = "\xaf\xa4\x34\x0d\x59\xe6\x1c\x2f" - "\x06\x3b\x52\x18\x49\x75\x1b\xf0" - "\x53\x09\x72\x7b\x45\x79\xe0\xbe" - "\x89\x85\x23\x15\xb8\x79\x07\x4c" - "\x53\x7a\x15\x37\x0a\xee\xb7\xfb" - "\xc4\x1f\x12\x27\xcf\x77\x90", - .clen = 47, - }, { - .key = "\x7a\xa5\xe8\x23\xa4\x84\x9e\x2d" - "\x25\x53\x58\x8c\xda\xa3\xc0\xa6" - "\xc8\x3e\xc8\x3a\x60\x68\xec\xa0" - "\xb8\x1c\x70\x08\xd3\x51\xa3\xbd", - .klen = 32, - .iv = "\x89\x6e\x77\x8b\xe8\x23\x49\xb4" - "\x45\x8a\x85\xb1\xd8\x6c\xf1\x28" - "\x93\xef\x4b\x5b\xa1\x10\xcc\xa6" - "\xe8\x28\xa8\xfe\x89\x69\x8b\x72", - .assoc = "", - .alen = 0, - .ptext = "\xa7\x00\x93\x5b\x70\x61\x9d\xc2" - "\x86\xf7\xde\xfa\xd5\xfe\x52\x2b" - "\x28\x50\x51\x9d\x24\x60\x8d\xb3" - "\x49\x3e\x17\xea\xf6\x99\x5a\xdd", - .plen = 32, - .ctext = "\xe2\xc9\x0b\x33\x31\x02\xb3\xb4" - "\x33\xfe\xeb\xa8\xb7\x9b\xb2\xd7" - "\xeb\x0f\x05\x2b\xba\xb3\xca\xef" - "\xf6\xd1\xb6\xc0\xb9\x9b\x85\xc5" - "\xbf\x7a\x3e\xcc\x31\x76\x09\x80" - "\x32\x5d\xbb\xe8\x38\x0e\x77\xd3", - .clen = 48, - }, { - .key = "\xb6\xca\x22\xc3\xb4\x00\x47\x49" - "\xa6\x2d\x0a\x1e\xd4\xc7\x83\xad" - "\xf3\x00\xd4\xbf\x65\x08\x6e\xb9" - "\x7a\x4a\x4f\xe0\xad\xb0\x42\x93", - .klen = 32, - .iv = "\xc5\x93\xb0\x2a\xf8\x9f\xf1\xd0" - "\xc6\x64\x37\x42\xd2\x90\xb3\x2e" - "\xbd\xb1\x57\xe0\xa6\xb0\x4e\xc0" - "\xaa\x55\x87\xd6\x63\xc8\x2a\x49", - .assoc = "\xd5", - .alen = 1, - .ptext = "", - .plen = 0, - .ctext = "\x96\x43\x30\xca\x6c\x4f\xd7\x12" - "\xba\xd9\xb3\x18\x86\xdf\xc3\x52", - .clen = 16, - }, { - .key = "\xf3\xee\x5c\x62\xc4\x7c\xf0\x65" - "\x27\x08\xbd\xaf\xce\xec\x45\xb3" - "\x1d\xc3\xdf\x43\x6a\xa8\xf0\xd3" - "\x3b\x77\x2e\xb9\x87\x0f\xe1\x6a", - .klen = 32, - .iv = "\x02\xb8\xea\xca\x09\x1b\x9a\xec" - "\x47\x3e\xe9\xd4\xcc\xb5\x76\x34" - "\xe8\x73\x62\x64\xab\x50\xd0\xda" - "\x6b\x83\x66\xaf\x3e\x27\xc9\x1f", - .assoc = "\x11\x81\x78\x32\x4d\xb9\x44\x73" - "\x68\x75\x16\xf8\xcb\x7e\xa7", - .alen = 15, - .ptext = "", - .plen = 0, - .ctext = "\x2f\xab\x45\xe2\xa7\x46\xc5\x83" - "\x11\x9f\xb0\x74\xee\xc7\x03\xdd", - .clen = 16, - }, { - .key = "\x2f\x13\x95\x01\xd5\xf7\x99\x81" - "\xa8\xe2\x6f\x41\xc8\x10\x08\xb9" - "\x47\x85\xeb\xc7\x6f\x48\x72\xed" - "\xfc\xa5\x0d\x91\x61\x6e\x81\x40", - .klen = 32, - .iv = "\x3f\xdc\x24\x69\x19\x96\x43\x08" - "\xc8\x18\x9b\x65\xc6\xd9\x39\x3b" - "\x12\x35\x6e\xe8\xb0\xf0\x52\xf3" - "\x2d\xb0\x45\x87\x18\x86\x68\xf6", - .assoc = "\x4e\xa5\xb2\xd1\x5d\x35\xed\x8f" - "\xe8\x4f\xc8\x89\xc5\xa2\x69\xbc", - .alen = 16, - .ptext = "", - .plen = 0, - .ctext = "\x16\x44\x73\x33\x5d\xf2\xb9\x04" - "\x6b\x79\x98\xef\xdb\xd5\xc5\xf1", - .clen = 16, - }, { - .key = "\x6c\x38\xcf\xa1\xe5\x73\x41\x9d" - "\x29\xbc\x21\xd2\xc2\x35\xcb\xbf" - "\x72\x47\xf6\x4b\x74\xe8\xf4\x06" - "\xbe\xd3\xec\x6a\x3b\xcd\x20\x17", - .klen = 32, - .iv = "\x7b\x01\x5d\x08\x29\x12\xec\x24" - "\x49\xf3\x4d\xf7\xc0\xfe\xfb\x41" - "\x3c\xf8\x79\x6c\xb6\x90\xd4\x0d" - "\xee\xde\x23\x60\xf2\xe5\x08\xcc", - .assoc = "\x8a\xca\xec\x70\x6d\xb1\x96\xab" - "\x69\x29\x7a\x1b\xbf\xc7\x2c\xc2" - "\x07", - .alen = 17, - .ptext = "", - .plen = 0, - .ctext = "\xa4\x9b\xb8\x47\xc0\xed\x7a\x45" - "\x98\x54\x8c\xed\x3d\x17\xf0\xdd", - .clen = 16, - }, { - .key = "\xa8\x5c\x09\x40\xf5\xef\xea\xb8" - "\xaa\x96\xd3\x64\xbc\x59\x8d\xc6" - "\x9c\x0a\x02\xd0\x79\x88\x76\x20" - "\x7f\x00\xca\x42\x15\x2c\xbf\xed", - .klen = 32, - .iv = "\xb8\x26\x97\xa8\x39\x8e\x94\x3f" - "\xca\xcd\xff\x88\xba\x22\xbe\x47" - "\x67\xba\x85\xf1\xbb\x30\x56\x26" - "\xaf\x0b\x02\x38\xcc\x44\xa7\xa3", - .assoc = "\xc7\xef\x26\x10\x7d\x2c\x3f\xc6" - "\xea\x03\x2c\xac\xb9\xeb\xef\xc9" - "\x31\x6b\x08\x12\xfc\xd8\x37\x2d" - "\xe0\x17\x3a\x2e\x83\x5c\x8f", - .alen = 31, - .ptext = "", - .plen = 0, - .ctext = "\x20\x24\xe2\x33\x5c\x60\xc9\xf0" - "\xa4\x96\x2f\x0d\x53\xc2\xf8\xfc", - .clen = 16, - }, { - .key = "\xe5\x81\x42\xdf\x05\x6a\x93\xd4" - "\x2b\x70\x85\xf5\xb6\x7d\x50\xcc" - "\xc6\xcc\x0e\x54\x7f\x28\xf8\x3a" - "\x40\x2e\xa9\x1a\xf0\x8b\x5e\xc4", - .klen = 32, - .iv = "\xf4\x4a\xd1\x47\x49\x09\x3d\x5b" - "\x4b\xa7\xb1\x19\xb4\x46\x81\x4d" - "\x91\x7c\x91\x75\xc0\xd0\xd8\x40" - "\x71\x39\xe1\x10\xa6\xa3\x46\x7a", - .assoc = "\x03\x14\x5f\xaf\x8d\xa8\xe7\xe2" - "\x6b\xde\xde\x3e\xb3\x10\xb1\xcf" - "\x5c\x2d\x14\x96\x01\x78\xb9\x47" - "\xa1\x44\x19\x06\x5d\xbb\x2e\x2f", - .alen = 32, - .ptext = "", - .plen = 0, - .ctext = "\x6f\x4a\xb9\xe0\xff\x51\xa3\xf1" - "\xd2\x64\x3e\x66\x6a\xb2\x03\xc0", - .clen = 16, - }, { - .key = "\x22\xa6\x7c\x7f\x15\xe6\x3c\xf0" - "\xac\x4b\x37\x86\xb0\xa2\x13\xd2" - "\xf1\x8e\x19\xd8\x84\xc8\x7a\x53" - "\x02\x5b\x88\xf3\xca\xea\xfe\x9b", - .klen = 32, - .iv = "\x31\x6f\x0b\xe6\x59\x85\xe6\x77" - "\xcc\x81\x63\xab\xae\x6b\x43\x54" - "\xbb\x3f\x9c\xf9\xc5\x70\x5a\x5a" - "\x32\x67\xc0\xe9\x80\x02\xe5\x50", - .assoc = "\x40", - .alen = 1, - .ptext = "\x4f", - .plen = 1, - .ctext = "\x2c\xfb\xad\x7e\xbe\xa0\x9a\x5b" - "\x7a\x3f\x81\xf7\xfc\x1b\x79\x83" - "\xc7", - .clen = 17, - }, { - .key = "\x5e\xcb\xb6\x1e\x25\x62\xe4\x0c" - "\x2d\x25\xe9\x18\xaa\xc6\xd5\xd8" - "\x1b\x50\x25\x5d\x89\x68\xfc\x6d" - "\xc3\x89\x67\xcb\xa4\x49\x9d\x71", - .klen = 32, - .iv = "\x6d\x94\x44\x86\x69\x00\x8f\x93" - "\x4d\x5b\x15\x3c\xa8\x8f\x06\x5a" - "\xe6\x01\xa8\x7e\xca\x10\xdc\x73" - "\xf4\x94\x9f\xc1\x5a\x61\x85\x27", - .assoc = "\x7c\x5d\xd3\xee\xad\x9f\x39\x1a" - "\x6d\x92\x42\x61\xa7\x58\x37", - .alen = 15, - .ptext = "\x8b\x26\x61\x55\xf1\x3e\xe3\xa1" - "\x8d\xc8\x6e\x85\xa5\x21\x67", - .plen = 15, - .ctext = "\x1f\x7f\xca\x3c\x2b\xe7\x27\xba" - "\x7e\x98\x83\x02\x34\x23\xf7\x94" - "\xde\x35\xe6\x1d\x14\x18\xe5\x38" - "\x14\x80\x6a\xa7\x1b\xae\x1d", - .clen = 31, - }, { - .key = "\x9b\xef\xf0\xbd\x35\xdd\x8d\x28" - "\xad\xff\x9b\xa9\xa4\xeb\x98\xdf" - "\x46\x13\x31\xe1\x8e\x08\x7e\x87" - "\x85\xb6\x46\xa3\x7e\xa8\x3c\x48", - .klen = 32, - .iv = "\xaa\xb8\x7e\x25\x79\x7c\x37\xaf" - "\xce\x36\xc7\xce\xa2\xb4\xc9\x60" - "\x10\xc3\xb3\x02\xcf\xb0\x5e\x8d" - "\xb5\xc2\x7e\x9a\x35\xc0\x24\xfd", - .assoc = "\xb9\x82\x0c\x8d\xbd\x1b\xe2\x36" - "\xee\x6c\xf4\xf2\xa1\x7d\xf9\xe2", - .alen = 16, - .ptext = "\xc8\x4b\x9b\xf5\x01\xba\x8c\xbd" - "\x0e\xa3\x21\x16\x9f\x46\x2a\x63", - .plen = 16, - .ctext = "\x05\x86\x9e\xd7\x2b\xa3\x97\x01" - "\xbe\x28\x98\x10\x6f\xe9\x61\x32" - "\x96\xbb\xb1\x2e\x8f\x0c\x44\xb9" - "\x46\x2d\x55\xe3\x42\x67\xf2\xaf", - .clen = 32, - }, { - .key = "\xd7\x14\x29\x5d\x45\x59\x36\x44" - "\x2e\xd9\x4d\x3b\x9e\x0f\x5b\xe5" - "\x70\xd5\x3c\x65\x93\xa8\x00\xa0" - "\x46\xe4\x25\x7c\x58\x08\xdb\x1e", - .klen = 32, - .iv = "\xe6\xdd\xb8\xc4\x89\xf8\xe0\xca" - "\x4f\x10\x7a\x5f\x9c\xd8\x8b\x66" - "\x3b\x86\xbf\x86\xd4\x50\xe0\xa7" - "\x76\xef\x5c\x72\x0f\x1f\xc3\xd4", - .assoc = "\xf5\xa6\x46\x2c\xce\x97\x8a\x51" - "\x6f\x46\xa6\x83\x9b\xa1\xbc\xe8" - "\x05", - .alen = 17, - .ptext = "\x05\x70\xd5\x94\x12\x36\x35\xd8" - "\x8f\x7d\xd3\xa8\x99\x6a\xed\x69" - "\xd0", - .plen = 17, - .ctext = "\x9c\xe0\x06\x7b\x86\xcf\x2e\xd8" - "\x45\x65\x1b\x72\x9b\xaa\xa3\x1e" - "\x87\x9d\x26\xdf\xff\x81\x11\xd2" - "\x47\x41\xb9\x24\xc1\x8a\xa3\x8b" - "\x55", - .clen = 33, - }, { - .key = "\x14\x39\x63\xfc\x56\xd5\xdf\x5f" - "\xaf\xb3\xff\xcc\x98\x33\x1d\xeb" - "\x9a\x97\x48\xe9\x98\x48\x82\xba" - "\x07\x11\x04\x54\x32\x67\x7b\xf5", - .klen = 32, - .iv = "\x23\x02\xf1\x64\x9a\x73\x89\xe6" - "\xd0\xea\x2c\xf1\x96\xfc\x4e\x6d" - "\x65\x48\xcb\x0a\xda\xf0\x62\xc0" - "\x38\x1d\x3b\x4a\xe9\x7e\x62\xaa", - .assoc = "\x32\xcb\x80\xcc\xde\x12\x33\x6d" - "\xf0\x20\x58\x15\x95\xc6\x7f\xee" - "\x2f\xf9\x4e\x2c\x1b\x98\x43\xc7" - "\x68\x28\x73\x40\x9f\x96\x4a", - .alen = 31, - .ptext = "\x41\x94\x0e\x33\x22\xb1\xdd\xf4" - "\x10\x57\x85\x39\x93\x8f\xaf\x70" - "\xfa\xa9\xd0\x4d\x5c\x40\x23\xcd" - "\x98\x34\xab\x37\x56\xae\x32", - .plen = 31, - .ctext = "\xa0\xc8\xde\x83\x0d\xc3\x4e\xd5" - "\x69\x7f\x7a\xdd\x8c\x46\xda\xba" - "\x0a\x5c\x0e\x7f\xac\xee\x02\xd2" - "\xe5\x4b\x0a\xba\xb8\xa4\x7b\x66" - "\xde\xae\xdb\xc2\xc0\x0b\xf7\x2b" - "\xdf\xb8\xea\xd8\xa9\x38\xed", - .clen = 47, - }, { - .key = "\x50\x5d\x9d\x9b\x66\x50\x88\x7b" - "\x30\x8e\xb1\x5e\x92\x58\xe0\xf1" - "\xc5\x5a\x53\x6e\x9d\xe8\x04\xd4" - "\xc9\x3f\xe2\x2d\x0c\xc6\x1a\xcb", - .klen = 32, - .iv = "\x5f\x27\x2b\x03\xaa\xef\x32\x02" - "\x50\xc4\xde\x82\x90\x21\x11\x73" - "\x8f\x0a\xd6\x8f\xdf\x90\xe4\xda" - "\xf9\x4a\x1a\x23\xc3\xdd\x02\x81", - .assoc = "\x6e\xf0\xba\x6b\xee\x8e\xdc\x89" - "\x71\xfb\x0a\xa6\x8f\xea\x41\xf4" - "\x5a\xbb\x59\xb0\x20\x38\xc5\xe0" - "\x29\x56\x52\x19\x79\xf5\xe9\x37", - .alen = 32, - .ptext = "\x7e\xb9\x48\xd3\x32\x2d\x86\x10" - "\x91\x31\x37\xcb\x8d\xb3\x72\x76" - "\x24\x6b\xdc\xd1\x61\xe0\xa5\xe7" - "\x5a\x61\x8a\x0f\x30\x0d\xd1\xec", - .plen = 32, - .ctext = "\xd3\x68\x14\x70\x3c\x01\x43\x86" - "\x02\xab\xbe\x75\xaa\xe7\xf5\x53" - "\x5c\x05\xbd\x9b\x19\xbb\x2a\x61" - "\x8f\x69\x05\x75\x8e\xca\x60\x0c" - "\x5b\xa2\x48\x61\x32\x74\x11\x2b" - "\xf6\xcf\x06\x78\x6f\x78\x1a\x4a", - .clen = 48, - }, { - .key = "\x8d\x82\xd6\x3b\x76\xcc\x30\x97" - "\xb1\x68\x63\xef\x8c\x7c\xa3\xf7" - "\xef\x1c\x5f\xf2\xa3\x88\x86\xed" - "\x8a\x6d\xc1\x05\xe7\x25\xb9\xa2", - .klen = 32, - .iv = "\x9c\x4b\x65\xa2\xba\x6b\xdb\x1e" - "\xd1\x9e\x90\x13\x8a\x45\xd3\x79" - "\xba\xcd\xe2\x13\xe4\x30\x66\xf4" - "\xba\x78\xf9\xfb\x9d\x3c\xa1\x58", - .assoc = "\xab\x14\xf3\x0a\xfe\x0a\x85\xa5" - "\xf2\xd5\xbc\x38\x89\x0e\x04\xfb" - "\x84\x7d\x65\x34\x25\xd8\x47\xfa" - "\xeb\x83\x31\xf1\x54\x54\x89\x0d" - "\x9d", - .alen = 33, - .ptext = "\xba\xde\x82\x72\x42\xa9\x2f\x2c" - "\x12\x0b\xe9\x5c\x87\xd7\x35\x7c" - "\x4f\x2e\xe8\x55\x66\x80\x27\x00" - "\x1b\x8f\x68\xe7\x0a\x6c\x71\xc3" - "\x21\x78\x55\x9d\x9c\x65\x7b\xcd" - "\x0a\x34\x97\xff\x47\x37\xb0\x2a" - "\x80\x0d\x19\x98\x33\xa9\x7a\xe3" - "\x2e\x4c\xc6\xf3\x8c\x88\x42\x01" - "\xbd", - .plen = 65, - .ctext = "\x07\x0a\x35\xb0\x82\x03\x5a\xd2" - "\x15\x3a\x6c\x72\x83\x9b\xb1\x75" - "\xea\xf2\xfc\xff\xc6\xf1\x13\xa4" - "\x1a\x93\x33\x79\x97\x82\x81\xc0" - "\x96\xc2\x00\xab\x39\xae\xa1\x62" - "\x53\xa3\x86\xc9\x07\x8c\xaf\x22" - "\x47\x31\x29\xca\x4a\x95\xf5\xd5" - "\x20\x63\x5a\x54\x80\x2c\x4a\x63" - "\xfb\x18\x73\x31\x4f\x08\x21\x5d" - "\x20\xe9\xc3\x7e\xea\x25\x77\x3a" - "\x65", - .clen = 81, - }, { - .key = "\xc9\xa7\x10\xda\x86\x48\xd9\xb3" - "\x32\x42\x15\x80\x85\xa1\x65\xfe" - "\x19\xde\x6b\x76\xa8\x28\x08\x07" - "\x4b\x9a\xa0\xdd\xc1\x84\x58\x79", - .klen = 32, - .iv = "\xd8\x70\x9f\x42\xca\xe6\x83\x3a" - "\x52\x79\x42\xa5\x84\x6a\x96\x7f" - "\xe4\x8f\xed\x97\xe9\xd0\xe8\x0d" - "\x7c\xa6\xd8\xd4\x77\x9b\x40\x2e", - .assoc = "\xe8\x39\x2d\xaa\x0e\x85\x2d\xc1" - "\x72\xaf\x6e\xc9\x82\x33\xc7\x01" - "\xaf\x40\x70\xb8\x2a\x78\xc9\x14" - "\xac\xb1\x10\xca\x2e\xb3\x28\xe4" - "\xac\xfa\x58\x7f\xe5\x73\x09\x8c" - "\x1d\x40\x87\x8c\xd9\x75\xc0\x55" - "\xa2\xda\x07\xd1\xc2\xa9\xd1\xbb" - "\x09\x4f\x77\x62\x88\x2d\xf2\x68" - "\x54", - .alen = 65, - .ptext = "\xf7\x02\xbb\x11\x52\x24\xd8\x48" - "\x93\xe6\x9b\xee\x81\xfc\xf7\x82" - "\x79\xf0\xf3\xd9\x6c\x20\xa9\x1a" - "\xdc\xbc\x47\xc0\xe4\xcb\x10\x99" - "\x2f", - .plen = 33, - .ctext = "\x33\xc1\xda\xfa\x15\x21\x07\x8e" - "\x93\x68\xea\x64\x7b\x3d\x4b\x6b" - "\x71\x5e\x5e\x6b\x92\xaa\x65\xc2" - "\x7a\x2a\xc1\xa9\x0a\xa1\x24\x81" - "\x26\x3a\x5a\x09\xe8\xce\x73\x72" - "\xde\x7b\x58\x9e\x85\xb9\xa4\x28" - "\xda", - .clen = 49, - }, { - .key = "\x06\xcc\x4a\x79\x96\xc3\x82\xcf" - "\xb3\x1c\xc7\x12\x7f\xc5\x28\x04" - "\x44\xa1\x76\xfb\xad\xc8\x8a\x21" - "\x0d\xc8\x7f\xb6\x9b\xe3\xf8\x4f", - .klen = 32, - .iv = "\x15\x95\xd8\xe1\xda\x62\x2c\x56" - "\xd3\x53\xf4\x36\x7e\x8e\x59\x85" - "\x0e\x51\xf9\x1c\xee\x70\x6a\x27" - "\x3d\xd3\xb7\xac\x51\xfa\xdf\x05", - .assoc = "\x24\x5e\x67\x49\x1e\x01\xd6\xdd" - "\xf3\x89\x20\x5b\x7c\x57\x89\x07", - .alen = 16, - .ptext = "\x33\x27\xf5\xb1\x62\xa0\x80\x63" - "\x14\xc0\x4d\x7f\x7b\x20\xba\x89", - .plen = 16, - .ctext = "\x3e\xf8\x86\x3d\x39\xf8\x96\x02" - "\x0f\xdf\xc9\x6e\x37\x1e\x57\x99" - "\x07\x2a\x1a\xac\xd1\xda\xfd\x3b" - "\xc7\xff\xbd\xbc\x85\x09\x0b", - .clen = 31, - }, { - .key = "\x42\xf0\x84\x19\xa6\x3f\x2b\xea" - "\x34\xf6\x79\xa3\x79\xe9\xeb\x0a" - "\x6e\x63\x82\x7f\xb2\x68\x0c\x3a" - "\xce\xf5\x5e\x8e\x75\x42\x97\x26", - .klen = 32, - .iv = "\x51\xb9\x12\x80\xea\xde\xd5\x71" - "\x54\x2d\xa6\xc8\x78\xb2\x1b\x8c" - "\x39\x14\x05\xa0\xf3\x10\xec\x41" - "\xff\x01\x95\x84\x2b\x59\x7f\xdb", - .assoc = "\x61\x83\xa0\xe8\x2e\x7d\x7f\xf8" - "\x74\x63\xd2\xec\x76\x7c\x4c\x0d", - .alen = 16, - .ptext = "\x70\x4c\x2f\x50\x72\x1c\x29\x7f" - "\x95\x9a\xff\x10\x75\x45\x7d\x8f", - .plen = 16, - .ctext = "\x2f\xc4\xd8\x0d\xa6\x07\xef\x2e" - "\x6c\xd9\x84\x63\x70\x97\x61\x37" - "\x08\x2f\x16\x90\x9e\x62\x30\x0d" - "\x62\xd5\xc8\xf0\x46\x1a", - .clen = 30, - }, { - .key = "\x7f\x15\xbd\xb8\xb6\xba\xd3\x06" - "\xb5\xd1\x2b\x35\x73\x0e\xad\x10" - "\x98\x25\x8d\x03\xb7\x08\x8e\x54" - "\x90\x23\x3d\x67\x4f\xa1\x36\xfc", - .klen = 32, - .iv = "\x8e\xde\x4c\x20\xfa\x59\x7e\x8d" - "\xd5\x07\x58\x59\x72\xd7\xde\x92" - "\x63\xd6\x10\x24\xf8\xb0\x6e\x5a" - "\xc0\x2e\x74\x5d\x06\xb8\x1e\xb2", - .assoc = "\x9d\xa7\xda\x88\x3e\xf8\x28\x14" - "\xf5\x3e\x85\x7d\x70\xa0\x0f\x13", - .alen = 16, - .ptext = "\xac\x70\x69\xef\x82\x97\xd2\x9b" - "\x15\x74\xb1\xa2\x6f\x69\x3f\x95", - .plen = 16, - .ctext = "\xce\xf3\x17\x87\x49\xc2\x00\x46" - "\xc6\x12\x5c\x8f\x81\x38\xaa\x55" - "\xf8\x67\x75\xf1\x75\xe3\x2a\x24", - .clen = 24, - }, -}; - /* * All key wrapping test vectors taken from * http://csrc.nist.gov/groups/STM/cavp/documents/mac/kwtestvectors.zip -- GitLab From 368b1bdc0a5983c8c908ce2001229e2291eac583 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:08 +0200 Subject: [PATCH 0804/7155] crypto: aegis128 - drop empty TFM init/exit routines TFM init/exit routines are optional, so no need to provide empty ones. Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/aegis128.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crypto/aegis128.c b/crypto/aegis128.c index d78f77fc5dd1..32840d5e7f65 100644 --- a/crypto/aegis128.c +++ b/crypto/aegis128.c @@ -403,22 +403,11 @@ static int crypto_aegis128_decrypt(struct aead_request *req) return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; } -static int crypto_aegis128_init_tfm(struct crypto_aead *tfm) -{ - return 0; -} - -static void crypto_aegis128_exit_tfm(struct crypto_aead *tfm) -{ -} - static struct aead_alg crypto_aegis128_alg = { .setkey = crypto_aegis128_setkey, .setauthsize = crypto_aegis128_setauthsize, .encrypt = crypto_aegis128_encrypt, .decrypt = crypto_aegis128_decrypt, - .init = crypto_aegis128_init_tfm, - .exit = crypto_aegis128_exit_tfm, .ivsize = AEGIS128_NONCE_SIZE, .maxauthsize = AEGIS128_MAX_AUTH_SIZE, -- GitLab From 521cdde758bf331d4e264ef3deef5a26d5ce0b4f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:09 +0200 Subject: [PATCH 0805/7155] crypto: aegis - avoid prerotated AES tables The generic AES code provides four sets of lookup tables, where each set consists of four tables containing the same 32-bit values, but rotated by 0, 8, 16 and 24 bits, respectively. This makes sense for CISC architectures such as x86 which support memory operands, but for other architectures, the rotates are quite cheap, and using all four tables needlessly thrashes the D-cache, and actually hurts rather than helps performance. Since x86 already has its own implementation of AEGIS based on AES-NI instructions, let's tweak the generic implementation towards other architectures, and avoid the prerotated tables, and perform the rotations inline. On ARM Cortex-A53, this results in a ~8% speedup. Acked-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/aegis.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/crypto/aegis.h b/crypto/aegis.h index 41a3090cda8e..3308066ddde0 100644 --- a/crypto/aegis.h +++ b/crypto/aegis.h @@ -10,6 +10,7 @@ #define _CRYPTO_AEGIS_H #include +#include #include #define AEGIS_BLOCK_SIZE 16 @@ -53,16 +54,13 @@ static void crypto_aegis_aesenc(union aegis_block *dst, const union aegis_block *key) { const u8 *s = src->bytes; - const u32 *t0 = crypto_ft_tab[0]; - const u32 *t1 = crypto_ft_tab[1]; - const u32 *t2 = crypto_ft_tab[2]; - const u32 *t3 = crypto_ft_tab[3]; + const u32 *t = crypto_ft_tab[0]; u32 d0, d1, d2, d3; - d0 = t0[s[ 0]] ^ t1[s[ 5]] ^ t2[s[10]] ^ t3[s[15]]; - d1 = t0[s[ 4]] ^ t1[s[ 9]] ^ t2[s[14]] ^ t3[s[ 3]]; - d2 = t0[s[ 8]] ^ t1[s[13]] ^ t2[s[ 2]] ^ t3[s[ 7]]; - d3 = t0[s[12]] ^ t1[s[ 1]] ^ t2[s[ 6]] ^ t3[s[11]]; + d0 = t[s[ 0]] ^ rol32(t[s[ 5]], 8) ^ rol32(t[s[10]], 16) ^ rol32(t[s[15]], 24); + d1 = t[s[ 4]] ^ rol32(t[s[ 9]], 8) ^ rol32(t[s[14]], 16) ^ rol32(t[s[ 3]], 24); + d2 = t[s[ 8]] ^ rol32(t[s[13]], 8) ^ rol32(t[s[ 2]], 16) ^ rol32(t[s[ 7]], 24); + d3 = t[s[12]] ^ rol32(t[s[ 1]], 8) ^ rol32(t[s[ 6]], 16) ^ rol32(t[s[11]], 24); dst->words32[0] = cpu_to_le32(d0) ^ key->words32[0]; dst->words32[1] = cpu_to_le32(d1) ^ key->words32[1]; -- GitLab From 7cdc0ddbf74a19cecb2f0e9efa2cae9d3c665189 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:10 +0200 Subject: [PATCH 0806/7155] crypto: aegis128 - add support for SIMD acceleration Add some plumbing to allow the AEGIS128 code to be built with SIMD routines for acceleration. Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Makefile | 1 + crypto/aegis.h | 14 ++++----- crypto/{aegis128.c => aegis128-core.c} | 42 +++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 11 deletions(-) rename crypto/{aegis128.c => aegis128-core.c} (89%) diff --git a/crypto/Makefile b/crypto/Makefile index 93375e124ff7..362a36f0bd2f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o +aegis128-y := aegis128-core.o obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o obj-$(CONFIG_CRYPTO_DES) += des_generic.o diff --git a/crypto/aegis.h b/crypto/aegis.h index 3308066ddde0..6cb65a497ba2 100644 --- a/crypto/aegis.h +++ b/crypto/aegis.h @@ -35,23 +35,23 @@ static const union aegis_block crypto_aegis_const[2] = { } }, }; -static void crypto_aegis_block_xor(union aegis_block *dst, - const union aegis_block *src) +static inline void crypto_aegis_block_xor(union aegis_block *dst, + const union aegis_block *src) { dst->words64[0] ^= src->words64[0]; dst->words64[1] ^= src->words64[1]; } -static void crypto_aegis_block_and(union aegis_block *dst, - const union aegis_block *src) +static inline void crypto_aegis_block_and(union aegis_block *dst, + const union aegis_block *src) { dst->words64[0] &= src->words64[0]; dst->words64[1] &= src->words64[1]; } -static void crypto_aegis_aesenc(union aegis_block *dst, - const union aegis_block *src, - const union aegis_block *key) +static inline void crypto_aegis_aesenc(union aegis_block *dst, + const union aegis_block *src, + const union aegis_block *key) { const u8 *s = src->bytes; const u32 *t = crypto_ft_tab[0]; diff --git a/crypto/aegis128.c b/crypto/aegis128-core.c similarity index 89% rename from crypto/aegis128.c rename to crypto/aegis128-core.c index 32840d5e7f65..f815b4685156 100644 --- a/crypto/aegis128.c +++ b/crypto/aegis128-core.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #include "aegis.h" @@ -40,6 +42,15 @@ struct aegis128_ops { const u8 *src, unsigned int size); }; +static bool have_simd; + +bool crypto_aegis128_have_simd(void); +void crypto_aegis128_update_simd(struct aegis_state *state, const void *msg); +void crypto_aegis128_encrypt_chunk_simd(struct aegis_state *state, u8 *dst, + const u8 *src, unsigned int size); +void crypto_aegis128_decrypt_chunk_simd(struct aegis_state *state, u8 *dst, + const u8 *src, unsigned int size); + static void crypto_aegis128_update(struct aegis_state *state) { union aegis_block tmp; @@ -55,12 +66,22 @@ static void crypto_aegis128_update(struct aegis_state *state) static void crypto_aegis128_update_a(struct aegis_state *state, const union aegis_block *msg) { + if (have_simd && crypto_simd_usable()) { + crypto_aegis128_update_simd(state, msg); + return; + } + crypto_aegis128_update(state); crypto_aegis_block_xor(&state->blocks[0], msg); } static void crypto_aegis128_update_u(struct aegis_state *state, const void *msg) { + if (have_simd && crypto_simd_usable()) { + crypto_aegis128_update_simd(state, msg); + return; + } + crypto_aegis128_update(state); crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE); } @@ -365,7 +386,7 @@ static void crypto_aegis128_crypt(struct aead_request *req, static int crypto_aegis128_encrypt(struct aead_request *req) { - static const struct aegis128_ops ops = { + const struct aegis128_ops *ops = &(struct aegis128_ops){ .skcipher_walk_init = skcipher_walk_aead_encrypt, .crypt_chunk = crypto_aegis128_encrypt_chunk, }; @@ -375,7 +396,12 @@ static int crypto_aegis128_encrypt(struct aead_request *req) unsigned int authsize = crypto_aead_authsize(tfm); unsigned int cryptlen = req->cryptlen; - crypto_aegis128_crypt(req, &tag, cryptlen, &ops); + if (have_simd && crypto_simd_usable()) + ops = &(struct aegis128_ops){ + .skcipher_walk_init = skcipher_walk_aead_encrypt, + .crypt_chunk = crypto_aegis128_encrypt_chunk_simd }; + + crypto_aegis128_crypt(req, &tag, cryptlen, ops); scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, authsize, 1); @@ -384,7 +410,7 @@ static int crypto_aegis128_encrypt(struct aead_request *req) static int crypto_aegis128_decrypt(struct aead_request *req) { - static const struct aegis128_ops ops = { + const struct aegis128_ops *ops = &(struct aegis128_ops){ .skcipher_walk_init = skcipher_walk_aead_decrypt, .crypt_chunk = crypto_aegis128_decrypt_chunk, }; @@ -398,7 +424,12 @@ static int crypto_aegis128_decrypt(struct aead_request *req) scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, authsize, 0); - crypto_aegis128_crypt(req, &tag, cryptlen, &ops); + if (have_simd && crypto_simd_usable()) + ops = &(struct aegis128_ops){ + .skcipher_walk_init = skcipher_walk_aead_decrypt, + .crypt_chunk = crypto_aegis128_decrypt_chunk_simd }; + + crypto_aegis128_crypt(req, &tag, cryptlen, ops); return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; } @@ -429,6 +460,9 @@ static struct aead_alg crypto_aegis128_alg = { static int __init crypto_aegis128_module_init(void) { + if (IS_ENABLED(CONFIG_CRYPTO_AEGIS128_SIMD)) + have_simd = crypto_aegis128_have_simd(); + return crypto_register_aead(&crypto_aegis128_alg); } -- GitLab From ecc8bc81f2fb3976737ef312f824ba6053aa3590 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:11 +0200 Subject: [PATCH 0807/7155] crypto: aegis128 - provide a SIMD implementation based on NEON intrinsics Provide an accelerated implementation of aegis128 by wiring up the SIMD hooks in the generic driver to an implementation based on NEON intrinsics, which can be compiled to both ARM and arm64 code. This results in a performance of 2.2 cycles per byte on Cortex-A53, which is a performance increase of ~11x compared to the generic code. Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 5 ++ crypto/Makefile | 11 +++ crypto/aegis128-neon-inner.c | 149 +++++++++++++++++++++++++++++++++++ crypto/aegis128-neon.c | 43 ++++++++++ 4 files changed, 208 insertions(+) create mode 100644 crypto/aegis128-neon-inner.c create mode 100644 crypto/aegis128-neon.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 559494bbc0db..2e7f08ba0675 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -306,6 +306,11 @@ config CRYPTO_AEGIS128 help Support for the AEGIS-128 dedicated AEAD algorithm. +config CRYPTO_AEGIS128_SIMD + bool "Support SIMD acceleration for AEGIS-128" + depends on CRYPTO_AEGIS128 && ((ARM || ARM64) && KERNEL_MODE_NEON) + default y + config CRYPTO_AEGIS128_AESNI_SSE2 tristate "AEGIS-128 AEAD algorithm (x86_64 AESNI+SSE2 implementation)" depends on X86 && 64BIT diff --git a/crypto/Makefile b/crypto/Makefile index 362a36f0bd2f..b3e16b4fb414 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -91,6 +91,17 @@ obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o aegis128-y := aegis128-core.o + +ifeq ($(ARCH),arm) +CFLAGS_aegis128-neon-inner.o += -ffreestanding -march=armv7-a -mfloat-abi=softfp -mfpu=crypto-neon-fp-armv8 +aegis128-$(CONFIG_CRYPTO_AEGIS128_SIMD) += aegis128-neon.o aegis128-neon-inner.o +endif +ifeq ($(ARCH),arm64) +CFLAGS_aegis128-neon-inner.o += -ffreestanding -mcpu=generic+crypto +CFLAGS_REMOVE_aegis128-neon-inner.o += -mgeneral-regs-only +aegis128-$(CONFIG_CRYPTO_AEGIS128_SIMD) += aegis128-neon.o aegis128-neon-inner.o +endif + obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o obj-$(CONFIG_CRYPTO_DES) += des_generic.o diff --git a/crypto/aegis128-neon-inner.c b/crypto/aegis128-neon-inner.c new file mode 100644 index 000000000000..26e9450a5833 --- /dev/null +++ b/crypto/aegis128-neon-inner.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Linaro, Ltd. + */ + +#ifdef CONFIG_ARM64 +#include + +#define AES_ROUND "aese %0.16b, %1.16b \n\t aesmc %0.16b, %0.16b" +#else +#include + +#define AES_ROUND "aese.8 %q0, %q1 \n\t aesmc.8 %q0, %q0" +#endif + +#define AEGIS_BLOCK_SIZE 16 + +#include + +void *memcpy(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); + +struct aegis128_state { + uint8x16_t v[5]; +}; + +static struct aegis128_state aegis128_load_state_neon(const void *state) +{ + return (struct aegis128_state){ { + vld1q_u8(state), + vld1q_u8(state + 16), + vld1q_u8(state + 32), + vld1q_u8(state + 48), + vld1q_u8(state + 64) + } }; +} + +static void aegis128_save_state_neon(struct aegis128_state st, void *state) +{ + vst1q_u8(state, st.v[0]); + vst1q_u8(state + 16, st.v[1]); + vst1q_u8(state + 32, st.v[2]); + vst1q_u8(state + 48, st.v[3]); + vst1q_u8(state + 64, st.v[4]); +} + +static uint8x16_t aegis_aes_round(uint8x16_t w) +{ + uint8x16_t z = {}; + + /* + * We use inline asm here instead of the vaeseq_u8/vaesmcq_u8 intrinsics + * to force the compiler to issue the aese/aesmc instructions in pairs. + * This is much faster on many cores, where the instruction pair can + * execute in a single cycle. + */ + asm(AES_ROUND : "+w"(w) : "w"(z)); + return w; +} + +static struct aegis128_state aegis128_update_neon(struct aegis128_state st, + uint8x16_t m) +{ + uint8x16_t t; + + t = aegis_aes_round(st.v[3]); + st.v[3] ^= aegis_aes_round(st.v[2]); + st.v[2] ^= aegis_aes_round(st.v[1]); + st.v[1] ^= aegis_aes_round(st.v[0]); + st.v[0] ^= aegis_aes_round(st.v[4]) ^ m; + st.v[4] ^= t; + + return st; +} + +void crypto_aegis128_update_neon(void *state, const void *msg) +{ + struct aegis128_state st = aegis128_load_state_neon(state); + + st = aegis128_update_neon(st, vld1q_u8(msg)); + + aegis128_save_state_neon(st, state); +} + +void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size) +{ + struct aegis128_state st = aegis128_load_state_neon(state); + uint8x16_t tmp; + + while (size >= AEGIS_BLOCK_SIZE) { + uint8x16_t s = vld1q_u8(src); + + tmp = s ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; + st = aegis128_update_neon(st, s); + vst1q_u8(dst, tmp); + + size -= AEGIS_BLOCK_SIZE; + src += AEGIS_BLOCK_SIZE; + dst += AEGIS_BLOCK_SIZE; + } + + if (size > 0) { + uint8_t buf[AEGIS_BLOCK_SIZE] = {}; + uint8x16_t msg; + + memcpy(buf, src, size); + msg = vld1q_u8(buf); + tmp = msg ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; + st = aegis128_update_neon(st, msg); + vst1q_u8(buf, tmp); + memcpy(dst, buf, size); + } + + aegis128_save_state_neon(st, state); +} + +void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size) +{ + struct aegis128_state st = aegis128_load_state_neon(state); + uint8x16_t tmp; + + while (size >= AEGIS_BLOCK_SIZE) { + tmp = vld1q_u8(src) ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; + st = aegis128_update_neon(st, tmp); + vst1q_u8(dst, tmp); + + size -= AEGIS_BLOCK_SIZE; + src += AEGIS_BLOCK_SIZE; + dst += AEGIS_BLOCK_SIZE; + } + + if (size > 0) { + uint8_t buf[AEGIS_BLOCK_SIZE] = {}; + uint8x16_t msg; + + memcpy(buf, src, size); + msg = vld1q_u8(buf) ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; + vst1q_u8(buf, msg); + memcpy(dst, buf, size); + + memset(buf + size, 0, AEGIS_BLOCK_SIZE - size); + msg = vld1q_u8(buf); + st = aegis128_update_neon(st, msg); + } + + aegis128_save_state_neon(st, state); +} diff --git a/crypto/aegis128-neon.c b/crypto/aegis128-neon.c new file mode 100644 index 000000000000..c1c0a1686f67 --- /dev/null +++ b/crypto/aegis128-neon.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Linaro Ltd + */ + +#include +#include + +#include "aegis.h" + +void crypto_aegis128_update_neon(void *state, const void *msg); +void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size); +void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size); + +bool crypto_aegis128_have_simd(void) +{ + return cpu_have_feature(cpu_feature(AES)); +} + +void crypto_aegis128_update_simd(union aegis_block *state, const void *msg) +{ + kernel_neon_begin(); + crypto_aegis128_update_neon(state, msg); + kernel_neon_end(); +} + +void crypto_aegis128_encrypt_chunk_simd(union aegis_block *state, u8 *dst, + const u8 *src, unsigned int size) +{ + kernel_neon_begin(); + crypto_aegis128_encrypt_chunk_neon(state, dst, src, size); + kernel_neon_end(); +} + +void crypto_aegis128_decrypt_chunk_simd(union aegis_block *state, u8 *dst, + const u8 *src, unsigned int size) +{ + kernel_neon_begin(); + crypto_aegis128_decrypt_chunk_neon(state, dst, src, size); + kernel_neon_end(); +} -- GitLab From 97bcb161995548ad319c78b2533f998a7b92ab4c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Jul 2019 10:55:12 +0200 Subject: [PATCH 0808/7155] crypto: tcrypt - add a speed test for AEGIS128 Reviewed-by: Ondrej Mosnacek Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index ad78ab5b93cb..c578ccd92c57 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -2327,6 +2327,13 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) 0, speed_template_32); break; + case 221: + test_aead_speed("aegis128", ENCRYPT, sec, + NULL, 0, 16, 8, speed_template_16); + test_aead_speed("aegis128", DECRYPT, sec, + NULL, 0, 16, 8, speed_template_16); + break; + case 300: if (alg) { test_hash_speed(alg, sec, generic_hash_speed_template); -- GitLab From cc2a58f14fb88e753fbc38b658e320c3a62d8c47 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Thu, 4 Jul 2019 00:27:08 +0800 Subject: [PATCH 0809/7155] crypto: drivers - Use kmemdup rather than duplicating its implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kmemdup is introduced to duplicate a region of memory in a neat way. Rather than kmalloc/kzalloc + memcpy, which the programmer needs to write the size twice (sometimes lead to mistakes), kmemdup improves readability, leads to smaller code and also reduce the chances of mistakes. Suggestion to use kmemdup rather than using kmalloc/kzalloc + memcpy. Signed-off-by: Fuqian Huang Reviewed-by: Horia Geantă Acked-by: Michael S. Tsirkin Signed-off-by: Herbert Xu --- drivers/crypto/caam/caampkc.c | 11 +++-------- drivers/crypto/virtio/virtio_crypto_algs.c | 4 +--- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 80574106af29..2340f9441a80 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -867,7 +867,7 @@ static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, return ret; /* Copy key in DMA zone */ - rsa_key->e = kzalloc(raw_key.e_sz, GFP_DMA | GFP_KERNEL); + rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_DMA | GFP_KERNEL); if (!rsa_key->e) goto err; @@ -889,8 +889,6 @@ static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, rsa_key->e_sz = raw_key.e_sz; rsa_key->n_sz = raw_key.n_sz; - memcpy(rsa_key->e, raw_key.e, raw_key.e_sz); - return 0; err: caam_rsa_free_key(rsa_key); @@ -971,11 +969,11 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, return ret; /* Copy key in DMA zone */ - rsa_key->d = kzalloc(raw_key.d_sz, GFP_DMA | GFP_KERNEL); + rsa_key->d = kmemdup(raw_key.d, raw_key.d_sz, GFP_DMA | GFP_KERNEL); if (!rsa_key->d) goto err; - rsa_key->e = kzalloc(raw_key.e_sz, GFP_DMA | GFP_KERNEL); + rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_DMA | GFP_KERNEL); if (!rsa_key->e) goto err; @@ -998,9 +996,6 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, rsa_key->e_sz = raw_key.e_sz; rsa_key->n_sz = raw_key.n_sz; - memcpy(rsa_key->d, raw_key.d, raw_key.d_sz); - memcpy(rsa_key->e, raw_key.e, raw_key.e_sz); - caam_rsa_set_priv_key_form(ctx, &raw_key); return 0; diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c b/drivers/crypto/virtio/virtio_crypto_algs.c index 10f266d462d6..42d19205166b 100644 --- a/drivers/crypto/virtio/virtio_crypto_algs.c +++ b/drivers/crypto/virtio/virtio_crypto_algs.c @@ -129,13 +129,11 @@ static int virtio_crypto_alg_ablkcipher_init_session( * Avoid to do DMA from the stack, switch to using * dynamically-allocated for the key */ - uint8_t *cipher_key = kmalloc(keylen, GFP_ATOMIC); + uint8_t *cipher_key = kmemdup(key, keylen, GFP_ATOMIC); if (!cipher_key) return -ENOMEM; - memcpy(cipher_key, key, keylen); - spin_lock(&vcrypto->ctrl_lock); /* Pad ctrl header */ vcrypto->ctrl.header.opcode = -- GitLab From 5c9254ad7ae32a124fb084badd0cb3720f7c49cb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 4 Jul 2019 17:37:57 +0200 Subject: [PATCH 0810/7155] crypto: ux500 - Use spinlock_t instead of struct spinlock For spinlocks the type spinlock_t should be used instead of "struct spinlock". Use spinlock_t for spinlock's definition. Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Herbert Xu --- drivers/crypto/ux500/cryp/cryp.h | 4 ++-- drivers/crypto/ux500/hash/hash_alg.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/ux500/cryp/cryp.h b/drivers/crypto/ux500/cryp/cryp.h index bd89504e8167..8da7f87b339b 100644 --- a/drivers/crypto/ux500/cryp/cryp.h +++ b/drivers/crypto/ux500/cryp/cryp.h @@ -241,12 +241,12 @@ struct cryp_device_data { struct clk *clk; struct regulator *pwr_regulator; int power_status; - struct spinlock ctx_lock; + spinlock_t ctx_lock; struct cryp_ctx *current_ctx; struct klist_node list_node; struct cryp_dma dma; bool power_state; - struct spinlock power_state_spinlock; + spinlock_t power_state_spinlock; bool restore_dev_ctx; }; diff --git a/drivers/crypto/ux500/hash/hash_alg.h b/drivers/crypto/ux500/hash/hash_alg.h index ab2bd00c1c36..7c9bcc15125f 100644 --- a/drivers/crypto/ux500/hash/hash_alg.h +++ b/drivers/crypto/ux500/hash/hash_alg.h @@ -366,10 +366,10 @@ struct hash_device_data { phys_addr_t phybase; struct klist_node list_node; struct device *dev; - struct spinlock ctx_lock; + spinlock_t ctx_lock; struct hash_ctx *current_ctx; bool power_state; - struct spinlock power_state_lock; + spinlock_t power_state_lock; struct regulator *regulator; struct clk *clk; bool restore_dev_state; -- GitLab From 77cdd4efe571345e9c116e65f64a616969e0bc35 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Fri, 5 Jul 2019 08:49:22 +0200 Subject: [PATCH 0811/7155] crypto: inside-secure - add support for authenc(hmac(sha1),cbc(des3_ede)) Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 1 + drivers/crypto/inside-secure/safexcel.h | 1 + .../crypto/inside-secure/safexcel_cipher.c | 89 +++++++++++++++---- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 045919651272..29ea2341f10e 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -875,6 +875,7 @@ static struct safexcel_alg_template *safexcel_algs[] = { &safexcel_alg_authenc_hmac_sha256_cbc_aes, &safexcel_alg_authenc_hmac_sha384_cbc_aes, &safexcel_alg_authenc_hmac_sha512_cbc_aes, + &safexcel_alg_authenc_hmac_sha1_cbc_des3_ede, }; static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv) diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index b73b17dcb8b1..e6ee12a68857 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -735,5 +735,6 @@ extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede; #endif diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index ee3a90f028b5..9c25dd0a1bfd 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -183,14 +183,16 @@ static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, return 0; } -static int safexcel_aead_aes_setkey(struct crypto_aead *ctfm, const u8 *key, - unsigned int len) +static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, + unsigned int len) { struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_ahash_export_state istate, ostate; struct safexcel_crypto_priv *priv = ctx->priv; struct crypto_authenc_keys keys; + u32 flags; + int err; if (crypto_authenc_extractkeys(&keys, key, len) != 0) goto badkey; @@ -199,6 +201,15 @@ static int safexcel_aead_aes_setkey(struct crypto_aead *ctfm, const u8 *key, goto badkey; /* Encryption key */ + if (ctx->alg == SAFEXCEL_3DES) { + flags = crypto_aead_get_flags(ctfm); + err = __des3_verify_key(&flags, keys.enckey); + crypto_aead_set_flags(ctfm, flags); + + if (unlikely(err)) + return err; + } + if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && memcmp(ctx->key, keys.enckey, keys.enckeylen)) ctx->base.needs_inv = true; @@ -1246,7 +1257,7 @@ struct safexcel_alg_template safexcel_alg_ecb_des3_ede = { }, }; -static int safexcel_aead_encrypt(struct aead_request *req) +static int safexcel_aead_encrypt_aes(struct aead_request *req) { struct safexcel_cipher_req *creq = aead_request_ctx(req); @@ -1254,7 +1265,7 @@ static int safexcel_aead_encrypt(struct aead_request *req) CONTEXT_CONTROL_CRYPTO_MODE_CBC, SAFEXCEL_AES); } -static int safexcel_aead_decrypt(struct aead_request *req) +static int safexcel_aead_decrypt_aes(struct aead_request *req) { struct safexcel_cipher_req *creq = aead_request_ctx(req); @@ -1294,9 +1305,9 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_aes = { .type = SAFEXCEL_ALG_TYPE_AEAD, .engines = EIP97IES | EIP197B | EIP197D, .alg.aead = { - .setkey = safexcel_aead_aes_setkey, - .encrypt = safexcel_aead_encrypt, - .decrypt = safexcel_aead_decrypt, + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, .base = { @@ -1329,9 +1340,9 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes = { .type = SAFEXCEL_ALG_TYPE_AEAD, .engines = EIP97IES | EIP197B | EIP197D, .alg.aead = { - .setkey = safexcel_aead_aes_setkey, - .encrypt = safexcel_aead_encrypt, - .decrypt = safexcel_aead_decrypt, + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, .base = { @@ -1364,9 +1375,9 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_aes = { .type = SAFEXCEL_ALG_TYPE_AEAD, .engines = EIP97IES | EIP197B | EIP197D, .alg.aead = { - .setkey = safexcel_aead_aes_setkey, - .encrypt = safexcel_aead_encrypt, - .decrypt = safexcel_aead_decrypt, + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, .base = { @@ -1399,9 +1410,9 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes = { .type = SAFEXCEL_ALG_TYPE_AEAD, .engines = EIP97IES | EIP197B | EIP197D, .alg.aead = { - .setkey = safexcel_aead_aes_setkey, - .encrypt = safexcel_aead_encrypt, - .decrypt = safexcel_aead_decrypt, + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, .base = { @@ -1434,9 +1445,9 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = { .type = SAFEXCEL_ALG_TYPE_AEAD, .engines = EIP97IES | EIP197B | EIP197D, .alg.aead = { - .setkey = safexcel_aead_aes_setkey, - .encrypt = safexcel_aead_encrypt, - .decrypt = safexcel_aead_decrypt, + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, .base = { @@ -1454,3 +1465,43 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = { }, }, }; + +static int safexcel_aead_encrypt_3des(struct aead_request *req) +{ + struct safexcel_cipher_req *creq = aead_request_ctx(req); + + return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT, + CONTEXT_CONTROL_CRYPTO_MODE_CBC, SAFEXCEL_3DES); +} + +static int safexcel_aead_decrypt_3des(struct aead_request *req) +{ + struct safexcel_cipher_req *creq = aead_request_ctx(req); + + return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT, + CONTEXT_CONTROL_CRYPTO_MODE_CBC, SAFEXCEL_3DES); +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_3des, + .decrypt = safexcel_aead_decrypt_3des, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA1_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha1),cbc(des3_ede))", + .cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des3_ede", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha1_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; -- GitLab From baea35e4db17a72145c84a401f70d496c8ebf833 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 17 Jul 2019 11:20:17 +0530 Subject: [PATCH 0812/7155] opp: Not all power-domains are scalable A device may have multiple power-domains and not all of them may be scalable (i.e. support performance states). But dev_pm_opp_attach_genpd() doesn't take that into account currently. Fix that by not verifying the names argument with "power-domain-names" DT property and finding the index into the required-opps array. The names argument will anyway get verified later on when we call dev_pm_domain_attach_by_name(). Fixes: 6319aee10e53 ("opp: Attach genpds to devices from within OPP core") Reported-by: Rajendra Nayak Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index c094d5d20fd7..08b830f84d8c 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1784,12 +1784,15 @@ static void _opp_detach_genpd(struct opp_table *opp_table) * * This helper needs to be called once with a list of all genpd to attach. * Otherwise the original device structure will be used instead by the OPP core. + * + * The order of entries in the names array must match the order in which + * "required-opps" are added in DT. */ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names) { struct opp_table *opp_table; struct device *virt_dev; - int index, ret = -EINVAL; + int index = 0, ret = -EINVAL; const char **name = names; opp_table = dev_pm_opp_get_opp_table(dev); @@ -1815,14 +1818,6 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names goto unlock; while (*name) { - index = of_property_match_string(dev->of_node, - "power-domain-names", *name); - if (index < 0) { - dev_err(dev, "Failed to find power domain: %s (%d)\n", - *name, index); - goto err; - } - if (index >= opp_table->required_opp_count) { dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n", *name, opp_table->required_opp_count, index); @@ -1843,6 +1838,7 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names } opp_table->genpd_virt_devs[index] = virt_dev; + index++; name++; } -- GitLab From 17a8f868ae3e85a173843b1ac65e744e8585bc5a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 8 Jul 2019 11:24:56 +0530 Subject: [PATCH 0813/7155] opp: Return genpd virtual devices from dev_pm_opp_attach_genpd() The cpufreq drivers don't need to do runtime PM operations on the virtual devices returned by dev_pm_domain_attach_by_name() and so the virtual devices weren't shared with the callers of dev_pm_opp_attach_genpd() earlier. But the IO device drivers would want to do that. This patch updates the prototype of dev_pm_opp_attach_genpd() to accept another argument to return the pointer to the array of genpd virtual devices. Reported-by: Rajendra Nayak Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 6 +++++- include/linux/pm_opp.h | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 08b830f84d8c..bdb435822401 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1771,6 +1771,7 @@ static void _opp_detach_genpd(struct opp_table *opp_table) * dev_pm_opp_attach_genpd - Attach genpd(s) for the device and save virtual device pointer * @dev: Consumer device for which the genpd is getting attached. * @names: Null terminated array of pointers containing names of genpd to attach. + * @virt_devs: Pointer to return the array of virtual devices. * * Multiple generic power domains for a device are supported with the help of * virtual genpd devices, which are created for each consumer device - genpd @@ -1788,7 +1789,8 @@ static void _opp_detach_genpd(struct opp_table *opp_table) * The order of entries in the names array must match the order in which * "required-opps" are added in DT. */ -struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names) +struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, + const char **names, struct device ***virt_devs) { struct opp_table *opp_table; struct device *virt_dev; @@ -1842,6 +1844,8 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names name++; } + if (virt_devs) + *virt_devs = opp_table->genpd_virt_devs; mutex_unlock(&opp_table->genpd_virt_dev_lock); return opp_table; diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index af5021f27cb7..5bdceca5125d 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -128,7 +128,7 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name); void dev_pm_opp_put_clkname(struct opp_table *opp_table); struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data)); void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table); -struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names); +struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs); void dev_pm_opp_detach_genpd(struct opp_table *opp_table); int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate); int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); @@ -292,7 +292,7 @@ static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {} -static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names) +static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs) { return ERR_PTR(-ENOTSUPP); } -- GitLab From 71419d84c216cee8da3b19fb843b4242f112cde4 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 25 Jul 2019 12:41:29 +0200 Subject: [PATCH 0814/7155] opp: Add dev_pm_opp_find_level_exact() Since the performance states in the OPP table are unique, implement a dev_pm_opp_find_level_exact() in order to be able to fetch a specific OPP. Signed-off-by: Niklas Cassel [ Viresh: Updated commit log ] Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 48 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_opp.h | 8 +++++++ 2 files changed, 56 insertions(+) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index bdb435822401..0ee8c0133d3e 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -401,6 +401,54 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); +/** + * dev_pm_opp_find_level_exact() - search for an exact level + * @dev: device for which we do this operation + * @level: level to search for + * + * Return: Searches for exact match in the opp table and returns pointer to the + * matching opp if found, else returns ERR_PTR in case of error and should + * be handled using IS_ERR. Error return values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level) +{ + struct opp_table *opp_table; + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) { + int r = PTR_ERR(opp_table); + + dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); + return ERR_PTR(r); + } + + mutex_lock(&opp_table->lock); + + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { + if (temp_opp->level == level) { + opp = temp_opp; + + /* Increment the reference count of OPP */ + dev_pm_opp_get(opp); + break; + } + } + + mutex_unlock(&opp_table->lock); + dev_pm_opp_put_opp_table(opp_table); + + return opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_exact); + static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, unsigned long *freq) { diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 5bdceca5125d..b8197ab014f2 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -96,6 +96,8 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev); struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available); +struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level); struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq); @@ -200,6 +202,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, return ERR_PTR(-ENOTSUPP); } +static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level) +{ + return ERR_PTR(-ENOTSUPP); +} + static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { -- GitLab From 11e1a1648298656722fe206a53e555e2e98668ae Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 3 Jul 2019 15:03:14 +0530 Subject: [PATCH 0815/7155] opp: Don't decrement uninitialized list_kref The list_kref was added for static OPPs and to track their users. The kref is initialized while the static OPPs are added, but removed unconditionally even if the static OPPs were never added. This causes refcount mismatch warnings currently. Fix that by always initializing the kref when the OPP table is first initialized. The refcount is later incremented only for the second user onwards. Fixes: d0e8ae6c26da ("OPP: Create separate kref for static OPPs list") Reported-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 1 + drivers/opp/of.c | 21 ++++----------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 0ee8c0133d3e..9ff0538ee83a 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -988,6 +988,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); INIT_LIST_HEAD(&opp_table->opp_list); kref_init(&opp_table->kref); + kref_init(&opp_table->list_kref); /* Secure the device table modification */ list_add(&opp_table->node, &opp_tables); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index b313aca9894f..698a92c3c17b 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -662,8 +662,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) return 0; } - kref_init(&opp_table->list_kref); - /* We have opp-table node now, iterate over it and add OPPs */ for_each_available_child_of_node(opp_table->np, np) { opp = _opp_add_static_v2(opp_table, dev, np); @@ -672,17 +670,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, ret); of_node_put(np); - goto put_list_kref; + return ret; } else if (opp) { count++; } } /* There should be one of more OPP defined */ - if (WARN_ON(!count)) { - ret = -ENOENT; - goto put_list_kref; - } + if (WARN_ON(!count)) + return -ENOENT; list_for_each_entry(opp, &opp_table->opp_list, node) pstate_count += !!opp->pstate; @@ -691,8 +687,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) if (pstate_count && pstate_count != count) { dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", count, pstate_count); - ret = -ENOENT; - goto put_list_kref; + return -ENOENT; } if (pstate_count) @@ -701,11 +696,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) opp_table->parsed_static_opps = true; return 0; - -put_list_kref: - _put_opp_list_kref(opp_table); - - return ret; } /* Initializes OPP tables based on old-deprecated bindings */ @@ -731,8 +721,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) return -EINVAL; } - kref_init(&opp_table->list_kref); - val = prop->value; while (nr) { unsigned long freq = be32_to_cpup(val++) * 1000; @@ -742,7 +730,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) if (ret) { dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", __func__, freq, ret); - _put_opp_list_kref(opp_table); return ret; } nr -= 2; -- GitLab From 7f93ff73f7c8c8bfa6be33bcc16470b0b44682aa Mon Sep 17 00:00:00 2001 From: "k.konieczny@partner.samsung.com" Date: Fri, 19 Jul 2019 17:05:32 +0200 Subject: [PATCH 0816/7155] opp: core: add regulators enable and disable Add enable regulators to dev_pm_opp_set_regulators() and disable regulators to dev_pm_opp_put_regulators(). Even if bootloader leaves regulators enabled, they should be enabled in kernel in order to increase the reference count. Signed-off-by: Kamil Konieczny Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 9ff0538ee83a..3b7ffd0234e9 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1626,6 +1626,12 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, goto free_regulators; } + ret = regulator_enable(reg); + if (ret < 0) { + regulator_put(reg); + goto free_regulators; + } + opp_table->regulators[i] = reg; } @@ -1639,8 +1645,10 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, return opp_table; free_regulators: - while (i != 0) - regulator_put(opp_table->regulators[--i]); + while (i--) { + regulator_disable(opp_table->regulators[i]); + regulator_put(opp_table->regulators[i]); + } kfree(opp_table->regulators); opp_table->regulators = NULL; @@ -1666,8 +1674,10 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) /* Make sure there are no concurrent readers while updating opp_table */ WARN_ON(!list_empty(&opp_table->opp_list)); - for (i = opp_table->regulator_count - 1; i >= 0; i--) + for (i = opp_table->regulator_count - 1; i >= 0; i--) { + regulator_disable(opp_table->regulators[i]); regulator_put(opp_table->regulators[i]); + } _free_set_opp_data(opp_table); -- GitLab From 518c6880ffc965d59349bf064ff00153cf05f033 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 9 Jul 2019 16:00:12 +0800 Subject: [PATCH 0817/7155] dt-bindings: opp: Support multiple opp-suspend properties Update opp-suspend property's description to support multiple opp-suspend properties defined in DT, the OPP with highest opp-hz and with opp-suspend property present will be used as suspend opp. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Viresh Kumar --- Documentation/devicetree/bindings/opp/opp.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt index 76b6c79604a5..68592271461f 100644 --- a/Documentation/devicetree/bindings/opp/opp.txt +++ b/Documentation/devicetree/bindings/opp/opp.txt @@ -140,8 +140,8 @@ Optional properties: frequency for a short duration of time limited by the device's power, current and thermal limits. -- opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in - the table should have this. +- opp-suspend: Marks the OPP to be used during device suspend. If multiple OPPs + in the table have this, the OPP with highest opp-hz will be used. - opp-supported-hw: This enables us to select only a subset of OPPs from the larger OPP table, based on what version of the hardware we are running on. We -- GitLab From 4527551750e85f9be9296f2b30b19bb257f342e5 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 9 Jul 2019 16:00:13 +0800 Subject: [PATCH 0818/7155] opp: of: Support multiple suspend OPPs defined in DT With property "opp-supported-hw" introduced, the OPP table in DT could be a large OPP table and ONLY a subset of OPPs are available, based on the version of the hardware running on. That introduces restriction of using "opp-suspend" property to define the suspend OPP, as we are NOT sure if the OPP containing "opp-suspend" property is available for the hardware running on, and the of opp core does NOT allow multiple suspend OPPs defined in DT OPP table. To eliminate this restrition, make of opp core allow multiple suspend OPPs defined in DT, and pick the OPP with highest rate and with "opp-suspend" property present to be suspend OPP, it can speed up the suspend/resume process. Signed-off-by: Anson Huang Signed-off-by: Viresh Kumar --- drivers/opp/of.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 698a92c3c17b..1813f5ad5fa2 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -617,9 +617,12 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, /* OPP to select on device suspend */ if (of_property_read_bool(np, "opp-suspend")) { if (opp_table->suspend_opp) { - dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n", - __func__, opp_table->suspend_opp->rate, - new_opp->rate); + /* Pick the OPP with higher rate as suspend OPP */ + if (new_opp->rate > opp_table->suspend_opp->rate) { + opp_table->suspend_opp->suspend = false; + new_opp->suspend = true; + opp_table->suspend_opp = new_opp; + } } else { new_opp->suspend = true; opp_table->suspend_opp = new_opp; -- GitLab From 27a84f76738cc4a9509ec9234a7021de34a88e58 Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Fri, 26 Jul 2019 14:07:47 +0800 Subject: [PATCH 0819/7155] PM / OPP: Correct Documentation about library location OPP library is now located in drivers/opp/ directory. Signed-off-by: Yue Hu Signed-off-by: Viresh Kumar --- Documentation/power/opp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/power/opp.rst b/Documentation/power/opp.rst index b3cf1def9dee..209c7613f5a4 100644 --- a/Documentation/power/opp.rst +++ b/Documentation/power/opp.rst @@ -46,7 +46,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples: ---------------------------------------- OPP library provides a set of helper functions to organize and query the OPP -information. The library is located in drivers/base/power/opp.c and the header +information. The library is located in drivers/opp/ directory and the header is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to -- GitLab From 8cfda0df3a3020454848f55ed23a781169770c99 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Thu, 25 Jul 2019 12:41:30 +0200 Subject: [PATCH 0820/7155] dt-bindings: opp: Re-organise kryo cpufreq to use it for other nvmem based qcom socs The kryo cpufreq driver reads the nvmem cell and uses that data to populate the opps. There are other qcom cpufreq socs like krait which does similar thing. Except for the interpretation of the read data, rest of the driver is same for both the cases. So pull the common things out for reuse. Signed-off-by: Sricharan R [niklas.cassel@linaro.org: split dt-binding into a separate patch and do not rename the compatible string.] Signed-off-by: Niklas Cassel Reviewed-by: Ilia Lin Reviewed-by: Rob Herring Signed-off-by: Viresh Kumar --- .../opp/{kryo-cpufreq.txt => qcom-nvmem-cpufreq.txt} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename Documentation/devicetree/bindings/opp/{kryo-cpufreq.txt => qcom-nvmem-cpufreq.txt} (98%) diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt similarity index 98% rename from Documentation/devicetree/bindings/opp/kryo-cpufreq.txt rename to Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt index c2127b96805a..198441e80ba8 100644 --- a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt +++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt @@ -1,13 +1,13 @@ -Qualcomm Technologies, Inc. KRYO CPUFreq and OPP bindings +Qualcomm Technologies, Inc. NVMEM CPUFreq and OPP bindings =================================== -In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996 -that have KRYO processors, the CPU ferequencies subset and voltage value -of each OPP varies based on the silicon variant in use. +In Certain Qualcomm Technologies, Inc. SoCs like apq8096 and msm8996, +the CPU frequencies subset and voltage value of each OPP varies based on +the silicon variant in use. Qualcomm Technologies, Inc. Process Voltage Scaling Tables defines the voltage and frequency value based on the msm-id in SMEM and speedbin blown in the efuse combination. -The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC +The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC to provide the OPP framework with required information (existing HW bitmap). This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. -- GitLab From a409906003a2b5418e6e60ac2524948ea80819f2 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 25 Jul 2019 12:41:32 +0200 Subject: [PATCH 0821/7155] dt-bindings: opp: qcom-nvmem: Make speedbin related properties optional Not all Qualcomm platforms need to care about the speedbin efuse, nor the value blown into the speedbin efuse. Therefore, make the nvmem-cells and opp-supported-hw properties optional. Signed-off-by: Niklas Cassel Reviewed-by: Ilia Lin Reviewed-by: Rob Herring Signed-off-by: Viresh Kumar --- Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt index 198441e80ba8..c5ea8b90e35d 100644 --- a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt +++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt @@ -20,6 +20,10 @@ In 'cpus' nodes: In 'operating-points-v2' table: - compatible: Should be - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996. + +Optional properties: +-------------------- +In 'operating-points-v2' table: - nvmem-cells: A phandle pointing to a nvmem-cells node representing the efuse registers that has information about the speedbin that is used to select the right frequency/voltage -- GitLab From 690c4509e980e7c9652945f5ae47e90f00f25ffc Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 25 Jul 2019 21:13:28 +0200 Subject: [PATCH 0822/7155] mac80211_hwsim: Fix a typo in the name of function 'mac80211_hswim_he_capab()' This function name should be 'mac80211_hwsim_he_capab()' (s wand w switched) to be consistent with the rest of the file. Fix and use it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190725191328.18010-1-christophe.jaillet@wanadoo.fr Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 519b4ee88c5c..c4611eb4eb86 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2594,7 +2594,7 @@ static const struct ieee80211_sband_iftype_data he_capa_5ghz = { }, }; -static void mac80211_hswim_he_capab(struct ieee80211_supported_band *sband) +static void mac80211_hwsim_he_capab(struct ieee80211_supported_band *sband) { if (sband->band == NL80211_BAND_2GHZ) sband->iftype_data = @@ -2897,7 +2897,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, sband->ht_cap.mcs.rx_mask[1] = 0xff; sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - mac80211_hswim_he_capab(sband); + mac80211_hwsim_he_capab(sband); hw->wiphy->bands[band] = sband; } -- GitLab From 5db4c4b9559f8cddd5f7f74e58c7b8f172120e6d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 23 Jul 2019 21:00:01 +0300 Subject: [PATCH 0823/7155] mac80211: pass the vif to cancel_remain_on_channel This low level driver can find it useful to get the vif when a remain on channel session is cancelled. iwlwifi will need this soon. Signed-off-by: Emmanuel Grumbach Link: https://lore.kernel.org/r/20190723180001.5828-1-emmanuel.grumbach@intel.com Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- drivers/net/wireless/ath/ath9k/main.c | 3 ++- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 ++- drivers/net/wireless/mac80211_hwsim.c | 3 ++- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 3 ++- drivers/net/wireless/ti/wlcore/main.c | 3 ++- include/net/mac80211.h | 3 ++- net/mac80211/driver-ops.h | 8 +++++--- net/mac80211/offchannel.c | 5 +++-- net/mac80211/trace.h | 7 ++++--- 10 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0606416dc971..12dad659bf68 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6970,7 +6970,8 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, return ret; } -static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) +static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath10k *ar = hw->priv; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f23cb2f3d296..34121fbf32e3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2392,7 +2392,8 @@ static int ath9k_remain_on_channel(struct ieee80211_hw *hw, return ret; } -static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw) +static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 55cd49ccbf0b..e63623251d61 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4010,7 +4010,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, return ret; } -static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw) +static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c4611eb4eb86..0869f924e60c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2216,7 +2216,8 @@ static int mac80211_hwsim_roc(struct ieee80211_hw *hw, return 0; } -static int mac80211_hwsim_croc(struct ieee80211_hw *hw) +static int mac80211_hwsim_croc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct mac80211_hwsim_data *hwsim = hw->priv; diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 49df3bb08d41..ce5e92d82efc 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1818,7 +1818,8 @@ static int rsi_mac80211_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return status; } -static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw) +static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index b74dc8bc9755..547ad538d8b6 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5749,7 +5749,8 @@ static void wlcore_roc_complete_work(struct work_struct *work) ieee80211_remain_on_channel_expired(wl->hw); } -static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw) +static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d26da013f7c0..e39bf85ae4c2 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3914,7 +3914,8 @@ struct ieee80211_ops { struct ieee80211_channel *chan, int duration, enum ieee80211_roc_type type); - int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); + int (*cancel_remain_on_channel)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); void (*get_ringparam)(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index c2d8b5451a5e..2c9b3eb8b652 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -692,14 +692,16 @@ static inline int drv_remain_on_channel(struct ieee80211_local *local, return ret; } -static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) +static inline int +drv_cancel_remain_on_channel(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) { int ret; might_sleep(); - trace_drv_cancel_remain_on_channel(local); - ret = local->ops->cancel_remain_on_channel(&local->hw); + trace_drv_cancel_remain_on_channel(local, sdata); + ret = local->ops->cancel_remain_on_channel(&local->hw, &sdata->vif); trace_drv_return_int(local, ret); return ret; diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 60ef8972b254..c710504ccf1a 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -8,6 +8,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2009 Johannes Berg + * Copyright (C) 2019 Intel Corporation */ #include #include @@ -732,7 +733,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, } if (local->ops->remain_on_channel) { - ret = drv_cancel_remain_on_channel(local); + ret = drv_cancel_remain_on_channel(local, roc->sdata); if (WARN_ON_ONCE(ret)) { mutex_unlock(&local->mtx); return ret; @@ -991,7 +992,7 @@ void ieee80211_roc_purge(struct ieee80211_local *local, if (roc->started) { if (local->ops->remain_on_channel) { /* can race, so ignore return value */ - drv_cancel_remain_on_channel(local); + drv_cancel_remain_on_channel(local, sdata); ieee80211_roc_notify_destroy(roc); } else { roc->abort = true; diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3bb4459b52c7..4768322dc202 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -1242,9 +1242,10 @@ TRACE_EVENT(drv_remain_on_channel, ) ); -DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel, - TP_PROTO(struct ieee80211_local *local), - TP_ARGS(local) +DEFINE_EVENT(local_sdata_evt, drv_cancel_remain_on_channel, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_set_ringparam, -- GitLab From 49175fe63ee8433dffeb64aee685bf8d439d5698 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 16:26:56 +0200 Subject: [PATCH 0824/7155] iwlwifi: dvm: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. This driver was saving the debugfs file away to be removed at a later time. However, the 80211 core would delete the whole directory that the debugfs files are created in, after it asks the driver to do the deletion, so just rely on the 80211 core to do all of the cleanup for us, making us not need to keep a pointer to the dentries around at all. This cleans up the structure of the driver data a bit and makes the code a tiny bit smaller. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190612142658.12792-3-gregkh@linuxfoundation.org Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/dvm/rs.c | 29 ++++++--------------- drivers/net/wireless/intel/iwlwifi/dvm/rs.h | 4 --- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index b1e5d64ca60d..74229fcb63a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -3256,28 +3256,16 @@ static void rs_add_debugfs(void *priv, void *priv_sta, struct dentry *dir) { struct iwl_lq_sta *lq_sta = priv_sta; - lq_sta->rs_sta_dbgfs_scale_table_file = - debugfs_create_file("rate_scale_table", 0600, dir, - lq_sta, &rs_sta_dbgfs_scale_table_ops); - lq_sta->rs_sta_dbgfs_stats_table_file = - debugfs_create_file("rate_stats_table", 0400, dir, - lq_sta, &rs_sta_dbgfs_stats_table_ops); - lq_sta->rs_sta_dbgfs_rate_scale_data_file = - debugfs_create_file("rate_scale_data", 0400, dir, - lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); - lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = - debugfs_create_u8("tx_agg_tid_enable", 0600, dir, - &lq_sta->tx_agg_tid_en); -} + debugfs_create_file("rate_scale_table", 0600, dir, lq_sta, + &rs_sta_dbgfs_scale_table_ops); + debugfs_create_file("rate_stats_table", 0400, dir, lq_sta, + &rs_sta_dbgfs_stats_table_ops); + debugfs_create_file("rate_scale_data", 0400, dir, lq_sta, + &rs_sta_dbgfs_rate_scale_data_ops); + debugfs_create_u8("tx_agg_tid_enable", 0600, dir, + &lq_sta->tx_agg_tid_en); -static void rs_remove_debugfs(void *priv, void *priv_sta) -{ - struct iwl_lq_sta *lq_sta = priv_sta; - debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); } #endif @@ -3303,7 +3291,6 @@ static const struct rate_control_ops rs_ops = { .free_sta = rs_free_sta, #ifdef CONFIG_MAC80211_DEBUGFS .add_sta_debugfs = rs_add_debugfs, - .remove_sta_debugfs = rs_remove_debugfs, #endif }; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h index b7a1854cd202..68a840d739e8 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h @@ -356,10 +356,6 @@ struct iwl_lq_sta { struct iwl_traffic_load load[IWL_MAX_TID_COUNT]; u8 tx_agg_tid_en; #ifdef CONFIG_MAC80211_DEBUGFS - struct dentry *rs_sta_dbgfs_scale_table_file; - struct dentry *rs_sta_dbgfs_stats_table_file; - struct dentry *rs_sta_dbgfs_rate_scale_data_file; - struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; u32 dbg_fixed_rate; #endif struct iwl_priv *drv; -- GitLab From 09e1946cb7590d1a7a314534420f05c7abdf1f55 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 16:26:57 +0200 Subject: [PATCH 0825/7155] iwlwifi: mvm: remove unused .remove_sta_debugfs callback The .remove_sta_debugfs callback was not doing anything in this driver, so remove it as it is not needed. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190612142658.12792-4-gregkh@linuxfoundation.org Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 8c9069f28a58..009e72abcd51 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -4093,10 +4093,6 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta, MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, 0600); } - -void rs_remove_sta_debugfs(void *mvm, void *mvm_sta) -{ -} #endif /* @@ -4124,7 +4120,6 @@ static const struct rate_control_ops rs_mvm_ops_drv = { .rate_update = rs_drv_rate_update, #ifdef CONFIG_MAC80211_DEBUGFS .add_sta_debugfs = rs_drv_add_sta_debugfs, - .remove_sta_debugfs = rs_remove_sta_debugfs, #endif .capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW, }; -- GitLab From 612fcfd9b31f08858d2a2e1279adda367e1ade00 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 16:26:58 +0200 Subject: [PATCH 0826/7155] mac80211: remove unused and unneeded remove_sta_debugfs callback The remove_sta_debugfs callback in struct rate_control_ops is no longer used by any driver, as there is no need for it (the debugfs directory is already removed recursivly by the mac80211 core.) Because no one needs it, just remove it to keep anyone else from accidentally using it in the future. Cc: Johannes Berg Cc: "David S. Miller" Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190612142658.12792-5-gregkh@linuxfoundation.org Signed-off-by: Johannes Berg --- include/net/mac80211.h | 1 - net/mac80211/rate.h | 9 --------- net/mac80211/sta_info.c | 1 - 3 files changed, 11 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e39bf85ae4c2..6cc5b25edf9d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5946,7 +5946,6 @@ struct rate_control_ops { void (*add_sta_debugfs)(void *priv, void *priv_sta, struct dentry *dir); - void (*remove_sta_debugfs)(void *priv, void *priv_sta); u32 (*get_expected_throughput)(void *priv_sta); }; diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5d5348bc41ec..5397c6dad056 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -60,15 +60,6 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta) #endif } -static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) -{ -#ifdef CONFIG_MAC80211_DEBUGFS - struct rate_control_ref *ref = sta->rate_ctrl; - if (ref && ref->ops->remove_sta_debugfs) - ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); -#endif -} - void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata); /* Get a reference to the rate control algorithm. If `name' is NULL, get the diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 95eb8220e2e4..fb6614f57cbc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1065,7 +1065,6 @@ static void __sta_info_destroy_part2(struct sta_info *sta) cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); kfree(sinfo); - rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); cleanup_single_sta(sta); -- GitLab From a11e2f85481c2f08b55c06467445602a2330ee5b Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 17 Jun 2019 11:19:01 +0200 Subject: [PATCH 0827/7155] lib80211: use crypto API ccm(aes) transform for CCMP processing Instead of open coding the CCM aead mode in the driver, and invoking the AES block cipher block by block, use a ccm(aes) aead transform which already encapsulates this functionality. This is a cleaner use of the crypto API, and permits optimized implementations to be used, which are typically much faster and deal more efficiently with the SIMD register file, which usually needs to be preserved/restored in order to use special AES instructions. Signed-off-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20190617091901.7063-1-ard.biesheuvel@linaro.org Signed-off-by: Johannes Berg --- net/wireless/Kconfig | 2 + net/wireless/lib80211_crypt_ccmp.c | 197 +++++++++++++---------------- 2 files changed, 87 insertions(+), 112 deletions(-) diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 67f8360dfcee..63cf7131f601 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -217,6 +217,8 @@ config LIB80211_CRYPT_WEP config LIB80211_CRYPT_CCMP tristate + select CRYPTO_AES + select CRYPTO_CCM config LIB80211_CRYPT_TKIP tristate diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index 7e8ff9d7dcfa..6a5f08f7491e 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -48,20 +49,13 @@ struct lib80211_ccmp_data { int key_idx; - struct crypto_cipher *tfm; + struct crypto_aead *tfm; /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; + u8 tx_aad[2 * AES_BLOCK_LEN]; + u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static inline void lib80211_ccmp_aes_encrypt(struct crypto_cipher *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one(tfm, ct, pt); -} - static void *lib80211_ccmp_init(int key_idx) { struct lib80211_ccmp_data *priv; @@ -71,7 +65,7 @@ static void *lib80211_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = crypto_alloc_cipher("aes", 0, 0); + priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { priv->tfm = NULL; goto fail; @@ -82,7 +76,7 @@ static void *lib80211_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher(priv->tfm); + crypto_free_aead(priv->tfm); kfree(priv); } @@ -93,25 +87,16 @@ static void lib80211_ccmp_deinit(void *priv) { struct lib80211_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher(_priv->tfm); + crypto_free_aead(_priv->tfm); kfree(priv); } -static inline void xor_block(u8 * b, u8 * a, size_t len) -{ - int i; - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - -static void ccmp_init_blocks(struct crypto_cipher *tfm, - struct ieee80211_hdr *hdr, - u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) +static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr, + const u8 *pn, u8 *iv, u8 *aad) { u8 *pos, qc = 0; size_t aad_len; int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; a4_included = ieee80211_has_a4(hdr->frame_control); qc_included = ieee80211_is_data_qos(hdr->frame_control); @@ -127,17 +112,19 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm, aad_len += 2; } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from the same vector. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. + */ + iv[0] = 0x1; + + /* Nonce: QC | A2 | PN */ + iv[1] = qc; + memcpy(iv + 2, hdr->addr2, ETH_ALEN); + memcpy(iv + 8, pn, CCMP_PN_LEN); /* AAD: * FC with bits 4..6 and 11..13 masked to zero; 14 is always one @@ -147,31 +134,20 @@ static void ccmp_init_blocks(struct crypto_cipher *tfm, * QC (if present) */ pos = (u8 *) hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + aad[0] = pos[0] & 0x8f; + aad[1] = pos[1] & 0xc7; + memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); pos = (u8 *) & hdr->seq_ctrl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); + aad[20] = pos[0] & 0x0f; + aad[21] = 0; /* all bits masked */ + memset(aad + 22, 0, 8); if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); + memcpy(aad + 22, hdr->addr4, ETH_ALEN); if (qc_included) { - aad[a4_included ? 30 : 24] = qc; + aad[a4_included ? 28 : 22] = qc; /* rest of QC masked */ } - - /* Start with the first block and AAD */ - lib80211_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - lib80211_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - lib80211_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = b0[15] = 0; - lib80211_ccmp_aes_encrypt(tfm, b0, s0); + return aad_len; } static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, @@ -214,13 +190,13 @@ static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_ccmp_data *key = priv; - int data_len, i, blocks, last, len; - u8 *pos, *mic; struct ieee80211_hdr *hdr; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->tx_aad; + u8 iv[AES_BLOCK_LEN]; + int len, data_len, aad_len; + int ret; if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len) return -1; @@ -230,31 +206,28 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) if (len < 0) return -1; - pos = skb->data + hdr_len + CCMP_HDR_LEN; + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + hdr = (struct ieee80211_hdr *)skb->data; - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - lib80211_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - lib80211_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } + aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); - mic = skb_put(skb, CCMP_MIC_LEN); - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; + skb_put(skb, CCMP_MIC_LEN); - return 0; + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, + data_len + CCMP_MIC_LEN); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_encrypt(req); + aead_request_free(req); + + return ret; } /* @@ -283,13 +256,13 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) struct lib80211_ccmp_data *key = priv; u8 keyidx, *pos; struct ieee80211_hdr *hdr; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->rx_aad; + u8 iv[AES_BLOCK_LEN]; u8 pn[6]; - int i, blocks, last, len; - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; + int aad_len, ret; + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { key->dot11RSNAStatsCCMPFormatErrors++; @@ -337,28 +310,26 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -4; } - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - lib80211_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - lib80211_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { - net_dbg_ratelimited("CCMP: decrypt failed: STA=%pM\n", - hdr->addr2); + aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], pos, data_len); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_decrypt(req); + aead_request_free(req); + + if (ret) { + net_dbg_ratelimited("CCMP: decrypt failed: STA=%pM (%d)\n", + hdr->addr2, ret); key->dot11RSNAStatsCCMPDecryptErrors++; return -5; } @@ -377,7 +348,7 @@ static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) { struct lib80211_ccmp_data *data = priv; int keyidx; - struct crypto_cipher *tfm = data->tfm; + struct crypto_aead *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); @@ -394,7 +365,9 @@ static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) data->rx_pn[4] = seq[1]; data->rx_pn[5] = seq[0]; } - crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN); + if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) || + crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN)) + return -1; } else if (len == 0) data->key_set = 0; else -- GitLab From fb0e76abe34bd67756dbdf4d5982b7dc54afa1d8 Mon Sep 17 00:00:00 2001 From: Erik Stromdahl Date: Mon, 17 Jun 2019 22:01:39 +0200 Subject: [PATCH 0828/7155] mac80211: add tx dequeue function for process context Since ieee80211_tx_dequeue() must not be called with softirqs enabled (i.e. from process context without proper disable of bottom halves), we add a wrapper that disables bottom halves before calling ieee80211_tx_dequeue() The new function is named ieee80211_tx_dequeue_ni() just as all other from-process-context versions found in mac80211. The documentation of ieee80211_tx_dequeue() is also updated so it mentions that the function should not be called from process context. Signed-off-by: Erik Stromdahl Link: https://lore.kernel.org/r/20190617200140.6189-1-erik.stromdahl@gmail.com Signed-off-by: Johannes Berg --- include/net/mac80211.h | 26 ++++++++++++++++++++++++++ net/mac80211/tx.c | 2 ++ 2 files changed, 28 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 6cc5b25edf9d..fbe1c29e3349 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -6234,10 +6234,36 @@ void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid); * but for the duration of the frame handling. * However, also note that while in the wake_tx_queue() method, * rcu_read_lock() is already held. + * + * softirqs must also be disabled when this function is called. + * In process context, use ieee80211_tx_dequeue_ni() instead. */ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); +/** + * ieee80211_tx_dequeue_ni - dequeue a packet from a software tx queue + * (in process context) + * + * Like ieee80211_tx_dequeue() but can be called in process context + * (internally disables bottom halves). + * + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @txq: pointer obtained from station or virtual interface, or from + * ieee80211_next_txq() + */ +static inline struct sk_buff *ieee80211_tx_dequeue_ni(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct sk_buff *skb; + + local_bh_disable(); + skb = ieee80211_tx_dequeue(hw, txq); + local_bh_enable(); + + return skb; +} + /** * ieee80211_next_txq - get next tx queue to pull packets from * diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f13eb2f61ccf..fb8870d9eba3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3546,6 +3546,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, ieee80211_tx_result r; struct ieee80211_vif *vif = txq->vif; + WARN_ON_ONCE(softirq_count() == 0); + begin: spin_lock_bh(&fq->lock); -- GitLab From c627c58acdc48055a9e4d40d6f9f1b434222a68d Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:48 +0800 Subject: [PATCH 0829/7155] spi: sprd: adi: Remove redundant address bits setting The ADI default transfer address bits is 12bit on Spreadtrum SC9860 platform, thus there is no need to set again, remove it. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/3cb57b8aadb7747a9f833e9b4fe8596ba738d9f6.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index df5960bddfe6..11880db08ce9 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -380,9 +380,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi) const __be32 *list; u32 tmp; - /* Address bits select default 12 bits */ - writel_relaxed(0, sadi->base + REG_ADI_CTRL0); - /* Set all channels as default priority */ writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL); writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH); -- GitLab From cc6b3431b36a1109d44cb8e4015cc68dddc75208 Mon Sep 17 00:00:00 2001 From: Chenxu Wei Date: Fri, 26 Jul 2019 15:20:49 +0800 Subject: [PATCH 0830/7155] spi: sprd: adi: Add a reset reason for TOS panic Add a new reset flag to indicate the reset reason is caused by TOS. Signed-off-by: Chenxu Wei Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/97583aad1f2b849d69b4e76e8d29113da72a9fff.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 11880db08ce9..0b3f23ad6479 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -86,6 +86,7 @@ #define BIT_WDG_EN BIT(2) /* Definition of PMIC reset status register */ +#define HWRST_STATUS_SECURITY 0x02 #define HWRST_STATUS_RECOVERY 0x20 #define HWRST_STATUS_NORMAL 0x40 #define HWRST_STATUS_ALARM 0x50 @@ -336,6 +337,8 @@ static int sprd_adi_restart_handler(struct notifier_block *this, reboot_mode = HWRST_STATUS_IQMODE; else if (!strncmp(cmd, "sprdisk", 7)) reboot_mode = HWRST_STATUS_SPRDISK; + else if (!strncmp(cmd, "tospanic", 8)) + reboot_mode = HWRST_STATUS_SECURITY; else reboot_mode = HWRST_STATUS_NORMAL; -- GitLab From 9d9aa1cc91d68e2140e5948c15947b8254e008e2 Mon Sep 17 00:00:00 2001 From: Sherry Zong Date: Fri, 26 Jul 2019 15:20:50 +0800 Subject: [PATCH 0831/7155] spi: sprd: adi: Add a reset reason for factory test mode Add a new reset flag to indicate that the system need enter factory test mode after restarting system. Signed-off-by: Sherry Zong Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/8ae5651e876b527920ff878721a8a8ef47b099ac.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 0b3f23ad6479..509ce6943adc 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -98,6 +98,7 @@ #define HWRST_STATUS_AUTODLOADER 0xa0 #define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_SPRDISK 0xc0 +#define HWRST_STATUS_FACTORYTEST 0xe0 /* Use default timeout 50 ms that converts to watchdog values */ #define WDG_LOAD_VAL ((50 * 1000) / 32768) @@ -339,6 +340,8 @@ static int sprd_adi_restart_handler(struct notifier_block *this, reboot_mode = HWRST_STATUS_SPRDISK; else if (!strncmp(cmd, "tospanic", 8)) reboot_mode = HWRST_STATUS_SECURITY; + else if (!strncmp(cmd, "factorytest", 11)) + reboot_mode = HWRST_STATUS_FACTORYTEST; else reboot_mode = HWRST_STATUS_NORMAL; -- GitLab From e6d722ca09c1eebba5660e58b6bcac30c1ccc7ca Mon Sep 17 00:00:00 2001 From: Sherry Zong Date: Fri, 26 Jul 2019 15:20:51 +0800 Subject: [PATCH 0832/7155] spi: sprd: adi: Add a reset reason for watchdog mode When the system was rebooted by watchdog, now we did not save the watchdog reset mode which will make system enter a incorrect mode after rebooting. Thus we should set the watchdog reset mode as default when opening the watchdog configuration, that means if the system was rebooted by other reason through the restart_handler(), then we will clear the default watchdog reset mode to save the correct reset mode. Signed-off-by: Sherry Zong Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/1563f3de43c6c2262d597a25d6138b5de61ea23d.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 509ce6943adc..0d767eb67fcf 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -99,6 +99,7 @@ #define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_SPRDISK 0xc0 #define HWRST_STATUS_FACTORYTEST 0xe0 +#define HWRST_STATUS_WATCHDOG 0xf0 /* Use default timeout 50 ms that converts to watchdog values */ #define WDG_LOAD_VAL ((50 * 1000) / 32768) @@ -309,6 +310,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, return 0; } +static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi) +{ +#ifdef CONFIG_SPRD_WATCHDOG + u32 val; + + /* Set default watchdog reboot mode */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val |= HWRST_STATUS_WATCHDOG; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); +#endif +} + static int sprd_adi_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd) { @@ -347,6 +360,7 @@ static int sprd_adi_restart_handler(struct notifier_block *this, /* Record the reboot mode */ sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val &= ~HWRST_STATUS_WATCHDOG; val |= reboot_mode; sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); @@ -475,6 +489,7 @@ static int sprd_adi_probe(struct platform_device *pdev) } sprd_adi_hw_init(sadi); + sprd_adi_set_wdt_rst_mode(sadi); ctlr->dev.of_node = pdev->dev.of_node; ctlr->bus_num = pdev->id; -- GitLab From f9adf61e983f5d03334d841bc30f0e967a340b37 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:52 +0800 Subject: [PATCH 0833/7155] spi: sprd: adi: Change hwlock to be optional Now Spreadtrum ADI controller supplies multiple master accessing channel to support multiple subsystems accessing, instead of using a hardware spinlock to synchronize between the multiple subsystems. To keep backward compatibility, we should change the hardware spinlock to be optional. Moreover change to use of_hwspin_lock_get_id() function which return -ENOENT error number to indicate no hwlock support. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/2abe7dcf210e4197f8c5ece7fc6d6cc1eda8c655.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 68 +++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 0d767eb67fcf..9a051286f120 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -165,14 +165,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) int read_timeout = ADI_READ_TIMEOUT; unsigned long flags; u32 val, rd_addr; - int ret; - - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + int ret = 0; + + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } /* @@ -219,7 +221,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) *read_val = val & RD_VALUE_MASK; out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -230,12 +233,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) unsigned long flags; int ret; - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } ret = sprd_adi_drain_fifo(sadi); @@ -261,7 +266,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) } out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -476,16 +482,26 @@ static int sprd_adi_probe(struct platform_device *pdev) sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET; sadi->ctlr = ctlr; sadi->dev = &pdev->dev; - ret = of_hwspin_lock_get_id_byname(np, "adi"); - if (ret < 0) { - dev_err(&pdev->dev, "can not get the hardware spinlock\n"); - goto put_ctlr; - } - - sadi->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret); - if (!sadi->hwlock) { - ret = -ENXIO; - goto put_ctlr; + ret = of_hwspin_lock_get_id(np, 0); + if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) { + sadi->hwlock = + devm_hwspin_lock_request_specific(&pdev->dev, ret); + if (!sadi->hwlock) { + ret = -ENXIO; + goto put_ctlr; + } + } else { + switch (ret) { + case -ENOENT: + dev_info(&pdev->dev, "no hardware spinlock supplied\n"); + break; + default: + dev_err(&pdev->dev, + "failed to find hwlock id, %d\n", ret); + /* fall-through */ + case -EPROBE_DEFER: + goto put_ctlr; + } } sprd_adi_hw_init(sadi); -- GitLab From 5d29050b409d961df34a7290270ba53f0c025152 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sat, 29 Jun 2019 21:50:12 +0200 Subject: [PATCH 0834/7155] mac80211_hwsim: Extended Key ID API update Prepare hwsim Extended Key ID support for a mac80211 API change. The mac80211 flag IEEE80211_HW_EXT_KEY_ID_NATIVE is being replaced by NL80211_EXT_FEATURE_EXT_KEY_ID which only must be set by drivers when they support HW crypto. This reverts commit cfe7007a9b4c ("mac80211_hwsim: Extended Key ID support"). Signed-off-by: Alexander Wetzel Link: https://lore.kernel.org/r/20190629195015.19680-1-alexander@wetzel-home.de Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 0869f924e60c..23692229dacf 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2806,12 +2806,6 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, TDLS_WIDER_BW); - - /* We only have SW crypto and only implement the A-MPDU API - * (but don't really build A-MPDUs) so can have extended key - * support - */ - ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE); if (rctbl) ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); -- GitLab From 70f69f481b87da0614360e57e05a3ba962d60439 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 26 Jul 2019 15:20:53 +0800 Subject: [PATCH 0835/7155] spi: sprd: Change the hwlock support to be optional No need to add hardware spinlock proctection due to add multiple msater channel, so change it to be optional in documentation. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/23d51f5d9c9cc647ad0c5a1fb950d3d9fb9c1303.1564125131.git.baolin.wang@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-sprd-adi.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt index 8de589b376ce..2567c829e2dc 100644 --- a/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt +++ b/Documentation/devicetree/bindings/spi/spi-sprd-adi.txt @@ -25,18 +25,23 @@ data by ADI software channels at the same time, or two parallel routine of setti ADI registers will make ADI controller registers chaos to lead incorrect results. Then we need one hardware spinlock to synchronize between the multiple subsystems. +The new version ADI controller supplies multiple master channels for different +subsystem accessing, that means no need to add hardware spinlock to synchronize, +thus change the hardware spinlock support to be optional to keep backward +compatibility. + Required properties: - compatible: Should be "sprd,sc9860-adi". - reg: Offset and length of ADI-SPI controller register space. -- hwlocks: Reference to a phandle of a hwlock provider node. -- hwlock-names: Reference to hwlock name strings defined in the same order - as the hwlocks, should be "adi". - #address-cells: Number of cells required to define a chip select address on the ADI-SPI bus. Should be set to 1. - #size-cells: Size of cells required to define a chip select address size on the ADI-SPI bus. Should be set to 0. Optional properties: +- hwlocks: Reference to a phandle of a hwlock provider node. +- hwlock-names: Reference to hwlock name strings defined in the same order + as the hwlocks, should be "adi". - sprd,hw-channels: This is an array of channel values up to 49 channels. The first value specifies the hardware channel id which is used to transfer data triggered by hardware automatically, and the second -- GitLab From 3e47bf1ca4c363ba8b1f99c4c3dcda13d2979954 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sat, 29 Jun 2019 21:50:13 +0200 Subject: [PATCH 0836/7155] mac80211: Simplify Extended Key ID API 1) Drop IEEE80211_HW_EXT_KEY_ID_NATIVE and let drivers directly set the NL80211_EXT_FEATURE_EXT_KEY_ID flag. 2) Drop IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT and simply assume all drivers are unable to handle A-MPDU key borders. The new Extended Key ID API now requires all mac80211 drivers to set NL80211_EXT_FEATURE_EXT_KEY_ID when they implement set_key() and can handle Extended Key ID. For drivers not providing set_key() mac80211 itself enables Extended Key ID support, using the internal SW crypto services. Signed-off-by: Alexander Wetzel Link: https://lore.kernel.org/r/20190629195015.19680-2-alexander@wetzel-home.de Signed-off-by: Johannes Berg --- include/net/mac80211.h | 8 -------- net/mac80211/debugfs.c | 2 -- net/mac80211/key.c | 18 ++++++++---------- net/mac80211/main.c | 18 ++++++------------ 4 files changed, 14 insertions(+), 32 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fbe1c29e3349..58941893a13f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2268,12 +2268,6 @@ struct ieee80211_txq { * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID * only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set. * - * @IEEE80211_HW_EXT_KEY_ID_NATIVE: Driver and hardware are supporting Extended - * Key ID and can handle two unicast keys per station for Rx and Tx. - * - * @IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT: The card/driver can't handle - * active Tx A-MPDU sessions with Extended Key IDs during rekey. - * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2325,8 +2319,6 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN, IEEE80211_HW_SUPPORTS_MULTI_BSSID, IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, - IEEE80211_HW_EXT_KEY_ID_NATIVE, - IEEE80211_HW_NO_AMPDU_KEYBORDER_SUPPORT, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 2e7f75938c51..47435f57e086 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -271,8 +271,6 @@ static const char *hw_flag_names[] = { FLAG(TX_STATUS_NO_AMPDU_LEN), FLAG(SUPPORTS_MULTI_BSSID), FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), - FLAG(EXT_KEY_ID_NATIVE), - FLAG(NO_AMPDU_KEYBORDER_SUPPORT), #undef FLAG }; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index dd60f6428049..92c3affb0eb0 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -270,8 +270,7 @@ int ieee80211_set_tx_key(struct ieee80211_key *key) sta->ptk_idx = key->conf.keyidx; - if (ieee80211_hw_check(&local->hw, NO_AMPDU_KEYBORDER_SUPPORT)) - clear_sta_flag(sta, WLAN_STA_BLOCK_BA); + clear_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_check_fast_xmit(sta); return 0; @@ -289,16 +288,15 @@ static void ieee80211_pairwise_rekey(struct ieee80211_key *old, if (new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX) { /* Extended Key ID key install, initial one or rekey */ - if (sta->ptk_idx != INVALID_PTK_KEYIDX && - ieee80211_hw_check(&local->hw, - NO_AMPDU_KEYBORDER_SUPPORT)) { + if (sta->ptk_idx != INVALID_PTK_KEYIDX) { /* Aggregation Sessions with Extended Key ID must not * mix MPDUs with different keyIDs within one A-MPDU. - * Tear down any running Tx aggregation and all new - * Rx/Tx aggregation request during rekey if the driver - * asks us to do so. (Blocking Tx only would be - * sufficient but WLAN_STA_BLOCK_BA gets the job done - * for the few ms we need it.) + * Tear down running Tx aggregation sessions and block + * new Rx/Tx aggregation requests during rekey to + * ensure there are no A-MPDUs for the driver to + * aggregate. (Blocking Tx only would be sufficient but + * WLAN_STA_BLOCK_BA gets the job done for the few ms + * we need it.) */ set_sta_flag(sta, WLAN_STA_BLOCK_BA); mutex_lock(&sta->ampdu_mlme.mtx); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4c2702f128f3..29b9d57df1a3 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1048,21 +1048,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } } - /* Enable Extended Key IDs when driver allowed it, or when it - * supports neither HW crypto nor A-MPDUs + /* Mac80211 and therefore all drivers using SW crypto only + * are able to handle PTK rekeys and Extended Key ID. */ - if ((!local->ops->set_key && - !ieee80211_hw_check(hw, AMPDU_AGGREGATION)) || - ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE)) - wiphy_ext_feature_set(local->hw.wiphy, - NL80211_EXT_FEATURE_EXT_KEY_ID); - - /* Mac80211 and therefore all cards only using SW crypto are able to - * handle PTK rekeys correctly - */ - if (!local->ops->set_key) + if (!local->ops->set_key) { wiphy_ext_feature_set(local->hw.wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + wiphy_ext_feature_set(local->hw.wiphy, + NL80211_EXT_FEATURE_EXT_KEY_ID); + } /* * Calculate scan IE length -- we need this to alloc -- GitLab From dc3998ec5cf2d377f2e85ba16b6a15affec98a0a Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sat, 29 Jun 2019 21:50:14 +0200 Subject: [PATCH 0837/7155] mac80211: AMPDU handling for rekeys with Extended Key ID Extended Key ID allows A-MPDU sessions while rekeying as long as each A-MPDU aggregates only MPDUs with one keyid together. Drivers able to segregate MPDUs accordingly can tell mac80211 to not stop A-MPDU sessions when rekeying by setting the new flag IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT. Signed-off-by: Alexander Wetzel Link: https://lore.kernel.org/r/20190629195015.19680-3-alexander@wetzel-home.de Signed-off-by: Johannes Berg --- include/net/mac80211.h | 5 +++++ net/mac80211/debugfs.c | 1 + net/mac80211/key.c | 14 ++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 58941893a13f..0187d84031fc 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2268,6 +2268,10 @@ struct ieee80211_txq { * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID * only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set. * + * @IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT: The card and driver is only + * aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx + * A-MPDU sessions active while rekeying with Extended Key ID. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2319,6 +2323,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN, IEEE80211_HW_SUPPORTS_MULTI_BSSID, IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, + IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 47435f57e086..568b3b276931 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -271,6 +271,7 @@ static const char *hw_flag_names[] = { FLAG(TX_STATUS_NO_AMPDU_LEN), FLAG(SUPPORTS_MULTI_BSSID), FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), + FLAG(AMPDU_KEYBORDER_SUPPORT), #undef FLAG }; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 92c3affb0eb0..7dfee848abac 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -270,7 +270,8 @@ int ieee80211_set_tx_key(struct ieee80211_key *key) sta->ptk_idx = key->conf.keyidx; - clear_sta_flag(sta, WLAN_STA_BLOCK_BA); + if (!ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) + clear_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_check_fast_xmit(sta); return 0; @@ -288,15 +289,16 @@ static void ieee80211_pairwise_rekey(struct ieee80211_key *old, if (new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX) { /* Extended Key ID key install, initial one or rekey */ - if (sta->ptk_idx != INVALID_PTK_KEYIDX) { + if (sta->ptk_idx != INVALID_PTK_KEYIDX && + !ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) { /* Aggregation Sessions with Extended Key ID must not * mix MPDUs with different keyIDs within one A-MPDU. * Tear down running Tx aggregation sessions and block * new Rx/Tx aggregation requests during rekey to - * ensure there are no A-MPDUs for the driver to - * aggregate. (Blocking Tx only would be sufficient but - * WLAN_STA_BLOCK_BA gets the job done for the few ms - * we need it.) + * ensure there are no A-MPDUs when the driver is not + * supporting A-MPDU key borders. (Blocking Tx only + * would be sufficient but WLAN_STA_BLOCK_BA gets the + * job done for the few ms we need it.) */ set_sta_flag(sta, WLAN_STA_BLOCK_BA); mutex_lock(&sta->ampdu_mlme.mtx); -- GitLab From d82574a8e5a469b72efaaa134f953a71642217e8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 3 Jul 2019 09:01:42 +0200 Subject: [PATCH 0838/7155] cfg80211: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190703070142.GA29993@kroah.com Signed-off-by: Johannes Berg --- net/wireless/core.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 45d9afcff6d5..742986c73490 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -142,12 +142,10 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, if (result) return result; - if (rdev->wiphy.debugfsdir && - !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, - rdev->wiphy.debugfsdir, - rdev->wiphy.debugfsdir->d_parent, - newname)) - pr_err("failed to rename debugfs dir to %s!\n", newname); + if (rdev->wiphy.debugfsdir) + debugfs_rename(rdev->wiphy.debugfsdir->d_parent, + rdev->wiphy.debugfsdir, + rdev->wiphy.debugfsdir->d_parent, newname); nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); @@ -899,11 +897,8 @@ int wiphy_register(struct wiphy *wiphy) cfg80211_rdev_list_generation++; /* add to debugfs */ - rdev->wiphy.debugfsdir = - debugfs_create_dir(wiphy_name(&rdev->wiphy), - ieee80211_debugfs_dir); - if (IS_ERR(rdev->wiphy.debugfsdir)) - rdev->wiphy.debugfsdir = NULL; + rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy), + ieee80211_debugfs_dir); cfg80211_debugfs_rdev_add(rdev); nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); -- GitLab From 84f1772bc0c7bc26db9dbdbeabc4b1fa0ea1ace3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Jul 2019 15:38:21 +0200 Subject: [PATCH 0839/7155] cfg80211: clean up cfg80211_inform_single_bss_frame_data() cfg80211_inform_single_bss_frame_data() doesn't need the non_tx_data data argument since it's always NULL. Signed-off-by: Johannes Berg Reviewed-by: Sergey Matyukevich Link: https://lore.kernel.org/r/20190703133823.10530-1-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- net/wireless/scan.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d66e6d4b7555..70d061ed9cb6 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1776,7 +1776,6 @@ static struct cfg80211_bss * cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy, struct cfg80211_inform_bss *data, struct ieee80211_mgmt *mgmt, size_t len, - struct cfg80211_non_tx_bss *non_tx_data, gfp_t gfp) { struct cfg80211_internal_bss tmp = {}, *res; @@ -1835,11 +1834,6 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy, tmp.pub.chains = data->chains; memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS); ether_addr_copy(tmp.parent_bssid, data->parent_bssid); - if (non_tx_data) { - tmp.pub.transmitted_bss = non_tx_data->tx_bss; - tmp.pub.bssid_index = non_tx_data->bssid_index; - tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator; - } signal_valid = abs(data->chan->center_freq - channel->center_freq) <= wiphy->max_adj_channel_rssi_comp; @@ -1877,7 +1871,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, struct cfg80211_non_tx_bss non_tx_data; res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt, - len, NULL, gfp); + len, gfp); if (!res || !wiphy->support_mbssid || !cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen)) return res; -- GitLab From b0d1d7ffc55571185e626a6ab2983400fc493cc2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Jul 2019 15:38:22 +0200 Subject: [PATCH 0840/7155] cfg80211: don't parse MBSSID if transmitting BSS isn't created Don't parse the multi-BSSID structures if we couldn't even create their transmitting BSS, this would confuse all of our tracking. This also means that non_tx_data->tx_bss will never be NULL, so we can clean up a little bit. Signed-off-by: Johannes Berg Reviewed-by: Sergey Matyukevich Link: https://lore.kernel.org/r/20190703133823.10530-2-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- net/wireless/scan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 70d061ed9cb6..186ae1bb510a 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1440,7 +1440,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, regulatory_hint_found_beacon(wiphy, channel, gfp); } - if (non_tx_data && non_tx_data->tx_bss) { + if (non_tx_data) { /* this is a nontransmitting bss, we need to add it to * transmitting bss' list if it is not there */ @@ -1659,6 +1659,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy, res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf, capability, beacon_interval, ie, ielen, NULL, gfp); + if (!res) + return NULL; non_tx_data.tx_bss = res; cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf, beacon_interval, ie, ielen, &non_tx_data, -- GitLab From 60d7dfea00e14d87bdfd94cb7cca1f7592069fd4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Jul 2019 15:38:23 +0200 Subject: [PATCH 0841/7155] cfg80211: give all multi-BSSID BSS entries the same timestamp If we just read jiffies over and over again, a non-transmitting entry may have a newer timestamp than the transmitting one, leading to possible confusion on expiry. Give them all the same timestamp when creating them. Signed-off-by: Johannes Berg Reviewed-by: Sergey Matyukevich Link: https://lore.kernel.org/r/20190703133823.10530-3-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- net/wireless/scan.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 186ae1bb510a..a98dabab557a 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1368,6 +1368,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, struct cfg80211_internal_bss tmp = {}, *res; int bss_type; bool signal_valid; + unsigned long ts; if (WARN_ON(!wiphy)) return NULL; @@ -1390,8 +1391,11 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, tmp.ts_boottime = data->boottime_ns; if (non_tx_data) { tmp.pub.transmitted_bss = non_tx_data->tx_bss; + ts = bss_from_pub(non_tx_data->tx_bss)->ts; tmp.pub.bssid_index = non_tx_data->bssid_index; tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator; + } else { + ts = jiffies; } /* @@ -1425,8 +1429,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, signal_valid = abs(data->chan->center_freq - channel->center_freq) <= wiphy->max_adj_channel_rssi_comp; - res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, - jiffies); + res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, ts); if (!res) return NULL; -- GitLab From 2aa485e1148557215337731b2c79f5569edcbbab Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sat, 13 Jul 2019 18:36:41 +0200 Subject: [PATCH 0842/7155] mac80211: add support for parsing ADDBA_EXT IEs ADDBA_EXT IEs can be used to negotiate the BA fragmentation level. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190713163642.18491-2-john@phrozen.org Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 8 ++++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/util.c | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 8511fadc0935..f36144eda5d6 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -881,6 +881,14 @@ struct ieee80211_tpc_report_ie { u8 link_margin; } __packed; +#define IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK GENMASK(2, 1) +#define IEEE80211_ADDBA_EXT_FRAG_LEVEL_SHIFT 1 +#define IEEE80211_ADDBA_EXT_NO_FRAG BIT(0) + +struct ieee80211_addba_ext_ie { + u8 data; +} __packed; + struct ieee80211_mgmt { __le16 frame_control; __le16 duration; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 004e2e3adb88..c67da3575e74 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1506,6 +1506,7 @@ struct ieee802_11_elems { u8 max_bssid_indicator; u8 dtim_count; u8 dtim_period; + const struct ieee80211_addba_ext_ie *addba_ext_ie; /* length of them, respectively */ u8 ext_capab_len; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1b224fa27367..3441558ef2d2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1200,6 +1200,13 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elems->cisco_dtpc_elem = pos; break; + case WLAN_EID_ADDBA_EXT: + if (elen != sizeof(struct ieee80211_addba_ext_ie)) { + elem_parse_failed = true; + break; + } + elems->addba_ext_ie = (void *)pos; + break; case WLAN_EID_TIMEOUT_INTERVAL: if (elen >= sizeof(struct ieee80211_timeout_interval_ie)) elems->timeout_int = (void *)pos; -- GitLab From cbe77dde4757446bbe333299b0c91d48b8d575a2 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 14 Jul 2019 17:44:14 +0200 Subject: [PATCH 0843/7155] mac80211: add xmit rate to struct ieee80211_tx_status Right now struct ieee80211_tx_rate cannot hold HE rates. Lets use struct ieee80211_tx_status instead. This will also make the code future-proof for when we have EHT. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190714154419.11854-2-john@phrozen.org Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0187d84031fc..6fe4381ba0ef 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1058,11 +1058,13 @@ struct ieee80211_tx_info { * @sta: Station that the packet was transmitted for * @info: Basic tx status information * @skb: Packet skb (can be NULL if not provided by the driver) + * @rate: The TX rate that was used when sending the packet */ struct ieee80211_tx_status { struct ieee80211_sta *sta; struct ieee80211_tx_info *info; struct sk_buff *skb; + struct rate_info *rate; }; /** -- GitLab From b7b2e8caa08c30d3ad2dcdb2133991b44db2913d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 14 Jul 2019 17:44:15 +0200 Subject: [PATCH 0844/7155] mac80211: propagate struct ieee80211_tx_status into ieee80211_tx_monitor() This will allow use to report HE rates on the radiotap interface. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190714154419.11854-3-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 3 ++- net/mac80211/status.c | 6 ++++-- net/mac80211/tx.c | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c67da3575e74..4c80c0ed67a7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1768,7 +1768,8 @@ ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u32 info_flags); void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_supported_band *sband, - int retry_count, int shift, bool send_to_cooked); + int retry_count, int shift, bool send_to_cooked, + struct ieee80211_tx_status *status); void ieee80211_check_fast_xmit(struct sta_info *sta); void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); diff --git a/net/mac80211/status.c b/net/mac80211/status.c index a88e3bf17e9d..adf6269fa363 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -645,7 +645,8 @@ static int ieee80211_tx_get_rates(struct ieee80211_hw *hw, void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_supported_band *sband, - int retry_count, int shift, bool send_to_cooked) + int retry_count, int shift, bool send_to_cooked, + struct ieee80211_tx_status *status) { struct sk_buff *skb2; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -901,7 +902,8 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, } /* send to monitor interfaces */ - ieee80211_tx_monitor(local, skb, sband, retry_count, shift, send_to_cooked); + ieee80211_tx_monitor(local, skb, sband, retry_count, shift, + send_to_cooked, status); } void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index fb8870d9eba3..235c6377a203 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4649,7 +4649,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, if (!sband) return bcn; - ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false); + ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false, + NULL); return bcn; } -- GitLab From 47ef78b09952eb8498457753f4ba351a8366b80f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 13 Jul 2019 11:52:29 +0200 Subject: [PATCH 0845/7155] ARM: dts: gemini: Fix up confused pin settings The SL93512r board has its pin muxing set up for the wrong ASIC: SL3516 instead of SL3512 that it is using. Fix it up and reference the right GPIO for the WPS button. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/gemini-sl93512r.dts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini-sl93512r.dts index 2bb953440793..afe655593b28 100644 --- a/arch/arm/boot/dts/gemini-sl93512r.dts +++ b/arch/arm/boot/dts/gemini-sl93512r.dts @@ -36,8 +36,8 @@ wakeup-source; linux,code = ; label = "WPS"; - /* Conflict with NAND flash */ - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + /* Conflicts with TVC and extended flash */ + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; }; button-setup { @@ -180,17 +180,20 @@ syscon: syscon@40000000 { pinctrl { /* - * gpio0egrp cover line 16 used by HD LED - * gpio0fgrp cover line 17, 18 used by wireless LED and reset button - * gpio0hgrp cover line 21, 22 used by MDIO for Marvell PHY - * gpio0kgrp cover line 31 used by USB LED + * gpio0agrp cover line 0, used by WPS button + * gpio0fgrp cover line 16 used by HD LED + * gpio0ggrp cover line 17, 18 used by wireless LAN LED and + * reset button OR USB ID select on 17 and USB VBUS select + * on 18. (Confusing.) + * gpio0igrp cover line 21, 22 used by MDIO for Marvell PHY */ gpio0_default_pins: pinctrl-gpio0 { mux { function = "gpio0"; - groups = "gpio0egrp", + groups = "gpio0agrp", "gpio0fgrp", - "gpio0hgrp"; + "gpio0ggrp", + "gpio0igrp"; }; }; /* -- GitLab From b5a923f8c7395bea1e4b9f1de75a8ed76978e33f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 12 Jul 2019 22:57:11 +0200 Subject: [PATCH 0846/7155] ARM: dts: gemini: Switch to redboot partition parsing This switches the kernel to parse the Redboot partitions in the SL93512r and the NAS4220B properly using the right compatible string instead of using hard-coded partitions. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/gemini-nas4220b.dts | 35 +++------------------------ arch/arm/boot/dts/gemini-sl93512r.dts | 35 +++------------------------ 2 files changed, 8 insertions(+), 62 deletions(-) diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts index f4535d635f3b..254ecbc3d79f 100644 --- a/arch/arm/boot/dts/gemini-nas4220b.dts +++ b/arch/arm/boot/dts/gemini-nas4220b.dts @@ -81,37 +81,10 @@ /* 16MB of flash */ reg = <0x30000000 0x01000000>; - partition@0 { - label = "RedBoot"; - reg = <0x00000000 0x00020000>; - read-only; - }; - partition@20000 { - label = "Kernel"; - reg = <0x00020000 0x00300000>; - }; - partition@320000 { - label = "Ramdisk"; - reg = <0x00320000 0x00600000>; - }; - partition@920000 { - label = "Application"; - reg = <0x00920000 0x00600000>; - }; - partition@f20000 { - label = "VCTL"; - reg = <0x00f20000 0x00020000>; - read-only; - }; - partition@f40000 { - label = "CurConf"; - reg = <0x00f40000 0x000a0000>; - read-only; - }; - partition@fe0000 { - label = "FIS directory"; - reg = <0x00fe0000 0x00020000>; - read-only; + partitions { + compatible = "redboot-fis"; + /* Eraseblock at 0xfe0000 */ + fis-index-block = <0x1fc>; }; }; diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini-sl93512r.dts index afe655593b28..5f70e01af7ec 100644 --- a/arch/arm/boot/dts/gemini-sl93512r.dts +++ b/arch/arm/boot/dts/gemini-sl93512r.dts @@ -143,37 +143,10 @@ /* 16MB of flash */ reg = <0x30000000 0x01000000>; - partition@0 { - label = "BOOT"; - reg = <0x00000000 0x00020000>; - read-only; - }; - partition@120000 { - label = "Kern"; - reg = <0x00020000 0x00300000>; - }; - partition@320000 { - label = "Ramdisk"; - reg = <0x00320000 0x00600000>; - }; - partition@920000 { - label = "Application"; - reg = <0x00920000 0x00600000>; - }; - partition@f20000 { - label = "VCTL"; - reg = <0x00f20000 0x00020000>; - read-only; - }; - partition@f40000 { - label = "CurConf"; - reg = <0x00f40000 0x000a0000>; - read-only; - }; - partition@fe0000 { - label = "FIS directory"; - reg = <0x00fe0000 0x00020000>; - read-only; + partitions { + compatible = "redboot-fis"; + /* Eraseblock at 0xfe0000 */ + fis-index-block = <0x1fc>; }; }; -- GitLab From e8547e12d5d6a40a16263cc8678d7025e54c379a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 12 Jul 2019 22:59:39 +0200 Subject: [PATCH 0847/7155] ARM: dts: gemini: Mount root from mtdblock3 The third mtdblock device named "Application" is where we want to mount our root filesystem. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/gemini-nas4220b.dts | 2 +- arch/arm/boot/dts/gemini-sl93512r.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts index 254ecbc3d79f..521714f38eed 100644 --- a/arch/arm/boot/dts/gemini-nas4220b.dts +++ b/arch/arm/boot/dts/gemini-nas4220b.dts @@ -20,7 +20,7 @@ }; chosen { - bootargs = "console=ttyS0,19200n8"; + bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait"; stdout-path = &uart0; }; diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini-sl93512r.dts index 5f70e01af7ec..a98af0351906 100644 --- a/arch/arm/boot/dts/gemini-sl93512r.dts +++ b/arch/arm/boot/dts/gemini-sl93512r.dts @@ -24,7 +24,7 @@ }; chosen { - bootargs = "console=ttyS0,19200n8 root=/dev/sda1 rw rootwait"; + bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait"; stdout-path = &uart0; }; -- GitLab From 54f9e8fa6668366620655df4e6ce5e7b9bf0de8c Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Fri, 5 Jul 2019 08:49:23 +0200 Subject: [PATCH 0848/7155] crypto: inside-secure - added support for rfc3686(ctr(aes)) Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 15 +- drivers/crypto/inside-secure/safexcel.h | 32 +--- .../crypto/inside-secure/safexcel_cipher.c | 155 +++++++++++++++--- 3 files changed, 138 insertions(+), 64 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 29ea2341f10e..47cb2da06eb3 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -404,17 +404,9 @@ static int safexcel_hw_init(struct safexcel_crypto_priv *priv) EIP197_PE_EIP96_TOKEN_CTRL_POST_REUSE_CTX; writel(val, EIP197_PE(priv) + EIP197_PE_EIP96_TOKEN_CTRL(pe)); - /* H/W capabilities selection */ - val = EIP197_FUNCTION_RSVD; - val |= EIP197_PROTOCOL_ENCRYPT_ONLY | EIP197_PROTOCOL_HASH_ONLY; - val |= EIP197_PROTOCOL_ENCRYPT_HASH | EIP197_PROTOCOL_HASH_DECRYPT; - val |= EIP197_ALG_DES_ECB | EIP197_ALG_DES_CBC; - val |= EIP197_ALG_3DES_ECB | EIP197_ALG_3DES_CBC; - val |= EIP197_ALG_AES_ECB | EIP197_ALG_AES_CBC; - val |= EIP197_ALG_MD5 | EIP197_ALG_HMAC_MD5; - val |= EIP197_ALG_SHA1 | EIP197_ALG_HMAC_SHA1; - val |= EIP197_ALG_SHA2 | EIP197_ALG_HMAC_SHA2; - writel(val, EIP197_PE(priv) + EIP197_PE_EIP96_FUNCTION_EN(pe)); + /* H/W capabilities selection: just enable everything */ + writel(EIP197_FUNCTION_ALL, + EIP197_PE(priv) + EIP197_PE_EIP96_FUNCTION_EN(pe)); } /* Command Descriptor Rings prepare */ @@ -858,6 +850,7 @@ static struct safexcel_alg_template *safexcel_algs[] = { &safexcel_alg_cbc_des3_ede, &safexcel_alg_ecb_aes, &safexcel_alg_cbc_aes, + &safexcel_alg_ctr_aes, &safexcel_alg_md5, &safexcel_alg_sha1, &safexcel_alg_sha224, diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index e6ee12a68857..64274c7bd65d 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -256,35 +256,7 @@ #define EIP197_PE_EIP96_TOKEN_CTRL_POST_REUSE_CTX BIT(20) /* EIP197_PE_EIP96_FUNCTION_EN */ -#define EIP197_FUNCTION_RSVD (BIT(6) | BIT(15) | BIT(20) | BIT(23)) -#define EIP197_PROTOCOL_HASH_ONLY BIT(0) -#define EIP197_PROTOCOL_ENCRYPT_ONLY BIT(1) -#define EIP197_PROTOCOL_HASH_ENCRYPT BIT(2) -#define EIP197_PROTOCOL_HASH_DECRYPT BIT(3) -#define EIP197_PROTOCOL_ENCRYPT_HASH BIT(4) -#define EIP197_PROTOCOL_DECRYPT_HASH BIT(5) -#define EIP197_ALG_ARC4 BIT(7) -#define EIP197_ALG_AES_ECB BIT(8) -#define EIP197_ALG_AES_CBC BIT(9) -#define EIP197_ALG_AES_CTR_ICM BIT(10) -#define EIP197_ALG_AES_OFB BIT(11) -#define EIP197_ALG_AES_CFB BIT(12) -#define EIP197_ALG_DES_ECB BIT(13) -#define EIP197_ALG_DES_CBC BIT(14) -#define EIP197_ALG_DES_OFB BIT(16) -#define EIP197_ALG_DES_CFB BIT(17) -#define EIP197_ALG_3DES_ECB BIT(18) -#define EIP197_ALG_3DES_CBC BIT(19) -#define EIP197_ALG_3DES_OFB BIT(21) -#define EIP197_ALG_3DES_CFB BIT(22) -#define EIP197_ALG_MD5 BIT(24) -#define EIP197_ALG_HMAC_MD5 BIT(25) -#define EIP197_ALG_SHA1 BIT(26) -#define EIP197_ALG_HMAC_SHA1 BIT(27) -#define EIP197_ALG_SHA2 BIT(28) -#define EIP197_ALG_HMAC_SHA2 BIT(29) -#define EIP197_ALG_AES_XCBC_MAC BIT(30) -#define EIP197_ALG_GCM_HASH BIT(31) +#define EIP197_FUNCTION_ALL 0xffffffff /* EIP197_PE_EIP96_CONTEXT_CTRL */ #define EIP197_CONTEXT_SIZE(n) (n) @@ -333,6 +305,7 @@ struct safexcel_context_record { /* control1 */ #define CONTEXT_CONTROL_CRYPTO_MODE_ECB (0 << 0) #define CONTEXT_CONTROL_CRYPTO_MODE_CBC (1 << 0) +#define CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD (6 << 0) #define CONTEXT_CONTROL_IV0 BIT(5) #define CONTEXT_CONTROL_IV1 BIT(6) #define CONTEXT_CONTROL_IV2 BIT(7) @@ -718,6 +691,7 @@ extern struct safexcel_alg_template safexcel_alg_ecb_des3_ede; extern struct safexcel_alg_template safexcel_alg_cbc_des3_ede; extern struct safexcel_alg_template safexcel_alg_ecb_aes; extern struct safexcel_alg_template safexcel_alg_cbc_aes; +extern struct safexcel_alg_template safexcel_alg_ctr_aes; extern struct safexcel_alg_template safexcel_alg_md5; extern struct safexcel_alg_template safexcel_alg_sha1; extern struct safexcel_alg_template safexcel_alg_sha224; diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 9c25dd0a1bfd..776da6515511 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -40,6 +40,7 @@ struct safexcel_cipher_ctx { bool aead; __le32 key[8]; + u32 nonce; unsigned int key_len; /* All the below is AEAD specific */ @@ -62,9 +63,9 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, u32 length) { struct safexcel_token *token; - u32 offset = 0, block_sz = 0; + u32 block_sz = 0; - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { + if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { switch (ctx->alg) { case SAFEXCEL_DES: block_sz = DES_BLOCK_SIZE; @@ -80,11 +81,20 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, break; } - offset = block_sz / sizeof(u32); - memcpy(cdesc->control_data.token, iv, block_sz); + if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { + /* 32 bit nonce */ + cdesc->control_data.token[0] = ctx->nonce; + /* 64 bit IV part */ + memcpy(&cdesc->control_data.token[1], iv, 8); + /* 32 bit counter, start at 1 (big endian!) */ + cdesc->control_data.token[3] = cpu_to_be32(1); + } else { + memcpy(cdesc->control_data.token, iv, block_sz); + } } - token = (struct safexcel_token *)(cdesc->control_data.token + offset); + /* skip over worst case IV of 4 dwords, no need to be exact */ + token = (struct safexcel_token *)(cdesc->control_data.token + 4); token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; token[0].packet_length = length; @@ -101,33 +111,35 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, u32 cryptlen, u32 assoclen, u32 digestsize) { struct safexcel_token *token; - unsigned offset = 0; + u32 block_sz = 0; - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { - offset = AES_BLOCK_SIZE / sizeof(u32); - memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE); + if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { + switch (ctx->alg) { + case SAFEXCEL_DES: + block_sz = DES_BLOCK_SIZE; + cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; + break; + case SAFEXCEL_3DES: + block_sz = DES3_EDE_BLOCK_SIZE; + cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; + break; + case SAFEXCEL_AES: + block_sz = AES_BLOCK_SIZE; + cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; + break; + } - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; + memcpy(cdesc->control_data.token, iv, block_sz); } - token = (struct safexcel_token *)(cdesc->control_data.token + offset); - if (direction == SAFEXCEL_DECRYPT) cryptlen -= digestsize; - token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[0].packet_length = assoclen; - token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; - - token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[1].packet_length = cryptlen; - token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; - token[1].instructions = EIP197_TOKEN_INS_LAST | - EIP197_TOKEN_INS_TYPE_CRYPTO | - EIP197_TOKEN_INS_TYPE_HASH | - EIP197_TOKEN_INS_TYPE_OUTPUT; - if (direction == SAFEXCEL_ENCRYPT) { + /* align end of instruction sequence to end of token */ + token = (struct safexcel_token *)(cdesc->control_data.token + + EIP197_MAX_TOKENS - 3); + token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; token[2].packet_length = digestsize; token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | @@ -135,6 +147,10 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | EIP197_TOKEN_INS_INSERT_HASH_DIGEST; } else { + /* align end of instruction sequence to end of token */ + token = (struct safexcel_token *)(cdesc->control_data.token + + EIP197_MAX_TOKENS - 4); + token[2].opcode = EIP197_TOKEN_OPCODE_RETRIEVE; token[2].packet_length = digestsize; token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | @@ -148,6 +164,19 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, EIP197_TOKEN_STAT_LAST_PACKET; token[3].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; } + + token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; + token[0].packet_length = assoclen; + token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; + + token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; + token[1].packet_length = cryptlen; + token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; + token[1].instructions = EIP197_TOKEN_INS_LAST | + EIP197_TOKEN_INS_TYPE_CRYPTO | + EIP197_TOKEN_INS_TYPE_HASH | + EIP197_TOKEN_INS_TYPE_OUTPUT; + } static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, @@ -1046,6 +1075,84 @@ struct safexcel_alg_template safexcel_alg_cbc_aes = { }, }; +static int safexcel_ctr_aes_encrypt(struct skcipher_request *req) +{ + return safexcel_queue_req(&req->base, skcipher_request_ctx(req), + SAFEXCEL_ENCRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD, + SAFEXCEL_AES); +} + +static int safexcel_ctr_aes_decrypt(struct skcipher_request *req) +{ + return safexcel_queue_req(&req->base, skcipher_request_ctx(req), + SAFEXCEL_DECRYPT, CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD, + SAFEXCEL_AES); +} + +static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm, + const u8 *key, unsigned int len) +{ + struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + struct safexcel_crypto_priv *priv = ctx->priv; + struct crypto_aes_ctx aes; + int ret, i; + unsigned int keylen; + + /* last 4 bytes of key are the nonce! */ + ctx->nonce = *(u32 *)(key + len - 4); + /* exclude the nonce here */ + keylen = len - 4; + ret = aes_expandkey(&aes, key, keylen); + if (ret) { + crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } + + if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { + for (i = 0; i < keylen / sizeof(u32); i++) { + if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { + ctx->base.needs_inv = true; + break; + } + } + } + + for (i = 0; i < keylen / sizeof(u32); i++) + ctx->key[i] = cpu_to_le32(aes.key_enc[i]); + + ctx->key_len = keylen; + + memzero_explicit(&aes, sizeof(aes)); + return 0; +} + +struct safexcel_alg_template safexcel_alg_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_SKCIPHER, + .alg.skcipher = { + .setkey = safexcel_skcipher_aesctr_setkey, + .encrypt = safexcel_ctr_aes_encrypt, + .decrypt = safexcel_ctr_aes_decrypt, + /* Add 4 to include the 4 byte nonce! */ + .min_keysize = AES_MIN_KEY_SIZE + 4, + .max_keysize = AES_MAX_KEY_SIZE + 4, + .ivsize = 8, + .base = { + .cra_name = "rfc3686(ctr(aes))", + .cra_driver_name = "safexcel-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_skcipher_cra_init, + .cra_exit = safexcel_skcipher_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + static int safexcel_cbc_des_encrypt(struct skcipher_request *req) { return safexcel_queue_req(&req->base, skcipher_request_ctx(req), -- GitLab From 0e17e3621a28a67871a8c69f5fccdf7d009fd939 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Fri, 5 Jul 2019 08:49:24 +0200 Subject: [PATCH 0849/7155] crypto: inside-secure - add support for authenc(hmac(sha*),rfc3686(ctr(aes))) suites This patch adds support for the following AEAD ciphersuites: - authenc(hmac(sha1),rfc3686(ctr(aes))) - authenc(hmac(sha224),rfc3686(ctr(aes))) - authenc(hmac(sha256),rfc3686(ctr(aes))) - authenc(hmac(sha384),rfc3686(ctr(aes))) - authenc(hmac(sha512),rfc3686(ctr(aes))) Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 14 +- drivers/crypto/inside-secure/safexcel.h | 5 + .../crypto/inside-secure/safexcel_cipher.c | 276 +++++++++++++++--- 3 files changed, 250 insertions(+), 45 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 47cb2da06eb3..d1f60fd7e91a 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -592,17 +592,18 @@ inline int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, if (rdesc->buffer_overflow) dev_err(priv->dev, "Buffer overflow detected"); - if (rdesc->result_data.error_code & 0x4067) { - /* Fatal error (bits 0,1,2,5,6 & 14) */ + if (rdesc->result_data.error_code & 0x4066) { + /* Fatal error (bits 1,2,5,6 & 14) */ dev_err(priv->dev, "result descriptor error (%x)", rdesc->result_data.error_code); return -EIO; } else if (rdesc->result_data.error_code & - (BIT(7) | BIT(4) | BIT(3))) { + (BIT(7) | BIT(4) | BIT(3) | BIT(0))) { /* * Give priority over authentication fails: - * Blocksize & overflow errors, something wrong with the input! + * Blocksize, length & overflow errors, + * something wrong with the input! */ return -EINVAL; } else if (rdesc->result_data.error_code & BIT(9)) { @@ -869,6 +870,11 @@ static struct safexcel_alg_template *safexcel_algs[] = { &safexcel_alg_authenc_hmac_sha384_cbc_aes, &safexcel_alg_authenc_hmac_sha512_cbc_aes, &safexcel_alg_authenc_hmac_sha1_cbc_des3_ede, + &safexcel_alg_authenc_hmac_sha1_ctr_aes, + &safexcel_alg_authenc_hmac_sha224_ctr_aes, + &safexcel_alg_authenc_hmac_sha256_ctr_aes, + &safexcel_alg_authenc_hmac_sha384_ctr_aes, + &safexcel_alg_authenc_hmac_sha512_ctr_aes, }; static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv) diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index 64274c7bd65d..04dfbbc63971 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -710,5 +710,10 @@ extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_aes; extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes; +extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes; #endif diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 776da6515511..477e0ec35f45 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -58,11 +58,9 @@ struct safexcel_cipher_req { int nr_src, nr_dst; }; -static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, - struct safexcel_command_desc *cdesc, - u32 length) +static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, + struct safexcel_command_desc *cdesc) { - struct safexcel_token *token; u32 block_sz = 0; if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { @@ -92,6 +90,15 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, memcpy(cdesc->control_data.token, iv, block_sz); } } +} + +static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, + struct safexcel_command_desc *cdesc, + u32 length) +{ + struct safexcel_token *token; + + safexcel_cipher_token(ctx, iv, cdesc); /* skip over worst case IV of 4 dwords, no need to be exact */ token = (struct safexcel_token *)(cdesc->control_data.token + 4); @@ -111,26 +118,8 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, u32 cryptlen, u32 assoclen, u32 digestsize) { struct safexcel_token *token; - u32 block_sz = 0; - if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { - switch (ctx->alg) { - case SAFEXCEL_DES: - block_sz = DES_BLOCK_SIZE; - cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; - break; - case SAFEXCEL_3DES: - block_sz = DES3_EDE_BLOCK_SIZE; - cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; - break; - case SAFEXCEL_AES: - block_sz = AES_BLOCK_SIZE; - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; - break; - } - - memcpy(cdesc->control_data.token, iv, block_sz); - } + safexcel_cipher_token(ctx, iv, cdesc); if (direction == SAFEXCEL_DECRYPT) cryptlen -= digestsize; @@ -165,18 +154,27 @@ static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, token[3].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; } - token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[0].packet_length = assoclen; - token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; - - token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[1].packet_length = cryptlen; - token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; - token[1].instructions = EIP197_TOKEN_INS_LAST | - EIP197_TOKEN_INS_TYPE_CRYPTO | - EIP197_TOKEN_INS_TYPE_HASH | - EIP197_TOKEN_INS_TYPE_OUTPUT; + if (unlikely(!cryptlen)) { + token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; + token[1].packet_length = assoclen; + token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; + token[1].instructions = EIP197_TOKEN_INS_LAST | + EIP197_TOKEN_INS_TYPE_HASH; + } else { + if (likely(assoclen)) { + token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; + token[0].packet_length = assoclen; + token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; + } + token[1].opcode = EIP197_TOKEN_OPCODE_DIRECTION; + token[1].packet_length = cryptlen; + token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; + token[1].instructions = EIP197_TOKEN_INS_LAST | + EIP197_TOKEN_INS_TYPE_CRYPTO | + EIP197_TOKEN_INS_TYPE_HASH | + EIP197_TOKEN_INS_TYPE_OUTPUT; + } } static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, @@ -220,23 +218,43 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, struct safexcel_ahash_export_state istate, ostate; struct safexcel_crypto_priv *priv = ctx->priv; struct crypto_authenc_keys keys; + struct crypto_aes_ctx aes; u32 flags; - int err; + int err = -EINVAL; if (crypto_authenc_extractkeys(&keys, key, len) != 0) goto badkey; - if (keys.enckeylen > sizeof(ctx->key)) - goto badkey; + if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { + /* 20 is minimum AES key: 16 bytes + 4 bytes nonce */ + if (keys.enckeylen < 20) + goto badkey; + /* last 4 bytes of key are the nonce! */ + ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen - 4); + /* exclude the nonce here */ + keys.enckeylen -= 4; + } /* Encryption key */ - if (ctx->alg == SAFEXCEL_3DES) { + switch (ctx->alg) { + case SAFEXCEL_3DES: + if (keys.enckeylen != 24) + goto badkey; flags = crypto_aead_get_flags(ctfm); err = __des3_verify_key(&flags, keys.enckey); crypto_aead_set_flags(ctfm, flags); if (unlikely(err)) - return err; + goto badkey_expflags; + break; + case SAFEXCEL_AES: + err = aes_expandkey(&aes, keys.enckey, keys.enckeylen); + if (unlikely(err)) + goto badkey; + break; + default: + dev_err(priv->dev, "aead: unsupported cipher algorithm\n"); + goto badkey; } if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && @@ -295,8 +313,9 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, badkey: crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); +badkey_expflags: memzero_explicit(&keys, sizeof(keys)); - return -EINVAL; + return err; } static int safexcel_context_control(struct safexcel_cipher_ctx *ctx, @@ -1392,6 +1411,7 @@ static int safexcel_aead_cra_init(struct crypto_tfm *tfm) ctx->priv = tmpl->priv; + ctx->alg = SAFEXCEL_AES; /* default */ ctx->aead = true; ctx->base.send = safexcel_aead_send; ctx->base.handle_result = safexcel_aead_handle_result; @@ -1573,6 +1593,15 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_aes = { }, }; +static int safexcel_aead_sha1_des3_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha1_cra_init(tfm); + ctx->alg = SAFEXCEL_3DES; /* override default */ + return 0; +} + static int safexcel_aead_encrypt_3des(struct aead_request *req) { struct safexcel_cipher_req *creq = aead_request_ctx(req); @@ -1606,7 +1635,172 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des3_ede = { .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), .cra_alignmask = 0, - .cra_init = safexcel_aead_sha1_cra_init, + .cra_init = safexcel_aead_sha1_des3_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + +static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha1_cra_init(tfm); + ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */ + return 0; +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, + .ivsize = 8, + .maxauthsize = SHA1_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", + .cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha1_ctr_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + +static int safexcel_aead_sha256_ctr_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha256_cra_init(tfm); + ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */ + return 0; +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, + .ivsize = 8, + .maxauthsize = SHA256_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", + .cra_driver_name = "safexcel-authenc-hmac-sha256-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha256_ctr_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + +static int safexcel_aead_sha224_ctr_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha224_cra_init(tfm); + ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */ + return 0; +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, + .ivsize = 8, + .maxauthsize = SHA224_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", + .cra_driver_name = "safexcel-authenc-hmac-sha224-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha224_ctr_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + +static int safexcel_aead_sha512_ctr_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha512_cra_init(tfm); + ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */ + return 0; +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, + .ivsize = 8, + .maxauthsize = SHA512_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))", + .cra_driver_name = "safexcel-authenc-hmac-sha512-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha512_ctr_cra_init, + .cra_exit = safexcel_aead_cra_exit, + .cra_module = THIS_MODULE, + }, + }, +}; + +static int safexcel_aead_sha384_ctr_cra_init(struct crypto_tfm *tfm) +{ + struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + + safexcel_aead_sha384_cra_init(tfm); + ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; /* override default */ + return 0; +} + +struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = { + .type = SAFEXCEL_ALG_TYPE_AEAD, + .alg.aead = { + .setkey = safexcel_aead_setkey, + .encrypt = safexcel_aead_encrypt_aes, + .decrypt = safexcel_aead_decrypt_aes, + .ivsize = 8, + .maxauthsize = SHA384_DIGEST_SIZE, + .base = { + .cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))", + .cra_driver_name = "safexcel-authenc-hmac-sha384-ctr-aes", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), + .cra_alignmask = 0, + .cra_init = safexcel_aead_sha384_ctr_cra_init, .cra_exit = safexcel_aead_cra_exit, .cra_module = THIS_MODULE, }, -- GitLab From 31fb084c4eb556fac30115d99bc518c7944887d2 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Fri, 5 Jul 2019 09:36:31 +0200 Subject: [PATCH 0850/7155] crypto: inside-secure -reduce hash byte counters to 64 bits This patch recognises the fact that the hardware cannot ever process more than 2,199,023,386,111 bytes of hash or HMAC payload, so there is no point in maintaining 128 bit wide byte counters, 64 bits is more than sufficient Signed-off-by: Pascal van Leeuwen Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.h | 4 +- drivers/crypto/inside-secure/safexcel_hash.c | 88 ++++++++------------ 2 files changed, 36 insertions(+), 56 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h index 04dfbbc63971..6f9875e7a0c0 100644 --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h @@ -613,8 +613,8 @@ struct safexcel_context { #define HASH_CACHE_SIZE SHA512_BLOCK_SIZE struct safexcel_ahash_export_state { - u64 len[2]; - u64 processed[2]; + u64 len; + u64 processed; u32 digest; diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index a777dec5f41f..c1776b6690fc 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -41,8 +41,8 @@ struct safexcel_ahash_req { u8 block_sz; /* block size, only set once */ u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); - u64 len[2]; - u64 processed[2]; + u64 len; + u64 processed; u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); dma_addr_t cache_dma; @@ -53,12 +53,7 @@ struct safexcel_ahash_req { static inline u64 safexcel_queued_len(struct safexcel_ahash_req *req) { - u64 len, processed; - - len = (0xffffffff * req->len[1]) + req->len[0]; - processed = (0xffffffff * req->processed[1]) + req->processed[0]; - - return len - processed; + return req->len - req->processed; } static void safexcel_hash_token(struct safexcel_command_desc *cdesc, @@ -94,7 +89,7 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, * fields. Do this now as we need it to setup the first command * descriptor. */ - if ((!req->processed[0]) && (!req->processed[1])) { + if (!req->processed) { /* First - and possibly only - block of basic hash only */ if (req->finish) { cdesc->control_data.control0 |= @@ -119,11 +114,8 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, if (req->finish) { /* Compute digest count for hash/HMAC finish operations */ if ((req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED) || - req->hmac_zlen || req->processed[1] || - (req->processed[0] != req->block_sz)) { - count = req->processed[0] / EIP197_COUNTER_BLOCK_SIZE; - count += ((0x100000000ULL / EIP197_COUNTER_BLOCK_SIZE) * - req->processed[1]); + req->hmac_zlen || (req->processed != req->block_sz)) { + count = req->processed / EIP197_COUNTER_BLOCK_SIZE; /* This is a hardware limitation, as the * counter must fit into an u32. This represents @@ -141,8 +133,7 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, /* Special case: zero length HMAC */ req->hmac_zlen || /* PE HW < 4.4 cannot do HMAC continue, fake using hash */ - ((req->processed[1] || - (req->processed[0] != req->block_sz)))) { + (req->processed != req->block_sz)) { /* Basic hash continue operation, need digest + cnt */ cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE((req->state_sz >> 2) + 1) | @@ -234,11 +225,9 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv, memcpy(sreq->state, ctx->opad, sreq->state_sz); - sreq->len[0] = sreq->block_sz + - crypto_ahash_digestsize(ahash); - sreq->len[1] = 0; - sreq->processed[0] = sreq->block_sz; - sreq->processed[1] = 0; + sreq->len = sreq->block_sz + + crypto_ahash_digestsize(ahash); + sreq->processed = sreq->block_sz; sreq->hmac = 0; ctx->base.needs_inv = true; @@ -393,9 +382,7 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); - req->processed[0] += len; - if (req->processed[0] < len) - req->processed[1]++; + req->processed += len; *commands = n_cdesc; *results = 1; @@ -603,15 +590,14 @@ static int safexcel_ahash_enqueue(struct ahash_request *areq) if (ctx->base.ctxr) { if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && - (req->processed[0] || req->processed[1]) && + req->processed && (/* invalidate for basic hash continuation finish */ (req->finish && (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) || /* invalidate if (i)digest changed */ memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || /* invalidate for HMAC continuation finish */ - (req->finish && (req->processed[1] || - (req->processed[0] != req->block_sz))) || + (req->finish && (req->processed != req->block_sz)) || /* invalidate for HMAC finish with odigest changed */ (req->finish && memcmp(ctx->base.ctxr->data + (req->state_sz>>2), @@ -662,9 +648,7 @@ static int safexcel_ahash_update(struct ahash_request *areq) ret = safexcel_ahash_cache(areq); /* Update total request length */ - req->len[0] += areq->nbytes; - if (req->len[0] < areq->nbytes) - req->len[1]++; + req->len += areq->nbytes; /* If not all data could fit into the cache, go process the excess. * Also go process immediately for an HMAC IV precompute, which @@ -683,7 +667,7 @@ static int safexcel_ahash_final(struct ahash_request *areq) req->finish = true; - if (unlikely(!req->len[0] && !req->len[1] && !areq->nbytes)) { + if (unlikely(!req->len && !areq->nbytes)) { /* * If we have an overall 0 length *hash* request: * The HW cannot do 0 length hash, so we provide the correct @@ -709,8 +693,8 @@ static int safexcel_ahash_final(struct ahash_request *areq) SHA512_DIGEST_SIZE); return 0; - } else if (unlikely(req->hmac && !req->len[1] && - (req->len[0] == req->block_sz) && + } else if (unlikely(req->hmac && + (req->len == req->block_sz) && !areq->nbytes)) { /* * If we have an overall 0 length *HMAC* request: @@ -736,7 +720,7 @@ static int safexcel_ahash_final(struct ahash_request *areq) 255; } - req->len[0] += req->block_sz; /* plus 1 hash block */ + req->len += req->block_sz; /* plus 1 hash block */ /* Set special zero-length HMAC flag */ req->hmac_zlen = true; @@ -766,10 +750,8 @@ static int safexcel_ahash_export(struct ahash_request *areq, void *out) struct safexcel_ahash_req *req = ahash_request_ctx(areq); struct safexcel_ahash_export_state *export = out; - export->len[0] = req->len[0]; - export->len[1] = req->len[1]; - export->processed[0] = req->processed[0]; - export->processed[1] = req->processed[1]; + export->len = req->len; + export->processed = req->processed; export->digest = req->digest; @@ -789,10 +771,8 @@ static int safexcel_ahash_import(struct ahash_request *areq, const void *in) if (ret) return ret; - req->len[0] = export->len[0]; - req->len[1] = export->len[1]; - req->processed[0] = export->processed[0]; - req->processed[1] = export->processed[1]; + req->len = export->len; + req->processed = export->processed; req->digest = export->digest; @@ -903,8 +883,8 @@ static int safexcel_hmac_sha1_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, SHA1_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = SHA1_BLOCK_SIZE; - req->processed[0] = SHA1_BLOCK_SIZE; + req->len = SHA1_BLOCK_SIZE; + req->processed = SHA1_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; @@ -1262,8 +1242,8 @@ static int safexcel_hmac_sha224_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = SHA256_BLOCK_SIZE; - req->processed[0] = SHA256_BLOCK_SIZE; + req->len = SHA256_BLOCK_SIZE; + req->processed = SHA256_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; @@ -1332,8 +1312,8 @@ static int safexcel_hmac_sha256_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, SHA256_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = SHA256_BLOCK_SIZE; - req->processed[0] = SHA256_BLOCK_SIZE; + req->len = SHA256_BLOCK_SIZE; + req->processed = SHA256_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; @@ -1512,8 +1492,8 @@ static int safexcel_hmac_sha512_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = SHA512_BLOCK_SIZE; - req->processed[0] = SHA512_BLOCK_SIZE; + req->len = SHA512_BLOCK_SIZE; + req->processed = SHA512_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; @@ -1582,8 +1562,8 @@ static int safexcel_hmac_sha384_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, SHA512_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = SHA512_BLOCK_SIZE; - req->processed[0] = SHA512_BLOCK_SIZE; + req->len = SHA512_BLOCK_SIZE; + req->processed = SHA512_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; @@ -1700,8 +1680,8 @@ static int safexcel_hmac_md5_init(struct ahash_request *areq) /* Start from ipad precompute */ memcpy(req->state, ctx->ipad, MD5_DIGEST_SIZE); /* Already processed the key^ipad part now! */ - req->len[0] = MD5_HMAC_BLOCK_SIZE; - req->processed[0] = MD5_HMAC_BLOCK_SIZE; + req->len = MD5_HMAC_BLOCK_SIZE; + req->processed = MD5_HMAC_BLOCK_SIZE; ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; -- GitLab From 91b05a7e7d8033a90a64f5fc0e3808db423e420a Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Tue, 9 Jul 2019 13:11:24 +0200 Subject: [PATCH 0851/7155] crypto: user - make NETLINK_CRYPTO work inside netns Currently, NETLINK_CRYPTO works only in the init network namespace. It doesn't make much sense to cut it out of the other network namespaces, so do the minor plumbing work necessary to make it work in any network namespace. Code inspired by net/core/sock_diag.c. Tested using kcapi-dgst from libkcapi [1]: Before: # unshare -n kcapi-dgst -c sha256 Signed-off-by: Herbert Xu --- crypto/crypto_user_base.c | 37 +++++++++++++++++++--------- crypto/crypto_user_stat.c | 4 ++- include/crypto/internal/cryptouser.h | 2 -- include/net/net_namespace.h | 3 +++ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/crypto/crypto_user_base.c b/crypto/crypto_user_base.c index c65e39005ce2..910e0b46012e 100644 --- a/crypto/crypto_user_base.c +++ b/crypto/crypto_user_base.c @@ -10,9 +10,10 @@ #include #include #include -#include #include +#include #include +#include #include #include #include @@ -25,9 +26,6 @@ static DEFINE_MUTEX(crypto_cfg_mutex); -/* The crypto netlink socket */ -struct sock *crypto_nlsk; - struct crypto_dump_info { struct sk_buff *in_skb; struct sk_buff *out_skb; @@ -186,6 +184,7 @@ static int crypto_report_alg(struct crypto_alg *alg, static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs) { + struct net *net = sock_net(in_skb->sk); struct crypto_user_alg *p = nlmsg_data(in_nlh); struct crypto_alg *alg; struct sk_buff *skb; @@ -217,7 +216,7 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, if (err) return err; - return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid); + return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid); } static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb) @@ -420,6 +419,7 @@ static const struct crypto_link { static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) { + struct net *net = sock_net(skb->sk); struct nlattr *attrs[CRYPTOCFGA_MAX+1]; const struct crypto_link *link; int type, err; @@ -450,7 +450,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, .done = link->done, .min_dump_alloc = min(dump_alloc, 65535UL), }; - err = netlink_dump_start(crypto_nlsk, skb, nlh, &c); + err = netlink_dump_start(net->crypto_nlsk, skb, nlh, &c); } return err; @@ -474,22 +474,35 @@ static void crypto_netlink_rcv(struct sk_buff *skb) mutex_unlock(&crypto_cfg_mutex); } -static int __init crypto_user_init(void) +static int __net_init crypto_netlink_init(struct net *net) { struct netlink_kernel_cfg cfg = { .input = crypto_netlink_rcv, }; - crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg); - if (!crypto_nlsk) - return -ENOMEM; + net->crypto_nlsk = netlink_kernel_create(net, NETLINK_CRYPTO, &cfg); + return net->crypto_nlsk == NULL ? -ENOMEM : 0; +} - return 0; +static void __net_exit crypto_netlink_exit(struct net *net) +{ + netlink_kernel_release(net->crypto_nlsk); + net->crypto_nlsk = NULL; +} + +static struct pernet_operations crypto_netlink_net_ops = { + .init = crypto_netlink_init, + .exit = crypto_netlink_exit, +}; + +static int __init crypto_user_init(void) +{ + return register_pernet_subsys(&crypto_netlink_net_ops); } static void __exit crypto_user_exit(void) { - netlink_kernel_release(crypto_nlsk); + unregister_pernet_subsys(&crypto_netlink_net_ops); } module_init(crypto_user_init); diff --git a/crypto/crypto_user_stat.c b/crypto/crypto_user_stat.c index a03f326a63d3..8bad88413de1 100644 --- a/crypto/crypto_user_stat.c +++ b/crypto/crypto_user_stat.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -298,6 +299,7 @@ static int crypto_reportstat_alg(struct crypto_alg *alg, int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs) { + struct net *net = sock_net(in_skb->sk); struct crypto_user_alg *p = nlmsg_data(in_nlh); struct crypto_alg *alg; struct sk_buff *skb; @@ -329,7 +331,7 @@ int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, if (err) return err; - return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid); + return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid); } MODULE_LICENSE("GPL"); diff --git a/include/crypto/internal/cryptouser.h b/include/crypto/internal/cryptouser.h index 8c602b187c58..40623f4457df 100644 --- a/include/crypto/internal/cryptouser.h +++ b/include/crypto/internal/cryptouser.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include -extern struct sock *crypto_nlsk; - struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact); #ifdef CONFIG_CRYPTO_STATS diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 4a9da951a794..85bc1de5dece 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -170,6 +170,9 @@ struct net { #endif #ifdef CONFIG_XDP_SOCKETS struct netns_xdp xdp; +#endif +#if IS_ENABLED(CONFIG_CRYPTO_USER) + struct sock *crypto_nlsk; #endif struct sock *diag_nlsk; atomic_t fnhe_genid; -- GitLab From 93308baf075039dccf347391491773f272cc24f6 Mon Sep 17 00:00:00 2001 From: "Hook, Gary" Date: Tue, 9 Jul 2019 15:07:15 +0000 Subject: [PATCH 0852/7155] crypto: ccp - Make CCP debugfs support optional Add a config option to exclude DebugFS support in the CCP driver. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/Kconfig | 8 ++++++++ drivers/crypto/ccp/Makefile | 4 ++-- drivers/crypto/ccp/ccp-dev-v5.c | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig index ce1c47286fc6..8fec733f567f 100644 --- a/drivers/crypto/ccp/Kconfig +++ b/drivers/crypto/ccp/Kconfig @@ -46,3 +46,11 @@ config CRYPTO_DEV_SP_PSP management commands in Secure Encrypted Virtualization (SEV) mode, along with software-based Trusted Execution Environment (TEE) to enable third-party trusted applications. + +config CRYPTO_DEV_CCP_DEBUGFS + bool "Enable CCP Internals in DebugFS" + default n + depends on CRYPTO_DEV_SP_CCP + help + Expose CCP device information such as operation statistics, feature + information, and descriptor queue contents. diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index 51d1c0cf66c7..6b86f1e6d634 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -5,8 +5,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-ops.o \ ccp-dev-v3.o \ ccp-dev-v5.o \ - ccp-dmaengine.o \ - ccp-debugfs.o + ccp-dmaengine.o +ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index 217e41bbadaf..35b3d866726d 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -970,8 +970,10 @@ static int ccp5_init(struct ccp_device *ccp) if (ret) goto e_hwrng; +#ifdef CONFIG_CRYPTO_DEV_CCP_DEBUGFS /* Set up debugfs entries */ ccp5_debugfs_setup(ccp); +#endif return 0; @@ -1009,11 +1011,13 @@ static void ccp5_destroy(struct ccp_device *ccp) /* Remove this device from the list of available units first */ ccp_del_device(ccp); +#ifdef CONFIG_CRYPTO_DEV_CCP_DEBUGFS /* We're in the process of tearing down the entire driver; * when all the devices are gone clean up debugfs */ if (ccp_present()) ccp5_debugfs_destroy(); +#endif /* Disable and clear interrupts */ ccp5_disable_queue_interrupts(ccp); -- GitLab From c4a89279086e9c98eba659d7665b1732e0d5e3e3 Mon Sep 17 00:00:00 2001 From: "Hook, Gary" Date: Tue, 9 Jul 2019 15:07:22 +0000 Subject: [PATCH 0853/7155] crypto: ccp - Add a module parameter to specify a queue count Add a module parameter to limit the number of queues per CCP. The default value (nqueues=0) is to set up every available queue on each device. The count of queues starts from the first one found on the device (which varies based on the device ID). Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev-v3.c | 2 +- drivers/crypto/ccp/ccp-dev-v5.c | 7 ++----- drivers/crypto/ccp/ccp-dev.c | 11 +++++++++++ drivers/crypto/ccp/ccp-dev.h | 1 + 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 2b7d47ed5c74..4005d438dff9 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -379,7 +379,7 @@ static int ccp_init(struct ccp_device *ccp) /* Find available queues */ ccp->qim = 0; qmr = ioread32(ccp->io_regs + Q_MASK_REG); - for (i = 0; i < MAX_HW_QUEUES; i++) { + for (i = 0; (i < MAX_HW_QUEUES) && (ccp->cmd_q_count < ccp->max_q_count); i++) { if (!(qmr & (1 << i))) continue; diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index 35b3d866726d..f146b51a23a5 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -2,16 +2,14 @@ /* * AMD Cryptographic Coprocessor (CCP) driver * - * Copyright (C) 2016,2017 Advanced Micro Devices, Inc. + * Copyright (C) 2016,2019 Advanced Micro Devices, Inc. * * Author: Gary R Hook */ -#include #include #include #include -#include #include #include #include @@ -792,8 +790,7 @@ static int ccp5_init(struct ccp_device *ccp) /* Find available queues */ qmr = ioread32(ccp->io_regs + Q_MASK_REG); - for (i = 0; i < MAX_HW_QUEUES; i++) { - + for (i = 0; (i < MAX_HW_QUEUES) && (ccp->cmd_q_count < ccp->max_q_count); i++) { if (!(qmr & (1 << i))) continue; diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index f79eede71c62..352059d0c572 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -8,6 +8,7 @@ * Author: Gary R Hook */ +#include #include #include #include @@ -26,6 +27,11 @@ #include "ccp-dev.h" +/* Limit CCP use to a specifed number of queues per device */ +static unsigned int nqueues = 0; +module_param(nqueues, uint, 0444); +MODULE_PARM_DESC(nqueues, "Number of queues per CCP (minimum 1; default: all available)"); + struct ccp_tasklet_data { struct completion completion; struct ccp_cmd *cmd; @@ -592,6 +598,11 @@ int ccp_dev_init(struct sp_device *sp) goto e_err; sp->ccp_data = ccp; + if (!nqueues || (nqueues > MAX_HW_QUEUES)) + ccp->max_q_count = MAX_HW_QUEUES; + else + ccp->max_q_count = nqueues; + ccp->vdata = (struct ccp_vdata *)sp->dev_vdata->ccp_vdata; if (!ccp->vdata || !ccp->vdata->version) { ret = -ENODEV; diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 5e624920fd99..dd13468111cd 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -379,6 +379,7 @@ struct ccp_device { */ struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES]; unsigned int cmd_q_count; + unsigned int max_q_count; /* Support for the CCP True RNG */ -- GitLab From 90773bc1ab407bc2198d7e9fc1c6d6b5ef27a24f Mon Sep 17 00:00:00 2001 From: "Hook, Gary" Date: Tue, 9 Jul 2019 15:07:29 +0000 Subject: [PATCH 0854/7155] crypto: ccp - module parameter to limit the number of enabled CCPs Provide the ability to constrain the total number of enabled devices in the system. Once max_devs devices have been configured, subsequently probed devices are ignored. The max_devs parameter may be zero, in which case all CCPs are disabled. PSPs are always enabled and active. Disabling the CCPs also disables DMA and RNG registration. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index 352059d0c572..e58d69d4dd43 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -2,7 +2,7 @@ /* * AMD Cryptographic Coprocessor (CCP) driver * - * Copyright (C) 2013,2017 Advanced Micro Devices, Inc. + * Copyright (C) 2013,2019 Advanced Micro Devices, Inc. * * Author: Tom Lendacky * Author: Gary R Hook @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef CONFIG_X86 #include #endif @@ -27,11 +28,19 @@ #include "ccp-dev.h" +#define MAX_CCPS 32 + /* Limit CCP use to a specifed number of queues per device */ static unsigned int nqueues = 0; module_param(nqueues, uint, 0444); MODULE_PARM_DESC(nqueues, "Number of queues per CCP (minimum 1; default: all available)"); +/* Limit the maximum number of configured CCPs */ +static atomic_t dev_count = ATOMIC_INIT(0); +static unsigned int max_devs = MAX_CCPS; +module_param(max_devs, uint, 0444); +MODULE_PARM_DESC(max_devs, "Maximum number of CCPs to enable (default: all; 0 disables all CCPs)"); + struct ccp_tasklet_data { struct completion completion; struct ccp_cmd *cmd; @@ -592,6 +601,13 @@ int ccp_dev_init(struct sp_device *sp) struct ccp_device *ccp; int ret; + /* + * Check how many we have so far, and stop after reaching + * that number + */ + if (atomic_inc_return(&dev_count) > max_devs) + return 0; /* don't fail the load */ + ret = -ENOMEM; ccp = ccp_alloc_struct(sp); if (!ccp) -- GitLab From a7c2647034fa34e03d3f4e2cf66315440db2aa14 Mon Sep 17 00:00:00 2001 From: "Hook, Gary" Date: Tue, 9 Jul 2019 15:07:35 +0000 Subject: [PATCH 0855/7155] crypto: ccp - Add a module parameter to control registration for DMA The CCP driver is able to act as a DMA engine. Add a module parameter that allows this feature to be enabled/disabled. Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dmaengine.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c index 7f22a45bbc11..9d077c42bcbe 100644 --- a/drivers/crypto/ccp/ccp-dmaengine.c +++ b/drivers/crypto/ccp/ccp-dmaengine.c @@ -2,7 +2,7 @@ /* * AMD Cryptographic Coprocessor (CCP) driver * - * Copyright (C) 2016,2017 Advanced Micro Devices, Inc. + * Copyright (C) 2016,2019 Advanced Micro Devices, Inc. * * Author: Gary R Hook */ @@ -35,6 +35,10 @@ static unsigned int dma_chan_attr = CCP_DMA_DFLT; module_param(dma_chan_attr, uint, 0444); MODULE_PARM_DESC(dma_chan_attr, "Set DMA channel visibility: 0 (default) = device defaults, 1 = make private, 2 = make public"); +static unsigned int dmaengine = 1; +module_param(dmaengine, uint, 0444); +MODULE_PARM_DESC(dmaengine, "Register services with the DMA subsystem (any non-zero value, default: 1)"); + static unsigned int ccp_get_dma_chan_attr(struct ccp_device *ccp) { switch (dma_chan_attr) { @@ -637,6 +641,9 @@ int ccp_dmaengine_register(struct ccp_device *ccp) unsigned int i; int ret; + if (!dmaengine) + return 0; + ccp->ccp_dma_chan = devm_kcalloc(ccp->dev, ccp->cmd_q_count, sizeof(*(ccp->ccp_dma_chan)), GFP_KERNEL); @@ -740,6 +747,9 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp) { struct dma_device *dma_dev = &ccp->dma_dev; + if (!dmaengine) + return; + dma_async_device_unregister(dma_dev); kmem_cache_destroy(ccp->dma_desc_cache); -- GitLab From a7268c4d4205b7f92eb77ac99d64099152b0f738 Mon Sep 17 00:00:00 2001 From: Phani Kiran Hemadri Date: Tue, 9 Jul 2019 15:24:24 +0000 Subject: [PATCH 0856/7155] crypto: cavium/nitrox - Add support for loading asymmetric crypto firmware This patch adds support to load Asymmetric crypto firmware on AE cores of CNN55XX device. Firmware is stored on UCD block 2 and all available AE cores are tagged to group 0. Signed-off-by: Phani Kiran Hemadri Reviewed-by: Srikanth Jampala Signed-off-by: Herbert Xu --- drivers/crypto/cavium/nitrox/nitrox_csr.h | 124 ++++++++++++++- drivers/crypto/cavium/nitrox/nitrox_debugfs.c | 3 +- drivers/crypto/cavium/nitrox/nitrox_dev.h | 4 +- drivers/crypto/cavium/nitrox/nitrox_main.c | 144 ++++++++++++++---- 4 files changed, 244 insertions(+), 31 deletions(-) diff --git a/drivers/crypto/cavium/nitrox/nitrox_csr.h b/drivers/crypto/cavium/nitrox/nitrox_csr.h index a2a452642b38..da1d73303780 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_csr.h +++ b/drivers/crypto/cavium/nitrox/nitrox_csr.h @@ -40,9 +40,77 @@ #define EMU_FUSE_MAPX(_i) (0x1402708 + ((_i) * 0x40000)) /* UCD registers */ +#define UCD_SE_EID_UCODE_BLOCK_NUMX(_i) (0x12C0000 + ((_i) * 0x1000)) +#define UCD_AE_EID_UCODE_BLOCK_NUMX(_i) (0x12C0008 + ((_i) * 0x800)) #define UCD_UCODE_LOAD_BLOCK_NUM 0x12C0010 #define UCD_UCODE_LOAD_IDX_DATAX(_i) (0x12C0018 + ((_i) * 0x20)) -#define UCD_SE_EID_UCODE_BLOCK_NUMX(_i) (0x12C0000 + ((_i) * 0x1000)) +#define UCD_SE_CNTX(_i) (0x12C0040 + ((_i) * 0x1000)) +#define UCD_AE_CNTX(_i) (0x12C0048 + ((_i) * 0x800)) + +/* AQM registers */ +#define AQM_CTL 0x1300000 +#define AQM_INT 0x1300008 +#define AQM_DBELL_OVF_LO 0x1300010 +#define AQM_DBELL_OVF_HI 0x1300018 +#define AQM_DBELL_OVF_LO_W1S 0x1300020 +#define AQM_DBELL_OVF_LO_ENA_W1C 0x1300028 +#define AQM_DBELL_OVF_LO_ENA_W1S 0x1300030 +#define AQM_DBELL_OVF_HI_W1S 0x1300038 +#define AQM_DBELL_OVF_HI_ENA_W1C 0x1300040 +#define AQM_DBELL_OVF_HI_ENA_W1S 0x1300048 +#define AQM_DMA_RD_ERR_LO 0x1300050 +#define AQM_DMA_RD_ERR_HI 0x1300058 +#define AQM_DMA_RD_ERR_LO_W1S 0x1300060 +#define AQM_DMA_RD_ERR_LO_ENA_W1C 0x1300068 +#define AQM_DMA_RD_ERR_LO_ENA_W1S 0x1300070 +#define AQM_DMA_RD_ERR_HI_W1S 0x1300078 +#define AQM_DMA_RD_ERR_HI_ENA_W1C 0x1300080 +#define AQM_DMA_RD_ERR_HI_ENA_W1S 0x1300088 +#define AQM_EXEC_NA_LO 0x1300090 +#define AQM_EXEC_NA_HI 0x1300098 +#define AQM_EXEC_NA_LO_W1S 0x13000A0 +#define AQM_EXEC_NA_LO_ENA_W1C 0x13000A8 +#define AQM_EXEC_NA_LO_ENA_W1S 0x13000B0 +#define AQM_EXEC_NA_HI_W1S 0x13000B8 +#define AQM_EXEC_NA_HI_ENA_W1C 0x13000C0 +#define AQM_EXEC_NA_HI_ENA_W1S 0x13000C8 +#define AQM_EXEC_ERR_LO 0x13000D0 +#define AQM_EXEC_ERR_HI 0x13000D8 +#define AQM_EXEC_ERR_LO_W1S 0x13000E0 +#define AQM_EXEC_ERR_LO_ENA_W1C 0x13000E8 +#define AQM_EXEC_ERR_LO_ENA_W1S 0x13000F0 +#define AQM_EXEC_ERR_HI_W1S 0x13000F8 +#define AQM_EXEC_ERR_HI_ENA_W1C 0x1300100 +#define AQM_EXEC_ERR_HI_ENA_W1S 0x1300108 +#define AQM_ECC_INT 0x1300110 +#define AQM_ECC_INT_W1S 0x1300118 +#define AQM_ECC_INT_ENA_W1C 0x1300120 +#define AQM_ECC_INT_ENA_W1S 0x1300128 +#define AQM_ECC_CTL 0x1300130 +#define AQM_BIST_STATUS 0x1300138 +#define AQM_CMD_INF_THRX(x) (0x1300400 + ((x) * 0x8)) +#define AQM_CMD_INFX(x) (0x1300800 + ((x) * 0x8)) +#define AQM_GRP_EXECMSK_LOX(x) (0x1300C00 + ((x) * 0x10)) +#define AQM_GRP_EXECMSK_HIX(x) (0x1300C08 + ((x) * 0x10)) +#define AQM_ACTIVITY_STAT_LO 0x1300C80 +#define AQM_ACTIVITY_STAT_HI 0x1300C88 +#define AQM_Q_CMD_PROCX(x) (0x1301000 + ((x) * 0x8)) +#define AQM_PERF_CTL_LO 0x1301400 +#define AQM_PERF_CTL_HI 0x1301408 +#define AQM_PERF_CNT 0x1301410 + +#define AQMQ_DRBLX(x) (0x20000 + ((x) * 0x40000)) +#define AQMQ_QSZX(x) (0x20008 + ((x) * 0x40000)) +#define AQMQ_BADRX(x) (0x20010 + ((x) * 0x40000)) +#define AQMQ_NXT_CMDX(x) (0x20018 + ((x) * 0x40000)) +#define AQMQ_CMD_CNTX(x) (0x20020 + ((x) * 0x40000)) +#define AQMQ_CMP_THRX(x) (0x20028 + ((x) * 0x40000)) +#define AQMQ_CMP_CNTX(x) (0x20030 + ((x) * 0x40000)) +#define AQMQ_TIM_LDX(x) (0x20038 + ((x) * 0x40000)) +#define AQMQ_TIMERX(x) (0x20040 + ((x) * 0x40000)) +#define AQMQ_ENX(x) (0x20048 + ((x) * 0x40000)) +#define AQMQ_ACTIVITY_STATX(x) (0x20050 + ((x) * 0x40000)) +#define AQM_VF_CMP_STATX(x) (0x28000 + ((x) * 0x40000)) /* NPS core registers */ #define NPS_CORE_GBL_VFCFG 0x1000000 @@ -134,6 +202,60 @@ /* PEM registers */ #define PEM0_INT 0x1080428 +/** + * struct ucd_core_eid_ucode_block_num - Core Eid to Ucode Blk Mapping Registers + * @ucode_len: Ucode length identifier 32KB or 64KB + * @ucode_blk: Ucode Block Number + */ +union ucd_core_eid_ucode_block_num { + u64 value; + struct { +#if (defined(__BIG_ENDIAN_BITFIELD)) + u64 raz_4_63 : 60; + u64 ucode_len : 1; + u64 ucode_blk : 3; +#else + u64 ucode_blk : 3; + u64 ucode_len : 1; + u64 raz_4_63 : 60; +#endif + }; +}; + +/** + * struct aqm_grp_execmsk_lo - Available AE engines for the group + * @exec_0_to_39: AE engines 0 to 39 status + */ +union aqm_grp_execmsk_lo { + u64 value; + struct { +#if (defined(__BIG_ENDIAN_BITFIELD)) + u64 raz_40_63 : 24; + u64 exec_0_to_39 : 40; +#else + u64 exec_0_to_39 : 40; + u64 raz_40_63 : 24; +#endif + }; +}; + +/** + * struct aqm_grp_execmsk_hi - Available AE engines for the group + * @exec_40_to_79: AE engines 40 to 79 status + */ +union aqm_grp_execmsk_hi { + u64 value; + struct { +#if (defined(__BIG_ENDIAN_BITFIELD)) + u64 raz_40_63 : 24; + u64 exec_40_to_79 : 40; +#else + u64 exec_40_to_79 : 40; + u64 raz_40_63 : 24; +#endif + }; +}; + /** * struct emu_fuse_map - EMU Fuse Map Registers * @ae_fuse: Fuse settings for AE 19..0 diff --git a/drivers/crypto/cavium/nitrox/nitrox_debugfs.c b/drivers/crypto/cavium/nitrox/nitrox_debugfs.c index 848ec93d4333..16f7d0bd1303 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_debugfs.c +++ b/drivers/crypto/cavium/nitrox/nitrox_debugfs.c @@ -9,7 +9,8 @@ static int firmware_show(struct seq_file *s, void *v) { struct nitrox_device *ndev = s->private; - seq_printf(s, "Version: %s\n", ndev->hw.fw_name); + seq_printf(s, "Version: %s\n", ndev->hw.fw_name[0]); + seq_printf(s, "Version: %s\n", ndev->hw.fw_name[1]); return 0; } diff --git a/drivers/crypto/cavium/nitrox/nitrox_dev.h b/drivers/crypto/cavium/nitrox/nitrox_dev.h index 0338877b828f..5ee98eca728c 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_dev.h +++ b/drivers/crypto/cavium/nitrox/nitrox_dev.h @@ -10,6 +10,8 @@ #define VERSION_LEN 32 /* Maximum queues in PF mode */ #define MAX_PF_QUEUES 64 +/* Maximum UCD Blocks */ +#define CNN55XX_MAX_UCD_BLOCKS 8 /** * struct nitrox_cmdq - NITROX command queue @@ -74,7 +76,7 @@ struct nitrox_cmdq { */ struct nitrox_hw { char partname[IFNAMSIZ * 2]; - char fw_name[VERSION_LEN]; + char fw_name[CNN55XX_MAX_UCD_BLOCKS][VERSION_LEN]; int freq; u16 vendor_id; diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c index fe825d0ef9ca..345d3ea10b1f 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_main.c +++ b/drivers/crypto/cavium/nitrox/nitrox_main.c @@ -17,12 +17,17 @@ #define CNN55XX_DEV_ID 0x12 #define UCODE_HLEN 48 -#define SE_GROUP 0 +#define DEFAULT_SE_GROUP 0 +#define DEFAULT_AE_GROUP 0 -#define DRIVER_VERSION "1.1" +#define DRIVER_VERSION "1.2" +#define CNN55XX_UCD_BLOCK_SIZE 32768 +#define CNN55XX_MAX_UCODE_SIZE (CNN55XX_UCD_BLOCK_SIZE * 2) #define FW_DIR "cavium/" /* SE microcode */ #define SE_FW FW_DIR "cnn55xx_se.fw" +/* AE microcode */ +#define AE_FW FW_DIR "cnn55xx_ae.fw" static const char nitrox_driver_name[] = "CNN55XX"; @@ -72,10 +77,10 @@ struct ucode { /** * write_to_ucd_unit - Write Firmware to NITROX UCD unit */ -static void write_to_ucd_unit(struct nitrox_device *ndev, - struct ucode *ucode) +static void write_to_ucd_unit(struct nitrox_device *ndev, u32 ucode_size, + u64 *ucode_data, int block_num) { - u32 code_size = be32_to_cpu(ucode->code_size) * 2; + u32 code_size; u64 offset, data; int i = 0; @@ -96,11 +101,12 @@ static void write_to_ucd_unit(struct nitrox_device *ndev, /* set the block number */ offset = UCD_UCODE_LOAD_BLOCK_NUM; - nitrox_write_csr(ndev, offset, 0); + nitrox_write_csr(ndev, offset, block_num); + code_size = ucode_size; code_size = roundup(code_size, 8); while (code_size) { - data = ucode->code[i]; + data = ucode_data[i]; /* write 8 bytes at a time */ offset = UCD_UCODE_LOAD_IDX_DATAX(i); nitrox_write_csr(ndev, offset, data); @@ -108,29 +114,74 @@ static void write_to_ucd_unit(struct nitrox_device *ndev, i++; } - /* put all SE cores in group 0 */ - offset = POM_GRP_EXECMASKX(SE_GROUP); - nitrox_write_csr(ndev, offset, (~0ULL)); - - for (i = 0; i < ndev->hw.se_cores; i++) { - /* - * write block number and firware length - * bit:<2:0> block number - * bit:3 is set SE uses 32KB microcode - * bit:3 is clear SE uses 64KB microcode - */ - offset = UCD_SE_EID_UCODE_BLOCK_NUMX(i); - nitrox_write_csr(ndev, offset, 0x8); - } usleep_range(300, 400); } -static int nitrox_load_fw(struct nitrox_device *ndev, const char *fw_name) +static int nitrox_load_fw(struct nitrox_device *ndev) { const struct firmware *fw; + const char *fw_name; struct ucode *ucode; - int ret; + u64 *ucode_data; + u64 offset; + union ucd_core_eid_ucode_block_num core_2_eid_val; + union aqm_grp_execmsk_lo aqm_grp_execmask_lo; + union aqm_grp_execmsk_hi aqm_grp_execmask_hi; + u32 ucode_size; + int ret, i = 0; + + fw_name = SE_FW; + dev_info(DEV(ndev), "Loading firmware \"%s\"\n", fw_name); + + ret = request_firmware(&fw, fw_name, DEV(ndev)); + if (ret < 0) { + dev_err(DEV(ndev), "failed to get firmware %s\n", fw_name); + return ret; + } + + ucode = (struct ucode *)fw->data; + + ucode_size = be32_to_cpu(ucode->code_size) * 2; + if (!ucode_size || ucode_size > CNN55XX_MAX_UCODE_SIZE) { + dev_err(DEV(ndev), "Invalid ucode size: %u for firmware %s\n", + ucode_size, fw_name); + release_firmware(fw); + return -EINVAL; + } + ucode_data = ucode->code; + + /* copy the firmware version */ + memcpy(&ndev->hw.fw_name[0][0], ucode->version, (VERSION_LEN - 2)); + ndev->hw.fw_name[0][VERSION_LEN - 1] = '\0'; + + /* Load SE Firmware on UCD Block 0 */ + write_to_ucd_unit(ndev, ucode_size, ucode_data, 0); + release_firmware(fw); + + /* put all SE cores in DEFAULT_SE_GROUP */ + offset = POM_GRP_EXECMASKX(DEFAULT_SE_GROUP); + nitrox_write_csr(ndev, offset, (~0ULL)); + + /* write block number and firmware length + * bit:<2:0> block number + * bit:3 is set SE uses 32KB microcode + * bit:3 is clear SE uses 64KB microcode + */ + core_2_eid_val.value = 0ULL; + core_2_eid_val.ucode_blk = 0; + if (ucode_size <= CNN55XX_UCD_BLOCK_SIZE) + core_2_eid_val.ucode_len = 1; + else + core_2_eid_val.ucode_len = 0; + + for (i = 0; i < ndev->hw.se_cores; i++) { + offset = UCD_SE_EID_UCODE_BLOCK_NUMX(i); + nitrox_write_csr(ndev, offset, core_2_eid_val.value); + } + + + fw_name = AE_FW; dev_info(DEV(ndev), "Loading firmware \"%s\"\n", fw_name); ret = request_firmware(&fw, fw_name, DEV(ndev)); @@ -140,13 +191,50 @@ static int nitrox_load_fw(struct nitrox_device *ndev, const char *fw_name) } ucode = (struct ucode *)fw->data; + + ucode_size = be32_to_cpu(ucode->code_size) * 2; + if (!ucode_size || ucode_size > CNN55XX_MAX_UCODE_SIZE) { + dev_err(DEV(ndev), "Invalid ucode size: %u for firmware %s\n", + ucode_size, fw_name); + release_firmware(fw); + return -EINVAL; + } + ucode_data = ucode->code; + /* copy the firmware version */ - memcpy(ndev->hw.fw_name, ucode->version, (VERSION_LEN - 2)); - ndev->hw.fw_name[VERSION_LEN - 1] = '\0'; + memcpy(&ndev->hw.fw_name[1][0], ucode->version, (VERSION_LEN - 2)); + ndev->hw.fw_name[1][VERSION_LEN - 1] = '\0'; + + /* Load AE Firmware on UCD Block 2 */ + write_to_ucd_unit(ndev, ucode_size, ucode_data, 2); - write_to_ucd_unit(ndev, ucode); release_firmware(fw); + /* put all AE cores in DEFAULT_AE_GROUP */ + offset = AQM_GRP_EXECMSK_LOX(DEFAULT_AE_GROUP); + aqm_grp_execmask_lo.exec_0_to_39 = 0xFFFFFFFFFFULL; + nitrox_write_csr(ndev, offset, aqm_grp_execmask_lo.value); + offset = AQM_GRP_EXECMSK_HIX(DEFAULT_AE_GROUP); + aqm_grp_execmask_hi.exec_40_to_79 = 0xFFFFFFFFFFULL; + nitrox_write_csr(ndev, offset, aqm_grp_execmask_hi.value); + + /* write block number and firmware length + * bit:<2:0> block number + * bit:3 is set SE uses 32KB microcode + * bit:3 is clear SE uses 64KB microcode + */ + core_2_eid_val.value = 0ULL; + core_2_eid_val.ucode_blk = 0; + if (ucode_size <= CNN55XX_UCD_BLOCK_SIZE) + core_2_eid_val.ucode_len = 1; + else + core_2_eid_val.ucode_len = 0; + + for (i = 0; i < ndev->hw.ae_cores; i++) { + offset = UCD_AE_EID_UCODE_BLOCK_NUMX(i); + nitrox_write_csr(ndev, offset, core_2_eid_val.value); + } + return 0; } @@ -309,8 +397,8 @@ static int nitrox_pf_hw_init(struct nitrox_device *ndev) nitrox_config_lbc_unit(ndev); nitrox_config_rand_unit(ndev); - /* load firmware on SE cores */ - err = nitrox_load_fw(ndev, SE_FW); + /* load firmware on cores */ + err = nitrox_load_fw(ndev); if (err) return err; -- GitLab From 4f22f32356629ab2843e873887d34868b96a82b4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 10 Jul 2019 13:32:18 +0800 Subject: [PATCH 0857/7155] crypto: Remove orphan tools/crypto directory The directory tools/crypto and the only file under it never gets built anywhere. This program should instead be incorporated into one of the existing user-space projects, crconf or libkcapi. Signed-off-by: Herbert Xu --- tools/crypto/getstat.c | 294 ----------------------------------------- 1 file changed, 294 deletions(-) delete mode 100644 tools/crypto/getstat.c diff --git a/tools/crypto/getstat.c b/tools/crypto/getstat.c deleted file mode 100644 index 9e8ff76420fa..000000000000 --- a/tools/crypto/getstat.c +++ /dev/null @@ -1,294 +0,0 @@ -/* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CR_RTA(x) ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg)))) - -static int get_stat(const char *drivername) -{ - struct { - struct nlmsghdr n; - struct crypto_user_alg cru; - } req; - struct sockaddr_nl nl; - int sd = 0, ret; - socklen_t addr_len; - struct iovec iov; - struct msghdr msg; - char buf[4096]; - struct nlmsghdr *res_n = (struct nlmsghdr *)buf; - struct crypto_user_alg *cru_res = NULL; - int res_len = 0; - struct rtattr *tb[CRYPTOCFGA_MAX + 1]; - struct rtattr *rta; - struct nlmsgerr *errmsg; - - memset(&req, 0, sizeof(req)); - memset(&buf, 0, sizeof(buf)); - memset(&msg, 0, sizeof(msg)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.cru)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = CRYPTO_MSG_GETSTAT; - req.n.nlmsg_seq = time(NULL); - - strncpy(req.cru.cru_driver_name, drivername, strlen(drivername)); - - sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_CRYPTO); - if (sd < 0) { - fprintf(stderr, "Netlink error: cannot open netlink socket"); - return -errno; - } - memset(&nl, 0, sizeof(nl)); - nl.nl_family = AF_NETLINK; - if (bind(sd, (struct sockaddr *)&nl, sizeof(nl)) < 0) { - ret = -errno; - fprintf(stderr, "Netlink error: cannot bind netlink socket"); - goto out; - } - - /* sanity check that netlink socket was successfully opened */ - addr_len = sizeof(nl); - if (getsockname(sd, (struct sockaddr *)&nl, &addr_len) < 0) { - ret = -errno; - printf("Netlink error: cannot getsockname"); - goto out; - } - if (addr_len != sizeof(nl)) { - ret = -errno; - printf("Netlink error: wrong address length %d", addr_len); - goto out; - } - if (nl.nl_family != AF_NETLINK) { - ret = -errno; - printf("Netlink error: wrong address family %d", - nl.nl_family); - goto out; - } - - memset(&nl, 0, sizeof(nl)); - nl.nl_family = AF_NETLINK; - iov.iov_base = (void *)&req.n; - iov.iov_len = req.n.nlmsg_len; - msg.msg_name = &nl; - msg.msg_namelen = sizeof(nl); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - if (sendmsg(sd, &msg, 0) < 0) { - ret = -errno; - printf("Netlink error: sendmsg failed"); - goto out; - } - memset(buf, 0, sizeof(buf)); - iov.iov_base = buf; - while (1) { - iov.iov_len = sizeof(buf); - ret = recvmsg(sd, &msg, 0); - if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - ret = -errno; - printf("Netlink error: netlink receive error"); - goto out; - } - if (ret == 0) { - ret = -errno; - printf("Netlink error: no data"); - goto out; - } - if (ret > sizeof(buf)) { - ret = -errno; - printf("Netlink error: received too much data"); - goto out; - } - break; - } - - ret = -EFAULT; - res_len = res_n->nlmsg_len; - if (res_n->nlmsg_type == NLMSG_ERROR) { - errmsg = NLMSG_DATA(res_n); - fprintf(stderr, "Fail with %d\n", errmsg->error); - ret = errmsg->error; - goto out; - } - - if (res_n->nlmsg_type == CRYPTO_MSG_GETSTAT) { - cru_res = NLMSG_DATA(res_n); - res_len -= NLMSG_SPACE(sizeof(*cru_res)); - } - if (res_len < 0) { - printf("Netlink error: nlmsg len %d\n", res_len); - goto out; - } - - if (!cru_res) { - ret = -EFAULT; - printf("Netlink error: no cru_res\n"); - goto out; - } - - rta = CR_RTA(cru_res); - memset(tb, 0, sizeof(struct rtattr *) * (CRYPTOCFGA_MAX + 1)); - while (RTA_OK(rta, res_len)) { - if ((rta->rta_type <= CRYPTOCFGA_MAX) && (!tb[rta->rta_type])) - tb[rta->rta_type] = rta; - rta = RTA_NEXT(rta, res_len); - } - if (res_len) { - printf("Netlink error: unprocessed data %d", - res_len); - goto out; - } - - if (tb[CRYPTOCFGA_STAT_HASH]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_HASH]; - struct crypto_stat_hash *rhash = - (struct crypto_stat_hash *)RTA_DATA(rta); - printf("%s\tHash\n\tHash: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rhash->stat_hash_cnt, rhash->stat_hash_tlen, - rhash->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_COMPRESS]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_COMPRESS]; - struct crypto_stat_compress *rblk = - (struct crypto_stat_compress *)RTA_DATA(rta); - printf("%s\tCompress\n\tCompress: %llu bytes: %llu\n\tDecompress: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rblk->stat_compress_cnt, rblk->stat_compress_tlen, - rblk->stat_decompress_cnt, rblk->stat_decompress_tlen, - rblk->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_ACOMP]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_ACOMP]; - struct crypto_stat_compress *rcomp = - (struct crypto_stat_compress *)RTA_DATA(rta); - printf("%s\tACompress\n\tCompress: %llu bytes: %llu\n\tDecompress: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rcomp->stat_compress_cnt, rcomp->stat_compress_tlen, - rcomp->stat_decompress_cnt, rcomp->stat_decompress_tlen, - rcomp->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_AEAD]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_AEAD]; - struct crypto_stat_aead *raead = - (struct crypto_stat_aead *)RTA_DATA(rta); - printf("%s\tAEAD\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - raead->stat_encrypt_cnt, raead->stat_encrypt_tlen, - raead->stat_decrypt_cnt, raead->stat_decrypt_tlen, - raead->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_BLKCIPHER]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_BLKCIPHER]; - struct crypto_stat_cipher *rblk = - (struct crypto_stat_cipher *)RTA_DATA(rta); - printf("%s\tCipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, - rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, - rblk->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_AKCIPHER]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_AKCIPHER]; - struct crypto_stat_akcipher *rblk = - (struct crypto_stat_akcipher *)RTA_DATA(rta); - printf("%s\tAkcipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n\tSign: %llu\n\tVerify: %llu\n\tErrors: %llu\n", - drivername, - rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, - rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, - rblk->stat_sign_cnt, rblk->stat_verify_cnt, - rblk->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_CIPHER]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_CIPHER]; - struct crypto_stat_cipher *rblk = - (struct crypto_stat_cipher *)RTA_DATA(rta); - printf("%s\tcipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, - rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, - rblk->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_RNG]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_RNG]; - struct crypto_stat_rng *rrng = - (struct crypto_stat_rng *)RTA_DATA(rta); - printf("%s\tRNG\n\tSeed: %llu\n\tGenerate: %llu bytes: %llu\n\tErrors: %llu\n", - drivername, - rrng->stat_seed_cnt, - rrng->stat_generate_cnt, rrng->stat_generate_tlen, - rrng->stat_err_cnt); - } else if (tb[CRYPTOCFGA_STAT_KPP]) { - struct rtattr *rta = tb[CRYPTOCFGA_STAT_KPP]; - struct crypto_stat_kpp *rkpp = - (struct crypto_stat_kpp *)RTA_DATA(rta); - printf("%s\tKPP\n\tSetsecret: %llu\n\tGenerate public key: %llu\n\tCompute_shared_secret: %llu\n\tErrors: %llu\n", - drivername, - rkpp->stat_setsecret_cnt, - rkpp->stat_generate_public_key_cnt, - rkpp->stat_compute_shared_secret_cnt, - rkpp->stat_err_cnt); - } else { - fprintf(stderr, "%s is of an unknown algorithm\n", drivername); - } - ret = 0; -out: - close(sd); - return ret; -} - -int main(int argc, const char *argv[]) -{ - char buf[4096]; - FILE *procfd; - int i, lastspace; - int ret; - - procfd = fopen("/proc/crypto", "r"); - if (!procfd) { - ret = errno; - fprintf(stderr, "Cannot open /proc/crypto %s\n", strerror(errno)); - return ret; - } - if (argc > 1) { - if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { - printf("Usage: %s [-h|--help] display this help\n", argv[0]); - printf("Usage: %s display all crypto statistics\n", argv[0]); - printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv[0]); - return 0; - } - for (i = 1; i < argc; i++) { - ret = get_stat(argv[i]); - if (ret) { - fprintf(stderr, "Failed with %s\n", strerror(-ret)); - return ret; - } - } - return 0; - } - - while (fgets(buf, sizeof(buf), procfd)) { - if (!strncmp(buf, "driver", 6)) { - lastspace = 0; - i = 0; - while (i < strlen(buf)) { - i++; - if (buf[i] == ' ') - lastspace = i; - } - buf[strlen(buf) - 1] = '\0'; - ret = get_stat(buf + lastspace + 1); - if (ret) { - fprintf(stderr, "Failed with %s\n", strerror(-ret)); - goto out; - } - } - } -out: - fclose(procfd); - return ret; -} -- GitLab From 2a03e3a50a61494fd26d82eabd43a26be0f736cc Mon Sep 17 00:00:00 2001 From: "Hook, Gary" Date: Wed, 10 Jul 2019 21:45:37 +0000 Subject: [PATCH 0858/7155] crypto: ccp - Include the module name in system log messages Redefine pr_fmt so that the module name is prefixed to every log message produced by the ccp-crypto module Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 25409cea8465..599f7f2820a0 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -24,6 +24,10 @@ #include #include +/* We want the module name in front of our messages */ +#undef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define CCP_LOG_LEVEL KERN_INFO #define CCP_CRA_PRIORITY 300 -- GitLab From 2448c813b12cf1fb08da1d20bdb2ae583cda2d6f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Jul 2019 09:42:44 +0300 Subject: [PATCH 0859/7155] ASoC: ti: davinci-mcasp: Support for correct symmetric sample bits Implement custom snd_pcm_hw_rule to filter the available formats for the second stream to make it symmetric and allow only formats which require the same amount of bits on the bus as the running stream. A simple constraint is not working correctly because for example: the first stream is started with S24_LE If we place 24 as constraint for the SAMPLE_BITS then the second stream can not use S24_LE as it is physically 32bits. If we would place 32 as constraint (physical width) then S32_LE would have been allowed, but S24_3LE is not. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190726064244.3762-3-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 50 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 87ae19329e71..7aa3c32e4a49 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -109,6 +109,7 @@ struct davinci_mcasp { /* Used for comstraint setting on the second stream */ u32 channels; + int max_format_width; u8 active_serializers[2]; #ifdef CONFIG_GPIOLIB @@ -766,6 +767,8 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, if (mcasp->slot_width) slot_width = mcasp->slot_width; + else if (mcasp->max_format_width) + slot_width = mcasp->max_format_width; else slot_width = sample_width; /* @@ -1233,8 +1236,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, davinci_config_channel_size(mcasp, word_length); - if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { mcasp->channels = channels; + if (!mcasp->max_format_width) + mcasp->max_format_width = word_length; + } return 0; } @@ -1286,6 +1292,28 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params, return snd_mask_refine(fmt, &nfmt); } +static int davinci_mcasp_hw_rule_format_width(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct davinci_mcasp_ruledata *rd = rule->private; + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_mask nfmt; + int i, format_width; + + snd_mask_none(&nfmt); + format_width = rd->mcasp->max_format_width; + + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + if (snd_mask_test(fmt, i)) { + if (snd_pcm_format_width(i) == format_width) { + snd_mask_set(&nfmt, i); + } + } + } + + return snd_mask_refine(fmt, &nfmt); +} + static const unsigned int davinci_mcasp_dai_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, @@ -1463,7 +1491,20 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &mcasp->chconstr[substream->stream]); - if (mcasp->slot_width) { + if (mcasp->max_format_width) { + /* + * Only allow formats which require same amount of bits on the + * bus as the currently running stream + */ + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + davinci_mcasp_hw_rule_format_width, + ruledata, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) + return ret; + } + else if (mcasp->slot_width) { /* Only allow formats require <= slot_width bits on the bus */ ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, @@ -1514,8 +1555,10 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream, if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) return; - if (!cpu_dai->active) + if (!cpu_dai->active) { mcasp->channels = 0; + mcasp->max_format_width = 0; + } } static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { @@ -1571,7 +1614,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }, .ops = &davinci_mcasp_dai_ops, - .symmetric_samplebits = 1, .symmetric_rates = 1, }, { -- GitLab From d8481155a3219ef427c6384022931758fbbe8ebe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 08:47:27 -0300 Subject: [PATCH 0860/7155] ASoC: sunxi: fix a sound binding broken reference Address this rename: Documentation/devicetree/bindings/sound/{sun4i-i2s.txt -> allwinner,sun4i-a10-i2s.yaml} Fixes: 0a0ca8e94ca3 ("dt-bindings: sound: Convert Allwinner I2S binding to YAML") Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9932608f32030c886d906ea656eda8408c544776.1564140865.git.mchehab+samsung@kernel.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt index 2ca3d138528e..7ecf6bd60d27 100644 --- a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt +++ b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt @@ -4,7 +4,7 @@ Allwinner SUN8I audio codec On Sun8i-A33 SoCs, the audio is separated in different parts: - A DAI driver. It uses the "sun4i-i2s" driver which is documented here: - Documentation/devicetree/bindings/sound/sun4i-i2s.txt + Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml - An analog part of the codec which is handled as PRCM registers. See Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt - An digital part of the codec which is documented in this current -- GitLab From dd65f7e19c6961ba6a69f7c925021b7a270cb950 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 26 Jul 2019 11:42:34 +0200 Subject: [PATCH 0861/7155] ALSA: hda - Show the fatal CORB/RIRB error more clearly The last fallback of CORB/RIRB communication error recovery is to turn on the single command mode, and this last resort usually means that something is really screwed up. Instead of a normal dev_err(), show the error more clearly with dev_WARN() with the caller stack trace. Also, show the bus-reset fallback also as an error, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_controller.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index c8d1b4316245..4b4cb0fd5102 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -864,10 +864,13 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, */ if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { hbus->response_reset = 1; + dev_err(chip->card->dev, + "No response from codec, resetting bus: last cmd=0x%08x\n", + bus->last_cmd[addr]); return -EAGAIN; /* give a chance to retry */ } - dev_err(chip->card->dev, + dev_WARN(chip->card->dev, "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", bus->last_cmd[addr]); chip->single_cmd = 1; -- GitLab From 2127c01b7f63b06a21559f56a8c81a3c6535bd1a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 26 Jul 2019 10:14:42 +0800 Subject: [PATCH 0862/7155] ALSA: i2c: ak4xxx-adda: Fix a possible null pointer dereference in build_adc_controls() In build_adc_controls(), there is an if statement on line 773 to check whether ak->adc_info is NULL: if (! ak->adc_info || ! ak->adc_info[mixer_ch].switch_name) When ak->adc_info is NULL, it is used on line 792: knew.name = ak->adc_info[mixer_ch].selector_name; Thus, a possible null-pointer dereference may occur. To fix this bug, referring to lines 773 and 774, ak->adc_info and ak->adc_info[mixer_ch].selector_name are checked before being used. This bug is found by a static analysis tool STCheck written by us. Signed-off-by: Jia-Ju Bai Signed-off-by: Takashi Iwai --- sound/i2c/other/ak4xxx-adda.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 5f59316f982a..7d15093844b9 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c @@ -775,11 +775,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak) return err; memset(&knew, 0, sizeof(knew)); - knew.name = ak->adc_info[mixer_ch].selector_name; - if (!knew.name) { + if (!ak->adc_info || + !ak->adc_info[mixer_ch].selector_name) { knew.name = "Capture Channel"; knew.index = mixer_ch + ak->idx_offset * 2; - } + } else + knew.name = ak->adc_info[mixer_ch].selector_name; knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; knew.info = ak4xxx_capture_source_info; -- GitLab From 3d07ffcaf32006486f8743ef35c4706d4c776661 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 14 Jul 2019 17:44:16 +0200 Subject: [PATCH 0863/7155] mac80211: add struct ieee80211_tx_status support to ieee80211_add_tx_radiotap_header Add support to ieee80211_add_tx_radiotap_header() for handling rates reported via ieee80211_tx_status. This allows us to also report HE rates. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190714154419.11854-4-john@phrozen.org [remove text about 60 GHz, mac80211 doesn't support it, fix endianness issue] Signed-off-by: Johannes Berg --- net/mac80211/status.c | 174 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 162 insertions(+), 12 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index adf6269fa363..f03aa8924d23 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -254,7 +254,8 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) tid_tx->bar_pending = true; } -static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) +static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info, + struct ieee80211_tx_status *status) { int len = sizeof(struct ieee80211_radiotap_header); @@ -272,7 +273,14 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) /* IEEE80211_RADIOTAP_MCS * IEEE80211_RADIOTAP_VHT */ - if (info->status.rates[0].idx >= 0) { + if (status && status->rate) { + if (status->rate->flags & RATE_INFO_FLAGS_MCS) + len += 3; + else if (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS) + len = ALIGN(len, 2) + 12; + else if (status->rate->flags & RATE_INFO_FLAGS_HE_MCS) + len = ALIGN(len, 2) + 12; + } else if (info->status.rates[0].idx >= 0) { if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) len += 3; else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) @@ -286,12 +294,14 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, struct ieee80211_supported_band *sband, struct sk_buff *skb, int retry_count, - int rtap_len, int shift) + int rtap_len, int shift, + struct ieee80211_tx_status *status) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_radiotap_header *rthdr; unsigned char *pos; + u16 legacy_rate = 0; u16 txflags; rthdr = skb_push(skb, rtap_len); @@ -310,14 +320,22 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, */ /* IEEE80211_RADIOTAP_RATE */ - if (info->status.rates[0].idx >= 0 && - !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS | - IEEE80211_TX_RC_VHT_MCS))) { - u16 rate; + if (status && status->rate && !(status->rate->flags & + (RATE_INFO_FLAGS_MCS | + RATE_INFO_FLAGS_60G | + RATE_INFO_FLAGS_VHT_MCS | + RATE_INFO_FLAGS_HE_MCS))) + legacy_rate = status->rate->legacy; + else if (info->status.rates[0].idx >= 0 && + !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS | + IEEE80211_TX_RC_VHT_MCS))) + legacy_rate = + sband->bitrates[info->status.rates[0].idx].bitrate; + + if (legacy_rate) { rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); - rate = sband->bitrates[info->status.rates[0].idx].bitrate; - *pos = DIV_ROUND_UP(rate, 5 * (1 << shift)); + *pos = DIV_ROUND_UP(legacy_rate, 5 * (1 << shift)); /* padding for tx flags */ pos += 2; } @@ -341,7 +359,139 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, *pos = retry_count; pos++; - if (info->status.rates[0].idx < 0) + if (status && status->rate && + (status->rate->flags & RATE_INFO_FLAGS_MCS)) { + rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); + pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | + IEEE80211_RADIOTAP_MCS_HAVE_GI | + IEEE80211_RADIOTAP_MCS_HAVE_BW; + if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI) + pos[1] |= IEEE80211_RADIOTAP_MCS_SGI; + if (status->rate->bw == RATE_INFO_BW_40) + pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40; + pos[2] = status->rate->mcs; + pos += 3; + } else if (status && status->rate && + (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)) { + u16 known = local->hw.radiotap_vht_details & + (IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); + + rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); + + /* required alignment from rthdr */ + pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2); + + /* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */ + put_unaligned_le16(known, pos); + pos += 2; + + /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */ + if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI) + *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; + pos++; + + /* u8 bandwidth */ + switch (status->rate->bw) { + case RATE_INFO_BW_160: + *pos = 11; + break; + case RATE_INFO_BW_80: + *pos = 2; + break; + case RATE_INFO_BW_40: + *pos = 1; + break; + default: + *pos = 0; + break; + } + + /* u8 mcs_nss[4] */ + *pos = (status->rate->mcs << 4) | status->rate->nss; + pos += 4; + + /* u8 coding */ + pos++; + /* u8 group_id */ + pos++; + /* u16 partial_aid */ + pos += 2; + } else if (status && status->rate && + (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) { + struct ieee80211_radiotap_he *he; + + rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE); + + /* required alignment from rthdr */ + pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2); + he = (struct ieee80211_radiotap_he *)pos; + + he->data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU | + IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); + + he->data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN); + +#define HE_PREP(f, val) le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f) + + he->data6 |= HE_PREP(DATA6_NSTS, status->rate->nss); + +#define CHECK_GI(s) \ + BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \ + (int)NL80211_RATE_INFO_HE_GI_##s) + + CHECK_GI(0_8); + CHECK_GI(1_6); + CHECK_GI(3_2); + + he->data3 |= HE_PREP(DATA3_DATA_MCS, status->rate->mcs); + he->data3 |= HE_PREP(DATA3_DATA_DCM, status->rate->he_dcm); + + he->data5 |= HE_PREP(DATA5_GI, status->rate->he_gi); + + switch (status->rate->bw) { + case RATE_INFO_BW_20: + he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); + break; + case RATE_INFO_BW_40: + he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ); + break; + case RATE_INFO_BW_80: + he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ); + break; + case RATE_INFO_BW_160: + he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ); + break; + case RATE_INFO_BW_HE_RU: +#define CHECK_RU_ALLOC(s) \ + BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_##s##T != \ + NL80211_RATE_INFO_HE_RU_ALLOC_##s + 4) + + CHECK_RU_ALLOC(26); + CHECK_RU_ALLOC(52); + CHECK_RU_ALLOC(106); + CHECK_RU_ALLOC(242); + CHECK_RU_ALLOC(484); + CHECK_RU_ALLOC(996); + CHECK_RU_ALLOC(2x996); + + he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, + status->rate->he_ru_alloc + 4); + break; + default: + WARN_ONCE(1, "Invalid SU BW %d\n", status->rate->bw); + } + + pos += sizeof(struct ieee80211_radiotap_he); + } + + if ((status && status->rate) || info->status.rates[0].idx < 0) return; /* IEEE80211_RADIOTAP_MCS @@ -655,14 +805,14 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, int rtap_len; /* send frame to monitor interfaces now */ - rtap_len = ieee80211_tx_radiotap_len(info); + rtap_len = ieee80211_tx_radiotap_len(info, status); if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { pr_err("ieee80211_tx_status: headroom too small\n"); dev_kfree_skb(skb); return; } ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count, - rtap_len, shift); + rtap_len, shift, status); /* XXX: is this sufficient for BPF? */ skb_reset_mac_header(skb); -- GitLab From ef11a931bd1c57b02fe2603ff95a392a73041f9e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 18 Jun 2019 08:19:14 +0200 Subject: [PATCH 0864/7155] mac80211: HE: add Spatial Reuse element parsing support Add support to mac80211 for parsing SPR elements as per P802.11ax_D4.0 section 9.4.2.241. Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190618061915.7102-2-john@phrozen.org Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 49 ++++++++++++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/util.c | 4 ++++ 3 files changed, 54 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index f36144eda5d6..a656f31262f1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1633,6 +1633,18 @@ struct ieee80211_he_operation { u8 optional[0]; } __packed; +/** + * struct ieee80211_he_spr - HE spatial reuse element + * + * This structure is the "HE spatial reuse element" element as + * described in P802.11ax_D4.0 section 9.4.2.241 + */ +struct ieee80211_he_spr { + u8 he_sr_control; + /* Optional 0 to 19 bytes: depends on @he_sr_control */ + u8 optional[0]; +} __packed; + /** * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field * @@ -2071,6 +2083,42 @@ ieee80211_he_oper_size(const u8 *he_oper_ie) return oper_len; } +/* HE Spatial Reuse defines */ +#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT 0x4 +#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT 0x8 + +/* + * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size + * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the the byte + * after the ext ID byte. It is assumed that he_spr_ie has at least + * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated + * this + * @return the actual size of the IE data (not including header), or 0 on error + */ +static inline u8 +ieee80211_he_spr_size(const u8 *he_spr_ie) +{ + struct ieee80211_he_spr *he_spr = (void *)he_spr_ie; + u8 spr_len = sizeof(struct ieee80211_he_spr); + u32 he_spr_params; + + /* Make sure the input is not NULL */ + if (!he_spr_ie) + return 0; + + /* Calc required length */ + he_spr_params = le32_to_cpu(he_spr->he_sr_control); + if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + spr_len++; + if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) + spr_len += 18; + + /* Add the first byte (extension ID) to the total length */ + spr_len++; + + return spr_len; +} + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -2493,6 +2541,7 @@ enum ieee80211_eid_ext { WLAN_EID_EXT_HE_OPERATION = 36, WLAN_EID_EXT_UORA = 37, WLAN_EID_EXT_HE_MU_EDCA = 38, + WLAN_EID_EXT_HE_SPR = 39, WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52, WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55, WLAN_EID_EXT_NON_INHERITANCE = 56, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4c80c0ed67a7..472c5a40317d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1480,6 +1480,7 @@ struct ieee802_11_elems { const struct ieee80211_meshconf_ie *mesh_config; const u8 *he_cap; const struct ieee80211_he_operation *he_operation; + const struct ieee80211_he_spr *he_spr; const struct ieee80211_mu_edca_param_set *mu_edca_param_set; const u8 *uora_element; const u8 *mesh_id; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3441558ef2d2..3e2aeb1a75b4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1240,6 +1240,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION && elen == 3) { elems->mbssid_config_ie = (void *)&pos[1]; + } else if (pos[0] == WLAN_EID_EXT_HE_SPR && + elen >= sizeof(*elems->he_spr) && + elen >= ieee80211_he_spr_size(&pos[1])) { + elems->he_spr = (void *)&pos[1]; } break; default: -- GitLab From a0b4496a43681cbeec03a38e1b685c80c0d7405d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 16 Jul 2019 00:09:19 +0200 Subject: [PATCH 0865/7155] mac80211: add IEEE80211_KEY_FLAG_GENERATE_MMIE to ieee80211_key_flags Add IEEE80211_KEY_FLAG_GENERATE_MMIE flag to ieee80211_key_flags in order to allow the driver to notify mac80211 to generate MMIE and that it requires sequence number generation only. This is a preliminary patch to add BIP_CMAC_128 hw support to mt7615 driver Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/dfe275f9aa0f1cc6b33085f9efd5d8447f68ad13.1563228405.git.lorenzo@kernel.org Signed-off-by: Johannes Berg --- include/net/mac80211.h | 4 ++++ net/mac80211/wpa.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 6fe4381ba0ef..9effd286c1ae 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1704,6 +1704,9 @@ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif); * a TKIP key if it only requires MIC space. Do not set together with * @IEEE80211_KEY_FLAG_GENERATE_MMIC on the same key. * @IEEE80211_KEY_FLAG_NO_AUTO_TX: Key needs explicit Tx activation. + * @IEEE80211_KEY_FLAG_GENERATE_MMIE: This flag should be set by the driver + * for a AES_CMAC key to indicate that it requires sequence number + * generation only */ enum ieee80211_key_flags { IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(0), @@ -1716,6 +1719,7 @@ enum ieee80211_key_flags { IEEE80211_KEY_FLAG_RESERVE_TAILROOM = BIT(7), IEEE80211_KEY_FLAG_PUT_MIC_SPACE = BIT(8), IEEE80211_KEY_FLAG_NO_AUTO_TX = BIT(9), + IEEE80211_KEY_FLAG_GENERATE_MMIE = BIT(10), }; /** diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index ee72779729e5..91bf32af55e9 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -946,7 +946,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) info = IEEE80211_SKB_CB(skb); - if (info->control.hw_key) + if (info->control.hw_key && + !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE)) return TX_CONTINUE; if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) @@ -962,6 +963,9 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) bip_ipn_set64(mmie->sequence_number, pn64); + if (info->control.hw_key) + return TX_CONTINUE; + bip_aad(skb, aad); /* -- GitLab From 60ad72da55ac74a67d0eae5fb57327d7b4967786 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 24 Jul 2019 18:33:56 +0200 Subject: [PATCH 0866/7155] mac80211: implement HE support for mesh Implement the basics required for supporting high efficiency with mesh: include HE information elements in beacons, probe responses, and peering action frames, and check for compatible HE configurations when peering. Signed-off-by: Sven Eckelmann Forwarded: https://patchwork.kernel.org/patch/11029299/ Link: https://lore.kernel.org/r/20190724163359.3507-2-sven@narfation.org Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/mesh.c | 62 ++++++++++++++++++++++++++++++++++++++ net/mac80211/mesh.h | 4 +++ net/mac80211/mesh_plink.c | 12 +++++++- net/mac80211/util.c | 49 ++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 472c5a40317d..a5818ff0e2a4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2136,9 +2136,11 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, u32 cap); u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, const struct cfg80211_chan_def *chandef); +u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype); u8 *ieee80211_ie_build_he_cap(u8 *pos, const struct ieee80211_sta_he_cap *he_cap, u8 *end); +u8 *ieee80211_ie_build_he_oper(u8 *pos); int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, const struct ieee80211_supported_band *sband, const u8 *srates, int srates_len, u32 *rates); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2e7fa743c892..d09b3c789314 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -532,6 +532,61 @@ int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata, return 0; } +int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u8 ie_len) +{ + const struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_supported_band *sband; + u8 *pos; + + sband = ieee80211_get_sband(sdata); + if (!sband) + return -EINVAL; + + he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT); + + if (!he_cap || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) + return 0; + + if (skb_tailroom(skb) < ie_len) + return -ENOMEM; + + pos = skb_put(skb, ie_len); + ieee80211_ie_build_he_cap(pos, he_cap, pos + ie_len); + + return 0; +} + +int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + const struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_supported_band *sband; + u8 *pos; + + sband = ieee80211_get_sband(sdata); + if (!sband) + return -EINVAL; + + he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT); + if (!he_cap || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) + return 0; + + if (skb_tailroom(skb) < 2 + 1 + sizeof(struct ieee80211_he_operation)) + return -ENOMEM; + + pos = skb_put(skb, 2 + 1 + sizeof(struct ieee80211_he_operation)); + ieee80211_ie_build_he_oper(pos); + + return 0; +} + static void ieee80211_mesh_path_timer(struct timer_list *t) { struct ieee80211_sub_if_data *sdata = @@ -677,6 +732,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) struct ieee80211_chanctx_conf *chanctx_conf; struct mesh_csa_settings *csa; enum nl80211_band band; + u8 ie_len_he_cap; u8 *pos; struct ieee80211_sub_if_data *sdata; int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon); @@ -687,6 +743,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) band = chanctx_conf->def.chan->band; rcu_read_unlock(); + ie_len_he_cap = ieee80211_ie_len_he_cap(sdata, + NL80211_IFTYPE_MESH_POINT); head_len = hdr_len + 2 + /* NULL SSID */ /* Channel Switch Announcement */ @@ -706,6 +764,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) 2 + sizeof(__le16) + /* awake window */ 2 + sizeof(struct ieee80211_vht_cap) + 2 + sizeof(struct ieee80211_vht_operation) + + ie_len_he_cap + + 2 + 1 + sizeof(struct ieee80211_he_operation) + ifmsh->ie_len; bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); @@ -823,6 +883,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) mesh_add_awake_window_ie(sdata, skb) || mesh_add_vht_cap_ie(sdata, skb) || mesh_add_vht_oper_ie(sdata, skb) || + mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) || + mesh_add_he_oper_ie(sdata, skb) || mesh_add_vendor_ies(sdata, skb)) goto out_free; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 94d57cce70da..953f720754e8 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -218,6 +218,10 @@ int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); +int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u8 ie_len); +int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index dd3aefd052a9..737c5f4dbf52 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -218,9 +218,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, bool include_plid = false; u16 peering_proto = 0; u8 *pos, ie_len = 4; + u8 ie_len_he_cap; int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot); int err = -ENOMEM; + ie_len_he_cap = ieee80211_ie_len_he_cap(sdata, + NL80211_IFTYPE_MESH_POINT); skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + /* capability info */ @@ -233,6 +236,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 2 + sizeof(struct ieee80211_ht_operation) + 2 + sizeof(struct ieee80211_vht_cap) + 2 + sizeof(struct ieee80211_vht_operation) + + ie_len_he_cap + + 2 + 1 + sizeof(struct ieee80211_he_operation) + 2 + 8 + /* peering IE */ sdata->u.mesh.ie_len); if (!skb) @@ -321,7 +326,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, if (mesh_add_ht_cap_ie(sdata, skb) || mesh_add_ht_oper_ie(sdata, skb) || mesh_add_vht_cap_ie(sdata, skb) || - mesh_add_vht_oper_ie(sdata, skb)) + mesh_add_vht_oper_ie(sdata, skb) || + mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) || + mesh_add_he_oper_ie(sdata, skb)) goto free; } @@ -433,6 +440,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, elems->vht_cap_elem, sta); + ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, + elems->he_cap_len, sta); + if (bw != sta->sta.bandwidth) changed |= IEEE80211_RC_BW_CHANGED; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3e2aeb1a75b4..caa317faee3c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2713,6 +2713,27 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, return pos; } +u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) +{ + const struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_supported_band *sband; + u8 n; + + sband = ieee80211_get_sband(sdata); + if (!sband) + return 0; + + he_cap = ieee80211_get_he_iftype_cap(sband, iftype); + if (!he_cap) + return 0; + + n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem); + return 2 + 1 + + sizeof(he_cap->he_cap_elem) + n + + ieee80211_he_ppe_size(he_cap->ppe_thres[0], + he_cap->he_cap_elem.phy_cap_info); +} + u8 *ieee80211_ie_build_he_cap(u8 *pos, const struct ieee80211_sta_he_cap *he_cap, u8 *end) @@ -2902,6 +2923,34 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, return pos + sizeof(struct ieee80211_vht_operation); } +u8 *ieee80211_ie_build_he_oper(u8 *pos) +{ + struct ieee80211_he_operation *he_oper; + u32 he_oper_params; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sizeof(struct ieee80211_he_operation); + *pos++ = WLAN_EID_EXT_HE_OPERATION; + + he_oper_params = 0; + he_oper_params |= u32_encode_bits(1023, /* disabled */ + IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); + he_oper_params |= u32_encode_bits(1, + IEEE80211_HE_OPERATION_ER_SU_DISABLE); + he_oper_params |= u32_encode_bits(1, + IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED); + + he_oper = (struct ieee80211_he_operation *)pos; + he_oper->he_oper_params = cpu_to_le32(he_oper_params); + + /* don't require special HE peer rates */ + he_oper->he_mcs_nss_set = cpu_to_le16(0xffff); + + /* TODO add VHT operational and 6GHz operational subelement? */ + + return pos + sizeof(struct ieee80211_vht_operation); +} + bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, struct cfg80211_chan_def *chandef) { -- GitLab From 7a113110fc8cdda14023c0bffc7bd8b5f3da1edf Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 22 Jul 2019 06:33:10 -0500 Subject: [PATCH 0867/7155] nl80211: document uapi for CMD_FRAME_WAIT_CANCEL Commit 1c38c7f22068 ("nl80211: send event when CMD_FRAME duration expires") added the possibility of NL80211_CMD_FRAME_WAIT_CANCEL being sent whenever the off-channel wait time associated with a CMD_FRAME completes. Document this in the uapi/linux/nl80211.h file. Signed-off-by: Denis Kenzior Link: https://lore.kernel.org/r/20190722113312.14031-1-denkenz@gmail.com Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index beb9a9d0c00a..c45587c2cf44 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -657,7 +657,9 @@ * is used during CSA period. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. + * time if it is known that it is no longer necessary. This command is + * also sent as an event whenever the driver has completed the off-channel + * wait time. * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies -- GitLab From ae6fa4d5e94ea520506b691140ebcb5dc6bf0a17 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 22 Jul 2019 06:33:12 -0500 Subject: [PATCH 0868/7155] nl80211: Include wiphy address setup in NEW_WIPHY Include wiphy address setup in wiphy dumps and new wiphy events. The wiphy permanent address is exposed as ATTR_MAC. If addr_mask is setup, then it is included as ATTR_MAC_MASK attribute. If multiple addresses are available, then their are exposed in a nested ATTR_MAC_ADDRS array. This information is already exposed via sysfs, but it makes sense to include it in the wiphy dump as well. Signed-off-by: Denis Kenzior Link: https://lore.kernel.org/r/20190722113312.14031-3-denkenz@gmail.com [use just nla_nest_start(), this is new functionality] Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fc83dd179c1a..10b57aa10227 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2172,6 +2172,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, rdev->wiphy.vht_capa_mod_mask)) goto nla_put_failure; + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, + rdev->wiphy.perm_addr)) + goto nla_put_failure; + + if (!is_zero_ether_addr(rdev->wiphy.addr_mask) && + nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, + rdev->wiphy.addr_mask)) + goto nla_put_failure; + + if (rdev->wiphy.n_addresses > 1) { + void *attr; + + attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS); + if (!attr) + goto nla_put_failure; + + for (i = 0; i < rdev->wiphy.n_addresses; i++) + if (nla_put(msg, i + 1, ETH_ALEN, + rdev->wiphy.addresses[i].addr)) + goto nla_put_failure; + + nla_nest_end(msg, attr); + } + state->split_start++; break; case 10: -- GitLab From c8415833ec242b9ddf73bf9e1057e12f9b0fcd16 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Jul 2019 13:33:27 +0100 Subject: [PATCH 0869/7155] ASoC: codec2codec: fix missing return of error return code Currently in function snd_soc_dai_link_event_pre_pmu the error return code in variable err is being set but this is not actually being returned, the function just returns zero even when there are failures. Fix this by returning the error return code. Addresses-Coverity: ("Unused value") Fixes: 3dcfb397dad2 ("ASoC: codec2codec: deal with params when necessary") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190726123327.10467-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index be9bb05b0165..2d183e2d23de 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3776,7 +3776,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, struct snd_pcm_hw_params *params = NULL; const struct snd_soc_pcm_stream *config = NULL; unsigned int fmt; - int ret; + int ret = 0; params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) @@ -3865,7 +3865,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, out: kfree(params); - return 0; + return ret; } static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, -- GitLab From 096769ea95380ef3048765aef676e8947bc368d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 26 Jul 2019 11:09:29 +0200 Subject: [PATCH 0870/7155] ASoC: Intel: Skylake: Remove static table index when parsing topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when we remove and reload driver we use previous ref_count value to start iterating over skl->modules which leads to out of table access. To fix this just inline the function and calculate indexes everytime we parse UUID token. Signed-off-by: Amadeusz Sławiński Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190726090929.27946-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 34 +++++++++----------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 118866cd5075..c1c37ce759bd 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -3333,25 +3333,6 @@ static int skl_tplg_get_int_tkn(struct device *dev, return tkn_count; } -static int skl_tplg_get_manifest_uuid(struct device *dev, - struct skl_dev *skl, - struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) -{ - static int ref_count; - struct skl_module *mod; - - if (uuid_tkn->token == SKL_TKN_UUID) { - mod = skl->modules[ref_count]; - guid_copy(&mod->uuid, (guid_t *)&uuid_tkn->uuid); - ref_count++; - } else { - dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); - return -EINVAL; - } - - return 0; -} - /* * Fill the manifest structure by parsing the tokens based on the * type. @@ -3362,6 +3343,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, { int tkn_count = 0, ret; int off = 0, tuple_size = 0; + u8 uuid_index = 0; struct snd_soc_tplg_vendor_array *array; struct snd_soc_tplg_vendor_value_elem *tkn_elem; @@ -3384,9 +3366,17 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, continue; case SND_SOC_TPLG_TUPLE_TYPE_UUID: - ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); - if (ret < 0) - return ret; + if (array->uuid->token != SKL_TKN_UUID) { + dev_err(dev, "Not an UUID token: %d\n", + array->uuid->token); + return -EINVAL; + } + if (uuid_index >= skl->nr_modules) { + dev_err(dev, "Too many UUID tokens\n"); + return -EINVAL; + } + guid_copy(&skl->modules[uuid_index++]->uuid, + (guid_t *)&array->uuid->uuid); tuple_size += sizeof(*array->uuid); continue; -- GitLab From 32630d526b9faaec02fa1d26582d91c01f6d476c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 11:52:34 -0300 Subject: [PATCH 0871/7155] MAINTAINERS: add entries for some documentation scripts There are some documentation scripts I wrote with doesn't have any maintainer at maintainer's file. Add them to the DOCUMENTATION entry, in order to have Jon and linux-doc ML c/c on those patches, plus a new entry to ensure that I'll be c/c when people send patches to those. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ff3ae2be2746..6d397fa03436 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4947,7 +4947,9 @@ M: Jonathan Corbet L: linux-doc@vger.kernel.org S: Maintained F: Documentation/ +F: scripts/documentation-file-ref-check F: scripts/kernel-doc +F: scripts/sphinx-pre-install X: Documentation/ABI/ X: Documentation/firmware-guide/acpi/ X: Documentation/devicetree/ @@ -4963,6 +4965,14 @@ L: linux-doc@vger.kernel.org S: Maintained F: Documentation/translations/it_IT +DOCUMENTATION SCRIPTS +M: Mauro Carvalho Chehab +L: linux-doc@vger.kernel.org +S: Maintained +F: scripts/documentation-file-ref-check +F: scripts/sphinx-pre-install +F: Documentation/sphinx/parse-headers.pl + DONGWOON DW9714 LENS VOICE COIL DRIVER M: Sakari Ailus L: linux-media@vger.kernel.org -- GitLab From 1fbf400b58fa70c35bf671ff640b83799e45388d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 26 Jul 2019 14:10:30 -0700 Subject: [PATCH 0872/7155] staging: octeon: Fix build failure due to typo. drivers/staging/octeon/ethernet-tx.c:287:23: error: implicit declaration of function 'skb_drag_size'; did you mean 'skb_frag_size'? [-Werror=implicit-function-declaration] From kernelci report: https://kernelci.org/build/id/5d3943f859b514103f688918/logs/ Fixes: 92493a2f8a8d ("Build fixes for skb_frag_size conversion") Signed-off-by: David S. Miller --- drivers/staging/octeon/ethernet-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 46a6fcf1414d..44f79cd32750 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -284,7 +284,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb_frag_address(fs)); - hw_buffer.s.size = skb_drag_size(fs); + hw_buffer.s.size = skb_frag_size(fs); CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb)); -- GitLab From cd8ae2073963eff4c318d0a1f0e91fc35f0c6a83 Mon Sep 17 00:00:00 2001 From: Sergej Benilov Date: Thu, 25 Jul 2019 21:48:06 +0200 Subject: [PATCH 0873/7155] sis900: add support for ethtool's EEPROM dump Implement ethtool's EEPROM dump command (ethtool -e|--eeprom-dump). Thx to Andrew Lunn for comments. Signed-off-by: Sergej Benilov Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/sis/sis900.c | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 6e07f5ebacfc..85eaccbbbac1 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -191,6 +191,8 @@ struct sis900_private { unsigned int tx_full; /* The Tx queue is full. */ u8 host_bridge_rev; u8 chipset_rev; + /* EEPROM data */ + int eeprom_size; }; MODULE_AUTHOR("Jim Huang , Ollie Lho "); @@ -475,6 +477,8 @@ static int sis900_probe(struct pci_dev *pci_dev, sis_priv->pci_dev = pci_dev; spin_lock_init(&sis_priv->lock); + sis_priv->eeprom_size = 24; + pci_set_drvdata(pci_dev, net_dev); ring_space = pci_alloc_consistent(pci_dev, TX_TOTAL_SIZE, &ring_dma); @@ -2122,6 +2126,68 @@ static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *w wol->supported = (WAKE_PHY | WAKE_MAGIC); } +static int sis900_get_eeprom_len(struct net_device *dev) +{ + struct sis900_private *sis_priv = netdev_priv(dev); + + return sis_priv->eeprom_size; +} + +static int sis900_read_eeprom(struct net_device *net_dev, u8 *buf) +{ + struct sis900_private *sis_priv = netdev_priv(net_dev); + void __iomem *ioaddr = sis_priv->ioaddr; + int wait, ret = -EAGAIN; + u16 signature; + u16 *ebuf = (u16 *)buf; + int i; + + if (sis_priv->chipset_rev == SIS96x_900_REV) { + sw32(mear, EEREQ); + for (wait = 0; wait < 2000; wait++) { + if (sr32(mear) & EEGNT) { + /* read 16 bits, and index by 16 bits */ + for (i = 0; i < sis_priv->eeprom_size / 2; i++) + ebuf[i] = (u16)read_eeprom(ioaddr, i); + ret = 0; + break; + } + udelay(1); + } + sw32(mear, EEDONE); + } else { + signature = (u16)read_eeprom(ioaddr, EEPROMSignature); + if (signature != 0xffff && signature != 0x0000) { + /* read 16 bits, and index by 16 bits */ + for (i = 0; i < sis_priv->eeprom_size / 2; i++) + ebuf[i] = (u16)read_eeprom(ioaddr, i); + ret = 0; + } + } + return ret; +} + +#define SIS900_EEPROM_MAGIC 0xBABE +static int sis900_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) +{ + struct sis900_private *sis_priv = netdev_priv(dev); + u8 *eebuf; + int res; + + eebuf = kmalloc(sis_priv->eeprom_size, GFP_KERNEL); + if (!eebuf) + return -ENOMEM; + + eeprom->magic = SIS900_EEPROM_MAGIC; + spin_lock_irq(&sis_priv->lock); + res = sis900_read_eeprom(dev, eebuf); + spin_unlock_irq(&sis_priv->lock); + if (!res) + memcpy(data, eebuf + eeprom->offset, eeprom->len); + kfree(eebuf); + return res; +} + static const struct ethtool_ops sis900_ethtool_ops = { .get_drvinfo = sis900_get_drvinfo, .get_msglevel = sis900_get_msglevel, @@ -2132,6 +2198,8 @@ static const struct ethtool_ops sis900_ethtool_ops = { .set_wol = sis900_set_wol, .get_link_ksettings = sis900_get_link_ksettings, .set_link_ksettings = sis900_set_link_ksettings, + .get_eeprom_len = sis900_get_eeprom_len, + .get_eeprom = sis900_get_eeprom, }; /** -- GitLab From 934d24a5e1508e73c0001afb54a3916e4270428f Mon Sep 17 00:00:00 2001 From: Vitor Soares Date: Fri, 19 Jul 2019 15:30:54 +0200 Subject: [PATCH 0874/7155] i3c: move i3c_device_match_id to device.c and export it Some I3C device drivers need to know which entry matches the i3c_device object passed to the probe function Let's move i3c_device_match_id() to device.c and export it so it can be used by drivers. Signed-off-by: Vitor Soares Signed-off-by: Boris Brezillon --- drivers/i3c/device.c | 53 ++++++++++++++++++++++++++++++++++++++ drivers/i3c/master.c | 45 -------------------------------- include/linux/i3c/device.h | 4 +++ 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c index 69cc040c3a1c..9e2e1406f85e 100644 --- a/drivers/i3c/device.c +++ b/drivers/i3c/device.c @@ -200,6 +200,59 @@ struct i3c_device *dev_to_i3cdev(struct device *dev) } EXPORT_SYMBOL_GPL(dev_to_i3cdev); +/** + * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev + * @i3cdev: I3C device + * @id_table: I3C device match table + * + * Return: a pointer to an i3c_device_id object or NULL if there's no match. + */ +const struct i3c_device_id * +i3c_device_match_id(struct i3c_device *i3cdev, + const struct i3c_device_id *id_table) +{ + struct i3c_device_info devinfo; + const struct i3c_device_id *id; + + i3c_device_get_info(i3cdev, &devinfo); + + /* + * The lower 32bits of the provisional ID is just filled with a random + * value, try to match using DCR info. + */ + if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) { + u16 manuf = I3C_PID_MANUF_ID(devinfo.pid); + u16 part = I3C_PID_PART_ID(devinfo.pid); + u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid); + + /* First try to match by manufacturer/part ID. */ + for (id = id_table; id->match_flags != 0; id++) { + if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) != + I3C_MATCH_MANUF_AND_PART) + continue; + + if (manuf != id->manuf_id || part != id->part_id) + continue; + + if ((id->match_flags & I3C_MATCH_EXTRA_INFO) && + ext_info != id->extra_info) + continue; + + return id; + } + } + + /* Fallback to DCR match. */ + for (id = id_table; id->match_flags != 0; id++) { + if ((id->match_flags & I3C_MATCH_DCR) && + id->dcr == devinfo.dcr) + return id; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(i3c_device_match_id); + /** * i3c_driver_register_with_owner() - register an I3C device driver * diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index d6f8b038a896..c58729081899 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -276,51 +276,6 @@ static const struct device_type i3c_device_type = { .uevent = i3c_device_uevent, }; -static const struct i3c_device_id * -i3c_device_match_id(struct i3c_device *i3cdev, - const struct i3c_device_id *id_table) -{ - struct i3c_device_info devinfo; - const struct i3c_device_id *id; - - i3c_device_get_info(i3cdev, &devinfo); - - /* - * The lower 32bits of the provisional ID is just filled with a random - * value, try to match using DCR info. - */ - if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) { - u16 manuf = I3C_PID_MANUF_ID(devinfo.pid); - u16 part = I3C_PID_PART_ID(devinfo.pid); - u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid); - - /* First try to match by manufacturer/part ID. */ - for (id = id_table; id->match_flags != 0; id++) { - if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) != - I3C_MATCH_MANUF_AND_PART) - continue; - - if (manuf != id->manuf_id || part != id->part_id) - continue; - - if ((id->match_flags & I3C_MATCH_EXTRA_INFO) && - ext_info != id->extra_info) - continue; - - return id; - } - } - - /* Fallback to DCR match. */ - for (id = id_table; id->match_flags != 0; id++) { - if ((id->match_flags & I3C_MATCH_DCR) && - id->dcr == devinfo.dcr) - return id; - } - - return NULL; -} - static int i3c_device_match(struct device *dev, struct device_driver *drv) { struct i3c_device *i3cdev; diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 5ecb055fd375..de102e4418ab 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -188,6 +188,10 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv) struct device *i3cdev_to_dev(struct i3c_device *i3cdev); struct i3c_device *dev_to_i3cdev(struct device *dev); +const struct i3c_device_id * +i3c_device_match_id(struct i3c_device *i3cdev, + const struct i3c_device_id *id_table); + static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev, void *data) { -- GitLab From 72c8117adfced37df101c8c0b3f363e0906f83f0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 12 Jul 2019 10:59:24 +0200 Subject: [PATCH 0875/7155] crypto: ccp - Reduce maximum stack usage Each of the operations in ccp_run_cmd() needs several hundred bytes of kernel stack. Depending on the inlining, these may need separate stack slots that add up to more than the warning limit, as shown in this clang based build: drivers/crypto/ccp/ccp-ops.c:871:12: error: stack frame size of 1164 bytes in function 'ccp_run_aes_cmd' [-Werror,-Wframe-larger-than=] static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) The problem may also happen when there is no warning, e.g. in the ccp_run_cmd()->ccp_run_aes_cmd()->ccp_run_aes_gcm_cmd() call chain with over 2000 bytes. Mark each individual function as 'noinline_for_stack' to prevent this from happening, and move the calls to the two special cases for aes into the top-level function. This will keep the actual combined stack usage to the mimimum: 828 bytes for ccp_run_aes_gcm_cmd() and at most 524 bytes for each of the other cases. Fixes: 63b945091a07 ("crypto: ccp - CCP device driver and interface support") Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-ops.c | 52 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index c69ed4bae2eb..acf4f653f25b 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -455,8 +455,8 @@ static int ccp_copy_from_sb(struct ccp_cmd_queue *cmd_q, return ccp_copy_to_from_sb(cmd_q, wa, jobid, sb, byte_swap, true); } -static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, - struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_aes_engine *aes = &cmd->u.aes; struct ccp_dm_workarea key, ctx; @@ -611,8 +611,8 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, return ret; } -static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, - struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_aes_engine *aes = &cmd->u.aes; struct ccp_dm_workarea key, ctx, final_wa, tag; @@ -879,7 +879,8 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, return ret; } -static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_aes_engine *aes = &cmd->u.aes; struct ccp_dm_workarea key, ctx; @@ -889,12 +890,6 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) bool in_place = false; int ret; - if (aes->mode == CCP_AES_MODE_CMAC) - return ccp_run_aes_cmac_cmd(cmd_q, cmd); - - if (aes->mode == CCP_AES_MODE_GCM) - return ccp_run_aes_gcm_cmd(cmd_q, cmd); - if (!((aes->key_len == AES_KEYSIZE_128) || (aes->key_len == AES_KEYSIZE_192) || (aes->key_len == AES_KEYSIZE_256))) @@ -1061,8 +1056,8 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return ret; } -static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, - struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_xts_aes_engine *xts = &cmd->u.xts; struct ccp_dm_workarea key, ctx; @@ -1261,7 +1256,8 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, return ret; } -static int ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_des3_engine *des3 = &cmd->u.des3; @@ -1457,7 +1453,8 @@ static int ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return ret; } -static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_sha_engine *sha = &cmd->u.sha; struct ccp_dm_workarea ctx; @@ -1801,7 +1798,8 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return ret; } -static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_rsa_engine *rsa = &cmd->u.rsa; struct ccp_dm_workarea exp, src, dst; @@ -1932,8 +1930,8 @@ static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return ret; } -static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, - struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_passthru_engine *pt = &cmd->u.passthru; struct ccp_dm_workarea mask; @@ -2064,7 +2062,8 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, return ret; } -static int ccp_run_passthru_nomap_cmd(struct ccp_cmd_queue *cmd_q, +static noinline_for_stack int +ccp_run_passthru_nomap_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_passthru_nomap_engine *pt = &cmd->u.passthru_nomap; @@ -2405,7 +2404,8 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return ret; } -static int ccp_run_ecc_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +static noinline_for_stack int +ccp_run_ecc_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_ecc_engine *ecc = &cmd->u.ecc; @@ -2442,7 +2442,17 @@ int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) switch (cmd->engine) { case CCP_ENGINE_AES: - ret = ccp_run_aes_cmd(cmd_q, cmd); + switch (cmd->u.aes.mode) { + case CCP_AES_MODE_CMAC: + ret = ccp_run_aes_cmac_cmd(cmd_q, cmd); + break; + case CCP_AES_MODE_GCM: + ret = ccp_run_aes_gcm_cmd(cmd_q, cmd); + break; + default: + ret = ccp_run_aes_cmd(cmd_q, cmd); + break; + } break; case CCP_ENGINE_XTS_AES_128: ret = ccp_run_xts_aes_cmd(cmd_q, cmd); -- GitLab From d10d094cbfd338f361a83a82e5d99feb7933008d Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 17:04:37 +0800 Subject: [PATCH 0876/7155] hwrng: imx-rngc - use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Acked-by: Arnd Bergmann Reviewed-by: Dong Aisheng Signed-off-by: Herbert Xu --- drivers/char/hw_random/imx-rngc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index 69f537980004..30cf00f8e9a0 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -196,7 +196,6 @@ static int imx_rngc_init(struct hwrng *rng) static int imx_rngc_probe(struct platform_device *pdev) { struct imx_rngc *rngc; - struct resource *res; int ret; int irq; @@ -204,8 +203,7 @@ static int imx_rngc_probe(struct platform_device *pdev) if (!rngc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rngc->base = devm_ioremap_resource(&pdev->dev, res); + rngc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rngc->base)) return PTR_ERR(rngc->base); -- GitLab From f2f1d75ab725106c4958bda30f87bd39a0e3040a Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jul 2019 17:04:38 +0800 Subject: [PATCH 0877/7155] hwrng: mxc-rnga - use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Reviewed-by: Dong Aisheng Signed-off-by: Herbert Xu --- drivers/char/hw_random/mxc-rnga.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c index ea2bf18b1fbb..025083c838f5 100644 --- a/drivers/char/hw_random/mxc-rnga.c +++ b/drivers/char/hw_random/mxc-rnga.c @@ -134,7 +134,6 @@ static void mxc_rnga_cleanup(struct hwrng *rng) static int __init mxc_rnga_probe(struct platform_device *pdev) { int err; - struct resource *res; struct mxc_rng *mxc_rng; mxc_rng = devm_kzalloc(&pdev->dev, sizeof(*mxc_rng), GFP_KERNEL); @@ -158,8 +157,7 @@ static int __init mxc_rnga_probe(struct platform_device *pdev) if (err) return err; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mxc_rng->mem = devm_ioremap_resource(&pdev->dev, res); + mxc_rng->mem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mxc_rng->mem)) { err = PTR_ERR(mxc_rng->mem); goto err_ioremap; -- GitLab From 6ed01097f4378199614fe625495657af7c601cea Mon Sep 17 00:00:00 2001 From: Vakul Garg Date: Thu, 18 Jul 2019 11:29:16 +0000 Subject: [PATCH 0878/7155] crypto: caam/qi2 - Increase napi budget to process more caam responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While running ipsec processing for traffic through multiple network interfaces, it is observed that caam driver gets less time to poll responses from caam block compared to ethernet driver. This is because ethernet driver has as many napi instances per cpu as the number of ethernet interfaces in system. Therefore, caam driver's napi executes lesser than the ethernet driver's napi instances. This results in situation that we end up submitting more requests to caam (which it is able to finish off quite fast), but don't dequeue the responses at same rate. This makes caam response FQs bloat with large number of frames. In some situations, it makes kernel crash due to out-of-memory. To prevent it We increase the napi budget of dpseci driver to a big value so that caam driver is able to drain its response queues at enough rate. Signed-off-by: Vakul Garg Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h index be5085451053..973f6296bc6f 100644 --- a/drivers/crypto/caam/caamalg_qi2.h +++ b/drivers/crypto/caam/caamalg_qi2.h @@ -15,7 +15,7 @@ #define DPAA2_CAAM_STORE_SIZE 16 /* NAPI weight *must* be a multiple of the store size. */ -#define DPAA2_CAAM_NAPI_WEIGHT 64 +#define DPAA2_CAAM_NAPI_WEIGHT 512 /* The congestion entrance threshold was chosen so that on LS2088 * we support the maximum throughput for the available memory -- GitLab From bfb5eb084ae93eb86d3b088c301500db138963e5 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 18 Jul 2019 21:16:09 +0800 Subject: [PATCH 0879/7155] crypto: ccp - Replace dma_pool_alloc + memset with dma_pool_zalloc Use dma_pool_zalloc instead of using dma_pool_alloc to allocate memory and then zeroing it with memset 0. This simplifies the code. Signed-off-by: Chuhong Yuan Acked-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-ops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index acf4f653f25b..42d167574131 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -150,14 +150,13 @@ static int ccp_init_dm_workarea(struct ccp_dm_workarea *wa, if (len <= CCP_DMAPOOL_MAX_SIZE) { wa->dma_pool = cmd_q->dma_pool; - wa->address = dma_pool_alloc(wa->dma_pool, GFP_KERNEL, + wa->address = dma_pool_zalloc(wa->dma_pool, GFP_KERNEL, &wa->dma.address); if (!wa->address) return -ENOMEM; wa->dma.length = CCP_DMAPOOL_MAX_SIZE; - memset(wa->address, 0, CCP_DMAPOOL_MAX_SIZE); } else { wa->address = kzalloc(len, GFP_KERNEL); if (!wa->address) -- GitLab From 97ac82d9135d989c81268cb0a02d336993b6f9cf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 Jul 2019 15:50:04 +0200 Subject: [PATCH 0880/7155] crypto: aegis - fix badly optimized clang output Clang sometimes makes very different inlining decisions from gcc. In case of the aegis crypto algorithms, it decides to turn the innermost primitives (and, xor, ...) into separate functions but inline most of the rest. This results in a huge amount of variables spilled on the stack, leading to rather slow execution as well as kernel stack usage beyond the 32-bit warning limit when CONFIG_KASAN is enabled: crypto/aegis256.c:123:13: warning: stack frame size of 648 bytes in function 'crypto_aegis256_encrypt_chunk' [-Wframe-larger-than=] crypto/aegis256.c:366:13: warning: stack frame size of 1264 bytes in function 'crypto_aegis256_crypt' [-Wframe-larger-than=] crypto/aegis256.c:187:13: warning: stack frame size of 656 bytes in function 'crypto_aegis256_decrypt_chunk' [-Wframe-larger-than=] crypto/aegis128l.c:135:13: warning: stack frame size of 832 bytes in function 'crypto_aegis128l_encrypt_chunk' [-Wframe-larger-than=] crypto/aegis128l.c:415:13: warning: stack frame size of 1480 bytes in function 'crypto_aegis128l_crypt' [-Wframe-larger-than=] crypto/aegis128l.c:218:13: warning: stack frame size of 848 bytes in function 'crypto_aegis128l_decrypt_chunk' [-Wframe-larger-than=] crypto/aegis128.c:116:13: warning: stack frame size of 584 bytes in function 'crypto_aegis128_encrypt_chunk' [-Wframe-larger-than=] crypto/aegis128.c:351:13: warning: stack frame size of 1064 bytes in function 'crypto_aegis128_crypt' [-Wframe-larger-than=] crypto/aegis128.c:177:13: warning: stack frame size of 592 bytes in function 'crypto_aegis128_decrypt_chunk' [-Wframe-larger-than=] Forcing the primitives to all get inlined avoids the issue and the resulting code is similar to what gcc produces. Signed-off-by: Arnd Bergmann Acked-by: Nick Desaulniers Signed-off-by: Herbert Xu --- crypto/aegis.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crypto/aegis.h b/crypto/aegis.h index 6cb65a497ba2..4d56a85aea49 100644 --- a/crypto/aegis.h +++ b/crypto/aegis.h @@ -35,23 +35,23 @@ static const union aegis_block crypto_aegis_const[2] = { } }, }; -static inline void crypto_aegis_block_xor(union aegis_block *dst, - const union aegis_block *src) +static __always_inline void crypto_aegis_block_xor(union aegis_block *dst, + const union aegis_block *src) { dst->words64[0] ^= src->words64[0]; dst->words64[1] ^= src->words64[1]; } -static inline void crypto_aegis_block_and(union aegis_block *dst, - const union aegis_block *src) +static __always_inline void crypto_aegis_block_and(union aegis_block *dst, + const union aegis_block *src) { dst->words64[0] &= src->words64[0]; dst->words64[1] &= src->words64[1]; } -static inline void crypto_aegis_aesenc(union aegis_block *dst, - const union aegis_block *src, - const union aegis_block *key) +static __always_inline void crypto_aegis_aesenc(union aegis_block *dst, + const union aegis_block *src, + const union aegis_block *key) { const u8 *s = src->bytes; const u32 *t = crypto_ft_tab[0]; -- GitLab From 6fc4dbcf0276279d488c5fbbfabe94734134f4fa Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 18 Jul 2019 23:01:46 +0800 Subject: [PATCH 0881/7155] padata: Replace delayed timer with immediate workqueue in padata_reorder The function padata_reorder will use a timer when it cannot progress while completed jobs are outstanding (pd->reorder_objects > 0). This is suboptimal as if we do end up using the timer then it would have introduced a gratuitous delay of one second. In fact we can easily distinguish between whether completed jobs are outstanding and whether we can make progress. All we have to do is look at the next pqueue list. This patch does that by replacing pd->processed with pd->cpu so that the next pqueue is more accessible. A work queue is used instead of the original try_again to avoid hogging the CPU. Note that we don't bother removing the work queue in padata_flush_queues because the whole premise is broken. You cannot flush async crypto requests so it makes no sense to even try. A subsequent patch will fix it by replacing it with a ref counting scheme. Signed-off-by: Herbert Xu --- include/linux/padata.h | 13 ++---- kernel/padata.c | 97 ++++++++---------------------------------- 2 files changed, 22 insertions(+), 88 deletions(-) diff --git a/include/linux/padata.h b/include/linux/padata.h index 56f09e36f770..8da673861d99 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -73,18 +72,14 @@ struct padata_serial_queue { * @serial: List to wait for serialization after reordering. * @pwork: work struct for parallelization. * @swork: work struct for serialization. - * @pd: Backpointer to the internal control structure. * @work: work struct for parallelization. - * @reorder_work: work struct for reordering. * @num_obj: Number of objects that are processed by this cpu. * @cpu_index: Index of the cpu. */ struct padata_parallel_queue { struct padata_list parallel; struct padata_list reorder; - struct parallel_data *pd; struct work_struct work; - struct work_struct reorder_work; atomic_t num_obj; int cpu_index; }; @@ -110,10 +105,10 @@ struct padata_cpumask { * @reorder_objects: Number of objects waiting in the reorder queues. * @refcnt: Number of objects holding a reference on this parallel_data. * @max_seq_nr: Maximal used sequence number. + * @cpu: Next CPU to be processed. * @cpumask: The cpumasks in use for parallel and serial workers. + * @reorder_work: work struct for reordering. * @lock: Reorder lock. - * @processed: Number of already processed objects. - * @timer: Reorder timer. */ struct parallel_data { struct padata_instance *pinst; @@ -122,10 +117,10 @@ struct parallel_data { atomic_t reorder_objects; atomic_t refcnt; atomic_t seq_nr; + int cpu; struct padata_cpumask cpumask; + struct work_struct reorder_work; spinlock_t lock ____cacheline_aligned; - unsigned int processed; - struct timer_list timer; }; /** diff --git a/kernel/padata.c b/kernel/padata.c index 15a8ad63f4ff..fbafca18597f 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -165,23 +165,12 @@ EXPORT_SYMBOL(padata_do_parallel); */ static struct padata_priv *padata_get_next(struct parallel_data *pd) { - int cpu, num_cpus; - unsigned int next_nr, next_index; struct padata_parallel_queue *next_queue; struct padata_priv *padata; struct padata_list *reorder; + int cpu = pd->cpu; - num_cpus = cpumask_weight(pd->cpumask.pcpu); - - /* - * Calculate the percpu reorder queue and the sequence - * number of the next object. - */ - next_nr = pd->processed; - next_index = next_nr % num_cpus; - cpu = padata_index_to_cpu(pd, next_index); next_queue = per_cpu_ptr(pd->pqueue, cpu); - reorder = &next_queue->reorder; spin_lock(&reorder->lock); @@ -192,7 +181,8 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd) list_del_init(&padata->list); atomic_dec(&pd->reorder_objects); - pd->processed++; + pd->cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu, -1, + false); spin_unlock(&reorder->lock); goto out; @@ -215,6 +205,7 @@ static void padata_reorder(struct parallel_data *pd) struct padata_priv *padata; struct padata_serial_queue *squeue; struct padata_instance *pinst = pd->pinst; + struct padata_parallel_queue *next_queue; /* * We need to ensure that only one cpu can work on dequeueing of @@ -246,7 +237,6 @@ static void padata_reorder(struct parallel_data *pd) * so exit immediately. */ if (PTR_ERR(padata) == -ENODATA) { - del_timer(&pd->timer); spin_unlock_bh(&pd->lock); return; } @@ -265,70 +255,29 @@ static void padata_reorder(struct parallel_data *pd) /* * The next object that needs serialization might have arrived to - * the reorder queues in the meantime, we will be called again - * from the timer function if no one else cares for it. + * the reorder queues in the meantime. * - * Ensure reorder_objects is read after pd->lock is dropped so we see - * an increment from another task in padata_do_serial. Pairs with + * Ensure reorder queue is read after pd->lock is dropped so we see + * new objects from another task in padata_do_serial. Pairs with * smp_mb__after_atomic in padata_do_serial. */ smp_mb(); - if (atomic_read(&pd->reorder_objects) - && !(pinst->flags & PADATA_RESET)) - mod_timer(&pd->timer, jiffies + HZ); - else - del_timer(&pd->timer); - return; + next_queue = per_cpu_ptr(pd->pqueue, pd->cpu); + if (!list_empty(&next_queue->reorder.list)) + queue_work(pinst->wq, &pd->reorder_work); } static void invoke_padata_reorder(struct work_struct *work) { - struct padata_parallel_queue *pqueue; struct parallel_data *pd; local_bh_disable(); - pqueue = container_of(work, struct padata_parallel_queue, reorder_work); - pd = pqueue->pd; + pd = container_of(work, struct parallel_data, reorder_work); padata_reorder(pd); local_bh_enable(); } -static void padata_reorder_timer(struct timer_list *t) -{ - struct parallel_data *pd = from_timer(pd, t, timer); - unsigned int weight; - int target_cpu, cpu; - - cpu = get_cpu(); - - /* We don't lock pd here to not interfere with parallel processing - * padata_reorder() calls on other CPUs. We just need any CPU out of - * the cpumask.pcpu set. It would be nice if it's the right one but - * it doesn't matter if we're off to the next one by using an outdated - * pd->processed value. - */ - weight = cpumask_weight(pd->cpumask.pcpu); - target_cpu = padata_index_to_cpu(pd, pd->processed % weight); - - /* ensure to call the reorder callback on the correct CPU */ - if (cpu != target_cpu) { - struct padata_parallel_queue *pqueue; - struct padata_instance *pinst; - - /* The timer function is serialized wrt itself -- no locking - * needed. - */ - pinst = pd->pinst; - pqueue = per_cpu_ptr(pd->pqueue, target_cpu); - queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work); - } else { - padata_reorder(pd); - } - - put_cpu(); -} - static void padata_serial_worker(struct work_struct *serial_work) { struct padata_serial_queue *squeue; @@ -376,9 +325,8 @@ void padata_do_serial(struct padata_priv *padata) cpu = get_cpu(); - /* We need to run on the same CPU padata_do_parallel(.., padata, ..) - * was called on -- or, at least, enqueue the padata object into the - * correct per-cpu queue. + /* We need to enqueue the padata object into the correct + * per-cpu queue. */ if (cpu != padata->cpu) { reorder_via_wq = 1; @@ -388,12 +336,12 @@ void padata_do_serial(struct padata_priv *padata) pqueue = per_cpu_ptr(pd->pqueue, cpu); spin_lock(&pqueue->reorder.lock); - atomic_inc(&pd->reorder_objects); list_add_tail(&padata->list, &pqueue->reorder.list); + atomic_inc(&pd->reorder_objects); spin_unlock(&pqueue->reorder.lock); /* - * Ensure the atomic_inc of reorder_objects above is ordered correctly + * Ensure the addition to the reorder list is ordered correctly * with the trylock of pd->lock in padata_reorder. Pairs with smp_mb * in padata_reorder. */ @@ -401,13 +349,7 @@ void padata_do_serial(struct padata_priv *padata) put_cpu(); - /* If we're running on the wrong CPU, call padata_reorder() via a - * kernel worker. - */ - if (reorder_via_wq) - queue_work_on(cpu, pd->pinst->wq, &pqueue->reorder_work); - else - padata_reorder(pd); + padata_reorder(pd); } EXPORT_SYMBOL(padata_do_serial); @@ -463,14 +405,12 @@ static void padata_init_pqueues(struct parallel_data *pd) continue; } - pqueue->pd = pd; pqueue->cpu_index = cpu_index; cpu_index++; __padata_list_init(&pqueue->reorder); __padata_list_init(&pqueue->parallel); INIT_WORK(&pqueue->work, padata_parallel_worker); - INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder); atomic_set(&pqueue->num_obj, 0); } } @@ -498,12 +438,13 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, padata_init_pqueues(pd); padata_init_squeues(pd); - timer_setup(&pd->timer, padata_reorder_timer, 0); atomic_set(&pd->seq_nr, -1); atomic_set(&pd->reorder_objects, 0); atomic_set(&pd->refcnt, 0); pd->pinst = pinst; spin_lock_init(&pd->lock); + pd->cpu = cpumask_first(pcpumask); + INIT_WORK(&pd->reorder_work, invoke_padata_reorder); return pd; @@ -538,8 +479,6 @@ static void padata_flush_queues(struct parallel_data *pd) flush_work(&pqueue->work); } - del_timer_sync(&pd->timer); - if (atomic_read(&pd->reorder_objects)) padata_reorder(pd); -- GitLab From b93ecf4296742c36192621645f59e4a607263233 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Fri, 19 Jul 2019 10:09:23 +0300 Subject: [PATCH 0882/7155] crypto: ccree - check assoclen for rfc4543 Check assoclen to solve the extra tests that expect -EINVAL to be returned when the associated data size is not valid. Validated assoclen for RFC4543 which expects an assoclen of 16 or 20, the same as RFC4106. Based on seqiv, IPsec ESP and RFC4543/RFC4106 the assoclen is sizeof IP Header (spi, seq_no, extended seq_no) and IV len. This can be 16 or 20 bytes. Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index a9914ea6c95f..ce302adc76c7 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -2272,9 +2272,16 @@ static int cc_rfc4106_gcm_encrypt(struct aead_request *req) static int cc_rfc4543_gcm_encrypt(struct aead_request *req) { /* Very similar to cc_aead_encrypt() above. */ - + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); - int rc; + int rc = -EINVAL; + + if (!valid_assoclen(req)) { + dev_err(dev, "invalid Assoclen:%u\n", req->assoclen); + goto out; + } memset(areq_ctx, 0, sizeof(*areq_ctx)); @@ -2291,7 +2298,7 @@ static int cc_rfc4543_gcm_encrypt(struct aead_request *req) rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); if (rc != -EINPROGRESS && rc != -EBUSY) req->iv = areq_ctx->backup_iv; - +out: return rc; } @@ -2330,9 +2337,16 @@ static int cc_rfc4106_gcm_decrypt(struct aead_request *req) static int cc_rfc4543_gcm_decrypt(struct aead_request *req) { /* Very similar to cc_aead_decrypt() above. */ - + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); - int rc; + int rc = -EINVAL; + + if (!valid_assoclen(req)) { + dev_err(dev, "invalid Assoclen:%u\n", req->assoclen); + goto out; + } memset(areq_ctx, 0, sizeof(*areq_ctx)); @@ -2349,7 +2363,7 @@ static int cc_rfc4543_gcm_decrypt(struct aead_request *req) rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); if (rc != -EINPROGRESS && rc != -EBUSY) req->iv = areq_ctx->backup_iv; - +out: return rc; } -- GitLab From b3553effafa027feca33e0aa357fce08b3c80b02 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Fri, 19 Jul 2019 10:09:24 +0300 Subject: [PATCH 0883/7155] crypto: bcm - check assoclen for rfc4543/rfc4106 Validated assoclen for RFC4543 which expects an assoclen of 16 or 20, the same as RFC4106. Based on seqiv, IPsec ESP and RFC4543/RFC4106 the assoclen is sizeof IP Header (spi, seq_no, extended seq_no) and IV len. This can be 16 or 20 bytes. Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/bcm/cipher.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 869602fcfd96..1c23e452700b 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -2629,6 +2629,19 @@ static int aead_need_fallback(struct aead_request *req) return 1; } + /* + * RFC4106 and RFC4543 cannot handle the case where AAD is other than + * 16 or 20 bytes long. So use fallback in this case. + */ + if (ctx->cipher.mode == CIPHER_MODE_GCM && + ctx->cipher.alg == CIPHER_ALG_AES && + rctx->iv_ctr_len == GCM_RFC4106_IV_SIZE && + req->assoclen != 16 && req->assoclen != 20) { + flow_log("RFC4106/RFC4543 needs fallback for assoclen" + " other than 16 or 20 bytes\n"); + return 1; + } + payload_len = req->cryptlen; if (spu->spu_type == SPU_TYPE_SPUM) payload_len += req->assoclen; -- GitLab From 065cf577135a4977931c7a1e1edf442bfd9773dd Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Fri, 19 Jul 2019 15:04:44 -0400 Subject: [PATCH 0884/7155] padata: purge get_cpu and reorder_via_wq from padata_do_serial With the removal of the padata timer, padata_do_serial no longer needs special CPU handling, so remove it. Signed-off-by: Daniel Jordan Cc: Herbert Xu Cc: Steffen Klassert Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Herbert Xu --- kernel/padata.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/kernel/padata.c b/kernel/padata.c index fbafca18597f..7372fb45eeeb 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -316,24 +316,9 @@ static void padata_serial_worker(struct work_struct *serial_work) */ void padata_do_serial(struct padata_priv *padata) { - int cpu; - struct padata_parallel_queue *pqueue; - struct parallel_data *pd; - int reorder_via_wq = 0; - - pd = padata->pd; - - cpu = get_cpu(); - - /* We need to enqueue the padata object into the correct - * per-cpu queue. - */ - if (cpu != padata->cpu) { - reorder_via_wq = 1; - cpu = padata->cpu; - } - - pqueue = per_cpu_ptr(pd->pqueue, cpu); + struct parallel_data *pd = padata->pd; + struct padata_parallel_queue *pqueue = per_cpu_ptr(pd->pqueue, + padata->cpu); spin_lock(&pqueue->reorder.lock); list_add_tail(&padata->list, &pqueue->reorder.list); @@ -347,8 +332,6 @@ void padata_do_serial(struct padata_priv *padata) */ smp_mb__after_atomic(); - put_cpu(); - padata_reorder(pd); } EXPORT_SYMBOL(padata_do_serial); -- GitLab From 8dfa20fcfbeb245642dfe3a43f8a3735d9aed42a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 19 Jul 2019 23:09:18 -0700 Subject: [PATCH 0885/7155] crypto: ghash - add comment and improve help text To help avoid confusion, add a comment to ghash-generic.c which explains the convention that the kernel's implementation of GHASH uses. Also update the Kconfig help text and module descriptions to call GHASH a "hash function" rather than a "message digest", since the latter normally means a real cryptographic hash function, which GHASH is not. Cc: Pascal Van Leeuwen Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel Acked-by: Pascal Van Leeuwen Signed-off-by: Herbert Xu --- arch/arm/crypto/ghash-ce-glue.c | 2 +- arch/s390/crypto/ghash_s390.c | 2 +- arch/x86/crypto/ghash-clmulni-intel_glue.c | 3 +-- crypto/Kconfig | 11 ++++---- crypto/ghash-generic.c | 31 +++++++++++++++++++--- drivers/crypto/Kconfig | 6 ++--- include/crypto/ghash.h | 2 +- 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c index bb906b5f1eb3..c691077679a6 100644 --- a/arch/arm/crypto/ghash-ce-glue.c +++ b/arch/arm/crypto/ghash-ce-glue.c @@ -18,7 +18,7 @@ #include #include -MODULE_DESCRIPTION("GHASH secure hash using ARMv8 Crypto Extensions"); +MODULE_DESCRIPTION("GHASH hash function using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS_CRYPTO("ghash"); diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c index eeeb6a7737a4..a3e7400e031c 100644 --- a/arch/s390/crypto/ghash_s390.c +++ b/arch/s390/crypto/ghash_s390.c @@ -153,4 +153,4 @@ module_exit(ghash_mod_exit); MODULE_ALIAS_CRYPTO("ghash"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation"); +MODULE_DESCRIPTION("GHASH hash function, s390 implementation"); diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c index ac76fe88ac4f..04d72a5a8ce9 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_glue.c +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c @@ -357,6 +357,5 @@ module_init(ghash_pclmulqdqni_mod_init); module_exit(ghash_pclmulqdqni_mod_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GHASH Message Digest Algorithm, " - "accelerated by PCLMULQDQ-NI"); +MODULE_DESCRIPTION("GHASH hash function, accelerated by PCLMULQDQ-NI"); MODULE_ALIAS_CRYPTO("ghash"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 2e7f08ba0675..455a3354e291 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -647,11 +647,12 @@ config CRYPTO_VPMSUM_TESTER Unless you are testing these algorithms, you don't need this. config CRYPTO_GHASH - tristate "GHASH digest algorithm" + tristate "GHASH hash function" select CRYPTO_GF128MUL select CRYPTO_HASH help - GHASH is message digest algorithm for GCM (Galois/Counter Mode). + GHASH is the hash function used in GCM (Galois/Counter Mode). + It is not a general-purpose cryptographic hash function. config CRYPTO_POLY1305 tristate "Poly1305 authenticator algorithm" @@ -976,12 +977,12 @@ config CRYPTO_WP512 config CRYPTO_GHASH_CLMUL_NI_INTEL - tristate "GHASH digest algorithm (CLMUL-NI accelerated)" + tristate "GHASH hash function (CLMUL-NI accelerated)" depends on X86 && 64BIT select CRYPTO_CRYPTD help - GHASH is message digest algorithm for GCM (Galois/Counter Mode). - The implementation is accelerated by CLMUL-NI of Intel. + This is the x86_64 CLMUL-NI accelerated implementation of + GHASH, the hash function used in GCM (Galois/Counter mode). comment "Ciphers" diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c index dad9e1f91a78..5027b3461c92 100644 --- a/crypto/ghash-generic.c +++ b/crypto/ghash-generic.c @@ -1,12 +1,37 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * GHASH: digest algorithm for GCM (Galois/Counter Mode). + * GHASH: hash function for GCM (Galois/Counter Mode). * * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen * Copyright (c) 2009 Intel Corp. * Author: Huang Ying + */ + +/* + * GHASH is a keyed hash function used in GCM authentication tag generation. + * + * The original GCM paper [1] presents GHASH as a function GHASH(H, A, C) which + * takes a 16-byte hash key H, additional authenticated data A, and a ciphertext + * C. It formats A and C into a single byte string X, interprets X as a + * polynomial over GF(2^128), and evaluates this polynomial at the point H. + * + * However, the NIST standard for GCM [2] presents GHASH as GHASH(H, X) where X + * is the already-formatted byte string containing both A and C. + * + * "ghash" in the Linux crypto API uses the 'X' (pre-formatted) convention, + * since the API supports only a single data stream per hash. Thus, the + * formatting of 'A' and 'C' is done in the "gcm" template, not in "ghash". + * + * The reason "ghash" is separate from "gcm" is to allow "gcm" to use an + * accelerated "ghash" when a standalone accelerated "gcm(aes)" is unavailable. + * It is generally inappropriate to use "ghash" for other purposes, since it is + * an "ε-almost-XOR-universal hash function", not a cryptographic hash function. + * It can only be used securely in crypto modes specially designed to use it. * - * The algorithm implementation is copied from gcm.c. + * [1] The Galois/Counter Mode of Operation (GCM) + * (http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.694.695&rep=rep1&type=pdf) + * [2] Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC + * (https://csrc.nist.gov/publications/detail/sp/800-38d/final) */ #include @@ -156,6 +181,6 @@ subsys_initcall(ghash_mod_init); module_exit(ghash_mod_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GHASH Message Digest Algorithm"); +MODULE_DESCRIPTION("GHASH hash function"); MODULE_ALIAS_CRYPTO("ghash"); MODULE_ALIAS_CRYPTO("ghash-generic"); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 69d1bbd5d9bf..b8c50871f11b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -189,12 +189,12 @@ config S390_PRNG It is available as of z9. config CRYPTO_GHASH_S390 - tristate "GHASH digest algorithm" + tristate "GHASH hash function" depends on S390 select CRYPTO_HASH help - This is the s390 hardware accelerated implementation of the - GHASH message digest algorithm for GCM (Galois/Counter Mode). + This is the s390 hardware accelerated implementation of GHASH, + the hash function used in GCM (Galois/Counter mode). It is available as of z196. diff --git a/include/crypto/ghash.h b/include/crypto/ghash.h index 9136301062a5..f832c9f2aca3 100644 --- a/include/crypto/ghash.h +++ b/include/crypto/ghash.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Common values for GHASH algorithms + * Common values for the GHASH hash function */ #ifndef __CRYPTO_GHASH_H__ -- GitLab From a5021c4597913aad16d9d176cbd1de7fa514477e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 27 Jul 2019 16:27:35 +0200 Subject: [PATCH 0886/7155] ARM: dts: rockchip: Cleanup style around assignment operator Use a space before and after assignment operator to have consistent style. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036.dtsi | 2 +- arch/arm/boot/dts/rk3288-evb.dtsi | 2 +- arch/arm/boot/dts/rk3288-tinker.dtsi | 12 ++++++------ arch/arm/boot/dts/rk3288-veyron-edp.dtsi | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 0290ea4edd32..c776321b2cc4 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -484,7 +484,7 @@ compatible = "rockchip,rockchip-spi"; reg = <0x20074000 0x1000>; interrupts = ; - clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>; + clocks = <&cru PCLK_SPI>, <&cru SCLK_SPI>; clock-names = "apb-pclk","spi_pclk"; dmas = <&pdma 8>, <&pdma 9>; dma-names = "tx", "rx"; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 820440715302..2afd686b2033 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -97,7 +97,7 @@ }; panel: panel { - compatible ="lg,lp079qx1-sp0v", "simple-panel"; + compatible = "lg,lp079qx1-sp0v", "simple-panel"; backlight = <&backlight>; enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&lcd_cs>; diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi index 293576869546..81e4e953d4a4 100644 --- a/arch/arm/boot/dts/rk3288-tinker.dtsi +++ b/arch/arm/boot/dts/rk3288-tinker.dtsi @@ -47,13 +47,13 @@ compatible = "gpio-leds"; act-led { - gpios=<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; - linux,default-trigger="mmc0"; + gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; }; heartbeat-led { - gpios=<&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>; - linux,default-trigger="heartbeat"; + gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; }; pwr-led { @@ -443,7 +443,7 @@ &saradc { vref-supply = <&vcc18_ldo1>; - status ="okay"; + status = "okay"; }; &sdmmc { @@ -516,7 +516,7 @@ }; &usb_otg { - status= "okay"; + status = "okay"; }; &vopb { diff --git a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi index 719d936b7822..d74b6205b022 100644 --- a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-edp.dtsi @@ -86,7 +86,7 @@ }; panel: panel { - compatible ="innolux,n116bge", "simple-panel"; + compatible = "innolux,n116bge", "simple-panel"; status = "okay"; power-supply = <&panel_regulator>; backlight = <&backlight>; -- GitLab From 433514fc7002bafcfafd222bf4341c391ccffa25 Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Wed, 10 Jul 2019 21:21:54 +0200 Subject: [PATCH 0887/7155] dt-bindings: iio: chemical: pms7003: convert bindings to yaml Convert existing device tree bindings to yaml. Signed-off-by: Tomasz Duszynski Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../iio/chemical/plantower,pms7003.txt | 26 ---------- .../iio/chemical/plantower,pms7003.yaml | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 26 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt create mode 100644 Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml diff --git a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt deleted file mode 100644 index c52ea2126eaa..000000000000 --- a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt +++ /dev/null @@ -1,26 +0,0 @@ -* Plantower PMS7003 particulate matter sensor - -Required properties: -- compatible: must one of: - "plantower,pms1003" - "plantower,pms3003" - "plantower,pms5003" - "plantower,pms6003" - "plantower,pms7003" - "plantower,pmsa003" -- vcc-supply: phandle to the regulator that provides power to the sensor - -Optional properties: -- plantower,set-gpios: phandle to the GPIO connected to the SET line -- reset-gpios: phandle to the GPIO connected to the RESET line - -Refer to serial/slave-device.txt for generic serial attached device bindings. - -Example: - -&uart0 { - air-pollution-sensor { - compatible = "plantower,pms7003"; - vcc-supply = <®_vcc5v0>; - }; -}; diff --git a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml new file mode 100644 index 000000000000..a551d3101f93 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/chemical/plantower,pms7003.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Plantower PMS7003 air pollution sensor + +maintainers: + - Tomasz Duszynski + +description: | + Air pollution sensor capable of measuring mass concentration of dust + particles. + +properties: + compatible: + enum: + - plantower,pms1003 + - plantower,pms3003 + - plantower,pms5003 + - plantower,pms6003 + - plantower,pms7003 + - plantower,pmsa003 + + vcc-supply: + description: regulator that provides power to the sensor + maxItems: 1 + + plantower,set-gpios: + description: GPIO connected to the SET line + maxItems: 1 + + reset-gpios: + description: GPIO connected to the RESET line + maxItems: 1 + +required: + - compatible + - vcc-supply + +examples: + - | + serial { + air-pollution-sensor { + compatible = "plantower,pms7003"; + vcc-supply = <®_vcc5v0>; + }; + }; + +... -- GitLab From 8e97d4c8a4633f6d826e1872448435894df1794c Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Wed, 10 Jul 2019 21:21:55 +0200 Subject: [PATCH 0888/7155] MAINTAINERS: add entry for plantower pms7003 driver Add myself as a plantower pms7003 driver maintainer. Signed-off-by: Tomasz Duszynski Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..90498954685b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12775,6 +12775,12 @@ F: drivers/i2c/busses/i2c-puv3.c F: drivers/video/fbdev/fb-puv3.c F: drivers/rtc/rtc-puv3.c +PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER +M: Tomasz Duszynski +S: Maintained +F: drivers/iio/chemical/pms7003.c +F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml + PMBUS HARDWARE MONITORING DRIVERS M: Guenter Roeck L: linux-hwmon@vger.kernel.org -- GitLab From a0b4dddaa131089cedbb4dea182b136e6aa1f21e Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 8 Jul 2019 20:32:21 +0800 Subject: [PATCH 0889/7155] iio: adc: sc27xx: Introduce local variable 'struct device *dev' Introduce local variable 'struct device *dev' and use it instead of dereferencing it repeatly. Signed-off-by: Fuqian Huang Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sc27xx_adc.c | 41 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index f7f7a18904b4..ec86f640e963 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -504,88 +504,89 @@ static void sc27xx_adc_free_hwlock(void *_data) static int sc27xx_adc_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct sc27xx_adc_data *sc27xx_data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sc27xx_data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data)); if (!indio_dev) return -ENOMEM; sc27xx_data = iio_priv(indio_dev); - sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL); + sc27xx_data->regmap = dev_get_regmap(dev->parent, NULL); if (!sc27xx_data->regmap) { - dev_err(&pdev->dev, "failed to get ADC regmap\n"); + dev_err(dev, "failed to get ADC regmap\n"); return -ENODEV; } ret = of_property_read_u32(np, "reg", &sc27xx_data->base); if (ret) { - dev_err(&pdev->dev, "failed to get ADC base address\n"); + dev_err(dev, "failed to get ADC base address\n"); return ret; } sc27xx_data->irq = platform_get_irq(pdev, 0); if (sc27xx_data->irq < 0) { - dev_err(&pdev->dev, "failed to get ADC irq number\n"); + dev_err(dev, "failed to get ADC irq number\n"); return sc27xx_data->irq; } ret = of_hwspin_lock_get_id(np, 0); if (ret < 0) { - dev_err(&pdev->dev, "failed to get hwspinlock id\n"); + dev_err(dev, "failed to get hwspinlock id\n"); return ret; } sc27xx_data->hwlock = hwspin_lock_request_specific(ret); if (!sc27xx_data->hwlock) { - dev_err(&pdev->dev, "failed to request hwspinlock\n"); + dev_err(dev, "failed to request hwspinlock\n"); return -ENXIO; } - ret = devm_add_action(&pdev->dev, sc27xx_adc_free_hwlock, + ret = devm_add_action(dev, sc27xx_adc_free_hwlock, sc27xx_data->hwlock); if (ret) { sc27xx_adc_free_hwlock(sc27xx_data->hwlock); - dev_err(&pdev->dev, "failed to add hwspinlock action\n"); + dev_err(dev, "failed to add hwspinlock action\n"); return ret; } init_completion(&sc27xx_data->completion); - sc27xx_data->dev = &pdev->dev; + sc27xx_data->dev = dev; ret = sc27xx_adc_enable(sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to enable ADC module\n"); + dev_err(dev, "failed to enable ADC module\n"); return ret; } - ret = devm_add_action(&pdev->dev, sc27xx_adc_disable, sc27xx_data); + ret = devm_add_action(dev, sc27xx_adc_disable, sc27xx_data); if (ret) { sc27xx_adc_disable(sc27xx_data); - dev_err(&pdev->dev, "failed to add ADC disable action\n"); + dev_err(dev, "failed to add ADC disable action\n"); return ret; } - ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL, + ret = devm_request_threaded_irq(dev, sc27xx_data->irq, NULL, sc27xx_adc_isr, IRQF_ONESHOT, pdev->name, sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to request ADC irq\n"); + dev_err(dev, "failed to request ADC irq\n"); return ret; } - indio_dev->dev.parent = &pdev->dev; - indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = dev; + indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &sc27xx_info; indio_dev->channels = sc27xx_channels; indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels); - ret = devm_iio_device_register(&pdev->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) - dev_err(&pdev->dev, "could not register iio (ADC)"); + dev_err(dev, "could not register iio (ADC)"); return ret; } -- GitLab From 46916ded7602039f7ecc02a49dd349a90a493d8c Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 8 Jul 2019 20:32:43 +0800 Subject: [PATCH 0890/7155] iio: adc: sc27xx: Replace devm_add_action() followed by failure action with devm_add_action_or_reset() devm_add_action_or_reset() is introduced as a helper function which internally calls devm_add_action(). If devm_add_action() fails then it will execute the action mentioned and return the error code. This reduce source code size (avoid writing the action twice) and reduce the likelyhood of bugs. Signed-off-by: Fuqian Huang Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sc27xx_adc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index ec86f640e963..d7ca002cbb17 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -546,10 +546,9 @@ static int sc27xx_adc_probe(struct platform_device *pdev) return -ENXIO; } - ret = devm_add_action(dev, sc27xx_adc_free_hwlock, + ret = devm_add_action_or_reset(dev, sc27xx_adc_free_hwlock, sc27xx_data->hwlock); if (ret) { - sc27xx_adc_free_hwlock(sc27xx_data->hwlock); dev_err(dev, "failed to add hwspinlock action\n"); return ret; } @@ -563,9 +562,8 @@ static int sc27xx_adc_probe(struct platform_device *pdev) return ret; } - ret = devm_add_action(dev, sc27xx_adc_disable, sc27xx_data); + ret = devm_add_action_or_reset(dev, sc27xx_adc_disable, sc27xx_data); if (ret) { - sc27xx_adc_disable(sc27xx_data); dev_err(dev, "failed to add ADC disable action\n"); return ret; } -- GitLab From d284feaf982aa881ca78cb4d81954d7240d5d2b9 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 8 Jul 2019 20:33:41 +0800 Subject: [PATCH 0891/7155] iio: imu: mpu6050: Replace devm_add_action() followed by failure action with devm_add_action_or_reset() devm_add_action_or_reset() is introduced as a helper function which internally calls devm_add_action(). If devm_add_action() fails then it will execute the action mentioned and return the error code. This reduce source code size (avoid writing the action twice) and reduce the likelyhood of bugs. Signed-off-by: Fuqian Huang Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 53a59957cc54..e067927317bd 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -1096,10 +1096,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, if (result) return result; - result = devm_add_action(dev, inv_mpu_core_disable_regulator_action, + result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action, st); if (result) { - inv_mpu_core_disable_regulator_action(st); dev_err(dev, "Failed to setup regulator cleanup action %d\n", result); return result; -- GitLab From 82efbabfe89718215ac9d6f9c0f21ce4e3c4a9cb Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 3 Jul 2019 20:05:57 +0200 Subject: [PATCH 0892/7155] dt-bindings: Add vendor prefix for sensortek Sensortek Technology Corp. produces Proximity Sensors with ALS and Accelerometers. Signed-off-by: Luca Weiss Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6992bbbbffab..30e222193164 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -813,6 +813,8 @@ patternProperties: description: Semtech Corporation "^sensirion,.*": description: Sensirion AG + "^sensortek,.*": + description: Sensortek Technology Corporation "^sff,.*": description: Small Form Factor Committee "^sgd,.*": -- GitLab From 04a14aed81144787e05f56faa7c07206b0c7308a Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 3 Jul 2019 20:05:58 +0200 Subject: [PATCH 0893/7155] dt-bindings: iio: light: add stk33xx Add binding documentation for the stk33xx family of ambient light sensors. Signed-off-by: Luca Weiss Signed-off-by: Jonathan Cameron --- .../bindings/iio/light/stk33xx.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/stk33xx.yaml diff --git a/Documentation/devicetree/bindings/iio/light/stk33xx.yaml b/Documentation/devicetree/bindings/iio/light/stk33xx.yaml new file mode 100644 index 000000000000..aae8a6d627c9 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/stk33xx.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/stk33xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: | + Sensortek STK33xx I2C Ambient Light and Proximity sensor + +maintainers: + - Jonathan Cameron + +description: | + Ambient light and proximity sensor over an i2c interface. + +properties: + compatible: + enum: + - sensortek,stk3310 + - sensortek,stk3311 + - sensortek,stk3335 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include + + i2c { + + #address-cells = <1>; + #size-cells = <0>; + + stk3310@48 { + compatible = "sensortek,stk3310"; + reg = <0x48>; + interrupt-parent = <&gpio1>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + }; + }; +... -- GitLab From c3a686070670d9efad9a4af354ca88031cd7e7f9 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 3 Jul 2019 20:05:59 +0200 Subject: [PATCH 0894/7155] iio: light: stk3310: Add device tree support Add device tree support for the stk33xx family of ambient light sensors. Tested-by: Martijn Braam Signed-off-by: Luca Weiss Signed-off-by: Jonathan Cameron --- drivers/iio/light/stk3310.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index b955183edfe8..185c24a75ae6 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -679,9 +679,18 @@ static const struct acpi_device_id stk3310_acpi_id[] = { MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); +static const struct of_device_id stk3310_of_match[] = { + { .compatible = "sensortek,stk3310", }, + { .compatible = "sensortek,stk3311", }, + { .compatible = "sensortek,stk3335", }, + {} +}; +MODULE_DEVICE_TABLE(of, stk3310_of_match); + static struct i2c_driver stk3310_driver = { .driver = { .name = "stk3310", + .of_match_table = stk3310_of_match, .pm = STK3310_PM_OPS, .acpi_match_table = ACPI_PTR(stk3310_acpi_id), }, -- GitLab From a85a43e04523df3b0f1e5f3100592806e29966a8 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 3 Jul 2019 12:08:14 +0200 Subject: [PATCH 0895/7155] dt-bindings: iio: adc: stm32: add analog switches supply control On stm32h7 and stm32mp1, the ADC inputs are multiplexed with analog switches which have reduced performances when their supply is below 2.7V (vdda by default). Booster or vdd can be used, to get full ADC performances. Add documentation for: - optional booster-supply that can be used on stm32h7 and stm32mp1. - optional vdd-supply that can be used on stm32mp1 to supply analog circuitry, selected by syscfg. Mark these as optional, since this is a trade-off between analog performance and power consumption. Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt index 93a0bd2efc05..4c0da8c74bb2 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt @@ -47,6 +47,12 @@ Required properties: Optional properties: - A pinctrl state named "default" for each ADC channel may be defined to set inX ADC pins in mode of operation for analog input on external pin. +- booster-supply: Phandle to the embedded booster regulator that can be used + to supply ADC analog input switches on stm32h7 and stm32mp1. +- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC + analog input switches on stm32mp1. +- st,syscfg: Phandle to system configuration controller. It can be used to + control the analog circuitry on stm32mp1. Contents of a stm32 adc child node: ----------------------------------- -- GitLab From 3a81bde5457ec3292cf05c83c9a0b731b1b1531e Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 3 Jul 2019 12:08:15 +0200 Subject: [PATCH 0896/7155] iio: adc: stm32-adc: add analog switches supply control On stm32h7 and stm32mp1, the ADC inputs are multiplexed with analog switches which have reduced performances when their supply is below 2.7V (vdda by default): - 3.3V embedded booster can be used, to get full ADC performances (increases power consumption). - vdd supply can be selected if above 2.7V by setting ANASWVDD syscfg bit, on STM32MP1 only. Make this optional, since this is a trade-off between analog performance and power consumption. Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 193 ++++++++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 1f7ce5186dfc..4299cef69385 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -14,9 +14,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -51,6 +53,17 @@ #define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 +/* SYSCFG registers */ +#define STM32MP1_SYSCFG_PMCSETR 0x04 +#define STM32MP1_SYSCFG_PMCCLRR 0x44 + +/* SYSCFG bit fields */ +#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9) + +/* SYSCFG capability flags */ +#define HAS_VBOOSTER BIT(0) +#define HAS_ANASWVDD BIT(1) + /** * stm32_adc_common_regs - stm32 common registers, compatible dependent data * @csr: common status register offset @@ -74,11 +87,13 @@ struct stm32_adc_priv; * @regs: common registers for all instances * @clk_sel: clock selection routine * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) + * @has_syscfg: SYSCFG capability flags */ struct stm32_adc_priv_cfg { const struct stm32_adc_common_regs *regs; int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); u32 max_clk_rate_hz; + unsigned int has_syscfg; }; /** @@ -87,22 +102,32 @@ struct stm32_adc_priv_cfg { * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used + * @booster: booster supply reference + * @vdd: vdd supply reference * @vdda: vdda analog supply reference * @vref: regulator reference + * @vdd_uv: vdd supply voltage (microvolts) + * @vdda_uv: vdda supply voltage (microvolts) * @cfg: compatible configuration data * @common: common data for all ADC instances * @ccr_bak: backup CCR in low power mode + * @syscfg: reference to syscon, system control registers */ struct stm32_adc_priv { int irq[STM32_ADC_MAX_ADCS]; struct irq_domain *domain; struct clk *aclk; struct clk *bclk; + struct regulator *booster; + struct regulator *vdd; struct regulator *vdda; struct regulator *vref; + int vdd_uv; + int vdda_uv; const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; u32 ccr_bak; + struct regmap *syscfg; }; static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) @@ -390,6 +415,82 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, } } +static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, + struct device *dev) +{ + int ret; + + /* + * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog + * switches (via PCSEL) which have reduced performances when their + * supply is below 2.7V (vdda by default): + * - Voltage booster can be used, to get full ADC performances + * (increases power consumption). + * - Vdd can be used to supply them, if above 2.7V (STM32MP1 only). + * + * Recommended settings for ANASWVDD and EN_BOOSTER: + * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1) + * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1 + * - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default) + */ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regmap_write(priv->syscfg, + STM32MP1_SYSCFG_PMCSETR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + if (ret < 0) { + regulator_disable(priv->vdd); + dev_err(dev, "vdd select failed, %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by vdd\n"); + + return 0; + } + + if (priv->booster) { + /* + * This is optional, as this is a trade-off between + * analog performance and power consumption. + */ + ret = regulator_enable(priv->booster); + if (ret < 0) { + dev_err(dev, "booster enable failed %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by booster\n"); + + return 0; + } + } + + /* Fallback using vdda (default), nothing to do */ + dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n", + priv->vdda_uv); + + return 0; +} + +static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv) +{ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + regulator_disable(priv->vdd); + return; + } + if (priv->booster) + regulator_disable(priv->booster); + } +} + static int stm32_adc_core_hw_start(struct device *dev) { struct stm32_adc_common *common = dev_get_drvdata(dev); @@ -402,10 +503,21 @@ static int stm32_adc_core_hw_start(struct device *dev) return ret; } + ret = regulator_get_voltage(priv->vdda); + if (ret < 0) { + dev_err(dev, "vdda get voltage failed, %d\n", ret); + goto err_vdda_disable; + } + priv->vdda_uv = ret; + + ret = stm32_adc_core_switches_supply_en(priv, dev); + if (ret < 0) + goto err_vdda_disable; + ret = regulator_enable(priv->vref); if (ret < 0) { dev_err(dev, "vref enable failed\n"); - goto err_vdda_disable; + goto err_switches_dis; } if (priv->bclk) { @@ -433,6 +545,8 @@ static int stm32_adc_core_hw_start(struct device *dev) clk_disable_unprepare(priv->bclk); err_regulator_disable: regulator_disable(priv->vref); +err_switches_dis: + stm32_adc_core_switches_supply_dis(priv); err_vdda_disable: regulator_disable(priv->vdda); @@ -451,9 +565,80 @@ static void stm32_adc_core_hw_stop(struct device *dev) if (priv->bclk) clk_disable_unprepare(priv->bclk); regulator_disable(priv->vref); + stm32_adc_core_switches_supply_dis(priv); regulator_disable(priv->vdda); } +static int stm32_adc_core_switches_probe(struct device *dev, + struct stm32_adc_priv *priv) +{ + struct device_node *np = dev->of_node; + int ret; + + /* Analog switches supply can be controlled by syscfg (optional) */ + priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(priv->syscfg)) { + ret = PTR_ERR(priv->syscfg); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Can't probe syscfg: %d\n", ret); + return ret; + } + priv->syscfg = NULL; + } + + /* Booster can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_VBOOSTER && + of_property_read_bool(np, "booster-supply")) { + priv->booster = devm_regulator_get_optional(dev, "booster"); + if (IS_ERR(priv->booster)) { + ret = PTR_ERR(priv->booster); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get booster %d\n", + ret); + return ret; + } + priv->booster = NULL; + } + } + + /* Vdd can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_ANASWVDD && + of_property_read_bool(np, "vdd-supply")) { + priv->vdd = devm_regulator_get_optional(dev, "vdd"); + if (IS_ERR(priv->vdd)) { + ret = PTR_ERR(priv->vdd); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get vdd %d\n", ret); + return ret; + } + priv->vdd = NULL; + } + } + + if (priv->vdd) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regulator_get_voltage(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd get voltage failed %d\n", ret); + regulator_disable(priv->vdd); + return ret; + } + priv->vdd_uv = ret; + + regulator_disable(priv->vdd); + } + + return 0; +} + static int stm32_adc_probe(struct platform_device *pdev) { struct stm32_adc_priv *priv; @@ -514,6 +699,10 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->bclk = NULL; } + ret = stm32_adc_core_switches_probe(dev, priv); + if (ret) + return ret; + pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); @@ -611,12 +800,14 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 36000000, + .has_syscfg = HAS_VBOOSTER, }; static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 40000000, + .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, }; static const struct of_device_id stm32_adc_of_match[] = { -- GitLab From daa2b5c6229d568b7fdef5f8d33cf271fecf8b8d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 1 Jul 2019 15:56:31 +0200 Subject: [PATCH 0897/7155] Documentation: ABI: iio: Add missing newline at end of file "git diff" says: \ No newline at end of file after modifying the files. Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 index da9822309f07..0e66ae9b0071 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 @@ -13,4 +13,4 @@ Description: error on writing If DFSDM input is SPI Slave: Reading returns value previously set. - Writing value before starting conversions. \ No newline at end of file + Writing value before starting conversions. -- GitLab From dbcd2088a718875b4ef214099e9b3f378c47c2f4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 29 Jun 2019 12:13:53 +0200 Subject: [PATCH 0898/7155] iio: imu: st_lsm6dsx: add support to LSM6DS3TR-C Add support to STM LSM6DS3TR-C 6-axis (acc + gyro) Mems sensor https://www.st.com/resource/en/datasheet/lsm6ds3tr-c.pdf Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/Kconfig | 2 +- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 8 ++++---- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 5 ++++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 5 +++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 5 +++++ 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 002a423eae52..2d8b2e1edfce 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -10,7 +10,7 @@ config IIO_ST_LSM6DSX help Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, - ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr + ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c To compile this driver as a module, choose M here: the module will be called st_lsm6dsx. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index c14bf533b66b..af379a5429ed 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -22,6 +22,7 @@ #define ST_ASM330LHH_DEV_NAME "asm330lhh" #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" #define ST_LSM6DSR_DEV_NAME "lsm6dsr" +#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" enum st_lsm6dsx_hw_id { ST_LSM6DS3_ID, @@ -33,6 +34,7 @@ enum st_lsm6dsx_hw_id { ST_ASM330LHH_ID, ST_LSM6DSOX_ID, ST_LSM6DSR_ID, + ST_LSM6DS3TRC_ID, ST_LSM6DSX_MAX_ID, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index e4d8a79d557d..38194f4d2b7e 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -2,10 +2,10 @@ /* * STMicroelectronics st_lsm6dsx FIFO buffer library driver * - * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: The FIFO buffer can be - * configured to store data from gyroscope and accelerometer. Samples are - * queued without any tag according to a specific pattern based on - * 'FIFO data sets' (6 bytes each): + * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: + * The FIFO buffer can be configured to store data from gyroscope and + * accelerometer. Samples are queued without any tag according to a + * specific pattern based on 'FIFO data sets' (6 bytes each): * - 1st data set is reserved for gyroscope data * - 2nd data set is reserved for accelerometer data * The FIFO pattern changes depending on the ODRs and decimation factors diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index a6702a74570e..d8c4417cf4eb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -18,7 +18,7 @@ * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 8KB * - * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: + * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 @@ -233,6 +233,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .hw_id = ST_ISM330DLC_ID, .name = ST_ISM330DLC_DEV_NAME, + }, { + .hw_id = ST_LSM6DS3TRC_ID, + .name = ST_LSM6DS3TRC_DEV_NAME, }, }, .decimator = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index b3211e0ac07b..28581eb0532c 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -75,6 +75,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,lsm6dsr", .data = (void *)ST_LSM6DSR_ID, }, + { + .compatible = "st,lsm6ds3tr-c", + .data = (void *)ST_LSM6DS3TRC_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); @@ -89,6 +93,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, {}, }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index c9d3c4711018..0371e8b94a3e 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -75,6 +75,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,lsm6dsr", .data = (void *)ST_LSM6DSR_ID, }, + { + .compatible = "st,lsm6ds3tr-c", + .data = (void *)ST_LSM6DS3TRC_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -89,6 +93,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, {}, }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); -- GitLab From 0ebcdf3dfa3359c6a301ff1bc22cf67291d69113 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 29 Jun 2019 12:13:54 +0200 Subject: [PATCH 0899/7155] dt-bindings: iio: imu: st_lsm6dsx: add lsm6ds3tr-c device bindings Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index efec9ece034a..92b48f242356 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -11,6 +11,7 @@ Required properties: "st,asm330lhh" "st,lsm6dsox" "st,lsm6dsr" + "st,lsm6ds3tr-c" - reg: i2c address of the sensor / spi cs line Optional properties: -- GitLab From 0eec1f38c7bb53b9dd2221ac982739cce7aab7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Fernandes?= Date: Fri, 28 Jun 2019 16:49:22 -0300 Subject: [PATCH 0900/7155] staging: iio: ad7192: create of_device_id array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create list of compatible device ids to be matched with those stated in the device tree. Signed-off-by: Bárbara Fernandes Signed-off-by: Wilson Sales Co-developed by: Wilson Sales Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index b6d12fe7c12a..df06e0570f9b 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -809,11 +809,23 @@ static const struct spi_device_id ad7192_id[] = { {"ad7195", ID_AD7195}, {} }; + MODULE_DEVICE_TABLE(spi, ad7192_id); +static const struct of_device_id ad7192_of_match[] = { + { .compatible = "adi,ad7190" }, + { .compatible = "adi,ad7192" }, + { .compatible = "adi,ad7193" }, + { .compatible = "adi,ad7195" }, + {} +}; + +MODULE_DEVICE_TABLE(of, ad7192_of_match); + static struct spi_driver ad7192_driver = { .driver = { .name = "ad7192", + .of_match_table = ad7192_of_match, }, .probe = ad7192_probe, .remove = ad7192_remove, -- GitLab From b299d00420e2cc4289b1909943bb1e68634ef0bb Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 7 May 2019 11:12:24 +0200 Subject: [PATCH 0901/7155] IIO: stm32: Remove quadrature related functions from trigger driver Quadrature feature is now hosted on it own framework. Remove quadrature related code from stm32-trigger driver to avoid code duplication and simplify the ABI. Signed-off-by: Benjamin Gaignard Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-timer-stm32 | 23 ----- drivers/iio/trigger/stm32-timer-trigger.c | 84 ------------------- 2 files changed, 107 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index 161c147d3c40..b7259234ad70 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -91,29 +91,6 @@ Description: When counting down the counter start from preset value and fire event when reach 0. -What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available -KernelVersion: 4.12 -Contact: benjamin.gaignard@st.com -Description: - Reading returns the list possible quadrature modes. - -What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode -KernelVersion: 4.12 -Contact: benjamin.gaignard@st.com -Description: - Configure the device counter quadrature modes: - channel_A: - Encoder A input servers as the count input and B as - the UP/DOWN direction control input. - - channel_B: - Encoder B input serves as the count input and A as - the UP/DOWN direction control input. - - quadrature: - Encoder A and B inputs are mixed to get direction - and count with a scale of 0.25. - What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available KernelVersion: 4.12 Contact: benjamin.gaignard@st.com diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index ccf1ce653b25..a5dfe65cd9b9 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -608,86 +608,6 @@ static const struct iio_enum stm32_enable_mode_enum = { .get = stm32_get_enable_mode }; -static const char *const stm32_quadrature_modes[] = { - "channel_A", - "channel_B", - "quadrature", -}; - -static int stm32_set_quadrature_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - unsigned int mode) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - - regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, mode + 1); - - return 0; -} - -static int stm32_get_quadrature_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 smcr; - int mode; - - regmap_read(priv->regmap, TIM_SMCR, &smcr); - mode = (smcr & TIM_SMCR_SMS) - 1; - if ((mode < 0) || (mode > ARRAY_SIZE(stm32_quadrature_modes))) - return -EINVAL; - - return mode; -} - -static const struct iio_enum stm32_quadrature_mode_enum = { - .items = stm32_quadrature_modes, - .num_items = ARRAY_SIZE(stm32_quadrature_modes), - .set = stm32_set_quadrature_mode, - .get = stm32_get_quadrature_mode -}; - -static const char *const stm32_count_direction_states[] = { - "up", - "down" -}; - -static int stm32_set_count_direction(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - unsigned int dir) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 val; - int mode; - - /* In encoder mode, direction is RO (given by TI1/TI2 signals) */ - regmap_read(priv->regmap, TIM_SMCR, &val); - mode = (val & TIM_SMCR_SMS) - 1; - if ((mode >= 0) || (mode < ARRAY_SIZE(stm32_quadrature_modes))) - return -EBUSY; - - return regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_DIR, - dir ? TIM_CR1_DIR : 0); -} - -static int stm32_get_count_direction(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 cr1; - - regmap_read(priv->regmap, TIM_CR1, &cr1); - - return ((cr1 & TIM_CR1_DIR) ? 1 : 0); -} - -static const struct iio_enum stm32_count_direction_enum = { - .items = stm32_count_direction_states, - .num_items = ARRAY_SIZE(stm32_count_direction_states), - .set = stm32_set_count_direction, - .get = stm32_get_count_direction -}; - static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, @@ -728,10 +648,6 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { .read = stm32_count_get_preset, .write = stm32_count_set_preset }, - IIO_ENUM("count_direction", IIO_SEPARATE, &stm32_count_direction_enum), - IIO_ENUM_AVAILABLE("count_direction", &stm32_count_direction_enum), - IIO_ENUM("quadrature_mode", IIO_SEPARATE, &stm32_quadrature_mode_enum), - IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum), IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), -- GitLab From 80343f5b8a203c5643dfdcc87a6e7a6d4db81226 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 12:53:53 +0200 Subject: [PATCH 0902/7155] iio: sca3000: Fix a typo All #define are about SCA3000_... except the last one. Make it consistent. s/SAC3000/SCA3000/ This #define is apparently unused up to now. Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/accel/sca3000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index a923f90f6e80..66d768d971e1 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -111,7 +111,7 @@ /* Currently unsupported */ #define SCA3000_MD_CTRL_AND_Y BIT(3) #define SCA3000_MD_CTRL_AND_X BIT(4) -#define SAC3000_MD_CTRL_AND_Z BIT(5) +#define SCA3000_MD_CTRL_AND_Z BIT(5) /* * Some control registers of complex access methods requiring this register to -- GitLab From 50e5bae0c1f976e881eecf4d1ad70ce1593021c9 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 12:49:18 +0200 Subject: [PATCH 0903/7155] iio: light: apds9960: Fix a typo s/ADPS9960/APDS9960/ (P and D switched) Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/light/apds9960.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index b09b8b60bd83..c5dfb9a6b5a1 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1135,5 +1135,5 @@ static struct i2c_driver apds9960_driver = { module_i2c_driver(apds9960_driver); MODULE_AUTHOR("Matt Ranostay "); -MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor"); +MODULE_DESCRIPTION("APDS9960 Gesture/RGB/ALS/Proximity sensor"); MODULE_LICENSE("GPL"); -- GitLab From ed1f2e85da79274f3dc4092953f1359eb732f0c6 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Thu, 18 Jul 2019 16:28:24 -0700 Subject: [PATCH 0904/7155] iio: cros_ec: Add calibscale for 3d MEMS Add calibration scale support to accel, gyro and magnetometer. Check on eve with current firmware, check reading calibscale returns 1.0, check with newer firmware values are applied. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- .../common/cros_ec_sensors/cros_ec_sensors.c | 51 +++++++++++++++++-- .../cros_ec_sensors/cros_ec_sensors_core.c | 2 +- drivers/iio/light/cros_ec_light_prox.c | 12 ++--- drivers/iio/pressure/cros_ec_baro.c | 2 - .../linux/iio/common/cros_ec_sensors_core.h | 5 +- 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 17af4e0fd5f8..2af09606c438 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->core.calib[i] = + st->core.calib[i].offset = st->core.resp->sensor_offset.offset[i]; ret = IIO_VAL_INT; - *val = st->core.calib[idx]; + *val = st->core.calib[idx].offset; + break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = 0; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == -EPROTO) { + /* Reading calibscale is not supported on older EC. */ + *val = 1; + *val2 = 0; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + } else if (ret) { + break; + } + + /* Save values */ + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.calib[i].scale = + st->core.resp->sensor_scale.scale[i]; + + *val = st->core.calib[idx].scale >> 15; + *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) / + MOTION_SENSE_DEFAULT_SCALE; + ret = IIO_VAL_INT_PLUS_MICRO; break; case IIO_CHAN_INFO_SCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; @@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - st->core.calib[idx] = val; + st->core.calib[idx].offset = val; /* Send to EC for each axis, even if not complete */ st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; @@ -142,10 +167,25 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, MOTION_SENSE_SET_OFFSET; for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) st->core.param.sensor_offset.offset[i] = - st->core.calib[i]; + st->core.calib[i].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.calib[idx].scale = val; + /* Send to EC for each axis, even if not complete */ + + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = + MOTION_SENSE_SET_OFFSET; + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.param.sensor_scale.scale[i] = + st->core.calib[i].scale; + st->core.param.sensor_scale.temp = + EC_MOTION_SENSE_INVALID_CALIB_TEMP; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; case IIO_CHAN_INFO_SCALE: @@ -206,7 +246,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) /* Common part */ channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBBIAS); + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_FREQUENCY) | diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 130362ca421b..96d5aa1f4bd5 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -118,7 +118,7 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev, } else { /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->calib[i] = st->resp->perform_calib.offset[i]; + st->calib[i].offset = st->resp->perform_calib.offset[i]; } mutex_unlock(&st->cmd_lock); diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 308ee6ff2e22..b81746a99f1f 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -88,9 +88,10 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, } /* Save values */ - st->core.calib[0] = st->core.resp->sensor_offset.offset[0]; + st->core.calib[0].offset = + st->core.resp->sensor_offset.offset[0]; - *val = st->core.calib[idx]; + *val = st->core.calib[idx].offset; break; case IIO_CHAN_INFO_CALIBSCALE: /* @@ -134,11 +135,12 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - st->core.calib[idx] = val; + st->core.calib[idx].offset = val; /* Send to EC for each axis, even if not complete */ st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET; - st->core.param.sensor_offset.offset[0] = st->core.calib[0]; + st->core.param.sensor_offset.offset[0] = + st->core.calib[0].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; if (cros_ec_motion_send_host_cmd(&st->core, 0)) @@ -205,8 +207,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) channel->ext_info = cros_ec_sensors_ext_info; channel->scan_type.sign = 'u'; - state->core.calib[0] = 0; - /* Sensor specific */ switch (state->core.type) { case MOTIONSENSE_TYPE_LIGHT: diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index 034ce98d6e97..d3acba7ba582 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -152,8 +152,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev) channel->ext_info = cros_ec_sensors_ext_info; channel->scan_type.sign = 'u'; - state->core.calib[0] = 0; - /* Sensor specific */ switch (state->core.type) { case MOTIONSENSE_TYPE_BARO: diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 0c636b9fe8d7..bb03a252bd04 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -62,7 +62,10 @@ struct cros_ec_sensors_core_state { enum motionsensor_type type; enum motionsensor_location loc; - s16 calib[CROS_EC_SENSOR_MAX_AXIS]; + struct calib_data { + s16 offset; + u16 scale; + } calib[CROS_EC_SENSOR_MAX_AXIS]; u8 samples[CROS_EC_SAMPLE_SIZE]; -- GitLab From f530eed65bcaf9f74c312bbea09a36a27c48e06c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Jul 2019 10:46:11 +0100 Subject: [PATCH 0905/7155] net: neigh: remove redundant assignment to variable bucket The variable bucket is being initialized with a value that is never read and it is being updated later with a new value in a following for-loop. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f79e61c570ea..5480edff0c86 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -3033,7 +3033,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) struct net *net = seq_file_net(seq); struct neigh_hash_table *nht = state->nht; struct neighbour *n = NULL; - int bucket = state->bucket; + int bucket; state->flags &= ~NEIGH_SEQ_IS_PNEIGH; for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) { -- GitLab From 1a981c0586c038710227eb740350f291e77ce365 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 26 Jul 2019 12:27:40 +0200 Subject: [PATCH 0906/7155] net: stmmac: Make MDIO bus reset optional The Tegra EQOS driver already resets the MDIO bus at probe time via the reset GPIO specified in the phy-reset-gpios device tree property. There is no need to reset the bus again later on. This avoids the need to query the device tree for the snps,reset GPIO, which is not part of the Tegra EQOS device tree bindings. This quiesces an error message from the generic bus reset code if it doesn't find the snps,reset related delays. Signed-off-by: Thierry Reding Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 3 +++ drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 4 +++- drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 8 +++++++- include/linux/stmmac.h | 1 + 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 3a14cdd01f5f..66933332c68e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -333,6 +333,9 @@ static void *tegra_eqos_probe(struct platform_device *pdev, usleep_range(2000, 4000); gpiod_set_value(eqos->reset, 0); + /* MDIO bus was already reset just above */ + data->mdio_bus_data->needs_reset = false; + eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); if (IS_ERR(eqos->rst)) { err = PTR_ERR(eqos->rst); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 4304c1abc5d1..40c42637ad75 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -348,7 +348,9 @@ int stmmac_mdio_register(struct net_device *ndev) max_addr = PHY_MAX_ADDR; } - new_bus->reset = &stmmac_mdio_reset; + if (mdio_bus_data->needs_reset) + new_bus->reset = &stmmac_mdio_reset; + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name, priv->plat->bus_id); new_bus->priv = ndev; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 86f9c07a38cf..d5d08e11c353 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -63,6 +63,7 @@ static void common_default_data(struct plat_stmmacenet_data *plat) plat->has_gmac = 1; plat->force_sf_dma_mode = 1; + plat->mdio_bus_data->needs_reset = true; plat->mdio_bus_data->phy_mask = 0; /* Set default value for multicast hash bins */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 73fc2524372e..333b09564b88 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -342,10 +342,16 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, mdio = true; } - if (mdio) + if (mdio) { plat->mdio_bus_data = devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); + if (!plat->mdio_bus_data) + return -ENOMEM; + + plat->mdio_bus_data->needs_reset = true; + } + return 0; } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 7d06241582dd..7b3e354bcd3c 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -81,6 +81,7 @@ struct stmmac_mdio_bus_data { unsigned int phy_mask; int *irqs; int probed_phy_irq; + bool needs_reset; }; struct stmmac_dma_cfg { -- GitLab From ddfbee9e3204a0158774bbe9df0f555573e81f43 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 26 Jul 2019 12:27:41 +0200 Subject: [PATCH 0907/7155] net: stmmac: Do not request stmmaceth clock The stmmaceth clock is specified by the slave_bus and apb_pclk clocks in the device tree bindings for snps,dwc-qos-ethernet-4.10 compatible nodes of this IP. The subdrivers for these bindings will be requesting the stmmac clock correctly at a later point, so there is no need to request it here and cause an error message to be printed to the kernel log. Signed-off-by: Thierry Reding Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 333b09564b88..7ad2bb90ceb1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -521,13 +521,15 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) } /* clock setup */ - plat->stmmac_clk = devm_clk_get(&pdev->dev, - STMMAC_RESOURCE_NAME); - if (IS_ERR(plat->stmmac_clk)) { - dev_warn(&pdev->dev, "Cannot get CSR clock\n"); - plat->stmmac_clk = NULL; + if (!of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) { + plat->stmmac_clk = devm_clk_get(&pdev->dev, + STMMAC_RESOURCE_NAME); + if (IS_ERR(plat->stmmac_clk)) { + dev_warn(&pdev->dev, "Cannot get CSR clock\n"); + plat->stmmac_clk = NULL; + } + clk_prepare_enable(plat->stmmac_clk); } - clk_prepare_enable(plat->stmmac_clk); plat->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(plat->pclk)) { -- GitLab From 85d2c5cde158ce00fe965561cfc57404fbefb0a7 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 26 Jul 2019 09:20:37 -0700 Subject: [PATCH 0908/7155] drivers: net: xgene: Move status variable declaration into CONFIG_ACPI block When CONFIG_ACPI is unset (arm allyesconfig), status is unused. drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c:383:14: warning: unused variable 'status' [-Wunused-variable] acpi_status status; ^ drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:440:14: warning: unused variable 'status' [-Wunused-variable] acpi_status status; ^ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c:697:14: warning: unused variable 'status' [-Wunused-variable] acpi_status status; ^ Move the declaration into the CONFIG_ACPI block so that there are no compiler warnings. Fixes: 570d785ba46b ("drivers: net: xgene: Remove acpi_has_method() calls") Signed-off-by: Nathan Chancellor Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 3 ++- drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 3 ++- drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 79924efd4ab7..5f657879134e 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -694,7 +694,6 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -713,6 +712,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index 3b3dc5b25b29..f482ced2cadd 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -437,7 +437,6 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p) static int xgene_enet_reset(struct xgene_enet_pdata *p) { struct device *dev = &p->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(p)) return -ENODEV; @@ -461,6 +460,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p) } } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 78584089d76d..304b5d43f236 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -380,7 +380,6 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - acpi_status status; if (!xgene_ring_mgr_init(pdata)) return -ENODEV; @@ -394,6 +393,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata) udelay(5); } else { #ifdef CONFIG_ACPI + acpi_status status; + status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), "_RST", NULL, NULL); if (ACPI_FAILURE(status)) { -- GitLab From 91c6bfb8315b05d0c3aa8c2cfc172888d05e31d5 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Fri, 26 Jul 2019 20:18:12 +0200 Subject: [PATCH 0909/7155] mlx4/en_netdev: allow offloading VXLAN over VLAN ConnectX-3 Pro can offload transmission of VLAN packets with VXLAN inside: enable tunnel offloads in dev->vlan_features, like it's done with other NIC drivers (e.g. be2net and ixgbe). It's no more necessary to change dev->hw_enc_features when VXLAN are added or removed, since .ndo_features_check() already checks for VXLAN packet where the UDP destination port matches the configured value. Just set dev->hw_enc_features when the NIC is initialized, so that overlying VLAN can correctly inherit the tunnel offload capabilities. Changes since v1: - avoid flipping hw_enc_features, instead of calling netdev notifiers, thanks to Saeed Mahameed - squash two patches into a single one CC: Paolo Abeni CC: Marcelo Ricardo Leitner Signed-off-by: Davide Caratti Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx4/en_netdev.c | 43 ++++++++----------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index c1438ae52a11..40ec5acf79c0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2645,14 +2645,6 @@ static void mlx4_en_add_vxlan_offloads(struct work_struct *work) en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret); return; } - - /* set offloads */ - priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; } static void mlx4_en_del_vxlan_offloads(struct work_struct *work) @@ -2660,14 +2652,6 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work) int ret; struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, vxlan_del_task); - /* unset offloads */ - priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL); - ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC, 0); if (ret) @@ -3415,6 +3399,23 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (mdev->LSO_support) dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; + if (mdev->dev->caps.tunnel_offload_mode == + MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { + dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + dev->features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; + dev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_GSO_PARTIAL; + } + dev->vlan_features = dev->hw_features; dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_RXHASH; @@ -3483,16 +3484,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->rss_hash_fn = ETH_RSS_HASH_TOP; } - if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { - dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; - dev->features |= NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_PARTIAL; - dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; - } - /* MTU range: 68 - hw-specific max */ dev->min_mtu = ETH_MIN_MTU; dev->max_mtu = priv->max_mtu; -- GitLab From edcde3ee579bcac75ceb47758f18d2b1d26a39f8 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 26 Jul 2019 20:56:20 +0200 Subject: [PATCH 0910/7155] r8169: align setting PME with vendor driver Align setting PME with the vendor driver. PMEnable is writable on RTL8169 only, on later chip versions it's read-only. PME_SIGNAL is used on chip versions from RTL8168evl with the exception of the RTL8168f family. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index e1e1c89fbe3d..5c337234b7bc 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1414,18 +1414,22 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) } switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: options = RTL_R8(tp, Config1) & ~PMEnable; if (wolopts) options |= PMEnable; RTL_W8(tp, Config1, options); break; - default: + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_37: + case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_51: options = RTL_R8(tp, Config2) & ~PME_SIGNAL; if (wolopts) options |= PME_SIGNAL; RTL_W8(tp, Config2, options); break; + default: + break; } rtl_lock_config_regs(tp); -- GitLab From 280b0b8e89ade4277147e598d5806de12bff5fbc Mon Sep 17 00:00:00 2001 From: Jonathan Lemon Date: Fri, 26 Jul 2019 12:16:09 -0700 Subject: [PATCH 0911/7155] ipv6: remove printk ipv6_find_hdr() prints a non-rate limited error message when it cannot find an ipv6 header at a specific offset. This could be used as a DoS, so just remove it. Signed-off-by: Jonathan Lemon Signed-off-by: David S. Miller --- net/ipv6/exthdrs_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index b358f1a4dd08..da46c4284676 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -197,10 +197,8 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, struct ipv6hdr _ip6, *ip6; ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6); - if (!ip6 || (ip6->version != 6)) { - printk(KERN_ERR "IPv6 header not found\n"); + if (!ip6 || (ip6->version != 6)) return -EBADMSG; - } start = *offset + sizeof(struct ipv6hdr); nexthdr = ip6->nexthdr; } -- GitLab From 0170d594ded8297760ca9d8eb7eb6a9aff378059 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 26 Jul 2019 21:48:32 +0200 Subject: [PATCH 0912/7155] r8169: set GSO size and segment limits Set GSO max size and max segment number as in the vendor driver. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 5c337234b7bc..52a9e2d2fc73 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -569,6 +569,11 @@ enum rtl_rx_desc_bit { #define RsvdMask 0x3fffc000 +#define RTL_GSO_MAX_SIZE_V1 32000 +#define RTL_GSO_MAX_SEGS_V1 24 +#define RTL_GSO_MAX_SIZE_V2 64000 +#define RTL_GSO_MAX_SEGS_V2 64 + struct TxDesc { __le32 opts1; __le32 opts2; @@ -6919,8 +6924,14 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disallow toggling */ dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; - if (rtl_chip_supports_csum_v2(tp)) + if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->gso_max_size = RTL_GSO_MAX_SIZE_V2; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2; + } else { + dev->gso_max_size = RTL_GSO_MAX_SIZE_V1; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1; + } dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; -- GitLab From e64e0c89749969b22415fd3e766b33b37264c6ea Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 26 Jul 2019 21:49:22 +0200 Subject: [PATCH 0913/7155] r8169: implement callback ndo_features_check Implement callback ndo_features_check and move all feature checks there. This will allow us to get rid of r8169_csum_workaround() completely in a subsequent step. Like in the vendor driver disable HW csum for short packets on RTL8168b. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 60 ++++++++++++++--------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 52a9e2d2fc73..7e1b68b19d60 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -539,11 +539,11 @@ enum rtl_tx_desc_bit_1 { TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */ TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */ #define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU +#define GTTCPHO_MAX 0x7f /* Second doubleword. */ #define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU +#define TCPHO_MAX 0x3ff #define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */ TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */ @@ -5534,11 +5534,6 @@ static void r8169_csum_workaround(struct rtl8169_private *tp, } while (segs); dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8169_start_xmit(skb, tp->dev); } else { drop: tp->dev->stats.tx_dropped++; @@ -5595,13 +5590,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, u32 mss = skb_shinfo(skb)->gso_size; if (mss) { - if (transport_offset > GTTCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x for TSO\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[0] |= TD1_GTSENV4; @@ -5624,16 +5612,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 ip_protocol; - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !(skb_checksum_help(skb) || eth_skb_pad(skb)); - - if (transport_offset > TCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[1] |= TD1_IPv4_CS; @@ -5790,6 +5768,39 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } +static netdev_features_t rtl8169_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + int transport_offset = skb_transport_offset(skb); + struct rtl8169_private *tp = netdev_priv(dev); + + if (skb_is_gso(skb)) { + if (transport_offset > GTTCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_ALL_TSO; + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->len < ETH_ZLEN) { + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_34: + features &= ~NETIF_F_CSUM_MASK; + break; + default: + break; + } + } + + if (transport_offset > TCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_CSUM_MASK; + } + + return vlan_features_check(skb, features); +} + static void rtl8169_pcierr_interrupt(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -6546,6 +6557,7 @@ static const struct net_device_ops rtl_netdev_ops = { .ndo_stop = rtl8169_close, .ndo_get_stats64 = rtl8169_get_stats64, .ndo_start_xmit = rtl8169_start_xmit, + .ndo_features_check = rtl8169_features_check, .ndo_tx_timeout = rtl8169_tx_timeout, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = rtl8169_change_mtu, -- GitLab From 96ea772ef24114e6aa3ce39599474ae794be625f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 26 Jul 2019 21:50:34 +0200 Subject: [PATCH 0914/7155] r8169: remove r8169_csum_workaround The loop in r8169_csum_workaround is called only if in msdn_giant_send_check a copy of the skb header needs to be made and we don't have enough memory. Let's simply drop the packet in that case so that we can remove r8169_csum_workaround. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 39 ++--------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 7e1b68b19d60..f771595403e0 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5508,39 +5508,6 @@ static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb) return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; } -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -/* r8169_csum_workaround() - * The hw limites the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ -static void r8169_csum_workaround(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - if (skb_is_gso(skb)) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8169_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else { -drop: - tp->dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - } -} - /* msdn_giant_send_check() * According to the document of microsoft, the TCP Pseudo Header excludes the * packet length for IPv6 TCP large packets. @@ -5688,10 +5655,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, opts[0] = DescOwn; if (rtl_chip_supports_csum_v2(tp)) { - if (!rtl8169_tso_csum_v2(tp, skb, opts)) { - r8169_csum_workaround(tp, skb); - return NETDEV_TX_OK; - } + if (!rtl8169_tso_csum_v2(tp, skb, opts)) + goto err_dma_0; } else { rtl8169_tso_csum_v1(skb, opts); } -- GitLab From 93681cd7d94f83903cb3f0f95433d10c28a7e9a5 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 26 Jul 2019 21:51:36 +0200 Subject: [PATCH 0915/7155] r8169: enable HW csum and TSO Enable HW csum and TSO per default except on known buggy chip versions. Realtek confirmed that RTL8168evl has a HW issue with TSO. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index f771595403e0..61a23aee0eef 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -6879,11 +6879,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT); - /* don't enable SG, IP_CSUM and TSO by default - it might not work - * properly for all devices */ - dev->features |= NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; @@ -6903,6 +6901,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; dev->gso_max_size = RTL_GSO_MAX_SIZE_V2; dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2; } else { @@ -6910,6 +6909,13 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1; } + /* RTL8168e-vl has a HW issue with TSO */ + if (tp->mac_version == RTL_GIGA_MAC_VER_34) { + dev->vlan_features &= ~NETIF_F_ALL_TSO; + dev->hw_features &= ~NETIF_F_ALL_TSO; + dev->features &= ~NETIF_F_ALL_TSO; + } + dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; -- GitLab From 185556f092491120ea2bd7eab6f9f78ff6c4d6d0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 27 Jul 2019 20:32:55 +0300 Subject: [PATCH 0916/7155] mlxsw: spectrum_flower: Forbid to offload mirred redirect on egress Spectrum ASIC does not support redirection on egress, so refuse to insert such flows: $ tc qdisc add dev ens16np1 clsact $ tc filter add dev ens16np1 egress protocol all pref 1 handle 101 flower skip_sw action mirred egress redirect dev ens16np2 Error: mlxsw_spectrum: Redirect action is not supported on egress. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 202e9a246019..1eeac8a36ead 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -78,6 +78,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid; u16 fid_index; + if (mlxsw_sp_acl_block_is_egress_bound(block)) { + NL_SET_ERR_MSG_MOD(extack, "Redirect action is not supported on egress"); + return -EOPNOTSUPP; + } + fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); fid_index = mlxsw_sp_fid_index(fid); err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, -- GitLab From c9588e28123c563a355964c6ee8ca5dd28aebd6a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 27 Jul 2019 20:32:56 +0300 Subject: [PATCH 0917/7155] mlxsw: spectrum_acl: Track rules that forbid egress block bind Some matches and actions are not supported on egress. Track such rules and forbid a bind of block which contains them to egress. With this patch, the kernel tells the user he cannot do that: $ tc qdisc add dev ens16np1 ingress_block 22 clsact $ tc filter add block 22 protocol 802.1q pref 2 handle 101 flower vlan_id 100 skip_sw action pass $ tc qdisc add dev ens16np2 egress_block 22 clsact Error: mlxsw_spectrum: Block cannot be bound to egress because it contains unsupported rules. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 7 +++++-- .../net/ethernet/mellanox/mlxsw/spectrum_acl.c | 17 +++++++++++++---- .../ethernet/mellanox/mlxsw/spectrum_flower.c | 11 +++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 7e8a54068d92..9277b3f125e8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1625,7 +1625,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, } flow_block_cb_incref(block_cb); err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block, - mlxsw_sp_port, ingress); + mlxsw_sp_port, ingress, f->extack); if (err) goto err_block_bind; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 131f62ce9297..c78d93afbb9d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -623,7 +623,8 @@ struct mlxsw_sp_acl_rule_info { unsigned int priority; struct mlxsw_afk_element_values values; struct mlxsw_afa_block *act_block; - u8 action_created:1; + u8 action_created:1, + egress_bind_blocker:1; unsigned int counter_index; }; @@ -642,6 +643,7 @@ struct mlxsw_sp_acl_block { struct mlxsw_sp *mlxsw_sp; unsigned int rule_count; unsigned int disable_count; + unsigned int egress_blocker_rule_count; struct net *net; }; @@ -657,7 +659,8 @@ void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block); int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress); + bool ingress, + struct netlink_ext_ack *extack); int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index e8ac90564dbe..1aaab8446270 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -239,7 +239,8 @@ mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress) + bool ingress, + struct netlink_ext_ack *extack) { struct mlxsw_sp_acl_block_binding *binding; int err; @@ -247,6 +248,11 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress))) return -EEXIST; + if (!ingress && block->egress_blocker_rule_count) { + NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules"); + return -EOPNOTSUPP; + } + binding = kzalloc(sizeof(*binding), GFP_KERNEL); if (!binding) return -ENOMEM; @@ -672,6 +678,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; + struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; int err; err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei); @@ -689,14 +696,14 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, * one, to be directly bound to device. The rest of the * rulesets are bound by "Goto action set". */ - err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, - ruleset->ht_key.block); + err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block); if (err) goto err_ruleset_block_bind; } list_add_tail(&rule->list, &mlxsw_sp->acl->rules); - ruleset->ht_key.block->rule_count++; + block->rule_count++; + block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker; return 0; err_ruleset_block_bind: @@ -712,7 +719,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; + struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; + block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; ruleset->ht_key.block->rule_count--; list_del(&rule->list); if (!ruleset->ht_key.chain_index && diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 1eeac8a36ead..c86d582dafbe 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -83,6 +83,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return -EOPNOTSUPP; } + /* Forbid block with this rulei to be bound + * to egress in future. + */ + rulei->egress_bind_blocker = 1; + fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); fid_index = mlxsw_sp_fid_index(fid); err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, @@ -395,6 +400,12 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); return -EOPNOTSUPP; } + + /* Forbid block with this rulei to be bound + * to egress in future. + */ + rulei->egress_bind_blocker = 1; + if (match.mask->vlan_id != 0) mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VID, -- GitLab From 7079676d0931e30f4f4949d1580fc87fde4ddc5b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 27 Jul 2019 20:32:57 +0300 Subject: [PATCH 0918/7155] mlxsw: spectrum_flower: Forbid to offload match on reserved TCP flags bits Matching on reserved TCP flags bits is only supported using custom parser. Since the usecase for that is not known now, just forbid to offload rules that match on these bits. Reported-by: Alex Kushnarov Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index c86d582dafbe..0ad1a24abfc6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -267,6 +267,12 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, flow_rule_match_tcp(rule, &match); + if (match.mask->flags & htons(0x0E00)) { + NL_SET_ERR_MSG_MOD(f->common.extack, "TCP flags match not supported on reserved bits"); + dev_err(mlxsw_sp->bus_info->dev, "TCP flags match not supported on reserved bits\n"); + return -EINVAL; + } + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, ntohs(match.key->flags), ntohs(match.mask->flags)); -- GitLab From f53199c0bc62657f7bc253b5dfc9f3d81ed2ca28 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Thu, 18 Jul 2019 15:22:37 -0700 Subject: [PATCH 0919/7155] iio: cros_ec: Remove replacing error code with -EIO Due to an API misread, error code can be different for -EIO when reading a sysfs entry. Return the error reported by the cros_ec stack. Check the proper error message (protocol error, not supported) is reported when there is an error returned by the EC stack. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- .../cros_ec_sensors/cros_ec_sensors_core.c | 44 +++++++++++-------- drivers/iio/light/cros_ec_light_prox.c | 36 +++++++-------- drivers/iio/pressure/cros_ec_baro.c | 17 ++++--- 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 96d5aa1f4bd5..8d43965c3b9a 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -33,6 +33,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); + int ret; platform_set_drvdata(pdev, indio_dev); @@ -60,9 +61,10 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->param.cmd = MOTIONSENSE_CMD_INFO; state->param.info.sensor_num = sensor_platform->sensor_num; - if (cros_ec_motion_send_host_cmd(state, 0)) { + ret = cros_ec_motion_send_host_cmd(state, 0); + if (ret) { dev_warn(dev, "Can not access sensor info\n"); - return -EIO; + return ret; } state->type = state->resp->info.type; state->loc = state->resp->info.location; @@ -86,7 +88,7 @@ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, ret = cros_ec_cmd_xfer_status(state->ec, state->msg); if (ret < 0) - return -EIO; + return ret; if (ret && state->resp != (struct ec_response_motion_sense *)state->msg->data) @@ -396,7 +398,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret = IIO_VAL_INT; + int ret; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: @@ -404,22 +406,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->ec_rate.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->ec_rate.ret; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_FREQUENCY: st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; st->param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->sensor_odr.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->sensor_odr.ret; + ret = IIO_VAL_INT; break; default: + ret = -EINVAL; break; } @@ -431,7 +438,7 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int ret = 0; + int ret; switch (mask) { case IIO_CHAN_INFO_FREQUENCY: @@ -441,17 +448,16 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, /* Always roundup, so caller gets at least what it asks for. */ st->param.sensor_odr.roundup = 1; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(st, 0); break; case IIO_CHAN_INFO_SAMP_FREQ: st->param.cmd = MOTIONSENSE_CMD_EC_RATE; st->param.ec_rate.data = val; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - st->curr_sampl_freq = val; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + st->curr_sampl_freq = val; break; default: ret = -EINVAL; diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index b81746a99f1f..965f346d7d64 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -42,7 +42,7 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, struct cros_ec_light_prox_state *st = iio_priv(indio_dev); u16 data = 0; s64 val64; - int ret = IIO_VAL_INT; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); @@ -50,23 +50,22 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type == IIO_PROXIMITY) { - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) { - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) break; - } *val = data; + ret = IIO_VAL_INT; } else { ret = -EINVAL; } break; case IIO_CHAN_INFO_PROCESSED: if (chan->type == IIO_LIGHT) { - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) { - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) break; - } /* * The data coming from the light sensor is * pre-processed and represents the ambient light @@ -82,16 +81,16 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; st->core.param.sensor_offset.flags = 0; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } /* Save values */ st->core.calib[0].offset = st->core.resp->sensor_offset.offset[0]; *val = st->core.calib[idx].offset; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_CALIBSCALE: /* @@ -102,10 +101,9 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } val64 = st->core.resp->sensor_range.ret; *val = val64 >> 16; @@ -128,7 +126,7 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, int val, int val2, long mask) { struct cros_ec_light_prox_state *st = iio_priv(indio_dev); - int ret = 0; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); @@ -143,14 +141,12 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, st->core.calib[0].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; case IIO_CHAN_INFO_CALIBSCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = (val << 16) | (val2 / 100); - if (cros_ec_motion_send_host_cmd(&st->core, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; default: ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index d3acba7ba582..70148624db64 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -39,26 +39,29 @@ static int cros_ec_baro_read(struct iio_dev *indio_dev, { struct cros_ec_baro_state *st = iio_priv(indio_dev); u16 data = 0; - int ret = IIO_VAL_INT; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); switch (mask) { case IIO_CHAN_INFO_RAW: - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) + break; + *val = data; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } + *val = st->core.resp->sensor_range.ret; /* scale * in_pressure_raw --> kPa */ -- GitLab From a090965b882333500d8780e2c1762e17782f413f Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:43 -0700 Subject: [PATCH 0920/7155] iio:common:st_sensors: add st_sensors_get_settings_index() helper function Extract from st_sensors_check_device_support() function the code that is used to get the specific settings for a device. This will be used as generic extractor by each ST driver. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- .../iio/common/st_sensors/st_sensors_core.c | 49 +++++++++++++------ include/linux/iio/common/st_sensors.h | 4 ++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8b22dc241482..3610ca9eaa87 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -633,28 +633,47 @@ static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, return 0; } +/* + * st_sensors_get_settings_index() - get index of the sensor settings for a + * specific device from list of settings + * @name: device name buffer reference. + * @list: sensor settings list. + * @list_length: length of sensor settings list. + * + * Return: non negative number on success (valid index), + * negative error code otherwise. + */ +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length) +{ + int i, n; + + for (i = 0; i < list_length; i++) { + for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { + if (strcmp(name, list[i].sensors_supported[n]) == 0) + return i; + } + } + + return -ENODEV; +} +EXPORT_SYMBOL(st_sensors_get_settings_index); + int st_sensors_check_device_support(struct iio_dev *indio_dev, int num_sensors_list, const struct st_sensor_settings *sensor_settings) { - int i, n, err = 0; - u8 wai; struct st_sensor_data *sdata = iio_priv(indio_dev); + int i, err; + u8 wai; - for (i = 0; i < num_sensors_list; i++) { - for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { - if (strcmp(indio_dev->name, - sensor_settings[i].sensors_supported[n]) == 0) { - break; - } - } - if (n < ST_SENSORS_MAX_4WAI) - break; - } - if (i == num_sensors_list) { + i = st_sensors_get_settings_index(indio_dev->name, + sensor_settings, num_sensors_list); + if (i < 0) { dev_err(&indio_dev->dev, "device name %s not recognized.\n", - indio_dev->name); - return -ENODEV; + indio_dev->name); + return i; } err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 2948ac99e2da..17fbf3e9b013 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -334,6 +334,10 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale); int st_sensors_read_info_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val); +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length); + int st_sensors_check_device_support(struct iio_dev *indio_dev, int num_sensors_list, const struct st_sensor_settings *sensor_settings); -- GitLab From 823a7adac4f1bde2828d18f3bd8fa75285d00f4d Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:44 -0700 Subject: [PATCH 0921/7155] iio:accel: introduce st_accel_get_settings() function The function is introduced to retrieve accel device settings. It will be used by probe in order to configure regmap. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel.h | 1 + drivers/iio/accel/st_accel_core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 979ab9679b99..af09943f38c9 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -68,6 +68,7 @@ static const struct st_sensors_platform_data default_accel_pdata = { .drdy_int_pin = 1, }; +const struct st_sensor_settings *st_accel_get_settings(const char *name); int st_accel_common_probe(struct iio_dev *indio_dev); void st_accel_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index e02b79931979..6fc490ffef7e 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1147,6 +1147,24 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev, #endif } +/* + * st_accel_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_accel_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_accel_sensors_settings, + ARRAY_SIZE(st_accel_sensors_settings)); + if (index < 0) + return NULL; + + return &st_accel_sensors_settings[index]; +} +EXPORT_SYMBOL(st_accel_get_settings); + int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); -- GitLab From 2acca26bba3a7487e941e234e8ee33a998eecf53 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:45 -0700 Subject: [PATCH 0922/7155] iio:gyro: introduce st_gyro_get_settings() function The function is introduced to retrieve gyro device settings. It will be used by probe in order to configure regmap. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro.h | 1 + drivers/iio/gyro/st_gyro_core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index 460d190be4a4..592f6b34e987 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -32,6 +32,7 @@ static const struct st_sensors_platform_data gyro_pdata = { .drdy_int_pin = 2, }; +const struct st_sensor_settings *st_gyro_get_settings(const char *name); int st_gyro_common_probe(struct iio_dev *indio_dev); void st_gyro_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index e995dc77e30e..5cc63d41d855 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -368,6 +368,24 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = { #define ST_GYRO_TRIGGER_OPS NULL #endif +/* + * st_gyro_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_gyro_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_gyro_sensors_settings, + ARRAY_SIZE(st_gyro_sensors_settings)); + if (index < 0) + return NULL; + + return &st_gyro_sensors_settings[index]; +} +EXPORT_SYMBOL(st_gyro_get_settings); + int st_gyro_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *gdata = iio_priv(indio_dev); -- GitLab From aa4e75c85076c056d944b92ed94b76277430d263 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:46 -0700 Subject: [PATCH 0923/7155] iio:magn: introduce st_magn_get_settings() function The function is introduced to retrieve magn device settings. It will be used by probe in order to configure regmap. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/st_magn.h | 1 + drivers/iio/magnetometer/st_magn_core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h index d69ef9b2a731..204b285725c8 100644 --- a/drivers/iio/magnetometer/st_magn.h +++ b/drivers/iio/magnetometer/st_magn.h @@ -22,6 +22,7 @@ #define LIS2MDL_MAGN_DEV_NAME "lis2mdl" #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" +const struct st_sensor_settings *st_magn_get_settings(const char *name); int st_magn_common_probe(struct iio_dev *indio_dev); void st_magn_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 2f7a1dbcdeb3..43a49a52c81a 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -470,6 +470,24 @@ static const struct iio_trigger_ops st_magn_trigger_ops = { #define ST_MAGN_TRIGGER_OPS NULL #endif +/* + * st_magn_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_magn_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_magn_sensors_settings, + ARRAY_SIZE(st_magn_sensors_settings)); + if (index < 0) + return NULL; + + return &st_magn_sensors_settings[index]; +} +EXPORT_SYMBOL(st_magn_get_settings); + int st_magn_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *mdata = iio_priv(indio_dev); -- GitLab From 539b25fa700acf8985ea1a273fcccef5e52d52e4 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:47 -0700 Subject: [PATCH 0924/7155] iio:pressure: introduce st_press_get_settings() function The function is introduced to retrieve press device settings. It will be used by probe in order to configure regmap. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure.h | 1 + drivers/iio/pressure/st_pressure_core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index 6a720cfb5686..c2e47a6c3118 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -41,6 +41,7 @@ static const struct st_sensors_platform_data default_press_pdata = { .drdy_int_pin = 1, }; +const struct st_sensor_settings *st_press_get_settings(const char *name); int st_press_common_probe(struct iio_dev *indio_dev); void st_press_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index b960e76f7dfd..35d80ff27464 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -664,6 +664,24 @@ static const struct iio_trigger_ops st_press_trigger_ops = { #define ST_PRESS_TRIGGER_OPS NULL #endif +/* + * st_press_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_press_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_press_sensors_settings, + ARRAY_SIZE(st_press_sensors_settings)); + if (index < 0) + return NULL; + + return &st_press_sensors_settings[index]; +} +EXPORT_SYMBOL(st_press_get_settings); + int st_press_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *press_data = iio_priv(indio_dev); -- GitLab From feba6b18c926ad59cb7ea97e6023a38c6bf74310 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:48 -0700 Subject: [PATCH 0925/7155] iio:accel: device settings are set immediately during probe This patch set accel settings right after probe start. This is done in preparation of regmap that needs different configuration based on multiread bit value. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 19 ++++++++++++++----- drivers/iio/accel/st_accel_spi.c | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index c3c8f2e73c2a..a92cf776031e 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -150,20 +150,29 @@ MODULE_DEVICE_TABLE(i2c, st_accel_id_table); static int st_accel_i2c_probe(struct i2c_client *client) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *adata; + struct iio_dev *indio_dev; const char *match; int ret; + match = device_get_match_data(&client->dev); + if (match) + strlcpy(client->name, match, sizeof(client->name)); + + settings = st_accel_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); if (!indio_dev) return -ENOMEM; adata = iio_priv(indio_dev); - - match = device_get_match_data(&client->dev); - if (match) - strlcpy(client->name, match, sizeof(client->name)); + adata->sensor_settings = (struct st_sensor_settings *)settings; st_sensors_i2c_configure(indio_dev, client, adata); diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 474742e35d92..c0556db9d60a 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -102,18 +102,28 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match); static int st_accel_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *adata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_accel_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_accel_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); if (!indio_dev) return -ENOMEM; adata = iio_priv(indio_dev); + adata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_accel_of_match, - spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, adata); err = st_accel_common_probe(indio_dev); -- GitLab From 3c05484c79071f3a20acb7242630590ba596b99e Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:49 -0700 Subject: [PATCH 0926/7155] iio:gyro: device settings are set immediately during probe This patch set gyro settings right after probe start. This is done in preparation of regmap that needs different configuration based on multiread bit value. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro_i2c.c | 18 ++++++++++++++---- drivers/iio/gyro/st_gyro_spi.c | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index f2a8683db7d9..fa71e94b76f4 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -63,19 +63,29 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); #endif static int st_gyro_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *gdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&client->dev, st_gyro_of_match, + client->name, sizeof(client->name)); + + settings = st_gyro_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata)); if (!indio_dev) return -ENOMEM; gdata = iio_priv(indio_dev); - st_sensors_of_name_probe(&client->dev, st_gyro_of_match, - client->name, sizeof(client->name)); + gdata->sensor_settings = (struct st_sensor_settings *)settings; st_sensors_i2c_configure(indio_dev, client, gdata); diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 93c48248bea6..bb7082055f85 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -69,18 +69,28 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); static int st_gyro_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *gdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_gyro_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata)); if (!indio_dev) return -ENOMEM; gdata = iio_priv(indio_dev); + gdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, - spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, gdata); err = st_gyro_common_probe(indio_dev); -- GitLab From 291d83f2f4ef40e1d2d9504d29ecdf7000a655fb Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:50 -0700 Subject: [PATCH 0927/7155] iio:magn: device settings are set immediately during probe This patch set magn settings right after probe start. This is done in preparation of regmap that needs different configuration based on multiread bit value. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/st_magn_i2c.c | 18 ++++++++++++++---- drivers/iio/magnetometer/st_magn_spi.c | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 4d014fd1aeb0..d5d565639bed 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -55,19 +55,29 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); #endif static int st_magn_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *mdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&client->dev, st_magn_of_match, + client->name, sizeof(client->name)); + + settings = st_magn_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata)); if (!indio_dev) return -ENOMEM; mdata = iio_priv(indio_dev); - st_sensors_of_name_probe(&client->dev, st_magn_of_match, - client->name, sizeof(client->name)); + mdata->sensor_settings = (struct st_sensor_settings *)settings; st_sensors_i2c_configure(indio_dev, client, mdata); diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 0d47070611b1..a3045afc6b53 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -51,18 +51,28 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); static int st_magn_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *mdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_magn_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_magn_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata)); if (!indio_dev) return -ENOMEM; mdata = iio_priv(indio_dev); + mdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_magn_of_match, - spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, mdata); err = st_magn_common_probe(indio_dev); -- GitLab From 570c2c55ef364ef6aed531e554be4c989fb1a49c Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:51 -0700 Subject: [PATCH 0928/7155] iio:pressure: device settings are set immediately during probe This patch set pressure settings right after probe start. This is done in preparation of regmap that needs different configuration based on multiread bit value. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_i2c.c | 27 +++++++++++++++++--------- drivers/iio/pressure/st_pressure_spi.c | 18 +++++++++++++---- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index b7d9ba706abc..466e7dde5eae 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -78,18 +78,13 @@ static const struct i2c_device_id st_press_id_table[] = { MODULE_DEVICE_TABLE(i2c, st_press_id_table); static int st_press_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *press_data; + struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); - if (!indio_dev) - return -ENOMEM; - - press_data = iio_priv(indio_dev); - if (client->dev.of_node) { st_sensors_of_name_probe(&client->dev, st_press_of_match, client->name, sizeof(client->name)); @@ -99,10 +94,24 @@ static int st_press_i2c_probe(struct i2c_client *client, return -ENODEV; strlcpy(client->name, st_press_id_table[ret].name, - sizeof(client->name)); + sizeof(client->name)); } else if (!id) return -ENODEV; + settings = st_press_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); + if (!indio_dev) + return -ENOMEM; + + press_data = iio_priv(indio_dev); + press_data->sensor_settings = (struct st_sensor_settings *)settings; + st_sensors_i2c_configure(indio_dev, client, press_data); ret = st_press_common_probe(indio_dev); diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index ef61401c41d3..3e8c1ffe001e 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -61,18 +61,28 @@ MODULE_DEVICE_TABLE(of, st_press_of_match); static int st_press_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *press_data; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_press_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_press_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*press_data)); - if (indio_dev == NULL) + if (!indio_dev) return -ENOMEM; press_data = iio_priv(indio_dev); + press_data->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_press_of_match, - spi->modalias, sizeof(spi->modalias)); st_sensors_spi_configure(indio_dev, spi, press_data); err = st_press_common_probe(indio_dev); -- GitLab From 1ecd245e0eb23d1c3803474eba75589743d0d1fe Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:52 -0700 Subject: [PATCH 0929/7155] iio: move 3-wire spi initialization to st_sensors_spi Some devices need to be configured with special bit in order to use spi 3-wire. This was done during device identification phase. Instead, let's move this part as spi specific. Doing this the check_device_support function becomes a simple device id check, so let's rename it. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 4 +- drivers/iio/accel/st_accel_spi.c | 4 +- .../iio/common/st_sensors/st_sensors_core.c | 64 +++++------------- .../iio/common/st_sensors/st_sensors_spi.c | 65 ++++++++++++++++++- drivers/iio/gyro/st_gyro_core.c | 4 +- drivers/iio/gyro/st_gyro_spi.c | 4 +- drivers/iio/magnetometer/st_magn_core.c | 4 +- drivers/iio/magnetometer/st_magn_spi.c | 4 +- drivers/iio/pressure/st_pressure_core.c | 4 +- drivers/iio/pressure/st_pressure_spi.c | 4 +- include/linux/iio/common/st_sensors.h | 3 +- include/linux/iio/common/st_sensors_spi.h | 4 +- 12 files changed, 97 insertions(+), 71 deletions(-) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 6fc490ffef7e..630909702a19 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1183,9 +1183,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_accel_sensors_settings), - st_accel_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_accel_power_off; diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index c0556db9d60a..8af7027d5598 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -124,7 +124,9 @@ static int st_accel_spi_probe(struct spi_device *spi) adata = iio_priv(indio_dev); adata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_spi_configure(indio_dev, spi, adata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_accel_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 3610ca9eaa87..f05bf7cf0594 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -608,31 +608,6 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_read_info_raw); -static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, - const struct st_sensor_settings *sensor_settings) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); - struct device_node *np = sdata->dev->of_node; - struct st_sensors_platform_data *pdata; - - pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; - if (((np && of_property_read_bool(np, "spi-3wire")) || - (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { - int err; - - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, - sensor_settings->sim.addr, - sensor_settings->sim.value); - if (err < 0) { - dev_err(&indio_dev->dev, - "failed to init interface mode\n"); - return err; - } - } - - return 0; -} - /* * st_sensors_get_settings_index() - get index of the sensor settings for a * specific device from list of settings @@ -660,36 +635,30 @@ int st_sensors_get_settings_index(const char *name, } EXPORT_SYMBOL(st_sensors_get_settings_index); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, - const struct st_sensor_settings *sensor_settings) +/* + * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the + * expected value + * @indio_dev: IIO device reference. + * + * Return: 0 on success (valid sensor ID), else a negative error code. + */ +int st_sensors_verify_id(struct iio_dev *indio_dev) { struct st_sensor_data *sdata = iio_priv(indio_dev); - int i, err; + int err; u8 wai; - i = st_sensors_get_settings_index(indio_dev->name, - sensor_settings, num_sensors_list); - if (i < 0) { - dev_err(&indio_dev->dev, "device name %s not recognized.\n", - indio_dev->name); - return i; - } - - err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); - if (err < 0) - return err; - - if (sensor_settings[i].wai_addr) { + if (sdata->sensor_settings->wai_addr) { err = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sensor_settings[i].wai_addr, &wai); + sdata->sensor_settings->wai_addr, + &wai); if (err < 0) { dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); return err; } - if (sensor_settings[i].wai != wai) { + if (sdata->sensor_settings->wai != wai) { dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n", indio_dev->name, wai); @@ -697,12 +666,9 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, } } - sdata->sensor_settings = - (struct st_sensor_settings *)&sensor_settings[i]; - - return i; + return 0; } -EXPORT_SYMBOL(st_sensors_check_device_support); +EXPORT_SYMBOL(st_sensors_verify_id); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 2213843f02cb..a57cd648975c 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -102,9 +102,68 @@ static const struct st_sensor_transfer_function st_sensors_tf_spi = { .read_multiple_byte = st_sensors_spi_read_multiple_byte, }; -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata) +/* + * st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected + * @spi: spi device reference. + * + * Return: true if SPI 3-wire mode is selected, false otherwise. + */ +static bool st_sensors_is_spi_3_wire(struct spi_device *spi) +{ + struct device_node *np = spi->dev.of_node; + struct st_sensors_platform_data *pdata; + + pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; + if ((np && of_property_read_bool(np, "spi-3wire")) || + (pdata && pdata->spi_3wire)) { + return true; + } + + return false; +} + +/* + * st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed + * @spi: spi device reference. + * @settings: sensor specific settings reference. + * + * Return: 0 on success, else a negative error code. + */ +static int st_sensors_configure_spi_3_wire(struct spi_device *spi, + struct st_sensor_settings *settings) +{ + if (settings->sim.addr) { + u8 buffer[] = { + settings->sim.addr, + settings->sim.value + }; + + return spi_write(spi, buffer, 2); + } + + return 0; +} + +/* + * st_sensors_spi_configure() - configure SPI interface + * @indio_dev: IIO device reference. + * @spi: spi device reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + int err; + + if (st_sensors_is_spi_3_wire(spi)) { + err = st_sensors_configure_spi_3_wire(spi, + sdata->sensor_settings); + if (err < 0) + return err; + } + spi_set_drvdata(spi, indio_dev); indio_dev->dev.parent = &spi->dev; @@ -113,6 +172,8 @@ void st_sensors_spi_configure(struct iio_dev *indio_dev, sdata->dev = &spi->dev; sdata->tf = &st_sensors_tf_spi; sdata->get_irq_data_ready = st_sensors_spi_get_irq; + + return 0; } EXPORT_SYMBOL(st_sensors_spi_configure); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 5cc63d41d855..4b87e79aa744 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -400,9 +400,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_gyro_sensors_settings), - st_gyro_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_gyro_power_off; diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index bb7082055f85..b5c624251231 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -91,7 +91,9 @@ static int st_gyro_spi_probe(struct spi_device *spi) gdata = iio_priv(indio_dev); gdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_spi_configure(indio_dev, spi, gdata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_gyro_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 43a49a52c81a..3f313aefece6 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -502,9 +502,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_magn_sensors_settings), - st_magn_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_magn_power_off; diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index a3045afc6b53..fbf909bde841 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -73,7 +73,9 @@ static int st_magn_spi_probe(struct spi_device *spi) mdata = iio_priv(indio_dev); mdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_spi_configure(indio_dev, spi, mdata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_magn_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 35d80ff27464..a783fc075c26 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -698,9 +698,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_press_sensors_settings), - st_press_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_press_power_off; diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 3e8c1ffe001e..7c8b70221e70 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -83,7 +83,9 @@ static int st_press_spi_probe(struct spi_device *spi) press_data = iio_priv(indio_dev); press_data->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_spi_configure(indio_dev, spi, press_data); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_press_common_probe(indio_dev); if (err < 0) diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 17fbf3e9b013..566b955e2980 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -338,8 +338,7 @@ int st_sensors_get_settings_index(const char *name, const struct st_sensor_settings *list, const int list_length); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, const struct st_sensor_settings *sensor_settings); +int st_sensors_verify_id(struct iio_dev *indio_dev); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf); diff --git a/include/linux/iio/common/st_sensors_spi.h b/include/linux/iio/common/st_sensors_spi.h index 6020f7167859..90b25f087f06 100644 --- a/include/linux/iio/common/st_sensors_spi.h +++ b/include/linux/iio/common/st_sensors_spi.h @@ -13,7 +13,7 @@ #include #include -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata); +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi); #endif /* ST_SENSORS_SPI_H */ -- GitLab From 062809ef7733209312562e87cefc84a470430929 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Thu, 18 Jul 2019 15:53:53 -0700 Subject: [PATCH 0930/7155] iio: make st_sensors drivers use regmap This patch is meant to replace the i2c/spi transfer functions with regmap. SPI framework requires DMA safe buffers so let's add GFP_DMA flag for memory allocation used by bulk_read functions. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_buffer.c | 3 +- drivers/iio/accel/st_accel_core.c | 3 - drivers/iio/accel/st_accel_i2c.c | 4 +- .../iio/common/st_sensors/st_sensors_buffer.c | 10 +- .../iio/common/st_sensors/st_sensors_core.c | 39 +++---- .../iio/common/st_sensors/st_sensors_i2c.c | 73 ++++++------- .../iio/common/st_sensors/st_sensors_spi.c | 100 ++++-------------- .../common/st_sensors/st_sensors_trigger.c | 10 +- drivers/iio/gyro/st_gyro_buffer.c | 3 +- drivers/iio/gyro/st_gyro_core.c | 3 - drivers/iio/gyro/st_gyro_i2c.c | 4 +- drivers/iio/magnetometer/st_magn_buffer.c | 3 +- drivers/iio/magnetometer/st_magn_core.c | 3 - drivers/iio/magnetometer/st_magn_i2c.c | 4 +- drivers/iio/pressure/st_pressure_buffer.c | 3 +- drivers/iio/pressure/st_pressure_core.c | 3 - drivers/iio/pressure/st_pressure_i2c.c | 4 +- include/linux/iio/common/st_sensors.h | 40 +------ include/linux/iio/common/st_sensors_i2c.h | 4 +- 19 files changed, 104 insertions(+), 212 deletions(-) diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c index 0205c0167cdd..05f9aea431e2 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -39,7 +39,8 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) int err; struct st_sensor_data *adata = iio_priv(indio_dev); - adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + adata->buffer_data = kmalloc(indio_dev->scan_bytes, + GFP_DMA | GFP_KERNEL); if (adata->buffer_data == NULL) { err = -ENOMEM; goto allocate_memory_error; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 630909702a19..0b17004cb12e 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -1177,7 +1176,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &accel_info; - mutex_init(&adata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) @@ -1188,7 +1186,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev) goto st_accel_power_off; adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; - adata->multiread_bit = adata->sensor_settings->multi_read_bit; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index a92cf776031e..50fa0fc32baa 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -174,7 +174,9 @@ static int st_accel_i2c_probe(struct i2c_client *client) adata = iio_priv(indio_dev); adata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, adata); + ret = st_sensors_i2c_configure(indio_dev, client); + if (ret < 0) + return ret; ret = st_accel_common_probe(indio_dev); if (ret < 0) diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index 4a68669dc555..eee30130ae23 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -17,15 +17,16 @@ #include #include #include +#include #include static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - int i; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; + int i; for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { const struct iio_chan_spec *channel = &indio_dev->channels[i]; @@ -36,11 +37,8 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) channel->scan_type.storagebits >> 3; buf = PTR_ALIGN(buf, storage_bytes); - if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - channel->address, - bytes_to_read, buf, - sdata->multiread_bit) < - bytes_to_read) + if (regmap_bulk_read(sdata->regmap, channel->address, + buf, bytes_to_read) < 0) return -EIO; /* Advance the buffer pointer */ diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index f05bf7cf0594..4a3064fb6cd9 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p) int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, u8 reg_addr, u8 mask, u8 data) { - int err; - u8 new_data; struct st_sensor_data *sdata = iio_priv(indio_dev); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data); - if (err < 0) - goto st_sensors_write_data_with_mask_error; - - new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask)); - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data); - -st_sensors_write_data_with_mask_error: - return err; + return regmap_update_bits(sdata->regmap, + reg_addr, mask, data << __ffs(mask)); } int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, @@ -48,19 +40,15 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, unsigned *readval) { struct st_sensor_data *sdata = iio_priv(indio_dev); - u8 readdata; int err; if (!readval) - return sdata->tf->write_byte(&sdata->tb, sdata->dev, - (u8)reg, (u8)writeval); + return regmap_write(sdata->regmap, reg, writeval); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); + err = regmap_read(sdata->regmap, reg, readval); if (err < 0) return err; - *readval = (unsigned)readdata; - return 0; } EXPORT_SYMBOL(st_sensors_debugfs_reg_access); @@ -545,7 +533,7 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale) EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); static int st_sensors_read_axis_data(struct iio_dev *indio_dev, - struct iio_chan_spec const *ch, int *data) + struct iio_chan_spec const *ch, int *data) { int err; u8 *outdata; @@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + ch->scan_type.shift, 8); - outdata = kmalloc(byte_for_channel, GFP_KERNEL); + outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); if (!outdata) return -ENOMEM; - err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - ch->address, byte_for_channel, - outdata, sdata->multiread_bit); + err = regmap_bulk_read(sdata->regmap, ch->address, + outdata, byte_for_channel); if (err < 0) goto st_sensors_free_memory; @@ -645,13 +632,11 @@ EXPORT_SYMBOL(st_sensors_get_settings_index); int st_sensors_verify_id(struct iio_dev *indio_dev) { struct st_sensor_data *sdata = iio_priv(indio_dev); - int err; - u8 wai; + int wai, err; if (sdata->sensor_settings->wai_addr) { - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sdata->sensor_settings->wai_addr, - &wai); + err = regmap_read(sdata->regmap, + sdata->sensor_settings->wai_addr, &wai); if (err < 0) { dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index b1c9812407e7..9240625534df 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -26,55 +27,51 @@ static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) return to_i2c_client(sdata->dev)->irq; } -static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) -{ - int err; - - err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr); - if (err < 0) - goto st_accel_i2c_read_byte_error; - - *res_byte = err & 0xff; - -st_accel_i2c_read_byte_error: - return err < 0 ? err : 0; -} - -static int st_sensors_i2c_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - if (multiread_bit) - reg_addr |= ST_SENSORS_I2C_MULTIREAD; - - return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev), - reg_addr, len, data); -} - -static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) -{ - return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data); -} +static const struct regmap_config st_sensors_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; -static const struct st_sensor_transfer_function st_sensors_tf_i2c = { - .read_byte = st_sensors_i2c_read_byte, - .write_byte = st_sensors_i2c_write_byte, - .read_multiple_byte = st_sensors_i2c_read_multiple_byte, +static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_I2C_MULTIREAD, }; -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata) +/* + * st_sensors_i2c_configure() - configure I2C interface + * @indio_dev: IIO device reference. + * @client: i2c client reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; + + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_i2c_regmap_multiread_bit_config; + else + config = &st_sensors_i2c_regmap_config; + + sdata->regmap = devm_regmap_init_i2c(client, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } + i2c_set_clientdata(client, indio_dev); indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; sdata->dev = &client->dev; - sdata->tf = &st_sensors_tf_i2c; sdata->get_irq_data_ready = st_sensors_i2c_get_irq; + + return 0; } EXPORT_SYMBOL(st_sensors_i2c_configure); diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index a57cd648975c..9c0661a283d0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -11,12 +11,12 @@ #include #include #include +#include #include - +#include "st_sensors_core.h" #define ST_SENSORS_SPI_MULTIREAD 0xc0 -#define ST_SENSORS_SPI_READ 0x80 static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) { @@ -25,81 +25,15 @@ static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) return to_spi_device(sdata->dev)->irq; } -static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - int err; - - struct spi_transfer xfers[] = { - { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 1, - }, - { - .rx_buf = tb->rx_buf, - .bits_per_word = 8, - .len = len, - } - }; - - mutex_lock(&tb->buf_lock); - if ((multiread_bit) && (len > 1)) - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD; - else - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ; - - err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); - if (err) - goto acc_spi_read_error; - - memcpy(data, tb->rx_buf, len); - mutex_unlock(&tb->buf_lock); - return len; - -acc_spi_read_error: - mutex_unlock(&tb->buf_lock); - return err; -} - -static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) -{ - return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false); -} - -static int st_sensors_spi_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); -} - -static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) -{ - int err; - - struct spi_transfer xfers = { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 2, - }; - - mutex_lock(&tb->buf_lock); - tb->tx_buf[0] = reg_addr; - tb->tx_buf[1] = data; - - err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); - mutex_unlock(&tb->buf_lock); - - return err; -} +static const struct regmap_config st_sensors_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; -static const struct st_sensor_transfer_function st_sensors_tf_spi = { - .read_byte = st_sensors_spi_read_byte, - .write_byte = st_sensors_spi_write_byte, - .read_multiple_byte = st_sensors_spi_read_multiple_byte, +static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_SPI_MULTIREAD, }; /* @@ -155,6 +89,7 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev, struct spi_device *spi) { struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; int err; if (st_sensors_is_spi_3_wire(spi)) { @@ -164,13 +99,24 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev, return err; } + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_spi_regmap_multiread_bit_config; + else + config = &st_sensors_spi_regmap_config; + + sdata->regmap = devm_regmap_init_spi(spi, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } + spi_set_drvdata(spi, indio_dev); indio_dev->dev.parent = &spi->dev; indio_dev->name = spi->modalias; sdata->dev = &spi->dev; - sdata->tf = &st_sensors_tf_spi; sdata->get_irq_data_ready = st_sensors_spi_get_irq; return 0; diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 630c8cb35e8b..bed7b8682b17 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "st_sensors_core.h" @@ -26,8 +27,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, struct st_sensor_data *sdata) { - u8 status; - int ret; + int ret, status; /* How would I know if I can't check it? */ if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) @@ -37,9 +37,9 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, if (!indio_dev->active_scan_mask) return 0; - ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sdata->sensor_settings->drdy_irq.stat_drdy.addr, - &status); + ret = regmap_read(sdata->regmap, + sdata->sensor_settings->drdy_irq.stat_drdy.addr, + &status); if (ret < 0) { dev_err(sdata->dev, "error checking samples available\n"); diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c index 6e362f735e92..21360681d4dd 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -39,7 +39,8 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) int err; struct st_sensor_data *gdata = iio_priv(indio_dev); - gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + gdata->buffer_data = kmalloc(indio_dev->scan_bytes, + GFP_DMA | GFP_KERNEL); if (gdata->buffer_data == NULL) { err = -ENOMEM; goto allocate_memory_error; diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 4b87e79aa744..02e42c945181 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -394,7 +393,6 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &gyro_info; - mutex_init(&gdata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) @@ -405,7 +403,6 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) goto st_gyro_power_off; gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; - gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; indio_dev->channels = gdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index fa71e94b76f4..05a1a0874bd5 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -87,7 +87,9 @@ static int st_gyro_i2c_probe(struct i2c_client *client, gdata = iio_priv(indio_dev); gdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, gdata); + err = st_sensors_i2c_configure(indio_dev, client); + if (err < 0) + return err; err = st_gyro_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index 11d7806655bc..9dba93539a99 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -34,7 +34,8 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev) int err; struct st_sensor_data *mdata = iio_priv(indio_dev); - mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + mdata->buffer_data = kmalloc(indio_dev->scan_bytes, + GFP_DMA | GFP_KERNEL); if (mdata->buffer_data == NULL) { err = -ENOMEM; goto allocate_memory_error; diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 3f313aefece6..804353a483c7 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -496,7 +495,6 @@ int st_magn_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &magn_info; - mutex_init(&mdata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) @@ -507,7 +505,6 @@ int st_magn_common_probe(struct iio_dev *indio_dev) goto st_magn_power_off; mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; - mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; indio_dev->channels = mdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index d5d565639bed..fdba480a12be 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -79,7 +79,9 @@ static int st_magn_i2c_probe(struct i2c_client *client, mdata = iio_priv(indio_dev); mdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, mdata); + err = st_sensors_i2c_configure(indio_dev, client); + if (err < 0) + return err; err = st_magn_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c index 4566e08a64a1..f21b630abaa0 100644 --- a/drivers/iio/pressure/st_pressure_buffer.c +++ b/drivers/iio/pressure/st_pressure_buffer.c @@ -39,7 +39,8 @@ static int st_press_buffer_postenable(struct iio_dev *indio_dev) int err; struct st_sensor_data *press_data = iio_priv(indio_dev); - press_data->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + press_data->buffer_data = kmalloc(indio_dev->scan_bytes, + GFP_DMA | GFP_KERNEL); if (press_data->buffer_data == NULL) { err = -ENOMEM; goto allocate_memory_error; diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index a783fc075c26..9ef92a501286 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -692,7 +691,6 @@ int st_press_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &press_info; - mutex_init(&press_data->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) @@ -709,7 +707,6 @@ int st_press_common_probe(struct iio_dev *indio_dev) * element. */ press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; - press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; indio_dev->channels = press_data->sensor_settings->ch; indio_dev->num_channels = press_data->sensor_settings->num_ch; diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 466e7dde5eae..71d2ed6b4948 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -112,7 +112,9 @@ static int st_press_i2c_probe(struct i2c_client *client, press_data = iio_priv(indio_dev); press_data->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, press_data); + ret = st_sensors_i2c_configure(indio_dev, client); + if (ret < 0) + return ret; ret = st_press_common_probe(indio_dev); if (ret < 0) diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 566b955e2980..28fc1f9fa7d5 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -169,36 +170,6 @@ struct st_sensor_data_ready_irq { } ig1; }; -/** - * struct st_sensor_transfer_buffer - ST sensor device I/O buffer - * @buf_lock: Mutex to protect rx and tx buffers. - * @tx_buf: Buffer used by SPI transfer function to send data to the sensors. - * This buffer is used to avoid DMA not-aligned issue. - * @rx_buf: Buffer used by SPI transfer to receive data from sensors. - * This buffer is used to avoid DMA not-aligned issue. - */ -struct st_sensor_transfer_buffer { - struct mutex buf_lock; - u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH]; - u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned; -}; - -/** - * struct st_sensor_transfer_function - ST sensor device I/O function - * @read_byte: Function used to read one byte. - * @write_byte: Function used to write one byte. - * @read_multiple_byte: Function used to read multiple byte. - */ -struct st_sensor_transfer_function { - int (*read_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte); - int (*write_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data); - int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, - bool multiread_bit); -}; - /** * struct st_sensor_settings - ST specific sensor settings * @wai: Contents of WhoAmI register. @@ -242,16 +213,14 @@ struct st_sensor_settings { * @current_fullscale: Maximum range of measure by the sensor. * @vdd: Pointer to sensor's Vdd power supply * @vdd_io: Pointer to sensor's Vdd-IO power supply + * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). - * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. * @buffer_data: Data used by buffer part. * @odr: Output data rate of the sensor [Hz]. * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * @int_pin_open_drain: Set the interrupt/DRDY to open drain. * @get_irq_data_ready: Function to get the IRQ used for data ready signal. - * @tf: Transfer function structure used by I/O operations. - * @tb: Transfer buffers and mutex used by I/O operations. * @edge_irq: the IRQ triggers on edges and need special handling. * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. @@ -264,9 +233,9 @@ struct st_sensor_data { struct st_sensor_fullscale_avl *current_fullscale; struct regulator *vdd; struct regulator *vdd_io; + struct regmap *regmap; bool enabled; - bool multiread_bit; char *buffer_data; @@ -278,9 +247,6 @@ struct st_sensor_data { unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); - const struct st_sensor_transfer_function *tf; - struct st_sensor_transfer_buffer tb; - bool edge_irq; bool hw_irq_trigger; s64 hw_timestamp; diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 5ada89944698..01e424e2af4f 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -14,8 +14,8 @@ #include #include -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata); +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client); #ifdef CONFIG_ACPI int st_sensors_match_acpi_device(struct device *dev); -- GitLab From 8ecc8b2b78e6af55aa366db4da79be1c772d5e55 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 18:49:50 +0800 Subject: [PATCH 0931/7155] iio: maxim_thermocouple: Use device-managed APIs Use device-managed APIs to simplify the code. The remove functions are redundant now and can be deleted. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/maxim_thermocouple.c | 25 +++----------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index c613a64c017f..2ab68282d0b6 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -230,31 +230,13 @@ static int maxim_thermocouple_probe(struct spi_device *spi) data->spi = spi; data->chip = chip; - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&spi->dev, + indio_dev, NULL, maxim_thermocouple_trigger_handler, NULL); if (ret) return ret; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_buffer; - - return 0; - -error_unreg_buffer: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int maxim_thermocouple_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id maxim_thermocouple_id[] = { @@ -277,7 +259,6 @@ static struct spi_driver maxim_thermocouple_driver = { .of_match_table = maxim_thermocouple_of_match, }, .probe = maxim_thermocouple_probe, - .remove = maxim_thermocouple_remove, .id_table = maxim_thermocouple_id, }; module_spi_driver(maxim_thermocouple_driver); -- GitLab From 857ba268f918dec28470c2074e7c69ccad52547e Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 19:07:42 +0800 Subject: [PATCH 0932/7155] staging: iio: ad2s1210: Use device-managed API Use device-managed API to simplify the code. The remove function is redundant now and can be deleted. Signed-off-by: Chuhong Yuan Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/staging/iio/resolver/ad2s1210.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 0c1bd108c386..4b25a3a314ed 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -671,7 +671,7 @@ static int ad2s1210_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; @@ -683,15 +683,6 @@ static int ad2s1210_probe(struct spi_device *spi) return 0; } -static int ad2s1210_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct of_device_id ad2s1210_of_match[] = { { .compatible = "adi,ad2s1210", }, { } @@ -710,7 +701,6 @@ static struct spi_driver ad2s1210_driver = { .of_match_table = of_match_ptr(ad2s1210_of_match), }, .probe = ad2s1210_probe, - .remove = ad2s1210_remove, .id_table = ad2s1210_id, }; module_spi_driver(ad2s1210_driver); -- GitLab From 23f1ce3c08aad743cd828ca5a36946f043ecf0f1 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 16:02:55 +0800 Subject: [PATCH 0933/7155] iio: humidity: Use device-managed APIs Use device-managed APIs to simplify the code. The remove functions are redundant now and can be deleted. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/am2315.c | 24 +++--------------------- drivers/iio/humidity/hdc100x.c | 19 +++---------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index f18da7859229..3bac98e731d9 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -240,32 +240,15 @@ static int am2315_probe(struct i2c_client *client, indio_dev->channels = am2315_channels; indio_dev->num_channels = ARRAY_SIZE(am2315_channels); - ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, iio_pollfunc_store_time, am2315_trigger_handler, NULL); if (ret < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) - goto err_buffer_cleanup; - - return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int am2315_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id am2315_i2c_id[] = { @@ -287,7 +270,6 @@ static struct i2c_driver am2315_driver = { .acpi_match_table = ACPI_PTR(am2315_acpi_id), }, .probe = am2315_probe, - .remove = am2315_remove, .id_table = am2315_i2c_id, }; diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 066e05f92081..bfe1cdb16846 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -385,28 +385,16 @@ static int hdc100x_probe(struct i2c_client *client, hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, NULL, hdc100x_trigger_handler, &hdc_buffer_setup_ops); if (ret < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int hdc100x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id hdc100x_id[] = { @@ -436,7 +424,6 @@ static struct i2c_driver hdc100x_driver = { .of_match_table = of_match_ptr(hdc100x_dt_ids), }, .probe = hdc100x_probe, - .remove = hdc100x_remove, .id_table = hdc100x_id, }; module_i2c_driver(hdc100x_driver); -- GitLab From 6e4707ed3411d0cb3c1d9a0a093f77fbdf768fa5 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 14:36:16 +0800 Subject: [PATCH 0934/7155] iio: mxc4005: Use device-managed APIs Use device-managed APIs to simplify the code. The remove function is redundant now and can be deleted. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mxc4005.c | 40 ++++++------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index 637e6e676061..3d5bea651923 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -424,7 +424,7 @@ static int mxc4005_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mxc4005_info; - ret = iio_triggered_buffer_setup(indio_dev, + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, iio_pollfunc_store_time, mxc4005_trigger_handler, NULL); @@ -452,7 +452,7 @@ static int mxc4005_probe(struct i2c_client *client, if (ret) { dev_err(&client->dev, "failed to init threaded irq\n"); - goto err_buffer_cleanup; + return ret; } data->dready_trig->dev.parent = &client->dev; @@ -460,43 +460,16 @@ static int mxc4005_probe(struct i2c_client *client, iio_trigger_set_drvdata(data->dready_trig, indio_dev); indio_dev->trig = data->dready_trig; iio_trigger_get(indio_dev->trig); - ret = iio_trigger_register(data->dready_trig); + ret = devm_iio_trigger_register(&client->dev, + data->dready_trig); if (ret) { dev_err(&client->dev, "failed to register trigger\n"); - goto err_trigger_unregister; + return ret; } } - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, - "unable to register iio device %d\n", ret); - goto err_buffer_cleanup; - } - - return 0; - -err_trigger_unregister: - iio_trigger_unregister(data->dready_trig); -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int mxc4005_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct mxc4005_data *data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - iio_triggered_buffer_cleanup(indio_dev); - if (data->dready_trig) - iio_trigger_unregister(data->dready_trig); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct acpi_device_id mxc4005_acpi_match[] = { @@ -517,7 +490,6 @@ static struct i2c_driver mxc4005_driver = { .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), }, .probe = mxc4005_probe, - .remove = mxc4005_remove, .id_table = mxc4005_id, }; -- GitLab From dca39af8831e65adc13e0f9f8bdca3a746185072 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 23 Jul 2019 10:36:38 +0300 Subject: [PATCH 0935/7155] iio: imu: adis: Add support for SPI transfer cs_change_delay The ADIS16460 requires a higher delay before the next transfer. Since the SPI framework supports configuring the delay before the next transfer, this driver will become the first user of it. The support for this functionality in ADIS16460 requires an addition to the ADIS lib to support the `cs_change_delay` functionality from the SPI subsystem. Signed-off-by: Michael Hennerich Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 12 ++++++++++++ include/linux/iio/imu/adis.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 30281e91dbf9..1631c255deab 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, @@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .rx_buf = adis->rx, @@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 3428d06b2f44..4c53815bb729 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -26,6 +26,7 @@ struct adis_burst; * struct adis_data - ADIS chip variant specific data * @read_delay: SPI delay for read operations in us * @write_delay: SPI delay for write operations in us + * @cs_change_delay: SPI delay between CS changes in us * @glob_cmd_reg: Register address of the GLOB_CMD register * @msc_ctrl_reg: Register address of the MSC_CTRL register * @diag_stat_reg: Register address of the DIAG_STAT register @@ -35,6 +36,7 @@ struct adis_burst; struct adis_data { unsigned int read_delay; unsigned int write_delay; + unsigned int cs_change_delay; unsigned int glob_cmd_reg; unsigned int msc_ctrl_reg; -- GitLab From db6ed4d23dd10a5bfbe922f23fc284bd4b4b0a1d Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 23 Jul 2019 10:36:39 +0300 Subject: [PATCH 0936/7155] iio: imu: Add support for the ADIS16460 IMU The ADIS16460 device is a complete inertial system that includes a triaxial gyroscope and a triaxial accelerometer. It's more simplified design than that of the ADIS16480, and does not offer the triaxial magnetometers & pressure sensors. It does also have a temperature sensor (like the ADIS16480). Since it is part of the ADIS16XXX family, it re-uses parts of the ADIS library. Naturally, the register map is different and much more simplified than the ADIS16480 subfamily, so it cannot be integrated into that driver. A major difference is that the registers are not paged. One thing that is particularly special about it, is that it requires a higher delay between CS changes (i.e. when CS goes up, the spec recommends that it be brought down after a minimum of 16 uS). Other ADIS chips require (via spec) a minimum of 2 uS between CS changes. The kernel's 10 uS default should be fine for those other chips; they haven't been tested with lower CS change delays yet. Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adis16460.pdf Signed-off-by: Dragos Bogdan Signed-off-by: Michael Hennerich Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/imu/Kconfig | 12 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/adis16460.c | 489 ++++++++++++++++++++++++++++++++++++ 4 files changed, 509 insertions(+) create mode 100644 drivers/iio/imu/adis16460.c diff --git a/MAINTAINERS b/MAINTAINERS index 90498954685b..4213e3b00a75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -945,6 +945,13 @@ L: linux-iio@vger.kernel.org F: include/linux/iio/imu/adis.h F: drivers/iio/imu/adis.c +ANALOG DEVICES INC ADIS16460 DRIVER +M: Dragos Bogdan +S: Supported +L: linux-iio@vger.kernel.org +W: http://ez.analog.com/community/linux-device-drivers +F: drivers/iio/imu/adis16460.c + ANALOG DEVICES INC ADP5061 DRIVER M: Stefan Popa L: linux-pm@vger.kernel.org diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 4957e6df447e..f3c7282321a8 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -17,6 +17,18 @@ config ADIS16400 adis16365, adis16400 and adis16405 triaxial inertial sensors (adis16400 series also have magnetometers). +config ADIS16460 + tristate "Analog Devices ADIS16460 and similar IMU driver" + depends on SPI + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER + help + Say yes here to build support for Analog Devices ADIS16460 inertial + sensor. + + To compile this driver as a module, choose M here: the module will be + called adis16460. + config ADIS16480 tristate "Analog Devices ADIS16480 and similar IMU driver" depends on SPI diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 9e452fce1aaf..4a6958865504 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -5,6 +5,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_ADIS16400) += adis16400.o +obj-$(CONFIG_ADIS16460) += adis16460.o obj-$(CONFIG_ADIS16480) += adis16480.o adis_lib-y += adis.o diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c new file mode 100644 index 000000000000..1ef11640ee20 --- /dev/null +++ b/drivers/iio/imu/adis16460.c @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ADIS16460 IMU driver + * + * Copyright 2019 Analog Devices Inc. + */ + +#include +#include +#include + +#include +#include + +#include + +#define ADIS16460_REG_FLASH_CNT 0x00 +#define ADIS16460_REG_DIAG_STAT 0x02 +#define ADIS16460_REG_X_GYRO_LOW 0x04 +#define ADIS16460_REG_X_GYRO_OUT 0x06 +#define ADIS16460_REG_Y_GYRO_LOW 0x08 +#define ADIS16460_REG_Y_GYRO_OUT 0x0A +#define ADIS16460_REG_Z_GYRO_LOW 0x0C +#define ADIS16460_REG_Z_GYRO_OUT 0x0E +#define ADIS16460_REG_X_ACCL_LOW 0x10 +#define ADIS16460_REG_X_ACCL_OUT 0x12 +#define ADIS16460_REG_Y_ACCL_LOW 0x14 +#define ADIS16460_REG_Y_ACCL_OUT 0x16 +#define ADIS16460_REG_Z_ACCL_LOW 0x18 +#define ADIS16460_REG_Z_ACCL_OUT 0x1A +#define ADIS16460_REG_SMPL_CNTR 0x1C +#define ADIS16460_REG_TEMP_OUT 0x1E +#define ADIS16460_REG_X_DELT_ANG 0x24 +#define ADIS16460_REG_Y_DELT_ANG 0x26 +#define ADIS16460_REG_Z_DELT_ANG 0x28 +#define ADIS16460_REG_X_DELT_VEL 0x2A +#define ADIS16460_REG_Y_DELT_VEL 0x2C +#define ADIS16460_REG_Z_DELT_VEL 0x2E +#define ADIS16460_REG_MSC_CTRL 0x32 +#define ADIS16460_REG_SYNC_SCAL 0x34 +#define ADIS16460_REG_DEC_RATE 0x36 +#define ADIS16460_REG_FLTR_CTRL 0x38 +#define ADIS16460_REG_GLOB_CMD 0x3E +#define ADIS16460_REG_X_GYRO_OFF 0x40 +#define ADIS16460_REG_Y_GYRO_OFF 0x42 +#define ADIS16460_REG_Z_GYRO_OFF 0x44 +#define ADIS16460_REG_X_ACCL_OFF 0x46 +#define ADIS16460_REG_Y_ACCL_OFF 0x48 +#define ADIS16460_REG_Z_ACCL_OFF 0x4A +#define ADIS16460_REG_LOT_ID1 0x52 +#define ADIS16460_REG_LOT_ID2 0x54 +#define ADIS16460_REG_PROD_ID 0x56 +#define ADIS16460_REG_SERIAL_NUM 0x58 +#define ADIS16460_REG_CAL_SGNTR 0x60 +#define ADIS16460_REG_CAL_CRC 0x62 +#define ADIS16460_REG_CODE_SGNTR 0x64 +#define ADIS16460_REG_CODE_CRC 0x66 + +struct adis16460_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; + unsigned int gyro_max_val; + unsigned int gyro_max_scale; + unsigned int accel_max_val; + unsigned int accel_max_scale; +}; + +struct adis16460 { + const struct adis16460_chip_info *chip_info; + struct adis adis; +}; + +#ifdef CONFIG_DEBUG_FS + +static int adis16460_show_serial_number(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u16 serial; + int ret; + + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM, + &serial); + if (ret < 0) + return ret; + + *val = serial; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops, + adis16460_show_serial_number, NULL, "0x%.4llx\n"); + +static int adis16460_show_product_id(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u16 prod_id; + int ret; + + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID, + &prod_id); + if (ret < 0) + return ret; + + *val = prod_id; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops, + adis16460_show_product_id, NULL, "%llu\n"); + +static int adis16460_show_flash_count(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u32 flash_count; + int ret; + + ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT, + &flash_count); + if (ret < 0) + return ret; + + *val = flash_count; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops, + adis16460_show_flash_count, NULL, "%lld\n"); + +static int adis16460_debugfs_init(struct iio_dev *indio_dev) +{ + struct adis16460 *adis16460 = iio_priv(indio_dev); + + debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_serial_number_fops); + debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_product_id_fops); + debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_flash_count_fops); + + return 0; +} + +#else + +static int adis16460_debugfs_init(struct iio_dev *indio_dev) +{ + return 0; +} + +#endif + +static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2) +{ + struct adis16460 *st = iio_priv(indio_dev); + unsigned int t; + + t = val * 1000 + val2 / 1000; + if (t <= 0) + return -EINVAL; + + t = 2048000 / t; + if (t > 2048) + t = 2048; + + if (t != 0) + t--; + + return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t); +} + +static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2) +{ + struct adis16460 *st = iio_priv(indio_dev); + uint16_t t; + int ret; + unsigned int freq; + + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t); + if (ret < 0) + return ret; + + freq = 2048000 / (t + 1); + *val = freq / 1000; + *val2 = (freq % 1000) * 1000; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int adis16460_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) +{ + struct adis16460 *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = st->chip_info->gyro_max_scale; + *val2 = st->chip_info->gyro_max_val; + return IIO_VAL_FRACTIONAL; + case IIO_ACCEL: + *val = st->chip_info->accel_max_scale; + *val2 = st->chip_info->accel_max_val; + return IIO_VAL_FRACTIONAL; + case IIO_TEMP: + *val = 50; /* 50 milli degrees Celsius/LSB */ + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + *val = 500; /* 25 degrees Celsius = 0x0000 */ + return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16460_get_freq(indio_dev, val, val2); + default: + return -EINVAL; + } +} + +static int adis16460_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int val, int val2, long info) +{ + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16460_set_freq(indio_dev, val, val2); + default: + return -EINVAL; + } +} + +enum { + ADIS16460_SCAN_GYRO_X, + ADIS16460_SCAN_GYRO_Y, + ADIS16460_SCAN_GYRO_Z, + ADIS16460_SCAN_ACCEL_X, + ADIS16460_SCAN_ACCEL_Y, + ADIS16460_SCAN_ACCEL_Z, + ADIS16460_SCAN_TEMP, +}; + +#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \ + { \ + .type = (_type), \ + .modified = 1, \ + .channel2 = (_mod), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = (_address), \ + .scan_index = (_si), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (_bits), \ + .storagebits = (_bits), \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16460_GYRO_CHANNEL(_mod) \ + ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ + ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \ + 32) + +#define ADIS16460_ACCEL_CHANNEL(_mod) \ + ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \ + ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \ + 32) + +#define ADIS16460_TEMP_CHANNEL() { \ + .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = ADIS16460_REG_TEMP_OUT, \ + .scan_index = ADIS16460_SCAN_TEMP, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adis16460_channels[] = { + ADIS16460_GYRO_CHANNEL(X), + ADIS16460_GYRO_CHANNEL(Y), + ADIS16460_GYRO_CHANNEL(Z), + ADIS16460_ACCEL_CHANNEL(X), + ADIS16460_ACCEL_CHANNEL(Y), + ADIS16460_ACCEL_CHANNEL(Z), + ADIS16460_TEMP_CHANNEL(), + IIO_CHAN_SOFT_TIMESTAMP(7) +}; + +static const struct adis16460_chip_info adis16460_chip_info = { + .channels = adis16460_channels, + .num_channels = ARRAY_SIZE(adis16460_channels), + /* + * storing the value in rad/degree and the scale in degree + * gives us the result in rad and better precession than + * storing the scale directly in rad. + */ + .gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16), + .gyro_max_scale = 1, + .accel_max_val = IIO_M_S_2_TO_G(20000 << 16), + .accel_max_scale = 5, +}; + +static const struct iio_info adis16460_info = { + .read_raw = &adis16460_read_raw, + .write_raw = &adis16460_write_raw, + .update_scan_mode = adis_update_scan_mode, + .debugfs_reg_access = adis_debugfs_reg_access, +}; + +static int adis16460_enable_irq(struct adis *adis, bool enable) +{ + /* + * There is no way to gate the data-ready signal internally inside the + * ADIS16460 :( + */ + if (enable) + enable_irq(adis->spi->irq); + else + disable_irq(adis->spi->irq); + + return 0; +} + +static int adis16460_initial_setup(struct iio_dev *indio_dev) +{ + struct adis16460 *st = iio_priv(indio_dev); + uint16_t prod_id; + unsigned int device_id; + int ret; + + adis_reset(&st->adis); + msleep(222); + + ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1)); + if (ret) + return ret; + msleep(75); + + ret = adis_check_status(&st->adis); + if (ret) + return ret; + + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id); + if (ret) + return ret; + + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); + if (ret != 1) + return -EINVAL; + + if (prod_id != device_id) + dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", + device_id, prod_id); + + return 0; +} + +#define ADIS16460_DIAG_STAT_IN_CLK_OOS 7 +#define ADIS16460_DIAG_STAT_FLASH_MEM 6 +#define ADIS16460_DIAG_STAT_SELF_TEST 5 +#define ADIS16460_DIAG_STAT_OVERRANGE 4 +#define ADIS16460_DIAG_STAT_SPI_COMM 3 +#define ADIS16460_DIAG_STAT_FLASH_UPT 2 + +static const char * const adis16460_status_error_msgs[] = { + [ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync", + [ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure", + [ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure", + [ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange", + [ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure", + [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", +}; + +static const struct adis_data adis16460_data = { + .diag_stat_reg = ADIS16460_REG_DIAG_STAT, + .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, + .has_paging = false, + .read_delay = 5, + .write_delay = 5, + .cs_change_delay = 16, + .status_error_msgs = adis16460_status_error_msgs, + .status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) | + BIT(ADIS16460_DIAG_STAT_FLASH_MEM) | + BIT(ADIS16460_DIAG_STAT_SELF_TEST) | + BIT(ADIS16460_DIAG_STAT_OVERRANGE) | + BIT(ADIS16460_DIAG_STAT_SPI_COMM) | + BIT(ADIS16460_DIAG_STAT_FLASH_UPT), + .enable_irq = adis16460_enable_irq, +}; + +static int adis16460_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adis16460 *st; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, indio_dev); + + st = iio_priv(indio_dev); + + st->chip_info = &adis16460_chip_info; + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->info = &adis16460_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data); + if (ret) + return ret; + + ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + if (ret) + return ret; + + adis16460_enable_irq(&st->adis, 0); + + ret = adis16460_initial_setup(indio_dev); + if (ret) + goto error_cleanup_buffer; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_cleanup_buffer; + + adis16460_debugfs_init(indio_dev); + + return 0; + +error_cleanup_buffer: + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + return ret; +} + +static int adis16460_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis16460 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + + return 0; +} + +static const struct spi_device_id adis16460_ids[] = { + { "adis16460", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adis16460_ids); + +static const struct of_device_id adis16460_of_match[] = { + { .compatible = "adi,adis16460" }, + {} +}; +MODULE_DEVICE_TABLE(of, adis16460_of_match); + +static struct spi_driver adis16460_driver = { + .driver = { + .name = "adis16460", + .of_match_table = adis16460_of_match, + }, + .id_table = adis16460_ids, + .probe = adis16460_probe, + .remove = adis16460_remove, +}; +module_spi_driver(adis16460_driver); + +MODULE_AUTHOR("Dragos Bogdan "); +MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver"); +MODULE_LICENSE("GPL"); -- GitLab From 1c667c4d99d7a42bc6bdcafc2896045e8c17b910 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 23 Jul 2019 10:36:40 +0300 Subject: [PATCH 0937/7155] dt-bindings: iio: imu: add bindings for ADIS16460 This change adds device-tree bindings for the ADIS16460. Signed-off-by: Alexandru Ardelean Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/imu/adi,adis16460.yaml | 53 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml new file mode 100644 index 000000000000..0c53009ba7d6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/imu/adi,adis16460.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADIS16460 and similar IMUs + +maintainers: + - Dragos Bogdan + +description: | + Analog Devices ADIS16460 and similar IMUs + https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16460.pdf + +properties: + compatible: + enum: + - adi,adis16460 + + reg: + maxItems: 1 + + spi-cpha: true + + spi-cpol: true + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + imu@0 { + compatible = "adi,adis16460"; + reg = <0>; + spi-max-frequency = <5000000>; + spi-cpol; + spi-cpha; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 4213e3b00a75..ff1cac18ef38 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -951,6 +951,7 @@ S: Supported L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers F: drivers/iio/imu/adis16460.c +F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml ANALOG DEVICES INC ADP5061 DRIVER M: Stefan Popa -- GitLab From d96dbb3f1b74f5d521e9f6148e6d467be9892dcf Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:11 +0200 Subject: [PATCH 0938/7155] iio: light: cm36651: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Signed-off-by: Jonathan Cameron --- drivers/iio/light/cm36651.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 7702c2bcbcfa..1019d625adb1 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -646,18 +646,18 @@ static int cm36651_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); cm36651->client = client; - cm36651->ps_client = i2c_new_dummy(client->adapter, + cm36651->ps_client = i2c_new_dummy_device(client->adapter, CM36651_I2C_ADDR_PS); - if (!cm36651->ps_client) { + if (IS_ERR(cm36651->ps_client)) { dev_err(&client->dev, "%s: new i2c device failed\n", __func__); - ret = -ENODEV; + ret = PTR_ERR(cm36651->ps_client); goto error_disable_reg; } - cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); - if (!cm36651->ara_client) { + cm36651->ara_client = i2c_new_dummy_device(client->adapter, CM36651_ARA); + if (IS_ERR(cm36651->ara_client)) { dev_err(&client->dev, "%s: new i2c device failed\n", __func__); - ret = -ENODEV; + ret = PTR_ERR(cm36651->ara_client); goto error_i2c_unregister_ps; } -- GitLab From 48cfd4ef0d52c1e02152949556492011b2524555 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:12 +0200 Subject: [PATCH 0939/7155] iio: light: veml6070: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Signed-off-by: Jonathan Cameron --- drivers/iio/light/veml6070.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index a3138e1b5803..0be553ad5989 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -158,10 +158,10 @@ static int veml6070_probe(struct i2c_client *client, indio_dev->name = VEML6070_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); - if (!data->client2) { + data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB); + if (IS_ERR(data->client2)) { dev_err(&client->dev, "i2c device for second chip address failed\n"); - return -ENODEV; + return PTR_ERR(data->client2); } data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | -- GitLab From b4a339baf35995cd9443439120de60d4605384b1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Jul 2019 19:26:13 +0200 Subject: [PATCH 0940/7155] iio: pressure: hp03: convert to i2c_new_dummy_device Move from i2c_new_dummy() to i2c_new_dummy_device(), so we now get an ERRPTR which we use in error handling. Signed-off-by: Wolfram Sang Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/hp03.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index f00102577fd5..026ba15ef68f 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -243,10 +243,10 @@ static int hp03_probe(struct i2c_client *client, * which has it's dedicated I2C address and contains * the calibration constants for the sensor. */ - priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR); - if (!priv->eeprom_client) { + priv->eeprom_client = i2c_new_dummy_device(client->adapter, HP03_EEPROM_ADDR); + if (IS_ERR(priv->eeprom_client)) { dev_err(dev, "New EEPROM I2C device failed\n"); - return -ENODEV; + return PTR_ERR(priv->eeprom_client); } priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client, -- GitLab From 3f2cde742632226a86b54b2f8ed9cf5c4f50638c Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jul 2019 23:35:33 +0200 Subject: [PATCH 0941/7155] iio: magnetometer: mmc35240: Fix a typo in the name of a constant Everything is about mmc35240_ except MMC53240_WAIT_SET_RESET (3 and 5 switched). This is likely a typo. Define and use MMC35240_WAIT_SET_RESET instead. Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mmc35240.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 7de10281ad9e..425cdd07b4e5 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -53,7 +53,7 @@ #define MMC35240_CTRL1_BW_SHIFT 0 #define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ -#define MMC53240_WAIT_SET_RESET 1000 /* us */ +#define MMC35240_WAIT_SET_RESET 1000 /* us */ /* * Memsic OTP process code piece is put here for reference: @@ -225,7 +225,7 @@ static int mmc35240_init(struct mmc35240_data *data) ret = mmc35240_hw_set(data, true); if (ret < 0) return ret; - usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); + usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1); ret = mmc35240_hw_set(data, false); if (ret < 0) -- GitLab From 2660b0080bb26506d2f12983485deb9d0cf2747c Mon Sep 17 00:00:00 2001 From: Vitor Soares Date: Fri, 19 Jul 2019 15:30:55 +0200 Subject: [PATCH 0942/7155] iio: imu: st_lsm6dsx: add i3c basic support for LSM6DSO and LSM6DSR For today the st_lsm6dsx driver support LSM6DSO and LSM6DSR sensor only in spi and i2c mode. The LSM6DSO and LSM6DSR are also i3c capable so let's give i3c support to them. Signed-off-by: Vitor Soares Acked-by: Lorenzo Bianconi Reviewed-by: Boris Brezillon Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/Kconfig | 8 ++- drivers/iio/imu/st_lsm6dsx/Makefile | 1 + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c | 57 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 2d8b2e1edfce..6cbf65a7e11e 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -2,11 +2,12 @@ config IIO_ST_LSM6DSX tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" - depends on (I2C || SPI) + depends on (I2C || SPI || I3C) select IIO_BUFFER select IIO_KFIFO_BUF select IIO_ST_LSM6DSX_I2C if (I2C) select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) + select IIO_ST_LSM6DSX_I3C if (I3C) help Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, @@ -24,3 +25,8 @@ config IIO_ST_LSM6DSX_SPI tristate depends on IIO_ST_LSM6DSX select REGMAP_SPI + +config IIO_ST_LSM6DSX_I3C + tristate + depends on IIO_ST_LSM6DSX + select REGMAP_I3C diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6dsx/Makefile index 28cc67399d94..57cbcd67d64f 100644 --- a/drivers/iio/imu/st_lsm6dsx/Makefile +++ b/drivers/iio/imu/st_lsm6dsx/Makefile @@ -5,3 +5,4 @@ st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \ obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o +obj-$(CONFIG_IIO_ST_LSM6DSX_I3C) += st_lsm6dsx_i3c.o diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c new file mode 100644 index 000000000000..57e633121bdc --- /dev/null +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + * + * Author: Vitor Soares + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "st_lsm6dsx.h" + +static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = { + I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID), + I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID), + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids); + +static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev) +{ + struct regmap_config st_lsm6dsx_i3c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + }; + const struct i3c_device_id *id = i3c_device_match_id(i3cdev, + st_lsm6dsx_i3c_ids); + struct regmap *regmap; + + regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&i3cdev->dev, "Failed to register i3c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return st_lsm6dsx_probe(&i3cdev->dev, 0, (uintptr_t)id->data, regmap); +} + +static struct i3c_driver st_lsm6dsx_driver = { + .driver = { + .name = "st_lsm6dsx_i3c", + .pm = &st_lsm6dsx_pm_ops, + }, + .probe = st_lsm6dsx_i3c_probe, + .id_table = st_lsm6dsx_i3c_ids, +}; +module_i3c_driver(st_lsm6dsx_driver); + +MODULE_AUTHOR("Vitor Soares "); +MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i3c driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From ec76d918f23034f9f662539ca9c64e2ae3ba9fba Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 15 Jul 2019 09:07:15 +0200 Subject: [PATCH 0943/7155] iio: imu: st_lsm6dsx: flip irq return logic No need for using reverse logic in the irq return, fix this by flip things around. Signed-off-by: Sean Nyekjaer Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 38194f4d2b7e..1be1cec2ab23 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -670,7 +670,7 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) count = hw->settings->fifo_ops.read_fifo(hw); mutex_unlock(&hw->fifo_lock); - return !count ? IRQ_NONE : IRQ_HANDLED; + return count ? IRQ_HANDLED : IRQ_NONE; } static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) -- GitLab From 3e4dabacf967535e87bb1b254c08471a2148faea Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 21:39:16 +0800 Subject: [PATCH 0944/7155] counter/ftm-quaddec: Use device-managed registration API Make use of devm_counter_register. Then we can remove redundant unregistration API usage to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/counter/ftm-quaddec.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index 68a9b7393457..4046aa9f9234 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -100,16 +100,18 @@ static void ftm_quaddec_init(struct ftm_quaddec *ftm) ftm_set_write_protection(ftm); } -static void ftm_quaddec_disable(struct ftm_quaddec *ftm) +static void ftm_quaddec_disable(void *ftm) { - ftm_clear_write_protection(ftm); - ftm_write(ftm, FTM_MODE, 0); - ftm_write(ftm, FTM_QDCTRL, 0); + struct ftm_quaddec *ftm_qua = ftm; + + ftm_clear_write_protection(ftm_qua); + ftm_write(ftm_qua, FTM_MODE, 0); + ftm_write(ftm_qua, FTM_QDCTRL, 0); /* * This is enough to disable the counter. No clock has been * selected by writing to FTM_SC in init() */ - ftm_set_write_protection(ftm); + ftm_set_write_protection(ftm_qua); } static int ftm_quaddec_get_prescaler(struct counter_device *counter, @@ -317,20 +319,13 @@ static int ftm_quaddec_probe(struct platform_device *pdev) ftm_quaddec_init(ftm); - ret = counter_register(&ftm->counter); + ret = devm_add_action_or_reset(&pdev->dev, ftm_quaddec_disable, ftm); if (ret) - ftm_quaddec_disable(ftm); - - return ret; -} + return ret; -static int ftm_quaddec_remove(struct platform_device *pdev) -{ - struct ftm_quaddec *ftm = platform_get_drvdata(pdev); - - counter_unregister(&ftm->counter); - - ftm_quaddec_disable(ftm); + ret = devm_counter_register(&pdev->dev, &ftm->counter); + if (ret) + return ret; return 0; } @@ -346,7 +341,6 @@ static struct platform_driver ftm_quaddec_driver = { .of_match_table = ftm_quaddec_match, }, .probe = ftm_quaddec_probe, - .remove = ftm_quaddec_remove, }; module_platform_driver(ftm_quaddec_driver); -- GitLab From 3cf9df00957fb27cb116761cd4d656aee06e40d3 Mon Sep 17 00:00:00 2001 From: Fabien Lahoudere Date: Tue, 2 Jul 2019 10:49:38 +0200 Subject: [PATCH 0945/7155] iio: common: cros_ec_sensors: determine protocol version This patch adds a function to determine which version of the protocol is used to communicate with EC. Signed-off-by: Nick Vaccaro Signed-off-by: Fabien Lahoudere Reviewed-by: Gwendal Grignou Tested-by: Gwendal Grignou [rebased on top of iio/testing and solved conflicts] Signed-off-by: Enric Balletbo i Serra Signed-off-by: Jonathan Cameron --- .../cros_ec_sensors/cros_ec_sensors_core.c | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 8d43965c3b9a..d02660b1f0fe 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -25,6 +25,31 @@ static char *cros_ec_loc[] = { [MOTIONSENSE_LOC_MAX] = "unknown", }; +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, + u16 cmd_offset, u16 cmd, u32 *mask) +{ + int ret; + struct { + struct cros_ec_command msg; + union { + struct ec_params_get_cmd_versions params; + struct ec_response_get_cmd_versions resp; + }; + } __packed buf = { + .msg = { + .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset, + .insize = sizeof(struct ec_response_get_cmd_versions), + .outsize = sizeof(struct ec_params_get_cmd_versions) + }, + .params = {.cmd = cmd} + }; + + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); + if (ret >= 0) + *mask = buf.resp.version_mask; + return ret; +} + int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device) @@ -33,6 +58,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); + u32 ver_mask; int ret; platform_set_drvdata(pdev, indio_dev); @@ -48,8 +74,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, mutex_init(&state->cmd_lock); + ret = cros_ec_get_host_cmd_version_mask(state->ec, + ec->cmd_offset, + EC_CMD_MOTION_SENSE_CMD, + &ver_mask); + if (ret < 0) + return ret; + /* Set up the host command structure. */ - state->msg->version = 2; + state->msg->version = fls(ver_mask) - 1; state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; state->msg->outsize = sizeof(struct ec_params_motion_sense); -- GitLab From 12bf745c9afb6755acba186091bcbb61229f4165 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 15 Jul 2019 16:14:51 -0700 Subject: [PATCH 0946/7155] iio: cros_ec: Add sign vector in core for backward compatibility To allow cros_ec iio core library to be used with legacy device, add a vector to rotate sensor data if necessary: legacy devices are not reporting data in HTML5/Android sensor referential. Check the data is not rotated on recent chromebooks that use the HTML5 standard to present sensor data. Signed-off-by: Gwendal Grignou Reviewed-by: Douglas Anderson Signed-off-by: Jonathan Cameron --- drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 4 ++++ include/linux/iio/common/cros_ec_sensors_core.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index d02660b1f0fe..3b491cf7be95 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -101,6 +101,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, } state->type = state->resp->info.type; state->loc = state->resp->info.location; + + /* Set sign vector, only used for backward compatibility. */ + memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); } return 0; @@ -303,6 +306,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev, if (ret < 0) return ret; + *data *= st->sign[i]; data++; } diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index bb03a252bd04..6f13c73bac3d 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -66,7 +66,7 @@ struct cros_ec_sensors_core_state { s16 offset; u16 scale; } calib[CROS_EC_SENSOR_MAX_AXIS]; - + s8 sign[CROS_EC_SENSOR_MAX_AXIS]; u8 samples[CROS_EC_SAMPLE_SIZE]; int (*read_ec_sensors_data)(struct iio_dev *indio_dev, -- GitLab From b9a0a64e3b35934128551a25513d91bd634736ed Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 15 Jul 2019 16:14:52 -0700 Subject: [PATCH 0947/7155] iio: cros_ec_accel_legacy: Fix incorrect channel setting INFO_SCALE is set both for each channel and all channels. iio is using all channel setting, so the error was not user visible. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- drivers/iio/accel/cros_ec_accel_legacy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index 46bb2e421bb9..ad19d9c716f4 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { .modified = 1, \ .info_mask_separate = \ BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ .ext_info = cros_ec_accel_legacy_ext_info, \ -- GitLab From d96e267762fc723079b8089172077e94a4cf8dd2 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 15 Jul 2019 16:14:53 -0700 Subject: [PATCH 0948/7155] iio: cros_ec_accel_legacy: Use cros_ec_sensors_core Remove duplicate code in cros-ec-accel-legacy, use cros-ec-sensors-core functions and structures when possible. On glimmer, check the 2 accelerometers are presented and working. Signed-off-by: Gwendal Grignou Reviewed-by: Enric Balletbo i Serra Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 4 +- drivers/iio/accel/cros_ec_accel_legacy.c | 336 ++++------------------- 2 files changed, 55 insertions(+), 285 deletions(-) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9b9656ce37e6..d4ef35aeb579 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -202,9 +202,7 @@ config HID_SENSOR_ACCEL_3D config IIO_CROS_EC_ACCEL_LEGACY tristate "ChromeOS EC Legacy Accelerometer Sensor" - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select CROS_EC_LPC_REGISTER_DEVICE + depends on IIO_CROS_EC_SENSORS_CORE help Say yes here to get support for accelerometers on Chromebook using legacy EC firmware. diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index ad19d9c716f4..f65578c65a1c 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -25,191 +26,51 @@ #define DRV_NAME "cros-ec-accel-legacy" +#define CROS_EC_SENSOR_LEGACY_NUM 2 /* * Sensor scale hard coded at 10 bits per g, computed as: * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2 */ #define ACCEL_LEGACY_NSCALE 9586168 -/* Indices for EC sensor values. */ -enum { - X, - Y, - Z, - MAX_AXIS, -}; - -/* State data for cros_ec_accel_legacy iio driver. */ -struct cros_ec_accel_legacy_state { - struct cros_ec_device *ec; - - /* - * Array holding data from a single capture. 2 bytes per channel - * for the 3 channels plus the timestamp which is always last and - * 8-bytes aligned. - */ - s16 capture_data[8]; - s8 sign[MAX_AXIS]; - u8 sensor_num; -}; - -static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset, - u8 *dest) -{ - return ec->cmd_readmem(ec, offset, 1, dest); -} - -static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset, - u16 *dest) -{ - __le16 tmp; - int ret = ec->cmd_readmem(ec, offset, 2, &tmp); - - *dest = le16_to_cpu(tmp); - - return ret; -} - -/** - * read_ec_until_not_busy() - Read from EC status byte until it reads not busy. - * @st: Pointer to state information for device. - * - * This function reads EC status until its busy bit gets cleared. It does not - * wait indefinitely and returns -EIO if the EC status is still busy after a - * few hundreds milliseconds. - * - * Return: 8-bit status if ok, -EIO on error - */ -static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st) -{ - struct cros_ec_device *ec = st->ec; - u8 status; - int attempts = 0; - - ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); - while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) { - /* Give up after enough attempts, return error. */ - if (attempts++ >= 50) - return -EIO; - - /* Small delay every so often. */ - if (attempts % 5 == 0) - msleep(25); - - ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); - } - - return status; -} - -/** - * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory. - * @st: Pointer to state information for device. - * @scan_mask: Bitmap of the sensor indices to scan. - * @data: Location to store data. - * - * This is the unsafe function for reading the EC data. It does not guarantee - * that the EC will not modify the data as it is being read in. - */ -static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st, - unsigned long scan_mask, s16 *data) -{ - int i = 0; - int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS); - - /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */ - while (num_enabled--) { - i = find_next_bit(&scan_mask, MAX_AXIS, i); - ec_cmd_read_u16(st->ec, - EC_MEMMAP_ACC_DATA + - sizeof(s16) * - (1 + i + st->sensor_num * MAX_AXIS), - data); - *data *= st->sign[i]; - i++; - data++; - } -} - -/** - * read_ec_accel_data() - Read acceleration data from EC shared memory. - * @st: Pointer to state information for device. - * @scan_mask: Bitmap of the sensor indices to scan. - * @data: Location to store data. - * - * This is the safe function for reading the EC data. It guarantees that - * the data sampled was not modified by the EC while being read. - * - * Return: 0 if ok, -ve on error - */ -static int read_ec_accel_data(struct cros_ec_accel_legacy_state *st, - unsigned long scan_mask, s16 *data) -{ - u8 samp_id = 0xff; - u8 status = 0; - int ret; - int attempts = 0; - - /* - * Continually read all data from EC until the status byte after - * all reads reflects that the EC is not busy and the sample id - * matches the sample id from before all reads. This guarantees - * that data read in was not modified by the EC while reading. - */ - while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT | - EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) { - /* If we have tried to read too many times, return error. */ - if (attempts++ >= 5) - return -EIO; - - /* Read status byte until EC is not busy. */ - ret = read_ec_until_not_busy(st); - if (ret < 0) - return ret; - status = ret; - - /* - * Store the current sample id so that we can compare to the - * sample id after reading the data. - */ - samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; - - /* Read all EC data, format it, and store it into data. */ - read_ec_accel_data_unsafe(st, scan_mask, data); - - /* Read status byte. */ - ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status); - } - - return 0; -} - static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); s16 data = 0; - int ret = IIO_VAL_INT; + int ret; + int idx = chan->scan_index; + + mutex_lock(&st->cmd_lock); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = read_ec_accel_data(st, (1 << chan->scan_index), &data); - if (ret) - return ret; + ret = st->read_ec_sensors_data(indio_dev, 1 << idx, &data); + if (ret < 0) + break; + ret = IIO_VAL_INT; *val = data; - return IIO_VAL_INT; + break; case IIO_CHAN_INFO_SCALE: + WARN_ON(st->type != MOTIONSENSE_TYPE_ACCEL); *val = 0; *val2 = ACCEL_LEGACY_NSCALE; - return IIO_VAL_INT_PLUS_NANO; + ret = IIO_VAL_INT_PLUS_NANO; + break; case IIO_CHAN_INFO_CALIBBIAS: /* Calibration not supported. */ *val = 0; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = cros_ec_sensors_core_read(st, chan, val, val2, + mask); + break; } + mutex_unlock(&st->cmd_lock); + + return ret; } static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev, @@ -231,86 +92,14 @@ static const struct iio_info cros_ec_accel_legacy_info = { .write_raw = &cros_ec_accel_legacy_write, }; -/** - * cros_ec_accel_legacy_capture() - The trigger handler function - * @irq: The interrupt number. - * @p: Private data - always a pointer to the poll func. - * - * On a trigger event occurring, if the pollfunc is attached then this - * handler is called as a threaded interrupt (and hence may sleep). It - * is responsible for grabbing data from the device and pushing it into - * the associated buffer. - * - * Return: IRQ_HANDLED +/* + * Present the channel using HTML5 standard: + * need to invert X and Y and invert some lid axis. */ -static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - /* Clear capture data. */ - memset(st->capture_data, 0, sizeof(st->capture_data)); - - /* - * Read data based on which channels are enabled in scan mask. Note - * that on a capture we are always reading the calibrated data. - */ - read_ec_accel_data(st, *indio_dev->active_scan_mask, st->capture_data); - - iio_push_to_buffers_with_timestamp(indio_dev, (void *)st->capture_data, - iio_get_time_ns(indio_dev)); - - /* - * Tell the core we are done with this trigger and ready for the - * next one. - */ - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static char *cros_ec_accel_legacy_loc_strings[] = { - [MOTIONSENSE_LOC_BASE] = "base", - [MOTIONSENSE_LOC_LID] = "lid", - [MOTIONSENSE_LOC_MAX] = "unknown", -}; - -static ssize_t cros_ec_accel_legacy_loc(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - char *buf) -{ - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%s\n", - cros_ec_accel_legacy_loc_strings[st->sensor_num + - MOTIONSENSE_LOC_BASE]); -} - -static ssize_t cros_ec_accel_legacy_id(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - char *buf) -{ - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->sensor_num); -} - -static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { - { - .name = "id", - .shared = IIO_SHARED_BY_ALL, - .read = cros_ec_accel_legacy_id, - }, - { - .name = "location", - .shared = IIO_SHARED_BY_ALL, - .read = cros_ec_accel_legacy_loc, - }, - { } -}; +#define CROS_EC_ACCEL_ROTATE_AXIS(_axis) \ + ((_axis) == CROS_EC_SENSOR_Z ? CROS_EC_SENSOR_Z : \ + ((_axis) == CROS_EC_SENSOR_X ? CROS_EC_SENSOR_Y : \ + CROS_EC_SENSOR_X)) #define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \ { \ @@ -321,28 +110,28 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ - .ext_info = cros_ec_accel_legacy_ext_info, \ + .ext_info = cros_ec_sensors_ext_info, \ .scan_type = { \ .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ + .realbits = CROS_EC_SENSOR_BITS, \ + .storagebits = CROS_EC_SENSOR_BITS, \ }, \ + .scan_index = CROS_EC_ACCEL_ROTATE_AXIS(_axis), \ } \ -static struct iio_chan_spec ec_accel_channels[] = { - CROS_EC_ACCEL_LEGACY_CHAN(X), - CROS_EC_ACCEL_LEGACY_CHAN(Y), - CROS_EC_ACCEL_LEGACY_CHAN(Z), - IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS) +static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_X), + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Y), + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Z), + IIO_CHAN_SOFT_TIMESTAMP(CROS_EC_SENSOR_MAX_AXIS) }; static int cros_ec_accel_legacy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); - struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); struct iio_dev *indio_dev; - struct cros_ec_accel_legacy_state *state; + struct cros_ec_sensors_core_state *state; int ret; if (!ec || !ec->ec_dev) { @@ -350,46 +139,29 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) return -EINVAL; } - if (!ec->ec_dev->cmd_readmem) { - dev_warn(&pdev->dev, "EC does not support direct reads.\n"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; - platform_set_drvdata(pdev, indio_dev); - state = iio_priv(indio_dev); - state->ec = ec->ec_dev; - state->sensor_num = sensor_platform->sensor_num; - - indio_dev->dev.parent = dev; - indio_dev->name = pdev->name; - indio_dev->channels = ec_accel_channels; - /* - * Present the channel using HTML5 standard: - * need to invert X and Y and invert some lid axis. - */ - ec_accel_channels[X].scan_index = Y; - ec_accel_channels[Y].scan_index = X; - ec_accel_channels[Z].scan_index = Z; + ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + if (ret) + return ret; - state->sign[Y] = 1; + indio_dev->info = &cros_ec_accel_legacy_info; + state = iio_priv(indio_dev); - if (state->sensor_num == MOTIONSENSE_LOC_LID) - state->sign[X] = state->sign[Z] = -1; - else - state->sign[X] = state->sign[Z] = 1; + state->read_ec_sensors_data = cros_ec_sensors_read_lpc; - indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &cros_ec_accel_legacy_info; - indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = cros_ec_accel_legacy_channels; + indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels); + /* The lid sensor needs to be presented inverted. */ + if (state->loc == MOTIONSENSE_LOC_LID) { + state->sign[CROS_EC_SENSOR_X] = -1; + state->sign[CROS_EC_SENSOR_Z] = -1; + } ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_accel_legacy_capture, - NULL); + cros_ec_sensors_capture, NULL); if (ret) return ret; -- GitLab From 9566cb1ddb81c4f232d08cb2c7aff5b947959381 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 15 Jul 2019 16:14:54 -0700 Subject: [PATCH 0949/7155] iio: cros_ec_accel_legacy: Add support for veyron-minnie Veyron minnie embedded controller presents 2 accelerometers using an older interface. Add function to query the data in cros_ec_accel. Verify accelerometers on veyron-minnie are presented and working. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- drivers/iio/accel/cros_ec_accel_legacy.c | 40 ++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index f65578c65a1c..39002cb5605d 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -5,7 +5,7 @@ * Copyright 2017 Google, Inc * * This driver uses the memory mapper cros-ec interface to communicate - * with the Chrome OS EC about accelerometer data. + * with the Chrome OS EC about accelerometer data or older commands. * Accelerometer access is presented through iio sysfs. */ @@ -33,6 +33,39 @@ */ #define ACCEL_LEGACY_NSCALE 9586168 +static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret; + unsigned int i; + u8 sensor_num; + + /* + * Read all sensor data through a command. + * Save sensor_num, it is assumed to stay. + */ + sensor_num = st->param.info.sensor_num; + st->param.cmd = MOTIONSENSE_CMD_DUMP; + st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM; + ret = cros_ec_motion_send_host_cmd(st, + sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM * + sizeof(struct ec_response_motion_sensor_data)); + st->param.info.sensor_num = sensor_num; + if (ret != 0) { + dev_warn(&indio_dev->dev, "Unable to read sensor data\n"); + return ret; + } + + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + *data = st->resp->dump.sensor[sensor_num].data[i] * + st->sign[i]; + data++; + } + + return 0; +} + static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -150,7 +183,10 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) indio_dev->info = &cros_ec_accel_legacy_info; state = iio_priv(indio_dev); - state->read_ec_sensors_data = cros_ec_sensors_read_lpc; + if (state->ec->cmd_readmem != NULL) + state->read_ec_sensors_data = cros_ec_sensors_read_lpc; + else + state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd; indio_dev->channels = cros_ec_accel_legacy_channels; indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels); -- GitLab From ae7b02ad2f32d39d1434655f346c04a16c1aa703 Mon Sep 17 00:00:00 2001 From: Fabien Lahoudere Date: Tue, 16 Jul 2019 11:11:06 +0200 Subject: [PATCH 0950/7155] iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range via iio sysfs Embedded controller return minimum and maximum frequencies, unfortunately we have no way to know the step for all available frequencies. Even if not complete, we can return a list of known values using the standard read_avail callback (IIO_CHAN_INFO_SAMP_FREQ) to provide them to userland. Now cros_ec_* sensors provides frequencies values in sysfs like this: "0 min max". 0 is always true to disable the sensor. Default frequencies are provided for earlier protocol. Signed-off-by: Nick Vaccaro Signed-off-by: Fabien Lahoudere [rebased on top of iio/testing and solved conflicts] Signed-off-by: Enric Balletbo i Serra Signed-off-by: Jonathan Cameron --- .../common/cros_ec_sensors/cros_ec_sensors.c | 3 + .../cros_ec_sensors/cros_ec_sensors_core.c | 65 +++++++++++++++++++ drivers/iio/light/cros_ec_light_prox.c | 3 + .../linux/iio/common/cros_ec_sensors_core.h | 21 ++++++ 4 files changed, 92 insertions(+) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 2af09606c438..6a4919cd83c3 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -215,6 +215,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, static const struct iio_info ec_sensors_info = { .read_raw = &cros_ec_sensors_read, .write_raw = &cros_ec_sensors_write, + .read_avail = &cros_ec_sensors_core_read_avail, }; static int cros_ec_sensors_probe(struct platform_device *pdev) @@ -252,6 +253,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_FREQUENCY) | BIT(IIO_CHAN_INFO_SAMP_FREQ); + channel->info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_index = i; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 3b491cf7be95..fd833295bb17 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -50,6 +50,37 @@ static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, return ret; } +static void get_default_min_max_freq(enum motionsensor_type type, + u32 *min_freq, + u32 *max_freq) +{ + switch (type) { + case MOTIONSENSE_TYPE_ACCEL: + case MOTIONSENSE_TYPE_GYRO: + *min_freq = 12500; + *max_freq = 100000; + break; + case MOTIONSENSE_TYPE_MAG: + *min_freq = 5000; + *max_freq = 25000; + break; + case MOTIONSENSE_TYPE_PROX: + case MOTIONSENSE_TYPE_LIGHT: + *min_freq = 100; + *max_freq = 50000; + break; + case MOTIONSENSE_TYPE_BARO: + *min_freq = 250; + *max_freq = 20000; + break; + case MOTIONSENSE_TYPE_ACTIVITY: + default: + *min_freq = 0; + *max_freq = 0; + break; + } +} + int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device) @@ -104,6 +135,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, /* Set sign vector, only used for backward compatibility. */ memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); + + /* 0 is a correct value used to stop the device */ + state->frequencies[0] = 0; + if (state->msg->version < 3) { + get_default_min_max_freq(state->resp->info.type, + &state->frequencies[1], + &state->frequencies[2]); + } else { + state->frequencies[1] = + state->resp->info_3.min_frequency; + state->frequencies[2] = + state->resp->info_3.max_frequency; + } } return 0; @@ -471,6 +515,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask) +{ + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *length = ARRAY_SIZE(state->frequencies); + *vals = (const int *)&state->frequencies; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail); + int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask) diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 965f346d7d64..44313a009928 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -162,6 +162,7 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, static const struct iio_info cros_ec_light_prox_info = { .read_raw = &cros_ec_light_prox_read, .write_raw = &cros_ec_light_prox_write, + .read_avail = &cros_ec_sensors_core_read_avail, }; static int cros_ec_light_prox_probe(struct platform_device *pdev) @@ -196,6 +197,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_FREQUENCY); + channel->info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_type.shift = 0; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 6f13c73bac3d..ea1f50ce2e49 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -73,6 +73,9 @@ struct cros_ec_sensors_core_state { unsigned long scan_mask, s16 *data); int curr_sampl_freq; + + /* Table of known available frequencies : 0, Min and Max in mHz */ + int frequencies[3]; }; /** @@ -153,6 +156,24 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask); +/** + * cros_ec_sensors_core_read_avail() - get available values + * @indio_dev: pointer to state information for device + * @chan: channel specification structure table + * @vals: list of available values + * @type: type of data returned + * @length: number of data returned in the array + * @mask: specifies which values to be requested + * + * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST + */ +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask); + /** * cros_ec_sensors_core_write() - function to write a value to the sensor * @st: pointer to state information for device -- GitLab From 61098e89e6c80d6a141774ef8ee41e38471b069e Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:23 -0700 Subject: [PATCH 0951/7155] selftests/bpf: prevent headers to be compiled as C code Apprently listing header as a normal dependency for a binary output makes it go through compilation as if it was C code. This currently works without a problem, but in subsequent commits causes problems for differently generated test.h for test_progs. Marking those headers as order-only dependency solves the issue. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 11c9c62c3362..bb66cc4a7f34 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -235,7 +235,7 @@ PROG_TESTS_H := $(PROG_TESTS_DIR)/tests.h PROG_TESTS_FILES := $(wildcard prog_tests/*.c) test_progs.c: $(PROG_TESTS_H) $(OUTPUT)/test_progs: CFLAGS += $(TEST_PROGS_CFLAGS) -$(OUTPUT)/test_progs: test_progs.c $(PROG_TESTS_H) $(PROG_TESTS_FILES) +$(OUTPUT)/test_progs: test_progs.c $(PROG_TESTS_FILES) | $(PROG_TESTS_H) $(PROG_TESTS_H): $(PROG_TESTS_FILES) | $(PROG_TESTS_DIR) $(shell ( cd prog_tests/; \ echo '/* Generated header, do not edit */'; \ @@ -256,7 +256,7 @@ MAP_TESTS_H := $(MAP_TESTS_DIR)/tests.h MAP_TESTS_FILES := $(wildcard map_tests/*.c) test_maps.c: $(MAP_TESTS_H) $(OUTPUT)/test_maps: CFLAGS += $(TEST_MAPS_CFLAGS) -$(OUTPUT)/test_maps: test_maps.c $(MAP_TESTS_H) $(MAP_TESTS_FILES) +$(OUTPUT)/test_maps: test_maps.c $(MAP_TESTS_FILES) | $(MAP_TESTS_H) $(MAP_TESTS_H): $(MAP_TESTS_FILES) | $(MAP_TESTS_DIR) $(shell ( cd map_tests/; \ echo '/* Generated header, do not edit */'; \ @@ -277,7 +277,7 @@ VERIFIER_TESTS_H := $(VERIFIER_TESTS_DIR)/tests.h VERIFIER_TEST_FILES := $(wildcard verifier/*.c) test_verifier.c: $(VERIFIER_TESTS_H) $(OUTPUT)/test_verifier: CFLAGS += $(TEST_VERIFIER_CFLAGS) -$(OUTPUT)/test_verifier: test_verifier.c $(VERIFIER_TESTS_H) +$(OUTPUT)/test_verifier: test_verifier.c | $(VERIFIER_TEST_FILES) $(VERIFIER_TESTS_H) $(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR) $(shell ( cd verifier/; \ echo '/* Generated header, do not edit */'; \ -- GitLab From 766f2a59323a7881613af577718bb46cc1267b1f Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:24 -0700 Subject: [PATCH 0952/7155] selftests/bpf: revamp test_progs to allow more control Refactor test_progs to allow better control on what's being run. Also use argp to do argument parsing, so that it's easier to keep adding more options. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/Makefile | 8 +-- tools/testing/selftests/bpf/test_progs.c | 84 +++++++++++++++++++++--- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index bb66cc4a7f34..3bd0f4a0336a 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -239,14 +239,8 @@ $(OUTPUT)/test_progs: test_progs.c $(PROG_TESTS_FILES) | $(PROG_TESTS_H) $(PROG_TESTS_H): $(PROG_TESTS_FILES) | $(PROG_TESTS_DIR) $(shell ( cd prog_tests/; \ echo '/* Generated header, do not edit */'; \ - echo '#ifdef DECLARE'; \ ls *.c 2> /dev/null | \ - sed -e 's@\([^\.]*\)\.c@extern void test_\1(void);@'; \ - echo '#endif'; \ - echo '#ifdef CALL'; \ - ls *.c 2> /dev/null | \ - sed -e 's@\([^\.]*\)\.c@test_\1();@'; \ - echo '#endif' \ + sed -e 's@\([^\.]*\)\.c@DEFINE_TEST(\1)@'; \ ) > $(PROG_TESTS_H)) MAP_TESTS_DIR = $(OUTPUT)/map_tests diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index dae0819b1141..eea88ba59225 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -3,6 +3,7 @@ */ #include "test_progs.h" #include "bpf_rlimit.h" +#include int error_cnt, pass_cnt; bool jit_enabled; @@ -156,22 +157,89 @@ void *spin_lock_thread(void *arg) pthread_exit(arg); } -#define DECLARE +/* extern declarations for test funcs */ +#define DEFINE_TEST(name) extern void test_##name(); #include -#undef DECLARE +#undef DEFINE_TEST -int main(int ac, char **av) +struct prog_test_def { + const char *test_name; + void (*run_test)(void); +}; + +static struct prog_test_def prog_test_defs[] = { +#define DEFINE_TEST(name) { \ + .test_name = #name, \ + .run_test = &test_##name, \ +}, +#include +#undef DEFINE_TEST +}; + +const char *argp_program_version = "test_progs 0.1"; +const char *argp_program_bug_address = ""; +const char argp_program_doc[] = "BPF selftests test runner"; + +enum ARG_KEYS { + ARG_VERIFIER_STATS = 's', +}; + +static const struct argp_option opts[] = { + { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, + "Output verifier statistics", }, + {}, +}; + +struct test_env { + bool verifier_stats; +}; + +static struct test_env env = {}; + +static error_t parse_arg(int key, char *arg, struct argp_state *state) { + struct test_env *env = state->input; + + switch (key) { + case ARG_VERIFIER_STATS: + env->verifier_stats = true; + break; + case ARGP_KEY_ARG: + argp_usage(state); + break; + case ARGP_KEY_END: + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + + +int main(int argc, char **argv) +{ + static const struct argp argp = { + .options = opts, + .parser = parse_arg, + .doc = argp_program_doc, + }; + const struct prog_test_def *def; + int err, i; + + err = argp_parse(&argp, argc, argv, 0, NULL, &env); + if (err) + return err; + srand(time(NULL)); jit_enabled = is_jit_enabled(); - if (ac == 2 && strcmp(av[1], "-s") == 0) - verifier_stats = true; + verifier_stats = env.verifier_stats; -#define CALL -#include -#undef CALL + for (i = 0; i < ARRAY_SIZE(prog_test_defs); i++) { + def = &prog_test_defs[i]; + def->run_test(); + } printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; -- GitLab From 8160bae21fc29de0ec795abcd209cdd7cc144e8e Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:25 -0700 Subject: [PATCH 0953/7155] selftests/bpf: add test selectors by number and name to test_progs Add ability to specify either test number or test name substring to narrow down a set of test to run. Usage: sudo ./test_progs -n 1 sudo ./test_progs -t attach_probe Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_progs.c | 43 +++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index eea88ba59225..6e04b9f83777 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -4,6 +4,7 @@ #include "test_progs.h" #include "bpf_rlimit.h" #include +#include int error_cnt, pass_cnt; bool jit_enabled; @@ -164,6 +165,7 @@ void *spin_lock_thread(void *arg) struct prog_test_def { const char *test_name; + int test_num; void (*run_test)(void); }; @@ -181,26 +183,49 @@ const char *argp_program_bug_address = ""; const char argp_program_doc[] = "BPF selftests test runner"; enum ARG_KEYS { + ARG_TEST_NUM = 'n', + ARG_TEST_NAME = 't', ARG_VERIFIER_STATS = 's', }; static const struct argp_option opts[] = { + { "num", ARG_TEST_NUM, "NUM", 0, + "Run test number NUM only " }, + { "name", ARG_TEST_NAME, "NAME", 0, + "Run tests with names containing NAME" }, { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, "Output verifier statistics", }, {}, }; struct test_env { + int test_num_selector; + const char *test_name_selector; bool verifier_stats; }; -static struct test_env env = {}; +static struct test_env env = { + .test_num_selector = -1, +}; static error_t parse_arg(int key, char *arg, struct argp_state *state) { struct test_env *env = state->input; switch (key) { + case ARG_TEST_NUM: { + int test_num; + + errno = 0; + test_num = strtol(arg, NULL, 10); + if (errno) + return -errno; + env->test_num_selector = test_num; + break; + } + case ARG_TEST_NAME: + env->test_name_selector = arg; + break; case ARG_VERIFIER_STATS: env->verifier_stats = true; break; @@ -223,7 +248,7 @@ int main(int argc, char **argv) .parser = parse_arg, .doc = argp_program_doc, }; - const struct prog_test_def *def; + struct prog_test_def *test; int err, i; err = argp_parse(&argp, argc, argv, 0, NULL, &env); @@ -237,8 +262,18 @@ int main(int argc, char **argv) verifier_stats = env.verifier_stats; for (i = 0; i < ARRAY_SIZE(prog_test_defs); i++) { - def = &prog_test_defs[i]; - def->run_test(); + test = &prog_test_defs[i]; + + test->test_num = i + 1; + + if (env.test_num_selector >= 0 && + test->test_num != env.test_num_selector) + continue; + if (env.test_name_selector && + !strstr(test->test_name, env.test_name_selector)) + continue; + + test->run_test(); } printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); -- GitLab From e87fd8bae44c3eaa6205c9c81419e773896dc157 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:26 -0700 Subject: [PATCH 0954/7155] libbpf: return previous print callback from libbpf_set_print By returning previously set print callback from libbpf_set_print, it's possible to restore it, eventually. This is useful when running many independent test with one default print function, but overriding log verbosity for particular subset of tests. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf.c | 5 ++++- tools/lib/bpf/libbpf.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8741c39adb1c..ead915aec349 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -74,9 +74,12 @@ static int __base_pr(enum libbpf_print_level level, const char *format, static libbpf_print_fn_t __libbpf_pr = __base_pr; -void libbpf_set_print(libbpf_print_fn_t fn) +libbpf_print_fn_t libbpf_set_print(libbpf_print_fn_t fn) { + libbpf_print_fn_t old_print_fn = __libbpf_pr; + __libbpf_pr = fn; + return old_print_fn; } __printf(2, 3) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 5cbf459ece0b..8a9d462a6f6d 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -57,7 +57,7 @@ enum libbpf_print_level { typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level, const char *, va_list ap); -LIBBPF_API void libbpf_set_print(libbpf_print_fn_t fn); +LIBBPF_API libbpf_print_fn_t libbpf_set_print(libbpf_print_fn_t fn); /* Hide internal to user */ struct bpf_object; -- GitLab From 329e38f76cc2a77085264ce6e0dbe902c33fd7a3 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:27 -0700 Subject: [PATCH 0955/7155] selftest/bpf: centralize libbpf logging management for test_progs Make test_progs test runner own libbpf logging. Also introduce two levels of verbosity: -v and -vv. First one will be used in subsequent patches to enable test log output always. Second one increases verbosity level of libbpf logging further to include debug output as well. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- .../bpf/prog_tests/bpf_verif_scale.c | 6 +++- .../bpf/prog_tests/reference_tracking.c | 15 +++------- tools/testing/selftests/bpf/test_progs.c | 29 +++++++++++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index e1b55261526f..ceddb8cc86f4 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -70,10 +70,11 @@ void test_bpf_verif_scale(void) const char *cg_sysctl[] = { "./test_sysctl_loop1.o", "./test_sysctl_loop2.o", }; + libbpf_print_fn_t old_print_fn = NULL; int err, i; if (verifier_stats) - libbpf_set_print(libbpf_debug_print); + old_print_fn = libbpf_set_print(libbpf_debug_print); err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT); printf("test_scale:loop3:%s\n", err ? (error_cnt--, "OK") : "FAIL"); @@ -97,4 +98,7 @@ void test_bpf_verif_scale(void) err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL); printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK"); + + if (verifier_stats) + libbpf_set_print(old_print_fn); } diff --git a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c index 5633be43828f..4a4f428d1a78 100644 --- a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c +++ b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c @@ -1,15 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include -static int libbpf_debug_print(enum libbpf_print_level level, - const char *format, va_list args) -{ - if (level == LIBBPF_DEBUG) - return 0; - - return vfprintf(stderr, format, args); -} - void test_reference_tracking(void) { const char *file = "./test_sk_lookup_kern.o"; @@ -36,9 +27,11 @@ void test_reference_tracking(void) /* Expect verifier failure if test name has 'fail' */ if (strstr(title, "fail") != NULL) { - libbpf_set_print(NULL); + libbpf_print_fn_t old_print_fn; + + old_print_fn = libbpf_set_print(NULL); err = !bpf_program__load(prog, "GPL", 0); - libbpf_set_print(libbpf_debug_print); + libbpf_set_print(old_print_fn); } else { err = bpf_program__load(prog, "GPL", 0); } diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 6e04b9f83777..94b6951b90b3 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -186,6 +186,8 @@ enum ARG_KEYS { ARG_TEST_NUM = 'n', ARG_TEST_NAME = 't', ARG_VERIFIER_STATS = 's', + + ARG_VERBOSE = 'v', }; static const struct argp_option opts[] = { @@ -195,6 +197,8 @@ static const struct argp_option opts[] = { "Run tests with names containing NAME" }, { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, "Output verifier statistics", }, + { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL, + "Verbose output (use -vv for extra verbose output)" }, {}, }; @@ -202,12 +206,22 @@ struct test_env { int test_num_selector; const char *test_name_selector; bool verifier_stats; + bool verbose; + bool very_verbose; }; static struct test_env env = { .test_num_selector = -1, }; +static int libbpf_print_fn(enum libbpf_print_level level, + const char *format, va_list args) +{ + if (!env.very_verbose && level == LIBBPF_DEBUG) + return 0; + return vfprintf(stderr, format, args); +} + static error_t parse_arg(int key, char *arg, struct argp_state *state) { struct test_env *env = state->input; @@ -229,6 +243,19 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case ARG_VERIFIER_STATS: env->verifier_stats = true; break; + case ARG_VERBOSE: + if (arg) { + if (strcmp(arg, "v") == 0) { + env->very_verbose = true; + } else { + fprintf(stderr, + "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n", + arg); + return -EINVAL; + } + } + env->verbose = true; + break; case ARGP_KEY_ARG: argp_usage(state); break; @@ -255,6 +282,8 @@ int main(int argc, char **argv) if (err) return err; + libbpf_set_print(libbpf_print_fn); + srand(time(NULL)); jit_enabled = is_jit_enabled(); -- GitLab From 0ff97e56c0986ea6633083c3487d9231bbbd881b Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:28 -0700 Subject: [PATCH 0956/7155] selftests/bpf: abstract away test log output This patch changes how test output is printed out. By default, if test had no errors, the only output will be a single line with test number, name, and verdict at the end, e.g.: #31 xdp:OK If test had any errors, all log output captured during test execution will be output after test completes. It's possible to force output of log with `-v` (`--verbose`) option, in which case output won't be buffered and will be output immediately. To support this, individual tests are required to use helper methods for logging: `test__printf()` and `test__vprintf()`. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/bpf_obj_id.c | 6 +- .../bpf/prog_tests/bpf_verif_scale.c | 31 ++-- .../bpf/prog_tests/get_stack_raw_tp.c | 4 +- .../selftests/bpf/prog_tests/l4lb_all.c | 2 +- .../selftests/bpf/prog_tests/map_lock.c | 10 +- .../selftests/bpf/prog_tests/send_signal.c | 8 +- .../selftests/bpf/prog_tests/spinlock.c | 2 +- .../bpf/prog_tests/stacktrace_build_id.c | 4 +- .../bpf/prog_tests/stacktrace_build_id_nmi.c | 4 +- .../selftests/bpf/prog_tests/xdp_noinline.c | 3 +- tools/testing/selftests/bpf/test_progs.c | 145 ++++++++++++++---- tools/testing/selftests/bpf/test_progs.h | 37 ++++- 12 files changed, 183 insertions(+), 73 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c index cb827383db4d..fb5840a62548 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c @@ -106,8 +106,8 @@ void test_bpf_obj_id(void) if (CHECK(err || prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER || info_len != sizeof(struct bpf_prog_info) || - (jit_enabled && !prog_infos[i].jited_prog_len) || - (jit_enabled && + (env.jit_enabled && !prog_infos[i].jited_prog_len) || + (env.jit_enabled && !memcmp(jited_insns, zeros, sizeof(zeros))) || !prog_infos[i].xlated_prog_len || !memcmp(xlated_insns, zeros, sizeof(zeros)) || @@ -121,7 +121,7 @@ void test_bpf_obj_id(void) err, errno, i, prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER, info_len, sizeof(struct bpf_prog_info), - jit_enabled, + env.jit_enabled, prog_infos[i].jited_prog_len, prog_infos[i].xlated_prog_len, !!memcmp(jited_insns, zeros, sizeof(zeros)), diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index ceddb8cc86f4..b59017279e0b 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -4,12 +4,15 @@ static int libbpf_debug_print(enum libbpf_print_level level, const char *format, va_list args) { - if (level != LIBBPF_DEBUG) - return vfprintf(stderr, format, args); + if (level != LIBBPF_DEBUG) { + test__vprintf(format, args); + return 0; + } if (!strstr(format, "verifier log")) return 0; - return vfprintf(stderr, "%s", args); + test__vprintf("%s", args); + return 0; } static int check_load(const char *file, enum bpf_prog_type type) @@ -73,32 +76,38 @@ void test_bpf_verif_scale(void) libbpf_print_fn_t old_print_fn = NULL; int err, i; - if (verifier_stats) + if (env.verifier_stats) { + test__force_log(); old_print_fn = libbpf_set_print(libbpf_debug_print); + } err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT); - printf("test_scale:loop3:%s\n", err ? (error_cnt--, "OK") : "FAIL"); + test__printf("test_scale:loop3:%s\n", + err ? (error_cnt--, "OK") : "FAIL"); for (i = 0; i < ARRAY_SIZE(sched_cls); i++) { err = check_load(sched_cls[i], BPF_PROG_TYPE_SCHED_CLS); - printf("test_scale:%s:%s\n", sched_cls[i], err ? "FAIL" : "OK"); + test__printf("test_scale:%s:%s\n", sched_cls[i], + err ? "FAIL" : "OK"); } for (i = 0; i < ARRAY_SIZE(raw_tp); i++) { err = check_load(raw_tp[i], BPF_PROG_TYPE_RAW_TRACEPOINT); - printf("test_scale:%s:%s\n", raw_tp[i], err ? "FAIL" : "OK"); + test__printf("test_scale:%s:%s\n", raw_tp[i], + err ? "FAIL" : "OK"); } for (i = 0; i < ARRAY_SIZE(cg_sysctl); i++) { err = check_load(cg_sysctl[i], BPF_PROG_TYPE_CGROUP_SYSCTL); - printf("test_scale:%s:%s\n", cg_sysctl[i], err ? "FAIL" : "OK"); + test__printf("test_scale:%s:%s\n", cg_sysctl[i], + err ? "FAIL" : "OK"); } err = check_load("./test_xdp_loop.o", BPF_PROG_TYPE_XDP); - printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK"); + test__printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK"); err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL); - printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK"); + test__printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK"); - if (verifier_stats) + if (env.verifier_stats) libbpf_set_print(old_print_fn); } diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c index 9d73a8f932ac..3d59b3c841fe 100644 --- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c +++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c @@ -41,7 +41,7 @@ static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size) * just assume it is good if the stack is not empty. * This could be improved in the future. */ - if (jit_enabled) { + if (env.jit_enabled) { found = num_stack > 0; } else { for (i = 0; i < num_stack; i++) { @@ -58,7 +58,7 @@ static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size) } } else { num_stack = e->kern_stack_size / sizeof(__u64); - if (jit_enabled) { + if (env.jit_enabled) { good_kern_stack = num_stack > 0; } else { for (i = 0; i < num_stack; i++) { diff --git a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c index 20ddca830e68..5ce572c03a5f 100644 --- a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c +++ b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c @@ -74,7 +74,7 @@ static void test_l4lb(const char *file) } if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) { error_cnt++; - printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts); + test__printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts); } out: bpf_object__close(obj); diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c index ee99368c595c..2e78217ed3fd 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_lock.c +++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c @@ -9,12 +9,12 @@ static void *parallel_map_access(void *arg) for (i = 0; i < 10000; i++) { err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK); if (err) { - printf("lookup failed\n"); + test__printf("lookup failed\n"); error_cnt++; goto out; } if (vars[0] != 0) { - printf("lookup #%d var[0]=%d\n", i, vars[0]); + test__printf("lookup #%d var[0]=%d\n", i, vars[0]); error_cnt++; goto out; } @@ -22,8 +22,8 @@ static void *parallel_map_access(void *arg) for (j = 2; j < 17; j++) { if (vars[j] == rnd) continue; - printf("lookup #%d var[1]=%d var[%d]=%d\n", - i, rnd, j, vars[j]); + test__printf("lookup #%d var[1]=%d var[%d]=%d\n", + i, rnd, j, vars[j]); error_cnt++; goto out; } @@ -43,7 +43,7 @@ void test_map_lock(void) err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); if (err) { - printf("test_map_lock:bpf_prog_load errno %d\n", errno); + test__printf("test_map_lock:bpf_prog_load errno %d\n", errno); goto close_prog; } map_fd[0] = bpf_find_map(__func__, obj, "hash_map"); diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c index 54218ee3c004..d950f4558897 100644 --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c @@ -202,8 +202,8 @@ static int test_send_signal_nmi(void) -1 /* cpu */, -1 /* group_fd */, 0 /* flags */); if (pmu_fd == -1) { if (errno == ENOENT) { - printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", - __func__); + test__printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", + __func__); return 0; } /* Let the test fail with a more informative message */ @@ -222,8 +222,4 @@ void test_send_signal(void) ret |= test_send_signal_tracepoint(); ret |= test_send_signal_perf(); ret |= test_send_signal_nmi(); - if (!ret) - printf("test_send_signal:OK\n"); - else - printf("test_send_signal:FAIL\n"); } diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c index 114ebe6a438e..deb2db5b85b0 100644 --- a/tools/testing/selftests/bpf/prog_tests/spinlock.c +++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c @@ -12,7 +12,7 @@ void test_spinlock(void) err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); if (err) { - printf("test_spin_lock:bpf_prog_load errno %d\n", errno); + test__printf("test_spin_lock:bpf_prog_load errno %d\n", errno); goto close_prog; } for (i = 0; i < 4; i++) diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c index ac44fda84833..356d2c017a9c 100644 --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c @@ -109,8 +109,8 @@ void test_stacktrace_build_id(void) if (build_id_matches < 1 && retry--) { bpf_link__destroy(link); bpf_object__close(obj); - printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", - __func__); + test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", + __func__); goto retry; } diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c index 9557b7dfb782..f44f2c159714 100644 --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c @@ -140,8 +140,8 @@ void test_stacktrace_build_id_nmi(void) if (build_id_matches < 1 && retry--) { bpf_link__destroy(link); bpf_object__close(obj); - printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", - __func__); + test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", + __func__); goto retry; } diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c index 09e6b46f5515..b5404494b8aa 100644 --- a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c +++ b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c @@ -75,7 +75,8 @@ void test_xdp_noinline(void) } if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) { error_cnt++; - printf("test_xdp_noinline:FAIL:stats %lld %lld\n", bytes, pkts); + test__printf("test_xdp_noinline:FAIL:stats %lld %lld\n", + bytes, pkts); } out: bpf_object__close(obj); diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 94b6951b90b3..1b7470d3da22 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -6,9 +6,85 @@ #include #include +/* defined in test_progs.h */ +struct test_env env = { + .test_num_selector = -1, +}; int error_cnt, pass_cnt; -bool jit_enabled; -bool verifier_stats = false; + +struct prog_test_def { + const char *test_name; + int test_num; + void (*run_test)(void); + bool force_log; + int pass_cnt; + int error_cnt; + bool tested; +}; + +void test__force_log() { + env.test->force_log = true; +} + +void test__vprintf(const char *fmt, va_list args) +{ + size_t rem_sz; + int ret = 0; + + if (env.verbose || (env.test && env.test->force_log)) { + vfprintf(stderr, fmt, args); + return; + } + +try_again: + rem_sz = env.log_cap - env.log_cnt; + if (rem_sz) { + va_list ap; + + va_copy(ap, args); + /* we reserved extra byte for \0 at the end */ + ret = vsnprintf(env.log_buf + env.log_cnt, rem_sz + 1, fmt, ap); + va_end(ap); + + if (ret < 0) { + env.log_buf[env.log_cnt] = '\0'; + fprintf(stderr, "failed to log w/ fmt '%s'\n", fmt); + return; + } + } + + if (!rem_sz || ret > rem_sz) { + size_t new_sz = env.log_cap * 3 / 2; + char *new_buf; + + if (new_sz < 4096) + new_sz = 4096; + if (new_sz < ret + env.log_cnt) + new_sz = ret + env.log_cnt; + + /* +1 for guaranteed space for terminating \0 */ + new_buf = realloc(env.log_buf, new_sz + 1); + if (!new_buf) { + fprintf(stderr, "failed to realloc log buffer: %d\n", + errno); + return; + } + env.log_buf = new_buf; + env.log_cap = new_sz; + goto try_again; + } + + env.log_cnt += ret; +} + +void test__printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + test__vprintf(fmt, args); + va_end(args); +} struct ipv4_packet pkt_v4 = { .eth.h_proto = __bpf_constant_htons(ETH_P_IP), @@ -163,20 +239,15 @@ void *spin_lock_thread(void *arg) #include #undef DEFINE_TEST -struct prog_test_def { - const char *test_name; - int test_num; - void (*run_test)(void); -}; - static struct prog_test_def prog_test_defs[] = { -#define DEFINE_TEST(name) { \ - .test_name = #name, \ - .run_test = &test_##name, \ +#define DEFINE_TEST(name) { \ + .test_name = #name, \ + .run_test = &test_##name, \ }, #include #undef DEFINE_TEST }; +const int prog_test_cnt = ARRAY_SIZE(prog_test_defs); const char *argp_program_version = "test_progs 0.1"; const char *argp_program_bug_address = ""; @@ -186,7 +257,6 @@ enum ARG_KEYS { ARG_TEST_NUM = 'n', ARG_TEST_NAME = 't', ARG_VERIFIER_STATS = 's', - ARG_VERBOSE = 'v', }; @@ -202,24 +272,13 @@ static const struct argp_option opts[] = { {}, }; -struct test_env { - int test_num_selector; - const char *test_name_selector; - bool verifier_stats; - bool verbose; - bool very_verbose; -}; - -static struct test_env env = { - .test_num_selector = -1, -}; - static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { if (!env.very_verbose && level == LIBBPF_DEBUG) return 0; - return vfprintf(stderr, format, args); + test__vprintf(format, args); + return 0; } static error_t parse_arg(int key, char *arg, struct argp_state *state) @@ -267,7 +326,6 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) return 0; } - int main(int argc, char **argv) { static const struct argp argp = { @@ -275,7 +333,6 @@ int main(int argc, char **argv) .parser = parse_arg, .doc = argp_program_doc, }; - struct prog_test_def *test; int err, i; err = argp_parse(&argp, argc, argv, 0, NULL, &env); @@ -286,13 +343,14 @@ int main(int argc, char **argv) srand(time(NULL)); - jit_enabled = is_jit_enabled(); + env.jit_enabled = is_jit_enabled(); - verifier_stats = env.verifier_stats; - - for (i = 0; i < ARRAY_SIZE(prog_test_defs); i++) { - test = &prog_test_defs[i]; + for (i = 0; i < prog_test_cnt; i++) { + struct prog_test_def *test = &prog_test_defs[i]; + int old_pass_cnt = pass_cnt; + int old_error_cnt = error_cnt; + env.test = test; test->test_num = i + 1; if (env.test_num_selector >= 0 && @@ -303,8 +361,29 @@ int main(int argc, char **argv) continue; test->run_test(); + test->tested = true; + test->pass_cnt = pass_cnt - old_pass_cnt; + test->error_cnt = error_cnt - old_error_cnt; + if (test->error_cnt) + env.fail_cnt++; + else + env.succ_cnt++; + + if (env.verbose || test->force_log || test->error_cnt) { + if (env.log_cnt) { + fprintf(stdout, "%s", env.log_buf); + if (env.log_buf[env.log_cnt - 1] != '\n') + fprintf(stdout, "\n"); + } + } + env.log_cnt = 0; + + printf("#%d %s:%s\n", test->test_num, test->test_name, + test->error_cnt ? "FAIL" : "OK"); } + printf("Summary: %d PASSED, %d FAILED\n", env.succ_cnt, env.fail_cnt); + + free(env.log_buf); - printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 49e0f7d85643..62f55a4231e9 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -38,9 +38,33 @@ typedef __u16 __sum16; #include "trace_helpers.h" #include "flow_dissector_load.h" -extern int error_cnt, pass_cnt; -extern bool jit_enabled; -extern bool verifier_stats; +struct prog_test_def; + +struct test_env { + int test_num_selector; + const char *test_name_selector; + bool verifier_stats; + bool verbose; + bool very_verbose; + + bool jit_enabled; + + struct prog_test_def *test; + char *log_buf; + size_t log_cnt; + size_t log_cap; + + int succ_cnt; + int fail_cnt; +}; + +extern int error_cnt; +extern int pass_cnt; +extern struct test_env env; + +extern void test__printf(const char *fmt, ...); +extern void test__vprintf(const char *fmt, va_list args); +extern void test__force_log(); #define MAGIC_BYTES 123 @@ -64,11 +88,12 @@ extern struct ipv6_packet pkt_v6; int __ret = !!(condition); \ if (__ret) { \ error_cnt++; \ - printf("%s:FAIL:%s ", __func__, tag); \ - printf(format); \ + test__printf("%s:FAIL:%s ", __func__, tag); \ + test__printf(format); \ } else { \ pass_cnt++; \ - printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\ + test__printf("%s:PASS:%s %d nsec\n", \ + __func__, tag, duration); \ } \ __ret; \ }) -- GitLab From 3a516a0a3a7b21ec038db83ffb0d3cddc42514c9 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:29 -0700 Subject: [PATCH 0957/7155] selftests/bpf: add sub-tests support for test_progs Allow tests to have their own set of sub-tests. Also add ability to do test/subtest selection using `-t /` and `-n /`, as an extension of existing -t/-n selector options. For the format: it's a comma-separated list of either individual test numbers (1-based), or range of test numbers. E.g., all of the following are valid sets of test numbers: - 10 - 1,2,3 - 1-3 - 5-10,1,3-4 '/ Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_progs.c | 198 ++++++++++++++++++++--- tools/testing/selftests/bpf/test_progs.h | 16 +- 2 files changed, 185 insertions(+), 29 deletions(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 1b7470d3da22..546d99b3ec34 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -7,9 +7,7 @@ #include /* defined in test_progs.h */ -struct test_env env = { - .test_num_selector = -1, -}; +struct test_env env; int error_cnt, pass_cnt; struct prog_test_def { @@ -20,8 +18,82 @@ struct prog_test_def { int pass_cnt; int error_cnt; bool tested; + + const char *subtest_name; + int subtest_num; + + /* store counts before subtest started */ + int old_pass_cnt; + int old_error_cnt; }; +static bool should_run(struct test_selector *sel, int num, const char *name) +{ + if (sel->name && sel->name[0] && !strstr(name, sel->name)) + return false; + + if (!sel->num_set) + return true; + + return num < sel->num_set_len && sel->num_set[num]; +} + +static void dump_test_log(const struct prog_test_def *test, bool failed) +{ + if (env.verbose || test->force_log || failed) { + if (env.log_cnt) { + fprintf(stdout, "%s", env.log_buf); + if (env.log_buf[env.log_cnt - 1] != '\n') + fprintf(stdout, "\n"); + } + env.log_cnt = 0; + } +} + +void test__end_subtest() +{ + struct prog_test_def *test = env.test; + int sub_error_cnt = error_cnt - test->old_error_cnt; + + if (sub_error_cnt) + env.fail_cnt++; + else + env.sub_succ_cnt++; + + dump_test_log(test, sub_error_cnt); + + printf("#%d/%d %s:%s\n", + test->test_num, test->subtest_num, + test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); +} + +bool test__start_subtest(const char *name) +{ + struct prog_test_def *test = env.test; + + if (test->subtest_name) { + test__end_subtest(); + test->subtest_name = NULL; + } + + test->subtest_num++; + + if (!name || !name[0]) { + fprintf(stderr, "Subtest #%d didn't provide sub-test name!\n", + test->subtest_num); + return false; + } + + if (!should_run(&env.subtest_selector, test->subtest_num, name)) + return false; + + test->subtest_name = name; + env.test->old_pass_cnt = pass_cnt; + env.test->old_error_cnt = error_cnt; + + return true; +} + void test__force_log() { env.test->force_log = true; } @@ -281,24 +353,103 @@ static int libbpf_print_fn(enum libbpf_print_level level, return 0; } +int parse_num_list(const char *s, struct test_selector *sel) +{ + int i, set_len = 0, num, start = 0, end = -1; + bool *set = NULL, *tmp, parsing_end = false; + char *next; + + while (s[0]) { + errno = 0; + num = strtol(s, &next, 10); + if (errno) + return -errno; + + if (parsing_end) + end = num; + else + start = num; + + if (!parsing_end && *next == '-') { + s = next + 1; + parsing_end = true; + continue; + } else if (*next == ',') { + parsing_end = false; + s = next + 1; + end = num; + } else if (*next == '\0') { + parsing_end = false; + s = next; + end = num; + } else { + return -EINVAL; + } + + if (start > end) + return -EINVAL; + + if (end + 1 > set_len) { + set_len = end + 1; + tmp = realloc(set, set_len); + if (!tmp) { + free(set); + return -ENOMEM; + } + set = tmp; + } + for (i = start; i <= end; i++) { + set[i] = true; + } + + } + + if (!set) + return -EINVAL; + + sel->num_set = set; + sel->num_set_len = set_len; + + return 0; +} + static error_t parse_arg(int key, char *arg, struct argp_state *state) { struct test_env *env = state->input; switch (key) { case ARG_TEST_NUM: { - int test_num; + char *subtest_str = strchr(arg, '/'); - errno = 0; - test_num = strtol(arg, NULL, 10); - if (errno) - return -errno; - env->test_num_selector = test_num; + if (subtest_str) { + *subtest_str = '\0'; + if (parse_num_list(subtest_str + 1, + &env->subtest_selector)) { + fprintf(stderr, + "Failed to parse subtest numbers.\n"); + return -EINVAL; + } + } + if (parse_num_list(arg, &env->test_selector)) { + fprintf(stderr, "Failed to parse test numbers.\n"); + return -EINVAL; + } break; } - case ARG_TEST_NAME: - env->test_name_selector = arg; + case ARG_TEST_NAME: { + char *subtest_str = strchr(arg, '/'); + + if (subtest_str) { + *subtest_str = '\0'; + env->subtest_selector.name = strdup(subtest_str + 1); + if (!env->subtest_selector.name) + return -ENOMEM; + } + env->test_selector.name = strdup(arg); + if (!env->test_selector.name) + return -ENOMEM; break; + } case ARG_VERIFIER_STATS: env->verifier_stats = true; break; @@ -353,14 +504,15 @@ int main(int argc, char **argv) env.test = test; test->test_num = i + 1; - if (env.test_num_selector >= 0 && - test->test_num != env.test_num_selector) - continue; - if (env.test_name_selector && - !strstr(test->test_name, env.test_name_selector)) + if (!should_run(&env.test_selector, + test->test_num, test->test_name)) continue; test->run_test(); + /* ensure last sub-test is finalized properly */ + if (test->subtest_name) + test__end_subtest(); + test->tested = true; test->pass_cnt = pass_cnt - old_pass_cnt; test->error_cnt = error_cnt - old_error_cnt; @@ -369,21 +521,17 @@ int main(int argc, char **argv) else env.succ_cnt++; - if (env.verbose || test->force_log || test->error_cnt) { - if (env.log_cnt) { - fprintf(stdout, "%s", env.log_buf); - if (env.log_buf[env.log_cnt - 1] != '\n') - fprintf(stdout, "\n"); - } - } - env.log_cnt = 0; + dump_test_log(test, test->error_cnt); printf("#%d %s:%s\n", test->test_num, test->test_name, test->error_cnt ? "FAIL" : "OK"); } - printf("Summary: %d PASSED, %d FAILED\n", env.succ_cnt, env.fail_cnt); + printf("Summary: %d/%d PASSED, %d FAILED\n", + env.succ_cnt, env.sub_succ_cnt, env.fail_cnt); free(env.log_buf); + free(env.test_selector.num_set); + free(env.subtest_selector.num_set); return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 62f55a4231e9..afd14962456f 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -40,9 +40,15 @@ typedef __u16 __sum16; struct prog_test_def; +struct test_selector { + const char *name; + bool *num_set; + int num_set_len; +}; + struct test_env { - int test_num_selector; - const char *test_name_selector; + struct test_selector test_selector; + struct test_selector subtest_selector; bool verifier_stats; bool verbose; bool very_verbose; @@ -54,8 +60,9 @@ struct test_env { size_t log_cnt; size_t log_cap; - int succ_cnt; - int fail_cnt; + int succ_cnt; /* successful tests */ + int sub_succ_cnt; /* successful sub-tests */ + int fail_cnt; /* total failed tests + sub-tests */ }; extern int error_cnt; @@ -65,6 +72,7 @@ extern struct test_env env; extern void test__printf(const char *fmt, ...); extern void test__vprintf(const char *fmt, va_list args); extern void test__force_log(); +extern bool test__start_subtest(const char *name); #define MAGIC_BYTES 123 -- GitLab From 51436ed78d59d0a0b7e64a2a2b997ac66a6c050e Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:30 -0700 Subject: [PATCH 0958/7155] selftests/bpf: convert bpf_verif_scale.c to sub-tests API Expose each BPF verifier scale test as individual sub-test to allow independent results output and test selection. Test run results now look like this: $ sudo ./test_progs -t verif/ #3/1 loop3.o:OK #3/2 test_verif_scale1.o:OK #3/3 test_verif_scale2.o:OK #3/4 test_verif_scale3.o:OK #3/5 pyperf50.o:OK #3/6 pyperf100.o:OK #3/7 pyperf180.o:OK #3/8 pyperf600.o:OK #3/9 pyperf600_nounroll.o:OK #3/10 loop1.o:OK #3/11 loop2.o:OK #3/12 strobemeta.o:OK #3/13 strobemeta_nounroll1.o:OK #3/14 strobemeta_nounroll2.o:OK #3/15 test_sysctl_loop1.o:OK #3/16 test_sysctl_loop2.o:OK #3/17 test_xdp_loop.o:OK #3/18 test_seg6_loop.o:OK #3 bpf_verif_scale:OK Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- .../bpf/prog_tests/bpf_verif_scale.c | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index b59017279e0b..b4be96162ff4 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -33,14 +33,25 @@ static int check_load(const char *file, enum bpf_prog_type type) return err; } +struct scale_test_def { + const char *file; + enum bpf_prog_type attach_type; + bool fails; +}; + void test_bpf_verif_scale(void) { - const char *sched_cls[] = { - "./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o", - }; - const char *raw_tp[] = { + struct scale_test_def tests[] = { + { "loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT, true /* fails */ }, + + { "test_verif_scale1.o", BPF_PROG_TYPE_SCHED_CLS }, + { "test_verif_scale2.o", BPF_PROG_TYPE_SCHED_CLS }, + { "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS }, + /* full unroll by llvm */ - "./pyperf50.o", "./pyperf100.o", "./pyperf180.o", + { "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + { "pyperf100.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + { "pyperf180.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, /* partial unroll. llvm will unroll loop ~150 times. * C loop count -> 600. @@ -48,7 +59,7 @@ void test_bpf_verif_scale(void) * 16k insns in loop body. * Total of 5 such loops. Total program size ~82k insns. */ - "./pyperf600.o", + { "pyperf600.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, /* no unroll at all. * C loop count -> 600. @@ -56,22 +67,26 @@ void test_bpf_verif_scale(void) * ~110 insns in loop body. * Total of 5 such loops. Total program size ~1500 insns. */ - "./pyperf600_nounroll.o", + { "pyperf600_nounroll.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, - "./loop1.o", "./loop2.o", + { "loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + { "loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, /* partial unroll. 19k insn in a loop. * Total program size 20.8k insn. * ~350k processed_insns */ - "./strobemeta.o", + { "strobemeta.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, /* no unroll, tiny loops */ - "./strobemeta_nounroll1.o", - "./strobemeta_nounroll2.o", - }; - const char *cg_sysctl[] = { - "./test_sysctl_loop1.o", "./test_sysctl_loop2.o", + { "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + { "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + + { "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL }, + { "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL }, + + { "test_xdp_loop.o", BPF_PROG_TYPE_XDP }, + { "test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL }, }; libbpf_print_fn_t old_print_fn = NULL; int err, i; @@ -81,33 +96,21 @@ void test_bpf_verif_scale(void) old_print_fn = libbpf_set_print(libbpf_debug_print); } - err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT); - test__printf("test_scale:loop3:%s\n", - err ? (error_cnt--, "OK") : "FAIL"); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const struct scale_test_def *test = &tests[i]; - for (i = 0; i < ARRAY_SIZE(sched_cls); i++) { - err = check_load(sched_cls[i], BPF_PROG_TYPE_SCHED_CLS); - test__printf("test_scale:%s:%s\n", sched_cls[i], - err ? "FAIL" : "OK"); - } + if (!test__start_subtest(test->file)) + continue; - for (i = 0; i < ARRAY_SIZE(raw_tp); i++) { - err = check_load(raw_tp[i], BPF_PROG_TYPE_RAW_TRACEPOINT); - test__printf("test_scale:%s:%s\n", raw_tp[i], - err ? "FAIL" : "OK"); + err = check_load(test->file, test->attach_type); + if (test->fails) { /* expected to fail */ + if (err) + error_cnt--; + else + error_cnt++; + } } - for (i = 0; i < ARRAY_SIZE(cg_sysctl); i++) { - err = check_load(cg_sysctl[i], BPF_PROG_TYPE_CGROUP_SYSCTL); - test__printf("test_scale:%s:%s\n", cg_sysctl[i], - err ? "FAIL" : "OK"); - } - err = check_load("./test_xdp_loop.o", BPF_PROG_TYPE_XDP); - test__printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK"); - - err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL); - test__printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK"); - if (env.verifier_stats) libbpf_set_print(old_print_fn); } -- GitLab From b207edfe4e021f3d992ec8a277edee103840dfd9 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sat, 27 Jul 2019 20:25:31 -0700 Subject: [PATCH 0959/7155] selftests/bpf: convert send_signal.c to use subtests Convert send_signal set of tests to be exposed as three sub-tests. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/prog_tests/send_signal.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c index d950f4558897..461b423d0584 100644 --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c @@ -219,7 +219,10 @@ void test_send_signal(void) { int ret = 0; - ret |= test_send_signal_tracepoint(); - ret |= test_send_signal_perf(); - ret |= test_send_signal_nmi(); + if (test__start_subtest("send_signal_tracepoint")) + ret |= test_send_signal_tracepoint(); + if (test__start_subtest("send_signal_perf")) + ret |= test_send_signal_perf(); + if (test__start_subtest("send_signal_nmi")) + ret |= test_send_signal_nmi(); } -- GitLab From 06ae56b9e723d653b6c14da947794d440554dff4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 21 Feb 2019 18:02:47 +0100 Subject: [PATCH 0960/7155] iio: document bindings for mounting matrices The mounting matrix for sensors was introduced in commit dfc57732ad38 ("iio:core: mounting matrix support") However the device tree bindings are very terse and since this is a widely applicable property, we need a proper binding for it that the other bindings can reference. This will also be useful for other operating systems and sensor engineering at large. I think all 3D sensors should support it, the current situation is probably that the mounting information is confined in magic userspace components rather than using the mounting matrix, which is not good for portability and reuse. Cc: Linus Walleij Cc: Gregor Boirie Cc: Sebastian Reichel Cc: Samu Onkalo Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Signed-off-by: H. Nikolaus Schaller Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/mount-matrix.txt | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/mount-matrix.txt diff --git a/Documentation/devicetree/bindings/iio/mount-matrix.txt b/Documentation/devicetree/bindings/iio/mount-matrix.txt new file mode 100644 index 000000000000..c3344ab509a3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/mount-matrix.txt @@ -0,0 +1,203 @@ +For discussion. Unclear are: +* is the definition of +/- values practical or counterintuitive? +* are the definitions unambiguous and easy to follow? +* are the examples correct? +* should we have HOWTO engineer a correct matrix for a new device (without comparing to a different one)? + +==== + + +Mounting matrix + +The mounting matrix is a device tree property used to orient any device +that produce three-dimensional data in relation to the world where it is +deployed. + +The purpose of the mounting matrix is to translate the sensor frame of +reference into the device frame of reference using a translation matrix as +defined in linear algebra. + +The typical usecase is that where a component has an internal representation +of the (x,y,z) triplets, such as different registers to read these coordinates, +and thus implying that the component should be mounted in a certain orientation +relative to some specific device frame of reference. + +For example a device with some kind of screen, where the user is supposed to +interact with the environment using an accelerometer, gyroscope or magnetometer +mounted on the same chassis as this screen, will likely take the screen as +reference to (x,y,z) orientation, with (x,y) corresponding to these axes on the +screen and (z) being depth, the axis perpendicular to the screen. + +For a screen you probably want (x) coordinates to go from negative on the left +to positive on the right, (y) from negative on the bottom to positive on top +and (z) depth to be negative under the screen and positive in front of it, +toward the face of the user. + +A sensor can be mounted in any angle along the axes relative to the frame of +reference. This means that the sensor may be flipped upside-down, left-right, +or tilted at any angle relative to the frame of reference. + +Another frame of reference is how the device with its sensor relates to the +external world, the environment where the device is deployed. Usually the data +from the sensor is used to figure out how the device is oriented with respect +to this world. When using the mounting matrix, the sensor and device orientation +becomes identical and we can focus on the data as it relates to the surrounding +world. + +Device-to-world examples for some three-dimensional sensor types: + +- Accelerometers have their world frame of reference toward the center of + gravity, usually to the core of the planet. A reading of the (x,y,z) values + from the sensor will give a projection of the gravity vector through the + device relative to the center of the planet, i.e. relative to its surface at + this point. Up and down in the world relative to the device frame of + reference can thus be determined. and users would likely expect a value of + 9.81 m/s^2 upwards along the (z) axis, i.e. out of the screen when the device + is held with its screen flat on the planets surface and 0 on the other axes, + as the gravity vector is projected 1:1 onto the sensors (z)-axis. + + If you tilt the device, the g vector virtually coming out of the display + is projected onto the (x,y) plane of the display panel. + + Example: + + ^ z: +g ^ z: > 0 + ! /! + ! x=y=0 / ! x: > 0 + +--------+ +--------+ + ! ! ! ! + +--------+ +--------+ + ! / + ! / + v v + center of center of + gravity gravity + + + If the device is tilted to the left, you get a positive x value. If you point + its top towards surface, you get a negative y axis. + + (---------) + ! ! y: -g + ! ! ^ + ! ! ! + ! ! + ! ! x: +g <- z: +g -> x: -g + ! 1 2 3 ! + ! 4 5 6 ! ! + ! 7 8 9 ! v + ! * 0 # ! y: +g + (---------) + + +- Magnetometers (compasses) have their world frame of reference relative to the + geomagnetic field. The system orientation vis-a-vis the world is defined with + respect to the local earth geomagnetic reference frame where (y) is in the + ground plane and positive towards magnetic North, (x) is in the ground plane, + perpendicular to the North axis and positive towards the East and (z) is + perpendicular to the ground plane and positive upwards. + + + ^^^ North: y > 0 + + (---------) + ! ! + ! ! + ! ! + ! ! > + ! ! > North: x > 0 + ! 1 2 3 ! > + ! 4 5 6 ! + ! 7 8 9 ! + ! * 0 # ! + (---------) + + Since the geomagnetic field is not uniform this definition fails if we come + closer to the poles. + + Sensors and driver can not and should not take care of this because there + are complex calculations and empirical data to be taken care of. We leave + this up to user space. + + The definition we take: + + If the device is placed at the equator and the top is pointing north, the + display is readable by a person standing upright on the earth surface, this + defines a positive y value. + + +- Gyroscopes detects the movement relative the device itself. The angular + velocity is defined as orthogonal to the plane of rotation, so if you put the + device on a flat surface and spin it around the z axis (such as rotating a + device with a screen lying flat on a table), you should get a negative value + along the (z) axis if rotated clockwise, and a positive value if rotated + counter-clockwise according to the right-hand rule. + + + (---------) y > 0 + ! ! v---\ + ! ! + ! ! + ! ! <--\ + ! ! ! z > 0 + ! 1 2 3 ! --/ + ! 4 5 6 ! + ! 7 8 9 ! + ! * 0 # ! + (---------) + + +So unless the sensor is ideally mounted, we need a means to indicate the +relative orientation of any given sensor of this type with respect to the +frame of reference. + +To achieve this, use the device tree property "mount-matrix" for the sensor. + +This supplies a 3x3 rotation matrix in the strict linear algebraic sense, +to orient the senor axes relative to a desired point of reference. This means +the resulting values from the sensor, after scaling to proper units, should be +multiplied by this matrix to give the proper vectors values in three-dimensional +space, relative to the device or world point of reference. + +For more information, consult: +https://en.wikipedia.org/wiki/Rotation_matrix + +The mounting matrix has the layout: + + (mxx, myx, mzx) + (mxy, myy, mzy) + (mxz, myz, mzz) + +Values are intended to be multiplied as: + + x' = mxx * x + myx * y + mzx * z + y' = mxy * x + myy * y + mzy * z + z' = mxz * x + myz * y + mzz * z + +It is represented as an array of strings containing the real values for +producing the transformation matrix. + +Examples: + +Identity matrix (nothing happens to the coordinates, which means the device was +mechanically mounted in an ideal way and we need no transformation): + +mount-matrix = "1", "0", "0", + "0", "1", "0", + "0", "0", "1"; + +The sensor is mounted 30 degrees (Pi/6 radians) tilted along the X axis, so we +compensate by performing a -30 degrees rotation around the X axis: + +mount-matrix = "1", "0", "0", + "0", "0.866", "0.5", + "0", "-0.5", "0.866"; + +The sensor is flipped 180 degrees (Pi radians) around the Z axis, i.e. mounted +upside-down: + +mount-matrix = "0.998", "0.054", "0", + "-0.054", "0.998", "0", + "0", "0", "1"; + +???: this does not match "180 degrees" - factors indicate ca. 3 degrees compensation -- GitLab From 7677f73158d3dac530daca7ce834603989c05b18 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Thu, 18 Jul 2019 09:27:30 +0300 Subject: [PATCH 0961/7155] iio: adc: ad7606: Move common channel definition to header The common channel definition which are going to be used by both core file but also spi file, were moved in header file. Some devices have different channel definitions when are used in software mode, feature available only with spi, and those definitions will be added in spi file. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 23 ----------------------- drivers/iio/adc/ad7606.h | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index aba0fd123a51..a49dc106a21c 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -308,29 +308,6 @@ static const struct attribute_group ad7606_attribute_group_range = { .attrs = ad7606_attributes_range, }; -#define AD760X_CHANNEL(num, mask) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = mask, \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_CPU, \ - }, \ -} - -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, 0) - -#define AD7606_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) - static const struct iio_chan_spec ad7605_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), AD7605_CHANNEL(0), diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index d8a509c2c428..d547e88f4c9d 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -8,6 +8,29 @@ #ifndef IIO_ADC_AD7606_H_ #define IIO_ADC_AD7606_H_ +#define AD760X_CHANNEL(num, mask) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = mask, \ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define AD7605_CHANNEL(num) \ + AD760X_CHANNEL(num, 0) + +#define AD7606_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + /** * struct ad7606_chip_info - chip specific information * @channels: channel specification -- GitLab From a0c648c07ce50744d0f6ddb58b483e87907e9122 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Thu, 18 Jul 2019 09:27:31 +0300 Subject: [PATCH 0962/7155] iio: adc: ad7606: Move spi dependent features to spi file Because software mode and register access are only available in spi, they were moved in spi file and are accessbile via bops structure. The write_os/scale will be overwritten by sw_mode_config function. This patch was made in order to support devices in software mode without making the driver dependent to spi and increase the abstraction of the core. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 20 ++------------------ drivers/iio/adc/ad7606.h | 12 +++--------- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index a49dc106a21c..9eec3db01a17 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -597,7 +597,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; - if (st->chip_info->sw_mode_config) + if (st->bops->sw_mode_config) st->sw_mode_en = device_property_present(st->dev, "adi,sw-mode"); @@ -606,23 +606,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, memset32(st->range, 2, ARRAY_SIZE(st->range)); indio_dev->info = &ad7606_info_os_and_range; - /* - * In software mode, the range gpio has no longer its function. - * Instead, the scale can be configured individually for each - * channel from the range registers. - */ - if (st->chip_info->write_scale_sw) - st->write_scale = st->chip_info->write_scale_sw; - - /* - * In software mode, the oversampling is no longer configured - * with GPIO pins. Instead, the oversampling can be configured - * in configuratiion register. - */ - if (st->chip_info->write_os_sw) - st->write_os = st->chip_info->write_os_sw; - - ret = st->chip_info->sw_mode_config(indio_dev); + ret = st->bops->sw_mode_config(indio_dev); if (ret < 0) return ret; } diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index d547e88f4c9d..a6aac33aa33c 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -39,12 +39,6 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling - * @write_scale_sw pointer to the function which writes the scale via spi - in software mode - * @write_os_sw pointer to the function which writes the os via spi - in software mode - * @sw_mode_config: pointer to a function which configured the device - * for software mode */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -52,9 +46,6 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; - int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); - int (*write_os_sw)(struct iio_dev *indio_dev, int val); - int (*sw_mode_config)(struct iio_dev *indio_dev); }; /** @@ -124,10 +115,13 @@ struct ad7606_state { /** * struct ad7606_bus_ops - driver bus operations * @read_block function pointer for reading blocks of data + * @sw_mode_config: pointer to a function which configured the device + * for software mode */ struct ad7606_bus_ops { /* more methods added in future? */ int (*read_block)(struct device *dev, int num, void *data); + int (*sw_mode_config)(struct iio_dev *indio_dev); }; int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, -- GitLab From c5d93137af93c228392d133b3b00a0edae80dd40 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Thu, 18 Jul 2019 09:27:32 +0300 Subject: [PATCH 0963/7155] iio: adc: ad7606: Allow reconfigration after reset According to datasheet, ad7616 require at least 15ms after a restart to fully reconfigure and being able to receive new commands via spi. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 9eec3db01a17..a6034cf7238a 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -594,6 +594,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + /* AD7616 requires al least 15ms to reconfigure after a reset */ + if (msleep_interruptible(15)) + return -ERESTARTSYS; + st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; -- GitLab From f2a22e1e172f7dc486325216ec0890f301cb09e2 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Thu, 18 Jul 2019 09:27:33 +0300 Subject: [PATCH 0964/7155] iio: adc: ad7606: Add support for software mode for ad7616 Support for ad7616 running in software was added. In order to activate the software mode, HW_RNGSEL pins must be pulled low. Oversampling and input ranges are now configured in corresponding registers. Ad7616 has multiple scale options when it is configured in software mode. Also, in order to support multiple devices in software mode, the spi calculation of registers address must be generic. Because the length of address and bit which specifies the read/write operation is different for every device, calculation of address was made generic. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 9 ++ drivers/iio/adc/ad7606.h | 38 ++++++-- drivers/iio/adc/ad7606_spi.c | 175 ++++++++++++++++++++++++++++++++++- 3 files changed, 213 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index a6034cf7238a..be2330c8b277 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = { 152588, 305176 }; + +static const unsigned int ad7616_sw_scale_avail[3] = { + 76293, 152588, 305176 +}; + static const unsigned int ad7606_oversampling_avail[7] = { 1, 2, 4, 8, 16, 32, 64, }; @@ -606,6 +611,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, "adi,sw-mode"); if (st->sw_mode_en) { + /* Scale of 0.076293 is only available in sw mode */ + st->scale_avail = ad7616_sw_scale_avail; + st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); + /* After reset, in software mode, ±10 V is set by default */ memset32(st->range, 2, ARRAY_SIZE(st->range)); indio_dev->info = &ad7606_info_os_and_range; diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index a6aac33aa33c..eeaaa8b905db 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -8,14 +8,14 @@ #ifndef IIO_ADC_AD7606_H_ #define IIO_ADC_AD7606_H_ -#define AD760X_CHANNEL(num, mask) { \ +#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = num, \ .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = mask, \ + .info_mask_separate = mask_sep, \ + .info_mask_shared_by_type = mask_type, \ + .info_mask_shared_by_all = mask_all, \ .scan_index = num, \ .scan_type = { \ .sign = 's', \ @@ -25,11 +25,18 @@ }, \ } -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, 0) +#define AD7605_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), 0) -#define AD7606_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) +#define AD7606_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + +#define AD7616_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\ + 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) /** * struct ad7606_chip_info - chip specific information @@ -77,6 +84,7 @@ struct ad7606_chip_info { * @complete completion to indicate end of conversion * @trig The IIO trigger associated with the device. * @data buffer for reading data from the device + * @d16 be16 buffer for reading data from the device */ struct ad7606_state { struct device *dev; @@ -110,6 +118,7 @@ struct ad7606_state { * 16 * 16-bit samples + 64-bit timestamp */ unsigned short data[20] ____cacheline_aligned; + __be16 d16[2]; }; /** @@ -117,11 +126,24 @@ struct ad7606_state { * @read_block function pointer for reading blocks of data * @sw_mode_config: pointer to a function which configured the device * for software mode + * @reg_read function pointer for reading spi register + * @reg_write function pointer for writing spi register + * @write_mask function pointer for write spi register with mask + * @rd_wr_cmd pointer to the function which calculates the spi address */ struct ad7606_bus_ops { /* more methods added in future? */ int (*read_block)(struct device *dev, int num, void *data); int (*sw_mode_config)(struct iio_dev *indio_dev); + int (*reg_read)(struct ad7606_state *st, unsigned int addr); + int (*reg_write)(struct ad7606_state *st, + unsigned int addr, + unsigned int val); + int (*write_mask)(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val); + u16 (*rd_wr_cmd)(int addr, char isWriteOp); }; int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index b7faef69a58f..98ed52b74507 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -15,6 +15,51 @@ #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ +#define AD7616_CONFIGURATION_REGISTER 0x02 +#define AD7616_OS_MASK GENMASK(4, 2) +#define AD7616_BURST_MODE BIT(6) +#define AD7616_SEQEN_MODE BIT(5) +#define AD7616_RANGE_CH_A_ADDR_OFF 0x04 +#define AD7616_RANGE_CH_B_ADDR_OFF 0x06 +/* + * Range of channels from a group are stored in 2 registers. + * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register. + * For channels from second group(8-15) the order is the same, only with + * an offset of 2 for register address. + */ +#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) +/* The range of the channel is stored on 2 bits*/ +#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) +#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) +static const struct iio_chan_spec ad7616_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(16), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), + AD7616_CHANNEL(8), + AD7616_CHANNEL(9), + AD7616_CHANNEL(10), + AD7616_CHANNEL(11), + AD7616_CHANNEL(12), + AD7616_CHANNEL(13), + AD7616_CHANNEL(14), + AD7616_CHANNEL(15), +}; + +static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) +{ + /* + * The address of register consist of one w/r bit + * 6 bits of address followed by one reserved bit. + */ + return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); +} + static int ad7606_spi_read_block(struct device *dev, int count, void *buf) { @@ -35,17 +80,145 @@ static int ad7606_spi_read_block(struct device *dev, return 0; } +static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) +{ + struct spi_device *spi = to_spi_device(st->dev); + struct spi_transfer t[] = { + { + .tx_buf = &st->d16[0], + .len = 2, + .cs_change = 0, + }, { + .rx_buf = &st->d16[1], + .len = 2, + }, + }; + int ret; + + st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8); + + ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t)); + if (ret < 0) + return ret; + + return be16_to_cpu(st->d16[1]); +} + +static int ad7606_spi_reg_write(struct ad7606_state *st, + unsigned int addr, + unsigned int val) +{ + struct spi_device *spi = to_spi_device(st->dev); + + st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) | + (val & 0x1FF)); + + return spi_write(spi, &st->d16[0], sizeof(st->d16[0])); +} + +static int ad7606_spi_write_mask(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val) +{ + int readval; + + readval = st->bops->reg_read(st, addr); + if (readval < 0) + return readval; + + readval &= ~mask; + readval |= val; + + return st->bops->reg_write(st, addr, readval); +} + +static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned int ch_addr, mode, ch_index; + + + /* + * Ad7616 has 16 channels divided in group A and group B. + * The range of channels from A are stored in registers with address 4 + * while channels from B are stored in register with address 6. + * The last bit from channels determines if it is from group A or B + * because the order of channels in iio is 0A, 0B, 1A, 1B... + */ + ch_index = ch >> 1; + + ch_addr = AD7616_RANGE_CH_ADDR(ch_index); + + if ((ch & 0x1) == 0) /* channel A */ + ch_addr += AD7616_RANGE_CH_A_ADDR_OFF; + else /* channel B */ + ch_addr += AD7616_RANGE_CH_B_ADDR_OFF; + + /* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */ + mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11)); + return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index), + mode); +} + +static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER, + AD7616_OS_MASK, val << 2); +} + +static int ad7616_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7616_sw_channels; + + st->write_scale = ad7616_write_scale_sw; + st->write_os = &ad7616_write_os_sw; + + /* Activate Burst mode and SEQEN MODE */ + return st->bops->write_mask(st, + AD7616_CONFIGURATION_REGISTER, + AD7616_BURST_MODE | AD7616_SEQEN_MODE, + AD7616_BURST_MODE | AD7616_SEQEN_MODE); +} + static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; +static const struct ad7606_bus_ops ad7616_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7616_spi_rd_wr_cmd, + .sw_mode_config = ad7616_sw_mode_config, +}; + static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const struct ad7606_bus_ops *bops; + + switch (id->driver_data) { + case ID_AD7616: + bops = &ad7616_spi_bops; + break; + default: + bops = &ad7606_spi_bops; + break; + } return ad7606_probe(&spi->dev, spi->irq, NULL, id->name, id->driver_data, - &ad7606_spi_bops); + bops); } static const struct spi_device_id ad7606_id_table[] = { -- GitLab From a444fa597e2a130d2c56f1bfbe131c62625d7b55 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Thu, 18 Jul 2019 09:27:34 +0300 Subject: [PATCH 0965/7155] iio: adc: ad7606: Add debug mode for ad7616 Support for register access was added for devices which have software mode. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index be2330c8b277..ed2d08437e5d 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -60,6 +60,29 @@ static int ad7606_reset(struct ad7606_state *st) return -ENODEV; } +static int ad7606_reg_access(struct iio_dev *indio_dev, + unsigned int reg, + unsigned int writeval, + unsigned int *readval) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + if (readval) { + ret = st->bops->reg_read(st, reg); + if (ret < 0) + goto err_unlock; + *readval = ret; + ret = 0; + } else { + ret = st->bops->reg_write(st, reg, writeval); + } +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + static int ad7606_read_samples(struct ad7606_state *st) { unsigned int num = st->chip_info->num_channels; @@ -501,6 +524,14 @@ static const struct iio_info ad7606_info_os_and_range = { .validate_trigger = &ad7606_validate_trigger, }; +static const struct iio_info ad7606_info_os_range_and_debug = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .debugfs_reg_access = &ad7606_reg_access, + .attrs = &ad7606_attribute_group_os_and_range, + .validate_trigger = &ad7606_validate_trigger, +}; + static const struct iio_info ad7606_info_os = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, @@ -617,7 +648,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, /* After reset, in software mode, ±10 V is set by default */ memset32(st->range, 2, ARRAY_SIZE(st->range)); - indio_dev->info = &ad7606_info_os_and_range; + indio_dev->info = &ad7606_info_os_range_and_debug; ret = st->bops->sw_mode_config(indio_dev); if (ret < 0) -- GitLab From 2229a3618abdaac40c9e32754509357ed78c90f5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Jun 2019 11:34:18 +0200 Subject: [PATCH 0966/7155] unicore: Drop pointless include I can't see why this file includes , it is not using any of the interfaces. Lots of things are named "gpio" in the file but it is an irqchip driver and has nothing to do with the GPIO interfaces. Cc: Guan Xuetao Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190626093418.6263-1-linus.walleij@linaro.org --- arch/unicore32/kernel/irq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c index d1129828c41e..c014ae3c3e48 100644 --- a/arch/unicore32/kernel/irq.c +++ b/arch/unicore32/kernel/irq.c @@ -21,7 +21,6 @@ #include #include #include -#include #include -- GitLab From cbf2be749076c266f51cafc71dc9045bcad9ed05 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 28 Jun 2019 17:14:19 +0100 Subject: [PATCH 0967/7155] gpio: bd70528: fix spelling misstake "debouce" -> "debounce" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190628161419.26439-1-colin.king@canonical.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bd70528.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c index fd85605d2dab..633422b430b4 100644 --- a/drivers/gpio/gpio-bd70528.c +++ b/drivers/gpio/gpio-bd70528.c @@ -36,7 +36,7 @@ static int bd70528_set_debounce(struct bd70528_gpio *bdgpio, break; default: dev_err(bdgpio->chip.dev, - "Invalid debouce value %u\n", debounce); + "Invalid debounce value %u\n", debounce); return -EINVAL; } return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset), -- GitLab From f8650b8ff6fd96075391e72bb3b6d0a99f27829d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 29 Jun 2019 13:33:06 +0100 Subject: [PATCH 0968/7155] gpio: bd70528: remove redundant assignment to variable ret Variable ret is being initialized with a value that is never read and ret is being re-assigned a little later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190629123306.12519-1-colin.king@canonical.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bd70528.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c index 633422b430b4..0c1ead12d883 100644 --- a/drivers/gpio/gpio-bd70528.c +++ b/drivers/gpio/gpio-bd70528.c @@ -153,7 +153,7 @@ static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset) static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset) { - int ret = -EINVAL; + int ret; struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); /* -- GitLab From 9e4d5c1be21f0c00e747e92186784f3298309b3e Mon Sep 17 00:00:00 2001 From: "Geoffrey D. Bennett" Date: Mon, 29 Jul 2019 00:42:45 +0930 Subject: [PATCH 0969/7155] ALSA: usb-audio: Scarlett Gen 2 mixer interface Add mixer quirk for the Focusrite Scarlett 6i6, 18i8, and 18i20 Gen 2 audio interfaces. Although the interfaces are USB compliant, additional input/output level controls and hardware routing/mixing functionality are available using proprietary USB requests. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai --- sound/usb/Makefile | 1 + sound/usb/mixer.c | 4 + sound/usb/mixer.h | 4 + sound/usb/mixer_quirks.c | 7 + sound/usb/mixer_scarlett_gen2.c | 2075 +++++++++++++++++++++++++++++++ sound/usb/mixer_scarlett_gen2.h | 7 + 6 files changed, 2098 insertions(+) create mode 100644 sound/usb/mixer_scarlett_gen2.c create mode 100644 sound/usb/mixer_scarlett_gen2.h diff --git a/sound/usb/Makefile b/sound/usb/Makefile index e1ce257ab705..f4b7384caa9d 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -11,6 +11,7 @@ snd-usb-audio-objs := card.o \ mixer.o \ mixer_quirks.o \ mixer_scarlett.o \ + mixer_scarlett_gen2.o \ mixer_us16x08.o \ pcm.o \ power.o \ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 7498b5191b68..7b51ab4c35b0 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3509,6 +3509,8 @@ void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) usb_kill_urb(mixer->urb); if (mixer->rc_urb) usb_kill_urb(mixer->rc_urb); + if (mixer->private_free) + mixer->private_free(mixer); mixer->disconnected = true; } @@ -3536,6 +3538,8 @@ static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) { snd_usb_mixer_inactivate(mixer); + if (mixer->private_suspend) + mixer->private_suspend(mixer); return 0; } diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 394cd9107507..37e1b234c802 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -28,6 +28,10 @@ struct usb_mixer_interface { struct media_mixer_ctl *media_mixer_ctl; bool disconnected; + + void *private_data; + void (*private_free)(struct usb_mixer_interface *mixer); + void (*private_suspend)(struct usb_mixer_interface *mixer); }; #define MAX_CHANNELS 16 /* max logical channels */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 199fa157a411..70805c15b0b5 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -32,6 +32,7 @@ #include "mixer.h" #include "mixer_quirks.h" #include "mixer_scarlett.h" +#include "mixer_scarlett_gen2.h" #include "mixer_us16x08.h" #include "helper.h" @@ -2258,6 +2259,12 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) err = snd_scarlett_controls_create(mixer); break; + case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ + case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ + case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ + err = snd_scarlett_gen2_controls_create(mixer); + break; + case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ err = snd_soundblaster_e1_switch_create(mixer); break; diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c new file mode 100644 index 000000000000..7d460b1f1735 --- /dev/null +++ b/sound/usb/mixer_scarlett_gen2.c @@ -0,0 +1,2075 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Focusrite Scarlett 6i6/18i8/18i20 Gen 2 Driver for ALSA + * + * Copyright (c) 2018-2019 by Geoffrey D. Bennett + * + * Based on the Scarlett (Gen 1) Driver for ALSA: + * + * Copyright (c) 2013 by Tobias Hoffmann + * Copyright (c) 2013 by Robin Gareus + * Copyright (c) 2002 by Takashi Iwai + * Copyright (c) 2014 by Chris J Arges + * + * Many codes borrowed from audio.c by + * Alan Cox (alan at lxorguk.ukuu.org.uk) + * Thomas Sailer (sailer at ife.ee.ethz.ch) + * + * Code cleanup: + * David Henningsson + */ + +/* Mixer Interface for the Focusrite Scarlett 6i6/18i8/18i20 Gen 2 audio + * interface. Based on the Gen 1 driver and rewritten. + */ + +/* The protocol was reverse engineered by looking at the communication + * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20 + * (firmware 1083) using usbmon in July-August 2018. + * + * Scarlett 18i8 support added in April 2019. + * + * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann + * for providing usbmon output and testing). + * + * This ALSA mixer gives access to: + * - input, output, mixer-matrix muxes + * - 18x10 mixer-matrix gain stages + * - gain/volume controls + * - level meters + * - line/inst level and pad controls + * + * + * /--------------\ 18chn 20chn /--------------\ + * | Hardware in +--+------\ /-------------+--+ ALSA PCM out | + * \--------------/ | | | | \--------------/ + * | | | /-----\ | + * | | | | | | + * | v v v | | + * | +---------------+ | | + * | \ Matrix Mux / | | + * | +-----+-----+ | | + * | | | | + * | |18chn | | + * | | | | + * | | 10chn| | + * | v | | + * | +------------+ | | + * | | Mixer | | | + * | | Matrix | | | + * | | | | | + * | | 18x10 Gain | | | + * | | stages | | | + * | +-----+------+ | | + * | | | | + * |18chn |10chn | |20chn + * | | | | + * | +----------/ | + * | | | + * v v v + * =========================== + * +---------------+ +--—------------+ + * \ Output Mux / \ Capture Mux / + * +---+---+---+ +-----+-----+ + * | | | + * 10chn| | |18chn + * | | | + * /--------------\ | | | /--------------\ + * | S/PDIF, ADAT |<--/ |10chn \-->| ALSA PCM in | + * | Hardware out | | \--------------/ + * \--------------/ | + * v + * +-------------+ Software gain per channel. + * | Master Gain |<-- 18i20 only: Switch per channel + * +------+------+ to select HW or SW gain control. + * | + * |10chn + * /--------------\ | + * | Analogue |<------/ + * | Hardware out | + * \--------------/ + * + * + */ + +#include +#include +#include + +#include +#include + +#include "usbaudio.h" +#include "mixer.h" +#include "helper.h" + +#include "mixer_scarlett_gen2.h" + +/* device_setup value to enable */ +#define SCARLETT2_ENABLE 0x01 + +/* some gui mixers can't handle negative ctl values */ +#define SCARLETT2_VOLUME_BIAS 127 + +/* mixer range from -80dB to +6dB in 0.5dB steps */ +#define SCARLETT2_MIXER_MIN_DB -80 +#define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2) +#define SCARLETT2_MIXER_MAX_DB 6 +#define SCARLETT2_MIXER_MAX_VALUE \ + ((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2) + +/* map from (dB + 80) * 2 to mixer value + * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20))) + */ +static const u16 scarlett2_mixer_values[173] = { + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 23, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, 48, 51, + 54, 57, 61, 65, 68, 73, 77, 81, 86, 91, 97, 103, 109, 115, + 122, 129, 137, 145, 154, 163, 173, 183, 194, 205, 217, 230, + 244, 259, 274, 290, 307, 326, 345, 365, 387, 410, 434, 460, + 487, 516, 547, 579, 614, 650, 689, 730, 773, 819, 867, 919, + 973, 1031, 1092, 1157, 1225, 1298, 1375, 1456, 1543, 1634, + 1731, 1833, 1942, 2057, 2179, 2308, 2445, 2590, 2744, 2906, + 3078, 3261, 3454, 3659, 3876, 4105, 4349, 4606, 4879, 5168, + 5475, 5799, 6143, 6507, 6892, 7301, 7733, 8192, 8677, 9191, + 9736, 10313, 10924, 11571, 12257, 12983, 13752, 14567, 15430, + 16345 +}; + +/* Maximum number of analogue outputs */ +#define SCARLETT2_ANALOGUE_MAX 10 + +/* Maximum number of level and pad switches */ +#define SCARLETT2_LEVEL_SWITCH_MAX 2 +#define SCARLETT2_PAD_SWITCH_MAX 4 + +/* Maximum number of inputs to the mixer */ +#define SCARLETT2_INPUT_MIX_MAX 18 + +/* Maximum number of outputs from the mixer */ +#define SCARLETT2_OUTPUT_MIX_MAX 10 + +/* Maximum size of the data in the USB mux assignment message: + * 18 inputs, 20 outputs, 18 matrix inputs, 8 spare + */ +#define SCARLETT2_MUX_MAX 64 + +/* Number of meters: + * 18 inputs, 20 outputs, 18 matrix inputs + */ +#define SCARLETT2_NUM_METERS 56 + +/* Hardware port types: + * - None (no input to mux) + * - Analogue I/O + * - S/PDIF I/O + * - ADAT I/O + * - Mixer I/O + * - PCM I/O + */ +enum { + SCARLETT2_PORT_TYPE_NONE = 0, + SCARLETT2_PORT_TYPE_ANALOGUE = 1, + SCARLETT2_PORT_TYPE_SPDIF = 2, + SCARLETT2_PORT_TYPE_ADAT = 3, + SCARLETT2_PORT_TYPE_MIX = 4, + SCARLETT2_PORT_TYPE_PCM = 5, + SCARLETT2_PORT_TYPE_COUNT = 6, +}; + +/* Count of total I/O and number available at each sample rate */ +enum { + SCARLETT2_PORT_IN = 0, + SCARLETT2_PORT_OUT = 1, + SCARLETT2_PORT_OUT_44 = 2, + SCARLETT2_PORT_OUT_88 = 3, + SCARLETT2_PORT_OUT_176 = 4, + SCARLETT2_PORT_DIRECTIONS = 5, +}; + +/* Hardware buttons on the 18i20 */ +#define SCARLETT2_BUTTON_MAX 2 + +static const char *const scarlett2_button_names[SCARLETT2_BUTTON_MAX] = { + "Mute", "Dim" +}; + +/* Description of each hardware port type: + * - id: hardware ID for this port type + * - num: number of sources/destinations of this port type + * - src_descr: printf format string for mux input selections + * - src_num_offset: added to channel number for the fprintf + * - dst_descr: printf format string for mixer controls + */ +struct scarlett2_ports { + u16 id; + int num[SCARLETT2_PORT_DIRECTIONS]; + const char * const src_descr; + int src_num_offset; + const char * const dst_descr; +}; + +struct scarlett2_device_info { + u8 line_out_hw_vol; /* line out hw volume is sw controlled */ + u8 button_count; /* number of buttons */ + u8 level_input_count; /* inputs with level selectable */ + u8 pad_input_count; /* inputs with pad selectable */ + const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; + struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; +}; + +struct scarlett2_mixer_data { + struct usb_mixer_interface *mixer; + struct mutex usb_mutex; /* prevent sending concurrent USB requests */ + struct mutex data_mutex; /* lock access to this data */ + struct delayed_work work; + const struct scarlett2_device_info *info; + int num_mux_srcs; + u16 scarlett2_seq; + u8 vol_updated; + u8 master_vol; + u8 vol[SCARLETT2_ANALOGUE_MAX]; + u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; + u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; + u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; + u8 buttons[SCARLETT2_BUTTON_MAX]; + struct snd_kcontrol *master_vol_ctl; + struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; + struct snd_kcontrol *button_ctls[SCARLETT2_BUTTON_MAX]; + u8 mux[SCARLETT2_MUX_MAX]; + u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; +}; + +/*** Model-specific data ***/ + +static const struct scarlett2_device_info s6i6_gen2_info = { + /* The first two analogue inputs can be switched between line + * and instrument levels. + */ + .level_input_count = 2, + + /* The first two analogue inputs have an optional pad. */ + .pad_input_count = 2, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Headphones L", + "Headphones R", + }, + + .ports = { + { + .id = 0x000, + .num = { 1, 0, 8, 8, 8 }, + .src_descr = "Off", + .src_num_offset = 0, + }, + { + .id = 0x080, + .num = { 4, 4, 4, 4, 4 }, + .src_descr = "Analogue %d", + .src_num_offset = 1, + .dst_descr = "Analogue Output %02d Playback" + }, + { + .id = 0x180, + .num = { 2, 2, 2, 2, 2 }, + .src_descr = "S/PDIF %d", + .src_num_offset = 1, + .dst_descr = "S/PDIF Output %d Playback" + }, + { + .id = 0x300, + .num = { 10, 18, 18, 18, 18 }, + .src_descr = "Mix %c", + .src_num_offset = 65, + .dst_descr = "Mixer Input %02d Capture" + }, + { + .id = 0x600, + .num = { 6, 6, 6, 6, 6 }, + .src_descr = "PCM %d", + .src_num_offset = 1, + .dst_descr = "PCM %02d Capture" + }, + }, +}; + +static const struct scarlett2_device_info s18i8_gen2_info = { + /* The first two analogue inputs can be switched between line + * and instrument levels. + */ + .level_input_count = 2, + + /* The first four analogue inputs have an optional pad. */ + .pad_input_count = 4, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .ports = { + { + .id = 0x000, + .num = { 1, 0, 8, 8, 4 }, + .src_descr = "Off", + .src_num_offset = 0, + }, + { + .id = 0x080, + .num = { 8, 6, 6, 6, 6 }, + .src_descr = "Analogue %d", + .src_num_offset = 1, + .dst_descr = "Analogue Output %02d Playback" + }, + { + /* S/PDIF outputs aren't available at 192KHz + * but are included in the USB mux I/O + * assignment message anyway + */ + .id = 0x180, + .num = { 2, 2, 2, 2, 2 }, + .src_descr = "S/PDIF %d", + .src_num_offset = 1, + .dst_descr = "S/PDIF Output %d Playback" + }, + { + .id = 0x200, + .num = { 8, 0, 0, 0, 0 }, + .src_descr = "ADAT %d", + .src_num_offset = 1, + }, + { + .id = 0x300, + .num = { 10, 18, 18, 18, 18 }, + .src_descr = "Mix %c", + .src_num_offset = 65, + .dst_descr = "Mixer Input %02d Capture" + }, + { + .id = 0x600, + .num = { 20, 18, 18, 14, 10 }, + .src_descr = "PCM %d", + .src_num_offset = 1, + .dst_descr = "PCM %02d Capture" + }, + }, +}; + +static const struct scarlett2_device_info s18i20_gen2_info = { + /* The analogue line outputs on the 18i20 can be switched + * between software and hardware volume control + */ + .line_out_hw_vol = 1, + + /* Mute and dim buttons */ + .button_count = 2, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + NULL, + NULL, + NULL, + NULL, + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .ports = { + { + .id = 0x000, + .num = { 1, 0, 8, 8, 6 }, + .src_descr = "Off", + .src_num_offset = 0, + }, + { + .id = 0x080, + .num = { 8, 10, 10, 10, 10 }, + .src_descr = "Analogue %d", + .src_num_offset = 1, + .dst_descr = "Analogue Output %02d Playback" + }, + { + /* S/PDIF outputs aren't available at 192KHz + * but are included in the USB mux I/O + * assignment message anyway + */ + .id = 0x180, + .num = { 2, 2, 2, 2, 2 }, + .src_descr = "S/PDIF %d", + .src_num_offset = 1, + .dst_descr = "S/PDIF Output %d Playback" + }, + { + .id = 0x200, + .num = { 8, 8, 8, 4, 0 }, + .src_descr = "ADAT %d", + .src_num_offset = 1, + .dst_descr = "ADAT Output %d Playback" + }, + { + .id = 0x300, + .num = { 10, 18, 18, 18, 18 }, + .src_descr = "Mix %c", + .src_num_offset = 65, + .dst_descr = "Mixer Input %02d Capture" + }, + { + .id = 0x600, + .num = { 20, 18, 18, 14, 10 }, + .src_descr = "PCM %d", + .src_num_offset = 1, + .dst_descr = "PCM %02d Capture" + }, + }, +}; + +/* get the starting port index number for a given port type/direction */ +static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, + int direction, int port_type) +{ + int i, num = 0; + + for (i = 0; i < port_type; i++) + num += ports[i].num[direction]; + + return num; +} + +/*** USB Interactions ***/ + +/* Vendor-Specific Interface, Endpoint, MaxPacketSize, Interval */ +#define SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE 5 +#define SCARLETT2_USB_INTERRUPT_ENDPOINT 4 +#define SCARLETT2_USB_INTERRUPT_MAX_DATA 64 +#define SCARLETT2_USB_INTERRUPT_INTERVAL 3 + +/* Interrupt flags for volume and mute/dim button changes */ +#define SCARLETT2_USB_INTERRUPT_VOL_CHANGE 0x400000 +#define SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE 0x200000 + +/* Commands for sending/receiving requests/responses */ +#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ 2 +#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP 3 + +#define SCARLETT2_USB_INIT_SEQ 0x00000000 +#define SCARLETT2_USB_GET_METER_LEVELS 0x00001001 +#define SCARLETT2_USB_SET_MIX 0x00002002 +#define SCARLETT2_USB_SET_MUX 0x00003002 +#define SCARLETT2_USB_GET_DATA 0x00800000 +#define SCARLETT2_USB_SET_DATA 0x00800001 +#define SCARLETT2_USB_DATA_CMD 0x00800002 +#define SCARLETT2_USB_CONFIG_SAVE 6 + +#define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31 +#define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1 + +/* volume status is read together (matches scarlett2_config_items[]) */ +struct scarlett2_usb_volume_status { + /* mute & dim buttons */ + u8 buttons[SCARLETT2_BUTTON_MAX]; + + u8 pad1; + + /* software volume setting */ + s16 sw_vol[SCARLETT2_ANALOGUE_MAX]; + + /* actual volume of output inc. dim (-18dB) */ + s16 hw_vol[SCARLETT2_ANALOGUE_MAX]; + + u8 pad2[SCARLETT2_ANALOGUE_MAX]; + + /* sw (0) or hw (1) controlled */ + u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; + + u8 pad3[6]; + + /* front panel volume knob */ + s16 master_vol; +} __packed; + +/* Configuration parameters that can be read and written */ +enum { + SCARLETT2_CONFIG_BUTTONS = 0, + SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1, + SCARLETT2_CONFIG_SW_HW_SWITCH = 2, + SCARLETT2_CONFIG_LEVEL_SWITCH = 3, + SCARLETT2_CONFIG_PAD_SWITCH = 4, + SCARLETT2_CONFIG_COUNT = 5 +}; + +/* Location, size, and activation command number for the configuration + * parameters + */ +struct scarlett2_config { + u8 offset; + u8 size; + u8 activate; +}; + +static const struct scarlett2_config + scarlett2_config_items[SCARLETT2_CONFIG_COUNT] = { + /* Mute/Dim Buttons */ + { + .offset = 0x31, + .size = 1, + .activate = 2 + }, + + /* Line Out Volume */ + { + .offset = 0x34, + .size = 2, + .activate = 1 + }, + + /* SW/HW Volume Switch */ + { + .offset = 0x66, + .size = 1, + .activate = 3 + }, + + /* Level Switch */ + { + .offset = 0x7c, + .size = 1, + .activate = 7 + }, + + /* Pad Switch */ + { + .offset = 0x84, + .size = 1, + .activate = 8 + } +}; + +/* proprietary request/response format */ +struct scarlett2_usb_packet { + u32 cmd; + u16 size; + u16 seq; + u32 error; + u32 pad; + u8 data[]; +}; + +#define SCARLETT2_USB_PACKET_LEN (sizeof(struct scarlett2_usb_packet)) + +static void scarlett2_fill_request_header(struct scarlett2_mixer_data *private, + struct scarlett2_usb_packet *req, + u32 cmd, u16 req_size) +{ + /* sequence must go up by 1 for each request */ + u16 seq = private->scarlett2_seq++; + + req->cmd = cpu_to_le32(cmd); + req->size = cpu_to_le16(req_size); + req->seq = cpu_to_le16(seq); + req->error = 0; + req->pad = 0; +} + +/* Send a proprietary format request to the Scarlett interface */ +static int scarlett2_usb( + struct usb_mixer_interface *mixer, u32 cmd, + void *req_data, u16 req_size, void *resp_data, u16 resp_size) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + u16 req_buf_size = sizeof(struct scarlett2_usb_packet) + req_size; + u16 resp_buf_size = sizeof(struct scarlett2_usb_packet) + resp_size; + struct scarlett2_usb_packet *req = NULL, *resp = NULL; + int err = 0; + + req = kmalloc(req_buf_size, GFP_KERNEL); + if (!req) { + err = -ENOMEM; + goto error; + } + + resp = kmalloc(resp_buf_size, GFP_KERNEL); + if (!resp) { + err = -ENOMEM; + goto error; + } + + mutex_lock(&private->usb_mutex); + + /* build request message and send it */ + + scarlett2_fill_request_header(private, req, cmd, req_size); + + if (req_size) + memcpy(req->data, req_data, req_size); + + err = snd_usb_ctl_msg(mixer->chip->dev, + usb_sndctrlpipe(mixer->chip->dev, 0), + SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + 0, + SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, + req, + req_buf_size); + + if (err != req_buf_size) { + usb_audio_err( + mixer->chip, + "Scarlett Gen 2 USB request result cmd %x was %d\n", + cmd, err); + err = -EINVAL; + goto unlock; + } + + /* send a second message to get the response */ + + err = snd_usb_ctl_msg(mixer->chip->dev, + usb_sndctrlpipe(mixer->chip->dev, 0), + SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + 0, + SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, + resp, + resp_buf_size); + + /* validate the response */ + + if (err != resp_buf_size) { + usb_audio_err( + mixer->chip, + "Scarlett Gen 2 USB response result cmd %x was %d\n", + cmd, err); + err = -EINVAL; + goto unlock; + } + + if (resp->cmd != req->cmd || + resp->seq != req->seq || + resp_size != le16_to_cpu(resp->size) || + resp->error || + resp->pad) { + usb_audio_err( + mixer->chip, + "Scarlett Gen 2 USB invalid response; " + "cmd tx/rx %d/%d seq %d/%d size %d/%d " + "error %d pad %d\n", + le16_to_cpu(req->cmd), le16_to_cpu(resp->cmd), + le16_to_cpu(req->seq), le16_to_cpu(resp->seq), + resp_size, le16_to_cpu(resp->size), + le16_to_cpu(resp->error), + le16_to_cpu(resp->pad)); + err = -EINVAL; + goto unlock; + } + + if (resp_size > 0) + memcpy(resp_data, resp->data, resp_size); + +unlock: + mutex_unlock(&private->usb_mutex); +error: + kfree(req); + kfree(resp); + return err; +} + +/* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ +static void scarlett2_config_save(struct usb_mixer_interface *mixer) +{ + u32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE); + + scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, + &req, sizeof(u32), + NULL, 0); +} + +/* Delayed work to save config */ +static void scarlett2_config_save_work(struct work_struct *work) +{ + struct scarlett2_mixer_data *private = + container_of(work, struct scarlett2_mixer_data, work.work); + + scarlett2_config_save(private->mixer); +} + +/* Send a USB message to set a configuration parameter (volume level, + * sw/hw volume switch, line/inst level switch, or pad switch) + */ +static int scarlett2_usb_set_config( + struct usb_mixer_interface *mixer, + int config_item_num, int index, int value) +{ + const struct scarlett2_config config_item = + scarlett2_config_items[config_item_num]; + struct { + u32 offset; + u32 bytes; + s32 value; + } __packed req; + u32 req2; + int err; + struct scarlett2_mixer_data *private = mixer->private_data; + + /* Cancel any pending NVRAM save */ + cancel_delayed_work_sync(&private->work); + + /* Send the configuration parameter data */ + req.offset = cpu_to_le32(config_item.offset + index * config_item.size); + req.bytes = cpu_to_le32(config_item.size); + req.value = cpu_to_le32(value); + err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA, + &req, sizeof(u32) * 2 + config_item.size, + NULL, 0); + if (err < 0) + return err; + + /* Activate the change */ + req2 = cpu_to_le32(config_item.activate); + err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, + &req2, sizeof(req2), NULL, 0); + if (err < 0) + return err; + + /* Schedule the change to be written to NVRAM */ + schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); + + return 0; +} + +/* Send a USB message to get data; result placed in *buf */ +static int scarlett2_usb_get( + struct usb_mixer_interface *mixer, + int offset, void *buf, int size) +{ + struct { + u32 offset; + u32 size; + } __packed req; + + req.offset = cpu_to_le32(offset); + req.size = cpu_to_le32(size); + return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, + &req, sizeof(req), buf, size); +} + +/* Send a USB message to get configuration parameters; result placed in *buf */ +static int scarlett2_usb_get_config( + struct usb_mixer_interface *mixer, + int config_item_num, int count, void *buf) +{ + const struct scarlett2_config config_item = + scarlett2_config_items[config_item_num]; + int size = config_item.size * count; + + return scarlett2_usb_get(mixer, config_item.offset, buf, size); +} + +/* Send a USB message to get volume status; result placed in *buf */ +static int scarlett2_usb_get_volume_status( + struct usb_mixer_interface *mixer, + struct scarlett2_usb_volume_status *buf) +{ + return scarlett2_usb_get(mixer, SCARLETT2_USB_VOLUME_STATUS_OFFSET, + buf, sizeof(*buf)); +} + +/* Send a USB message to set the volumes for all inputs of one mix + * (values obtained from private->mix[]) + */ +static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, + int mix_num) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + struct { + u16 mix_num; + u16 data[SCARLETT2_INPUT_MIX_MAX]; + } __packed req; + + int i, j; + int num_mixer_in = + info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + + req.mix_num = cpu_to_le16(mix_num); + + for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) + req.data[i] = cpu_to_le16( + scarlett2_mixer_values[private->mix[j]] + ); + + return scarlett2_usb(mixer, SCARLETT2_USB_SET_MIX, + &req, (num_mixer_in + 1) * sizeof(u16), + NULL, 0); +} + +/* Convert a port number index (per info->ports) to a hardware ID */ +static u32 scarlett2_mux_src_num_to_id(const struct scarlett2_ports *ports, + int num) +{ + int port_type; + + for (port_type = 0; + port_type < SCARLETT2_PORT_TYPE_COUNT; + port_type++) { + if (num < ports[port_type].num[SCARLETT2_PORT_IN]) + return ports[port_type].id | num; + num -= ports[port_type].num[SCARLETT2_PORT_IN]; + } + + /* Oops */ + return 0; +} + +/* Send USB messages to set mux inputs */ +static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int rate, port_dir_rate; + + static const int assignment_order[SCARLETT2_PORT_TYPE_COUNT] = { + SCARLETT2_PORT_TYPE_PCM, + SCARLETT2_PORT_TYPE_ANALOGUE, + SCARLETT2_PORT_TYPE_SPDIF, + SCARLETT2_PORT_TYPE_ADAT, + SCARLETT2_PORT_TYPE_MIX, + SCARLETT2_PORT_TYPE_NONE, + }; + + struct { + u16 pad; + u16 num; + u32 data[SCARLETT2_MUX_MAX]; + } __packed req; + + req.pad = 0; + + /* mux settings for each rate */ + for (rate = 0, port_dir_rate = SCARLETT2_PORT_OUT_44; + port_dir_rate <= SCARLETT2_PORT_OUT_176; + rate++, port_dir_rate++) { + int order_num, i, err; + + req.num = cpu_to_le16(rate); + + for (order_num = 0, i = 0; + order_num < SCARLETT2_PORT_TYPE_COUNT; + order_num++) { + int port_type = assignment_order[order_num]; + int j = scarlett2_get_port_start_num(ports, + SCARLETT2_PORT_OUT, + port_type); + int port_id = ports[port_type].id; + int channel; + + for (channel = 0; + channel < ports[port_type].num[port_dir_rate]; + channel++, i++, j++) + /* lower 12 bits for the destination and + * next 12 bits for the source + */ + req.data[i] = !port_id + ? 0 + : cpu_to_le32( + port_id | + channel | + scarlett2_mux_src_num_to_id( + ports, private->mux[j] + ) << 12 + ); + + /* skip private->mux[j] entries not output */ + j += ports[port_type].num[SCARLETT2_PORT_OUT] - + ports[port_type].num[port_dir_rate]; + } + + err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX, + &req, (i + 1) * sizeof(u32), + NULL, 0); + if (err < 0) + return err; + } + + return 0; +} + +/* Send USB message to get meter levels */ +static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer, + u16 *levels) +{ + struct { + u16 pad; + u16 num_meters; + u32 magic; + } __packed req; + u32 resp[SCARLETT2_NUM_METERS]; + int i, err; + + req.pad = 0; + req.num_meters = cpu_to_le16(SCARLETT2_NUM_METERS); + req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC); + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER_LEVELS, + &req, sizeof(req), resp, sizeof(resp)); + if (err < 0) + return err; + + /* copy, convert to u16 */ + for (i = 0; i < SCARLETT2_NUM_METERS; i++) + levels[i] = resp[i]; + + return 0; +} + +/*** Control Functions ***/ + +/* helper function to create a new control */ +static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, + const struct snd_kcontrol_new *ncontrol, + int index, int channels, const char *name, + struct snd_kcontrol **kctl_return) +{ + struct snd_kcontrol *kctl; + struct usb_mixer_elem_info *elem; + int err; + + elem = kzalloc(sizeof(*elem), GFP_KERNEL); + if (!elem) + return -ENOMEM; + + elem->head.mixer = mixer; + elem->control = index; + elem->head.id = index; + elem->channels = channels; + + kctl = snd_ctl_new1(ncontrol, elem); + if (!kctl) { + kfree(elem); + return -ENOMEM; + } + kctl->private_free = snd_usb_mixer_elem_free; + + strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); + + err = snd_usb_mixer_add_control(&elem->head, kctl); + if (err < 0) + return err; + + if (kctl_return) + *kctl_return = kctl; + + return 0; +} + +/*** Analogue Line Out Volume Controls ***/ + +/* Update hardware volume controls after receiving notification that + * they have changed + */ +static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_ports *ports = private->info->ports; + struct scarlett2_usb_volume_status volume_status; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + int err, i; + + private->vol_updated = 0; + + err = scarlett2_usb_get_volume_status(mixer, &volume_status); + if (err < 0) + return err; + + private->master_vol = clamp( + volume_status.master_vol + SCARLETT2_VOLUME_BIAS, + 0, SCARLETT2_VOLUME_BIAS); + + for (i = 0; i < num_line_out; i++) { + if (private->vol_sw_hw_switch[i]) + private->vol[i] = private->master_vol; + } + + for (i = 0; i < private->info->button_count; i++) + private->buttons[i] = !!volume_status.buttons[i]; + + return 0; +} + +static int scarlett2_volume_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = elem->channels; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = SCARLETT2_VOLUME_BIAS; + uinfo->value.integer.step = 1; + return 0; +} + +static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + if (private->vol_updated) { + mutex_lock(&private->data_mutex); + scarlett2_update_volumes(mixer); + mutex_unlock(&private->data_mutex); + } + + ucontrol->value.integer.value[0] = private->master_vol; + return 0; +} + +static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + int index = elem->control; + + if (private->vol_updated) { + mutex_lock(&private->data_mutex); + scarlett2_update_volumes(mixer); + mutex_unlock(&private->data_mutex); + } + + ucontrol->value.integer.value[0] = private->vol[index]; + return 0; +} + +static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->vol[index]; + val = ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->vol[index] = val; + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, + index, val - SCARLETT2_VOLUME_BIAS); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const DECLARE_TLV_DB_MINMAX( + db_scale_scarlett2_gain, -SCARLETT2_VOLUME_BIAS * 100, 0 +); + +static const struct snd_kcontrol_new scarlett2_master_volume_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .name = "", + .info = scarlett2_volume_ctl_info, + .get = scarlett2_master_volume_ctl_get, + .private_value = 0, /* max value */ + .tlv = { .p = db_scale_scarlett2_gain } +}; + +static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .name = "", + .info = scarlett2_volume_ctl_info, + .get = scarlett2_volume_ctl_get, + .put = scarlett2_volume_ctl_put, + .private_value = 0, /* max value */ + .tlv = { .p = db_scale_scarlett2_gain } +}; + +/*** HW/SW Volume Switch Controls ***/ + +static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[2] = { + "SW", "HW" + }; + + return snd_ctl_enum_info(uinfo, 1, 2, values); +} + +static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0] = + private->vol_sw_hw_switch[elem->control]; + return 0; +} + +static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->vol_sw_hw_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->vol_sw_hw_switch[index] = val; + + /* Change access mode to RO (hardware controlled volume) + * or RW (software controlled volume) + */ + if (val) + private->vol_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + else + private->vol_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; + + /* Reset volume to master volume */ + private->vol[index] = private->master_vol; + + /* Set SW volume to current HW volume */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, + index, private->master_vol - SCARLETT2_VOLUME_BIAS); + if (err < 0) + goto unlock; + + /* Notify of RO/RW change */ + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, + &private->vol_ctls[index]->id); + + /* Send SW/HW switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_sw_hw_enum_ctl_info, + .get = scarlett2_sw_hw_enum_ctl_get, + .put = scarlett2_sw_hw_enum_ctl_put, +}; + +/*** Line Level/Instrument Level Switch Controls ***/ + +static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[2] = { + "Line", "Inst" + }; + + return snd_ctl_enum_info(uinfo, 1, 2, values); +} + +static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0] = + private->level_switch[elem->control]; + return 0; +} + +static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->level_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->level_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_level_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_level_enum_ctl_info, + .get = scarlett2_level_enum_ctl_get, + .put = scarlett2_level_enum_ctl_put, +}; + +/*** Pad Switch Controls ***/ + +static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0] = + private->pad_switch[elem->control]; + return 0; +} + +static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->pad_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->pad_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_pad_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_pad_ctl_get, + .put = scarlett2_pad_ctl_put, +}; + +/*** Mute/Dim Controls ***/ + +static int scarlett2_button_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + if (private->vol_updated) { + mutex_lock(&private->data_mutex); + scarlett2_update_volumes(mixer); + mutex_unlock(&private->data_mutex); + } + + ucontrol->value.enumerated.item[0] = private->buttons[elem->control]; + return 0; +} + +static int scarlett2_button_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->buttons[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->buttons[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BUTTONS, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_button_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_button_ctl_get, + .put = scarlett2_button_ctl_put +}; + +/*** Create the analogue output controls ***/ + +static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + int err, i; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + /* Add R/O HW volume control */ + if (info->line_out_hw_vol) { + snprintf(s, sizeof(s), "Master HW Playback Volume"); + err = scarlett2_add_new_ctl(mixer, + &scarlett2_master_volume_ctl, + 0, 1, s, &private->master_vol_ctl); + if (err < 0) + return err; + } + + /* Add volume controls */ + for (i = 0; i < num_line_out; i++) { + + /* Fader */ + if (info->line_out_descrs[i]) + snprintf(s, sizeof(s), + "Line %02d (%s) Playback Volume", + i + 1, info->line_out_descrs[i]); + else + snprintf(s, sizeof(s), + "Line %02d Playback Volume", + i + 1); + err = scarlett2_add_new_ctl(mixer, + &scarlett2_line_out_volume_ctl, + i, 1, s, &private->vol_ctls[i]); + if (err < 0) + return err; + + /* Make the fader read-only if the SW/HW switch is set to HW */ + if (private->vol_sw_hw_switch[i]) + private->vol_ctls[i]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + + /* SW/HW Switch */ + if (info->line_out_hw_vol) { + snprintf(s, sizeof(s), + "Line Out %02d Volume Control Playback Enum", + i + 1); + err = scarlett2_add_new_ctl(mixer, + &scarlett2_sw_hw_enum_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + } + + /* Add HW button controls */ + for (i = 0; i < private->info->button_count; i++) { + err = scarlett2_add_new_ctl(mixer, &scarlett2_button_ctl, + i, 1, scarlett2_button_names[i], + &private->button_ctls[i]); + if (err < 0) + return err; + } + + return 0; +} + +/*** Create the analogue input controls ***/ + +static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int err, i; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + /* Add input level (line/inst) controls */ + for (i = 0; i < info->level_input_count; i++) { + snprintf(s, sizeof(s), "Line In %d Level Capture Enum", i + 1); + err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + + /* Add input pad controls */ + for (i = 0; i < info->pad_input_count; i++) { + snprintf(s, sizeof(s), "Line In %d Pad Capture Switch", i + 1); + err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + + return 0; +} + +/*** Mixer Volume Controls ***/ + +static int scarlett2_mixer_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = elem->channels; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = SCARLETT2_MIXER_MAX_VALUE; + uinfo->value.integer.step = 1; + return 0; +} + +static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0] = private->mix[elem->control]; + return 0; +} + +static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int oval, val, num_mixer_in, mix_num, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->mix[elem->control]; + val = ucontrol->value.integer.value[0]; + num_mixer_in = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + mix_num = elem->control / num_mixer_in; + + if (oval == val) + goto unlock; + + private->mix[elem->control] = val; + err = scarlett2_usb_set_mix(mixer, mix_num); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const DECLARE_TLV_DB_MINMAX( + db_scale_scarlett2_mixer, + SCARLETT2_MIXER_MIN_DB * 100, + SCARLETT2_MIXER_MAX_DB * 100 +); + +static const struct snd_kcontrol_new scarlett2_mixer_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .name = "", + .info = scarlett2_mixer_ctl_info, + .get = scarlett2_mixer_ctl_get, + .put = scarlett2_mixer_ctl_put, + .private_value = SCARLETT2_MIXER_MAX_DB, /* max value */ + .tlv = { .p = db_scale_scarlett2_mixer } +}; + +static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_ports *ports = private->info->ports; + int err, i, j; + int index; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + int num_inputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + int num_outputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN]; + + for (i = 0, index = 0; i < num_outputs; i++) { + for (j = 0; j < num_inputs; j++, index++) { + snprintf(s, sizeof(s), + "Mix %c Input %02d Playback Volume", + 'A' + i, j + 1); + err = scarlett2_add_new_ctl(mixer, &scarlett2_mixer_ctl, + index, 1, s, NULL); + if (err < 0) + return err; + } + } + + return 0; +} + +/*** Mux Source Selection Controls ***/ + +static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + const struct scarlett2_ports *ports = private->info->ports; + unsigned int item = uinfo->value.enumerated.item; + int items = private->num_mux_srcs; + int port_type; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = elem->channels; + uinfo->value.enumerated.items = items; + + if (item >= items) + item = uinfo->value.enumerated.item = items - 1; + + for (port_type = 0; + port_type < SCARLETT2_PORT_TYPE_COUNT; + port_type++) { + if (item < ports[port_type].num[SCARLETT2_PORT_IN]) { + sprintf(uinfo->value.enumerated.name, + ports[port_type].src_descr, + item + ports[port_type].src_num_offset); + return 0; + } + item -= ports[port_type].num[SCARLETT2_PORT_IN]; + } + + return -EINVAL; +} + +static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0] = private->mux[elem->control]; + return 0; +} + +static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_mixer_data *private = mixer->private_data; + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->mux[index]; + val = clamp(ucontrol->value.integer.value[0], + 0L, private->num_mux_srcs - 1L); + + if (oval == val) + goto unlock; + + private->mux[index] = val; + err = scarlett2_usb_set_mux(mixer); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_mux_src_enum_ctl_info, + .get = scarlett2_mux_src_enum_ctl_get, + .put = scarlett2_mux_src_enum_ctl_put, +}; + +static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_ports *ports = private->info->ports; + int port_type, channel, i; + + for (i = 0, port_type = 0; + port_type < SCARLETT2_PORT_TYPE_COUNT; + port_type++) { + for (channel = 0; + channel < ports[port_type].num[SCARLETT2_PORT_OUT]; + channel++, i++) { + int err; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + const char *const descr = ports[port_type].dst_descr; + + snprintf(s, sizeof(s) - 5, descr, channel + 1); + strcat(s, " Enum"); + + err = scarlett2_add_new_ctl(mixer, + &scarlett2_mux_src_enum_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + } + + return 0; +} + +/*** Meter Controls ***/ + +static int scarlett2_meter_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = elem->channels; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 4095; + uinfo->value.integer.step = 1; + return 0; +} + +static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + u16 meter_levels[SCARLETT2_NUM_METERS]; + int i, err; + + err = scarlett2_usb_get_meter_levels(elem->head.mixer, meter_levels); + if (err < 0) + return err; + + for (i = 0; i < elem->channels; i++) + ucontrol->value.integer.value[i] = meter_levels[i]; + + return 0; +} + +static const struct snd_kcontrol_new scarlett2_meter_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .name = "", + .info = scarlett2_meter_ctl_info, + .get = scarlett2_meter_ctl_get +}; + +static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer) +{ + return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl, + 0, SCARLETT2_NUM_METERS, + "Level Meter", NULL); +} + +/*** Cleanup/Suspend Callbacks ***/ + +static void scarlett2_private_free(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + + cancel_delayed_work_sync(&private->work); + kfree(private); + mixer->private_data = NULL; +} + +static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + + if (cancel_delayed_work_sync(&private->work)) + scarlett2_config_save(private->mixer); +} + +/*** Initialisation ***/ + +static int scarlett2_count_mux_srcs(const struct scarlett2_ports *ports) +{ + int port_type, count = 0; + + for (port_type = 0; + port_type < SCARLETT2_PORT_TYPE_COUNT; + port_type++) + count += ports[port_type].num[SCARLETT2_PORT_IN]; + + return count; +} + +/* Default routing connects PCM outputs and inputs to Analogue, + * S/PDIF, then ADAT + */ +static void scarlett2_init_routing(u8 *mux, + const struct scarlett2_ports *ports) +{ + int i, input_num, input_count, port_type; + int output_num, output_count, port_type_connect_num; + + static const int connect_order[] = { + SCARLETT2_PORT_TYPE_ANALOGUE, + SCARLETT2_PORT_TYPE_SPDIF, + SCARLETT2_PORT_TYPE_ADAT, + -1 + }; + + /* Assign PCM inputs (routing outputs) */ + output_num = scarlett2_get_port_start_num(ports, + SCARLETT2_PORT_OUT, + SCARLETT2_PORT_TYPE_PCM); + output_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_OUT]; + + for (port_type = connect_order[port_type_connect_num = 0]; + port_type >= 0; + port_type = connect_order[++port_type_connect_num]) { + input_num = scarlett2_get_port_start_num( + ports, SCARLETT2_PORT_IN, port_type); + input_count = ports[port_type].num[SCARLETT2_PORT_IN]; + for (i = 0; + i < input_count && output_count; + i++, output_count--) + mux[output_num++] = input_num++; + } + + /* Assign PCM outputs (routing inputs) */ + input_num = scarlett2_get_port_start_num(ports, + SCARLETT2_PORT_IN, + SCARLETT2_PORT_TYPE_PCM); + input_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_IN]; + + for (port_type = connect_order[port_type_connect_num = 0]; + port_type >= 0; + port_type = connect_order[++port_type_connect_num]) { + output_num = scarlett2_get_port_start_num( + ports, SCARLETT2_PORT_OUT, port_type); + output_count = ports[port_type].num[SCARLETT2_PORT_OUT]; + for (i = 0; + i < output_count && input_count; + i++, input_count--) + mux[output_num++] = input_num++; + } +} + +/* Initialise private data, routing, sequence number */ +static int scarlett2_init_private(struct usb_mixer_interface *mixer, + const struct scarlett2_device_info *info) +{ + struct scarlett2_mixer_data *private = + kzalloc(sizeof(struct scarlett2_mixer_data), GFP_KERNEL); + + if (!private) + return -ENOMEM; + + mutex_init(&private->usb_mutex); + mutex_init(&private->data_mutex); + INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work); + private->info = info; + private->num_mux_srcs = scarlett2_count_mux_srcs(info->ports); + private->scarlett2_seq = 0; + private->mixer = mixer; + mixer->private_data = private; + mixer->private_free = scarlett2_private_free; + mixer->private_suspend = scarlett2_private_suspend; + + /* Setup default routing */ + scarlett2_init_routing(private->mux, info->ports); + + /* Initialise the sequence number used for the proprietary commands */ + return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0); +} + +/* Read line-in config and line-out volume settings on start */ +static int scarlett2_read_configs(struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + u8 level_switches[SCARLETT2_LEVEL_SWITCH_MAX]; + u8 pad_switches[SCARLETT2_PAD_SWITCH_MAX]; + struct scarlett2_usb_volume_status volume_status; + int err, i; + + if (info->level_input_count) { + err = scarlett2_usb_get_config( + mixer, + SCARLETT2_CONFIG_LEVEL_SWITCH, + info->level_input_count, + level_switches); + if (err < 0) + return err; + for (i = 0; i < info->level_input_count; i++) + private->level_switch[i] = level_switches[i]; + } + + if (info->pad_input_count) { + err = scarlett2_usb_get_config( + mixer, + SCARLETT2_CONFIG_PAD_SWITCH, + info->pad_input_count, + pad_switches); + if (err < 0) + return err; + for (i = 0; i < info->pad_input_count; i++) + private->pad_switch[i] = pad_switches[i]; + } + + err = scarlett2_usb_get_volume_status(mixer, &volume_status); + if (err < 0) + return err; + + private->master_vol = clamp( + volume_status.master_vol + SCARLETT2_VOLUME_BIAS, + 0, SCARLETT2_VOLUME_BIAS); + + for (i = 0; i < num_line_out; i++) { + int volume; + + private->vol_sw_hw_switch[i] = + info->line_out_hw_vol + && volume_status.sw_hw_switch[i]; + + volume = private->vol_sw_hw_switch[i] + ? volume_status.master_vol + : volume_status.sw_vol[i]; + volume = clamp(volume + SCARLETT2_VOLUME_BIAS, + 0, SCARLETT2_VOLUME_BIAS); + private->vol[i] = volume; + } + + for (i = 0; i < info->button_count; i++) + private->buttons[i] = !!volume_status.buttons[i]; + + return 0; +} + +/* Notify on volume change */ +static void scarlett2_mixer_interrupt_vol_change( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + const struct scarlett2_ports *ports = private->info->ports; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + int i; + + private->vol_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->master_vol_ctl->id); + + for (i = 0; i < num_line_out; i++) { + if (!private->vol_sw_hw_switch[i]) + continue; + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->vol_ctls[i]->id); + } +} + +/* Notify on button change */ +static void scarlett2_mixer_interrupt_button_change( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_mixer_data *private = mixer->private_data; + int i; + + private->vol_updated = 1; + + for (i = 0; i < private->info->button_count; i++) + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->button_ctls[i]->id); +} + +/* Interrupt callback */ +static void scarlett2_mixer_interrupt(struct urb *urb) +{ + struct usb_mixer_interface *mixer = urb->context; + int len = urb->actual_length; + int ustatus = urb->status; + u32 data; + + if (ustatus != 0) + goto requeue; + + if (len == 8) { + data = le32_to_cpu(*(u32 *)urb->transfer_buffer); + if (data & SCARLETT2_USB_INTERRUPT_VOL_CHANGE) + scarlett2_mixer_interrupt_vol_change(mixer); + if (data & SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE) + scarlett2_mixer_interrupt_button_change(mixer); + } else { + usb_audio_err(mixer->chip, + "scarlett mixer interrupt length %d\n", len); + } + +requeue: + if (ustatus != -ENOENT && + ustatus != -ECONNRESET && + ustatus != -ESHUTDOWN) { + urb->dev = mixer->chip->dev; + usb_submit_urb(urb, GFP_ATOMIC); + } +} + +static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer) +{ + struct usb_device *dev = mixer->chip->dev; + unsigned int pipe = usb_rcvintpipe(dev, + SCARLETT2_USB_INTERRUPT_ENDPOINT); + void *transfer_buffer; + + if (mixer->urb) { + usb_audio_err(mixer->chip, + "%s: mixer urb already in use!\n", __func__); + return 0; + } + + if (snd_usb_pipe_sanity_check(dev, pipe)) + return -EINVAL; + + mixer->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mixer->urb) + return -ENOMEM; + + transfer_buffer = kmalloc(SCARLETT2_USB_INTERRUPT_MAX_DATA, GFP_KERNEL); + if (!transfer_buffer) + return -ENOMEM; + + usb_fill_int_urb(mixer->urb, dev, pipe, + transfer_buffer, SCARLETT2_USB_INTERRUPT_MAX_DATA, + scarlett2_mixer_interrupt, mixer, + SCARLETT2_USB_INTERRUPT_INTERVAL); + + return usb_submit_urb(mixer->urb, GFP_KERNEL); +} + +/* Entry point */ +int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) +{ + const struct scarlett2_device_info *info; + int err; + + /* only use UAC_VERSION_2 */ + if (!mixer->protocol) + return 0; + + switch (mixer->chip->usb_id) { + case USB_ID(0x1235, 0x8203): + info = &s6i6_gen2_info; + break; + case USB_ID(0x1235, 0x8204): + info = &s18i8_gen2_info; + break; + case USB_ID(0x1235, 0x8201): + info = &s18i20_gen2_info; + break; + default: /* device not (yet) supported */ + return -EINVAL; + } + + if (!(mixer->chip->setup & SCARLETT2_ENABLE)) { + usb_audio_err(mixer->chip, + "Focusrite Scarlett Gen 2 Mixer Driver disabled; " + "use options snd_usb_audio device_setup=1 " + "to enable and report any issues to g@b4.vu"); + return 0; + } + + /* Initialise private data, routing, sequence number */ + err = scarlett2_init_private(mixer, info); + if (err < 0) + return err; + + /* Read volume levels and controls from the interface */ + err = scarlett2_read_configs(mixer); + if (err < 0) + return err; + + /* Create the analogue output controls */ + err = scarlett2_add_line_out_ctls(mixer); + if (err < 0) + return err; + + /* Create the analogue input controls */ + err = scarlett2_add_line_in_ctls(mixer); + if (err < 0) + return err; + + /* Create the input, output, and mixer mux input selections */ + err = scarlett2_add_mux_enums(mixer); + if (err < 0) + return err; + + /* Create the matrix mixer controls */ + err = scarlett2_add_mixer_ctls(mixer); + if (err < 0) + return err; + + /* Create the level meter controls */ + err = scarlett2_add_meter_ctl(mixer); + if (err < 0) + return err; + + /* Set up the interrupt polling if there are hardware buttons */ + if (info->button_count) { + err = scarlett2_mixer_status_create(mixer); + if (err < 0) + return err; + } + + return 0; +} diff --git a/sound/usb/mixer_scarlett_gen2.h b/sound/usb/mixer_scarlett_gen2.h new file mode 100644 index 000000000000..52e1dad77afd --- /dev/null +++ b/sound/usb/mixer_scarlett_gen2.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __USB_MIXER_SCARLETT_GEN2_H +#define __USB_MIXER_SCARLETT_GEN2_H + +int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer); + +#endif /* __USB_MIXER_SCARLETT_GEN2_H */ -- GitLab From f626d6dfb709852595e6fb24710819f9d21bc5ae Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 17 Jul 2019 09:10:01 +0200 Subject: [PATCH 0970/7155] gpio: of: Break out OF-only code The core gpiolib should not contain any OF/device tree-only code. Try to break out the main part of it and push it down into the optional gpiolib-of.c part of the library. Create a local gpiolib-of.h header and move stuff around a bit to get a clean cut. Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190717071001.3858-1-linus.walleij@linaro.org --- drivers/gpio/gpiolib-of.c | 114 ++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-of.h | 45 +++++++++++++++ drivers/gpio/gpiolib.c | 113 +++---------------------------------- drivers/gpio/gpiolib.h | 27 --------- 4 files changed, 167 insertions(+), 132 deletions(-) create mode 100644 drivers/gpio/gpiolib-of.h diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 567fb98c0892..b10d04dd9296 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -21,6 +21,34 @@ #include #include "gpiolib.h" +#include "gpiolib-of.h" + +/* + * This is used by external users of of_gpio_count() from + * + * FIXME: get rid of those external users by converting them to GPIO + * descriptors and let them all use gpiod_get_count() + */ +int of_gpio_get_count(struct device *dev, const char *con_id) +{ + int ret; + char propname[32]; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { + if (con_id) + snprintf(propname, sizeof(propname), "%s-%s", + con_id, gpio_suffixes[i]); + else + snprintf(propname, sizeof(propname), "%s", + gpio_suffixes[i]); + + ret = of_gpio_named_count(dev->of_node, propname); + if (ret > 0) + break; + } + return ret ? ret : -ENOENT; +} static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) { @@ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, return gpiochip_get_desc(chip, ret); } +/** + * of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs + * to set the .valid_mask + * @dev: the device for the GPIO provider + * @return: true if the valid mask needs to be set + */ +bool of_gpio_need_valid_mask(struct gpio_chip *gc) +{ + int size; + struct device_node *np = gc->of_node; + + size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + return true; + return false; +} + static void of_gpio_flags_quirks(struct device_node *np, const char *propname, enum of_gpio_flags *flags, @@ -231,6 +276,75 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, } EXPORT_SYMBOL(of_get_named_gpio_flags); +/** + * gpiod_get_from_of_node() - obtain a GPIO from an OF node + * @node: handle of the OF node + * @propname: name of the DT property representing the GPIO + * @index: index of the GPIO to obtain for the consumer + * @dflags: GPIO initialization flags + * @label: label to attach to the requested GPIO + * + * Returns: + * On successful request the GPIO pin is configured in accordance with + * provided @dflags. + * + * In case of error an ERR_PTR() is returned. + */ +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; + struct gpio_desc *desc; + enum of_gpio_flags flags; + bool active_low = false; + bool single_ended = false; + bool open_drain = false; + bool transitory = false; + int ret; + + desc = of_get_named_gpiod_flags(node, propname, + index, &flags); + + if (!desc || IS_ERR(desc)) { + return desc; + } + + active_low = flags & OF_GPIO_ACTIVE_LOW; + single_ended = flags & OF_GPIO_SINGLE_ENDED; + open_drain = flags & OF_GPIO_OPEN_DRAIN; + transitory = flags & OF_GPIO_TRANSITORY; + + ret = gpiod_request(desc, label); + if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) + return desc; + if (ret) + return ERR_PTR(ret); + + if (active_low) + lflags |= GPIO_ACTIVE_LOW; + + if (single_ended) { + if (open_drain) + lflags |= GPIO_OPEN_DRAIN; + else + lflags |= GPIO_OPEN_SOURCE; + } + + if (transitory) + lflags |= GPIO_TRANSITORY; + + ret = gpiod_configure_flags(desc, propname, lflags, dflags); + if (ret < 0) { + gpiod_put(desc); + return ERR_PTR(ret); + } + + return desc; +} +EXPORT_SYMBOL(gpiod_get_from_of_node); + /* * The SPI GPIO bindings happened before we managed to establish that GPIO * properties should be named "foo-gpios" so we have this special kludge for diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h new file mode 100644 index 000000000000..34954921d96e --- /dev/null +++ b/drivers/gpio/gpiolib-of.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef GPIOLIB_OF_H +#define GPIOLIB_OF_H + +struct gpio_chip; +enum of_gpio_flags; + +#ifdef CONFIG_OF_GPIO +struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *lookupflags); +struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags); +int of_gpiochip_add(struct gpio_chip *gc); +void of_gpiochip_remove(struct gpio_chip *gc); +int of_gpio_get_count(struct device *dev, const char *con_id); +bool of_gpio_need_valid_mask(struct gpio_chip *gc); +#else +static inline struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags) +{ + return ERR_PTR(-ENOENT); +} +static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } +static inline void of_gpiochip_remove(struct gpio_chip *gc) { } +static inline int of_gpio_get_count(struct device *dev, const char *con_id) +{ + return 0; +} +static inline bool of_gpio_need_valid_mask(struct gpio_chip *gc) +{ + return false; +} +#endif /* CONFIG_OF_GPIO */ + +#endif /* GPIOLIB_OF_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3ee99d070608..03883f519d53 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include "gpiolib.h" +#include "gpiolib-of.h" #define CREATE_TRACE_POINTS #include @@ -360,22 +360,15 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) return p; } -static int gpiochip_alloc_valid_mask(struct gpio_chip *gpiochip) +static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { -#ifdef CONFIG_OF_GPIO - int size; - struct device_node *np = gpiochip->of_node; - - size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); - if (size > 0 && size % 2 == 0) - gpiochip->need_valid_mask = true; -#endif - - if (!gpiochip->need_valid_mask) + if (IS_ENABLED(CONFIG_OF_GPIO)) + gc->need_valid_mask = of_gpio_need_valid_mask(gc); + if (!gc->need_valid_mask) return 0; - gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); - if (!gpiochip->valid_mask) + gc->valid_mask = gpiochip_allocate_mask(gc); + if (!gc->valid_mask) return -ENOMEM; return 0; @@ -3993,27 +3986,6 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return desc; } -static int dt_gpio_count(struct device *dev, const char *con_id) -{ - int ret; - char propname[32]; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { - if (con_id) - snprintf(propname, sizeof(propname), "%s-%s", - con_id, gpio_suffixes[i]); - else - snprintf(propname, sizeof(propname), "%s", - gpio_suffixes[i]); - - ret = of_gpio_named_count(dev->of_node, propname); - if (ret > 0) - break; - } - return ret ? ret : -ENOENT; -} - static int platform_gpio_count(struct device *dev, const char *con_id) { struct gpiod_lookup_table *table; @@ -4046,7 +4018,7 @@ int gpiod_count(struct device *dev, const char *con_id) int count = -ENOENT; if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) - count = dt_gpio_count(dev, con_id); + count = of_gpio_get_count(dev, con_id); else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) count = acpi_gpio_count(dev, con_id); @@ -4247,75 +4219,6 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, } EXPORT_SYMBOL_GPL(gpiod_get_index); -/** - * gpiod_get_from_of_node() - obtain a GPIO from an OF node - * @node: handle of the OF node - * @propname: name of the DT property representing the GPIO - * @index: index of the GPIO to obtain for the consumer - * @dflags: GPIO initialization flags - * @label: label to attach to the requested GPIO - * - * Returns: - * On successful request the GPIO pin is configured in accordance with - * provided @dflags. - * - * In case of error an ERR_PTR() is returned. - */ -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; - struct gpio_desc *desc; - enum of_gpio_flags flags; - bool active_low = false; - bool single_ended = false; - bool open_drain = false; - bool transitory = false; - int ret; - - desc = of_get_named_gpiod_flags(node, propname, - index, &flags); - - if (!desc || IS_ERR(desc)) { - return desc; - } - - active_low = flags & OF_GPIO_ACTIVE_LOW; - single_ended = flags & OF_GPIO_SINGLE_ENDED; - open_drain = flags & OF_GPIO_OPEN_DRAIN; - transitory = flags & OF_GPIO_TRANSITORY; - - ret = gpiod_request(desc, label); - if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) - return desc; - if (ret) - return ERR_PTR(ret); - - if (active_low) - lflags |= GPIO_ACTIVE_LOW; - - if (single_ended) { - if (open_drain) - lflags |= GPIO_OPEN_DRAIN; - else - lflags |= GPIO_OPEN_SOURCE; - } - - if (transitory) - lflags |= GPIO_TRANSITORY; - - ret = gpiod_configure_flags(desc, propname, lflags, dflags); - if (ret < 0) { - gpiod_put(desc); - return ERR_PTR(ret); - } - - return desc; -} -EXPORT_SYMBOL(gpiod_get_from_of_node); - /** * fwnode_get_named_gpiod - obtain a GPIO from firmware node * @fwnode: handle of the firmware node diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 7c52c2442173..75d2e909d8c6 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -16,7 +16,6 @@ #include #include -enum of_gpio_flags; struct acpi_device; /** @@ -92,32 +91,6 @@ struct acpi_gpio_info { /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; -#ifdef CONFIG_OF_GPIO -struct gpio_desc *of_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - unsigned long *lookupflags); -struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags); -int of_gpiochip_add(struct gpio_chip *gc); -void of_gpiochip_remove(struct gpio_chip *gc); -#else -static inline struct gpio_desc *of_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - unsigned long *lookupflags) -{ - return ERR_PTR(-ENOENT); -} -static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags) -{ - return ERR_PTR(-ENOENT); -} -static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } -static inline void of_gpiochip_remove(struct gpio_chip *gc) { } -#endif /* CONFIG_OF_GPIO */ - #ifdef CONFIG_ACPI void acpi_gpiochip_add(struct gpio_chip *chip); void acpi_gpiochip_remove(struct gpio_chip *chip); -- GitLab From a299726da44fd679ce805aa80d7d6b559bac9874 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:46:01 +0200 Subject: [PATCH 0971/7155] gpio: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the gpio sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190703084601.9276-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max77650.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c index 3f03f4e8956c..3075f2513c6f 100644 --- a/drivers/gpio/gpio-max77650.c +++ b/drivers/gpio/gpio-max77650.c @@ -188,3 +188,4 @@ module_platform_driver(max77650_gpio_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-gpio"); -- GitLab From 6ff2deb2e8f6f2e23959724bab03ac60a050710b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:20 -0700 Subject: [PATCH 0972/7155] fs-verity: add a documentation file Add a documentation file for fs-verity, covering: - Introduction - Use cases - User API - FS_IOC_ENABLE_VERITY - FS_IOC_MEASURE_VERITY - FS_IOC_GETFLAGS - Accessing verity files - File measurement computation - Merkle tree - fs-verity descriptor - Built-in signature verification - Filesystem support - ext4 - f2fs - Implementation details - Verifying data - Pagecache - Block device based filesystems - Userspace utility - Tests - FAQ Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- Documentation/filesystems/fsverity.rst | 726 +++++++++++++++++++++++++ Documentation/filesystems/index.rst | 1 + 2 files changed, 727 insertions(+) create mode 100644 Documentation/filesystems/fsverity.rst diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst new file mode 100644 index 000000000000..42a0b6dd9e0b --- /dev/null +++ b/Documentation/filesystems/fsverity.rst @@ -0,0 +1,726 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _fsverity: + +======================================================= +fs-verity: read-only file-based authenticity protection +======================================================= + +Introduction +============ + +fs-verity (``fs/verity/``) is a support layer that filesystems can +hook into to support transparent integrity and authenticity protection +of read-only files. Currently, it is supported by the ext4 and f2fs +filesystems. Like fscrypt, not too much filesystem-specific code is +needed to support fs-verity. + +fs-verity is similar to `dm-verity +`_ +but works on files rather than block devices. On regular files on +filesystems supporting fs-verity, userspace can execute an ioctl that +causes the filesystem to build a Merkle tree for the file and persist +it to a filesystem-specific location associated with the file. + +After this, the file is made readonly, and all reads from the file are +automatically verified against the file's Merkle tree. Reads of any +corrupted data, including mmap reads, will fail. + +Userspace can use another ioctl to retrieve the root hash (actually +the "file measurement", which is a hash that includes the root hash) +that fs-verity is enforcing for the file. This ioctl executes in +constant time, regardless of the file size. + +fs-verity is essentially a way to hash a file in constant time, +subject to the caveat that reads which would violate the hash will +fail at runtime. + +Use cases +========= + +By itself, the base fs-verity feature only provides integrity +protection, i.e. detection of accidental (non-malicious) corruption. + +However, because fs-verity makes retrieving the file hash extremely +efficient, it's primarily meant to be used as a tool to support +authentication (detection of malicious modifications) or auditing +(logging file hashes before use). + +Trusted userspace code (e.g. operating system code running on a +read-only partition that is itself authenticated by dm-verity) can +authenticate the contents of an fs-verity file by using the +`FS_IOC_MEASURE_VERITY`_ ioctl to retrieve its hash, then verifying a +digital signature of it. + +A standard file hash could be used instead of fs-verity. However, +this is inefficient if the file is large and only a small portion may +be accessed. This is often the case for Android application package +(APK) files, for example. These typically contain many translations, +classes, and other resources that are infrequently or even never +accessed on a particular device. It would be slow and wasteful to +read and hash the entire file before starting the application. + +Unlike an ahead-of-time hash, fs-verity also re-verifies data each +time it's paged in. This ensures that malicious disk firmware can't +undetectably change the contents of the file at runtime. + +fs-verity does not replace or obsolete dm-verity. dm-verity should +still be used on read-only filesystems. fs-verity is for files that +must live on a read-write filesystem because they are independently +updated and potentially user-installed, so dm-verity cannot be used. + +The base fs-verity feature is a hashing mechanism only; actually +authenticating the files is up to userspace. However, to meet some +users' needs, fs-verity optionally supports a simple signature +verification mechanism where users can configure the kernel to require +that all fs-verity files be signed by a key loaded into a keyring; see +`Built-in signature verification`_. Support for fs-verity file hashes +in IMA (Integrity Measurement Architecture) policies is also planned. + +User API +======== + +FS_IOC_ENABLE_VERITY +-------------------- + +The FS_IOC_ENABLE_VERITY ioctl enables fs-verity on a file. It takes +in a pointer to a :c:type:`struct fsverity_enable_arg`, defined as +follows:: + + struct fsverity_enable_arg { + __u32 version; + __u32 hash_algorithm; + __u32 block_size; + __u32 salt_size; + __u64 salt_ptr; + __u32 sig_size; + __u32 __reserved1; + __u64 sig_ptr; + __u64 __reserved2[11]; + }; + +This structure contains the parameters of the Merkle tree to build for +the file, and optionally contains a signature. It must be initialized +as follows: + +- ``version`` must be 1. +- ``hash_algorithm`` must be the identifier for the hash algorithm to + use for the Merkle tree, such as FS_VERITY_HASH_ALG_SHA256. See + ``include/uapi/linux/fsverity.h`` for the list of possible values. +- ``block_size`` must be the Merkle tree block size. Currently, this + must be equal to the system page size, which is usually 4096 bytes. + Other sizes may be supported in the future. This value is not + necessarily the same as the filesystem block size. +- ``salt_size`` is the size of the salt in bytes, or 0 if no salt is + provided. The salt is a value that is prepended to every hashed + block; it can be used to personalize the hashing for a particular + file or device. Currently the maximum salt size is 32 bytes. +- ``salt_ptr`` is the pointer to the salt, or NULL if no salt is + provided. +- ``sig_size`` is the size of the signature in bytes, or 0 if no + signature is provided. Currently the signature is (somewhat + arbitrarily) limited to 16128 bytes. See `Built-in signature + verification`_ for more information. +- ``sig_ptr`` is the pointer to the signature, or NULL if no + signature is provided. +- All reserved fields must be zeroed. + +FS_IOC_ENABLE_VERITY causes the filesystem to build a Merkle tree for +the file and persist it to a filesystem-specific location associated +with the file, then mark the file as a verity file. This ioctl may +take a long time to execute on large files, and it is interruptible by +fatal signals. + +FS_IOC_ENABLE_VERITY checks for write access to the inode. However, +it must be executed on an O_RDONLY file descriptor and no processes +can have the file open for writing. Attempts to open the file for +writing while this ioctl is executing will fail with ETXTBSY. (This +is necessary to guarantee that no writable file descriptors will exist +after verity is enabled, and to guarantee that the file's contents are +stable while the Merkle tree is being built over it.) + +On success, FS_IOC_ENABLE_VERITY returns 0, and the file becomes a +verity file. On failure (including the case of interruption by a +fatal signal), no changes are made to the file. + +FS_IOC_ENABLE_VERITY can fail with the following errors: + +- ``EACCES``: the process does not have write access to the file +- ``EBADMSG``: the signature is malformed +- ``EBUSY``: this ioctl is already running on the file +- ``EEXIST``: the file already has verity enabled +- ``EFAULT``: the caller provided inaccessible memory +- ``EINTR``: the operation was interrupted by a fatal signal +- ``EINVAL``: unsupported version, hash algorithm, or block size; or + reserved bits are set; or the file descriptor refers to neither a + regular file nor a directory. +- ``EISDIR``: the file descriptor refers to a directory +- ``EKEYREJECTED``: the signature doesn't match the file +- ``EMSGSIZE``: the salt or signature is too long +- ``ENOKEY``: the fs-verity keyring doesn't contain the certificate + needed to verify the signature +- ``ENOPKG``: fs-verity recognizes the hash algorithm, but it's not + available in the kernel's crypto API as currently configured (e.g. + for SHA-512, missing CONFIG_CRYPTO_SHA512). +- ``ENOTTY``: this type of filesystem does not implement fs-verity +- ``EOPNOTSUPP``: the kernel was not configured with fs-verity + support; or the filesystem superblock has not had the 'verity' + feature enabled on it; or the filesystem does not support fs-verity + on this file. (See `Filesystem support`_.) +- ``EPERM``: the file is append-only; or, a signature is required and + one was not provided. +- ``EROFS``: the filesystem is read-only +- ``ETXTBSY``: someone has the file open for writing. This can be the + caller's file descriptor, another open file descriptor, or the file + reference held by a writable memory map. + +FS_IOC_MEASURE_VERITY +--------------------- + +The FS_IOC_MEASURE_VERITY ioctl retrieves the measurement of a verity +file. The file measurement is a digest that cryptographically +identifies the file contents that are being enforced on reads. + +This ioctl takes in a pointer to a variable-length structure:: + + struct fsverity_digest { + __u16 digest_algorithm; + __u16 digest_size; /* input/output */ + __u8 digest[]; + }; + +``digest_size`` is an input/output field. On input, it must be +initialized to the number of bytes allocated for the variable-length +``digest`` field. + +On success, 0 is returned and the kernel fills in the structure as +follows: + +- ``digest_algorithm`` will be the hash algorithm used for the file + measurement. It will match ``fsverity_enable_arg::hash_algorithm``. +- ``digest_size`` will be the size of the digest in bytes, e.g. 32 + for SHA-256. (This can be redundant with ``digest_algorithm``.) +- ``digest`` will be the actual bytes of the digest. + +FS_IOC_MEASURE_VERITY is guaranteed to execute in constant time, +regardless of the size of the file. + +FS_IOC_MEASURE_VERITY can fail with the following errors: + +- ``EFAULT``: the caller provided inaccessible memory +- ``ENODATA``: the file is not a verity file +- ``ENOTTY``: this type of filesystem does not implement fs-verity +- ``EOPNOTSUPP``: the kernel was not configured with fs-verity + support, or the filesystem superblock has not had the 'verity' + feature enabled on it. (See `Filesystem support`_.) +- ``EOVERFLOW``: the digest is longer than the specified + ``digest_size`` bytes. Try providing a larger buffer. + +FS_IOC_GETFLAGS +--------------- + +The existing ioctl FS_IOC_GETFLAGS (which isn't specific to fs-verity) +can also be used to check whether a file has fs-verity enabled or not. +To do so, check for FS_VERITY_FL (0x00100000) in the returned flags. + +The verity flag is not settable via FS_IOC_SETFLAGS. You must use +FS_IOC_ENABLE_VERITY instead, since parameters must be provided. + +Accessing verity files +====================== + +Applications can transparently access a verity file just like a +non-verity one, with the following exceptions: + +- Verity files are readonly. They cannot be opened for writing or + truncate()d, even if the file mode bits allow it. Attempts to do + one of these things will fail with EPERM. However, changes to + metadata such as owner, mode, timestamps, and xattrs are still + allowed, since these are not measured by fs-verity. Verity files + can also still be renamed, deleted, and linked to. + +- Direct I/O is not supported on verity files. Attempts to use direct + I/O on such files will fall back to buffered I/O. + +- DAX (Direct Access) is not supported on verity files, because this + would circumvent the data verification. + +- Reads of data that doesn't match the verity Merkle tree will fail + with EIO (for read()) or SIGBUS (for mmap() reads). + +- If the sysctl "fs.verity.require_signatures" is set to 1 and the + file's verity measurement is not signed by a key in the fs-verity + keyring, then opening the file will fail. See `Built-in signature + verification`_. + +Direct access to the Merkle tree is not supported. Therefore, if a +verity file is copied, or is backed up and restored, then it will lose +its "verity"-ness. fs-verity is primarily meant for files like +executables that are managed by a package manager. + +File measurement computation +============================ + +This section describes how fs-verity hashes the file contents using a +Merkle tree to produce the "file measurement" which cryptographically +identifies the file contents. This algorithm is the same for all +filesystems that support fs-verity. + +Userspace only needs to be aware of this algorithm if it needs to +compute the file measurement itself, e.g. in order to sign the file. + +.. _fsverity_merkle_tree: + +Merkle tree +----------- + +The file contents is divided into blocks, where the block size is +configurable but is usually 4096 bytes. The end of the last block is +zero-padded if needed. Each block is then hashed, producing the first +level of hashes. Then, the hashes in this first level are grouped +into 'blocksize'-byte blocks (zero-padding the ends as needed) and +these blocks are hashed, producing the second level of hashes. This +proceeds up the tree until only a single block remains. The hash of +this block is the "Merkle tree root hash". + +If the file fits in one block and is nonempty, then the "Merkle tree +root hash" is simply the hash of the single data block. If the file +is empty, then the "Merkle tree root hash" is all zeroes. + +The "blocks" here are not necessarily the same as "filesystem blocks". + +If a salt was specified, then it's zero-padded to the closest multiple +of the input size of the hash algorithm's compression function, e.g. +64 bytes for SHA-256 or 128 bytes for SHA-512. The padded salt is +prepended to every data or Merkle tree block that is hashed. + +The purpose of the block padding is to cause every hash to be taken +over the same amount of data, which simplifies the implementation and +keeps open more possibilities for hardware acceleration. The purpose +of the salt padding is to make the salting "free" when the salted hash +state is precomputed, then imported for each hash. + +Example: in the recommended configuration of SHA-256 and 4K blocks, +128 hash values fit in each block. Thus, each level of the Merkle +tree is approximately 128 times smaller than the previous, and for +large files the Merkle tree's size converges to approximately 1/127 of +the original file size. However, for small files, the padding is +significant, making the space overhead proportionally more. + +.. _fsverity_descriptor: + +fs-verity descriptor +-------------------- + +By itself, the Merkle tree root hash is ambiguous. For example, it +can't a distinguish a large file from a small second file whose data +is exactly the top-level hash block of the first file. Ambiguities +also arise from the convention of padding to the next block boundary. + +To solve this problem, the verity file measurement is actually +computed as a hash of the following structure, which contains the +Merkle tree root hash as well as other fields such as the file size:: + + struct fsverity_descriptor { + __u8 version; /* must be 1 */ + __u8 hash_algorithm; /* Merkle tree hash algorithm */ + __u8 log_blocksize; /* log2 of size of data and tree blocks */ + __u8 salt_size; /* size of salt in bytes; 0 if none */ + __le32 sig_size; /* must be 0 */ + __le64 data_size; /* size of file the Merkle tree is built over */ + __u8 root_hash[64]; /* Merkle tree root hash */ + __u8 salt[32]; /* salt prepended to each hashed block */ + __u8 __reserved[144]; /* must be 0's */ + }; + +Note that the ``sig_size`` field must be set to 0 for the purpose of +computing the file measurement, even if a signature was provided (or +will be provided) to `FS_IOC_ENABLE_VERITY`_. + +Built-in signature verification +=============================== + +With CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y, fs-verity supports putting +a portion of an authentication policy (see `Use cases`_) in the +kernel. Specifically, it adds support for: + +1. At fs-verity module initialization time, a keyring ".fs-verity" is + created. The root user can add trusted X.509 certificates to this + keyring using the add_key() system call, then (when done) + optionally use keyctl_restrict_keyring() to prevent additional + certificates from being added. + +2. `FS_IOC_ENABLE_VERITY`_ accepts a pointer to a PKCS#7 formatted + detached signature in DER format of the file measurement. On + success, this signature is persisted alongside the Merkle tree. + Then, any time the file is opened, the kernel will verify the + file's actual measurement against this signature, using the + certificates in the ".fs-verity" keyring. + +3. A new sysctl "fs.verity.require_signatures" is made available. + When set to 1, the kernel requires that all verity files have a + correctly signed file measurement as described in (2). + +File measurements must be signed in the following format, which is +similar to the structure used by `FS_IOC_MEASURE_VERITY`_:: + + struct fsverity_signed_digest { + char magic[8]; /* must be "FSVerity" */ + __le16 digest_algorithm; + __le16 digest_size; + __u8 digest[]; + }; + +fs-verity's built-in signature verification support is meant as a +relatively simple mechanism that can be used to provide some level of +authenticity protection for verity files, as an alternative to doing +the signature verification in userspace or using IMA-appraisal. +However, with this mechanism, userspace programs still need to check +that the verity bit is set, and there is no protection against verity +files being swapped around. + +Filesystem support +================== + +fs-verity is currently supported by the ext4 and f2fs filesystems. +The CONFIG_FS_VERITY kconfig option must be enabled to use fs-verity +on either filesystem. + +``include/linux/fsverity.h`` declares the interface between the +``fs/verity/`` support layer and filesystems. Briefly, filesystems +must provide an ``fsverity_operations`` structure that provides +methods to read and write the verity metadata to a filesystem-specific +location, including the Merkle tree blocks and +``fsverity_descriptor``. Filesystems must also call functions in +``fs/verity/`` at certain times, such as when a file is opened or when +pages have been read into the pagecache. (See `Verifying data`_.) + +ext4 +---- + +ext4 supports fs-verity since Linux TODO and e2fsprogs v1.45.2. + +To create verity files on an ext4 filesystem, the filesystem must have +been formatted with ``-O verity`` or had ``tune2fs -O verity`` run on +it. "verity" is an RO_COMPAT filesystem feature, so once set, old +kernels will only be able to mount the filesystem readonly, and old +versions of e2fsck will be unable to check the filesystem. Moreover, +currently ext4 only supports mounting a filesystem with the "verity" +feature when its block size is equal to PAGE_SIZE (often 4096 bytes). + +ext4 sets the EXT4_VERITY_FL on-disk inode flag on verity files. It +can only be set by `FS_IOC_ENABLE_VERITY`_, and it cannot be cleared. + +ext4 also supports encryption, which can be used simultaneously with +fs-verity. In this case, the plaintext data is verified rather than +the ciphertext. This is necessary in order to make the file +measurement meaningful, since every file is encrypted differently. + +ext4 stores the verity metadata (Merkle tree and fsverity_descriptor) +past the end of the file, starting at the first 64K boundary beyond +i_size. This approach works because (a) verity files are readonly, +and (b) pages fully beyond i_size aren't visible to userspace but can +be read/written internally by ext4 with only some relatively small +changes to ext4. This approach avoids having to depend on the +EA_INODE feature and on rearchitecturing ext4's xattr support to +support paging multi-gigabyte xattrs into memory, and to support +encrypting xattrs. Note that the verity metadata *must* be encrypted +when the file is, since it contains hashes of the plaintext data. + +Currently, ext4 verity only supports the case where the Merkle tree +block size, filesystem block size, and page size are all the same. It +also only supports extent-based files. + +f2fs +---- + +f2fs supports fs-verity since Linux TODO and f2fs-tools v1.11.0. + +To create verity files on an f2fs filesystem, the filesystem must have +been formatted with ``-O verity``. + +f2fs sets the FADVISE_VERITY_BIT on-disk inode flag on verity files. +It can only be set by `FS_IOC_ENABLE_VERITY`_, and it cannot be +cleared. + +Like ext4, f2fs stores the verity metadata (Merkle tree and +fsverity_descriptor) past the end of the file, starting at the first +64K boundary beyond i_size. See explanation for ext4 above. +Moreover, f2fs supports at most 4096 bytes of xattr entries per inode +which wouldn't be enough for even a single Merkle tree block. + +Currently, f2fs verity only supports a Merkle tree block size of 4096. +Also, f2fs doesn't support enabling verity on files that currently +have atomic or volatile writes pending. + +Implementation details +====================== + +Verifying data +-------------- + +fs-verity ensures that all reads of a verity file's data are verified, +regardless of which syscall is used to do the read (e.g. mmap(), +read(), pread()) and regardless of whether it's the first read or a +later read (unless the later read can return cached data that was +already verified). Below, we describe how filesystems implement this. + +Pagecache +~~~~~~~~~ + +For filesystems using Linux's pagecache, the ``->readpage()`` and +``->readpages()`` methods must be modified to verify pages before they +are marked Uptodate. Merely hooking ``->read_iter()`` would be +insufficient, since ``->read_iter()`` is not used for memory maps. + +Therefore, fs/verity/ provides a function fsverity_verify_page() which +verifies a page that has been read into the pagecache of a verity +inode, but is still locked and not Uptodate, so it's not yet readable +by userspace. As needed to do the verification, +fsverity_verify_page() will call back into the filesystem to read +Merkle tree pages via fsverity_operations::read_merkle_tree_page(). + +fsverity_verify_page() returns false if verification failed; in this +case, the filesystem must not set the page Uptodate. Following this, +as per the usual Linux pagecache behavior, attempts by userspace to +read() from the part of the file containing the page will fail with +EIO, and accesses to the page within a memory map will raise SIGBUS. + +fsverity_verify_page() currently only supports the case where the +Merkle tree block size is equal to PAGE_SIZE (often 4096 bytes). + +In principle, fsverity_verify_page() verifies the entire path in the +Merkle tree from the data page to the root hash. However, for +efficiency the filesystem may cache the hash pages. Therefore, +fsverity_verify_page() only ascends the tree reading hash pages until +an already-verified hash page is seen, as indicated by the PageChecked +bit being set. It then verifies the path to that page. + +This optimization, which is also used by dm-verity, results in +excellent sequential read performance. This is because usually (e.g. +127 in 128 times for 4K blocks and SHA-256) the hash page from the +bottom level of the tree will already be cached and checked from +reading a previous data page. However, random reads perform worse. + +Block device based filesystems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Block device based filesystems (e.g. ext4 and f2fs) in Linux also use +the pagecache, so the above subsection applies too. However, they +also usually read many pages from a file at once, grouped into a +structure called a "bio". To make it easier for these types of +filesystems to support fs-verity, fs/verity/ also provides a function +fsverity_verify_bio() which verifies all pages in a bio. + +ext4 and f2fs also support encryption. If a verity file is also +encrypted, the pages must be decrypted before being verified. To +support this, these filesystems allocate a "post-read context" for +each bio and store it in ``->bi_private``:: + + struct bio_post_read_ctx { + struct bio *bio; + struct work_struct work; + unsigned int cur_step; + unsigned int enabled_steps; + }; + +``enabled_steps`` is a bitmask that specifies whether decryption, +verity, or both is enabled. After the bio completes, for each needed +postprocessing step the filesystem enqueues the bio_post_read_ctx on a +workqueue, and then the workqueue work does the decryption or +verification. Finally, pages where no decryption or verity error +occurred are marked Uptodate, and the pages are unlocked. + +Files on ext4 and f2fs may contain holes. Normally, ``->readpages()`` +simply zeroes holes and sets the corresponding pages Uptodate; no bios +are issued. To prevent this case from bypassing fs-verity, these +filesystems use fsverity_verify_page() to verify hole pages. + +ext4 and f2fs disable direct I/O on verity files, since otherwise +direct I/O would bypass fs-verity. (They also do the same for +encrypted files.) + +Userspace utility +================= + +This document focuses on the kernel, but a userspace utility for +fs-verity can be found at: + + https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/fsverity-utils.git + +See the README.md file in the fsverity-utils source tree for details, +including examples of setting up fs-verity protected files. + +Tests +===== + +To test fs-verity, use xfstests. For example, using `kvm-xfstests +`_:: + + kvm-xfstests -c ext4,f2fs -g verity + +FAQ +=== + +This section answers frequently asked questions about fs-verity that +weren't already directly answered in other parts of this document. + +:Q: Why isn't fs-verity part of IMA? +:A: fs-verity and IMA (Integrity Measurement Architecture) have + different focuses. fs-verity is a filesystem-level mechanism for + hashing individual files using a Merkle tree. In contrast, IMA + specifies a system-wide policy that specifies which files are + hashed and what to do with those hashes, such as log them, + authenticate them, or add them to a measurement list. + + IMA is planned to support the fs-verity hashing mechanism as an + alternative to doing full file hashes, for people who want the + performance and security benefits of the Merkle tree based hash. + But it doesn't make sense to force all uses of fs-verity to be + through IMA. As a standalone filesystem feature, fs-verity + already meets many users' needs, and it's testable like other + filesystem features e.g. with xfstests. + +:Q: Isn't fs-verity useless because the attacker can just modify the + hashes in the Merkle tree, which is stored on-disk? +:A: To verify the authenticity of an fs-verity file you must verify + the authenticity of the "file measurement", which is basically the + root hash of the Merkle tree. See `Use cases`_. + +:Q: Isn't fs-verity useless because the attacker can just replace a + verity file with a non-verity one? +:A: See `Use cases`_. In the initial use case, it's really trusted + userspace code that authenticates the files; fs-verity is just a + tool to do this job efficiently and securely. The trusted + userspace code will consider non-verity files to be inauthentic. + +:Q: Why does the Merkle tree need to be stored on-disk? Couldn't you + store just the root hash? +:A: If the Merkle tree wasn't stored on-disk, then you'd have to + compute the entire tree when the file is first accessed, even if + just one byte is being read. This is a fundamental consequence of + how Merkle tree hashing works. To verify a leaf node, you need to + verify the whole path to the root hash, including the root node + (the thing which the root hash is a hash of). But if the root + node isn't stored on-disk, you have to compute it by hashing its + children, and so on until you've actually hashed the entire file. + + That defeats most of the point of doing a Merkle tree-based hash, + since if you have to hash the whole file ahead of time anyway, + then you could simply do sha256(file) instead. That would be much + simpler, and a bit faster too. + + It's true that an in-memory Merkle tree could still provide the + advantage of verification on every read rather than just on the + first read. However, it would be inefficient because every time a + hash page gets evicted (you can't pin the entire Merkle tree into + memory, since it may be very large), in order to restore it you + again need to hash everything below it in the tree. This again + defeats most of the point of doing a Merkle tree-based hash, since + a single block read could trigger re-hashing gigabytes of data. + +:Q: But couldn't you store just the leaf nodes and compute the rest? +:A: See previous answer; this really just moves up one level, since + one could alternatively interpret the data blocks as being the + leaf nodes of the Merkle tree. It's true that the tree can be + computed much faster if the leaf level is stored rather than just + the data, but that's only because each level is less than 1% the + size of the level below (assuming the recommended settings of + SHA-256 and 4K blocks). For the exact same reason, by storing + "just the leaf nodes" you'd already be storing over 99% of the + tree, so you might as well simply store the whole tree. + +:Q: Can the Merkle tree be built ahead of time, e.g. distributed as + part of a package that is installed to many computers? +:A: This isn't currently supported. It was part of the original + design, but was removed to simplify the kernel UAPI and because it + wasn't a critical use case. Files are usually installed once and + used many times, and cryptographic hashing is somewhat fast on + most modern processors. + +:Q: Why doesn't fs-verity support writes? +:A: Write support would be very difficult and would require a + completely different design, so it's well outside the scope of + fs-verity. Write support would require: + + - A way to maintain consistency between the data and hashes, + including all levels of hashes, since corruption after a crash + (especially of potentially the entire file!) is unacceptable. + The main options for solving this are data journalling, + copy-on-write, and log-structured volume. But it's very hard to + retrofit existing filesystems with new consistency mechanisms. + Data journalling is available on ext4, but is very slow. + + - Rebuilding the the Merkle tree after every write, which would be + extremely inefficient. Alternatively, a different authenticated + dictionary structure such as an "authenticated skiplist" could + be used. However, this would be far more complex. + + Compare it to dm-verity vs. dm-integrity. dm-verity is very + simple: the kernel just verifies read-only data against a + read-only Merkle tree. In contrast, dm-integrity supports writes + but is slow, is much more complex, and doesn't actually support + full-device authentication since it authenticates each sector + independently, i.e. there is no "root hash". It doesn't really + make sense for the same device-mapper target to support these two + very different cases; the same applies to fs-verity. + +:Q: Since verity files are immutable, why isn't the immutable bit set? +:A: The existing "immutable" bit (FS_IMMUTABLE_FL) already has a + specific set of semantics which not only make the file contents + read-only, but also prevent the file from being deleted, renamed, + linked to, or having its owner or mode changed. These extra + properties are unwanted for fs-verity, so reusing the immutable + bit isn't appropriate. + +:Q: Why does the API use ioctls instead of setxattr() and getxattr()? +:A: Abusing the xattr interface for basically arbitrary syscalls is + heavily frowned upon by most of the Linux filesystem developers. + An xattr should really just be an xattr on-disk, not an API to + e.g. magically trigger construction of a Merkle tree. + +:Q: Does fs-verity support remote filesystems? +:A: Only ext4 and f2fs support is implemented currently, but in + principle any filesystem that can store per-file verity metadata + can support fs-verity, regardless of whether it's local or remote. + Some filesystems may have fewer options of where to store the + verity metadata; one possibility is to store it past the end of + the file and "hide" it from userspace by manipulating i_size. The + data verification functions provided by ``fs/verity/`` also assume + that the filesystem uses the Linux pagecache, but both local and + remote filesystems normally do so. + +:Q: Why is anything filesystem-specific at all? Shouldn't fs-verity + be implemented entirely at the VFS level? +:A: There are many reasons why this is not possible or would be very + difficult, including the following: + + - To prevent bypassing verification, pages must not be marked + Uptodate until they've been verified. Currently, each + filesystem is responsible for marking pages Uptodate via + ``->readpages()``. Therefore, currently it's not possible for + the VFS to do the verification on its own. Changing this would + require significant changes to the VFS and all filesystems. + + - It would require defining a filesystem-independent way to store + the verity metadata. Extended attributes don't work for this + because (a) the Merkle tree may be gigabytes, but many + filesystems assume that all xattrs fit into a single 4K + filesystem block, and (b) ext4 and f2fs encryption doesn't + encrypt xattrs, yet the Merkle tree *must* be encrypted when the + file contents are, because it stores hashes of the plaintext + file contents. + + So the verity metadata would have to be stored in an actual + file. Using a separate file would be very ugly, since the + metadata is fundamentally part of the file to be protected, and + it could cause problems where users could delete the real file + but not the metadata file or vice versa. On the other hand, + having it be in the same file would break applications unless + filesystems' notion of i_size were divorced from the VFS's, + which would be complex and require changes to all filesystems. + + - It's desirable that FS_IOC_ENABLE_VERITY uses the filesystem's + transaction mechanism so that either the file ends up with + verity enabled, or no changes were made. Allowing intermediate + states to occur after a crash may cause problems. diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index 2de2fe2ab078..54f2c6aac187 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -32,3 +32,4 @@ filesystem implementations. journalling fscrypt + fsverity -- GitLab From c9570b2ced0305ad2e69ff57012641c584bfa2a9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:20 -0700 Subject: [PATCH 0973/7155] fs-verity: add MAINTAINERS file entry fs-verity will be jointly maintained by Eric Biggers and Theodore Ts'o. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- MAINTAINERS | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6426db5198f0..bf086a7f324a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6629,6 +6629,18 @@ S: Maintained F: fs/notify/ F: include/linux/fsnotify*.h +FSVERITY: READ-ONLY FILE-BASED AUTHENTICITY PROTECTION +M: Eric Biggers +M: Theodore Y. Ts'o +L: linux-fscrypt@vger.kernel.org +Q: https://patchwork.kernel.org/project/linux-fscrypt/list/ +T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git fsverity +S: Supported +F: fs/verity/ +F: include/linux/fsverity.h +F: include/uapi/linux/fsverity.h +F: Documentation/filesystems/fsverity.rst + FUJITSU LAPTOP EXTRAS M: Jonathan Woithe L: platform-driver-x86@vger.kernel.org -- GitLab From 085771ec14b9bdb843fe9283d4703ced395d1b0b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:20 -0700 Subject: [PATCH 0974/7155] fs-verity: add UAPI header Add the UAPI header for fs-verity, including two ioctls: - FS_IOC_ENABLE_VERITY - FS_IOC_MEASURE_VERITY These ioctls are documented in the "User API" section of Documentation/filesystems/fsverity.rst. Examples of using these ioctls can be found in fsverity-utils (https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/fsverity-utils.git). I've also written xfstests that test these ioctls (https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/xfstests-dev.git/log/?h=fsverity). Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- Documentation/ioctl/ioctl-number.rst | 1 + include/uapi/linux/fsverity.h | 39 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 include/uapi/linux/fsverity.h diff --git a/Documentation/ioctl/ioctl-number.rst b/Documentation/ioctl/ioctl-number.rst index 7f8dcae7a230..bef79cd4c6b4 100644 --- a/Documentation/ioctl/ioctl-number.rst +++ b/Documentation/ioctl/ioctl-number.rst @@ -233,6 +233,7 @@ Code Seq# Include File Comments 'f' 00-0F fs/ext4/ext4.h conflict! 'f' 00-0F linux/fs.h conflict! 'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict! +'f' 81-8F linux/fsverity.h 'g' 00-0F linux/usb/gadgetfs.h 'g' 20-2F linux/usb/g_printer.h 'h' 00-7F conflict! Charon filesystem diff --git a/include/uapi/linux/fsverity.h b/include/uapi/linux/fsverity.h new file mode 100644 index 000000000000..57d1d7fc0c34 --- /dev/null +++ b/include/uapi/linux/fsverity.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * fs-verity user API + * + * These ioctls can be used on filesystems that support fs-verity. See the + * "User API" section of Documentation/filesystems/fsverity.rst. + * + * Copyright 2019 Google LLC + */ +#ifndef _UAPI_LINUX_FSVERITY_H +#define _UAPI_LINUX_FSVERITY_H + +#include +#include + +#define FS_VERITY_HASH_ALG_SHA256 1 + +struct fsverity_enable_arg { + __u32 version; + __u32 hash_algorithm; + __u32 block_size; + __u32 salt_size; + __u64 salt_ptr; + __u32 sig_size; + __u32 __reserved1; + __u64 sig_ptr; + __u64 __reserved2[11]; +}; + +struct fsverity_digest { + __u16 digest_algorithm; + __u16 digest_size; /* input/output */ + __u8 digest[]; +}; + +#define FS_IOC_ENABLE_VERITY _IOW('f', 133, struct fsverity_enable_arg) +#define FS_IOC_MEASURE_VERITY _IOWR('f', 134, struct fsverity_digest) + +#endif /* _UAPI_LINUX_FSVERITY_H */ -- GitLab From fe9918d3b228b3e8c726849d1486933f46b9069e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:21 -0700 Subject: [PATCH 0975/7155] fs: uapi: define verity bit for FS_IOC_GETFLAGS Add FS_VERITY_FL to the flags for FS_IOC_GETFLAGS, so that applications can easily determine whether a file is a verity file at the same time as they're checking other file flags. This flag will be gettable only; FS_IOC_SETFLAGS won't allow setting it, since an ioctl must be used instead to provide more parameters. This flag matches the on-disk bit that was already allocated for ext4. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- include/uapi/linux/fs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 59c71fa8c553..df261b7e0587 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -306,6 +306,7 @@ struct fscrypt_key { #define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define FS_HUGE_FILE_FL 0x00040000 /* Reserved for ext4 */ #define FS_EXTENT_FL 0x00080000 /* Extents */ +#define FS_VERITY_FL 0x00100000 /* Verity protected inode */ #define FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */ #define FS_EOFBLOCKS_FL 0x00400000 /* Reserved for ext4 */ #define FS_NOCOW_FL 0x00800000 /* Do not cow file */ -- GitLab From 671e67b47e9fffd12c8f69eda853a202cb5b3fc5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:21 -0700 Subject: [PATCH 0976/7155] fs-verity: add Kconfig and the helper functions for hashing Add the beginnings of the fs/verity/ support layer, including the Kconfig option and various helper functions for hashing. To start, only SHA-256 is supported, but other hash algorithms can easily be added. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/Kconfig | 2 + fs/Makefile | 1 + fs/verity/Kconfig | 38 +++++ fs/verity/Makefile | 4 + fs/verity/fsverity_private.h | 88 +++++++++++ fs/verity/hash_algs.c | 275 +++++++++++++++++++++++++++++++++++ fs/verity/init.c | 41 ++++++ 7 files changed, 449 insertions(+) create mode 100644 fs/verity/Kconfig create mode 100644 fs/verity/Makefile create mode 100644 fs/verity/fsverity_private.h create mode 100644 fs/verity/hash_algs.c create mode 100644 fs/verity/init.c diff --git a/fs/Kconfig b/fs/Kconfig index bfb1c6095c7a..14cd4abdc143 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -112,6 +112,8 @@ config MANDATORY_FILE_LOCKING source "fs/crypto/Kconfig" +source "fs/verity/Kconfig" + source "fs/notify/Kconfig" source "fs/quota/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index d60089fd689b..6cef5df93683 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_AIO) += aio.o obj-$(CONFIG_IO_URING) += io_uring.o obj-$(CONFIG_FS_DAX) += dax.o obj-$(CONFIG_FS_ENCRYPTION) += crypto/ +obj-$(CONFIG_FS_VERITY) += verity/ obj-$(CONFIG_FILE_LOCKING) += locks.o obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o diff --git a/fs/verity/Kconfig b/fs/verity/Kconfig new file mode 100644 index 000000000000..c2bca0b01ecf --- /dev/null +++ b/fs/verity/Kconfig @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 + +config FS_VERITY + bool "FS Verity (read-only file-based authenticity protection)" + select CRYPTO + # SHA-256 is selected as it's intended to be the default hash algorithm. + # To avoid bloat, other wanted algorithms must be selected explicitly. + select CRYPTO_SHA256 + help + This option enables fs-verity. fs-verity is the dm-verity + mechanism implemented at the file level. On supported + filesystems (currently EXT4 and F2FS), userspace can use an + ioctl to enable verity for a file, which causes the filesystem + to build a Merkle tree for the file. The filesystem will then + transparently verify any data read from the file against the + Merkle tree. The file is also made read-only. + + This serves as an integrity check, but the availability of the + Merkle tree root hash also allows efficiently supporting + various use cases where normally the whole file would need to + be hashed at once, such as: (a) auditing (logging the file's + hash), or (b) authenticity verification (comparing the hash + against a known good value, e.g. from a digital signature). + + fs-verity is especially useful on large files where not all + the contents may actually be needed. Also, fs-verity verifies + data each time it is paged back in, which provides better + protection against malicious disks vs. an ahead-of-time hash. + + If unsure, say N. + +config FS_VERITY_DEBUG + bool "FS Verity debugging" + depends on FS_VERITY + help + Enable debugging messages related to fs-verity by default. + + Say N unless you are an fs-verity developer. diff --git a/fs/verity/Makefile b/fs/verity/Makefile new file mode 100644 index 000000000000..398f3f85fa18 --- /dev/null +++ b/fs/verity/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_FS_VERITY) += hash_algs.o \ + init.o diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h new file mode 100644 index 000000000000..9697aaebb5dc --- /dev/null +++ b/fs/verity/fsverity_private.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * fs-verity: read-only file-based authenticity protection + * + * Copyright 2019 Google LLC + */ + +#ifndef _FSVERITY_PRIVATE_H +#define _FSVERITY_PRIVATE_H + +#ifdef CONFIG_FS_VERITY_DEBUG +#define DEBUG +#endif + +#define pr_fmt(fmt) "fs-verity: " fmt + +#include +#include +#include + +struct ahash_request; + +/* + * Implementation limit: maximum depth of the Merkle tree. For now 8 is plenty; + * it's enough for over U64_MAX bytes of data using SHA-256 and 4K blocks. + */ +#define FS_VERITY_MAX_LEVELS 8 + +/* + * Largest digest size among all hash algorithms supported by fs-verity. + * Currently assumed to be <= size of fsverity_descriptor::root_hash. + */ +#define FS_VERITY_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + +/* A hash algorithm supported by fs-verity */ +struct fsverity_hash_alg { + struct crypto_ahash *tfm; /* hash tfm, allocated on demand */ + const char *name; /* crypto API name, e.g. sha256 */ + unsigned int digest_size; /* digest size in bytes, e.g. 32 for SHA-256 */ + unsigned int block_size; /* block size in bytes, e.g. 64 for SHA-256 */ +}; + +/* Merkle tree parameters: hash algorithm, initial hash state, and topology */ +struct merkle_tree_params { + const struct fsverity_hash_alg *hash_alg; /* the hash algorithm */ + const u8 *hashstate; /* initial hash state or NULL */ + unsigned int digest_size; /* same as hash_alg->digest_size */ + unsigned int block_size; /* size of data and tree blocks */ + unsigned int hashes_per_block; /* number of hashes per tree block */ + unsigned int log_blocksize; /* log2(block_size) */ + unsigned int log_arity; /* log2(hashes_per_block) */ + unsigned int num_levels; /* number of levels in Merkle tree */ + u64 tree_size; /* Merkle tree size in bytes */ + + /* + * Starting block index for each tree level, ordered from leaf level (0) + * to root level ('num_levels - 1') + */ + u64 level_start[FS_VERITY_MAX_LEVELS]; +}; + +/* hash_algs.c */ + +extern struct fsverity_hash_alg fsverity_hash_algs[]; + +const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode, + unsigned int num); +const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg, + const u8 *salt, size_t salt_size); +int fsverity_hash_page(const struct merkle_tree_params *params, + const struct inode *inode, + struct ahash_request *req, struct page *page, u8 *out); +int fsverity_hash_buffer(const struct fsverity_hash_alg *alg, + const void *data, size_t size, u8 *out); +void __init fsverity_check_hash_algs(void); + +/* init.c */ + +extern void __printf(3, 4) __cold +fsverity_msg(const struct inode *inode, const char *level, + const char *fmt, ...); + +#define fsverity_warn(inode, fmt, ...) \ + fsverity_msg((inode), KERN_WARNING, fmt, ##__VA_ARGS__) +#define fsverity_err(inode, fmt, ...) \ + fsverity_msg((inode), KERN_ERR, fmt, ##__VA_ARGS__) + +#endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/hash_algs.c b/fs/verity/hash_algs.c new file mode 100644 index 000000000000..7df1d67742b8 --- /dev/null +++ b/fs/verity/hash_algs.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/hash_algs.c: fs-verity hash algorithms + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include +#include + +/* The hash algorithms supported by fs-verity */ +struct fsverity_hash_alg fsverity_hash_algs[] = { + [FS_VERITY_HASH_ALG_SHA256] = { + .name = "sha256", + .digest_size = SHA256_DIGEST_SIZE, + .block_size = SHA256_BLOCK_SIZE, + }, +}; + +/** + * fsverity_get_hash_alg() - validate and prepare a hash algorithm + * @inode: optional inode for logging purposes + * @num: the hash algorithm number + * + * Get the struct fsverity_hash_alg for the given hash algorithm number, and + * ensure it has a hash transform ready to go. The hash transforms are + * allocated on-demand so that we don't waste resources unnecessarily, and + * because the crypto modules may be initialized later than fs/verity/. + * + * Return: pointer to the hash alg on success, else an ERR_PTR() + */ +const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode, + unsigned int num) +{ + struct fsverity_hash_alg *alg; + struct crypto_ahash *tfm; + int err; + + if (num >= ARRAY_SIZE(fsverity_hash_algs) || + !fsverity_hash_algs[num].name) { + fsverity_warn(inode, "Unknown hash algorithm number: %u", num); + return ERR_PTR(-EINVAL); + } + alg = &fsverity_hash_algs[num]; + + /* pairs with cmpxchg() below */ + tfm = READ_ONCE(alg->tfm); + if (likely(tfm != NULL)) + return alg; + /* + * Using the shash API would make things a bit simpler, but the ahash + * API is preferable as it allows the use of crypto accelerators. + */ + tfm = crypto_alloc_ahash(alg->name, 0, 0); + if (IS_ERR(tfm)) { + if (PTR_ERR(tfm) == -ENOENT) { + fsverity_warn(inode, + "Missing crypto API support for hash algorithm \"%s\"", + alg->name); + return ERR_PTR(-ENOPKG); + } + fsverity_err(inode, + "Error allocating hash algorithm \"%s\": %ld", + alg->name, PTR_ERR(tfm)); + return ERR_CAST(tfm); + } + + err = -EINVAL; + if (WARN_ON(alg->digest_size != crypto_ahash_digestsize(tfm))) + goto err_free_tfm; + if (WARN_ON(alg->block_size != crypto_ahash_blocksize(tfm))) + goto err_free_tfm; + + pr_info("%s using implementation \"%s\"\n", + alg->name, crypto_ahash_driver_name(tfm)); + + /* pairs with READ_ONCE() above */ + if (cmpxchg(&alg->tfm, NULL, tfm) != NULL) + crypto_free_ahash(tfm); + + return alg; + +err_free_tfm: + crypto_free_ahash(tfm); + return ERR_PTR(err); +} + +/** + * fsverity_prepare_hash_state() - precompute the initial hash state + * @alg: hash algorithm + * @salt: a salt which is to be prepended to all data to be hashed + * @salt_size: salt size in bytes, possibly 0 + * + * Return: NULL if the salt is empty, otherwise the kmalloc()'ed precomputed + * initial hash state on success or an ERR_PTR() on failure. + */ +const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg, + const u8 *salt, size_t salt_size) +{ + u8 *hashstate = NULL; + struct ahash_request *req = NULL; + u8 *padded_salt = NULL; + size_t padded_salt_size; + struct scatterlist sg; + DECLARE_CRYPTO_WAIT(wait); + int err; + + if (salt_size == 0) + return NULL; + + hashstate = kmalloc(crypto_ahash_statesize(alg->tfm), GFP_KERNEL); + if (!hashstate) + return ERR_PTR(-ENOMEM); + + req = ahash_request_alloc(alg->tfm, GFP_KERNEL); + if (!req) { + err = -ENOMEM; + goto err_free; + } + + /* + * Zero-pad the salt to the next multiple of the input size of the hash + * algorithm's compression function, e.g. 64 bytes for SHA-256 or 128 + * bytes for SHA-512. This ensures that the hash algorithm won't have + * any bytes buffered internally after processing the salt, thus making + * salted hashing just as fast as unsalted hashing. + */ + padded_salt_size = round_up(salt_size, alg->block_size); + padded_salt = kzalloc(padded_salt_size, GFP_KERNEL); + if (!padded_salt) { + err = -ENOMEM; + goto err_free; + } + memcpy(padded_salt, salt, salt_size); + + sg_init_one(&sg, padded_salt, padded_salt_size); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP | + CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + ahash_request_set_crypt(req, &sg, NULL, padded_salt_size); + + err = crypto_wait_req(crypto_ahash_init(req), &wait); + if (err) + goto err_free; + + err = crypto_wait_req(crypto_ahash_update(req), &wait); + if (err) + goto err_free; + + err = crypto_ahash_export(req, hashstate); + if (err) + goto err_free; +out: + ahash_request_free(req); + kfree(padded_salt); + return hashstate; + +err_free: + kfree(hashstate); + hashstate = ERR_PTR(err); + goto out; +} + +/** + * fsverity_hash_page() - hash a single data or hash page + * @params: the Merkle tree's parameters + * @inode: inode for which the hashing is being done + * @req: preallocated hash request + * @page: the page to hash + * @out: output digest, size 'params->digest_size' bytes + * + * Hash a single data or hash block, assuming block_size == PAGE_SIZE. + * The hash is salted if a salt is specified in the Merkle tree parameters. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_hash_page(const struct merkle_tree_params *params, + const struct inode *inode, + struct ahash_request *req, struct page *page, u8 *out) +{ + struct scatterlist sg; + DECLARE_CRYPTO_WAIT(wait); + int err; + + if (WARN_ON(params->block_size != PAGE_SIZE)) + return -EINVAL; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, PAGE_SIZE, 0); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP | + CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + ahash_request_set_crypt(req, &sg, out, PAGE_SIZE); + + if (params->hashstate) { + err = crypto_ahash_import(req, params->hashstate); + if (err) { + fsverity_err(inode, + "Error %d importing hash state", err); + return err; + } + err = crypto_ahash_finup(req); + } else { + err = crypto_ahash_digest(req); + } + + err = crypto_wait_req(err, &wait); + if (err) + fsverity_err(inode, "Error %d computing page hash", err); + return err; +} + +/** + * fsverity_hash_buffer() - hash some data + * @alg: the hash algorithm to use + * @data: the data to hash + * @size: size of data to hash, in bytes + * @out: output digest, size 'alg->digest_size' bytes + * + * Hash some data which is located in physically contiguous memory (i.e. memory + * allocated by kmalloc(), not by vmalloc()). No salt is used. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_hash_buffer(const struct fsverity_hash_alg *alg, + const void *data, size_t size, u8 *out) +{ + struct ahash_request *req; + struct scatterlist sg; + DECLARE_CRYPTO_WAIT(wait); + int err; + + req = ahash_request_alloc(alg->tfm, GFP_KERNEL); + if (!req) + return -ENOMEM; + + sg_init_one(&sg, data, size); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP | + CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + ahash_request_set_crypt(req, &sg, out, size); + + err = crypto_wait_req(crypto_ahash_digest(req), &wait); + + ahash_request_free(req); + return err; +} + +void __init fsverity_check_hash_algs(void) +{ + size_t i; + + /* + * Sanity check the hash algorithms (could be a build-time check, but + * they're in an array) + */ + for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) { + const struct fsverity_hash_alg *alg = &fsverity_hash_algs[i]; + + if (!alg->name) + continue; + + BUG_ON(alg->digest_size > FS_VERITY_MAX_DIGEST_SIZE); + + /* + * For efficiency, the implementation currently assumes the + * digest and block sizes are powers of 2. This limitation can + * be lifted if the code is updated to handle other values. + */ + BUG_ON(!is_power_of_2(alg->digest_size)); + BUG_ON(!is_power_of_2(alg->block_size)); + } +} diff --git a/fs/verity/init.c b/fs/verity/init.c new file mode 100644 index 000000000000..40076bbe452a --- /dev/null +++ b/fs/verity/init.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/init.c: fs-verity module initialization and logging + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include + +void fsverity_msg(const struct inode *inode, const char *level, + const char *fmt, ...) +{ + static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + struct va_format vaf; + va_list args; + + if (!__ratelimit(&rs)) + return; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + if (inode) + printk("%sfs-verity (%s, inode %lu): %pV\n", + level, inode->i_sb->s_id, inode->i_ino, &vaf); + else + printk("%sfs-verity: %pV\n", level, &vaf); + va_end(args); +} + +static int __init fsverity_init(void) +{ + fsverity_check_hash_algs(); + + pr_debug("Initialized fs-verity\n"); + return 0; +} +late_initcall(fsverity_init) -- GitLab From 5585f2af737ae3d7454cb0ae77b995cd3ac7e43c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:21 -0700 Subject: [PATCH 0977/7155] fs-verity: add inode and superblock fields Analogous to fs/crypto/, add fields to the VFS inode and superblock for use by the fs/verity/ support layer: - ->s_vop: points to the fsverity_operations if the filesystem supports fs-verity, otherwise is NULL. - ->i_verity_info: points to cached fs-verity information for the inode after someone opens it, otherwise is NULL. - S_VERITY: bit in ->i_flags that identifies verity inodes, even when they haven't been opened yet and thus still have NULL ->i_verity_info. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- include/linux/fs.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index 56b8e358af5c..b3a0f5bfb06d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -64,6 +64,8 @@ struct workqueue_struct; struct iov_iter; struct fscrypt_info; struct fscrypt_operations; +struct fsverity_info; +struct fsverity_operations; struct fs_context; struct fs_parameter_description; @@ -723,6 +725,10 @@ struct inode { struct fscrypt_info *i_crypt_info; #endif +#ifdef CONFIG_FS_VERITY + struct fsverity_info *i_verity_info; +#endif + void *i_private; /* fs or device private pointer */ } __randomize_layout; @@ -1427,6 +1433,9 @@ struct super_block { const struct xattr_handler **s_xattr; #ifdef CONFIG_FS_ENCRYPTION const struct fscrypt_operations *s_cop; +#endif +#ifdef CONFIG_FS_VERITY + const struct fsverity_operations *s_vop; #endif struct hlist_bl_head s_roots; /* alternate root dentries for NFS */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ @@ -1965,6 +1974,7 @@ struct super_operations { #endif #define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */ #define S_CASEFOLD 32768 /* Casefolded file */ +#define S_VERITY 65536 /* Verity file (using fs/verity/) */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -2006,6 +2016,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags #define IS_DAX(inode) ((inode)->i_flags & S_DAX) #define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED) #define IS_CASEFOLDED(inode) ((inode)->i_flags & S_CASEFOLD) +#define IS_VERITY(inode) ((inode)->i_flags & S_VERITY) #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \ (inode)->i_rdev == WHITEOUT_DEV) -- GitLab From fd2d1acfcadfe2e42567afaec5e989b38061a7d2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:22 -0700 Subject: [PATCH 0978/7155] fs-verity: add the hook for file ->open() Add the fsverity_file_open() function, which prepares an fs-verity file to be read from. If not already done, it loads the fs-verity descriptor from the filesystem and sets up an fsverity_info structure for the inode which describes the Merkle tree and contains the file measurement. It also denies all attempts to open verity files for writing. This commit also begins the include/linux/fsverity.h header, which declares the interface between fs/verity/ and filesystems. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/Makefile | 3 +- fs/verity/fsverity_private.h | 54 +++++- fs/verity/init.c | 6 + fs/verity/open.c | 318 +++++++++++++++++++++++++++++++++++ include/linux/fsverity.h | 71 ++++++++ 5 files changed, 449 insertions(+), 3 deletions(-) create mode 100644 fs/verity/open.c create mode 100644 include/linux/fsverity.h diff --git a/fs/verity/Makefile b/fs/verity/Makefile index 398f3f85fa18..e6a8951c493a 100644 --- a/fs/verity/Makefile +++ b/fs/verity/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_FS_VERITY) += hash_algs.o \ - init.o + init.o \ + open.o diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index 9697aaebb5dc..c79746ff335e 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -15,8 +15,7 @@ #define pr_fmt(fmt) "fs-verity: " fmt #include -#include -#include +#include struct ahash_request; @@ -59,6 +58,40 @@ struct merkle_tree_params { u64 level_start[FS_VERITY_MAX_LEVELS]; }; +/** + * fsverity_info - cached verity metadata for an inode + * + * When a verity file is first opened, an instance of this struct is allocated + * and stored in ->i_verity_info; it remains until the inode is evicted. It + * caches information about the Merkle tree that's needed to efficiently verify + * data read from the file. It also caches the file measurement. The Merkle + * tree pages themselves are not cached here, but the filesystem may cache them. + */ +struct fsverity_info { + struct merkle_tree_params tree_params; + u8 root_hash[FS_VERITY_MAX_DIGEST_SIZE]; + u8 measurement[FS_VERITY_MAX_DIGEST_SIZE]; + const struct inode *inode; +}; + +/* + * Merkle tree properties. The file measurement is the hash of this structure. + */ +struct fsverity_descriptor { + __u8 version; /* must be 1 */ + __u8 hash_algorithm; /* Merkle tree hash algorithm */ + __u8 log_blocksize; /* log2 of size of data and tree blocks */ + __u8 salt_size; /* size of salt in bytes; 0 if none */ + __le32 sig_size; /* reserved, must be 0 */ + __le64 data_size; /* size of file the Merkle tree is built over */ + __u8 root_hash[64]; /* Merkle tree root hash */ + __u8 salt[32]; /* salt prepended to each hashed block */ + __u8 __reserved[144]; /* must be 0's */ +}; + +/* Arbitrary limit to bound the kmalloc() size. Can be changed. */ +#define FS_VERITY_MAX_DESCRIPTOR_SIZE 16384 + /* hash_algs.c */ extern struct fsverity_hash_alg fsverity_hash_algs[]; @@ -85,4 +118,21 @@ fsverity_msg(const struct inode *inode, const char *level, #define fsverity_err(inode, fmt, ...) \ fsverity_msg((inode), KERN_ERR, fmt, ##__VA_ARGS__) +/* open.c */ + +int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, + const struct inode *inode, + unsigned int hash_algorithm, + unsigned int log_blocksize, + const u8 *salt, size_t salt_size); + +struct fsverity_info *fsverity_create_info(const struct inode *inode, + const void *desc, size_t desc_size); + +void fsverity_set_info(struct inode *inode, struct fsverity_info *vi); + +void fsverity_free_info(struct fsverity_info *vi); + +int __init fsverity_init_info_cache(void); + #endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/init.c b/fs/verity/init.c index 40076bbe452a..fff1fd634335 100644 --- a/fs/verity/init.c +++ b/fs/verity/init.c @@ -33,8 +33,14 @@ void fsverity_msg(const struct inode *inode, const char *level, static int __init fsverity_init(void) { + int err; + fsverity_check_hash_algs(); + err = fsverity_init_info_cache(); + if (err) + return err; + pr_debug("Initialized fs-verity\n"); return 0; } diff --git a/fs/verity/open.c b/fs/verity/open.c new file mode 100644 index 000000000000..8013f77f907e --- /dev/null +++ b/fs/verity/open.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/open.c: opening fs-verity files + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include + +static struct kmem_cache *fsverity_info_cachep; + +/** + * fsverity_init_merkle_tree_params() - initialize Merkle tree parameters + * @params: the parameters struct to initialize + * @inode: the inode for which the Merkle tree is being built + * @hash_algorithm: number of hash algorithm to use + * @log_blocksize: log base 2 of block size to use + * @salt: pointer to salt (optional) + * @salt_size: size of salt, possibly 0 + * + * Validate the hash algorithm and block size, then compute the tree topology + * (num levels, num blocks in each level, etc.) and initialize @params. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, + const struct inode *inode, + unsigned int hash_algorithm, + unsigned int log_blocksize, + const u8 *salt, size_t salt_size) +{ + const struct fsverity_hash_alg *hash_alg; + int err; + u64 blocks; + u64 offset; + int level; + + memset(params, 0, sizeof(*params)); + + hash_alg = fsverity_get_hash_alg(inode, hash_algorithm); + if (IS_ERR(hash_alg)) + return PTR_ERR(hash_alg); + params->hash_alg = hash_alg; + params->digest_size = hash_alg->digest_size; + + params->hashstate = fsverity_prepare_hash_state(hash_alg, salt, + salt_size); + if (IS_ERR(params->hashstate)) { + err = PTR_ERR(params->hashstate); + params->hashstate = NULL; + fsverity_err(inode, "Error %d preparing hash state", err); + goto out_err; + } + + if (log_blocksize != PAGE_SHIFT) { + fsverity_warn(inode, "Unsupported log_blocksize: %u", + log_blocksize); + err = -EINVAL; + goto out_err; + } + params->log_blocksize = log_blocksize; + params->block_size = 1 << log_blocksize; + + if (WARN_ON(!is_power_of_2(params->digest_size))) { + err = -EINVAL; + goto out_err; + } + if (params->block_size < 2 * params->digest_size) { + fsverity_warn(inode, + "Merkle tree block size (%u) too small for hash algorithm \"%s\"", + params->block_size, hash_alg->name); + err = -EINVAL; + goto out_err; + } + params->log_arity = params->log_blocksize - ilog2(params->digest_size); + params->hashes_per_block = 1 << params->log_arity; + + pr_debug("Merkle tree uses %s with %u-byte blocks (%u hashes/block), salt=%*phN\n", + hash_alg->name, params->block_size, params->hashes_per_block, + (int)salt_size, salt); + + /* + * Compute the number of levels in the Merkle tree and create a map from + * level to the starting block of that level. Level 'num_levels - 1' is + * the root and is stored first. Level 0 is the level directly "above" + * the data blocks and is stored last. + */ + + /* Compute number of levels and the number of blocks in each level */ + blocks = (inode->i_size + params->block_size - 1) >> log_blocksize; + pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks); + while (blocks > 1) { + if (params->num_levels >= FS_VERITY_MAX_LEVELS) { + fsverity_err(inode, "Too many levels in Merkle tree"); + err = -EINVAL; + goto out_err; + } + blocks = (blocks + params->hashes_per_block - 1) >> + params->log_arity; + /* temporarily using level_start[] to store blocks in level */ + params->level_start[params->num_levels++] = blocks; + } + + /* Compute the starting block of each level */ + offset = 0; + for (level = (int)params->num_levels - 1; level >= 0; level--) { + blocks = params->level_start[level]; + params->level_start[level] = offset; + pr_debug("Level %d is %llu blocks starting at index %llu\n", + level, blocks, offset); + offset += blocks; + } + + params->tree_size = offset << log_blocksize; + return 0; + +out_err: + kfree(params->hashstate); + memset(params, 0, sizeof(*params)); + return err; +} + +/* Compute the file measurement by hashing the fsverity_descriptor. */ +static int compute_file_measurement(const struct fsverity_hash_alg *hash_alg, + const struct fsverity_descriptor *desc, + u8 *measurement) +{ + return fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), measurement); +} + +/* + * Validate the given fsverity_descriptor and create a new fsverity_info from + * it. + */ +struct fsverity_info *fsverity_create_info(const struct inode *inode, + const void *_desc, size_t desc_size) +{ + const struct fsverity_descriptor *desc = _desc; + struct fsverity_info *vi; + int err; + + if (desc_size < sizeof(*desc)) { + fsverity_err(inode, "Unrecognized descriptor size: %zu bytes", + desc_size); + return ERR_PTR(-EINVAL); + } + + if (desc->version != 1) { + fsverity_err(inode, "Unrecognized descriptor version: %u", + desc->version); + return ERR_PTR(-EINVAL); + } + + if (desc->sig_size || + memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) { + fsverity_err(inode, "Reserved bits set in descriptor"); + return ERR_PTR(-EINVAL); + } + + if (desc->salt_size > sizeof(desc->salt)) { + fsverity_err(inode, "Invalid salt_size: %u", desc->salt_size); + return ERR_PTR(-EINVAL); + } + + if (le64_to_cpu(desc->data_size) != inode->i_size) { + fsverity_err(inode, + "Wrong data_size: %llu (desc) != %lld (inode)", + le64_to_cpu(desc->data_size), inode->i_size); + return ERR_PTR(-EINVAL); + } + + vi = kmem_cache_zalloc(fsverity_info_cachep, GFP_KERNEL); + if (!vi) + return ERR_PTR(-ENOMEM); + vi->inode = inode; + + err = fsverity_init_merkle_tree_params(&vi->tree_params, inode, + desc->hash_algorithm, + desc->log_blocksize, + desc->salt, desc->salt_size); + if (err) { + fsverity_err(inode, + "Error %d initializing Merkle tree parameters", + err); + goto out; + } + + memcpy(vi->root_hash, desc->root_hash, vi->tree_params.digest_size); + + err = compute_file_measurement(vi->tree_params.hash_alg, desc, + vi->measurement); + if (err) { + fsverity_err(inode, "Error %d computing file measurement", err); + goto out; + } + pr_debug("Computed file measurement: %s:%*phN\n", + vi->tree_params.hash_alg->name, + vi->tree_params.digest_size, vi->measurement); +out: + if (err) { + fsverity_free_info(vi); + vi = ERR_PTR(err); + } + return vi; +} + +void fsverity_set_info(struct inode *inode, struct fsverity_info *vi) +{ + /* + * Multiple processes may race to set ->i_verity_info, so use cmpxchg. + * This pairs with the READ_ONCE() in fsverity_get_info(). + */ + if (cmpxchg(&inode->i_verity_info, NULL, vi) != NULL) + fsverity_free_info(vi); +} + +void fsverity_free_info(struct fsverity_info *vi) +{ + if (!vi) + return; + kfree(vi->tree_params.hashstate); + kmem_cache_free(fsverity_info_cachep, vi); +} + +/* Ensure the inode has an ->i_verity_info */ +static int ensure_verity_info(struct inode *inode) +{ + struct fsverity_info *vi = fsverity_get_info(inode); + struct fsverity_descriptor *desc; + int res; + + if (vi) + return 0; + + res = inode->i_sb->s_vop->get_verity_descriptor(inode, NULL, 0); + if (res < 0) { + fsverity_err(inode, + "Error %d getting verity descriptor size", res); + return res; + } + if (res > FS_VERITY_MAX_DESCRIPTOR_SIZE) { + fsverity_err(inode, "Verity descriptor is too large (%d bytes)", + res); + return -EMSGSIZE; + } + desc = kmalloc(res, GFP_KERNEL); + if (!desc) + return -ENOMEM; + res = inode->i_sb->s_vop->get_verity_descriptor(inode, desc, res); + if (res < 0) { + fsverity_err(inode, "Error %d reading verity descriptor", res); + goto out_free_desc; + } + + vi = fsverity_create_info(inode, desc, res); + if (IS_ERR(vi)) { + res = PTR_ERR(vi); + goto out_free_desc; + } + + fsverity_set_info(inode, vi); + res = 0; +out_free_desc: + kfree(desc); + return res; +} + +/** + * fsverity_file_open() - prepare to open a verity file + * @inode: the inode being opened + * @filp: the struct file being set up + * + * When opening a verity file, deny the open if it is for writing. Otherwise, + * set up the inode's ->i_verity_info if not already done. + * + * When combined with fscrypt, this must be called after fscrypt_file_open(). + * Otherwise, we won't have the key set up to decrypt the verity metadata. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_file_open(struct inode *inode, struct file *filp) +{ + if (!IS_VERITY(inode)) + return 0; + + if (filp->f_mode & FMODE_WRITE) { + pr_debug("Denying opening verity file (ino %lu) for write\n", + inode->i_ino); + return -EPERM; + } + + return ensure_verity_info(inode); +} +EXPORT_SYMBOL_GPL(fsverity_file_open); + +/** + * fsverity_cleanup_inode() - free the inode's verity info, if present + * + * Filesystems must call this on inode eviction to free ->i_verity_info. + */ +void fsverity_cleanup_inode(struct inode *inode) +{ + fsverity_free_info(inode->i_verity_info); + inode->i_verity_info = NULL; +} +EXPORT_SYMBOL_GPL(fsverity_cleanup_inode); + +int __init fsverity_init_info_cache(void) +{ + fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info, + SLAB_RECLAIM_ACCOUNT, + measurement); + if (!fsverity_info_cachep) + return -ENOMEM; + return 0; +} diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h new file mode 100644 index 000000000000..09b04dab6452 --- /dev/null +++ b/include/linux/fsverity.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * fs-verity: read-only file-based authenticity protection + * + * This header declares the interface between the fs/verity/ support layer and + * filesystems that support fs-verity. + * + * Copyright 2019 Google LLC + */ + +#ifndef _LINUX_FSVERITY_H +#define _LINUX_FSVERITY_H + +#include +#include + +/* Verity operations for filesystems */ +struct fsverity_operations { + + /** + * Get the verity descriptor of the given inode. + * + * @inode: an inode with the S_VERITY flag set + * @buf: buffer in which to place the verity descriptor + * @bufsize: size of @buf, or 0 to retrieve the size only + * + * If bufsize == 0, then the size of the verity descriptor is returned. + * Otherwise the verity descriptor is written to 'buf' and its actual + * size is returned; -ERANGE is returned if it's too large. This may be + * called by multiple processes concurrently on the same inode. + * + * Return: the size on success, -errno on failure + */ + int (*get_verity_descriptor)(struct inode *inode, void *buf, + size_t bufsize); +}; + +#ifdef CONFIG_FS_VERITY + +static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) +{ + /* pairs with the cmpxchg() in fsverity_set_info() */ + return READ_ONCE(inode->i_verity_info); +} + +/* open.c */ + +extern int fsverity_file_open(struct inode *inode, struct file *filp); +extern void fsverity_cleanup_inode(struct inode *inode); + +#else /* !CONFIG_FS_VERITY */ + +static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) +{ + return NULL; +} + +/* open.c */ + +static inline int fsverity_file_open(struct inode *inode, struct file *filp) +{ + return IS_VERITY(inode) ? -EOPNOTSUPP : 0; +} + +static inline void fsverity_cleanup_inode(struct inode *inode) +{ +} + +#endif /* !CONFIG_FS_VERITY */ + +#endif /* _LINUX_FSVERITY_H */ -- GitLab From c1d9b584e2cf3f0562d8fcf34574c044d17853a1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:22 -0700 Subject: [PATCH 0979/7155] fs-verity: add the hook for file ->setattr() Add a function fsverity_prepare_setattr() which filesystems that support fs-verity must call to deny truncates of verity files. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/open.c | 21 +++++++++++++++++++++ include/linux/fsverity.h | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/fs/verity/open.c b/fs/verity/open.c index 8013f77f907e..2cb2fe8082bf 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -295,6 +295,27 @@ int fsverity_file_open(struct inode *inode, struct file *filp) } EXPORT_SYMBOL_GPL(fsverity_file_open); +/** + * fsverity_prepare_setattr() - prepare to change a verity inode's attributes + * @dentry: dentry through which the inode is being changed + * @attr: attributes to change + * + * Verity files are immutable, so deny truncates. This isn't covered by the + * open-time check because sys_truncate() takes a path, not a file descriptor. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr) +{ + if (IS_VERITY(d_inode(dentry)) && (attr->ia_valid & ATTR_SIZE)) { + pr_debug("Denying truncate of verity file (ino %lu)\n", + d_inode(dentry)->i_ino); + return -EPERM; + } + return 0; +} +EXPORT_SYMBOL_GPL(fsverity_prepare_setattr); + /** * fsverity_cleanup_inode() - free the inode's verity info, if present * diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 09b04dab6452..cbd0f84e1620 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -46,6 +46,7 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) /* open.c */ extern int fsverity_file_open(struct inode *inode, struct file *filp); +extern int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr); extern void fsverity_cleanup_inode(struct inode *inode); #else /* !CONFIG_FS_VERITY */ @@ -62,6 +63,12 @@ static inline int fsverity_file_open(struct inode *inode, struct file *filp) return IS_VERITY(inode) ? -EOPNOTSUPP : 0; } +static inline int fsverity_prepare_setattr(struct dentry *dentry, + struct iattr *attr) +{ + return IS_VERITY(d_inode(dentry)) ? -EOPNOTSUPP : 0; +} + static inline void fsverity_cleanup_inode(struct inode *inode) { } -- GitLab From 8a1d0f9cacc997bedc017056a94f35dc823394ed Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:22 -0700 Subject: [PATCH 0980/7155] fs-verity: add data verification hooks for ->readpages() Add functions that verify data pages that have been read from a fs-verity file, against that file's Merkle tree. These will be called from filesystems' ->readpage() and ->readpages() methods. Since data verification can block, a workqueue is provided for these methods to enqueue verification work from their bio completion callback. See the "Verifying data" section of Documentation/filesystems/fsverity.rst for more information. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/Makefile | 3 +- fs/verity/fsverity_private.h | 5 + fs/verity/init.c | 8 + fs/verity/open.c | 6 + fs/verity/verify.c | 275 +++++++++++++++++++++++++++++++++++ include/linux/fsverity.h | 56 +++++++ 6 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 fs/verity/verify.c diff --git a/fs/verity/Makefile b/fs/verity/Makefile index e6a8951c493a..7fa628cd5eba 100644 --- a/fs/verity/Makefile +++ b/fs/verity/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_FS_VERITY) += hash_algs.o \ init.o \ - open.o + open.o \ + verify.o diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index c79746ff335e..eaa2b3b93bbf 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -134,5 +134,10 @@ void fsverity_set_info(struct inode *inode, struct fsverity_info *vi); void fsverity_free_info(struct fsverity_info *vi); int __init fsverity_init_info_cache(void); +void __init fsverity_exit_info_cache(void); + +/* verify.c */ + +int __init fsverity_init_workqueue(void); #endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/init.c b/fs/verity/init.c index fff1fd634335..b593805aafcc 100644 --- a/fs/verity/init.c +++ b/fs/verity/init.c @@ -41,7 +41,15 @@ static int __init fsverity_init(void) if (err) return err; + err = fsverity_init_workqueue(); + if (err) + goto err_exit_info_cache; + pr_debug("Initialized fs-verity\n"); return 0; + +err_exit_info_cache: + fsverity_exit_info_cache(); + return err; } late_initcall(fsverity_init) diff --git a/fs/verity/open.c b/fs/verity/open.c index 2cb2fe8082bf..3636a1ed8e2c 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -337,3 +337,9 @@ int __init fsverity_init_info_cache(void) return -ENOMEM; return 0; } + +void __init fsverity_exit_info_cache(void) +{ + kmem_cache_destroy(fsverity_info_cachep); + fsverity_info_cachep = NULL; +} diff --git a/fs/verity/verify.c b/fs/verity/verify.c new file mode 100644 index 000000000000..62ab8f6a8ea1 --- /dev/null +++ b/fs/verity/verify.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/verify.c: data verification functions, i.e. hooks for ->readpages() + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include +#include +#include + +static struct workqueue_struct *fsverity_read_workqueue; + +/** + * hash_at_level() - compute the location of the block's hash at the given level + * + * @params: (in) the Merkle tree parameters + * @dindex: (in) the index of the data block being verified + * @level: (in) the level of hash we want (0 is leaf level) + * @hindex: (out) the index of the hash block containing the wanted hash + * @hoffset: (out) the byte offset to the wanted hash within the hash block + */ +static void hash_at_level(const struct merkle_tree_params *params, + pgoff_t dindex, unsigned int level, pgoff_t *hindex, + unsigned int *hoffset) +{ + pgoff_t position; + + /* Offset of the hash within the level's region, in hashes */ + position = dindex >> (level * params->log_arity); + + /* Index of the hash block in the tree overall */ + *hindex = params->level_start[level] + (position >> params->log_arity); + + /* Offset of the wanted hash (in bytes) within the hash block */ + *hoffset = (position & ((1 << params->log_arity) - 1)) << + (params->log_blocksize - params->log_arity); +} + +/* Extract a hash from a hash page */ +static void extract_hash(struct page *hpage, unsigned int hoffset, + unsigned int hsize, u8 *out) +{ + void *virt = kmap_atomic(hpage); + + memcpy(out, virt + hoffset, hsize); + kunmap_atomic(virt); +} + +static inline int cmp_hashes(const struct fsverity_info *vi, + const u8 *want_hash, const u8 *real_hash, + pgoff_t index, int level) +{ + const unsigned int hsize = vi->tree_params.digest_size; + + if (memcmp(want_hash, real_hash, hsize) == 0) + return 0; + + fsverity_err(vi->inode, + "FILE CORRUPTED! index=%lu, level=%d, want_hash=%s:%*phN, real_hash=%s:%*phN", + index, level, + vi->tree_params.hash_alg->name, hsize, want_hash, + vi->tree_params.hash_alg->name, hsize, real_hash); + return -EBADMSG; +} + +/* + * Verify a single data page against the file's Merkle tree. + * + * In principle, we need to verify the entire path to the root node. However, + * for efficiency the filesystem may cache the hash pages. Therefore we need + * only ascend the tree until an already-verified page is seen, as indicated by + * the PageChecked bit being set; then verify the path to that page. + * + * This code currently only supports the case where the verity block size is + * equal to PAGE_SIZE. Doing otherwise would be possible but tricky, since we + * wouldn't be able to use the PageChecked bit. + * + * Note that multiple processes may race to verify a hash page and mark it + * Checked, but it doesn't matter; the result will be the same either way. + * + * Return: true if the page is valid, else false. + */ +static bool verify_page(struct inode *inode, const struct fsverity_info *vi, + struct ahash_request *req, struct page *data_page) +{ + const struct merkle_tree_params *params = &vi->tree_params; + const unsigned int hsize = params->digest_size; + const pgoff_t index = data_page->index; + int level; + u8 _want_hash[FS_VERITY_MAX_DIGEST_SIZE]; + const u8 *want_hash; + u8 real_hash[FS_VERITY_MAX_DIGEST_SIZE]; + struct page *hpages[FS_VERITY_MAX_LEVELS]; + unsigned int hoffsets[FS_VERITY_MAX_LEVELS]; + int err; + + if (WARN_ON_ONCE(!PageLocked(data_page) || PageUptodate(data_page))) + return false; + + pr_debug_ratelimited("Verifying data page %lu...\n", index); + + /* + * Starting at the leaf level, ascend the tree saving hash pages along + * the way until we find a verified hash page, indicated by PageChecked; + * or until we reach the root. + */ + for (level = 0; level < params->num_levels; level++) { + pgoff_t hindex; + unsigned int hoffset; + struct page *hpage; + + hash_at_level(params, index, level, &hindex, &hoffset); + + pr_debug_ratelimited("Level %d: hindex=%lu, hoffset=%u\n", + level, hindex, hoffset); + + hpage = inode->i_sb->s_vop->read_merkle_tree_page(inode, + hindex); + if (IS_ERR(hpage)) { + err = PTR_ERR(hpage); + fsverity_err(inode, + "Error %d reading Merkle tree page %lu", + err, hindex); + goto out; + } + + if (PageChecked(hpage)) { + extract_hash(hpage, hoffset, hsize, _want_hash); + want_hash = _want_hash; + put_page(hpage); + pr_debug_ratelimited("Hash page already checked, want %s:%*phN\n", + params->hash_alg->name, + hsize, want_hash); + goto descend; + } + pr_debug_ratelimited("Hash page not yet checked\n"); + hpages[level] = hpage; + hoffsets[level] = hoffset; + } + + want_hash = vi->root_hash; + pr_debug("Want root hash: %s:%*phN\n", + params->hash_alg->name, hsize, want_hash); +descend: + /* Descend the tree verifying hash pages */ + for (; level > 0; level--) { + struct page *hpage = hpages[level - 1]; + unsigned int hoffset = hoffsets[level - 1]; + + err = fsverity_hash_page(params, inode, req, hpage, real_hash); + if (err) + goto out; + err = cmp_hashes(vi, want_hash, real_hash, index, level - 1); + if (err) + goto out; + SetPageChecked(hpage); + extract_hash(hpage, hoffset, hsize, _want_hash); + want_hash = _want_hash; + put_page(hpage); + pr_debug("Verified hash page at level %d, now want %s:%*phN\n", + level - 1, params->hash_alg->name, hsize, want_hash); + } + + /* Finally, verify the data page */ + err = fsverity_hash_page(params, inode, req, data_page, real_hash); + if (err) + goto out; + err = cmp_hashes(vi, want_hash, real_hash, index, -1); +out: + for (; level > 0; level--) + put_page(hpages[level - 1]); + + return err == 0; +} + +/** + * fsverity_verify_page() - verify a data page + * + * Verify a page that has just been read from a verity file. The page must be a + * pagecache page that is still locked and not yet uptodate. + * + * Return: true if the page is valid, else false. + */ +bool fsverity_verify_page(struct page *page) +{ + struct inode *inode = page->mapping->host; + const struct fsverity_info *vi = inode->i_verity_info; + struct ahash_request *req; + bool valid; + + req = ahash_request_alloc(vi->tree_params.hash_alg->tfm, GFP_NOFS); + if (unlikely(!req)) + return false; + + valid = verify_page(inode, vi, req, page); + + ahash_request_free(req); + + return valid; +} +EXPORT_SYMBOL_GPL(fsverity_verify_page); + +#ifdef CONFIG_BLOCK +/** + * fsverity_verify_bio() - verify a 'read' bio that has just completed + * + * Verify a set of pages that have just been read from a verity file. The pages + * must be pagecache pages that are still locked and not yet uptodate. Pages + * that fail verification are set to the Error state. Verification is skipped + * for pages already in the Error state, e.g. due to fscrypt decryption failure. + * + * This is a helper function for use by the ->readpages() method of filesystems + * that issue bios to read data directly into the page cache. Filesystems that + * populate the page cache without issuing bios (e.g. non block-based + * filesystems) must instead call fsverity_verify_page() directly on each page. + * All filesystems must also call fsverity_verify_page() on holes. + */ +void fsverity_verify_bio(struct bio *bio) +{ + struct inode *inode = bio_first_page_all(bio)->mapping->host; + const struct fsverity_info *vi = inode->i_verity_info; + struct ahash_request *req; + struct bio_vec *bv; + struct bvec_iter_all iter_all; + + req = ahash_request_alloc(vi->tree_params.hash_alg->tfm, GFP_NOFS); + if (unlikely(!req)) { + bio_for_each_segment_all(bv, bio, iter_all) + SetPageError(bv->bv_page); + return; + } + + bio_for_each_segment_all(bv, bio, iter_all) { + struct page *page = bv->bv_page; + + if (!PageError(page) && !verify_page(inode, vi, req, page)) + SetPageError(page); + } + + ahash_request_free(req); +} +EXPORT_SYMBOL_GPL(fsverity_verify_bio); +#endif /* CONFIG_BLOCK */ + +/** + * fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue + * + * Enqueue verification work for asynchronous processing. + */ +void fsverity_enqueue_verify_work(struct work_struct *work) +{ + queue_work(fsverity_read_workqueue, work); +} +EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work); + +int __init fsverity_init_workqueue(void) +{ + /* + * Use an unbound workqueue to allow bios to be verified in parallel + * even when they happen to complete on the same CPU. This sacrifices + * locality, but it's worthwhile since hashing is CPU-intensive. + * + * Also use a high-priority workqueue to prioritize verification work, + * which blocks reads from completing, over regular application tasks. + */ + fsverity_read_workqueue = alloc_workqueue("fsverity_read_queue", + WQ_UNBOUND | WQ_HIGHPRI, + num_online_cpus()); + if (!fsverity_read_workqueue) + return -ENOMEM; + return 0; +} diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index cbd0f84e1620..95c257cd7ff0 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -33,6 +33,23 @@ struct fsverity_operations { */ int (*get_verity_descriptor)(struct inode *inode, void *buf, size_t bufsize); + + /** + * Read a Merkle tree page of the given inode. + * + * @inode: the inode + * @index: 0-based index of the page within the Merkle tree + * + * This can be called at any time on an open verity file, as well as + * between ->begin_enable_verity() and ->end_enable_verity(). It may be + * called by multiple processes concurrently, even with the same page. + * + * Note that this must retrieve a *page*, not necessarily a *block*. + * + * Return: the page on success, ERR_PTR() on failure + */ + struct page *(*read_merkle_tree_page)(struct inode *inode, + pgoff_t index); }; #ifdef CONFIG_FS_VERITY @@ -49,6 +66,12 @@ extern int fsverity_file_open(struct inode *inode, struct file *filp); extern int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr); extern void fsverity_cleanup_inode(struct inode *inode); +/* verify.c */ + +extern bool fsverity_verify_page(struct page *page); +extern void fsverity_verify_bio(struct bio *bio); +extern void fsverity_enqueue_verify_work(struct work_struct *work); + #else /* !CONFIG_FS_VERITY */ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) @@ -73,6 +96,39 @@ static inline void fsverity_cleanup_inode(struct inode *inode) { } +/* verify.c */ + +static inline bool fsverity_verify_page(struct page *page) +{ + WARN_ON(1); + return false; +} + +static inline void fsverity_verify_bio(struct bio *bio) +{ + WARN_ON(1); +} + +static inline void fsverity_enqueue_verify_work(struct work_struct *work) +{ + WARN_ON(1); +} + #endif /* !CONFIG_FS_VERITY */ +/** + * fsverity_active() - do reads from the inode need to go through fs-verity? + * + * This checks whether ->i_verity_info has been set. + * + * Filesystems call this from ->readpages() to check whether the pages need to + * be verified or not. Don't use IS_VERITY() for this purpose; it's subject to + * a race condition where the file is being read concurrently with + * FS_IOC_ENABLE_VERITY completing. (S_VERITY is set before ->i_verity_info.) + */ +static inline bool fsverity_active(const struct inode *inode) +{ + return fsverity_get_info(inode) != NULL; +} + #endif /* _LINUX_FSVERITY_H */ -- GitLab From d72e3dc7915fc6c54645772c13f4afc0e676c7e2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 26 Jul 2019 15:18:19 +0300 Subject: [PATCH 0981/7155] extcon: axp288: Add missed error check It seems from the very beginning the error check has been missed in axp288_extcon_log_rsi(). Add it here. Signed-off-by: Andy Shevchenko Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-axp288.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c index 7254852e6ec0..694a8d4a57ff 100644 --- a/drivers/extcon/extcon-axp288.c +++ b/drivers/extcon/extcon-axp288.c @@ -135,6 +135,11 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) int ret; ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val); + if (ret < 0) { + dev_err(info->dev, "failed to read reset source indicator\n"); + return; + } + for (i = 0, rsi = axp288_pwr_up_down_info; *rsi; rsi++, i++) { if (val & BIT(i)) { dev_dbg(info->dev, "%s\n", *rsi); -- GitLab From 21be848ebc5f3cb714b23c2528fbe73f69073c32 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 26 Jul 2019 15:18:20 +0300 Subject: [PATCH 0982/7155] extcon: axp288: Use for_each_set_bit() in axp288_extcon_log_rsi() This simplifies and standardizes axp288_extcon_log_rsi() by using for_each_set_bit() library function. Signed-off-by: Andy Shevchenko Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-axp288.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c index 694a8d4a57ff..415afaf479e7 100644 --- a/drivers/extcon/extcon-axp288.c +++ b/drivers/extcon/extcon-axp288.c @@ -121,7 +121,6 @@ static const char * const axp288_pwr_up_down_info[] = { "Last shutdown caused by PMIC UVLO threshold", "Last shutdown caused by SOC initiated cold off", "Last shutdown caused by user pressing the power button", - NULL, }; /* @@ -130,8 +129,8 @@ static const char * const axp288_pwr_up_down_info[] = { */ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) { - const char * const *rsi; unsigned int val, i, clear_mask = 0; + unsigned long bits; int ret; ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val); @@ -140,12 +139,10 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) return; } - for (i = 0, rsi = axp288_pwr_up_down_info; *rsi; rsi++, i++) { - if (val & BIT(i)) { - dev_dbg(info->dev, "%s\n", *rsi); - clear_mask |= BIT(i); - } - } + bits = val & GENMASK(ARRAY_SIZE(axp288_pwr_up_down_info) - 1, 0); + for_each_set_bit(i, &bits, ARRAY_SIZE(axp288_pwr_up_down_info)) + dev_dbg(info->dev, "%s\n", axp288_pwr_up_down_info[i]); + clear_mask = bits; /* Clear the register value for next reboot (write 1 to clear bit) */ regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask); -- GitLab From aac8670369dc017609b8e8870975641ad3143448 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 16 Jul 2019 11:24:58 +0300 Subject: [PATCH 0983/7155] dmaengine: ti: omap-dma: Readability cleanup in omap_dma_tx_status() The tx_status is most likely going to be asked for the current transfer, so check that first then try to fall back to lookup of non started transfers. In this way the code is a bit more readable and in most cases we will avoid to run vchan_find_desc() all the time. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190716082459.1222-2-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/omap-dma.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index 49da402a1927..80fd2667b2c8 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -833,10 +833,8 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, return ret; spin_lock_irqsave(&c->vc.lock, flags); - vd = vchan_find_desc(&c->vc, cookie); - if (vd) { - txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx)); - } else if (c->desc && c->desc->vd.tx.cookie == cookie) { + + if (c->desc && c->desc->vd.tx.cookie == cookie) { struct omap_desc *d = c->desc; dma_addr_t pos; @@ -848,11 +846,15 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, pos = 0; txstate->residue = omap_dma_desc_size_pos(d, pos); + } else if ((vd = vchan_find_desc(&c->vc, cookie))) { + txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx)); } else { txstate->residue = 0; } + if (ret == DMA_IN_PROGRESS && c->paused) ret = DMA_PAUSED; + spin_unlock_irqrestore(&c->vc.lock, flags); return ret; -- GitLab From 4689d35c765c696bdf0535486a990038b242a26b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 16 Jul 2019 11:24:59 +0300 Subject: [PATCH 0984/7155] dmaengine: ti: omap-dma: Improved memcpy polling support When a DMA client driver does not set the DMA_PREP_INTERRUPT because it does not want to use interrupts for DMA completion or because it can not rely on DMA interrupts due to executing the memcpy when interrupts are disabled it will poll the status of the transfer. If the interrupts are enabled then the cookie will be set completed in the interrupt handler so only check in HW completion when the polling is really needed. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190716082459.1222-3-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/omap-dma.c | 44 +++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index 80fd2667b2c8..a4a63425dc0b 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -91,6 +91,7 @@ struct omap_desc { bool using_ll; enum dma_transfer_direction dir; dma_addr_t dev_addr; + bool polled; int32_t fi; /* for OMAP_DMA_SYNC_PACKET / double indexing */ int16_t ei; /* for double indexing */ @@ -816,26 +817,20 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, struct virt_dma_desc *vd; enum dma_status ret; unsigned long flags; + struct omap_desc *d = NULL; ret = dma_cookie_status(chan, cookie, txstate); - - if (!c->paused && c->running) { - uint32_t ccr = omap_dma_chan_read(c, CCR); - /* - * The channel is no longer active, set the return value - * accordingly - */ - if (!(ccr & CCR_ENABLE)) - ret = DMA_COMPLETE; - } - - if (ret == DMA_COMPLETE || !txstate) + if (ret == DMA_COMPLETE) return ret; spin_lock_irqsave(&c->vc.lock, flags); + if (c->desc && c->desc->vd.tx.cookie == cookie) + d = c->desc; + + if (!txstate) + goto out; - if (c->desc && c->desc->vd.tx.cookie == cookie) { - struct omap_desc *d = c->desc; + if (d) { dma_addr_t pos; if (d->dir == DMA_MEM_TO_DEV) @@ -852,8 +847,22 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan, txstate->residue = 0; } - if (ret == DMA_IN_PROGRESS && c->paused) +out: + if (ret == DMA_IN_PROGRESS && c->paused) { ret = DMA_PAUSED; + } else if (d && d->polled && c->running) { + uint32_t ccr = omap_dma_chan_read(c, CCR); + /* + * The channel is no longer active, set the return value + * accordingly and mark it as completed + */ + if (!(ccr & CCR_ENABLE)) { + struct omap_desc *d = c->desc; + ret = DMA_COMPLETE; + omap_dma_start_desc(c); + vchan_cookie_complete(&d->vd); + } + } spin_unlock_irqrestore(&c->vc.lock, flags); @@ -1181,7 +1190,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy( d->ccr = c->ccr; d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC; - d->cicr = CICR_DROP_IE | CICR_FRAME_IE; + if (tx_flags & DMA_PREP_INTERRUPT) + d->cicr |= CICR_FRAME_IE; + else + d->polled = true; d->csdp = data_type; -- GitLab From e96b1f64ee2885acb8fb26325eb9743ad6c64696 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 16 Jul 2019 11:26:53 +0300 Subject: [PATCH 0985/7155] dmaengine: ti: edma: Clean up the 2x32bit array register accesses Introduce defines for getting the array index and the bit number within the 64bit array register pairs. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190716082655.1620-2-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 106 ++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index f2549ee3fb49..6d0e0bcc0379 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -132,6 +132,17 @@ #define EDMA_CONT_PARAMS_FIXED_EXACT 1002 #define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003 +/* + * 64bit array registers are split into two 32bit registers: + * reg0: channel/event 0-31 + * reg1: channel/event 32-63 + * + * bit 5 in the channel number tells the array index (0/1) + * bit 0-4 (0x1f) is the bit offset within the register + */ +#define EDMA_REG_ARRAY_INDEX(channel) ((channel) >> 5) +#define EDMA_CHANNEL_BIT(channel) (BIT((channel) & 0x1f)) + /* PaRAM slots are laid out like this */ struct edmacc_param { u32 opt; @@ -440,15 +451,14 @@ static void edma_setup_interrupt(struct edma_chan *echan, bool enable) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); if (enable) { - edma_shadow0_write_array(ecc, SH_ICR, channel >> 5, - BIT(channel & 0x1f)); - edma_shadow0_write_array(ecc, SH_IESR, channel >> 5, - BIT(channel & 0x1f)); + edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_IESR, idx, ch_bit); } else { - edma_shadow0_write_array(ecc, SH_IECR, channel >> 5, - BIT(channel & 0x1f)); + edma_shadow0_write_array(ecc, SH_IECR, idx, ch_bit); } } @@ -586,26 +596,26 @@ static void edma_start(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); if (!echan->hw_triggered) { /* EDMA channels without event association */ - dev_dbg(ecc->dev, "ESR%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_ESR, j)); - edma_shadow0_write_array(ecc, SH_ESR, j, mask); + dev_dbg(ecc->dev, "ESR%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ESR, idx)); + edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit); } else { /* EDMA channel with event association */ - dev_dbg(ecc->dev, "ER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_ER, j)); + dev_dbg(ecc->dev, "ER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ER, idx)); /* Clear any pending event or error */ - edma_write_array(ecc, EDMA_ECR, j, mask); - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_write_array(ecc, EDMA_ECR, idx, ch_bit); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* Clear any SER */ - edma_shadow0_write_array(ecc, SH_SECR, j, mask); - edma_shadow0_write_array(ecc, SH_EESR, j, mask); - dev_dbg(ecc->dev, "EER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_EER, j)); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_EESR, idx, ch_bit); + dev_dbg(ecc->dev, "EER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_EER, idx)); } } @@ -613,19 +623,19 @@ static void edma_stop(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - edma_shadow0_write_array(ecc, SH_EECR, j, mask); - edma_shadow0_write_array(ecc, SH_ECR, j, mask); - edma_shadow0_write_array(ecc, SH_SECR, j, mask); - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_shadow0_write_array(ecc, SH_EECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* clear possibly pending completion interrupt */ - edma_shadow0_write_array(ecc, SH_ICR, j, mask); + edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit); - dev_dbg(ecc->dev, "EER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_EER, j)); + dev_dbg(ecc->dev, "EER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_EER, idx)); /* REVISIT: consider guarding against inappropriate event * chaining by overwriting with dummy_paramset. @@ -639,45 +649,49 @@ static void edma_stop(struct edma_chan *echan) static void edma_pause(struct edma_chan *echan) { int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); - edma_shadow0_write_array(echan->ecc, SH_EECR, channel >> 5, mask); + edma_shadow0_write_array(echan->ecc, SH_EECR, + EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); } /* Re-enable EDMA hardware events on the specified channel. */ static void edma_resume(struct edma_chan *echan) { int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); - edma_shadow0_write_array(echan->ecc, SH_EESR, channel >> 5, mask); + edma_shadow0_write_array(echan->ecc, SH_EESR, + EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); } static void edma_trigger_channel(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - edma_shadow0_write_array(ecc, SH_ESR, (channel >> 5), mask); + edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit); - dev_dbg(ecc->dev, "ESR%d %08x\n", (channel >> 5), - edma_shadow0_read_array(ecc, SH_ESR, (channel >> 5))); + dev_dbg(ecc->dev, "ESR%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ESR, idx)); } static void edma_clean_channel(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - dev_dbg(ecc->dev, "EMR%d %08x\n", j, edma_read_array(ecc, EDMA_EMR, j)); - edma_shadow0_write_array(ecc, SH_ECR, j, mask); + dev_dbg(ecc->dev, "EMR%d %08x\n", idx, + edma_read_array(ecc, EDMA_EMR, idx)); + edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit); /* Clear the corresponding EMR bits */ - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* Clear any SER */ - edma_shadow0_write_array(ecc, SH_SECR, j, mask); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); edma_write(ecc, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0)); } @@ -707,7 +721,8 @@ static int edma_alloc_channel(struct edma_chan *echan, int channel = EDMA_CHAN_SLOT(echan->ch_num); /* ensure access through shadow region 0 */ - edma_or_array2(ecc, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f)); + edma_or_array2(ecc, EDMA_DRAE, 0, EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); /* ensure no events are pending */ edma_stop(echan); @@ -2483,8 +2498,9 @@ static int edma_pm_resume(struct device *dev) for (i = 0; i < ecc->num_channels; i++) { if (echan[i].alloced) { /* ensure access through shadow region 0 */ - edma_or_array2(ecc, EDMA_DRAE, 0, i >> 5, - BIT(i & 0x1f)); + edma_or_array2(ecc, EDMA_DRAE, 0, + EDMA_REG_ARRAY_INDEX(i), + EDMA_CHANNEL_BIT(i)); edma_setup_interrupt(&echan[i], true); -- GitLab From 097ffdc75259139ba157b7f924cfeb0d6b00559e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 16 Jul 2019 11:26:54 +0300 Subject: [PATCH 0986/7155] dmaengine: ti: edma: Correct the residue calculation (fix for memcpy) For memcpy we never stored the start address of the transfer for the pset which rendered the memcpy residue calculation completely broken. In the edma_residue() function we also need to to some correction for the calculations: Instead waiting for all EDMA channels to be idle (in a busy system it can take few iteration to hit a point when all queues are idle) wait for the event pending on the given channel (SH_ER for hw synchronized channels, SH_ESR for manually triggered channels). If the position returned by EMDA is 0 it implies that the last paRAM set has been consumed and we are at the closing dummy set, thus we can conclude that the transfer is completed and we can return 0 as residue. Signed-off-by: Peter Ujfalusi [vkoul: fixed typo in commit log] Link: https://lore.kernel.org/r/20190716082655.1620-3-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index 6d0e0bcc0379..201b838ec808 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -1025,6 +1025,7 @@ static int edma_config_pset(struct dma_chan *chan, struct edma_pset *epset, src_cidx = cidx; dst_bidx = acnt; dst_cidx = cidx; + epset->addr = src_addr; } else { dev_err(dev, "%s: direction not implemented yet\n", __func__); return -EINVAL; @@ -1735,7 +1736,11 @@ static u32 edma_residue(struct edma_desc *edesc) int loop_count = EDMA_MAX_TR_WAIT_LOOPS; struct edma_chan *echan = edesc->echan; struct edma_pset *pset = edesc->pset; - dma_addr_t done, pos; + dma_addr_t done, pos, pos_old; + int channel = EDMA_CHAN_SLOT(echan->ch_num); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); + int event_reg; int i; /* @@ -1748,16 +1753,20 @@ static u32 edma_residue(struct edma_desc *edesc) * "pos" may represent a transfer request that is still being * processed by the EDMACC or EDMATC. We will busy wait until * any one of the situations occurs: - * 1. the DMA hardware is idle - * 2. a new transfer request is setup + * 1. while and event is pending for the channel + * 2. a position updated * 3. we hit the loop limit */ - while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) { - /* check if a new transfer request is setup */ - if (edma_get_position(echan->ecc, - echan->slot[0], dst) != pos) { + if (is_slave_direction(edesc->direction)) + event_reg = SH_ER; + else + event_reg = SH_ESR; + + pos_old = pos; + while (edma_shadow0_read_array(echan->ecc, event_reg, idx) & ch_bit) { + pos = edma_get_position(echan->ecc, echan->slot[0], dst); + if (pos != pos_old) break; - } if (!--loop_count) { dev_dbg_ratelimited(echan->vchan.chan.device->dev, @@ -1782,6 +1791,12 @@ static u32 edma_residue(struct edma_desc *edesc) return edesc->residue_stat; } + /* + * If the position is 0, then EDMA loaded the closing dummy slot, the + * transfer is completed + */ + if (!pos) + return 0; /* * For SG operation we catch up with the last processed * status. -- GitLab From aa3c6ce4eab8fb0e967954be1ba1cad3b715f63b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 16 Jul 2019 11:26:55 +0300 Subject: [PATCH 0987/7155] dmaengine: ti: edma: Support for polled (memcpy) completion When a DMA client driver does not set the DMA_PREP_INTERRUPT because it does not want to use interrupts for DMA completion or because it can not rely on DMA interrupts due to executing the memcpy when interrupts are disabled it will poll the status of the transfer. Since we can not tell from any EDMA register that the transfer is completed, we can only know that the paRAM set has been sent to TPTC for processing we need to check the residue of the transfer, if it is 0 then the transfer is completed. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190716082655.1620-4-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index 201b838ec808..fe468e2f7e67 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -179,6 +179,7 @@ struct edma_desc { struct list_head node; enum dma_transfer_direction direction; int cyclic; + bool polled; int absync; int pset_nr; struct edma_chan *echan; @@ -1226,8 +1227,9 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( edesc->pset[0].param.opt |= ITCCHEN; if (nslots == 1) { - /* Enable transfer complete interrupt */ - edesc->pset[0].param.opt |= TCINTEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + edesc->pset[0].param.opt |= TCINTEN; } else { /* Enable transfer complete chaining for the first slot */ edesc->pset[0].param.opt |= TCCHEN; @@ -1254,9 +1256,14 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( } edesc->pset[1].param.opt |= ITCCHEN; - edesc->pset[1].param.opt |= TCINTEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + edesc->pset[1].param.opt |= TCINTEN; } + if (!(tx_flags & DMA_PREP_INTERRUPT)) + edesc->polled = true; + return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); } @@ -1826,18 +1833,40 @@ static enum dma_status edma_tx_status(struct dma_chan *chan, { struct edma_chan *echan = to_edma_chan(chan); struct virt_dma_desc *vdesc; + struct dma_tx_state txstate_tmp; enum dma_status ret; unsigned long flags; ret = dma_cookie_status(chan, cookie, txstate); - if (ret == DMA_COMPLETE || !txstate) + + if (ret == DMA_COMPLETE) return ret; + /* Provide a dummy dma_tx_state for completion checking */ + if (!txstate) + txstate = &txstate_tmp; + + txstate->residue = 0; spin_lock_irqsave(&echan->vchan.lock, flags); if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) txstate->residue = edma_residue(echan->edesc); else if ((vdesc = vchan_find_desc(&echan->vchan, cookie))) txstate->residue = to_edma_desc(&vdesc->tx)->residue; + + /* + * Mark the cookie completed if the residue is 0 for non cyclic + * transfers + */ + if (ret != DMA_COMPLETE && !txstate->residue && + echan->edesc && echan->edesc->polled && + echan->edesc->vdesc.tx.cookie == cookie) { + edma_stop(echan); + vchan_cookie_complete(&echan->edesc->vdesc); + echan->edesc = NULL; + edma_execute(echan); + ret = DMA_COMPLETE; + } + spin_unlock_irqrestore(&echan->vchan.lock, flags); return ret; -- GitLab From b37e3534ac4275c1f0d0e08d1b6f672f6cc740c3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 20 Jul 2019 11:26:05 +0200 Subject: [PATCH 0988/7155] dt-bindings: dmaengine: Add YAML schemas for the generic DMA bindings The DMA controllers and consumers have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Signed-off-by: Maxime Ripard Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20190720092607.31095-1-maxime.ripard@bootlin.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/dma-common.yaml | 45 +++++++ .../bindings/dma/dma-controller.yaml | 35 ++++++ .../devicetree/bindings/dma/dma-router.yaml | 50 ++++++++ Documentation/devicetree/bindings/dma/dma.txt | 114 +----------------- 4 files changed, 131 insertions(+), 113 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/dma-common.yaml create mode 100644 Documentation/devicetree/bindings/dma/dma-controller.yaml create mode 100644 Documentation/devicetree/bindings/dma/dma-router.yaml diff --git a/Documentation/devicetree/bindings/dma/dma-common.yaml b/Documentation/devicetree/bindings/dma/dma-common.yaml new file mode 100644 index 000000000000..0141af047820 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/dma-common.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/dma-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DMA Engine Generic Binding + +maintainers: + - Vinod Koul + +description: + Generic binding to provide a way for a driver using DMA Engine to + retrieve the DMA request or channel information that goes from a + hardware device to a DMA controller. + +select: false + +properties: + "#dma-cells": + minimum: 1 + # Should be enough + maximum: 255 + description: + Used to provide DMA controller specific information. + + dma-channel-masks: + $ref: /schemas/types.yaml#definitions/uint32 + description: + Bitmask of available DMA channels in ascending order that are + not reserved by firmware and are available to the + kernel. i.e. first channel corresponds to LSB. + + dma-channels: + $ref: /schemas/types.yaml#definitions/uint32 + description: + Number of DMA channels supported by the controller. + + dma-requests: + $ref: /schemas/types.yaml#definitions/uint32 + description: + Number of DMA request signals supported by the controller. + +required: + - "#dma-cells" diff --git a/Documentation/devicetree/bindings/dma/dma-controller.yaml b/Documentation/devicetree/bindings/dma/dma-controller.yaml new file mode 100644 index 000000000000..c39f6de76670 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/dma-controller.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/dma-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DMA Controller Generic Binding + +maintainers: + - Vinod Koul + +allOf: + - $ref: "dma-common.yaml#" + +# Everything else is described in the common file +properties: + $nodename: + pattern: "^dma-controller(@.*)?$" + +examples: + - | + dma: dma-controller@48000000 { + compatible = "ti,omap-sdma"; + reg = <0x48000000 0x1000>; + interrupts = <0 12 0x4 + 0 13 0x4 + 0 14 0x4 + 0 15 0x4>; + #dma-cells = <1>; + dma-channels = <32>; + dma-requests = <127>; + dma-channel-mask = <0xfffe>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/dma-router.yaml b/Documentation/devicetree/bindings/dma/dma-router.yaml new file mode 100644 index 000000000000..5b5f07393135 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/dma-router.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/dma-router.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DMA Router Generic Binding + +maintainers: + - Vinod Koul + +allOf: + - $ref: "dma-common.yaml#" + +description: + DMA routers are transparent IP blocks used to route DMA request + lines from devices to the DMA controller. Some SoCs (like TI DRA7x) + have more peripherals integrated with DMA requests than what the DMA + controller can handle directly. + +properties: + $nodename: + pattern: "^dma-router(@.*)?$" + + dma-masters: + $ref: /schemas/types.yaml#definitions/phandle-array + description: + Array of phandles to the DMA controllers the router can direct + the signal to. + + dma-requests: + description: + Number of incoming request lines the router can handle. + +required: + - "#dma-cells" + - dma-masters + +examples: + - | + sdma_xbar: dma-router@4a002b78 { + compatible = "ti,dra7-dma-crossbar"; + reg = <0x4a002b78 0xfc>; + #dma-cells = <1>; + dma-requests = <205>; + ti,dma-safe-map = <0>; + dma-masters = <&sdma>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt index eeb4e4d1771e..90a67a016a48 100644 --- a/Documentation/devicetree/bindings/dma/dma.txt +++ b/Documentation/devicetree/bindings/dma/dma.txt @@ -1,113 +1 @@ -* Generic DMA Controller and DMA request bindings - -Generic binding to provide a way for a driver using DMA Engine to retrieve the -DMA request or channel information that goes from a hardware device to a DMA -controller. - - -* DMA controller - -Required property: -- #dma-cells: Must be at least 1. Used to provide DMA controller - specific information. See DMA client binding below for - more details. - -Optional properties: -- dma-channels: Number of DMA channels supported by the controller. -- dma-requests: Number of DMA request signals supported by the - controller. -- dma-channel-mask: Bitmask of available DMA channels in ascending order - that are not reserved by firmware and are available to - the kernel. i.e. first channel corresponds to LSB. - -Example: - - dma: dma@48000000 { - compatible = "ti,omap-sdma"; - reg = <0x48000000 0x1000>; - interrupts = <0 12 0x4 - 0 13 0x4 - 0 14 0x4 - 0 15 0x4>; - #dma-cells = <1>; - dma-channels = <32>; - dma-requests = <127>; - dma-channel-mask = <0xfffe> - }; - -* DMA router - -DMA routers are transparent IP blocks used to route DMA request lines from -devices to the DMA controller. Some SoCs (like TI DRA7x) have more peripherals -integrated with DMA requests than what the DMA controller can handle directly. - -Required property: -- dma-masters: phandle of the DMA controller or list of phandles for - the DMA controllers the router can direct the signal to. -- #dma-cells: Must be at least 1. Used to provide DMA router specific - information. See DMA client binding below for more - details. - -Optional properties: -- dma-requests: Number of incoming request lines the router can handle. -- In the node pointed by the dma-masters: - - dma-requests: The router driver might need to look for this in order - to configure the routing. - -Example: - sdma_xbar: dma-router@4a002b78 { - compatible = "ti,dra7-dma-crossbar"; - reg = <0x4a002b78 0xfc>; - #dma-cells = <1>; - dma-requests = <205>; - ti,dma-safe-map = <0>; - dma-masters = <&sdma>; - }; - -* DMA client - -Client drivers should specify the DMA property using a phandle to the controller -followed by DMA controller specific data. - -Required property: -- dmas: List of one or more DMA specifiers, each consisting of - - A phandle pointing to DMA controller node - - A number of integer cells, as determined by the - #dma-cells property in the node referenced by phandle - containing DMA controller specific information. This - typically contains a DMA request line number or a - channel number, but can contain any data that is - required for configuring a channel. -- dma-names: Contains one identifier string for each DMA specifier in - the dmas property. The specific strings that can be used - are defined in the binding of the DMA client device. - Multiple DMA specifiers can be used to represent - alternatives and in this case the dma-names for those - DMA specifiers must be identical (see examples). - -Examples: - -1. A device with one DMA read channel, one DMA write channel: - - i2c1: i2c@1 { - ... - dmas = <&dma 2 /* read channel */ - &dma 3>; /* write channel */ - dma-names = "rx", "tx"; - ... - }; - -2. A single read-write channel with three alternative DMA controllers: - - dmas = <&dma1 5 - &dma2 7 - &dma3 2>; - dma-names = "rx-tx", "rx-tx", "rx-tx"; - -3. A device with three channels, one of which has two alternatives: - - dmas = <&dma1 2 /* read channel */ - &dma1 3 /* write channel */ - &dma2 0 /* error read */ - &dma3 0>; /* alternative error read */ - dma-names = "rx", "tx", "error", "error"; +This file has been moved to dma-controller.yaml. -- GitLab From 545a29c811f6a07433c2725a94243f56ae28a81f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 20 Jul 2019 11:26:06 +0200 Subject: [PATCH 0989/7155] dt-bindings: dmaengine: Convert Allwinner A10 DMA to a schema The older Allwinner SoCs have a DMA controller supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20190720092607.31095-2-maxime.ripard@bootlin.com Signed-off-by: Vinod Koul --- .../bindings/dma/allwinner,sun4i-a10-dma.yaml | 55 +++++++++++++++++++ .../devicetree/bindings/dma/sun4i-dma.txt | 45 --------------- 2 files changed, 55 insertions(+), 45 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml delete mode 100644 Documentation/devicetree/bindings/dma/sun4i-dma.txt diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml new file mode 100644 index 000000000000..15abc0f9429f --- /dev/null +++ b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/allwinner,sun4i-a10-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 DMA Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 2 + description: + The first cell is either 0 or 1, the former to use the normal + DMA, 1 for dedicated DMA. The second cell is the request line + number. + + compatible: + const: allwinner,sun4i-a10-dma + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - "#dma-cells" + - compatible + - reg + - interrupts + - clocks + +additionalProperties: false + +examples: + - | + dma: dma-controller@1c02000 { + compatible = "allwinner,sun4i-a10-dma"; + reg = <0x01c02000 0x1000>; + interrupts = <27>; + clocks = <&ahb_gates 6>; + #dma-cells = <2>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/sun4i-dma.txt b/Documentation/devicetree/bindings/dma/sun4i-dma.txt deleted file mode 100644 index 8ad556aca70b..000000000000 --- a/Documentation/devicetree/bindings/dma/sun4i-dma.txt +++ /dev/null @@ -1,45 +0,0 @@ -Allwinner A10 DMA Controller - -This driver follows the generic DMA bindings defined in dma.txt. - -Required properties: - -- compatible: Must be "allwinner,sun4i-a10-dma" -- reg: Should contain the registers base address and length -- interrupts: Should contain a reference to the interrupt used by this device -- clocks: Should contain a reference to the parent AHB clock -- #dma-cells : Should be 2, first cell denoting normal or dedicated dma, - second cell holding the request line number. - -Example: - dma: dma-controller@1c02000 { - compatible = "allwinner,sun4i-a10-dma"; - reg = <0x01c02000 0x1000>; - interrupts = <27>; - clocks = <&ahb_gates 6>; - #dma-cells = <2>; - }; - -Clients: - -DMA clients connected to the Allwinner A10 DMA controller must use the -format described in the dma.txt file, using a three-cell specifier for -each channel: a phandle plus two integer cells. -The three cells in order are: - -1. A phandle pointing to the DMA controller. -2. Whether it is using normal (0) or dedicated (1) channels -3. The port ID as specified in the datasheet - -Example: - spi2: spi@1c17000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c17000 0x1000>; - interrupts = <0 12 4>; - clocks = <&ahb_gates 22>, <&spi2_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma 1 29>, <&dma 1 28>; - dma-names = "rx", "tx"; - #address-cells = <1>; - #size-cells = <0>; - }; -- GitLab From edd14218bd663e4dd2f1c8f4eed84f92ada93c9d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 20 Jul 2019 11:26:07 +0200 Subject: [PATCH 0990/7155] dt-bindings: dmaengine: Convert Allwinner A31 and A64 DMA to a schema The newer Allwinner SoCs have a DMA controller supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20190720092607.31095-3-maxime.ripard@bootlin.com Signed-off-by: Vinod Koul --- .../dma/allwinner,sun50i-a64-dma.yaml | 88 +++++++++++++++++++ .../bindings/dma/allwinner,sun6i-a31-dma.yaml | 62 +++++++++++++ .../devicetree/bindings/dma/sun6i-dma.txt | 81 ----------------- 3 files changed, 150 insertions(+), 81 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml create mode 100644 Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml delete mode 100644 Documentation/devicetree/bindings/dma/sun6i-dma.txt diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml new file mode 100644 index 000000000000..4cb9d6b93138 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/allwinner,sun50i-a64-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A64 DMA Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 1 + description: The cell is the request line number. + + compatible: + enum: + - allwinner,sun50i-a64-dma + - allwinner,sun50i-h6-dma + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + items: + - const: bus + - const: mbus + + resets: + maxItems: 1 + +required: + - "#dma-cells" + - compatible + - reg + - interrupts + - clocks + - resets + - dma-channels + +if: + properties: + compatible: + const: allwinner,sun50i-h6-dma + +then: + properties: + clocks: + maxItems: 2 + + required: + - clock-names + +else: + properties: + clocks: + maxItems: 1 + +# FIXME: We should set it, but it would report all the generic +# properties as additional properties. +# additionalProperties: false + +examples: + - | + dma: dma-controller@1c02000 { + compatible = "allwinner,sun50i-a64-dma"; + reg = <0x01c02000 0x1000>; + interrupts = <0 50 4>; + clocks = <&ccu 30>; + dma-channels = <8>; + dma-requests = <27>; + resets = <&ccu 7>; + #dma-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml new file mode 100644 index 000000000000..740b7f9b535b --- /dev/null +++ b/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/allwinner,sun6i-a31-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 DMA Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 1 + description: The cell is the request line number. + + compatible: + oneOf: + - const: allwinner,sun6i-a31-dma + - const: allwinner,sun8i-a23-dma + - const: allwinner,sun8i-a83t-dma + - const: allwinner,sun8i-h3-dma + - const: allwinner,sun8i-v3s-dma + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - "#dma-cells" + - compatible + - reg + - interrupts + - clocks + - resets + +additionalProperties: false + +examples: + - | + dma: dma-controller@1c02000 { + compatible = "allwinner,sun6i-a31-dma"; + reg = <0x01c02000 0x1000>; + interrupts = <0 50 4>; + clocks = <&ahb1_gates 6>; + resets = <&ahb1_rst 6>; + #dma-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt deleted file mode 100644 index cae31f4e77ba..000000000000 --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt +++ /dev/null @@ -1,81 +0,0 @@ -Allwinner A31 DMA Controller - -This driver follows the generic DMA bindings defined in dma.txt. - -Required properties: - -- compatible: Must be one of - "allwinner,sun6i-a31-dma" - "allwinner,sun8i-a23-dma" - "allwinner,sun8i-a83t-dma" - "allwinner,sun8i-h3-dma" - "allwinner,sun8i-v3s-dma" -- reg: Should contain the registers base address and length -- interrupts: Should contain a reference to the interrupt used by this device -- clocks: Should contain a reference to the parent AHB clock -- resets: Should contain a reference to the reset controller asserting - this device in reset -- #dma-cells : Should be 1, a single cell holding a line request number - -Example: - dma: dma-controller@1c02000 { - compatible = "allwinner,sun6i-a31-dma"; - reg = <0x01c02000 0x1000>; - interrupts = <0 50 4>; - clocks = <&ahb1_gates 6>; - resets = <&ahb1_rst 6>; - #dma-cells = <1>; - }; - ------------------------------------------------------------------------------- -For A64 and H6 DMA controller: - -Required properties: -- compatible: Must be one of - "allwinner,sun50i-a64-dma" - "allwinner,sun50i-h6-dma" -- dma-channels: Number of DMA channels supported by the controller. - Refer to Documentation/devicetree/bindings/dma/dma.txt -- clocks: In addition to parent AHB clock, it should also contain mbus - clock (H6 only) -- clock-names: Should contain "bus" and "mbus" (H6 only) -- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells - -Optional properties: -- dma-requests: Number of DMA request signals supported by the controller. - Refer to Documentation/devicetree/bindings/dma/dma.txt - -Example: - dma: dma-controller@1c02000 { - compatible = "allwinner,sun50i-a64-dma"; - reg = <0x01c02000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_DMA>; - dma-channels = <8>; - dma-requests = <27>; - resets = <&ccu RST_BUS_DMA>; - #dma-cells = <1>; - }; ------------------------------------------------------------------------------- - -Clients: - -DMA clients connected to the A31 DMA controller must use the format -described in the dma.txt file, using a two-cell specifier for each -channel: a phandle plus one integer cells. -The two cells in order are: - -1. A phandle pointing to the DMA controller. -2. The port ID as specified in the datasheet - -Example: -spi2: spi@1c6a000 { - compatible = "allwinner,sun6i-a31-spi"; - reg = <0x01c6a000 0x1000>; - interrupts = <0 67 4>; - clocks = <&ahb1_gates 22>, <&spi2_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma 25>, <&dma 25>; - dma-names = "rx", "tx"; - resets = <&ahb1_rst 22>; -}; -- GitLab From ffbb569b9cee1fa0277a48d7925dbed1356dbb32 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 24 Jul 2019 13:49:46 +0200 Subject: [PATCH 0991/7155] dt-bindings: dmaengine: shdma: Rename bindings documentation file Rename the bindings documentation file for shdma from shdma.txt to renesas,shdma.txt. This is part of an ongoing effort to name bindings documentation files for Renesas IP blocks consistently, in line with the compat strings they document. Signed-off-by: Simon Horman Link: https://lore.kernel.org/r/20190724114946.14021-1-horms+renesas@verge.net.au [vkoul: add subsystem name] Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/{shdma.txt => renesas,shdma.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/dma/{shdma.txt => renesas,shdma.txt} (100%) diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/renesas,shdma.txt similarity index 100% rename from Documentation/devicetree/bindings/dma/shdma.txt rename to Documentation/devicetree/bindings/dma/renesas,shdma.txt -- GitLab From 2cb114c4fac7a9c3e8fd8c39ceac1e6ca030b412 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:07:56 +0300 Subject: [PATCH 0992/7155] dmaengine: stm32-dmamux: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190723190757.67351-1-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dmamux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index b552949da14b..3c89bd39e096 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -185,8 +185,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev) if (!node) return -ENODEV; - count = device_property_read_u32_array(&pdev->dev, "dma-masters", - NULL, 0); + count = device_property_count_u32(&pdev->dev, "dma-masters"); if (count < 0) { dev_err(&pdev->dev, "Can't get DMA master(s) node\n"); return -ENODEV; -- GitLab From 57dbd0e4b97d3bc9f257159a8853badff2dfb0d1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:07:57 +0300 Subject: [PATCH 0993/7155] dmaengine: stm32-mdma: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190723190757.67351-2-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index d6e919d3936a..0d56fde78c1f 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1555,8 +1555,7 @@ static int stm32_mdma_probe(struct platform_device *pdev) nr_requests); } - count = device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks", - NULL, 0); + count = device_property_count_u32(&pdev->dev, "st,ahb-addr-masks"); if (count < 0) count = 0; -- GitLab From f474808acb3c4b30552d9c59b181244e0300d218 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Jul 2019 09:14:22 +0200 Subject: [PATCH 0994/7155] ALSA: aoa: onyx: always initialize register read value A lot of places in the driver use onyx_read_register() without checking the return value, and it's been working OK for ~10 years or so, so probably never fails ... Rather than trying to check the return value everywhere, which would be relatively intrusive, at least make sure we don't use an uninitialized value. Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") Reported-by: Stephen Rothwell Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai --- sound/aoa/codecs/onyx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index db917546965d..9827bee109c1 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -71,8 +71,10 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) return 0; } v = i2c_smbus_read_byte_data(onyx->i2c, reg); - if (v < 0) + if (v < 0) { + *value = 0; return -1; + } *value = (u8)v; onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; return 0; -- GitLab From 282420eed23f237963f2033b2f2bedb90fbcc5e1 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:40:23 +0200 Subject: [PATCH 0995/7155] clk: meson: axg-audio: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. A recent patch [0] allows parents to be specified without string names or with device-tree clock name by using a new assignment structure. Migrate to the new way by using .parent_hws where possible (when parent clocks are localy declared in the controller) and use .parent_data otherwise. Remove clk input helper and all bypass clocks (declared in probe function) which are no longer used since we are able to use device-tree clock name directly. [0] commit fc0c209c147f ("clk: Allow parents to be specified without string names") Signed-off-by: Alexandre Mergnat [jbrunet@baylibre.com: remove CLK_SET_RATE_PARENT from mst muxes] Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 1 - drivers/clk/meson/axg-audio.c | 261 ++++++++++++++++------------------ 2 files changed, 120 insertions(+), 142 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index a6b20e123e0c..ee0b84b6b329 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -86,7 +86,6 @@ config COMMON_CLK_AXG config COMMON_CLK_AXG_AUDIO tristate "Meson AXG Audio Clock Controller Driver" depends on ARCH_MESON - select COMMON_CLK_MESON_INPUT select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_PHASE select COMMON_CLK_MESON_SCLK_DIV diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c index 8028ff6f6610..741df7e955ca 100644 --- a/drivers/clk/meson/axg-audio.c +++ b/drivers/clk/meson/axg-audio.c @@ -15,7 +15,6 @@ #include #include "axg-audio.h" -#include "clk-input.h" #include "clk-regmap.h" #include "clk-phase.h" #include "sclk-div.h" @@ -24,7 +23,7 @@ #define AUD_SLV_SCLK_COUNT 10 #define AUD_SLV_LRCLK_COUNT 10 -#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) \ +#define AUD_GATE(_name, _reg, _bit, _phws, _iflags) \ struct clk_regmap aud_##_name = { \ .data = &(struct clk_regmap_gate_data){ \ .offset = (_reg), \ @@ -33,13 +32,13 @@ struct clk_regmap aud_##_name = { \ .hw.init = &(struct clk_init_data) { \ .name = "aud_"#_name, \ .ops = &clk_regmap_gate_ops, \ - .parent_names = (const char *[]){ _pname }, \ + .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \ .num_parents = 1, \ .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \ }, \ } -#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \ +#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) \ struct clk_regmap aud_##_name = { \ .data = &(struct clk_regmap_mux_data){ \ .offset = (_reg), \ @@ -50,13 +49,13 @@ struct clk_regmap aud_##_name = { \ .hw.init = &(struct clk_init_data){ \ .name = "aud_"#_name, \ .ops = &clk_regmap_mux_ops, \ - .parent_names = (_pnames), \ - .num_parents = ARRAY_SIZE(_pnames), \ + .parent_data = _pdata, \ + .num_parents = ARRAY_SIZE(_pdata), \ .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \ }, \ } -#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \ +#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _phws, _iflags) \ struct clk_regmap aud_##_name = { \ .data = &(struct clk_regmap_div_data){ \ .offset = (_reg), \ @@ -67,15 +66,27 @@ struct clk_regmap aud_##_name = { \ .hw.init = &(struct clk_init_data){ \ .name = "aud_"#_name, \ .ops = &clk_regmap_divider_ops, \ - .parent_names = (const char *[]) { _pname }, \ + .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \ .num_parents = 1, \ .flags = (_iflags), \ }, \ } #define AUD_PCLK_GATE(_name, _bit) \ - AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0) - +struct clk_regmap aud_##_name = { \ + .data = &(struct clk_regmap_gate_data){ \ + .offset = (AUDIO_CLK_GATE_EN), \ + .bit_idx = (_bit), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = "aud_"#_name, \ + .ops = &clk_regmap_gate_ops, \ + .parent_data = &(const struct clk_parent_data) { \ + .fw_name = "pclk", \ + }, \ + .num_parents = 1, \ + }, \ +} /* Audio peripheral clocks */ static AUD_PCLK_GATE(ddr_arb, 0); static AUD_PCLK_GATE(pdm, 1); @@ -100,14 +111,20 @@ static AUD_PCLK_GATE(power_detect, 19); static AUD_PCLK_GATE(spdifout_b, 21); /* Audio Master Clocks */ -static const char * const mst_mux_parent_names[] = { - "aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3", - "aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7", +static const struct clk_parent_data mst_mux_parent_data[] = { + { .fw_name = "mst_in0", }, + { .fw_name = "mst_in1", }, + { .fw_name = "mst_in2", }, + { .fw_name = "mst_in3", }, + { .fw_name = "mst_in4", }, + { .fw_name = "mst_in5", }, + { .fw_name = "mst_in6", }, + { .fw_name = "mst_in7", }, }; #define AUD_MST_MUX(_name, _reg, _flag) \ AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \ - mst_mux_parent_names, CLK_SET_RATE_PARENT) + mst_mux_parent_data, 0) #define AUD_MST_MCLK_MUX(_name, _reg) \ AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST) @@ -129,7 +146,7 @@ static AUD_MST_MCLK_MUX(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL); #define AUD_MST_DIV(_name, _reg, _flag) \ AUD_DIV(_name##_div, _reg, 0, 16, _flag, \ - "aud_"#_name"_sel", CLK_SET_RATE_PARENT) \ + aud_##_name##_sel, CLK_SET_RATE_PARENT) \ #define AUD_MST_MCLK_DIV(_name, _reg) \ AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST) @@ -150,7 +167,7 @@ static AUD_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); static AUD_MST_MCLK_DIV(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL); #define AUD_MST_MCLK_GATE(_name, _reg) \ - AUD_GATE(_name, _reg, 31, "aud_"#_name"_div", \ + AUD_GATE(_name, _reg, 31, aud_##_name##_div, \ CLK_SET_RATE_PARENT) static AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL); @@ -168,7 +185,7 @@ static AUD_MST_MCLK_GATE(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL); /* Sample Clocks */ #define AUD_MST_SCLK_PRE_EN(_name, _reg) \ AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \ - "aud_mst_"#_name"_mclk", 0) + aud_mst_##_name##_mclk, 0) static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0); static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0); @@ -178,7 +195,7 @@ static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0); static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0); #define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \ - _hi_shift, _hi_width, _pname, _iflags) \ + _hi_shift, _hi_width, _phws, _iflags) \ struct clk_regmap aud_##_name = { \ .data = &(struct meson_sclk_div_data) { \ .div = { \ @@ -195,7 +212,7 @@ struct clk_regmap aud_##_name = { \ .hw.init = &(struct clk_init_data) { \ .name = "aud_"#_name, \ .ops = &meson_sclk_div_ops, \ - .parent_names = (const char *[]) { _pname }, \ + .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \ .num_parents = 1, \ .flags = (_iflags), \ }, \ @@ -203,7 +220,7 @@ struct clk_regmap aud_##_name = { \ #define AUD_MST_SCLK_DIV(_name, _reg) \ AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \ - "aud_mst_"#_name"_sclk_pre_en", \ + aud_mst_##_name##_sclk_pre_en, \ CLK_SET_RATE_PARENT) static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0); @@ -214,8 +231,8 @@ static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0); static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0); #define AUD_MST_SCLK_POST_EN(_name, _reg) \ - AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \ - "aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT) + AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \ + aud_mst_##_name##_sclk_div, CLK_SET_RATE_PARENT) static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0); static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0); @@ -224,8 +241,8 @@ static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0); static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0); static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0); -#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \ - _pname, _iflags) \ +#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \ + _phws, _iflags) \ struct clk_regmap aud_##_name = { \ .data = &(struct meson_clk_triphase_data) { \ .ph0 = { \ @@ -247,7 +264,7 @@ struct clk_regmap aud_##_name = { \ .hw.init = &(struct clk_init_data) { \ .name = "aud_"#_name, \ .ops = &meson_clk_triphase_ops, \ - .parent_names = (const char *[]) { _pname }, \ + .parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \ .num_parents = 1, \ .flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \ }, \ @@ -255,7 +272,7 @@ struct clk_regmap aud_##_name = { \ #define AUD_MST_SCLK(_name, _reg) \ AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \ - "aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT) + aud_mst_##_name##_sclk_post_en, CLK_SET_RATE_PARENT) static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1); static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1); @@ -266,7 +283,7 @@ static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1); #define AUD_MST_LRCLK_DIV(_name, _reg) \ AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \ - "aud_mst_"#_name"_sclk_post_en", 0) \ + aud_mst_##_name##_sclk_post_en, 0) \ static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0); static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0); @@ -277,7 +294,7 @@ static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0); #define AUD_MST_LRCLK(_name, _reg) \ AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \ - "aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT) + aud_mst_##_name##_lrclk_div, CLK_SET_RATE_PARENT) static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1); static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1); @@ -286,19 +303,29 @@ static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1); static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1); static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1); -static const char * const tdm_sclk_parent_names[] = { - "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk", - "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk", - "aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2", - "aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5", - "aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8", - "aud_slv_sclk9" +static const struct clk_parent_data tdm_sclk_parent_data[] = { + { .hw = &aud_mst_a_sclk.hw, }, + { .hw = &aud_mst_b_sclk.hw, }, + { .hw = &aud_mst_c_sclk.hw, }, + { .hw = &aud_mst_d_sclk.hw, }, + { .hw = &aud_mst_e_sclk.hw, }, + { .hw = &aud_mst_f_sclk.hw, }, + { .fw_name = "slv_sclk0", }, + { .fw_name = "slv_sclk1", }, + { .fw_name = "slv_sclk2", }, + { .fw_name = "slv_sclk3", }, + { .fw_name = "slv_sclk4", }, + { .fw_name = "slv_sclk5", }, + { .fw_name = "slv_sclk6", }, + { .fw_name = "slv_sclk7", }, + { .fw_name = "slv_sclk8", }, + { .fw_name = "slv_sclk9", }, }; #define AUD_TDM_SCLK_MUX(_name, _reg) \ AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \ CLK_MUX_ROUND_CLOSEST, \ - tdm_sclk_parent_names, 0) + tdm_sclk_parent_data, 0) static AUD_TDM_SCLK_MUX(in_a, AUDIO_CLK_TDMIN_A_CTRL); static AUD_TDM_SCLK_MUX(in_b, AUDIO_CLK_TDMIN_B_CTRL); @@ -310,7 +337,7 @@ static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL); #define AUD_TDM_SCLK_PRE_EN(_name, _reg) \ AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \ - "aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT) + aud_tdm##_name##_sclk_sel, CLK_SET_RATE_PARENT) static AUD_TDM_SCLK_PRE_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL); static AUD_TDM_SCLK_PRE_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL); @@ -322,7 +349,7 @@ static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL); #define AUD_TDM_SCLK_POST_EN(_name, _reg) \ AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \ - "aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT) + aud_tdm##_name##_sclk_pre_en, CLK_SET_RATE_PARENT) static AUD_TDM_SCLK_POST_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL); static AUD_TDM_SCLK_POST_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL); @@ -344,8 +371,9 @@ static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL); .hw.init = &(struct clk_init_data) { \ .name = "aud_tdm"#_name"_sclk", \ .ops = &meson_clk_phase_ops, \ - .parent_names = (const char *[]) \ - { "aud_tdm"#_name"_sclk_post_en" }, \ + .parent_hws = (const struct clk_hw *[]) { \ + &aud_tdm##_name##_sclk_post_en.hw \ + }, \ .num_parents = 1, \ .flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \ }, \ @@ -359,19 +387,29 @@ static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL); static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL); static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL); -static const char * const tdm_lrclk_parent_names[] = { - "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk", - "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk", - "aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2", - "aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5", - "aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8", - "aud_slv_lrclk9" +static const struct clk_parent_data tdm_lrclk_parent_data[] = { + { .hw = &aud_mst_a_lrclk.hw, }, + { .hw = &aud_mst_b_lrclk.hw, }, + { .hw = &aud_mst_c_lrclk.hw, }, + { .hw = &aud_mst_d_lrclk.hw, }, + { .hw = &aud_mst_e_lrclk.hw, }, + { .hw = &aud_mst_f_lrclk.hw, }, + { .fw_name = "slv_lrclk0", }, + { .fw_name = "slv_lrclk1", }, + { .fw_name = "slv_lrclk2", }, + { .fw_name = "slv_lrclk3", }, + { .fw_name = "slv_lrclk4", }, + { .fw_name = "slv_lrclk5", }, + { .fw_name = "slv_lrclk6", }, + { .fw_name = "slv_lrclk7", }, + { .fw_name = "slv_lrclk8", }, + { .fw_name = "slv_lrclk9", }, }; -#define AUD_TDM_LRLCK(_name, _reg) \ - AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \ - CLK_MUX_ROUND_CLOSEST, \ - tdm_lrclk_parent_names, 0) +#define AUD_TDM_LRLCK(_name, _reg) \ + AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \ + CLK_MUX_ROUND_CLOSEST, \ + tdm_lrclk_parent_data, 0) static AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL); static AUD_TDM_LRLCK(in_b, AUDIO_CLK_TDMIN_B_CTRL); @@ -386,39 +424,51 @@ static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL); AUD_MUX(tdm_##_name, _reg, 0x7, _shift, 0, _parents, \ CLK_SET_RATE_NO_REPARENT) -static const char * const mclk_pad_ctrl_parent_names[] = { - "aud_mst_a_mclk", "aud_mst_b_mclk", "aud_mst_c_mclk", - "aud_mst_d_mclk", "aud_mst_e_mclk", "aud_mst_f_mclk", +static const struct clk_parent_data mclk_pad_ctrl_parent_data[] = { + { .hw = &aud_mst_a_mclk.hw }, + { .hw = &aud_mst_b_mclk.hw }, + { .hw = &aud_mst_c_mclk.hw }, + { .hw = &aud_mst_d_mclk.hw }, + { .hw = &aud_mst_e_mclk.hw }, + { .hw = &aud_mst_f_mclk.hw }, }; static AUD_TDM_PAD_CTRL(mclk_pad_0, AUDIO_MST_PAD_CTRL0, 0, - mclk_pad_ctrl_parent_names); + mclk_pad_ctrl_parent_data); static AUD_TDM_PAD_CTRL(mclk_pad_1, AUDIO_MST_PAD_CTRL0, 4, - mclk_pad_ctrl_parent_names); - -static const char * const lrclk_pad_ctrl_parent_names[] = { - "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk", - "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk", + mclk_pad_ctrl_parent_data); + +static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = { + { .hw = &aud_mst_a_lrclk.hw }, + { .hw = &aud_mst_b_lrclk.hw }, + { .hw = &aud_mst_c_lrclk.hw }, + { .hw = &aud_mst_d_lrclk.hw }, + { .hw = &aud_mst_e_lrclk.hw }, + { .hw = &aud_mst_f_lrclk.hw }, }; static AUD_TDM_PAD_CTRL(lrclk_pad_0, AUDIO_MST_PAD_CTRL1, 16, - lrclk_pad_ctrl_parent_names); + lrclk_pad_ctrl_parent_data); static AUD_TDM_PAD_CTRL(lrclk_pad_1, AUDIO_MST_PAD_CTRL1, 20, - lrclk_pad_ctrl_parent_names); + lrclk_pad_ctrl_parent_data); static AUD_TDM_PAD_CTRL(lrclk_pad_2, AUDIO_MST_PAD_CTRL1, 24, - lrclk_pad_ctrl_parent_names); - -static const char * const sclk_pad_ctrl_parent_names[] = { - "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk", - "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk", + lrclk_pad_ctrl_parent_data); + +static const struct clk_parent_data sclk_pad_ctrl_parent_data[] = { + { .hw = &aud_mst_a_sclk.hw }, + { .hw = &aud_mst_b_sclk.hw }, + { .hw = &aud_mst_c_sclk.hw }, + { .hw = &aud_mst_d_sclk.hw }, + { .hw = &aud_mst_e_sclk.hw }, + { .hw = &aud_mst_f_sclk.hw }, }; static AUD_TDM_PAD_CTRL(sclk_pad_0, AUDIO_MST_PAD_CTRL1, 0, - sclk_pad_ctrl_parent_names); + sclk_pad_ctrl_parent_data); static AUD_TDM_PAD_CTRL(sclk_pad_1, AUDIO_MST_PAD_CTRL1, 4, - sclk_pad_ctrl_parent_names); + sclk_pad_ctrl_parent_data); static AUD_TDM_PAD_CTRL(sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8, - sclk_pad_ctrl_parent_names); + sclk_pad_ctrl_parent_data); /* * Array of all clocks provided by this provider @@ -868,54 +918,6 @@ static int devm_clk_get_enable(struct device *dev, char *id) return 0; } -static int axg_register_clk_hw_input(struct device *dev, - const char *name) -{ - char *clk_name; - struct clk_hw *hw; - int err = 0; - - clk_name = kasprintf(GFP_KERNEL, "aud_%s", name); - if (!clk_name) - return -ENOMEM; - - hw = meson_clk_hw_register_input(dev, name, clk_name, 0); - if (IS_ERR(hw)) { - /* It is ok if an input clock is missing */ - if (PTR_ERR(hw) == -ENOENT) { - dev_dbg(dev, "%s not provided", name); - } else { - err = PTR_ERR(hw); - if (err != -EPROBE_DEFER) - dev_err(dev, "failed to get %s clock", name); - } - } - - kfree(clk_name); - return err; -} - -static int axg_register_clk_hw_inputs(struct device *dev, - const char *basename, - unsigned int count) -{ - char *name; - int i, ret; - - for (i = 0; i < count; i++) { - name = kasprintf(GFP_KERNEL, "%s%d", basename, i); - if (!name) - return -ENOMEM; - - ret = axg_register_clk_hw_input(dev, name); - kfree(name); - if (ret) - return ret; - } - - return 0; -} - static const struct regmap_config axg_audio_regmap_cfg = { .reg_bits = 32, .val_bits = 32, @@ -963,29 +965,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev) return ret; } - /* Register the peripheral input clock */ - hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - /* Register optional input master clocks */ - ret = axg_register_clk_hw_inputs(dev, "mst_in", - AUD_MST_IN_COUNT); - if (ret) - return ret; - - /* Register optional input slave sclks */ - ret = axg_register_clk_hw_inputs(dev, "slv_sclk", - AUD_SLV_SCLK_COUNT); - if (ret) - return ret; - - /* Register optional input slave lrclks */ - ret = axg_register_clk_hw_inputs(dev, "slv_lrclk", - AUD_SLV_LRCLK_COUNT); - if (ret) - return ret; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++) aud_clk_regmaps[i]->map = map; -- GitLab From ba626081107dceacff554e5ca2efc7cea7326b6e Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:41:23 +0200 Subject: [PATCH 0996/7155] clk: meson: g12a-aoclk: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (when parent clocks are localy declared in the controller) and use .parent_data otherwise. Remove clk input helper and all bypass clocks (declared in probe function) which are no longer used since we are able to use device-tree clock name directly. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a-aoclk.c | 81 +++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c index 1994e735396b..62499563e4f5 100644 --- a/drivers/clk/meson/g12a-aoclk.c +++ b/drivers/clk/meson/g12a-aoclk.c @@ -18,8 +18,6 @@ #include "clk-regmap.h" #include "clk-dualdiv.h" -#define IN_PREFIX "ao-in-" - /* * AO Configuration Clock registers offsets * Register offsets from the data sheet must be multiplied by 4. @@ -51,7 +49,9 @@ static struct clk_regmap g12a_aoclk_##_name = { \ .hw.init = &(struct clk_init_data) { \ .name = "g12a_ao_" #_name, \ .ops = &clk_regmap_gate_ops, \ - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \ + .parent_data = &(const struct clk_parent_data) { \ + .fw_name = "mpeg-clk", \ + }, \ .num_parents = 1, \ .flags = CLK_IGNORE_UNUSED, \ }, \ @@ -81,7 +81,9 @@ static struct clk_regmap g12a_aoclk_cts_oscin = { .hw.init = &(struct clk_init_data){ .name = "cts_oscin", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -106,7 +108,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_32k_by_oscin_pre", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_oscin" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_cts_oscin.hw + }, .num_parents = 1, }, }; @@ -143,7 +147,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_div = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_32k_by_oscin_div", .ops = &meson_clk_dualdiv_ops, - .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_32k_by_oscin_pre.hw + }, .num_parents = 1, }, }; @@ -158,8 +164,10 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_32k_by_oscin_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div", - "g12a_ao_32k_by_oscin_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_32k_by_oscin_div.hw, + &g12a_aoclk_32k_by_oscin_pre.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -173,7 +181,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_32k_by_oscin", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_32k_by_oscin_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -189,7 +199,9 @@ static struct clk_regmap g12a_aoclk_cec_pre = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_cec_pre", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_oscin" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_cts_oscin.hw + }, .num_parents = 1, }, }; @@ -226,7 +238,9 @@ static struct clk_regmap g12a_aoclk_cec_div = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_cec_div", .ops = &meson_clk_dualdiv_ops, - .parent_names = (const char *[]){ "g12a_ao_cec_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_cec_pre.hw + }, .num_parents = 1, }, }; @@ -241,8 +255,10 @@ static struct clk_regmap g12a_aoclk_cec_sel = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_cec_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "g12a_ao_cec_div", - "g12a_ao_cec_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_cec_div.hw, + &g12a_aoclk_cec_pre.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -256,7 +272,9 @@ static struct clk_regmap g12a_aoclk_cec = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_cec", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "g12a_ao_cec_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_cec_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -272,8 +290,10 @@ static struct clk_regmap g12a_aoclk_cts_rtc_oscin = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_cts_rtc_oscin", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin", - IN_PREFIX "ext_32k-0" }, + .parent_data = (const struct clk_parent_data []) { + { .hw = &g12a_aoclk_32k_by_oscin.hw }, + { .fw_name = "ext-32k-0", }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -289,8 +309,10 @@ static struct clk_regmap g12a_aoclk_clk81 = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_clk81", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk", - "g12a_ao_cts_rtc_oscin"}, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "mpeg-clk", }, + { .hw = &g12a_aoclk_cts_rtc_oscin.hw }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -305,8 +327,10 @@ static struct clk_regmap g12a_aoclk_saradc_mux = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_saradc_mux", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "g12a_ao_clk81" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_aoclk_clk81.hw }, + }, .num_parents = 2, }, }; @@ -320,7 +344,9 @@ static struct clk_regmap g12a_aoclk_saradc_div = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_saradc_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "g12a_ao_saradc_mux" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_saradc_mux.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -334,7 +360,9 @@ static struct clk_regmap g12a_aoclk_saradc_gate = { .hw.init = &(struct clk_init_data){ .name = "g12a_ao_saradc_gate", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "g12a_ao_saradc_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_aoclk_saradc_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -417,12 +445,6 @@ static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = { .num = NR_CLKS, }; -static const struct meson_aoclk_input g12a_aoclk_inputs[] = { - { .name = "xtal", .required = true }, - { .name = "mpeg-clk", .required = true }, - { .name = "ext-32k-0", .required = false }, -}; - static const struct meson_aoclk_data g12a_aoclkc_data = { .reset_reg = AO_RTI_GEN_CNTL_REG0, .num_reset = ARRAY_SIZE(g12a_aoclk_reset), @@ -430,9 +452,6 @@ static const struct meson_aoclk_data g12a_aoclkc_data = { .num_clks = ARRAY_SIZE(g12a_aoclk_regmap), .clks = g12a_aoclk_regmap, .hw_data = &g12a_aoclk_onecell_data, - .inputs = g12a_aoclk_inputs, - .num_inputs = ARRAY_SIZE(g12a_aoclk_inputs), - .input_prefix = IN_PREFIX, }; static const struct of_device_id g12a_aoclkc_match_table[] = { -- GitLab From 6e2bfc352e7a3a9b22f13c36627545d5f4caf3e9 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:41:24 +0200 Subject: [PATCH 0997/7155] clk: meson: gxbb-aoclk: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (when parent clocks are localy declared in the controller) and use .parent_data otherwise. Remove clk input helper and all bypass clocks (declared in probe function) which are no longer used since we are able to use device-tree clock name directly. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb-aoclk.c | 55 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index 449f6ac189d8..e940861a396b 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c @@ -11,8 +11,6 @@ #include "clk-regmap.h" #include "clk-dualdiv.h" -#define IN_PREFIX "ao-in-" - /* AO Configuration Clock registers offsets */ #define AO_RTI_PWR_CNTL_REG1 0x0c #define AO_RTI_PWR_CNTL_REG0 0x10 @@ -31,7 +29,9 @@ static struct clk_regmap _name##_ao = { \ .hw.init = &(struct clk_init_data) { \ .name = #_name "_ao", \ .ops = &clk_regmap_gate_ops, \ - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \ + .parent_data = &(const struct clk_parent_data) { \ + .fw_name = "mpeg-clk", \ + }, \ .num_parents = 1, \ .flags = CLK_IGNORE_UNUSED, \ }, \ @@ -52,7 +52,9 @@ static struct clk_regmap ao_cts_oscin = { .hw.init = &(struct clk_init_data){ .name = "ao_cts_oscin", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -65,7 +67,7 @@ static struct clk_regmap ao_32k_pre = { .hw.init = &(struct clk_init_data){ .name = "ao_32k_pre", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "ao_cts_oscin" }, + .parent_hws = (const struct clk_hw *[]) { &ao_cts_oscin.hw }, .num_parents = 1, }, }; @@ -112,7 +114,7 @@ static struct clk_regmap ao_32k_div = { .hw.init = &(struct clk_init_data){ .name = "ao_32k_div", .ops = &meson_clk_dualdiv_ops, - .parent_names = (const char *[]){ "ao_32k_pre" }, + .parent_hws = (const struct clk_hw *[]) { &ao_32k_pre.hw }, .num_parents = 1, }, }; @@ -127,8 +129,10 @@ static struct clk_regmap ao_32k_sel = { .hw.init = &(struct clk_init_data){ .name = "ao_32k_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "ao_32k_div", - "ao_32k_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &ao_32k_div.hw, + &ao_32k_pre.hw + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -142,7 +146,7 @@ static struct clk_regmap ao_32k = { .hw.init = &(struct clk_init_data){ .name = "ao_32k", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "ao_32k_sel" }, + .parent_hws = (const struct clk_hw *[]) { &ao_32k_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -159,10 +163,12 @@ static struct clk_regmap ao_cts_rtc_oscin = { .hw.init = &(struct clk_init_data){ .name = "ao_cts_rtc_oscin", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ IN_PREFIX "ext-32k-0", - IN_PREFIX "ext-32k-1", - IN_PREFIX "ext-32k-2", - "ao_32k" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "ext-32k-0", }, + { .fw_name = "ext-32k-1", }, + { .fw_name = "ext-32k-2", }, + { .hw = &ao_32k.hw }, + }, .num_parents = 4, .flags = CLK_SET_RATE_PARENT, }, @@ -178,8 +184,10 @@ static struct clk_regmap ao_clk81 = { .hw.init = &(struct clk_init_data){ .name = "ao_clk81", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk", - "ao_cts_rtc_oscin" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "mpeg-clk", }, + { .hw = &ao_cts_rtc_oscin.hw }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -208,8 +216,10 @@ static struct clk_regmap ao_cts_cec = { * Until CCF gets fixed, adding this fake parent that won't * ever be registered should work around the problem */ - .parent_names = (const char *[]){ "fixme", - "ao_cts_rtc_oscin" }, + .parent_data = (const struct clk_parent_data []) { + { .name = "fixme", .index = -1, }, + { .hw = &ao_cts_rtc_oscin.hw }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -261,14 +271,6 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { .num = NR_CLKS, }; -static const struct meson_aoclk_input gxbb_aoclk_inputs[] = { - { .name = "xtal", .required = true, }, - { .name = "mpeg-clk", .required = true, }, - {. name = "ext-32k-0", .required = false, }, - {. name = "ext-32k-1", .required = false, }, - {. name = "ext-32k-2", .required = false, }, -}; - static const struct meson_aoclk_data gxbb_aoclkc_data = { .reset_reg = AO_RTI_GEN_CNTL_REG0, .num_reset = ARRAY_SIZE(gxbb_aoclk_reset), @@ -276,9 +278,6 @@ static const struct meson_aoclk_data gxbb_aoclkc_data = { .num_clks = ARRAY_SIZE(gxbb_aoclk), .clks = gxbb_aoclk, .hw_data = &gxbb_aoclk_onecell_data, - .inputs = gxbb_aoclk_inputs, - .num_inputs = ARRAY_SIZE(gxbb_aoclk_inputs), - .input_prefix = IN_PREFIX, }; static const struct of_device_id gxbb_aoclkc_match_table[] = { -- GitLab From b90ec1e344a2dd4c1afebd75c1ce05afaf9e116b Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:41:25 +0200 Subject: [PATCH 0998/7155] clk: meson: axg-aoclk: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (when parent clocks are localy declared in the controller) and use .parent_data otherwise. Remove clk input helper and all bypass clocks (declared in probe function) which are no longer used since we are able to use device-tree clock name directly. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg-aoclk.c | 63 ++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c index 0086f31288eb..b488b40c9d0e 100644 --- a/drivers/clk/meson/axg-aoclk.c +++ b/drivers/clk/meson/axg-aoclk.c @@ -18,8 +18,6 @@ #include "clk-regmap.h" #include "clk-dualdiv.h" -#define IN_PREFIX "ao-in-" - /* * AO Configuration Clock registers offsets * Register offsets from the data sheet must be multiplied by 4. @@ -42,7 +40,9 @@ static struct clk_regmap axg_aoclk_##_name = { \ .hw.init = &(struct clk_init_data) { \ .name = "axg_ao_" #_name, \ .ops = &clk_regmap_gate_ops, \ - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \ + .parent_data = &(const struct clk_parent_data) { \ + .fw_name = "mpeg-clk", \ + }, \ .num_parents = 1, \ .flags = CLK_IGNORE_UNUSED, \ }, \ @@ -64,7 +64,9 @@ static struct clk_regmap axg_aoclk_cts_oscin = { .hw.init = &(struct clk_init_data){ .name = "cts_oscin", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -77,7 +79,9 @@ static struct clk_regmap axg_aoclk_32k_pre = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_32k_pre", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_oscin" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_cts_oscin.hw + }, .num_parents = 1, }, }; @@ -124,7 +128,9 @@ static struct clk_regmap axg_aoclk_32k_div = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_32k_div", .ops = &meson_clk_dualdiv_ops, - .parent_names = (const char *[]){ "axg_ao_32k_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_32k_pre.hw + }, .num_parents = 1, }, }; @@ -139,8 +145,10 @@ static struct clk_regmap axg_aoclk_32k_sel = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_32k_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "axg_ao_32k_div", - "axg_ao_32k_pre" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_32k_div.hw, + &axg_aoclk_32k_pre.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -154,7 +162,9 @@ static struct clk_regmap axg_aoclk_32k = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_32k", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "axg_ao_32k_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_32k_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -170,8 +180,10 @@ static struct clk_regmap axg_aoclk_cts_rtc_oscin = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_cts_rtc_oscin", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "axg_ao_32k", - IN_PREFIX "ext_32k-0" }, + .parent_data = (const struct clk_parent_data []) { + { .hw = &axg_aoclk_32k.hw }, + { .fw_name = "ext_32k-0", }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -187,8 +199,10 @@ static struct clk_regmap axg_aoclk_clk81 = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_clk81", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk", - "axg_ao_cts_rtc_oscin"}, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "mpeg-clk", }, + { .hw = &axg_aoclk_cts_rtc_oscin.hw }, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -203,8 +217,10 @@ static struct clk_regmap axg_aoclk_saradc_mux = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_saradc_mux", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "axg_ao_clk81" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &axg_aoclk_clk81.hw }, + }, .num_parents = 2, }, }; @@ -218,7 +234,9 @@ static struct clk_regmap axg_aoclk_saradc_div = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_saradc_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "axg_ao_saradc_mux" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_saradc_mux.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -232,7 +250,9 @@ static struct clk_regmap axg_aoclk_saradc_gate = { .hw.init = &(struct clk_init_data){ .name = "axg_ao_saradc_gate", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "axg_ao_saradc_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_aoclk_saradc_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -290,12 +310,6 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = { .num = NR_CLKS, }; -static const struct meson_aoclk_input axg_aoclk_inputs[] = { - { .name = "xtal", .required = true }, - { .name = "mpeg-clk", .required = true }, - { .name = "ext-32k-0", .required = false }, -}; - static const struct meson_aoclk_data axg_aoclkc_data = { .reset_reg = AO_RTI_GEN_CNTL_REG0, .num_reset = ARRAY_SIZE(axg_aoclk_reset), @@ -303,9 +317,6 @@ static const struct meson_aoclk_data axg_aoclkc_data = { .num_clks = ARRAY_SIZE(axg_aoclk_regmap), .clks = axg_aoclk_regmap, .hw_data = &axg_aoclk_onecell_data, - .inputs = axg_aoclk_inputs, - .num_inputs = ARRAY_SIZE(axg_aoclk_inputs), - .input_prefix = IN_PREFIX, }; static const struct of_device_id axg_aoclkc_match_table[] = { -- GitLab From 072a043f5a2e02441002fff34e3885e6026714eb Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:41:26 +0200 Subject: [PATCH 0999/7155] clk: meson: remove ao input bypass clocks During probe, bypass clocks (i.e. ao-in-xtal) are made from device-tree inputs to provide input clocks which can be access through global name. The cons of this method are the duplicated clocks, means more string comparison. Specify parent directly with device-tree clock name. Function to regiter bypass clocks is removed. Input parameters from meson aoclk data structure are deprecated and then deleted since all aoclk files are migrated. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 1 - drivers/clk/meson/meson-aoclk.c | 37 --------------------------------- drivers/clk/meson/meson-aoclk.h | 8 ------- 3 files changed, 46 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index ee0b84b6b329..178ee72ba4bc 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -33,7 +33,6 @@ config COMMON_CLK_MESON_VID_PLL_DIV config COMMON_CLK_MESON_AO_CLKC tristate select COMMON_CLK_MESON_REGMAP - select COMMON_CLK_MESON_INPUT select RESET_CONTROLLER config COMMON_CLK_MESON_EE_CLKC diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c index b67951909e04..bf8bea675d24 100644 --- a/drivers/clk/meson/meson-aoclk.c +++ b/drivers/clk/meson/meson-aoclk.c @@ -17,8 +17,6 @@ #include #include "meson-aoclk.h" -#include "clk-input.h" - static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev, unsigned long id) { @@ -33,37 +31,6 @@ static const struct reset_control_ops meson_aoclk_reset_ops = { .reset = meson_aoclk_do_reset, }; -static int meson_aoclkc_register_inputs(struct device *dev, - struct meson_aoclk_data *data) -{ - struct clk_hw *hw; - char *str; - int i; - - for (i = 0; i < data->num_inputs; i++) { - const struct meson_aoclk_input *in = &data->inputs[i]; - - str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix, - in->name); - if (!str) - return -ENOMEM; - - hw = meson_clk_hw_register_input(dev, in->name, str, 0); - kfree(str); - - if (IS_ERR(hw)) { - if (!in->required && PTR_ERR(hw) == -ENOENT) - continue; - else if (PTR_ERR(hw) != -EPROBE_DEFER) - dev_err(dev, "failed to register input %s\n", - in->name); - return PTR_ERR(hw); - } - } - - return 0; -} - int meson_aoclkc_probe(struct platform_device *pdev) { struct meson_aoclk_reset_controller *rstc; @@ -86,10 +53,6 @@ int meson_aoclkc_probe(struct platform_device *pdev) return PTR_ERR(regmap); } - ret = meson_aoclkc_register_inputs(dev, data); - if (ret) - return ret; - /* Reset Controller */ rstc->data = data; rstc->regmap = regmap; diff --git a/drivers/clk/meson/meson-aoclk.h b/drivers/clk/meson/meson-aoclk.h index 999cde3868f7..605b43855a69 100644 --- a/drivers/clk/meson/meson-aoclk.h +++ b/drivers/clk/meson/meson-aoclk.h @@ -18,20 +18,12 @@ #include "clk-regmap.h" -struct meson_aoclk_input { - const char *name; - bool required; -}; - struct meson_aoclk_data { const unsigned int reset_reg; const int num_reset; const unsigned int *reset; const int num_clks; struct clk_regmap **clks; - const int num_inputs; - const struct meson_aoclk_input *inputs; - const char *input_prefix; const struct clk_hw_onecell_data *hw_data; }; -- GitLab From 25e682a02d91e2d09f47c089a4b42bba726106b9 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:31 +0200 Subject: [PATCH 1000/7155] clk: meson: g12a: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (ie. when all clocks are local to the controller) and use .parent_data otherwise. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a.c | 1087 ++++++++++++++++++++++++-------------- 1 file changed, 693 insertions(+), 394 deletions(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 7bc5566b66f7..8cc7f5acf7ab 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -15,7 +15,6 @@ #include #include -#include "clk-input.h" #include "clk-mpll.h" #include "clk-pll.h" #include "clk-regmap.h" @@ -61,7 +60,9 @@ static struct clk_regmap g12a_fixed_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -76,7 +77,9 @@ static struct clk_regmap g12a_fixed_pll = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fixed_pll_dco.hw + }, .num_parents = 1, /* * This clock won't ever change at runtime so @@ -130,7 +133,9 @@ static struct clk_regmap g12a_sys_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "sys_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -145,7 +150,9 @@ static struct clk_regmap g12a_sys_pll = { .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "sys_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sys_pll_dco.hw + }, .num_parents = 1, }, }; @@ -181,7 +188,9 @@ static struct clk_regmap g12b_sys1_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "sys1_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -196,7 +205,9 @@ static struct clk_regmap g12b_sys1_pll = { .hw.init = &(struct clk_init_data){ .name = "sys1_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "sys1_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_sys1_pll_dco.hw + }, .num_parents = 1, }, }; @@ -209,7 +220,7 @@ static struct clk_regmap g12a_sys_pll_div16_en = { .hw.init = &(struct clk_init_data) { .name = "sys_pll_div16_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "sys_pll" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_sys_pll.hw }, .num_parents = 1, /* * This clock is used to debug the sys_pll range @@ -226,7 +237,9 @@ static struct clk_regmap g12b_sys1_pll_div16_en = { .hw.init = &(struct clk_init_data) { .name = "sys1_pll_div16_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "sys1_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_sys1_pll.hw + }, .num_parents = 1, /* * This clock is used to debug the sys_pll range @@ -241,7 +254,9 @@ static struct clk_fixed_factor g12a_sys_pll_div16 = { .hw.init = &(struct clk_init_data){ .name = "sys_pll_div16", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "sys_pll_div16_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sys_pll_div16_en.hw + }, .num_parents = 1, }, }; @@ -252,11 +267,75 @@ static struct clk_fixed_factor g12b_sys1_pll_div16 = { .hw.init = &(struct clk_init_data){ .name = "sys1_pll_div16", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "sys1_pll_div16_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_sys1_pll_div16_en.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_FIX_PLL_CNTL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div2_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw }, .num_parents = 1, }, }; +static struct clk_regmap g12a_fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_FIX_PLL_CNTL1, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div3_div.hw + }, + .num_parents = 1, + /* + * This clock is used by the resident firmware and is required + * by the platform to operate correctly. + * Until the following condition are met, we need this clock to + * be marked as critical: + * a) Mark the clock used by a firmware resource, if possible + * b) CCF has a clock hand-off mechanism to make the sure the + * clock stays on until the proper driver comes along + */ + .flags = CLK_IS_CRITICAL, + }, +}; + /* Datasheet names this field as "premux0" */ static struct clk_regmap g12a_cpu_clk_premux0 = { .data = &(struct clk_regmap_mux_data){ @@ -267,9 +346,30 @@ static struct clk_regmap g12a_cpu_clk_premux0 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "fclk_div2", - "fclk_div3" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div2.hw }, + { .hw = &g12a_fclk_div3.hw }, + }, + .num_parents = 3, + }, +}; + +/* Datasheet names this field as "premux1" */ +static struct clk_regmap g12a_cpu_clk_premux1 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn1_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div2.hw }, + { .hw = &g12a_fclk_div3.hw }, + }, .num_parents = 3, }, }; @@ -284,7 +384,9 @@ static struct clk_regmap g12a_cpu_clk_mux0_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_premux0.hw + }, .num_parents = 1, }, }; @@ -299,29 +401,14 @@ static struct clk_regmap g12a_cpu_clk_postmux0 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn0_sel", - "cpu_clk_dyn0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_premux0.hw, + &g12a_cpu_clk_mux0_div.hw, + }, .num_parents = 2, }, }; -/* Datasheet names this field as "premux1" */ -static struct clk_regmap g12a_cpu_clk_premux1 = { - .data = &(struct clk_regmap_mux_data){ - .offset = HHI_SYS_CPU_CLK_CNTL0, - .mask = 0x3, - .shift = 16, - }, - .hw.init = &(struct clk_init_data){ - .name = "cpu_clk_dyn1_sel", - .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "fclk_div2", - "fclk_div3" }, - .num_parents = 3, - }, -}; - /* Datasheet names this field as "Mux1_divn_tcnt" */ static struct clk_regmap g12a_cpu_clk_mux1_div = { .data = &(struct clk_regmap_div_data){ @@ -332,7 +419,9 @@ static struct clk_regmap g12a_cpu_clk_mux1_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn1_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_premux1.hw + }, .num_parents = 1, }, }; @@ -347,8 +436,10 @@ static struct clk_regmap g12a_cpu_clk_postmux1 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn1", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn1_sel", - "cpu_clk_dyn1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_premux1.hw, + &g12a_cpu_clk_mux1_div.hw, + }, .num_parents = 2, }, }; @@ -363,8 +454,10 @@ static struct clk_regmap g12a_cpu_clk_dyn = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn0", - "cpu_clk_dyn1" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_postmux0.hw, + &g12a_cpu_clk_postmux1.hw, + }, .num_parents = 2, }, }; @@ -379,8 +472,10 @@ static struct clk_regmap g12a_cpu_clk = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn", - "sys_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_dyn.hw, + &g12a_sys_pll.hw, + }, .num_parents = 2, }, }; @@ -395,8 +490,10 @@ static struct clk_regmap g12b_cpu_clk = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_dyn", - "sys1_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_dyn.hw, + &g12b_sys1_pll.hw + }, .num_parents = 2, }, }; @@ -411,9 +508,11 @@ static struct clk_regmap g12b_cpub_clk_premux0 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "fclk_div2", - "fclk_div3" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div2.hw }, + { .hw = &g12a_fclk_div3.hw }, + }, .num_parents = 3, }, }; @@ -428,7 +527,9 @@ static struct clk_regmap g12b_cpub_clk_mux0_div = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_premux0.hw + }, .num_parents = 1, }, }; @@ -443,8 +544,10 @@ static struct clk_regmap g12b_cpub_clk_postmux0 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn0_sel", - "cpub_clk_dyn0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_premux0.hw, + &g12b_cpub_clk_mux0_div.hw + }, .num_parents = 2, }, }; @@ -459,9 +562,11 @@ static struct clk_regmap g12b_cpub_clk_premux1 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn1_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "fclk_div2", - "fclk_div3" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div2.hw }, + { .hw = &g12a_fclk_div3.hw }, + }, .num_parents = 3, }, }; @@ -476,7 +581,9 @@ static struct clk_regmap g12b_cpub_clk_mux1_div = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn1_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_premux1.hw + }, .num_parents = 1, }, }; @@ -491,8 +598,10 @@ static struct clk_regmap g12b_cpub_clk_postmux1 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn1", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn1_sel", - "cpub_clk_dyn1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_premux1.hw, + &g12b_cpub_clk_mux1_div.hw + }, .num_parents = 2, }, }; @@ -507,8 +616,10 @@ static struct clk_regmap g12b_cpub_clk_dyn = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn0", - "cpub_clk_dyn1" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_postmux0.hw, + &g12b_cpub_clk_postmux1.hw + }, .num_parents = 2, }, }; @@ -523,8 +634,10 @@ static struct clk_regmap g12b_cpub_clk = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_dyn", - "sys_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_dyn.hw, + &g12a_sys_pll.hw + }, .num_parents = 2, }, }; @@ -537,7 +650,9 @@ static struct clk_regmap g12a_cpu_clk_div16_en = { .hw.init = &(struct clk_init_data) { .name = "cpu_clk_div16_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk.hw + }, .num_parents = 1, /* * This clock is used to debug the cpu_clk range @@ -554,7 +669,9 @@ static struct clk_regmap g12b_cpub_clk_div16_en = { .hw.init = &(struct clk_init_data) { .name = "cpub_clk_div16_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, /* * This clock is used to debug the cpu_clk range @@ -569,7 +686,9 @@ static struct clk_fixed_factor g12a_cpu_clk_div16 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div16", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk_div16_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_div16_en.hw + }, .num_parents = 1, }, }; @@ -580,7 +699,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div16 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div16", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk_div16_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_div16_en.hw + }, .num_parents = 1, }, }; @@ -595,7 +716,7 @@ static struct clk_regmap g12a_cpu_clk_apb_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_apb_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, .num_parents = 1, }, }; @@ -608,7 +729,9 @@ static struct clk_regmap g12a_cpu_clk_apb = { .hw.init = &(struct clk_init_data) { .name = "cpu_clk_apb", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_apb_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_apb_div.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -627,7 +750,7 @@ static struct clk_regmap g12a_cpu_clk_atb_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_atb_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, .num_parents = 1, }, }; @@ -640,7 +763,9 @@ static struct clk_regmap g12a_cpu_clk_atb = { .hw.init = &(struct clk_init_data) { .name = "cpu_clk_atb", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_atb_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_atb_div.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -659,7 +784,7 @@ static struct clk_regmap g12a_cpu_clk_axi_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_axi_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw }, .num_parents = 1, }, }; @@ -672,7 +797,9 @@ static struct clk_regmap g12a_cpu_clk_axi = { .hw.init = &(struct clk_init_data) { .name = "cpu_clk_axi", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_axi_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_axi_div.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -691,7 +818,17 @@ static struct clk_regmap g12a_cpu_clk_trace_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_trace_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * G12A and G12B have different cpu_clks (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so cpu_clk_trace_div picks + * up the appropriate one. + */ + .name = "cpu_clk", + .index = -1, + }, .num_parents = 1, }, }; @@ -704,7 +841,9 @@ static struct clk_regmap g12a_cpu_clk_trace = { .hw.init = &(struct clk_init_data) { .name = "cpu_clk_trace", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpu_clk_trace_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cpu_clk_trace_div.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -719,7 +858,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div2 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -730,7 +871,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div3 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div3", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -741,7 +884,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div4 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -752,7 +897,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div5 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div5", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -763,7 +910,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div6 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -774,7 +923,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div7 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div7", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -785,7 +936,9 @@ static struct clk_fixed_factor g12b_cpub_clk_div8 = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_div8", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpub_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk.hw + }, .num_parents = 1, }, }; @@ -801,13 +954,15 @@ static struct clk_regmap g12b_cpub_clk_apb_sel = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_apb_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_div2", - "cpub_clk_div3", - "cpub_clk_div4", - "cpub_clk_div5", - "cpub_clk_div6", - "cpub_clk_div7", - "cpub_clk_div8" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_div2.hw, + &g12b_cpub_clk_div3.hw, + &g12b_cpub_clk_div4.hw, + &g12b_cpub_clk_div5.hw, + &g12b_cpub_clk_div6.hw, + &g12b_cpub_clk_div7.hw, + &g12b_cpub_clk_div8.hw + }, .num_parents = 7, }, }; @@ -821,7 +976,9 @@ static struct clk_regmap g12b_cpub_clk_apb = { .hw.init = &(struct clk_init_data) { .name = "cpub_clk_apb", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_apb_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_apb_sel.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -840,13 +997,15 @@ static struct clk_regmap g12b_cpub_clk_atb_sel = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_atb_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_div2", - "cpub_clk_div3", - "cpub_clk_div4", - "cpub_clk_div5", - "cpub_clk_div6", - "cpub_clk_div7", - "cpub_clk_div8" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_div2.hw, + &g12b_cpub_clk_div3.hw, + &g12b_cpub_clk_div4.hw, + &g12b_cpub_clk_div5.hw, + &g12b_cpub_clk_div6.hw, + &g12b_cpub_clk_div7.hw, + &g12b_cpub_clk_div8.hw + }, .num_parents = 7, }, }; @@ -860,7 +1019,9 @@ static struct clk_regmap g12b_cpub_clk_atb = { .hw.init = &(struct clk_init_data) { .name = "cpub_clk_atb", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_atb_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_atb_sel.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -879,13 +1040,15 @@ static struct clk_regmap g12b_cpub_clk_axi_sel = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_axi_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_div2", - "cpub_clk_div3", - "cpub_clk_div4", - "cpub_clk_div5", - "cpub_clk_div6", - "cpub_clk_div7", - "cpub_clk_div8" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_div2.hw, + &g12b_cpub_clk_div3.hw, + &g12b_cpub_clk_div4.hw, + &g12b_cpub_clk_div5.hw, + &g12b_cpub_clk_div6.hw, + &g12b_cpub_clk_div7.hw, + &g12b_cpub_clk_div8.hw + }, .num_parents = 7, }, }; @@ -899,7 +1062,9 @@ static struct clk_regmap g12b_cpub_clk_axi = { .hw.init = &(struct clk_init_data) { .name = "cpub_clk_axi", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_axi_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_axi_sel.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -918,13 +1083,15 @@ static struct clk_regmap g12b_cpub_clk_trace_sel = { .hw.init = &(struct clk_init_data){ .name = "cpub_clk_trace_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_div2", - "cpub_clk_div3", - "cpub_clk_div4", - "cpub_clk_div5", - "cpub_clk_div6", - "cpub_clk_div7", - "cpub_clk_div8" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_div2.hw, + &g12b_cpub_clk_div3.hw, + &g12b_cpub_clk_div4.hw, + &g12b_cpub_clk_div5.hw, + &g12b_cpub_clk_div6.hw, + &g12b_cpub_clk_div7.hw, + &g12b_cpub_clk_div8.hw + }, .num_parents = 7, }, }; @@ -938,7 +1105,9 @@ static struct clk_regmap g12b_cpub_clk_trace = { .hw.init = &(struct clk_init_data) { .name = "cpub_clk_trace", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cpub_clk_trace_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12b_cpub_clk_trace_sel.hw + }, .num_parents = 1, /* * This clock is set by the ROM monitor code, @@ -1003,7 +1172,9 @@ static struct clk_regmap g12a_gp0_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -1019,7 +1190,9 @@ static struct clk_regmap g12a_gp0_pll = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gp0_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_gp0_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1077,7 +1250,9 @@ static struct clk_regmap g12a_hifi_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "hifi_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -1093,7 +1268,9 @@ static struct clk_regmap g12a_hifi_pll = { .hw.init = &(struct clk_init_data){ .name = "hifi_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "hifi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_hifi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1164,7 +1341,9 @@ static struct clk_regmap g12a_pcie_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_dco", .ops = &meson_clk_pcie_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -1175,7 +1354,9 @@ static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_dco_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "pcie_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_pcie_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1193,7 +1374,9 @@ static struct clk_regmap g12a_pcie_pll_od = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_od", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "pcie_pll_dco_div2" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_pcie_pll_dco_div2.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1205,7 +1388,9 @@ static struct clk_fixed_factor g12a_pcie_pll = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_pll", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "pcie_pll_od" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_pcie_pll_od.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1247,7 +1432,9 @@ static struct clk_regmap g12a_hdmi_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, /* * Display directly handle hdmi pll registers ATM, we need @@ -1267,7 +1454,9 @@ static struct clk_regmap g12a_hdmi_pll_od = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -1283,7 +1472,9 @@ static struct clk_regmap g12a_hdmi_pll_od2 = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od2", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_hdmi_pll_od.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -1299,77 +1490,21 @@ static struct clk_regmap g12a_hdmi_pll = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od2" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_hdmi_pll_od2.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, }; -static struct clk_fixed_factor g12a_fclk_div2_div = { - .mult = 1, - .div = 2, - .hw.init = &(struct clk_init_data){ - .name = "fclk_div2_div", - .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, - .num_parents = 1, - }, -}; - -static struct clk_regmap g12a_fclk_div2 = { - .data = &(struct clk_regmap_gate_data){ - .offset = HHI_FIX_PLL_CNTL1, - .bit_idx = 24, - }, - .hw.init = &(struct clk_init_data){ - .name = "fclk_div2", - .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div2_div" }, - .num_parents = 1, - }, -}; - -static struct clk_fixed_factor g12a_fclk_div3_div = { - .mult = 1, - .div = 3, - .hw.init = &(struct clk_init_data){ - .name = "fclk_div3_div", - .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, - .num_parents = 1, - }, -}; - -static struct clk_regmap g12a_fclk_div3 = { - .data = &(struct clk_regmap_gate_data){ - .offset = HHI_FIX_PLL_CNTL1, - .bit_idx = 20, - }, - .hw.init = &(struct clk_init_data){ - .name = "fclk_div3", - .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div3_div" }, - .num_parents = 1, - /* - * This clock is used by the resident firmware and is required - * by the platform to operate correctly. - * Until the following condition are met, we need this clock to - * be marked as critical: - * a) Mark the clock used by a firmware resource, if possible - * b) CCF has a clock hand-off mechanism to make the sure the - * clock stays on until the proper driver comes along - */ - .flags = CLK_IS_CRITICAL, - }, -}; - static struct clk_fixed_factor g12a_fclk_div4_div = { .mult = 1, .div = 4, .hw.init = &(struct clk_init_data){ .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw }, .num_parents = 1, }, }; @@ -1382,7 +1517,9 @@ static struct clk_regmap g12a_fclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div4_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div4_div.hw + }, .num_parents = 1, }, }; @@ -1393,7 +1530,7 @@ static struct clk_fixed_factor g12a_fclk_div5_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw }, .num_parents = 1, }, }; @@ -1406,7 +1543,9 @@ static struct clk_regmap g12a_fclk_div5 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div5_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div5_div.hw + }, .num_parents = 1, }, }; @@ -1417,7 +1556,7 @@ static struct clk_fixed_factor g12a_fclk_div7_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_fixed_pll.hw }, .num_parents = 1, }, }; @@ -1430,7 +1569,9 @@ static struct clk_regmap g12a_fclk_div7 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div7_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div7_div.hw + }, .num_parents = 1, }, }; @@ -1441,7 +1582,9 @@ static struct clk_fixed_factor g12a_fclk_div2p5_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2p5_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fixed_pll_dco.hw + }, .num_parents = 1, }, }; @@ -1454,7 +1597,9 @@ static struct clk_regmap g12a_fclk_div2p5 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2p5", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div2p5_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fclk_div2p5_div.hw + }, .num_parents = 1, }, }; @@ -1465,7 +1610,9 @@ static struct clk_fixed_factor g12a_mpll_50m_div = { .hw.init = &(struct clk_init_data){ .name = "mpll_50m_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fixed_pll_dco.hw + }, .num_parents = 1, }, }; @@ -1479,8 +1626,10 @@ static struct clk_regmap g12a_mpll_50m = { .hw.init = &(struct clk_init_data){ .name = "mpll_50m", .ops = &clk_regmap_mux_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal", - "mpll_50m_div" }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &g12a_mpll_50m_div.hw }, + }, .num_parents = 2, }, }; @@ -1491,7 +1640,9 @@ static struct clk_fixed_factor g12a_mpll_prediv = { .hw.init = &(struct clk_init_data){ .name = "mpll_prediv", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_fixed_pll_dco.hw + }, .num_parents = 1, }, }; @@ -1529,7 +1680,9 @@ static struct clk_regmap g12a_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -1542,7 +1695,7 @@ static struct clk_regmap g12a_mpll0 = { .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll0_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_mpll0_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1581,7 +1734,9 @@ static struct clk_regmap g12a_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -1594,7 +1749,7 @@ static struct clk_regmap g12a_mpll1 = { .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll1_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_mpll1_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1633,7 +1788,9 @@ static struct clk_regmap g12a_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -1646,7 +1803,7 @@ static struct clk_regmap g12a_mpll2 = { .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll2_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_mpll2_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1685,7 +1842,9 @@ static struct clk_regmap g12a_mpll3_div = { .hw.init = &(struct clk_init_data){ .name = "mpll3_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -1698,16 +1857,21 @@ static struct clk_regmap g12a_mpll3 = { .hw.init = &(struct clk_init_data){ .name = "mpll3", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll3_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_mpll3_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; -static const char * const clk81_parent_names[] = { - IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", - "fclk_div3", "fclk_div5" +static const struct clk_parent_data clk81_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div7.hw }, + { .hw = &g12a_mpll1.hw }, + { .hw = &g12a_mpll2.hw }, + { .hw = &g12a_fclk_div4.hw }, + { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div5.hw }, }; static struct clk_regmap g12a_mpeg_clk_sel = { @@ -1720,8 +1884,8 @@ static struct clk_regmap g12a_mpeg_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = clk81_parent_names, - .num_parents = ARRAY_SIZE(clk81_parent_names), + .parent_data = clk81_parent_data, + .num_parents = ARRAY_SIZE(clk81_parent_data), }, }; @@ -1734,7 +1898,9 @@ static struct clk_regmap g12a_mpeg_clk_div = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpeg_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1748,15 +1914,20 @@ static struct clk_regmap g12a_clk81 = { .hw.init = &(struct clk_init_data){ .name = "clk81", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpeg_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mpeg_clk_div.hw + }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), }, }; -static const char * const g12a_sd_emmc_clk0_parent_names[] = { - IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", - +static const struct clk_parent_data g12a_sd_emmc_clk0_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div2.hw }, + { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div5.hw }, + { .hw = &g12a_fclk_div7.hw }, /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All @@ -1775,8 +1946,8 @@ static struct clk_regmap g12a_sd_emmc_a_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names), + .parent_data = g12a_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1790,7 +1961,9 @@ static struct clk_regmap g12a_sd_emmc_a_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_a_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1804,7 +1977,9 @@ static struct clk_regmap g12a_sd_emmc_a_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_a_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_a_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1820,8 +1995,8 @@ static struct clk_regmap g12a_sd_emmc_b_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names), + .parent_data = g12a_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1835,7 +2010,9 @@ static struct clk_regmap g12a_sd_emmc_b_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_b_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1849,7 +2026,9 @@ static struct clk_regmap g12a_sd_emmc_b_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_b_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_b_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1865,8 +2044,8 @@ static struct clk_regmap g12a_sd_emmc_c_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names), + .parent_data = g12a_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1880,7 +2059,9 @@ static struct clk_regmap g12a_sd_emmc_c_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_c_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1894,17 +2075,89 @@ static struct clk_regmap g12a_sd_emmc_c_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_c_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_sd_emmc_c_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; +/* Video Clocks */ + +static struct clk_regmap g12a_vid_pll_div = { + .data = &(struct meson_vid_pll_div_data){ + .val = { + .reg_off = HHI_VID_PLL_CLK_DIV, + .shift = 0, + .width = 15, + }, + .sel = { + .reg_off = HHI_VID_PLL_CLK_DIV, + .shift = 16, + .width = 2, + }, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll_div", + .ops = &meson_vid_pll_div_ro_ops, + .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_pll.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, + }, +}; + +static const struct clk_hw *g12a_vid_pll_parent_hws[] = { + &g12a_vid_pll_div.hw, + &g12a_hdmi_pll.hw, +}; + +static struct clk_regmap g12a_vid_pll_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VID_PLL_CLK_DIV, + .mask = 0x1, + .shift = 18, + }, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll_sel", + .ops = &clk_regmap_mux_ops, + /* + * bit 18 selects from 2 possible parents: + * vid_pll_div or hdmi_pll + */ + .parent_hws = g12a_vid_pll_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_hws), + .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_regmap g12a_vid_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VID_PLL_CLK_DIV, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vid_pll_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + /* VPU Clock */ -static const char * const g12a_vpu_parent_names[] = { - "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", - "mpll1", "vid_pll", "hifi_pll", "gp0_pll", +static const struct clk_hw *g12a_vpu_parent_hws[] = { + &g12a_fclk_div3.hw, + &g12a_fclk_div4.hw, + &g12a_fclk_div5.hw, + &g12a_fclk_div7.hw, + &g12a_mpll1.hw, + &g12a_vid_pll.hw, + &g12a_hifi_pll.hw, + &g12a_gp0_pll.hw, }; static struct clk_regmap g12a_vpu_0_sel = { @@ -1916,8 +2169,8 @@ static struct clk_regmap g12a_vpu_0_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vpu_parent_names, - .num_parents = ARRAY_SIZE(g12a_vpu_parent_names), + .parent_hws = g12a_vpu_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vpu_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1931,7 +2184,7 @@ static struct clk_regmap g12a_vpu_0_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_0_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1945,7 +2198,7 @@ static struct clk_regmap g12a_vpu_0 = { .hw.init = &(struct clk_init_data) { .name = "vpu_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_0_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_0_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1960,8 +2213,8 @@ static struct clk_regmap g12a_vpu_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vpu_parent_names, - .num_parents = ARRAY_SIZE(g12a_vpu_parent_names), + .parent_hws = g12a_vpu_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vpu_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1975,7 +2228,7 @@ static struct clk_regmap g12a_vpu_1_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_1_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1989,7 +2242,7 @@ static struct clk_regmap g12a_vpu_1 = { .hw.init = &(struct clk_init_data) { .name = "vpu_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_1_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vpu_1_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2008,7 +2261,10 @@ static struct clk_regmap g12a_vpu = { * bit 31 selects from 2 possible parents: * vpu_0 or vpu_1 */ - .parent_names = (const char *[]){ "vpu_0", "vpu_1" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vpu_0.hw, + &g12a_vpu_1.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2016,9 +2272,14 @@ static struct clk_regmap g12a_vpu = { /* VDEC clocks */ -static const char * const g12a_vdec_parent_names[] = { - "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", - "hifi_pll", "gp0_pll", +static const struct clk_hw *g12a_vdec_parent_hws[] = { + &g12a_fclk_div2p5.hw, + &g12a_fclk_div3.hw, + &g12a_fclk_div4.hw, + &g12a_fclk_div5.hw, + &g12a_fclk_div7.hw, + &g12a_hifi_pll.hw, + &g12a_gp0_pll.hw, }; static struct clk_regmap g12a_vdec_1_sel = { @@ -2031,8 +2292,8 @@ static struct clk_regmap g12a_vdec_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vdec_parent_names, - .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .parent_hws = g12a_vdec_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2047,7 +2308,9 @@ static struct clk_regmap g12a_vdec_1_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2061,7 +2324,9 @@ static struct clk_regmap g12a_vdec_1 = { .hw.init = &(struct clk_init_data) { .name = "vdec_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2077,8 +2342,8 @@ static struct clk_regmap g12a_vdec_hevcf_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevcf_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vdec_parent_names, - .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .parent_hws = g12a_vdec_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2093,7 +2358,9 @@ static struct clk_regmap g12a_vdec_hevcf_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevcf_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_hevcf_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_hevcf_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2107,7 +2374,9 @@ static struct clk_regmap g12a_vdec_hevcf = { .hw.init = &(struct clk_init_data) { .name = "vdec_hevcf", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_hevcf_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_hevcf_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2123,8 +2392,8 @@ static struct clk_regmap g12a_vdec_hevc_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vdec_parent_names, - .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .parent_hws = g12a_vdec_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2139,7 +2408,9 @@ static struct clk_regmap g12a_vdec_hevc_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_hevc_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_hevc_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2153,7 +2424,9 @@ static struct clk_regmap g12a_vdec_hevc = { .hw.init = &(struct clk_init_data) { .name = "vdec_hevc", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_hevc_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vdec_hevc_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2161,9 +2434,15 @@ static struct clk_regmap g12a_vdec_hevc = { /* VAPB Clock */ -static const char * const g12a_vapb_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", - "mpll1", "vid_pll", "mpll2", "fclk_div2p5", +static const struct clk_hw *g12a_vapb_parent_hws[] = { + &g12a_fclk_div4.hw, + &g12a_fclk_div3.hw, + &g12a_fclk_div5.hw, + &g12a_fclk_div7.hw, + &g12a_mpll1.hw, + &g12a_vid_pll.hw, + &g12a_mpll2.hw, + &g12a_fclk_div2p5.hw, }; static struct clk_regmap g12a_vapb_0_sel = { @@ -2175,8 +2454,8 @@ static struct clk_regmap g12a_vapb_0_sel = { .hw.init = &(struct clk_init_data){ .name = "vapb_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vapb_parent_names, - .num_parents = ARRAY_SIZE(g12a_vapb_parent_names), + .parent_hws = g12a_vapb_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vapb_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -2190,7 +2469,9 @@ static struct clk_regmap g12a_vapb_0_div = { .hw.init = &(struct clk_init_data){ .name = "vapb_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vapb_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vapb_0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2204,7 +2485,9 @@ static struct clk_regmap g12a_vapb_0 = { .hw.init = &(struct clk_init_data) { .name = "vapb_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vapb_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2219,8 +2502,8 @@ static struct clk_regmap g12a_vapb_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vapb_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vapb_parent_names, - .num_parents = ARRAY_SIZE(g12a_vapb_parent_names), + .parent_hws = g12a_vapb_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vapb_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -2234,7 +2517,9 @@ static struct clk_regmap g12a_vapb_1_div = { .hw.init = &(struct clk_init_data){ .name = "vapb_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vapb_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vapb_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2248,7 +2533,9 @@ static struct clk_regmap g12a_vapb_1 = { .hw.init = &(struct clk_init_data) { .name = "vapb_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vapb_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2267,7 +2554,10 @@ static struct clk_regmap g12a_vapb_sel = { * bit 31 selects from 2 possible parents: * vapb_0 or vapb_1 */ - .parent_names = (const char *[]){ "vapb_0", "vapb_1" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vapb_0.hw, + &g12a_vapb_1.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2281,75 +2571,21 @@ static struct clk_regmap g12a_vapb = { .hw.init = &(struct clk_init_data) { .name = "vapb", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vapb_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, }; -/* Video Clocks */ - -static struct clk_regmap g12a_vid_pll_div = { - .data = &(struct meson_vid_pll_div_data){ - .val = { - .reg_off = HHI_VID_PLL_CLK_DIV, - .shift = 0, - .width = 15, - }, - .sel = { - .reg_off = HHI_VID_PLL_CLK_DIV, - .shift = 16, - .width = 2, - }, - }, - .hw.init = &(struct clk_init_data) { - .name = "vid_pll_div", - .ops = &meson_vid_pll_div_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, - }, -}; - -static const char * const g12a_vid_pll_parent_names[] = { "vid_pll_div", - "hdmi_pll" }; - -static struct clk_regmap g12a_vid_pll_sel = { - .data = &(struct clk_regmap_mux_data){ - .offset = HHI_VID_PLL_CLK_DIV, - .mask = 0x1, - .shift = 18, - }, - .hw.init = &(struct clk_init_data){ - .name = "vid_pll_sel", - .ops = &clk_regmap_mux_ops, - /* - * bit 18 selects from 2 possible parents: - * vid_pll_div or hdmi_pll - */ - .parent_names = g12a_vid_pll_parent_names, - .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_names), - .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_regmap g12a_vid_pll = { - .data = &(struct clk_regmap_gate_data){ - .offset = HHI_VID_PLL_CLK_DIV, - .bit_idx = 19, - }, - .hw.init = &(struct clk_init_data) { - .name = "vid_pll", - .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vid_pll_sel" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, - }, -}; - -static const char * const g12a_vclk_parent_names[] = { - "vid_pll", "gp0_pll", "hifi_pll", "mpll1", "fclk_div3", "fclk_div4", - "fclk_div5", "fclk_div7" +static const struct clk_hw *g12a_vclk_parent_hws[] = { + &g12a_vid_pll.hw, + &g12a_gp0_pll.hw, + &g12a_hifi_pll.hw, + &g12a_mpll1.hw, + &g12a_fclk_div3.hw, + &g12a_fclk_div4.hw, + &g12a_fclk_div5.hw, + &g12a_fclk_div7.hw, }; static struct clk_regmap g12a_vclk_sel = { @@ -2361,8 +2597,8 @@ static struct clk_regmap g12a_vclk_sel = { .hw.init = &(struct clk_init_data){ .name = "vclk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vclk_parent_names, - .num_parents = ARRAY_SIZE(g12a_vclk_parent_names), + .parent_hws = g12a_vclk_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2376,8 +2612,8 @@ static struct clk_regmap g12a_vclk2_sel = { .hw.init = &(struct clk_init_data){ .name = "vclk2_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_vclk_parent_names, - .num_parents = ARRAY_SIZE(g12a_vclk_parent_names), + .parent_hws = g12a_vclk_parent_hws, + .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2390,7 +2626,7 @@ static struct clk_regmap g12a_vclk_input = { .hw.init = &(struct clk_init_data) { .name = "vclk_input", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2404,7 +2640,7 @@ static struct clk_regmap g12a_vclk2_input = { .hw.init = &(struct clk_init_data) { .name = "vclk2_input", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2419,7 +2655,9 @@ static struct clk_regmap g12a_vclk_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vclk_input" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk_input.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -2434,7 +2672,9 @@ static struct clk_regmap g12a_vclk2_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vclk2_input" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk2_input.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -2448,7 +2688,7 @@ static struct clk_regmap g12a_vclk = { .hw.init = &(struct clk_init_data) { .name = "vclk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2462,7 +2702,7 @@ static struct clk_regmap g12a_vclk2 = { .hw.init = &(struct clk_init_data) { .name = "vclk2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2476,7 +2716,7 @@ static struct clk_regmap g12a_vclk_div1 = { .hw.init = &(struct clk_init_data) { .name = "vclk_div1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2490,7 +2730,7 @@ static struct clk_regmap g12a_vclk_div2_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div2_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2504,7 +2744,7 @@ static struct clk_regmap g12a_vclk_div4_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div4_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2518,7 +2758,7 @@ static struct clk_regmap g12a_vclk_div6_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div6_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2532,7 +2772,7 @@ static struct clk_regmap g12a_vclk_div12_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div12_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2546,7 +2786,7 @@ static struct clk_regmap g12a_vclk2_div1 = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2560,7 +2800,7 @@ static struct clk_regmap g12a_vclk2_div2_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div2_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2574,7 +2814,7 @@ static struct clk_regmap g12a_vclk2_div4_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div4_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2588,7 +2828,7 @@ static struct clk_regmap g12a_vclk2_div6_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div6_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2602,7 +2842,7 @@ static struct clk_regmap g12a_vclk2_div12_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div12_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2614,7 +2854,9 @@ static struct clk_fixed_factor g12a_vclk_div2 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div2_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk_div2_en.hw + }, .num_parents = 1, }, }; @@ -2625,7 +2867,9 @@ static struct clk_fixed_factor g12a_vclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div4_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk_div4_en.hw + }, .num_parents = 1, }, }; @@ -2636,7 +2880,9 @@ static struct clk_fixed_factor g12a_vclk_div6 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div6_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk_div6_en.hw + }, .num_parents = 1, }, }; @@ -2647,7 +2893,9 @@ static struct clk_fixed_factor g12a_vclk_div12 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div12_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk_div12_en.hw + }, .num_parents = 1, }, }; @@ -2658,7 +2906,9 @@ static struct clk_fixed_factor g12a_vclk2_div2 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div2_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk2_div2_en.hw + }, .num_parents = 1, }, }; @@ -2669,7 +2919,9 @@ static struct clk_fixed_factor g12a_vclk2_div4 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div4_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk2_div4_en.hw + }, .num_parents = 1, }, }; @@ -2680,7 +2932,9 @@ static struct clk_fixed_factor g12a_vclk2_div6 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div6_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk2_div6_en.hw + }, .num_parents = 1, }, }; @@ -2691,16 +2945,25 @@ static struct clk_fixed_factor g12a_vclk2_div12 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div12_en" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_vclk2_div12_en.hw + }, .num_parents = 1, }, }; static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; -static const char * const g12a_cts_parent_names[] = { - "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6", - "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4", - "vclk2_div6", "vclk2_div12" +static const struct clk_hw *g12a_cts_parent_hws[] = { + &g12a_vclk_div1.hw, + &g12a_vclk_div2.hw, + &g12a_vclk_div4.hw, + &g12a_vclk_div6.hw, + &g12a_vclk_div12.hw, + &g12a_vclk2_div1.hw, + &g12a_vclk2_div2.hw, + &g12a_vclk2_div4.hw, + &g12a_vclk2_div6.hw, + &g12a_vclk2_div12.hw, }; static struct clk_regmap g12a_cts_enci_sel = { @@ -2713,8 +2976,8 @@ static struct clk_regmap g12a_cts_enci_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_enci_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_cts_parent_names, - .num_parents = ARRAY_SIZE(g12a_cts_parent_names), + .parent_hws = g12a_cts_parent_hws, + .num_parents = ARRAY_SIZE(g12a_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2729,8 +2992,8 @@ static struct clk_regmap g12a_cts_encp_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_encp_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_cts_parent_names, - .num_parents = ARRAY_SIZE(g12a_cts_parent_names), + .parent_hws = g12a_cts_parent_hws, + .num_parents = ARRAY_SIZE(g12a_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2745,18 +3008,25 @@ static struct clk_regmap g12a_cts_vdac_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_vdac_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_cts_parent_names, - .num_parents = ARRAY_SIZE(g12a_cts_parent_names), + .parent_hws = g12a_cts_parent_hws, + .num_parents = ARRAY_SIZE(g12a_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; /* TOFIX: add support for cts_tcon */ static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; -static const char * const g12a_cts_hdmi_tx_parent_names[] = { - "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6", - "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4", - "vclk2_div6", "vclk2_div12" +static const struct clk_hw *g12a_cts_hdmi_tx_parent_hws[] = { + &g12a_vclk_div1.hw, + &g12a_vclk_div2.hw, + &g12a_vclk_div4.hw, + &g12a_vclk_div6.hw, + &g12a_vclk_div12.hw, + &g12a_vclk2_div1.hw, + &g12a_vclk2_div2.hw, + &g12a_vclk2_div4.hw, + &g12a_vclk2_div6.hw, + &g12a_vclk2_div12.hw, }; static struct clk_regmap g12a_hdmi_tx_sel = { @@ -2769,8 +3039,8 @@ static struct clk_regmap g12a_hdmi_tx_sel = { .hw.init = &(struct clk_init_data){ .name = "hdmi_tx_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_cts_hdmi_tx_parent_names, - .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_names), + .parent_hws = g12a_cts_hdmi_tx_parent_hws, + .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2783,7 +3053,9 @@ static struct clk_regmap g12a_cts_enci = { .hw.init = &(struct clk_init_data) { .name = "cts_enci", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_enci_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cts_enci_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2797,7 +3069,9 @@ static struct clk_regmap g12a_cts_encp = { .hw.init = &(struct clk_init_data) { .name = "cts_encp", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_encp_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cts_encp_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2811,7 +3085,9 @@ static struct clk_regmap g12a_cts_vdac = { .hw.init = &(struct clk_init_data) { .name = "cts_vdac", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_vdac_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_cts_vdac_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2825,7 +3101,9 @@ static struct clk_regmap g12a_hdmi_tx = { .hw.init = &(struct clk_init_data) { .name = "hdmi_tx", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "hdmi_tx_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_hdmi_tx_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2833,8 +3111,11 @@ static struct clk_regmap g12a_hdmi_tx = { /* HDMI Clocks */ -static const char * const g12a_hdmi_parent_names[] = { - IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5" +static const struct clk_parent_data g12a_hdmi_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_fclk_div4.hw }, + { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div5.hw }, }; static struct clk_regmap g12a_hdmi_sel = { @@ -2847,8 +3128,8 @@ static struct clk_regmap g12a_hdmi_sel = { .hw.init = &(struct clk_init_data){ .name = "hdmi_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_hdmi_parent_names, - .num_parents = ARRAY_SIZE(g12a_hdmi_parent_names), + .parent_data = g12a_hdmi_parent_data, + .num_parents = ARRAY_SIZE(g12a_hdmi_parent_data), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2862,7 +3143,7 @@ static struct clk_regmap g12a_hdmi_div = { .hw.init = &(struct clk_init_data){ .name = "hdmi_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "hdmi_sel" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_sel.hw }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -2876,7 +3157,7 @@ static struct clk_regmap g12a_hdmi = { .hw.init = &(struct clk_init_data) { .name = "hdmi", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "hdmi_div" }, + .parent_hws = (const struct clk_hw *[]) { &g12a_hdmi_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2886,10 +3167,15 @@ static struct clk_regmap g12a_hdmi = { * The MALI IP is clocked by two identical clocks (mali_0 and mali_1) * muxed by a glitch-free switch. */ - -static const char * const g12a_mali_0_1_parent_names[] = { - IN_PREFIX "xtal", "gp0_pll", "hifi_pll", "fclk_div2p5", - "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7" +static const struct clk_parent_data g12a_mali_0_1_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_gp0_pll.hw }, + { .hw = &g12a_hifi_pll.hw }, + { .hw = &g12a_fclk_div2p5.hw }, + { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div4.hw }, + { .hw = &g12a_fclk_div5.hw }, + { .hw = &g12a_fclk_div7.hw }, }; static struct clk_regmap g12a_mali_0_sel = { @@ -2901,7 +3187,7 @@ static struct clk_regmap g12a_mali_0_sel = { .hw.init = &(struct clk_init_data){ .name = "mali_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_mali_0_1_parent_names, + .parent_data = g12a_mali_0_1_parent_data, .num_parents = 8, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2916,7 +3202,9 @@ static struct clk_regmap g12a_mali_0_div = { .hw.init = &(struct clk_init_data){ .name = "mali_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mali_0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2930,7 +3218,9 @@ static struct clk_regmap g12a_mali_0 = { .hw.init = &(struct clk_init_data){ .name = "mali_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mali_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2945,7 +3235,7 @@ static struct clk_regmap g12a_mali_1_sel = { .hw.init = &(struct clk_init_data){ .name = "mali_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_mali_0_1_parent_names, + .parent_data = g12a_mali_0_1_parent_data, .num_parents = 8, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2960,7 +3250,9 @@ static struct clk_regmap g12a_mali_1_div = { .hw.init = &(struct clk_init_data){ .name = "mali_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mali_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -2974,14 +3266,17 @@ static struct clk_regmap g12a_mali_1 = { .hw.init = &(struct clk_init_data){ .name = "mali_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_mali_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const g12a_mali_parent_names[] = { - "mali_0", "mali_1" +static const struct clk_hw *g12a_mali_parent_hws[] = { + &g12a_mali_0.hw, + &g12a_mali_1.hw, }; static struct clk_regmap g12a_mali = { @@ -2993,7 +3288,7 @@ static struct clk_regmap g12a_mali = { .hw.init = &(struct clk_init_data){ .name = "mali", .ops = &clk_regmap_mux_ops, - .parent_names = g12a_mali_parent_names, + .parent_hws = g12a_mali_parent_hws, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -3008,7 +3303,9 @@ static struct clk_regmap g12a_ts_div = { .hw.init = &(struct clk_init_data){ .name = "ts_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -3021,7 +3318,9 @@ static struct clk_regmap g12a_ts = { .hw.init = &(struct clk_init_data){ .name = "ts", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "ts_div" }, + .parent_hws = (const struct clk_hw *[]) { + &g12a_ts_div.hw + }, .num_parents = 1, }, }; -- GitLab From 0dea3f35996f4571eacbf6cac889d57bfd20822a Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:33 +0200 Subject: [PATCH 1001/7155] clk: meson: gxbb: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (ie. when all clocks are local to the controller) and use .parent_data otherwise. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 654 +++++++++++++++++++++++++++------------ 1 file changed, 451 insertions(+), 203 deletions(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index dab16d9b1af8..67e466356d4b 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -10,15 +10,12 @@ #include #include "gxbb.h" -#include "clk-input.h" #include "clk-regmap.h" #include "clk-pll.h" #include "clk-mpll.h" #include "meson-eeclk.h" #include "vid-pll-div.h" -#define IN_PREFIX "ee-in-" - static DEFINE_SPINLOCK(meson_clk_lock); static const struct pll_params_table gxbb_gp0_pll_params_table[] = { @@ -121,7 +118,9 @@ static struct clk_regmap gxbb_fixed_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -136,7 +135,9 @@ static struct clk_regmap gxbb_fixed_pll = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fixed_pll_dco.hw + }, .num_parents = 1, /* * This clock won't ever change at runtime so @@ -151,7 +152,9 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_pre_mult", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -192,7 +195,9 @@ static struct clk_regmap gxbb_hdmi_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_pre_mult" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_hdmi_pll_pre_mult.hw + }, .num_parents = 1, /* * Display directly handle hdmi pll registers ATM, we need @@ -244,7 +249,9 @@ static struct clk_regmap gxl_hdmi_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, /* * Display directly handle hdmi pll registers ATM, we need @@ -264,7 +271,9 @@ static struct clk_regmap gxbb_hdmi_pll_od = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -280,7 +289,9 @@ static struct clk_regmap gxbb_hdmi_pll_od2 = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od2", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_hdmi_pll_od.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -296,7 +307,9 @@ static struct clk_regmap gxbb_hdmi_pll = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od2" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_hdmi_pll_od2.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -312,7 +325,9 @@ static struct clk_regmap gxl_hdmi_pll_od = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &gxl_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -328,7 +343,9 @@ static struct clk_regmap gxl_hdmi_pll_od2 = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_od2", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od" }, + .parent_hws = (const struct clk_hw *[]) { + &gxl_hdmi_pll_od.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -344,7 +361,9 @@ static struct clk_regmap gxl_hdmi_pll = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_od2" }, + .parent_hws = (const struct clk_hw *[]) { + &gxl_hdmi_pll_od2.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, }, @@ -381,7 +400,9 @@ static struct clk_regmap gxbb_sys_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "sys_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -396,7 +417,9 @@ static struct clk_regmap gxbb_sys_pll = { .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "sys_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sys_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -442,7 +465,9 @@ static struct clk_regmap gxbb_gp0_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -494,7 +519,9 @@ static struct clk_regmap gxl_gp0_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -509,7 +536,17 @@ static struct clk_regmap gxbb_gp0_pll = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gp0_pll_dco" }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * GXL and GXBB have different gp0_pll_dco (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so gp0_pll picks up the + * appropriate one. + */ + .name = "gp0_pll_dco", + .index = -1, + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -521,7 +558,9 @@ static struct clk_fixed_factor gxbb_fclk_div2_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -534,7 +573,9 @@ static struct clk_regmap gxbb_fclk_div2 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fclk_div2_div.hw + }, .num_parents = 1, .flags = CLK_IS_CRITICAL, }, @@ -546,7 +587,7 @@ static struct clk_fixed_factor gxbb_fclk_div3_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw }, .num_parents = 1, }, }; @@ -559,7 +600,9 @@ static struct clk_regmap gxbb_fclk_div3 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div3_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fclk_div3_div.hw + }, .num_parents = 1, /* * FIXME: @@ -582,7 +625,7 @@ static struct clk_fixed_factor gxbb_fclk_div4_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw }, .num_parents = 1, }, }; @@ -595,7 +638,9 @@ static struct clk_regmap gxbb_fclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div4_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fclk_div4_div.hw + }, .num_parents = 1, }, }; @@ -606,7 +651,7 @@ static struct clk_fixed_factor gxbb_fclk_div5_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw }, .num_parents = 1, }, }; @@ -619,7 +664,9 @@ static struct clk_regmap gxbb_fclk_div5 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div5_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fclk_div5_div.hw + }, .num_parents = 1, }, }; @@ -630,7 +677,7 @@ static struct clk_fixed_factor gxbb_fclk_div7_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw }, .num_parents = 1, }, }; @@ -643,7 +690,9 @@ static struct clk_regmap gxbb_fclk_div7 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div7_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_fclk_div7_div.hw + }, .num_parents = 1, }, }; @@ -657,7 +706,7 @@ static struct clk_regmap gxbb_mpll_prediv = { .hw.init = &(struct clk_init_data){ .name = "mpll_prediv", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw }, .num_parents = 1, }, }; @@ -684,7 +733,9 @@ static struct clk_regmap gxbb_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -697,7 +748,7 @@ static struct clk_regmap gxbb_mpll0 = { .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll0_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -725,7 +776,9 @@ static struct clk_regmap gxbb_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -738,7 +791,7 @@ static struct clk_regmap gxbb_mpll1 = { .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll1_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll1_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -766,7 +819,9 @@ static struct clk_regmap gxbb_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -779,16 +834,21 @@ static struct clk_regmap gxbb_mpll2 = { .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll2_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll2_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; -static const char * const clk81_parent_names[] = { - IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", - "fclk_div3", "fclk_div5" +static const struct clk_parent_data clk81_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &gxbb_fclk_div7.hw }, + { .hw = &gxbb_mpll1.hw }, + { .hw = &gxbb_mpll2.hw }, + { .hw = &gxbb_fclk_div4.hw }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, }; static struct clk_regmap gxbb_mpeg_clk_sel = { @@ -806,8 +866,8 @@ static struct clk_regmap gxbb_mpeg_clk_sel = { * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, * fclk_div4, fclk_div3, fclk_div5 */ - .parent_names = clk81_parent_names, - .num_parents = ARRAY_SIZE(clk81_parent_names), + .parent_data = clk81_parent_data, + .num_parents = ARRAY_SIZE(clk81_parent_data), }, }; @@ -820,7 +880,9 @@ static struct clk_regmap gxbb_mpeg_clk_div = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpeg_clk_sel.hw + }, .num_parents = 1, }, }; @@ -834,7 +896,9 @@ static struct clk_regmap gxbb_clk81 = { .hw.init = &(struct clk_init_data){ .name = "clk81", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpeg_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpeg_clk_div.hw + }, .num_parents = 1, .flags = CLK_IS_CRITICAL, }, @@ -850,7 +914,10 @@ static struct clk_regmap gxbb_sar_adc_clk_sel = { .name = "sar_adc_clk_sel", .ops = &clk_regmap_mux_ops, /* NOTE: The datasheet doesn't list the parents for bit 10 */ - .parent_names = (const char *[]){ IN_PREFIX "xtal", "clk81", }, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &gxbb_clk81.hw }, + }, .num_parents = 2, }, }; @@ -864,7 +931,9 @@ static struct clk_regmap gxbb_sar_adc_clk_div = { .hw.init = &(struct clk_init_data){ .name = "sar_adc_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sar_adc_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sar_adc_clk_sel.hw + }, .num_parents = 1, }, }; @@ -877,7 +946,9 @@ static struct clk_regmap gxbb_sar_adc_clk = { .hw.init = &(struct clk_init_data){ .name = "sar_adc_clk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sar_adc_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sar_adc_clk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -888,9 +959,15 @@ static struct clk_regmap gxbb_sar_adc_clk = { * muxed by a glitch-free switch. */ -static const char * const gxbb_mali_0_1_parent_names[] = { - IN_PREFIX "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7", - "fclk_div4", "fclk_div3", "fclk_div5" +static const struct clk_parent_data gxbb_mali_0_1_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &gxbb_gp0_pll.hw }, + { .hw = &gxbb_mpll2.hw }, + { .hw = &gxbb_mpll1.hw }, + { .hw = &gxbb_fclk_div7.hw }, + { .hw = &gxbb_fclk_div4.hw }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, }; static struct clk_regmap gxbb_mali_0_sel = { @@ -907,7 +984,7 @@ static struct clk_regmap gxbb_mali_0_sel = { * xtal, gp0_pll, mpll2, mpll1, fclk_div7, * fclk_div4, fclk_div3, fclk_div5 */ - .parent_names = gxbb_mali_0_1_parent_names, + .parent_data = gxbb_mali_0_1_parent_data, .num_parents = 8, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -922,7 +999,9 @@ static struct clk_regmap gxbb_mali_0_div = { .hw.init = &(struct clk_init_data){ .name = "mali_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mali_0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -936,7 +1015,9 @@ static struct clk_regmap gxbb_mali_0 = { .hw.init = &(struct clk_init_data){ .name = "mali_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mali_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -956,7 +1037,7 @@ static struct clk_regmap gxbb_mali_1_sel = { * xtal, gp0_pll, mpll2, mpll1, fclk_div7, * fclk_div4, fclk_div3, fclk_div5 */ - .parent_names = gxbb_mali_0_1_parent_names, + .parent_data = gxbb_mali_0_1_parent_data, .num_parents = 8, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -971,7 +1052,9 @@ static struct clk_regmap gxbb_mali_1_div = { .hw.init = &(struct clk_init_data){ .name = "mali_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mali_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -985,14 +1068,17 @@ static struct clk_regmap gxbb_mali_1 = { .hw.init = &(struct clk_init_data){ .name = "mali_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mali_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const gxbb_mali_parent_names[] = { - "mali_0", "mali_1" +static const struct clk_hw *gxbb_mali_parent_hws[] = { + &gxbb_mali_0.hw, + &gxbb_mali_1.hw, }; static struct clk_regmap gxbb_mali = { @@ -1004,7 +1090,7 @@ static struct clk_regmap gxbb_mali = { .hw.init = &(struct clk_init_data){ .name = "mali", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_mali_parent_names, + .parent_hws = gxbb_mali_parent_hws, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -1021,7 +1107,11 @@ static struct clk_regmap gxbb_cts_amclk_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll0.hw, + &gxbb_mpll1.hw, + &gxbb_mpll2.hw, + }, .num_parents = 3, }, }; @@ -1036,7 +1126,9 @@ static struct clk_regmap gxbb_cts_amclk_div = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "cts_amclk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_amclk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1050,7 +1142,9 @@ static struct clk_regmap gxbb_cts_amclk = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_amclk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_amclk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1067,7 +1161,11 @@ static struct clk_regmap gxbb_cts_mclk_i958_sel = { .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_mpll0.hw, + &gxbb_mpll1.hw, + &gxbb_mpll2.hw, + }, .num_parents = 3, }, }; @@ -1082,7 +1180,9 @@ static struct clk_regmap gxbb_cts_mclk_i958_div = { .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_mclk_i958_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1096,7 +1196,9 @@ static struct clk_regmap gxbb_cts_mclk_i958 = { .hw.init = &(struct clk_init_data){ .name = "cts_mclk_i958", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_mclk_i958_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_mclk_i958_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1111,7 +1213,10 @@ static struct clk_regmap gxbb_cts_i958 = { .hw.init = &(struct clk_init_data){ .name = "cts_i958", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_amclk.hw, + &gxbb_cts_mclk_i958.hw + }, .num_parents = 2, /* *The parent is specific to origin of the audio data. Let the @@ -1121,6 +1226,33 @@ static struct clk_regmap gxbb_cts_i958 = { }, }; +static const struct clk_parent_data gxbb_32k_clk_parent_data[] = { + { .fw_name = "xtal", }, + /* + * FIXME: This clock is provided by the ao clock controller but the + * clock is not yet part of the binding of this controller, so string + * name must be use to set this parent. + */ + { .name = "cts_slow_oscin", .index = -1 }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, +}; + +static struct clk_regmap gxbb_32k_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_32K_CLK_CNTL, + .mask = 0x3, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "32k_clk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = gxbb_32k_clk_parent_data, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static struct clk_regmap gxbb_32k_clk_div = { .data = &(struct clk_regmap_div_data){ .offset = HHI_32K_CLK_CNTL, @@ -1130,7 +1262,9 @@ static struct clk_regmap gxbb_32k_clk_div = { .hw.init = &(struct clk_init_data){ .name = "32k_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "32k_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_32k_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, }, @@ -1144,34 +1278,20 @@ static struct clk_regmap gxbb_32k_clk = { .hw.init = &(struct clk_init_data){ .name = "32k_clk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "32k_clk_div" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - }, -}; - -static const char * const gxbb_32k_clk_parent_names[] = { - IN_PREFIX "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5" -}; - -static struct clk_regmap gxbb_32k_clk_sel = { - .data = &(struct clk_regmap_mux_data){ - .offset = HHI_32K_CLK_CNTL, - .mask = 0x3, - .shift = 16, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_32k_clk_div.hw }, - .hw.init = &(struct clk_init_data){ - .name = "32k_clk_sel", - .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_32k_clk_parent_names, - .num_parents = 4, + .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const gxbb_sd_emmc_clk0_parent_names[] = { - IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", - +static const struct clk_parent_data gxbb_sd_emmc_clk0_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &gxbb_fclk_div2.hw }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, + { .hw = &gxbb_fclk_div7.hw }, /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All @@ -1190,8 +1310,8 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), + .parent_data = gxbb_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1206,7 +1326,9 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_a_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1220,7 +1342,9 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_a_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_a_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1236,8 +1360,8 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), + .parent_data = gxbb_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1252,7 +1376,9 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_b_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1266,7 +1392,9 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_b_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_b_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1282,8 +1410,8 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), + .parent_data = gxbb_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1298,7 +1426,9 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_c_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1312,7 +1442,9 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_c_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_sd_emmc_c_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1320,8 +1452,11 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0 = { /* VPU Clock */ -static const char * const gxbb_vpu_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +static const struct clk_hw *gxbb_vpu_parent_hws[] = { + &gxbb_fclk_div4.hw, + &gxbb_fclk_div3.hw, + &gxbb_fclk_div5.hw, + &gxbb_fclk_div7.hw, }; static struct clk_regmap gxbb_vpu_0_sel = { @@ -1337,8 +1472,8 @@ static struct clk_regmap gxbb_vpu_0_sel = { * bits 9:10 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, */ - .parent_names = gxbb_vpu_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .parent_hws = gxbb_vpu_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1352,7 +1487,7 @@ static struct clk_regmap gxbb_vpu_0_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1366,7 +1501,7 @@ static struct clk_regmap gxbb_vpu_0 = { .hw.init = &(struct clk_init_data) { .name = "vpu_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_0_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1385,8 +1520,8 @@ static struct clk_regmap gxbb_vpu_1_sel = { * bits 25:26 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, */ - .parent_names = gxbb_vpu_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .parent_hws = gxbb_vpu_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1400,7 +1535,7 @@ static struct clk_regmap gxbb_vpu_1_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1414,7 +1549,7 @@ static struct clk_regmap gxbb_vpu_1 = { .hw.init = &(struct clk_init_data) { .name = "vpu_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_1_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1433,7 +1568,10 @@ static struct clk_regmap gxbb_vpu = { * bit 31 selects from 2 possible parents: * vpu_0 or vpu_1 */ - .parent_names = (const char *[]){ "vpu_0", "vpu_1" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vpu_0.hw, + &gxbb_vpu_1.hw + }, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -1441,8 +1579,11 @@ static struct clk_regmap gxbb_vpu = { /* VAPB Clock */ -static const char * const gxbb_vapb_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +static const struct clk_hw *gxbb_vapb_parent_hws[] = { + &gxbb_fclk_div4.hw, + &gxbb_fclk_div3.hw, + &gxbb_fclk_div5.hw, + &gxbb_fclk_div7.hw, }; static struct clk_regmap gxbb_vapb_0_sel = { @@ -1458,8 +1599,8 @@ static struct clk_regmap gxbb_vapb_0_sel = { * bits 9:10 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, */ - .parent_names = gxbb_vapb_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .parent_hws = gxbb_vapb_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1473,7 +1614,9 @@ static struct clk_regmap gxbb_vapb_0_div = { .hw.init = &(struct clk_init_data){ .name = "vapb_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vapb_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vapb_0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1487,7 +1630,9 @@ static struct clk_regmap gxbb_vapb_0 = { .hw.init = &(struct clk_init_data) { .name = "vapb_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vapb_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1506,8 +1651,8 @@ static struct clk_regmap gxbb_vapb_1_sel = { * bits 25:26 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, */ - .parent_names = gxbb_vapb_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .parent_hws = gxbb_vapb_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -1521,7 +1666,9 @@ static struct clk_regmap gxbb_vapb_1_div = { .hw.init = &(struct clk_init_data){ .name = "vapb_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vapb_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vapb_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1535,7 +1682,9 @@ static struct clk_regmap gxbb_vapb_1 = { .hw.init = &(struct clk_init_data) { .name = "vapb_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vapb_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1554,7 +1703,10 @@ static struct clk_regmap gxbb_vapb_sel = { * bit 31 selects from 2 possible parents: * vapb_0 or vapb_1 */ - .parent_names = (const char *[]){ "vapb_0", "vapb_1" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vapb_0.hw, + &gxbb_vapb_1.hw + }, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -1568,7 +1720,7 @@ static struct clk_regmap gxbb_vapb = { .hw.init = &(struct clk_init_data) { .name = "vapb", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vapb_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vapb_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1592,13 +1744,33 @@ static struct clk_regmap gxbb_vid_pll_div = { .hw.init = &(struct clk_init_data) { .name = "vid_pll_div", .ops = &meson_vid_pll_div_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll" }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * GXL and GXBB have different hdmi_plls (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so vid_pll_div picks up the + * appropriate one. + */ + .name = "hdmi_pll", + .index = -1, + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, }, }; -static const char * const gxbb_vid_pll_parent_names[] = { "vid_pll_div", "hdmi_pll" }; +static const struct clk_parent_data gxbb_vid_pll_parent_data[] = { + { .hw = &gxbb_vid_pll_div.hw }, + /* + * Note: + * GXL and GXBB have different hdmi_plls (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so vid_pll_div picks up the + * appropriate one. + */ + { .name = "hdmi_pll", .index = -1 }, +}; static struct clk_regmap gxbb_vid_pll_sel = { .data = &(struct clk_regmap_mux_data){ @@ -1613,8 +1785,8 @@ static struct clk_regmap gxbb_vid_pll_sel = { * bit 18 selects from 2 possible parents: * vid_pll_div or hdmi_pll */ - .parent_names = gxbb_vid_pll_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_names), + .parent_data = gxbb_vid_pll_parent_data, + .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_data), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -1627,15 +1799,22 @@ static struct clk_regmap gxbb_vid_pll = { .hw.init = &(struct clk_init_data) { .name = "vid_pll", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vid_pll_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vid_pll_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, }; -static const char * const gxbb_vclk_parent_names[] = { - "vid_pll", "fclk_div4", "fclk_div3", "fclk_div5", "vid_pll", - "fclk_div7", "mpll1", +static const struct clk_hw *gxbb_vclk_parent_hws[] = { + &gxbb_vid_pll.hw, + &gxbb_fclk_div4.hw, + &gxbb_fclk_div3.hw, + &gxbb_fclk_div5.hw, + &gxbb_vid_pll.hw, + &gxbb_fclk_div7.hw, + &gxbb_mpll1.hw, }; static struct clk_regmap gxbb_vclk_sel = { @@ -1652,8 +1831,8 @@ static struct clk_regmap gxbb_vclk_sel = { * vid_pll, fclk_div4, fclk_div3, fclk_div5, * vid_pll, fclk_div7, mp1 */ - .parent_names = gxbb_vclk_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names), + .parent_hws = gxbb_vclk_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -1672,8 +1851,8 @@ static struct clk_regmap gxbb_vclk2_sel = { * vid_pll, fclk_div4, fclk_div3, fclk_div5, * vid_pll, fclk_div7, mp1 */ - .parent_names = gxbb_vclk_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names), + .parent_hws = gxbb_vclk_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -1686,7 +1865,7 @@ static struct clk_regmap gxbb_vclk_input = { .hw.init = &(struct clk_init_data) { .name = "vclk_input", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1700,7 +1879,7 @@ static struct clk_regmap gxbb_vclk2_input = { .hw.init = &(struct clk_init_data) { .name = "vclk2_input", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_sel.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1715,7 +1894,9 @@ static struct clk_regmap gxbb_vclk_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vclk_input" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk_input.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -1730,7 +1911,9 @@ static struct clk_regmap gxbb_vclk2_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vclk2_input" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk2_input.hw + }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -1744,7 +1927,7 @@ static struct clk_regmap gxbb_vclk = { .hw.init = &(struct clk_init_data) { .name = "vclk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1758,7 +1941,7 @@ static struct clk_regmap gxbb_vclk2 = { .hw.init = &(struct clk_init_data) { .name = "vclk2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1772,7 +1955,7 @@ static struct clk_regmap gxbb_vclk_div1 = { .hw.init = &(struct clk_init_data) { .name = "vclk_div1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1786,7 +1969,7 @@ static struct clk_regmap gxbb_vclk_div2_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div2_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1800,7 +1983,7 @@ static struct clk_regmap gxbb_vclk_div4_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div4_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1814,7 +1997,7 @@ static struct clk_regmap gxbb_vclk_div6_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div6_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1828,7 +2011,7 @@ static struct clk_regmap gxbb_vclk_div12_en = { .hw.init = &(struct clk_init_data) { .name = "vclk_div12_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1842,7 +2025,7 @@ static struct clk_regmap gxbb_vclk2_div1 = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1856,7 +2039,7 @@ static struct clk_regmap gxbb_vclk2_div2_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div2_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1870,7 +2053,7 @@ static struct clk_regmap gxbb_vclk2_div4_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div4_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1884,7 +2067,7 @@ static struct clk_regmap gxbb_vclk2_div6_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div6_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1898,7 +2081,7 @@ static struct clk_regmap gxbb_vclk2_div12_en = { .hw.init = &(struct clk_init_data) { .name = "vclk2_div12_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vclk2" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -1910,7 +2093,9 @@ static struct clk_fixed_factor gxbb_vclk_div2 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div2_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk_div2_en.hw + }, .num_parents = 1, }, }; @@ -1921,7 +2106,9 @@ static struct clk_fixed_factor gxbb_vclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div4_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk_div4_en.hw + }, .num_parents = 1, }, }; @@ -1932,7 +2119,9 @@ static struct clk_fixed_factor gxbb_vclk_div6 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div6_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk_div6_en.hw + }, .num_parents = 1, }, }; @@ -1943,7 +2132,9 @@ static struct clk_fixed_factor gxbb_vclk_div12 = { .hw.init = &(struct clk_init_data){ .name = "vclk_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_div12_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk_div12_en.hw + }, .num_parents = 1, }, }; @@ -1954,7 +2145,9 @@ static struct clk_fixed_factor gxbb_vclk2_div2 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div2_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk2_div2_en.hw + }, .num_parents = 1, }, }; @@ -1965,7 +2158,9 @@ static struct clk_fixed_factor gxbb_vclk2_div4 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div4_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk2_div4_en.hw + }, .num_parents = 1, }, }; @@ -1976,7 +2171,9 @@ static struct clk_fixed_factor gxbb_vclk2_div6 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div6_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk2_div6_en.hw + }, .num_parents = 1, }, }; @@ -1987,16 +2184,25 @@ static struct clk_fixed_factor gxbb_vclk2_div12 = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_div12_en" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vclk2_div12_en.hw + }, .num_parents = 1, }, }; static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; -static const char * const gxbb_cts_parent_names[] = { - "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6", - "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4", - "vclk2_div6", "vclk2_div12" +static const struct clk_hw *gxbb_cts_parent_hws[] = { + &gxbb_vclk_div1.hw, + &gxbb_vclk_div2.hw, + &gxbb_vclk_div4.hw, + &gxbb_vclk_div6.hw, + &gxbb_vclk_div12.hw, + &gxbb_vclk2_div1.hw, + &gxbb_vclk2_div2.hw, + &gxbb_vclk2_div4.hw, + &gxbb_vclk2_div6.hw, + &gxbb_vclk2_div12.hw, }; static struct clk_regmap gxbb_cts_enci_sel = { @@ -2009,8 +2215,8 @@ static struct clk_regmap gxbb_cts_enci_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_enci_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_cts_parent_names, - .num_parents = ARRAY_SIZE(gxbb_cts_parent_names), + .parent_hws = gxbb_cts_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2025,8 +2231,8 @@ static struct clk_regmap gxbb_cts_encp_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_encp_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_cts_parent_names, - .num_parents = ARRAY_SIZE(gxbb_cts_parent_names), + .parent_hws = gxbb_cts_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2041,18 +2247,25 @@ static struct clk_regmap gxbb_cts_vdac_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_vdac_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_cts_parent_names, - .num_parents = ARRAY_SIZE(gxbb_cts_parent_names), + .parent_hws = gxbb_cts_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; /* TOFIX: add support for cts_tcon */ static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; -static const char * const gxbb_cts_hdmi_tx_parent_names[] = { - "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6", - "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4", - "vclk2_div6", "vclk2_div12" +static const struct clk_hw *gxbb_cts_hdmi_tx_parent_hws[] = { + &gxbb_vclk_div1.hw, + &gxbb_vclk_div2.hw, + &gxbb_vclk_div4.hw, + &gxbb_vclk_div6.hw, + &gxbb_vclk_div12.hw, + &gxbb_vclk2_div1.hw, + &gxbb_vclk2_div2.hw, + &gxbb_vclk2_div4.hw, + &gxbb_vclk2_div6.hw, + &gxbb_vclk2_div12.hw, }; static struct clk_regmap gxbb_hdmi_tx_sel = { @@ -2071,8 +2284,8 @@ static struct clk_regmap gxbb_hdmi_tx_sel = { * vclk2_div1, vclk2_div2, vclk2_div4, vclk2_div6, vclk2_div12, * cts_tcon */ - .parent_names = gxbb_cts_hdmi_tx_parent_names, - .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_names), + .parent_hws = gxbb_cts_hdmi_tx_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_hws), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2085,7 +2298,9 @@ static struct clk_regmap gxbb_cts_enci = { .hw.init = &(struct clk_init_data) { .name = "cts_enci", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_enci_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_enci_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2099,7 +2314,9 @@ static struct clk_regmap gxbb_cts_encp = { .hw.init = &(struct clk_init_data) { .name = "cts_encp", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_encp_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_encp_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2113,7 +2330,9 @@ static struct clk_regmap gxbb_cts_vdac = { .hw.init = &(struct clk_init_data) { .name = "cts_vdac", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_vdac_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_cts_vdac_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2127,7 +2346,9 @@ static struct clk_regmap gxbb_hdmi_tx = { .hw.init = &(struct clk_init_data) { .name = "hdmi_tx", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "hdmi_tx_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_hdmi_tx_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2135,8 +2356,11 @@ static struct clk_regmap gxbb_hdmi_tx = { /* HDMI Clocks */ -static const char * const gxbb_hdmi_parent_names[] = { - IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5" +static const struct clk_parent_data gxbb_hdmi_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &gxbb_fclk_div4.hw }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, }; static struct clk_regmap gxbb_hdmi_sel = { @@ -2149,8 +2373,8 @@ static struct clk_regmap gxbb_hdmi_sel = { .hw.init = &(struct clk_init_data){ .name = "hdmi_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_hdmi_parent_names, - .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_names), + .parent_data = gxbb_hdmi_parent_data, + .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_data), .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, }, }; @@ -2164,7 +2388,7 @@ static struct clk_regmap gxbb_hdmi_div = { .hw.init = &(struct clk_init_data){ .name = "hdmi_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "hdmi_sel" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_hdmi_sel.hw }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -2178,7 +2402,7 @@ static struct clk_regmap gxbb_hdmi = { .hw.init = &(struct clk_init_data) { .name = "hdmi", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "hdmi_div" }, + .parent_hws = (const struct clk_hw *[]) { &gxbb_hdmi_div.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, @@ -2186,8 +2410,11 @@ static struct clk_regmap gxbb_hdmi = { /* VDEC clocks */ -static const char * const gxbb_vdec_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +static const struct clk_hw *gxbb_vdec_parent_hws[] = { + &gxbb_fclk_div4.hw, + &gxbb_fclk_div3.hw, + &gxbb_fclk_div5.hw, + &gxbb_fclk_div7.hw, }; static struct clk_regmap gxbb_vdec_1_sel = { @@ -2200,8 +2427,8 @@ static struct clk_regmap gxbb_vdec_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_vdec_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names), + .parent_hws = gxbb_vdec_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2216,7 +2443,9 @@ static struct clk_regmap gxbb_vdec_1_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vdec_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2230,7 +2459,9 @@ static struct clk_regmap gxbb_vdec_1 = { .hw.init = &(struct clk_init_data) { .name = "vdec_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vdec_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2246,8 +2477,8 @@ static struct clk_regmap gxbb_vdec_hevc_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_sel", .ops = &clk_regmap_mux_ops, - .parent_names = gxbb_vdec_parent_names, - .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names), + .parent_hws = gxbb_vdec_parent_hws, + .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2262,7 +2493,9 @@ static struct clk_regmap gxbb_vdec_hevc_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_hevc_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vdec_hevc_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2276,7 +2509,9 @@ static struct clk_regmap gxbb_vdec_hevc = { .hw.init = &(struct clk_init_data) { .name = "vdec_hevc", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_hevc_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_vdec_hevc_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2284,9 +2519,18 @@ static struct clk_regmap gxbb_vdec_hevc = { static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, }; -static const char * const gen_clk_parent_names[] = { - IN_PREFIX "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2", - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll", +static const struct clk_parent_data gen_clk_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &gxbb_vdec_1.hw }, + { .hw = &gxbb_vdec_hevc.hw }, + { .hw = &gxbb_mpll0.hw }, + { .hw = &gxbb_mpll1.hw }, + { .hw = &gxbb_mpll2.hw }, + { .hw = &gxbb_fclk_div4.hw }, + { .hw = &gxbb_fclk_div3.hw }, + { .hw = &gxbb_fclk_div5.hw }, + { .hw = &gxbb_fclk_div7.hw }, + { .hw = &gxbb_gp0_pll.hw }, }; static struct clk_regmap gxbb_gen_clk_sel = { @@ -2305,8 +2549,8 @@ static struct clk_regmap gxbb_gen_clk_sel = { * vid_pll, vid2_pll (hevc), mpll0, mpll1, mpll2, fdiv4, * fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll */ - .parent_names = gen_clk_parent_names, - .num_parents = ARRAY_SIZE(gen_clk_parent_names), + .parent_data = gen_clk_parent_data, + .num_parents = ARRAY_SIZE(gen_clk_parent_data), }, }; @@ -2319,7 +2563,9 @@ static struct clk_regmap gxbb_gen_clk_div = { .hw.init = &(struct clk_init_data){ .name = "gen_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gen_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_gen_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2333,7 +2579,9 @@ static struct clk_regmap gxbb_gen_clk = { .hw.init = &(struct clk_init_data){ .name = "gen_clk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "gen_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &gxbb_gen_clk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, -- GitLab From cc132d113dc589d8449fe2b53043b0f17029acac Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:34 +0200 Subject: [PATCH 1002/7155] clk: meson: axg: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (ie. when all clocks are local to the controller) and use .parent_data otherwise. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 204 ++++++++++++++++++++++++++++------------ 1 file changed, 144 insertions(+), 60 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 3ddd0efc9ee0..7a3d795cc614 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -14,7 +14,6 @@ #include #include -#include "clk-input.h" #include "clk-regmap.h" #include "clk-pll.h" #include "clk-mpll.h" @@ -59,7 +58,9 @@ static struct clk_regmap axg_fixed_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -74,7 +75,9 @@ static struct clk_regmap axg_fixed_pll = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fixed_pll_dco.hw + }, .num_parents = 1, /* * This clock won't ever change at runtime so @@ -114,7 +117,9 @@ static struct clk_regmap axg_sys_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "sys_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -129,7 +134,9 @@ static struct clk_regmap axg_sys_pll = { .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "sys_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_sys_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -215,7 +222,9 @@ static struct clk_regmap axg_gp0_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -230,7 +239,9 @@ static struct clk_regmap axg_gp0_pll = { .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gp0_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_gp0_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -284,7 +295,9 @@ static struct clk_regmap axg_hifi_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "hifi_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -299,7 +312,9 @@ static struct clk_regmap axg_hifi_pll = { .hw.init = &(struct clk_init_data){ .name = "hifi_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "hifi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_hifi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -311,7 +326,7 @@ static struct clk_fixed_factor axg_fclk_div2_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw }, .num_parents = 1, }, }; @@ -324,7 +339,9 @@ static struct clk_regmap axg_fclk_div2 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fclk_div2_div.hw + }, .num_parents = 1, .flags = CLK_IS_CRITICAL, }, @@ -336,7 +353,7 @@ static struct clk_fixed_factor axg_fclk_div3_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw }, .num_parents = 1, }, }; @@ -349,7 +366,9 @@ static struct clk_regmap axg_fclk_div3 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div3_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fclk_div3_div.hw + }, .num_parents = 1, /* * FIXME: @@ -372,7 +391,7 @@ static struct clk_fixed_factor axg_fclk_div4_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw }, .num_parents = 1, }, }; @@ -385,7 +404,9 @@ static struct clk_regmap axg_fclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div4_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fclk_div4_div.hw + }, .num_parents = 1, }, }; @@ -396,7 +417,7 @@ static struct clk_fixed_factor axg_fclk_div5_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw }, .num_parents = 1, }, }; @@ -409,7 +430,9 @@ static struct clk_regmap axg_fclk_div5 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div5_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fclk_div5_div.hw + }, .num_parents = 1, }, }; @@ -420,7 +443,9 @@ static struct clk_fixed_factor axg_fclk_div7_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -433,7 +458,9 @@ static struct clk_regmap axg_fclk_div7 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div7_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fclk_div7_div.hw + }, .num_parents = 1, }, }; @@ -447,7 +474,9 @@ static struct clk_regmap axg_mpll_prediv = { .hw.init = &(struct clk_init_data){ .name = "mpll_prediv", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -480,7 +509,9 @@ static struct clk_regmap axg_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -493,7 +524,9 @@ static struct clk_regmap axg_mpll0 = { .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -527,7 +560,9 @@ static struct clk_regmap axg_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -540,7 +575,9 @@ static struct clk_regmap axg_mpll1 = { .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -579,7 +616,9 @@ static struct clk_regmap axg_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -592,7 +631,9 @@ static struct clk_regmap axg_mpll2 = { .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -626,7 +667,9 @@ static struct clk_regmap axg_mpll3_div = { .hw.init = &(struct clk_init_data){ .name = "mpll3_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -639,7 +682,9 @@ static struct clk_regmap axg_mpll3 = { .hw.init = &(struct clk_init_data){ .name = "mpll3", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll3_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpll3_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -702,7 +747,9 @@ static struct clk_regmap axg_pcie_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, .num_parents = 1, }, }; @@ -717,7 +764,9 @@ static struct clk_regmap axg_pcie_pll_od = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll_od", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "pcie_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_pcie_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -733,7 +782,9 @@ static struct clk_regmap axg_pcie_pll = { .hw.init = &(struct clk_init_data){ .name = "pcie_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "pcie_pll_od" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_pcie_pll_od.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -750,7 +801,7 @@ static struct clk_regmap axg_pcie_mux = { .hw.init = &(struct clk_init_data){ .name = "pcie_mux", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "pcie_pll" }, + .parent_hws = (const struct clk_hw *[]) { &axg_pcie_pll.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -767,7 +818,7 @@ static struct clk_regmap axg_pcie_ref = { .hw.init = &(struct clk_init_data){ .name = "pcie_ref", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "pcie_mux" }, + .parent_hws = (const struct clk_hw *[]) { &axg_pcie_mux.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -781,7 +832,7 @@ static struct clk_regmap axg_pcie_cml_en0 = { .hw.init = &(struct clk_init_data) { .name = "pcie_cml_en0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "pcie_ref" }, + .parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -796,16 +847,21 @@ static struct clk_regmap axg_pcie_cml_en1 = { .hw.init = &(struct clk_init_data) { .name = "pcie_cml_en1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "pcie_ref" }, + .parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; -static const char * const clk81_parent_names[] = { - IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", - "fclk_div3", "fclk_div5" +static const struct clk_parent_data clk81_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &axg_fclk_div7.hw }, + { .hw = &axg_mpll1.hw }, + { .hw = &axg_mpll2.hw }, + { .hw = &axg_fclk_div4.hw }, + { .hw = &axg_fclk_div3.hw }, + { .hw = &axg_fclk_div5.hw }, }; static struct clk_regmap axg_mpeg_clk_sel = { @@ -818,8 +874,8 @@ static struct clk_regmap axg_mpeg_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = clk81_parent_names, - .num_parents = ARRAY_SIZE(clk81_parent_names), + .parent_data = clk81_parent_data, + .num_parents = ARRAY_SIZE(clk81_parent_data), }, }; @@ -832,7 +888,9 @@ static struct clk_regmap axg_mpeg_clk_div = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpeg_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -846,15 +904,20 @@ static struct clk_regmap axg_clk81 = { .hw.init = &(struct clk_init_data){ .name = "clk81", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpeg_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_mpeg_clk_div.hw + }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), }, }; -static const char * const axg_sd_emmc_clk0_parent_names[] = { - IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", - +static const struct clk_parent_data axg_sd_emmc_clk0_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &axg_fclk_div2.hw }, + { .hw = &axg_fclk_div3.hw }, + { .hw = &axg_fclk_div5.hw }, + { .hw = &axg_fclk_div7.hw }, /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All @@ -873,8 +936,8 @@ static struct clk_regmap axg_sd_emmc_b_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = axg_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), + .parent_data = axg_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -889,7 +952,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_sd_emmc_b_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -903,7 +968,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_b_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_sd_emmc_b_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -919,8 +986,8 @@ static struct clk_regmap axg_sd_emmc_c_clk0_sel = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = axg_sd_emmc_clk0_parent_names, - .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), + .parent_data = axg_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data), .flags = CLK_SET_RATE_PARENT, }, }; @@ -935,7 +1002,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0_div = { .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_sd_emmc_c_clk0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -949,7 +1018,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = { .hw.init = &(struct clk_init_data){ .name = "sd_emmc_c_clk0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_sd_emmc_c_clk0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -957,9 +1028,18 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = { static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, }; -static const char * const gen_clk_parent_names[] = { - IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3", - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll", +static const struct clk_parent_data gen_clk_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &axg_hifi_pll.hw }, + { .hw = &axg_mpll0.hw }, + { .hw = &axg_mpll1.hw }, + { .hw = &axg_mpll2.hw }, + { .hw = &axg_mpll3.hw }, + { .hw = &axg_fclk_div4.hw }, + { .hw = &axg_fclk_div3.hw }, + { .hw = &axg_fclk_div5.hw }, + { .hw = &axg_fclk_div7.hw }, + { .hw = &axg_gp0_pll.hw }, }; static struct clk_regmap axg_gen_clk_sel = { @@ -978,8 +1058,8 @@ static struct clk_regmap axg_gen_clk_sel = { * hifi_pll, mpll0, mpll1, mpll2, mpll3, fdiv4, * fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll */ - .parent_names = gen_clk_parent_names, - .num_parents = ARRAY_SIZE(gen_clk_parent_names), + .parent_data = gen_clk_parent_data, + .num_parents = ARRAY_SIZE(gen_clk_parent_data), }, }; @@ -992,7 +1072,9 @@ static struct clk_regmap axg_gen_clk_div = { .hw.init = &(struct clk_init_data){ .name = "gen_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gen_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_gen_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1006,7 +1088,9 @@ static struct clk_regmap axg_gen_clk = { .hw.init = &(struct clk_init_data){ .name = "gen_clk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "gen_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &axg_gen_clk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, -- GitLab From 4b5b85c0e6505c50d4a986f75effe5b88d923737 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:35 +0200 Subject: [PATCH 1003/7155] clk: meson: meson8b: migrate to the new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (ie. when all clocks are local to the controller) and use .parent_data otherwise. Signed-off-by: Alexandre Mergnat Reviewed-by: Martin Blumenstingl Tested-by: Martin Blumenstingl Signed-off-by: Jerome Brunet --- drivers/clk/meson/meson8b.c | 707 +++++++++++++++++++++++++----------- 1 file changed, 496 insertions(+), 211 deletions(-) diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 537219fa573e..b30279a5bfcc 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -97,7 +97,9 @@ static struct clk_regmap meson8b_fixed_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw + }, .num_parents = 1, }, }; @@ -112,7 +114,9 @@ static struct clk_regmap meson8b_fixed_pll = { .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll_dco.hw + }, .num_parents = 1, /* * This clock won't ever change at runtime so @@ -158,7 +162,9 @@ static struct clk_regmap meson8b_hdmi_pll_dco = { /* sometimes also called "HPLL" or "HPLL PLL" */ .name = "hdmi_pll_dco", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw + }, .num_parents = 1, }, }; @@ -173,7 +179,9 @@ static struct clk_regmap meson8b_hdmi_pll_lvds_out = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_lvds_out", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -189,7 +197,9 @@ static struct clk_regmap meson8b_hdmi_pll_hdmi_out = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_hdmi_out", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -227,7 +237,9 @@ static struct clk_regmap meson8b_sys_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "sys_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw + }, .num_parents = 1, }, }; @@ -242,7 +254,9 @@ static struct clk_regmap meson8b_sys_pll = { .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "sys_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_sys_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -254,7 +268,9 @@ static struct clk_fixed_factor meson8b_fclk_div2_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -267,7 +283,9 @@ static struct clk_regmap meson8b_fclk_div2 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div2_div.hw + }, .num_parents = 1, /* * FIXME: Ethernet with a RGMII PHYs is not working if @@ -285,7 +303,9 @@ static struct clk_fixed_factor meson8b_fclk_div3_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -298,7 +318,9 @@ static struct clk_regmap meson8b_fclk_div3 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div3", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div3_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div3_div.hw + }, .num_parents = 1, }, }; @@ -309,7 +331,9 @@ static struct clk_fixed_factor meson8b_fclk_div4_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -322,7 +346,9 @@ static struct clk_regmap meson8b_fclk_div4 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div4", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div4_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div4_div.hw + }, .num_parents = 1, }, }; @@ -333,7 +359,9 @@ static struct clk_fixed_factor meson8b_fclk_div5_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -346,7 +374,9 @@ static struct clk_regmap meson8b_fclk_div5 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div5", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div5_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div5_div.hw + }, .num_parents = 1, }, }; @@ -357,7 +387,9 @@ static struct clk_fixed_factor meson8b_fclk_div7_div = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -370,7 +402,9 @@ static struct clk_regmap meson8b_fclk_div7 = { .hw.init = &(struct clk_init_data){ .name = "fclk_div7", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "fclk_div7_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div7_div.hw + }, .num_parents = 1, }, }; @@ -384,7 +418,9 @@ static struct clk_regmap meson8b_mpll_prediv = { .hw.init = &(struct clk_init_data){ .name = "mpll_prediv", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fixed_pll.hw + }, .num_parents = 1, }, }; @@ -416,7 +452,9 @@ static struct clk_regmap meson8b_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -429,7 +467,9 @@ static struct clk_regmap meson8b_mpll0 = { .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -457,7 +497,9 @@ static struct clk_regmap meson8b_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -470,7 +512,9 @@ static struct clk_regmap meson8b_mpll1 = { .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -498,7 +542,9 @@ static struct clk_regmap meson8b_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "mpll_prediv" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll_prediv.hw + }, .num_parents = 1, }, }; @@ -511,7 +557,9 @@ static struct clk_regmap meson8b_mpll2 = { .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpll2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpll2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -533,8 +581,11 @@ static struct clk_regmap meson8b_mpeg_clk_sel = { * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, * fclk_div4, fclk_div3, fclk_div5 */ - .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", - "fclk_div5" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div3.hw, + &meson8b_fclk_div4.hw, + &meson8b_fclk_div5.hw, + }, .num_parents = 3, }, }; @@ -548,7 +599,9 @@ static struct clk_regmap meson8b_mpeg_clk_div = { .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpeg_clk_sel.hw + }, .num_parents = 1, }, }; @@ -561,7 +614,9 @@ static struct clk_regmap meson8b_clk81 = { .hw.init = &(struct clk_init_data){ .name = "clk81", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mpeg_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mpeg_clk_div.hw + }, .num_parents = 1, .flags = CLK_IS_CRITICAL, }, @@ -576,7 +631,10 @@ static struct clk_regmap meson8b_cpu_in_sel = { .hw.init = &(struct clk_init_data){ .name = "cpu_in_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "xtal", "sys_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw, + &meson8b_sys_pll.hw, + }, .num_parents = 2, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), @@ -589,7 +647,9 @@ static struct clk_fixed_factor meson8b_cpu_in_div2 = { .hw.init = &(struct clk_init_data){ .name = "cpu_in_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -601,7 +661,9 @@ static struct clk_fixed_factor meson8b_cpu_in_div3 = { .hw.init = &(struct clk_init_data){ .name = "cpu_in_div3", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -630,7 +692,9 @@ static struct clk_regmap meson8b_cpu_scale_div = { .hw.init = &(struct clk_init_data){ .name = "cpu_scale_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "cpu_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -649,13 +713,15 @@ static struct clk_regmap meson8b_cpu_scale_out_sel = { .ops = &clk_regmap_mux_ops, /* * NOTE: We are skipping the parent with value 0x2 (which is - * "cpu_in_div3") because it results in a duty cycle of 33% - * which makes the system unstable and can result in a lockup - * of the whole system. + * meson8b_cpu_in_div3) because it results in a duty cycle of + * 33% which makes the system unstable and can result in a + * lockup of the whole system. */ - .parent_names = (const char *[]) { "cpu_in_sel", - "cpu_in_div2", - "cpu_scale_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_in_sel.hw, + &meson8b_cpu_in_div2.hw, + &meson8b_cpu_scale_div.hw, + }, .num_parents = 3, .flags = CLK_SET_RATE_PARENT, }, @@ -670,8 +736,10 @@ static struct clk_regmap meson8b_cpu_clk = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "xtal", - "cpu_scale_out_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw, + &meson8b_cpu_scale_out_sel.hw, + }, .num_parents = 2, .flags = (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | @@ -690,8 +758,13 @@ static struct clk_regmap meson8b_nand_clk_sel = { .name = "nand_clk_sel", .ops = &clk_regmap_mux_ops, /* FIXME all other parents are unknown: */ - .parent_names = (const char *[]){ "fclk_div4", "fclk_div3", - "fclk_div5", "fclk_div7", "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, + &meson8b_fclk_div7.hw, + &meson8b_xtal.hw, + }, .num_parents = 5, .flags = CLK_SET_RATE_PARENT, }, @@ -707,7 +780,9 @@ static struct clk_regmap meson8b_nand_clk_div = { .hw.init = &(struct clk_init_data){ .name = "nand_clk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "nand_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_nand_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -721,7 +796,9 @@ static struct clk_regmap meson8b_nand_clk_gate = { .hw.init = &(struct clk_init_data){ .name = "nand_clk_gate", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "nand_clk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_nand_clk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -733,7 +810,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div2 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -744,7 +823,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div3 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div3", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -755,7 +836,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div4 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -766,7 +849,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div5 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div5", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -777,7 +862,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div6 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -788,7 +875,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div7 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div7", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -799,7 +888,9 @@ static struct clk_fixed_factor meson8b_cpu_clk_div8 = { .hw.init = &(struct clk_init_data){ .name = "cpu_clk_div8", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "cpu_clk" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk.hw + }, .num_parents = 1, }, }; @@ -815,13 +906,15 @@ static struct clk_regmap meson8b_apb_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "apb_clk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cpu_clk_div2", - "cpu_clk_div3", - "cpu_clk_div4", - "cpu_clk_div5", - "cpu_clk_div6", - "cpu_clk_div7", - "cpu_clk_div8", }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk_div2.hw, + &meson8b_cpu_clk_div3.hw, + &meson8b_cpu_clk_div4.hw, + &meson8b_cpu_clk_div5.hw, + &meson8b_cpu_clk_div6.hw, + &meson8b_cpu_clk_div7.hw, + &meson8b_cpu_clk_div8.hw, + }, .num_parents = 7, }, }; @@ -835,7 +928,9 @@ static struct clk_regmap meson8b_apb_clk_gate = { .hw.init = &(struct clk_init_data){ .name = "apb_clk_dis", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "apb_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_apb_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -850,13 +945,15 @@ static struct clk_regmap meson8b_periph_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "periph_clk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cpu_clk_div2", - "cpu_clk_div3", - "cpu_clk_div4", - "cpu_clk_div5", - "cpu_clk_div6", - "cpu_clk_div7", - "cpu_clk_div8", }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk_div2.hw, + &meson8b_cpu_clk_div3.hw, + &meson8b_cpu_clk_div4.hw, + &meson8b_cpu_clk_div5.hw, + &meson8b_cpu_clk_div6.hw, + &meson8b_cpu_clk_div7.hw, + &meson8b_cpu_clk_div8.hw, + }, .num_parents = 7, }, }; @@ -870,7 +967,9 @@ static struct clk_regmap meson8b_periph_clk_gate = { .hw.init = &(struct clk_init_data){ .name = "periph_clk_dis", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "periph_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_periph_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -887,13 +986,15 @@ static struct clk_regmap meson8b_axi_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "axi_clk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cpu_clk_div2", - "cpu_clk_div3", - "cpu_clk_div4", - "cpu_clk_div5", - "cpu_clk_div6", - "cpu_clk_div7", - "cpu_clk_div8", }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk_div2.hw, + &meson8b_cpu_clk_div3.hw, + &meson8b_cpu_clk_div4.hw, + &meson8b_cpu_clk_div5.hw, + &meson8b_cpu_clk_div6.hw, + &meson8b_cpu_clk_div7.hw, + &meson8b_cpu_clk_div8.hw, + }, .num_parents = 7, }, }; @@ -907,7 +1008,9 @@ static struct clk_regmap meson8b_axi_clk_gate = { .hw.init = &(struct clk_init_data){ .name = "axi_clk_dis", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "axi_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_axi_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -922,13 +1025,15 @@ static struct clk_regmap meson8b_l2_dram_clk_sel = { .hw.init = &(struct clk_init_data){ .name = "l2_dram_clk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cpu_clk_div2", - "cpu_clk_div3", - "cpu_clk_div4", - "cpu_clk_div5", - "cpu_clk_div6", - "cpu_clk_div7", - "cpu_clk_div8", }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cpu_clk_div2.hw, + &meson8b_cpu_clk_div3.hw, + &meson8b_cpu_clk_div4.hw, + &meson8b_cpu_clk_div5.hw, + &meson8b_cpu_clk_div6.hw, + &meson8b_cpu_clk_div7.hw, + &meson8b_cpu_clk_div8.hw, + }, .num_parents = 7, }, }; @@ -942,7 +1047,9 @@ static struct clk_regmap meson8b_l2_dram_clk_gate = { .hw.init = &(struct clk_init_data){ .name = "l2_dram_clk_dis", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "l2_dram_clk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_l2_dram_clk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -963,7 +1070,9 @@ static struct clk_regmap meson8b_vid_pll_in_sel = { * Meson8b: hdmi_pll_dco * Meson8m2: vid2_pll */ - .parent_names = (const char *[]){ "hdmi_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -977,7 +1086,9 @@ static struct clk_regmap meson8b_vid_pll_in_en = { .hw.init = &(struct clk_init_data){ .name = "vid_pll_in_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vid_pll_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vid_pll_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -992,7 +1103,9 @@ static struct clk_regmap meson8b_vid_pll_pre_div = { .hw.init = &(struct clk_init_data){ .name = "vid_pll_pre_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "vid_pll_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vid_pll_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1007,7 +1120,9 @@ static struct clk_regmap meson8b_vid_pll_post_div = { .hw.init = &(struct clk_init_data){ .name = "vid_pll_post_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "vid_pll_pre_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vid_pll_pre_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1023,8 +1138,10 @@ static struct clk_regmap meson8b_vid_pll = { .name = "vid_pll", .ops = &clk_regmap_mux_ro_ops, /* TODO: parent 0x2 is vid_pll_pre_div_mult7_div2 */ - .parent_names = (const char *[]){ "vid_pll_pre_div", - "vid_pll_post_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vid_pll_pre_div.hw, + &meson8b_vid_pll_post_div.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -1039,15 +1156,22 @@ static struct clk_regmap meson8b_vid_pll_final_div = { .hw.init = &(struct clk_init_data){ .name = "vid_pll_final_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "vid_pll" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vid_pll.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const meson8b_vclk_mux_parents[] = { - "vid_pll_final_div", "fclk_div4", "fclk_div3", "fclk_div5", - "vid_pll_final_div", "fclk_div7", "mpll1" +static const struct clk_hw *meson8b_vclk_mux_parent_hws[] = { + &meson8b_vid_pll_final_div.hw, + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, + &meson8b_vid_pll_final_div.hw, + &meson8b_fclk_div7.hw, + &meson8b_mpll1.hw, }; static struct clk_regmap meson8b_vclk_in_sel = { @@ -1059,8 +1183,8 @@ static struct clk_regmap meson8b_vclk_in_sel = { .hw.init = &(struct clk_init_data){ .name = "vclk_in_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents), + .parent_hws = meson8b_vclk_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1073,7 +1197,9 @@ static struct clk_regmap meson8b_vclk_in_en = { .hw.init = &(struct clk_init_data){ .name = "vclk_in_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1087,7 +1213,9 @@ static struct clk_regmap meson8b_vclk_div1_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk_div1_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1099,7 +1227,9 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1113,7 +1243,9 @@ static struct clk_regmap meson8b_vclk_div2_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk_div2_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_div2" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_div2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1125,7 +1257,9 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1139,7 +1273,9 @@ static struct clk_regmap meson8b_vclk_div4_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk_div4_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_div4" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_div4_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1151,7 +1287,9 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1165,7 +1303,9 @@ static struct clk_regmap meson8b_vclk_div6_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk_div6_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_div6" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_div6_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1177,7 +1317,9 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = { .hw.init = &(struct clk_init_data){ .name = "vclk_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1191,7 +1333,9 @@ static struct clk_regmap meson8b_vclk_div12_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk_div12_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk_div12" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_div12_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1206,8 +1350,8 @@ static struct clk_regmap meson8b_vclk2_in_sel = { .hw.init = &(struct clk_init_data){ .name = "vclk2_in_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents), + .parent_hws = meson8b_vclk_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1220,7 +1364,9 @@ static struct clk_regmap meson8b_vclk2_clk_in_en = { .hw.init = &(struct clk_init_data){ .name = "vclk2_in_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_in_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_in_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1234,7 +1380,9 @@ static struct clk_regmap meson8b_vclk2_div1_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div1_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1246,7 +1394,9 @@ static struct clk_fixed_factor meson8b_vclk2_div2_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div2", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1260,7 +1410,9 @@ static struct clk_regmap meson8b_vclk2_div2_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div2_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_div2" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_div2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1272,7 +1424,9 @@ static struct clk_fixed_factor meson8b_vclk2_div4_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div4", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1286,7 +1440,9 @@ static struct clk_regmap meson8b_vclk2_div4_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div4_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_div4" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_div4_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1298,7 +1454,9 @@ static struct clk_fixed_factor meson8b_vclk2_div6_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div6", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1312,7 +1470,9 @@ static struct clk_regmap meson8b_vclk2_div6_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div6_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_div6" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_div6_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1324,7 +1484,9 @@ static struct clk_fixed_factor meson8b_vclk2_div12_div = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div12", .ops = &clk_fixed_factor_ops, - .parent_names = (const char *[]){ "vclk2_in_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, } @@ -1338,15 +1500,20 @@ static struct clk_regmap meson8b_vclk2_div12_div_gate = { .hw.init = &(struct clk_init_data){ .name = "vclk2_div12_en", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "vclk2_div12" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_div12_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const meson8b_vclk_enc_mux_parents[] = { - "vclk_div1_en", "vclk_div2_en", "vclk_div4_en", "vclk_div6_en", - "vclk_div12_en", +static const struct clk_hw *meson8b_vclk_enc_mux_parent_hws[] = { + &meson8b_vclk_div1_gate.hw, + &meson8b_vclk_div2_div_gate.hw, + &meson8b_vclk_div4_div_gate.hw, + &meson8b_vclk_div6_div_gate.hw, + &meson8b_vclk_div12_div_gate.hw, }; static struct clk_regmap meson8b_cts_enct_sel = { @@ -1358,8 +1525,8 @@ static struct clk_regmap meson8b_cts_enct_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_enct_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents), + .parent_hws = meson8b_vclk_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1372,7 +1539,9 @@ static struct clk_regmap meson8b_cts_enct = { .hw.init = &(struct clk_init_data){ .name = "cts_enct", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cts_enct_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_enct_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1387,8 +1556,8 @@ static struct clk_regmap meson8b_cts_encp_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_encp_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents), + .parent_hws = meson8b_vclk_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1401,7 +1570,9 @@ static struct clk_regmap meson8b_cts_encp = { .hw.init = &(struct clk_init_data){ .name = "cts_encp", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cts_encp_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_encp_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1416,8 +1587,8 @@ static struct clk_regmap meson8b_cts_enci_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_enci_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents), + .parent_hws = meson8b_vclk_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1430,7 +1601,9 @@ static struct clk_regmap meson8b_cts_enci = { .hw.init = &(struct clk_init_data){ .name = "cts_enci", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cts_enci_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_enci_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1445,8 +1618,8 @@ static struct clk_regmap meson8b_hdmi_tx_pixel_sel = { .hw.init = &(struct clk_init_data){ .name = "hdmi_tx_pixel_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents), + .parent_hws = meson8b_vclk_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1459,15 +1632,20 @@ static struct clk_regmap meson8b_hdmi_tx_pixel = { .hw.init = &(struct clk_init_data){ .name = "hdmi_tx_pixel", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "hdmi_tx_pixel_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_tx_pixel_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const meson8b_vclk2_enc_mux_parents[] = { - "vclk2_div1_en", "vclk2_div2_en", "vclk2_div4_en", "vclk2_div6_en", - "vclk2_div12_en", +static const struct clk_hw *meson8b_vclk2_enc_mux_parent_hws[] = { + &meson8b_vclk2_div1_gate.hw, + &meson8b_vclk2_div2_div_gate.hw, + &meson8b_vclk2_div4_div_gate.hw, + &meson8b_vclk2_div6_div_gate.hw, + &meson8b_vclk2_div12_div_gate.hw, }; static struct clk_regmap meson8b_cts_encl_sel = { @@ -1479,8 +1657,8 @@ static struct clk_regmap meson8b_cts_encl_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_encl_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk2_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents), + .parent_hws = meson8b_vclk2_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1493,7 +1671,9 @@ static struct clk_regmap meson8b_cts_encl = { .hw.init = &(struct clk_init_data){ .name = "cts_encl", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cts_encl_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_encl_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1508,8 +1688,8 @@ static struct clk_regmap meson8b_cts_vdac0_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_vdac0_sel", .ops = &clk_regmap_mux_ro_ops, - .parent_names = meson8b_vclk2_enc_mux_parents, - .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents), + .parent_hws = meson8b_vclk2_enc_mux_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1522,7 +1702,9 @@ static struct clk_regmap meson8b_cts_vdac0 = { .hw.init = &(struct clk_init_data){ .name = "cts_vdac0", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "cts_vdac0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_vdac0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1539,7 +1721,9 @@ static struct clk_regmap meson8b_hdmi_sys_sel = { .name = "hdmi_sys_sel", .ops = &clk_regmap_mux_ro_ops, /* FIXME: all other parents are unknown */ - .parent_names = (const char *[]){ "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, }, @@ -1554,7 +1738,9 @@ static struct clk_regmap meson8b_hdmi_sys_div = { .hw.init = &(struct clk_init_data){ .name = "hdmi_sys_div", .ops = &clk_regmap_divider_ro_ops, - .parent_names = (const char *[]){ "hdmi_sys_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_sys_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1568,7 +1754,9 @@ static struct clk_regmap meson8b_hdmi_sys = { .hw.init = &(struct clk_init_data) { .name = "hdmi_sys", .ops = &clk_regmap_gate_ro_ops, - .parent_names = (const char *[]){ "hdmi_sys_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_sys_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1579,9 +1767,14 @@ static struct clk_regmap meson8b_hdmi_sys = { * muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only * has mali_0 and no glitch-free mux. */ -static const char * const meson8b_mali_0_1_parent_names[] = { - "xtal", "mpll2", "mpll1", "fclk_div7", "fclk_div4", "fclk_div3", - "fclk_div5" +static const struct clk_hw *meson8b_mali_0_1_parent_hws[] = { + &meson8b_xtal.hw, + &meson8b_mpll2.hw, + &meson8b_mpll1.hw, + &meson8b_fclk_div7.hw, + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, }; static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 }; @@ -1596,8 +1789,8 @@ static struct clk_regmap meson8b_mali_0_sel = { .hw.init = &(struct clk_init_data){ .name = "mali_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_mali_0_1_parent_names, - .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names), + .parent_hws = meson8b_mali_0_1_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws), /* * Don't propagate rate changes up because the only changeable * parents are mpll1 and mpll2 but we need those for audio and @@ -1617,7 +1810,9 @@ static struct clk_regmap meson8b_mali_0_div = { .hw.init = &(struct clk_init_data){ .name = "mali_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_0_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mali_0_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1631,7 +1826,9 @@ static struct clk_regmap meson8b_mali_0 = { .hw.init = &(struct clk_init_data){ .name = "mali_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mali_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1647,8 +1844,8 @@ static struct clk_regmap meson8b_mali_1_sel = { .hw.init = &(struct clk_init_data){ .name = "mali_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_mali_0_1_parent_names, - .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names), + .parent_hws = meson8b_mali_0_1_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws), /* * Don't propagate rate changes up because the only changeable * parents are mpll1 and mpll2 but we need those for audio and @@ -1668,7 +1865,9 @@ static struct clk_regmap meson8b_mali_1_div = { .hw.init = &(struct clk_init_data){ .name = "mali_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "mali_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mali_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1682,7 +1881,9 @@ static struct clk_regmap meson8b_mali_1 = { .hw.init = &(struct clk_init_data){ .name = "mali_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "mali_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mali_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1697,7 +1898,10 @@ static struct clk_regmap meson8b_mali = { .hw.init = &(struct clk_init_data){ .name = "mali", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "mali_0", "mali_1" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_mali_0.hw, + &meson8b_mali_1.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -1740,7 +1944,9 @@ static struct clk_regmap meson8m2_gp_pll_dco = { .hw.init = &(struct clk_init_data){ .name = "gp_pll_dco", .ops = &meson_clk_pll_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_xtal.hw + }, .num_parents = 1, }, }; @@ -1755,18 +1961,26 @@ static struct clk_regmap meson8m2_gp_pll = { .hw.init = &(struct clk_init_data){ .name = "gp_pll", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "gp_pll_dco" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8m2_gp_pll_dco.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; -static const char * const meson8b_vpu_0_1_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +static const struct clk_hw *meson8b_vpu_0_1_parent_hws[] = { + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, + &meson8b_fclk_div7.hw, }; -static const char * const mmeson8m2_vpu_0_1_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "gp_pll" +static const struct clk_hw *mmeson8m2_vpu_0_1_parent_hws[] = { + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, + &meson8m2_gp_pll.hw, }; static struct clk_regmap meson8b_vpu_0_sel = { @@ -1778,8 +1992,8 @@ static struct clk_regmap meson8b_vpu_0_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vpu_0_1_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_names), + .parent_hws = meson8b_vpu_0_1_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1793,8 +2007,8 @@ static struct clk_regmap meson8m2_vpu_0_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_sel", .ops = &clk_regmap_mux_ops, - .parent_names = mmeson8m2_vpu_0_1_parent_names, - .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names), + .parent_hws = mmeson8m2_vpu_0_1_parent_hws, + .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1808,7 +2022,17 @@ static struct clk_regmap meson8b_vpu_0_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_0_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_0_sel" }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * meson8b and meson8m2 have different vpu_0_sels (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so vpu_0_div picks up the + * appropriate one. + */ + .name = "vpu_0_sel", + .index = -1, + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1822,7 +2046,9 @@ static struct clk_regmap meson8b_vpu_0 = { .hw.init = &(struct clk_init_data) { .name = "vpu_0", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_0_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vpu_0_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1837,8 +2063,8 @@ static struct clk_regmap meson8b_vpu_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vpu_0_1_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_names), + .parent_hws = meson8b_vpu_0_1_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1852,8 +2078,8 @@ static struct clk_regmap meson8m2_vpu_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = mmeson8m2_vpu_0_1_parent_names, - .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names), + .parent_hws = mmeson8m2_vpu_0_1_parent_hws, + .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1867,7 +2093,17 @@ static struct clk_regmap meson8b_vpu_1_div = { .hw.init = &(struct clk_init_data){ .name = "vpu_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vpu_1_sel" }, + .parent_data = &(const struct clk_parent_data) { + /* + * Note: + * meson8b and meson8m2 have different vpu_1_sels (with + * different struct clk_hw). We fallback to the global + * naming string mechanism so vpu_1_div picks up the + * appropriate one. + */ + .name = "vpu_1_sel", + .index = -1, + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1881,7 +2117,9 @@ static struct clk_regmap meson8b_vpu_1 = { .hw.init = &(struct clk_init_data) { .name = "vpu_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vpu_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vpu_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1896,14 +2134,22 @@ static struct clk_regmap meson8b_vpu = { .hw.init = &(struct clk_init_data){ .name = "vpu", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "vpu_0", "vpu_1" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vpu_0.hw, + &meson8b_vpu_1.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, }; -static const char * const meson8b_vdec_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll1" +static const struct clk_hw *meson8b_vdec_parent_hws[] = { + &meson8b_fclk_div4.hw, + &meson8b_fclk_div3.hw, + &meson8b_fclk_div5.hw, + &meson8b_fclk_div7.hw, + &meson8b_mpll2.hw, + &meson8b_mpll1.hw, }; static struct clk_regmap meson8b_vdec_1_sel = { @@ -1916,8 +2162,8 @@ static struct clk_regmap meson8b_vdec_1_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vdec_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names), + .parent_hws = meson8b_vdec_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -1932,7 +2178,9 @@ static struct clk_regmap meson8b_vdec_1_1_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_1_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1946,7 +2194,9 @@ static struct clk_regmap meson8b_vdec_1_1 = { .hw.init = &(struct clk_init_data) { .name = "vdec_1_1", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_1_1_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_1_1_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1962,7 +2212,9 @@ static struct clk_regmap meson8b_vdec_1_2_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_1_2_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_1_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_1_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1976,7 +2228,9 @@ static struct clk_regmap meson8b_vdec_1_2 = { .hw.init = &(struct clk_init_data) { .name = "vdec_1_2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_1_2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_1_2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -1992,7 +2246,10 @@ static struct clk_regmap meson8b_vdec_1 = { .hw.init = &(struct clk_init_data){ .name = "vdec_1", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "vdec_1_1", "vdec_1_2" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_1_1.hw, + &meson8b_vdec_1_2.hw, + }, .num_parents = 2, .flags = CLK_SET_RATE_PARENT, }, @@ -2008,8 +2265,8 @@ static struct clk_regmap meson8b_vdec_hcodec_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_hcodec_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vdec_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names), + .parent_hws = meson8b_vdec_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2024,7 +2281,9 @@ static struct clk_regmap meson8b_vdec_hcodec_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_hcodec_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_hcodec_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_hcodec_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2038,7 +2297,9 @@ static struct clk_regmap meson8b_vdec_hcodec = { .hw.init = &(struct clk_init_data) { .name = "vdec_hcodec", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_hcodec_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_hcodec_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2054,8 +2315,8 @@ static struct clk_regmap meson8b_vdec_2_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_2_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vdec_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names), + .parent_hws = meson8b_vdec_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2070,7 +2331,9 @@ static struct clk_regmap meson8b_vdec_2_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_2_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_2_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_2_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2084,7 +2347,9 @@ static struct clk_regmap meson8b_vdec_2 = { .hw.init = &(struct clk_init_data) { .name = "vdec_2", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_2_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_2_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2100,8 +2365,8 @@ static struct clk_regmap meson8b_vdec_hevc_sel = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_vdec_parent_names, - .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names), + .parent_hws = meson8b_vdec_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws), .flags = CLK_SET_RATE_PARENT, }, }; @@ -2116,7 +2381,9 @@ static struct clk_regmap meson8b_vdec_hevc_div = { .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "vdec_hevc_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_hevc_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2130,7 +2397,9 @@ static struct clk_regmap meson8b_vdec_hevc_en = { .hw.init = &(struct clk_init_data) { .name = "vdec_hevc_en", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "vdec_hevc_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_hevc_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2147,15 +2416,19 @@ static struct clk_regmap meson8b_vdec_hevc = { .name = "vdec_hevc", .ops = &clk_regmap_mux_ops, /* TODO: The second parent is currently unknown */ - .parent_names = (const char *[]){ "vdec_hevc_en" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vdec_hevc_en.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; /* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */ -static const char * const meson8b_cts_amclk_parent_names[] = { - "mpll0", "mpll1", "mpll2" +static const struct clk_hw *meson8b_cts_amclk_parent_hws[] = { + &meson8b_mpll0.hw, + &meson8b_mpll1.hw, + &meson8b_mpll2.hw }; static u32 meson8b_cts_amclk_mux_table[] = { 1, 2, 3 }; @@ -2171,8 +2444,8 @@ static struct clk_regmap meson8b_cts_amclk_sel = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_cts_amclk_parent_names, - .num_parents = ARRAY_SIZE(meson8b_cts_amclk_parent_names), + .parent_hws = meson8b_cts_amclk_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_cts_amclk_parent_hws), }, }; @@ -2186,7 +2459,9 @@ static struct clk_regmap meson8b_cts_amclk_div = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "cts_amclk_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_amclk_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2200,15 +2475,19 @@ static struct clk_regmap meson8b_cts_amclk = { .hw.init = &(struct clk_init_data){ .name = "cts_amclk", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_amclk_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_amclk_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, }; /* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */ -static const char * const meson8b_cts_mclk_i958_parent_names[] = { - "mpll0", "mpll1", "mpll2" +static const struct clk_hw *meson8b_cts_mclk_i958_parent_hws[] = { + &meson8b_mpll0.hw, + &meson8b_mpll1.hw, + &meson8b_mpll2.hw }; static u32 meson8b_cts_mclk_i958_mux_table[] = { 1, 2, 3 }; @@ -2224,8 +2503,8 @@ static struct clk_regmap meson8b_cts_mclk_i958_sel = { .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_sel", .ops = &clk_regmap_mux_ops, - .parent_names = meson8b_cts_mclk_i958_parent_names, - .num_parents = ARRAY_SIZE(meson8b_cts_mclk_i958_parent_names), + .parent_hws = meson8b_cts_mclk_i958_parent_hws, + .num_parents = ARRAY_SIZE(meson8b_cts_mclk_i958_parent_hws), }, }; @@ -2239,7 +2518,9 @@ static struct clk_regmap meson8b_cts_mclk_i958_div = { .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_div", .ops = &clk_regmap_divider_ops, - .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_mclk_i958_sel.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2253,7 +2534,9 @@ static struct clk_regmap meson8b_cts_mclk_i958 = { .hw.init = &(struct clk_init_data){ .name = "cts_mclk_i958", .ops = &clk_regmap_gate_ops, - .parent_names = (const char *[]){ "cts_mclk_i958_div" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_mclk_i958_div.hw + }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, }, @@ -2268,8 +2551,10 @@ static struct clk_regmap meson8b_cts_i958 = { .hw.init = &(struct clk_init_data){ .name = "cts_i958", .ops = &clk_regmap_mux_ops, - .parent_names = (const char *[]){ "cts_amclk", - "cts_mclk_i958" }, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_cts_amclk.hw, + &meson8b_cts_mclk_i958.hw + }, .num_parents = 2, /* * The parent is specific to origin of the audio data. Let the -- GitLab From 3a36044e7f3909c7ddb7ddfc727ab8104a563439 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:36 +0200 Subject: [PATCH 1004/7155] clk: meson: clk-regmap: migrate to new parent description method This clock controller use the string comparison method to describe parent relation between the clocks, which is not optimized. Migrate to the new way by using .parent_hws where possible (ie. when all clocks are local to the controller) and use .parent_data otherwise. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 3 +++ drivers/clk/meson/clk-regmap.h | 12 ++++++------ drivers/clk/meson/g12a.c | 6 ++++++ drivers/clk/meson/gxbb.c | 3 +++ drivers/clk/meson/meson8b.c | 3 +++ 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 7a3d795cc614..13fc0006f63d 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -1096,6 +1096,9 @@ static struct clk_regmap axg_gen_clk = { }, }; +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &axg_clk81.hw) + /* Everything Else (EE) domain gates */ static MESON_GATE(axg_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(axg_audio_locker, HHI_GCLK_MPEG0, 2); diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h index 1dd0abe3ba91..c4a39604cffd 100644 --- a/drivers/clk/meson/clk-regmap.h +++ b/drivers/clk/meson/clk-regmap.h @@ -111,7 +111,7 @@ clk_get_regmap_mux_data(struct clk_regmap *clk) extern const struct clk_ops clk_regmap_mux_ops; extern const struct clk_ops clk_regmap_mux_ro_ops; -#define __MESON_GATE(_name, _reg, _bit, _ops) \ +#define __MESON_PCLK(_name, _reg, _bit, _ops, _pname) \ struct clk_regmap _name = { \ .data = &(struct clk_regmap_gate_data){ \ .offset = (_reg), \ @@ -120,15 +120,15 @@ struct clk_regmap _name = { \ .hw.init = &(struct clk_init_data) { \ .name = #_name, \ .ops = _ops, \ - .parent_names = (const char *[]){ "clk81" }, \ + .parent_hws = (const struct clk_hw *[]) { _pname }, \ .num_parents = 1, \ .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ }, \ } -#define MESON_GATE(_name, _reg, _bit) \ - __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops) +#define MESON_PCLK(_name, _reg, _bit, _pname) \ + __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname) -#define MESON_GATE_RO(_name, _reg, _bit) \ - __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops) +#define MESON_PCLK_RO(_name, _reg, _bit, _pname) \ + __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname) #endif /* __CLK_REGMAP_H */ diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 8cc7f5acf7ab..a8f706de811b 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -3325,6 +3325,12 @@ static struct clk_regmap g12a_ts = { }, }; +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw) + +#define MESON_GATE_RO(_name, _reg, _bit) \ + MESON_PCLK_RO(_name, _reg, _bit, &g12a_clk81.hw) + /* Everything Else (EE) domain gates */ static MESON_GATE(g12a_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(g12a_dos, HHI_GCLK_MPEG0, 1); diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 67e466356d4b..7cfb998eeb3e 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -2587,6 +2587,9 @@ static struct clk_regmap gxbb_gen_clk = { }, }; +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &gxbb_clk81.hw) + /* Everything Else (EE) domain gates */ static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index b30279a5bfcc..67e6691e080c 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -2564,6 +2564,9 @@ static struct clk_regmap meson8b_cts_i958 = { }, }; +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &meson8b_clk81.hw) + /* Everything Else (EE) domain gates */ static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0); -- GitLab From b11cfaba5b4d6e287540a3d64c403e5b26dd2728 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:37 +0200 Subject: [PATCH 1005/7155] clk: meson: remove ee input bypass clocks During probe, bypass clocks (i.e. ee-in-xtal) are made from device-tree inputs to provide input clocks which can be access through global name. The cons of this method are the duplicated clocks, means more string comparison. Specify parent directly with device-tree clock name. Remove the bypass clock registration from the ee probe function. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 1 - drivers/clk/meson/meson-eeclk.c | 10 ---------- drivers/clk/meson/meson-eeclk.h | 2 -- 3 files changed, 13 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 178ee72ba4bc..72a37572501f 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -38,7 +38,6 @@ config COMMON_CLK_MESON_AO_CLKC config COMMON_CLK_MESON_EE_CLKC tristate select COMMON_CLK_MESON_REGMAP - select COMMON_CLK_MESON_INPUT config COMMON_CLK_MESON8B bool diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c index 6ba2094be257..a7cb1e7aedc4 100644 --- a/drivers/clk/meson/meson-eeclk.c +++ b/drivers/clk/meson/meson-eeclk.c @@ -10,7 +10,6 @@ #include #include -#include "clk-input.h" #include "clk-regmap.h" #include "meson-eeclk.h" @@ -18,7 +17,6 @@ int meson_eeclkc_probe(struct platform_device *pdev) { const struct meson_eeclkc_data *data; struct device *dev = &pdev->dev; - struct clk_hw *input; struct regmap *map; int ret, i; @@ -37,14 +35,6 @@ int meson_eeclkc_probe(struct platform_device *pdev) if (data->init_count) regmap_multi_reg_write(map, data->init_regs, data->init_count); - input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0); - if (IS_ERR(input)) { - ret = PTR_ERR(input); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get input clock"); - return ret; - } - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < data->regmap_clk_num; i++) data->regmap_clks[i]->map = map; diff --git a/drivers/clk/meson/meson-eeclk.h b/drivers/clk/meson/meson-eeclk.h index 9ab5d6fa7ccb..77316207bde1 100644 --- a/drivers/clk/meson/meson-eeclk.h +++ b/drivers/clk/meson/meson-eeclk.h @@ -10,8 +10,6 @@ #include #include "clk-regmap.h" -#define IN_PREFIX "ee-in-" - struct platform_device; struct meson_eeclkc_data { -- GitLab From e96c7612315a1183e12d5b6ebd523a3a93617510 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 25 Jul 2019 18:42:38 +0200 Subject: [PATCH 1006/7155] clk: meson: remove clk input helper The clk input function which allows clock controllers to register a bypass clock from a clock producer is no longer needed anymore since meson clock controllers have migrated to a new parent allocation method. Signed-off-by: Alexandre Mergnat Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 3 --- drivers/clk/meson/Makefile | 1 - drivers/clk/meson/clk-input.c | 49 ----------------------------------- drivers/clk/meson/clk-input.h | 19 -------------- 4 files changed, 72 deletions(-) delete mode 100644 drivers/clk/meson/clk-input.c delete mode 100644 drivers/clk/meson/clk-input.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 72a37572501f..500be0b0d473 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -1,7 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -config COMMON_CLK_MESON_INPUT - tristate - config COMMON_CLK_MESON_REGMAP tristate select REGMAP diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index bc35a4efd6b7..f09d83dc3d60 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o -obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o diff --git a/drivers/clk/meson/clk-input.c b/drivers/clk/meson/clk-input.c deleted file mode 100644 index 086226e9dba6..000000000000 --- a/drivers/clk/meson/clk-input.c +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (c) 2018 BayLibre, SAS. - * Author: Jerome Brunet - */ - -#include -#include -#include -#include -#include "clk-input.h" - -static const struct clk_ops meson_clk_no_ops = {}; - -struct clk_hw *meson_clk_hw_register_input(struct device *dev, - const char *of_name, - const char *clk_name, - unsigned long flags) -{ - struct clk *parent_clk = devm_clk_get(dev, of_name); - struct clk_init_data init; - const char *parent_name; - struct clk_hw *hw; - int ret; - - if (IS_ERR(parent_clk)) - return (struct clk_hw *)parent_clk; - - hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); - if (!hw) - return ERR_PTR(-ENOMEM); - - parent_name = __clk_get_name(parent_clk); - init.name = clk_name; - init.ops = &meson_clk_no_ops; - init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; - hw->init = &init; - - ret = devm_clk_hw_register(dev, hw); - - return ret ? ERR_PTR(ret) : hw; -} -EXPORT_SYMBOL_GPL(meson_clk_hw_register_input); - -MODULE_DESCRIPTION("Amlogic clock input helper"); -MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/meson/clk-input.h b/drivers/clk/meson/clk-input.h deleted file mode 100644 index 4a541b9685a6..000000000000 --- a/drivers/clk/meson/clk-input.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2019 BayLibre, SAS. - * Author: Jerome Brunet - */ - -#ifndef __MESON_CLK_INPUT_H -#define __MESON_CLK_INPUT_H - -#include - -struct device; - -struct clk_hw *meson_clk_hw_register_input(struct device *dev, - const char *of_name, - const char *clk_name, - unsigned long flags); - -#endif /* __MESON_CLK_INPUT_H */ -- GitLab From 4193a39240fbeda2ee35232bd0a1deedd41d31aa Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Mon, 24 Jun 2019 12:52:23 +0200 Subject: [PATCH 1007/7155] arm64: dts: renesas: r8a77990: Add cpg reset for DU Add CPG reset properties to DU node of E3 (r8a77990) SoC. According to Laurent Pinchart, R-Car Gen3 reset is handled at the group level so specifying one reset entry per group is sufficient. Signed-off-by: Takeshi Kihara Signed-off-by: Yoshihiro Kaneko Signed-off-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77990.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index b4318661f35e..84d1f58e73e7 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1766,6 +1766,8 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; vsps = <&vspd0 0 &vspd1 0>; status = "disabled"; -- GitLab From 3ed1db9071fde0ba9c4ce22a9b404887c0dbe909 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 24 Jun 2019 12:52:24 +0200 Subject: [PATCH 1008/7155] arm64: dts: renesas: r8a77995: Add cpg reset for DU Add CPG reset properties to DU node of D3 (r8a77995) SoC. According to Laurent Pinchart, R-Car Gen3 reset is handled at the group level so specifying one reset entry per group is sufficient. This patch was inspired by a patch in the BSP by Takeshi Kihara . Signed-off-by: Yoshihiro Kaneko Signed-off-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index 0a344eb55094..ca6aeabd6d04 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -1001,6 +1001,8 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; vsps = <&vspd0 0 &vspd1 0>; status = "disabled"; -- GitLab From 56d651e890f3befd616b6962a862f5ffa1a514fa Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Tue, 18 Jun 2019 05:18:16 +0900 Subject: [PATCH 1009/7155] arm64: dts: renesas: r8a77995: Fix register range of display node Since the R8A77995 SoC uses DU{0,1}, the range from the base address to the 0x4000 address is used. This patch fixed it. Fixes: 18f1a773e3f9e6d1 ("arm64: dts: renesas: r8a77995: add DU support") Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index ca6aeabd6d04..bcd54421796d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -995,7 +995,7 @@ du: display@feb00000 { compatible = "renesas,du-r8a77995"; - reg = <0 0xfeb00000 0 0x80000>; + reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; clocks = <&cpg CPG_MOD 724>, -- GitLab From e8efd2a8e20a9d7a7bd701950254a0ae04a8ce27 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:31 +0100 Subject: [PATCH 1010/7155] arm64: dts: renesas: r8a774c0: Add missing assigned-clocks for CAN[01] Define "assigned-clocks" and "assigned-clock-rates" properties for CAN[01] DT nodes, as required by the dt-bindings. Fixes: 036bc85c1d06ef0a ("arm64: dts: renesas: r8a774c0: Add clkp2 clock to CAN nodes") Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index e7b5bf23f978..bdf555f48268 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -973,6 +973,8 @@ <&cpg CPG_CORE R8A774C0_CLK_CANFD>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A774C0_CLK_CANFD>; + assigned-clock-rates = <40000000>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 916>; status = "disabled"; @@ -987,6 +989,8 @@ <&cpg CPG_CORE R8A774C0_CLK_CANFD>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A774C0_CLK_CANFD>; + assigned-clock-rates = <40000000>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 915>; status = "disabled"; -- GitLab From 0a930f64a1cc36a34797a9e54f3040ad1d5833f2 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:32 +0100 Subject: [PATCH 1011/7155] arm64: dts: renesas: r8a774a1: Add missing assigned-clocks for CAN[01] Define "assigned-clocks" and "assigned-clock-rates" properties for CAN[01] DT nodes, as required by the dt-bindings. Fixes: eccc40002972c424 ("arm64: dts: renesas: r8a774a1: Add clkp2 clock to CAN nodes") Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index f209457c7807..0ef8f5326b64 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -1128,6 +1128,8 @@ <&cpg CPG_CORE R8A774A1_CLK_CANFD>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>; + assigned-clock-rates = <40000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 916>; status = "disabled"; @@ -1142,6 +1144,8 @@ <&cpg CPG_CORE R8A774A1_CLK_CANFD>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>; + assigned-clock-rates = <40000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 915>; status = "disabled"; -- GitLab From 5b971c71dd64c08c73c37f754f60a7d777ea70e9 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:33 +0100 Subject: [PATCH 1012/7155] arm64: dts: renesas: r8a774a1: Add CANFD support Add CANFD support to the SoC specific dtsi. Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index 0ef8f5326b64..a849ca726a51 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -1151,6 +1151,31 @@ status = "disabled"; }; + canfd: can@e66c0000 { + compatible = "renesas,r8a774a1-canfd", + "renesas,rcar-gen3-canfd"; + reg = <0 0xe66c0000 0 0x8000>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 914>, + <&cpg CPG_CORE R8A774A1_CLK_CANFD>, + <&can_clk>; + clock-names = "fck", "canfd", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>; + assigned-clock-rates = <40000000>; + power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; + resets = <&cpg 914>; + status = "disabled"; + + channel0 { + status = "disabled"; + }; + + channel1 { + status = "disabled"; + }; + }; + pwm0: pwm@e6e30000 { compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; reg = <0 0xe6e30000 0 0x8>; -- GitLab From 816c5248df0fdcee33e56444232394d597a1894b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:34 +0100 Subject: [PATCH 1013/7155] arm64: dts: renesas: hihope-rzg2-ex: Enable CAN interfaces This patch enables both CAN0 and CAN1, both exposed via connectors found on the expansion board. Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/hihope-rzg2-ex.dtsi | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi index 07a6eeaed12e..4280b190dc68 100644 --- a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi +++ b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi @@ -31,6 +31,18 @@ }; }; +&can0 { + pinctrl-0 = <&can0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&can1 { + pinctrl-0 = <&can1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + &pciec0 { status = "okay"; }; @@ -60,4 +72,14 @@ drive-strength = <12>; }; }; + + can0_pins: can0 { + groups = "can0_data_a"; + function = "can0"; + }; + + can1_pins: can1 { + groups = "can1_data"; + function = "can1"; + }; }; -- GitLab From cd3e43be14189542d8934faa94eff0392da32536 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 5 Jul 2019 11:15:18 +0100 Subject: [PATCH 1014/7155] arm64: dts: renesas: hihope-common: Add PCA9654 I/O expander Enable PCA9654 GPIO expander, so that we can configure its GPIOs later. Signed-off-by: Biju Das Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/hihope-common.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/hihope-common.dtsi b/arch/arm64/boot/dts/renesas/hihope-common.dtsi index 3311a982fff8..14802425d2fb 100644 --- a/arch/arm64/boot/dts/renesas/hihope-common.dtsi +++ b/arch/arm64/boot/dts/renesas/hihope-common.dtsi @@ -162,6 +162,13 @@ clock-frequency = <400000>; status = "okay"; + gpio_expander: gpio@20 { + compatible = "onnn,pca9654"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; + versaclock5: clock-generator@6a { compatible = "idt,5p49v5923"; reg = <0x6a>; -- GitLab From d112c20925443b4a8876b101e5b7b13ef105057e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 5 Jul 2019 11:15:19 +0100 Subject: [PATCH 1015/7155] arm64: dts: renesas: hihope-common: Add BT support This patch enables BT support for the HiHope RZ/G2[MN] boards. Signed-off-by: Biju Das Signed-off-by: Geert Uytterhoeven --- .../arm64/boot/dts/renesas/hihope-common.dtsi | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/hihope-common.dtsi b/arch/arm64/boot/dts/renesas/hihope-common.dtsi index 14802425d2fb..fdeb4d2c0e3a 100644 --- a/arch/arm64/boot/dts/renesas/hihope-common.dtsi +++ b/arch/arm64/boot/dts/renesas/hihope-common.dtsi @@ -10,6 +10,7 @@ / { aliases { serial0 = &scif2; + serial1 = &hscif0; }; chosen { @@ -31,6 +32,13 @@ leds { compatible = "gpio-leds"; + bt_active_led { + label = "blue:bt"; + gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "hci0-power"; + default-state = "off"; + }; + led0 { gpios = <&gpio6 11 GPIO_ACTIVE_HIGH>; }; @@ -153,6 +161,19 @@ }; }; +&hscif0 { + pinctrl-0 = <&hscif0_pins>; + pinctrl-names = "default"; + + uart-has-rtscts; + status = "okay"; + + bluetooth { + compatible = "ti,wl1837-st"; + enable-gpios = <&gpio_expander 2 GPIO_ACTIVE_HIGH>; + }; +}; + &hsusb { dr_mode = "otg"; status = "okay"; @@ -194,6 +215,11 @@ pinctrl-0 = <&scif_clk_pins>; pinctrl-names = "default"; + hscif0_pins: hscif0 { + groups = "hscif0_data", "hscif0_ctrl"; + function = "hscif0"; + }; + scif2_pins: scif2 { groups = "scif2_data_a"; function = "scif2"; -- GitLab From 176f936a1e887a53d78f05248dc3c9bbd2c7f4c8 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 5 Jul 2019 11:15:20 +0100 Subject: [PATCH 1016/7155] arm64: dts: renesas: hihope-common: Add WLAN support This patch enables WLAN support for the HiHope RZ/G2[MN] boards. Signed-off-by: Biju Das Signed-off-by: Geert Uytterhoeven --- .../arm64/boot/dts/renesas/hihope-common.dtsi | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/hihope-common.dtsi b/arch/arm64/boot/dts/renesas/hihope-common.dtsi index fdeb4d2c0e3a..52d61c958325 100644 --- a/arch/arm64/boot/dts/renesas/hihope-common.dtsi +++ b/arch/arm64/boot/dts/renesas/hihope-common.dtsi @@ -54,6 +54,13 @@ led3 { gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; + + wlan_active_led { + label = "yellow:wlan"; + gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; }; reg_1p8v: regulator0 { @@ -98,6 +105,17 @@ 1800000 0>; }; + wlan_en_reg: regulator-wlan_en { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <70000>; + + gpio = <&gpio_expander 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + x302_clk: x302-clock { compatible = "fixed-clock"; #clock-cells = <0>; @@ -242,6 +260,12 @@ power-source = <1800>; }; + sdhi2_pins: sd2 { + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; + }; + sdhi3_pins: sd3 { groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds"; function = "sdhi3"; @@ -301,6 +325,27 @@ status = "okay"; }; +&sdhi2 { + status = "okay"; + pinctrl-0 = <&sdhi2_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&wlan_en_reg>; + bus-width = <4>; + non-removable; + cap-power-off-card; + keep-power-in-suspend; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@2 { + compatible = "ti,wl1837"; + reg = <2>; + interrupt-parent = <&gpio2>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + &sdhi3 { pinctrl-0 = <&sdhi3_pins>; pinctrl-1 = <&sdhi3_pins>; -- GitLab From da245a5066aa4c96c153a4ede3dab68d6b2306e8 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 5 Jul 2019 14:39:37 +0100 Subject: [PATCH 1017/7155] arm64: dts: renesas: r8a774a1: Use extended audio dmac registers Basic audio dmac register only supports busif from 0 to 3, in order to use busif4 ~ busif7 extended audio dmac registers need to be used. Based on similar work from Jiada Wang in commit 7a516e49d975 ("arm64: dts: renesas: use extended audio dmac register"). Signed-off-by: Fabrizio Castro Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index a849ca726a51..a87436cade54 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -1682,7 +1682,7 @@ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ <0 0xec541000 0 0x280>, /* SSI */ - <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ + <0 0xec760000 0 0x200>; /* Audio DMAC peri peri*/ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; clocks = <&cpg CPG_MOD 1005>, -- GitLab From a44efeaa0bbf699f7ad397f5130e2834d52f621e Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 5 Jul 2019 14:39:38 +0100 Subject: [PATCH 1018/7155] arm64: dts: renesas: r8a774a1: Add SSIU support for sound Add SSIU support to the SoC DT as the sound driver supports it now, and also since the sound driver can now handle BUSIF0-7 via SSIU remove the no longer needed "rxu" and "txu" properties. Based on similar work from Kuninori Morimoto and Simon Horman in commits 8d14bfa074db ("arm64: dts: renesas: r8a7796: add SSIU support for sound") and 10bd03fa896e ("arm64: dts: renesas: r8a7796: remove BUSIF0 settings from rcar_sound,ssi"). Signed-off-by: Fabrizio Castro Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 251 ++++++++++++++++++++-- 1 file changed, 231 insertions(+), 20 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index a87436cade54..bdb4675249fa 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -1806,56 +1806,267 @@ }; }; + rcar_sound,ssiu { + ssiu00: ssiu-0 { + dmas = <&audma0 0x15>, <&audma1 0x16>; + dma-names = "rx", "tx"; + }; + ssiu01: ssiu-1 { + dmas = <&audma0 0x35>, <&audma1 0x36>; + dma-names = "rx", "tx"; + }; + ssiu02: ssiu-2 { + dmas = <&audma0 0x37>, <&audma1 0x38>; + dma-names = "rx", "tx"; + }; + ssiu03: ssiu-3 { + dmas = <&audma0 0x47>, <&audma1 0x48>; + dma-names = "rx", "tx"; + }; + ssiu04: ssiu-4 { + dmas = <&audma0 0x3F>, <&audma1 0x40>; + dma-names = "rx", "tx"; + }; + ssiu05: ssiu-5 { + dmas = <&audma0 0x43>, <&audma1 0x44>; + dma-names = "rx", "tx"; + }; + ssiu06: ssiu-6 { + dmas = <&audma0 0x4F>, <&audma1 0x50>; + dma-names = "rx", "tx"; + }; + ssiu07: ssiu-7 { + dmas = <&audma0 0x53>, <&audma1 0x54>; + dma-names = "rx", "tx"; + }; + ssiu10: ssiu-8 { + dmas = <&audma0 0x49>, <&audma1 0x4a>; + dma-names = "rx", "tx"; + }; + ssiu11: ssiu-9 { + dmas = <&audma0 0x4B>, <&audma1 0x4C>; + dma-names = "rx", "tx"; + }; + ssiu12: ssiu-10 { + dmas = <&audma0 0x57>, <&audma1 0x58>; + dma-names = "rx", "tx"; + }; + ssiu13: ssiu-11 { + dmas = <&audma0 0x59>, <&audma1 0x5A>; + dma-names = "rx", "tx"; + }; + ssiu14: ssiu-12 { + dmas = <&audma0 0x5F>, <&audma1 0x60>; + dma-names = "rx", "tx"; + }; + ssiu15: ssiu-13 { + dmas = <&audma0 0xC3>, <&audma1 0xC4>; + dma-names = "rx", "tx"; + }; + ssiu16: ssiu-14 { + dmas = <&audma0 0xC7>, <&audma1 0xC8>; + dma-names = "rx", "tx"; + }; + ssiu17: ssiu-15 { + dmas = <&audma0 0xCB>, <&audma1 0xCC>; + dma-names = "rx", "tx"; + }; + ssiu20: ssiu-16 { + dmas = <&audma0 0x63>, <&audma1 0x64>; + dma-names = "rx", "tx"; + }; + ssiu21: ssiu-17 { + dmas = <&audma0 0x67>, <&audma1 0x68>; + dma-names = "rx", "tx"; + }; + ssiu22: ssiu-18 { + dmas = <&audma0 0x6B>, <&audma1 0x6C>; + dma-names = "rx", "tx"; + }; + ssiu23: ssiu-19 { + dmas = <&audma0 0x6D>, <&audma1 0x6E>; + dma-names = "rx", "tx"; + }; + ssiu24: ssiu-20 { + dmas = <&audma0 0xCF>, <&audma1 0xCE>; + dma-names = "rx", "tx"; + }; + ssiu25: ssiu-21 { + dmas = <&audma0 0xEB>, <&audma1 0xEC>; + dma-names = "rx", "tx"; + }; + ssiu26: ssiu-22 { + dmas = <&audma0 0xED>, <&audma1 0xEE>; + dma-names = "rx", "tx"; + }; + ssiu27: ssiu-23 { + dmas = <&audma0 0xEF>, <&audma1 0xF0>; + dma-names = "rx", "tx"; + }; + ssiu30: ssiu-24 { + dmas = <&audma0 0x6f>, <&audma1 0x70>; + dma-names = "rx", "tx"; + }; + ssiu31: ssiu-25 { + dmas = <&audma0 0x21>, <&audma1 0x22>; + dma-names = "rx", "tx"; + }; + ssiu32: ssiu-26 { + dmas = <&audma0 0x23>, <&audma1 0x24>; + dma-names = "rx", "tx"; + }; + ssiu33: ssiu-27 { + dmas = <&audma0 0x25>, <&audma1 0x26>; + dma-names = "rx", "tx"; + }; + ssiu34: ssiu-28 { + dmas = <&audma0 0x27>, <&audma1 0x28>; + dma-names = "rx", "tx"; + }; + ssiu35: ssiu-29 { + dmas = <&audma0 0x29>, <&audma1 0x2A>; + dma-names = "rx", "tx"; + }; + ssiu36: ssiu-30 { + dmas = <&audma0 0x2B>, <&audma1 0x2C>; + dma-names = "rx", "tx"; + }; + ssiu37: ssiu-31 { + dmas = <&audma0 0x2D>, <&audma1 0x2E>; + dma-names = "rx", "tx"; + }; + ssiu40: ssiu-32 { + dmas = <&audma0 0x71>, <&audma1 0x72>; + dma-names = "rx", "tx"; + }; + ssiu41: ssiu-33 { + dmas = <&audma0 0x17>, <&audma1 0x18>; + dma-names = "rx", "tx"; + }; + ssiu42: ssiu-34 { + dmas = <&audma0 0x19>, <&audma1 0x1A>; + dma-names = "rx", "tx"; + }; + ssiu43: ssiu-35 { + dmas = <&audma0 0x1B>, <&audma1 0x1C>; + dma-names = "rx", "tx"; + }; + ssiu44: ssiu-36 { + dmas = <&audma0 0x1D>, <&audma1 0x1E>; + dma-names = "rx", "tx"; + }; + ssiu45: ssiu-37 { + dmas = <&audma0 0x1F>, <&audma1 0x20>; + dma-names = "rx", "tx"; + }; + ssiu46: ssiu-38 { + dmas = <&audma0 0x31>, <&audma1 0x32>; + dma-names = "rx", "tx"; + }; + ssiu47: ssiu-39 { + dmas = <&audma0 0x33>, <&audma1 0x34>; + dma-names = "rx", "tx"; + }; + ssiu50: ssiu-40 { + dmas = <&audma0 0x73>, <&audma1 0x74>; + dma-names = "rx", "tx"; + }; + ssiu60: ssiu-41 { + dmas = <&audma0 0x75>, <&audma1 0x76>; + dma-names = "rx", "tx"; + }; + ssiu70: ssiu-42 { + dmas = <&audma0 0x79>, <&audma1 0x7a>; + dma-names = "rx", "tx"; + }; + ssiu80: ssiu-43 { + dmas = <&audma0 0x7b>, <&audma1 0x7c>; + dma-names = "rx", "tx"; + }; + ssiu90: ssiu-44 { + dmas = <&audma0 0x7d>, <&audma1 0x7e>; + dma-names = "rx", "tx"; + }; + ssiu91: ssiu-45 { + dmas = <&audma0 0x7F>, <&audma1 0x80>; + dma-names = "rx", "tx"; + }; + ssiu92: ssiu-46 { + dmas = <&audma0 0x81>, <&audma1 0x82>; + dma-names = "rx", "tx"; + }; + ssiu93: ssiu-47 { + dmas = <&audma0 0x83>, <&audma1 0x84>; + dma-names = "rx", "tx"; + }; + ssiu94: ssiu-48 { + dmas = <&audma0 0xA3>, <&audma1 0xA4>; + dma-names = "rx", "tx"; + }; + ssiu95: ssiu-49 { + dmas = <&audma0 0xA5>, <&audma1 0xA6>; + dma-names = "rx", "tx"; + }; + ssiu96: ssiu-50 { + dmas = <&audma0 0xA7>, <&audma1 0xA8>; + dma-names = "rx", "tx"; + }; + ssiu97: ssiu-51 { + dmas = <&audma0 0xA9>, <&audma1 0xAA>; + dma-names = "rx", "tx"; + }; + }; + rcar_sound,ssi { ssi0: ssi-0 { interrupts = ; - dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x01>, <&audma1 0x02>; + dma-names = "rx", "tx"; }; ssi1: ssi-1 { interrupts = ; - dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x03>, <&audma1 0x04>; + dma-names = "rx", "tx"; }; ssi2: ssi-2 { interrupts = ; - dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x05>, <&audma1 0x06>; + dma-names = "rx", "tx"; }; ssi3: ssi-3 { interrupts = ; - dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x07>, <&audma1 0x08>; + dma-names = "rx", "tx"; }; ssi4: ssi-4 { interrupts = ; - dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x09>, <&audma1 0x0a>; + dma-names = "rx", "tx"; }; ssi5: ssi-5 { interrupts = ; - dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x0b>, <&audma1 0x0c>; + dma-names = "rx", "tx"; }; ssi6: ssi-6 { interrupts = ; - dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x0d>, <&audma1 0x0e>; + dma-names = "rx", "tx"; }; ssi7: ssi-7 { interrupts = ; - dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x0f>, <&audma1 0x10>; + dma-names = "rx", "tx"; }; ssi8: ssi-8 { interrupts = ; - dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x11>, <&audma1 0x12>; + dma-names = "rx", "tx"; }; ssi9: ssi-9 { interrupts = ; - dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>; - dma-names = "rx", "tx", "rxu", "txu"; + dmas = <&audma0 0x13>, <&audma1 0x14>; + dma-names = "rx", "tx"; }; }; -- GitLab From a7aa356e2c9ad1e874460ac5ee499ed1690e80cb Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:29 +0100 Subject: [PATCH 1019/7155] dt-bindings: can: rcar_canfd: document r8a774a1 support Document the support for rcar_canfd on R8A774A1 SoC devices. Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_canfd.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt index 32f051f6d338..00afaffb9614 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt @@ -4,6 +4,7 @@ Renesas R-Car CAN FD controller Device Tree Bindings Required properties: - compatible: Must contain one or more of the following: - "renesas,rcar-gen3-canfd" for R-Car Gen3 and RZ/G2 compatible controllers. + - "renesas,r8a774a1-canfd" for R8A774A1 (RZ/G2M) compatible controller. - "renesas,r8a774c0-canfd" for R8A774C0 (RZ/G2E) compatible controller. - "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller. - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3-W) compatible controller. @@ -32,10 +33,10 @@ enable/disable the respective channel. Required properties for "renesas,r8a774c0-canfd", "renesas,r8a7795-canfd", "renesas,r8a7796-canfd", "renesas,r8a77965-canfd", and "renesas,r8a77990-canfd" compatible: -In R8A774C0, R8A7795, R8A7796, R8A77965, and R8A77990 SoCs, canfd clock is a -div6 clock and can be used by both CAN and CAN FD controller at the same time. -It needs to be scaled to maximum frequency if any of these controllers use it. -This is done using the below properties: +In R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, and R8A77990 SoCs, canfd +clock is a div6 clock and can be used by both CAN and CAN FD controller at the +same time. It needs to be scaled to maximum frequency if any of these +controllers use it. This is done using the below properties: - assigned-clocks: phandle of canfd clock. - assigned-clock-rates: maximum frequency of this clock. -- GitLab From 8cb7ec14188649cf2151464050413e2814fd7cf1 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 14 Jun 2019 12:53:30 +0100 Subject: [PATCH 1020/7155] dt-bindings: can: rcar_can: Complete documentation for RZ/G2[EM] Add missing RZ/G2[EM] CANFD clock specific documentation. Fixes: 868b7c0f43e61f22 ("dt-bindings: can: rcar_can: Add r8a774a1 support") Fixes: d703a52eb1ebeeba ("dt-bindings: can: rcar_can: Add r8a774c0 support") Signed-off-by: Fabrizio Castro Reviewed-by: Chris Paterson Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_can.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index b463e1268ac4..e1f315ab2353 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -33,7 +33,7 @@ Required properties: - pinctrl-0: pin control group to be used for this controller. - pinctrl-names: must be "default". -Required properties for R8A7795, R8A7796 and R8A77965: +Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796 and R8A77965: For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can be used by both CAN and CAN FD controller at the same time. It needs to be scaled to maximum frequency if any of these controllers use it. This is done -- GitLab From 0ed0eb0171d7c19310d9f7b06a6dee82a4fb8ab6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 17 Jun 2019 14:00:56 +0200 Subject: [PATCH 1021/7155] soc: renesas: rcar-sysc: Use [] to denote a flexible array member Flexible array members should be denoted using [] instead of [0], else gcc will not warn when they are no longer at the end of the structure. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 0c80fab4f8de..02b29ea62dc4 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -170,7 +170,7 @@ struct rcar_sysc_pd { struct generic_pm_domain genpd; struct rcar_sysc_ch ch; unsigned int flags; - char name[0]; + char name[]; }; static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) -- GitLab From 3ab8227d3e7d1d2bf1829675d3197e3cb600e9f6 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 26 Jul 2019 16:39:32 +0000 Subject: [PATCH 1022/7155] cfg80211: refactor cfg80211_bss_update This patch implements minor refactoring for cfg80211_bss_update function. Code path for updating known BSS is extracted into dedicated cfg80211_update_known_bss function. Signed-off-by: Sergey Matyukevich Link: https://lore.kernel.org/r/20190726163922.27509-2-sergey.matyukevich.os@quantenna.com Signed-off-by: Johannes Berg --- net/wireless/scan.c | 171 +++++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 82 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index a98dabab557a..9119f5ce3677 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1091,6 +1091,93 @@ struct cfg80211_non_tx_bss { u8 bssid_index; }; +static bool +cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, + struct cfg80211_internal_bss *known, + struct cfg80211_internal_bss *new, + bool signal_valid) +{ + lockdep_assert_held(&rdev->bss_lock); + + /* Update IEs */ + if (rcu_access_pointer(new->pub.proberesp_ies)) { + const struct cfg80211_bss_ies *old; + + old = rcu_access_pointer(known->pub.proberesp_ies); + + rcu_assign_pointer(known->pub.proberesp_ies, + new->pub.proberesp_ies); + /* Override possible earlier Beacon frame IEs */ + rcu_assign_pointer(known->pub.ies, + new->pub.proberesp_ies); + if (old) + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); + } else if (rcu_access_pointer(new->pub.beacon_ies)) { + const struct cfg80211_bss_ies *old; + struct cfg80211_internal_bss *bss; + + if (known->pub.hidden_beacon_bss && + !list_empty(&known->hidden_list)) { + const struct cfg80211_bss_ies *f; + + /* The known BSS struct is one of the probe + * response members of a group, but we're + * receiving a beacon (beacon_ies in the new + * bss is used). This can only mean that the + * AP changed its beacon from not having an + * SSID to showing it, which is confusing so + * drop this information. + */ + + f = rcu_access_pointer(new->pub.beacon_ies); + kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head); + return false; + } + + old = rcu_access_pointer(known->pub.beacon_ies); + + rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies); + + /* Override IEs if they were from a beacon before */ + if (old == rcu_access_pointer(known->pub.ies)) + rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies); + + /* Assign beacon IEs to all sub entries */ + list_for_each_entry(bss, &known->hidden_list, hidden_list) { + const struct cfg80211_bss_ies *ies; + + ies = rcu_access_pointer(bss->pub.beacon_ies); + WARN_ON(ies != old); + + rcu_assign_pointer(bss->pub.beacon_ies, + new->pub.beacon_ies); + } + + if (old) + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); + } + + known->pub.beacon_interval = new->pub.beacon_interval; + + /* don't update the signal if beacon was heard on + * adjacent channel. + */ + if (signal_valid) + known->pub.signal = new->pub.signal; + known->pub.capability = new->pub.capability; + known->ts = new->ts; + known->ts_boottime = new->ts_boottime; + known->parent_tsf = new->parent_tsf; + known->pub.chains = new->pub.chains; + memcpy(known->pub.chain_signal, new->pub.chain_signal, + IEEE80211_MAX_CHAINS); + ether_addr_copy(known->parent_bssid, new->parent_bssid); + known->pub.max_bssid_indicator = new->pub.max_bssid_indicator; + known->pub.bssid_index = new->pub.bssid_index; + + return true; +} + /* Returned bss is reference counted and must be cleaned up appropriately. */ struct cfg80211_internal_bss * cfg80211_bss_update(struct cfg80211_registered_device *rdev, @@ -1114,88 +1201,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR); if (found) { - /* Update IEs */ - if (rcu_access_pointer(tmp->pub.proberesp_ies)) { - const struct cfg80211_bss_ies *old; - - old = rcu_access_pointer(found->pub.proberesp_ies); - - rcu_assign_pointer(found->pub.proberesp_ies, - tmp->pub.proberesp_ies); - /* Override possible earlier Beacon frame IEs */ - rcu_assign_pointer(found->pub.ies, - tmp->pub.proberesp_ies); - if (old) - kfree_rcu((struct cfg80211_bss_ies *)old, - rcu_head); - } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { - const struct cfg80211_bss_ies *old; - struct cfg80211_internal_bss *bss; - - if (found->pub.hidden_beacon_bss && - !list_empty(&found->hidden_list)) { - const struct cfg80211_bss_ies *f; - - /* - * The found BSS struct is one of the probe - * response members of a group, but we're - * receiving a beacon (beacon_ies in the tmp - * bss is used). This can only mean that the - * AP changed its beacon from not having an - * SSID to showing it, which is confusing so - * drop this information. - */ - - f = rcu_access_pointer(tmp->pub.beacon_ies); - kfree_rcu((struct cfg80211_bss_ies *)f, - rcu_head); - goto drop; - } - - old = rcu_access_pointer(found->pub.beacon_ies); - - rcu_assign_pointer(found->pub.beacon_ies, - tmp->pub.beacon_ies); - - /* Override IEs if they were from a beacon before */ - if (old == rcu_access_pointer(found->pub.ies)) - rcu_assign_pointer(found->pub.ies, - tmp->pub.beacon_ies); - - /* Assign beacon IEs to all sub entries */ - list_for_each_entry(bss, &found->hidden_list, - hidden_list) { - const struct cfg80211_bss_ies *ies; - - ies = rcu_access_pointer(bss->pub.beacon_ies); - WARN_ON(ies != old); - - rcu_assign_pointer(bss->pub.beacon_ies, - tmp->pub.beacon_ies); - } - - if (old) - kfree_rcu((struct cfg80211_bss_ies *)old, - rcu_head); - } - - found->pub.beacon_interval = tmp->pub.beacon_interval; - /* - * don't update the signal if beacon was heard on - * adjacent channel. - */ - if (signal_valid) - found->pub.signal = tmp->pub.signal; - found->pub.capability = tmp->pub.capability; - found->ts = tmp->ts; - found->ts_boottime = tmp->ts_boottime; - found->parent_tsf = tmp->parent_tsf; - found->pub.chains = tmp->pub.chains; - memcpy(found->pub.chain_signal, tmp->pub.chain_signal, - IEEE80211_MAX_CHAINS); - ether_addr_copy(found->parent_bssid, tmp->parent_bssid); - found->pub.max_bssid_indicator = tmp->pub.max_bssid_indicator; - found->pub.bssid_index = tmp->pub.bssid_index; + if (!cfg80211_update_known_bss(rdev, found, tmp, signal_valid)) + goto drop; } else { struct cfg80211_internal_bss *new; struct cfg80211_internal_bss *hidden; -- GitLab From 0afd425b1b64251f19b5d8d8b49bf56fefbc643f Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 26 Jul 2019 16:39:34 +0000 Subject: [PATCH 1023/7155] cfg80211: fix duplicated scan entries after channel switch When associated BSS completes channel switch procedure, its channel record needs to be updated. The existing mac80211 solution was extended to cfg80211 in commit 5dc8cdce1d72 ("mac80211/cfg80211: update bss channel on channel switch"). However that solution still appears to be incomplete as it may lead to duplicated scan entries for associated BSS after channel switch. The root cause of the problem is as follows. Each BSS entry is included into the following data structures: - bss list rdev->bss_list - bss search tree rdev->bss_tree Updating BSS channel record without rebuilding bss_tree may break tree search since cmp_bss considers all of the following: channel, bssid, ssid. When BSS channel is updated, but its location in bss_tree is not updated, then subsequent search operations may fail to locate this BSS since they will be traversing bss_tree in wrong direction. As a result, for scan performed after associated BSS channel switch, cfg80211_bss_update may add the second entry for the same BSS to both bss_list and bss_tree, rather then update the existing one. To summarize, if BSS channel needs to be updated, then bss_tree should be rebuilt in order to put updated BSS entry into a proper location. This commit suggests the following straightforward solution: - if new entry has been already created for BSS after channel switch, then use its IEs to update known BSS entry and then remove new entry completely - use rb_erase/rb_insert_bss reinstall updated BSS in bss_tree - for nontransmit BSS entry, the whole transmit BSS hierarchy is updated Signed-off-by: Sergey Matyukevich Link: https://lore.kernel.org/r/20190726163922.27509-3-sergey.matyukevich.os@quantenna.com Signed-off-by: Johannes Berg --- net/wireless/core.h | 2 ++ net/wireless/nl80211.c | 2 +- net/wireless/scan.c | 79 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index ee8388fe4a92..77556c58d9ac 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -306,6 +306,8 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy); void cfg80211_bss_expire(struct cfg80211_registered_device *rdev); void cfg80211_bss_age(struct cfg80211_registered_device *rdev, unsigned long age_secs); +void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev, + struct ieee80211_channel *channel); /* IBSS */ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 10b57aa10227..a8d4b2b6b3ec 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16116,7 +16116,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, if (wdev->iftype == NL80211_IFTYPE_STATION && !WARN_ON(!wdev->current_bss)) - wdev->current_bss->pub.channel = chandef->chan; + cfg80211_update_assoc_bss_entry(wdev, chandef->chan); nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, NL80211_CMD_CH_SWITCH_NOTIFY, 0); diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 9119f5ce3677..d313c9befa23 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2001,6 +2001,85 @@ void cfg80211_bss_iter(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_bss_iter); +void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev, + struct ieee80211_channel *chan) +{ + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct cfg80211_internal_bss *cbss = wdev->current_bss; + struct cfg80211_internal_bss *new = NULL; + struct cfg80211_internal_bss *bss; + struct cfg80211_bss *nontrans_bss; + struct cfg80211_bss *tmp; + + spin_lock_bh(&rdev->bss_lock); + + if (WARN_ON(cbss->pub.channel == chan)) + goto done; + + /* use transmitting bss */ + if (cbss->pub.transmitted_bss) + cbss = container_of(cbss->pub.transmitted_bss, + struct cfg80211_internal_bss, + pub); + + cbss->pub.channel = chan; + + list_for_each_entry(bss, &rdev->bss_list, list) { + if (!cfg80211_bss_type_match(bss->pub.capability, + bss->pub.channel->band, + wdev->conn_bss_type)) + continue; + + if (bss == cbss) + continue; + + if (!cmp_bss(&bss->pub, &cbss->pub, BSS_CMP_REGULAR)) { + new = bss; + break; + } + } + + if (new) { + /* to save time, update IEs for transmitting bss only */ + if (cfg80211_update_known_bss(rdev, cbss, new, false)) { + new->pub.proberesp_ies = NULL; + new->pub.beacon_ies = NULL; + } + + list_for_each_entry_safe(nontrans_bss, tmp, + &new->pub.nontrans_list, + nontrans_list) { + bss = container_of(nontrans_bss, + struct cfg80211_internal_bss, pub); + if (__cfg80211_unlink_bss(rdev, bss)) + rdev->bss_generation++; + } + + WARN_ON(atomic_read(&new->hold)); + if (!WARN_ON(!__cfg80211_unlink_bss(rdev, new))) + rdev->bss_generation++; + } + + rb_erase(&cbss->rbn, &rdev->bss_tree); + rb_insert_bss(rdev, cbss); + rdev->bss_generation++; + + list_for_each_entry_safe(nontrans_bss, tmp, + &cbss->pub.nontrans_list, + nontrans_list) { + bss = container_of(nontrans_bss, + struct cfg80211_internal_bss, pub); + bss->pub.channel = chan; + rb_erase(&bss->rbn, &rdev->bss_tree); + rb_insert_bss(rdev, bss); + rdev->bss_generation++; + } + +done: + spin_unlock_bh(&rdev->bss_lock); +} + #ifdef CONFIG_CFG80211_WEXT static struct cfg80211_registered_device * cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) -- GitLab From d34990bbc25559fa1af5e23759c65a3951cbc956 Mon Sep 17 00:00:00 2001 From: Michael Vassernis Date: Mon, 29 Jul 2019 06:01:16 +0000 Subject: [PATCH 1024/7155] cfg80211: fix dfs channels remain DFS_AVAILABLE after ch_switch Depending on the regulatory domain, leaving a DFS channel requires a new CAC to be performed when returning back to that channel. If needed, update dfs states after a driver channel switch. Signed-off-by: Michael Vassernis Link: https://lore.kernel.org/r/20190729060024.5660-1-michael.vassernis@tandemg.com Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a8d4b2b6b3ec..08a66c1bcb83 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16118,6 +16118,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, !WARN_ON(!wdev->current_bss)) cfg80211_update_assoc_bss_entry(wdev, chandef->chan); + cfg80211_sched_dfs_chan_update(rdev); + nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, NL80211_CMD_CH_SWITCH_NOTIFY, 0); } -- GitLab From 90d4962cfc87a6994a19db0d76e1fa214dd67267 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 29 Jul 2019 12:23:41 +0200 Subject: [PATCH 1025/7155] mac80211: fix ieee80211_he_oper_size() comment Johannes mentioned that the comment should not reference mac80211 as other subsystems might call the helper. Signed-off-by: John Crispin Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20190729102342.8659-1-john@phrozen.org Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a656f31262f1..9c81895c63c1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2053,8 +2053,8 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size * @he_oper_ie: byte data of the He Operations IE, stating from the the byte * after the ext ID byte. It is assumed that he_oper_ie has at least - * sizeof(struct ieee80211_he_operation) bytes, checked already in - * ieee802_11_parse_elems_crc() + * sizeof(struct ieee80211_he_operation) bytes, the caller must have + * validated this. * @return the actual size of the IE data (not including header), or 0 on error */ static inline u8 -- GitLab From 697f6c507c74991057eb6df3cfb46579ca136467 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 29 Jul 2019 12:23:42 +0200 Subject: [PATCH 1026/7155] mac80211: propagate HE operation info into bss_conf Upon a successful assoc a station shall store the content of the HE operation element inside bss_conf so that the driver can setup the hardware accordingly. Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20190729102342.8659-2-john@phrozen.org [use struct copy] Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 ++ net/mac80211/he.c | 15 +++++++++++++++ net/mac80211/ieee80211_i.h | 4 ++++ net/mac80211/mlme.c | 1 + 4 files changed, 22 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9effd286c1ae..bd91388797fc 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -600,6 +600,7 @@ struct ieee80211_ftm_responder_params { * nontransmitted BSSIDs * @profile_periodicity: the least number of beacon frames need to be received * in order to discover all the nontransmitted BSSIDs in the set. + * @he_operation: HE operation information of the AP we are connected to */ struct ieee80211_bss_conf { const u8 *bssid; @@ -661,6 +662,7 @@ struct ieee80211_bss_conf { u8 bssid_indicator; bool ema_ap; u8 profile_periodicity; + struct ieee80211_he_operation he_operation; }; /** diff --git a/net/mac80211/he.c b/net/mac80211/he.c index 219650591c79..f910f730ad0d 100644 --- a/net/mac80211/he.c +++ b/net/mac80211/he.c @@ -50,3 +50,18 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, he_cap->has_he = true; } + +void +ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif, + const struct ieee80211_he_operation *he_op_ie_elem) +{ + struct ieee80211_he_operation *he_operation = + &vif->bss_conf.he_operation; + + if (!he_op_ie_elem) { + memset(he_operation, 0, sizeof(*he_operation)); + return; + } + + vif->bss_conf.he_operation = *he_op_ie_elem; +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a5818ff0e2a4..ba1bc245678e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1873,6 +1873,10 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, const u8 *he_cap_ie, u8 he_cap_len, struct sta_info *sta); +void +ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif, + const struct ieee80211_he_operation *he_op_ie_elem); + /* Spectrum management */ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a99ad0325309..2b8a7428973d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3381,6 +3381,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, if (elems.uora_element) bss_conf->uora_ocw_range = elems.uora_element[0]; + ieee80211_he_op_ie_to_bss_conf(&sdata->vif, elems.he_operation); /* TODO: OPEN: what happens if BSS color disable is set? */ } -- GitLab From 2ab45876756fb6c132ae801b0939e0474f84c426 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 29 Jul 2019 12:45:12 +0200 Subject: [PATCH 1027/7155] mac80211: add support for the ADDBA extension element HE allows peers to negotiate the aggregation fragmentation level to be used during transmission. The level can be 1-3. The Ext element is added behind the ADDBA request inside the action frame. The responder will then reply with the same level or a lower one if the requested one is not supported. This patch only handles the negotiation part as the ADDBA frames get passed to the ATH11k firmware, which does the rest of the magic for us aswell as generating the requests. Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190729104512.27615-1-john@phrozen.org Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 2 ++ net/mac80211/agg-rx.c | 70 +++++++++++++++++++++++++++++++++----- net/mac80211/ht.c | 2 +- net/mac80211/ieee80211_i.h | 3 +- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 9c81895c63c1..7d3f2ced92d1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -981,6 +981,8 @@ struct ieee80211_mgmt { __le16 capab; __le16 timeout; __le16 start_seq_num; + /* followed by BA Extension */ + u8 variable[0]; } __packed addba_req; struct{ u8 action_code; diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 01b0dad24500..0e1bb43973b8 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -178,17 +178,52 @@ static void sta_rx_agg_reorder_timer_expired(struct timer_list *t) rcu_read_unlock(); } -static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, +static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + const struct ieee80211_addba_ext_ie *req) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_addba_ext_ie *resp; + const struct ieee80211_sta_he_cap *he_cap; + u8 frag_level, cap_frag_level; + u8 *pos; + + sband = ieee80211_get_sband(sdata); + he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type); + if (!he_cap) + return; + + pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie)); + *pos++ = WLAN_EID_ADDBA_EXT; + *pos++ = sizeof(struct ieee80211_addba_ext_ie); + resp = (struct ieee80211_addba_ext_ie *)pos; + resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG; + + frag_level = u32_get_bits(req->data, + IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK); + cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0], + IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK); + if (frag_level > cap_frag_level) + frag_level = cap_frag_level; + resp->data |= u8_encode_bits(frag_level, + IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK); +} + +static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, - u16 buf_size, u16 timeout) + u16 buf_size, u16 timeout, + const struct ieee80211_addba_ext_ie *addbaext) { + struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU); u16 capab; - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); + skb = dev_alloc_skb(sizeof(*mgmt) + + 2 + sizeof(struct ieee80211_addba_ext_ie) + + local->hw.extra_tx_headroom); if (!skb) return; @@ -222,13 +257,17 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); + if (sta->sta.he_cap.has_he && addbaext) + ieee80211_add_addbaext(sdata, skb, addbaext); + ieee80211_tx_skb(sdata, skb); } void ___ieee80211_start_rx_ba_session(struct sta_info *sta, u8 dialog_token, u16 timeout, u16 start_seq_num, u16 ba_policy, u16 tid, - u16 buf_size, bool tx, bool auto_seq) + u16 buf_size, bool tx, bool auto_seq, + const struct ieee80211_addba_ext_ie *addbaext) { struct ieee80211_local *local = sta->sdata->local; struct tid_ampdu_rx *tid_agg_rx; @@ -410,21 +449,22 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, } if (tx) - ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, + ieee80211_send_addba_resp(sta, sta->sta.addr, tid, dialog_token, status, 1, buf_size, - timeout); + timeout, addbaext); } static void __ieee80211_start_rx_ba_session(struct sta_info *sta, u8 dialog_token, u16 timeout, u16 start_seq_num, u16 ba_policy, u16 tid, u16 buf_size, bool tx, - bool auto_seq) + bool auto_seq, + const struct ieee80211_addba_ext_ie *addbaext) { mutex_lock(&sta->ampdu_mlme.mtx); ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout, start_seq_num, ba_policy, tid, - buf_size, tx, auto_seq); + buf_size, tx, auto_seq, addbaext); mutex_unlock(&sta->ampdu_mlme.mtx); } @@ -434,7 +474,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, size_t len) { u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; + struct ieee802_11_elems elems = { 0 }; u8 dialog_token; + int ies_len; /* extract session parameters from addba request frame */ dialog_token = mgmt->u.action.u.addba_req.dialog_token; @@ -447,9 +489,19 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; + ies_len = len - offsetof(struct ieee80211_mgmt, + u.action.u.addba_req.variable); + if (ies_len) { + ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, + ies_len, true, &elems, mgmt->bssid, NULL); + if (elems.parse_error) + return; + } + __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, start_seq_num, ba_policy, tid, - buf_size, true, false); + buf_size, true, false, + elems.addba_ext_ie); } void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index d5a500b2a448..a2e4d6b8fd98 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -359,7 +359,7 @@ void ieee80211_ba_session_work(struct work_struct *work) sta->ampdu_mlme.tid_rx_manage_offl)) ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, IEEE80211_MAX_AMPDU_BUF_HT, - false, true); + false, true, NULL); if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, sta->ampdu_mlme.tid_rx_manage_offl)) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ba1bc245678e..38769f5c3da4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1807,7 +1807,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, void ___ieee80211_start_rx_ba_session(struct sta_info *sta, u8 dialog_token, u16 timeout, u16 start_seq_num, u16 ba_policy, u16 tid, - u16 buf_size, bool tx, bool auto_seq); + u16 buf_size, bool tx, bool auto_seq, + const struct ieee80211_addba_ext_ie *addbaext); void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, enum ieee80211_agg_stop_reason reason); void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, -- GitLab From 44950d28cccf3049696e02d0adebb10e112cee24 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Mon, 29 Jul 2019 10:53:22 +0800 Subject: [PATCH 1028/7155] net: hns3: add reset checking before set channels hns3_set_channels() should check the resetting status firstly, since the device will reinitialize when resetting. If the reset has not completed, the hns3_set_channels() may access invalid memory. Signed-off-by: Jian Shen Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 69f7ef810654..08af782f70b5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4378,6 +4378,9 @@ int hns3_set_channels(struct net_device *netdev, u16 org_tqp_num; int ret; + if (hns3_nic_resetting(netdev)) + return -EBUSY; + if (ch->rx_count || ch->tx_count) return -EINVAL; -- GitLab From aa3253b8899d685811d159288f21cd2a2dbb5f0b Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Mon, 29 Jul 2019 10:53:23 +0800 Subject: [PATCH 1029/7155] net: hns3: add a check for get_reset_level For some cases, ops->get_reset_level may not be implemented, so we should check whether it is NULL before calling get_reset_level. Signed-off-by: Guangbin Huang Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 08af782f70b5..4d58c538fe9c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1963,7 +1963,7 @@ static pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev) ops = ae_dev->ops; /* request the reset */ - if (ops->reset_event) { + if (ops->reset_event && ops->get_reset_level) { if (ae_dev->hw_err_reset_req) { reset_type = ops->get_reset_level(ae_dev, &ae_dev->hw_err_reset_req); -- GitLab From 8e9eee78316037f07fd391ddaef99e9c29b53b4b Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Mon, 29 Jul 2019 10:53:24 +0800 Subject: [PATCH 1030/7155] net: hns3: remove upgrade reset level when reset fail Currently, hclge_reset_err_handle() will assert a global reset when the failing count is smaller than MAX_RESET_FAIL_CNT, which will affect other running functions. So this patch removes this upgrading, and uses re-scheduling reset task to do it. Signed-off-by: Huazhong Tan Reviewed-by: Yunsheng Lin Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3fde5471e1c0..3c64d70df4d4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3305,7 +3305,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) return ret; } -static bool hclge_reset_err_handle(struct hclge_dev *hdev, bool is_timeout) +static bool hclge_reset_err_handle(struct hclge_dev *hdev) { #define MAX_RESET_FAIL_CNT 5 @@ -3322,20 +3322,11 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev, bool is_timeout) return false; } else if (hdev->reset_fail_cnt < MAX_RESET_FAIL_CNT) { hdev->reset_fail_cnt++; - if (is_timeout) { - set_bit(hdev->reset_type, &hdev->reset_pending); - dev_info(&hdev->pdev->dev, - "re-schedule to wait for hw reset done\n"); - return true; - } - - dev_info(&hdev->pdev->dev, "Upgrade reset level\n"); - hclge_clear_reset_cause(hdev); - set_bit(HNAE3_GLOBAL_RESET, &hdev->default_reset_request); - mod_timer(&hdev->reset_timer, - jiffies + HCLGE_RESET_INTERVAL); - - return false; + set_bit(hdev->reset_type, &hdev->reset_pending); + dev_info(&hdev->pdev->dev, + "re-schedule reset task(%d)\n", + hdev->reset_fail_cnt); + return true; } hclge_clear_reset_cause(hdev); @@ -3382,7 +3373,6 @@ static int hclge_reset_stack(struct hclge_dev *hdev) static void hclge_reset(struct hclge_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); - bool is_timeout = false; int ret; /* Initialize ae_dev reset status as well, in case enet layer wants to @@ -3410,10 +3400,8 @@ static void hclge_reset(struct hclge_dev *hdev) if (ret) goto err_reset; - if (hclge_reset_wait(hdev)) { - is_timeout = true; + if (hclge_reset_wait(hdev)) goto err_reset; - } hdev->rst_stats.hw_reset_done_cnt++; @@ -3465,7 +3453,7 @@ static void hclge_reset(struct hclge_dev *hdev) err_reset_lock: rtnl_unlock(); err_reset: - if (hclge_reset_err_handle(hdev, is_timeout)) + if (hclge_reset_err_handle(hdev)) hclge_reset_task_schedule(hdev); } -- GitLab From d659f9f60f6a119654c65bfa58aa6fa762c0824d Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Mon, 29 Jul 2019 10:53:25 +0800 Subject: [PATCH 1031/7155] net: hns3: change GFP flag during lock period When allocating memory, the GFP_KERNEL cannot be used during the spin_lock period. This is because it may cause scheduling when holding spin_lock. This patch changes GFP flag to GFP_ATOMIC in this case. Fixes: dd74f815dd41 ("net: hns3: Add support for rule add/delete for flow director") Signed-off-by: Yufeng Mo Signed-off-by: lipeng 00277521 Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3c64d70df4d4..14199c455ddc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5796,7 +5796,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id, return -ENOSPC; } - rule = kzalloc(sizeof(*rule), GFP_KERNEL); + rule = kzalloc(sizeof(*rule), GFP_ATOMIC); if (!rule) { spin_unlock_bh(&hdev->fd_rule_lock); -- GitLab From 923713730db9795ac0658cc207935c11b2bbd705 Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Mon, 29 Jul 2019 10:53:26 +0800 Subject: [PATCH 1032/7155] net: hns3: modify firmware version display format This patch modifies firmware version display format in hclge(vf)_cmd_init() and hns3_get_drvinfo(). Also, adds some optimizations for firmware version display format. Signed-off-by: Yufeng Mo Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 9 +++++++++ .../net/ethernet/hisilicon/hns3/hns3_ethtool.c | 15 +++++++++++++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 10 +++++++++- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 10 +++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 48c7b70fc2c4..a4624db3b5d5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -179,6 +179,15 @@ struct hnae3_vector_info { #define HNAE3_RING_GL_RX 0 #define HNAE3_RING_GL_TX 1 +#define HNAE3_FW_VERSION_BYTE3_SHIFT 24 +#define HNAE3_FW_VERSION_BYTE3_MASK GENMASK(31, 24) +#define HNAE3_FW_VERSION_BYTE2_SHIFT 16 +#define HNAE3_FW_VERSION_BYTE2_MASK GENMASK(23, 16) +#define HNAE3_FW_VERSION_BYTE1_SHIFT 8 +#define HNAE3_FW_VERSION_BYTE1_MASK GENMASK(15, 8) +#define HNAE3_FW_VERSION_BYTE0_SHIFT 0 +#define HNAE3_FW_VERSION_BYTE0_MASK GENMASK(7, 0) + struct hnae3_ring_chain_node { struct hnae3_ring_chain_node *next; u32 tqp_index; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 5bff98a9b0dc..e71c92b8ae8a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -527,6 +527,7 @@ static void hns3_get_drvinfo(struct net_device *netdev, { struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; + u32 fw_version; if (!h->ae_algo->ops->get_fw_version) { netdev_err(netdev, "could not get fw version!\n"); @@ -545,8 +546,18 @@ static void hns3_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->bus_info)); drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0'; - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "0x%08x", - priv->ae_handle->ae_algo->ops->get_fw_version(h)); + fw_version = priv->ae_handle->ae_algo->ops->get_fw_version(h); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%lu.%lu.%lu.%lu", + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); } static u32 hns3_get_link(struct net_device *netdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 22f6acd45d9a..d9858f285460 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -419,7 +419,15 @@ int hclge_cmd_init(struct hclge_dev *hdev) } hdev->fw_version = version; - dev_info(&hdev->pdev->dev, "The firmware version is %08x\n", version); + dev_info(&hdev->pdev->dev, "The firmware version is %lu.%lu.%lu.%lu\n", + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 652b796044e3..8f21eb3d9bd2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -405,7 +405,15 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev) } hdev->fw_version = version; - dev_info(&hdev->pdev->dev, "The firmware version is %08x\n", version); + dev_info(&hdev->pdev->dev, "The firmware version is %lu.%lu.%lu.%lu\n", + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE3_MASK, + HNAE3_FW_VERSION_BYTE3_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE2_MASK, + HNAE3_FW_VERSION_BYTE2_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE1_MASK, + HNAE3_FW_VERSION_BYTE1_SHIFT), + hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK, + HNAE3_FW_VERSION_BYTE0_SHIFT)); return 0; -- GitLab From 1c822948fa600d2d2e7926640279b16d1f4a7423 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Mon, 29 Jul 2019 10:53:27 +0800 Subject: [PATCH 1033/7155] net: hns3: add debug messages to identify eth down cause Some times just see the eth interface have been down/up via dmesg, but can not know why the eth down. So adds some debug messages to identify the cause for this. Signed-off-by: Yonglong Liu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 18 ++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3_ethtool.c | 19 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_dcb.c | 11 +++++++++++ 3 files changed, 48 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 4d58c538fe9c..0cf9301beb2b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -459,6 +459,9 @@ static int hns3_nic_net_open(struct net_device *netdev) h->ae_algo->ops->set_timer_task(priv->ae_handle, true); hns3_config_xps(priv); + + netif_dbg(h, drv, netdev, "net open\n"); + return 0; } @@ -519,6 +522,8 @@ static int hns3_nic_net_stop(struct net_device *netdev) if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state)) return 0; + netif_dbg(h, drv, netdev, "net stop\n"); + if (h->ae_algo->ops->set_timer_task) h->ae_algo->ops->set_timer_task(priv->ae_handle, false); @@ -1550,6 +1555,8 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) h = hns3_get_handle(netdev); kinfo = &h->kinfo; + netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc); + return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; } @@ -1593,6 +1600,10 @@ static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, struct hnae3_handle *h = hns3_get_handle(netdev); int ret = -EIO; + netif_dbg(h, drv, netdev, + "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=%u\n", + vf, vlan, qos, vlan_proto); + if (h->ae_algo->ops->set_vf_vlan_filter) ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan, qos, vlan_proto); @@ -1611,6 +1622,9 @@ static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu) if (!h->ae_algo->ops->set_mtu) return -EOPNOTSUPP; + netif_dbg(h, drv, netdev, + "change mtu from %u to %d\n", netdev->mtu, new_mtu); + ret = h->ae_algo->ops->set_mtu(h, new_mtu); if (ret) netdev_err(netdev, "failed to change MTU in hardware %d\n", @@ -4395,6 +4409,10 @@ int hns3_set_channels(struct net_device *netdev, if (kinfo->rss_size == new_tqp_num) return 0; + netif_dbg(h, drv, netdev, + "set channels: tqp_num=%u, rxfh=%d\n", + new_tqp_num, rxfh_configured); + ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index e71c92b8ae8a..fe0f82a97234 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -311,6 +311,8 @@ static void hns3_self_test(struct net_device *ndev, if (eth_test->flags != ETH_TEST_FL_OFFLINE) return; + netif_dbg(h, drv, ndev, "self test start"); + st_param[HNAE3_LOOP_APP][0] = HNAE3_LOOP_APP; st_param[HNAE3_LOOP_APP][1] = h->flags & HNAE3_SUPPORT_APP_LOOPBACK; @@ -374,6 +376,8 @@ static void hns3_self_test(struct net_device *ndev, if (if_running) ndev->netdev_ops->ndo_open(ndev); + + netif_dbg(h, drv, ndev, "self test end\n"); } static int hns3_get_sset_count(struct net_device *netdev, int stringset) @@ -604,6 +608,10 @@ static int hns3_set_pauseparam(struct net_device *netdev, { struct hnae3_handle *h = hns3_get_handle(netdev); + netif_dbg(h, drv, netdev, + "set pauseparam: autoneg=%u, rx:%u, tx:%u\n", + param->autoneg, param->rx_pause, param->tx_pause); + if (h->ae_algo->ops->set_pauseparam) return h->ae_algo->ops->set_pauseparam(h, param->autoneg, param->rx_pause, @@ -743,6 +751,11 @@ static int hns3_set_link_ksettings(struct net_device *netdev, if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) return -EINVAL; + netif_dbg(handle, drv, netdev, + "set link(%s): autoneg=%u, speed=%u, duplex=%u\n", + netdev->phydev ? "phy" : "mac", + cmd->base.autoneg, cmd->base.speed, cmd->base.duplex); + /* Only support ksettings_set for netdev with phy attached for now */ if (netdev->phydev) return phy_ethtool_ksettings_set(netdev->phydev, cmd); @@ -984,6 +997,9 @@ static int hns3_nway_reset(struct net_device *netdev) return -EINVAL; } + netif_dbg(handle, drv, netdev, + "nway reset (using %s)\n", phy ? "phy" : "mac"); + if (phy) return genphy_restart_aneg(phy); @@ -1308,6 +1324,9 @@ static int hns3_set_fecparam(struct net_device *netdev, if (!ops->set_fec) return -EOPNOTSUPP; fec_mode = eth_to_loc_fec(fec->fec); + + netif_dbg(handle, drv, netdev, "set fecparam: mode=%u\n", fec_mode); + return ops->set_fec(handle, fec_mode); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index bac4ce13f6ae..814e0f076e32 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -201,6 +201,7 @@ static int hclge_client_setup_tc(struct hclge_dev *hdev) static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; bool map_changed = false; u8 num_tc = 0; @@ -215,6 +216,8 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) return ret; if (map_changed) { + netif_dbg(h, drv, netdev, "set ets\n"); + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); if (ret) return ret; @@ -300,6 +303,7 @@ static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; u8 i, j, pfc_map, *prio_tc; @@ -325,6 +329,10 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) hdev->tm_info.hw_pfc_map = pfc_map; hdev->tm_info.pfc_en = pfc->pfc_en; + netif_dbg(h, drv, netdev, + "set pfc: pfc_en=%u, pfc_map=%u, num_tc=%u\n", + pfc->pfc_en, pfc_map, hdev->tm_info.num_tc); + hclge_tm_pfc_info_update(hdev); return hclge_pause_setup_hw(hdev, false); @@ -345,8 +353,11 @@ static u8 hclge_getdcbx(struct hnae3_handle *h) static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) { struct hclge_vport *vport = hclge_get_vport(h); + struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; + netif_dbg(h, drv, netdev, "set dcbx: mode=%u\n", mode); + /* No support for LLD_MANAGED modes or CEE */ if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || (mode & DCB_CAP_DCBX_VER_CEE) || -- GitLab From 7be1b9f3e99f6213d053d16ed2438126931d8351 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Mon, 29 Jul 2019 10:53:28 +0800 Subject: [PATCH 1034/7155] net: hns3: make hclge_service use delayed workqueue Use delayed work instead of using timers to trigger the hclge_serive. Simplify the code with one less middle function and in order to support misc irq affinity. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 52 +++++++------------ .../hisilicon/hns3/hns3pf/hclge_main.h | 3 +- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 14199c455ddc..13c9697f3a02 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2513,8 +2513,12 @@ static void hclge_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) && !test_bit(HCLGE_STATE_REMOVING, &hdev->state) && - !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) - (void)schedule_work(&hdev->service_task); + !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) { + hdev->hw_stats.stats_timer++; + hdev->fd_arfs_expire_timer++; + mod_delayed_work(system_wq, &hdev->service_task, + round_jiffies_relative(HZ)); + } } static int hclge_get_mac_link_status(struct hclge_dev *hdev) @@ -2729,25 +2733,6 @@ static int hclge_get_status(struct hnae3_handle *handle) return hdev->hw.mac.link; } -static void hclge_service_timer(struct timer_list *t) -{ - struct hclge_dev *hdev = from_timer(hdev, t, service_timer); - - mod_timer(&hdev->service_timer, jiffies + HZ); - hdev->hw_stats.stats_timer++; - hdev->fd_arfs_expire_timer++; - hclge_task_schedule(hdev); -} - -static void hclge_service_complete(struct hclge_dev *hdev) -{ - WARN_ON(!test_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)); - - /* Flush memory before next watchdog */ - smp_mb__before_atomic(); - clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); -} - static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) { u32 rst_src_reg, cmdq_src_reg, msix_src_reg; @@ -3594,7 +3579,9 @@ static void hclge_update_vport_alive(struct hclge_dev *hdev) static void hclge_service_task(struct work_struct *work) { struct hclge_dev *hdev = - container_of(work, struct hclge_dev, service_task); + container_of(work, struct hclge_dev, service_task.work); + + clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) { hclge_update_stats_for_all(hdev); @@ -3609,7 +3596,8 @@ static void hclge_service_task(struct work_struct *work) hclge_rfs_filter_expire(hdev); hdev->fd_arfs_expire_timer = 0; } - hclge_service_complete(hdev); + + hclge_task_schedule(hdev); } struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle) @@ -6148,10 +6136,13 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable) struct hclge_dev *hdev = vport->back; if (enable) { - mod_timer(&hdev->service_timer, jiffies + HZ); + hclge_task_schedule(hdev); } else { - del_timer_sync(&hdev->service_timer); - cancel_work_sync(&hdev->service_task); + /* Set the DOWN flag here to disable the service to be + * scheduled again + */ + set_bit(HCLGE_STATE_DOWN, &hdev->state); + cancel_delayed_work_sync(&hdev->service_task); clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); } } @@ -8590,12 +8581,10 @@ static void hclge_state_uninit(struct hclge_dev *hdev) set_bit(HCLGE_STATE_DOWN, &hdev->state); set_bit(HCLGE_STATE_REMOVING, &hdev->state); - if (hdev->service_timer.function) - del_timer_sync(&hdev->service_timer); if (hdev->reset_timer.function) del_timer_sync(&hdev->reset_timer); - if (hdev->service_task.func) - cancel_work_sync(&hdev->service_task); + if (hdev->service_task.work.func) + cancel_delayed_work_sync(&hdev->service_task); if (hdev->rst_service_task.func) cancel_work_sync(&hdev->rst_service_task); if (hdev->mbx_service_task.func) @@ -8800,9 +8789,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_dcb_ops_set(hdev); - timer_setup(&hdev->service_timer, hclge_service_timer, 0); timer_setup(&hdev->reset_timer, hclge_reset_timer, 0); - INIT_WORK(&hdev->service_task, hclge_service_task); + INIT_DELAYED_WORK(&hdev->service_task, hclge_service_task); INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task); INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6a12285f4c76..dde8f22b0810 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -806,9 +806,8 @@ struct hclge_dev { u16 adminq_work_limit; /* Num of admin receive queue desc to process */ unsigned long service_timer_period; unsigned long service_timer_previous; - struct timer_list service_timer; struct timer_list reset_timer; - struct work_struct service_task; + struct delayed_work service_task; struct work_struct rst_service_task; struct work_struct mbx_service_task; -- GitLab From 0812545487eca362126cc1ef6b7798ecac693629 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Mon, 29 Jul 2019 10:53:29 +0800 Subject: [PATCH 1035/7155] net: hns3: add interrupt affinity support for misc interrupt The misc interrupt is used to schedule the reset and mailbox subtask, and service_task delayed_work is used to do periodic management work each second. This patch sets the above three subtask's affinity using the misc interrupt' affinity. Also this patch setups a affinity notify for misc interrupt to allow user to change the above three subtask's affinity. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 53 +++++++++++++++++-- .../hisilicon/hns3/hns3pf/hclge_main.h | 4 ++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 13c9697f3a02..30a70743de89 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1270,6 +1270,12 @@ static int hclge_configure(struct hclge_dev *hdev) hclge_init_kdump_kernel_config(hdev); + /* Set the init affinity based on pci func number */ + i = cpumask_weight(cpumask_of_node(dev_to_node(&hdev->pdev->dev))); + i = i ? PCI_FUNC(hdev->pdev->devfn) % i : 0; + cpumask_set_cpu(cpumask_local_spread(i, dev_to_node(&hdev->pdev->dev)), + &hdev->affinity_mask); + return ret; } @@ -2499,14 +2505,16 @@ static void hclge_mbx_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) && !test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state)) - schedule_work(&hdev->mbx_service_task); + queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq, + &hdev->mbx_service_task); } static void hclge_reset_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) && !test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state)) - schedule_work(&hdev->rst_service_task); + queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq, + &hdev->rst_service_task); } static void hclge_task_schedule(struct hclge_dev *hdev) @@ -2516,8 +2524,9 @@ static void hclge_task_schedule(struct hclge_dev *hdev) !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) { hdev->hw_stats.stats_timer++; hdev->fd_arfs_expire_timer++; - mod_delayed_work(system_wq, &hdev->service_task, - round_jiffies_relative(HZ)); + mod_delayed_work_on(cpumask_first(&hdev->affinity_mask), + system_wq, &hdev->service_task, + round_jiffies_relative(HZ)); } } @@ -2903,6 +2912,36 @@ static void hclge_get_misc_vector(struct hclge_dev *hdev) hdev->num_msi_used += 1; } +static void hclge_irq_affinity_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct hclge_dev *hdev = container_of(notify, struct hclge_dev, + affinity_notify); + + cpumask_copy(&hdev->affinity_mask, mask); +} + +static void hclge_irq_affinity_release(struct kref *ref) +{ +} + +static void hclge_misc_affinity_setup(struct hclge_dev *hdev) +{ + irq_set_affinity_hint(hdev->misc_vector.vector_irq, + &hdev->affinity_mask); + + hdev->affinity_notify.notify = hclge_irq_affinity_notify; + hdev->affinity_notify.release = hclge_irq_affinity_release; + irq_set_affinity_notifier(hdev->misc_vector.vector_irq, + &hdev->affinity_notify); +} + +static void hclge_misc_affinity_teardown(struct hclge_dev *hdev) +{ + irq_set_affinity_notifier(hdev->misc_vector.vector_irq, NULL); + irq_set_affinity_hint(hdev->misc_vector.vector_irq, NULL); +} + static int hclge_misc_irq_init(struct hclge_dev *hdev) { int ret; @@ -8794,6 +8833,11 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task); INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task); + /* Setup affinity after service timer setup because add_timer_on + * is called in affinity notify. + */ + hclge_misc_affinity_setup(hdev); + hclge_clear_all_event_cause(hdev); hclge_clear_resetting_state(hdev); @@ -8955,6 +8999,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) struct hclge_dev *hdev = ae_dev->priv; struct hclge_mac *mac = &hdev->hw.mac; + hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); if (mac->phydev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index dde8f22b0810..688e4250491d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -863,6 +863,10 @@ struct hclge_dev { DECLARE_KFIFO(mac_tnl_log, struct hclge_mac_tnl_stats, HCLGE_MAC_TNL_LOG_SIZE); + + /* affinity mask and notify for misc interrupt */ + cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; }; /* VPort level vlan tag configuration for TX direction */ -- GitLab From dbba6da0c67ca99721b74760d3cc69df8a5a8230 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Mon, 29 Jul 2019 10:53:30 +0800 Subject: [PATCH 1036/7155] net: hns3: Add support for using order 1 pages with a 4K buffer Hardware supports 0.5K, 1K, 2K, 4K RX buffer size, the RX buffer can not be reused because the hns3_page_order return 0 when page size and RX buffer size are both 4096. So this patch changes the hns3_page_order to return 1 when RX buffer is greater than half of the page size and page size is less the 8192, and dev_alloc_pages has already been used to allocate the compound page for RX buffer. This patch also changes hnae3_* to hns3_* for page order and RX buffer size calculation because they are used in hns3 module. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 10 +++++----- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0cf9301beb2b..d2df42d30d88 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2081,7 +2081,7 @@ static void hns3_set_default_feature(struct net_device *netdev) static int hns3_alloc_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) { - unsigned int order = hnae3_page_order(ring); + unsigned int order = hns3_page_order(ring); struct page *p; p = dev_alloc_pages(order); @@ -2092,7 +2092,7 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, cb->page_offset = 0; cb->reuse_flag = 0; cb->buf = page_address(p); - cb->length = hnae3_page_size(ring); + cb->length = hns3_page_size(ring); cb->type = DESC_TYPE_PAGE; return 0; @@ -2395,7 +2395,7 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, { struct hns3_desc *desc = &ring->desc[ring->next_to_clean]; int size = le16_to_cpu(desc->rx.size); - u32 truesize = hnae3_buf_size(ring); + u32 truesize = hns3_buf_size(ring); skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, size - pull_len, truesize); @@ -2410,7 +2410,7 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, /* Move offset up to the next cache line */ desc_cb->page_offset += truesize; - if (desc_cb->page_offset + truesize <= hnae3_page_size(ring)) { + if (desc_cb->page_offset + truesize <= hns3_page_size(ring)) { desc_cb->reuse_flag = 1; /* Bump ref count on page before it is given */ get_page(desc_cb->priv); @@ -2692,7 +2692,7 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc, } if (ring->tail_skb) { - head_skb->truesize += hnae3_buf_size(ring); + head_skb->truesize += hns3_buf_size(ring); head_skb->data_len += le16_to_cpu(desc->rx.size); head_skb->len += le16_to_cpu(desc->rx.size); skb = ring->tail_skb; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 848b866761df..1a17856f9a3b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -608,9 +608,18 @@ static inline bool hns3_nic_resetting(struct net_device *netdev) #define tx_ring_data(priv, idx) ((priv)->ring_data[idx]) -#define hnae3_buf_size(_ring) ((_ring)->buf_size) -#define hnae3_page_order(_ring) (get_order(hnae3_buf_size(_ring))) -#define hnae3_page_size(_ring) (PAGE_SIZE << (u32)hnae3_page_order(_ring)) +#define hns3_buf_size(_ring) ((_ring)->buf_size) + +static inline unsigned int hns3_page_order(struct hns3_enet_ring *ring) +{ +#if (PAGE_SIZE < 8192) + if (ring->buf_size > (PAGE_SIZE / 2)) + return 1; +#endif + return 0; +} + +#define hns3_page_size(_ring) (PAGE_SIZE << hns3_page_order(_ring)) /* iterator for handling rings in ring group */ #define hns3_for_each_ring(pos, head) \ -- GitLab From 08d80a4c90bdaa83680d1bdb58403fd8fe101885 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Mon, 29 Jul 2019 10:53:31 +0800 Subject: [PATCH 1037/7155] net: hns3: use dev_info() instead of pr_info() dev_info() is more appropriate for printing messages when driver initialization done, so switch to dev_info(). Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 +++- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 30a70743de89..4138780fca39 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8862,7 +8862,9 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_state_init(hdev); hdev->last_reset_time = jiffies; - pr_info("%s driver initialization finished.\n", HCLGE_DRIVER_NAME); + dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n", + HCLGE_DRIVER_NAME); + return 0; err_mdiobus_unreg: diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index a13a0e101c3b..ae0e6a69d54b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2695,7 +2695,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) } hdev->last_reset_time = jiffies; - pr_info("finished initializing %s driver\n", HCLGEVF_DRIVER_NAME); + dev_info(&hdev->pdev->dev, "finished initializing %s driver\n", + HCLGEVF_DRIVER_NAME); return 0; -- GitLab From 4215484f8e33c8a4664aecb6db5ce2c544d3b908 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 10 Jul 2019 13:33:26 +0800 Subject: [PATCH 1038/7155] platform/x86: hp_accel: Add support for HP ZBook 17 G5 HP ZBook 17 G5 needs a non-standard mapping, x_inverted. Signed-off-by: Kai-Heng Feng Signed-off-by: Andy Shevchenko --- drivers/platform/x86/hp_accel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 7a2747455237..799cbe2ffcf3 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -240,6 +240,7 @@ static const struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted), + AXIS_DMI_MATCH("HPZBook17G5", "HP ZBook 17 G5", x_inverted), AXIS_DMI_MATCH("HPZBook17", "HP ZBook 17", xy_swap_yz_inverted), { NULL, } /* Laptop models without axis info (yet): -- GitLab From 340f25ff1d4fd3bfe0d3e0769261fec8fb32ae9f Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Thu, 4 Jul 2019 00:29:51 +0800 Subject: [PATCH 1039/7155] platform/x86: asus-wmi: Use kmemdup rather than duplicating its implementation kmemdup is introduced to duplicate a region of memory in a neat way. Rather than kmalloc/kzalloc + memcpy, which the programmer needs to write the size twice (sometimes lead to mistakes), kmemdup improves readability, leads to smaller code and also reduce the chances of mistakes. Suggestion to use kmemdup rather than using kmalloc/kzalloc + memcpy. Signed-off-by: Fuqian Huang Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-wmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index ca28d27dae63..0c6a810fcb72 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -292,12 +292,11 @@ static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args) * Copy to dma capable address otherwise memory corruption occurs as * bios has to be able to access it. */ - input.pointer = kzalloc(args.length, GFP_DMA | GFP_KERNEL); + input.pointer = kmemdup(args.pointer, args.length, GFP_DMA | GFP_KERNEL); input.length = args.length; if (!input.pointer) return -ENOMEM; phys_addr = virt_to_phys(input.pointer); - memcpy(input.pointer, args.pointer, args.length); status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_AGFN, phys_addr, 0, &retval); -- GitLab From 35b7c80827e9352b88a2379f06cbb9aa3dd64c14 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Thu, 4 Jul 2019 00:30:00 +0800 Subject: [PATCH 1040/7155] platform/x86: thinkpad_acpi: Use kmemdup rather than duplicating its implementation kmemdup is introduced to duplicate a region of memory in a neat way. Rather than kmalloc/kzalloc + memcpy, which the programmer needs to write the size twice (sometimes lead to mistakes), kmemdup improves readability, leads to smaller code and also reduce the chances of mistakes. Suggestion to use kmemdup rather than using kmalloc/kzalloc + memcpy. Signed-off-by: Fuqian Huang Signed-off-by: Andy Shevchenko --- drivers/platform/x86/thinkpad_acpi.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7bde4640ef34..d379bdf98a0f 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3647,22 +3647,19 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) goto err_exit; /* Set up key map */ - hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, - GFP_KERNEL); - if (!hotkey_keycode_map) { - pr_err("failed to allocate memory for key map\n"); - res = -ENOMEM; - goto err_exit; - } - keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable, ARRAY_SIZE(tpacpi_keymap_qtable)); BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps)); dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "using keymap number %lu\n", keymap_id); - memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id], - TPACPI_HOTKEY_MAP_SIZE); + hotkey_keycode_map = kmemdup(&tpacpi_keymaps[keymap_id], + TPACPI_HOTKEY_MAP_SIZE, GFP_KERNEL); + if (!hotkey_keycode_map) { + pr_err("failed to allocate memory for key map\n"); + res = -ENOMEM; + goto err_exit; + } input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; -- GitLab From 18917d51472fe3b126a3a8f756c6b18085eb8130 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Mon, 29 Jul 2019 16:35:01 +0300 Subject: [PATCH 1041/7155] NFC: fix attrs checks in netlink interface nfc_genl_deactivate_target() relies on the NFC_ATTR_TARGET_INDEX attribute being present, but doesn't check whether it is actually provided by the user. Same goes for nfc_genl_fw_download() and NFC_ATTR_FIRMWARE_NAME. This patch adds appropriate checks. Found with syzkaller. Signed-off-by: Andrey Konovalov Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- net/nfc/netlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ea64c90b14e8..17e6ca62f1be 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -970,7 +970,8 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info) int rc; u32 idx; - if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || + !info->attrs[NFC_ATTR_TARGET_INDEX]) return -EINVAL; idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); @@ -1018,7 +1019,8 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info) struct sk_buff *msg = NULL; u32 idx; - if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || + !info->attrs[NFC_ATTR_FIRMWARE_NAME]) return -EINVAL; idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); -- GitLab From 1b14a37565d9e88b82b8a227690e5fbc0079b61b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:02 +0300 Subject: [PATCH 1042/7155] NFC: nxp-nci: Add NXP1001 to the ACPI ID table It seems a lot of laptops are equipped with NXP NFC300 chip with the ACPI ID NXP1001 as per DSDT. Append it to the driver's ACPI ID table. Reported-by: Sedat Dilek Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 4aeb3861b409..5db71869f04b 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -396,6 +396,7 @@ MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match); #ifdef CONFIG_ACPI static struct acpi_device_id acpi_id[] = { + { "NXP1001" }, { "NXP7471" }, { }, }; -- GitLab From 3b0b278312ba7d6c1eb8b2fb48d459fb7f341a20 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:03 +0300 Subject: [PATCH 1043/7155] NFC: nxp-nci: Get rid of platform data Legacy platform data must go away. We are on the safe side here since there are no users of it in the kernel. If anyone by any odd reason needs it the GPIO lookup tables and built-in device properties at your service. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- MAINTAINERS | 1 - drivers/nfc/nxp-nci/core.c | 1 - drivers/nfc/nxp-nci/i2c.c | 9 +-------- drivers/nfc/nxp-nci/nxp-nci.h | 1 - include/linux/platform_data/nxp-nci.h | 19 ------------------- 5 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 include/linux/platform_data/nxp-nci.h diff --git a/MAINTAINERS b/MAINTAINERS index 9cc156c58f0c..ee663e0e2f2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11327,7 +11327,6 @@ F: include/net/nfc/ F: include/uapi/linux/nfc.h F: drivers/nfc/ F: include/linux/platform_data/nfcmrvl.h -F: include/linux/platform_data/nxp-nci.h F: Documentation/devicetree/bindings/net/nfc/ NFS, SUNRPC, AND LOCKD CLIENTS diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c index 8dafc696719f..aed18ca60170 100644 --- a/drivers/nfc/nxp-nci/core.c +++ b/drivers/nfc/nxp-nci/core.c @@ -14,7 +14,6 @@ #include #include #include -#include #include diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 5db71869f04b..47b3b7e612e6 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -304,7 +303,6 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct nxp_nci_i2c_phy *phy; - struct nxp_nci_nfc_platform_data *pdata; int r; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { @@ -323,17 +321,12 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, phy->i2c_dev = client; i2c_set_clientdata(client, phy); - pdata = client->dev.platform_data; - - if (!pdata && client->dev.of_node) { + if (client->dev.of_node) { r = nxp_nci_i2c_parse_devtree(client); if (r < 0) { nfc_err(&client->dev, "Failed to get DT data\n"); goto probe_exit; } - } else if (pdata) { - phy->gpio_en = pdata->gpio_en; - phy->gpio_fw = pdata->gpio_fw; } else if (ACPI_HANDLE(&client->dev)) { r = nxp_nci_i2c_acpi_config(phy); if (r < 0) diff --git a/drivers/nfc/nxp-nci/nxp-nci.h b/drivers/nfc/nxp-nci/nxp-nci.h index 6fe7c45544bf..ae3fb2735a4e 100644 --- a/drivers/nfc/nxp-nci/nxp-nci.h +++ b/drivers/nfc/nxp-nci/nxp-nci.h @@ -14,7 +14,6 @@ #include #include #include -#include #include diff --git a/include/linux/platform_data/nxp-nci.h b/include/linux/platform_data/nxp-nci.h deleted file mode 100644 index 97827ad468e2..000000000000 --- a/include/linux/platform_data/nxp-nci.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Generic platform data for the NXP NCI NFC chips. - * - * Copyright (C) 2014 NXP Semiconductors All rights reserved. - * - * Authors: Clément Perrochaud - */ - -#ifndef _NXP_NCI_H_ -#define _NXP_NCI_H_ - -struct nxp_nci_nfc_platform_data { - unsigned int gpio_en; - unsigned int gpio_fw; - unsigned int irq; -}; - -#endif /* _NXP_NCI_H_ */ -- GitLab From 43201767b44cbd873c60dbd2acd370147588cb18 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:04 +0300 Subject: [PATCH 1044/7155] NFC: nxp-nci: Convert to use GPIO descriptor Since we got rid of platform data, the driver may use GPIO descriptor directly. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/core.c | 1 - drivers/nfc/nxp-nci/i2c.c | 60 ++++++++++---------------------------- 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c index aed18ca60170..a0ce95a287c5 100644 --- a/drivers/nfc/nxp-nci/core.c +++ b/drivers/nfc/nxp-nci/core.c @@ -11,7 +11,6 @@ */ #include -#include #include #include diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 47b3b7e612e6..713c267acf88 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include @@ -37,8 +35,8 @@ struct nxp_nci_i2c_phy { struct i2c_client *i2c_dev; struct nci_dev *ndev; - unsigned int gpio_en; - unsigned int gpio_fw; + struct gpio_desc *gpiod_en; + struct gpio_desc *gpiod_fw; int hard_fault; /* * < 0 if hardware error occurred (e.g. i2c err) @@ -51,8 +49,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id, { struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; - gpio_set_value(phy->gpio_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); - gpio_set_value(phy->gpio_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); + gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); + gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); usleep_range(10000, 15000); if (mode == NXP_NCI_MODE_COLD) @@ -252,30 +250,18 @@ static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id) static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) { struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client); - struct device_node *pp; - int r; - - pp = client->dev.of_node; - if (!pp) - return -ENODEV; - r = of_get_named_gpio(pp, "enable-gpios", 0); - if (r == -EPROBE_DEFER) - r = of_get_named_gpio(pp, "enable-gpios", 0); - if (r < 0) { - nfc_err(&client->dev, "Failed to get EN gpio, error: %d\n", r); - return r; + phy->gpiod_en = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_en)) { + nfc_err(&client->dev, "Failed to get EN gpio\n"); + return PTR_ERR(phy->gpiod_en); } - phy->gpio_en = r; - r = of_get_named_gpio(pp, "firmware-gpios", 0); - if (r == -EPROBE_DEFER) - r = of_get_named_gpio(pp, "firmware-gpios", 0); - if (r < 0) { - nfc_err(&client->dev, "Failed to get FW gpio, error: %d\n", r); - return r; + phy->gpiod_fw = devm_gpiod_get(&client->dev, "firmware", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_fw)) { + nfc_err(&client->dev, "Failed to get FW gpio\n"); + return PTR_ERR(phy->gpiod_fw); } - phy->gpio_fw = r; return 0; } @@ -283,19 +269,15 @@ static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) { struct i2c_client *client = phy->i2c_dev; - struct gpio_desc *gpiod_en, *gpiod_fw; - gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW); - gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW); + phy->gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW); + phy->gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW); - if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw)) { + if (IS_ERR(phy->gpiod_en) || IS_ERR(phy->gpiod_fw)) { nfc_err(&client->dev, "No GPIOs\n"); return -EINVAL; } - phy->gpio_en = desc_to_gpio(gpiod_en); - phy->gpio_fw = desc_to_gpio(gpiod_fw); - return 0; } @@ -331,24 +313,12 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, r = nxp_nci_i2c_acpi_config(phy); if (r < 0) goto probe_exit; - goto nci_probe; } else { nfc_err(&client->dev, "No platform data\n"); r = -EINVAL; goto probe_exit; } - r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en, - GPIOF_OUT_INIT_LOW, "nxp_nci_en"); - if (r < 0) - goto probe_exit; - - r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw, - GPIOF_OUT_INIT_LOW, "nxp_nci_fw"); - if (r < 0) - goto probe_exit; - -nci_probe: r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); if (r < 0) -- GitLab From 099d03f02dbffe1575d86063b2bf416502faa5e9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:05 +0300 Subject: [PATCH 1045/7155] NFC: nxp-nci: Add GPIO ACPI mapping table In order to unify GPIO resource request prepare gpiod_get_index() to behave correctly when there is no mapping provided by firmware. Here we add explicit mapping between _CRS GpioIo() resources and their names used in the driver. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 713c267acf88..7344405feddf 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -247,6 +247,15 @@ static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id) return IRQ_NONE; } +static const struct acpi_gpio_params firmware_gpios = { 1, 0, false }; +static const struct acpi_gpio_params enable_gpios = { 2, 0, false }; + +static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { + { "enable-gpios", &enable_gpios, 1 }, + { "firmware-gpios", &firmware_gpios, 1 }, + { } +}; + static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) { struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client); @@ -269,9 +278,14 @@ static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) { struct i2c_client *client = phy->i2c_dev; + int r; - phy->gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW); - phy->gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW); + r = devm_acpi_dev_add_driver_gpios(&client->dev, acpi_nxp_nci_gpios); + if (r) + return r; + + phy->gpiod_en = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); + phy->gpiod_fw = devm_gpiod_get(&client->dev, "firmware", GPIOD_OUT_LOW); if (IS_ERR(phy->gpiod_en) || IS_ERR(phy->gpiod_fw)) { nfc_err(&client->dev, "No GPIOs\n"); -- GitLab From ad0acfd69add44ab00abcce2240a7523f75bd315 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:06 +0300 Subject: [PATCH 1046/7155] NFC: nxp-nci: Get rid of code duplication in ->probe() Since OF and ACPI case almost the same get rid of code duplication by moving gpiod_get() calls directly to ->probe(). Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 68 +++++++++------------------------------ 1 file changed, 15 insertions(+), 53 deletions(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 7344405feddf..6a627d1b6f85 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -256,48 +256,10 @@ static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { { } }; -static int nxp_nci_i2c_parse_devtree(struct i2c_client *client) -{ - struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client); - - phy->gpiod_en = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(phy->gpiod_en)) { - nfc_err(&client->dev, "Failed to get EN gpio\n"); - return PTR_ERR(phy->gpiod_en); - } - - phy->gpiod_fw = devm_gpiod_get(&client->dev, "firmware", GPIOD_OUT_LOW); - if (IS_ERR(phy->gpiod_fw)) { - nfc_err(&client->dev, "Failed to get FW gpio\n"); - return PTR_ERR(phy->gpiod_fw); - } - - return 0; -} - -static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) -{ - struct i2c_client *client = phy->i2c_dev; - int r; - - r = devm_acpi_dev_add_driver_gpios(&client->dev, acpi_nxp_nci_gpios); - if (r) - return r; - - phy->gpiod_en = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); - phy->gpiod_fw = devm_gpiod_get(&client->dev, "firmware", GPIOD_OUT_LOW); - - if (IS_ERR(phy->gpiod_en) || IS_ERR(phy->gpiod_fw)) { - nfc_err(&client->dev, "No GPIOs\n"); - return -EINVAL; - } - - return 0; -} - static int nxp_nci_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct nxp_nci_i2c_phy *phy; int r; @@ -317,20 +279,20 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, phy->i2c_dev = client; i2c_set_clientdata(client, phy); - if (client->dev.of_node) { - r = nxp_nci_i2c_parse_devtree(client); - if (r < 0) { - nfc_err(&client->dev, "Failed to get DT data\n"); - goto probe_exit; - } - } else if (ACPI_HANDLE(&client->dev)) { - r = nxp_nci_i2c_acpi_config(phy); - if (r < 0) - goto probe_exit; - } else { - nfc_err(&client->dev, "No platform data\n"); - r = -EINVAL; - goto probe_exit; + r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios); + if (r) + return r; + + phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_en)) { + nfc_err(dev, "Failed to get EN gpio\n"); + return PTR_ERR(phy->gpiod_en); + } + + phy->gpiod_fw = devm_gpiod_get(dev, "firmware", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_fw)) { + nfc_err(dev, "Failed to get FW gpio\n"); + return PTR_ERR(phy->gpiod_fw); } r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, -- GitLab From 4f1cbf24fc523167e50f375d3a635431a96a4b03 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:07 +0300 Subject: [PATCH 1047/7155] NFC: nxp-nci: Get rid of useless label Return directly in ->probe() since there no special cleaning is needed. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 6a627d1b6f85..bec9b1ea78e2 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -265,16 +265,13 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); - r = -ENODEV; - goto probe_exit; + return -ENODEV; } phy = devm_kzalloc(&client->dev, sizeof(struct nxp_nci_i2c_phy), GFP_KERNEL); - if (!phy) { - r = -ENOMEM; - goto probe_exit; - } + if (!phy) + return -ENOMEM; phy->i2c_dev = client; i2c_set_clientdata(client, phy); @@ -298,7 +295,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); if (r < 0) - goto probe_exit; + return r; r = request_threaded_irq(client->irq, NULL, nxp_nci_i2c_irq_thread_fn, @@ -307,7 +304,6 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, if (r < 0) nfc_err(&client->dev, "Unable to register IRQ handler\n"); -probe_exit: return r; } -- GitLab From 52c2ea049142c75166456fed055883e22d6ba983 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:08 +0300 Subject: [PATCH 1048/7155] NFC: nxp-nci: Constify acpi_device_id The content of acpi_device_id is not supposed to change at runtime. All functions working with acpi_device_id provided by work with const acpi_device_id. So mark the non-const structs as const. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index bec9b1ea78e2..4e71962dc557 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -330,7 +330,7 @@ static const struct of_device_id of_nxp_nci_i2c_match[] = { MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match); #ifdef CONFIG_ACPI -static struct acpi_device_id acpi_id[] = { +static const struct acpi_device_id acpi_id[] = { { "NXP1001" }, { "NXP7471" }, { }, -- GitLab From da05208a0cb62d539470dd7f951f06cf0092e322 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:09 +0300 Subject: [PATCH 1049/7155] NFC: nxp-nci: Drop of_match_ptr() use There is no need to guard OF device ID table with of_match_ptr(). Otherwise we would get a defined but not used data. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 4e71962dc557..f2c8a560e265 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -342,7 +342,7 @@ static struct i2c_driver nxp_nci_i2c_driver = { .driver = { .name = NXP_NCI_I2C_DRIVER_NAME, .acpi_match_table = ACPI_PTR(acpi_id), - .of_match_table = of_match_ptr(of_nxp_nci_i2c_match), + .of_match_table = of_nxp_nci_i2c_match, }, .probe = nxp_nci_i2c_probe, .id_table = nxp_nci_i2c_id_table, -- GitLab From 41bd9cee8a68b61743e096ac92a82de1c88f96be Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:10 +0300 Subject: [PATCH 1050/7155] NFC: nxp-nci: Drop comma in terminator lines There is no need to have a comma after terminator entry in the arrays of IDs. This may prevent the misguided addition behind the terminator without compiler notice. Drop the comma in terminator lines for good. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index f2c8a560e265..59b0a02a813d 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table); static const struct of_device_id of_nxp_nci_i2c_match[] = { { .compatible = "nxp,nxp-nci-i2c", }, - {}, + {} }; MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match); @@ -333,7 +333,7 @@ MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match); static const struct acpi_device_id acpi_id[] = { { "NXP1001" }, { "NXP7471" }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, acpi_id); #endif -- GitLab From 3b11dc5712c30cf56b73e9f67a815e7c728c67be Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:11 +0300 Subject: [PATCH 1051/7155] NFC: nxp-nci: Remove unused macro pr_fmt() The macro had never been used. The driver uses mostly the nfc_err(), which, with other macros in the family, is backed by corresponding dev_err(). pr_fmt() is not used for dev_err() macro. Moreover, there is no need to print the module name which is part of the device instance name anyway. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/i2c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 59b0a02a813d..307bd2afbe05 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -12,8 +12,6 @@ * Copyright (C) 2012 Intel Corporation. All rights reserved. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include -- GitLab From 826a99ebd4e24da32984cbe847ccc86d4c9a7437 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 29 Jul 2019 16:35:12 +0300 Subject: [PATCH 1052/7155] NFC: nxp-nci: Remove 'default n' for the core It seems contributors follow the style of Kconfig entries where explicit 'default n' is present. The default 'default' is 'n' already, thus, drop these lines from Kconfig to make it more clear. Signed-off-by: Andy Shevchenko Tested-by: Sedat Dilek Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/nfc/nxp-nci/Kconfig b/drivers/nfc/nxp-nci/Kconfig index 12df2c8cc51d..ed6cbdf0f0b4 100644 --- a/drivers/nfc/nxp-nci/Kconfig +++ b/drivers/nfc/nxp-nci/Kconfig @@ -2,7 +2,6 @@ config NFC_NXP_NCI tristate "NXP-NCI NFC driver" depends on NFC_NCI - default n ---help--- Generic core driver for NXP NCI chips such as the NPC100 or PN7150 families. -- GitLab From 6f713f49b4b845d4c7a99b35e50cab5aed3dbbc0 Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Mon, 29 Jul 2019 16:35:13 +0300 Subject: [PATCH 1053/7155] NFC: nxp-nci: Clarify on supported chips This patch clarifies on the supported NXP NCI chips and families and lists PN547 and PN548 separately which are known as NPC100 respectively NPC300. This helps to find informations and identify drivers on vendor's support websites. For details see the discussion in [1] and [2]. [1] https://marc.info/?t=155774435600001&r=1&w=2 [2] https://patchwork.kernel.org/project/linux-wireless/list/?submitter=33142 Suggested-by: Andy Shevchenko Suggested-by: Oleg Zhurakivskyy Signed-off-by: Sedat Dilek Signed-off-by: Andy Shevchenko Acked-by: Oleg Zhurakivskyy Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/nxp-nci/Kconfig b/drivers/nfc/nxp-nci/Kconfig index ed6cbdf0f0b4..746b91aa74f0 100644 --- a/drivers/nfc/nxp-nci/Kconfig +++ b/drivers/nfc/nxp-nci/Kconfig @@ -3,8 +3,8 @@ config NFC_NXP_NCI tristate "NXP-NCI NFC driver" depends on NFC_NCI ---help--- - Generic core driver for NXP NCI chips such as the NPC100 - or PN7150 families. + Generic core driver for NXP NCI chips such as the NPC100 (PN547), + NPC300 (PN548) or PN7150 families. This is a driver based on the NCI NFC kernel layers and will thus not work with NXP libnfc library. -- GitLab From 8f6920ac0050c3156ce617d78a188dd1f40be93c Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Mon, 29 Jul 2019 16:35:14 +0300 Subject: [PATCH 1054/7155] NFC: nxp-nci: Fix recommendation for NFC_NXP_NCI_I2C Kconfig This is a simple cleanup to the Kconfig help text as discussed in [1]. [1] https://marc.info/?t=155774435600001&r=1&w=2 Suggested-by: Andy Shevchenko Suggested-by: Oleg Zhurakivskyy Signed-off-by: Sedat Dilek Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- drivers/nfc/nxp-nci/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nfc/nxp-nci/Kconfig b/drivers/nfc/nxp-nci/Kconfig index 746b91aa74f0..e1f71deab6fc 100644 --- a/drivers/nfc/nxp-nci/Kconfig +++ b/drivers/nfc/nxp-nci/Kconfig @@ -22,4 +22,4 @@ config NFC_NXP_NCI_I2C To compile this driver as a module, choose m here. The module will be called nxp_nci_i2c. - Say Y if unsure. + Say N if unsure. -- GitLab From efc598e6c8a93491868ef7dc7c6fd28508898af2 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Tue, 11 Jun 2019 11:16:56 +0200 Subject: [PATCH 1055/7155] s390/zcrypt: move cca misc functions to new code file Rework of the pkey code. Moved all the cca generic code away from pkey_api.c into a new file zcrypt_ccamisc.c. This new file is now part of the zcrypt device driver and exports a bunch of cca functions to pkey and may be called from other kernel modules as well. The pkey ioctl API is unchanged. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/Makefile | 2 +- drivers/s390/crypto/pkey_api.c | 967 +-------------------------- drivers/s390/crypto/zcrypt_api.c | 2 + drivers/s390/crypto/zcrypt_ccamisc.c | 901 +++++++++++++++++++++++++ drivers/s390/crypto/zcrypt_ccamisc.h | 95 +++ 5 files changed, 1036 insertions(+), 931 deletions(-) create mode 100644 drivers/s390/crypto/zcrypt_ccamisc.c create mode 100644 drivers/s390/crypto/zcrypt_ccamisc.h diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index 6ccd93d0b1cb..52aa95c8af4b 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile @@ -7,7 +7,7 @@ ap-objs := ap_bus.o ap_card.o ap_queue.o obj-$(subst m,y,$(CONFIG_ZCRYPT)) += ap.o # zcrypt_api.o and zcrypt_msgtype*.o depend on ap.o zcrypt-objs := zcrypt_api.o zcrypt_card.o zcrypt_queue.o -zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o +zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o zcrypt_ccamisc.o obj-$(CONFIG_ZCRYPT) += zcrypt.o # adapter drivers depend on ap.o and zcrypt.o obj-$(CONFIG_ZCRYPT) += zcrypt_cex2c.o zcrypt_cex2a.o zcrypt_cex4.o diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 7f418d2d8cdf..9f7c26b6ca04 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -24,17 +24,12 @@ #include #include "zcrypt_api.h" +#include "zcrypt_ccamisc.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key interface"); -/* Size of parameter block used for all cca requests/replies */ -#define PARMBSIZE 512 - -/* Size of vardata block used for some of the cca requests/replies */ -#define VARDATASIZE 4096 - /* mask of available pckmo subfunctions, fetched once at module init */ static cpacf_mask_t pckmo_functions; @@ -62,40 +57,6 @@ static void __exit pkey_debug_exit(void) debug_unregister(debug_info); } -/* Key token types */ -#define TOKTYPE_NON_CCA 0x00 /* Non-CCA key token */ -#define TOKTYPE_CCA_INTERNAL 0x01 /* CCA internal key token */ - -/* For TOKTYPE_NON_CCA: */ -#define TOKVER_PROTECTED_KEY 0x01 /* Protected key token */ - -/* For TOKTYPE_CCA_INTERNAL: */ -#define TOKVER_CCA_AES 0x04 /* CCA AES key token */ - -/* header part of a key token */ -struct keytoken_header { - u8 type; /* one of the TOKTYPE values */ - u8 res0[3]; - u8 version; /* one of the TOKVER values */ - u8 res1[3]; -} __packed; - -/* inside view of a secure key token (only type 0x01 version 0x04) */ -struct secaeskeytoken { - u8 type; /* 0x01 for internal key token */ - u8 res0[3]; - u8 version; /* should be 0x04 */ - u8 res1[1]; - u8 flag; /* key flags */ - u8 res2[1]; - u64 mkvp; /* master key verification pattern */ - u8 key[32]; /* key value (encrypted) */ - u8 cv[8]; /* control vector */ - u16 bitsize; /* key bit size */ - u16 keysize; /* key byte size */ - u8 tvv[4]; /* token validation value */ -} __packed; - /* inside view of a protected key token (only type 0x00 version 0x01) */ struct protaeskeytoken { u8 type; /* 0x00 for PAES specific key tokens */ @@ -107,552 +68,6 @@ struct protaeskeytoken { u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ } __packed; -/* - * Simple check if the token is a valid CCA secure AES key - * token. If keybitsize is given, the bitsize of the key is - * also checked. Returns 0 on success or errno value on failure. - */ -static int check_secaeskeytoken(const u8 *token, int keybitsize) -{ - struct secaeskeytoken *t = (struct secaeskeytoken *) token; - - if (t->type != TOKTYPE_CCA_INTERNAL) { - DEBUG_ERR( - "%s secure token check failed, type mismatch 0x%02x != 0x%02x\n", - __func__, (int) t->type, TOKTYPE_CCA_INTERNAL); - return -EINVAL; - } - if (t->version != TOKVER_CCA_AES) { - DEBUG_ERR( - "%s secure token check failed, version mismatch 0x%02x != 0x%02x\n", - __func__, (int) t->version, TOKVER_CCA_AES); - return -EINVAL; - } - if (keybitsize > 0 && t->bitsize != keybitsize) { - DEBUG_ERR( - "%s secure token check failed, bitsize mismatch %d != %d\n", - __func__, (int) t->bitsize, keybitsize); - return -EINVAL; - } - - return 0; -} - -/* - * Allocate consecutive memory for request CPRB, request param - * block, reply CPRB and reply param block and fill in values - * for the common fields. Returns 0 on success or errno value - * on failure. - */ -static int alloc_and_prep_cprbmem(size_t paramblen, - u8 **pcprbmem, - struct CPRBX **preqCPRB, - struct CPRBX **prepCPRB) -{ - u8 *cprbmem; - size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; - struct CPRBX *preqcblk, *prepcblk; - - /* - * allocate consecutive memory for request CPRB, request param - * block, reply CPRB and reply param block - */ - cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL); - if (!cprbmem) - return -ENOMEM; - - preqcblk = (struct CPRBX *) cprbmem; - prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); - - /* fill request cprb struct */ - preqcblk->cprb_len = sizeof(struct CPRBX); - preqcblk->cprb_ver_id = 0x02; - memcpy(preqcblk->func_id, "T2", 2); - preqcblk->rpl_msgbl = cprbplusparamblen; - if (paramblen) { - preqcblk->req_parmb = - ((u8 *) preqcblk) + sizeof(struct CPRBX); - preqcblk->rpl_parmb = - ((u8 *) prepcblk) + sizeof(struct CPRBX); - } - - *pcprbmem = cprbmem; - *preqCPRB = preqcblk; - *prepCPRB = prepcblk; - - return 0; -} - -/* - * Free the cprb memory allocated with the function above. - * If the scrub value is not zero, the memory is filled - * with zeros before freeing (useful if there was some - * clear key material in there). - */ -static void free_cprbmem(void *mem, size_t paramblen, int scrub) -{ - if (scrub) - memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); - kfree(mem); -} - -/* - * Helper function to prepare the xcrb struct - */ -static inline void prep_xcrb(struct ica_xcRB *pxcrb, - u16 cardnr, - struct CPRBX *preqcblk, - struct CPRBX *prepcblk) -{ - memset(pxcrb, 0, sizeof(*pxcrb)); - pxcrb->agent_ID = 0x4341; /* 'CA' */ - pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); - pxcrb->request_control_blk_length = - preqcblk->cprb_len + preqcblk->req_parml; - pxcrb->request_control_blk_addr = (void __user *) preqcblk; - pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; - pxcrb->reply_control_blk_addr = (void __user *) prepcblk; -} - -/* - * Helper function which calls zcrypt_send_cprb with - * memory management segment adjusted to kernel space - * so that the copy_from_user called within this - * function do in fact copy from kernel space. - */ -static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) -{ - int rc; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - rc = zcrypt_send_cprb(xcrb); - set_fs(old_fs); - - return rc; -} - -/* - * Generate (random) AES secure key. - */ -int pkey_genseckey(u16 cardnr, u16 domain, - u32 keytype, struct pkey_seckey *seckey) -{ - int i, rc, keysize; - int seckeysize; - u8 *mem; - struct CPRBX *preqcblk, *prepcblk; - struct ica_xcRB xcrb; - struct kgreqparm { - u8 subfunc_code[2]; - u16 rule_array_len; - struct lv1 { - u16 len; - char key_form[8]; - char key_length[8]; - char key_type1[8]; - char key_type2[8]; - } lv1; - struct lv2 { - u16 len; - struct keyid { - u16 len; - u16 attr; - u8 data[SECKEYBLOBSIZE]; - } keyid[6]; - } lv2; - } *preqparm; - struct kgrepparm { - u8 subfunc_code[2]; - u16 rule_array_len; - struct lv3 { - u16 len; - u16 keyblocklen; - struct { - u16 toklen; - u16 tokattr; - u8 tok[0]; - /* ... some more data ... */ - } keyblock; - } lv3; - } *prepparm; - - /* get already prepared memory for 2 cprbs with param block each */ - rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); - if (rc) - return rc; - - /* fill request cprb struct */ - preqcblk->domain = domain; - - /* fill request cprb param block with KG request */ - preqparm = (struct kgreqparm *) preqcblk->req_parmb; - memcpy(preqparm->subfunc_code, "KG", 2); - preqparm->rule_array_len = sizeof(preqparm->rule_array_len); - preqparm->lv1.len = sizeof(struct lv1); - memcpy(preqparm->lv1.key_form, "OP ", 8); - switch (keytype) { - case PKEY_KEYTYPE_AES_128: - keysize = 16; - memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); - break; - case PKEY_KEYTYPE_AES_192: - keysize = 24; - memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); - break; - case PKEY_KEYTYPE_AES_256: - keysize = 32; - memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); - break; - default: - DEBUG_ERR( - "%s unknown/unsupported keytype %d\n", - __func__, keytype); - rc = -EINVAL; - goto out; - } - memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); - preqparm->lv2.len = sizeof(struct lv2); - for (i = 0; i < 6; i++) { - preqparm->lv2.keyid[i].len = sizeof(struct keyid); - preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); - } - preqcblk->req_parml = sizeof(struct kgreqparm); - - /* fill xcrb struct */ - prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); - - /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ - rc = _zcrypt_send_cprb(&xcrb); - if (rc) { - DEBUG_ERR( - "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", - __func__, (int) cardnr, (int) domain, rc); - goto out; - } - - /* check response returncode and reasoncode */ - if (prepcblk->ccp_rtcode != 0) { - DEBUG_ERR( - "%s secure key generate failure, card response %d/%d\n", - __func__, - (int) prepcblk->ccp_rtcode, - (int) prepcblk->ccp_rscode); - rc = -EIO; - goto out; - } - - /* process response cprb param block */ - prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); - prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; - - /* check length of the returned secure key token */ - seckeysize = prepparm->lv3.keyblock.toklen - - sizeof(prepparm->lv3.keyblock.toklen) - - sizeof(prepparm->lv3.keyblock.tokattr); - if (seckeysize != SECKEYBLOBSIZE) { - DEBUG_ERR( - "%s secure token size mismatch %d != %d bytes\n", - __func__, seckeysize, SECKEYBLOBSIZE); - rc = -EIO; - goto out; - } - - /* check secure key token */ - rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); - if (rc) { - rc = -EIO; - goto out; - } - - /* copy the generated secure key token */ - memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); - -out: - free_cprbmem(mem, PARMBSIZE, 0); - return rc; -} -EXPORT_SYMBOL(pkey_genseckey); - -/* - * Generate an AES secure key with given key value. - */ -int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_seckey *seckey) -{ - int rc, keysize, seckeysize; - u8 *mem; - struct CPRBX *preqcblk, *prepcblk; - struct ica_xcRB xcrb; - struct cmreqparm { - u8 subfunc_code[2]; - u16 rule_array_len; - char rule_array[8]; - struct lv1 { - u16 len; - u8 clrkey[0]; - } lv1; - struct lv2 { - u16 len; - struct keyid { - u16 len; - u16 attr; - u8 data[SECKEYBLOBSIZE]; - } keyid; - } lv2; - } *preqparm; - struct lv2 *plv2; - struct cmrepparm { - u8 subfunc_code[2]; - u16 rule_array_len; - struct lv3 { - u16 len; - u16 keyblocklen; - struct { - u16 toklen; - u16 tokattr; - u8 tok[0]; - /* ... some more data ... */ - } keyblock; - } lv3; - } *prepparm; - - /* get already prepared memory for 2 cprbs with param block each */ - rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); - if (rc) - return rc; - - /* fill request cprb struct */ - preqcblk->domain = domain; - - /* fill request cprb param block with CM request */ - preqparm = (struct cmreqparm *) preqcblk->req_parmb; - memcpy(preqparm->subfunc_code, "CM", 2); - memcpy(preqparm->rule_array, "AES ", 8); - preqparm->rule_array_len = - sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); - switch (keytype) { - case PKEY_KEYTYPE_AES_128: - keysize = 16; - break; - case PKEY_KEYTYPE_AES_192: - keysize = 24; - break; - case PKEY_KEYTYPE_AES_256: - keysize = 32; - break; - default: - DEBUG_ERR( - "%s unknown/unsupported keytype %d\n", - __func__, keytype); - rc = -EINVAL; - goto out; - } - preqparm->lv1.len = sizeof(struct lv1) + keysize; - memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); - plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); - plv2->len = sizeof(struct lv2); - plv2->keyid.len = sizeof(struct keyid); - plv2->keyid.attr = 0x30; - preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; - - /* fill xcrb struct */ - prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); - - /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ - rc = _zcrypt_send_cprb(&xcrb); - if (rc) { - DEBUG_ERR( - "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", - __func__, (int) cardnr, (int) domain, rc); - goto out; - } - - /* check response returncode and reasoncode */ - if (prepcblk->ccp_rtcode != 0) { - DEBUG_ERR( - "%s clear key import failure, card response %d/%d\n", - __func__, - (int) prepcblk->ccp_rtcode, - (int) prepcblk->ccp_rscode); - rc = -EIO; - goto out; - } - - /* process response cprb param block */ - prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); - prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; - - /* check length of the returned secure key token */ - seckeysize = prepparm->lv3.keyblock.toklen - - sizeof(prepparm->lv3.keyblock.toklen) - - sizeof(prepparm->lv3.keyblock.tokattr); - if (seckeysize != SECKEYBLOBSIZE) { - DEBUG_ERR( - "%s secure token size mismatch %d != %d bytes\n", - __func__, seckeysize, SECKEYBLOBSIZE); - rc = -EIO; - goto out; - } - - /* check secure key token */ - rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); - if (rc) { - rc = -EIO; - goto out; - } - - /* copy the generated secure key token */ - memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); - -out: - free_cprbmem(mem, PARMBSIZE, 1); - return rc; -} -EXPORT_SYMBOL(pkey_clr2seckey); - -/* - * Derive a proteced key from the secure key blob. - */ -int pkey_sec2protkey(u16 cardnr, u16 domain, - const struct pkey_seckey *seckey, - struct pkey_protkey *protkey) -{ - int rc; - u8 *mem; - struct CPRBX *preqcblk, *prepcblk; - struct ica_xcRB xcrb; - struct uskreqparm { - u8 subfunc_code[2]; - u16 rule_array_len; - struct lv1 { - u16 len; - u16 attr_len; - u16 attr_flags; - } lv1; - struct lv2 { - u16 len; - u16 attr_len; - u16 attr_flags; - u8 token[0]; /* cca secure key token */ - } lv2 __packed; - } *preqparm; - struct uskrepparm { - u8 subfunc_code[2]; - u16 rule_array_len; - struct lv3 { - u16 len; - u16 attr_len; - u16 attr_flags; - struct cpacfkeyblock { - u8 version; /* version of this struct */ - u8 flags[2]; - u8 algo; - u8 form; - u8 pad1[3]; - u16 keylen; - u8 key[64]; /* the key (keylen bytes) */ - u16 keyattrlen; - u8 keyattr[32]; - u8 pad2[1]; - u8 vptype; - u8 vp[32]; /* verification pattern */ - } keyblock; - } lv3 __packed; - } *prepparm; - - /* get already prepared memory for 2 cprbs with param block each */ - rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); - if (rc) - return rc; - - /* fill request cprb struct */ - preqcblk->domain = domain; - - /* fill request cprb param block with USK request */ - preqparm = (struct uskreqparm *) preqcblk->req_parmb; - memcpy(preqparm->subfunc_code, "US", 2); - preqparm->rule_array_len = sizeof(preqparm->rule_array_len); - preqparm->lv1.len = sizeof(struct lv1); - preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); - preqparm->lv1.attr_flags = 0x0001; - preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; - preqparm->lv2.attr_len = sizeof(struct lv2) - - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; - preqparm->lv2.attr_flags = 0x0000; - memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); - preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; - - /* fill xcrb struct */ - prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); - - /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ - rc = _zcrypt_send_cprb(&xcrb); - if (rc) { - DEBUG_ERR( - "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", - __func__, (int) cardnr, (int) domain, rc); - goto out; - } - - /* check response returncode and reasoncode */ - if (prepcblk->ccp_rtcode != 0) { - DEBUG_ERR( - "%s unwrap secure key failure, card response %d/%d\n", - __func__, - (int) prepcblk->ccp_rtcode, - (int) prepcblk->ccp_rscode); - rc = -EIO; - goto out; - } - if (prepcblk->ccp_rscode != 0) { - DEBUG_WARN( - "%s unwrap secure key warning, card response %d/%d\n", - __func__, - (int) prepcblk->ccp_rtcode, - (int) prepcblk->ccp_rscode); - } - - /* process response cprb param block */ - prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); - prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; - - /* check the returned keyblock */ - if (prepparm->lv3.keyblock.version != 0x01) { - DEBUG_ERR( - "%s reply param keyblock version mismatch 0x%02x != 0x01\n", - __func__, (int) prepparm->lv3.keyblock.version); - rc = -EIO; - goto out; - } - - /* copy the tanslated protected key */ - switch (prepparm->lv3.keyblock.keylen) { - case 16+32: - protkey->type = PKEY_KEYTYPE_AES_128; - break; - case 24+32: - protkey->type = PKEY_KEYTYPE_AES_192; - break; - case 32+32: - protkey->type = PKEY_KEYTYPE_AES_256; - break; - default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", - __func__, prepparm->lv3.keyblock.keylen); - rc = -EIO; - goto out; - } - protkey->len = prepparm->lv3.keyblock.keylen; - memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); - -out: - free_cprbmem(mem, PARMBSIZE, 0); - return rc; -} -EXPORT_SYMBOL(pkey_sec2protkey); - /* * Create a protected key from a clear key value. */ @@ -709,336 +124,30 @@ int pkey_clr2protkey(u32 keytype, } EXPORT_SYMBOL(pkey_clr2protkey); -/* - * query cryptographic facility from adapter - */ -static int query_crypto_facility(u16 cardnr, u16 domain, - const char *keyword, - u8 *rarray, size_t *rarraylen, - u8 *varray, size_t *varraylen) -{ - int rc; - u16 len; - u8 *mem, *ptr; - struct CPRBX *preqcblk, *prepcblk; - struct ica_xcRB xcrb; - struct fqreqparm { - u8 subfunc_code[2]; - u16 rule_array_len; - char rule_array[8]; - struct lv1 { - u16 len; - u8 data[VARDATASIZE]; - } lv1; - u16 dummylen; - } *preqparm; - size_t parmbsize = sizeof(struct fqreqparm); - struct fqrepparm { - u8 subfunc_code[2]; - u8 lvdata[0]; - } *prepparm; - - /* get already prepared memory for 2 cprbs with param block each */ - rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); - if (rc) - return rc; - - /* fill request cprb struct */ - preqcblk->domain = domain; - - /* fill request cprb param block with FQ request */ - preqparm = (struct fqreqparm *) preqcblk->req_parmb; - memcpy(preqparm->subfunc_code, "FQ", 2); - memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); - preqparm->rule_array_len = - sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); - preqparm->lv1.len = sizeof(preqparm->lv1); - preqparm->dummylen = sizeof(preqparm->dummylen); - preqcblk->req_parml = parmbsize; - - /* fill xcrb struct */ - prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); - - /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ - rc = _zcrypt_send_cprb(&xcrb); - if (rc) { - DEBUG_ERR( - "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", - __func__, (int) cardnr, (int) domain, rc); - goto out; - } - - /* check response returncode and reasoncode */ - if (prepcblk->ccp_rtcode != 0) { - DEBUG_ERR( - "%s unwrap secure key failure, card response %d/%d\n", - __func__, - (int) prepcblk->ccp_rtcode, - (int) prepcblk->ccp_rscode); - rc = -EIO; - goto out; - } - - /* process response cprb param block */ - prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); - prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; - ptr = prepparm->lvdata; - - /* check and possibly copy reply rule array */ - len = *((u16 *) ptr); - if (len > sizeof(u16)) { - ptr += sizeof(u16); - len -= sizeof(u16); - if (rarray && rarraylen && *rarraylen > 0) { - *rarraylen = (len > *rarraylen ? *rarraylen : len); - memcpy(rarray, ptr, *rarraylen); - } - ptr += len; - } - /* check and possible copy reply var array */ - len = *((u16 *) ptr); - if (len > sizeof(u16)) { - ptr += sizeof(u16); - len -= sizeof(u16); - if (varray && varraylen && *varraylen > 0) { - *varraylen = (len > *varraylen ? *varraylen : len); - memcpy(varray, ptr, *varraylen); - } - ptr += len; - } - -out: - free_cprbmem(mem, parmbsize, 0); - return rc; -} - -/* - * Fetch the current and old mkvp values via - * query_crypto_facility from adapter. - */ -static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) -{ - int rc, found = 0; - size_t rlen, vlen; - u8 *rarray, *varray, *pg; - - pg = (u8 *) __get_free_page(GFP_KERNEL); - if (!pg) - return -ENOMEM; - rarray = pg; - varray = pg + PAGE_SIZE/2; - rlen = vlen = PAGE_SIZE/2; - - rc = query_crypto_facility(cardnr, domain, "STATICSA", - rarray, &rlen, varray, &vlen); - if (rc == 0 && rlen > 8*8 && vlen > 184+8) { - if (rarray[8*8] == '2') { - /* current master key state is valid */ - mkvp[0] = *((u64 *)(varray + 184)); - mkvp[1] = *((u64 *)(varray + 172)); - found = 1; - } - } - - free_page((unsigned long) pg); - - return found ? 0 : -ENOENT; -} - -/* struct to hold cached mkvp info for each card/domain */ -struct mkvp_info { - struct list_head list; - u16 cardnr; - u16 domain; - u64 mkvp[2]; -}; - -/* a list with mkvp_info entries */ -static LIST_HEAD(mkvp_list); -static DEFINE_SPINLOCK(mkvp_list_lock); - -static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) -{ - int rc = -ENOENT; - struct mkvp_info *ptr; - - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { - if (ptr->cardnr == cardnr && - ptr->domain == domain) { - memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); - rc = 0; - break; - } - } - spin_unlock_bh(&mkvp_list_lock); - - return rc; -} - -static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) -{ - int found = 0; - struct mkvp_info *ptr; - - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { - if (ptr->cardnr == cardnr && - ptr->domain == domain) { - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); - found = 1; - break; - } - } - if (!found) { - ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); - if (!ptr) { - spin_unlock_bh(&mkvp_list_lock); - return; - } - ptr->cardnr = cardnr; - ptr->domain = domain; - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); - list_add(&ptr->list, &mkvp_list); - } - spin_unlock_bh(&mkvp_list_lock); -} - -static void mkvp_cache_scrub(u16 cardnr, u16 domain) -{ - struct mkvp_info *ptr; - - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { - if (ptr->cardnr == cardnr && - ptr->domain == domain) { - list_del(&ptr->list); - kfree(ptr); - break; - } - } - spin_unlock_bh(&mkvp_list_lock); -} - -static void __exit mkvp_cache_free(void) -{ - struct mkvp_info *ptr, *pnext; - - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { - list_del(&ptr->list); - kfree(ptr); - } - spin_unlock_bh(&mkvp_list_lock); -} - -/* - * Search for a matching crypto card based on the Master Key - * Verification Pattern provided inside a secure key. - */ -int pkey_findcard(const struct pkey_seckey *seckey, - u16 *pcardnr, u16 *pdomain, int verify) -{ - struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; - struct zcrypt_device_status_ext *device_status; - u16 card, dom; - u64 mkvp[2]; - int i, rc, oi = -1; - - /* mkvp must not be zero */ - if (t->mkvp == 0) - return -EINVAL; - - /* fetch status of all crypto cards */ - device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, - sizeof(struct zcrypt_device_status_ext), - GFP_KERNEL); - if (!device_status) - return -ENOMEM; - zcrypt_device_status_mask_ext(device_status); - - /* walk through all crypto cards */ - for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { - card = AP_QID_CARD(device_status[i].qid); - dom = AP_QID_QUEUE(device_status[i].qid); - if (device_status[i].online && - device_status[i].functions & 0x04) { - /* an enabled CCA Coprocessor card */ - /* try cached mkvp */ - if (mkvp_cache_fetch(card, dom, mkvp) == 0 && - t->mkvp == mkvp[0]) { - if (!verify) - break; - /* verify: fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) - break; - } - } - } else { - /* Card is offline and/or not a CCA card. */ - /* del mkvp entry from cache if it exists */ - mkvp_cache_scrub(card, dom); - } - } - if (i >= MAX_ZDEV_ENTRIES_EXT) { - /* nothing found, so this time without cache */ - for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { - if (!(device_status[i].online && - device_status[i].functions & 0x04)) - continue; - card = AP_QID_CARD(device_status[i].qid); - dom = AP_QID_QUEUE(device_status[i].qid); - /* fresh fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) - break; - if (t->mkvp == mkvp[1] && oi < 0) - oi = i; - } - } - if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { - /* old mkvp matched, use this card then */ - card = AP_QID_CARD(device_status[oi].qid); - dom = AP_QID_QUEUE(device_status[oi].qid); - } - } - if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { - if (pcardnr) - *pcardnr = card; - if (pdomain) - *pdomain = dom; - rc = 0; - } else - rc = -ENODEV; - - kfree(device_status); - return rc; -} -EXPORT_SYMBOL(pkey_findcard); - /* * Find card and transform secure key into protected key. */ int pkey_skey2pkey(const struct pkey_seckey *seckey, - struct pkey_protkey *protkey) + struct pkey_protkey *pkey) { u16 cardnr, domain; int rc, verify; /* - * The pkey_sec2protkey call may fail when a card has been + * The cca_sec2protkey call may fail when a card has been * addressed where the master key was changed after last fetch - * of the mkvp into the cache. So first try without verify then - * with verify enabled (thus refreshing the mkvp for each card). + * of the mkvp into the cache. Try 3 times: First witout verify + * then with verify and last round with verify and old master + * key verification pattern match not ignored. */ - for (verify = 0; verify < 2; verify++) { - rc = pkey_findcard(seckey, &cardnr, &domain, verify); - if (rc) + for (verify = 0; verify < 3; verify++) { + rc = cca_findcard(seckey->seckey, &cardnr, &domain, verify); + if (rc < 0) + continue; + if (rc > 0 && verify < 2) continue; - rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); + rc = cca_sec2protkey(cardnr, domain, seckey->seckey, + pkey->protkey, &pkey->len, &pkey->type); if (rc == 0) break; } @@ -1059,11 +168,10 @@ int pkey_verifykey(const struct pkey_seckey *seckey, { struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; u16 cardnr, domain; - u64 mkvp[2]; int rc; /* check the secure key for valid AES secure key */ - rc = check_secaeskeytoken((u8 *) seckey, 0); + rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); if (rc) goto out; if (pattributes) @@ -1072,18 +180,16 @@ int pkey_verifykey(const struct pkey_seckey *seckey, *pkeysize = t->bitsize; /* try to find a card which can handle this key */ - rc = pkey_findcard(seckey, &cardnr, &domain, 1); - if (rc) + rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); + if (rc < 0) goto out; - /* check mkvp for old mkvp match */ - rc = mkvp_cache_fetch(cardnr, domain, mkvp); - if (rc) - goto out; - if (t->mkvp == mkvp[1] && t->mkvp != mkvp[0]) { + if (rc > 0) { + /* key mkvp matches to old master key mkvp */ DEBUG_DBG("%s secure key has old mkvp\n", __func__); if (pattributes) *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; + rc = 0; } if (pcardnr) @@ -1273,9 +379,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kgs, ugs, sizeof(kgs))) return -EFAULT; - rc = pkey_genseckey(kgs.cardnr, kgs.domain, - kgs.keytype, &kgs.seckey); - DEBUG_DBG("%s pkey_genseckey()=%d\n", __func__, rc); + rc = cca_genseckey(kgs.cardnr, kgs.domain, + kgs.keytype, kgs.seckey.seckey); + DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); if (rc) break; if (copy_to_user(ugs, &kgs, sizeof(kgs))) @@ -1288,9 +394,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kcs, ucs, sizeof(kcs))) return -EFAULT; - rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, - &kcs.clrkey, &kcs.seckey); - DEBUG_DBG("%s pkey_clr2seckey()=%d\n", __func__, rc); + rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, + kcs.clrkey.clrkey, kcs.seckey.seckey); + DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); if (rc) break; if (copy_to_user(ucs, &kcs, sizeof(kcs))) @@ -1304,9 +410,10 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; - rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, - &ksp.seckey, &ksp.protkey); - DEBUG_DBG("%s pkey_sec2protkey()=%d\n", __func__, rc); + rc = cca_sec2protkey(ksp.cardnr, ksp.domain, + ksp.seckey.seckey, ksp.protkey.protkey, + NULL, &ksp.protkey.type); + DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); if (rc) break; if (copy_to_user(usp, &ksp, sizeof(ksp))) @@ -1335,10 +442,10 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kfc, ufc, sizeof(kfc))) return -EFAULT; - rc = pkey_findcard(&kfc.seckey, - &kfc.cardnr, &kfc.domain, 1); - DEBUG_DBG("%s pkey_findcard()=%d\n", __func__, rc); - if (rc) + rc = cca_findcard(kfc.seckey.seckey, + &kfc.cardnr, &kfc.domain, 1); + DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); + if (rc < 0) break; if (copy_to_user(ufc, &kfc, sizeof(kfc))) return -EFAULT; @@ -1567,6 +674,7 @@ static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, loff_t off, size_t count) { int rc; + struct pkey_seckey *seckey = (struct pkey_seckey *) buf; if (off != 0 || count < sizeof(struct secaeskeytoken)) return -EINVAL; @@ -1574,13 +682,13 @@ static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, if (count < 2 * sizeof(struct secaeskeytoken)) return -EINVAL; - rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); + rc = cca_genseckey(-1, -1, keytype, seckey->seckey); if (rc) return rc; if (is_xts) { - buf += sizeof(struct pkey_seckey); - rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); + seckey++; + rc = cca_genseckey(-1, -1, keytype, seckey->seckey); if (rc) return rc; @@ -1716,7 +824,6 @@ static int __init pkey_init(void) static void __exit pkey_exit(void) { misc_deregister(&pkey_dev); - mkvp_cache_free(); pkey_debug_exit(); } diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 1058b4b5cc1e..69ac7bf09a57 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -35,6 +35,7 @@ #include "zcrypt_msgtype6.h" #include "zcrypt_msgtype50.h" +#include "zcrypt_ccamisc.h" /* * Module description. @@ -1874,6 +1875,7 @@ void __exit zcrypt_api_exit(void) misc_deregister(&zcrypt_misc_device); zcrypt_msgtype6_exit(); zcrypt_msgtype50_exit(); + zcrypt_ccamisc_exit(); zcrypt_debug_exit(); } diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c new file mode 100644 index 000000000000..3a76c7b5e33c --- /dev/null +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -0,0 +1,901 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright IBM Corp. 2019 + * Author(s): Harald Freudenberger + * Ingo Franzki + * + * Collection of CCA misc functions used by zcrypt and pkey + */ + +#define KMSG_COMPONENT "zcrypt" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include +#include +#include +#include + +#include "ap_bus.h" +#include "zcrypt_api.h" +#include "zcrypt_debug.h" +#include "zcrypt_msgtype6.h" +#include "zcrypt_ccamisc.h" + +#define DEBUG_DBG(...) ZCRYPT_DBF(DBF_DEBUG, ##__VA_ARGS__) +#define DEBUG_INFO(...) ZCRYPT_DBF(DBF_INFO, ##__VA_ARGS__) +#define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__) +#define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__) + +/* Size of parameter block used for all cca requests/replies */ +#define PARMBSIZE 512 + +/* Size of vardata block used for some of the cca requests/replies */ +#define VARDATASIZE 4096 + +/* struct to hold cached mkvp info for each CCA card/domain */ +struct mkvp_info { + struct list_head list; + u16 cardnr; + u16 domain; + u64 mkvp[2]; +}; + +/* a list with mkvp_info entries */ +static LIST_HEAD(mkvp_list); +static DEFINE_SPINLOCK(mkvp_list_lock); + +/* + * Simple check if the token is a valid CCA secure AES key + * token. If keybitsize is given, the bitsize of the key is + * also checked. Returns 0 on success or errno value on failure. + */ +int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, + const u8 *token, int keybitsize) + +{ + struct secaeskeytoken *t = (struct secaeskeytoken *) token; + +#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) + + if (t->type != TOKTYPE_CCA_INTERNAL) { + if (dbg) + DBF("%s token check failed, type 0x%02x != 0x%02x\n", + __func__, (int) t->type, TOKTYPE_CCA_INTERNAL); + return -EINVAL; + } + if (t->version != TOKVER_CCA_AES) { + if (dbg) + DBF("%s token check failed, version 0x%02x != 0x%02x\n", + __func__, (int) t->version, TOKVER_CCA_AES); + return -EINVAL; + } + if (keybitsize > 0 && t->bitsize != keybitsize) { + if (dbg) + DBF("%s token check failed, bitsize %d != %d\n", + __func__, (int) t->bitsize, keybitsize); + return -EINVAL; + } + +#undef DBF + + return 0; +} +EXPORT_SYMBOL(cca_check_secaeskeytoken); + +/* + * Allocate consecutive memory for request CPRB, request param + * block, reply CPRB and reply param block and fill in values + * for the common fields. Returns 0 on success or errno value + * on failure. + */ +static int alloc_and_prep_cprbmem(size_t paramblen, + u8 **pcprbmem, + struct CPRBX **preqCPRB, + struct CPRBX **prepCPRB) +{ + u8 *cprbmem; + size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; + struct CPRBX *preqcblk, *prepcblk; + + /* + * allocate consecutive memory for request CPRB, request param + * block, reply CPRB and reply param block + */ + cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL); + if (!cprbmem) + return -ENOMEM; + + preqcblk = (struct CPRBX *) cprbmem; + prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); + + /* fill request cprb struct */ + preqcblk->cprb_len = sizeof(struct CPRBX); + preqcblk->cprb_ver_id = 0x02; + memcpy(preqcblk->func_id, "T2", 2); + preqcblk->rpl_msgbl = cprbplusparamblen; + if (paramblen) { + preqcblk->req_parmb = + ((u8 *) preqcblk) + sizeof(struct CPRBX); + preqcblk->rpl_parmb = + ((u8 *) prepcblk) + sizeof(struct CPRBX); + } + + *pcprbmem = cprbmem; + *preqCPRB = preqcblk; + *prepCPRB = prepcblk; + + return 0; +} + +/* + * Free the cprb memory allocated with the function above. + * If the scrub value is not zero, the memory is filled + * with zeros before freeing (useful if there was some + * clear key material in there). + */ +static void free_cprbmem(void *mem, size_t paramblen, int scrub) +{ + if (scrub) + memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); + kfree(mem); +} + +/* + * Helper function to prepare the xcrb struct + */ +static inline void prep_xcrb(struct ica_xcRB *pxcrb, + u16 cardnr, + struct CPRBX *preqcblk, + struct CPRBX *prepcblk) +{ + memset(pxcrb, 0, sizeof(*pxcrb)); + pxcrb->agent_ID = 0x4341; /* 'CA' */ + pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); + pxcrb->request_control_blk_length = + preqcblk->cprb_len + preqcblk->req_parml; + pxcrb->request_control_blk_addr = (void *) preqcblk; + pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; + pxcrb->reply_control_blk_addr = (void *) prepcblk; +} + +/* + * Helper function which calls zcrypt_send_cprb with + * memory management segment adjusted to kernel space + * so that the copy_from_user called within this + * function do in fact copy from kernel space. + */ +static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) +{ + int rc; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + rc = zcrypt_send_cprb(xcrb); + set_fs(old_fs); + + return rc; +} + +/* + * Generate (random) CCA AES DATA secure key. + */ +int cca_genseckey(u16 cardnr, u16 domain, + u32 keytype, u8 seckey[SECKEYBLOBSIZE]) +{ + int i, rc, keysize; + int seckeysize; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct kgreqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct lv1 { + u16 len; + char key_form[8]; + char key_length[8]; + char key_type1[8]; + char key_type2[8]; + } lv1; + struct lv2 { + u16 len; + struct keyid { + u16 len; + u16 attr; + u8 data[SECKEYBLOBSIZE]; + } keyid[6]; + } lv2; + } __packed * preqparm; + struct kgrepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct lv3 { + u16 len; + u16 keyblocklen; + struct { + u16 toklen; + u16 tokattr; + u8 tok[0]; + /* ... some more data ... */ + } keyblock; + } lv3; + } __packed * prepparm; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + + /* fill request cprb param block with KG request */ + preqparm = (struct kgreqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "KG", 2); + preqparm->rule_array_len = sizeof(preqparm->rule_array_len); + preqparm->lv1.len = sizeof(struct lv1); + memcpy(preqparm->lv1.key_form, "OP ", 8); + switch (keytype) { + case PKEY_KEYTYPE_AES_128: + keysize = 16; + memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); + break; + case PKEY_KEYTYPE_AES_192: + keysize = 24; + memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); + break; + case PKEY_KEYTYPE_AES_256: + keysize = 32; + memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); + break; + default: + DEBUG_ERR("%s unknown/unsupported keytype %d\n", + __func__, keytype); + rc = -EINVAL; + goto out; + } + memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); + preqparm->lv2.len = sizeof(struct lv2); + for (i = 0; i < 6; i++) { + preqparm->lv2.keyid[i].len = sizeof(struct keyid); + preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); + } + preqcblk->req_parml = sizeof(struct kgreqparm); + + /* fill xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR("%s secure key generate failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; + + /* check length of the returned secure key token */ + seckeysize = prepparm->lv3.keyblock.toklen + - sizeof(prepparm->lv3.keyblock.toklen) + - sizeof(prepparm->lv3.keyblock.tokattr); + if (seckeysize != SECKEYBLOBSIZE) { + DEBUG_ERR("%s secure token size mismatch %d != %d bytes\n", + __func__, seckeysize, SECKEYBLOBSIZE); + rc = -EIO; + goto out; + } + + /* check secure key token */ + rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, + prepparm->lv3.keyblock.tok, 8*keysize); + if (rc) { + rc = -EIO; + goto out; + } + + /* copy the generated secure key token */ + memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); + +out: + free_cprbmem(mem, PARMBSIZE, 0); + return rc; +} +EXPORT_SYMBOL(cca_genseckey); + +/* + * Generate an CCA AES DATA secure key with given key value. + */ +int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, + const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) +{ + int rc, keysize, seckeysize; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct cmreqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + char rule_array[8]; + struct lv1 { + u16 len; + u8 clrkey[0]; + } lv1; + struct lv2 { + u16 len; + struct keyid { + u16 len; + u16 attr; + u8 data[SECKEYBLOBSIZE]; + } keyid; + } lv2; + } __packed * preqparm; + struct lv2 *plv2; + struct cmrepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct lv3 { + u16 len; + u16 keyblocklen; + struct { + u16 toklen; + u16 tokattr; + u8 tok[0]; + /* ... some more data ... */ + } keyblock; + } lv3; + } __packed * prepparm; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + + /* fill request cprb param block with CM request */ + preqparm = (struct cmreqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "CM", 2); + memcpy(preqparm->rule_array, "AES ", 8); + preqparm->rule_array_len = + sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); + switch (keytype) { + case PKEY_KEYTYPE_AES_128: + keysize = 16; + break; + case PKEY_KEYTYPE_AES_192: + keysize = 24; + break; + case PKEY_KEYTYPE_AES_256: + keysize = 32; + break; + default: + DEBUG_ERR("%s unknown/unsupported keytype %d\n", + __func__, keytype); + rc = -EINVAL; + goto out; + } + preqparm->lv1.len = sizeof(struct lv1) + keysize; + memcpy(preqparm->lv1.clrkey, clrkey, keysize); + plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); + plv2->len = sizeof(struct lv2); + plv2->keyid.len = sizeof(struct keyid); + plv2->keyid.attr = 0x30; + preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; + + /* fill xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR("%s clear key import failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; + + /* check length of the returned secure key token */ + seckeysize = prepparm->lv3.keyblock.toklen + - sizeof(prepparm->lv3.keyblock.toklen) + - sizeof(prepparm->lv3.keyblock.tokattr); + if (seckeysize != SECKEYBLOBSIZE) { + DEBUG_ERR("%s secure token size mismatch %d != %d bytes\n", + __func__, seckeysize, SECKEYBLOBSIZE); + rc = -EIO; + goto out; + } + + /* check secure key token */ + rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, + prepparm->lv3.keyblock.tok, 8*keysize); + if (rc) { + rc = -EIO; + goto out; + } + + /* copy the generated secure key token */ + memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); + +out: + free_cprbmem(mem, PARMBSIZE, 1); + return rc; +} +EXPORT_SYMBOL(cca_clr2seckey); + +/* + * Derive proteced key from an CCA AES DATA secure key. + */ +int cca_sec2protkey(u16 cardnr, u16 domain, + const u8 seckey[SECKEYBLOBSIZE], + u8 *protkey, u32 *protkeylen, + u32 *keytype) +{ + int rc; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct uskreqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct lv1 { + u16 len; + u16 attr_len; + u16 attr_flags; + } lv1; + struct lv2 { + u16 len; + u16 attr_len; + u16 attr_flags; + u8 token[0]; /* cca secure key token */ + } lv2; + } __packed * preqparm; + struct uskrepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct lv3 { + u16 len; + u16 attr_len; + u16 attr_flags; + struct cpacfkeyblock { + u8 version; /* version of this struct */ + u8 flags[2]; + u8 algo; + u8 form; + u8 pad1[3]; + u16 len; + u8 key[64]; /* the key (len bytes) */ + u16 keyattrlen; + u8 keyattr[32]; + u8 pad2[1]; + u8 vptype; + u8 vp[32]; /* verification pattern */ + } keyblock; + } lv3; + } __packed * prepparm; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + + /* fill request cprb param block with USK request */ + preqparm = (struct uskreqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "US", 2); + preqparm->rule_array_len = sizeof(preqparm->rule_array_len); + preqparm->lv1.len = sizeof(struct lv1); + preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); + preqparm->lv1.attr_flags = 0x0001; + preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; + preqparm->lv2.attr_len = sizeof(struct lv2) + - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; + preqparm->lv2.attr_flags = 0x0000; + memcpy(preqparm->lv2.token, seckey, SECKEYBLOBSIZE); + preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; + + /* fill xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR("%s unwrap secure key failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + if (prepcblk->ccp_rscode != 0) { + DEBUG_WARN("%s unwrap secure key warning, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; + + /* check the returned keyblock */ + if (prepparm->lv3.keyblock.version != 0x01) { + DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x != 0x01\n", + __func__, (int) prepparm->lv3.keyblock.version); + rc = -EIO; + goto out; + } + + /* copy the tanslated protected key */ + switch (prepparm->lv3.keyblock.len) { + case 16+32: + /* AES 128 protected key */ + if (keytype) + *keytype = PKEY_KEYTYPE_AES_128; + break; + case 24+32: + /* AES 192 protected key */ + if (keytype) + *keytype = PKEY_KEYTYPE_AES_192; + break; + case 32+32: + /* AES 256 protected key */ + if (keytype) + *keytype = PKEY_KEYTYPE_AES_256; + break; + default: + DEBUG_ERR("%s unknown/unsupported keytype %d\n", + __func__, prepparm->lv3.keyblock.len); + rc = -EIO; + goto out; + } + memcpy(protkey, prepparm->lv3.keyblock.key, prepparm->lv3.keyblock.len); + if (protkeylen) + *protkeylen = prepparm->lv3.keyblock.len; + +out: + free_cprbmem(mem, PARMBSIZE, 0); + return rc; +} +EXPORT_SYMBOL(cca_sec2protkey); + +/* + * query cryptographic facility from CCA adapter + */ +int cca_query_crypto_facility(u16 cardnr, u16 domain, + const char *keyword, + u8 *rarray, size_t *rarraylen, + u8 *varray, size_t *varraylen) +{ + int rc; + u16 len; + u8 *mem, *ptr; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct fqreqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + char rule_array[8]; + struct lv1 { + u16 len; + u8 data[VARDATASIZE]; + } lv1; + u16 dummylen; + } __packed * preqparm; + size_t parmbsize = sizeof(struct fqreqparm); + struct fqrepparm { + u8 subfunc_code[2]; + u8 lvdata[0]; + } __packed * prepparm; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + + /* fill request cprb param block with FQ request */ + preqparm = (struct fqreqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "FQ", 2); + memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); + preqparm->rule_array_len = + sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); + preqparm->lv1.len = sizeof(preqparm->lv1); + preqparm->dummylen = sizeof(preqparm->dummylen); + preqcblk->req_parml = parmbsize; + + /* fill xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR("%s unwrap secure key failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; + ptr = prepparm->lvdata; + + /* check and possibly copy reply rule array */ + len = *((u16 *) ptr); + if (len > sizeof(u16)) { + ptr += sizeof(u16); + len -= sizeof(u16); + if (rarray && rarraylen && *rarraylen > 0) { + *rarraylen = (len > *rarraylen ? *rarraylen : len); + memcpy(rarray, ptr, *rarraylen); + } + ptr += len; + } + /* check and possible copy reply var array */ + len = *((u16 *) ptr); + if (len > sizeof(u16)) { + ptr += sizeof(u16); + len -= sizeof(u16); + if (varray && varraylen && *varraylen > 0) { + *varraylen = (len > *varraylen ? *varraylen : len); + memcpy(varray, ptr, *varraylen); + } + ptr += len; + } + +out: + free_cprbmem(mem, parmbsize, 0); + return rc; +} +EXPORT_SYMBOL(cca_query_crypto_facility); + +static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) +{ + int rc = -ENOENT; + struct mkvp_info *ptr; + + spin_lock_bh(&mkvp_list_lock); + list_for_each_entry(ptr, &mkvp_list, list) { + if (ptr->cardnr == cardnr && + ptr->domain == domain) { + memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); + rc = 0; + break; + } + } + spin_unlock_bh(&mkvp_list_lock); + + return rc; +} + +static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) +{ + int found = 0; + struct mkvp_info *ptr; + + spin_lock_bh(&mkvp_list_lock); + list_for_each_entry(ptr, &mkvp_list, list) { + if (ptr->cardnr == cardnr && + ptr->domain == domain) { + memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); + found = 1; + break; + } + } + if (!found) { + ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); + if (!ptr) { + spin_unlock_bh(&mkvp_list_lock); + return; + } + ptr->cardnr = cardnr; + ptr->domain = domain; + memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); + list_add(&ptr->list, &mkvp_list); + } + spin_unlock_bh(&mkvp_list_lock); +} + +static void mkvp_cache_scrub(u16 cardnr, u16 domain) +{ + struct mkvp_info *ptr; + + spin_lock_bh(&mkvp_list_lock); + list_for_each_entry(ptr, &mkvp_list, list) { + if (ptr->cardnr == cardnr && + ptr->domain == domain) { + list_del(&ptr->list); + kfree(ptr); + break; + } + } + spin_unlock_bh(&mkvp_list_lock); +} + +static void __exit mkvp_cache_free(void) +{ + struct mkvp_info *ptr, *pnext; + + spin_lock_bh(&mkvp_list_lock); + list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { + list_del(&ptr->list); + kfree(ptr); + } + spin_unlock_bh(&mkvp_list_lock); +} + +/* + * Fetch the current and old mkvp values via + * query_crypto_facility from adapter. + */ +static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) +{ + int rc, found = 0; + size_t rlen, vlen; + u8 *rarray, *varray, *pg; + + pg = (u8 *) __get_free_page(GFP_KERNEL); + if (!pg) + return -ENOMEM; + rarray = pg; + varray = pg + PAGE_SIZE/2; + rlen = vlen = PAGE_SIZE/2; + + rc = cca_query_crypto_facility(cardnr, domain, "STATICSA", + rarray, &rlen, varray, &vlen); + if (rc == 0 && rlen > 8*8 && vlen > 184+8) { + if (rarray[8*8] == '2') { + /* current master key state is valid */ + mkvp[0] = *((u64 *)(varray + 184)); + mkvp[1] = *((u64 *)(varray + 172)); + found = 1; + } + } + + free_page((unsigned long) pg); + + return found ? 0 : -ENOENT; +} + +/* + * Search for a matching crypto card based on the Master Key + * Verification Pattern provided inside a secure key. + * Returns < 0 on failure, 0 if CURRENT MKVP matches and + * 1 if OLD MKVP matches. + */ +int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) +{ + const struct secaeskeytoken *t = (const struct secaeskeytoken *) seckey; + struct zcrypt_device_status_ext *device_status; + u16 card, dom; + u64 mkvp[2]; + int i, rc, oi = -1; + + /* some simple checks of the given secure key token */ + if (t->type != TOKTYPE_CCA_INTERNAL || + t->version != TOKVER_CCA_AES || + t->mkvp == 0) + return -EINVAL; + + /* fetch status of all crypto cards */ + device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, + sizeof(struct zcrypt_device_status_ext), + GFP_KERNEL); + if (!device_status) + return -ENOMEM; + zcrypt_device_status_mask_ext(device_status); + + /* walk through all crypto cards */ + for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { + card = AP_QID_CARD(device_status[i].qid); + dom = AP_QID_QUEUE(device_status[i].qid); + if (device_status[i].online && + device_status[i].functions & 0x04) { + /* an enabled CCA Coprocessor card */ + /* try cached mkvp */ + if (mkvp_cache_fetch(card, dom, mkvp) == 0 && + t->mkvp == mkvp[0]) { + if (!verify) + break; + /* verify: fetch mkvp from adapter */ + if (fetch_mkvp(card, dom, mkvp) == 0) { + mkvp_cache_update(card, dom, mkvp); + if (t->mkvp == mkvp[0]) + break; + } + } + } else { + /* Card is offline and/or not a CCA card. */ + /* del mkvp entry from cache if it exists */ + mkvp_cache_scrub(card, dom); + } + } + if (i >= MAX_ZDEV_ENTRIES_EXT) { + /* nothing found, so this time without cache */ + for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { + if (!(device_status[i].online && + device_status[i].functions & 0x04)) + continue; + card = AP_QID_CARD(device_status[i].qid); + dom = AP_QID_QUEUE(device_status[i].qid); + /* fresh fetch mkvp from adapter */ + if (fetch_mkvp(card, dom, mkvp) == 0) { + mkvp_cache_update(card, dom, mkvp); + if (t->mkvp == mkvp[0]) + break; + if (t->mkvp == mkvp[1] && oi < 0) + oi = i; + } + } + if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { + /* old mkvp matched, use this card then */ + card = AP_QID_CARD(device_status[oi].qid); + dom = AP_QID_QUEUE(device_status[oi].qid); + } + } + if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { + if (pcardnr) + *pcardnr = card; + if (pdomain) + *pdomain = dom; + rc = (i < MAX_ZDEV_ENTRIES_EXT ? 0 : 1); + } else + rc = -ENODEV; + + kfree(device_status); + return rc; +} +EXPORT_SYMBOL(cca_findcard); + +void __exit zcrypt_ccamisc_exit(void) +{ + mkvp_cache_free(); +} diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h new file mode 100644 index 000000000000..417427462493 --- /dev/null +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright IBM Corp. 2019 + * Author(s): Harald Freudenberger + * Ingo Franzki + * + * Collection of CCA misc functions used by zcrypt and pkey + */ + +#ifndef _ZCRYPT_CCAMISC_H_ +#define _ZCRYPT_CCAMISC_H_ + +#include +#include + +/* Key token types */ +#define TOKTYPE_NON_CCA 0x00 /* Non-CCA key token */ +#define TOKTYPE_CCA_INTERNAL 0x01 /* CCA internal key token */ + +/* For TOKTYPE_NON_CCA: */ +#define TOKVER_PROTECTED_KEY 0x01 /* Protected key token */ + +/* For TOKTYPE_CCA_INTERNAL: */ +#define TOKVER_CCA_AES 0x04 /* CCA AES key token */ + +/* header part of a CCA key token */ +struct keytoken_header { + u8 type; /* one of the TOKTYPE values */ + u8 res0[3]; + u8 version; /* one of the TOKVER values */ + u8 res1[3]; +} __packed; + +/* inside view of a CCA secure key token (only type 0x01 version 0x04) */ +struct secaeskeytoken { + u8 type; /* 0x01 for internal key token */ + u8 res0[3]; + u8 version; /* should be 0x04 */ + u8 res1[1]; + u8 flag; /* key flags */ + u8 res2[1]; + u64 mkvp; /* master key verification pattern */ + u8 key[32]; /* key value (encrypted) */ + u8 cv[8]; /* control vector */ + u16 bitsize; /* key bit size */ + u16 keysize; /* key byte size */ + u8 tvv[4]; /* token validation value */ +} __packed; + +/* + * Simple check if the token is a valid CCA secure AES data key + * token. If keybitsize is given, the bitsize of the key is + * also checked. Returns 0 on success or errno value on failure. + */ +int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, + const u8 *token, int keybitsize); + +/* + * Generate (random) CCA AES DATA secure key. + */ +int cca_genseckey(u16 cardnr, u16 domain, u32 keytype, u8 *seckey); + +/* + * Generate CCA AES DATA secure key with given clear key value. + */ +int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, + const u8 *clrkey, u8 *seckey); + +/* + * Derive proteced key from an CCA AES DATA secure key. + */ +int cca_sec2protkey(u16 cardnr, u16 domain, + const u8 seckey[SECKEYBLOBSIZE], + u8 *protkey, u32 *protkeylen, + u32 *protkeytype); + +/* + * Query cryptographic facility from CCA adapter + */ +int cca_query_crypto_facility(u16 cardnr, u16 domain, + const char *keyword, + u8 *rarray, size_t *rarraylen, + u8 *varray, size_t *varraylen); + +/* + * Search for a matching crypto card based on the Master Key + * Verification Pattern provided inside a secure key. + * Returns < 0 on failure, 0 if CURRENT MKVP matches and + * 1 if OLD MKVP matches. + */ +int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify); + +void zcrypt_ccamisc_exit(void); + +#endif /* _ZCRYPT_CCAMISC_H_ */ -- GitLab From 94bbd34e51bc7809357e24e4011b169d321a8272 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Tue, 11 Jun 2019 14:10:47 +0200 Subject: [PATCH 1056/7155] s390/zcrypt: add base code for cca crypto card info support This patch widens the information held for cca crypto apqns. Currently the current and old master key verification pattern is used by the existing code. Now the new master key registers mkvp, the 8 byte serial number and state info about each master key register is part of the cca info cache. In a next step this information will be used to provide some additional attributes in sysfs for each CCA crypto adapter. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_ccamisc.c | 131 +++++++++++++++------------ 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 3a76c7b5e33c..b1f9332a0298 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -33,17 +33,27 @@ /* Size of vardata block used for some of the cca requests/replies */ #define VARDATASIZE 4096 -/* struct to hold cached mkvp info for each CCA card/domain */ -struct mkvp_info { +/* struct to hold cached info for each CCA card/domain */ +struct cca_info { + char new_mk_state; /* '1' Empty, '2' Partially full, '3' Full */ + char cur_mk_state; /* '1' Invalid, '2' Valid */ + char old_mk_state; /* '1' Invalid, '2' Valid */ + u64 new_mkvp; /* truncated sha256 hash of new master key */ + u64 cur_mkvp; /* truncated sha256 hash of current master key */ + u64 old_mkvp; /* truncated sha256 hash of old master key */ + char serial[9]; +}; + +struct cca_info_list_entry { struct list_head list; u16 cardnr; u16 domain; - u64 mkvp[2]; + struct cca_info info; }; -/* a list with mkvp_info entries */ -static LIST_HEAD(mkvp_list); -static DEFINE_SPINLOCK(mkvp_list_lock); +/* a list with cca_info_list_entry entries */ +static LIST_HEAD(cca_info_list); +static DEFINE_SPINLOCK(cca_info_list_lock); /* * Simple check if the token is a valid CCA secure AES key @@ -697,35 +707,35 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, } EXPORT_SYMBOL(cca_query_crypto_facility); -static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) +static int cca_info_cache_fetch(u16 cardnr, u16 domain, struct cca_info *ci) { int rc = -ENOENT; - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { - if (ptr->cardnr == cardnr && - ptr->domain == domain) { - memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { + if (ptr->cardnr == cardnr && ptr->domain == domain) { + memcpy(ci, &ptr->info, sizeof(*ci)); rc = 0; break; } } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); return rc; } -static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) +static void cca_info_cache_update(u16 cardnr, u16 domain, + const struct cca_info *ci) { int found = 0; - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { if (ptr->cardnr == cardnr && ptr->domain == domain) { - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); + memcpy(&ptr->info, ci, sizeof(*ci)); found = 1; break; } @@ -733,23 +743,23 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) if (!found) { ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); if (!ptr) { - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); return; } ptr->cardnr = cardnr; ptr->domain = domain; - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); - list_add(&ptr->list, &mkvp_list); + memcpy(&ptr->info, ci, sizeof(*ci)); + list_add(&ptr->list, &cca_info_list); } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } -static void mkvp_cache_scrub(u16 cardnr, u16 domain) +static void cca_info_cache_scrub(u16 cardnr, u16 domain) { - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { if (ptr->cardnr == cardnr && ptr->domain == domain) { list_del(&ptr->list); @@ -757,26 +767,25 @@ static void mkvp_cache_scrub(u16 cardnr, u16 domain) break; } } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } static void __exit mkvp_cache_free(void) { - struct mkvp_info *ptr, *pnext; + struct cca_info_list_entry *ptr, *pnext; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry_safe(ptr, pnext, &cca_info_list, list) { list_del(&ptr->list); kfree(ptr); } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } /* - * Fetch the current and old mkvp values via - * query_crypto_facility from adapter. + * Fetch cca_info values via query_crypto_facility from adapter. */ -static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) +static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) { int rc, found = 0; size_t rlen, vlen; @@ -791,13 +800,19 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) rc = cca_query_crypto_facility(cardnr, domain, "STATICSA", rarray, &rlen, varray, &vlen); - if (rc == 0 && rlen > 8*8 && vlen > 184+8) { - if (rarray[8*8] == '2') { - /* current master key state is valid */ - mkvp[0] = *((u64 *)(varray + 184)); - mkvp[1] = *((u64 *)(varray + 172)); - found = 1; - } + if (rc == 0 && rlen >= 10*8 && vlen >= 204) { + memset(ci, 0, sizeof(*ci)); + memcpy(ci->serial, rarray, 8); + ci->new_mk_state = (char) rarray[7*8]; + ci->cur_mk_state = (char) rarray[8*8]; + ci->old_mk_state = (char) rarray[9*8]; + if (ci->old_mk_state == '2') + memcpy(&ci->old_mkvp, varray + 172, 8); + if (ci->cur_mk_state == '2') + memcpy(&ci->cur_mkvp, varray + 184, 8); + if (ci->new_mk_state == '3') + memcpy(&ci->new_mkvp, varray + 196, 8); + found = 1; } free_page((unsigned long) pg); @@ -816,7 +831,7 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) const struct secaeskeytoken *t = (const struct secaeskeytoken *) seckey; struct zcrypt_device_status_ext *device_status; u16 card, dom; - u64 mkvp[2]; + struct cca_info ci; int i, rc, oi = -1; /* some simple checks of the given secure key token */ @@ -839,23 +854,24 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) dom = AP_QID_QUEUE(device_status[i].qid); if (device_status[i].online && device_status[i].functions & 0x04) { - /* an enabled CCA Coprocessor card */ - /* try cached mkvp */ - if (mkvp_cache_fetch(card, dom, mkvp) == 0 && - t->mkvp == mkvp[0]) { + /* enabled CCA card, check current mkvp from cache */ + if (cca_info_cache_fetch(card, dom, &ci) == 0 && + ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) { if (!verify) break; - /* verify: fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) + /* verify: refresh card info */ + if (fetch_cca_info(card, dom, &ci) == 0) { + cca_info_cache_update(card, dom, &ci); + if (ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) break; } } } else { /* Card is offline and/or not a CCA card. */ /* del mkvp entry from cache if it exists */ - mkvp_cache_scrub(card, dom); + cca_info_cache_scrub(card, dom); } } if (i >= MAX_ZDEV_ENTRIES_EXT) { @@ -867,11 +883,14 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) card = AP_QID_CARD(device_status[i].qid); dom = AP_QID_QUEUE(device_status[i].qid); /* fresh fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) + if (fetch_cca_info(card, dom, &ci) == 0) { + cca_info_cache_update(card, dom, &ci); + if (ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) break; - if (t->mkvp == mkvp[1] && oi < 0) + if (ci.old_mk_state == '2' && + ci.old_mkvp == t->mkvp && + oi < 0) oi = i; } } -- GitLab From 7c4e91c0959bf42a86ba4887425fc944d0d28595 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 12 Jun 2019 15:05:34 +0200 Subject: [PATCH 1057/7155] s390/zcrypt: new sysfs attributes serialnr and mkvps This patch extends the sysfs interface with two new attributes for the CEX4, CEX5 and CEX6 crypto cards/queues in coprocessor ('CCA') mode: /sys/devices/ap/cardxx/serialnr /sys/devices/ap/cardxx/xx.yyyy/mkvps The serialnr attribute is card based and shows the 8 character ASCII serial number string which should unique identify the card. The mkvps is queue based and displays 3 lines of information about the new, current and old master key register: AES NEW: AES CUR: AES OLD: with : 'empty' or 'partial' or 'full' : 'valid' or 'invalid' : 'valid' or 'invalid' , , 8 byte hex string with leading 0x MKVP means Master Key Verification Pattern and is a folded hash over the key value. Only the states 'full' and 'valid' result in displaying a useful mkvp, otherwise a mkvp of all bytes zero is shown. If for any reason the FQ fails and the (cached) information is not available, the state '-' will be shown with the mkvp value also '-'. The values shown here are the very same as the cca panel tools displays. As of now only the AES master keys states and verification patterns are shown. A CCA APQN also has similar master key registers for DES, RSA and ECC. So the content of this attribute may get extended. Reading the sysfs attribute automatically triggers an FQ CPRB to be sent to the queue as long as the queue is (soft-) online. For the serialnr attribute the queue with the default domain id is addressed (if available and valid). This is reasonable as it is assumed that this sysfs interface is not performance critical and on the other side a master key change should be visiable as soon as possible. When a queue is (soft-) offline however, the cached values are displayed. If no cached values are available, the serial number string will be empty and the mkvp lines will show state '-' and mkvp value '-'. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_ccamisc.c | 33 +++++---- drivers/s390/crypto/zcrypt_ccamisc.h | 16 ++++ drivers/s390/crypto/zcrypt_cex4.c | 106 ++++++++++++++++++++++++++- 3 files changed, 141 insertions(+), 14 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index b1f9332a0298..9dd31577ce47 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -33,17 +33,6 @@ /* Size of vardata block used for some of the cca requests/replies */ #define VARDATASIZE 4096 -/* struct to hold cached info for each CCA card/domain */ -struct cca_info { - char new_mk_state; /* '1' Empty, '2' Partially full, '3' Full */ - char cur_mk_state; /* '1' Invalid, '2' Valid */ - char old_mk_state; /* '1' Invalid, '2' Valid */ - u64 new_mkvp; /* truncated sha256 hash of new master key */ - u64 cur_mkvp; /* truncated sha256 hash of current master key */ - u64 old_mkvp; /* truncated sha256 hash of old master key */ - char serial[9]; -}; - struct cca_info_list_entry { struct list_head list; u16 cardnr; @@ -164,9 +153,9 @@ static inline void prep_xcrb(struct ica_xcRB *pxcrb, pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); pxcrb->request_control_blk_length = preqcblk->cprb_len + preqcblk->req_parml; - pxcrb->request_control_blk_addr = (void *) preqcblk; + pxcrb->request_control_blk_addr = (void __user *) preqcblk; pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; - pxcrb->reply_control_blk_addr = (void *) prepcblk; + pxcrb->reply_control_blk_addr = (void __user *) prepcblk; } /* @@ -820,6 +809,24 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) return found ? 0 : -ENOENT; } +/* + * Fetch cca information about a CCA queue. + */ +int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify) +{ + int rc; + + rc = cca_info_cache_fetch(card, dom, ci); + if (rc || verify) { + rc = fetch_cca_info(card, dom, ci); + if (rc == 0) + cca_info_cache_update(card, dom, ci); + } + + return rc; +} +EXPORT_SYMBOL(cca_get_info); + /* * Search for a matching crypto card based on the Master Key * Verification Pattern provided inside a secure key. diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index 417427462493..d92fb731602a 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -90,6 +90,22 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, */ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify); +/* struct to hold info for each CCA queue */ +struct cca_info { + char new_mk_state; /* '1' empty, '2' partially full, '3' full */ + char cur_mk_state; /* '1' invalid, '2' valid */ + char old_mk_state; /* '1' invalid, '2' valid */ + u64 new_mkvp; /* truncated sha256 hash of new master key */ + u64 cur_mkvp; /* truncated sha256 hash of current master key */ + u64 old_mkvp; /* truncated sha256 hash of old master key */ + char serial[9]; /* serial number string (8 ascii numbers + 0x00) */ +}; + +/* + * Fetch cca information about an CCA queue. + */ +int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify); + void zcrypt_ccamisc_exit(void); #endif /* _ZCRYPT_CCAMISC_H_ */ diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 582ffa7e0f18..f58d8dec19dc 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -18,6 +18,7 @@ #include "zcrypt_msgtype50.h" #include "zcrypt_error.h" #include "zcrypt_cex4.h" +#include "zcrypt_ccamisc.h" #define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ #define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ @@ -65,6 +66,85 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = { MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids); +/* + * CCA card addditional device attributes + */ +static ssize_t serialnr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cca_info ci; + struct ap_card *ac = to_ap_card(dev); + struct zcrypt_card *zc = ac->private; + + memset(&ci, 0, sizeof(ci)); + + if (ap_domain_index >= 0) + cca_get_info(ac->id, ap_domain_index, &ci, zc->online); + + return snprintf(buf, PAGE_SIZE, "%s\n", ci.serial); +} +static DEVICE_ATTR_RO(serialnr); + +static struct attribute *cca_card_attrs[] = { + &dev_attr_serialnr.attr, + NULL, +}; + +static const struct attribute_group cca_card_attr_group = { + .attrs = cca_card_attrs, +}; + +/* + * CCA queue addditional device attributes + */ +static ssize_t mkvps_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int n = 0; + struct cca_info ci; + struct zcrypt_queue *zq = to_ap_queue(dev)->private; + static const char * const cao_state[] = { "invalid", "valid" }; + static const char * const new_state[] = { "empty", "partial", "full" }; + + memset(&ci, 0, sizeof(ci)); + + cca_get_info(AP_QID_CARD(zq->queue->qid), + AP_QID_QUEUE(zq->queue->qid), + &ci, zq->online); + + if (ci.new_mk_state >= '1' && ci.new_mk_state <= '3') + n = snprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n", + new_state[ci.new_mk_state - '1'], ci.new_mkvp); + else + n = snprintf(buf, PAGE_SIZE, "AES NEW: - -\n"); + + if (ci.cur_mk_state >= '1' && ci.cur_mk_state <= '2') + n += snprintf(buf + n, PAGE_SIZE - n, "AES CUR: %s 0x%016llx\n", + cao_state[ci.cur_mk_state - '1'], ci.cur_mkvp); + else + n += snprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n"); + + if (ci.old_mk_state >= '1' && ci.old_mk_state <= '2') + n += snprintf(buf + n, PAGE_SIZE - n, "AES OLD: %s 0x%016llx\n", + cao_state[ci.old_mk_state - '1'], ci.old_mkvp); + else + n += snprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n"); + + return n; +} +static DEVICE_ATTR_RO(mkvps); + +static struct attribute *cca_queue_attrs[] = { + &dev_attr_mkvps.attr, + NULL, +}; + +static const struct attribute_group cca_queue_attr_group = { + .attrs = cca_queue_attrs, +}; + /** * Probe function for CEX4/CEX5/CEX6 card device. It always * accepts the AP device since the bus_match already checked @@ -194,8 +274,17 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) if (rc) { ac->private = NULL; zcrypt_card_free(zc); + goto out; } + if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { + rc = sysfs_create_group(&ap_dev->device.kobj, + &cca_card_attr_group); + if (rc) + zcrypt_card_unregister(zc); + } + +out: return rc; } @@ -205,8 +294,11 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) */ static void zcrypt_cex4_card_remove(struct ap_device *ap_dev) { - struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private; + struct ap_card *ac = to_ap_card(&ap_dev->device); + struct zcrypt_card *zc = ac->private; + if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) + sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_group); if (zc) zcrypt_card_unregister(zc); } @@ -251,6 +343,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) } else { return -ENODEV; } + zq->queue = aq; zq->online = 1; atomic_set(&zq->load, 0); @@ -261,8 +354,17 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) if (rc) { aq->private = NULL; zcrypt_queue_free(zq); + goto out; + } + + if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { + rc = sysfs_create_group(&ap_dev->device.kobj, + &cca_queue_attr_group); + if (rc) + zcrypt_queue_unregister(zq); } +out: return rc; } @@ -275,6 +377,8 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev) struct ap_queue *aq = to_ap_queue(&ap_dev->device); struct zcrypt_queue *zq = aq->private; + if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) + sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_group); if (zq) zcrypt_queue_unregister(zq); } -- GitLab From 56f8af5e9d38f120cba2c2adb0786fa2dbc901a4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:06 +0100 Subject: [PATCH 1058/7155] iommu: Pass struct iommu_iotlb_gather to ->unmap() and ->iotlb_sync() To allow IOMMU drivers to batch up TLB flushing operations and postpone them until ->iotlb_sync() is called, extend the prototypes for the ->unmap() and ->iotlb_sync() IOMMU ops callbacks to take a pointer to the current iommu_iotlb_gather structure. All affected IOMMU drivers are updated, but there should be no functional change since the extra parameter is ignored for now. Signed-off-by: Will Deacon --- drivers/iommu/amd_iommu.c | 11 +++++++++-- drivers/iommu/arm-smmu-v3.c | 7 ++++--- drivers/iommu/arm-smmu.c | 5 +++-- drivers/iommu/exynos-iommu.c | 3 ++- drivers/iommu/intel-iommu.c | 3 ++- drivers/iommu/iommu.c | 2 +- drivers/iommu/ipmmu-vmsa.c | 12 +++++++++--- drivers/iommu/msm_iommu.c | 2 +- drivers/iommu/mtk_iommu.c | 13 ++++++++++--- drivers/iommu/mtk_iommu_v1.c | 3 ++- drivers/iommu/omap-iommu.c | 2 +- drivers/iommu/qcom_iommu.c | 12 +++++++++--- drivers/iommu/rockchip-iommu.c | 2 +- drivers/iommu/s390-iommu.c | 3 ++- drivers/iommu/tegra-gart.c | 12 +++++++++--- drivers/iommu/tegra-smmu.c | 2 +- drivers/iommu/virtio-iommu.c | 5 +++-- include/linux/iommu.h | 7 ++++--- 18 files changed, 73 insertions(+), 33 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index f93b148cf55e..29eeea914660 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3055,7 +3055,8 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova, } static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, - size_t page_size) + size_t page_size, + struct iommu_iotlb_gather *gather) { struct protection_domain *domain = to_pdomain(dom); size_t unmap_size; @@ -3196,6 +3197,12 @@ static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain) domain_flush_complete(dom); } +static void amd_iommu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) +{ + amd_iommu_flush_iotlb_all(domain); +} + const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, @@ -3214,7 +3221,7 @@ const struct iommu_ops amd_iommu_ops = { .is_attach_deferred = amd_iommu_is_attach_deferred, .pgsize_bitmap = AMD_IOMMU_PGSIZES, .flush_iotlb_all = amd_iommu_flush_iotlb_all, - .iotlb_sync = amd_iommu_flush_iotlb_all, + .iotlb_sync = amd_iommu_iotlb_sync, }; /***************************************************************************** diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 7e137e1e28f1..80753b8ca054 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1985,8 +1985,8 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, return ops->map(ops, iova, paddr, size, prot); } -static size_t -arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) +static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, + size_t size, struct iommu_iotlb_gather *gather) { int ret; struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); @@ -2010,7 +2010,8 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) arm_smmu_tlb_inv_context(smmu_domain); } -static void arm_smmu_iotlb_sync(struct iommu_domain *domain) +static void arm_smmu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) { struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index dc08db347ef3..e535ae2a9e65 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1301,7 +1301,7 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, } static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; @@ -1329,7 +1329,8 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) } } -static void arm_smmu_iotlb_sync(struct iommu_domain *domain) +static void arm_smmu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index b0c1e5f9daae..cf5af34cb681 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1130,7 +1130,8 @@ static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *domain } static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain, - unsigned long l_iova, size_t size) + unsigned long l_iova, size_t size, + struct iommu_iotlb_gather *gather) { struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index ac4172c02244..b9fb8d6ddc6e 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -5147,7 +5147,8 @@ static int intel_iommu_map(struct iommu_domain *domain, } static size_t intel_iommu_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size) + unsigned long iova, size_t size, + struct iommu_iotlb_gather *gather) { struct dmar_domain *dmar_domain = to_dmar_domain(domain); struct page *freelist = NULL; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d67222fdfe44..70bfbcc09248 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1899,7 +1899,7 @@ static size_t __iommu_unmap(struct iommu_domain *domain, while (unmapped < size) { size_t pgsize = iommu_pgsize(domain, iova, size - unmapped); - unmapped_page = ops->unmap(domain, iova, pgsize); + unmapped_page = ops->unmap(domain, iova, pgsize, iotlb_gather); if (!unmapped_page) break; diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 2c14a2c65b22..a9332b893ce2 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -733,14 +733,14 @@ static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova, } static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain); return domain->iop->unmap(domain->iop, iova, size); } -static void ipmmu_iotlb_sync(struct iommu_domain *io_domain) +static void ipmmu_flush_iotlb_all(struct iommu_domain *io_domain) { struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain); @@ -748,6 +748,12 @@ static void ipmmu_iotlb_sync(struct iommu_domain *io_domain) ipmmu_tlb_flush_all(domain); } +static void ipmmu_iotlb_sync(struct iommu_domain *io_domain, + struct iommu_iotlb_gather *gather) +{ + ipmmu_flush_iotlb_all(io_domain); +} + static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain, dma_addr_t iova) { @@ -957,7 +963,7 @@ static const struct iommu_ops ipmmu_ops = { .detach_dev = ipmmu_detach_device, .map = ipmmu_map, .unmap = ipmmu_unmap, - .flush_iotlb_all = ipmmu_iotlb_sync, + .flush_iotlb_all = ipmmu_flush_iotlb_all, .iotlb_sync = ipmmu_iotlb_sync, .iova_to_phys = ipmmu_iova_to_phys, .add_device = ipmmu_add_device, diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 8b602384a385..681ab3d3376d 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -509,7 +509,7 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova, } static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t len) + size_t len, struct iommu_iotlb_gather *gather) { struct msm_priv *priv = to_msm_priv(domain); unsigned long flags; diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index fed77658d67e..c870f1674903 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -371,7 +371,8 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, } static size_t mtk_iommu_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size) + unsigned long iova, size_t size, + struct iommu_iotlb_gather *gather) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); unsigned long flags; @@ -384,7 +385,13 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain, return unmapsz; } -static void mtk_iommu_iotlb_sync(struct iommu_domain *domain) +static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain) +{ + mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data()); +} + +static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) { mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data()); } @@ -490,7 +497,7 @@ static const struct iommu_ops mtk_iommu_ops = { .detach_dev = mtk_iommu_detach_device, .map = mtk_iommu_map, .unmap = mtk_iommu_unmap, - .flush_iotlb_all = mtk_iommu_iotlb_sync, + .flush_iotlb_all = mtk_iommu_flush_iotlb_all, .iotlb_sync = mtk_iommu_iotlb_sync, .iova_to_phys = mtk_iommu_iova_to_phys, .add_device = mtk_iommu_add_device, diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index abeeac488372..7b92ddd5d9fd 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -324,7 +324,8 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, } static size_t mtk_iommu_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size) + unsigned long iova, size_t size, + struct iommu_iotlb_gather *gather) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); unsigned long flags; diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index dfb961d8c21b..8039bc5ee425 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1149,7 +1149,7 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, } static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct omap_iommu_domain *omap_domain = to_omap_domain(domain); struct device *dev = omap_domain->dev; diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index fd9d9f4da735..a7432991fa04 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -417,7 +417,7 @@ static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova, } static size_t qcom_iommu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { size_t ret; unsigned long flags; @@ -441,7 +441,7 @@ static size_t qcom_iommu_unmap(struct iommu_domain *domain, unsigned long iova, return ret; } -static void qcom_iommu_iotlb_sync(struct iommu_domain *domain) +static void qcom_iommu_flush_iotlb_all(struct iommu_domain *domain) { struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain); struct io_pgtable *pgtable = container_of(qcom_domain->pgtbl_ops, @@ -454,6 +454,12 @@ static void qcom_iommu_iotlb_sync(struct iommu_domain *domain) pm_runtime_put_sync(qcom_domain->iommu->dev); } +static void qcom_iommu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) +{ + qcom_iommu_flush_iotlb_all(domain); +} + static phys_addr_t qcom_iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) { @@ -581,7 +587,7 @@ static const struct iommu_ops qcom_iommu_ops = { .detach_dev = qcom_iommu_detach_dev, .map = qcom_iommu_map, .unmap = qcom_iommu_unmap, - .flush_iotlb_all = qcom_iommu_iotlb_sync, + .flush_iotlb_all = qcom_iommu_flush_iotlb_all, .iotlb_sync = qcom_iommu_iotlb_sync, .iova_to_phys = qcom_iommu_iova_to_phys, .add_device = qcom_iommu_add_device, diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index dc26d74d79c2..26290f310f90 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -794,7 +794,7 @@ static int rk_iommu_map(struct iommu_domain *domain, unsigned long _iova, } static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct rk_iommu_domain *rk_domain = to_rk_domain(domain); unsigned long flags; diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c index 22d4db302c1c..3b0b18e23187 100644 --- a/drivers/iommu/s390-iommu.c +++ b/drivers/iommu/s390-iommu.c @@ -314,7 +314,8 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain, } static size_t s390_iommu_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size) + unsigned long iova, size_t size, + struct iommu_iotlb_gather *gather) { struct s390_domain *s390_domain = to_s390_domain(domain); int flags = ZPCI_PTE_INVALID; diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 6d40bc1b38bf..3924f7c05544 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -207,7 +207,7 @@ static inline int __gart_iommu_unmap(struct gart_device *gart, } static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t bytes) + size_t bytes, struct iommu_iotlb_gather *gather) { struct gart_device *gart = gart_handle; int err; @@ -273,11 +273,17 @@ static int gart_iommu_of_xlate(struct device *dev, return 0; } -static void gart_iommu_sync(struct iommu_domain *domain) +static void gart_iommu_sync_map(struct iommu_domain *domain) { FLUSH_GART_REGS(gart_handle); } +static void gart_iommu_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) +{ + gart_iommu_sync_map(domain); +} + static const struct iommu_ops gart_iommu_ops = { .capable = gart_iommu_capable, .domain_alloc = gart_iommu_domain_alloc, @@ -292,7 +298,7 @@ static const struct iommu_ops gart_iommu_ops = { .iova_to_phys = gart_iommu_iova_to_phys, .pgsize_bitmap = GART_IOMMU_PGSIZES, .of_xlate = gart_iommu_of_xlate, - .iotlb_sync_map = gart_iommu_sync, + .iotlb_sync_map = gart_iommu_sync_map, .iotlb_sync = gart_iommu_sync, }; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c4a652b227f8..7293fc3f796d 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -680,7 +680,7 @@ static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova, } static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct tegra_smmu_as *as = to_smmu_as(domain); dma_addr_t pte_dma; diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index 433f4d2ee956..5f9f91a4d7f3 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -742,7 +742,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova, } static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { int ret = 0; size_t unmapped; @@ -788,7 +788,8 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain, return paddr; } -static void viommu_iotlb_sync(struct iommu_domain *domain) +static void viommu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) { struct viommu_domain *vdomain = to_viommu_domain(domain); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index ad41aee55bc6..64ebaff33455 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -258,10 +258,11 @@ struct iommu_ops { int (*map)(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, - size_t size); + size_t size, struct iommu_iotlb_gather *iotlb_gather); void (*flush_iotlb_all)(struct iommu_domain *domain); void (*iotlb_sync_map)(struct iommu_domain *domain); - void (*iotlb_sync)(struct iommu_domain *domain); + void (*iotlb_sync)(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); @@ -502,7 +503,7 @@ static inline void iommu_tlb_sync(struct iommu_domain *domain, struct iommu_iotlb_gather *iotlb_gather) { if (domain->ops->iotlb_sync) - domain->ops->iotlb_sync(domain); + domain->ops->iotlb_sync(domain, iotlb_gather); iommu_iotlb_gather_init(iotlb_gather); } -- GitLab From 3445545b2248300319b6965208e77140c960c3fd Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:16 +0100 Subject: [PATCH 1059/7155] iommu/io-pgtable: Introduce tlb_flush_walk() and tlb_flush_leaf() In preparation for deferring TLB flushes to iommu_tlb_sync(), introduce two new synchronous invalidation helpers to the io-pgtable API, which allow the unmap() code to force invalidation in cases where it cannot be deferred (e.g. when replacing a table with a block or when TLBI_ON_MAP is set). Signed-off-by: Will Deacon --- include/linux/io-pgtable.h | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 6292ea15d674..27275575b305 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -19,17 +19,31 @@ enum io_pgtable_fmt { /** * struct iommu_flush_ops - IOMMU callbacks for TLB and page table management. * - * @tlb_flush_all: Synchronously invalidate the entire TLB context. - * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range. - * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and - * any corresponding page table updates are visible to the - * IOMMU. + * @tlb_flush_all: Synchronously invalidate the entire TLB context. + * @tlb_flush_walk: Synchronously invalidate all intermediate TLB state + * (sometimes referred to as the "walk cache") for a virtual + * address range. + * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual + * address range. + * @tlb_add_flush: Optional callback to queue up leaf TLB invalidation for a + * virtual address range. This function exists purely as an + * optimisation for IOMMUs that cannot batch TLB invalidation + * operations efficiently and are therefore better suited to + * issuing them early rather than deferring them until + * iommu_tlb_sync(). + * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and + * any corresponding page table updates are visible to the + * IOMMU. * * Note that these can all be called in atomic context and must therefore * not block. */ struct iommu_flush_ops { void (*tlb_flush_all)(void *cookie); + void (*tlb_flush_walk)(unsigned long iova, size_t size, size_t granule, + void *cookie); + void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule, + void *cookie); void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie); void (*tlb_sync)(void *cookie); -- GitLab From 05aed9412b0bd0d9a985d94010c42ff0a5c6cc29 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:25 +0100 Subject: [PATCH 1060/7155] iommu/io-pgtable: Hook up ->tlb_flush_walk() and ->tlb_flush_leaf() in drivers Hook up ->tlb_flush_walk() and ->tlb_flush_leaf() in drivers using the io-pgtable API so that we can start making use of them in the page-table code. For now, they can just wrap the implementations of ->tlb_add_flush and ->tlb_sync pending future optimisation in each driver. Signed-off-by: Will Deacon --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 14 ++++++++++++++ drivers/iommu/arm-smmu-v3.c | 22 ++++++++++++++++++++++ drivers/iommu/arm-smmu.c | 24 ++++++++++++++++++++++++ drivers/iommu/ipmmu-vmsa.c | 8 ++++++++ drivers/iommu/msm_iommu.c | 16 ++++++++++++++++ drivers/iommu/mtk_iommu.c | 16 ++++++++++++++++ drivers/iommu/qcom_iommu.c | 16 ++++++++++++++++ 7 files changed, 116 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 17bceb11e708..651858147bd6 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -257,8 +257,22 @@ static void mmu_tlb_sync_context(void *cookie) // TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X } +static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule, + void *cookie) +{ + mmu_tlb_sync_context(cookie); +} + +static void mmu_tlb_flush_leaf(unsigned long iova, size_t size, size_t granule, + void *cookie) +{ + mmu_tlb_sync_context(cookie); +} + static const struct iommu_flush_ops mmu_tlb_ops = { .tlb_flush_all = mmu_tlb_inv_context_s1, + .tlb_flush_walk = mmu_tlb_flush_walk, + .tlb_flush_leaf = mmu_tlb_flush_leaf, .tlb_add_flush = mmu_tlb_inv_range_nosync, .tlb_sync = mmu_tlb_sync_context, }; diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 80753b8ca054..79819b003b07 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1603,8 +1603,30 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, } while (size -= granule); } +static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + struct arm_smmu_domain *smmu_domain = cookie; + struct arm_smmu_device *smmu = smmu_domain->smmu; + + arm_smmu_tlb_inv_range_nosync(iova, size, granule, false, cookie); + arm_smmu_cmdq_issue_sync(smmu); +} + +static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + struct arm_smmu_domain *smmu_domain = cookie; + struct arm_smmu_device *smmu = smmu_domain->smmu; + + arm_smmu_tlb_inv_range_nosync(iova, size, granule, true, cookie); + arm_smmu_cmdq_issue_sync(smmu); +} + static const struct iommu_flush_ops arm_smmu_flush_ops = { .tlb_flush_all = arm_smmu_tlb_inv_context, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync, }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e535ae2a9e65..e9f01b860ae3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -547,20 +547,44 @@ static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size, writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID); } +static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + struct arm_smmu_domain *smmu_domain = cookie; + + smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, false, cookie); + smmu_domain->tlb_ops->tlb_sync(cookie); +} + +static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + struct arm_smmu_domain *smmu_domain = cookie; + + smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, true, cookie); + smmu_domain->tlb_ops->tlb_sync(cookie); +} + static const struct iommu_flush_ops arm_smmu_s1_tlb_ops = { .tlb_flush_all = arm_smmu_tlb_inv_context_s1, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v2 = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb_flush_all = arm_smmu_tlb_inv_context_s2, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_flush = arm_smmu_tlb_inv_vmid_nosync, .tlb_sync = arm_smmu_tlb_sync_vmid, }; diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index a9332b893ce2..9cc7bcb7e39d 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -361,6 +361,12 @@ static void ipmmu_tlb_flush_all(void *cookie) ipmmu_tlb_invalidate(domain); } +static void ipmmu_tlb_flush(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + ipmmu_tlb_flush_all(cookie); +} + static void ipmmu_tlb_add_flush(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie) { @@ -369,6 +375,8 @@ static void ipmmu_tlb_add_flush(unsigned long iova, size_t size, static const struct iommu_flush_ops ipmmu_flush_ops = { .tlb_flush_all = ipmmu_tlb_flush_all, + .tlb_flush_walk = ipmmu_tlb_flush, + .tlb_flush_leaf = ipmmu_tlb_flush, .tlb_add_flush = ipmmu_tlb_add_flush, .tlb_sync = ipmmu_tlb_flush_all, }; diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 681ab3d3376d..64132093751a 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -178,8 +178,24 @@ static void __flush_iotlb_sync(void *cookie) */ } +static void __flush_iotlb_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + __flush_iotlb_range(iova, size, granule, false, cookie); + __flush_iotlb_sync(cookie); +} + +static void __flush_iotlb_leaf(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + __flush_iotlb_range(iova, size, granule, true, cookie); + __flush_iotlb_sync(cookie); +} + static const struct iommu_flush_ops msm_iommu_flush_ops = { .tlb_flush_all = __flush_iotlb, + .tlb_flush_walk = __flush_iotlb_walk, + .tlb_flush_leaf = __flush_iotlb_leaf, .tlb_add_flush = __flush_iotlb_range, .tlb_sync = __flush_iotlb_sync, }; diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index c870f1674903..85a7176bf9ae 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -188,8 +188,24 @@ static void mtk_iommu_tlb_sync(void *cookie) } } +static void mtk_iommu_tlb_flush_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + mtk_iommu_tlb_add_flush_nosync(iova, size, granule, false, cookie); + mtk_iommu_tlb_sync(cookie); +} + +static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + mtk_iommu_tlb_add_flush_nosync(iova, size, granule, true, cookie); + mtk_iommu_tlb_sync(cookie); +} + static const struct iommu_flush_ops mtk_iommu_flush_ops = { .tlb_flush_all = mtk_iommu_tlb_flush_all, + .tlb_flush_walk = mtk_iommu_tlb_flush_walk, + .tlb_flush_leaf = mtk_iommu_tlb_flush_leaf, .tlb_add_flush = mtk_iommu_tlb_add_flush_nosync, .tlb_sync = mtk_iommu_tlb_sync, }; diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index a7432991fa04..643079e52e69 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -164,8 +164,24 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, } } +static void qcom_iommu_tlb_flush_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + qcom_iommu_tlb_inv_range_nosync(iova, size, granule, false, cookie); + qcom_iommu_tlb_sync(cookie); +} + +static void qcom_iommu_tlb_flush_leaf(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ + qcom_iommu_tlb_inv_range_nosync(iova, size, granule, true, cookie); + qcom_iommu_tlb_sync(cookie); +} + static const struct iommu_flush_ops qcom_flush_ops = { .tlb_flush_all = qcom_iommu_tlb_inv_context, + .tlb_flush_walk = qcom_iommu_tlb_flush_walk, + .tlb_flush_leaf = qcom_iommu_tlb_flush_leaf, .tlb_add_flush = qcom_iommu_tlb_inv_range_nosync, .tlb_sync = qcom_iommu_tlb_sync, }; -- GitLab From 10b7a7d912697afd681a0bcfced9e05543aded35 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:32 +0100 Subject: [PATCH 1061/7155] iommu/io-pgtable-arm: Call ->tlb_flush_walk() and ->tlb_flush_leaf() Now that all IOMMU drivers using the io-pgtable API implement the ->tlb_flush_walk() and ->tlb_flush_leaf() callbacks, we can use them in the io-pgtable code instead of ->tlb_add_flush() immediately followed by ->tlb_sync(). Signed-off-by: Will Deacon --- drivers/iommu/io-pgtable-arm-v7s.c | 25 +++++++++++++++---------- drivers/iommu/io-pgtable-arm.c | 17 ++++++++++++----- include/linux/io-pgtable.h | 14 ++++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 116f97ee991e..8d4914fe73bc 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -493,9 +493,8 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova, * a chance for anything to kick off a table walk for the new iova. */ if (iop->cfg.quirks & IO_PGTABLE_QUIRK_TLBI_ON_MAP) { - io_pgtable_tlb_add_flush(iop, iova, size, - ARM_V7S_BLOCK_SIZE(2), false); - io_pgtable_tlb_sync(iop); + io_pgtable_tlb_flush_walk(iop, iova, size, + ARM_V7S_BLOCK_SIZE(2)); } else { wmb(); } @@ -541,8 +540,7 @@ static arm_v7s_iopte arm_v7s_split_cont(struct arm_v7s_io_pgtable *data, __arm_v7s_pte_sync(ptep, ARM_V7S_CONT_PAGES, &iop->cfg); size *= ARM_V7S_CONT_PAGES; - io_pgtable_tlb_add_flush(iop, iova, size, size, true); - io_pgtable_tlb_sync(iop); + io_pgtable_tlb_flush_leaf(iop, iova, size, size); return pte; } @@ -637,9 +635,8 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, for (i = 0; i < num_entries; i++) { if (ARM_V7S_PTE_IS_TABLE(pte[i], lvl)) { /* Also flush any partial walks */ - io_pgtable_tlb_add_flush(iop, iova, blk_size, - ARM_V7S_BLOCK_SIZE(lvl + 1), false); - io_pgtable_tlb_sync(iop); + io_pgtable_tlb_flush_walk(iop, iova, blk_size, + ARM_V7S_BLOCK_SIZE(lvl + 1)); ptep = iopte_deref(pte[i], lvl); __arm_v7s_free_table(ptep, lvl + 1, data); } else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) { @@ -805,13 +802,19 @@ static void dummy_tlb_flush_all(void *cookie) WARN_ON(cookie != cfg_cookie); } -static void dummy_tlb_add_flush(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) +static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, + void *cookie) { WARN_ON(cookie != cfg_cookie); WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } +static void dummy_tlb_add_flush(unsigned long iova, size_t size, + size_t granule, bool leaf, void *cookie) +{ + dummy_tlb_flush(iova, size, granule, cookie); +} + static void dummy_tlb_sync(void *cookie) { WARN_ON(cookie != cfg_cookie); @@ -819,6 +822,8 @@ static void dummy_tlb_sync(void *cookie) static const struct iommu_flush_ops dummy_tlb_ops = { .tlb_flush_all = dummy_tlb_flush_all, + .tlb_flush_walk = dummy_tlb_flush, + .tlb_flush_leaf = dummy_tlb_flush, .tlb_add_flush = dummy_tlb_add_flush, .tlb_sync = dummy_tlb_sync, }; diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 402f913b6f6d..b58338c86323 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -611,9 +611,8 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, if (!iopte_leaf(pte, lvl, iop->fmt)) { /* Also flush any partial walks */ - io_pgtable_tlb_add_flush(iop, iova, size, - ARM_LPAE_GRANULE(data), false); - io_pgtable_tlb_sync(iop); + io_pgtable_tlb_flush_walk(iop, iova, size, + ARM_LPAE_GRANULE(data)); ptep = iopte_deref(pte, data); __arm_lpae_free_pgtable(data, lvl + 1, ptep); } else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) { @@ -1069,13 +1068,19 @@ static void dummy_tlb_flush_all(void *cookie) WARN_ON(cookie != cfg_cookie); } -static void dummy_tlb_add_flush(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) +static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, + void *cookie) { WARN_ON(cookie != cfg_cookie); WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } +static void dummy_tlb_add_flush(unsigned long iova, size_t size, + size_t granule, bool leaf, void *cookie) +{ + dummy_tlb_flush(iova, size, granule, cookie); +} + static void dummy_tlb_sync(void *cookie) { WARN_ON(cookie != cfg_cookie); @@ -1083,6 +1088,8 @@ static void dummy_tlb_sync(void *cookie) static const struct iommu_flush_ops dummy_tlb_ops __initconst = { .tlb_flush_all = dummy_tlb_flush_all, + .tlb_flush_walk = dummy_tlb_flush, + .tlb_flush_leaf = dummy_tlb_flush, .tlb_add_flush = dummy_tlb_add_flush, .tlb_sync = dummy_tlb_sync, }; diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 27275575b305..0618aac59e74 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -198,6 +198,20 @@ static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop) iop->cfg.tlb->tlb_flush_all(iop->cookie); } +static inline void +io_pgtable_tlb_flush_walk(struct io_pgtable *iop, unsigned long iova, + size_t size, size_t granule) +{ + iop->cfg.tlb->tlb_flush_walk(iova, size, granule, iop->cookie); +} + +static inline void +io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova, + size_t size, size_t granule) +{ + iop->cfg.tlb->tlb_flush_leaf(iova, size, granule, iop->cookie); +} + static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop, unsigned long iova, size_t size, size_t granule, bool leaf) { -- GitLab From abfd6fe0cd535d31ee83b668be6eb59ce6a8469d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:41 +0100 Subject: [PATCH 1062/7155] iommu/io-pgtable: Replace ->tlb_add_flush() with ->tlb_add_page() The ->tlb_add_flush() callback in the io-pgtable API now looks a bit silly: - It takes a size and a granule, which are always the same - It takes a 'bool leaf', which is always true - It only ever flushes a single page With that in mind, replace it with an optional ->tlb_add_page() callback that drops the useless parameters. Signed-off-by: Will Deacon --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 5 -- drivers/iommu/arm-smmu-v3.c | 8 ++- drivers/iommu/arm-smmu.c | 88 ++++++++++++++++--------- drivers/iommu/io-pgtable-arm-v7s.c | 12 ++-- drivers/iommu/io-pgtable-arm.c | 11 ++-- drivers/iommu/ipmmu-vmsa.c | 7 -- drivers/iommu/msm_iommu.c | 7 +- drivers/iommu/mtk_iommu.c | 8 ++- drivers/iommu/qcom_iommu.c | 8 ++- include/linux/io-pgtable.h | 22 +++---- 10 files changed, 105 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 651858147bd6..ff9af320cacc 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -247,10 +247,6 @@ static void mmu_tlb_inv_context_s1(void *cookie) mmu_hw_do_operation(pfdev, 0, 0, ~0UL, AS_COMMAND_FLUSH_MEM); } -static void mmu_tlb_inv_range_nosync(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) -{} - static void mmu_tlb_sync_context(void *cookie) { //struct panfrost_device *pfdev = cookie; @@ -273,7 +269,6 @@ static const struct iommu_flush_ops mmu_tlb_ops = { .tlb_flush_all = mmu_tlb_inv_context_s1, .tlb_flush_walk = mmu_tlb_flush_walk, .tlb_flush_leaf = mmu_tlb_flush_leaf, - .tlb_add_flush = mmu_tlb_inv_range_nosync, .tlb_sync = mmu_tlb_sync_context, }; diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 79819b003b07..98c90a1b4b22 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1603,6 +1603,12 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, } while (size -= granule); } +static void arm_smmu_tlb_inv_page_nosync(unsigned long iova, size_t granule, + void *cookie) +{ + arm_smmu_tlb_inv_range_nosync(iova, granule, granule, true, cookie); +} + static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, size_t granule, void *cookie) { @@ -1627,7 +1633,7 @@ static const struct iommu_flush_ops arm_smmu_flush_ops = { .tlb_flush_all = arm_smmu_tlb_inv_context, .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, - .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, + .tlb_add_page = arm_smmu_tlb_inv_page_nosync, .tlb_sync = arm_smmu_tlb_sync, }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e9f01b860ae3..f056164a94b0 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -248,10 +248,16 @@ enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_BYPASS, }; +struct arm_smmu_flush_ops { + struct iommu_flush_ops tlb; + void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule, + bool leaf, void *cookie) +}; + struct arm_smmu_domain { struct arm_smmu_device *smmu; struct io_pgtable_ops *pgtbl_ops; - const struct iommu_flush_ops *tlb_ops; + const struct arm_smmu_flush_ops *flush_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; @@ -551,42 +557,62 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, size_t granule, void *cookie) { struct arm_smmu_domain *smmu_domain = cookie; + const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; - smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, false, cookie); - smmu_domain->tlb_ops->tlb_sync(cookie); + ops->tlb_inv_range(iova, size, granule, false, cookie); + ops->tlb.tlb_sync(cookie); } static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, size_t granule, void *cookie) { struct arm_smmu_domain *smmu_domain = cookie; + const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + + ops->tlb_inv_range(iova, size, granule, true, cookie); + ops->tlb.tlb_sync(cookie); +} + +static void arm_smmu_tlb_add_page(unsigned long iova, size_t granule, + void *cookie) +{ + struct arm_smmu_domain *smmu_domain = cookie; + const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; - smmu_domain->tlb_ops->tlb_add_flush(iova, size, granule, true, cookie); - smmu_domain->tlb_ops->tlb_sync(cookie); + ops->tlb_inv_range(iova, granule, granule, true, cookie); } -static const struct iommu_flush_ops arm_smmu_s1_tlb_ops = { - .tlb_flush_all = arm_smmu_tlb_inv_context_s1, - .tlb_flush_walk = arm_smmu_tlb_inv_walk, - .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, - .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, - .tlb_sync = arm_smmu_tlb_sync_context, +static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = { + .tlb = { + .tlb_flush_all = arm_smmu_tlb_inv_context_s1, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, + .tlb_add_page = arm_smmu_tlb_add_page, + .tlb_sync = arm_smmu_tlb_sync_context, + }, + .tlb_inv_range = arm_smmu_tlb_inv_range_nosync, }; -static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v2 = { - .tlb_flush_all = arm_smmu_tlb_inv_context_s2, - .tlb_flush_walk = arm_smmu_tlb_inv_walk, - .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, - .tlb_add_flush = arm_smmu_tlb_inv_range_nosync, - .tlb_sync = arm_smmu_tlb_sync_context, +static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = { + .tlb = { + .tlb_flush_all = arm_smmu_tlb_inv_context_s2, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, + .tlb_add_page = arm_smmu_tlb_add_page, + .tlb_sync = arm_smmu_tlb_sync_context, + }, + .tlb_inv_range = arm_smmu_tlb_inv_range_nosync, }; -static const struct iommu_flush_ops arm_smmu_s2_tlb_ops_v1 = { - .tlb_flush_all = arm_smmu_tlb_inv_context_s2, - .tlb_flush_walk = arm_smmu_tlb_inv_walk, - .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, - .tlb_add_flush = arm_smmu_tlb_inv_vmid_nosync, - .tlb_sync = arm_smmu_tlb_sync_vmid, +static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { + .tlb = { + .tlb_flush_all = arm_smmu_tlb_inv_context_s2, + .tlb_flush_walk = arm_smmu_tlb_inv_walk, + .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, + .tlb_add_page = arm_smmu_tlb_add_page, + .tlb_sync = arm_smmu_tlb_sync_vmid, + }, + .tlb_inv_range = arm_smmu_tlb_inv_vmid_nosync, }; static irqreturn_t arm_smmu_context_fault(int irq, void *dev) @@ -866,7 +892,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ias = min(ias, 32UL); oas = min(oas, 32UL); } - smmu_domain->tlb_ops = &arm_smmu_s1_tlb_ops; + smmu_domain->flush_ops = &arm_smmu_s1_tlb_ops; break; case ARM_SMMU_DOMAIN_NESTED: /* @@ -886,9 +912,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, oas = min(oas, 40UL); } if (smmu->version == ARM_SMMU_V2) - smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v2; + smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v2; else - smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v1; + smmu_domain->flush_ops = &arm_smmu_s2_tlb_ops_v1; break; default: ret = -EINVAL; @@ -917,7 +943,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .ias = ias, .oas = oas, .coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK, - .tlb = smmu_domain->tlb_ops, + .tlb = &smmu_domain->flush_ops->tlb, .iommu_dev = smmu->dev, }; @@ -1346,9 +1372,9 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domain->tlb_ops) { + if (smmu_domain->flush_ops) { arm_smmu_rpm_get(smmu); - smmu_domain->tlb_ops->tlb_flush_all(smmu_domain); + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); arm_smmu_rpm_put(smmu); } } @@ -1359,9 +1385,9 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain, struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; - if (smmu_domain->tlb_ops) { + if (smmu_domain->flush_ops) { arm_smmu_rpm_get(smmu); - smmu_domain->tlb_ops->tlb_sync(smmu_domain); + smmu_domain->flush_ops->tlb.tlb_sync(smmu_domain); arm_smmu_rpm_put(smmu); } } diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 8d4914fe73bc..b3f975c95f76 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -584,7 +584,7 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data, return __arm_v7s_unmap(data, iova, size, 2, tablep); } - io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true); + io_pgtable_tlb_add_page(&data->iop, iova, size); return size; } @@ -647,8 +647,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, */ smp_wmb(); } else { - io_pgtable_tlb_add_flush(iop, iova, blk_size, - blk_size, true); + io_pgtable_tlb_add_page(iop, iova, blk_size); } iova += blk_size; } @@ -809,10 +808,9 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } -static void dummy_tlb_add_flush(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) +static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) { - dummy_tlb_flush(iova, size, granule, cookie); + dummy_tlb_flush(iova, granule, granule, cookie); } static void dummy_tlb_sync(void *cookie) @@ -824,7 +822,7 @@ static const struct iommu_flush_ops dummy_tlb_ops = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_flush_walk = dummy_tlb_flush, .tlb_flush_leaf = dummy_tlb_flush, - .tlb_add_flush = dummy_tlb_add_flush, + .tlb_add_page = dummy_tlb_add_page, .tlb_sync = dummy_tlb_sync, }; diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index b58338c86323..a5c0db01533e 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -582,7 +582,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data, tablep = iopte_deref(pte, data); } else if (unmap_idx >= 0) { - io_pgtable_tlb_add_flush(&data->iop, iova, size, size, true); + io_pgtable_tlb_add_page(&data->iop, iova, size); return size; } @@ -623,7 +623,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, */ smp_wmb(); } else { - io_pgtable_tlb_add_flush(iop, iova, size, size, true); + io_pgtable_tlb_add_page(iop, iova, size); } return size; @@ -1075,10 +1075,9 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } -static void dummy_tlb_add_flush(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) +static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) { - dummy_tlb_flush(iova, size, granule, cookie); + dummy_tlb_flush(iova, granule, granule, cookie); } static void dummy_tlb_sync(void *cookie) @@ -1090,7 +1089,7 @@ static const struct iommu_flush_ops dummy_tlb_ops __initconst = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_flush_walk = dummy_tlb_flush, .tlb_flush_leaf = dummy_tlb_flush, - .tlb_add_flush = dummy_tlb_add_flush, + .tlb_add_page = dummy_tlb_add_page, .tlb_sync = dummy_tlb_sync, }; diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 9cc7bcb7e39d..c4da271af90e 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -367,17 +367,10 @@ static void ipmmu_tlb_flush(unsigned long iova, size_t size, ipmmu_tlb_flush_all(cookie); } -static void ipmmu_tlb_add_flush(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) -{ - /* The hardware doesn't support selective TLB flush. */ -} - static const struct iommu_flush_ops ipmmu_flush_ops = { .tlb_flush_all = ipmmu_tlb_flush_all, .tlb_flush_walk = ipmmu_tlb_flush, .tlb_flush_leaf = ipmmu_tlb_flush, - .tlb_add_flush = ipmmu_tlb_add_flush, .tlb_sync = ipmmu_tlb_flush_all, }; diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 64132093751a..2cd83295a841 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -192,11 +192,16 @@ static void __flush_iotlb_leaf(unsigned long iova, size_t size, __flush_iotlb_sync(cookie); } +static void __flush_iotlb_page(unsigned long iova, size_t granule, void *cookie) +{ + __flush_iotlb_range(iova, granule, granule, true, cookie); +} + static const struct iommu_flush_ops msm_iommu_flush_ops = { .tlb_flush_all = __flush_iotlb, .tlb_flush_walk = __flush_iotlb_walk, .tlb_flush_leaf = __flush_iotlb_leaf, - .tlb_add_flush = __flush_iotlb_range, + .tlb_add_page = __flush_iotlb_page, .tlb_sync = __flush_iotlb_sync, }; diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 85a7176bf9ae..a0b4b4dc4b90 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -202,11 +202,17 @@ static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size, mtk_iommu_tlb_sync(cookie); } +static void mtk_iommu_tlb_flush_page_nosync(unsigned long iova, size_t granule, + void *cookie) +{ + mtk_iommu_tlb_add_flush_nosync(iova, granule, granule, true, cookie); +} + static const struct iommu_flush_ops mtk_iommu_flush_ops = { .tlb_flush_all = mtk_iommu_tlb_flush_all, .tlb_flush_walk = mtk_iommu_tlb_flush_walk, .tlb_flush_leaf = mtk_iommu_tlb_flush_leaf, - .tlb_add_flush = mtk_iommu_tlb_add_flush_nosync, + .tlb_add_page = mtk_iommu_tlb_flush_page_nosync, .tlb_sync = mtk_iommu_tlb_sync, }; diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 643079e52e69..7d8411dee4cf 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -178,11 +178,17 @@ static void qcom_iommu_tlb_flush_leaf(unsigned long iova, size_t size, qcom_iommu_tlb_sync(cookie); } +static void qcom_iommu_tlb_add_page(unsigned long iova, size_t granule, + void *cookie) +{ + qcom_iommu_tlb_inv_range_nosync(iova, granule, granule, true, cookie); +} + static const struct iommu_flush_ops qcom_flush_ops = { .tlb_flush_all = qcom_iommu_tlb_inv_context, .tlb_flush_walk = qcom_iommu_tlb_flush_walk, .tlb_flush_leaf = qcom_iommu_tlb_flush_leaf, - .tlb_add_flush = qcom_iommu_tlb_inv_range_nosync, + .tlb_add_page = qcom_iommu_tlb_add_page, .tlb_sync = qcom_iommu_tlb_sync, }; diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 0618aac59e74..99e04bd2baa1 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -25,12 +25,11 @@ enum io_pgtable_fmt { * address range. * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual * address range. - * @tlb_add_flush: Optional callback to queue up leaf TLB invalidation for a - * virtual address range. This function exists purely as an - * optimisation for IOMMUs that cannot batch TLB invalidation - * operations efficiently and are therefore better suited to - * issuing them early rather than deferring them until - * iommu_tlb_sync(). + * @tlb_add_page: Optional callback to queue up leaf TLB invalidation for a + * single page. This function exists purely as an optimisation + * for IOMMUs that cannot batch TLB invalidation operations + * efficiently and are therefore better suited to issuing them + * early rather than deferring them until iommu_tlb_sync(). * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and * any corresponding page table updates are visible to the * IOMMU. @@ -44,8 +43,7 @@ struct iommu_flush_ops { void *cookie); void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule, void *cookie); - void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule, - bool leaf, void *cookie); + void (*tlb_add_page)(unsigned long iova, size_t granule, void *cookie); void (*tlb_sync)(void *cookie); }; @@ -212,10 +210,12 @@ io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova, iop->cfg.tlb->tlb_flush_leaf(iova, size, granule, iop->cookie); } -static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop, - unsigned long iova, size_t size, size_t granule, bool leaf) +static inline void +io_pgtable_tlb_add_page(struct io_pgtable *iop, unsigned long iova, + size_t granule) { - iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie); + if (iop->cfg.tlb->tlb_add_page) + iop->cfg.tlb->tlb_add_page(iova, granule, iop->cookie); } static inline void io_pgtable_tlb_sync(struct io_pgtable *iop) -- GitLab From e953f7f2fa78d1c7fd064171f88457c6b1e21af9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:50 +0100 Subject: [PATCH 1063/7155] iommu/io-pgtable: Remove unused ->tlb_sync() callback The ->tlb_sync() callback is no longer used, so it can be removed. Signed-off-by: Will Deacon --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 1 - drivers/iommu/arm-smmu-v3.c | 8 -------- drivers/iommu/arm-smmu.c | 17 +++++++++-------- drivers/iommu/io-pgtable-arm-v7s.c | 6 ------ drivers/iommu/io-pgtable-arm.c | 6 ------ drivers/iommu/ipmmu-vmsa.c | 1 - drivers/iommu/msm_iommu.c | 20 +++++++------------- drivers/iommu/mtk_iommu.c | 1 - drivers/iommu/qcom_iommu.c | 1 - include/linux/io-pgtable.h | 9 --------- 10 files changed, 16 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index ff9af320cacc..de22a2276e00 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -269,7 +269,6 @@ static const struct iommu_flush_ops mmu_tlb_ops = { .tlb_flush_all = mmu_tlb_inv_context_s1, .tlb_flush_walk = mmu_tlb_flush_walk, .tlb_flush_leaf = mmu_tlb_flush_leaf, - .tlb_sync = mmu_tlb_sync_context, }; static const char *access_type_name(struct panfrost_device *pfdev, diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 98c90a1b4b22..231093413ff9 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1545,13 +1545,6 @@ static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, } /* IO_PGTABLE API */ -static void arm_smmu_tlb_sync(void *cookie) -{ - struct arm_smmu_domain *smmu_domain = cookie; - - arm_smmu_cmdq_issue_sync(smmu_domain->smmu); -} - static void arm_smmu_tlb_inv_context(void *cookie) { struct arm_smmu_domain *smmu_domain = cookie; @@ -1634,7 +1627,6 @@ static const struct iommu_flush_ops arm_smmu_flush_ops = { .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_inv_page_nosync, - .tlb_sync = arm_smmu_tlb_sync, }; /* IOMMU API */ diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f056164a94b0..07a267c437d6 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -251,7 +251,8 @@ enum arm_smmu_domain_stage { struct arm_smmu_flush_ops { struct iommu_flush_ops tlb; void (*tlb_inv_range)(unsigned long iova, size_t size, size_t granule, - bool leaf, void *cookie) + bool leaf, void *cookie); + void (*tlb_sync)(void *cookie); }; struct arm_smmu_domain { @@ -539,7 +540,7 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, * On MMU-401 at least, the cost of firing off multiple TLBIVMIDs appears * almost negligible, but the benefit of getting the first one in as far ahead * of the sync as possible is significant, hence we don't just make this a - * no-op and set .tlb_sync to arm_smmu_inv_context_s2() as you might think. + * no-op and set .tlb_sync to arm_smmu_tlb_inv_context_s2() as you might think. */ static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie) @@ -560,7 +561,7 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; ops->tlb_inv_range(iova, size, granule, false, cookie); - ops->tlb.tlb_sync(cookie); + ops->tlb_sync(cookie); } static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, @@ -570,7 +571,7 @@ static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; ops->tlb_inv_range(iova, size, granule, true, cookie); - ops->tlb.tlb_sync(cookie); + ops->tlb_sync(cookie); } static void arm_smmu_tlb_add_page(unsigned long iova, size_t granule, @@ -588,9 +589,9 @@ static const struct arm_smmu_flush_ops arm_smmu_s1_tlb_ops = { .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, - .tlb_sync = arm_smmu_tlb_sync_context, }, .tlb_inv_range = arm_smmu_tlb_inv_range_nosync, + .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = { @@ -599,9 +600,9 @@ static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v2 = { .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, - .tlb_sync = arm_smmu_tlb_sync_context, }, .tlb_inv_range = arm_smmu_tlb_inv_range_nosync, + .tlb_sync = arm_smmu_tlb_sync_context, }; static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { @@ -610,9 +611,9 @@ static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb_flush_walk = arm_smmu_tlb_inv_walk, .tlb_flush_leaf = arm_smmu_tlb_inv_leaf, .tlb_add_page = arm_smmu_tlb_add_page, - .tlb_sync = arm_smmu_tlb_sync_vmid, }, .tlb_inv_range = arm_smmu_tlb_inv_vmid_nosync, + .tlb_sync = arm_smmu_tlb_sync_vmid, }; static irqreturn_t arm_smmu_context_fault(int irq, void *dev) @@ -1387,7 +1388,7 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain, if (smmu_domain->flush_ops) { arm_smmu_rpm_get(smmu); - smmu_domain->flush_ops->tlb.tlb_sync(smmu_domain); + smmu_domain->flush_ops->tlb_sync(smmu_domain); arm_smmu_rpm_put(smmu); } } diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index b3f975c95f76..203894fb6765 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -813,17 +813,11 @@ static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) dummy_tlb_flush(iova, granule, granule, cookie); } -static void dummy_tlb_sync(void *cookie) -{ - WARN_ON(cookie != cfg_cookie); -} - static const struct iommu_flush_ops dummy_tlb_ops = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_flush_walk = dummy_tlb_flush, .tlb_flush_leaf = dummy_tlb_flush, .tlb_add_page = dummy_tlb_add_page, - .tlb_sync = dummy_tlb_sync, }; #define __FAIL(ops) ({ \ diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index a5c0db01533e..f35516744965 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -1080,17 +1080,11 @@ static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) dummy_tlb_flush(iova, granule, granule, cookie); } -static void dummy_tlb_sync(void *cookie) -{ - WARN_ON(cookie != cfg_cookie); -} - static const struct iommu_flush_ops dummy_tlb_ops __initconst = { .tlb_flush_all = dummy_tlb_flush_all, .tlb_flush_walk = dummy_tlb_flush, .tlb_flush_leaf = dummy_tlb_flush, .tlb_add_page = dummy_tlb_add_page, - .tlb_sync = dummy_tlb_sync, }; static void __init arm_lpae_dump_ops(struct io_pgtable_ops *ops) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index c4da271af90e..a2b8eff4c1f7 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -371,7 +371,6 @@ static const struct iommu_flush_ops ipmmu_flush_ops = { .tlb_flush_all = ipmmu_tlb_flush_all, .tlb_flush_walk = ipmmu_tlb_flush, .tlb_flush_leaf = ipmmu_tlb_flush, - .tlb_sync = ipmmu_tlb_flush_all, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 2cd83295a841..ccfc7ed230ef 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -168,28 +168,16 @@ static void __flush_iotlb_range(unsigned long iova, size_t size, return; } -static void __flush_iotlb_sync(void *cookie) -{ - /* - * Nothing is needed here, the barrier to guarantee - * completion of the tlb sync operation is implicitly - * taken care when the iommu client does a writel before - * kick starting the other master. - */ -} - static void __flush_iotlb_walk(unsigned long iova, size_t size, size_t granule, void *cookie) { __flush_iotlb_range(iova, size, granule, false, cookie); - __flush_iotlb_sync(cookie); } static void __flush_iotlb_leaf(unsigned long iova, size_t size, size_t granule, void *cookie) { __flush_iotlb_range(iova, size, granule, true, cookie); - __flush_iotlb_sync(cookie); } static void __flush_iotlb_page(unsigned long iova, size_t granule, void *cookie) @@ -202,7 +190,6 @@ static const struct iommu_flush_ops msm_iommu_flush_ops = { .tlb_flush_walk = __flush_iotlb_walk, .tlb_flush_leaf = __flush_iotlb_leaf, .tlb_add_page = __flush_iotlb_page, - .tlb_sync = __flush_iotlb_sync, }; static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end) @@ -712,6 +699,13 @@ static struct iommu_ops msm_iommu_ops = { .detach_dev = msm_iommu_detach_dev, .map = msm_iommu_map, .unmap = msm_iommu_unmap, + /* + * Nothing is needed here, the barrier to guarantee + * completion of the tlb sync operation is implicitly + * taken care when the iommu client does a writel before + * kick starting the other master. + */ + .iotlb_sync = NULL, .iova_to_phys = msm_iommu_iova_to_phys, .add_device = msm_iommu_add_device, .remove_device = msm_iommu_remove_device, diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index a0b4b4dc4b90..3785750bdb44 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -213,7 +213,6 @@ static const struct iommu_flush_ops mtk_iommu_flush_ops = { .tlb_flush_walk = mtk_iommu_tlb_flush_walk, .tlb_flush_leaf = mtk_iommu_tlb_flush_leaf, .tlb_add_page = mtk_iommu_tlb_flush_page_nosync, - .tlb_sync = mtk_iommu_tlb_sync, }; static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 7d8411dee4cf..0b8a6d6bb475 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -189,7 +189,6 @@ static const struct iommu_flush_ops qcom_flush_ops = { .tlb_flush_walk = qcom_iommu_tlb_flush_walk, .tlb_flush_leaf = qcom_iommu_tlb_flush_leaf, .tlb_add_page = qcom_iommu_tlb_add_page, - .tlb_sync = qcom_iommu_tlb_sync, }; static irqreturn_t qcom_iommu_fault(int irq, void *dev) diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 99e04bd2baa1..843310484fe2 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -30,9 +30,6 @@ enum io_pgtable_fmt { * for IOMMUs that cannot batch TLB invalidation operations * efficiently and are therefore better suited to issuing them * early rather than deferring them until iommu_tlb_sync(). - * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and - * any corresponding page table updates are visible to the - * IOMMU. * * Note that these can all be called in atomic context and must therefore * not block. @@ -44,7 +41,6 @@ struct iommu_flush_ops { void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule, void *cookie); void (*tlb_add_page)(unsigned long iova, size_t granule, void *cookie); - void (*tlb_sync)(void *cookie); }; /** @@ -218,11 +214,6 @@ io_pgtable_tlb_add_page(struct io_pgtable *iop, unsigned long iova, iop->cfg.tlb->tlb_add_page(iova, granule, iop->cookie); } -static inline void io_pgtable_tlb_sync(struct io_pgtable *iop) -{ - iop->cfg.tlb->tlb_sync(iop->cookie); -} - /** * struct io_pgtable_init_fns - Alloc/free a set of page tables for a * particular format. -- GitLab From a2d3a382d6c682e22b263c9e7f0d857c3fa6c9d6 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:44:58 +0100 Subject: [PATCH 1064/7155] iommu/io-pgtable: Pass struct iommu_iotlb_gather to ->unmap() Update the io-pgtable ->unmap() function to take an iommu_iotlb_gather pointer as an argument, and update the callers as appropriate. Signed-off-by: Will Deacon --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 2 +- drivers/iommu/io-pgtable-arm-v7s.c | 6 +++--- drivers/iommu/io-pgtable-arm.c | 7 +++---- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/msm_iommu.c | 2 +- drivers/iommu/mtk_iommu.c | 2 +- drivers/iommu/qcom_iommu.c | 2 +- include/linux/io-pgtable.h | 4 +++- 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index de22a2276e00..6e8145c36e93 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -222,7 +222,7 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo) size_t unmapped_page; size_t pgsize = get_pgsize(iova, len - unmapped_len); - unmapped_page = ops->unmap(ops, iova, pgsize); + unmapped_page = ops->unmap(ops, iova, pgsize, NULL); if (!unmapped_page) break; diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 231093413ff9..8e2e53079f48 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2015,7 +2015,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, if (!ops) return 0; - ret = ops->unmap(ops, iova, size); + ret = ops->unmap(ops, iova, size, gather); if (ret && arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size)) return 0; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 07a267c437d6..f6689956ab6e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1362,7 +1362,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, return 0; arm_smmu_rpm_get(smmu); - ret = ops->unmap(ops, iova, size); + ret = ops->unmap(ops, iova, size, gather); arm_smmu_rpm_put(smmu); return ret; diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 203894fb6765..a7776e982b6c 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -666,7 +666,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, } static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops); @@ -892,7 +892,7 @@ static int __init arm_v7s_do_selftests(void) size = 1UL << __ffs(cfg.pgsize_bitmap); while (i < loopnr) { iova_start = i * SZ_16M; - if (ops->unmap(ops, iova_start + size, size) != size) + if (ops->unmap(ops, iova_start + size, size, NULL) != size) return __FAIL(ops); /* Remap of partial unmap */ @@ -910,7 +910,7 @@ static int __init arm_v7s_do_selftests(void) for_each_set_bit(i, &cfg.pgsize_bitmap, BITS_PER_LONG) { size = 1UL << i; - if (ops->unmap(ops, iova, size) != size) + if (ops->unmap(ops, iova, size, NULL) != size) return __FAIL(ops); if (ops->iova_to_phys(ops, iova + 42)) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index f35516744965..325430f8a0a1 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -642,7 +641,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, } static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, - size_t size) + size_t size, struct iommu_iotlb_gather *gather) { struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops); arm_lpae_iopte *ptep = data->pgd; @@ -1167,7 +1166,7 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg) /* Partial unmap */ size = 1UL << __ffs(cfg->pgsize_bitmap); - if (ops->unmap(ops, SZ_1G + size, size) != size) + if (ops->unmap(ops, SZ_1G + size, size, NULL) != size) return __FAIL(ops, i); /* Remap of partial unmap */ @@ -1182,7 +1181,7 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg) for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) { size = 1UL << j; - if (ops->unmap(ops, iova, size) != size) + if (ops->unmap(ops, iova, size, NULL) != size) return __FAIL(ops, i); if (ops->iova_to_phys(ops, iova + 42)) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index a2b8eff4c1f7..76a8ec343d53 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -737,7 +737,7 @@ static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova, { struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain); - return domain->iop->unmap(domain->iop, iova, size); + return domain->iop->unmap(domain->iop, iova, size, gather); } static void ipmmu_flush_iotlb_all(struct iommu_domain *io_domain) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index ccfc7ed230ef..8a0dcaf0a9e9 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -523,7 +523,7 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova, unsigned long flags; spin_lock_irqsave(&priv->pgtlock, flags); - len = priv->iop->unmap(priv->iop, iova, len); + len = priv->iop->unmap(priv->iop, iova, len, gather); spin_unlock_irqrestore(&priv->pgtlock, flags); return len; diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3785750bdb44..b73cffd63262 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -400,7 +400,7 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain, size_t unmapsz; spin_lock_irqsave(&dom->pgtlock, flags); - unmapsz = dom->iop->unmap(dom->iop, iova, size); + unmapsz = dom->iop->unmap(dom->iop, iova, size, gather); spin_unlock_irqrestore(&dom->pgtlock, flags); return unmapsz; diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 0b8a6d6bb475..48b288ef74b4 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -455,7 +455,7 @@ static size_t qcom_iommu_unmap(struct iommu_domain *domain, unsigned long iova, */ pm_runtime_get_sync(qcom_domain->iommu->dev); spin_lock_irqsave(&qcom_domain->pgtbl_lock, flags); - ret = ops->unmap(ops, iova, size); + ret = ops->unmap(ops, iova, size, gather); spin_unlock_irqrestore(&qcom_domain->pgtbl_lock, flags); pm_runtime_put_sync(qcom_domain->iommu->dev); diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 843310484fe2..fe27d93c8ad9 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __IO_PGTABLE_H #define __IO_PGTABLE_H + #include +#include /* * Public API for use by IOMMU drivers @@ -136,7 +138,7 @@ struct io_pgtable_ops { int (*map)(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova, - size_t size); + size_t size, struct iommu_iotlb_gather *gather); phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops, unsigned long iova); }; -- GitLab From 3951c41af4a65ba418e6b1b973d398552bedb84f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 16:45:15 +0100 Subject: [PATCH 1065/7155] iommu/io-pgtable: Pass struct iommu_iotlb_gather to ->tlb_add_page() With all the pieces in place, we can finally propagate the iommu_iotlb_gather structure from the call to unmap() down to the IOMMU drivers' implementation of ->tlb_add_page(). Currently everybody ignores it, but the machinery is now there to defer invalidation. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 3 ++- drivers/iommu/arm-smmu.c | 3 ++- drivers/iommu/io-pgtable-arm-v7s.c | 23 ++++++++++++++--------- drivers/iommu/io-pgtable-arm.c | 22 ++++++++++++++-------- drivers/iommu/msm_iommu.c | 3 ++- drivers/iommu/mtk_iommu.c | 3 ++- drivers/iommu/qcom_iommu.c | 3 ++- include/linux/io-pgtable.h | 16 +++++++++------- 8 files changed, 47 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 8e2e53079f48..d1ebc7103065 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1596,7 +1596,8 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, } while (size -= granule); } -static void arm_smmu_tlb_inv_page_nosync(unsigned long iova, size_t granule, +static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { arm_smmu_tlb_inv_range_nosync(iova, granule, granule, true, cookie); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f6689956ab6e..5598d0ff71a8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -574,7 +574,8 @@ static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, ops->tlb_sync(cookie); } -static void arm_smmu_tlb_add_page(unsigned long iova, size_t granule, +static void arm_smmu_tlb_add_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { struct arm_smmu_domain *smmu_domain = cookie; diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index a7776e982b6c..18e7d212c7de 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -362,7 +362,8 @@ static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl) return false; } -static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *, unsigned long, +static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *, + struct iommu_iotlb_gather *, unsigned long, size_t, int, arm_v7s_iopte *); static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data, @@ -383,7 +384,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data, size_t sz = ARM_V7S_BLOCK_SIZE(lvl); tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl); - if (WARN_ON(__arm_v7s_unmap(data, iova + i * sz, + if (WARN_ON(__arm_v7s_unmap(data, NULL, iova + i * sz, sz, lvl, tblp) != sz)) return -EINVAL; } else if (ptep[i]) { @@ -545,6 +546,7 @@ static arm_v7s_iopte arm_v7s_split_cont(struct arm_v7s_io_pgtable *data, } static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data, + struct iommu_iotlb_gather *gather, unsigned long iova, size_t size, arm_v7s_iopte blk_pte, arm_v7s_iopte *ptep) @@ -581,14 +583,15 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data, return 0; tablep = iopte_deref(pte, 1); - return __arm_v7s_unmap(data, iova, size, 2, tablep); + return __arm_v7s_unmap(data, gather, iova, size, 2, tablep); } - io_pgtable_tlb_add_page(&data->iop, iova, size); + io_pgtable_tlb_add_page(&data->iop, gather, iova, size); return size; } static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, + struct iommu_iotlb_gather *gather, unsigned long iova, size_t size, int lvl, arm_v7s_iopte *ptep) { @@ -647,7 +650,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, */ smp_wmb(); } else { - io_pgtable_tlb_add_page(iop, iova, blk_size); + io_pgtable_tlb_add_page(iop, gather, iova, blk_size); } iova += blk_size; } @@ -657,12 +660,13 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, * Insert a table at the next level to map the old region, * minus the part we want to unmap */ - return arm_v7s_split_blk_unmap(data, iova, size, pte[0], ptep); + return arm_v7s_split_blk_unmap(data, gather, iova, size, pte[0], + ptep); } /* Keep on walkin' */ ptep = iopte_deref(pte[0], lvl); - return __arm_v7s_unmap(data, iova, size, lvl + 1, ptep); + return __arm_v7s_unmap(data, gather, iova, size, lvl + 1, ptep); } static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova, @@ -673,7 +677,7 @@ static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova, if (WARN_ON(upper_32_bits(iova))) return 0; - return __arm_v7s_unmap(data, iova, size, 1, data->pgd); + return __arm_v7s_unmap(data, gather, iova, size, 1, data->pgd); } static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops, @@ -808,7 +812,8 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } -static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) +static void dummy_tlb_add_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { dummy_tlb_flush(iova, granule, granule, cookie); } diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 325430f8a0a1..4c91359057c5 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -289,6 +289,7 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte, } static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, + struct iommu_iotlb_gather *gather, unsigned long iova, size_t size, int lvl, arm_lpae_iopte *ptep); @@ -334,8 +335,10 @@ static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data, size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data); tblp = ptep - ARM_LPAE_LVL_IDX(iova, lvl, data); - if (WARN_ON(__arm_lpae_unmap(data, iova, sz, lvl, tblp) != sz)) + if (__arm_lpae_unmap(data, NULL, iova, sz, lvl, tblp) != sz) { + WARN_ON(1); return -EINVAL; + } } __arm_lpae_init_pte(data, paddr, prot, lvl, ptep); @@ -536,6 +539,7 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop) } static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data, + struct iommu_iotlb_gather *gather, unsigned long iova, size_t size, arm_lpae_iopte blk_pte, int lvl, arm_lpae_iopte *ptep) @@ -581,14 +585,15 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data, tablep = iopte_deref(pte, data); } else if (unmap_idx >= 0) { - io_pgtable_tlb_add_page(&data->iop, iova, size); + io_pgtable_tlb_add_page(&data->iop, gather, iova, size); return size; } - return __arm_lpae_unmap(data, iova, size, lvl, tablep); + return __arm_lpae_unmap(data, gather, iova, size, lvl, tablep); } static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, + struct iommu_iotlb_gather *gather, unsigned long iova, size_t size, int lvl, arm_lpae_iopte *ptep) { @@ -622,7 +627,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, */ smp_wmb(); } else { - io_pgtable_tlb_add_page(iop, iova, size); + io_pgtable_tlb_add_page(iop, gather, iova, size); } return size; @@ -631,13 +636,13 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, * Insert a table at the next level to map the old region, * minus the part we want to unmap */ - return arm_lpae_split_blk_unmap(data, iova, size, pte, + return arm_lpae_split_blk_unmap(data, gather, iova, size, pte, lvl + 1, ptep); } /* Keep on walkin' */ ptep = iopte_deref(pte, data); - return __arm_lpae_unmap(data, iova, size, lvl + 1, ptep); + return __arm_lpae_unmap(data, gather, iova, size, lvl + 1, ptep); } static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, @@ -650,7 +655,7 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias))) return 0; - return __arm_lpae_unmap(data, iova, size, lvl, ptep); + return __arm_lpae_unmap(data, gather, iova, size, lvl, ptep); } static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops, @@ -1074,7 +1079,8 @@ static void dummy_tlb_flush(unsigned long iova, size_t size, size_t granule, WARN_ON(!(size & cfg_cookie->pgsize_bitmap)); } -static void dummy_tlb_add_page(unsigned long iova, size_t granule, void *cookie) +static void dummy_tlb_add_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { dummy_tlb_flush(iova, granule, granule, cookie); } diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 8a0dcaf0a9e9..4c0be5b75c28 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -180,7 +180,8 @@ static void __flush_iotlb_leaf(unsigned long iova, size_t size, __flush_iotlb_range(iova, size, granule, true, cookie); } -static void __flush_iotlb_page(unsigned long iova, size_t granule, void *cookie) +static void __flush_iotlb_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { __flush_iotlb_range(iova, granule, granule, true, cookie); } diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index b73cffd63262..0827d51936fa 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -202,7 +202,8 @@ static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size, mtk_iommu_tlb_sync(cookie); } -static void mtk_iommu_tlb_flush_page_nosync(unsigned long iova, size_t granule, +static void mtk_iommu_tlb_flush_page_nosync(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { mtk_iommu_tlb_add_flush_nosync(iova, granule, granule, true, cookie); diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 48b288ef74b4..eac760cdbb28 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -178,7 +178,8 @@ static void qcom_iommu_tlb_flush_leaf(unsigned long iova, size_t size, qcom_iommu_tlb_sync(cookie); } -static void qcom_iommu_tlb_add_page(unsigned long iova, size_t granule, +static void qcom_iommu_tlb_add_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) { qcom_iommu_tlb_inv_range_nosync(iova, granule, granule, true, cookie); diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index fe27d93c8ad9..6b1b8be3ebec 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -28,10 +28,10 @@ enum io_pgtable_fmt { * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual * address range. * @tlb_add_page: Optional callback to queue up leaf TLB invalidation for a - * single page. This function exists purely as an optimisation - * for IOMMUs that cannot batch TLB invalidation operations - * efficiently and are therefore better suited to issuing them - * early rather than deferring them until iommu_tlb_sync(). + * single page. IOMMUs that cannot batch TLB invalidation + * operations efficiently will typically issue them here, but + * others may decide to update the iommu_iotlb_gather structure + * and defer the invalidation until iommu_tlb_sync() instead. * * Note that these can all be called in atomic context and must therefore * not block. @@ -42,7 +42,8 @@ struct iommu_flush_ops { void *cookie); void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule, void *cookie); - void (*tlb_add_page)(unsigned long iova, size_t granule, void *cookie); + void (*tlb_add_page)(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie); }; /** @@ -209,11 +210,12 @@ io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova, } static inline void -io_pgtable_tlb_add_page(struct io_pgtable *iop, unsigned long iova, +io_pgtable_tlb_add_page(struct io_pgtable *iop, + struct iommu_iotlb_gather * gather, unsigned long iova, size_t granule) { if (iop->cfg.tlb->tlb_add_page) - iop->cfg.tlb->tlb_add_page(iova, granule, iop->cookie); + iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie); } /** -- GitLab From 2a8868f16e6b1987cf43f1f46d2a12b7b6ddcd88 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:12:24 +0100 Subject: [PATCH 1066/7155] iommu/arm-smmu-v3: Separate s/w and h/w views of prod and cons indexes In preparation for rewriting the command queue insertion code to use a new algorithm, separate the software and hardware views of the prod and cons indexes so that manipulating the software state doesn't automatically update the hardware state at the same time. No functional change. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index d1ebc7103065..06f569e41d84 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -697,17 +697,13 @@ static bool queue_empty(struct arm_smmu_queue *q) Q_WRP(q, q->prod) == Q_WRP(q, q->cons); } -static void queue_sync_cons(struct arm_smmu_queue *q) +static void queue_sync_cons_in(struct arm_smmu_queue *q) { q->cons = readl_relaxed(q->cons_reg); } -static void queue_inc_cons(struct arm_smmu_queue *q) +static void queue_sync_cons_out(struct arm_smmu_queue *q) { - u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; - - q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); - /* * Ensure that all CPU accesses (reads and writes) to the queue * are complete before we update the cons pointer. @@ -716,7 +712,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q) writel_relaxed(q->cons, q->cons_reg); } -static int queue_sync_prod(struct arm_smmu_queue *q) +static void queue_inc_cons(struct arm_smmu_queue *q) +{ + u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; + q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); +} + +static int queue_sync_prod_in(struct arm_smmu_queue *q) { int ret = 0; u32 prod = readl_relaxed(q->prod_reg); @@ -728,12 +730,15 @@ static int queue_sync_prod(struct arm_smmu_queue *q) return ret; } +static void queue_sync_prod_out(struct arm_smmu_queue *q) +{ + writel(q->prod, q->prod_reg); +} + static void queue_inc_prod(struct arm_smmu_queue *q) { u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1; - q->prod = Q_OVF(q, q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); - writel(q->prod, q->prod_reg); } /* @@ -750,7 +755,7 @@ static int queue_poll_cons(struct arm_smmu_queue *q, bool sync, bool wfe) ARM_SMMU_CMDQ_SYNC_TIMEOUT_US : ARM_SMMU_POLL_TIMEOUT_US); - while (queue_sync_cons(q), (sync ? !queue_empty(q) : queue_full(q))) { + while (queue_sync_cons_in(q), (sync ? !queue_empty(q) : queue_full(q))) { if (ktime_compare(ktime_get(), timeout) > 0) return -ETIMEDOUT; @@ -784,6 +789,7 @@ static int queue_insert_raw(struct arm_smmu_queue *q, u64 *ent) queue_write(Q_ENT(q, q->prod), ent, q->ent_dwords); queue_inc_prod(q); + queue_sync_prod_out(q); return 0; } @@ -802,6 +808,7 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent) queue_read(ent, Q_ENT(q, q->cons), q->ent_dwords); queue_inc_cons(q); + queue_sync_cons_out(q); return 0; } @@ -1322,7 +1329,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) * Not much we can do on overflow, so scream and pretend we're * trying harder. */ - if (queue_sync_prod(q) == -EOVERFLOW) + if (queue_sync_prod_in(q) == -EOVERFLOW) dev_err(smmu->dev, "EVTQ overflow detected -- events lost\n"); } while (!queue_empty(q)); @@ -1379,7 +1386,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) while (!queue_remove_raw(q, evt)) arm_smmu_handle_ppr(smmu, evt); - if (queue_sync_prod(q) == -EOVERFLOW) + if (queue_sync_prod_in(q) == -EOVERFLOW) dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n"); } while (!queue_empty(q)); @@ -1563,8 +1570,9 @@ static void arm_smmu_tlb_inv_context(void *cookie) /* * NOTE: when io-pgtable is in non-strict mode, we may get here with * PTEs previously cleared by unmaps on the current CPU not yet visible - * to the SMMU. We are relying on the DSB implicit in queue_inc_prod() - * to guarantee those are observed before the TLBI. Do be careful, 007. + * to the SMMU. We are relying on the DSB implicit in + * queue_sync_prod_out() to guarantee those are observed before the + * TLBI. Do be careful, 007. */ arm_smmu_cmdq_issue_cmd(smmu, &cmd); arm_smmu_cmdq_issue_sync(smmu); -- GitLab From 8a073da07bac169601a1874606e09bdb62811978 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:15:50 +0100 Subject: [PATCH 1067/7155] iommu/arm-smmu-v3: Drop unused 'q' argument from Q_OVF macro The Q_OVF macro doesn't need to access the arm_smmu_queue structure, so drop the unused macro argument. No functional change. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 06f569e41d84..3a8020795959 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -184,7 +184,7 @@ #define Q_IDX(q, p) ((p) & ((1 << (q)->max_n_shift) - 1)) #define Q_WRP(q, p) ((p) & (1 << (q)->max_n_shift)) #define Q_OVERFLOW_FLAG (1 << 31) -#define Q_OVF(q, p) ((p) & Q_OVERFLOW_FLAG) +#define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) #define Q_ENT(q, p) ((q)->base + \ Q_IDX(q, p) * (q)->ent_dwords) @@ -715,7 +715,7 @@ static void queue_sync_cons_out(struct arm_smmu_queue *q) static void queue_inc_cons(struct arm_smmu_queue *q) { u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; - q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); + q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); } static int queue_sync_prod_in(struct arm_smmu_queue *q) @@ -723,7 +723,7 @@ static int queue_sync_prod_in(struct arm_smmu_queue *q) int ret = 0; u32 prod = readl_relaxed(q->prod_reg); - if (Q_OVF(q, prod) != Q_OVF(q, q->prod)) + if (Q_OVF(prod) != Q_OVF(q->prod)) ret = -EOVERFLOW; q->prod = prod; @@ -738,7 +738,7 @@ static void queue_sync_prod_out(struct arm_smmu_queue *q) static void queue_inc_prod(struct arm_smmu_queue *q) { u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1; - q->prod = Q_OVF(q, q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); + q->prod = Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); } /* @@ -1334,7 +1334,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + q->cons = Q_OVF(q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); return IRQ_HANDLED; } @@ -1391,7 +1391,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + q->cons = Q_OVF(q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); writel(q->cons, q->cons_reg); return IRQ_HANDLED; } -- GitLab From 52be86374f48a0d34015257f3e06965910b5b774 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:16:08 +0100 Subject: [PATCH 1068/7155] iommu/arm-smmu-v3: Move low-level queue fields out of arm_smmu_queue In preparation for rewriting the command queue insertion code to use a new algorithm, introduce a new arm_smmu_ll_queue structure which contains only the information necessary to perform queue arithmetic for a queue and will later be extended so that we can perform complex atomic manipulation on some of the fields. No functional change. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 88 ++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 3a8020795959..cb1aa156974e 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -181,8 +181,8 @@ #define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1 #define ARM_SMMU_MEMATTR_OIWB 0xf -#define Q_IDX(q, p) ((p) & ((1 << (q)->max_n_shift) - 1)) -#define Q_WRP(q, p) ((p) & (1 << (q)->max_n_shift)) +#define Q_IDX(q, p) ((p) & ((1 << (q)->llq.max_n_shift) - 1)) +#define Q_WRP(q, p) ((p) & (1 << (q)->llq.max_n_shift)) #define Q_OVERFLOW_FLAG (1 << 31) #define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) #define Q_ENT(q, p) ((q)->base + \ @@ -478,7 +478,14 @@ struct arm_smmu_cmdq_ent { }; }; +struct arm_smmu_ll_queue { + u32 prod; + u32 cons; + u32 max_n_shift; +}; + struct arm_smmu_queue { + struct arm_smmu_ll_queue llq; int irq; /* Wired interrupt */ __le64 *base; @@ -486,9 +493,6 @@ struct arm_smmu_queue { u64 q_base; size_t ent_dwords; - u32 max_n_shift; - u32 prod; - u32 cons; u32 __iomem *prod_reg; u32 __iomem *cons_reg; @@ -687,19 +691,19 @@ static void parse_driver_options(struct arm_smmu_device *smmu) /* Low-level queue manipulation functions */ static bool queue_full(struct arm_smmu_queue *q) { - return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && - Q_WRP(q, q->prod) != Q_WRP(q, q->cons); + return Q_IDX(q, q->llq.prod) == Q_IDX(q, q->llq.cons) && + Q_WRP(q, q->llq.prod) != Q_WRP(q, q->llq.cons); } static bool queue_empty(struct arm_smmu_queue *q) { - return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && - Q_WRP(q, q->prod) == Q_WRP(q, q->cons); + return Q_IDX(q, q->llq.prod) == Q_IDX(q, q->llq.cons) && + Q_WRP(q, q->llq.prod) == Q_WRP(q, q->llq.cons); } static void queue_sync_cons_in(struct arm_smmu_queue *q) { - q->cons = readl_relaxed(q->cons_reg); + q->llq.cons = readl_relaxed(q->cons_reg); } static void queue_sync_cons_out(struct arm_smmu_queue *q) @@ -709,13 +713,13 @@ static void queue_sync_cons_out(struct arm_smmu_queue *q) * are complete before we update the cons pointer. */ mb(); - writel_relaxed(q->cons, q->cons_reg); + writel_relaxed(q->llq.cons, q->cons_reg); } static void queue_inc_cons(struct arm_smmu_queue *q) { - u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; - q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); + u32 cons = (Q_WRP(q, q->llq.cons) | Q_IDX(q, q->llq.cons)) + 1; + q->llq.cons = Q_OVF(q->llq.cons) | Q_WRP(q, cons) | Q_IDX(q, cons); } static int queue_sync_prod_in(struct arm_smmu_queue *q) @@ -723,22 +727,22 @@ static int queue_sync_prod_in(struct arm_smmu_queue *q) int ret = 0; u32 prod = readl_relaxed(q->prod_reg); - if (Q_OVF(prod) != Q_OVF(q->prod)) + if (Q_OVF(prod) != Q_OVF(q->llq.prod)) ret = -EOVERFLOW; - q->prod = prod; + q->llq.prod = prod; return ret; } static void queue_sync_prod_out(struct arm_smmu_queue *q) { - writel(q->prod, q->prod_reg); + writel(q->llq.prod, q->prod_reg); } static void queue_inc_prod(struct arm_smmu_queue *q) { - u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1; - q->prod = Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); + u32 prod = (Q_WRP(q, q->llq.prod) | Q_IDX(q, q->llq.prod)) + 1; + q->llq.prod = Q_OVF(q->llq.prod) | Q_WRP(q, prod) | Q_IDX(q, prod); } /* @@ -787,7 +791,7 @@ static int queue_insert_raw(struct arm_smmu_queue *q, u64 *ent) if (queue_full(q)) return -ENOSPC; - queue_write(Q_ENT(q, q->prod), ent, q->ent_dwords); + queue_write(Q_ENT(q, q->llq.prod), ent, q->ent_dwords); queue_inc_prod(q); queue_sync_prod_out(q); return 0; @@ -806,7 +810,7 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent) if (queue_empty(q)) return -EAGAIN; - queue_read(ent, Q_ENT(q, q->cons), q->ent_dwords); + queue_read(ent, Q_ENT(q, q->llq.cons), q->ent_dwords); queue_inc_cons(q); queue_sync_cons_out(q); return 0; @@ -1334,7 +1338,8 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + q->llq.cons = Q_OVF(q->llq.prod) | Q_WRP(q, q->llq.cons) | + Q_IDX(q, q->llq.cons); return IRQ_HANDLED; } @@ -1391,8 +1396,9 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); - writel(q->cons, q->cons_reg); + q->llq.cons = Q_OVF(q->llq.prod) | Q_WRP(q, q->llq.cons) | + Q_IDX(q, q->llq.cons); + writel(q->llq.cons, q->cons_reg); return IRQ_HANDLED; } @@ -2316,13 +2322,13 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, size_t qsz; do { - qsz = ((1 << q->max_n_shift) * dwords) << 3; + qsz = ((1 << q->llq.max_n_shift) * dwords) << 3; q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma, GFP_KERNEL); if (q->base || qsz < PAGE_SIZE) break; - q->max_n_shift--; + q->llq.max_n_shift--; } while (1); if (!q->base) { @@ -2334,7 +2340,7 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, if (!WARN_ON(q->base_dma & (qsz - 1))) { dev_info(smmu->dev, "allocated %u entries for %s\n", - 1 << q->max_n_shift, name); + 1 << q->llq.max_n_shift, name); } q->prod_reg = arm_smmu_page1_fixup(prod_off, smmu); @@ -2343,9 +2349,9 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, q->q_base = Q_BASE_RWA; q->q_base |= q->base_dma & Q_BASE_ADDR_MASK; - q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->max_n_shift); + q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->llq.max_n_shift); - q->prod = q->cons = 0; + q->llq.prod = q->llq.cons = 0; return 0; } @@ -2738,8 +2744,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) /* Command queue */ writeq_relaxed(smmu->cmdq.q.q_base, smmu->base + ARM_SMMU_CMDQ_BASE); - writel_relaxed(smmu->cmdq.q.prod, smmu->base + ARM_SMMU_CMDQ_PROD); - writel_relaxed(smmu->cmdq.q.cons, smmu->base + ARM_SMMU_CMDQ_CONS); + writel_relaxed(smmu->cmdq.q.llq.prod, smmu->base + ARM_SMMU_CMDQ_PROD); + writel_relaxed(smmu->cmdq.q.llq.cons, smmu->base + ARM_SMMU_CMDQ_CONS); enables = CR0_CMDQEN; ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, @@ -2766,9 +2772,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) /* Event queue */ writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE); - writel_relaxed(smmu->evtq.q.prod, + writel_relaxed(smmu->evtq.q.llq.prod, arm_smmu_page1_fixup(ARM_SMMU_EVTQ_PROD, smmu)); - writel_relaxed(smmu->evtq.q.cons, + writel_relaxed(smmu->evtq.q.llq.cons, arm_smmu_page1_fixup(ARM_SMMU_EVTQ_CONS, smmu)); enables |= CR0_EVTQEN; @@ -2783,9 +2789,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) if (smmu->features & ARM_SMMU_FEAT_PRI) { writeq_relaxed(smmu->priq.q.q_base, smmu->base + ARM_SMMU_PRIQ_BASE); - writel_relaxed(smmu->priq.q.prod, + writel_relaxed(smmu->priq.q.llq.prod, arm_smmu_page1_fixup(ARM_SMMU_PRIQ_PROD, smmu)); - writel_relaxed(smmu->priq.q.cons, + writel_relaxed(smmu->priq.q.llq.cons, arm_smmu_page1_fixup(ARM_SMMU_PRIQ_CONS, smmu)); enables |= CR0_PRIQEN; @@ -2939,18 +2945,18 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) } /* Queue sizes, capped to ensure natural alignment */ - smmu->cmdq.q.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, - FIELD_GET(IDR1_CMDQS, reg)); - if (!smmu->cmdq.q.max_n_shift) { + smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, + FIELD_GET(IDR1_CMDQS, reg)); + if (!smmu->cmdq.q.llq.max_n_shift) { /* Odd alignment restrictions on the base, so ignore for now */ dev_err(smmu->dev, "unit-length command queue not supported\n"); return -ENXIO; } - smmu->evtq.q.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT, - FIELD_GET(IDR1_EVTQS, reg)); - smmu->priq.q.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT, - FIELD_GET(IDR1_PRIQS, reg)); + smmu->evtq.q.llq.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT, + FIELD_GET(IDR1_EVTQS, reg)); + smmu->priq.q.llq.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT, + FIELD_GET(IDR1_PRIQS, reg)); /* SID/SSID sizes */ smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg); -- GitLab From 7c288a5b27934281d9ea8b5807bc727268b7001a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:16:16 +0100 Subject: [PATCH 1069/7155] iommu/arm-smmu-v3: Operate directly on low-level queue where possible In preparation for rewriting the command queue insertion code to use a new algorithm, rework many of our queue macro accessors and manipulation functions so that they operate on the arm_smmu_ll_queue structure where possible. This will allow us to call these helpers on local variables without having to construct a full-blown arm_smmu_queue on the stack. No functional change. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 58 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index cb1aa156974e..9ebb8b39a3b1 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -181,12 +181,13 @@ #define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1 #define ARM_SMMU_MEMATTR_OIWB 0xf -#define Q_IDX(q, p) ((p) & ((1 << (q)->llq.max_n_shift) - 1)) -#define Q_WRP(q, p) ((p) & (1 << (q)->llq.max_n_shift)) +#define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1)) +#define Q_WRP(llq, p) ((p) & (1 << (llq)->max_n_shift)) #define Q_OVERFLOW_FLAG (1 << 31) #define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) #define Q_ENT(q, p) ((q)->base + \ - Q_IDX(q, p) * (q)->ent_dwords) + Q_IDX(&((q)->llq), p) * \ + (q)->ent_dwords) #define Q_BASE_RWA (1UL << 62) #define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) @@ -689,16 +690,16 @@ static void parse_driver_options(struct arm_smmu_device *smmu) } /* Low-level queue manipulation functions */ -static bool queue_full(struct arm_smmu_queue *q) +static bool queue_full(struct arm_smmu_ll_queue *q) { - return Q_IDX(q, q->llq.prod) == Q_IDX(q, q->llq.cons) && - Q_WRP(q, q->llq.prod) != Q_WRP(q, q->llq.cons); + return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && + Q_WRP(q, q->prod) != Q_WRP(q, q->cons); } -static bool queue_empty(struct arm_smmu_queue *q) +static bool queue_empty(struct arm_smmu_ll_queue *q) { - return Q_IDX(q, q->llq.prod) == Q_IDX(q, q->llq.cons) && - Q_WRP(q, q->llq.prod) == Q_WRP(q, q->llq.cons); + return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && + Q_WRP(q, q->prod) == Q_WRP(q, q->cons); } static void queue_sync_cons_in(struct arm_smmu_queue *q) @@ -716,10 +717,10 @@ static void queue_sync_cons_out(struct arm_smmu_queue *q) writel_relaxed(q->llq.cons, q->cons_reg); } -static void queue_inc_cons(struct arm_smmu_queue *q) +static void queue_inc_cons(struct arm_smmu_ll_queue *q) { - u32 cons = (Q_WRP(q, q->llq.cons) | Q_IDX(q, q->llq.cons)) + 1; - q->llq.cons = Q_OVF(q->llq.cons) | Q_WRP(q, cons) | Q_IDX(q, cons); + u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; + q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); } static int queue_sync_prod_in(struct arm_smmu_queue *q) @@ -739,10 +740,10 @@ static void queue_sync_prod_out(struct arm_smmu_queue *q) writel(q->llq.prod, q->prod_reg); } -static void queue_inc_prod(struct arm_smmu_queue *q) +static void queue_inc_prod(struct arm_smmu_ll_queue *q) { - u32 prod = (Q_WRP(q, q->llq.prod) | Q_IDX(q, q->llq.prod)) + 1; - q->llq.prod = Q_OVF(q->llq.prod) | Q_WRP(q, prod) | Q_IDX(q, prod); + u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1; + q->prod = Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); } /* @@ -759,7 +760,8 @@ static int queue_poll_cons(struct arm_smmu_queue *q, bool sync, bool wfe) ARM_SMMU_CMDQ_SYNC_TIMEOUT_US : ARM_SMMU_POLL_TIMEOUT_US); - while (queue_sync_cons_in(q), (sync ? !queue_empty(q) : queue_full(q))) { + while (queue_sync_cons_in(q), + (sync ? !queue_empty(&q->llq) : queue_full(&q->llq))) { if (ktime_compare(ktime_get(), timeout) > 0) return -ETIMEDOUT; @@ -788,11 +790,11 @@ static void queue_write(__le64 *dst, u64 *src, size_t n_dwords) static int queue_insert_raw(struct arm_smmu_queue *q, u64 *ent) { - if (queue_full(q)) + if (queue_full(&q->llq)) return -ENOSPC; queue_write(Q_ENT(q, q->llq.prod), ent, q->ent_dwords); - queue_inc_prod(q); + queue_inc_prod(&q->llq); queue_sync_prod_out(q); return 0; } @@ -807,11 +809,11 @@ static void queue_read(__le64 *dst, u64 *src, size_t n_dwords) static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent) { - if (queue_empty(q)) + if (queue_empty(&q->llq)) return -EAGAIN; queue_read(ent, Q_ENT(q, q->llq.cons), q->ent_dwords); - queue_inc_cons(q); + queue_inc_cons(&q->llq); queue_sync_cons_out(q); return 0; } @@ -1316,6 +1318,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) int i; struct arm_smmu_device *smmu = dev; struct arm_smmu_queue *q = &smmu->evtq.q; + struct arm_smmu_ll_queue *llq = &q->llq; u64 evt[EVTQ_ENT_DWORDS]; do { @@ -1335,11 +1338,11 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) */ if (queue_sync_prod_in(q) == -EOVERFLOW) dev_err(smmu->dev, "EVTQ overflow detected -- events lost\n"); - } while (!queue_empty(q)); + } while (!queue_empty(llq)); /* Sync our overflow flag, as we believe we're up to speed */ - q->llq.cons = Q_OVF(q->llq.prod) | Q_WRP(q, q->llq.cons) | - Q_IDX(q, q->llq.cons); + llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | + Q_IDX(llq, llq->cons); return IRQ_HANDLED; } @@ -1385,6 +1388,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) { struct arm_smmu_device *smmu = dev; struct arm_smmu_queue *q = &smmu->priq.q; + struct arm_smmu_ll_queue *llq = &q->llq; u64 evt[PRIQ_ENT_DWORDS]; do { @@ -1393,12 +1397,12 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) if (queue_sync_prod_in(q) == -EOVERFLOW) dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n"); - } while (!queue_empty(q)); + } while (!queue_empty(llq)); /* Sync our overflow flag, as we believe we're up to speed */ - q->llq.cons = Q_OVF(q->llq.prod) | Q_WRP(q, q->llq.cons) | - Q_IDX(q, q->llq.cons); - writel(q->llq.cons, q->cons_reg); + llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | + Q_IDX(llq, llq->cons); + queue_sync_cons_out(q); return IRQ_HANDLED; } -- GitLab From c51ab067c5312695331129806cb9a42791903305 Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Mon, 29 Jul 2019 17:01:22 +0800 Subject: [PATCH 1070/7155] net: ag71xx: use resource_size for the ioremap size use resource_size to calcuate ioremap size and make the code simpler. Signed-off-by: Ding Xiang Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/ag71xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 8b69d0d7e726..77542bd1e5bd 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1686,7 +1686,7 @@ static int ag71xx_probe(struct platform_device *pdev) } ag->mac_base = devm_ioremap_nocache(&pdev->dev, res->start, - res->end - res->start + 1); + resource_size(res)); if (!ag->mac_base) { err = -ENOMEM; goto err_free; -- GitLab From 171a9bae68c72f2d1260c3825203760856e6793b Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Fri, 26 Jul 2019 10:44:25 -0700 Subject: [PATCH 1071/7155] staging/octeon: Allow test build on !MIPS Add compile test support by moving all includes of files under asm/octeon into octeon-ethernet.h, and if we're not on MIPS, stub out all the calls into the octeon support code in octeon-stubs.h Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/staging/octeon/Kconfig | 2 +- drivers/staging/octeon/ethernet-defines.h | 2 - drivers/staging/octeon/ethernet-mdio.c | 6 +- drivers/staging/octeon/ethernet-mem.c | 5 +- drivers/staging/octeon/ethernet-rgmii.c | 10 +- drivers/staging/octeon/ethernet-rx.c | 13 +- drivers/staging/octeon/ethernet-rx.h | 2 - drivers/staging/octeon/ethernet-sgmii.c | 8 +- drivers/staging/octeon/ethernet-spi.c | 10 +- drivers/staging/octeon/ethernet-tx.c | 12 +- drivers/staging/octeon/ethernet-util.h | 4 - drivers/staging/octeon/ethernet.c | 12 +- drivers/staging/octeon/octeon-ethernet.h | 29 +- drivers/staging/octeon/octeon-stubs.h | 1429 +++++++++++++++++++++ 14 files changed, 1466 insertions(+), 78 deletions(-) create mode 100644 drivers/staging/octeon/octeon-stubs.h diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 1e3012b9991c..5b3994649d99 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CAVIUM_OCTEON_SOC && NETDEVICES + depends on CAVIUM_OCTEON_SOC && NETDEVICES || COMPILE_TEST select PHYLIB select MDIO_OCTEON help diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 1e114422993a..ef9e767b0e2e 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -21,8 +21,6 @@ #ifndef __ETHERNET_DEFINES_H__ #define __ETHERNET_DEFINES_H__ -#include - #ifdef CONFIG_NETFILTER #define REUSE_SKBUFFS_WITHOUT_FREE 0 #else diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 2aee64fdaec5..ffac0c4b3f5c 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -13,15 +13,11 @@ #include #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-mdio.h" #include "ethernet-util.h" -#include - static void cvm_oct_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 0d26c4a93ec1..532594957ebc 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -9,13 +9,10 @@ #include #include -#include - +#include "octeon-ethernet.h" #include "ethernet-mem.h" #include "ethernet-defines.h" -#include - /** * cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs * @pool: Pool to allocate an skbuff for diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index c15376d33891..d91fd5ce9e68 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -12,19 +12,11 @@ #include #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" #include "ethernet-mdio.h" -#include - -#include -#include -#include - static DEFINE_SPINLOCK(global_register_lock); static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 5e271245273c..0e65955c746b 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -23,23 +23,12 @@ #include #endif /* CONFIG_XFRM */ -#include - +#include "octeon-ethernet.h" #include "ethernet-defines.h" #include "ethernet-mem.h" #include "ethernet-rx.h" -#include "octeon-ethernet.h" #include "ethernet-util.h" -#include -#include -#include -#include -#include -#include - -#include - static atomic_t oct_rx_ready = ATOMIC_INIT(0); static struct oct_rx_group { diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h index 096553d8fc99..ff6482fa20d6 100644 --- a/drivers/staging/octeon/ethernet-rx.h +++ b/drivers/staging/octeon/ethernet-rx.h @@ -5,8 +5,6 @@ * Copyright (c) 2003-2007 Cavium Networks */ -#include - void cvm_oct_poll_controller(struct net_device *dev); void cvm_oct_rx_initialize(void); void cvm_oct_rx_shutdown(void); diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index a4a8f094e2b4..d7fbd9159302 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -11,17 +11,11 @@ #include #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" #include "ethernet-mdio.h" -#include - -#include - int cvm_oct_sgmii_open(struct net_device *dev) { return cvm_oct_common_open(dev, cvm_oct_link_poll); diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 01efdf2a2c20..c582403e6a1f 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -10,18 +10,10 @@ #include #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-util.h" -#include - -#include -#include -#include - static int number_spi_ports; static int need_retrain[2] = { 0, 0 }; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 44f79cd32750..c64728fc21f2 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -22,21 +22,11 @@ #include #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-tx.h" #include "ethernet-util.h" -#include -#include -#include -#include -#include - -#include - #define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb)) /* diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 31a82873e15c..2af83a12ca78 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -5,10 +5,6 @@ * Copyright (c) 2003-2007 Cavium Networks */ -#include -#include -#include - /** * cvm_oct_get_buffer_ptr - convert packet data address to pointer * @packet_ptr: Packet data hardware address diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 8847a11c212f..8889494adf1f 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -19,24 +19,14 @@ #include -#include - -#include "ethernet-defines.h" #include "octeon-ethernet.h" +#include "ethernet-defines.h" #include "ethernet-mem.h" #include "ethernet-rx.h" #include "ethernet-tx.h" #include "ethernet-mdio.h" #include "ethernet-util.h" -#include -#include -#include -#include -#include -#include -#include - #define OCTEON_MAX_MTU 65392 static int num_packet_buffers = 1024; diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index be570d33685a..a8a864b40913 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -13,7 +13,34 @@ #include #include -#include + +#ifdef CONFIG_MIPS + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include "octeon-stubs.h" + +#endif /** * This is the definition of the Ethernet driver's private diff --git a/drivers/staging/octeon/octeon-stubs.h b/drivers/staging/octeon/octeon-stubs.h new file mode 100644 index 000000000000..a4ac3bfb62a8 --- /dev/null +++ b/drivers/staging/octeon/octeon-stubs.h @@ -0,0 +1,1429 @@ +#define CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 512 +#define XKPHYS_TO_PHYS(p) (p) + +#define OCTEON_IRQ_WORKQ0 0 +#define OCTEON_IRQ_RML 0 +#define OCTEON_IRQ_TIMER1 0 +#define OCTEON_IS_MODEL(x) 0 +#define octeon_has_feature(x) 0 +#define octeon_get_clock_rate() 0 + +#define CVMX_SYNCIOBDMA do { } while(0) + +#define CVMX_HELPER_INPUT_TAG_TYPE 0 +#define CVMX_HELPER_FIRST_MBUFF_SKIP 7 +#define CVMX_FAU_REG_END (2048) +#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) +#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 16 +#define CVMX_FPA_PACKET_POOL (0) +#define CVMX_FPA_PACKET_POOL_SIZE 16 +#define CVMX_FPA_WQE_POOL (1) +#define CVMX_FPA_WQE_POOL_SIZE 16 +#define CVMX_GMXX_RXX_ADR_CAM_EN(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CTL(a, b) ((a)+(b)) +#define CVMX_GMXX_PRTX_CFG(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_FRM_MAX(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_JABBER(a, b) ((a)+(b)) +#define CVMX_IPD_CTL_STATUS 0 +#define CVMX_PIP_FRM_LEN_CHKX(a) (a) +#define CVMX_PIP_NUM_INPUT_PORTS 1 +#define CVMX_SCR_SCRATCH 0 +#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 2 +#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 2 +#define CVMX_IPD_SUB_PORT_FCS 0 +#define CVMX_SSO_WQ_IQ_DIS 0 +#define CVMX_SSO_WQ_INT 0 +#define CVMX_POW_WQ_INT 0 +#define CVMX_SSO_WQ_INT_PC 0 +#define CVMX_NPI_RSL_INT_BLOCKS 0 +#define CVMX_POW_WQ_INT_PC 0 + +typedef union { + uint64_t u64; + struct { + uint64_t bufs:8; + uint64_t ip_offset:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t pr:4; + uint64_t unassigned2:8; + uint64_t dec_ipcomp:1; + uint64_t tcp_or_udp:1; + uint64_t dec_ipsec:1; + uint64_t is_v6:1; + uint64_t software:1; + uint64_t L4_error:1; + uint64_t is_frag:1; + uint64_t IP_exc:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } s; + struct { + uint64_t bufs:8; + uint64_t ip_offset:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t port:12; + uint64_t dec_ipcomp:1; + uint64_t tcp_or_udp:1; + uint64_t dec_ipsec:1; + uint64_t is_v6:1; + uint64_t software:1; + uint64_t L4_error:1; + uint64_t is_frag:1; + uint64_t IP_exc:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } s_cn68xx; + + struct { + uint64_t unused1:16; + uint64_t vlan:16; + uint64_t unused2:32; + } svlan; + struct { + uint64_t bufs:8; + uint64_t unused:8; + uint64_t vlan_valid:1; + uint64_t vlan_stacked:1; + uint64_t unassigned:1; + uint64_t vlan_cfi:1; + uint64_t vlan_id:12; + uint64_t pr:4; + uint64_t unassigned2:12; + uint64_t software:1; + uint64_t unassigned3:1; + uint64_t is_rarp:1; + uint64_t is_arp:1; + uint64_t is_bcast:1; + uint64_t is_mcast:1; + uint64_t not_IP:1; + uint64_t rcv_error:1; + uint64_t err_code:8; + } snoip; + +} cvmx_pip_wqe_word2; + +union cvmx_pip_wqe_word0 { + struct { + uint64_t next_ptr:40; + uint8_t unused; + uint16_t hw_chksum; + } cn38xx; + struct { + uint64_t pknd:6; /* 0..5 */ + uint64_t unused2:2; /* 6..7 */ + uint64_t bpid:6; /* 8..13 */ + uint64_t unused1:18; /* 14..31 */ + uint64_t l2ptr:8; /* 32..39 */ + uint64_t l3ptr:8; /* 40..47 */ + uint64_t unused0:8; /* 48..55 */ + uint64_t l4ptr:8; /* 56..63 */ + } cn68xx; +}; + +union cvmx_wqe_word0 { + uint64_t u64; + union cvmx_pip_wqe_word0 pip; +}; + +union cvmx_wqe_word1 { + uint64_t u64; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t varies:14; + uint64_t len:16; + }; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t zero_2:3; + uint64_t grp:6; + uint64_t zero_1:1; + uint64_t qos:3; + uint64_t zero_0:1; + uint64_t len:16; + } cn68xx; + struct { + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t zero_2:1; + uint64_t grp:4; + uint64_t qos:3; + uint64_t ipprt:6; + uint64_t len:16; + } cn38xx; +}; + +union cvmx_buf_ptr { + void *ptr; + uint64_t u64; + struct { + uint64_t i:1; + uint64_t back:4; + uint64_t pool:3; + uint64_t size:16; + uint64_t addr:40; + } s; +}; + +typedef struct { + union cvmx_wqe_word0 word0; + union cvmx_wqe_word1 word1; + cvmx_pip_wqe_word2 word2; + union cvmx_buf_ptr packet_ptr; + uint8_t packet_data[96]; +} cvmx_wqe_t; + +typedef union { + uint64_t u64; + struct { + uint64_t reserved_20_63:44; + uint64_t link_up:1; /**< Is the physical link up? */ + uint64_t full_duplex:1; /**< 1 if the link is full duplex */ + uint64_t speed:18; /**< Speed of the link in Mbps */ + } s; +} cvmx_helper_link_info_t; + +typedef enum { + CVMX_FAU_REG_32_START = 0, +} cvmx_fau_reg_32_t; + +typedef enum { + CVMX_FAU_OP_SIZE_8 = 0, + CVMX_FAU_OP_SIZE_16 = 1, + CVMX_FAU_OP_SIZE_32 = 2, + CVMX_FAU_OP_SIZE_64 = 3 +} cvmx_fau_op_size_t; + +typedef enum { + CVMX_SPI_MODE_UNKNOWN = 0, + CVMX_SPI_MODE_TX_HALFPLEX = 1, + CVMX_SPI_MODE_RX_HALFPLEX = 2, + CVMX_SPI_MODE_DUPLEX = 3 +} cvmx_spi_mode_t; + +typedef enum { + CVMX_HELPER_INTERFACE_MODE_DISABLED, + CVMX_HELPER_INTERFACE_MODE_RGMII, + CVMX_HELPER_INTERFACE_MODE_GMII, + CVMX_HELPER_INTERFACE_MODE_SPI, + CVMX_HELPER_INTERFACE_MODE_PCIE, + CVMX_HELPER_INTERFACE_MODE_XAUI, + CVMX_HELPER_INTERFACE_MODE_SGMII, + CVMX_HELPER_INTERFACE_MODE_PICMG, + CVMX_HELPER_INTERFACE_MODE_NPI, + CVMX_HELPER_INTERFACE_MODE_LOOP, +} cvmx_helper_interface_mode_t; + +typedef enum { + CVMX_POW_WAIT = 1, + CVMX_POW_NO_WAIT = 0, +} cvmx_pow_wait_t; + +typedef enum { + CVMX_PKO_LOCK_NONE = 0, + CVMX_PKO_LOCK_ATOMIC_TAG = 1, + CVMX_PKO_LOCK_CMD_QUEUE = 2, +} cvmx_pko_lock_t; + +typedef enum { + CVMX_PKO_SUCCESS, + CVMX_PKO_INVALID_PORT, + CVMX_PKO_INVALID_QUEUE, + CVMX_PKO_INVALID_PRIORITY, + CVMX_PKO_NO_MEMORY, + CVMX_PKO_PORT_ALREADY_SETUP, + CVMX_PKO_CMD_QUEUE_INIT_ERROR +} cvmx_pko_status_t; + +enum cvmx_pow_tag_type { + CVMX_POW_TAG_TYPE_ORDERED = 0L, + CVMX_POW_TAG_TYPE_ATOMIC = 1L, + CVMX_POW_TAG_TYPE_NULL = 2L, + CVMX_POW_TAG_TYPE_NULL_NULL = 3L +}; + +union cvmx_ipd_ctl_status { + uint64_t u64; + struct cvmx_ipd_ctl_status_s { + uint64_t reserved_18_63:46; + uint64_t use_sop:1; + uint64_t rst_done:1; + uint64_t clken:1; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } s; + struct cvmx_ipd_ctl_status_cn30xx { + uint64_t reserved_10_63:54; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn30xx; + struct cvmx_ipd_ctl_status_cn38xxp2 { + uint64_t reserved_9_63:55; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn38xxp2; + struct cvmx_ipd_ctl_status_cn50xx { + uint64_t reserved_15_63:49; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn50xx; + struct cvmx_ipd_ctl_status_cn58xx { + uint64_t reserved_12_63:52; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn58xx; + struct cvmx_ipd_ctl_status_cn63xxp1 { + uint64_t reserved_16_63:48; + uint64_t clken:1; + uint64_t no_wptr:1; + uint64_t pq_apkt:1; + uint64_t pq_nabuf:1; + uint64_t ipd_full:1; + uint64_t pkt_off:1; + uint64_t len_m8:1; + uint64_t reset:1; + uint64_t addpkt:1; + uint64_t naddbuf:1; + uint64_t pkt_lend:1; + uint64_t wqe_lend:1; + uint64_t pbp_en:1; + uint64_t opc_mode:2; + uint64_t ipd_en:1; + } cn63xxp1; +}; + +union cvmx_ipd_sub_port_fcs { + uint64_t u64; + struct cvmx_ipd_sub_port_fcs_s { + uint64_t port_bit:32; + uint64_t reserved_32_35:4; + uint64_t port_bit2:4; + uint64_t reserved_40_63:24; + } s; + struct cvmx_ipd_sub_port_fcs_cn30xx { + uint64_t port_bit:3; + uint64_t reserved_3_63:61; + } cn30xx; + struct cvmx_ipd_sub_port_fcs_cn38xx { + uint64_t port_bit:32; + uint64_t reserved_32_63:32; + } cn38xx; +}; + +union cvmx_ipd_sub_port_qos_cnt { + uint64_t u64; + struct cvmx_ipd_sub_port_qos_cnt_s { + uint64_t cnt:32; + uint64_t port_qos:9; + uint64_t reserved_41_63:23; + } s; +}; +typedef struct { + uint32_t dropped_octets; + uint32_t dropped_packets; + uint32_t pci_raw_packets; + uint32_t octets; + uint32_t packets; + uint32_t multicast_packets; + uint32_t broadcast_packets; + uint32_t len_64_packets; + uint32_t len_65_127_packets; + uint32_t len_128_255_packets; + uint32_t len_256_511_packets; + uint32_t len_512_1023_packets; + uint32_t len_1024_1518_packets; + uint32_t len_1519_max_packets; + uint32_t fcs_align_err_packets; + uint32_t runt_packets; + uint32_t runt_crc_packets; + uint32_t oversize_packets; + uint32_t oversize_crc_packets; + uint32_t inb_packets; + uint64_t inb_octets; + uint16_t inb_errors; +} cvmx_pip_port_status_t; + +typedef struct { + uint32_t packets; + uint64_t octets; + uint64_t doorbell; +} cvmx_pko_port_status_t; + +union cvmx_pip_frm_len_chkx { + uint64_t u64; + struct cvmx_pip_frm_len_chkx_s { + uint64_t reserved_32_63:32; + uint64_t maxlen:16; + uint64_t minlen:16; + } s; +}; + +union cvmx_gmxx_rxx_frm_ctl { + uint64_t u64; + struct cvmx_gmxx_rxx_frm_ctl_s { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_11:1; + uint64_t ptp_mode:1; + uint64_t reserved_13_63:51; + } s; + struct cvmx_gmxx_rxx_frm_ctl_cn30xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t reserved_9_63:55; + } cn30xx; + struct cvmx_gmxx_rxx_frm_ctl_cn31xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t reserved_8_63:56; + } cn31xx; + struct cvmx_gmxx_rxx_frm_ctl_cn50xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_63:53; + } cn50xx; + struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t reserved_10_63:54; + } cn56xxp1; + struct cvmx_gmxx_rxx_frm_ctl_cn58xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t vlan_len:1; + uint64_t pad_len:1; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_63:53; + } cn58xx; + struct cvmx_gmxx_rxx_frm_ctl_cn61xx { + uint64_t pre_chk:1; + uint64_t pre_strp:1; + uint64_t ctl_drp:1; + uint64_t ctl_bck:1; + uint64_t ctl_mcst:1; + uint64_t ctl_smac:1; + uint64_t pre_free:1; + uint64_t reserved_7_8:2; + uint64_t pre_align:1; + uint64_t null_dis:1; + uint64_t reserved_11_11:1; + uint64_t ptp_mode:1; + uint64_t reserved_13_63:51; + } cn61xx; +}; + +union cvmx_gmxx_rxx_int_reg { + uint64_t u64; + struct cvmx_gmxx_rxx_int_reg_s { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } s; + struct cvmx_gmxx_rxx_int_reg_cn30xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t reserved_19_63:45; + } cn30xx; + struct cvmx_gmxx_rxx_int_reg_cn50xx { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t reserved_6_6:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t reserved_20_63:44; + } cn50xx; + struct cvmx_gmxx_rxx_int_reg_cn52xx { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } cn52xx; + struct cvmx_gmxx_rxx_int_reg_cn56xxp1 { + uint64_t reserved_0_0:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t reserved_27_63:37; + } cn56xxp1; + struct cvmx_gmxx_rxx_int_reg_cn58xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t maxerr:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t alnerr:1; + uint64_t lenerr:1; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t niberr:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t phy_link:1; + uint64_t phy_spd:1; + uint64_t phy_dupx:1; + uint64_t pause_drp:1; + uint64_t reserved_20_63:44; + } cn58xx; + struct cvmx_gmxx_rxx_int_reg_cn61xx { + uint64_t minerr:1; + uint64_t carext:1; + uint64_t reserved_2_2:1; + uint64_t jabber:1; + uint64_t fcserr:1; + uint64_t reserved_5_6:2; + uint64_t rcverr:1; + uint64_t skperr:1; + uint64_t reserved_9_9:1; + uint64_t ovrerr:1; + uint64_t pcterr:1; + uint64_t rsverr:1; + uint64_t falerr:1; + uint64_t coldet:1; + uint64_t ifgerr:1; + uint64_t reserved_16_18:3; + uint64_t pause_drp:1; + uint64_t loc_fault:1; + uint64_t rem_fault:1; + uint64_t bad_seq:1; + uint64_t bad_term:1; + uint64_t unsop:1; + uint64_t uneop:1; + uint64_t undat:1; + uint64_t hg2fld:1; + uint64_t hg2cc:1; + uint64_t reserved_29_63:35; + } cn61xx; +}; + +union cvmx_gmxx_prtx_cfg { + uint64_t u64; + struct cvmx_gmxx_prtx_cfg_s { + uint64_t reserved_22_63:42; + uint64_t pknd:6; + uint64_t reserved_14_15:2; + uint64_t tx_idle:1; + uint64_t rx_idle:1; + uint64_t reserved_9_11:3; + uint64_t speed_msb:1; + uint64_t reserved_4_7:4; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } s; + struct cvmx_gmxx_prtx_cfg_cn30xx { + uint64_t reserved_4_63:60; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } cn30xx; + struct cvmx_gmxx_prtx_cfg_cn52xx { + uint64_t reserved_14_63:50; + uint64_t tx_idle:1; + uint64_t rx_idle:1; + uint64_t reserved_9_11:3; + uint64_t speed_msb:1; + uint64_t reserved_4_7:4; + uint64_t slottime:1; + uint64_t duplex:1; + uint64_t speed:1; + uint64_t en:1; + } cn52xx; +}; + +union cvmx_gmxx_rxx_adr_ctl { + uint64_t u64; + struct cvmx_gmxx_rxx_adr_ctl_s { + uint64_t reserved_4_63:60; + uint64_t cam_mode:1; + uint64_t mcst:2; + uint64_t bcst:1; + } s; +}; + +union cvmx_pip_prt_tagx { + uint64_t u64; + struct cvmx_pip_prt_tagx_s { + uint64_t reserved_54_63:10; + uint64_t portadd_en:1; + uint64_t inc_hwchk:1; + uint64_t reserved_50_51:2; + uint64_t grptagbase_msb:2; + uint64_t reserved_46_47:2; + uint64_t grptagmask_msb:2; + uint64_t reserved_42_43:2; + uint64_t grp_msb:2; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t grptag_mskip:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } s; + struct cvmx_pip_prt_tagx_cn30xx { + uint64_t reserved_40_63:24; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t reserved_30_30:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } cn30xx; + struct cvmx_pip_prt_tagx_cn50xx { + uint64_t reserved_40_63:24; + uint64_t grptagbase:4; + uint64_t grptagmask:4; + uint64_t grptag:1; + uint64_t grptag_mskip:1; + uint64_t tag_mode:2; + uint64_t inc_vs:2; + uint64_t inc_vlan:1; + uint64_t inc_prt_flag:1; + uint64_t ip6_dprt_flag:1; + uint64_t ip4_dprt_flag:1; + uint64_t ip6_sprt_flag:1; + uint64_t ip4_sprt_flag:1; + uint64_t ip6_nxth_flag:1; + uint64_t ip4_pctl_flag:1; + uint64_t ip6_dst_flag:1; + uint64_t ip4_dst_flag:1; + uint64_t ip6_src_flag:1; + uint64_t ip4_src_flag:1; + uint64_t tcp6_tag_type:2; + uint64_t tcp4_tag_type:2; + uint64_t ip6_tag_type:2; + uint64_t ip4_tag_type:2; + uint64_t non_tag_type:2; + uint64_t grp:4; + } cn50xx; +}; + +union cvmx_spxx_int_reg { + uint64_t u64; + struct cvmx_spxx_int_reg_s { + uint64_t reserved_32_63:32; + uint64_t spf:1; + uint64_t reserved_12_30:19; + uint64_t calerr:1; + uint64_t syncerr:1; + uint64_t diperr:1; + uint64_t tpaovr:1; + uint64_t rsverr:1; + uint64_t drwnng:1; + uint64_t clserr:1; + uint64_t spiovr:1; + uint64_t reserved_2_3:2; + uint64_t abnorm:1; + uint64_t prtnxa:1; + } s; +}; + +union cvmx_spxx_int_msk { + uint64_t u64; + struct cvmx_spxx_int_msk_s { + uint64_t reserved_12_63:52; + uint64_t calerr:1; + uint64_t syncerr:1; + uint64_t diperr:1; + uint64_t tpaovr:1; + uint64_t rsverr:1; + uint64_t drwnng:1; + uint64_t clserr:1; + uint64_t spiovr:1; + uint64_t reserved_2_3:2; + uint64_t abnorm:1; + uint64_t prtnxa:1; + } s; +}; + +union cvmx_pow_wq_int { + uint64_t u64; + struct cvmx_pow_wq_int_s { + uint64_t wq_int:16; + uint64_t iq_dis:16; + uint64_t reserved_32_63:32; + } s; +}; + +union cvmx_sso_wq_int_thrx { + uint64_t u64; + struct { + uint64_t iq_thr:12; + uint64_t reserved_12_13:2; + uint64_t ds_thr:12; + uint64_t reserved_26_27:2; + uint64_t tc_thr:4; + uint64_t tc_en:1; + uint64_t reserved_33_63:31; + } s; +}; + +union cvmx_stxx_int_reg { + uint64_t u64; + struct cvmx_stxx_int_reg_s { + uint64_t reserved_9_63:55; + uint64_t syncerr:1; + uint64_t frmerr:1; + uint64_t unxfrm:1; + uint64_t nosync:1; + uint64_t diperr:1; + uint64_t datovr:1; + uint64_t ovrbst:1; + uint64_t calpar1:1; + uint64_t calpar0:1; + } s; +}; + +union cvmx_stxx_int_msk { + uint64_t u64; + struct cvmx_stxx_int_msk_s { + uint64_t reserved_8_63:56; + uint64_t frmerr:1; + uint64_t unxfrm:1; + uint64_t nosync:1; + uint64_t diperr:1; + uint64_t datovr:1; + uint64_t ovrbst:1; + uint64_t calpar1:1; + uint64_t calpar0:1; + } s; +}; + +union cvmx_pow_wq_int_pc { + uint64_t u64; + struct cvmx_pow_wq_int_pc_s { + uint64_t reserved_0_7:8; + uint64_t pc_thr:20; + uint64_t reserved_28_31:4; + uint64_t pc:28; + uint64_t reserved_60_63:4; + } s; +}; + +union cvmx_pow_wq_int_thrx { + uint64_t u64; + struct cvmx_pow_wq_int_thrx_s { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_23_23:1; + uint64_t ds_thr:11; + uint64_t reserved_11_11:1; + uint64_t iq_thr:11; + } s; + struct cvmx_pow_wq_int_thrx_cn30xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_18_23:6; + uint64_t ds_thr:6; + uint64_t reserved_6_11:6; + uint64_t iq_thr:6; + } cn30xx; + struct cvmx_pow_wq_int_thrx_cn31xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_20_23:4; + uint64_t ds_thr:8; + uint64_t reserved_8_11:4; + uint64_t iq_thr:8; + } cn31xx; + struct cvmx_pow_wq_int_thrx_cn52xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_21_23:3; + uint64_t ds_thr:9; + uint64_t reserved_9_11:3; + uint64_t iq_thr:9; + } cn52xx; + struct cvmx_pow_wq_int_thrx_cn63xx { + uint64_t reserved_29_63:35; + uint64_t tc_en:1; + uint64_t tc_thr:4; + uint64_t reserved_22_23:2; + uint64_t ds_thr:10; + uint64_t reserved_10_11:2; + uint64_t iq_thr:10; + } cn63xx; +}; + +union cvmx_npi_rsl_int_blocks { + uint64_t u64; + struct cvmx_npi_rsl_int_blocks_s { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t reserved_28_29:2; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t reserved_13_14:2; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } s; + struct cvmx_npi_rsl_int_blocks_cn30xx { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t rint_29:1; + uint64_t rint_28:1; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t rint_14:1; + uint64_t usb:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn30xx; + struct cvmx_npi_rsl_int_blocks_cn38xx { + uint64_t reserved_32_63:32; + uint64_t rint_31:1; + uint64_t iob:1; + uint64_t rint_29:1; + uint64_t rint_28:1; + uint64_t rint_27:1; + uint64_t rint_26:1; + uint64_t rint_25:1; + uint64_t rint_24:1; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t rint_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t rint_15:1; + uint64_t rint_14:1; + uint64_t rint_13:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t rint_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn38xx; + struct cvmx_npi_rsl_int_blocks_cn50xx { + uint64_t reserved_31_63:33; + uint64_t iob:1; + uint64_t lmc1:1; + uint64_t agl:1; + uint64_t reserved_24_27:4; + uint64_t asx1:1; + uint64_t asx0:1; + uint64_t reserved_21_21:1; + uint64_t pip:1; + uint64_t spx1:1; + uint64_t spx0:1; + uint64_t lmc:1; + uint64_t l2c:1; + uint64_t reserved_15_15:1; + uint64_t rad:1; + uint64_t usb:1; + uint64_t pow:1; + uint64_t tim:1; + uint64_t pko:1; + uint64_t ipd:1; + uint64_t reserved_8_8:1; + uint64_t zip:1; + uint64_t dfa:1; + uint64_t fpa:1; + uint64_t key:1; + uint64_t npi:1; + uint64_t gmx1:1; + uint64_t gmx0:1; + uint64_t mio:1; + } cn50xx; +}; + +typedef union { + uint64_t u64; + struct { + uint64_t total_bytes:16; + uint64_t segs:6; + uint64_t dontfree:1; + uint64_t ignore_i:1; + uint64_t ipoffp1:7; + uint64_t gather:1; + uint64_t rsp:1; + uint64_t wqp:1; + uint64_t n2:1; + uint64_t le:1; + uint64_t reg0:11; + uint64_t subone0:1; + uint64_t reg1:11; + uint64_t subone1:1; + uint64_t size0:2; + uint64_t size1:2; + } s; +} cvmx_pko_command_word0_t; + +union cvmx_ciu_timx { + uint64_t u64; + struct cvmx_ciu_timx_s { + uint64_t reserved_37_63:27; + uint64_t one_shot:1; + uint64_t len:36; + } s; +}; + +union cvmx_gmxx_rxx_rx_inbnd { + uint64_t u64; + struct cvmx_gmxx_rxx_rx_inbnd_s { + uint64_t status:1; + uint64_t speed:2; + uint64_t duplex:1; + uint64_t reserved_4_63:60; + } s; +}; + +static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, + int32_t value) +{ + return value; +} + +static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) +{ } + +static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) +{ } + +static inline uint64_t cvmx_scratch_read64(uint64_t address) +{ + return 0; +} + +static inline void cvmx_scratch_write64(uint64_t address, uint64_t value) +{ } + +static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work) +{ + return 0; +} + +static inline void *cvmx_phys_to_ptr(uint64_t physical_address) +{ + return (void *)(physical_address); +} + +static inline uint64_t cvmx_ptr_to_phys(void *ptr) +{ + return (unsigned long)ptr; +} + +static inline int cvmx_helper_get_interface_num(int ipd_port) +{ + return ipd_port; +} + +static inline int cvmx_helper_get_interface_index_num(int ipd_port) +{ + return ipd_port; +} + +static inline void cvmx_fpa_enable(void) +{ } + +static inline uint64_t cvmx_read_csr(uint64_t csr_addr) +{ + return 0; +} + +static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) +{ } + +static inline int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) +{ + return 0; +} + +static inline void *cvmx_fpa_alloc(uint64_t pool) +{ + return NULL; +} + +static inline void cvmx_fpa_free(void *ptr, uint64_t pool, + uint64_t num_cache_lines) +{ } + +static inline int octeon_is_simulation(void) +{ + return 1; +} + +static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, + cvmx_pip_port_status_t *status) +{ } + +static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, + cvmx_pko_port_status_t *status) +{ } + +static inline cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int + interface) +{ + return 0; +} + +static inline cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) +{ + cvmx_helper_link_info_t ret = { .u64 = 0 }; + + return ret; +} + +static inline int cvmx_helper_link_set(int ipd_port, + cvmx_helper_link_info_t link_info) +{ + return 0; +} + +static inline int cvmx_helper_initialize_packet_io_global(void) +{ + return 0; +} + +static inline int cvmx_helper_get_number_of_interfaces(void) +{ + return 2; +} + +static inline int cvmx_helper_ports_on_interface(int interface) +{ + return 1; +} + +static inline int cvmx_helper_get_ipd_port(int interface, int port) +{ + return 0; +} + +static inline int cvmx_helper_ipd_and_packet_input_enable(void) +{ + return 0; +} + +static inline void cvmx_ipd_disable(void) +{ } + +static inline void cvmx_ipd_free_ptr(void) +{ } + +static inline void cvmx_pko_disable(void) +{ } + +static inline void cvmx_pko_shutdown(void) +{ } + +static inline int cvmx_pko_get_base_queue_per_core(int port, int core) +{ + return port; +} + +static inline int cvmx_pko_get_base_queue(int port) +{ + return port; +} + +static inline int cvmx_pko_get_num_queues(int port) +{ + return port; +} + +static inline unsigned int cvmx_get_core_num(void) +{ + return 0; +} + +static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, + cvmx_pow_wait_t wait) +{ } + +static inline void cvmx_pow_work_request_async(int scr_addr, + cvmx_pow_wait_t wait) +{ } + +static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr) +{ + cvmx_wqe_t *wqe = (void *)(unsigned long)scr_addr; + + return wqe; +} + +static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait) +{ + return (void *)(unsigned long)wait; +} + +static inline int cvmx_spi_restart_interface(int interface, + cvmx_spi_mode_t mode, int timeout) +{ + return 0; +} + +static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr, + cvmx_fau_reg_32_t reg, + int32_t value) +{ } + +static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed( + int interface, + int port) +{ + union cvmx_gmxx_rxx_rx_inbnd r; + r.u64 = 0; + return r; +} + +static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, + cvmx_pko_lock_t use_locking) +{ } + +static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(uint64_t port, + uint64_t queue, cvmx_pko_command_word0_t pko_command, + union cvmx_buf_ptr packet, cvmx_pko_lock_t use_locking) +{ + cvmx_pko_status_t ret = 0; + + return ret; +} + +static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port) +{ } + +static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos) +{ } + +static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work) +{ + return 0; +} + +static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp) +{ } + +static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag, + enum cvmx_pow_tag_type tag_type, + uint64_t qos, uint64_t grp) +{ } + +#define CVMX_ASXX_RX_CLK_SETX(a, b) ((a)+(b)) +#define CVMX_ASXX_TX_CLK_SETX(a, b) ((a)+(b)) +#define CVMX_CIU_TIMX(a) (a) +#define CVMX_GMXX_RXX_ADR_CAM0(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM1(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM2(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM3(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM4(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_ADR_CAM5(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_FRM_CTL(a, b) ((a)+(b)) +#define CVMX_GMXX_RXX_INT_REG(a, b) ((a)+(b)) +#define CVMX_GMXX_SMACX(a, b) ((a)+(b)) +#define CVMX_PIP_PRT_TAGX(a) (a) +#define CVMX_POW_PP_GRP_MSKX(a) (a) +#define CVMX_POW_WQ_INT_THRX(a) (a) +#define CVMX_SPXX_INT_MSK(a) (a) +#define CVMX_SPXX_INT_REG(a) (a) +#define CVMX_SSO_PPX_GRP_MSK(a) (a) +#define CVMX_SSO_WQ_INT_THRX(a) (a) +#define CVMX_STXX_INT_MSK(a) (a) +#define CVMX_STXX_INT_REG(a) (a) -- GitLab From ef14358546b115d9ea4108f21c6badd97334ad18 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 28 Jul 2019 11:25:19 +0200 Subject: [PATCH 1072/7155] r8169: make use of xmit_more There was a previous attempt to use xmit_more, but the change had to be reverted because under load sometimes a transmit timeout occurred [0]. Maybe this was caused by a missing memory barrier, the new attempt keeps the memory barrier before the call to netif_stop_queue like it is used by the driver as of today. The new attempt also changes the order of some calls as suggested by Eric. [0] https://lkml.org/lkml/2019/2/10/39 Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 61a23aee0eef..109779e449cd 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5641,6 +5641,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, struct device *d = tp_to_dev(tp); dma_addr_t mapping; u32 opts[2], len; + bool stop_queue; + bool door_bell; int frags; if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { @@ -5684,13 +5686,13 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); - netdev_sent_queue(dev, skb->len); - skb_tx_timestamp(skb); /* Force memory writes to complete before releasing descriptor */ dma_wmb(); + door_bell = __netdev_sent_queue(dev, skb->len, netdev_xmit_more()); + txd->opts1 = rtl8169_get_txd_opts1(opts[0], len, entry); /* Force all memory writes to complete before notifying device */ @@ -5698,14 +5700,19 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->cur_tx += frags + 1; - RTL_W8(tp, TxPoll, NPQ); - - if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) { + stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS); + if (unlikely(stop_queue)) { /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must * not miss a ring update when it notices a stopped queue. */ smp_wmb(); netif_stop_queue(dev); + } + + if (door_bell) + RTL_W8(tp, TxPoll, NPQ); + + if (unlikely(stop_queue)) { /* Sync with rtl_tx: * - publish queue status and cur_tx ring index (write barrier) * - refresh dirty_tx ring index (read barrier). -- GitLab From 1cb9dfca39eb406960f8f84864ddd6ba329ec321 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 22 Jul 2019 23:37:26 +0000 Subject: [PATCH 1073/7155] net: dsa: mv88e6xxx: avoid some redundant vtu load/purge operations We have an ERPS (Ethernet Ring Protection Switching) setup involving mv88e6250 switches which we're in the process of switching to a BSP based on the mainline driver. Breaking any link in the ring works as expected, with the ring reconfiguring itself quickly and traffic continuing with almost no noticable drops. However, when plugging back the cable, we see 5+ second stalls. This has been tracked down to the userspace application in charge of the protocol missing a few CCM messages on the good link (the one that was not unplugged), causing it to broadcast a "signal fail". That message eventually reaches its link partner, which responds by blocking the port. Meanwhile, the first node has continued to block the port with the just plugged-in cable, breaking the network. And the reason for those missing CCM messages has in turn been tracked down to the VTU apparently being too busy servicing load/purge operations that the normal lookups are delayed. Initial state, the link between C and D is blocked in software. _____________________ / \ | | A ----- B ----- C *---- D Unplug the cable between C and D. _____________________ / \ | | A ----- B ----- C * * D Reestablish the link between C and D. _____________________ / \ | | A ----- B ----- C *---- D Somehow, enough VTU/ATU operations happen inside C that prevents the application from receving the CCM messages from B in a timely manner, so a Signal Fail message is sent by C. When B receives that, it responds by blocking its port. _____________________ / \ | | A ----- B *---* C *---- D Very shortly after this, the signal fail condition clears on the BC link (some CCM messages finally make it through), so C unblocks the port. However, a guard timer inside B prevents it from removing the blocking before 5 seconds have elapsed. It is not unlikely that our userspace ERPS implementation could be smarter and/or is simply buggy. However, this patch fixes the symptoms we see, and is a small optimization that should not break anything (knock wood). The idea is simply to avoid doing an VTU load of an entry identical to the one already present. To do that, we need to know whether mv88e6xxx_vtu_get() actually found an existing entry, or has just prepared a struct mv88e6xxx_vtu_entry for us to load. To that end, let vlan->valid be an output parameter. The other two callers of mv88e6xxx_vtu_get() are not affected by this patch since they pass new=false. Signed-off-by: Rasmus Villemoes Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6b17cd961d06..2e500428670c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1423,7 +1423,6 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid, /* Initialize a fresh VLAN entry */ memset(entry, 0, sizeof(*entry)); - entry->valid = true; entry->vid = vid; /* Exclude all ports */ @@ -1618,6 +1617,9 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port, if (err) return err; + if (vlan.valid && vlan.member[port] == member) + return 0; + vlan.valid = true; vlan.member[port] = member; err = mv88e6xxx_vtu_loadpurge(chip, &vlan); -- GitLab From 156189a6d7a797d6fa0b13dd6b4f32b11d234a99 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Jul 2019 01:40:15 +0900 Subject: [PATCH 1074/7155] leds: netxbig: remove legacy board-file support Since commit ebc278f15759 ("ARM: mvebu: remove static LED setup for netxbig boards"), no one in upstream passes in the platform data to this driver. Squash leds-kirkwood-netxbig.h into the driver, and remove the legacy board-file support. Link: https://lkml.org/lkml/2019/7/20/83 Suggested-by: Arnd Bergmann Signed-off-by: Masahiro Yamada Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 1 + drivers/leds/leds-netxbig.c | 70 +++++++++++++------ .../platform_data/leds-kirkwood-netxbig.h | 54 -------------- 3 files changed, 51 insertions(+), 74 deletions(-) delete mode 100644 include/linux/platform_data/leds-kirkwood-netxbig.h diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f7a3dd7ecf3d..1988de1d64c0 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -590,6 +590,7 @@ config LEDS_NETXBIG tristate "LED support for Big Network series LEDs" depends on LEDS_CLASS depends on MACH_KIRKWOOD + depends on OF_GPIO default y help This option enables support for LEDs found on the LaCie 2Big diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index 10497a466775..0944cb111c34 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -15,7 +15,48 @@ #include #include #include -#include + +struct netxbig_gpio_ext { + unsigned int *addr; + int num_addr; + unsigned int *data; + int num_data; + unsigned int enable; +}; + +enum netxbig_led_mode { + NETXBIG_LED_OFF, + NETXBIG_LED_ON, + NETXBIG_LED_SATA, + NETXBIG_LED_TIMER1, + NETXBIG_LED_TIMER2, + NETXBIG_LED_MODE_NUM, +}; + +#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM + +struct netxbig_led_timer { + unsigned long delay_on; + unsigned long delay_off; + enum netxbig_led_mode mode; +}; + +struct netxbig_led { + const char *name; + const char *default_trigger; + int mode_addr; + int *mode_val; + int bright_addr; + int bright_max; +}; + +struct netxbig_led_platform_data { + struct netxbig_gpio_ext *gpio_ext; + struct netxbig_led_timer *timer; + int num_timer; + struct netxbig_led *leds; + int num_leds; +}; /* * GPIO extension bus. @@ -306,7 +347,6 @@ static int create_netxbig_led(struct platform_device *pdev, return devm_led_classdev_register(&pdev->dev, &led_dat->cdev); } -#ifdef CONFIG_OF_GPIO static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np, struct netxbig_gpio_ext *gpio_ext) { @@ -522,30 +562,20 @@ static const struct of_device_id of_netxbig_leds_match[] = { {}, }; MODULE_DEVICE_TABLE(of, of_netxbig_leds_match); -#else -static inline int -netxbig_leds_get_of_pdata(struct device *dev, - struct netxbig_led_platform_data *pdata) -{ - return -ENODEV; -} -#endif /* CONFIG_OF_GPIO */ static int netxbig_led_probe(struct platform_device *pdev) { - struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct netxbig_led_platform_data *pdata; struct netxbig_led_data *leds_data; int i; int ret; - if (!pdata) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata); - if (ret) - return ret; - } + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata); + if (ret) + return ret; leds_data = devm_kcalloc(&pdev->dev, pdata->num_leds, sizeof(*leds_data), @@ -571,7 +601,7 @@ static struct platform_driver netxbig_led_driver = { .probe = netxbig_led_probe, .driver = { .name = "leds-netxbig", - .of_match_table = of_match_ptr(of_netxbig_leds_match), + .of_match_table = of_netxbig_leds_match, }, }; diff --git a/include/linux/platform_data/leds-kirkwood-netxbig.h b/include/linux/platform_data/leds-kirkwood-netxbig.h deleted file mode 100644 index 3c85a735c380..000000000000 --- a/include/linux/platform_data/leds-kirkwood-netxbig.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Platform data structure for netxbig LED driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __LEDS_KIRKWOOD_NETXBIG_H -#define __LEDS_KIRKWOOD_NETXBIG_H - -struct netxbig_gpio_ext { - unsigned *addr; - int num_addr; - unsigned *data; - int num_data; - unsigned enable; -}; - -enum netxbig_led_mode { - NETXBIG_LED_OFF, - NETXBIG_LED_ON, - NETXBIG_LED_SATA, - NETXBIG_LED_TIMER1, - NETXBIG_LED_TIMER2, - NETXBIG_LED_MODE_NUM, -}; - -#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM - -struct netxbig_led_timer { - unsigned long delay_on; - unsigned long delay_off; - enum netxbig_led_mode mode; -}; - -struct netxbig_led { - const char *name; - const char *default_trigger; - int mode_addr; - int *mode_val; - int bright_addr; - int bright_max; -}; - -struct netxbig_led_platform_data { - struct netxbig_gpio_ext *gpio_ext; - struct netxbig_led_timer *timer; - int num_timer; - struct netxbig_led *leds; - int num_leds; -}; - -#endif /* __LEDS_KIRKWOOD_NETXBIG_H */ -- GitLab From af7b65054952a9898534d966f2e548d7692b7016 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 29 Jul 2019 12:23:56 +0530 Subject: [PATCH 1075/7155] leds: netxbig: Add of_node_put() in netxbig_leds_get_of_pdata() The variable gpio_ext_np in the function netxbig_leds_get_of_pdata takes the value returned by of_parse_phandle; hence, it must be put in order to prevent a memory leak. Add an of_node_put for gpio_ext_np before a return statement, and move a pre-existing of_node_put statement to right after the last usage of this variable. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-netxbig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index 0944cb111c34..14ef4ccdda3a 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -428,12 +428,14 @@ static int netxbig_leds_get_of_pdata(struct device *dev, } gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL); - if (!gpio_ext) + if (!gpio_ext) { + of_node_put(gpio_ext_np); return -ENOMEM; + } ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext); + of_node_put(gpio_ext_np); if (ret) return ret; - of_node_put(gpio_ext_np); pdata->gpio_ext = gpio_ext; /* Timers (optional) */ -- GitLab From 6dbff13ca8a2ad2fddd904c2e789dd5e59a8644c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:52 +0200 Subject: [PATCH 1076/7155] include/bpf.h: Remove map_insert_ctx() stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we changed the device and CPU maps to use linked lists instead of bitmaps, we also removed the need for the map_insert_ctx() helpers to keep track of the bitmaps inside each map. However, it seems I forgot to remove the function definitions stubs, so remove those here. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Acked-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov --- include/linux/bpf.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 18f4cc2c6acd..bfdb54dd2ad1 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -713,7 +713,6 @@ struct xdp_buff; struct sk_buff; struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key); -void __dev_map_insert_ctx(struct bpf_map *map, u32 index); void __dev_map_flush(struct bpf_map *map); int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp, struct net_device *dev_rx); @@ -721,7 +720,6 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb, struct bpf_prog *xdp_prog); struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key); -void __cpu_map_insert_ctx(struct bpf_map *map, u32 index); void __cpu_map_flush(struct bpf_map *map); int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_buff *xdp, struct net_device *dev_rx); @@ -801,10 +799,6 @@ static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map, return NULL; } -static inline void __dev_map_insert_ctx(struct bpf_map *map, u32 index) -{ -} - static inline void __dev_map_flush(struct bpf_map *map) { } @@ -834,10 +828,6 @@ struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key) return NULL; } -static inline void __cpu_map_insert_ctx(struct bpf_map *map, u32 index) -{ -} - static inline void __cpu_map_flush(struct bpf_map *map) { } -- GitLab From fca16e51078e8e5c0af839426b3d2dcd2bede135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:53 +0200 Subject: [PATCH 1077/7155] xdp: Refactor devmap allocation code for reuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The subsequent patch to add a new devmap sub-type can re-use much of the initialisation and allocation code, so refactor it into separate functions. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Acked-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov --- kernel/bpf/devmap.c | 136 +++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 53 deletions(-) diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index d83cf8ccc872..a0501266bdb8 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -60,9 +60,9 @@ struct xdp_bulk_queue { struct bpf_dtab_netdev { struct net_device *dev; /* must be first member, due to tracepoint */ struct bpf_dtab *dtab; - unsigned int bit; struct xdp_bulk_queue __percpu *bulkq; struct rcu_head rcu; + unsigned int idx; /* keep track of map index for tracepoint */ }; struct bpf_dtab { @@ -75,28 +75,21 @@ struct bpf_dtab { static DEFINE_SPINLOCK(dev_map_lock); static LIST_HEAD(dev_map_list); -static struct bpf_map *dev_map_alloc(union bpf_attr *attr) +static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) { - struct bpf_dtab *dtab; int err, cpu; u64 cost; - if (!capable(CAP_NET_ADMIN)) - return ERR_PTR(-EPERM); - /* check sanity of attributes */ if (attr->max_entries == 0 || attr->key_size != 4 || attr->value_size != 4 || attr->map_flags & ~DEV_CREATE_FLAG_MASK) - return ERR_PTR(-EINVAL); + return -EINVAL; /* Lookup returns a pointer straight to dev->ifindex, so make sure the * verifier prevents writes from the BPF side */ attr->map_flags |= BPF_F_RDONLY_PROG; - dtab = kzalloc(sizeof(*dtab), GFP_USER); - if (!dtab) - return ERR_PTR(-ENOMEM); bpf_map_init_from_attr(&dtab->map, attr); @@ -107,9 +100,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) /* if map size is larger than memlock limit, reject it */ err = bpf_map_charge_init(&dtab->map.memory, cost); if (err) - goto free_dtab; - - err = -ENOMEM; + return -EINVAL; dtab->flush_list = alloc_percpu(struct list_head); if (!dtab->flush_list) @@ -124,19 +115,38 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) if (!dtab->netdev_map) goto free_percpu; - spin_lock(&dev_map_lock); - list_add_tail_rcu(&dtab->list, &dev_map_list); - spin_unlock(&dev_map_lock); - - return &dtab->map; + return 0; free_percpu: free_percpu(dtab->flush_list); free_charge: bpf_map_charge_finish(&dtab->map.memory); -free_dtab: - kfree(dtab); - return ERR_PTR(err); + return -ENOMEM; +} + +static struct bpf_map *dev_map_alloc(union bpf_attr *attr) +{ + struct bpf_dtab *dtab; + int err; + + if (!capable(CAP_NET_ADMIN)) + return ERR_PTR(-EPERM); + + dtab = kzalloc(sizeof(*dtab), GFP_USER); + if (!dtab) + return ERR_PTR(-ENOMEM); + + err = dev_map_init_map(dtab, attr); + if (err) { + kfree(dtab); + return ERR_PTR(err); + } + + spin_lock(&dev_map_lock); + list_add_tail_rcu(&dtab->list, &dev_map_list); + spin_unlock(&dev_map_lock); + + return &dtab->map; } static void dev_map_free(struct bpf_map *map) @@ -235,7 +245,7 @@ static int bq_xmit_all(struct xdp_bulk_queue *bq, u32 flags, out: bq->count = 0; - trace_xdp_devmap_xmit(&obj->dtab->map, obj->bit, + trace_xdp_devmap_xmit(&obj->dtab->map, obj->idx, sent, drops, bq->dev_rx, dev, err); bq->dev_rx = NULL; __list_del_clearprev(&bq->flush_node); @@ -412,17 +422,52 @@ static int dev_map_delete_elem(struct bpf_map *map, void *key) return 0; } -static int dev_map_update_elem(struct bpf_map *map, void *key, void *value, - u64 map_flags) +static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, + struct bpf_dtab *dtab, + u32 ifindex, + unsigned int idx) { - struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); - struct net *net = current->nsproxy->net_ns; gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN; + struct bpf_dtab_netdev *dev; + struct xdp_bulk_queue *bq; + int cpu; + + dev = kmalloc_node(sizeof(*dev), gfp, dtab->map.numa_node); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->bulkq = __alloc_percpu_gfp(sizeof(*dev->bulkq), + sizeof(void *), gfp); + if (!dev->bulkq) { + kfree(dev); + return ERR_PTR(-ENOMEM); + } + + for_each_possible_cpu(cpu) { + bq = per_cpu_ptr(dev->bulkq, cpu); + bq->obj = dev; + } + + dev->dev = dev_get_by_index(net, ifindex); + if (!dev->dev) { + free_percpu(dev->bulkq); + kfree(dev); + return ERR_PTR(-EINVAL); + } + + dev->idx = idx; + dev->dtab = dtab; + + return dev; +} + +static int __dev_map_update_elem(struct net *net, struct bpf_map *map, + void *key, void *value, u64 map_flags) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); struct bpf_dtab_netdev *dev, *old_dev; u32 ifindex = *(u32 *)value; - struct xdp_bulk_queue *bq; u32 i = *(u32 *)key; - int cpu; if (unlikely(map_flags > BPF_EXIST)) return -EINVAL; @@ -434,31 +479,9 @@ static int dev_map_update_elem(struct bpf_map *map, void *key, void *value, if (!ifindex) { dev = NULL; } else { - dev = kmalloc_node(sizeof(*dev), gfp, map->numa_node); - if (!dev) - return -ENOMEM; - - dev->bulkq = __alloc_percpu_gfp(sizeof(*dev->bulkq), - sizeof(void *), gfp); - if (!dev->bulkq) { - kfree(dev); - return -ENOMEM; - } - - for_each_possible_cpu(cpu) { - bq = per_cpu_ptr(dev->bulkq, cpu); - bq->obj = dev; - } - - dev->dev = dev_get_by_index(net, ifindex); - if (!dev->dev) { - free_percpu(dev->bulkq); - kfree(dev); - return -EINVAL; - } - - dev->bit = i; - dev->dtab = dtab; + dev = __dev_map_alloc_node(net, dtab, ifindex, i); + if (IS_ERR(dev)) + return PTR_ERR(dev); } /* Use call_rcu() here to ensure rcu critical sections have completed @@ -472,6 +495,13 @@ static int dev_map_update_elem(struct bpf_map *map, void *key, void *value, return 0; } +static int dev_map_update_elem(struct bpf_map *map, void *key, void *value, + u64 map_flags) +{ + return __dev_map_update_elem(current->nsproxy->net_ns, + map, key, value, map_flags); +} + const struct bpf_map_ops dev_map_ops = { .map_alloc = dev_map_alloc, .map_free = dev_map_free, -- GitLab From 6f9d451ab1a33728adb72d7ff66a7b374d665176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:55 +0200 Subject: [PATCH 1078/7155] xdp: Add devmap_hash map type for looking up devices by hashed index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A common pattern when using xdp_redirect_map() is to create a device map where the lookup key is simply ifindex. Because device maps are arrays, this leaves holes in the map, and the map has to be sized to fit the largest ifindex, regardless of how many devices actually are actually needed in the map. This patch adds a second type of device map where the key is looked up using a hashmap, instead of being used as an array index. This allows maps to be densely packed, so they can be smaller. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Acked-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov --- include/linux/bpf.h | 7 ++ include/linux/bpf_types.h | 1 + include/trace/events/xdp.h | 3 +- include/uapi/linux/bpf.h | 1 + kernel/bpf/devmap.c | 200 +++++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 2 + net/core/filter.c | 9 +- 7 files changed, 220 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index bfdb54dd2ad1..f9a506147c8a 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -713,6 +713,7 @@ struct xdp_buff; struct sk_buff; struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key); +struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key); void __dev_map_flush(struct bpf_map *map); int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp, struct net_device *dev_rx); @@ -799,6 +800,12 @@ static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map, return NULL; } +static inline struct net_device *__dev_map_hash_lookup_elem(struct bpf_map *map, + u32 key) +{ + return NULL; +} + static inline void __dev_map_flush(struct bpf_map *map) { } diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index eec5aeeeaf92..36a9c2325176 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -62,6 +62,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_of_maps_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops) #ifdef CONFIG_NET BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops) +BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops) #if defined(CONFIG_BPF_STREAM_PARSER) BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) diff --git a/include/trace/events/xdp.h b/include/trace/events/xdp.h index 68899fdc985b..8c8420230a10 100644 --- a/include/trace/events/xdp.h +++ b/include/trace/events/xdp.h @@ -175,7 +175,8 @@ struct _bpf_dtab_netdev { #endif /* __DEVMAP_OBJ_TYPE */ #define devmap_ifindex(fwd, map) \ - ((map->map_type == BPF_MAP_TYPE_DEVMAP) ? \ + ((map->map_type == BPF_MAP_TYPE_DEVMAP || \ + map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) ? \ ((struct _bpf_dtab_netdev *)fwd)->dev->ifindex : 0) #define _trace_xdp_redirect_map(dev, xdp, fwd, map, idx) \ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index e985f07a98ed..6bbef0c7f585 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -134,6 +134,7 @@ enum bpf_map_type { BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK, BPF_MAP_TYPE_SK_STORAGE, + BPF_MAP_TYPE_DEVMAP_HASH, }; /* Note that tracing related programs such as diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index a0501266bdb8..9af048a932b5 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -37,6 +37,12 @@ * notifier hook walks the map we know that new dev references can not be * added by the user because core infrastructure ensures dev_get_by_index() * calls will fail at this point. + * + * The devmap_hash type is a map type which interprets keys as ifindexes and + * indexes these using a hashmap. This allows maps that use ifindex as key to be + * densely packed instead of having holes in the lookup array for unused + * ifindexes. The setup and packet enqueue/send code is shared between the two + * types of devmap; only the lookup and insertion is different. */ #include #include @@ -59,6 +65,7 @@ struct xdp_bulk_queue { struct bpf_dtab_netdev { struct net_device *dev; /* must be first member, due to tracepoint */ + struct hlist_node index_hlist; struct bpf_dtab *dtab; struct xdp_bulk_queue __percpu *bulkq; struct rcu_head rcu; @@ -70,11 +77,30 @@ struct bpf_dtab { struct bpf_dtab_netdev **netdev_map; struct list_head __percpu *flush_list; struct list_head list; + + /* these are only used for DEVMAP_HASH type maps */ + struct hlist_head *dev_index_head; + spinlock_t index_lock; + unsigned int items; + u32 n_buckets; }; static DEFINE_SPINLOCK(dev_map_lock); static LIST_HEAD(dev_map_list); +static struct hlist_head *dev_map_create_hash(unsigned int entries) +{ + int i; + struct hlist_head *hash; + + hash = kmalloc_array(entries, sizeof(*hash), GFP_KERNEL); + if (hash != NULL) + for (i = 0; i < entries; i++) + INIT_HLIST_HEAD(&hash[i]); + + return hash; +} + static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) { int err, cpu; @@ -97,6 +123,14 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) cost = (u64) dtab->map.max_entries * sizeof(struct bpf_dtab_netdev *); cost += sizeof(struct list_head) * num_possible_cpus(); + if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) { + dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries); + + if (!dtab->n_buckets) /* Overflow check */ + return -EINVAL; + cost += sizeof(struct hlist_head) * dtab->n_buckets; + } + /* if map size is larger than memlock limit, reject it */ err = bpf_map_charge_init(&dtab->map.memory, cost); if (err) @@ -115,8 +149,18 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) if (!dtab->netdev_map) goto free_percpu; + if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) { + dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets); + if (!dtab->dev_index_head) + goto free_map_area; + + spin_lock_init(&dtab->index_lock); + } + return 0; +free_map_area: + bpf_map_area_free(dtab->netdev_map); free_percpu: free_percpu(dtab->flush_list); free_charge: @@ -198,6 +242,7 @@ static void dev_map_free(struct bpf_map *map) free_percpu(dtab->flush_list); bpf_map_area_free(dtab->netdev_map); + kfree(dtab->dev_index_head); kfree(dtab); } @@ -218,6 +263,70 @@ static int dev_map_get_next_key(struct bpf_map *map, void *key, void *next_key) return 0; } +static inline struct hlist_head *dev_map_index_hash(struct bpf_dtab *dtab, + int idx) +{ + return &dtab->dev_index_head[idx & (dtab->n_buckets - 1)]; +} + +struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + struct hlist_head *head = dev_map_index_hash(dtab, key); + struct bpf_dtab_netdev *dev; + + hlist_for_each_entry_rcu(dev, head, index_hlist) + if (dev->idx == key) + return dev; + + return NULL; +} + +static int dev_map_hash_get_next_key(struct bpf_map *map, void *key, + void *next_key) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + u32 idx, *next = next_key; + struct bpf_dtab_netdev *dev, *next_dev; + struct hlist_head *head; + int i = 0; + + if (!key) + goto find_first; + + idx = *(u32 *)key; + + dev = __dev_map_hash_lookup_elem(map, idx); + if (!dev) + goto find_first; + + next_dev = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(&dev->index_hlist)), + struct bpf_dtab_netdev, index_hlist); + + if (next_dev) { + *next = next_dev->idx; + return 0; + } + + i = idx & (dtab->n_buckets - 1); + i++; + + find_first: + for (; i < dtab->n_buckets; i++) { + head = dev_map_index_hash(dtab, i); + + next_dev = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)), + struct bpf_dtab_netdev, + index_hlist); + if (next_dev) { + *next = next_dev->idx; + return 0; + } + } + + return -ENOENT; +} + static int bq_xmit_all(struct xdp_bulk_queue *bq, u32 flags, bool in_napi_ctx) { @@ -373,6 +482,15 @@ static void *dev_map_lookup_elem(struct bpf_map *map, void *key) return dev ? &dev->ifindex : NULL; } +static void *dev_map_hash_lookup_elem(struct bpf_map *map, void *key) +{ + struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map, + *(u32 *)key); + struct net_device *dev = obj ? obj->dev : NULL; + + return dev ? &dev->ifindex : NULL; +} + static void dev_map_flush_old(struct bpf_dtab_netdev *dev) { if (dev->dev->netdev_ops->ndo_xdp_xmit) { @@ -422,6 +540,28 @@ static int dev_map_delete_elem(struct bpf_map *map, void *key) return 0; } +static int dev_map_hash_delete_elem(struct bpf_map *map, void *key) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + struct bpf_dtab_netdev *old_dev; + int k = *(u32 *)key; + unsigned long flags; + int ret = -ENOENT; + + spin_lock_irqsave(&dtab->index_lock, flags); + + old_dev = __dev_map_hash_lookup_elem(map, k); + if (old_dev) { + dtab->items--; + hlist_del_init_rcu(&old_dev->index_hlist); + call_rcu(&old_dev->rcu, __dev_map_entry_free); + ret = 0; + } + spin_unlock_irqrestore(&dtab->index_lock, flags); + + return ret; +} + static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, struct bpf_dtab *dtab, u32 ifindex, @@ -502,6 +642,56 @@ static int dev_map_update_elem(struct bpf_map *map, void *key, void *value, map, key, value, map_flags); } +static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, + void *key, void *value, u64 map_flags) +{ + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + struct bpf_dtab_netdev *dev, *old_dev; + u32 ifindex = *(u32 *)value; + u32 idx = *(u32 *)key; + unsigned long flags; + + if (unlikely(map_flags > BPF_EXIST || !ifindex)) + return -EINVAL; + + old_dev = __dev_map_hash_lookup_elem(map, idx); + if (old_dev && (map_flags & BPF_NOEXIST)) + return -EEXIST; + + dev = __dev_map_alloc_node(net, dtab, ifindex, idx); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + spin_lock_irqsave(&dtab->index_lock, flags); + + if (old_dev) { + hlist_del_rcu(&old_dev->index_hlist); + } else { + if (dtab->items >= dtab->map.max_entries) { + spin_unlock_irqrestore(&dtab->index_lock, flags); + call_rcu(&dev->rcu, __dev_map_entry_free); + return -E2BIG; + } + dtab->items++; + } + + hlist_add_head_rcu(&dev->index_hlist, + dev_map_index_hash(dtab, idx)); + spin_unlock_irqrestore(&dtab->index_lock, flags); + + if (old_dev) + call_rcu(&old_dev->rcu, __dev_map_entry_free); + + return 0; +} + +static int dev_map_hash_update_elem(struct bpf_map *map, void *key, void *value, + u64 map_flags) +{ + return __dev_map_hash_update_elem(current->nsproxy->net_ns, + map, key, value, map_flags); +} + const struct bpf_map_ops dev_map_ops = { .map_alloc = dev_map_alloc, .map_free = dev_map_free, @@ -512,6 +702,16 @@ const struct bpf_map_ops dev_map_ops = { .map_check_btf = map_check_no_btf, }; +const struct bpf_map_ops dev_map_hash_ops = { + .map_alloc = dev_map_alloc, + .map_free = dev_map_free, + .map_get_next_key = dev_map_hash_get_next_key, + .map_lookup_elem = dev_map_hash_lookup_elem, + .map_update_elem = dev_map_hash_update_elem, + .map_delete_elem = dev_map_hash_delete_elem, + .map_check_btf = map_check_no_btf, +}; + static int dev_map_notification(struct notifier_block *notifier, ulong event, void *ptr) { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 5900cbb966b1..cef851cd5c36 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3457,6 +3457,7 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, goto error; break; case BPF_MAP_TYPE_DEVMAP: + case BPF_MAP_TYPE_DEVMAP_HASH: if (func_id != BPF_FUNC_redirect_map && func_id != BPF_FUNC_map_lookup_elem) goto error; @@ -3539,6 +3540,7 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, break; case BPF_FUNC_redirect_map: if (map->map_type != BPF_MAP_TYPE_DEVMAP && + map->map_type != BPF_MAP_TYPE_DEVMAP_HASH && map->map_type != BPF_MAP_TYPE_CPUMAP && map->map_type != BPF_MAP_TYPE_XSKMAP) goto error; diff --git a/net/core/filter.c b/net/core/filter.c index 3961437ccc50..1eee70f80fba 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3517,7 +3517,8 @@ static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd, int err; switch (map->map_type) { - case BPF_MAP_TYPE_DEVMAP: { + case BPF_MAP_TYPE_DEVMAP: + case BPF_MAP_TYPE_DEVMAP_HASH: { struct bpf_dtab_netdev *dst = fwd; err = dev_map_enqueue(dst, xdp, dev_rx); @@ -3554,6 +3555,7 @@ void xdp_do_flush_map(void) if (map) { switch (map->map_type) { case BPF_MAP_TYPE_DEVMAP: + case BPF_MAP_TYPE_DEVMAP_HASH: __dev_map_flush(map); break; case BPF_MAP_TYPE_CPUMAP: @@ -3574,6 +3576,8 @@ static inline void *__xdp_map_lookup_elem(struct bpf_map *map, u32 index) switch (map->map_type) { case BPF_MAP_TYPE_DEVMAP: return __dev_map_lookup_elem(map, index); + case BPF_MAP_TYPE_DEVMAP_HASH: + return __dev_map_hash_lookup_elem(map, index); case BPF_MAP_TYPE_CPUMAP: return __cpu_map_lookup_elem(map, index); case BPF_MAP_TYPE_XSKMAP: @@ -3655,7 +3659,8 @@ static int xdp_do_generic_redirect_map(struct net_device *dev, ri->tgt_value = NULL; WRITE_ONCE(ri->map, NULL); - if (map->map_type == BPF_MAP_TYPE_DEVMAP) { + if (map->map_type == BPF_MAP_TYPE_DEVMAP || + map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) { struct bpf_dtab_netdev *dst = fwd; err = dev_map_generic_redirect(dst, skb, xdp_prog); -- GitLab From 10fbe21163fc6f05f5991d9cf9a2da9bdee4e834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:56 +0200 Subject: [PATCH 1079/7155] tools/include/uapi: Add devmap_hash BPF map type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the devmap_hash BPF map type to the uapi headers in tools/. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Acked-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov --- tools/include/uapi/linux/bpf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 3d7fc67ec1b8..21d0f6863df3 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -134,6 +134,7 @@ enum bpf_map_type { BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK, BPF_MAP_TYPE_SK_STORAGE, + BPF_MAP_TYPE_DEVMAP_HASH, }; /* Note that tracing related programs such as -- GitLab From e42346192c9f179a9a47845e4663ad2f453d2b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:57 +0200 Subject: [PATCH 1080/7155] tools/libbpf_probes: Add new devmap_hash type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the definition for BPF_MAP_TYPE_DEVMAP_HASH to libbpf_probes.c in tools/lib/bpf. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Acked-by: Jesper Dangaard Brouer --- tools/lib/bpf/libbpf_probes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c index ace1a0708d99..4b0b0364f5fc 100644 --- a/tools/lib/bpf/libbpf_probes.c +++ b/tools/lib/bpf/libbpf_probes.c @@ -244,6 +244,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) case BPF_MAP_TYPE_ARRAY_OF_MAPS: case BPF_MAP_TYPE_HASH_OF_MAPS: case BPF_MAP_TYPE_DEVMAP: + case BPF_MAP_TYPE_DEVMAP_HASH: case BPF_MAP_TYPE_SOCKMAP: case BPF_MAP_TYPE_CPUMAP: case BPF_MAP_TYPE_XSKMAP: -- GitLab From 1375dc4a4579d5e767dd8c2d2abcd929ff59d0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Jul 2019 18:06:58 +0200 Subject: [PATCH 1081/7155] tools: Add definitions for devmap_hash map type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds selftest and bpftool updates for the devmap_hash map type. Signed-off-by: Toke Høiland-Jørgensen Acked-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/Documentation/bpftool-map.rst | 2 +- tools/bpf/bpftool/bash-completion/bpftool | 4 ++-- tools/bpf/bpftool/map.c | 3 ++- tools/testing/selftests/bpf/test_maps.c | 16 ++++++++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 490b4501cb6e..61d1d270eb5e 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -46,7 +46,7 @@ MAP COMMANDS | *TYPE* := { **hash** | **array** | **prog_array** | **perf_event_array** | **percpu_hash** | | **percpu_array** | **stack_trace** | **cgroup_array** | **lru_hash** | | **lru_percpu_hash** | **lpm_trie** | **array_of_maps** | **hash_of_maps** -| | **devmap** | **sockmap** | **cpumap** | **xskmap** | **sockhash** +| | **devmap** | **devmap_hash** | **sockmap** | **cpumap** | **xskmap** | **sockhash** | | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage** | | **queue** | **stack** } diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index c8f42e1fcbc9..6b961a5ed100 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -489,8 +489,8 @@ _bpftool() perf_event_array percpu_hash percpu_array \ stack_trace cgroup_array lru_hash \ lru_percpu_hash lpm_trie array_of_maps \ - hash_of_maps devmap sockmap cpumap xskmap \ - sockhash cgroup_storage reuseport_sockarray \ + hash_of_maps devmap devmap_hash sockmap cpumap \ + xskmap sockhash cgroup_storage reuseport_sockarray \ percpu_cgroup_storage queue stack' -- \ "$cur" ) ) return 0 diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 5da5a7311f13..bfbbc6b4cb83 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -37,6 +37,7 @@ const char * const map_type_name[] = { [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps", [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps", [BPF_MAP_TYPE_DEVMAP] = "devmap", + [BPF_MAP_TYPE_DEVMAP_HASH] = "devmap_hash", [BPF_MAP_TYPE_SOCKMAP] = "sockmap", [BPF_MAP_TYPE_CPUMAP] = "cpumap", [BPF_MAP_TYPE_XSKMAP] = "xskmap", @@ -1271,7 +1272,7 @@ static int do_help(int argc, char **argv) " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n" " percpu_array | stack_trace | cgroup_array | lru_hash |\n" " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n" - " devmap | sockmap | cpumap | xskmap | sockhash |\n" + " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n" " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n" " " HELP_SPEC_OPTIONS "\n" "", diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index 5443b9bd75ed..e1f1becda529 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c @@ -508,6 +508,21 @@ static void test_devmap(unsigned int task, void *data) close(fd); } +static void test_devmap_hash(unsigned int task, void *data) +{ + int fd; + __u32 key, value; + + fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP_HASH, sizeof(key), sizeof(value), + 2, 0); + if (fd < 0) { + printf("Failed to create devmap_hash '%s'!\n", strerror(errno)); + exit(1); + } + + close(fd); +} + static void test_queuemap(unsigned int task, void *data) { const int MAP_SIZE = 32; @@ -1684,6 +1699,7 @@ static void run_all_tests(void) test_arraymap_percpu_many_keys(); test_devmap(0, NULL); + test_devmap_hash(0, NULL); test_sockmap(0, NULL); test_map_large(); -- GitLab From 473d924d7d46cb57aa4c1863261d18366af345af Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 29 Jul 2019 22:40:56 +0200 Subject: [PATCH 1082/7155] can: fix ioctl function removal Commit 60649d4e0af ("can: remove obsolete empty ioctl() handler") replaced the almost empty can_ioctl() function with sock_no_ioctl() which always returns -EOPNOTSUPP. Even though we don't have any ioctl() functions on socket/network layer we need to return -ENOIOCTLCMD to be able to forward ioctl commands like SIOCGIFINDEX to the network driver layer. This patch fixes the wrong return codes in the CAN network layer protocols. Reported-by: kernel test robot Fixes: 60649d4e0af ("can: remove obsolete empty ioctl() handler") Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/bcm.c | 9 ++++++++- net/can/raw.c | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 8da986b19d88..bf1d0bbecec8 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1680,6 +1680,13 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, return size; } +int bcm_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + /* no ioctls for socket layer -> hand it down to NIC layer */ + return -ENOIOCTLCMD; +} + static const struct proto_ops bcm_ops = { .family = PF_CAN, .release = bcm_release, @@ -1689,7 +1696,7 @@ static const struct proto_ops bcm_ops = { .accept = sock_no_accept, .getname = sock_no_getname, .poll = datagram_poll, - .ioctl = sock_no_ioctl, + .ioctl = bcm_sock_no_ioctlcmd, .gettstamp = sock_gettstamp, .listen = sock_no_listen, .shutdown = sock_no_shutdown, diff --git a/net/can/raw.c b/net/can/raw.c index ff720272f7b7..da386f1fa815 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -837,6 +837,13 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, return size; } +int raw_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + /* no ioctls for socket layer -> hand it down to NIC layer */ + return -ENOIOCTLCMD; +} + static const struct proto_ops raw_ops = { .family = PF_CAN, .release = raw_release, @@ -846,7 +853,7 @@ static const struct proto_ops raw_ops = { .accept = sock_no_accept, .getname = raw_getname, .poll = datagram_poll, - .ioctl = sock_no_ioctl, + .ioctl = raw_sock_no_ioctlcmd, .gettstamp = sock_gettstamp, .listen = sock_no_listen, .shutdown = sock_no_shutdown, -- GitLab From 2792b5b95ed5f38279da08f467a490687332324d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:18 -0400 Subject: [PATCH 1083/7155] bnxt_en: Update firmware interface spec. to 1.10.0.89. Among the changes are new CoS discard counters and new ctx_hw_stats_ext struct for the latest 5750X B0 chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 15 +++ drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 109 +++++++++++++++--- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index c7ee63d69679..1eb590eac47a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -207,6 +207,20 @@ static int bnxt_set_coalesce(struct net_device *dev, BNXT_TX_STATS_EXT_COS_ENTRY(6), \ BNXT_TX_STATS_EXT_COS_ENTRY(7) \ +#define BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \ + BNXT_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \ + BNXT_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n) + +#define BNXT_RX_STATS_EXT_DISCARD_COS_ENTRIES \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \ + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRY(7) + #define BNXT_RX_STATS_PRI_ENTRY(counter, n) \ { BNXT_RX_STATS_EXT_OFFSET(counter##_cos0), \ __stringify(counter##_pri##n) } @@ -352,6 +366,7 @@ static const struct { BNXT_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold), BNXT_RX_STATS_EXT_ENTRY(rx_pcs_symbol_err), BNXT_RX_STATS_EXT_ENTRY(rx_corrected_bits), + BNXT_RX_STATS_EXT_DISCARD_COS_ENTRIES, }; static const struct { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index 12bbb2a207d0..2cdef753a1bc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -1,7 +1,8 @@ /* Broadcom NetXtreme-C/E network driver. * * Copyright (c) 2014-2016 Broadcom Corporation - * Copyright (c) 2016-2019 Broadcom Limited + * Copyright (c) 2014-2018 Broadcom Limited + * Copyright (c) 2018-2019 Broadcom Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,15 +40,15 @@ struct hwrm_resp_hdr { #define TLV_TYPE_ROCE_SP_COMMAND 0x3UL #define TLV_TYPE_QUERY_ROCE_CC_GEN1 0x4UL #define TLV_TYPE_MODIFY_ROCE_CC_GEN1 0x5UL -#define TLV_TYPE_ENGINE_CKV_DEVICE_SERIAL_NUMBER 0x8001UL -#define TLV_TYPE_ENGINE_CKV_NONCE 0x8002UL +#define TLV_TYPE_ENGINE_CKV_ALIAS_ECC_PUBLIC_KEY 0x8001UL #define TLV_TYPE_ENGINE_CKV_IV 0x8003UL #define TLV_TYPE_ENGINE_CKV_AUTH_TAG 0x8004UL #define TLV_TYPE_ENGINE_CKV_CIPHERTEXT 0x8005UL #define TLV_TYPE_ENGINE_CKV_ALGORITHMS 0x8006UL -#define TLV_TYPE_ENGINE_CKV_ECC_PUBLIC_KEY 0x8007UL +#define TLV_TYPE_ENGINE_CKV_HOST_ECC_PUBLIC_KEY 0x8007UL #define TLV_TYPE_ENGINE_CKV_ECDSA_SIGNATURE 0x8008UL -#define TLV_TYPE_LAST TLV_TYPE_ENGINE_CKV_ECDSA_SIGNATURE +#define TLV_TYPE_ENGINE_CKV_SRT_ECC_PUBLIC_KEY 0x8009UL +#define TLV_TYPE_LAST TLV_TYPE_ENGINE_CKV_SRT_ECC_PUBLIC_KEY /* tlv (size:64b/8B) */ @@ -267,7 +268,6 @@ struct cmd_nums { #define HWRM_CFA_EEM_OP 0x123UL #define HWRM_CFA_ADV_FLOW_MGNT_QCAPS 0x124UL #define HWRM_CFA_TFLIB 0x125UL - #define HWRM_ENGINE_CKV_HELLO 0x12dUL #define HWRM_ENGINE_CKV_STATUS 0x12eUL #define HWRM_ENGINE_CKV_CKEK_ADD 0x12fUL #define HWRM_ENGINE_CKV_CKEK_DELETE 0x130UL @@ -313,6 +313,7 @@ struct cmd_nums { #define HWRM_FUNC_BACKING_STORE_QCFG 0x194UL #define HWRM_FUNC_VF_BW_CFG 0x195UL #define HWRM_FUNC_VF_BW_QCFG 0x196UL + #define HWRM_FUNC_HOST_PF_IDS_QUERY 0x197UL #define HWRM_SELFTEST_QLIST 0x200UL #define HWRM_SELFTEST_EXEC 0x201UL #define HWRM_SELFTEST_IRQ 0x202UL @@ -410,8 +411,8 @@ struct hwrm_err_output { #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 0 -#define HWRM_VERSION_RSVD 69 -#define HWRM_VERSION_STR "1.10.0.69" +#define HWRM_VERSION_RSVD 89 +#define HWRM_VERSION_STR "1.10.0.89" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -624,6 +625,8 @@ struct hwrm_async_event_cmpl { #define ASYNC_EVENT_CMPL_EVENT_ID_TCP_FLAG_ACTION_CHANGE 0x3aUL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_FLOW_ACTIVE 0x3bUL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CFG_CHANGE 0x3cUL + #define ASYNC_EVENT_CMPL_EVENT_ID_TFLIB_DEFAULT_VNIC_CHANGE 0x3dUL + #define ASYNC_EVENT_CMPL_EVENT_ID_TFLIB_LINK_STATUS_CHANGE 0x3eUL #define ASYNC_EVENT_CMPL_EVENT_ID_FW_TRACE_MSG 0xfeUL #define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL #define ASYNC_EVENT_CMPL_EVENT_ID_LAST ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR @@ -1122,6 +1125,7 @@ struct hwrm_func_qcfg_output { #define FUNC_QCFG_RESP_FLAGS_MULTI_HOST 0x20UL #define FUNC_QCFG_RESP_FLAGS_TRUSTED_VF 0x40UL #define FUNC_QCFG_RESP_FLAGS_SECURE_MODE_ENABLED 0x80UL + #define FUNC_QCFG_RESP_FLAGS_PREBOOT_LEGACY_L2_RINGS 0x100UL u8 mac_address[6]; __le16 pci_id; __le16 alloc_rsscos_ctx; @@ -1241,6 +1245,7 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC 0x400000UL #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST 0x800000UL #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE 0x1000000UL + #define FUNC_CFG_REQ_FLAGS_PREBOOT_LEGACY_L2_RINGS 0x2000000UL __le32 enables; #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL @@ -2916,7 +2921,7 @@ struct tx_port_stats_ext { __le64 pfc_pri7_tx_transitions; }; -/* rx_port_stats_ext (size:2624b/328B) */ +/* rx_port_stats_ext (size:3648b/456B) */ struct rx_port_stats_ext { __le64 link_down_events; __le64 continuous_pause_events; @@ -2959,6 +2964,22 @@ struct rx_port_stats_ext { __le64 rx_buffer_passed_threshold; __le64 rx_pcs_symbol_err; __le64 rx_corrected_bits; + __le64 rx_discard_bytes_cos0; + __le64 rx_discard_bytes_cos1; + __le64 rx_discard_bytes_cos2; + __le64 rx_discard_bytes_cos3; + __le64 rx_discard_bytes_cos4; + __le64 rx_discard_bytes_cos5; + __le64 rx_discard_bytes_cos6; + __le64 rx_discard_bytes_cos7; + __le64 rx_discard_packets_cos0; + __le64 rx_discard_packets_cos1; + __le64 rx_discard_packets_cos2; + __le64 rx_discard_packets_cos3; + __le64 rx_discard_packets_cos4; + __le64 rx_discard_packets_cos5; + __le64 rx_discard_packets_cos6; + __le64 rx_discard_packets_cos7; }; /* hwrm_port_qstats_ext_input (size:320b/40B) */ @@ -6115,6 +6136,21 @@ struct hwrm_cfa_flow_alloc_output { u8 valid; }; +/* hwrm_cfa_flow_alloc_cmd_err (size:64b/8B) */ +struct hwrm_cfa_flow_alloc_cmd_err { + u8 code; + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_UNKNOWN 0x0UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_L2_CONTEXT_TCAM 0x1UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_ACTION_RECORD 0x2UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_COUNTER 0x3UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_WILD_CARD_TCAM 0x4UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_HASH_COLLISION 0x5UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_KEY_EXISTS 0x6UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_CTXT_DB 0x7UL + #define CFA_FLOW_ALLOC_CMD_ERR_CODE_LAST CFA_FLOW_ALLOC_CMD_ERR_CODE_FLOW_CTXT_DB + u8 unused_0[7]; +}; + /* hwrm_cfa_flow_free_input (size:256b/32B) */ struct hwrm_cfa_flow_free_input { __le16 req_type; @@ -6305,7 +6341,7 @@ struct hwrm_cfa_eem_qcaps_input { __le32 unused_0; }; -/* hwrm_cfa_eem_qcaps_output (size:256b/32B) */ +/* hwrm_cfa_eem_qcaps_output (size:320b/40B) */ struct hwrm_cfa_eem_qcaps_output { __le16 error_code; __le16 req_type; @@ -6322,15 +6358,17 @@ struct hwrm_cfa_eem_qcaps_output { #define CFA_EEM_QCAPS_RESP_SUPPORTED_KEY1_TABLE 0x2UL #define CFA_EEM_QCAPS_RESP_SUPPORTED_EXTERNAL_RECORD_TABLE 0x4UL #define CFA_EEM_QCAPS_RESP_SUPPORTED_EXTERNAL_FLOW_COUNTERS_TABLE 0x8UL + #define CFA_EEM_QCAPS_RESP_SUPPORTED_FID_TABLE 0x10UL __le32 max_entries_supported; __le16 key_entry_size; __le16 record_entry_size; __le16 efc_entry_size; - u8 unused_1; + __le16 fid_entry_size; + u8 unused_1[7]; u8 valid; }; -/* hwrm_cfa_eem_cfg_input (size:320b/40B) */ +/* hwrm_cfa_eem_cfg_input (size:384b/48B) */ struct hwrm_cfa_eem_cfg_input { __le16 req_type; __le16 cmpl_ring; @@ -6350,6 +6388,9 @@ struct hwrm_cfa_eem_cfg_input { __le16 key1_ctx_id; __le16 record_ctx_id; __le16 efc_ctx_id; + __le16 fid_ctx_id; + __le16 unused_2; + __le32 unused_3; }; /* hwrm_cfa_eem_cfg_output (size:128b/16B) */ @@ -6375,7 +6416,7 @@ struct hwrm_cfa_eem_qcfg_input { __le32 unused_0; }; -/* hwrm_cfa_eem_qcfg_output (size:192b/24B) */ +/* hwrm_cfa_eem_qcfg_output (size:256b/32B) */ struct hwrm_cfa_eem_qcfg_output { __le16 error_code; __le16 req_type; @@ -6386,7 +6427,12 @@ struct hwrm_cfa_eem_qcfg_output { #define CFA_EEM_QCFG_RESP_FLAGS_PATH_RX 0x2UL #define CFA_EEM_QCFG_RESP_FLAGS_PREFERRED_OFFLOAD 0x4UL __le32 num_entries; - u8 unused_0[7]; + __le16 key0_ctx_id; + __le16 key1_ctx_id; + __le16 record_ctx_id; + __le16 efc_ctx_id; + __le16 fid_ctx_id; + u8 unused_2[5]; u8 valid; }; @@ -6567,6 +6613,31 @@ struct ctx_hw_stats { __le64 tpa_aborts; }; +/* ctx_hw_stats_ext (size:1344b/168B) */ +struct ctx_hw_stats_ext { + __le64 rx_ucast_pkts; + __le64 rx_mcast_pkts; + __le64 rx_bcast_pkts; + __le64 rx_discard_pkts; + __le64 rx_drop_pkts; + __le64 rx_ucast_bytes; + __le64 rx_mcast_bytes; + __le64 rx_bcast_bytes; + __le64 tx_ucast_pkts; + __le64 tx_mcast_pkts; + __le64 tx_bcast_pkts; + __le64 tx_discard_pkts; + __le64 tx_drop_pkts; + __le64 tx_ucast_bytes; + __le64 tx_mcast_bytes; + __le64 tx_bcast_bytes; + __le64 rx_tpa_eligible_pkt; + __le64 rx_tpa_eligible_bytes; + __le64 rx_tpa_pkt; + __le64 rx_tpa_bytes; + __le64 rx_tpa_errors; +}; + /* hwrm_stat_ctx_alloc_input (size:256b/32B) */ struct hwrm_stat_ctx_alloc_input { __le16 req_type; @@ -6578,7 +6649,8 @@ struct hwrm_stat_ctx_alloc_input { __le32 update_period_ms; u8 stat_ctx_flags; #define STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE 0x1UL - u8 unused_0[3]; + u8 unused_0; + __le16 stats_dma_length; }; /* hwrm_stat_ctx_alloc_output (size:128b/16B) */ @@ -7204,7 +7276,9 @@ struct coredump_segment_record { u8 version_hi; u8 version_low; u8 seg_flags; - u8 unused_0[7]; + u8 compress_flags; + #define SFLAG_COMPRESSED_ZLIB 0x1UL + u8 unused_0[6]; }; /* hwrm_dbg_coredump_list_input (size:256b/32B) */ @@ -7729,6 +7803,9 @@ struct hwrm_nvm_set_variable_input { #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_AES256 (0x2UL << 1) #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1_AUTH (0x3UL << 1) #define NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_LAST NVM_SET_VARIABLE_REQ_FLAGS_ENCRYPT_MODE_HMAC_SHA1_AUTH + #define NVM_SET_VARIABLE_REQ_FLAGS_FLAGS_UNUSED_0_MASK 0x70UL + #define NVM_SET_VARIABLE_REQ_FLAGS_FLAGS_UNUSED_0_SFT 4 + #define NVM_SET_VARIABLE_REQ_FLAGS_FACTORY_DEFAULT 0x80UL u8 unused_0; }; -- GitLab From 218a8a71d91ab9e52205f4098cf1fe121c98850e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:19 -0400 Subject: [PATCH 1084/7155] bnxt_en: Add TPA structure definitions for BCM57500 chips. The new chips have a slightly modified TPA interface for LRO/GRO_HW. Modify the TPA structures so that the same structures can also be used on the new chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 16694b704d15..650d8003d01d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -113,6 +113,7 @@ struct tx_cmp { #define CMP_TYPE_RX_AGG_CMP 18 #define CMP_TYPE_RX_L2_TPA_START_CMP 19 #define CMP_TYPE_RX_L2_TPA_END_CMP 21 + #define CMP_TYPE_RX_TPA_AGG_CMP 22 #define CMP_TYPE_STATUS_CMP 32 #define CMP_TYPE_REMOTE_DRIVER_REQ 34 #define CMP_TYPE_REMOTE_DRIVER_RESP 36 @@ -263,14 +264,21 @@ struct rx_agg_cmp { u32 rx_agg_cmp_opaque; __le32 rx_agg_cmp_v; #define RX_AGG_CMP_V (1 << 0) + #define RX_AGG_CMP_AGG_ID (0xffff << 16) + #define RX_AGG_CMP_AGG_ID_SHIFT 16 __le32 rx_agg_cmp_unused; }; +#define TPA_AGG_AGG_ID(rx_agg) \ + ((le32_to_cpu((rx_agg)->rx_agg_cmp_v) & \ + RX_AGG_CMP_AGG_ID) >> RX_AGG_CMP_AGG_ID_SHIFT) + struct rx_tpa_start_cmp { __le32 rx_tpa_start_cmp_len_flags_type; #define RX_TPA_START_CMP_TYPE (0x3f << 0) #define RX_TPA_START_CMP_FLAGS (0x3ff << 6) #define RX_TPA_START_CMP_FLAGS_SHIFT 6 + #define RX_TPA_START_CMP_FLAGS_ERROR (0x1 << 6) #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7) #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) @@ -278,6 +286,7 @@ struct rx_tpa_start_cmp { #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) #define RX_TPA_START_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_START_CMP_FLAGS_TIMESTAMP (0x1 << 11) #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 12) #define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12 #define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12) @@ -291,6 +300,8 @@ struct rx_tpa_start_cmp { #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 #define RX_TPA_START_CMP_AGG_ID (0x7f << 25) #define RX_TPA_START_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16 __le32 rx_tpa_start_cmp_rss_hash; }; @@ -308,6 +319,14 @@ struct rx_tpa_start_cmp { ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ RX_TPA_START_CMP_AGG_ID) >> RX_TPA_START_CMP_AGG_ID_SHIFT) +#define TPA_START_AGG_ID_P5(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_AGG_ID_P5) >> RX_TPA_START_CMP_AGG_ID_SHIFT_P5) + +#define TPA_START_ERROR(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_ERROR)) + struct rx_tpa_start_cmp_ext { __le32 rx_tpa_start_cmp_flags2; #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0) @@ -315,10 +334,20 @@ struct rx_tpa_start_cmp_ext { #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) #define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID (0x1 << 9) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT (0x3 << 10) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT_SHIFT 10 + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL (0xffff << 16) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_SHIFT 16 __le32 rx_tpa_start_cmp_metadata; __le32 rx_tpa_start_cmp_cfa_code_v2; #define RX_TPA_START_CMP_V2 (0x1 << 0) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK (0x7 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT 1 + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) #define RX_TPA_START_CMP_CFA_CODE (0xffff << 16) #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 __le32 rx_tpa_start_cmp_hdr_info; @@ -332,6 +361,11 @@ struct rx_tpa_start_cmp_ext { (!!((rx_tpa_start)->rx_tpa_start_cmp_flags2 & \ cpu_to_le32(RX_TPA_START_CMP_FLAGS2_IP_TYPE))) +#define TPA_START_ERROR_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK) >> \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT) + struct rx_tpa_end_cmp { __le32 rx_tpa_end_cmp_len_flags_type; #define RX_TPA_END_CMP_TYPE (0x3f << 0) @@ -361,6 +395,8 @@ struct rx_tpa_end_cmp { #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 #define RX_TPA_END_CMP_AGG_ID (0x7f << 25) #define RX_TPA_END_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_END_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_END_CMP_AGG_ID_SHIFT_P5 16 __le32 rx_tpa_end_cmp_tsdelta; #define RX_TPA_END_GRO_TS (0x1 << 31) @@ -370,6 +406,18 @@ struct rx_tpa_end_cmp { ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT) +#define TPA_END_AGG_ID_P5(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_ID_P5) >> RX_TPA_END_CMP_AGG_ID_SHIFT_P5) + +#define TPA_END_PAYLOAD_OFF(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET) >> RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT) + +#define TPA_END_AGG_BUFS(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT) + #define TPA_END_TPA_SEGS(rx_tpa_end) \ ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT) @@ -389,6 +437,10 @@ struct rx_tpa_end_cmp { struct rx_tpa_end_cmp_ext { __le32 rx_tpa_end_cmp_dup_acks; #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_P5 (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5 16 + #define RX_TPA_END_CMP_AGG_BUFS_P5 (0xff << 24) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5 24 __le32 rx_tpa_end_cmp_seg_len; #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0) @@ -396,7 +448,13 @@ struct rx_tpa_end_cmp_ext { __le32 rx_tpa_end_cmp_errors_v2; #define RX_TPA_END_CMP_V2 (0x1 << 0) #define RX_TPA_END_CMP_ERRORS (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_P5 (0x7 << 1) #define RX_TPA_END_CMPL_ERRORS_SHIFT 1 + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_RSV_ERROR (0x4 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) u32 rx_tpa_end_cmp_start_opaque; }; @@ -405,6 +463,15 @@ struct rx_tpa_end_cmp_ext { ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \ cpu_to_le32(RX_TPA_END_CMP_ERRORS)) +#define TPA_END_PAYLOAD_OFF_P5(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_P5) >> \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5) + +#define TPA_END_AGG_BUFS_P5(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_AGG_BUFS_P5) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5) + struct nqe_cn { __le16 type; #define NQ_CN_TYPE_MASK 0x3fUL -- GitLab From 4a228a3a5e58e5c05c6ffb5b430e5cb936865a8b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:20 -0400 Subject: [PATCH 1085/7155] bnxt_en: Refactor TPA logic. Refactor the TPA logic slightly, so that the code can be more easily extended to support TPA on the new 57500 chips. In particular, the logic to get the next aggregation completion is refactored into a new function bnxt_get_agg() so that this operation is made more generalized. This operation will be different on the new chip in TPA mode. The logic to recycle the aggregation buffers has a new start index parameter added for the same purpose. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 117 +++++++++++++--------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 1fedefd499ac..2491bf139cf5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -828,8 +828,20 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp, return 0; } -static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, - u32 agg_bufs) +static struct rx_agg_cmp *bnxt_get_agg(struct bnxt *bp, + struct bnxt_cp_ring_info *cpr, + u16 cp_cons, u16 curr) +{ + struct rx_agg_cmp *agg; + + cp_cons = RING_CMP(ADV_RAW_CMP(cp_cons, curr)); + agg = (struct rx_agg_cmp *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + return agg; +} + +static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 idx, + u16 start, u32 agg_bufs, bool tpa) { struct bnxt_napi *bnapi = cpr->bnapi; struct bnxt *bp = bnapi->bp; @@ -845,8 +857,7 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, struct rx_bd *prod_bd; struct page *page; - agg = (struct rx_agg_cmp *) - &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + agg = bnxt_get_agg(bp, cpr, idx, start + i); cons = agg->rx_agg_cmp_opaque; __clear_bit(cons, rxr->rx_agg_bmap); @@ -874,7 +885,6 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 cp_cons, prod = NEXT_RX_AGG(prod); sw_prod = NEXT_RX_AGG(sw_prod); - cp_cons = NEXT_CMP(cp_cons); } rxr->rx_agg_prod = prod; rxr->rx_sw_agg_prod = sw_prod; @@ -957,8 +967,8 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp, static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, - struct sk_buff *skb, u16 cp_cons, - u32 agg_bufs) + struct sk_buff *skb, u16 idx, + u32 agg_bufs, bool tpa) { struct bnxt_napi *bnapi = cpr->bnapi; struct pci_dev *pdev = bp->pdev; @@ -973,8 +983,7 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct page *page; dma_addr_t mapping; - agg = (struct rx_agg_cmp *) - &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + agg = bnxt_get_agg(bp, cpr, idx, i); cons = agg->rx_agg_cmp_opaque; frag_len = (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; @@ -1008,7 +1017,7 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, * allocated already. */ rxr->rx_agg_prod = prod; - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs - i); + bnxt_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i, tpa); return NULL; } @@ -1021,7 +1030,6 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, skb->truesize += PAGE_SIZE; prod = NEXT_RX_AGG(prod); - cp_cons = NEXT_CMP(cp_cons); } rxr->rx_agg_prod = prod; return skb; @@ -1081,9 +1089,7 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) { struct rx_tpa_end_cmp *tpa_end = cmp; - agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_AGG_BUFS) >> - RX_TPA_END_CMP_AGG_BUFS_SHIFT; + agg_bufs = TPA_END_AGG_BUFS(tpa_end); } if (agg_bufs) { @@ -1195,11 +1201,10 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, cons_rx_buf->data = NULL; } -static void bnxt_abort_tpa(struct bnxt_cp_ring_info *cpr, u16 cp_cons, - u32 agg_bufs) +static void bnxt_abort_tpa(struct bnxt_cp_ring_info *cpr, u16 idx, u32 agg_bufs) { if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, idx, 0, agg_bufs, true); } static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, @@ -1371,9 +1376,7 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp, skb_shinfo(skb)->gso_size = le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); skb_shinfo(skb)->gso_type = tpa_info->gso_type; - payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_PAYLOAD_OFFSET) >> - RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT; + payload_off = TPA_END_PAYLOAD_OFF(tpa_end); skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb); if (likely(skb)) tcp_gro_complete(skb); @@ -1403,11 +1406,11 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; u8 agg_id = TPA_END_AGG_ID(tpa_end); u8 *data_ptr, agg_bufs; - u16 cp_cons = RING_CMP(*raw_cons); unsigned int len; struct bnxt_tpa_info *tpa_info; dma_addr_t mapping; struct sk_buff *skb; + u16 idx = 0; void *data; if (unlikely(bnapi->in_reset)) { @@ -1425,19 +1428,19 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, len = tpa_info->len; mapping = tpa_info->mapping; - agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & - RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT; + agg_bufs = TPA_END_AGG_BUFS(tpa_end); if (agg_bufs) { + idx = RING_CMP(*raw_cons); if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) return ERR_PTR(-EBUSY); *event |= BNXT_AGG_EVENT; - cp_cons = NEXT_CMP(cp_cons); + idx = NEXT_CMP(idx); } if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); if (agg_bufs > MAX_SKB_FRAGS) netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", agg_bufs, (int)MAX_SKB_FRAGS); @@ -1447,7 +1450,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (len <= bp->rx_copy_thresh) { skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping); if (!skb) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } } else { @@ -1456,7 +1459,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC); if (!new_data) { - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } @@ -1471,7 +1474,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (!skb) { kfree(data); - bnxt_abort_tpa(cpr, cp_cons, agg_bufs); + bnxt_abort_tpa(cpr, idx, agg_bufs); return NULL; } skb_reserve(skb, bp->rx_offset); @@ -1479,7 +1482,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, } if (agg_bufs) { - skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs); + skb = bnxt_rx_pages(bp, cpr, skb, idx, agg_bufs, true); if (!skb) { /* Page reuse already handled by bnxt_rx_pages(). */ return NULL; @@ -1623,7 +1626,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, bnxt_reuse_rx_data(rxr, cons, data); if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs, + false); rc = -EIO; if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) { @@ -1646,7 +1650,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, bnxt_reuse_rx_data(rxr, cons, data); if (!skb) { if (agg_bufs) - bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs); + bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0, + agg_bufs, false); rc = -ENOMEM; goto next_rx; } @@ -1666,7 +1671,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } if (agg_bufs) { - skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs); + skb = bnxt_rx_pages(bp, cpr, skb, cp_cons, agg_bufs, false); if (!skb) { rc = -ENOMEM; goto next_rx; @@ -2483,6 +2488,33 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) return 0; } +static void bnxt_free_tpa_info(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + + kfree(rxr->rx_tpa); + rxr->rx_tpa = NULL; + } +} + +static int bnxt_alloc_tpa_info(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + + rxr->rx_tpa = kcalloc(MAX_TPA, sizeof(struct bnxt_tpa_info), + GFP_KERNEL); + if (!rxr->rx_tpa) + return -ENOMEM; + } + return 0; +} + static void bnxt_free_rx_rings(struct bnxt *bp) { int i; @@ -2490,6 +2522,7 @@ static void bnxt_free_rx_rings(struct bnxt *bp) if (!bp->rx_ring) return; + bnxt_free_tpa_info(bp); for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; struct bnxt_ring_struct *ring; @@ -2503,9 +2536,6 @@ static void bnxt_free_rx_rings(struct bnxt *bp) page_pool_destroy(rxr->page_pool); rxr->page_pool = NULL; - kfree(rxr->rx_tpa); - rxr->rx_tpa = NULL; - kfree(rxr->rx_agg_bmap); rxr->rx_agg_bmap = NULL; @@ -2539,7 +2569,7 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, static int bnxt_alloc_rx_rings(struct bnxt *bp) { - int i, rc, agg_rings = 0, tpa_rings = 0; + int i, rc = 0, agg_rings = 0; if (!bp->rx_ring) return -ENOMEM; @@ -2547,9 +2577,6 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp) if (bp->flags & BNXT_FLAG_AGG_RINGS) agg_rings = 1; - if (bp->flags & BNXT_FLAG_TPA) - tpa_rings = 1; - for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; struct bnxt_ring_struct *ring; @@ -2591,17 +2618,11 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp) rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL); if (!rxr->rx_agg_bmap) return -ENOMEM; - - if (tpa_rings) { - rxr->rx_tpa = kcalloc(MAX_TPA, - sizeof(struct bnxt_tpa_info), - GFP_KERNEL); - if (!rxr->rx_tpa) - return -ENOMEM; - } } } - return 0; + if (bp->flags & BNXT_FLAG_TPA) + rc = bnxt_alloc_tpa_info(bp); + return rc; } static void bnxt_free_tx_rings(struct bnxt *bp) -- GitLab From 79632e9ba38671215fb193346ef6fb8db582744d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:21 -0400 Subject: [PATCH 1086/7155] bnxt_en: Expand bnxt_tpa_info struct to support 57500 chips. Add an aggregation array to bnxt_tpa_info struct to keep track of the aggregation completions. The aggregation completions are not completed at the TPA_END completion on 57500 chips so we need to keep track of them. The array is only allocated on the new chips when required. An agg_count field is also added to keep track of the number of these completions. The maximum concurrent TPA is now discovered from firmware instead of the hardcoded 64. Add a new bp->max_tpa to keep track of maximum configured TPA. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 41 +++++++++++++++++++---- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 6 ++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 2491bf139cf5..47f59e0ae147 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2333,7 +2333,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp) int j; if (rxr->rx_tpa) { - for (j = 0; j < MAX_TPA; j++) { + for (j = 0; j < bp->max_tpa; j++) { struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[j]; u8 *data = tpa_info->data; @@ -2495,6 +2495,10 @@ static void bnxt_free_tpa_info(struct bnxt *bp) for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + if (rxr->rx_tpa) { + kfree(rxr->rx_tpa[0].agg_arr); + rxr->rx_tpa[0].agg_arr = NULL; + } kfree(rxr->rx_tpa); rxr->rx_tpa = NULL; } @@ -2502,15 +2506,33 @@ static void bnxt_free_tpa_info(struct bnxt *bp) static int bnxt_alloc_tpa_info(struct bnxt *bp) { - int i; + int i, j, total_aggs = 0; + + bp->max_tpa = MAX_TPA; + if (bp->flags & BNXT_FLAG_CHIP_P5) { + if (!bp->max_tpa_v2) + return 0; + bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5); + total_aggs = bp->max_tpa * MAX_SKB_FRAGS; + } for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + struct rx_agg_cmp *agg; - rxr->rx_tpa = kcalloc(MAX_TPA, sizeof(struct bnxt_tpa_info), + rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info), GFP_KERNEL); if (!rxr->rx_tpa) return -ENOMEM; + + if (!(bp->flags & BNXT_FLAG_CHIP_P5)) + continue; + agg = kcalloc(total_aggs, sizeof(*agg), GFP_KERNEL); + rxr->rx_tpa[0].agg_arr = agg; + if (!agg) + return -ENOMEM; + for (j = 1; j < bp->max_tpa; j++) + rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS; } return 0; } @@ -2974,7 +2996,7 @@ static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr) u8 *data; dma_addr_t mapping; - for (i = 0; i < MAX_TPA; i++) { + for (i = 0; i < bp->max_tpa; i++) { data = __bnxt_alloc_rx_data(bp, &mapping, GFP_KERNEL); if (!data) @@ -4435,6 +4457,7 @@ static int bnxt_hwrm_clear_vnic_filter(struct bnxt *bp) static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) { struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + u16 max_aggs = VNIC_TPA_CFG_REQ_MAX_AGGS_MAX; struct hwrm_vnic_tpa_cfg_input req = {0}; if (vnic->fw_vnic_id == INVALID_HW_RING_ID) @@ -4474,9 +4497,14 @@ static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) nsegs = (MAX_SKB_FRAGS - n) / n; } - segs = ilog2(nsegs); + if (bp->flags & BNXT_FLAG_CHIP_P5) { + segs = MAX_TPA_SEGS_P5; + max_aggs = bp->max_tpa; + } else { + segs = ilog2(nsegs); + } req.max_agg_segs = cpu_to_le16(segs); - req.max_aggs = cpu_to_le16(VNIC_TPA_CFG_REQ_MAX_AGGS_MAX); + req.max_aggs = cpu_to_le16(max_aggs); req.min_agg_len = cpu_to_le32(512); } @@ -4836,6 +4864,7 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) if (flags & VNIC_QCAPS_RESP_FLAGS_ROCE_MIRRORING_CAPABLE_VNIC_CAP) bp->flags |= BNXT_FLAG_ROCE_MIRROR_CAP; + bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported); } mutex_unlock(&bp->hwrm_cmd_lock); return rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 650d8003d01d..290f42669ba5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -554,6 +554,8 @@ struct nqe_cn { #define BNXT_DEFAULT_TX_RING_SIZE 511 #define MAX_TPA 64 +#define MAX_TPA_P5 256 +#define MAX_TPA_SEGS_P5 0x3f #if (BNXT_PAGE_SHIFT == 16) #define MAX_RX_PAGES 1 @@ -835,6 +837,8 @@ struct bnxt_tpa_info { ((hdr_info) & 0x1ff) u16 cfa_code; /* cfa_code in TPA start compl */ + u8 agg_count; + struct rx_agg_cmp *agg_arr; }; struct bnxt_rx_ring_info { @@ -1481,6 +1485,8 @@ struct bnxt { u16, void *, u8 *, dma_addr_t, unsigned int); + u16 max_tpa_v2; + u16 max_tpa; u32 rx_buf_size; u32 rx_buf_use_size; /* useable size */ u16 rx_offset; -- GitLab From 8fe88ce7ab3181a11989eb7a8bb00c42a2b7b3b0 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:22 -0400 Subject: [PATCH 1087/7155] bnxt_en: Handle standalone RX_AGG completions. On the new 57500 chips, these new RX_AGG completions are not coalesced at the TPA_END completion. Handle these by storing them in the array in the bnxt_tpa_info struct, as they are seen when processing the CMPL ring. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 47f59e0ae147..f0867402f3b0 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1517,6 +1517,17 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, return skb; } +static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, + struct rx_agg_cmp *rx_agg) +{ + u16 agg_id = TPA_AGG_AGG_ID(rx_agg); + struct bnxt_tpa_info *tpa_info; + + tpa_info = &rxr->rx_tpa[agg_id]; + BUG_ON(tpa_info->agg_count >= MAX_SKB_FRAGS); + tpa_info->agg_arr[tpa_info->agg_count++] = *rx_agg; +} + static void bnxt_deliver_skb(struct bnxt *bp, struct bnxt_napi *bnapi, struct sk_buff *skb) { @@ -1558,6 +1569,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, rxcmp = (struct rx_cmp *) &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + cmp_type = RX_CMP_TYPE(rxcmp); + + if (cmp_type == CMP_TYPE_RX_TPA_AGG_CMP) { + bnxt_tpa_agg(bp, rxr, (struct rx_agg_cmp *)rxcmp); + goto next_rx_no_prod_no_len; + } + tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons); cp_cons = RING_CMP(tmp_raw_cons); rxcmp1 = (struct rx_cmp_ext *) @@ -1566,8 +1584,6 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) return -EBUSY; - cmp_type = RX_CMP_TYPE(rxcmp); - prod = rxr->rx_prod; if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) { -- GitLab From bee5a188b71657092dc9eb1a529b4e502fe51444 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:23 -0400 Subject: [PATCH 1088/7155] bnxt_en: Refactor tunneled hardware GRO logic. The 2 GRO functions to set up the hardware GRO SKB fields for 2 different hardware chips have practically identical logic for tunneled packets. Refactor the logic into a separate bnxt_gro_tunnel() function that can be used by both functions. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 69 +++++++++-------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f0867402f3b0..4a3f4abd3c79 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1207,6 +1207,31 @@ static void bnxt_abort_tpa(struct bnxt_cp_ring_info *cpr, u16 idx, u32 agg_bufs) bnxt_reuse_rx_agg_bufs(cpr, idx, 0, agg_bufs, true); } +#ifdef CONFIG_INET +static void bnxt_gro_tunnel(struct sk_buff *skb, __be16 ip_proto) +{ + struct udphdr *uh = NULL; + + if (ip_proto == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)skb->data; + + if (iph->protocol == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } else { + struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; + + if (iph->nexthdr == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } + if (uh) { + if (uh->check) + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; + else + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; + } +} +#endif + static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, int payload_off, int tcp_ts, struct sk_buff *skb) @@ -1264,28 +1289,10 @@ static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, } if (inner_mac_off) { /* tunnel */ - struct udphdr *uh = NULL; __be16 proto = *((__be16 *)(skb->data + outer_ip_off - ETH_HLEN - 2)); - if (proto == htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)skb->data; - - if (iph->protocol == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } else { - struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; - - if (iph->nexthdr == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } - if (uh) { - if (uh->check) - skb_shinfo(skb)->gso_type |= - SKB_GSO_UDP_TUNNEL_CSUM; - else - skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; - } + bnxt_gro_tunnel(skb, proto); } #endif return skb; @@ -1332,28 +1339,8 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info, return NULL; } - if (nw_off) { /* tunnel */ - struct udphdr *uh = NULL; - - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)skb->data; - - if (iph->protocol == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } else { - struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; - - if (iph->nexthdr == IPPROTO_UDP) - uh = (struct udphdr *)(iph + 1); - } - if (uh) { - if (uh->check) - skb_shinfo(skb)->gso_type |= - SKB_GSO_UDP_TUNNEL_CSUM; - else - skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; - } - } + if (nw_off) /* tunnel */ + bnxt_gro_tunnel(skb, skb->protocol); #endif return skb; } -- GitLab From f45b7b78c619cd73c7ca25b68c6ba9653b8e4a0a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:24 -0400 Subject: [PATCH 1089/7155] bnxt_en: Set TPA GRO mode flags on 57500 chips properly. On 57500 chips, hardware GRO mode cannot be determined from the TPA end, so we need to check bp->flags to determine if we are in hardware GRO mode or not. Modify bnxt_set_features so that the TPA flags in bp->flags don't change until the device is closed. This will ensure that the fast path can safely rely on bp->flags to determine the TPA mode. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4a3f4abd3c79..ef0d2c0a8d87 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9345,7 +9345,8 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (changes & BNXT_FLAG_TPA) { update_tpa = true; if ((bp->flags & BNXT_FLAG_TPA) == 0 || - (flags & BNXT_FLAG_TPA) == 0) + (flags & BNXT_FLAG_TPA) == 0 || + (bp->flags & BNXT_FLAG_CHIP_P5)) re_init = true; } @@ -9355,9 +9356,8 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (flags != bp->flags) { u32 old_flags = bp->flags; - bp->flags = flags; - if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { + bp->flags = flags; if (update_tpa) bnxt_set_ring_params(bp); return rc; @@ -9365,12 +9365,14 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) if (re_init) { bnxt_close_nic(bp, false, false); + bp->flags = flags; if (update_tpa) bnxt_set_ring_params(bp); return bnxt_open_nic(bp, false, false); } if (update_tpa) { + bp->flags = flags; rc = bnxt_set_tpa(bp, (flags & BNXT_FLAG_TPA) ? true : false); -- GitLab From bfcd8d791ec18496772d117774398e336917f56e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:25 -0400 Subject: [PATCH 1090/7155] bnxt_en: Add fast path logic for TPA on 57500 chips. With all the previous refactoring, the TPA fast path can now be modified slightly to support TPA on the new chips. The main difference is that the agg completions are retrieved differently using the bnxt_get_tpa_agg_p5() function on the new chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 100 ++++++++++++++++------ 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index ef0d2c0a8d87..59358e5ddc37 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -840,6 +840,15 @@ static struct rx_agg_cmp *bnxt_get_agg(struct bnxt *bp, return agg; } +static struct rx_agg_cmp *bnxt_get_tpa_agg_p5(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr, + u16 agg_id, u16 curr) +{ + struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[agg_id]; + + return &tpa_info->agg_arr[curr]; +} + static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 idx, u16 start, u32 agg_bufs, bool tpa) { @@ -848,8 +857,12 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 idx, struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; u16 prod = rxr->rx_agg_prod; u16 sw_prod = rxr->rx_sw_agg_prod; + bool p5_tpa = false; u32 i; + if ((bp->flags & BNXT_FLAG_CHIP_P5) && tpa) + p5_tpa = true; + for (i = 0; i < agg_bufs; i++) { u16 cons; struct rx_agg_cmp *agg; @@ -857,7 +870,10 @@ static void bnxt_reuse_rx_agg_bufs(struct bnxt_cp_ring_info *cpr, u16 idx, struct rx_bd *prod_bd; struct page *page; - agg = bnxt_get_agg(bp, cpr, idx, start + i); + if (p5_tpa) + agg = bnxt_get_tpa_agg_p5(bp, rxr, idx, start + i); + else + agg = bnxt_get_agg(bp, cpr, idx, start + i); cons = agg->rx_agg_cmp_opaque; __clear_bit(cons, rxr->rx_agg_bmap); @@ -974,8 +990,12 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct pci_dev *pdev = bp->pdev; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; u16 prod = rxr->rx_agg_prod; + bool p5_tpa = false; u32 i; + if ((bp->flags & BNXT_FLAG_CHIP_P5) && tpa) + p5_tpa = true; + for (i = 0; i < agg_bufs; i++) { u16 cons, frag_len; struct rx_agg_cmp *agg; @@ -983,7 +1003,10 @@ static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct page *page; dma_addr_t mapping; - agg = bnxt_get_agg(bp, cpr, idx, i); + if (p5_tpa) + agg = bnxt_get_tpa_agg_p5(bp, rxr, idx, i); + else + agg = bnxt_get_agg(bp, cpr, idx, i); cons = agg->rx_agg_cmp_opaque; frag_len = (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; @@ -1089,6 +1112,9 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) { struct rx_tpa_end_cmp *tpa_end = cmp; + if (bp->flags & BNXT_FLAG_CHIP_P5) + return 0; + agg_bufs = TPA_END_AGG_BUFS(tpa_end); } @@ -1130,22 +1156,27 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, struct rx_tpa_start_cmp *tpa_start, struct rx_tpa_start_cmp_ext *tpa_start1) { - u8 agg_id = TPA_START_AGG_ID(tpa_start); - u16 cons, prod; - struct bnxt_tpa_info *tpa_info; struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnxt_tpa_info *tpa_info; + u16 cons, prod, agg_id; struct rx_bd *prod_bd; dma_addr_t mapping; + if (bp->flags & BNXT_FLAG_CHIP_P5) + agg_id = TPA_START_AGG_ID_P5(tpa_start); + else + agg_id = TPA_START_AGG_ID(tpa_start); cons = tpa_start->rx_tpa_start_cmp_opaque; prod = rxr->rx_prod; cons_rx_buf = &rxr->rx_buf_ring[cons]; prod_rx_buf = &rxr->rx_buf_ring[prod]; tpa_info = &rxr->rx_tpa[agg_id]; - if (unlikely(cons != rxr->rx_next_cons)) { - netdev_warn(bp->dev, "TPA cons %x != expected cons %x\n", - cons, rxr->rx_next_cons); + if (unlikely(cons != rxr->rx_next_cons || + TPA_START_ERROR(tpa_start))) { + netdev_warn(bp->dev, "TPA cons %x, expected cons %x, error code %x\n", + cons, rxr->rx_next_cons, + TPA_START_ERROR_CODE(tpa_start1)); bnxt_sched_reset(bp, rxr); return; } @@ -1190,6 +1221,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, tpa_info->flags2 = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2); tpa_info->metadata = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata); tpa_info->hdr_info = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_hdr_info); + tpa_info->agg_count = 0; rxr->rx_prod = NEXT_RX(prod); cons = NEXT_RX(cons); @@ -1363,7 +1395,10 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp, skb_shinfo(skb)->gso_size = le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); skb_shinfo(skb)->gso_type = tpa_info->gso_type; - payload_off = TPA_END_PAYLOAD_OFF(tpa_end); + if (bp->flags & BNXT_FLAG_CHIP_P5) + payload_off = TPA_END_PAYLOAD_OFF_P5(tpa_end1); + else + payload_off = TPA_END_PAYLOAD_OFF(tpa_end); skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb); if (likely(skb)) tcp_gro_complete(skb); @@ -1391,14 +1426,14 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, { struct bnxt_napi *bnapi = cpr->bnapi; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; - u8 agg_id = TPA_END_AGG_ID(tpa_end); u8 *data_ptr, agg_bufs; unsigned int len; struct bnxt_tpa_info *tpa_info; dma_addr_t mapping; struct sk_buff *skb; - u16 idx = 0; + u16 idx = 0, agg_id; void *data; + bool gro; if (unlikely(bnapi->in_reset)) { int rc = bnxt_discard_rx(bp, cpr, raw_cons, tpa_end); @@ -1408,24 +1443,39 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, return NULL; } - tpa_info = &rxr->rx_tpa[agg_id]; + if (bp->flags & BNXT_FLAG_CHIP_P5) { + agg_id = TPA_END_AGG_ID_P5(tpa_end); + agg_bufs = TPA_END_AGG_BUFS_P5(tpa_end1); + tpa_info = &rxr->rx_tpa[agg_id]; + if (unlikely(agg_bufs != tpa_info->agg_count)) { + netdev_warn(bp->dev, "TPA end agg_buf %d != expected agg_bufs %d\n", + agg_bufs, tpa_info->agg_count); + agg_bufs = tpa_info->agg_count; + } + tpa_info->agg_count = 0; + *event |= BNXT_AGG_EVENT; + idx = agg_id; + gro = !!(bp->flags & BNXT_FLAG_GRO); + } else { + agg_id = TPA_END_AGG_ID(tpa_end); + agg_bufs = TPA_END_AGG_BUFS(tpa_end); + tpa_info = &rxr->rx_tpa[agg_id]; + idx = RING_CMP(*raw_cons); + if (agg_bufs) { + if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) + return ERR_PTR(-EBUSY); + + *event |= BNXT_AGG_EVENT; + idx = NEXT_CMP(idx); + } + gro = !!TPA_END_GRO(tpa_end); + } data = tpa_info->data; data_ptr = tpa_info->data_ptr; prefetch(data_ptr); len = tpa_info->len; mapping = tpa_info->mapping; - agg_bufs = TPA_END_AGG_BUFS(tpa_end); - - if (agg_bufs) { - idx = RING_CMP(*raw_cons); - if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) - return ERR_PTR(-EBUSY); - - *event |= BNXT_AGG_EVENT; - idx = NEXT_CMP(idx); - } - if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) { bnxt_abort_tpa(cpr, idx, agg_bufs); if (agg_bufs > MAX_SKB_FRAGS) @@ -1498,7 +1548,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3; } - if (TPA_END_GRO(tpa_end)) + if (gro) skb = bnxt_gro_skb(bp, tpa_info, tpa_end, tpa_end1, skb); return skb; @@ -10785,7 +10835,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #endif if (BNXT_SUPPORTS_TPA(bp)) { bp->gro_func = bnxt_gro_func_5730x; - if (BNXT_CHIP_P4(bp)) + if (BNXT_CHIP_P4_PLUS(bp)) bp->gro_func = bnxt_gro_func_5731x; } if (!BNXT_CHIP_P4_PLUS(bp)) -- GitLab From ec4d8e7cf024e42def027531676918048e5c7982 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:26 -0400 Subject: [PATCH 1091/7155] bnxt_en: Add TPA ID mapping logic for 57500 chips. The new TPA feature on 57500 supports a larger number of concurrent TPAs (up to 1024) divided among the functions. We need to add some logic to map the hardware TPA ID to a software index that keeps track of each TPA in progress. A 1:1 direct mapping without translation would be too wasteful as we would have to allocate 1024 TPA structures for each RX ring on each PCI function. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 46 ++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 9 +++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 59358e5ddc37..05c69a5626be 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1152,6 +1152,33 @@ static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) rxr->rx_next_cons = 0xffff; } +static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + u16 idx = agg_id & MAX_TPA_P5_MASK; + + if (test_bit(idx, map->agg_idx_bmap)) + idx = find_first_zero_bit(map->agg_idx_bmap, + BNXT_AGG_IDX_BMAP_SIZE); + __set_bit(idx, map->agg_idx_bmap); + map->agg_id_tbl[agg_id] = idx; + return idx; +} + +static void bnxt_free_agg_idx(struct bnxt_rx_ring_info *rxr, u16 idx) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + + __clear_bit(idx, map->agg_idx_bmap); +} + +static u16 bnxt_lookup_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id) +{ + struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; + + return map->agg_id_tbl[agg_id]; +} + static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, struct rx_tpa_start_cmp *tpa_start, struct rx_tpa_start_cmp_ext *tpa_start1) @@ -1162,10 +1189,12 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, struct rx_bd *prod_bd; dma_addr_t mapping; - if (bp->flags & BNXT_FLAG_CHIP_P5) + if (bp->flags & BNXT_FLAG_CHIP_P5) { agg_id = TPA_START_AGG_ID_P5(tpa_start); - else + agg_id = bnxt_alloc_agg_idx(rxr, agg_id); + } else { agg_id = TPA_START_AGG_ID(tpa_start); + } cons = tpa_start->rx_tpa_start_cmp_opaque; prod = rxr->rx_prod; cons_rx_buf = &rxr->rx_buf_ring[cons]; @@ -1445,6 +1474,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (bp->flags & BNXT_FLAG_CHIP_P5) { agg_id = TPA_END_AGG_ID_P5(tpa_end); + agg_id = bnxt_lookup_agg_idx(rxr, agg_id); agg_bufs = TPA_END_AGG_BUFS_P5(tpa_end1); tpa_info = &rxr->rx_tpa[agg_id]; if (unlikely(agg_bufs != tpa_info->agg_count)) { @@ -1454,6 +1484,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, } tpa_info->agg_count = 0; *event |= BNXT_AGG_EVENT; + bnxt_free_agg_idx(rxr, agg_id); idx = agg_id; gro = !!(bp->flags & BNXT_FLAG_GRO); } else { @@ -1560,6 +1591,7 @@ static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 agg_id = TPA_AGG_AGG_ID(rx_agg); struct bnxt_tpa_info *tpa_info; + agg_id = bnxt_lookup_agg_idx(rxr, agg_id); tpa_info = &rxr->rx_tpa[agg_id]; BUG_ON(tpa_info->agg_count >= MAX_SKB_FRAGS); tpa_info->agg_arr[tpa_info->agg_count++] = *rx_agg; @@ -2383,6 +2415,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp) max_agg_idx = bp->rx_agg_nr_pages * RX_DESC_CNT; for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + struct bnxt_tpa_idx_map *map; int j; if (rxr->rx_tpa) { @@ -2453,6 +2486,9 @@ static void bnxt_free_rx_skbs(struct bnxt *bp) __free_page(rxr->rx_page); rxr->rx_page = NULL; } + map = rxr->rx_tpa_idx_map; + if (map) + memset(map->agg_idx_bmap, 0, sizeof(map->agg_idx_bmap)); } } @@ -2548,6 +2584,8 @@ static void bnxt_free_tpa_info(struct bnxt *bp) for (i = 0; i < bp->rx_nr_rings; i++) { struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i]; + kfree(rxr->rx_tpa_idx_map); + rxr->rx_tpa_idx_map = NULL; if (rxr->rx_tpa) { kfree(rxr->rx_tpa[0].agg_arr); rxr->rx_tpa[0].agg_arr = NULL; @@ -2586,6 +2624,10 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp) return -ENOMEM; for (j = 1; j < bp->max_tpa; j++) rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS; + rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map), + GFP_KERNEL); + if (!rxr->rx_tpa_idx_map) + return -ENOMEM; } return 0; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 290f42669ba5..309cf99bcda9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -555,6 +555,7 @@ struct nqe_cn { #define MAX_TPA 64 #define MAX_TPA_P5 256 +#define MAX_TPA_P5_MASK (MAX_TPA_P5 - 1) #define MAX_TPA_SEGS_P5 0x3f #if (BNXT_PAGE_SHIFT == 16) @@ -841,6 +842,13 @@ struct bnxt_tpa_info { struct rx_agg_cmp *agg_arr; }; +#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG) + +struct bnxt_tpa_idx_map { + u16 agg_id_tbl[1024]; + unsigned long agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE]; +}; + struct bnxt_rx_ring_info { struct bnxt_napi *bnapi; u16 rx_prod; @@ -868,6 +876,7 @@ struct bnxt_rx_ring_info { dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; struct bnxt_tpa_info *rx_tpa; + struct bnxt_tpa_idx_map *rx_tpa_idx_map; struct bnxt_ring_struct rx_ring_struct; struct bnxt_ring_struct rx_agg_ring_struct; -- GitLab From 67912c366d4bb0a9d108459e7c845cc7ba83f76f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:27 -0400 Subject: [PATCH 1092/7155] bnxt_en: Add hardware GRO setup function for 57500 chips. Add a more optimized hardware GRO function to setup the SKB on 57500 chips. Some workaround code is no longer needed on 57500 chips and the pseudo checksum is also calculated in hardware, so no need to do the software pseudo checksum in the driver. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 05c69a5626be..9269a94455a9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1359,6 +1359,35 @@ static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info, return skb; } +static struct sk_buff *bnxt_gro_func_5750x(struct bnxt_tpa_info *tpa_info, + int payload_off, int tcp_ts, + struct sk_buff *skb) +{ +#ifdef CONFIG_INET + u16 outer_ip_off, inner_ip_off, inner_mac_off; + u32 hdr_info = tpa_info->hdr_info; + int iphdr_len, nw_off; + + inner_ip_off = BNXT_TPA_INNER_L3_OFF(hdr_info); + inner_mac_off = BNXT_TPA_INNER_L2_OFF(hdr_info); + outer_ip_off = BNXT_TPA_OUTER_L3_OFF(hdr_info); + + nw_off = inner_ip_off - ETH_HLEN; + skb_set_network_header(skb, nw_off); + iphdr_len = (tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_IP_TYPE) ? + sizeof(struct ipv6hdr) : sizeof(struct iphdr); + skb_set_transport_header(skb, nw_off + iphdr_len); + + if (inner_mac_off) { /* tunnel */ + __be16 proto = *((__be16 *)(skb->data + outer_ip_off - + ETH_HLEN - 2)); + + bnxt_gro_tunnel(skb, proto); + } +#endif + return skb; +} + #define BNXT_IPV4_HDR_SIZE (sizeof(struct iphdr) + sizeof(struct tcphdr)) #define BNXT_IPV6_HDR_SIZE (sizeof(struct ipv6hdr) + sizeof(struct tcphdr)) @@ -10877,8 +10906,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #endif if (BNXT_SUPPORTS_TPA(bp)) { bp->gro_func = bnxt_gro_func_5730x; - if (BNXT_CHIP_P4_PLUS(bp)) + if (BNXT_CHIP_P4(bp)) bp->gro_func = bnxt_gro_func_5731x; + else if (BNXT_CHIP_P5(bp)) + bp->gro_func = bnxt_gro_func_5750x; } if (!BNXT_CHIP_P4_PLUS(bp)) bp->flags |= BNXT_FLAG_DOUBLE_DB; -- GitLab From ee79566e65945dcf557bcfb9335e46fac67fb002 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:28 -0400 Subject: [PATCH 1093/7155] bnxt_en: Refactor ethtool ring statistics logic. The current code assumes that the per ring statistics counters are fixed. In newer chips that support a newer version of TPA, the TPA counters are also changed. Refactor the code by defining these counter names in arrays so that it is easy to add a new array for a new set of counters supported by the newer chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 120 ++++++++++-------- 1 file changed, 70 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 1eb590eac47a..a3a7becce01c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -137,7 +137,36 @@ static int bnxt_set_coalesce(struct net_device *dev, return rc; } -#define BNXT_NUM_STATS 22 +static const char * const bnxt_ring_stats_str[] = { + "rx_ucast_packets", + "rx_mcast_packets", + "rx_bcast_packets", + "rx_discards", + "rx_drops", + "rx_ucast_bytes", + "rx_mcast_bytes", + "rx_bcast_bytes", + "tx_ucast_packets", + "tx_mcast_packets", + "tx_bcast_packets", + "tx_discards", + "tx_drops", + "tx_ucast_bytes", + "tx_mcast_bytes", + "tx_bcast_bytes", +}; + +static const char * const bnxt_ring_tpa_stats_str[] = { + "tpa_packets", + "tpa_bytes", + "tpa_events", + "tpa_aborts", +}; + +static const char * const bnxt_ring_sw_stats_str[] = { + "rx_l4_csum_errors", + "missed_irqs", +}; #define BNXT_RX_STATS_ENTRY(counter) \ { BNXT_RX_STATS_OFFSET(counter), __stringify(counter) } @@ -432,9 +461,20 @@ static const struct { ARRAY_SIZE(bnxt_tx_pkts_pri_arr)) #define BNXT_NUM_PCIE_STATS ARRAY_SIZE(bnxt_pcie_stats_arr) +static int bnxt_get_num_ring_stats(struct bnxt *bp) +{ + int num_stats; + + num_stats = ARRAY_SIZE(bnxt_ring_stats_str) + + ARRAY_SIZE(bnxt_ring_sw_stats_str); + if (BNXT_SUPPORTS_TPA(bp)) + num_stats += ARRAY_SIZE(bnxt_ring_tpa_stats_str); + return num_stats * bp->cp_nr_rings; +} + static int bnxt_get_num_stats(struct bnxt *bp) { - int num_stats = BNXT_NUM_STATS * bp->cp_nr_rings; + int num_stats = bnxt_get_num_ring_stats(bp); num_stats += BNXT_NUM_SW_FUNC_STATS; @@ -475,10 +515,13 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, { u32 i, j = 0; struct bnxt *bp = netdev_priv(dev); - u32 stat_fields = sizeof(struct ctx_hw_stats) / 8; + u32 stat_fields = ARRAY_SIZE(bnxt_ring_stats_str); + + if (BNXT_SUPPORTS_TPA(bp)) + stat_fields += ARRAY_SIZE(bnxt_ring_tpa_stats_str); if (!bp->bnapi) { - j += BNXT_NUM_STATS * bp->cp_nr_rings + BNXT_NUM_SW_FUNC_STATS; + j += bnxt_get_num_ring_stats(bp) + BNXT_NUM_SW_FUNC_STATS; goto skip_ring_stats; } @@ -566,56 +609,33 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnxt *bp = netdev_priv(dev); - u32 i; + u32 i, j, num_str; switch (stringset) { - /* The number of strings must match BNXT_NUM_STATS defined above. */ case ETH_SS_STATS: for (i = 0; i < bp->cp_nr_rings; i++) { - sprintf(buf, "[%d]: rx_ucast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_mcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_bcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_discards", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_drops", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_ucast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_mcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_bcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_ucast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_mcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_bcast_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_discards", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_drops", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_ucast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_mcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tx_bcast_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_packets", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_bytes", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_events", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: tpa_aborts", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: rx_l4_csum_errors", i); - buf += ETH_GSTRING_LEN; - sprintf(buf, "[%d]: missed_irqs", i); - buf += ETH_GSTRING_LEN; + num_str = ARRAY_SIZE(bnxt_ring_stats_str); + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, + bnxt_ring_stats_str[j]); + buf += ETH_GSTRING_LEN; + } + if (!BNXT_SUPPORTS_TPA(bp)) + goto skip_tpa_stats; + + num_str = ARRAY_SIZE(bnxt_ring_tpa_stats_str); + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, + bnxt_ring_tpa_stats_str[j]); + buf += ETH_GSTRING_LEN; + } +skip_tpa_stats: + num_str = ARRAY_SIZE(bnxt_ring_sw_stats_str); + for (j = 0; j < num_str; j++) { + sprintf(buf, "[%d]: %s", i, + bnxt_ring_sw_stats_str[j]); + buf += ETH_GSTRING_LEN; + } } for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) { strcpy(buf, bnxt_sw_func_stats[i].string); -- GitLab From 4e7485066373f3e9a87fa063b65d0838990753e5 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:29 -0400 Subject: [PATCH 1094/7155] bnxt_en: Allocate the larger per-ring statistics block for 57500 chips. The new TPA implemantation has additional TPA counters that extend the per-ring statistics block. Allocate the proper size accordingly. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 ++++++++-- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 9269a94455a9..f607873b96bd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3635,7 +3635,7 @@ static void bnxt_free_ring_stats(struct bnxt *bp) if (!bp->bnapi) return; - size = sizeof(struct ctx_hw_stats); + size = bp->hw_ring_stats_size; for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; @@ -3654,7 +3654,7 @@ static int bnxt_alloc_stats(struct bnxt *bp) u32 size, i; struct pci_dev *pdev = bp->pdev; - size = sizeof(struct ctx_hw_stats); + size = bp->hw_ring_stats_size; for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; @@ -4989,6 +4989,11 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) VNIC_QCAPS_RESP_FLAGS_ROCE_MIRRORING_CAPABLE_VNIC_CAP) bp->flags |= BNXT_FLAG_ROCE_MIRROR_CAP; bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported); + if (bp->max_tpa_v2) + bp->hw_ring_stats_size = + sizeof(struct ctx_hw_stats_ext); + else + bp->hw_ring_stats_size = sizeof(struct ctx_hw_stats); } mutex_unlock(&bp->hwrm_cmd_lock); return rc; @@ -6186,6 +6191,7 @@ static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp) bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_ALLOC, -1, -1); + req.stats_dma_length = cpu_to_le16(bp->hw_ring_stats_size); req.update_period_ms = cpu_to_le32(bp->stats_coal_ticks / 1000); mutex_lock(&bp->hwrm_cmd_lock); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 309cf99bcda9..6c710d70adbd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1607,6 +1607,7 @@ struct bnxt { int hw_port_stats_size; u16 fw_rx_stats_ext_size; u16 fw_tx_stats_ext_size; + u16 hw_ring_stats_size; u8 pri2cos[8]; u8 pri2cos_valid; -- GitLab From 78e7b86605b460e8b40622d16d840f9276d58627 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:30 -0400 Subject: [PATCH 1095/7155] bnxt_en: Support TPA counters on 57500 chips. Support the new expanded TPA v2 counters on 57500 B0 chips for ethtool -S. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index a3a7becce01c..3a3d8a9be5ed 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -163,6 +163,14 @@ static const char * const bnxt_ring_tpa_stats_str[] = { "tpa_aborts", }; +static const char * const bnxt_ring_tpa2_stats_str[] = { + "rx_tpa_eligible_pkt", + "rx_tpa_eligible_bytes", + "rx_tpa_pkt", + "rx_tpa_bytes", + "rx_tpa_errors", +}; + static const char * const bnxt_ring_sw_stats_str[] = { "rx_l4_csum_errors", "missed_irqs", @@ -461,14 +469,23 @@ static const struct { ARRAY_SIZE(bnxt_tx_pkts_pri_arr)) #define BNXT_NUM_PCIE_STATS ARRAY_SIZE(bnxt_pcie_stats_arr) +static int bnxt_get_num_tpa_ring_stats(struct bnxt *bp) +{ + if (BNXT_SUPPORTS_TPA(bp)) { + if (bp->max_tpa_v2) + return ARRAY_SIZE(bnxt_ring_tpa2_stats_str); + return ARRAY_SIZE(bnxt_ring_tpa_stats_str); + } + return 0; +} + static int bnxt_get_num_ring_stats(struct bnxt *bp) { int num_stats; num_stats = ARRAY_SIZE(bnxt_ring_stats_str) + - ARRAY_SIZE(bnxt_ring_sw_stats_str); - if (BNXT_SUPPORTS_TPA(bp)) - num_stats += ARRAY_SIZE(bnxt_ring_tpa_stats_str); + ARRAY_SIZE(bnxt_ring_sw_stats_str) + + bnxt_get_num_tpa_ring_stats(bp); return num_stats * bp->cp_nr_rings; } @@ -515,10 +532,8 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, { u32 i, j = 0; struct bnxt *bp = netdev_priv(dev); - u32 stat_fields = ARRAY_SIZE(bnxt_ring_stats_str); - - if (BNXT_SUPPORTS_TPA(bp)) - stat_fields += ARRAY_SIZE(bnxt_ring_tpa_stats_str); + u32 stat_fields = ARRAY_SIZE(bnxt_ring_stats_str) + + bnxt_get_num_tpa_ring_stats(bp); if (!bp->bnapi) { j += bnxt_get_num_ring_stats(bp) + BNXT_NUM_SW_FUNC_STATS; @@ -609,6 +624,7 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnxt *bp = netdev_priv(dev); + static const char * const *str; u32 i, j, num_str; switch (stringset) { @@ -623,10 +639,15 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) if (!BNXT_SUPPORTS_TPA(bp)) goto skip_tpa_stats; - num_str = ARRAY_SIZE(bnxt_ring_tpa_stats_str); + if (bp->max_tpa_v2) { + num_str = ARRAY_SIZE(bnxt_ring_tpa2_stats_str); + str = bnxt_ring_tpa2_stats_str; + } else { + num_str = ARRAY_SIZE(bnxt_ring_tpa_stats_str); + str = bnxt_ring_tpa_stats_str; + } for (j = 0; j < num_str; j++) { - sprintf(buf, "[%d]: %s", i, - bnxt_ring_tpa_stats_str[j]); + sprintf(buf, "[%d]: %s", i, str[j]); buf += ETH_GSTRING_LEN; } skip_tpa_stats: -- GitLab From 7c3809181468a219aa2abd25910bd3b02b89b0de Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:31 -0400 Subject: [PATCH 1096/7155] bnxt_en: Refactor bnxt_init_one() and turn on TPA support on 57500 chips. With the new TPA feature in the 57500 chips, we need to discover the feature first before setting up the netdev features. Refactor the the firmware probe and init logic more cleanly into 2 functions and and make these calls before setting up the netdev features. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 116 ++++++++++++---------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 +- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f607873b96bd..90d20052f113 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9896,6 +9896,68 @@ static void bnxt_init_dflt_coal(struct bnxt *bp) bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS; } +static int bnxt_fw_init_one_p1(struct bnxt *bp) +{ + int rc; + + bp->fw_cap = 0; + rc = bnxt_hwrm_ver_get(bp); + if (rc) + return rc; + + if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) { + rc = bnxt_alloc_kong_hwrm_resources(bp); + if (rc) + bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL; + } + + if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) || + bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) { + rc = bnxt_alloc_hwrm_short_cmd_req(bp); + if (rc) + return rc; + } + rc = bnxt_hwrm_func_reset(bp); + if (rc) + return -ENODEV; + + bnxt_hwrm_fw_set_time(bp); + return 0; +} + +static int bnxt_fw_init_one_p2(struct bnxt *bp) +{ + int rc; + + /* Get the MAX capabilities for this function */ + rc = bnxt_hwrm_func_qcaps(bp); + if (rc) { + netdev_err(bp->dev, "hwrm query capability failure rc: %x\n", + rc); + return -ENODEV; + } + + rc = bnxt_hwrm_cfa_adv_flow_mgnt_qcaps(bp); + if (rc) + netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n", + rc); + + rc = bnxt_hwrm_func_drv_rgtr(bp); + if (rc) + return -ENODEV; + + rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0); + if (rc) + return -ENODEV; + + bnxt_hwrm_func_qcfg(bp); + bnxt_hwrm_vnic_qcaps(bp); + bnxt_hwrm_port_led_qcaps(bp); + bnxt_ethtool_init(bp); + bnxt_dcb_init(bp); + return 0; +} + static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) { int rc; @@ -10851,32 +10913,18 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto init_err_pci_clean; mutex_init(&bp->hwrm_cmd_lock); - rc = bnxt_hwrm_ver_get(bp); + + rc = bnxt_fw_init_one_p1(bp); if (rc) goto init_err_pci_clean; - if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) { - rc = bnxt_alloc_kong_hwrm_resources(bp); - if (rc) - bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL; - } - - if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) || - bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) { - rc = bnxt_alloc_hwrm_short_cmd_req(bp); - if (rc) - goto init_err_pci_clean; - } - if (BNXT_CHIP_P5(bp)) bp->flags |= BNXT_FLAG_CHIP_P5; - rc = bnxt_hwrm_func_reset(bp); + rc = bnxt_fw_init_one_p2(bp); if (rc) goto init_err_pci_clean; - bnxt_hwrm_fw_set_time(bp); - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | @@ -10920,37 +10968,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!BNXT_CHIP_P4_PLUS(bp)) bp->flags |= BNXT_FLAG_DOUBLE_DB; - rc = bnxt_hwrm_func_drv_rgtr(bp); - if (rc) - goto init_err_pci_clean; - - rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0); - if (rc) - goto init_err_pci_clean; - bp->ulp_probe = bnxt_ulp_probe; - rc = bnxt_hwrm_queue_qportcfg(bp); - if (rc) { - netdev_err(bp->dev, "hwrm query qportcfg failure rc: %x\n", - rc); - rc = -1; - goto init_err_pci_clean; - } - /* Get the MAX capabilities for this function */ - rc = bnxt_hwrm_func_qcaps(bp); - if (rc) { - netdev_err(bp->dev, "hwrm query capability failure rc: %x\n", - rc); - rc = -1; - goto init_err_pci_clean; - } - - rc = bnxt_hwrm_cfa_adv_flow_mgnt_qcaps(bp); - if (rc) - netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n", - rc); - rc = bnxt_init_mac_addr(bp); if (rc) { dev_err(&pdev->dev, "Unable to initialize mac address.\n"); @@ -10964,11 +10983,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto init_err_pci_clean; } - bnxt_hwrm_func_qcfg(bp); - bnxt_hwrm_vnic_qcaps(bp); - bnxt_hwrm_port_led_qcaps(bp); - bnxt_ethtool_init(bp); - bnxt_dcb_init(bp); /* MTU range: 60 - FW defined max */ dev->min_mtu = ETH_ZLEN; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 6c710d70adbd..c61af57596c4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1459,8 +1459,8 @@ struct bnxt { #define BNXT_CHIP_TYPE_NITRO_A0(bp) ((bp)->flags & BNXT_FLAG_CHIP_NITRO_A0) #define BNXT_RX_PAGE_MODE(bp) ((bp)->flags & BNXT_FLAG_RX_PAGE_MODE) #define BNXT_SUPPORTS_TPA(bp) (!BNXT_CHIP_TYPE_NITRO_A0(bp) && \ - !(bp->flags & BNXT_FLAG_CHIP_P5) && \ - !is_kdump_kernel()) + (!((bp)->flags & BNXT_FLAG_CHIP_P5) || \ + (bp)->max_tpa_v2) && !is_kdump_kernel()) /* Chip class phase 5 */ #define BNXT_CHIP_P5(bp) \ -- GitLab From 1dc88b97a020148c0eea6c595d511a19c2fab347 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:32 -0400 Subject: [PATCH 1097/7155] bnxt_en: Support all variants of the 5750X chip family. Define the 57508, 57504, and 57502 chip IDs that are all part of the BNXT_CHIP_P5 family of chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index c61af57596c4..e3262089b751 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1362,7 +1362,9 @@ struct bnxt { #define CHIP_NUM_5745X 0xd730 -#define CHIP_NUM_57500 0x1750 +#define CHIP_NUM_57508 0x1750 +#define CHIP_NUM_57504 0x1751 +#define CHIP_NUM_57502 0x1752 #define CHIP_NUM_58802 0xd802 #define CHIP_NUM_58804 0xd804 @@ -1464,7 +1466,9 @@ struct bnxt { /* Chip class phase 5 */ #define BNXT_CHIP_P5(bp) \ - ((bp)->chip_num == CHIP_NUM_57500) + ((bp)->chip_num == CHIP_NUM_57508 || \ + (bp)->chip_num == CHIP_NUM_57504 || \ + (bp)->chip_num == CHIP_NUM_57502) /* Chip class phase 4.x */ #define BNXT_CHIP_P4(bp) \ -- GitLab From 49c98421e6ab33665e8ee7901218a712f5b0db2e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 29 Jul 2019 06:10:33 -0400 Subject: [PATCH 1098/7155] bnxt_en: Add PCI IDs for 57500 series NPAR devices. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 90d20052f113..ac61c9352535 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -116,6 +116,9 @@ enum board_idx { BCM57508, BCM57504, BCM57502, + BCM57508_NPAR, + BCM57504_NPAR, + BCM57502_NPAR, BCM58802, BCM58804, BCM58808, @@ -161,6 +164,9 @@ static const struct { [BCM57508] = { "Broadcom BCM57508 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, [BCM57504] = { "Broadcom BCM57504 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, [BCM57502] = { "Broadcom BCM57502 NetXtreme-E 10Gb/25Gb/50Gb Ethernet" }, + [BCM57508_NPAR] = { "Broadcom BCM57508 NetXtreme-E Ethernet Partition" }, + [BCM57504_NPAR] = { "Broadcom BCM57504 NetXtreme-E Ethernet Partition" }, + [BCM57502_NPAR] = { "Broadcom BCM57502 NetXtreme-E Ethernet Partition" }, [BCM58802] = { "Broadcom BCM58802 NetXtreme-S 10Gb/25Gb/40Gb/50Gb Ethernet" }, [BCM58804] = { "Broadcom BCM58804 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, [BCM58808] = { "Broadcom BCM58808 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, @@ -209,6 +215,12 @@ static const struct pci_device_id bnxt_pci_tbl[] = { { PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 }, { PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 }, { PCI_VDEVICE(BROADCOM, 0x1752), .driver_data = BCM57502 }, + { PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57508_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1801), .driver_data = BCM57504_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57502_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57508_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1804), .driver_data = BCM57504_NPAR }, + { PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57502_NPAR }, { PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 }, { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 }, #ifdef CONFIG_BNXT_SRIOV -- GitLab From 0470e5e38c9d97e7ce1e804cd54cf59accdf3ac2 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Mon, 22 Jul 2019 14:34:42 -0400 Subject: [PATCH 1099/7155] net/mlx5: fix -Wtype-limits compilation warnings The commit b9a7ba556207 ("net/mlx5: Use event mask based on device capabilities") introduced a few compilation warnings due to it bumps MLX5_EVENT_TYPE_MAX from 0x27 to 0x100 which is always greater than an "struct {mlx5_eqe|mlx5_nb}.type" that is an "u8". drivers/net/ethernet/mellanox/mlx5/core/eq.c: In function 'mlx5_eq_notifier_register': drivers/net/ethernet/mellanox/mlx5/core/eq.c:948:21: warning: comparison is always false due to limited range of data type [-Wtype-limits] if (nb->event_type >= MLX5_EVENT_TYPE_MAX) ^~ drivers/net/ethernet/mellanox/mlx5/core/eq.c: In function 'mlx5_eq_notifier_unregister': drivers/net/ethernet/mellanox/mlx5/core/eq.c:959:21: warning: comparison is always false due to limited range of data type [-Wtype-limits] if (nb->event_type >= MLX5_EVENT_TYPE_MAX) Fix them by removing unnecessary checkings. Fixes: b9a7ba556207 ("net/mlx5: Use event mask based on device capabilities") Signed-off-by: Qian Cai Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 41f25ea2e8d9..2df9aaa421c6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -215,11 +215,7 @@ static int mlx5_eq_async_int(struct notifier_block *nb, */ dma_rmb(); - if (likely(eqe->type < MLX5_EVENT_TYPE_MAX)) - atomic_notifier_call_chain(&eqt->nh[eqe->type], eqe->type, eqe); - else - mlx5_core_warn_once(dev, "notifier_call_chain is not setup for eqe: %d\n", eqe->type); - + atomic_notifier_call_chain(&eqt->nh[eqe->type], eqe->type, eqe); atomic_notifier_call_chain(&eqt->nh[MLX5_EVENT_TYPE_NOTIFY_ANY], eqe->type, eqe); ++eq->cons_index; @@ -945,9 +941,6 @@ int mlx5_eq_notifier_register(struct mlx5_core_dev *dev, struct mlx5_nb *nb) { struct mlx5_eq_table *eqt = dev->priv.eq_table; - if (nb->event_type >= MLX5_EVENT_TYPE_MAX) - return -EINVAL; - return atomic_notifier_chain_register(&eqt->nh[nb->event_type], &nb->nb); } EXPORT_SYMBOL(mlx5_eq_notifier_register); @@ -956,9 +949,6 @@ int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb) { struct mlx5_eq_table *eqt = dev->priv.eq_table; - if (nb->event_type >= MLX5_EVENT_TYPE_MAX) - return -EINVAL; - return atomic_notifier_chain_unregister(&eqt->nh[nb->event_type], &nb->nb); } EXPORT_SYMBOL(mlx5_eq_notifier_unregister); -- GitLab From 941a7658e065e339ebdaf27b9a7702f9935d1d4a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 15:25:41 -0300 Subject: [PATCH 1100/7155] perf include bpf: Add bpf_tail_call() prototype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be used together with BPF_MAP_TYPE_PROG_ARRAY in tools/perf/examples/bpf/augmented_raw_syscalls.c. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-pd1bpy8i31nta6jqwdex871g@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/include/bpf/bpf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h index 2eac6d804b2d..b422aeef5339 100644 --- a/tools/perf/include/bpf/bpf.h +++ b/tools/perf/include/bpf/bpf.h @@ -45,6 +45,8 @@ struct ____btf_map_##name __attribute__((section(".maps." #name), used)) \ static int (*bpf_map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags) = (void *)BPF_FUNC_map_update_elem; static void *(*bpf_map_lookup_elem)(struct bpf_map *map, void *key) = (void *)BPF_FUNC_map_lookup_elem; +static void (*bpf_tail_call)(void *ctx, void *map, int index) = (void *)BPF_FUNC_tail_call; + #define SEC(NAME) __attribute__((section(NAME), used)) #define probe(function, vars) \ -- GitLab From 2620b7e3696a9470c7cda0a08e55813fd5e57e5c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 15:29:34 -0300 Subject: [PATCH 1101/7155] perf bpf: Do not attach a BPF prog to a tracepoint if its name starts with ! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With BPF_MAP_TYPE_PROG_ARRAY + bpf_tail_call() we want to have BPF programs, i.e. functions in a object file that perf's BPF loader shouldn't try to attach to anything, i.e. "!syscalls:sys_enter_open" should just stay there, not be attached to a tracepoint with that name, it'll be used by, for instance, 'perf trace' to associate with syscalls that copy, in addition to the syscall raw args, a filename pointed by the first arg, i.e. multiple syscalls that need copying the same pointer arg in the same way, as a filename, for instance, will share the same BPF program/function. Right now when perf's BPF loader sees a function with a name "sys:name" it'll look for a tracepoint and will associate that BPF program with it, say: SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { //SNIP } Will crate a perf_evsel tracepoint event and then associate with it that BPF program. This convention at some point will switch to the one used by the BPF loader in libbpf, but to experiment with BPF_MAP_TYPE_PROG_ARRAY in 'perf trace' lets do this, that will not require changing too much stuff. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-lk6dasjr1yf9rtvl292b2hpc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 371ff3aee769..fac6b32ef94a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -639,6 +639,15 @@ static int add_bpf_event(const char *group, const char *event, int fd, struct list_head *list = param->list; struct perf_evsel *pos; int err; + /* + * Check if we should add the event, i.e. if it is a TP but starts with a '!', + * then don't add the tracepoint, this will be used for something else, like + * adding to a BPF_MAP_TYPE_PROG_ARRAY. + * + * See tools/perf/examples/bpf/augmented_raw_syscalls.c + */ + if (group[0] == '!') + return 0; pr_debug("add bpf event %s:%s and attach bpf program %d\n", group, event, fd); -- GitLab From af4a0991f40a1e50e5caff0317f152df2c82bdeb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 16:22:57 -0300 Subject: [PATCH 1102/7155] perf evsel: Store backpointer to attached bpf_object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We may want to get to this bpf_object, to search for other BPF programs, etc. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-3y8hrb6lszjfi23vjlic3cib@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-loader.c | 4 ++-- tools/perf/util/bpf-loader.h | 2 +- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 3 +++ tools/perf/util/parse-events.c | 3 ++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index c61974a50aa5..6d0dfb777a79 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -763,7 +763,7 @@ int bpf__foreach_event(struct bpf_object *obj, if (priv->is_tp) { fd = bpf_program__fd(prog); - err = (*func)(priv->sys_name, priv->evt_name, fd, arg); + err = (*func)(priv->sys_name, priv->evt_name, fd, obj, arg); if (err) { pr_debug("bpf: tracepoint call back failed, stop iterate\n"); return err; @@ -788,7 +788,7 @@ int bpf__foreach_event(struct bpf_object *obj, return fd; } - err = (*func)(tev->group, tev->event, fd, arg); + err = (*func)(tev->group, tev->event, fd, obj, arg); if (err) { pr_debug("bpf: call back failed, stop iterate\n"); return err; diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index 3f46856e3330..8c3441a4b72c 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -46,7 +46,7 @@ struct parse_events_term; #define PERF_BPF_PROBE_GROUP "perf_bpf_probe" typedef int (*bpf_prog_iter_callback_t)(const char *group, const char *event, - int fd, void *arg); + int fd, struct bpf_object *obj, void *arg); #ifdef HAVE_LIBBPF_SUPPORT struct bpf_object *bpf__prepare_load(const char *filename, bool source); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 52459dd5ad0c..7d1757a2ec46 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -234,6 +234,7 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->scale = 1.0; evsel->max_events = ULONG_MAX; evsel->evlist = NULL; + evsel->bpf_obj = NULL; evsel->bpf_fd = -1; INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->config_terms); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index cad54e8ba522..b27935a6d36c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -82,6 +82,8 @@ enum perf_tool_event { PERF_TOOL_DURATION_TIME = 1, }; +struct bpf_object; + /** struct perf_evsel - event selector * * @evlist - evlist this evsel is in, if it is in one. @@ -152,6 +154,7 @@ struct perf_evsel { char *group_name; bool cmdline_group_boundary; struct list_head config_terms; + struct bpf_object *bpf_obj; int bpf_fd; bool auto_merge_stats; bool merged_stat; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index fac6b32ef94a..0540303e5e97 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -630,7 +630,7 @@ struct __add_bpf_event_param { struct list_head *head_config; }; -static int add_bpf_event(const char *group, const char *event, int fd, +static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj, void *_param) { LIST_HEAD(new_evsels); @@ -672,6 +672,7 @@ static int add_bpf_event(const char *group, const char *event, int fd, pr_debug("adding %s:%s to %p\n", group, event, pos); pos->bpf_fd = fd; + pos->bpf_obj = obj; } list_splice(&new_evsels, list); return 0; -- GitLab From c8c805707ed4c5d976210821da3242af8610a533 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 16:58:23 -0300 Subject: [PATCH 1103/7155] perf trace: Add pointer to BPF object containing __augmented_syscalls__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that we can use it when looking for other components of that object file, such as other programs to add to the BPF_MAP_TYPE_PROG_ARRAY and use with bpf_tail_call(). Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-1ibmz7ouv6llqxajy7m8igtd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4f0bbffee05f..6aa080845a84 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -96,6 +96,7 @@ struct trace { struct perf_evlist *evlist; struct machine *host; struct thread *current; + struct bpf_object *bpf_obj; struct cgroup *cgroup; u64 base_time; FILE *output; @@ -3895,6 +3896,20 @@ int cmd_trace(int argc, const char **argv) if (evsel) { trace.syscalls.events.augmented = evsel; + + evsel = perf_evlist__find_tracepoint_by_name(trace.evlist, "raw_syscalls:sys_enter"); + if (evsel == NULL) { + pr_err("ERROR: raw_syscalls:sys_enter not found in the augmented BPF object\n"); + goto out; + } + + if (evsel->bpf_obj == NULL) { + pr_err("ERROR: raw_syscalls:sys_enter not associated to a BPF object\n"); + goto out; + } + + trace.bpf_obj = evsel->bpf_obj; + trace__set_bpf_map_filtered_pids(&trace); trace__set_bpf_map_syscalls(&trace); } -- GitLab From 5ca0b7f5004a5f1a35c1cb47894790ad98e34ed1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 17:03:10 -0300 Subject: [PATCH 1104/7155] perf trace: Look up maps just on the __augmented_syscalls__ BPF object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can conceivably have multiple BPF object files for other purposes, so better look just on the BPF object containing the __augmented_syscalls__ map for all things augmented_syscalls related. Cc: Adrian Hunter Cc: Brendan Gregg Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-3jt8knkuae9lt705r1lns202@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6aa080845a84..bfd739a321d1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3669,28 +3669,22 @@ static int trace__parse_cgroups(const struct option *opt, const char *str, int u return 0; } -static struct bpf_map *bpf__find_map_by_name(const char *name) +static struct bpf_map *trace__find_bpf_map_by_name(struct trace *trace, const char *name) { - struct bpf_object *obj, *tmp; - - bpf_object__for_each_safe(obj, tmp) { - struct bpf_map *map = bpf_object__find_map_by_name(obj, name); - if (map) - return map; - - } + if (trace->bpf_obj == NULL) + return NULL; - return NULL; + return bpf_object__find_map_by_name(trace->bpf_obj, name); } static void trace__set_bpf_map_filtered_pids(struct trace *trace) { - trace->filter_pids.map = bpf__find_map_by_name("pids_filtered"); + trace->filter_pids.map = trace__find_bpf_map_by_name(trace, "pids_filtered"); } static void trace__set_bpf_map_syscalls(struct trace *trace) { - trace->syscalls.map = bpf__find_map_by_name("syscalls"); + trace->syscalls.map = trace__find_bpf_map_by_name(trace, "syscalls"); } static int trace__config(const char *var, const char *value, void *arg) @@ -3924,7 +3918,7 @@ int cmd_trace(int argc, const char **argv) err = -1; if (map_dump_str) { - trace.dump.map = bpf__find_map_by_name(map_dump_str); + trace.dump.map = trace__find_bpf_map_by_name(&trace, map_dump_str); if (trace.dump.map == NULL) { pr_err("ERROR: BPF map \"%s\" not found\n", map_dump_str); goto out; -- GitLab From 83e69b92b10c2a8b75e1919b7074338f8bdbacaf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 17:28:25 -0300 Subject: [PATCH 1105/7155] perf trace: Order -e syscalls table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ev_qualifier is an array with the syscall ids passed via -e on the command line, sort it as we'll search it when setting up the BPF_MAP_TYPE_PROG_ARRAY. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-c8hprylp3ai6e0z9burn2r3s@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index bfd739a321d1..9bd5ecd6a8dd 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1528,6 +1528,13 @@ static int trace__read_syscall_info(struct trace *trace, int id) return syscall__set_arg_fmts(sc); } +static int intcmp(const void *a, const void *b) +{ + const int *one = a, *another = b; + + return *one - *another; +} + static int trace__validate_ev_qualifier(struct trace *trace) { int err = 0; @@ -1591,6 +1598,7 @@ static int trace__validate_ev_qualifier(struct trace *trace) } trace->ev_qualifier_ids.nr = nr_used; + qsort(trace->ev_qualifier_ids.entries, nr_used, sizeof(int), intcmp); out: if (printed_invalid_prefix) pr_debug("\n"); -- GitLab From 5834da7f10917245d191032f76f132e62e57197c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jul 2019 17:51:43 -0300 Subject: [PATCH 1106/7155] perf trace: Add BPF handler for unaugmented syscalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be used to assign to syscalls that don't need augmentation, i.e. those with just integer args. All syscalls will be in a BPF_MAP_TYPE_PROG_ARRAY, and the bpf_tail_call() keyed by the syscall id will either find nothing in place, which means the syscall is being filtered, or a function that will either add things like filenames to the ring buffer, right after the raw syscall args, or be this unaugmented handler that will just return 1, meaning don't filter the original raw_syscalls:sys_{enter,exit} tracepoint. For now it is not really being used, this is just leg work to break the patch into smaller pieces. It introduces a trace__find_bpf_program_by_title() helper that in turn uses libbpf's bpf_object__find_program_by_title() on the BPF object with the __augmented_syscalls__ map. "title" is how libbpf calls the SEC() argument for functions, i.e. the ELF section that follows a convention to specify what BPF program (a function with this SEC() marking) should be connected to which tracepoint, kprobes, etc. In perf anything that is of the form SEC("sys:event_name") will be connected to that tracepoint by perf's BPF loader. In this case its something that will be bpf_tail_call()ed from either the "raw_syscalls:sys_enter" or "raw_syscall:sys_exit" tracepoints, so its named "!raw_syscalls:unaugmented" to convey that idea, i.e. its not going to be directly attached to a tracepoint, thus it starts with a "!". Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-meucpjx2u0slpkayx56lxqq6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 16 ++++++++++++++++ tools/perf/examples/bpf/augmented_raw_syscalls.c | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 9bd5ecd6a8dd..07df952a0d7f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -88,6 +88,7 @@ struct trace { *sys_exit, *augmented; } events; + struct bpf_program *unaugmented_prog; } syscalls; struct { struct bpf_map *map; @@ -2733,6 +2734,14 @@ static int trace__set_ev_qualifier_tp_filter(struct trace *trace) } #ifdef HAVE_LIBBPF_SUPPORT +static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name) +{ + if (trace->bpf_obj == NULL) + return NULL; + + return bpf_object__find_program_by_title(trace->bpf_obj, name); +} + static void trace__init_bpf_map_syscall_args(struct trace *trace, int id, struct bpf_map_syscall_entry *entry) { struct syscall *sc = trace__syscall_info(trace, NULL, id); @@ -2814,6 +2823,12 @@ static int trace__init_syscalls_bpf_map(struct trace *trace __maybe_unused) { return 0; } + +static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace __maybe_unused, + const char *name __maybe_unused) +{ + return NULL; +} #endif // HAVE_LIBBPF_SUPPORT static int trace__set_ev_qualifier_filter(struct trace *trace) @@ -3914,6 +3929,7 @@ int cmd_trace(int argc, const char **argv) trace__set_bpf_map_filtered_pids(&trace); trace__set_bpf_map_syscalls(&trace); + trace.syscalls.unaugmented_prog = trace__find_bpf_program_by_title(&trace, "!raw_syscalls:unaugmented"); } err = bpf__setup_stdout(trace.evlist); diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 2f822bb51717..48a536b1be6d 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -88,6 +88,12 @@ unsigned int augmented_filename__read(struct augmented_filename *augmented_filen return len; } +SEC("!raw_syscalls:unaugmented") +int syscall_unaugmented(struct syscall_enter_args *args) +{ + return 1; +} + SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { -- GitLab From 6ff8fff45611e0b5ff4c0979cd0470b5cbc0a031 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 10:59:19 -0300 Subject: [PATCH 1107/7155] perf trace: Allow specifying the bpf prog to augment specific syscalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a step in the direction of being able to use a BPF_MAP_TYPE_PROG_ARRAY to handle syscalls that need to copy pointer payloads in addition to the raw tracepoint syscall args. There is a first example in tools/perf/examples/bpf/augmented_raw_syscalls.c for the 'open' syscall. Next step is to introduce the prog array map and use this 'open' augmenter, then use that augmenter in other syscalls that also only copy the first arg as a string, and then show how to use with a syscall that reads more than one filename, like 'rename', etc. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-pys4v57x5qqrybb4cery2mc8@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 50 ++++++++++++++++++- .../examples/bpf/augmented_raw_syscalls.c | 23 +++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 07df952a0d7f..6cc696edf24a 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -690,6 +690,10 @@ struct syscall_arg_fmt { static struct syscall_fmt { const char *name; const char *alias; + struct { + const char *sys_enter, + *sys_exit; + } bpf_prog_name; struct syscall_arg_fmt arg[6]; u8 nr_args; bool errpid; @@ -823,6 +827,7 @@ static struct syscall_fmt { { .name = "newfstatat", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, { .name = "open", + .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_open", }, .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "open_by_handle_at", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, @@ -967,6 +972,10 @@ struct syscall { struct tep_event *tp_format; int nr_args; int args_size; + struct { + struct bpf_program *sys_enter, + *sys_exit; + } bpf_prog; bool is_exit; bool is_open; struct tep_format_field *args; @@ -2742,6 +2751,39 @@ static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, return bpf_object__find_program_by_title(trace->bpf_obj, name); } +static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc, + const char *prog_name, const char *type) +{ + struct bpf_program *prog; + + if (prog_name == NULL) + goto out_unaugmented; + + prog = trace__find_bpf_program_by_title(trace, prog_name); + if (prog != NULL) + return prog; + + pr_debug("Couldn't find BPF prog \"%s\" to associate with syscalls:sys_%s_%s, not augmenting it\n", + prog_name, type, sc->name); +out_unaugmented: + return trace->syscalls.unaugmented_prog; +} + +static void trace__init_syscall_bpf_progs(struct trace *trace, int id) +{ + struct syscall *sc = trace__syscall_info(trace, NULL, id); + + if (sc == NULL) + return; + + if (sc->fmt != NULL) { + sc->bpf_prog.sys_enter = trace__find_syscall_bpf_prog(trace, sc, sc->fmt->bpf_prog_name.sys_enter, "enter"); + sc->bpf_prog.sys_exit = trace__find_syscall_bpf_prog(trace, sc, sc->fmt->bpf_prog_name.sys_exit, "exit"); + } else { + sc->bpf_prog.sys_enter = sc->bpf_prog.sys_exit = trace->syscalls.unaugmented_prog; + } +} + static void trace__init_bpf_map_syscall_args(struct trace *trace, int id, struct bpf_map_syscall_entry *entry) { struct syscall *sc = trace__syscall_info(trace, NULL, id); @@ -2773,8 +2815,10 @@ static int trace__set_ev_qualifier_bpf_filter(struct trace *trace) for (i = 0; i < trace->ev_qualifier_ids.nr; ++i) { int key = trace->ev_qualifier_ids.entries[i]; - if (value.enabled) + if (value.enabled) { trace__init_bpf_map_syscall_args(trace, key, &value); + trace__init_syscall_bpf_progs(trace, key); + } err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST); if (err) @@ -2793,8 +2837,10 @@ static int __trace__init_syscalls_bpf_map(struct trace *trace, bool enabled) int err = 0, key; for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) { - if (enabled) + if (enabled) { trace__init_bpf_map_syscall_args(trace, key, &value); + trace__init_syscall_bpf_progs(trace, key); + } err = bpf_map_update_elem(fd, &key, &value, BPF_ANY); if (err) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 48a536b1be6d..66b33b299349 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -94,6 +94,29 @@ int syscall_unaugmented(struct syscall_enter_args *args) return 1; } +/* + * This will be tail_called from SEC("raw_syscalls:sys_enter"), so will find in + * augmented_filename_map what was read by that raw_syscalls:sys_enter and go + * on from there, reading the first syscall arg as a string, i.e. open's + * filename. + */ +SEC("!syscalls:sys_enter_open") +int sys_enter_open(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + const void *filename_arg = (const void *)args->args[0]; + unsigned int len = sizeof(augmented_args->args); + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + len += augmented_filename__read(&augmented_args->filename, filename_arg, sizeof(augmented_args->filename.value)); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); +} + SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { -- GitLab From 3803a229312de539d2878f2fc5c6ee0202ce6728 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 11:27:03 -0300 Subject: [PATCH 1108/7155] perf trace: Put the per-syscall entry/exit prog_array BPF map infrastructure in place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I.e. look for "syscalls_sys_enter" and "syscalls_sys_exit" BPF maps of type PROG_ARRAY and populate it with the handlers as specified per syscall, for now only 'open' is wiring it to something, in time all syscalls that need to copy arguments entering a syscall or returning from one will set these to the right handlers, reusing when possible pre-existing ones. Next step is to use bpf_tail_call() into that. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-t0p4u43i9vbpzs1xtowna3gb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 76 ++++++++++++++++++- .../examples/bpf/augmented_raw_syscalls.c | 14 ++++ 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6cc696edf24a..fb8b8e78d7b5 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: GPL-2.0-only /* * builtin-trace.c * @@ -83,6 +82,10 @@ struct trace { int max; struct syscall *table; struct bpf_map *map; + struct { // per syscall BPF_MAP_TYPE_PROG_ARRAY + struct bpf_map *sys_enter, + *sys_exit; + } prog_array; struct { struct perf_evsel *sys_enter, *sys_exit, @@ -1619,6 +1622,22 @@ static int trace__validate_ev_qualifier(struct trace *trace) goto out; } +static __maybe_unused bool trace__syscall_enabled(struct trace *trace, int id) +{ + bool in_ev_qualifier; + + if (trace->ev_qualifier_ids.nr == 0) + return true; + + in_ev_qualifier = bsearch(&id, trace->ev_qualifier_ids.entries, + trace->ev_qualifier_ids.nr, sizeof(int), intcmp) != NULL; + + if (in_ev_qualifier) + return !trace->not_ev_qualifier; + + return trace->not_ev_qualifier; +} + /* * args is to be interpreted as a series of longs but we need to handle * 8-byte unaligned accesses. args points to raw_data within the event @@ -2784,6 +2803,18 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id) } } +static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id) +{ + struct syscall *sc = trace__syscall_info(trace, NULL, id); + return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->syscalls.unaugmented_prog); +} + +static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id) +{ + struct syscall *sc = trace__syscall_info(trace, NULL, id); + return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->syscalls.unaugmented_prog); +} + static void trace__init_bpf_map_syscall_args(struct trace *trace, int id, struct bpf_map_syscall_entry *entry) { struct syscall *sc = trace__syscall_info(trace, NULL, id); @@ -2837,10 +2868,8 @@ static int __trace__init_syscalls_bpf_map(struct trace *trace, bool enabled) int err = 0, key; for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) { - if (enabled) { + if (enabled) trace__init_bpf_map_syscall_args(trace, key, &value); - trace__init_syscall_bpf_progs(trace, key); - } err = bpf_map_update_elem(fd, &key, &value, BPF_ANY); if (err) @@ -2859,6 +2888,34 @@ static int trace__init_syscalls_bpf_map(struct trace *trace) return __trace__init_syscalls_bpf_map(trace, enabled); } + +static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace) +{ + int map_enter_fd = bpf_map__fd(trace->syscalls.prog_array.sys_enter), + map_exit_fd = bpf_map__fd(trace->syscalls.prog_array.sys_exit); + int err = 0, key; + + for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) { + int prog_fd; + + if (!trace__syscall_enabled(trace, key)) + continue; + + trace__init_syscall_bpf_progs(trace, key); + + // It'll get at least the "!raw_syscalls:unaugmented" + prog_fd = trace__bpf_prog_sys_enter_fd(trace, key); + err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY); + if (err) + break; + prog_fd = trace__bpf_prog_sys_exit_fd(trace, key); + err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY); + if (err) + break; + } + + return err; +} #else static int trace__set_ev_qualifier_bpf_filter(struct trace *trace __maybe_unused) { @@ -2875,6 +2932,11 @@ static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace { return NULL; } + +static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace __maybe_unused) +{ + return 0; +} #endif // HAVE_LIBBPF_SUPPORT static int trace__set_ev_qualifier_filter(struct trace *trace) @@ -3129,6 +3191,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (trace->syscalls.map) trace__init_syscalls_bpf_map(trace); + if (trace->syscalls.prog_array.sys_enter) + trace__init_syscalls_bpf_prog_array_maps(trace); + + if (trace->ev_qualifier_ids.nr > 0) { err = trace__set_ev_qualifier_filter(trace); if (err < 0) @@ -3754,6 +3820,8 @@ static void trace__set_bpf_map_filtered_pids(struct trace *trace) static void trace__set_bpf_map_syscalls(struct trace *trace) { trace->syscalls.map = trace__find_bpf_map_by_name(trace, "syscalls"); + trace->syscalls.prog_array.sys_enter = trace__find_bpf_map_by_name(trace, "syscalls_sys_enter"); + trace->syscalls.prog_array.sys_exit = trace__find_bpf_map_by_name(trace, "syscalls_sys_exit"); } static int trace__config(const char *var, const char *value, void *arg) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 66b33b299349..c66474a6ccf4 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -33,6 +33,20 @@ struct syscall { bpf_map(syscalls, ARRAY, int, struct syscall, 512); +/* + * What to augment at entry? + * + * Pointer arg payloads (filenames, etc) passed from userspace to the kernel + */ +bpf_map(syscalls_sys_enter, PROG_ARRAY, u32, u32, 512); + +/* + * What to augment at exit? + * + * Pointer arg payloads returned from the kernel (struct stat, etc) to userspace. + */ +bpf_map(syscalls_sys_exit, PROG_ARRAY, u32, u32, 512); + struct syscall_enter_args { unsigned long long common_tp_fields; long syscall_nr; -- GitLab From b119970aa541091e405373399690c24ead9d2920 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 11:53:03 -0300 Subject: [PATCH 1109/7155] perf trace: Handle raw_syscalls:sys_enter just like the BPF_OUTPUT augmented event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So, we use a PERF_COUNT_SW_BPF_OUTPUT to output the augmented sys_enter payload, i.e. to output more than just the raw syscall args, and if something goes wrong when handling an unfiltered syscall, we bail out and just return 1 in the bpf program associated with raw_syscalls:sys_enter, meaning, don't filter that tracepoint, in which case what will appear in the perf ring buffer isn't the BPF_OUTPUT event, but the original raw_syscalls:sys_enter event with its normal payload. Now that we're switching to using a bpf_tail_call + BPF_MAP_TYPE_PROG_ARRAY we're going to use this in the common case, so a bug where raw_syscalls:sys_enter wasn't being handled by trace__sys_enter() surfaced and for that case, instead of using the strace-like augmenter (trace__sys_enter()), we continued to use the normal generic tracepoint handler: (gdb) p evsel $2 = (struct perf_evsel *) 0xc03e40 (gdb) p evsel->name $3 = 0xbc56c0 "raw_syscalls:sys_enter" (gdb) p ((struct perf_evsel *) 0xc03e40)->name $4 = 0xbc56c0 "raw_syscalls:sys_enter" (gdb) p ((struct perf_evsel *) 0xc03e40)->handler $5 = (void *) 0x495eb3 This resulted in this: 0.027 raw_syscalls:sys_enter:NR 12 (0, 7fcfcac64c9b, 4d, 7fcfcac64c9b, 7fcfcac6ce00, 19) ... [continued]: brk()) = 0x563b88677000 I.e. only the sys_exit tracepoint was being properly handled, but since the sys_enter went to the generic trace__event_handler() we printed it using libtraceevent's formatter instead of 'perf trace's strace-like one. Fix it by setting trace__sys_enter() as the handler for raw_syscalls:sys_enter and setup the tp_field tracepoint field accessors. Now, to test it we just make raw_syscalls:sys_enter return 1 right after checking if the pid is filtered, making it not use bpf_perf_output_event() but rather ask for the tracepoint not to be filtered and the result is the expected one: brk(NULL) = 0x556f42d6e000 I.e. raw_syscalls:sys_enter returns 1, gets handled by trace__sys_enter() and gets it combined with the raw_syscalls:sys_exit in a strace-like way. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-0mkocgk31nmy0odknegcby4z@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index fb8b8e78d7b5..872c9cc982a5 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4128,7 +4128,22 @@ int cmd_trace(int argc, const char **argv) if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) || perf_evsel__init_augmented_syscall_tp_args(augmented)) goto out; + /* + * Augmented is __augmented_syscalls__ BPF_OUTPUT event + * Above we made sure we can get from the payload the tp fields + * that we get from syscalls:sys_enter tracefs format file. + */ augmented->handler = trace__sys_enter; + /* + * Now we do the same for the *syscalls:sys_enter event so that + * if we handle it directly, i.e. if the BPF prog returns 0 so + * as not to filter it, then we'll handle it just like we would + * for the BPF_OUTPUT one: + */ + if (perf_evsel__init_augmented_syscall_tp(evsel, evsel) || + perf_evsel__init_augmented_syscall_tp_args(evsel)) + goto out; + evsel->handler = trace__sys_enter; } if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) { -- GitLab From 236dd5838871024d58d354ff8d0dab00ee59a867 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 12:31:10 -0300 Subject: [PATCH 1110/7155] perf augmented_raw_syscalls: Add handler for "openat" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I.e. for a syscall that has its second argument being a string, its difficult these days to find 'open' being used in the wild :-) Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-yf3kbzirqrukd3fb2sp5qx4p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 1 + .../perf/examples/bpf/augmented_raw_syscalls.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 872c9cc982a5..a681b8c2ee4e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -836,6 +836,7 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "openat", + .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_openat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "perf_event_open", diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index c66474a6ccf4..661936f90fe0 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -131,6 +131,23 @@ int sys_enter_open(struct syscall_enter_args *args) return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); } +SEC("!syscalls:sys_enter_openat") +int sys_enter_openat(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + const void *filename_arg = (const void *)args->args[1]; + unsigned int len = sizeof(augmented_args->args); + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + len += augmented_filename__read(&augmented_args->filename, filename_arg, sizeof(augmented_args->filename.value)); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); +} + SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { -- GitLab From bf134ca6c8eafd7ddc28840f767259b97e950bac Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 12:34:59 -0300 Subject: [PATCH 1111/7155] perf augmented_raw_syscalls: Switch to using BPF_MAP_TYPE_PROG_ARRAY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to control what arguments to copy, which ones were strings, etc all from userspace via maps went nowhere, lots of difficulties to get the verifier satisfied, so use what the fine BPF guys designed for such a syscall handling mechanism: bpf_tail_call + BPF_MAP_TYPE_PROG_ARRAY. The series leading to this should have explained it thoroughly, but the end result, explained via gdb should help understand this: Breakpoint 1, syscall_arg__scnprintf_filename (bf=0xc002b1 "", size=2031, arg=0x7fffffff7970) at builtin-trace.c:1268 1268 { (gdb) n 1269 unsigned long ptr = arg->val; (gdb) n 1271 if (arg->augmented.args) (gdb) n 1272 return syscall_arg__scnprintf_augmented_string(arg, bf, size); (gdb) s syscall_arg__scnprintf_augmented_string (arg=0x7fffffff7970, bf=0xc002b1 "", size=2031) at builtin-trace.c:1251 1251 { (gdb) n 1252 struct augmented_arg *augmented_arg = arg->augmented.args; (gdb) n 1253 size_t printed = scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value); (gdb) n 1258 int consumed = sizeof(*augmented_arg) + augmented_arg->size; (gdb) p bf $1 = 0xc002b1 "\"/etc/ld.so.cache\"" (gdb) bt #0 syscall_arg__scnprintf_augmented_string (arg=0x7fffffff7970, bf=0xc002b1 "\"/etc/ld.so.cache\"", size=2031) at builtin-trace.c:1258 #1 0x0000000000492634 in syscall_arg__scnprintf_filename (bf=0xc002b1 "\"/etc/ld.so.cache\"", size=2031, arg=0x7fffffff7970) at builtin-trace.c:1272 #2 0x0000000000493cd7 in syscall__scnprintf_val (sc=0xc0de68, bf=0xc002b1 "\"/etc/ld.so.cache\"", size=2031, arg=0x7fffffff7970, val=140737354091036) at builtin-trace.c:1689 #3 0x000000000049404f in syscall__scnprintf_args (sc=0xc0de68, bf=0xc002a7 "AT_FDCWD, \"/etc/ld.so.cache\"", size=2041, args=0x7ffff6cbf1ec "\234\377\377\377", augmented_args=0x7ffff6cbf21c, augmented_args_size=28, trace=0x7fffffffa170, thread=0xbff940) at builtin-trace.c:1756 #4 0x0000000000494a97 in trace__sys_enter (trace=0x7fffffffa170, evsel=0xbe1900, event=0x7ffff6cbf1a0, sample=0x7fffffff7b00) at builtin-trace.c:1975 #5 0x0000000000496ff1 in trace__handle_event (trace=0x7fffffffa170, event=0x7ffff6cbf1a0, sample=0x7fffffff7b00) at builtin-trace.c:2685 #6 0x0000000000497edb in __trace__deliver_event (trace=0x7fffffffa170, event=0x7ffff6cbf1a0) at builtin-trace.c:3029 #7 0x000000000049801e in trace__deliver_event (trace=0x7fffffffa170, event=0x7ffff6cbf1a0) at builtin-trace.c:3056 #8 0x00000000004988de in trace__run (trace=0x7fffffffa170, argc=2, argv=0x7fffffffd660) at builtin-trace.c:3258 #9 0x000000000049c2d3 in cmd_trace (argc=2, argv=0x7fffffffd660) at builtin-trace.c:4220 #10 0x00000000004dcb6c in run_builtin (p=0xa18e00 , argc=5, argv=0x7fffffffd660) at perf.c:304 #11 0x00000000004dcdd9 in handle_internal_command (argc=5, argv=0x7fffffffd660) at perf.c:356 #12 0x00000000004dcf20 in run_argv (argcp=0x7fffffffd4bc, argv=0x7fffffffd4b0) at perf.c:400 #13 0x00000000004dd28c in main (argc=5, argv=0x7fffffffd660) at perf.c:522 (gdb) (gdb) continue Continuing. openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 Now its a matter of automagically assigning the BPF programs copying syscall arg pointers to functions that are "open"-like (i.e. that need only the first syscall arg copied as a string), or "openat"-like (2nd arg, etc). End result in tool output: # perf trace -e open* ls /tmp/notthere LLVM: dumping /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.o openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = ls: cannot access '/tmp/notthere'-1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY: No such file or directory) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) # Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-snc7ry99cl6r0pqaspjim98x@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../examples/bpf/augmented_raw_syscalls.c | 127 +++--------------- 1 file changed, 16 insertions(+), 111 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 661936f90fe0..ce308b9a317c 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -174,131 +174,36 @@ int sys_enter(struct syscall_enter_args *args) probe_read(&augmented_args->args, sizeof(augmented_args->args), args); - syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr); - if (syscall == NULL || !syscall->enabled) - return 0; /* - * Yonghong and Edward Cree sayz: - * - * https://www.spinics.net/lists/netdev/msg531645.html - * - * >> R0=inv(id=0) R1=inv2 R6=ctx(id=0,off=0,imm=0) R7=inv64 R10=fp0,call_-1 - * >> 10: (bf) r1 = r6 - * >> 11: (07) r1 += 16 - * >> 12: (05) goto pc+2 - * >> 15: (79) r3 = *(u64 *)(r1 +0) - * >> dereference of modified ctx ptr R1 off=16 disallowed - * > Aha, we at least got a different error message this time. - * > And indeed llvm has done that optimisation, rather than the more obvious - * > 11: r3 = *(u64 *)(r1 +16) - * > because it wants to have lots of reads share a single insn. You may be able - * > to defeat that optimisation by adding compiler barriers, idk. Maybe someone - * > with llvm knowledge can figure out how to stop it (ideally, llvm would know - * > when it's generating for bpf backend and not do that). -O0? ¯\_(ツ)_/¯ - * - * The optimization mostly likes below: - * - * br1: - * ... - * r1 += 16 - * goto merge - * br2: - * ... - * r1 += 20 - * goto merge - * merge: - * *(u64 *)(r1 + 0) - * - * The compiler tries to merge common loads. There is no easy way to - * stop this compiler optimization without turning off a lot of other - * optimizations. The easiest way is to add barriers: - * - * __asm__ __volatile__("": : :"memory") - * - * after the ctx memory access to prevent their down stream merging. + * Jump to syscall specific augmenter, even if the default one, + * "!raw_syscalls:unaugmented" that will just return 1 to return the + * unagmented tracepoint payload. */ - /* - * For now copy just the first string arg, we need to improve the protocol - * and have more than one. - * - * Using the unrolled loop is not working, only when we do it manually, - * check this out later... - - u8 arg; -#pragma clang loop unroll(full) - for (arg = 0; arg < 6; ++arg) { - if (syscall->string_args_len[arg] != 0) { - filename_len = syscall->string_args_len[arg]; - filename_arg = (const void *)args->args[arg]; - __asm__ __volatile__("": : :"memory"); - break; - } - } - - verifier log: - -; if (syscall->string_args_len[arg] != 0) { -37: (69) r3 = *(u16 *)(r0 +2) - R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1_w=inv0 R2_w=map_value(id=0,off=2,ks=4,vs=14,imm=0) R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm -; if (syscall->string_args_len[arg] != 0) { -38: (55) if r3 != 0x0 goto pc+5 - R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1=inv0 R2=map_value(id=0,off=2,ks=4,vs=14,imm=0) R3=inv0 R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm -39: (b7) r1 = 1 -; if (syscall->string_args_len[arg] != 0) { -40: (bf) r2 = r0 -41: (07) r2 += 4 -42: (69) r3 = *(u16 *)(r0 +4) - R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1_w=inv1 R2_w=map_value(id=0,off=4,ks=4,vs=14,imm=0) R3_w=inv0 R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm -; if (syscall->string_args_len[arg] != 0) { -43: (15) if r3 == 0x0 goto pc+32 - R0=map_value(id=0,off=0,ks=4,vs=14,imm=0) R1=inv1 R2=map_value(id=0,off=4,ks=4,vs=14,imm=0) R3=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R6=ctx(id=0,off=0,imm=0) R7=map_value(id=0,off=0,ks=4,vs=4168,imm=0) R10=fp0,call_-1 fp-8=mmmmmmmm -; filename_arg = (const void *)args->args[arg]; -44: (67) r1 <<= 3 -45: (bf) r3 = r6 -46: (0f) r3 += r1 -47: (b7) r5 = 64 -48: (79) r3 = *(u64 *)(r3 +16) -dereference of modified ctx ptr R3 off=8 disallowed -processed 46 insns (limit 1000000) max_states_per_insn 0 total_states 12 peak_states 12 mark_read 7 - */ - -#define __loop_iter(arg) \ - if (syscall->string_args_len[arg] != 0) { \ - unsigned int filename_len = syscall->string_args_len[arg]; \ - const void *filename_arg = (const void *)args->args[arg]; \ - if (filename_len <= sizeof(augmented_args->filename.value)) \ - len += augmented_filename__read(&augmented_args->filename, filename_arg, filename_len); -#define loop_iter_first() __loop_iter(0); } -#define loop_iter(arg) else __loop_iter(arg); } -#define loop_iter_last(arg) else __loop_iter(arg); __asm__ __volatile__("": : :"memory"); } - - loop_iter_first() - loop_iter(1) - loop_iter(2) - loop_iter(3) - loop_iter(4) - loop_iter_last(5) + bpf_tail_call(args, &syscalls_sys_enter, augmented_args->args.syscall_nr); - /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ - return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); + // If not found on the PROG_ARRAY syscalls map, then we're filtering it: + return 0; } SEC("raw_syscalls:sys_exit") int sys_exit(struct syscall_exit_args *args) { struct syscall_exit_args exit_args; - struct syscall *syscall; if (pid_filter__has(&pids_filtered, getpid())) return 0; probe_read(&exit_args, sizeof(exit_args), args); - - syscall = bpf_map_lookup_elem(&syscalls, &exit_args.syscall_nr); - if (syscall == NULL || !syscall->enabled) - return 0; - - return 1; + /* + * Jump to syscall specific return augmenter, even if the default one, + * "!raw_syscalls:unaugmented" that will just return 1 to return the + * unagmented tracepoint payload. + */ + bpf_tail_call(args, &syscalls_sys_exit, exit_args.syscall_nr); + /* + * If not found on the PROG_ARRAY syscalls map, then we're filtering it: + */ + return 0; } license(GPL); -- GitLab From 8d5da2649d8211e63c5f65ccf8945f2c46a9c0b8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 14:55:57 -0300 Subject: [PATCH 1112/7155] perf augmented_raw_syscalls: Support copying two string syscall args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting with the renameat and renameat2 syscall, that both receive as second and fourth parameters a pathname: # perf trace -e rename* mv one ANOTHER LLVM: dumping /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.o mv: cannot stat 'one': No such file or directory renameat2(AT_FDCWD, "one", AT_FDCWD, "ANOTHER", RENAME_NOREPLACE) = -1 ENOENT (No such file or directory) # Since the per CPU scratch buffer map has space for two maximum sized pathnames, the verifier is satisfied that there will be no overrun. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-x2uboyg5kx2wqeru288209b6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 ++ .../examples/bpf/augmented_raw_syscalls.c | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a681b8c2ee4e..c64f7c99db15 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -873,9 +873,11 @@ static struct syscall_fmt { { .name = "recvmsg", .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, { .name = "renameat", + .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_renameat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, }, }, { .name = "renameat2", + .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_renameat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, [4] = { .scnprintf = SCA_RENAMEAT2_FLAGS, /* flags */ }, }, }, diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index ce308b9a317c..df52d92e1c69 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -70,6 +70,7 @@ pid_filter(pids_filtered); struct augmented_args_filename { struct syscall_enter_args args; struct augmented_filename filename; + struct augmented_filename filename2; }; bpf_map(augmented_filename_map, PERCPU_ARRAY, int, struct augmented_args_filename, 1); @@ -148,6 +149,25 @@ int sys_enter_openat(struct syscall_enter_args *args) return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); } +SEC("!syscalls:sys_enter_renameat") +int sys_enter_renameat(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + const void *oldpath_arg = (const void *)args->args[1], + *newpath_arg = (const void *)args->args[3]; + unsigned int len = sizeof(augmented_args->args), oldpath_len; + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + oldpath_len = augmented_filename__read(&augmented_args->filename, oldpath_arg, sizeof(augmented_args->filename.value)); + len += oldpath_len + augmented_filename__read((void *)(&augmented_args->filename) + oldpath_len, newpath_arg, sizeof(augmented_args->filename.value)); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); +} + SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { -- GitLab From 8b8044e5c9527cdfff3b0937f2d17470cc4acf9e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 15:24:58 -0300 Subject: [PATCH 1113/7155] perf trace: Look for default name for entries in the syscalls prog array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I.e. just look for "!syscalls:sys_enter_" or "exit_" plus the syscall name, that way we need just to add entries to the augmented_raw_syscalls.c BPF source to add handlers. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-6xavwddruokp6ohs7tf4qilb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c64f7c99db15..5258399a1c94 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -830,13 +830,11 @@ static struct syscall_fmt { { .name = "newfstatat", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, { .name = "open", - .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_open", }, .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "open_by_handle_at", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "openat", - .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_openat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, { .name = "perf_event_open", @@ -873,7 +871,6 @@ static struct syscall_fmt { { .name = "recvmsg", .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, { .name = "renameat", - .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_renameat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, }, }, { .name = "renameat2", @@ -2778,12 +2775,27 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str { struct bpf_program *prog; - if (prog_name == NULL) + if (prog_name == NULL) { + char default_prog_name[256]; + scnprintf(default_prog_name, sizeof(default_prog_name), "!syscalls:sys_%s_%s", type, sc->name); + prog = trace__find_bpf_program_by_title(trace, default_prog_name); + if (prog != NULL) + goto out_found; + if (sc->fmt && sc->fmt->alias) { + scnprintf(default_prog_name, sizeof(default_prog_name), "!syscalls:sys_%s_%s", type, sc->fmt->alias); + prog = trace__find_bpf_program_by_title(trace, default_prog_name); + if (prog != NULL) + goto out_found; + } goto out_unaugmented; + } prog = trace__find_bpf_program_by_title(trace, prog_name); - if (prog != NULL) + + if (prog != NULL) { +out_found: return prog; + } pr_debug("Couldn't find BPF prog \"%s\" to associate with syscalls:sys_%s_%s, not augmenting it\n", prog_name, type, sc->name); @@ -2798,12 +2810,8 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id) if (sc == NULL) return; - if (sc->fmt != NULL) { - sc->bpf_prog.sys_enter = trace__find_syscall_bpf_prog(trace, sc, sc->fmt->bpf_prog_name.sys_enter, "enter"); - sc->bpf_prog.sys_exit = trace__find_syscall_bpf_prog(trace, sc, sc->fmt->bpf_prog_name.sys_exit, "exit"); - } else { - sc->bpf_prog.sys_enter = sc->bpf_prog.sys_exit = trace->syscalls.unaugmented_prog; - } + sc->bpf_prog.sys_enter = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_enter : NULL, "enter"); + sc->bpf_prog.sys_exit = trace__find_syscall_bpf_prog(trace, sc, sc->fmt ? sc->fmt->bpf_prog_name.sys_exit : NULL, "exit"); } static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id) -- GitLab From 6f563674935e6dc9e2190ce798c1917f51af6eed Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 15:33:20 -0300 Subject: [PATCH 1114/7155] perf augmented_raw_syscalls: Rename augmented_args_filename to augmented_args_payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It'll get other stuff in there than just filenames, starting with sockaddr for 'connect' and 'bind'. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-bsexidtsn91ehdpzcd6n5fm9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../examples/bpf/augmented_raw_syscalls.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index df52d92e1c69..77bb6a0edce3 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -67,13 +67,15 @@ struct augmented_filename { pid_filter(pids_filtered); -struct augmented_args_filename { +struct augmented_args_payload { struct syscall_enter_args args; - struct augmented_filename filename; - struct augmented_filename filename2; + struct { + struct augmented_filename filename; + struct augmented_filename filename2; + }; }; -bpf_map(augmented_filename_map, PERCPU_ARRAY, int, struct augmented_args_filename, 1); +bpf_map(augmented_args_tmp, PERCPU_ARRAY, int, struct augmented_args_payload, 1); static inline unsigned int augmented_filename__read(struct augmented_filename *augmented_filename, @@ -111,7 +113,7 @@ int syscall_unaugmented(struct syscall_enter_args *args) /* * This will be tail_called from SEC("raw_syscalls:sys_enter"), so will find in - * augmented_filename_map what was read by that raw_syscalls:sys_enter and go + * augmented_args_tmp what was read by that raw_syscalls:sys_enter and go * on from there, reading the first syscall arg as a string, i.e. open's * filename. */ @@ -119,7 +121,7 @@ SEC("!syscalls:sys_enter_open") int sys_enter_open(struct syscall_enter_args *args) { int key = 0; - struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); const void *filename_arg = (const void *)args->args[0]; unsigned int len = sizeof(augmented_args->args); @@ -136,7 +138,7 @@ SEC("!syscalls:sys_enter_openat") int sys_enter_openat(struct syscall_enter_args *args) { int key = 0; - struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); const void *filename_arg = (const void *)args->args[1]; unsigned int len = sizeof(augmented_args->args); @@ -153,7 +155,7 @@ SEC("!syscalls:sys_enter_renameat") int sys_enter_renameat(struct syscall_enter_args *args) { int key = 0; - struct augmented_args_filename *augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); const void *oldpath_arg = (const void *)args->args[1], *newpath_arg = (const void *)args->args[3]; unsigned int len = sizeof(augmented_args->args), oldpath_len; @@ -171,7 +173,7 @@ int sys_enter_renameat(struct syscall_enter_args *args) SEC("raw_syscalls:sys_enter") int sys_enter(struct syscall_enter_args *args) { - struct augmented_args_filename *augmented_args; + struct augmented_args_payload *augmented_args; /* * We start len, the amount of data that will be in the perf ring * buffer, if this is not filtered out by one of pid_filter__has(), @@ -185,7 +187,7 @@ int sys_enter(struct syscall_enter_args *args) struct syscall *syscall; int key = 0; - augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key); + augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); if (augmented_args == NULL) return 1; -- GitLab From 212b9ab6775b5f340de848b5b6eef6968ccf7f20 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 16:28:14 -0300 Subject: [PATCH 1115/7155] perf augmented_raw_syscalls: Augment sockaddr arg in 'connect' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already had a beautifier for an augmented sockaddr payload, but that was when we were hooking on each syscalls:sys_enter_foo tracepoints, since now we're almost doing that by doing a tail call from raw_syscalls:sys_enter, its almost the same, we can reuse it straight away. # perf trace -e connec* ssh www.bla.com connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(4, { .family: PF_LOCAL, path: /var/lib/sss/pipes/nss }, 0x6e) = 0 connect(7, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(7, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 0x6e) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_INET, port: 53, addr: 192.168.44.1 }, 0x10) = 0 connect(5, { .family: PF_INET, port: 22, addr: 146.112.61.108 }, 0x10) = 0 connect(5, { .family: PF_INET6, port: 22, addr: ::ffff:146.112.61.108 }, 0x1c) = 0 ^C# Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-5xkrbcpjsgnr3zt1aqdd7nvc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../examples/bpf/augmented_raw_syscalls.c | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 77bb6a0edce3..d7a292d7ee2f 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -16,6 +16,7 @@ #include #include +#include #include /* bpf-output associated map */ @@ -69,10 +70,13 @@ pid_filter(pids_filtered); struct augmented_args_payload { struct syscall_enter_args args; - struct { - struct augmented_filename filename; - struct augmented_filename filename2; - }; + union { + struct { + struct augmented_filename filename, + filename2; + }; + struct sockaddr_storage saddr; + }; }; bpf_map(augmented_args_tmp, PERCPU_ARRAY, int, struct augmented_args_payload, 1); @@ -112,11 +116,32 @@ int syscall_unaugmented(struct syscall_enter_args *args) } /* - * This will be tail_called from SEC("raw_syscalls:sys_enter"), so will find in + * These will be tail_called from SEC("raw_syscalls:sys_enter"), so will find in * augmented_args_tmp what was read by that raw_syscalls:sys_enter and go * on from there, reading the first syscall arg as a string, i.e. open's * filename. */ +SEC("!syscalls:sys_enter_connect") +int sys_enter_connect(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); + const void *sockaddr_arg = (const void *)args->args[1]; + unsigned int socklen = args->args[2]; + unsigned int len = sizeof(augmented_args->args); + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + if (socklen > sizeof(augmented_args->saddr)) + socklen = sizeof(augmented_args->saddr); + + probe_read(&augmented_args->saddr, socklen, sockaddr_arg); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len + socklen); +} + SEC("!syscalls:sys_enter_open") int sys_enter_open(struct syscall_enter_args *args) { -- GitLab From 1d86275225b4c9db3fb426e992886df5051f0047 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 16:34:27 -0300 Subject: [PATCH 1116/7155] perf trace beauty: Make connect's addrlen be printed as an int, not hex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # perf trace -e connec* ssh www.bla.com connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(4, { .family: PF_LOCAL, path: /var/lib/sss/pipes/nss }, 110) = 0 connect(7, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(7, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) connect(5, { .family: PF_INET, port: 53, addr: 192.168.44.1 }, 16) = 0 connect(5, { .family: PF_INET, port: 22, addr: 146.112.61.108 }, 16) = 0 connect(5, { .family: PF_INET6, port: 22, addr: ::ffff:146.112.61.108 }, 28) = 0 ^Cconnect(5, { .family: PF_INET, port: 22, addr: 146.112.61.108 }, 16) = -1 (unknown) (INTERNAL ERROR: strerror_r(512, [buf], 128)=22) # Argh, the SCA_FD needs to invalidate its cache when close is done... It works if the 'close' syscall is not filtered out ;-\ # perf trace -e close,connec* ssh www.bla.com close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 close(4) = 0 close(3) = 0 close(3) = 0 connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) close(3) = 0 connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) close(3) = 0 close(3) = 0 close(3) = 0 close(3) = 0 connect(4, { .family: PF_LOCAL, path: /var/lib/sss/pipes/nss }, 110) = 0 ^C # Will disable this beautifier when 'close' is filtered out... Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-ekuiciyx4znchvy95c8p1yyi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5258399a1c94..123d7efc12e8 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -725,7 +725,8 @@ static struct syscall_fmt { { .name = "close", .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, { .name = "connect", - .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, }, + .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, + [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, }, { .name = "epoll_ctl", .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, }, { .name = "eventfd2", -- GitLab From 79d725cdf24dec7bfe7ad27b107f5cb06cd3785a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 16:56:49 -0300 Subject: [PATCH 1117/7155] perf trace beauty: Disable fd->pathname when close() not enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we invalidate the fd->pathname table in the SCA_CLOSE_FD beautifier, if we don't have it we may end up keeping an fd->pathname association that then gets misprinted. The previous behaviour continues when the close() syscall is enabled, which may still be a a problem if we lose records (i.e. we may lose a 'close' record and then get that fd reused by socket()) but then the tool will notify that records are being lost and the user will be warned that some of the heuristics will fall apart. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-b7t6h8sq9lebemvfy2zh3qq1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 123d7efc12e8..94c33bb573c1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -127,6 +127,7 @@ struct trace { unsigned int min_stack; int raw_augmented_syscalls_args_size; bool raw_augmented_syscalls; + bool fd_path_disabled; bool sort_events; bool not_ev_qualifier; bool live; @@ -1178,7 +1179,7 @@ static const char *thread__fd_path(struct thread *thread, int fd, { struct thread_trace *ttrace = thread__priv(thread); - if (ttrace == NULL) + if (ttrace == NULL || trace->fd_path_disabled) return NULL; if (fd < 0) @@ -2097,7 +2098,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, ret = perf_evsel__sc_tp_uint(evsel, ret, sample); - if (sc->is_open && ret >= 0 && ttrace->filename.pending_open) { + if (!trace->fd_path_disabled && sc->is_open && ret >= 0 && ttrace->filename.pending_open) { trace__set_fd_pathname(thread, ret, ttrace->filename.name); ttrace->filename.pending_open = false; ++trace->stats.vfs_getname; @@ -3206,7 +3207,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (trace->syscalls.prog_array.sys_enter) trace__init_syscalls_bpf_prog_array_maps(trace); - if (trace->ev_qualifier_ids.nr > 0) { err = trace__set_ev_qualifier_filter(trace); if (err < 0) @@ -3218,6 +3218,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } } + /* + * If the "close" syscall is not traced, then we will not have the + * opportunity to, in syscall_arg__scnprintf_close_fd() invalidate the + * fd->pathname table and were ending up showing the last value set by + * syscalls opening a pathname and associating it with a descriptor or + * reading it from /proc/pid/fd/ in cases where that doesn't make + * sense. + * + * So just disable this beautifier (SCA_FD, SCA_FDAT) when 'close' is + * not in use. + */ + trace->fd_path_disabled = !trace__syscall_enabled(trace, syscalltbl__id(trace->sctbl, "close")); + err = perf_evlist__apply_filters(evlist, &evsel); if (err < 0) goto out_error_apply_filters; -- GitLab From ef969ca64d04161ccbde2aaf8b0767f91a6d32ff Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 17:21:09 -0300 Subject: [PATCH 1118/7155] perf trace beauty: Do not try to use the fd->pathname beautifier for bind/connect fd arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doesn't make sense and also we now beautify the sockaddr, which provides enough info: # trace -e close,socket,connec* ssh www.bla.com close(5) = 0 socket(PF_INET, SOCK_DGRAM|CLOEXEC|NONBLOCK, IPPROTO_IP) = 5 connect(5, { .family: PF_INET, port: 53, addr: 192.168.44.1 }, 16) = 0 close(5) = 0 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5 ^C# Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-h9drpb7ail808d2mh4n7tla4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 94c33bb573c1..010aa9e9a561 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -710,7 +710,8 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_X86_ARCH_PRCTL_CODE, /* code */ }, [1] = { .scnprintf = SCA_PTR, /* arg2 */ }, }, }, { .name = "bind", - .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, }, + .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ }, + [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, }, { .name = "bpf", .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, { .name = "brk", .hexret = true, @@ -726,7 +727,8 @@ static struct syscall_fmt { { .name = "close", .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, { .name = "connect", - .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, + .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ }, + [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, }, { .name = "epoll_ctl", .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, }, -- GitLab From 3c475bc021be1f5e0a00dc1a13dc85ce7924a7d6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 17:33:39 -0300 Subject: [PATCH 1119/7155] perf trace beauty: Beautify 'sendto's sockaddr arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By just writing the collector in the augmented_raw_syscalls.c BPF program: # perf trace -e sendto ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 Socket Thread/3573 sendto(247, 0x7fb32d49c000, 120, NONE, { .family: PF_UNSPEC }, NULL) = 120 DNS Res~er #18/11374 sendto(242, 0x7fb342cfe420, 20, NONE, { .family: PF_NETLINK }, 0xc) = 20 DNS Res~er #18/11374 sendto(242, 0x7fb342cfcca0, 42, MSG_NOSIGNAL, { .family: PF_UNSPEC }, NULL) = 42 DNS Res~er #18/11374 sendto(242, 0x7fb342cfcccc, 42, MSG_NOSIGNAL, { .family: PF_UNSPEC }, NULL) = 42 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 Socket Thread/3573 sendto(242, 0x7fb308bb1c08, 296, NONE, { .family: PF_UNSPEC }, NULL) = 296 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ping/23492 sendto(3, 0x56253bbef700, 64, NONE, { .family: PF_INET, port: 0, addr: 10.10.161.32 }, 0x10) = 64 ^C # Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-p0l0rlvq19v5zf8qc2x2itow@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../examples/bpf/augmented_raw_syscalls.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index d7a292d7ee2f..9c2228b01ee6 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -142,6 +142,27 @@ int sys_enter_connect(struct syscall_enter_args *args) return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len + socklen); } +SEC("!syscalls:sys_enter_sendto") +int sys_enter_sendto(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); + const void *sockaddr_arg = (const void *)args->args[4]; + unsigned int socklen = args->args[5]; + unsigned int len = sizeof(augmented_args->args); + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + if (socklen > sizeof(augmented_args->saddr)) + socklen = sizeof(augmented_args->saddr); + + probe_read(&augmented_args->saddr, socklen, sockaddr_arg); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len + socklen); +} + SEC("!syscalls:sys_enter_open") int sys_enter_open(struct syscall_enter_args *args) { -- GitLab From 247dd65b909f1cd62a178febe3f6f8d5efdd7dd2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jul 2019 17:38:26 -0300 Subject: [PATCH 1120/7155] perf trace beauty: Beautify bind's sockaddr arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By reusing the "connect" BPF collector. Testing it system wide and stopping/starting sshd: # perf trace -e bind LLVM: dumping /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.o DNS Res~er #18/15132 bind(243, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #19/4833 bind(247, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #19/4833 bind(238, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #18/15132 bind(243, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #18/10327 bind(258, { .family: PF_NETLINK }, 12) = 0 :6507/6507 bind(24, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #19/4833 bind(238, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #18/15132 bind(242, { .family: PF_NETLINK }, 12) = 0 sshd/6514 bind(3, { .family: PF_NETLINK }, 12) = 0 sshd/6514 bind(5, { .family: PF_INET, port: 22, addr: 0.0.0.0 }, 16) = 0 sshd/6514 bind(7, { .family: PF_INET6, port: 22, addr: :: }, 28) = 0 DNS Res~er #18/10327 bind(229, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #18/15132 bind(231, { .family: PF_NETLINK }, 12) = 0 DNS Res~er #19/4833 bind(229, { .family: PF_NETLINK }, 12) = 0 ^C# Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-m2hmxqrckxxw2ciki0tu889u@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 010aa9e9a561..d403b09812d1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -710,8 +710,10 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_X86_ARCH_PRCTL_CODE, /* code */ }, [1] = { .scnprintf = SCA_PTR, /* arg2 */ }, }, }, { .name = "bind", + .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_connect", }, .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ }, - [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, }, + [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, + [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, }, { .name = "bpf", .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, { .name = "brk", .hexret = true, -- GitLab From cfa9ac73d6f9790f569959a729cbc9d52bff4270 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jul 2019 11:47:37 -0300 Subject: [PATCH 1121/7155] perf trace beauty: Add BPF augmenter for the 'rename' syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I.e. two strings: # perf trace -e rename systemd/1 rename("/run/systemd/units/.#invocation:dnf-makecache.service970761b7f2840dcc", "/run/systemd/units/invocation:dnf-makecache.service") = 0 systemd-journa/715 rename("/run/systemd/journal/streams/.#9:17539785BJDblc", "/run/systemd/journal/streams/9:17539785") = 0 mv/1936 rename("/tmp/build/perf/fd/.array.o.tmp", "/tmp/build/perf/fd/.array.o.cmd") = 0 sh/1949 rename("/tmp/build/perf/.cpu.o.tmp", "/tmp/build/perf/.cpu.o.cmd") = 0 mv/1954 rename("/tmp/build/perf/fs/.tracing_path.o.tmp", "/tmp/build/perf/fs/.tracing_path.o.cmd") = 0 mv/1963 rename("/tmp/build/perf/common-cmds.h+", "/tmp/build/perf/common-cmds.h") = 0 :1975/1975 rename("/tmp/build/perf/.exec-cmd.o.tmp", "/tmp/build/perf/.exec-cmd.o.cmd") = 0 mv/1979 rename("/tmp/build/perf/fs/.fs.o.tmp", "/tmp/build/perf/fs/.fs.o.cmd") = 0 mv/2005 rename("/tmp/build/perf/.debug.o.tmp", "/tmp/build/perf/.debug.o.cmd") = 0 mv/2012 rename("/tmp/build/perf/.str_error_r.o.tmp", "/tmp/build/perf/.str_error_r.o.cmd") = 0 mv/2019 rename("/tmp/build/perf/.help.o.tmp", "/tmp/build/perf/.help.o.cmd") = 0 mv/2031 rename("/tmp/build/perf/.trace-seq.o.tmp", "/tmp/build/perf/.trace-seq.o.cmd") = 0 make/2038 ... [continued]: rename()) = 0 :2038/2038 rename("/tmp/build/perf/.event-plugin.o.tmp", "/tmp/build/perf/.event-plugin.o.cmd") ... ar/2035 rename("/tmp/build/perf/stzwBX3a", "/tmp/build/perf/libapi.a") = 0 mv/2051 rename("/tmp/build/perf/.parse-utils.o.tmp", "/tmp/build/perf/.parse-utils.o.cmd") = 0 mv/2069 rename("/tmp/build/perf/.subcmd-config.o.tmp", "/tmp/build/perf/.subcmd-config.o.cmd") = 0 make/2080 rename("/tmp/build/perf/.parse-filter.o.tmp", "/tmp/build/perf/.parse-filter.o.cmd") = 0 mv/2099 rename("/tmp/build/perf/.pager.o.tmp", "/tmp/build/perf/.pager.o.cmd") = 0 :2124/2124 rename("/tmp/build/perf/.sigchain.o.tmp", "/tmp/build/perf/.sigchain.o.cmd") = 0 make/2140 rename("/tmp/build/perf/.event-parse.o.tmp", "/tmp/build/perf/.event-parse.o.cmd") = 0 mv/2164 rename("/tmp/build/perf/.kbuffer-parse.o.tmp", "/tmp/build/perf/.kbuffer-parse.o.cmd") = 0 sh/2174 rename("/tmp/build/perf/.run-command.o.tmp", "/tmp/build/perf/.run-command.o.cmd") = 0 mv/2190 rename("/tmp/build/perf/.tep_strerror.o.tmp", "/tmp/build/perf/.tep_strerror.o.cmd") = 0 :2261/2261 rename("/tmp/build/perf/.event-parse-api.o.tmp", "/tmp/build/perf/.event-parse-api.o.cmd") = 0 :2480/2480 rename("/tmp/build/perf/stLv3kG2", "/tmp/build/perf/libtraceevent.a") = 0 ^C# Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-6hh2rl27uri6gsxhmk6q3hx5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../examples/bpf/augmented_raw_syscalls.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 9c2228b01ee6..79787cf4fce9 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -197,6 +197,25 @@ int sys_enter_openat(struct syscall_enter_args *args) return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); } +SEC("!syscalls:sys_enter_rename") +int sys_enter_rename(struct syscall_enter_args *args) +{ + int key = 0; + struct augmented_args_payload *augmented_args = bpf_map_lookup_elem(&augmented_args_tmp, &key); + const void *oldpath_arg = (const void *)args->args[0], + *newpath_arg = (const void *)args->args[1]; + unsigned int len = sizeof(augmented_args->args), oldpath_len; + + if (augmented_args == NULL) + return 1; /* Failure: don't filter */ + + oldpath_len = augmented_filename__read(&augmented_args->filename, oldpath_arg, sizeof(augmented_args->filename.value)); + len += oldpath_len + augmented_filename__read((void *)(&augmented_args->filename) + oldpath_len, newpath_arg, sizeof(augmented_args->filename.value)); + + /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ + return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, augmented_args, len); +} + SEC("!syscalls:sys_enter_renameat") int sys_enter_renameat(struct syscall_enter_args *args) { -- GitLab From 5d2bd88975117062766a48b5f36ce31d2c1a8269 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jul 2019 19:53:51 -0300 Subject: [PATCH 1122/7155] perf trace: Forward error codes when trying to read syscall info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We iterate thru the syscall table produced from the kernel syscall tables reading info, propagate the error and add to the debug message. This helps in fixing further bugs, such as failing to read the "sendfile" syscall info when it really should try the aliasm "sendfile64". Problems reading syscall 40: 2 (No such file or directory)(sendfile) information # grep sendfile /tmp/build/perf/arch/x86/include/generated/asm/syscalls_64.c [40] = "sendfile", # I.e. in the tracefs format file for the syscall tracepoints we have it as sendfile64: # find /sys -type f -name format | grep sendfile /sys/kernel/debug/tracing/events/syscalls/sys_enter_sendfile64/format /sys/kernel/debug/tracing/events/syscalls/sys_exit_sendfile64/format # But as "sendfile" in the file used to build the syscall table used in perf: $ grep sendfile arch/x86/entry/syscalls/syscall_64.tbl 40 common sendfile __x64_sys_sendfile64 $ So we need to add, in followup patches, aliases in 'perf trace' syscall data structures to cope with thie. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-w3eluap63x9je0bb8o3t79tz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d403b09812d1..5dae7b172291 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1492,13 +1492,13 @@ static int trace__read_syscall_info(struct trace *trace, int id) const char *name = syscalltbl__name(trace->sctbl, id); if (name == NULL) - return -1; + return -EINVAL; if (id > trace->syscalls.max) { struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); if (nsyscalls == NULL) - return -1; + return -ENOMEM; if (trace->syscalls.max != -1) { memset(nsyscalls + trace->syscalls.max + 1, 0, @@ -1525,10 +1525,10 @@ static int trace__read_syscall_info(struct trace *trace, int id) } if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields)) - return -1; + return -ENOMEM; if (IS_ERR(sc->tp_format)) - return -1; + return PTR_ERR(sc->tp_format); sc->args = sc->tp_format->format.fields; /* @@ -1789,6 +1789,7 @@ typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel, static struct syscall *trace__syscall_info(struct trace *trace, struct perf_evsel *evsel, int id) { + int err = 0; if (id < 0) { @@ -1811,9 +1812,10 @@ static struct syscall *trace__syscall_info(struct trace *trace, } if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && - trace__read_syscall_info(trace, id)) + (err = trace__read_syscall_info(trace, id)) != 0) goto out_cant_read; + err = -EINVAL; if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) goto out_cant_read; @@ -1821,7 +1823,8 @@ static struct syscall *trace__syscall_info(struct trace *trace, out_cant_read: if (verbose > 0) { - fprintf(trace->output, "Problems reading syscall %d", id); + char sbuf[STRERR_BUFSIZE]; + fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf))); if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) fprintf(trace->output, "(%s)", trace->syscalls.table[id].name); fputs(" information\n", trace->output); -- GitLab From b8b1033fcaa091d82289698d7179e84e28cbd92a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jul 2019 20:21:37 -0300 Subject: [PATCH 1123/7155] perf trace: Mark syscall ids that are not allocated to avoid unnecessary error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are holes in syscall tables with IDs not associated with any syscall, mark those when trying to read information for syscalls, which could happen when iterating thru all syscalls from 0 to the highest numbered syscall id. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-cku9mpcrcsqaiq0jepu86r68@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5dae7b172291..765b998755ce 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -976,6 +976,7 @@ static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias) * is_exit: is this "exit" or "exit_group"? * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc. + * nonexistent: Just a hole in the syscall table, syscall id not allocated */ struct syscall { struct tep_event *tp_format; @@ -987,6 +988,7 @@ struct syscall { } bpf_prog; bool is_exit; bool is_open; + bool nonexistent; struct tep_format_field *args; const char *name; struct syscall_fmt *fmt; @@ -1491,9 +1493,6 @@ static int trace__read_syscall_info(struct trace *trace, int id) struct syscall *sc; const char *name = syscalltbl__name(trace->sctbl, id); - if (name == NULL) - return -EINVAL; - if (id > trace->syscalls.max) { struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); @@ -1512,8 +1511,15 @@ static int trace__read_syscall_info(struct trace *trace, int id) } sc = trace->syscalls.table + id; - sc->name = name; + if (sc->nonexistent) + return 0; + if (name == NULL) { + sc->nonexistent = true; + return 0; + } + + sc->name = name; sc->fmt = syscall_fmt__find(sc->name); snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); @@ -1811,14 +1817,21 @@ static struct syscall *trace__syscall_info(struct trace *trace, return NULL; } + err = -EINVAL; + if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && (err = trace__read_syscall_info(trace, id)) != 0) goto out_cant_read; - err = -EINVAL; - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) + if (id > trace->syscalls.max) goto out_cant_read; + if (trace->syscalls.table[id].name == NULL) { + if (trace->syscalls.table[id].nonexistent) + return NULL; + goto out_cant_read; + } + return &trace->syscalls.table[id]; out_cant_read: -- GitLab From 30a910d7d3e04dd920e4ca3e8dcabf10c67fb03e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 18 Jul 2019 20:19:30 -0300 Subject: [PATCH 1124/7155] perf trace: Preallocate the syscall table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll continue reading its details from tracefs as we need it, but preallocate the whole thing otherwise we may realloc and end up with pointers to the previous buffer. I.e. in an upcoming algorithm we'll look for syscalls that have function signatures that are similar to a given syscall to see if we can reuse its BPF augmenter, so we may be at syscall 42, having a 'struct syscall' pointing to that slot in trace->syscalls.table[] and try to read the slot for an yet unread syscall, which would realloc that table to read the info for syscall 43, say, which would trigger a realoc of trace->syscalls.table[], and then the pointer we had for syscall 42 would be pointing to the previous block of memory. b00m. Cc: Adrian Hunter Cc: Brendan Gregg Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-m3cjzzifibs13imafhkk77a0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 29 +++++++---------------------- tools/perf/util/syscalltbl.c | 1 + tools/perf/util/syscalltbl.h | 1 + 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 765b998755ce..d8565c9a18a2 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -79,7 +79,6 @@ struct trace { struct perf_tool tool; struct syscalltbl *sctbl; struct { - int max; struct syscall *table; struct bpf_map *map; struct { // per syscall BPF_MAP_TYPE_PROG_ARRAY @@ -1493,21 +1492,10 @@ static int trace__read_syscall_info(struct trace *trace, int id) struct syscall *sc; const char *name = syscalltbl__name(trace->sctbl, id); - if (id > trace->syscalls.max) { - struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); - - if (nsyscalls == NULL) + if (trace->syscalls.table == NULL) { + trace->syscalls.table = calloc(trace->sctbl->syscalls.nr_entries, sizeof(*sc)); + if (trace->syscalls.table == NULL) return -ENOMEM; - - if (trace->syscalls.max != -1) { - memset(nsyscalls + trace->syscalls.max + 1, 0, - (id - trace->syscalls.max) * sizeof(*sc)); - } else { - memset(nsyscalls, 0, (id + 1) * sizeof(*sc)); - } - - trace->syscalls.table = nsyscalls; - trace->syscalls.max = id; } sc = trace->syscalls.table + id; @@ -1819,11 +1807,11 @@ static struct syscall *trace__syscall_info(struct trace *trace, err = -EINVAL; - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && - (err = trace__read_syscall_info(trace, id)) != 0) + if (id > trace->sctbl->syscalls.max_id) goto out_cant_read; - if (id > trace->syscalls.max) + if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) && + (err = trace__read_syscall_info(trace, id)) != 0) goto out_cant_read; if (trace->syscalls.table[id].name == NULL) { @@ -1838,7 +1826,7 @@ static struct syscall *trace__syscall_info(struct trace *trace, if (verbose > 0) { char sbuf[STRERR_BUFSIZE]; fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf))); - if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) + if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL) fprintf(trace->output, "(%s)", trace->syscalls.table[id].name); fputs(" information\n", trace->output); } @@ -3922,9 +3910,6 @@ int cmd_trace(int argc, const char **argv) NULL }; struct trace trace = { - .syscalls = { - . max = -1, - }, .opts = { .target = { .uid = UINT_MAX, diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c index 022a9c670338..820fceeb19a9 100644 --- a/tools/perf/util/syscalltbl.c +++ b/tools/perf/util/syscalltbl.c @@ -79,6 +79,7 @@ static int syscalltbl__init_native(struct syscalltbl *tbl) qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp); tbl->syscalls.nr_entries = nr_entries; + tbl->syscalls.max_id = syscalltbl_native_max_id; return 0; } diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h index c8e7e9ce0f01..9172613028d0 100644 --- a/tools/perf/util/syscalltbl.h +++ b/tools/perf/util/syscalltbl.h @@ -6,6 +6,7 @@ struct syscalltbl { union { int audit_machine; struct { + int max_id; int nr_entries; void *entries; } syscalls; -- GitLab From ad4153f964ebb756617e1586ba372156db0efeed Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jul 2019 18:27:33 -0300 Subject: [PATCH 1125/7155] perf trace: Reuse BPF augmenters from syscalls with similar args signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have an augmenter for the "open" syscall, which has just one pointer, in the first argument, a "const char *", so any other syscall that has just one pointer and that is the first can reuse the "open" BPF augmenter program. Even more, syscalls that get two pointers with the first being a string can reuse "open"'s BPF augmenter till we have an augmenter that better matches that syscall with two pointers. With this the few augmenters we have, for open (first arg is a string), openat (2nd arg is a string), renameat (2nd and 4th are strings) can be reused by a lot of syscalls, ditto for "bind" reusing "connect" because both have the 2nd argument as a sockaddr and the 3rd as its len. Lets see how this makes the "bind" syscall reuse the "connect" BPF prog augmenter found in tools/perf/examples/bpf/augmented_raw_syscalls.c: # perf trace -e bind,connect systemctl restart sshd connect(3, { .family: PF_LOCAL, path: /run/systemd/private }, 23) = 0 # Oh, it just connects to some daemon, so we better do it system wide and then stop/start sshd: # perf trace -e bind,connect systemctl/10124 connect(3, { .family: PF_LOCAL, path: /run/systemd/private }, 23) = 0 sshd/10102 connect(7, { .family: PF_LOCAL, path: /dev/log }, 110) = 0 systemctl/10126 connect(3, { .family: PF_LOCAL, path: /run/systemd/private }, 23) = 0 systemd/10128 ... [continued]: connect()) = 0 (sshd)/10128 connect(3, { .family: PF_LOCAL, path: /run/systemd/journal/stdout }, 30) ... sshd/10128 bind(3, { .family: PF_NETLINK }, 12) = 0 sshd/10128 connect(4, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) sshd/10128 connect(3, { .family: PF_INET6, port: 22, addr: :: }, 28) = 0 sshd/10128 connect(3, { .family: PF_UNSPEC }, 16) = 0 sshd/10128 connect(3, { .family: PF_INET, port: 22, addr: 0.0.0.0 }, 16) = 0 sshd/10128 connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) sshd/10128 connect(3, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) sshd/10128 connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) sshd/10128 connect(5, { .family: PF_LOCAL, path: /var/run/nscd/socket }, 110) = -1 ENOENT (No such file or directory) sshd/10128 bind(4, { .family: PF_INET, port: 22, addr: 0.0.0.0 }, 16) = 0 sshd/10128 connect(6, { .family: PF_LOCAL, path: /dev/log }, 110) = 0 sshd/10128 bind(6, { .family: PF_INET6, port: 22, addr: :: }, 28) = 0 sshd/10128 connect(7, { .family: PF_LOCAL, path: /dev/log }, 110) = 0 ^C# Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-zfley2ghs4nim1uq4nu6ed3l@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 154 ++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d8565c9a18a2..200fbe33d5de 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -709,7 +709,6 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_X86_ARCH_PRCTL_CODE, /* code */ }, [1] = { .scnprintf = SCA_PTR, /* arg2 */ }, }, }, { .name = "bind", - .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_connect", }, .arg = { [0] = { .scnprintf = SCA_INT, /* fd */ }, [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, [2] = { .scnprintf = SCA_INT, /* addrlen */ }, }, }, @@ -879,7 +878,6 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, }, }, { .name = "renameat2", - .bpf_prog_name = { .sys_enter = "!syscalls:sys_enter_renameat", }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, [4] = { .scnprintf = SCA_RENAMEAT2_FLAGS, /* flags */ }, }, }, @@ -2910,6 +2908,94 @@ static int trace__init_syscalls_bpf_map(struct trace *trace) return __trace__init_syscalls_bpf_map(trace, enabled); } +static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc) +{ + struct tep_format_field *field, *candidate_field; + int id; + + /* + * We're only interested in syscalls that have a pointer: + */ + for (field = sc->args; field; field = field->next) { + if (field->flags & TEP_FIELD_IS_POINTER) + goto try_to_find_pair; + } + + return NULL; + +try_to_find_pair: + for (id = 0; id < trace->sctbl->syscalls.nr_entries; ++id) { + struct syscall *pair = trace__syscall_info(trace, NULL, id); + struct bpf_program *pair_prog; + bool is_candidate = false; + + if (pair == NULL || pair == sc || + pair->bpf_prog.sys_enter == trace->syscalls.unaugmented_prog) + continue; + + for (field = sc->args, candidate_field = pair->args; + field && candidate_field; field = field->next, candidate_field = candidate_field->next) { + bool is_pointer = field->flags & TEP_FIELD_IS_POINTER, + candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER; + + if (is_pointer) { + if (!candidate_is_pointer) { + // The candidate just doesn't copies our pointer arg, might copy other pointers we want. + continue; + } + } else { + if (candidate_is_pointer) { + // The candidate might copy a pointer we don't have, skip it. + goto next_candidate; + } + continue; + } + + if (strcmp(field->type, candidate_field->type)) + goto next_candidate; + + is_candidate = true; + } + + if (!is_candidate) + goto next_candidate; + + /* + * Check if the tentative pair syscall augmenter has more pointers, if it has, + * then it may be collecting that and we then can't use it, as it would collect + * more than what is common to the two syscalls. + */ + if (candidate_field) { + for (candidate_field = candidate_field->next; candidate_field; candidate_field = candidate_field->next) + if (candidate_field->flags & TEP_FIELD_IS_POINTER) + goto next_candidate; + } + + pair_prog = pair->bpf_prog.sys_enter; + /* + * If the pair isn't enabled, then its bpf_prog.sys_enter will not + * have been searched for, so search it here and if it returns the + * unaugmented one, then ignore it, otherwise we'll reuse that BPF + * program for a filtered syscall on a non-filtered one. + * + * For instance, we have "!syscalls:sys_enter_renameat" and that is + * useful for "renameat2". + */ + if (pair_prog == NULL) { + pair_prog = trace__find_syscall_bpf_prog(trace, pair, pair->fmt ? pair->fmt->bpf_prog_name.sys_enter : NULL, "enter"); + if (pair_prog == trace->syscalls.unaugmented_prog) + goto next_candidate; + } + + pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc->name); + return pair_prog; + next_candidate: + continue; + } + + return NULL; +} + static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace) { int map_enter_fd = bpf_map__fd(trace->syscalls.prog_array.sys_enter), @@ -2935,6 +3021,70 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace) break; } + /* + * Now lets do a second pass looking for enabled syscalls without + * an augmenter that have a signature that is a superset of another + * syscall with an augmenter so that we can auto-reuse it. + * + * I.e. if we have an augmenter for the "open" syscall that has + * this signature: + * + * int open(const char *pathname, int flags, mode_t mode); + * + * I.e. that will collect just the first string argument, then we + * can reuse it for the 'creat' syscall, that has this signature: + * + * int creat(const char *pathname, mode_t mode); + * + * and for: + * + * int stat(const char *pathname, struct stat *statbuf); + * int lstat(const char *pathname, struct stat *statbuf); + * + * Because the 'open' augmenter will collect the first arg as a string, + * and leave alone all the other args, which already helps with + * beautifying 'stat' and 'lstat''s pathname arg. + * + * Then, in time, when 'stat' gets an augmenter that collects both + * first and second arg (this one on the raw_syscalls:sys_exit prog + * array tail call, then that one will be used. + */ + for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) { + struct syscall *sc = trace__syscall_info(trace, NULL, key); + struct bpf_program *pair_prog; + int prog_fd; + + if (sc == NULL || sc->bpf_prog.sys_enter == NULL) + continue; + + /* + * For now we're just reusing the sys_enter prog, and if it + * already has an augmenter, we don't need to find one. + */ + if (sc->bpf_prog.sys_enter != trace->syscalls.unaugmented_prog) + continue; + + /* + * Look at all the other syscalls for one that has a signature + * that is close enough that we can share: + */ + pair_prog = trace__find_usable_bpf_prog_entry(trace, sc); + if (pair_prog == NULL) + continue; + + sc->bpf_prog.sys_enter = pair_prog; + + /* + * Update the BPF_MAP_TYPE_PROG_SHARED for raw_syscalls:sys_enter + * with the fd for the program we're reusing: + */ + prog_fd = bpf_program__fd(sc->bpf_prog.sys_enter); + err = bpf_map_update_elem(map_enter_fd, &key, &prog_fd, BPF_ANY); + if (err) + break; + } + + return err; } #else -- GitLab From e4b00e930bf71ef32189716e6cb6b0565592f078 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jul 2019 20:32:13 -0300 Subject: [PATCH 1126/7155] perf trace: Add "sendfile64" alias to the "sendfile" syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were looking in tracefs for: /sys/kernel/debug/tracing/events/syscalls/sys_enter_sendfile/format when what is there is just /sys/kernel/debug/tracing/events/syscalls/sys_enter_sendfile/format Its the same id, 40 in x86_64, so just add an alias and let the existing logic take care of that. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-km2hmg7hru6u4pawi5fi903q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 200fbe33d5de..ca28c48f812e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -895,6 +895,7 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ }, [1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, }, { .name = "select", .timeout = true, }, + { .name = "sendfile", .alias = "sendfile64", }, { .name = "sendmmsg", .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, { .name = "sendmsg", -- GitLab From df1d6856eaa7ec9ad1e670685b370f3e66326079 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:48 +0200 Subject: [PATCH 1127/7155] perf stat: Move loaded out of struct perf_counts_values Because we will make struct perf_counts_values public in following patches and 'loaded' is implementation related. No functional change is expected. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 4 ++-- tools/perf/util/counts.c | 11 +++++++++++ tools/perf/util/counts.h | 14 +++++++++++++- tools/perf/util/evsel.c | 3 ++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 352cf39d7c2f..7b9c26f9cf34 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -287,7 +287,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs) * The leader's group read loads data into its group members * (via perf_evsel__read_counter) and sets threir count->loaded. */ - if (!count->loaded && + if (!perf_counts__is_loaded(counter->counts, cpu, thread) && read_single_counter(counter, cpu, thread, rs)) { counter->counts->scaled = -1; perf_counts(counter->counts, cpu, thread)->ena = 0; @@ -295,7 +295,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs) return -1; } - count->loaded = false; + perf_counts__set_loaded(counter->counts, cpu, thread, false); if (STAT_RECORD) { if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c index 88be9c4365e0..01ee81df3fe5 100644 --- a/tools/perf/util/counts.c +++ b/tools/perf/util/counts.c @@ -19,6 +19,15 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads) } counts->values = values; + + values = xyarray__new(ncpus, nthreads, sizeof(bool)); + if (!values) { + xyarray__delete(counts->values); + free(counts); + return NULL; + } + + counts->loaded = values; } return counts; @@ -27,6 +36,7 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads) void perf_counts__delete(struct perf_counts *counts) { if (counts) { + xyarray__delete(counts->loaded); xyarray__delete(counts->values); free(counts); } @@ -34,6 +44,7 @@ void perf_counts__delete(struct perf_counts *counts) static void perf_counts__reset(struct perf_counts *counts) { + xyarray__reset(counts->loaded); xyarray__reset(counts->values); } diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index 0d1050ccc586..460b56ce3252 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -13,13 +13,13 @@ struct perf_counts_values { }; u64 values[3]; }; - bool loaded; }; struct perf_counts { s8 scaled; struct perf_counts_values aggr; struct xyarray *values; + struct xyarray *loaded; }; @@ -29,6 +29,18 @@ perf_counts(struct perf_counts *counts, int cpu, int thread) return xyarray__entry(counts->values, cpu, thread); } +static inline bool +perf_counts__is_loaded(struct perf_counts *counts, int cpu, int thread) +{ + return *((bool *) xyarray__entry(counts->loaded, cpu, thread)); +} + +static inline void +perf_counts__set_loaded(struct perf_counts *counts, int cpu, int thread, bool loaded) +{ + *((bool *) xyarray__entry(counts->loaded, cpu, thread)) = loaded; +} + struct perf_counts *perf_counts__new(int ncpus, int nthreads); void perf_counts__delete(struct perf_counts *counts); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7d1757a2ec46..d23b9574f793 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1439,7 +1439,8 @@ perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, count->val = val; count->ena = ena; count->run = run; - count->loaded = true; + + perf_counts__set_loaded(counter->counts, cpu, thread, true); } static int -- GitLab From f854839ba2a546a888159667c5ade96793e5cd10 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:49 +0200 Subject: [PATCH 1128/7155] perf cpu_map: Rename struct cpu_map to struct perf_cpu_map Rename struct cpu_map to struct perf_cpu_map, so it could be part of libperf. Committer notes: Added fixes for arm64, provided by Jiri. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 16 ++-- tools/perf/arch/arm64/util/header.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/arch/x86/util/intel-bts.c | 2 +- tools/perf/arch/x86/util/intel-pt.c | 2 +- tools/perf/bench/epoll-ctl.c | 4 +- tools/perf/bench/epoll-wait.c | 4 +- tools/perf/bench/futex-hash.c | 2 +- tools/perf/bench/futex-lock-pi.c | 4 +- tools/perf/bench/futex-requeue.c | 4 +- tools/perf/bench/futex-wake-parallel.c | 4 +- tools/perf/bench/futex-wake.c | 4 +- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-ftrace.c | 6 +- tools/perf/builtin-sched.c | 8 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-stat.c | 46 +++++------ tools/perf/tests/bitmap.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/cpumap.c | 8 +- tools/perf/tests/event-times.c | 4 +- tools/perf/tests/event_update.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mem2node.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/tests/topology.c | 4 +- tools/perf/util/cpumap.c | 78 +++++++++---------- tools/perf/util/cpumap.h | 52 ++++++------- tools/perf/util/cputopo.c | 4 +- tools/perf/util/env.h | 2 +- tools/perf/util/event.c | 18 ++--- tools/perf/util/event.h | 8 +- tools/perf/util/evlist.c | 10 +-- tools/perf/util/evlist.h | 8 +- tools/perf/util/evsel.c | 8 +- tools/perf/util/evsel.h | 12 +-- tools/perf/util/header.c | 4 +- tools/perf/util/mmap.c | 2 +- tools/perf/util/parse-events.c | 2 +- tools/perf/util/pmu.c | 10 +-- tools/perf/util/pmu.h | 2 +- tools/perf/util/python.c | 6 +- tools/perf/util/record.c | 6 +- .../scripting-engines/trace-event-python.c | 2 +- tools/perf/util/session.c | 2 +- tools/perf/util/stat.c | 2 +- tools/perf/util/stat.h | 6 +- tools/perf/util/svghelper.c | 2 +- 52 files changed, 198 insertions(+), 198 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 4208974c24f8..d08b55c27774 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -155,8 +155,8 @@ static int cs_etm_set_option(struct auxtrace_record *itr, struct perf_evsel *evsel, u32 option) { int i, err = -EINVAL; - struct cpu_map *event_cpus = evsel->evlist->cpus; - struct cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *event_cpus = evsel->evlist->cpus; + struct perf_cpu_map *online_cpus = cpu_map__new(NULL); /* Set option of each CPU we have */ for (i = 0; i < cpu__max_cpu(); i++) { @@ -253,7 +253,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; struct perf_evsel *evsel, *cs_etm_evsel = NULL; - struct cpu_map *cpus = evlist->cpus; + struct perf_cpu_map *cpus = evlist->cpus; bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0); int err = 0; @@ -489,8 +489,8 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, { int i; int etmv3 = 0, etmv4 = 0; - struct cpu_map *event_cpus = evlist->cpus; - struct cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *event_cpus = evlist->cpus; + struct perf_cpu_map *online_cpus = cpu_map__new(NULL); /* cpu map is not empty, we have specific CPUs to work with */ if (!cpu_map__empty(event_cpus)) { @@ -635,9 +635,9 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, int i; u32 offset; u64 nr_cpu, type; - struct cpu_map *cpu_map; - struct cpu_map *event_cpus = session->evlist->cpus; - struct cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *cpu_map; + struct perf_cpu_map *event_cpus = session->evlist->cpus; + struct perf_cpu_map *online_cpus = cpu_map__new(NULL); struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c index 534cd2507d83..b3e73a413f5a 100644 --- a/tools/perf/arch/arm64/util/header.c +++ b/tools/perf/arch/arm64/util/header.c @@ -16,7 +16,7 @@ char *get_cpuid_str(struct perf_pmu *pmu) const char *sysfs = sysfs__mountpoint(); int cpu; u64 midr = 0; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; FILE *file; if (!sysfs || !pmu || !pmu->cpus) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 7a7721604b86..4676fd967dc6 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -50,7 +50,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe .sample_time = true, }; struct thread_map *threads = NULL; - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; int err = -1, ret, i; diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index ec5c1bb84095..da1583d27efd 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -106,7 +106,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, container_of(itr, struct intel_bts_recording, itr); struct perf_pmu *intel_bts_pmu = btsr->intel_bts_pmu; struct perf_evsel *evsel, *intel_bts_evsel = NULL; - const struct cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; btsr->evlist = evlist; diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 609088c01e3a..69a23e40abc9 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -557,7 +557,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; bool have_timing_info, need_immediate = false; struct perf_evsel *evsel, *intel_pt_evsel = NULL; - const struct cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; u64 tsc_bit; int err; diff --git a/tools/perf/bench/epoll-ctl.c b/tools/perf/bench/epoll-ctl.c index 2af067859966..1fd724f1d48b 100644 --- a/tools/perf/bench/epoll-ctl.c +++ b/tools/perf/bench/epoll-ctl.c @@ -219,7 +219,7 @@ static void init_fdmaps(struct worker *w, int pct) } } -static int do_threads(struct worker *worker, struct cpu_map *cpu) +static int do_threads(struct worker *worker, struct perf_cpu_map *cpu) { pthread_attr_t thread_attr, *attrp = NULL; cpu_set_t cpuset; @@ -301,7 +301,7 @@ int bench_epoll_ctl(int argc, const char **argv) int j, ret = 0; struct sigaction act; struct worker *worker = NULL; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; struct rlimit rl, prevrl; unsigned int i; diff --git a/tools/perf/bench/epoll-wait.c b/tools/perf/bench/epoll-wait.c index fe85448abd45..79a254fff2d1 100644 --- a/tools/perf/bench/epoll-wait.c +++ b/tools/perf/bench/epoll-wait.c @@ -288,7 +288,7 @@ static void print_summary(void) (int) runtime.tv_sec); } -static int do_threads(struct worker *worker, struct cpu_map *cpu) +static int do_threads(struct worker *worker, struct perf_cpu_map *cpu) { pthread_attr_t thread_attr, *attrp = NULL; cpu_set_t cpuset; @@ -415,7 +415,7 @@ int bench_epoll_wait(int argc, const char **argv) struct sigaction act; unsigned int i; struct worker *worker = NULL; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; pthread_t wthread; struct rlimit rl, prevrl; diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c index a80797763e1f..b4fea8e3a368 100644 --- a/tools/perf/bench/futex-hash.c +++ b/tools/perf/bench/futex-hash.c @@ -124,7 +124,7 @@ int bench_futex_hash(int argc, const char **argv) unsigned int i; pthread_attr_t thread_attr; struct worker *worker = NULL; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0); if (argc) { diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c index d02330a69745..596769924709 100644 --- a/tools/perf/bench/futex-lock-pi.c +++ b/tools/perf/bench/futex-lock-pi.c @@ -116,7 +116,7 @@ static void *workerfn(void *arg) } static void create_threads(struct worker *w, pthread_attr_t thread_attr, - struct cpu_map *cpu) + struct perf_cpu_map *cpu) { cpu_set_t cpuset; unsigned int i; @@ -150,7 +150,7 @@ int bench_futex_lock_pi(int argc, const char **argv) unsigned int i; struct sigaction act; pthread_attr_t thread_attr; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0); if (argc) diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c index fc692efa0c05..1fd32a4f9c14 100644 --- a/tools/perf/bench/futex-requeue.c +++ b/tools/perf/bench/futex-requeue.c @@ -84,7 +84,7 @@ static void *workerfn(void *arg __maybe_unused) } static void block_threads(pthread_t *w, - pthread_attr_t thread_attr, struct cpu_map *cpu) + pthread_attr_t thread_attr, struct perf_cpu_map *cpu) { cpu_set_t cpuset; unsigned int i; @@ -117,7 +117,7 @@ int bench_futex_requeue(int argc, const char **argv) unsigned int i, j; struct sigaction act; pthread_attr_t thread_attr; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0); if (argc) diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c index 69d8fdc87315..884c73e5bd1b 100644 --- a/tools/perf/bench/futex-wake-parallel.c +++ b/tools/perf/bench/futex-wake-parallel.c @@ -138,7 +138,7 @@ static void *blocked_workerfn(void *arg __maybe_unused) } static void block_threads(pthread_t *w, pthread_attr_t thread_attr, - struct cpu_map *cpu) + struct perf_cpu_map *cpu) { cpu_set_t cpuset; unsigned int i; @@ -224,7 +224,7 @@ int bench_futex_wake_parallel(int argc, const char **argv) struct sigaction act; pthread_attr_t thread_attr; struct thread_data *waking_worker; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; argc = parse_options(argc, argv, options, bench_futex_wake_parallel_usage, 0); diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c index e8181ad7d088..2288fa8412ff 100644 --- a/tools/perf/bench/futex-wake.c +++ b/tools/perf/bench/futex-wake.c @@ -90,7 +90,7 @@ static void print_summary(void) } static void block_threads(pthread_t *w, - pthread_attr_t thread_attr, struct cpu_map *cpu) + pthread_attr_t thread_attr, struct perf_cpu_map *cpu) { cpu_set_t cpuset; unsigned int i; @@ -123,7 +123,7 @@ int bench_futex_wake(int argc, const char **argv) unsigned int i, j; struct sigaction act; pthread_attr_t thread_attr; - struct cpu_map *cpu; + struct perf_cpu_map *cpu; argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0); if (argc) { diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index e3776f5c2e01..52035dacf253 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2049,7 +2049,7 @@ static int setup_nodes(struct perf_session *session) c2c.cpu2node = cpu2node; for (node = 0; node < c2c.nodes_cnt; node++) { - struct cpu_map *map = n[node].map; + struct perf_cpu_map *map = n[node].map; unsigned long *set; set = bitmap_alloc(c2c.cpus_cnt); diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 66d5a6658daf..3e81e0b6628f 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -165,7 +165,7 @@ static int set_tracing_pid(struct perf_ftrace *ftrace) return 0; } -static int set_tracing_cpumask(struct cpu_map *cpumap) +static int set_tracing_cpumask(struct perf_cpu_map *cpumap) { char *cpumask; size_t mask_size; @@ -192,7 +192,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap) static int set_tracing_cpu(struct perf_ftrace *ftrace) { - struct cpu_map *cpumap = ftrace->evlist->cpus; + struct perf_cpu_map *cpumap = ftrace->evlist->cpus; if (!target__has_cpu(&ftrace->target)) return 0; @@ -202,7 +202,7 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace) static int reset_tracing_cpu(void) { - struct cpu_map *cpumap = cpu_map__new(NULL); + struct perf_cpu_map *cpumap = cpu_map__new(NULL); int ret; ret = set_tracing_cpumask(cpumap); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 56d1907b1215..51dd48f20972 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -161,9 +161,9 @@ struct perf_sched_map { bool comp; struct thread_map *color_pids; const char *color_pids_str; - struct cpu_map *color_cpus; + struct perf_cpu_map *color_cpus; const char *color_cpus_str; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; const char *cpus_str; }; @@ -3170,7 +3170,7 @@ static int perf_sched__lat(struct perf_sched *sched) static int setup_map_cpus(struct perf_sched *sched) { - struct cpu_map *map; + struct perf_cpu_map *map; sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); @@ -3212,7 +3212,7 @@ static int setup_color_pids(struct perf_sched *sched) static int setup_color_cpus(struct perf_sched *sched) { - struct cpu_map *map; + struct perf_cpu_map *map; if (!sched->map.color_cpus_str) return 0; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 0140ddb8dd0b..0109c8710b93 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1627,7 +1627,7 @@ struct perf_script { bool show_bpf_events; bool allocated; bool per_event_dump; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; int name_width; const char *time_str; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7b9c26f9cf34..d68738b5bd0c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -164,7 +164,7 @@ struct perf_stat { u64 bytes_written; struct perf_tool tool; bool maps_allocated; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; enum aggr_mode aggr_mode; }; @@ -803,24 +803,24 @@ static struct option stat_options[] = { }; static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int cpu) + struct perf_cpu_map *map, int cpu) { return cpu_map__get_socket(map, cpu, NULL); } static int perf_stat__get_die(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int cpu) + struct perf_cpu_map *map, int cpu) { return cpu_map__get_die(map, cpu, NULL); } static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int cpu) + struct perf_cpu_map *map, int cpu) { return cpu_map__get_core(map, cpu, NULL); } -static int cpu_map__get_max(struct cpu_map *map) +static int cpu_map__get_max(struct perf_cpu_map *map) { int i, max = -1; @@ -833,7 +833,7 @@ static int cpu_map__get_max(struct cpu_map *map) } static int perf_stat__get_aggr(struct perf_stat_config *config, - aggr_get_id_t get_id, struct cpu_map *map, int idx) + aggr_get_id_t get_id, struct perf_cpu_map *map, int idx) { int cpu; @@ -849,19 +849,19 @@ static int perf_stat__get_aggr(struct perf_stat_config *config, } static int perf_stat__get_socket_cached(struct perf_stat_config *config, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx); } static int perf_stat__get_die_cached(struct perf_stat_config *config, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_stat__get_aggr(config, perf_stat__get_die, map, idx); } static int perf_stat__get_core_cached(struct perf_stat_config *config, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_stat__get_aggr(config, perf_stat__get_core, map, idx); } @@ -939,7 +939,7 @@ static void perf_stat__exit_aggr_mode(void) stat_config.cpus_aggr_map = NULL; } -static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) +static inline int perf_env__get_cpu(struct perf_env *env, struct perf_cpu_map *map, int idx) { int cpu; @@ -954,7 +954,7 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, i return cpu; } -static int perf_env__get_socket(struct cpu_map *map, int idx, void *data) +static int perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data) { struct perf_env *env = data; int cpu = perf_env__get_cpu(env, map, idx); @@ -962,7 +962,7 @@ static int perf_env__get_socket(struct cpu_map *map, int idx, void *data) return cpu == -1 ? -1 : env->cpu[cpu].socket_id; } -static int perf_env__get_die(struct cpu_map *map, int idx, void *data) +static int perf_env__get_die(struct perf_cpu_map *map, int idx, void *data) { struct perf_env *env = data; int die_id = -1, cpu = perf_env__get_cpu(env, map, idx); @@ -986,7 +986,7 @@ static int perf_env__get_die(struct cpu_map *map, int idx, void *data) return die_id; } -static int perf_env__get_core(struct cpu_map *map, int idx, void *data) +static int perf_env__get_core(struct perf_cpu_map *map, int idx, void *data) { struct perf_env *env = data; int core = -1, cpu = perf_env__get_cpu(env, map, idx); @@ -1016,37 +1016,37 @@ static int perf_env__get_core(struct cpu_map *map, int idx, void *data) return core; } -static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus, - struct cpu_map **sockp) +static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus, + struct perf_cpu_map **sockp) { return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env); } -static int perf_env__build_die_map(struct perf_env *env, struct cpu_map *cpus, - struct cpu_map **diep) +static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus, + struct perf_cpu_map **diep) { return cpu_map__build_map(cpus, diep, perf_env__get_die, env); } -static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus, - struct cpu_map **corep) +static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus, + struct perf_cpu_map **corep) { return cpu_map__build_map(cpus, corep, perf_env__get_core, env); } static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_env__get_socket(map, idx, &perf_stat.session->header.env); } static int perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_env__get_die(map, idx, &perf_stat.session->header.env); } static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused, - struct cpu_map *map, int idx) + struct perf_cpu_map *map, int idx) { return perf_env__get_core(map, idx, &perf_stat.session->header.env); } @@ -1551,7 +1551,7 @@ int process_cpu_map_event(struct perf_session *session, { struct perf_tool *tool = session->tool; struct perf_stat *st = container_of(tool, struct perf_stat, tool); - struct cpu_map *cpus; + struct perf_cpu_map *cpus; if (st->cpus) { pr_warning("Extra cpu map event, ignoring.\n"); diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c index 96e7fc1ad3f9..74d0cd32a5c4 100644 --- a/tools/perf/tests/bitmap.c +++ b/tools/perf/tests/bitmap.c @@ -9,7 +9,7 @@ static unsigned long *get_bitmap(const char *str, int nbits) { - struct cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = cpu_map__new(str); unsigned long *bm = NULL; int i; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index aa6df122b175..948ec278ad06 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -553,7 +553,7 @@ static int do_test_code_reading(bool try_kcore) .done_cnt = 0, }; struct thread_map *threads = NULL; - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; int err = -1, ret; diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index e78b897677bd..10da4400493d 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -17,7 +17,7 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused, struct cpu_map_event *map_event = &event->cpu_map; struct cpu_map_mask *mask; struct cpu_map_data *data; - struct cpu_map *map; + struct perf_cpu_map *map; int i; data = &map_event->data; @@ -51,7 +51,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, struct cpu_map_event *map_event = &event->cpu_map; struct cpu_map_entries *cpus; struct cpu_map_data *data; - struct cpu_map *map; + struct perf_cpu_map *map; data = &map_event->data; @@ -75,7 +75,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct cpu_map *cpus; + struct perf_cpu_map *cpus; /* This one is better stores in mask. */ cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19"); @@ -97,7 +97,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may static int cpu_map_print(const char *str) { - struct cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = cpu_map__new(str); char buf[100]; if (!map) diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 1a2686f1fcf0..ed90b62bf048 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -110,7 +110,7 @@ static int detach__disable(struct perf_evlist *evlist) static int attach__cpu_disabled(struct perf_evlist *evlist) { struct perf_evsel *evsel = perf_evlist__last(evlist); - struct cpu_map *cpus; + struct perf_cpu_map *cpus; int err; pr_debug("attaching to CPU 0 as enabled\n"); @@ -139,7 +139,7 @@ static int attach__cpu_disabled(struct perf_evlist *evlist) static int attach__cpu_enabled(struct perf_evlist *evlist) { struct perf_evsel *evsel = perf_evlist__last(evlist); - struct cpu_map *cpus; + struct perf_cpu_map *cpus; int err; pr_debug("attaching to CPU 0 as enabled\n"); diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index f14dcd613438..b5042f019ec4 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -61,7 +61,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, { struct event_update_event *ev = (struct event_update_event*) event; struct event_update_event_cpus *ev_data; - struct cpu_map *map; + struct perf_cpu_map *map; ev_data = (struct event_update_event_cpus*) ev->data; diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 17c46f3e6f1e..68331a81bcdd 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -66,7 +66,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un }, }; struct thread_map *threads = NULL; - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; int found, err = -1; diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c index 520cc91af256..e12eedfba781 100644 --- a/tools/perf/tests/mem2node.c +++ b/tools/perf/tests/mem2node.c @@ -19,7 +19,7 @@ static struct node { static unsigned long *get_bitmap(const char *str, int nbits) { - struct cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = cpu_map__new(str); unsigned long *bm = NULL; int i; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 0919b0793e5b..1bc8fd3ea510 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -28,7 +28,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse int err = -1; union perf_event *event; struct thread_map *threads; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct perf_evlist *evlist; cpu_set_t cpu_set; const char *syscall_names[] = { "getsid", "getppid", "getpgid", }; diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 493ecb611540..f393aa836dfb 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -20,7 +20,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused) { int err = -1, fd, cpu; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct perf_evsel *evsel; unsigned int nr_openat_calls = 111, i; cpu_set_t cpu_set; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index f9490b237893..d9121b5033b7 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -37,7 +37,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) .disabled = 1, .freq = 1, }; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; struct perf_mmap *md; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 6cdab5f4812a..826f20a4cb51 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -328,7 +328,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ }, }; struct thread_map *threads = NULL; - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; struct perf_evsel *switch_evsel, *tracking_evsel; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index e92fa6029ac7..d66767be4c45 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -45,7 +45,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused }; const char *argv[] = { "true", NULL }; char sbuf[STRERR_BUFSIZE]; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; struct perf_mmap *md; diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 9497d02f69e6..443d0272ebbd 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -57,7 +57,7 @@ static int session_write_header(char *path) return 0; } -static int check_cpu_topology(char *path, struct cpu_map *map) +static int check_cpu_topology(char *path, struct perf_cpu_map *map) { struct perf_session *session; struct perf_data data = { @@ -116,7 +116,7 @@ static int check_cpu_topology(char *path, struct cpu_map *map) int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused) { char path[PATH_MAX]; - struct cpu_map *map; + struct perf_cpu_map *map; int ret = TEST_FAIL; TEST_ASSERT_VAL("can't get templ file", !get_temp(path)); diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 3acfbe34ebaf..5eb4e1fbb877 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -17,9 +17,9 @@ static int max_present_cpu_num; static int max_node_num; static int *cpunode_map; -static struct cpu_map *cpu_map__default_new(void) +static struct perf_cpu_map *cpu_map__default_new(void) { - struct cpu_map *cpus; + struct perf_cpu_map *cpus; int nr_cpus; nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -39,10 +39,10 @@ static struct cpu_map *cpu_map__default_new(void) return cpus; } -static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) +static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) { size_t payload_size = nr_cpus * sizeof(int); - struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); + struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); if (cpus != NULL) { cpus->nr = nr_cpus; @@ -53,9 +53,9 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) return cpus; } -struct cpu_map *cpu_map__read(FILE *file) +struct perf_cpu_map *cpu_map__read(FILE *file) { - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; int nr_cpus = 0; int *tmp_cpus = NULL, *tmp; int max_entries = 0; @@ -108,9 +108,9 @@ struct cpu_map *cpu_map__read(FILE *file) return cpus; } -static struct cpu_map *cpu_map__read_all_cpu_map(void) +static struct perf_cpu_map *cpu_map__read_all_cpu_map(void) { - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; FILE *onlnf; onlnf = fopen("/sys/devices/system/cpu/online", "r"); @@ -122,9 +122,9 @@ static struct cpu_map *cpu_map__read_all_cpu_map(void) return cpus; } -struct cpu_map *cpu_map__new(const char *cpu_list) +struct perf_cpu_map *cpu_map__new(const char *cpu_list) { - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; unsigned long start_cpu, end_cpu = 0; char *p = NULL; int i, nr_cpus = 0; @@ -196,9 +196,9 @@ struct cpu_map *cpu_map__new(const char *cpu_list) return cpus; } -static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) +static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) { - struct cpu_map *map; + struct perf_cpu_map *map; map = cpu_map__empty_new(cpus->nr); if (map) { @@ -220,9 +220,9 @@ static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) return map; } -static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask) +static struct perf_cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask) { - struct cpu_map *map; + struct perf_cpu_map *map; int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE; nr = bitmap_weight(mask->mask, nbits); @@ -238,7 +238,7 @@ static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask) } -struct cpu_map *cpu_map__new_data(struct cpu_map_data *data) +struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data) { if (data->type == PERF_CPU_MAP__CPUS) return cpu_map__from_entries((struct cpu_map_entries *)data->data); @@ -246,7 +246,7 @@ struct cpu_map *cpu_map__new_data(struct cpu_map_data *data) return cpu_map__from_mask((struct cpu_map_mask *)data->data); } -size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) +size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) { #define BUFSIZE 1024 char buf[BUFSIZE]; @@ -256,9 +256,9 @@ size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) #undef BUFSIZE } -struct cpu_map *cpu_map__dummy_new(void) +struct perf_cpu_map *cpu_map__dummy_new(void) { - struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); + struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); if (cpus != NULL) { cpus->nr = 1; @@ -269,9 +269,9 @@ struct cpu_map *cpu_map__dummy_new(void) return cpus; } -struct cpu_map *cpu_map__empty_new(int nr) +struct perf_cpu_map *cpu_map__empty_new(int nr) { - struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); + struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); if (cpus != NULL) { int i; @@ -286,7 +286,7 @@ struct cpu_map *cpu_map__empty_new(int nr) return cpus; } -static void cpu_map__delete(struct cpu_map *map) +static void cpu_map__delete(struct perf_cpu_map *map) { if (map) { WARN_ONCE(refcount_read(&map->refcnt) != 0, @@ -295,14 +295,14 @@ static void cpu_map__delete(struct cpu_map *map) } } -struct cpu_map *cpu_map__get(struct cpu_map *map) +struct perf_cpu_map *cpu_map__get(struct perf_cpu_map *map) { if (map) refcount_inc(&map->refcnt); return map; } -void cpu_map__put(struct cpu_map *map) +void cpu_map__put(struct perf_cpu_map *map) { if (map && refcount_dec_and_test(&map->refcnt)) cpu_map__delete(map); @@ -324,7 +324,7 @@ int cpu_map__get_socket_id(int cpu) return ret ?: value; } -int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused) +int cpu_map__get_socket(struct perf_cpu_map *map, int idx, void *data __maybe_unused) { int cpu; @@ -341,11 +341,11 @@ static int cmp_ids(const void *a, const void *b) return *(int *)a - *(int *)b; } -int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, - int (*f)(struct cpu_map *map, int cpu, void *data), +int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res, + int (*f)(struct perf_cpu_map *map, int cpu, void *data), void *data) { - struct cpu_map *c; + struct perf_cpu_map *c; int nr = cpus->nr; int cpu, s1, s2; @@ -380,7 +380,7 @@ int cpu_map__get_die_id(int cpu) return ret ?: value; } -int cpu_map__get_die(struct cpu_map *map, int idx, void *data) +int cpu_map__get_die(struct perf_cpu_map *map, int idx, void *data) { int cpu, die_id, s; @@ -419,7 +419,7 @@ int cpu_map__get_core_id(int cpu) return ret ?: value; } -int cpu_map__get_core(struct cpu_map *map, int idx, void *data) +int cpu_map__get_core(struct perf_cpu_map *map, int idx, void *data) { int cpu, s_die; @@ -448,17 +448,17 @@ int cpu_map__get_core(struct cpu_map *map, int idx, void *data) return (s_die << 16) | (cpu & 0xffff); } -int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp) +int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct perf_cpu_map **sockp) { return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL); } -int cpu_map__build_die_map(struct cpu_map *cpus, struct cpu_map **diep) +int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct perf_cpu_map **diep) { return cpu_map__build_map(cpus, diep, cpu_map__get_die, NULL); } -int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep) +int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct perf_cpu_map **corep) { return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL); } @@ -670,12 +670,12 @@ int cpu__setup_cpunode_map(void) return 0; } -bool cpu_map__has(struct cpu_map *cpus, int cpu) +bool cpu_map__has(struct perf_cpu_map *cpus, int cpu) { return cpu_map__idx(cpus, cpu) != -1; } -int cpu_map__idx(struct cpu_map *cpus, int cpu) +int cpu_map__idx(struct perf_cpu_map *cpus, int cpu) { int i; @@ -687,12 +687,12 @@ int cpu_map__idx(struct cpu_map *cpus, int cpu) return -1; } -int cpu_map__cpu(struct cpu_map *cpus, int idx) +int cpu_map__cpu(struct perf_cpu_map *cpus, int idx) { return cpus->map[idx]; } -size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size) +size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size) { int i, cpu, start = -1; bool first = true; @@ -744,7 +744,7 @@ static char hex_char(unsigned char val) return '?'; } -size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size) +size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size) { int i, cpu; char *ptr = buf; @@ -781,9 +781,9 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size) return ptr - buf; } -const struct cpu_map *cpu_map__online(void) /* thread unsafe */ +const struct perf_cpu_map *cpu_map__online(void) /* thread unsafe */ { - static const struct cpu_map *online = NULL; + static const struct perf_cpu_map *online = NULL; if (!online) online = cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */ diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 1265f0e33920..22729beae959 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -9,35 +9,35 @@ #include "perf.h" #include "util/debug.h" -struct cpu_map { +struct perf_cpu_map { refcount_t refcnt; int nr; int map[]; }; -struct cpu_map *cpu_map__new(const char *cpu_list); -struct cpu_map *cpu_map__empty_new(int nr); -struct cpu_map *cpu_map__dummy_new(void); -struct cpu_map *cpu_map__new_data(struct cpu_map_data *data); -struct cpu_map *cpu_map__read(FILE *file); -size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size); -size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size); -size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); +struct perf_cpu_map *cpu_map__new(const char *cpu_list); +struct perf_cpu_map *cpu_map__empty_new(int nr); +struct perf_cpu_map *cpu_map__dummy_new(void); +struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); +struct perf_cpu_map *cpu_map__read(FILE *file); +size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); +size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); +size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); int cpu_map__get_socket_id(int cpu); -int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); +int cpu_map__get_socket(struct perf_cpu_map *map, int idx, void *data); int cpu_map__get_die_id(int cpu); -int cpu_map__get_die(struct cpu_map *map, int idx, void *data); +int cpu_map__get_die(struct perf_cpu_map *map, int idx, void *data); int cpu_map__get_core_id(int cpu); -int cpu_map__get_core(struct cpu_map *map, int idx, void *data); -int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); -int cpu_map__build_die_map(struct cpu_map *cpus, struct cpu_map **diep); -int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); -const struct cpu_map *cpu_map__online(void); /* thread unsafe */ +int cpu_map__get_core(struct perf_cpu_map *map, int idx, void *data); +int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct perf_cpu_map **sockp); +int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct perf_cpu_map **diep); +int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct perf_cpu_map **corep); +const struct perf_cpu_map *cpu_map__online(void); /* thread unsafe */ -struct cpu_map *cpu_map__get(struct cpu_map *map); -void cpu_map__put(struct cpu_map *map); +struct perf_cpu_map *cpu_map__get(struct perf_cpu_map *map); +void cpu_map__put(struct perf_cpu_map *map); -static inline int cpu_map__socket(struct cpu_map *sock, int s) +static inline int cpu_map__socket(struct perf_cpu_map *sock, int s) { if (!sock || s > sock->nr || s < 0) return 0; @@ -59,12 +59,12 @@ static inline int cpu_map__id_to_cpu(int id) return id & 0xffff; } -static inline int cpu_map__nr(const struct cpu_map *map) +static inline int cpu_map__nr(const struct perf_cpu_map *map) { return map ? map->nr : 1; } -static inline bool cpu_map__empty(const struct cpu_map *map) +static inline bool cpu_map__empty(const struct perf_cpu_map *map) { return map ? map->map[0] == -1 : true; } @@ -76,11 +76,11 @@ int cpu__max_cpu(void); int cpu__max_present_cpu(void); int cpu__get_node(int cpu); -int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, - int (*f)(struct cpu_map *map, int cpu, void *data), +int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res, + int (*f)(struct perf_cpu_map *map, int cpu, void *data), void *data); -int cpu_map__cpu(struct cpu_map *cpus, int idx); -bool cpu_map__has(struct cpu_map *cpus, int cpu); -int cpu_map__idx(struct cpu_map *cpus, int cpu); +int cpu_map__cpu(struct perf_cpu_map *cpus, int idx); +bool cpu_map__has(struct perf_cpu_map *cpus, int cpu); +int cpu_map__idx(struct perf_cpu_map *cpus, int cpu); #endif /* __PERF_CPUMAP_H */ diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 64336a280967..157b0988435e 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -176,7 +176,7 @@ struct cpu_topology *cpu_topology__new(void) size_t sz; long ncpus; int ret = -1; - struct cpu_map *map; + struct perf_cpu_map *map; bool has_die = has_die_topology(); ncpus = cpu__max_present_cpu(); @@ -289,7 +289,7 @@ static int load_numa_node(struct numa_topology_node *node, int nr) struct numa_topology *numa_topology__new(void) { - struct cpu_map *node_map = NULL; + struct perf_cpu_map *node_map = NULL; struct numa_topology *tp = NULL; char path[MAXPATHLEN]; char *buf = NULL; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index d5d9865aa812..d8e083d42610 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -27,7 +27,7 @@ struct numa_node { u32 node; u64 mem_total; u64 mem_free; - struct cpu_map *map; + struct perf_cpu_map *map; }; struct memory_node { diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f1f4848947ce..406ad8772907 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1008,7 +1008,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, } static void synthesize_cpus(struct cpu_map_entries *cpus, - struct cpu_map *map) + struct perf_cpu_map *map) { int i; @@ -1019,7 +1019,7 @@ static void synthesize_cpus(struct cpu_map_entries *cpus, } static void synthesize_mask(struct cpu_map_mask *mask, - struct cpu_map *map, int max) + struct perf_cpu_map *map, int max) { int i; @@ -1030,12 +1030,12 @@ static void synthesize_mask(struct cpu_map_mask *mask, set_bit(map->map[i], mask->mask); } -static size_t cpus_size(struct cpu_map *map) +static size_t cpus_size(struct perf_cpu_map *map) { return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16); } -static size_t mask_size(struct cpu_map *map, int *max) +static size_t mask_size(struct perf_cpu_map *map, int *max) { int i; @@ -1052,7 +1052,7 @@ static size_t mask_size(struct cpu_map *map, int *max) return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long); } -void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max) +void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max) { size_t size_cpus, size_mask; bool is_dummy = cpu_map__empty(map); @@ -1086,7 +1086,7 @@ void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max return zalloc(*size); } -void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, +void cpu_map_data__synthesize(struct cpu_map_data *data, struct perf_cpu_map *map, u16 type, int max) { data->type = type; @@ -1102,7 +1102,7 @@ void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, }; } -static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map) +static struct cpu_map_event* cpu_map_event__new(struct perf_cpu_map *map) { size_t size = sizeof(struct cpu_map_event); struct cpu_map_event *event; @@ -1122,7 +1122,7 @@ static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map) } int perf_event__synthesize_cpu_map(struct perf_tool *tool, - struct cpu_map *map, + struct perf_cpu_map *map, perf_event__handler_t process, struct machine *machine) { @@ -1393,7 +1393,7 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp) size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp) { - struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); + struct perf_cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); size_t ret; ret = fprintf(fp, ": "); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 1f1da6082806..cafaac5128ab 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -675,7 +675,7 @@ void perf_event__print_totals(void); struct perf_tool; struct thread_map; -struct cpu_map; +struct perf_cpu_map; struct perf_stat_config; struct perf_counts_values; @@ -693,7 +693,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_cpu_map(struct perf_tool *tool, - struct cpu_map *cpus, + struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_threads(struct perf_tool *tool, @@ -844,8 +844,8 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp); int kallsyms__get_function_start(const char *kallsyms_filename, const char *symbol_name, u64 *addr); -void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); -void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, +void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max); +void cpu_map_data__synthesize(struct cpu_map_data *data, struct perf_cpu_map *map, u16 type, int max); void event_attr_init(struct perf_event_attr *attr); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b0364d923f76..bce883eaf0dc 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -41,7 +41,7 @@ int sigqueue(pid_t pid, int sig, const union sigval value); #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) -void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, +void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, struct thread_map *threads) { int i; @@ -1012,7 +1012,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, int comp_level) { struct perf_evsel *evsel; - const struct cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->cpus; const struct thread_map *threads = evlist->threads; /* * Delay setting mp.prot: set it before calling perf_mmap__mmap. @@ -1058,7 +1058,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages) int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) { bool all_threads = (target->per_thread && target->system_wide); - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; /* @@ -1104,7 +1104,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) return -1; } -void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, +void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, struct thread_map *threads) { /* @@ -1358,7 +1358,7 @@ void perf_evlist__close(struct perf_evlist *evlist) static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) { - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; int err = -ENOMEM; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 49354fe24d5f..c8cda300b584 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -18,7 +18,7 @@ struct pollfd; struct thread_map; -struct cpu_map; +struct perf_cpu_map; struct record_opts; #define PERF_EVLIST__HLIST_BITS 8 @@ -45,7 +45,7 @@ struct perf_evlist { struct perf_mmap *mmap; struct perf_mmap *overwrite_mmap; struct thread_map *threads; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct perf_evsel *selected; struct events_stats stats; struct perf_env *env; @@ -68,7 +68,7 @@ struct perf_evsel_str_handler { struct perf_evlist *perf_evlist__new(void); struct perf_evlist *perf_evlist__new_default(void); struct perf_evlist *perf_evlist__new_dummy(void); -void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, +void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, struct thread_map *threads); void perf_evlist__exit(struct perf_evlist *evlist); void perf_evlist__delete(struct perf_evlist *evlist); @@ -194,7 +194,7 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist, void perf_evlist__set_selected(struct perf_evlist *evlist, struct perf_evsel *evsel); -void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, +void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, struct thread_map *threads); int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d23b9574f793..958206c538c3 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1825,7 +1825,7 @@ static int perf_event_open(struct perf_evsel *evsel, return fd; } -int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, +int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct thread_map *threads) { int cpu, thread, nthreads; @@ -1837,7 +1837,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, return -EINVAL; if (cpus == NULL) { - static struct cpu_map *empty_cpu_map; + static struct perf_cpu_map *empty_cpu_map; if (empty_cpu_map == NULL) { empty_cpu_map = cpu_map__dummy_new(); @@ -2084,7 +2084,7 @@ void perf_evsel__close(struct perf_evsel *evsel) } int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus) + struct perf_cpu_map *cpus) { return perf_evsel__open(evsel, cpus, NULL); } @@ -3064,7 +3064,7 @@ static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) { - struct cpu_map *cpus = evsel->cpus; + struct perf_cpu_map *cpus = evsel->cpus; struct thread_map *threads = evsel->threads; if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr)) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index b27935a6d36c..76b14037f260 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -124,8 +124,8 @@ struct perf_evsel { u64 db_id; struct cgroup *cgrp; void *handler; - struct cpu_map *cpus; - struct cpu_map *own_cpus; + struct perf_cpu_map *cpus; + struct perf_cpu_map *own_cpus; struct thread_map *threads; unsigned int sample_size; int id_pos; @@ -192,12 +192,12 @@ struct perf_missing_features { extern struct perf_missing_features perf_missing_features; -struct cpu_map; +struct perf_cpu_map; struct target; struct thread_map; struct record_opts; -static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) +static inline struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) { return evsel->cpus; } @@ -300,10 +300,10 @@ int perf_evsel__enable(struct perf_evsel *evsel); int perf_evsel__disable(struct perf_evsel *evsel); int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus); + struct perf_cpu_map *cpus); int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads); -int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, +int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct thread_map *threads); void perf_evsel__close(struct perf_evsel *evsel); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1903d7ec9797..4be216f3598b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3886,7 +3886,7 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) struct event_update_event *ev = &event->event_update; struct event_update_event_scale *ev_scale; struct event_update_event_cpus *ev_cpus; - struct cpu_map *map; + struct perf_cpu_map *map; size_t ret; ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id); @@ -4054,7 +4054,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, struct event_update_event_cpus *ev_cpus; struct perf_evlist *evlist; struct perf_evsel *evsel; - struct cpu_map *map; + struct perf_cpu_map *map; if (!pevlist || *pevlist == NULL) return -EINVAL; diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 9f0b6391af33..177c41fc9842 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -325,7 +325,7 @@ void perf_mmap__munmap(struct perf_mmap *map) static void build_node_mask(int node, cpu_set_t *mask) { int c, cpu, nr_cpus; - const struct cpu_map *cpu_map = NULL; + const struct perf_cpu_map *cpu_map = NULL; cpu_map = cpu_map__online(); if (!cpu_map) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 0540303e5e97..077509609d03 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -322,7 +322,7 @@ __add_event(struct list_head *list, int *idx, const char *cpu_list) { struct perf_evsel *evsel; - struct cpu_map *cpus = pmu ? pmu->cpus : + struct perf_cpu_map *cpus = pmu ? pmu->cpus : cpu_list ? cpu_map__new(cpu_list) : NULL; event_attr_init(attr); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index f32b710347db..4929a50c0973 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -572,10 +572,10 @@ static void pmu_read_sysfs(void) closedir(dir); } -static struct cpu_map *__pmu_cpumask(const char *path) +static struct perf_cpu_map *__pmu_cpumask(const char *path) { FILE *file; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; file = fopen(path, "r"); if (!file) @@ -593,10 +593,10 @@ static struct cpu_map *__pmu_cpumask(const char *path) #define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask" #define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus" -static struct cpu_map *pmu_cpumask(const char *name) +static struct perf_cpu_map *pmu_cpumask(const char *name) { char path[PATH_MAX]; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; const char *sysfs = sysfs__mountpoint(); const char *templates[] = { CPUS_TEMPLATE_UNCORE, @@ -621,7 +621,7 @@ static struct cpu_map *pmu_cpumask(const char *name) static bool pmu_is_uncore(const char *name) { char path[PATH_MAX]; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; const char *sysfs = sysfs__mountpoint(); snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name); diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index bd9ec2704a57..3f8b79b1dd85 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -28,7 +28,7 @@ struct perf_pmu { bool is_uncore; int max_precise; struct perf_event_attr *default_config; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct list_head format; /* HEAD struct perf_pmu_format -> list */ struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ struct list_head list; /* ELEM */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 1e5b6718dcea..be27956ae080 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -536,7 +536,7 @@ static PyObject *pyrf_event__new(union perf_event *event) struct pyrf_cpu_map { PyObject_HEAD - struct cpu_map *cpus; + struct perf_cpu_map *cpus; }; static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, @@ -796,7 +796,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, PyObject *args, PyObject *kwargs) { struct perf_evsel *evsel = &pevsel->evsel; - struct cpu_map *cpus = NULL; + struct perf_cpu_map *cpus = NULL; struct thread_map *threads = NULL; PyObject *pcpus = NULL, *pthreads = NULL; int group = 0, inherit = 0; @@ -865,7 +865,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs __maybe_unused) { PyObject *pcpus = NULL, *pthreads = NULL; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; struct thread_map *threads; if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads)) diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 9cfc7bf16531..051c67f82548 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -60,7 +60,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) static bool perf_probe_api(setup_probe_fn_t fn) { const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; int cpu, ret, i = 0; cpus = cpu_map__new(NULL); @@ -115,7 +115,7 @@ bool perf_can_record_cpu_wide(void) .config = PERF_COUNT_SW_CPU_CLOCK, .exclude_kernel = 1, }; - struct cpu_map *cpus; + struct perf_cpu_map *cpus; int cpu, fd; cpus = cpu_map__new(NULL); @@ -275,7 +275,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) evsel = perf_evlist__last(temp_evlist); if (!evlist || cpu_map__empty(evlist->cpus)) { - struct cpu_map *cpus = cpu_map__new(NULL); + struct perf_cpu_map *cpus = cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; cpu_map__put(cpus); diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 25dc1d765553..a53b30b8819b 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1393,7 +1393,7 @@ static void python_process_stat(struct perf_stat_config *config, struct perf_evsel *counter, u64 tstamp) { struct thread_map *threads = counter->threads; - struct cpu_map *cpus = counter->cpus; + struct perf_cpu_map *cpus = counter->cpus; int cpu, thread; if (config->aggr_mode == AGGR_GLOBAL) { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 37efa1f43d8b..69d1d158a610 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -2273,7 +2273,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap) { int i, err = -1; - struct cpu_map *map; + struct perf_cpu_map *map; for (i = 0; i < PERF_TYPE_MAX; ++i) { struct perf_evsel *evsel; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index db8a6cf336be..62791c063f7a 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -215,7 +215,7 @@ static int check_per_pkg(struct perf_evsel *counter, struct perf_counts_values *vals, int cpu, bool *skip) { unsigned long *mask = counter->per_pkg_mask; - struct cpu_map *cpus = perf_evsel__cpus(counter); + struct perf_cpu_map *cpus = perf_evsel__cpus(counter); int s; *skip = false; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 7032dd1eeac2..fa675d09febd 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -92,7 +92,7 @@ struct runtime_stat { }; typedef int (*aggr_get_id_t)(struct perf_stat_config *config, - struct cpu_map *m, int cpu); + struct perf_cpu_map *m, int cpu); struct perf_stat_config { enum aggr_mode aggr_mode; @@ -122,9 +122,9 @@ struct perf_stat_config { const char *csv_sep; struct stats *walltime_nsecs_stats; struct rusage ru_data; - struct cpu_map *aggr_map; + struct perf_cpu_map *aggr_map; aggr_get_id_t aggr_get_id; - struct cpu_map *cpus_aggr_map; + struct perf_cpu_map *cpus_aggr_map; u64 *walltime_run; struct rblist metric_events; }; diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 76cc54000483..99132c6a30a6 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -728,7 +728,7 @@ static int str_to_bitmap(char *s, cpumask_t *b) { int i; int ret = 0; - struct cpu_map *m; + struct perf_cpu_map *m; int c; m = cpu_map__new(s); -- GitLab From 9749b90e566ca1a235fc8e2118f99c5690969342 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:50 +0200 Subject: [PATCH 1129/7155] perf tools: Rename struct thread_map to struct perf_thread_map Rename struct thread_map to struct perf_thread_map, so it could be part of libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-sched.c | 4 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-stat.c | 4 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/event-times.c | 4 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/mmap-thread-lookup.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/tests/thread-map.c | 8 +-- tools/perf/util/event.c | 6 +- tools/perf/util/event.h | 6 +- tools/perf/util/evlist.c | 10 ++-- tools/perf/util/evlist.h | 6 +- tools/perf/util/evsel.c | 10 ++-- tools/perf/util/evsel.h | 6 +- tools/perf/util/machine.c | 2 +- tools/perf/util/machine.h | 4 +- tools/perf/util/parse-events.c | 2 +- tools/perf/util/python.c | 6 +- .../scripting-engines/trace-event-python.c | 2 +- tools/perf/util/thread_map.c | 60 +++++++++---------- tools/perf/util/thread_map.h | 40 ++++++------- 29 files changed, 102 insertions(+), 102 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 4676fd967dc6..f542b878bdb5 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -49,7 +49,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe }, .sample_time = true, }; - struct thread_map *threads = NULL; + struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8779cee58185..bcfc16450608 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1047,7 +1047,7 @@ record__finish_output(struct record *rec) static int record__synthesize_workload(struct record *rec, bool tail) { int err; - struct thread_map *thread_map; + struct perf_thread_map *thread_map; if (rec->opts.tail_synthesize != tail) return 0; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 51dd48f20972..ac6a0c5d6d6b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -159,7 +159,7 @@ struct perf_sched_map { DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); int *comp_cpus; bool comp; - struct thread_map *color_pids; + struct perf_thread_map *color_pids; const char *color_pids_str; struct perf_cpu_map *color_cpus; const char *color_cpus_str; @@ -3195,7 +3195,7 @@ static int setup_map_cpus(struct perf_sched *sched) static int setup_color_pids(struct perf_sched *sched) { - struct thread_map *map; + struct perf_thread_map *map; if (!sched->map.color_pids_str) return 0; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 0109c8710b93..fccc960df92b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1628,7 +1628,7 @@ struct perf_script { bool allocated; bool per_event_dump; struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; int name_width; const char *time_str; struct perf_time_interval *ptime_range; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d68738b5bd0c..2b9518a38baf 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -165,7 +165,7 @@ struct perf_stat { struct perf_tool tool; bool maps_allocated; struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; enum aggr_mode aggr_mode; }; @@ -395,7 +395,7 @@ static bool perf_evsel__should_store_id(struct perf_evsel *counter) } static bool is_target_alive(struct target *_target, - struct thread_map *threads) + struct perf_thread_map *threads) { struct stat st; int i; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 948ec278ad06..88c218eacc43 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -552,7 +552,7 @@ static int do_test_code_reading(bool try_kcore) struct state state = { .done_cnt = 0, }; - struct thread_map *threads = NULL; + struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index ed90b62bf048..684ad56f7b0f 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -57,7 +57,7 @@ static int detach__enable_on_exec(struct perf_evlist *evlist) static int attach__current_disabled(struct perf_evlist *evlist) { struct perf_evsel *evsel = perf_evlist__last(evlist); - struct thread_map *threads; + struct perf_thread_map *threads; int err; pr_debug("attaching to current thread as disabled\n"); @@ -83,7 +83,7 @@ static int attach__current_disabled(struct perf_evlist *evlist) static int attach__current_enabled(struct perf_evlist *evlist) { struct perf_evsel *evsel = perf_evlist__last(evlist); - struct thread_map *threads; + struct perf_thread_map *threads; int err; pr_debug("attaching to current thread as enabled\n"); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 68331a81bcdd..e1e5e32cbb53 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -65,7 +65,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un .uses_mmap = true, }, }; - struct thread_map *threads = NULL; + struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 1bc8fd3ea510..c1e2fe087b67 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -27,7 +27,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse { int err = -1; union perf_event *event; - struct thread_map *threads; + struct perf_thread_map *threads; struct perf_cpu_map *cpus; struct perf_evlist *evlist; cpu_set_t cpu_set; diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 0a4301a5155c..ad6ca943e568 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -138,7 +138,7 @@ static int synth_all(struct machine *machine) static int synth_process(struct machine *machine) { - struct thread_map *map; + struct perf_thread_map *map; int err; map = thread_map__new_by_pid(getpid()); diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index f393aa836dfb..9cd5bf63bec1 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -24,7 +24,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int struct perf_evsel *evsel; unsigned int nr_openat_calls = 111, i; cpu_set_t cpu_set; - struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); + struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); char sbuf[STRERR_BUFSIZE]; char errbuf[BUFSIZ]; diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 00cd63f90b92..652b8328ca93 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -16,7 +16,7 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __m int err = -1, fd; struct perf_evsel *evsel; unsigned int nr_openat_calls = 111, i; - struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); + struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); char sbuf[STRERR_BUFSIZE]; char errbuf[BUFSIZ]; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index d9121b5033b7..d57b8d9c1575 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -38,7 +38,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) .freq = 1, }; struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; struct perf_mmap *md; attr.sample_freq = 500; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 826f20a4cb51..3652c548cc22 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -327,7 +327,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ .uses_mmap = true, }, }; - struct thread_map *threads = NULL; + struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index d66767be4c45..9602ff91a3c7 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -46,7 +46,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused const char *argv[] = { "true", NULL }; char sbuf[STRERR_BUFSIZE]; struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; struct perf_mmap *md; signal(SIGCHLD, sig_handler); diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c index ccc17aced49e..367dfe708e4c 100644 --- a/tools/perf/tests/thread-map.c +++ b/tools/perf/tests/thread-map.c @@ -13,7 +13,7 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct thread_map *map; + struct perf_thread_map *map; TEST_ASSERT_VAL("failed to set process name", !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); @@ -57,7 +57,7 @@ static int process_event(struct perf_tool *tool __maybe_unused, struct machine *machine __maybe_unused) { struct thread_map_event *map = &event->thread_map; - struct thread_map *threads; + struct perf_thread_map *threads; TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid()); @@ -80,7 +80,7 @@ static int process_event(struct perf_tool *tool __maybe_unused, int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct thread_map *threads; + struct perf_thread_map *threads; TEST_ASSERT_VAL("failed to set process name", !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); @@ -99,7 +99,7 @@ int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __ int test__thread_map_remove(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct thread_map *threads; + struct perf_thread_map *threads; char *str; int i; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 406ad8772907..f78837788b14 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -616,7 +616,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, } int perf_event__synthesize_thread_map(struct perf_tool *tool, - struct thread_map *threads, + struct perf_thread_map *threads, perf_event__handler_t process, struct machine *machine, bool mmap_data) @@ -972,7 +972,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, } int perf_event__synthesize_thread_map2(struct perf_tool *tool, - struct thread_map *threads, + struct perf_thread_map *threads, perf_event__handler_t process, struct machine *machine) { @@ -1377,7 +1377,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp) { - struct thread_map *threads = thread_map__new_event(&event->thread_map); + struct perf_thread_map *threads = thread_map__new_event(&event->thread_map); size_t ret; ret = fprintf(fp, " nr: "); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index cafaac5128ab..70841d115349 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -674,7 +674,7 @@ union perf_event { void perf_event__print_totals(void); struct perf_tool; -struct thread_map; +struct perf_thread_map; struct perf_cpu_map; struct perf_stat_config; struct perf_counts_values; @@ -685,11 +685,11 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, struct machine *machine); int perf_event__synthesize_thread_map(struct perf_tool *tool, - struct thread_map *threads, + struct perf_thread_map *threads, perf_event__handler_t process, struct machine *machine, bool mmap_data); int perf_event__synthesize_thread_map2(struct perf_tool *tool, - struct thread_map *threads, + struct perf_thread_map *threads, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_cpu_map(struct perf_tool *tool, diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index bce883eaf0dc..a95d0461f718 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -42,7 +42,7 @@ int sigqueue(pid_t pid, int sig, const union sigval value); #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, - struct thread_map *threads) + struct perf_thread_map *threads) { int i; @@ -1013,7 +1013,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, { struct perf_evsel *evsel; const struct perf_cpu_map *cpus = evlist->cpus; - const struct thread_map *threads = evlist->threads; + const struct perf_thread_map *threads = evlist->threads; /* * Delay setting mp.prot: set it before calling perf_mmap__mmap. * Its value is decided by evsel's write_backward. @@ -1059,7 +1059,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) { bool all_threads = (target->per_thread && target->system_wide); struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; /* * If specify '-a' and '--per-thread' to perf record, perf record @@ -1105,7 +1105,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) } void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, - struct thread_map *threads) + struct perf_thread_map *threads) { /* * Allow for the possibility that one or another of the maps isn't being @@ -1359,7 +1359,7 @@ void perf_evlist__close(struct perf_evlist *evlist) static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) { struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; int err = -ENOMEM; /* diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index c8cda300b584..ab2f0b6c7640 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -44,7 +44,7 @@ struct perf_evlist { struct fdarray pollfd; struct perf_mmap *mmap; struct perf_mmap *overwrite_mmap; - struct thread_map *threads; + struct perf_thread_map *threads; struct perf_cpu_map *cpus; struct perf_evsel *selected; struct events_stats stats; @@ -69,7 +69,7 @@ struct perf_evlist *perf_evlist__new(void); struct perf_evlist *perf_evlist__new_default(void); struct perf_evlist *perf_evlist__new_dummy(void); void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, - struct thread_map *threads); + struct perf_thread_map *threads); void perf_evlist__exit(struct perf_evlist *evlist); void perf_evlist__delete(struct perf_evlist *evlist); @@ -195,7 +195,7 @@ void perf_evlist__set_selected(struct perf_evlist *evlist, struct perf_evsel *evsel); void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, - struct thread_map *threads); + struct perf_thread_map *threads); int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 958206c538c3..ab66d65b7968 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1743,7 +1743,7 @@ static int update_fds(struct perf_evsel *evsel, static bool ignore_missing_thread(struct perf_evsel *evsel, int nr_cpus, int cpu, - struct thread_map *threads, + struct perf_thread_map *threads, int thread, int err) { pid_t ignore_pid = thread_map__pid(threads, thread); @@ -1826,7 +1826,7 @@ static int perf_event_open(struct perf_evsel *evsel, } int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, - struct thread_map *threads) + struct perf_thread_map *threads) { int cpu, thread, nthreads; unsigned long flags = PERF_FLAG_FD_CLOEXEC; @@ -1849,7 +1849,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, } if (threads == NULL) { - static struct thread_map *empty_thread_map; + static struct perf_thread_map *empty_thread_map; if (empty_thread_map == NULL) { empty_thread_map = thread_map__new_by_tid(-1); @@ -2090,7 +2090,7 @@ int perf_evsel__open_per_cpu(struct perf_evsel *evsel, } int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads) + struct perf_thread_map *threads) { return perf_evsel__open(evsel, NULL, threads); } @@ -3065,7 +3065,7 @@ static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) { struct perf_cpu_map *cpus = evsel->cpus; - struct thread_map *threads = evsel->threads; + struct perf_thread_map *threads = evsel->threads; if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr)) return -ENOMEM; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 76b14037f260..ba2385f22e28 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -126,7 +126,7 @@ struct perf_evsel { void *handler; struct perf_cpu_map *cpus; struct perf_cpu_map *own_cpus; - struct thread_map *threads; + struct perf_thread_map *threads; unsigned int sample_size; int id_pos; int is_pos; @@ -302,9 +302,9 @@ int perf_evsel__disable(struct perf_evsel *evsel); int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct perf_cpu_map *cpus); int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads); + struct perf_thread_map *threads); int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, - struct thread_map *threads); + struct perf_thread_map *threads); void perf_evsel__close(struct perf_evsel *evsel); struct perf_sample; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index cf826eca3aaf..a2359a33c748 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2599,7 +2599,7 @@ int machines__for_each_thread(struct machines *machines, } int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct target *target, struct thread_map *threads, + struct target *target, struct perf_thread_map *threads, perf_event__handler_t process, bool data_mmap, unsigned int nr_threads_synthesize) { diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index f70ab98a7bde..7f64016758e0 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -251,12 +251,12 @@ int machines__for_each_thread(struct machines *machines, void *priv); int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct target *target, struct thread_map *threads, + struct target *target, struct perf_thread_map *threads, perf_event__handler_t process, bool data_mmap, unsigned int nr_threads_synthesize); static inline int machine__synthesize_threads(struct machine *machine, struct target *target, - struct thread_map *threads, bool data_mmap, + struct perf_thread_map *threads, bool data_mmap, unsigned int nr_threads_synthesize) { return __machine__synthesize_threads(machine, NULL, target, threads, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 077509609d03..352c5198b453 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2313,7 +2313,7 @@ static bool is_event_supported(u8 type, unsigned config) .config = config, .disabled = 1, }; - struct thread_map *tmap = thread_map__new_by_tid(0); + struct perf_thread_map *tmap = thread_map__new_by_tid(0); if (tmap == NULL) return false; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index be27956ae080..62dda70227e5 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -605,7 +605,7 @@ static int pyrf_cpu_map__setup_types(void) struct pyrf_thread_map { PyObject_HEAD - struct thread_map *threads; + struct perf_thread_map *threads; }; static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, @@ -797,7 +797,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, { struct perf_evsel *evsel = &pevsel->evsel; struct perf_cpu_map *cpus = NULL; - struct thread_map *threads = NULL; + struct perf_thread_map *threads = NULL; PyObject *pcpus = NULL, *pthreads = NULL; int group = 0, inherit = 0; static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL }; @@ -866,7 +866,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist, { PyObject *pcpus = NULL, *pthreads = NULL; struct perf_cpu_map *cpus; - struct thread_map *threads; + struct perf_thread_map *threads; if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads)) return -1; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index a53b30b8819b..0a7e662036b4 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1392,7 +1392,7 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, static void python_process_stat(struct perf_stat_config *config, struct perf_evsel *counter, u64 tstamp) { - struct thread_map *threads = counter->threads; + struct perf_thread_map *threads = counter->threads; struct perf_cpu_map *cpus = counter->cpus; int cpu, thread; diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 5b3511f2b6b1..e89496c39d58 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -28,7 +28,7 @@ static int filter(const struct dirent *dir) return 1; } -static void thread_map__reset(struct thread_map *map, int start, int nr) +static void thread_map__reset(struct perf_thread_map *map, int start, int nr) { size_t size = (nr - start) * sizeof(map->map[0]); @@ -36,7 +36,7 @@ static void thread_map__reset(struct thread_map *map, int start, int nr) map->err_thread = -1; } -static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) +static struct perf_thread_map *thread_map__realloc(struct perf_thread_map *map, int nr) { size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; int start = map ? map->nr : 0; @@ -53,9 +53,9 @@ static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) #define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr) -struct thread_map *thread_map__new_by_pid(pid_t pid) +struct perf_thread_map *thread_map__new_by_pid(pid_t pid) { - struct thread_map *threads; + struct perf_thread_map *threads; char name[256]; int items; struct dirent **namelist = NULL; @@ -81,9 +81,9 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) return threads; } -struct thread_map *thread_map__new_by_tid(pid_t tid) +struct perf_thread_map *thread_map__new_by_tid(pid_t tid) { - struct thread_map *threads = thread_map__alloc(1); + struct perf_thread_map *threads = thread_map__alloc(1); if (threads != NULL) { thread_map__set_pid(threads, 0, tid); @@ -94,13 +94,13 @@ struct thread_map *thread_map__new_by_tid(pid_t tid) return threads; } -static struct thread_map *__thread_map__new_all_cpus(uid_t uid) +static struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid) { DIR *proc; int max_threads = 32, items, i; char path[NAME_MAX + 1 + 6]; struct dirent *dirent, **namelist = NULL; - struct thread_map *threads = thread_map__alloc(max_threads); + struct perf_thread_map *threads = thread_map__alloc(max_threads); if (threads == NULL) goto out; @@ -140,7 +140,7 @@ static struct thread_map *__thread_map__new_all_cpus(uid_t uid) } if (grow) { - struct thread_map *tmp; + struct perf_thread_map *tmp; tmp = thread_map__realloc(threads, max_threads); if (tmp == NULL) @@ -180,17 +180,17 @@ static struct thread_map *__thread_map__new_all_cpus(uid_t uid) goto out_closedir; } -struct thread_map *thread_map__new_all_cpus(void) +struct perf_thread_map *thread_map__new_all_cpus(void) { return __thread_map__new_all_cpus(UINT_MAX); } -struct thread_map *thread_map__new_by_uid(uid_t uid) +struct perf_thread_map *thread_map__new_by_uid(uid_t uid) { return __thread_map__new_all_cpus(uid); } -struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) +struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) { if (pid != -1) return thread_map__new_by_pid(pid); @@ -201,9 +201,9 @@ struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) return thread_map__new_by_tid(tid); } -static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) +static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str) { - struct thread_map *threads = NULL, *nt; + struct perf_thread_map *threads = NULL, *nt; char name[256]; int items, total_tasks = 0; struct dirent **namelist = NULL; @@ -263,9 +263,9 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) goto out; } -struct thread_map *thread_map__new_dummy(void) +struct perf_thread_map *thread_map__new_dummy(void) { - struct thread_map *threads = thread_map__alloc(1); + struct perf_thread_map *threads = thread_map__alloc(1); if (threads != NULL) { thread_map__set_pid(threads, 0, -1); @@ -275,9 +275,9 @@ struct thread_map *thread_map__new_dummy(void) return threads; } -struct thread_map *thread_map__new_by_tid_str(const char *tid_str) +struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) { - struct thread_map *threads = NULL, *nt; + struct perf_thread_map *threads = NULL, *nt; int ntasks = 0; pid_t tid, prev_tid = INT_MAX; char *end_ptr; @@ -324,7 +324,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str) goto out; } -struct thread_map *thread_map__new_str(const char *pid, const char *tid, +struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid, bool all_threads) { if (pid) @@ -339,7 +339,7 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid, return thread_map__new_by_tid_str(tid); } -static void thread_map__delete(struct thread_map *threads) +static void thread_map__delete(struct perf_thread_map *threads) { if (threads) { int i; @@ -352,20 +352,20 @@ static void thread_map__delete(struct thread_map *threads) } } -struct thread_map *thread_map__get(struct thread_map *map) +struct perf_thread_map *thread_map__get(struct perf_thread_map *map) { if (map) refcount_inc(&map->refcnt); return map; } -void thread_map__put(struct thread_map *map) +void thread_map__put(struct perf_thread_map *map) { if (map && refcount_dec_and_test(&map->refcnt)) thread_map__delete(map); } -size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) +size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp) { int i; size_t printed = fprintf(fp, "%d thread%s: ", @@ -400,7 +400,7 @@ static int get_comm(char **comm, pid_t pid) return err; } -static void comm_init(struct thread_map *map, int i) +static void comm_init(struct perf_thread_map *map, int i) { pid_t pid = thread_map__pid(map, i); char *comm = NULL; @@ -421,7 +421,7 @@ static void comm_init(struct thread_map *map, int i) map->map[i].comm = comm; } -void thread_map__read_comms(struct thread_map *threads) +void thread_map__read_comms(struct perf_thread_map *threads) { int i; @@ -429,7 +429,7 @@ void thread_map__read_comms(struct thread_map *threads) comm_init(threads, i); } -static void thread_map__copy_event(struct thread_map *threads, +static void thread_map__copy_event(struct perf_thread_map *threads, struct thread_map_event *event) { unsigned i; @@ -444,9 +444,9 @@ static void thread_map__copy_event(struct thread_map *threads, refcount_set(&threads->refcnt, 1); } -struct thread_map *thread_map__new_event(struct thread_map_event *event) +struct perf_thread_map *thread_map__new_event(struct thread_map_event *event) { - struct thread_map *threads; + struct perf_thread_map *threads; threads = thread_map__alloc(event->nr); if (threads) @@ -455,7 +455,7 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event) return threads; } -bool thread_map__has(struct thread_map *threads, pid_t pid) +bool thread_map__has(struct perf_thread_map *threads, pid_t pid) { int i; @@ -467,7 +467,7 @@ bool thread_map__has(struct thread_map *threads, pid_t pid) return false; } -int thread_map__remove(struct thread_map *threads, int idx) +int thread_map__remove(struct perf_thread_map *threads, int idx) { int i; diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 2f689c90a8c6..9358b1b6e657 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -11,7 +11,7 @@ struct thread_map_data { char *comm; }; -struct thread_map { +struct perf_thread_map { refcount_t refcnt; int nr; int err_thread; @@ -20,46 +20,46 @@ struct thread_map { struct thread_map_event; -struct thread_map *thread_map__new_dummy(void); -struct thread_map *thread_map__new_by_pid(pid_t pid); -struct thread_map *thread_map__new_by_tid(pid_t tid); -struct thread_map *thread_map__new_by_uid(uid_t uid); -struct thread_map *thread_map__new_all_cpus(void); -struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); -struct thread_map *thread_map__new_event(struct thread_map_event *event); +struct perf_thread_map *thread_map__new_dummy(void); +struct perf_thread_map *thread_map__new_by_pid(pid_t pid); +struct perf_thread_map *thread_map__new_by_tid(pid_t tid); +struct perf_thread_map *thread_map__new_by_uid(uid_t uid); +struct perf_thread_map *thread_map__new_all_cpus(void); +struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); +struct perf_thread_map *thread_map__new_event(struct thread_map_event *event); -struct thread_map *thread_map__get(struct thread_map *map); -void thread_map__put(struct thread_map *map); +struct perf_thread_map *thread_map__get(struct perf_thread_map *map); +void thread_map__put(struct perf_thread_map *map); -struct thread_map *thread_map__new_str(const char *pid, +struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid, bool all_threads); -struct thread_map *thread_map__new_by_tid_str(const char *tid_str); +struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str); -size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); +size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp); -static inline int thread_map__nr(struct thread_map *threads) +static inline int thread_map__nr(struct perf_thread_map *threads) { return threads ? threads->nr : 1; } -static inline pid_t thread_map__pid(struct thread_map *map, int thread) +static inline pid_t thread_map__pid(struct perf_thread_map *map, int thread) { return map->map[thread].pid; } static inline void -thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) +thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid) { map->map[thread].pid = pid; } -static inline char *thread_map__comm(struct thread_map *map, int thread) +static inline char *thread_map__comm(struct perf_thread_map *map, int thread) { return map->map[thread].comm; } -void thread_map__read_comms(struct thread_map *threads); -bool thread_map__has(struct thread_map *threads, pid_t pid); -int thread_map__remove(struct thread_map *threads, int idx); +void thread_map__read_comms(struct perf_thread_map *threads); +bool thread_map__has(struct perf_thread_map *threads, pid_t pid); +int thread_map__remove(struct perf_thread_map *threads, int idx); #endif /* __PERF_THREAD_MAP_H */ -- GitLab From 32dcd021d004038ca12ac17319da5aa4756e9312 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:51 +0200 Subject: [PATCH 1130/7155] perf evsel: Rename struct perf_evsel to struct evsel Rename struct perf_evsel to struct evsel, so we don't have a name clash when we add struct perf_evsel in libperf. Committer notes: Added fixes for arm64, provided by Jiri. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/auxtrace.c | 2 +- tools/perf/arch/arm/util/cs-etm.c | 20 +-- tools/perf/arch/arm64/util/arm-spe.c | 6 +- tools/perf/arch/powerpc/util/kvm-stat.c | 6 +- tools/perf/arch/s390/util/auxtrace.c | 2 +- tools/perf/arch/s390/util/kvm-stat.c | 8 +- tools/perf/arch/x86/tests/intel-cqm.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/arch/x86/util/auxtrace.c | 2 +- tools/perf/arch/x86/util/intel-bts.c | 10 +- tools/perf/arch/x86/util/intel-pt.c | 20 +-- tools/perf/arch/x86/util/kvm-stat.c | 12 +- tools/perf/builtin-annotate.c | 16 +- tools/perf/builtin-c2c.c | 4 +- tools/perf/builtin-diff.c | 12 +- tools/perf/builtin-evlist.c | 2 +- tools/perf/builtin-inject.c | 30 ++-- tools/perf/builtin-kmem.c | 24 +-- tools/perf/builtin-kvm.c | 20 +-- tools/perf/builtin-lock.c | 30 ++-- tools/perf/builtin-mem.c | 2 +- tools/perf/builtin-record.c | 4 +- tools/perf/builtin-report.c | 22 +-- tools/perf/builtin-sched.c | 74 ++++---- tools/perf/builtin-script.c | 90 +++++----- tools/perf/builtin-stat.c | 18 +- tools/perf/builtin-timechart.c | 44 ++--- tools/perf/builtin-top.c | 30 ++-- tools/perf/builtin-trace.c | 76 ++++---- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/event-times.c | 14 +- tools/perf/tests/event_update.c | 2 +- tools/perf/tests/evsel-roundtrip-name.c | 4 +- tools/perf/tests/evsel-tp-sched.c | 4 +- tools/perf/tests/hists_cumulate.c | 14 +- tools/perf/tests/hists_filter.c | 4 +- tools/perf/tests/hists_link.c | 4 +- tools/perf/tests/hists_output.c | 16 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/tests/parse-events.c | 120 ++++++------- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/sample-parsing.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 10 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/ui/browsers/annotate.c | 14 +- tools/perf/ui/browsers/hists.c | 40 ++--- tools/perf/ui/browsers/res_sample.c | 2 +- tools/perf/ui/browsers/scripts.c | 4 +- tools/perf/ui/gtk/annotate.c | 6 +- tools/perf/ui/gtk/gtk.h | 4 +- tools/perf/ui/gtk/hists.c | 2 +- tools/perf/ui/hist.c | 8 +- tools/perf/util/annotate.c | 32 ++-- tools/perf/util/annotate.h | 26 +-- tools/perf/util/auxtrace.c | 8 +- tools/perf/util/bpf-loader.c | 12 +- tools/perf/util/bpf-loader.h | 6 +- tools/perf/util/build-id.c | 2 +- tools/perf/util/build-id.h | 2 +- tools/perf/util/callchain.c | 2 +- tools/perf/util/callchain.h | 2 +- tools/perf/util/cgroup.c | 10 +- tools/perf/util/counts.c | 6 +- tools/perf/util/counts.h | 6 +- tools/perf/util/cs-etm.c | 4 +- tools/perf/util/data-convert-bt.c | 18 +- tools/perf/util/db-export.c | 6 +- tools/perf/util/db-export.h | 10 +- tools/perf/util/evlist.c | 142 +++++++-------- tools/perf/util/evlist.h | 46 ++--- tools/perf/util/evsel.c | 168 +++++++++--------- tools/perf/util/evsel.h | 146 +++++++-------- tools/perf/util/evsel_fprintf.c | 4 +- tools/perf/util/header.c | 58 +++--- tools/perf/util/header.h | 8 +- tools/perf/util/hist.c | 26 +-- tools/perf/util/hist.h | 28 +-- tools/perf/util/intel-bts.c | 2 +- tools/perf/util/intel-pt.c | 36 ++-- tools/perf/util/jitdump.c | 4 +- tools/perf/util/kvm-stat.h | 18 +- tools/perf/util/machine.c | 6 +- tools/perf/util/machine.h | 4 +- tools/perf/util/map.h | 2 +- tools/perf/util/metricgroup.c | 22 +-- tools/perf/util/metricgroup.h | 6 +- tools/perf/util/parse-events.c | 48 ++--- tools/perf/util/parse-events.h | 2 +- tools/perf/util/python.c | 14 +- tools/perf/util/record.c | 16 +- tools/perf/util/s390-cpumsf.c | 2 +- tools/perf/util/s390-sample-raw.c | 2 +- .../util/scripting-engines/trace-event-perl.c | 8 +- .../scripting-engines/trace-event-python.c | 22 +-- tools/perf/util/session.c | 30 ++-- tools/perf/util/session.h | 8 +- tools/perf/util/sort.c | 28 +-- tools/perf/util/stat-display.c | 60 +++---- tools/perf/util/stat-shadow.c | 38 ++-- tools/perf/util/stat.c | 38 ++-- tools/perf/util/stat.h | 14 +- tools/perf/util/tool.h | 4 +- tools/perf/util/top.c | 2 +- tools/perf/util/top.h | 4 +- tools/perf/util/trace-event-info.c | 4 +- tools/perf/util/trace-event-scripting.c | 2 +- tools/perf/util/trace-event.h | 4 +- 113 files changed, 1056 insertions(+), 1056 deletions(-) diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c index 02014740a1aa..fd17dccfcb0b 100644 --- a/tools/perf/arch/arm/util/auxtrace.c +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -53,7 +53,7 @@ struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, int *err) { struct perf_pmu *cs_etm_pmu; - struct perf_evsel *evsel; + struct evsel *evsel; bool found_etm = false; bool found_spe = false; static struct perf_pmu **arm_spe_pmus = NULL; diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index d08b55c27774..476f845be5fe 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -55,7 +55,7 @@ static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = { static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu); static int cs_etm_set_context_id(struct auxtrace_record *itr, - struct perf_evsel *evsel, int cpu) + struct evsel *evsel, int cpu) { struct cs_etm_recording *ptr; struct perf_pmu *cs_etm_pmu; @@ -104,7 +104,7 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr, } static int cs_etm_set_timestamp(struct auxtrace_record *itr, - struct perf_evsel *evsel, int cpu) + struct evsel *evsel, int cpu) { struct cs_etm_recording *ptr; struct perf_pmu *cs_etm_pmu; @@ -152,7 +152,7 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr, } static int cs_etm_set_option(struct auxtrace_record *itr, - struct perf_evsel *evsel, u32 option) + struct evsel *evsel, u32 option) { int i, err = -EINVAL; struct perf_cpu_map *event_cpus = evsel->evlist->cpus; @@ -208,7 +208,7 @@ static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr, } static int cs_etm_set_sink_attr(struct perf_pmu *pmu, - struct perf_evsel *evsel) + struct evsel *evsel) { char msg[BUFSIZ], path[PATH_MAX], *sink; struct perf_evsel_config_term *term; @@ -252,7 +252,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; - struct perf_evsel *evsel, *cs_etm_evsel = NULL; + struct evsel *evsel, *cs_etm_evsel = NULL; struct perf_cpu_map *cpus = evlist->cpus; bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0); int err = 0; @@ -407,7 +407,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { - struct perf_evsel *tracking_evsel; + struct evsel *tracking_evsel; err = parse_events(evlist, "dummy:u", NULL); if (err) @@ -435,7 +435,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr) container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; struct perf_evlist *evlist = ptr->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type == cs_etm_pmu->type) { @@ -817,7 +817,7 @@ static int cs_etm_snapshot_start(struct auxtrace_record *itr) { struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->cs_etm_pmu->type) @@ -830,7 +830,7 @@ static int cs_etm_snapshot_finish(struct auxtrace_record *itr) { struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->cs_etm_pmu->type) @@ -858,7 +858,7 @@ static int cs_etm_read_finish(struct auxtrace_record *itr, int idx) { struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->cs_etm_pmu->type) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 2c009aa74633..103bf20ae32a 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -65,9 +65,9 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, struct arm_spe_recording *sper = container_of(itr, struct arm_spe_recording, itr); struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; - struct perf_evsel *evsel, *arm_spe_evsel = NULL; + struct evsel *evsel, *arm_spe_evsel = NULL; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; - struct perf_evsel *tracking_evsel; + struct evsel *tracking_evsel; int err; sper->evlist = evlist; @@ -160,7 +160,7 @@ static int arm_spe_read_finish(struct auxtrace_record *itr, int idx) { struct arm_spe_recording *sper = container_of(itr, struct arm_spe_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(sper->evlist, evsel) { if (evsel->attr.type == sper->arm_spe_pmu->type) diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c index f9db341c47b6..557c474f0a4b 100644 --- a/tools/perf/arch/powerpc/util/kvm-stat.c +++ b/tools/perf/arch/powerpc/util/kvm-stat.c @@ -32,7 +32,7 @@ const char *ppc_book3s_hv_kvm_tp[] = { const char *kvm_events_tp[NR_TPS + 1]; const char *kvm_exit_reason; -static void hcall_event_get_key(struct perf_evsel *evsel, +static void hcall_event_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -55,14 +55,14 @@ static const char *get_hcall_exit_reason(u64 exit_code) return "UNKNOWN"; } -static bool hcall_event_end(struct perf_evsel *evsel, +static bool hcall_event_end(struct evsel *evsel, struct perf_sample *sample __maybe_unused, struct event_key *key __maybe_unused) { return (!strcmp(evsel->name, kvm_events_tp[3])); } -static bool hcall_event_begin(struct perf_evsel *evsel, +static bool hcall_event_begin(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { if (!strcmp(evsel->name, kvm_events_tp[2])) { diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c index 0fe1be93f375..aec819b945c5 100644 --- a/tools/perf/arch/s390/util/auxtrace.c +++ b/tools/perf/arch/s390/util/auxtrace.c @@ -86,7 +86,7 @@ struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, int *err) { struct auxtrace_record *aux; - struct perf_evsel *pos; + struct evsel *pos; int diagnose = 0; *err = 0; diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c index f852f2a77e0a..dac78441338c 100644 --- a/tools/perf/arch/s390/util/kvm-stat.c +++ b/tools/perf/arch/s390/util/kvm-stat.c @@ -23,7 +23,7 @@ const char *kvm_exit_reason = "icptcode"; const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter"; const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit"; -static void event_icpt_insn_get_key(struct perf_evsel *evsel, +static void event_icpt_insn_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -34,7 +34,7 @@ static void event_icpt_insn_get_key(struct perf_evsel *evsel, key->exit_reasons = sie_icpt_insn_codes; } -static void event_sigp_get_key(struct perf_evsel *evsel, +static void event_sigp_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -42,7 +42,7 @@ static void event_sigp_get_key(struct perf_evsel *evsel, key->exit_reasons = sie_sigp_order_codes; } -static void event_diag_get_key(struct perf_evsel *evsel, +static void event_diag_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -50,7 +50,7 @@ static void event_diag_get_key(struct perf_evsel *evsel, key->exit_reasons = sie_diagnose_codes; } -static void event_icpt_prog_get_key(struct perf_evsel *evsel, +static void event_icpt_prog_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c index 94aa0b673b7f..b88ed71b2e3f 100644 --- a/tools/perf/arch/x86/tests/intel-cqm.c +++ b/tools/perf/arch/x86/tests/intel-cqm.c @@ -41,7 +41,7 @@ static pid_t spawn(void) int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused) { struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel = NULL; + struct evsel *evsel = NULL; struct perf_event_attr pe; int i, fd[2], flag, ret; size_t mmap_len; diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index f542b878bdb5..43fc7d426d93 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -52,7 +52,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel = NULL; + struct evsel *evsel = NULL; int err = -1, ret, i; const char *comm1, *comm2; struct perf_tsc_conversion tc; diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c index d711268af330..02f192114448 100644 --- a/tools/perf/arch/x86/util/auxtrace.c +++ b/tools/perf/arch/x86/util/auxtrace.c @@ -21,7 +21,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist, { struct perf_pmu *intel_pt_pmu; struct perf_pmu *intel_bts_pmu; - struct perf_evsel *evsel; + struct evsel *evsel; bool found_pt = false; bool found_bts = false; diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index da1583d27efd..59685a19c3b9 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -105,7 +105,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, struct intel_bts_recording *btsr = container_of(itr, struct intel_bts_recording, itr); struct perf_pmu *intel_bts_pmu = btsr->intel_bts_pmu; - struct perf_evsel *evsel, *intel_bts_evsel = NULL; + struct evsel *evsel, *intel_bts_evsel = NULL; const struct perf_cpu_map *cpus = evlist->cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; @@ -220,7 +220,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { - struct perf_evsel *tracking_evsel; + struct evsel *tracking_evsel; int err; err = parse_events(evlist, "dummy:u", NULL); @@ -313,7 +313,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr) { struct intel_bts_recording *btsr = container_of(itr, struct intel_bts_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { if (evsel->attr.type == btsr->intel_bts_pmu->type) @@ -326,7 +326,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr) { struct intel_bts_recording *btsr = container_of(itr, struct intel_bts_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { if (evsel->attr.type == btsr->intel_bts_pmu->type) @@ -408,7 +408,7 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx) { struct intel_bts_recording *btsr = container_of(itr, struct intel_bts_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { if (evsel->attr.type == btsr->intel_bts_pmu->type) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 69a23e40abc9..b42df73fd7ff 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -112,7 +112,7 @@ static u64 intel_pt_masked_bits(u64 mask, u64 bits) static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, struct perf_evlist *evlist, u64 *res) { - struct perf_evsel *evsel; + struct evsel *evsel; u64 mask; *res = 0; @@ -271,7 +271,7 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu) static const char *intel_pt_find_filter(struct perf_evlist *evlist, struct perf_pmu *intel_pt_pmu) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type == intel_pt_pmu->type) @@ -401,7 +401,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, static int intel_pt_track_switches(struct perf_evlist *evlist) { const char *sched_switch = "sched:sched_switch"; - struct perf_evsel *evsel; + struct evsel *evsel; int err; if (!perf_evlist__can_select_event(evlist, sched_switch)) @@ -513,7 +513,7 @@ static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu, } static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, - struct perf_evsel *evsel) + struct evsel *evsel) { int err; char c; @@ -556,7 +556,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, container_of(itr, struct intel_pt_recording, itr); struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; bool have_timing_info, need_immediate = false; - struct perf_evsel *evsel, *intel_pt_evsel = NULL; + struct evsel *evsel, *intel_pt_evsel = NULL; const struct perf_cpu_map *cpus = evlist->cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; u64 tsc_bit; @@ -685,7 +685,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, !target__has_task(&opts->target); if (!cpu_wide && perf_can_record_cpu_wide()) { - struct perf_evsel *switch_evsel; + struct evsel *switch_evsel; err = parse_events(evlist, "dummy:u", NULL); if (err) @@ -743,7 +743,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { - struct perf_evsel *tracking_evsel; + struct evsel *tracking_evsel; err = parse_events(evlist, "dummy:u", NULL); if (err) @@ -784,7 +784,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr) { struct intel_pt_recording *ptr = container_of(itr, struct intel_pt_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->intel_pt_pmu->type) @@ -797,7 +797,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr) { struct intel_pt_recording *ptr = container_of(itr, struct intel_pt_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->intel_pt_pmu->type) @@ -1070,7 +1070,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx) { struct intel_pt_recording *ptr = container_of(itr, struct intel_pt_recording, itr); - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->intel_pt_pmu->type) diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c index 865a9762f22e..54a3f2373c35 100644 --- a/tools/perf/arch/x86/util/kvm-stat.c +++ b/tools/perf/arch/x86/util/kvm-stat.c @@ -27,7 +27,7 @@ const char *kvm_exit_trace = "kvm:kvm_exit"; * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). */ -static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, +static void mmio_event_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { key->key = perf_evsel__intval(evsel, sample, "gpa"); @@ -38,7 +38,7 @@ static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sam #define KVM_TRACE_MMIO_READ 1 #define KVM_TRACE_MMIO_WRITE 2 -static bool mmio_event_begin(struct perf_evsel *evsel, +static bool mmio_event_begin(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { /* MMIO read begin event in kernel. */ @@ -55,7 +55,7 @@ static bool mmio_event_begin(struct perf_evsel *evsel, return false; } -static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample, +static bool mmio_event_end(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { /* MMIO write end event in kernel. */ @@ -89,7 +89,7 @@ static struct kvm_events_ops mmio_events = { }; /* The time of emulation pio access is from kvm_pio to kvm_entry. */ -static void ioport_event_get_key(struct perf_evsel *evsel, +static void ioport_event_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -97,7 +97,7 @@ static void ioport_event_get_key(struct perf_evsel *evsel, key->info = perf_evsel__intval(evsel, sample, "rw"); } -static bool ioport_event_begin(struct perf_evsel *evsel, +static bool ioport_event_begin(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -109,7 +109,7 @@ static bool ioport_event_begin(struct perf_evsel *evsel, return false; } -static bool ioport_event_end(struct perf_evsel *evsel, +static bool ioport_event_end(struct evsel *evsel, struct perf_sample *sample __maybe_unused, struct event_key *key __maybe_unused) { diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e0aa14faf2b5..9bb637165bf9 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -156,7 +156,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, struct hist_entry *he = iter->he; struct branch_info *bi; struct perf_sample *sample = iter->sample; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; int err; bi = he->branch_info; @@ -171,7 +171,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, return err; } -static int process_branch_callback(struct perf_evsel *evsel, +static int process_branch_callback(struct evsel *evsel, struct perf_sample *sample, struct addr_location *al __maybe_unused, struct perf_annotate *ann, @@ -208,7 +208,7 @@ static bool has_annotation(struct perf_annotate *ann) return ui__has_annotation() || ann->use_stdio2; } -static int perf_evsel__add_sample(struct perf_evsel *evsel, +static int perf_evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, struct addr_location *al, struct perf_annotate *ann, @@ -257,7 +257,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); @@ -293,7 +293,7 @@ static int process_feature_event(struct perf_session *session, } static int hist_entry__tty_annotate(struct hist_entry *he, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_annotate *ann) { if (!ann->use_stdio2) @@ -303,7 +303,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he, } static void hists__find_annotations(struct hists *hists, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_annotate *ann) { struct rb_node *nd = rb_first_cached(&hists->entries), *next; @@ -333,7 +333,7 @@ static void hists__find_annotations(struct hists *hists, if (use_browser == 2) { int ret; int (*annotate)(struct hist_entry *he, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt); annotate = dlsym(perf_gtk_handle, @@ -387,7 +387,7 @@ static int __cmd_annotate(struct perf_annotate *ann) { int ret; struct perf_session *session = ann->session; - struct perf_evsel *pos; + struct evsel *pos; u64 total_nr_samples; if (ann->cpu_list) { diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 52035dacf253..d251a486f329 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -248,7 +248,7 @@ static void compute_stats(struct c2c_hist_entry *c2c_he, static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct c2c_hists *c2c_hists = &c2c.hists; @@ -2237,7 +2237,7 @@ static void print_pareto(FILE *out) static void print_c2c_info(FILE *out, struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; bool first = true; fprintf(out, "=================================================\n"); diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f6f5dd15bea7..c3b4b8196e00 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -376,7 +376,7 @@ struct hist_entry_ops block_hist_ops = { static int diff__process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool); @@ -448,10 +448,10 @@ static struct perf_diff pdiff = { }, }; -static struct perf_evsel *evsel_match(struct perf_evsel *evsel, +static struct evsel *evsel_match(struct evsel *evsel, struct perf_evlist *evlist) { - struct perf_evsel *e; + struct evsel *e; evlist__for_each_entry(evlist, e) { if (perf_evsel__match2(evsel, e)) @@ -463,7 +463,7 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, static void perf_evlist__collapse_resort(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { struct hists *hists = evsel__hists(evsel); @@ -1010,7 +1010,7 @@ static void data__fprintf(void) static void data_process(void) { struct perf_evlist *evlist_base = data__files[0].session->evlist; - struct perf_evsel *evsel_base; + struct evsel *evsel_base; bool first = true; evlist__for_each_entry(evlist_base, evsel_base) { @@ -1020,7 +1020,7 @@ static void data_process(void) data__for_each_file_new(i, d) { struct perf_evlist *evlist = d->session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; struct hists *hists; evsel = evsel_match(evsel_base, evlist); diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 6e4f63b0da4a..e4cb61dc6315 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c @@ -21,7 +21,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) { struct perf_session *session; - struct perf_evsel *pos; + struct evsel *pos; struct perf_data data = { .path = file_name, .mode = PERF_DATA_MODE_READ, diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f4591a1438b4..646a1bf790fc 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -215,13 +215,13 @@ static int perf_event__drop_aux(struct perf_tool *tool, typedef int (*inject_handler)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine); static int perf_event__repipe_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { if (evsel && evsel->handler) { @@ -424,7 +424,7 @@ static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, static int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine) { struct addr_location al; @@ -465,7 +465,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, static int perf_inject__sched_process_exit(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); @@ -485,7 +485,7 @@ static int perf_inject__sched_process_exit(struct perf_tool *tool, static int perf_inject__sched_switch(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); @@ -509,7 +509,7 @@ static int perf_inject__sched_switch(struct perf_tool *tool, static int perf_inject__sched_stat(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct event_entry *ent; @@ -541,7 +541,7 @@ static void sig_handler(int sig __maybe_unused) session_done = 1; } -static int perf_evsel__check_stype(struct perf_evsel *evsel, +static int perf_evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg) { struct perf_event_attr *attr = &evsel->attr; @@ -559,7 +559,7 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel, static int drop_sample(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { return 0; @@ -568,7 +568,7 @@ static int drop_sample(struct perf_tool *tool __maybe_unused, static void strip_init(struct perf_inject *inject) { struct perf_evlist *evlist = inject->session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; inject->tool.context_switch = perf_event__drop; @@ -576,7 +576,7 @@ static void strip_init(struct perf_inject *inject) evsel->handler = drop_sample; } -static bool has_tracking(struct perf_evsel *evsel) +static bool has_tracking(struct evsel *evsel) { return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm || evsel->attr.task; @@ -591,9 +591,9 @@ static bool has_tracking(struct perf_evsel *evsel) * and it has a compatible sample type. */ static bool ok_to_remove(struct perf_evlist *evlist, - struct perf_evsel *evsel_to_remove) + struct evsel *evsel_to_remove) { - struct perf_evsel *evsel; + struct evsel *evsel; int cnt = 0; bool ok = false; @@ -615,7 +615,7 @@ static bool ok_to_remove(struct perf_evlist *evlist, static void strip_fini(struct perf_inject *inject) { struct perf_evlist *evlist = inject->session->evlist; - struct perf_evsel *evsel, *tmp; + struct evsel *evsel, *tmp; /* Remove non-synthesized evsels if possible */ evlist__for_each_entry_safe(evlist, tmp, evsel) { @@ -651,7 +651,7 @@ static int __cmd_inject(struct perf_inject *inject) if (inject->build_ids) { inject->tool.sample = perf_event__inject_buildid; } else if (inject->sched_stat) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(session->evlist, evsel) { const char *name = perf_evsel__name(evsel); @@ -712,7 +712,7 @@ static int __cmd_inject(struct perf_inject *inject) * remove the evsel. */ if (inject->itrace_synth_opts.set) { - struct perf_evsel *evsel; + struct evsel *evsel; perf_header__clear_feat(&session->header, HEADER_AUXTRACE); diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 9e5e60898083..46f828936120 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -166,7 +166,7 @@ static int insert_caller_stat(unsigned long call_site, return 0; } -static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, +static int perf_evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *sample) { unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"), @@ -185,7 +185,7 @@ static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, return 0; } -static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel, +static int perf_evsel__process_alloc_node_event(struct evsel *evsel, struct perf_sample *sample) { int ret = perf_evsel__process_alloc_event(evsel, sample); @@ -229,7 +229,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static int perf_evsel__process_free_event(struct perf_evsel *evsel, +static int perf_evsel__process_free_event(struct evsel *evsel, struct perf_sample *sample) { unsigned long ptr = perf_evsel__intval(evsel, sample, "ptr"); @@ -381,7 +381,7 @@ static int build_alloc_func_list(void) * Find first non-memory allocation function from callchain. * The allocation functions are in the 'alloc_func_list'. */ -static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample) +static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample) { struct addr_location al; struct machine *machine = &kmem_session->machines.host; @@ -728,7 +728,7 @@ static char *compact_gfp_string(unsigned long gfp_flags) return NULL; } -static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample, +static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample, unsigned int gfp_flags) { struct tep_record record = { @@ -779,7 +779,7 @@ static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample, return 0; } -static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel, +static int perf_evsel__process_page_alloc_event(struct evsel *evsel, struct perf_sample *sample) { u64 page; @@ -852,7 +852,7 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel, return 0; } -static int perf_evsel__process_page_free_event(struct perf_evsel *evsel, +static int perf_evsel__process_page_free_event(struct evsel *evsel, struct perf_sample *sample) { u64 page; @@ -930,13 +930,13 @@ static bool perf_kmem__skip_sample(struct perf_sample *sample) return false; } -typedef int (*tracepoint_handler)(struct perf_evsel *evsel, +typedef int (*tracepoint_handler)(struct evsel *evsel, struct perf_sample *sample); static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { int err = 0; @@ -1363,8 +1363,8 @@ static void sort_result(void) static int __cmd_kmem(struct perf_session *session) { int err = -EINVAL; - struct perf_evsel *evsel; - const struct perf_evsel_str_handler kmem_tracepoints[] = { + struct evsel *evsel; + const struct evsel_str_handler kmem_tracepoints[] = { /* slab allocator */ { "kmem:kmalloc", perf_evsel__process_alloc_event, }, { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, @@ -1967,7 +1967,7 @@ int cmd_kmem(int argc, const char **argv) } if (kmem_page) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = perf_evlist__find_tracepoint_by_name(session->evlist, "kmem:mm_page_alloc"); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index b33c83489120..cf8f27d05296 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -57,7 +57,7 @@ static const char *get_filename_for_perf_kvm(void) #ifdef HAVE_KVM_STAT_SUPPORT #include "util/kvm-stat.h" -void exit_event_get_key(struct perf_evsel *evsel, +void exit_event_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -65,12 +65,12 @@ void exit_event_get_key(struct perf_evsel *evsel, key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason); } -bool kvm_exit_event(struct perf_evsel *evsel) +bool kvm_exit_event(struct evsel *evsel) { return !strcmp(evsel->name, kvm_exit_trace); } -bool exit_event_begin(struct perf_evsel *evsel, +bool exit_event_begin(struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { if (kvm_exit_event(evsel)) { @@ -81,12 +81,12 @@ bool exit_event_begin(struct perf_evsel *evsel, return false; } -bool kvm_entry_event(struct perf_evsel *evsel) +bool kvm_entry_event(struct evsel *evsel) { return !strcmp(evsel->name, kvm_entry_trace); } -bool exit_event_end(struct perf_evsel *evsel, +bool exit_event_end(struct evsel *evsel, struct perf_sample *sample __maybe_unused, struct event_key *key __maybe_unused) { @@ -286,7 +286,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id, } static bool is_child_event(struct perf_kvm_stat *kvm, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -396,7 +396,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, static struct vcpu_event_record *per_vcpu_record(struct thread *thread, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { /* Only kvm_entry records vcpu id. */ @@ -419,7 +419,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, static bool handle_kvm_event(struct perf_kvm_stat *kvm, struct thread *thread, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { struct vcpu_event_record *vcpu_record; @@ -672,7 +672,7 @@ static bool skip_sample(struct perf_kvm_stat *kvm, static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { int err = 0; @@ -1011,7 +1011,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) static int kvm_live_open_events(struct perf_kvm_stat *kvm) { int err, rc = -1; - struct perf_evsel *pos; + struct evsel *pos; struct perf_evlist *evlist = kvm->evlist; char sbuf[STRERR_BUFSIZE]; diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 574e30ec6d7c..38500bff4423 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -347,16 +347,16 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) } struct trace_lock_handler { - int (*acquire_event)(struct perf_evsel *evsel, + int (*acquire_event)(struct evsel *evsel, struct perf_sample *sample); - int (*acquired_event)(struct perf_evsel *evsel, + int (*acquired_event)(struct evsel *evsel, struct perf_sample *sample); - int (*contended_event)(struct perf_evsel *evsel, + int (*contended_event)(struct evsel *evsel, struct perf_sample *sample); - int (*release_event)(struct perf_evsel *evsel, + int (*release_event)(struct evsel *evsel, struct perf_sample *sample); }; @@ -396,7 +396,7 @@ enum acquire_flags { READ_LOCK = 2, }; -static int report_lock_acquire_event(struct perf_evsel *evsel, +static int report_lock_acquire_event(struct evsel *evsel, struct perf_sample *sample) { void *addr; @@ -468,7 +468,7 @@ static int report_lock_acquire_event(struct perf_evsel *evsel, return 0; } -static int report_lock_acquired_event(struct perf_evsel *evsel, +static int report_lock_acquired_event(struct evsel *evsel, struct perf_sample *sample) { void *addr; @@ -531,7 +531,7 @@ static int report_lock_acquired_event(struct perf_evsel *evsel, return 0; } -static int report_lock_contended_event(struct perf_evsel *evsel, +static int report_lock_contended_event(struct evsel *evsel, struct perf_sample *sample) { void *addr; @@ -586,7 +586,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel, return 0; } -static int report_lock_release_event(struct perf_evsel *evsel, +static int report_lock_release_event(struct evsel *evsel, struct perf_sample *sample) { void *addr; @@ -656,7 +656,7 @@ static struct trace_lock_handler report_lock_ops = { static struct trace_lock_handler *trace_handler; -static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel, +static int perf_evsel__process_lock_acquire(struct evsel *evsel, struct perf_sample *sample) { if (trace_handler->acquire_event) @@ -664,7 +664,7 @@ static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel, return 0; } -static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel, +static int perf_evsel__process_lock_acquired(struct evsel *evsel, struct perf_sample *sample) { if (trace_handler->acquired_event) @@ -672,7 +672,7 @@ static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel, return 0; } -static int perf_evsel__process_lock_contended(struct perf_evsel *evsel, +static int perf_evsel__process_lock_contended(struct evsel *evsel, struct perf_sample *sample) { if (trace_handler->contended_event) @@ -680,7 +680,7 @@ static int perf_evsel__process_lock_contended(struct perf_evsel *evsel, return 0; } -static int perf_evsel__process_lock_release(struct perf_evsel *evsel, +static int perf_evsel__process_lock_release(struct evsel *evsel, struct perf_sample *sample) { if (trace_handler->release_event) @@ -806,13 +806,13 @@ static int dump_info(void) return rc; } -typedef int (*tracepoint_handler)(struct perf_evsel *evsel, +typedef int (*tracepoint_handler)(struct evsel *evsel, struct perf_sample *sample); static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { int err = 0; @@ -847,7 +847,7 @@ static void sort_result(void) } } -static const struct perf_evsel_str_handler lock_tracepoints[] = { +static const struct evsel_str_handler lock_tracepoints[] = { { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ { "lock:lock_contended", perf_evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index f45c8b502f63..9e60eda9297d 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -230,7 +230,7 @@ dump_raw_samples(struct perf_tool *tool, static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine) { return dump_raw_samples(tool, event, sample, machine); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index bcfc16450608..7ba3a2c32e54 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -713,7 +713,7 @@ static int record__mmap(struct record *rec) static int record__open(struct record *rec) { char msg[BUFSIZ]; - struct perf_evsel *pos; + struct evsel *pos; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; struct record_opts *opts = &rec->opts; @@ -782,7 +782,7 @@ static int record__open(struct record *rec) static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct record *rec = container_of(tool, struct record, tool); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index abf0b9b8f566..96a506f0d4c1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -128,7 +128,7 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, int err = 0; struct report *rep = arg; struct hist_entry *he = iter->he; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; struct mem_info *mi; struct branch_info *bi; @@ -172,7 +172,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, struct report *rep = arg; struct branch_info *bi; struct perf_sample *sample = iter->sample; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; int err; if (!ui__has_annotation() && !rep->symbol_ipc) @@ -225,7 +225,7 @@ static int process_feature_event(struct perf_session *session, static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct report *rep = container_of(tool, struct report, tool); @@ -292,7 +292,7 @@ static int process_sample_event(struct perf_tool *tool, static int process_read_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine __maybe_unused) { struct report *rep = container_of(tool, struct report, tool); @@ -400,7 +400,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report char unit; unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists->stats.total_period; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); char buf[512]; size_t size = sizeof(buf); int socked_id = hists->socket_filter; @@ -414,7 +414,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report } if (perf_evsel__is_group_event(evsel)) { - struct perf_evsel *pos; + struct evsel *pos; perf_evsel__group_desc(evsel, buf, size); evname = buf; @@ -463,7 +463,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct report *rep, const char *help) { - struct perf_evsel *pos; + struct evsel *pos; if (!quiet) { fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", @@ -586,7 +586,7 @@ static int report__browse_hists(struct report *rep) static int report__collapse_hists(struct report *rep) { struct ui_progress prog; - struct perf_evsel *pos; + struct evsel *pos; int ret = 0; ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); @@ -623,7 +623,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg) struct symbol *sym = he->ms.sym; if (rep->symbol_ipc && sym && !sym->annotate2) { - struct perf_evsel *evsel = hists_to_evsel(he->hists); + struct evsel *evsel = hists_to_evsel(he->hists); symbol__annotate2(sym, he->ms.map, evsel, &annotation__default_options, NULL); @@ -635,7 +635,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg) static void report__output_resort(struct report *rep) { struct ui_progress prog; - struct perf_evsel *pos; + struct evsel *pos; ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); @@ -818,7 +818,7 @@ static int __cmd_report(struct report *rep) { int ret; struct perf_session *session = rep->session; - struct perf_evsel *pos; + struct evsel *pos; struct perf_data *data = session->data; signal(SIGINT, sig_handler); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index ac6a0c5d6d6b..55779f496d27 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -133,13 +133,13 @@ typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); struct perf_sched; struct trace_sched_handler { - int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel, + int (*switch_event)(struct perf_sched *sched, struct evsel *evsel, struct perf_sample *sample, struct machine *machine); - int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel, + int (*runtime_event)(struct perf_sched *sched, struct evsel *evsel, struct perf_sample *sample, struct machine *machine); - int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, + int (*wakeup_event)(struct perf_sched *sched, struct evsel *evsel, struct perf_sample *sample, struct machine *machine); /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */ @@ -147,7 +147,7 @@ struct trace_sched_handler { struct machine *machine); int (*migrate_task_event)(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine); }; @@ -799,7 +799,7 @@ static void test_calibrations(struct perf_sched *sched) static int replay_wakeup_event(struct perf_sched *sched, - struct perf_evsel *evsel, struct perf_sample *sample, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { const char *comm = perf_evsel__strval(evsel, sample, "comm"); @@ -820,7 +820,7 @@ replay_wakeup_event(struct perf_sched *sched, } static int replay_switch_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1093,7 +1093,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp) } static int latency_switch_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1163,7 +1163,7 @@ static int latency_switch_event(struct perf_sched *sched, } static int latency_runtime_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1198,7 +1198,7 @@ static int latency_runtime_event(struct perf_sched *sched, } static int latency_wakeup_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1259,7 +1259,7 @@ static int latency_wakeup_event(struct perf_sched *sched, } static int latency_migrate_task_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1470,7 +1470,7 @@ static void perf_sched__sort_lat(struct perf_sched *sched) } static int process_sched_wakeup_event(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1514,7 +1514,7 @@ map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid return thread; } -static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, +static int map_switch_event(struct perf_sched *sched, struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); @@ -1655,7 +1655,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, } static int process_sched_switch_event(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1681,7 +1681,7 @@ static int process_sched_switch_event(struct perf_tool *tool, } static int process_sched_runtime_event(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1711,7 +1711,7 @@ static int perf_sched__process_fork_event(struct perf_tool *tool, } static int process_sched_migrate_task_event(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1724,14 +1724,14 @@ static int process_sched_migrate_task_event(struct perf_tool *tool, } typedef int (*tracepoint_handler)(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine); static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { int err = 0; @@ -1777,7 +1777,7 @@ static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused, static int perf_sched__read_events(struct perf_sched *sched) { - const struct perf_evsel_str_handler handlers[] = { + const struct evsel_str_handler handlers[] = { { "sched:sched_switch", process_sched_switch_event, }, { "sched:sched_stat_runtime", process_sched_runtime_event, }, { "sched:sched_wakeup", process_sched_wakeup_event, }, @@ -1839,7 +1839,7 @@ static inline void print_sched_time(unsigned long long nsecs, int width) * returns runtime data for event, allocating memory for it the * first time it is used. */ -static struct evsel_runtime *perf_evsel__get_runtime(struct perf_evsel *evsel) +static struct evsel_runtime *perf_evsel__get_runtime(struct evsel *evsel) { struct evsel_runtime *r = evsel->priv; @@ -1854,7 +1854,7 @@ static struct evsel_runtime *perf_evsel__get_runtime(struct perf_evsel *evsel) /* * save last time event was seen per cpu */ -static void perf_evsel__save_time(struct perf_evsel *evsel, +static void perf_evsel__save_time(struct evsel *evsel, u64 timestamp, u32 cpu) { struct evsel_runtime *r = perf_evsel__get_runtime(evsel); @@ -1881,7 +1881,7 @@ static void perf_evsel__save_time(struct perf_evsel *evsel, } /* returns last time this event was seen on the given cpu */ -static u64 perf_evsel__get_time(struct perf_evsel *evsel, u32 cpu) +static u64 perf_evsel__get_time(struct evsel *evsel, u32 cpu) { struct evsel_runtime *r = perf_evsel__get_runtime(evsel); @@ -1988,7 +1988,7 @@ static char task_state_char(struct thread *thread, int state) } static void timehist_print_sample(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct addr_location *al, struct thread *thread, @@ -2121,7 +2121,7 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, } static bool is_idle_sample(struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { /* pid 0 == swapper == idle task */ if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0) @@ -2132,7 +2132,7 @@ static bool is_idle_sample(struct perf_sample *sample, static void save_task_callchain(struct perf_sched *sched, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct callchain_cursor *cursor = &callchain_cursor; @@ -2286,7 +2286,7 @@ static void save_idle_callchain(struct perf_sched *sched, static struct thread *timehist_get_thread(struct perf_sched *sched, struct perf_sample *sample, struct machine *machine, - struct perf_evsel *evsel) + struct evsel *evsel) { struct thread *thread; @@ -2332,7 +2332,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, static bool timehist_skip_sample(struct perf_sched *sched, struct thread *thread, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { bool rc = false; @@ -2354,7 +2354,7 @@ static bool timehist_skip_sample(struct perf_sched *sched, } static void timehist_print_wakeup_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *awakened) @@ -2389,7 +2389,7 @@ static void timehist_print_wakeup_event(struct perf_sched *sched, static int timehist_sched_wakeup_event(struct perf_tool *tool, union perf_event *event __maybe_unused, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2419,7 +2419,7 @@ static int timehist_sched_wakeup_event(struct perf_tool *tool, } static void timehist_print_migration_event(struct perf_sched *sched, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *migrated) @@ -2473,7 +2473,7 @@ static void timehist_print_migration_event(struct perf_sched *sched, static int timehist_migrate_task_event(struct perf_tool *tool, union perf_event *event __maybe_unused, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2501,7 +2501,7 @@ static int timehist_migrate_task_event(struct perf_tool *tool, static int timehist_sched_change_event(struct perf_tool *tool, union perf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2627,7 +2627,7 @@ static int timehist_sched_change_event(struct perf_tool *tool, static int timehist_sched_switch_event(struct perf_tool *tool, union perf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -2897,14 +2897,14 @@ static void timehist_print_summary(struct perf_sched *sched, typedef int (*sched_handler)(struct perf_tool *tool, union perf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine); static int perf_timehist__process_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); @@ -2926,7 +2926,7 @@ static int perf_timehist__process_sample(struct perf_tool *tool, static int timehist_check_attr(struct perf_sched *sched, struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; struct evsel_runtime *er; list_for_each_entry(evsel, &evlist->entries, node) { @@ -2948,12 +2948,12 @@ static int timehist_check_attr(struct perf_sched *sched, static int perf_sched__timehist(struct perf_sched *sched) { - const struct perf_evsel_str_handler handlers[] = { + const struct evsel_str_handler handlers[] = { { "sched:sched_switch", timehist_sched_switch_event, }, { "sched:sched_wakeup", timehist_sched_wakeup_event, }, { "sched:sched_wakeup_new", timehist_sched_wakeup_event, }, }; - const struct perf_evsel_str_handler migrate_handlers[] = { + const struct evsel_str_handler migrate_handlers[] = { { "sched:sched_migrate_task", timehist_migrate_task_event, }, }; struct perf_data data = { diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index fccc960df92b..4f9c8bb7620d 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -242,7 +242,7 @@ static struct { }, }; -struct perf_evsel_script { +struct evsel_script { char *filename; FILE *fp; u64 samples; @@ -251,15 +251,15 @@ struct perf_evsel_script { int gnum; }; -static inline struct perf_evsel_script *evsel_script(struct perf_evsel *evsel) +static inline struct evsel_script *evsel_script(struct evsel *evsel) { - return (struct perf_evsel_script *)evsel->priv; + return (struct evsel_script *)evsel->priv; } -static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel, +static struct evsel_script *perf_evsel_script__new(struct evsel *evsel, struct perf_data *data) { - struct perf_evsel_script *es = zalloc(sizeof(*es)); + struct evsel_script *es = zalloc(sizeof(*es)); if (es != NULL) { if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0) @@ -277,7 +277,7 @@ static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel return NULL; } -static void perf_evsel_script__delete(struct perf_evsel_script *es) +static void perf_evsel_script__delete(struct evsel_script *es) { zfree(&es->filename); fclose(es->fp); @@ -285,7 +285,7 @@ static void perf_evsel_script__delete(struct perf_evsel_script *es) free(es); } -static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp) +static int perf_evsel_script__fprintf(struct evsel_script *es, FILE *fp) { struct stat st; @@ -340,7 +340,7 @@ static const char *output_field2str(enum perf_output_field field) #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x) -static int perf_evsel__do_check_stype(struct perf_evsel *evsel, +static int perf_evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set) @@ -372,7 +372,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel, return 0; } -static int perf_evsel__check_stype(struct perf_evsel *evsel, +static int perf_evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field) { @@ -380,7 +380,7 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel, false); } -static int perf_evsel__check_attr(struct perf_evsel *evsel, +static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->attr; @@ -507,7 +507,7 @@ static void set_print_ip_opts(struct perf_event_attr *attr) static int perf_session__check_output_opt(struct perf_session *session) { unsigned int j; - struct perf_evsel *evsel; + struct evsel *evsel; for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { evsel = perf_session__find_first_evtype(session, attr_type(j)); @@ -614,7 +614,7 @@ static int perf_sample__fprintf_uregs(struct perf_sample *sample, static int perf_sample__fprintf_start(struct perf_sample *sample, struct thread *thread, - struct perf_evsel *evsel, + struct evsel *evsel, u32 type, FILE *fp) { struct perf_event_attr *attr = &evsel->attr; @@ -1162,7 +1162,7 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample, } static const char *resolve_branch_sym(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct thread *thread, struct addr_location *al, u64 *ip) @@ -1191,7 +1191,7 @@ static const char *resolve_branch_sym(struct perf_sample *sample, } static int perf_sample__fprintf_callindent(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct thread *thread, struct addr_location *al, FILE *fp) { @@ -1285,7 +1285,7 @@ static int perf_sample__fprintf_ipc(struct perf_sample *sample, } static int perf_sample__fprintf_bts(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct thread *thread, struct addr_location *al, struct machine *machine, FILE *fp) @@ -1593,7 +1593,7 @@ static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp) } static int perf_sample__fprintf_synth(struct perf_sample *sample, - struct perf_evsel *evsel, FILE *fp) + struct evsel *evsel, FILE *fp) { switch (evsel->attr.config) { case PERF_SYNTH_INTEL_PTWRITE: @@ -1638,7 +1638,7 @@ struct perf_script { static int perf_evlist__max_name_len(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; int max = 0; evlist__for_each_entry(evlist, evsel) { @@ -1670,7 +1670,7 @@ static int data_src__fprintf(u64 data_src, FILE *fp) struct metric_ctx { struct perf_sample *sample; struct thread *thread; - struct perf_evsel *evsel; + struct evsel *evsel; FILE *fp; }; @@ -1705,7 +1705,7 @@ static void script_new_line(struct perf_stat_config *config __maybe_unused, static void perf_sample__fprint_metric(struct perf_script *script, struct thread *thread, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, FILE *fp) { @@ -1720,7 +1720,7 @@ static void perf_sample__fprint_metric(struct perf_script *script, }, .force_header = false, }; - struct perf_evsel *ev2; + struct evsel *ev2; u64 val; if (!evsel->stats) @@ -1747,7 +1747,7 @@ static void perf_sample__fprint_metric(struct perf_script *script, } static bool show_event(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct thread *thread, struct addr_location *al) { @@ -1788,14 +1788,14 @@ static bool show_event(struct perf_sample *sample, } static void process_event(struct perf_script *script, - struct perf_sample *sample, struct perf_evsel *evsel, + struct perf_sample *sample, struct evsel *evsel, struct addr_location *al, struct machine *machine) { struct thread *thread = al->thread; struct perf_event_attr *attr = &evsel->attr; unsigned int type = output_type(attr->type); - struct perf_evsel_script *es = evsel->priv; + struct evsel_script *es = evsel->priv; FILE *fp = es->fp; if (output[type].fields == 0) @@ -1897,7 +1897,7 @@ static void process_event(struct perf_script *script, static struct scripting_ops *scripting_ops; -static void __process_stat(struct perf_evsel *counter, u64 tstamp) +static void __process_stat(struct evsel *counter, u64 tstamp) { int nthreads = thread_map__nr(counter->threads); int ncpus = perf_evsel__nr_cpus(counter); @@ -1931,7 +1931,7 @@ static void __process_stat(struct perf_evsel *counter, u64 tstamp) } } -static void process_stat(struct perf_evsel *counter, u64 tstamp) +static void process_stat(struct evsel *counter, u64 tstamp) { if (scripting_ops && scripting_ops->process_stat) scripting_ops->process_stat(&stat_config, counter, tstamp); @@ -1973,7 +1973,7 @@ static bool filter_cpu(struct perf_sample *sample) static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct perf_script *scr = container_of(tool, struct perf_script, tool); @@ -2022,9 +2022,9 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, { struct perf_script *scr = container_of(tool, struct perf_script, tool); struct perf_evlist *evlist; - struct perf_evsel *evsel, *pos; + struct evsel *evsel, *pos; int err; - static struct perf_evsel_script *es; + static struct evsel_script *es; err = perf_event__process_attr(tool, event, pevlist); if (err) @@ -2071,7 +2071,7 @@ static int process_comm_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); int ret = -1; thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); @@ -2108,7 +2108,7 @@ static int process_namespaces_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); int ret = -1; thread = machine__findnew_thread(machine, event->namespaces.pid, @@ -2146,7 +2146,7 @@ static int process_fork_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); if (perf_event__process_fork(tool, event, sample, machine) < 0) return -1; @@ -2181,7 +2181,7 @@ static int process_exit_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); if (thread == NULL) { @@ -2216,7 +2216,7 @@ static int process_mmap_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); if (perf_event__process_mmap(tool, event, sample, machine) < 0) return -1; @@ -2250,7 +2250,7 @@ static int process_mmap2_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); if (perf_event__process_mmap2(tool, event, sample, machine) < 0) return -1; @@ -2284,7 +2284,7 @@ static int process_switch_event(struct perf_tool *tool, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); if (perf_event__process_switch(tool, event, sample, machine) < 0) return -1; @@ -2319,7 +2319,7 @@ process_lost_event(struct perf_tool *tool, { struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); struct thread *thread; thread = machine__findnew_thread(machine, sample->pid, @@ -2355,7 +2355,7 @@ process_bpf_events(struct perf_tool *tool __maybe_unused, struct thread *thread; struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); if (machine__process_ksymbol(machine, event, sample) < 0) return -1; @@ -2389,7 +2389,7 @@ static void sig_handler(int sig __maybe_unused) static void perf_script__fclose_per_event_dump(struct perf_script *script) { struct perf_evlist *evlist = script->session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (!evsel->priv) @@ -2401,7 +2401,7 @@ static void perf_script__fclose_per_event_dump(struct perf_script *script) static int perf_script__fopen_per_event_dump(struct perf_script *script) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(script->session->evlist, evsel) { /* @@ -2428,8 +2428,8 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script) static int perf_script__setup_per_event_dump(struct perf_script *script) { - struct perf_evsel *evsel; - static struct perf_evsel_script es_stdout; + struct evsel *evsel; + static struct evsel_script es_stdout; if (script->per_event_dump) return perf_script__fopen_per_event_dump(script); @@ -2444,10 +2444,10 @@ static int perf_script__setup_per_event_dump(struct perf_script *script) static void perf_script__exit_per_event_dump_stats(struct perf_script *script) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(script->session->evlist, evsel) { - struct perf_evsel_script *es = evsel->priv; + struct evsel_script *es = evsel->priv; perf_evsel_script__fprintf(es, stdout); perf_evsel_script__delete(es); @@ -3003,7 +3003,7 @@ static int check_ev_match(char *dir_name, char *scriptname, { char filename[MAXPATHLEN], evname[128]; char line[BUFSIZ], *p; - struct perf_evsel *pos; + struct evsel *pos; int match, len; FILE *fp; @@ -3236,7 +3236,7 @@ static int process_stat_round_event(struct perf_session *session, union perf_event *event) { struct stat_round_event *round = &event->stat_round; - struct perf_evsel *counter; + struct evsel *counter; evlist__for_each_entry(session->evlist, counter) { perf_stat_process_counter(&stat_config, counter); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 2b9518a38baf..e0ba97018ad7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -234,7 +234,7 @@ static int write_stat_round_event(u64 tm, u64 type) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) static int -perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, +perf_evsel__write_stat_event(struct evsel *counter, u32 cpu, u32 thread, struct perf_counts_values *count) { struct perf_sample_id *sid = SID(counter, cpu, thread); @@ -243,7 +243,7 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, process_synthesized_event, NULL); } -static int read_single_counter(struct perf_evsel *counter, int cpu, +static int read_single_counter(struct evsel *counter, int cpu, int thread, struct timespec *rs) { if (counter->tool_event == PERF_TOOL_DURATION_TIME) { @@ -261,7 +261,7 @@ static int read_single_counter(struct perf_evsel *counter, int cpu, * Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode */ -static int read_counter(struct perf_evsel *counter, struct timespec *rs) +static int read_counter(struct evsel *counter, struct timespec *rs) { int nthreads = thread_map__nr(evsel_list->threads); int ncpus, cpu, thread; @@ -319,7 +319,7 @@ static int read_counter(struct perf_evsel *counter, struct timespec *rs) static void read_counters(struct timespec *rs) { - struct perf_evsel *counter; + struct evsel *counter; int ret; evlist__for_each_entry(evsel_list, counter) { @@ -389,7 +389,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf workload_exec_errno = info->si_value.sival_int; } -static bool perf_evsel__should_store_id(struct perf_evsel *counter) +static bool perf_evsel__should_store_id(struct evsel *counter) { return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; } @@ -423,7 +423,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) int timeout = stat_config.timeout; char msg[BUFSIZ]; unsigned long long t0, t1; - struct perf_evsel *counter; + struct evsel *counter; struct timespec ts; size_t l; int status = 0; @@ -868,7 +868,7 @@ static int perf_stat__get_core_cached(struct perf_stat_config *config, static bool term_percore_set(void) { - struct perf_evsel *counter; + struct evsel *counter; evlist__for_each_entry(evsel_list, counter) { if (counter->percore) @@ -1462,7 +1462,7 @@ static int process_stat_round_event(struct perf_session *session, union perf_event *event) { struct stat_round_event *stat_round = &event->stat_round; - struct perf_evsel *counter; + struct evsel *counter; struct timespec tsh, *ts = NULL; const char **argv = session->header.env.cmdline_argv; int argc = session->header.env.nr_cmdline; @@ -1676,7 +1676,7 @@ static void setup_system_wide(int forks) if (!forks) target.system_wide = true; else { - struct perf_evsel *counter; + struct evsel *counter; evlist__for_each_entry(evsel_list, counter) { if (!counter->system_wide) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 4bde3fa245d1..f5f70c83d304 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -545,14 +545,14 @@ static const char *cat_backtrace(union perf_event *event, } typedef int (*tracepoint_handler)(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace); static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { struct timechart *tchart = container_of(tool, struct timechart, tool); @@ -575,7 +575,7 @@ static int process_sample_event(struct perf_tool *tool, static int process_sample_cpu_idle(struct timechart *tchart __maybe_unused, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -591,7 +591,7 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused, static int process_sample_cpu_frequency(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -604,7 +604,7 @@ process_sample_cpu_frequency(struct timechart *tchart, static int process_sample_sched_wakeup(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace) { @@ -618,7 +618,7 @@ process_sample_sched_wakeup(struct timechart *tchart, static int process_sample_sched_switch(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace) { @@ -634,7 +634,7 @@ process_sample_sched_switch(struct timechart *tchart, #ifdef SUPPORT_OLD_POWER_EVENTS static int process_sample_power_start(struct timechart *tchart __maybe_unused, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -647,7 +647,7 @@ process_sample_power_start(struct timechart *tchart __maybe_unused, static int process_sample_power_end(struct timechart *tchart, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -657,7 +657,7 @@ process_sample_power_end(struct timechart *tchart, static int process_sample_power_frequency(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -840,7 +840,7 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type, static int process_enter_read(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -850,7 +850,7 @@ process_enter_read(struct timechart *tchart, static int process_exit_read(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -860,7 +860,7 @@ process_exit_read(struct timechart *tchart, static int process_enter_write(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -870,7 +870,7 @@ process_enter_write(struct timechart *tchart, static int process_exit_write(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -880,7 +880,7 @@ process_exit_write(struct timechart *tchart, static int process_enter_sync(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -890,7 +890,7 @@ process_enter_sync(struct timechart *tchart, static int process_exit_sync(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -900,7 +900,7 @@ process_exit_sync(struct timechart *tchart, static int process_enter_tx(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -910,7 +910,7 @@ process_enter_tx(struct timechart *tchart, static int process_exit_tx(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -920,7 +920,7 @@ process_exit_tx(struct timechart *tchart, static int process_enter_rx(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -930,7 +930,7 @@ process_enter_rx(struct timechart *tchart, static int process_exit_rx(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -940,7 +940,7 @@ process_exit_rx(struct timechart *tchart, static int process_enter_poll(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long fd = perf_evsel__intval(evsel, sample, "fd"); @@ -950,7 +950,7 @@ process_enter_poll(struct timechart *tchart, static int process_exit_poll(struct timechart *tchart, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { long ret = perf_evsel__intval(evsel, sample, "ret"); @@ -1534,7 +1534,7 @@ static int process_header(struct perf_file_section *section __maybe_unused, static int __cmd_timechart(struct timechart *tchart, const char *output_name) { - const struct perf_evsel_str_handler power_tracepoints[] = { + const struct evsel_str_handler power_tracepoints[] = { { "power:cpu_idle", process_sample_cpu_idle }, { "power:cpu_frequency", process_sample_cpu_frequency }, { "sched:sched_wakeup", process_sample_sched_wakeup }, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b46b3c9f57a0..2f22f313985e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -101,7 +101,7 @@ static void perf_top__resize(struct perf_top *top) static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) { - struct perf_evsel *evsel; + struct evsel *evsel; struct symbol *sym; struct annotation *notes; struct map *map; @@ -186,7 +186,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) static void perf_top__record_precise_ip(struct perf_top *top, struct hist_entry *he, struct perf_sample *sample, - struct perf_evsel *evsel, u64 ip) + struct evsel *evsel, u64 ip) { struct annotation *notes; struct symbol *sym = he->ms.sym; @@ -228,7 +228,7 @@ static void perf_top__record_precise_ip(struct perf_top *top, static void perf_top__show_details(struct perf_top *top) { struct hist_entry *he = top->sym_filter_entry; - struct perf_evsel *evsel; + struct evsel *evsel; struct annotation *notes; struct symbol *symbol; int more; @@ -270,7 +270,7 @@ static void perf_top__print_sym_table(struct perf_top *top) char bf[160]; int printed = 0; const int win_width = top->winsize.ws_col - 1; - struct perf_evsel *evsel = top->sym_evsel; + struct evsel *evsel = top->sym_evsel; struct hists *hists = evsel__hists(evsel); puts(CONSOLE_CLEAR); @@ -554,7 +554,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) static void perf_top__sort_new_samples(void *arg) { struct perf_top *t = arg; - struct perf_evsel *evsel = t->sym_evsel; + struct evsel *evsel = t->sym_evsel; struct hists *hists; if (t->evlist->selected != NULL) @@ -586,7 +586,7 @@ static void stop_top(void) static void *display_thread_tui(void *arg) { - struct perf_evsel *pos; + struct evsel *pos; struct perf_top *top = arg; const char *help = "For a higher level overview, try: perf top --sort comm,dso"; struct hist_browser_timer hbt = { @@ -693,7 +693,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter, { struct perf_top *top = arg; struct hist_entry *he = iter->he; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; if (perf_hpp_list.sym && single) perf_top__record_precise_ip(top, he, iter->sample, evsel, al->addr); @@ -705,7 +705,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter, static void perf_event__process_sample(struct perf_tool *tool, const union perf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -813,7 +813,7 @@ static void perf_event__process_sample(struct perf_tool *tool, static void perf_top__process_lost(struct perf_top *top, union perf_event *event, - struct perf_evsel *evsel) + struct evsel *evsel) { struct hists *hists = evsel__hists(evsel); @@ -825,7 +825,7 @@ perf_top__process_lost(struct perf_top *top, union perf_event *event, static void perf_top__process_lost_samples(struct perf_top *top, union perf_event *event, - struct perf_evsel *evsel) + struct evsel *evsel) { struct hists *hists = evsel__hists(evsel); @@ -912,7 +912,7 @@ static int perf_top__overwrite_check(struct perf_top *top) struct perf_evlist *evlist = top->evlist; struct perf_evsel_config_term *term; struct list_head *config_terms; - struct perf_evsel *evsel; + struct evsel *evsel; int set, overwrite = -1; evlist__for_each_entry(evlist, evsel) { @@ -952,11 +952,11 @@ static int perf_top__overwrite_check(struct perf_top *top) } static int perf_top_overwrite_fallback(struct perf_top *top, - struct perf_evsel *evsel) + struct evsel *evsel) { struct record_opts *opts = &top->record_opts; struct perf_evlist *evlist = top->evlist; - struct perf_evsel *counter; + struct evsel *counter; if (!opts->overwrite) return 0; @@ -975,7 +975,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top, static int perf_top__start_counters(struct perf_top *top) { char msg[BUFSIZ]; - struct perf_evsel *counter; + struct evsel *counter; struct perf_evlist *evlist = top->evlist; struct record_opts *opts = &top->record_opts; @@ -1104,7 +1104,7 @@ static int deliver_event(struct ordered_events *qe, struct perf_session *session = top->session; union perf_event *event = qevent->event; struct perf_sample sample; - struct perf_evsel *evsel; + struct evsel *evsel; struct machine *machine; int ret = -1; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index ca28c48f812e..fde7eff811f9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -86,7 +86,7 @@ struct trace { *sys_exit; } prog_array; struct { - struct perf_evsel *sys_enter, + struct evsel *sys_enter, *sys_exit, *augmented; } events; @@ -242,7 +242,7 @@ struct syscall_tp { }; }; -static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel, +static int perf_evsel__init_tp_uint_field(struct evsel *evsel, struct tp_field *field, const char *name) { @@ -258,7 +258,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel, ({ struct syscall_tp *sc = evsel->priv;\ perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); }) -static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel, +static int perf_evsel__init_tp_ptr_field(struct evsel *evsel, struct tp_field *field, const char *name) { @@ -274,13 +274,13 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel, ({ struct syscall_tp *sc = evsel->priv;\ perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); }) -static void perf_evsel__delete_priv(struct perf_evsel *evsel) +static void perf_evsel__delete_priv(struct evsel *evsel) { zfree(&evsel->priv); perf_evsel__delete(evsel); } -static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel) +static int perf_evsel__init_syscall_tp(struct evsel *evsel) { struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp)); @@ -297,7 +297,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel) return -ENOENT; } -static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel, struct perf_evsel *tp) +static int perf_evsel__init_augmented_syscall_tp(struct evsel *evsel, struct evsel *tp) { struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp)); @@ -319,21 +319,21 @@ static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel, struc return -EINVAL; } -static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel) +static int perf_evsel__init_augmented_syscall_tp_args(struct evsel *evsel) { struct syscall_tp *sc = evsel->priv; return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)); } -static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel) +static int perf_evsel__init_augmented_syscall_tp_ret(struct evsel *evsel) { struct syscall_tp *sc = evsel->priv; return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap); } -static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler) +static int perf_evsel__init_raw_syscall_tp(struct evsel *evsel, void *handler) { evsel->priv = malloc(sizeof(struct syscall_tp)); if (evsel->priv != NULL) { @@ -351,9 +351,9 @@ static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handl return -ENOENT; } -static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler) +static struct evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler) { - struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); + struct evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */ if (IS_ERR(evsel)) @@ -1775,12 +1775,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, return printed; } -typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel, +typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel, union perf_event *event, struct perf_sample *sample); static struct syscall *trace__syscall_info(struct trace *trace, - struct perf_evsel *evsel, int id) + struct evsel *evsel, int id) { int err = 0; @@ -1886,7 +1886,7 @@ static int trace__printf_interrupted_entry(struct trace *trace) return printed; } -static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel, +static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel, struct perf_sample *sample, struct thread *thread) { int printed = 0; @@ -1929,7 +1929,7 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam return augmented_args; } -static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, +static int trace__sys_enter(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2008,7 +2008,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, return err; } -static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evsel, +static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, struct perf_sample *sample) { struct thread_trace *ttrace; @@ -2041,7 +2041,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse return err; } -static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel, +static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel, struct perf_sample *sample, struct callchain_cursor *cursor) { @@ -2069,7 +2069,7 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output); } -static const char *errno_to_name(struct perf_evsel *evsel, int err) +static const char *errno_to_name(struct evsel *evsel, int err) { struct perf_env *env = perf_evsel__env(evsel); const char *arch_name = perf_env__arch(env); @@ -2077,7 +2077,7 @@ static const char *errno_to_name(struct perf_evsel *evsel, int err) return arch_syscalls__strerrno(arch_name, err); } -static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, +static int trace__sys_exit(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2211,7 +2211,7 @@ errno_print: { return err; } -static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel, +static int trace__vfs_getname(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2272,7 +2272,7 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel, return 0; } -static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, +static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2334,7 +2334,7 @@ static void bpf_output__fprintf(struct trace *trace, ++trace->nr_events_printed; } -static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, +static int trace__event_handler(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2436,7 +2436,7 @@ static void print_location(FILE *f, struct perf_sample *sample, } static int trace__pgfault(struct trace *trace, - struct perf_evsel *evsel, + struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -2511,7 +2511,7 @@ static int trace__pgfault(struct trace *trace, } static void trace__set_base_time(struct trace *trace, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { /* @@ -2530,7 +2530,7 @@ static void trace__set_base_time(struct trace *trace, static int trace__process_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine __maybe_unused) { struct trace *trace = container_of(tool, struct trace, tool); @@ -2619,7 +2619,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) { bool found = false; - struct perf_evsel *evsel, *tmp; + struct evsel *evsel, *tmp; struct parse_events_error err = { .idx = 0, }; int ret = parse_events(evlist, "probe:vfs_getname*", &err); @@ -2644,9 +2644,9 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) return found; } -static struct perf_evsel *perf_evsel__new_pgfault(u64 config) +static struct evsel *perf_evsel__new_pgfault(u64 config) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .mmap_data = 1, @@ -2667,7 +2667,7 @@ static struct perf_evsel *perf_evsel__new_pgfault(u64 config) static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) { const u32 type = event->header.type; - struct perf_evsel *evsel; + struct evsel *evsel; if (type != PERF_RECORD_SAMPLE) { trace__process_event(trace, trace->host, event, sample); @@ -2700,7 +2700,7 @@ static int trace__add_syscall_newtp(struct trace *trace) { int ret = -1; struct perf_evlist *evlist = trace->evlist; - struct perf_evsel *sys_enter, *sys_exit; + struct evsel *sys_enter, *sys_exit; sys_enter = perf_evsel__raw_syscall_newtp("sys_enter", trace__sys_enter); if (sys_enter == NULL) @@ -2748,7 +2748,7 @@ static int trace__add_syscall_newtp(struct trace *trace) static int trace__set_ev_qualifier_tp_filter(struct trace *trace) { int err = -1; - struct perf_evsel *sys_exit; + struct evsel *sys_exit; char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier, trace->ev_qualifier_ids.nr, trace->ev_qualifier_ids.entries); @@ -3251,7 +3251,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe, static int trace__run(struct trace *trace, int argc, const char **argv) { struct perf_evlist *evlist = trace->evlist; - struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL; + struct evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL; int err = -1, i; unsigned long before; const bool forks = argc > 0; @@ -3543,7 +3543,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) static int trace__replay(struct trace *trace) { - const struct perf_evsel_str_handler handlers[] = { + const struct evsel_str_handler handlers[] = { { "probe:vfs_getname", trace__vfs_getname, }, }; struct perf_data data = { @@ -3552,7 +3552,7 @@ static int trace__replay(struct trace *trace) .force = trace->force, }; struct perf_session *session; - struct perf_evsel *evsel; + struct evsel *evsel; int err = -1; trace->tool.sample = trace__process_sample; @@ -3845,7 +3845,7 @@ static int parse_pagefaults(const struct option *opt, const char *str, static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) evsel->handler = handler; @@ -3853,7 +3853,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler) static int evlist__set_syscall_tp_fields(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->priv || !evsel->tp_format) @@ -4161,7 +4161,7 @@ int cmd_trace(int argc, const char **argv) }; bool __maybe_unused max_stack_user_set = true; bool mmap_pages_user_set = true; - struct perf_evsel *evsel; + struct evsel *evsel; const char * const trace_subcommands[] = { "record", NULL }; int err = -1; char bf[BUFSIZ]; @@ -4305,7 +4305,7 @@ int cmd_trace(int argc, const char **argv) if (trace.syscalls.events.augmented->priv == NULL && strstr(perf_evsel__name(evsel), "syscalls:sys_enter")) { - struct perf_evsel *augmented = trace.syscalls.events.augmented; + struct evsel *augmented = trace.syscalls.events.augmented; if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) || perf_evsel__init_augmented_syscall_tp_args(augmented)) goto out; diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 1a9c3becf5ff..921af318507c 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -83,7 +83,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; char pid[16], sbuf[STRERR_BUFSIZE]; struct perf_evlist *evlist; - struct perf_evsel *evsel __maybe_unused; + struct evsel *evsel __maybe_unused; struct parse_events_error parse_error; struct record_opts opts = { .target = { diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 88c218eacc43..062d23bba2df 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -555,7 +555,7 @@ static int do_test_code_reading(bool try_kcore) struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel = NULL; + struct evsel *evsel = NULL; int err = -1, ret; pid_t pid; struct map *map; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 684ad56f7b0f..45fe674233d7 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -14,7 +14,7 @@ static int attach__enable_on_exec(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); struct target target = { .uid = UINT_MAX, }; @@ -56,7 +56,7 @@ static int detach__enable_on_exec(struct perf_evlist *evlist) static int attach__current_disabled(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); struct perf_thread_map *threads; int err; @@ -82,7 +82,7 @@ static int attach__current_disabled(struct perf_evlist *evlist) static int attach__current_enabled(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); struct perf_thread_map *threads; int err; @@ -102,14 +102,14 @@ static int attach__current_enabled(struct perf_evlist *evlist) static int detach__disable(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); return perf_evsel__enable(evsel); } static int attach__cpu_disabled(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); struct perf_cpu_map *cpus; int err; @@ -138,7 +138,7 @@ static int attach__cpu_disabled(struct perf_evlist *evlist) static int attach__cpu_enabled(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__last(evlist); + struct evsel *evsel = perf_evlist__last(evlist); struct perf_cpu_map *cpus; int err; @@ -163,7 +163,7 @@ static int test_times(int (attach)(struct perf_evlist *), { struct perf_counts_values count; struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel; + struct evsel *evsel; int err = -1, i; evlist = perf_evlist__new(); diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index b5042f019ec4..0e5a2e8195e4 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -80,7 +80,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused) { struct perf_evlist *evlist; - struct perf_evsel *evsel; + struct evsel *evsel; struct event_name tmp; evlist = perf_evlist__new_default(); diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index a104728ebf25..bb38489eda1e 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -11,7 +11,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) { char name[128]; int type, op, err = 0, ret = 0, i, idx; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = perf_evlist__new(); if (evlist == NULL) @@ -67,7 +67,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) static int __perf_evsel__name_array_test(const char *names[], int nr_names) { int i, err; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = perf_evlist__new(); if (evlist == NULL) diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 71f60c0f9faa..0170e9d2e329 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -5,7 +5,7 @@ #include "tests.h" #include "debug.h" -static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, +static int perf_evsel__test_field(struct evsel *evsel, const char *name, int size, bool should_be_signed) { struct tep_format_field *field = perf_evsel__field(evsel, name); @@ -35,7 +35,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); + struct evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); int ret = 0; if (IS_ERR(evsel)) { diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 7a2eed6c783e..b62bf7c3bea2 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -80,7 +80,7 @@ static u64 fake_callchains[][10] = { static int add_hist_entries(struct hists *hists, struct machine *machine) { struct addr_location al; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); struct perf_sample sample = { .period = 1000, }; size_t i; @@ -147,7 +147,7 @@ static void del_hist_entries(struct hists *hists) } } -typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); +typedef int (*test_fn_t)(struct evsel *, struct machine *); #define COMM(he) (thread__comm_str(he->thread)) #define DSO(he) (he->ms.map->dso->short_name) @@ -247,7 +247,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec } /* NO callchain + NO children */ -static int test1(struct perf_evsel *evsel, struct machine *machine) +static int test1(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -298,7 +298,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) } /* callcain + NO children */ -static int test2(struct perf_evsel *evsel, struct machine *machine) +static int test2(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -446,7 +446,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) } /* NO callchain + children */ -static int test3(struct perf_evsel *evsel, struct machine *machine) +static int test3(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -503,7 +503,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) } /* callchain + children */ -static int test4(struct perf_evsel *evsel, struct machine *machine) +static int test4(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -694,7 +694,7 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u int err = TEST_FAIL; struct machines machines; struct machine *machine; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = perf_evlist__new(); size_t i; test_fn_t testcases[] = { diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 975844807fe2..3e679bb8da7f 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -50,7 +50,7 @@ static struct sample fake_samples[] = { static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) { - struct perf_evsel *evsel; + struct evsel *evsel; struct addr_location al; struct perf_sample sample = { .period = 100, }; size_t i; @@ -108,7 +108,7 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu int err = TEST_FAIL; struct machines machines; struct machine *machine; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = perf_evlist__new(); TEST_ASSERT_VAL("No memory", evlist); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index af633db63f4d..078ee9876980 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -64,7 +64,7 @@ static struct sample fake_samples[][5] = { static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) { - struct perf_evsel *evsel; + struct evsel *evsel; struct addr_location al; struct hist_entry *he; struct perf_sample sample = { .period = 1, .weight = 1, }; @@ -271,7 +271,7 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse struct hists *hists, *first_hists; struct machines machines; struct machine *machine = NULL; - struct perf_evsel *evsel, *first; + struct evsel *evsel, *first; struct perf_evlist *evlist = perf_evlist__new(); if (evlist == NULL) diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index 0a510c524a5d..5cd4b1baa9d1 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -50,7 +50,7 @@ static struct sample fake_samples[] = { static int add_hist_entries(struct hists *hists, struct machine *machine) { struct addr_location al; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); struct perf_sample sample = { .period = 100, }; size_t i; @@ -113,7 +113,7 @@ static void del_hist_entries(struct hists *hists) } } -typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); +typedef int (*test_fn_t)(struct evsel *, struct machine *); #define COMM(he) (thread__comm_str(he->thread)) #define DSO(he) (he->ms.map->dso->short_name) @@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); #define PID(he) (he->thread->tid) /* default sort keys (no field) */ -static int test1(struct perf_evsel *evsel, struct machine *machine) +static int test1(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -224,7 +224,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) } /* mixed fields and sort keys */ -static int test2(struct perf_evsel *evsel, struct machine *machine) +static int test2(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -280,7 +280,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) } /* fields only (no sort key) */ -static int test3(struct perf_evsel *evsel, struct machine *machine) +static int test3(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -354,7 +354,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) } /* handle duplicate 'dso' field */ -static int test4(struct perf_evsel *evsel, struct machine *machine) +static int test4(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -456,7 +456,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) } /* full sort keys w/o overhead field */ -static int test5(struct perf_evsel *evsel, struct machine *machine) +static int test5(struct evsel *evsel, struct machine *machine) { int err; struct hists *hists = evsel__hists(evsel); @@ -580,7 +580,7 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu int err = TEST_FAIL; struct machines machines; struct machine *machine; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = perf_evlist__new(); size_t i; test_fn_t testcases[] = { diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index e1e5e32cbb53..8ada3e63f1ba 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -68,7 +68,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel = NULL; + struct evsel *evsel = NULL; int found, err = -1; const char *comm; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index c1e2fe087b67..76ee42eb1355 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -36,7 +36,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse #define nsyscalls ARRAY_SIZE(syscall_names) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; - struct perf_evsel *evsels[nsyscalls], *evsel; + struct evsel *evsels[nsyscalls], *evsel; char sbuf[STRERR_BUFSIZE]; struct perf_mmap *md; diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 9cd5bf63bec1..4bf73896695a 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -21,7 +21,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int { int err = -1, fd, cpu; struct perf_cpu_map *cpus; - struct perf_evsel *evsel; + struct evsel *evsel; unsigned int nr_openat_calls = 111, i; cpu_set_t cpu_set; struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 344dc3ac2469..2e467448e220 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -33,7 +33,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest const char *filename = "/etc/passwd"; int flags = O_RDONLY | O_DIRECTORY; struct perf_evlist *evlist = perf_evlist__new(); - struct perf_evsel *evsel; + struct evsel *evsel; int err = -1, i, nr_events = 0, nr_polls = 0; char sbuf[STRERR_BUFSIZE]; diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 652b8328ca93..f3efadd05863 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -14,7 +14,7 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused) { int err = -1, fd; - struct perf_evsel *evsel; + struct evsel *evsel; unsigned int nr_openat_calls = 111, i; struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); char sbuf[STRERR_BUFSIZE]; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 8f3c80e13584..f55ab43d51bd 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -46,7 +46,7 @@ static bool kvm_s390_create_vm_valid(void) static int test__checkevent_tracepoint(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); @@ -59,7 +59,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist) static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); @@ -77,7 +77,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) static int test__checkevent_raw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -87,7 +87,7 @@ static int test__checkevent_raw(struct perf_evlist *evlist) static int test__checkevent_numeric(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); @@ -97,7 +97,7 @@ static int test__checkevent_numeric(struct perf_evlist *evlist) static int test__checkevent_symbolic_name(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); @@ -108,7 +108,7 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist) static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); @@ -129,7 +129,7 @@ static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); @@ -140,7 +140,7 @@ static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) static int test__checkevent_genhw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); @@ -150,7 +150,7 @@ static int test__checkevent_genhw(struct perf_evlist *evlist) static int test__checkevent_breakpoint(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -164,7 +164,7 @@ static int test__checkevent_breakpoint(struct perf_evlist *evlist) static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -177,7 +177,7 @@ static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -192,7 +192,7 @@ static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -207,7 +207,7 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", @@ -222,7 +222,7 @@ static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -235,7 +235,7 @@ static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) static int test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); @@ -253,7 +253,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) static int test__checkevent_raw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -265,7 +265,7 @@ static int test__checkevent_raw_modifier(struct perf_evlist *evlist) static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -277,7 +277,7 @@ static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -289,7 +289,7 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); @@ -299,7 +299,7 @@ static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); @@ -309,7 +309,7 @@ static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -321,7 +321,7 @@ static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -333,7 +333,7 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); @@ -348,7 +348,7 @@ static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist) static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); @@ -363,7 +363,7 @@ static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist) static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); @@ -378,7 +378,7 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -392,7 +392,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -406,7 +406,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -420,7 +420,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); @@ -435,7 +435,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) static int test__checkevent_pmu(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -453,7 +453,7 @@ static int test__checkevent_pmu(struct perf_evlist *evlist) static int test__checkevent_list(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); @@ -492,7 +492,7 @@ static int test__checkevent_list(struct perf_evlist *evlist) static int test__checkevent_pmu_name(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); /* cpu/config=1,name=krava/u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); @@ -513,7 +513,7 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist) static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); /* cpu/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); @@ -546,7 +546,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlis static int test__checkevent_pmu_events(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -564,7 +564,7 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist) static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); /* pmu-event:u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); @@ -636,7 +636,7 @@ static int test__checkterms_simple(struct list_head *terms) static int test__group1(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -678,7 +678,7 @@ static int test__group1(struct perf_evlist *evlist) static int test__group2(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -733,7 +733,7 @@ static int test__group2(struct perf_evlist *evlist) static int test__group3(struct perf_evlist *evlist __maybe_unused) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); @@ -825,7 +825,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) static int test__group4(struct perf_evlist *evlist __maybe_unused) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -869,7 +869,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) static int test__group5(struct perf_evlist *evlist __maybe_unused) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); @@ -955,7 +955,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) static int test__group_gh1(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -995,7 +995,7 @@ static int test__group_gh1(struct perf_evlist *evlist) static int test__group_gh2(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -1035,7 +1035,7 @@ static int test__group_gh2(struct perf_evlist *evlist) static int test__group_gh3(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -1075,7 +1075,7 @@ static int test__group_gh3(struct perf_evlist *evlist) static int test__group_gh4(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); @@ -1115,7 +1115,7 @@ static int test__group_gh4(struct perf_evlist *evlist) static int test__leader_sample1(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); @@ -1168,7 +1168,7 @@ static int test__leader_sample1(struct perf_evlist *evlist) static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); @@ -1207,7 +1207,7 @@ static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused) static int test__checkevent_pinned_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -1220,7 +1220,7 @@ static int test__checkevent_pinned_modifier(struct perf_evlist *evlist) static int test__pinned_group(struct perf_evlist *evlist) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); @@ -1251,7 +1251,7 @@ static int test__pinned_group(struct perf_evlist *evlist) static int test__checkevent_breakpoint_len(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -1266,7 +1266,7 @@ static int test__checkevent_breakpoint_len(struct perf_evlist *evlist) static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); @@ -1282,7 +1282,7 @@ static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist) static int test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); @@ -1294,7 +1294,7 @@ test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); @@ -1305,7 +1305,7 @@ static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist) static int test__checkevent_config_symbol(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "insn") == 0); return 0; @@ -1313,7 +1313,7 @@ static int test__checkevent_config_symbol(struct perf_evlist *evlist) static int test__checkevent_config_raw(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "rawpmu") == 0); return 0; @@ -1321,7 +1321,7 @@ static int test__checkevent_config_raw(struct perf_evlist *evlist) static int test__checkevent_config_num(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "numpmu") == 0); return 0; @@ -1329,7 +1329,7 @@ static int test__checkevent_config_num(struct perf_evlist *evlist) static int test__checkevent_config_cache(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "cachepmu") == 0); return 0; @@ -1342,7 +1342,7 @@ static bool test__intel_pt_valid(void) static int test__intel_pt(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "intel_pt//u") == 0); return 0; @@ -1350,7 +1350,7 @@ static int test__intel_pt(struct perf_evlist *evlist) static int test__checkevent_complex_name(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong complex name parsing", strcmp(evsel->name, "COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks") == 0); return 0; @@ -1358,7 +1358,7 @@ static int test__checkevent_complex_name(struct perf_evlist *evlist) static int test__sym_event_slash(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); @@ -1368,7 +1368,7 @@ static int test__sym_event_slash(struct perf_evlist *evlist) static int test__sym_event_dc(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evlist__first(evlist); + struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 07f6bd8ed719..7e576c2db941 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -51,7 +51,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus cpu_set_t cpu_mask; size_t cpu_mask_size = sizeof(cpu_mask); struct perf_evlist *evlist = perf_evlist__new_dummy(); - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_sample sample; const char *cmd = "sleep"; const char *argv[] = { cmd, "1", NULL, }; diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index 361714e2583c..a8cd3ed3c116 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -153,7 +153,7 @@ static bool samples_same(const struct perf_sample *s1, static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) { - struct perf_evsel evsel = { + struct evsel evsel = { .needs_swap = false, .attr = { .sample_type = sample_type, diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index d57b8d9c1575..620a99aad1e3 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -27,7 +27,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) int nr_samples = 0; char sbuf[STRERR_BUFSIZE]; union perf_event *event; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist; struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 3652c548cc22..a946b9fa60dd 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -52,8 +52,8 @@ static int spin_sleep(void) } struct switch_tracking { - struct perf_evsel *switch_evsel; - struct perf_evsel *cycles_evsel; + struct evsel *switch_evsel; + struct evsel *cycles_evsel; pid_t *tids; int nr_tids; int comm_seen[4]; @@ -118,7 +118,7 @@ static int process_sample_event(struct perf_evlist *evlist, struct switch_tracking *switch_tracking) { struct perf_sample sample; - struct perf_evsel *evsel; + struct evsel *evsel; pid_t next_tid, prev_tid; int cpu, err; @@ -330,8 +330,8 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; struct perf_evlist *evlist = NULL; - struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; - struct perf_evsel *switch_evsel, *tracking_evsel; + struct evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; + struct evsel *switch_evsel, *tracking_evsel; const char *comm; int err = -1; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 9602ff91a3c7..e6fb4b8d8bc2 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -37,7 +37,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused { int err = -1; union perf_event *event; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist; struct target target = { .uid = UINT_MAX, diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index e67880bf1efe..64cc650c4543 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -299,7 +299,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, } static void annotate_browser__calc_percent(struct annotate_browser *browser, - struct perf_evsel *evsel) + struct evsel *evsel) { struct map_symbol *ms = browser->b.priv; struct symbol *sym = ms->sym; @@ -406,7 +406,7 @@ static int sym_title(struct symbol *sym, struct map *map, char *title, * to the calling function. */ static bool annotate_browser__callq(struct annotate_browser *browser, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt) { struct map_symbol *ms = browser->b.priv; @@ -455,7 +455,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows } static bool annotate_browser__jump(struct annotate_browser *browser, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt) { struct disasm_line *dl = disasm_line(browser->selection); @@ -656,7 +656,7 @@ switch_percent_type(struct annotation_options *opts, bool base) } static int annotate_browser__run(struct annotate_browser *browser, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt) { struct rb_node *nd = NULL; @@ -869,14 +869,14 @@ static int annotate_browser__run(struct annotate_browser *browser, return key; } -int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, +int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts) { return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts); } -int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, +int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts) { @@ -888,7 +888,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, } int symbol__tui_annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts) { diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a94eb0755e8b..9bc818621eb6 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2187,7 +2187,7 @@ struct hist_browser *hist_browser__new(struct hists *hists) } static struct hist_browser * -perf_evsel_browser__new(struct perf_evsel *evsel, +perf_evsel_browser__new(struct evsel *evsel, struct hist_browser_timer *hbt, struct perf_env *env, struct annotation_options *annotation_opts) @@ -2352,7 +2352,7 @@ struct popup_action { struct thread *thread; struct map_symbol ms; int socket; - struct perf_evsel *evsel; + struct evsel *evsel; enum rstype rstype; int (*fn)(struct hist_browser *browser, struct popup_action *act); @@ -2361,7 +2361,7 @@ struct popup_action { static int do_annotate(struct hist_browser *browser, struct popup_action *act) { - struct perf_evsel *evsel; + struct evsel *evsel; struct annotation *notes; struct hist_entry *he; int err; @@ -2596,7 +2596,7 @@ static int add_script_opt_2(struct hist_browser *browser __maybe_unused, struct popup_action *act, char **optstr, struct thread *thread, struct symbol *sym, - struct perf_evsel *evsel, const char *tstr) + struct evsel *evsel, const char *tstr) { if (thread) { @@ -2623,7 +2623,7 @@ static int add_script_opt(struct hist_browser *browser, struct popup_action *act, char **optstr, struct thread *thread, struct symbol *sym, - struct perf_evsel *evsel) + struct evsel *evsel) { int n, j; struct hist_entry *he; @@ -2653,7 +2653,7 @@ static int add_res_sample_opt(struct hist_browser *browser __maybe_unused, struct popup_action *act, char **optstr, struct res_sample *res_sample, - struct perf_evsel *evsel, + struct evsel *evsel, enum rstype type) { if (!res_sample) @@ -2814,7 +2814,7 @@ static void hist_browser__update_percent_limit(struct hist_browser *hb, } } -static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, +static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, const char *helpline, bool left_exits, struct hist_browser_timer *hbt, @@ -3198,9 +3198,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, return key; } -struct perf_evsel_menu { +struct evsel_menu { struct ui_browser b; - struct perf_evsel *selection; + struct evsel *selection; struct annotation_options *annotation_opts; bool lost_events, lost_events_warned; float min_pcnt; @@ -3210,9 +3210,9 @@ struct perf_evsel_menu { static void perf_evsel_menu__write(struct ui_browser *browser, void *entry, int row) { - struct perf_evsel_menu *menu = container_of(browser, - struct perf_evsel_menu, b); - struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); + struct evsel_menu *menu = container_of(browser, + struct evsel_menu, b); + struct evsel *evsel = list_entry(entry, struct evsel, node); struct hists *hists = evsel__hists(evsel); bool current_entry = ui_browser__is_current_entry(browser, row); unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE]; @@ -3225,7 +3225,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser, HE_COLORSET_NORMAL); if (perf_evsel__is_group_event(evsel)) { - struct perf_evsel *pos; + struct evsel *pos; ev_name = perf_evsel__group_name(evsel); @@ -3257,13 +3257,13 @@ static void perf_evsel_menu__write(struct ui_browser *browser, menu->selection = evsel; } -static int perf_evsel_menu__run(struct perf_evsel_menu *menu, +static int perf_evsel_menu__run(struct evsel_menu *menu, int nr_events, const char *help, struct hist_browser_timer *hbt, bool warn_lost_event) { struct perf_evlist *evlist = menu->b.priv; - struct perf_evsel *pos; + struct evsel *pos; const char *title = "Available samples"; int delay_secs = hbt ? hbt->refresh : 0; int key; @@ -3351,7 +3351,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, static bool filter_group_entries(struct ui_browser *browser __maybe_unused, void *entry) { - struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); + struct evsel *evsel = list_entry(entry, struct evsel, node); if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel)) return true; @@ -3367,8 +3367,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, bool warn_lost_event, struct annotation_options *annotation_opts) { - struct perf_evsel *pos; - struct perf_evsel_menu menu = { + struct evsel *pos; + struct evsel_menu menu = { .b = { .entries = &evlist->entries, .refresh = ui_browser__list_head_refresh, @@ -3408,7 +3408,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, single_entry: if (nr_entries == 1) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); return perf_evsel__hists_browse(first, nr_entries, help, false, hbt, min_pcnt, @@ -3417,7 +3417,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, } if (symbol_conf.event_group) { - struct perf_evsel *pos; + struct evsel *pos; nr_entries = 0; evlist__for_each_entry(evlist, pos) { diff --git a/tools/perf/ui/browsers/res_sample.c b/tools/perf/ui/browsers/res_sample.c index 8aa3547bb9ff..7f3576deafd7 100644 --- a/tools/perf/ui/browsers/res_sample.c +++ b/tools/perf/ui/browsers/res_sample.c @@ -24,7 +24,7 @@ void res_sample_init(void) } int res_sample_browse(struct res_sample *res_samples, int num_res, - struct perf_evsel *evsel, enum rstype rstype) + struct evsel *evsel, enum rstype rstype) { char **names; int i, n; diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index 4d565cc14076..c0462457e9f9 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c @@ -78,7 +78,7 @@ static int scripts_config(const char *var, const char *value, void *data) * Return -1 on failure. */ static int list_scripts(char *script_name, bool *custom, - struct perf_evsel *evsel) + struct evsel *evsel) { char *buf, *paths[SCRIPT_MAX_NO], *names[SCRIPT_MAX_NO]; int i, num, choice; @@ -162,7 +162,7 @@ void run_script(char *cmd) SLsmg_refresh(); } -int script_browse(const char *script_opt, struct perf_evsel *evsel) +int script_browse(const char *script_opt, struct evsel *evsel) { char *cmd, script_name[SCRIPT_FULLPATH_LEN]; bool custom = false; diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 3af87c18a914..40e263a730e4 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -91,7 +91,7 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl) } static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, - struct map *map, struct perf_evsel *evsel, + struct map *map, struct evsel *evsel, struct hist_browser_timer *hbt __maybe_unused) { struct disasm_line *pos, *n; @@ -160,7 +160,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, } static int symbol__gtk_annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt) { GtkWidget *window; @@ -238,7 +238,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, } int hist_entry__gtk_annotate(struct hist_entry *he, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt) { return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt); diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 9846ea5c831b..e2f5fbef3c9a 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -52,7 +52,7 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void) } #endif -struct perf_evsel; +struct evsel; struct perf_evlist; struct hist_entry; struct hist_browser_timer; @@ -61,7 +61,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, struct hist_browser_timer *hbt, float min_pcnt); int hist_entry__gtk_annotate(struct hist_entry *he, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt); void perf_gtk__show_annotations(void); diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 3955ed1d1bd9..d5c9fe230632 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -595,7 +595,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, struct hist_browser_timer *hbt __maybe_unused, float min_pcnt) { - struct perf_evsel *pos; + struct evsel *pos; GtkWidget *vbox; GtkWidget *notebook; GtkWidget *info_bar; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 412d6f1626e3..214af526901b 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -25,7 +25,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, { int ret; struct hists *hists = he->hists; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); char *buf = hpp->buf; size_t size = hpp->size; @@ -153,7 +153,7 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, { s64 ret; int i, nr_members; - struct perf_evsel *evsel; + struct evsel *evsel; struct hist_entry *pair; u64 *fields_a, *fields_b; @@ -223,7 +223,7 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt, struct hists *hists) { int len = fmt->user_len ?: fmt->len; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); if (symbol_conf.event_group) len = max(len, evsel->nr_members * fmt->len); @@ -797,7 +797,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt) int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_hpp_fmt *fmt; struct hists *hists; int ret; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ac9ad2330f93..6ea5d678a81c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -929,7 +929,7 @@ struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists) } static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, u64 addr, + struct evsel *evsel, u64 addr, struct perf_sample *sample) { struct annotated_source *src; @@ -1080,13 +1080,13 @@ void annotation__compute_ipc(struct annotation *notes, size_t size) } int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample); } int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, - struct perf_evsel *evsel, u64 ip) + struct evsel *evsel, u64 ip) { return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample); } @@ -1134,7 +1134,7 @@ struct annotate_args { size_t privsize; struct arch *arch; struct map_symbol ms; - struct perf_evsel *evsel; + struct evsel *evsel; struct annotation_options *options; s64 offset; char *line; @@ -1165,7 +1165,7 @@ static struct annotation_line * annotation_line__new(struct annotate_args *args, size_t privsize) { struct annotation_line *al; - struct perf_evsel *evsel = args->evsel; + struct evsel *evsel = args->evsel; size_t size = privsize + sizeof(*al); int nr = 1; @@ -1359,7 +1359,7 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi static int annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start, - struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, + struct evsel *evsel, u64 len, int min_pcnt, int printed, int max_lines, struct annotation_line *queue, int addr_fmt_width, int percent_type) { @@ -2011,10 +2011,10 @@ static void calc_percent(struct sym_hist *sym_hist, } static void annotation__calc_percent(struct annotation *notes, - struct perf_evsel *leader, s64 len) + struct evsel *leader, s64 len) { struct annotation_line *al, *next; - struct perf_evsel *evsel; + struct evsel *evsel; list_for_each_entry(al, ¬es->src->source, node) { s64 end; @@ -2041,7 +2041,7 @@ static void annotation__calc_percent(struct annotation *notes, } } -void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel) +void symbol__calc_percent(struct symbol *sym, struct evsel *evsel) { struct annotation *notes = symbol__annotation(sym); @@ -2049,7 +2049,7 @@ void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel) } int symbol__annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, size_t privsize, + struct evsel *evsel, size_t privsize, struct annotation_options *options, struct arch **parch) { @@ -2214,7 +2214,7 @@ static void print_summary(struct rb_root *root, const char *filename) } } -static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel) +static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel) { struct annotation *notes = symbol__annotation(sym); struct sym_hist *h = annotation__histogram(notes, evsel->idx); @@ -2241,7 +2241,7 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start) } int symbol__annotate_printf(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct annotation_options *opts) { struct dso *dso = map->dso; @@ -2405,7 +2405,7 @@ static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp, return 0; } -int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel, +int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts) { const char *ev_name = perf_evsel__name(evsel); @@ -2657,7 +2657,7 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map, } int symbol__tty_annotate2(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct annotation_options *opts) { struct dso *dso = map->dso; @@ -2685,7 +2685,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, } int symbol__tty_annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct annotation_options *opts) { struct dso *dso = map->dso; @@ -2956,7 +2956,7 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes wops->write_graph); } -int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel, +int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel, struct annotation_options *options, struct arch **parch) { struct annotation *notes = symbol__annotation(sym); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 5bc0cf655d37..7c42f320efa2 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -20,7 +20,7 @@ struct map_symbol; struct addr_map_symbol; struct option; struct perf_sample; -struct perf_evsel; +struct evsel; struct symbol; struct ins { @@ -216,12 +216,12 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes int __annotation__scnprintf_samples_period(struct annotation *notes, char *bf, size_t size, - struct perf_evsel *evsel, + struct evsel *evsel, bool show_freq); int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name); size_t disasm__fprintf(struct list_head *head, FILE *fp); -void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); +void symbol__calc_percent(struct symbol *sym, struct evsel *evsel); struct sym_hist { u64 nr_samples; @@ -335,24 +335,24 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) } int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, - struct perf_evsel *evsel); + struct evsel *evsel); int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, struct addr_map_symbol *start, unsigned cycles); int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, - struct perf_evsel *evsel, u64 addr); + struct evsel *evsel, u64 addr); struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists); void symbol__annotate_zero_histograms(struct symbol *sym); int symbol__annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, size_t privsize, + struct evsel *evsel, size_t privsize, struct annotation_options *options, struct arch **parch); int symbol__annotate2(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct annotation_options *options, struct arch **parch); @@ -378,32 +378,32 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map, int errnum, char *buf, size_t buflen); int symbol__annotate_printf(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct annotation_options *options); void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); void annotated_source__purge(struct annotated_source *as); -int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel, +int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts); bool ui__has_annotation(void); int symbol__tty_annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, struct annotation_options *opts); + struct evsel *evsel, struct annotation_options *opts); int symbol__tty_annotate2(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, struct annotation_options *opts); + struct evsel *evsel, struct annotation_options *opts); #ifdef HAVE_SLANG_SUPPORT int symbol__tui_annotate(struct symbol *sym, struct map *map, - struct perf_evsel *evsel, + struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts); #else static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, struct map *map __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, struct annotation_options *opts __maybe_unused) { diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index ec0af36697c4..98b151bc9a36 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -2084,7 +2084,7 @@ static char *addr_filter__to_str(struct addr_filter *filt) return err < 0 ? NULL : filter; } -static int parse_addr_filter(struct perf_evsel *evsel, const char *filter, +static int parse_addr_filter(struct evsel *evsel, const char *filter, int max_nr) { struct addr_filters filts; @@ -2135,7 +2135,7 @@ static int parse_addr_filter(struct perf_evsel *evsel, const char *filter, return err; } -static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel) +static struct perf_pmu *perf_evsel__find_pmu(struct evsel *evsel) { struct perf_pmu *pmu = NULL; @@ -2147,7 +2147,7 @@ static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel) return pmu; } -static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel) +static int perf_evsel__nr_addr_filter(struct evsel *evsel) { struct perf_pmu *pmu = perf_evsel__find_pmu(evsel); int nr_addr_filters = 0; @@ -2162,7 +2162,7 @@ static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel) int auxtrace_parse_filters(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; char *filter; int err, max_nr; diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 6d0dfb777a79..594ea279e25b 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -817,7 +817,7 @@ struct bpf_map_op { } k; union { u64 value; - struct perf_evsel *evsel; + struct evsel *evsel; } v; }; @@ -1063,7 +1063,7 @@ __bpf_map__config_event(struct bpf_map *map, struct parse_events_term *term, struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; const struct bpf_map_def *def; struct bpf_map_op *op; const char *map_name = bpf_map__name(map); @@ -1401,7 +1401,7 @@ apply_config_value_for_key(int map_fd, void *pkey, static int apply_config_evsel_for_key(const char *name, int map_fd, void *pkey, - struct perf_evsel *evsel) + struct evsel *evsel) { struct xyarray *xy = evsel->fd; struct perf_event_attr *attr; @@ -1523,11 +1523,11 @@ int bpf__apply_obj_config(void) (strcmp(name, \ bpf_map__name(pos)) == 0)) -struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name) +struct evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name) { struct bpf_map_priv *tmpl_priv = NULL; struct bpf_object *obj, *tmp; - struct perf_evsel *evsel = NULL; + struct evsel *evsel = NULL; struct bpf_map *map; int err; bool need_init = false; @@ -1602,7 +1602,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha int bpf__setup_stdout(struct perf_evlist *evlist) { - struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); + struct evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); return PTR_ERR_OR_ZERO(evsel); } diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index 8c3441a4b72c..e2048c978a24 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -39,7 +39,7 @@ enum bpf_loader_errno { __BPF_LOADER_ERRNO__END, }; -struct perf_evsel; +struct evsel; struct perf_evlist; struct bpf_object; struct parse_events_term; @@ -80,7 +80,7 @@ int bpf__apply_obj_config(void); int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); int bpf__setup_stdout(struct perf_evlist *evlist); -struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name); +struct evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name); int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size); #else #include @@ -137,7 +137,7 @@ bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) return 0; } -static inline struct perf_evsel * +static inline struct evsel * bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused) { return NULL; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index f1abfab7aa8c..b98754863de9 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -37,7 +37,7 @@ static bool no_buildid_cache; int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine) { struct addr_location al; diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 93668f38f1ed..aad419bb165c 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -24,7 +24,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size, bool is_debug); int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample, struct perf_evsel *evsel, + struct perf_sample *sample, struct evsel *evsel, struct machine *machine); int dsos__hit_all(struct perf_session *session); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 8d7d8f62fcca..d077704f9afa 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1077,7 +1077,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor, int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, - struct perf_evsel *evsel, struct addr_location *al, + struct evsel *evsel, struct addr_location *al, int max_stack) { if (sample->callchain == NULL && !symbol_conf.show_branchflag_count) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 80e056a3d882..45b9ed49e2b1 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -236,7 +236,7 @@ int record_opts__parse_callchain(struct record_opts *record, int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, - struct perf_evsel *evsel, struct addr_location *al, + struct evsel *evsel, struct addr_location *al, int max_stack); int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node, diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 484c29830a81..4f5c326a9477 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -92,7 +92,7 @@ static int open_cgroup(const char *name) static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str) { - struct perf_evsel *counter; + struct evsel *counter; /* * check if cgrp is already defined, if so we reuse it */ @@ -139,7 +139,7 @@ struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *na static int add_cgroup(struct perf_evlist *evlist, const char *str) { - struct perf_evsel *counter; + struct evsel *counter; struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str); int n; @@ -184,7 +184,7 @@ struct cgroup *cgroup__get(struct cgroup *cgroup) return cgroup; } -static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup) +static void evsel__set_default_cgroup(struct evsel *evsel, struct cgroup *cgroup) { if (evsel->cgrp == NULL) evsel->cgrp = cgroup__get(cgroup); @@ -192,7 +192,7 @@ static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *c void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) evsel__set_default_cgroup(evsel, cgroup); @@ -202,7 +202,7 @@ int parse_cgroups(const struct option *opt, const char *str, int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; - struct perf_evsel *counter; + struct evsel *counter; struct cgroup *cgrp = NULL; const char *p, *e, *eos = str + strlen(str); char *s; diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c index 01ee81df3fe5..f94e1a23dad6 100644 --- a/tools/perf/util/counts.c +++ b/tools/perf/util/counts.c @@ -48,18 +48,18 @@ static void perf_counts__reset(struct perf_counts *counts) xyarray__reset(counts->values); } -void perf_evsel__reset_counts(struct perf_evsel *evsel) +void perf_evsel__reset_counts(struct evsel *evsel) { perf_counts__reset(evsel->counts); } -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads) +int perf_evsel__alloc_counts(struct evsel *evsel, int ncpus, int nthreads) { evsel->counts = perf_counts__new(ncpus, nthreads); return evsel->counts != NULL ? 0 : -ENOMEM; } -void perf_evsel__free_counts(struct perf_evsel *evsel) +void perf_evsel__free_counts(struct evsel *evsel) { perf_counts__delete(evsel->counts); evsel->counts = NULL; diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index 460b56ce3252..0f0cb2d8f70d 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -44,8 +44,8 @@ perf_counts__set_loaded(struct perf_counts *counts, int cpu, int thread, bool lo struct perf_counts *perf_counts__new(int ncpus, int nthreads); void perf_counts__delete(struct perf_counts *counts); -void perf_evsel__reset_counts(struct perf_evsel *evsel); -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads); -void perf_evsel__free_counts(struct perf_evsel *evsel); +void perf_evsel__reset_counts(struct evsel *evsel); +int perf_evsel__alloc_counts(struct evsel *evsel, int ncpus, int nthreads); +void perf_evsel__free_counts(struct evsel *evsel); #endif /* __PERF_COUNTS_H */ diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 3d1c34fc4d68..5a9fcb60ec88 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1223,7 +1223,7 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr; bool found = false; u64 id; @@ -2294,7 +2294,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = etm->session->evlist; bool timeless_decoding = true; diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index ddbcd59f2d9b..042ee5b6f9f1 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -413,7 +413,7 @@ static int add_tracepoint_fields_values(struct ctf_writer *cw, static int add_tracepoint_values(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; @@ -584,7 +584,7 @@ add_callchain_output_values(struct bt_ctf_event_class *event_class, static int add_generic_values(struct ctf_writer *cw, struct bt_ctf_event *event, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample) { u64 type = evsel->attr.sample_type; @@ -753,7 +753,7 @@ static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu) } static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { int cpu = 0; @@ -785,7 +785,7 @@ static bool is_flush_needed(struct ctf_stream *cs) static int process_sample_event(struct perf_tool *tool, union perf_event *_event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine __maybe_unused) { struct convert *c = container_of(tool, struct convert, tool); @@ -1051,7 +1051,7 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw, } static int add_tracepoint_types(struct ctf_writer *cw, - struct perf_evsel *evsel, + struct evsel *evsel, struct bt_ctf_event_class *class) { struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; @@ -1084,7 +1084,7 @@ static int add_bpf_output_types(struct ctf_writer *cw, return bt_ctf_event_class_add_field(class, seq_type, "raw_data"); } -static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, +static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel, struct bt_ctf_event_class *event_class) { u64 type = evsel->attr.sample_type; @@ -1150,7 +1150,7 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, return 0; } -static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) +static int add_event(struct ctf_writer *cw, struct evsel *evsel) { struct bt_ctf_event_class *event_class; struct evsel_priv *priv; @@ -1202,7 +1202,7 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) static int setup_events(struct ctf_writer *cw, struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; int ret; evlist__for_each_entry(evlist, evsel) { @@ -1309,7 +1309,7 @@ static int setup_non_sample_events(struct ctf_writer *cw, static void cleanup_events(struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { struct evsel_priv *priv; diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index ffbb3e7d3288..dc2d4de772e3 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -32,7 +32,7 @@ void db_export__exit(struct db_export *dbe) dbe->crp = NULL; } -int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel) +int db_export__evsel(struct db_export *dbe, struct evsel *evsel) { if (evsel->db_id) return 0; @@ -209,7 +209,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe, struct machine *machine, struct thread *thread, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { u64 kernel_start = machine__kernel_start(machine); struct call_path *current = &dbe->cpr->call_path; @@ -341,7 +341,7 @@ static int db_export__threads(struct db_export *dbe, struct thread *thread, } int db_export__sample(struct db_export *dbe, union perf_event *event, - struct perf_sample *sample, struct perf_evsel *evsel, + struct perf_sample *sample, struct evsel *evsel, struct addr_location *al) { struct thread *thread = al->thread; diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h index ba1f62a5fe10..9c3d38f5a40d 100644 --- a/tools/perf/util/db-export.h +++ b/tools/perf/util/db-export.h @@ -10,7 +10,7 @@ #include #include -struct perf_evsel; +struct evsel; struct machine; struct thread; struct comm; @@ -25,7 +25,7 @@ struct call_return; struct export_sample { union perf_event *event; struct perf_sample *sample; - struct perf_evsel *evsel; + struct evsel *evsel; struct addr_location *al; u64 db_id; u64 comm_db_id; @@ -39,7 +39,7 @@ struct export_sample { }; struct db_export { - int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel); + int (*export_evsel)(struct db_export *dbe, struct evsel *evsel); int (*export_machine)(struct db_export *dbe, struct machine *machine); int (*export_thread)(struct db_export *dbe, struct thread *thread, u64 main_thread_db_id, struct machine *machine); @@ -79,7 +79,7 @@ struct db_export { int db_export__init(struct db_export *dbe); void db_export__exit(struct db_export *dbe); -int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel); +int db_export__evsel(struct db_export *dbe, struct evsel *evsel); int db_export__machine(struct db_export *dbe, struct machine *machine); int db_export__thread(struct db_export *dbe, struct thread *thread, struct machine *machine, struct thread *main_thread); @@ -96,7 +96,7 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym, int db_export__branch_type(struct db_export *dbe, u32 branch_type, const char *name); int db_export__sample(struct db_export *dbe, union perf_event *event, - struct perf_sample *sample, struct perf_evsel *evsel, + struct perf_sample *sample, struct evsel *evsel, struct addr_location *al); int db_export__branch_types(struct db_export *dbe); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index a95d0461f718..7e6066cb525b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -98,7 +98,7 @@ struct perf_evlist *perf_evlist__new_dummy(void) */ void perf_evlist__set_id_pos(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); evlist->id_pos = first->id_pos; evlist->is_pos = first->is_pos; @@ -106,7 +106,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist) static void perf_evlist__update_id_pos(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) perf_evsel__calc_id_pos(evsel); @@ -116,7 +116,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist) static void perf_evlist__purge(struct perf_evlist *evlist) { - struct perf_evsel *pos, *n; + struct evsel *pos, *n; evlist__for_each_entry_safe(evlist, n, pos) { list_del_init(&pos->node); @@ -151,7 +151,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) } static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, - struct perf_evsel *evsel) + struct evsel *evsel) { /* * We already have cpus for evsel (via PMU sysfs) so @@ -171,13 +171,13 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, static void perf_evlist__propagate_maps(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) __perf_evlist__propagate_maps(evlist, evsel); } -void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) +void perf_evlist__add(struct perf_evlist *evlist, struct evsel *entry) { entry->evlist = evlist; list_add_tail(&entry->node, &evlist->entries); @@ -190,7 +190,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) __perf_evlist__propagate_maps(evlist, entry); } -void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel) +void perf_evlist__remove(struct perf_evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; list_del_init(&evsel->node); @@ -200,7 +200,7 @@ void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel) void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list) { - struct perf_evsel *evsel, *temp; + struct evsel *evsel, *temp; __evlist__for_each_entry_safe(list, temp, evsel) { list_del_init(&evsel->node); @@ -210,10 +210,10 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist, void __perf_evlist__set_leader(struct list_head *list) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; - leader = list_entry(list->next, struct perf_evsel, node); - evsel = list_entry(list->prev, struct perf_evsel, node); + leader = list_entry(list->next, struct evsel, node); + evsel = list_entry(list->prev, struct evsel, node); leader->nr_members = evsel->idx - leader->idx + 1; @@ -232,7 +232,7 @@ void perf_evlist__set_leader(struct perf_evlist *evlist) int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise) { - struct perf_evsel *evsel = perf_evsel__new_cycles(precise); + struct evsel *evsel = perf_evsel__new_cycles(precise); if (evsel == NULL) return -ENOMEM; @@ -248,7 +248,7 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist) .config = PERF_COUNT_SW_DUMMY, .size = sizeof(attr), /* to capture ABI version */ }; - struct perf_evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries); + struct evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries); if (evsel == NULL) return -ENOMEM; @@ -260,7 +260,7 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist) static int perf_evlist__add_attrs(struct perf_evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { - struct perf_evsel *evsel, *n; + struct evsel *evsel, *n; LIST_HEAD(head); size_t i; @@ -292,10 +292,10 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, return perf_evlist__add_attrs(evlist, attrs, nr_attrs); } -struct perf_evsel * +struct evsel * perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type == PERF_TYPE_TRACEPOINT && @@ -306,11 +306,11 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) return NULL; } -struct perf_evsel * +struct evsel * perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, const char *name) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && @@ -324,7 +324,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler) { - struct perf_evsel *evsel = perf_evsel__newtp(sys, name); + struct evsel *evsel = perf_evsel__newtp(sys, name); if (IS_ERR(evsel)) return -1; @@ -335,7 +335,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, } static int perf_evlist__nr_threads(struct perf_evlist *evlist, - struct perf_evsel *evsel) + struct evsel *evsel) { if (evsel->system_wide) return 1; @@ -345,7 +345,7 @@ static int perf_evlist__nr_threads(struct perf_evlist *evlist, void perf_evlist__disable(struct perf_evlist *evlist) { - struct perf_evsel *pos; + struct evsel *pos; evlist__for_each_entry(evlist, pos) { if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd) @@ -358,7 +358,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) void perf_evlist__enable(struct perf_evlist *evlist) { - struct perf_evsel *pos; + struct evsel *pos; evlist__for_each_entry(evlist, pos) { if (!perf_evsel__is_group_leader(pos) || !pos->fd) @@ -375,7 +375,7 @@ void perf_evlist__toggle_enable(struct perf_evlist *evlist) } static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, - struct perf_evsel *evsel, int cpu) + struct evsel *evsel, int cpu) { int thread; int nr_threads = perf_evlist__nr_threads(evlist, evsel); @@ -392,7 +392,7 @@ static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, } static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, - struct perf_evsel *evsel, + struct evsel *evsel, int thread) { int cpu; @@ -410,7 +410,7 @@ static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, } int perf_evlist__enable_event_idx(struct perf_evlist *evlist, - struct perf_evsel *evsel, int idx) + struct evsel *evsel, int idx) { bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus); @@ -425,7 +425,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) int nr_cpus = cpu_map__nr(evlist->cpus); int nr_threads = thread_map__nr(evlist->threads); int nfds = 0; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->system_wide) @@ -484,7 +484,7 @@ int perf_evlist__poll(struct perf_evlist *evlist, int timeout) } static void perf_evlist__id_hash(struct perf_evlist *evlist, - struct perf_evsel *evsel, + struct evsel *evsel, int cpu, int thread, u64 id) { int hash; @@ -496,7 +496,7 @@ static void perf_evlist__id_hash(struct perf_evlist *evlist, hlist_add_head(&sid->node, &evlist->heads[hash]); } -void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, +void perf_evlist__id_add(struct perf_evlist *evlist, struct evsel *evsel, int cpu, int thread, u64 id) { perf_evlist__id_hash(evlist, evsel, cpu, thread, id); @@ -504,7 +504,7 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, } int perf_evlist__id_add_fd(struct perf_evlist *evlist, - struct perf_evsel *evsel, + struct evsel *evsel, int cpu, int thread, int fd) { u64 read_data[4] = { 0, }; @@ -545,7 +545,7 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist, } static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, - struct perf_evsel *evsel, int idx, int cpu, + struct evsel *evsel, int idx, int cpu, int thread) { struct perf_sample_id *sid = SID(evsel, cpu, thread); @@ -576,7 +576,7 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) return NULL; } -struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) +struct evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) { struct perf_sample_id *sid; @@ -593,7 +593,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) return NULL; } -struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, +struct evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, u64 id) { struct perf_sample_id *sid; @@ -629,10 +629,10 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, return 0; } -struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, +struct evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, union perf_event *event) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); struct hlist_head *head; struct perf_sample_id *sid; int hash; @@ -744,7 +744,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist, static bool perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, - struct perf_evsel *evsel) + struct evsel *evsel) { if (evsel->attr.write_backward) return false; @@ -755,7 +755,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, struct mmap_params *mp, int cpu_idx, int thread, int *_output, int *_output_overwrite) { - struct perf_evsel *evsel; + struct evsel *evsel; int revent; int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx); @@ -1011,7 +1011,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush, int comp_level) { - struct perf_evsel *evsel; + struct evsel *evsel; const struct perf_cpu_map *cpus = evlist->cpus; const struct perf_thread_map *threads = evlist->threads; /* @@ -1130,7 +1130,7 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, enum perf_event_sample_format bit) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) __perf_evsel__set_sample_bit(evsel, bit); @@ -1139,15 +1139,15 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, enum perf_event_sample_format bit) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) __perf_evsel__reset_sample_bit(evsel, bit); } -int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) +int perf_evlist__apply_filters(struct perf_evlist *evlist, struct evsel **err_evsel) { - struct perf_evsel *evsel; + struct evsel *evsel; int err = 0; evlist__for_each_entry(evlist, evsel) { @@ -1170,7 +1170,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter) { - struct perf_evsel *evsel; + struct evsel *evsel; int err = 0; evlist__for_each_entry(evlist, evsel) { @@ -1219,7 +1219,7 @@ int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid) bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) { - struct perf_evsel *pos; + struct evsel *pos; if (evlist->nr_entries == 1) return true; @@ -1238,7 +1238,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; if (evlist->combined_sample_type) return evlist->combined_sample_type; @@ -1257,7 +1257,7 @@ u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; u64 branch_type = 0; evlist__for_each_entry(evlist, evsel) @@ -1267,7 +1267,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) bool perf_evlist__valid_read_format(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; + struct evsel *first = perf_evlist__first(evlist), *pos = first; u64 read_format = first->attr.read_format; u64 sample_type = first->attr.sample_type; @@ -1287,13 +1287,13 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) u64 perf_evlist__read_format(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); return first->attr.read_format; } u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); struct perf_sample *data; u64 sample_type; u16 size = 0; @@ -1326,7 +1326,7 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; + struct evsel *first = perf_evlist__first(evlist), *pos = first; evlist__for_each_entry_continue(evlist, pos) { if (first->attr.sample_id_all != pos->attr.sample_id_all) @@ -1338,19 +1338,19 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) bool perf_evlist__sample_id_all(struct perf_evlist *evlist) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); return first->attr.sample_id_all; } void perf_evlist__set_selected(struct perf_evlist *evlist, - struct perf_evsel *evsel) + struct evsel *evsel) { evlist->selected = evsel; } void perf_evlist__close(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry_reverse(evlist, evsel) perf_evsel__close(evsel); @@ -1389,7 +1389,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) int perf_evlist__open(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; int err; /* @@ -1553,7 +1553,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample) { - struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); + struct evsel *evsel = perf_evlist__event2evsel(evlist, event); if (!evsel) return -EFAULT; @@ -1564,7 +1564,7 @@ int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, union perf_event *event, u64 *timestamp) { - struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); + struct evsel *evsel = perf_evlist__event2evsel(evlist, event); if (!evsel) return -EFAULT; @@ -1573,7 +1573,7 @@ int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) { - struct perf_evsel *evsel; + struct evsel *evsel; size_t printed = 0; evlist__for_each_entry(evlist, evsel) { @@ -1613,7 +1613,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist, "Hint:\tThe current value is %d.", value); break; case EINVAL: { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); int max_freq; if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0) @@ -1670,9 +1670,9 @@ int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, s } void perf_evlist__to_front(struct perf_evlist *evlist, - struct perf_evsel *move_evsel) + struct evsel *move_evsel) { - struct perf_evsel *evsel, *n; + struct evsel *evsel, *n; LIST_HEAD(move); if (move_evsel == perf_evlist__first(evlist)) @@ -1687,9 +1687,9 @@ void perf_evlist__to_front(struct perf_evlist *evlist, } void perf_evlist__set_tracking_event(struct perf_evlist *evlist, - struct perf_evsel *tracking_evsel) + struct evsel *tracking_evsel) { - struct perf_evsel *evsel; + struct evsel *evsel; if (tracking_evsel->tracking) return; @@ -1702,11 +1702,11 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, tracking_evsel->tracking = true; } -struct perf_evsel * +struct evsel * perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (!evsel->name) @@ -1778,7 +1778,7 @@ void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, bool perf_evlist__exclude_kernel(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (!evsel->attr.exclude_kernel) @@ -1796,17 +1796,17 @@ bool perf_evlist__exclude_kernel(struct perf_evlist *evlist) void perf_evlist__force_leader(struct perf_evlist *evlist) { if (!evlist->nr_groups) { - struct perf_evsel *leader = perf_evlist__first(evlist); + struct evsel *leader = perf_evlist__first(evlist); perf_evlist__set_leader(evlist); leader->forced_leader = true; } } -struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, - struct perf_evsel *evsel) +struct evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, + struct evsel *evsel) { - struct perf_evsel *c2, *leader; + struct evsel *c2, *leader; bool is_open = true; leader = evsel->leader; @@ -1835,7 +1835,7 @@ int perf_evlist__add_sb_event(struct perf_evlist **evlist, perf_evsel__sb_cb_t cb, void *data) { - struct perf_evsel *evsel; + struct evsel *evsel; bool new_evlist = (*evlist) == NULL; if (*evlist == NULL) @@ -1887,7 +1887,7 @@ static void *perf_evlist__poll_thread(void *arg) if (perf_mmap__read_init(map)) continue; while ((event = perf_mmap__read_event(map)) != NULL) { - struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); + struct evsel *evsel = perf_evlist__event2evsel(evlist, event); if (evsel && evsel->side_band.cb) evsel->side_band.cb(event, evsel->side_band.data); @@ -1909,7 +1909,7 @@ static void *perf_evlist__poll_thread(void *arg) int perf_evlist__start_sb_thread(struct perf_evlist *evlist, struct target *target) { - struct perf_evsel *counter; + struct evsel *counter; if (!evlist) return 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index ab2f0b6c7640..576d59a0d8cf 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -46,7 +46,7 @@ struct perf_evlist { struct perf_mmap *overwrite_mmap; struct perf_thread_map *threads; struct perf_cpu_map *cpus; - struct perf_evsel *selected; + struct evsel *selected; struct events_stats stats; struct perf_env *env; void (*trace_event_sample_raw)(struct perf_evlist *evlist, @@ -60,7 +60,7 @@ struct perf_evlist { } thread; }; -struct perf_evsel_str_handler { +struct evsel_str_handler { const char *name; void *handler; }; @@ -73,8 +73,8 @@ void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, void perf_evlist__exit(struct perf_evlist *evlist); void perf_evlist__delete(struct perf_evlist *evlist); -void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); -void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); +void perf_evlist__add(struct perf_evlist *evlist, struct evsel *entry); +void perf_evlist__remove(struct perf_evlist *evlist, struct evsel *evsel); int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise); @@ -117,17 +117,17 @@ int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter); int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid); int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids); -struct perf_evsel * +struct evsel * perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); -struct perf_evsel * +struct evsel * perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, const char *name); -void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, +void perf_evlist__id_add(struct perf_evlist *evlist, struct evsel *evsel, int cpu, int thread, u64 id); int perf_evlist__id_add_fd(struct perf_evlist *evlist, - struct perf_evsel *evsel, + struct evsel *evsel, int cpu, int thread, int fd); int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); @@ -136,8 +136,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas int perf_evlist__poll(struct perf_evlist *evlist, int timeout); -struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); -struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, +struct evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); +struct evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, u64 id); struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); @@ -189,15 +189,15 @@ void perf_evlist__enable(struct perf_evlist *evlist); void perf_evlist__toggle_enable(struct perf_evlist *evlist); int perf_evlist__enable_event_idx(struct perf_evlist *evlist, - struct perf_evsel *evsel, int idx); + struct evsel *evsel, int idx); void perf_evlist__set_selected(struct perf_evlist *evlist, - struct perf_evsel *evsel); + struct evsel *evsel); void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads); int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); -int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); +int perf_evlist__apply_filters(struct perf_evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct perf_evlist *evlist); @@ -228,14 +228,14 @@ static inline bool perf_evlist__empty(struct perf_evlist *evlist) return list_empty(&evlist->entries); } -static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) +static inline struct evsel *perf_evlist__first(struct perf_evlist *evlist) { - return list_entry(evlist->entries.next, struct perf_evsel, node); + return list_entry(evlist->entries.next, struct evsel, node); } -static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) +static inline struct evsel *perf_evlist__last(struct perf_evlist *evlist) { - return list_entry(evlist->entries.prev, struct perf_evsel, node); + return list_entry(evlist->entries.prev, struct evsel, node); } size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); @@ -245,7 +245,7 @@ int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, s bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str); void perf_evlist__to_front(struct perf_evlist *evlist, - struct perf_evsel *move_evsel); + struct evsel *move_evsel); /** * __evlist__for_each_entry - iterate thru all the evsels @@ -314,18 +314,18 @@ void perf_evlist__to_front(struct perf_evlist *evlist, __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel) void perf_evlist__set_tracking_event(struct perf_evlist *evlist, - struct perf_evsel *tracking_evsel); + struct evsel *tracking_evsel); -struct perf_evsel * +struct evsel * perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); -struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, +struct evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, union perf_event *event); bool perf_evlist__exclude_kernel(struct perf_evlist *evlist); void perf_evlist__force_leader(struct perf_evlist *evlist); -struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evlist, - struct perf_evsel *evsel); +struct evsel *perf_evlist__reset_weak_group(struct perf_evlist *evlist, + struct evsel *evsel); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ab66d65b7968..44421bbebd64 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -45,30 +45,30 @@ struct perf_missing_features perf_missing_features; static clockid_t clockid; -static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) +static int perf_evsel__no_extra_init(struct evsel *evsel __maybe_unused) { return 0; } void __weak test_attr__ready(void) { } -static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused) +static void perf_evsel__no_extra_fini(struct evsel *evsel __maybe_unused) { } static struct { size_t size; - int (*init)(struct perf_evsel *evsel); - void (*fini)(struct perf_evsel *evsel); + int (*init)(struct evsel *evsel); + void (*fini)(struct evsel *evsel); } perf_evsel__object = { - .size = sizeof(struct perf_evsel), + .size = sizeof(struct evsel), .init = perf_evsel__no_extra_init, .fini = perf_evsel__no_extra_fini, }; int perf_evsel__object_config(size_t object_size, - int (*init)(struct perf_evsel *evsel), - void (*fini)(struct perf_evsel *evsel)) + int (*init)(struct evsel *evsel), + void (*fini)(struct evsel *evsel)) { if (object_size == 0) @@ -167,13 +167,13 @@ static int __perf_evsel__calc_is_pos(u64 sample_type) return idx; } -void perf_evsel__calc_id_pos(struct perf_evsel *evsel) +void perf_evsel__calc_id_pos(struct evsel *evsel) { evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type); evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); } -void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, +void __perf_evsel__set_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit) { if (!(evsel->attr.sample_type & bit)) { @@ -183,7 +183,7 @@ void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, } } -void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, +void __perf_evsel__reset_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit) { if (evsel->attr.sample_type & bit) { @@ -193,7 +193,7 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, } } -void perf_evsel__set_sample_id(struct perf_evsel *evsel, +void perf_evsel__set_sample_id(struct evsel *evsel, bool can_sample_identifier) { if (can_sample_identifier) { @@ -213,7 +213,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel, * * Return %true if event is function trace event */ -bool perf_evsel__is_function_event(struct perf_evsel *evsel) +bool perf_evsel__is_function_event(struct evsel *evsel) { #define FUNCTION_EVENT "ftrace:function" @@ -223,7 +223,7 @@ bool perf_evsel__is_function_event(struct perf_evsel *evsel) #undef FUNCTION_EVENT } -void perf_evsel__init(struct perf_evsel *evsel, +void perf_evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx) { evsel->idx = idx; @@ -249,9 +249,9 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->pmu_name = NULL; } -struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) +struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) { - struct perf_evsel *evsel = zalloc(perf_evsel__object.size); + struct evsel *evsel = zalloc(perf_evsel__object.size); if (!evsel) return NULL; @@ -282,14 +282,14 @@ static bool perf_event_can_profile_kernel(void) return geteuid() == 0 || perf_event_paranoid() == -1; } -struct perf_evsel *perf_evsel__new_cycles(bool precise) +struct evsel *perf_evsel__new_cycles(bool precise) { struct perf_event_attr attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, .exclude_kernel = !perf_event_can_profile_kernel(), }; - struct perf_evsel *evsel; + struct evsel *evsel; event_attr_init(&attr); @@ -324,9 +324,9 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise) /* * Returns pointer with encoded error via interface. */ -struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) +struct evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) { - struct perf_evsel *evsel = zalloc(perf_evsel__object.size); + struct evsel *evsel = zalloc(perf_evsel__object.size); int err = -ENOMEM; if (evsel == NULL) { @@ -383,7 +383,7 @@ static const char *__perf_evsel__hw_name(u64 config) return "unknown-hardware"; } -static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size) { int colon = 0, r = 0; struct perf_event_attr *attr = &evsel->attr; @@ -419,7 +419,7 @@ static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t return r; } -static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__hw_name(struct evsel *evsel, char *bf, size_t size) { int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); @@ -445,7 +445,7 @@ static const char *__perf_evsel__sw_name(u64 config) return "unknown-software"; } -static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__sw_name(struct evsel *evsel, char *bf, size_t size) { int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); @@ -469,7 +469,7 @@ static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) return r; } -static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__bp_name(struct evsel *evsel, char *bf, size_t size) { struct perf_event_attr *attr = &evsel->attr; int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); @@ -569,13 +569,13 @@ static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) return scnprintf(bf, size, "%s", err); } -static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__hw_cache_name(struct evsel *evsel, char *bf, size_t size) { int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); } -static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size) +static int perf_evsel__raw_name(struct evsel *evsel, char *bf, size_t size) { int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); @@ -587,7 +587,7 @@ static int perf_evsel__tool_name(char *bf, size_t size) return ret; } -const char *perf_evsel__name(struct perf_evsel *evsel) +const char *perf_evsel__name(struct evsel *evsel) { char bf[128]; @@ -639,7 +639,7 @@ const char *perf_evsel__name(struct perf_evsel *evsel) return "unknown"; } -const char *perf_evsel__group_name(struct perf_evsel *evsel) +const char *perf_evsel__group_name(struct evsel *evsel) { return evsel->group_name ?: "anon group"; } @@ -654,10 +654,10 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel) * For record -e 'cycles,instructions' and report --group * 'cycles:u, instructions:u' */ -int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) +int perf_evsel__group_desc(struct evsel *evsel, char *buf, size_t size) { int ret = 0; - struct perf_evsel *pos; + struct evsel *pos; const char *group_name = perf_evsel__group_name(evsel); if (!evsel->forced_leader) @@ -676,7 +676,7 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) return ret; } -static void __perf_evsel__config_callchain(struct perf_evsel *evsel, +static void __perf_evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, struct callchain_param *param) { @@ -735,7 +735,7 @@ static void __perf_evsel__config_callchain(struct perf_evsel *evsel, } } -void perf_evsel__config_callchain(struct perf_evsel *evsel, +void perf_evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, struct callchain_param *param) { @@ -744,7 +744,7 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel, } static void -perf_evsel__reset_callgraph(struct perf_evsel *evsel, +perf_evsel__reset_callgraph(struct evsel *evsel, struct callchain_param *param) { struct perf_event_attr *attr = &evsel->attr; @@ -761,7 +761,7 @@ perf_evsel__reset_callgraph(struct perf_evsel *evsel, } } -static void apply_config_terms(struct perf_evsel *evsel, +static void apply_config_terms(struct evsel *evsel, struct record_opts *opts, bool track) { struct perf_evsel_config_term *term; @@ -886,7 +886,7 @@ static void apply_config_terms(struct perf_evsel *evsel, } } -static bool is_dummy_event(struct perf_evsel *evsel) +static bool is_dummy_event(struct evsel *evsel) { return (evsel->attr.type == PERF_TYPE_SOFTWARE) && (evsel->attr.config == PERF_COUNT_SW_DUMMY); @@ -920,10 +920,10 @@ static bool is_dummy_event(struct perf_evsel *evsel) * enable/disable events specifically, as there's no * initial traced exec call. */ -void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, +void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, struct callchain_param *callchain) { - struct perf_evsel *leader = evsel->leader; + struct evsel *leader = evsel->leader; struct perf_event_attr *attr = &evsel->attr; int track = evsel->tracking; bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; @@ -1153,7 +1153,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); } -static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) +static int perf_evsel__alloc_fd(struct evsel *evsel, int ncpus, int nthreads) { evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); @@ -1169,7 +1169,7 @@ static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthread return evsel->fd != NULL ? 0 : -ENOMEM; } -static int perf_evsel__run_ioctl(struct perf_evsel *evsel, +static int perf_evsel__run_ioctl(struct evsel *evsel, int ioc, void *arg) { int cpu, thread; @@ -1187,14 +1187,14 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, return 0; } -int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter) +int perf_evsel__apply_filter(struct evsel *evsel, const char *filter) { return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_SET_FILTER, (void *)filter); } -int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter) +int perf_evsel__set_filter(struct evsel *evsel, const char *filter) { char *new_filter = strdup(filter); @@ -1207,7 +1207,7 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter) return -1; } -static int perf_evsel__append_filter(struct perf_evsel *evsel, +static int perf_evsel__append_filter(struct evsel *evsel, const char *fmt, const char *filter) { char *new_filter; @@ -1224,17 +1224,17 @@ static int perf_evsel__append_filter(struct perf_evsel *evsel, return -1; } -int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter) +int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter) { return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter); } -int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter) +int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter) { return perf_evsel__append_filter(evsel, "%s,%s", filter); } -int perf_evsel__enable(struct perf_evsel *evsel) +int perf_evsel__enable(struct evsel *evsel) { int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0); @@ -1244,7 +1244,7 @@ int perf_evsel__enable(struct perf_evsel *evsel) return err; } -int perf_evsel__disable(struct perf_evsel *evsel) +int perf_evsel__disable(struct evsel *evsel) { int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0); /* @@ -1259,7 +1259,7 @@ int perf_evsel__disable(struct perf_evsel *evsel) return err; } -int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) +int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads) { if (ncpus == 0 || nthreads == 0) return 0; @@ -1281,13 +1281,13 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) return 0; } -static void perf_evsel__free_fd(struct perf_evsel *evsel) +static void perf_evsel__free_fd(struct evsel *evsel) { xyarray__delete(evsel->fd); evsel->fd = NULL; } -static void perf_evsel__free_id(struct perf_evsel *evsel) +static void perf_evsel__free_id(struct evsel *evsel) { xyarray__delete(evsel->sample_id); evsel->sample_id = NULL; @@ -1295,7 +1295,7 @@ static void perf_evsel__free_id(struct perf_evsel *evsel) evsel->ids = 0; } -static void perf_evsel__free_config_terms(struct perf_evsel *evsel) +static void perf_evsel__free_config_terms(struct evsel *evsel) { struct perf_evsel_config_term *term, *h; @@ -1305,7 +1305,7 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel) } } -void perf_evsel__close_fd(struct perf_evsel *evsel) +void perf_evsel__close_fd(struct evsel *evsel) { int cpu, thread; @@ -1316,7 +1316,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel) } } -void perf_evsel__exit(struct perf_evsel *evsel) +void perf_evsel__exit(struct evsel *evsel) { assert(list_empty(&evsel->node)); assert(evsel->evlist == NULL); @@ -1333,13 +1333,13 @@ void perf_evsel__exit(struct perf_evsel *evsel) perf_evsel__object.fini(evsel); } -void perf_evsel__delete(struct perf_evsel *evsel) +void perf_evsel__delete(struct evsel *evsel) { perf_evsel__exit(evsel); free(evsel); } -void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, +void perf_evsel__compute_deltas(struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { struct perf_counts_values tmp; @@ -1379,7 +1379,7 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } -static int perf_evsel__read_size(struct perf_evsel *evsel) +static int perf_evsel__read_size(struct evsel *evsel) { u64 read_format = evsel->attr.read_format; int entry = sizeof(u64); /* value */ @@ -1404,7 +1404,7 @@ static int perf_evsel__read_size(struct perf_evsel *evsel) return size; } -int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, +int perf_evsel__read(struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { size_t size = perf_evsel__read_size(evsel); @@ -1421,7 +1421,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, } static int -perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread) +perf_evsel__read_one(struct evsel *evsel, int cpu, int thread) { struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread); @@ -1429,7 +1429,7 @@ perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread) } static void -perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, +perf_evsel__set_count(struct evsel *counter, int cpu, int thread, u64 val, u64 ena, u64 run) { struct perf_counts_values *count; @@ -1444,7 +1444,7 @@ perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, } static int -perf_evsel__process_group_data(struct perf_evsel *leader, +perf_evsel__process_group_data(struct evsel *leader, int cpu, int thread, u64 *data) { u64 read_format = leader->attr.read_format; @@ -1468,7 +1468,7 @@ perf_evsel__process_group_data(struct perf_evsel *leader, v[0].value, ena, run); for (i = 1; i < nr; i++) { - struct perf_evsel *counter; + struct evsel *counter; counter = perf_evlist__id2evsel(leader->evlist, v[i].id); if (!counter) @@ -1482,7 +1482,7 @@ perf_evsel__process_group_data(struct perf_evsel *leader, } static int -perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread) +perf_evsel__read_group(struct evsel *leader, int cpu, int thread) { struct perf_stat_evsel *ps = leader->stats; u64 read_format = leader->attr.read_format; @@ -1512,7 +1512,7 @@ perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread) return perf_evsel__process_group_data(leader, cpu, thread, data); } -int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread) +int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread) { u64 read_format = evsel->attr.read_format; @@ -1522,7 +1522,7 @@ int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread) return perf_evsel__read_one(evsel, cpu, thread); } -int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, +int __perf_evsel__read_on_cpu(struct evsel *evsel, int cpu, int thread, bool scale) { struct perf_counts_values count; @@ -1543,9 +1543,9 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, return 0; } -static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) +static int get_group_fd(struct evsel *evsel, int cpu, int thread) { - struct perf_evsel *leader = evsel->leader; + struct evsel *leader = evsel->leader; int fd; if (perf_evsel__is_group_leader(evsel)) @@ -1708,7 +1708,7 @@ static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, return fprintf(fp, " %-32s %s\n", name, val); } -static void perf_evsel__remove_fd(struct perf_evsel *pos, +static void perf_evsel__remove_fd(struct evsel *pos, int nr_cpus, int nr_threads, int thread_idx) { @@ -1717,11 +1717,11 @@ static void perf_evsel__remove_fd(struct perf_evsel *pos, FD(pos, cpu, thread) = FD(pos, cpu, thread + 1); } -static int update_fds(struct perf_evsel *evsel, +static int update_fds(struct evsel *evsel, int nr_cpus, int cpu_idx, int nr_threads, int thread_idx) { - struct perf_evsel *pos; + struct evsel *pos; if (cpu_idx >= nr_cpus || thread_idx >= nr_threads) return -EINVAL; @@ -1741,7 +1741,7 @@ static int update_fds(struct perf_evsel *evsel, return 0; } -static bool ignore_missing_thread(struct perf_evsel *evsel, +static bool ignore_missing_thread(struct evsel *evsel, int nr_cpus, int cpu, struct perf_thread_map *threads, int thread, int err) @@ -1788,7 +1788,7 @@ static void display_attr(struct perf_event_attr *attr) } } -static int perf_event_open(struct perf_evsel *evsel, +static int perf_event_open(struct evsel *evsel, pid_t pid, int cpu, int group_fd, unsigned long flags) { @@ -1825,7 +1825,7 @@ static int perf_event_open(struct perf_evsel *evsel, return fd; } -int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, +int perf_evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads) { int cpu, thread, nthreads; @@ -2073,7 +2073,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, return err; } -void perf_evsel__close(struct perf_evsel *evsel) +void perf_evsel__close(struct evsel *evsel) { if (evsel->fd == NULL) return; @@ -2083,19 +2083,19 @@ void perf_evsel__close(struct perf_evsel *evsel) perf_evsel__free_id(evsel); } -int perf_evsel__open_per_cpu(struct perf_evsel *evsel, +int perf_evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus) { return perf_evsel__open(evsel, cpus, NULL); } -int perf_evsel__open_per_thread(struct perf_evsel *evsel, +int perf_evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads) { return perf_evsel__open(evsel, NULL, threads); } -static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, +static int perf_evsel__parse_id_sample(const struct evsel *evsel, const union perf_event *event, struct perf_sample *sample) { @@ -2185,7 +2185,7 @@ perf_event__check_size(union perf_event *event, unsigned int sample_size) return 0; } -int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, +int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, struct perf_sample *data) { u64 type = evsel->attr.sample_type; @@ -2464,7 +2464,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, return 0; } -int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel, +int perf_evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, u64 *timestamp) { @@ -2785,12 +2785,12 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, return 0; } -struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) +struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name) { return tep_find_field(evsel->tp_format, name); } -void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, +void *perf_evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name) { struct tep_format_field *field = perf_evsel__field(evsel, name); @@ -2848,7 +2848,7 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam return 0; } -u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, +u64 perf_evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name) { struct tep_format_field *field = perf_evsel__field(evsel, name); @@ -2859,7 +2859,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; } -bool perf_evsel__fallback(struct perf_evsel *evsel, int err, +bool perf_evsel__fallback(struct evsel *evsel, int err, char *msg, size_t msgsize) { int paranoid; @@ -2946,7 +2946,7 @@ static bool find_process(const char *name) return ret ? false : true; } -int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, +int perf_evsel__open_strerror(struct evsel *evsel, struct target *target, int err, char *msg, size_t size) { char sbuf[STRERR_BUFSIZE]; @@ -3037,14 +3037,14 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, perf_evsel__name(evsel)); } -struct perf_env *perf_evsel__env(struct perf_evsel *evsel) +struct perf_env *perf_evsel__env(struct evsel *evsel) { if (evsel && evsel->evlist) return evsel->evlist->env; return NULL; } -static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) +static int store_evsel_ids(struct evsel *evsel, struct perf_evlist *evlist) { int cpu, thread; @@ -3062,7 +3062,7 @@ static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) return 0; } -int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist) +int perf_evsel__store_ids(struct evsel *evsel, struct perf_evlist *evlist) { struct perf_cpu_map *cpus = evsel->cpus; struct perf_thread_map *threads = evsel->threads; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index ba2385f22e28..2c31c5e99524 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -12,7 +12,7 @@ #include "cpumap.h" #include "counts.h" -struct perf_evsel; +struct evsel; /* * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are @@ -21,7 +21,7 @@ struct perf_evsel; struct perf_sample_id { struct hlist_node node; u64 id; - struct perf_evsel *evsel; + struct evsel *evsel; int idx; int cpu; pid_t tid; @@ -84,7 +84,7 @@ enum perf_tool_event { struct bpf_object; -/** struct perf_evsel - event selector +/** struct evsel - event selector * * @evlist - evlist this evsel is in, if it is in one. * @node - To insert it into evlist->entries or in other list_heads, say in @@ -100,7 +100,7 @@ struct bpf_object; * is used there is an id sample appended to non-sample events * @priv: And what is in its containing unnamed union are tool specific */ -struct perf_evsel { +struct evsel { struct list_head node; struct perf_evlist *evlist; struct perf_event_attr attr; @@ -150,7 +150,7 @@ struct perf_evsel { int nr_members; int sample_read; unsigned long *per_pkg_mask; - struct perf_evsel *leader; + struct evsel *leader; char *group_name; bool cmdline_group_boundary; struct list_head config_terms; @@ -160,7 +160,7 @@ struct perf_evsel { bool merged_stat; const char * metric_expr; const char * metric_name; - struct perf_evsel **metric_events; + struct evsel **metric_events; bool collect_stat; bool weak_group; bool percore; @@ -197,12 +197,12 @@ struct target; struct thread_map; struct record_opts; -static inline struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) +static inline struct perf_cpu_map *perf_evsel__cpus(struct evsel *evsel) { return evsel->cpus; } -static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) +static inline int perf_evsel__nr_cpus(struct evsel *evsel) { return perf_evsel__cpus(evsel)->nr; } @@ -210,50 +210,50 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) void perf_counts_values__scale(struct perf_counts_values *count, bool scale, s8 *pscaled); -void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, +void perf_evsel__compute_deltas(struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count); int perf_evsel__object_config(size_t object_size, - int (*init)(struct perf_evsel *evsel), - void (*fini)(struct perf_evsel *evsel)); + int (*init)(struct evsel *evsel), + void (*fini)(struct evsel *evsel)); -struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); +struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); -static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) +static inline struct evsel *perf_evsel__new(struct perf_event_attr *attr) { return perf_evsel__new_idx(attr, 0); } -struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); +struct evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); /* * Returns pointer with encoded error via interface. */ -static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) +static inline struct evsel *perf_evsel__newtp(const char *sys, const char *name) { return perf_evsel__newtp_idx(sys, name, 0); } -struct perf_evsel *perf_evsel__new_cycles(bool precise); +struct evsel *perf_evsel__new_cycles(bool precise); struct tep_event *event_format__new(const char *sys, const char *name); -void perf_evsel__init(struct perf_evsel *evsel, +void perf_evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx); -void perf_evsel__exit(struct perf_evsel *evsel); -void perf_evsel__delete(struct perf_evsel *evsel); +void perf_evsel__exit(struct evsel *evsel); +void perf_evsel__delete(struct evsel *evsel); struct callchain_param; -void perf_evsel__config(struct perf_evsel *evsel, +void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, struct callchain_param *callchain); -void perf_evsel__config_callchain(struct perf_evsel *evsel, +void perf_evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, struct callchain_param *callchain); int __perf_evsel__sample_size(u64 sample_type); -void perf_evsel__calc_id_pos(struct perf_evsel *evsel); +void perf_evsel__calc_id_pos(struct evsel *evsel); bool perf_evsel__is_cache_op_valid(u8 type, u8 op); @@ -269,17 +269,17 @@ extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX]; extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size); -const char *perf_evsel__name(struct perf_evsel *evsel); +const char *perf_evsel__name(struct evsel *evsel); -const char *perf_evsel__group_name(struct perf_evsel *evsel); -int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); +const char *perf_evsel__group_name(struct evsel *evsel); +int perf_evsel__group_desc(struct evsel *evsel, char *buf, size_t size); -int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); -void perf_evsel__close_fd(struct perf_evsel *evsel); +int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads); +void perf_evsel__close_fd(struct evsel *evsel); -void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, +void __perf_evsel__set_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit); -void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, +void __perf_evsel__reset_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit); #define perf_evsel__set_sample_bit(evsel, bit) \ @@ -288,33 +288,33 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, #define perf_evsel__reset_sample_bit(evsel, bit) \ __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit) -void perf_evsel__set_sample_id(struct perf_evsel *evsel, +void perf_evsel__set_sample_id(struct evsel *evsel, bool use_sample_identifier); -int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter); -int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter); -int perf_evsel__append_addr_filter(struct perf_evsel *evsel, +int perf_evsel__set_filter(struct evsel *evsel, const char *filter); +int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter); +int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter); -int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter); -int perf_evsel__enable(struct perf_evsel *evsel); -int perf_evsel__disable(struct perf_evsel *evsel); +int perf_evsel__apply_filter(struct evsel *evsel, const char *filter); +int perf_evsel__enable(struct evsel *evsel); +int perf_evsel__disable(struct evsel *evsel); -int perf_evsel__open_per_cpu(struct perf_evsel *evsel, +int perf_evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus); -int perf_evsel__open_per_thread(struct perf_evsel *evsel, +int perf_evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads); -int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, +int perf_evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads); -void perf_evsel__close(struct perf_evsel *evsel); +void perf_evsel__close(struct evsel *evsel); struct perf_sample; -void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, +void *perf_evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name); -u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, +u64 perf_evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name); -static inline char *perf_evsel__strval(struct perf_evsel *evsel, +static inline char *perf_evsel__strval(struct evsel *evsel, struct perf_sample *sample, const char *name) { @@ -325,14 +325,14 @@ struct tep_format_field; u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap); -struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); +struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name); #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ evsel->attr.config == PERF_COUNT_##c) -static inline bool perf_evsel__match2(struct perf_evsel *e1, - struct perf_evsel *e2) +static inline bool perf_evsel__match2(struct evsel *e1, + struct evsel *e2) { return (e1->attr.type == e2->attr.type) && (e1->attr.config == e2->attr.config); @@ -344,12 +344,12 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (a)->attr.type == (b)->attr.type && \ (a)->attr.config == (b)->attr.config) -int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, +int perf_evsel__read(struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count); -int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread); +int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread); -int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, +int __perf_evsel__read_on_cpu(struct evsel *evsel, int cpu, int thread, bool scale); /** @@ -359,7 +359,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, * @cpu - CPU of interest * @thread - thread of interest */ -static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel, +static inline int perf_evsel__read_on_cpu(struct evsel *evsel, int cpu, int thread) { return __perf_evsel__read_on_cpu(evsel, cpu, thread, false); @@ -372,27 +372,27 @@ static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel, * @cpu - CPU of interest * @thread - thread of interest */ -static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel, +static inline int perf_evsel__read_on_cpu_scaled(struct evsel *evsel, int cpu, int thread) { return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); } -int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, +int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, struct perf_sample *sample); -int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel, +int perf_evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, u64 *timestamp); -static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) +static inline struct evsel *perf_evsel__next(struct evsel *evsel) { - return list_entry(evsel->node.next, struct perf_evsel, node); + return list_entry(evsel->node.next, struct evsel, node); } -static inline struct perf_evsel *perf_evsel__prev(struct perf_evsel *evsel) +static inline struct evsel *perf_evsel__prev(struct evsel *evsel) { - return list_entry(evsel->node.prev, struct perf_evsel, node); + return list_entry(evsel->node.prev, struct evsel, node); } /** @@ -402,7 +402,7 @@ static inline struct perf_evsel *perf_evsel__prev(struct perf_evsel *evsel) * * Return %true if @evsel is a group leader or a stand-alone event */ -static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel) +static inline bool perf_evsel__is_group_leader(const struct evsel *evsel) { return evsel->leader == evsel; } @@ -415,7 +415,7 @@ static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel) * Return %true iff event group view is enabled and @evsel is a actual group * leader which has other members in the group */ -static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel) +static inline bool perf_evsel__is_group_event(struct evsel *evsel) { if (!symbol_conf.event_group) return false; @@ -423,14 +423,14 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel) return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; } -bool perf_evsel__is_function_event(struct perf_evsel *evsel); +bool perf_evsel__is_function_event(struct evsel *evsel); -static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) +static inline bool perf_evsel__is_bpf_output(struct evsel *evsel) { return perf_evsel__match(evsel, SOFTWARE, SW_BPF_OUTPUT); } -static inline bool perf_evsel__is_clock(struct perf_evsel *evsel) +static inline bool perf_evsel__is_clock(struct evsel *evsel) { return perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK); @@ -444,7 +444,7 @@ struct perf_attr_details { bool trace_fields; }; -int perf_evsel__fprintf(struct perf_evsel *evsel, +int perf_evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE *fp); #define EVSEL__PRINT_IP (1<<0) @@ -467,34 +467,34 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, int left_alignment, unsigned int print_opts, struct callchain_cursor *cursor, FILE *fp); -bool perf_evsel__fallback(struct perf_evsel *evsel, int err, +bool perf_evsel__fallback(struct evsel *evsel, int err, char *msg, size_t msgsize); -int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, +int perf_evsel__open_strerror(struct evsel *evsel, struct target *target, int err, char *msg, size_t size); -static inline int perf_evsel__group_idx(struct perf_evsel *evsel) +static inline int perf_evsel__group_idx(struct evsel *evsel) { return evsel->idx - evsel->leader->idx; } /* Iterates group WITHOUT the leader. */ #define for_each_group_member(_evsel, _leader) \ -for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ +for ((_evsel) = list_entry((_leader)->node.next, struct evsel, node); \ (_evsel) && (_evsel)->leader == (_leader); \ - (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) + (_evsel) = list_entry((_evsel)->node.next, struct evsel, node)) /* Iterates group WITH the leader. */ #define for_each_group_evsel(_evsel, _leader) \ for ((_evsel) = _leader; \ (_evsel) && (_evsel)->leader == (_leader); \ - (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) + (_evsel) = list_entry((_evsel)->node.next, struct evsel, node)) -static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel) +static inline bool perf_evsel__has_branch_callstack(const struct evsel *evsel) { return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; } -static inline bool evsel__has_callchain(const struct perf_evsel *evsel) +static inline bool evsel__has_callchain(const struct evsel *evsel) { return (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0; } @@ -504,7 +504,7 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, attr__fprintf_f attr__fprintf, void *priv); -struct perf_env *perf_evsel__env(struct perf_evsel *evsel); +struct perf_env *perf_evsel__env(struct evsel *evsel); -int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist); +int perf_evsel__store_ids(struct evsel *evsel, struct perf_evlist *evlist); #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 95ea147f9e18..1fddb7da4b51 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -33,14 +33,14 @@ static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, vo return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val); } -int perf_evsel__fprintf(struct perf_evsel *evsel, +int perf_evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE *fp) { bool first = true; int printed = 0; if (details->event_group) { - struct perf_evsel *pos; + struct evsel *pos; if (!perf_evsel__is_group_leader(evsel)) return 0; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4be216f3598b..132bbc29f977 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -74,7 +74,7 @@ struct feat_fd { void *buf; /* Either buf != NULL or fd >= 0 */ ssize_t offset; size_t size; - struct perf_evsel *events; + struct evsel *events; }; void perf_header__set_feat(struct perf_header *header, int feat) @@ -472,7 +472,7 @@ static int write_nrcpus(struct feat_fd *ff, static int write_event_desc(struct feat_fd *ff, struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; u32 nre, nri, sz; int ret; @@ -762,7 +762,7 @@ static int write_group_desc(struct feat_fd *ff, struct perf_evlist *evlist) { u32 nr_groups = evlist->nr_groups; - struct perf_evsel *evsel; + struct evsel *evsel; int ret; ret = do_write(ff, &nr_groups, sizeof(nr_groups)); @@ -1568,9 +1568,9 @@ static void print_bpf_btf(struct feat_fd *ff, FILE *fp) up_read(&env->bpf_progs.lock); } -static void free_event_desc(struct perf_evsel *events) +static void free_event_desc(struct evsel *events) { - struct perf_evsel *evsel; + struct evsel *evsel; if (!events) return; @@ -1583,9 +1583,9 @@ static void free_event_desc(struct perf_evsel *events) free(events); } -static struct perf_evsel *read_event_desc(struct feat_fd *ff) +static struct evsel *read_event_desc(struct feat_fd *ff) { - struct perf_evsel *evsel, *events = NULL; + struct evsel *evsel, *events = NULL; u64 *id; void *buf = NULL; u32 nre, sz, nr, i, j; @@ -1669,7 +1669,7 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, static void print_event_desc(struct feat_fd *ff, FILE *fp) { - struct perf_evsel *evsel, *events; + struct evsel *evsel, *events; u32 j; u64 *id; @@ -1804,7 +1804,7 @@ static void print_pmu_mappings(struct feat_fd *ff, FILE *fp) static void print_group_desc(struct feat_fd *ff, FILE *fp) { struct perf_session *session; - struct perf_evsel *evsel; + struct evsel *evsel; u32 nr = 0; session = container_of(ff->ph, struct perf_session, header); @@ -2089,10 +2089,10 @@ static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused) return 0; } -static struct perf_evsel * +static struct evsel * perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->idx == idx) @@ -2104,9 +2104,9 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) static void perf_evlist__set_event_name(struct perf_evlist *evlist, - struct perf_evsel *event) + struct evsel *event) { - struct perf_evsel *evsel; + struct evsel *evsel; if (!event->name) return; @@ -2125,7 +2125,7 @@ static int process_event_desc(struct feat_fd *ff, void *data __maybe_unused) { struct perf_session *session; - struct perf_evsel *evsel, *events = read_event_desc(ff); + struct evsel *evsel, *events = read_event_desc(ff); if (!events) return 0; @@ -2415,7 +2415,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused) size_t ret = -1; u32 i, nr, nr_groups; struct perf_session *session; - struct perf_evsel *evsel, *leader = NULL; + struct evsel *evsel, *leader = NULL; struct group_desc { char *name; u32 leader_idx; @@ -3050,7 +3050,7 @@ int perf_session__write_header(struct perf_session *session, struct perf_file_header f_header; struct perf_file_attr f_attr; struct perf_header *header = &session->header; - struct perf_evsel *evsel; + struct evsel *evsel; struct feat_fd ff; u64 attr_offset; int err; @@ -3479,7 +3479,7 @@ static int read_attr(int fd, struct perf_header *ph, return ret <= 0 ? -1 : 0; } -static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, +static int perf_evsel__prepare_tracepoint_event(struct evsel *evsel, struct tep_handle *pevent) { struct tep_event *event; @@ -3514,7 +3514,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, struct tep_handle *pevent) { - struct perf_evsel *pos; + struct evsel *pos; evlist__for_each_entry(evlist, pos) { if (pos->attr.type == PERF_TYPE_TRACEPOINT && @@ -3570,7 +3570,7 @@ int perf_session__read_header(struct perf_session *session) lseek(fd, f_header.attrs.offset, SEEK_SET); for (i = 0; i < nr_attrs; i++) { - struct perf_evsel *evsel; + struct evsel *evsel; off_t tmp; if (read_attr(fd, header, &f_attr) < 0) @@ -3794,7 +3794,7 @@ event_update_event__new(size_t size, u64 type, u64 id) int perf_event__synthesize_event_update_unit(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process) { struct event_update_event *ev; @@ -3813,7 +3813,7 @@ perf_event__synthesize_event_update_unit(struct perf_tool *tool, int perf_event__synthesize_event_update_scale(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process) { struct event_update_event *ev; @@ -3833,7 +3833,7 @@ perf_event__synthesize_event_update_scale(struct perf_tool *tool, int perf_event__synthesize_event_update_name(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process) { struct event_update_event *ev; @@ -3852,7 +3852,7 @@ perf_event__synthesize_event_update_name(struct perf_tool *tool, int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process) { size_t size = sizeof(struct event_update_event); @@ -3924,7 +3924,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_evlist *evlist, perf_event__handler_t process) { - struct perf_evsel *evsel; + struct evsel *evsel; int err = 0; evlist__for_each_entry(evlist, evsel) { @@ -3939,12 +3939,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, return err; } -static bool has_unit(struct perf_evsel *counter) +static bool has_unit(struct evsel *counter) { return counter->unit && *counter->unit; } -static bool has_scale(struct perf_evsel *counter) +static bool has_scale(struct evsel *counter) { return counter->scale != 1; } @@ -3954,7 +3954,7 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool, perf_event__handler_t process, bool is_pipe) { - struct perf_evsel *counter; + struct evsel *counter; int err; /* @@ -4012,7 +4012,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, struct perf_evlist **pevlist) { u32 i, ids, n_ids; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_evlist *evlist = *pevlist; if (evlist == NULL) { @@ -4053,7 +4053,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, struct event_update_event_scale *ev_scale; struct event_update_event_cpus *ev_cpus; struct perf_evlist *evlist; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_cpu_map *map; if (!pevlist || *pevlist == NULL) diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 5b3abe4172e2..437d8617de27 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -135,16 +135,16 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_event_update_unit(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_scale(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_name(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, - struct perf_evsel *evsel, + struct evsel *evsel, perf_event__handler_t process); int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f24fd1954f6c..3da49c479880 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -816,7 +816,7 @@ static int iter_finish_mem_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) { - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct hists *hists = evsel__hists(evsel); struct hist_entry *he = iter->he; int err = -EINVAL; @@ -886,7 +886,7 @@ static int iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) { struct branch_info *bi; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct hists *hists = evsel__hists(evsel); struct perf_sample *sample = iter->sample; struct hist_entry *he = NULL; @@ -938,7 +938,7 @@ iter_prepare_normal_entry(struct hist_entry_iter *iter __maybe_unused, static int iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; struct hist_entry *he; @@ -956,7 +956,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) { struct hist_entry *he = iter->he; - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; if (he == NULL) @@ -996,7 +996,7 @@ static int iter_add_single_cumulative_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct hists *hists = evsel__hists(evsel); struct perf_sample *sample = iter->sample; struct hist_entry **he_cache = iter->priv; @@ -1041,7 +1041,7 @@ static int iter_add_next_cumulative_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct perf_evsel *evsel = iter->evsel; + struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; struct hist_entry **he_cache = iter->priv; struct hist_entry *he; @@ -1873,7 +1873,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog, } } -void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress *prog, +void perf_evsel__output_resort_cb(struct evsel *evsel, struct ui_progress *prog, hists__resort_cb_t cb, void *cb_arg) { bool use_callchain; @@ -1888,7 +1888,7 @@ void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress * output_resort(evsel__hists(evsel), prog, use_callchain, cb, cb_arg); } -void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog) +void perf_evsel__output_resort(struct evsel *evsel, struct ui_progress *prog) { return perf_evsel__output_resort_cb(evsel, prog, NULL, NULL); } @@ -2575,7 +2575,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp) { - struct perf_evsel *pos; + struct evsel *pos; size_t ret = 0; evlist__for_each_entry(evlist, pos) { @@ -2602,7 +2602,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh int socket_id = hists->socket_filter; unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists->stats.total_period; - struct perf_evsel *evsel = hists_to_evsel(hists); + struct evsel *evsel = hists_to_evsel(hists); const char *ev_name = perf_evsel__name(evsel); char buf[512], sample_freq_str[64] = ""; size_t buflen = sizeof(buf); @@ -2615,7 +2615,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh } if (perf_evsel__is_group_event(evsel)) { - struct perf_evsel *pos; + struct evsel *pos; perf_evsel__group_desc(evsel, buf, buflen); ev_name = buf; @@ -2731,7 +2731,7 @@ static void hists__delete_all_entries(struct hists *hists) hists__delete_remaining_entries(&hists->entries_collapsed); } -static void hists_evsel__exit(struct perf_evsel *evsel) +static void hists_evsel__exit(struct evsel *evsel) { struct hists *hists = evsel__hists(evsel); struct perf_hpp_fmt *fmt, *pos; @@ -2749,7 +2749,7 @@ static void hists_evsel__exit(struct perf_evsel *evsel) } } -static int hists_evsel__init(struct perf_evsel *evsel) +static int hists_evsel__init(struct evsel *evsel) { struct hists *hists = evsel__hists(evsel); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 24635f36148d..9bf247c638b8 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -116,7 +116,7 @@ struct hist_entry_iter { bool hide_unresolved; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_sample *sample; struct hist_entry *he; struct symbol *parent; @@ -171,9 +171,9 @@ void hist_entry__delete(struct hist_entry *he); typedef int (*hists__resort_cb_t)(struct hist_entry *he, void *arg); -void perf_evsel__output_resort_cb(struct perf_evsel *evsel, struct ui_progress *prog, +void perf_evsel__output_resort_cb(struct evsel *evsel, struct ui_progress *prog, hists__resort_cb_t cb, void *cb_arg); -void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); +void perf_evsel__output_resort(struct evsel *evsel, struct ui_progress *prog); void hists__output_resort(struct hists *hists, struct ui_progress *prog); void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, hists__resort_cb_t cb); @@ -219,17 +219,17 @@ void hists__match(struct hists *leader, struct hists *other); int hists__link(struct hists *leader, struct hists *other); struct hists_evsel { - struct perf_evsel evsel; + struct evsel evsel; struct hists hists; }; -static inline struct perf_evsel *hists_to_evsel(struct hists *hists) +static inline struct evsel *hists_to_evsel(struct hists *hists) { struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists); return &hevsel->evsel; } -static inline struct hists *evsel__hists(struct perf_evsel *evsel) +static inline struct hists *evsel__hists(struct evsel *evsel) { struct hists_evsel *hevsel = (struct hists_evsel *)evsel; return &hevsel->hists; @@ -453,11 +453,11 @@ enum rstype { #include "../ui/keysyms.h" void attr_to_script(char *buf, struct perf_event_attr *attr); -int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, +int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *annotation_opts); -int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, +int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *annotation_opts); @@ -468,11 +468,11 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, bool warn_lost_event, struct annotation_options *annotation_options); -int script_browse(const char *script_opt, struct perf_evsel *evsel); +int script_browse(const char *script_opt, struct evsel *evsel); void run_script(char *cmd); int res_sample_browse(struct res_sample *res_samples, int num_res, - struct perf_evsel *evsel, enum rstype rstype); + struct evsel *evsel, enum rstype rstype); void res_sample_init(void); #else static inline @@ -487,7 +487,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, return 0; } static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, struct annotation_options *annotation_options __maybe_unused) { @@ -495,7 +495,7 @@ static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused, } static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, struct annotation_options *annotation_opts __maybe_unused) { @@ -503,14 +503,14 @@ static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, } static inline int script_browse(const char *script_opt __maybe_unused, - struct perf_evsel *evsel __maybe_unused) + struct evsel *evsel __maybe_unused) { return 0; } static inline int res_sample_browse(struct res_sample *res_samples __maybe_unused, int num_res __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, enum rstype rstype __maybe_unused) { return 0; diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 5560e95afdda..8fd46d5f4b39 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -761,7 +761,7 @@ static int intel_bts_synth_events(struct intel_bts *bts, struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr; bool found = false; u64 id; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index df061599fef4..f1595b86d7c7 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -56,7 +56,7 @@ struct intel_pt { u32 auxtrace_type; struct perf_session *session; struct machine *machine; - struct perf_evsel *switch_evsel; + struct evsel *switch_evsel; struct thread *unknown_thread; bool timeless_decoding; bool sampling_mode; @@ -104,7 +104,7 @@ struct intel_pt { u64 cbr_id; bool sample_pebs; - struct perf_evsel *pebs_evsel; + struct evsel *pebs_evsel; u64 tsc_bit; u64 mtc_bit; @@ -723,7 +723,7 @@ static bool intel_pt_get_config(struct intel_pt *pt, static bool intel_pt_exclude_kernel(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(pt->session->evlist, evsel) { if (intel_pt_get_config(pt, &evsel->attr, NULL) && @@ -735,7 +735,7 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt) static bool intel_pt_return_compression(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; u64 config; if (!pt->noretcomp_bit) @@ -751,7 +751,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt) static bool intel_pt_branch_enable(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; u64 config; evlist__for_each_entry(pt->session->evlist, evsel) { @@ -764,7 +764,7 @@ static bool intel_pt_branch_enable(struct intel_pt *pt) static unsigned int intel_pt_mtc_period(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; unsigned int shift; u64 config; @@ -783,7 +783,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt) static bool intel_pt_timeless_decoding(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; bool timeless_decoding = true; u64 config; @@ -805,7 +805,7 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt) static bool intel_pt_tracing_kernel(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(pt->session->evlist, evsel) { if (intel_pt_get_config(pt, &evsel->attr, NULL) && @@ -817,7 +817,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt) static bool intel_pt_have_tsc(struct intel_pt *pt) { - struct perf_evsel *evsel; + struct evsel *evsel; bool have_tsc = false; u64 config; @@ -1702,7 +1702,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq) struct perf_sample sample = { .ip = 0, }; union perf_event *event = ptq->event_buf; struct intel_pt *pt = ptq->pt; - struct perf_evsel *evsel = pt->pebs_evsel; + struct evsel *evsel = pt->pebs_evsel; u64 sample_type = evsel->attr.sample_type; u64 id = evsel->id[0]; u8 cpumode; @@ -2401,7 +2401,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid, static int intel_pt_process_switch(struct intel_pt *pt, struct perf_sample *sample) { - struct perf_evsel *evsel; + struct evsel *evsel; pid_t tid; int cpu, ret; @@ -2716,7 +2716,7 @@ static int intel_pt_synth_event(struct perf_session *session, const char *name, static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, const char *name) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->id && evsel->id[0] == id) { @@ -2728,10 +2728,10 @@ static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, } } -static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt, +static struct evsel *intel_pt_evsel(struct intel_pt *pt, struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type == pt->pmu_type && evsel->ids) @@ -2745,7 +2745,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, struct perf_session *session) { struct perf_evlist *evlist = session->evlist; - struct perf_evsel *evsel = intel_pt_evsel(pt, evlist); + struct evsel *evsel = intel_pt_evsel(pt, evlist); struct perf_event_attr attr; u64 id; int err; @@ -2894,9 +2894,9 @@ static int intel_pt_synth_events(struct intel_pt *pt, return 0; } -static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) +static struct evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry_reverse(evlist, evsel) { const char *name = perf_evsel__name(evsel); @@ -2910,7 +2910,7 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) static bool intel_pt_find_switch(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.context_switch) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 18c34f0c1966..8df60703411a 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -118,7 +118,7 @@ jit_close(struct jit_buf_desc *jd) static int jit_validate_events(struct perf_session *session) { - struct perf_evsel *evsel; + struct evsel *evsel; /* * check that all events use CLOCK_MONOTONIC @@ -758,7 +758,7 @@ jit_process(struct perf_session *session, pid_t pid, u64 *nbytes) { - struct perf_evsel *first; + struct evsel *first; struct jit_buf_desc jd; int ret; diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index 1403dec189b4..299edd32d3d4 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -6,7 +6,7 @@ #include "tool.h" #include "stat.h" -struct perf_evsel; +struct evsel; struct perf_evlist; struct perf_session; @@ -45,17 +45,17 @@ struct kvm_event_key { struct perf_kvm_stat; struct child_event_ops { - void (*get_key)(struct perf_evsel *evsel, + void (*get_key)(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); const char *name; }; struct kvm_events_ops { - bool (*is_begin_event)(struct perf_evsel *evsel, + bool (*is_begin_event)(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); - bool (*is_end_event)(struct perf_evsel *evsel, + bool (*is_end_event)(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); struct child_event_ops *child_ops; void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, @@ -109,21 +109,21 @@ struct kvm_reg_events_ops { struct kvm_events_ops *ops; }; -void exit_event_get_key(struct perf_evsel *evsel, +void exit_event_get_key(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); -bool exit_event_begin(struct perf_evsel *evsel, +bool exit_event_begin(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); -bool exit_event_end(struct perf_evsel *evsel, +bool exit_event_end(struct evsel *evsel, struct perf_sample *sample, struct event_key *key); void exit_event_decode_key(struct perf_kvm_stat *kvm, struct event_key *key, char *decode); -bool kvm_exit_event(struct perf_evsel *evsel); -bool kvm_entry_event(struct perf_evsel *evsel); +bool kvm_exit_event(struct evsel *evsel); +bool kvm_entry_event(struct evsel *evsel); int setup_kvm_events_tp(struct perf_kvm_stat *kvm); #define define_exit_reasons_table(name, symbols) \ diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a2359a33c748..ec0675b0caa8 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2287,7 +2287,7 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread, static int thread__resolve_callchain_sample(struct thread *thread, struct callchain_cursor *cursor, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, @@ -2493,7 +2493,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) static int thread__resolve_callchain_unwind(struct thread *thread, struct callchain_cursor *cursor, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, int max_stack) { @@ -2513,7 +2513,7 @@ static int thread__resolve_callchain_unwind(struct thread *thread, int thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 7f64016758e0..ef803f08ae12 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -11,7 +11,7 @@ struct addr_location; struct branch_stack; -struct perf_evsel; +struct evsel; struct perf_sample; struct symbol; struct thread; @@ -175,7 +175,7 @@ struct callchain_cursor; int thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, - struct perf_evsel *evsel, + struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index dc93787c74f0..c3614195ddc7 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -16,7 +16,7 @@ struct ip_callchain; struct ref_reloc_sym; struct map_groups; struct machine; -struct perf_evsel; +struct evsel; struct map { union { diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 416a9015405e..14c423974d63 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -21,7 +21,7 @@ #include struct metric_event *metricgroup__lookup(struct rblist *metric_events, - struct perf_evsel *evsel, + struct evsel *evsel, bool create) { struct rb_node *nd; @@ -86,10 +86,10 @@ struct egroup { const char *metric_expr; }; -static bool record_evsel(int *ind, struct perf_evsel **start, +static bool record_evsel(int *ind, struct evsel **start, int idnum, - struct perf_evsel **metric_events, - struct perf_evsel *ev) + struct evsel **metric_events, + struct evsel *ev) { metric_events[*ind] = ev; if (*ind == 0) @@ -101,12 +101,12 @@ static bool record_evsel(int *ind, struct perf_evsel **start, return false; } -static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, - const char **ids, - int idnum, - struct perf_evsel **metric_events) +static struct evsel *find_evsel_group(struct perf_evlist *perf_evlist, + const char **ids, + int idnum, + struct evsel **metric_events) { - struct perf_evsel *ev, *start = NULL; + struct evsel *ev, *start = NULL; int ind = 0; evlist__for_each_entry (perf_evlist, ev) { @@ -148,10 +148,10 @@ static int metricgroup__setup_events(struct list_head *groups, int i = 0; int ret = 0; struct egroup *eg; - struct perf_evsel *evsel; + struct evsel *evsel; list_for_each_entry (eg, groups, nd) { - struct perf_evsel **metric_events; + struct evsel **metric_events; metric_events = calloc(sizeof(void *), eg->idnum + 1); if (!metric_events) { diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 5c52097a5c63..500e828533f8 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -9,7 +9,7 @@ struct metric_event { struct rb_node nd; - struct perf_evsel *evsel; + struct evsel *evsel; struct list_head head; /* list of metric_expr */ }; @@ -17,11 +17,11 @@ struct metric_expr { struct list_head nd; const char *metric_expr; const char *metric_name; - struct perf_evsel **metric_events; + struct evsel **metric_events; }; struct metric_event *metricgroup__lookup(struct rblist *metric_events, - struct perf_evsel *evsel, + struct evsel *evsel, bool create); int metricgroup__parse_groups(const struct option *opt, const char *str, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 352c5198b453..dfde9cb31562 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -314,14 +314,14 @@ static char *get_config_name(struct list_head *head_terms) return NULL; } -static struct perf_evsel * +static struct evsel * __add_event(struct list_head *list, int *idx, struct perf_event_attr *attr, char *name, struct perf_pmu *pmu, struct list_head *config_terms, bool auto_merge_stats, const char *cpu_list) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_cpu_map *cpus = pmu ? pmu->cpus : cpu_list ? cpu_map__new(cpu_list) : NULL; @@ -357,7 +357,7 @@ static int add_event(struct list_head *list, int *idx, static int add_event_tool(struct list_head *list, int *idx, enum perf_tool_event tool_event) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_DUMMY, @@ -510,7 +510,7 @@ static int add_tracepoint(struct list_head *list, int *idx, struct parse_events_error *err, struct list_head *head_config) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); if (IS_ERR(evsel)) { @@ -637,7 +637,7 @@ static int add_bpf_event(const char *group, const char *event, int fd, struct bp struct __add_bpf_event_param *param = _param; struct parse_events_state *parse_state = param->parse_state; struct list_head *list = param->list; - struct perf_evsel *pos; + struct evsel *pos; int err; /* * Check if we should add the event, i.e. if it is a TP but starts with a '!', @@ -656,7 +656,7 @@ static int add_bpf_event(const char *group, const char *event, int fd, struct bp event, parse_state->error, param->head_config); if (err) { - struct perf_evsel *evsel, *tmp; + struct evsel *evsel, *tmp; pr_debug("Failed to add BPF event %s:%s\n", group, event); @@ -1306,7 +1306,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, struct perf_event_attr attr; struct perf_pmu_info info; struct perf_pmu *pmu; - struct perf_evsel *evsel; + struct evsel *evsel; struct parse_events_error *err = parse_state->error; bool use_uncore_alias; LIST_HEAD(config_terms); @@ -1453,13 +1453,13 @@ static int parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, struct parse_events_state *parse_state) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; uintptr_t *leaders; bool is_leader = true; int i, nr_pmu = 0, total_members, ret = 0; - leader = list_first_entry(list, struct perf_evsel, node); - evsel = list_last_entry(list, struct perf_evsel, node); + leader = list_first_entry(list, struct evsel, node); + evsel = list_last_entry(list, struct evsel, node); total_members = evsel->idx - leader->idx + 1; leaders = calloc(total_members, sizeof(uintptr_t)); @@ -1521,12 +1521,12 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, __evlist__for_each_entry(list, evsel) { if (i >= nr_pmu) i = 0; - evsel->leader = (struct perf_evsel *) leaders[i++]; + evsel->leader = (struct evsel *) leaders[i++]; } /* The number of members and group name are same for each group */ for (i = 0; i < nr_pmu; i++) { - evsel = (struct perf_evsel *) leaders[i]; + evsel = (struct evsel *) leaders[i]; evsel->nr_members = total_members / nr_pmu; evsel->group_name = name ? strdup(name) : NULL; } @@ -1544,7 +1544,7 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, void parse_events__set_leader(char *name, struct list_head *list, struct parse_events_state *parse_state) { - struct perf_evsel *leader; + struct evsel *leader; if (list_empty(list)) { WARN_ONCE(true, "WARNING: failed to set leader: empty list"); @@ -1555,7 +1555,7 @@ void parse_events__set_leader(char *name, struct list_head *list, return; __perf_evlist__set_leader(list); - leader = list_entry(list->next, struct perf_evsel, node); + leader = list_entry(list->next, struct evsel, node); leader->group_name = name ? strdup(name) : NULL; } @@ -1588,7 +1588,7 @@ struct event_modifier { }; static int get_event_modifier(struct event_modifier *mod, char *str, - struct perf_evsel *evsel) + struct evsel *evsel) { int eu = evsel ? evsel->attr.exclude_user : 0; int ek = evsel ? evsel->attr.exclude_kernel : 0; @@ -1701,7 +1701,7 @@ static int check_modifier(char *str) int parse_events__modifier_event(struct list_head *list, char *str, bool add) { - struct perf_evsel *evsel; + struct evsel *evsel; struct event_modifier mod; if (str == NULL) @@ -1738,7 +1738,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) int parse_events_name(struct list_head *list, char *name) { - struct perf_evsel *evsel; + struct evsel *evsel; __evlist__for_each_entry(list, evsel) { if (!evsel->name) @@ -1918,7 +1918,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS); perf_pmu__parse_cleanup(); if (!ret) { - struct perf_evsel *last; + struct evsel *last; if (list_empty(&parse_state.list)) { WARN_ONCE(true, "WARNING: event parser found nothing\n"); @@ -2027,11 +2027,11 @@ int parse_events_option(const struct option *opt, const char *str, static int foreach_evsel_in_last_glob(struct perf_evlist *evlist, - int (*func)(struct perf_evsel *evsel, + int (*func)(struct evsel *evsel, const void *arg), const void *arg) { - struct perf_evsel *last = NULL; + struct evsel *last = NULL; int err; /* @@ -2052,13 +2052,13 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist, if (last->node.prev == &evlist->entries) return 0; - last = list_entry(last->node.prev, struct perf_evsel, node); + last = list_entry(last->node.prev, struct evsel, node); } while (!last->cmdline_group_boundary); return 0; } -static int set_filter(struct perf_evsel *evsel, const void *arg) +static int set_filter(struct evsel *evsel, const void *arg) { const char *str = arg; bool found = false; @@ -2115,7 +2115,7 @@ int parse_filter(const struct option *opt, const char *str, (const void *)str); } -static int add_exclude_perf_filter(struct perf_evsel *evsel, +static int add_exclude_perf_filter(struct evsel *evsel, const void *arg __maybe_unused) { char new_filter[64]; @@ -2307,7 +2307,7 @@ static bool is_event_supported(u8 type, unsigned config) { bool ret = true; int open_return; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr = { .type = type, .config = config, diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index f7139e1a2fd3..99e206598b60 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -12,7 +12,7 @@ #include struct list_head; -struct perf_evsel; +struct evsel; struct perf_evlist; struct parse_events_error; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 62dda70227e5..beafbd469b0c 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -93,7 +93,7 @@ PyMODINIT_FUNC PyInit_perf(void); struct pyrf_event { PyObject_HEAD - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_sample sample; union perf_event event; }; @@ -383,7 +383,7 @@ static PyObject* get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) { const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); - struct perf_evsel *evsel = pevent->evsel; + struct evsel *evsel = pevent->evsel; struct tep_format_field *field; if (!evsel->tp_format) { @@ -674,7 +674,7 @@ static int pyrf_thread_map__setup_types(void) struct pyrf_evsel { PyObject_HEAD - struct perf_evsel evsel; + struct evsel evsel; }; static int pyrf_evsel__init(struct pyrf_evsel *pevsel, @@ -795,7 +795,7 @@ static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, PyObject *args, PyObject *kwargs) { - struct perf_evsel *evsel = &pevsel->evsel; + struct evsel *evsel = &pevsel->evsel; struct perf_cpu_map *cpus = NULL; struct perf_thread_map *threads = NULL; PyObject *pcpus = NULL, *pthreads = NULL; @@ -966,7 +966,7 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, { struct perf_evlist *evlist = &pevlist->evlist; PyObject *pevsel; - struct perf_evsel *evsel; + struct evsel *evsel; if (!PyArg_ParseTuple(args, "O", &pevsel)) return NULL; @@ -1018,7 +1018,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, if (event != NULL) { PyObject *pyevent = pyrf_event__new(event); struct pyrf_event *pevent = (struct pyrf_event *)pyevent; - struct perf_evsel *evsel; + struct evsel *evsel; if (pyevent == NULL) return PyErr_NoMemory(); @@ -1118,7 +1118,7 @@ static Py_ssize_t pyrf_evlist__length(PyObject *obj) static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) { struct pyrf_evlist *pevlist = (void *)obj; - struct perf_evsel *pos; + struct evsel *pos; if (i >= pevlist->evlist.nr_entries) return NULL; diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 051c67f82548..ef8f686729fd 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -9,12 +9,12 @@ #include "util.h" #include "cloexec.h" -typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); +typedef void (*setup_probe_fn_t)(struct evsel *evsel); static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) { struct perf_evlist *evlist; - struct perf_evsel *evsel; + struct evsel *evsel; unsigned long flags = perf_event_open_cloexec_flag(); int err = -EAGAIN, fd; static pid_t pid = -1; @@ -78,17 +78,17 @@ static bool perf_probe_api(setup_probe_fn_t fn) return false; } -static void perf_probe_sample_identifier(struct perf_evsel *evsel) +static void perf_probe_sample_identifier(struct evsel *evsel) { evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; } -static void perf_probe_comm_exec(struct perf_evsel *evsel) +static void perf_probe_comm_exec(struct evsel *evsel) { evsel->attr.comm_exec = 1; } -static void perf_probe_context_switch(struct perf_evsel *evsel) +static void perf_probe_context_switch(struct evsel *evsel) { evsel->attr.context_switch = 1; } @@ -135,7 +135,7 @@ bool perf_can_record_cpu_wide(void) void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, struct callchain_param *callchain) { - struct perf_evsel *evsel; + struct evsel *evsel; bool use_sample_identifier = false; bool use_comm_exec; bool sample_id = opts->sample_id; @@ -167,7 +167,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, use_sample_identifier = perf_can_sample_identifier(); sample_id = true; } else if (evlist->nr_entries > 1) { - struct perf_evsel *first = perf_evlist__first(evlist); + struct evsel *first = perf_evlist__first(evlist); evlist__for_each_entry(evlist, evsel) { if (evsel->attr.sample_type == first->attr.sample_type) @@ -259,7 +259,7 @@ int record_opts__config(struct record_opts *opts) bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) { struct perf_evlist *temp_evlist; - struct perf_evsel *evsel; + struct evsel *evsel; int err, fd, cpu; bool ret = false; pid_t pid = -1; diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c index 83d2e149ef19..59d78a9fe703 100644 --- a/tools/perf/util/s390-cpumsf.c +++ b/tools/perf/util/s390-cpumsf.c @@ -918,7 +918,7 @@ s390_cpumsf_process_event(struct perf_session *session, struct s390_cpumsf, auxtrace); u64 timestamp = sample->time; - struct perf_evsel *ev_bc000; + struct evsel *ev_bc000; int err = 0; diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 6650f599ed9c..159a08220947 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -203,7 +203,7 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample) void perf_evlist__s390_sample_raw(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample) { - struct perf_evsel *ev_bc000; + struct evsel *ev_bc000; if (event->header.type != PERF_RECORD_SAMPLE) return; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 61aa7f3df915..98dcdb9a79a4 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -258,7 +258,7 @@ static void define_event_symbols(struct tep_event *event, } static SV *perl_process_callchain(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { AV *list; @@ -336,7 +336,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, } static void perl_process_tracepoint(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { struct thread *thread = al->thread; @@ -431,7 +431,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { dSP; @@ -455,7 +455,7 @@ static void perl_process_event_generic(union perf_event *event, static void perl_process_event(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { perl_process_tracepoint(sample, evsel, al); diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 0a7e662036b4..106aec31c07c 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -392,7 +392,7 @@ static const char *get_dsoname(struct map *map) } static PyObject *python_process_callchain(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { PyObject *pylist; @@ -634,7 +634,7 @@ static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) static void set_sample_read_in_dict(PyObject *dict_sample, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { u64 read_format = evsel->attr.read_format; PyObject *values; @@ -705,7 +705,7 @@ static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size) static void set_regs_in_dict(PyObject *dict, struct perf_sample *sample, - struct perf_evsel *evsel) + struct evsel *evsel) { struct perf_event_attr *attr = &evsel->attr; char bf[512]; @@ -722,7 +722,7 @@ static void set_regs_in_dict(PyObject *dict, } static PyObject *get_perf_sample_dict(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al, PyObject *callchain) { @@ -790,7 +790,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, } static void python_process_tracepoint(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { struct tep_event *event = evsel->tp_format; @@ -955,7 +955,7 @@ static int tuple_set_bytes(PyObject *t, unsigned int pos, void *bytes, return PyTuple_SetItem(t, pos, _PyBytes_FromStringAndSize(bytes, sz)); } -static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) +static int python_export_evsel(struct db_export *dbe, struct evsel *evsel) { struct tables *tables = container_of(dbe, struct tables, dbe); PyObject *t; @@ -1275,7 +1275,7 @@ static int python_process_call_return(struct call_return *cr, u64 *parent_db_id, } static void python_process_general_event(struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { PyObject *handler, *t, *dict, *callchain; @@ -1311,7 +1311,7 @@ static void python_process_general_event(struct perf_sample *sample, static void python_process_event(union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al) { struct tables *tables = &tables_global; @@ -1340,7 +1340,7 @@ static void python_process_switch(union perf_event *event, } static void get_handler_name(char *str, size_t size, - struct perf_evsel *evsel) + struct evsel *evsel) { char *p = str; @@ -1353,7 +1353,7 @@ static void get_handler_name(char *str, size_t size, } static void -process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, +process_stat(struct evsel *counter, int cpu, int thread, u64 tstamp, struct perf_counts_values *count) { PyObject *handler, *t; @@ -1390,7 +1390,7 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, } static void python_process_stat(struct perf_stat_config *config, - struct perf_evsel *counter, u64 tstamp) + struct evsel *counter, u64 tstamp) { struct perf_thread_map *threads = counter->threads; struct perf_cpu_map *cpus = counter->cpus; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 69d1d158a610..e9d1cf8eb274 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -151,7 +151,7 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session) static bool perf_session__has_comm_exec(struct perf_session *session) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(session->evlist, evsel) { if (evsel->attr.comm_exec) @@ -322,7 +322,7 @@ static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_ static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { dump_printf(": unhandled!\n"); @@ -1033,7 +1033,7 @@ static void callchain__lbr_callstack_printf(struct perf_sample *sample) } } -static void callchain__printf(struct perf_evsel *evsel, +static void callchain__printf(struct evsel *evsel, struct perf_sample *sample) { unsigned int i; @@ -1198,7 +1198,7 @@ static void dump_event(struct perf_evlist *evlist, union perf_event *event, event->header.size, perf_event__name(event->header.type)); } -static void dump_sample(struct perf_evsel *evsel, union perf_event *event, +static void dump_sample(struct evsel *evsel, union perf_event *event, struct perf_sample *sample) { u64 sample_type; @@ -1243,7 +1243,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, sample_read__printf(sample, evsel->attr.read_format); } -static void dump_read(struct perf_evsel *evsel, union perf_event *event) +static void dump_read(struct evsel *evsel, union perf_event *event) { struct read_event *read_event = &event->read; u64 read_format; @@ -1351,7 +1351,7 @@ static int struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct machine *machine) { /* We know evsel != NULL. */ @@ -1377,7 +1377,7 @@ static int machines__deliver_event(struct machines *machines, struct perf_sample *sample, struct perf_tool *tool, u64 file_offset) { - struct perf_evsel *evsel; + struct evsel *evsel; struct machine *machine; dump_event(evlist, event, file_offset, sample); @@ -1705,7 +1705,7 @@ static void perf_session__warn_order(const struct perf_session *session) { const struct ordered_events *oe = &session->ordered_events; - struct perf_evsel *evsel; + struct evsel *evsel; bool should_warn = true; evlist__for_each_entry(session->evlist, evsel) { @@ -2183,7 +2183,7 @@ int perf_session__process_events(struct perf_session *session) bool perf_session__has_traces(struct perf_session *session, const char *msg) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(session->evlist, evsel) { if (evsel->attr.type == PERF_TYPE_TRACEPOINT) @@ -2257,10 +2257,10 @@ size_t perf_session__fprintf(struct perf_session *session, FILE *fp) return machine__fprintf(&session->machines.host, fp); } -struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, +struct evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type) { - struct perf_evsel *pos; + struct evsel *pos; evlist__for_each_entry(session->evlist, pos) { if (pos->attr.type == type) @@ -2276,7 +2276,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, struct perf_cpu_map *map; for (i = 0; i < PERF_TYPE_MAX; ++i) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = perf_session__find_first_evtype(session, i); if (!evsel) @@ -2327,10 +2327,10 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp, int __perf_session__set_tracepoints_handlers(struct perf_session *session, - const struct perf_evsel_str_handler *assocs, + const struct evsel_str_handler *assocs, size_t nr_assocs) { - struct perf_evsel *evsel; + struct evsel *evsel; size_t i; int err; @@ -2397,7 +2397,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, struct machine *machine) { union perf_event *ev; - struct perf_evsel *evsel; + struct evsel *evsel; size_t nr = 0, i = 0, sz, max_nr, n; int err; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 863dbad87849..2b2427c4c0b9 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -73,7 +73,7 @@ int perf_session__queue_event(struct perf_session *s, union perf_event *event, void perf_tool__fill_defaults(struct perf_tool *tool); int perf_session__resolve_callchain(struct perf_session *session, - struct perf_evsel *evsel, + struct evsel *evsel, struct thread *thread, struct ip_callchain *chain, struct symbol **parent); @@ -110,7 +110,7 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); -struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, +struct evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); int perf_session__cpu_bitmap(struct perf_session *session, @@ -118,10 +118,10 @@ int perf_session__cpu_bitmap(struct perf_session *session, void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full); -struct perf_evsel_str_handler; +struct evsel_str_handler; int __perf_session__set_tracepoints_handlers(struct perf_session *session, - const struct perf_evsel_str_handler *assocs, + const struct evsel_str_handler *assocs, size_t nr_assocs); #define perf_session__set_tracepoints_handlers(session, array) \ diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5d2518e89fc4..133d3a45997f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -698,7 +698,7 @@ struct sort_entry sort_time = { static char *get_trace_output(struct hist_entry *he) { struct trace_seq seq; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_record rec = { .data = he->raw_data, .size = he->raw_size, @@ -723,7 +723,7 @@ static char *get_trace_output(struct hist_entry *he) static int64_t sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = hists_to_evsel(left->hists); if (evsel->attr.type != PERF_TYPE_TRACEPOINT) @@ -740,7 +740,7 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = hists_to_evsel(he->hists); if (evsel->attr.type != PERF_TYPE_TRACEPOINT) @@ -1984,7 +1984,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd, struct hpp_dynamic_entry { struct perf_hpp_fmt hpp; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; unsigned dynamic_len; bool raw_trace; @@ -2218,7 +2218,7 @@ static void hde_free(struct perf_hpp_fmt *fmt) } static struct hpp_dynamic_entry * -__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field, +__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field, int level) { struct hpp_dynamic_entry *hde; @@ -2313,10 +2313,10 @@ static int parse_field_name(char *str, char **event, char **field, char **opt) * 2. full event name (e.g. sched:sched_switch) * 3. partial event name (should not contain ':') */ -static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name) +static struct evsel *find_evsel(struct perf_evlist *evlist, char *event_name) { - struct perf_evsel *evsel = NULL; - struct perf_evsel *pos; + struct evsel *evsel = NULL; + struct evsel *pos; bool full_name; /* case 1 */ @@ -2352,7 +2352,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam return evsel; } -static int __dynamic_dimension__add(struct perf_evsel *evsel, +static int __dynamic_dimension__add(struct evsel *evsel, struct tep_format_field *field, bool raw_trace, int level) { @@ -2368,7 +2368,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel, return 0; } -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) +static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level) { int ret; struct tep_format_field *field; @@ -2388,7 +2388,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, int level) { int ret; - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (evsel->attr.type != PERF_TYPE_TRACEPOINT) @@ -2405,7 +2405,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist, char *field_name, bool raw_trace, int level) { int ret = -ESRCH; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; evlist__for_each_entry(evlist, evsel) { @@ -2427,7 +2427,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, int level) { char *str, *event_name, *field_name, *opt_name; - struct perf_evsel *evsel; + struct evsel *evsel; struct tep_format_field *field; bool raw_trace = symbol_conf.raw_trace; int ret = 0; @@ -2720,7 +2720,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) default_tracepoint_sort_order, }; bool use_trace = true; - struct perf_evsel *evsel; + struct evsel *evsel; BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 58df6a0dbb9f..8da4ddcb2e44 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -45,7 +45,7 @@ static void print_noise_pct(struct perf_stat_config *config, } static void print_noise(struct perf_stat_config *config, - struct perf_evsel *evsel, double avg) + struct evsel *evsel, double avg) { struct perf_stat_evsel *ps; @@ -56,7 +56,7 @@ static void print_noise(struct perf_stat_config *config, print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); } -static void print_cgroup(struct perf_stat_config *config, struct perf_evsel *evsel) +static void print_cgroup(struct perf_stat_config *config, struct evsel *evsel) { if (nr_cgroups) { const char *cgrp_name = evsel->cgrp ? evsel->cgrp->name : ""; @@ -66,7 +66,7 @@ static void print_cgroup(struct perf_stat_config *config, struct perf_evsel *evs static void aggr_printout(struct perf_stat_config *config, - struct perf_evsel *evsel, int id, int nr) + struct evsel *evsel, int id, int nr) { switch (config->aggr_mode) { case AGGR_CORE: @@ -134,7 +134,7 @@ struct outstate { const char *prefix; int nfields; int id, nr; - struct perf_evsel *evsel; + struct evsel *evsel; }; #define METRIC_LEN 35 @@ -233,7 +233,7 @@ static bool valid_only_metric(const char *unit) return true; } -static const char *fixunit(char *buf, struct perf_evsel *evsel, +static const char *fixunit(char *buf, struct evsel *evsel, const char *unit) { if (!strncmp(unit, "of all", 6)) { @@ -310,7 +310,7 @@ static void print_metric_header(struct perf_stat_config *config, } static int first_shadow_cpu(struct perf_stat_config *config, - struct perf_evsel *evsel, int id) + struct evsel *evsel, int id) { struct perf_evlist *evlist = evsel->evlist; int i; @@ -334,7 +334,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, } static void abs_printout(struct perf_stat_config *config, - int id, int nr, struct perf_evsel *evsel, double avg) + int id, int nr, struct evsel *evsel, double avg) { FILE *output = config->output; double sc = evsel->scale; @@ -363,11 +363,11 @@ static void abs_printout(struct perf_stat_config *config, print_cgroup(config, evsel); } -static bool is_mixed_hw_group(struct perf_evsel *counter) +static bool is_mixed_hw_group(struct evsel *counter) { struct perf_evlist *evlist = counter->evlist; u32 pmu_type = counter->attr.type; - struct perf_evsel *pos; + struct evsel *pos; if (counter->nr_members < 2) return false; @@ -388,7 +388,7 @@ static bool is_mixed_hw_group(struct perf_evsel *counter) } static void printout(struct perf_stat_config *config, int id, int nr, - struct perf_evsel *counter, double uval, + struct evsel *counter, double uval, char *prefix, u64 run, u64 ena, double noise, struct runtime_stat *st) { @@ -493,7 +493,7 @@ static void aggr_update_shadow(struct perf_stat_config *config, { int cpu, s2, id, s; u64 val; - struct perf_evsel *counter; + struct evsel *counter; for (s = 0; s < config->aggr_map->nr; s++) { id = config->aggr_map->map[s]; @@ -512,7 +512,7 @@ static void aggr_update_shadow(struct perf_stat_config *config, } } -static void uniquify_event_name(struct perf_evsel *counter) +static void uniquify_event_name(struct evsel *counter) { char *new_name; char *config; @@ -540,13 +540,13 @@ static void uniquify_event_name(struct perf_evsel *counter) counter->uniquified_name = true; } -static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter, - void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, +static void collect_all_aliases(struct perf_stat_config *config, struct evsel *counter, + void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data, bool first), void *data) { struct perf_evlist *evlist = counter->evlist; - struct perf_evsel *alias; + struct evsel *alias; alias = list_prepare_entry(counter, &(evlist->entries), node); list_for_each_entry_continue (alias, &evlist->entries, node) { @@ -562,8 +562,8 @@ static void collect_all_aliases(struct perf_stat_config *config, struct perf_evs } } -static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter, - void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data, +static bool collect_data(struct perf_stat_config *config, struct evsel *counter, + void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data, bool first), void *data) { @@ -585,7 +585,7 @@ struct aggr_data { }; static void aggr_cb(struct perf_stat_config *config, - struct perf_evsel *counter, void *data, bool first) + struct evsel *counter, void *data, bool first) { struct aggr_data *ad = data; int cpu, s2; @@ -616,7 +616,7 @@ static void aggr_cb(struct perf_stat_config *config, } static void print_counter_aggrdata(struct perf_stat_config *config, - struct perf_evsel *counter, int s, + struct evsel *counter, int s, char *prefix, bool metric_only, bool *first) { @@ -656,7 +656,7 @@ static void print_aggr(struct perf_stat_config *config, { bool metric_only = config->metric_only; FILE *output = config->output; - struct perf_evsel *counter; + struct evsel *counter; int s; bool first; @@ -691,7 +691,7 @@ static int cmp_val(const void *a, const void *b) } static struct perf_aggr_thread_value *sort_aggr_thread( - struct perf_evsel *counter, + struct evsel *counter, int nthreads, int ncpus, int *ret, struct target *_target) @@ -741,7 +741,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread( static void print_aggr_thread(struct perf_stat_config *config, struct target *_target, - struct perf_evsel *counter, char *prefix) + struct evsel *counter, char *prefix) { FILE *output = config->output; int nthreads = thread_map__nr(counter->threads); @@ -779,7 +779,7 @@ struct caggr_data { }; static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused, - struct perf_evsel *counter, void *data, + struct evsel *counter, void *data, bool first __maybe_unused) { struct caggr_data *cd = data; @@ -795,7 +795,7 @@ static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused, * aggregated counts in system-wide mode */ static void print_counter_aggr(struct perf_stat_config *config, - struct perf_evsel *counter, char *prefix) + struct evsel *counter, char *prefix) { bool metric_only = config->metric_only; FILE *output = config->output; @@ -816,7 +816,7 @@ static void print_counter_aggr(struct perf_stat_config *config, } static void counter_cb(struct perf_stat_config *config __maybe_unused, - struct perf_evsel *counter, void *data, + struct evsel *counter, void *data, bool first __maybe_unused) { struct aggr_data *ad = data; @@ -831,7 +831,7 @@ static void counter_cb(struct perf_stat_config *config __maybe_unused, * does not use aggregated count in system-wide */ static void print_counter(struct perf_stat_config *config, - struct perf_evsel *counter, char *prefix) + struct evsel *counter, char *prefix) { FILE *output = config->output; u64 ena, run, val; @@ -864,7 +864,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config, { int cpu; int nrcpus = 0; - struct perf_evsel *counter; + struct evsel *counter; u64 ena, run, val; double uval; @@ -914,7 +914,7 @@ static void print_metric_headers(struct perf_stat_config *config, const char *prefix, bool no_indent) { struct perf_stat_output_ctx out; - struct perf_evsel *counter; + struct evsel *counter; struct outstate os = { .fh = config->output }; @@ -1132,7 +1132,7 @@ static void print_footer(struct perf_stat_config *config) } static void print_percore(struct perf_stat_config *config, - struct perf_evsel *counter, char *prefix) + struct evsel *counter, char *prefix) { bool metric_only = config->metric_only; FILE *output = config->output; @@ -1164,7 +1164,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, { bool metric_only = config->metric_only; int interval = config->interval; - struct perf_evsel *counter; + struct evsel *counter; char buf[64], *prefix = NULL; if (interval) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index accb1bf1cfd8..8c19f3149f34 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -25,7 +25,7 @@ struct stats walltime_nsecs_stats; struct saved_value { struct rb_node rb_node; - struct perf_evsel *evsel; + struct evsel *evsel; enum stat_type type; int ctx; int cpu; @@ -94,7 +94,7 @@ static void saved_value_delete(struct rblist *rblist __maybe_unused, free(v); } -static struct saved_value *saved_value_lookup(struct perf_evsel *evsel, +static struct saved_value *saved_value_lookup(struct evsel *evsel, int cpu, bool create, enum stat_type type, @@ -146,7 +146,7 @@ void perf_stat__init_shadow_stats(void) runtime_stat__init(&rt_stat); } -static int evsel_context(struct perf_evsel *evsel) +static int evsel_context(struct evsel *evsel) { int ctx = 0; @@ -207,7 +207,7 @@ static void update_runtime_stat(struct runtime_stat *st, * more semantic information such as miss/hit ratios, * instruction rates, etc: */ -void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, +void perf_stat__update_shadow_stats(struct evsel *counter, u64 count, int cpu, struct runtime_stat *st) { int ctx = evsel_context(counter); @@ -299,10 +299,10 @@ static const char *get_ratio_color(enum grc_type type, double ratio) return color; } -static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list, +static struct evsel *perf_stat__find_event(struct perf_evlist *evsel_list, const char *name) { - struct perf_evsel *c2; + struct evsel *c2; evlist__for_each_entry (evsel_list, c2) { if (!strcasecmp(c2->name, name) && !c2->collect_stat) @@ -314,7 +314,7 @@ static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list, /* Mark MetricExpr target events and link events using them to them. */ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) { - struct perf_evsel *counter, *leader, **metric_events, *oc; + struct evsel *counter, *leader, **metric_events, *oc; bool found; const char **metric_names; int i; @@ -332,7 +332,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) &metric_names, &num_metric_names) < 0) continue; - metric_events = calloc(sizeof(struct perf_evsel *), + metric_events = calloc(sizeof(struct evsel *), num_metric_names + 1); if (!metric_events) return; @@ -415,7 +415,7 @@ static double runtime_stat_n(struct runtime_stat *st, static void print_stalled_cycles_frontend(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, double avg, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) { @@ -439,7 +439,7 @@ static void print_stalled_cycles_frontend(struct perf_stat_config *config, static void print_stalled_cycles_backend(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, double avg, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) { @@ -459,7 +459,7 @@ static void print_stalled_cycles_backend(struct perf_stat_config *config, static void print_branch_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -480,7 +480,7 @@ static void print_branch_misses(struct perf_stat_config *config, static void print_l1_dcache_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -502,7 +502,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config, static void print_l1_icache_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -523,7 +523,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config, static void print_dtlb_cache_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -543,7 +543,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config, static void print_itlb_cache_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -563,7 +563,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config, static void print_ll_cache_misses(struct perf_stat_config *config, int cpu, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, struct perf_stat_output_ctx *out, struct runtime_stat *st) @@ -686,7 +686,7 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st) } static void print_smi_cost(struct perf_stat_config *config, - int cpu, struct perf_evsel *evsel, + int cpu, struct evsel *evsel, struct perf_stat_output_ctx *out, struct runtime_stat *st) { @@ -712,7 +712,7 @@ static void print_smi_cost(struct perf_stat_config *config, static void generic_metric(struct perf_stat_config *config, const char *metric_expr, - struct perf_evsel **metric_events, + struct evsel **metric_events, char *name, const char *metric_name, double avg, @@ -780,7 +780,7 @@ static void generic_metric(struct perf_stat_config *config, } void perf_stat__print_shadow_stats(struct perf_stat_config *config, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, int cpu, struct perf_stat_output_ctx *out, struct rblist *metric_events, diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 62791c063f7a..7acb9a6730fe 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -68,7 +68,7 @@ double rel_stddev_stats(double stddev, double avg) return pct; } -bool __perf_evsel_stat__is(struct perf_evsel *evsel, +bool __perf_evsel_stat__is(struct evsel *evsel, enum perf_stat_evsel_id id) { struct perf_stat_evsel *ps = evsel->stats; @@ -93,7 +93,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = { }; #undef ID -static void perf_stat_evsel_id_init(struct perf_evsel *evsel) +static void perf_stat_evsel_id_init(struct evsel *evsel) { struct perf_stat_evsel *ps = evsel->stats; int i; @@ -108,7 +108,7 @@ static void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } -static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) +static void perf_evsel__reset_stat_priv(struct evsel *evsel) { int i; struct perf_stat_evsel *ps = evsel->stats; @@ -119,7 +119,7 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) perf_stat_evsel_id_init(evsel); } -static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) +static int perf_evsel__alloc_stat_priv(struct evsel *evsel) { evsel->stats = zalloc(sizeof(struct perf_stat_evsel)); if (evsel->stats == NULL) @@ -128,7 +128,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) return 0; } -static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) +static void perf_evsel__free_stat_priv(struct evsel *evsel) { struct perf_stat_evsel *ps = evsel->stats; @@ -137,7 +137,7 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) zfree(&evsel->stats); } -static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, +static int perf_evsel__alloc_prev_raw_counts(struct evsel *evsel, int ncpus, int nthreads) { struct perf_counts *counts; @@ -149,13 +149,13 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, return counts ? 0 : -ENOMEM; } -static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) +static void perf_evsel__free_prev_raw_counts(struct evsel *evsel) { perf_counts__delete(evsel->prev_raw_counts); evsel->prev_raw_counts = NULL; } -static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) +static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw) { int ncpus = perf_evsel__nr_cpus(evsel); int nthreads = thread_map__nr(evsel->threads); @@ -170,7 +170,7 @@ static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { if (perf_evsel__alloc_stats(evsel, alloc_raw)) @@ -186,7 +186,7 @@ int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) void perf_evlist__free_stats(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { perf_evsel__free_stat_priv(evsel); @@ -197,7 +197,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist) void perf_evlist__reset_stats(struct perf_evlist *evlist) { - struct perf_evsel *evsel; + struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { perf_evsel__reset_stat_priv(evsel); @@ -205,13 +205,13 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist) } } -static void zero_per_pkg(struct perf_evsel *counter) +static void zero_per_pkg(struct evsel *counter) { if (counter->per_pkg_mask) memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); } -static int check_per_pkg(struct perf_evsel *counter, +static int check_per_pkg(struct evsel *counter, struct perf_counts_values *vals, int cpu, bool *skip) { unsigned long *mask = counter->per_pkg_mask; @@ -254,7 +254,7 @@ static int check_per_pkg(struct perf_evsel *counter, } static int -process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel, +process_counter_values(struct perf_stat_config *config, struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { @@ -306,7 +306,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel } static int process_counter_maps(struct perf_stat_config *config, - struct perf_evsel *counter) + struct evsel *counter) { int nthreads = thread_map__nr(counter->threads); int ncpus = perf_evsel__nr_cpus(counter); @@ -327,7 +327,7 @@ static int process_counter_maps(struct perf_stat_config *config, } int perf_stat_process_counter(struct perf_stat_config *config, - struct perf_evsel *counter) + struct evsel *counter) { struct perf_counts_values *aggr = &counter->counts->aggr; struct perf_stat_evsel *ps = counter->stats; @@ -381,7 +381,7 @@ int perf_event__process_stat_event(struct perf_session *session, { struct perf_counts_values count; struct stat_event *st = &event->stat; - struct perf_evsel *counter; + struct evsel *counter; count.val = st->val; count.ena = st->ena; @@ -437,12 +437,12 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp) return ret; } -int create_perf_stat_counter(struct perf_evsel *evsel, +int create_perf_stat_counter(struct evsel *evsel, struct perf_stat_config *config, struct target *target) { struct perf_event_attr *attr = &evsel->attr; - struct perf_evsel *leader = evsel->leader; + struct evsel *leader = evsel->leader; attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index fa675d09febd..b64cf0177a91 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -143,11 +143,11 @@ static inline void init_stats(struct stats *stats) stats->max = 0; } -struct perf_evsel; +struct evsel; struct perf_evlist; struct perf_aggr_thread_value { - struct perf_evsel *counter; + struct evsel *counter; int id; double uval; u64 val; @@ -155,7 +155,7 @@ struct perf_aggr_thread_value { u64 ena; }; -bool __perf_evsel_stat__is(struct perf_evsel *evsel, +bool __perf_evsel_stat__is(struct evsel *evsel, enum perf_stat_evsel_id id); #define perf_stat_evsel__is(evsel, id) \ @@ -174,7 +174,7 @@ void runtime_stat__exit(struct runtime_stat *st); void perf_stat__init_shadow_stats(void); void perf_stat__reset_shadow_stats(void); void perf_stat__reset_shadow_per_stat(struct runtime_stat *st); -void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, +void perf_stat__update_shadow_stats(struct evsel *counter, u64 count, int cpu, struct runtime_stat *st); struct perf_stat_output_ctx { void *ctx; @@ -184,7 +184,7 @@ struct perf_stat_output_ctx { }; void perf_stat__print_shadow_stats(struct perf_stat_config *config, - struct perf_evsel *evsel, + struct evsel *evsel, double avg, int cpu, struct perf_stat_output_ctx *out, struct rblist *metric_events, @@ -196,7 +196,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist); void perf_evlist__reset_stats(struct perf_evlist *evlist); int perf_stat_process_counter(struct perf_stat_config *config, - struct perf_evsel *counter); + struct evsel *counter); struct perf_tool; union perf_event; struct perf_session; @@ -207,7 +207,7 @@ size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); -int create_perf_stat_counter(struct perf_evsel *evsel, +int create_perf_stat_counter(struct evsel *evsel, struct perf_stat_config *config, struct target *target); int perf_stat_synthesize_config(struct perf_stat_config *config, diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 9096a6e3de59..5d880a6f0a34 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -9,7 +9,7 @@ struct perf_session; union perf_event; struct perf_evlist; -struct perf_evsel; +struct evsel; struct perf_sample; struct perf_tool; struct machine; @@ -17,7 +17,7 @@ struct ordered_events; typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, struct machine *machine); + struct evsel *evsel, struct machine *machine); typedef int (*event_op)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine); diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 251bbf124fb0..9f098db76e3c 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -71,7 +71,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) } if (top->evlist->nr_entries == 1) { - struct perf_evsel *first = perf_evlist__first(top->evlist); + struct evsel *first = perf_evlist__first(top->evlist); ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", (uint64_t)first->attr.sample_period, opts->freq ? "Hz" : ""); diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 19f95eaf75c8..7e0f363c0658 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -10,7 +10,7 @@ #include struct perf_evlist; -struct perf_evsel; +struct evsel; struct perf_session; struct perf_top { @@ -33,7 +33,7 @@ struct perf_top { bool vmlinux_warned; bool dump_symtab; struct hist_entry *sym_filter_entry; - struct perf_evsel *sym_evsel; + struct evsel *sym_evsel; struct perf_session *session; struct winsize winsize; int realtime_prio; diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 4550015b9d5d..d7ae0627ac47 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -405,7 +405,7 @@ static struct tracepoint_path * get_tracepoints_path(struct list_head *pattrs) { struct tracepoint_path path, *ppath = &path; - struct perf_evsel *pos; + struct evsel *pos; int nr_tracepoints = 0; list_for_each_entry(pos, pattrs, node) { @@ -441,7 +441,7 @@ get_tracepoints_path(struct list_head *pattrs) bool have_tracepoints(struct list_head *pattrs) { - struct perf_evsel *pos; + struct evsel *pos; list_for_each_entry(pos, pattrs, node) if (pos->attr.type == PERF_TYPE_TRACEPOINT) diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index ba58f69777a1..dfd2640c763a 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -29,7 +29,7 @@ static int stop_script_unsupported(void) static void process_event_unsupported(union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct perf_evsel *evsel __maybe_unused, + struct evsel *evsel __maybe_unused, struct addr_location *al __maybe_unused) { } diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index c7002fe11673..258d79071d81 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -79,13 +79,13 @@ struct scripting_ops { int (*stop_script) (void); void (*process_event) (union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel, + struct evsel *evsel, struct addr_location *al); void (*process_switch)(union perf_event *event, struct perf_sample *sample, struct machine *machine); void (*process_stat)(struct perf_stat_config *config, - struct perf_evsel *evsel, u64 tstamp); + struct evsel *evsel, u64 tstamp); void (*process_stat_interval)(u64 tstamp); int (*generate_script) (struct tep_handle *pevent, const char *outfile); }; -- GitLab From 63503dba87acfab49280d3b05df6705a6f327e8a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:52 +0200 Subject: [PATCH 1131/7155] perf evlist: Rename struct perf_evlist to struct evlist Rename struct perf_evlist to struct evlist, so we don't have a name clash when we add struct perf_evlist in libperf. Committer notes: Added fixes to build on arm64, from Jiri and from me (tools/perf/util/cs-etm.c) Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/auxtrace.c | 2 +- tools/perf/arch/arm/util/cs-etm.c | 8 +- tools/perf/arch/arm64/util/arm-spe.c | 6 +- tools/perf/arch/powerpc/util/kvm-stat.c | 6 +- tools/perf/arch/s390/util/auxtrace.c | 6 +- tools/perf/arch/x86/tests/intel-cqm.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/arch/x86/util/auxtrace.c | 4 +- tools/perf/arch/x86/util/intel-bts.c | 6 +- tools/perf/arch/x86/util/intel-pt.c | 14 +- tools/perf/builtin-c2c.c | 4 +- tools/perf/builtin-diff.c | 8 +- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-inject.c | 8 +- tools/perf/builtin-kvm.c | 8 +- tools/perf/builtin-record.c | 14 +- tools/perf/builtin-report.c | 8 +- tools/perf/builtin-sched.c | 4 +- tools/perf/builtin-script.c | 10 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 14 +- tools/perf/builtin-trace.c | 16 +- tools/perf/tests/backward-ring-buffer.c | 6 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 8 +- tools/perf/tests/event-times.c | 20 +- tools/perf/tests/event_update.c | 2 +- tools/perf/tests/evsel-roundtrip-name.c | 4 +- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 4 +- tools/perf/tests/hists_link.c | 4 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/tests/keep-tracking.c | 4 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/parse-events.c | 126 ++++++------ tools/perf/tests/parse-no-sample-id-all.c | 4 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 10 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/tests/time-utils-test.c | 2 +- tools/perf/ui/browsers/hists.c | 6 +- tools/perf/ui/gtk/gtk.h | 4 +- tools/perf/ui/gtk/hists.c | 2 +- tools/perf/ui/hist.c | 2 +- tools/perf/util/auxtrace.c | 10 +- tools/perf/util/auxtrace.h | 24 +-- tools/perf/util/bpf-event.c | 2 +- tools/perf/util/bpf-event.h | 4 +- tools/perf/util/bpf-loader.c | 20 +- tools/perf/util/bpf-loader.h | 24 +-- tools/perf/util/cgroup.c | 10 +- tools/perf/util/cgroup.h | 6 +- tools/perf/util/cs-etm.c | 4 +- tools/perf/util/data-convert-bt.c | 4 +- tools/perf/util/evlist.c | 194 +++++++++---------- tools/perf/util/evlist.h | 160 +++++++-------- tools/perf/util/evsel.c | 4 +- tools/perf/util/evsel.h | 4 +- tools/perf/util/header.c | 86 ++++---- tools/perf/util/header.h | 16 +- tools/perf/util/hist.c | 2 +- tools/perf/util/hist.h | 10 +- tools/perf/util/intel-bts.c | 2 +- tools/perf/util/intel-pt.c | 10 +- tools/perf/util/kvm-stat.h | 4 +- tools/perf/util/metricgroup.c | 6 +- tools/perf/util/mmap.c | 2 +- tools/perf/util/parse-events.c | 10 +- tools/perf/util/parse-events.h | 6 +- tools/perf/util/python.c | 16 +- tools/perf/util/record.c | 8 +- tools/perf/util/s390-sample-raw.c | 2 +- tools/perf/util/sample-raw.c | 2 +- tools/perf/util/sample-raw.h | 6 +- tools/perf/util/session.c | 24 +-- tools/perf/util/session.h | 4 +- tools/perf/util/sort.c | 20 +- tools/perf/util/sort.h | 6 +- tools/perf/util/stat-display.c | 18 +- tools/perf/util/stat-shadow.c | 4 +- tools/perf/util/stat.c | 8 +- tools/perf/util/stat.h | 14 +- tools/perf/util/tool.h | 4 +- tools/perf/util/top.h | 4 +- 86 files changed, 571 insertions(+), 571 deletions(-) diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c index fd17dccfcb0b..306a54185438 100644 --- a/tools/perf/arch/arm/util/auxtrace.c +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -50,7 +50,7 @@ static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err) } struct auxtrace_record -*auxtrace_record__init(struct perf_evlist *evlist, int *err) +*auxtrace_record__init(struct evlist *evlist, int *err) { struct perf_pmu *cs_etm_pmu; struct evsel *evsel; diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 476f845be5fe..91c64daa4487 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -32,7 +32,7 @@ struct cs_etm_recording { struct auxtrace_record itr; struct perf_pmu *cs_etm_pmu; - struct perf_evlist *evlist; + struct evlist *evlist; int wrapped_cnt; bool *wrapped; bool snapshot_mode; @@ -245,7 +245,7 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, } static int cs_etm_recording_options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts) { int ret; @@ -434,7 +434,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr) struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; - struct perf_evlist *evlist = ptr->evlist; + struct evlist *evlist = ptr->evlist; struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { @@ -485,7 +485,7 @@ static u64 cs_etmv4_get_config(struct auxtrace_record *itr) static size_t cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { int i; int etmv3 = 0, etmv4 = 0; diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 103bf20ae32a..cc29b995c751 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -27,12 +27,12 @@ struct arm_spe_recording { struct auxtrace_record itr; struct perf_pmu *arm_spe_pmu; - struct perf_evlist *evlist; + struct evlist *evlist; }; static size_t arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return ARM_SPE_AUXTRACE_PRIV_SIZE; } @@ -59,7 +59,7 @@ static int arm_spe_info_fill(struct auxtrace_record *itr, } static int arm_spe_recording_options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts) { struct arm_spe_recording *sper = diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c index 557c474f0a4b..28fc0bab370f 100644 --- a/tools/perf/arch/powerpc/util/kvm-stat.c +++ b/tools/perf/arch/powerpc/util/kvm-stat.c @@ -106,7 +106,7 @@ const char * const kvm_skip_events[] = { }; -static int is_tracepoint_available(const char *str, struct perf_evlist *evlist) +static int is_tracepoint_available(const char *str, struct evlist *evlist) { struct parse_events_error err; int ret; @@ -119,7 +119,7 @@ static int is_tracepoint_available(const char *str, struct perf_evlist *evlist) } static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, - struct perf_evlist *evlist) + struct evlist *evlist) { const char **events_ptr; int i, nr_tp = 0, err = -1; @@ -146,7 +146,7 @@ static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, /* Wrapper to setup kvm tracepoints */ static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm) { - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c index aec819b945c5..833f60fa9c5a 100644 --- a/tools/perf/arch/s390/util/auxtrace.c +++ b/tools/perf/arch/s390/util/auxtrace.c @@ -20,7 +20,7 @@ static void cpumsf_free(struct auxtrace_record *itr) } static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return 0; } @@ -43,7 +43,7 @@ cpumsf_reference(struct auxtrace_record *itr __maybe_unused) static int cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, struct record_opts *opts) { unsigned int factor = 1; @@ -82,7 +82,7 @@ cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused, * auxtrace_record__init is called when perf record * check if the event really need auxtrace */ -struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, +struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, int *err) { struct auxtrace_record *aux; diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c index b88ed71b2e3f..333b2f0d61e4 100644 --- a/tools/perf/arch/x86/tests/intel-cqm.c +++ b/tools/perf/arch/x86/tests/intel-cqm.c @@ -40,7 +40,7 @@ static pid_t spawn(void) */ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel = NULL; struct perf_event_attr pe; int i, fd[2], flag, ret; diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 43fc7d426d93..d7092fc00e3b 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -51,7 +51,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe }; struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel = NULL; int err = -1, ret, i; const char *comm1, *comm2; diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c index 02f192114448..6b3ad5c826fd 100644 --- a/tools/perf/arch/x86/util/auxtrace.c +++ b/tools/perf/arch/x86/util/auxtrace.c @@ -16,7 +16,7 @@ #include "../../util/evlist.h" static -struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist, +struct auxtrace_record *auxtrace_record__init_intel(struct evlist *evlist, int *err) { struct perf_pmu *intel_pt_pmu; @@ -50,7 +50,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist, return NULL; } -struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, +struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, int *err) { char buffer[64]; diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 59685a19c3b9..c845531d383a 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -35,7 +35,7 @@ struct intel_bts_snapshot_ref { struct intel_bts_recording { struct auxtrace_record itr; struct perf_pmu *intel_bts_pmu; - struct perf_evlist *evlist; + struct evlist *evlist; bool snapshot_mode; size_t snapshot_size; int snapshot_ref_cnt; @@ -50,7 +50,7 @@ struct branch { static size_t intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return INTEL_BTS_AUXTRACE_PRIV_SIZE; } @@ -99,7 +99,7 @@ static int intel_bts_info_fill(struct auxtrace_record *itr, } static int intel_bts_recording_options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts) { struct intel_bts_recording *btsr = diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index b42df73fd7ff..e4dfe8c3d5c3 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -44,7 +44,7 @@ struct intel_pt_recording { struct auxtrace_record itr; struct perf_pmu *intel_pt_pmu; int have_sched_switch; - struct perf_evlist *evlist; + struct evlist *evlist; bool snapshot_mode; bool snapshot_init_done; size_t snapshot_size; @@ -110,7 +110,7 @@ static u64 intel_pt_masked_bits(u64 mask, u64 bits) } static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, - struct perf_evlist *evlist, u64 *res) + struct evlist *evlist, u64 *res) { struct evsel *evsel; u64 mask; @@ -132,7 +132,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, } static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu, - struct perf_evlist *evlist) + struct evlist *evlist) { u64 val; int err, topa_multiple_entries; @@ -268,7 +268,7 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu) return attr; } -static const char *intel_pt_find_filter(struct perf_evlist *evlist, +static const char *intel_pt_find_filter(struct evlist *evlist, struct perf_pmu *intel_pt_pmu) { struct evsel *evsel; @@ -289,7 +289,7 @@ static size_t intel_pt_filter_bytes(const char *filter) } static size_t -intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist) +intel_pt_info_priv_size(struct auxtrace_record *itr, struct evlist *evlist) { struct intel_pt_recording *ptr = container_of(itr, struct intel_pt_recording, itr); @@ -398,7 +398,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, return 0; } -static int intel_pt_track_switches(struct perf_evlist *evlist) +static int intel_pt_track_switches(struct evlist *evlist) { const char *sched_switch = "sched:sched_switch"; struct evsel *evsel; @@ -549,7 +549,7 @@ static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, } static int intel_pt_recording_options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts) { struct intel_pt_recording *ptr = diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d251a486f329..f0aae6e13a33 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2236,7 +2236,7 @@ static void print_pareto(FILE *out) static void print_c2c_info(FILE *out, struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel; bool first = true; @@ -2567,7 +2567,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) return parse_callchain_report_opt(arg); } -static int setup_callchain(struct perf_evlist *evlist) +static int setup_callchain(struct evlist *evlist) { u64 sample_type = perf_evlist__combined_sample_type(evlist); enum perf_call_graph_mode mode = CALLCHAIN_NONE; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index c3b4b8196e00..e91c0d798181 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -449,7 +449,7 @@ static struct perf_diff pdiff = { }; static struct evsel *evsel_match(struct evsel *evsel, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *e; @@ -461,7 +461,7 @@ static struct evsel *evsel_match(struct evsel *evsel, return NULL; } -static void perf_evlist__collapse_resort(struct perf_evlist *evlist) +static void perf_evlist__collapse_resort(struct evlist *evlist) { struct evsel *evsel; @@ -1009,7 +1009,7 @@ static void data__fprintf(void) static void data_process(void) { - struct perf_evlist *evlist_base = data__files[0].session->evlist; + struct evlist *evlist_base = data__files[0].session->evlist; struct evsel *evsel_base; bool first = true; @@ -1019,7 +1019,7 @@ static void data_process(void) int i; data__for_each_file_new(i, d) { - struct perf_evlist *evlist = d->session->evlist; + struct evlist *evlist = d->session->evlist; struct evsel *evsel; struct hists *hists; diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 3e81e0b6628f..1263987c291a 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -27,7 +27,7 @@ #define DEFAULT_TRACER "function_graph" struct perf_ftrace { - struct perf_evlist *evlist; + struct evlist *evlist; struct target target; const char *tracer; struct list_head filters; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 646a1bf790fc..d2131fc863be 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -96,7 +96,7 @@ static int perf_event__repipe_op2_synth(struct perf_session *session, static int perf_event__repipe_attr(struct perf_tool *tool, union perf_event *event, - struct perf_evlist **pevlist) + struct evlist **pevlist) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); @@ -567,7 +567,7 @@ static int drop_sample(struct perf_tool *tool __maybe_unused, static void strip_init(struct perf_inject *inject) { - struct perf_evlist *evlist = inject->session->evlist; + struct evlist *evlist = inject->session->evlist; struct evsel *evsel; inject->tool.context_switch = perf_event__drop; @@ -590,7 +590,7 @@ static bool has_tracking(struct evsel *evsel) * their selected event to exist, except if there is only 1 selected event left * and it has a compatible sample type. */ -static bool ok_to_remove(struct perf_evlist *evlist, +static bool ok_to_remove(struct evlist *evlist, struct evsel *evsel_to_remove) { struct evsel *evsel; @@ -614,7 +614,7 @@ static bool ok_to_remove(struct perf_evlist *evlist, static void strip_fini(struct perf_inject *inject) { - struct perf_evlist *evlist = inject->session->evlist; + struct evlist *evlist = inject->session->evlist; struct evsel *evsel, *tmp; /* Remove non-synthesized evsels if possible */ diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index cf8f27d05296..963dddc5853d 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -743,7 +743,7 @@ static bool verify_vcpu(int vcpu) static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, u64 *mmap_time) { - struct perf_evlist *evlist = kvm->evlist; + struct evlist *evlist = kvm->evlist; union perf_event *event; struct perf_mmap *md; u64 timestamp; @@ -1012,7 +1012,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) { int err, rc = -1; struct evsel *pos; - struct perf_evlist *evlist = kvm->evlist; + struct evlist *evlist = kvm->evlist; char sbuf[STRERR_BUFSIZE]; perf_evlist__config(evlist, &kvm->opts, NULL); @@ -1283,9 +1283,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) } #ifdef HAVE_TIMERFD_SUPPORT -static struct perf_evlist *kvm_live_event_list(void) +static struct evlist *kvm_live_event_list(void) { - struct perf_evlist *evlist; + struct evlist *evlist; char *tp, *name, *sys; int err = -1; const char * const *events_tp; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 7ba3a2c32e54..f08d1e6a1651 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -73,7 +73,7 @@ struct record { u64 bytes_written; struct perf_data data; struct auxtrace_record *itr; - struct perf_evlist *evlist; + struct evlist *evlist; struct perf_session *session; int realtime_prio; bool no_buildid; @@ -346,7 +346,7 @@ static void record__aio_set_pos(int trace_fd, off_t pos) static void record__aio_mmap_read_sync(struct record *rec) { int i; - struct perf_evlist *evlist = rec->evlist; + struct evlist *evlist = rec->evlist; struct perf_mmap *maps = evlist->mmap; if (!record__aio_enabled(rec)) @@ -672,7 +672,7 @@ static int record__auxtrace_init(struct record *rec __maybe_unused) #endif static int record__mmap_evlist(struct record *rec, - struct perf_evlist *evlist) + struct evlist *evlist) { struct record_opts *opts = &rec->opts; char msg[512]; @@ -714,7 +714,7 @@ static int record__open(struct record *rec) { char msg[BUFSIZ]; struct evsel *pos; - struct perf_evlist *evlist = rec->evlist; + struct evlist *evlist = rec->evlist; struct perf_session *session = rec->session; struct record_opts *opts = &rec->opts; int rc = 0; @@ -904,7 +904,7 @@ static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_ return compressed; } -static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, +static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist, bool overwrite, bool synch) { u64 bytes_written = rec->bytes_written; @@ -1165,7 +1165,7 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused } static const struct perf_event_mmap_page * -perf_evlist__pick_pc(struct perf_evlist *evlist) +perf_evlist__pick_pc(struct evlist *evlist) { if (evlist) { if (evlist->mmap && evlist->mmap[0].base) @@ -1313,7 +1313,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) struct perf_data *data = &rec->data; struct perf_session *session; bool disabled = false, draining = false; - struct perf_evlist *sb_evlist = NULL; + struct evlist *sb_evlist = NULL; int fd; float ratio = 0; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 96a506f0d4c1..e258e988c55b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -193,7 +193,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, } static void setup_forced_leader(struct report *report, - struct perf_evlist *evlist) + struct evlist *evlist) { if (report->group_set) perf_evlist__force_leader(evlist); @@ -459,7 +459,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report return ret + fprintf(fp, "\n#\n"); } -static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, +static int perf_evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, const char *help) { @@ -532,7 +532,7 @@ static void report__warn_kptr_restrict(const struct report *rep) static int report__gtk_browse_hists(struct report *rep, const char *help) { - int (*hist_browser)(struct perf_evlist *evlist, const char *help, + int (*hist_browser)(struct evlist *evlist, const char *help, struct hist_browser_timer *timer, float min_pcnt); hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists"); @@ -549,7 +549,7 @@ static int report__browse_hists(struct report *rep) { int ret; struct perf_session *session = rep->session; - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; const char *help = perf_tip(system_path(TIPDIR)); if (help == NULL) { diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 55779f496d27..c02ecb295f23 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2924,7 +2924,7 @@ static int perf_timehist__process_sample(struct perf_tool *tool, } static int timehist_check_attr(struct perf_sched *sched, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *evsel; struct evsel_runtime *er; @@ -2963,7 +2963,7 @@ static int perf_sched__timehist(struct perf_sched *sched) }; struct perf_session *session; - struct perf_evlist *evlist; + struct evlist *evlist; int err = -1; /* diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4f9c8bb7620d..d741c0aa2750 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1636,7 +1636,7 @@ struct perf_script { int range_num; }; -static int perf_evlist__max_name_len(struct perf_evlist *evlist) +static int perf_evlist__max_name_len(struct evlist *evlist) { struct evsel *evsel; int max = 0; @@ -2018,10 +2018,10 @@ static int process_sample_event(struct perf_tool *tool, } static int process_attr(struct perf_tool *tool, union perf_event *event, - struct perf_evlist **pevlist) + struct evlist **pevlist) { struct perf_script *scr = container_of(tool, struct perf_script, tool); - struct perf_evlist *evlist; + struct evlist *evlist; struct evsel *evsel, *pos; int err; static struct evsel_script *es; @@ -2388,7 +2388,7 @@ static void sig_handler(int sig __maybe_unused) static void perf_script__fclose_per_event_dump(struct perf_script *script) { - struct perf_evlist *evlist = script->session->evlist; + struct evlist *evlist = script->session->evlist; struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { @@ -3256,7 +3256,7 @@ static int process_stat_config_event(struct perf_session *session __maybe_unused static int set_maps(struct perf_script *script) { - struct perf_evlist *evlist = script->session->evlist; + struct evlist *evlist = script->session->evlist; if (!script->cpus || !script->threads) return 0; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e0ba97018ad7..4e61f8a1d22b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -130,7 +130,7 @@ static const char *smi_cost_attrs = { "}" }; -static struct perf_evlist *evsel_list; +static struct evlist *evsel_list; static struct target target = { .uid = UINT_MAX, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 2f22f313985e..c29fa1de854f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -839,7 +839,7 @@ static u64 last_timestamp; static void perf_top__mmap_read_idx(struct perf_top *top, int idx) { struct record_opts *opts = &top->record_opts; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; struct perf_mmap *md; union perf_event *event; @@ -874,7 +874,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) static void perf_top__mmap_read(struct perf_top *top) { bool overwrite = top->record_opts.overwrite; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; int i; if (overwrite) @@ -909,7 +909,7 @@ static void perf_top__mmap_read(struct perf_top *top) static int perf_top__overwrite_check(struct perf_top *top) { struct record_opts *opts = &top->record_opts; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; struct perf_evsel_config_term *term; struct list_head *config_terms; struct evsel *evsel; @@ -955,7 +955,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top, struct evsel *evsel) { struct record_opts *opts = &top->record_opts; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; struct evsel *counter; if (!opts->overwrite) @@ -976,7 +976,7 @@ static int perf_top__start_counters(struct perf_top *top) { char msg[BUFSIZ]; struct evsel *counter; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; struct record_opts *opts = &top->record_opts; if (perf_top__overwrite_check(top)) { @@ -1100,7 +1100,7 @@ static int deliver_event(struct ordered_events *qe, struct ordered_event *qevent) { struct perf_top *top = qe->data; - struct perf_evlist *evlist = top->evlist; + struct evlist *evlist = top->evlist; struct perf_session *session = top->session; union perf_event *event = qevent->event; struct perf_sample sample; @@ -1511,7 +1511,7 @@ int cmd_top(int argc, const char **argv) "Record namespaces events"), OPT_END() }; - struct perf_evlist *sb_evlist = NULL; + struct evlist *sb_evlist = NULL; const char * const top_usage[] = { "perf top []", NULL diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index fde7eff811f9..f7e7daac3cbe 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -96,7 +96,7 @@ struct trace { struct bpf_map *map; } dump; struct record_opts opts; - struct perf_evlist *evlist; + struct evlist *evlist; struct machine *host; struct thread *current; struct bpf_object *bpf_obj; @@ -1388,7 +1388,7 @@ static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long l return machine__resolve_kernel_addr(vmachine, addrp, modp); } -static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) +static int trace__symbols_init(struct trace *trace, struct evlist *evlist) { int err = symbol__init(NULL); @@ -2616,7 +2616,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv) static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); -static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) +static bool perf_evlist__add_vfs_getname(struct evlist *evlist) { bool found = false; struct evsel *evsel, *tmp; @@ -2699,7 +2699,7 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st static int trace__add_syscall_newtp(struct trace *trace) { int ret = -1; - struct perf_evlist *evlist = trace->evlist; + struct evlist *evlist = trace->evlist; struct evsel *sys_enter, *sys_exit; sys_enter = perf_evsel__raw_syscall_newtp("sys_enter", trace__sys_enter); @@ -3192,7 +3192,7 @@ static int trace__set_filter_pids(struct trace *trace) static int __trace__deliver_event(struct trace *trace, union perf_event *event) { - struct perf_evlist *evlist = trace->evlist; + struct evlist *evlist = trace->evlist; struct perf_sample sample; int err; @@ -3250,7 +3250,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe, static int trace__run(struct trace *trace, int argc, const char **argv) { - struct perf_evlist *evlist = trace->evlist; + struct evlist *evlist = trace->evlist; struct evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL; int err = -1, i; unsigned long before; @@ -3843,7 +3843,7 @@ static int parse_pagefaults(const struct option *opt, const char *str, return 0; } -static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler) +static void evlist__set_evsel_handler(struct evlist *evlist, void *handler) { struct evsel *evsel; @@ -3851,7 +3851,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler) evsel->handler = handler; } -static int evlist__set_syscall_tp_fields(struct perf_evlist *evlist) +static int evlist__set_syscall_tp_fields(struct evlist *evlist) { struct evsel *evsel; diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 921af318507c..3f9c931069b0 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -25,7 +25,7 @@ static void testcase(void) } } -static int count_samples(struct perf_evlist *evlist, int *sample_count, +static int count_samples(struct evlist *evlist, int *sample_count, int *comm_count) { int i; @@ -55,7 +55,7 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count, return TEST_OK; } -static int do_test(struct perf_evlist *evlist, int mmap_pages, +static int do_test(struct evlist *evlist, int mmap_pages, int *sample_count, int *comm_count) { int err; @@ -82,7 +82,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m { int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; char pid[16], sbuf[STRERR_BUFSIZE]; - struct perf_evlist *evlist; + struct evlist *evlist; struct evsel *evsel __maybe_unused; struct parse_events_error parse_error; struct record_opts opts = { diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index c9e4cdc4c9c8..95a15b51f95c 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -118,7 +118,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), char pid[16]; char sbuf[STRERR_BUFSIZE]; - struct perf_evlist *evlist; + struct evlist *evlist; int i, ret = TEST_FAIL, err = 0, count = 0; struct parse_events_state parse_state; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 062d23bba2df..168deb9c563e 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -362,7 +362,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, } static int process_sample_event(struct machine *machine, - struct perf_evlist *evlist, + struct evlist *evlist, union perf_event *event, struct state *state) { struct perf_sample sample; @@ -385,7 +385,7 @@ static int process_sample_event(struct machine *machine, return ret; } -static int process_event(struct machine *machine, struct perf_evlist *evlist, +static int process_event(struct machine *machine, struct evlist *evlist, union perf_event *event, struct state *state) { if (event->header.type == PERF_RECORD_SAMPLE) @@ -408,7 +408,7 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist, return 0; } -static int process_events(struct machine *machine, struct perf_evlist *evlist, +static int process_events(struct machine *machine, struct evlist *evlist, struct state *state) { union perf_event *event; @@ -554,7 +554,7 @@ static int do_test_code_reading(bool try_kcore) }; struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel = NULL; int err = -1, ret; pid_t pid; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 45fe674233d7..c3545a6efcbc 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -12,7 +12,7 @@ #include "thread_map.h" #include "target.h" -static int attach__enable_on_exec(struct perf_evlist *evlist) +static int attach__enable_on_exec(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); struct target target = { @@ -48,13 +48,13 @@ static int attach__enable_on_exec(struct perf_evlist *evlist) return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL; } -static int detach__enable_on_exec(struct perf_evlist *evlist) +static int detach__enable_on_exec(struct evlist *evlist) { waitpid(evlist->workload.pid, NULL, 0); return 0; } -static int attach__current_disabled(struct perf_evlist *evlist) +static int attach__current_disabled(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); struct perf_thread_map *threads; @@ -80,7 +80,7 @@ static int attach__current_disabled(struct perf_evlist *evlist) return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; } -static int attach__current_enabled(struct perf_evlist *evlist) +static int attach__current_enabled(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); struct perf_thread_map *threads; @@ -100,14 +100,14 @@ static int attach__current_enabled(struct perf_evlist *evlist) return err == 0 ? TEST_OK : TEST_FAIL; } -static int detach__disable(struct perf_evlist *evlist) +static int detach__disable(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); return perf_evsel__enable(evsel); } -static int attach__cpu_disabled(struct perf_evlist *evlist) +static int attach__cpu_disabled(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); struct perf_cpu_map *cpus; @@ -136,7 +136,7 @@ static int attach__cpu_disabled(struct perf_evlist *evlist) return perf_evsel__enable(evsel); } -static int attach__cpu_enabled(struct perf_evlist *evlist) +static int attach__cpu_enabled(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); struct perf_cpu_map *cpus; @@ -158,11 +158,11 @@ static int attach__cpu_enabled(struct perf_evlist *evlist) return err ? TEST_FAIL : TEST_OK; } -static int test_times(int (attach)(struct perf_evlist *), - int (detach)(struct perf_evlist *)) +static int test_times(int (attach)(struct evlist *), + int (detach)(struct evlist *)) { struct perf_counts_values count; - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel; int err = -1, i; diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index 0e5a2e8195e4..eb0dd359762d 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -79,7 +79,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct perf_evlist *evlist; + struct evlist *evlist; struct evsel *evsel; struct event_name tmp; diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index bb38489eda1e..6cc408b23026 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -12,7 +12,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) char name[128]; int type, op, err = 0, ret = 0, i, idx; struct evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist == NULL) return -ENOMEM; @@ -68,7 +68,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) { int i, err; struct evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index b62bf7c3bea2..d7a6b97683d6 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -695,7 +695,7 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u struct machines machines; struct machine *machine; struct evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); size_t i; test_fn_t testcases[] = { test1, diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 3e679bb8da7f..9f0d6af839e9 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -47,7 +47,7 @@ static struct sample fake_samples[] = { { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 }, }; -static int add_hist_entries(struct perf_evlist *evlist, +static int add_hist_entries(struct evlist *evlist, struct machine *machine) { struct evsel *evsel; @@ -109,7 +109,7 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu struct machines machines; struct machine *machine; struct evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); TEST_ASSERT_VAL("No memory", evlist); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 078ee9876980..6ab27dd3bf3f 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -62,7 +62,7 @@ static struct sample fake_samples[][5] = { }, }; -static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) +static int add_hist_entries(struct evlist *evlist, struct machine *machine) { struct evsel *evsel; struct addr_location al; @@ -272,7 +272,7 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse struct machines machines; struct machine *machine = NULL; struct evsel *evsel, *first; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index 5cd4b1baa9d1..cd36e51cdf3b 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -581,7 +581,7 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu struct machines machines; struct machine *machine; struct evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); size_t i; test_fn_t testcases[] = { test1, diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 8ada3e63f1ba..e0779f2a340c 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -24,7 +24,7 @@ } \ } -static int find_comm(struct perf_evlist *evlist, const char *comm) +static int find_comm(struct evlist *evlist, const char *comm) { union perf_event *event; struct perf_mmap *md; @@ -67,7 +67,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un }; struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel = NULL; int found, err = -1; const char *comm; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 76ee42eb1355..749b580e9a92 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -29,7 +29,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse union perf_event *event; struct perf_thread_map *threads; struct perf_cpu_map *cpus; - struct perf_evlist *evlist; + struct evlist *evlist; cpu_set_t cpu_set; const char *syscall_names[] = { "getsid", "getppid", "getpgid", }; pid_t (*syscalls[])(void) = { (void *)getsid, getppid, (void*)getpgid }; diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 2e467448e220..69bf0ec2fe5f 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -32,7 +32,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest }; const char *filename = "/etc/passwd"; int flags = O_RDONLY | O_DIRECTORY; - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); struct evsel *evsel; int err = -1, i, nr_events = 0, nr_polls = 0; char sbuf[STRERR_BUFSIZE]; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index f55ab43d51bd..7409eed11b65 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -44,7 +44,7 @@ static bool kvm_s390_create_vm_valid(void) } #endif -static int test__checkevent_tracepoint(struct perf_evlist *evlist) +static int test__checkevent_tracepoint(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -57,7 +57,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist) return 0; } -static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) +static int test__checkevent_tracepoint_multi(struct evlist *evlist) { struct evsel *evsel; @@ -75,7 +75,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) return 0; } -static int test__checkevent_raw(struct perf_evlist *evlist) +static int test__checkevent_raw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -85,7 +85,7 @@ static int test__checkevent_raw(struct perf_evlist *evlist) return 0; } -static int test__checkevent_numeric(struct perf_evlist *evlist) +static int test__checkevent_numeric(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -95,7 +95,7 @@ static int test__checkevent_numeric(struct perf_evlist *evlist) return 0; } -static int test__checkevent_symbolic_name(struct perf_evlist *evlist) +static int test__checkevent_symbolic_name(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -106,7 +106,7 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist) return 0; } -static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) +static int test__checkevent_symbolic_name_config(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -127,7 +127,7 @@ static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) return 0; } -static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) +static int test__checkevent_symbolic_alias(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -138,7 +138,7 @@ static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) return 0; } -static int test__checkevent_genhw(struct perf_evlist *evlist) +static int test__checkevent_genhw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -148,7 +148,7 @@ static int test__checkevent_genhw(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint(struct perf_evlist *evlist) +static int test__checkevent_breakpoint(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -162,7 +162,7 @@ static int test__checkevent_breakpoint(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_x(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -175,7 +175,7 @@ static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_r(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -190,7 +190,7 @@ static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_w(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -205,7 +205,7 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_rw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -220,7 +220,7 @@ static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) return 0; } -static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) +static int test__checkevent_tracepoint_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -233,7 +233,7 @@ static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) } static int -test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) +test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) { struct evsel *evsel; @@ -251,7 +251,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) return test__checkevent_tracepoint_multi(evlist); } -static int test__checkevent_raw_modifier(struct perf_evlist *evlist) +static int test__checkevent_raw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -263,7 +263,7 @@ static int test__checkevent_raw_modifier(struct perf_evlist *evlist) return test__checkevent_raw(evlist); } -static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) +static int test__checkevent_numeric_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -275,7 +275,7 @@ static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) return test__checkevent_numeric(evlist); } -static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) +static int test__checkevent_symbolic_name_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -287,7 +287,7 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) +static int test__checkevent_exclude_host_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -297,7 +297,7 @@ static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) +static int test__checkevent_exclude_guest_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -307,7 +307,7 @@ static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) +static int test__checkevent_symbolic_alias_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -319,7 +319,7 @@ static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_alias(evlist); } -static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) +static int test__checkevent_genhw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -331,7 +331,7 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) return test__checkevent_genhw(evlist); } -static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist) +static int test__checkevent_exclude_idle_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -346,7 +346,7 @@ static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist) +static int test__checkevent_exclude_idle_modifier_1(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -361,7 +361,7 @@ static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -376,7 +376,7 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint(evlist); } -static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_x_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -390,7 +390,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_x(evlist); } -static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_r_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -404,7 +404,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_r(evlist); } -static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_w_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -418,7 +418,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_w(evlist); } -static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_rw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -432,7 +432,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_rw(evlist); } -static int test__checkevent_pmu(struct perf_evlist *evlist) +static int test__checkevent_pmu(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -451,7 +451,7 @@ static int test__checkevent_pmu(struct perf_evlist *evlist) return 0; } -static int test__checkevent_list(struct perf_evlist *evlist) +static int test__checkevent_list(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -490,7 +490,7 @@ static int test__checkevent_list(struct perf_evlist *evlist) return 0; } -static int test__checkevent_pmu_name(struct perf_evlist *evlist) +static int test__checkevent_pmu_name(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -511,7 +511,7 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist) return 0; } -static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlist) +static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -544,7 +544,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlis return 0; } -static int test__checkevent_pmu_events(struct perf_evlist *evlist) +static int test__checkevent_pmu_events(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -562,7 +562,7 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist) } -static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist) +static int test__checkevent_pmu_events_mix(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -634,7 +634,7 @@ static int test__checkterms_simple(struct list_head *terms) return 0; } -static int test__group1(struct perf_evlist *evlist) +static int test__group1(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -676,7 +676,7 @@ static int test__group1(struct perf_evlist *evlist) return 0; } -static int test__group2(struct perf_evlist *evlist) +static int test__group2(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -731,7 +731,7 @@ static int test__group2(struct perf_evlist *evlist) return 0; } -static int test__group3(struct perf_evlist *evlist __maybe_unused) +static int test__group3(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; @@ -823,7 +823,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) return 0; } -static int test__group4(struct perf_evlist *evlist __maybe_unused) +static int test__group4(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; @@ -867,7 +867,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) return 0; } -static int test__group5(struct perf_evlist *evlist __maybe_unused) +static int test__group5(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; @@ -953,7 +953,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) return 0; } -static int test__group_gh1(struct perf_evlist *evlist) +static int test__group_gh1(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -993,7 +993,7 @@ static int test__group_gh1(struct perf_evlist *evlist) return 0; } -static int test__group_gh2(struct perf_evlist *evlist) +static int test__group_gh2(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -1033,7 +1033,7 @@ static int test__group_gh2(struct perf_evlist *evlist) return 0; } -static int test__group_gh3(struct perf_evlist *evlist) +static int test__group_gh3(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -1073,7 +1073,7 @@ static int test__group_gh3(struct perf_evlist *evlist) return 0; } -static int test__group_gh4(struct perf_evlist *evlist) +static int test__group_gh4(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -1113,7 +1113,7 @@ static int test__group_gh4(struct perf_evlist *evlist) return 0; } -static int test__leader_sample1(struct perf_evlist *evlist) +static int test__leader_sample1(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -1166,7 +1166,7 @@ static int test__leader_sample1(struct perf_evlist *evlist) return 0; } -static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused) +static int test__leader_sample2(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; @@ -1205,7 +1205,7 @@ static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused) return 0; } -static int test__checkevent_pinned_modifier(struct perf_evlist *evlist) +static int test__checkevent_pinned_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1218,7 +1218,7 @@ static int test__checkevent_pinned_modifier(struct perf_evlist *evlist) return test__checkevent_symbolic_name(evlist); } -static int test__pinned_group(struct perf_evlist *evlist) +static int test__pinned_group(struct evlist *evlist) { struct evsel *evsel, *leader; @@ -1249,7 +1249,7 @@ static int test__pinned_group(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_len(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_len(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1264,7 +1264,7 @@ static int test__checkevent_breakpoint_len(struct perf_evlist *evlist) return 0; } -static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist) +static int test__checkevent_breakpoint_len_w(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1280,7 +1280,7 @@ static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist) } static int -test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) +test__checkevent_breakpoint_len_rw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1292,7 +1292,7 @@ test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) return test__checkevent_breakpoint_rw(evlist); } -static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist) +static int test__checkevent_precise_max_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1303,7 +1303,7 @@ static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist) return 0; } -static int test__checkevent_config_symbol(struct perf_evlist *evlist) +static int test__checkevent_config_symbol(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1311,7 +1311,7 @@ static int test__checkevent_config_symbol(struct perf_evlist *evlist) return 0; } -static int test__checkevent_config_raw(struct perf_evlist *evlist) +static int test__checkevent_config_raw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1319,7 +1319,7 @@ static int test__checkevent_config_raw(struct perf_evlist *evlist) return 0; } -static int test__checkevent_config_num(struct perf_evlist *evlist) +static int test__checkevent_config_num(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1327,7 +1327,7 @@ static int test__checkevent_config_num(struct perf_evlist *evlist) return 0; } -static int test__checkevent_config_cache(struct perf_evlist *evlist) +static int test__checkevent_config_cache(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1340,7 +1340,7 @@ static bool test__intel_pt_valid(void) return !!perf_pmu__find("intel_pt"); } -static int test__intel_pt(struct perf_evlist *evlist) +static int test__intel_pt(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1348,7 +1348,7 @@ static int test__intel_pt(struct perf_evlist *evlist) return 0; } -static int test__checkevent_complex_name(struct perf_evlist *evlist) +static int test__checkevent_complex_name(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1356,7 +1356,7 @@ static int test__checkevent_complex_name(struct perf_evlist *evlist) return 0; } -static int test__sym_event_slash(struct perf_evlist *evlist) +static int test__sym_event_slash(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1366,7 +1366,7 @@ static int test__sym_event_slash(struct perf_evlist *evlist) return 0; } -static int test__sym_event_dc(struct perf_evlist *evlist) +static int test__sym_event_dc(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); @@ -1422,7 +1422,7 @@ static int count_tracepoints(void) return cnt; } -static int test__all_tracepoints(struct perf_evlist *evlist) +static int test__all_tracepoints(struct evlist *evlist) { TEST_ASSERT_VAL("wrong events count", count_tracepoints() == evlist->nr_entries); @@ -1435,7 +1435,7 @@ struct evlist_test { __u32 type; const int id; bool (*valid)(void); - int (*check)(struct perf_evlist *evlist); + int (*check)(struct evlist *evlist); }; static struct evlist_test test__events[] = { @@ -1769,7 +1769,7 @@ static struct terms_test test__terms[] = { static int test_event(struct evlist_test *e) { struct parse_events_error err = { .idx = 0, }; - struct perf_evlist *evlist; + struct evlist *evlist; int ret; if (e->valid && !e->valid()) { diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c index 2196d1497c0c..fc0213246aaf 100644 --- a/tools/perf/tests/parse-no-sample-id-all.c +++ b/tools/perf/tests/parse-no-sample-id-all.c @@ -11,7 +11,7 @@ #include "util.h" #include "debug.h" -static int process_event(struct perf_evlist **pevlist, union perf_event *event) +static int process_event(struct evlist **pevlist, union perf_event *event) { struct perf_sample sample; @@ -39,7 +39,7 @@ static int process_event(struct perf_evlist **pevlist, union perf_event *event) static int process_events(union perf_event **events, size_t count) { - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; int err = 0; size_t i; diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 7e576c2db941..99b2d26881f9 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -50,7 +50,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus }; cpu_set_t cpu_mask; size_t cpu_mask_size = sizeof(cpu_mask); - struct perf_evlist *evlist = perf_evlist__new_dummy(); + struct evlist *evlist = perf_evlist__new_dummy(); struct evsel *evsel; struct perf_sample sample; const char *cmd = "sleep"; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 620a99aad1e3..69b997eeb639 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -28,7 +28,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) char sbuf[STRERR_BUFSIZE]; union perf_event *event; struct evsel *evsel; - struct perf_evlist *evlist; + struct evlist *evlist; struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .config = clock_id, diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index a946b9fa60dd..3e26ea36ec29 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -113,7 +113,7 @@ static int check_cpu(struct switch_tracking *switch_tracking, int cpu) return 0; } -static int process_sample_event(struct perf_evlist *evlist, +static int process_sample_event(struct evlist *evlist, union perf_event *event, struct switch_tracking *switch_tracking) { @@ -163,7 +163,7 @@ static int process_sample_event(struct perf_evlist *evlist, return 0; } -static int process_event(struct perf_evlist *evlist, union perf_event *event, +static int process_event(struct evlist *evlist, union perf_event *event, struct switch_tracking *switch_tracking) { if (event->header.type == PERF_RECORD_SAMPLE) @@ -203,7 +203,7 @@ struct event_node { u64 event_time; }; -static int add_event(struct perf_evlist *evlist, struct list_head *events, +static int add_event(struct evlist *evlist, struct list_head *events, union perf_event *event) { struct perf_sample sample; @@ -252,7 +252,7 @@ static int compar(const void *a, const void *b) return cmp; } -static int process_events(struct perf_evlist *evlist, +static int process_events(struct evlist *evlist, struct switch_tracking *switch_tracking) { union perf_event *event; @@ -329,7 +329,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ }; struct perf_thread_map *threads = NULL; struct perf_cpu_map *cpus = NULL; - struct perf_evlist *evlist = NULL; + struct evlist *evlist = NULL; struct evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; struct evsel *switch_evsel, *tracking_evsel; const char *comm; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index e6fb4b8d8bc2..5c2cdb0ccb96 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -38,7 +38,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused int err = -1; union perf_event *event; struct evsel *evsel; - struct perf_evlist *evlist; + struct evlist *evlist; struct target target = { .uid = UINT_MAX, .uses_mmap = true, diff --git a/tools/perf/tests/time-utils-test.c b/tools/perf/tests/time-utils-test.c index 4f53006233a1..fe57ca3b6e54 100644 --- a/tools/perf/tests/time-utils-test.c +++ b/tools/perf/tests/time-utils-test.c @@ -69,7 +69,7 @@ struct test_data { static bool test__perf_time__parse_for_ranges(struct test_data *d) { - struct perf_evlist evlist = { + struct evlist evlist = { .first_sample_time = d->first, .last_sample_time = d->last, }; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 9bc818621eb6..b83258bece05 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -3262,7 +3262,7 @@ static int perf_evsel_menu__run(struct evsel_menu *menu, struct hist_browser_timer *hbt, bool warn_lost_event) { - struct perf_evlist *evlist = menu->b.priv; + struct evlist *evlist = menu->b.priv; struct evsel *pos; const char *title = "Available samples"; int delay_secs = hbt ? hbt->refresh : 0; @@ -3359,7 +3359,7 @@ static bool filter_group_entries(struct ui_browser *browser __maybe_unused, return false; } -static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, +static int __perf_evlist__tui_browse_hists(struct evlist *evlist, int nr_entries, const char *help, struct hist_browser_timer *hbt, float min_pcnt, @@ -3397,7 +3397,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, hbt, warn_lost_event); } -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, +int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help, struct hist_browser_timer *hbt, float min_pcnt, struct perf_env *env, diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index e2f5fbef3c9a..a9563932fa04 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -53,11 +53,11 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void) #endif struct evsel; -struct perf_evlist; +struct evlist; struct hist_entry; struct hist_browser_timer; -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, +int perf_evlist__gtk_browse_hists(struct evlist *evlist, const char *help, struct hist_browser_timer *hbt, float min_pcnt); int hist_entry__gtk_annotate(struct hist_entry *he, diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index d5c9fe230632..1b181d8ea953 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -590,7 +590,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, gtk_container_add(GTK_CONTAINER(window), view); } -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, +int perf_evlist__gtk_browse_hists(struct evlist *evlist, const char *help, struct hist_browser_timer *hbt __maybe_unused, float min_pcnt) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 214af526901b..8c7fb11edc60 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -795,7 +795,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt) } int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *evsel; struct perf_hpp_fmt *fmt; diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 98b151bc9a36..9ec2841ddec4 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -124,7 +124,7 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, } void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct perf_evlist *evlist, int idx, + struct evlist *evlist, int idx, bool per_cpu) { mp->idx = idx; @@ -503,7 +503,7 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) } size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr, - struct perf_evlist *evlist) + struct evlist *evlist) { if (itr) return itr->info_priv_size(itr, evlist); @@ -556,7 +556,7 @@ int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx, } int auxtrace_record__options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts) { if (itr) @@ -585,7 +585,7 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, } struct auxtrace_record *__weak -auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err) +auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err) { *err = 0; return NULL; @@ -2160,7 +2160,7 @@ static int perf_evsel__nr_addr_filter(struct evsel *evsel) return nr_addr_filters; } -int auxtrace_parse_filters(struct perf_evlist *evlist) +int auxtrace_parse_filters(struct evlist *evlist) { struct evsel *evsel; char *filter; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index e9b4c5edf78b..17eb04a1da4d 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -23,7 +23,7 @@ union perf_event; struct perf_session; -struct perf_evlist; +struct evlist; struct perf_tool; struct perf_mmap; struct option; @@ -309,10 +309,10 @@ struct auxtrace_mmap_params { */ struct auxtrace_record { int (*recording_options)(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts); size_t (*info_priv_size)(struct auxtrace_record *itr, - struct perf_evlist *evlist); + struct evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, @@ -432,7 +432,7 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct perf_evlist *evlist, int idx, + struct evlist *evlist, int idx, bool per_cpu); typedef int (*process_auxtrace_t)(struct perf_tool *tool, @@ -482,17 +482,17 @@ int auxtrace_cache__add(struct auxtrace_cache *c, u32 key, struct auxtrace_cache_entry *entry); void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key); -struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, +struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, int *err); int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, struct record_opts *opts, const char *str); int auxtrace_record__options(struct auxtrace_record *itr, - struct perf_evlist *evlist, + struct evlist *evlist, struct record_opts *opts); size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr, - struct perf_evlist *evlist); + struct evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, @@ -540,7 +540,7 @@ void addr_filters__init(struct addr_filters *filts); void addr_filters__exit(struct addr_filters *filts); int addr_filters__parse_bare_filter(struct addr_filters *filts, const char *filter); -int auxtrace_parse_filters(struct perf_evlist *evlist); +int auxtrace_parse_filters(struct evlist *evlist); static inline int auxtrace__process_event(struct perf_session *session, union perf_event *event, @@ -613,7 +613,7 @@ void itrace_synth_opts__clear_time_range(struct itrace_synth_opts *opts) #else static inline struct auxtrace_record * -auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, +auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err) { *err = 0; @@ -636,7 +636,7 @@ perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused, static inline int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, struct record_opts *opts __maybe_unused) { return 0; @@ -733,7 +733,7 @@ void auxtrace_index__free(struct list_head *head __maybe_unused) } static inline -int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused) +int auxtrace_parse_filters(struct evlist *evlist __maybe_unused) { return 0; } @@ -747,7 +747,7 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct perf_evlist *evlist, int idx, + struct evlist *evlist, int idx, bool per_cpu); #define ITRACE_HELP "" diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 2a4a0da35632..5a5dcc6d8f85 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -418,7 +418,7 @@ static int bpf_event__sb_cb(union perf_event *event, void *data) return 0; } -int bpf_event__add_sb_event(struct perf_evlist **evlist, +int bpf_event__add_sb_event(struct evlist **evlist, struct perf_env *env) { struct perf_event_attr attr = { diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index 04c33b3bfe28..26ab9239f986 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -37,7 +37,7 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts); -int bpf_event__add_sb_event(struct perf_evlist **evlist, +int bpf_event__add_sb_event(struct evlist **evlist, struct perf_env *env); void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, struct perf_env *env, @@ -58,7 +58,7 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session return 0; } -static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused, +static inline int bpf_event__add_sb_event(struct evlist **evlist __maybe_unused, struct perf_env *env __maybe_unused) { return 0; diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 594ea279e25b..b0696726ab76 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -1043,7 +1043,7 @@ __bpf_map__config_value(struct bpf_map *map, static int bpf_map__config_value(struct bpf_map *map, struct parse_events_term *term, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { if (!term->err_val) { pr_debug("Config value not set\n"); @@ -1061,7 +1061,7 @@ bpf_map__config_value(struct bpf_map *map, static int __bpf_map__config_event(struct bpf_map *map, struct parse_events_term *term, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *evsel; const struct bpf_map_def *def; @@ -1103,7 +1103,7 @@ __bpf_map__config_event(struct bpf_map *map, static int bpf_map__config_event(struct bpf_map *map, struct parse_events_term *term, - struct perf_evlist *evlist) + struct evlist *evlist) { if (!term->err_val) { pr_debug("Config value not set\n"); @@ -1121,7 +1121,7 @@ bpf_map__config_event(struct bpf_map *map, struct bpf_obj_config__map_func { const char *config_opt; int (*config_func)(struct bpf_map *, struct parse_events_term *, - struct perf_evlist *); + struct evlist *); }; struct bpf_obj_config__map_func bpf_obj_config__map_funcs[] = { @@ -1169,7 +1169,7 @@ config_map_indices_range_check(struct parse_events_term *term, static int bpf__obj_config_map(struct bpf_object *obj, struct parse_events_term *term, - struct perf_evlist *evlist, + struct evlist *evlist, int *key_scan_pos) { /* key is "map:." */ @@ -1228,7 +1228,7 @@ bpf__obj_config_map(struct bpf_object *obj, int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, - struct perf_evlist *evlist, + struct evlist *evlist, int *error_pos) { int key_scan_pos = 0; @@ -1523,7 +1523,7 @@ int bpf__apply_obj_config(void) (strcmp(name, \ bpf_map__name(pos)) == 0)) -struct evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name) +struct evsel *bpf__setup_output_event(struct evlist *evlist, const char *name) { struct bpf_map_priv *tmpl_priv = NULL; struct bpf_object *obj, *tmp; @@ -1600,7 +1600,7 @@ struct evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *na return evsel; } -int bpf__setup_stdout(struct perf_evlist *evlist) +int bpf__setup_stdout(struct evlist *evlist) { struct evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); return PTR_ERR_OR_ZERO(evsel); @@ -1756,7 +1756,7 @@ int bpf__strerror_load(struct bpf_object *obj, int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused, struct parse_events_term *term __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, int *error_pos __maybe_unused, int err, char *buf, size_t size) { @@ -1780,7 +1780,7 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size) return 0; } -int bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused, +int bpf__strerror_setup_output_event(struct evlist *evlist __maybe_unused, int err, char *buf, size_t size) { bpf__strerror_head(err, buf, size); diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index e2048c978a24..25251d63164c 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -40,7 +40,7 @@ enum bpf_loader_errno { }; struct evsel; -struct perf_evlist; +struct evlist; struct bpf_object; struct parse_events_term; #define PERF_BPF_PROBE_GROUP "perf_bpf_probe" @@ -70,18 +70,18 @@ int bpf__foreach_event(struct bpf_object *obj, bpf_prog_iter_callback_t func, void *arg); int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, - struct perf_evlist *evlist, int *error_pos); + struct evlist *evlist, int *error_pos); int bpf__strerror_config_obj(struct bpf_object *obj, struct parse_events_term *term, - struct perf_evlist *evlist, + struct evlist *evlist, int *error_pos, int err, char *buf, size_t size); int bpf__apply_obj_config(void); int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); -int bpf__setup_stdout(struct perf_evlist *evlist); -struct evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name); -int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size); +int bpf__setup_stdout(struct evlist *evlist); +struct evsel *bpf__setup_output_event(struct evlist *evlist, const char *name); +int bpf__strerror_setup_output_event(struct evlist *evlist, int err, char *buf, size_t size); #else #include #include @@ -119,7 +119,7 @@ bpf__foreach_event(struct bpf_object *obj __maybe_unused, static inline int bpf__config_obj(struct bpf_object *obj __maybe_unused, struct parse_events_term *term __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, int *error_pos __maybe_unused) { return 0; @@ -132,13 +132,13 @@ bpf__apply_obj_config(void) } static inline int -bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) +bpf__setup_stdout(struct evlist *evlist __maybe_unused) { return 0; } static inline struct evsel * -bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused) +bpf__setup_output_event(struct evlist *evlist __maybe_unused, const char *name __maybe_unused) { return NULL; } @@ -182,7 +182,7 @@ static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused, static inline int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused, struct parse_events_term *term __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, int *error_pos __maybe_unused, int err __maybe_unused, char *buf, size_t size) @@ -198,7 +198,7 @@ bpf__strerror_apply_obj_config(int err __maybe_unused, } static inline int -bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused, +bpf__strerror_setup_output_event(struct evlist *evlist __maybe_unused, int err __maybe_unused, char *buf, size_t size) { return __bpf_strerror(buf, size); @@ -206,7 +206,7 @@ bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused, #endif -static inline int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, char *buf, size_t size) +static inline int bpf__strerror_setup_stdout(struct evlist *evlist, int err, char *buf, size_t size) { return bpf__strerror_setup_output_event(evlist, err, buf, size); } diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 4f5c326a9477..deb87ecd3671 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -90,7 +90,7 @@ static int open_cgroup(const char *name) return fd; } -static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str) +static struct cgroup *evlist__find_cgroup(struct evlist *evlist, const char *str) { struct evsel *counter; /* @@ -130,14 +130,14 @@ static struct cgroup *cgroup__new(const char *name) return NULL; } -struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name) +struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name) { struct cgroup *cgroup = evlist__find_cgroup(evlist, name); return cgroup ?: cgroup__new(name); } -static int add_cgroup(struct perf_evlist *evlist, const char *str) +static int add_cgroup(struct evlist *evlist, const char *str) { struct evsel *counter; struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str); @@ -190,7 +190,7 @@ static void evsel__set_default_cgroup(struct evsel *evsel, struct cgroup *cgroup evsel->cgrp = cgroup__get(cgroup); } -void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup) +void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup) { struct evsel *evsel; @@ -201,7 +201,7 @@ void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgrou int parse_cgroups(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; struct evsel *counter; struct cgroup *cgrp = NULL; const char *p, *e, *eos = str + strlen(str); diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h index f033a80c1b14..2ec11f01090d 100644 --- a/tools/perf/util/cgroup.h +++ b/tools/perf/util/cgroup.h @@ -18,11 +18,11 @@ extern int nr_cgroups; /* number of explicit cgroups defined */ struct cgroup *cgroup__get(struct cgroup *cgroup); void cgroup__put(struct cgroup *cgroup); -struct perf_evlist; +struct evlist; -struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name); +struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name); -void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup); +void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup); int parse_cgroups(const struct option *opt, const char *str, int unset); diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 5a9fcb60ec88..c1df366f4519 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1222,7 +1222,7 @@ static int cs_etm__synth_event(struct perf_session *session, static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel; struct perf_event_attr attr; bool found = false; @@ -2295,7 +2295,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm) { struct evsel *evsel; - struct perf_evlist *evlist = etm->session->evlist; + struct evlist *evlist = etm->session->evlist; bool timeless_decoding = true; /* diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 042ee5b6f9f1..083101ae7b77 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -1201,7 +1201,7 @@ static int add_event(struct ctf_writer *cw, struct evsel *evsel) static int setup_events(struct ctf_writer *cw, struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel; int ret; @@ -1308,7 +1308,7 @@ static int setup_non_sample_events(struct ctf_writer *cw, static void cleanup_events(struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7e6066cb525b..c234fa4ba92a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -41,7 +41,7 @@ int sigqueue(pid_t pid, int sig, const union sigval value); #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) -void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, +void perf_evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads) { int i; @@ -55,9 +55,9 @@ void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, evlist->bkw_mmap_state = BKW_MMAP_NOTREADY; } -struct perf_evlist *perf_evlist__new(void) +struct evlist *perf_evlist__new(void) { - struct perf_evlist *evlist = zalloc(sizeof(*evlist)); + struct evlist *evlist = zalloc(sizeof(*evlist)); if (evlist != NULL) perf_evlist__init(evlist, NULL, NULL); @@ -65,9 +65,9 @@ struct perf_evlist *perf_evlist__new(void) return evlist; } -struct perf_evlist *perf_evlist__new_default(void) +struct evlist *perf_evlist__new_default(void) { - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist && perf_evlist__add_default(evlist)) { perf_evlist__delete(evlist); @@ -77,9 +77,9 @@ struct perf_evlist *perf_evlist__new_default(void) return evlist; } -struct perf_evlist *perf_evlist__new_dummy(void) +struct evlist *perf_evlist__new_dummy(void) { - struct perf_evlist *evlist = perf_evlist__new(); + struct evlist *evlist = perf_evlist__new(); if (evlist && perf_evlist__add_dummy(evlist)) { perf_evlist__delete(evlist); @@ -96,7 +96,7 @@ struct perf_evlist *perf_evlist__new_dummy(void) * Events with compatible sample types all have the same id_pos * and is_pos. For convenience, put a copy on evlist. */ -void perf_evlist__set_id_pos(struct perf_evlist *evlist) +void perf_evlist__set_id_pos(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); @@ -104,7 +104,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist) evlist->is_pos = first->is_pos; } -static void perf_evlist__update_id_pos(struct perf_evlist *evlist) +static void perf_evlist__update_id_pos(struct evlist *evlist) { struct evsel *evsel; @@ -114,7 +114,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist) perf_evlist__set_id_pos(evlist); } -static void perf_evlist__purge(struct perf_evlist *evlist) +static void perf_evlist__purge(struct evlist *evlist) { struct evsel *pos, *n; @@ -127,14 +127,14 @@ static void perf_evlist__purge(struct perf_evlist *evlist) evlist->nr_entries = 0; } -void perf_evlist__exit(struct perf_evlist *evlist) +void perf_evlist__exit(struct evlist *evlist) { zfree(&evlist->mmap); zfree(&evlist->overwrite_mmap); fdarray__exit(&evlist->pollfd); } -void perf_evlist__delete(struct perf_evlist *evlist) +void perf_evlist__delete(struct evlist *evlist) { if (evlist == NULL) return; @@ -150,7 +150,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) free(evlist); } -static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, +static void __perf_evlist__propagate_maps(struct evlist *evlist, struct evsel *evsel) { /* @@ -169,7 +169,7 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, evsel->threads = thread_map__get(evlist->threads); } -static void perf_evlist__propagate_maps(struct perf_evlist *evlist) +static void perf_evlist__propagate_maps(struct evlist *evlist) { struct evsel *evsel; @@ -177,7 +177,7 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist) __perf_evlist__propagate_maps(evlist, evsel); } -void perf_evlist__add(struct perf_evlist *evlist, struct evsel *entry) +void perf_evlist__add(struct evlist *evlist, struct evsel *entry) { entry->evlist = evlist; list_add_tail(&entry->node, &evlist->entries); @@ -190,14 +190,14 @@ void perf_evlist__add(struct perf_evlist *evlist, struct evsel *entry) __perf_evlist__propagate_maps(evlist, entry); } -void perf_evlist__remove(struct perf_evlist *evlist, struct evsel *evsel) +void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; list_del_init(&evsel->node); evlist->nr_entries -= 1; } -void perf_evlist__splice_list_tail(struct perf_evlist *evlist, +void perf_evlist__splice_list_tail(struct evlist *evlist, struct list_head *list) { struct evsel *evsel, *temp; @@ -222,7 +222,7 @@ void __perf_evlist__set_leader(struct list_head *list) } } -void perf_evlist__set_leader(struct perf_evlist *evlist) +void perf_evlist__set_leader(struct evlist *evlist) { if (evlist->nr_entries) { evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; @@ -230,7 +230,7 @@ void perf_evlist__set_leader(struct perf_evlist *evlist) } } -int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise) +int __perf_evlist__add_default(struct evlist *evlist, bool precise) { struct evsel *evsel = perf_evsel__new_cycles(precise); @@ -241,7 +241,7 @@ int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise) return 0; } -int perf_evlist__add_dummy(struct perf_evlist *evlist) +int perf_evlist__add_dummy(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, @@ -257,7 +257,7 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist) return 0; } -static int perf_evlist__add_attrs(struct perf_evlist *evlist, +static int perf_evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; @@ -281,7 +281,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, return -1; } -int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, +int __perf_evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { size_t i; @@ -293,7 +293,7 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, } struct evsel * -perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) +perf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id) { struct evsel *evsel; @@ -307,7 +307,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) } struct evsel * -perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, +perf_evlist__find_tracepoint_by_name(struct evlist *evlist, const char *name) { struct evsel *evsel; @@ -321,7 +321,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, return NULL; } -int perf_evlist__add_newtp(struct perf_evlist *evlist, +int perf_evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler) { struct evsel *evsel = perf_evsel__newtp(sys, name); @@ -334,7 +334,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, return 0; } -static int perf_evlist__nr_threads(struct perf_evlist *evlist, +static int perf_evlist__nr_threads(struct evlist *evlist, struct evsel *evsel) { if (evsel->system_wide) @@ -343,7 +343,7 @@ static int perf_evlist__nr_threads(struct perf_evlist *evlist, return thread_map__nr(evlist->threads); } -void perf_evlist__disable(struct perf_evlist *evlist) +void perf_evlist__disable(struct evlist *evlist) { struct evsel *pos; @@ -356,7 +356,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) evlist->enabled = false; } -void perf_evlist__enable(struct perf_evlist *evlist) +void perf_evlist__enable(struct evlist *evlist) { struct evsel *pos; @@ -369,12 +369,12 @@ void perf_evlist__enable(struct perf_evlist *evlist) evlist->enabled = true; } -void perf_evlist__toggle_enable(struct perf_evlist *evlist) +void perf_evlist__toggle_enable(struct evlist *evlist) { (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist); } -static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, +static int perf_evlist__enable_event_cpu(struct evlist *evlist, struct evsel *evsel, int cpu) { int thread; @@ -391,7 +391,7 @@ static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, return 0; } -static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, +static int perf_evlist__enable_event_thread(struct evlist *evlist, struct evsel *evsel, int thread) { @@ -409,7 +409,7 @@ static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, return 0; } -int perf_evlist__enable_event_idx(struct perf_evlist *evlist, +int perf_evlist__enable_event_idx(struct evlist *evlist, struct evsel *evsel, int idx) { bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus); @@ -420,7 +420,7 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist, return perf_evlist__enable_event_thread(evlist, evsel, idx); } -int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) +int perf_evlist__alloc_pollfd(struct evlist *evlist) { int nr_cpus = cpu_map__nr(evlist->cpus); int nr_threads = thread_map__nr(evlist->threads); @@ -441,7 +441,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) return 0; } -static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, +static int __perf_evlist__add_pollfd(struct evlist *evlist, int fd, struct perf_mmap *map, short revent) { int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP); @@ -458,7 +458,7 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, return pos; } -int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) +int perf_evlist__add_pollfd(struct evlist *evlist, int fd) { return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN); } @@ -472,18 +472,18 @@ static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd, perf_mmap__put(map); } -int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) +int perf_evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask) { return fdarray__filter(&evlist->pollfd, revents_and_mask, perf_evlist__munmap_filtered, NULL); } -int perf_evlist__poll(struct perf_evlist *evlist, int timeout) +int perf_evlist__poll(struct evlist *evlist, int timeout) { return fdarray__poll(&evlist->pollfd, timeout); } -static void perf_evlist__id_hash(struct perf_evlist *evlist, +static void perf_evlist__id_hash(struct evlist *evlist, struct evsel *evsel, int cpu, int thread, u64 id) { @@ -496,14 +496,14 @@ static void perf_evlist__id_hash(struct perf_evlist *evlist, hlist_add_head(&sid->node, &evlist->heads[hash]); } -void perf_evlist__id_add(struct perf_evlist *evlist, struct evsel *evsel, +void perf_evlist__id_add(struct evlist *evlist, struct evsel *evsel, int cpu, int thread, u64 id) { perf_evlist__id_hash(evlist, evsel, cpu, thread, id); evsel->id[evsel->ids++] = id; } -int perf_evlist__id_add_fd(struct perf_evlist *evlist, +int perf_evlist__id_add_fd(struct evlist *evlist, struct evsel *evsel, int cpu, int thread, int fd) { @@ -544,7 +544,7 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist, return 0; } -static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, +static void perf_evlist__set_sid_idx(struct evlist *evlist, struct evsel *evsel, int idx, int cpu, int thread) { @@ -560,7 +560,7 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, sid->tid = -1; } -struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) +struct perf_sample_id *perf_evlist__id2sid(struct evlist *evlist, u64 id) { struct hlist_head *head; struct perf_sample_id *sid; @@ -576,7 +576,7 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) return NULL; } -struct evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) +struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) { struct perf_sample_id *sid; @@ -593,7 +593,7 @@ struct evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) return NULL; } -struct evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, +struct evsel *perf_evlist__id2evsel_strict(struct evlist *evlist, u64 id) { struct perf_sample_id *sid; @@ -608,7 +608,7 @@ struct evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, return NULL; } -static int perf_evlist__event2id(struct perf_evlist *evlist, +static int perf_evlist__event2id(struct evlist *evlist, union perf_event *event, u64 *id) { const u64 *array = event->sample.array; @@ -629,7 +629,7 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, return 0; } -struct evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, +struct evsel *perf_evlist__event2evsel(struct evlist *evlist, union perf_event *event) { struct evsel *first = perf_evlist__first(evlist); @@ -662,7 +662,7 @@ struct evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, return NULL; } -static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) +static int perf_evlist__set_paused(struct evlist *evlist, bool value) { int i; @@ -682,17 +682,17 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) return 0; } -static int perf_evlist__pause(struct perf_evlist *evlist) +static int perf_evlist__pause(struct evlist *evlist) { return perf_evlist__set_paused(evlist, true); } -static int perf_evlist__resume(struct perf_evlist *evlist) +static int perf_evlist__resume(struct evlist *evlist) { return perf_evlist__set_paused(evlist, false); } -static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) +static void perf_evlist__munmap_nofree(struct evlist *evlist) { int i; @@ -705,14 +705,14 @@ static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) perf_mmap__munmap(&evlist->overwrite_mmap[i]); } -void perf_evlist__munmap(struct perf_evlist *evlist) +void perf_evlist__munmap(struct evlist *evlist) { perf_evlist__munmap_nofree(evlist); zfree(&evlist->mmap); zfree(&evlist->overwrite_mmap); } -static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist, +static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, bool overwrite) { int i; @@ -743,7 +743,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist, } static bool -perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, +perf_evlist__should_poll(struct evlist *evlist __maybe_unused, struct evsel *evsel) { if (evsel->attr.write_backward) @@ -751,7 +751,7 @@ perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, return true; } -static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, +static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, struct mmap_params *mp, int cpu_idx, int thread, int *_output, int *_output_overwrite) { @@ -829,7 +829,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, return 0; } -static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, +static int perf_evlist__mmap_per_cpu(struct evlist *evlist, struct mmap_params *mp) { int cpu, thread; @@ -858,7 +858,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, return -1; } -static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, +static int perf_evlist__mmap_per_thread(struct evlist *evlist, struct mmap_params *mp) { int thread; @@ -1006,7 +1006,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, * * Return: %0 on success, negative error code otherwise. */ -int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, +int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, unsigned int auxtrace_pages, bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush, int comp_level) @@ -1050,12 +1050,12 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, return perf_evlist__mmap_per_cpu(evlist, &mp); } -int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages) +int perf_evlist__mmap(struct evlist *evlist, unsigned int pages) { return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1, 0); } -int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) +int perf_evlist__create_maps(struct evlist *evlist, struct target *target) { bool all_threads = (target->per_thread && target->system_wide); struct perf_cpu_map *cpus; @@ -1104,7 +1104,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) return -1; } -void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, +void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads) { /* @@ -1127,7 +1127,7 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus perf_evlist__propagate_maps(evlist); } -void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, +void __perf_evlist__set_sample_bit(struct evlist *evlist, enum perf_event_sample_format bit) { struct evsel *evsel; @@ -1136,7 +1136,7 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, __perf_evsel__set_sample_bit(evsel, bit); } -void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, +void __perf_evlist__reset_sample_bit(struct evlist *evlist, enum perf_event_sample_format bit) { struct evsel *evsel; @@ -1145,7 +1145,7 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, __perf_evsel__reset_sample_bit(evsel, bit); } -int perf_evlist__apply_filters(struct perf_evlist *evlist, struct evsel **err_evsel) +int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel) { struct evsel *evsel; int err = 0; @@ -1168,7 +1168,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct evsel **err_ev return err; } -int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter) +int perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter) { struct evsel *evsel; int err = 0; @@ -1185,7 +1185,7 @@ int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter) return err; } -int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids) +int perf_evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids) { char *filter; int ret = -1; @@ -1212,12 +1212,12 @@ int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pi return ret; } -int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid) +int perf_evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid) { return perf_evlist__set_tp_filter_pids(evlist, 1, &pid); } -bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; @@ -1236,7 +1236,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) return true; } -u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) +u64 __perf_evlist__combined_sample_type(struct evlist *evlist) { struct evsel *evsel; @@ -1249,13 +1249,13 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) return evlist->combined_sample_type; } -u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) +u64 perf_evlist__combined_sample_type(struct evlist *evlist) { evlist->combined_sample_type = 0; return __perf_evlist__combined_sample_type(evlist); } -u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) +u64 perf_evlist__combined_branch_type(struct evlist *evlist) { struct evsel *evsel; u64 branch_type = 0; @@ -1265,7 +1265,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) return branch_type; } -bool perf_evlist__valid_read_format(struct perf_evlist *evlist) +bool perf_evlist__valid_read_format(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist), *pos = first; u64 read_format = first->attr.read_format; @@ -1285,13 +1285,13 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) return true; } -u64 perf_evlist__read_format(struct perf_evlist *evlist) +u64 perf_evlist__read_format(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); return first->attr.read_format; } -u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) +u16 perf_evlist__id_hdr_size(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); struct perf_sample *data; @@ -1324,7 +1324,7 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) return size; } -bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_id_all(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist), *pos = first; @@ -1336,19 +1336,19 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct perf_evlist *evlist) +bool perf_evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); return first->attr.sample_id_all; } -void perf_evlist__set_selected(struct perf_evlist *evlist, +void perf_evlist__set_selected(struct evlist *evlist, struct evsel *evsel) { evlist->selected = evsel; } -void perf_evlist__close(struct perf_evlist *evlist) +void perf_evlist__close(struct evlist *evlist) { struct evsel *evsel; @@ -1356,7 +1356,7 @@ void perf_evlist__close(struct perf_evlist *evlist) perf_evsel__close(evsel); } -static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) +static int perf_evlist__create_syswide_maps(struct evlist *evlist) { struct perf_cpu_map *cpus; struct perf_thread_map *threads; @@ -1387,7 +1387,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) goto out; } -int perf_evlist__open(struct perf_evlist *evlist) +int perf_evlist__open(struct evlist *evlist) { struct evsel *evsel; int err; @@ -1417,7 +1417,7 @@ int perf_evlist__open(struct perf_evlist *evlist) return err; } -int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, +int perf_evlist__prepare_workload(struct evlist *evlist, struct target *target, const char *argv[], bool pipe_output, void (*exec_error)(int signo, siginfo_t *info, void *ucontext)) { @@ -1531,7 +1531,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar return -1; } -int perf_evlist__start_workload(struct perf_evlist *evlist) +int perf_evlist__start_workload(struct evlist *evlist) { if (evlist->workload.cork_fd > 0) { char bf = 0; @@ -1550,7 +1550,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) return 0; } -int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, +int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { struct evsel *evsel = perf_evlist__event2evsel(evlist, event); @@ -1560,7 +1560,7 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even return perf_evsel__parse_sample(evsel, event, sample); } -int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, +int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp) { @@ -1571,7 +1571,7 @@ int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, return perf_evsel__parse_sample_timestamp(evsel, event, timestamp); } -size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) +size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp) { struct evsel *evsel; size_t printed = 0; @@ -1584,7 +1584,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) return printed + fprintf(fp, "\n"); } -int perf_evlist__strerror_open(struct perf_evlist *evlist, +int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size) { int printed, value; @@ -1638,7 +1638,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist, return 0; } -int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) +int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) { char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; @@ -1669,7 +1669,7 @@ int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, s return 0; } -void perf_evlist__to_front(struct perf_evlist *evlist, +void perf_evlist__to_front(struct evlist *evlist, struct evsel *move_evsel) { struct evsel *evsel, *n; @@ -1686,7 +1686,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist, list_splice(&move, &evlist->entries); } -void perf_evlist__set_tracking_event(struct perf_evlist *evlist, +void perf_evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_evsel) { struct evsel *evsel; @@ -1703,7 +1703,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, } struct evsel * -perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, +perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str) { struct evsel *evsel; @@ -1718,7 +1718,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, return NULL; } -void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, +void perf_evlist__toggle_bkw_mmap(struct evlist *evlist, enum bkw_mmap_state state) { enum bkw_mmap_state old_state = evlist->bkw_mmap_state; @@ -1776,7 +1776,7 @@ void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, return; } -bool perf_evlist__exclude_kernel(struct perf_evlist *evlist) +bool perf_evlist__exclude_kernel(struct evlist *evlist) { struct evsel *evsel; @@ -1793,7 +1793,7 @@ bool perf_evlist__exclude_kernel(struct perf_evlist *evlist) * the group display. Set the artificial group and set the leader's * forced_leader flag to notify the display code. */ -void perf_evlist__force_leader(struct perf_evlist *evlist) +void perf_evlist__force_leader(struct evlist *evlist) { if (!evlist->nr_groups) { struct evsel *leader = perf_evlist__first(evlist); @@ -1803,7 +1803,7 @@ void perf_evlist__force_leader(struct perf_evlist *evlist) } } -struct evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, +struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, struct evsel *evsel) { struct evsel *c2, *leader; @@ -1830,7 +1830,7 @@ struct evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, return leader; } -int perf_evlist__add_sb_event(struct perf_evlist **evlist, +int perf_evlist__add_sb_event(struct evlist **evlist, struct perf_event_attr *attr, perf_evsel__sb_cb_t cb, void *data) @@ -1867,7 +1867,7 @@ int perf_evlist__add_sb_event(struct perf_evlist **evlist, static void *perf_evlist__poll_thread(void *arg) { - struct perf_evlist *evlist = arg; + struct evlist *evlist = arg; bool draining = false; int i, done = 0; @@ -1906,7 +1906,7 @@ static void *perf_evlist__poll_thread(void *arg) return NULL; } -int perf_evlist__start_sb_thread(struct perf_evlist *evlist, +int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target) { struct evsel *counter; @@ -1943,7 +1943,7 @@ int perf_evlist__start_sb_thread(struct perf_evlist *evlist, return -1; } -void perf_evlist__stop_sb_thread(struct perf_evlist *evlist) +void perf_evlist__stop_sb_thread(struct evlist *evlist) { if (!evlist) return; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 576d59a0d8cf..54f1c3e2b721 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -24,7 +24,7 @@ struct record_opts; #define PERF_EVLIST__HLIST_BITS 8 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) -struct perf_evlist { +struct evlist { struct list_head entries; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; @@ -49,7 +49,7 @@ struct perf_evlist { struct evsel *selected; struct events_stats stats; struct perf_env *env; - void (*trace_event_sample_raw)(struct perf_evlist *evlist, + void (*trace_event_sample_raw)(struct evlist *evlist, union perf_event *event, struct perf_sample *sample); u64 first_sample_time; @@ -65,46 +65,46 @@ struct evsel_str_handler { void *handler; }; -struct perf_evlist *perf_evlist__new(void); -struct perf_evlist *perf_evlist__new_default(void); -struct perf_evlist *perf_evlist__new_dummy(void); -void perf_evlist__init(struct perf_evlist *evlist, struct perf_cpu_map *cpus, +struct evlist *perf_evlist__new(void); +struct evlist *perf_evlist__new_default(void); +struct evlist *perf_evlist__new_dummy(void); +void perf_evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads); -void perf_evlist__exit(struct perf_evlist *evlist); -void perf_evlist__delete(struct perf_evlist *evlist); +void perf_evlist__exit(struct evlist *evlist); +void perf_evlist__delete(struct evlist *evlist); -void perf_evlist__add(struct perf_evlist *evlist, struct evsel *entry); -void perf_evlist__remove(struct perf_evlist *evlist, struct evsel *evsel); +void perf_evlist__add(struct evlist *evlist, struct evsel *entry); +void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel); -int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise); +int __perf_evlist__add_default(struct evlist *evlist, bool precise); -static inline int perf_evlist__add_default(struct perf_evlist *evlist) +static inline int perf_evlist__add_default(struct evlist *evlist) { return __perf_evlist__add_default(evlist, true); } -int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, +int __perf_evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); #define perf_evlist__add_default_attrs(evlist, array) \ __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__add_dummy(struct perf_evlist *evlist); +int perf_evlist__add_dummy(struct evlist *evlist); -int perf_evlist__add_sb_event(struct perf_evlist **evlist, +int perf_evlist__add_sb_event(struct evlist **evlist, struct perf_event_attr *attr, perf_evsel__sb_cb_t cb, void *data); -int perf_evlist__start_sb_thread(struct perf_evlist *evlist, +int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target); -void perf_evlist__stop_sb_thread(struct perf_evlist *evlist); +void perf_evlist__stop_sb_thread(struct evlist *evlist); -int perf_evlist__add_newtp(struct perf_evlist *evlist, +int perf_evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler); -void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, +void __perf_evlist__set_sample_bit(struct evlist *evlist, enum perf_event_sample_format bit); -void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, +void __perf_evlist__reset_sample_bit(struct evlist *evlist, enum perf_event_sample_format bit); #define perf_evlist__set_sample_bit(evlist, bit) \ @@ -113,58 +113,58 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, #define perf_evlist__reset_sample_bit(evlist, bit) \ __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit) -int perf_evlist__set_tp_filter(struct perf_evlist *evlist, const char *filter); -int perf_evlist__set_tp_filter_pid(struct perf_evlist *evlist, pid_t pid); -int perf_evlist__set_tp_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids); +int perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter); +int perf_evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid); +int perf_evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids); struct evsel * -perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); +perf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id); struct evsel * -perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, +perf_evlist__find_tracepoint_by_name(struct evlist *evlist, const char *name); -void perf_evlist__id_add(struct perf_evlist *evlist, struct evsel *evsel, +void perf_evlist__id_add(struct evlist *evlist, struct evsel *evsel, int cpu, int thread, u64 id); -int perf_evlist__id_add_fd(struct perf_evlist *evlist, +int perf_evlist__id_add_fd(struct evlist *evlist, struct evsel *evsel, int cpu, int thread, int fd); -int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); -int perf_evlist__alloc_pollfd(struct perf_evlist *evlist); -int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask); +int perf_evlist__add_pollfd(struct evlist *evlist, int fd); +int perf_evlist__alloc_pollfd(struct evlist *evlist); +int perf_evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask); -int perf_evlist__poll(struct perf_evlist *evlist, int timeout); +int perf_evlist__poll(struct evlist *evlist, int timeout); -struct evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); -struct evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, +struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id); +struct evsel *perf_evlist__id2evsel_strict(struct evlist *evlist, u64 id); -struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); +struct perf_sample_id *perf_evlist__id2sid(struct evlist *evlist, u64 id); -void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); +void perf_evlist__toggle_bkw_mmap(struct evlist *evlist, enum bkw_mmap_state state); -void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); +void perf_evlist__mmap_consume(struct evlist *evlist, int idx); -int perf_evlist__open(struct perf_evlist *evlist); -void perf_evlist__close(struct perf_evlist *evlist); +int perf_evlist__open(struct evlist *evlist); +void perf_evlist__close(struct evlist *evlist); struct callchain_param; -void perf_evlist__set_id_pos(struct perf_evlist *evlist); +void perf_evlist__set_id_pos(struct evlist *evlist); bool perf_can_sample_identifier(void); bool perf_can_record_switch_events(void); bool perf_can_record_cpu_wide(void); -void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, +void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, struct callchain_param *callchain); int record_opts__config(struct record_opts *opts); -int perf_evlist__prepare_workload(struct perf_evlist *evlist, +int perf_evlist__prepare_workload(struct evlist *evlist, struct target *target, const char *argv[], bool pipe_output, void (*exec_error)(int signo, siginfo_t *info, void *ucontext)); -int perf_evlist__start_workload(struct perf_evlist *evlist); +int perf_evlist__start_workload(struct evlist *evlist); struct option; @@ -175,76 +175,76 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, unsigned long perf_event_mlock_kb_in_pages(void); -int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, +int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, unsigned int auxtrace_pages, bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush, int comp_level); -int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages); -void perf_evlist__munmap(struct perf_evlist *evlist); +int perf_evlist__mmap(struct evlist *evlist, unsigned int pages); +void perf_evlist__munmap(struct evlist *evlist); size_t perf_evlist__mmap_size(unsigned long pages); -void perf_evlist__disable(struct perf_evlist *evlist); -void perf_evlist__enable(struct perf_evlist *evlist); -void perf_evlist__toggle_enable(struct perf_evlist *evlist); +void perf_evlist__disable(struct evlist *evlist); +void perf_evlist__enable(struct evlist *evlist); +void perf_evlist__toggle_enable(struct evlist *evlist); -int perf_evlist__enable_event_idx(struct perf_evlist *evlist, +int perf_evlist__enable_event_idx(struct evlist *evlist, struct evsel *evsel, int idx); -void perf_evlist__set_selected(struct perf_evlist *evlist, +void perf_evlist__set_selected(struct evlist *evlist, struct evsel *evsel); -void perf_evlist__set_maps(struct perf_evlist *evlist, struct perf_cpu_map *cpus, +void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads); -int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); -int perf_evlist__apply_filters(struct perf_evlist *evlist, struct evsel **err_evsel); +int perf_evlist__create_maps(struct evlist *evlist, struct target *target); +int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); -void perf_evlist__set_leader(struct perf_evlist *evlist); +void perf_evlist__set_leader(struct evlist *evlist); -u64 perf_evlist__read_format(struct perf_evlist *evlist); -u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist); -u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist); -u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist); -bool perf_evlist__sample_id_all(struct perf_evlist *evlist); -u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist); +u64 perf_evlist__read_format(struct evlist *evlist); +u64 __perf_evlist__combined_sample_type(struct evlist *evlist); +u64 perf_evlist__combined_sample_type(struct evlist *evlist); +u64 perf_evlist__combined_branch_type(struct evlist *evlist); +bool perf_evlist__sample_id_all(struct evlist *evlist); +u16 perf_evlist__id_hdr_size(struct evlist *evlist); -int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, +int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample); -int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist, +int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp); -bool perf_evlist__valid_sample_type(struct perf_evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist); -bool perf_evlist__valid_read_format(struct perf_evlist *evlist); +bool perf_evlist__valid_sample_type(struct evlist *evlist); +bool perf_evlist__valid_sample_id_all(struct evlist *evlist); +bool perf_evlist__valid_read_format(struct evlist *evlist); -void perf_evlist__splice_list_tail(struct perf_evlist *evlist, +void perf_evlist__splice_list_tail(struct evlist *evlist, struct list_head *list); -static inline bool perf_evlist__empty(struct perf_evlist *evlist) +static inline bool perf_evlist__empty(struct evlist *evlist) { return list_empty(&evlist->entries); } -static inline struct evsel *perf_evlist__first(struct perf_evlist *evlist) +static inline struct evsel *perf_evlist__first(struct evlist *evlist) { return list_entry(evlist->entries.next, struct evsel, node); } -static inline struct evsel *perf_evlist__last(struct perf_evlist *evlist) +static inline struct evsel *perf_evlist__last(struct evlist *evlist) { return list_entry(evlist->entries.prev, struct evsel, node); } -size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); +size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp); -int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); +int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); +int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); -bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str); -void perf_evlist__to_front(struct perf_evlist *evlist, +bool perf_evlist__can_select_event(struct evlist *evlist, const char *str); +void perf_evlist__to_front(struct evlist *evlist, struct evsel *move_evsel); /** @@ -313,19 +313,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist, #define evlist__for_each_entry_safe(evlist, tmp, evsel) \ __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel) -void perf_evlist__set_tracking_event(struct perf_evlist *evlist, +void perf_evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_evsel); struct evsel * -perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); +perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str); -struct evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, +struct evsel *perf_evlist__event2evsel(struct evlist *evlist, union perf_event *event); -bool perf_evlist__exclude_kernel(struct perf_evlist *evlist); +bool perf_evlist__exclude_kernel(struct evlist *evlist); -void perf_evlist__force_leader(struct perf_evlist *evlist); +void perf_evlist__force_leader(struct evlist *evlist); -struct evsel *perf_evlist__reset_weak_group(struct perf_evlist *evlist, +struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist, struct evsel *evsel); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 44421bbebd64..f7f97ca6e96d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3044,7 +3044,7 @@ struct perf_env *perf_evsel__env(struct evsel *evsel) return NULL; } -static int store_evsel_ids(struct evsel *evsel, struct perf_evlist *evlist) +static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) { int cpu, thread; @@ -3062,7 +3062,7 @@ static int store_evsel_ids(struct evsel *evsel, struct perf_evlist *evlist) return 0; } -int perf_evsel__store_ids(struct evsel *evsel, struct perf_evlist *evlist) +int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist) { struct perf_cpu_map *cpus = evsel->cpus; struct perf_thread_map *threads = evsel->threads; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 2c31c5e99524..3caabd8a4aa6 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -102,7 +102,7 @@ struct bpf_object; */ struct evsel { struct list_head node; - struct perf_evlist *evlist; + struct evlist *evlist; struct perf_event_attr attr; char *filter; struct xyarray *fd; @@ -506,5 +506,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, struct perf_env *perf_evsel__env(struct evsel *evsel); -int perf_evsel__store_ids(struct evsel *evsel, struct perf_evlist *evlist); +int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist); #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 132bbc29f977..692fe8ac12ae 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -299,7 +299,7 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize) } static int write_tracing_data(struct feat_fd *ff, - struct perf_evlist *evlist) + struct evlist *evlist) { if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) return -1; @@ -308,7 +308,7 @@ static int write_tracing_data(struct feat_fd *ff, } static int write_build_id(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_session *session; int err; @@ -332,7 +332,7 @@ static int write_build_id(struct feat_fd *ff, } static int write_hostname(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -345,7 +345,7 @@ static int write_hostname(struct feat_fd *ff, } static int write_osrelease(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -358,7 +358,7 @@ static int write_osrelease(struct feat_fd *ff, } static int write_arch(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -371,7 +371,7 @@ static int write_arch(struct feat_fd *ff, } static int write_version(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return do_write_string(ff, perf_version_string); } @@ -432,7 +432,7 @@ static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc) } static int write_cpudesc(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { const char *cpuinfo_procs[] = CPUINFO_PROC; unsigned int i; @@ -448,7 +448,7 @@ static int write_cpudesc(struct feat_fd *ff, static int write_nrcpus(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { long nr; u32 nrc, nra; @@ -470,7 +470,7 @@ static int write_nrcpus(struct feat_fd *ff, } static int write_event_desc(struct feat_fd *ff, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *evsel; u32 nre, nri, sz; @@ -526,7 +526,7 @@ static int write_event_desc(struct feat_fd *ff, } static int write_cmdline(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { char pbuf[MAXPATHLEN], *buf; int i, ret, n; @@ -555,7 +555,7 @@ static int write_cmdline(struct feat_fd *ff, static int write_cpu_topology(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct cpu_topology *tp; u32 i; @@ -627,7 +627,7 @@ static int write_cpu_topology(struct feat_fd *ff, static int write_total_mem(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { char *buf = NULL; FILE *fp; @@ -656,7 +656,7 @@ static int write_total_mem(struct feat_fd *ff, } static int write_numa_topology(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct numa_topology *tp; int ret = -1; @@ -710,7 +710,7 @@ static int write_numa_topology(struct feat_fd *ff, */ static int write_pmu_mappings(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_pmu *pmu = NULL; u32 pmu_num = 0; @@ -759,7 +759,7 @@ static int write_pmu_mappings(struct feat_fd *ff, * }; */ static int write_group_desc(struct feat_fd *ff, - struct perf_evlist *evlist) + struct evlist *evlist) { u32 nr_groups = evlist->nr_groups; struct evsel *evsel; @@ -841,7 +841,7 @@ int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused) } static int write_cpuid(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { char buffer[64]; int ret; @@ -854,13 +854,13 @@ static int write_cpuid(struct feat_fd *ff, } static int write_branch_stack(struct feat_fd *ff __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return 0; } static int write_auxtrace(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_session *session; int err; @@ -877,14 +877,14 @@ static int write_auxtrace(struct feat_fd *ff, } static int write_clockid(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return do_write(ff, &ff->ph->env.clockid_res_ns, sizeof(ff->ph->env.clockid_res_ns)); } static int write_dir_format(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_session *session; struct perf_data *data; @@ -900,7 +900,7 @@ static int write_dir_format(struct feat_fd *ff, #ifdef HAVE_LIBBPF_SUPPORT static int write_bpf_prog_info(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_env *env = &ff->ph->env; struct rb_root *root; @@ -942,14 +942,14 @@ static int write_bpf_prog_info(struct feat_fd *ff, } #else // HAVE_LIBBPF_SUPPORT static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return 0; } #endif // HAVE_LIBBPF_SUPPORT static int write_bpf_btf(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct perf_env *env = &ff->ph->env; struct rb_root *root; @@ -1123,7 +1123,7 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp) #define MAX_CACHES (MAX_NR_CPUS * 4) static int write_cache(struct feat_fd *ff, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { struct cpu_cache_level caches[MAX_CACHES]; u32 cnt = 0, i, version = 1; @@ -1175,13 +1175,13 @@ static int write_cache(struct feat_fd *ff, } static int write_stat(struct feat_fd *ff __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { return 0; } static int write_sample_time(struct feat_fd *ff, - struct perf_evlist *evlist) + struct evlist *evlist) { int ret; @@ -1315,7 +1315,7 @@ static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp) * 48 - bitmap | bitmap of memory indexes that belongs to node */ static int write_mem_topology(struct feat_fd *ff __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { static struct memory_node nodes[MAX_MEMORY_NODES]; u64 bsize, version = 1, i, nr; @@ -1365,7 +1365,7 @@ static int write_mem_topology(struct feat_fd *ff __maybe_unused, } static int write_compressed(struct feat_fd *ff __maybe_unused, - struct perf_evlist *evlist __maybe_unused) + struct evlist *evlist __maybe_unused) { int ret; @@ -2090,7 +2090,7 @@ static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused) } static struct evsel * -perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) +perf_evlist__find_by_index(struct evlist *evlist, int idx) { struct evsel *evsel; @@ -2103,7 +2103,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) } static void -perf_evlist__set_event_name(struct perf_evlist *evlist, +perf_evlist__set_event_name(struct evlist *evlist, struct evsel *event) { struct evsel *evsel; @@ -2801,7 +2801,7 @@ static int process_compressed(struct feat_fd *ff, } struct feature_ops { - int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); + int (*write)(struct feat_fd *ff, struct evlist *evlist); void (*print)(struct feat_fd *ff, FILE *fp); int (*process)(struct feat_fd *ff, void *data); const char *name; @@ -2946,7 +2946,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) static int do_write_feat(struct feat_fd *ff, int type, struct perf_file_section **p, - struct perf_evlist *evlist) + struct evlist *evlist) { int err; int ret = 0; @@ -2976,7 +2976,7 @@ static int do_write_feat(struct feat_fd *ff, int type, } static int perf_header__adds_write(struct perf_header *header, - struct perf_evlist *evlist, int fd) + struct evlist *evlist, int fd) { int nr_sections; struct feat_fd ff; @@ -3044,7 +3044,7 @@ int perf_header__write_pipe(int fd) } int perf_session__write_header(struct perf_session *session, - struct perf_evlist *evlist, + struct evlist *evlist, int fd, bool at_exit) { struct perf_file_header f_header; @@ -3511,7 +3511,7 @@ static int perf_evsel__prepare_tracepoint_event(struct evsel *evsel, return 0; } -static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, +static int perf_evlist__prepare_tracepoint_events(struct evlist *evlist, struct tep_handle *pevent) { struct evsel *pos; @@ -3669,7 +3669,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process) { struct perf_header *header = &session->header; @@ -3921,7 +3921,7 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) } int perf_event__synthesize_attrs(struct perf_tool *tool, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process) { struct evsel *evsel; @@ -3950,7 +3950,7 @@ static bool has_scale(struct evsel *counter) } int perf_event__synthesize_extra_attr(struct perf_tool *tool, - struct perf_evlist *evsel_list, + struct evlist *evsel_list, perf_event__handler_t process, bool is_pipe) { @@ -4009,11 +4009,11 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool, int perf_event__process_attr(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_evlist **pevlist) + struct evlist **pevlist) { u32 i, ids, n_ids; struct evsel *evsel; - struct perf_evlist *evlist = *pevlist; + struct evlist *evlist = *pevlist; if (evlist == NULL) { *pevlist = evlist = perf_evlist__new(); @@ -4047,12 +4047,12 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_evlist **pevlist) + struct evlist **pevlist) { struct event_update_event *ev = &event->event_update; struct event_update_event_scale *ev_scale; struct event_update_event_cpus *ev_cpus; - struct perf_evlist *evlist; + struct evlist *evlist; struct evsel *evsel; struct perf_cpu_map *map; @@ -4092,7 +4092,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, } int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process) { union perf_event ev; diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 437d8617de27..3e48ae3c49b1 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -92,12 +92,12 @@ struct perf_header { struct perf_env env; }; -struct perf_evlist; +struct evlist; struct perf_session; int perf_session__read_header(struct perf_session *session); int perf_session__write_header(struct perf_session *session, - struct perf_evlist *evlist, + struct evlist *evlist, int fd, bool at_exit); int perf_header__write_pipe(int fd); @@ -117,11 +117,11 @@ int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_extra_attr(struct perf_tool *tool, - struct perf_evlist *evsel_list, + struct evlist *evsel_list, perf_event__handler_t process, bool is_pipe); @@ -132,7 +132,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_attrs(struct perf_tool *tool, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_event_update_unit(struct perf_tool *tool, struct evsel *evsel, @@ -147,14 +147,14 @@ int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, - struct perf_evlist **pevlist); + struct evlist **pevlist); int perf_event__process_event_update(struct perf_tool *tool, union perf_event *event, - struct perf_evlist **pevlist); + struct evlist **pevlist); size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp); int perf_event__synthesize_tracing_data(struct perf_tool *tool, - int fd, struct perf_evlist *evlist, + int fd, struct evlist *evlist, perf_event__handler_t process); int perf_event__process_tracing_data(struct perf_session *session, union perf_event *event); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 3da49c479880..bb5437f549b6 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2573,7 +2573,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, } } -size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp) +size_t perf_evlist__fprintf_nr_events(struct evlist *evlist, FILE *fp) { struct evsel *pos; size_t ret = 0; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9bf247c638b8..83d5fc15429c 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -196,7 +196,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp, bool ignore_callchains); -size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); +size_t perf_evlist__fprintf_nr_events(struct evlist *evlist, FILE *fp); void hists__filter_by_dso(struct hists *hists); void hists__filter_by_thread(struct hists *hists); @@ -367,7 +367,7 @@ void perf_hpp__setup_output_field(struct perf_hpp_list *list); void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__append_sort_keys(struct perf_hpp_list *list); int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, - struct perf_evlist *evlist); + struct evlist *evlist); bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); @@ -432,7 +432,7 @@ static inline size_t perf_hpp__color_overhead(void) : 0; } -struct perf_evlist; +struct evlist; struct hist_browser_timer { void (*timer)(void *arg); @@ -461,7 +461,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *annotation_opts); -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, +int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help, struct hist_browser_timer *hbt, float min_pcnt, struct perf_env *env, @@ -476,7 +476,7 @@ int res_sample_browse(struct res_sample *res_samples, int num_res, void res_sample_init(void); #else static inline -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, +int perf_evlist__tui_browse_hists(struct evlist *evlist __maybe_unused, const char *help __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, float min_pcnt __maybe_unused, diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 8fd46d5f4b39..849a5b713b04 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -760,7 +760,7 @@ static int intel_bts_synth_event(struct perf_session *session, static int intel_bts_synth_events(struct intel_bts *bts, struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel; struct perf_event_attr attr; bool found = false; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index f1595b86d7c7..c88e3d1ee9c7 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -2713,7 +2713,7 @@ static int intel_pt_synth_event(struct perf_session *session, const char *name, return err; } -static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, +static void intel_pt_set_event_name(struct evlist *evlist, u64 id, const char *name) { struct evsel *evsel; @@ -2729,7 +2729,7 @@ static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, } static struct evsel *intel_pt_evsel(struct intel_pt *pt, - struct perf_evlist *evlist) + struct evlist *evlist) { struct evsel *evsel; @@ -2744,7 +2744,7 @@ static struct evsel *intel_pt_evsel(struct intel_pt *pt, static int intel_pt_synth_events(struct intel_pt *pt, struct perf_session *session) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct evsel *evsel = intel_pt_evsel(pt, evlist); struct perf_event_attr attr; u64 id; @@ -2894,7 +2894,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, return 0; } -static struct evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) +static struct evsel *intel_pt_find_sched_switch(struct evlist *evlist) { struct evsel *evsel; @@ -2908,7 +2908,7 @@ static struct evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) return NULL; } -static bool intel_pt_find_switch(struct perf_evlist *evlist) +static bool intel_pt_find_switch(struct evlist *evlist) { struct evsel *evsel; diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index 299edd32d3d4..a09c495f866b 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -7,7 +7,7 @@ #include "stat.h" struct evsel; -struct perf_evlist; +struct evlist; struct perf_session; struct event_key { @@ -74,7 +74,7 @@ struct exit_reasons_table { struct perf_kvm_stat { struct perf_tool tool; struct record_opts opts; - struct perf_evlist *evlist; + struct evlist *evlist; struct perf_session *session; const char *file_name; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 14c423974d63..fdb0d1c5c5cf 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -101,7 +101,7 @@ static bool record_evsel(int *ind, struct evsel **start, return false; } -static struct evsel *find_evsel_group(struct perf_evlist *perf_evlist, +static struct evsel *find_evsel_group(struct evlist *perf_evlist, const char **ids, int idnum, struct evsel **metric_events) @@ -140,7 +140,7 @@ static struct evsel *find_evsel_group(struct perf_evlist *perf_evlist, } static int metricgroup__setup_events(struct list_head *groups, - struct perf_evlist *perf_evlist, + struct evlist *perf_evlist, struct rblist *metric_events_list) { struct metric_event *me; @@ -502,7 +502,7 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct parse_events_error parse_error; - struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; + struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 177c41fc9842..42a5971146ae 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -150,7 +150,7 @@ void __weak auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp __maybe_u } void __weak auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp __maybe_unused, - struct perf_evlist *evlist __maybe_unused, + struct evlist *evlist __maybe_unused, int idx __maybe_unused, bool per_cpu __maybe_unused) { diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index dfde9cb31562..d341b11fb141 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1904,7 +1904,7 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct perf_evlist *evlist, const char *str, +int parse_events(struct evlist *evlist, const char *str, struct parse_events_error *err) { struct parse_events_state parse_state = { @@ -2013,7 +2013,7 @@ void parse_events_print_error(struct parse_events_error *err, int parse_events_option(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; struct parse_events_error err = { .idx = 0, }; int ret = parse_events(evlist, str, &err); @@ -2026,7 +2026,7 @@ int parse_events_option(const struct option *opt, const char *str, } static int -foreach_evsel_in_last_glob(struct perf_evlist *evlist, +foreach_evsel_in_last_glob(struct evlist *evlist, int (*func)(struct evsel *evsel, const void *arg), const void *arg) @@ -2109,7 +2109,7 @@ static int set_filter(struct evsel *evsel, const void *arg) int parse_filter(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; return foreach_evsel_in_last_glob(evlist, set_filter, (const void *)str); @@ -2141,7 +2141,7 @@ int exclude_perf(const struct option *opt, const char *arg __maybe_unused, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, NULL); diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 99e206598b60..48111b8fc232 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -13,7 +13,7 @@ struct list_head; struct evsel; -struct perf_evlist; +struct evlist; struct parse_events_error; struct option; @@ -31,7 +31,7 @@ bool have_tracepoints(struct list_head *evlist); const char *event_type(int type); int parse_events_option(const struct option *opt, const char *str, int unset); -int parse_events(struct perf_evlist *evlist, const char *str, +int parse_events(struct evlist *evlist, const char *str, struct parse_events_error *error); int parse_events_terms(struct list_head *terms, const char *str); int parse_filter(const struct option *opt, const char *str, int unset); @@ -119,7 +119,7 @@ struct parse_events_state { int idx; int nr_groups; struct parse_events_error *error; - struct perf_evlist *evlist; + struct evlist *evlist; struct list_head *terms; }; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index beafbd469b0c..ed57b6b5ed91 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -858,7 +858,7 @@ static int pyrf_evsel__setup_types(void) struct pyrf_evlist { PyObject_HEAD - struct perf_evlist evlist; + struct evlist evlist; }; static int pyrf_evlist__init(struct pyrf_evlist *pevlist, @@ -886,7 +886,7 @@ static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; static char *kwlist[] = { "pages", "overwrite", NULL }; int pages = 128, overwrite = false; @@ -906,7 +906,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; static char *kwlist[] = { "timeout", NULL }; int timeout = -1, n; @@ -926,7 +926,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, PyObject *args __maybe_unused, PyObject *kwargs __maybe_unused) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; PyObject *list = PyList_New(0); int i; @@ -964,7 +964,7 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs __maybe_unused) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; PyObject *pevsel; struct evsel *evsel; @@ -979,7 +979,7 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, return Py_BuildValue("i", evlist->nr_entries); } -static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu) +static struct perf_mmap *get_md(struct evlist *evlist, int cpu) { int i; @@ -996,7 +996,7 @@ static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu) static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; union perf_event *event; int sample_id_all = 1, cpu; static char *kwlist[] = { "cpu", "sample_id_all", NULL }; @@ -1049,7 +1049,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { - struct perf_evlist *evlist = &pevlist->evlist; + struct evlist *evlist = &pevlist->evlist; int group = 0; static char *kwlist[] = { "group", NULL }; diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index ef8f686729fd..a550d78a0b4d 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -13,7 +13,7 @@ typedef void (*setup_probe_fn_t)(struct evsel *evsel); static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) { - struct perf_evlist *evlist; + struct evlist *evlist; struct evsel *evsel; unsigned long flags = perf_event_open_cloexec_flag(); int err = -EAGAIN, fd; @@ -132,7 +132,7 @@ bool perf_can_record_cpu_wide(void) return true; } -void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, +void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, struct callchain_param *callchain) { struct evsel *evsel; @@ -256,9 +256,9 @@ int record_opts__config(struct record_opts *opts) return record_opts__config_freq(opts); } -bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) +bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) { - struct perf_evlist *temp_evlist; + struct evlist *temp_evlist; struct evsel *evsel; int err, fd, cpu; bool ret = false; diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 159a08220947..6c709647cd8e 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -200,7 +200,7 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample) * its raw data. * The function is only invoked when the dump flag -D is set. */ -void perf_evlist__s390_sample_raw(struct perf_evlist *evlist, union perf_event *event, +void perf_evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { struct evsel *ev_bc000; diff --git a/tools/perf/util/sample-raw.c b/tools/perf/util/sample-raw.c index c21e1311fb0f..e84bbe0e441a 100644 --- a/tools/perf/util/sample-raw.c +++ b/tools/perf/util/sample-raw.c @@ -9,7 +9,7 @@ * Check platform the perf data file was created on and perform platform * specific interpretation. */ -void perf_evlist__init_trace_event_sample_raw(struct perf_evlist *evlist) +void perf_evlist__init_trace_event_sample_raw(struct evlist *evlist) { const char *arch_pf = perf_env__arch(evlist->env); diff --git a/tools/perf/util/sample-raw.h b/tools/perf/util/sample-raw.h index 95d445c87e93..afe1491a117e 100644 --- a/tools/perf/util/sample-raw.h +++ b/tools/perf/util/sample-raw.h @@ -2,13 +2,13 @@ #ifndef __SAMPLE_RAW_H #define __SAMPLE_RAW_H 1 -struct perf_evlist; +struct evlist; union perf_event; struct perf_sample; -void perf_evlist__s390_sample_raw(struct perf_evlist *evlist, +void perf_evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample); -void perf_evlist__init_trace_event_sample_raw(struct perf_evlist *evlist); +void perf_evlist__init_trace_event_sample_raw(struct evlist *evlist); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e9d1cf8eb274..c191dc152175 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -300,7 +300,7 @@ static int process_event_synth_tracing_data_stub(struct perf_session *session static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct perf_evlist **pevlist + struct evlist **pevlist __maybe_unused) { dump_printf(": unhandled!\n"); @@ -309,7 +309,7 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused, static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct perf_evlist **pevlist + struct evlist **pevlist __maybe_unused) { if (dump_trace) @@ -1129,7 +1129,7 @@ static void stack_user__printf(struct stack_dump *dump) dump->size, dump->offset); } -static void perf_evlist__print_tstamp(struct perf_evlist *evlist, +static void perf_evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { @@ -1178,7 +1178,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format) sample->read.one.id, sample->read.one.value); } -static void dump_event(struct perf_evlist *evlist, union perf_event *event, +static void dump_event(struct evlist *evlist, union perf_event *event, u64 file_offset, struct perf_sample *sample) { if (!dump_trace) @@ -1296,7 +1296,7 @@ static struct machine *machines__find_for_cpumode(struct machines *machines, return &machines->host; } -static int deliver_sample_value(struct perf_evlist *evlist, +static int deliver_sample_value(struct evlist *evlist, struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -1326,7 +1326,7 @@ static int deliver_sample_value(struct perf_evlist *evlist, return tool->sample(tool, event, sample, sid->evsel, machine); } -static int deliver_sample_group(struct perf_evlist *evlist, +static int deliver_sample_group(struct evlist *evlist, struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -1347,7 +1347,7 @@ static int deliver_sample_group(struct perf_evlist *evlist, } static int - perf_evlist__deliver_sample(struct perf_evlist *evlist, + perf_evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -1372,7 +1372,7 @@ static int } static int machines__deliver_event(struct machines *machines, - struct perf_evlist *evlist, + struct evlist *evlist, union perf_event *event, struct perf_sample *sample, struct perf_tool *tool, u64 file_offset) @@ -1553,7 +1553,7 @@ int perf_session__deliver_synth_event(struct perf_session *session, union perf_event *event, struct perf_sample *sample) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct perf_tool *tool = session->tool; events_stats__inc(&evlist->stats, event->header.type); @@ -1631,7 +1631,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, static s64 perf_session__process_event(struct perf_session *session, union perf_event *event, u64 file_offset) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct perf_tool *tool = session->tool; int ret; @@ -2357,7 +2357,7 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, int perf_event__process_id_index(struct perf_session *session, union perf_event *event) { - struct perf_evlist *evlist = session->evlist; + struct evlist *evlist = session->evlist; struct id_index_event *ie = &event->id_index; size_t i, nr, max_nr; @@ -2393,7 +2393,7 @@ int perf_event__process_id_index(struct perf_session *session, int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process, - struct perf_evlist *evlist, + struct evlist *evlist, struct machine *machine) { union perf_event *ev; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 2b2427c4c0b9..79e97d17ea04 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -23,7 +23,7 @@ struct itrace_synth_opts; struct perf_session { struct perf_header header; struct machines machines; - struct perf_evlist *evlist; + struct evlist *evlist; struct auxtrace *auxtrace; struct itrace_synth_opts *itrace_synth_opts; struct list_head auxtrace_index; @@ -140,7 +140,7 @@ int perf_event__process_id_index(struct perf_session *session, int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process, - struct perf_evlist *evlist, + struct evlist *evlist, struct machine *machine); #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 133d3a45997f..d8e4392d6e18 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2313,7 +2313,7 @@ static int parse_field_name(char *str, char **event, char **field, char **opt) * 2. full event name (e.g. sched:sched_switch) * 3. partial event name (should not contain ':') */ -static struct evsel *find_evsel(struct perf_evlist *evlist, char *event_name) +static struct evsel *find_evsel(struct evlist *evlist, char *event_name) { struct evsel *evsel = NULL; struct evsel *pos; @@ -2384,7 +2384,7 @@ static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level) return 0; } -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, +static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace, int level) { int ret; @@ -2401,7 +2401,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, return 0; } -static int add_all_matching_fields(struct perf_evlist *evlist, +static int add_all_matching_fields(struct evlist *evlist, char *field_name, bool raw_trace, int level) { int ret = -ESRCH; @@ -2423,7 +2423,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist, return ret; } -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, +static int add_dynamic_entry(struct evlist *evlist, const char *tok, int level) { char *str, *event_name, *field_name, *opt_name; @@ -2567,7 +2567,7 @@ int hpp_dimension__add_output(unsigned col) } int sort_dimension__add(struct perf_hpp_list *list, const char *tok, - struct perf_evlist *evlist, + struct evlist *evlist, int level) { unsigned int i; @@ -2663,7 +2663,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok, } static int setup_sort_list(struct perf_hpp_list *list, char *str, - struct perf_evlist *evlist) + struct evlist *evlist) { char *tmp, *tok; int ret = 0; @@ -2709,7 +2709,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, return ret; } -static const char *get_default_sort_order(struct perf_evlist *evlist) +static const char *get_default_sort_order(struct evlist *evlist) { const char *default_sort_orders[] = { default_sort_order, @@ -2743,7 +2743,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) return default_sort_orders[sort__mode]; } -static int setup_sort_order(struct perf_evlist *evlist) +static int setup_sort_order(struct evlist *evlist) { char *new_sort_order; @@ -2804,7 +2804,7 @@ static char *setup_overhead(char *keys) return keys; } -static int __setup_sorting(struct perf_evlist *evlist) +static int __setup_sorting(struct evlist *evlist) { char *str; const char *sort_keys; @@ -3057,7 +3057,7 @@ static int __setup_output_field(void) return ret; } -int setup_sorting(struct perf_evlist *evlist) +int setup_sorting(struct evlist *evlist) { int err; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index a0f232151d6f..5e34676a98e8 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -301,9 +301,9 @@ struct block_hist { extern struct sort_entry sort_thread; extern struct list_head hist_entry__sort_list; -struct perf_evlist; +struct evlist; struct tep_handle; -int setup_sorting(struct perf_evlist *evlist); +int setup_sorting(struct evlist *evlist); int setup_output_field(void); void reset_output_field(void); void sort__setup_elide(FILE *fp); @@ -318,7 +318,7 @@ bool is_strict_order(const char *order); int hpp_dimension__add_output(unsigned col); void reset_dimensions(void); int sort_dimension__add(struct perf_hpp_list *list, const char *tok, - struct perf_evlist *evlist, + struct evlist *evlist, int level); int output_field_add(struct perf_hpp_list *list, char *tok); int64_t diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 8da4ddcb2e44..cdfceb5b4d72 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -312,7 +312,7 @@ static void print_metric_header(struct perf_stat_config *config, static int first_shadow_cpu(struct perf_stat_config *config, struct evsel *evsel, int id) { - struct perf_evlist *evlist = evsel->evlist; + struct evlist *evlist = evsel->evlist; int i; if (!config->aggr_get_id) @@ -365,7 +365,7 @@ static void abs_printout(struct perf_stat_config *config, static bool is_mixed_hw_group(struct evsel *counter) { - struct perf_evlist *evlist = counter->evlist; + struct evlist *evlist = counter->evlist; u32 pmu_type = counter->attr.type; struct evsel *pos; @@ -489,7 +489,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, } static void aggr_update_shadow(struct perf_stat_config *config, - struct perf_evlist *evlist) + struct evlist *evlist) { int cpu, s2, id, s; u64 val; @@ -545,7 +545,7 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c bool first), void *data) { - struct perf_evlist *evlist = counter->evlist; + struct evlist *evlist = counter->evlist; struct evsel *alias; alias = list_prepare_entry(counter, &(evlist->entries), node); @@ -651,7 +651,7 @@ static void print_counter_aggrdata(struct perf_stat_config *config, } static void print_aggr(struct perf_stat_config *config, - struct perf_evlist *evlist, + struct evlist *evlist, char *prefix) { bool metric_only = config->metric_only; @@ -859,7 +859,7 @@ static void print_counter(struct perf_stat_config *config, } static void print_no_aggr_metric(struct perf_stat_config *config, - struct perf_evlist *evlist, + struct evlist *evlist, char *prefix) { int cpu; @@ -910,7 +910,7 @@ static const char *aggr_header_csv[] = { }; static void print_metric_headers(struct perf_stat_config *config, - struct perf_evlist *evlist, + struct evlist *evlist, const char *prefix, bool no_indent) { struct perf_stat_output_ctx out; @@ -949,7 +949,7 @@ static void print_metric_headers(struct perf_stat_config *config, } static void print_interval(struct perf_stat_config *config, - struct perf_evlist *evlist, + struct evlist *evlist, char *prefix, struct timespec *ts) { bool metric_only = config->metric_only; @@ -1156,7 +1156,7 @@ static void print_percore(struct perf_stat_config *config, } void -perf_evlist__print_counters(struct perf_evlist *evlist, +perf_evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config, struct target *_target, struct timespec *ts, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 8c19f3149f34..d81bcab2e64c 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -299,7 +299,7 @@ static const char *get_ratio_color(enum grc_type type, double ratio) return color; } -static struct evsel *perf_stat__find_event(struct perf_evlist *evsel_list, +static struct evsel *perf_stat__find_event(struct evlist *evsel_list, const char *name) { struct evsel *c2; @@ -312,7 +312,7 @@ static struct evsel *perf_stat__find_event(struct perf_evlist *evsel_list, } /* Mark MetricExpr target events and link events using them to them. */ -void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) +void perf_stat__collect_metric_expr(struct evlist *evsel_list) { struct evsel *counter, *leader, **metric_events, *oc; bool found; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 7acb9a6730fe..efd934ec02c3 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -168,7 +168,7 @@ static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw) return 0; } -int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) +int perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw) { struct evsel *evsel; @@ -184,7 +184,7 @@ int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) return -1; } -void perf_evlist__free_stats(struct perf_evlist *evlist) +void perf_evlist__free_stats(struct evlist *evlist) { struct evsel *evsel; @@ -195,7 +195,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist) } } -void perf_evlist__reset_stats(struct perf_evlist *evlist) +void perf_evlist__reset_stats(struct evlist *evlist) { struct evsel *evsel; @@ -490,7 +490,7 @@ int create_perf_stat_counter(struct evsel *evsel, int perf_stat_synthesize_config(struct perf_stat_config *config, struct perf_tool *tool, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process, bool attrs) { diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index b64cf0177a91..95b4de7a9d51 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -144,7 +144,7 @@ static inline void init_stats(struct stats *stats) } struct evsel; -struct perf_evlist; +struct evlist; struct perf_aggr_thread_value { struct evsel *counter; @@ -189,11 +189,11 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct perf_stat_output_ctx *out, struct rblist *metric_events, struct runtime_stat *st); -void perf_stat__collect_metric_expr(struct perf_evlist *); +void perf_stat__collect_metric_expr(struct evlist *); -int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); -void perf_evlist__free_stats(struct perf_evlist *evlist); -void perf_evlist__reset_stats(struct perf_evlist *evlist); +int perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw); +void perf_evlist__free_stats(struct evlist *evlist); +void perf_evlist__reset_stats(struct evlist *evlist); int perf_stat_process_counter(struct perf_stat_config *config, struct evsel *counter); @@ -212,11 +212,11 @@ int create_perf_stat_counter(struct evsel *evsel, struct target *target); int perf_stat_synthesize_config(struct perf_stat_config *config, struct perf_tool *tool, - struct perf_evlist *evlist, + struct evlist *evlist, perf_event__handler_t process, bool attrs); void -perf_evlist__print_counters(struct perf_evlist *evlist, +perf_evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config, struct target *_target, struct timespec *ts, diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 5d880a6f0a34..7f95dd1d6883 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -8,7 +8,7 @@ struct perf_session; union perf_event; -struct perf_evlist; +struct evlist; struct evsel; struct perf_sample; struct perf_tool; @@ -24,7 +24,7 @@ typedef int (*event_op)(struct perf_tool *tool, union perf_event *event, typedef int (*event_attr_op)(struct perf_tool *tool, union perf_event *event, - struct perf_evlist **pevlist); + struct evlist **pevlist); typedef int (*event_op2)(struct perf_session *session, union perf_event *event); typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 7e0f363c0658..2023e0bf6165 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -9,13 +9,13 @@ #include #include -struct perf_evlist; +struct evlist; struct evsel; struct perf_session; struct perf_top { struct perf_tool tool; - struct perf_evlist *evlist; + struct evlist *evlist; struct record_opts record_opts; struct annotation_options annotation_opts; /* -- GitLab From b4b62ee688eb39151c9d8182c3e2f12c9d34602d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:53 +0200 Subject: [PATCH 1132/7155] perf evsel: Rename perf_evsel__init() to evsel__init() Rename perf_evsel__init() to evsel__init(), so we don't have a name clash when we add perf_evsel__init() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-7-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 8 ++++---- tools/perf/util/evsel.h | 3 +-- tools/perf/util/python.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index f7f97ca6e96d..97bee83f0f98 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -223,8 +223,8 @@ bool perf_evsel__is_function_event(struct evsel *evsel) #undef FUNCTION_EVENT } -void perf_evsel__init(struct evsel *evsel, - struct perf_event_attr *attr, int idx) +void evsel__init(struct evsel *evsel, + struct perf_event_attr *attr, int idx) { evsel->idx = idx; evsel->tracking = !idx; @@ -255,7 +255,7 @@ struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) if (!evsel) return NULL; - perf_evsel__init(evsel, attr, idx); + evsel__init(evsel, attr, idx); if (perf_evsel__is_bpf_output(evsel)) { evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | @@ -350,7 +350,7 @@ struct evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) event_attr_init(&attr); attr.config = evsel->tp_format->id; attr.sample_period = 1; - perf_evsel__init(evsel, &attr, idx); + evsel__init(evsel, &attr, idx); } return evsel; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3caabd8a4aa6..af230d92fbef 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -238,8 +238,7 @@ struct evsel *perf_evsel__new_cycles(bool precise); struct tep_event *event_format__new(const char *sys, const char *name); -void perf_evsel__init(struct evsel *evsel, - struct perf_event_attr *attr, int idx); +void evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx); void perf_evsel__exit(struct evsel *evsel); void perf_evsel__delete(struct evsel *evsel); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index ed57b6b5ed91..f6fe3c90828f 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -782,7 +782,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, attr.sample_id_all = sample_id_all; attr.size = sizeof(attr); - perf_evsel__init(&pevsel->evsel, &attr, idx); + evsel__init(&pevsel->evsel, &attr, idx); return 0; } -- GitLab From 52c86bca94b42239563b1510d5fc6329b0ec1a86 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:54 +0200 Subject: [PATCH 1133/7155] perf evlist: Rename perf_evlist__init() to evlist__init() Rename perf_evlist__init() to evlist__init(), so we don't have a name clash when we add perf_evlist__init() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 4 ++-- tools/perf/util/python.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c234fa4ba92a..4fcd55c8a8d5 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -41,8 +41,8 @@ int sigqueue(pid_t pid, int sig, const union sigval value); #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) -void perf_evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, - struct perf_thread_map *threads) +void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, + struct perf_thread_map *threads) { int i; @@ -60,7 +60,7 @@ struct evlist *perf_evlist__new(void) struct evlist *evlist = zalloc(sizeof(*evlist)); if (evlist != NULL) - perf_evlist__init(evlist, NULL, NULL); + evlist__init(evlist, NULL, NULL); return evlist; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 54f1c3e2b721..d6a3fa461566 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -68,8 +68,8 @@ struct evsel_str_handler { struct evlist *perf_evlist__new(void); struct evlist *perf_evlist__new_default(void); struct evlist *perf_evlist__new_dummy(void); -void perf_evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, - struct perf_thread_map *threads); +void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, + struct perf_thread_map *threads); void perf_evlist__exit(struct evlist *evlist); void perf_evlist__delete(struct evlist *evlist); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index f6fe3c90828f..ade4e85c6d81 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -873,7 +873,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist, threads = ((struct pyrf_thread_map *)pthreads)->threads; cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; - perf_evlist__init(&pevlist->evlist, cpus, threads); + evlist__init(&pevlist->evlist, cpus, threads); return 0; } -- GitLab From 0f98b11c616f240b54ee85629ff4d3650c7ccc7d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:55 +0200 Subject: [PATCH 1134/7155] perf evlist: Rename perf_evlist__new() to evlist__new() Rename perf_evlist__new() to evlist__new(), so we don't have a name clash when we add perf_evlist__new() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/util/kvm-stat.c | 2 +- tools/perf/arch/x86/tests/intel-cqm.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/event-times.c | 2 +- tools/perf/tests/evsel-roundtrip-name.c | 4 ++-- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_link.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/parse-events.c | 2 +- tools/perf/tests/sw-clock.c | 4 ++-- tools/perf/tests/switch-tracking.c | 4 ++-- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 2 +- tools/perf/util/header.c | 4 ++-- tools/perf/util/record.c | 4 ++-- 28 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c index 28fc0bab370f..f0dbf7b075c8 100644 --- a/tools/perf/arch/powerpc/util/kvm-stat.c +++ b/tools/perf/arch/powerpc/util/kvm-stat.c @@ -146,7 +146,7 @@ static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, /* Wrapper to setup kvm tracepoints */ static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm) { - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c index 333b2f0d61e4..8089a33c6c16 100644 --- a/tools/perf/arch/x86/tests/intel-cqm.c +++ b/tools/perf/arch/x86/tests/intel-cqm.c @@ -51,7 +51,7 @@ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subt flag = perf_event_open_cloexec_flag(); - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { pr_debug("perf_evlist__new failed\n"); return TEST_FAIL; diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index d7092fc00e3b..da9a3302d8e6 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -68,7 +68,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe cpus = cpu_map__new(NULL); CHECK_NOT_NULL__(cpus); - evlist = perf_evlist__new(); + evlist = evlist__new(); CHECK_NOT_NULL__(evlist); perf_evlist__set_maps(evlist, cpus, threads); diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 1263987c291a..b8bdc593e5b8 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -495,7 +495,7 @@ int cmd_ftrace(int argc, const char **argv) goto out_delete_filters; } - ftrace.evlist = perf_evlist__new(); + ftrace.evlist = evlist__new(); if (ftrace.evlist == NULL) { ret = -ENOMEM; goto out_delete_filters; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 963dddc5853d..ee896b8a9fe8 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1290,7 +1290,7 @@ static struct evlist *kvm_live_event_list(void) int err = -1; const char * const *events_tp; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (evlist == NULL) return NULL; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f08d1e6a1651..e8aa8a078dff 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2265,7 +2265,7 @@ int cmd_record(int argc, const char **argv) CPU_ZERO(&rec->affinity_mask); rec->opts.affinity = PERF_AFFINITY_SYS; - rec->evlist = perf_evlist__new(); + rec->evlist = evlist__new(); if (rec->evlist == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4e61f8a1d22b..ee0dc8088ac0 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1702,7 +1702,7 @@ int cmd_stat(int argc, const char **argv) setlocale(LC_ALL, ""); - evsel_list = perf_evlist__new(); + evsel_list = evlist__new(); if (evsel_list == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c29fa1de854f..e4b7146cd666 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1524,7 +1524,7 @@ int cmd_top(int argc, const char **argv) top.annotation_opts.min_pcnt = 5; top.annotation_opts.context = 4; - top.evlist = perf_evlist__new(); + top.evlist = evlist__new(); if (top.evlist == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index f7e7daac3cbe..767b04eaaf45 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4169,7 +4169,7 @@ int cmd_trace(int argc, const char **argv) signal(SIGSEGV, sighandler_dump_stack); signal(SIGFPE, sighandler_dump_stack); - trace.evlist = perf_evlist__new(); + trace.evlist = evlist__new(); trace.sctbl = syscalltbl__new(); if (trace.evlist == NULL || trace.sctbl == NULL) { diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 3f9c931069b0..3883b315b25b 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -99,7 +99,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m pid[sizeof(pid) - 1] = '\0'; opts.target.tid = opts.target.pid = pid; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { pr_debug("Not enough memory to create evlist\n"); return TEST_FAIL; diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 95a15b51f95c..d15f62dc4261 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -140,7 +140,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), opts.target.tid = opts.target.pid = pid; /* Instead of perf_evlist__new_default, don't add default events */ - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { pr_debug("Not enough memory to create evlist\n"); return TEST_FAIL; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 168deb9c563e..dd0325eabc25 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -622,7 +622,7 @@ static int do_test_code_reading(bool try_kcore) while (1) { const char *str; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { pr_debug("perf_evlist__new failed\n"); goto out_put; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index c3545a6efcbc..8d3cf9792d9e 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -166,7 +166,7 @@ static int test_times(int (attach)(struct evlist *), struct evsel *evsel; int err = -1, i; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { pr_debug("failed to create event list\n"); goto out_err; diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 6cc408b23026..74e79d6b7e96 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -12,7 +12,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) char name[128]; int type, op, err = 0, ret = 0, i, idx; struct evsel *evsel; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; @@ -68,7 +68,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) { int i, err; struct evsel *evsel; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index d7a6b97683d6..897e74b5ed1f 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -695,7 +695,7 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u struct machines machines; struct machine *machine; struct evsel *evsel; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); size_t i; test_fn_t testcases[] = { test1, diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 9f0d6af839e9..b0468db74ca3 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -109,7 +109,7 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu struct machines machines; struct machine *machine; struct evsel *evsel; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); TEST_ASSERT_VAL("No memory", evlist); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 6ab27dd3bf3f..878cb5bfbe78 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -272,7 +272,7 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse struct machines machines; struct machine *machine = NULL; struct evsel *evsel, *first; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index cd36e51cdf3b..87a05e7afb7e 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -581,7 +581,7 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu struct machines machines; struct machine *machine; struct evsel *evsel; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); size_t i; test_fn_t testcases[] = { test1, diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index e0779f2a340c..4c73377bfccb 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -78,7 +78,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un cpus = cpu_map__new(NULL); CHECK_NOT_NULL__(cpus); - evlist = perf_evlist__new(); + evlist = evlist__new(); CHECK_NOT_NULL__(evlist); perf_evlist__set_maps(evlist, cpus, threads); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 749b580e9a92..8d1be34fd951 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -61,7 +61,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse goto out_free_cpus; } - evlist = perf_evlist__new(); + evlist = evlist__new(); if (evlist == NULL) { pr_debug("perf_evlist__new\n"); goto out_free_cpus; diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 69bf0ec2fe5f..141592437520 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -32,7 +32,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest }; const char *filename = "/etc/passwd"; int flags = O_RDONLY | O_DIRECTORY; - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); struct evsel *evsel; int err = -1, i, nr_events = 0, nr_polls = 0; char sbuf[STRERR_BUFSIZE]; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7409eed11b65..6e81a930b224 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1777,7 +1777,7 @@ static int test_event(struct evlist_test *e) return 0; } - evlist = perf_evlist__new(); + evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 69b997eeb639..88a75cbae230 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -43,9 +43,9 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) attr.sample_freq = 500; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (evlist == NULL) { - pr_debug("perf_evlist__new\n"); + pr_debug("evlist__new\n"); return -1; } diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 3e26ea36ec29..89bc20b2178a 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -347,9 +347,9 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) { - pr_debug("perf_evlist__new failed!\n"); + pr_debug("evlist__new failed!\n"); goto out_err; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4fcd55c8a8d5..317b2d64ba6d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -55,7 +55,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, evlist->bkw_mmap_state = BKW_MMAP_NOTREADY; } -struct evlist *perf_evlist__new(void) +struct evlist *evlist__new(void) { struct evlist *evlist = zalloc(sizeof(*evlist)); @@ -67,7 +67,7 @@ struct evlist *perf_evlist__new(void) struct evlist *perf_evlist__new_default(void) { - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist && perf_evlist__add_default(evlist)) { perf_evlist__delete(evlist); @@ -79,7 +79,7 @@ struct evlist *perf_evlist__new_default(void) struct evlist *perf_evlist__new_dummy(void) { - struct evlist *evlist = perf_evlist__new(); + struct evlist *evlist = evlist__new(); if (evlist && perf_evlist__add_dummy(evlist)) { perf_evlist__delete(evlist); @@ -1839,7 +1839,7 @@ int perf_evlist__add_sb_event(struct evlist **evlist, bool new_evlist = (*evlist) == NULL; if (*evlist == NULL) - *evlist = perf_evlist__new(); + *evlist = evlist__new(); if (*evlist == NULL) return -1; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index d6a3fa461566..60e1c9268e9e 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -65,7 +65,7 @@ struct evsel_str_handler { void *handler; }; -struct evlist *perf_evlist__new(void); +struct evlist *evlist__new(void); struct evlist *perf_evlist__new_default(void); struct evlist *perf_evlist__new_dummy(void); void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 692fe8ac12ae..5b90786a8436 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3535,7 +3535,7 @@ int perf_session__read_header(struct perf_session *session) int nr_attrs, nr_ids, i, j; int fd = perf_data__fd(data); - session->evlist = perf_evlist__new(); + session->evlist = evlist__new(); if (session->evlist == NULL) return -ENOMEM; @@ -4016,7 +4016,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, struct evlist *evlist = *pevlist; if (evlist == NULL) { - *pevlist = evlist = perf_evlist__new(); + *pevlist = evlist = evlist__new(); if (evlist == NULL) return -ENOMEM; } diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index a550d78a0b4d..a23c69137dfc 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -19,7 +19,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) int err = -EAGAIN, fd; static pid_t pid = -1; - evlist = perf_evlist__new(); + evlist = evlist__new(); if (!evlist) return -ENOMEM; @@ -264,7 +264,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) bool ret = false; pid_t pid = -1; - temp_evlist = perf_evlist__new(); + temp_evlist = evlist__new(); if (!temp_evlist) return false; -- GitLab From c12995a55474e1cefac52da38c7fc47c024de067 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:56 +0200 Subject: [PATCH 1135/7155] perf evlist: Rename perf_evlist__delete() to evlist__delete() Rename perf_evlist__delete() to evlist__delete(), so we don't have a name clash when we add perf_evlist__delete() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/intel-cqm.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-kvm.c | 4 ++-- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 4 ++-- tools/perf/tests/event-times.c | 2 +- tools/perf/tests/evsel-roundtrip-name.c | 4 ++-- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_link.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/parse-events.c | 2 +- tools/perf/tests/parse-no-sample-id-all.c | 2 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/util/data-convert-bt.c | 2 +- tools/perf/util/evlist.c | 12 ++++++------ tools/perf/util/evlist.h | 2 +- tools/perf/util/header.c | 4 ++-- tools/perf/util/parse-events.c | 2 +- tools/perf/util/record.c | 4 ++-- 32 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c index 8089a33c6c16..2a105e3b2ad1 100644 --- a/tools/perf/arch/x86/tests/intel-cqm.c +++ b/tools/perf/arch/x86/tests/intel-cqm.c @@ -124,6 +124,6 @@ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subt kill(pid, SIGKILL); wait(NULL); out: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index da9a3302d8e6..09b6cef76f5b 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -163,6 +163,6 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe err = 0; out_err: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index b8bdc593e5b8..105ef2a17a9c 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -508,7 +508,7 @@ int cmd_ftrace(int argc, const char **argv) ret = __cmd_ftrace(&ftrace, argc, argv); out_delete_evlist: - perf_evlist__delete(ftrace.evlist); + evlist__delete(ftrace.evlist); out_delete_filters: delete_filter_func(&ftrace.filters); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index ee896b8a9fe8..8f54bdfb5743 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1325,7 +1325,7 @@ static struct evlist *kvm_live_event_list(void) out: if (err) { - perf_evlist__delete(evlist); + evlist__delete(evlist); evlist = NULL; } @@ -1460,7 +1460,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, out: perf_session__delete(kvm->session); kvm->session = NULL; - perf_evlist__delete(kvm->evlist); + evlist__delete(kvm->evlist); return err; } diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e8aa8a078dff..06966a2c2cdd 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2449,7 +2449,7 @@ int cmd_record(int argc, const char **argv) err = __cmd_record(&record, argc, argv); out: - perf_evlist__delete(rec->evlist); + evlist__delete(rec->evlist); symbol__exit(); auxtrace_record__free(rec->itr); return err; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ee0dc8088ac0..d28d4d71d9b7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2015,7 +2015,7 @@ int cmd_stat(int argc, const char **argv) if (smi_cost && smi_reset) sysfs__write_int(FREEZE_ON_SMI_PATH, 0); - perf_evlist__delete(evsel_list); + evlist__delete(evsel_list); runtime_stat_delete(&stat_config); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e4b7146cd666..6c0c2b78093a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1661,7 +1661,7 @@ int cmd_top(int argc, const char **argv) perf_evlist__stop_sb_thread(sb_evlist); out_delete_evlist: - perf_evlist__delete(top.evlist); + evlist__delete(top.evlist); perf_session__delete(top.session); return status; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 767b04eaaf45..e133204b3bb9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3498,7 +3498,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) out_delete_evlist: trace__symbols__exit(trace); - perf_evlist__delete(evlist); + evlist__delete(evlist); cgroup__put(trace->cgroup); trace->evlist = NULL; trace->live = false; diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 3883b315b25b..ef3c6db2fae4 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -150,6 +150,6 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m ret = TEST_OK; out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); return ret; } diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index d15f62dc4261..313ff1aadd9c 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -200,7 +200,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), ret = TEST_OK; out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); return ret; } diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index dd0325eabc25..1c7f092a7388 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -658,7 +658,7 @@ static int do_test_code_reading(bool try_kcore) cpu_map__get(cpus); thread_map__get(threads); perf_evlist__set_maps(evlist, NULL, NULL); - perf_evlist__delete(evlist); + evlist__delete(evlist); evlist = NULL; continue; } @@ -703,7 +703,7 @@ static int do_test_code_reading(bool try_kcore) out_err: if (evlist) { - perf_evlist__delete(evlist); + evlist__delete(evlist); } else { cpu_map__put(cpus); thread_map__put(threads); diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 8d3cf9792d9e..0f74ca103c41 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -204,7 +204,7 @@ static int test_times(int (attach)(struct evlist *), count.ena, count.run); out_err: - perf_evlist__delete(evlist); + evlist__delete(evlist); return !err ? TEST_OK : TEST_FAIL; } diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 74e79d6b7e96..5330f106a6ee 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -60,7 +60,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) } } - perf_evlist__delete(evlist); + evlist__delete(evlist); return ret; } @@ -91,7 +91,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) } out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 897e74b5ed1f..1f3de85ae18b 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -731,7 +731,7 @@ int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_u out: /* tear down everything */ - perf_evlist__delete(evlist); + evlist__delete(evlist); machines__exit(&machines); return err; diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index b0468db74ca3..a274716fc438 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -321,7 +321,7 @@ int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unu out: /* tear down everything */ - perf_evlist__delete(evlist); + evlist__delete(evlist); reset_output_field(); machines__exit(&machines); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 878cb5bfbe78..b25383aa2e6e 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -334,7 +334,7 @@ int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unuse out: /* tear down everything */ - perf_evlist__delete(evlist); + evlist__delete(evlist); reset_output_field(); machines__exit(&machines); diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index 87a05e7afb7e..009888adf4b3 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -618,7 +618,7 @@ int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unu out: /* tear down everything */ - perf_evlist__delete(evlist); + evlist__delete(evlist); machines__exit(&machines); return err; diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 4c73377bfccb..cdc19bcc7523 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -147,7 +147,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un out_err: if (evlist) { perf_evlist__disable(evlist); - perf_evlist__delete(evlist); + evlist__delete(evlist); } else { cpu_map__put(cpus); thread_map__put(threads); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 8d1be34fd951..7f96bb72f7e5 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -151,7 +151,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse } out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); cpus = NULL; threads = NULL; out_free_cpus: diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 141592437520..0263420f4495 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -134,7 +134,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest out_ok: err = 0; out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); out: return err; } diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 6e81a930b224..2365dd655c88 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1790,7 +1790,7 @@ static int test_event(struct evlist_test *e) ret = e->check(evlist); } - perf_evlist__delete(evlist); + evlist__delete(evlist); return ret; } diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c index fc0213246aaf..396e40d68922 100644 --- a/tools/perf/tests/parse-no-sample-id-all.c +++ b/tools/perf/tests/parse-no-sample-id-all.c @@ -46,7 +46,7 @@ static int process_events(union perf_event **events, size_t count) for (i = 0; i < count && !err; i++) err = process_event(&evlist, events[i]); - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 99b2d26881f9..779d5996428b 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -325,7 +325,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus ++errs; } out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); out: return (err < 0 || errs > 0) ? -1 : 0; } diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 88a75cbae230..1c7d8adb43d0 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -128,7 +128,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) cpu_map__put(cpus); thread_map__put(threads); out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 89bc20b2178a..ac5da4fd222f 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -567,7 +567,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ out: if (evlist) { perf_evlist__disable(evlist); - perf_evlist__delete(evlist); + evlist__delete(evlist); } else { cpu_map__put(cpus); thread_map__put(threads); diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 5c2cdb0ccb96..698ee5369c02 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -138,6 +138,6 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused cpu_map__put(cpus); thread_map__put(threads); out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 083101ae7b77..ca30bb25b3c5 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -1319,7 +1319,7 @@ static void cleanup_events(struct perf_session *session) zfree(&evsel->priv); } - perf_evlist__delete(evlist); + evlist__delete(evlist); session->evlist = NULL; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 317b2d64ba6d..9fa3663068b4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -70,7 +70,7 @@ struct evlist *perf_evlist__new_default(void) struct evlist *evlist = evlist__new(); if (evlist && perf_evlist__add_default(evlist)) { - perf_evlist__delete(evlist); + evlist__delete(evlist); evlist = NULL; } @@ -82,7 +82,7 @@ struct evlist *perf_evlist__new_dummy(void) struct evlist *evlist = evlist__new(); if (evlist && perf_evlist__add_dummy(evlist)) { - perf_evlist__delete(evlist); + evlist__delete(evlist); evlist = NULL; } @@ -134,7 +134,7 @@ void perf_evlist__exit(struct evlist *evlist) fdarray__exit(&evlist->pollfd); } -void perf_evlist__delete(struct evlist *evlist) +void evlist__delete(struct evlist *evlist) { if (evlist == NULL) return; @@ -1859,7 +1859,7 @@ int perf_evlist__add_sb_event(struct evlist **evlist, out_err: if (new_evlist) { - perf_evlist__delete(*evlist); + evlist__delete(*evlist); *evlist = NULL; } return -1; @@ -1938,7 +1938,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, return 0; out_delete_evlist: - perf_evlist__delete(evlist); + evlist__delete(evlist); evlist = NULL; return -1; } @@ -1949,5 +1949,5 @@ void perf_evlist__stop_sb_thread(struct evlist *evlist) return; evlist->thread.done = 1; pthread_join(evlist->thread.th, NULL); - perf_evlist__delete(evlist); + evlist__delete(evlist); } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 60e1c9268e9e..12a5fd6972df 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -71,7 +71,7 @@ struct evlist *perf_evlist__new_dummy(void); void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, struct perf_thread_map *threads); void perf_evlist__exit(struct evlist *evlist); -void perf_evlist__delete(struct evlist *evlist); +void evlist__delete(struct evlist *evlist); void perf_evlist__add(struct evlist *evlist, struct evsel *entry); void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 5b90786a8436..29bbfd699226 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3591,7 +3591,7 @@ int perf_session__read_header(struct perf_session *session) evsel->needs_swap = header->needs_swap; /* * Do it before so that if perf_evsel__alloc_id fails, this - * entry gets purged too at perf_evlist__delete(). + * entry gets purged too at evlist__delete(). */ perf_evlist__add(session->evlist, evsel); @@ -3628,7 +3628,7 @@ int perf_session__read_header(struct perf_session *session) return -errno; out_delete_evlist: - perf_evlist__delete(session->evlist); + evlist__delete(session->evlist); session->evlist = NULL; return -ENOMEM; } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d341b11fb141..6a4bfc7ab0c1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1935,7 +1935,7 @@ int parse_events(struct evlist *evlist, const char *str, /* * There are 2 users - builtin-record and builtin-test objects. - * Both call perf_evlist__delete in case of error, so we dont + * Both call evlist__delete in case of error, so we dont * need to bother. */ return ret; diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index a23c69137dfc..9f8841548539 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -53,7 +53,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) err = 0; out_delete: - perf_evlist__delete(evlist); + evlist__delete(evlist); return err; } @@ -299,7 +299,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) ret = true; out_delete: - perf_evlist__delete(temp_evlist); + evlist__delete(temp_evlist); return ret; } -- GitLab From 5eb2dd2ade8354dcbe4cef54cd1719622af8f2dc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:57 +0200 Subject: [PATCH 1136/7155] perf evsel: Rename perf_evsel__delete() to evsel__delete() Remame perf_evsel__delete() to evsel__delete(), so we don't have a name clash when we add perf_evsel__delete() in libperf. Also renaming perf_evsel__delete_priv() to evsel__delete_priv(). Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 4 ++-- tools/perf/builtin-trace.c | 12 ++++++------ tools/perf/tests/evsel-tp-sched.c | 4 ++-- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 2 +- tools/perf/util/parse-events.c | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index d2131fc863be..917c8fb4baa5 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -623,7 +623,7 @@ static void strip_fini(struct perf_inject *inject) ok_to_remove(evlist, evsel)) { pr_debug("Deleting %s\n", perf_evsel__name(evsel)); perf_evlist__remove(evlist, evsel); - perf_evsel__delete(evsel); + evsel__delete(evsel); } } } @@ -725,7 +725,7 @@ static int __cmd_inject(struct perf_inject *inject) pr_debug("Deleting %s\n", perf_evsel__name(evsel)); perf_evlist__remove(session->evlist, evsel); - perf_evsel__delete(evsel); + evsel__delete(evsel); } if (inject->strip) strip_fini(inject); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e133204b3bb9..0f7d1859a2d1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -274,10 +274,10 @@ static int perf_evsel__init_tp_ptr_field(struct evsel *evsel, ({ struct syscall_tp *sc = evsel->priv;\ perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); }) -static void perf_evsel__delete_priv(struct evsel *evsel) +static void evsel__delete_priv(struct evsel *evsel) { zfree(&evsel->priv); - perf_evsel__delete(evsel); + evsel__delete(evsel); } static int perf_evsel__init_syscall_tp(struct evsel *evsel) @@ -368,7 +368,7 @@ static struct evsel *perf_evsel__raw_syscall_newtp(const char *direction, void * return evsel; out_delete: - perf_evsel__delete_priv(evsel); + evsel__delete_priv(evsel); return NULL; } @@ -2638,7 +2638,7 @@ static bool perf_evlist__add_vfs_getname(struct evlist *evlist) list_del_init(&evsel->node); evsel->evlist = NULL; - perf_evsel__delete(evsel); + evsel__delete(evsel); } return found; @@ -2739,9 +2739,9 @@ static int trace__add_syscall_newtp(struct trace *trace) return ret; out_delete_sys_exit: - perf_evsel__delete_priv(sys_exit); + evsel__delete_priv(sys_exit); out_delete_sys_enter: - perf_evsel__delete_priv(sys_enter); + evsel__delete_priv(sys_enter); goto out; } diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 0170e9d2e329..261e6eaaee99 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -64,7 +64,7 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes if (perf_evsel__test_field(evsel, "next_prio", 4, true)) ret = -1; - perf_evsel__delete(evsel); + evsel__delete(evsel); evsel = perf_evsel__newtp("sched", "sched_wakeup"); @@ -85,6 +85,6 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) ret = -1; - perf_evsel__delete(evsel); + evsel__delete(evsel); return ret; } diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 4bf73896695a..001a0e8e6998 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -118,7 +118,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int out_close_fd: perf_evsel__close_fd(evsel); out_evsel_delete: - perf_evsel__delete(evsel); + evsel__delete(evsel); out_cpu_map_delete: cpu_map__put(cpus); out_thread_map_delete: diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index f3efadd05863..20e353fbfdd0 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -59,7 +59,7 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __m out_close_fd: perf_evsel__close_fd(evsel); out_evsel_delete: - perf_evsel__delete(evsel); + evsel__delete(evsel); out_thread_map_delete: thread_map__put(threads); return err; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9fa3663068b4..986d20c15778 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -121,7 +121,7 @@ static void perf_evlist__purge(struct evlist *evlist) evlist__for_each_entry_safe(evlist, n, pos) { list_del_init(&pos->node); pos->evlist = NULL; - perf_evsel__delete(pos); + evsel__delete(pos); } evlist->nr_entries = 0; @@ -277,7 +277,7 @@ static int perf_evlist__add_attrs(struct evlist *evlist, out_delete_partial_list: __evlist__for_each_entry_safe(&head, n, evsel) - perf_evsel__delete(evsel); + evsel__delete(evsel); return -1; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 97bee83f0f98..de379b63f1ce 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -316,7 +316,7 @@ struct evsel *perf_evsel__new_cycles(bool precise) out: return evsel; error_free: - perf_evsel__delete(evsel); + evsel__delete(evsel); evsel = NULL; goto out; } @@ -1333,7 +1333,7 @@ void perf_evsel__exit(struct evsel *evsel) perf_evsel__object.fini(evsel); } -void perf_evsel__delete(struct evsel *evsel) +void evsel__delete(struct evsel *evsel) { perf_evsel__exit(evsel); free(evsel); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index af230d92fbef..20b4e31b63a9 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -240,7 +240,7 @@ struct tep_event *event_format__new(const char *sys, const char *name); void evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx); void perf_evsel__exit(struct evsel *evsel); -void perf_evsel__delete(struct evsel *evsel); +void evsel__delete(struct evsel *evsel); struct callchain_param; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6a4bfc7ab0c1..cc63367f6e45 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -662,7 +662,7 @@ static int add_bpf_event(const char *group, const char *event, int fd, struct bp group, event); list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { list_del_init(&evsel->node); - perf_evsel__delete(evsel); + evsel__delete(evsel); } return err; } @@ -2334,7 +2334,7 @@ static bool is_event_supported(u8 type, unsigned config) evsel->attr.exclude_kernel = 1; ret = perf_evsel__open(evsel, NULL, tmap) >= 0; } - perf_evsel__delete(evsel); + evsel__delete(evsel); } thread_map__put(tmap); -- GitLab From 365c3ae7452ca95e0a8f1e4716dd806550ade706 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:58 +0200 Subject: [PATCH 1137/7155] perf evsel: Rename perf_evsel__new() to evsel__new() Rename perf_evsel__new() to evsel__new(), so we don't have a name clash when we add perf_evsel__new() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/util/evsel.c | 2 +- tools/perf/util/evsel.h | 2 +- tools/perf/util/header.c | 4 ++-- tools/perf/util/parse-events.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0f7d1859a2d1..c5eb47f4e42e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2657,7 +2657,7 @@ static struct evsel *perf_evsel__new_pgfault(u64 config) event_attr_init(&attr); - evsel = perf_evsel__new(&attr); + evsel = evsel__new(&attr); if (evsel) evsel->handler = trace__pgfault; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 1c7d8adb43d0..247d3734686e 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -49,7 +49,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) return -1; } - evsel = perf_evsel__new(&attr); + evsel = evsel__new(&attr); if (evsel == NULL) { pr_debug("perf_evsel__new\n"); goto out_delete_evlist; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index de379b63f1ce..c9723c2d57c9 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -301,7 +301,7 @@ struct evsel *perf_evsel__new_cycles(bool precise) * to kick in when we return and before perf_evsel__open() is called. */ new_event: - evsel = perf_evsel__new(&attr); + evsel = evsel__new(&attr); if (evsel == NULL) goto out; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 20b4e31b63a9..ecea51a918e0 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -219,7 +219,7 @@ int perf_evsel__object_config(size_t object_size, struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); -static inline struct evsel *perf_evsel__new(struct perf_event_attr *attr) +static inline struct evsel *evsel__new(struct perf_event_attr *attr) { return perf_evsel__new_idx(attr, 0); } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 29bbfd699226..7760ddc4bc18 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3583,7 +3583,7 @@ int perf_session__read_header(struct perf_session *session) } tmp = lseek(fd, 0, SEEK_CUR); - evsel = perf_evsel__new(&f_attr.attr); + evsel = evsel__new(&f_attr.attr); if (evsel == NULL) goto out_delete_evlist; @@ -4021,7 +4021,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, return -ENOMEM; } - evsel = perf_evsel__new(&event->attr.attr); + evsel = evsel__new(&event->attr.attr); if (evsel == NULL) return -ENOMEM; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index cc63367f6e45..40087cf74dd1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2318,7 +2318,7 @@ static bool is_event_supported(u8 type, unsigned config) if (tmap == NULL) return false; - evsel = perf_evsel__new(&attr); + evsel = evsel__new(&attr); if (evsel) { open_return = perf_evsel__open(evsel, NULL, tmap); ret = open_return >= 0; -- GitLab From a1cf3a75d3317ed893d453c222d220ca4d5f4c4e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:23:59 +0200 Subject: [PATCH 1138/7155] perf evlist: Rename perf_evlist__add() to evlist__add() Rename perf_evlist__add() to evlist__add(), so we don't have a name clash when we add perf_evlist__add() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 12 ++++++------ tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/util/evlist.c | 16 ++++++++-------- tools/perf/util/evlist.h | 2 +- tools/perf/util/header.c | 4 ++-- tools/perf/util/python.c | 2 +- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c5eb47f4e42e..89ae4737ef74 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2616,7 +2616,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv) static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); -static bool perf_evlist__add_vfs_getname(struct evlist *evlist) +static bool evlist__add_vfs_getname(struct evlist *evlist) { bool found = false; struct evsel *evsel, *tmp; @@ -2719,8 +2719,8 @@ static int trace__add_syscall_newtp(struct trace *trace) perf_evsel__config_callchain(sys_enter, &trace->opts, &callchain_param); perf_evsel__config_callchain(sys_exit, &trace->opts, &callchain_param); - perf_evlist__add(evlist, sys_enter); - perf_evlist__add(evlist, sys_exit); + evlist__add(evlist, sys_enter); + evlist__add(evlist, sys_exit); if (callchain_param.enabled && !trace->kernel_syscallchains) { /* @@ -3264,7 +3264,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error_raw_syscalls; if (trace->trace_syscalls) - trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); + trace->vfs_getname = evlist__add_vfs_getname(evlist); } if ((trace->trace_pgfaults & TRACE_PFMAJ)) { @@ -3272,7 +3272,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (pgfault_maj == NULL) goto out_error_mem; perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param); - perf_evlist__add(evlist, pgfault_maj); + evlist__add(evlist, pgfault_maj); } if ((trace->trace_pgfaults & TRACE_PFMIN)) { @@ -3280,7 +3280,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (pgfault_min == NULL) goto out_error_mem; perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param); - perf_evlist__add(evlist, pgfault_min); + evlist__add(evlist, pgfault_min); } if (trace->sched && diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 7f96bb72f7e5..16b8a4e5de8f 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -82,7 +82,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse evsels[i]->attr.wakeup_events = 1; perf_evsel__set_sample_id(evsels[i], false); - perf_evlist__add(evlist, evsels[i]); + evlist__add(evlist, evsels[i]); if (perf_evsel__open(evsels[i], cpus, threads) < 0) { pr_debug("failed to open counter: %s, " diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 0263420f4495..f822c3c181f3 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -48,7 +48,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest goto out_delete_evlist; } - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); err = perf_evlist__create_maps(evlist, &opts.target); if (err < 0) { diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 247d3734686e..3ab11291174c 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -54,7 +54,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) pr_debug("perf_evsel__new\n"); goto out_delete_evlist; } - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); cpus = cpu_map__dummy_new(); threads = thread_map__new_by_tid(getpid()); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 986d20c15778..7741e12bdcb0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -177,7 +177,7 @@ static void perf_evlist__propagate_maps(struct evlist *evlist) __perf_evlist__propagate_maps(evlist, evsel); } -void perf_evlist__add(struct evlist *evlist, struct evsel *entry) +void evlist__add(struct evlist *evlist, struct evsel *entry) { entry->evlist = evlist; list_add_tail(&entry->node, &evlist->entries); @@ -204,7 +204,7 @@ void perf_evlist__splice_list_tail(struct evlist *evlist, __evlist__for_each_entry_safe(list, temp, evsel) { list_del_init(&evsel->node); - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); } } @@ -237,7 +237,7 @@ int __perf_evlist__add_default(struct evlist *evlist, bool precise) if (evsel == NULL) return -ENOMEM; - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); return 0; } @@ -253,11 +253,11 @@ int perf_evlist__add_dummy(struct evlist *evlist) if (evsel == NULL) return -ENOMEM; - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); return 0; } -static int perf_evlist__add_attrs(struct evlist *evlist, +static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; @@ -289,7 +289,7 @@ int __perf_evlist__add_default_attrs(struct evlist *evlist, for (i = 0; i < nr_attrs; i++) event_attr_init(attrs + i); - return perf_evlist__add_attrs(evlist, attrs, nr_attrs); + return evlist__add_attrs(evlist, attrs, nr_attrs); } struct evsel * @@ -330,7 +330,7 @@ int perf_evlist__add_newtp(struct evlist *evlist, return -1; evsel->handler = handler; - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); return 0; } @@ -1854,7 +1854,7 @@ int perf_evlist__add_sb_event(struct evlist **evlist, evsel->side_band.cb = cb; evsel->side_band.data = data; - perf_evlist__add(*evlist, evsel); + evlist__add(*evlist, evsel); return 0; out_err: diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 12a5fd6972df..d52b29a1d852 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -73,7 +73,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, void perf_evlist__exit(struct evlist *evlist); void evlist__delete(struct evlist *evlist); -void perf_evlist__add(struct evlist *evlist, struct evsel *entry); +void evlist__add(struct evlist *evlist, struct evsel *entry); void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel); int __perf_evlist__add_default(struct evlist *evlist, bool precise); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 7760ddc4bc18..5e0093251f26 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3593,7 +3593,7 @@ int perf_session__read_header(struct perf_session *session) * Do it before so that if perf_evsel__alloc_id fails, this * entry gets purged too at evlist__delete(). */ - perf_evlist__add(session->evlist, evsel); + evlist__add(session->evlist, evsel); nr_ids = f_attr.ids.size / sizeof(u64); /* @@ -4025,7 +4025,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, if (evsel == NULL) return -ENOMEM; - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); ids = event->header.size; ids -= (void *)&event->attr.id - (void *)event; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index ade4e85c6d81..48c951a4a76b 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -974,7 +974,7 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, Py_INCREF(pevsel); evsel = &((struct pyrf_evsel *)pevsel)->evsel; evsel->idx = evlist->nr_entries; - perf_evlist__add(evlist, evsel); + evlist__add(evlist, evsel); return Py_BuildValue("i", evlist->nr_entries); } -- GitLab From 1625102764a578b11fb407b8194cb0521129d919 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:00 +0200 Subject: [PATCH 1139/7155] perf evlist: Rename perf_evlist__remove() to evlist__remove() Rename perf_evlist__remove() to evlist__remove(), so we don't have a name clash when we add perf_evlist__remove() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 4 ++-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 917c8fb4baa5..4e56e399bbc8 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -622,7 +622,7 @@ static void strip_fini(struct perf_inject *inject) if (evsel->handler == drop_sample && ok_to_remove(evlist, evsel)) { pr_debug("Deleting %s\n", perf_evsel__name(evsel)); - perf_evlist__remove(evlist, evsel); + evlist__remove(evlist, evsel); evsel__delete(evsel); } } @@ -724,7 +724,7 @@ static int __cmd_inject(struct perf_inject *inject) if (evsel) { pr_debug("Deleting %s\n", perf_evsel__name(evsel)); - perf_evlist__remove(session->evlist, evsel); + evlist__remove(session->evlist, evsel); evsel__delete(evsel); } if (inject->strip) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7741e12bdcb0..47516db62424 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -190,7 +190,7 @@ void evlist__add(struct evlist *evlist, struct evsel *entry) __perf_evlist__propagate_maps(evlist, entry); } -void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel) +void evlist__remove(struct evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; list_del_init(&evsel->node); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index d52b29a1d852..b3a44e2eed08 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -74,7 +74,7 @@ void perf_evlist__exit(struct evlist *evlist); void evlist__delete(struct evlist *evlist); void evlist__add(struct evlist *evlist, struct evsel *entry); -void perf_evlist__remove(struct evlist *evlist, struct evsel *evsel); +void evlist__remove(struct evlist *evlist, struct evsel *evsel); int __perf_evlist__add_default(struct evlist *evlist, bool precise); -- GitLab From 5972d1e07bd95c7458e2d7f484391d69008affc7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:01 +0200 Subject: [PATCH 1140/7155] perf evsel: Rename perf_evsel__open() to evsel__open() Rename perf_evsel__open() to evsel__open(), so we don't have a name clash when we add perf_evsel__open() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-15-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 8 ++++---- tools/perf/util/evsel.h | 4 ++-- tools/perf/util/parse-events.c | 4 ++-- tools/perf/util/python.c | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 06966a2c2cdd..7f933997b6d0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -739,7 +739,7 @@ static int record__open(struct record *rec) evlist__for_each_entry(evlist, pos) { try_again: - if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { + if (evsel__open(pos, pos->cpus, pos->threads) < 0) { if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { if (verbose > 0) ui__warning("%s\n", msg); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6c0c2b78093a..5886389f6a40 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -989,7 +989,7 @@ static int perf_top__start_counters(struct perf_top *top) evlist__for_each_entry(evlist, counter) { try_again: - if (perf_evsel__open(counter, top->evlist->cpus, + if (evsel__open(counter, top->evlist->cpus, top->evlist->threads) < 0) { /* diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 16b8a4e5de8f..40511025208f 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -84,7 +84,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse evlist__add(evlist, evsels[i]); - if (perf_evsel__open(evsels[i], cpus, threads) < 0) { + if (evsel__open(evsels[i], cpus, threads) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 001a0e8e6998..f96cbd304024 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -48,7 +48,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int goto out_cpu_map_delete; } - if (perf_evsel__open(evsel, cpus, threads) < 0) { + if (evsel__open(evsel, cpus, threads) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 47516db62424..4627cc47de3e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1405,7 +1405,7 @@ int perf_evlist__open(struct evlist *evlist) perf_evlist__update_id_pos(evlist); evlist__for_each_entry(evlist, evsel) { - err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); + err = evsel__open(evsel, evsel->cpus, evsel->threads); if (err < 0) goto out_err; } @@ -1918,7 +1918,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, goto out_delete_evlist; evlist__for_each_entry(evlist, counter) { - if (perf_evsel__open(counter, evlist->cpus, + if (evsel__open(counter, evlist->cpus, evlist->threads) < 0) goto out_delete_evlist; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index c9723c2d57c9..f365d0685268 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1825,8 +1825,8 @@ static int perf_event_open(struct evsel *evsel, return fd; } -int perf_evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, - struct perf_thread_map *threads) +int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, + struct perf_thread_map *threads) { int cpu, thread, nthreads; unsigned long flags = PERF_FLAG_FD_CLOEXEC; @@ -2086,13 +2086,13 @@ void perf_evsel__close(struct evsel *evsel) int perf_evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus) { - return perf_evsel__open(evsel, cpus, NULL); + return evsel__open(evsel, cpus, NULL); } int perf_evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads) { - return perf_evsel__open(evsel, NULL, threads); + return evsel__open(evsel, NULL, threads); } static int perf_evsel__parse_id_sample(const struct evsel *evsel, diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index ecea51a918e0..d43409bb07c5 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -302,8 +302,8 @@ int perf_evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus); int perf_evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads); -int perf_evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, - struct perf_thread_map *threads); +int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, + struct perf_thread_map *threads); void perf_evsel__close(struct evsel *evsel); struct perf_sample; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 40087cf74dd1..decb66d243ca 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2320,7 +2320,7 @@ static bool is_event_supported(u8 type, unsigned config) evsel = evsel__new(&attr); if (evsel) { - open_return = perf_evsel__open(evsel, NULL, tmap); + open_return = evsel__open(evsel, NULL, tmap); ret = open_return >= 0; if (open_return == -EACCES) { @@ -2332,7 +2332,7 @@ static bool is_event_supported(u8 type, unsigned config) * */ evsel->attr.exclude_kernel = 1; - ret = perf_evsel__open(evsel, NULL, tmap) >= 0; + ret = evsel__open(evsel, NULL, tmap) >= 0; } evsel__delete(evsel); } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 48c951a4a76b..3eb7348d29f8 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -817,7 +817,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, * This will group just the fds for this single evsel, to group * multiple events, use evlist.open(). */ - if (perf_evsel__open(evsel, cpus, threads) < 0) { + if (evsel__open(evsel, cpus, threads) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } -- GitLab From ec7f24ef44fc5a4eb5cb71658c33db538ed66003 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:02 +0200 Subject: [PATCH 1141/7155] perf evsel: Rename perf_evsel__enable() to evsel__enable() Rename perf_evsel__enable() to evsel__enable(), so we don't have a name clash when we add perf_evsel__enable() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 2 +- tools/perf/arch/x86/util/intel-bts.c | 2 +- tools/perf/arch/x86/util/intel-pt.c | 2 +- tools/perf/tests/event-times.c | 6 +++--- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 2 +- tools/perf/util/evsel.h | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 91c64daa4487..4b70b9504603 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -834,7 +834,7 @@ static int cs_etm_snapshot_finish(struct auxtrace_record *itr) evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->cs_etm_pmu->type) - return perf_evsel__enable(evsel); + return evsel__enable(evsel); } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index c845531d383a..d27832fcb34c 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -330,7 +330,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr) evlist__for_each_entry(btsr->evlist, evsel) { if (evsel->attr.type == btsr->intel_bts_pmu->type) - return perf_evsel__enable(evsel); + return evsel__enable(evsel); } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index e4dfe8c3d5c3..e3dacb2bf01b 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -801,7 +801,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr) evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->intel_pt_pmu->type) - return perf_evsel__enable(evsel); + return evsel__enable(evsel); } return -EINVAL; } diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 0f74ca103c41..6f9995df2c27 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -77,7 +77,7 @@ static int attach__current_disabled(struct evlist *evlist) } thread_map__put(threads); - return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; + return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; } static int attach__current_enabled(struct evlist *evlist) @@ -104,7 +104,7 @@ static int detach__disable(struct evlist *evlist) { struct evsel *evsel = perf_evlist__last(evlist); - return perf_evsel__enable(evsel); + return evsel__enable(evsel); } static int attach__cpu_disabled(struct evlist *evlist) @@ -133,7 +133,7 @@ static int attach__cpu_disabled(struct evlist *evlist) } cpu_map__put(cpus); - return perf_evsel__enable(evsel); + return evsel__enable(evsel); } static int attach__cpu_enabled(struct evlist *evlist) diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index ac5da4fd222f..acc4b5ff0cea 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -509,7 +509,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - err = perf_evsel__enable(cycles_evsel); + err = evsel__enable(cycles_evsel); if (err) { pr_debug("perf_evlist__disable_event failed!\n"); goto out_err; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4627cc47de3e..e87c43e339d0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -363,7 +363,7 @@ void perf_evlist__enable(struct evlist *evlist) evlist__for_each_entry(evlist, pos) { if (!perf_evsel__is_group_leader(pos) || !pos->fd) continue; - perf_evsel__enable(pos); + evsel__enable(pos); } evlist->enabled = true; @@ -1927,7 +1927,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, goto out_delete_evlist; evlist__for_each_entry(evlist, counter) { - if (perf_evsel__enable(counter)) + if (evsel__enable(counter)) goto out_delete_evlist; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index f365d0685268..7adae1736191 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1234,7 +1234,7 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter) return perf_evsel__append_filter(evsel, "%s,%s", filter); } -int perf_evsel__enable(struct evsel *evsel) +int evsel__enable(struct evsel *evsel) { int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d43409bb07c5..fa26c583a606 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -295,7 +295,7 @@ int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter); int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter); int perf_evsel__apply_filter(struct evsel *evsel, const char *filter); -int perf_evsel__enable(struct evsel *evsel); +int evsel__enable(struct evsel *evsel); int perf_evsel__disable(struct evsel *evsel); int perf_evsel__open_per_cpu(struct evsel *evsel, -- GitLab From 9a10bb22897ae9c2aa0ac9c2071f539f406ef942 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:03 +0200 Subject: [PATCH 1142/7155] perf evsel: Rename perf_evsel__disable() to evsel__disable() Renaming perf_evsel__disable() to evsel__disable(), so we don't have a name clash when we add perf_evsel__disable() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-17-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 2 +- tools/perf/arch/x86/util/intel-bts.c | 2 +- tools/perf/arch/x86/util/intel-pt.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/switch-tracking.c | 4 ++-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evsel.c | 2 +- tools/perf/util/evsel.h | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 4b70b9504603..268fcb31cd53 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -821,7 +821,7 @@ static int cs_etm_snapshot_start(struct auxtrace_record *itr) evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->cs_etm_pmu->type) - return perf_evsel__disable(evsel); + return evsel__disable(evsel); } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index d27832fcb34c..8b0a53d748c9 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -317,7 +317,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr) evlist__for_each_entry(btsr->evlist, evsel) { if (evsel->attr.type == btsr->intel_bts_pmu->type) - return perf_evsel__disable(evsel); + return evsel__disable(evsel); } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index e3dacb2bf01b..4ce157a4e5e2 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -788,7 +788,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr) evlist__for_each_entry(ptr->evlist, evsel) { if (evsel->attr.type == ptr->intel_pt_pmu->type) - return perf_evsel__disable(evsel); + return evsel__disable(evsel); } return -EINVAL; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 89ae4737ef74..95ecefa9ff7e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2400,7 +2400,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, ++trace->nr_events_printed; if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) { - perf_evsel__disable(evsel); + evsel__disable(evsel); perf_evsel__close(evsel); } } diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index cdc19bcc7523..1976ccb3c812 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -129,7 +129,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evsel = perf_evlist__last(evlist); - CHECK__(perf_evsel__disable(evsel)); + CHECK__(evsel__disable(evsel)); comm = "Test COMM 2"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index acc4b5ff0cea..5662dc1c6bd3 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -464,7 +464,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ perf_evlist__enable(evlist); - err = perf_evsel__disable(cpu_clocks_evsel); + err = evsel__disable(cpu_clocks_evsel); if (err) { pr_debug("perf_evlist__disable_event failed!\n"); goto out_err; @@ -483,7 +483,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - err = perf_evsel__disable(cycles_evsel); + err = evsel__disable(cycles_evsel); if (err) { pr_debug("perf_evlist__disable_event failed!\n"); goto out_err; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e87c43e339d0..9461583c53d9 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -350,7 +350,7 @@ void perf_evlist__disable(struct evlist *evlist) evlist__for_each_entry(evlist, pos) { if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd) continue; - perf_evsel__disable(pos); + evsel__disable(pos); } evlist->enabled = false; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7adae1736191..855d286298eb 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1244,7 +1244,7 @@ int evsel__enable(struct evsel *evsel) return err; } -int perf_evsel__disable(struct evsel *evsel) +int evsel__disable(struct evsel *evsel) { int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0); /* diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index fa26c583a606..c338ce14e8aa 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -296,7 +296,7 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter); int perf_evsel__apply_filter(struct evsel *evsel, const char *filter); int evsel__enable(struct evsel *evsel); -int perf_evsel__disable(struct evsel *evsel); +int evsel__disable(struct evsel *evsel); int perf_evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus); -- GitLab From 24e376b24582648d363df4e0a6bcc2ffcecd211e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:04 +0200 Subject: [PATCH 1143/7155] perf evsel: Rename perf_evsel__apply_filter() to evsel__apply_filter() Rename perf_evsel__apply_filter() to evsel__apply_filter(), so we don't have a name clash when we add perf_evsel__apply_filter() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-18-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 2 +- tools/perf/util/evsel.c | 2 +- tools/perf/util/evsel.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9461583c53d9..e71c3cc93924 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1158,7 +1158,7 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel) * filters only work for tracepoint event, which doesn't have cpu limit. * So evlist and evsel should always be same. */ - err = perf_evsel__apply_filter(evsel, evsel->filter); + err = evsel__apply_filter(evsel, evsel->filter); if (err) { *err_evsel = evsel; break; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 855d286298eb..5aeb7260c8e1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1187,7 +1187,7 @@ static int perf_evsel__run_ioctl(struct evsel *evsel, return 0; } -int perf_evsel__apply_filter(struct evsel *evsel, const char *filter) +int evsel__apply_filter(struct evsel *evsel, const char *filter) { return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_SET_FILTER, diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c338ce14e8aa..35f7e7ff3c5e 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -294,7 +294,7 @@ int perf_evsel__set_filter(struct evsel *evsel, const char *filter); int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter); int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter); -int perf_evsel__apply_filter(struct evsel *evsel, const char *filter); +int evsel__apply_filter(struct evsel *evsel, const char *filter); int evsel__enable(struct evsel *evsel); int evsel__disable(struct evsel *evsel); -- GitLab From b49aca3e9ce60d00e5bf0694b2ff4c2cd40809e5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:05 +0200 Subject: [PATCH 1144/7155] perf evsel: Rename perf_evsel__cpus() to evsel__cpus() Rename perf_evsel__cpus() to evsel__cpus(), so we don't have a name clash when we add perf_evsel__cpus() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-19-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 4 ++-- tools/perf/util/stat-display.c | 6 +++--- tools/perf/util/stat.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 35f7e7ff3c5e..5fec1ca64f58 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -197,14 +197,14 @@ struct target; struct thread_map; struct record_opts; -static inline struct perf_cpu_map *perf_evsel__cpus(struct evsel *evsel) +static inline struct perf_cpu_map *evsel__cpus(struct evsel *evsel) { return evsel->cpus; } static inline int perf_evsel__nr_cpus(struct evsel *evsel) { - return perf_evsel__cpus(evsel)->nr; + return evsel__cpus(evsel)->nr; } void perf_counts_values__scale(struct perf_counts_values *count, diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index cdfceb5b4d72..f7666d2e6e0c 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -109,7 +109,7 @@ static void aggr_printout(struct perf_stat_config *config, } else { fprintf(config->output, "CPU%*d%s ", config->csv_output ? 0 : -5, - perf_evsel__cpus(evsel)->map[id], + evsel__cpus(evsel)->map[id], config->csv_sep); } break; @@ -325,7 +325,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, return 0; for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { - int cpu2 = perf_evsel__cpus(evsel)->map[i]; + int cpu2 = evsel__cpus(evsel)->map[i]; if (config->aggr_get_id(config, evlist->cpus, cpu2) == id) return cpu2; @@ -593,7 +593,7 @@ static void aggr_cb(struct perf_stat_config *config, for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { struct perf_counts_values *counts; - s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu); + s2 = config->aggr_get_id(config, evsel__cpus(counter), cpu); if (s2 != ad->id) continue; if (first) diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index efd934ec02c3..63f7815ceb4f 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -215,7 +215,7 @@ static int check_per_pkg(struct evsel *counter, struct perf_counts_values *vals, int cpu, bool *skip) { unsigned long *mask = counter->per_pkg_mask; - struct perf_cpu_map *cpus = perf_evsel__cpus(counter); + struct perf_cpu_map *cpus = evsel__cpus(counter); int s; *skip = false; @@ -483,7 +483,7 @@ int create_perf_stat_counter(struct evsel *evsel, } if (target__has_cpu(target) && !target__has_per_thread(target)) - return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel)); return perf_evsel__open_per_thread(evsel, evsel->threads); } -- GitLab From 474ddc4c46025a615d0ea791d37ce9038fa20229 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:06 +0200 Subject: [PATCH 1145/7155] perf evlist: Rename perf_evlist__open() to evlist__open() Rename perf_evlist__open() to evlist__open(), so we don't have a name clash when we add perf_evlist__open() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-20-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/event-times.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/python.c | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 09b6cef76f5b..ea4cf1d367a6 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -83,7 +83,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe evsel->attr.disabled = 1; evsel->attr.enable_on_exec = 0; - CHECK__(perf_evlist__open(evlist)); + CHECK__(evlist__open(evlist)); CHECK__(perf_evlist__mmap(evlist, UINT_MAX)); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 8f54bdfb5743..85604d117558 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1048,7 +1048,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) attr->disabled = 1; } - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { printf("Couldn't create the events: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 95ecefa9ff7e..e508fdb77099 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3342,7 +3342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } } - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) goto out_error_open; diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index ef3c6db2fae4..8de2d6ad93ce 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -125,7 +125,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m perf_evlist__config(evlist, &opts, NULL); - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 313ff1aadd9c..b41c41482283 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -157,7 +157,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), perf_evlist__config(evlist, &opts, NULL); - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 1c7f092a7388..23abc775a69c 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -646,7 +646,7 @@ static int do_test_code_reading(bool try_kcore) evsel->attr.disabled = 1; evsel->attr.enable_on_exec = 0; - ret = perf_evlist__open(evlist); + ret = evlist__open(evlist); if (ret < 0) { if (!excl_kernel) { excl_kernel = true; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 6f9995df2c27..bf00d3d792fb 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -38,7 +38,7 @@ static int attach__enable_on_exec(struct evlist *evlist) evsel->attr.enable_on_exec = 1; - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 1976ccb3c812..c55bc062e200 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -94,7 +94,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evsel->attr.disabled = 1; evsel->attr.enable_on_exec = 0; - if (perf_evlist__open(evlist) < 0) { + if (evlist__open(evlist) < 0) { pr_debug("Unable to open dummy and cycles event\n"); err = TEST_SKIP; goto out_err; diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index f822c3c181f3..233447af9d03 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -60,7 +60,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest thread_map__set_pid(evlist->threads, 0, getpid()); - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 779d5996428b..f5d1e7f1b58b 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -130,7 +130,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus * Call sys_perf_event_open on all the fds on all the evsels, * grouping them if asked to. */ - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 3ab11291174c..528a2dff06e0 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -69,7 +69,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) cpus = NULL; threads = NULL; - if (perf_evlist__open(evlist)) { + if (evlist__open(evlist)) { const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; err = -errno; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 5662dc1c6bd3..47f9895ba807 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -450,7 +450,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ } } - if (perf_evlist__open(evlist) < 0) { + if (evlist__open(evlist) < 0) { pr_debug("Not supported\n"); err = 0; goto out; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 698ee5369c02..d17effdd55c8 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -95,7 +95,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused evsel->attr.wakeup_events = 1; evsel->attr.exclude_kernel = 1; - err = perf_evlist__open(evlist); + err = evlist__open(evlist); if (err < 0) { pr_debug("Couldn't open the evlist: %s\n", str_error_r(-err, sbuf, sizeof(sbuf))); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e71c3cc93924..7d44e05dfaa4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1387,7 +1387,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) goto out; } -int perf_evlist__open(struct evlist *evlist) +int evlist__open(struct evlist *evlist) { struct evsel *evsel; int err; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b3a44e2eed08..f4b3152c879e 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -146,7 +146,7 @@ void perf_evlist__toggle_bkw_mmap(struct evlist *evlist, enum bkw_mmap_state sta void perf_evlist__mmap_consume(struct evlist *evlist, int idx); -int perf_evlist__open(struct evlist *evlist); +int evlist__open(struct evlist *evlist); void perf_evlist__close(struct evlist *evlist); struct callchain_param; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 3eb7348d29f8..cc4af99ab190 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1059,7 +1059,7 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, if (group) perf_evlist__set_leader(evlist); - if (perf_evlist__open(evlist) < 0) { + if (evlist__open(evlist) < 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } -- GitLab From 750b4edeb0527414fb17b0ee2a76d2dbbd9a199d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:07 +0200 Subject: [PATCH 1146/7155] perf evlist: Rename perf_evlist__close() to evlist__close() Rename perf_evlist__close() to evlist__close(), so we don't have a name clash when we add perf_evlist__close() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-21-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-stat.c | 4 ++-- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 85604d117558..6a0573a9c16b 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1058,7 +1058,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) { ui__error("Failed to mmap the events: %s\n", str_error_r(errno, sbuf, sizeof(sbuf))); - perf_evlist__close(evlist); + evlist__close(evlist); goto out; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d28d4d71d9b7..bdfe138f7aed 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -613,7 +613,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) * later the evsel_list will be closed after. */ if (!STAT_RECORD) - perf_evlist__close(evsel_list); + evlist__close(evsel_list); return WEXITSTATUS(status); } @@ -2003,7 +2003,7 @@ int cmd_stat(int argc, const char **argv) perf_session__write_header(perf_stat.session, evsel_list, fd, true); } - perf_evlist__close(evsel_list); + evlist__close(evsel_list); perf_session__delete(perf_stat.session); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7d44e05dfaa4..67c288f467f6 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -140,7 +140,7 @@ void evlist__delete(struct evlist *evlist) return; perf_evlist__munmap(evlist); - perf_evlist__close(evlist); + evlist__close(evlist); cpu_map__put(evlist->cpus); thread_map__put(evlist->threads); evlist->cpus = NULL; @@ -1348,7 +1348,7 @@ void perf_evlist__set_selected(struct evlist *evlist, evlist->selected = evsel; } -void perf_evlist__close(struct evlist *evlist) +void evlist__close(struct evlist *evlist) { struct evsel *evsel; @@ -1412,7 +1412,7 @@ int evlist__open(struct evlist *evlist) return 0; out_err: - perf_evlist__close(evlist); + evlist__close(evlist); errno = -err; return err; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index f4b3152c879e..47e9d26b6774 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -147,7 +147,7 @@ void perf_evlist__toggle_bkw_mmap(struct evlist *evlist, enum bkw_mmap_state sta void perf_evlist__mmap_consume(struct evlist *evlist, int idx); int evlist__open(struct evlist *evlist); -void perf_evlist__close(struct evlist *evlist); +void evlist__close(struct evlist *evlist); struct callchain_param; -- GitLab From 1c87f1654cc315fbeae0238a8dbf5bf3c498f3af Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:08 +0200 Subject: [PATCH 1147/7155] perf evlist: Rename perf_evlist__enable() to evlist__enable() Rename perf_evlist__enable() to evlist__enable(), so we don't have a name clash when we add perf_evlist__enable() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-22-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 4 ++-- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evlist.h | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index ea4cf1d367a6..aa5a5c972ce5 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -97,7 +97,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe goto out_err; } - perf_evlist__enable(evlist); + evlist__enable(evlist); comm1 = "Test COMM 1"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0)); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 6a0573a9c16b..9207bd49583e 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -972,7 +972,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) goto out; /* everything is good - enable the events and process */ - perf_evlist__enable(kvm->evlist); + evlist__enable(kvm->evlist); while (!done) { struct fdarray *fda = &kvm->evlist->pollfd; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 7f933997b6d0..8e20ead0ddbe 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1453,7 +1453,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * so don't spoil it by prematurely enabling them. */ if (!target__none(&opts->target) && !opts->initial_delay) - perf_evlist__enable(rec->evlist); + evlist__enable(rec->evlist); /* * Let the child rip @@ -1506,7 +1506,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) if (opts->initial_delay) { usleep(opts->initial_delay * USEC_PER_MSEC); - perf_evlist__enable(rec->evlist); + evlist__enable(rec->evlist); } trigger_ready(&auxtrace_snapshot_trigger); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index bdfe138f7aed..c0e9d94b6dd5 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -362,7 +362,7 @@ static void enable_counters(void) * - we have initial delay configured */ if (!target__none(&target) || stat_config.initial_delay) - perf_evlist__enable(evsel_list); + evlist__enable(evsel_list); } static void disable_counters(void) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5886389f6a40..b103f1ba01cb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1255,7 +1255,7 @@ static int __cmd_top(struct perf_top *top) * so leave the check here. */ if (!target__none(&opts->target)) - perf_evlist__enable(top->evlist); + evlist__enable(top->evlist); ret = -1; if (pthread_create(&thread_process, NULL, process_thread, top)) { diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e508fdb77099..46fab1ff92dc 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3402,14 +3402,14 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error_mmap; if (!target__none(&trace->opts.target) && !trace->opts.initial_delay) - perf_evlist__enable(evlist); + evlist__enable(evlist); if (forks) perf_evlist__start_workload(evlist); if (trace->opts.initial_delay) { usleep(trace->opts.initial_delay * 1000); - perf_evlist__enable(evlist); + evlist__enable(evlist); } trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 8de2d6ad93ce..f4b45702821d 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -68,7 +68,7 @@ static int do_test(struct evlist *evlist, int mmap_pages, return TEST_FAIL; } - perf_evlist__enable(evlist); + evlist__enable(evlist); testcase(); perf_evlist__disable(evlist); diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index b41c41482283..92fed94f4b6c 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -171,7 +171,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), goto out_delete_evlist; } - perf_evlist__enable(evlist); + evlist__enable(evlist); (*func)(); perf_evlist__disable(evlist); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 23abc775a69c..8d38e001160d 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -680,7 +680,7 @@ static int do_test_code_reading(bool try_kcore) goto out_put; } - perf_evlist__enable(evlist); + evlist__enable(evlist); do_something(); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index c55bc062e200..c333b9c765e8 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -107,7 +107,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un * enabled. */ - perf_evlist__enable(evlist); + evlist__enable(evlist); comm = "Test COMM 1"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); @@ -125,7 +125,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un * disabled with the dummy event still enabled. */ - perf_evlist__enable(evlist); + evlist__enable(evlist); evsel = perf_evlist__last(evlist); diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 233447af9d03..c7182b7840e5 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -74,7 +74,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest goto out_delete_evlist; } - perf_evlist__enable(evlist); + evlist__enable(evlist); /* * Generate the event: diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index f5d1e7f1b58b..67b388e92cba 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -153,7 +153,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus * Now that all is properly set up, enable the events, they will * count just on workload.pid, which will start... */ - perf_evlist__enable(evlist); + evlist__enable(evlist); /* * Now! diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 528a2dff06e0..4ab316c04ce7 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -86,7 +86,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) goto out_delete_evlist; } - perf_evlist__enable(evlist); + evlist__enable(evlist); /* collect samples */ for (i = 0; i < NR_LOOPS; i++) diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 47f9895ba807..ea214313f22b 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -462,7 +462,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - perf_evlist__enable(evlist); + evlist__enable(evlist); err = evsel__disable(cpu_clocks_evsel); if (err) { diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 67c288f467f6..94825c37a35f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -356,7 +356,7 @@ void perf_evlist__disable(struct evlist *evlist) evlist->enabled = false; } -void perf_evlist__enable(struct evlist *evlist) +void evlist__enable(struct evlist *evlist) { struct evsel *pos; @@ -371,7 +371,7 @@ void perf_evlist__enable(struct evlist *evlist) void perf_evlist__toggle_enable(struct evlist *evlist) { - (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist); + (evlist->enabled ? perf_evlist__disable : evlist__enable)(evlist); } static int perf_evlist__enable_event_cpu(struct evlist *evlist, diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 47e9d26b6774..ab48bbfbca41 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -185,7 +185,7 @@ void perf_evlist__munmap(struct evlist *evlist); size_t perf_evlist__mmap_size(unsigned long pages); void perf_evlist__disable(struct evlist *evlist); -void perf_evlist__enable(struct evlist *evlist); +void evlist__enable(struct evlist *evlist); void perf_evlist__toggle_enable(struct evlist *evlist); int perf_evlist__enable_event_idx(struct evlist *evlist, -- GitLab From e74676debaae7dcce20a34817ef145478887ba95 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:09 +0200 Subject: [PATCH 1148/7155] perf evlist: Rename perf_evlist__disable() to evlist__disable() Rename perf_evlist__disable() to evlist__disable(), so we don't have a name clash when we add perf_evlist__disable() in libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-23-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 6 +++--- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 4 ++-- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evlist.h | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index aa5a5c972ce5..8b70e9ee341a 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -107,7 +107,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe comm2 = "Test COMM 2"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0)); - perf_evlist__disable(evlist); + evlist__disable(evlist); for (i = 0; i < evlist->nr_mmaps; i++) { md = &evlist->mmap[i]; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 9207bd49583e..3370eba0d3f3 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -993,7 +993,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) err = fdarray__poll(fda, 100); } - perf_evlist__disable(kvm->evlist); + evlist__disable(kvm->evlist); if (err == 0) { sort_result(kvm); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8e20ead0ddbe..c0962ddfad04 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1605,7 +1605,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) */ if (done && !disabled && !target__none(&opts->target)) { trigger_off(&auxtrace_snapshot_trigger); - perf_evlist__disable(rec->evlist); + evlist__disable(rec->evlist); disabled = true; } } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c0e9d94b6dd5..36e66a4f3c57 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -373,7 +373,7 @@ static void disable_counters(void) * from counting before reading their constituent counters. */ if (!target__none(&target)) - perf_evlist__disable(evsel_list); + evlist__disable(evsel_list); } static volatile int workload_exec_errno; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 46fab1ff92dc..51d142594a12 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3451,7 +3451,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_disable; if (done && !draining) { - perf_evlist__disable(evlist); + evlist__disable(evlist); draining = true; } } @@ -3477,7 +3477,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) out_disable: thread__zput(trace->current); - perf_evlist__disable(evlist); + evlist__disable(evlist); if (trace->sort_events) ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL); diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index f4b45702821d..9bdf66139099 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -70,7 +70,7 @@ static int do_test(struct evlist *evlist, int mmap_pages, evlist__enable(evlist); testcase(); - perf_evlist__disable(evlist); + evlist__disable(evlist); err = count_samples(evlist, sample_count, comm_count); perf_evlist__munmap(evlist); diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 92fed94f4b6c..e16f927f38b6 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -173,7 +173,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), evlist__enable(evlist); (*func)(); - perf_evlist__disable(evlist); + evlist__disable(evlist); for (i = 0; i < evlist->nr_mmaps; i++) { union perf_event *event; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 8d38e001160d..ec4b0bf28270 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -684,7 +684,7 @@ static int do_test_code_reading(bool try_kcore) do_something(); - perf_evlist__disable(evlist); + evlist__disable(evlist); ret = process_events(machine, evlist, &state); if (ret < 0) diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index c333b9c765e8..7bfc859971e5 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -112,7 +112,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un comm = "Test COMM 1"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); - perf_evlist__disable(evlist); + evlist__disable(evlist); found = find_comm(evlist, comm); if (found != 1) { @@ -134,7 +134,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un comm = "Test COMM 2"; CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); - perf_evlist__disable(evlist); + evlist__disable(evlist); found = find_comm(evlist, comm); if (found != 1) { @@ -146,7 +146,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un out_err: if (evlist) { - perf_evlist__disable(evlist); + evlist__disable(evlist); evlist__delete(evlist); } else { cpu_map__put(cpus); diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 4ab316c04ce7..ba033a6e6c0f 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -92,7 +92,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) for (i = 0; i < NR_LOOPS; i++) tmp++; - perf_evlist__disable(evlist); + evlist__disable(evlist); md = &evlist->mmap[0]; if (perf_mmap__read_init(md) < 0) diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index ea214313f22b..d5537edb47db 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -528,7 +528,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - perf_evlist__disable(evlist); + evlist__disable(evlist); switch_tracking.switch_evsel = switch_evsel; switch_tracking.cycles_evsel = cycles_evsel; @@ -566,7 +566,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ } out: if (evlist) { - perf_evlist__disable(evlist); + evlist__disable(evlist); evlist__delete(evlist); } else { cpu_map__put(cpus); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 94825c37a35f..1bedec28e58f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -343,7 +343,7 @@ static int perf_evlist__nr_threads(struct evlist *evlist, return thread_map__nr(evlist->threads); } -void perf_evlist__disable(struct evlist *evlist) +void evlist__disable(struct evlist *evlist) { struct evsel *pos; @@ -371,7 +371,7 @@ void evlist__enable(struct evlist *evlist) void perf_evlist__toggle_enable(struct evlist *evlist) { - (evlist->enabled ? perf_evlist__disable : evlist__enable)(evlist); + (evlist->enabled ? evlist__disable : evlist__enable)(evlist); } static int perf_evlist__enable_event_cpu(struct evlist *evlist, diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index ab48bbfbca41..99621c056d09 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -184,7 +184,7 @@ void perf_evlist__munmap(struct evlist *evlist); size_t perf_evlist__mmap_size(unsigned long pages); -void perf_evlist__disable(struct evlist *evlist); +void evlist__disable(struct evlist *evlist); void evlist__enable(struct evlist *evlist); void perf_evlist__toggle_enable(struct evlist *evlist); -- GitLab From 3143504918105156d03e8f927e127f7b9ea260d2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:10 +0200 Subject: [PATCH 1149/7155] libperf: Make libperf.a part of the perf build Add an empty libperf.a under tools/perf/lib and link it with perf. It can also be built separately with: $ cd tools/perf/lib && make CC core.o LD libperf-in.o AR libperf.a LINK libperf.so Committer testing: $ make O=/tmp/build/perf -C tools/perf/lib/ make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK /tmp/build/perf/libperf.so make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ ls -la /tmp/build/perf/libperf.so -rwxrwxr-x. 1 acme acme 16232 Jul 22 15:30 /tmp/build/perf/libperf.so $ file /tmp/build/perf/libperf.so /tmp/build/perf/libperf.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=7a51d227d871b381ddb686dcf94145c4dd908221, not stripped $ git status tools/perf On branch perf/core nothing to commit, working tree clean $ $ ls -lart tools/perf/lib/ total 16 drwxrwxr-x. 16 acme acme 4096 Jul 22 15:29 .. -rw-rw-r--. 1 acme acme 1633 Jul 22 15:29 Makefile -rw-rw-r--. 1 acme acme 0 Jul 22 15:29 core.c -rw-rw-r--. 1 acme acme 20 Jul 22 15:29 Build drwxrwxr-x. 2 acme acme 4096 Jul 22 15:29 . $ Committer notes: Need to add -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi to tools/perf/lib/Makefile's INCLUDE variable to pick up the latest versions of kernel headers, even in older systems, this is in line with what is in tools/lib/bpf/Makefile. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-24-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 1 + tools/perf/Makefile.perf | 30 ++++++++-------- tools/perf/lib/Build | 1 + tools/perf/lib/Makefile | 74 ++++++++++++++++++++++++++++++++++++++ tools/perf/lib/core.c | 0 5 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 tools/perf/lib/Build create mode 100644 tools/perf/lib/Makefile create mode 100644 tools/perf/lib/core.c diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 89ac5a1f1550..e4988f49ea79 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -277,6 +277,7 @@ ifeq ($(DEBUG),0) endif endif +INC_FLAGS += -I$(src-perf)/lib/include INC_FLAGS += -I$(src-perf)/util/include INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include INC_FLAGS += -I$(srctree)/tools/include/uapi diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 0fffd2bb6cd9..6e7e7d44ffac 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -224,6 +224,7 @@ LIB_DIR = $(srctree)/tools/lib/api/ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ BPF_DIR = $(srctree)/tools/lib/bpf/ SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ +LIBPERF_DIR = $(srctree)/tools/perf/lib/ # Set FEATURE_TESTS to 'all' so all possible feature checkers are executed. # Without this setting the output feature dump file misses some features, for @@ -272,6 +273,7 @@ ifneq ($(OUTPUT),) TE_PATH=$(OUTPUT) BPF_PATH=$(OUTPUT) SUBCMD_PATH=$(OUTPUT) + LIBPERF_PATH=$(OUTPUT) ifneq ($(subdir),) API_PATH=$(OUTPUT)/../lib/api/ else @@ -282,6 +284,7 @@ else API_PATH=$(LIB_DIR) BPF_PATH=$(BPF_DIR) SUBCMD_PATH=$(SUBCMD_DIR) + LIBPERF_PATH=$(LIBPERF_DIR) endif LIBTRACEEVENT = $(TE_PATH)libtraceevent.a @@ -303,6 +306,8 @@ LIBBPF = $(BPF_PATH)libbpf.a LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a +LIBPERF = $(LIBPERF_PATH)libperf.a + # python extension build directories PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ @@ -348,9 +353,7 @@ endif export PERL_PATH -LIBPERF_A=$(OUTPUT)libperf.a - -PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD) +PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD) $(LIBPERF) ifndef NO_LIBBPF PERFLIBS += $(LIBBPF) endif @@ -583,8 +586,6 @@ JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o -LIBPERF_IN := $(OUTPUT)libperf-in.o - export JEVENTS build := -f $(srctree)/tools/build/Makefile.build dir=. obj @@ -601,12 +602,9 @@ $(JEVENTS): $(JEVENTS_IN) $(PMU_EVENTS_IN): $(JEVENTS) FORCE $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events -$(LIBPERF_IN): prepare FORCE - $(Q)$(MAKE) $(build)=libperf - -$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) +$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ - $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBS) -o $@ + $(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@ $(GTK_IN): FORCE $(Q)$(MAKE) $(build)=gtk @@ -727,9 +725,6 @@ endif $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) -$(LIBPERF_A): $(LIBPERF_IN) - $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS) - LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)' $(LIBTRACEEVENT): FORCE @@ -762,6 +757,13 @@ $(LIBBPF)-clean: $(call QUIET_CLEAN, libbpf) $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null +$(LIBPERF): FORCE + $(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) $(OUTPUT)libperf.a + +$(LIBPERF)-clean: + $(call QUIET_CLEAN, libperf) + $(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) clean >/dev/null + $(LIBSUBCMD): FORCE $(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a @@ -948,7 +950,7 @@ config-clean: python-clean: $(python-clean) -clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean +clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBPERF)-clean config-clean fixdep-clean python-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete $(Q)$(RM) $(OUTPUT).config-detected diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build new file mode 100644 index 000000000000..5196958cec01 --- /dev/null +++ b/tools/perf/lib/Build @@ -0,0 +1 @@ +libperf-y += core.o diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile new file mode 100644 index 000000000000..33046e7c6a2a --- /dev/null +++ b/tools/perf/lib/Makefile @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +# Most of this file is copied from tools/lib/bpf/Makefile + +MAKEFLAGS += --no-print-directory + +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +#$(info Determined 'srctree' to be $(srctree)) +endif + +include $(srctree)/tools/scripts/Makefile.include +include $(srctree)/tools/scripts/Makefile.arch + +ifeq ("$(origin V)", "command line") + VERBOSE = $(V) +endif +ifndef VERBOSE + VERBOSE = 0 +endif + +ifeq ($(VERBOSE),1) + Q = +else + Q = @ +endif + +# Set compile option CFLAGS +ifdef EXTRA_CFLAGS + CFLAGS := $(EXTRA_CFLAGS) +else + CFLAGS := -g -Wall +endif + +INCLUDES = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/ -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi + +# Append required CFLAGS +override CFLAGS += $(EXTRA_WARNINGS) +override CFLAGS += -Werror -Wall +override CFLAGS += -fPIC +override CFLAGS += $(INCLUDES) +override CFLAGS += -fvisibility=hidden + +all: + +export srctree OUTPUT CC LD CFLAGS V +include $(srctree)/tools/build/Makefile.include + +LIBPERF_SO := $(OUTPUT)libperf.so +LIBPERF_A := $(OUTPUT)libperf.a +LIBPERF_IN := $(OUTPUT)libperf-in.o + +$(LIBPERF_IN): FORCE + $(Q)$(MAKE) $(build)=libperf + +$(LIBPERF_A): $(LIBPERF_IN) + $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) + +$(LIBPERF_SO): $(LIBPERF_IN) + $(QUIET_LINK)$(CC) --shared -Wl,-soname,libperf.so $^ -o $@ + +libs: $(LIBPERF_A) $(LIBPERF_SO) + +all: fixdep + $(Q)$(MAKE) libs + +clean: + $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \ + *.o *~ *.a *.so .*.d .*.cmd LIBPERF-CFLAGS + +FORCE: + +.PHONY: all install clean FORCE diff --git a/tools/perf/lib/core.c b/tools/perf/lib/core.c new file mode 100644 index 000000000000..e69de29bb2d1 -- GitLab From 47f9bccc79cb067103ad5e9790e0d01c94839429 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:11 +0200 Subject: [PATCH 1150/7155] libperf: Add build version support Add a shared library version, generating the following files: $ ll tools/perf/lib/libperf.so* libperf.so -> libperf.so.0.0.1 libperf.so.0 -> libperf.so.0.0.1 libperf.so.0.0.1 Committer testing: One has to build just libbperf to get this, building perf so far doesn't trigger this, i.e. I tried: $ make O=/tmp/build/perf -C tools/perf And the files above were not created, so one has to do: $ make O=/tmp/build/perf -C tools/perf/lib/ make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK /tmp/build/perf/libperf.so.0.0.1 make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ ls -la /tmp/build/perf/*.so.* lrwxrwxrwx. 1 acme acme 16 Jul 22 15:37 /tmp/build/perf/libperf.so.0 -> libperf.so.0.0.1 -rwxrwxr-x. 1 acme acme 16368 Jul 22 15:37 /tmp/build/perf/libperf.so.0.0.1 $ Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-25-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Makefile | 20 +++++++++++++++++--- tools/perf/lib/libperf.map | 4 ++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tools/perf/lib/libperf.map diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile index 33046e7c6a2a..cd571ec648ad 100644 --- a/tools/perf/lib/Makefile +++ b/tools/perf/lib/Makefile @@ -1,6 +1,10 @@ # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) # Most of this file is copied from tools/lib/bpf/Makefile +LIBPERF_VERSION = 0 +LIBPERF_PATCHLEVEL = 0 +LIBPERF_EXTRAVERSION = 1 + MAKEFLAGS += --no-print-directory ifeq ($(srctree),) @@ -47,7 +51,13 @@ all: export srctree OUTPUT CC LD CFLAGS V include $(srctree)/tools/build/Makefile.include -LIBPERF_SO := $(OUTPUT)libperf.so +VERSION_SCRIPT := libperf.map + +PATCHLEVEL = $(LIBPERF_PATCHLEVEL) +EXTRAVERSION = $(LIBPERF_EXTRAVERSION) +VERSION = $(LIBPERF_VERSION).$(LIBPERF_PATCHLEVEL).$(LIBPERF_EXTRAVERSION) + +LIBPERF_SO := $(OUTPUT)libperf.so.$(VERSION) LIBPERF_A := $(OUTPUT)libperf.a LIBPERF_IN := $(OUTPUT)libperf-in.o @@ -58,7 +68,11 @@ $(LIBPERF_A): $(LIBPERF_IN) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIBPERF_SO): $(LIBPERF_IN) - $(QUIET_LINK)$(CC) --shared -Wl,-soname,libperf.so $^ -o $@ + $(QUIET_LINK)$(CC) --shared -Wl,-soname,libperf.so \ + -Wl,--version-script=$(VERSION_SCRIPT) $^ -o $@ + @ln -sf $(@F) $(OUTPUT)libperf.so + @ln -sf $(@F) $(OUTPUT)libperf.so.$(LIBPERF_VERSION) + libs: $(LIBPERF_A) $(LIBPERF_SO) @@ -67,7 +81,7 @@ all: fixdep clean: $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \ - *.o *~ *.a *.so .*.d .*.cmd LIBPERF-CFLAGS + *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS FORCE: diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map new file mode 100644 index 000000000000..a8e913988edf --- /dev/null +++ b/tools/perf/lib/libperf.map @@ -0,0 +1,4 @@ +LIBPERF_0.0.1 { + local: + *; +}; -- GitLab From a429dcb8feb60b8500fed81e2275c1944e3091fc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:12 +0200 Subject: [PATCH 1151/7155] libperf: Add libperf to the python.so build Link libperf.a with python.so. Committer testing: Continues to work: # perf test python 18: 'import perf' in python : Ok # Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-26-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 1 + tools/perf/util/setup.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 6e7e7d44ffac..67512a12276b 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -307,6 +307,7 @@ LIBBPF = $(BPF_PATH)libbpf.a LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a LIBPERF = $(LIBPERF_PATH)libperf.a +export LIBPERF # python extension build directories PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index a1a68a2fa917..d48f9cd58964 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -48,6 +48,7 @@ build_lib = getenv('PYTHON_EXTBUILD_LIB') build_tmp = getenv('PYTHON_EXTBUILD_TMP') libtraceevent = getenv('LIBTRACEEVENT') libapikfs = getenv('LIBAPI') +libperf = getenv('LIBPERF') ext_sources = [f.strip() for f in open('util/python-ext-sources') if len(f.strip()) > 0 and f[0] != '#'] @@ -64,7 +65,7 @@ perf = Extension('perf', include_dirs = ['util/include'], libraries = extra_libraries, extra_compile_args = cflags, - extra_objects = [libtraceevent, libapikfs], + extra_objects = [libtraceevent, libapikfs, libperf], ) setup(name='perf', -- GitLab From 5b7f445d684fc287a2101e29d42d1fee19ae14ff Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:13 +0200 Subject: [PATCH 1152/7155] libperf: Add perf/core.h header Add perf/core.h header to be used in header files coming in the following patches. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-27-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/perf/core.h | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tools/perf/lib/include/perf/core.h diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h new file mode 100644 index 000000000000..e2e4b43c9131 --- /dev/null +++ b/tools/perf/lib/include/perf/core.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_CORE_H +#define __LIBPERF_CORE_H + +#ifndef LIBPERF_API +#define LIBPERF_API __attribute__((visibility("default"))) +#endif + +#endif /* __LIBPERF_CORE_H */ -- GitLab From a1556f8479ed58b8d5a33aef54578bad0165c7e7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:14 +0200 Subject: [PATCH 1153/7155] libperf: Add debug output support Add the perf_set_print() function to allow setting an output function for warn/info/debug messages. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-28-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/core.c | 34 ++++++++++++++++++++++++++++++ tools/perf/lib/include/perf/core.h | 13 ++++++++++++ tools/perf/lib/internal.h | 18 ++++++++++++++++ tools/perf/lib/libperf.map | 2 ++ 4 files changed, 67 insertions(+) create mode 100644 tools/perf/lib/internal.h diff --git a/tools/perf/lib/core.c b/tools/perf/lib/core.c index e69de29bb2d1..29d5e3348718 100644 --- a/tools/perf/lib/core.c +++ b/tools/perf/lib/core.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define __printf(a, b) __attribute__((format(printf, a, b))) + +#include +#include +#include +#include "internal.h" + +static int __base_pr(enum libperf_print_level level, const char *format, + va_list args) +{ + return vfprintf(stderr, format, args); +} + +static libperf_print_fn_t __libperf_pr = __base_pr; + +void libperf_set_print(libperf_print_fn_t fn) +{ + __libperf_pr = fn; +} + +__printf(2, 3) +void libperf_print(enum libperf_print_level level, const char *format, ...) +{ + va_list args; + + if (!__libperf_pr) + return; + + va_start(args, format); + __libperf_pr(level, format, args); + va_end(args); +} diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h index e2e4b43c9131..c341a7b2c874 100644 --- a/tools/perf/lib/include/perf/core.h +++ b/tools/perf/lib/include/perf/core.h @@ -2,8 +2,21 @@ #ifndef __LIBPERF_CORE_H #define __LIBPERF_CORE_H +#include + #ifndef LIBPERF_API #define LIBPERF_API __attribute__((visibility("default"))) #endif +enum libperf_print_level { + LIBPERF_WARN, + LIBPERF_INFO, + LIBPERF_DEBUG, +}; + +typedef int (*libperf_print_fn_t)(enum libperf_print_level level, + const char *, va_list ap); + +LIBPERF_API void libperf_set_print(libperf_print_fn_t fn); + #endif /* __LIBPERF_CORE_H */ diff --git a/tools/perf/lib/internal.h b/tools/perf/lib/internal.h new file mode 100644 index 000000000000..dc92f241732e --- /dev/null +++ b/tools/perf/lib/internal.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_H +#define __LIBPERF_INTERNAL_H + +void libperf_print(enum libperf_print_level level, + const char *format, ...) + __attribute__((format(printf, 2, 3))); + +#define __pr(level, fmt, ...) \ +do { \ + libperf_print(level, "libperf: " fmt, ##__VA_ARGS__); \ +} while (0) + +#define pr_warning(fmt, ...) __pr(LIBPERF_WARN, fmt, ##__VA_ARGS__) +#define pr_info(fmt, ...) __pr(LIBPERF_INFO, fmt, ##__VA_ARGS__) +#define pr_debug(fmt, ...) __pr(LIBPERF_DEBUG, fmt, ##__VA_ARGS__) + +#endif /* __LIBPERF_INTERNAL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index a8e913988edf..3536242c545c 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -1,4 +1,6 @@ LIBPERF_0.0.1 { + global: + libperf_set_print; local: *; }; -- GitLab From 959b83c769389b24d64759f60e64c4c62620ff02 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:15 +0200 Subject: [PATCH 1154/7155] libperf: Add perf_cpu_map struct Add perf_cpu_map struct to libperf. It's added as a declaration into: include/perf/cpumap.h which will be included by users. The perf_cpu_map struct definition is added into: include/internal/cpumap.h which is not to be included by users, but shared within perf and libperf. We tried the total separation of the perf_cpu_map struct in libperf, but it lead to complications and much bigger changes in perf code, so we decided to share the declaration. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-29-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Build | 1 + tools/perf/lib/cpumap.c | 5 +++++ tools/perf/lib/include/internal/cpumap.h | 13 +++++++++++++ tools/perf/lib/include/perf/cpumap.h | 7 +++++++ tools/perf/util/cpumap.h | 7 +------ 5 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 tools/perf/lib/cpumap.c create mode 100644 tools/perf/lib/include/internal/cpumap.h create mode 100644 tools/perf/lib/include/perf/cpumap.h diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index 5196958cec01..195b274db49a 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -1 +1,2 @@ libperf-y += core.o +libperf-y += cpumap.o diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c new file mode 100644 index 000000000000..86a199c26f20 --- /dev/null +++ b/tools/perf/lib/cpumap.c @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include diff --git a/tools/perf/lib/include/internal/cpumap.h b/tools/perf/lib/include/internal/cpumap.h new file mode 100644 index 000000000000..53ce95374b05 --- /dev/null +++ b/tools/perf/lib/include/internal/cpumap.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_CPUMAP_H +#define __LIBPERF_INTERNAL_CPUMAP_H + +#include + +struct perf_cpu_map { + refcount_t refcnt; + int nr; + int map[]; +}; + +#endif /* __LIBPERF_INTERNAL_CPUMAP_H */ diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h new file mode 100644 index 000000000000..8355d3ce7d0c --- /dev/null +++ b/tools/perf/lib/include/perf/cpumap.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_CPUMAP_H +#define __LIBPERF_CPUMAP_H + +struct perf_cpu_map; + +#endif /* __LIBPERF_CPUMAP_H */ diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 22729beae959..c2ba9ae195f7 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -5,16 +5,11 @@ #include #include #include +#include #include "perf.h" #include "util/debug.h" -struct perf_cpu_map { - refcount_t refcnt; - int nr; - int map[]; -}; - struct perf_cpu_map *cpu_map__new(const char *cpu_list); struct perf_cpu_map *cpu_map__empty_new(int nr); struct perf_cpu_map *cpu_map__dummy_new(void); -- GitLab From 397721e06e52d017cfdd403f63284ed0995d4caf Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:16 +0200 Subject: [PATCH 1155/7155] libperf: Add perf_cpu_map__dummy_new() function Move cpu_map__dummy_new() to libperf as perf_cpu_map__dummy_new() function. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-30-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/cpumap.c | 13 +++++++++++++ tools/perf/lib/include/perf/cpumap.h | 4 ++++ tools/perf/lib/libperf.map | 1 + tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/util/cpumap.c | 15 +-------------- tools/perf/util/cpumap.h | 2 +- tools/perf/util/evlist.c | 2 +- tools/perf/util/evsel.c | 2 +- 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index 86a199c26f20..80d587ab95aa 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -3,3 +3,16 @@ #include #include #include + +struct perf_cpu_map *perf_cpu_map__dummy_new(void) +{ + struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); + + if (cpus != NULL) { + cpus->nr = 1; + cpus->map[0] = -1; + refcount_set(&cpus->refcnt, 1); + } + + return cpus; +} diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h index 8355d3ce7d0c..fa1e5aa9d662 100644 --- a/tools/perf/lib/include/perf/cpumap.h +++ b/tools/perf/lib/include/perf/cpumap.h @@ -2,6 +2,10 @@ #ifndef __LIBPERF_CPUMAP_H #define __LIBPERF_CPUMAP_H +#include + struct perf_cpu_map; +LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); + #endif /* __LIBPERF_CPUMAP_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 3536242c545c..65201c6cbe7e 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -1,6 +1,7 @@ LIBPERF_0.0.1 { global: libperf_set_print; + perf_cpu_map__dummy_new; local: *; }; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index ba033a6e6c0f..c6d3f4488b73 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -56,7 +56,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) } evlist__add(evlist, evsel); - cpus = cpu_map__dummy_new(); + cpus = perf_cpu_map__dummy_new(); threads = thread_map__new_by_tid(getpid()); if (!cpus || !threads) { err = -ENOMEM; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index d17effdd55c8..c094fb8cc877 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -63,7 +63,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused * perf_evlist__prepare_workload we'll fill in the only thread * we're monitoring, the one forked there. */ - cpus = cpu_map__dummy_new(); + cpus = perf_cpu_map__dummy_new(); threads = thread_map__new_by_tid(-1); if (!cpus || !threads) { err = -ENOMEM; diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 5eb4e1fbb877..acda9bfb4002 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -189,7 +189,7 @@ struct perf_cpu_map *cpu_map__new(const char *cpu_list) else if (*cpu_list != '\0') cpus = cpu_map__default_new(); else - cpus = cpu_map__dummy_new(); + cpus = perf_cpu_map__dummy_new(); invalid: free(tmp_cpus); out: @@ -256,19 +256,6 @@ size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) #undef BUFSIZE } -struct perf_cpu_map *cpu_map__dummy_new(void) -{ - struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); - - if (cpus != NULL) { - cpus->nr = 1; - cpus->map[0] = -1; - refcount_set(&cpus->refcnt, 1); - } - - return cpus; -} - struct perf_cpu_map *cpu_map__empty_new(int nr) { struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index c2ba9ae195f7..0ce3f6bd9449 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -6,13 +6,13 @@ #include #include #include +#include #include "perf.h" #include "util/debug.h" struct perf_cpu_map *cpu_map__new(const char *cpu_list); struct perf_cpu_map *cpu_map__empty_new(int nr); -struct perf_cpu_map *cpu_map__dummy_new(void); struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); struct perf_cpu_map *cpu_map__read(FILE *file); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 1bedec28e58f..461c1e68e9e7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1086,7 +1086,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) return -1; if (target__uses_dummy_map(target)) - cpus = cpu_map__dummy_new(); + cpus = perf_cpu_map__dummy_new(); else cpus = cpu_map__new(target->cpu_list); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5aeb7260c8e1..a389752840a9 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1840,7 +1840,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, static struct perf_cpu_map *empty_cpu_map; if (empty_cpu_map == NULL) { - empty_cpu_map = cpu_map__dummy_new(); + empty_cpu_map = perf_cpu_map__dummy_new(); if (empty_cpu_map == NULL) return -ENOMEM; } -- GitLab From 38f01d8da1d8d28678ea16a0a484f4d3eded34b2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:17 +0200 Subject: [PATCH 1156/7155] libperf: Add perf_cpu_map__get()/perf_cpu_map__put() Moving the following functions: cpu_map__get() cpu_map__put() to libperf with following names: perf_cpu_map__get() perf_cpu_map__put() Committer notes: Added fixes for arm/arm64 Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-31-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +++--- tools/perf/arch/arm64/util/header.c | 4 ++-- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-stat.c | 4 ++-- tools/perf/lib/cpumap.c | 24 ++++++++++++++++++++++ tools/perf/lib/include/perf/cpumap.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ tools/perf/tests/bitmap.c | 2 +- tools/perf/tests/code-reading.c | 4 ++-- tools/perf/tests/cpumap.c | 8 ++++---- tools/perf/tests/event-times.c | 4 ++-- tools/perf/tests/event_update.c | 4 ++-- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mem2node.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/tests/topology.c | 2 +- tools/perf/util/cpumap.c | 22 -------------------- tools/perf/util/cpumap.h | 3 --- tools/perf/util/cputopo.c | 4 ++-- tools/perf/util/env.c | 2 +- tools/perf/util/event.c | 2 +- tools/perf/util/evlist.c | 16 +++++++-------- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/parse-events.c | 4 ++-- tools/perf/util/pmu.c | 2 +- tools/perf/util/python.c | 2 +- tools/perf/util/record.c | 6 +++--- tools/perf/util/session.c | 2 +- tools/perf/util/svghelper.c | 2 +- 33 files changed, 78 insertions(+), 75 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 268fcb31cd53..3a78b38e43ca 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -181,7 +181,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr, err = 0; out: - cpu_map__put(online_cpus); + perf_cpu_map__put(online_cpus); return err; } @@ -517,7 +517,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, } } - cpu_map__put(online_cpus); + perf_cpu_map__put(online_cpus); return (CS_ETM_HEADER_SIZE + (etmv4 * CS_ETMV4_PRIV_SIZE) + @@ -679,7 +679,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, if (cpu_map__has(cpu_map, i)) cs_etm_get_metadata(i, &offset, itr, info); - cpu_map__put(online_cpus); + perf_cpu_map__put(online_cpus); return 0; } diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c index b3e73a413f5a..602caf550e7f 100644 --- a/tools/perf/arch/arm64/util/header.c +++ b/tools/perf/arch/arm64/util/header.c @@ -27,7 +27,7 @@ char *get_cpuid_str(struct perf_pmu *pmu) return NULL; /* read midr from list of cpus mapped to this pmu */ - cpus = cpu_map__get(pmu->cpus); + cpus = perf_cpu_map__get(pmu->cpus); for (cpu = 0; cpu < cpus->nr; cpu++) { scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR, sysfs, cpus->map[cpu]); @@ -60,6 +60,6 @@ char *get_cpuid_str(struct perf_pmu *pmu) buf = NULL; } - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return buf; } diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 105ef2a17a9c..6943352b8d94 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -206,7 +206,7 @@ static int reset_tracing_cpu(void) int ret; ret = set_tracing_cpumask(cpumap); - cpu_map__put(cpumap); + perf_cpu_map__put(cpumap); return ret; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 36e66a4f3c57..39bd73d0e06e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -933,8 +933,8 @@ static int perf_stat_init_aggr_mode(void) static void perf_stat__exit_aggr_mode(void) { - cpu_map__put(stat_config.aggr_map); - cpu_map__put(stat_config.cpus_aggr_map); + perf_cpu_map__put(stat_config.aggr_map); + perf_cpu_map__put(stat_config.cpus_aggr_map); stat_config.aggr_map = NULL; stat_config.cpus_aggr_map = NULL; } diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index 80d587ab95aa..f3cfb4c71106 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include struct perf_cpu_map *perf_cpu_map__dummy_new(void) { @@ -16,3 +18,25 @@ struct perf_cpu_map *perf_cpu_map__dummy_new(void) return cpus; } + +static void cpu_map__delete(struct perf_cpu_map *map) +{ + if (map) { + WARN_ONCE(refcount_read(&map->refcnt) != 0, + "cpu_map refcnt unbalanced\n"); + free(map); + } +} + +struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map) +{ + if (map) + refcount_inc(&map->refcnt); + return map; +} + +void perf_cpu_map__put(struct perf_cpu_map *map) +{ + if (map && refcount_dec_and_test(&map->refcnt)) + cpu_map__delete(map); +} diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h index fa1e5aa9d662..e16c2515a499 100644 --- a/tools/perf/lib/include/perf/cpumap.h +++ b/tools/perf/lib/include/perf/cpumap.h @@ -7,5 +7,7 @@ struct perf_cpu_map; LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); +LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); +LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); #endif /* __LIBPERF_CPUMAP_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 65201c6cbe7e..76ce3bc59dd8 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -2,6 +2,8 @@ LIBPERF_0.0.1 { global: libperf_set_print; perf_cpu_map__dummy_new; + perf_cpu_map__get; + perf_cpu_map__put; local: *; }; diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c index 74d0cd32a5c4..95304d29092e 100644 --- a/tools/perf/tests/bitmap.c +++ b/tools/perf/tests/bitmap.c @@ -21,7 +21,7 @@ static unsigned long *get_bitmap(const char *str, int nbits) } if (map) - cpu_map__put(map); + perf_cpu_map__put(map); return bm; } diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index ec4b0bf28270..ce2d3266286a 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -655,7 +655,7 @@ static int do_test_code_reading(bool try_kcore) * and will be freed by following perf_evlist__set_maps * call. Getting refference to keep them alive. */ - cpu_map__get(cpus); + perf_cpu_map__get(cpus); thread_map__get(threads); perf_evlist__set_maps(evlist, NULL, NULL); evlist__delete(evlist); @@ -705,7 +705,7 @@ static int do_test_code_reading(bool try_kcore) if (evlist) { evlist__delete(evlist); } else { - cpu_map__put(cpus); + perf_cpu_map__put(cpus); thread_map__put(threads); } machine__delete_threads(machine); diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 10da4400493d..6c921087b0fe 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -39,7 +39,7 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong cpu", map->map[i] == i); } - cpu_map__put(map); + perf_cpu_map__put(map); return 0; } @@ -68,7 +68,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1); TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256); TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1); - cpu_map__put(map); + perf_cpu_map__put(map); return 0; } @@ -83,7 +83,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL)); - cpu_map__put(cpus); + perf_cpu_map__put(cpus); /* This one is better stores in cpu values. */ cpus = cpu_map__new("1,256"); @@ -91,7 +91,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL)); - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return 0; } diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index bf00d3d792fb..dcfff4b20c92 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -132,7 +132,7 @@ static int attach__cpu_disabled(struct evlist *evlist) return err; } - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return evsel__enable(evsel); } @@ -154,7 +154,7 @@ static int attach__cpu_enabled(struct evlist *evlist) if (err == -EACCES) return TEST_SKIP; - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return err ? TEST_FAIL : TEST_OK; } diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index eb0dd359762d..415d12e96834 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -73,7 +73,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong cpus", map->map[0] == 1); TEST_ASSERT_VAL("wrong cpus", map->map[1] == 2); TEST_ASSERT_VAL("wrong cpus", map->map[2] == 3); - cpu_map__put(map); + perf_cpu_map__put(map); return 0; } @@ -113,6 +113,6 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu TEST_ASSERT_VAL("failed to synthesize attr update cpus", !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); - cpu_map__put(evsel->own_cpus); + perf_cpu_map__put(evsel->own_cpus); return 0; } diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 7bfc859971e5..43e55fe98f8c 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -149,7 +149,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evlist__disable(evlist); evlist__delete(evlist); } else { - cpu_map__put(cpus); + perf_cpu_map__put(cpus); thread_map__put(threads); } diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c index e12eedfba781..6fe2c1e7918b 100644 --- a/tools/perf/tests/mem2node.c +++ b/tools/perf/tests/mem2node.c @@ -32,7 +32,7 @@ static unsigned long *get_bitmap(const char *str, int nbits) } if (map) - cpu_map__put(map); + perf_cpu_map__put(map); else free(bm); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 40511025208f..d15282174b2e 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -155,7 +155,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse cpus = NULL; threads = NULL; out_free_cpus: - cpu_map__put(cpus); + perf_cpu_map__put(cpus); out_free_threads: thread_map__put(threads); return err; diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index f96cbd304024..611f6ea9b702 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -120,7 +120,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int out_evsel_delete: evsel__delete(evsel); out_cpu_map_delete: - cpu_map__put(cpus); + perf_cpu_map__put(cpus); out_thread_map_delete: thread_map__put(threads); return err; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index c6d3f4488b73..c464e301ade9 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -125,7 +125,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) } out_free_maps: - cpu_map__put(cpus); + perf_cpu_map__put(cpus); thread_map__put(threads); out_delete_evlist: evlist__delete(evlist); diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index d5537edb47db..27af7b7109a3 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -569,7 +569,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ evlist__disable(evlist); evlist__delete(evlist); } else { - cpu_map__put(cpus); + perf_cpu_map__put(cpus); thread_map__put(threads); } diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index c094fb8cc877..f026759a05d7 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -135,7 +135,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused } out_free_maps: - cpu_map__put(cpus); + perf_cpu_map__put(cpus); thread_map__put(threads); out_delete_evlist: evlist__delete(evlist); diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 443d0272ebbd..1b57ded58d59 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -133,7 +133,7 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe } ret = check_cpu_topology(path, map); - cpu_map__put(map); + perf_cpu_map__put(map); free_path: unlink(path); diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index acda9bfb4002..44082e5eabde 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -273,28 +273,6 @@ struct perf_cpu_map *cpu_map__empty_new(int nr) return cpus; } -static void cpu_map__delete(struct perf_cpu_map *map) -{ - if (map) { - WARN_ONCE(refcount_read(&map->refcnt) != 0, - "cpu_map refcnt unbalanced\n"); - free(map); - } -} - -struct perf_cpu_map *cpu_map__get(struct perf_cpu_map *map) -{ - if (map) - refcount_inc(&map->refcnt); - return map; -} - -void cpu_map__put(struct perf_cpu_map *map) -{ - if (map && refcount_dec_and_test(&map->refcnt)) - cpu_map__delete(map); -} - static int cpu__get_topology_int(int cpu, const char *name, int *value) { char path[PATH_MAX]; diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 0ce3f6bd9449..b7af2cb68c19 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -29,9 +29,6 @@ int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct perf_cpu_map **diep int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct perf_cpu_map **corep); const struct perf_cpu_map *cpu_map__online(void); /* thread unsafe */ -struct perf_cpu_map *cpu_map__get(struct perf_cpu_map *map); -void cpu_map__put(struct perf_cpu_map *map); - static inline int cpu_map__socket(struct perf_cpu_map *sock, int s) { if (!sock || s > sock->nr || s < 0) diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 157b0988435e..0cd99c460cd4 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -219,7 +219,7 @@ struct cpu_topology *cpu_topology__new(void) } out_free: - cpu_map__put(map); + perf_cpu_map__put(map); if (ret) { cpu_topology__delete(tp); tp = NULL; @@ -335,7 +335,7 @@ struct numa_topology *numa_topology__new(void) out: free(buf); fclose(fp); - cpu_map__put(node_map); + perf_cpu_map__put(node_map); return tp; } diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 9909ec40c6d2..d77912b2b5e7 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -179,7 +179,7 @@ void perf_env__exit(struct perf_env *env) zfree(&env->cpu); for (i = 0; i < env->nr_numa_nodes; i++) - cpu_map__put(env->numa_nodes[i].map); + perf_cpu_map__put(env->numa_nodes[i].map); zfree(&env->numa_nodes); for (i = 0; i < env->caches_cnt; i++) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f78837788b14..1a3db35f9f7d 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1403,7 +1403,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp) else ret += fprintf(fp, "failed to get cpumap from event\n"); - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return ret; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 461c1e68e9e7..35020d50f51e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -141,7 +141,7 @@ void evlist__delete(struct evlist *evlist) perf_evlist__munmap(evlist); evlist__close(evlist); - cpu_map__put(evlist->cpus); + perf_cpu_map__put(evlist->cpus); thread_map__put(evlist->threads); evlist->cpus = NULL; evlist->threads = NULL; @@ -158,11 +158,11 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, * keep it, if there's no target cpu list defined. */ if (!evsel->own_cpus || evlist->has_user_cpus) { - cpu_map__put(evsel->cpus); - evsel->cpus = cpu_map__get(evlist->cpus); + perf_cpu_map__put(evsel->cpus); + evsel->cpus = perf_cpu_map__get(evlist->cpus); } else if (evsel->cpus != evsel->own_cpus) { - cpu_map__put(evsel->cpus); - evsel->cpus = cpu_map__get(evsel->own_cpus); + perf_cpu_map__put(evsel->cpus); + evsel->cpus = perf_cpu_map__get(evsel->own_cpus); } thread_map__put(evsel->threads); @@ -1115,8 +1115,8 @@ void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, * the caller to increase the reference count. */ if (cpus != evlist->cpus) { - cpu_map__put(evlist->cpus); - evlist->cpus = cpu_map__get(cpus); + perf_cpu_map__put(evlist->cpus); + evlist->cpus = perf_cpu_map__get(cpus); } if (threads != evlist->threads) { @@ -1383,7 +1383,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) out: return err; out_put: - cpu_map__put(cpus); + perf_cpu_map__put(cpus); goto out; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a389752840a9..72c0e6948e83 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1325,8 +1325,8 @@ void perf_evsel__exit(struct evsel *evsel) perf_evsel__free_id(evsel); perf_evsel__free_config_terms(evsel); cgroup__put(evsel->cgrp); - cpu_map__put(evsel->cpus); - cpu_map__put(evsel->own_cpus); + perf_cpu_map__put(evsel->cpus); + perf_cpu_map__put(evsel->own_cpus); thread_map__put(evsel->threads); zfree(&evsel->group_name); zfree(&evsel->name); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index decb66d243ca..8c9928feb38a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -332,8 +332,8 @@ __add_event(struct list_head *list, int *idx, return NULL; (*idx)++; - evsel->cpus = cpu_map__get(cpus); - evsel->own_cpus = cpu_map__get(cpus); + evsel->cpus = perf_cpu_map__get(cpus); + evsel->own_cpus = perf_cpu_map__get(cpus); evsel->system_wide = pmu ? pmu->is_uncore : false; evsel->auto_merge_stats = auto_merge_stats; diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 4929a50c0973..d355f9506a1c 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -626,7 +626,7 @@ static bool pmu_is_uncore(const char *name) snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name); cpus = __pmu_cpumask(path); - cpu_map__put(cpus); + perf_cpu_map__put(cpus); return !!cpus; } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index cc4af99ab190..677c93f91c6c 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -557,7 +557,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) { - cpu_map__put(pcpus->cpus); + perf_cpu_map__put(pcpus->cpus); Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); } diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 9f8841548539..fecccfd71aa1 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -67,7 +67,7 @@ static bool perf_probe_api(setup_probe_fn_t fn) if (!cpus) return false; cpu = cpus->map[0]; - cpu_map__put(cpus); + perf_cpu_map__put(cpus); do { ret = perf_do_probe_api(fn, cpu, try[i++]); @@ -122,7 +122,7 @@ bool perf_can_record_cpu_wide(void) if (!cpus) return false; cpu = cpus->map[0]; - cpu_map__put(cpus); + perf_cpu_map__put(cpus); fd = sys_perf_event_open(&attr, -1, cpu, -1, 0); if (fd < 0) @@ -278,7 +278,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) struct perf_cpu_map *cpus = cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; - cpu_map__put(cpus); + perf_cpu_map__put(cpus); } else { cpu = evlist->cpus->map[0]; } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c191dc152175..62d37440cbee 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -2310,7 +2310,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, err = 0; out_delete_map: - cpu_map__put(map); + perf_cpu_map__put(map); return err; } diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 99132c6a30a6..a9ca5c4fffee 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -745,7 +745,7 @@ static int str_to_bitmap(char *s, cpumask_t *b) set_bit(c, cpumask_bits(b)); } - cpu_map__put(m); + perf_cpu_map__put(m); return ret; } -- GitLab From 07acd22677ac6bb2db404d1d258e8c7d06ca7706 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:18 +0200 Subject: [PATCH 1157/7155] libperf: Add perf_thread_map struct Add perf_thread_map struct to libperf. It's added as a declaration into into: include/perf/threadmap.h which will be included by users. The perf_thread_map struct definition is added into: include/internal/threadmap.h which is not to be included by users, but shared within perf and libperf. We tried the total separation of the perf_thread_map struct in libperf, but it lead to complications and much bigger changes in perf code, so we decided to share the declaration. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-32-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Build | 1 + tools/perf/lib/include/internal/threadmap.h | 21 +++++++++++++++++++++ tools/perf/lib/include/perf/threadmap.h | 7 +++++++ tools/perf/lib/threadmap.c | 5 +++++ tools/perf/util/thread_map.h | 13 +------------ 5 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 tools/perf/lib/include/internal/threadmap.h create mode 100644 tools/perf/lib/include/perf/threadmap.h create mode 100644 tools/perf/lib/threadmap.c diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index 195b274db49a..9beadfc81a71 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -1,2 +1,3 @@ libperf-y += core.o libperf-y += cpumap.o +libperf-y += threadmap.o diff --git a/tools/perf/lib/include/internal/threadmap.h b/tools/perf/lib/include/internal/threadmap.h new file mode 100644 index 000000000000..c8088005a9ab --- /dev/null +++ b/tools/perf/lib/include/internal/threadmap.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_THREADMAP_H +#define __LIBPERF_INTERNAL_THREADMAP_H + +#include +#include +#include + +struct thread_map_data { + pid_t pid; + char *comm; +}; + +struct perf_thread_map { + refcount_t refcnt; + int nr; + int err_thread; + struct thread_map_data map[]; +}; + +#endif /* __LIBPERF_INTERNAL_THREADMAP_H */ diff --git a/tools/perf/lib/include/perf/threadmap.h b/tools/perf/lib/include/perf/threadmap.h new file mode 100644 index 000000000000..dc3a3837b56f --- /dev/null +++ b/tools/perf/lib/include/perf/threadmap.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_THREADMAP_H +#define __LIBPERF_THREADMAP_H + +struct perf_thread_map; + +#endif /* __LIBPERF_THREADMAP_H */ diff --git a/tools/perf/lib/threadmap.c b/tools/perf/lib/threadmap.c new file mode 100644 index 000000000000..163dc609b909 --- /dev/null +++ b/tools/perf/lib/threadmap.c @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 9358b1b6e657..5a7be6f8934f 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -5,18 +5,7 @@ #include #include #include - -struct thread_map_data { - pid_t pid; - char *comm; -}; - -struct perf_thread_map { - refcount_t refcnt; - int nr; - int err_thread; - struct thread_map_data map[]; -}; +#include struct thread_map_event; -- GitLab From 4b49cce25e719587e934b745fe9bbb5bc8c4ba29 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:19 +0200 Subject: [PATCH 1158/7155] libperf: Add perf_thread_map__new_dummy() function Moving the following functions: thread_map__new_dummy() thread_map__realloc() thread_map__set_pid() to libperf with the following names: perf_thread_map__new_dummy() perf_thread_map__realloc() perf_thread_map__set_pid() the other 2 functions are dependencies of the perf_thread_map__new_dummy() function. The perf_thread_map__realloc() function is not exported. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-33-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/internal/threadmap.h | 2 + tools/perf/lib/include/perf/threadmap.h | 7 +++ tools/perf/lib/libperf.map | 2 + tools/perf/lib/threadmap.c | 43 +++++++++++++++ tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/thread-map.c | 2 +- tools/perf/util/evlist.c | 4 +- tools/perf/util/thread_map.c | 59 +++++---------------- tools/perf/util/thread_map.h | 7 +-- 9 files changed, 71 insertions(+), 57 deletions(-) diff --git a/tools/perf/lib/include/internal/threadmap.h b/tools/perf/lib/include/internal/threadmap.h index c8088005a9ab..df748baf9eda 100644 --- a/tools/perf/lib/include/internal/threadmap.h +++ b/tools/perf/lib/include/internal/threadmap.h @@ -18,4 +18,6 @@ struct perf_thread_map { struct thread_map_data map[]; }; +struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr); + #endif /* __LIBPERF_INTERNAL_THREADMAP_H */ diff --git a/tools/perf/lib/include/perf/threadmap.h b/tools/perf/lib/include/perf/threadmap.h index dc3a3837b56f..34ed7f587101 100644 --- a/tools/perf/lib/include/perf/threadmap.h +++ b/tools/perf/lib/include/perf/threadmap.h @@ -2,6 +2,13 @@ #ifndef __LIBPERF_THREADMAP_H #define __LIBPERF_THREADMAP_H +#include +#include + struct perf_thread_map; +LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void); + +LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid); + #endif /* __LIBPERF_THREADMAP_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 76ce3bc59dd8..6b4ec1c4d3f3 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -4,6 +4,8 @@ LIBPERF_0.0.1 { perf_cpu_map__dummy_new; perf_cpu_map__get; perf_cpu_map__put; + perf_thread_map__new_dummy; + perf_thread_map__set_pid; local: *; }; diff --git a/tools/perf/lib/threadmap.c b/tools/perf/lib/threadmap.c index 163dc609b909..23e628a1437a 100644 --- a/tools/perf/lib/threadmap.c +++ b/tools/perf/lib/threadmap.c @@ -3,3 +3,46 @@ #include #include #include +#include + +static void perf_thread_map__reset(struct perf_thread_map *map, int start, int nr) +{ + size_t size = (nr - start) * sizeof(map->map[0]); + + memset(&map->map[start], 0, size); + map->err_thread = -1; +} + +struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr) +{ + size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; + int start = map ? map->nr : 0; + + map = realloc(map, size); + /* + * We only realloc to add more items, let's reset new items. + */ + if (map) + perf_thread_map__reset(map, start, nr); + + return map; +} + +#define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr) + +void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid) +{ + map->map[thread].pid = pid; +} + +struct perf_thread_map *perf_thread_map__new_dummy(void) +{ + struct perf_thread_map *threads = thread_map__alloc(1); + + if (threads != NULL) { + perf_thread_map__set_pid(threads, 0, -1); + threads->nr = 1; + refcount_set(&threads->refcnt, 1); + } + return threads; +} diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index c7182b7840e5..1de79208e690 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -58,7 +58,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest perf_evsel__config(evsel, &opts, NULL); - thread_map__set_pid(evlist->threads, 0, getpid()); + perf_thread_map__set_pid(evlist->threads, 0, getpid()); err = evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c index 367dfe708e4c..73bc404ed390 100644 --- a/tools/perf/tests/thread-map.c +++ b/tools/perf/tests/thread-map.c @@ -35,7 +35,7 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse thread_map__put(map); /* test dummy pid */ - map = thread_map__new_dummy(); + map = perf_thread_map__new_dummy(); TEST_ASSERT_VAL("failed to alloc map", map); thread_map__read_comms(map); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 35020d50f51e..88d131769df4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1375,7 +1375,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) if (!cpus) goto out; - threads = thread_map__new_dummy(); + threads = perf_thread_map__new_dummy(); if (!threads) goto out_put; @@ -1504,7 +1504,7 @@ int perf_evlist__prepare_workload(struct evlist *evlist, struct target *target, __func__, __LINE__); goto out_close_pipes; } - thread_map__set_pid(evlist->threads, 0, evlist->workload.pid); + perf_thread_map__set_pid(evlist->threads, 0, evlist->workload.pid); } close(child_ready_pipe[1]); diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index e89496c39d58..06dd9f2e4ce5 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -28,30 +28,7 @@ static int filter(const struct dirent *dir) return 1; } -static void thread_map__reset(struct perf_thread_map *map, int start, int nr) -{ - size_t size = (nr - start) * sizeof(map->map[0]); - - memset(&map->map[start], 0, size); - map->err_thread = -1; -} - -static struct perf_thread_map *thread_map__realloc(struct perf_thread_map *map, int nr) -{ - size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; - int start = map ? map->nr : 0; - - map = realloc(map, size); - /* - * We only realloc to add more items, let's reset new items. - */ - if (map) - thread_map__reset(map, start, nr); - - return map; -} - -#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr) +#define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr) struct perf_thread_map *thread_map__new_by_pid(pid_t pid) { @@ -69,7 +46,7 @@ struct perf_thread_map *thread_map__new_by_pid(pid_t pid) threads = thread_map__alloc(items); if (threads != NULL) { for (i = 0; i < items; i++) - thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); + perf_thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); threads->nr = items; refcount_set(&threads->refcnt, 1); } @@ -86,7 +63,7 @@ struct perf_thread_map *thread_map__new_by_tid(pid_t tid) struct perf_thread_map *threads = thread_map__alloc(1); if (threads != NULL) { - thread_map__set_pid(threads, 0, tid); + perf_thread_map__set_pid(threads, 0, tid); threads->nr = 1; refcount_set(&threads->refcnt, 1); } @@ -142,7 +119,7 @@ static struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid) if (grow) { struct perf_thread_map *tmp; - tmp = thread_map__realloc(threads, max_threads); + tmp = perf_thread_map__realloc(threads, max_threads); if (tmp == NULL) goto out_free_namelist; @@ -150,8 +127,8 @@ static struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid) } for (i = 0; i < items; i++) { - thread_map__set_pid(threads, threads->nr + i, - atoi(namelist[i]->d_name)); + perf_thread_map__set_pid(threads, threads->nr + i, + atoi(namelist[i]->d_name)); } for (i = 0; i < items; i++) @@ -233,14 +210,14 @@ static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str) goto out_free_threads; total_tasks += items; - nt = thread_map__realloc(threads, total_tasks); + nt = perf_thread_map__realloc(threads, total_tasks); if (nt == NULL) goto out_free_namelist; threads = nt; for (i = 0; i < items; i++) { - thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); + perf_thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); zfree(&namelist[i]); } threads->nr = total_tasks; @@ -263,18 +240,6 @@ static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str) goto out; } -struct perf_thread_map *thread_map__new_dummy(void) -{ - struct perf_thread_map *threads = thread_map__alloc(1); - - if (threads != NULL) { - thread_map__set_pid(threads, 0, -1); - threads->nr = 1; - refcount_set(&threads->refcnt, 1); - } - return threads; -} - struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) { struct perf_thread_map *threads = NULL, *nt; @@ -287,7 +252,7 @@ struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) /* perf-stat expects threads to be generated even if tid not given */ if (!tid_str) - return thread_map__new_dummy(); + return perf_thread_map__new_dummy(); slist = strlist__new(tid_str, &slist_config); if (!slist) @@ -304,13 +269,13 @@ struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) continue; ntasks++; - nt = thread_map__realloc(threads, ntasks); + nt = perf_thread_map__realloc(threads, ntasks); if (nt == NULL) goto out_free_threads; threads = nt; - thread_map__set_pid(threads, ntasks - 1, tid); + perf_thread_map__set_pid(threads, ntasks - 1, tid); threads->nr = ntasks; } out: @@ -437,7 +402,7 @@ static void thread_map__copy_event(struct perf_thread_map *threads, threads->nr = (int) event->nr; for (i = 0; i < event->nr; i++) { - thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid); + perf_thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid); threads->map[i].comm = strndup(event->entries[i].comm, 16); } diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 5a7be6f8934f..94a1f9565f5e 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -6,6 +6,7 @@ #include #include #include +#include struct thread_map_event; @@ -37,12 +38,6 @@ static inline pid_t thread_map__pid(struct perf_thread_map *map, int thread) return map->map[thread].pid; } -static inline void -thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid) -{ - map->map[thread].pid = pid; -} - static inline char *thread_map__comm(struct perf_thread_map *map, int thread) { return map->map[thread].comm; -- GitLab From 7836e52e518b5e3fd695850f1d4081f756f58406 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:20 +0200 Subject: [PATCH 1159/7155] libperf: Add perf_thread_map__get()/perf_thread_map__put() Move the following functions: thread_map__get() thread_map__put() thread_map__comm() to libperf with the following names: perf_thread_map__get() perf_thread_map__put() perf_thread_map__comm() Add the perf_thread_map__comm() function for it to work/compile. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-34-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/lib/include/perf/threadmap.h | 4 +++ tools/perf/lib/libperf.map | 3 ++ tools/perf/lib/threadmap.c | 33 ++++++++++++++++++++++ tools/perf/tests/code-reading.c | 4 +-- tools/perf/tests/event-times.c | 4 +-- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/mmap-thread-lookup.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/tests/thread-map.c | 18 ++++++------ tools/perf/util/event.c | 4 +-- tools/perf/util/evlist.c | 12 ++++---- tools/perf/util/evsel.c | 2 +- tools/perf/util/parse-events.c | 2 +- tools/perf/util/python.c | 2 +- tools/perf/util/stat-display.c | 2 +- tools/perf/util/thread_map.c | 26 ----------------- tools/perf/util/thread_map.h | 8 ------ 23 files changed, 74 insertions(+), 68 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index c0962ddfad04..03fbe4600ca0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1060,7 +1060,7 @@ static int record__synthesize_workload(struct record *rec, bool tail) process_synthesized_event, &rec->session->machines.host, rec->opts.sample_address); - thread_map__put(thread_map); + perf_thread_map__put(thread_map); return err; } diff --git a/tools/perf/lib/include/perf/threadmap.h b/tools/perf/lib/include/perf/threadmap.h index 34ed7f587101..456295273daa 100644 --- a/tools/perf/lib/include/perf/threadmap.h +++ b/tools/perf/lib/include/perf/threadmap.h @@ -10,5 +10,9 @@ struct perf_thread_map; LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void); LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid); +LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread); + +LIBPERF_API struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map); +LIBPERF_API void perf_thread_map__put(struct perf_thread_map *map); #endif /* __LIBPERF_THREADMAP_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 6b4ec1c4d3f3..c4f611010ccc 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -6,6 +6,9 @@ LIBPERF_0.0.1 { perf_cpu_map__put; perf_thread_map__new_dummy; perf_thread_map__set_pid; + perf_thread_map__comm; + perf_thread_map__get; + perf_thread_map__put; local: *; }; diff --git a/tools/perf/lib/threadmap.c b/tools/perf/lib/threadmap.c index 23e628a1437a..4865b73e2586 100644 --- a/tools/perf/lib/threadmap.c +++ b/tools/perf/lib/threadmap.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include static void perf_thread_map__reset(struct perf_thread_map *map, int start, int nr) { @@ -35,6 +37,11 @@ void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid map->map[thread].pid = pid; } +char *perf_thread_map__comm(struct perf_thread_map *map, int thread) +{ + return map->map[thread].comm; +} + struct perf_thread_map *perf_thread_map__new_dummy(void) { struct perf_thread_map *threads = thread_map__alloc(1); @@ -46,3 +53,29 @@ struct perf_thread_map *perf_thread_map__new_dummy(void) } return threads; } + +static void perf_thread_map__delete(struct perf_thread_map *threads) +{ + if (threads) { + int i; + + WARN_ONCE(refcount_read(&threads->refcnt) != 0, + "thread map refcnt unbalanced\n"); + for (i = 0; i < threads->nr; i++) + free(perf_thread_map__comm(threads, i)); + free(threads); + } +} + +struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map) +{ + if (map) + refcount_inc(&map->refcnt); + return map; +} + +void perf_thread_map__put(struct perf_thread_map *map) +{ + if (map && refcount_dec_and_test(&map->refcnt)) + perf_thread_map__delete(map); +} diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index ce2d3266286a..7b26be1dfb47 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -656,7 +656,7 @@ static int do_test_code_reading(bool try_kcore) * call. Getting refference to keep them alive. */ perf_cpu_map__get(cpus); - thread_map__get(threads); + perf_thread_map__get(threads); perf_evlist__set_maps(evlist, NULL, NULL); evlist__delete(evlist); evlist = NULL; @@ -706,7 +706,7 @@ static int do_test_code_reading(bool try_kcore) evlist__delete(evlist); } else { perf_cpu_map__put(cpus); - thread_map__put(threads); + perf_thread_map__put(threads); } machine__delete_threads(machine); machine__delete(machine); diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index dcfff4b20c92..9238180416b0 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -76,7 +76,7 @@ static int attach__current_disabled(struct evlist *evlist) return err; } - thread_map__put(threads); + perf_thread_map__put(threads); return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; } @@ -96,7 +96,7 @@ static int attach__current_enabled(struct evlist *evlist) err = perf_evsel__open_per_thread(evsel, threads); - thread_map__put(threads); + perf_thread_map__put(threads); return err == 0 ? TEST_OK : TEST_FAIL; } diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 43e55fe98f8c..830fb3d7ea2e 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -150,7 +150,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evlist__delete(evlist); } else { perf_cpu_map__put(cpus); - thread_map__put(threads); + perf_thread_map__put(threads); } return err; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index d15282174b2e..72fbf55f4fc3 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -157,6 +157,6 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse out_free_cpus: perf_cpu_map__put(cpus); out_free_threads: - thread_map__put(threads); + perf_thread_map__put(threads); return err; } diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index ad6ca943e568..360d70deb855 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -147,7 +147,7 @@ static int synth_process(struct machine *machine) perf_event__process, machine, 0); - thread_map__put(map); + perf_thread_map__put(map); return err; } diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 611f6ea9b702..674b0fa035ec 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -122,6 +122,6 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int out_cpu_map_delete: perf_cpu_map__put(cpus); out_thread_map_delete: - thread_map__put(threads); + perf_thread_map__put(threads); return err; } diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 20e353fbfdd0..87c212545767 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -61,6 +61,6 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __m out_evsel_delete: evsel__delete(evsel); out_thread_map_delete: - thread_map__put(threads); + perf_thread_map__put(threads); return err; } diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index c464e301ade9..2decda2d4c17 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -126,7 +126,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) out_free_maps: perf_cpu_map__put(cpus); - thread_map__put(threads); + perf_thread_map__put(threads); out_delete_evlist: evlist__delete(evlist); return err; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 27af7b7109a3..0935a5a1ecaa 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -570,7 +570,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ evlist__delete(evlist); } else { perf_cpu_map__put(cpus); - thread_map__put(threads); + perf_thread_map__put(threads); } return err; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index f026759a05d7..24257285844b 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -136,7 +136,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused out_free_maps: perf_cpu_map__put(cpus); - thread_map__put(threads); + perf_thread_map__put(threads); out_delete_evlist: evlist__delete(evlist); return err; diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c index 73bc404ed390..d61773cacf0b 100644 --- a/tools/perf/tests/thread-map.c +++ b/tools/perf/tests/thread-map.c @@ -28,11 +28,11 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", - thread_map__comm(map, 0) && - !strcmp(thread_map__comm(map, 0), NAME)); + perf_thread_map__comm(map, 0) && + !strcmp(perf_thread_map__comm(map, 0), NAME)); TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1); - thread_map__put(map); + perf_thread_map__put(map); /* test dummy pid */ map = perf_thread_map__new_dummy(); @@ -43,11 +43,11 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1); TEST_ASSERT_VAL("wrong comm", - thread_map__comm(map, 0) && - !strcmp(thread_map__comm(map, 0), "dummy")); + perf_thread_map__comm(map, 0) && + !strcmp(perf_thread_map__comm(map, 0), "dummy")); TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1); - thread_map__put(map); + perf_thread_map__put(map); return 0; } @@ -70,11 +70,11 @@ static int process_event(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong pid", thread_map__pid(threads, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", - thread_map__comm(threads, 0) && - !strcmp(thread_map__comm(threads, 0), NAME)); + perf_thread_map__comm(threads, 0) && + !strcmp(perf_thread_map__comm(threads, 0), NAME)); TEST_ASSERT_VAL("wrong refcnt", refcount_read(&threads->refcnt) == 1); - thread_map__put(threads); + perf_thread_map__put(threads); return 0; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 1a3db35f9f7d..f440fdc3e953 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -992,7 +992,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, for (i = 0; i < threads->nr; i++) { struct thread_map_event_entry *entry = &event->thread_map.entries[i]; - char *comm = thread_map__comm(threads, i); + char *comm = perf_thread_map__comm(threads, i); if (!comm) comm = (char *) ""; @@ -1387,7 +1387,7 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp) else ret += fprintf(fp, "failed to get threads from event\n"); - thread_map__put(threads); + perf_thread_map__put(threads); return ret; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 88d131769df4..38a3c6d16b4b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -142,7 +142,7 @@ void evlist__delete(struct evlist *evlist) perf_evlist__munmap(evlist); evlist__close(evlist); perf_cpu_map__put(evlist->cpus); - thread_map__put(evlist->threads); + perf_thread_map__put(evlist->threads); evlist->cpus = NULL; evlist->threads = NULL; perf_evlist__purge(evlist); @@ -165,8 +165,8 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, evsel->cpus = perf_cpu_map__get(evsel->own_cpus); } - thread_map__put(evsel->threads); - evsel->threads = thread_map__get(evlist->threads); + perf_thread_map__put(evsel->threads); + evsel->threads = perf_thread_map__get(evlist->threads); } static void perf_evlist__propagate_maps(struct evlist *evlist) @@ -1100,7 +1100,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) return 0; out_delete_threads: - thread_map__put(threads); + perf_thread_map__put(threads); return -1; } @@ -1120,8 +1120,8 @@ void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, } if (threads != evlist->threads) { - thread_map__put(evlist->threads); - evlist->threads = thread_map__get(threads); + perf_thread_map__put(evlist->threads); + evlist->threads = perf_thread_map__get(threads); } perf_evlist__propagate_maps(evlist); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 72c0e6948e83..652e53279b28 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1327,7 +1327,7 @@ void perf_evsel__exit(struct evsel *evsel) cgroup__put(evsel->cgrp); perf_cpu_map__put(evsel->cpus); perf_cpu_map__put(evsel->own_cpus); - thread_map__put(evsel->threads); + perf_thread_map__put(evsel->threads); zfree(&evsel->group_name); zfree(&evsel->name); perf_evsel__object.fini(evsel); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 8c9928feb38a..38eeca6fa1fc 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2337,7 +2337,7 @@ static bool is_event_supported(u8 type, unsigned config) evsel__delete(evsel); } - thread_map__put(tmap); + perf_thread_map__put(tmap); return ret; } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 677c93f91c6c..19d2feee91d5 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -626,7 +626,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) { - thread_map__put(pthreads->threads); + perf_thread_map__put(pthreads->threads); Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index f7666d2e6e0c..1f099823a1f9 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -116,7 +116,7 @@ static void aggr_printout(struct perf_stat_config *config, case AGGR_THREAD: fprintf(config->output, "%*s-%*d%s", config->csv_output ? 0 : 16, - thread_map__comm(evsel->threads, id), + perf_thread_map__comm(evsel->threads, id), config->csv_output ? 0 : -8, thread_map__pid(evsel->threads, id), config->csv_sep); diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 06dd9f2e4ce5..c58385ea05be 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -304,32 +304,6 @@ struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, return thread_map__new_by_tid_str(tid); } -static void thread_map__delete(struct perf_thread_map *threads) -{ - if (threads) { - int i; - - WARN_ONCE(refcount_read(&threads->refcnt) != 0, - "thread map refcnt unbalanced\n"); - for (i = 0; i < threads->nr; i++) - free(thread_map__comm(threads, i)); - free(threads); - } -} - -struct perf_thread_map *thread_map__get(struct perf_thread_map *map) -{ - if (map) - refcount_inc(&map->refcnt); - return map; -} - -void thread_map__put(struct perf_thread_map *map) -{ - if (map && refcount_dec_and_test(&map->refcnt)) - thread_map__delete(map); -} - size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp) { int i; diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 94a1f9565f5e..ba45c760be72 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -18,9 +18,6 @@ struct perf_thread_map *thread_map__new_all_cpus(void); struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); struct perf_thread_map *thread_map__new_event(struct thread_map_event *event); -struct perf_thread_map *thread_map__get(struct perf_thread_map *map); -void thread_map__put(struct perf_thread_map *map); - struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid, bool all_threads); @@ -38,11 +35,6 @@ static inline pid_t thread_map__pid(struct perf_thread_map *map, int thread) return map->map[thread].pid; } -static inline char *thread_map__comm(struct perf_thread_map *map, int thread) -{ - return map->map[thread].comm; -} - void thread_map__read_comms(struct perf_thread_map *threads); bool thread_map__has(struct perf_thread_map *threads, pid_t pid); int thread_map__remove(struct perf_thread_map *threads, int idx); -- GitLab From 285a30c36d1e18e7e2afa24dae50ba5596be45e7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:21 +0200 Subject: [PATCH 1160/7155] libperf: Add perf_evlist and perf_evsel structs Add the perf_evlist and perf_evsel structs to libperf. It's added as a declarations into: include/perf/evlist.h include/perf/evsel.h which will be included by users. The definitions are added into: include/internal/evlist.h include/internal/evsel.h which is not to be included by users, but shared within perf and libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-35-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Build | 2 ++ tools/perf/lib/evlist.c | 4 ++++ tools/perf/lib/evsel.c | 4 ++++ tools/perf/lib/include/internal/evlist.h | 9 +++++++++ tools/perf/lib/include/internal/evsel.h | 9 +++++++++ tools/perf/lib/include/perf/evlist.h | 7 +++++++ tools/perf/lib/include/perf/evsel.h | 7 +++++++ 7 files changed, 42 insertions(+) create mode 100644 tools/perf/lib/evlist.c create mode 100644 tools/perf/lib/evsel.c create mode 100644 tools/perf/lib/include/internal/evlist.h create mode 100644 tools/perf/lib/include/internal/evsel.h create mode 100644 tools/perf/lib/include/perf/evlist.h create mode 100644 tools/perf/lib/include/perf/evsel.h diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index 9beadfc81a71..b27c1543b046 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -1,3 +1,5 @@ libperf-y += core.o libperf-y += cpumap.o libperf-y += threadmap.o +libperf-y += evsel.o +libperf-y += evlist.o diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c new file mode 100644 index 000000000000..646bdd518793 --- /dev/null +++ b/tools/perf/lib/evlist.c @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c new file mode 100644 index 000000000000..12e86de1994b --- /dev/null +++ b/tools/perf/lib/evsel.c @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h new file mode 100644 index 000000000000..7fbfe5716652 --- /dev/null +++ b/tools/perf/lib/include/internal/evlist.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_EVLIST_H +#define __LIBPERF_INTERNAL_EVLIST_H + +struct perf_evlist { + struct list_head entries; +}; + +#endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h new file mode 100644 index 000000000000..690943d0408a --- /dev/null +++ b/tools/perf/lib/include/internal/evsel.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_EVSEL_H +#define __LIBPERF_INTERNAL_EVSEL_H + +struct perf_evsel { + struct list_head node; +}; + +#endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h new file mode 100644 index 000000000000..92b0eb39caec --- /dev/null +++ b/tools/perf/lib/include/perf/evlist.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_EVLIST_H +#define __LIBPERF_EVLIST_H + +struct perf_evlist; + +#endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h new file mode 100644 index 000000000000..162bffd43409 --- /dev/null +++ b/tools/perf/lib/include/perf/evsel.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_EVSEL_H +#define __LIBPERF_EVSEL_H + +struct perf_evsel; + +#endif /* __LIBPERF_EVSEL_H */ -- GitLab From b27c4ece725a7f2225f76ad05dc6f3f5463fe893 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:22 +0200 Subject: [PATCH 1161/7155] libperf: Include perf_evsel in evsel object Including perf_evsel in evsel object, will continue to move other generic things into libperf's perf_evsel struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-36-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/ui/browsers/hists.c | 8 ++++---- tools/perf/util/evlist.c | 16 ++++++++-------- tools/perf/util/evlist.h | 12 ++++++------ tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 16 ++++++++-------- tools/perf/util/parse-events.c | 20 ++++++++++---------- tools/perf/util/stat-display.c | 4 ++-- tools/perf/util/trace-event-info.c | 4 ++-- 10 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c02ecb295f23..70247f1b23da 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2929,7 +2929,7 @@ static int timehist_check_attr(struct perf_sched *sched, struct evsel *evsel; struct evsel_runtime *er; - list_for_each_entry(evsel, &evlist->entries, node) { + list_for_each_entry(evsel, &evlist->entries, core.node) { er = perf_evsel__get_runtime(evsel); if (er == NULL) { pr_err("Failed to allocate memory for evsel runtime data\n"); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 51d142594a12..29dbf99f6081 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2636,7 +2636,7 @@ static bool evlist__add_vfs_getname(struct evlist *evlist) continue; } - list_del_init(&evsel->node); + list_del_init(&evsel->core.node); evsel->evlist = NULL; evsel__delete(evsel); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index b83258bece05..280347499c50 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -3212,7 +3212,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser, { struct evsel_menu *menu = container_of(browser, struct evsel_menu, b); - struct evsel *evsel = list_entry(entry, struct evsel, node); + struct evsel *evsel = list_entry(entry, struct evsel, core.node); struct hists *hists = evsel__hists(evsel); bool current_entry = ui_browser__is_current_entry(browser, row); unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE]; @@ -3309,13 +3309,13 @@ static int perf_evsel_menu__run(struct evsel_menu *menu, ui_browser__show_title(&menu->b, title); switch (key) { case K_TAB: - if (pos->node.next == &evlist->entries) + if (pos->core.node.next == &evlist->entries) pos = perf_evlist__first(evlist); else pos = perf_evsel__next(pos); goto browse_hists; case K_UNTAB: - if (pos->node.prev == &evlist->entries) + if (pos->core.node.prev == &evlist->entries) pos = perf_evlist__last(evlist); else pos = perf_evsel__prev(pos); @@ -3351,7 +3351,7 @@ static int perf_evsel_menu__run(struct evsel_menu *menu, static bool filter_group_entries(struct ui_browser *browser __maybe_unused, void *entry) { - struct evsel *evsel = list_entry(entry, struct evsel, node); + struct evsel *evsel = list_entry(entry, struct evsel, core.node); if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel)) return true; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 38a3c6d16b4b..227576bf16c0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -119,7 +119,7 @@ static void perf_evlist__purge(struct evlist *evlist) struct evsel *pos, *n; evlist__for_each_entry_safe(evlist, n, pos) { - list_del_init(&pos->node); + list_del_init(&pos->core.node); pos->evlist = NULL; evsel__delete(pos); } @@ -180,7 +180,7 @@ static void perf_evlist__propagate_maps(struct evlist *evlist) void evlist__add(struct evlist *evlist, struct evsel *entry) { entry->evlist = evlist; - list_add_tail(&entry->node, &evlist->entries); + list_add_tail(&entry->core.node, &evlist->entries); entry->idx = evlist->nr_entries; entry->tracking = !entry->idx; @@ -193,7 +193,7 @@ void evlist__add(struct evlist *evlist, struct evsel *entry) void evlist__remove(struct evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; - list_del_init(&evsel->node); + list_del_init(&evsel->core.node); evlist->nr_entries -= 1; } @@ -203,7 +203,7 @@ void perf_evlist__splice_list_tail(struct evlist *evlist, struct evsel *evsel, *temp; __evlist__for_each_entry_safe(list, temp, evsel) { - list_del_init(&evsel->node); + list_del_init(&evsel->core.node); evlist__add(evlist, evsel); } } @@ -212,8 +212,8 @@ void __perf_evlist__set_leader(struct list_head *list) { struct evsel *evsel, *leader; - leader = list_entry(list->next, struct evsel, node); - evsel = list_entry(list->prev, struct evsel, node); + leader = list_entry(list->next, struct evsel, core.node); + evsel = list_entry(list->prev, struct evsel, core.node); leader->nr_members = evsel->idx - leader->idx + 1; @@ -268,7 +268,7 @@ static int evlist__add_attrs(struct evlist *evlist, evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); if (evsel == NULL) goto out_delete_partial_list; - list_add_tail(&evsel->node, &head); + list_add_tail(&evsel->core.node, &head); } perf_evlist__splice_list_tail(evlist, &head); @@ -1680,7 +1680,7 @@ void perf_evlist__to_front(struct evlist *evlist, evlist__for_each_entry_safe(evlist, n, evsel) { if (evsel->leader == move_evsel->leader) - list_move_tail(&evsel->node, &move); + list_move_tail(&evsel->core.node, &move); } list_splice(&move, &evlist->entries); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 99621c056d09..1315e64ad69e 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -230,12 +230,12 @@ static inline bool perf_evlist__empty(struct evlist *evlist) static inline struct evsel *perf_evlist__first(struct evlist *evlist) { - return list_entry(evlist->entries.next, struct evsel, node); + return list_entry(evlist->entries.next, struct evsel, core.node); } static inline struct evsel *perf_evlist__last(struct evlist *evlist) { - return list_entry(evlist->entries.prev, struct evsel, node); + return list_entry(evlist->entries.prev, struct evsel, core.node); } size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp); @@ -253,7 +253,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define __evlist__for_each_entry(list, evsel) \ - list_for_each_entry(evsel, list, node) + list_for_each_entry(evsel, list, core.node) /** * evlist__for_each_entry - iterate thru all the evsels @@ -269,7 +269,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define __evlist__for_each_entry_continue(list, evsel) \ - list_for_each_entry_continue(evsel, list, node) + list_for_each_entry_continue(evsel, list, core.node) /** * evlist__for_each_entry_continue - continue iteration thru all the evsels @@ -285,7 +285,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define __evlist__for_each_entry_reverse(list, evsel) \ - list_for_each_entry_reverse(evsel, list, node) + list_for_each_entry_reverse(evsel, list, core.node) /** * evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order @@ -302,7 +302,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define __evlist__for_each_entry_safe(list, tmp, evsel) \ - list_for_each_entry_safe(evsel, tmp, list, node) + list_for_each_entry_safe(evsel, tmp, list, core.node) /** * evlist__for_each_entry_safe - safely iterate thru all the evsels diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 652e53279b28..8fed22d889a4 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -236,7 +236,7 @@ void evsel__init(struct evsel *evsel, evsel->evlist = NULL; evsel->bpf_obj = NULL; evsel->bpf_fd = -1; - INIT_LIST_HEAD(&evsel->node); + INIT_LIST_HEAD(&evsel->core.node); INIT_LIST_HEAD(&evsel->config_terms); perf_evsel__object.init(evsel); evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); @@ -1318,7 +1318,7 @@ void perf_evsel__close_fd(struct evsel *evsel) void perf_evsel__exit(struct evsel *evsel) { - assert(list_empty(&evsel->node)); + assert(list_empty(&evsel->core.node)); assert(evsel->evlist == NULL); perf_evsel__free_counts(evsel); perf_evsel__free_fd(evsel); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 5fec1ca64f58..d74cac6fe306 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "xyarray.h" #include "symbol_conf.h" #include "cpumap.h" @@ -87,8 +88,7 @@ struct bpf_object; /** struct evsel - event selector * * @evlist - evlist this evsel is in, if it is in one. - * @node - To insert it into evlist->entries or in other list_heads, say in - * the event parsing routines. + * @core - libperf evsel object * @name - Can be set to retain the original event name passed by the user, * so that when showing results in tools such as 'perf stat', we * show the name used, not some alias. @@ -101,7 +101,7 @@ struct bpf_object; * @priv: And what is in its containing unnamed union are tool specific */ struct evsel { - struct list_head node; + struct perf_evsel core; struct evlist *evlist; struct perf_event_attr attr; char *filter; @@ -386,12 +386,12 @@ int perf_evsel__parse_sample_timestamp(struct evsel *evsel, static inline struct evsel *perf_evsel__next(struct evsel *evsel) { - return list_entry(evsel->node.next, struct evsel, node); + return list_entry(evsel->core.node.next, struct evsel, core.node); } static inline struct evsel *perf_evsel__prev(struct evsel *evsel) { - return list_entry(evsel->node.prev, struct evsel, node); + return list_entry(evsel->core.node.prev, struct evsel, core.node); } /** @@ -478,15 +478,15 @@ static inline int perf_evsel__group_idx(struct evsel *evsel) /* Iterates group WITHOUT the leader. */ #define for_each_group_member(_evsel, _leader) \ -for ((_evsel) = list_entry((_leader)->node.next, struct evsel, node); \ +for ((_evsel) = list_entry((_leader)->core.node.next, struct evsel, core.node); \ (_evsel) && (_evsel)->leader == (_leader); \ - (_evsel) = list_entry((_evsel)->node.next, struct evsel, node)) + (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) /* Iterates group WITH the leader. */ #define for_each_group_evsel(_evsel, _leader) \ for ((_evsel) = _leader; \ (_evsel) && (_evsel)->leader == (_leader); \ - (_evsel) = list_entry((_evsel)->node.next, struct evsel, node)) + (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) static inline bool perf_evsel__has_branch_callstack(const struct evsel *evsel) { diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 38eeca6fa1fc..e111c0e0a5ac 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -343,7 +343,7 @@ __add_event(struct list_head *list, int *idx, if (config_terms) list_splice(config_terms, &evsel->config_terms); - list_add_tail(&evsel->node, list); + list_add_tail(&evsel->core.node, list); return evsel; } @@ -526,7 +526,7 @@ static int add_tracepoint(struct list_head *list, int *idx, list_splice(&config_terms, &evsel->config_terms); } - list_add_tail(&evsel->node, list); + list_add_tail(&evsel->core.node, list); return 0; } @@ -660,15 +660,15 @@ static int add_bpf_event(const char *group, const char *event, int fd, struct bp pr_debug("Failed to add BPF event %s:%s\n", group, event); - list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { - list_del_init(&evsel->node); + list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) { + list_del_init(&evsel->core.node); evsel__delete(evsel); } return err; } pr_debug("adding %s:%s\n", group, event); - list_for_each_entry(pos, &new_evsels, node) { + list_for_each_entry(pos, &new_evsels, core.node) { pr_debug("adding %s:%s to %p\n", group, event, pos); pos->bpf_fd = fd; @@ -1458,8 +1458,8 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, bool is_leader = true; int i, nr_pmu = 0, total_members, ret = 0; - leader = list_first_entry(list, struct evsel, node); - evsel = list_last_entry(list, struct evsel, node); + leader = list_first_entry(list, struct evsel, core.node); + evsel = list_last_entry(list, struct evsel, core.node); total_members = evsel->idx - leader->idx + 1; leaders = calloc(total_members, sizeof(uintptr_t)); @@ -1555,7 +1555,7 @@ void parse_events__set_leader(char *name, struct list_head *list, return; __perf_evlist__set_leader(list); - leader = list_entry(list->next, struct evsel, node); + leader = list_entry(list->next, struct evsel, core.node); leader->group_name = name ? strdup(name) : NULL; } @@ -2050,9 +2050,9 @@ foreach_evsel_in_last_glob(struct evlist *evlist, if (!last) return 0; - if (last->node.prev == &evlist->entries) + if (last->core.node.prev == &evlist->entries) return 0; - last = list_entry(last->node.prev, struct evsel, node); + last = list_entry(last->core.node.prev, struct evsel, core.node); } while (!last->cmdline_group_boundary); return 0; diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 1f099823a1f9..17b7d3b55b5f 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -548,8 +548,8 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c struct evlist *evlist = counter->evlist; struct evsel *alias; - alias = list_prepare_entry(counter, &(evlist->entries), node); - list_for_each_entry_continue (alias, &evlist->entries, node) { + alias = list_prepare_entry(counter, &(evlist->entries), core.node); + list_for_each_entry_continue (alias, &evlist->entries, core.node) { if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || alias->scale != counter->scale || alias->cgrp != counter->cgrp || diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index d7ae0627ac47..7efdbb182ea1 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -408,7 +408,7 @@ get_tracepoints_path(struct list_head *pattrs) struct evsel *pos; int nr_tracepoints = 0; - list_for_each_entry(pos, pattrs, node) { + list_for_each_entry(pos, pattrs, core.node) { if (pos->attr.type != PERF_TYPE_TRACEPOINT) continue; ++nr_tracepoints; @@ -443,7 +443,7 @@ bool have_tracepoints(struct list_head *pattrs) { struct evsel *pos; - list_for_each_entry(pos, pattrs, node) + list_for_each_entry(pos, pattrs, core.node) if (pos->attr.type == PERF_TYPE_TRACEPOINT) return true; -- GitLab From ce9036a6e3bdfac6c7ccf8221aec9bcf9c2d355e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:23 +0200 Subject: [PATCH 1162/7155] libperf: Include perf_evlist in evlist object Include perf_evlist in the evlist object, will continue to move other generic things into libperf's perf_evlist. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-37-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-sched.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/ui/browsers/hists.c | 6 +++--- tools/perf/util/cgroup.c | 2 +- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 17 +++++++++-------- tools/perf/util/header.c | 4 ++-- tools/perf/util/parse-events.c | 2 +- tools/perf/util/stat-display.c | 4 ++-- 10 files changed, 26 insertions(+), 25 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 03fbe4600ca0..17bb0a536da3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1002,7 +1002,7 @@ static void record__init_features(struct record *rec) if (rec->no_buildid) perf_header__clear_feat(&session->header, HEADER_BUILD_ID); - if (!have_tracepoints(&rec->evlist->entries)) + if (!have_tracepoints(&rec->evlist->core.entries)) perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); if (!rec->opts.branch_stack) @@ -1218,7 +1218,7 @@ static int record__synthesize(struct record *rec, bool tail) return err; } - if (have_tracepoints(&rec->evlist->entries)) { + if (have_tracepoints(&rec->evlist->core.entries)) { /* * FIXME err <= 0 here actually means that * there were no tracepoints so its not really diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 70247f1b23da..897d11c8ca2e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2929,7 +2929,7 @@ static int timehist_check_attr(struct perf_sched *sched, struct evsel *evsel; struct evsel_runtime *er; - list_for_each_entry(evsel, &evlist->entries, core.node) { + list_for_each_entry(evsel, &evlist->core.entries, core.node) { er = perf_evsel__get_runtime(evsel); if (er == NULL) { pr_err("Failed to allocate memory for evsel runtime data\n"); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 29dbf99f6081..bcd033e91de4 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3980,7 +3980,7 @@ static int trace__parse_cgroups(const struct option *opt, const char *str, int u { struct trace *trace = opt->value; - if (!list_empty(&trace->evlist->entries)) + if (!list_empty(&trace->evlist->core.entries)) return parse_cgroups(opt, str, unset); trace->cgroup = evlist__findnew_cgroup(trace->evlist, str); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 280347499c50..ed5406ff9fe4 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -3309,13 +3309,13 @@ static int perf_evsel_menu__run(struct evsel_menu *menu, ui_browser__show_title(&menu->b, title); switch (key) { case K_TAB: - if (pos->core.node.next == &evlist->entries) + if (pos->core.node.next == &evlist->core.entries) pos = perf_evlist__first(evlist); else pos = perf_evsel__next(pos); goto browse_hists; case K_UNTAB: - if (pos->core.node.prev == &evlist->entries) + if (pos->core.node.prev == &evlist->core.entries) pos = perf_evlist__last(evlist); else pos = perf_evsel__prev(pos); @@ -3370,7 +3370,7 @@ static int __perf_evlist__tui_browse_hists(struct evlist *evlist, struct evsel *pos; struct evsel_menu menu = { .b = { - .entries = &evlist->entries, + .entries = &evlist->core.entries, .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = perf_evsel_menu__write, diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index deb87ecd3671..f73599f271ff 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -208,7 +208,7 @@ int parse_cgroups(const struct option *opt, const char *str, char *s; int ret, i; - if (list_empty(&evlist->entries)) { + if (list_empty(&evlist->core.entries)) { fprintf(stderr, "must define events before cgroups\n"); return -1; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 227576bf16c0..faf3ffd81d4c 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -48,7 +48,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) INIT_HLIST_HEAD(&evlist->heads[i]); - INIT_LIST_HEAD(&evlist->entries); + INIT_LIST_HEAD(&evlist->core.entries); perf_evlist__set_maps(evlist, cpus, threads); fdarray__init(&evlist->pollfd, 64); evlist->workload.pid = -1; @@ -180,7 +180,7 @@ static void perf_evlist__propagate_maps(struct evlist *evlist) void evlist__add(struct evlist *evlist, struct evsel *entry) { entry->evlist = evlist; - list_add_tail(&entry->core.node, &evlist->entries); + list_add_tail(&entry->core.node, &evlist->core.entries); entry->idx = evlist->nr_entries; entry->tracking = !entry->idx; @@ -226,7 +226,7 @@ void perf_evlist__set_leader(struct evlist *evlist) { if (evlist->nr_entries) { evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; - __perf_evlist__set_leader(&evlist->entries); + __perf_evlist__set_leader(&evlist->core.entries); } } @@ -1683,7 +1683,7 @@ void perf_evlist__to_front(struct evlist *evlist, list_move_tail(&evsel->core.node, &move); } - list_splice(&move, &evlist->entries); + list_splice(&move, &evlist->core.entries); } void perf_evlist__set_tracking_event(struct evlist *evlist, diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 1315e64ad69e..7117378a08e3 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "../perf.h" #include "event.h" #include "evsel.h" @@ -25,7 +26,7 @@ struct record_opts; #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) struct evlist { - struct list_head entries; + struct perf_evlist core; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; int nr_groups; @@ -225,17 +226,17 @@ void perf_evlist__splice_list_tail(struct evlist *evlist, static inline bool perf_evlist__empty(struct evlist *evlist) { - return list_empty(&evlist->entries); + return list_empty(&evlist->core.entries); } static inline struct evsel *perf_evlist__first(struct evlist *evlist) { - return list_entry(evlist->entries.next, struct evsel, core.node); + return list_entry(evlist->core.entries.next, struct evsel, core.node); } static inline struct evsel *perf_evlist__last(struct evlist *evlist) { - return list_entry(evlist->entries.prev, struct evsel, core.node); + return list_entry(evlist->core.entries.prev, struct evsel, core.node); } size_t perf_evlist__fprintf(struct evlist *evlist, FILE *fp); @@ -261,7 +262,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define evlist__for_each_entry(evlist, evsel) \ - __evlist__for_each_entry(&(evlist)->entries, evsel) + __evlist__for_each_entry(&(evlist)->core.entries, evsel) /** * __evlist__for_each_entry_continue - continue iteration thru all the evsels @@ -277,7 +278,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define evlist__for_each_entry_continue(evlist, evsel) \ - __evlist__for_each_entry_continue(&(evlist)->entries, evsel) + __evlist__for_each_entry_continue(&(evlist)->core.entries, evsel) /** * __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order @@ -293,7 +294,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @evsel: struct evsel iterator */ #define evlist__for_each_entry_reverse(evlist, evsel) \ - __evlist__for_each_entry_reverse(&(evlist)->entries, evsel) + __evlist__for_each_entry_reverse(&(evlist)->core.entries, evsel) /** * __evlist__for_each_entry_safe - safely iterate thru all the evsels @@ -311,7 +312,7 @@ void perf_evlist__to_front(struct evlist *evlist, * @tmp: struct evsel temp iterator */ #define evlist__for_each_entry_safe(evlist, tmp, evsel) \ - __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel) + __evlist__for_each_entry_safe(&(evlist)->core.entries, tmp, evsel) void perf_evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_evsel); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 5e0093251f26..70ab6b8c715b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -304,7 +304,7 @@ static int write_tracing_data(struct feat_fd *ff, if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) return -1; - return read_tracing_data(ff->fd, &evlist->entries); + return read_tracing_data(ff->fd, &evlist->core.entries); } static int write_build_id(struct feat_fd *ff, @@ -4112,7 +4112,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, * - write the tracing data from the temp file * to the pipe */ - tdata = tracing_data_get(&evlist->entries, fd, true); + tdata = tracing_data_get(&evlist->core.entries, fd, true); if (!tdata) return -1; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e111c0e0a5ac..a0b7d68d2f8e 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2050,7 +2050,7 @@ foreach_evsel_in_last_glob(struct evlist *evlist, if (!last) return 0; - if (last->core.node.prev == &evlist->entries) + if (last->core.node.prev == &evlist->core.entries) return 0; last = list_entry(last->core.node.prev, struct evsel, core.node); } while (!last->cmdline_group_boundary); diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 17b7d3b55b5f..b1a2571f7c8f 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -548,8 +548,8 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c struct evlist *evlist = counter->evlist; struct evsel *alias; - alias = list_prepare_entry(counter, &(evlist->entries), core.node); - list_for_each_entry_continue (alias, &evlist->entries, core.node) { + alias = list_prepare_entry(counter, &(evlist->core.entries), core.node); + list_for_each_entry_continue (alias, &evlist->core.entries, core.node) { if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || alias->scale != counter->scale || alias->cgrp != counter->cgrp || -- GitLab From b04c597af761ccfd32f40ee3629843b6f3674fce Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:24 +0200 Subject: [PATCH 1163/7155] libperf: Add perf_evsel__init function Add the perf_evsel__init() function to initialize perf_evsel struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-38-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 5 +++++ tools/perf/lib/include/perf/evsel.h | 4 ++++ tools/perf/lib/libperf.map | 1 + tools/perf/util/evsel.c | 3 ++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 12e86de1994b..9a87e867a7ec 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -2,3 +2,8 @@ #include #include #include + +void perf_evsel__init(struct perf_evsel *evsel) +{ + INIT_LIST_HEAD(&evsel->node); +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index 162bffd43409..b4d074a3684b 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -2,6 +2,10 @@ #ifndef __LIBPERF_EVSEL_H #define __LIBPERF_EVSEL_H +#include + struct perf_evsel; +LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel); + #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index c4f611010ccc..54f8503c6d82 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -9,6 +9,7 @@ LIBPERF_0.0.1 { perf_thread_map__comm; perf_thread_map__get; perf_thread_map__put; + perf_evsel__init; local: *; }; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8fed22d889a4..172bcc2e198f 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "asm/bug.h" #include "callchain.h" #include "cgroup.h" @@ -226,6 +227,7 @@ bool perf_evsel__is_function_event(struct evsel *evsel) void evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx) { + perf_evsel__init(&evsel->core); evsel->idx = idx; evsel->tracking = !idx; evsel->attr = *attr; @@ -236,7 +238,6 @@ void evsel__init(struct evsel *evsel, evsel->evlist = NULL; evsel->bpf_obj = NULL; evsel->bpf_fd = -1; - INIT_LIST_HEAD(&evsel->core.node); INIT_LIST_HEAD(&evsel->config_terms); perf_evsel__object.init(evsel); evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); -- GitLab From 4562a7393996bb28bf629277903a561bfefea177 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:25 +0200 Subject: [PATCH 1164/7155] libperf: Add perf_evlist__init() function Add the perf_evlist__init() function to initialize a perf_evlist struct. Committer testing: Fix a change in init ordering that was causing this backtrace: (gdb) run stat sleep 1 Starting program: /root/bin/perf stat sleep 1 Program received signal SIGSEGV, Segmentation fault. 0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161 161 if (!evsel->own_cpus || evlist->has_user_cpus) { Missing separate debuginfos, use: dnf debuginfo-install bzip2-libs-1.0.6-29.fc30.x86_64 elfutils-libelf-0.176-3.fc30.x86_64 elfutils-libs-0.176-3.fc30.x86_64 glib2-2.60.4-1.fc30.x86_64 libbabeltrace-1.5.6-2.fc30.x86_64 libgcc-9.1.1-1.fc30.x86_64 libunwind-1.3.1-2.fc30.x86_64 libuuid-2.33.2-1.fc30.x86_64 libxcrypt-4.4.6-2.fc30.x86_64 libzstd-1.4.0-1.fc30.x86_64 numactl-libs-2.0.12-2.fc30.x86_64 pcre-8.43-2.fc30.x86_64 perl-libs-5.28.2-436.fc30.x86_64 popt-1.16-17.fc30.x86_64 python2-libs-2.7.16-2.fc30.x86_64 slang-2.3.2-5.fc30.x86_64 xz-libs-5.2.4-5.fc30.x86_64 zlib-1.2.11-15.fc30.x86_64 (gdb) bt #0 0x00000000004f6b55 in __perf_evlist__propagate_maps (evlist=0xbb34c0, evsel=0x0) at util/evlist.c:161 #1 0x00000000004f6c7a in perf_evlist__propagate_maps (evlist=0xbb34c0) at util/evlist.c:178 #2 0x00000000004f955e in perf_evlist__set_maps (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:1128 #3 0x00000000004f66f8 in evlist__init (evlist=0xbb34c0, cpus=0x0, threads=0x0) at util/evlist.c:52 #4 0x00000000004f6790 in evlist__new () at util/evlist.c:64 #5 0x0000000000456071 in cmd_stat (argc=3, argv=0x7fffffffd670) at builtin-stat.c:1705 #6 0x00000000004dd0fa in run_builtin (p=0xa21e00 , argc=3, argv=0x7fffffffd670) at perf.c:304 #7 0x00000000004dd367 in handle_internal_command (argc=3, argv=0x7fffffffd670) at perf.c:356 #8 0x00000000004dd4ae in run_argv (argcp=0x7fffffffd4cc, argv=0x7fffffffd4c0) at perf.c:400 #9 0x00000000004dd81a in main (argc=3, argv=0x7fffffffd670) at perf.c:522 (gdb) bt So move the initialization of the core evlist (calling perf_evlist__init()) to before perf_evlist__set_maps() in evlist__init(). Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-39-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 5 +++++ tools/perf/lib/include/perf/evlist.h | 4 ++++ tools/perf/lib/libperf.map | 1 + tools/perf/util/evlist.c | 3 ++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 646bdd518793..fdc8c1894b37 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -2,3 +2,8 @@ #include #include #include + +void perf_evlist__init(struct perf_evlist *evlist) +{ + INIT_LIST_HEAD(&evlist->entries); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 92b0eb39caec..1ddfcca0bd01 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -2,6 +2,10 @@ #ifndef __LIBPERF_EVLIST_H #define __LIBPERF_EVLIST_H +#include + struct perf_evlist; +LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist); + #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 54f8503c6d82..5ca6ff6fcdfa 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -10,6 +10,7 @@ LIBPERF_0.0.1 { perf_thread_map__get; perf_thread_map__put; perf_evsel__init; + perf_evlist__init; local: *; }; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index faf3ffd81d4c..f4aa6cf80559 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef LACKS_SIGQUEUE_PROTOTYPE int sigqueue(pid_t pid, int sig, const union sigval value); @@ -48,7 +49,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) INIT_HLIST_HEAD(&evlist->heads[i]); - INIT_LIST_HEAD(&evlist->core.entries); + perf_evlist__init(&evlist->core); perf_evlist__set_maps(evlist, cpus, threads); fdarray__init(&evlist->pollfd, 64); evlist->workload.pid = -1; -- GitLab From 9a5edde6d3a6fb26101406534f7a5d09a9fcd362 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:26 +0200 Subject: [PATCH 1165/7155] libperf: Add perf_evlist__add() function Add the perf_evlist__add() function to add a perf_evsel in a perf_evlist struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-40-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 7 +++++++ tools/perf/lib/include/perf/evlist.h | 3 +++ tools/perf/lib/libperf.map | 1 + tools/perf/util/evlist.c | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index fdc8c1894b37..e5f187fa4e57 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -2,8 +2,15 @@ #include #include #include +#include void perf_evlist__init(struct perf_evlist *evlist) { INIT_LIST_HEAD(&evlist->entries); } + +void perf_evlist__add(struct perf_evlist *evlist, + struct perf_evsel *evsel) +{ + list_add_tail(&evsel->node, &evlist->entries); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 1ddfcca0bd01..6992568b14a0 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -5,7 +5,10 @@ #include struct perf_evlist; +struct perf_evsel; LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist); +LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, + struct perf_evsel *evsel); #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 5ca6ff6fcdfa..06ccf31eb24d 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -11,6 +11,7 @@ LIBPERF_0.0.1 { perf_thread_map__put; perf_evsel__init; perf_evlist__init; + perf_evlist__add; local: *; }; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index f4aa6cf80559..f2b86f49ab8d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -180,8 +180,8 @@ static void perf_evlist__propagate_maps(struct evlist *evlist) void evlist__add(struct evlist *evlist, struct evsel *entry) { + perf_evlist__add(&evlist->core, &entry->core); entry->evlist = evlist; - list_add_tail(&entry->core.node, &evlist->core.entries); entry->idx = evlist->nr_entries; entry->tracking = !entry->idx; -- GitLab From 52e22fb8af779e1a26b1cbde1db2f82f78b3ae68 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:27 +0200 Subject: [PATCH 1166/7155] libperf: Add perf_evlist__remove() function Adding perf_evlist__remove() function to remove a perf_evsel from a perf_evlist struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-41-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 6 ++++++ tools/perf/lib/include/perf/evlist.h | 2 ++ tools/perf/lib/libperf.map | 1 + tools/perf/util/evlist.c | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index e5f187fa4e57..023fe4b44131 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -14,3 +14,9 @@ void perf_evlist__add(struct perf_evlist *evlist, { list_add_tail(&evsel->node, &evlist->entries); } + +void perf_evlist__remove(struct perf_evlist *evlist, + struct perf_evsel *evsel) +{ + list_del_init(&evsel->node); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 6992568b14a0..e0c87995c6ff 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -10,5 +10,7 @@ struct perf_evsel; LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist); LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *evsel); +LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist, + struct perf_evsel *evsel); #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 06ccf31eb24d..168339f89a2e 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -12,6 +12,7 @@ LIBPERF_0.0.1 { perf_evsel__init; perf_evlist__init; perf_evlist__add; + perf_evlist__remove; local: *; }; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index f2b86f49ab8d..9b0108c23010 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -194,7 +194,7 @@ void evlist__add(struct evlist *evlist, struct evsel *entry) void evlist__remove(struct evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; - list_del_init(&evsel->core.node); + perf_evlist__remove(&evlist->core, &evsel->core); evlist->nr_entries -= 1; } -- GitLab From 6484d2f9dc3ecbf13f07100f7f771d1d779eda04 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:28 +0200 Subject: [PATCH 1167/7155] libperf: Add nr_entries to struct perf_evlist Move nr_entries count from 'struct perf' to into perf_evlist struct. Committer notes: Fix tools/perf/arch/s390/util/auxtrace.c case. And also the comment in tools/perf/util/annotate.h. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-42-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/auxtrace.c | 2 +- tools/perf/builtin-record.c | 4 +- tools/perf/builtin-stat.c | 4 +- tools/perf/builtin-top.c | 12 ++-- tools/perf/builtin-trace.c | 4 +- tools/perf/lib/evlist.c | 3 + tools/perf/lib/include/internal/evlist.h | 1 + tools/perf/tests/parse-events.c | 76 ++++++++++++------------ tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/annotate.h | 2 +- tools/perf/util/evlist.c | 26 ++++---- tools/perf/util/evlist.h | 1 - tools/perf/util/header.c | 4 +- tools/perf/util/parse-events.c | 4 +- tools/perf/util/python.c | 8 +-- tools/perf/util/record.c | 2 +- tools/perf/util/sort.c | 2 +- tools/perf/util/top.c | 2 +- 20 files changed, 83 insertions(+), 80 deletions(-) diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c index 833f60fa9c5a..480ada281bdb 100644 --- a/tools/perf/arch/s390/util/auxtrace.c +++ b/tools/perf/arch/s390/util/auxtrace.c @@ -90,7 +90,7 @@ struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, int diagnose = 0; *err = 0; - if (evlist->nr_entries == 0) + if (evlist->core.nr_entries == 0) return NULL; evlist__for_each_entry(evlist, pos) { diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 17bb0a536da3..778e46417f6b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1375,7 +1375,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * because we synthesize event name through the pipe * and need the id for that. */ - if (data->is_pipe && rec->evlist->nr_entries == 1) + if (data->is_pipe && rec->evlist->core.nr_entries == 1) rec->opts.sample_id = true; if (record__open(rec) != 0) { @@ -2386,7 +2386,7 @@ int cmd_record(int argc, const char **argv) if (record.opts.overwrite) record.opts.tail_synthesize = true; - if (rec->evlist->nr_entries == 0 && + if (rec->evlist->core.nr_entries == 0 && __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { pr_err("Not enough memory for event selector list\n"); goto out; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 39bd73d0e06e..3ba184f2e64f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1366,7 +1366,7 @@ static int add_default_attributes(void) free(str); } - if (!evsel_list->nr_entries) { + if (!evsel_list->core.nr_entries) { if (target__has_cpu(&target)) default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; @@ -1683,7 +1683,7 @@ static void setup_system_wide(int forks) return; } - if (evsel_list->nr_entries) + if (evsel_list->core.nr_entries) target.system_wide = true; } } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b103f1ba01cb..3291eff13e28 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -129,7 +129,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) notes = symbol__annotation(sym); pthread_mutex_lock(¬es->lock); - if (!symbol__hists(sym, top->evlist->nr_entries)) { + if (!symbol__hists(sym, top->evlist->core.nr_entries)) { pthread_mutex_unlock(¬es->lock); pr_err("Not enough memory for annotating '%s' symbol!\n", sym->name); @@ -404,7 +404,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top) fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top->delay_secs); fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries); - if (top->evlist->nr_entries > 1) + if (top->evlist->core.nr_entries > 1) fprintf(stdout, "\t[E] active event counter. \t(%s)\n", perf_evsel__name(top->sym_evsel)); fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter); @@ -439,7 +439,7 @@ static int perf_top__key_mapped(struct perf_top *top, int c) case 'S': return 1; case 'E': - return top->evlist->nr_entries > 1 ? 1 : 0; + return top->evlist->core.nr_entries > 1 ? 1 : 0; default: break; } @@ -485,7 +485,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) } break; case 'E': - if (top->evlist->nr_entries > 1) { + if (top->evlist->core.nr_entries > 1) { /* Select 0 as the default event: */ int counter = 0; @@ -496,7 +496,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) prompt_integer(&counter, "Enter details event counter"); - if (counter >= top->evlist->nr_entries) { + if (counter >= top->evlist->core.nr_entries) { top->sym_evsel = perf_evlist__first(top->evlist); fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel)); sleep(1); @@ -1536,7 +1536,7 @@ int cmd_top(int argc, const char **argv) if (argc) usage_with_options(top_usage, options); - if (!top.evlist->nr_entries && + if (!top.evlist->core.nr_entries && perf_evlist__add_default(top.evlist) < 0) { pr_err("Not enough memory for event selector list\n"); goto out_delete_evlist; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index bcd033e91de4..06fcd8b1f160 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4270,7 +4270,7 @@ int cmd_trace(int argc, const char **argv) symbol_conf.use_callchain = true; } - if (trace.evlist->nr_entries > 0) { + if (trace.evlist->core.nr_entries > 0) { evlist__set_evsel_handler(trace.evlist, trace__event_handler); if (evlist__set_syscall_tp_fields(trace.evlist)) { perror("failed to set syscalls:* tracepoint fields"); @@ -4368,7 +4368,7 @@ int cmd_trace(int argc, const char **argv) trace.summary = trace.summary_only; if (!trace.trace_syscalls && !trace.trace_pgfaults && - trace.evlist->nr_entries == 0 /* Was --events used? */) { + trace.evlist->core.nr_entries == 0 /* Was --events used? */) { trace.trace_syscalls = true; } diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 023fe4b44131..1b27fd2de9b9 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -7,16 +7,19 @@ void perf_evlist__init(struct perf_evlist *evlist) { INIT_LIST_HEAD(&evlist->entries); + evlist->nr_entries = 0; } void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *evsel) { list_add_tail(&evsel->node, &evlist->entries); + evlist->nr_entries += 1; } void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel) { list_del_init(&evsel->node); + evlist->nr_entries -= 1; } diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index 7fbfe5716652..a12c712a9197 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -4,6 +4,7 @@ struct perf_evlist { struct list_head entries; + int nr_entries; }; #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 2365dd655c88..878140501edf 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -48,7 +48,7 @@ static int test__checkevent_tracepoint(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", @@ -61,7 +61,7 @@ static int test__checkevent_tracepoint_multi(struct evlist *evlist) { struct evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); + TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1); TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); evlist__for_each_entry(evlist, evsel) { @@ -79,7 +79,7 @@ static int test__checkevent_raw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config); return 0; @@ -89,7 +89,7 @@ static int test__checkevent_numeric(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); return 0; @@ -99,7 +99,7 @@ static int test__checkevent_symbolic_name(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); TEST_ASSERT_VAL("wrong config", PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); @@ -110,7 +110,7 @@ static int test__checkevent_symbolic_name_config(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); TEST_ASSERT_VAL("wrong config", PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); @@ -131,7 +131,7 @@ static int test__checkevent_symbolic_alias(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); TEST_ASSERT_VAL("wrong config", PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); @@ -142,7 +142,7 @@ static int test__checkevent_genhw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config); return 0; @@ -152,7 +152,7 @@ static int test__checkevent_breakpoint(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == @@ -166,7 +166,7 @@ static int test__checkevent_breakpoint_x(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); TEST_ASSERT_VAL("wrong bp_type", @@ -179,7 +179,7 @@ static int test__checkevent_breakpoint_r(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); @@ -194,7 +194,7 @@ static int test__checkevent_breakpoint_w(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); @@ -209,7 +209,7 @@ static int test__checkevent_breakpoint_rw(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); @@ -237,7 +237,7 @@ test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) { struct evsel *evsel; - TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); + TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1); evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("wrong exclude_user", @@ -437,7 +437,7 @@ static int test__checkevent_pmu(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config); TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1); @@ -455,7 +455,7 @@ static int test__checkevent_list(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); /* r1 */ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); @@ -495,14 +495,14 @@ static int test__checkevent_pmu_name(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); /* cpu/config=1,name=krava/u */ - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava")); /* cpu/config=2/u" */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); TEST_ASSERT_VAL("wrong name", @@ -516,7 +516,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); /* cpu/config=1,call-graph=fp,time,period=100000/ */ - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); /* @@ -548,7 +548,7 @@ static int test__checkevent_pmu_events(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); @@ -567,7 +567,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); /* pmu-event:u */ - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", @@ -578,7 +578,7 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) /* cpu/pmu-event/u*/ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); @@ -638,7 +638,7 @@ static int test__group1(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* instructions:k */ @@ -680,7 +680,7 @@ static int test__group2(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* faults + :ku modifier */ @@ -735,7 +735,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); /* group1 syscalls:sys_enter_openat:H */ @@ -827,7 +827,7 @@ static int test__group4(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles:u + p */ @@ -871,7 +871,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); /* cycles + G */ @@ -957,7 +957,7 @@ static int test__group_gh1(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles + :H group modifier */ @@ -997,7 +997,7 @@ static int test__group_gh2(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles + :G group modifier */ @@ -1037,7 +1037,7 @@ static int test__group_gh3(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles:G + :u group modifier */ @@ -1077,7 +1077,7 @@ static int test__group_gh4(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles:G + :uG group modifier */ @@ -1117,7 +1117,7 @@ static int test__leader_sample1(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); /* cycles - sampling group leader */ evsel = leader = perf_evlist__first(evlist); @@ -1170,7 +1170,7 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); /* instructions - sampling group leader */ evsel = leader = perf_evlist__first(evlist); @@ -1222,7 +1222,7 @@ static int test__pinned_group(struct evlist *evlist) { struct evsel *evsel, *leader; - TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); /* cycles - group leader */ evsel = leader = perf_evlist__first(evlist); @@ -1253,7 +1253,7 @@ static int test__checkevent_breakpoint_len(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == @@ -1268,7 +1268,7 @@ static int test__checkevent_breakpoint_len_w(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == @@ -1296,7 +1296,7 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); TEST_ASSERT_VAL("wrong config", PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config); @@ -1425,7 +1425,7 @@ static int count_tracepoints(void) static int test__all_tracepoints(struct evlist *evlist) { TEST_ASSERT_VAL("wrong events count", - count_tracepoints() == evlist->nr_entries); + count_tracepoints() == evlist->core.nr_entries); return test__checkevent_tracepoint_multi(evlist); } diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 64cc650c4543..e633eb42550d 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -422,7 +422,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, notes = symbol__annotation(dl->ops.target.sym); pthread_mutex_lock(¬es->lock); - if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) { + if (!symbol__hists(dl->ops.target.sym, evsel->evlist->core.nr_entries)) { pthread_mutex_unlock(¬es->lock); ui__warning("Not enough memory for annotating '%s' symbol!\n", dl->ops.target.sym->name); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index ed5406ff9fe4..b195b1ba625b 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -3404,7 +3404,7 @@ int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help, bool warn_lost_event, struct annotation_options *annotation_opts) { - int nr_entries = evlist->nr_entries; + int nr_entries = evlist->core.nr_entries; single_entry: if (nr_entries == 1) { diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 6ea5d678a81c..d46f2ae2c695 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -936,7 +936,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, if (sym == NULL) return 0; - src = symbol__hists(sym, evsel->evlist->nr_entries); + src = symbol__hists(sym, evsel->evlist->core.nr_entries); return (src) ? __symbol__inc_addr_samples(sym, map, src, evsel->idx, addr, sample) : 0; } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 7c42f320efa2..d94be9140e31 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -245,7 +245,7 @@ struct cyc_hist { /** struct annotated_source - symbols with hits have this attached as in sannotation * * @histograms: Array of addr hit histograms per event being monitored - * nr_histograms: This may not be the same as evsel->evlist->nr_entries if + * nr_histograms: This may not be the same as evsel->evlist->core.nr_entries if * we have more than a group in a evlist, where we will want * to see each group separately, that is why symbol__annotate2() * sets src->nr_histograms to evsel->nr_members. diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9b0108c23010..ce9f52215d60 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -125,7 +125,7 @@ static void perf_evlist__purge(struct evlist *evlist) evsel__delete(pos); } - evlist->nr_entries = 0; + evlist->core.nr_entries = 0; } void perf_evlist__exit(struct evlist *evlist) @@ -180,12 +180,13 @@ static void perf_evlist__propagate_maps(struct evlist *evlist) void evlist__add(struct evlist *evlist, struct evsel *entry) { - perf_evlist__add(&evlist->core, &entry->core); entry->evlist = evlist; - entry->idx = evlist->nr_entries; + entry->idx = evlist->core.nr_entries; entry->tracking = !entry->idx; - if (!evlist->nr_entries++) + perf_evlist__add(&evlist->core, &entry->core); + + if (evlist->core.nr_entries == 1) perf_evlist__set_id_pos(evlist); __perf_evlist__propagate_maps(evlist, entry); @@ -195,7 +196,6 @@ void evlist__remove(struct evlist *evlist, struct evsel *evsel) { evsel->evlist = NULL; perf_evlist__remove(&evlist->core, &evsel->core); - evlist->nr_entries -= 1; } void perf_evlist__splice_list_tail(struct evlist *evlist, @@ -225,8 +225,8 @@ void __perf_evlist__set_leader(struct list_head *list) void perf_evlist__set_leader(struct evlist *evlist) { - if (evlist->nr_entries) { - evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; + if (evlist->core.nr_entries) { + evlist->nr_groups = evlist->core.nr_entries > 1 ? 1 : 0; __perf_evlist__set_leader(&evlist->core.entries); } } @@ -249,7 +249,7 @@ int perf_evlist__add_dummy(struct evlist *evlist) .config = PERF_COUNT_SW_DUMMY, .size = sizeof(attr), /* to capture ABI version */ }; - struct evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries); + struct evsel *evsel = perf_evsel__new_idx(&attr, evlist->core.nr_entries); if (evsel == NULL) return -ENOMEM; @@ -266,7 +266,7 @@ static int evlist__add_attrs(struct evlist *evlist, size_t i; for (i = 0; i < nr_attrs; i++) { - evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); + evsel = perf_evsel__new_idx(attrs + i, evlist->core.nr_entries + i); if (evsel == NULL) goto out_delete_partial_list; list_add_tail(&evsel->core.node, &head); @@ -581,7 +581,7 @@ struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) { struct perf_sample_id *sid; - if (evlist->nr_entries == 1 || !id) + if (evlist->core.nr_entries == 1 || !id) return perf_evlist__first(evlist); sid = perf_evlist__id2sid(evlist, id); @@ -639,7 +639,7 @@ struct evsel *perf_evlist__event2evsel(struct evlist *evlist, int hash; u64 id; - if (evlist->nr_entries == 1) + if (evlist->core.nr_entries == 1) return first; if (!first->attr.sample_id_all && @@ -1222,7 +1222,7 @@ bool perf_evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; - if (evlist->nr_entries == 1) + if (evlist->core.nr_entries == 1) return true; if (evlist->id_pos < 0 || evlist->is_pos < 0) @@ -1849,7 +1849,7 @@ int perf_evlist__add_sb_event(struct evlist **evlist, attr->sample_id_all = 1; } - evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries); + evsel = perf_evsel__new_idx(attr, (*evlist)->core.nr_entries); if (!evsel) goto out_err; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 7117378a08e3..17dd83021a79 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -28,7 +28,6 @@ struct record_opts; struct evlist { struct perf_evlist core; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; - int nr_entries; int nr_groups; int nr_mmaps; bool enabled; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 70ab6b8c715b..141de4425100 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -476,7 +476,7 @@ static int write_event_desc(struct feat_fd *ff, u32 nre, nri, sz; int ret; - nre = evlist->nr_entries; + nre = evlist->core.nr_entries; /* * write number of events @@ -3100,7 +3100,7 @@ int perf_session__write_header(struct perf_session *session, .attr_size = sizeof(f_attr), .attrs = { .offset = attr_offset, - .size = evlist->nr_entries * sizeof(f_attr), + .size = evlist->core.nr_entries * sizeof(f_attr), }, .data = { .offset = header->data_offset, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a0b7d68d2f8e..10efc33c56a1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1909,7 +1909,7 @@ int parse_events(struct evlist *evlist, const char *str, { struct parse_events_state parse_state = { .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->nr_entries, + .idx = evlist->core.nr_entries, .error = err, .evlist = evlist, }; @@ -2040,7 +2040,7 @@ foreach_evsel_in_last_glob(struct evlist *evlist, * * So no need to WARN here, let *func do this. */ - if (evlist->nr_entries > 0) + if (evlist->core.nr_entries > 0) last = perf_evlist__last(evlist); do { diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 19d2feee91d5..cf0a18d49018 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -973,10 +973,10 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, Py_INCREF(pevsel); evsel = &((struct pyrf_evsel *)pevsel)->evsel; - evsel->idx = evlist->nr_entries; + evsel->idx = evlist->core.nr_entries; evlist__add(evlist, evsel); - return Py_BuildValue("i", evlist->nr_entries); + return Py_BuildValue("i", evlist->core.nr_entries); } static struct perf_mmap *get_md(struct evlist *evlist, int cpu) @@ -1112,7 +1112,7 @@ static Py_ssize_t pyrf_evlist__length(PyObject *obj) { struct pyrf_evlist *pevlist = (void *)obj; - return pevlist->evlist.nr_entries; + return pevlist->evlist.core.nr_entries; } static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) @@ -1120,7 +1120,7 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) struct pyrf_evlist *pevlist = (void *)obj; struct evsel *pos; - if (i >= pevlist->evlist.nr_entries) + if (i >= pevlist->evlist.core.nr_entries) return NULL; evlist__for_each_entry(&pevlist->evlist, pos) { diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index fecccfd71aa1..3d3d732498e1 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -166,7 +166,7 @@ void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, */ use_sample_identifier = perf_can_sample_identifier(); sample_id = true; - } else if (evlist->nr_entries > 1) { + } else if (evlist->core.nr_entries > 1) { struct evsel *first = perf_evlist__first(evlist); evlist__for_each_entry(evlist, evsel) { diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index d8e4392d6e18..fa3cc2112b82 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2323,7 +2323,7 @@ static struct evsel *find_evsel(struct evlist *evlist, char *event_name) if (event_name[0] == '%') { int nr = strtol(event_name+1, NULL, 0); - if (nr > evlist->nr_entries) + if (nr > evlist->core.nr_entries) return NULL; evsel = perf_evlist__first(evlist); diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 9f098db76e3c..3bbbdac2c550 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -70,7 +70,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) esamples_percent); } - if (top->evlist->nr_entries == 1) { + if (top->evlist->core.nr_entries == 1) { struct evsel *first = perf_evlist__first(top->evlist); ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", (uint64_t)first->attr.sample_period, -- GitLab From 1fc632cef4ea137bc45fd0fc4cb902e374064163 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:29 +0200 Subject: [PATCH 1168/7155] libperf: Move perf_event_attr field from perf's evsel to libperf's perf_evsel Move the perf_event_attr struct fron 'struct evsel' to 'struct perf_evsel'. Committer notes: Fixed up these: tools/perf/arch/arm/util/auxtrace.c tools/perf/arch/arm/util/cs-etm.c tools/perf/arch/arm64/util/arm-spe.c tools/perf/arch/s390/util/auxtrace.c tools/perf/util/cs-etm.c Also cc1: warnings being treated as errors tests/sample-parsing.c: In function 'do_test': tests/sample-parsing.c:162: error: missing initializer tests/sample-parsing.c:162: error: (near initialization for 'evsel.core.cpus') struct evsel evsel = { .needs_swap = false, - .core.attr = { - .sample_type = sample_type, - .read_format = read_format, + .core = { + . attr = { + .sample_type = sample_type, + .read_format = read_format, + }, [perfbuilder@a70e4eeb5549 /]$ gcc --version |& head -1 gcc (GCC) 4.4.7 Also we don't need to include perf_event.h in tools/perf/lib/include/perf/evsel.h, forward declaring 'struct perf_event_attr' is enough. And this even fixes the build in some systems where things are used somewhere down the include path from perf_event.h without defining __always_inline. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-43-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/auxtrace.c | 4 +- tools/perf/arch/arm/util/cs-etm.c | 28 +- tools/perf/arch/arm64/util/arm-spe.c | 12 +- tools/perf/arch/s390/util/auxtrace.c | 2 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 6 +- tools/perf/arch/x86/util/auxtrace.c | 4 +- tools/perf/arch/x86/util/intel-bts.c | 16 +- tools/perf/arch/x86/util/intel-pt.c | 40 +- tools/perf/builtin-evlist.c | 2 +- tools/perf/builtin-inject.c | 14 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-script.c | 52 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-timechart.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 32 +- tools/perf/lib/evsel.c | 3 +- tools/perf/lib/include/internal/evsel.h | 4 + tools/perf/lib/include/perf/evsel.h | 4 +- tools/perf/tests/code-reading.c | 6 +- tools/perf/tests/event-times.c | 8 +- tools/perf/tests/keep-tracking.c | 6 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/parse-events.c | 872 +++++++++--------- tools/perf/tests/sample-parsing.c | 12 +- tools/perf/tests/switch-tracking.c | 8 +- tools/perf/tests/task-exit.c | 14 +- tools/perf/ui/browsers/res_sample.c | 2 +- tools/perf/ui/browsers/scripts.c | 2 +- tools/perf/util/auxtrace.c | 2 +- tools/perf/util/bpf-loader.c | 2 +- tools/perf/util/cs-etm.c | 20 +- tools/perf/util/data-convert-bt.c | 14 +- tools/perf/util/db-export.c | 4 +- tools/perf/util/evlist.c | 50 +- tools/perf/util/evsel.c | 167 ++-- tools/perf/util/evsel.h | 17 +- tools/perf/util/evsel_fprintf.c | 8 +- tools/perf/util/header.c | 28 +- tools/perf/util/hist.c | 2 +- tools/perf/util/intel-bts.c | 18 +- tools/perf/util/intel-pt.c | 50 +- tools/perf/util/jitdump.c | 4 +- tools/perf/util/machine.c | 4 +- tools/perf/util/parse-events.c | 40 +- tools/perf/util/python.c | 6 +- tools/perf/util/record.c | 16 +- tools/perf/util/s390-cpumsf.c | 2 +- tools/perf/util/s390-sample-raw.c | 2 +- .../util/scripting-engines/trace-event-perl.c | 6 +- .../scripting-engines/trace-event-python.c | 14 +- tools/perf/util/session.c | 20 +- tools/perf/util/sort.c | 12 +- tools/perf/util/stat-display.c | 8 +- tools/perf/util/stat-shadow.c | 30 +- tools/perf/util/stat.c | 2 +- tools/perf/util/top.c | 2 +- tools/perf/util/trace-event-info.c | 6 +- 59 files changed, 864 insertions(+), 857 deletions(-) diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c index 306a54185438..41b78f74599f 100644 --- a/tools/perf/arch/arm/util/auxtrace.c +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -70,14 +70,14 @@ struct auxtrace_record evlist__for_each_entry(evlist, evsel) { if (cs_etm_pmu && - evsel->attr.type == cs_etm_pmu->type) + evsel->core.attr.type == cs_etm_pmu->type) found_etm = true; if (!nr_spes) continue; for (i = 0; i < nr_spes; i++) { - if (evsel->attr.type == arm_spe_pmus[i]->type) { + if (evsel->core.attr.type == arm_spe_pmus[i]->type) { found_spe = true; break; } diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 3a78b38e43ca..f5aafdec7f50 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -95,7 +95,7 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr, } /* All good, let the kernel know */ - evsel->attr.config |= (1 << ETM_OPT_CTXTID); + evsel->core.attr.config |= (1 << ETM_OPT_CTXTID); err = 0; out: @@ -144,7 +144,7 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr, } /* All good, let the kernel know */ - evsel->attr.config |= (1 << ETM_OPT_TS); + evsel->core.attr.config |= (1 << ETM_OPT_TS); err = 0; out: @@ -215,7 +215,7 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, int ret = -EINVAL; u32 hash; - if (evsel->attr.config2 & GENMASK(31, 0)) + if (evsel->core.attr.config2 & GENMASK(31, 0)) return 0; list_for_each_entry(term, &evsel->config_terms, list) { @@ -233,7 +233,7 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, return ret; } - evsel->attr.config2 |= hash; + evsel->core.attr.config2 |= hash; return 0; } @@ -264,14 +264,14 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, opts->record_switch_events = true; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == cs_etm_pmu->type) { + if (evsel->core.attr.type == cs_etm_pmu->type) { if (cs_etm_evsel) { pr_err("There may be only one %s event\n", CORESIGHT_ETM_PMU_NAME); return -EINVAL; } - evsel->attr.freq = 0; - evsel->attr.sample_period = 1; + evsel->core.attr.freq = 0; + evsel->core.attr.sample_period = 1; cs_etm_evsel = evsel; opts->full_auxtrace = true; } @@ -416,8 +416,8 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, tracking_evsel = perf_evlist__last(evlist); perf_evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->attr.freq = 0; - tracking_evsel->attr.sample_period = 1; + tracking_evsel->core.attr.freq = 0; + tracking_evsel->core.attr.sample_period = 1; /* In per-cpu case, always need the time of mmap events etc */ if (!cpu_map__empty(cpus)) @@ -438,7 +438,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == cs_etm_pmu->type) { + if (evsel->core.attr.type == cs_etm_pmu->type) { /* * Variable perf_event_attr::config is assigned to * ETMv3/PTM. The bit fields have been made to match @@ -447,7 +447,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr) * drivers/hwtracing/coresight/coresight-perf.c for * details. */ - config = evsel->attr.config; + config = evsel->core.attr.config; break; } } @@ -820,7 +820,7 @@ static int cs_etm_snapshot_start(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->cs_etm_pmu->type) + if (evsel->core.attr.type == ptr->cs_etm_pmu->type) return evsel__disable(evsel); } return -EINVAL; @@ -833,7 +833,7 @@ static int cs_etm_snapshot_finish(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->cs_etm_pmu->type) + if (evsel->core.attr.type == ptr->cs_etm_pmu->type) return evsel__enable(evsel); } return -EINVAL; @@ -861,7 +861,7 @@ static int cs_etm_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->cs_etm_pmu->type) + if (evsel->core.attr.type == ptr->cs_etm_pmu->type) return perf_evlist__enable_event_idx(ptr->evlist, evsel, idx); } diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index cc29b995c751..00915b8fd05b 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -73,13 +73,13 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, sper->evlist = evlist; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == arm_spe_pmu->type) { + if (evsel->core.attr.type == arm_spe_pmu->type) { if (arm_spe_evsel) { pr_err("There may be only one " ARM_SPE_PMU_NAME "x event\n"); return -EINVAL; } - evsel->attr.freq = 0; - evsel->attr.sample_period = 1; + evsel->core.attr.freq = 0; + evsel->core.attr.sample_period = 1; arm_spe_evsel = evsel; opts->full_auxtrace = true; } @@ -130,8 +130,8 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, tracking_evsel = perf_evlist__last(evlist); perf_evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->attr.freq = 0; - tracking_evsel->attr.sample_period = 1; + tracking_evsel->core.attr.freq = 0; + tracking_evsel->core.attr.sample_period = 1; perf_evsel__set_sample_bit(tracking_evsel, TIME); perf_evsel__set_sample_bit(tracking_evsel, CPU); perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK); @@ -163,7 +163,7 @@ static int arm_spe_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(sper->evlist, evsel) { - if (evsel->attr.type == sper->arm_spe_pmu->type) + if (evsel->core.attr.type == sper->arm_spe_pmu->type) return perf_evlist__enable_event_idx(sper->evlist, evsel, idx); } diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c index 480ada281bdb..cab46f517b83 100644 --- a/tools/perf/arch/s390/util/auxtrace.c +++ b/tools/perf/arch/s390/util/auxtrace.c @@ -94,7 +94,7 @@ struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, return NULL; evlist__for_each_entry(evlist, pos) { - if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) { + if (pos->core.attr.config == PERF_EVENT_CPUM_SF_DIAG) { diagnose = 1; break; } diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 8b70e9ee341a..07129e007eb0 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -79,9 +79,9 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe evsel = perf_evlist__first(evlist); - evsel->attr.comm = 1; - evsel->attr.disabled = 1; - evsel->attr.enable_on_exec = 0; + evsel->core.attr.comm = 1; + evsel->core.attr.disabled = 1; + evsel->core.attr.enable_on_exec = 0; CHECK__(evlist__open(evlist)); diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c index 6b3ad5c826fd..96f4a2c11893 100644 --- a/tools/perf/arch/x86/util/auxtrace.c +++ b/tools/perf/arch/x86/util/auxtrace.c @@ -29,9 +29,9 @@ struct auxtrace_record *auxtrace_record__init_intel(struct evlist *evlist, intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); evlist__for_each_entry(evlist, evsel) { - if (intel_pt_pmu && evsel->attr.type == intel_pt_pmu->type) + if (intel_pt_pmu && evsel->core.attr.type == intel_pt_pmu->type) found_pt = true; - if (intel_bts_pmu && evsel->attr.type == intel_bts_pmu->type) + if (intel_bts_pmu && evsel->core.attr.type == intel_bts_pmu->type) found_bts = true; } diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 8b0a53d748c9..d8a091266185 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -113,13 +113,13 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, btsr->snapshot_mode = opts->auxtrace_snapshot_mode; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == intel_bts_pmu->type) { + if (evsel->core.attr.type == intel_bts_pmu->type) { if (intel_bts_evsel) { pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n"); return -EINVAL; } - evsel->attr.freq = 0; - evsel->attr.sample_period = 1; + evsel->core.attr.freq = 0; + evsel->core.attr.sample_period = 1; intel_bts_evsel = evsel; opts->full_auxtrace = true; } @@ -231,8 +231,8 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, perf_evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->attr.freq = 0; - tracking_evsel->attr.sample_period = 1; + tracking_evsel->core.attr.freq = 0; + tracking_evsel->core.attr.sample_period = 1; } return 0; @@ -316,7 +316,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { - if (evsel->attr.type == btsr->intel_bts_pmu->type) + if (evsel->core.attr.type == btsr->intel_bts_pmu->type) return evsel__disable(evsel); } return -EINVAL; @@ -329,7 +329,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { - if (evsel->attr.type == btsr->intel_bts_pmu->type) + if (evsel->core.attr.type == btsr->intel_bts_pmu->type) return evsel__enable(evsel); } return -EINVAL; @@ -411,7 +411,7 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { - if (evsel->attr.type == btsr->intel_bts_pmu->type) + if (evsel->core.attr.type == btsr->intel_bts_pmu->type) return perf_evlist__enable_event_idx(btsr->evlist, evsel, idx); } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 4ce157a4e5e2..aada6a2c456a 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -122,8 +122,8 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, return -EINVAL; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == intel_pt_pmu->type) { - *res = intel_pt_masked_bits(mask, evsel->attr.config); + if (evsel->core.attr.type == intel_pt_pmu->type) { + *res = intel_pt_masked_bits(mask, evsel->core.attr.config); return 0; } } @@ -274,7 +274,7 @@ static const char *intel_pt_find_filter(struct evlist *evlist, struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == intel_pt_pmu->type) + if (evsel->core.attr.type == intel_pt_pmu->type) return evsel->filter; } @@ -526,26 +526,26 @@ static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, * sets pt=0, which avoids senseless kernel errors. */ if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 && - !(evsel->attr.config & 1)) { + !(evsel->core.attr.config & 1)) { pr_warning("pt=0 doesn't make sense, forcing pt=1\n"); - evsel->attr.config |= 1; + evsel->core.attr.config |= 1; } err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds", "cyc_thresh", "caps/psb_cyc", - evsel->attr.config); + evsel->core.attr.config); if (err) return err; err = intel_pt_val_config_term(intel_pt_pmu, "caps/mtc_periods", "mtc_period", "caps/mtc", - evsel->attr.config); + evsel->core.attr.config); if (err) return err; return intel_pt_val_config_term(intel_pt_pmu, "caps/psb_periods", "psb_period", "caps/psb_cyc", - evsel->attr.config); + evsel->core.attr.config); } static int intel_pt_recording_options(struct auxtrace_record *itr, @@ -566,13 +566,13 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ptr->snapshot_mode = opts->auxtrace_snapshot_mode; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == intel_pt_pmu->type) { + if (evsel->core.attr.type == intel_pt_pmu->type) { if (intel_pt_evsel) { pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n"); return -EINVAL; } - evsel->attr.freq = 0; - evsel->attr.sample_period = 1; + evsel->core.attr.freq = 0; + evsel->core.attr.sample_period = 1; intel_pt_evsel = evsel; opts->full_auxtrace = true; } @@ -670,7 +670,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); - if (opts->full_auxtrace && (intel_pt_evsel->attr.config & tsc_bit)) + if (opts->full_auxtrace && (intel_pt_evsel->core.attr.config & tsc_bit)) have_timing_info = true; else have_timing_info = false; @@ -693,9 +693,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, switch_evsel = perf_evlist__last(evlist); - switch_evsel->attr.freq = 0; - switch_evsel->attr.sample_period = 1; - switch_evsel->attr.context_switch = 1; + switch_evsel->core.attr.freq = 0; + switch_evsel->core.attr.sample_period = 1; + switch_evsel->core.attr.context_switch = 1; switch_evsel->system_wide = true; switch_evsel->no_aux_samples = true; @@ -753,8 +753,8 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, perf_evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->attr.freq = 0; - tracking_evsel->attr.sample_period = 1; + tracking_evsel->core.attr.freq = 0; + tracking_evsel->core.attr.sample_period = 1; tracking_evsel->no_aux_samples = true; if (need_immediate) @@ -787,7 +787,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->intel_pt_pmu->type) + if (evsel->core.attr.type == ptr->intel_pt_pmu->type) return evsel__disable(evsel); } return -EINVAL; @@ -800,7 +800,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->intel_pt_pmu->type) + if (evsel->core.attr.type == ptr->intel_pt_pmu->type) return evsel__enable(evsel); } return -EINVAL; @@ -1073,7 +1073,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->attr.type == ptr->intel_pt_pmu->type) + if (evsel->core.attr.type == ptr->intel_pt_pmu->type) return perf_evlist__enable_event_idx(ptr->evlist, evsel, idx); } diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index e4cb61dc6315..238fa3876805 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c @@ -36,7 +36,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details evlist__for_each_entry(session->evlist, pos) { perf_evsel__fprintf(pos, details, stdout); - if (pos->attr.type == PERF_TYPE_TRACEPOINT) + if (pos->core.attr.type == PERF_TYPE_TRACEPOINT) has_tracepoint = true; } diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 4e56e399bbc8..040142581d20 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -530,8 +530,8 @@ static int perf_inject__sched_stat(struct perf_tool *tool, sample_sw.period = sample->period; sample_sw.time = sample->time; - perf_event__synthesize_sample(event_sw, evsel->attr.sample_type, - evsel->attr.read_format, &sample_sw); + perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type, + evsel->core.attr.read_format, &sample_sw); build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); return perf_event__repipe(tool, event_sw, &sample_sw, machine); } @@ -544,7 +544,7 @@ static void sig_handler(int sig __maybe_unused) static int perf_evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; const char *name = perf_evsel__name(evsel); if (!(attr->sample_type & sample_type)) { @@ -578,8 +578,8 @@ static void strip_init(struct perf_inject *inject) static bool has_tracking(struct evsel *evsel) { - return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm || - evsel->attr.task; + return evsel->core.attr.mmap || evsel->core.attr.mmap2 || evsel->core.attr.comm || + evsel->core.attr.task; } #define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \ @@ -603,8 +603,8 @@ static bool ok_to_remove(struct evlist *evlist, evlist__for_each_entry(evlist, evsel) { if (evsel->handler != drop_sample) { cnt += 1; - if ((evsel->attr.sample_type & COMPAT_MASK) == - (evsel_to_remove->attr.sample_type & COMPAT_MASK)) + if ((evsel->core.attr.sample_type & COMPAT_MASK) == + (evsel_to_remove->core.attr.sample_type & COMPAT_MASK)) ok = true; } } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 3370eba0d3f3..b9c58a5c1ba6 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1022,7 +1022,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) * This command processes KVM tracepoints from host only */ evlist__for_each_entry(evlist, pos) { - struct perf_event_attr *attr = &pos->attr; + struct perf_event_attr *attr = &pos->core.attr; /* make sure these *are* set */ perf_evsel__set_sample_bit(pos, TID); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 778e46417f6b..b7d2c27c4164 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -732,7 +732,7 @@ static int record__open(struct record *rec) pos->tracking = 0; pos = perf_evlist__last(evlist); pos->tracking = 1; - pos->attr.enable_on_exec = 1; + pos->core.attr.enable_on_exec = 1; } perf_evlist__config(evlist, opts, &callchain_param); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index d741c0aa2750..69133b35bbc1 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -345,7 +345,7 @@ static int perf_evsel__do_check_stype(struct evsel *evsel, enum perf_output_field field, bool allow_user_set) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; int type = output_type(attr->type); const char *evname; @@ -383,7 +383,7 @@ static int perf_evsel__check_stype(struct evsel *evsel, static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; if (perf_header__has_feat(&session->header, HEADER_STAT)) @@ -418,7 +418,7 @@ static int perf_evsel__check_attr(struct evsel *evsel, return -EINVAL; if (PRINT_FIELD(SYM) && - !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { + !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { pr_err("Display of symbols requested but neither sample IP nor " "sample address\navailable. Hence, no addresses to convert " "to symbols.\n"); @@ -430,7 +430,7 @@ static int perf_evsel__check_attr(struct evsel *evsel, return -EINVAL; } if (PRINT_FIELD(DSO) && - !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { + !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { pr_err("Display of DSO requested but no address to convert.\n"); return -EINVAL; } @@ -531,7 +531,7 @@ static int perf_session__check_output_opt(struct perf_session *session) if (evsel == NULL) continue; - set_print_ip_opts(&evsel->attr); + set_print_ip_opts(&evsel->core.attr); } if (!no_callchain) { @@ -558,7 +558,7 @@ static int perf_session__check_output_opt(struct perf_session *session) j = PERF_TYPE_TRACEPOINT; evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.type != j) + if (evsel->core.attr.type != j) continue; if (evsel__has_callchain(evsel)) { @@ -566,7 +566,7 @@ static int perf_session__check_output_opt(struct perf_session *session) output[j].fields |= PERF_OUTPUT_SYM; output[j].fields |= PERF_OUTPUT_SYMOFFSET; output[j].fields |= PERF_OUTPUT_DSO; - set_print_ip_opts(&evsel->attr); + set_print_ip_opts(&evsel->core.attr); goto out; } } @@ -617,7 +617,7 @@ static int perf_sample__fprintf_start(struct perf_sample *sample, struct evsel *evsel, u32 type, FILE *fp) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; unsigned long secs; unsigned long long nsecs; int printed = 0; @@ -1168,7 +1168,7 @@ static const char *resolve_branch_sym(struct perf_sample *sample, u64 *ip) { struct addr_location addr_al; - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; const char *name = NULL; if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { @@ -1195,7 +1195,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, struct thread *thread, struct addr_location *al, FILE *fp) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; size_t depth = thread_stack__depth(thread, sample->cpu); const char *name = NULL; static int spacing; @@ -1290,7 +1290,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, struct addr_location *al, struct machine *machine, FILE *fp) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; unsigned int type = output_type(attr->type); bool print_srcline_last = false; int printed = 0; @@ -1322,7 +1322,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, /* print branch_to information */ if (PRINT_FIELD(ADDR) || - ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && + ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) && !output[type].user_set)) { printed += fprintf(fp, " => "); printed += perf_sample__fprintf_addr(sample, thread, attr, fp); @@ -1595,7 +1595,7 @@ static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp) static int perf_sample__fprintf_synth(struct perf_sample *sample, struct evsel *evsel, FILE *fp) { - switch (evsel->attr.config) { + switch (evsel->core.attr.config) { case PERF_SYNTH_INTEL_PTWRITE: return perf_sample__fprintf_synth_ptwrite(sample, fp); case PERF_SYNTH_INTEL_MWAIT: @@ -1793,7 +1793,7 @@ static void process_event(struct perf_script *script, struct machine *machine) { struct thread *thread = al->thread; - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; unsigned int type = output_type(attr->type); struct evsel_script *es = evsel->priv; FILE *fp = es->fp; @@ -2046,18 +2046,18 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, } } - if (evsel->attr.type >= PERF_TYPE_MAX && - evsel->attr.type != PERF_TYPE_SYNTH) + if (evsel->core.attr.type >= PERF_TYPE_MAX && + evsel->core.attr.type != PERF_TYPE_SYNTH) return 0; evlist__for_each_entry(evlist, pos) { - if (pos->attr.type == evsel->attr.type && pos != evsel) + if (pos->core.attr.type == evsel->core.attr.type && pos != evsel) return 0; } - set_print_ip_opts(&evsel->attr); + set_print_ip_opts(&evsel->core.attr); - if (evsel->attr.sample_type) + if (evsel->core.attr.sample_type) err = perf_evsel__check_attr(evsel, scr->session); return err; @@ -2083,7 +2083,7 @@ static int process_comm_event(struct perf_tool *tool, if (perf_event__process_comm(tool, event, sample, machine) < 0) goto out; - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = 0; sample->tid = event->comm.tid; @@ -2121,7 +2121,7 @@ static int process_namespaces_event(struct perf_tool *tool, if (perf_event__process_namespaces(tool, event, sample, machine) < 0) goto out; - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = 0; sample->tid = event->namespaces.tid; @@ -2157,7 +2157,7 @@ static int process_fork_event(struct perf_tool *tool, return -1; } - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = event->fork.time; sample->tid = event->fork.tid; @@ -2189,7 +2189,7 @@ static int process_exit_event(struct perf_tool *tool, return -1; } - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = 0; sample->tid = event->fork.tid; @@ -2227,7 +2227,7 @@ static int process_mmap_event(struct perf_tool *tool, return -1; } - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = 0; sample->tid = event->mmap.tid; @@ -2261,7 +2261,7 @@ static int process_mmap2_event(struct perf_tool *tool, return -1; } - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = 0; sample->tid = event->mmap2.tid; @@ -2360,7 +2360,7 @@ process_bpf_events(struct perf_tool *tool __maybe_unused, if (machine__process_ksymbol(machine, event, sample) < 0) return -1; - if (!evsel->attr.sample_id_all) { + if (!evsel->core.attr.sample_id_all) { perf_event__fprintf(event, stdout); return 0; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3ba184f2e64f..8ad3643d61f9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -391,7 +391,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf static bool perf_evsel__should_store_id(struct evsel *counter) { - return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; + return STAT_RECORD || counter->core.attr.read_format & PERF_FORMAT_ID; } static bool is_target_alive(struct target *_target, diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index f5f70c83d304..7d6a6ecf4e02 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -557,7 +557,7 @@ static int process_sample_event(struct perf_tool *tool, { struct timechart *tchart = container_of(tool, struct timechart, tool); - if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { + if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) { if (!tchart->first_time || tchart->first_time > sample->time) tchart->first_time = sample->time; if (tchart->last_time < sample->time) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 3291eff13e28..54d06d271bfd 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -966,7 +966,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top, return 0; evlist__for_each_entry(evlist, counter) - counter->attr.write_backward = false; + counter->core.attr.write_backward = false; opts->overwrite = false; pr_debug2("fall back to non-overwrite mode\n"); return 1; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 06fcd8b1f160..abfd22ff1730 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2046,8 +2046,8 @@ static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel, struct callchain_cursor *cursor) { struct addr_location al; - int max_stack = evsel->attr.sample_max_stack ? - evsel->attr.sample_max_stack : + int max_stack = evsel->core.attr.sample_max_stack ? + evsel->core.attr.sample_max_stack : trace->max_stack; int err; @@ -2462,7 +2462,7 @@ static int trace__pgfault(struct trace *trace, if (ttrace == NULL) goto out_put; - if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) + if (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) ttrace->pfmaj++; else ttrace->pfmin++; @@ -2475,7 +2475,7 @@ static int trace__pgfault(struct trace *trace, trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output); fprintf(trace->output, "%sfault [", - evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? + evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? "maj" : "min"); print_location(trace->output, sample, &al, false, true); @@ -2523,7 +2523,7 @@ static void trace__set_base_time(struct trace *trace, * appears in our event stream (vfs_getname comes to mind). */ if (trace->base_time == 0 && !trace->full_time && - (evsel->attr.sample_type & PERF_SAMPLE_TIME)) + (evsel->core.attr.sample_type & PERF_SAMPLE_TIME)) trace->base_time = sample->time; } @@ -2682,7 +2682,7 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st trace__set_base_time(trace, evsel, sample); - if (evsel->attr.type == PERF_TYPE_TRACEPOINT && + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT && sample->raw_data == NULL) { fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", perf_evsel__name(evsel), sample->tid, @@ -2728,7 +2728,7 @@ static int trace__add_syscall_newtp(struct trace *trace) * leading to the syscall, allow overriding that for * debugging reasons using --kernel_syscall_callchains */ - sys_exit->attr.exclude_callchain_kernel = 1; + sys_exit->core.attr.exclude_callchain_kernel = 1; } trace->syscalls.events.sys_enter = sys_enter; @@ -3414,18 +3414,18 @@ static int trace__run(struct trace *trace, int argc, const char **argv) trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || evlist->threads->nr > 1 || - perf_evlist__first(evlist)->attr.inherit; + perf_evlist__first(evlist)->core.attr.inherit; /* - * Now that we already used evsel->attr to ask the kernel to setup the - * events, lets reuse evsel->attr.sample_max_stack as the limit in + * Now that we already used evsel->core.attr to ask the kernel to setup the + * events, lets reuse evsel->core.attr.sample_max_stack as the limit in * trace__resolve_callchain(), allowing per-event max-stack settings * to override an explicitly set --max-stack global setting. */ evlist__for_each_entry(evlist, evsel) { if (evsel__has_callchain(evsel) && - evsel->attr.sample_max_stack == 0) - evsel->attr.sample_max_stack = trace->max_stack; + evsel->core.attr.sample_max_stack == 0) + evsel->core.attr.sample_max_stack = trace->max_stack; } again: before = trace->nr_events; @@ -3618,10 +3618,10 @@ static int trace__replay(struct trace *trace) } evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.type == PERF_TYPE_SOFTWARE && - (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || - evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || - evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS)) + if (evsel->core.attr.type == PERF_TYPE_SOFTWARE && + (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || + evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || + evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS)) evsel->handler = trace__pgfault; } diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 9a87e867a7ec..17cba35becc7 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -3,7 +3,8 @@ #include #include -void perf_evsel__init(struct perf_evsel *evsel) +void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) { INIT_LIST_HEAD(&evsel->node); + evsel->attr = *attr; } diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 690943d0408a..c2e0bd104c94 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -2,8 +2,12 @@ #ifndef __LIBPERF_INTERNAL_EVSEL_H #define __LIBPERF_INTERNAL_EVSEL_H +#include +#include + struct perf_evsel { struct list_head node; + struct perf_event_attr attr; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index b4d074a3684b..295583b89f46 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -5,7 +5,9 @@ #include struct perf_evsel; +struct perf_event_attr; -LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel); +LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel, + struct perf_event_attr *attr); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 7b26be1dfb47..131bbeec62d2 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -642,9 +642,9 @@ static int do_test_code_reading(bool try_kcore) evsel = perf_evlist__first(evlist); - evsel->attr.comm = 1; - evsel->attr.disabled = 1; - evsel->attr.enable_on_exec = 0; + evsel->core.attr.comm = 1; + evsel->core.attr.disabled = 1; + evsel->core.attr.enable_on_exec = 0; ret = evlist__open(evlist); if (ret < 0) { diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 9238180416b0..165534f62036 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -36,7 +36,7 @@ static int attach__enable_on_exec(struct evlist *evlist) return err; } - evsel->attr.enable_on_exec = 1; + evsel->core.attr.enable_on_exec = 1; err = evlist__open(evlist); if (err < 0) { @@ -68,7 +68,7 @@ static int attach__current_disabled(struct evlist *evlist) return -1; } - evsel->attr.disabled = 1; + evsel->core.attr.disabled = 1; err = perf_evsel__open_per_thread(evsel, threads); if (err) { @@ -121,7 +121,7 @@ static int attach__cpu_disabled(struct evlist *evlist) return -1; } - evsel->attr.disabled = 1; + evsel->core.attr.disabled = 1; err = perf_evsel__open_per_cpu(evsel, cpus); if (err) { @@ -179,7 +179,7 @@ static int test_times(int (attach)(struct evlist *), } evsel = perf_evlist__last(evlist); - evsel->attr.read_format |= + evsel->core.attr.read_format |= PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 830fb3d7ea2e..4fc7b3b4e153 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -90,9 +90,9 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evsel = perf_evlist__first(evlist); - evsel->attr.comm = 1; - evsel->attr.disabled = 1; - evsel->attr.enable_on_exec = 0; + evsel->core.attr.comm = 1; + evsel->core.attr.disabled = 1; + evsel->core.attr.enable_on_exec = 0; if (evlist__open(evlist) < 0) { pr_debug("Unable to open dummy and cycles event\n"); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 72fbf55f4fc3..9d8eb43b12cb 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -79,7 +79,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse goto out_delete_evlist; } - evsels[i]->attr.wakeup_events = 1; + evsels[i]->core.attr.wakeup_events = 1; perf_evsel__set_sample_id(evsels[i], false); evlist__add(evlist, evsels[i]); diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 878140501edf..5b4a5a3dac50 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -50,10 +50,10 @@ static int test__checkevent_tracepoint(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); return 0; } @@ -66,11 +66,11 @@ static int test__checkevent_tracepoint_multi(struct evlist *evlist) evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("wrong type", - PERF_TYPE_TRACEPOINT == evsel->attr.type); + PERF_TYPE_TRACEPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); TEST_ASSERT_VAL("wrong sample_period", - 1 == evsel->attr.sample_period); + 1 == evsel->core.attr.sample_period); } return 0; } @@ -80,8 +80,8 @@ static int test__checkevent_raw(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config); return 0; } @@ -90,8 +90,8 @@ static int test__checkevent_numeric(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); return 0; } @@ -100,9 +100,9 @@ static int test__checkevent_symbolic_name(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); return 0; } @@ -111,19 +111,19 @@ static int test__checkevent_symbolic_name_config(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); /* * The period value gets configured within perf_evlist__config, * while this test executes only parse events method. */ TEST_ASSERT_VAL("wrong period", - 0 == evsel->attr.sample_period); + 0 == evsel->core.attr.sample_period); TEST_ASSERT_VAL("wrong config1", - 0 == evsel->attr.config1); + 0 == evsel->core.attr.config1); TEST_ASSERT_VAL("wrong config2", - 1 == evsel->attr.config2); + 1 == evsel->core.attr.config2); return 0; } @@ -132,9 +132,9 @@ static int test__checkevent_symbolic_alias(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); + PERF_COUNT_SW_PAGE_FAULTS == evsel->core.attr.config); return 0; } @@ -143,8 +143,8 @@ static int test__checkevent_genhw(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->core.attr.config); return 0; } @@ -153,12 +153,12 @@ static int test__checkevent_breakpoint(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == - evsel->attr.bp_type); + evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 == - evsel->attr.bp_len); + evsel->core.attr.bp_len); return 0; } @@ -167,11 +167,11 @@ static int test__checkevent_breakpoint_x(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_X == evsel->attr.bp_type); - TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len); + HW_BREAKPOINT_X == evsel->core.attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->core.attr.bp_len); return 0; } @@ -181,12 +181,12 @@ static int test__checkevent_breakpoint_r(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_R == evsel->attr.bp_type); + HW_BREAKPOINT_R == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); return 0; } @@ -196,12 +196,12 @@ static int test__checkevent_breakpoint_w(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", - HW_BREAKPOINT_W == evsel->attr.bp_type); + HW_BREAKPOINT_W == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); return 0; } @@ -211,12 +211,12 @@ static int test__checkevent_breakpoint_rw(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong type", - PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", - (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type); + (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", - HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + HW_BREAKPOINT_LEN_4 == evsel->core.attr.bp_len); return 0; } @@ -224,10 +224,10 @@ static int test__checkevent_tracepoint_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_tracepoint(evlist); } @@ -241,11 +241,11 @@ test__checkevent_tracepoint_multi_modifier(struct evlist *evlist) evlist__for_each_entry(evlist, evsel) { TEST_ASSERT_VAL("wrong exclude_user", - !evsel->attr.exclude_user); + !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); } return test__checkevent_tracepoint_multi(evlist); @@ -255,10 +255,10 @@ static int test__checkevent_raw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); return test__checkevent_raw(evlist); } @@ -267,10 +267,10 @@ static int test__checkevent_numeric_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); return test__checkevent_numeric(evlist); } @@ -279,10 +279,10 @@ static int test__checkevent_symbolic_name_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_symbolic_name(evlist); } @@ -291,8 +291,8 @@ static int test__checkevent_exclude_host_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); return test__checkevent_symbolic_name(evlist); } @@ -301,8 +301,8 @@ static int test__checkevent_exclude_guest_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); return test__checkevent_symbolic_name(evlist); } @@ -311,10 +311,10 @@ static int test__checkevent_symbolic_alias_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_symbolic_alias(evlist); } @@ -323,10 +323,10 @@ static int test__checkevent_genhw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); return test__checkevent_genhw(evlist); } @@ -335,13 +335,13 @@ static int test__checkevent_exclude_idle_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_symbolic_name(evlist); } @@ -350,13 +350,13 @@ static int test__checkevent_exclude_idle_modifier_1(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude idle", evsel->core.attr.exclude_idle); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_symbolic_name(evlist); } @@ -366,10 +366,10 @@ static int test__checkevent_breakpoint_modifier(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "mem:0:u")); @@ -380,10 +380,10 @@ static int test__checkevent_breakpoint_x_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "mem:0:x:k")); @@ -394,10 +394,10 @@ static int test__checkevent_breakpoint_r_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "mem:0:r:hp")); @@ -408,10 +408,10 @@ static int test__checkevent_breakpoint_w_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "mem:0:w:up")); @@ -422,10 +422,10 @@ static int test__checkevent_breakpoint_rw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "mem:0:rw:kp")); @@ -438,15 +438,15 @@ static int test__checkevent_pmu(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config); - TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1); - TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 10 == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1); + TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2); /* * The period value gets configured within perf_evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); + TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); return 0; } @@ -458,34 +458,34 @@ static int test__checkevent_list(struct evlist *evlist) TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); /* r1 */ - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); - TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1); - TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong config1", 0 == evsel->core.attr.config1); + TEST_ASSERT_VAL("wrong config2", 0 == evsel->core.attr.config2); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); /* syscalls:sys_enter_openat:k */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); /* 1:1:hp */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); return 0; } @@ -496,15 +496,15 @@ static int test__checkevent_pmu_name(struct evlist *evlist) /* cpu/config=1,name=krava/u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava")); /* cpu/config=2/u" */ evsel = perf_evsel__next(evsel); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "cpu/config=2/u")); @@ -517,29 +517,29 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) /* cpu/config=1,call-graph=fp,time,period=100000/ */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured * within perf_evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); + TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel)); - TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type)); + TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type)); /* cpu/config=2,call-graph=no,time=0,period=2000/ */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); /* * The period, time and callgraph value gets configured * within perf_evlist__config, * while this test executes only parse events method. */ - TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); + TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel)); - TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type)); + TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->core.attr.sample_type)); return 0; } @@ -549,14 +549,14 @@ static int test__checkevent_pmu_events(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); TEST_ASSERT_VAL("wrong exclude_user", - !evsel->attr.exclude_user); + !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned); + evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); return 0; } @@ -569,24 +569,24 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) /* pmu-event:u */ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); TEST_ASSERT_VAL("wrong exclude_user", - !evsel->attr.exclude_user); + !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned); + evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); /* cpu/pmu-event/u*/ evsel = perf_evsel__next(evsel); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); TEST_ASSERT_VAL("wrong exclude_user", - !evsel->attr.exclude_user); + !evsel->core.attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", - evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned); + evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); + TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); return 0; } @@ -643,15 +643,15 @@ static int test__group1(struct evlist *evlist) /* instructions:k */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); @@ -659,16 +659,16 @@ static int test__group1(struct evlist *evlist) /* cycles:upp */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); /* use of precise requires exclude_guest */ - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -685,15 +685,15 @@ static int test__group2(struct evlist *evlist) /* faults + :ku modifier */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_SW_PAGE_FAULTS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); @@ -701,30 +701,30 @@ static int test__group2(struct evlist *evlist) /* cache-references + :u modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_REFERENCES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); /* cycles:k */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -740,16 +740,16 @@ static int test__group3(struct evlist *evlist __maybe_unused) /* group1 syscalls:sys_enter_openat:H */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); TEST_ASSERT_VAL("wrong sample_type", - PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); - TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->core.attr.sample_period); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group1")); @@ -759,16 +759,16 @@ static int test__group3(struct evlist *evlist __maybe_unused) /* group1 cycles:kppp */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); /* use of precise requires exclude_guest */ - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 3); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); @@ -776,15 +776,15 @@ static int test__group3(struct evlist *evlist __maybe_unused) /* group2 cycles + G modifier */ evsel = leader = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group2")); @@ -794,29 +794,29 @@ static int test__group3(struct evlist *evlist __maybe_unused) /* group2 1:3 + G modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong type", 1 == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 3 == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); /* instructions:u */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -832,16 +832,16 @@ static int test__group4(struct evlist *evlist __maybe_unused) /* cycles:u + p */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); /* use of precise requires exclude_guest */ - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -850,16 +850,16 @@ static int test__group4(struct evlist *evlist __maybe_unused) /* instructions:kp + p */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); /* use of precise requires exclude_guest */ - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -876,15 +876,15 @@ static int test__group5(struct evlist *evlist __maybe_unused) /* cycles + G */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -893,30 +893,30 @@ static int test__group5(struct evlist *evlist __maybe_unused) /* instructions + G */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); /* cycles:G */ evsel = leader = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -925,29 +925,29 @@ static int test__group5(struct evlist *evlist __maybe_unused) /* instructions:G */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* cycles */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); return 0; @@ -962,15 +962,15 @@ static int test__group_gh1(struct evlist *evlist) /* cycles + :H group modifier */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -978,15 +978,15 @@ static int test__group_gh1(struct evlist *evlist) /* cache-misses:G + :H group modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); @@ -1002,15 +1002,15 @@ static int test__group_gh2(struct evlist *evlist) /* cycles + :G group modifier */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -1018,15 +1018,15 @@ static int test__group_gh2(struct evlist *evlist) /* cache-misses:H + :G group modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); @@ -1042,15 +1042,15 @@ static int test__group_gh3(struct evlist *evlist) /* cycles:G + :u group modifier */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -1058,15 +1058,15 @@ static int test__group_gh3(struct evlist *evlist) /* cache-misses:H + :u group modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); @@ -1082,15 +1082,15 @@ static int test__group_gh4(struct evlist *evlist) /* cycles:G + :uG group modifier */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); @@ -1098,15 +1098,15 @@ static int test__group_gh4(struct evlist *evlist) /* cache-misses:H + :uG group modifier */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); @@ -1121,44 +1121,44 @@ static int test__leader_sample1(struct evlist *evlist) /* cycles - sampling group leader */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); /* cache-misses - not sampling */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); /* branch-misses - not sampling */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); @@ -1174,30 +1174,30 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused) /* instructions - sampling group leader */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_INSTRUCTIONS == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); /* branch-misses - not sampling */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); - TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); + TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); @@ -1209,11 +1209,11 @@ static int test__checkevent_pinned_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip); + TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned); return test__checkevent_symbolic_name(evlist); } @@ -1226,25 +1226,25 @@ static int test__pinned_group(struct evlist *evlist) /* cycles - group leader */ evsel = leader = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config); + PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned); + TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned); /* cache-misses - can not be pinned, but will go on with the leader */ evsel = perf_evsel__next(evsel); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned); + PERF_COUNT_HW_CACHE_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); /* branch-misses - ditto */ evsel = perf_evsel__next(evsel); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config); - TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned); + PERF_COUNT_HW_BRANCH_MISSES == evsel->core.attr.config); + TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); return 0; } @@ -1254,12 +1254,12 @@ static int test__checkevent_breakpoint_len(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == - evsel->attr.bp_type); + evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 == - evsel->attr.bp_len); + evsel->core.attr.bp_len); return 0; } @@ -1269,12 +1269,12 @@ static int test__checkevent_breakpoint_len_w(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); - TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->core.attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->core.attr.config); TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == - evsel->attr.bp_type); + evsel->core.attr.bp_type); TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 == - evsel->attr.bp_len); + evsel->core.attr.bp_len); return 0; } @@ -1284,10 +1284,10 @@ test__checkevent_breakpoint_len_rw_modifier(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); - TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); + TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); + TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); + TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); return test__checkevent_breakpoint_rw(evlist); } @@ -1297,9 +1297,9 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist) struct evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); - TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", - PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config); + PERF_COUNT_SW_TASK_CLOCK == evsel->core.attr.config); return 0; } @@ -1360,9 +1360,9 @@ static int test__sym_event_slash(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); - TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); - TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); + TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); + TEST_ASSERT_VAL("wrong config", evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES); + TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); return 0; } @@ -1370,9 +1370,9 @@ static int test__sym_event_dc(struct evlist *evlist) { struct evsel *evsel = perf_evlist__first(evlist); - TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); - TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); - TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); + TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); + TEST_ASSERT_VAL("wrong config", evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES); + TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); return 0; } diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index a8cd3ed3c116..a8ca29fe172b 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -155,9 +155,11 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) { struct evsel evsel = { .needs_swap = false, - .attr = { - .sample_type = sample_type, - .read_format = read_format, + .core = { + . attr = { + .sample_type = sample_type, + .read_format = read_format, + }, }, }; union perf_event *event; @@ -221,10 +223,10 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) int err, ret = -1; if (sample_type & PERF_SAMPLE_REGS_USER) - evsel.attr.sample_regs_user = sample_regs; + evsel.core.attr.sample_regs_user = sample_regs; if (sample_type & PERF_SAMPLE_REGS_INTR) - evsel.attr.sample_regs_intr = sample_regs; + evsel.core.attr.sample_regs_intr = sample_regs; for (i = 0; i < sizeof(regs); i++) *(i + (u8 *)regs) = i & 0xfe; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 0935a5a1ecaa..dd07acced4af 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -420,8 +420,8 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ perf_evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->attr.freq = 0; - tracking_evsel->attr.sample_period = 1; + tracking_evsel->core.attr.freq = 0; + tracking_evsel->core.attr.sample_period = 1; perf_evsel__set_sample_bit(tracking_evsel, TIME); @@ -435,7 +435,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ } /* Check tracking event is tracking */ - if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) { + if (!tracking_evsel->core.attr.mmap || !tracking_evsel->core.attr.comm) { pr_debug("Tracking event not tracking\n"); goto out_err; } @@ -443,7 +443,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ /* Check non-tracking events are not tracking */ evlist__for_each_entry(evlist, evsel) { if (evsel != tracking_evsel) { - if (evsel->attr.mmap || evsel->attr.comm) { + if (evsel->core.attr.mmap || evsel->core.attr.comm) { pr_debug("Non-tracking event is tracking\n"); goto out_err; } diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 24257285844b..b0192ea636a7 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -84,16 +84,16 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused } evsel = perf_evlist__first(evlist); - evsel->attr.task = 1; + evsel->core.attr.task = 1; #ifdef __s390x__ - evsel->attr.sample_freq = 1000000; + evsel->core.attr.sample_freq = 1000000; #else - evsel->attr.sample_freq = 1; + evsel->core.attr.sample_freq = 1; #endif - evsel->attr.inherit = 0; - evsel->attr.watermark = 0; - evsel->attr.wakeup_events = 1; - evsel->attr.exclude_kernel = 1; + evsel->core.attr.inherit = 0; + evsel->core.attr.watermark = 0; + evsel->core.attr.wakeup_events = 1; + evsel->core.attr.exclude_kernel = 1; err = evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/ui/browsers/res_sample.c b/tools/perf/ui/browsers/res_sample.c index 7f3576deafd7..08897bd5eb0f 100644 --- a/tools/perf/ui/browsers/res_sample.c +++ b/tools/perf/ui/browsers/res_sample.c @@ -66,7 +66,7 @@ int res_sample_browse(struct res_sample *res_samples, int num_res, timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample); - attr_to_script(extra_format, &evsel->attr); + attr_to_script(extra_format, &evsel->core.attr); if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s", perf, diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index c0462457e9f9..04f9aff5621e 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c @@ -100,7 +100,7 @@ static int list_scripts(char *script_name, bool *custom, return -1; if (evsel) - attr_to_script(scriptc.extra_format, &evsel->attr); + attr_to_script(scriptc.extra_format, &evsel->core.attr); add_script_option("Show individual samples", "", &scriptc); add_script_option("Show individual samples with assembler", "-F +insn --xed", &scriptc); diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 9ec2841ddec4..843959f85d6f 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -2140,7 +2140,7 @@ static struct perf_pmu *perf_evsel__find_pmu(struct evsel *evsel) struct perf_pmu *pmu = NULL; while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (pmu->type == evsel->attr.type) + if (pmu->type == evsel->core.attr.type) break; } diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index b0696726ab76..4df8bdea14ac 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -1421,7 +1421,7 @@ apply_config_evsel_for_key(const char *name, int map_fd, void *pkey, return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM; } - attr = &evsel->attr; + attr = &evsel->core.attr; if (attr->inherit) { pr_debug("ERROR: Can't put inherit event into map %s\n", name); return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index c1df366f4519..ed6f7fd5b90b 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1230,7 +1230,7 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, int err; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == etm->pmu_type) { + if (evsel->core.attr.type == etm->pmu_type) { found = true; break; } @@ -1244,7 +1244,7 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, memset(&attr, 0, sizeof(struct perf_event_attr)); attr.size = sizeof(struct perf_event_attr); attr.type = PERF_TYPE_HARDWARE; - attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; + attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK; attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_PERIOD; if (etm->timeless_decoding) @@ -1252,13 +1252,13 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, else attr.sample_type |= PERF_SAMPLE_TIME; - attr.exclude_user = evsel->attr.exclude_user; - attr.exclude_kernel = evsel->attr.exclude_kernel; - attr.exclude_hv = evsel->attr.exclude_hv; - attr.exclude_host = evsel->attr.exclude_host; - attr.exclude_guest = evsel->attr.exclude_guest; - attr.sample_id_all = evsel->attr.sample_id_all; - attr.read_format = evsel->attr.read_format; + attr.exclude_user = evsel->core.attr.exclude_user; + attr.exclude_kernel = evsel->core.attr.exclude_kernel; + attr.exclude_hv = evsel->core.attr.exclude_hv; + attr.exclude_host = evsel->core.attr.exclude_host; + attr.exclude_guest = evsel->core.attr.exclude_guest; + attr.sample_id_all = evsel->core.attr.sample_id_all; + attr.read_format = evsel->core.attr.read_format; /* create new id val to be a fixed offset from evsel id */ id = evsel->id[0] + 1000000000; @@ -2303,7 +2303,7 @@ static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm) * with the time bit set. */ evlist__for_each_entry(evlist, evsel) { - if ((evsel->attr.sample_type & PERF_SAMPLE_TIME)) + if ((evsel->core.attr.sample_type & PERF_SAMPLE_TIME)) timeless_decoding = false; } diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index ca30bb25b3c5..0c268449959c 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -587,7 +587,7 @@ static int add_generic_values(struct ctf_writer *cw, struct evsel *evsel, struct perf_sample *sample) { - u64 type = evsel->attr.sample_type; + u64 type = evsel->core.attr.sample_type; int ret; /* @@ -757,7 +757,7 @@ static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, { int cpu = 0; - if (evsel->attr.sample_type & PERF_SAMPLE_CPU) + if (evsel->core.attr.sample_type & PERF_SAMPLE_CPU) cpu = sample->cpu; if (cpu > cw->stream_cnt) { @@ -795,7 +795,7 @@ static int process_sample_event(struct perf_tool *tool, struct bt_ctf_event_class *event_class; struct bt_ctf_event *event; int ret; - unsigned long type = evsel->attr.sample_type; + unsigned long type = evsel->core.attr.sample_type; if (WARN_ONCE(!priv, "Failed to setup all events.\n")) return 0; @@ -820,7 +820,7 @@ static int process_sample_event(struct perf_tool *tool, if (ret) return -1; - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { ret = add_tracepoint_values(cw, event_class, event, evsel, sample); if (ret) @@ -1087,7 +1087,7 @@ static int add_bpf_output_types(struct ctf_writer *cw, static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel, struct bt_ctf_event_class *event_class) { - u64 type = evsel->attr.sample_type; + u64 type = evsel->core.attr.sample_type; /* * missing: @@ -1157,7 +1157,7 @@ static int add_event(struct ctf_writer *cw, struct evsel *evsel) const char *name = perf_evsel__name(evsel); int ret; - pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); + pr("Adding event '%s' (type %d)\n", name, evsel->core.attr.type); event_class = bt_ctf_event_class_create(name); if (!event_class) @@ -1167,7 +1167,7 @@ static int add_event(struct ctf_writer *cw, struct evsel *evsel) if (ret) goto err; - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { ret = add_tracepoint_types(cw, evsel, event_class); if (ret) goto err; diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index dc2d4de772e3..701e9f814313 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -388,8 +388,8 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, } } - if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && - sample_addr_correlates_sym(&evsel->attr)) { + if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) && + sample_addr_correlates_sym(&evsel->core.attr)) { struct addr_location addr_al; thread__resolve(thread, &addr_al, sample); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index ce9f52215d60..ae75777a0ba4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -299,8 +299,8 @@ perf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id) struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == PERF_TYPE_TRACEPOINT && - (int)evsel->attr.config == id) + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT && + (int)evsel->core.attr.config == id) return evsel; } @@ -314,7 +314,7 @@ perf_evlist__find_tracepoint_by_name(struct evlist *evlist, struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && + if ((evsel->core.attr.type == PERF_TYPE_TRACEPOINT) && (strcmp(evsel->name, name) == 0)) return evsel; } @@ -529,13 +529,13 @@ int perf_evlist__id_add_fd(struct evlist *evlist, if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP) return -1; - if (!(evsel->attr.read_format & PERF_FORMAT_ID) || + if (!(evsel->core.attr.read_format & PERF_FORMAT_ID) || read(fd, &read_data, sizeof(read_data)) == -1) return -1; - if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) ++id_idx; - if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) ++id_idx; id = read_data[id_idx]; @@ -642,7 +642,7 @@ struct evsel *perf_evlist__event2evsel(struct evlist *evlist, if (evlist->core.nr_entries == 1) return first; - if (!first->attr.sample_id_all && + if (!first->core.attr.sample_id_all && event->header.type != PERF_RECORD_SAMPLE) return first; @@ -747,7 +747,7 @@ static bool perf_evlist__should_poll(struct evlist *evlist __maybe_unused, struct evsel *evsel) { - if (evsel->attr.write_backward) + if (evsel->core.attr.write_backward) return false; return true; } @@ -767,7 +767,7 @@ static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, int cpu; mp->prot = PROT_READ | PROT_WRITE; - if (evsel->attr.write_backward) { + if (evsel->core.attr.write_backward) { output = _output_overwrite; maps = evlist->overwrite_mmap; @@ -818,7 +818,7 @@ static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, return -1; } - if (evsel->attr.read_format & PERF_FORMAT_ID) { + if (evsel->core.attr.read_format & PERF_FORMAT_ID) { if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) return -1; @@ -1039,7 +1039,7 @@ int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, auxtrace_pages, auxtrace_overwrite); evlist__for_each_entry(evlist, evsel) { - if ((evsel->attr.read_format & PERF_FORMAT_ID) && + if ((evsel->core.attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL && perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) return -ENOMEM; @@ -1175,7 +1175,7 @@ int perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter) int err = 0; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) continue; err = perf_evsel__set_filter(evsel, filter); @@ -1245,7 +1245,7 @@ u64 __perf_evlist__combined_sample_type(struct evlist *evlist) return evlist->combined_sample_type; evlist__for_each_entry(evlist, evsel) - evlist->combined_sample_type |= evsel->attr.sample_type; + evlist->combined_sample_type |= evsel->core.attr.sample_type; return evlist->combined_sample_type; } @@ -1262,18 +1262,18 @@ u64 perf_evlist__combined_branch_type(struct evlist *evlist) u64 branch_type = 0; evlist__for_each_entry(evlist, evsel) - branch_type |= evsel->attr.branch_sample_type; + branch_type |= evsel->core.attr.branch_sample_type; return branch_type; } bool perf_evlist__valid_read_format(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist), *pos = first; - u64 read_format = first->attr.read_format; - u64 sample_type = first->attr.sample_type; + u64 read_format = first->core.attr.read_format; + u64 sample_type = first->core.attr.sample_type; evlist__for_each_entry(evlist, pos) { - if (read_format != pos->attr.read_format) + if (read_format != pos->core.attr.read_format) return false; } @@ -1289,7 +1289,7 @@ bool perf_evlist__valid_read_format(struct evlist *evlist) u64 perf_evlist__read_format(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); - return first->attr.read_format; + return first->core.attr.read_format; } u16 perf_evlist__id_hdr_size(struct evlist *evlist) @@ -1299,10 +1299,10 @@ u16 perf_evlist__id_hdr_size(struct evlist *evlist) u64 sample_type; u16 size = 0; - if (!first->attr.sample_id_all) + if (!first->core.attr.sample_id_all) goto out; - sample_type = first->attr.sample_type; + sample_type = first->core.attr.sample_type; if (sample_type & PERF_SAMPLE_TID) size += sizeof(data->tid) * 2; @@ -1330,7 +1330,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) struct evsel *first = perf_evlist__first(evlist), *pos = first; evlist__for_each_entry_continue(evlist, pos) { - if (first->attr.sample_id_all != pos->attr.sample_id_all) + if (first->core.attr.sample_id_all != pos->core.attr.sample_id_all) return false; } @@ -1340,7 +1340,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) bool perf_evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = perf_evlist__first(evlist); - return first->attr.sample_id_all; + return first->core.attr.sample_id_all; } void perf_evlist__set_selected(struct evlist *evlist, @@ -1620,14 +1620,14 @@ int perf_evlist__strerror_open(struct evlist *evlist, if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0) goto out_default; - if (first->attr.sample_freq < (u64)max_freq) + if (first->core.attr.sample_freq < (u64)max_freq) goto out_default; printed = scnprintf(buf, size, "Error:\t%s.\n" "Hint:\tCheck /proc/sys/kernel/perf_event_max_sample_rate.\n" "Hint:\tThe current value is %d and %" PRIu64 " is being requested.", - emsg, max_freq, first->attr.sample_freq); + emsg, max_freq, first->core.attr.sample_freq); break; } default: @@ -1782,7 +1782,7 @@ bool perf_evlist__exclude_kernel(struct evlist *evlist) struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (!evsel->attr.exclude_kernel) + if (!evsel->core.attr.exclude_kernel) return false; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 172bcc2e198f..089582e644d7 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -170,15 +170,15 @@ static int __perf_evsel__calc_is_pos(u64 sample_type) void perf_evsel__calc_id_pos(struct evsel *evsel) { - evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type); - evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); + evsel->id_pos = __perf_evsel__calc_id_pos(evsel->core.attr.sample_type); + evsel->is_pos = __perf_evsel__calc_is_pos(evsel->core.attr.sample_type); } void __perf_evsel__set_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit) { - if (!(evsel->attr.sample_type & bit)) { - evsel->attr.sample_type |= bit; + if (!(evsel->core.attr.sample_type & bit)) { + evsel->core.attr.sample_type |= bit; evsel->sample_size += sizeof(u64); perf_evsel__calc_id_pos(evsel); } @@ -187,8 +187,8 @@ void __perf_evsel__set_sample_bit(struct evsel *evsel, void __perf_evsel__reset_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit) { - if (evsel->attr.sample_type & bit) { - evsel->attr.sample_type &= ~bit; + if (evsel->core.attr.sample_type & bit) { + evsel->core.attr.sample_type &= ~bit; evsel->sample_size -= sizeof(u64); perf_evsel__calc_id_pos(evsel); } @@ -203,7 +203,7 @@ void perf_evsel__set_sample_id(struct evsel *evsel, } else { perf_evsel__set_sample_bit(evsel, ID); } - evsel->attr.read_format |= PERF_FORMAT_ID; + evsel->core.attr.read_format |= PERF_FORMAT_ID; } /** @@ -227,10 +227,9 @@ bool perf_evsel__is_function_event(struct evsel *evsel) void evsel__init(struct evsel *evsel, struct perf_event_attr *attr, int idx) { - perf_evsel__init(&evsel->core); + perf_evsel__init(&evsel->core, attr); evsel->idx = idx; evsel->tracking = !idx; - evsel->attr = *attr; evsel->leader = evsel; evsel->unit = ""; evsel->scale = 1.0; @@ -259,9 +258,9 @@ struct evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) evsel__init(evsel, attr, idx); if (perf_evsel__is_bpf_output(evsel)) { - evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), - evsel->attr.sample_period = 1; + evsel->core.attr.sample_period = 1; } if (perf_evsel__is_clock(evsel)) { @@ -387,7 +386,7 @@ static const char *__perf_evsel__hw_name(u64 config) static int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size) { int colon = 0, r = 0; - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; bool exclude_guest_default = false; #define MOD_PRINT(context, mod) do { \ @@ -422,7 +421,7 @@ static int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size) static int perf_evsel__hw_name(struct evsel *evsel, char *bf, size_t size) { - int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config)); + int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->core.attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } @@ -448,7 +447,7 @@ static const char *__perf_evsel__sw_name(u64 config) static int perf_evsel__sw_name(struct evsel *evsel, char *bf, size_t size) { - int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config)); + int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->core.attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } @@ -472,7 +471,7 @@ static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) static int perf_evsel__bp_name(struct evsel *evsel, char *bf, size_t size) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); } @@ -572,13 +571,13 @@ static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) static int perf_evsel__hw_cache_name(struct evsel *evsel, char *bf, size_t size) { - int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); + int ret = __perf_evsel__hw_cache_name(evsel->core.attr.config, bf, size); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); } static int perf_evsel__raw_name(struct evsel *evsel, char *bf, size_t size) { - int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); + int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->core.attr.config); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); } @@ -598,7 +597,7 @@ const char *perf_evsel__name(struct evsel *evsel) if (evsel->name) return evsel->name; - switch (evsel->attr.type) { + switch (evsel->core.attr.type) { case PERF_TYPE_RAW: perf_evsel__raw_name(evsel, bf, sizeof(bf)); break; @@ -628,7 +627,7 @@ const char *perf_evsel__name(struct evsel *evsel) default: scnprintf(bf, sizeof(bf), "unknown attr type: %d", - evsel->attr.type); + evsel->core.attr.type); break; } @@ -682,7 +681,7 @@ static void __perf_evsel__config_callchain(struct evsel *evsel, struct callchain_param *param) { bool function = perf_evsel__is_function_event(evsel); - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; perf_evsel__set_sample_bit(evsel, CALLCHAIN); @@ -748,7 +747,7 @@ static void perf_evsel__reset_callgraph(struct evsel *evsel, struct callchain_param *param) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; perf_evsel__reset_sample_bit(evsel, CALLCHAIN); if (param->record_mode == CALLCHAIN_LBR) { @@ -767,7 +766,7 @@ static void apply_config_terms(struct evsel *evsel, { struct perf_evsel_config_term *term; struct list_head *config_terms = &evsel->config_terms; - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; /* callgraph default */ struct callchain_param param = { .record_mode = callchain_param.record_mode, @@ -880,7 +879,7 @@ static void apply_config_terms(struct evsel *evsel, if (sample_address) { perf_evsel__set_sample_bit(evsel, ADDR); perf_evsel__set_sample_bit(evsel, DATA_SRC); - evsel->attr.mmap_data = track; + evsel->core.attr.mmap_data = track; } perf_evsel__config_callchain(evsel, opts, ¶m); } @@ -889,8 +888,8 @@ static void apply_config_terms(struct evsel *evsel, static bool is_dummy_event(struct evsel *evsel) { - return (evsel->attr.type == PERF_TYPE_SOFTWARE) && - (evsel->attr.config == PERF_COUNT_SW_DUMMY); + return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) && + (evsel->core.attr.config == PERF_COUNT_SW_DUMMY); } /* @@ -925,7 +924,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, struct callchain_param *callchain) { struct evsel *leader = evsel->leader; - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; int track = evsel->tracking; bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; @@ -986,14 +985,14 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, * event to follow the master sample_type to ease up * report. */ - attr->sample_type = leader->attr.sample_type; + attr->sample_type = leader->core.attr.sample_type; } if (opts->no_samples) attr->sample_freq = 0; if (opts->inherit_stat) { - evsel->attr.read_format |= + evsel->core.attr.read_format |= PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; @@ -1011,7 +1010,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, * fault handler and its overall trickiness nature. */ if (perf_evsel__is_function_event(evsel)) - evsel->attr.exclude_callchain_user = 1; + evsel->core.attr.exclude_callchain_user = 1; if (callchain && callchain->enabled && !evsel->no_aux_samples) perf_evsel__config_callchain(evsel, opts, callchain); @@ -1080,7 +1079,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, perf_evsel__set_sample_bit(evsel, TRANSACTION); if (opts->running_time) { - evsel->attr.read_format |= + evsel->core.attr.read_format |= PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; } @@ -1127,7 +1126,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, } if (evsel->own_cpus || evsel->unit) - evsel->attr.read_format |= PERF_FORMAT_ID; + evsel->core.attr.read_format |= PERF_FORMAT_ID; /* * Apply event specific term settings, @@ -1382,7 +1381,7 @@ void perf_counts_values__scale(struct perf_counts_values *count, static int perf_evsel__read_size(struct evsel *evsel) { - u64 read_format = evsel->attr.read_format; + u64 read_format = evsel->core.attr.read_format; int entry = sizeof(u64); /* value */ int size = 0; int nr = 1; @@ -1448,7 +1447,7 @@ static int perf_evsel__process_group_data(struct evsel *leader, int cpu, int thread, u64 *data) { - u64 read_format = leader->attr.read_format; + u64 read_format = leader->core.attr.read_format; struct sample_read_value *v; u64 nr, ena = 0, run = 0, i; @@ -1486,7 +1485,7 @@ static int perf_evsel__read_group(struct evsel *leader, int cpu, int thread) { struct perf_stat_evsel *ps = leader->stats; - u64 read_format = leader->attr.read_format; + u64 read_format = leader->core.attr.read_format; int size = perf_evsel__read_size(leader); u64 *data = ps->group_data; @@ -1515,7 +1514,7 @@ perf_evsel__read_group(struct evsel *leader, int cpu, int thread) int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread) { - u64 read_format = evsel->attr.read_format; + u64 read_format = evsel->core.attr.read_format; if (read_format & PERF_FORMAT_GROUP) return perf_evsel__read_group(evsel, cpu, thread); @@ -1793,14 +1792,14 @@ static int perf_event_open(struct evsel *evsel, pid_t pid, int cpu, int group_fd, unsigned long flags) { - int precise_ip = evsel->attr.precise_ip; + int precise_ip = evsel->core.attr.precise_ip; int fd; while (1) { pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", pid, cpu, group_fd, flags); - fd = sys_perf_event_open(&evsel->attr, pid, cpu, group_fd, flags); + fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags); if (fd >= 0) break; @@ -1812,15 +1811,15 @@ static int perf_event_open(struct evsel *evsel, * We tried all the precise_ip values, and it's * still failing, so leave it to standard fallback. */ - if (!evsel->attr.precise_ip) { - evsel->attr.precise_ip = precise_ip; + if (!evsel->core.attr.precise_ip) { + evsel->core.attr.precise_ip = precise_ip; break; } pr_debug2("\nsys_perf_event_open failed, error %d\n", -ENOTSUP); - evsel->attr.precise_ip--; - pr_debug2("decreasing precise_ip by one (%d)\n", evsel->attr.precise_ip); - display_attr(&evsel->attr); + evsel->core.attr.precise_ip--; + pr_debug2("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip); + display_attr(&evsel->core.attr); } return fd; @@ -1834,7 +1833,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, int pid = -1, err; enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; - if (perf_missing_features.write_backward && evsel->attr.write_backward) + if (perf_missing_features.write_backward && evsel->core.attr.write_backward) return -EINVAL; if (cpus == NULL) { @@ -1877,31 +1876,31 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, fallback_missing_features: if (perf_missing_features.clockid_wrong) - evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */ + evsel->core.attr.clockid = CLOCK_MONOTONIC; /* should always work */ if (perf_missing_features.clockid) { - evsel->attr.use_clockid = 0; - evsel->attr.clockid = 0; + evsel->core.attr.use_clockid = 0; + evsel->core.attr.clockid = 0; } if (perf_missing_features.cloexec) flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; if (perf_missing_features.mmap2) - evsel->attr.mmap2 = 0; + evsel->core.attr.mmap2 = 0; if (perf_missing_features.exclude_guest) - evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; + evsel->core.attr.exclude_guest = evsel->core.attr.exclude_host = 0; if (perf_missing_features.lbr_flags) - evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | + evsel->core.attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | PERF_SAMPLE_BRANCH_NO_CYCLES); - if (perf_missing_features.group_read && evsel->attr.inherit) - evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID); + if (perf_missing_features.group_read && evsel->core.attr.inherit) + evsel->core.attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID); if (perf_missing_features.ksymbol) - evsel->attr.ksymbol = 0; + evsel->core.attr.ksymbol = 0; if (perf_missing_features.bpf_event) - evsel->attr.bpf_event = 0; + evsel->core.attr.bpf_event = 0; retry_sample_id: if (perf_missing_features.sample_id_all) - evsel->attr.sample_id_all = 0; + evsel->core.attr.sample_id_all = 0; - display_attr(&evsel->attr); + display_attr(&evsel->core.attr); for (cpu = 0; cpu < cpus->nr; cpu++) { @@ -2008,23 +2007,23 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, * Must probe features in the order they were added to the * perf_event_attr interface. */ - if (!perf_missing_features.bpf_event && evsel->attr.bpf_event) { + if (!perf_missing_features.bpf_event && evsel->core.attr.bpf_event) { perf_missing_features.bpf_event = true; pr_debug2("switching off bpf_event\n"); goto fallback_missing_features; - } else if (!perf_missing_features.ksymbol && evsel->attr.ksymbol) { + } else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) { perf_missing_features.ksymbol = true; pr_debug2("switching off ksymbol\n"); goto fallback_missing_features; - } else if (!perf_missing_features.write_backward && evsel->attr.write_backward) { + } else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) { perf_missing_features.write_backward = true; pr_debug2("switching off write_backward\n"); goto out_close; - } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { + } else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) { perf_missing_features.clockid_wrong = true; pr_debug2("switching off clockid\n"); goto fallback_missing_features; - } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { + } else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) { perf_missing_features.clockid = true; pr_debug2("switching off use_clockid\n"); goto fallback_missing_features; @@ -2032,12 +2031,12 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, perf_missing_features.cloexec = true; pr_debug2("switching off cloexec flag\n"); goto fallback_missing_features; - } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { + } else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) { perf_missing_features.mmap2 = true; pr_debug2("switching off mmap2\n"); goto fallback_missing_features; } else if (!perf_missing_features.exclude_guest && - (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { + (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) { perf_missing_features.exclude_guest = true; pr_debug2("switching off exclude_guest, exclude_host\n"); goto fallback_missing_features; @@ -2046,15 +2045,15 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, pr_debug2("switching off sample_id_all\n"); goto retry_sample_id; } else if (!perf_missing_features.lbr_flags && - (evsel->attr.branch_sample_type & + (evsel->core.attr.branch_sample_type & (PERF_SAMPLE_BRANCH_NO_CYCLES | PERF_SAMPLE_BRANCH_NO_FLAGS))) { perf_missing_features.lbr_flags = true; pr_debug2("switching off branch sample type no (cycles/flags)\n"); goto fallback_missing_features; } else if (!perf_missing_features.group_read && - evsel->attr.inherit && - (evsel->attr.read_format & PERF_FORMAT_GROUP) && + evsel->core.attr.inherit && + (evsel->core.attr.read_format & PERF_FORMAT_GROUP) && perf_evsel__is_group_leader(evsel)) { perf_missing_features.group_read = true; pr_debug2("switching off group read\n"); @@ -2100,7 +2099,7 @@ static int perf_evsel__parse_id_sample(const struct evsel *evsel, const union perf_event *event, struct perf_sample *sample) { - u64 type = evsel->attr.sample_type; + u64 type = evsel->core.attr.sample_type; const u64 *array = event->sample.array; bool swapped = evsel->needs_swap; union u64_swap u; @@ -2189,7 +2188,7 @@ perf_event__check_size(union perf_event *event, unsigned int sample_size) int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, struct perf_sample *data) { - u64 type = evsel->attr.sample_type; + u64 type = evsel->core.attr.sample_type; bool swapped = evsel->needs_swap; const u64 *array; u16 max_size = event->header.size; @@ -2205,14 +2204,14 @@ int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, memset(data, 0, sizeof(*data)); data->cpu = data->pid = data->tid = -1; data->stream_id = data->id = data->time = -1ULL; - data->period = evsel->attr.sample_period; + data->period = evsel->core.attr.sample_period; data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; data->misc = event->header.misc; data->id = -1ULL; data->data_src = PERF_MEM_DATA_SRC_NONE; if (event->header.type != PERF_RECORD_SAMPLE) { - if (!evsel->attr.sample_id_all) + if (!evsel->core.attr.sample_id_all) return 0; return perf_evsel__parse_id_sample(evsel, event, data); } @@ -2285,7 +2284,7 @@ int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, } if (type & PERF_SAMPLE_READ) { - u64 read_format = evsel->attr.read_format; + u64 read_format = evsel->core.attr.read_format; OVERFLOW_CHECK_u64(array); if (read_format & PERF_FORMAT_GROUP) @@ -2390,7 +2389,7 @@ int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, array++; if (data->user_regs.abi) { - u64 mask = evsel->attr.sample_regs_user; + u64 mask = evsel->core.attr.sample_regs_user; sz = hweight64(mask) * sizeof(u64); OVERFLOW_CHECK(array, sz, max_size); @@ -2446,7 +2445,7 @@ int perf_evsel__parse_sample(struct evsel *evsel, union perf_event *event, array++; if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { - u64 mask = evsel->attr.sample_regs_intr; + u64 mask = evsel->core.attr.sample_regs_intr; sz = hweight64(mask) * sizeof(u64); OVERFLOW_CHECK(array, sz, max_size); @@ -2469,7 +2468,7 @@ int perf_evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, u64 *timestamp) { - u64 type = evsel->attr.sample_type; + u64 type = evsel->core.attr.sample_type; const u64 *array; if (!(type & PERF_SAMPLE_TIME)) @@ -2480,7 +2479,7 @@ int perf_evsel__parse_sample_timestamp(struct evsel *evsel, .time = -1ULL, }; - if (!evsel->attr.sample_id_all) + if (!evsel->core.attr.sample_id_all) return -1; if (perf_evsel__parse_id_sample(evsel, event, &data)) return -1; @@ -2866,8 +2865,8 @@ bool perf_evsel__fallback(struct evsel *evsel, int err, int paranoid; if ((err == ENOENT || err == ENXIO || err == ENODEV) && - evsel->attr.type == PERF_TYPE_HARDWARE && - evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { + evsel->core.attr.type == PERF_TYPE_HARDWARE && + evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES) { /* * If it's cycles then fall back to hrtimer based * cpu-clock-tick sw counter, which is always available even if @@ -2879,12 +2878,12 @@ bool perf_evsel__fallback(struct evsel *evsel, int err, scnprintf(msg, msgsize, "%s", "The cycles event is not supported, trying to fall back to cpu-clock-ticks"); - evsel->attr.type = PERF_TYPE_SOFTWARE; - evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; + evsel->core.attr.type = PERF_TYPE_SOFTWARE; + evsel->core.attr.config = PERF_COUNT_SW_CPU_CLOCK; zfree(&evsel->name); return true; - } else if (err == EACCES && !evsel->attr.exclude_kernel && + } else if (err == EACCES && !evsel->core.attr.exclude_kernel && (paranoid = perf_event_paranoid()) > 1) { const char *name = perf_evsel__name(evsel); char *new_name; @@ -2903,7 +2902,7 @@ bool perf_evsel__fallback(struct evsel *evsel, int err, evsel->name = new_name; scnprintf(msg, msgsize, "kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples", paranoid); - evsel->attr.exclude_kernel = 1; + evsel->core.attr.exclude_kernel = 1; return true; } @@ -3000,15 +2999,15 @@ int perf_evsel__open_strerror(struct evsel *evsel, struct target *target, "No such device - did you specify an out-of-range profile CPU?"); break; case EOPNOTSUPP: - if (evsel->attr.sample_period != 0) + if (evsel->core.attr.sample_period != 0) return scnprintf(msg, size, "%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'", perf_evsel__name(evsel)); - if (evsel->attr.precise_ip) + if (evsel->core.attr.precise_ip) return scnprintf(msg, size, "%s", "\'precise\' request may not be supported. Try removing 'p' modifier."); #if defined(__i386__) || defined(__x86_64__) - if (evsel->attr.type == PERF_TYPE_HARDWARE) + if (evsel->core.attr.type == PERF_TYPE_HARDWARE) return scnprintf(msg, size, "%s", "No hardware sampling interrupt available.\n"); #endif @@ -3020,7 +3019,7 @@ int perf_evsel__open_strerror(struct evsel *evsel, struct target *target, "We found oprofile daemon running, please stop it and try again."); break; case EINVAL: - if (evsel->attr.write_backward && perf_missing_features.write_backward) + if (evsel->core.attr.write_backward && perf_missing_features.write_backward) return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel."); if (perf_missing_features.clockid) return scnprintf(msg, size, "clockid feature not supported."); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d74cac6fe306..43f66158de3b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -103,7 +103,6 @@ struct bpf_object; struct evsel { struct perf_evsel core; struct evlist *evlist; - struct perf_event_attr attr; char *filter; struct xyarray *fd; struct xyarray *sample_id; @@ -327,21 +326,21 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name); #define perf_evsel__match(evsel, t, c) \ - (evsel->attr.type == PERF_TYPE_##t && \ - evsel->attr.config == PERF_COUNT_##c) + (evsel->core.attr.type == PERF_TYPE_##t && \ + evsel->core.attr.config == PERF_COUNT_##c) static inline bool perf_evsel__match2(struct evsel *e1, struct evsel *e2) { - return (e1->attr.type == e2->attr.type) && - (e1->attr.config == e2->attr.config); + return (e1->core.attr.type == e2->core.attr.type) && + (e1->core.attr.config == e2->core.attr.config); } #define perf_evsel__cmp(a, b) \ ((a) && \ (b) && \ - (a)->attr.type == (b)->attr.type && \ - (a)->attr.config == (b)->attr.config) + (a)->core.attr.type == (b)->core.attr.type && \ + (a)->core.attr.config == (b)->core.attr.config) int perf_evsel__read(struct evsel *evsel, int cpu, int thread, struct perf_counts_values *count); @@ -490,12 +489,12 @@ for ((_evsel) = _leader; \ static inline bool perf_evsel__has_branch_callstack(const struct evsel *evsel) { - return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; + return evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; } static inline bool evsel__has_callchain(const struct evsel *evsel) { - return (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0; + return (evsel->core.attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0; } typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 1fddb7da4b51..3466eca34a00 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -60,22 +60,22 @@ int perf_evsel__fprintf(struct evsel *evsel, printed += fprintf(fp, "%s", perf_evsel__name(evsel)); if (details->verbose) { - printed += perf_event_attr__fprintf(fp, &evsel->attr, + printed += perf_event_attr__fprintf(fp, &evsel->core.attr, __print_attr__fprintf, &first); } else if (details->freq) { const char *term = "sample_freq"; - if (!evsel->attr.freq) + if (!evsel->core.attr.freq) term = "sample_period"; printed += comma_fprintf(fp, &first, " %s=%" PRIu64, - term, (u64)evsel->attr.sample_freq); + term, (u64)evsel->core.attr.sample_freq); } if (details->trace_fields) { struct tep_format_field *field; - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { printed += comma_fprintf(fp, &first, " (not a tracepoint)"); goto out; } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 141de4425100..d81afe56392c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -488,13 +488,13 @@ static int write_event_desc(struct feat_fd *ff, /* * size of perf_event_attr struct */ - sz = (u32)sizeof(evsel->attr); + sz = (u32)sizeof(evsel->core.attr); ret = do_write(ff, &sz, sizeof(sz)); if (ret < 0) return ret; evlist__for_each_entry(evlist, evsel) { - ret = do_write(ff, &evsel->attr, sz); + ret = do_write(ff, &evsel->core.attr, sz); if (ret < 0) return ret; /* @@ -1575,7 +1575,7 @@ static void free_event_desc(struct evsel *events) if (!events) return; - for (evsel = events; evsel->attr.size; evsel++) { + for (evsel = events; evsel->core.attr.size; evsel++) { zfree(&evsel->name); zfree(&evsel->id); } @@ -1603,12 +1603,12 @@ static struct evsel *read_event_desc(struct feat_fd *ff) if (!buf) goto error; - /* the last event terminates with evsel->attr.size == 0: */ + /* the last event terminates with evsel->core.attr.size == 0: */ events = calloc(nre + 1, sizeof(*events)); if (!events) goto error; - msz = sizeof(evsel->attr); + msz = sizeof(evsel->core.attr); if (sz < msz) msz = sz; @@ -1625,7 +1625,7 @@ static struct evsel *read_event_desc(struct feat_fd *ff) if (ff->ph->needs_swap) perf_event__attr_swap(buf); - memcpy(&evsel->attr, buf, msz); + memcpy(&evsel->core.attr, buf, msz); if (do_read_u32(ff, &nr)) goto error; @@ -1683,7 +1683,7 @@ static void print_event_desc(struct feat_fd *ff, FILE *fp) return; } - for (evsel = events; evsel->attr.size; evsel++) { + for (evsel = events; evsel->core.attr.size; evsel++) { fprintf(fp, "# event : name = %s, ", evsel->name); if (evsel->ids) { @@ -1696,7 +1696,7 @@ static void print_event_desc(struct feat_fd *ff, FILE *fp) fprintf(fp, " }"); } - perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL); + perf_event_attr__fprintf(fp, &evsel->core.attr, __desc_attr__fprintf, NULL); fputc('\n', fp); } @@ -2138,7 +2138,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused) ff->events = events; } - for (evsel = events; evsel->attr.size; evsel++) + for (evsel = events; evsel->core.attr.size; evsel++) perf_evlist__set_event_name(session->evlist, evsel); if (!session->data->is_pipe) @@ -3071,7 +3071,7 @@ int perf_session__write_header(struct perf_session *session, evlist__for_each_entry(evlist, evsel) { f_attr = (struct perf_file_attr){ - .attr = evsel->attr, + .attr = evsel->core.attr, .ids = { .offset = evsel->id_offset, .size = evsel->ids * sizeof(u64), @@ -3494,9 +3494,9 @@ static int perf_evsel__prepare_tracepoint_event(struct evsel *evsel, return -1; } - event = tep_find_event(pevent, evsel->attr.config); + event = tep_find_event(pevent, evsel->core.attr.config); if (event == NULL) { - pr_debug("cannot find event format for %d\n", (int)evsel->attr.config); + pr_debug("cannot find event format for %d\n", (int)evsel->core.attr.config); return -1; } @@ -3517,7 +3517,7 @@ static int perf_evlist__prepare_tracepoint_events(struct evlist *evlist, struct evsel *pos; evlist__for_each_entry(evlist, pos) { - if (pos->attr.type == PERF_TYPE_TRACEPOINT && + if (pos->core.attr.type == PERF_TYPE_TRACEPOINT && perf_evsel__prepare_tracepoint_event(pos, pevent)) return -1; } @@ -3928,7 +3928,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, int err = 0; evlist__for_each_entry(evlist, evsel) { - err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, + err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->ids, evsel->id, process); if (err) { pr_debug("failed to create perf header attribute\n"); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index bb5437f549b6..821e0fe6cf26 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2638,7 +2638,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh enable_ref = true; if (show_freq) - scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); + scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->core.attr.sample_freq); nr_samples = convert_unit(nr_samples, &unit); printed = scnprintf(bf, size, diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 849a5b713b04..7eb9e6dc27dd 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -768,7 +768,7 @@ static int intel_bts_synth_events(struct intel_bts *bts, int err; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == bts->pmu_type && evsel->ids) { + if (evsel->core.attr.type == bts->pmu_type && evsel->ids) { found = true; break; } @@ -782,18 +782,18 @@ static int intel_bts_synth_events(struct intel_bts *bts, memset(&attr, 0, sizeof(struct perf_event_attr)); attr.size = sizeof(struct perf_event_attr); attr.type = PERF_TYPE_HARDWARE; - attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; + attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK; attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_PERIOD; attr.sample_type &= ~(u64)PERF_SAMPLE_TIME; attr.sample_type &= ~(u64)PERF_SAMPLE_CPU; - attr.exclude_user = evsel->attr.exclude_user; - attr.exclude_kernel = evsel->attr.exclude_kernel; - attr.exclude_hv = evsel->attr.exclude_hv; - attr.exclude_host = evsel->attr.exclude_host; - attr.exclude_guest = evsel->attr.exclude_guest; - attr.sample_id_all = evsel->attr.sample_id_all; - attr.read_format = evsel->attr.read_format; + attr.exclude_user = evsel->core.attr.exclude_user; + attr.exclude_kernel = evsel->core.attr.exclude_kernel; + attr.exclude_hv = evsel->core.attr.exclude_hv; + attr.exclude_host = evsel->core.attr.exclude_host; + attr.exclude_guest = evsel->core.attr.exclude_guest; + attr.sample_id_all = evsel->core.attr.sample_id_all; + attr.read_format = evsel->core.attr.read_format; id = evsel->id[0] + 1000000000; if (!id) diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index c88e3d1ee9c7..4c52204868d8 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -726,8 +726,8 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt) struct evsel *evsel; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, NULL) && - !evsel->attr.exclude_kernel) + if (intel_pt_get_config(pt, &evsel->core.attr, NULL) && + !evsel->core.attr.exclude_kernel) return false; } return true; @@ -742,7 +742,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt) return true; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, &config) && + if (intel_pt_get_config(pt, &evsel->core.attr, &config) && (config & pt->noretcomp_bit)) return false; } @@ -755,7 +755,7 @@ static bool intel_pt_branch_enable(struct intel_pt *pt) u64 config; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, &config) && + if (intel_pt_get_config(pt, &evsel->core.attr, &config) && (config & 1) && !(config & 0x2000)) return false; } @@ -775,7 +775,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt) config >>= 1; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, &config)) + if (intel_pt_get_config(pt, &evsel->core.attr, &config)) return (config & pt->mtc_freq_bits) >> shift; } return 0; @@ -791,9 +791,9 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt) return true; evlist__for_each_entry(pt->session->evlist, evsel) { - if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) + if (!(evsel->core.attr.sample_type & PERF_SAMPLE_TIME)) return true; - if (intel_pt_get_config(pt, &evsel->attr, &config)) { + if (intel_pt_get_config(pt, &evsel->core.attr, &config)) { if (config & pt->tsc_bit) timeless_decoding = false; else @@ -808,8 +808,8 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt) struct evsel *evsel; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, NULL) && - !evsel->attr.exclude_kernel) + if (intel_pt_get_config(pt, &evsel->core.attr, NULL) && + !evsel->core.attr.exclude_kernel) return true; } return false; @@ -825,7 +825,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt) return false; evlist__for_each_entry(pt->session->evlist, evsel) { - if (intel_pt_get_config(pt, &evsel->attr, &config)) { + if (intel_pt_get_config(pt, &evsel->core.attr, &config)) { if (config & pt->tsc_bit) have_tsc = true; else @@ -1703,7 +1703,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq) union perf_event *event = ptq->event_buf; struct intel_pt *pt = ptq->pt; struct evsel *evsel = pt->pebs_evsel; - u64 sample_type = evsel->attr.sample_type; + u64 sample_type = evsel->core.attr.sample_type; u64 id = evsel->id[0]; u8 cpumode; @@ -1715,8 +1715,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq) sample.id = id; sample.stream_id = id; - if (!evsel->attr.freq) - sample.period = evsel->attr.sample_period; + if (!evsel->core.attr.freq) + sample.period = evsel->core.attr.sample_period; /* No support for non-zero CS base */ if (items->has_ip) @@ -1757,7 +1757,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq) if (sample_type & PERF_SAMPLE_REGS_INTR && items->mask[INTEL_PT_GP_REGS_POS]) { u64 regs[sizeof(sample.intr_regs.mask)]; - u64 regs_mask = evsel->attr.sample_regs_intr; + u64 regs_mask = evsel->core.attr.sample_regs_intr; u64 *pos; sample.intr_regs.abi = items->is_32_bit ? @@ -2734,7 +2734,7 @@ static struct evsel *intel_pt_evsel(struct intel_pt *pt, struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type == pt->pmu_type && evsel->ids) + if (evsel->core.attr.type == pt->pmu_type && evsel->ids) return evsel; } @@ -2758,7 +2758,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, memset(&attr, 0, sizeof(struct perf_event_attr)); attr.size = sizeof(struct perf_event_attr); attr.type = PERF_TYPE_HARDWARE; - attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; + attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK; attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_PERIOD; if (pt->timeless_decoding) @@ -2767,13 +2767,13 @@ static int intel_pt_synth_events(struct intel_pt *pt, attr.sample_type |= PERF_SAMPLE_TIME; if (!pt->per_cpu_mmaps) attr.sample_type &= ~(u64)PERF_SAMPLE_CPU; - attr.exclude_user = evsel->attr.exclude_user; - attr.exclude_kernel = evsel->attr.exclude_kernel; - attr.exclude_hv = evsel->attr.exclude_hv; - attr.exclude_host = evsel->attr.exclude_host; - attr.exclude_guest = evsel->attr.exclude_guest; - attr.sample_id_all = evsel->attr.sample_id_all; - attr.read_format = evsel->attr.read_format; + attr.exclude_user = evsel->core.attr.exclude_user; + attr.exclude_kernel = evsel->core.attr.exclude_kernel; + attr.exclude_hv = evsel->core.attr.exclude_hv; + attr.exclude_host = evsel->core.attr.exclude_host; + attr.exclude_guest = evsel->core.attr.exclude_guest; + attr.sample_id_all = evsel->core.attr.sample_id_all; + attr.read_format = evsel->core.attr.read_format; id = evsel->id[0] + 1000000000; if (!id) @@ -2857,7 +2857,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, id += 1; } - if (pt->synth_opts.pwr_events && (evsel->attr.config & 0x10)) { + if (pt->synth_opts.pwr_events && (evsel->core.attr.config & 0x10)) { attr.config = PERF_SYNTH_INTEL_MWAIT; err = intel_pt_synth_event(session, "mwait", &attr, id); if (err) @@ -2913,7 +2913,7 @@ static bool intel_pt_find_switch(struct evlist *evlist) struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.context_switch) + if (evsel->core.attr.context_switch) return true; } diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 8df60703411a..bbeac4f66402 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -124,7 +124,7 @@ jit_validate_events(struct perf_session *session) * check that all events use CLOCK_MONOTONIC */ evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) + if (evsel->core.attr.use_clockid == 0 || evsel->core.attr.clockid != CLOCK_MONOTONIC) return -1; } return 0; @@ -779,7 +779,7 @@ jit_process(struct perf_session *session, * perf sets the same sample type to all events as of now */ first = perf_evlist__first(session->evlist); - jd.sample_type = first->attr.sample_type; + jd.sample_type = first->core.attr.sample_type; *nbytes = 0; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index ec0675b0caa8..f6ee7fbad3e4 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2498,8 +2498,8 @@ static int thread__resolve_callchain_unwind(struct thread *thread, int max_stack) { /* Can we do dwarf post unwind? */ - if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && - (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) + if (!((evsel->core.attr.sample_type & PERF_SAMPLE_REGS_USER) && + (evsel->core.attr.sample_type & PERF_SAMPLE_STACK_USER))) return 0; /* Bail out if nothing was captured. */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 10efc33c56a1..ec7ce18b999a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1590,16 +1590,16 @@ struct event_modifier { static int get_event_modifier(struct event_modifier *mod, char *str, struct evsel *evsel) { - int eu = evsel ? evsel->attr.exclude_user : 0; - int ek = evsel ? evsel->attr.exclude_kernel : 0; - int eh = evsel ? evsel->attr.exclude_hv : 0; - int eH = evsel ? evsel->attr.exclude_host : 0; - int eG = evsel ? evsel->attr.exclude_guest : 0; - int eI = evsel ? evsel->attr.exclude_idle : 0; - int precise = evsel ? evsel->attr.precise_ip : 0; + int eu = evsel ? evsel->core.attr.exclude_user : 0; + int ek = evsel ? evsel->core.attr.exclude_kernel : 0; + int eh = evsel ? evsel->core.attr.exclude_hv : 0; + int eH = evsel ? evsel->core.attr.exclude_host : 0; + int eG = evsel ? evsel->core.attr.exclude_guest : 0; + int eI = evsel ? evsel->core.attr.exclude_idle : 0; + int precise = evsel ? evsel->core.attr.precise_ip : 0; int precise_max = 0; int sample_read = 0; - int pinned = evsel ? evsel->attr.pinned : 0; + int pinned = evsel ? evsel->core.attr.pinned : 0; int exclude = eu | ek | eh; int exclude_GH = evsel ? evsel->exclude_GH : 0; @@ -1717,20 +1717,20 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) if (add && get_event_modifier(&mod, str, evsel)) return -EINVAL; - evsel->attr.exclude_user = mod.eu; - evsel->attr.exclude_kernel = mod.ek; - evsel->attr.exclude_hv = mod.eh; - evsel->attr.precise_ip = mod.precise; - evsel->attr.exclude_host = mod.eH; - evsel->attr.exclude_guest = mod.eG; - evsel->attr.exclude_idle = mod.eI; + evsel->core.attr.exclude_user = mod.eu; + evsel->core.attr.exclude_kernel = mod.ek; + evsel->core.attr.exclude_hv = mod.eh; + evsel->core.attr.precise_ip = mod.precise; + evsel->core.attr.exclude_host = mod.eH; + evsel->core.attr.exclude_guest = mod.eG; + evsel->core.attr.exclude_idle = mod.eI; evsel->exclude_GH = mod.exclude_GH; evsel->sample_read = mod.sample_read; evsel->precise_max = mod.precise_max; evsel->weak_group = mod.weak; if (perf_evsel__is_group_leader(evsel)) - evsel->attr.pinned = mod.pinned; + evsel->core.attr.pinned = mod.pinned; } return 0; @@ -2071,7 +2071,7 @@ static int set_filter(struct evsel *evsel, const void *arg) return -1; } - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { if (perf_evsel__append_tp_filter(evsel, str) < 0) { fprintf(stderr, "not enough memory to hold filter string\n"); @@ -2082,7 +2082,7 @@ static int set_filter(struct evsel *evsel, const void *arg) } while ((pmu = perf_pmu__scan(pmu)) != NULL) - if (pmu->type == evsel->attr.type) { + if (pmu->type == evsel->core.attr.type) { found = true; break; } @@ -2120,7 +2120,7 @@ static int add_exclude_perf_filter(struct evsel *evsel, { char new_filter[64]; - if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { fprintf(stderr, "--exclude-perf option should follow a -e tracepoint option\n"); return -1; @@ -2331,7 +2331,7 @@ static bool is_event_supported(u8 type, unsigned config) * by default as some ARM machines do not support it. * */ - evsel->attr.exclude_kernel = 1; + evsel->core.attr.exclude_kernel = 1; ret = evsel__open(evsel, NULL, tmap) >= 0; } evsel__delete(evsel); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index cf0a18d49018..23a4fa13b92d 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -337,7 +337,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) static bool is_tracepoint(struct pyrf_event *pevent) { - return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT; + return pevent->evsel->core.attr.type == PERF_TYPE_TRACEPOINT; } static PyObject* @@ -389,7 +389,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) if (!evsel->tp_format) { struct tep_event *tp_format; - tp_format = trace_event__tp_format_id(evsel->attr.config); + tp_format = trace_event__tp_format_id(evsel->core.attr.config); if (!tp_format) return NULL; @@ -812,7 +812,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, if (pcpus != NULL) cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; - evsel->attr.inherit = inherit; + evsel->core.attr.inherit = inherit; /* * This will group just the fds for this single evsel, to group * multiple events, use evlist.open(). diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 3d3d732498e1..445788819969 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -29,7 +29,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) evsel = perf_evlist__first(evlist); while (1) { - fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); + fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags); if (fd < 0) { if (pid == -1 && errno == EACCES) { pid = 0; @@ -43,7 +43,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) fn(evsel); - fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); + fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags); if (fd < 0) { if (errno == EINVAL) err = -EINVAL; @@ -80,17 +80,17 @@ static bool perf_probe_api(setup_probe_fn_t fn) static void perf_probe_sample_identifier(struct evsel *evsel) { - evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; + evsel->core.attr.sample_type |= PERF_SAMPLE_IDENTIFIER; } static void perf_probe_comm_exec(struct evsel *evsel) { - evsel->attr.comm_exec = 1; + evsel->core.attr.comm_exec = 1; } static void perf_probe_context_switch(struct evsel *evsel) { - evsel->attr.context_switch = 1; + evsel->core.attr.context_switch = 1; } bool perf_can_sample_identifier(void) @@ -155,7 +155,7 @@ void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, evlist__for_each_entry(evlist, evsel) { perf_evsel__config(evsel, opts, callchain); if (evsel->tracking && use_comm_exec) - evsel->attr.comm_exec = 1; + evsel->core.attr.comm_exec = 1; } if (opts->full_auxtrace) { @@ -170,7 +170,7 @@ void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, struct evsel *first = perf_evlist__first(evlist); evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.sample_type == first->attr.sample_type) + if (evsel->core.attr.sample_type == first->core.attr.sample_type) continue; use_sample_identifier = perf_can_sample_identifier(); break; @@ -284,7 +284,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) } while (1) { - fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, + fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, perf_event_open_cloexec_flag()); if (fd < 0) { if (pid == -1 && errno == EACCES) { diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c index 59d78a9fe703..d078ae8353c8 100644 --- a/tools/perf/util/s390-cpumsf.c +++ b/tools/perf/util/s390-cpumsf.c @@ -935,7 +935,7 @@ s390_cpumsf_process_event(struct perf_session *session, /* Handle event with raw data */ ev_bc000 = perf_evlist__event2evsel(session->evlist, event); if (ev_bc000 && - ev_bc000->attr.config == PERF_EVENT_CPUM_CF_DIAG) + ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) err = s390_cpumcf_dumpctr(sf, sample); return err; } diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 6c709647cd8e..d311c81464e5 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -210,7 +210,7 @@ void perf_evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event ev_bc000 = perf_evlist__event2evsel(evlist, event); if (ev_bc000 == NULL || - ev_bc000->attr.config != PERF_EVENT_CPUM_CF_DIAG) + ev_bc000->core.attr.config != PERF_EVENT_CPUM_CF_DIAG) return; /* Display raw data on screen */ diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 98dcdb9a79a4..01ebf10b8bf4 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -353,11 +353,11 @@ static void perl_process_tracepoint(struct perf_sample *sample, dSP; - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) return; if (!event) { - pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); + pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config); return; } @@ -442,7 +442,7 @@ static void perl_process_event_generic(union perf_event *event, SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size))); - XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr)))); + XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->core.attr, sizeof(evsel->core.attr)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size))); PUTBACK; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 106aec31c07c..78b40c1d688e 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -636,7 +636,7 @@ static void set_sample_read_in_dict(PyObject *dict_sample, struct perf_sample *sample, struct evsel *evsel) { - u64 read_format = evsel->attr.read_format; + u64 read_format = evsel->core.attr.read_format; PyObject *values; unsigned int i; @@ -707,7 +707,7 @@ static void set_regs_in_dict(PyObject *dict, struct perf_sample *sample, struct evsel *evsel) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; char bf[512]; regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf)); @@ -737,7 +737,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel))); - pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->attr, sizeof(evsel->attr))); + pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->core.attr, sizeof(evsel->core.attr))); pydict_set_item_string_decref(dict_sample, "pid", _PyLong_FromLong(sample->pid)); @@ -809,7 +809,7 @@ static void python_process_tracepoint(struct perf_sample *sample, if (!event) { snprintf(handler_name, sizeof(handler_name), - "ug! no event found for type %" PRIu64, (u64)evsel->attr.config); + "ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config); Py_FatalError(handler_name); } @@ -1163,7 +1163,7 @@ static void python_export_synth(struct db_export *dbe, struct export_sample *es) t = tuple_new(3); tuple_set_u64(t, 0, es->db_id); - tuple_set_u64(t, 1, es->evsel->attr.config); + tuple_set_u64(t, 1, es->evsel->core.attr.config); tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size); call_object(tables->synth_handler, t, "synth_data"); @@ -1178,7 +1178,7 @@ static int python_export_sample(struct db_export *dbe, python_export_sample_table(dbe, es); - if (es->evsel->attr.type == PERF_TYPE_SYNTH && tables->synth_handler) + if (es->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler) python_export_synth(dbe, es); return 0; @@ -1316,7 +1316,7 @@ static void python_process_event(union perf_event *event, { struct tables *tables = &tables_global; - switch (evsel->attr.type) { + switch (evsel->core.attr.type) { case PERF_TYPE_TRACEPOINT: python_process_tracepoint(sample, evsel, al); break; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 62d37440cbee..1f3dc7a8cee6 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -154,7 +154,7 @@ static bool perf_session__has_comm_exec(struct perf_session *session) struct evsel *evsel; evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.comm_exec) + if (evsel->core.attr.comm_exec) return true; } @@ -1210,7 +1210,7 @@ static void dump_sample(struct evsel *evsel, union perf_event *event, event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); - sample_type = evsel->attr.sample_type; + sample_type = evsel->core.attr.sample_type; if (evsel__has_callchain(evsel)) callchain__printf(evsel, sample); @@ -1240,7 +1240,7 @@ static void dump_sample(struct evsel *evsel, union perf_event *event, printf("... transaction: %" PRIx64 "\n", sample->transaction); if (sample_type & PERF_SAMPLE_READ) - sample_read__printf(sample, evsel->attr.read_format); + sample_read__printf(sample, evsel->core.attr.read_format); } static void dump_read(struct evsel *evsel, union perf_event *event) @@ -1258,7 +1258,7 @@ static void dump_read(struct evsel *evsel, union perf_event *event) if (!evsel) return; - read_format = evsel->attr.read_format; + read_format = evsel->core.attr.read_format; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) printf("... time enabled : %" PRIu64 "\n", read_event->time_enabled); @@ -1355,8 +1355,8 @@ static int struct machine *machine) { /* We know evsel != NULL. */ - u64 sample_type = evsel->attr.sample_type; - u64 read_format = evsel->attr.read_format; + u64 sample_type = evsel->core.attr.sample_type; + u64 read_format = evsel->core.attr.read_format; /* Standard sample delivery. */ if (!(sample_type & PERF_SAMPLE_READ)) @@ -1709,7 +1709,7 @@ perf_session__warn_order(const struct perf_session *session) bool should_warn = true; evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.write_backward) + if (evsel->core.attr.write_backward) should_warn = false; } @@ -2186,7 +2186,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg) struct evsel *evsel; evlist__for_each_entry(session->evlist, evsel) { - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) return true; } @@ -2263,7 +2263,7 @@ struct evsel *perf_session__find_first_evtype(struct perf_session *session, struct evsel *pos; evlist__for_each_entry(session->evlist, pos) { - if (pos->attr.type == type) + if (pos->core.attr.type == type) return pos; } return NULL; @@ -2282,7 +2282,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, if (!evsel) continue; - if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) { + if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CPU)) { pr_err("File does not contain CPU events. " "Remove -C option to proceed.\n"); return -1; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index fa3cc2112b82..f9a38a1dd4d1 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -726,7 +726,7 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) struct evsel *evsel; evsel = hists_to_evsel(left->hists); - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) return 0; if (left->trace_output == NULL) @@ -743,7 +743,7 @@ static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, struct evsel *evsel; evsel = hists_to_evsel(he->hists); - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) return scnprintf(bf, size, "%-.*s", width, "N/A"); if (he->trace_output == NULL) @@ -2391,7 +2391,7 @@ static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace, struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) continue; ret = add_evsel_fields(evsel, raw_trace, level); @@ -2409,7 +2409,7 @@ static int add_all_matching_fields(struct evlist *evlist, struct tep_format_field *field; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) continue; field = tep_find_any_field(evsel->tp_format, field_name); @@ -2470,7 +2470,7 @@ static int add_dynamic_entry(struct evlist *evlist, const char *tok, goto out; } - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { pr_debug("%s is not a tracepoint event\n", event_name); ret = -EINVAL; goto out; @@ -2728,7 +2728,7 @@ static const char *get_default_sort_order(struct evlist *evlist) goto out_no_evlist; evlist__for_each_entry(evlist, evsel) { - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { use_trace = false; break; } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index b1a2571f7c8f..99bda99a1b2d 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -366,7 +366,7 @@ static void abs_printout(struct perf_stat_config *config, static bool is_mixed_hw_group(struct evsel *counter) { struct evlist *evlist = counter->evlist; - u32 pmu_type = counter->attr.type; + u32 pmu_type = counter->core.attr.type; struct evsel *pos; if (counter->nr_members < 2) @@ -374,13 +374,13 @@ static bool is_mixed_hw_group(struct evsel *counter) evlist__for_each_entry(evlist, pos) { /* software events can be part of any hardware group */ - if (pos->attr.type == PERF_TYPE_SOFTWARE) + if (pos->core.attr.type == PERF_TYPE_SOFTWARE) continue; if (pmu_type == PERF_TYPE_SOFTWARE) { - pmu_type = pos->attr.type; + pmu_type = pos->core.attr.type; continue; } - if (pmu_type != pos->attr.type) + if (pmu_type != pos->core.attr.type) return true; } diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index d81bcab2e64c..2ed5e0066c70 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -150,15 +150,15 @@ static int evsel_context(struct evsel *evsel) { int ctx = 0; - if (evsel->attr.exclude_kernel) + if (evsel->core.attr.exclude_kernel) ctx |= CTX_BIT_KERNEL; - if (evsel->attr.exclude_user) + if (evsel->core.attr.exclude_user) ctx |= CTX_BIT_USER; - if (evsel->attr.exclude_hv) + if (evsel->core.attr.exclude_hv) ctx |= CTX_BIT_HV; - if (evsel->attr.exclude_host) + if (evsel->core.attr.exclude_host) ctx |= CTX_BIT_HOST; - if (evsel->attr.exclude_idle) + if (evsel->core.attr.exclude_idle) ctx |= CTX_BIT_IDLE; return ctx; @@ -829,8 +829,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, else print_metric(config, ctxp, NULL, NULL, "of all branches", 0); } else if ( - evsel->attr.type == PERF_TYPE_HW_CACHE && - evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | + evsel->core.attr.type == PERF_TYPE_HW_CACHE && + evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1D | ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -839,8 +839,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, else print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0); } else if ( - evsel->attr.type == PERF_TYPE_HW_CACHE && - evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | + evsel->core.attr.type == PERF_TYPE_HW_CACHE && + evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1I | ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -849,8 +849,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, else print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0); } else if ( - evsel->attr.type == PERF_TYPE_HW_CACHE && - evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | + evsel->core.attr.type == PERF_TYPE_HW_CACHE && + evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_DTLB | ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -859,8 +859,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, else print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0); } else if ( - evsel->attr.type == PERF_TYPE_HW_CACHE && - evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | + evsel->core.attr.type == PERF_TYPE_HW_CACHE && + evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_ITLB | ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { @@ -869,8 +869,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, else print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0); } else if ( - evsel->attr.type == PERF_TYPE_HW_CACHE && - evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | + evsel->core.attr.type == PERF_TYPE_HW_CACHE && + evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_LL | ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 63f7815ceb4f..632bf72cf780 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -441,7 +441,7 @@ int create_perf_stat_counter(struct evsel *evsel, struct perf_stat_config *config, struct target *target) { - struct perf_event_attr *attr = &evsel->attr; + struct perf_event_attr *attr = &evsel->core.attr; struct evsel *leader = evsel->leader; attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 3bbbdac2c550..f533f1aac045 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -73,7 +73,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) if (top->evlist->core.nr_entries == 1) { struct evsel *first = perf_evlist__first(top->evlist); ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", - (uint64_t)first->attr.sample_period, + (uint64_t)first->core.attr.sample_period, opts->freq ? "Hz" : ""); } diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 7efdbb182ea1..2f8a0601a546 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -409,7 +409,7 @@ get_tracepoints_path(struct list_head *pattrs) int nr_tracepoints = 0; list_for_each_entry(pos, pattrs, core.node) { - if (pos->attr.type != PERF_TYPE_TRACEPOINT) + if (pos->core.attr.type != PERF_TYPE_TRACEPOINT) continue; ++nr_tracepoints; @@ -425,7 +425,7 @@ get_tracepoints_path(struct list_head *pattrs) } try_id: - ppath->next = tracepoint_id_to_path(pos->attr.config); + ppath->next = tracepoint_id_to_path(pos->core.attr.config); if (!ppath->next) { error: pr_debug("No memory to alloc tracepoints list\n"); @@ -444,7 +444,7 @@ bool have_tracepoints(struct list_head *pattrs) struct evsel *pos; list_for_each_entry(pos, pattrs, core.node) - if (pos->attr.type == PERF_TYPE_TRACEPOINT) + if (pos->core.attr.type == PERF_TYPE_TRACEPOINT) return true; return false; -- GitLab From 9c3516d1b850ea938b074df33e4c86d721c77720 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:30 +0200 Subject: [PATCH 1169/7155] libperf: Add perf_cpu_map__new()/perf_cpu_map__read() functions Moving the following functions from tools/perf: cpu_map__new() cpu_map__read() to libperf with the following names: perf_cpu_map__new() perf_cpu_map__read() Committer notes: Fixed up this one: tools/perf/arch/arm/util/cs-etm.c Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-44-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 3 +- tools/perf/bench/epoll-ctl.c | 3 +- tools/perf/bench/epoll-wait.c | 3 +- tools/perf/bench/futex-hash.c | 3 +- tools/perf/bench/futex-lock-pi.c | 3 +- tools/perf/bench/futex-requeue.c | 3 +- tools/perf/bench/futex-wake-parallel.c | 2 +- tools/perf/bench/futex-wake.c | 3 +- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-sched.c | 4 +- tools/perf/lib/cpumap.c | 184 +++++++++++++++++++ tools/perf/lib/include/internal/cpumap.h | 4 + tools/perf/lib/include/perf/cpumap.h | 3 + tools/perf/lib/libperf.map | 2 + tools/perf/tests/bitmap.c | 3 +- tools/perf/tests/code-reading.c | 5 +- tools/perf/tests/cpumap.c | 7 +- tools/perf/tests/event-times.c | 9 +- tools/perf/tests/event_update.c | 3 +- tools/perf/tests/keep-tracking.c | 3 +- tools/perf/tests/mem2node.c | 3 +- tools/perf/tests/mmap-basic.c | 3 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/switch-tracking.c | 5 +- tools/perf/tests/topology.c | 3 +- tools/perf/util/cpumap.c | 181 +----------------- tools/perf/util/cpumap.h | 2 - tools/perf/util/cputopo.c | 5 +- tools/perf/util/evlist.c | 5 +- tools/perf/util/header.c | 3 +- tools/perf/util/parse-events.c | 3 +- tools/perf/util/pmu.c | 3 +- tools/perf/util/python.c | 3 +- tools/perf/util/record.c | 7 +- tools/perf/util/session.c | 3 +- tools/perf/util/svghelper.c | 3 +- 37 files changed, 265 insertions(+), 227 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index f5aafdec7f50..c25bc1528b96 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -156,7 +156,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr, { int i, err = -EINVAL; struct perf_cpu_map *event_cpus = evsel->evlist->cpus; - struct perf_cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); /* Set option of each CPU we have */ for (i = 0; i < cpu__max_cpu(); i++) { @@ -490,7 +490,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, int i; int etmv3 = 0, etmv4 = 0; struct perf_cpu_map *event_cpus = evlist->cpus; - struct perf_cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); /* cpu map is not empty, we have specific CPUs to work with */ if (!cpu_map__empty(event_cpus)) { @@ -637,7 +637,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, u64 nr_cpu, type; struct perf_cpu_map *cpu_map; struct perf_cpu_map *event_cpus = session->evlist->cpus; - struct perf_cpu_map *online_cpus = cpu_map__new(NULL); + struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 07129e007eb0..261bdd680651 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -65,7 +66,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe threads = thread_map__new(-1, getpid(), UINT_MAX); CHECK_NOT_NULL__(threads); - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); CHECK_NOT_NULL__(cpus); evlist = evlist__new(); diff --git a/tools/perf/bench/epoll-ctl.c b/tools/perf/bench/epoll-ctl.c index 1fd724f1d48b..84658d45f349 100644 --- a/tools/perf/bench/epoll-ctl.c +++ b/tools/perf/bench/epoll-ctl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "../util/stat.h" #include @@ -315,7 +316,7 @@ int bench_epoll_ctl(int argc, const char **argv) act.sa_sigaction = toggle_done; sigaction(SIGINT, &act, NULL); - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) goto errmem; diff --git a/tools/perf/bench/epoll-wait.c b/tools/perf/bench/epoll-wait.c index 79a254fff2d1..c27a65639cfb 100644 --- a/tools/perf/bench/epoll-wait.c +++ b/tools/perf/bench/epoll-wait.c @@ -75,6 +75,7 @@ #include #include #include +#include #include "../util/stat.h" #include @@ -429,7 +430,7 @@ int bench_epoll_wait(int argc, const char **argv) act.sa_sigaction = toggle_done; sigaction(SIGINT, &act, NULL); - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) goto errmem; diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c index b4fea8e3a368..80e138904c66 100644 --- a/tools/perf/bench/futex-hash.c +++ b/tools/perf/bench/futex-hash.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "../util/stat.h" #include @@ -132,7 +133,7 @@ int bench_futex_hash(int argc, const char **argv) exit(EXIT_FAILURE); } - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) goto errmem; diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c index 596769924709..c5d6d0abbaa9 100644 --- a/tools/perf/bench/futex-lock-pi.c +++ b/tools/perf/bench/futex-lock-pi.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "bench.h" #include "futex.h" #include "cpumap.h" @@ -156,7 +157,7 @@ int bench_futex_lock_pi(int argc, const char **argv) if (argc) goto err; - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) err(EXIT_FAILURE, "calloc"); diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c index 1fd32a4f9c14..75d3418c1a88 100644 --- a/tools/perf/bench/futex-requeue.c +++ b/tools/perf/bench/futex-requeue.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "bench.h" #include "futex.h" #include "cpumap.h" @@ -123,7 +124,7 @@ int bench_futex_requeue(int argc, const char **argv) if (argc) goto err; - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) err(EXIT_FAILURE, "cpu_map__new"); diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c index 884c73e5bd1b..163fe16c275a 100644 --- a/tools/perf/bench/futex-wake-parallel.c +++ b/tools/perf/bench/futex-wake-parallel.c @@ -237,7 +237,7 @@ int bench_futex_wake_parallel(int argc, const char **argv) act.sa_sigaction = toggle_done; sigaction(SIGINT, &act, NULL); - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) err(EXIT_FAILURE, "calloc"); diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c index 2288fa8412ff..77dcdc13618a 100644 --- a/tools/perf/bench/futex-wake.c +++ b/tools/perf/bench/futex-wake.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "bench.h" #include "futex.h" #include "cpumap.h" @@ -131,7 +132,7 @@ int bench_futex_wake(int argc, const char **argv) exit(EXIT_FAILURE); } - cpu = cpu_map__new(NULL); + cpu = perf_cpu_map__new(NULL); if (!cpu) err(EXIT_FAILURE, "calloc"); diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 6943352b8d94..77989254fdd8 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -202,7 +202,7 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace) static int reset_tracing_cpu(void) { - struct perf_cpu_map *cpumap = cpu_map__new(NULL); + struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL); int ret; ret = set_tracing_cpumask(cpumap); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 897d11c8ca2e..0d6b4c3b1a51 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3183,7 +3183,7 @@ static int setup_map_cpus(struct perf_sched *sched) if (!sched->map.cpus_str) return 0; - map = cpu_map__new(sched->map.cpus_str); + map = perf_cpu_map__new(sched->map.cpus_str); if (!map) { pr_err("failed to get cpus map from %s\n", sched->map.cpus_str); return -1; @@ -3217,7 +3217,7 @@ static int setup_color_cpus(struct perf_sched *sched) if (!sched->map.color_cpus_str) return 0; - map = cpu_map__new(sched->map.color_cpus_str); + map = perf_cpu_map__new(sched->map.color_cpus_str); if (!map) { pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str); return -1; diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index f3cfb4c71106..a5d4f7ff7174 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include +#include struct perf_cpu_map *perf_cpu_map__dummy_new(void) { @@ -40,3 +44,183 @@ void perf_cpu_map__put(struct perf_cpu_map *map) if (map && refcount_dec_and_test(&map->refcnt)) cpu_map__delete(map); } + +static struct perf_cpu_map *cpu_map__default_new(void) +{ + struct perf_cpu_map *cpus; + int nr_cpus; + + nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (nr_cpus < 0) + return NULL; + + cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int)); + if (cpus != NULL) { + int i; + + for (i = 0; i < nr_cpus; ++i) + cpus->map[i] = i; + + cpus->nr = nr_cpus; + refcount_set(&cpus->refcnt, 1); + } + + return cpus; +} + +static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) +{ + size_t payload_size = nr_cpus * sizeof(int); + struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); + + if (cpus != NULL) { + cpus->nr = nr_cpus; + memcpy(cpus->map, tmp_cpus, payload_size); + refcount_set(&cpus->refcnt, 1); + } + + return cpus; +} + +struct perf_cpu_map *perf_cpu_map__read(FILE *file) +{ + struct perf_cpu_map *cpus = NULL; + int nr_cpus = 0; + int *tmp_cpus = NULL, *tmp; + int max_entries = 0; + int n, cpu, prev; + char sep; + + sep = 0; + prev = -1; + for (;;) { + n = fscanf(file, "%u%c", &cpu, &sep); + if (n <= 0) + break; + if (prev >= 0) { + int new_max = nr_cpus + cpu - prev - 1; + + if (new_max >= max_entries) { + max_entries = new_max + MAX_NR_CPUS / 2; + tmp = realloc(tmp_cpus, max_entries * sizeof(int)); + if (tmp == NULL) + goto out_free_tmp; + tmp_cpus = tmp; + } + + while (++prev < cpu) + tmp_cpus[nr_cpus++] = prev; + } + if (nr_cpus == max_entries) { + max_entries += MAX_NR_CPUS; + tmp = realloc(tmp_cpus, max_entries * sizeof(int)); + if (tmp == NULL) + goto out_free_tmp; + tmp_cpus = tmp; + } + + tmp_cpus[nr_cpus++] = cpu; + if (n == 2 && sep == '-') + prev = cpu; + else + prev = -1; + if (n == 1 || sep == '\n') + break; + } + + if (nr_cpus > 0) + cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); + else + cpus = cpu_map__default_new(); +out_free_tmp: + free(tmp_cpus); + return cpus; +} + +static struct perf_cpu_map *cpu_map__read_all_cpu_map(void) +{ + struct perf_cpu_map *cpus = NULL; + FILE *onlnf; + + onlnf = fopen("/sys/devices/system/cpu/online", "r"); + if (!onlnf) + return cpu_map__default_new(); + + cpus = perf_cpu_map__read(onlnf); + fclose(onlnf); + return cpus; +} + +struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list) +{ + struct perf_cpu_map *cpus = NULL; + unsigned long start_cpu, end_cpu = 0; + char *p = NULL; + int i, nr_cpus = 0; + int *tmp_cpus = NULL, *tmp; + int max_entries = 0; + + if (!cpu_list) + return cpu_map__read_all_cpu_map(); + + /* + * must handle the case of empty cpumap to cover + * TOPOLOGY header for NUMA nodes with no CPU + * ( e.g., because of CPU hotplug) + */ + if (!isdigit(*cpu_list) && *cpu_list != '\0') + goto out; + + while (isdigit(*cpu_list)) { + p = NULL; + start_cpu = strtoul(cpu_list, &p, 0); + if (start_cpu >= INT_MAX + || (*p != '\0' && *p != ',' && *p != '-')) + goto invalid; + + if (*p == '-') { + cpu_list = ++p; + p = NULL; + end_cpu = strtoul(cpu_list, &p, 0); + + if (end_cpu >= INT_MAX || (*p != '\0' && *p != ',')) + goto invalid; + + if (end_cpu < start_cpu) + goto invalid; + } else { + end_cpu = start_cpu; + } + + for (; start_cpu <= end_cpu; start_cpu++) { + /* check for duplicates */ + for (i = 0; i < nr_cpus; i++) + if (tmp_cpus[i] == (int)start_cpu) + goto invalid; + + if (nr_cpus == max_entries) { + max_entries += MAX_NR_CPUS; + tmp = realloc(tmp_cpus, max_entries * sizeof(int)); + if (tmp == NULL) + goto invalid; + tmp_cpus = tmp; + } + tmp_cpus[nr_cpus++] = (int)start_cpu; + } + if (*p) + ++p; + + cpu_list = p; + } + + if (nr_cpus > 0) + cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); + else if (*cpu_list != '\0') + cpus = cpu_map__default_new(); + else + cpus = perf_cpu_map__dummy_new(); +invalid: + free(tmp_cpus); +out: + return cpus; +} diff --git a/tools/perf/lib/include/internal/cpumap.h b/tools/perf/lib/include/internal/cpumap.h index 53ce95374b05..3306319f7df8 100644 --- a/tools/perf/lib/include/internal/cpumap.h +++ b/tools/perf/lib/include/internal/cpumap.h @@ -10,4 +10,8 @@ struct perf_cpu_map { int map[]; }; +#ifndef MAX_NR_CPUS +#define MAX_NR_CPUS 2048 +#endif + #endif /* __LIBPERF_INTERNAL_CPUMAP_H */ diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h index e16c2515a499..b4a9283a5dfa 100644 --- a/tools/perf/lib/include/perf/cpumap.h +++ b/tools/perf/lib/include/perf/cpumap.h @@ -3,10 +3,13 @@ #define __LIBPERF_CPUMAP_H #include +#include struct perf_cpu_map; LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); +LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list); +LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file); LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 168339f89a2e..e38473a8f32f 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -4,6 +4,8 @@ LIBPERF_0.0.1 { perf_cpu_map__dummy_new; perf_cpu_map__get; perf_cpu_map__put; + perf_cpu_map__new; + perf_cpu_map__read; perf_thread_map__new_dummy; perf_thread_map__set_pid; perf_thread_map__comm; diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c index 95304d29092e..db2aadff3708 100644 --- a/tools/perf/tests/bitmap.c +++ b/tools/perf/tests/bitmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include "tests.h" #include "cpumap.h" #include "debug.h" @@ -9,7 +10,7 @@ static unsigned long *get_bitmap(const char *str, int nbits) { - struct perf_cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = perf_cpu_map__new(str); unsigned long *bm = NULL; int i; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 131bbeec62d2..bfaf22c2023c 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -613,9 +614,9 @@ static int do_test_code_reading(bool try_kcore) goto out_put; } - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (!cpus) { - pr_debug("cpu_map__new failed\n"); + pr_debug("perf_cpu_map__new failed\n"); goto out_put; } diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 6c921087b0fe..b71fe09a8087 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -5,6 +5,7 @@ #include "event.h" #include #include +#include #include "debug.h" struct machine; @@ -78,7 +79,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may struct perf_cpu_map *cpus; /* This one is better stores in mask. */ - cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19"); + cpus = perf_cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19"); TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL)); @@ -86,7 +87,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may perf_cpu_map__put(cpus); /* This one is better stores in cpu values. */ - cpus = cpu_map__new("1,256"); + cpus = perf_cpu_map__new("1,256"); TEST_ASSERT_VAL("failed to synthesize map", !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL)); @@ -97,7 +98,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may static int cpu_map_print(const char *str) { - struct perf_cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = perf_cpu_map__new(str); char buf[100]; if (!map) diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 165534f62036..00adba86403b 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "tests.h" #include "evlist.h" #include "evsel.h" @@ -115,9 +116,9 @@ static int attach__cpu_disabled(struct evlist *evlist) pr_debug("attaching to CPU 0 as enabled\n"); - cpus = cpu_map__new("0"); + cpus = perf_cpu_map__new("0"); if (cpus == NULL) { - pr_debug("failed to call cpu_map__new\n"); + pr_debug("failed to call perf_cpu_map__new\n"); return -1; } @@ -144,9 +145,9 @@ static int attach__cpu_enabled(struct evlist *evlist) pr_debug("attaching to CPU 0 as enabled\n"); - cpus = cpu_map__new("0"); + cpus = perf_cpu_map__new("0"); if (cpus == NULL) { - pr_debug("failed to call cpu_map__new\n"); + pr_debug("failed to call perf_cpu_map__new\n"); return -1; } diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index 415d12e96834..2bc5145284c0 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include "evlist.h" #include "evsel.h" #include "machine.h" @@ -108,7 +109,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu TEST_ASSERT_VAL("failed to synthesize attr update name", !perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name)); - evsel->own_cpus = cpu_map__new("1,2,3"); + evsel->own_cpus = perf_cpu_map__new("1,2,3"); TEST_ASSERT_VAL("failed to synthesize attr update cpus", !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 4fc7b3b4e153..46478ba1ed16 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -75,7 +76,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un threads = thread_map__new(-1, getpid(), UINT_MAX); CHECK_NOT_NULL__(threads); - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); CHECK_NOT_NULL__(cpus); evlist = evlist__new(); diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c index 6fe2c1e7918b..5ec193f7968d 100644 --- a/tools/perf/tests/mem2node.c +++ b/tools/perf/tests/mem2node.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "cpumap.h" #include "mem2node.h" #include "tests.h" @@ -19,7 +20,7 @@ static struct node { static unsigned long *get_bitmap(const char *str, int nbits) { - struct perf_cpu_map *map = cpu_map__new(str); + struct perf_cpu_map *map = perf_cpu_map__new(str); unsigned long *bm = NULL; int i; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 9d8eb43b12cb..aa792aebd7f0 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -3,6 +3,7 @@ #include /* For the CLR_() macros */ #include +#include #include "evlist.h" #include "evsel.h" @@ -46,7 +47,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse return -1; } - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (cpus == NULL) { pr_debug("cpu_map__new\n"); goto out_free_threads; diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 674b0fa035ec..d161b1a78703 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -33,7 +33,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int return -1; } - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (cpus == NULL) { pr_debug("cpu_map__new\n"); goto out_thread_map_delete; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index dd07acced4af..9e0bbea15005 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -341,9 +342,9 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (!cpus) { - pr_debug("cpu_map__new failed!\n"); + pr_debug("perf_cpu_map__new failed!\n"); goto out_err; } diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 1b57ded58d59..a4f9f5182b47 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "tests.h" #include "util.h" #include "session.h" @@ -126,7 +127,7 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe if (session_write_header(path)) goto free_path; - map = cpu_map__new(NULL); + map = perf_cpu_map__new(NULL); if (map == NULL) { pr_debug("failed to get system cpumap\n"); goto free_path; diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 44082e5eabde..71d4d7b35a57 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -17,185 +17,6 @@ static int max_present_cpu_num; static int max_node_num; static int *cpunode_map; -static struct perf_cpu_map *cpu_map__default_new(void) -{ - struct perf_cpu_map *cpus; - int nr_cpus; - - nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); - if (nr_cpus < 0) - return NULL; - - cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int)); - if (cpus != NULL) { - int i; - for (i = 0; i < nr_cpus; ++i) - cpus->map[i] = i; - - cpus->nr = nr_cpus; - refcount_set(&cpus->refcnt, 1); - } - - return cpus; -} - -static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) -{ - size_t payload_size = nr_cpus * sizeof(int); - struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); - - if (cpus != NULL) { - cpus->nr = nr_cpus; - memcpy(cpus->map, tmp_cpus, payload_size); - refcount_set(&cpus->refcnt, 1); - } - - return cpus; -} - -struct perf_cpu_map *cpu_map__read(FILE *file) -{ - struct perf_cpu_map *cpus = NULL; - int nr_cpus = 0; - int *tmp_cpus = NULL, *tmp; - int max_entries = 0; - int n, cpu, prev; - char sep; - - sep = 0; - prev = -1; - for (;;) { - n = fscanf(file, "%u%c", &cpu, &sep); - if (n <= 0) - break; - if (prev >= 0) { - int new_max = nr_cpus + cpu - prev - 1; - - if (new_max >= max_entries) { - max_entries = new_max + MAX_NR_CPUS / 2; - tmp = realloc(tmp_cpus, max_entries * sizeof(int)); - if (tmp == NULL) - goto out_free_tmp; - tmp_cpus = tmp; - } - - while (++prev < cpu) - tmp_cpus[nr_cpus++] = prev; - } - if (nr_cpus == max_entries) { - max_entries += MAX_NR_CPUS; - tmp = realloc(tmp_cpus, max_entries * sizeof(int)); - if (tmp == NULL) - goto out_free_tmp; - tmp_cpus = tmp; - } - - tmp_cpus[nr_cpus++] = cpu; - if (n == 2 && sep == '-') - prev = cpu; - else - prev = -1; - if (n == 1 || sep == '\n') - break; - } - - if (nr_cpus > 0) - cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); - else - cpus = cpu_map__default_new(); -out_free_tmp: - free(tmp_cpus); - return cpus; -} - -static struct perf_cpu_map *cpu_map__read_all_cpu_map(void) -{ - struct perf_cpu_map *cpus = NULL; - FILE *onlnf; - - onlnf = fopen("/sys/devices/system/cpu/online", "r"); - if (!onlnf) - return cpu_map__default_new(); - - cpus = cpu_map__read(onlnf); - fclose(onlnf); - return cpus; -} - -struct perf_cpu_map *cpu_map__new(const char *cpu_list) -{ - struct perf_cpu_map *cpus = NULL; - unsigned long start_cpu, end_cpu = 0; - char *p = NULL; - int i, nr_cpus = 0; - int *tmp_cpus = NULL, *tmp; - int max_entries = 0; - - if (!cpu_list) - return cpu_map__read_all_cpu_map(); - - /* - * must handle the case of empty cpumap to cover - * TOPOLOGY header for NUMA nodes with no CPU - * ( e.g., because of CPU hotplug) - */ - if (!isdigit(*cpu_list) && *cpu_list != '\0') - goto out; - - while (isdigit(*cpu_list)) { - p = NULL; - start_cpu = strtoul(cpu_list, &p, 0); - if (start_cpu >= INT_MAX - || (*p != '\0' && *p != ',' && *p != '-')) - goto invalid; - - if (*p == '-') { - cpu_list = ++p; - p = NULL; - end_cpu = strtoul(cpu_list, &p, 0); - - if (end_cpu >= INT_MAX || (*p != '\0' && *p != ',')) - goto invalid; - - if (end_cpu < start_cpu) - goto invalid; - } else { - end_cpu = start_cpu; - } - - for (; start_cpu <= end_cpu; start_cpu++) { - /* check for duplicates */ - for (i = 0; i < nr_cpus; i++) - if (tmp_cpus[i] == (int)start_cpu) - goto invalid; - - if (nr_cpus == max_entries) { - max_entries += MAX_NR_CPUS; - tmp = realloc(tmp_cpus, max_entries * sizeof(int)); - if (tmp == NULL) - goto invalid; - tmp_cpus = tmp; - } - tmp_cpus[nr_cpus++] = (int)start_cpu; - } - if (*p) - ++p; - - cpu_list = p; - } - - if (nr_cpus > 0) - cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); - else if (*cpu_list != '\0') - cpus = cpu_map__default_new(); - else - cpus = perf_cpu_map__dummy_new(); -invalid: - free(tmp_cpus); -out: - return cpus; -} - static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) { struct perf_cpu_map *map; @@ -751,7 +572,7 @@ const struct perf_cpu_map *cpu_map__online(void) /* thread unsafe */ static const struct perf_cpu_map *online = NULL; if (!online) - online = cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */ + online = perf_cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */ return online; } diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index b7af2cb68c19..a3d27f4131be 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -11,10 +11,8 @@ #include "perf.h" #include "util/debug.h" -struct perf_cpu_map *cpu_map__new(const char *cpu_list); struct perf_cpu_map *cpu_map__empty_new(int nr); struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); -struct perf_cpu_map *cpu_map__read(FILE *file); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 0cd99c460cd4..4f70155eaf83 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "cputopo.h" #include "cpumap.h" @@ -182,7 +183,7 @@ struct cpu_topology *cpu_topology__new(void) ncpus = cpu__max_present_cpu(); /* build online CPU map */ - map = cpu_map__new(NULL); + map = perf_cpu_map__new(NULL); if (map == NULL) { pr_debug("failed to get system cpumap\n"); return NULL; @@ -312,7 +313,7 @@ struct numa_topology *numa_topology__new(void) if (c) *c = '\0'; - node_map = cpu_map__new(buf); + node_map = perf_cpu_map__new(buf); if (!node_map) goto out; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index ae75777a0ba4..67c67e9a38cd 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef LACKS_SIGQUEUE_PROTOTYPE int sigqueue(pid_t pid, int sig, const union sigval value); @@ -1089,7 +1090,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) if (target__uses_dummy_map(target)) cpus = perf_cpu_map__dummy_new(); else - cpus = cpu_map__new(target->cpu_list); + cpus = perf_cpu_map__new(target->cpu_list); if (!cpus) goto out_delete_threads; @@ -1372,7 +1373,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) * error, and we may not want to do that fallback to a * default cpu identity map :-\ */ - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (!cpus) goto out; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d81afe56392c..fa914ba8cd56 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "evlist.h" #include "evsel.h" @@ -2348,7 +2349,7 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused) if (!str) goto error; - n->map = cpu_map__new(str); + n->map = perf_cpu_map__new(str); if (!n->map) goto error; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index ec7ce18b999a..db2460d6b625 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -24,6 +24,7 @@ #include "bpf-loader.h" #include "debug.h" #include +#include #include "parse-events-bison.h" #define YY_EXTRA_TYPE int #include "parse-events-flex.h" @@ -323,7 +324,7 @@ __add_event(struct list_head *list, int *idx, { struct evsel *evsel; struct perf_cpu_map *cpus = pmu ? pmu->cpus : - cpu_list ? cpu_map__new(cpu_list) : NULL; + cpu_list ? perf_cpu_map__new(cpu_list) : NULL; event_attr_init(attr); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d355f9506a1c..b7da21a7d627 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "pmu.h" #include "parse-events.h" #include "cpumap.h" @@ -581,7 +582,7 @@ static struct perf_cpu_map *__pmu_cpumask(const char *path) if (!file) return NULL; - cpus = cpu_map__read(file); + cpus = perf_cpu_map__read(file); fclose(file); return cpus; } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 23a4fa13b92d..75ecc32a4427 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "evlist.h" #include "callchain.h" #include "evsel.h" @@ -549,7 +550,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, kwlist, &cpustr)) return -1; - pcpus->cpus = cpu_map__new(cpustr); + pcpus->cpus = perf_cpu_map__new(cpustr); if (pcpus->cpus == NULL) return -1; return 0; diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 445788819969..03dcdb3f33a7 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "util.h" #include "cloexec.h" @@ -63,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn) struct perf_cpu_map *cpus; int cpu, ret, i = 0; - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (!cpus) return false; cpu = cpus->map[0]; @@ -118,7 +119,7 @@ bool perf_can_record_cpu_wide(void) struct perf_cpu_map *cpus; int cpu, fd; - cpus = cpu_map__new(NULL); + cpus = perf_cpu_map__new(NULL); if (!cpus) return false; cpu = cpus->map[0]; @@ -275,7 +276,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) evsel = perf_evlist__last(temp_evlist); if (!evlist || cpu_map__empty(evlist->cpus)) { - struct perf_cpu_map *cpus = cpu_map__new(NULL); + struct perf_cpu_map *cpus = perf_cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; perf_cpu_map__put(cpus); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1f3dc7a8cee6..11e6093c941b 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "evlist.h" #include "evsel.h" @@ -2289,7 +2290,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, } } - map = cpu_map__new(cpu_list); + map = perf_cpu_map__new(cpu_list); if (map == NULL) { pr_err("Invalid cpu_list\n"); return -1; diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index a9ca5c4fffee..ae6a534a7a80 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "perf.h" #include "svghelper.h" @@ -731,7 +732,7 @@ static int str_to_bitmap(char *s, cpumask_t *b) struct perf_cpu_map *m; int c; - m = cpu_map__new(s); + m = perf_cpu_map__new(s); if (!m) return -1; -- GitLab From 93bce7e5bfcd570e9250c974b5c2c91d6b8332ef Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:31 +0200 Subject: [PATCH 1170/7155] libperf: Move zalloc.o into libperf We need it in both perf and libperf, thus moving it to libperf. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-45-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Build | 5 +++++ tools/perf/util/Build | 5 ----- tools/perf/util/python-ext-sources | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index b27c1543b046..faf64db13e37 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -3,3 +3,8 @@ libperf-y += cpumap.o libperf-y += threadmap.o libperf-y += evsel.o libperf-y += evlist.o +libperf-y += zalloc.o + +$(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 14f812bb07a7..08f670d21615 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -26,7 +26,6 @@ perf-y += rbtree.o perf-y += libstring.o perf-y += bitmap.o perf-y += hweight.o -perf-y += zalloc.o perf-y += smt.o perf-y += strbuf.o perf-y += string.o @@ -243,7 +242,3 @@ $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE $(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) - -$(OUTPUT)util/zalloc.o: ../lib/zalloc.c FORCE - $(call rule_mkdir) - $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index ceb8afdf9a89..2237bac9fadb 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -18,7 +18,6 @@ util/namespaces.c ../lib/hweight.c ../lib/string.c ../lib/vsprintf.c -../lib/zalloc.c util/thread_map.c util/util.c util/xyarray.c -- GitLab From 634912d61ccc6bfeebb87716c276fbea20f63bdc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:32 +0200 Subject: [PATCH 1171/7155] libperf: Add perf_evlist__new() function Add perf_evlist__new() function to create and init a perf_evlist struct dynamicaly. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-46-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 11 +++++++++++ tools/perf/lib/include/perf/evlist.h | 1 + tools/perf/lib/libperf.map | 1 + 3 files changed, 13 insertions(+) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 1b27fd2de9b9..0517deb4cb1c 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -3,6 +3,7 @@ #include #include #include +#include void perf_evlist__init(struct perf_evlist *evlist) { @@ -23,3 +24,13 @@ void perf_evlist__remove(struct perf_evlist *evlist, list_del_init(&evsel->node); evlist->nr_entries -= 1; } + +struct perf_evlist *perf_evlist__new(void) +{ + struct perf_evlist *evlist = zalloc(sizeof(*evlist)); + + if (evlist != NULL) + perf_evlist__init(evlist); + + return evlist; +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index e0c87995c6ff..7255a60869a1 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -12,5 +12,6 @@ LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *evsel); LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); +LIBPERF_API struct perf_evlist *perf_evlist__new(void); #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index e38473a8f32f..5e685d6c7a95 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -12,6 +12,7 @@ LIBPERF_0.0.1 { perf_thread_map__get; perf_thread_map__put; perf_evsel__init; + perf_evlist__new; perf_evlist__init; perf_evlist__add; perf_evlist__remove; -- GitLab From 63bd5dfa69658c459d08a6ee6bfebbd4a91cf24d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:33 +0200 Subject: [PATCH 1172/7155] libperf: Add perf_evsel__new() function Add a perf_evsel__new() function to create and init a perf_evsel struct dynamicaly. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-47-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 11 +++++++++++ tools/perf/lib/include/perf/evsel.h | 1 + tools/perf/lib/libperf.map | 1 + 3 files changed, 13 insertions(+) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 17cba35becc7..8e91738c5c38 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -2,9 +2,20 @@ #include #include #include +#include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) { INIT_LIST_HEAD(&evsel->node); evsel->attr = *attr; } + +struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) +{ + struct perf_evsel *evsel = zalloc(sizeof(*evsel)); + + if (evsel != NULL) + perf_evsel__init(evsel, attr); + + return evsel; +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index 295583b89f46..21b66fc1937f 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -9,5 +9,6 @@ struct perf_event_attr; LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr); +LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 5e685d6c7a95..e3eac9b60726 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -11,6 +11,7 @@ LIBPERF_0.0.1 { perf_thread_map__comm; perf_thread_map__get; perf_thread_map__put; + perf_evsel__new; perf_evsel__init; perf_evlist__new; perf_evlist__init; -- GitLab From 651bf38ce10a65ef8efb901fc33187127c023e97 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:34 +0200 Subject: [PATCH 1173/7155] libperf: Add perf_evlist__for_each_evsel() iterator Add a perf_evlist__for_each_evsel() macro to iterate perf_evsel objects in evlist. Introduce the perf_evlist__next() function to do that without exposing 'struct perf_evlist' internals. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-48-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 20 ++++++++++++++++++++ tools/perf/lib/include/perf/evlist.h | 7 +++++++ tools/perf/lib/libperf.map | 1 + 3 files changed, 28 insertions(+) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 0517deb4cb1c..979ee423490f 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -34,3 +34,23 @@ struct perf_evlist *perf_evlist__new(void) return evlist; } + +struct perf_evsel * +perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *prev) +{ + struct perf_evsel *next; + + if (!prev) { + next = list_first_entry(&evlist->entries, + struct perf_evsel, + node); + } else { + next = list_next_entry(prev, node); + } + + /* Empty list is noticed here so don't need checking on entry. */ + if (&next->node == &evlist->entries) + return NULL; + + return next; +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 7255a60869a1..5092b622935b 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -13,5 +13,12 @@ LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); LIBPERF_API struct perf_evlist *perf_evlist__new(void); +LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, + struct perf_evsel *evsel); + +#define perf_evlist__for_each_evsel(evlist, pos) \ + for ((pos) = perf_evlist__next((evlist), NULL); \ + (pos) != NULL; \ + (pos) = perf_evlist__next((evlist), (pos))) #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index e3eac9b60726..c0968226f7b6 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -17,6 +17,7 @@ LIBPERF_0.0.1 { perf_evlist__init; perf_evlist__add; perf_evlist__remove; + perf_evlist__next; local: *; }; -- GitLab From 57f0c3b6e13ae822ba02dd37563c8e6956a47141 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:35 +0200 Subject: [PATCH 1174/7155] libperf: Add perf_evlist__delete() function Add the perf_evlist__delete() function to delete a perf_evlist instance. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-49-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 6 ++++++ tools/perf/lib/include/perf/evlist.h | 1 + tools/perf/lib/libperf.map | 1 + 3 files changed, 8 insertions(+) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 979ee423490f..087ef76ea8fd 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -4,6 +4,7 @@ #include #include #include +#include void perf_evlist__init(struct perf_evlist *evlist) { @@ -54,3 +55,8 @@ perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *prev) return next; } + +void perf_evlist__delete(struct perf_evlist *evlist) +{ + free(evlist); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 5092b622935b..9a126fd0773c 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -13,6 +13,7 @@ LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); LIBPERF_API struct perf_evlist *perf_evlist__new(void); +LIBPERF_API void perf_evlist__delete(struct perf_evlist *evlist); LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *evsel); diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index c0968226f7b6..153e77cd6739 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -14,6 +14,7 @@ LIBPERF_0.0.1 { perf_evsel__new; perf_evsel__init; perf_evlist__new; + perf_evlist__delete; perf_evlist__init; perf_evlist__add; perf_evlist__remove; -- GitLab From b9358ee95ec65fe7e2c4dc12e4d3da4aeee0d8fc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:36 +0200 Subject: [PATCH 1175/7155] libperf: Add perf_evsel__delete() function Add the perf_evsel__delete() function to delete a perf_evsel instance. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-50-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 6 ++++++ tools/perf/lib/include/perf/evsel.h | 1 + tools/perf/lib/libperf.map | 1 + 3 files changed, 8 insertions(+) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 8e91738c5c38..ddc3ad447bfb 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -3,6 +3,7 @@ #include #include #include +#include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) { @@ -19,3 +20,8 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) return evsel; } + +void perf_evsel__delete(struct perf_evsel *evsel) +{ + free(evsel); +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index 21b66fc1937f..a57efc0f5c8b 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -10,5 +10,6 @@ struct perf_event_attr; LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr); LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); +LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 153e77cd6739..28ed04cbd223 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -12,6 +12,7 @@ LIBPERF_0.0.1 { perf_thread_map__get; perf_thread_map__put; perf_evsel__new; + perf_evsel__delete; perf_evsel__init; perf_evlist__new; perf_evlist__delete; -- GitLab From d400bd3abf2cc68df2df32047d3533faf690f404 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:37 +0200 Subject: [PATCH 1176/7155] libperf: Add cpus to struct perf_evsel Mov the 'cpus' field from tools/perf's evsel to libperf's perf_evsel. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-51-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-script.c | 2 +- tools/perf/lib/include/internal/evsel.h | 7 +++++-- tools/perf/util/evlist.c | 14 +++++++------- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 3 +-- tools/perf/util/parse-events.c | 2 +- .../util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/stat-display.c | 2 +- 9 files changed, 20 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index b7d2c27c4164..090aaa2cf4b3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -739,7 +739,7 @@ static int record__open(struct record *rec) evlist__for_each_entry(evlist, pos) { try_again: - if (evsel__open(pos, pos->cpus, pos->threads) < 0) { + if (evsel__open(pos, pos->core.cpus, pos->threads) < 0) { if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { if (verbose > 0) ui__warning("%s\n", msg); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 69133b35bbc1..35f07dde5ad4 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1920,7 +1920,7 @@ static void __process_stat(struct evsel *counter, u64 tstamp) counts = perf_counts(counter->counts, cpu, thread); printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n", - counter->cpus->map[cpu], + counter->core.cpus->map[cpu], thread_map__pid(counter->threads, thread), counts->val, counts->ena, diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index c2e0bd104c94..b2c76e1a6244 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -5,9 +5,12 @@ #include #include +struct perf_cpu_map; + struct perf_evsel { - struct list_head node; - struct perf_event_attr attr; + struct list_head node; + struct perf_event_attr attr; + struct perf_cpu_map *cpus; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 67c67e9a38cd..713968130d1d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -160,11 +160,11 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, * keep it, if there's no target cpu list defined. */ if (!evsel->own_cpus || evlist->has_user_cpus) { - perf_cpu_map__put(evsel->cpus); - evsel->cpus = perf_cpu_map__get(evlist->cpus); - } else if (evsel->cpus != evsel->own_cpus) { - perf_cpu_map__put(evsel->cpus); - evsel->cpus = perf_cpu_map__get(evsel->own_cpus); + perf_cpu_map__put(evsel->core.cpus); + evsel->core.cpus = perf_cpu_map__get(evlist->cpus); + } else if (evsel->core.cpus != evsel->own_cpus) { + perf_cpu_map__put(evsel->core.cpus); + evsel->core.cpus = perf_cpu_map__get(evsel->own_cpus); } perf_thread_map__put(evsel->threads); @@ -786,7 +786,7 @@ static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, if (evsel->system_wide && thread) continue; - cpu = cpu_map__idx(evsel->cpus, evlist_cpu); + cpu = cpu_map__idx(evsel->core.cpus, evlist_cpu); if (cpu == -1) continue; @@ -1407,7 +1407,7 @@ int evlist__open(struct evlist *evlist) perf_evlist__update_id_pos(evlist); evlist__for_each_entry(evlist, evsel) { - err = evsel__open(evsel, evsel->cpus, evsel->threads); + err = evsel__open(evsel, evsel->core.cpus, evsel->threads); if (err < 0) goto out_err; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 089582e644d7..651f66ee902e 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1325,7 +1325,7 @@ void perf_evsel__exit(struct evsel *evsel) perf_evsel__free_id(evsel); perf_evsel__free_config_terms(evsel); cgroup__put(evsel->cgrp); - perf_cpu_map__put(evsel->cpus); + perf_cpu_map__put(evsel->core.cpus); perf_cpu_map__put(evsel->own_cpus); perf_thread_map__put(evsel->threads); zfree(&evsel->group_name); @@ -3064,7 +3064,7 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist) { - struct perf_cpu_map *cpus = evsel->cpus; + struct perf_cpu_map *cpus = evsel->core.cpus; struct perf_thread_map *threads = evsel->threads; if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr)) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 43f66158de3b..8ece5edf65ac 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -123,7 +123,6 @@ struct evsel { u64 db_id; struct cgroup *cgrp; void *handler; - struct perf_cpu_map *cpus; struct perf_cpu_map *own_cpus; struct perf_thread_map *threads; unsigned int sample_size; @@ -198,7 +197,7 @@ struct record_opts; static inline struct perf_cpu_map *evsel__cpus(struct evsel *evsel) { - return evsel->cpus; + return evsel->core.cpus; } static inline int perf_evsel__nr_cpus(struct evsel *evsel) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index db2460d6b625..a27771eca9c2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -333,7 +333,7 @@ __add_event(struct list_head *list, int *idx, return NULL; (*idx)++; - evsel->cpus = perf_cpu_map__get(cpus); + evsel->core.cpus = perf_cpu_map__get(cpus); evsel->own_cpus = perf_cpu_map__get(cpus); evsel->system_wide = pmu ? pmu->is_uncore : false; evsel->auto_merge_stats = auto_merge_stats; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 78b40c1d688e..c5f520e0885b 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1393,7 +1393,7 @@ static void python_process_stat(struct perf_stat_config *config, struct evsel *counter, u64 tstamp) { struct perf_thread_map *threads = counter->threads; - struct perf_cpu_map *cpus = counter->cpus; + struct perf_cpu_map *cpus = counter->core.cpus; int cpu, thread; if (config->aggr_mode == AGGR_GLOBAL) { diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 99bda99a1b2d..e84f8063c2db 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -745,7 +745,7 @@ static void print_aggr_thread(struct perf_stat_config *config, { FILE *output = config->output; int nthreads = thread_map__nr(counter->threads); - int ncpus = cpu_map__nr(counter->cpus); + int ncpus = cpu_map__nr(counter->core.cpus); int thread, sorted_threads, id; struct perf_aggr_thread_value *buf; -- GitLab From fe1f61b37ffada9fc7ec2c9d4ca5376b5a797dbc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:38 +0200 Subject: [PATCH 1177/7155] libperf: Add own_cpus to struct perf_evsel Move own_cpus from tools/perf's evsel to libbpf's perf_evsel. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-52-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/internal/evsel.h | 1 + tools/perf/tests/event_update.c | 4 ++-- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 1 - tools/perf/util/header.c | 10 +++++----- tools/perf/util/parse-events.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index b2c76e1a6244..d15d8ccfa3dc 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -11,6 +11,7 @@ struct perf_evsel { struct list_head node; struct perf_event_attr attr; struct perf_cpu_map *cpus; + struct perf_cpu_map *own_cpus; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index 2bc5145284c0..c37ff49c07c7 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -109,11 +109,11 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu TEST_ASSERT_VAL("failed to synthesize attr update name", !perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name)); - evsel->own_cpus = perf_cpu_map__new("1,2,3"); + evsel->core.own_cpus = perf_cpu_map__new("1,2,3"); TEST_ASSERT_VAL("failed to synthesize attr update cpus", !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); - perf_cpu_map__put(evsel->own_cpus); + perf_cpu_map__put(evsel->core.own_cpus); return 0; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 713968130d1d..d203305ac187 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -159,12 +159,12 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, * We already have cpus for evsel (via PMU sysfs) so * keep it, if there's no target cpu list defined. */ - if (!evsel->own_cpus || evlist->has_user_cpus) { + if (!evsel->core.own_cpus || evlist->has_user_cpus) { perf_cpu_map__put(evsel->core.cpus); evsel->core.cpus = perf_cpu_map__get(evlist->cpus); - } else if (evsel->core.cpus != evsel->own_cpus) { + } else if (evsel->core.cpus != evsel->core.own_cpus) { perf_cpu_map__put(evsel->core.cpus); - evsel->core.cpus = perf_cpu_map__get(evsel->own_cpus); + evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); } perf_thread_map__put(evsel->threads); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 651f66ee902e..c5f6ee6d5f3b 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1125,7 +1125,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, attr->exclude_user = 1; } - if (evsel->own_cpus || evsel->unit) + if (evsel->core.own_cpus || evsel->unit) evsel->core.attr.read_format |= PERF_FORMAT_ID; /* @@ -1326,7 +1326,7 @@ void perf_evsel__exit(struct evsel *evsel) perf_evsel__free_config_terms(evsel); cgroup__put(evsel->cgrp); perf_cpu_map__put(evsel->core.cpus); - perf_cpu_map__put(evsel->own_cpus); + perf_cpu_map__put(evsel->core.own_cpus); perf_thread_map__put(evsel->threads); zfree(&evsel->group_name); zfree(&evsel->name); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8ece5edf65ac..2eff837f10bd 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -123,7 +123,6 @@ struct evsel { u64 db_id; struct cgroup *cgrp; void *handler; - struct perf_cpu_map *own_cpus; struct perf_thread_map *threads; unsigned int sample_size; int id_pos; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index fa914ba8cd56..f97df418d661 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3861,10 +3861,10 @@ perf_event__synthesize_event_update_cpus(struct perf_tool *tool, int max, err; u16 type; - if (!evsel->own_cpus) + if (!evsel->core.own_cpus) return 0; - ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max); + ev = cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max); if (!ev) return -ENOMEM; @@ -3874,7 +3874,7 @@ perf_event__synthesize_event_update_cpus(struct perf_tool *tool, ev->id = evsel->id[0]; cpu_map_data__synthesize((struct cpu_map_data *) ev->data, - evsel->own_cpus, + evsel->core.own_cpus, type, max); err = process(tool, (union perf_event*) ev, NULL, NULL); @@ -3985,7 +3985,7 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool, } } - if (counter->own_cpus) { + if (counter->core.own_cpus) { err = perf_event__synthesize_event_update_cpus(tool, counter, process); if (err < 0) { pr_err("Couldn't synthesize evsel cpus.\n"); @@ -4082,7 +4082,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, map = cpu_map__new_data(&ev_cpus->cpus); if (map) - evsel->own_cpus = map; + evsel->core.own_cpus = map; else pr_err("failed to get event_update cpus\n"); default: diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a27771eca9c2..8182b1e66ec6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -334,7 +334,7 @@ __add_event(struct list_head *list, int *idx, (*idx)++; evsel->core.cpus = perf_cpu_map__get(cpus); - evsel->own_cpus = perf_cpu_map__get(cpus); + evsel->core.own_cpus = perf_cpu_map__get(cpus); evsel->system_wide = pmu ? pmu->is_uncore : false; evsel->auto_merge_stats = auto_merge_stats; -- GitLab From af663bd01beaff8d9514199fcc1b239902a77de5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:39 +0200 Subject: [PATCH 1178/7155] libperf: Add threads to struct perf_evsel Move 'threads' from tools/perf's evsel to libperf's perf_evsel struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-53-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-script.c | 4 ++-- tools/perf/lib/include/internal/evsel.h | 2 ++ tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 1 - tools/perf/util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/stat-display.c | 6 +++--- tools/perf/util/stat.c | 6 +++--- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 090aaa2cf4b3..27ff899bed88 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -739,7 +739,7 @@ static int record__open(struct record *rec) evlist__for_each_entry(evlist, pos) { try_again: - if (evsel__open(pos, pos->core.cpus, pos->threads) < 0) { + if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { if (verbose > 0) ui__warning("%s\n", msg); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 35f07dde5ad4..a787c5cb1331 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1899,7 +1899,7 @@ static struct scripting_ops *scripting_ops; static void __process_stat(struct evsel *counter, u64 tstamp) { - int nthreads = thread_map__nr(counter->threads); + int nthreads = thread_map__nr(counter->core.threads); int ncpus = perf_evsel__nr_cpus(counter); int cpu, thread; static int header_printed; @@ -1921,7 +1921,7 @@ static void __process_stat(struct evsel *counter, u64 tstamp) printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n", counter->core.cpus->map[cpu], - thread_map__pid(counter->threads, thread), + thread_map__pid(counter->core.threads, thread), counts->val, counts->ena, counts->run, diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index d15d8ccfa3dc..8340fd883a3d 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -6,12 +6,14 @@ #include struct perf_cpu_map; +struct perf_thread_map; struct perf_evsel { struct list_head node; struct perf_event_attr attr; struct perf_cpu_map *cpus; struct perf_cpu_map *own_cpus; + struct perf_thread_map *threads; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d203305ac187..5ce8fc730453 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -167,8 +167,8 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); } - perf_thread_map__put(evsel->threads); - evsel->threads = perf_thread_map__get(evlist->threads); + perf_thread_map__put(evsel->core.threads); + evsel->core.threads = perf_thread_map__get(evlist->threads); } static void perf_evlist__propagate_maps(struct evlist *evlist) @@ -1407,7 +1407,7 @@ int evlist__open(struct evlist *evlist) perf_evlist__update_id_pos(evlist); evlist__for_each_entry(evlist, evsel) { - err = evsel__open(evsel, evsel->core.cpus, evsel->threads); + err = evsel__open(evsel, evsel->core.cpus, evsel->core.threads); if (err < 0) goto out_err; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index c5f6ee6d5f3b..f7758ce0dd5c 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1327,7 +1327,7 @@ void perf_evsel__exit(struct evsel *evsel) cgroup__put(evsel->cgrp); perf_cpu_map__put(evsel->core.cpus); perf_cpu_map__put(evsel->core.own_cpus); - perf_thread_map__put(evsel->threads); + perf_thread_map__put(evsel->core.threads); zfree(&evsel->group_name); zfree(&evsel->name); perf_evsel__object.fini(evsel); @@ -3065,7 +3065,7 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist) { struct perf_cpu_map *cpus = evsel->core.cpus; - struct perf_thread_map *threads = evsel->threads; + struct perf_thread_map *threads = evsel->core.threads; if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr)) return -ENOMEM; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 2eff837f10bd..57b5523b480c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -123,7 +123,6 @@ struct evsel { u64 db_id; struct cgroup *cgrp; void *handler; - struct perf_thread_map *threads; unsigned int sample_size; int id_pos; int is_pos; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index c5f520e0885b..32c17a727450 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1392,7 +1392,7 @@ process_stat(struct evsel *counter, int cpu, int thread, u64 tstamp, static void python_process_stat(struct perf_stat_config *config, struct evsel *counter, u64 tstamp) { - struct perf_thread_map *threads = counter->threads; + struct perf_thread_map *threads = counter->core.threads; struct perf_cpu_map *cpus = counter->core.cpus; int cpu, thread; diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index e84f8063c2db..7c938135398b 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -116,9 +116,9 @@ static void aggr_printout(struct perf_stat_config *config, case AGGR_THREAD: fprintf(config->output, "%*s-%*d%s", config->csv_output ? 0 : 16, - perf_thread_map__comm(evsel->threads, id), + perf_thread_map__comm(evsel->core.threads, id), config->csv_output ? 0 : -8, - thread_map__pid(evsel->threads, id), + thread_map__pid(evsel->core.threads, id), config->csv_sep); break; case AGGR_GLOBAL: @@ -744,7 +744,7 @@ static void print_aggr_thread(struct perf_stat_config *config, struct evsel *counter, char *prefix) { FILE *output = config->output; - int nthreads = thread_map__nr(counter->threads); + int nthreads = thread_map__nr(counter->core.threads); int ncpus = cpu_map__nr(counter->core.cpus); int thread, sorted_threads, id; struct perf_aggr_thread_value *buf; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 632bf72cf780..1e351462ca49 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -158,7 +158,7 @@ static void perf_evsel__free_prev_raw_counts(struct evsel *evsel) static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw) { int ncpus = perf_evsel__nr_cpus(evsel); - int nthreads = thread_map__nr(evsel->threads); + int nthreads = thread_map__nr(evsel->core.threads); if (perf_evsel__alloc_stat_priv(evsel) < 0 || perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || @@ -308,7 +308,7 @@ process_counter_values(struct perf_stat_config *config, struct evsel *evsel, static int process_counter_maps(struct perf_stat_config *config, struct evsel *counter) { - int nthreads = thread_map__nr(counter->threads); + int nthreads = thread_map__nr(counter->core.threads); int ncpus = perf_evsel__nr_cpus(counter); int cpu, thread; @@ -485,7 +485,7 @@ int create_perf_stat_counter(struct evsel *evsel, if (target__has_cpu(target) && !target__has_per_thread(target)) return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel)); - return perf_evsel__open_per_thread(evsel, evsel->threads); + return perf_evsel__open_per_thread(evsel, evsel->core.threads); } int perf_stat_synthesize_config(struct perf_stat_config *config, -- GitLab From ec903f264f0184a0aba62b42d7717c61f1893450 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:40 +0200 Subject: [PATCH 1179/7155] libperf: Add has_user_cpus to struct perf_evlist Move has_user_cpus from tools/perf's evlist to libbperf's perf_evlist struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-54-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/internal/evlist.h | 1 + tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evlist.h | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index a12c712a9197..9964e4a9456e 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -5,6 +5,7 @@ struct perf_evlist { struct list_head entries; int nr_entries; + bool has_user_cpus; }; #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 5ce8fc730453..23a8ead4512f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -159,7 +159,7 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, * We already have cpus for evsel (via PMU sysfs) so * keep it, if there's no target cpu list defined. */ - if (!evsel->core.own_cpus || evlist->has_user_cpus) { + if (!evsel->core.own_cpus || evlist->core.has_user_cpus) { perf_cpu_map__put(evsel->core.cpus); evsel->core.cpus = perf_cpu_map__get(evlist->cpus); } else if (evsel->core.cpus != evsel->core.own_cpus) { @@ -1095,7 +1095,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) if (!cpus) goto out_delete_threads; - evlist->has_user_cpus = !!target->cpu_list; + evlist->core.has_user_cpus = !!target->cpu_list; perf_evlist__set_maps(evlist, cpus, threads); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 17dd83021a79..35cca0242631 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -31,7 +31,6 @@ struct evlist { int nr_groups; int nr_mmaps; bool enabled; - bool has_user_cpus; size_t mmap_len; int id_pos; int is_pos; -- GitLab From f72f901d90b00aaf2a6c1335b41311687b3f2dec Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:41 +0200 Subject: [PATCH 1180/7155] libperf: Add cpus to struct perf_evlist Move cpus from tools/perf's evlist to libperf's perf_evlist struct. Committer notes: Fixed up this one: tools/perf/arch/arm/util/cs-etm.c Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-55-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 8 +++--- tools/perf/arch/x86/util/intel-bts.c | 2 +- tools/perf/arch/x86/util/intel-pt.c | 4 +-- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 16 +++++------ tools/perf/builtin-top.c | 2 +- tools/perf/lib/include/internal/evlist.h | 9 ++++-- tools/perf/util/auxtrace.c | 2 +- tools/perf/util/evlist.c | 36 ++++++++++++------------ tools/perf/util/evlist.h | 1 - tools/perf/util/record.c | 6 ++-- tools/perf/util/stat-display.c | 6 ++-- tools/perf/util/stat.c | 2 +- tools/perf/util/top.c | 6 ++-- 15 files changed, 53 insertions(+), 51 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index c25bc1528b96..5cb07e8cb296 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -155,7 +155,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr, struct evsel *evsel, u32 option) { int i, err = -EINVAL; - struct perf_cpu_map *event_cpus = evsel->evlist->cpus; + struct perf_cpu_map *event_cpus = evsel->evlist->core.cpus; struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); /* Set option of each CPU we have */ @@ -253,7 +253,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, container_of(itr, struct cs_etm_recording, itr); struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; struct evsel *evsel, *cs_etm_evsel = NULL; - struct perf_cpu_map *cpus = evlist->cpus; + struct perf_cpu_map *cpus = evlist->core.cpus; bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0); int err = 0; @@ -489,7 +489,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, { int i; int etmv3 = 0, etmv4 = 0; - struct perf_cpu_map *event_cpus = evlist->cpus; + struct perf_cpu_map *event_cpus = evlist->core.cpus; struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); /* cpu map is not empty, we have specific CPUs to work with */ @@ -636,7 +636,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, u32 offset; u64 nr_cpu, type; struct perf_cpu_map *cpu_map; - struct perf_cpu_map *event_cpus = session->evlist->cpus; + struct perf_cpu_map *event_cpus = session->evlist->core.cpus; struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index d8a091266185..7b23318ebd7b 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -106,7 +106,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, container_of(itr, struct intel_bts_recording, itr); struct perf_pmu *intel_bts_pmu = btsr->intel_bts_pmu; struct evsel *evsel, *intel_bts_evsel = NULL; - const struct perf_cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->core.cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; btsr->evlist = evlist; diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index aada6a2c456a..218a4e694618 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -365,7 +365,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, ui__warning("Intel Processor Trace: TSC not available\n"); } - per_cpu_mmaps = !cpu_map__empty(session->evlist->cpus); + per_cpu_mmaps = !cpu_map__empty(session->evlist->core.cpus); auxtrace_info->type = PERF_AUXTRACE_INTEL_PT; auxtrace_info->priv[INTEL_PT_PMU_TYPE] = intel_pt_pmu->type; @@ -557,7 +557,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; bool have_timing_info, need_immediate = false; struct evsel *evsel, *intel_pt_evsel = NULL; - const struct perf_cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->core.cpus; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; u64 tsc_bit; int err; diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 77989254fdd8..f481a870e728 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -192,7 +192,7 @@ static int set_tracing_cpumask(struct perf_cpu_map *cpumap) static int set_tracing_cpu(struct perf_ftrace *ftrace) { - struct perf_cpu_map *cpumap = ftrace->evlist->cpus; + struct perf_cpu_map *cpumap = ftrace->evlist->core.cpus; if (!target__has_cpu(&ftrace->target)) return 0; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 27ff899bed88..d4f0430c2f49 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1283,7 +1283,7 @@ static int record__synthesize(struct record *rec, bool tail) return err; } - err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus, + err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize cpu map.\n"); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8ad3643d61f9..d81b0b1ef514 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -884,21 +884,21 @@ static int perf_stat_init_aggr_mode(void) switch (stat_config.aggr_mode) { case AGGR_SOCKET: - if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) { + if (cpu_map__build_socket_map(evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build socket map"); return -1; } stat_config.aggr_get_id = perf_stat__get_socket_cached; break; case AGGR_DIE: - if (cpu_map__build_die_map(evsel_list->cpus, &stat_config.aggr_map)) { + if (cpu_map__build_die_map(evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build die map"); return -1; } stat_config.aggr_get_id = perf_stat__get_die_cached; break; case AGGR_CORE: - if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) { + if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build core map"); return -1; } @@ -906,7 +906,7 @@ static int perf_stat_init_aggr_mode(void) break; case AGGR_NONE: if (term_percore_set()) { - if (cpu_map__build_core_map(evsel_list->cpus, + if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build core map"); return -1; @@ -926,7 +926,7 @@ static int perf_stat_init_aggr_mode(void) * taking the highest cpu number to be the size of * the aggregation translate cpumap. */ - nr = cpu_map__get_max(evsel_list->cpus); + nr = cpu_map__get_max(evsel_list->core.cpus); stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1); return stat_config.cpus_aggr_map ? 0 : -ENOMEM; } @@ -1057,21 +1057,21 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) switch (stat_config.aggr_mode) { case AGGR_SOCKET: - if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) { + if (perf_env__build_socket_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build socket map"); return -1; } stat_config.aggr_get_id = perf_stat__get_socket_file; break; case AGGR_DIE: - if (perf_env__build_die_map(env, evsel_list->cpus, &stat_config.aggr_map)) { + if (perf_env__build_die_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build die map"); return -1; } stat_config.aggr_get_id = perf_stat__get_die_file; break; case AGGR_CORE: - if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) { + if (perf_env__build_core_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) { perror("cannot build core map"); return -1; } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 54d06d271bfd..947f83e53272 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -989,7 +989,7 @@ static int perf_top__start_counters(struct perf_top *top) evlist__for_each_entry(evlist, counter) { try_again: - if (evsel__open(counter, top->evlist->cpus, + if (evsel__open(counter, top->evlist->core.cpus, top->evlist->threads) < 0) { /* diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index 9964e4a9456e..f9caab1fe3c3 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -2,10 +2,13 @@ #ifndef __LIBPERF_INTERNAL_EVLIST_H #define __LIBPERF_INTERNAL_EVLIST_H +struct perf_cpu_map; + struct perf_evlist { - struct list_head entries; - int nr_entries; - bool has_user_cpus; + struct list_head entries; + int nr_entries; + bool has_user_cpus; + struct perf_cpu_map *cpus; }; #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 843959f85d6f..67a2afc5d964 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -130,7 +130,7 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, mp->idx = idx; if (per_cpu) { - mp->cpu = evlist->cpus->map[idx]; + mp->cpu = evlist->core.cpus->map[idx]; if (evlist->threads) mp->tid = thread_map__pid(evlist->threads, 0); else diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 23a8ead4512f..977b9291fb0d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -143,9 +143,9 @@ void evlist__delete(struct evlist *evlist) perf_evlist__munmap(evlist); evlist__close(evlist); - perf_cpu_map__put(evlist->cpus); + perf_cpu_map__put(evlist->core.cpus); perf_thread_map__put(evlist->threads); - evlist->cpus = NULL; + evlist->core.cpus = NULL; evlist->threads = NULL; perf_evlist__purge(evlist); perf_evlist__exit(evlist); @@ -161,7 +161,7 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, */ if (!evsel->core.own_cpus || evlist->core.has_user_cpus) { perf_cpu_map__put(evsel->core.cpus); - evsel->core.cpus = perf_cpu_map__get(evlist->cpus); + evsel->core.cpus = perf_cpu_map__get(evlist->core.cpus); } else if (evsel->core.cpus != evsel->core.own_cpus) { perf_cpu_map__put(evsel->core.cpus); evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); @@ -398,7 +398,7 @@ static int perf_evlist__enable_event_thread(struct evlist *evlist, int thread) { int cpu; - int nr_cpus = cpu_map__nr(evlist->cpus); + int nr_cpus = cpu_map__nr(evlist->core.cpus); if (!evsel->fd) return -EINVAL; @@ -414,7 +414,7 @@ static int perf_evlist__enable_event_thread(struct evlist *evlist, int perf_evlist__enable_event_idx(struct evlist *evlist, struct evsel *evsel, int idx) { - bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus); + bool per_cpu_mmaps = !cpu_map__empty(evlist->core.cpus); if (per_cpu_mmaps) return perf_evlist__enable_event_cpu(evlist, evsel, idx); @@ -424,7 +424,7 @@ int perf_evlist__enable_event_idx(struct evlist *evlist, int perf_evlist__alloc_pollfd(struct evlist *evlist) { - int nr_cpus = cpu_map__nr(evlist->cpus); + int nr_cpus = cpu_map__nr(evlist->core.cpus); int nr_threads = thread_map__nr(evlist->threads); int nfds = 0; struct evsel *evsel; @@ -552,8 +552,8 @@ static void perf_evlist__set_sid_idx(struct evlist *evlist, { struct perf_sample_id *sid = SID(evsel, cpu, thread); sid->idx = idx; - if (evlist->cpus && cpu >= 0) - sid->cpu = evlist->cpus->map[cpu]; + if (evlist->core.cpus && cpu >= 0) + sid->cpu = evlist->core.cpus->map[cpu]; else sid->cpu = -1; if (!evsel->system_wide && evlist->threads && thread >= 0) @@ -720,8 +720,8 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, int i; struct perf_mmap *map; - evlist->nr_mmaps = cpu_map__nr(evlist->cpus); - if (cpu_map__empty(evlist->cpus)) + evlist->nr_mmaps = cpu_map__nr(evlist->core.cpus); + if (cpu_map__empty(evlist->core.cpus)) evlist->nr_mmaps = thread_map__nr(evlist->threads); map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); if (!map) @@ -759,7 +759,7 @@ static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, { struct evsel *evsel; int revent; - int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx); + int evlist_cpu = cpu_map__cpu(evlist->core.cpus, cpu_idx); evlist__for_each_entry(evlist, evsel) { struct perf_mmap *maps = evlist->mmap; @@ -835,7 +835,7 @@ static int perf_evlist__mmap_per_cpu(struct evlist *evlist, struct mmap_params *mp) { int cpu, thread; - int nr_cpus = cpu_map__nr(evlist->cpus); + int nr_cpus = cpu_map__nr(evlist->core.cpus); int nr_threads = thread_map__nr(evlist->threads); pr_debug2("perf event ring buffer mmapped per cpu\n"); @@ -1014,7 +1014,7 @@ int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, int comp_level) { struct evsel *evsel; - const struct perf_cpu_map *cpus = evlist->cpus; + const struct perf_cpu_map *cpus = evlist->core.cpus; const struct perf_thread_map *threads = evlist->threads; /* * Delay setting mp.prot: set it before calling perf_mmap__mmap. @@ -1116,9 +1116,9 @@ void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, * original reference count of 1. If that is not the case it is up to * the caller to increase the reference count. */ - if (cpus != evlist->cpus) { - perf_cpu_map__put(evlist->cpus); - evlist->cpus = perf_cpu_map__get(cpus); + if (cpus != evlist->core.cpus) { + perf_cpu_map__put(evlist->core.cpus); + evlist->core.cpus = perf_cpu_map__get(cpus); } if (threads != evlist->threads) { @@ -1398,7 +1398,7 @@ int evlist__open(struct evlist *evlist) * Default: one fd per CPU, all threads, aka systemwide * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL */ - if (evlist->threads == NULL && evlist->cpus == NULL) { + if (evlist->threads == NULL && evlist->core.cpus == NULL) { err = perf_evlist__create_syswide_maps(evlist); if (err < 0) goto out_err; @@ -1920,7 +1920,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, goto out_delete_evlist; evlist__for_each_entry(evlist, counter) { - if (evsel__open(counter, evlist->cpus, + if (evsel__open(counter, evlist->core.cpus, evlist->threads) < 0) goto out_delete_evlist; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 35cca0242631..fdd8f83eac2d 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -44,7 +44,6 @@ struct evlist { struct perf_mmap *mmap; struct perf_mmap *overwrite_mmap; struct perf_thread_map *threads; - struct perf_cpu_map *cpus; struct evsel *selected; struct events_stats stats; struct perf_env *env; diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 03dcdb3f33a7..e59382d99196 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -148,7 +148,7 @@ void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, if (opts->group) perf_evlist__set_leader(evlist); - if (evlist->cpus->map[0] < 0) + if (evlist->core.cpus->map[0] < 0) opts->no_inherit = true; use_comm_exec = perf_can_comm_exec(); @@ -275,13 +275,13 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) evsel = perf_evlist__last(temp_evlist); - if (!evlist || cpu_map__empty(evlist->cpus)) { + if (!evlist || cpu_map__empty(evlist->core.cpus)) { struct perf_cpu_map *cpus = perf_cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; perf_cpu_map__put(cpus); } else { - cpu = evlist->cpus->map[0]; + cpu = evlist->core.cpus->map[0]; } while (1) { diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 7c938135398b..4a162858583f 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -327,7 +327,7 @@ static int first_shadow_cpu(struct perf_stat_config *config, for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { int cpu2 = evsel__cpus(evsel)->map[i]; - if (config->aggr_get_id(config, evlist->cpus, cpu2) == id) + if (config->aggr_get_id(config, evlist->core.cpus, cpu2) == id) return cpu2; } return 0; @@ -500,7 +500,7 @@ static void aggr_update_shadow(struct perf_stat_config *config, evlist__for_each_entry(evlist, counter) { val = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - s2 = config->aggr_get_id(config, evlist->cpus, cpu); + s2 = config->aggr_get_id(config, evlist->core.cpus, cpu); if (s2 != id) continue; val += perf_counts(counter->counts, cpu, 0)->val; @@ -868,7 +868,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config, u64 ena, run, val; double uval; - nrcpus = evlist->cpus->nr; + nrcpus = evlist->core.cpus->nr; for (cpu = 0; cpu < nrcpus; cpu++) { bool first = true; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 1e351462ca49..24c9c3015983 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -514,7 +514,7 @@ int perf_stat_synthesize_config(struct perf_stat_config *config, return err; } - err = perf_event__synthesize_cpu_map(tool, evlist->cpus, + err = perf_event__synthesize_cpu_map(tool, evlist->core.cpus, process, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index f533f1aac045..e5b690cf2898 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -95,15 +95,15 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) if (target->cpu_list) ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", - top->evlist->cpus->nr > 1 ? "s" : "", + top->evlist->core.cpus->nr > 1 ? "s" : "", target->cpu_list); else { if (target->tid) ret += SNPRINTF(bf + ret, size - ret, ")"); else ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", - top->evlist->cpus->nr, - top->evlist->cpus->nr > 1 ? "s" : ""); + top->evlist->core.cpus->nr, + top->evlist->core.cpus->nr > 1 ? "s" : ""); } perf_top__reset_sample_counters(top); -- GitLab From 03617c22e31f32cbf0e4797e216db898fb898d90 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:42 +0200 Subject: [PATCH 1181/7155] libperf: Add threads to struct perf_evlist Move threads from tools/perf's evlist to libperf's perf_evlist struct. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-56-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-ftrace.c | 4 +-- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 +-- tools/perf/builtin-stat.c | 18 +++++------ tools/perf/builtin-top.c | 4 +-- tools/perf/builtin-trace.c | 8 ++--- tools/perf/lib/include/internal/evlist.h | 2 ++ tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/util/auxtrace.c | 6 ++-- tools/perf/util/evlist.c | 36 ++++++++++----------- tools/perf/util/evlist.h | 1 - tools/perf/util/stat.c | 2 +- 12 files changed, 45 insertions(+), 44 deletions(-) diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index f481a870e728..ae1466aa3b26 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -156,9 +156,9 @@ static int set_tracing_pid(struct perf_ftrace *ftrace) if (target__has_cpu(&ftrace->target)) return 0; - for (i = 0; i < thread_map__nr(ftrace->evlist->threads); i++) { + for (i = 0; i < thread_map__nr(ftrace->evlist->core.threads); i++) { scnprintf(buf, sizeof(buf), "%d", - ftrace->evlist->threads->map[i]); + ftrace->evlist->core.threads->map[i]); if (append_tracing_file("set_ftrace_pid", buf) < 0) return -1; } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index b9c58a5c1ba6..69d16ac852c3 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1450,7 +1450,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, perf_session__set_id_hdr_size(kvm->session); ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true); machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, - kvm->evlist->threads, false, 1); + kvm->evlist->core.threads, false, 1); err = kvm_live_open_events(kvm); if (err) goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d4f0430c2f49..d31d7a5a1be3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1275,7 +1275,7 @@ static int record__synthesize(struct record *rec, bool tail) if (err) goto out; - err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads, + err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads, process_synthesized_event, NULL); if (err < 0) { @@ -1295,7 +1295,7 @@ static int record__synthesize(struct record *rec, bool tail) if (err < 0) pr_warning("Couldn't synthesize bpf events.\n"); - err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, + err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads, process_synthesized_event, opts->sample_address, 1); out: diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d81b0b1ef514..4a94ca131d56 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -263,7 +263,7 @@ static int read_single_counter(struct evsel *counter, int cpu, */ static int read_counter(struct evsel *counter, struct timespec *rs) { - int nthreads = thread_map__nr(evsel_list->threads); + int nthreads = thread_map__nr(evsel_list->core.threads); int ncpus, cpu, thread; if (target__has_cpu(&target) && !target__has_per_thread(&target)) @@ -485,15 +485,15 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) ui__warning("%s\n", msg); goto try_again; } else if (target__has_per_thread(&target) && - evsel_list->threads && - evsel_list->threads->err_thread != -1) { + evsel_list->core.threads && + evsel_list->core.threads->err_thread != -1) { /* * For global --per-thread case, skip current * error thread. */ - if (!thread_map__remove(evsel_list->threads, - evsel_list->threads->err_thread)) { - evsel_list->threads->err_thread = -1; + if (!thread_map__remove(evsel_list->core.threads, + evsel_list->core.threads->err_thread)) { + evsel_list->core.threads->err_thread = -1; goto try_again; } } @@ -579,7 +579,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) enable_counters(); while (!done) { nanosleep(&ts, NULL); - if (!is_target_alive(&target, evsel_list->threads)) + if (!is_target_alive(&target, evsel_list->core.threads)) break; if (timeout) break; @@ -1889,10 +1889,10 @@ int cmd_stat(int argc, const char **argv) * so we could print it out on output. */ if (stat_config.aggr_mode == AGGR_THREAD) { - thread_map__read_comms(evsel_list->threads); + thread_map__read_comms(evsel_list->core.threads); if (target.system_wide) { if (runtime_stat_new(&stat_config, - thread_map__nr(evsel_list->threads))) { + thread_map__nr(evsel_list->core.threads))) { goto out; } } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 947f83e53272..c69ddc67c672 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -990,7 +990,7 @@ static int perf_top__start_counters(struct perf_top *top) evlist__for_each_entry(evlist, counter) { try_again: if (evsel__open(counter, top->evlist->core.cpus, - top->evlist->threads) < 0) { + top->evlist->core.threads) < 0) { /* * Specially handle overwrite fall back. @@ -1222,7 +1222,7 @@ static int __cmd_top(struct perf_top *top) pr_debug("Couldn't synthesize BPF events: Pre-existing BPF programs won't have symbols resolved.\n"); machine__synthesize_threads(&top->session->machines.host, &opts->target, - top->evlist->threads, false, + top->evlist->core.threads, false, top->nr_threads_synthesize); if (top->nr_threads_synthesize > 1) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index abfd22ff1730..35f3684f5327 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1404,7 +1404,7 @@ static int trace__symbols_init(struct trace *trace, struct evlist *evlist) goto out; err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, - evlist->threads, trace__tool_process, false, + evlist->core.threads, trace__tool_process, false, 1); out: if (err) @@ -3183,7 +3183,7 @@ static int trace__set_filter_pids(struct trace *trace) err = bpf_map__set_filter_pids(trace->filter_pids.map, trace->filter_pids.nr, trace->filter_pids.entries); } - } else if (thread_map__pid(trace->evlist->threads, 0) == -1) { + } else if (thread_map__pid(trace->evlist->core.threads, 0) == -1) { err = trace__set_filter_loop_pids(trace); } @@ -3412,8 +3412,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv) evlist__enable(evlist); } - trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || - evlist->threads->nr > 1 || + trace->multiple_threads = thread_map__pid(evlist->core.threads, 0) == -1 || + evlist->core.threads->nr > 1 || perf_evlist__first(evlist)->core.attr.inherit; /* diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index f9caab1fe3c3..b7b43dbc9b82 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -3,12 +3,14 @@ #define __LIBPERF_INTERNAL_EVLIST_H struct perf_cpu_map; +struct perf_thread_map; struct perf_evlist { struct list_head entries; int nr_entries; bool has_user_cpus; struct perf_cpu_map *cpus; + struct perf_thread_map *threads; }; #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 1de79208e690..9c06130d37be 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -58,7 +58,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest perf_evsel__config(evsel, &opts, NULL); - perf_thread_map__set_pid(evlist->threads, 0, getpid()); + perf_thread_map__set_pid(evlist->core.threads, 0, getpid()); err = evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 67a2afc5d964..65728cdeefb6 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -131,13 +131,13 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, if (per_cpu) { mp->cpu = evlist->core.cpus->map[idx]; - if (evlist->threads) - mp->tid = thread_map__pid(evlist->threads, 0); + if (evlist->core.threads) + mp->tid = thread_map__pid(evlist->core.threads, 0); else mp->tid = -1; } else { mp->cpu = -1; - mp->tid = thread_map__pid(evlist->threads, idx); + mp->tid = thread_map__pid(evlist->core.threads, idx); } } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 977b9291fb0d..1a6f877ebb03 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -144,9 +144,9 @@ void evlist__delete(struct evlist *evlist) perf_evlist__munmap(evlist); evlist__close(evlist); perf_cpu_map__put(evlist->core.cpus); - perf_thread_map__put(evlist->threads); + perf_thread_map__put(evlist->core.threads); evlist->core.cpus = NULL; - evlist->threads = NULL; + evlist->core.threads = NULL; perf_evlist__purge(evlist); perf_evlist__exit(evlist); free(evlist); @@ -168,7 +168,7 @@ static void __perf_evlist__propagate_maps(struct evlist *evlist, } perf_thread_map__put(evsel->core.threads); - evsel->core.threads = perf_thread_map__get(evlist->threads); + evsel->core.threads = perf_thread_map__get(evlist->core.threads); } static void perf_evlist__propagate_maps(struct evlist *evlist) @@ -342,7 +342,7 @@ static int perf_evlist__nr_threads(struct evlist *evlist, if (evsel->system_wide) return 1; else - return thread_map__nr(evlist->threads); + return thread_map__nr(evlist->core.threads); } void evlist__disable(struct evlist *evlist) @@ -425,7 +425,7 @@ int perf_evlist__enable_event_idx(struct evlist *evlist, int perf_evlist__alloc_pollfd(struct evlist *evlist) { int nr_cpus = cpu_map__nr(evlist->core.cpus); - int nr_threads = thread_map__nr(evlist->threads); + int nr_threads = thread_map__nr(evlist->core.threads); int nfds = 0; struct evsel *evsel; @@ -556,8 +556,8 @@ static void perf_evlist__set_sid_idx(struct evlist *evlist, sid->cpu = evlist->core.cpus->map[cpu]; else sid->cpu = -1; - if (!evsel->system_wide && evlist->threads && thread >= 0) - sid->tid = thread_map__pid(evlist->threads, thread); + if (!evsel->system_wide && evlist->core.threads && thread >= 0) + sid->tid = thread_map__pid(evlist->core.threads, thread); else sid->tid = -1; } @@ -722,7 +722,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, evlist->nr_mmaps = cpu_map__nr(evlist->core.cpus); if (cpu_map__empty(evlist->core.cpus)) - evlist->nr_mmaps = thread_map__nr(evlist->threads); + evlist->nr_mmaps = thread_map__nr(evlist->core.threads); map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); if (!map) return NULL; @@ -836,7 +836,7 @@ static int perf_evlist__mmap_per_cpu(struct evlist *evlist, { int cpu, thread; int nr_cpus = cpu_map__nr(evlist->core.cpus); - int nr_threads = thread_map__nr(evlist->threads); + int nr_threads = thread_map__nr(evlist->core.threads); pr_debug2("perf event ring buffer mmapped per cpu\n"); for (cpu = 0; cpu < nr_cpus; cpu++) { @@ -864,7 +864,7 @@ static int perf_evlist__mmap_per_thread(struct evlist *evlist, struct mmap_params *mp) { int thread; - int nr_threads = thread_map__nr(evlist->threads); + int nr_threads = thread_map__nr(evlist->core.threads); pr_debug2("perf event ring buffer mmapped per thread\n"); for (thread = 0; thread < nr_threads; thread++) { @@ -1015,7 +1015,7 @@ int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, { struct evsel *evsel; const struct perf_cpu_map *cpus = evlist->core.cpus; - const struct perf_thread_map *threads = evlist->threads; + const struct perf_thread_map *threads = evlist->core.threads; /* * Delay setting mp.prot: set it before calling perf_mmap__mmap. * Its value is decided by evsel's write_backward. @@ -1121,9 +1121,9 @@ void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, evlist->core.cpus = perf_cpu_map__get(cpus); } - if (threads != evlist->threads) { - perf_thread_map__put(evlist->threads); - evlist->threads = perf_thread_map__get(threads); + if (threads != evlist->core.threads) { + perf_thread_map__put(evlist->core.threads); + evlist->core.threads = perf_thread_map__get(threads); } perf_evlist__propagate_maps(evlist); @@ -1398,7 +1398,7 @@ int evlist__open(struct evlist *evlist) * Default: one fd per CPU, all threads, aka systemwide * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL */ - if (evlist->threads == NULL && evlist->core.cpus == NULL) { + if (evlist->core.threads == NULL && evlist->core.cpus == NULL) { err = perf_evlist__create_syswide_maps(evlist); if (err < 0) goto out_err; @@ -1501,12 +1501,12 @@ int perf_evlist__prepare_workload(struct evlist *evlist, struct target *target, } if (target__none(target)) { - if (evlist->threads == NULL) { + if (evlist->core.threads == NULL) { fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n", __func__, __LINE__); goto out_close_pipes; } - perf_thread_map__set_pid(evlist->threads, 0, evlist->workload.pid); + perf_thread_map__set_pid(evlist->core.threads, 0, evlist->workload.pid); } close(child_ready_pipe[1]); @@ -1921,7 +1921,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, evlist__for_each_entry(evlist, counter) { if (evsel__open(counter, evlist->core.cpus, - evlist->threads) < 0) + evlist->core.threads) < 0) goto out_delete_evlist; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index fdd8f83eac2d..de2025d198d4 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -43,7 +43,6 @@ struct evlist { struct fdarray pollfd; struct perf_mmap *mmap; struct perf_mmap *overwrite_mmap; - struct perf_thread_map *threads; struct evsel *selected; struct events_stats stats; struct perf_env *env; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 24c9c3015983..799f3c0a9050 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -507,7 +507,7 @@ int perf_stat_synthesize_config(struct perf_stat_config *config, err = perf_event__synthesize_extra_attr(tool, evlist, process, attrs); - err = perf_event__synthesize_thread_map2(tool, evlist->threads, + err = perf_event__synthesize_thread_map2(tool, evlist->core.threads, process, NULL); if (err < 0) { pr_err("Couldn't synthesize thread map.\n"); -- GitLab From 453fa03090a64c0e0a561f10dfd5e8747796949c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:43 +0200 Subject: [PATCH 1182/7155] libperf: Add perf_evlist__set_maps() function Move the evlist__set_maps() function from tools/perf to libperf. Committer notes: Fix up reject due to earlier inversion in calling perf_evlist__init(). Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-57-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 3 +- tools/perf/builtin-script.c | 3 +- tools/perf/builtin-stat.c | 3 +- tools/perf/lib/evlist.c | 54 ++++++++++++++++++ tools/perf/lib/include/perf/evlist.h | 6 ++ tools/perf/lib/libperf.map | 1 + tools/perf/tests/code-reading.c | 5 +- tools/perf/tests/keep-tracking.c | 3 +- tools/perf/tests/mmap-basic.c | 3 +- tools/perf/tests/sw-clock.c | 3 +- tools/perf/tests/switch-tracking.c | 3 +- tools/perf/tests/task-exit.c | 3 +- tools/perf/util/evlist.c | 58 +------------------- tools/perf/util/evlist.h | 2 - 14 files changed, 83 insertions(+), 67 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 261bdd680651..582182d98a7f 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -72,7 +73,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe evlist = evlist__new(); CHECK_NOT_NULL__(evlist); - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); CHECK__(parse_events(evlist, "cycles:u", NULL)); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a787c5cb1331..46fadbbe1c3e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -3264,7 +3265,7 @@ static int set_maps(struct perf_script *script) if (WARN_ONCE(script->allocated, "stats double allocation\n")) return -EINVAL; - perf_evlist__set_maps(evlist, script->cpus, script->threads); + perf_evlist__set_maps(&evlist->core, script->cpus, script->threads); if (perf_evlist__alloc_stats(evlist, true)) return -ENOMEM; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4a94ca131d56..14e4c970d16a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -83,6 +83,7 @@ #include #include +#include #define DEFAULT_SEPARATOR " " #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" @@ -1517,7 +1518,7 @@ static int set_maps(struct perf_stat *st) if (WARN_ONCE(st->maps_allocated, "stats double allocation\n")) return -EINVAL; - perf_evlist__set_maps(evsel_list, st->cpus, st->threads); + perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads); if (perf_evlist__alloc_stats(evsel_list, true)) return -ENOMEM; diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 087ef76ea8fd..6a2308ef9868 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include void perf_evlist__init(struct perf_evlist *evlist) { @@ -12,11 +14,39 @@ void perf_evlist__init(struct perf_evlist *evlist) evlist->nr_entries = 0; } +static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, + struct perf_evsel *evsel) +{ + /* + * We already have cpus for evsel (via PMU sysfs) so + * keep it, if there's no target cpu list defined. + */ + if (!evsel->own_cpus || evlist->has_user_cpus) { + perf_cpu_map__put(evsel->cpus); + evsel->cpus = perf_cpu_map__get(evlist->cpus); + } else if (evsel->cpus != evsel->own_cpus) { + perf_cpu_map__put(evsel->cpus); + evsel->cpus = perf_cpu_map__get(evsel->own_cpus); + } + + perf_thread_map__put(evsel->threads); + evsel->threads = perf_thread_map__get(evlist->threads); +} + +static void perf_evlist__propagate_maps(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + perf_evlist__for_each_evsel(evlist, evsel) + __perf_evlist__propagate_maps(evlist, evsel); +} + void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *evsel) { list_add_tail(&evsel->node, &evlist->entries); evlist->nr_entries += 1; + __perf_evlist__propagate_maps(evlist, evsel); } void perf_evlist__remove(struct perf_evlist *evlist, @@ -60,3 +90,27 @@ void perf_evlist__delete(struct perf_evlist *evlist) { free(evlist); } + +void perf_evlist__set_maps(struct perf_evlist *evlist, + struct perf_cpu_map *cpus, + struct perf_thread_map *threads) +{ + /* + * Allow for the possibility that one or another of the maps isn't being + * changed i.e. don't put it. Note we are assuming the maps that are + * being applied are brand new and evlist is taking ownership of the + * original reference count of 1. If that is not the case it is up to + * the caller to increase the reference count. + */ + if (cpus != evlist->cpus) { + perf_cpu_map__put(evlist->cpus); + evlist->cpus = perf_cpu_map__get(cpus); + } + + if (threads != evlist->threads) { + perf_thread_map__put(evlist->threads); + evlist->threads = perf_thread_map__get(threads); + } + + perf_evlist__propagate_maps(evlist); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 9a126fd0773c..b1d8dee018d6 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -6,6 +6,8 @@ struct perf_evlist; struct perf_evsel; +struct perf_cpu_map; +struct perf_thread_map; LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist); LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist, @@ -22,4 +24,8 @@ LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, (pos) != NULL; \ (pos) = perf_evlist__next((evlist), (pos))) +LIBPERF_API void perf_evlist__set_maps(struct perf_evlist *evlist, + struct perf_cpu_map *cpus, + struct perf_thread_map *threads); + #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 28ed04cbd223..9b6e8f165014 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -20,6 +20,7 @@ LIBPERF_0.0.1 { perf_evlist__add; perf_evlist__remove; perf_evlist__next; + perf_evlist__set_maps; local: *; }; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index bfaf22c2023c..e45df0736261 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -629,7 +630,7 @@ static int do_test_code_reading(bool try_kcore) goto out_put; } - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); str = do_determine_event(excl_kernel); pr_debug("Parsing event '%s'\n", str); @@ -658,7 +659,7 @@ static int do_test_code_reading(bool try_kcore) */ perf_cpu_map__get(cpus); perf_thread_map__get(threads); - perf_evlist__set_maps(evlist, NULL, NULL); + perf_evlist__set_maps(&evlist->core, NULL, NULL); evlist__delete(evlist); evlist = NULL; continue; diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 46478ba1ed16..0ce5ce33bac4 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -82,7 +83,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un evlist = evlist__new(); CHECK_NOT_NULL__(evlist); - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); CHECK__(parse_events(evlist, "dummy:u", NULL)); CHECK__(parse_events(evlist, "cycles:u", NULL)); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index aa792aebd7f0..7327694fbde0 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -12,6 +12,7 @@ #include "tests.h" #include #include +#include /* * This test will generate random numbers of calls to some getpid syscalls, @@ -68,7 +69,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse goto out_free_cpus; } - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); for (i = 0; i < nsyscalls; ++i) { char name[64]; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 2decda2d4c17..c5f1a9f83380 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -11,6 +11,7 @@ #include "util/evlist.h" #include "util/cpumap.h" #include "util/thread_map.h" +#include #define NR_LOOPS 10000000 @@ -64,7 +65,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) goto out_free_maps; } - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); cpus = NULL; threads = NULL; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 9e0bbea15005..e3cee69f6ea2 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "parse-events.h" #include "evlist.h" @@ -354,7 +355,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ goto out_err; } - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); /* First event */ err = parse_events(evlist, "cpu-clock:u", NULL); diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index b0192ea636a7..4ca38fd0379a 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -7,6 +7,7 @@ #include #include +#include static int exited; static int nr_exit; @@ -71,7 +72,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused goto out_free_maps; } - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); cpus = NULL; threads = NULL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 1a6f877ebb03..4433b656cfb7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -51,7 +51,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) INIT_HLIST_HEAD(&evlist->heads[i]); perf_evlist__init(&evlist->core); - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); fdarray__init(&evlist->pollfd, 64); evlist->workload.pid = -1; evlist->bkw_mmap_state = BKW_MMAP_NOTREADY; @@ -152,33 +152,6 @@ void evlist__delete(struct evlist *evlist) free(evlist); } -static void __perf_evlist__propagate_maps(struct evlist *evlist, - struct evsel *evsel) -{ - /* - * We already have cpus for evsel (via PMU sysfs) so - * keep it, if there's no target cpu list defined. - */ - if (!evsel->core.own_cpus || evlist->core.has_user_cpus) { - perf_cpu_map__put(evsel->core.cpus); - evsel->core.cpus = perf_cpu_map__get(evlist->core.cpus); - } else if (evsel->core.cpus != evsel->core.own_cpus) { - perf_cpu_map__put(evsel->core.cpus); - evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); - } - - perf_thread_map__put(evsel->core.threads); - evsel->core.threads = perf_thread_map__get(evlist->core.threads); -} - -static void perf_evlist__propagate_maps(struct evlist *evlist) -{ - struct evsel *evsel; - - evlist__for_each_entry(evlist, evsel) - __perf_evlist__propagate_maps(evlist, evsel); -} - void evlist__add(struct evlist *evlist, struct evsel *entry) { entry->evlist = evlist; @@ -189,8 +162,6 @@ void evlist__add(struct evlist *evlist, struct evsel *entry) if (evlist->core.nr_entries == 1) perf_evlist__set_id_pos(evlist); - - __perf_evlist__propagate_maps(evlist, entry); } void evlist__remove(struct evlist *evlist, struct evsel *evsel) @@ -1097,7 +1068,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) evlist->core.has_user_cpus = !!target->cpu_list; - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); return 0; @@ -1106,29 +1077,6 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) return -1; } -void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, - struct perf_thread_map *threads) -{ - /* - * Allow for the possibility that one or another of the maps isn't being - * changed i.e. don't put it. Note we are assuming the maps that are - * being applied are brand new and evlist is taking ownership of the - * original reference count of 1. If that is not the case it is up to - * the caller to increase the reference count. - */ - if (cpus != evlist->core.cpus) { - perf_cpu_map__put(evlist->core.cpus); - evlist->core.cpus = perf_cpu_map__get(cpus); - } - - if (threads != evlist->core.threads) { - perf_thread_map__put(evlist->core.threads); - evlist->core.threads = perf_thread_map__get(threads); - } - - perf_evlist__propagate_maps(evlist); -} - void __perf_evlist__set_sample_bit(struct evlist *evlist, enum perf_event_sample_format bit) { @@ -1381,7 +1329,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) if (!threads) goto out_put; - perf_evlist__set_maps(evlist, cpus, threads); + perf_evlist__set_maps(&evlist->core, cpus, threads); out: return err; out_put: diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index de2025d198d4..e31ddcc058f2 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -191,8 +191,6 @@ int perf_evlist__enable_event_idx(struct evlist *evlist, void perf_evlist__set_selected(struct evlist *evlist, struct evsel *evsel); -void perf_evlist__set_maps(struct evlist *evlist, struct perf_cpu_map *cpus, - struct perf_thread_map *threads); int perf_evlist__create_maps(struct evlist *evlist, struct target *target); int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); -- GitLab From 4b247fa7314ce48282f3da400a9ffb7f3fd3f863 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:44 +0200 Subject: [PATCH 1183/7155] libperf: Adopt xyarray class from perf Move the xyarray class from perf to libperf, because it's going to be used in both. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-58-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 1 - tools/perf/lib/Build | 1 + .../{util => lib/include/internal}/xyarray.h | 6 ++-- tools/perf/lib/xyarray.c | 33 +++++++++++++++++++ tools/perf/util/Build | 1 - tools/perf/util/counts.h | 2 +- tools/perf/util/evsel.h | 2 +- tools/perf/util/python-ext-sources | 1 - tools/perf/util/stat.h | 1 - 9 files changed, 39 insertions(+), 9 deletions(-) rename tools/perf/{util => lib/include/internal}/xyarray.h (84%) create mode 100644 tools/perf/lib/xyarray.c diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c69ddc67c672..1a4615a5f6c9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -38,7 +38,6 @@ #include #include "util/parse-events.h" #include "util/cpumap.h" -#include "util/xyarray.h" #include "util/sort.h" #include "util/string2.h" #include "util/term.h" diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index faf64db13e37..4f78ec0b4e10 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -4,6 +4,7 @@ libperf-y += threadmap.o libperf-y += evsel.o libperf-y += evlist.o libperf-y += zalloc.o +libperf-y += xyarray.o $(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE $(call rule_mkdir) diff --git a/tools/perf/util/xyarray.h b/tools/perf/lib/include/internal/xyarray.h similarity index 84% rename from tools/perf/util/xyarray.h rename to tools/perf/lib/include/internal/xyarray.h index 7ffe562e7ae7..3bf70e4d474c 100644 --- a/tools/perf/util/xyarray.h +++ b/tools/perf/lib/include/internal/xyarray.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _PERF_XYARRAY_H_ -#define _PERF_XYARRAY_H_ 1 +#ifndef __LIBPERF_INTERNAL_XYARRAY_H +#define __LIBPERF_INTERNAL_XYARRAY_H #include @@ -32,4 +32,4 @@ static inline int xyarray__max_x(struct xyarray *xy) return xy->max_x; } -#endif /* _PERF_XYARRAY_H_ */ +#endif /* __LIBPERF_INTERNAL_XYARRAY_H */ diff --git a/tools/perf/lib/xyarray.c b/tools/perf/lib/xyarray.c new file mode 100644 index 000000000000..dcd901d154bb --- /dev/null +++ b/tools/perf/lib/xyarray.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size) +{ + size_t row_size = ylen * entry_size; + struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size); + + if (xy != NULL) { + xy->entry_size = entry_size; + xy->row_size = row_size; + xy->entries = xlen * ylen; + xy->max_x = xlen; + xy->max_y = ylen; + } + + return xy; +} + +void xyarray__reset(struct xyarray *xy) +{ + size_t n = xy->entries * xy->entry_size; + + memset(xy->contents, 0, n); +} + +void xyarray__delete(struct xyarray *xy) +{ + free(xy); +} diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 08f670d21615..7abf05131889 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -69,7 +69,6 @@ perf-y += svghelper.o perf-y += sort.o perf-y += hist.o perf-y += util.o -perf-y += xyarray.o perf-y += cpumap.o perf-y += cputopo.o perf-y += cgroup.o diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index 0f0cb2d8f70d..bbfac9ecf642 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -2,7 +2,7 @@ #ifndef __PERF_COUNTS_H #define __PERF_COUNTS_H -#include "xyarray.h" +#include struct perf_counts_values { union { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 57b5523b480c..1f9f66fe43f4 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -8,7 +8,7 @@ #include #include #include -#include "xyarray.h" +#include #include "symbol_conf.h" #include "cpumap.h" #include "counts.h" diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 2237bac9fadb..235bd9803390 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -20,7 +20,6 @@ util/namespaces.c ../lib/vsprintf.c util/thread_map.c util/util.c -util/xyarray.c util/cgroup.c util/parse-branch-options.c util/rblist.c diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 95b4de7a9d51..bcb376e1b3a7 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -8,7 +8,6 @@ #include #include #include -#include "xyarray.h" #include "rblist.h" #include "perf.h" #include "event.h" -- GitLab From 9dfcb7599084382884fec6d0fd9ca33945fa7578 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:45 +0200 Subject: [PATCH 1184/7155] libperf: Move fd array from perf's evsel to lobperf's perf_evsel class Move the fd array from perf's evsel to libperf's perf_evsel class. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-59-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/internal/evsel.h | 1 + tools/perf/util/bpf-loader.c | 2 +- tools/perf/util/evlist.c | 10 ++++----- tools/perf/util/evsel.c | 30 ++++++++++++------------- tools/perf/util/evsel.h | 1 - 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 8340fd883a3d..df4078194e9a 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -14,6 +14,7 @@ struct perf_evsel { struct perf_cpu_map *cpus; struct perf_cpu_map *own_cpus; struct perf_thread_map *threads; + struct xyarray *fd; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 4df8bdea14ac..9c219d413e57 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -1403,7 +1403,7 @@ static int apply_config_evsel_for_key(const char *name, int map_fd, void *pkey, struct evsel *evsel) { - struct xyarray *xy = evsel->fd; + struct xyarray *xy = evsel->core.fd; struct perf_event_attr *attr; unsigned int key, events; bool check_pass = false; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4433b656cfb7..e4b1a9914ea4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -40,7 +40,7 @@ int sigqueue(pid_t pid, int sig, const union sigval value); #endif -#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, @@ -321,7 +321,7 @@ void evlist__disable(struct evlist *evlist) struct evsel *pos; evlist__for_each_entry(evlist, pos) { - if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd) + if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd) continue; evsel__disable(pos); } @@ -334,7 +334,7 @@ void evlist__enable(struct evlist *evlist) struct evsel *pos; evlist__for_each_entry(evlist, pos) { - if (!perf_evsel__is_group_leader(pos) || !pos->fd) + if (!perf_evsel__is_group_leader(pos) || !pos->core.fd) continue; evsel__enable(pos); } @@ -353,7 +353,7 @@ static int perf_evlist__enable_event_cpu(struct evlist *evlist, int thread; int nr_threads = perf_evlist__nr_threads(evlist, evsel); - if (!evsel->fd) + if (!evsel->core.fd) return -EINVAL; for (thread = 0; thread < nr_threads; thread++) { @@ -371,7 +371,7 @@ static int perf_evlist__enable_event_thread(struct evlist *evlist, int cpu; int nr_cpus = cpu_map__nr(evlist->core.cpus); - if (!evsel->fd) + if (!evsel->core.fd) return -EINVAL; for (cpu = 0; cpu < nr_cpus; cpu++) { diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index f7758ce0dd5c..8d087d0e55f1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -90,7 +90,7 @@ int perf_evsel__object_config(size_t object_size, return 0; } -#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) int __perf_evsel__sample_size(u64 sample_type) { @@ -1155,9 +1155,9 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, static int perf_evsel__alloc_fd(struct evsel *evsel, int ncpus, int nthreads) { - evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); + evsel->core.fd = xyarray__new(ncpus, nthreads, sizeof(int)); - if (evsel->fd) { + if (evsel->core.fd) { int cpu, thread; for (cpu = 0; cpu < ncpus; cpu++) { for (thread = 0; thread < nthreads; thread++) { @@ -1166,7 +1166,7 @@ static int perf_evsel__alloc_fd(struct evsel *evsel, int ncpus, int nthreads) } } - return evsel->fd != NULL ? 0 : -ENOMEM; + return evsel->core.fd != NULL ? 0 : -ENOMEM; } static int perf_evsel__run_ioctl(struct evsel *evsel, @@ -1174,8 +1174,8 @@ static int perf_evsel__run_ioctl(struct evsel *evsel, { int cpu, thread; - for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { - for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { + for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) { + for (thread = 0; thread < xyarray__max_y(evsel->core.fd); thread++) { int fd = FD(evsel, cpu, thread), err = ioctl(fd, ioc, arg); @@ -1283,8 +1283,8 @@ int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads) static void perf_evsel__free_fd(struct evsel *evsel) { - xyarray__delete(evsel->fd); - evsel->fd = NULL; + xyarray__delete(evsel->core.fd); + evsel->core.fd = NULL; } static void perf_evsel__free_id(struct evsel *evsel) @@ -1309,8 +1309,8 @@ void perf_evsel__close_fd(struct evsel *evsel) { int cpu, thread; - for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) - for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { + for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) + for (thread = 0; thread < xyarray__max_y(evsel->core.fd); ++thread) { close(FD(evsel, cpu, thread)); FD(evsel, cpu, thread) = -1; } @@ -1555,7 +1555,7 @@ static int get_group_fd(struct evsel *evsel, int cpu, int thread) * Leader must be already processed/open, * if not it's a bug. */ - BUG_ON(!leader->fd); + BUG_ON(!leader->core.fd); fd = FD(leader, cpu, thread); BUG_ON(fd == -1); @@ -1865,7 +1865,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, else nthreads = threads->nr; - if (evsel->fd == NULL && + if (evsel->core.fd == NULL && perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) return -ENOMEM; @@ -2075,7 +2075,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, void perf_evsel__close(struct evsel *evsel) { - if (evsel->fd == NULL) + if (evsel->core.fd == NULL) return; perf_evsel__close_fd(evsel); @@ -3048,8 +3048,8 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) { int cpu, thread; - for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { - for (thread = 0; thread < xyarray__max_y(evsel->fd); + for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) { + for (thread = 0; thread < xyarray__max_y(evsel->core.fd); thread++) { int fd = FD(evsel, cpu, thread); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1f9f66fe43f4..6056ce64bfdf 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -104,7 +104,6 @@ struct evsel { struct perf_evsel core; struct evlist *evlist; char *filter; - struct xyarray *fd; struct xyarray *sample_id; u64 *id; struct perf_counts *counts; -- GitLab From 5643b1a59e581ac3f66d36caba8124313cc446c0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:46 +0200 Subject: [PATCH 1185/7155] libperf: Move nr_members from perf's evsel to libperf's perf_evsel Move the nr_members member from perf's evsel to libperf's perf_evsel. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-60-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/lib/include/internal/evsel.h | 3 +++ tools/perf/tests/parse-events.c | 22 +++++++++++----------- tools/perf/ui/gtk/annotate.c | 2 +- tools/perf/ui/gtk/hists.c | 2 +- tools/perf/ui/hist.c | 6 +++--- tools/perf/util/annotate.c | 8 ++++---- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 3 +-- tools/perf/util/evsel_fprintf.c | 4 ++-- tools/perf/util/header.c | 12 ++++++------ tools/perf/util/hist.c | 2 +- tools/perf/util/parse-events.c | 2 +- tools/perf/util/stat-display.c | 2 +- tools/perf/util/stat.c | 2 +- 18 files changed, 45 insertions(+), 43 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e258e988c55b..d4288dcce156 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -436,7 +436,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); if (evname != NULL) { ret += fprintf(fp, " of event%s '%s'", - evsel->nr_members > 1 ? "s" : "", evname); + evsel->core.nr_members > 1 ? "s" : "", evname); } if (rep->time_str) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 46fadbbe1c3e..31a529ec139f 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1734,7 +1734,7 @@ static void perf_sample__fprint_metric(struct perf_script *script, sample->cpu, &rt_stat); evsel_script(evsel)->val = val; - if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) { + if (evsel_script(evsel->leader)->gnum == evsel->leader->core.nr_members) { for_each_group_member (ev2, evsel->leader) { perf_stat__print_shadow_stats(&stat_config, ev2, evsel_script(ev2)->val, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 14e4c970d16a..b19df671111e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -479,7 +479,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) counter->supported = false; if ((counter->leader != counter) || - !(counter->leader->nr_members > 1)) + !(counter->leader->core.nr_members > 1)) continue; } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { if (verbose > 0) diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index df4078194e9a..29eca9576546 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -15,6 +15,9 @@ struct perf_evsel { struct perf_cpu_map *own_cpus; struct perf_thread_map *threads; struct xyarray *fd; + + /* parse modifier helper */ + int nr_members; }; #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 5b4a5a3dac50..49f52e4de41b 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -653,7 +653,7 @@ static int test__group1(struct evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -695,7 +695,7 @@ static int test__group2(struct evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -753,7 +753,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group1")); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -788,7 +788,7 @@ static int test__group3(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group2")); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -844,7 +844,7 @@ static int test__group4(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -887,7 +887,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -919,7 +919,7 @@ static int test__group5(struct evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); @@ -973,7 +973,7 @@ static int test__group_gh1(struct evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cache-misses:G + :H group modifier */ @@ -1013,7 +1013,7 @@ static int test__group_gh2(struct evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cache-misses:H + :G group modifier */ @@ -1053,7 +1053,7 @@ static int test__group_gh3(struct evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cache-misses:H + :u group modifier */ @@ -1093,7 +1093,7 @@ static int test__group_gh4(struct evlist *evlist) TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); + TEST_ASSERT_VAL("wrong core.nr_members", evsel->core.nr_members == 2); TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cache-misses:H + :uG group modifier */ diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 40e263a730e4..d7f984436dec 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -129,7 +129,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, gtk_list_store_append(store, &iter); if (perf_evsel__is_group_event(evsel)) { - for (i = 0; i < evsel->nr_members; i++) { + for (i = 0; i < evsel->core.nr_members; i++) { ret += perf_gtk__get_percent(s + ret, sizeof(s) - ret, sym, pos, diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 1b181d8ea953..0efdb226d1a7 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -645,7 +645,7 @@ int perf_evlist__gtk_browse_hists(struct evlist *evlist, if (!perf_evsel__is_group_leader(pos)) continue; - if (pos->nr_members > 1) { + if (pos->core.nr_members > 1) { perf_evsel__group_desc(pos, buf, size); evname = buf; } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 8c7fb11edc60..e5fb64347b2c 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -43,7 +43,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, if (perf_evsel__is_group_event(evsel)) { int prev_idx, idx_delta; struct hist_entry *pair; - int nr_members = evsel->nr_members; + int nr_members = evsel->core.nr_members; prev_idx = perf_evsel__group_idx(evsel); @@ -165,7 +165,7 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, if (!perf_evsel__is_group_event(evsel)) return ret; - nr_members = evsel->nr_members; + nr_members = evsel->core.nr_members; fields_a = calloc(nr_members, sizeof(*fields_a)); fields_b = calloc(nr_members, sizeof(*fields_b)); @@ -226,7 +226,7 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt, struct evsel *evsel = hists_to_evsel(hists); if (symbol_conf.event_group) - len = max(len, evsel->nr_members * fmt->len); + len = max(len, evsel->core.nr_members * fmt->len); if (len < (int)strlen(fmt->name)) len = strlen(fmt->name); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index d46f2ae2c695..91d4fc3e78cf 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1170,7 +1170,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize) int nr = 1; if (perf_evsel__is_group_event(evsel)) - nr = evsel->nr_members; + nr = evsel->core.nr_members; size += sizeof(al->data[0]) * nr; @@ -1448,7 +1448,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start return -1; if (perf_evsel__is_group_event(evsel)) - width *= evsel->nr_members; + width *= evsel->core.nr_members; if (!*al->line) printf(" %*s:\n", width, " "); @@ -2272,7 +2272,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, len = symbol__size(sym); if (perf_evsel__is_group_event(evsel)) { - width *= evsel->nr_members; + width *= evsel->core.nr_members; perf_evsel__group_desc(evsel, buf, sizeof(buf)); evsel_name = buf; } @@ -2968,7 +2968,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel, return -1; if (perf_evsel__is_group_event(evsel)) - nr_pcnt = evsel->nr_members; + nr_pcnt = evsel->core.nr_members; err = symbol__annotate(sym, map, evsel, 0, options, parch); if (err) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e4b1a9914ea4..eac4d634b9c7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -188,7 +188,7 @@ void __perf_evlist__set_leader(struct list_head *list) leader = list_entry(list->next, struct evsel, core.node); evsel = list_entry(list->prev, struct evsel, core.node); - leader->nr_members = evsel->idx - leader->idx + 1; + leader->core.nr_members = evsel->idx - leader->idx + 1; __evlist__for_each_entry(list, evsel) { evsel->leader = leader; @@ -1761,7 +1761,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, leader = evsel->leader; pr_debug("Weak group for %s/%d failed\n", - leader->name, leader->nr_members); + leader->name, leader->core.nr_members); /* * for_each_group_member doesn't work here because it doesn't @@ -1774,7 +1774,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, if (is_open) perf_evsel__close(c2); c2->leader = c2; - c2->nr_members = 0; + c2->core.nr_members = 0; } } return leader; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8d087d0e55f1..8b9a00598677 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -948,7 +948,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, * Apply group format only if we belong to group * with more than one members. */ - if (leader->nr_members > 1) { + if (leader->core.nr_members > 1) { attr->read_format |= PERF_FORMAT_GROUP; attr->inherit = 0; } @@ -1396,7 +1396,7 @@ static int perf_evsel__read_size(struct evsel *evsel) entry += sizeof(u64); if (read_format & PERF_FORMAT_GROUP) { - nr = evsel->nr_members; + nr = evsel->core.nr_members; size += sizeof(u64); } @@ -1453,7 +1453,7 @@ perf_evsel__process_group_data(struct evsel *leader, nr = *data++; - if (nr != (u64) leader->nr_members) + if (nr != (u64) leader->core.nr_members) return -EINVAL; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6056ce64bfdf..afd3a5b7bcc3 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -142,7 +142,6 @@ struct evsel { bool use_uncore_alias; /* parse modifier helper */ int exclude_GH; - int nr_members; int sample_read; unsigned long *per_pkg_mask; struct evsel *leader; @@ -414,7 +413,7 @@ static inline bool perf_evsel__is_group_event(struct evsel *evsel) if (!symbol_conf.event_group) return false; - return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; + return perf_evsel__is_group_leader(evsel) && evsel->core.nr_members > 1; } bool perf_evsel__is_function_event(struct evsel *evsel); diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 3466eca34a00..496fec01f5d1 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -45,14 +45,14 @@ int perf_evsel__fprintf(struct evsel *evsel, if (!perf_evsel__is_group_leader(evsel)) return 0; - if (evsel->nr_members > 1) + if (evsel->core.nr_members > 1) printed += fprintf(fp, "%s{", evsel->group_name ?: ""); printed += fprintf(fp, "%s", perf_evsel__name(evsel)); for_each_group_member(pos, evsel) printed += fprintf(fp, ",%s", perf_evsel__name(pos)); - if (evsel->nr_members > 1) + if (evsel->core.nr_members > 1) printed += fprintf(fp, "}"); goto out; } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f97df418d661..b04c2b6b28b3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -772,10 +772,10 @@ static int write_group_desc(struct feat_fd *ff, evlist__for_each_entry(evlist, evsel) { if (perf_evsel__is_group_leader(evsel) && - evsel->nr_members > 1) { + evsel->core.nr_members > 1) { const char *name = evsel->group_name ?: "{anon_group}"; u32 leader_idx = evsel->idx; - u32 nr_members = evsel->nr_members; + u32 nr_members = evsel->core.nr_members; ret = do_write_string(ff, name); if (ret < 0) @@ -1812,11 +1812,11 @@ static void print_group_desc(struct feat_fd *ff, FILE *fp) evlist__for_each_entry(session->evlist, evsel) { if (perf_evsel__is_group_leader(evsel) && - evsel->nr_members > 1) { + evsel->core.nr_members > 1) { fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", perf_evsel__name(evsel)); - nr = evsel->nr_members - 1; + nr = evsel->core.nr_members - 1; } else if (nr) { fprintf(fp, ",%s", perf_evsel__name(evsel)); @@ -2463,7 +2463,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused) evsel->group_name = desc[i].name; desc[i].name = NULL; } - evsel->nr_members = desc[i].nr_members; + evsel->core.nr_members = desc[i].nr_members; if (i >= nr_groups || nr > 0) { pr_debug("invalid group desc\n"); @@ -2471,7 +2471,7 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused) } leader = evsel; - nr = evsel->nr_members - 1; + nr = evsel->core.nr_members - 1; i++; } else if (nr) { /* This is a group member */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 821e0fe6cf26..4297f56b1e05 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2643,7 +2643,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh nr_samples = convert_unit(nr_samples, &unit); printed = scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, - nr_samples, unit, evsel->nr_members > 1 ? "s" : "", + nr_samples, unit, evsel->core.nr_members > 1 ? "s" : "", ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 8182b1e66ec6..2cfec3b7a982 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1528,7 +1528,7 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, /* The number of members and group name are same for each group */ for (i = 0; i < nr_pmu; i++) { evsel = (struct evsel *) leaders[i]; - evsel->nr_members = total_members / nr_pmu; + evsel->core.nr_members = total_members / nr_pmu; evsel->group_name = name ? strdup(name) : NULL; } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 4a162858583f..f7b39f4bc51e 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -369,7 +369,7 @@ static bool is_mixed_hw_group(struct evsel *counter) u32 pmu_type = counter->core.attr.type; struct evsel *pos; - if (counter->nr_members < 2) + if (counter->core.nr_members < 2) return false; evlist__for_each_entry(evlist, pos) { diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 799f3c0a9050..e4e4e3bf8b2b 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -452,7 +452,7 @@ int create_perf_stat_counter(struct evsel *evsel, * the group read (for leader) and ID retrieval for all * members. */ - if (leader->nr_members > 1) + if (leader->core.nr_members > 1) attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; attr->inherit = !config->no_inherit; -- GitLab From c03538b1f1a7e0e996a8d6feb20cf001d4b14939 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:47 +0200 Subject: [PATCH 1186/7155] libperf: Adopt the readn()/writen() functions from tools/perf Move the readn()/writen() functions into libperf. Keep those non-namespaced names because they will be shared only between perf and libperf. Again, these are not exported functions. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-61-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Build | 1 + tools/perf/lib/include/internal/lib.h | 10 ++++++ tools/perf/lib/lib.c | 46 +++++++++++++++++++++++++++ tools/perf/util/util.c | 40 ----------------------- tools/perf/util/util.h | 4 +-- 5 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 tools/perf/lib/include/internal/lib.h create mode 100644 tools/perf/lib/lib.c diff --git a/tools/perf/lib/Build b/tools/perf/lib/Build index 4f78ec0b4e10..c31f1c111f8f 100644 --- a/tools/perf/lib/Build +++ b/tools/perf/lib/Build @@ -5,6 +5,7 @@ libperf-y += evsel.o libperf-y += evlist.o libperf-y += zalloc.o libperf-y += xyarray.o +libperf-y += lib.o $(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE $(call rule_mkdir) diff --git a/tools/perf/lib/include/internal/lib.h b/tools/perf/lib/include/internal/lib.h new file mode 100644 index 000000000000..0b56f1201dc9 --- /dev/null +++ b/tools/perf/lib/include/internal/lib.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_LIB_H +#define __LIBPERF_INTERNAL_LIB_H + +#include + +ssize_t readn(int fd, void *buf, size_t n); +ssize_t writen(int fd, const void *buf, size_t n); + +#endif /* __LIBPERF_INTERNAL_CPUMAP_H */ diff --git a/tools/perf/lib/lib.c b/tools/perf/lib/lib.c new file mode 100644 index 000000000000..2a81819c3b8c --- /dev/null +++ b/tools/perf/lib/lib.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +static ssize_t ion(bool is_read, int fd, void *buf, size_t n) +{ + void *buf_start = buf; + size_t left = n; + + while (left) { + /* buf must be treated as const if !is_read. */ + ssize_t ret = is_read ? read(fd, buf, left) : + write(fd, buf, left); + + if (ret < 0 && errno == EINTR) + continue; + if (ret <= 0) + return ret; + + left -= ret; + buf += ret; + } + + BUG_ON((size_t)(buf - buf_start) != n); + return n; +} + +/* + * Read exactly 'n' bytes or return an error. + */ +ssize_t readn(int fd, void *buf, size_t n) +{ + return ion(true, fd, buf, n); +} + +/* + * Write exactly 'n' bytes or return an error. + */ +ssize_t writen(int fd, const void *buf, size_t n) +{ + /* ion does not modify buf. */ + return ion(false, fd, (void *)buf, n); +} diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index a61535cf1bca..9c3c97697387 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -384,46 +384,6 @@ int copyfile(const char *from, const char *to) return copyfile_mode(from, to, 0755); } -static ssize_t ion(bool is_read, int fd, void *buf, size_t n) -{ - void *buf_start = buf; - size_t left = n; - - while (left) { - /* buf must be treated as const if !is_read. */ - ssize_t ret = is_read ? read(fd, buf, left) : - write(fd, buf, left); - - if (ret < 0 && errno == EINTR) - continue; - if (ret <= 0) - return ret; - - left -= ret; - buf += ret; - } - - BUG_ON((size_t)(buf - buf_start) != n); - return n; -} - -/* - * Read exactly 'n' bytes or return an error. - */ -ssize_t readn(int fd, void *buf, size_t n) -{ - return ion(true, fd, buf, n); -} - -/* - * Write exactly 'n' bytes or return an error. - */ -ssize_t writen(int fd, const void *buf, size_t n) -{ - /* ion does not modify buf. */ - return ion(false, fd, (void *)buf, n); -} - size_t hex_width(u64 v) { size_t n = 1; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index dc7a469921e9..0dab140c6517 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -11,6 +11,7 @@ #include #include #include +#include /* General helper functions */ void usage(const char *err) __noreturn; @@ -30,9 +31,6 @@ int copyfile_mode(const char *from, const char *to, mode_t mode); int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi); int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size); -ssize_t readn(int fd, void *buf, size_t n); -ssize_t writen(int fd, const void *buf, size_t n); - size_t hex_width(u64 v); extern unsigned int page_size; -- GitLab From b8eca4d761c57fcf691a8063cd562f205645d11f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:48 +0200 Subject: [PATCH 1187/7155] libperf: Adopt perf_evsel__alloc_fd() function from tools/perf Move the perf_evsel__alloc_fd() function from perf to libperf. It's not exported. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-62-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 21 +++++++++++++++++++++ tools/perf/lib/include/internal/evsel.h | 2 ++ tools/perf/util/evsel.c | 18 +----------------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index ddc3ad447bfb..027f1edb4e8e 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -1,9 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include #include #include +#include +#include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) { @@ -25,3 +28,21 @@ void perf_evsel__delete(struct perf_evsel *evsel) { free(evsel); } + +#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y)) + +int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) +{ + evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); + + if (evsel->fd) { + int cpu, thread; + for (cpu = 0; cpu < ncpus; cpu++) { + for (thread = 0; thread < nthreads; thread++) { + FD(evsel, cpu, thread) = -1; + } + } + } + + return evsel->fd != NULL ? 0 : -ENOMEM; +} diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 29eca9576546..3cb9a0f5f32e 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -20,4 +20,6 @@ struct perf_evsel { int nr_members; }; +int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); + #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8b9a00598677..d3c8488f7069 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1153,22 +1153,6 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); } -static int perf_evsel__alloc_fd(struct evsel *evsel, int ncpus, int nthreads) -{ - evsel->core.fd = xyarray__new(ncpus, nthreads, sizeof(int)); - - if (evsel->core.fd) { - int cpu, thread; - for (cpu = 0; cpu < ncpus; cpu++) { - for (thread = 0; thread < nthreads; thread++) { - FD(evsel, cpu, thread) = -1; - } - } - } - - return evsel->core.fd != NULL ? 0 : -ENOMEM; -} - static int perf_evsel__run_ioctl(struct evsel *evsel, int ioc, void *arg) { @@ -1866,7 +1850,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, nthreads = threads->nr; if (evsel->core.fd == NULL && - perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) + perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0) return -ENOMEM; if (evsel->cgrp) { -- GitLab From 50a4e6fa450c4e5b688814a7ec8236d0de6e38bf Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:49 +0200 Subject: [PATCH 1188/7155] libperf: Adopt simplified perf_evsel__open() function from tools/perf Add a perf_evsel__open() function to libperf. It's a simplified version of evsel__open() without the fallback mechanism. We can try to merge it in the future to libperf, but it has many details, lets start simple, requiring the latest kernel, perf should continue using its evsel__open() version, continuing to support running on older kernels when possible. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-63-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 65 +++++++++++++++++++++++++++++ tools/perf/lib/include/perf/evsel.h | 4 ++ tools/perf/lib/libperf.map | 1 + 3 files changed, 70 insertions(+) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 027f1edb4e8e..7027dacb50f6 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -1,11 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) @@ -46,3 +52,62 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) return evsel->fd != NULL ? 0 : -ENOMEM; } + +static int +sys_perf_event_open(struct perf_event_attr *attr, + pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); +} + +int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, + struct perf_thread_map *threads) +{ + int cpu, thread, err = 0; + + if (cpus == NULL) { + static struct perf_cpu_map *empty_cpu_map; + + if (empty_cpu_map == NULL) { + empty_cpu_map = perf_cpu_map__dummy_new(); + if (empty_cpu_map == NULL) + return -ENOMEM; + } + + cpus = empty_cpu_map; + } + + if (threads == NULL) { + static struct perf_thread_map *empty_thread_map; + + if (empty_thread_map == NULL) { + empty_thread_map = perf_thread_map__new_dummy(); + if (empty_thread_map == NULL) + return -ENOMEM; + } + + threads = empty_thread_map; + } + + if (evsel->fd == NULL && + perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) + return -ENOMEM; + + for (cpu = 0; cpu < cpus->nr; cpu++) { + for (thread = 0; thread < threads->nr; thread++) { + int fd; + + fd = sys_perf_event_open(&evsel->attr, + threads->map[thread].pid, + cpus->map[cpu], -1, 0); + + if (fd < 0) + return -errno; + + FD(evsel, cpu, thread) = fd; + } + } + + return err; +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index a57efc0f5c8b..e9fbaa8fb51a 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -6,10 +6,14 @@ struct perf_evsel; struct perf_event_attr; +struct perf_cpu_map; +struct perf_thread_map; LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr); LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel); +LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, + struct perf_thread_map *threads); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 9b6e8f165014..7594d3d89c5f 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -14,6 +14,7 @@ LIBPERF_0.0.1 { perf_evsel__new; perf_evsel__delete; perf_evsel__init; + perf_evsel__open; perf_evlist__new; perf_evlist__delete; perf_evlist__init; -- GitLab From 88761fa1f1e3fb2df86727ac99f88abf2ac7e00b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:50 +0200 Subject: [PATCH 1189/7155] libperf: Adopt simplified perf_evsel__close() function from tools/perf Add perf_evsel__close() function to libperf while keeping a tools/perf specific evsel__close() to free ids. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-64-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- tools/perf/lib/evsel.c | 26 +++++++++++++++++++++ tools/perf/lib/include/internal/evsel.h | 2 ++ tools/perf/lib/include/perf/evsel.h | 1 + tools/perf/lib/libperf.map | 1 + tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/evlist.c | 5 ++-- tools/perf/util/evsel.c | 27 +++------------------- tools/perf/util/evsel.h | 3 +-- 10 files changed, 40 insertions(+), 31 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 35f3684f5327..75eb3811e942 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2401,7 +2401,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) { evsel__disable(evsel); - perf_evsel__close(evsel); + evsel__close(evsel); } } } diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 7027dacb50f6..50f09e939229 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -111,3 +111,29 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, return err; } + +void perf_evsel__close_fd(struct perf_evsel *evsel) +{ + int cpu, thread; + + for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) + for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { + close(FD(evsel, cpu, thread)); + FD(evsel, cpu, thread) = -1; + } +} + +void perf_evsel__free_fd(struct perf_evsel *evsel) +{ + xyarray__delete(evsel->fd); + evsel->fd = NULL; +} + +void perf_evsel__close(struct perf_evsel *evsel) +{ + if (evsel->fd == NULL) + return; + + perf_evsel__close_fd(evsel); + perf_evsel__free_fd(evsel); +} diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 3cb9a0f5f32e..878e2cf41ffc 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -21,5 +21,7 @@ struct perf_evsel { }; int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); +void perf_evsel__close_fd(struct perf_evsel *evsel); +void perf_evsel__free_fd(struct perf_evsel *evsel); #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index e9fbaa8fb51a..aa5c48f822d2 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -15,5 +15,6 @@ LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel); LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads); +LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 7594d3d89c5f..0b90999dcdcb 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -15,6 +15,7 @@ LIBPERF_0.0.1 { perf_evsel__delete; perf_evsel__init; perf_evsel__open; + perf_evsel__close; perf_evlist__new; perf_evlist__delete; perf_evlist__init; diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index d161b1a78703..8322b6aa4047 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -116,7 +116,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int perf_evsel__free_counts(evsel); out_close_fd: - perf_evsel__close_fd(evsel); + perf_evsel__close_fd(&evsel->core); out_evsel_delete: evsel__delete(evsel); out_cpu_map_delete: diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 87c212545767..f217972977e0 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -57,7 +57,7 @@ int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __m err = 0; out_close_fd: - perf_evsel__close_fd(evsel); + perf_evsel__close_fd(&evsel->core); out_evsel_delete: evsel__delete(evsel); out_thread_map_delete: diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index eac4d634b9c7..c6b4883b2d49 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #ifdef LACKS_SIGQUEUE_PROTOTYPE @@ -1303,7 +1304,7 @@ void evlist__close(struct evlist *evlist) struct evsel *evsel; evlist__for_each_entry_reverse(evlist, evsel) - perf_evsel__close(evsel); + evsel__close(evsel); } static int perf_evlist__create_syswide_maps(struct evlist *evlist) @@ -1772,7 +1773,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, is_open = false; if (c2->leader == leader) { if (is_open) - perf_evsel__close(c2); + evsel__close(c2); c2->leader = c2; c2->core.nr_members = 0; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d3c8488f7069..8d8ed36377f5 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1265,12 +1265,6 @@ int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads) return 0; } -static void perf_evsel__free_fd(struct evsel *evsel) -{ - xyarray__delete(evsel->core.fd); - evsel->core.fd = NULL; -} - static void perf_evsel__free_id(struct evsel *evsel) { xyarray__delete(evsel->sample_id); @@ -1289,23 +1283,12 @@ static void perf_evsel__free_config_terms(struct evsel *evsel) } } -void perf_evsel__close_fd(struct evsel *evsel) -{ - int cpu, thread; - - for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) - for (thread = 0; thread < xyarray__max_y(evsel->core.fd); ++thread) { - close(FD(evsel, cpu, thread)); - FD(evsel, cpu, thread) = -1; - } -} - void perf_evsel__exit(struct evsel *evsel) { assert(list_empty(&evsel->core.node)); assert(evsel->evlist == NULL); perf_evsel__free_counts(evsel); - perf_evsel__free_fd(evsel); + perf_evsel__free_fd(&evsel->core); perf_evsel__free_id(evsel); perf_evsel__free_config_terms(evsel); cgroup__put(evsel->cgrp); @@ -2057,13 +2040,9 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, return err; } -void perf_evsel__close(struct evsel *evsel) +void evsel__close(struct evsel *evsel) { - if (evsel->core.fd == NULL) - return; - - perf_evsel__close_fd(evsel); - perf_evsel__free_fd(evsel); + perf_evsel__close(&evsel->core); perf_evsel__free_id(evsel); } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index afd3a5b7bcc3..03fc8edad492 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -268,7 +268,6 @@ const char *perf_evsel__group_name(struct evsel *evsel); int perf_evsel__group_desc(struct evsel *evsel, char *buf, size_t size); int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads); -void perf_evsel__close_fd(struct evsel *evsel); void __perf_evsel__set_sample_bit(struct evsel *evsel, enum perf_event_sample_format bit); @@ -298,7 +297,7 @@ int perf_evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads); int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads); -void perf_evsel__close(struct evsel *evsel); +void evsel__close(struct evsel *evsel); struct perf_sample; -- GitLab From 5c30af92f2b1e9d844e1ae3243e4adcd7753d4c1 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:51 +0200 Subject: [PATCH 1190/7155] libperf: Adopt perf_evsel__read() function from tools/perf Move the perf_evsel__read() function to libperf as a public interface together with struct perf_counts_values for returning counter values. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-65-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 42 +++++++++++++++++++++++ tools/perf/lib/include/internal/evsel.h | 1 + tools/perf/lib/include/perf/evsel.h | 14 ++++++++ tools/perf/lib/libperf.map | 1 + tools/perf/tests/event-times.c | 2 +- tools/perf/util/counts.h | 12 +------ tools/perf/util/evsel.c | 45 ++----------------------- tools/perf/util/evsel.h | 3 -- 8 files changed, 62 insertions(+), 58 deletions(-) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 50f09e939229..390fcf9107c1 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -12,6 +12,7 @@ #include #include #include +#include #include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) @@ -137,3 +138,44 @@ void perf_evsel__close(struct perf_evsel *evsel) perf_evsel__close_fd(evsel); perf_evsel__free_fd(evsel); } + +int perf_evsel__read_size(struct perf_evsel *evsel) +{ + u64 read_format = evsel->attr.read_format; + int entry = sizeof(u64); /* value */ + int size = 0; + int nr = 1; + + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + size += sizeof(u64); + + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + size += sizeof(u64); + + if (read_format & PERF_FORMAT_ID) + entry += sizeof(u64); + + if (read_format & PERF_FORMAT_GROUP) { + nr = evsel->nr_members; + size += sizeof(u64); + } + + size += entry * nr; + return size; +} + +int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, + struct perf_counts_values *count) +{ + size_t size = perf_evsel__read_size(evsel); + + memset(count, 0, sizeof(*count)); + + if (FD(evsel, cpu, thread) < 0) + return -EINVAL; + + if (readn(FD(evsel, cpu, thread), count->values, size) <= 0) + return -errno; + + return 0; +} diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 878e2cf41ffc..89bae3720d67 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -23,5 +23,6 @@ struct perf_evsel { int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__close_fd(struct perf_evsel *evsel); void perf_evsel__free_fd(struct perf_evsel *evsel); +int perf_evsel__read_size(struct perf_evsel *evsel); #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index aa5c48f822d2..16ae3f873280 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -2,6 +2,7 @@ #ifndef __LIBPERF_EVSEL_H #define __LIBPERF_EVSEL_H +#include #include struct perf_evsel; @@ -9,6 +10,17 @@ struct perf_event_attr; struct perf_cpu_map; struct perf_thread_map; +struct perf_counts_values { + union { + struct { + uint64_t val; + uint64_t ena; + uint64_t run; + }; + uint64_t values[3]; + }; +}; + LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr); LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); @@ -16,5 +28,7 @@ LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel); LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads); LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel); +LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, + struct perf_counts_values *count); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 0b90999dcdcb..2e23cf420cce 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -16,6 +16,7 @@ LIBPERF_0.0.1 { perf_evsel__init; perf_evsel__open; perf_evsel__close; + perf_evsel__read; perf_evlist__new; perf_evlist__delete; perf_evlist__init; diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 00adba86403b..714e3611352c 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -196,7 +196,7 @@ static int test_times(int (attach)(struct evlist *), TEST_ASSERT_VAL("failed to detach", !detach(evlist)); - perf_evsel__read(evsel, 0, 0, &count); + perf_evsel__read(&evsel->core, 0, 0, &count); err = !(count.ena == count.run); diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index bbfac9ecf642..13430f353c19 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -3,17 +3,7 @@ #define __PERF_COUNTS_H #include - -struct perf_counts_values { - union { - struct { - u64 val; - u64 ena; - u64 run; - }; - u64 values[3]; - }; -}; +#include struct perf_counts { s8 scaled; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8d8ed36377f5..0957ec24f518 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1346,53 +1346,12 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } -static int perf_evsel__read_size(struct evsel *evsel) -{ - u64 read_format = evsel->core.attr.read_format; - int entry = sizeof(u64); /* value */ - int size = 0; - int nr = 1; - - if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) - size += sizeof(u64); - - if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) - size += sizeof(u64); - - if (read_format & PERF_FORMAT_ID) - entry += sizeof(u64); - - if (read_format & PERF_FORMAT_GROUP) { - nr = evsel->core.nr_members; - size += sizeof(u64); - } - - size += entry * nr; - return size; -} - -int perf_evsel__read(struct evsel *evsel, int cpu, int thread, - struct perf_counts_values *count) -{ - size_t size = perf_evsel__read_size(evsel); - - memset(count, 0, sizeof(*count)); - - if (FD(evsel, cpu, thread) < 0) - return -EINVAL; - - if (readn(FD(evsel, cpu, thread), count->values, size) <= 0) - return -errno; - - return 0; -} - static int perf_evsel__read_one(struct evsel *evsel, int cpu, int thread) { struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread); - return perf_evsel__read(evsel, cpu, thread, count); + return perf_evsel__read(&evsel->core, cpu, thread, count); } static void @@ -1453,7 +1412,7 @@ perf_evsel__read_group(struct evsel *leader, int cpu, int thread) { struct perf_stat_evsel *ps = leader->stats; u64 read_format = leader->core.attr.read_format; - int size = perf_evsel__read_size(leader); + int size = perf_evsel__read_size(&leader->core); u64 *data = ps->group_data; if (!(read_format & PERF_FORMAT_ID)) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 03fc8edad492..57e315d8158e 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -336,9 +336,6 @@ static inline bool perf_evsel__match2(struct evsel *e1, (a)->core.attr.type == (b)->core.attr.type && \ (a)->core.attr.config == (b)->core.attr.config) -int perf_evsel__read(struct evsel *evsel, int cpu, int thread, - struct perf_counts_values *count); - int perf_evsel__read_counter(struct evsel *evsel, int cpu, int thread); int __perf_evsel__read_on_cpu(struct evsel *evsel, -- GitLab From a00571fda6091b5268d05e87d0797efe2db1920a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:52 +0200 Subject: [PATCH 1191/7155] libperf: Adopt perf_evsel__enable()/disable()/apply_filter() functions Move the following functions: evsel__enable() evsel__disable() evsel__apply_filter() to libperf with the following names: perf_evsel__enable() perf_evsel__disable() perf_evsel__apply_filter() Export only perf_evsel__enable()/disable(), keeping the perf_evsel__apply_filter() one private for the moment. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-66-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 36 +++++++++++++++++++++++++ tools/perf/lib/include/internal/evsel.h | 1 + tools/perf/lib/include/perf/evsel.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ tools/perf/util/evlist.c | 2 +- tools/perf/util/evsel.c | 29 ++------------------ tools/perf/util/evsel.h | 1 - 7 files changed, 44 insertions(+), 29 deletions(-) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 390fcf9107c1..c3f3722e9f91 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -14,6 +14,7 @@ #include #include #include +#include void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) { @@ -179,3 +180,38 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, return 0; } + +static int perf_evsel__run_ioctl(struct perf_evsel *evsel, + int ioc, void *arg) +{ + int cpu, thread; + + for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { + for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { + int fd = FD(evsel, cpu, thread), + err = ioctl(fd, ioc, arg); + + if (err) + return err; + } + } + + return 0; +} + +int perf_evsel__enable(struct perf_evsel *evsel) +{ + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0); +} + +int perf_evsel__disable(struct perf_evsel *evsel) +{ + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0); +} + +int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter) +{ + return perf_evsel__run_ioctl(evsel, + PERF_EVENT_IOC_SET_FILTER, + (void *)filter); +} diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h index 89bae3720d67..8b854d1c9b45 100644 --- a/tools/perf/lib/include/internal/evsel.h +++ b/tools/perf/lib/include/internal/evsel.h @@ -24,5 +24,6 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__close_fd(struct perf_evsel *evsel); void perf_evsel__free_fd(struct perf_evsel *evsel); int perf_evsel__read_size(struct perf_evsel *evsel); +int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter); #endif /* __LIBPERF_INTERNAL_EVSEL_H */ diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index 16ae3f873280..0db18dfabdb8 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -30,5 +30,7 @@ LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map * LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel); LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count); +LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel); +LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 2e23cf420cce..5bd491ac1762 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -13,6 +13,8 @@ LIBPERF_0.0.1 { perf_thread_map__put; perf_evsel__new; perf_evsel__delete; + perf_evsel__enable; + perf_evsel__disable; perf_evsel__init; perf_evsel__open; perf_evsel__close; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c6b4883b2d49..c4489a1ad6bc 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1109,7 +1109,7 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel) * filters only work for tracepoint event, which doesn't have cpu limit. * So evlist and evsel should always be same. */ - err = evsel__apply_filter(evsel, evsel->filter); + err = perf_evsel__apply_filter(&evsel->core, evsel->filter); if (err) { *err_evsel = evsel; break; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0957ec24f518..64bc32ed6dfa 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1153,31 +1153,6 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts, perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); } -static int perf_evsel__run_ioctl(struct evsel *evsel, - int ioc, void *arg) -{ - int cpu, thread; - - for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) { - for (thread = 0; thread < xyarray__max_y(evsel->core.fd); thread++) { - int fd = FD(evsel, cpu, thread), - err = ioctl(fd, ioc, arg); - - if (err) - return err; - } - } - - return 0; -} - -int evsel__apply_filter(struct evsel *evsel, const char *filter) -{ - return perf_evsel__run_ioctl(evsel, - PERF_EVENT_IOC_SET_FILTER, - (void *)filter); -} - int perf_evsel__set_filter(struct evsel *evsel, const char *filter) { char *new_filter = strdup(filter); @@ -1220,7 +1195,7 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter) int evsel__enable(struct evsel *evsel) { - int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0); + int err = perf_evsel__enable(&evsel->core); if (!err) evsel->disabled = false; @@ -1230,7 +1205,7 @@ int evsel__enable(struct evsel *evsel) int evsel__disable(struct evsel *evsel) { - int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0); + int err = perf_evsel__disable(&evsel->core); /* * We mark it disabled here so that tools that disable a event can * ignore events after they disable it. I.e. the ring buffer may have diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 57e315d8158e..0989fb2eb1ec 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -287,7 +287,6 @@ int perf_evsel__set_filter(struct evsel *evsel, const char *filter); int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter); int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter); -int evsel__apply_filter(struct evsel *evsel, const char *filter); int evsel__enable(struct evsel *evsel); int evsel__disable(struct evsel *evsel); -- GitLab From 09145d26b608e886415396e9277ae08f0617d21b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:53 +0200 Subject: [PATCH 1192/7155] libperf: Add perf_cpu_map__for_each_cpu() macro Add the following macro to libperf: perf_cpu_map__for_each_cpu() And its related functions: perf_cpu_map__cpu() perf_cpu_map__nr() That will allow hiding how it is implemented. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-67-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/cpumap.c | 13 +++++++++++++ tools/perf/lib/include/perf/cpumap.h | 7 +++++++ tools/perf/lib/libperf.map | 2 ++ 3 files changed, 22 insertions(+) diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index a5d4f7ff7174..1ddb69e796e5 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -224,3 +224,16 @@ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list) out: return cpus; } + +int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx) +{ + if (idx < cpus->nr) + return cpus->map[idx]; + + return -1; +} + +int perf_cpu_map__nr(const struct perf_cpu_map *cpus) +{ + return cpus ? cpus->nr : 1; +} diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h index b4a9283a5dfa..1b6e7db3fa2b 100644 --- a/tools/perf/lib/include/perf/cpumap.h +++ b/tools/perf/lib/include/perf/cpumap.h @@ -12,5 +12,12 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list); LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file); LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); +LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx); +LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); + +#define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \ + for ((idx) = 0, (cpu) = perf_cpu_map__cpu(cpus, idx); \ + (idx) < perf_cpu_map__nr(cpus); \ + (idx)++, (cpu) = perf_cpu_map__cpu(cpus, idx)) #endif /* __LIBPERF_CPUMAP_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 5bd491ac1762..d4d34bea0b40 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -6,6 +6,8 @@ LIBPERF_0.0.1 { perf_cpu_map__put; perf_cpu_map__new; perf_cpu_map__read; + perf_cpu_map__nr; + perf_cpu_map__cpu; perf_thread_map__new_dummy; perf_thread_map__set_pid; perf_thread_map__comm; -- GitLab From 0ff1a0fdf52cffa998eee4303e02780d39b2b09c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:54 +0200 Subject: [PATCH 1193/7155] libperf: Add perf_evsel__cpus()/threads() functions Add the following functions: perf_evsel__cpus() perf_evsel__threads() to access the evsel's cpus and threads objects. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-68-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 10 ++++++++++ tools/perf/lib/include/perf/evsel.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ tools/perf/util/evsel.h | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index c3f3722e9f91..8dbe0e841b8f 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -215,3 +215,13 @@ int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter) PERF_EVENT_IOC_SET_FILTER, (void *)filter); } + +struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) +{ + return evsel->cpus; +} + +struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel) +{ + return evsel->threads; +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index 0db18dfabdb8..ae9f7eeb53a2 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -32,5 +32,7 @@ LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count); LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel); LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel); +LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel); +LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index d4d34bea0b40..9f43b5cda031 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -21,6 +21,8 @@ LIBPERF_0.0.1 { perf_evsel__open; perf_evsel__close; perf_evsel__read; + perf_evsel__cpus; + perf_evsel__threads; perf_evlist__new; perf_evlist__delete; perf_evlist__init; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 0989fb2eb1ec..3cf35aa782b9 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -193,7 +193,7 @@ struct record_opts; static inline struct perf_cpu_map *evsel__cpus(struct evsel *evsel) { - return evsel->core.cpus; + return perf_evsel__cpus(&evsel->core); } static inline int perf_evsel__nr_cpus(struct evsel *evsel) -- GitLab From 80dc2b3e257cbd62e1cd5b18a6581f231c828c81 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:55 +0200 Subject: [PATCH 1194/7155] libperf: Adopt simplified perf_evlist__open()/close() functions from tools/perf Add the following functions: perf_evlist__open() perf_evlist__close() It's a simplified version of perf's evlist__open() without the sampling id index calculations. We can try to merge it in the future when we need it in some new libperf user. Also adopt some helper evlist traversing macros. In the future we can remove them from util/evlist.h, but that requires also some other changes. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-69-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 27 +++++++++++++++++++ tools/perf/lib/include/internal/evlist.h | 34 ++++++++++++++++++++++++ tools/perf/lib/include/perf/evlist.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ 4 files changed, 65 insertions(+) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 6a2308ef9868..5dda96b1d4da 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -114,3 +115,29 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, perf_evlist__propagate_maps(evlist); } + +int perf_evlist__open(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + int err; + + perf_evlist__for_each_entry(evlist, evsel) { + err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); + if (err < 0) + goto out_err; + } + + return 0; + +out_err: + perf_evlist__close(evlist); + return err; +} + +void perf_evlist__close(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + perf_evlist__for_each_entry_reverse(evlist, evsel) + perf_evsel__close(evsel); +} diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index b7b43dbc9b82..448891f06e3e 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -2,6 +2,8 @@ #ifndef __LIBPERF_INTERNAL_EVLIST_H #define __LIBPERF_INTERNAL_EVLIST_H +#include + struct perf_cpu_map; struct perf_thread_map; @@ -13,4 +15,36 @@ struct perf_evlist { struct perf_thread_map *threads; }; +/** + * __perf_evlist__for_each_entry - iterate thru all the evsels + * @list: list_head instance to iterate + * @evsel: struct perf_evsel iterator + */ +#define __perf_evlist__for_each_entry(list, evsel) \ + list_for_each_entry(evsel, list, node) + +/** + * evlist__for_each_entry - iterate thru all the evsels + * @evlist: perf_evlist instance to iterate + * @evsel: struct perf_evsel iterator + */ +#define perf_evlist__for_each_entry(evlist, evsel) \ + __perf_evlist__for_each_entry(&(evlist)->entries, evsel) + +/** + * __perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order + * @list: list_head instance to iterate + * @evsel: struct evsel iterator + */ +#define __perf_evlist__for_each_entry_reverse(list, evsel) \ + list_for_each_entry_reverse(evsel, list, node) + +/** + * perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order + * @evlist: evlist instance to iterate + * @evsel: struct evsel iterator + */ +#define perf_evlist__for_each_entry_reverse(evlist, evsel) \ + __perf_evlist__for_each_entry_reverse(&(evlist)->entries, evsel) + #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index b1d8dee018d6..6d3dda743541 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -18,6 +18,8 @@ LIBPERF_API struct perf_evlist *perf_evlist__new(void); LIBPERF_API void perf_evlist__delete(struct perf_evlist *evlist); LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *evsel); +LIBPERF_API int perf_evlist__open(struct perf_evlist *evlist); +LIBPERF_API void perf_evlist__close(struct perf_evlist *evlist); #define perf_evlist__for_each_evsel(evlist, pos) \ for ((pos) = perf_evlist__next((evlist), NULL); \ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 9f43b5cda031..4f966ddd5e53 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -25,6 +25,8 @@ LIBPERF_0.0.1 { perf_evsel__threads; perf_evlist__new; perf_evlist__delete; + perf_evlist__open; + perf_evlist__close; perf_evlist__init; perf_evlist__add; perf_evlist__remove; -- GitLab From fcc97c3e7a9d6fd3fda7674f52fb005f4e8453e7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:56 +0200 Subject: [PATCH 1195/7155] libperf: Adopt perf_evlist__enable()/disable() functions from perf Adopt the following functions from tools/perf: perf_evlist__enable() perf_evlist__disable() Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-70-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evlist.c | 16 ++++++++++++++++ tools/perf/lib/include/perf/evlist.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ 3 files changed, 20 insertions(+) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 5dda96b1d4da..f4dc9a208332 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -141,3 +141,19 @@ void perf_evlist__close(struct perf_evlist *evlist) perf_evlist__for_each_entry_reverse(evlist, evsel) perf_evsel__close(evsel); } + +void perf_evlist__enable(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + perf_evlist__for_each_entry(evlist, evsel) + perf_evsel__enable(evsel); +} + +void perf_evlist__disable(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + perf_evlist__for_each_entry(evlist, evsel) + perf_evsel__disable(evsel); +} diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 6d3dda743541..38365f8f3fba 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -20,6 +20,8 @@ LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *evsel); LIBPERF_API int perf_evlist__open(struct perf_evlist *evlist); LIBPERF_API void perf_evlist__close(struct perf_evlist *evlist); +LIBPERF_API void perf_evlist__enable(struct perf_evlist *evlist); +LIBPERF_API void perf_evlist__disable(struct perf_evlist *evlist); #define perf_evlist__for_each_evsel(evlist, pos) \ for ((pos) = perf_evlist__next((evlist), NULL); \ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 4f966ddd5e53..2068e3d52227 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -27,6 +27,8 @@ LIBPERF_0.0.1 { perf_evlist__delete; perf_evlist__open; perf_evlist__close; + perf_evlist__enable; + perf_evlist__disable; perf_evlist__init; perf_evlist__add; perf_evlist__remove; -- GitLab From 384c4ad192a01fe235c7ac9e9fd8605d12a807e8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:57 +0200 Subject: [PATCH 1196/7155] libperf: Add perf_evsel__attr() function Add a perf_evsel__attr() function to get attr pointer from a perf_evsel instance. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-71-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/evsel.c | 5 +++++ tools/perf/lib/include/perf/evsel.h | 1 + tools/perf/lib/libperf.map | 1 + 3 files changed, 7 insertions(+) diff --git a/tools/perf/lib/evsel.c b/tools/perf/lib/evsel.c index 8dbe0e841b8f..24abc80dd767 100644 --- a/tools/perf/lib/evsel.c +++ b/tools/perf/lib/evsel.c @@ -225,3 +225,8 @@ struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel) { return evsel->threads; } + +struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel) +{ + return &evsel->attr; +} diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h index ae9f7eeb53a2..4388667f265c 100644 --- a/tools/perf/lib/include/perf/evsel.h +++ b/tools/perf/lib/include/perf/evsel.h @@ -34,5 +34,6 @@ LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel); LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel); LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel); LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel); +LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel); #endif /* __LIBPERF_EVSEL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 2068e3d52227..e24d3cec01c1 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -23,6 +23,7 @@ LIBPERF_0.0.1 { perf_evsel__read; perf_evsel__cpus; perf_evsel__threads; + perf_evsel__attr; perf_evlist__new; perf_evlist__delete; perf_evlist__open; -- GitLab From 0a64d7091efde161a7d0fa385ed5c3bdb72ecdf9 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:58 +0200 Subject: [PATCH 1197/7155] libperf: Add install targets Add install targets (mostly copied from tools/lib/bpf), it's now possible to install libperf with: $ make DESTDIR=/tmp/krava install INSTALL libperf.a INSTALL libperf.so INSTALL libperf.so.0 INSTALL libperf.so.0.0.1 INSTALL headers INSTALL libperf.pc $ find /tmp/krava/ /tmp/krava/ /tmp/krava/include /tmp/krava/include/perf /tmp/krava/include/perf/evsel.h /tmp/krava/include/perf/evlist.h /tmp/krava/include/perf/threadmap.h /tmp/krava/include/perf/cpumap.h /tmp/krava/include/perf/core.h /tmp/krava/lib64 /tmp/krava/lib64/pkgconfig /tmp/krava/lib64/pkgconfig/libperf.pc /tmp/krava/lib64/libperf.so.0.0.1 /tmp/krava/lib64/libperf.so.0 /tmp/krava/lib64/libperf.so /tmp/krava/lib64/libperf.a Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-72-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Makefile | 69 +++++++++++++++++++++++++++++- tools/perf/lib/libperf.pc.template | 11 +++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tools/perf/lib/libperf.pc.template diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile index cd571ec648ad..f1b3d4c6d5f0 100644 --- a/tools/perf/lib/Makefile +++ b/tools/perf/lib/Makefile @@ -14,9 +14,31 @@ srctree := $(patsubst %/,%,$(dir $(srctree))) #$(info Determined 'srctree' to be $(srctree)) endif +INSTALL = install + +# Use DESTDIR for installing into a different root directory. +# This is useful for building a package. The program will be +# installed in this directory as if it was the root directory. +# Then the build tool can move it later. +DESTDIR ?= +DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' + include $(srctree)/tools/scripts/Makefile.include include $(srctree)/tools/scripts/Makefile.arch +ifeq ($(LP64), 1) + libdir_relative = lib64 +else + libdir_relative = lib +endif + +prefix ?= +libdir = $(prefix)/$(libdir_relative) + +# Shell quotes +libdir_SQ = $(subst ','\'',$(libdir)) +libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) + ifeq ("$(origin V)", "command line") VERBOSE = $(V) endif @@ -49,6 +71,8 @@ override CFLAGS += -fvisibility=hidden all: export srctree OUTPUT CC LD CFLAGS V +export DESTDIR DESTDIR_SQ + include $(srctree)/tools/build/Makefile.include VERSION_SCRIPT := libperf.map @@ -60,6 +84,9 @@ VERSION = $(LIBPERF_VERSION).$(LIBPERF_PATCHLEVEL).$(LIBPERF_EXTRAVERSION) LIBPERF_SO := $(OUTPUT)libperf.so.$(VERSION) LIBPERF_A := $(OUTPUT)libperf.a LIBPERF_IN := $(OUTPUT)libperf-in.o +LIBPERF_PC := $(OUTPUT)libperf.pc + +LIBPERF_ALL := $(LIBPERF_A) $(OUTPUT)libperf.so* $(LIBPERF_IN): FORCE $(Q)$(MAKE) $(build)=libperf @@ -74,14 +101,52 @@ $(LIBPERF_SO): $(LIBPERF_IN) @ln -sf $(@F) $(OUTPUT)libperf.so.$(LIBPERF_VERSION) -libs: $(LIBPERF_A) $(LIBPERF_SO) +libs: $(LIBPERF_A) $(LIBPERF_SO) $(LIBPERF_PC) all: fixdep $(Q)$(MAKE) libs clean: $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \ - *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS + *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS $(LIBPERF_PC) + +$(LIBPERF_PC): + $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \ + -e "s|@LIBDIR@|$(libdir_SQ)|" \ + -e "s|@VERSION@|$(VERSION)|" \ + < libperf.pc.template > $@ + +define do_install_mkdir + if [ ! -d '$(DESTDIR_SQ)$1' ]; then \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ + fi +endef + +define do_install + if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ + fi; \ + $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2' +endef + +install_lib: libs + $(call QUIET_INSTALL, $(LIBPERF_ALL)) \ + $(call do_install_mkdir,$(libdir_SQ)); \ + cp -fpR $(LIBPERF_ALL) $(DESTDIR)$(libdir_SQ) + +install_headers: + $(call QUIET_INSTALL, headers) \ + $(call do_install,include/perf/core.h,$(prefix)/include/perf,644); \ + $(call do_install,include/perf/cpumap.h,$(prefix)/include/perf,644); \ + $(call do_install,include/perf/threadmap.h,$(prefix)/include/perf,644); \ + $(call do_install,include/perf/evlist.h,$(prefix)/include/perf,644); \ + $(call do_install,include/perf/evsel.h,$(prefix)/include/perf,644); + +install_pkgconfig: $(LIBPERF_PC) + $(call QUIET_INSTALL, $(LIBPERF_PC)) \ + $(call do_install,$(LIBPERF_PC),$(libdir_SQ)/pkgconfig,644) + +install: install_lib install_headers install_pkgconfig FORCE: diff --git a/tools/perf/lib/libperf.pc.template b/tools/perf/lib/libperf.pc.template new file mode 100644 index 000000000000..117e4a237b55 --- /dev/null +++ b/tools/perf/lib/libperf.pc.template @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +prefix=@PREFIX@ +libdir=@LIBDIR@ +includedir=${prefix}/include + +Name: libperf +Description: perf library +Version: @VERSION@ +Libs: -L${libdir} -lperf +Cflags: -I${includedir} -- GitLab From 6a94b52a71b7d3ca3ec47c194f7916b306cb26ef Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:24:59 +0200 Subject: [PATCH 1198/7155] libperf: Add tests support Adding simple test framework, now empty. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-73-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Makefile | 7 ++++- tools/perf/lib/include/internal/tests.h | 19 +++++++++++++ tools/perf/lib/tests/Makefile | 38 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tools/perf/lib/include/internal/tests.h create mode 100644 tools/perf/lib/tests/Makefile diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile index f1b3d4c6d5f0..8a9ae50818e4 100644 --- a/tools/perf/lib/Makefile +++ b/tools/perf/lib/Makefile @@ -109,6 +109,11 @@ all: fixdep clean: $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \ *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS $(LIBPERF_PC) + $(Q)$(MAKE) -C tests clean + +tests: + $(Q)$(MAKE) -C tests + $(Q)$(MAKE) -C tests run $(LIBPERF_PC): $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \ @@ -150,4 +155,4 @@ install: install_lib install_headers install_pkgconfig FORCE: -.PHONY: all install clean FORCE +.PHONY: all install clean tests FORCE diff --git a/tools/perf/lib/include/internal/tests.h b/tools/perf/lib/include/internal/tests.h new file mode 100644 index 000000000000..b7a20cd24ee1 --- /dev/null +++ b/tools/perf/lib/include/internal/tests.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_TESTS_H +#define __LIBPERF_INTERNAL_TESTS_H + +#include + +#define __T_START fprintf(stdout, "- running %s...", __FILE__) +#define __T_OK fprintf(stdout, "OK\n") +#define __T_FAIL fprintf(stdout, "FAIL\n") + +#define __T(text, cond) \ +do { \ + if (!(cond)) { \ + fprintf(stderr, "FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + return -1; \ + } \ +} while (0) + +#endif /* __LIBPERF_INTERNAL_TESTS_H */ diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile new file mode 100644 index 000000000000..de951ae38dea --- /dev/null +++ b/tools/perf/lib/tests/Makefile @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +TESTS = + +TESTS_SO := $(addsuffix -so,$(TESTS)) +TESTS_A := $(addsuffix -a,$(TESTS)) + +# Set compile option CFLAGS +ifdef EXTRA_CFLAGS + CFLAGS := $(EXTRA_CFLAGS) +else + CFLAGS := -g -Wall +endif + +all: + +include $(srctree)/tools/scripts/Makefile.include + +INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include + +$(TESTS_A): FORCE + $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a + +$(TESTS_SO): FORCE + $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) -lperf + +all: $(TESTS_A) $(TESTS_SO) + +run: + @echo "running static:" + @for i in $(TESTS_A); do ./$$i; done + @echo "running dynamic:" + @for i in $(TESTS_SO); do LD_LIBRARY_PATH=../ ./$$i; done + +clean: + $(call QUIET_CLEAN, tests)$(RM) $(TESTS_A) $(TESTS_SO) + +.PHONY: all clean FORCE -- GitLab From c0e730456ae8a864701f5ca4f6c2e23010e4b04a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:00 +0200 Subject: [PATCH 1199/7155] libperf: Add perf_cpu_map test Add simple perf_cpu_map tests. Committer testing: One has to build it in the source tree, a limitation that should be fixed in followup patches: $ make O=/tmp/build/perf -C tools/perf/lib make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK /tmp/build/perf/libperf.so.0.0.1 GEN /tmp/build/perf/libperf.pc make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ make O=/tmp/build/perf -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a gcc: error: ../libperf.a: No such file or directory make[1]: *** [Makefile:22: test-cpumap-a] Error 1 make: *** [Makefile:115: tests] Error 2 make: Leaving directory '/home/acme/git/perf/tools/perf/lib' [acme@quaco perf]$ make -C tools/perf/lib make: Entering directory '/home/acme/git/perf/tools/perf/lib' HOSTCC fixdep.o HOSTLD fixdep-in.o LINK fixdep CC core.o CC cpumap.o CC threadmap.o CC evsel.o CC evlist.o CC zalloc.o CC xyarray.o CC lib.o LD libperf-in.o AR libperf.a LINK libperf.so.0.0.1 GEN libperf.pc make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ make O=/tmp/build/perf -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-cpumap-so running static: - running test-cpumap.c...OK running dynamic: - running test-cpumap.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-74-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/Makefile | 2 +- tools/perf/lib/tests/test-cpumap.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tools/perf/lib/tests/test-cpumap.c diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile index de951ae38dea..b72c8c47df61 100644 --- a/tools/perf/lib/tests/Makefile +++ b/tools/perf/lib/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -TESTS = +TESTS = test-cpumap TESTS_SO := $(addsuffix -so,$(TESTS)) TESTS_A := $(addsuffix -a,$(TESTS)) diff --git a/tools/perf/lib/tests/test-cpumap.c b/tools/perf/lib/tests/test-cpumap.c new file mode 100644 index 000000000000..76a43cfb83a1 --- /dev/null +++ b/tools/perf/lib/tests/test-cpumap.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +int main(int argc, char **argv) +{ + struct perf_cpu_map *cpus; + + __T_START; + + cpus = perf_cpu_map__dummy_new(); + if (!cpus) + return -1; + + perf_cpu_map__get(cpus); + perf_cpu_map__put(cpus); + perf_cpu_map__put(cpus); + + __T_OK; + return 0; +} -- GitLab From 43d6976365d5f90de487e8f9f49ab21775ae84f4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:01 +0200 Subject: [PATCH 1200/7155] libperf: Add perf_thread_map test Add simple perf_thread_map tests. Committer testing: $ make O=/tmp/build/perf -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-threadmap-a LINK test-cpumap-so LINK test-threadmap-so running static: - running test-cpumap.c...OK - running test-threadmap.c...OK running dynamic: - running test-cpumap.c...OK - running test-threadmap.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' $ Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-75-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/Makefile | 2 +- tools/perf/lib/tests/test-threadmap.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tools/perf/lib/tests/test-threadmap.c diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile index b72c8c47df61..5dc84003e3a7 100644 --- a/tools/perf/lib/tests/Makefile +++ b/tools/perf/lib/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -TESTS = test-cpumap +TESTS = test-cpumap test-threadmap TESTS_SO := $(addsuffix -so,$(TESTS)) TESTS_A := $(addsuffix -a,$(TESTS)) diff --git a/tools/perf/lib/tests/test-threadmap.c b/tools/perf/lib/tests/test-threadmap.c new file mode 100644 index 000000000000..10a4f4cbbdd5 --- /dev/null +++ b/tools/perf/lib/tests/test-threadmap.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +int main(int argc, char **argv) +{ + struct perf_thread_map *threads; + + __T_START; + + threads = perf_thread_map__new_dummy(); + if (!threads) + return -1; + + perf_thread_map__get(threads); + perf_thread_map__put(threads); + perf_thread_map__put(threads); + + __T_OK; + return 0; +} -- GitLab From 8ded5425fa71e2f7f60eb59d64ecdba80582b641 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:02 +0200 Subject: [PATCH 1201/7155] libperf: Add perf_evlist test Add 2 simple perf_evlist tests to test counters reading interface through the struct evlist object. Committer testing: # make -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-threadmap-a LINK test-evlist-a LINK test-cpumap-so LINK test-threadmap-so LINK test-evlist-so running static: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK running dynamic: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' # Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-76-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/Makefile | 2 +- tools/perf/lib/tests/test-evlist.c | 123 +++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 tools/perf/lib/tests/test-evlist.c diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile index 5dc84003e3a7..e66ed090f08e 100644 --- a/tools/perf/lib/tests/Makefile +++ b/tools/perf/lib/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -TESTS = test-cpumap test-threadmap +TESTS = test-cpumap test-threadmap test-evlist TESTS_SO := $(addsuffix -so,$(TESTS)) TESTS_A := $(addsuffix -a,$(TESTS)) diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c new file mode 100644 index 000000000000..f24c531afcb6 --- /dev/null +++ b/tools/perf/lib/tests/test-evlist.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +static int test_stat_cpu(void) +{ + struct perf_cpu_map *cpus; + struct perf_evlist *evlist; + struct perf_evsel *evsel; + struct perf_event_attr attr1 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + }; + struct perf_event_attr attr2 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + }; + int err, cpu, tmp; + + cpus = perf_cpu_map__new(NULL); + __T("failed to create cpus", cpus); + + evlist = perf_evlist__new(); + __T("failed to create evlist", evlist); + + evsel = perf_evsel__new(&attr1); + __T("failed to create evsel1", evsel); + + perf_evlist__add(evlist, evsel); + + evsel = perf_evsel__new(&attr2); + __T("failed to create evsel2", evsel); + + perf_evlist__add(evlist, evsel); + + perf_evlist__set_maps(evlist, cpus, NULL); + + err = perf_evlist__open(evlist); + __T("failed to open evsel", err == 0); + + perf_evlist__for_each_evsel(evlist, evsel) { + cpus = perf_evsel__cpus(evsel); + + perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { + struct perf_counts_values counts = { .val = 0 }; + + perf_evsel__read(evsel, cpu, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + } + } + + perf_evlist__close(evlist); + perf_evlist__delete(evlist); + + perf_cpu_map__put(cpus); + return 0; +} + +static int test_stat_thread(void) +{ + struct perf_counts_values counts = { .val = 0 }; + struct perf_thread_map *threads; + struct perf_evlist *evlist; + struct perf_evsel *evsel; + struct perf_event_attr attr1 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + }; + struct perf_event_attr attr2 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + }; + int err; + + threads = perf_thread_map__new_dummy(); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + + evlist = perf_evlist__new(); + __T("failed to create evlist", evlist); + + evsel = perf_evsel__new(&attr1); + __T("failed to create evsel1", evsel); + + perf_evlist__add(evlist, evsel); + + evsel = perf_evsel__new(&attr2); + __T("failed to create evsel2", evsel); + + perf_evlist__add(evlist, evsel); + + perf_evlist__set_maps(evlist, NULL, threads); + + err = perf_evlist__open(evlist); + __T("failed to open evsel", err == 0); + + perf_evlist__for_each_evsel(evlist, evsel) { + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + } + + perf_evlist__close(evlist); + perf_evlist__delete(evlist); + + perf_thread_map__put(threads); + return 0; +} + +int main(int argc, char **argv) +{ + __T_START; + + test_stat_cpu(); + test_stat_thread(); + + __T_OK; + return 0; +} -- GitLab From bb5133ae4d404a8a08d8a94dfdea1c477c93e842 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:03 +0200 Subject: [PATCH 1202/7155] libperf: Add perf_evsel tests Add 2 simple perf_evsel tests to test counters reading interface through the struct evsel object. Committer testing: # make -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-threadmap-a LINK test-evlist-a LINK test-evsel-a LINK test-cpumap-so LINK test-threadmap-so LINK test-evlist-so LINK test-evsel-so running static: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK running dynamic: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' # Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-77-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/Makefile | 2 +- tools/perf/lib/tests/test-evsel.c | 82 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 tools/perf/lib/tests/test-evsel.c diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile index e66ed090f08e..1ee4e9ba848b 100644 --- a/tools/perf/lib/tests/Makefile +++ b/tools/perf/lib/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -TESTS = test-cpumap test-threadmap test-evlist +TESTS = test-cpumap test-threadmap test-evlist test-evsel TESTS_SO := $(addsuffix -so,$(TESTS)) TESTS_A := $(addsuffix -a,$(TESTS)) diff --git a/tools/perf/lib/tests/test-evsel.c b/tools/perf/lib/tests/test-evsel.c new file mode 100644 index 000000000000..268712292f60 --- /dev/null +++ b/tools/perf/lib/tests/test-evsel.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +static int test_stat_cpu(void) +{ + struct perf_cpu_map *cpus; + struct perf_evsel *evsel; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + }; + int err, cpu, tmp; + + cpus = perf_cpu_map__new(NULL); + __T("failed to create cpus", cpus); + + evsel = perf_evsel__new(&attr); + __T("failed to create evsel", evsel); + + err = perf_evsel__open(evsel, cpus, NULL); + __T("failed to open evsel", err == 0); + + perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { + struct perf_counts_values counts = { .val = 0 }; + + perf_evsel__read(evsel, cpu, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + } + + perf_evsel__close(evsel); + perf_evsel__delete(evsel); + + perf_cpu_map__put(cpus); + return 0; +} + +static int test_stat_thread(void) +{ + struct perf_counts_values counts = { .val = 0 }; + struct perf_thread_map *threads; + struct perf_evsel *evsel; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + }; + int err; + + threads = perf_thread_map__new_dummy(); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + + evsel = perf_evsel__new(&attr); + __T("failed to create evsel", evsel); + + err = perf_evsel__open(evsel, NULL, threads); + __T("failed to open evsel", err == 0); + + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + + perf_evsel__close(evsel); + perf_evsel__delete(evsel); + + perf_thread_map__put(threads); + return 0; +} + +int main(int argc, char **argv) +{ + __T_START; + + test_stat_cpu(); + test_stat_thread(); + + __T_OK; + return 0; +} -- GitLab From 6bda376ff416cf713773d38b743953a1a9bc0603 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:04 +0200 Subject: [PATCH 1203/7155] libperf: Add perf_evlist__enable/disable test Add simple perf_evlist enable/disable test together with evlist counter reading interface. Committer testing: # make -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-threadmap-a LINK test-evlist-a LINK test-evsel-a LINK test-cpumap-so LINK test-threadmap-so LINK test-evlist-so LINK test-evsel-so running static: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK running dynamic: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' # Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-78-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/test-evlist.c | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c index f24c531afcb6..4e1407f20ffd 100644 --- a/tools/perf/lib/tests/test-evlist.c +++ b/tools/perf/lib/tests/test-evlist.c @@ -111,12 +111,75 @@ static int test_stat_thread(void) return 0; } +static int test_stat_thread_enable(void) +{ + struct perf_counts_values counts = { .val = 0 }; + struct perf_thread_map *threads; + struct perf_evlist *evlist; + struct perf_evsel *evsel; + struct perf_event_attr attr1 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CPU_CLOCK, + .disabled = 1, + }; + struct perf_event_attr attr2 = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + .disabled = 1, + }; + int err; + + threads = perf_thread_map__new_dummy(); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + + evlist = perf_evlist__new(); + __T("failed to create evlist", evlist); + + evsel = perf_evsel__new(&attr1); + __T("failed to create evsel1", evsel); + + perf_evlist__add(evlist, evsel); + + evsel = perf_evsel__new(&attr2); + __T("failed to create evsel2", evsel); + + perf_evlist__add(evlist, evsel); + + perf_evlist__set_maps(evlist, NULL, threads); + + err = perf_evlist__open(evlist); + __T("failed to open evsel", err == 0); + + perf_evlist__for_each_evsel(evlist, evsel) { + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val == 0); + } + + perf_evlist__enable(evlist); + + perf_evlist__for_each_evsel(evlist, evsel) { + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + } + + perf_evlist__disable(evlist); + + perf_evlist__close(evlist); + perf_evlist__delete(evlist); + + perf_thread_map__put(threads); + return 0; +} + int main(int argc, char **argv) { __T_START; test_stat_cpu(); test_stat_thread(); + test_stat_thread_enable(); __T_OK; return 0; -- GitLab From 02266a2d9cf7e04bf3d4b4457654839dc253f605 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:05 +0200 Subject: [PATCH 1204/7155] libperf: Add perf_evsel__enable/disable test Add simple perf_evsel enable/disable test together with evsel counter reading interface. Committer testing: # make -C tools/perf/lib tests make: Entering directory '/home/acme/git/perf/tools/perf/lib' LINK test-cpumap-a LINK test-threadmap-a LINK test-evlist-a LINK test-evsel-a LINK test-cpumap-so LINK test-threadmap-so LINK test-evlist-so LINK test-evsel-so running static: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK running dynamic: - running test-cpumap.c...OK - running test-threadmap.c...OK - running test-evlist.c...OK - running test-evsel.c...OK make: Leaving directory '/home/acme/git/perf/tools/perf/lib' # Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-79-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/tests/test-evsel.c | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tools/perf/lib/tests/test-evsel.c b/tools/perf/lib/tests/test-evsel.c index 268712292f60..2c648fe5617e 100644 --- a/tools/perf/lib/tests/test-evsel.c +++ b/tools/perf/lib/tests/test-evsel.c @@ -70,12 +70,55 @@ static int test_stat_thread(void) return 0; } +static int test_stat_thread_enable(void) +{ + struct perf_counts_values counts = { .val = 0 }; + struct perf_thread_map *threads; + struct perf_evsel *evsel; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + .disabled = 1, + }; + int err; + + threads = perf_thread_map__new_dummy(); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + + evsel = perf_evsel__new(&attr); + __T("failed to create evsel", evsel); + + err = perf_evsel__open(evsel, NULL, threads); + __T("failed to open evsel", err == 0); + + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val == 0); + + err = perf_evsel__enable(evsel); + __T("failed to enable evsel", err == 0); + + perf_evsel__read(evsel, 0, 0, &counts); + __T("failed to read value for evsel", counts.val != 0); + + err = perf_evsel__disable(evsel); + __T("failed to enable evsel", err == 0); + + perf_evsel__close(evsel); + perf_evsel__delete(evsel); + + perf_thread_map__put(threads); + return 0; +} + int main(int argc, char **argv) { __T_START; test_stat_cpu(); test_stat_thread(); + test_stat_thread_enable(); __T_OK; return 0; -- GitLab From f4f48e9c1adb49f732ac0abc4b2513f2b62a10cb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Jul 2019 13:25:06 +0200 Subject: [PATCH 1205/7155] libperf: Initial documentation Add initial drafts of documentation files, hugely unfinished. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Alexey Budankov Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190721112506.12306-80-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/Documentation/Makefile | 7 + tools/perf/lib/Documentation/man/libperf.rst | 100 ++++++++++++++ .../lib/Documentation/tutorial/tutorial.rst | 123 ++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 tools/perf/lib/Documentation/Makefile create mode 100644 tools/perf/lib/Documentation/man/libperf.rst create mode 100644 tools/perf/lib/Documentation/tutorial/tutorial.rst diff --git a/tools/perf/lib/Documentation/Makefile b/tools/perf/lib/Documentation/Makefile new file mode 100644 index 000000000000..586425a88795 --- /dev/null +++ b/tools/perf/lib/Documentation/Makefile @@ -0,0 +1,7 @@ +all: + rst2man man/libperf.rst > man/libperf.7 + rst2pdf tutorial/tutorial.rst + +clean: + rm -f man/libperf.7 + rm -f tutorial/tutorial.pdf diff --git a/tools/perf/lib/Documentation/man/libperf.rst b/tools/perf/lib/Documentation/man/libperf.rst new file mode 100644 index 000000000000..09a270fccb9c --- /dev/null +++ b/tools/perf/lib/Documentation/man/libperf.rst @@ -0,0 +1,100 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +libperf + +The libperf library provides an API to access the linux kernel perf +events subsystem. It provides the following high level objects: + + - struct perf_cpu_map + - struct perf_thread_map + - struct perf_evlist + - struct perf_evsel + +reference +========= +Function reference by header files: + +perf/core.h +----------- +.. code-block:: c + + typedef int (\*libperf_print_fn_t)(enum libperf_print_level level, + const char \*, va_list ap); + + void libperf_set_print(libperf_print_fn_t fn); + +perf/cpumap.h +------------- +.. code-block:: c + + struct perf_cpu_map \*perf_cpu_map__dummy_new(void); + struct perf_cpu_map \*perf_cpu_map__new(const char \*cpu_list); + struct perf_cpu_map \*perf_cpu_map__read(FILE \*file); + struct perf_cpu_map \*perf_cpu_map__get(struct perf_cpu_map \*map); + void perf_cpu_map__put(struct perf_cpu_map \*map); + int perf_cpu_map__cpu(const struct perf_cpu_map \*cpus, int idx); + int perf_cpu_map__nr(const struct perf_cpu_map \*cpus); + perf_cpu_map__for_each_cpu(cpu, idx, cpus) + +perf/threadmap.h +---------------- +.. code-block:: c + + struct perf_thread_map \*perf_thread_map__new_dummy(void); + void perf_thread_map__set_pid(struct perf_thread_map \*map, int thread, pid_t pid); + char \*perf_thread_map__comm(struct perf_thread_map \*map, int thread); + struct perf_thread_map \*perf_thread_map__get(struct perf_thread_map \*map); + void perf_thread_map__put(struct perf_thread_map \*map); + +perf/evlist.h +------------- +.. code-block:: + + void perf_evlist__init(struct perf_evlist \*evlist); + void perf_evlist__add(struct perf_evlist \*evlist, + struct perf_evsel \*evsel); + void perf_evlist__remove(struct perf_evlist \*evlist, + struct perf_evsel \*evsel); + struct perf_evlist \*perf_evlist__new(void); + void perf_evlist__delete(struct perf_evlist \*evlist); + struct perf_evsel\* perf_evlist__next(struct perf_evlist \*evlist, + struct perf_evsel \*evsel); + int perf_evlist__open(struct perf_evlist \*evlist); + void perf_evlist__close(struct perf_evlist \*evlist); + void perf_evlist__enable(struct perf_evlist \*evlist); + void perf_evlist__disable(struct perf_evlist \*evlist); + perf_evlist__for_each_evsel(evlist, pos) + void perf_evlist__set_maps(struct perf_evlist \*evlist, + struct perf_cpu_map \*cpus, + struct perf_thread_map \*threads); + +perf/evsel.h +------------ +.. code-block:: c + + struct perf_counts_values { + union { + struct { + uint64_t val; + uint64_t ena; + uint64_t run; + }; + uint64_t values[3]; + }; + }; + + void perf_evsel__init(struct perf_evsel \*evsel, + struct perf_event_attr \*attr); + struct perf_evsel \*perf_evsel__new(struct perf_event_attr \*attr); + void perf_evsel__delete(struct perf_evsel \*evsel); + int perf_evsel__open(struct perf_evsel \*evsel, struct perf_cpu_map \*cpus, + struct perf_thread_map \*threads); + void perf_evsel__close(struct perf_evsel \*evsel); + int perf_evsel__read(struct perf_evsel \*evsel, int cpu, int thread, + struct perf_counts_values \*count); + int perf_evsel__enable(struct perf_evsel \*evsel); + int perf_evsel__disable(struct perf_evsel \*evsel); + int perf_evsel__apply_filter(struct perf_evsel \*evsel, const char \*filter); + struct perf_cpu_map \*perf_evsel__cpus(struct perf_evsel \*evsel); + struct perf_thread_map \*perf_evsel__threads(struct perf_evsel \*evsel); + struct perf_event_attr \*perf_evsel__attr(struct perf_evsel \*evsel); diff --git a/tools/perf/lib/Documentation/tutorial/tutorial.rst b/tools/perf/lib/Documentation/tutorial/tutorial.rst new file mode 100644 index 000000000000..7be7bc27b385 --- /dev/null +++ b/tools/perf/lib/Documentation/tutorial/tutorial.rst @@ -0,0 +1,123 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +libperf tutorial +================ + +Compile and install libperf from kernel sources +=============================================== +.. code-block:: bash + + git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + cd linux/tools/perf/lib + make + sudo make install prefix=/usr + +Libperf object +============== +The libperf library provides several high level objects: + +struct perf_cpu_map + Provides a cpu list abstraction. + +struct perf_thread_map + Provides a thread list abstraction. + +struct perf_evsel + Provides an abstraction for single a perf event. + +struct perf_evlist + Gathers several struct perf_evsel object and performs functions on all of them. + +The exported API binds these objects together, +for full reference see the libperf.7 man page. + +Examples +======== +Examples aim to explain libperf functionality on simple use cases. +They are based in on a checked out linux kernel git tree: + +.. code-block:: bash + + $ cd tools/perf/lib/Documentation/tutorial/ + $ ls -d ex-* + ex-1-compile ex-2-evsel-stat ex-3-evlist-stat + +ex-1-compile example +==================== +This example shows the basic usage of *struct perf_cpu_map*, +how to create it and display its cpus: + +.. code-block:: bash + + $ cd ex-1-compile/ + $ make + gcc -o test test.c -lperf + $ ./test + 0 1 2 3 4 5 6 7 + + +The full code listing is here: + +.. code-block:: c + + 1 #include + 2 + 3 int main(int argc, char **Argv) + 4 { + 5 struct perf_cpu_map *cpus; + 6 int cpu, tmp; + 7 + 8 cpus = perf_cpu_map__new(NULL); + 9 + 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) + 11 fprintf(stdout, "%d ", cpu); + 12 + 13 fprintf(stdout, "\n"); + 14 + 15 perf_cpu_map__put(cpus); + 16 return 0; + 17 } + + +First you need to include the proper header to have *struct perf_cpumap* +declaration and functions: + +.. code-block:: c + + 1 #include + + +The *struct perf_cpumap* object is created by *perf_cpu_map__new* call. +The *NULL* argument asks it to populate the object with the current online CPUs list: + +.. code-block:: c + + 8 cpus = perf_cpu_map__new(NULL); + +This is paired with a *perf_cpu_map__put*, that drops its reference at the end, possibly deleting it. + +.. code-block:: c + + 15 perf_cpu_map__put(cpus); + +The iteration through the *struct perf_cpumap* CPUs is done using the *perf_cpu_map__for_each_cpu* +macro which requires 3 arguments: + +- cpu - the cpu numer +- tmp - iteration helper variable +- cpus - the *struct perf_cpumap* object + +.. code-block:: c + + 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) + 11 fprintf(stdout, "%d ", cpu); + +ex-2-evsel-stat example +======================= + +TBD + +ex-3-evlist-stat example +======================== + +TBD -- GitLab From 123a039d0d54de6d5bafd551e7aa17569e13e315 Mon Sep 17 00:00:00 2001 From: Michael Petlan Date: Fri, 19 Jul 2019 12:08:37 +0200 Subject: [PATCH 1206/7155] perf vendor events power9: Added missing event descriptions Documentation source: https://wiki.raptorcs.com/w/images/6/6b/POWER9_PMU_UG_v12_28NOV2018_pub.pdf Signed-off-by: Michael Petlan Reviewed-by: Madhavan Srinivasan Cc: Ananth N Mavinakayanahalli Cc: Carl Love Cc: Michael Ellerman Cc: Naveen N. Rao Cc: Paul Clarke Cc: Sukadev Bhattiprolu Cc: linuxppc-dev@ozlabs.org LPU-Reference: 20190719100837.7503-1-mpetlan@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/powerpc/power9/memory.json | 2 +- tools/perf/pmu-events/arch/powerpc/power9/other.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json index 2e2ebc700c74..c3bb283e37e9 100644 --- a/tools/perf/pmu-events/arch/powerpc/power9/memory.json +++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json @@ -52,7 +52,7 @@ {, "EventCode": "0x4D02C", "EventName": "PM_PMC1_REWIND", - "BriefDescription": "" + "BriefDescription": "PMC1 rewind event" }, {, "EventCode": "0x15158", diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json index 48cf4f920b3f..62b864269623 100644 --- a/tools/perf/pmu-events/arch/powerpc/power9/other.json +++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json @@ -237,7 +237,7 @@ {, "EventCode": "0xD0B0", "EventName": "PM_HWSYNC", - "BriefDescription": "" + "BriefDescription": "A hwsync instruction was decoded and transferred" }, {, "EventCode": "0x168B0", @@ -1232,7 +1232,7 @@ {, "EventCode": "0xD8AC", "EventName": "PM_LWSYNC", - "BriefDescription": "" + "BriefDescription": "An lwsync instruction was decoded and transferred" }, {, "EventCode": "0x2094", @@ -1747,7 +1747,7 @@ {, "EventCode": "0xD8B0", "EventName": "PM_PTESYNC", - "BriefDescription": "" + "BriefDescription": "A ptesync instruction was counted when the instruction is decoded and transmitted" }, {, "EventCode": "0x26086", @@ -2107,7 +2107,7 @@ {, "EventCode": "0xF080", "EventName": "PM_LSU_STCX_FAIL", - "BriefDescription": "" + "BriefDescription": "The LSU detects the condition that a stcx instruction failed. No requirement to wait for a response from the nest" }, {, "EventCode": "0x30038", -- GitLab From 842a2eb28f14b184c7a653448f402f5273e6ff5c Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 27 Jun 2019 09:24:57 -0500 Subject: [PATCH 1207/7155] net/mlx5e: Print a warning when LRO feature is dropped or not allowed When user enables LRO via ethtool and if the RQ mode is legacy, mlx5e_fix_features drops the request without any explanation. Add netdev_warn to cover this case. Fixes: 6c3a823e1e9c ("net/mlx5e: RX, Remove HW LRO support in legacy RQ") Signed-off-by: Huy Nguyen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 47eea6b3a1c3..776eb46d263d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3788,9 +3788,10 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev, netdev_warn(netdev, "Dropping C-tag vlan stripping offload due to S-tag vlan\n"); } if (!MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ)) { - features &= ~NETIF_F_LRO; - if (params->lro_en) + if (features & NETIF_F_LRO) { netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\n"); + features &= ~NETIF_F_LRO; + } } if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) { -- GitLab From 4240196776572a133a54d631ce18b447279af2b5 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 24 May 2019 12:24:43 -0700 Subject: [PATCH 1208/7155] net/mlx5e: Avoid warning print when not required When disabling CQE compression in favor of time-stamping, don't show a warning when CQE compression is already disabled. Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 776eb46d263d..266783295124 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3958,7 +3958,8 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL: /* Disable CQE compression */ - netdev_warn(priv->netdev, "Disabling cqe compression"); + if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS)) + netdev_warn(priv->netdev, "Disabling RX cqe compression\n"); err = mlx5e_modify_rx_cqe_compression_locked(priv, false); if (err) { netdev_err(priv->netdev, "Failed disabling cqe compression err=%d\n", err); -- GitLab From 79ce39be1d63cc919062ffdacea583c90f3364f6 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Tue, 25 Jun 2019 11:17:18 -0700 Subject: [PATCH 1209/7155] net/mlx5e: Improve ethtool rxnfc callback structure Don't choose who implements the rxnfc "get/set" callbacks according to CONFIG_MLX5_EN_RXNFC, instead have the callbacks always available and delegate to a function of a different driver module when needed (en_fs_ethtool.c), have stubs in en/fs.h to fallback to when en_fs_ethtool.c is compiled out, to avoid complications and ifdefs in en_main.c. Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/fs.h | 11 ++++++-- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 28 +++++++++++-------- .../mellanox/mlx5/core/en_fs_ethtool.c | 11 +++----- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h index be5961ff24cc..eb70ada89b09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h @@ -132,12 +132,17 @@ struct mlx5e_ethtool_steering { void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv); void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv); -int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); -int mlx5e_get_rxnfc(struct net_device *dev, - struct ethtool_rxnfc *info, u32 *rule_locs); +int mlx5e_ethtool_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); +int mlx5e_ethtool_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *info, u32 *rule_locs); #else static inline void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv) { } static inline void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv) { } +static inline int mlx5e_ethtool_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ return -EOPNOTSUPP; } +static inline int mlx5e_ethtool_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *info, u32 *rule_locs) +{ return -EOPNOTSUPP; } #endif /* CONFIG_MLX5_EN_RXNFC */ #ifdef CONFIG_MLX5_EN_ARFS diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 126ec4181286..a6b0eda0bd1a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1888,21 +1888,27 @@ static u32 mlx5e_get_priv_flags(struct net_device *netdev) return priv->channels.params.pflags; } -#ifndef CONFIG_MLX5_EN_RXNFC -/* When CONFIG_MLX5_EN_RXNFC=n we only support ETHTOOL_GRXRINGS - * otherwise this function will be defined from en_fs_ethtool.c - */ static int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *rule_locs) { struct mlx5e_priv *priv = netdev_priv(dev); - if (info->cmd != ETHTOOL_GRXRINGS) - return -EOPNOTSUPP; - /* ring_count is needed by ethtool -x */ - info->data = priv->channels.params.num_channels; - return 0; + /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part + * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc, + * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc + * is compiled out via CONFIG_MLX5_EN_RXNFC=n. + */ + if (info->cmd == ETHTOOL_GRXRINGS) { + info->data = priv->channels.params.num_channels; + return 0; + } + + return mlx5e_ethtool_get_rxnfc(dev, info, rule_locs); +} + +static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + return mlx5e_ethtool_set_rxnfc(dev, cmd); } -#endif const struct ethtool_ops mlx5e_ethtool_ops = { .get_drvinfo = mlx5e_get_drvinfo, @@ -1923,9 +1929,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .get_rxfh = mlx5e_get_rxfh, .set_rxfh = mlx5e_set_rxfh, .get_rxnfc = mlx5e_get_rxnfc, -#ifdef CONFIG_MLX5_EN_RXNFC .set_rxnfc = mlx5e_set_rxnfc, -#endif .get_tunable = mlx5e_get_tunable, .set_tunable = mlx5e_set_tunable, .get_pauseparam = mlx5e_get_pauseparam, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c index ea3a490b569a..a66589816e21 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c @@ -887,10 +887,10 @@ static int mlx5e_get_rss_hash_opt(struct mlx5e_priv *priv, return 0; } -int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +int mlx5e_ethtool_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) { - int err = 0; struct mlx5e_priv *priv = netdev_priv(dev); + int err = 0; switch (cmd->cmd) { case ETHTOOL_SRXCLSRLINS: @@ -910,16 +910,13 @@ int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) return err; } -int mlx5e_get_rxnfc(struct net_device *dev, - struct ethtool_rxnfc *info, u32 *rule_locs) +int mlx5e_ethtool_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *info, u32 *rule_locs) { struct mlx5e_priv *priv = netdev_priv(dev); int err = 0; switch (info->cmd) { - case ETHTOOL_GRXRINGS: - info->data = priv->channels.params.num_channels; - break; case ETHTOOL_GRXCLSRLCNT: info->rule_cnt = priv->fs.ethtool.tot_num_rules; break; -- GitLab From aae67158da3677cde569919d66c6521f7b3a4502 Mon Sep 17 00:00:00 2001 From: wenxu Date: Sat, 27 Jul 2019 22:59:55 +0800 Subject: [PATCH 1210/7155] net/mlx5e: Fix unnecessary flow_block_cb_is_busy call When call flow_block_cb_is_busy. The indr_priv is guaranteed to NULL ptr. So there is no need to call flow_bock_cb_is_busy. Fixes: 0d4fd02e7199 ("net: flow_offload: add flow_block_cb_is_busy() and use it") Signed-off-by: wenxu Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 7f747cb1a4f4..496d3034e278 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -722,10 +722,6 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev, if (indr_priv) return -EEXIST; - if (flow_block_cb_is_busy(mlx5e_rep_indr_setup_block_cb, - indr_priv, &mlx5e_block_cb_list)) - return -EBUSY; - indr_priv = kmalloc(sizeof(*indr_priv), GFP_KERNEL); if (!indr_priv) return -ENOMEM; -- GitLab From 233fd21211bd0c77109460811eefa8d10dcfc5e7 Mon Sep 17 00:00:00 2001 From: Eli Britstein Date: Mon, 3 Jun 2019 08:57:13 +0000 Subject: [PATCH 1211/7155] net/mlx5e: Simplify get_route_and_out_devs helper function The helper function has "if" branches that do the same. Merge them to simplify the code. Signed-off-by: Eli Britstein Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/tc_tun.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index a6a52806be45..ae439d95f5a3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -40,20 +40,15 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv, /* if the egress device isn't on the same HW e-switch or * it's a LAG device, use the uplink */ + *route_dev = dev; if (!netdev_port_same_parent_id(priv->netdev, real_dev) || - dst_is_lag_dev) { - *route_dev = dev; + dst_is_lag_dev || is_vlan_dev(*route_dev)) *out_dev = uplink_dev; - } else { - *route_dev = dev; - if (is_vlan_dev(*route_dev)) - *out_dev = uplink_dev; - else if (mlx5e_eswitch_rep(dev) && - mlx5e_is_valid_eswitch_fwd_dev(priv, dev)) - *out_dev = *route_dev; - else - return -EOPNOTSUPP; - } + else if (mlx5e_eswitch_rep(dev) && + mlx5e_is_valid_eswitch_fwd_dev(priv, dev)) + *out_dev = *route_dev; + else + return -EOPNOTSUPP; if (!(mlx5e_eswitch_rep(*out_dev) && mlx5e_is_uplink_rep(netdev_priv(*out_dev)))) -- GitLab From 5a7e5bcb663d46d9cfe7d86d5a8ede91338275cb Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 8 Nov 2018 17:46:06 +0200 Subject: [PATCH 1212/7155] net/mlx5e: Extend tc flow struct with reference counter With new classifier type that doesn't require rtnl lock, following invariant holds: - Filter with specified cookie created only once. - Filter with specified cookie deleted only once. - Stats updates can be performed in parallel to each other. Extend tc flow with rcu and reference counter. To protect from concurrent delete, get reference to tc flow when: - Reading flow stats. - Accessing flow in neigh update handler. - Accessing flow in neigh update used value handler. Only free flow when reference counter reached zero. Modify flow cleanup to account for flows that could be not fully initialized by checking if flow is actually in the list of corresponding mod_hdr, hairpin and encap entries. Don't cleanup flow directly in case of error to allow concurrent neigh update (neigh update will be modified to always take reference to flow when using it). Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 193 ++++++++++-------- 1 file changed, 105 insertions(+), 88 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cc096f6011d9..e2b87f723819 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,7 @@ struct mlx5e_tc_flow { struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ + refcount_t refcnt; union { struct mlx5_esw_flow_attr esw_attr[0]; struct mlx5_nic_flow_attr nic_attr[0]; @@ -184,6 +186,25 @@ struct mlx5e_mod_hdr_entry { #define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto) +static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow); + +static struct mlx5e_tc_flow *mlx5e_flow_get(struct mlx5e_tc_flow *flow) +{ + if (!flow || !refcount_inc_not_zero(&flow->refcnt)) + return ERR_PTR(-EINVAL); + return flow; +} + +static void mlx5e_flow_put(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow) +{ + if (refcount_dec_and_test(&flow->refcnt)) { + mlx5e_tc_del_flow(priv, flow); + kfree(flow); + } +} + static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key) { return jhash(key->actions, @@ -281,6 +302,10 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv, { struct list_head *next = flow->mod_hdr.next; + /* flow wasn't fully initialized */ + if (list_empty(&flow->mod_hdr)) + return; + list_del(&flow->mod_hdr); if (list_empty(next)) { @@ -694,6 +719,10 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv, { struct list_head *next = flow->hairpin.next; + /* flow wasn't fully initialized */ + if (list_empty(&flow->hairpin)) + return; + list_del(&flow->hairpin); /* no more hairpin flows for us, release the hairpin pair */ @@ -727,7 +756,6 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, .flags = FLOW_ACT_NO_APPEND, }; struct mlx5_fc *counter = NULL; - bool table_created = false; int err, dest_ix = 0; flow_context->flags |= FLOW_CONTEXT_HAS_TAG; @@ -735,9 +763,9 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) { err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack); - if (err) { - goto err_add_hairpin_flow; - } + if (err) + return err; + if (flow->flags & MLX5E_TC_FLOW_HAIRPIN_RSS) { dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[dest_ix].ft = attr->hairpin_ft; @@ -754,10 +782,9 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { counter = mlx5_fc_create(dev, true); - if (IS_ERR(counter)) { - err = PTR_ERR(counter); - goto err_fc_create; - } + if (IS_ERR(counter)) + return PTR_ERR(counter); + dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; dest[dest_ix].counter_id = mlx5_fc_id(counter); dest_ix++; @@ -769,7 +796,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, flow_act.modify_id = attr->mod_hdr_id; kfree(parse_attr->mod_hdr_actions); if (err) - goto err_create_mod_hdr_id; + return err; } if (IS_ERR_OR_NULL(priv->fs.tc.t)) { @@ -795,11 +822,8 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, "Failed to create tc offload table\n"); netdev_err(priv->netdev, "Failed to create tc offload table\n"); - err = PTR_ERR(priv->fs.tc.t); - goto err_create_ft; + return PTR_ERR(priv->fs.tc.t); } - - table_created = true; } if (attr->match_level != MLX5_MATCH_NONE) @@ -808,28 +832,10 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, flow->rule[0] = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec, &flow_act, dest, dest_ix); - if (IS_ERR(flow->rule[0])) { - err = PTR_ERR(flow->rule[0]); - goto err_add_rule; - } + if (IS_ERR(flow->rule[0])) + return PTR_ERR(flow->rule[0]); return 0; - -err_add_rule: - if (table_created) { - mlx5_destroy_flow_table(priv->fs.tc.t); - priv->fs.tc.t = NULL; - } -err_create_ft: - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) - mlx5e_detach_mod_hdr(priv, flow); -err_create_mod_hdr_id: - mlx5_fc_destroy(dev, counter); -err_fc_create: - if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) - mlx5e_hairpin_flow_del(priv, flow); -err_add_hairpin_flow: - return err; } static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, @@ -839,7 +845,8 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, struct mlx5_fc *counter = NULL; counter = attr->counter; - mlx5_del_flow_rules(flow->rule[0]); + if (!IS_ERR_OR_NULL(flow->rule[0])) + mlx5_del_flow_rules(flow->rule[0]); mlx5_fc_destroy(priv->mdev, counter); if (!mlx5e_tc_num_filters(priv, MLX5E_TC_NIC_OFFLOAD) && priv->fs.tc.t) { @@ -980,14 +987,12 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, if (attr->chain > max_chain) { NL_SET_ERR_MSG(extack, "Requested chain is out of supported range"); - err = -EOPNOTSUPP; - goto err_max_prio_chain; + return -EOPNOTSUPP; } if (attr->prio > max_prio) { NL_SET_ERR_MSG(extack, "Requested priority is out of supported range"); - err = -EOPNOTSUPP; - goto err_max_prio_chain; + return -EOPNOTSUPP; } for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { @@ -1002,7 +1007,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, err = mlx5e_attach_encap(priv, flow, out_dev, out_index, extack, &encap_dev, &encap_valid); if (err) - goto err_attach_encap; + return err; out_priv = netdev_priv(encap_dev); rpriv = out_priv->ppriv; @@ -1012,21 +1017,19 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, err = mlx5_eswitch_add_vlan_action(esw, attr); if (err) - goto err_add_vlan; + return err; if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { err = mlx5e_attach_mod_hdr(priv, flow, parse_attr); kfree(parse_attr->mod_hdr_actions); if (err) - goto err_mod_hdr; + return err; } if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { counter = mlx5_fc_create(attr->counter_dev, true); - if (IS_ERR(counter)) { - err = PTR_ERR(counter); - goto err_create_counter; - } + if (IS_ERR(counter)) + return PTR_ERR(counter); attr->counter = counter; } @@ -1044,27 +1047,10 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, flow->rule[0] = mlx5e_tc_offload_fdb_rules(esw, flow, &parse_attr->spec, attr); } - if (IS_ERR(flow->rule[0])) { - err = PTR_ERR(flow->rule[0]); - goto err_add_rule; - } + if (IS_ERR(flow->rule[0])) + return PTR_ERR(flow->rule[0]); return 0; - -err_add_rule: - mlx5_fc_destroy(attr->counter_dev, counter); -err_create_counter: - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) - mlx5e_detach_mod_hdr(priv, flow); -err_mod_hdr: - mlx5_eswitch_del_vlan_action(esw, attr); -err_add_vlan: - for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) - if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) - mlx5e_detach_encap(priv, flow, out_index); -err_attach_encap: -err_max_prio_chain: - return err; } static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow) @@ -1123,9 +1109,9 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr slow_attr, *esw_attr; + struct encap_flow_item *efi, *tmp; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; - struct encap_flow_item *efi; struct mlx5e_tc_flow *flow; int err; @@ -1142,11 +1128,14 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(priv); - list_for_each_entry(efi, &e->flows, list) { + list_for_each_entry_safe(efi, tmp, &e->flows, list) { bool all_flow_encaps_valid = true; int i; flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); + if (IS_ERR(mlx5e_flow_get(flow))) + continue; + esw_attr = flow->esw_attr; spec = &esw_attr->parse_attr->spec; @@ -1166,19 +1155,22 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, } /* Do not offload flows with unresolved neighbors */ if (!all_flow_encaps_valid) - continue; + goto loop_cont; /* update from slow path rule to encap rule */ rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, esw_attr); if (IS_ERR(rule)) { err = PTR_ERR(rule); mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n", err); - continue; + goto loop_cont; } mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); flow->flags |= MLX5E_TC_FLOW_OFFLOADED; /* was unset when slow path rule removed */ flow->rule[0] = rule; + +loop_cont: + mlx5e_flow_put(priv, flow); } } @@ -1187,14 +1179,17 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr slow_attr; + struct encap_flow_item *efi, *tmp; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; - struct encap_flow_item *efi; struct mlx5e_tc_flow *flow; int err; - list_for_each_entry(efi, &e->flows, list) { + list_for_each_entry_safe(efi, tmp, &e->flows, list) { flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); + if (IS_ERR(mlx5e_flow_get(flow))) + continue; + spec = &flow->esw_attr->parse_attr->spec; /* update from encap rule to slow path rule */ @@ -1206,12 +1201,15 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, err = PTR_ERR(rule); mlx5_core_warn(priv->mdev, "Failed to update slow path (encap) flow, %d\n", err); - continue; + goto loop_cont; } mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->esw_attr); flow->flags |= MLX5E_TC_FLOW_OFFLOADED; /* was unset when fast path rule removed */ flow->rule[0] = rule; + +loop_cont: + mlx5e_flow_put(priv, flow); } /* we know that the encap is valid */ @@ -1248,20 +1246,26 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) return; list_for_each_entry(e, &nhe->encap_list, encap_list) { - struct encap_flow_item *efi; + struct encap_flow_item *efi, *tmp; if (!(e->flags & MLX5_ENCAP_ENTRY_VALID)) continue; - list_for_each_entry(efi, &e->flows, list) { + list_for_each_entry_safe(efi, tmp, &e->flows, list) { flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); + if (IS_ERR(mlx5e_flow_get(flow))) + continue; + if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { counter = mlx5e_tc_get_counter(flow); mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) { + mlx5e_flow_put(netdev_priv(e->out_dev), flow); neigh_used = true; break; } } + + mlx5e_flow_put(netdev_priv(e->out_dev), flow); } if (neigh_used) break; @@ -1287,6 +1291,10 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv, { struct list_head *next = flow->encaps[out_index].list.next; + /* flow wasn't fully initialized */ + if (list_empty(&flow->encaps[out_index].list)) + return; + list_del(&flow->encaps[out_index].list); if (list_empty(next)) { struct mlx5e_encap_entry *e; @@ -3122,7 +3130,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, { struct mlx5e_tc_flow_parse_attr *parse_attr; struct mlx5e_tc_flow *flow; - int err; + int out_index, err; flow = kzalloc(sizeof(*flow) + attr_size, GFP_KERNEL); parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL); @@ -3134,6 +3142,11 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, flow->cookie = f->cookie; flow->flags = flow_flags; flow->priv = priv; + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) + INIT_LIST_HEAD(&flow->encaps[out_index].list); + INIT_LIST_HEAD(&flow->mod_hdr); + INIT_LIST_HEAD(&flow->hairpin); + refcount_set(&flow->refcnt, 1); *__flow = flow; *__parse_attr = parse_attr; @@ -3216,8 +3229,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, return flow; err_free: - kfree(flow); - kvfree(parse_attr); + mlx5e_flow_put(priv, flow); out: return ERR_PTR(err); } @@ -3351,7 +3363,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, return 0; err_free: - kfree(flow); + mlx5e_flow_put(priv, flow); kvfree(parse_attr); out: return err; @@ -3413,8 +3425,7 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, return 0; err_free: - mlx5e_tc_del_flow(priv, flow); - kfree(flow); + mlx5e_flow_put(priv, flow); out: return err; } @@ -3442,9 +3453,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params); - mlx5e_tc_del_flow(priv, flow); - - kfree(flow); + mlx5e_flow_put(priv, flow); return 0; } @@ -3460,15 +3469,22 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, u64 lastuse = 0; u64 packets = 0; u64 bytes = 0; + int err = 0; - flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params); - if (!flow || !same_flow_direction(flow, flags)) - return -EINVAL; + flow = mlx5e_flow_get(rhashtable_lookup_fast(tc_ht, &f->cookie, + tc_ht_params)); + if (IS_ERR(flow)) + return PTR_ERR(flow); + + if (!same_flow_direction(flow, flags)) { + err = -EINVAL; + goto errout; + } if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { counter = mlx5e_tc_get_counter(flow); if (!counter) - return 0; + goto errout; mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); } @@ -3500,8 +3516,9 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); out: flow_stats_update(&f->stats, bytes, packets, lastuse); - - return 0; +errout: + mlx5e_flow_put(priv, flow); + return err; } static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, -- GitLab From 226f2ca3075ab20abf69c68235e8ba9ac2dab596 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 8 Nov 2018 20:01:35 +0200 Subject: [PATCH 1213/7155] net/mlx5e: Change flow flags type to unsigned long To remove dependency on rtnl lock and allow concurrent modification of 'flags' field of tc flow structure, change flow flag type to unsigned long and use atomic bit ops for reading and changing the flags. Implement auxiliary functions for setting, resetting and getting specific flag, and for checking most often used flag values. Always set flags with smp_mb__before_atomic() to ensure that all mlx5e_tc_flow are updated before concurrent readers can read new flags value. Rearrange all code paths to actually set flow->rule[] pointers before setting the OFFLOADED flag. On read side, use smp_mb__after_atomic() when accessing flags to ensure that offload-related flow fields are only read after the flags. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 8 +- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 6 +- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 206 +++++++++++------- .../net/ethernet/mellanox/mlx5/core/en_tc.h | 26 ++- 4 files changed, 149 insertions(+), 97 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 266783295124..b2618dd6dd10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3429,7 +3429,7 @@ static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv, #ifdef CONFIG_MLX5_ESWITCH static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv, struct flow_cls_offload *cls_flower, - int flags) + unsigned long flags) { switch (cls_flower->command) { case FLOW_CLS_REPLACE: @@ -3449,12 +3449,12 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv, static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { + unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(NIC_OFFLOAD); struct mlx5e_priv *priv = cb_priv; switch (type) { case TC_SETUP_CLSFLOWER: - return mlx5e_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS | - MLX5E_TC_NIC_OFFLOAD); + return mlx5e_setup_tc_cls_flower(priv, type_data, flags); default: return -EOPNOTSUPP; } @@ -3647,7 +3647,7 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable) { struct mlx5e_priv *priv = netdev_priv(netdev); - if (!enable && mlx5e_tc_num_filters(priv, MLX5E_TC_NIC_OFFLOAD)) { + if (!enable && mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD))) { netdev_err(netdev, "Active offloaded tc filters, can't turn hw_tc_offload off\n"); return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 496d3034e278..69f7ac8fc9be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -659,8 +659,8 @@ mlx5e_rep_indr_offload(struct net_device *netdev, struct flow_cls_offload *flower, struct mlx5e_rep_indr_block_priv *indr_priv) { + unsigned long flags = MLX5_TC_FLAG(EGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD); struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev); - int flags = MLX5E_TC_EGRESS | MLX5E_TC_ESW_OFFLOAD; int err = 0; switch (flower->command) { @@ -1159,12 +1159,12 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv, static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { + unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD); struct mlx5e_priv *priv = cb_priv; switch (type) { case TC_SETUP_CLSFLOWER: - return mlx5e_rep_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS | - MLX5E_TC_ESW_OFFLOAD); + return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index e2b87f723819..241157b699df 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -66,19 +66,19 @@ struct mlx5_nic_flow_attr { struct mlx5_fc *counter; }; -#define MLX5E_TC_FLOW_BASE (MLX5E_TC_LAST_EXPORTED_BIT + 1) +#define MLX5E_TC_FLOW_BASE (MLX5E_TC_FLAG_LAST_EXPORTED_BIT + 1) enum { - MLX5E_TC_FLOW_INGRESS = MLX5E_TC_INGRESS, - MLX5E_TC_FLOW_EGRESS = MLX5E_TC_EGRESS, - MLX5E_TC_FLOW_ESWITCH = MLX5E_TC_ESW_OFFLOAD, - MLX5E_TC_FLOW_NIC = MLX5E_TC_NIC_OFFLOAD, - MLX5E_TC_FLOW_OFFLOADED = BIT(MLX5E_TC_FLOW_BASE), - MLX5E_TC_FLOW_HAIRPIN = BIT(MLX5E_TC_FLOW_BASE + 1), - MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(MLX5E_TC_FLOW_BASE + 2), - MLX5E_TC_FLOW_SLOW = BIT(MLX5E_TC_FLOW_BASE + 3), - MLX5E_TC_FLOW_DUP = BIT(MLX5E_TC_FLOW_BASE + 4), - MLX5E_TC_FLOW_NOT_READY = BIT(MLX5E_TC_FLOW_BASE + 5), + MLX5E_TC_FLOW_FLAG_INGRESS = MLX5E_TC_FLAG_INGRESS_BIT, + MLX5E_TC_FLOW_FLAG_EGRESS = MLX5E_TC_FLAG_EGRESS_BIT, + MLX5E_TC_FLOW_FLAG_ESWITCH = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, + MLX5E_TC_FLOW_FLAG_NIC = MLX5E_TC_FLAG_NIC_OFFLOAD_BIT, + MLX5E_TC_FLOW_FLAG_OFFLOADED = MLX5E_TC_FLOW_BASE, + MLX5E_TC_FLOW_FLAG_HAIRPIN = MLX5E_TC_FLOW_BASE + 1, + MLX5E_TC_FLOW_FLAG_HAIRPIN_RSS = MLX5E_TC_FLOW_BASE + 2, + MLX5E_TC_FLOW_FLAG_SLOW = MLX5E_TC_FLOW_BASE + 3, + MLX5E_TC_FLOW_FLAG_DUP = MLX5E_TC_FLOW_BASE + 4, + MLX5E_TC_FLOW_FLAG_NOT_READY = MLX5E_TC_FLOW_BASE + 5, }; #define MLX5E_TC_MAX_SPLITS 1 @@ -109,7 +109,7 @@ struct mlx5e_tc_flow { struct rhash_head node; struct mlx5e_priv *priv; u64 cookie; - u16 flags; + unsigned long flags; struct mlx5_flow_handle *rule[MLX5E_TC_MAX_SPLITS + 1]; /* Flow can be associated with multiple encap IDs. * The number of encaps is bounded by the number of supported @@ -205,6 +205,47 @@ static void mlx5e_flow_put(struct mlx5e_priv *priv, } } +static void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag) +{ + /* Complete all memory stores before setting bit. */ + smp_mb__before_atomic(); + set_bit(flag, &flow->flags); +} + +#define flow_flag_set(flow, flag) __flow_flag_set(flow, MLX5E_TC_FLOW_FLAG_##flag) + +static void __flow_flag_clear(struct mlx5e_tc_flow *flow, unsigned long flag) +{ + /* Complete all memory stores before clearing bit. */ + smp_mb__before_atomic(); + clear_bit(flag, &flow->flags); +} + +#define flow_flag_clear(flow, flag) __flow_flag_clear(flow, \ + MLX5E_TC_FLOW_FLAG_##flag) + +static bool __flow_flag_test(struct mlx5e_tc_flow *flow, unsigned long flag) +{ + bool ret = test_bit(flag, &flow->flags); + + /* Read fields of flow structure only after checking flags. */ + smp_mb__after_atomic(); + return ret; +} + +#define flow_flag_test(flow, flag) __flow_flag_test(flow, \ + MLX5E_TC_FLOW_FLAG_##flag) + +static bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow) +{ + return flow_flag_test(flow, ESWITCH); +} + +static bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow) +{ + return flow_flag_test(flow, OFFLOADED); +} + static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key) { return jhash(key->actions, @@ -226,9 +267,9 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; int num_actions, actions_size, namespace, err; + bool found = false, is_eswitch_flow; struct mlx5e_mod_hdr_entry *mh; struct mod_hdr_key key; - bool found = false; u32 hash_key; num_actions = parse_attr->num_mod_hdr_actions; @@ -239,7 +280,8 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, hash_key = hash_mod_hdr_info(&key); - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { + is_eswitch_flow = mlx5e_is_eswitch_flow(flow); + if (is_eswitch_flow) { namespace = MLX5_FLOW_NAMESPACE_FDB; hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh, mod_hdr_hlist, hash_key) { @@ -278,14 +320,14 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, if (err) goto out_err; - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + if (is_eswitch_flow) hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key); else hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key); attach_flow: list_add(&flow->mod_hdr, &mh->flows); - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + if (is_eswitch_flow) flow->esw_attr->mod_hdr_id = mh->mod_hdr_id; else flow->nic_attr->mod_hdr_id = mh->mod_hdr_id; @@ -700,7 +742,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, attach_flow: if (hpe->hp->num_channels > 1) { - flow->flags |= MLX5E_TC_FLOW_HAIRPIN_RSS; + flow_flag_set(flow, HAIRPIN_RSS); flow->nic_attr->hairpin_ft = hpe->hp->ttc.ft.t; } else { flow->nic_attr->hairpin_tirn = hpe->hp->tirn; @@ -761,12 +803,12 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, flow_context->flags |= FLOW_CONTEXT_HAS_TAG; flow_context->flow_tag = attr->flow_tag; - if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) { + if (flow_flag_test(flow, HAIRPIN)) { err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack); if (err) return err; - if (flow->flags & MLX5E_TC_FLOW_HAIRPIN_RSS) { + if (flow_flag_test(flow, HAIRPIN_RSS)) { dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[dest_ix].ft = attr->hairpin_ft; } else { @@ -849,7 +891,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, mlx5_del_flow_rules(flow->rule[0]); mlx5_fc_destroy(priv->mdev, counter); - if (!mlx5e_tc_num_filters(priv, MLX5E_TC_NIC_OFFLOAD) && priv->fs.tc.t) { + if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) && priv->fs.tc.t) { mlx5_destroy_flow_table(priv->fs.tc.t); priv->fs.tc.t = NULL; } @@ -857,7 +899,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) mlx5e_detach_mod_hdr(priv, flow); - if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) + if (flow_flag_test(flow, HAIRPIN)) mlx5e_hairpin_flow_del(priv, flow); } @@ -892,7 +934,6 @@ mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, } } - flow->flags |= MLX5E_TC_FLOW_OFFLOADED; return rule; } @@ -901,7 +942,7 @@ mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw, struct mlx5e_tc_flow *flow, struct mlx5_esw_flow_attr *attr) { - flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED; + flow_flag_clear(flow, OFFLOADED); if (attr->split_count) mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr); @@ -924,7 +965,7 @@ mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); if (!IS_ERR(rule)) - flow->flags |= MLX5E_TC_FLOW_SLOW; + flow_flag_set(flow, SLOW); return rule; } @@ -939,7 +980,7 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, slow_attr->split_count = 0; slow_attr->dest_chain = FDB_SLOW_PATH_CHAIN; mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr); - flow->flags &= ~MLX5E_TC_FLOW_SLOW; + flow_flag_clear(flow, SLOW); } static void add_unready_flow(struct mlx5e_tc_flow *flow) @@ -952,14 +993,14 @@ static void add_unready_flow(struct mlx5e_tc_flow *flow) rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); uplink_priv = &rpriv->uplink_priv; - flow->flags |= MLX5E_TC_FLOW_NOT_READY; + flow_flag_set(flow, NOT_READY); list_add_tail(&flow->unready, &uplink_priv->unready_flows); } static void remove_unready_flow(struct mlx5e_tc_flow *flow) { list_del(&flow->unready); - flow->flags &= ~MLX5E_TC_FLOW_NOT_READY; + flow_flag_clear(flow, NOT_READY); } static int @@ -1049,6 +1090,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, if (IS_ERR(flow->rule[0])) return PTR_ERR(flow->rule[0]); + else + flow_flag_set(flow, OFFLOADED); return 0; } @@ -1074,14 +1117,14 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, struct mlx5_esw_flow_attr slow_attr; int out_index; - if (flow->flags & MLX5E_TC_FLOW_NOT_READY) { + if (flow_flag_test(flow, NOT_READY)) { remove_unready_flow(flow); kvfree(attr->parse_attr); return; } - if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { - if (flow->flags & MLX5E_TC_FLOW_SLOW) + if (mlx5e_is_offloaded_flow(flow)) { + if (flow_flag_test(flow, SLOW)) mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); else mlx5e_tc_unoffload_fdb_rules(esw, flow, attr); @@ -1166,8 +1209,9 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, } mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); - flow->flags |= MLX5E_TC_FLOW_OFFLOADED; /* was unset when slow path rule removed */ flow->rule[0] = rule; + /* was unset when slow path rule removed */ + flow_flag_set(flow, OFFLOADED); loop_cont: mlx5e_flow_put(priv, flow); @@ -1205,8 +1249,9 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, } mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->esw_attr); - flow->flags |= MLX5E_TC_FLOW_OFFLOADED; /* was unset when fast path rule removed */ flow->rule[0] = rule; + /* was unset when fast path rule removed */ + flow_flag_set(flow, OFFLOADED); loop_cont: mlx5e_flow_put(priv, flow); @@ -1219,7 +1264,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow) { - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + if (mlx5e_is_eswitch_flow(flow)) return flow->esw_attr->counter; else return flow->nic_attr->counter; @@ -1255,7 +1300,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) if (IS_ERR(mlx5e_flow_get(flow))) continue; - if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { + if (mlx5e_is_offloaded_flow(flow)) { counter = mlx5e_tc_get_counter(flow); mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) { @@ -1315,15 +1360,15 @@ static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) { struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch; - if (!(flow->flags & MLX5E_TC_FLOW_ESWITCH) || - !(flow->flags & MLX5E_TC_FLOW_DUP)) + if (!flow_flag_test(flow, ESWITCH) || + !flow_flag_test(flow, DUP)) return; mutex_lock(&esw->offloads.peer_mutex); list_del(&flow->peer); mutex_unlock(&esw->offloads.peer_mutex); - flow->flags &= ~MLX5E_TC_FLOW_DUP; + flow_flag_clear(flow, DUP); mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow); kvfree(flow->peer_flow); @@ -1347,7 +1392,7 @@ static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { + if (mlx5e_is_eswitch_flow(flow)) { mlx5e_tc_del_fdb_peer_flow(flow); mlx5e_tc_del_fdb_flow(priv, flow); } else { @@ -1845,11 +1890,13 @@ static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5e_rep_priv *rpriv = priv->ppriv; u8 match_level, tunnel_match_level = MLX5_MATCH_NONE; struct mlx5_eswitch_rep *rep; + bool is_eswitch_flow; int err; err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level); - if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) { + is_eswitch_flow = mlx5e_is_eswitch_flow(flow); + if (!err && is_eswitch_flow) { rep = rpriv->rep; if (rep->vport != MLX5_VPORT_UPLINK && (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE && @@ -1863,7 +1910,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv, } } - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { + if (is_eswitch_flow) { flow->esw_attr->match_level = match_level; flow->esw_attr->tunnel_match_level = tunnel_match_level; } else { @@ -2384,12 +2431,12 @@ static bool actions_match_supported(struct mlx5e_priv *priv, { u32 actions; - if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + if (mlx5e_is_eswitch_flow(flow)) actions = flow->esw_attr->action; else actions = flow->nic_attr->action; - if (flow->flags & MLX5E_TC_FLOW_EGRESS && + if (flow_flag_test(flow, EGRESS) && !((actions & MLX5_FLOW_CONTEXT_ACTION_DECAP) || (actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP))) return false; @@ -2541,7 +2588,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, if (priv->netdev->netdev_ops == peer_dev->netdev_ops && same_hw_devs(priv, netdev_priv(peer_dev))) { parse_attr->mirred_ifindex[0] = peer_dev->ifindex; - flow->flags |= MLX5E_TC_FLOW_HAIRPIN; + flow_flag_set(flow, HAIRPIN); action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT; } else { @@ -3065,19 +3112,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, return 0; } -static void get_flags(int flags, u16 *flow_flags) +static void get_flags(int flags, unsigned long *flow_flags) { - u16 __flow_flags = 0; + unsigned long __flow_flags = 0; - if (flags & MLX5E_TC_INGRESS) - __flow_flags |= MLX5E_TC_FLOW_INGRESS; - if (flags & MLX5E_TC_EGRESS) - __flow_flags |= MLX5E_TC_FLOW_EGRESS; + if (flags & MLX5_TC_FLAG(INGRESS)) + __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_INGRESS); + if (flags & MLX5_TC_FLAG(EGRESS)) + __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_EGRESS); - if (flags & MLX5E_TC_ESW_OFFLOAD) - __flow_flags |= MLX5E_TC_FLOW_ESWITCH; - if (flags & MLX5E_TC_NIC_OFFLOAD) - __flow_flags |= MLX5E_TC_FLOW_NIC; + if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) + __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH); + if (flags & MLX5_TC_FLAG(NIC_OFFLOAD)) + __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC); *flow_flags = __flow_flags; } @@ -3089,12 +3136,13 @@ static const struct rhashtable_params tc_ht_params = { .automatic_shrinking = true, }; -static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, int flags) +static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, + unsigned long flags) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5e_rep_priv *uplink_rpriv; - if (flags & MLX5E_TC_ESW_OFFLOAD) { + if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) { uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); return &uplink_rpriv->uplink_priv.tc_ht; } else /* NIC offload */ @@ -3105,7 +3153,7 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) { struct mlx5_esw_flow_attr *attr = flow->esw_attr; bool is_rep_ingress = attr->in_rep->vport != MLX5_VPORT_UPLINK && - flow->flags & MLX5E_TC_FLOW_INGRESS; + flow_flag_test(flow, INGRESS); bool act_is_encap = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); bool esw_paired = mlx5_devcom_is_paired(attr->in_mdev->priv.devcom, @@ -3124,7 +3172,7 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) static int mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, - struct flow_cls_offload *f, u16 flow_flags, + struct flow_cls_offload *f, unsigned long flow_flags, struct mlx5e_tc_flow_parse_attr **__parse_attr, struct mlx5e_tc_flow **__flow) { @@ -3186,7 +3234,7 @@ mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr, static struct mlx5e_tc_flow * __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct flow_cls_offload *f, - u16 flow_flags, + unsigned long flow_flags, struct net_device *filter_dev, struct mlx5_eswitch_rep *in_rep, struct mlx5_core_dev *in_mdev) @@ -3197,7 +3245,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow; int attr_size, err; - flow_flags |= MLX5E_TC_FLOW_ESWITCH; + flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH); attr_size = sizeof(struct mlx5_esw_flow_attr); err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags, &parse_attr, &flow); @@ -3236,7 +3284,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, struct mlx5e_tc_flow *flow, - u16 flow_flags) + unsigned long flow_flags) { struct mlx5e_priv *priv = flow->priv, *peer_priv; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw; @@ -3274,7 +3322,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, } flow->peer_flow = peer_flow; - flow->flags |= MLX5E_TC_FLOW_DUP; + flow_flag_set(flow, DUP); mutex_lock(&esw->offloads.peer_mutex); list_add_tail(&flow->peer, &esw->offloads.peer_flows); mutex_unlock(&esw->offloads.peer_mutex); @@ -3287,7 +3335,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, static int mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct flow_cls_offload *f, - u16 flow_flags, + unsigned long flow_flags, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { @@ -3321,7 +3369,7 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, static int mlx5e_add_nic_flow(struct mlx5e_priv *priv, struct flow_cls_offload *f, - u16 flow_flags, + unsigned long flow_flags, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { @@ -3335,7 +3383,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, if (!tc_cls_can_offload_and_chain0(priv->netdev, &f->common)) return -EOPNOTSUPP; - flow_flags |= MLX5E_TC_FLOW_NIC; + flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC); attr_size = sizeof(struct mlx5_nic_flow_attr); err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags, &parse_attr, &flow); @@ -3356,7 +3404,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, if (err) goto err_free; - flow->flags |= MLX5E_TC_FLOW_OFFLOADED; + flow_flag_set(flow, OFFLOADED); kvfree(parse_attr); *__flow = flow; @@ -3372,12 +3420,12 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, static int mlx5e_tc_add_flow(struct mlx5e_priv *priv, struct flow_cls_offload *f, - int flags, + unsigned long flags, struct net_device *filter_dev, struct mlx5e_tc_flow **flow) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; - u16 flow_flags; + unsigned long flow_flags; int err; get_flags(flags, &flow_flags); @@ -3396,7 +3444,7 @@ mlx5e_tc_add_flow(struct mlx5e_priv *priv, } int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags) + struct flow_cls_offload *f, unsigned long flags) { struct netlink_ext_ack *extack = f->common.extack; struct rhashtable *tc_ht = get_tc_ht(priv, flags); @@ -3430,19 +3478,17 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, return err; } -#define DIRECTION_MASK (MLX5E_TC_INGRESS | MLX5E_TC_EGRESS) -#define FLOW_DIRECTION_MASK (MLX5E_TC_FLOW_INGRESS | MLX5E_TC_FLOW_EGRESS) - static bool same_flow_direction(struct mlx5e_tc_flow *flow, int flags) { - if ((flow->flags & FLOW_DIRECTION_MASK) == (flags & DIRECTION_MASK)) - return true; + bool dir_ingress = !!(flags & MLX5_TC_FLAG(INGRESS)); + bool dir_egress = !!(flags & MLX5_TC_FLAG(EGRESS)); - return false; + return flow_flag_test(flow, INGRESS) == dir_ingress && + flow_flag_test(flow, EGRESS) == dir_egress; } int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags) + struct flow_cls_offload *f, unsigned long flags) { struct rhashtable *tc_ht = get_tc_ht(priv, flags); struct mlx5e_tc_flow *flow; @@ -3459,7 +3505,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, } int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags) + struct flow_cls_offload *f, unsigned long flags) { struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct rhashtable *tc_ht = get_tc_ht(priv, flags); @@ -3481,7 +3527,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, goto errout; } - if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { + if (mlx5e_is_offloaded_flow(flow)) { counter = mlx5e_tc_get_counter(flow); if (!counter) goto errout; @@ -3496,8 +3542,8 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, if (!peer_esw) goto out; - if ((flow->flags & MLX5E_TC_FLOW_DUP) && - (flow->peer_flow->flags & MLX5E_TC_FLOW_OFFLOADED)) { + if (flow_flag_test(flow, DUP) && + flow_flag_test(flow->peer_flow, OFFLOADED)) { u64 bytes2; u64 packets2; u64 lastuse2; @@ -3622,7 +3668,7 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht) rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL); } -int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags) +int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags) { struct rhashtable *tc_ht = get_tc_ht(priv, flags); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index 3ab39275ca7d..1cb66bf76997 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -40,13 +40,15 @@ #ifdef CONFIG_MLX5_ESWITCH enum { - MLX5E_TC_INGRESS = BIT(0), - MLX5E_TC_EGRESS = BIT(1), - MLX5E_TC_NIC_OFFLOAD = BIT(2), - MLX5E_TC_ESW_OFFLOAD = BIT(3), - MLX5E_TC_LAST_EXPORTED_BIT = 3, + MLX5E_TC_FLAG_INGRESS_BIT, + MLX5E_TC_FLAG_EGRESS_BIT, + MLX5E_TC_FLAG_NIC_OFFLOAD_BIT, + MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, + MLX5E_TC_FLAG_LAST_EXPORTED_BIT = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, }; +#define MLX5_TC_FLAG(flag) BIT(MLX5E_TC_FLAG_##flag##_BIT) + int mlx5e_tc_nic_init(struct mlx5e_priv *priv); void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv); @@ -54,12 +56,12 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht); void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht); int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags); + struct flow_cls_offload *f, unsigned long flags); int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags); + struct flow_cls_offload *f, unsigned long flags); int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, - struct flow_cls_offload *f, int flags); + struct flow_cls_offload *f, unsigned long flags); struct mlx5e_encap_entry; void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, @@ -70,7 +72,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, struct mlx5e_neigh_hash_entry; void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe); -int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags); +int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags); void mlx5e_tc_reoffload_flows_work(struct work_struct *work); @@ -80,7 +82,11 @@ bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv, #else /* CONFIG_MLX5_ESWITCH */ static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; } static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {} -static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags) { return 0; } +static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv, + unsigned long flags) +{ + return 0; +} #endif #endif /* __MLX5_EN_TC_H__ */ -- GitLab From c5d326b29603bad4e5342801414b7302ba010209 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 10 Oct 2018 13:51:10 +0300 Subject: [PATCH 1214/7155] net/mlx5e: Protect tc flows hashtable with rcu In order to remove dependency on rtnl lock, access to tc flows hashtable must be explicitly protected from concurrent flows removal. Extend tc flow structure with rcu to allow concurrent parallel access. Use rcu read lock to safely lookup flow in tc flows hash table, and take reference to it. Use rcu free for flow deletion to accommodate concurrent stats requests. Add new DELETED flow flag. Imlement new flow_flag_test_and_set() helper that is used to set a flag and return its previous value. Use it to atomically set the flag in mlx5e_delete_flower() to guarantee that flow can only be deleted once, even when same flow is deleted concurrently by multiple tasks. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 241157b699df..a39f8a07de0a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -79,6 +79,7 @@ enum { MLX5E_TC_FLOW_FLAG_SLOW = MLX5E_TC_FLOW_BASE + 3, MLX5E_TC_FLOW_FLAG_DUP = MLX5E_TC_FLOW_BASE + 4, MLX5E_TC_FLOW_FLAG_NOT_READY = MLX5E_TC_FLOW_BASE + 5, + MLX5E_TC_FLOW_FLAG_DELETED = MLX5E_TC_FLOW_BASE + 6, }; #define MLX5E_TC_MAX_SPLITS 1 @@ -122,6 +123,7 @@ struct mlx5e_tc_flow { struct list_head peer; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ refcount_t refcnt; + struct rcu_head rcu_head; union { struct mlx5_esw_flow_attr esw_attr[0]; struct mlx5_nic_flow_attr nic_attr[0]; @@ -201,7 +203,7 @@ static void mlx5e_flow_put(struct mlx5e_priv *priv, { if (refcount_dec_and_test(&flow->refcnt)) { mlx5e_tc_del_flow(priv, flow); - kfree(flow); + kfree_rcu(flow, rcu_head); } } @@ -214,6 +216,17 @@ static void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag) #define flow_flag_set(flow, flag) __flow_flag_set(flow, MLX5E_TC_FLOW_FLAG_##flag) +static bool __flow_flag_test_and_set(struct mlx5e_tc_flow *flow, + unsigned long flag) +{ + /* test_and_set_bit() provides all necessary barriers */ + return test_and_set_bit(flag, &flow->flags); +} + +#define flow_flag_test_and_set(flow, flag) \ + __flow_flag_test_and_set(flow, \ + MLX5E_TC_FLOW_FLAG_##flag) + static void __flow_flag_clear(struct mlx5e_tc_flow *flow, unsigned long flag) { /* Complete all memory stores before clearing bit. */ @@ -3451,7 +3464,9 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow; int err = 0; - flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params); + rcu_read_lock(); + flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params); + rcu_read_unlock(); if (flow) { NL_SET_ERR_MSG_MOD(extack, "flow cookie already exists, ignoring"); @@ -3466,7 +3481,7 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, if (err) goto out; - err = rhashtable_insert_fast(tc_ht, &flow->node, tc_ht_params); + err = rhashtable_lookup_insert_fast(tc_ht, &flow->node, tc_ht_params); if (err) goto err_free; @@ -3492,16 +3507,32 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, { struct rhashtable *tc_ht = get_tc_ht(priv, flags); struct mlx5e_tc_flow *flow; + int err; + rcu_read_lock(); flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params); - if (!flow || !same_flow_direction(flow, flags)) - return -EINVAL; + if (!flow || !same_flow_direction(flow, flags)) { + err = -EINVAL; + goto errout; + } + /* Only delete the flow if it doesn't have MLX5E_TC_FLOW_DELETED flag + * set. + */ + if (flow_flag_test_and_set(flow, DELETED)) { + err = -EINVAL; + goto errout; + } rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params); + rcu_read_unlock(); mlx5e_flow_put(priv, flow); return 0; + +errout: + rcu_read_unlock(); + return err; } int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, @@ -3517,8 +3548,10 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, u64 bytes = 0; int err = 0; - flow = mlx5e_flow_get(rhashtable_lookup_fast(tc_ht, &f->cookie, - tc_ht_params)); + rcu_read_lock(); + flow = mlx5e_flow_get(rhashtable_lookup(tc_ht, &f->cookie, + tc_ht_params)); + rcu_read_unlock(); if (IS_ERR(flow)) return PTR_ERR(flow); -- GitLab From ad86755b18d5edf1956f6d25c844f27289216877 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 13 Mar 2019 19:50:24 +0200 Subject: [PATCH 1215/7155] net/mlx5e: Protect unready flows with dedicated lock In order to remove dependency on rtnl lock for protecting unready_flows list when reoffloading unready flows on workqueue, extend representor uplink private structure with dedicated 'unready_flows_lock' mutex. Take the lock in all users of unready_flows list before accessing it. Implement helper functions to add and delete unready flow. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 2 + .../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 43 ++++++++++++++++--- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 69f7ac8fc9be..6edf0aeb1e26 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1560,6 +1560,7 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { uplink_priv = &rpriv->uplink_priv; + mutex_init(&uplink_priv->unready_flows_lock); INIT_LIST_HEAD(&uplink_priv->unready_flows); /* init shared tc flow table */ @@ -1604,6 +1605,7 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) /* delete shared tc flow table */ mlx5e_tc_esw_cleanup(&rpriv->uplink_priv.tc_ht); + mutex_destroy(&rpriv->uplink_priv.unready_flows_lock); } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index c56e6ee4350c..10fafd5fa17b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -75,6 +75,8 @@ struct mlx5_rep_uplink_priv { struct mlx5_tun_entropy tun_entropy; + /* protects unready_flows */ + struct mutex unready_flows_lock; struct list_head unready_flows; struct work_struct reoffload_flows_work; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a39f8a07de0a..714aa9d7180b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -996,6 +996,25 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, flow_flag_clear(flow, SLOW); } +/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this + * function. + */ +static void unready_flow_add(struct mlx5e_tc_flow *flow, + struct list_head *unready_flows) +{ + flow_flag_set(flow, NOT_READY); + list_add_tail(&flow->unready, unready_flows); +} + +/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this + * function. + */ +static void unready_flow_del(struct mlx5e_tc_flow *flow) +{ + list_del(&flow->unready); + flow_flag_clear(flow, NOT_READY); +} + static void add_unready_flow(struct mlx5e_tc_flow *flow) { struct mlx5_rep_uplink_priv *uplink_priv; @@ -1006,14 +1025,24 @@ static void add_unready_flow(struct mlx5e_tc_flow *flow) rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); uplink_priv = &rpriv->uplink_priv; - flow_flag_set(flow, NOT_READY); - list_add_tail(&flow->unready, &uplink_priv->unready_flows); + mutex_lock(&uplink_priv->unready_flows_lock); + unready_flow_add(flow, &uplink_priv->unready_flows); + mutex_unlock(&uplink_priv->unready_flows_lock); } static void remove_unready_flow(struct mlx5e_tc_flow *flow) { - list_del(&flow->unready); - flow_flag_clear(flow, NOT_READY); + struct mlx5_rep_uplink_priv *uplink_priv; + struct mlx5e_rep_priv *rpriv; + struct mlx5_eswitch *esw; + + esw = flow->priv->mdev->priv.eswitch; + rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); + uplink_priv = &rpriv->uplink_priv; + + mutex_lock(&uplink_priv->unready_flows_lock); + unready_flow_del(flow); + mutex_unlock(&uplink_priv->unready_flows_lock); } static int @@ -3723,10 +3752,10 @@ void mlx5e_tc_reoffload_flows_work(struct work_struct *work) reoffload_flows_work); struct mlx5e_tc_flow *flow, *tmp; - rtnl_lock(); + mutex_lock(&rpriv->unready_flows_lock); list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) { if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL)) - remove_unready_flow(flow); + unready_flow_del(flow); } - rtnl_unlock(); + mutex_unlock(&rpriv->unready_flows_lock); } -- GitLab From 525e84bea52be145b0ae863ff8d242ce273e3bc6 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Sun, 18 Nov 2018 13:12:59 +0200 Subject: [PATCH 1216/7155] net/mlx5e: Eswitch, change offloads num_flows type to atomic64 Eswitch implements its own locking by means of state_lock mutex and multiple fine-grained lock in containing data structures, and is supposed to not rely on rtnl lock. However, eswitch offloads num_flows type is a regular long long integer and cannot be modified concurrently. This is an implicit assumptions that mlx5 tc is serialized (by rtnl lock or any other means). In order to remove implicit dependency on rtnl lock, change num_flows type to atomic64 to allow concurrent modifications. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 3 ++- .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 10 +++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 1f3891fde2eb..d365551d2f10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1933,6 +1933,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) hash_init(esw->offloads.encap_tbl); hash_init(esw->offloads.mod_hdr_tbl); + atomic64_set(&esw->offloads.num_flows, 0); mutex_init(&esw->state_lock); mlx5_esw_for_all_vports(esw, i, vport) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index a38e8a3c7c9a..60f0c62b447b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -179,7 +180,7 @@ struct mlx5_esw_offload { struct mutex termtbl_mutex; /* protects termtbl hash */ const struct mlx5_eswitch_rep_ops *rep_ops[NUM_REP_TYPES]; u8 inline_mode; - u64 num_flows; + atomic64_t num_flows; enum devlink_eswitch_encap_mode encap; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 089ae4d48a82..244ad1893691 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -233,7 +233,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, if (IS_ERR(rule)) goto err_add_rule; else - esw->offloads.num_flows++; + atomic64_inc(&esw->offloads.num_flows); return rule; @@ -298,7 +298,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw, if (IS_ERR(rule)) goto add_err; - esw->offloads.num_flows++; + atomic64_inc(&esw->offloads.num_flows); return rule; add_err: @@ -326,7 +326,7 @@ __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw, mlx5_eswitch_termtbl_put(esw, attr->dests[i].termtbl); } - esw->offloads.num_flows--; + atomic64_dec(&esw->offloads.num_flows); if (fwd_rule) { esw_put_prio_table(esw, attr->chain, attr->prio, 1); @@ -2349,7 +2349,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, break; } - if (esw->offloads.num_flows > 0) { + if (atomic64_read(&esw->offloads.num_flows) > 0) { NL_SET_ERR_MSG_MOD(extack, "Can't set inline mode when flows are configured"); return -EOPNOTSUPP; @@ -2459,7 +2459,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, if (esw->offloads.encap == encap) return 0; - if (esw->offloads.num_flows > 0) { + if (atomic64_read(&esw->offloads.num_flows) > 0) { NL_SET_ERR_MSG_MOD(extack, "Can't set encapsulation when flows are configured"); return -EOPNOTSUPP; -- GitLab From 0e18134f4f9f1e5c75b63b84d250b116c76d5116 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 11 Sep 2018 15:48:59 +0300 Subject: [PATCH 1217/7155] net/mlx5e: Eswitch, use state_lock to synchronize vlan change esw->state_lock is already used to protect vlan vport configuration change. However, all preparation and correctness checks, and code that sets vport data are not protected by this lock and assume external synchronization by rtnl lock. In order to remove dependency on rtnl lock, extend esw->state_lock protection to whole eswitch vlan add/del functions. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 15 ++++++++------- .../mellanox/mlx5/core/eswitch_offloads.c | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d365551d2f10..7a0888470fae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -2086,23 +2086,19 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, if (vlan > 4095 || qos > 7) return -EINVAL; - mutex_lock(&esw->state_lock); - err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); if (err) - goto unlock; + return err; evport->info.vlan = vlan; evport->info.qos = qos; if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) { err = esw_vport_ingress_config(esw, evport); if (err) - goto unlock; + return err; err = esw_vport_egress_config(esw, evport); } -unlock: - mutex_unlock(&esw->state_lock); return err; } @@ -2110,11 +2106,16 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, u16 vport, u16 vlan, u8 qos) { u8 set_flags = 0; + int err; if (vlan || qos) set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT; - return __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags); + mutex_lock(&esw->state_lock); + err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags); + mutex_unlock(&esw->state_lock); + + return err; } int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 244ad1893691..d502c91c148c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -442,9 +442,11 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw, fwd = !!((attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && !attr->dest_chain); + mutex_lock(&esw->state_lock); + err = esw_add_vlan_action_check(attr, push, pop, fwd); if (err) - return err; + goto unlock; attr->vlan_handled = false; @@ -457,11 +459,11 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw, attr->vlan_handled = true; } - return 0; + goto unlock; } if (!push && !pop) - return 0; + goto unlock; if (!(offloads->vlan_push_pop_refcount)) { /* it's the 1st vlan rule, apply global vlan pop policy */ @@ -486,6 +488,8 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw, out: if (!err) attr->vlan_handled = true; +unlock: + mutex_unlock(&esw->state_lock); return err; } @@ -508,6 +512,8 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, pop = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP); fwd = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST); + mutex_lock(&esw->state_lock); + vport = esw_vlan_action_get_vport(attr, push, pop); if (!push && !pop && fwd) { @@ -515,7 +521,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) vport->vlan_refcount--; - return 0; + goto out; } if (push) { @@ -533,12 +539,13 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, skip_unset_push: offloads->vlan_push_pop_refcount--; if (offloads->vlan_push_pop_refcount) - return 0; + goto out; /* no more vlan rules, stop global vlan pop policy */ err = esw_set_global_vlan_pop(esw, 0); out: + mutex_unlock(&esw->state_lock); return err; } -- GitLab From fa833bd52b7b58d8311bf6a0be29a32e62a1f289 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 12 Mar 2019 11:40:12 +0200 Subject: [PATCH 1218/7155] net/mlx5e: Rely on rcu instead of rtnl lock when getting upper dev Function netdev_master_upper_dev_get() generates warning if caller doesn't hold rtnl lock. Modify rules update path to use rcu version of that function. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 14 +++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index ae439d95f5a3..4c4620db3d31 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -31,11 +31,23 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv, real_dev = is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : dev; uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); - uplink_upper = netdev_master_upper_dev_get(uplink_dev); + + rcu_read_lock(); + uplink_upper = netdev_master_upper_dev_get_rcu(uplink_dev); + /* mlx5_lag_is_sriov() is a blocking function which can't be called + * while holding rcu read lock. Take the net_device for correctness + * sake. + */ + if (uplink_upper) + dev_hold(uplink_upper); + rcu_read_unlock(); + dst_is_lag_dev = (uplink_upper && netif_is_lag_master(uplink_upper) && real_dev == uplink_upper && mlx5_lag_is_sriov(priv->mdev)); + if (uplink_upper) + dev_put(uplink_upper); /* if the egress device isn't on the same HW e-switch or * it's a LAG device, use the uplink diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 714aa9d7180b..595a4c5667ea 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2978,12 +2978,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, if (netdev_port_same_parent_id(priv->netdev, out_dev)) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); - struct net_device *uplink_upper = netdev_master_upper_dev_get(uplink_dev); + struct net_device *uplink_upper; + rcu_read_lock(); + uplink_upper = + netdev_master_upper_dev_get_rcu(uplink_dev); if (uplink_upper && netif_is_lag_master(uplink_upper) && uplink_upper == out_dev) out_dev = uplink_dev; + rcu_read_unlock(); if (is_vlan_dev(out_dev)) { err = add_vlan_push_action(priv, attr, -- GitLab From b6fac0b46a1a76024698d240f0f9aac552f897b7 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Mon, 17 Sep 2018 14:01:58 +0300 Subject: [PATCH 1219/7155] net/mlx5e: Protect tc flow table with mutex TC flow table is created when first flow is added, and destroyed when last flow is removed. This assumes that all accesses to the table are externally synchronized with rtnl lock. To remove dependency on rtnl lock, add new mutex mlx5e_tc_table->t_lock and use it to protect the flow table. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/fs.h | 2 ++ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h index eb70ada89b09..4518ce19112e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h @@ -10,6 +10,8 @@ enum { }; struct mlx5e_tc_table { + /* protects flow table */ + struct mutex t_lock; struct mlx5_flow_table *t; struct rhashtable ht; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 595a4c5667ea..f3ed028d5017 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -854,6 +854,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, return err; } + mutex_lock(&priv->fs.tc.t_lock); if (IS_ERR_OR_NULL(priv->fs.tc.t)) { int tc_grp_size, tc_tbl_size; u32 max_flow_counter; @@ -873,6 +874,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, MLX5E_TC_TABLE_NUM_GROUPS, MLX5E_TC_FT_LEVEL, 0); if (IS_ERR(priv->fs.tc.t)) { + mutex_unlock(&priv->fs.tc.t_lock); NL_SET_ERR_MSG_MOD(extack, "Failed to create tc offload table\n"); netdev_err(priv->netdev, @@ -886,6 +888,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, flow->rule[0] = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec, &flow_act, dest, dest_ix); + mutex_unlock(&priv->fs.tc.t_lock); if (IS_ERR(flow->rule[0])) return PTR_ERR(flow->rule[0]); @@ -904,10 +907,12 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, mlx5_del_flow_rules(flow->rule[0]); mlx5_fc_destroy(priv->mdev, counter); + mutex_lock(&priv->fs.tc.t_lock); if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) && priv->fs.tc.t) { mlx5_destroy_flow_table(priv->fs.tc.t); priv->fs.tc.t = NULL; } + mutex_unlock(&priv->fs.tc.t_lock); if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) mlx5e_detach_mod_hdr(priv, flow); @@ -3684,6 +3689,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) struct mlx5e_tc_table *tc = &priv->fs.tc; int err; + mutex_init(&tc->t_lock); hash_init(tc->mod_hdr_tbl); hash_init(tc->hairpin_tbl); @@ -3722,6 +3728,7 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) mlx5_destroy_flow_table(tc->t); tc->t = NULL; } + mutex_destroy(&tc->t_lock); } int mlx5e_tc_esw_init(struct rhashtable *tc_ht) -- GitLab From 51dbe89768289c32406f47ad89957b79220c1b63 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 17:49:33 -0500 Subject: [PATCH 1220/7155] cpufreq: ti-cpufreq: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: arm): drivers/cpufreq/ti-cpufreq.c: In function ‘dra7_efuse_xlate’: drivers/cpufreq/ti-cpufreq.c:79:20: warning: this statement may fall through [-Wimplicit-fallthrough=] calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; drivers/cpufreq/ti-cpufreq.c:80:2: note: here case DRA7_EFUSE_HAS_OD_MPU_OPP: ^~~~ Signed-off-by: Gustavo A. R. Silva Signed-off-by: Viresh Kumar --- drivers/cpufreq/ti-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 2ad1ae17932d..aeaa883a8c9d 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -77,6 +77,7 @@ static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data, case DRA7_EFUSE_HAS_ALL_MPU_OPP: case DRA7_EFUSE_HAS_HIGH_MPU_OPP: calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; + /* Fall through */ case DRA7_EFUSE_HAS_OD_MPU_OPP: calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP; } -- GitLab From 8e774e023565c682c67617da5141c7395c8a5fac Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 15:54:54 -0500 Subject: [PATCH 1221/7155] sound: dmasound_atari: Mark expected switch fall-through Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: m68k): sound/oss/dmasound/dmasound_atari.c: warning: this statement may fall through [-Wimplicit-fallthrough=]: => 1449:24 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. Reported-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Takashi Iwai --- sound/oss/dmasound/dmasound_atari.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 83653683fd68..823ccfa089b2 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -1432,25 +1432,25 @@ static int FalconMixerIoctl(u_int cmd, u_long arg) { int data; switch (cmd) { - case SOUND_MIXER_READ_RECMASK: + case SOUND_MIXER_READ_RECMASK: return IOCTL_OUT(arg, SOUND_MASK_MIC); - case SOUND_MIXER_READ_DEVMASK: + case SOUND_MIXER_READ_DEVMASK: return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); - case SOUND_MIXER_READ_STEREODEVS: + case SOUND_MIXER_READ_STEREODEVS: return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); - case SOUND_MIXER_READ_VOLUME: + case SOUND_MIXER_READ_VOLUME: return IOCTL_OUT(arg, VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8); - case SOUND_MIXER_READ_CAPS: + case SOUND_MIXER_READ_CAPS: return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); - case SOUND_MIXER_WRITE_MIC: + case SOUND_MIXER_WRITE_MIC: IOCTL_IN(arg, data); tt_dmasnd.input_gain = RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall thru, return set value */ - case SOUND_MIXER_READ_MIC: + /* fall through - return set value */ + case SOUND_MIXER_READ_MIC: return IOCTL_OUT(arg, RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); -- GitLab From 83554cb94515467cfff10f70ec858d60bbbab8ca Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 20:49:44 -0500 Subject: [PATCH 1222/7155] ALSA: sparc: Mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warnings (Building: sparc64): sound/sparc/dbri.c: In function ‘reverse_bytes’: sound/sparc/dbri.c:582:5: warning: this statement may fall through [-Wimplicit-fallthrough=] b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/sparc/dbri.c:583:2: note: here case 16: ^~~~ sound/sparc/dbri.c:584:5: warning: this statement may fall through [-Wimplicit-fallthrough=] b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/sparc/dbri.c:585:2: note: here case 8: ^~~~ sound/sparc/dbri.c:586:5: warning: this statement may fall through [-Wimplicit-fallthrough=] b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/sparc/dbri.c:587:2: note: here case 4: ^~~~ sound/sparc/dbri.c:588:5: warning: this statement may fall through [-Wimplicit-fallthrough=] b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/sparc/dbri.c:589:2: note: here case 2: ^~~~ Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/sparc/dbri.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 010113156239..6e065d44060e 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -580,12 +580,16 @@ static __u32 reverse_bytes(__u32 b, int len) switch (len) { case 32: b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); + /* fall through */ case 16: b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); + /* fall through */ case 8: b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); + /* fall through */ case 4: b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); + /* fall through */ case 2: b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); case 1: -- GitLab From 9091373ab7ea27cad381ce71aa37de6b9e687e81 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 30 Jul 2019 14:43:47 +0900 Subject: [PATCH 1223/7155] gpio: remove less important #ifdef around declarations The whole struct/function declarations in this header are surrounded by #ifdef. As far as I understood, the motivation of this is probably to break the build earlier if a driver misses to select or depend on correct CONFIG options in Kconfig. Since commit 94bed2a9c4ae ("Add -Werror-implicit-function-declaration") no one cannot call functions that have not been declared. So, I see some benefit in doing this in the cost of uglier headers. In reality, it would not be so easy to catch missed 'select' or 'depends on' because GPIOLIB, GPIOLIB_IRQCHIP etc. are already selected by someone else eventually. So, this kind of error, if any, will be caught by randconfig bots. In summary, I am not a big fan of cluttered #ifdef nesting, and this does not matter for normal developers. The code readability wins. Signed-off-by: Masahiro Yamada Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6a0e420915a3..f28f534f451a 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -20,9 +20,6 @@ struct module; enum gpiod_flags; enum gpio_lookup_flags; -#ifdef CONFIG_GPIOLIB - -#ifdef CONFIG_GPIOLIB_IRQCHIP /** * struct gpio_irq_chip - GPIO interrupt controller */ @@ -161,7 +158,6 @@ struct gpio_irq_chip { */ void (*irq_disable)(struct irq_data *data); }; -#endif /* CONFIG_GPIOLIB_IRQCHIP */ /** * struct gpio_chip - abstract a GPIO controller @@ -441,16 +437,12 @@ bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *chip); -struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); - struct bgpio_pdata { const char *label; int base; int ngpio; }; -#if IS_ENABLED(CONFIG_GPIO_GENERIC) - int bgpio_init(struct gpio_chip *gc, struct device *dev, unsigned long sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, @@ -463,10 +455,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ -#endif /* CONFIG_GPIO_GENERIC */ - -#ifdef CONFIG_GPIOLIB_IRQCHIP - int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq); void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); @@ -555,15 +543,11 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, } #endif /* CONFIG_LOCKDEP */ -#endif /* CONFIG_GPIOLIB_IRQCHIP */ - int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, unsigned long config); -#ifdef CONFIG_PINCTRL - /** * struct gpio_pin_range - pin range controlled by a gpio chip * @node: list for maintaining set of pin ranges, used internally @@ -576,6 +560,8 @@ struct gpio_pin_range { struct pinctrl_gpio_range range; }; +#ifdef CONFIG_PINCTRL + int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins); @@ -586,8 +572,6 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip); #else /* ! CONFIG_PINCTRL */ -struct pinctrl_dev; - static inline int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, @@ -619,6 +603,11 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); + +#ifdef CONFIG_GPIOLIB + +struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -630,4 +619,4 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) #endif /* CONFIG_GPIOLIB */ -#endif +#endif /* __LINUX_GPIO_DRIVER_H */ -- GitLab From 07ca9aa4a4b7fdd3c29cc9f8b07a2d1b8e0b6ba5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:03:21 +0800 Subject: [PATCH 1224/7155] staging: rtl8723bs: remove set but not used variable 'bWifiBusy' Fixes gcc '-Wunused-but-set-variable' warning: In function halbtc8723b1ant_TdmaDurationAdjustForAcl: drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c:1761:7: warning: variable bWifiBusy set but not used [-Wunused-but-set-variable] It is never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140321.19200-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c index 8e4caeeb4070..dd349c506da8 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c +++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c @@ -1758,7 +1758,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( static s32 up, dn, m, n, WaitCount; s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ u8 retryCount = 0, btInfoExt; - bool bWifiBusy = false; BTC_PRINT( BTC_MSG_ALGORITHM, @@ -1766,11 +1765,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( ("[BTCoex], TdmaDurationAdjustForAcl()\n") ); - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifiStatus) - bWifiBusy = true; - else - bWifiBusy = false; - if ( (BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifiStatus) || (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifiStatus) || -- GitLab From 30833b4b4bc6c3da04e3478552a25a7da4ebc92c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:07:34 +0800 Subject: [PATCH 1225/7155] staging: rtl8723bs: remove set but not used variable 'pszBBRegMpFile' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c: In function phy_BB8723b_Config_ParaFile: drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c:436:77: warning: variable pszBBRegMpFile set but not used [-Wunused-but-set-variable] It is never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140734.39564-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index cb3ec085faa5..6df2b58bdc67 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -431,14 +431,12 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter) u8 sz8723BBRegFile[] = RTL8723B_PHY_REG; u8 sz8723AGCTableFile[] = RTL8723B_AGC_TAB; u8 sz8723BBBRegPgFile[] = RTL8723B_PHY_REG_PG; - u8 sz8723BBRegMpFile[] = RTL8723B_PHY_REG_MP; u8 sz8723BRFTxPwrLmtFile[] = RTL8723B_TXPWR_LMT; - u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszBBRegMpFile = NULL, *pszRFTxPwrLmtFile = NULL; + u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszRFTxPwrLmtFile = NULL; pszBBRegFile = sz8723BBRegFile; pszAGCTableFile = sz8723AGCTableFile; pszBBRegPgFile = sz8723BBBRegPgFile; - pszBBRegMpFile = sz8723BBRegMpFile; pszRFTxPwrLmtFile = sz8723BRFTxPwrLmtFile; /* Read Tx Power Limit File */ -- GitLab From 149726d3d78a6053445aaff6361374a0b67b7ac1 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:09:59 +0800 Subject: [PATCH 1226/7155] staging: rtl8723bs: os_dep: remove two set but not used variables Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs//os_dep/osdep_service.c: In function 'rtw_buf_free': drivers/staging/rtl8723bs//os_dep/osdep_service.c:321:6: warning: variable 'ori_len' set but not used [-Wunused-but-set-variable] drivers/staging/rtl8723bs//os_dep/ioctl_linux.c: In function 'rtw_ioctl_wext_private': drivers/staging/rtl8723bs//os_dep/ioctl_linux.c:4915:6: warning: variable 'num_priv' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140959.15008-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 -- drivers/staging/rtl8723bs/os_dep/osdep_service.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 99e6b1028f71..90c2997256b7 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -4912,7 +4912,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ s32 k; const iw_handler *priv; /* Private ioctl */ const struct iw_priv_args *priv_args; /* Private ioctl description */ - u32 num_priv; /* Number of ioctl */ u32 num_priv_args; /* Number of descriptions */ iw_handler handler; int temp; @@ -4948,7 +4947,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ priv = rtw_private_handler; priv_args = rtw_private_args; - num_priv = ARRAY_SIZE(rtw_private_handler); num_priv_args = ARRAY_SIZE(rtw_private_args); if (num_priv_args == 0) { diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index 62fdd24ba427..25a80041ce87 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -318,13 +318,9 @@ int rtw_change_ifname(struct adapter *padapter, const char *ifname) void rtw_buf_free(u8 **buf, u32 *buf_len) { - u32 ori_len; - if (!buf || !buf_len) return; - ori_len = *buf_len; - if (*buf) { *buf_len = 0; kfree(*buf); -- GitLab From db0e6a573e9c54151cdc828e80ab82849802337f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 09:35:24 +0800 Subject: [PATCH 1227/7155] staging: vc04_services: fix unused-but-set-variable warning Fix gcc used-but-set-variable warning: drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function vchiq_release_internal: drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:2827:16: warning: variable local_entity_uc set but not used [-Wunused-but-set-variable] drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:2827:6: warning: variable local_uc set but not used [-Wunused-but-set-variable] Remove the unused variables 'local_entity_uc' and 'local_uc' Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Stefan Wahren Link: https://lore.kernel.org/r/20190727013524.33168-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index cc4383d1ec3e..b1595b13dea8 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2824,7 +2824,6 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; - int local_uc, local_entity_uc; if (!arm_state) goto out; @@ -2849,8 +2848,8 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) ret = VCHIQ_ERROR; goto unlock; } - local_uc = --arm_state->videocore_use_count; - local_entity_uc = --(*entity_uc); + --arm_state->videocore_use_count; + --(*entity_uc); if (!vchiq_videocore_wanted(state)) { if (vchiq_platform_use_suspend_timer() && -- GitLab From 5f251e986de05af8a177bfc632980cc64a4d3e7e Mon Sep 17 00:00:00 2001 From: Jerry Lin Date: Mon, 29 Jul 2019 10:35:44 +0800 Subject: [PATCH 1228/7155] staging: olpc_dcon: Remove TODO item All uses of old GPIO API have been converted to new API. This item can be removed from TODO file. Signed-off-by: Jerry Lin Link: https://lore.kernel.org/r/20190729023544.GA25930@compute1 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/TODO | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO index fe09efbc7f77..d8296f2ae872 100644 --- a/drivers/staging/olpc_dcon/TODO +++ b/drivers/staging/olpc_dcon/TODO @@ -8,10 +8,6 @@ TODO: internals, but isn't properly integrated, is not the correct solution. - see if vx855 gpio API can be made similar enough to cs5535 so we can share more code - - convert all uses of the old GPIO API from to the - GPIO descriptor API in and look up GPIO - lines from device tree, ACPI or board files, board files should - use - allow simultaneous XO-1 and XO-1.5 support Please send patches to Greg Kroah-Hartman and -- GitLab From a20eefaee64610541d125cd2c10fa25e278f0bee Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 13:22:14 +0200 Subject: [PATCH 1229/7155] staging: most: Use DEFINE_SPINLOCK() instead of struct spinlock For spinlocks the type spinlock_t should be used instead of "struct spinlock". Use DEFINE_SPINLOCK() and spare the run time initialization Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190704153803.12739-5-bigeasy@linutronix.de Link: https://lore.kernel.org/r/alpine.DEB.2.21.1907261319100.1791@nanos.tec.linutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/net/net.c | 3 +-- drivers/staging/most/video/video.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index aababdf2be12..26a31854c636 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -69,7 +69,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ -static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ +static DEFINE_SPINLOCK(list_lock); /* list_head, ch->linked = false, dev_hold */ static struct core_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) @@ -509,7 +509,6 @@ static int __init most_net_init(void) { int err; - spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); err = most_register_component(&comp); if (err) diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 6f6e98ab0550..250af9fb704d 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -54,7 +54,7 @@ struct comp_fh { }; static struct list_head video_devices = LIST_HEAD_INIT(video_devices); -static struct spinlock list_lock; +static DEFINE_SPINLOCK(list_lock); static inline bool data_ready(struct most_video_dev *mdev) { @@ -538,7 +538,6 @@ static int __init comp_init(void) { int err; - spin_lock_init(&list_lock); err = most_register_component(&comp); if (err) return err; -- GitLab From 9d6b3ee001cba29ad6d8d5f31953926504c67a1d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 25 Jul 2019 20:38:56 +0200 Subject: [PATCH 1230/7155] Staging: fbtft: Fix some typo. pdc8544 --> pcd8544 The driver is related to 'pcd8544'. However, 2 strings are about pdc8544 (c and d switched) Fix it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190725183856.17616-1-christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_pcd8544.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index ad49973ad594..08f8a4bb8772 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -157,10 +157,10 @@ static struct fbtft_display display = { .backlight = 1, }; -FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pdc8544", &display); +FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pcd8544", &display); MODULE_ALIAS("spi:" DRVNAME); -MODULE_ALIAS("spi:pdc8544"); +MODULE_ALIAS("spi:pcd8544"); MODULE_DESCRIPTION("FB driver for the PCD8544 LCD Controller"); MODULE_AUTHOR("Noralf Tronnes"); -- GitLab From c47f77eed0da6f829042a266a2f33ef31c250969 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Thu, 25 Jul 2019 19:09:22 +0200 Subject: [PATCH 1231/7155] staging: rtl8188eu: replace hal_EfusePgCheckAvailableAddr() Function hal_EfusePgCheckAvailableAddr() contains just a single if test. Remove the function and replace the call to it with the if test. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190725170922.16465-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 51c3dd6d7ffb..533ca1ddffb0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -763,17 +763,6 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u return ret; } -static bool -hal_EfusePgCheckAvailableAddr( - struct adapter *pAdapter, - u8 efuseType - ) -{ - if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) - return false; - return true; -} - static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) { memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); @@ -789,7 +778,7 @@ bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pD u16 startAddr = 0; u8 efuseType = EFUSE_WIFI; - if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) + if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); -- GitLab From 91e590851f51064a2f4cd11cf6ea01c21c4490bc Mon Sep 17 00:00:00 2001 From: Abhinav Jain Date: Fri, 26 Jul 2019 19:01:46 +0000 Subject: [PATCH 1232/7155] Staging: rtl8192e: fixed a function prototype definition issue Added the identifier name in the function prototype definition. Signed-off-by: Abhinav Jain Link: https://lore.kernel.org/r/20190726190146.10875-1-ubuntu@ip-172-31-129-142.ec2.internal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 096254e422b3..7a012881578f 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1940,7 +1940,7 @@ int rtllib_encrypt_fragment( int hdr_len); int rtllib_xmit(struct sk_buff *skb, struct net_device *dev); -void rtllib_txb_free(struct rtllib_txb *); +void rtllib_txb_free(struct rtllib_txb *txb); /* rtllib_rx.c */ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, -- GitLab From 36475456f3530491460453baae591b0bfd2e94be Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Jul 2019 13:48:03 +0100 Subject: [PATCH 1233/7155] staging: rtl8188eu: remove redundant assignment to rtstatus Variable rtstatus is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190726124803.11349-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 739e62dc60e3..47b1bf5a6143 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -222,7 +222,7 @@ bool rtl88eu_phy_rf_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; - bool rtstatus = true; + bool rtstatus; struct bb_reg_def *pphyreg; pphyreg = &hal_data->PHYRegDef[RF90_PATH_A]; -- GitLab From 8e7cb7352ec85e9e4fbbd7bfe6c5c5a6806f70e3 Mon Sep 17 00:00:00 2001 From: Bharath Vedartham Date: Thu, 25 Jul 2019 18:14:18 +0530 Subject: [PATCH 1234/7155] staging: kpc2000: Convert put_page() to put_user_page*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For pages that were retained via get_user_pages*(), release those pages via the new put_user_page*() routines, instead of via put_page(). This is part a tree-wide conversion, as described in commit fc1d8e7cca2d ("mm: introduce put_user_page*(), placeholder versions"). Cc: Ira Weiny Cc: John Hubbard Cc: Jérôme Glisse Cc: Greg Kroah-Hartman Cc: Matt Sickler Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org Reviewed-by: John Hubbard Signed-off-by: Bharath Vedartham Link: https://lore.kernel.org/r/1564058658-3551-1-git-send-email-linux.bhar@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/fileops.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index 48ca88bc6b0b..f15e29209d55 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -190,9 +190,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv, sg_free_table(&acd->sgt); err_dma_map_sg: err_alloc_sg_table: - for (i = 0 ; i < acd->page_count ; i++) { - put_page(acd->user_pages[i]); - } + put_user_pages(acd->user_pages, acd->page_count); err_get_user_pages: kfree(acd->user_pages); err_alloc_userpages: @@ -211,16 +209,13 @@ void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) BUG_ON(acd->ldev == NULL); BUG_ON(acd->ldev->pldev == NULL); - for (i = 0 ; i < acd->page_count ; i++) { - if (!PageReserved(acd->user_pages[i])) { - set_page_dirty(acd->user_pages[i]); - } - } - dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - for (i = 0 ; i < acd->page_count ; i++) { - put_page(acd->user_pages[i]); + for (i = 0; i < acd->page_count; i++) { + if (!PageReserved(acd->user_pages[i])) + put_user_pages_dirty(&acd->user_pages[i], 1); + else + put_user_page(acd->user_pages[i]); } sg_free_table(&acd->sgt); -- GitLab From f68dc00ee710ba56ee2112ea1184d7c5d3c40370 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:33 +0000 Subject: [PATCH 1235/7155] staging: wilc1000: remove inetaddr notifier Driver registers an inetaddr notifier to disable powersave while the ip address is being obtained which should be controlled only by cfg80211. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 65 -------------------------- 1 file changed, 65 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 8d8b7e4399f7..68129a0ba55f 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -504,12 +504,6 @@ static int wlan_initialize_threads(struct net_device *dev) return 0; } -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr); -static struct notifier_block g_dev_notifier = { - .notifier_call = dev_state_ev_handler -}; - static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) { int ret = 0; @@ -575,7 +569,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ret = -EIO; goto fail_fw_start; } - register_inetaddr_notifier(&g_dev_notifier); wl->initialized = true; return 0; @@ -781,7 +774,6 @@ static int wilc_mac_close(struct net_device *ndev) if (wl->open_ifcs == 0) { netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; - unregister_inetaddr_notifier(&g_dev_notifier); wilc_wlan_deinitialize(ndev); } @@ -864,63 +856,6 @@ static const struct net_device_ops wilc_netdev_ops = { .ndo_set_rx_mode = wilc_set_multicast_list, }; -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct in_ifaddr *dev_iface = ptr; - struct wilc_priv *priv; - struct host_if_drv *hif_drv; - struct net_device *dev; - struct wilc_vif *vif; - - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) - return NOTIFY_DONE; - - dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (dev->netdev_ops != &wilc_netdev_ops) - return NOTIFY_DONE; - - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) - return NOTIFY_DONE; - - vif = netdev_priv(dev); - priv = &vif->priv; - - hif_drv = (struct host_if_drv *)priv->hif_drv; - - switch (event) { - case NETDEV_UP: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 1; - vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); - } - - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, 1, 0); - - break; - - case NETDEV_DOWN: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 0; - vif->obtaining_ip = false; - wilc_set_power_mgmt(vif, 0, 0); - } - - wilc_resolve_disconnect_aberration(vif); - - break; - - default: - break; - } - - return NOTIFY_DONE; -} - void wilc_netdev_cleanup(struct wilc *wilc) { int i; -- GitLab From 98af3e7ed6831f001fee70584c08f39264002b1d Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:34 +0000 Subject: [PATCH 1236/7155] staging: wilc1000: remove ip timeout timer during_ip_timer is not required after removing the code that disables powersave while the ip is being obtained. Its handler clear_during_ip is also removed Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 2 -- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 16 ---------------- 2 files changed, 18 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 9345cabe3c93..9bd2d14ad610 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -684,8 +684,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_CONNECTED; vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(10000)); } else { hif_drv->hif_state = HOST_IF_IDLE; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 12fb4add05ec..81fe26a6b6db 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -70,15 +70,6 @@ struct wilc_p2p_mgmt_data { static const u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; static const u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; -#define WILC_IP_TIMEOUT_MS 15000 - -static void clear_during_ip(struct timer_list *t) -{ - struct wilc_vif *vif = from_timer(vif, t, during_ip_timer); - - vif->obtaining_ip = false; -} - static void cfg_scan_result(enum scan_event scan_event, struct wilc_rcvd_net_info *info, void *user_void) { @@ -1421,7 +1412,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); switch (type) { case NL80211_IFTYPE_STATION: @@ -1469,8 +1459,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, case NL80211_IFTYPE_P2P_GO: vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)); wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; @@ -1948,8 +1936,6 @@ int wilc_init_host_int(struct net_device *net) struct wilc_vif *vif = netdev_priv(net); struct wilc_priv *priv = &vif->priv; - timer_setup(&vif->during_ip_timer, clear_during_ip, 0); - priv->p2p_listen_state = false; mutex_init(&priv->scan_req_lock); @@ -1971,8 +1957,6 @@ void wilc_deinit_host_int(struct net_device *net) mutex_destroy(&priv->scan_req_lock); ret = wilc_deinit(vif); - del_timer_sync(&vif->during_ip_timer); - if (ret) netdev_err(net, "Error while deinitializing host interface\n"); } -- GitLab From 5a28d3fd407bf5225e7ab4eea1c5779a8a71c966 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:34 +0000 Subject: [PATCH 1237/7155] staging: wilc1000: remove unused members remove obtaining_ip from struct wilc_vif Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-4-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 9 ++------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 --- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 9bd2d14ad610..611f842d2836 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -248,7 +248,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, goto error; } - if (vif->obtaining_ip || vif->connecting) { + if (vif->connecting) { netdev_err(vif->ndev, "Don't do obss scan\n"); result = -EBUSY; goto error; @@ -682,8 +682,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, wilc_set_power_mgmt(vif, 0, 0); hif_drv->hif_state = HOST_IF_CONNECTED; - - vif->obtaining_ip = true; } else { hif_drv->hif_state = HOST_IF_IDLE; } @@ -707,7 +705,6 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) } if (hif_drv->conn_info.conn_result) { - vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, @@ -770,7 +767,6 @@ int wilc_disconnect(struct wilc_vif *vif) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); @@ -922,7 +918,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif, if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) return -EBUSY; - if (vif->obtaining_ip || vif->connecting) + if (vif->connecting) return -EBUSY; remain_on_chan_flag = true; @@ -1608,7 +1604,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) *hif_drv_handler = hif_drv; vif->hif_drv = hif_drv; - vif->obtaining_ip = false; if (wilc->clients_count == 0) mutex_init(&wilc->deinit_lock); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 81fe26a6b6db..deaf040f6623 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -167,7 +167,6 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { u16 reason = 0; - vif->obtaining_ip = false; priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; @@ -1411,7 +1410,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; - vif->obtaining_ip = false; switch (type) { case NL80211_IFTYPE_STATION: @@ -1458,7 +1456,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_GO: - vif->obtaining_ip = true; wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 1e74a08e7cf1..704e4d572695 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -203,7 +203,6 @@ struct wilc_vif { struct net_device *ndev; u8 mode; struct timer_list during_ip_timer; - bool obtaining_ip; struct timer_list periodic_rssi; struct rf_info periodic_stat; struct tcp_ack_filter ack_filter; -- GitLab From ded11ab1818440a9e5b35f2cff78a76148762dbd Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:35 +0000 Subject: [PATCH 1238/7155] staging: wilc1000: avoid overriding powersave state Don't override powersave state with respect to the open interfaces and let the firmware take care of when it's appropriate to do so Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-5-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 11 ++--------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 15 +-------------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 611f842d2836..16ff610c6a5b 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -679,8 +679,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, if (mac_status == WILC_MAC_STATUS_CONNECTED && conn_info->status == WLAN_STATUS_SUCCESS) { ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid); - wilc_set_power_mgmt(vif, 0, 0); - hif_drv->hif_state = HOST_IF_CONNECTED; } else { hif_drv->hif_state = HOST_IF_IDLE; @@ -704,14 +702,11 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) handle_scan_done(vif, SCAN_EVENT_ABORTED); } - if (hif_drv->conn_info.conn_result) { - wilc_set_power_mgmt(vif, 0, 0); - + if (hif_drv->conn_info.conn_result) hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, hif_drv->conn_info.arg); - } else { + else netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); - } eth_zero_addr(hif_drv->assoc_bssid); @@ -767,8 +762,6 @@ int wilc_disconnect(struct wilc_vif *vif) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - wilc_set_power_mgmt(vif, 0, 0); - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); if (result) { netdev_err(vif->ndev, "Failed to send disconnect\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index deaf040f6623..e2d9efed36b0 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1393,8 +1393,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, if (!priv->hif_drv) return -EIO; - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, enabled, timeout); + wilc_set_power_mgmt(vif, enabled, timeout); return 0; } @@ -1424,9 +1423,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, memset(priv->assoc_stainfo.sta_associated_bss, 0, WILC_MAX_NUM_STA * ETH_ALEN); - - wl->enable_ps = true; - wilc_set_power_mgmt(vif, 1, 0); break; case NL80211_IFTYPE_P2P_CLIENT: @@ -1437,12 +1433,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->iftype = WILC_CLIENT_MODE; wilc_set_operation_mode(vif, WILC_STATION_MODE); - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); break; case NL80211_IFTYPE_AP: - wl->enable_ps = false; dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_AP_MODE; @@ -1451,7 +1444,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), 0, vif->idx); wilc_set_operation_mode(vif, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); } break; @@ -1460,9 +1452,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_GO_MODE; - - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); break; default: @@ -1484,7 +1473,6 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, netdev_err(dev, "Error in setting channel\n"); wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); return wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, &settings->beacon); @@ -1835,7 +1823,6 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, *wilc = wl; wl->io_type = io_type; wl->hif_func = ops; - wl->enable_ps = false; wl->chip_ps_state = WILC_CHIP_WAKEDUP; INIT_LIST_HEAD(&wl->txq_head.list); INIT_LIST_HEAD(&wl->rxq_head.list); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 704e4d572695..7e7ce9471f67 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -261,7 +261,6 @@ struct wilc { struct device *dev; bool suspend_event; - bool enable_ps; int clients_count; struct workqueue_struct *hif_workqueue; enum chip_ps_states chip_ps_state; -- GitLab From 7e0cf3e3bfe94d030c3d3d79f8af8f0e365fdf1c Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:36 +0000 Subject: [PATCH 1239/7155] staging: wilc1000: apply power management regardless of open interfaces Don't ignore power management if 2 interfaces are open Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-6-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 16ff610c6a5b..75a6931aa147 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -2010,9 +2010,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) int result; s8 power_mode; - if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) - return 0; - if (enabled) power_mode = WILC_FW_MIN_FAST_PS; else -- GitLab From 25f12201a4ba67451a8be71db83dd734b2f62b30 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:37 +0000 Subject: [PATCH 1240/7155] staging: wilc1000: remove manual sleep mode manual sleep mode was used to put the wilc1000 chip in sleep while in disconnected state. This is taken care of in the firmware Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-7-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 4 ---- drivers/staging/wilc1000/wilc_sdio.c | 4 +--- drivers/staging/wilc1000/wilc_wlan.c | 14 -------------- drivers/staging/wilc1000/wilc_wlan.h | 2 -- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 75a6931aa147..f8646ea3b0c4 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -1056,13 +1056,9 @@ static void handle_scan_timer(struct work_struct *work) static void handle_scan_complete(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc *wilc = msg->vif->wilc; del_timer(&msg->vif->hif_drv->scan_timer); - if (!wilc_wlan_get_num_conn_ifcs(wilc)) - wilc_chip_sleep_manually(wilc); - handle_scan_done(msg->vif, SCAN_EVENT_DONE); kfree(msg); diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 4c1c81fed11f..2f9aa36e0114 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -193,9 +193,7 @@ static int wilc_sdio_suspend(struct device *dev) dev_info(dev, "sdio suspend\n"); chip_wakeup(wilc); - if (!wilc->suspend_event) { - wilc_chip_sleep_manually(wilc); - } else { + if (wilc->suspend_event) { host_sleep_notify(wilc); chip_allow_sleep(wilc); } diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 8ca0a7a4fa3f..d4ca6467485c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -455,20 +455,6 @@ void chip_wakeup(struct wilc *wilc) } EXPORT_SYMBOL_GPL(chip_wakeup); -void wilc_chip_sleep_manually(struct wilc *wilc) -{ - if (wilc->chip_ps_state != WILC_CHIP_WAKEDUP) - return; - acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); - - chip_allow_sleep(wilc); - wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1); - - wilc->chip_ps_state = WILC_CHIP_SLEEPING_MANUAL; - release_bus(wilc, WILC_BUS_RELEASE_ONLY); -} -EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); - void host_wakeup_notify(struct wilc *wilc) { acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index b70014142686..802f11807659 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -293,8 +293,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*func)(void *, int)); -void wilc_chip_sleep_manually(struct wilc *wilc); - void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc); netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); -- GitLab From 3455db0e056516f576c3d4a8baf320d814a6e202 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:43 +0200 Subject: [PATCH 1241/7155] staging: rtl8188eu: add spaces around '+' in usb_halinit.c Add spaces around '+' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 76 ++++++++++----------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 994392ac249b..c2e1b000cf89 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -183,7 +183,7 @@ static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy) usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - usb_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy); } static void _InitPageBoundary(struct adapter *Adapter) @@ -504,7 +504,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) switch (haldata->UsbRxAggMode) { case USB_RX_AGG_DMA: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, haldata->UsbRxAggPageTimeout); + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout); break; case USB_RX_AGG_USB: usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); @@ -512,7 +512,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) break; case USB_RX_AGG_MIX: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout); break; @@ -569,9 +569,9 @@ static void _InitBeaconParameters(struct adapter *Adapter) haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL); haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE); - haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL+2); - haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT+2); - haldata->RegCR_1 = usb_read8(Adapter, REG_CR+1); + haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL + 2); + haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT + 2); + haldata->RegCR_1 = usb_read8(Adapter, REG_CR + 1); } static void _BeaconFunctionEnable(struct adapter *Adapter, @@ -579,7 +579,7 @@ static void _BeaconFunctionEnable(struct adapter *Adapter, { usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1))); - usb_write8(Adapter, REG_RD_CTRL+1, 0x6F); + usb_write8(Adapter, REG_RD_CTRL + 1, 0x6F); } /* Set CCK and OFDM Block "ON" */ @@ -770,7 +770,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) value8 = usb_read8(Adapter, REG_TX_RPT_CTRL); usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0))); /* Set MAX RPT MACID */ - usb_write8(Adapter, REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ /* Tx RPT Timer. Unit: 32us */ usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0); @@ -827,10 +827,10 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) pwrctrlpriv->rf_pwrstate = rf_on; /* enable Tx report. */ - usb_write8(Adapter, REG_FWHW_TXQ_CTRL+1, 0x0F); + usb_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F); /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */ - usb_write8(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ + usb_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ /* tynli_test_tx_report. */ usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0); @@ -894,9 +894,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_MCUFWDL); if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */ /* Reset MCU 0x2[10]=0. */ - val8 = usb_read8(Adapter, REG_SYS_FUNC_EN+1); + val8 = usb_read8(Adapter, REG_SYS_FUNC_EN + 1); val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */ - usb_write8(Adapter, REG_SYS_FUNC_EN+1, val8); + usb_write8(Adapter, REG_SYS_FUNC_EN + 1, val8); } /* reset MCU ready status */ @@ -912,10 +912,10 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) Rtl8188E_NIC_DISABLE_FLOW); /* Reset MCU IO Wrapper */ - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT(3)))); - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, val8 | BIT(3)); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, (val8&(~BIT(3)))); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); /* YJ,test add, 111207. For Power Consumption. */ val8 = usb_read8(Adapter, GPIO_IN); @@ -924,8 +924,8 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); - val8 = usb_read8(Adapter, REG_GPIO_IO_SEL+1); - usb_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */ + val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); + usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8|0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; @@ -1103,11 +1103,11 @@ static void ResumeTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT(6)); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6)); haldata->RegFwHwTxQCtrl |= BIT(6); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff); haldata->RegReg542 |= BIT(0); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); } static void StopTxBeacon(struct adapter *adapt) @@ -1117,11 +1117,11 @@ static void StopTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); haldata->RegFwHwTxQCtrl &= (~BIT(6)); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64); haldata->RegReg542 &= ~(BIT(0)); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */ } @@ -1191,7 +1191,7 @@ static void hw_var_set_macaddr(struct adapter *Adapter, u8 variable, u8 *val) reg_macid = REG_MACID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_macid+idx), val[idx]); + usb_write8(Adapter, (reg_macid + idx), val[idx]); } static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) @@ -1202,7 +1202,7 @@ static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) reg_bssid = REG_BSSID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_bssid+idx), val[idx]); + usb_write8(Adapter, (reg_bssid + idx), val[idx]); } static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) @@ -1274,8 +1274,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) BrateCfg |= 0x01; /* default enable 1M ACK rate */ /* Set RRSR rate table. */ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff); - usb_write8(Adapter, REG_RRSR+1, (BrateCfg >> 8) & 0xff); - usb_write8(Adapter, REG_RRSR+2, usb_read8(Adapter, REG_RRSR+2)&0xf0); + usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); + usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2)&0xf0); /* Set RTS initial rate */ while (BrateCfg > 0x1) { @@ -1307,7 +1307,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); - usb_write32(Adapter, REG_TSFTR+4, tsf>>32); + usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); @@ -1432,10 +1432,10 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) case HW_VAR_RESP_SIFS: /* RESP_SIFS for CCK */ usb_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */ - usb_write8(Adapter, REG_R2T_SIFS+1, val[1]); /* SIFS_R2T_CCK(0x08) */ + usb_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */ /* RESP_SIFS for OFDM */ usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */ - usb_write8(Adapter, REG_T2T_SIFS+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ + usb_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ break; case HW_VAR_ACK_PREAMBLE: { @@ -1446,7 +1446,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if (bShortPreamble) regTmp |= 0x80; - usb_write8(Adapter, REG_RRSR+2, regTmp); + usb_write8(Adapter, REG_RRSR + 2, regTmp); } break; case HW_VAR_SEC_CFG: @@ -1484,7 +1484,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) else ulContent = 0; /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT*ucIndex+i; + ulCommand = CAM_CONTENT_COUNT*ucIndex + i; ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE; /* write content 0 is equall to mark invalid */ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */ @@ -1595,7 +1595,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if ((pRegToSet[index] & 0x0f) > FactorToSet) pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); - usb_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]); + usb_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]); } } } @@ -1706,8 +1706,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 maxMacid = *val; - DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid+1); - usb_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1); + DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1); + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1); } break; case HW_VAR_H2C_MEDIA_STATUS_RPT: @@ -1715,7 +1715,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */ - usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT(0)); + usb_write8(Adapter, REG_TDECTRL + 2, usb_read8(Adapter, REG_TDECTRL + 2) | BIT(0)); break; default: break; @@ -1733,7 +1733,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ - val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; + val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL + 2)) ? true : false; break; case HW_VAR_FWLPS_RF_ON: { -- GitLab From 6d7ff7361137cced8aaf7de568ad2fb8c00ec532 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:44 +0200 Subject: [PATCH 1242/7155] staging: rtl8188eu: add spaces around '&' in usb_halinit.c Add spaces around '&' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 38 ++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index c2e1b000cf89..fe68af7eaf85 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -633,7 +633,7 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8); rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on; } else { /* rf on/off */ - usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT(3))); + usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3))); val8 = usb_read8(adapt, REG_GPIO_IO_SEL); DBG_88E("GPIO_IN=%02x\n", val8); rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; @@ -880,7 +880,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ val8 = usb_read8(Adapter, REG_TX_RPT_CTRL); - usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT(1))); + usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1))); /* stop rx */ usb_write8(Adapter, REG_CR, 0x0); @@ -905,7 +905,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* YJ,add,111212 */ /* Disable 32k */ val8 = usb_read8(Adapter, REG_32K_CTRL); - usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT(0))); + usb_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0))); /* Card disable power action flow */ rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK, @@ -913,7 +913,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* Reset MCU IO Wrapper */ val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); - usb_write8(Adapter, REG_RSV_CTRL + 1, (val8&(~BIT(3)))); + usb_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3)))); val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); @@ -1135,7 +1135,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4)); /* set net_type */ - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= mode; usb_write8(Adapter, MSR, val8); @@ -1214,7 +1214,7 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) if (*((u8 *)val)) usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); else - usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); + usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); } void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) @@ -1228,7 +1228,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 val8; - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= *((u8 *)val); usb_write8(Adapter, MSR, val8); } @@ -1275,7 +1275,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* Set RRSR rate table. */ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff); usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); - usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2)&0xf0); + usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2) & 0xf0); /* Set RTS initial rate */ while (BrateCfg > 0x1) { @@ -1300,11 +1300,11 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); /* disable related TSF function */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); @@ -1312,7 +1312,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) ResumeTxBeacon(Adapter); } break; @@ -1357,16 +1357,16 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; if ((is_client_associated_to_ap(Adapter)) || - ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)) { + ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { /* enable to rx data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); - } else if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); + } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); } usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); @@ -1394,7 +1394,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) } else if (type == 2) { /* sta add event call back */ /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) RetryLimit = 0x7; @@ -1683,7 +1683,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* RX DMA stop */ usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN)); do { - if (!(usb_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE)) + if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; } while (trycnt--); if (trycnt == 0) @@ -1764,7 +1764,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) *val = Adapter->HalData->bMacPwrCtrlOn; break; case HW_VAR_CHK_HI_QUEUE_EMPTY: - *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false; + *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false; break; default: break; @@ -1925,7 +1925,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) mask &= rate_bitmap; - init_rate = get_highest_rate_idx(mask)&0x3f; + init_rate = get_highest_rate_idx(mask) & 0x3f; ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate); -- GitLab From fe6c0d20bb911b9c31ee5d724428551b3aa2f7a9 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:45 +0200 Subject: [PATCH 1243/7155] staging: rtl8188eu: add spaces around '|' in usb_halinit.c Add spaces around '|' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index fe68af7eaf85..9fa34c5c11c4 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -925,7 +925,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); - usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8|0x0F);/* Reg0x43 */ + usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; @@ -1176,7 +1176,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) /* enable BCN0 Function for if1 */ /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ - usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | BIT(1))); + usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1))); /* dis BCN1 ATIM WND if if2 is station */ usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0)); @@ -1318,7 +1318,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_CHECK_BSSID: if (*((u8 *)val)) { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); } else { u32 val32; @@ -1369,7 +1369,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); } - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN); } break; case HW_VAR_MLME_JOIN: @@ -1382,7 +1382,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable to rx data frame.Accept all data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48; @@ -1396,7 +1396,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable update TSF */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) RetryLimit = 0x7; } usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); @@ -1485,7 +1485,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) ulContent = 0; /* polling bit, and No Write enable, and address */ ulCommand = CAM_CONTENT_COUNT*ucIndex + i; - ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE; + ulCommand = ulCommand | CAM_POLLINIG | + CAM_WRITE; /* write content 0 is equall to mark invalid */ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */ usb_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */ @@ -1681,7 +1682,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if (!pwrpriv->bkeepfwalive) { /* RX DMA stop */ - usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN)); + usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN)); do { if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; -- GitLab From 8f4686cb7db0839c9d42e3b8e813bf55a9161d29 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:46 +0200 Subject: [PATCH 1244/7155] staging: rtl8188eu: add spaces around '<<' and '>>' in usb_halinit.c Add spaces around '<<' and '>>' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-4-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 9fa34c5c11c4..40162f111195 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -923,7 +923,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */ val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); - usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); + usb_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4)); val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ @@ -1307,7 +1307,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); - usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); + usb_write32(Adapter, REG_TSFTR + 4, tsf >> 32); /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); @@ -1442,7 +1442,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) u8 regTmp; u8 bShortPreamble = *((bool *)val); /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ - regTmp = (haldata->nCur40MhzPrimeSC)<<5; + regTmp = (haldata->nCur40MhzPrimeSC) << 5; if (bShortPreamble) regTmp |= 0x80; @@ -1480,7 +1480,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) for (i = 0; i < CAM_CONTENT_COUNT; i++) { /* filled id in CAM config 2 byte */ if (i == 0) - ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2); + ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2); else ulContent = 0; /* polling bit, and No Write enable, and address */ @@ -1590,8 +1590,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) FactorToSet = 0xf; for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet<<4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet<<4); + if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) + pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4); if ((pRegToSet[index] & 0x0f) > FactorToSet) pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); -- GitLab From 1f5bfba56f90afe8e158b655ecdd6eac78205dae Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:47 +0200 Subject: [PATCH 1245/7155] staging: rtl8188eu: add spaces around '-' and '*' in usb_halinit.c Add spaces around '-' and '*' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-5-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 40162f111195..0f54fde2f47b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -190,7 +190,7 @@ static void _InitPageBoundary(struct adapter *Adapter) { /* RX Page Boundary */ /* */ - u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E-1; + u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1; usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); } @@ -1298,7 +1298,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ + tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); @@ -1484,7 +1484,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) else ulContent = 0; /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT*ucIndex + i; + ulCommand = CAM_CONTENT_COUNT * ucIndex + i; ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; /* write content 0 is equall to mark invalid */ -- GitLab From 2c0e81ec21db971eb9eb6adf987f9f15aec75968 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:48 +0200 Subject: [PATCH 1246/7155] staging: rtl8188eu: cleanup comparsion to NULL in usb_halinit.c Use if(!x) instead of if(x == NULL). Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-6-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 0f54fde2f47b..16a57b31a439 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1889,7 +1889,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) if (mac_id >= NUM_STA) /* CAM_SIZE */ return; psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (psta == NULL) + if (!psta) return; switch (mac_id) { case 0:/* for infra mode */ -- GitLab From d9e5ebac18a122f53ee87671f62d42b0d9e9a491 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Mon, 29 Jul 2019 10:37:30 -0400 Subject: [PATCH 1247/7155] Documentation: gpio: fix function links in the HTML docs The shorthand [_data] and [devm_] cause the HTML documentation to not link to the function documentation properly. This expands the references to the complete function names with the exception of devm_gpiochip_remove() which was dropped by commit 48207d7595d2 ("gpio: drop devm_gpiochip_remove()"). Signed-off-by: Jeremy Cline Signed-off-by: Bartosz Golaszewski --- Documentation/driver-api/gpio/driver.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 921c71a3d683..906af220b164 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -69,9 +69,9 @@ driver code: The code implementing a gpio_chip should support multiple instances of the controller, preferably using the driver model. That code will configure each -gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``. -Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()`` -when it is unavoidable. +gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or +devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use +gpiochip_remove() when it is unavoidable. Often a gpio_chip is part of an instance-specific structure with states not exposed by the GPIO interfaces, such as addressing, power management, and more. @@ -418,11 +418,11 @@ symbol: If there is a need to exclude certain GPIO lines from the IRQ domain handled by these helpers, we can set .irq.need_valid_mask of the gpiochip before -``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as -many bits set as there are GPIO lines in the chip, each bit representing line -0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask -must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested() -is called. +devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an +.irq.valid_mask with as many bits set as there are GPIO lines in the chip, each +bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits +from this mask. The mask must be filled in before gpiochip_irqchip_add() or +gpiochip_irqchip_add_nested() is called. To use the helpers please keep the following in mind: -- GitLab From c7a895fc5dd58b9e9378f420b1bbecf6737aeb55 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 18 Jul 2019 23:43:26 +0900 Subject: [PATCH 1248/7155] arm64: dts: renesas: r8a7795: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 154 +++++++++++------------ 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 1745ac4b307e..6cd5fe4c1da6 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -2731,6 +2731,83 @@ resets = <&cpg 820>; }; + vspbc: vsp@fe920000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe920000 0 0x8000>; + interrupts = ; + clocks = <&cpg CPG_MOD 624>; + power-domains = <&sysc R8A7795_PD_A3VP>; + resets = <&cpg 624>; + + renesas,fcp = <&fcpvb1>; + }; + + vspbd: vsp@fe960000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe960000 0 0x8000>; + interrupts = ; + clocks = <&cpg CPG_MOD 626>; + power-domains = <&sysc R8A7795_PD_A3VP>; + resets = <&cpg 626>; + + renesas,fcp = <&fcpvb0>; + }; + + vspd0: vsp@fea20000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea20000 0 0x5000>; + interrupts = ; + clocks = <&cpg CPG_MOD 623>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 623>; + + renesas,fcp = <&fcpvd0>; + }; + + vspd1: vsp@fea28000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea28000 0 0x5000>; + interrupts = ; + clocks = <&cpg CPG_MOD 622>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 622>; + + renesas,fcp = <&fcpvd1>; + }; + + vspd2: vsp@fea30000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea30000 0 0x5000>; + interrupts = ; + clocks = <&cpg CPG_MOD 621>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 621>; + + renesas,fcp = <&fcpvd2>; + }; + + vspi0: vsp@fe9a0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9a0000 0 0x8000>; + interrupts = ; + clocks = <&cpg CPG_MOD 631>; + power-domains = <&sysc R8A7795_PD_A3VP>; + resets = <&cpg 631>; + + renesas,fcp = <&fcpvi0>; + }; + + vspi1: vsp@fe9b0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9b0000 0 0x8000>; + interrupts = ; + clocks = <&cpg CPG_MOD 630>; + power-domains = <&sysc R8A7795_PD_A3VP>; + resets = <&cpg 630>; + + renesas,fcp = <&fcpvi1>; + }; + fdp1@fe940000 { compatible = "renesas,fdp1"; reg = <0 0xfe940000 0 0x2400>; @@ -2832,83 +2909,6 @@ iommus = <&ipmmu_vi1 10>; }; - vspbd: vsp@fe960000 { - compatible = "renesas,vsp2"; - reg = <0 0xfe960000 0 0x8000>; - interrupts = ; - clocks = <&cpg CPG_MOD 626>; - power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 626>; - - renesas,fcp = <&fcpvb0>; - }; - - vspbc: vsp@fe920000 { - compatible = "renesas,vsp2"; - reg = <0 0xfe920000 0 0x8000>; - interrupts = ; - clocks = <&cpg CPG_MOD 624>; - power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 624>; - - renesas,fcp = <&fcpvb1>; - }; - - vspd0: vsp@fea20000 { - compatible = "renesas,vsp2"; - reg = <0 0xfea20000 0 0x5000>; - interrupts = ; - clocks = <&cpg CPG_MOD 623>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 623>; - - renesas,fcp = <&fcpvd0>; - }; - - vspd1: vsp@fea28000 { - compatible = "renesas,vsp2"; - reg = <0 0xfea28000 0 0x5000>; - interrupts = ; - clocks = <&cpg CPG_MOD 622>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 622>; - - renesas,fcp = <&fcpvd1>; - }; - - vspd2: vsp@fea30000 { - compatible = "renesas,vsp2"; - reg = <0 0xfea30000 0 0x5000>; - interrupts = ; - clocks = <&cpg CPG_MOD 621>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 621>; - - renesas,fcp = <&fcpvd2>; - }; - - vspi0: vsp@fe9a0000 { - compatible = "renesas,vsp2"; - reg = <0 0xfe9a0000 0 0x8000>; - interrupts = ; - clocks = <&cpg CPG_MOD 631>; - power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 631>; - - renesas,fcp = <&fcpvi0>; - }; - - vspi1: vsp@fe9b0000 { - compatible = "renesas,vsp2"; - reg = <0 0xfe9b0000 0 0x8000>; - interrupts = ; - clocks = <&cpg CPG_MOD 630>; - power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 630>; - - renesas,fcp = <&fcpvi1>; - }; - csi20: csi2@fea80000 { compatible = "renesas,r8a7795-csi2"; reg = <0 0xfea80000 0 0x10000>; -- GitLab From 3bb350f2249277abedbc9b6cc1de3a715e981c3b Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 18 Jul 2019 23:43:53 +0900 Subject: [PATCH 1249/7155] arm64: dts: renesas: r8a7795-es1: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 223 ++++++++++--------- 1 file changed, 112 insertions(+), 111 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi index 40d10daca852..e4650ae5b75a 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi @@ -7,22 +7,75 @@ #include "r8a7795.dtsi" -&soc { - xhci1: usb@ee040000 { - compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci"; - reg = <0 0xee040000 0 0xc00>; - interrupts = ; - clocks = <&cpg CPG_MOD 327>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 327>; - status = "disabled"; - }; +&audma0 { + iommus = <&ipmmu_mp1 0>, <&ipmmu_mp1 1>, + <&ipmmu_mp1 2>, <&ipmmu_mp1 3>, + <&ipmmu_mp1 4>, <&ipmmu_mp1 5>, + <&ipmmu_mp1 6>, <&ipmmu_mp1 7>, + <&ipmmu_mp1 8>, <&ipmmu_mp1 9>, + <&ipmmu_mp1 10>, <&ipmmu_mp1 11>, + <&ipmmu_mp1 12>, <&ipmmu_mp1 13>, + <&ipmmu_mp1 14>, <&ipmmu_mp1 15>; +}; - /delete-node/ mmu@febe0000; - /delete-node/ mmu@fe980000; - /delete-node/ mmu@fd950000; - /delete-node/ mmu@fd960000; - /delete-node/ mmu@fd970000; +&audma1 { + iommus = <&ipmmu_mp1 16>, <&ipmmu_mp1 17>, + <&ipmmu_mp1 18>, <&ipmmu_mp1 19>, + <&ipmmu_mp1 20>, <&ipmmu_mp1 21>, + <&ipmmu_mp1 22>, <&ipmmu_mp1 23>, + <&ipmmu_mp1 24>, <&ipmmu_mp1 25>, + <&ipmmu_mp1 26>, <&ipmmu_mp1 27>, + <&ipmmu_mp1 28>, <&ipmmu_mp1 29>, + <&ipmmu_mp1 30>, <&ipmmu_mp1 31>; +}; + +&du { + vsps = <&vspd0 &vspd1 &vspd2 &vspd3>; +}; + +&fcpvb1 { + iommus = <&ipmmu_vp0 7>; +}; + +&fcpf1 { + iommus = <&ipmmu_vp0 1>; +}; + +&fcpvi1 { + iommus = <&ipmmu_vp0 9>; +}; + +&fcpvd2 { + iommus = <&ipmmu_vi0 10>; +}; + +&gpio1 { + gpio-ranges = <&pfc 0 32 28>; +}; + +&ipmmu_vi0 { + renesas,ipmmu-main = <&ipmmu_mm 11>; +}; + +&ipmmu_vp0 { + renesas,ipmmu-main = <&ipmmu_mm 12>; +}; + +&ipmmu_vc0 { + renesas,ipmmu-main = <&ipmmu_mm 9>; +}; + +&ipmmu_vc1 { + renesas,ipmmu-main = <&ipmmu_mm 10>; +}; + +&ipmmu_rt { + renesas,ipmmu-main = <&ipmmu_mm 7>; +}; + +&soc { + /delete-node/ dma-controller@e6460000; + /delete-node/ dma-controller@e6470000; ipmmu_mp1: mmu@ec680000 { compatible = "renesas,ipmmu-r8a7795"; @@ -40,13 +93,37 @@ #iommu-cells = <1>; }; - /delete-node/ usb-phy@ee0e0200; - /delete-node/ usb@ee0e0100; - /delete-node/ usb@ee0e0000; + /delete-node/ mmu@fd950000; + /delete-node/ mmu@fd960000; + /delete-node/ mmu@fd970000; + /delete-node/ mmu@febe0000; + /delete-node/ mmu@fe980000; + + xhci1: usb@ee040000 { + compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci"; + reg = <0 0xee040000 0 0xc00>; + interrupts = ; + clocks = <&cpg CPG_MOD 327>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 327>; + status = "disabled"; + }; + /delete-node/ usb@e659c000; + /delete-node/ usb@ee0e0000; + /delete-node/ usb@ee0e0100; - /delete-node/ dma-controller@e6460000; - /delete-node/ dma-controller@e6470000; + /delete-node/ usb-phy@ee0e0200; + + fdp1@fe948000 { + compatible = "renesas,fdp1"; + reg = <0 0xfe948000 0 0x2400>; + interrupts = ; + clocks = <&cpg CPG_MOD 117>; + power-domains = <&sysc R8A7795_PD_A3VP>; + resets = <&cpg 117>; + renesas,fcp = <&fcpf2>; + }; fcpf2: fcp@fe952000 { compatible = "renesas,fcpf"; @@ -57,15 +134,13 @@ iommus = <&ipmmu_vp0 2>; }; - vspi2: vsp@fe9c0000 { - compatible = "renesas,vsp2"; - reg = <0 0xfe9c0000 0 0x8000>; - interrupts = ; - clocks = <&cpg CPG_MOD 629>; - power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 629>; - - renesas,fcp = <&fcpvi2>; + fcpvd3: fcp@fea3f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea3f000 0 0x200>; + clocks = <&cpg CPG_MOD 600>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 600>; + iommus = <&ipmmu_vi0 11>; }; fcpvi2: fcp@fe9cf000 { @@ -88,23 +163,15 @@ renesas,fcp = <&fcpvd3>; }; - fcpvd3: fcp@fea3f000 { - compatible = "renesas,fcpv"; - reg = <0 0xfea3f000 0 0x200>; - clocks = <&cpg CPG_MOD 600>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 600>; - iommus = <&ipmmu_vi0 11>; - }; - - fdp1@fe948000 { - compatible = "renesas,fdp1"; - reg = <0 0xfe948000 0 0x2400>; - interrupts = ; - clocks = <&cpg CPG_MOD 117>; + vspi2: vsp@fe9c0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9c0000 0 0x8000>; + interrupts = ; + clocks = <&cpg CPG_MOD 629>; power-domains = <&sysc R8A7795_PD_A3VP>; - resets = <&cpg 117>; - renesas,fcp = <&fcpf2>; + resets = <&cpg 629>; + + renesas,fcp = <&fcpvi2>; }; csi21: csi2@fea90000 { @@ -163,72 +230,6 @@ }; }; -&gpio1 { - gpio-ranges = <&pfc 0 32 28>; -}; - -&ipmmu_vi0 { - renesas,ipmmu-main = <&ipmmu_mm 11>; -}; - -&ipmmu_vp0 { - renesas,ipmmu-main = <&ipmmu_mm 12>; -}; - -&ipmmu_vc0 { - renesas,ipmmu-main = <&ipmmu_mm 9>; -}; - -&ipmmu_vc1 { - renesas,ipmmu-main = <&ipmmu_mm 10>; -}; - -&ipmmu_rt { - renesas,ipmmu-main = <&ipmmu_mm 7>; -}; - -&audma0 { - iommus = <&ipmmu_mp1 0>, <&ipmmu_mp1 1>, - <&ipmmu_mp1 2>, <&ipmmu_mp1 3>, - <&ipmmu_mp1 4>, <&ipmmu_mp1 5>, - <&ipmmu_mp1 6>, <&ipmmu_mp1 7>, - <&ipmmu_mp1 8>, <&ipmmu_mp1 9>, - <&ipmmu_mp1 10>, <&ipmmu_mp1 11>, - <&ipmmu_mp1 12>, <&ipmmu_mp1 13>, - <&ipmmu_mp1 14>, <&ipmmu_mp1 15>; -}; - -&audma1 { - iommus = <&ipmmu_mp1 16>, <&ipmmu_mp1 17>, - <&ipmmu_mp1 18>, <&ipmmu_mp1 19>, - <&ipmmu_mp1 20>, <&ipmmu_mp1 21>, - <&ipmmu_mp1 22>, <&ipmmu_mp1 23>, - <&ipmmu_mp1 24>, <&ipmmu_mp1 25>, - <&ipmmu_mp1 26>, <&ipmmu_mp1 27>, - <&ipmmu_mp1 28>, <&ipmmu_mp1 29>, - <&ipmmu_mp1 30>, <&ipmmu_mp1 31>; -}; - -&fcpvb1 { - iommus = <&ipmmu_vp0 7>; -}; - -&fcpf1 { - iommus = <&ipmmu_vp0 1>; -}; - -&fcpvi1 { - iommus = <&ipmmu_vp0 9>; -}; - -&fcpvd2 { - iommus = <&ipmmu_vi0 10>; -}; - -&du { - vsps = <&vspd0 &vspd1 &vspd2 &vspd3>; -}; - &vin0 { ports { port@1 { -- GitLab From da3db1c84629b6a4e7b780dfdfb6ec2112ad0d56 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 18 Jul 2019 23:45:37 +0900 Subject: [PATCH 1250/7155] arm64: dts: renesas: r8a77965: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77965.dtsi | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 131f895ab778..09e4f52db764 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2255,14 +2255,6 @@ renesas,fcp = <&fcpvb0>; }; - fcpvb0: fcp@fe96f000 { - compatible = "renesas,fcpv"; - reg = <0 0xfe96f000 0 0x200>; - clocks = <&cpg CPG_MOD 607>; - power-domains = <&sysc R8A77965_PD_A3VP>; - resets = <&cpg 607>; - }; - vspi0: vsp@fe9a0000 { compatible = "renesas,vsp2"; reg = <0 0xfe9a0000 0 0x8000>; @@ -2274,14 +2266,6 @@ renesas,fcp = <&fcpvi0>; }; - fcpvi0: fcp@fe9af000 { - compatible = "renesas,fcpv"; - reg = <0 0xfe9af000 0 0x200>; - clocks = <&cpg CPG_MOD 611>; - power-domains = <&sysc R8A77965_PD_A3VP>; - resets = <&cpg 611>; - }; - vspd0: vsp@fea20000 { compatible = "renesas,vsp2"; reg = <0 0xfea20000 0 0x5000>; @@ -2293,14 +2277,6 @@ renesas,fcp = <&fcpvd0>; }; - fcpvd0: fcp@fea27000 { - compatible = "renesas,fcpv"; - reg = <0 0xfea27000 0 0x200>; - clocks = <&cpg CPG_MOD 603>; - power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 603>; - }; - vspd1: vsp@fea28000 { compatible = "renesas,vsp2"; reg = <0 0xfea28000 0 0x5000>; @@ -2312,6 +2288,22 @@ renesas,fcp = <&fcpvd1>; }; + fcpvb0: fcp@fe96f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe96f000 0 0x200>; + clocks = <&cpg CPG_MOD 607>; + power-domains = <&sysc R8A77965_PD_A3VP>; + resets = <&cpg 607>; + }; + + fcpvd0: fcp@fea27000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea27000 0 0x200>; + clocks = <&cpg CPG_MOD 603>; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 603>; + }; + fcpvd1: fcp@fea2f000 { compatible = "renesas,fcpv"; reg = <0 0xfea2f000 0 0x200>; @@ -2320,6 +2312,14 @@ resets = <&cpg 602>; }; + fcpvi0: fcp@fe9af000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9af000 0 0x200>; + clocks = <&cpg CPG_MOD 611>; + power-domains = <&sysc R8A77965_PD_A3VP>; + resets = <&cpg 611>; + }; + csi20: csi2@fea80000 { compatible = "renesas,r8a77965-csi2"; reg = <0 0xfea80000 0 0x10000>; -- GitLab From 34e776ea894a063670d61d2e6f16795d84a3ccc1 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Tue, 23 Jul 2019 02:22:21 +0900 Subject: [PATCH 1251/7155] arm64: dts: renesas: r8a7795-es1: salvator-x: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../dts/renesas/r8a7795-es1-salvator-x.dts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts index c1a56eab7b24..c72968623e94 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts @@ -52,12 +52,6 @@ status = "okay"; }; -&sound_card { - dais = <&rsnd_port0 /* ak4613 */ - &rsnd_port1 /* HDMI0 */ - &rsnd_port2>; /* HDMI1 */ -}; - &hdmi0 { status = "okay"; @@ -108,6 +102,13 @@ status = "okay"; }; +&pfc { + usb2_pins: usb2 { + groups = "usb2"; + function = "usb2"; + }; +}; + &rcar_sound { ports { /* rsnd_port0 is on salvator-common */ @@ -138,17 +139,16 @@ }; }; -&pfc { - usb2_pins: usb2 { - groups = "usb2"; - function = "usb2"; - }; -}; - &sata { status = "okay"; }; +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1 /* HDMI0 */ + &rsnd_port2>; /* HDMI1 */ +}; + &usb2_phy2 { pinctrl-0 = <&usb2_pins>; pinctrl-names = "default"; -- GitLab From 480160ee3c05e2729a048139dc37af98739b3ddf Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Tue, 23 Jul 2019 02:22:52 +0900 Subject: [PATCH 1252/7155] arm64: dts: renesas: r8a7795: salvator-x: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a7795-salvator-x.dts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index d2d48b33b37f..72874f675359 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -52,12 +52,6 @@ status = "okay"; }; -&sound_card { - dais = <&rsnd_port0 /* ak4613 */ - &rsnd_port1 /* HDMI0 */ - &rsnd_port2>; /* HDMI1 */ -}; - &hdmi0 { status = "okay"; @@ -108,6 +102,13 @@ status = "okay"; }; +&pfc { + usb2_pins: usb2 { + groups = "usb2"; + function = "usb2"; + }; +}; + &rcar_sound { ports { /* rsnd_port0 is on salvator-common */ @@ -138,17 +139,16 @@ }; }; -&pfc { - usb2_pins: usb2 { - groups = "usb2"; - function = "usb2"; - }; -}; - &sata { status = "okay"; }; +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1 /* HDMI0 */ + &rsnd_port2>; /* HDMI1 */ +}; + &usb2_phy2 { pinctrl-0 = <&usb2_pins>; pinctrl-names = "default"; -- GitLab From a23bc44c2deaf659c565b522bed6e78ce573a16d Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Tue, 23 Jul 2019 02:23:08 +0900 Subject: [PATCH 1253/7155] arm64: dts: renesas: r8a7795: salvator-xs: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a7795-salvator-xs.dts | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts index 42101fc76837..36667c81d43d 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts @@ -57,17 +57,6 @@ status = "okay"; }; -&hsusb3 { - dr_mode = "otg"; - status = "okay"; -}; - -&sound_card { - dais = <&rsnd_port0 /* ak4613 */ - &rsnd_port1 /* HDMI0 */ - &rsnd_port2>; /* HDMI1 */ -}; - &hdmi0 { status = "okay"; @@ -114,6 +103,11 @@ remote-endpoint = <&rcar_dw_hdmi1_out>; }; +&hsusb3 { + dr_mode = "otg"; + status = "okay"; +}; + &ohci2 { status = "okay"; }; @@ -123,36 +117,6 @@ status = "okay"; }; -&rcar_sound { - ports { - /* rsnd_port0 is on salvator-common */ - rsnd_port1: port@1 { - reg = <1>; - rsnd_endpoint1: endpoint { - remote-endpoint = <&dw_hdmi0_snd_in>; - - dai-format = "i2s"; - bitclock-master = <&rsnd_endpoint1>; - frame-master = <&rsnd_endpoint1>; - - playback = <&ssi2>; - }; - }; - rsnd_port2: port@2 { - reg = <2>; - rsnd_endpoint2: endpoint { - remote-endpoint = <&dw_hdmi1_snd_in>; - - dai-format = "i2s"; - bitclock-master = <&rsnd_endpoint2>; - frame-master = <&rsnd_endpoint2>; - - playback = <&ssi3>; - }; - }; - }; -}; - &pca9654 { pcie_sata_switch { gpio-hog; @@ -186,11 +150,47 @@ }; }; +&rcar_sound { + ports { + /* rsnd_port0 is on salvator-common */ + rsnd_port1: port@1 { + reg = <1>; + rsnd_endpoint1: endpoint { + remote-endpoint = <&dw_hdmi0_snd_in>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_endpoint1>; + frame-master = <&rsnd_endpoint1>; + + playback = <&ssi2>; + }; + }; + rsnd_port2: port@2 { + reg = <2>; + rsnd_endpoint2: endpoint { + remote-endpoint = <&dw_hdmi1_snd_in>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_endpoint2>; + frame-master = <&rsnd_endpoint2>; + + playback = <&ssi3>; + }; + }; + }; +}; + /* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */ &sata { status = "okay"; }; +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1 /* HDMI0 */ + &rsnd_port2>; /* HDMI1 */ +}; + &usb2_phy2 { pinctrl-0 = <&usb2_pins>; pinctrl-names = "default"; -- GitLab From 74b1435efb0b6e14eba9feeb5a5ec89d2e2652a5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Wed, 24 Jul 2019 03:02:08 +0900 Subject: [PATCH 1254/7155] arm64: dts: renesas: r8a7796: salvator-x: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts index 2aefa53cb16b..de37e91e3b7a 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts @@ -36,11 +36,6 @@ "dclkin.0", "dclkin.1", "dclkin.2"; }; -&sound_card { - dais = <&rsnd_port0 /* ak4613 */ - &rsnd_port1>; /* HDMI0 */ -}; - &hdmi0 { status = "okay"; @@ -81,3 +76,8 @@ }; }; }; + +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1>; /* HDMI0 */ +}; -- GitLab From 93c3438f7604385f6a7dc6ccfc880acb6c0819a5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Wed, 24 Jul 2019 03:02:41 +0900 Subject: [PATCH 1255/7155] arm64: dts: renesas: r8a7796: salvator-xs: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts index d58ede18108d..a1cbfef2053f 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts @@ -36,11 +36,6 @@ "dclkin.0", "dclkin.1", "dclkin.2"; }; -&sound_card { - dais = <&rsnd_port0 /* ak4613 */ - &rsnd_port1>; /* HDMI0 */ -}; - &hdmi0 { status = "okay"; @@ -81,3 +76,8 @@ }; }; }; + +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1>; /* HDMI0 */ +}; -- GitLab From 44d2266c8c6945fad704d62617d8772089d82b4e Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Wed, 24 Jul 2019 03:03:10 +0900 Subject: [PATCH 1256/7155] arm64: dts: renesas: salvator-common: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman [geert: Sort i2c slave nodes] Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/salvator-common.dtsi | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi index 5c2c84723ec5..21e01056e759 100644 --- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi +++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi @@ -87,6 +87,28 @@ }; }; + hdmi0-out { + compatible = "hdmi-connector"; + label = "HDMI0 OUT"; + type = "a"; + + port { + hdmi0_con: endpoint { + }; + }; + }; + + hdmi1-out { + compatible = "hdmi-connector"; + label = "HDMI1 OUT"; + type = "a"; + + port { + hdmi1_con: endpoint { + }; + }; + }; + keys { compatible = "gpio-keys"; @@ -238,28 +260,6 @@ 1800000 0>; }; - hdmi0-out { - compatible = "hdmi-connector"; - label = "HDMI0 OUT"; - type = "a"; - - port { - hdmi0_con: endpoint { - }; - }; - }; - - hdmi1-out { - compatible = "hdmi-connector"; - label = "HDMI1 OUT"; - type = "a"; - - port { - hdmi1_con: endpoint { - }; - }; - }; - vga { compatible = "vga-connector"; @@ -462,20 +462,6 @@ #gpio-cells = <2>; }; - csa_vdd: adc@7c { - compatible = "maxim,max9611"; - reg = <0x7c>; - - shunt-resistor-micro-ohms = <5000>; - }; - - csa_dvfs: adc@7f { - compatible = "maxim,max9611"; - reg = <0x7f>; - - shunt-resistor-micro-ohms = <5000>; - }; - video-receiver@70 { compatible = "adi,adv7482"; reg = <0x70 0x71 0x72 0x73 0x74 0x75 @@ -527,6 +513,20 @@ }; }; }; + + csa_vdd: adc@7c { + compatible = "maxim,max9611"; + reg = <0x7c>; + + shunt-resistor-micro-ohms = <5000>; + }; + + csa_dvfs: adc@7f { + compatible = "maxim,max9611"; + reg = <0x7f>; + + shunt-resistor-micro-ohms = <5000>; + }; }; &i2c_dvfs { -- GitLab From b726a9e3ac06fa05e2b40d78750882348658a248 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Wed, 24 Jul 2019 03:03:35 +0900 Subject: [PATCH 1257/7155] arm64: dts: renesas: ulcb-kf: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman [geert: Sort i2c slave nodes] Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 226 +++++++++++------------ 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi index 27851a77f538..202177706cde 100644 --- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -83,6 +83,56 @@ }; &i2c2 { + i2cswitch2: i2c-switch@71 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x71>; + reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; + + /* Audio_SDA, Audio_SCL */ + i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + + pcm3168a: audio-codec@44 { + #sound-dai-cells = <0>; + compatible = "ti,pcm3168a"; + reg = <0x44>; + clocks = <&clksndsel>; + clock-names = "scki"; + + VDD1-supply = <&snd_3p3v>; + VDD2-supply = <&snd_3p3v>; + VCCAD1-supply = <&snd_vcc5v>; + VCCAD2-supply = <&snd_vcc5v>; + VCCDA1-supply = <&snd_vcc5v>; + VCCDA2-supply = <&snd_vcc5v>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + mclk-fs = <512>; + port@0 { + reg = <0>; + pcm3168a_endpoint_p: endpoint { + remote-endpoint = <&rsnd_for_pcm3168a_play>; + clocks = <&clksndsel>; + }; + }; + port@1 { + reg = <1>; + pcm3168a_endpoint_c: endpoint { + remote-endpoint = <&rsnd_for_pcm3168a_capture>; + clocks = <&clksndsel>; + }; + }; + }; + }; + }; + }; + /* U11 */ gpio_exp_74: gpio@74 { compatible = "ti,tca9539"; @@ -100,13 +150,6 @@ line-name = "Audio_Out_OFF"; }; - sd-wifi-mux { - gpio-hog; - gpios = <5 GPIO_ACTIVE_HIGH>; - output-low; /* Connect WL1837 */ - line-name = "SD WiFi mux"; - }; - hub_pwen { gpio-hog; gpios = <6 GPIO_ACTIVE_HIGH>; @@ -121,6 +164,13 @@ line-name = "HUB rst"; }; + otg_extlpn { + gpio-hog; + gpios = <9 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "OTG EXTLPn"; + }; + otg_offvbusn { gpio-hog; gpios = <8 GPIO_ACTIVE_HIGH>; @@ -128,11 +178,11 @@ line-name = "OTG OFFVBUSn"; }; - otg_extlpn { + sd-wifi-mux { gpio-hog; - gpios = <9 GPIO_ACTIVE_HIGH>; - output-high; - line-name = "OTG EXTLPn"; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-low; /* Connect WL1837 */ + line-name = "SD WiFi mux"; }; snd_rst { @@ -153,59 +203,17 @@ interrupt-parent = <&gpio6>; interrupts = <4 IRQ_TYPE_EDGE_FALLING>; }; +}; - i2cswitch2: i2c-switch@71 { +&i2c4 { + i2cswitch4: i2c-switch@71 { compatible = "nxp,pca9548"; #address-cells = <1>; #size-cells = <0>; reg = <0x71>; - reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; - - /* Audio_SDA, Audio_SCL */ - i2c@7 { - #address-cells = <1>; - #size-cells = <0>; - reg = <7>; - - pcm3168a: audio-codec@44 { - #sound-dai-cells = <0>; - compatible = "ti,pcm3168a"; - reg = <0x44>; - clocks = <&clksndsel>; - clock-names = "scki"; - - VDD1-supply = <&snd_3p3v>; - VDD2-supply = <&snd_3p3v>; - VCCAD1-supply = <&snd_vcc5v>; - VCCAD2-supply = <&snd_vcc5v>; - VCCDA1-supply = <&snd_vcc5v>; - VCCDA2-supply = <&snd_vcc5v>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - mclk-fs = <512>; - port@0 { - reg = <0>; - pcm3168a_endpoint_p: endpoint { - remote-endpoint = <&rsnd_for_pcm3168a_play>; - clocks = <&clksndsel>; - }; - }; - port@1 { - reg = <1>; - pcm3168a_endpoint_c: endpoint { - remote-endpoint = <&rsnd_for_pcm3168a_capture>; - clocks = <&clksndsel>; - }; - }; - }; - }; - }; + reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; }; -}; -&i2c4 { gpio_exp_76: gpio@76 { compatible = "ti,tca9539"; reg = <0x76>; @@ -225,14 +233,6 @@ interrupt-parent = <&gpio5>; interrupts = <9 IRQ_TYPE_EDGE_FALLING>; }; - - i2cswitch4: i2c-switch@71 { - compatible = "nxp,pca9548"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x71>; - reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; - }; }; &ohci0 { @@ -279,14 +279,50 @@ power-source = <3300>; }; + sound_pcm_pins: sound-pcm { + groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; + function = "ssi"; + }; + usb0_pins: usb0 { groups = "usb0"; function = "usb0"; }; +}; - sound_pcm_pins: sound-pcm { - groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; - function = "ssi"; +&rcar_sound { + pinctrl-0 = <&sound_pins + &sound_clk_pins + &sound_pcm_pins>; + + ports { + /* rsnd_port0/1 are on salvator-common */ + rsnd_port2: port@2 { + reg = <2>; + rsnd_for_pcm3168a_play: endpoint { + remote-endpoint = <&pcm3168a_endpoint_p>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_for_pcm3168a_play>; + frame-master = <&rsnd_for_pcm3168a_play>; + dai-tdm-slot-num = <8>; + + playback = <&ssi3>; + }; + }; + rsnd_port3: port@3 { + reg = <3>; + rsnd_for_pcm3168a_capture: endpoint { + remote-endpoint = <&pcm3168a_endpoint_c>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_for_pcm3168a_capture>; + frame-master = <&rsnd_for_pcm3168a_capture>; + dai-tdm-slot-num = <6>; + + capture = <&ssi4>; + }; + }; }; }; @@ -322,17 +358,6 @@ }; }; -&usb2_phy0 { - pinctrl-0 = <&usb0_pins>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&xhci0 { - status = "okay"; -}; - &sound_card { dais = <&rsnd_port0 /* ak4613 */ &rsnd_port1 /* HDMI0 */ @@ -341,42 +366,17 @@ >; }; -&rcar_sound { - pinctrl-0 = <&sound_pins - &sound_clk_pins - &sound_pcm_pins>; - - ports { - /* rsnd_port0/1 are on salvator-common */ - rsnd_port2: port@2 { - reg = <2>; - rsnd_for_pcm3168a_play: endpoint { - remote-endpoint = <&pcm3168a_endpoint_p>; - - dai-format = "i2s"; - bitclock-master = <&rsnd_for_pcm3168a_play>; - frame-master = <&rsnd_for_pcm3168a_play>; - dai-tdm-slot-num = <8>; - - playback = <&ssi3>; - }; - }; - rsnd_port3: port@3 { - reg = <3>; - rsnd_for_pcm3168a_capture: endpoint { - remote-endpoint = <&pcm3168a_endpoint_c>; +&ssi4 { + shared-pin; +}; - dai-format = "i2s"; - bitclock-master = <&rsnd_for_pcm3168a_capture>; - frame-master = <&rsnd_for_pcm3168a_capture>; - dai-tdm-slot-num = <6>; +&usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; - capture = <&ssi4>; - }; - }; - }; + status = "okay"; }; -&ssi4 { - shared-pin; +&xhci0 { + status = "okay"; }; -- GitLab From 0a05b3d7fee511de8a1c9dffc3d86f1df55e1737 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Wed, 24 Jul 2019 03:04:06 +0900 Subject: [PATCH 1258/7155] arm64: dts: renesas: ulcb: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/ulcb.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi index 7e498b46e9ae..3ef89171538f 100644 --- a/arch/arm64/boot/dts/renesas/ulcb.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi @@ -428,6 +428,11 @@ }; }; +&rwdt { + timeout-sec = <60>; + status = "okay"; +}; + &scif2 { pinctrl-0 = <&scif2_pins>; pinctrl-names = "default"; @@ -478,8 +483,3 @@ status = "okay"; }; - -&rwdt { - timeout-sec = <60>; - status = "okay"; -}; -- GitLab From 10a08fd65ec1a68ccd86b19ec822ed5f2e50113f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2019 11:55:59 +0200 Subject: [PATCH 1259/7155] ACPI: PM: Set up EC GPE for system wakeup from drivers that need it The EC GPE needs to be set up for system wakeup only if there is a driver depending on it, either intel-hid or intel-vbtn, bound to a button device that is expected to wake up the system from sleep (such as the power button on some Dell systems, like the XPS13 9360). It doesn't need to be set up for waking up the system from sleep in any other cases and whether or not it is expected to wake up the system from sleep doesn't depend on whether or not the LPS0 device is present in the ACPI namespace. For this reason, rearrange the ACPI suspend-to-idle code to make the drivers depending on the EC GPE wakeup take care of setting it up and decouple that from the LPS0 device handling. While at it, make intel-hid and intel-vbtn prepare for system wakeup only if they are allowed to wake up the system from sleep by user space (via sysfs). [Note that acpi_ec_mark_gpe_for_wake() and acpi_ec_set_gpe_wake_mask() are there to prevent the EC GPE from being disabled by the acpi_enable_all_wakeup_gpes() call in acpi_s2idle_prepare(), so on systems with either intel-hid or intel-vbtn this change doesn't affect any interactions with the hardware or platform firmware.] Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko --- drivers/acpi/ec.c | 7 ++++++- drivers/acpi/internal.h | 2 -- drivers/acpi/sleep.c | 13 ++----------- drivers/platform/x86/intel-hid.c | 20 ++++++++++++++++---- drivers/platform/x86/intel-vbtn.c | 20 ++++++++++++++++---- include/linux/acpi.h | 4 ++++ include/linux/suspend.h | 1 + 7 files changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 58c7ad402d8d..b996ca5f253f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1048,17 +1049,21 @@ void acpi_ec_unblock_transactions(void) acpi_ec_start(first_ec, true); } +#ifdef CONFIG_PM_SLEEP void acpi_ec_mark_gpe_for_wake(void) { if (first_ec && !ec_no_wakeup) acpi_mark_gpe_for_wake(NULL, first_ec->gpe); } +EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake); void acpi_ec_set_gpe_wake_mask(u8 action) { - if (first_ec && !ec_no_wakeup) + if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); } +EXPORT_SYMBOL_GPL(acpi_ec_set_gpe_wake_mask); +#endif bool acpi_ec_dispatch_gpe(void) { diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 1b5f9ac06ea8..bcc080511197 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -194,8 +194,6 @@ void acpi_ec_ecdt_probe(void); void acpi_ec_dsdt_probe(void); void acpi_ec_block_transactions(void); void acpi_ec_unblock_transactions(void); -void acpi_ec_mark_gpe_for_wake(void); -void acpi_ec_set_gpe_wake_mask(u8 action); bool acpi_ec_dispatch_gpe(void); int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 970ae7c7a3f7..9cb0532f7471 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -930,8 +930,6 @@ static int lps0_device_attach(struct acpi_device *adev, acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", bitmask); - - acpi_ec_mark_gpe_for_wake(); } else { acpi_handle_debug(adev->handle, "_DSM function 0 evaluation failed\n"); @@ -960,8 +958,6 @@ static int acpi_s2idle_prepare(void) if (lps0_device_handle) { acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); - - acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); } if (acpi_sci_irq_valid()) @@ -979,10 +975,7 @@ static int acpi_s2idle_prepare(void) static void acpi_s2idle_wake(void) { - if (!lps0_device_handle) - return; - - if (pm_debug_messages_on) + if (lps0_device_handle && pm_debug_messages_on) lpi_check_constraints(); /* @@ -1031,8 +1024,6 @@ static void acpi_s2idle_restore(void) disable_irq_wake(acpi_sci_irq); if (lps0_device_handle) { - acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); - acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); } @@ -1081,7 +1072,7 @@ bool acpi_s2idle_wakeup(void) bool acpi_sleep_no_ec_events(void) { - return !s2idle_in_progress || !lps0_device_handle; + return !s2idle_in_progress; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index bc0d55a59015..e51c72b92cbd 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -253,9 +253,12 @@ static void intel_button_array_enable(struct device *device, bool enable) static int intel_hid_pm_prepare(struct device *device) { - struct intel_hid_priv *priv = dev_get_drvdata(device); + if (device_may_wakeup(device)) { + struct intel_hid_priv *priv = dev_get_drvdata(device); - priv->wakeup_mode = true; + priv->wakeup_mode = true; + acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); + } return 0; } @@ -270,9 +273,12 @@ static int intel_hid_pl_suspend_handler(struct device *device) static int intel_hid_pl_resume_handler(struct device *device) { - struct intel_hid_priv *priv = dev_get_drvdata(device); + if (device_may_wakeup(device)) { + struct intel_hid_priv *priv = dev_get_drvdata(device); - priv->wakeup_mode = false; + acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); + priv->wakeup_mode = false; + } if (pm_resume_via_firmware()) { intel_hid_set_enable(device, true); intel_button_array_enable(device, true); @@ -491,6 +497,12 @@ static int intel_hid_probe(struct platform_device *device) } device_init_wakeup(&device->dev, true); + /* + * In order for system wakeup to work, the EC GPE has to be marked as + * a wakeup one, so do that here (this setting will persist, but it has + * no effect until the wakeup mask is set for the EC GPE). + */ + acpi_ec_mark_gpe_for_wake(); return 0; err_remove_notify: diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index a0d0cecff55f..ab84e1bbdedd 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -176,6 +176,12 @@ static int intel_vbtn_probe(struct platform_device *device) return -EBUSY; device_init_wakeup(&device->dev, true); + /* + * In order for system wakeup to work, the EC GPE has to be marked as + * a wakeup one, so do that here (this setting will persist, but it has + * no effect until the wakeup mask is set for the EC GPE). + */ + acpi_ec_mark_gpe_for_wake(); return 0; } @@ -195,17 +201,23 @@ static int intel_vbtn_remove(struct platform_device *device) static int intel_vbtn_pm_prepare(struct device *dev) { - struct intel_vbtn_priv *priv = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) { + struct intel_vbtn_priv *priv = dev_get_drvdata(dev); - priv->wakeup_mode = true; + priv->wakeup_mode = true; + acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); + } return 0; } static int intel_vbtn_pm_resume(struct device *dev) { - struct intel_vbtn_priv *priv = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) { + struct intel_vbtn_priv *priv = dev_get_drvdata(dev); - priv->wakeup_mode = false; + acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); + priv->wakeup_mode = false; + } return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9426b9aaed86..e65a4c5bbeae 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -931,6 +931,8 @@ int acpi_subsys_suspend_noirq(struct device *dev); int acpi_subsys_suspend(struct device *dev); int acpi_subsys_freeze(struct device *dev); int acpi_subsys_poweroff(struct device *dev); +void acpi_ec_mark_gpe_for_wake(void); +void acpi_ec_set_gpe_wake_mask(u8 action); #else static inline int acpi_subsys_prepare(struct device *dev) { return 0; } static inline void acpi_subsys_complete(struct device *dev) {} @@ -939,6 +941,8 @@ static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; } static inline int acpi_subsys_suspend(struct device *dev) { return 0; } static inline int acpi_subsys_freeze(struct device *dev) { return 0; } static inline int acpi_subsys_poweroff(struct device *dev) { return 0; } +static inline void acpi_ec_mark_gpe_for_wake(void) {} +static inline void acpi_ec_set_gpe_wake_mask(u8 action) {} #endif #ifdef CONFIG_ACPI diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 66ce3871ed61..f0c4a8445140 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -335,6 +335,7 @@ static inline void pm_set_suspend_via_firmware(void) {} static inline void pm_set_resume_via_firmware(void) {} static inline bool pm_suspend_via_firmware(void) { return false; } static inline bool pm_resume_via_firmware(void) { return false; } +static inline bool pm_suspend_no_platform(void) { return false; } static inline bool pm_suspend_default_s2idle(void) { return false; } static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} -- GitLab From fb583c8eeeb1fd57e24ef41ed94c9112067aeac9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2019 11:28:57 +0200 Subject: [PATCH 1260/7155] driver core: Fix creation of device links with PM-runtime flags After commit 515db266a9da ("driver core: Remove device link creation limitation"), if PM-runtime flags are passed to device_link_add(), it will fail (returning NULL) due to an overly restrictive flags check introduced by that commit. Fix this issue by extending the check in question to cover the PM-runtime flags too. Fixes: 515db266a9da ("driver core: Remove device link creation limitation") Reported-by: Dmitry Osipenko Tested-by: Jon Hunter Signed-off-by: Rafael J. Wysocki Tested-by: Dmitry Osipenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/7674989.cD04D8YV3U@kreacher Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 21cd08162219..08eecab2497b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -213,6 +213,9 @@ void device_pm_move_to_tail(struct device *dev) DL_FLAG_AUTOREMOVE_SUPPLIER | \ DL_FLAG_AUTOPROBE_CONSUMER) +#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) + /** * device_link_add - Create a link between two devices. * @consumer: Consumer end of the link. @@ -274,8 +277,7 @@ struct device_link *device_link_add(struct device *consumer, { struct device_link *link; - if (!consumer || !supplier || - (flags & ~(DL_FLAG_STATELESS | DL_MANAGED_LINK_FLAGS)) || + if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | -- GitLab From c27989cc536b5e0ba179d7ab50ebc2a06fddf663 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 26 Jul 2019 10:14:51 +0200 Subject: [PATCH 1261/7155] dt-bindings: switch Exynos EHCI/OHCI bindings to use array of generic PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 69bec7259853 ("USB: core: let USB device know device node") added support for attaching devicetree node for USB devices. Those nodes are children of their USB host controller. However Exynos EHCI and OHCI driver bindings already define child-nodes for each physical root hub port and assigns respective PHY controller and parameters to them. This leads to the conflict. A workaround for it has been merged as commit 01d4071486fe ("usb: exynos: add workaround for the USB device bindings conflict"), but it disabled support for USB device binding for Exynos EHCI/OHCI controllers. To resolve it properly, lets move PHYs from the sub-nodes to a standard array under the 'phys' property. Suggested-by: Måns Rullgård Reviewed-by: Rob Herring Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20190726081453.9456-2-m.szyprowski@samsung.com Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/usb/exynos-usb.txt | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt index b7111f43fa59..66c394f9e11f 100644 --- a/Documentation/devicetree/bindings/usb/exynos-usb.txt +++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt @@ -12,13 +12,11 @@ Required properties: - interrupts: interrupt number to the cpu. - clocks: from common clock binding: handle to usb clock. - clock-names: from common clock binding: Shall be "usbhost". - - port: if in the SoC there are EHCI phys, they should be listed here. - One phy per port. Each port should have following entries: - - reg: port number on EHCI controller, e.g - On Exynos5250, port 0 is USB2.0 otg phy - port 1 is HSIC phy0 - port 2 is HSIC phy1 - - phys: from the *Generic PHY* bindings; specifying phy used by port. + - phys: from the *Generic PHY* bindings; array specifying phy(s) used + by the root port. + - phy-names: from the *Generic PHY* bindings; array of the names for + each phy for the root ports, must be a subset of the following: + "host", "hsic0", "hsic1". Optional properties: - samsung,vbus-gpio: if present, specifies the GPIO that @@ -35,12 +33,8 @@ Example: clocks = <&clock 285>; clock-names = "usbhost"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2phy 1>; - }; + phys = <&usb2phy 1>; + phy-names = "host"; }; OHCI @@ -52,13 +46,11 @@ Required properties: - interrupts: interrupt number to the cpu. - clocks: from common clock binding: handle to usb clock. - clock-names: from common clock binding: Shall be "usbhost". - - port: if in the SoC there are OHCI phys, they should be listed here. - One phy per port. Each port should have following entries: - - reg: port number on OHCI controller, e.g - On Exynos5250, port 0 is USB2.0 otg phy - port 1 is HSIC phy0 - port 2 is HSIC phy1 - - phys: from the *Generic PHY* bindings, specifying phy used by port. + - phys: from the *Generic PHY* bindings; array specifying phy(s) used + by the root port. + - phy-names: from the *Generic PHY* bindings; array of the names for + each phy for the root ports, must be a subset of the following: + "host", "hsic0", "hsic1". Example: usb@12120000 { @@ -69,13 +61,8 @@ Example: clocks = <&clock 285>; clock-names = "usbhost"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2phy 1>; - }; - + phys = <&usb2phy 1>; + phy-names = "host"; }; DWC3 -- GitLab From 214b606e90dd087d190b7307183ec8c16f500371 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 26 Jul 2019 10:14:52 +0200 Subject: [PATCH 1262/7155] usb: exynos: add support for getting PHYs from the standard dt array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the code for getting generic PHYs from standard device tree array from the main controller device node. This is a first step in resolving the conflict between Exynos EHCI/OHCI sub-nodes and generic USB device bindings. Later the sub-nodes currently used for assigning PHYs to root ports of the controller will be removed making a place for the generic USB device bindings nodes. Suggested-by: Måns Rullgård Signed-off-by: Marek Szyprowski Acked-by: Alan Stern Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20190726081453.9456-3-m.szyprowski@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-exynos.c | 23 +++++++++++++++++++---- drivers/usb/host/ohci-exynos.c | 23 +++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 3a29a1a8519c..01debfd03d4a 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -41,6 +41,7 @@ struct exynos_ehci_hcd { struct clk *clk; struct device_node *of_node; struct phy *phy[PHY_NUMBER]; + bool legacy_phy; }; #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) @@ -50,10 +51,22 @@ static int exynos_ehci_get_phy(struct device *dev, { struct device_node *child; struct phy *phy; - int phy_number; + int phy_number, num_phys; int ret; /* Get PHYs for the controller */ + num_phys = of_count_phandle_with_args(dev->of_node, "phys", + "#phy-cells"); + for (phy_number = 0; phy_number < num_phys; phy_number++) { + phy = devm_of_phy_get_by_index(dev, dev->of_node, phy_number); + if (IS_ERR(phy)) + return PTR_ERR(phy); + exynos_ehci->phy[phy_number] = phy; + } + if (num_phys > 0) + return 0; + + /* Get PHYs using legacy bindings */ for_each_available_child_of_node(dev->of_node, child) { ret = of_property_read_u32(child, "reg", &phy_number); if (ret) { @@ -84,6 +97,7 @@ static int exynos_ehci_get_phy(struct device *dev, } } + exynos_ehci->legacy_phy = true; return 0; } @@ -205,11 +219,12 @@ static int exynos_ehci_probe(struct platform_device *pdev) ehci->caps = hcd->regs; /* - * Workaround: reset of_node pointer to avoid conflict between Exynos - * EHCI port subnodes and generic USB device bindings + * Workaround: reset of_node pointer to avoid conflict between legacy + * Exynos EHCI port subnodes and generic USB device bindings */ exynos_ehci->of_node = pdev->dev.of_node; - pdev->dev.of_node = NULL; + if (exynos_ehci->legacy_phy) + pdev->dev.of_node = NULL; /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 905c6317e0c3..d5ce98e205c7 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -32,6 +32,7 @@ struct exynos_ohci_hcd { struct clk *clk; struct device_node *of_node; struct phy *phy[PHY_NUMBER]; + bool legacy_phy; }; static int exynos_ohci_get_phy(struct device *dev, @@ -39,10 +40,22 @@ static int exynos_ohci_get_phy(struct device *dev, { struct device_node *child; struct phy *phy; - int phy_number; + int phy_number, num_phys; int ret; /* Get PHYs for the controller */ + num_phys = of_count_phandle_with_args(dev->of_node, "phys", + "#phy-cells"); + for (phy_number = 0; phy_number < num_phys; phy_number++) { + phy = devm_of_phy_get_by_index(dev, dev->of_node, phy_number); + if (IS_ERR(phy)) + return PTR_ERR(phy); + exynos_ohci->phy[phy_number] = phy; + } + if (num_phys > 0) + return 0; + + /* Get PHYs using legacy bindings */ for_each_available_child_of_node(dev->of_node, child) { ret = of_property_read_u32(child, "reg", &phy_number); if (ret) { @@ -73,6 +86,7 @@ static int exynos_ohci_get_phy(struct device *dev, } } + exynos_ohci->legacy_phy = true; return 0; } @@ -172,11 +186,12 @@ static int exynos_ohci_probe(struct platform_device *pdev) } /* - * Workaround: reset of_node pointer to avoid conflict between Exynos - * OHCI port subnodes and generic USB device bindings + * Workaround: reset of_node pointer to avoid conflict between legacy + * Exynos OHCI port subnodes and generic USB device bindings */ exynos_ohci->of_node = pdev->dev.of_node; - pdev->dev.of_node = NULL; + if (exynos_ohci->legacy_phy) + pdev->dev.of_node = NULL; err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { -- GitLab From 314de2f6b577a55772674dd2e4907a8c94b00975 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 26 Jul 2019 10:14:53 +0200 Subject: [PATCH 1263/7155] ARM: dts: exynos: Use standard arrays of generic PHYs for EHCI/OHCI devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move USB PHYs to a standard arrays for Exynos EHCI/OHCI devices. This resolves the conflict between Exynos EHCI/OHCI sub-nodes and generic USB device bindings. Once the Exynos EHCI/OHCI sub-nodes are removed, the boards can finally provide sub-nodes for the USB devices using generic USB device bindings. Suggested-by: Måns Rullgård Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20190726081453.9456-4-m.szyprowski@samsung.com Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/exynos4.dtsi | 28 +++---------------- .../boot/dts/exynos4210-universal_c210.dts | 8 ++---- arch/arm/boot/dts/exynos4412-itop-elite.dts | 9 ++---- arch/arm/boot/dts/exynos4412-odroidu3.dts | 8 ++---- arch/arm/boot/dts/exynos4412-odroidx.dts | 5 ++-- arch/arm/boot/dts/exynos4412-origen.dts | 9 ++---- arch/arm/boot/dts/exynos5250.dtsi | 16 +++-------- arch/arm/boot/dts/exynos54xx.dtsi | 18 +++--------- 8 files changed, 22 insertions(+), 79 deletions(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 1264cc431ff6..433f109d97ca 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -380,23 +380,8 @@ clocks = <&clock CLK_USB_HOST>; clock-names = "usbhost"; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&exynos_usbphy 1>; - status = "disabled"; - }; - port@1 { - reg = <1>; - phys = <&exynos_usbphy 2>; - status = "disabled"; - }; - port@2 { - reg = <2>; - phys = <&exynos_usbphy 3>; - status = "disabled"; - }; + phys = <&exynos_usbphy 1>, <&exynos_usbphy 2>, <&exynos_usbphy 3>; + phy-names = "host", "hsic0", "hsic1"; }; ohci: ohci@12590000 { @@ -406,13 +391,8 @@ clocks = <&clock CLK_USB_HOST>; clock-names = "usbhost"; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&exynos_usbphy 1>; - status = "disabled"; - }; + phys = <&exynos_usbphy 1>; + phy-names = "host"; }; gpu: gpu@13000000 { diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts index 82a8b5449978..09d3d54d09ff 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -204,9 +204,8 @@ &ehci { status = "okay"; - port@0 { - status = "okay"; - }; + phys = <&exynos_usbphy 1>; + phy-names = "host"; }; &exynos_usbphy { @@ -520,9 +519,6 @@ &ohci { status = "okay"; - port@0 { - status = "okay"; - }; }; &pinctrl_1 { diff --git a/arch/arm/boot/dts/exynos4412-itop-elite.dts b/arch/arm/boot/dts/exynos4412-itop-elite.dts index 0dedeba89b5f..f6d0a5f5d339 100644 --- a/arch/arm/boot/dts/exynos4412-itop-elite.dts +++ b/arch/arm/boot/dts/exynos4412-itop-elite.dts @@ -146,13 +146,8 @@ /* In order to reset USB ethernet */ samsung,vbus-gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>; - port@0 { - status = "okay"; - }; - - port@2 { - status = "okay"; - }; + phys = <&exynos_usbphy 1>, <&exynos_usbphy 3>; + phy-names = "host", "hsic1"; }; &exynos_usbphy { diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts index 96d99887bceb..8ff243ba4542 100644 --- a/arch/arm/boot/dts/exynos4412-odroidu3.dts +++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts @@ -105,12 +105,8 @@ }; &ehci { - port@1 { - status = "okay"; - }; - port@2 { - status = "okay"; - }; + phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>; + phy-names = "hsic0", "hsic1"; }; &sound { diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index a2251581f6b6..3ea2a0101e80 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -72,9 +72,8 @@ }; &ehci { - port@1 { - status = "okay"; - }; + phys = <&exynos_usbphy 2>; + phy-names = "hsic0"; }; &mshc_0 { diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index 698de4345d16..ecd14b283a6b 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -88,13 +88,8 @@ &ehci { samsung,vbus-gpio = <&gpx3 5 1>; status = "okay"; - - port@1 { - status = "okay"; - }; - port@2 { - status = "okay"; - }; + phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>; + phy-names = "hsic0", "hsic1"; }; &fimd { diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index d5e0392b409e..c5584f40ebfb 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -617,12 +617,8 @@ clocks = <&clock CLK_USB2>; clock-names = "usbhost"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2_phy_gen 1>; - }; + phys = <&usb2_phy_gen 1>; + phy-names = "host"; }; ohci: usb@12120000 { @@ -632,12 +628,8 @@ clocks = <&clock CLK_USB2>; clock-names = "usbhost"; - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2_phy_gen 1>; - }; + phys = <&usb2_phy_gen 1>; + phy-names = "host"; }; usb2_phy_gen: phy@12130000 { diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi index 0b27bebf9528..9c3b63b7cac6 100644 --- a/arch/arm/boot/dts/exynos54xx.dtsi +++ b/arch/arm/boot/dts/exynos54xx.dtsi @@ -189,26 +189,16 @@ compatible = "samsung,exynos4210-ehci"; reg = <0x12110000 0x100>; interrupts = ; - - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2_phy 1>; - }; + phys = <&usb2_phy 1>; + phy-names = "host"; }; usbhost1: usb@12120000 { compatible = "samsung,exynos4210-ohci"; reg = <0x12120000 0x100>; interrupts = ; - - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - phys = <&usb2_phy 1>; - }; + phys = <&usb2_phy 1>; + phy-names = "host"; }; usb2_phy: phy@12130000 { -- GitLab From 9e22cb82998253072ec05ee1f8b06daf5ca50800 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 17:22:01 -0500 Subject: [PATCH 1264/7155] usb: host: ohci-tmio: Mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: arm): drivers/usb/host/ohci-tmio.c: In function ‘tmio_stop_hc’: ./include/linux/device.h:1499:2: warning: this statement may fall through [-Wimplicit-fallthrough=] _dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/usb/host/ohci-tmio.c:99:4: note: in expansion of macro ‘dev_err’ dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports); ^~~~~~~ In file included from drivers/usb/host/ohci-hcd.c:1257:0: drivers/usb/host/ohci-tmio.c:100:3: note: here case 3: ^~~~ drivers/usb/host/ohci-tmio.c:101:7: warning: this statement may fall through [-Wimplicit-fallthrough=] pm |= CCR_PM_USBPW3; ^ drivers/usb/host/ohci-tmio.c:102:3: note: here case 2: ^~~~ drivers/usb/host/ohci-tmio.c:103:7: warning: this statement may fall through [-Wimplicit-fallthrough=] pm |= CCR_PM_USBPW2; ^ drivers/usb/host/ohci-tmio.c:104:3: note: here case 1: ^~~~ Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20190729222201.GA19408@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-tmio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index d5a293a707b6..fb6f5e9ae5c6 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -97,10 +97,13 @@ static void tmio_stop_hc(struct platform_device *dev) switch (ohci->num_ports) { default: dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports); + /* fall through */ case 3: pm |= CCR_PM_USBPW3; + /* fall through */ case 2: pm |= CCR_PM_USBPW2; + /* fall through */ case 1: pm |= CCR_PM_USBPW1; } -- GitLab From dcf8f7ecb36185f4cf96ad1f098704eb690f792e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 28 Jul 2019 19:06:31 -0500 Subject: [PATCH 1265/7155] usb: phy: ab8500-usb: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/usb/phy/phy-ab8500-usb.c: In function 'ab8500_usb_link_status_update': drivers/usb/phy/phy-ab8500-usb.c:424:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDB; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:425:2: note: here case USB_LINK_NOT_CONFIGURED_8500: ^~~~ drivers/usb/phy/phy-ab8500-usb.c:440:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDC; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:441:2: note: here case USB_LINK_STD_HOST_NC_8500: ^~~~ drivers/usb/phy/phy-ab8500-usb.c:459:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDA; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:460:2: note: here case USB_LINK_HM_IDGND_8500: ^~~~ drivers/usb/phy/phy-ab8500-usb.c: In function 'ab8505_usb_link_status_update': drivers/usb/phy/phy-ab8500-usb.c:332:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDB; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:333:2: note: here case USB_LINK_NOT_CONFIGURED_8505: ^~~~ drivers/usb/phy/phy-ab8500-usb.c:352:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDC; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:353:2: note: here case USB_LINK_STD_HOST_NC_8505: ^~~~ drivers/usb/phy/phy-ab8500-usb.c:370:9: warning: this statement may fall through [-Wimplicit-fallthrough=] event = UX500_MUSB_RIDA; ~~~~~~^~~~~~~~~~~~~~~~~ drivers/usb/phy/phy-ab8500-usb.c:371:2: note: here case USB_LINK_HM_IDGND_8505: ^~~~ Reported-by: Stephen Rothwell Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20190729000631.GA24165@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-ab8500-usb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index aaf363f19714..14b432982fd3 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -330,6 +330,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, switch (lsts) { case USB_LINK_ACA_RID_B_8505: event = UX500_MUSB_RIDB; + /* Fall through */ case USB_LINK_NOT_CONFIGURED_8505: case USB_LINK_RESERVED0_8505: case USB_LINK_RESERVED1_8505: @@ -350,6 +351,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, case USB_LINK_ACA_RID_C_NM_8505: event = UX500_MUSB_RIDC; + /* Fall through */ case USB_LINK_STD_HOST_NC_8505: case USB_LINK_STD_HOST_C_NS_8505: case USB_LINK_STD_HOST_C_S_8505: @@ -368,6 +370,7 @@ static int ab8505_usb_link_status_update(struct ab8500_usb *ab, case USB_LINK_ACA_RID_A_8505: case USB_LINK_ACA_DOCK_CHGR_8505: event = UX500_MUSB_RIDA; + /* Fall through */ case USB_LINK_HM_IDGND_8505: if (ab->mode == USB_IDLE) { ab->mode = USB_HOST; @@ -422,6 +425,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, switch (lsts) { case USB_LINK_ACA_RID_B_8500: event = UX500_MUSB_RIDB; + /* Fall through */ case USB_LINK_NOT_CONFIGURED_8500: case USB_LINK_NOT_VALID_LINK_8500: ab->mode = USB_IDLE; @@ -438,6 +442,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, case USB_LINK_ACA_RID_C_HS_8500: case USB_LINK_ACA_RID_C_HS_CHIRP_8500: event = UX500_MUSB_RIDC; + /* Fall through */ case USB_LINK_STD_HOST_NC_8500: case USB_LINK_STD_HOST_C_NS_8500: case USB_LINK_STD_HOST_C_S_8500: @@ -457,6 +462,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, case USB_LINK_ACA_RID_A_8500: event = UX500_MUSB_RIDA; + /* Fall through */ case USB_LINK_HM_IDGND_8500: if (ab->mode == USB_IDLE) { ab->mode = USB_HOST; -- GitLab From 6cda08a20dbde45b021091230c8a359fa08c5103 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:32 +0100 Subject: [PATCH 1266/7155] drivers: Introduce device lookup variants by name Add a helper to match the device name for device lookup. Also reuse this generic exported helper for the existing bus_find_device_by_name(). and add similar variants for driver/class. Cc: Alessandro Zummo Cc: Alexander Aring Cc: Alexander Shishkin Cc: Arnd Bergmann Cc: Dan Murphy Cc: Harald Freudenberger Cc: Heiko Carstens Cc: Jacek Anaszewski Cc: Lee Jones Cc: linux-leds@vger.kernel.org Cc: linux-rtc@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: linux-wpan@vger.kernel.org Cc: Maxime Coquelin Cc: Pavel Machek Cc: Peter Oberparleiter Cc: "Rafael J. Wysocki" Cc: Stefan Schmidt Cc: Greg Kroah-Hartman Cc: "Rafael J. Wysocki" Signed-off-by: Suzuki K Poulose Reviewed-by: Heikki Krogerus Acked-by: Alexandre Belloni Link: https://lore.kernel.org/r/20190723221838.12024-2-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 24 ------------------ drivers/base/core.c | 6 +++++ drivers/hwtracing/stm/core.c | 9 +------ drivers/leds/led-class.c | 9 +------ drivers/rtc/interface.c | 11 +-------- drivers/s390/cio/ccwgroup.c | 10 +------- drivers/s390/cio/device.c | 15 +----------- drivers/s390/crypto/zcrypt_api.c | 11 +-------- drivers/usb/roles/class.c | 8 +----- drivers/usb/typec/class.c | 8 +----- include/linux/device.h | 42 +++++++++++++++++++++++++++++--- net/ieee802154/core.c | 7 +----- 12 files changed, 54 insertions(+), 106 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index df3cac739813..a1d1e8256324 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -342,30 +342,6 @@ struct device *bus_find_device(struct bus_type *bus, } EXPORT_SYMBOL_GPL(bus_find_device); -static int match_name(struct device *dev, const void *data) -{ - const char *name = data; - - return sysfs_streq(name, dev_name(dev)); -} - -/** - * bus_find_device_by_name - device iterator for locating a particular device of a specific name - * @bus: bus type - * @start: Device to begin with - * @name: name of the device to match - * - * This is similar to the bus_find_device() function above, but it handles - * searching by a name automatically, no need to write another strcmp matching - * function. - */ -struct device *bus_find_device_by_name(struct bus_type *bus, - struct device *start, const char *name) -{ - return bus_find_device(bus, start, (void *)name, match_name); -} -EXPORT_SYMBOL_GPL(bus_find_device_by_name); - /** * subsys_find_device_by_id - find a device with a specific enumeration number * @subsys: subsystem diff --git a/drivers/base/core.c b/drivers/base/core.c index da84a73f2ba6..fb83647d685a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3357,6 +3357,12 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) } EXPORT_SYMBOL_GPL(device_set_of_node_from_dev); +int device_match_name(struct device *dev, const void *name) +{ + return sysfs_streq(dev_name(dev), name); +} +EXPORT_SYMBOL_GPL(device_match_name); + int device_match_of_node(struct device *dev, const void *np) { return dev->of_node == np; diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index e55b902560de..2b6bd42632e8 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -89,13 +89,6 @@ static struct class stm_class = { .dev_groups = stm_groups, }; -static int stm_dev_match(struct device *dev, const void *data) -{ - const char *name = data; - - return sysfs_streq(name, dev_name(dev)); -} - /** * stm_find_device() - find stm device by name * @buf: character buffer containing the name @@ -116,7 +109,7 @@ struct stm_device *stm_find_device(const char *buf) if (!stm_core_up) return NULL; - dev = class_find_device(&stm_class, NULL, buf, stm_dev_match); + dev = class_find_device_by_name(&stm_class, buf); if (!dev) return NULL; diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..d54c8e4d8954 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -213,13 +213,6 @@ static int led_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); -static int match_name(struct device *dev, const void *data) -{ - if (!dev_name(dev)) - return 0; - return !strcmp(dev_name(dev), (char *)data); -} - static int led_classdev_next_name(const char *init_name, char *name, size_t len) { @@ -230,7 +223,7 @@ static int led_classdev_next_name(const char *init_name, char *name, strlcpy(name, init_name, len); while ((ret < len) && - (dev = class_find_device(leds_class, NULL, name, match_name))) { + (dev = class_find_device_by_name(leds_class, name))) { put_device(dev); ret = snprintf(name, len, "%s_%u", init_name, ++i); } diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 72b7ddc43116..c93ef33b01d3 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -663,21 +663,12 @@ void rtc_update_irq(struct rtc_device *rtc, } EXPORT_SYMBOL_GPL(rtc_update_irq); -static int __rtc_match(struct device *dev, const void *data) -{ - const char *name = data; - - if (strcmp(dev_name(dev), name) == 0) - return 1; - return 0; -} - struct rtc_device *rtc_class_open(const char *name) { struct device *dev; struct rtc_device *rtc = NULL; - dev = class_find_device(rtc_class, NULL, name, __rtc_match); + dev = class_find_device_by_name(rtc_class, name); if (dev) rtc = to_rtc_device(dev); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index c522e9313c50..d843e362c167 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -608,13 +608,6 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) } EXPORT_SYMBOL(ccwgroup_driver_unregister); -static int __ccwgroupdev_check_busid(struct device *dev, const void *id) -{ - const char *bus_id = id; - - return (strcmp(bus_id, dev_name(dev)) == 0); -} - /** * get_ccwgroupdev_by_busid() - obtain device from a bus id * @gdrv: driver the device is owned by @@ -631,8 +624,7 @@ struct ccwgroup_device *get_ccwgroupdev_by_busid(struct ccwgroup_driver *gdrv, { struct device *dev; - dev = driver_find_device(&gdrv->driver, NULL, bus_id, - __ccwgroupdev_check_busid); + dev = driver_find_device_by_name(&gdrv->driver, bus_id); return dev ? to_ccwgroupdev(dev) : NULL; } diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index c421899be20f..131430bd48d9 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1695,18 +1695,6 @@ int ccw_device_force_console(struct ccw_device *cdev) EXPORT_SYMBOL_GPL(ccw_device_force_console); #endif -/* - * get ccw_device matching the busid, but only if owned by cdrv - */ -static int -__ccwdev_check_busid(struct device *dev, const void *id) -{ - const char *bus_id = id; - - return (strcmp(bus_id, dev_name(dev)) == 0); -} - - /** * get_ccwdev_by_busid() - obtain device from a bus id * @cdrv: driver the device is owned by @@ -1723,8 +1711,7 @@ struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, { struct device *dev; - dev = driver_find_device(&cdrv->driver, NULL, (void *)bus_id, - __ccwdev_check_busid); + dev = driver_find_device_by_name(&cdrv->driver, bus_id); return dev ? to_ccwdev(dev) : NULL; } diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 1058b4b5cc1e..38a5a47b8c9c 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -133,12 +133,6 @@ struct zcdn_device { static int zcdn_create(const char *name); static int zcdn_destroy(const char *name); -/* helper function, matches the name for find_zcdndev_by_name() */ -static int __match_zcdn_name(struct device *dev, const void *data) -{ - return strcmp(dev_name(dev), (const char *)data) == 0; -} - /* helper function, matches the devt value for find_zcdndev_by_devt() */ static int __match_zcdn_devt(struct device *dev, const void *data) { @@ -152,10 +146,7 @@ static int __match_zcdn_devt(struct device *dev, const void *data) */ static inline struct zcdn_device *find_zcdndev_by_name(const char *name) { - struct device *dev = - class_find_device(zcrypt_class, NULL, - (void *) name, - __match_zcdn_name); + struct device *dev = class_find_device_by_name(zcrypt_class, name); return dev ? to_zcdn_dev(dev) : NULL; } diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 86defca6623e..c8efe60e2465 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -90,11 +90,6 @@ static int switch_fwnode_match(struct device *dev, const void *fwnode) return dev_fwnode(dev) == fwnode; } -static int switch_name_match(struct device *dev, const void *name) -{ - return !strcmp((const char *)name, dev_name(dev)); -} - static void *usb_role_switch_match(struct device_connection *con, int ep, void *data) { @@ -107,8 +102,7 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, dev = class_find_device(role_class, NULL, con->fwnode, switch_fwnode_match); } else { - dev = class_find_device(role_class, NULL, con->endpoint[ep], - switch_name_match); + dev = class_find_device_by_name(role_class, con->endpoint[ep]); } return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index a18285a990a8..9b0d15b487e5 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -210,11 +210,6 @@ static int typec_port_fwnode_match(struct device *dev, const void *fwnode) return dev_fwnode(dev) == fwnode; } -static int typec_port_name_match(struct device *dev, const void *name) -{ - return !strcmp((const char *)name, dev_name(dev)); -} - static void *typec_port_match(struct device_connection *con, int ep, void *data) { struct device *dev; @@ -227,8 +222,7 @@ static void *typec_port_match(struct device_connection *con, int ep, void *data) return class_find_device(typec_class, NULL, con->fwnode, typec_port_fwnode_match); - dev = class_find_device(typec_class, NULL, con->endpoint[ep], - typec_port_name_match); + dev = class_find_device_by_name(typec_class, con->endpoint[ep]); return dev ? dev : ERR_PTR(-EPROBE_DEFER); } diff --git a/include/linux/device.h b/include/linux/device.h index c330b75c6c57..3ba376b8b456 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -164,6 +164,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); void subsys_dev_iter_exit(struct subsys_dev_iter *iter); +int device_match_name(struct device *dev, const void *name); int device_match_of_node(struct device *dev, const void *np); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, @@ -171,9 +172,20 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, struct device *bus_find_device(struct bus_type *bus, struct device *start, const void *data, int (*match)(struct device *dev, const void *data)); -struct device *bus_find_device_by_name(struct bus_type *bus, - struct device *start, - const char *name); +/** + * bus_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @bus: bus type + * @start: Device to begin with + * @name: name of the device to match + */ +static inline struct device *bus_find_device_by_name(struct bus_type *bus, + struct device *start, + const char *name) +{ + return bus_find_device(bus, start, name, device_match_name); +} + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -342,6 +354,18 @@ struct device *driver_find_device(struct device_driver *drv, struct device *start, const void *data, int (*match)(struct device *dev, const void *data)); +/** + * driver_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @driver: the driver we're iterating + * @name: name of the device to match + */ +static inline struct device *driver_find_device_by_name(struct device_driver *drv, + const char *name) +{ + return driver_find_device(drv, NULL, name, device_match_name); +} + void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); int driver_deferred_probe_check_state_continue(struct device *dev); @@ -471,6 +495,18 @@ extern struct device *class_find_device(struct class *class, struct device *start, const void *data, int (*match)(struct device *, const void *)); +/** + * class_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @class: class type + * @name: name of the device to match + */ +static inline struct device *class_find_device_by_name(struct class *class, + const char *name) +{ + return class_find_device(class, NULL, name, device_match_name); +} + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index 60b7ac56a1f5..de259b5170ab 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c @@ -23,11 +23,6 @@ LIST_HEAD(cfg802154_rdev_list); int cfg802154_rdev_list_generation; -static int wpan_phy_match(struct device *dev, const void *data) -{ - return !strcmp(dev_name(dev), (const char *)data); -} - struct wpan_phy *wpan_phy_find(const char *str) { struct device *dev; @@ -35,7 +30,7 @@ struct wpan_phy *wpan_phy_find(const char *str) if (WARN_ON(!str)) return NULL; - dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match); + dev = class_find_device_by_name(&wpan_phy_class, str); if (!dev) return NULL; -- GitLab From cfba5de9b99f8bbb8b4ea11b3049784e78b8759b Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:33 +0100 Subject: [PATCH 1267/7155] drivers: Introduce device lookup variants by of_node Introduce wrappers for {bus/driver/class}_find_device() to locate devices by its of_node. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: dri-devel@lists.freedesktop.org Cc: David Airlie Cc: Daniel Vetter Cc: devicetree@vger.kernel.org Cc: Florian Fainelli Cc: Frank Rowand Cc: Heiko Stuebner Cc: Liam Girdwood Cc: linux-i2c@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-spi@vger.kernel.org Cc: Mathieu Poirier Cc: Rob Herring Cc: Srinivas Kandagatla Cc: Takashi Iwai Cc: Alan Tull Cc: linux-fpga@vger.kernel.org Cc: Peter Rosin Cc: Florian Fainelli Cc: Heiner Kallweit Cc: "David S. Miller" Cc: Andrew Lunn Cc: Liam Girdwood Cc: "Rafael J. Wysocki" Cc: Thor Thayer Cc: Jiri Slaby Cc: Andrew Lunn Cc: Peter Rosin Signed-off-by: Suzuki K Poulose Acked-by: Lee Jones Acked-by: Wolfram Sang # I2C part Acked-by: Moritz Fischer # For FPGA part Acked-by: Mark Brown Link: https://lore.kernel.org/r/20190723221838.12024-3-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/amba/tegra-ahb.c | 11 +------- drivers/fpga/fpga-bridge.c | 8 +----- drivers/fpga/fpga-mgr.c | 8 +----- drivers/gpu/drm/drm_mipi_dsi.c | 7 +---- drivers/i2c/i2c-core-of.c | 7 +---- drivers/mfd/altera-sysmgr.c | 14 ++-------- drivers/mux/core.c | 7 +---- drivers/net/phy/mdio_bus.c | 9 +------ drivers/nvmem/core.c | 7 +---- drivers/of/of_mdio.c | 8 +----- drivers/of/platform.c | 7 +---- drivers/regulator/of_regulator.c | 7 +---- drivers/spi/spi.c | 20 +++------------ include/linux/device.h | 37 +++++++++++++++++++++++++++ sound/soc/rockchip/rk3399_gru_sound.c | 9 ++----- 15 files changed, 56 insertions(+), 110 deletions(-) diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index aa64eece77a6..57d3b2e2d007 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c @@ -134,22 +134,13 @@ static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset) } #ifdef CONFIG_TEGRA_IOMMU_SMMU -static int tegra_ahb_match_by_smmu(struct device *dev, const void *data) -{ - struct tegra_ahb *ahb = dev_get_drvdata(dev); - const struct device_node *dn = data; - - return (ahb->dev->of_node == dn) ? 1 : 0; -} - int tegra_ahb_enable_smmu(struct device_node *dn) { struct device *dev; u32 val; struct tegra_ahb *ahb; - dev = driver_find_device(&tegra_ahb_driver.driver, NULL, dn, - tegra_ahb_match_by_smmu); + dev = driver_find_device_by_of_node(&tegra_ahb_driver.driver, dn); if (!dev) return -EPROBE_DEFER; ahb = dev_get_drvdata(dev); diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 80bd8f1b2aa6..4bab9028940a 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -19,11 +19,6 @@ static struct class *fpga_bridge_class; /* Lock for adding/removing bridges to linked lists*/ static spinlock_t bridge_list_lock; -static int fpga_bridge_of_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /** * fpga_bridge_enable - Enable transactions on the bridge * @@ -104,8 +99,7 @@ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, { struct device *dev; - dev = class_find_device(fpga_bridge_class, NULL, np, - fpga_bridge_of_node_match); + dev = class_find_device_by_of_node(fpga_bridge_class, np); if (!dev) return ERR_PTR(-ENODEV); diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index c3866816456a..e05104f5e40c 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -482,11 +482,6 @@ struct fpga_manager *fpga_mgr_get(struct device *dev) } EXPORT_SYMBOL_GPL(fpga_mgr_get); -static int fpga_mgr_of_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /** * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. * @@ -498,8 +493,7 @@ struct fpga_manager *of_fpga_mgr_get(struct device_node *node) { struct device *dev; - dev = class_find_device(fpga_mgr_class, NULL, node, - fpga_mgr_of_node_match); + dev = class_find_device_by_of_node(fpga_mgr_class, node); if (!dev) return ERR_PTR(-ENODEV); diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index ad19df0686c9..bd2498bbd74a 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -93,11 +93,6 @@ static struct bus_type mipi_dsi_bus_type = { .pm = &mipi_dsi_device_pm_ops, }; -static int of_device_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /** * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a * device tree node @@ -110,7 +105,7 @@ struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np) { struct device *dev; - dev = bus_find_device(&mipi_dsi_bus_type, NULL, np, of_device_match); + dev = bus_find_device_by_of_node(&mipi_dsi_bus_type, np); return dev ? to_mipi_dsi_device(dev) : NULL; } diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index d1c48dec7118..6f632d543fcc 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -113,11 +113,6 @@ void of_i2c_register_devices(struct i2c_adapter *adap) of_node_put(bus); } -static int of_dev_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - static int of_dev_or_parent_node_match(struct device *dev, const void *data) { if (dev->of_node == data) @@ -135,7 +130,7 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) struct device *dev; struct i2c_client *client; - dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); + dev = bus_find_device_by_of_node(&i2c_bus_type, node); if (!dev) return NULL; diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index 2ee14d8a6d31..d2a13a547a3c 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -87,16 +87,6 @@ static struct regmap_config altr_sysmgr_regmap_cfg = { .use_single_write = true, }; -/** - * sysmgr_match_phandle - * Matching function used by driver_find_device(). - * Return: True if match is found, otherwise false. - */ -static int sysmgr_match_phandle(struct device *dev, const void *data) -{ - return dev->of_node == (const struct device_node *)data; -} - /** * altr_sysmgr_regmap_lookup_by_phandle * Find the sysmgr previous configured in probe() and return regmap property. @@ -117,8 +107,8 @@ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, if (!sysmgr_np) return ERR_PTR(-ENODEV); - dev = driver_find_device(&altr_sysmgr_driver.driver, NULL, - (void *)sysmgr_np, sysmgr_match_phandle); + dev = driver_find_device_by_of_node(&altr_sysmgr_driver.driver, + (void *)sysmgr_np); of_node_put(sysmgr_np); if (!dev) return ERR_PTR(-EPROBE_DEFER); diff --git a/drivers/mux/core.c b/drivers/mux/core.c index d1271c1ee23c..1fb22388e7e0 100644 --- a/drivers/mux/core.c +++ b/drivers/mux/core.c @@ -405,17 +405,12 @@ int mux_control_deselect(struct mux_control *mux) } EXPORT_SYMBOL_GPL(mux_control_deselect); -static int of_dev_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /* Note this function returns a reference to the mux_chip dev. */ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np) { struct device *dev; - dev = class_find_device(&mux_class, NULL, np, of_dev_node_match); + dev = class_find_device_by_of_node(&mux_class, np); return dev ? to_mux_chip(dev) : NULL; } diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index bd04fe762056..ce940871331e 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -262,11 +262,6 @@ static struct class mdio_bus_class = { }; #if IS_ENABLED(CONFIG_OF_MDIO) -/* Helper function for of_mdio_find_bus */ -static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np) -{ - return dev->of_node == mdio_bus_np; -} /** * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. * @mdio_bus_np: Pointer to the mii_bus. @@ -287,9 +282,7 @@ struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np) if (!mdio_bus_np) return NULL; - d = class_find_device(&mdio_bus_class, NULL, mdio_bus_np, - of_mdio_bus_match); - + d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np); return d ? to_mii_bus(d) : NULL; } EXPORT_SYMBOL(of_mdio_find_bus); diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ac5d945be88a..057d1ff87d5d 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -76,11 +76,6 @@ static struct bus_type nvmem_bus_type = { .name = "nvmem", }; -static int of_nvmem_match(struct device *dev, const void *nvmem_np) -{ - return dev->of_node == nvmem_np; -} - static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np) { struct device *d; @@ -88,7 +83,7 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np) if (!nvmem_np) return NULL; - d = bus_find_device(&nvmem_bus_type, NULL, nvmem_np, of_nvmem_match); + d = bus_find_device_by_of_node(&nvmem_bus_type, nvmem_np); if (!d) return NULL; diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 44f53496cab1..000b95787df1 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -280,12 +280,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) } EXPORT_SYMBOL(of_mdiobus_register); -/* Helper function for of_phy_find_device */ -static int of_phy_match(struct device *dev, const void *phy_np) -{ - return dev->of_node == phy_np; -} - /** * of_phy_find_device - Give a PHY node, find the phy_device * @phy_np: Pointer to the phy's device tree node @@ -301,7 +295,7 @@ struct phy_device *of_phy_find_device(struct device_node *phy_np) if (!phy_np) return NULL; - d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); + d = bus_find_device_by_of_node(&mdio_bus_type, phy_np); if (d) { mdiodev = to_mdio_device(d); if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 7801e25e6895..b47a2292fe8e 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -37,11 +37,6 @@ static const struct of_device_id of_skipped_node_table[] = { {} /* Empty terminated list */ }; -static int of_dev_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /** * of_find_device_by_node - Find the platform_device associated with a node * @np: Pointer to device tree node @@ -55,7 +50,7 @@ struct platform_device *of_find_device_by_node(struct device_node *np) { struct device *dev; - dev = bus_find_device(&platform_bus_type, NULL, np, of_dev_node_match); + dev = bus_find_device_by_of_node(&platform_bus_type, np); return dev ? to_platform_device(dev) : NULL; } EXPORT_SYMBOL(of_find_device_by_node); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 397918ebba55..20dcc9c03adc 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -460,16 +460,11 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, return NULL; } -static int of_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - struct regulator_dev *of_find_regulator_by_node(struct device_node *np) { struct device *dev; - dev = class_find_device(®ulator_class, NULL, np, of_node_match); + dev = class_find_device_by_of_node(®ulator_class, np); return dev ? dev_to_rdev(dev) : NULL; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 75ac046cae52..a591da87981a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3652,37 +3652,25 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_OF) -static int __spi_of_device_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /* must call put_device() when done with returned spi_device device */ struct spi_device *of_find_spi_device_by_node(struct device_node *node) { - struct device *dev = bus_find_device(&spi_bus_type, NULL, node, - __spi_of_device_match); + struct device *dev = bus_find_device_by_of_node(&spi_bus_type, node); + return dev ? to_spi_device(dev) : NULL; } EXPORT_SYMBOL_GPL(of_find_spi_device_by_node); #endif /* IS_ENABLED(CONFIG_OF) */ #if IS_ENABLED(CONFIG_OF_DYNAMIC) -static int __spi_of_controller_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /* the spi controllers are not using spi_bus, so we find it with another way */ static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) { struct device *dev; - dev = class_find_device(&spi_master_class, NULL, node, - __spi_of_controller_match); + dev = class_find_device_by_of_node(&spi_master_class, node); if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) - dev = class_find_device(&spi_slave_class, NULL, node, - __spi_of_controller_match); + dev = class_find_device_by_of_node(&spi_slave_class, node); if (!dev) return NULL; diff --git a/include/linux/device.h b/include/linux/device.h index 3ba376b8b456..29d8d7ad41e6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -186,6 +186,18 @@ static inline struct device *bus_find_device_by_name(struct bus_type *bus, return bus_find_device(bus, start, name, device_match_name); } +/** + * bus_find_device_by_of_node : device iterator for locating a particular device + * matching the of_node. + * @bus: bus type + * @np: of_node of the device to match. + */ +static inline struct device * +bus_find_device_by_of_node(struct bus_type *bus, const struct device_node *np) +{ + return bus_find_device(bus, NULL, np, device_match_of_node); +} + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -366,6 +378,19 @@ static inline struct device *driver_find_device_by_name(struct device_driver *dr return driver_find_device(drv, NULL, name, device_match_name); } +/** + * driver_find_device_by_of_node- device iterator for locating a particular device + * by of_node pointer. + * @driver: the driver we're iterating + * @np: of_node pointer to match. + */ +static inline struct device * +driver_find_device_by_of_node(struct device_driver *drv, + const struct device_node *np) +{ + return driver_find_device(drv, NULL, np, device_match_of_node); +} + void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); int driver_deferred_probe_check_state_continue(struct device *dev); @@ -507,6 +532,18 @@ static inline struct device *class_find_device_by_name(struct class *class, return class_find_device(class, NULL, name, device_match_name); } +/** + * class_find_device_by_of_node : device iterator for locating a particular device + * matching the of_node. + * @class: class type + * @np: of_node of the device to match. + */ +static inline struct device * +class_find_device_by_of_node(struct class *class, const struct device_node *np) +{ + return class_find_device(class, NULL, np, device_match_of_node); +} + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index c16b0ffe8cfc..d951100bf770 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -422,11 +422,6 @@ static const struct dailink_match_data dailink_match[] = { }, }; -static int of_dev_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - static int rockchip_sound_codec_node_match(struct device_node *np_codec) { struct device *dev; @@ -438,8 +433,8 @@ static int rockchip_sound_codec_node_match(struct device_node *np_codec) continue; if (dailink_match[i].bus_type) { - dev = bus_find_device(dailink_match[i].bus_type, NULL, - np_codec, of_dev_node_match); + dev = bus_find_device_by_of_node(dailink_match[i].bus_type, + np_codec); if (!dev) continue; put_device(dev); -- GitLab From 67843bbaf36eb087714f40e783ee78e99e9e4b86 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:34 +0100 Subject: [PATCH 1268/7155] drivers: Introduce device lookup variants by fwnode Add a helper to match the firmware node handle of a device and provide wrappers for {bus/class/driver}_find_device() APIs to avoid proliferation of duplicate custom match functions. Cc: "David S. Miller" Cc: Doug Ledford Cc: Jason Gunthorpe Cc: linux-usb@vger.kernel.org Cc: "Rafael J. Wysocki" Cc: Ulf Hansson Cc: Joe Perches Cc: Will Deacon Cc: Joerg Roedel Signed-off-by: Suzuki K Poulose Acked-by: Robin Murphy Reviewed-by: Mathieu Poirier Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20190723221838.12024-4-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 +++ drivers/base/devcon.c | 8 +--- .../hwtracing/coresight/coresight-platform.c | 11 +----- drivers/hwtracing/coresight/coresight-priv.h | 2 - drivers/hwtracing/coresight/coresight.c | 4 +- drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 8 +--- drivers/iommu/arm-smmu-v3.c | 9 +---- drivers/iommu/arm-smmu.c | 9 +---- .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 8 +--- drivers/usb/roles/class.c | 8 +--- drivers/usb/typec/class.c | 8 +--- include/linux/device.h | 39 +++++++++++++++++++ 12 files changed, 57 insertions(+), 63 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index fb83647d685a..e8f81a667545 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3368,3 +3368,9 @@ int device_match_of_node(struct device *dev, const void *np) return dev->of_node == np; } EXPORT_SYMBOL_GPL(device_match_of_node); + +int device_match_fwnode(struct device *dev, const void *fwnode) +{ + return dev_fwnode(dev) == fwnode; +} +EXPORT_SYMBOL_GPL(device_match_fwnode); diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index 09f28479b243..1d488dc5dd0c 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -133,19 +133,13 @@ static struct bus_type *generic_match_buses[] = { NULL, }; -static int device_fwnode_match(struct device *dev, const void *fwnode) -{ - return dev_fwnode(dev) == fwnode; -} - static void *device_connection_fwnode_match(struct device_connection *con) { struct bus_type *bus; struct device *dev; for (bus = generic_match_buses[0]; bus; bus++) { - dev = bus_find_device(bus, NULL, (void *)con->fwnode, - device_fwnode_match); + dev = bus_find_device_by_fwnode(bus, con->fwnode); if (dev && !strncmp(dev_name(dev), con->id, strlen(con->id))) return dev; diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index dad7d96c5943..3c5bee429105 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -37,11 +37,6 @@ static int coresight_alloc_conns(struct device *dev, return 0; } -int coresight_device_fwnode_match(struct device *dev, const void *fwnode) -{ - return dev_fwnode(dev) == fwnode; -} - static struct device * coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) { @@ -51,8 +46,7 @@ coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) * If we have a non-configurable replicator, it will be found on the * platform bus. */ - dev = bus_find_device(&platform_bus_type, NULL, - fwnode, coresight_device_fwnode_match); + dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode); if (dev) return dev; @@ -60,8 +54,7 @@ coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) * We have a configurable component - circle through the AMBA bus * looking for the device that matches the endpoint node. */ - return bus_find_device(&amba_bustype, NULL, - fwnode, coresight_device_fwnode_match); + return bus_find_device_by_fwnode(&amba_bustype, fwnode); } #ifdef CONFIG_OF diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 7d401790dd7e..61d7f9ff054d 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -202,6 +202,4 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) void coresight_release_platform_data(struct coresight_platform_data *pdata); -int coresight_device_fwnode_match(struct device *dev, const void *fwnode); - #endif diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 55db77f6410b..6453c67a4d01 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1046,9 +1046,7 @@ static void coresight_fixup_device_conns(struct coresight_device *csdev) struct coresight_connection *conn = &csdev->pdata->conns[i]; struct device *dev = NULL; - dev = bus_find_device(&coresight_bustype, NULL, - (void *)conn->child_fwnode, - coresight_device_fwnode_match); + dev = bus_find_device_by_fwnode(&coresight_bustype, conn->child_fwnode); if (dev) { conn->child_dev = to_coresight_device(dev); /* and put reference from 'bus_find_device()' */ diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c index 81e6dedb1e02..fa05e943038a 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c @@ -4499,19 +4499,13 @@ static const struct acpi_device_id hns_roce_acpi_match[] = { }; MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match); -static int hns_roce_node_match(struct device *dev, const void *fwnode) -{ - return dev->fwnode == fwnode; -} - static struct platform_device *hns_roce_find_pdev(struct fwnode_handle *fwnode) { struct device *dev; /* get the 'device' corresponding to the matching 'fwnode' */ - dev = bus_find_device(&platform_bus_type, NULL, - fwnode, hns_roce_node_match); + dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode); /* get the platform device */ return dev ? to_platform_device(dev) : NULL; } diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index a9a9fabd3968..6f0e13fa5e1a 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2034,16 +2034,11 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) static struct platform_driver arm_smmu_driver; -static int arm_smmu_match_node(struct device *dev, const void *data) -{ - return dev->fwnode == data; -} - static struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode) { - struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL, - fwnode, arm_smmu_match_node); + struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver, + fwnode); put_device(dev); return dev ? dev_get_drvdata(dev) : NULL; } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 64977c131ee6..aa06498f291d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1426,16 +1426,11 @@ static bool arm_smmu_capable(enum iommu_cap cap) } } -static int arm_smmu_match_node(struct device *dev, const void *data) -{ - return dev->fwnode == data; -} - static struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode) { - struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL, - fwnode, arm_smmu_match_node); + struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver, + fwnode); put_device(dev); return dev ? dev_get_drvdata(dev) : NULL; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index bb6586d0e5af..ed3829ae4ef1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -754,17 +754,11 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) return (void *)misc_op; } -static int hns_dsaf_dev_match(struct device *dev, const void *fwnode) -{ - return dev->fwnode == fwnode; -} - struct platform_device *hns_dsaf_find_platform_device(struct fwnode_handle *fwnode) { struct device *dev; - dev = bus_find_device(&platform_bus_type, NULL, - fwnode, hns_dsaf_dev_match); + dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode); return dev ? to_platform_device(dev) : NULL; } diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index c8efe60e2465..0526efbc4922 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -85,11 +85,6 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) } EXPORT_SYMBOL_GPL(usb_role_switch_get_role); -static int switch_fwnode_match(struct device *dev, const void *fwnode) -{ - return dev_fwnode(dev) == fwnode; -} - static void *usb_role_switch_match(struct device_connection *con, int ep, void *data) { @@ -99,8 +94,7 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, if (con->id && !fwnode_property_present(con->fwnode, con->id)) return NULL; - dev = class_find_device(role_class, NULL, con->fwnode, - switch_fwnode_match); + dev = class_find_device_by_fwnode(role_class, con->fwnode); } else { dev = class_find_device_by_name(role_class, con->endpoint[ep]); } diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 9b0d15b487e5..94a3eda62add 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -205,11 +205,6 @@ static void typec_altmode_put_partner(struct altmode *altmode) put_device(&adev->dev); } -static int typec_port_fwnode_match(struct device *dev, const void *fwnode) -{ - return dev_fwnode(dev) == fwnode; -} - static void *typec_port_match(struct device_connection *con, int ep, void *data) { struct device *dev; @@ -219,8 +214,7 @@ static void *typec_port_match(struct device_connection *con, int ep, void *data) * we need to return ERR_PTR(-PROBE_DEFER) when there is no device. */ if (con->fwnode) - return class_find_device(typec_class, NULL, con->fwnode, - typec_port_fwnode_match); + return class_find_device_by_fwnode(typec_class, con->fwnode); dev = class_find_device_by_name(typec_class, con->endpoint[ep]); diff --git a/include/linux/device.h b/include/linux/device.h index 29d8d7ad41e6..7133fc1c285d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -166,6 +166,7 @@ void subsys_dev_iter_exit(struct subsys_dev_iter *iter); int device_match_name(struct device *dev, const void *name); int device_match_of_node(struct device *dev, const void *np); +int device_match_fwnode(struct device *dev, const void *fwnode); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -198,6 +199,18 @@ bus_find_device_by_of_node(struct bus_type *bus, const struct device_node *np) return bus_find_device(bus, NULL, np, device_match_of_node); } +/** + * bus_find_device_by_fwnode : device iterator for locating a particular device + * matching the fwnode. + * @bus: bus type + * @fwnode: fwnode of the device to match. + */ +static inline struct device * +bus_find_device_by_fwnode(struct bus_type *bus, const struct fwnode_handle *fwnode) +{ + return bus_find_device(bus, NULL, fwnode, device_match_fwnode); +} + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -391,6 +404,19 @@ driver_find_device_by_of_node(struct device_driver *drv, return driver_find_device(drv, NULL, np, device_match_of_node); } +/** + * driver_find_device_by_fwnode- device iterator for locating a particular device + * by fwnode pointer. + * @driver: the driver we're iterating + * @fwnode: fwnode pointer to match. + */ +static inline struct device * +driver_find_device_by_fwnode(struct device_driver *drv, + const struct fwnode_handle *fwnode) +{ + return driver_find_device(drv, NULL, fwnode, device_match_fwnode); +} + void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); int driver_deferred_probe_check_state_continue(struct device *dev); @@ -544,6 +570,19 @@ class_find_device_by_of_node(struct class *class, const struct device_node *np) return class_find_device(class, NULL, np, device_match_of_node); } +/** + * class_find_device_by_fwnode : device iterator for locating a particular device + * matching the fwnode. + * @class: class type + * @fwnode: fwnode of the device to match. + */ +static inline struct device * +class_find_device_by_fwnode(struct class *class, + const struct fwnode_handle *fwnode) +{ + return class_find_device(class, NULL, fwnode, device_match_fwnode); +} + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, -- GitLab From 4495dfdd6193d9712b7b8f5d699d89d5996e6aaa Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:35 +0100 Subject: [PATCH 1269/7155] drivers: Introduce device lookup variants by device type Add a helper to match a device by its type and provide wrappers for {bus/class/driver}_find_device() APIs. Cc: Alexander Shishkin Cc: Arnd Bergmann Cc: Harald Freudenberger Cc: Heiko Carstens Cc: linux-usb@vger.kernel.org Cc: Oliver Neukum Cc: Sebastian Andrzej Siewior Cc: Tomas Winkler Cc: "Rafael J. Wysocki" Cc: Greg Kroah-Hartman Cc: Ulf Hansson Cc: Joe Perches Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190723221838.12024-5-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 15 ++++++------- drivers/hwtracing/intel_th/core.c | 10 +-------- drivers/misc/mei/main.c | 9 +------- drivers/s390/crypto/zcrypt_api.c | 11 +-------- drivers/tty/tty_io.c | 8 +------ drivers/usb/core/devio.c | 8 +------ include/linux/device.h | 37 +++++++++++++++++++++++++++++++ 7 files changed, 49 insertions(+), 49 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index e8f81a667545..3abc32b60c0a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2867,13 +2867,6 @@ struct device *device_create_with_groups(struct class *class, } EXPORT_SYMBOL_GPL(device_create_with_groups); -static int __match_devt(struct device *dev, const void *data) -{ - const dev_t *devt = data; - - return dev->devt == *devt; -} - /** * device_destroy - removes a device that was created with device_create() * @class: pointer to the struct class that this device was registered with @@ -2886,7 +2879,7 @@ void device_destroy(struct class *class, dev_t devt) { struct device *dev; - dev = class_find_device(class, NULL, &devt, __match_devt); + dev = class_find_device_by_devt(class, devt); if (dev) { put_device(dev); device_unregister(dev); @@ -3374,3 +3367,9 @@ int device_match_fwnode(struct device *dev, const void *fwnode) return dev_fwnode(dev) == fwnode; } EXPORT_SYMBOL_GPL(device_match_fwnode); + +int device_match_devt(struct device *dev, const void *pdevt) +{ + return dev->devt == *(dev_t *)pdevt; +} +EXPORT_SYMBOL_GPL(device_match_devt); diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 55922896d862..d5c1821b31c6 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -789,12 +789,6 @@ static int intel_th_populate(struct intel_th *th) return 0; } -static int match_devt(struct device *dev, const void *data) -{ - dev_t devt = (dev_t)(unsigned long)(void *)data; - return dev->devt == devt; -} - static int intel_th_output_open(struct inode *inode, struct file *file) { const struct file_operations *fops; @@ -802,9 +796,7 @@ static int intel_th_output_open(struct inode *inode, struct file *file) struct device *dev; int err; - dev = bus_find_device(&intel_th_bus, NULL, - (void *)(unsigned long)inode->i_rdev, - match_devt); + dev = bus_find_device_by_devt(&intel_th_bus, inode->i_rdev); if (!dev || !dev->driver) return -ENODEV; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index f894d1f8a53e..7310b476323c 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -858,13 +858,6 @@ static ssize_t dev_state_show(struct device *device, } static DEVICE_ATTR_RO(dev_state); -static int match_devt(struct device *dev, const void *data) -{ - const dev_t *devt = data; - - return dev->devt == *devt; -} - /** * dev_set_devstate: set to new device state and notify sysfs file. * @@ -880,7 +873,7 @@ void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state) dev->dev_state = state; - clsdev = class_find_device(mei_class, NULL, &dev->cdev.dev, match_devt); + clsdev = class_find_device_by_devt(mei_class, dev->cdev.dev); if (clsdev) { sysfs_notify(&clsdev->kobj, NULL, "dev_state"); put_device(clsdev); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 38a5a47b8c9c..150f6236c9bb 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -133,12 +133,6 @@ struct zcdn_device { static int zcdn_create(const char *name); static int zcdn_destroy(const char *name); -/* helper function, matches the devt value for find_zcdndev_by_devt() */ -static int __match_zcdn_devt(struct device *dev, const void *data) -{ - return dev->devt == *((dev_t *) data); -} - /* * Find zcdn device by name. * Returns reference to the zcdn device which needs to be released @@ -158,10 +152,7 @@ static inline struct zcdn_device *find_zcdndev_by_name(const char *name) */ static inline struct zcdn_device *find_zcdndev_by_devt(dev_t devt) { - struct device *dev = - class_find_device(zcrypt_class, NULL, - (void *) &devt, - __match_zcdn_devt); + struct device *dev = class_find_device_by_devt(zcrypt_class, devt); return dev ? to_zcdn_dev(dev) : NULL; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 566728fbaf3c..802c1210558f 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2952,17 +2952,11 @@ void do_SAK(struct tty_struct *tty) EXPORT_SYMBOL(do_SAK); -static int dev_match_devt(struct device *dev, const void *data) -{ - const dev_t *devt = data; - return dev->devt == *devt; -} - /* Must put_device() after it's unused! */ static struct device *tty_get_device(struct tty_struct *tty) { dev_t devt = tty_devnum(tty); - return class_find_device(tty_class, NULL, &devt, dev_match_devt); + return class_find_device_by_devt(tty_class, devt); } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index b265ab5405f9..60268aee93a8 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -942,17 +942,11 @@ static int parse_usbdevfs_streams(struct usb_dev_state *ps, return ret; } -static int match_devt(struct device *dev, const void *data) -{ - return dev->devt == (dev_t)(unsigned long)(void *)data; -} - static struct usb_device *usbdev_lookup_by_devt(dev_t devt) { struct device *dev; - dev = bus_find_device(&usb_bus_type, NULL, - (void *) (unsigned long) devt, match_devt); + dev = bus_find_device_by_devt(&usb_bus_type, devt); if (!dev) return NULL; return to_usb_device(dev); diff --git a/include/linux/device.h b/include/linux/device.h index 7133fc1c285d..93b2f55ef44e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -167,6 +167,7 @@ void subsys_dev_iter_exit(struct subsys_dev_iter *iter); int device_match_name(struct device *dev, const void *name); int device_match_of_node(struct device *dev, const void *np); int device_match_fwnode(struct device *dev, const void *fwnode); +int device_match_devt(struct device *dev, const void *pdevt); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -211,6 +212,18 @@ bus_find_device_by_fwnode(struct bus_type *bus, const struct fwnode_handle *fwno return bus_find_device(bus, NULL, fwnode, device_match_fwnode); } +/** + * bus_find_device_by_devt : device iterator for locating a particular device + * matching the device type. + * @bus: bus type + * @devt: device type of the device to match. + */ +static inline struct device *bus_find_device_by_devt(struct bus_type *bus, + dev_t devt) +{ + return bus_find_device(bus, NULL, &devt, device_match_devt); +} + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -417,6 +430,18 @@ driver_find_device_by_fwnode(struct device_driver *drv, return driver_find_device(drv, NULL, fwnode, device_match_fwnode); } +/** + * driver_find_device_by_devt- device iterator for locating a particular device + * by devt. + * @driver: the driver we're iterating + * @devt: devt pointer to match. + */ +static inline struct device *driver_find_device_by_devt(struct device_driver *drv, + dev_t devt) +{ + return driver_find_device(drv, NULL, &devt, device_match_devt); +} + void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); int driver_deferred_probe_check_state_continue(struct device *dev); @@ -583,6 +608,18 @@ class_find_device_by_fwnode(struct class *class, return class_find_device(class, NULL, fwnode, device_match_fwnode); } +/** + * class_find_device_by_devt : device iterator for locating a particular device + * matching the device type. + * @class: class type + * @devt: device type of the device to match. + */ +static inline struct device *class_find_device_by_devt(struct class *class, + dev_t devt) +{ + return class_find_device(class, NULL, &devt, device_match_devt); +} + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, -- GitLab From 00500147cbd3fc51353d0d003eaa9d31c72c0d50 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:36 +0100 Subject: [PATCH 1270/7155] drivers: Introduce device lookup variants by ACPI_COMPANION device Add a generic helper to match a device by the ACPI_COMPANION device and provide wrappers for the device lookup APIs. Cc: Len Brown Cc: linux-acpi@vger.kernel.org Cc: linux-spi@vger.kernel.org Cc: Mika Westerberg Cc: linux-i2c@vger.kernel.org Cc: "Rafael J. Wysocki" Signed-off-by: Suzuki K Poulose Acked-by: Mark Brown Acked-by: Wolfram Sang # I2C parts Link: https://lore.kernel.org/r/20190723221838.12024-6-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 ++++ drivers/i2c/i2c-core-acpi.c | 11 ++----- drivers/spi/spi.c | 8 +---- include/linux/device.h | 65 +++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 3abc32b60c0a..57d71bc2c559 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3373,3 +3373,9 @@ int device_match_devt(struct device *dev, const void *pdevt) return dev->devt == *(dev_t *)pdevt; } EXPORT_SYMBOL_GPL(device_match_devt); + +int device_match_acpi_dev(struct device *dev, const void *adev) +{ + return ACPI_COMPANION(dev) == adev; +} +EXPORT_SYMBOL(device_match_acpi_dev); diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 4dbbc9a35f65..bc80aafb521f 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -354,17 +354,11 @@ static int i2c_acpi_find_match_adapter(struct device *dev, const void *data) return ACPI_HANDLE(dev) == (acpi_handle)data; } -static int i2c_acpi_find_match_device(struct device *dev, const void *data) -{ - return ACPI_COMPANION(dev) == data; -} struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) { - struct device *dev; + struct device *dev = bus_find_device_by_acpi_dev(&i2c_bus_type, handle); - dev = bus_find_device(&i2c_bus_type, NULL, handle, - i2c_acpi_find_match_adapter); return dev ? i2c_verify_adapter(dev) : NULL; } EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle); @@ -373,8 +367,7 @@ static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) { struct device *dev; - dev = bus_find_device(&i2c_bus_type, NULL, adev, - i2c_acpi_find_match_device); + dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); return dev ? i2c_verify_client(dev) : NULL; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a591da87981a..c486a6f84c2c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3741,11 +3741,6 @@ static int spi_acpi_controller_match(struct device *dev, const void *data) return ACPI_COMPANION(dev->parent) == data; } -static int spi_acpi_device_match(struct device *dev, const void *data) -{ - return ACPI_COMPANION(dev) == data; -} - static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) { struct device *dev; @@ -3765,8 +3760,7 @@ static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev) { struct device *dev; - dev = bus_find_device(&spi_bus_type, NULL, adev, spi_acpi_device_match); - + dev = bus_find_device_by_acpi_dev(&spi_bus_type, adev); return dev ? to_spi_device(dev) : NULL; } diff --git a/include/linux/device.h b/include/linux/device.h index 93b2f55ef44e..7514ef3d3f1a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -168,6 +168,7 @@ int device_match_name(struct device *dev, const void *name); int device_match_of_node(struct device *dev, const void *np); int device_match_fwnode(struct device *dev, const void *fwnode); int device_match_devt(struct device *dev, const void *pdevt); +int device_match_acpi_dev(struct device *dev, const void *adev); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -224,6 +225,28 @@ static inline struct device *bus_find_device_by_devt(struct bus_type *bus, return bus_find_device(bus, NULL, &devt, device_match_devt); } +#ifdef CONFIG_ACPI +struct acpi_device; + +/** + * bus_find_device_by_acpi_dev : device iterator for locating a particular device + * matching the ACPI COMPANION device. + * @bus: bus type + * @adev: ACPI COMPANION device to match. + */ +static inline struct device * +bus_find_device_by_acpi_dev(struct bus_type *bus, const struct acpi_device *adev) +{ + return bus_find_device(bus, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +bus_find_device_by_acpi_dev(struct bus_type *bus, const void *adev) +{ + return NULL; +} +#endif + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -442,6 +465,27 @@ static inline struct device *driver_find_device_by_devt(struct device_driver *dr return driver_find_device(drv, NULL, &devt, device_match_devt); } +#ifdef CONFIG_ACPI +/** + * driver_find_device_by_acpi_dev : device iterator for locating a particular + * device matching the ACPI_COMPANION device. + * @driver: the driver we're iterating + * @adev: ACPI_COMPANION device to match. + */ +static inline struct device * +driver_find_device_by_acpi_dev(struct device_driver *drv, + const struct acpi_device *adev) +{ + return driver_find_device(drv, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) +{ + return NULL; +} +#endif + void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); int driver_deferred_probe_check_state_continue(struct device *dev); @@ -620,6 +664,27 @@ static inline struct device *class_find_device_by_devt(struct class *class, return class_find_device(class, NULL, &devt, device_match_devt); } +#ifdef CONFIG_ACPI +struct acpi_device; +/** + * class_find_device_by_acpi_dev : device iterator for locating a particular + * device matching the ACPI_COMPANION device. + * @class: class type + * @adev: ACPI_COMPANION device to match. + */ +static inline struct device * +class_find_device_by_acpi_dev(struct class *class, const struct acpi_device *adev) +{ + return class_find_device(class, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +class_find_device_by_acpi_dev(struct class *class, const void *adev) +{ + return NULL; +} +#endif + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, -- GitLab From 6bf85ba9e55f659ddc0747bf1bb504ec6d15f525 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:37 +0100 Subject: [PATCH 1271/7155] drivers: Add generic helper to match any device Add a generic helper to match any/all devices. Using this introduce new wrappers {bus/driver/class}_find_next_device(). Cc: Elie Morisse Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: Nehal Shah Cc: "Rafael J. Wysocki" Cc: Shyam Sundar S K Signed-off-by: Suzuki K Poulose Acked-by: Bjorn Helgaas # PCI Link: https://lore.kernel.org/r/20190723221838.12024-7-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 ++++++ drivers/i2c/busses/i2c-amd-mp2-pci.c | 8 +------- drivers/pci/probe.c | 7 +------ drivers/s390/cio/ccwgroup.c | 8 +------- drivers/scsi/scsi_proc.c | 9 ++------- include/linux/device.h | 17 +++++++++++++++++ 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 57d71bc2c559..e22e29b3dc97 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3379,3 +3379,9 @@ int device_match_acpi_dev(struct device *dev, const void *adev) return ACPI_COMPANION(dev) == adev; } EXPORT_SYMBOL(device_match_acpi_dev); + +int device_match_any(struct device *dev, const void *unused) +{ + return 1; +} +EXPORT_SYMBOL_GPL(device_match_any); diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c index c7fe3b44a860..5e4800d72e00 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-pci.c +++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c @@ -457,18 +457,12 @@ static struct pci_driver amd_mp2_pci_driver = { }; module_pci_driver(amd_mp2_pci_driver); -static int amd_mp2_device_match(struct device *dev, const void *data) -{ - return 1; -} - struct amd_mp2_dev *amd_mp2_find_device(void) { struct device *dev; struct pci_dev *pci_dev; - dev = driver_find_device(&amd_mp2_pci_driver.driver, NULL, NULL, - amd_mp2_device_match); + dev = driver_find_next_device(&amd_mp2_pci_driver.driver, NULL); if (!dev) return NULL; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a3c7338fad86..dbeeb385fb9f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -64,11 +64,6 @@ static struct resource *get_pci_domain_busn_res(int domain_nr) return &r->res; } -static int find_anything(struct device *dev, const void *data) -{ - return 1; -} - /* * Some device drivers need know if PCI is initiated. * Basically, we think PCI is not initiated when there @@ -79,7 +74,7 @@ int no_pci_devices(void) struct device *dev; int no_devices; - dev = bus_find_device(&pci_bus_type, NULL, NULL, find_anything); + dev = bus_find_next_device(&pci_bus_type, NULL); no_devices = (dev == NULL); put_device(dev); return no_devices; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index d843e362c167..0005ec9285aa 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -581,11 +581,6 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) } EXPORT_SYMBOL(ccwgroup_driver_register); -static int __ccwgroup_match_all(struct device *dev, const void *data) -{ - return 1; -} - /** * ccwgroup_driver_unregister() - deregister a ccw group driver * @cdriver: driver to be deregistered @@ -597,8 +592,7 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) struct device *dev; /* We don't want ccwgroup devices to live longer than their driver. */ - while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, - __ccwgroup_match_all))) { + while ((dev = driver_find_next_device(&cdriver->driver, NULL))) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); ccwgroup_ungroup(gdev); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index c074631086a4..5b313226f11c 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -372,15 +372,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, return err; } -static int always_match(struct device *dev, const void *data) -{ - return 1; -} - static inline struct device *next_scsi_device(struct device *start) { - struct device *next = bus_find_device(&scsi_bus_type, start, NULL, - always_match); + struct device *next = bus_find_next_device(&scsi_bus_type, start); + put_device(start); return next; } diff --git a/include/linux/device.h b/include/linux/device.h index 7514ef3d3f1a..8ae3f4b47293 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -169,6 +169,7 @@ int device_match_of_node(struct device *dev, const void *np); int device_match_fwnode(struct device *dev, const void *fwnode); int device_match_devt(struct device *dev, const void *pdevt); int device_match_acpi_dev(struct device *dev, const void *adev); +int device_match_any(struct device *dev, const void *unused); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -225,6 +226,16 @@ static inline struct device *bus_find_device_by_devt(struct bus_type *bus, return bus_find_device(bus, NULL, &devt, device_match_devt); } +/** + * bus_find_next_device - Find the next device after a given device in a + * given bus. + */ +static inline struct device * +bus_find_next_device(struct bus_type *bus,struct device *cur) +{ + return bus_find_device(bus, cur, NULL, device_match_any); +} + #ifdef CONFIG_ACPI struct acpi_device; @@ -465,6 +476,12 @@ static inline struct device *driver_find_device_by_devt(struct device_driver *dr return driver_find_device(drv, NULL, &devt, device_match_devt); } +static inline struct device *driver_find_next_device(struct device_driver *drv, + struct device *start) +{ + return driver_find_device(drv, start, NULL, device_match_any); +} + #ifdef CONFIG_ACPI /** * driver_find_device_by_acpi_dev : device iterator for locating a particular -- GitLab From 36f3313d6bff91ab2a9e47698c27d15363640a4e Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Jul 2019 23:18:38 +0100 Subject: [PATCH 1272/7155] platform: Add platform_find_device_by_driver() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide a helper to lookup platform devices by matching device driver in order to avoid drivers trying to use platform bus internals. Cc: Eric Anholt Cc: Greg Kroah-Hartman Cc: "Heiko Stübner" Cc: Inki Dae Cc: "Rafael J. Wysocki" Cc: Sandy Huang Cc: Seung-Woo Kim Tested-by: Heiko Stuebner Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190723221838.12024-8-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 14 ++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 9 +++------ drivers/gpu/drm/mcde/mcde_drv.c | 3 +-- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 3 +-- drivers/gpu/drm/vc4/vc4_drv.c | 3 +-- include/linux/platform_device.h | 3 +++ 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 506a0175a5a7..a174ce5ea17c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1197,6 +1197,20 @@ struct bus_type platform_bus_type = { }; EXPORT_SYMBOL_GPL(platform_bus_type); +/** + * platform_find_device_by_driver - Find a platform device with a given + * driver. + * @start: The device to start the search from. + * @drv: The device driver to look for. + */ +struct device *platform_find_device_by_driver(struct device *start, + const struct device_driver *drv) +{ + return bus_find_device(&platform_bus_type, start, drv, + (void *)platform_match); +} +EXPORT_SYMBOL_GPL(platform_find_device_by_driver); + int __init platform_bus_init(void) { int error; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 58baf49d9926..badab94be2d6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -242,9 +242,7 @@ static struct component_match *exynos_drm_match_add(struct device *dev) if (!info->driver || !(info->flags & DRM_COMPONENT_DRIVER)) continue; - while ((d = bus_find_device(&platform_bus_type, p, - &info->driver->driver, - (void *)platform_bus_type.match))) { + while ((d = platform_find_device_by_driver(p, &info->driver->driver))) { put_device(p); if (!(info->flags & DRM_FIMC_DEVICE) || @@ -412,9 +410,8 @@ static void exynos_drm_unregister_devices(void) if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE)) continue; - while ((dev = bus_find_device(&platform_bus_type, NULL, - &info->driver->driver, - (void *)platform_bus_type.match))) { + while ((dev = platform_find_device_by_driver(NULL, + &info->driver->driver))) { put_device(dev); platform_device_unregister(to_platform_device(dev)); } diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index baf63fb6850a..c07abf9e201c 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -477,8 +477,7 @@ static int mcde_probe(struct platform_device *pdev) struct device_driver *drv = &mcde_component_drivers[i]->driver; struct device *p = NULL, *d; - while ((d = bus_find_device(&platform_bus_type, p, drv, - (void *)platform_bus_type.match))) { + while ((d = platform_find_device_by_driver(p, drv))) { put_device(p); component_match_add(dev, &match, mcde_compare_dev, d); p = d; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 53d2c5bd61dc..38dc26376961 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -330,8 +330,7 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) struct device *p = NULL, *d; do { - d = bus_find_device(&platform_bus_type, p, &drv->driver, - (void *)platform_bus_type.match); + d = platform_find_device_by_driver(p, &drv->driver); put_device(p); p = d; diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index bf11930e40e1..1551c8253bec 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -237,8 +237,7 @@ static void vc4_match_add_drivers(struct device *dev, struct device_driver *drv = &drivers[i]->driver; struct device *p = NULL, *d; - while ((d = bus_find_device(&platform_bus_type, p, drv, - (void *)platform_bus_type.match))) { + while ((d = platform_find_device_by_driver(p, drv))) { put_device(p); component_match_add(dev, match, compare_dev, d); p = d; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 9bc36b589827..37e15a935a42 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -51,6 +51,9 @@ extern struct device platform_bus; extern void arch_setup_pdev_archdata(struct platform_device *); extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int); +extern struct device * +platform_find_device_by_driver(struct device *start, + const struct device_driver *drv); extern void __iomem * devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index); -- GitLab From 5599e98fe06a88db55133ae8ac53f69216b82c6a Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 20:23:20 +0800 Subject: [PATCH 1273/7155] platform/x86: ISST: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c index f7266a115a08..ad8c7c0df4d9 100644 --- a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c +++ b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c @@ -132,11 +132,9 @@ static void isst_if_remove(struct pci_dev *pdev) static int __maybe_unused isst_if_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct isst_if_device *punit_dev; + struct isst_if_device *punit_dev = dev_get_drvdata(device); int i; - punit_dev = pci_get_drvdata(pdev); for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i) punit_dev->range_0[i] = readl(punit_dev->punit_mmio + mmio_range[0].beg + 4 * i); @@ -149,11 +147,9 @@ static int __maybe_unused isst_if_suspend(struct device *device) static int __maybe_unused isst_if_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct isst_if_device *punit_dev; + struct isst_if_device *punit_dev = dev_get_drvdata(device); int i; - punit_dev = pci_get_drvdata(pdev); for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i) writel(punit_dev->range_0[i], punit_dev->punit_mmio + mmio_range[0].beg + 4 * i); -- GitLab From bad9da86f9f10a2e68a1574dd34edde6f8556d5f Mon Sep 17 00:00:00 2001 From: Kelsey Skunberg Date: Sun, 21 Jul 2019 21:11:58 -0600 Subject: [PATCH 1274/7155] platform/x86: wmi: Remove acpi_has_method() call acpi_has_method() is unnecessary within __query_block() and should be removed to avoid extra work. wc_status is initialized to AE_ERROR before the acpi_has_method() call. acpi_has_method() and acpi_execute_simple_method() failing due to the method not existing will result in the same outcome from __query_block(). Signed-off-by: Kelsey Skunberg Signed-off-by: Andy Shevchenko --- drivers/platform/x86/wmi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 784cea8572c2..59e9aa0f9643 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -340,9 +340,7 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, * expensive, but have no corresponding WCxx method. So we * should not fail if this happens. */ - if (acpi_has_method(handle, wc_method)) - wc_status = acpi_execute_simple_method(handle, - wc_method, 1); + wc_status = acpi_execute_simple_method(handle, wc_method, 1); } strcpy(method, "WQ"); -- GitLab From 6fe9363b15767babf3f5b9eb41a664de2cff4030 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:34:11 +0300 Subject: [PATCH 1275/7155] platform/x86: acer-wmi: Switch to acpi_dev_get_first_match_dev() The acpi_dev_get_first_match_dev() helper will find and return an ACPI device pointer of the first registered device in the system by its HID. Use it instead of open coded variant. Cc: Chun-Yi Lee Signed-off-by: Andy Shevchenko --- drivers/platform/x86/acer-wmi.c | 49 +++++---------------------------- 1 file changed, 7 insertions(+), 42 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 62b54e137231..60c18f21588d 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1881,52 +1881,17 @@ static int __init acer_wmi_enable_rf_button(void) return status; } -#define ACER_WMID_ACCEL_HID "BST0001" - -static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, - void *ctx, void **retval) -{ - struct acpi_device *dev; - - if (!strcmp(ctx, "SENR")) { - if (acpi_bus_get_device(ah, &dev)) - return AE_OK; - if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) - return AE_OK; - } else - return AE_OK; - - *(acpi_handle *)retval = ah; - - return AE_CTRL_TERMINATE; -} - -static int __init acer_wmi_get_handle(const char *name, const char *prop, - acpi_handle *ah) -{ - acpi_status status; - acpi_handle handle; - - BUG_ON(!name || !ah); - - handle = NULL; - status = acpi_get_devices(prop, acer_wmi_get_handle_cb, - (void *)name, &handle); - if (ACPI_SUCCESS(status) && handle) { - *ah = handle; - return 0; - } else { - return -ENODEV; - } -} - static int __init acer_wmi_accel_setup(void) { + struct acpi_device *adev; int err; - err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle); - if (err) - return err; + adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1); + if (!adev) + return -ENODEV; + + gsensor_handle = acpi_device_handle(adev); + acpi_dev_put(adev); interface->capability |= ACER_CAP_ACCEL; -- GitLab From ff32e6e2dfd3cfdcaef63a0688bbfb9259aebe02 Mon Sep 17 00:00:00 2001 From: Rhys Kidd Date: Wed, 24 Jul 2019 18:14:13 +1000 Subject: [PATCH 1276/7155] platform/x86: dell-wmi: Ignore keyboard backlight change KBD_LED_ON_TOKEN There's a wmi event generated by dell-wmi when pressing keyboard backlight toggle key: [1224203.948894] dell_wmi: Unknown key with type 0x0011 and code 0x01e2 pressed This event is for notification purposes, let's ignore it. Signed-off-by: Rhys Kidd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/dell-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index acc653f9c16f..d9cd59d60b66 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -312,6 +312,7 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = { /* Keyboard backlight level changed */ { KE_IGNORE, 0x01e1, { KEY_RESERVED } }, + { KE_IGNORE, 0x01e2, { KEY_RESERVED } }, { KE_IGNORE, 0x02ea, { KEY_RESERVED } }, { KE_IGNORE, 0x02eb, { KEY_RESERVED } }, { KE_IGNORE, 0x02ec, { KEY_RESERVED } }, -- GitLab From 1be4311063a44ba8f4292a3a4a1f537be1f0b344 Mon Sep 17 00:00:00 2001 From: Rhys Kidd Date: Wed, 24 Jul 2019 18:14:14 +1000 Subject: [PATCH 1277/7155] platform/x86: dell-wmi: Ignore keyboard backlight change KBD_LED_AUTO_TOKEN There's a wmi event generated by dell-wmi when pressing keyboard backlight toggle key: [1224178.355650] dell_wmi: Unknown key with type 0x0011 and code 0x01e3 pressed This event is for notification purposes, let's ignore it. Signed-off-by: Rhys Kidd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/dell-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index d9cd59d60b66..31a092e049a0 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -313,6 +313,7 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = { /* Keyboard backlight level changed */ { KE_IGNORE, 0x01e1, { KEY_RESERVED } }, { KE_IGNORE, 0x01e2, { KEY_RESERVED } }, + { KE_IGNORE, 0x01e3, { KEY_RESERVED } }, { KE_IGNORE, 0x02ea, { KEY_RESERVED } }, { KE_IGNORE, 0x02eb, { KEY_RESERVED } }, { KE_IGNORE, 0x02ec, { KEY_RESERVED } }, -- GitLab From aaed5c9c2a146640170e0fbc84ca97e352c065ce Mon Sep 17 00:00:00 2001 From: Rhys Kidd Date: Wed, 24 Jul 2019 18:14:15 +1000 Subject: [PATCH 1278/7155] platform/x86: dell-wmi: Use existing defined KBD_LED_* magic values These values have already been defined in platform/x86/dell-smbios.h Signed-off-by: Rhys Kidd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/dell-wmi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 31a092e049a0..6669db2555fb 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -311,13 +311,13 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = { { KE_IGNORE, 0xfff1, { KEY_RESERVED } }, /* Keyboard backlight level changed */ - { KE_IGNORE, 0x01e1, { KEY_RESERVED } }, - { KE_IGNORE, 0x01e2, { KEY_RESERVED } }, - { KE_IGNORE, 0x01e3, { KEY_RESERVED } }, - { KE_IGNORE, 0x02ea, { KEY_RESERVED } }, - { KE_IGNORE, 0x02eb, { KEY_RESERVED } }, - { KE_IGNORE, 0x02ec, { KEY_RESERVED } }, - { KE_IGNORE, 0x02f6, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_OFF_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_ON_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_AUTO_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_AUTO_25_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_AUTO_50_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_AUTO_75_TOKEN, { KEY_RESERVED } }, + { KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } }, }; static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code) -- GitLab From c03f282e506f1e873ef9b270cf245509d68dd53b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Jul 2019 22:05:50 +0300 Subject: [PATCH 1279/7155] platform/x86: i2c-multi-instantiate: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. Signed-off-by: Andy Shevchenko Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 197d8a192721..61fe341a85aa 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -81,9 +81,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) if (ret < 0) return ret; - multi = devm_kmalloc(dev, - offsetof(struct i2c_multi_inst_data, clients[ret]), - GFP_KERNEL); + multi = devm_kmalloc(dev, struct_size(multi, clients, ret), GFP_KERNEL); if (!multi) return -ENOMEM; -- GitLab From 6a0694b6a244bc43ee79b65d0ae5435fb7b74401 Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 26 Jul 2019 08:21:15 +0200 Subject: [PATCH 1280/7155] platform/x86: pcengines-apuv2: add mpcie reset gpio export On APUx we have also mpcie2/mpcie3 reset pins. To make it possible to reset the ports from the userspace, add the definition to this platform device. The gpio can then be exported by the legancy gpio subsystem to toggle the mpcie reset pin. Signed-off-by: Florian Eckert Acked-by: Enrico Weigelt Signed-off-by: Andy Shevchenko --- drivers/platform/x86/pcengines-apuv2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c index e4c68efac0c2..56703656e8e6 100644 --- a/drivers/platform/x86/pcengines-apuv2.c +++ b/drivers/platform/x86/pcengines-apuv2.c @@ -32,6 +32,8 @@ #define APU2_GPIO_REG_LED3 AMD_FCH_GPIO_REG_GPIO59_DEVSLP1 #define APU2_GPIO_REG_MODESW AMD_FCH_GPIO_REG_GPIO32_GE1 #define APU2_GPIO_REG_SIMSWAP AMD_FCH_GPIO_REG_GPIO33_GE2 +#define APU2_GPIO_REG_MPCIE2 AMD_FCH_GPIO_REG_GPIO59_DEVSLP0 +#define APU2_GPIO_REG_MPCIE3 AMD_FCH_GPIO_REG_GPIO51 /* order in which the gpio lines are defined in the register list */ #define APU2_GPIO_LINE_LED1 0 @@ -39,6 +41,8 @@ #define APU2_GPIO_LINE_LED3 2 #define APU2_GPIO_LINE_MODESW 3 #define APU2_GPIO_LINE_SIMSWAP 4 +#define APU2_GPIO_LINE_MPCIE2 5 +#define APU2_GPIO_LINE_MPCIE3 6 /* gpio device */ @@ -48,6 +52,8 @@ static int apu2_gpio_regs[] = { [APU2_GPIO_LINE_LED3] = APU2_GPIO_REG_LED3, [APU2_GPIO_LINE_MODESW] = APU2_GPIO_REG_MODESW, [APU2_GPIO_LINE_SIMSWAP] = APU2_GPIO_REG_SIMSWAP, + [APU2_GPIO_LINE_MPCIE2] = APU2_GPIO_REG_MPCIE2, + [APU2_GPIO_LINE_MPCIE3] = APU2_GPIO_REG_MPCIE3, }; static const char * const apu2_gpio_names[] = { @@ -56,6 +62,8 @@ static const char * const apu2_gpio_names[] = { [APU2_GPIO_LINE_LED3] = "front-led3", [APU2_GPIO_LINE_MODESW] = "front-button", [APU2_GPIO_LINE_SIMSWAP] = "simswap", + [APU2_GPIO_LINE_MPCIE2] = "mpcie2_reset", + [APU2_GPIO_LINE_MPCIE3] = "mpcie3_reset", }; static const struct amd_fch_gpio_pdata board_apu2 = { -- GitLab From 5037d4ddda31c2dbbb018109655f61054b1756dc Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Mon, 29 Jul 2019 16:39:26 +0200 Subject: [PATCH 1281/7155] platform/x86: pcengines-apuv2: wire up simswitch gpio as led The APU3+ boards have two SIM sockets, while only one of them can be routed to the mpcie slots at a time. Selection is done via simswap gpio. We currently don't have a fitting subsystem for those cases yet, so just wire it up to a LED for the time being. While this isn't really semantically correct, it's a good compromise. Signed-off-by: Enrico Weigelt Signed-off-by: Andy Shevchenko --- drivers/platform/x86/pcengines-apuv2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c index 56703656e8e6..48b112b4f0b0 100644 --- a/drivers/platform/x86/pcengines-apuv2.c +++ b/drivers/platform/x86/pcengines-apuv2.c @@ -77,7 +77,8 @@ static const struct amd_fch_gpio_pdata board_apu2 = { static const struct gpio_led apu2_leds[] = { { .name = "apu:green:1" }, { .name = "apu:green:2" }, - { .name = "apu:green:3" } + { .name = "apu:green:3" }, + { .name = "apu:simswap" }, }; static const struct gpio_led_platform_data apu2_leds_pdata = { @@ -94,6 +95,8 @@ static struct gpiod_lookup_table gpios_led_table = { NULL, 1, GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3, NULL, 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_REG_SIMSWAP, + NULL, 3, GPIO_ACTIVE_LOW), } }; -- GitLab From 2889ffcfc2522d6d25e5bda704275064062bbb21 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 29 Jul 2019 16:27:37 +0800 Subject: [PATCH 1282/7155] platform/x86: asus-wmi: cleanup AGFN fan handling The asus-wmi driver currently uses the "AGFN" interface and the FAN_CTRL device for fan control. According to the spec, this interface is very dated and marked as pending removal from products currently in development. Clean up the way that the AGFN fan is detected and handled, also preparing the driver for the introduction of an alternate fan control method needed to support recent Asus products. Not anticipating further development of this interface, simplify the code by dropping any notion of being able to control multiple AGFN fans (this was already limited to just a single fan through only exposing a single fan in sysfs). Check for the presence of AGFN fans at probe time, simplifying the code flow in asus_hwmon_sysfs_is_visible(). Signed-off-by: Daniel Drake Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-wmi.c | 238 +++++++++------------ include/linux/platform_data/x86/asus-wmi.h | 4 +- 2 files changed, 109 insertions(+), 133 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 0c6a810fcb72..fc2939ac1cfe 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -65,6 +65,8 @@ MODULE_LICENSE("GPL"); #define ASUS_FAN_MFUN 0x13 #define ASUS_FAN_SFUN_READ 0x06 #define ASUS_FAN_SFUN_WRITE 0x07 + +/* Based on standard hwmon pwmX_enable values */ #define ASUS_FAN_CTRL_MANUAL 1 #define ASUS_FAN_CTRL_AUTO 2 @@ -120,7 +122,7 @@ struct agfn_args { } __packed; /* struct used for calling fan read and write methods */ -struct fan_args { +struct agfn_fan_args { struct agfn_args agfn; /* common fields */ u8 fan; /* fan number: 0: set auto mode 1: 1st fan */ u32 speed; /* read: RPM/100 - write: 0-255 */ @@ -148,6 +150,11 @@ struct asus_rfkill { u32 dev_id; }; +enum fan_type { + FAN_TYPE_NONE = 0, + FAN_TYPE_AGFN, /* deprecated on newer platforms */ +}; + struct asus_wmi { int dsts_id; int spec; @@ -178,9 +185,9 @@ struct asus_wmi { struct asus_rfkill gps; struct asus_rfkill uwb; - bool asus_hwmon_fan_manual_mode; - int asus_hwmon_num_fans; - int asus_hwmon_pwm; + enum fan_type fan_type; + int fan_pwm_mode; + int agfn_pwm; bool fan_boost_mode_available; u8 fan_boost_mode_mask; @@ -1125,10 +1132,10 @@ static void asus_wmi_set_als(void) /* Hwmon device ***************************************************************/ -static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, +static int asus_agfn_fan_speed_read(struct asus_wmi *asus, int fan, int *speed) { - struct fan_args args = { + struct agfn_fan_args args = { .agfn.len = sizeof(args), .agfn.mfun = ASUS_FAN_MFUN, .agfn.sfun = ASUS_FAN_SFUN_READ, @@ -1152,10 +1159,10 @@ static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, return 0; } -static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, +static int asus_agfn_fan_speed_write(struct asus_wmi *asus, int fan, int *speed) { - struct fan_args args = { + struct agfn_fan_args args = { .agfn.len = sizeof(args), .agfn.mfun = ASUS_FAN_MFUN, .agfn.sfun = ASUS_FAN_SFUN_WRITE, @@ -1175,7 +1182,7 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, return -ENXIO; if (speed && fan == 1) - asus->asus_hwmon_pwm = *speed; + asus->agfn_pwm = *speed; return 0; } @@ -1184,87 +1191,75 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, * Check if we can read the speed of one fan. If true we assume we can also * control it. */ -static int asus_hwmon_get_fan_number(struct asus_wmi *asus, int *num_fans) +static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus) { int status; - int speed = 0; + int speed; + u32 value; - *num_fans = 0; + status = asus_agfn_fan_speed_read(asus, 1, &speed); + if (status != 0) + return false; - status = asus_hwmon_agfn_fan_speed_read(asus, 1, &speed); - if (!status) - *num_fans = 1; + status = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value); + if (status != 0) + return false; - return 0; + /* + * We need to find a better way, probably using sfun, + * bits or spec ... + * Currently we disable it if: + * - ASUS_WMI_UNSUPPORTED_METHOD is returned + * - reverved bits are non-zero + * - sfun and presence bit are not set + */ + return !(value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 + || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))); } -static int asus_hwmon_fan_set_auto(struct asus_wmi *asus) +static int asus_fan_set_auto(struct asus_wmi *asus) { int status; - status = asus_hwmon_agfn_fan_speed_write(asus, 0, NULL); + status = asus_agfn_fan_speed_write(asus, 0, NULL); if (status) return -ENXIO; - asus->asus_hwmon_fan_manual_mode = false; - return 0; } -static int asus_hwmon_fan_rpm_show(struct device *dev, int fan) +static ssize_t pwm1_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct asus_wmi *asus = dev_get_drvdata(dev); - int value; - int ret; - - /* no speed readable on manual mode */ - if (asus->asus_hwmon_fan_manual_mode) - return -ENXIO; - - ret = asus_hwmon_agfn_fan_speed_read(asus, fan+1, &value); - if (ret) { - pr_warn("reading fan speed failed: %d\n", ret); - return -ENXIO; - } - - return value; -} - -static void asus_hwmon_pwm_show(struct asus_wmi *asus, int fan, int *value) -{ int err; + int value; - if (asus->asus_hwmon_pwm >= 0) { - *value = asus->asus_hwmon_pwm; - return; - } + /* If we already set a value then just return it */ + if (asus->agfn_pwm >= 0) + return sprintf(buf, "%d\n", asus->agfn_pwm); - err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, value); + /* + * If we haven't set already set a value through the AGFN interface, + * we read a current value through the (now-deprecated) FAN_CTRL device. + */ + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value); if (err < 0) - return; + return err; - *value &= 0xFF; - - if (*value == 1) /* Low Speed */ - *value = 85; - else if (*value == 2) - *value = 170; - else if (*value == 3) - *value = 255; - else if (*value) { - pr_err("Unknown fan speed %#x\n", *value); - *value = -1; + value &= 0xFF; + + if (value == 1) /* Low Speed */ + value = 85; + else if (value == 2) + value = 170; + else if (value == 3) + value = 255; + else if (value) { + pr_err("Unknown fan speed %#x\n", value); + value = -1; } -} - -static ssize_t pwm1_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct asus_wmi *asus = dev_get_drvdata(dev); - int value; - - asus_hwmon_pwm_show(asus, 0, &value); return sprintf(buf, "%d\n", value); } @@ -1284,11 +1279,11 @@ static ssize_t pwm1_store(struct device *dev, value = clamp(value, 0, 255); - state = asus_hwmon_agfn_fan_speed_write(asus, 1, &value); + state = asus_agfn_fan_speed_write(asus, 1, &value); if (state) pr_warn("Setting fan speed failed: %d\n", state); else - asus->asus_hwmon_fan_manual_mode = true; + asus->fan_pwm_mode = ASUS_FAN_CTRL_MANUAL; return count; } @@ -1297,10 +1292,21 @@ static ssize_t fan1_input_show(struct device *dev, struct device_attribute *attr, char *buf) { - int value = asus_hwmon_fan_rpm_show(dev, 0); + struct asus_wmi *asus = dev_get_drvdata(dev); + int value; + int ret; - return sprintf(buf, "%d\n", value < 0 ? -1 : value*100); + /* no speed readable on manual mode */ + if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL) + return -ENXIO; + + ret = asus_agfn_fan_speed_read(asus, 1, &value); + if (ret) { + pr_warn("reading fan speed failed: %d\n", ret); + return -ENXIO; + } + return sprintf(buf, "%d\n", value < 0 ? -1 : value*100); } static ssize_t pwm1_enable_show(struct device *dev, @@ -1309,10 +1315,7 @@ static ssize_t pwm1_enable_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); - if (asus->asus_hwmon_fan_manual_mode) - return sprintf(buf, "%d\n", ASUS_FAN_CTRL_MANUAL); - - return sprintf(buf, "%d\n", ASUS_FAN_CTRL_AUTO); + return sprintf(buf, "%d\n", asus->fan_pwm_mode); } static ssize_t pwm1_enable_store(struct device *dev, @@ -1329,14 +1332,21 @@ static ssize_t pwm1_enable_store(struct device *dev, if (ret) return ret; - if (state == ASUS_FAN_CTRL_MANUAL) - asus->asus_hwmon_fan_manual_mode = true; - else - status = asus_hwmon_fan_set_auto(asus); + switch (state) { + case ASUS_FAN_CTRL_MANUAL: + break; - if (status) - return status; + case ASUS_FAN_CTRL_AUTO: + status = asus_fan_set_auto(asus); + if (status) + return status; + break; + default: + return -EINVAL; + } + + asus->fan_pwm_mode = state; return count; } @@ -1389,59 +1399,31 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, { struct device *dev = container_of(kobj, struct device, kobj); struct asus_wmi *asus = dev_get_drvdata(dev->parent); - int dev_id = -1; - int fan_attr = -1; u32 value = ASUS_WMI_UNSUPPORTED_METHOD; - bool ok = true; - - if (attr == &dev_attr_pwm1.attr) - dev_id = ASUS_WMI_DEVID_FAN_CTRL; - else if (attr == &dev_attr_temp1_input.attr) - dev_id = ASUS_WMI_DEVID_THERMAL_CTRL; - if (attr == &dev_attr_fan1_input.attr || attr == &dev_attr_fan1_label.attr || attr == &dev_attr_pwm1.attr || attr == &dev_attr_pwm1_enable.attr) { - fan_attr = 1; - } - - if (dev_id != -1) { - int err = asus_wmi_get_devstate(asus, dev_id, &value); + if (asus->fan_type == FAN_TYPE_NONE) + return 0; + } else if (attr == &dev_attr_temp1_input.attr) { + int err = asus_wmi_get_devstate(asus, + ASUS_WMI_DEVID_THERMAL_CTRL, + &value); - if (err < 0 && fan_attr == -1) + if (err < 0) return 0; /* can't return negative here */ - } - if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) { - /* - * We need to find a better way, probably using sfun, - * bits or spec ... - * Currently we disable it if: - * - ASUS_WMI_UNSUPPORTED_METHOD is returned - * - reverved bits are non-zero - * - sfun and presence bit are not set - */ - if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 - || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))) - ok = false; - else - ok = fan_attr <= asus->asus_hwmon_num_fans; - } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) { /* * If the temperature value in deci-Kelvin is near the absolute * zero temperature, something is clearly wrong */ if (value == 0 || value == 1) - ok = false; - } else if (fan_attr <= asus->asus_hwmon_num_fans && fan_attr != -1) { - ok = true; - } else { - ok = false; + return 0; } - return ok ? attr->mode : 0; + return attr->mode; } static const struct attribute_group hwmon_attribute_group = { @@ -1467,21 +1449,16 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) static int asus_wmi_fan_init(struct asus_wmi *asus) { - int status; - - asus->asus_hwmon_pwm = -1; - asus->asus_hwmon_num_fans = -1; - asus->asus_hwmon_fan_manual_mode = false; + asus->fan_type = FAN_TYPE_NONE; + asus->agfn_pwm = -1; - status = asus_hwmon_get_fan_number(asus, &asus->asus_hwmon_num_fans); - if (status) { - asus->asus_hwmon_num_fans = 0; - pr_warn("Could not determine number of fans: %d\n", status); - return -ENXIO; + if (asus_wmi_has_agfn_fan(asus)) { + asus->fan_type = FAN_TYPE_AGFN; + asus_fan_set_auto(asus); + asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO; } - pr_info("Number of fans: %d\n", asus->asus_hwmon_num_fans); - return 0; + return asus->fan_type != FAN_TYPE_NONE; } /* Fan mode *******************************************************************/ @@ -2333,7 +2310,6 @@ static int asus_wmi_add(struct platform_device *pdev) goto fail_input; err = asus_wmi_fan_init(asus); /* probably no problems on error */ - asus_hwmon_fan_set_auto(asus); err = asus_wmi_hwmon_init(asus); if (err) @@ -2425,7 +2401,7 @@ static int asus_wmi_remove(struct platform_device *device) asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); asus_wmi_sysfs_exit(asus->platform_device); - asus_hwmon_fan_set_auto(asus); + asus_fan_set_auto(asus); kfree(asus); return 0; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 4802cd2c7309..5ae9c062a1f6 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -12,7 +12,7 @@ #define ASUS_WMI_METHODID_GPID 0x44495047 /* Get Panel ID?? (Resol) */ #define ASUS_WMI_METHODID_QMOD 0x444F4D51 /* Quiet MODe */ #define ASUS_WMI_METHODID_SPLV 0x4C425053 /* Set Panel Light Value */ -#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* FaN? */ +#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* Atk Generic FuNction */ #define ASUS_WMI_METHODID_SFUN 0x4E554653 /* FUNCtionalities */ #define ASUS_WMI_METHODID_SDSP 0x50534453 /* Set DiSPlay output */ #define ASUS_WMI_METHODID_GDSP 0x50534447 /* Get DiSPlay output */ @@ -72,7 +72,7 @@ /* Fan, Thermal */ #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011 -#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 +#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */ /* Power */ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 -- GitLab From f1fc032192d2872caef69fb899e939bf7cc24fc7 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 29 Jul 2019 16:27:38 +0800 Subject: [PATCH 1283/7155] platform/x86: asus-wmi: add a helper for device presence Factor out the WLAN LED and lightbar LED presence checks into a helper function, which will also be used by the upcoming CPU fan device support. Signed-off-by: Daniel Drake Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-wmi.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index fc2939ac1cfe..25f1e256c442 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -358,6 +358,14 @@ static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id) ASUS_WMI_DSTS_STATUS_BIT); } +static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) +{ + u32 retval; + int status = asus_wmi_get_devstate(asus, dev_id, &retval); + + return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); +} + /* LEDs ***********************************************************************/ /* @@ -503,15 +511,6 @@ static int wlan_led_unknown_state(struct asus_wmi *asus) return result & ASUS_WMI_DSTS_UNKNOWN_BIT; } -static int wlan_led_presence(struct asus_wmi *asus) -{ - u32 result; - - asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result); - - return result & ASUS_WMI_DSTS_PRESENCE_BIT; -} - static void wlan_led_update(struct work_struct *work) { int ctrl_param; @@ -578,15 +577,6 @@ static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev) return result & ASUS_WMI_DSTS_LIGHTBAR_MASK; } -static int lightbar_led_presence(struct asus_wmi *asus) -{ - u32 result; - - asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result); - - return result & ASUS_WMI_DSTS_PRESENCE_BIT; -} - static void asus_wmi_led_exit(struct asus_wmi *asus) { if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) @@ -637,7 +627,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_WIRELESS_LED) + && (asus->driver->quirks->wapf > 0)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -654,7 +645,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (lightbar_led_presence(asus)) { + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_LIGHTBAR)) { INIT_WORK(&asus->lightbar_led_work, lightbar_led_update); asus->lightbar_led.name = "asus::lightbar"; -- GitLab From e3168b874321d04c160c9eb937919eb926ae232f Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 29 Jul 2019 16:27:39 +0800 Subject: [PATCH 1284/7155] platform/x86: asus-wmi: fix CPU fan control on recent products Previously, asus-wmi was using the AGFN interface and FAN_CTRL device for CPU fan control. However, this code has been found to be not fully working on some recent products, and having checked the spec, these interfaces are marked as being removed from future products currently in development. The replacement appears to be the CPU_FAN device, added in spec version 8.3 (March 2014) and present on many modern Asus laptops. Add support for this device, and use it whenever it is detected. The older approach based on AGFN and FAN_CTRL is used as a fallback on products that do not have such device. Other than switching between automatic and full speed, there is no fan speed control through this new interface. Signed-off-by: Daniel Drake Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-wmi.c | 125 ++++++++++++++++----- include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 101 insertions(+), 25 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 25f1e256c442..34dfbed65332 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -67,6 +67,7 @@ MODULE_LICENSE("GPL"); #define ASUS_FAN_SFUN_WRITE 0x07 /* Based on standard hwmon pwmX_enable values */ +#define ASUS_FAN_CTRL_FULLSPEED 0 #define ASUS_FAN_CTRL_MANUAL 1 #define ASUS_FAN_CTRL_AUTO 2 @@ -153,6 +154,7 @@ struct asus_rfkill { enum fan_type { FAN_TYPE_NONE = 0, FAN_TYPE_AGFN, /* deprecated on newer platforms */ + FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */ }; struct asus_wmi { @@ -1211,10 +1213,29 @@ static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus) static int asus_fan_set_auto(struct asus_wmi *asus) { int status; + u32 retval; - status = asus_agfn_fan_speed_write(asus, 0, NULL); - if (status) + switch (asus->fan_type) { + case FAN_TYPE_SPEC83: + status = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL, + 0, &retval); + if (status) + return status; + + if (retval != 1) + return -EIO; + break; + + case FAN_TYPE_AGFN: + status = asus_agfn_fan_speed_write(asus, 0, NULL); + if (status) + return -ENXIO; + break; + + default: return -ENXIO; + } + return 0; } @@ -1287,13 +1308,29 @@ static ssize_t fan1_input_show(struct device *dev, int value; int ret; - /* no speed readable on manual mode */ - if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL) - return -ENXIO; + switch (asus->fan_type) { + case FAN_TYPE_SPEC83: + ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL, + &value); + if (ret < 0) + return ret; - ret = asus_agfn_fan_speed_read(asus, 1, &value); - if (ret) { - pr_warn("reading fan speed failed: %d\n", ret); + value &= 0xffff; + break; + + case FAN_TYPE_AGFN: + /* no speed readable on manual mode */ + if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL) + return -ENXIO; + + ret = asus_agfn_fan_speed_read(asus, 1, &value); + if (ret) { + pr_warn("reading fan speed failed: %d\n", ret); + return -ENXIO; + } + break; + + default: return -ENXIO; } @@ -1306,6 +1343,15 @@ static ssize_t pwm1_enable_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); + /* + * Just read back the cached pwm mode. + * + * For the CPU_FAN device, the spec indicates that we should be + * able to read the device status and consult bit 19 to see if we + * are in Full On or Automatic mode. However, this does not work + * in practice on X532FL at least (the bit is always 0) and there's + * also nothing in the DSDT to indicate that this behaviour exists. + */ return sprintf(buf, "%d\n", asus->fan_pwm_mode); } @@ -1316,25 +1362,48 @@ static ssize_t pwm1_enable_store(struct device *dev, struct asus_wmi *asus = dev_get_drvdata(dev); int status = 0; int state; + int value; int ret; + u32 retval; ret = kstrtouint(buf, 10, &state); if (ret) return ret; - switch (state) { - case ASUS_FAN_CTRL_MANUAL: - break; + if (asus->fan_type == FAN_TYPE_SPEC83) { + switch (state) { /* standard documented hwmon values */ + case ASUS_FAN_CTRL_FULLSPEED: + value = 1; + break; + case ASUS_FAN_CTRL_AUTO: + value = 0; + break; + default: + return -EINVAL; + } - case ASUS_FAN_CTRL_AUTO: - status = asus_fan_set_auto(asus); - if (status) - return status; - break; + ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL, + value, &retval); + if (ret) + return ret; - default: - return -EINVAL; + if (retval != 1) + return -EIO; + } else if (asus->fan_type == FAN_TYPE_AGFN) { + switch (state) { + case ASUS_FAN_CTRL_MANUAL: + break; + + case ASUS_FAN_CTRL_AUTO: + status = asus_fan_set_auto(asus); + if (status) + return status; + break; + + default: + return -EINVAL; + } } asus->fan_pwm_mode = state; @@ -1392,9 +1461,11 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, struct asus_wmi *asus = dev_get_drvdata(dev->parent); u32 value = ASUS_WMI_UNSUPPORTED_METHOD; - if (attr == &dev_attr_fan1_input.attr + if (attr == &dev_attr_pwm1.attr) { + if (asus->fan_type != FAN_TYPE_AGFN) + return 0; + } else if (attr == &dev_attr_fan1_input.attr || attr == &dev_attr_fan1_label.attr - || attr == &dev_attr_pwm1.attr || attr == &dev_attr_pwm1_enable.attr) { if (asus->fan_type == FAN_TYPE_NONE) return 0; @@ -1443,13 +1514,17 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) asus->fan_type = FAN_TYPE_NONE; asus->agfn_pwm = -1; - if (asus_wmi_has_agfn_fan(asus)) { + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) + asus->fan_type = FAN_TYPE_SPEC83; + else if (asus_wmi_has_agfn_fan(asus)) asus->fan_type = FAN_TYPE_AGFN; - asus_fan_set_auto(asus); - asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO; - } - return asus->fan_type != FAN_TYPE_NONE; + if (asus->fan_type == FAN_TYPE_NONE) + return -ENODEV; + + asus_fan_set_auto(asus); + asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO; + return 0; } /* Fan mode *******************************************************************/ diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 5ae9c062a1f6..409e16064f4b 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -73,6 +73,7 @@ /* Fan, Thermal */ #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011 #define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */ +#define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013 /* Power */ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 -- GitLab From 7723f4c5ecdb8d832f049f8483beb0d1081cedf6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 29 Jul 2019 22:38:43 -0700 Subject: [PATCH 1285/7155] driver core: platform: Add an error message to platform_get_irq*() A grep of the kernel shows that many drivers print an error message if they fail to get the irq they're looking for. Furthermore, those drivers all decide to print the device name, or not, and the irq they were requesting, or not, etc. Let's consolidate all these error messages into the API itself, allowing us to get rid of the error messages in each driver. Cc: Rob Herring Cc: Bartlomiej Zolnierkiewicz Cc: Javier Martinez Canillas Cc: Andrzej Hajda Cc: Mark Brown Cc: Russell King - ARM Linux Cc: Marek Szyprowski Cc: Markus Elfring Reviewed-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730053845.126834-2-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a174ce5ea17c..9426736551b5 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -99,12 +99,7 @@ void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); #endif /* CONFIG_HAS_IOMEM */ -/** - * platform_get_irq - get an IRQ for a device - * @dev: platform device - * @num: IRQ number index - */ -int platform_get_irq(struct platform_device *dev, unsigned int num) +static int __platform_get_irq(struct platform_device *dev, unsigned int num) { #ifdef CONFIG_SPARC /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ @@ -163,6 +158,33 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) return -ENXIO; #endif } + +/** + * platform_get_irq - get an IRQ for a device + * @dev: platform device + * @num: IRQ number index + * + * Gets an IRQ for a platform device and prints an error message if finding the + * IRQ fails. Device drivers should check the return value for errors so as to + * not pass a negative integer value to the request_irq() APIs. + * + * Example: + * int irq = platform_get_irq(pdev, 0); + * if (irq < 0) + * return irq; + * + * Return: IRQ number on success, negative error number on failure. + */ +int platform_get_irq(struct platform_device *dev, unsigned int num) +{ + int ret; + + ret = __platform_get_irq(dev, num); + if (ret < 0 && ret != -EPROBE_DEFER) + dev_err(&dev->dev, "IRQ index %u not found\n", num); + + return ret; +} EXPORT_SYMBOL_GPL(platform_get_irq); /** @@ -175,7 +197,7 @@ int platform_irq_count(struct platform_device *dev) { int ret, nr = 0; - while ((ret = platform_get_irq(dev, nr)) >= 0) + while ((ret = __platform_get_irq(dev, nr)) >= 0) nr++; if (ret == -EPROBE_DEFER) @@ -228,7 +250,11 @@ int platform_get_irq_byname(struct platform_device *dev, const char *name) } r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); - return r ? r->start : -ENXIO; + if (r) + return r->start; + + dev_err(&dev->dev, "IRQ %s not found\n", name); + return -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq_byname); -- GitLab From 98051ba2b28be8a8ec5e22c01f464cff2d6d5f7c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 29 Jul 2019 22:38:45 -0700 Subject: [PATCH 1286/7155] coccinelle: Add script to check for platform_get_irq() excessive prints Add a coccinelle script to check for the usage of dev_err() after a call to platform_get_irq{,_byname}() as it's redundant now that the function already prints an error when it fails. Cc: Greg Kroah-Hartman Cc: Rob Herring Cc: Bartlomiej Zolnierkiewicz Cc: Javier Martinez Canillas Cc: Andrzej Hajda Cc: Mark Brown Cc: Russell King - ARM Linux Cc: Marek Szyprowski Cc: Rafael J. Wysocki Cc: Andy Shevchenko Cc: Markus Elfring Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730053845.126834-4-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- scripts/coccinelle/api/platform_get_irq.cocci | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 scripts/coccinelle/api/platform_get_irq.cocci diff --git a/scripts/coccinelle/api/platform_get_irq.cocci b/scripts/coccinelle/api/platform_get_irq.cocci new file mode 100644 index 000000000000..f6e1afc08c0b --- /dev/null +++ b/scripts/coccinelle/api/platform_get_irq.cocci @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/// Remove dev_err() messages after platform_get_irq*() failures +// +// Confidence: Medium +// Options: --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +if (ret != -EPROBE_DEFER) +{ ... +*dev_err(...); +... } +| +... +*dev_err(...); +) +... +} + +@depends on patch@ +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +-if (ret != -EPROBE_DEFER) +-{ ... +-dev_err(...); +-... } +| +... +-dev_err(...); +) +... +} + +@r depends on org || report@ +position p1; +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +if (ret != -EPROBE_DEFER) +{ ... +dev_err@p1(...); +... } +| +... +dev_err@p1(...); +) +... +} + +@script:python depends on org@ +p1 << r.p1; +@@ + +cocci.print_main(p1) + +@script:python depends on report@ +p1 << r.p1; +@@ + +msg = "line %s is redundant because platform_get_irq() already prints an error" % (p1[0].line) +coccilib.report.print_report(p1[0],msg) -- GitLab From 41763c2b50a19f23b519e3ca8d68fd9dc1b1e02a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 13 Jun 2019 06:53:34 -0500 Subject: [PATCH 1287/7155] ARM: dts: socfpga: add the QSPI OCP reset property on arria10 The QSPI module needs the OCP reset bit deasserted as well. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index a0a6d8507265..20af1543819a 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -753,7 +753,8 @@ cdns,fifo-width = <4>; cdns,trigger-address = <0x00000000>; clocks = <&qspi_clk>; - resets = <&rst QSPI_RESET>; + resets = <&rst QSPI_RESET>, <&rst QSPI_OCP_RESET>; + reset-names = "qspi", "qspi-ocp"; status = "disabled"; }; -- GitLab From 5adfd87d9ba7f27418851f0b2a59fba643bc846f Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 20 Jun 2019 10:07:56 -0500 Subject: [PATCH 1288/7155] ARM: dts: socfpga: add reset properties for DMA Add both the reset and reset-ocp properties for the DMA node on Arria10. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 20af1543819a..26c157b91189 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -68,6 +68,8 @@ #dma-requests = <32>; clocks = <&l4_main_clk>; clock-names = "apb_pclk"; + resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>; + reset-names = "dma", "dma-ocp"; }; }; -- GitLab From e10c18484b66afa830f9a36348e12143f0ec2267 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 20 Jun 2019 10:25:07 -0500 Subject: [PATCH 1289/7155] arm64: dts: agilex/stratix10: Add reset properties for DMA Add both the reset and reset-ocp properties for the DMA node on the Stratix10 and Agilex platforms. Signed-off-by: Dinh Nguyen --- arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | 2 ++ arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index b05d78164fc1..be78db2cd4c9 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi @@ -324,6 +324,8 @@ #dma-requests = <32>; clocks = <&clkmgr STRATIX10_L4_MAIN_CLK>; clock-names = "apb_pclk"; + resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>; + reset-names = "dma", "dma-ocp"; }; rst: rstmgr@ffd11000 { diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi index e4ceb3a73c81..36abc25320a8 100644 --- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi +++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi @@ -249,6 +249,8 @@ #dma-cells = <1>; #dma-channels = <8>; #dma-requests = <32>; + resets = <&rst DMA_RESET>, <&rst DMA_OCP_RESET>; + reset-names = "dma", "dma-ocp"; }; rst: rstmgr@ffd11000 { -- GitLab From c1459a9d7e920b045aa3eb458ee099dc76f50502 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 21 Jun 2019 20:23:06 +0900 Subject: [PATCH 1290/7155] ARM: dts: socfpga: update to new Denali NAND binding With commit d8e8fd0ebf8b ("mtd: rawnand: denali: decouple controller and NAND chips"), the Denali NAND controller driver migrated to the new controller/chip representation. Update DT for it. Signed-off-by: Masahiro Yamada Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga.dtsi | 2 +- arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +- .../boot/dts/socfpga_arria10_socdk_nand.dts | 20 ++++++++++++------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index ec1966480f2f..90d6d0d4417d 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -747,7 +747,7 @@ nand0: nand@ff900000 { #address-cells = <0x1>; - #size-cells = <0x1>; + #size-cells = <0x0>; compatible = "altr,socfpga-denali-nand"; reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 26c157b91189..2a86e72d9791 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -662,7 +662,7 @@ nand: nand@ffb90000 { #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; compatible = "altr,socfpga-denali-nand"; reg = <0xffb90000 0x72000>, <0xffb80000 0x10000>; diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts index e36e0a0f8aa6..9bd9e04c7361 100644 --- a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts +++ b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts @@ -9,12 +9,18 @@ &nand { status = "okay"; - partition@nand-boot { - label = "Boot and fpga data"; - reg = <0x0 0x1C00000>; - }; - partition@nand-rootfs { - label = "Root Filesystem - JFFS2"; - reg = <0x1C00000 0x6400000>; + nand@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Boot and fpga data"; + reg = <0x0 0x1C00000>; + }; + partition@1c00000 { + label = "Root Filesystem - JFFS2"; + reg = <0x1C00000 0x6400000>; + }; }; }; -- GitLab From 67c9fd2d23208e65c6658a1fc83bc37392f241b5 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 24 Jun 2019 16:12:32 -0500 Subject: [PATCH 1291/7155] arm64: dts: stratix10: Add NAND device node Add the NAND device node to the base Stratix10 DTS. Signed-off-by: Dinh Nguyen --- .../arm64/boot/dts/altera/socfpga_stratix10.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index be78db2cd4c9..144a2c19ac02 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi @@ -302,6 +302,22 @@ status = "disabled"; }; + nand: nand@ffb90000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "altr,socfpga-denali-nand"; + reg = <0xffb90000 0x10000>, + <0xffb80000 0x1000>; + reg-names = "nand_data", "denali_reg"; + interrupts = <0 97 4>; + clocks = <&clkmgr STRATIX10_NAND_CLK>, + <&clkmgr STRATIX10_NAND_X_CLK>, + <&clkmgr STRATIX10_NAND_ECC_CLK>; + clock-names = "nand", "nand_x", "ecc"; + resets = <&rst NAND_RESET>, <&rst NAND_OCP_RESET>; + status = "disabled"; + }; + ocram: sram@ffe00000 { compatible = "mmio-sram"; reg = <0xffe00000 0x100000>; -- GitLab From 325ec920eeb7b96b9cb490213bfdb03650c19d86 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 28 Jun 2019 02:19:20 +0200 Subject: [PATCH 1292/7155] ARM: dts: socfpga: Fix up button mapping on VINING FPGA Add missing buttons and signals to the VINING FPGA device tree, so they are presented to the userspace via gpio-keys evdev. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- .../boot/dts/socfpga_cyclone5_vining_fpga.dts | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts index 355b3dbf438d..622cc7cc1471 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts @@ -36,21 +36,33 @@ hps_temp0 { label = "BTN_0"; /* TEMP_OS */ - gpios = <&portc 18 GPIO_ACTIVE_LOW>; /* HPS_GPIO60 */ + gpios = <&portc 18 GPIO_ACTIVE_LOW>; /* HPS_GPI5 */ linux,code = ; }; hps_hkey0 { - label = "BTN_1"; /* DIS_PWR */ - gpios = <&portc 19 GPIO_ACTIVE_LOW>; /* HPS_GPIO61 */ + label = "GP_SWITCH"; /* GP_SWITCH */ + gpios = <&portc 19 GPIO_ACTIVE_LOW>; /* HPS_GPI6 */ linux,code = ; }; hps_hkey1 { - label = "hps_hkey1"; /* POWER_DOWN */ - gpios = <&portc 20 GPIO_ACTIVE_LOW>; /* HPS_GPIO62 */ + label = "RESET_SWITCH"; /* RESET_SWITCH */ + gpios = <&portc 20 GPIO_ACTIVE_LOW>; /* HPS_GPI7 */ + linux,code = ; + }; + + hps_hkey2 { + label = "POWER_DOWN"; /* POWER_DOWN */ + gpios = <&portc 4 GPIO_ACTIVE_LOW>; /* HPS_GPIO62 */ linux,code = ; }; + + hps_hkey3 { + label = "SENSE"; /* SENSE */ + gpios = <&porta 9 GPIO_ACTIVE_LOW>; /* HPS_GPIO9 */ + linux,code = ; + }; }; regulator-usb-nrst { -- GitLab From 2dbaa6a6dcf01b84bcf076a0e906dc7dacbd0a1d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 28 Jun 2019 02:19:44 +0200 Subject: [PATCH 1293/7155] ARM: dts: socfpga: Adjust GMAC1 clock and TXD lines skew on VINING FPGA Adjust GMAC1 clock lines skew to maximum (+960 ps) and TXD lines skew to minimum (-420 ps), to improve signal integrity. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts index 622cc7cc1471..a060718758b6 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts @@ -96,10 +96,14 @@ rxd1-skew-ps = <0>; rxd2-skew-ps = <0>; rxd3-skew-ps = <0>; + txd0-skew-ps = <0>; + txd1-skew-ps = <0>; + txd2-skew-ps = <0>; + txd3-skew-ps = <0>; txen-skew-ps = <0>; - txc-skew-ps = <2600>; + txc-skew-ps = <1860>; rxdv-skew-ps = <0>; - rxc-skew-ps = <2000>; + rxc-skew-ps = <1860>; }; }; }; -- GitLab From d8c1ccac448fd21a3753517a34ee0164c28ac786 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2019 09:07:04 -0500 Subject: [PATCH 1294/7155] ARM: dts: socfpga: add missing reset-names for dma The dma dts node was missing the reset-names = "dma". The reset driver needs this line to get the reset property. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 90d6d0d4417d..4f3993cc0227 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -85,6 +85,7 @@ clocks = <&l4_main_clk>; clock-names = "apb_pclk"; resets = <&rst DMA_RESET>; + reset-names = "dma"; }; }; -- GitLab From fa86ee90eb1111267de67cb4272b5ce711f18cbb Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 3 Jul 2019 20:51:25 -0300 Subject: [PATCH 1295/7155] add cpuidle-haltpoll driver Add a cpuidle driver that calls the architecture default_idle routine. To be used in conjunction with the haltpoll governor. Signed-off-by: Marcelo Tosatti Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/process.c | 2 +- drivers/cpuidle/Kconfig | 9 ++++ drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-haltpoll.c | 68 ++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 drivers/cpuidle/cpuidle-haltpoll.c diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 75fea0d48c0e..5e94c4354d4e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -580,7 +580,7 @@ void __cpuidle default_idle(void) safe_halt(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); } -#ifdef CONFIG_APM_MODULE +#if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE) EXPORT_SYMBOL(default_idle); #endif diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index a4ac31e4a58c..cc8efc56be7d 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -51,6 +51,15 @@ depends on PPC source "drivers/cpuidle/Kconfig.powerpc" endmenu +config HALTPOLL_CPUIDLE + tristate "Halt poll cpuidle driver" + depends on X86 && KVM_GUEST + default y + help + This option enables halt poll cpuidle driver, which allows to poll + before halting in the guest (more efficient than polling in the + host via halt_poll_ns for some scenarios). + endif config ARCH_NEEDS_CPU_IDLE_COUPLED diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 9d7176cee3d3..240227474cd9 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -7,6 +7,7 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o +obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o ################################################################################## # ARM SoC drivers diff --git a/drivers/cpuidle/cpuidle-haltpoll.c b/drivers/cpuidle/cpuidle-haltpoll.c new file mode 100644 index 000000000000..35cfb53e9287 --- /dev/null +++ b/drivers/cpuidle/cpuidle-haltpoll.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * cpuidle driver for haltpoll governor. + * + * Copyright 2019 Red Hat, Inc. and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Authors: Marcelo Tosatti + */ + +#include +#include +#include +#include +#include + +static int default_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + if (current_clr_polling_and_test()) { + local_irq_enable(); + return index; + } + default_idle(); + return index; +} + +static struct cpuidle_driver haltpoll_driver = { + .name = "haltpoll", + .owner = THIS_MODULE, + .states = { + { /* entry 0 is for polling */ }, + { + .enter = default_enter_idle, + .exit_latency = 1, + .target_residency = 1, + .power_usage = -1, + .name = "haltpoll idle", + .desc = "default architecture idle", + }, + }, + .safe_state_index = 0, + .state_count = 2, +}; + +static int __init haltpoll_init(void) +{ + struct cpuidle_driver *drv = &haltpoll_driver; + + cpuidle_poll_state_init(drv); + + if (!kvm_para_available()) + return 0; + + return cpuidle_register(&haltpoll_driver, NULL); +} + +static void __exit haltpoll_exit(void) +{ + cpuidle_unregister(&haltpoll_driver); +} + +module_init(haltpoll_init); +module_exit(haltpoll_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marcelo Tosatti "); -- GitLab From 259231a045616c4101d023a8f4dcc8379af265a6 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 3 Jul 2019 20:51:26 -0300 Subject: [PATCH 1296/7155] cpuidle: add poll_limit_ns to cpuidle_device structure Add a poll_limit_ns variable to cpuidle_device structure. Calculate and configure it in the new cpuidle_poll_time function, in case its zero. Individual governors are allowed to override this value. Signed-off-by: Marcelo Tosatti Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 30 ++++++++++++++++++++++++++++++ drivers/cpuidle/poll_state.c | 11 ++--------- drivers/cpuidle/sysfs.c | 7 +++++++ include/linux/cpuidle.h | 6 ++++++ 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 0f4b7c45df3e..0895b988fa92 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -361,6 +361,36 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index) cpuidle_curr_governor->reflect(dev, index); } +/** + * cpuidle_poll_time - return amount of time to poll for, + * governors can override dev->poll_limit_ns if necessary + * + * @drv: the cpuidle driver tied with the cpu + * @dev: the cpuidle device + * + */ +u64 cpuidle_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{ + int i; + u64 limit_ns; + + if (dev->poll_limit_ns) + return dev->poll_limit_ns; + + limit_ns = TICK_NSEC; + for (i = 1; i < drv->state_count; i++) { + if (drv->states[i].disabled || dev->states_usage[i].disable) + continue; + + limit_ns = (u64)drv->states[i].target_residency * NSEC_PER_USEC; + } + + dev->poll_limit_ns = limit_ns; + + return dev->poll_limit_ns; +} + /** * cpuidle_install_idle_handler - installs the cpuidle idle loop handler */ diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index 02b9315a9e96..c8fa5f41dfc4 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -20,16 +20,9 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, local_irq_enable(); if (!current_set_polling_and_test()) { unsigned int loop_count = 0; - u64 limit = TICK_NSEC; - int i; + u64 limit; - for (i = 1; i < drv->state_count; i++) { - if (drv->states[i].disabled || dev->states_usage[i].disable) - continue; - - limit = (u64)drv->states[i].target_residency * NSEC_PER_USEC; - break; - } + limit = cpuidle_poll_time(drv, dev); while (!need_resched()) { cpu_relax(); diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index eb20adb5de23..2bb2683b493c 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -334,6 +334,7 @@ struct cpuidle_state_kobj { struct cpuidle_state_usage *state_usage; struct completion kobj_unregister; struct kobject kobj; + struct cpuidle_device *device; }; #ifdef CONFIG_SUSPEND @@ -391,6 +392,7 @@ static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *k #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj) #define kobj_to_state(k) (kobj_to_state_obj(k)->state) #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) +#define kobj_to_device(k) (kobj_to_state_obj(k)->device) #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr, @@ -414,10 +416,14 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr, struct cpuidle_state *state = kobj_to_state(kobj); struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); + struct cpuidle_device *dev = kobj_to_device(kobj); if (cattr->store) ret = cattr->store(state, state_usage, buf, size); + /* reset poll time cache */ + dev->poll_limit_ns = 0; + return ret; } @@ -468,6 +474,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) } kobj->state = &drv->states[i]; kobj->state_usage = &device->states_usage[i]; + kobj->device = device; init_completion(&kobj->kobj_unregister); ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index bb9a0db89f1a..b484dd69ec21 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -86,6 +86,7 @@ struct cpuidle_device { ktime_t next_hrtimer; int last_residency; + u64 poll_limit_ns; struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; struct cpuidle_driver_kobj *kobj_driver; @@ -132,6 +133,8 @@ extern int cpuidle_select(struct cpuidle_driver *drv, extern int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index); extern void cpuidle_reflect(struct cpuidle_device *dev, int index); +extern u64 cpuidle_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev); extern int cpuidle_register_driver(struct cpuidle_driver *drv); extern struct cpuidle_driver *cpuidle_get_driver(void); @@ -166,6 +169,9 @@ static inline int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) {return -ENODEV; } static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } +extern u64 cpuidle_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{return 0; } static inline int cpuidle_register_driver(struct cpuidle_driver *drv) {return -ENODEV; } static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } -- GitLab From 7d4daeedd575bbc3c40c87fc6708a8b88c50fe7e Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 3 Jul 2019 20:51:27 -0300 Subject: [PATCH 1297/7155] governors: unify last_state_idx Since this field is shared by all governors, move it to cpuidle device structure. Signed-off-by: Marcelo Tosatti Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/ladder.c | 21 ++++++++++----------- drivers/cpuidle/governors/menu.c | 5 ++--- drivers/cpuidle/governors/teo.c | 12 ++++++------ include/linux/cpuidle.h | 1 + 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index f0dddc66af26..428eeb832fe7 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -38,7 +38,6 @@ struct ladder_device_state { struct ladder_device { struct ladder_device_state states[CPUIDLE_STATE_MAX]; - int last_state_idx; }; static DEFINE_PER_CPU(struct ladder_device, ladder_devices); @@ -49,12 +48,13 @@ static DEFINE_PER_CPU(struct ladder_device, ladder_devices); * @old_idx: the current state index * @new_idx: the new target state index */ -static inline void ladder_do_selection(struct ladder_device *ldev, +static inline void ladder_do_selection(struct cpuidle_device *dev, + struct ladder_device *ldev, int old_idx, int new_idx) { ldev->states[old_idx].stats.promotion_count = 0; ldev->states[old_idx].stats.demotion_count = 0; - ldev->last_state_idx = new_idx; + dev->last_state_idx = new_idx; } /** @@ -68,13 +68,13 @@ static int ladder_select_state(struct cpuidle_driver *drv, { struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); struct ladder_device_state *last_state; - int last_residency, last_idx = ldev->last_state_idx; + int last_residency, last_idx = dev->last_state_idx; int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0; int latency_req = cpuidle_governor_latency_req(dev->cpu); /* Special case when user has set very strict latency requirement */ if (unlikely(latency_req == 0)) { - ladder_do_selection(ldev, last_idx, 0); + ladder_do_selection(dev, ldev, last_idx, 0); return 0; } @@ -91,7 +91,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, last_state->stats.promotion_count++; last_state->stats.demotion_count = 0; if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { - ladder_do_selection(ldev, last_idx, last_idx + 1); + ladder_do_selection(dev, ldev, last_idx, last_idx + 1); return last_idx + 1; } } @@ -107,7 +107,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, if (drv->states[i].exit_latency <= latency_req) break; } - ladder_do_selection(ldev, last_idx, i); + ladder_do_selection(dev, ldev, last_idx, i); return i; } @@ -116,7 +116,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, last_state->stats.demotion_count++; last_state->stats.promotion_count = 0; if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) { - ladder_do_selection(ldev, last_idx, last_idx - 1); + ladder_do_selection(dev, ldev, last_idx, last_idx - 1); return last_idx - 1; } } @@ -139,7 +139,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, struct ladder_device_state *lstate; struct cpuidle_state *state; - ldev->last_state_idx = first_idx; + dev->last_state_idx = first_idx; for (i = first_idx; i < drv->state_count; i++) { state = &drv->states[i]; @@ -167,9 +167,8 @@ static int ladder_enable_device(struct cpuidle_driver *drv, */ static void ladder_reflect(struct cpuidle_device *dev, int index) { - struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); if (index > 0) - ldev->last_state_idx = index; + dev->last_state_idx = index; } static struct cpuidle_governor ladder_governor = { diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index e9a28c7846d6..dace4c7f830c 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -117,7 +117,6 @@ */ struct menu_device { - int last_state_idx; int needs_update; int tick_wakeup; @@ -455,7 +454,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index) { struct menu_device *data = this_cpu_ptr(&menu_devices); - data->last_state_idx = index; + dev->last_state_idx = index; data->needs_update = 1; data->tick_wakeup = tick_nohz_idle_got_tick(); } @@ -468,7 +467,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index) static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = this_cpu_ptr(&menu_devices); - int last_idx = data->last_state_idx; + int last_idx = dev->last_state_idx; struct cpuidle_state *target = &drv->states[last_idx]; unsigned int measured_us; unsigned int new_factor; diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c index 7d05efdbd3c6..a2fd81067a13 100644 --- a/drivers/cpuidle/governors/teo.c +++ b/drivers/cpuidle/governors/teo.c @@ -96,7 +96,6 @@ struct teo_idle_state { * @time_span_ns: Time between idle state selection and post-wakeup update. * @sleep_length_ns: Time till the closest timer event (at the selection time). * @states: Idle states data corresponding to this CPU. - * @last_state: Idle state entered by the CPU last time. * @interval_idx: Index of the most recent saved idle interval. * @intervals: Saved idle duration values. */ @@ -104,7 +103,6 @@ struct teo_cpu { u64 time_span_ns; u64 sleep_length_ns; struct teo_idle_state states[CPUIDLE_STATE_MAX]; - int last_state; int interval_idx; unsigned int intervals[INTERVALS]; }; @@ -130,7 +128,9 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) */ measured_us = sleep_length_us; } else { - unsigned int lat = drv->states[cpu_data->last_state].exit_latency; + unsigned int lat; + + lat = drv->states[dev->last_state_idx].exit_latency; measured_us = ktime_to_us(cpu_data->time_span_ns); /* @@ -245,9 +245,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, int max_early_idx, idx, i; ktime_t delta_tick; - if (cpu_data->last_state >= 0) { + if (dev->last_state_idx >= 0) { teo_update(drv, dev); - cpu_data->last_state = -1; + dev->last_state_idx = -1; } cpu_data->time_span_ns = local_clock(); @@ -394,7 +394,7 @@ static void teo_reflect(struct cpuidle_device *dev, int state) { struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); - cpu_data->last_state = state; + dev->last_state_idx = state; /* * If the wakeup was not "natural", but triggered by one of the safety * nets, assume that the CPU might have been idle for the entire sleep diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index b484dd69ec21..ba535a1a47d5 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -85,6 +85,7 @@ struct cpuidle_device { unsigned int cpu; ktime_t next_hrtimer; + int last_state_idx; int last_residency; u64 poll_limit_ns; struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; -- GitLab From 2cffe9f6b96fece065ee8522673c90e92ef2085d Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 3 Jul 2019 20:51:28 -0300 Subject: [PATCH 1298/7155] cpuidle: add haltpoll governor The cpuidle_haltpoll governor, in conjunction with the haltpoll cpuidle driver, allows guest vcpus to poll for a specified amount of time before halting. This provides the following benefits to host side polling: 1) The POLL flag is set while polling is performed, which allows a remote vCPU to avoid sending an IPI (and the associated cost of handling the IPI) when performing a wakeup. 2) The VM-exit cost can be avoided. The downside of guest side polling is that polling is performed even with other runnable tasks in the host. Results comparing halt_poll_ns and server/client application where a small packet is ping-ponged: host --> 31.33 halt_poll_ns=300000 / no guest busy spin --> 33.40 (93.8%) halt_poll_ns=0 / guest_halt_poll_ns=300000 --> 32.73 (95.7%) For the SAP HANA benchmarks (where idle_spin is a parameter of the previous version of the patch, results should be the same): hpns == halt_poll_ns idle_spin=0/ idle_spin=800/ idle_spin=0/ hpns=200000 hpns=0 hpns=800000 DeleteC06T03 (100 thread) 1.76 1.71 (-3%) 1.78 (+1%) InsertC16T02 (100 thread) 2.14 2.07 (-3%) 2.18 (+1.8%) DeleteC00T01 (1 thread) 1.34 1.28 (-4.5%) 1.29 (-3.7%) UpdateC00T03 (1 thread) 4.72 4.18 (-12%) 4.53 (-5%) Signed-off-by: Marcelo Tosatti Signed-off-by: Rafael J. Wysocki --- Documentation/virtual/guest-halt-polling.txt | 78 ++++++++++ drivers/cpuidle/Kconfig | 11 ++ drivers/cpuidle/governors/Makefile | 1 + drivers/cpuidle/governors/haltpoll.c | 150 +++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 Documentation/virtual/guest-halt-polling.txt create mode 100644 drivers/cpuidle/governors/haltpoll.c diff --git a/Documentation/virtual/guest-halt-polling.txt b/Documentation/virtual/guest-halt-polling.txt new file mode 100644 index 000000000000..b3a2a294532d --- /dev/null +++ b/Documentation/virtual/guest-halt-polling.txt @@ -0,0 +1,78 @@ +Guest halt polling +================== + +The cpuidle_haltpoll driver, with the haltpoll governor, allows +the guest vcpus to poll for a specified amount of time before +halting. +This provides the following benefits to host side polling: + + 1) The POLL flag is set while polling is performed, which allows + a remote vCPU to avoid sending an IPI (and the associated + cost of handling the IPI) when performing a wakeup. + + 2) The VM-exit cost can be avoided. + +The downside of guest side polling is that polling is performed +even with other runnable tasks in the host. + +The basic logic as follows: A global value, guest_halt_poll_ns, +is configured by the user, indicating the maximum amount of +time polling is allowed. This value is fixed. + +Each vcpu has an adjustable guest_halt_poll_ns +("per-cpu guest_halt_poll_ns"), which is adjusted by the algorithm +in response to events (explained below). + +Module Parameters +================= + +The haltpoll governor has 5 tunable module parameters: + +1) guest_halt_poll_ns: +Maximum amount of time, in nanoseconds, that polling is +performed before halting. + +Default: 200000 + +2) guest_halt_poll_shrink: +Division factor used to shrink per-cpu guest_halt_poll_ns when +wakeup event occurs after the global guest_halt_poll_ns. + +Default: 2 + +3) guest_halt_poll_grow: +Multiplication factor used to grow per-cpu guest_halt_poll_ns +when event occurs after per-cpu guest_halt_poll_ns +but before global guest_halt_poll_ns. + +Default: 2 + +4) guest_halt_poll_grow_start: +The per-cpu guest_halt_poll_ns eventually reaches zero +in case of an idle system. This value sets the initial +per-cpu guest_halt_poll_ns when growing. This can +be increased from 10000, to avoid misses during the initial +growth stage: + +10k, 20k, 40k, ... (example assumes guest_halt_poll_grow=2). + +Default: 50000 + +5) guest_halt_poll_allow_shrink: + +Bool parameter which allows shrinking. Set to N +to avoid it (per-cpu guest_halt_poll_ns will remain +high once achieves global guest_halt_poll_ns value). + +Default: Y + +The module parameters can be set from the debugfs files in: + + /sys/module/haltpoll/parameters/ + +Further Notes +============= + +- Care should be taken when setting the guest_halt_poll_ns parameter as a +large value has the potential to drive the cpu usage to 100% on a machine which +would be almost entirely idle otherwise. diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index cc8efc56be7d..88727b7c0d59 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -33,6 +33,17 @@ config CPU_IDLE_GOV_TEO Some workloads benefit from using it and it generally should be safe to use. Say Y here if you are not happy with the alternatives. +config CPU_IDLE_GOV_HALTPOLL + bool "Haltpoll governor (for virtualized systems)" + depends on KVM_GUEST + help + This governor implements haltpoll idle state selection, to be + used in conjunction with the haltpoll cpuidle driver, allowing + for polling for a certain amount of time before entering idle + state. + + Some virtualized workloads benefit from using it. + config DT_IDLE_STATES bool diff --git a/drivers/cpuidle/governors/Makefile b/drivers/cpuidle/governors/Makefile index 42f44cc610dd..63abb5393a4d 100644 --- a/drivers/cpuidle/governors/Makefile +++ b/drivers/cpuidle/governors/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o obj-$(CONFIG_CPU_IDLE_GOV_TEO) += teo.o +obj-$(CONFIG_CPU_IDLE_GOV_HALTPOLL) += haltpoll.o diff --git a/drivers/cpuidle/governors/haltpoll.c b/drivers/cpuidle/governors/haltpoll.c new file mode 100644 index 000000000000..797477bda486 --- /dev/null +++ b/drivers/cpuidle/governors/haltpoll.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * haltpoll.c - haltpoll idle governor + * + * Copyright 2019 Red Hat, Inc. and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Authors: Marcelo Tosatti + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int guest_halt_poll_ns __read_mostly = 200000; +module_param(guest_halt_poll_ns, uint, 0644); + +/* division factor to shrink halt_poll_ns */ +static unsigned int guest_halt_poll_shrink __read_mostly = 2; +module_param(guest_halt_poll_shrink, uint, 0644); + +/* multiplication factor to grow per-cpu poll_limit_ns */ +static unsigned int guest_halt_poll_grow __read_mostly = 2; +module_param(guest_halt_poll_grow, uint, 0644); + +/* value in us to start growing per-cpu halt_poll_ns */ +static unsigned int guest_halt_poll_grow_start __read_mostly = 50000; +module_param(guest_halt_poll_grow_start, uint, 0644); + +/* allow shrinking guest halt poll */ +static bool guest_halt_poll_allow_shrink __read_mostly = true; +module_param(guest_halt_poll_allow_shrink, bool, 0644); + +/** + * haltpoll_select - selects the next idle state to enter + * @drv: cpuidle driver containing state data + * @dev: the CPU + * @stop_tick: indication on whether or not to stop the tick + */ +static int haltpoll_select(struct cpuidle_driver *drv, + struct cpuidle_device *dev, + bool *stop_tick) +{ + int latency_req = cpuidle_governor_latency_req(dev->cpu); + + if (!drv->state_count || latency_req == 0) { + *stop_tick = false; + return 0; + } + + if (dev->poll_limit_ns == 0) + return 1; + + /* Last state was poll? */ + if (dev->last_state_idx == 0) { + /* Halt if no event occurred on poll window */ + if (dev->poll_time_limit == true) + return 1; + + *stop_tick = false; + /* Otherwise, poll again */ + return 0; + } + + *stop_tick = false; + /* Last state was halt: poll */ + return 0; +} + +static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us) +{ + unsigned int val; + u64 block_ns = block_us*NSEC_PER_USEC; + + /* Grow cpu_halt_poll_us if + * cpu_halt_poll_us < block_ns < guest_halt_poll_us + */ + if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) { + val = dev->poll_limit_ns * guest_halt_poll_grow; + + if (val < guest_halt_poll_grow_start) + val = guest_halt_poll_grow_start; + if (val > guest_halt_poll_ns) + val = guest_halt_poll_ns; + + dev->poll_limit_ns = val; + } else if (block_ns > guest_halt_poll_ns && + guest_halt_poll_allow_shrink) { + unsigned int shrink = guest_halt_poll_shrink; + + val = dev->poll_limit_ns; + if (shrink == 0) + val = 0; + else + val /= shrink; + dev->poll_limit_ns = val; + } +} + +/** + * haltpoll_reflect - update variables and update poll time + * @dev: the CPU + * @index: the index of actual entered state + */ +static void haltpoll_reflect(struct cpuidle_device *dev, int index) +{ + dev->last_state_idx = index; + + if (index != 0) + adjust_poll_limit(dev, dev->last_residency); +} + +/** + * haltpoll_enable_device - scans a CPU's states and does setup + * @drv: cpuidle driver + * @dev: the CPU + */ +static int haltpoll_enable_device(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{ + dev->poll_limit_ns = 0; + + return 0; +} + +static struct cpuidle_governor haltpoll_governor = { + .name = "haltpoll", + .rating = 21, + .enable = haltpoll_enable_device, + .select = haltpoll_select, + .reflect = haltpoll_reflect, +}; + +static int __init init_haltpoll(void) +{ + if (kvm_para_available()) + return cpuidle_register_governor(&haltpoll_governor); + + return 0; +} + +postcore_initcall(init_haltpoll); -- GitLab From a1c4423b02b2121108e3ea9580741e0f26309a48 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 3 Jul 2019 20:51:29 -0300 Subject: [PATCH 1299/7155] cpuidle-haltpoll: disable host side polling when kvm virtualized When performing guest side polling, it is not necessary to also perform host side polling. So disable host side polling, via the new MSR interface, when loading cpuidle-haltpoll driver. Signed-off-by: Marcelo Tosatti Signed-off-by: Rafael J. Wysocki --- arch/x86/Kconfig | 7 +++++ arch/x86/include/asm/cpuidle_haltpoll.h | 8 +++++ arch/x86/kernel/kvm.c | 42 +++++++++++++++++++++++++ drivers/cpuidle/cpuidle-haltpoll.c | 9 +++++- include/linux/cpuidle_haltpoll.h | 16 ++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 arch/x86/include/asm/cpuidle_haltpoll.h create mode 100644 include/linux/cpuidle_haltpoll.h diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 222855cc0158..05e78acb187c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -794,6 +794,7 @@ config KVM_GUEST bool "KVM Guest support (including kvmclock)" depends on PARAVIRT select PARAVIRT_CLOCK + select ARCH_CPUIDLE_HALTPOLL default y ---help--- This option enables various optimizations for running under the KVM @@ -802,6 +803,12 @@ config KVM_GUEST underlying device model, the host provides the guest with timing infrastructure such as time of day, and system time +config ARCH_CPUIDLE_HALTPOLL + def_bool n + prompt "Disable host haltpoll when loading haltpoll driver" + help + If virtualized under KVM, disable host haltpoll. + config PVH bool "Support for running PVH guests" ---help--- diff --git a/arch/x86/include/asm/cpuidle_haltpoll.h b/arch/x86/include/asm/cpuidle_haltpoll.h new file mode 100644 index 000000000000..ff8607d81526 --- /dev/null +++ b/arch/x86/include/asm/cpuidle_haltpoll.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ARCH_HALTPOLL_H +#define _ARCH_HALTPOLL_H + +void arch_haltpoll_enable(void); +void arch_haltpoll_disable(void); + +#endif diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b7f34fe2171e..f48401be8ce0 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -875,3 +875,45 @@ void __init kvm_spinlock_init(void) } #endif /* CONFIG_PARAVIRT_SPINLOCKS */ + +#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL + +static void kvm_disable_host_haltpoll(void *i) +{ + wrmsrl(MSR_KVM_POLL_CONTROL, 0); +} + +static void kvm_enable_host_haltpoll(void *i) +{ + wrmsrl(MSR_KVM_POLL_CONTROL, 1); +} + +void arch_haltpoll_enable(void) +{ + if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) { + printk(KERN_ERR "kvm: host does not support poll control\n"); + printk(KERN_ERR "kvm: host upgrade recommended\n"); + return; + } + + preempt_disable(); + /* Enable guest halt poll disables host halt poll */ + kvm_disable_host_haltpoll(NULL); + smp_call_function(kvm_disable_host_haltpoll, NULL, 1); + preempt_enable(); +} +EXPORT_SYMBOL_GPL(arch_haltpoll_enable); + +void arch_haltpoll_disable(void) +{ + if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) + return; + + preempt_disable(); + /* Enable guest halt poll disables host halt poll */ + kvm_enable_host_haltpoll(NULL); + smp_call_function(kvm_enable_host_haltpoll, NULL, 1); + preempt_enable(); +} +EXPORT_SYMBOL_GPL(arch_haltpoll_disable); +#endif diff --git a/drivers/cpuidle/cpuidle-haltpoll.c b/drivers/cpuidle/cpuidle-haltpoll.c index 35cfb53e9287..9ac093dcbb01 100644 --- a/drivers/cpuidle/cpuidle-haltpoll.c +++ b/drivers/cpuidle/cpuidle-haltpoll.c @@ -15,6 +15,7 @@ #include #include #include +#include static int default_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -47,6 +48,7 @@ static struct cpuidle_driver haltpoll_driver = { static int __init haltpoll_init(void) { + int ret; struct cpuidle_driver *drv = &haltpoll_driver; cpuidle_poll_state_init(drv); @@ -54,11 +56,16 @@ static int __init haltpoll_init(void) if (!kvm_para_available()) return 0; - return cpuidle_register(&haltpoll_driver, NULL); + ret = cpuidle_register(&haltpoll_driver, NULL); + if (ret == 0) + arch_haltpoll_enable(); + + return ret; } static void __exit haltpoll_exit(void) { + arch_haltpoll_disable(); cpuidle_unregister(&haltpoll_driver); } diff --git a/include/linux/cpuidle_haltpoll.h b/include/linux/cpuidle_haltpoll.h new file mode 100644 index 000000000000..fe5954c2409e --- /dev/null +++ b/include/linux/cpuidle_haltpoll.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _CPUIDLE_HALTPOLL_H +#define _CPUIDLE_HALTPOLL_H + +#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL +#include +#else +static inline void arch_haltpoll_enable(void) +{ +} + +static inline void arch_haltpoll_disable(void) +{ +} +#endif +#endif -- GitLab From 7c490e2561f271a59605ac31e2582d62c918715d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 Jul 2019 07:27:03 -0400 Subject: [PATCH 1300/7155] media: v4l2-ioctl.c: OR flags in v4l_fill_fmtdesc(), not don't overwrite If a driver sets a FMT flag in the enum_fmt op, then that will be ignored since v4l_fill_fmtdesc() overwrites it again. v4l_fill_fmtdesc() should OR its flag, not overwrite it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 9484cc2619e4..bb5b4926538a 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1395,7 +1395,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) if (descr) WARN_ON(strscpy(fmt->description, descr, sz) < 0); - fmt->flags = flags; + fmt->flags |= flags; } static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, -- GitLab From 4b4d62b03191700f3245941146a8510d31ec66b3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 Jul 2019 07:27:06 -0400 Subject: [PATCH 1301/7155] media: videodev2.h.rst.exceptions: tymecode -> timecode Fix typo. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/videodev2.h.rst.exceptions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions index 55cbe324b9fc..8e7d3492d248 100644 --- a/Documentation/media/videodev2.h.rst.exceptions +++ b/Documentation/media/videodev2.h.rst.exceptions @@ -181,14 +181,14 @@ replace define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA reserved-formats replace define V4L2_FMT_FLAG_COMPRESSED fmtdesc-flags replace define V4L2_FMT_FLAG_EMULATED fmtdesc-flags -# V4L2 tymecode types +# V4L2 timecode types replace define V4L2_TC_TYPE_24FPS timecode-type replace define V4L2_TC_TYPE_25FPS timecode-type replace define V4L2_TC_TYPE_30FPS timecode-type replace define V4L2_TC_TYPE_50FPS timecode-type replace define V4L2_TC_TYPE_60FPS timecode-type -# V4L2 tymecode flags +# V4L2 timecode flags replace define V4L2_TC_FLAG_DROPFRAME timecode-flags replace define V4L2_TC_FLAG_COLORFRAME timecode-flags replace define V4L2_TC_USERBITS_field timecode-flags -- GitLab From 1e42d384aa19e06410be52bd05cfc159722c0b7f Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Thu, 25 Jul 2019 14:55:59 -0400 Subject: [PATCH 1302/7155] media: v4l2-ctrl: Add a comment on why we zero out compound controls fields Since it's not necessarily very explicit why we need to zero some fields in std_validate_compound, add a comment before the function to explain why, which should help as a reminder. Signed-off-by: Paul Kocialkowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 76fa2db0e8fb..cd1ae016706f 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1645,6 +1645,10 @@ static void std_log(const struct v4l2_ctrl *ctrl) #define zero_padding(s) \ memset(&(s).padding, 0, sizeof((s).padding)) +/* + * Compound controls validation requires setting unused fields/flags to zero + * in order to properly detect unchanged controls with std_equal's memcmp. + */ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr) { -- GitLab From cad2991a950198f71520e8bbbe9d1ea9d001e7f0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jul 2019 08:08:19 -0400 Subject: [PATCH 1303/7155] media: v4l2-tpg: add support for new pixelformats Several new variations of RGB444, RGB555 and RGB32 were added. Add support for these. This is the list of new pixelformats: V4L2_PIX_FMT_RGBX444 V4L2_PIX_FMT_RGBA444 V4L2_PIX_FMT_XBGR444 V4L2_PIX_FMT_ABGR444 V4L2_PIX_FMT_BGRX444 V4L2_PIX_FMT_BGRA444 V4L2_PIX_FMT_RGBX555 V4L2_PIX_FMT_RGBA555 V4L2_PIX_FMT_XBGR555 V4L2_PIX_FMT_ABGR555 V4L2_PIX_FMT_BGRX555 V4L2_PIX_FMT_BGRA555 V4L2_PIX_FMT_RGBX32 V4L2_PIX_FMT_BGRX32 V4L2_PIX_FMT_RGBA32 V4L2_PIX_FMT_BGRA32 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/v4l2-tpg/v4l2-tpg-core.c | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index 07e0629af8ed..50f1e0b28b25 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -217,9 +217,21 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_RGB444: case V4L2_PIX_FMT_XRGB444: case V4L2_PIX_FMT_ARGB444: + case V4L2_PIX_FMT_RGBX444: + case V4L2_PIX_FMT_RGBA444: + case V4L2_PIX_FMT_XBGR444: + case V4L2_PIX_FMT_ABGR444: + case V4L2_PIX_FMT_BGRX444: + case V4L2_PIX_FMT_BGRA444: case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_XRGB555: case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGBX555: + case V4L2_PIX_FMT_RGBA555: + case V4L2_PIX_FMT_XBGR555: + case V4L2_PIX_FMT_ABGR555: + case V4L2_PIX_FMT_BGRX555: + case V4L2_PIX_FMT_BGRA555: case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_XRGB555X: case V4L2_PIX_FMT_ARGB555X: @@ -232,6 +244,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_ARGB32: case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_RGBX32: + case V4L2_PIX_FMT_BGRX32: + case V4L2_PIX_FMT_RGBA32: + case V4L2_PIX_FMT_BGRA32: tpg->color_enc = TGP_COLOR_ENC_RGB; break; case V4L2_PIX_FMT_GREY: @@ -343,9 +359,21 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_RGB444: case V4L2_PIX_FMT_XRGB444: case V4L2_PIX_FMT_ARGB444: + case V4L2_PIX_FMT_RGBX444: + case V4L2_PIX_FMT_RGBA444: + case V4L2_PIX_FMT_XBGR444: + case V4L2_PIX_FMT_ABGR444: + case V4L2_PIX_FMT_BGRX444: + case V4L2_PIX_FMT_BGRA444: case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_XRGB555: case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGBX555: + case V4L2_PIX_FMT_RGBA555: + case V4L2_PIX_FMT_XBGR555: + case V4L2_PIX_FMT_ABGR555: + case V4L2_PIX_FMT_BGRX555: + case V4L2_PIX_FMT_BGRA555: case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_XRGB555X: case V4L2_PIX_FMT_ARGB555X: @@ -375,6 +403,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_ARGB32: case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_RGBX32: + case V4L2_PIX_FMT_BGRX32: + case V4L2_PIX_FMT_RGBA32: + case V4L2_PIX_FMT_BGRA32: case V4L2_PIX_FMT_YUV32: case V4L2_PIX_FMT_AYUV32: case V4L2_PIX_FMT_XYUV32: @@ -1007,6 +1039,12 @@ static void precalculate_color(struct tpg_data *tpg, int k) case V4L2_PIX_FMT_RGB444: case V4L2_PIX_FMT_XRGB444: case V4L2_PIX_FMT_ARGB444: + case V4L2_PIX_FMT_RGBX444: + case V4L2_PIX_FMT_RGBA444: + case V4L2_PIX_FMT_XBGR444: + case V4L2_PIX_FMT_ABGR444: + case V4L2_PIX_FMT_BGRX444: + case V4L2_PIX_FMT_BGRA444: r >>= 8; g >>= 8; b >>= 8; @@ -1014,6 +1052,12 @@ static void precalculate_color(struct tpg_data *tpg, int k) case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_XRGB555: case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_RGBX555: + case V4L2_PIX_FMT_RGBA555: + case V4L2_PIX_FMT_XBGR555: + case V4L2_PIX_FMT_ABGR555: + case V4L2_PIX_FMT_BGRX555: + case V4L2_PIX_FMT_BGRA555: case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_XRGB555X: case V4L2_PIX_FMT_ARGB555X: @@ -1237,6 +1281,27 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset] = (g_u_s << 4) | b_v; buf[0][offset + 1] = (alpha & 0xf0) | r_y_h; break; + case V4L2_PIX_FMT_RGBX444: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_RGBA444: + buf[0][offset] = (b_v << 4) | (alpha >> 4); + buf[0][offset + 1] = (r_y_h << 4) | g_u_s; + break; + case V4L2_PIX_FMT_XBGR444: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_ABGR444: + buf[0][offset] = (g_u_s << 4) | r_y_h; + buf[0][offset + 1] = (alpha & 0xf0) | b_v; + break; + case V4L2_PIX_FMT_BGRX444: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_BGRA444: + buf[0][offset] = (r_y_h << 4) | (alpha >> 4); + buf[0][offset + 1] = (b_v << 4) | g_u_s; + break; case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_XRGB555: alpha = 0; @@ -1247,6 +1312,30 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset + 1] = (alpha & 0x80) | (r_y_h << 2) | (g_u_s >> 3); break; + case V4L2_PIX_FMT_RGBX555: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_RGBA555: + buf[0][offset] = (g_u_s << 6) | (b_v << 1) | + ((alpha & 0x80) >> 7); + buf[0][offset + 1] = (r_y_h << 3) | (g_u_s >> 2); + break; + case V4L2_PIX_FMT_XBGR555: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_ABGR555: + buf[0][offset] = (g_u_s << 5) | r_y_h; + buf[0][offset + 1] = (alpha & 0x80) | (b_v << 2) + | (g_u_s >> 3); + break; + case V4L2_PIX_FMT_BGRX555: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_BGRA555: + buf[0][offset] = (g_u_s << 6) | (r_y_h << 1) | + ((alpha & 0x80) >> 7); + buf[0][offset + 1] = (b_v << 3) | (g_u_s >> 2); + break; case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_XRGB555X: alpha = 0; @@ -1286,6 +1375,15 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset + 2] = g_u_s; buf[0][offset + 3] = b_v; break; + case V4L2_PIX_FMT_RGBX32: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_RGBA32: + buf[0][offset] = r_y_h; + buf[0][offset + 1] = g_u_s; + buf[0][offset + 2] = b_v; + buf[0][offset + 3] = alpha; + break; case V4L2_PIX_FMT_BGR32: case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_VUYX32: @@ -1298,6 +1396,15 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset + 2] = r_y_h; buf[0][offset + 3] = alpha; break; + case V4L2_PIX_FMT_BGRX32: + alpha = 0; + /* fall through */ + case V4L2_PIX_FMT_BGRA32: + buf[0][offset] = alpha; + buf[0][offset + 1] = b_v; + buf[0][offset + 2] = g_u_s; + buf[0][offset + 3] = r_y_h; + break; case V4L2_PIX_FMT_SBGGR8: buf[0][offset] = odd ? g_u_s : b_v; buf[1][offset] = odd ? r_y_h : g_u_s; -- GitLab From 079a649c75252b76799713262835cc5200013149 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jul 2019 08:08:20 -0400 Subject: [PATCH 1304/7155] media: v4l2-common: add support for new RGB32 pixelformats Four new variants of RGB32 were added. Add support for them to the v4l2_format_info() function. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index f8ad1c580a3e..ab4a792a3bc1 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -455,11 +455,15 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) { .format = V4L2_PIX_FMT_HSV24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_BGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_XBGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRX32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_RGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_XRGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBX32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_HSV32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_ARGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBA32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_ABGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRA32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, { .format = V4L2_PIX_FMT_GREY, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, /* YUV packed formats */ -- GitLab From 4e4f3b99b41ff3e5cd85e6a309e423b5721ca8ce Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jul 2019 08:08:21 -0400 Subject: [PATCH 1305/7155] media: vivid: add support for new pixelformats New RGB444, RGB555 and RGB32 variants were recently added. Now also support them in vivid. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vivid/vivid-vid-common.c | 132 +++++++++++++++++- 1 file changed, 129 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index 1f33eb1a76b6..8665dfd25eb4 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -262,21 +262,66 @@ struct vivid_fmt vivid_formats[] = { .can_do_overlay = true, }, { - .fourcc = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */ + .fourcc = V4L2_PIX_FMT_RGB444, /* ggggbbbb xxxxrrrr */ .vdownsampling = { 1 }, .bit_depth = { 16 }, .planes = 1, .buffers = 1, }, { - .fourcc = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */ + .fourcc = V4L2_PIX_FMT_XRGB444, /* ggggbbbb xxxxrrrr */ .vdownsampling = { 1 }, .bit_depth = { 16 }, .planes = 1, .buffers = 1, }, { - .fourcc = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */ + .fourcc = V4L2_PIX_FMT_ARGB444, /* ggggbbbb aaaarrrr */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .alpha_mask = 0x00f0, + }, + { + .fourcc = V4L2_PIX_FMT_RGBX444, /* bbbbxxxx rrrrgggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_RGBA444, /* bbbbaaaa rrrrgggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .alpha_mask = 0x00f0, + }, + { + .fourcc = V4L2_PIX_FMT_XBGR444, /* ggggrrrr xxxxbbbb */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_ABGR444, /* ggggrrrr aaaabbbb */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .alpha_mask = 0x00f0, + }, + { + .fourcc = V4L2_PIX_FMT_BGRX444, /* rrrrxxxx bbbbgggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_BGRA444, /* rrrraaaa bbbbgggg */ .vdownsampling = { 1 }, .bit_depth = { 16 }, .planes = 1, @@ -308,6 +353,57 @@ struct vivid_fmt vivid_formats[] = { .can_do_overlay = true, .alpha_mask = 0x8000, }, + { + .fourcc = V4L2_PIX_FMT_RGBX555, /* ggbbbbbx rrrrrggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + }, + { + .fourcc = V4L2_PIX_FMT_RGBA555, /* ggbbbbba rrrrrggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + .alpha_mask = 0x8000, + }, + { + .fourcc = V4L2_PIX_FMT_XBGR555, /* gggrrrrr xbbbbbgg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + }, + { + .fourcc = V4L2_PIX_FMT_ABGR555, /* gggrrrrr abbbbbgg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + .alpha_mask = 0x8000, + }, + { + .fourcc = V4L2_PIX_FMT_BGRX555, /* ggrrrrrx bbbbbggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + }, + { + .fourcc = V4L2_PIX_FMT_BGRA555, /* ggrrrrra bbbbbggg */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + .can_do_overlay = true, + .alpha_mask = 0x8000, + }, { .fourcc = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */ .vdownsampling = { 1 }, @@ -395,6 +491,36 @@ struct vivid_fmt vivid_formats[] = { .buffers = 1, .alpha_mask = 0xff000000, }, + { + .fourcc = V4L2_PIX_FMT_RGBX32, /* rgbx */ + .vdownsampling = { 1 }, + .bit_depth = { 32 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_BGRX32, /* xbgr */ + .vdownsampling = { 1 }, + .bit_depth = { 32 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_RGBA32, /* rgba */ + .vdownsampling = { 1 }, + .bit_depth = { 32 }, + .planes = 1, + .buffers = 1, + .alpha_mask = 0x000000ff, + }, + { + .fourcc = V4L2_PIX_FMT_BGRA32, /* abgr */ + .vdownsampling = { 1 }, + .bit_depth = { 32 }, + .planes = 1, + .buffers = 1, + .alpha_mask = 0xff000000, + }, { .fourcc = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */ .vdownsampling = { 1 }, -- GitLab From 4590c07462fbff4ecbfe1deec44431c16191bd19 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Jul 2019 10:43:41 -0400 Subject: [PATCH 1306/7155] media: via-camera: convert to the vb2 framework Convert the via-camera to the vb2 framework. With this change this driver passes all 'v4l2-compliance -s' tests on my OLPC 1.5. Also tested with the Sugar 'Record' application. All tests were done under the OLPC official 5.0.8 kernel. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 2 +- drivers/media/platform/via-camera.c | 492 +++++++++------------------- 2 files changed, 159 insertions(+), 335 deletions(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 8a19654b393a..89555f9a813f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -16,7 +16,7 @@ source "drivers/media/platform/marvell-ccic/Kconfig" config VIDEO_VIA_CAMERA tristate "VIAFB camera controller support" depends on FB_VIA - select VIDEOBUF_DMA_SG + select VIDEOBUF2_DMA_SG select VIDEO_OV7670 help Driver support for the integrated camera controller in VIA diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 24c5d2a7b91f..78841b9015ce 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,16 +85,11 @@ struct via_camera { * live in frame buffer memory, so we don't call them "DMA". */ unsigned int cb_offsets[3]; /* offsets into fb mem */ - u8 __iomem *cb_addrs[3]; /* Kernel-space addresses */ + u8 __iomem *cb_addrs[3]; /* Kernel-space addresses */ int n_cap_bufs; /* How many are we using? */ - int next_buf; - struct videobuf_queue vb_queue; - struct list_head buffer_queue; /* prot. by reg_lock */ - /* - * User tracking. - */ - int users; - struct file *owner; + struct vb2_queue vq; + struct list_head buffer_queue; + u32 sequence; /* * Video format information. sensor_format is kept in a form * that we can use to pass to the sensor. We always run the @@ -107,6 +102,13 @@ struct via_camera { u32 mbus_code; }; +/* buffer for one video frame */ +struct via_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vbuf; + struct list_head queue; +}; + /* * Yes, this is a hack, but there's only going to be one of these * on any system we know of. @@ -323,28 +325,15 @@ static irqreturn_t viacam_quick_irq(int irq, void *data) } /* - * Find the next videobuf buffer which has somebody waiting on it. + * Find the next buffer which has somebody waiting on it. */ -static struct videobuf_buffer *viacam_next_buffer(struct via_camera *cam) +static struct via_buffer *viacam_next_buffer(struct via_camera *cam) { - unsigned long flags; - struct videobuf_buffer *buf = NULL; - - spin_lock_irqsave(&cam->viadev->reg_lock, flags); if (cam->opstate != S_RUNNING) - goto out; + return NULL; if (list_empty(&cam->buffer_queue)) - goto out; - buf = list_entry(cam->buffer_queue.next, struct videobuf_buffer, queue); - if (!waitqueue_active(&buf->done)) {/* Nobody waiting */ - buf = NULL; - goto out; - } - list_del(&buf->queue); - buf->state = VIDEOBUF_ACTIVE; -out: - spin_unlock_irqrestore(&cam->viadev->reg_lock, flags); - return buf; + return NULL; + return list_entry(cam->buffer_queue.next, struct via_buffer, queue); } /* @@ -352,11 +341,12 @@ static struct videobuf_buffer *viacam_next_buffer(struct via_camera *cam) */ static irqreturn_t viacam_irq(int irq, void *data) { - int bufn; - struct videobuf_buffer *vb; struct via_camera *cam = data; - struct videobuf_dmabuf *vdma; + struct via_buffer *vb; + int bufn; + struct sg_table *sgt; + mutex_lock(&cam->lock); /* * If there is no place to put the data frame, don't bother * with anything else. @@ -374,12 +364,15 @@ static irqreturn_t viacam_irq(int irq, void *data) /* * Copy over the data and let any waiters know. */ - vdma = videobuf_to_dma(vb); - viafb_dma_copy_out_sg(cam->cb_offsets[bufn], vdma->sglist, vdma->sglen); - vb->state = VIDEOBUF_DONE; - vb->size = cam->user_format.sizeimage; - wake_up(&vb->done); + sgt = vb2_dma_sg_plane_desc(&vb->vbuf.vb2_buf, 0); + vb->vbuf.vb2_buf.timestamp = ktime_get_ns(); + viafb_dma_copy_out_sg(cam->cb_offsets[bufn], sgt->sgl, sgt->nents); + vb->vbuf.sequence = cam->sequence++; + vb->vbuf.field = V4L2_FIELD_NONE; + list_del(&vb->queue); + vb2_buffer_done(&vb->vbuf.vb2_buf, VB2_BUF_STATE_DONE); done: + mutex_unlock(&cam->lock); return IRQ_HANDLED; } @@ -555,7 +548,6 @@ static int viacam_config_controller(struct via_camera *cam) static void viacam_start_engine(struct via_camera *cam) { spin_lock_irq(&cam->viadev->reg_lock); - cam->next_buf = 0; viacam_write_reg_mask(cam, VCR_CAPINTC, VCR_CI_ENABLE, VCR_CI_ENABLE); viacam_int_enable(cam); (void) viacam_read_reg(cam, VCR_CAPINTC); /* Force post */ @@ -576,81 +568,117 @@ static void viacam_stop_engine(struct via_camera *cam) /* --------------------------------------------------------------------------*/ -/* Videobuf callback ops */ +/* vb2 callback ops */ -/* - * buffer_setup. The purpose of this one would appear to be to tell - * videobuf how big a single image is. It's also evidently up to us - * to put some sort of limit on the maximum number of buffers allowed. - */ -static int viacam_vb_buf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) +static struct via_buffer *vb2_to_via_buffer(struct vb2_buffer *vb) { - struct via_camera *cam = q->priv_data; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - *size = cam->user_format.sizeimage; - if (*count == 0 || *count > 6) /* Arbitrary number */ - *count = 6; - return 0; + return container_of(vbuf, struct via_buffer, vbuf); } -/* - * Prepare a buffer. - */ -static int viacam_vb_buf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, enum v4l2_field field) +static void viacam_vb2_queue(struct vb2_buffer *vb) { - struct via_camera *cam = q->priv_data; - - vb->size = cam->user_format.sizeimage; - vb->width = cam->user_format.width; /* bytesperline???? */ - vb->height = cam->user_format.height; - vb->field = field; - if (vb->state == VIDEOBUF_NEEDS_INIT) { - int ret = videobuf_iolock(q, vb, NULL); - if (ret) - return ret; + struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue); + struct via_buffer *via = vb2_to_via_buffer(vb); + + list_add_tail(&via->queue, &cam->buffer_queue); +} + +static int viacam_vb2_prepare(struct vb2_buffer *vb) +{ + struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue); + + if (vb2_plane_size(vb, 0) < cam->user_format.sizeimage) { + cam_dbg(cam, + "Plane size too small (%lu < %u)\n", + vb2_plane_size(vb, 0), + cam->user_format.sizeimage); + return -EINVAL; } - vb->state = VIDEOBUF_PREPARED; + + vb2_set_plane_payload(vb, 0, cam->user_format.sizeimage); + return 0; } -/* - * We've got a buffer to put data into. - * - * FIXME: check for a running engine and valid buffers? - */ -static void viacam_vb_buf_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static int viacam_vb2_queue_setup(struct vb2_queue *vq, + unsigned int *nbufs, + unsigned int *num_planes, unsigned int sizes[], + struct device *alloc_devs[]) { - struct via_camera *cam = q->priv_data; + struct via_camera *cam = vb2_get_drv_priv(vq); + int size = cam->user_format.sizeimage; + + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; + + *num_planes = 1; + sizes[0] = size; + return 0; +} +static int viacam_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct via_camera *cam = vb2_get_drv_priv(vq); + struct via_buffer *buf, *tmp; + int ret = 0; + + if (cam->opstate != S_IDLE) { + ret = -EBUSY; + goto out; + } /* - * Note that videobuf holds the lock when it calls - * us, so we need not (indeed, cannot) take it here. + * Configure things if need be. */ - vb->state = VIDEOBUF_QUEUED; - list_add_tail(&vb->queue, &cam->buffer_queue); + if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { + ret = viacam_configure_sensor(cam); + if (ret) + goto out; + ret = viacam_config_controller(cam); + if (ret) + goto out; + } + cam->sequence = 0; + /* + * If the CPU goes into C3, the DMA transfer gets corrupted and + * users start filing unsightly bug reports. Put in a "latency" + * requirement which will keep the CPU out of the deeper sleep + * states. + */ + pm_qos_add_request(&cam->qos_request, PM_QOS_CPU_DMA_LATENCY, 50); + viacam_start_engine(cam); + return 0; +out: + list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) { + list_del(&buf->queue); + vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); + } + return ret; } -/* - * Free a buffer. - */ -static void viacam_vb_buf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void viacam_vb2_stop_streaming(struct vb2_queue *vq) { - struct via_camera *cam = q->priv_data; + struct via_camera *cam = vb2_get_drv_priv(vq); + struct via_buffer *buf, *tmp; + + pm_qos_remove_request(&cam->qos_request); + viacam_stop_engine(cam); - videobuf_dma_unmap(&cam->platdev->dev, videobuf_to_dma(vb)); - videobuf_dma_free(videobuf_to_dma(vb)); - vb->state = VIDEOBUF_NEEDS_INIT; + list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) { + list_del(&buf->queue); + vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); + } } -static const struct videobuf_queue_ops viacam_vb_ops = { - .buf_setup = viacam_vb_buf_setup, - .buf_prepare = viacam_vb_buf_prepare, - .buf_queue = viacam_vb_buf_queue, - .buf_release = viacam_vb_buf_release, +static const struct vb2_ops viacam_vb2_ops = { + .queue_setup = viacam_vb2_queue_setup, + .buf_queue = viacam_vb2_queue, + .buf_prepare = viacam_vb2_prepare, + .start_streaming = viacam_vb2_start_streaming, + .stop_streaming = viacam_vb2_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; /* --------------------------------------------------------------------------*/ @@ -678,15 +706,7 @@ static int viacam_open(struct file *filp) } via_sensor_power_up(cam); set_bit(CF_CONFIG_NEEDED, &cam->flags); - /* - * Hook into videobuf. Evidently this cannot fail. - */ - videobuf_queue_sg_init(&cam->vb_queue, &viacam_vb_ops, - &cam->platdev->dev, &cam->viadev->reg_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct videobuf_buffer), cam, NULL); } - (cam->users)++; out: mutex_unlock(&cam->lock); return ret; @@ -698,108 +718,27 @@ static int viacam_release(struct file *filp) bool last_open; mutex_lock(&cam->lock); - (cam->users)--; last_open = v4l2_fh_is_singular_file(filp); - /* - * If the "owner" is closing, shut down any ongoing - * operations. - */ - if (filp == cam->owner) { - videobuf_stop(&cam->vb_queue); - /* - * We don't hold the spinlock here, but, if release() - * is being called by the owner, nobody else will - * be changing the state. And an extra stop would - * not hurt anyway. - */ - if (cam->opstate != S_IDLE) - viacam_stop_engine(cam); - cam->owner = NULL; - } + _vb2_fop_release(filp, NULL); /* * Last one out needs to turn out the lights. */ if (last_open) { - videobuf_mmap_free(&cam->vb_queue); via_sensor_power_down(cam); viafb_release_dma(); } - v4l2_fh_release(filp); mutex_unlock(&cam->lock); return 0; } -/* - * Read a frame from the device. - */ -static ssize_t viacam_read(struct file *filp, char __user *buffer, - size_t len, loff_t *pos) -{ - struct via_camera *cam = video_drvdata(filp); - int ret; - - mutex_lock(&cam->lock); - /* - * Enforce the V4l2 "only one owner gets to read data" rule. - */ - if (cam->owner && cam->owner != filp) { - ret = -EBUSY; - goto out_unlock; - } - cam->owner = filp; - /* - * Do we need to configure the hardware? - */ - if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { - ret = viacam_configure_sensor(cam); - if (!ret) - ret = viacam_config_controller(cam); - if (ret) - goto out_unlock; - } - /* - * Fire up the capture engine, then have videobuf do - * the heavy lifting. Someday it would be good to avoid - * stopping and restarting the engine each time. - */ - INIT_LIST_HEAD(&cam->buffer_queue); - viacam_start_engine(cam); - ret = videobuf_read_stream(&cam->vb_queue, buffer, len, pos, 0, - filp->f_flags & O_NONBLOCK); - viacam_stop_engine(cam); - /* videobuf_stop() ?? */ - -out_unlock: - mutex_unlock(&cam->lock); - return ret; -} - - -static __poll_t viacam_poll(struct file *filp, struct poll_table_struct *pt) -{ - struct via_camera *cam = video_drvdata(filp); - - return v4l2_ctrl_poll(filp, pt) | videobuf_poll_stream(filp, &cam->vb_queue, pt); -} - - -static int viacam_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct via_camera *cam = video_drvdata(filp); - - return videobuf_mmap_mapper(&cam->vb_queue, vma); -} - - - static const struct v4l2_file_operations viacam_fops = { .owner = THIS_MODULE, .open = viacam_open, .release = viacam_release, - .read = viacam_read, - .poll = viacam_poll, - .mmap = viacam_mmap, - .unlocked_ioctl = video_ioctl2, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, }; /*----------------------------------------------------------------------------*/ @@ -926,12 +865,8 @@ static int viacam_try_fmt_vid_cap(struct file *filp, void *priv, { struct via_camera *cam = video_drvdata(filp); struct v4l2_format sfmt; - int ret; - mutex_lock(&cam->lock); - ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); - mutex_unlock(&cam->lock); - return ret; + return viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); } @@ -940,9 +875,7 @@ static int viacam_g_fmt_vid_cap(struct file *filp, void *priv, { struct via_camera *cam = video_drvdata(filp); - mutex_lock(&cam->lock); fmt->fmt.pix = cam->user_format; - mutex_unlock(&cam->lock); return 0; } @@ -958,18 +891,15 @@ static int viacam_s_fmt_vid_cap(struct file *filp, void *priv, * Camera must be idle or we can't mess with the * video setup. */ - mutex_lock(&cam->lock); - if (cam->opstate != S_IDLE) { - ret = -EBUSY; - goto out; - } + if (cam->opstate != S_IDLE) + return -EBUSY; /* * Let the sensor code look over and tweak the * requested formatting. */ ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); if (ret) - goto out; + return ret; /* * OK, let's commit to the new format. */ @@ -979,8 +909,6 @@ static int viacam_s_fmt_vid_cap(struct file *filp, void *priv, ret = viacam_configure_sensor(cam); if (!ret) ret = viacam_config_controller(cam); -out: - mutex_unlock(&cam->lock); return ret; } @@ -993,140 +921,22 @@ static int viacam_querycap(struct file *filp, void *priv, return 0; } -/* - * Streaming operations - pure videobuf stuff. - */ -static int viacam_reqbufs(struct file *filp, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct via_camera *cam = video_drvdata(filp); - - return videobuf_reqbufs(&cam->vb_queue, rb); -} - -static int viacam_querybuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct via_camera *cam = video_drvdata(filp); - - return videobuf_querybuf(&cam->vb_queue, buf); -} - -static int viacam_qbuf(struct file *filp, void *priv, struct v4l2_buffer *buf) -{ - struct via_camera *cam = video_drvdata(filp); - - return videobuf_qbuf(&cam->vb_queue, buf); -} - -static int viacam_dqbuf(struct file *filp, void *priv, struct v4l2_buffer *buf) -{ - struct via_camera *cam = video_drvdata(filp); - - return videobuf_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK); -} - -static int viacam_streamon(struct file *filp, void *priv, enum v4l2_buf_type t) -{ - struct via_camera *cam = video_drvdata(filp); - int ret = 0; - - if (t != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - mutex_lock(&cam->lock); - if (cam->opstate != S_IDLE) { - ret = -EBUSY; - goto out; - } - /* - * Enforce the V4l2 "only one owner gets to read data" rule. - */ - if (cam->owner && cam->owner != filp) { - ret = -EBUSY; - goto out; - } - cam->owner = filp; - /* - * Configure things if need be. - */ - if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { - ret = viacam_configure_sensor(cam); - if (ret) - goto out; - ret = viacam_config_controller(cam); - if (ret) - goto out; - } - /* - * If the CPU goes into C3, the DMA transfer gets corrupted and - * users start filing unsightly bug reports. Put in a "latency" - * requirement which will keep the CPU out of the deeper sleep - * states. - */ - pm_qos_add_request(&cam->qos_request, PM_QOS_CPU_DMA_LATENCY, 50); - /* - * Fire things up. - */ - INIT_LIST_HEAD(&cam->buffer_queue); - ret = videobuf_streamon(&cam->vb_queue); - if (!ret) - viacam_start_engine(cam); -out: - mutex_unlock(&cam->lock); - return ret; -} - -static int viacam_streamoff(struct file *filp, void *priv, enum v4l2_buf_type t) -{ - struct via_camera *cam = video_drvdata(filp); - int ret; - - if (t != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->lock); - if (cam->opstate != S_RUNNING) { - ret = -EINVAL; - goto out; - } - pm_qos_remove_request(&cam->qos_request); - viacam_stop_engine(cam); - /* - * Videobuf will recycle all of the outstanding buffers, but - * we should be sure we don't retain any references to - * any of them. - */ - ret = videobuf_streamoff(&cam->vb_queue); - INIT_LIST_HEAD(&cam->buffer_queue); -out: - mutex_unlock(&cam->lock); - return ret; -} - /* G/S_PARM */ static int viacam_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { struct via_camera *cam = video_drvdata(filp); - int ret; - mutex_lock(&cam->lock); - ret = v4l2_g_parm_cap(video_devdata(filp), cam->sensor, parm); - mutex_unlock(&cam->lock); - return ret; + return v4l2_g_parm_cap(video_devdata(filp), cam->sensor, parm); } static int viacam_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { struct via_camera *cam = video_drvdata(filp); - int ret; - mutex_lock(&cam->lock); - ret = v4l2_s_parm_cap(video_devdata(filp), cam->sensor, parm); - mutex_unlock(&cam->lock); - return ret; + return v4l2_s_parm_cap(video_devdata(filp), cam->sensor, parm); } static int viacam_enum_framesizes(struct file *filp, void *priv, @@ -1172,9 +982,7 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, if (interval->width < QCIF_WIDTH || interval->width > VGA_WIDTH || interval->height < QCIF_HEIGHT || interval->height > VGA_HEIGHT) return -EINVAL; - mutex_lock(&cam->lock); ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie); - mutex_unlock(&cam->lock); if (ret) return ret; interval->type = V4L2_FRMIVAL_TYPE_DISCRETE; @@ -1182,8 +990,6 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, return 0; } - - static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_enum_input = viacam_enum_input, .vidioc_g_input = viacam_g_input, @@ -1193,12 +999,15 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_g_fmt_vid_cap = viacam_g_fmt_vid_cap, .vidioc_s_fmt_vid_cap = viacam_s_fmt_vid_cap, .vidioc_querycap = viacam_querycap, - .vidioc_reqbufs = viacam_reqbufs, - .vidioc_querybuf = viacam_querybuf, - .vidioc_qbuf = viacam_qbuf, - .vidioc_dqbuf = viacam_dqbuf, - .vidioc_streamon = viacam_streamon, - .vidioc_streamoff = viacam_streamoff, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_parm = viacam_g_parm, .vidioc_s_parm = viacam_s_parm, .vidioc_enum_framesizes = viacam_enum_framesizes, @@ -1242,7 +1051,7 @@ static int viacam_resume(void *priv) /* * Make sure the sensor's power state is correct */ - if (cam->users > 0) + if (!list_empty(&cam->vdev.fh_list)) via_sensor_power_up(cam); else via_sensor_power_down(cam); @@ -1327,6 +1136,7 @@ static int viacam_probe(struct platform_device *pdev) int ret; struct i2c_adapter *sensor_adapter; struct viafb_dev *viadev = pdev->dev.platform_data; + struct vb2_queue *vq; struct i2c_board_info ov7670_info = { .type = "ov7670", .addr = 0x42 >> 1, @@ -1370,8 +1180,6 @@ static int viacam_probe(struct platform_device *pdev) via_cam_info = cam; cam->platdev = pdev; cam->viadev = viadev; - cam->users = 0; - cam->owner = NULL; cam->opstate = S_IDLE; cam->user_format = cam->sensor_format = viacam_def_pix_format; mutex_init(&cam->lock); @@ -1432,11 +1240,27 @@ static int viacam_probe(struct platform_device *pdev) viacam_irq, IRQF_SHARED, "via-camera", cam); if (ret) goto out_power_down; + + vq = &cam->vq; + vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; + vq->drv_priv = cam; + vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vq->buf_struct_size = sizeof(struct via_buffer); + vq->dev = cam->v4l2_dev.dev; + + vq->ops = &viacam_vb2_ops; + vq->mem_ops = &vb2_dma_sg_memops; + vq->lock = &cam->lock; + + ret = vb2_queue_init(vq); /* * Tell V4l2 that we exist. */ cam->vdev = viacam_v4l_template; cam->vdev.v4l2_dev = &cam->v4l2_dev; + cam->vdev.lock = &cam->lock; + cam->vdev.queue = vq; video_set_drvdata(&cam->vdev, cam); ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); if (ret) -- GitLab From e2724c77ca219ef4e7ba2a5399e2d02f560d0c69 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:48 +0300 Subject: [PATCH 1307/7155] staging: fsl-dpaa2/ethsw: remove unused structure The dpsw_cfg structure is only used when creating a new dpsw DPAA2 object. In the DPAA2 architecture, objects are created at boot time by the firmware or dynamically from userspace while drivers on the fsl-mc bus only configure those objects. Remove the structure since it's of no use. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-2-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 31 -------------------------- 1 file changed, 31 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 25635259ce44..0d9330e01915 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -75,37 +75,6 @@ enum dpsw_component_type { DPSW_COMPONENT_TYPE_S_VLAN }; -/** - * struct dpsw_cfg - DPSW configuration - * @num_ifs: Number of external and internal interfaces - * @adv: Advanced parameters; default is all zeros; - * use this structure to change default settings - * @adv.options: Enable/Disable DPSW features (bitmap) - * @adv.max_vlans: Maximum Number of VLAN's; 0 - indicates default 16 - * @adv.max_meters_per_if: Number of meters per interface - * @adv.max_fdbs: Maximum Number of FDB's; 0 - indicates default 16 - * @adv.max_fdb_entries: Number of FDB entries for default FDB table; - * 0 - indicates default 1024 entries. - * @adv.fdb_aging_time: Default FDB aging time for default FDB table; - * 0 - indicates default 300 seconds - * @adv.max_fdb_mc_groups: Number of multicast groups in each FDB table; - * 0 - indicates default 32 - * @adv.component_type: Indicates the component type of this bridge - */ -struct dpsw_cfg { - u16 num_ifs; - struct { - u64 options; - u16 max_vlans; - u8 max_meters_per_if; - u8 max_fdbs; - u16 max_fdb_entries; - u16 fdb_aging_time; - u16 max_fdb_mc_groups; - enum dpsw_component_type component_type; - } adv; -}; - int dpsw_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -- GitLab From b380a4e6e5e1f25eb40ec2a2f40196d0c00e6832 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:49 +0300 Subject: [PATCH 1308/7155] staging: fsl-dpaa2/ethsw: notify switchdev of offloaded entry Notify switchdev in case the FDB entry was successfully offloaded. This will help users to make the distinction between entries known to the HW switch and those that are held only on the software bridge. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-3-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 341c36b3a76d..d6953ac427b1 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1039,6 +1039,7 @@ static void ethsw_switchdev_event_work(struct work_struct *work) container_of(work, struct ethsw_switchdev_event_work, work); struct net_device *dev = switchdev_work->dev; struct switchdev_notifier_fdb_info *fdb_info; + int err; rtnl_lock(); fdb_info = &switchdev_work->fdb_info; @@ -1046,9 +1047,16 @@ static void ethsw_switchdev_event_work(struct work_struct *work) switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: if (is_unicast_ether_addr(fdb_info->addr)) - ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_uc(netdev_priv(dev), + fdb_info->addr); else - ethsw_port_fdb_add_mc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_mc(netdev_priv(dev), + fdb_info->addr); + if (err) + break; + fdb_info->offloaded = true; + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, + &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: if (is_unicast_ether_addr(fdb_info->addr)) -- GitLab From de01ac2e49d5b403c3edca17e7fb257060e5192c Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:50 +0300 Subject: [PATCH 1309/7155] staging: fsl-dpaa2/ethsw: add .ndo_fdb_dump callback Implement the .ndo_fdb_dump callback for the switch net devices. The list of all offloaded FDB entries is retrieved through the dpsw_fdb_dump() firmware call. Filter the entries by the switch port on which the callback was called and for each of them create a new neighbour message. Also remove the requirement from the TODO list. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-4-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/TODO | 1 - drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 15 ++- drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 51 ++++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 25 ++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 135 ++++++++++++++++++++- 5 files changed, 224 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/TODO b/drivers/staging/fsl-dpaa2/ethsw/TODO index 24b5e95a96f8..4d46857b0b2b 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/TODO +++ b/drivers/staging/fsl-dpaa2/ethsw/TODO @@ -1,7 +1,6 @@ * Add I/O capabilities on switch port netdevices. This will allow control traffic to reach the CPU. * Add ACL to redirect control traffic to CPU. -* Add support for displaying learned FDB entries * Add support for multiple FDBs and switch port partitioning * MC firmware uprev; the DPAA2 objects used by the Ethernet Switch driver need to be kept in sync with binary interface changes in MC diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 14b974defa3a..5e1339daa7c7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -10,7 +10,7 @@ /* DPSW Version */ #define DPSW_VER_MAJOR 8 -#define DPSW_VER_MINOR 0 +#define DPSW_VER_MINOR 1 #define DPSW_CMD_BASE_VERSION 1 #define DPSW_CMD_ID_OFFSET 4 @@ -67,6 +67,7 @@ #define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) #define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) #define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) +#define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ @@ -351,6 +352,18 @@ struct dpsw_cmd_fdb_set_learning_mode { u8 mode; }; +struct dpsw_cmd_fdb_dump { + __le16 fdb_id; + __le16 pad0; + __le32 pad1; + __le64 iova_addr; + __le32 iova_size; +}; + +struct dpsw_rsp_fdb_dump { + __le16 num_entries; +}; + struct dpsw_rsp_get_api_version { __le16 version_major; __le16 version_minor; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index cabed77b445d..56b0fa789a67 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -980,6 +980,57 @@ int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpsw_fdb_dump() - Dump the content of FDB table into memory. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @fdb_id: Forwarding Database Identifier + * @iova_addr: Data will be stored here as an array of struct fdb_dump_entry + * @iova_size: Memory size allocated at iova_addr + * @num_entries:Number of entries written at iova_addr + * + * Return: Completion status. '0' on Success; Error code otherwise. + * + * The memory allocated at iova_addr must be initialized with zero before + * command execution. If the FDB table does not fit into memory MC will stop + * after the memory is filled up. + * The struct fdb_dump_entry array must be parsed until the end of memory + * area or until an entry with mac_addr set to zero is found. + */ +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries) +{ + struct dpsw_cmd_fdb_dump *cmd_params; + struct dpsw_rsp_fdb_dump *rsp_params; + struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_DUMP, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_fdb_dump *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->iova_addr = cpu_to_le64(iova_addr); + cmd_params->iova_size = cpu_to_le32(iova_size); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + rsp_params = (struct dpsw_rsp_fdb_dump *)cmd.params; + *num_entries = le16_to_cpu(rsp_params->num_entries); + + return 0; +} + /** * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 0d9330e01915..25b45850925c 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -465,6 +465,31 @@ int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, u16 fdb_id, const struct dpsw_fdb_unicast_cfg *cfg); +#define DPSW_FDB_ENTRY_TYPE_DYNAMIC BIT(0) +#define DPSW_FDB_ENTRY_TYPE_UNICAST BIT(1) + +/** + * struct fdb_dump_entry - fdb snapshot entry + * @mac_addr: MAC address + * @type: bit0 - DINAMIC(1)/STATIC(0), bit1 - UNICAST(1)/MULTICAST(0) + * @if_info: unicast - egress interface, multicast - number of egress interfaces + * @if_mask: multicast - egress interface mask + */ +struct fdb_dump_entry { + u8 mac_addr[6]; + u8 type; + u8 if_info; + u8 if_mask[8]; +}; + +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries); + /** * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration * @type: Select static or dynamic entry diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index d6953ac427b1..e6423f1e190d 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -22,7 +22,7 @@ static struct workqueue_struct *ethsw_owq; /* Minimal supported DPSW version */ #define DPSW_MIN_VER_MAJOR 8 -#define DPSW_MIN_VER_MINOR 0 +#define DPSW_MIN_VER_MINOR 1 #define DEFAULT_VLAN_ID 1 @@ -529,6 +529,138 @@ static int port_get_phys_name(struct net_device *netdev, char *name, return 0; } +struct ethsw_dump_ctx { + struct net_device *dev; + struct sk_buff *skb; + struct netlink_callback *cb; + int idx; +}; + +static int ethsw_fdb_do_dump(struct fdb_dump_entry *entry, + struct ethsw_dump_ctx *dump) +{ + int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC; + u32 portid = NETLINK_CB(dump->cb->skb).portid; + u32 seq = dump->cb->nlh->nlmsg_seq; + struct nlmsghdr *nlh; + struct ndmsg *ndm; + + if (dump->idx < dump->cb->args[2]) + goto skip; + + nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, + sizeof(*ndm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + + ndm = nlmsg_data(nlh); + ndm->ndm_family = AF_BRIDGE; + ndm->ndm_pad1 = 0; + ndm->ndm_pad2 = 0; + ndm->ndm_flags = NTF_SELF; + ndm->ndm_type = 0; + ndm->ndm_ifindex = dump->dev->ifindex; + ndm->ndm_state = is_dynamic ? NUD_REACHABLE : NUD_NOARP; + + if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, entry->mac_addr)) + goto nla_put_failure; + + nlmsg_end(dump->skb, nlh); + +skip: + dump->idx++; + return 0; + +nla_put_failure: + nlmsg_cancel(dump->skb, nlh); + return -EMSGSIZE; +} + +static int port_fdb_valid_entry(struct fdb_dump_entry *entry, + struct ethsw_port_priv *port_priv) +{ + int idx = port_priv->idx; + int valid; + + if (entry->type & DPSW_FDB_ENTRY_TYPE_UNICAST) + valid = entry->if_info == port_priv->idx; + else + valid = entry->if_mask[idx / 8] & BIT(idx % 8); + + return valid; +} + +static int port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, + struct net_device *net_dev, + struct net_device *filter_dev, int *idx) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct device *dev = net_dev->dev.parent; + struct fdb_dump_entry *fdb_entries; + struct fdb_dump_entry fdb_entry; + struct ethsw_dump_ctx dump = { + .dev = net_dev, + .skb = skb, + .cb = cb, + .idx = *idx, + }; + dma_addr_t fdb_dump_iova; + u16 num_fdb_entries; + u32 fdb_dump_size; + int err = 0, i; + u8 *dma_mem; + + fdb_dump_size = ethsw->sw_attr.max_fdb_entries * sizeof(fdb_entry); + dma_mem = kzalloc(fdb_dump_size, GFP_KERNEL); + if (!dma_mem) + return -ENOMEM; + + memset(dma_mem, 0, fdb_dump_size); + + fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, fdb_dump_iova)) { + netdev_err(net_dev, "dma_map_single() failed\n"); + err = -ENOMEM; + goto err_map; + } + + err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + fdb_dump_iova, fdb_dump_size, &num_fdb_entries); + if (err) { + netdev_err(net_dev, "dpsw_fdb_dump() = %d\n", err); + goto err_dump; + } + + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_FROM_DEVICE); + + fdb_entries = (struct fdb_dump_entry *)dma_mem; + for (i = 0; i < num_fdb_entries; i++) { + fdb_entry = fdb_entries[i]; + + if (!port_fdb_valid_entry(&fdb_entry, port_priv)) + continue; + + err = ethsw_fdb_do_dump(&fdb_entry, &dump); + if (err) + goto end; + } + +end: + *idx = dump.idx; + + kfree(dma_mem); + + return 0; + +err_dump: + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_TO_DEVICE); +err_map: + kfree(dma_mem); + return err; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -538,6 +670,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, + .ndo_fdb_dump = port_fdb_dump, .ndo_start_xmit = port_dropframe, .ndo_get_port_parent_id = swdev_get_port_parent_id, -- GitLab From e1e6a04d97cf747ccbec3ae23008c9faf8557aee Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:51 +0300 Subject: [PATCH 1310/7155] staging: fsl-dpaa2/ethsw: check added_by_user flag We do not want to offload FDB entries if not added by user as static entries. Check the added_by_user flag and break if not set. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-5-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e6423f1e190d..2d3179c6bad8 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1179,6 +1179,8 @@ static void ethsw_switchdev_event_work(struct work_struct *work) switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) err = ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); @@ -1192,6 +1194,8 @@ static void ethsw_switchdev_event_work(struct work_struct *work) &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) ethsw_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr); else -- GitLab From 939878fe06461dec3edfb31f7dd130dcea1d21e4 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:52 +0300 Subject: [PATCH 1311/7155] staging: fsl-dpaa2/ethsw: add .ndo_fdb[add|del] callbacks Add the .ndo_fdb_[add|del] callbacks so that FDB entries not associated with a master device still end up offloaded. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-6-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 2d3179c6bad8..4b94a01513a7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -316,6 +316,31 @@ static int ethsw_port_fdb_del_mc(struct ethsw_port_priv *port_priv, return err; } +static int port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, const unsigned char *addr, + u16 vid, u16 flags, + struct netlink_ext_ack *extack) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_add_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_add_mc(netdev_priv(dev), + addr); +} + +static int port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 vid) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_del_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_del_mc(netdev_priv(dev), + addr); +} + static void port_get_stats(struct net_device *netdev, struct rtnl_link_stats64 *stats) { @@ -670,6 +695,8 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, + .ndo_fdb_add = port_fdb_add, + .ndo_fdb_del = port_fdb_del, .ndo_fdb_dump = port_fdb_dump, .ndo_start_xmit = port_dropframe, -- GitLab From 1db88c5343712e411a2dd45375f27c477e33dc07 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 30 Jul 2019 15:56:57 +0100 Subject: [PATCH 1312/7155] rxrpc: Fix -Wframe-larger-than= warnings from on-stack crypto rxkad sometimes triggers a warning about oversized stack frames when building with clang for a 32-bit architecture: net/rxrpc/rxkad.c:243:12: error: stack frame size of 1088 bytes in function 'rxkad_secure_packet' [-Werror,-Wframe-larger-than=] net/rxrpc/rxkad.c:501:12: error: stack frame size of 1088 bytes in function 'rxkad_verify_packet' [-Werror,-Wframe-larger-than=] The problem is the combination of SYNC_SKCIPHER_REQUEST_ON_STACK() in rxkad_verify_packet()/rxkad_secure_packet() with the relatively large scatterlist in rxkad_verify_packet_1()/rxkad_secure_packet_encrypt(). The warning does not show up when using gcc, which does not inline the functions as aggressively, but the problem is still the same. Allocate the cipher buffers from the slab instead, caching the allocated packet crypto request memory used for DATA packet crypto in the rxrpc_call struct. Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") Reported-by: Arnd Bergmann Signed-off-by: David Howells Acked-by: Arnd Bergmann cc: Herbert Xu Signed-off-by: David S. Miller --- net/rxrpc/ar-internal.h | 4 ++ net/rxrpc/call_object.c | 4 +- net/rxrpc/insecure.c | 5 ++ net/rxrpc/rxkad.c | 103 ++++++++++++++++++++++++++++++++-------- 4 files changed, 96 insertions(+), 20 deletions(-) diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 80335b4ee4fd..bea2a02850af 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -226,6 +226,9 @@ struct rxrpc_security { int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, unsigned int, unsigned int, rxrpc_seq_t, u16); + /* Free crypto request on a call */ + void (*free_call_crypto)(struct rxrpc_call *); + /* Locate the data in a received packet that has been verified. */ void (*locate_data)(struct rxrpc_call *, struct sk_buff *, unsigned int *, unsigned int *); @@ -557,6 +560,7 @@ struct rxrpc_call { unsigned long expect_term_by; /* When we expect call termination by */ u32 next_rx_timo; /* Timeout for next Rx packet (jif) */ u32 next_req_timo; /* Timeout for next Rx request packet (jif) */ + struct skcipher_request *cipher_req; /* Packet cipher request buffer */ struct timer_list timer; /* Combined event timer */ struct work_struct processor; /* Event processor */ rxrpc_notify_rx_t notify_rx; /* kernel service Rx notification function */ diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 217b12be9e08..60cbc81dc461 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -476,8 +476,10 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); - if (conn) + if (conn) { rxrpc_disconnect_call(call); + conn->security->free_call_crypto(call); + } for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { rxrpc_free_skb(call->rxtx_buffer[i], diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c index a29d26c273b5..f6c59f5fae9d 100644 --- a/net/rxrpc/insecure.c +++ b/net/rxrpc/insecure.c @@ -33,6 +33,10 @@ static int none_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, return 0; } +static void none_free_call_crypto(struct rxrpc_call *call) +{ +} + static void none_locate_data(struct rxrpc_call *call, struct sk_buff *skb, unsigned int *_offset, unsigned int *_len) { @@ -83,6 +87,7 @@ const struct rxrpc_security rxrpc_no_security = { .exit = none_exit, .init_connection_security = none_init_connection_security, .prime_packet_security = none_prime_packet_security, + .free_call_crypto = none_free_call_crypto, .secure_packet = none_secure_packet, .verify_packet = none_verify_packet, .locate_data = none_locate_data, diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index ae8cd8926456..dbb109da1835 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -43,6 +43,7 @@ struct rxkad_level2_hdr { * packets */ static struct crypto_sync_skcipher *rxkad_ci; +static struct skcipher_request *rxkad_ci_req; static DEFINE_MUTEX(rxkad_ci_mutex); /* @@ -99,8 +100,8 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn) */ static int rxkad_prime_packet_security(struct rxrpc_connection *conn) { + struct skcipher_request *req; struct rxrpc_key_token *token; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct scatterlist sg; struct rxrpc_crypt iv; __be32 *tmpbuf; @@ -115,6 +116,12 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn) if (!tmpbuf) return -ENOMEM; + req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS); + if (!req) { + kfree(tmpbuf); + return -ENOMEM; + } + token = conn->params.key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); @@ -128,7 +135,7 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn) skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x); crypto_skcipher_encrypt(req); - skcipher_request_zero(req); + skcipher_request_free(req); memcpy(&conn->csum_iv, tmpbuf + 2, sizeof(conn->csum_iv)); kfree(tmpbuf); @@ -136,6 +143,35 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn) return 0; } +/* + * Allocate and prepare the crypto request on a call. For any particular call, + * this is called serially for the packets, so no lock should be necessary. + */ +static struct skcipher_request *rxkad_get_call_crypto(struct rxrpc_call *call) +{ + struct crypto_skcipher *tfm = &call->conn->cipher->base; + struct skcipher_request *cipher_req = call->cipher_req; + + if (!cipher_req) { + cipher_req = skcipher_request_alloc(tfm, GFP_NOFS); + if (!cipher_req) + return NULL; + call->cipher_req = cipher_req; + } + + return cipher_req; +} + +/* + * Clean up the crypto on a call. + */ +static void rxkad_free_call_crypto(struct rxrpc_call *call) +{ + if (call->cipher_req) + skcipher_request_free(call->cipher_req); + call->cipher_req = NULL; +} + /* * partially encrypt a packet (level 1 security) */ @@ -246,7 +282,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, void *sechdr) { struct rxrpc_skb_priv *sp; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg; u32 x, y; @@ -265,6 +301,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call, if (ret < 0) return ret; + req = rxkad_get_call_crypto(call); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); @@ -502,7 +542,7 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, unsigned int offset, unsigned int len, rxrpc_seq_t seq, u16 expected_cksum) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg; bool aborted; @@ -515,6 +555,10 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, if (!call->conn->cipher) return 0; + req = rxkad_get_call_crypto(call); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); @@ -747,14 +791,18 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response) /* * encrypt the response packet */ -static void rxkad_encrypt_response(struct rxrpc_connection *conn, - struct rxkad_response *resp, - const struct rxkad_key *s2) +static int rxkad_encrypt_response(struct rxrpc_connection *conn, + struct rxkad_response *resp, + const struct rxkad_key *s2) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg[1]; + req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv)); @@ -764,7 +812,8 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); crypto_skcipher_encrypt(req); - skcipher_request_zero(req); + skcipher_request_free(req); + return 0; } /* @@ -839,8 +888,9 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, /* calculate the response checksum and then do the encryption */ rxkad_calc_response_checksum(resp); - rxkad_encrypt_response(conn, resp, token->kad); - ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad); + ret = rxkad_encrypt_response(conn, resp, token->kad); + if (ret == 0) + ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad); kfree(resp); return ret; @@ -1017,18 +1067,16 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, struct rxkad_response *resp, const struct rxrpc_crypt *session_key) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); + struct skcipher_request *req = rxkad_ci_req; struct scatterlist sg[1]; struct rxrpc_crypt iv; _enter(",,%08x%08x", ntohl(session_key->n[0]), ntohl(session_key->n[1])); - ASSERT(rxkad_ci != NULL); - mutex_lock(&rxkad_ci_mutex); if (crypto_sync_skcipher_setkey(rxkad_ci, session_key->x, - sizeof(*session_key)) < 0) + sizeof(*session_key)) < 0) BUG(); memcpy(&iv, session_key, sizeof(iv)); @@ -1222,10 +1270,26 @@ static void rxkad_clear(struct rxrpc_connection *conn) */ static int rxkad_init(void) { + struct crypto_sync_skcipher *tfm; + struct skcipher_request *req; + /* pin the cipher we need so that the crypto layer doesn't invoke * keventd to go get it */ - rxkad_ci = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0); - return PTR_ERR_OR_ZERO(rxkad_ci); + tfm = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + req = skcipher_request_alloc(&tfm->base, GFP_KERNEL); + if (!req) + goto nomem_tfm; + + rxkad_ci_req = req; + rxkad_ci = tfm; + return 0; + +nomem_tfm: + crypto_free_sync_skcipher(tfm); + return -ENOMEM; } /* @@ -1233,8 +1297,8 @@ static int rxkad_init(void) */ static void rxkad_exit(void) { - if (rxkad_ci) - crypto_free_sync_skcipher(rxkad_ci); + crypto_free_sync_skcipher(rxkad_ci); + skcipher_request_free(rxkad_ci_req); } /* @@ -1249,6 +1313,7 @@ const struct rxrpc_security rxkad = { .prime_packet_security = rxkad_prime_packet_security, .secure_packet = rxkad_secure_packet, .verify_packet = rxkad_verify_packet, + .free_call_crypto = rxkad_free_call_crypto, .locate_data = rxkad_locate_data, .issue_challenge = rxkad_issue_challenge, .respond_to_challenge = rxkad_respond_to_challenge, -- GitLab From b33f37064b743d4c5771d3bfc65976790b7396cc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:46 -0700 Subject: [PATCH 1313/7155] usb: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-47-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/core.c | 1 - drivers/usb/dwc2/platform.c | 4 +--- drivers/usb/dwc3/dwc3-keystone.c | 1 - drivers/usb/dwc3/dwc3-omap.c | 4 +--- drivers/usb/gadget/udc/aspeed-vhub/core.c | 1 - drivers/usb/gadget/udc/bcm63xx_udc.c | 8 ++------ drivers/usb/gadget/udc/bdc/bdc_core.c | 4 +--- drivers/usb/gadget/udc/gr_udc.c | 8 ++------ drivers/usb/gadget/udc/lpc32xx_udc.c | 5 +---- drivers/usb/gadget/udc/renesas_usb3.c | 4 +--- drivers/usb/gadget/udc/s3c-hsudc.c | 4 +--- drivers/usb/gadget/udc/udc-xilinx.c | 4 +--- drivers/usb/host/ehci-atmel.c | 3 --- drivers/usb/host/ehci-omap.c | 4 +--- drivers/usb/host/ehci-orion.c | 3 --- drivers/usb/host/ehci-platform.c | 4 +--- drivers/usb/host/ehci-sh.c | 3 --- drivers/usb/host/ehci-st.c | 4 +--- drivers/usb/host/imx21-hcd.c | 4 +--- drivers/usb/host/ohci-platform.c | 4 +--- drivers/usb/host/ohci-st.c | 4 +--- drivers/usb/mtu3/mtu3_core.c | 4 +--- drivers/usb/phy/phy-ab8500-usb.c | 12 +++--------- drivers/usb/typec/tcpm/wcove.c | 4 +--- 24 files changed, 22 insertions(+), 79 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 26062d610c20..36c964cd40a3 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -1008,7 +1008,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) ci->irq = platform_get_irq(pdev, 0); if (ci->irq < 0) { - dev_err(dev, "missing IRQ\n"); ret = ci->irq; goto deinit_phy; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 80fd3c6dcd1c..3c6ce09a6db5 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -407,10 +407,8 @@ static int dwc2_driver_probe(struct platform_device *dev) spin_lock_init(&hsotg->lock); hsotg->irq = platform_get_irq(dev, 0); - if (hsotg->irq < 0) { - dev_err(&dev->dev, "missing IRQ resource\n"); + if (hsotg->irq < 0) return hsotg->irq; - } dev_dbg(hsotg->dev, "registering common handler for irq%d\n", hsotg->irq); diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index cbee5fb9b9fb..a69eb4a7b832 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -112,7 +112,6 @@ static int kdwc3_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "missing irq\n"); error = irq; goto err_irq; } diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ed8b86517675..6f711d58d82f 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -469,10 +469,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, omap); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "missing IRQ resource: %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index db3628be38c0..c08d385e2723 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -348,7 +348,6 @@ static int ast_vhub_probe(struct platform_device *pdev) /* Find interrupt and install handler */ vhub->irq = platform_get_irq(pdev, 0); if (vhub->irq < 0) { - dev_err(&pdev->dev, "Failed to get interrupt\n"); rc = vhub->irq; goto err; } diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index c1fcc77403ea..97b16463f3ef 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c @@ -2328,10 +2328,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "missing IRQ resource #0\n"); + if (irq < 0) goto out_uninit; - } if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0, dev_name(dev), udc) < 0) goto report_request_failure; @@ -2339,10 +2337,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */ for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { irq = platform_get_irq(pdev, i + 1); - if (irq < 0) { - dev_err(dev, "missing IRQ resource #%d\n", i + 1); + if (irq < 0) goto out_uninit; - } if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0, dev_name(dev), &udc->iudma[i]) < 0) goto report_request_failure; diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index ccbd1d34eb2a..cc4a16e253ac 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -515,10 +515,8 @@ static int bdc_probe(struct platform_device *pdev) return -ENOMEM; } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "platform_get_irq failed:%d\n", irq); + if (irq < 0) return irq; - } spin_lock_init(&bdc->lock); platform_set_drvdata(pdev, bdc); bdc->irq = irq; diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index 729e60e49564..7a0e9a58c2d8 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -2134,19 +2134,15 @@ static int gr_probe(struct platform_device *pdev) return PTR_ERR(regs); dev->irq = platform_get_irq(pdev, 0); - if (dev->irq <= 0) { - dev_err(dev->dev, "No irq found\n"); + if (dev->irq <= 0) return -ENODEV; - } /* Some core configurations has separate irqs for IN and OUT events */ dev->irqi = platform_get_irq(pdev, 1); if (dev->irqi > 0) { dev->irqo = platform_get_irq(pdev, 2); - if (dev->irqo <= 0) { - dev_err(dev->dev, "Found irqi but not irqo\n"); + if (dev->irqo <= 0) return -ENODEV; - } } else { dev->irqi = 0; } diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 5f1b14f3e5a0..e9cf20979bf6 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -3061,11 +3061,8 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) /* Get IRQs */ for (i = 0; i < 4; i++) { udc->udp_irq[i] = platform_get_irq(pdev, i); - if (udc->udp_irq[i] < 0) { - dev_err(udc->dev, - "irq resource %d not available!\n", i); + if (udc->udp_irq[i] < 0) return udc->udp_irq[i]; - } } udc->udp_baseaddr = devm_ioremap_resource(dev, res); diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 87062d22134d..027a25694a68 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2743,10 +2743,8 @@ static int renesas_usb3_probe(struct platform_device *pdev) priv = of_device_get_match_data(&pdev->dev); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); if (!usb3) diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index 31c7c5587cf9..858993c73442 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -1311,10 +1311,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) s3c_hsudc_setup_ep(hsudc); ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "unable to obtain IRQ number\n"); + if (ret < 0) goto err_res; - } hsudc->irq = ret; ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0, diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index b1f4104d1283..29d8e5f8bb58 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -2074,10 +2074,8 @@ static int xudc_probe(struct platform_device *pdev) return PTR_ERR(udc->addr); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "unable to get irq\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, xudc_irq, 0, dev_name(&pdev->dev), udc); if (ret < 0) { diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 3ba140ceaf52..e893467d659c 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -100,9 +100,6 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); retval = -ENODEV; goto fail_create_hcd; } diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7d20296cbe9f..fc125b3d06e7 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -115,10 +115,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "EHCI irq failed: %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 790acf3633e8..a319b1df3011 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -223,9 +223,6 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); err = -ENODEV; goto err; } diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 4c306fb6b069..769749ca5961 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -145,10 +145,8 @@ static int ehci_platform_probe(struct platform_device *dev) } irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "no irq provided"); + if (irq < 0) return irq; - } hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index a9ee767952c1..ef75b9d70eb4 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -85,9 +85,6 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); ret = -ENODEV; goto fail_create_hcd; } diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c index ccb4e611001d..f74433aac948 100644 --- a/drivers/usb/host/ehci-st.c +++ b/drivers/usb/host/ehci-st.c @@ -158,10 +158,8 @@ static int st_ehci_platform_probe(struct platform_device *dev) return -ENODEV; irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "no irq provided"); + if (irq < 0) return irq; - } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { dev_err(&dev->dev, "no memory resource provided"); diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 6e3dad19d369..e406c5459a97 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1836,10 +1836,8 @@ static int imx21_probe(struct platform_device *pdev) if (!res) return -ENODEV; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } hcd = usb_create_hcd(&imx21_hc_driver, &pdev->dev, dev_name(&pdev->dev)); diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 65a1c3fdc88c..7addfc2cbadc 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -111,10 +111,8 @@ static int ohci_platform_probe(struct platform_device *dev) return err; irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "no irq provided"); + if (irq < 0) return irq; - } hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c index 638a92bd2cdc..ac796ccd93ef 100644 --- a/drivers/usb/host/ohci-st.c +++ b/drivers/usb/host/ohci-st.c @@ -138,10 +138,8 @@ static int st_ohci_platform_probe(struct platform_device *dev) return -ENODEV; irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "no irq provided"); + if (irq < 0) return irq; - } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index f8bd1d57e795..c3d5c1206eec 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -835,10 +835,8 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) return -ENOMEM; mtu->irq = platform_get_irq(pdev, 0); - if (mtu->irq < 0) { - dev_err(dev, "fail to get irq number\n"); + if (mtu->irq < 0) return mtu->irq; - } dev_info(dev, "irq %d\n", mtu->irq); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 14b432982fd3..4bb4b1d42f32 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -718,10 +718,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, if (ab->flags & AB8500_USB_FLAG_USE_LINK_STATUS_IRQ) { irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); - if (irq < 0) { - dev_err(&pdev->dev, "Link status irq not found\n"); + if (irq < 0) return irq; - } err = devm_request_threaded_irq(&pdev->dev, irq, NULL, ab8500_usb_link_status_irq, IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, @@ -734,10 +732,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, if (ab->flags & AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ) { irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); - if (irq < 0) { - dev_err(&pdev->dev, "ID fall irq not found\n"); + if (irq < 0) return irq; - } err = devm_request_threaded_irq(&pdev->dev, irq, NULL, ab8500_usb_disconnect_irq, IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, @@ -750,10 +746,8 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, if (ab->flags & AB8500_USB_FLAG_USE_VBUS_DET_IRQ) { irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); - if (irq < 0) { - dev_err(&pdev->dev, "VBUS fall irq not found\n"); + if (irq < 0) return irq; - } err = devm_request_threaded_irq(&pdev->dev, irq, NULL, ab8500_usb_disconnect_irq, IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c index 6b317c150bdd..edc271da14f4 100644 --- a/drivers/usb/typec/tcpm/wcove.c +++ b/drivers/usb/typec/tcpm/wcove.c @@ -617,10 +617,8 @@ static int wcove_typec_probe(struct platform_device *pdev) wcove->regmap = pmic->regmap; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq); if (irq < 0) -- GitLab From 75080370459a717da17fc9df2e7541f201c63746 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:45 -0700 Subject: [PATCH 1314/7155] uio: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Greg Kroah-Hartman Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-46-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_dmem_genirq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index f32cef94aa82..ebcf1434e296 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c @@ -200,10 +200,8 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev) if (!uioinfo->irq) { ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); + if (ret < 0) goto bad1; - } uioinfo->irq = ret; } uiomem = &uioinfo->mem[0]; -- GitLab From ab81f3f386e2650b625c4dfe8ca092d30289c2a3 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 20:46:27 +0800 Subject: [PATCH 1315/7155] mei: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190723124627.24671-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 19 ++++++++----------- drivers/misc/mei/pci-txe.c | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 57cb68f5cc64..563ebd56c3e5 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -381,12 +381,11 @@ static int mei_me_pci_resume(struct device *device) #ifdef CONFIG_PM static int mei_me_pm_runtime_idle(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; - dev_dbg(&pdev->dev, "rpm: me: runtime_idle\n"); + dev_dbg(device, "rpm: me: runtime_idle\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; if (mei_write_is_idle(dev)) @@ -397,13 +396,12 @@ static int mei_me_pm_runtime_idle(struct device *device) static int mei_me_pm_runtime_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; - dev_dbg(&pdev->dev, "rpm: me: runtime suspend\n"); + dev_dbg(device, "rpm: me: runtime suspend\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; @@ -416,7 +414,7 @@ static int mei_me_pm_runtime_suspend(struct device *device) mutex_unlock(&dev->device_lock); - dev_dbg(&pdev->dev, "rpm: me: runtime suspend ret=%d\n", ret); + dev_dbg(device, "rpm: me: runtime suspend ret=%d\n", ret); if (ret && ret != -EAGAIN) schedule_work(&dev->reset_work); @@ -426,13 +424,12 @@ static int mei_me_pm_runtime_suspend(struct device *device) static int mei_me_pm_runtime_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; - dev_dbg(&pdev->dev, "rpm: me: runtime resume\n"); + dev_dbg(device, "rpm: me: runtime resume\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; @@ -442,7 +439,7 @@ static int mei_me_pm_runtime_resume(struct device *device) mutex_unlock(&dev->device_lock); - dev_dbg(&pdev->dev, "rpm: me: runtime resume ret = %d\n", ret); + dev_dbg(device, "rpm: me: runtime resume ret = %d\n", ret); if (ret) schedule_work(&dev->reset_work); diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 2e37fc2e0fa8..f1c16a587495 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -276,12 +276,11 @@ static int mei_txe_pci_resume(struct device *device) #ifdef CONFIG_PM static int mei_txe_pm_runtime_idle(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; - dev_dbg(&pdev->dev, "rpm: txe: runtime_idle\n"); + dev_dbg(device, "rpm: txe: runtime_idle\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; if (mei_write_is_idle(dev)) @@ -291,13 +290,12 @@ static int mei_txe_pm_runtime_idle(struct device *device) } static int mei_txe_pm_runtime_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; - dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); + dev_dbg(device, "rpm: txe: runtime suspend\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; @@ -310,7 +308,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device) /* keep irq on we are staying in D0 */ - dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); + dev_dbg(device, "rpm: txe: runtime suspend ret=%d\n", ret); mutex_unlock(&dev->device_lock); @@ -322,13 +320,12 @@ static int mei_txe_pm_runtime_suspend(struct device *device) static int mei_txe_pm_runtime_resume(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; - dev_dbg(&pdev->dev, "rpm: txe: runtime resume\n"); + dev_dbg(device, "rpm: txe: runtime resume\n"); - dev = pci_get_drvdata(pdev); + dev = dev_get_drvdata(device); if (!dev) return -ENODEV; @@ -340,7 +337,7 @@ static int mei_txe_pm_runtime_resume(struct device *device) mutex_unlock(&dev->device_lock); - dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret); + dev_dbg(device, "rpm: txe: runtime resume ret = %d\n", ret); if (ret) schedule_work(&dev->reset_work); -- GitLab From 509ce4c85bd055ee1013bc853b5d543428b0f017 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Jul 2019 00:27:39 +0900 Subject: [PATCH 1316/7155] ppdev: add header include guard Add a header include guard just in case. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190728152739.9249-1-yamada.masahiro@socionext.com Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/ppdev.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/ppdev.h b/include/uapi/linux/ppdev.h index 8fe3c64d149e..eb895b83f2bd 100644 --- a/include/uapi/linux/ppdev.h +++ b/include/uapi/linux/ppdev.h @@ -15,6 +15,9 @@ * Added PPGETMODES/PPGETMODE/PPGETPHASE, Fred Barnes , 03/01/2001 */ +#ifndef _UAPI_LINUX_PPDEV_H +#define _UAPI_LINUX_PPDEV_H + #define PP_IOCTL 'p' /* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */ @@ -97,4 +100,4 @@ struct ppdev_frob_struct { /* only masks user-visible flags */ #define PP_FLAGMASK (PP_FASTWRITE | PP_FASTREAD | PP_W91284PIC) - +#endif /* _UAPI_LINUX_PPDEV_H */ -- GitLab From 04d15d5cadb8f764ccf978ddd33cf233dcc68e13 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:42 -0700 Subject: [PATCH 1317/7155] staging: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-43-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 4 +--- drivers/staging/goldfish/goldfish_audio.c | 4 +--- drivers/staging/media/allegro-dvt/allegro-core.c | 4 +--- drivers/staging/media/hantro/hantro_drv.c | 4 +--- drivers/staging/media/imx/imx7-media-csi.c | 4 +--- drivers/staging/media/imx/imx7-mipi-csis.c | 4 +--- drivers/staging/media/meson/vdec/esparser.c | 4 +--- drivers/staging/media/omap4iss/iss.c | 1 - drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 5 +---- drivers/staging/most/dim2/dim2.c | 2 -- drivers/staging/mt7621-dma/mtk-hsdma.c | 4 +--- drivers/staging/nvec/nvec.c | 4 +--- drivers/staging/ralink-gdma/ralink-gdma.c | 4 +--- .../vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 +--- 14 files changed, 12 insertions(+), 40 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 4f3c2c13a225..489cde4e915e 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3094,10 +3094,8 @@ static int nbu2ss_drv_probe(struct platform_device *pdev) return PTR_ERR(mmio_base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); + if (irq < 0) return irq; - } status = devm_request_irq(&pdev->dev, irq, _nbu2ss_udc_irq, 0, driver_name, udc); diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index 24a738238f9f..0c65a0121dde 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -302,10 +302,8 @@ static int goldfish_audio_probe(struct platform_device *pdev) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); + if (data->irq < 0) return -ENODEV; - } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index f050c7347fd5..6f0cd0784786 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -2947,10 +2947,8 @@ static int allegro_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, allegro_hardirq, allegro_irq_thread, diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index c3665f0e87a2..4a7afad2af92 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -733,10 +733,8 @@ static int hantro_probe(struct platform_device *pdev) continue; irq = platform_get_irq_byname(vpu->pdev, irq_name); - if (irq <= 0) { - dev_err(vpu->dev, "Could not get %s IRQ.\n", irq_name); + if (irq <= 0) return -ENXIO; - } ret = devm_request_irq(vpu->dev, irq, vpu->variant->irqs[i].handler, 0, diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 500b4c08d967..d7d38dd9f168 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1194,10 +1194,8 @@ static int imx7_csi_probe(struct platform_device *pdev) } csi->irq = platform_get_irq(pdev, 0); - if (csi->irq < 0) { - dev_err(dev, "Missing platform resources data\n"); + if (csi->irq < 0) return csi->irq; - } csi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(csi->regbase)) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index d1cdf011c8f1..73d8354e618c 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -975,10 +975,8 @@ static int mipi_csis_probe(struct platform_device *pdev) return PTR_ERR(state->regs); state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { - dev_err(dev, "Failed to get irq\n"); + if (state->irq < 0) return state->irq; - } ret = mipi_csis_clk_get(state); if (ret < 0) diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c index 3a21a8cec799..95102a4bdc62 100644 --- a/drivers/staging/media/meson/vdec/esparser.c +++ b/drivers/staging/media/meson/vdec/esparser.c @@ -301,10 +301,8 @@ int esparser_init(struct platform_device *pdev, struct amvdec_core *core) int irq; irq = platform_get_irq_byname(pdev, "esparser"); - if (irq < 0) { - dev_err(dev, "Failed getting ESPARSER IRQ from dtb\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, esparser_isr, IRQF_SHARED, "esparserirq", core); diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index c8be1db532ab..1a966cb2f3a6 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1276,7 +1276,6 @@ static int iss_probe(struct platform_device *pdev) /* Interrupt */ ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(iss->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iss; } diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index c34aec7c6e40..9ce3a65903c5 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -160,11 +160,8 @@ int cedrus_hw_probe(struct cedrus_dev *dev) dev->capabilities = variant->capabilities; irq_dec = platform_get_irq(dev->pdev, 0); - if (irq_dec <= 0) { - dev_err(dev->dev, "Failed to get IRQ\n"); - + if (irq_dec <= 0) return irq_dec; - } ret = devm_request_irq(dev->dev, irq_dec, cedrus_irq, 0, dev_name(dev->dev), dev); if (ret) { diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 043a3e14fdfc..64c979155a49 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -778,7 +778,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, AHB0_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } @@ -792,7 +791,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, MLB_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c index 60db06768c8a..d964642d95a3 100644 --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ b/drivers/staging/mt7621-dma/mtk-hsdma.c @@ -675,10 +675,8 @@ static int mtk_hsdma_probe(struct platform_device *pdev) tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, 0, dev_name(&pdev->dev), hsdma); if (ret) { diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 08027a36e0bc..1cbd7b71fc38 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -796,10 +796,8 @@ static int tegra_nvec_probe(struct platform_device *pdev) return PTR_ERR(base); nvec->irq = platform_get_irq(pdev, 0); - if (nvec->irq < 0) { - dev_err(dev, "no irq resource?\n"); + if (nvec->irq < 0) return -ENODEV; - } i2c_clk = devm_clk_get(dev, "div-clk"); if (IS_ERR(i2c_clk)) { diff --git a/drivers/staging/ralink-gdma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c index 5854551d0a52..900424db9b97 100644 --- a/drivers/staging/ralink-gdma/ralink-gdma.c +++ b/drivers/staging/ralink-gdma/ralink-gdma.c @@ -826,10 +826,8 @@ static int gdma_dma_probe(struct platform_device *pdev) tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, 0, dev_name(&pdev->dev), dma_dev); if (ret) { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 61c69f353cdb..8dc730cfe7a6 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -141,10 +141,8 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) return PTR_ERR(g_regs); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "failed to get IRQ\n"); + if (irq <= 0) return irq; - } err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, "VCHIQ doorbell", state); -- GitLab From da422ade5c879355f7410859069ef4f957c303d4 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 23 Jul 2019 14:22:03 +0100 Subject: [PATCH 1318/7155] Documentation/features/locking: update lists The locking feature lists don't match reality as of v5.3-rc1: * arm64 moved to queued spinlocks in commit: c11090474d70590170cf5fa6afe85864ab494b37 ("arm64: locking: Replace ticket lock implementation with qspinlock") * xtensa moved to queued spinlocks and rwlocks in commit: 579afe866f52adcd921272a224ab36733051059c ("xtensa: use generic spinlock/rwlock implementation") * architecture-specific rwsem support was removed in commit: 46ad0840b1584b92b5ff2cc3ed0b011dd6b8e0f1 ("locking/rwsem: Remove arch specific rwsem files") So update the feature lists accordingly, and remove the now redundant rwsem-optimized list. Signed-off-by: Mark Rutland Signed-off-by: Jonathan Corbet --- .../locking/queued-rwlocks/arch-support.txt | 2 +- .../locking/queued-spinlocks/arch-support.txt | 4 +-- .../locking/rwsem-optimized/arch-support.txt | 34 ------------------- 3 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 Documentation/features/locking/rwsem-optimized/arch-support.txt diff --git a/Documentation/features/locking/queued-rwlocks/arch-support.txt b/Documentation/features/locking/queued-rwlocks/arch-support.txt index c683da198f31..ee922746a64c 100644 --- a/Documentation/features/locking/queued-rwlocks/arch-support.txt +++ b/Documentation/features/locking/queued-rwlocks/arch-support.txt @@ -30,5 +30,5 @@ | um: | TODO | | unicore32: | TODO | | x86: | ok | - | xtensa: | TODO | + | xtensa: | ok | ----------------------- diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt index e3080b82aefd..c52116c1a049 100644 --- a/Documentation/features/locking/queued-spinlocks/arch-support.txt +++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt @@ -9,7 +9,7 @@ | alpha: | TODO | | arc: | TODO | | arm: | TODO | - | arm64: | TODO | + | arm64: | ok | | c6x: | TODO | | csky: | TODO | | h8300: | TODO | @@ -30,5 +30,5 @@ | um: | TODO | | unicore32: | TODO | | x86: | ok | - | xtensa: | TODO | + | xtensa: | ok | ----------------------- diff --git a/Documentation/features/locking/rwsem-optimized/arch-support.txt b/Documentation/features/locking/rwsem-optimized/arch-support.txt deleted file mode 100644 index 7521d7500fbe..000000000000 --- a/Documentation/features/locking/rwsem-optimized/arch-support.txt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Feature name: rwsem-optimized -# Kconfig: !RWSEM_GENERIC_SPINLOCK -# description: arch provides optimized rwsem APIs -# - ----------------------- - | arch |status| - ----------------------- - | alpha: | ok | - | arc: | TODO | - | arm: | ok | - | arm64: | ok | - | c6x: | TODO | - | csky: | TODO | - | h8300: | TODO | - | hexagon: | TODO | - | ia64: | ok | - | m68k: | TODO | - | microblaze: | TODO | - | mips: | TODO | - | nds32: | TODO | - | nios2: | TODO | - | openrisc: | TODO | - | parisc: | TODO | - | powerpc: | TODO | - | riscv: | TODO | - | s390: | ok | - | sh: | ok | - | sparc: | ok | - | um: | ok | - | unicore32: | TODO | - | x86: | ok | - | xtensa: | ok | - ----------------------- -- GitLab From 38a449ff533c9a21c254473a9f0cf59b6f420f50 Mon Sep 17 00:00:00 2001 From: Sheriff Esseson Date: Tue, 23 Jul 2019 12:48:13 +0100 Subject: [PATCH 1319/7155] Documentation: filesystem: fix "Removed Sysctls" table the "Removed Sysctls" section is a table - bring it alive with ReST. Signed-off-by: Sheriff Esseson Signed-off-by: Jonathan Corbet --- Documentation/admin-guide/xfs.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/xfs.rst b/Documentation/admin-guide/xfs.rst index e76665a8f2f2..fb5b39f73059 100644 --- a/Documentation/admin-guide/xfs.rst +++ b/Documentation/admin-guide/xfs.rst @@ -337,11 +337,12 @@ None at present. Removed Sysctls =============== +============================= ======= Name Removed - ---- ------- +============================= ======= fs.xfs.xfsbufd_centisec v4.0 fs.xfs.age_buffer_centisecs v4.0 - +============================= ======= Error handling ============== -- GitLab From c6e0396124de72d6ab7f8c8e01af7f79ee1aa698 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 19:57:50 +0300 Subject: [PATCH 1320/7155] coda: Fix typo in the struct CodaCred documentation Documentation mistakenly refers to a different type while explaining the contents of the struct CodaCred. Fix the typo in the struct CodaCred description in the documentation. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Corbet --- Documentation/filesystems/coda.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/coda.txt b/Documentation/filesystems/coda.txt index 545262c167c3..1711ad48e38a 100644 --- a/Documentation/filesystems/coda.txt +++ b/Documentation/filesystems/coda.txt @@ -421,14 +421,14 @@ kernel support. The CodaCred structure defines a variety of user and group ids as - they are set for the calling process. The vuid_t and guid_t are 32 bit + they are set for the calling process. The vuid_t and vgid_t are 32 bit unsigned integers. It also defines group membership in an array. On Unix the CodaCred has proven sufficient to implement good security semantics for Coda but the structure may have to undergo modification for the Windows environment when these mature. struct CodaCred { - vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, effective, set, fs uid*/ + vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, effective, set, fs uid */ vgid_t cr_gid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */ vgid_t cr_groups[NGROUPS]; /* Group membership for caller */ }; -- GitLab From 4c31bc6b1e2ee9c21608506431783dfa525b9989 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 30 Jul 2019 20:38:19 +0800 Subject: [PATCH 1321/7155] sctp: only copy the available addr data in sctp_transport_init 'addr' passed to sctp_transport_init is not always a whole size of union sctp_addr, like the path: sctp_sendmsg() -> sctp_sendmsg_new_asoc() -> sctp_assoc_add_peer() -> sctp_transport_new() -> sctp_transport_init() In the next patches, we will also pass the address length of data only to sctp_assoc_add_peer(). So sctp_transport_init() should copy the only available data from addr to peer->ipaddr, instead of 'peer->ipaddr = *addr' which may cause slab-out-of-bounds. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e2f8e369cd08..7235a6032671 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -43,8 +43,8 @@ static struct sctp_transport *sctp_transport_init(struct net *net, gfp_t gfp) { /* Copy in the address. */ - peer->ipaddr = *addr; peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); + memcpy(&peer->ipaddr, addr, peer->af_specific->sockaddr_len); memset(&peer->saddr, 0, sizeof(union sctp_addr)); peer->sack_generation = 0; -- GitLab From f40f1177c38cb642b65af9f077bc56241e2b41c2 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 30 Jul 2019 20:38:20 +0800 Subject: [PATCH 1322/7155] sctp: check addr_size with sa_family_t size in __sctp_setsockopt_connectx Now __sctp_connect() is called by __sctp_setsockopt_connectx() and sctp_inet_connect(), the latter has done addr_size check with size of sa_family_t. In the next patch to clean up __sctp_connect(), we will remove addr_size check with size of sa_family_t from __sctp_connect() for the 1st address. So before doing that, __sctp_setsockopt_connectx() should do this check first, as sctp_inet_connect() does. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index aa80cda36581..e9c5b3930ae6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1311,7 +1311,8 @@ static int __sctp_setsockopt_connectx(struct sock *sk, pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", __func__, sk, addrs, addrs_size); - if (unlikely(addrs_size <= 0)) + /* make sure the 1st addr's sa_family is accessible later */ + if (unlikely(addrs_size < sizeof(sa_family_t))) return -EINVAL; kaddrs = memdup_user(addrs, addrs_size); -- GitLab From dd8378b3af57840ef1cc87e416bd0bb35e60d8ec Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 30 Jul 2019 20:38:21 +0800 Subject: [PATCH 1323/7155] sctp: clean up __sctp_connect __sctp_connect is doing quit similar things as sctp_sendmsg_new_asoc. To factor out common functions, this patch is to clean up their code to make them look more similar: 1. create the asoc and add a peer with the 1st addr. 2. add peers with the other addrs into this asoc one by one. while at it, also remove the unused 'addrcnt'. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/socket.c | 209 ++++++++++++++++------------------------------ 1 file changed, 73 insertions(+), 136 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e9c5b3930ae6..b9804e51b5d1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1049,153 +1049,105 @@ static int sctp_setsockopt_bindx(struct sock *sk, * Common routine for handling connect() and sctp_connectx(). * Connect will come in with just a single address. */ -static int __sctp_connect(struct sock *sk, - struct sockaddr *kaddrs, - int addrs_size, int flags, - sctp_assoc_t *assoc_id) +static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, + int addrs_size, int flags, sctp_assoc_t *assoc_id) { - struct net *net = sock_net(sk); - struct sctp_sock *sp; - struct sctp_endpoint *ep; - struct sctp_association *asoc = NULL; - struct sctp_association *asoc2; + struct sctp_association *old, *asoc; + struct sctp_sock *sp = sctp_sk(sk); + struct sctp_endpoint *ep = sp->ep; struct sctp_transport *transport; - union sctp_addr to; + struct net *net = sock_net(sk); + void *addr_buf = kaddrs; + union sctp_addr *daddr; enum sctp_scope scope; + struct sctp_af *af; + int walk_size, err; long timeo; - int err = 0; - int addrcnt = 0; - int walk_size = 0; - union sctp_addr *sa_addr = NULL; - void *addr_buf; - unsigned short port; - sp = sctp_sk(sk); - ep = sp->ep; - - /* connect() cannot be done on a socket that is already in ESTABLISHED - * state - UDP-style peeled off socket or a TCP-style socket that - * is already connected. - * It cannot be done even on a TCP-style listening socket. - */ if (sctp_sstate(sk, ESTABLISHED) || sctp_sstate(sk, CLOSING) || - (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { - err = -EISCONN; - goto out_free; + (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) + return -EISCONN; + + daddr = addr_buf; + af = sctp_get_af_specific(daddr->sa.sa_family); + if (!af || af->sockaddr_len > addrs_size) + return -EINVAL; + + err = sctp_verify_addr(sk, daddr, af->sockaddr_len); + if (err) + return err; + + asoc = sctp_endpoint_lookup_assoc(ep, daddr, &transport); + if (asoc) + return asoc->state >= SCTP_STATE_ESTABLISHED ? -EISCONN + : -EALREADY; + + if (sctp_endpoint_is_peeled_off(ep, daddr)) + return -EADDRNOTAVAIL; + + if (!ep->base.bind_addr.port) { + if (sctp_autobind(sk)) + return -EAGAIN; + } else { + if (ep->base.bind_addr.port < inet_prot_sock(net) && + !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) + return -EACCES; } - /* Walk through the addrs buffer and count the number of addresses. */ - addr_buf = kaddrs; - while (walk_size < addrs_size) { - struct sctp_af *af; + scope = sctp_scope(daddr); + asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); + if (!asoc) + return -ENOMEM; - if (walk_size + sizeof(sa_family_t) > addrs_size) { - err = -EINVAL; - goto out_free; - } + err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); + if (err < 0) + goto out_free; - sa_addr = addr_buf; - af = sctp_get_af_specific(sa_addr->sa.sa_family); + transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); + if (!transport) { + err = -ENOMEM; + goto out_free; + } - /* If the address family is not supported or if this address - * causes the address buffer to overflow return EINVAL. - */ - if (!af || (walk_size + af->sockaddr_len) > addrs_size) { - err = -EINVAL; + addr_buf += af->sockaddr_len; + walk_size = af->sockaddr_len; + while (walk_size < addrs_size) { + err = -EINVAL; + if (walk_size + sizeof(sa_family_t) > addrs_size) goto out_free; - } - port = ntohs(sa_addr->v4.sin_port); - - /* Save current address so we can work with it */ - memcpy(&to, sa_addr, af->sockaddr_len); + daddr = addr_buf; + af = sctp_get_af_specific(daddr->sa.sa_family); + if (!af || af->sockaddr_len + walk_size > addrs_size) + goto out_free; - err = sctp_verify_addr(sk, &to, af->sockaddr_len); - if (err) + if (asoc->peer.port != ntohs(daddr->v4.sin_port)) goto out_free; - /* Make sure the destination port is correctly set - * in all addresses. - */ - if (asoc && asoc->peer.port && asoc->peer.port != port) { - err = -EINVAL; + err = sctp_verify_addr(sk, daddr, af->sockaddr_len); + if (err) goto out_free; - } - /* Check if there already is a matching association on the - * endpoint (other than the one created here). - */ - asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); - if (asoc2 && asoc2 != asoc) { - if (asoc2->state >= SCTP_STATE_ESTABLISHED) - err = -EISCONN; - else - err = -EALREADY; + old = sctp_endpoint_lookup_assoc(ep, daddr, &transport); + if (old && old != asoc) { + err = old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN + : -EALREADY; goto out_free; } - /* If we could not find a matching association on the endpoint, - * make sure that there is no peeled-off association matching - * the peer address even on another socket. - */ - if (sctp_endpoint_is_peeled_off(ep, &to)) { + if (sctp_endpoint_is_peeled_off(ep, daddr)) { err = -EADDRNOTAVAIL; goto out_free; } - if (!asoc) { - /* If a bind() or sctp_bindx() is not called prior to - * an sctp_connectx() call, the system picks an - * ephemeral port and will choose an address set - * equivalent to binding with a wildcard address. - */ - if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) { - err = -EAGAIN; - goto out_free; - } - } else { - /* - * If an unprivileged user inherits a 1-many - * style socket with open associations on a - * privileged port, it MAY be permitted to - * accept new associations, but it SHOULD NOT - * be permitted to open new associations. - */ - if (ep->base.bind_addr.port < - inet_prot_sock(net) && - !ns_capable(net->user_ns, - CAP_NET_BIND_SERVICE)) { - err = -EACCES; - goto out_free; - } - } - - scope = sctp_scope(&to); - asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); - if (!asoc) { - err = -ENOMEM; - goto out_free; - } - - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, - GFP_KERNEL); - if (err < 0) { - goto out_free; - } - - } - - /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, + transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; goto out_free; } - addrcnt++; - addr_buf += af->sockaddr_len; + addr_buf += af->sockaddr_len; walk_size += af->sockaddr_len; } @@ -1209,39 +1161,24 @@ static int __sctp_connect(struct sock *sk, } err = sctp_primitive_ASSOCIATE(net, asoc, NULL); - if (err < 0) { + if (err < 0) goto out_free; - } /* Initialize sk's dport and daddr for getpeername() */ inet_sk(sk)->inet_dport = htons(asoc->peer.port); - sp->pf->to_sk_daddr(sa_addr, sk); + sp->pf->to_sk_daddr(daddr, sk); sk->sk_err = 0; - timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); - if (assoc_id) *assoc_id = asoc->assoc_id; - err = sctp_wait_for_connect(asoc, &timeo); - /* Note: the asoc may be freed after the return of - * sctp_wait_for_connect. - */ - - /* Don't free association on exit. */ - asoc = NULL; + timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + return sctp_wait_for_connect(asoc, &timeo); out_free: pr_debug("%s: took out_free path with asoc:%p kaddrs:%p err:%d\n", __func__, asoc, kaddrs, err); - - if (asoc) { - /* sctp_primitive_ASSOCIATE may have added this association - * To the hash table, try to unhash it, just in case, its a noop - * if it wasn't hashed so we're safe - */ - sctp_association_free(asoc); - } + sctp_association_free(asoc); return err; } -- GitLab From f26f995122f4c16c3a863aacbe85043135976632 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 30 Jul 2019 20:38:22 +0800 Subject: [PATCH 1324/7155] sctp: factor out sctp_connect_new_asoc In this function factored out from sctp_sendmsg_new_asoc() and __sctp_connect(), it creates the asoc and adds a peer with the 1st addr. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/socket.c | 160 ++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 84 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b9804e51b5d1..6f778539c52b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1044,6 +1044,73 @@ static int sctp_setsockopt_bindx(struct sock *sk, return err; } +static int sctp_connect_new_asoc(struct sctp_endpoint *ep, + const union sctp_addr *daddr, + const struct sctp_initmsg *init, + struct sctp_transport **tp) +{ + struct sctp_association *asoc; + struct sock *sk = ep->base.sk; + struct net *net = sock_net(sk); + enum sctp_scope scope; + int err; + + if (sctp_endpoint_is_peeled_off(ep, daddr)) + return -EADDRNOTAVAIL; + + if (!ep->base.bind_addr.port) { + if (sctp_autobind(sk)) + return -EAGAIN; + } else { + if (ep->base.bind_addr.port < inet_prot_sock(net) && + !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) + return -EACCES; + } + + scope = sctp_scope(daddr); + asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); + if (!asoc) + return -ENOMEM; + + err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); + if (err < 0) + goto free; + + *tp = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); + if (!*tp) { + err = -ENOMEM; + goto free; + } + + if (!init) + return 0; + + if (init->sinit_num_ostreams) { + __u16 outcnt = init->sinit_num_ostreams; + + asoc->c.sinit_num_ostreams = outcnt; + /* outcnt has been changed, need to re-init stream */ + err = sctp_stream_init(&asoc->stream, outcnt, 0, GFP_KERNEL); + if (err) + goto free; + } + + if (init->sinit_max_instreams) + asoc->c.sinit_max_instreams = init->sinit_max_instreams; + + if (init->sinit_max_attempts) + asoc->max_init_attempts = init->sinit_max_attempts; + + if (init->sinit_max_init_timeo) + asoc->max_init_timeo = + msecs_to_jiffies(init->sinit_max_init_timeo); + + return 0; +free: + sctp_association_free(asoc); + return err; +} + /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) * * Common routine for handling connect() and sctp_connectx(). @@ -1056,10 +1123,8 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; struct sctp_transport *transport; - struct net *net = sock_net(sk); void *addr_buf = kaddrs; union sctp_addr *daddr; - enum sctp_scope scope; struct sctp_af *af; int walk_size, err; long timeo; @@ -1082,32 +1147,10 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, return asoc->state >= SCTP_STATE_ESTABLISHED ? -EISCONN : -EALREADY; - if (sctp_endpoint_is_peeled_off(ep, daddr)) - return -EADDRNOTAVAIL; - - if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) - return -EAGAIN; - } else { - if (ep->base.bind_addr.port < inet_prot_sock(net) && - !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) - return -EACCES; - } - - scope = sctp_scope(daddr); - asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); - if (!asoc) - return -ENOMEM; - - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); - if (err < 0) - goto out_free; - - transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); - if (!transport) { - err = -ENOMEM; - goto out_free; - } + err = sctp_connect_new_asoc(ep, daddr, NULL, &transport); + if (err) + return err; + asoc = transport->asoc; addr_buf += af->sockaddr_len; walk_size = af->sockaddr_len; @@ -1160,7 +1203,7 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, goto out_free; } - err = sctp_primitive_ASSOCIATE(net, asoc, NULL); + err = sctp_primitive_ASSOCIATE(sock_net(sk), asoc, NULL); if (err < 0) goto out_free; @@ -1597,9 +1640,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, struct sctp_transport **tp) { struct sctp_endpoint *ep = sctp_sk(sk)->ep; - struct net *net = sock_net(sk); struct sctp_association *asoc; - enum sctp_scope scope; struct cmsghdr *cmsg; __be32 flowinfo = 0; struct sctp_af *af; @@ -1614,20 +1655,6 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, sctp_sstate(sk, CLOSING))) return -EADDRNOTAVAIL; - if (sctp_endpoint_is_peeled_off(ep, daddr)) - return -EADDRNOTAVAIL; - - if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) - return -EAGAIN; - } else { - if (ep->base.bind_addr.port < inet_prot_sock(net) && - !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) - return -EACCES; - } - - scope = sctp_scope(daddr); - /* Label connection socket for first association 1-to-many * style for client sequence socket()->sendmsg(). This * needs to be done before sctp_assoc_add_peer() as that will @@ -1643,45 +1670,10 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, if (err < 0) return err; - asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); - if (!asoc) - return -ENOMEM; - - if (sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL) < 0) { - err = -ENOMEM; - goto free; - } - - if (cmsgs->init) { - struct sctp_initmsg *init = cmsgs->init; - - if (init->sinit_num_ostreams) { - __u16 outcnt = init->sinit_num_ostreams; - - asoc->c.sinit_num_ostreams = outcnt; - /* outcnt has been changed, need to re-init stream */ - err = sctp_stream_init(&asoc->stream, outcnt, 0, - GFP_KERNEL); - if (err) - goto free; - } - - if (init->sinit_max_instreams) - asoc->c.sinit_max_instreams = init->sinit_max_instreams; - - if (init->sinit_max_attempts) - asoc->max_init_attempts = init->sinit_max_attempts; - - if (init->sinit_max_init_timeo) - asoc->max_init_timeo = - msecs_to_jiffies(init->sinit_max_init_timeo); - } - - *tp = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); - if (!*tp) { - err = -ENOMEM; - goto free; - } + err = sctp_connect_new_asoc(ep, daddr, cmsgs->init, tp); + if (err) + return err; + asoc = (*tp)->asoc; if (!cmsgs->addrs_msg) return 0; -- GitLab From a64e59c72ca6383149a19164abd29f81e640c08d Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 30 Jul 2019 20:38:23 +0800 Subject: [PATCH 1325/7155] sctp: factor out sctp_connect_add_peer In this function factored out from sctp_sendmsg_new_asoc() and __sctp_connect(), it adds a peer with the other addr into the asoc after this asoc is created with the 1st addr. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/socket.c | 76 +++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6f778539c52b..2f7e88c46dd2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1111,6 +1111,33 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep, return err; } +static int sctp_connect_add_peer(struct sctp_association *asoc, + union sctp_addr *daddr, int addr_len) +{ + struct sctp_endpoint *ep = asoc->ep; + struct sctp_association *old; + struct sctp_transport *t; + int err; + + err = sctp_verify_addr(ep->base.sk, daddr, addr_len); + if (err) + return err; + + old = sctp_endpoint_lookup_assoc(ep, daddr, &t); + if (old && old != asoc) + return old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN + : -EALREADY; + + if (sctp_endpoint_is_peeled_off(ep, daddr)) + return -EADDRNOTAVAIL; + + t = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); + if (!t) + return -ENOMEM; + + return 0; +} + /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) * * Common routine for handling connect() and sctp_connectx(). @@ -1119,10 +1146,10 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep, static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, int addrs_size, int flags, sctp_assoc_t *assoc_id) { - struct sctp_association *old, *asoc; struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; struct sctp_transport *transport; + struct sctp_association *asoc; void *addr_buf = kaddrs; union sctp_addr *daddr; struct sctp_af *af; @@ -1167,29 +1194,10 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, if (asoc->peer.port != ntohs(daddr->v4.sin_port)) goto out_free; - err = sctp_verify_addr(sk, daddr, af->sockaddr_len); + err = sctp_connect_add_peer(asoc, daddr, af->sockaddr_len); if (err) goto out_free; - old = sctp_endpoint_lookup_assoc(ep, daddr, &transport); - if (old && old != asoc) { - err = old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN - : -EALREADY; - goto out_free; - } - - if (sctp_endpoint_is_peeled_off(ep, daddr)) { - err = -EADDRNOTAVAIL; - goto out_free; - } - - transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, - SCTP_UNKNOWN); - if (!transport) { - err = -ENOMEM; - goto out_free; - } - addr_buf += af->sockaddr_len; walk_size += af->sockaddr_len; } @@ -1683,8 +1691,6 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, /* sendv addr list parse */ for_each_cmsghdr(cmsg, cmsgs->addrs_msg) { - struct sctp_transport *transport; - struct sctp_association *old; union sctp_addr _daddr; int dlen; @@ -1718,30 +1724,10 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, daddr->v6.sin6_port = htons(asoc->peer.port); memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen); } - err = sctp_verify_addr(sk, daddr, sizeof(*daddr)); - if (err) - goto free; - - old = sctp_endpoint_lookup_assoc(ep, daddr, &transport); - if (old && old != asoc) { - if (old->state >= SCTP_STATE_ESTABLISHED) - err = -EISCONN; - else - err = -EALREADY; - goto free; - } - if (sctp_endpoint_is_peeled_off(ep, daddr)) { - err = -EADDRNOTAVAIL; - goto free; - } - - transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, - SCTP_UNKNOWN); - if (!transport) { - err = -ENOMEM; + err = sctp_connect_add_peer(asoc, daddr, sizeof(*daddr)); + if (err) goto free; - } } return 0; -- GitLab From 7240b60c98d6309363a9f8d5a4ecd5b0626f2aff Mon Sep 17 00:00:00 2001 From: Jonathan Lemon Date: Tue, 30 Jul 2019 07:40:32 -0700 Subject: [PATCH 1326/7155] linux: Add skb_frag_t page_offset accessors Add skb_frag_off(), skb_frag_off_add(), skb_frag_off_set(), and skb_frag_off_copy() accessors for page_offset. Signed-off-by: Jonathan Lemon Signed-off-by: David S. Miller --- include/linux/skbuff.h | 67 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 718742b1c505..2957cdd6c032 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -312,7 +312,7 @@ extern int sysctl_max_skb_frags; typedef struct bio_vec skb_frag_t; /** - * skb_frag_size - Returns the size of a skb fragment + * skb_frag_size() - Returns the size of a skb fragment * @frag: skb fragment */ static inline unsigned int skb_frag_size(const skb_frag_t *frag) @@ -321,7 +321,7 @@ static inline unsigned int skb_frag_size(const skb_frag_t *frag) } /** - * skb_frag_size_set - Sets the size of a skb fragment + * skb_frag_size_set() - Sets the size of a skb fragment * @frag: skb fragment * @size: size of fragment */ @@ -331,7 +331,7 @@ static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size) } /** - * skb_frag_size_add - Incrementes the size of a skb fragment by %delta + * skb_frag_size_add() - Increments the size of a skb fragment by @delta * @frag: skb fragment * @delta: value to add */ @@ -341,7 +341,7 @@ static inline void skb_frag_size_add(skb_frag_t *frag, int delta) } /** - * skb_frag_size_sub - Decrements the size of a skb fragment by %delta + * skb_frag_size_sub() - Decrements the size of a skb fragment by @delta * @frag: skb fragment * @delta: value to subtract */ @@ -2857,6 +2857,46 @@ static inline void skb_propagate_pfmemalloc(struct page *page, skb->pfmemalloc = true; } +/** + * skb_frag_off() - Returns the offset of a skb fragment + * @frag: the paged fragment + */ +static inline unsigned int skb_frag_off(const skb_frag_t *frag) +{ + return frag->page_offset; +} + +/** + * skb_frag_off_add() - Increments the offset of a skb fragment by @delta + * @frag: skb fragment + * @delta: value to add + */ +static inline void skb_frag_off_add(skb_frag_t *frag, int delta) +{ + frag->page_offset += delta; +} + +/** + * skb_frag_off_set() - Sets the offset of a skb fragment + * @frag: skb fragment + * @offset: offset of fragment + */ +static inline void skb_frag_off_set(skb_frag_t *frag, unsigned int offset) +{ + frag->page_offset = offset; +} + +/** + * skb_frag_off_copy() - Sets the offset of a skb fragment from another fragment + * @fragto: skb fragment where offset is set + * @fragfrom: skb fragment offset is copied from + */ +static inline void skb_frag_off_copy(skb_frag_t *fragto, + const skb_frag_t *fragfrom) +{ + fragto->page_offset = fragfrom->page_offset; +} + /** * skb_frag_page - retrieve the page referred to by a paged fragment * @frag: the paged fragment @@ -2923,7 +2963,7 @@ static inline void skb_frag_unref(struct sk_buff *skb, int f) */ static inline void *skb_frag_address(const skb_frag_t *frag) { - return page_address(skb_frag_page(frag)) + frag->page_offset; + return page_address(skb_frag_page(frag)) + skb_frag_off(frag); } /** @@ -2939,7 +2979,18 @@ static inline void *skb_frag_address_safe(const skb_frag_t *frag) if (unlikely(!ptr)) return NULL; - return ptr + frag->page_offset; + return ptr + skb_frag_off(frag); +} + +/** + * skb_frag_page_copy() - sets the page in a fragment from another fragment + * @fragto: skb fragment where page is set + * @fragfrom: skb fragment page is copied from + */ +static inline void skb_frag_page_copy(skb_frag_t *fragto, + const skb_frag_t *fragfrom) +{ + fragto->bv_page = fragfrom->bv_page; } /** @@ -2987,7 +3038,7 @@ static inline dma_addr_t skb_frag_dma_map(struct device *dev, enum dma_data_direction dir) { return dma_map_page(dev, skb_frag_page(frag), - frag->page_offset + offset, size, dir); + skb_frag_off(frag) + offset, size, dir); } static inline struct sk_buff *pskb_copy(struct sk_buff *skb, @@ -3157,7 +3208,7 @@ static inline bool skb_can_coalesce(struct sk_buff *skb, int i, const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; return page == skb_frag_page(frag) && - off == frag->page_offset + skb_frag_size(frag); + off == skb_frag_off(frag) + skb_frag_size(frag); } return false; } -- GitLab From b54c9d5bd6e38edac9ce3a3f95f14a1292b5268d Mon Sep 17 00:00:00 2001 From: Jonathan Lemon Date: Tue, 30 Jul 2019 07:40:33 -0700 Subject: [PATCH 1327/7155] net: Use skb_frag_off accessors Use accessor functions for skb fragment's page_offset instead of direct references, in preparation for bvec conversion. Signed-off-by: Jonathan Lemon Signed-off-by: David S. Miller --- drivers/atm/eni.c | 2 +- drivers/hsi/clients/ssi_protocol.c | 2 +- drivers/infiniband/hw/hfi1/vnic_sdma.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 3 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- .../ethernet/cavium/thunder/nicvf_queues.c | 2 +- drivers/net/ethernet/chelsio/cxgb3/sge.c | 2 +- drivers/net/ethernet/emulex/benet/be_main.c | 12 ++--- .../ethernet/freescale/fs_enet/fs_enet-main.c | 2 +- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 +- drivers/net/ethernet/intel/iavf/iavf_txrx.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +- drivers/net/ethernet/jme.c | 4 +- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- .../net/ethernet/myricom/myri10ge/myri10ge.c | 6 +-- drivers/net/ethernet/sfc/tx.c | 2 +- drivers/net/ethernet/sun/cassini.c | 8 +-- drivers/net/ethernet/sun/niu.c | 2 +- drivers/net/ethernet/sun/sunvnet_common.c | 4 +- drivers/net/ethernet/ti/netcp_core.c | 2 +- drivers/net/hyperv/netvsc_drv.c | 4 +- drivers/net/thunderbolt.c | 2 +- drivers/net/usb/usbnet.c | 2 +- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- drivers/net/xen-netback/netback.c | 6 +-- drivers/net/xen-netfront.c | 8 +-- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- drivers/scsi/fcoe/fcoe.c | 3 +- drivers/scsi/fcoe/fcoe_transport.c | 2 +- drivers/scsi/qedf/qedf_main.c | 2 +- .../staging/unisys/visornic/visornic_main.c | 2 +- drivers/target/iscsi/cxgbit/cxgbit_target.c | 4 +- net/appletalk/ddp.c | 4 +- net/core/datagram.c | 6 +-- net/core/dev.c | 2 +- net/core/pktgen.c | 2 +- net/core/skbuff.c | 54 ++++++++++--------- net/ipv4/tcp.c | 6 +-- net/ipv4/tcp_output.c | 2 +- net/kcm/kcmsock.c | 2 +- net/tls/tls_device.c | 8 +-- net/tls/tls_device_fallback.c | 2 +- net/xfrm/xfrm_ipcomp.c | 2 +- 44 files changed, 100 insertions(+), 98 deletions(-) diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 79b718430cd1..b23d1e4bad33 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -1136,7 +1136,7 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */ else put_dma(tx->index,eni_dev->dma,&j,(unsigned long) skb_frag_page(&skb_shinfo(skb)->frags[i]) + - skb_shinfo(skb)->frags[i].page_offset, + skb_frag_off(&skb_shinfo(skb)->frags[i]), skb_frag_size(&skb_shinfo(skb)->frags[i])); } if (skb->len & 3) { diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index c9e3f928b93d..0253e76f1df2 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -182,7 +182,7 @@ static void ssip_skb_to_msg(struct sk_buff *skb, struct hsi_msg *msg) BUG_ON(!sg); frag = &skb_shinfo(skb)->frags[i]; sg_set_page(sg, skb_frag_page(frag), skb_frag_size(frag), - frag->page_offset); + skb_frag_off(frag)); } } diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c index 05a140504a99..7d90b900131b 100644 --- a/drivers/infiniband/hw/hfi1/vnic_sdma.c +++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c @@ -108,7 +108,7 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde, ret = sdma_txadd_page(sde->dd, &tx->txreq, skb_frag_page(frag), - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag)); if (unlikely(ret)) goto bail_txadd; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 78fa777c87b1..c332b4761816 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -293,7 +293,8 @@ int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req) const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; mapping[i + off] = ib_dma_map_page(ca, skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), + skb_frag_off(frag), + skb_frag_size(frag), DMA_TO_DEVICE); if (unlikely(ib_dma_mapping_error(ca, mapping[i + off]))) goto partial_error; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index ac61c9352535..c23fbb34f0e9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -957,7 +957,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, frag = &skb_shinfo(skb)->frags[0]; skb_frag_size_sub(frag, payload); - frag->page_offset += payload; + skb_frag_off_add(frag, payload); skb->data_len -= payload; skb->tail += payload; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index c0266a87794c..4ab57d33a87e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -1594,7 +1594,7 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq, size = skb_frag_size(frag); dma_addr = dma_map_page_attrs(&nic->pdev->dev, skb_frag_page(frag), - frag->page_offset, size, + skb_frag_off(frag), size, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); if (dma_mapping_error(&nic->pdev->dev, dma_addr)) { diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 310a232e00f0..6dabbf1502c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2182,7 +2182,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, rx_frag += nr_frags; __skb_frag_set_page(rx_frag, sd->pg_chunk.page); - rx_frag->page_offset = sd->pg_chunk.offset + offset; + skb_frag_off_set(rx_frag, sd->pg_chunk.offset + offset); skb_frag_size_set(rx_frag, len); skb->len += len; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e00a94a03879..1c9883019767 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2346,8 +2346,8 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, memcpy(skb->data, start, hdr_len); skb_shinfo(skb)->nr_frags = 1; skb_frag_set_page(skb, 0, page_info->page); - skb_shinfo(skb)->frags[0].page_offset = - page_info->page_offset + hdr_len; + skb_frag_off_set(&skb_shinfo(skb)->frags[0], + page_info->page_offset + hdr_len); skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len); skb->data_len = curr_frag_len - hdr_len; @@ -2372,8 +2372,8 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, /* Fresh page */ j++; skb_frag_set_page(skb, j, page_info->page); - skb_shinfo(skb)->frags[j].page_offset = - page_info->page_offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[j], + page_info->page_offset); skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); skb_shinfo(skb)->nr_frags++; } else { @@ -2454,8 +2454,8 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, /* First frag or Fresh page */ j++; skb_frag_set_page(skb, j, page_info->page); - skb_shinfo(skb)->frags[j].page_offset = - page_info->page_offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[j], + page_info->page_offset); skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); } else { put_page(page_info->page); diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 5fad73b2e123..3981c06f082f 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -501,7 +501,7 @@ fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) nr_frags = skb_shinfo(skb)->nr_frags; frag = skb_shinfo(skb)->frags; for (i = 0; i < nr_frags; i++, frag++) { - if (!IS_ALIGNED(frag->page_offset, 4)) { + if (!IS_ALIGNED(skb_frag_off(frag), 4)) { is_aligned = 0; break; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 3da680073265..81a05ea38237 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1485,7 +1485,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) memcpy(dst + cur, page_address(skb_frag_page(frag)) + - frag->page_offset, skb_frag_size(frag)); + skb_frag_off(frag), skb_frag_size(frag)); cur += skb_frag_size(frag); } } else { diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index f162252f01b5..e3f29dc8b290 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3306,7 +3306,7 @@ bool __i40e_chk_linearize(struct sk_buff *skb) * descriptor associated with the fragment. */ if (stale_size > I40E_MAX_DATA_PER_TXD) { - int align_pad = -(stale->page_offset) & + int align_pad = -(skb_frag_off(stale)) & (I40E_MAX_READ_REQ_SIZE - 1); sum -= align_pad; diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index fae7cd1c618a..7a30d5d5ef53 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -2205,7 +2205,7 @@ bool __iavf_chk_linearize(struct sk_buff *skb) * descriptor associated with the fragment. */ if (stale_size > IAVF_MAX_DATA_PER_TXD) { - int align_pad = -(stale->page_offset) & + int align_pad = -(skb_frag_off(stale)) & (IAVF_MAX_READ_REQ_SIZE - 1); sum -= align_pad; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index e12d23d1fa64..dc7b128c780e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1807,7 +1807,7 @@ static void ixgbe_pull_tail(struct ixgbe_ring *rx_ring, /* update all of the pointers */ skb_frag_size_sub(frag, pull_len); - frag->page_offset += pull_len; + skb_frag_off_add(frag, pull_len); skb->data_len -= pull_len; skb->tail += pull_len; } @@ -1844,7 +1844,7 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, dma_sync_single_range_for_cpu(rx_ring->dev, IXGBE_CB(skb)->dma, - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag), DMA_FROM_DEVICE); } diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 9c3ab00643bd..6d52cf5ce20e 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2040,8 +2040,8 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) ctxbi = txbi + ((idx + i + 2) & (mask)); ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, - skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), hidma); + skb_frag_page(frag), skb_frag_off(frag), + skb_frag_size(frag), hidma); if (ret) { jme_drop_tx_map(jme, idx, i); goto out; diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 88ea5ac83c93..82ea55ae5053 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -659,7 +659,7 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { const skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag]; - if (skb_frag_size(fragp) <= 8 && fragp->page_offset & 7) + if (skb_frag_size(fragp) <= 8 && skb_frag_off(fragp) & 7) return 1; } diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 9ead6ecb7586..99eaadba555f 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -1306,8 +1306,8 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb) skb->len -= VLAN_HLEN; skb->data_len -= VLAN_HLEN; frag = skb_shinfo(skb)->frags; - frag->page_offset += VLAN_HLEN; - skb_frag_size_set(frag, skb_frag_size(frag) - VLAN_HLEN); + skb_frag_off_add(frag, VLAN_HLEN); + skb_frag_size_sub(frag, VLAN_HLEN); } } @@ -1364,7 +1364,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) } /* remove padding */ - rx_frags[0].page_offset += MXGEFW_PAD; + skb_frag_off_add(&rx_frags[0], MXGEFW_PAD); skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD); len -= MXGEFW_PAD; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 31ec56091a5d..65e81ec1b314 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -274,7 +274,7 @@ static void efx_skb_copy_bits_to_pio(struct efx_nic *efx, struct sk_buff *skb, vaddr = kmap_atomic(skb_frag_page(f)); - efx_memcpy_toio_aligned_cb(efx, piobuf, vaddr + f->page_offset, + efx_memcpy_toio_aligned_cb(efx, piobuf, vaddr + skb_frag_off(f), skb_frag_size(f), copy_buf); kunmap_atomic(vaddr); } diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 6fc05c106afc..c91876f8c536 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -2034,7 +2034,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, __skb_frag_set_page(frag, page->buffer); __skb_frag_ref(frag); - frag->page_offset = off; + skb_frag_off_set(frag, off); skb_frag_size_set(frag, hlen - swivel); /* any more data? */ @@ -2058,7 +2058,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, __skb_frag_set_page(frag, page->buffer); __skb_frag_ref(frag); - frag->page_offset = 0; + skb_frag_off_set(frag, 0); skb_frag_size_set(frag, hlen); RX_USED_ADD(page, hlen + cp->crc_size); } @@ -2816,7 +2816,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, mapping = skb_frag_dma_map(&cp->pdev->dev, fragp, 0, len, DMA_TO_DEVICE); - tabort = cas_calc_tabort(cp, fragp->page_offset, len); + tabort = cas_calc_tabort(cp, skb_frag_off(fragp), len); if (unlikely(tabort)) { void *addr; @@ -2827,7 +2827,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, addr = cas_page_map(skb_frag_page(fragp)); memcpy(tx_tiny_buf(cp, ring, entry), - addr + fragp->page_offset + len - tabort, + addr + skb_frag_off(fragp) + len - tabort, tabort); cas_page_unmap(addr); mapping = tx_tiny_map(cp, ring, entry, tentry); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 0bc5863bffeb..f5fd1f3c07cc 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -6695,7 +6695,7 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, len = skb_frag_size(frag); mapping = np->ops->map_page(np->device, skb_frag_page(frag), - frag->page_offset, len, + skb_frag_off(frag), len, DMA_TO_DEVICE); rp->tx_buffs[prod].skb = NULL; diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index baa3088b475c..646e67236b65 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1088,7 +1088,7 @@ static inline int vnet_skb_map(struct ldc_channel *lp, struct sk_buff *skb, vaddr = kmap_atomic(skb_frag_page(f)); blen = skb_frag_size(f); blen += 8 - (blen & 7); - err = ldc_map_single(lp, vaddr + f->page_offset, + err = ldc_map_single(lp, vaddr + skb_frag_off(f), blen, cookies + nc, ncookies - nc, map_perm); kunmap_atomic(vaddr); @@ -1124,7 +1124,7 @@ static inline struct sk_buff *vnet_skb_shape(struct sk_buff *skb, int ncookies) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *f = &skb_shinfo(skb)->frags[i]; - docopy |= f->page_offset & 7; + docopy |= skb_frag_off(f) & 7; } if (((unsigned long)skb->data & 7) != VNET_PACKET_SKIP || skb_tailroom(skb) < pad || diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 642843945031..1b2702f74455 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1116,7 +1116,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; struct page *page = skb_frag_page(frag); - u32 page_offset = frag->page_offset; + u32 page_offset = skb_frag_off(frag); u32 buf_len = skb_frag_size(frag); dma_addr_t desc_dma; u32 desc_dma_32; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 3544e1991579..86884c863013 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -435,7 +435,7 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, skb_frag_t *frag = skb_shinfo(skb)->frags + i; slots_used += fill_pg_buf(skb_frag_page(frag), - frag->page_offset, + skb_frag_off(frag), skb_frag_size(frag), &pb[slots_used]); } return slots_used; @@ -449,7 +449,7 @@ static int count_skb_frag_slots(struct sk_buff *skb) for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; unsigned long size = skb_frag_size(frag); - unsigned long offset = frag->page_offset; + unsigned long offset = skb_frag_off(frag); /* Skip unused frames from start of page */ offset &= ~PAGE_MASK; diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c index fcf31335a8b6..dacb4f680fd4 100644 --- a/drivers/net/thunderbolt.c +++ b/drivers/net/thunderbolt.c @@ -1005,7 +1005,7 @@ static void *tbnet_kmap_frag(struct sk_buff *skb, unsigned int frag_num, const skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_num]; *len = skb_frag_size(frag); - return kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + return kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } static netdev_tx_t tbnet_start_xmit(struct sk_buff *skb, diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ace7ffaf3913..58952a79b05f 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1328,7 +1328,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) total_len += skb_frag_size(f); sg_set_page(&urb->sg[i + s], skb_frag_page(f), skb_frag_size(f), - f->page_offset); + skb_frag_off(f)); } urb->transfer_buffer_length = total_len; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 03feaeae89cd..216acf37ca7c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -662,7 +662,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd, BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); __skb_frag_set_page(frag, rbi->page); - frag->page_offset = 0; + skb_frag_off_set(frag, 0); skb_frag_size_set(frag, rcd->len); skb->data_len += rcd->len; skb->truesize += PAGE_SIZE; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index a96c5c2a2c5a..3ef07b63613e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -136,12 +136,12 @@ static inline struct xenvif_queue *ubuf_to_queue(const struct ubuf_info *ubuf) static u16 frag_get_pending_idx(skb_frag_t *frag) { - return (u16)frag->page_offset; + return (u16)skb_frag_off(frag); } static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx) { - frag->page_offset = pending_idx; + skb_frag_off_set(frag, pending_idx); } static inline pending_ring_idx_t pending_index(unsigned i) @@ -1068,7 +1068,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s offset += len; __skb_frag_set_page(&frags[i], page); - frags[i].page_offset = 0; + skb_frag_off_set(&frags[i], 0); skb_frag_size_set(&frags[i], len); } diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 8d33970a2950..b930d5f95222 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -531,7 +531,7 @@ static int xennet_count_skb_slots(struct sk_buff *skb) for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; unsigned long size = skb_frag_size(frag); - unsigned long offset = frag->page_offset; + unsigned long offset = skb_frag_off(frag); /* Skip unused frames from start of page */ offset &= ~PAGE_MASK; @@ -674,8 +674,8 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev /* Requests for all the frags. */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - tx = xennet_make_txreqs(queue, tx, skb, - skb_frag_page(frag), frag->page_offset, + tx = xennet_make_txreqs(queue, tx, skb, skb_frag_page(frag), + skb_frag_off(frag), skb_frag_size(frag)); } @@ -1040,7 +1040,7 @@ static int xennet_poll(struct napi_struct *napi, int budget) if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD) NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD; - skb_shinfo(skb)->frags[0].page_offset = rx->offset; + skb_frag_off_set(&skb_shinfo(skb)->frags[0], rx->offset); skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); skb->data_len = rx->status; skb->len += rx->status; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7796799bf04a..9ff9429395eb 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -346,7 +346,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 00dd47bcbb1e..587d4bbb7d22 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1522,8 +1522,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) - + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index d0550384cc38..a20ddc301c89 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -318,7 +318,7 @@ u32 fcoe_fc_crc(struct fc_frame *fp) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; - off = frag->page_offset; + off = skb_frag_off(frag); len = skb_frag_size(frag); while (len > 0) { clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a42babde036d..42542720962f 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -1077,7 +1077,7 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp) return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; - cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset; + cp = kmap_atomic(skb_frag_page(frag)) + skb_frag_off(frag); } else { cp = skb_put(skb, tlen); } diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index b889b04a6e25..6fa7726185de 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -284,7 +284,7 @@ static int visor_copy_fragsinfo_from_skb(struct sk_buff *skb, for (frag = 0; frag < numfrags; frag++) { count = add_physinfo_entries(page_to_pfn( skb_frag_page(&skb_shinfo(skb)->frags[frag])), - skb_shinfo(skb)->frags[frag].page_offset, + skb_frag_off(&skb_shinfo(skb)->frags[frag]), skb_frag_size(&skb_shinfo(skb)->frags[frag]), count, frags_max, frags); /* add_physinfo_entries only returns diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index c25315431ad0..fcdc4211e3c2 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -900,7 +900,7 @@ cxgbit_handle_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, sg_init_table(&ccmd->sg, 1); sg_set_page(&ccmd->sg, skb_frag_page(dfrag), - skb_frag_size(dfrag), dfrag->page_offset); + skb_frag_size(dfrag), skb_frag_off(dfrag)); get_page(skb_frag_page(dfrag)); cmd->se_cmd.t_data_sg = &ccmd->sg; @@ -1403,7 +1403,7 @@ static void cxgbit_lro_skb_dump(struct sk_buff *skb) pdu_cb->ddigest, pdu_cb->frags); for (i = 0; i < ssi->nr_frags; i++) pr_info("skb 0x%p, frag %d, off %u, sz %u.\n", - skb, i, ssi->frags[i].page_offset, + skb, i, skb_frag_off(&ssi->frags[i]), skb_frag_size(&ssi->frags[i])); } diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index a8cb6b2e20c1..4072e9d394d6 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -953,8 +953,8 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap_atomic(skb_frag_page(frag)); - sum = atalk_sum_partial(vaddr + frag->page_offset + - offset - start, copy, sum); + sum = atalk_sum_partial(vaddr + skb_frag_off(frag) + + offset - start, copy, sum); kunmap_atomic(vaddr); if (!(len -= copy)) diff --git a/net/core/datagram.c b/net/core/datagram.c index 45a162ef5e02..4cc8dc5db2b7 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -442,8 +442,8 @@ static int __skb_datagram_iter(const struct sk_buff *skb, int offset, if (copy > len) copy = len; - n = cb(vaddr + frag->page_offset + - offset - start, copy, data, to); + n = cb(vaddr + skb_frag_off(frag) + offset - start, + copy, data, to); kunmap(page); offset += n; if (n != copy) @@ -573,7 +573,7 @@ int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, if (copy > len) copy = len; copied = copy_page_from_iter(skb_frag_page(frag), - frag->page_offset + offset - start, + skb_frag_off(frag) + offset - start, copy, from); if (copied != copy) goto fault; diff --git a/net/core/dev.c b/net/core/dev.c index fc676b2610e3..e2a11c62197b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5481,7 +5481,7 @@ static void gro_pull_from_frag0(struct sk_buff *skb, int grow) skb->data_len -= grow; skb->tail += grow; - pinfo->frags[0].page_offset += grow; + skb_frag_off_add(&pinfo->frags[0], grow); skb_frag_size_sub(&pinfo->frags[0], grow); if (unlikely(!skb_frag_size(&pinfo->frags[0]))) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index bb9915291644..c5dbdc87342a 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2652,7 +2652,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, } get_page(pkt_dev->page); skb_frag_set_page(skb, i, pkt_dev->page); - skb_shinfo(skb)->frags[i].page_offset = 0; + skb_frag_off_set(&skb_shinfo(skb)->frags[i], 0); /*last fragment, fill rest of data*/ if (i == (frags - 1)) skb_frag_size_set(&skb_shinfo(skb)->frags[i], diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0b788df5a75b..ea8e8d332d85 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -785,7 +785,7 @@ void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt) struct page *p; u8 *vaddr; - skb_frag_foreach_page(frag, frag->page_offset, + skb_frag_foreach_page(frag, skb_frag_off(frag), skb_frag_size(frag), p, p_off, p_len, copied) { seg_len = min_t(int, p_len, len); @@ -1375,7 +1375,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) struct page *p; u8 *vaddr; - skb_frag_foreach_page(f, f->page_offset, skb_frag_size(f), + skb_frag_foreach_page(f, skb_frag_off(f), skb_frag_size(f), p, p_off, p_len, copied) { u32 copy, done = 0; vaddr = kmap_atomic(p); @@ -2144,10 +2144,12 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta) skb_frag_unref(skb, i); eat -= size; } else { - skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[k]; + + *frag = skb_shinfo(skb)->frags[i]; if (eat) { - skb_shinfo(skb)->frags[k].page_offset += eat; - skb_frag_size_sub(&skb_shinfo(skb)->frags[k], eat); + skb_frag_off_add(frag, eat); + skb_frag_size_sub(frag, eat); if (!i) goto end; eat = 0; @@ -2219,7 +2221,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) copy = len; skb_frag_foreach_page(f, - f->page_offset + offset - start, + skb_frag_off(f) + offset - start, copy, p, p_off, p_len, copied) { vaddr = kmap_atomic(p); memcpy(to + copied, vaddr + p_off, p_len); @@ -2395,7 +2397,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; if (__splice_segment(skb_frag_page(f), - f->page_offset, skb_frag_size(f), + skb_frag_off(f), skb_frag_size(f), offset, len, spd, false, sk, pipe)) return true; } @@ -2498,7 +2500,7 @@ int skb_send_sock_locked(struct sock *sk, struct sk_buff *skb, int offset, while (slen) { ret = kernel_sendpage_locked(sk, skb_frag_page(frag), - frag->page_offset + offset, + skb_frag_off(frag) + offset, slen, MSG_DONTWAIT); if (ret <= 0) goto error; @@ -2580,7 +2582,7 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) copy = len; skb_frag_foreach_page(frag, - frag->page_offset + offset - start, + skb_frag_off(frag) + offset - start, copy, p, p_off, p_len, copied) { vaddr = kmap_atomic(p); memcpy(vaddr + p_off, from + copied, p_len); @@ -2660,7 +2662,7 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, copy = len; skb_frag_foreach_page(frag, - frag->page_offset + offset - start, + skb_frag_off(frag) + offset - start, copy, p, p_off, p_len, copied) { vaddr = kmap_atomic(p); csum2 = INDIRECT_CALL_1(ops->update, @@ -2759,7 +2761,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, copy = len; skb_frag_foreach_page(frag, - frag->page_offset + offset - start, + skb_frag_off(frag) + offset - start, copy, p, p_off, p_len, copied) { vaddr = kmap_atomic(p); csum2 = csum_partial_copy_nocheck(vaddr + p_off, @@ -3234,7 +3236,7 @@ static inline void skb_split_no_header(struct sk_buff *skb, * 2. Split is accurately. We make this. */ skb_frag_ref(skb, i); - skb_shinfo(skb1)->frags[0].page_offset += len - pos; + skb_frag_off_add(&skb_shinfo(skb1)->frags[0], len - pos); skb_frag_size_sub(&skb_shinfo(skb1)->frags[0], len - pos); skb_frag_size_set(&skb_shinfo(skb)->frags[i], len - pos); skb_shinfo(skb)->nr_frags++; @@ -3316,7 +3318,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) */ if (!to || !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom), - fragfrom->page_offset)) { + skb_frag_off(fragfrom))) { merge = -1; } else { merge = to - 1; @@ -3333,7 +3335,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) skb_frag_size_add(fragto, shiftlen); skb_frag_size_sub(fragfrom, shiftlen); - fragfrom->page_offset += shiftlen; + skb_frag_off_add(fragfrom, shiftlen); goto onlymerged; } @@ -3364,11 +3366,11 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) } else { __skb_frag_ref(fragfrom); - fragto->bv_page = fragfrom->bv_page; - fragto->page_offset = fragfrom->page_offset; + skb_frag_page_copy(fragto, fragfrom); + skb_frag_off_copy(fragto, fragfrom); skb_frag_size_set(fragto, todo); - fragfrom->page_offset += todo; + skb_frag_off_add(fragfrom, todo); skb_frag_size_sub(fragfrom, todo); todo = 0; @@ -3493,7 +3495,7 @@ unsigned int skb_seq_read(unsigned int consumed, const u8 **data, if (!st->frag_data) st->frag_data = kmap_atomic(skb_frag_page(frag)); - *data = (u8 *) st->frag_data + frag->page_offset + + *data = (u8 *) st->frag_data + skb_frag_off(frag) + (abs_offset - st->stepped_offset); return block_limit - abs_offset; @@ -3630,8 +3632,8 @@ static inline skb_frag_t skb_head_frag_to_page_desc(struct sk_buff *frag_skb) page = virt_to_head_page(frag_skb->head); __skb_frag_set_page(&head_frag, page); - head_frag.page_offset = frag_skb->data - - (unsigned char *)page_address(page); + skb_frag_off_set(&head_frag, frag_skb->data - + (unsigned char *)page_address(page)); skb_frag_size_set(&head_frag, skb_headlen(frag_skb)); return head_frag; } @@ -3875,7 +3877,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, size = skb_frag_size(nskb_frag); if (pos < offset) { - nskb_frag->page_offset += offset - pos; + skb_frag_off_add(nskb_frag, offset - pos); skb_frag_size_sub(nskb_frag, offset - pos); } @@ -3996,7 +3998,7 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb) *--frag = *--frag2; } while (--i); - frag->page_offset += offset; + skb_frag_off_add(frag, offset); skb_frag_size_sub(frag, offset); /* all fragments truesize : remove (head size + sk_buff) */ @@ -4026,7 +4028,7 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb) pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags; __skb_frag_set_page(frag, page); - frag->page_offset = first_offset; + skb_frag_off_set(frag, first_offset); skb_frag_size_set(frag, first_size); memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags); @@ -4042,7 +4044,7 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb) if (offset > headlen) { unsigned int eat = offset - headlen; - skbinfo->frags[0].page_offset += eat; + skb_frag_off_add(&skbinfo->frags[0], eat); skb_frag_size_sub(&skbinfo->frags[0], eat); skb->data_len -= eat; skb->len -= eat; @@ -4167,7 +4169,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, if (copy > len) copy = len; sg_set_page(&sg[elt], skb_frag_page(frag), copy, - frag->page_offset+offset-start); + skb_frag_off(frag) + offset - start); elt++; if (!(len -= copy)) return elt; @@ -5838,7 +5840,7 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off, * where splitting is expensive. * 2. Split is accurately. We make this. */ - shinfo->frags[0].page_offset += off - pos; + skb_frag_off_add(&shinfo->frags[0], off - pos); skb_frag_size_sub(&shinfo->frags[0], off - pos); } skb_frag_ref(skb, i); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f62f0e7e3cdd..a0a66321c0ee 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1782,12 +1782,12 @@ static int tcp_zerocopy_receive(struct sock *sk, frags++; } } - if (skb_frag_size(frags) != PAGE_SIZE || frags->page_offset) { + if (skb_frag_size(frags) != PAGE_SIZE || skb_frag_off(frags)) { int remaining = zc->recv_skip_hint; int size = skb_frag_size(frags); while (remaining && (size != PAGE_SIZE || - frags->page_offset)) { + skb_frag_off(frags))) { remaining -= size; frags++; size = skb_frag_size(frags); @@ -3784,7 +3784,7 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, for (i = 0; i < shi->nr_frags; ++i) { const skb_frag_t *f = &shi->frags[i]; - unsigned int offset = f->page_offset; + unsigned int offset = skb_frag_off(f); struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT); sg_set_page(&sg, page, skb_frag_size(f), diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6e4afc48d7bb..e6d02e05bb1c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1402,7 +1402,7 @@ static int __pskb_trim_head(struct sk_buff *skb, int len) } else { shinfo->frags[k] = shinfo->frags[i]; if (eat) { - shinfo->frags[k].page_offset += eat; + skb_frag_off_add(&shinfo->frags[k], eat); skb_frag_size_sub(&shinfo->frags[k], eat); eat = 0; } diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index 05f63c4300e9..4ff75c3a8d6e 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -642,7 +642,7 @@ static int kcm_write_msgs(struct kcm_sock *kcm) ret = kernel_sendpage(psock->sk->sk_socket, skb_frag_page(frag), - frag->page_offset + frag_offset, + skb_frag_off(frag) + frag_offset, skb_frag_size(frag) - frag_offset, MSG_DONTWAIT); if (ret <= 0) { diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 4ec8a06fa5d1..d184230665eb 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -244,12 +244,12 @@ static void tls_append_frag(struct tls_record_info *record, frag = &record->frags[record->num_frags - 1]; if (skb_frag_page(frag) == pfrag->page && - frag->page_offset + skb_frag_size(frag) == pfrag->offset) { + skb_frag_off(frag) + skb_frag_size(frag) == pfrag->offset) { skb_frag_size_add(frag, size); } else { ++frag; __skb_frag_set_page(frag, pfrag->page); - frag->page_offset = pfrag->offset; + skb_frag_off_set(frag, pfrag->offset); skb_frag_size_set(frag, size); ++record->num_frags; get_page(pfrag->page); @@ -301,7 +301,7 @@ static int tls_push_record(struct sock *sk, frag = &record->frags[i]; sg_unmark_end(&offload_ctx->sg_tx_data[i]); sg_set_page(&offload_ctx->sg_tx_data[i], skb_frag_page(frag), - skb_frag_size(frag), frag->page_offset); + skb_frag_size(frag), skb_frag_off(frag)); sk_mem_charge(sk, skb_frag_size(frag)); get_page(skb_frag_page(frag)); } @@ -324,7 +324,7 @@ static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx, frag = &record->frags[0]; __skb_frag_set_page(frag, pfrag->page); - frag->page_offset = pfrag->offset; + skb_frag_off_set(frag, pfrag->offset); skb_frag_size_set(frag, prepend_size); get_page(pfrag->page); diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c index 9070d68a92a4..28895333701e 100644 --- a/net/tls/tls_device_fallback.c +++ b/net/tls/tls_device_fallback.c @@ -273,7 +273,7 @@ static int fill_sg_in(struct scatterlist *sg_in, __skb_frag_ref(frag); sg_set_page(sg_in + i, skb_frag_page(frag), - skb_frag_size(frag), frag->page_offset); + skb_frag_size(frag), skb_frag_off(frag)); remaining -= skb_frag_size(frag); diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index 32c364d3bfb3..4d422447aadc 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c @@ -85,7 +85,7 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) if (dlen < len) len = dlen; - frag->page_offset = 0; + skb_frag_off_set(frag, 0); skb_frag_size_set(frag, len); memcpy(skb_frag_address(frag), scratch, len); -- GitLab From 65c84f148e359ed398dcc9ed736131103f40896b Mon Sep 17 00:00:00 2001 From: Jonathan Lemon Date: Tue, 30 Jul 2019 07:40:34 -0700 Subject: [PATCH 1328/7155] linux: Remove bvec page_offset, use bv_offset Now that page_offset is referenced through accessors, remove the union, and use bv_offset. Signed-off-by: Jonathan Lemon Signed-off-by: David S. Miller --- include/linux/bvec.h | 5 +---- include/linux/skbuff.h | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 7f2b2ea9399c..a032f01e928c 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -18,10 +18,7 @@ struct bio_vec { struct page *bv_page; unsigned int bv_len; - union { - __u32 page_offset; - unsigned int bv_offset; - }; + unsigned int bv_offset; }; struct bvec_iter { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2957cdd6c032..3aef8d82ea59 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2078,7 +2078,7 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, * on page_is_pfmemalloc doing the right thing(tm). */ frag->bv_page = page; - frag->page_offset = off; + frag->bv_offset = off; skb_frag_size_set(frag, size); page = compound_head(page); @@ -2863,7 +2863,7 @@ static inline void skb_propagate_pfmemalloc(struct page *page, */ static inline unsigned int skb_frag_off(const skb_frag_t *frag) { - return frag->page_offset; + return frag->bv_offset; } /** @@ -2873,7 +2873,7 @@ static inline unsigned int skb_frag_off(const skb_frag_t *frag) */ static inline void skb_frag_off_add(skb_frag_t *frag, int delta) { - frag->page_offset += delta; + frag->bv_offset += delta; } /** @@ -2883,7 +2883,7 @@ static inline void skb_frag_off_add(skb_frag_t *frag, int delta) */ static inline void skb_frag_off_set(skb_frag_t *frag, unsigned int offset) { - frag->page_offset = offset; + frag->bv_offset = offset; } /** @@ -2894,7 +2894,7 @@ static inline void skb_frag_off_set(skb_frag_t *frag, unsigned int offset) static inline void skb_frag_off_copy(skb_frag_t *fragto, const skb_frag_t *fragfrom) { - fragto->page_offset = fragfrom->page_offset; + fragto->bv_offset = fragfrom->bv_offset; } /** -- GitLab From d1a55841ab24c6d1e4087e5c285601a9dffb8641 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:51 -0700 Subject: [PATCH 1329/7155] net: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: "David S. Miller" Cc: Kalle Valo Cc: Saeed Mahameed Cc: Jeff Kirsher Cc: Felix Fietkau Cc: Lorenzo Bianconi Cc: netdev@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: David S. Miller --- drivers/net/can/janz-ican3.c | 1 - drivers/net/can/rcar/rcar_can.c | 1 - drivers/net/can/rcar/rcar_canfd.c | 2 -- drivers/net/can/sun4i_can.c | 1 - drivers/net/ethernet/amd/au1000_eth.c | 1 - drivers/net/ethernet/amd/xgbe/xgbe-platform.c | 14 +++----------- drivers/net/ethernet/apm/xgene-v2/main.c | 4 +--- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 5 +---- drivers/net/ethernet/aurora/nb8800.c | 4 +--- drivers/net/ethernet/broadcom/bgmac-platform.c | 4 +--- drivers/net/ethernet/cortina/gemini.c | 4 +--- drivers/net/ethernet/davicom/dm9000.c | 2 -- drivers/net/ethernet/hisilicon/hisi_femac.c | 1 - drivers/net/ethernet/lantiq_xrx200.c | 10 ++-------- drivers/net/ethernet/nuvoton/w90p910_ether.c | 2 -- drivers/net/ethernet/qualcomm/emac/emac.c | 5 +---- drivers/net/ethernet/socionext/sni_ave.c | 4 +--- .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 7 +------ .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 7 +------ drivers/net/wireless/mediatek/mt76/mt7603/soc.c | 4 +--- 20 files changed, 15 insertions(+), 68 deletions(-) diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 19d4f52a8f90..a761092e6ac9 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1936,7 +1936,6 @@ static int ican3_probe(struct platform_device *pdev) /* find our IRQ number */ mod->irq = platform_get_irq(pdev, 0); if (mod->irq < 0) { - dev_err(dev, "IRQ line not found\n"); ret = -ENODEV; goto out_free_ndev; } diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 13e66297b65f..cf218949a8fb 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -759,7 +759,6 @@ static int rcar_can_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); err = irq; goto fail; } diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 05410008aa6b..51eecc7cdcdd 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1651,14 +1651,12 @@ static int rcar_canfd_probe(struct platform_device *pdev) ch_irq = platform_get_irq(pdev, 0); if (ch_irq < 0) { - dev_err(&pdev->dev, "no Channel IRQ resource\n"); err = ch_irq; goto fail_dev; } g_irq = platform_get_irq(pdev, 1); if (g_irq < 0) { - dev_err(&pdev->dev, "no Global IRQ resource\n"); err = g_irq; goto fail_dev; } diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 093fc9a529f0..f4cd88196404 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -787,7 +787,6 @@ static int sun4ican_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "could not get a valid irq\n"); err = -ENODEV; goto exit; } diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 650d1bae5f56..1793950f0582 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1100,7 +1100,6 @@ static int au1000_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to retrieve IRQ\n"); err = -ENODEV; goto out; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c index d0f3dfb88202..dce9e59e8881 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c @@ -467,10 +467,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) /* Get the device interrupt */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "platform_get_irq 0 failed\n"); + if (ret < 0) goto err_io; - } pdata->dev_irq = ret; /* Get the per channel DMA interrupts */ @@ -479,12 +477,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) { ret = platform_get_irq(pdata->platdev, dma_irqnum++); - if (ret < 0) { - netdev_err(pdata->netdev, - "platform_get_irq %u failed\n", - dma_irqnum - 1); + if (ret < 0) goto err_io; - } pdata->channel_irq[i] = ret; } @@ -496,10 +490,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) /* Get the auto-negotiation interrupt */ ret = platform_get_irq(phy_pdev, phy_irqnum++); - if (ret < 0) { - dev_err(dev, "platform_get_irq phy 0 failed\n"); + if (ret < 0) goto err_io; - } pdata->an_irq = ret; /* Configure the netdev resource */ diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c index 79048cc46703..02b4f3af02b5 100644 --- a/drivers/net/ethernet/apm/xgene-v2/main.c +++ b/drivers/net/ethernet/apm/xgene-v2/main.c @@ -54,10 +54,8 @@ static int xge_get_resources(struct xge_pdata *pdata) } ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Unable to get irq\n"); + if (ret < 0) return ret; - } pdata->resources.irq = ret; return 0; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 949bff4d2921..d8612131c55e 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1617,7 +1617,6 @@ static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata) static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) { struct platform_device *pdev = pdata->pdev; - struct device *dev = &pdev->dev; int i, ret, max_irqs; if (phy_interface_mode_is_rgmii(pdata->phy_mode)) @@ -1637,9 +1636,7 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) pdata->cq_cnt = max_irqs / 2; break; } - dev_err(dev, "Unable to get ENET IRQ\n"); - ret = ret ? : -ENXIO; - return ret; + return ret ? : -ENXIO; } pdata->irqs[i] = ret; } diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index 3b3370a94a9c..37752d9514e7 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -1351,10 +1351,8 @@ static int nb8800_probe(struct platform_device *pdev) ops = match->data; irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "No IRQ\n"); + if (irq <= 0) return -EINVAL; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c index 6dc0dd91ad11..c46c1b1416f7 100644 --- a/drivers/net/ethernet/broadcom/bgmac-platform.c +++ b/drivers/net/ethernet/broadcom/bgmac-platform.c @@ -199,10 +199,8 @@ static int bgmac_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "MAC address not present in device tree\n"); bgmac->irq = platform_get_irq(pdev, 0); - if (bgmac->irq < 0) { - dev_err(&pdev->dev, "Unable to obtain IRQ\n"); + if (bgmac->irq < 0) return bgmac->irq; - } regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base"); if (!regs) { diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 46dd6b4886b6..e736ce2c58ca 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2422,10 +2422,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) /* Interrupt */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "no IRQ\n"); + if (irq <= 0) return irq ? irq : -ENODEV; - } port->irq = irq; /* Clock the port */ diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 386bdc1378d1..cce90b5925d9 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1500,8 +1500,6 @@ dm9000_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); if (ndev->irq < 0) { - dev_err(db->dev, "interrupt resource unavailable: %d\n", - ndev->irq); ret = ndev->irq; goto out; } diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index 689f18e3100f..90ab7ade44c4 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -877,7 +877,6 @@ static int hisi_femac_drv_probe(struct platform_device *pdev) ndev->irq = platform_get_irq(pdev, 0); if (ndev->irq <= 0) { - dev_err(dev, "No irq resource\n"); ret = -ENODEV; goto out_disconnect_phy; } diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c index cda641ef89af..900affbdcc0e 100644 --- a/drivers/net/ethernet/lantiq_xrx200.c +++ b/drivers/net/ethernet/lantiq_xrx200.c @@ -458,17 +458,11 @@ static int xrx200_probe(struct platform_device *pdev) } priv->chan_rx.dma.irq = platform_get_irq_byname(pdev, "rx"); - if (priv->chan_rx.dma.irq < 0) { - dev_err(dev, "failed to get RX IRQ, %i\n", - priv->chan_rx.dma.irq); + if (priv->chan_rx.dma.irq < 0) return -ENOENT; - } priv->chan_tx.dma.irq = platform_get_irq_byname(pdev, "tx"); - if (priv->chan_tx.dma.irq < 0) { - dev_err(dev, "failed to get TX IRQ, %i\n", - priv->chan_tx.dma.irq); + if (priv->chan_tx.dma.irq < 0) return -ENOENT; - } /* get the clock */ priv->clk = devm_clk_get(dev, NULL); diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 3d73970b3a2e..219b0b863c89 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -993,14 +993,12 @@ static int w90p910_ether_probe(struct platform_device *pdev) ether->txirq = platform_get_irq(pdev, 0); if (ether->txirq < 0) { - dev_err(&pdev->dev, "failed to get ether tx irq\n"); error = -ENXIO; goto failed_free_io; } ether->rxirq = platform_get_irq(pdev, 1); if (ether->rxirq < 0) { - dev_err(&pdev->dev, "failed to get ether rx irq\n"); error = -ENXIO; goto failed_free_io; } diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 59c2349b59df..bfe10464c81f 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -556,11 +556,8 @@ static int emac_probe_resources(struct platform_device *pdev, /* Core 0 interrupt */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, - "error: missing core0 irq resource (error=%i)\n", ret); + if (ret < 0) return ret; - } adpt->irq.irq = ret; /* base register address */ diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 51a7b48db4bc..87ab0b5da91e 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1573,10 +1573,8 @@ static int ave_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "IRQ not found\n"); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 66933332c68e..f2197b066ed1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -431,13 +431,8 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) * resource initialization is done in the glue logic. */ stmmac_res.irq = platform_get_irq(pdev, 0); - if (stmmac_res.irq < 0) { - if (stmmac_res.irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "IRQ configuration information not found\n"); - + if (stmmac_res.irq < 0) return stmmac_res.irq; - } stmmac_res.wol_irq = stmmac_res.irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 7ad2bb90ceb1..0f3e6ce7f6ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -610,13 +610,8 @@ int stmmac_get_platform_resources(struct platform_device *pdev, * probe if needed before we went too far with resource allocation. */ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); - if (stmmac_res->irq < 0) { - if (stmmac_res->irq != -EPROBE_DEFER) { - dev_err(&pdev->dev, - "MAC IRQ configuration information not found\n"); - } + if (stmmac_res->irq < 0) return stmmac_res->irq; - } /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c index b920be1f5718..c6c1ce69bcbc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c @@ -17,10 +17,8 @@ mt76_wmac_probe(struct platform_device *pdev) int ret; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get device IRQ\n"); + if (irq < 0) return irq; - } mem_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mem_base)) { -- GitLab From b74494872555d1f7888dfd9225700a363f4a84fc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 20:30:49 +0200 Subject: [PATCH 1330/7155] hrtimer: Remove task argument from hrtimer_init_sleeper() All callers hand in 'current' and that's the only task pointer which actually makes sense. Remove the task argument and set current in the function. Signed-off-by: Thomas Gleixner Reviewed-by: Steven Rostedt (VMware) Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185752.791885290@linutronix.de --- block/blk-mq.c | 2 +- drivers/staging/android/vsoc.c | 2 +- include/linux/hrtimer.h | 3 +-- include/linux/wait.h | 2 +- kernel/futex.c | 2 +- kernel/time/hrtimer.c | 8 ++++---- net/core/pktgen.c | 2 +- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index b038ec680e84..5f647cb8c695 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3418,7 +3418,7 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q, hrtimer_init_on_stack(&hs.timer, CLOCK_MONOTONIC, mode); hrtimer_set_expires(&hs.timer, kt); - hrtimer_init_sleeper(&hs, current); + hrtimer_init_sleeper(&hs); do { if (blk_mq_rq_state(rq) == MQ_RQ_COMPLETE) break; diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c index 00a1ec7b9154..ce480bcf20d2 100644 --- a/drivers/staging/android/vsoc.c +++ b/drivers/staging/android/vsoc.c @@ -442,7 +442,7 @@ static int handle_vsoc_cond_wait(struct file *filp, struct vsoc_cond_wait *arg) hrtimer_set_expires_range_ns(&to->timer, wake_time, current->timer_slack_ns); - hrtimer_init_sleeper(to, current); + hrtimer_init_sleeper(to); } while (1) { diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 4971100a8cab..3c74f89367c4 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -463,8 +463,7 @@ extern long hrtimer_nanosleep(const struct timespec64 *rqtp, const enum hrtimer_mode mode, const clockid_t clockid); -extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, - struct task_struct *tsk); +extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl); extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta, const enum hrtimer_mode mode); diff --git a/include/linux/wait.h b/include/linux/wait.h index b6f77cf60dd7..d57832774ca6 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -489,7 +489,7 @@ do { \ struct hrtimer_sleeper __t; \ \ hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); \ - hrtimer_init_sleeper(&__t, current); \ + hrtimer_init_sleeper(&__t); \ if ((timeout) != KTIME_MAX) \ hrtimer_start_range_ns(&__t.timer, timeout, \ current->timer_slack_ns, \ diff --git a/kernel/futex.c b/kernel/futex.c index 6d50728ef2e7..5e9842ea4012 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -490,7 +490,7 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout, hrtimer_init_on_stack(&timeout->timer, (flags & FLAGS_CLOCKRT) ? CLOCK_REALTIME : CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - hrtimer_init_sleeper(timeout, current); + hrtimer_init_sleeper(timeout); /* * If range_ns is 0, calling hrtimer_set_expires_range_ns() is diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 5ee77f1a8a92..de895d86800c 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1639,10 +1639,10 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer) return HRTIMER_NORESTART; } -void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task) +void hrtimer_init_sleeper(struct hrtimer_sleeper *sl) { sl->timer.function = hrtimer_wakeup; - sl->task = task; + sl->task = current; } EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); @@ -1669,7 +1669,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod { struct restart_block *restart; - hrtimer_init_sleeper(t, current); + hrtimer_init_sleeper(t); do { set_current_state(TASK_INTERRUPTIBLE); @@ -1930,7 +1930,7 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, hrtimer_init_on_stack(&t.timer, clock_id, mode); hrtimer_set_expires_range_ns(&t.timer, *expires, delta); - hrtimer_init_sleeper(&t, current); + hrtimer_init_sleeper(&t); hrtimer_start_expires(&t.timer, mode); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index bb9915291644..7f3cf2381f27 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2171,7 +2171,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) } while (ktime_compare(end_time, spin_until) < 0); } else { /* see do_nanosleep */ - hrtimer_init_sleeper(&t, current); + hrtimer_init_sleeper(&t); do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS); -- GitLab From 473c7391ce731adb482c03e420964676ed8b494d Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 30 Jul 2019 17:43:30 +0200 Subject: [PATCH 1331/7155] vsock/virtio: limit the memory used per-socket Since virtio-vsock was introduced, the buffers filled by the host and pushed to the guest using the vring, are directly queued in a per-socket list. These buffers are preallocated by the guest with a fixed size (4 KB). The maximum amount of memory used by each socket should be controlled by the credit mechanism. The default credit available per-socket is 256 KB, but if we use only 1 byte per packet, the guest can queue up to 262144 of 4 KB buffers, using up to 1 GB of memory per-socket. In addition, the guest will continue to fill the vring with new 4 KB free buffers to avoid starvation of other sockets. This patch mitigates this issue copying the payload of small packets (< 128 bytes) into the buffer of last packet queued, in order to avoid wasting memory. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/vhost/vsock.c | 2 + include/linux/virtio_vsock.h | 1 + net/vmw_vsock/virtio_transport.c | 1 + net/vmw_vsock/virtio_transport_common.c | 60 +++++++++++++++++++++---- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 6a50e1d0529c..6c8390a2af52 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -329,6 +329,8 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, return NULL; } + pkt->buf_len = pkt->len; + nbytes = copy_from_iter(pkt->buf, pkt->len, &iov_iter); if (nbytes != pkt->len) { vq_err(vq, "Expected %u byte payload, got %zu bytes\n", diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index e223e2632edd..7d973903f52e 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -52,6 +52,7 @@ struct virtio_vsock_pkt { /* socket refcnt not held, only use for cancellation */ struct vsock_sock *vsk; void *buf; + u32 buf_len; u32 len; u32 off; bool reply; diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 0815d1357861..082a30936690 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -307,6 +307,7 @@ static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) break; } + pkt->buf_len = buf_len; pkt->len = buf_len; sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 6f1a8aff65c5..095221f94786 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -26,6 +26,9 @@ /* How long to wait for graceful shutdown of a connection */ #define VSOCK_CLOSE_TIMEOUT (8 * HZ) +/* Threshold for detecting small packets to copy */ +#define GOOD_COPY_LEN 128 + static const struct virtio_transport *virtio_transport_get_ops(void) { const struct vsock_transport *t = vsock_core_get_transport(); @@ -64,6 +67,9 @@ virtio_transport_alloc_pkt(struct virtio_vsock_pkt_info *info, pkt->buf = kmalloc(len, GFP_KERNEL); if (!pkt->buf) goto out_pkt; + + pkt->buf_len = len; + err = memcpy_from_msg(pkt->buf, info->msg, len); if (err) goto out; @@ -841,24 +847,60 @@ virtio_transport_recv_connecting(struct sock *sk, return err; } +static void +virtio_transport_recv_enqueue(struct vsock_sock *vsk, + struct virtio_vsock_pkt *pkt) +{ + struct virtio_vsock_sock *vvs = vsk->trans; + bool free_pkt = false; + + pkt->len = le32_to_cpu(pkt->hdr.len); + pkt->off = 0; + + spin_lock_bh(&vvs->rx_lock); + + virtio_transport_inc_rx_pkt(vvs, pkt); + + /* Try to copy small packets into the buffer of last packet queued, + * to avoid wasting memory queueing the entire buffer with a small + * payload. + */ + if (pkt->len <= GOOD_COPY_LEN && !list_empty(&vvs->rx_queue)) { + struct virtio_vsock_pkt *last_pkt; + + last_pkt = list_last_entry(&vvs->rx_queue, + struct virtio_vsock_pkt, list); + + /* If there is space in the last packet queued, we copy the + * new packet in its buffer. + */ + if (pkt->len <= last_pkt->buf_len - last_pkt->len) { + memcpy(last_pkt->buf + last_pkt->len, pkt->buf, + pkt->len); + last_pkt->len += pkt->len; + free_pkt = true; + goto out; + } + } + + list_add_tail(&pkt->list, &vvs->rx_queue); + +out: + spin_unlock_bh(&vvs->rx_lock); + if (free_pkt) + virtio_transport_free_pkt(pkt); +} + static int virtio_transport_recv_connected(struct sock *sk, struct virtio_vsock_pkt *pkt) { struct vsock_sock *vsk = vsock_sk(sk); - struct virtio_vsock_sock *vvs = vsk->trans; int err = 0; switch (le16_to_cpu(pkt->hdr.op)) { case VIRTIO_VSOCK_OP_RW: - pkt->len = le32_to_cpu(pkt->hdr.len); - pkt->off = 0; - - spin_lock_bh(&vvs->rx_lock); - virtio_transport_inc_rx_pkt(vvs, pkt); - list_add_tail(&pkt->list, &vvs->rx_queue); - spin_unlock_bh(&vvs->rx_lock); - + virtio_transport_recv_enqueue(vsk, pkt); sk->sk_data_ready(sk); return err; case VIRTIO_VSOCK_OP_CREDIT_UPDATE: -- GitLab From b89d882dc9fc279c8acbf1df71d51b22394186d5 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 30 Jul 2019 17:43:31 +0200 Subject: [PATCH 1332/7155] vsock/virtio: reduce credit update messages In order to reduce the number of credit update messages, we send them only when the space available seen by the transmitter is less than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/linux/virtio_vsock.h | 1 + net/vmw_vsock/virtio_transport_common.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 7d973903f52e..49fc9d20bc43 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -41,6 +41,7 @@ struct virtio_vsock_sock { /* Protected by rx_lock */ u32 fwd_cnt; + u32 last_fwd_cnt; u32 rx_bytes; struct list_head rx_queue; }; diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 095221f94786..a85559d4d974 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -211,6 +211,7 @@ static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { spin_lock_bh(&vvs->tx_lock); + vvs->last_fwd_cnt = vvs->fwd_cnt; pkt->hdr.fwd_cnt = cpu_to_le32(vvs->fwd_cnt); pkt->hdr.buf_alloc = cpu_to_le32(vvs->buf_alloc); spin_unlock_bh(&vvs->tx_lock); @@ -261,6 +262,7 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, struct virtio_vsock_sock *vvs = vsk->trans; struct virtio_vsock_pkt *pkt; size_t bytes, total = 0; + u32 free_space; int err = -EFAULT; spin_lock_bh(&vvs->rx_lock); @@ -291,11 +293,19 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, virtio_transport_free_pkt(pkt); } } + + free_space = vvs->buf_alloc - (vvs->fwd_cnt - vvs->last_fwd_cnt); + spin_unlock_bh(&vvs->rx_lock); - /* Send a credit pkt to peer */ - virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM, - NULL); + /* We send a credit update only when the space available seen + * by the transmitter is less than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + */ + if (free_space < VIRTIO_VSOCK_MAX_PKT_BUF_SIZE) { + virtio_transport_send_credit_update(vsk, + VIRTIO_VSOCK_TYPE_STREAM, + NULL); + } return total; -- GitLab From 9632e9f61bc4191411c47933abe5f2d93c578f5e Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 30 Jul 2019 17:43:32 +0200 Subject: [PATCH 1333/7155] vsock/virtio: fix locking in virtio_transport_inc_tx_pkt() fwd_cnt and last_fwd_cnt are protected by rx_lock, so we should use the same spinlock also if we are in the TX path. Move also buf_alloc under the same lock. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/linux/virtio_vsock.h | 2 +- net/vmw_vsock/virtio_transport_common.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 49fc9d20bc43..4c7781f4b29b 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -35,7 +35,6 @@ struct virtio_vsock_sock { /* Protected by tx_lock */ u32 tx_cnt; - u32 buf_alloc; u32 peer_fwd_cnt; u32 peer_buf_alloc; @@ -43,6 +42,7 @@ struct virtio_vsock_sock { u32 fwd_cnt; u32 last_fwd_cnt; u32 rx_bytes; + u32 buf_alloc; struct list_head rx_queue; }; diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index a85559d4d974..34a2b42313b7 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -210,11 +210,11 @@ static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { - spin_lock_bh(&vvs->tx_lock); + spin_lock_bh(&vvs->rx_lock); vvs->last_fwd_cnt = vvs->fwd_cnt; pkt->hdr.fwd_cnt = cpu_to_le32(vvs->fwd_cnt); pkt->hdr.buf_alloc = cpu_to_le32(vvs->buf_alloc); - spin_unlock_bh(&vvs->tx_lock); + spin_unlock_bh(&vvs->rx_lock); } EXPORT_SYMBOL_GPL(virtio_transport_inc_tx_pkt); -- GitLab From 6dbd3e66e7785a2f055bf84d98de9b8fd31ff3f5 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 30 Jul 2019 17:43:33 +0200 Subject: [PATCH 1334/7155] vhost/vsock: split packets to send using multiple buffers If the packets to sent to the guest are bigger than the buffer available, we can split them, using multiple buffers and fixing the length in the packet header. This is safe since virtio-vsock supports only stream sockets. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/vhost/vsock.c | 66 ++++++++++++++++++------- net/vmw_vsock/virtio_transport_common.c | 15 ++++-- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 6c8390a2af52..9f57736fe15e 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -102,7 +102,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, struct iov_iter iov_iter; unsigned out, in; size_t nbytes; - size_t len; + size_t iov_len, payload_len; int head; spin_lock_bh(&vsock->send_pkt_list_lock); @@ -147,8 +147,24 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, break; } - len = iov_length(&vq->iov[out], in); - iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len); + iov_len = iov_length(&vq->iov[out], in); + if (iov_len < sizeof(pkt->hdr)) { + virtio_transport_free_pkt(pkt); + vq_err(vq, "Buffer len [%zu] too small\n", iov_len); + break; + } + + iov_iter_init(&iov_iter, READ, &vq->iov[out], in, iov_len); + payload_len = pkt->len - pkt->off; + + /* If the packet is greater than the space available in the + * buffer, we split it using multiple buffers. + */ + if (payload_len > iov_len - sizeof(pkt->hdr)) + payload_len = iov_len - sizeof(pkt->hdr); + + /* Set the correct length in the header */ + pkt->hdr.len = cpu_to_le32(payload_len); nbytes = copy_to_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter); if (nbytes != sizeof(pkt->hdr)) { @@ -157,33 +173,47 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, break; } - nbytes = copy_to_iter(pkt->buf, pkt->len, &iov_iter); - if (nbytes != pkt->len) { + nbytes = copy_to_iter(pkt->buf + pkt->off, payload_len, + &iov_iter); + if (nbytes != payload_len) { virtio_transport_free_pkt(pkt); vq_err(vq, "Faulted on copying pkt buf\n"); break; } - vhost_add_used(vq, head, sizeof(pkt->hdr) + pkt->len); + vhost_add_used(vq, head, sizeof(pkt->hdr) + payload_len); added = true; - if (pkt->reply) { - int val; - - val = atomic_dec_return(&vsock->queued_replies); - - /* Do we have resources to resume tx processing? */ - if (val + 1 == tx_vq->num) - restart_tx = true; - } - /* Deliver to monitoring devices all correctly transmitted * packets. */ virtio_transport_deliver_tap_pkt(pkt); - total_len += pkt->len; - virtio_transport_free_pkt(pkt); + pkt->off += payload_len; + total_len += payload_len; + + /* If we didn't send all the payload we can requeue the packet + * to send it with the next available buffer. + */ + if (pkt->off < pkt->len) { + spin_lock_bh(&vsock->send_pkt_list_lock); + list_add(&pkt->list, &vsock->send_pkt_list); + spin_unlock_bh(&vsock->send_pkt_list_lock); + } else { + if (pkt->reply) { + int val; + + val = atomic_dec_return(&vsock->queued_replies); + + /* Do we have resources to resume tx + * processing? + */ + if (val + 1 == tx_vq->num) + restart_tx = true; + } + + virtio_transport_free_pkt(pkt); + } } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); if (added) vhost_signal(&vsock->dev, vq); diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 34a2b42313b7..56fab3f03d0e 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -97,8 +97,17 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) struct virtio_vsock_pkt *pkt = opaque; struct af_vsockmon_hdr *hdr; struct sk_buff *skb; + size_t payload_len; + void *payload_buf; - skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + pkt->len, + /* A packet could be split to fit the RX buffer, so we can retrieve + * the payload length from the header and the buffer pointer taking + * care of the offset in the original packet. + */ + payload_len = le32_to_cpu(pkt->hdr.len); + payload_buf = pkt->buf + pkt->off; + + skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + payload_len, GFP_ATOMIC); if (!skb) return NULL; @@ -138,8 +147,8 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) skb_put_data(skb, &pkt->hdr, sizeof(pkt->hdr)); - if (pkt->len) { - skb_put_data(skb, pkt->buf, pkt->len); + if (payload_len) { + skb_put_data(skb, payload_buf, payload_len); } return skb; -- GitLab From 0038ff357f05fee242aa4e5ec5e75f83fa1ed28c Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 30 Jul 2019 17:43:34 +0200 Subject: [PATCH 1335/7155] vsock/virtio: change the maximum packet size allowed Since now we are able to split packets, we can avoid limiting their sizes to VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE. Instead, we can use VIRTIO_VSOCK_MAX_PKT_BUF_SIZE as the max packet size. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- net/vmw_vsock/virtio_transport_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 56fab3f03d0e..94cc0fa3e848 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -181,8 +181,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, vvs = vsk->trans; /* we can send less than pkt_len bytes */ - if (pkt_len > VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE) - pkt_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; + if (pkt_len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE) + pkt_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; /* virtio_transport_get_credit might return less than pkt_len credit */ pkt_len = virtio_transport_get_credit(vvs, pkt_len); -- GitLab From 4c173472d051ac469f2dc816aa94484c730c7e61 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 29 Jul 2019 19:49:45 +0200 Subject: [PATCH 1336/7155] dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches Document Microchip KSZ87xx family switches. These include KSZ8765 - 5 port switch KSZ8794 - 4 port switch KSZ8795 - 5 port switch Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Rob Herring Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Cc: devicetree@vger.kernel.org Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/dsa/ksz.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt b/Documentation/devicetree/bindings/net/dsa/ksz.txt index 4ac21cef370e..5e8429b6f9ca 100644 --- a/Documentation/devicetree/bindings/net/dsa/ksz.txt +++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt @@ -5,6 +5,9 @@ Required properties: - compatible: For external switch chips, compatible string must be exactly one of the following: + - "microchip,ksz8765" + - "microchip,ksz8794" + - "microchip,ksz8795" - "microchip,ksz9477" - "microchip,ksz9897" - "microchip,ksz9896" -- GitLab From 016e43a26bab0126e33c9682f9d9d05eca9f0386 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 29 Jul 2019 19:49:46 +0200 Subject: [PATCH 1337/7155] net: dsa: ksz: Add KSZ8795 tag code Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler and the tag is only 1 byte, instead of 2 as is the case with KSZ9477. Signed-off-by: Tristram Ha Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Signed-off-by: David S. Miller --- include/net/dsa.h | 2 ++ net/dsa/tag_ksz.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 1e8650fa8acc..147b757ef8ea 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -41,6 +41,7 @@ struct phylink_link_state; #define DSA_TAG_PROTO_TRAILER_VALUE 11 #define DSA_TAG_PROTO_8021Q_VALUE 12 #define DSA_TAG_PROTO_SJA1105_VALUE 13 +#define DSA_TAG_PROTO_KSZ8795_VALUE 14 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, @@ -57,6 +58,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_TRAILER = DSA_TAG_PROTO_TRAILER_VALUE, DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE, DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE, + DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE, }; struct packet_type; diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c index b4872b87d4a6..73605bcbb385 100644 --- a/net/dsa/tag_ksz.c +++ b/net/dsa/tag_ksz.c @@ -69,6 +69,67 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, return skb; } +/* + * For Ingress (Host -> KSZ8795), 1 byte is added before FCS. + * --------------------------------------------------------------------------- + * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag(1byte)|FCS(4bytes) + * --------------------------------------------------------------------------- + * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) + * + * For Egress (KSZ8795 -> Host), 1 byte is added before FCS. + * --------------------------------------------------------------------------- + * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes) + * --------------------------------------------------------------------------- + * tag0 : zero-based value represents port + * (eg, 0x00=port1, 0x02=port3, 0x06=port7) + */ + +#define KSZ8795_INGRESS_TAG_LEN 1 + +#define KSZ8795_TAIL_TAG_OVERRIDE BIT(6) +#define KSZ8795_TAIL_TAG_LOOKUP BIT(7) + +static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct sk_buff *nskb; + u8 *tag; + u8 *addr; + + nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN); + if (!nskb) + return NULL; + + /* Tag encoding */ + tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN); + addr = skb_mac_header(nskb); + + *tag = 1 << dp->index; + if (is_link_local_ether_addr(addr)) + *tag |= KSZ8795_TAIL_TAG_OVERRIDE; + + return nskb; +} + +static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) +{ + u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; + + return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN); +} + +static const struct dsa_device_ops ksz8795_netdev_ops = { + .name = "ksz8795", + .proto = DSA_TAG_PROTO_KSZ8795, + .xmit = ksz8795_xmit, + .rcv = ksz8795_rcv, + .overhead = KSZ8795_INGRESS_TAG_LEN, +}; + +DSA_TAG_DRIVER(ksz8795_netdev_ops); +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795); + /* * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS. * --------------------------------------------------------------------------- @@ -183,6 +244,7 @@ DSA_TAG_DRIVER(ksz9893_netdev_ops); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893); static struct dsa_tag_driver *dsa_tag_driver_array[] = { + &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops), &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops), &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops), }; -- GitLab From e66f840c08a237acfbb981592047b53e7411012f Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 29 Jul 2019 19:49:47 +0200 Subject: [PATCH 1338/7155] net: dsa: ksz: Add Microchip KSZ8795 DSA driver Add Microchip KSZ8795 DSA driver. Signed-off-by: Tristram Ha Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/Kconfig | 17 + drivers/net/dsa/microchip/Makefile | 2 + drivers/net/dsa/microchip/ksz8795.c | 1311 +++++++++++++++++++++++ drivers/net/dsa/microchip/ksz8795_reg.h | 1004 +++++++++++++++++ drivers/net/dsa/microchip/ksz8795_spi.c | 104 ++ drivers/net/dsa/microchip/ksz_common.c | 3 +- drivers/net/dsa/microchip/ksz_common.h | 28 + drivers/net/dsa/microchip/ksz_priv.h | 1 + 8 files changed, 2469 insertions(+), 1 deletion(-) create mode 100644 drivers/net/dsa/microchip/ksz8795.c create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig index fe0a13b79c4b..5e4f74286ea3 100644 --- a/drivers/net/dsa/microchip/Kconfig +++ b/drivers/net/dsa/microchip/Kconfig @@ -16,3 +16,20 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI select REGMAP_SPI help Select to enable support for registering switches configured through SPI. + +menuconfig NET_DSA_MICROCHIP_KSZ8795 + tristate "Microchip KSZ8795 series switch support" + depends on NET_DSA + select NET_DSA_MICROCHIP_KSZ_COMMON + help + This driver adds support for Microchip KSZ8795 switch chips. + +config NET_DSA_MICROCHIP_KSZ8795_SPI + tristate "KSZ8795 series SPI connected switch driver" + depends on NET_DSA_MICROCHIP_KSZ8795 && SPI + select REGMAP_SPI + help + This driver accesses KSZ8795 chip through SPI. + + It is required to use the KSZ8795 switch driver as the only access + is through SPI. diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile index 68451b02f775..e3d799b95d7d 100644 --- a/drivers/net/dsa/microchip/Makefile +++ b/drivers/net/dsa/microchip/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477) += ksz9477.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI) += ksz9477_spi.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795) += ksz8795.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI) += ksz8795_spi.o diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c new file mode 100644 index 000000000000..ae80b3c6dea2 --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -0,0 +1,1311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip KSZ8795 switch driver + * + * Copyright (C) 2017 Microchip Technology Inc. + * Tristram Ha + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ksz_priv.h" +#include "ksz_common.h" +#include "ksz8795_reg.h" + +static const struct { + char string[ETH_GSTRING_LEN]; +} mib_names[TOTAL_SWITCH_COUNTER_NUM] = { + { "rx_hi" }, + { "rx_undersize" }, + { "rx_fragments" }, + { "rx_oversize" }, + { "rx_jabbers" }, + { "rx_symbol_err" }, + { "rx_crc_err" }, + { "rx_align_err" }, + { "rx_mac_ctrl" }, + { "rx_pause" }, + { "rx_bcast" }, + { "rx_mcast" }, + { "rx_ucast" }, + { "rx_64_or_less" }, + { "rx_65_127" }, + { "rx_128_255" }, + { "rx_256_511" }, + { "rx_512_1023" }, + { "rx_1024_1522" }, + { "rx_1523_2000" }, + { "rx_2001" }, + { "tx_hi" }, + { "tx_late_col" }, + { "tx_pause" }, + { "tx_bcast" }, + { "tx_mcast" }, + { "tx_ucast" }, + { "tx_deferred" }, + { "tx_total_col" }, + { "tx_exc_col" }, + { "tx_single_col" }, + { "tx_mult_col" }, + { "rx_total" }, + { "tx_total" }, + { "rx_discards" }, + { "tx_discards" }, +}; + +static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) +{ + regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); +} + +static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, + bool set) +{ + regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + bits, set ? bits : 0); +} + +static int ksz8795_reset_switch(struct ksz_device *dev) +{ + /* reset switch */ + ksz_write8(dev, REG_POWER_MANAGEMENT_1, + SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); + ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0); + + return 0; +} + +static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) +{ + u8 hi, lo; + + /* Number of queues can only be 1, 2, or 4. */ + switch (queue) { + case 4: + case 3: + queue = PORT_QUEUE_SPLIT_4; + break; + case 2: + queue = PORT_QUEUE_SPLIT_2; + break; + default: + queue = PORT_QUEUE_SPLIT_1; + } + ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo); + ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi); + lo &= ~PORT_QUEUE_SPLIT_L; + if (queue & PORT_QUEUE_SPLIT_2) + lo |= PORT_QUEUE_SPLIT_L; + hi &= ~PORT_QUEUE_SPLIT_H; + if (queue & PORT_QUEUE_SPLIT_4) + hi |= PORT_QUEUE_SPLIT_H; + ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo); + ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi); + + /* Default is port based for egress rate limit. */ + if (queue != PORT_QUEUE_SPLIT_1) + ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED, + true); +} + +static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, + u64 *cnt) +{ + u16 ctrl_addr; + u32 data; + u8 check; + int loop; + + ctrl_addr = addr + SWITCH_COUNTER_NUM * port; + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + /* It is almost guaranteed to always read the valid bit because of + * slow SPI speed. + */ + for (loop = 2; loop > 0; loop--) { + ksz_read8(dev, REG_IND_MIB_CHECK, &check); + + if (check & MIB_COUNTER_VALID) { + ksz_read32(dev, REG_IND_DATA_LO, &data); + if (check & MIB_COUNTER_OVERFLOW) + *cnt += MIB_COUNTER_VALUE + 1; + *cnt += data & MIB_COUNTER_VALUE; + break; + } + } + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) +{ + u16 ctrl_addr; + u32 data; + u8 check; + int loop; + + addr -= SWITCH_COUNTER_NUM; + ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port; + ctrl_addr += addr + KS_MIB_TOTAL_RX_0; + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + /* It is almost guaranteed to always read the valid bit because of + * slow SPI speed. + */ + for (loop = 2; loop > 0; loop--) { + ksz_read8(dev, REG_IND_MIB_CHECK, &check); + + if (check & MIB_COUNTER_VALID) { + ksz_read32(dev, REG_IND_DATA_LO, &data); + if (addr < 2) { + u64 total; + + total = check & MIB_TOTAL_BYTES_H; + total <<= 32; + *cnt += total; + *cnt += data; + if (check & MIB_COUNTER_OVERFLOW) { + total = MIB_TOTAL_BYTES_H + 1; + total <<= 32; + *cnt += total; + } + } else { + if (check & MIB_COUNTER_OVERFLOW) + *cnt += MIB_PACKET_DROPPED + 1; + *cnt += data & MIB_PACKET_DROPPED; + } + break; + } + } + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze) +{ + /* enable the port for flush/freeze function */ + if (freeze) + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FREEZE, freeze); + + /* disable the port after freeze is done */ + if (!freeze) + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); +} + +static void ksz8795_port_init_cnt(struct ksz_device *dev, int port) +{ + struct ksz_port_mib *mib = &dev->ports[port].mib; + + /* flush all enabled port MIB counters */ + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); + + mib->cnt_ptr = 0; + + /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->reg_mib_cnt) { + dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, + &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + + /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->mib_cnt) { + dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, + NULL, &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + mib->cnt_ptr = 0; + memset(mib->counters, 0, dev->mib_cnt * sizeof(u64)); +} + +static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr, + u64 *data) +{ + u16 ctrl_addr; + + ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_read64(dev, REG_IND_DATA_HI, data); + mutex_unlock(&dev->alu_mutex); +} + +static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr, + u64 data) +{ + u16 ctrl_addr; + + ctrl_addr = IND_ACC_TABLE(table) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write64(dev, REG_IND_DATA_HI, data); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + mutex_unlock(&dev->alu_mutex); +} + +static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data) +{ + int timeout = 100; + + do { + ksz_read8(dev, REG_IND_DATA_CHECK, data); + timeout--; + } while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout); + + /* Entry is not ready for accessing. */ + if (*data & DYNAMIC_MAC_TABLE_NOT_READY) { + return -EAGAIN; + /* Entry is ready for accessing. */ + } else { + ksz_read8(dev, REG_IND_DATA_8, data); + + /* There is no valid entry in the table. */ + if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY) + return -ENXIO; + } + return 0; +} + +static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, + u8 *mac_addr, u8 *fid, u8 *src_port, + u8 *timestamp, u16 *entries) +{ + u32 data_hi, data_lo; + u16 ctrl_addr; + u8 data; + int rc; + + ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr; + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + + rc = ksz8795_valid_dyn_entry(dev, &data); + if (rc == -EAGAIN) { + if (addr == 0) + *entries = 0; + } else if (rc == -ENXIO) { + *entries = 0; + /* At least one valid entry in the table. */ + } else { + u64 buf = 0; + int cnt; + + ksz_read64(dev, REG_IND_DATA_HI, &buf); + data_hi = (u32)(buf >> 32); + data_lo = (u32)buf; + + /* Check out how many valid entry in the table. */ + cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H; + cnt <<= DYNAMIC_MAC_ENTRIES_H_S; + cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >> + DYNAMIC_MAC_ENTRIES_S; + *entries = cnt + 1; + + *fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >> + DYNAMIC_MAC_FID_S; + *src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >> + DYNAMIC_MAC_SRC_PORT_S; + *timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >> + DYNAMIC_MAC_TIMESTAMP_S; + + mac_addr[5] = (u8)data_lo; + mac_addr[4] = (u8)(data_lo >> 8); + mac_addr[3] = (u8)(data_lo >> 16); + mac_addr[2] = (u8)(data_lo >> 24); + + mac_addr[1] = (u8)data_hi; + mac_addr[0] = (u8)(data_hi >> 8); + rc = 0; + } + mutex_unlock(&dev->alu_mutex); + + return rc; +} + +static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) +{ + u32 data_hi, data_lo; + u64 data; + + ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data); + data_hi = data >> 32; + data_lo = (u32)data; + if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) { + alu->mac[5] = (u8)data_lo; + alu->mac[4] = (u8)(data_lo >> 8); + alu->mac[3] = (u8)(data_lo >> 16); + alu->mac[2] = (u8)(data_lo >> 24); + alu->mac[1] = (u8)data_hi; + alu->mac[0] = (u8)(data_hi >> 8); + alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >> + STATIC_MAC_FWD_PORTS_S; + alu->is_override = + (data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0; + data_hi >>= 1; + alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0; + alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >> + STATIC_MAC_FID_S; + return 0; + } + return -ENXIO; +} + +static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) +{ + u32 data_hi, data_lo; + u64 data; + + data_lo = ((u32)alu->mac[2] << 24) | + ((u32)alu->mac[3] << 16) | + ((u32)alu->mac[4] << 8) | alu->mac[5]; + data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1]; + data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S; + + if (alu->is_override) + data_hi |= STATIC_MAC_TABLE_OVERRIDE; + if (alu->is_use_fid) { + data_hi |= STATIC_MAC_TABLE_USE_FID; + data_hi |= (u32)alu->fid << STATIC_MAC_FID_S; + } + if (alu->is_static) + data_hi |= STATIC_MAC_TABLE_VALID; + else + data_hi &= ~STATIC_MAC_TABLE_OVERRIDE; + + data = (u64)data_hi << 32 | data_lo; + ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data); +} + +static void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) +{ + *fid = vlan & VLAN_TABLE_FID; + *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S; + *valid = !!(vlan & VLAN_TABLE_VALID); +} + +static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) +{ + *vlan = fid; + *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S; + if (valid) + *vlan |= VLAN_TABLE_VALID; +} + +static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr) +{ + u64 data; + int i; + + ksz8795_r_table(dev, TABLE_VLAN, addr, &data); + addr *= 4; + for (i = 0; i < 4; i++) { + dev->vlan_cache[addr + i].table[0] = (u16)data; + data >>= VLAN_TABLE_S; + } +} + +static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) +{ + int index; + u16 *data; + u16 addr; + u64 buf; + + data = (u16 *)&buf; + addr = vid / 4; + index = vid & 3; + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + *vlan = data[index]; +} + +static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) +{ + int index; + u16 *data; + u16 addr; + u64 buf; + + data = (u16 *)&buf; + addr = vid / 4; + index = vid & 3; + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + data[index] = vlan; + dev->vlan_cache[vid].table[0] = vlan; + ksz8795_w_table(dev, TABLE_VLAN, addr, buf); +} + +static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) +{ + u8 restart, speed, ctrl, link; + int processed = true; + u16 data = 0; + u8 p = phy; + + switch (reg) { + case PHY_REG_CTRL: + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); + ksz_pread8(dev, p, P_SPEED_STATUS, &speed); + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + if (restart & PORT_PHY_LOOPBACK) + data |= PHY_LOOPBACK; + if (ctrl & PORT_FORCE_100_MBIT) + data |= PHY_SPEED_100MBIT; + if (!(ctrl & PORT_AUTO_NEG_DISABLE)) + data |= PHY_AUTO_NEG_ENABLE; + if (restart & PORT_POWER_DOWN) + data |= PHY_POWER_DOWN; + if (restart & PORT_AUTO_NEG_RESTART) + data |= PHY_AUTO_NEG_RESTART; + if (ctrl & PORT_FORCE_FULL_DUPLEX) + data |= PHY_FULL_DUPLEX; + if (speed & PORT_HP_MDIX) + data |= PHY_HP_MDIX; + if (restart & PORT_FORCE_MDIX) + data |= PHY_FORCE_MDIX; + if (restart & PORT_AUTO_MDIX_DISABLE) + data |= PHY_AUTO_MDIX_DISABLE; + if (restart & PORT_TX_DISABLE) + data |= PHY_TRANSMIT_DISABLE; + if (restart & PORT_LED_OFF) + data |= PHY_LED_DISABLE; + break; + case PHY_REG_STATUS: + ksz_pread8(dev, p, P_LINK_STATUS, &link); + data = PHY_100BTX_FD_CAPABLE | + PHY_100BTX_CAPABLE | + PHY_10BT_FD_CAPABLE | + PHY_10BT_CAPABLE | + PHY_AUTO_NEG_CAPABLE; + if (link & PORT_AUTO_NEG_COMPLETE) + data |= PHY_AUTO_NEG_ACKNOWLEDGE; + if (link & PORT_STAT_LINK_GOOD) + data |= PHY_LINK_STATUS; + break; + case PHY_REG_ID_1: + data = KSZ8795_ID_HI; + break; + case PHY_REG_ID_2: + data = KSZ8795_ID_LO; + break; + case PHY_REG_AUTO_NEGOTIATION: + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + data = PHY_AUTO_NEG_802_3; + if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) + data |= PHY_AUTO_NEG_SYM_PAUSE; + if (ctrl & PORT_AUTO_NEG_100BTX_FD) + data |= PHY_AUTO_NEG_100BTX_FD; + if (ctrl & PORT_AUTO_NEG_100BTX) + data |= PHY_AUTO_NEG_100BTX; + if (ctrl & PORT_AUTO_NEG_10BT_FD) + data |= PHY_AUTO_NEG_10BT_FD; + if (ctrl & PORT_AUTO_NEG_10BT) + data |= PHY_AUTO_NEG_10BT; + break; + case PHY_REG_REMOTE_CAPABILITY: + ksz_pread8(dev, p, P_REMOTE_STATUS, &link); + data = PHY_AUTO_NEG_802_3; + if (link & PORT_REMOTE_SYM_PAUSE) + data |= PHY_AUTO_NEG_SYM_PAUSE; + if (link & PORT_REMOTE_100BTX_FD) + data |= PHY_AUTO_NEG_100BTX_FD; + if (link & PORT_REMOTE_100BTX) + data |= PHY_AUTO_NEG_100BTX; + if (link & PORT_REMOTE_10BT_FD) + data |= PHY_AUTO_NEG_10BT_FD; + if (link & PORT_REMOTE_10BT) + data |= PHY_AUTO_NEG_10BT; + if (data & ~PHY_AUTO_NEG_802_3) + data |= PHY_REMOTE_ACKNOWLEDGE_NOT; + break; + default: + processed = false; + break; + } + if (processed) + *val = data; +} + +static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) +{ + u8 p = phy; + u8 restart, speed, ctrl, data; + + switch (reg) { + case PHY_REG_CTRL: + + /* Do not support PHY reset function. */ + if (val & PHY_RESET) + break; + ksz_pread8(dev, p, P_SPEED_STATUS, &speed); + data = speed; + if (val & PHY_HP_MDIX) + data |= PORT_HP_MDIX; + else + data &= ~PORT_HP_MDIX; + if (data != speed) + ksz_pwrite8(dev, p, P_SPEED_STATUS, data); + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + data = ctrl; + if (!(val & PHY_AUTO_NEG_ENABLE)) + data |= PORT_AUTO_NEG_DISABLE; + else + data &= ~PORT_AUTO_NEG_DISABLE; + + /* Fiber port does not support auto-negotiation. */ + if (dev->ports[p].fiber) + data |= PORT_AUTO_NEG_DISABLE; + if (val & PHY_SPEED_100MBIT) + data |= PORT_FORCE_100_MBIT; + else + data &= ~PORT_FORCE_100_MBIT; + if (val & PHY_FULL_DUPLEX) + data |= PORT_FORCE_FULL_DUPLEX; + else + data &= ~PORT_FORCE_FULL_DUPLEX; + if (data != ctrl) + ksz_pwrite8(dev, p, P_FORCE_CTRL, data); + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); + data = restart; + if (val & PHY_LED_DISABLE) + data |= PORT_LED_OFF; + else + data &= ~PORT_LED_OFF; + if (val & PHY_TRANSMIT_DISABLE) + data |= PORT_TX_DISABLE; + else + data &= ~PORT_TX_DISABLE; + if (val & PHY_AUTO_NEG_RESTART) + data |= PORT_AUTO_NEG_RESTART; + else + data &= ~(PORT_AUTO_NEG_RESTART); + if (val & PHY_POWER_DOWN) + data |= PORT_POWER_DOWN; + else + data &= ~PORT_POWER_DOWN; + if (val & PHY_AUTO_MDIX_DISABLE) + data |= PORT_AUTO_MDIX_DISABLE; + else + data &= ~PORT_AUTO_MDIX_DISABLE; + if (val & PHY_FORCE_MDIX) + data |= PORT_FORCE_MDIX; + else + data &= ~PORT_FORCE_MDIX; + if (val & PHY_LOOPBACK) + data |= PORT_PHY_LOOPBACK; + else + data &= ~PORT_PHY_LOOPBACK; + if (data != restart) + ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data); + break; + case PHY_REG_AUTO_NEGOTIATION: + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + data = ctrl; + data &= ~(PORT_AUTO_NEG_SYM_PAUSE | + PORT_AUTO_NEG_100BTX_FD | + PORT_AUTO_NEG_100BTX | + PORT_AUTO_NEG_10BT_FD | + PORT_AUTO_NEG_10BT); + if (val & PHY_AUTO_NEG_SYM_PAUSE) + data |= PORT_AUTO_NEG_SYM_PAUSE; + if (val & PHY_AUTO_NEG_100BTX_FD) + data |= PORT_AUTO_NEG_100BTX_FD; + if (val & PHY_AUTO_NEG_100BTX) + data |= PORT_AUTO_NEG_100BTX; + if (val & PHY_AUTO_NEG_10BT_FD) + data |= PORT_AUTO_NEG_10BT_FD; + if (val & PHY_AUTO_NEG_10BT) + data |= PORT_AUTO_NEG_10BT; + if (data != ctrl) + ksz_pwrite8(dev, p, P_LOCAL_CTRL, data); + break; + default: + break; + } +} + +static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds, + int port) +{ + return DSA_TAG_PROTO_KSZ8795; +} + +static void ksz8795_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *buf) +{ + int i; + + for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) { + memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string, + ETH_GSTRING_LEN); + } +} + +static void ksz8795_cfg_port_member(struct ksz_device *dev, int port, + u8 member) +{ + u8 data; + + ksz_pread8(dev, port, P_MIRROR_CTRL, &data); + data &= ~PORT_VLAN_MEMBERSHIP; + data |= (member & dev->port_mask); + ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); + dev->ports[port].member = member; +} + +static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, + u8 state) +{ + struct ksz_device *dev = ds->priv; + int forward = dev->member; + struct ksz_port *p; + int member = -1; + u8 data; + + p = &dev->ports[port]; + + ksz_pread8(dev, port, P_STP_CTRL, &data); + data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); + + switch (state) { + case BR_STATE_DISABLED: + data |= PORT_LEARN_DISABLE; + if (port < SWITCH_PORT_NUM) + member = 0; + break; + case BR_STATE_LISTENING: + data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); + if (port < SWITCH_PORT_NUM && + p->stp_state == BR_STATE_DISABLED) + member = dev->host_mask | p->vid_member; + break; + case BR_STATE_LEARNING: + data |= PORT_RX_ENABLE; + break; + case BR_STATE_FORWARDING: + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); + + /* This function is also used internally. */ + if (port == dev->cpu_port) + break; + + /* Port is a member of a bridge. */ + if (dev->br_member & BIT(port)) { + dev->member |= BIT(port); + member = dev->member; + } else { + member = dev->host_mask | p->vid_member; + } + break; + case BR_STATE_BLOCKING: + data |= PORT_LEARN_DISABLE; + if (port < SWITCH_PORT_NUM && + p->stp_state == BR_STATE_DISABLED) + member = dev->host_mask | p->vid_member; + break; + default: + dev_err(ds->dev, "invalid STP state: %d\n", state); + return; + } + + ksz_pwrite8(dev, port, P_STP_CTRL, data); + p->stp_state = state; + if (data & PORT_RX_ENABLE) + dev->rx_ports |= BIT(port); + else + dev->rx_ports &= ~BIT(port); + if (data & PORT_TX_ENABLE) + dev->tx_ports |= BIT(port); + else + dev->tx_ports &= ~BIT(port); + + /* Port membership may share register with STP state. */ + if (member >= 0 && member != p->member) + ksz8795_cfg_port_member(dev, port, (u8)member); + + /* Check if forwarding needs to be updated. */ + if (state != BR_STATE_FORWARDING) { + if (dev->br_member & BIT(port)) + dev->member &= ~BIT(port); + } + + /* When topology has changed the function ksz_update_port_member + * should be called to modify port forwarding behavior. + */ + if (forward != dev->member) + ksz_update_port_member(dev, port); +} + +static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port) +{ + u8 learn[TOTAL_PORT_NUM]; + int first, index, cnt; + struct ksz_port *p; + + if ((uint)port < TOTAL_PORT_NUM) { + first = port; + cnt = port + 1; + } else { + /* Flush all ports. */ + first = 0; + cnt = dev->mib_port_cnt; + } + for (index = first; index < cnt; index++) { + p = &dev->ports[index]; + if (!p->on) + continue; + ksz_pread8(dev, index, P_STP_CTRL, &learn[index]); + if (!(learn[index] & PORT_LEARN_DISABLE)) + ksz_pwrite8(dev, index, P_STP_CTRL, + learn[index] | PORT_LEARN_DISABLE); + } + ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); + for (index = first; index < cnt; index++) { + p = &dev->ports[index]; + if (!p->on) + continue; + if (!(learn[index] & PORT_LEARN_DISABLE)) + ksz_pwrite8(dev, index, P_STP_CTRL, learn[index]); + } +} + +static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, + bool flag) +{ + struct ksz_device *dev = ds->priv; + + ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag); + + return 0; +} + +static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + struct ksz_device *dev = ds->priv; + u16 data, vid, new_pvid = 0; + u8 fid, member, valid; + + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + ksz8795_r_vlan_table(dev, vid, &data); + ksz8795_from_vlan(data, &fid, &member, &valid); + + /* First time to setup the VLAN entry. */ + if (!valid) { + /* Need to find a way to map VID to FID. */ + fid = 1; + valid = 1; + } + member |= BIT(port); + + ksz8795_to_vlan(fid, member, valid, &data); + ksz8795_w_vlan_table(dev, vid, data); + + /* change PVID */ + if (vlan->flags & BRIDGE_VLAN_INFO_PVID) + new_pvid = vid; + } + + if (new_pvid) { + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid); + vid &= 0xfff; + vid |= new_pvid; + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid); + } +} + +static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + struct ksz_device *dev = ds->priv; + u16 data, vid, pvid, new_pvid = 0; + u8 fid, member, valid; + + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); + pvid = pvid & 0xFFF; + + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + ksz8795_r_vlan_table(dev, vid, &data); + ksz8795_from_vlan(data, &fid, &member, &valid); + + member &= ~BIT(port); + + /* Invalidate the entry if no more member. */ + if (!member) { + fid = 0; + valid = 0; + } + + if (pvid == vid) + new_pvid = 1; + + ksz8795_to_vlan(fid, member, valid, &data); + ksz8795_w_vlan_table(dev, vid, data); + } + + if (new_pvid != pvid) + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid); + + return 0; +} + +static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + struct ksz_device *dev = ds->priv; + + if (ingress) { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); + dev->mirror_rx |= BIT(port); + } else { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); + dev->mirror_tx |= BIT(port); + } + + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); + + /* configure mirror port */ + if (dev->mirror_rx || dev->mirror_tx) + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + PORT_MIRROR_SNIFFER, true); + + return 0; +} + +static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + struct ksz_device *dev = ds->priv; + u8 data; + + if (mirror->ingress) { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); + dev->mirror_rx &= ~BIT(port); + } else { + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); + dev->mirror_tx &= ~BIT(port); + } + + ksz_pread8(dev, port, P_MIRROR_CTRL, &data); + + if (!dev->mirror_rx && !dev->mirror_tx) + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + PORT_MIRROR_SNIFFER, false); +} + +static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port) +{ + struct ksz_port *p = &dev->ports[port]; + u8 data8, member; + + /* enable broadcast storm limit */ + ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); + + ksz8795_set_prio_queue(dev, port, 4); + + /* disable DiffServ priority */ + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false); + + /* replace priority */ + ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false); + + /* enable 802.1p priority */ + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); + + if (cpu_port) { + /* Configure MII interface for proper network communication. */ + ksz_read8(dev, REG_PORT_5_CTRL_6, &data8); + data8 &= ~PORT_INTERFACE_TYPE; + data8 &= ~PORT_GMII_1GPS_MODE; + switch (dev->interface) { + case PHY_INTERFACE_MODE_MII: + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_RMII: + data8 |= PORT_INTERFACE_RMII; + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_GMII: + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_GMII; + p->phydev.speed = SPEED_1000; + break; + default: + data8 &= ~PORT_RGMII_ID_IN_ENABLE; + data8 &= ~PORT_RGMII_ID_OUT_ENABLE; + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || + dev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + data8 |= PORT_RGMII_ID_IN_ENABLE; + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || + dev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + data8 |= PORT_RGMII_ID_OUT_ENABLE; + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_RGMII; + p->phydev.speed = SPEED_1000; + break; + } + ksz_write8(dev, REG_PORT_5_CTRL_6, data8); + p->phydev.duplex = 1; + + member = dev->port_mask; + dev->on_ports = dev->host_mask; + dev->live_ports = dev->host_mask; + } else { + member = dev->host_mask | p->vid_member; + dev->on_ports |= BIT(port); + + /* Link was detected before port is enabled. */ + if (p->phydev.link) + dev->live_ports |= BIT(port); + } + ksz8795_cfg_port_member(dev, port, member); +} + +static void ksz8795_config_cpu_port(struct dsa_switch *ds) +{ + struct ksz_device *dev = ds->priv; + struct ksz_port *p; + u8 remote; + int i; + + ds->num_ports = dev->port_cnt + 1; + + /* Switch marks the maximum frame with extra byte as oversize. */ + ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true); + ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true); + + p = &dev->ports[dev->cpu_port]; + p->vid_member = dev->port_mask; + p->on = 1; + + ksz8795_port_setup(dev, dev->cpu_port, true); + dev->member = dev->host_mask; + + for (i = 0; i < SWITCH_PORT_NUM; i++) { + p = &dev->ports[i]; + + /* Initialize to non-zero so that ksz_cfg_port_member() will + * be called. + */ + p->vid_member = BIT(i); + p->member = dev->port_mask; + ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED); + + /* Last port may be disabled. */ + if (i == dev->port_cnt) + break; + p->on = 1; + p->phy = 1; + } + for (i = 0; i < dev->phy_port_cnt; i++) { + p = &dev->ports[i]; + if (!p->on) + continue; + ksz_pread8(dev, i, P_REMOTE_STATUS, &remote); + if (remote & PORT_FIBER_MODE) + p->fiber = 1; + if (p->fiber) + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, + true); + else + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, + false); + } +} + +static int ksz8795_setup(struct dsa_switch *ds) +{ + struct ksz_device *dev = ds->priv; + struct alu_struct alu; + int i, ret = 0; + + dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), + dev->num_vlans, GFP_KERNEL); + if (!dev->vlan_cache) + return -ENOMEM; + + ret = ksz8795_reset_switch(dev); + if (ret) { + dev_err(ds->dev, "failed to reset switch\n"); + return ret; + } + + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true); + + /* Enable automatic fast aging when link changed detected. */ + ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true); + + /* Enable aggressive back off algorithm in half duplex mode. */ + regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1, + SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); + + /* + * Make sure unicast VLAN boundary is set as default and + * enable no excessive collision drop. + */ + regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2, + UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, + UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); + + ksz8795_config_cpu_port(ds); + + ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true); + + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_REPLACE_VID, false); + + ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); + + /* set broadcast storm protection 10% rate */ + regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL, + BROADCAST_STORM_RATE, + (BROADCAST_STORM_VALUE * + BROADCAST_STORM_PROT_RATE) / 100); + + for (i = 0; i < VLAN_TABLE_ENTRIES; i++) + ksz8795_r_vlan_entries(dev, i); + + /* Setup STP address for STP operation. */ + memset(&alu, 0, sizeof(alu)); + ether_addr_copy(alu.mac, eth_stp_addr); + alu.is_static = true; + alu.is_override = true; + alu.port_forward = dev->host_mask; + + ksz8795_w_sta_mac_table(dev, 0, &alu); + + ksz_init_mib_timer(dev); + + return 0; +} + +static const struct dsa_switch_ops ksz8795_switch_ops = { + .get_tag_protocol = ksz8795_get_tag_protocol, + .setup = ksz8795_setup, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .adjust_link = ksz_adjust_link, + .port_enable = ksz_enable_port, + .port_disable = ksz_disable_port, + .get_strings = ksz8795_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_stp_state_set = ksz8795_port_stp_state_set, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz8795_port_vlan_filtering, + .port_vlan_prepare = ksz_port_vlan_prepare, + .port_vlan_add = ksz8795_port_vlan_add, + .port_vlan_del = ksz8795_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_mdb_prepare = ksz_port_mdb_prepare, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz8795_port_mirror_add, + .port_mirror_del = ksz8795_port_mirror_del, +}; + +static u32 ksz8795_get_port_addr(int port, int offset) +{ + return PORT_CTRL_ADDR(port, offset); +} + +static int ksz8795_switch_detect(struct ksz_device *dev) +{ + u8 id1, id2; + u16 id16; + int ret; + + /* read chip id */ + ret = ksz_read16(dev, REG_CHIP_ID0, &id16); + if (ret) + return ret; + + id1 = id16 >> 8; + id2 = id16 & SW_CHIP_ID_M; + if (id1 != FAMILY_ID || + (id2 != CHIP_ID_94 && id2 != CHIP_ID_95)) + return -ENODEV; + + dev->mib_port_cnt = TOTAL_PORT_NUM; + dev->phy_port_cnt = SWITCH_PORT_NUM; + dev->port_cnt = SWITCH_PORT_NUM; + + if (id2 == CHIP_ID_95) { + u8 val; + + id2 = 0x95; + ksz_read8(dev, REG_PORT_1_STATUS_0, &val); + if (val & PORT_FIBER_MODE) + id2 = 0x65; + } else if (id2 == CHIP_ID_94) { + dev->port_cnt--; + dev->last_port = dev->port_cnt; + id2 = 0x94; + } + id16 &= ~0xff; + id16 |= id2; + dev->chip_id = id16; + + dev->cpu_port = dev->mib_port_cnt - 1; + dev->host_mask = BIT(dev->cpu_port); + + return 0; +} + +struct ksz_chip_data { + u16 chip_id; + const char *dev_name; + int num_vlans; + int num_alus; + int num_statics; + int cpu_ports; + int port_cnt; +}; + +static const struct ksz_chip_data ksz8795_switch_chips[] = { + { + .chip_id = 0x8795, + .dev_name = "KSZ8795", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 4, /* total physical port count */ + }, + { + .chip_id = 0x8794, + .dev_name = "KSZ8794", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 3, /* total physical port count */ + }, + { + .chip_id = 0x8765, + .dev_name = "KSZ8765", + .num_vlans = 4096, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x10, /* can be configured as cpu port */ + .port_cnt = 4, /* total physical port count */ + }, +}; + +static int ksz8795_switch_init(struct ksz_device *dev) +{ + int i; + + mutex_init(&dev->stats_mutex); + mutex_init(&dev->alu_mutex); + mutex_init(&dev->vlan_mutex); + + dev->ds->ops = &ksz8795_switch_ops; + + for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) { + const struct ksz_chip_data *chip = &ksz8795_switch_chips[i]; + + if (dev->chip_id == chip->chip_id) { + dev->name = chip->dev_name; + dev->num_vlans = chip->num_vlans; + dev->num_alus = chip->num_alus; + dev->num_statics = chip->num_statics; + dev->port_cnt = chip->port_cnt; + dev->cpu_ports = chip->cpu_ports; + + break; + } + } + + /* no switch found */ + if (!dev->cpu_ports) + return -ENODEV; + + dev->port_mask = BIT(dev->port_cnt) - 1; + dev->port_mask |= dev->host_mask; + + dev->reg_mib_cnt = SWITCH_COUNTER_NUM; + dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM; + + i = dev->mib_port_cnt; + dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i, + GFP_KERNEL); + if (!dev->ports) + return -ENOMEM; + for (i = 0; i < dev->mib_port_cnt; i++) { + mutex_init(&dev->ports[i].mib.cnt_mutex); + dev->ports[i].mib.counters = + devm_kzalloc(dev->dev, + sizeof(u64) * + (TOTAL_SWITCH_COUNTER_NUM + 1), + GFP_KERNEL); + if (!dev->ports[i].mib.counters) + return -ENOMEM; + } + + return 0; +} + +static void ksz8795_switch_exit(struct ksz_device *dev) +{ + ksz8795_reset_switch(dev); +} + +static const struct ksz_dev_ops ksz8795_dev_ops = { + .get_port_addr = ksz8795_get_port_addr, + .cfg_port_member = ksz8795_cfg_port_member, + .flush_dyn_mac_table = ksz8795_flush_dyn_mac_table, + .port_setup = ksz8795_port_setup, + .r_phy = ksz8795_r_phy, + .w_phy = ksz8795_w_phy, + .r_dyn_mac_table = ksz8795_r_dyn_mac_table, + .r_sta_mac_table = ksz8795_r_sta_mac_table, + .w_sta_mac_table = ksz8795_w_sta_mac_table, + .r_mib_cnt = ksz8795_r_mib_cnt, + .r_mib_pkt = ksz8795_r_mib_pkt, + .freeze_mib = ksz8795_freeze_mib, + .port_init_cnt = ksz8795_port_init_cnt, + .shutdown = ksz8795_reset_switch, + .detect = ksz8795_switch_detect, + .init = ksz8795_switch_init, + .exit = ksz8795_switch_exit, +}; + +int ksz8795_switch_register(struct ksz_device *dev) +{ + return ksz_switch_register(dev, &ksz8795_dev_ops); +} +EXPORT_SYMBOL(ksz8795_switch_register); + +MODULE_AUTHOR("Tristram Ha "); +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h new file mode 100644 index 000000000000..3a50462df8fa --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795_reg.h @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Microchip KSZ8795 register definitions + * + * Copyright (c) 2017 Microchip Technology Inc. + * Tristram Ha + */ + +#ifndef __KSZ8795_REG_H +#define __KSZ8795_REG_H + +#define KS_PORT_M 0x1F + +#define KS_PRIO_M 0x3 +#define KS_PRIO_S 2 + +#define REG_CHIP_ID0 0x00 + +#define FAMILY_ID 0x87 + +#define REG_CHIP_ID1 0x01 + +#define SW_CHIP_ID_M 0xF0 +#define SW_CHIP_ID_S 4 +#define SW_REVISION_M 0x0E +#define SW_REVISION_S 1 +#define SW_START 0x01 + +#define CHIP_ID_94 0x60 +#define CHIP_ID_95 0x90 + +#define REG_SW_CTRL_0 0x02 + +#define SW_NEW_BACKOFF BIT(7) +#define SW_GLOBAL_RESET BIT(6) +#define SW_FLUSH_DYN_MAC_TABLE BIT(5) +#define SW_FLUSH_STA_MAC_TABLE BIT(4) +#define SW_LINK_AUTO_AGING BIT(0) + +#define REG_SW_CTRL_1 0x03 + +#define SW_HUGE_PACKET BIT(6) +#define SW_TX_FLOW_CTRL_DISABLE BIT(5) +#define SW_RX_FLOW_CTRL_DISABLE BIT(4) +#define SW_CHECK_LENGTH BIT(3) +#define SW_AGING_ENABLE BIT(2) +#define SW_FAST_AGING BIT(1) +#define SW_AGGR_BACKOFF BIT(0) + +#define REG_SW_CTRL_2 0x04 + +#define UNICAST_VLAN_BOUNDARY BIT(7) +#define MULTICAST_STORM_DISABLE BIT(6) +#define SW_BACK_PRESSURE BIT(5) +#define FAIR_FLOW_CTRL BIT(4) +#define NO_EXC_COLLISION_DROP BIT(3) +#define SW_LEGAL_PACKET_DISABLE BIT(1) + +#define REG_SW_CTRL_3 0x05 + #define WEIGHTED_FAIR_QUEUE_ENABLE BIT(3) + +#define SW_VLAN_ENABLE BIT(7) +#define SW_IGMP_SNOOP BIT(6) +#define SW_MIRROR_RX_TX BIT(0) + +#define REG_SW_CTRL_4 0x06 + +#define SW_HALF_DUPLEX_FLOW_CTRL BIT(7) +#define SW_HALF_DUPLEX BIT(6) +#define SW_FLOW_CTRL BIT(5) +#define SW_10_MBIT BIT(4) +#define SW_REPLACE_VID BIT(3) +#define BROADCAST_STORM_RATE_HI 0x07 + +#define REG_SW_CTRL_5 0x07 + +#define BROADCAST_STORM_RATE_LO 0xFF +#define BROADCAST_STORM_RATE 0x07FF + +#define REG_SW_CTRL_6 0x08 + +#define SW_MIB_COUNTER_FLUSH BIT(7) +#define SW_MIB_COUNTER_FREEZE BIT(6) +#define SW_MIB_COUNTER_CTRL_ENABLE KS_PORT_M + +#define REG_SW_CTRL_9 0x0B + +#define SPI_CLK_125_MHZ 0x80 +#define SPI_CLK_62_5_MHZ 0x40 +#define SPI_CLK_31_25_MHZ 0x00 + +#define SW_LED_MODE_M 0x3 +#define SW_LED_MODE_S 4 +#define SW_LED_LINK_ACT_SPEED 0 +#define SW_LED_LINK_ACT 1 +#define SW_LED_LINK_ACT_DUPLEX 2 +#define SW_LED_LINK_DUPLEX 3 + +#define REG_SW_CTRL_10 0x0C + +#define SW_TAIL_TAG_ENABLE BIT(1) +#define SW_PASS_PAUSE BIT(0) + +#define REG_SW_CTRL_11 0x0D + +#define REG_POWER_MANAGEMENT_1 0x0E + +#define SW_PLL_POWER_DOWN BIT(5) +#define SW_POWER_MANAGEMENT_MODE_M 0x3 +#define SW_POWER_MANAGEMENT_MODE_S 3 +#define SW_POWER_NORMAL 0 +#define SW_ENERGY_DETECTION 1 +#define SW_SOFTWARE_POWER_DOWN 2 + +#define REG_POWER_MANAGEMENT_2 0x0F + +#define REG_PORT_1_CTRL_0 0x10 +#define REG_PORT_2_CTRL_0 0x20 +#define REG_PORT_3_CTRL_0 0x30 +#define REG_PORT_4_CTRL_0 0x40 +#define REG_PORT_5_CTRL_0 0x50 + +#define PORT_BROADCAST_STORM BIT(7) +#define PORT_DIFFSERV_ENABLE BIT(6) +#define PORT_802_1P_ENABLE BIT(5) +#define PORT_BASED_PRIO_S 3 +#define PORT_BASED_PRIO_M KS_PRIO_M +#define PORT_BASED_PRIO_0 0 +#define PORT_BASED_PRIO_1 1 +#define PORT_BASED_PRIO_2 2 +#define PORT_BASED_PRIO_3 3 +#define PORT_INSERT_TAG BIT(2) +#define PORT_REMOVE_TAG BIT(1) +#define PORT_QUEUE_SPLIT_L BIT(0) + +#define REG_PORT_1_CTRL_1 0x11 +#define REG_PORT_2_CTRL_1 0x21 +#define REG_PORT_3_CTRL_1 0x31 +#define REG_PORT_4_CTRL_1 0x41 +#define REG_PORT_5_CTRL_1 0x51 + +#define PORT_MIRROR_SNIFFER BIT(7) +#define PORT_MIRROR_RX BIT(6) +#define PORT_MIRROR_TX BIT(5) +#define PORT_VLAN_MEMBERSHIP KS_PORT_M + +#define REG_PORT_1_CTRL_2 0x12 +#define REG_PORT_2_CTRL_2 0x22 +#define REG_PORT_3_CTRL_2 0x32 +#define REG_PORT_4_CTRL_2 0x42 +#define REG_PORT_5_CTRL_2 0x52 + +#define PORT_802_1P_REMAPPING BIT(7) +#define PORT_INGRESS_FILTER BIT(6) +#define PORT_DISCARD_NON_VID BIT(5) +#define PORT_FORCE_FLOW_CTRL BIT(4) +#define PORT_BACK_PRESSURE BIT(3) +#define PORT_TX_ENABLE BIT(2) +#define PORT_RX_ENABLE BIT(1) +#define PORT_LEARN_DISABLE BIT(0) + +#define REG_PORT_1_CTRL_3 0x13 +#define REG_PORT_2_CTRL_3 0x23 +#define REG_PORT_3_CTRL_3 0x33 +#define REG_PORT_4_CTRL_3 0x43 +#define REG_PORT_5_CTRL_3 0x53 +#define REG_PORT_1_CTRL_4 0x14 +#define REG_PORT_2_CTRL_4 0x24 +#define REG_PORT_3_CTRL_4 0x34 +#define REG_PORT_4_CTRL_4 0x44 +#define REG_PORT_5_CTRL_4 0x54 + +#define PORT_DEFAULT_VID 0x0001 + +#define REG_PORT_1_CTRL_5 0x15 +#define REG_PORT_2_CTRL_5 0x25 +#define REG_PORT_3_CTRL_5 0x35 +#define REG_PORT_4_CTRL_5 0x45 +#define REG_PORT_5_CTRL_5 0x55 + +#define PORT_ACL_ENABLE BIT(2) +#define PORT_AUTHEN_MODE 0x3 +#define PORT_AUTHEN_PASS 0 +#define PORT_AUTHEN_BLOCK 1 +#define PORT_AUTHEN_TRAP 2 + +#define REG_PORT_5_CTRL_6 0x56 + +#define PORT_MII_INTERNAL_CLOCK BIT(7) +#define PORT_GMII_1GPS_MODE BIT(6) +#define PORT_RGMII_ID_IN_ENABLE BIT(4) +#define PORT_RGMII_ID_OUT_ENABLE BIT(3) +#define PORT_GMII_MAC_MODE BIT(2) +#define PORT_INTERFACE_TYPE 0x3 +#define PORT_INTERFACE_MII 0 +#define PORT_INTERFACE_RMII 1 +#define PORT_INTERFACE_GMII 2 +#define PORT_INTERFACE_RGMII 3 + +#define REG_PORT_1_CTRL_7 0x17 +#define REG_PORT_2_CTRL_7 0x27 +#define REG_PORT_3_CTRL_7 0x37 +#define REG_PORT_4_CTRL_7 0x47 + +#define PORT_AUTO_NEG_ASYM_PAUSE BIT(5) +#define PORT_AUTO_NEG_SYM_PAUSE BIT(4) +#define PORT_AUTO_NEG_100BTX_FD BIT(3) +#define PORT_AUTO_NEG_100BTX BIT(2) +#define PORT_AUTO_NEG_10BT_FD BIT(1) +#define PORT_AUTO_NEG_10BT BIT(0) + +#define REG_PORT_1_STATUS_0 0x18 +#define REG_PORT_2_STATUS_0 0x28 +#define REG_PORT_3_STATUS_0 0x38 +#define REG_PORT_4_STATUS_0 0x48 + +/* For KSZ8765. */ +#define PORT_FIBER_MODE BIT(7) + +#define PORT_REMOTE_ASYM_PAUSE BIT(5) +#define PORT_REMOTE_SYM_PAUSE BIT(4) +#define PORT_REMOTE_100BTX_FD BIT(3) +#define PORT_REMOTE_100BTX BIT(2) +#define PORT_REMOTE_10BT_FD BIT(1) +#define PORT_REMOTE_10BT BIT(0) + +#define REG_PORT_1_STATUS_1 0x19 +#define REG_PORT_2_STATUS_1 0x29 +#define REG_PORT_3_STATUS_1 0x39 +#define REG_PORT_4_STATUS_1 0x49 + +#define PORT_HP_MDIX BIT(7) +#define PORT_REVERSED_POLARITY BIT(5) +#define PORT_TX_FLOW_CTRL BIT(4) +#define PORT_RX_FLOW_CTRL BIT(3) +#define PORT_STAT_SPEED_100MBIT BIT(2) +#define PORT_STAT_FULL_DUPLEX BIT(1) + +#define PORT_REMOTE_FAULT BIT(0) + +#define REG_PORT_1_LINK_MD_CTRL 0x1A +#define REG_PORT_2_LINK_MD_CTRL 0x2A +#define REG_PORT_3_LINK_MD_CTRL 0x3A +#define REG_PORT_4_LINK_MD_CTRL 0x4A + +#define PORT_CABLE_10M_SHORT BIT(7) +#define PORT_CABLE_DIAG_RESULT_M 0x3 +#define PORT_CABLE_DIAG_RESULT_S 5 +#define PORT_CABLE_STAT_NORMAL 0 +#define PORT_CABLE_STAT_OPEN 1 +#define PORT_CABLE_STAT_SHORT 2 +#define PORT_CABLE_STAT_FAILED 3 +#define PORT_START_CABLE_DIAG BIT(4) +#define PORT_FORCE_LINK BIT(3) +#define PORT_POWER_SAVING BIT(2) +#define PORT_PHY_REMOTE_LOOPBACK BIT(1) +#define PORT_CABLE_FAULT_COUNTER_H 0x01 + +#define REG_PORT_1_LINK_MD_RESULT 0x1B +#define REG_PORT_2_LINK_MD_RESULT 0x2B +#define REG_PORT_3_LINK_MD_RESULT 0x3B +#define REG_PORT_4_LINK_MD_RESULT 0x4B + +#define PORT_CABLE_FAULT_COUNTER_L 0xFF +#define PORT_CABLE_FAULT_COUNTER 0x1FF + +#define REG_PORT_1_CTRL_9 0x1C +#define REG_PORT_2_CTRL_9 0x2C +#define REG_PORT_3_CTRL_9 0x3C +#define REG_PORT_4_CTRL_9 0x4C + +#define PORT_AUTO_NEG_DISABLE BIT(7) +#define PORT_FORCE_100_MBIT BIT(6) +#define PORT_FORCE_FULL_DUPLEX BIT(5) + +#define REG_PORT_1_CTRL_10 0x1D +#define REG_PORT_2_CTRL_10 0x2D +#define REG_PORT_3_CTRL_10 0x3D +#define REG_PORT_4_CTRL_10 0x4D + +#define PORT_LED_OFF BIT(7) +#define PORT_TX_DISABLE BIT(6) +#define PORT_AUTO_NEG_RESTART BIT(5) +#define PORT_POWER_DOWN BIT(3) +#define PORT_AUTO_MDIX_DISABLE BIT(2) +#define PORT_FORCE_MDIX BIT(1) +#define PORT_MAC_LOOPBACK BIT(0) + +#define REG_PORT_1_STATUS_2 0x1E +#define REG_PORT_2_STATUS_2 0x2E +#define REG_PORT_3_STATUS_2 0x3E +#define REG_PORT_4_STATUS_2 0x4E + +#define PORT_MDIX_STATUS BIT(7) +#define PORT_AUTO_NEG_COMPLETE BIT(6) +#define PORT_STAT_LINK_GOOD BIT(5) + +#define REG_PORT_1_STATUS_3 0x1F +#define REG_PORT_2_STATUS_3 0x2F +#define REG_PORT_3_STATUS_3 0x3F +#define REG_PORT_4_STATUS_3 0x4F + +#define PORT_PHY_LOOPBACK BIT(7) +#define PORT_PHY_ISOLATE BIT(5) +#define PORT_PHY_SOFT_RESET BIT(4) +#define PORT_PHY_FORCE_LINK BIT(3) +#define PORT_PHY_MODE_M 0x7 +#define PHY_MODE_IN_AUTO_NEG 1 +#define PHY_MODE_10BT_HALF 2 +#define PHY_MODE_100BT_HALF 3 +#define PHY_MODE_10BT_FULL 5 +#define PHY_MODE_100BT_FULL 6 +#define PHY_MODE_ISOLDATE 7 + +#define REG_PORT_CTRL_0 0x00 +#define REG_PORT_CTRL_1 0x01 +#define REG_PORT_CTRL_2 0x02 +#define REG_PORT_CTRL_VID 0x03 + +#define REG_PORT_CTRL_5 0x05 + +#define REG_PORT_CTRL_7 0x07 +#define REG_PORT_STATUS_0 0x08 +#define REG_PORT_STATUS_1 0x09 +#define REG_PORT_LINK_MD_CTRL 0x0A +#define REG_PORT_LINK_MD_RESULT 0x0B +#define REG_PORT_CTRL_9 0x0C +#define REG_PORT_CTRL_10 0x0D +#define REG_PORT_STATUS_2 0x0E +#define REG_PORT_STATUS_3 0x0F + +#define REG_PORT_CTRL_12 0xA0 +#define REG_PORT_CTRL_13 0xA1 +#define REG_PORT_RATE_CTRL_3 0xA2 +#define REG_PORT_RATE_CTRL_2 0xA3 +#define REG_PORT_RATE_CTRL_1 0xA4 +#define REG_PORT_RATE_CTRL_0 0xA5 +#define REG_PORT_RATE_LIMIT 0xA6 +#define REG_PORT_IN_RATE_0 0xA7 +#define REG_PORT_IN_RATE_1 0xA8 +#define REG_PORT_IN_RATE_2 0xA9 +#define REG_PORT_IN_RATE_3 0xAA +#define REG_PORT_OUT_RATE_0 0xAB +#define REG_PORT_OUT_RATE_1 0xAC +#define REG_PORT_OUT_RATE_2 0xAD +#define REG_PORT_OUT_RATE_3 0xAE + +#define PORT_CTRL_ADDR(port, addr) \ + ((addr) + REG_PORT_1_CTRL_0 + (port) * \ + (REG_PORT_2_CTRL_0 - REG_PORT_1_CTRL_0)) + +#define REG_SW_MAC_ADDR_0 0x68 +#define REG_SW_MAC_ADDR_1 0x69 +#define REG_SW_MAC_ADDR_2 0x6A +#define REG_SW_MAC_ADDR_3 0x6B +#define REG_SW_MAC_ADDR_4 0x6C +#define REG_SW_MAC_ADDR_5 0x6D + +#define REG_IND_CTRL_0 0x6E + +#define TABLE_EXT_SELECT_S 5 +#define TABLE_EEE_V 1 +#define TABLE_ACL_V 2 +#define TABLE_PME_V 4 +#define TABLE_LINK_MD_V 5 +#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S) +#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S) +#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S) +#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S) +#define TABLE_READ BIT(4) +#define TABLE_SELECT_S 2 +#define TABLE_STATIC_MAC_V 0 +#define TABLE_VLAN_V 1 +#define TABLE_DYNAMIC_MAC_V 2 +#define TABLE_MIB_V 3 +#define TABLE_STATIC_MAC (TABLE_STATIC_MAC_V << TABLE_SELECT_S) +#define TABLE_VLAN (TABLE_VLAN_V << TABLE_SELECT_S) +#define TABLE_DYNAMIC_MAC (TABLE_DYNAMIC_MAC_V << TABLE_SELECT_S) +#define TABLE_MIB (TABLE_MIB_V << TABLE_SELECT_S) + +#define REG_IND_CTRL_1 0x6F + +#define TABLE_ENTRY_MASK 0x03FF +#define TABLE_EXT_ENTRY_MASK 0x0FFF + +#define REG_IND_DATA_8 0x70 +#define REG_IND_DATA_7 0x71 +#define REG_IND_DATA_6 0x72 +#define REG_IND_DATA_5 0x73 +#define REG_IND_DATA_4 0x74 +#define REG_IND_DATA_3 0x75 +#define REG_IND_DATA_2 0x76 +#define REG_IND_DATA_1 0x77 +#define REG_IND_DATA_0 0x78 + +#define REG_IND_DATA_PME_EEE_ACL 0xA0 + +#define REG_IND_DATA_CHECK REG_IND_DATA_6 +#define REG_IND_MIB_CHECK REG_IND_DATA_4 +#define REG_IND_DATA_HI REG_IND_DATA_7 +#define REG_IND_DATA_LO REG_IND_DATA_3 + +#define REG_INT_STATUS 0x7C +#define REG_INT_ENABLE 0x7D + +#define INT_PME BIT(4) + +#define REG_ACL_INT_STATUS 0x7E +#define REG_ACL_INT_ENABLE 0x7F + +#define INT_PORT_5 BIT(4) +#define INT_PORT_4 BIT(3) +#define INT_PORT_3 BIT(2) +#define INT_PORT_2 BIT(1) +#define INT_PORT_1 BIT(0) + +#define INT_PORT_ALL \ + (INT_PORT_5 | INT_PORT_4 | INT_PORT_3 | INT_PORT_2 | INT_PORT_1) + +#define REG_SW_CTRL_12 0x80 +#define REG_SW_CTRL_13 0x81 + +#define SWITCH_802_1P_MASK 3 +#define SWITCH_802_1P_BASE 3 +#define SWITCH_802_1P_SHIFT 2 + +#define SW_802_1P_MAP_M KS_PRIO_M +#define SW_802_1P_MAP_S KS_PRIO_S + +#define REG_SWITCH_CTRL_14 0x82 + +#define SW_PRIO_MAPPING_M KS_PRIO_M +#define SW_PRIO_MAPPING_S 6 +#define SW_PRIO_MAP_3_HI 0 +#define SW_PRIO_MAP_2_HI 2 +#define SW_PRIO_MAP_0_LO 3 + +#define REG_SW_CTRL_15 0x83 +#define REG_SW_CTRL_16 0x84 +#define REG_SW_CTRL_17 0x85 +#define REG_SW_CTRL_18 0x86 + +#define SW_SELF_ADDR_FILTER_ENABLE BIT(6) + +#define REG_SW_UNK_UCAST_CTRL 0x83 +#define REG_SW_UNK_MCAST_CTRL 0x84 +#define REG_SW_UNK_VID_CTRL 0x85 +#define REG_SW_UNK_IP_MCAST_CTRL 0x86 + +#define SW_UNK_FWD_ENABLE BIT(5) +#define SW_UNK_FWD_MAP KS_PORT_M + +#define REG_SW_CTRL_19 0x87 + +#define SW_IN_RATE_LIMIT_PERIOD_M 0x3 +#define SW_IN_RATE_LIMIT_PERIOD_S 4 +#define SW_IN_RATE_LIMIT_16_MS 0 +#define SW_IN_RATE_LIMIT_64_MS 1 +#define SW_IN_RATE_LIMIT_256_MS 2 +#define SW_OUT_RATE_LIMIT_QUEUE_BASED BIT(3) +#define SW_INS_TAG_ENABLE BIT(2) + +#define REG_TOS_PRIO_CTRL_0 0x90 +#define REG_TOS_PRIO_CTRL_1 0x91 +#define REG_TOS_PRIO_CTRL_2 0x92 +#define REG_TOS_PRIO_CTRL_3 0x93 +#define REG_TOS_PRIO_CTRL_4 0x94 +#define REG_TOS_PRIO_CTRL_5 0x95 +#define REG_TOS_PRIO_CTRL_6 0x96 +#define REG_TOS_PRIO_CTRL_7 0x97 +#define REG_TOS_PRIO_CTRL_8 0x98 +#define REG_TOS_PRIO_CTRL_9 0x99 +#define REG_TOS_PRIO_CTRL_10 0x9A +#define REG_TOS_PRIO_CTRL_11 0x9B +#define REG_TOS_PRIO_CTRL_12 0x9C +#define REG_TOS_PRIO_CTRL_13 0x9D +#define REG_TOS_PRIO_CTRL_14 0x9E +#define REG_TOS_PRIO_CTRL_15 0x9F + +#define TOS_PRIO_M KS_PRIO_M +#define TOS_PRIO_S KS_PRIO_S + +#define REG_SW_CTRL_20 0xA3 + +#define SW_GMII_DRIVE_STRENGTH_S 4 +#define SW_DRIVE_STRENGTH_M 0x7 +#define SW_DRIVE_STRENGTH_2MA 0 +#define SW_DRIVE_STRENGTH_4MA 1 +#define SW_DRIVE_STRENGTH_8MA 2 +#define SW_DRIVE_STRENGTH_12MA 3 +#define SW_DRIVE_STRENGTH_16MA 4 +#define SW_DRIVE_STRENGTH_20MA 5 +#define SW_DRIVE_STRENGTH_24MA 6 +#define SW_DRIVE_STRENGTH_28MA 7 +#define SW_MII_DRIVE_STRENGTH_S 0 + +#define REG_SW_CTRL_21 0xA4 + +#define SW_IPV6_MLD_OPTION BIT(3) +#define SW_IPV6_MLD_SNOOP BIT(2) + +#define REG_PORT_1_CTRL_12 0xB0 +#define REG_PORT_2_CTRL_12 0xC0 +#define REG_PORT_3_CTRL_12 0xD0 +#define REG_PORT_4_CTRL_12 0xE0 +#define REG_PORT_5_CTRL_12 0xF0 + +#define PORT_PASS_ALL BIT(6) +#define PORT_INS_TAG_FOR_PORT_5_S 3 +#define PORT_INS_TAG_FOR_PORT_5 BIT(3) +#define PORT_INS_TAG_FOR_PORT_4 BIT(2) +#define PORT_INS_TAG_FOR_PORT_3 BIT(1) +#define PORT_INS_TAG_FOR_PORT_2 BIT(0) + +#define REG_PORT_1_CTRL_13 0xB1 +#define REG_PORT_2_CTRL_13 0xC1 +#define REG_PORT_3_CTRL_13 0xD1 +#define REG_PORT_4_CTRL_13 0xE1 +#define REG_PORT_5_CTRL_13 0xF1 + +#define PORT_QUEUE_SPLIT_H BIT(1) +#define PORT_QUEUE_SPLIT_1 0 +#define PORT_QUEUE_SPLIT_2 1 +#define PORT_QUEUE_SPLIT_4 2 +#define PORT_DROP_TAG BIT(0) + +#define REG_PORT_1_CTRL_14 0xB2 +#define REG_PORT_2_CTRL_14 0xC2 +#define REG_PORT_3_CTRL_14 0xD2 +#define REG_PORT_4_CTRL_14 0xE2 +#define REG_PORT_5_CTRL_14 0xF2 +#define REG_PORT_1_CTRL_15 0xB3 +#define REG_PORT_2_CTRL_15 0xC3 +#define REG_PORT_3_CTRL_15 0xD3 +#define REG_PORT_4_CTRL_15 0xE3 +#define REG_PORT_5_CTRL_15 0xF3 +#define REG_PORT_1_CTRL_16 0xB4 +#define REG_PORT_2_CTRL_16 0xC4 +#define REG_PORT_3_CTRL_16 0xD4 +#define REG_PORT_4_CTRL_16 0xE4 +#define REG_PORT_5_CTRL_16 0xF4 +#define REG_PORT_1_CTRL_17 0xB5 +#define REG_PORT_2_CTRL_17 0xC5 +#define REG_PORT_3_CTRL_17 0xD5 +#define REG_PORT_4_CTRL_17 0xE5 +#define REG_PORT_5_CTRL_17 0xF5 + +#define REG_PORT_1_RATE_CTRL_3 0xB2 +#define REG_PORT_1_RATE_CTRL_2 0xB3 +#define REG_PORT_1_RATE_CTRL_1 0xB4 +#define REG_PORT_1_RATE_CTRL_0 0xB5 +#define REG_PORT_2_RATE_CTRL_3 0xC2 +#define REG_PORT_2_RATE_CTRL_2 0xC3 +#define REG_PORT_2_RATE_CTRL_1 0xC4 +#define REG_PORT_2_RATE_CTRL_0 0xC5 +#define REG_PORT_3_RATE_CTRL_3 0xD2 +#define REG_PORT_3_RATE_CTRL_2 0xD3 +#define REG_PORT_3_RATE_CTRL_1 0xD4 +#define REG_PORT_3_RATE_CTRL_0 0xD5 +#define REG_PORT_4_RATE_CTRL_3 0xE2 +#define REG_PORT_4_RATE_CTRL_2 0xE3 +#define REG_PORT_4_RATE_CTRL_1 0xE4 +#define REG_PORT_4_RATE_CTRL_0 0xE5 +#define REG_PORT_5_RATE_CTRL_3 0xF2 +#define REG_PORT_5_RATE_CTRL_2 0xF3 +#define REG_PORT_5_RATE_CTRL_1 0xF4 +#define REG_PORT_5_RATE_CTRL_0 0xF5 + +#define RATE_CTRL_ENABLE BIT(7) +#define RATE_RATIO_M (BIT(7) - 1) + +#define PORT_OUT_RATE_ENABLE BIT(7) + +#define REG_PORT_1_RATE_LIMIT 0xB6 +#define REG_PORT_2_RATE_LIMIT 0xC6 +#define REG_PORT_3_RATE_LIMIT 0xD6 +#define REG_PORT_4_RATE_LIMIT 0xE6 +#define REG_PORT_5_RATE_LIMIT 0xF6 + +#define PORT_IN_PORT_BASED_S 6 +#define PORT_RATE_PACKET_BASED_S 5 +#define PORT_IN_FLOW_CTRL_S 4 +#define PORT_IN_LIMIT_MODE_M 0x3 +#define PORT_IN_LIMIT_MODE_S 2 +#define PORT_COUNT_IFG_S 1 +#define PORT_COUNT_PREAMBLE_S 0 +#define PORT_IN_PORT_BASED BIT(PORT_IN_PORT_BASED_S) +#define PORT_RATE_PACKET_BASED BIT(PORT_RATE_PACKET_BASED_S) +#define PORT_IN_FLOW_CTRL BIT(PORT_IN_FLOW_CTRL_S) +#define PORT_IN_ALL 0 +#define PORT_IN_UNICAST 1 +#define PORT_IN_MULTICAST 2 +#define PORT_IN_BROADCAST 3 +#define PORT_COUNT_IFG BIT(PORT_COUNT_IFG_S) +#define PORT_COUNT_PREAMBLE BIT(PORT_COUNT_PREAMBLE_S) + +#define REG_PORT_1_IN_RATE_0 0xB7 +#define REG_PORT_2_IN_RATE_0 0xC7 +#define REG_PORT_3_IN_RATE_0 0xD7 +#define REG_PORT_4_IN_RATE_0 0xE7 +#define REG_PORT_5_IN_RATE_0 0xF7 +#define REG_PORT_1_IN_RATE_1 0xB8 +#define REG_PORT_2_IN_RATE_1 0xC8 +#define REG_PORT_3_IN_RATE_1 0xD8 +#define REG_PORT_4_IN_RATE_1 0xE8 +#define REG_PORT_5_IN_RATE_1 0xF8 +#define REG_PORT_1_IN_RATE_2 0xB9 +#define REG_PORT_2_IN_RATE_2 0xC9 +#define REG_PORT_3_IN_RATE_2 0xD9 +#define REG_PORT_4_IN_RATE_2 0xE9 +#define REG_PORT_5_IN_RATE_2 0xF9 +#define REG_PORT_1_IN_RATE_3 0xBA +#define REG_PORT_2_IN_RATE_3 0xCA +#define REG_PORT_3_IN_RATE_3 0xDA +#define REG_PORT_4_IN_RATE_3 0xEA +#define REG_PORT_5_IN_RATE_3 0xFA + +#define PORT_IN_RATE_ENABLE BIT(7) +#define PORT_RATE_LIMIT_M (BIT(7) - 1) + +#define REG_PORT_1_OUT_RATE_0 0xBB +#define REG_PORT_2_OUT_RATE_0 0xCB +#define REG_PORT_3_OUT_RATE_0 0xDB +#define REG_PORT_4_OUT_RATE_0 0xEB +#define REG_PORT_5_OUT_RATE_0 0xFB +#define REG_PORT_1_OUT_RATE_1 0xBC +#define REG_PORT_2_OUT_RATE_1 0xCC +#define REG_PORT_3_OUT_RATE_1 0xDC +#define REG_PORT_4_OUT_RATE_1 0xEC +#define REG_PORT_5_OUT_RATE_1 0xFC +#define REG_PORT_1_OUT_RATE_2 0xBD +#define REG_PORT_2_OUT_RATE_2 0xCD +#define REG_PORT_3_OUT_RATE_2 0xDD +#define REG_PORT_4_OUT_RATE_2 0xED +#define REG_PORT_5_OUT_RATE_2 0xFD +#define REG_PORT_1_OUT_RATE_3 0xBE +#define REG_PORT_2_OUT_RATE_3 0xCE +#define REG_PORT_3_OUT_RATE_3 0xDE +#define REG_PORT_4_OUT_RATE_3 0xEE +#define REG_PORT_5_OUT_RATE_3 0xFE + +/* PME */ + +#define SW_PME_OUTPUT_ENABLE BIT(1) +#define SW_PME_ACTIVE_HIGH BIT(0) + +#define PORT_MAGIC_PACKET_DETECT BIT(2) +#define PORT_LINK_UP_DETECT BIT(1) +#define PORT_ENERGY_DETECT BIT(0) + +/* ACL */ + +#define ACL_FIRST_RULE_M 0xF + +#define ACL_MODE_M 0x3 +#define ACL_MODE_S 4 +#define ACL_MODE_DISABLE 0 +#define ACL_MODE_LAYER_2 1 +#define ACL_MODE_LAYER_3 2 +#define ACL_MODE_LAYER_4 3 +#define ACL_ENABLE_M 0x3 +#define ACL_ENABLE_S 2 +#define ACL_ENABLE_2_COUNT 0 +#define ACL_ENABLE_2_TYPE 1 +#define ACL_ENABLE_2_MAC 2 +#define ACL_ENABLE_2_BOTH 3 +#define ACL_ENABLE_3_IP 1 +#define ACL_ENABLE_3_SRC_DST_COMP 2 +#define ACL_ENABLE_4_PROTOCOL 0 +#define ACL_ENABLE_4_TCP_PORT_COMP 1 +#define ACL_ENABLE_4_UDP_PORT_COMP 2 +#define ACL_ENABLE_4_TCP_SEQN_COMP 3 +#define ACL_SRC BIT(1) +#define ACL_EQUAL BIT(0) + +#define ACL_MAX_PORT 0xFFFF + +#define ACL_MIN_PORT 0xFFFF +#define ACL_IP_ADDR 0xFFFFFFFF +#define ACL_TCP_SEQNUM 0xFFFFFFFF + +#define ACL_RESERVED 0xF8 +#define ACL_PORT_MODE_M 0x3 +#define ACL_PORT_MODE_S 1 +#define ACL_PORT_MODE_DISABLE 0 +#define ACL_PORT_MODE_EITHER 1 +#define ACL_PORT_MODE_IN_RANGE 2 +#define ACL_PORT_MODE_OUT_OF_RANGE 3 + +#define ACL_TCP_FLAG_ENABLE BIT(0) + +#define ACL_TCP_FLAG_M 0xFF + +#define ACL_TCP_FLAG 0xFF +#define ACL_ETH_TYPE 0xFFFF +#define ACL_IP_M 0xFFFFFFFF + +#define ACL_PRIO_MODE_M 0x3 +#define ACL_PRIO_MODE_S 6 +#define ACL_PRIO_MODE_DISABLE 0 +#define ACL_PRIO_MODE_HIGHER 1 +#define ACL_PRIO_MODE_LOWER 2 +#define ACL_PRIO_MODE_REPLACE 3 +#define ACL_PRIO_M 0x7 +#define ACL_PRIO_S 3 +#define ACL_VLAN_PRIO_REPLACE BIT(2) +#define ACL_VLAN_PRIO_M 0x7 +#define ACL_VLAN_PRIO_HI_M 0x3 + +#define ACL_VLAN_PRIO_LO_M 0x8 +#define ACL_VLAN_PRIO_S 7 +#define ACL_MAP_MODE_M 0x3 +#define ACL_MAP_MODE_S 5 +#define ACL_MAP_MODE_DISABLE 0 +#define ACL_MAP_MODE_OR 1 +#define ACL_MAP_MODE_AND 2 +#define ACL_MAP_MODE_REPLACE 3 +#define ACL_MAP_PORT_M 0x1F + +#define ACL_CNT_M (BIT(11) - 1) +#define ACL_CNT_S 5 +#define ACL_MSEC_UNIT BIT(4) +#define ACL_INTR_MODE BIT(3) + +#define REG_PORT_ACL_BYTE_EN_MSB 0x10 + +#define ACL_BYTE_EN_MSB_M 0x3F + +#define REG_PORT_ACL_BYTE_EN_LSB 0x11 + +#define ACL_ACTION_START 0xA +#define ACL_ACTION_LEN 2 +#define ACL_INTR_CNT_START 0xB +#define ACL_RULESET_START 0xC +#define ACL_RULESET_LEN 2 +#define ACL_TABLE_LEN 14 + +#define ACL_ACTION_ENABLE 0x000C +#define ACL_MATCH_ENABLE 0x1FF0 +#define ACL_RULESET_ENABLE 0x2003 +#define ACL_BYTE_ENABLE ((ACL_BYTE_EN_MSB_M << 8) | 0xFF) +#define ACL_MODE_ENABLE (0x10 << 8) + +#define REG_PORT_ACL_CTRL_0 0x12 + +#define PORT_ACL_WRITE_DONE BIT(6) +#define PORT_ACL_READ_DONE BIT(5) +#define PORT_ACL_WRITE BIT(4) +#define PORT_ACL_INDEX_M 0xF + +#define REG_PORT_ACL_CTRL_1 0x13 + +#define PORT_ACL_FORCE_DLR_MISS BIT(0) + +#ifndef PHY_REG_CTRL +#define PHY_REG_CTRL 0 + +#define PHY_RESET BIT(15) +#define PHY_LOOPBACK BIT(14) +#define PHY_SPEED_100MBIT BIT(13) +#define PHY_AUTO_NEG_ENABLE BIT(12) +#define PHY_POWER_DOWN BIT(11) +#define PHY_MII_DISABLE BIT(10) +#define PHY_AUTO_NEG_RESTART BIT(9) +#define PHY_FULL_DUPLEX BIT(8) +#define PHY_COLLISION_TEST_NOT BIT(7) +#define PHY_HP_MDIX BIT(5) +#define PHY_FORCE_MDIX BIT(4) +#define PHY_AUTO_MDIX_DISABLE BIT(3) +#define PHY_REMOTE_FAULT_DISABLE BIT(2) +#define PHY_TRANSMIT_DISABLE BIT(1) +#define PHY_LED_DISABLE BIT(0) + +#define PHY_REG_STATUS 1 + +#define PHY_100BT4_CAPABLE BIT(15) +#define PHY_100BTX_FD_CAPABLE BIT(14) +#define PHY_100BTX_CAPABLE BIT(13) +#define PHY_10BT_FD_CAPABLE BIT(12) +#define PHY_10BT_CAPABLE BIT(11) +#define PHY_MII_SUPPRESS_CAPABLE_NOT BIT(6) +#define PHY_AUTO_NEG_ACKNOWLEDGE BIT(5) +#define PHY_REMOTE_FAULT BIT(4) +#define PHY_AUTO_NEG_CAPABLE BIT(3) +#define PHY_LINK_STATUS BIT(2) +#define PHY_JABBER_DETECT_NOT BIT(1) +#define PHY_EXTENDED_CAPABILITY BIT(0) + +#define PHY_REG_ID_1 2 +#define PHY_REG_ID_2 3 + +#define PHY_REG_AUTO_NEGOTIATION 4 + +#define PHY_AUTO_NEG_NEXT_PAGE_NOT BIT(15) +#define PHY_AUTO_NEG_REMOTE_FAULT_NOT BIT(13) +#define PHY_AUTO_NEG_SYM_PAUSE BIT(10) +#define PHY_AUTO_NEG_100BT4 BIT(9) +#define PHY_AUTO_NEG_100BTX_FD BIT(8) +#define PHY_AUTO_NEG_100BTX BIT(7) +#define PHY_AUTO_NEG_10BT_FD BIT(6) +#define PHY_AUTO_NEG_10BT BIT(5) +#define PHY_AUTO_NEG_SELECTOR 0x001F +#define PHY_AUTO_NEG_802_3 0x0001 + +#define PHY_REG_REMOTE_CAPABILITY 5 + +#define PHY_REMOTE_NEXT_PAGE_NOT BIT(15) +#define PHY_REMOTE_ACKNOWLEDGE_NOT BIT(14) +#define PHY_REMOTE_REMOTE_FAULT_NOT BIT(13) +#define PHY_REMOTE_SYM_PAUSE BIT(10) +#define PHY_REMOTE_100BTX_FD BIT(8) +#define PHY_REMOTE_100BTX BIT(7) +#define PHY_REMOTE_10BT_FD BIT(6) +#define PHY_REMOTE_10BT BIT(5) +#endif + +#define KSZ8795_ID_HI 0x0022 +#define KSZ8795_ID_LO 0x1550 + +#define KSZ8795_SW_ID 0x8795 + +#define PHY_REG_LINK_MD 0x1D + +#define PHY_START_CABLE_DIAG BIT(15) +#define PHY_CABLE_DIAG_RESULT 0x6000 +#define PHY_CABLE_STAT_NORMAL 0x0000 +#define PHY_CABLE_STAT_OPEN 0x2000 +#define PHY_CABLE_STAT_SHORT 0x4000 +#define PHY_CABLE_STAT_FAILED 0x6000 +#define PHY_CABLE_10M_SHORT BIT(12) +#define PHY_CABLE_FAULT_COUNTER 0x01FF + +#define PHY_REG_PHY_CTRL 0x1F + +#define PHY_MODE_M 0x7 +#define PHY_MODE_S 8 +#define PHY_STAT_REVERSED_POLARITY BIT(5) +#define PHY_STAT_MDIX BIT(4) +#define PHY_FORCE_LINK BIT(3) +#define PHY_POWER_SAVING_ENABLE BIT(2) +#define PHY_REMOTE_LOOPBACK BIT(1) + +/* Chip resource */ + +#define PRIO_QUEUES 4 + +#define KS_PRIO_IN_REG 4 + +#define TOTAL_PORT_NUM 5 + +/* Host port can only be last of them. */ +#define SWITCH_PORT_NUM (TOTAL_PORT_NUM - 1) + +#define KSZ8795_COUNTER_NUM 0x20 +#define TOTAL_KSZ8795_COUNTER_NUM (KSZ8795_COUNTER_NUM + 4) + +#define SWITCH_COUNTER_NUM KSZ8795_COUNTER_NUM +#define TOTAL_SWITCH_COUNTER_NUM TOTAL_KSZ8795_COUNTER_NUM + +/* Common names used by other drivers */ + +#define P_BCAST_STORM_CTRL REG_PORT_CTRL_0 +#define P_PRIO_CTRL REG_PORT_CTRL_0 +#define P_TAG_CTRL REG_PORT_CTRL_0 +#define P_MIRROR_CTRL REG_PORT_CTRL_1 +#define P_802_1P_CTRL REG_PORT_CTRL_2 +#define P_STP_CTRL REG_PORT_CTRL_2 +#define P_LOCAL_CTRL REG_PORT_CTRL_7 +#define P_REMOTE_STATUS REG_PORT_STATUS_0 +#define P_FORCE_CTRL REG_PORT_CTRL_9 +#define P_NEG_RESTART_CTRL REG_PORT_CTRL_10 +#define P_SPEED_STATUS REG_PORT_STATUS_1 +#define P_LINK_STATUS REG_PORT_STATUS_2 +#define P_PASS_ALL_CTRL REG_PORT_CTRL_12 +#define P_INS_SRC_PVID_CTRL REG_PORT_CTRL_12 +#define P_DROP_TAG_CTRL REG_PORT_CTRL_13 +#define P_RATE_LIMIT_CTRL REG_PORT_RATE_LIMIT + +#define S_UNKNOWN_DA_CTRL REG_SWITCH_CTRL_12 +#define S_FORWARD_INVALID_VID_CTRL REG_FORWARD_INVALID_VID + +#define S_FLUSH_TABLE_CTRL REG_SW_CTRL_0 +#define S_LINK_AGING_CTRL REG_SW_CTRL_0 +#define S_HUGE_PACKET_CTRL REG_SW_CTRL_1 +#define S_MIRROR_CTRL REG_SW_CTRL_3 +#define S_REPLACE_VID_CTRL REG_SW_CTRL_4 +#define S_PASS_PAUSE_CTRL REG_SW_CTRL_10 +#define S_TAIL_TAG_CTRL REG_SW_CTRL_10 +#define S_802_1P_PRIO_CTRL REG_SW_CTRL_12 +#define S_TOS_PRIO_CTRL REG_TOS_PRIO_CTRL_0 +#define S_IPV6_MLD_CTRL REG_SW_CTRL_21 + +#define IND_ACC_TABLE(table) ((table) << 8) + +/* Driver set switch broadcast storm protection at 10% rate. */ +#define BROADCAST_STORM_PROT_RATE 10 + +/* 148,800 frames * 67 ms / 100 */ +#define BROADCAST_STORM_VALUE 9969 + +/** + * STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF + * STATIC_MAC_TABLE_FWD_PORTS 00-001F0000-00000000 + * STATIC_MAC_TABLE_VALID 00-00200000-00000000 + * STATIC_MAC_TABLE_OVERRIDE 00-00400000-00000000 + * STATIC_MAC_TABLE_USE_FID 00-00800000-00000000 + * STATIC_MAC_TABLE_FID 00-7F000000-00000000 + */ + +#define STATIC_MAC_TABLE_ADDR 0x0000FFFF +#define STATIC_MAC_TABLE_FWD_PORTS 0x001F0000 +#define STATIC_MAC_TABLE_VALID 0x00200000 +#define STATIC_MAC_TABLE_OVERRIDE 0x00400000 +#define STATIC_MAC_TABLE_USE_FID 0x00800000 +#define STATIC_MAC_TABLE_FID 0x7F000000 + +#define STATIC_MAC_FWD_PORTS_S 16 +#define STATIC_MAC_FID_S 24 + +/** + * VLAN_TABLE_FID 00-007F007F-007F007F + * VLAN_TABLE_MEMBERSHIP 00-0F800F80-0F800F80 + * VLAN_TABLE_VALID 00-10001000-10001000 + */ + +#define VLAN_TABLE_FID 0x007F +#define VLAN_TABLE_MEMBERSHIP 0x0F80 +#define VLAN_TABLE_VALID 0x1000 + +#define VLAN_TABLE_MEMBERSHIP_S 7 +#define VLAN_TABLE_S 16 + +/** + * DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF + * DYNAMIC_MAC_TABLE_FID 00-007F0000-00000000 + * DYNAMIC_MAC_TABLE_NOT_READY 00-00800000-00000000 + * DYNAMIC_MAC_TABLE_SRC_PORT 00-07000000-00000000 + * DYNAMIC_MAC_TABLE_TIMESTAMP 00-18000000-00000000 + * DYNAMIC_MAC_TABLE_ENTRIES 7F-E0000000-00000000 + * DYNAMIC_MAC_TABLE_MAC_EMPTY 80-00000000-00000000 + */ + +#define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF +#define DYNAMIC_MAC_TABLE_FID 0x007F0000 +#define DYNAMIC_MAC_TABLE_SRC_PORT 0x07000000 +#define DYNAMIC_MAC_TABLE_TIMESTAMP 0x18000000 +#define DYNAMIC_MAC_TABLE_ENTRIES 0xE0000000 + +#define DYNAMIC_MAC_TABLE_NOT_READY 0x80 + +#define DYNAMIC_MAC_TABLE_ENTRIES_H 0x7F +#define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x80 + +#define DYNAMIC_MAC_FID_S 16 +#define DYNAMIC_MAC_SRC_PORT_S 24 +#define DYNAMIC_MAC_TIMESTAMP_S 27 +#define DYNAMIC_MAC_ENTRIES_S 29 +#define DYNAMIC_MAC_ENTRIES_H_S 3 + +/** + * MIB_COUNTER_VALUE 00-00000000-3FFFFFFF + * MIB_TOTAL_BYTES 00-0000000F-FFFFFFFF + * MIB_PACKET_DROPPED 00-00000000-0000FFFF + * MIB_COUNTER_VALID 00-00000020-00000000 + * MIB_COUNTER_OVERFLOW 00-00000040-00000000 + */ + +#define MIB_COUNTER_OVERFLOW BIT(6) +#define MIB_COUNTER_VALID BIT(5) + +#define MIB_COUNTER_VALUE 0x3FFFFFFF + +#define KS_MIB_TOTAL_RX_0 0x100 +#define KS_MIB_TOTAL_TX_0 0x101 +#define KS_MIB_PACKET_DROPPED_RX_0 0x102 +#define KS_MIB_PACKET_DROPPED_TX_0 0x103 +#define KS_MIB_TOTAL_RX_1 0x104 +#define KS_MIB_TOTAL_TX_1 0x105 +#define KS_MIB_PACKET_DROPPED_TX_1 0x106 +#define KS_MIB_PACKET_DROPPED_RX_1 0x107 +#define KS_MIB_TOTAL_RX_2 0x108 +#define KS_MIB_TOTAL_TX_2 0x109 +#define KS_MIB_PACKET_DROPPED_TX_2 0x10A +#define KS_MIB_PACKET_DROPPED_RX_2 0x10B +#define KS_MIB_TOTAL_RX_3 0x10C +#define KS_MIB_TOTAL_TX_3 0x10D +#define KS_MIB_PACKET_DROPPED_TX_3 0x10E +#define KS_MIB_PACKET_DROPPED_RX_3 0x10F +#define KS_MIB_TOTAL_RX_4 0x110 +#define KS_MIB_TOTAL_TX_4 0x111 +#define KS_MIB_PACKET_DROPPED_TX_4 0x112 +#define KS_MIB_PACKET_DROPPED_RX_4 0x113 + +#define MIB_PACKET_DROPPED 0x0000FFFF + +#define MIB_TOTAL_BYTES_H 0x0000000F + +#define TAIL_TAG_OVERRIDE BIT(6) +#define TAIL_TAG_LOOKUP BIT(7) + +#define VLAN_TABLE_ENTRIES (4096 / 4) +#define FID_ENTRIES 128 + +#endif diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c new file mode 100644 index 000000000000..50aa0d24effb --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Microchip KSZ8795 series register access through SPI + * + * Copyright (C) 2017 Microchip Technology Inc. + * Tristram Ha + */ + +#include + +#include +#include +#include +#include +#include + +#include "ksz_priv.h" +#include "ksz_common.h" + +#define SPI_ADDR_SHIFT 12 +#define SPI_ADDR_ALIGN 3 +#define SPI_TURNAROUND_SHIFT 1 + +KSZ_REGMAP_TABLE(ksz8795, 16, SPI_ADDR_SHIFT, + SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN); + +static int ksz8795_spi_probe(struct spi_device *spi) +{ + struct ksz_device *dev; + int i, ret; + + dev = ksz_switch_alloc(&spi->dev, spi); + if (!dev) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { + dev->regmap[i] = devm_regmap_init_spi(spi, + &ksz8795_regmap_config + [i]); + if (IS_ERR(dev->regmap[i])) { + ret = PTR_ERR(dev->regmap[i]); + dev_err(&spi->dev, + "Failed to initialize regmap%i: %d\n", + ksz8795_regmap_config[i].val_bits, ret); + return ret; + } + } + + if (spi->dev.platform_data) + dev->pdata = spi->dev.platform_data; + + ret = ksz8795_switch_register(dev); + + /* Main DSA driver may not be started yet. */ + if (ret) + return ret; + + spi_set_drvdata(spi, dev); + + return 0; +} + +static int ksz8795_spi_remove(struct spi_device *spi) +{ + struct ksz_device *dev = spi_get_drvdata(spi); + + if (dev) + ksz_switch_remove(dev); + + return 0; +} + +static void ksz8795_spi_shutdown(struct spi_device *spi) +{ + struct ksz_device *dev = spi_get_drvdata(spi); + + if (dev && dev->dev_ops->shutdown) + dev->dev_ops->shutdown(dev); +} + +static const struct of_device_id ksz8795_dt_ids[] = { + { .compatible = "microchip,ksz8765" }, + { .compatible = "microchip,ksz8794" }, + { .compatible = "microchip,ksz8795" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ksz8795_dt_ids); + +static struct spi_driver ksz8795_spi_driver = { + .driver = { + .name = "ksz8795-switch", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ksz8795_dt_ids), + }, + .probe = ksz8795_spi_probe, + .remove = ksz8795_spi_remove, + .shutdown = ksz8795_spi_shutdown, +}; + +module_spi_driver(ksz8795_spi_driver); + +MODULE_AUTHOR("Tristram Ha "); +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch SPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a3d2d67894bd..ce20cc90f9ef 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -373,7 +373,8 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) /* setup slave port */ dev->dev_ops->port_setup(dev, port, false); - dev->dev_ops->phy_setup(dev, port, phy); + if (dev->dev_ops->phy_setup) + dev->dev_ops->phy_setup(dev, port, phy); /* port_stp_state_set() will be called after to enable the port so * there is no need to do anything. diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index ee7096d8af07..84fed4a2578b 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -68,6 +68,22 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val) return ret; } +static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) +{ + u32 value[2]; + int ret; + + ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); + if (!ret) { + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value[0] = swab32(value[0]); + value[1] = swab32(value[1]); + *val = swab64((u64)*value); + } + + return ret; +} + static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) { return regmap_write(dev->regmap[0], reg, value); @@ -83,6 +99,18 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value) return regmap_write(dev->regmap[2], reg, value); } +static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) +{ + u32 val[2]; + + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value = swab64(value); + val[0] = swab32(value & 0xffffffffULL); + val[1] = swab32(value >> 32ULL); + + return regmap_bulk_write(dev->regmap[2], reg, val, 2); +} + static inline void ksz_pread8(struct ksz_device *dev, int port, int offset, u8 *data) { diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h index beacf0e40f42..44c16aaf775c 100644 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ b/drivers/net/dsa/microchip/ksz_priv.h @@ -150,6 +150,7 @@ int ksz_switch_register(struct ksz_device *dev, const struct ksz_dev_ops *ops); void ksz_switch_remove(struct ksz_device *dev); +int ksz8795_switch_register(struct ksz_device *dev); int ksz9477_switch_register(struct ksz_device *dev); #endif -- GitLab From fce04b1ce8e326bf2cafaea4a0c91dbc3e99e403 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:35 +0300 Subject: [PATCH 1339/7155] gpiolib: of: Reshuffle contents of consumer.h for new library layout Kernel build bot reported a compilation error after the commit f626d6dfb709 ("gpio: of: Break out OF-only code"): drivers/gpio/gpiolib-devres.o: In function `devm_gpiod_get_from_of_node': gpiolib-devres.c:(.text+0x19a): undefined reference to `gpiod_get_from_of_node' This happens due to move the latter under umbrella of CONFIG_OF_GPIO while customer.h contains staled data. Fix it by reshuffling contents of consumer.h to satisfy build dependencies. Reported-by: kbuild test robot Fixes: f626d6dfb709 ("gpio: of: Break out OF-only code"): Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- include/linux/gpio/consumer.h | 78 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 9ddcf50a3c59..6019d4d128c5 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -170,18 +170,8 @@ struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); /* Child properties interface */ -struct device_node; struct fwnode_handle; -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, enum gpiod_flags dflags, @@ -530,28 +520,8 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) } /* Child properties interface */ -struct device_node; struct fwnode_handle; -static inline -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - -static inline -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - static inline struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, @@ -584,6 +554,54 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev, flags, label); } +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO) +struct device_node; + +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +struct device_node; + +static inline +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +#ifdef CONFIG_GPIOLIB +struct device_node; + +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB */ + +struct device_node; + +static inline +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB */ + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); -- GitLab From 77cb907abe6c4b399ad77f9b6c1d77d44a435de3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:36 +0300 Subject: [PATCH 1340/7155] gpiolib: acpi: Split ACPI stuff to gpiolib-acpi.h This is a follow up to the commit f626d6dfb709 ("gpio: of: Break out OF-only code") which broke down OF parts of GPIO library. Here we do the similar to ACPI. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-2-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 1 + drivers/gpio/gpio-mb86s7x.c | 1 + drivers/gpio/gpio-xgene-sb.c | 1 + drivers/gpio/gpiolib-acpi.c | 1 + drivers/gpio/gpiolib-acpi.h | 104 +++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib.c | 1 + drivers/gpio/gpiolib.h | 93 ------------------------------- 7 files changed, 109 insertions(+), 93 deletions(-) create mode 100644 drivers/gpio/gpiolib-acpi.h diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 3108be5e208c..92e127e74813 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -27,6 +27,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" #define GPIO_SWPORTA_DR 0x00 #define GPIO_SWPORTA_DDR 0x04 diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 8f466993cd24..501e89548f53 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -21,6 +21,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /* * Only first 8bits of a register correspond to each pin, diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 38c01912c7b2..25d86441666e 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -16,6 +16,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /* Common property names */ #define XGENE_NIRQ_PROPERTY "apm,nr-irqs" diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 39f2f9035c11..d54fc6e7c8a9 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -18,6 +18,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /** * struct acpi_gpio_event - ACPI GPIO event handler data diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h new file mode 100644 index 000000000000..d7241b432b8b --- /dev/null +++ b/drivers/gpio/gpiolib-acpi.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ACPI helpers for GPIO API + * + * Copyright (C) 2012,2019 Intel Corporation + */ + +#ifndef GPIOLIB_ACPI_H +#define GPIOLIB_ACPI_H + +struct acpi_device; + +/** + * struct acpi_gpio_info - ACPI GPIO specific information + * @adev: reference to ACPI device which consumes GPIO resource + * @flags: GPIO initialization flags + * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo + * @pin_config: pin bias as provided by ACPI + * @polarity: interrupt polarity as provided by ACPI + * @triggering: triggering type as provided by ACPI + * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping + */ +struct acpi_gpio_info { + struct acpi_device *adev; + enum gpiod_flags flags; + bool gpioint; + int pin_config; + int polarity; + int triggering; + unsigned int quirks; +}; + +#ifdef CONFIG_ACPI +void acpi_gpiochip_add(struct gpio_chip *chip); +void acpi_gpiochip_remove(struct gpio_chip *chip); + +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); +void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); + +int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, + struct acpi_gpio_info *info); +int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info); + +struct gpio_desc *acpi_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpiod_flags *dflags, + unsigned long *lookupflags); +struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, + const char *propname, int index, + struct acpi_gpio_info *info); + +int acpi_gpio_count(struct device *dev, const char *con_id); + +bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); +#else +static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } +static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } + +static inline int +acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) +{ + return 0; +} +static inline int +acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info) +{ + return 0; +} + +static inline struct gpio_desc * +acpi_find_gpio(struct device *dev, const char *con_id, + unsigned int idx, enum gpiod_flags *dflags, + unsigned long *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc * +acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, + int index, struct acpi_gpio_info *info) +{ + return ERR_PTR(-ENXIO); +} +static inline int acpi_gpio_count(struct device *dev, const char *con_id) +{ + return -ENODEV; +} + +static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, + const char *con_id) +{ + return false; +} +#endif + +#endif /* GPIOLIB_ACPI_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 03883f519d53..f83870a18ae7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -30,6 +30,7 @@ #include "gpiolib.h" #include "gpiolib-of.h" +#include "gpiolib-acpi.h" #define CREATE_TRACE_POINTS #include diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 75d2e909d8c6..b8b10a409c7b 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -16,8 +16,6 @@ #include #include -struct acpi_device; - /** * struct gpio_device - internal state container for GPIO devices * @id: numerical ID number for the GPIO chip @@ -68,100 +66,9 @@ struct gpio_device { #endif }; -/** - * struct acpi_gpio_info - ACPI GPIO specific information - * @adev: reference to ACPI device which consumes GPIO resource - * @flags: GPIO initialization flags - * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo - * @pin_config: pin bias as provided by ACPI - * @polarity: interrupt polarity as provided by ACPI - * @triggering: triggering type as provided by ACPI - * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping - */ -struct acpi_gpio_info { - struct acpi_device *adev; - enum gpiod_flags flags; - bool gpioint; - int pin_config; - int polarity; - int triggering; - unsigned int quirks; -}; - /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; -#ifdef CONFIG_ACPI -void acpi_gpiochip_add(struct gpio_chip *chip); -void acpi_gpiochip_remove(struct gpio_chip *chip); - -void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); -void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); - -int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, - struct acpi_gpio_info *info); -int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, - struct acpi_gpio_info *info); - -struct gpio_desc *acpi_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - enum gpiod_flags *dflags, - unsigned long *lookupflags); -struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, - const char *propname, int index, - struct acpi_gpio_info *info); - -int acpi_gpio_count(struct device *dev, const char *con_id); - -bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); -#else -static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } -static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } - -static inline void -acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } - -static inline void -acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } - -static inline int -acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) -{ - return 0; -} -static inline int -acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, - struct acpi_gpio_info *info) -{ - return 0; -} - -static inline struct gpio_desc * -acpi_find_gpio(struct device *dev, const char *con_id, - unsigned int idx, enum gpiod_flags *dflags, - unsigned long *lookupflags) -{ - return ERR_PTR(-ENOENT); -} -static inline struct gpio_desc * -acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, - int index, struct acpi_gpio_info *info) -{ - return ERR_PTR(-ENXIO); -} -static inline int acpi_gpio_count(struct device *dev, const char *con_id) -{ - return -ENODEV; -} - -static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, - const char *con_id) -{ - return false; -} -#endif - struct gpio_array { struct gpio_desc **desc; unsigned int size; -- GitLab From 2838bf941b120ec846a3903db13e319368d51b08 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:37 +0300 Subject: [PATCH 1341/7155] gpiolib-acpi: Move acpi_dev_add_driver_gpios() et al to consumer.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API, which belongs to GPIO library, is foreign to ACPI headers. Earlier we moved out I²C out of the latter, and now it's time for acpi_dev_add_driver_gpios() et al. For time being the acpi_gpio_get_irq_resource() and acpi_dev_gpio_irq_get() are left untouched as they need more thought about. Note, it requires uninline acpi_dev_remove_driver_gpios() to keep purity of consumer.h. Cc: Pierre-Louis Bossart Cc: Liam Girdwood Cc: Jie Yang Cc: Mark Brown Cc: alsa-devel@alsa-project.org (moderated list:INTEL ASoC DRIVERS) Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-3-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 7 +++ include/linux/acpi.h | 51 ------------------ include/linux/gpio/consumer.h | 57 ++++++++++++++++++++ sound/soc/intel/boards/bytcht_cx2072x.c | 1 + sound/soc/intel/boards/cht_bsw_max98090_ti.c | 1 + sound/soc/intel/boards/cht_bsw_rt5672.c | 1 + 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d54fc6e7c8a9..fdee8afa5339 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -383,6 +383,13 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev, } EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); +void acpi_dev_remove_driver_gpios(struct acpi_device *adev) +{ + if (adev) + adev->driver_gpios = NULL; +} +EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios); + static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res) { acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev)); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9426b9aaed86..e40e1e27ed8e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -994,62 +994,11 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c #endif #endif -struct acpi_gpio_params { - unsigned int crs_entry_index; - unsigned int line_index; - bool active_low; -}; - -struct acpi_gpio_mapping { - const char *name; - const struct acpi_gpio_params *data; - unsigned int size; - -/* Ignore IoRestriction field */ -#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) -/* - * When ACPI GPIO mapping table is in use the index parameter inside it - * refers to the GPIO resource in _CRS method. That index has no - * distinction of actual type of the resource. When consumer wants to - * get GpioIo type explicitly, this quirk may be used. - */ -#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) - - unsigned int quirks; -}; - #if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) -int acpi_dev_add_driver_gpios(struct acpi_device *adev, - const struct acpi_gpio_mapping *gpios); - -static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) -{ - if (adev) - adev->driver_gpios = NULL; -} - -int devm_acpi_dev_add_driver_gpios(struct device *dev, - const struct acpi_gpio_mapping *gpios); -void devm_acpi_dev_remove_driver_gpios(struct device *dev); - bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio); int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index); #else -static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, - const struct acpi_gpio_mapping *gpios) -{ - return -ENXIO; -} -static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} - -static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, - const struct acpi_gpio_mapping *gpios) -{ - return -ENXIO; -} -static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {} - static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 6019d4d128c5..aac617371b60 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -602,6 +602,63 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, #endif /* CONFIG_GPIOLIB */ +struct acpi_gpio_params { + unsigned int crs_entry_index; + unsigned int line_index; + bool active_low; +}; + +struct acpi_gpio_mapping { + const char *name; + const struct acpi_gpio_params *data; + unsigned int size; + +/* Ignore IoRestriction field */ +#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) +/* + * When ACPI GPIO mapping table is in use the index parameter inside it + * refers to the GPIO resource in _CRS method. That index has no + * distinction of actual type of the resource. When consumer wants to + * get GpioIo type explicitly, this quirk may be used. + */ +#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) + + unsigned int quirks; +}; + +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI) + +struct acpi_device; + +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios); +void acpi_dev_remove_driver_gpios(struct acpi_device *adev); + +int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios); +void devm_acpi_dev_remove_driver_gpios(struct device *dev); + +#else /* CONFIG_GPIOLIB && CONFIG_ACPI */ + +struct acpi_device; + +static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} + +static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {} + +#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 54ac2fd41925..67f06c95eec5 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 33eb72545be6..05db311b579e 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 4977b5a65eb8..9d657421730a 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -8,6 +8,7 @@ * Mengdong Lin */ +#include #include #include #include -- GitLab From a3fc5723397703a56fb6083b3e2f2ac601d1dfe0 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:12 -0700 Subject: [PATCH 1342/7155] extcon: adc-jack: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. Signed-off-by: Stephen Boyd [cw00.choi: Edit patch title and description for readability] Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index ee9b5f70bfa4..ad02dc6747a4 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -140,10 +140,8 @@ static int adc_jack_probe(struct platform_device *pdev) return err; data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); + if (data->irq < 0) return -ENODEV; - } err = request_any_context_irq(data->irq, adc_jack_irq_thread, pdata->irq_flags, pdata->name, data); -- GitLab From 51b0c5c24484f7263ee34d2b48396b39734d0a1c Mon Sep 17 00:00:00 2001 From: Matt Spinler Date: Fri, 19 Jul 2019 15:30:37 -0500 Subject: [PATCH 1343/7155] ARM: dts: aspeed: swift: Fix FSI GPIOs Change the FSI clock and data GPIOs to match what the hardware turned out to use. Fixes: 8e8fd0cbd7c5 ("ARM: dts: aspeed: Add Swift BMC machine") Signed-off-by: Matt Spinler Reviewed-by: Andrew Jeffery Reviewed-by: Adriana Kobylak Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-bmc-opp-swift.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts index caac895c60b4..f14f745b34ca 100644 --- a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts +++ b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts @@ -207,8 +207,8 @@ #size-cells = <0>; no-gpio-delays; - clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>; - data-gpios = <&gpio ASPEED_GPIO(E, 0) GPIO_ACTIVE_HIGH>; + clock-gpios = <&gpio ASPEED_GPIO(P, 1) GPIO_ACTIVE_HIGH>; + data-gpios = <&gpio ASPEED_GPIO(P, 2) GPIO_ACTIVE_HIGH>; mux-gpios = <&gpio ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>; enable-gpios = <&gpio ASPEED_GPIO(P, 0) GPIO_ACTIVE_HIGH>; trans-gpios = <&gpio ASPEED_GPIO(P, 3) GPIO_ACTIVE_HIGH>; -- GitLab From 965112785e4bd4355262c6c5a32ea8f349adb401 Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:13 -0700 Subject: [PATCH 1344/7155] tcp: tcp_syn_flood_action read port from socket This allows us to call this function before an SKB has been allocated. Signed-off-by: Petar Penkov Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- net/ipv4/tcp_input.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c21e8a22fb3b..8892df6de1d4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6422,9 +6422,7 @@ EXPORT_SYMBOL(inet_reqsk_alloc); /* * Return true if a syncookie should be sent */ -static bool tcp_syn_flood_action(const struct sock *sk, - const struct sk_buff *skb, - const char *proto) +static bool tcp_syn_flood_action(const struct sock *sk, const char *proto) { struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; const char *msg = "Dropping request"; @@ -6444,7 +6442,7 @@ static bool tcp_syn_flood_action(const struct sock *sk, net->ipv4.sysctl_tcp_syncookies != 2 && xchg(&queue->synflood_warned, 1) == 0) net_info_ratelimited("%s: Possible SYN flooding on port %d. %s. Check SNMP counters.\n", - proto, ntohs(tcp_hdr(skb)->dest), msg); + proto, sk->sk_num, msg); return want_cookie; } @@ -6487,7 +6485,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, */ if ((net->ipv4.sysctl_tcp_syncookies == 2 || inet_csk_reqsk_queue_is_full(sk)) && !isn) { - want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name); + want_cookie = tcp_syn_flood_action(sk, rsk_ops->slab_name); if (!want_cookie) goto drop; } -- GitLab From 9349d600fb6a1ca0aaeb515523e1bb5409483d76 Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:14 -0700 Subject: [PATCH 1345/7155] tcp: add skb-less helpers to retrieve SYN cookie This patch allows generation of a SYN cookie before an SKB has been allocated, as is the case at XDP. Signed-off-by: Petar Penkov Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- include/net/tcp.h | 10 ++++++ net/ipv4/tcp_input.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 15 +++++++++ net/ipv6/tcp_ipv6.c | 15 +++++++++ 4 files changed, 113 insertions(+) diff --git a/include/net/tcp.h b/include/net/tcp.h index e5cf514ba118..fb7e153aecc5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -414,6 +414,16 @@ void tcp_parse_options(const struct net *net, const struct sk_buff *skb, int estab, struct tcp_fastopen_cookie *foc); const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); +/* + * BPF SKB-less helpers + */ +u16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph, + struct tcphdr *th, u32 *cookie); +u16 tcp_v6_get_syncookie(struct sock *sk, struct ipv6hdr *iph, + struct tcphdr *th, u32 *cookie); +u16 tcp_get_syncookie_mss(struct request_sock_ops *rsk_ops, + const struct tcp_request_sock_ops *af_ops, + struct sock *sk, struct tcphdr *th); /* * TCP v4 functions exported for the inet6 API */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8892df6de1d4..706cbb3b2986 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3782,6 +3782,49 @@ static void smc_parse_options(const struct tcphdr *th, #endif } +/* Try to parse the MSS option from the TCP header. Return 0 on failure, clamped + * value on success. + */ +static u16 tcp_parse_mss_option(const struct tcphdr *th, u16 user_mss) +{ + const unsigned char *ptr = (const unsigned char *)(th + 1); + int length = (th->doff * 4) - sizeof(struct tcphdr); + u16 mss = 0; + + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCPOPT_EOL: + return mss; + case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ + length--; + continue; + default: + if (length < 2) + return mss; + opsize = *ptr++; + if (opsize < 2) /* "silly options" */ + return mss; + if (opsize > length) + return mss; /* fail on partial options */ + if (opcode == TCPOPT_MSS && opsize == TCPOLEN_MSS) { + u16 in_mss = get_unaligned_be16(ptr); + + if (in_mss) { + if (user_mss && user_mss < in_mss) + in_mss = user_mss; + mss = in_mss; + } + } + ptr += opsize - 2; + length -= opsize; + } + } + return mss; +} + /* Look for tcp options. Normally only called on SYN and SYNACK packets. * But, this can also be called on packets in the established flow when * the fast version below fails. @@ -6464,6 +6507,36 @@ static void tcp_reqsk_record_syn(const struct sock *sk, } } +/* If a SYN cookie is required and supported, returns a clamped MSS value to be + * used for SYN cookie generation. + */ +u16 tcp_get_syncookie_mss(struct request_sock_ops *rsk_ops, + const struct tcp_request_sock_ops *af_ops, + struct sock *sk, struct tcphdr *th) +{ + struct tcp_sock *tp = tcp_sk(sk); + u16 mss; + + if (sock_net(sk)->ipv4.sysctl_tcp_syncookies != 2 && + !inet_csk_reqsk_queue_is_full(sk)) + return 0; + + if (!tcp_syn_flood_action(sk, rsk_ops->slab_name)) + return 0; + + if (sk_acceptq_is_full(sk)) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + return 0; + } + + mss = tcp_parse_mss_option(th, tp->rx_opt.user_mss); + if (!mss) + mss = af_ops->mss_clamp; + + return mss; +} +EXPORT_SYMBOL_GPL(tcp_get_syncookie_mss); + int tcp_conn_request(struct request_sock_ops *rsk_ops, const struct tcp_request_sock_ops *af_ops, struct sock *sk, struct sk_buff *skb) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d57641cb3477..10217393cda6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1515,6 +1515,21 @@ static struct sock *tcp_v4_cookie_check(struct sock *sk, struct sk_buff *skb) return sk; } +u16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph, + struct tcphdr *th, u32 *cookie) +{ + u16 mss = 0; +#ifdef CONFIG_SYN_COOKIES + mss = tcp_get_syncookie_mss(&tcp_request_sock_ops, + &tcp_request_sock_ipv4_ops, sk, th); + if (mss) { + *cookie = __cookie_v4_init_sequence(iph, th, &mss); + tcp_synq_overflow(sk); + } +#endif + return mss; +} + /* The socket must have it's spinlock held when we get * here, unless it is a TCP_LISTEN socket. * diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5da069e91cac..87f44d3250ee 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1063,6 +1063,21 @@ static struct sock *tcp_v6_cookie_check(struct sock *sk, struct sk_buff *skb) return sk; } +u16 tcp_v6_get_syncookie(struct sock *sk, struct ipv6hdr *iph, + struct tcphdr *th, u32 *cookie) +{ + u16 mss = 0; +#ifdef CONFIG_SYN_COOKIES + mss = tcp_get_syncookie_mss(&tcp6_request_sock_ops, + &tcp_request_sock_ipv6_ops, sk, th); + if (mss) { + *cookie = __cookie_v6_init_sequence(iph, th, &mss); + tcp_synq_overflow(sk); + } +#endif + return mss; +} + static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) -- GitLab From 70d66244317e958092e9c971b08dd5b7fd29d9cb Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:15 -0700 Subject: [PATCH 1346/7155] bpf: add bpf_tcp_gen_syncookie helper This helper function allows BPF programs to try to generate SYN cookies, given a reference to a listener socket. The function works from XDP and with an skb context since bpf_skc_lookup_tcp can lookup a socket in both cases. Signed-off-by: Petar Penkov Suggested-by: Eric Dumazet Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- include/uapi/linux/bpf.h | 30 ++++++++++++++++- net/core/filter.c | 73 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 6bbef0c7f585..4393bd4b2419 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2714,6 +2714,33 @@ union bpf_attr { * **-EPERM** if no permission to send the *sig*. * * **-EAGAIN** if bpf program can try again. + * + * s64 bpf_tcp_gen_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len) + * Description + * Try to issue a SYN cookie for the packet with corresponding + * IP/TCP headers, *iph* and *th*, on the listening socket in *sk*. + * + * *iph* points to the start of the IPv4 or IPv6 header, while + * *iph_len* contains **sizeof**\ (**struct iphdr**) or + * **sizeof**\ (**struct ip6hdr**). + * + * *th* points to the start of the TCP header, while *th_len* + * contains the length of the TCP header. + * + * Return + * On success, lower 32 bits hold the generated SYN cookie in + * followed by 16 bits which hold the MSS value for that cookie, + * and the top 16 bits are unused. + * + * On failure, the returned value is one of the following: + * + * **-EINVAL** SYN cookie cannot be issued due to error + * + * **-ENOENT** SYN cookie should not be issued (no SYN flood) + * + * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies + * + * **-EPROTONOSUPPORT** IP packet version is not 4 or 6 */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2825,7 +2852,8 @@ union bpf_attr { FN(strtoul), \ FN(sk_storage_get), \ FN(sk_storage_delete), \ - FN(send_signal), + FN(send_signal), \ + FN(tcp_gen_syncookie), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/net/core/filter.c b/net/core/filter.c index 1eee70f80fba..5a2707918629 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5855,6 +5855,75 @@ static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = { .arg5_type = ARG_CONST_SIZE, }; +BPF_CALL_5(bpf_tcp_gen_syncookie, struct sock *, sk, void *, iph, u32, iph_len, + struct tcphdr *, th, u32, th_len) +{ +#ifdef CONFIG_SYN_COOKIES + u32 cookie; + u16 mss; + + if (unlikely(th_len < sizeof(*th) || th_len != th->doff * 4)) + return -EINVAL; + + if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN) + return -EINVAL; + + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies) + return -ENOENT; + + if (!th->syn || th->ack || th->fin || th->rst) + return -EINVAL; + + if (unlikely(iph_len < sizeof(struct iphdr))) + return -EINVAL; + + /* Both struct iphdr and struct ipv6hdr have the version field at the + * same offset so we can cast to the shorter header (struct iphdr). + */ + switch (((struct iphdr *)iph)->version) { + case 4: + if (sk->sk_family == AF_INET6 && sk->sk_ipv6only) + return -EINVAL; + + mss = tcp_v4_get_syncookie(sk, iph, th, &cookie); + break; + +#if IS_BUILTIN(CONFIG_IPV6) + case 6: + if (unlikely(iph_len < sizeof(struct ipv6hdr))) + return -EINVAL; + + if (sk->sk_family != AF_INET6) + return -EINVAL; + + mss = tcp_v6_get_syncookie(sk, iph, th, &cookie); + break; +#endif /* CONFIG_IPV6 */ + + default: + return -EPROTONOSUPPORT; + } + if (mss <= 0) + return -ENOENT; + + return cookie | ((u64)mss << 32); +#else + return -EOPNOTSUPP; +#endif /* CONFIG_SYN_COOKIES */ +} + +static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = { + .func = bpf_tcp_gen_syncookie, + .gpl_only = true, /* __cookie_v*_init_sequence() is GPL */ + .pkt_access = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_SOCK_COMMON, + .arg2_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_PTR_TO_MEM, + .arg5_type = ARG_CONST_SIZE, +}; + #endif /* CONFIG_INET */ bool bpf_helper_changes_pkt_data(void *func) @@ -6144,6 +6213,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_tcp_check_syncookie_proto; case BPF_FUNC_skb_ecn_set_ce: return &bpf_skb_ecn_set_ce_proto; + case BPF_FUNC_tcp_gen_syncookie: + return &bpf_tcp_gen_syncookie_proto; #endif default: return bpf_base_func_proto(func_id); @@ -6183,6 +6254,8 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_xdp_skc_lookup_tcp_proto; case BPF_FUNC_tcp_check_syncookie: return &bpf_tcp_check_syncookie_proto; + case BPF_FUNC_tcp_gen_syncookie: + return &bpf_tcp_gen_syncookie_proto; #endif default: return bpf_base_func_proto(func_id); -- GitLab From 3745ee18017e36be34f6f2a81e802a20e54e5e8b Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:16 -0700 Subject: [PATCH 1347/7155] bpf: sync bpf.h to tools/ Sync updated documentation for bpf_redirect_map. Sync the bpf_tcp_gen_syncookie helper function definition with the one in tools/uapi. Signed-off-by: Petar Penkov Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- tools/include/uapi/linux/bpf.h | 37 +++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 21d0f6863df3..4393bd4b2419 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1572,8 +1572,11 @@ union bpf_attr { * but this is only implemented for native XDP (with driver * support) as of this writing). * - * All values for *flags* are reserved for future usage, and must - * be left at zero. + * The lower two bits of *flags* are used as the return code if + * the map lookup fails. This is so that the return value can be + * one of the XDP program return codes up to XDP_TX, as chosen by + * the caller. Any higher bits in the *flags* argument must be + * unset. * * When used to redirect packets to net devices, this helper * provides a high performance increase over **bpf_redirect**\ (). @@ -2711,6 +2714,33 @@ union bpf_attr { * **-EPERM** if no permission to send the *sig*. * * **-EAGAIN** if bpf program can try again. + * + * s64 bpf_tcp_gen_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len) + * Description + * Try to issue a SYN cookie for the packet with corresponding + * IP/TCP headers, *iph* and *th*, on the listening socket in *sk*. + * + * *iph* points to the start of the IPv4 or IPv6 header, while + * *iph_len* contains **sizeof**\ (**struct iphdr**) or + * **sizeof**\ (**struct ip6hdr**). + * + * *th* points to the start of the TCP header, while *th_len* + * contains the length of the TCP header. + * + * Return + * On success, lower 32 bits hold the generated SYN cookie in + * followed by 16 bits which hold the MSS value for that cookie, + * and the top 16 bits are unused. + * + * On failure, the returned value is one of the following: + * + * **-EINVAL** SYN cookie cannot be issued due to error + * + * **-ENOENT** SYN cookie should not be issued (no SYN flood) + * + * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies + * + * **-EPROTONOSUPPORT** IP packet version is not 4 or 6 */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2822,7 +2852,8 @@ union bpf_attr { FN(strtoul), \ FN(sk_storage_get), \ FN(sk_storage_delete), \ - FN(send_signal), + FN(send_signal), \ + FN(tcp_gen_syncookie), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call -- GitLab From 637f71c09ba22d1042f5b48b58c249ee5665d44d Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:17 -0700 Subject: [PATCH 1348/7155] selftests/bpf: bpf_tcp_gen_syncookie->bpf_helpers Expose bpf_tcp_gen_syncookie to selftests. Signed-off-by: Petar Penkov Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/bpf_helpers.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index f804f210244e..120aa86c58d3 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -228,6 +228,9 @@ static void *(*bpf_sk_storage_get)(void *map, struct bpf_sock *sk, static int (*bpf_sk_storage_delete)(void *map, struct bpf_sock *sk) = (void *)BPF_FUNC_sk_storage_delete; static int (*bpf_send_signal)(unsigned sig) = (void *)BPF_FUNC_send_signal; +static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip, + int ip_len, void *tcp, int tcp_len) = + (void *) BPF_FUNC_tcp_gen_syncookie; /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions -- GitLab From 91bc35789db4e1a489be7ab6e318e6265202e096 Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 29 Jul 2019 09:59:18 -0700 Subject: [PATCH 1349/7155] selftests/bpf: add test for bpf_tcp_gen_syncookie Modify the existing bpf_tcp_check_syncookie test to also generate a SYN cookie, pass the packet to the kernel, and verify that the two cookies are the same (and both valid). Since cloned SKBs are skipped during generic XDP, this test does not issue a SYN cookie when run in XDP mode. We therefore only check that a valid SYN cookie was issued at the TC hook. Additionally, verify that the MSS for that SYN cookie is within expected range. Signed-off-by: Petar Penkov Reviewed-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov --- .../bpf/progs/test_tcp_check_syncookie_kern.c | 48 +++++++++++++-- .../selftests/bpf/test_tcp_check_syncookie.sh | 3 + .../bpf/test_tcp_check_syncookie_user.c | 61 ++++++++++++++++--- 3 files changed, 99 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c b/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c index 1ab095bcacd8..d8803dfa8d32 100644 --- a/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c +++ b/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c @@ -19,10 +19,29 @@ struct bpf_map_def SEC("maps") results = { .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(__u32), - .value_size = sizeof(__u64), - .max_entries = 1, + .value_size = sizeof(__u32), + .max_entries = 3, }; +static __always_inline __s64 gen_syncookie(void *data_end, struct bpf_sock *sk, + void *iph, __u32 ip_size, + struct tcphdr *tcph) +{ + __u32 thlen = tcph->doff * 4; + + if (tcph->syn && !tcph->ack) { + // packet should only have an MSS option + if (thlen != 24) + return 0; + + if ((void *)tcph + thlen > data_end) + return 0; + + return bpf_tcp_gen_syncookie(sk, iph, ip_size, tcph, thlen); + } + return 0; +} + static __always_inline void check_syncookie(void *ctx, void *data, void *data_end) { @@ -33,8 +52,10 @@ static __always_inline void check_syncookie(void *ctx, void *data, struct ipv6hdr *ipv6h; struct tcphdr *tcph; int ret; + __u32 key_mss = 2; + __u32 key_gen = 1; __u32 key = 0; - __u64 value = 1; + __s64 seq_mss; ethh = data; if (ethh + 1 > data_end) @@ -66,6 +87,9 @@ static __always_inline void check_syncookie(void *ctx, void *data, if (sk->state != BPF_TCP_LISTEN) goto release; + seq_mss = gen_syncookie(data_end, sk, ipv4h, sizeof(*ipv4h), + tcph); + ret = bpf_tcp_check_syncookie(sk, ipv4h, sizeof(*ipv4h), tcph, sizeof(*tcph)); break; @@ -95,6 +119,9 @@ static __always_inline void check_syncookie(void *ctx, void *data, if (sk->state != BPF_TCP_LISTEN) goto release; + seq_mss = gen_syncookie(data_end, sk, ipv6h, sizeof(*ipv6h), + tcph); + ret = bpf_tcp_check_syncookie(sk, ipv6h, sizeof(*ipv6h), tcph, sizeof(*tcph)); break; @@ -103,8 +130,19 @@ static __always_inline void check_syncookie(void *ctx, void *data, return; } - if (ret == 0) - bpf_map_update_elem(&results, &key, &value, 0); + if (seq_mss > 0) { + __u32 cookie = (__u32)seq_mss; + __u32 mss = seq_mss >> 32; + + bpf_map_update_elem(&results, &key_gen, &cookie, 0); + bpf_map_update_elem(&results, &key_mss, &mss, 0); + } + + if (ret == 0) { + __u32 cookie = bpf_ntohl(tcph->ack_seq) - 1; + + bpf_map_update_elem(&results, &key, &cookie, 0); + } release: bpf_sk_release(sk); diff --git a/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh b/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh index d48e51716d19..9b3617d770a5 100755 --- a/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh +++ b/tools/testing/selftests/bpf/test_tcp_check_syncookie.sh @@ -37,6 +37,9 @@ setup() ns1_exec ip link set lo up ns1_exec sysctl -w net.ipv4.tcp_syncookies=2 + ns1_exec sysctl -w net.ipv4.tcp_window_scaling=0 + ns1_exec sysctl -w net.ipv4.tcp_timestamps=0 + ns1_exec sysctl -w net.ipv4.tcp_sack=0 wait_for_ip 127.0.0.1 wait_for_ip ::1 diff --git a/tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c b/tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c index 87829c86c746..b9e991d43155 100644 --- a/tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c +++ b/tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c @@ -2,6 +2,7 @@ // Copyright (c) 2018 Facebook // Copyright (c) 2019 Cloudflare +#include #include #include #include @@ -77,7 +78,7 @@ static int connect_to_server(int server_fd) return fd; } -static int get_map_fd_by_prog_id(int prog_id) +static int get_map_fd_by_prog_id(int prog_id, bool *xdp) { struct bpf_prog_info info = {}; __u32 info_len = sizeof(info); @@ -104,6 +105,8 @@ static int get_map_fd_by_prog_id(int prog_id) goto err; } + *xdp = info.type == BPF_PROG_TYPE_XDP; + map_fd = bpf_map_get_fd_by_id(map_ids[0]); if (map_fd < 0) log_err("Failed to get fd by map id %d", map_ids[0]); @@ -113,18 +116,32 @@ static int get_map_fd_by_prog_id(int prog_id) return map_fd; } -static int run_test(int server_fd, int results_fd) +static int run_test(int server_fd, int results_fd, bool xdp) { int client = -1, srv_client = -1; int ret = 0; __u32 key = 0; - __u64 value = 0; + __u32 key_gen = 1; + __u32 key_mss = 2; + __u32 value = 0; + __u32 value_gen = 0; + __u32 value_mss = 0; if (bpf_map_update_elem(results_fd, &key, &value, 0) < 0) { log_err("Can't clear results"); goto err; } + if (bpf_map_update_elem(results_fd, &key_gen, &value_gen, 0) < 0) { + log_err("Can't clear results"); + goto err; + } + + if (bpf_map_update_elem(results_fd, &key_mss, &value_mss, 0) < 0) { + log_err("Can't clear results"); + goto err; + } + client = connect_to_server(server_fd); if (client == -1) goto err; @@ -140,8 +157,35 @@ static int run_test(int server_fd, int results_fd) goto err; } - if (value != 1) { - log_err("Didn't match syncookie: %llu", value); + if (value == 0) { + log_err("Didn't match syncookie: %u", value); + goto err; + } + + if (bpf_map_lookup_elem(results_fd, &key_gen, &value_gen) < 0) { + log_err("Can't lookup result"); + goto err; + } + + if (xdp && value_gen == 0) { + // SYN packets do not get passed through generic XDP, skip the + // rest of the test. + printf("Skipping XDP cookie check\n"); + goto out; + } + + if (bpf_map_lookup_elem(results_fd, &key_mss, &value_mss) < 0) { + log_err("Can't lookup result"); + goto err; + } + + if (value != value_gen) { + log_err("BPF generated cookie does not match kernel one"); + goto err; + } + + if (value_mss < 536 || value_mss > USHRT_MAX) { + log_err("Unexpected MSS retrieved"); goto err; } @@ -163,13 +207,14 @@ int main(int argc, char **argv) int server_v6 = -1; int results = -1; int err = 0; + bool xdp; if (argc < 2) { fprintf(stderr, "Usage: %s prog_id\n", argv[0]); exit(1); } - results = get_map_fd_by_prog_id(atoi(argv[1])); + results = get_map_fd_by_prog_id(atoi(argv[1]), &xdp); if (results < 0) { log_err("Can't get map"); goto err; @@ -194,10 +239,10 @@ int main(int argc, char **argv) if (server_v6 == -1) goto err; - if (run_test(server, results)) + if (run_test(server, results, xdp)) goto err; - if (run_test(server_v6, results)) + if (run_test(server_v6, results, xdp)) goto err; printf("ok\n"); -- GitLab From bf8ff0f8cfd73e850c01b453ddb79609bd83279c Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 30 Jul 2019 11:05:41 -0700 Subject: [PATCH 1350/7155] selftests/bpf: fix clearing buffered output between tests/subtests Clear buffered output once test or subtests finishes even if test was successful. Not doing this leads to accumulation of output from previous tests and on first failed tests lots of irrelevant output will be dumped, greatly confusing things. v1->v2: fix Fixes tag, add more context to patch Fixes: 3a516a0a3a7b ("selftests/bpf: add sub-tests support for test_progs") Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 546d99b3ec34..db00196c8315 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -46,8 +46,8 @@ static void dump_test_log(const struct prog_test_def *test, bool failed) if (env.log_buf[env.log_cnt - 1] != '\n') fprintf(stdout, "\n"); } - env.log_cnt = 0; } + env.log_cnt = 0; } void test__end_subtest() -- GitLab From a98bf57391a24a68ec8381b9d35b60c2bee79150 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 30 Jul 2019 14:03:00 -0700 Subject: [PATCH 1351/7155] tools: bpftool: add support for reporting the effective cgroup progs Takshak said in the original submission: With different bpf attach_flags available to attach bpf programs specially with BPF_F_ALLOW_OVERRIDE and BPF_F_ALLOW_MULTI, the list of effective bpf-programs available to any sub-cgroups really needs to be available for easy debugging. Using BPF_F_QUERY_EFFECTIVE flag, one can get the list of not only attached bpf-programs to a cgroup but also the inherited ones from parent cgroup. So a new option is introduced to use BPF_F_QUERY_EFFECTIVE query flag here to list all the effective bpf-programs available for execution at a specified cgroup. Reused modified test program test_cgroup_attach from tools/testing/selftests/bpf: # ./test_cgroup_attach With old bpftool: # bpftool cgroup show /sys/fs/cgroup/cgroup-test-work-dir/cg1/ ID AttachType AttachFlags Name 271 egress multi pkt_cntr_1 272 egress multi pkt_cntr_2 Attached new program pkt_cntr_4 in cg2 gives following: # bpftool cgroup show /sys/fs/cgroup/cgroup-test-work-dir/cg1/cg2 ID AttachType AttachFlags Name 273 egress override pkt_cntr_4 And with new "effective" option it shows all effective programs for cg2: # bpftool cgroup show /sys/fs/cgroup/cgroup-test-work-dir/cg1/cg2 effective ID AttachType AttachFlags Name 273 egress override pkt_cntr_4 271 egress override pkt_cntr_1 272 egress override pkt_cntr_2 Compared to original submission use a local flag instead of global option. We need to clear query_flags on every command, in case batch mode wants to use varying settings. v2: (Takshak) - forbid duplicated flags; - fix cgroup path freeing. Signed-off-by: Takshak Chahande Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Reviewed-by: Takshak Chahande Signed-off-by: Alexei Starovoitov --- .../bpftool/Documentation/bpftool-cgroup.rst | 16 +++- tools/bpf/bpftool/bash-completion/bpftool | 15 ++-- tools/bpf/bpftool/cgroup.c | 83 ++++++++++++------- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst index 585f270c2d25..06a28b07787d 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst @@ -20,8 +20,8 @@ SYNOPSIS CGROUP COMMANDS =============== -| **bpftool** **cgroup { show | list }** *CGROUP* -| **bpftool** **cgroup tree** [*CGROUP_ROOT*] +| **bpftool** **cgroup { show | list }** *CGROUP* [**effective**] +| **bpftool** **cgroup tree** [*CGROUP_ROOT*] [**effective**] | **bpftool** **cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*] | **bpftool** **cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG* | **bpftool** **cgroup help** @@ -35,13 +35,17 @@ CGROUP COMMANDS DESCRIPTION =========== - **bpftool cgroup { show | list }** *CGROUP* + **bpftool cgroup { show | list }** *CGROUP* [**effective**] List all programs attached to the cgroup *CGROUP*. Output will start with program ID followed by attach type, attach flags and program name. - **bpftool cgroup tree** [*CGROUP_ROOT*] + If **effective** is specified retrieve effective programs that + will execute for events within a cgroup. This includes + inherited along with attached ones. + + **bpftool cgroup tree** [*CGROUP_ROOT*] [**effective**] Iterate over all cgroups in *CGROUP_ROOT* and list all attached programs. If *CGROUP_ROOT* is not specified, bpftool uses cgroup v2 mountpoint. @@ -50,6 +54,10 @@ DESCRIPTION commands: it starts with absolute cgroup path, followed by program ID, attach type, attach flags and program name. + If **effective** is specified retrieve effective programs that + will execute for events within a cgroup. This includes + inherited along with attached ones. + **bpftool cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*] Attach program *PROG* to the cgroup *CGROUP* with attach type *ATTACH_TYPE* and optional *ATTACH_FLAGS*. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 6b961a5ed100..df16c5415444 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -710,12 +710,15 @@ _bpftool() ;; cgroup) case $command in - show|list) - _filedir - return 0 - ;; - tree) - _filedir + show|list|tree) + case $cword in + 3) + _filedir + ;; + 4) + COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) + ;; + esac return 0 ;; attach|detach) diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c index f3c05b08c68c..44352b5aca85 100644 --- a/tools/bpf/bpftool/cgroup.c +++ b/tools/bpf/bpftool/cgroup.c @@ -29,6 +29,8 @@ " recvmsg4 | recvmsg6 | sysctl |\n" \ " getsockopt | setsockopt }" +static unsigned int query_flags; + static const char * const attach_type_strings[] = { [BPF_CGROUP_INET_INGRESS] = "ingress", [BPF_CGROUP_INET_EGRESS] = "egress", @@ -107,7 +109,8 @@ static int count_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type) __u32 prog_cnt = 0; int ret; - ret = bpf_prog_query(cgroup_fd, type, 0, NULL, NULL, &prog_cnt); + ret = bpf_prog_query(cgroup_fd, type, query_flags, NULL, + NULL, &prog_cnt); if (ret) return -1; @@ -125,8 +128,8 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, int ret; prog_cnt = ARRAY_SIZE(prog_ids); - ret = bpf_prog_query(cgroup_fd, type, 0, &attach_flags, prog_ids, - &prog_cnt); + ret = bpf_prog_query(cgroup_fd, type, query_flags, &attach_flags, + prog_ids, &prog_cnt); if (ret) return ret; @@ -158,20 +161,34 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, static int do_show(int argc, char **argv) { enum bpf_attach_type type; + const char *path; int cgroup_fd; int ret = -1; - if (argc < 1) { - p_err("too few parameters for cgroup show"); - goto exit; - } else if (argc > 1) { - p_err("too many parameters for cgroup show"); - goto exit; + query_flags = 0; + + if (!REQ_ARGS(1)) + return -1; + path = GET_ARG(); + + while (argc) { + if (is_prefix(*argv, "effective")) { + if (query_flags & BPF_F_QUERY_EFFECTIVE) { + p_err("duplicated argument: %s", *argv); + return -1; + } + query_flags |= BPF_F_QUERY_EFFECTIVE; + NEXT_ARG(); + } else { + p_err("expected no more arguments, 'effective', got: '%s'?", + *argv); + return -1; + } } - cgroup_fd = open(argv[0], O_RDONLY); + cgroup_fd = open(path, O_RDONLY); if (cgroup_fd < 0) { - p_err("can't open cgroup %s", argv[0]); + p_err("can't open cgroup %s", path); goto exit; } @@ -294,26 +311,37 @@ static char *find_cgroup_root(void) static int do_show_tree(int argc, char **argv) { - char *cgroup_root; + char *cgroup_root, *cgroup_alloced = NULL; int ret; - switch (argc) { - case 0: - cgroup_root = find_cgroup_root(); - if (!cgroup_root) { + query_flags = 0; + + if (!argc) { + cgroup_alloced = find_cgroup_root(); + if (!cgroup_alloced) { p_err("cgroup v2 isn't mounted"); return -1; } - break; - case 1: - cgroup_root = argv[0]; - break; - default: - p_err("too many parameters for cgroup tree"); - return -1; + cgroup_root = cgroup_alloced; + } else { + cgroup_root = GET_ARG(); + + while (argc) { + if (is_prefix(*argv, "effective")) { + if (query_flags & BPF_F_QUERY_EFFECTIVE) { + p_err("duplicated argument: %s", *argv); + return -1; + } + query_flags |= BPF_F_QUERY_EFFECTIVE; + NEXT_ARG(); + } else { + p_err("expected no more arguments, 'effective', got: '%s'?", + *argv); + return -1; + } + } } - if (json_output) jsonw_start_array(json_wtr); else @@ -338,8 +366,7 @@ static int do_show_tree(int argc, char **argv) if (json_output) jsonw_end_array(json_wtr); - if (argc == 0) - free(cgroup_root); + free(cgroup_alloced); return ret; } @@ -459,8 +486,8 @@ static int do_help(int argc, char **argv) } fprintf(stderr, - "Usage: %s %s { show | list } CGROUP\n" - " %s %s tree [CGROUP_ROOT]\n" + "Usage: %s %s { show | list } CGROUP [**effective**]\n" + " %s %s tree [CGROUP_ROOT] [**effective**]\n" " %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n" " %s %s detach CGROUP ATTACH_TYPE PROG\n" " %s %s help\n" -- GitLab From 9a675a13c3bbb6ff46414b4ffaca5fa6bb54b62a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 07:28:04 +0200 Subject: [PATCH 1352/7155] Revert "staging: kpc2000: Convert put_page() to put_user_page*()" This reverts commit 8e7cb7352ec85e9e4fbbd7bfe6c5c5a6806f70e3. Bharath writes: Could you drop this patch from the staging-next tree? This is because John is making some changes to the put_user_page*() functions. He has submitted a patch recently removing put_user_page_dirty() function which is being used in this patch. This might break the kernel build if John's patch gets merged in. I ll submit a patch once the put_user_page*() apis are fixed. Reported-by: Bharath Vedartham Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/fileops.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index f15e29209d55..48ca88bc6b0b 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -190,7 +190,9 @@ static int kpc_dma_transfer(struct dev_private_data *priv, sg_free_table(&acd->sgt); err_dma_map_sg: err_alloc_sg_table: - put_user_pages(acd->user_pages, acd->page_count); + for (i = 0 ; i < acd->page_count ; i++) { + put_page(acd->user_pages[i]); + } err_get_user_pages: kfree(acd->user_pages); err_alloc_userpages: @@ -209,13 +211,16 @@ void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) BUG_ON(acd->ldev == NULL); BUG_ON(acd->ldev->pldev == NULL); + for (i = 0 ; i < acd->page_count ; i++) { + if (!PageReserved(acd->user_pages[i])) { + set_page_dirty(acd->user_pages[i]); + } + } + dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - for (i = 0; i < acd->page_count; i++) { - if (!PageReserved(acd->user_pages[i])) - put_user_pages_dirty(&acd->user_pages[i], 1); - else - put_user_page(acd->user_pages[i]); + for (i = 0 ; i < acd->page_count ; i++) { + put_page(acd->user_pages[i]); } sg_free_table(&acd->sgt); -- GitLab From f12cac539fe07fe410f2776993e85d343c665141 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 30 Jul 2019 15:32:05 +0100 Subject: [PATCH 1353/7155] mac80211: add missing null return check from call to ieee80211_get_sband The return from ieee80211_get_sband can potentially be a null pointer, so it seems prudent to add a null check to avoid a null pointer dereference on sband. Addresses-Coverity: ("Dereference null return") Fixes: 2ab45876756f ("mac80211: add support for the ADDBA extension element") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190730143205.14261-1-colin.king@canonical.com Signed-off-by: Johannes Berg --- net/mac80211/agg-rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 0e1bb43973b8..4d1c335e06e5 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -189,6 +189,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, u8 *pos; sband = ieee80211_get_sband(sdata); + if (!sband) + return; he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type); if (!he_cap) return; -- GitLab From 05d610af3e71a782fa28a1351b687da982d208ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Jul 2019 18:06:05 +0200 Subject: [PATCH 1354/7155] mac80211_hwsim: fill boottime_ns in netlink RX path Give a proper boottime_ns value for netlink RX to avoid scan issues here. Signed-off-by: Johannes Berg Link: https://lore.kernel.org/r/20190729160605.1074-1-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 23692229dacf..3aeff7a3c3d8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -3228,6 +3228,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, { struct mac80211_hwsim_data *data2; struct ieee80211_rx_status rx_status; + struct ieee80211_hdr *hdr; const u8 *dst; int frame_data_len; void *frame_data; @@ -3294,6 +3295,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); + hdr = (void *)skb->data; + + if (ieee80211_is_beacon(hdr->frame_control) || + ieee80211_is_probe_resp(hdr->frame_control)) + rx_status.boottime_ns = ktime_get_boottime_ns(); + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); data2->rx_pkts++; data2->rx_bytes += skb->len; -- GitLab From 50508d941c180a105fdba802d5af1abf3d93a625 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Jul 2019 16:31:09 +0200 Subject: [PATCH 1355/7155] cfg80211: use parallel_ops for genl Over time, we really need to get rid of all of our global locking. One of the things needed is to use parallel_ops. This isn't really the most important (RTNL is much more important) but OTOH we just keep adding uses of genl_family_attrbuf() now. Use .parallel_ops to disallow this. Reviewed-By: Denis Kenzior Link: https://lore.kernel.org/r/20190729143109.18683-1-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 108 +++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 30 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 08a66c1bcb83..1e78ed45a759 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -749,17 +749,25 @@ int nl80211_prepare_wdev_dump(struct netlink_callback *cb, int err; if (!cb->args[0]) { + struct nlattr **attrbuf; + + attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), + GFP_KERNEL); + if (!attrbuf) + return -ENOMEM; + err = nlmsg_parse_deprecated(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, - genl_family_attrbuf(&nl80211_fam), - nl80211_fam.maxattr, + attrbuf, nl80211_fam.maxattr, nl80211_policy, NULL); - if (err) + if (err) { + kfree(attrbuf); return err; + } - *wdev = __cfg80211_wdev_from_attrs( - sock_net(cb->skb->sk), - genl_family_attrbuf(&nl80211_fam)); + *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk), + attrbuf); + kfree(attrbuf); if (IS_ERR(*wdev)) return PTR_ERR(*wdev); *rdev = wiphy_to_rdev((*wdev)->wiphy); @@ -2390,14 +2398,21 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb, struct netlink_callback *cb, struct nl80211_dump_wiphy_state *state) { - struct nlattr **tb = genl_family_attrbuf(&nl80211_fam); - int ret = nlmsg_parse_deprecated(cb->nlh, - GENL_HDRLEN + nl80211_fam.hdrsize, - tb, nl80211_fam.maxattr, - nl80211_policy, NULL); + struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL); + int ret; + + if (!tb) + return -ENOMEM; + + ret = nlmsg_parse_deprecated(cb->nlh, + GENL_HDRLEN + nl80211_fam.hdrsize, + tb, nl80211_fam.maxattr, + nl80211_policy, NULL); /* ignore parse errors for backward compatibility */ - if (ret) - return 0; + if (ret) { + ret = 0; + goto out; + } state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; if (tb[NL80211_ATTR_WIPHY]) @@ -2410,8 +2425,10 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb, int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); netdev = __dev_get_by_index(sock_net(skb->sk), ifidx); - if (!netdev) - return -ENODEV; + if (!netdev) { + ret = -ENODEV; + goto out; + } if (netdev->ieee80211_ptr) { rdev = wiphy_to_rdev( netdev->ieee80211_ptr->wiphy); @@ -2419,7 +2436,10 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb, } } - return 0; + ret = 0; +out: + kfree(tb); + return ret; } static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) @@ -8724,7 +8744,7 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) { - struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam); + struct nlattr **attrbuf; struct survey_info survey; struct cfg80211_registered_device *rdev; struct wireless_dev *wdev; @@ -8732,6 +8752,10 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) int res; bool radio_stats; + attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL); + if (!attrbuf) + return -ENOMEM; + rtnl_lock(); res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); if (res) @@ -8776,6 +8800,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) cb->args[2] = survey_idx; res = skb->len; out_err: + kfree(attrbuf); rtnl_unlock(); return res; } @@ -9635,6 +9660,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct cfg80211_registered_device *rdev; + struct nlattr **attrbuf = NULL; int err; long phy_idx; void *data = NULL; @@ -9655,7 +9681,12 @@ static int nl80211_testmode_dump(struct sk_buff *skb, goto out_err; } } else { - struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam); + attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), + GFP_KERNEL); + if (!attrbuf) { + err = -ENOMEM; + goto out_err; + } err = nlmsg_parse_deprecated(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, @@ -9722,6 +9753,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, /* see above */ cb->args[0] = phy_idx + 1; out_err: + kfree(attrbuf); rtnl_unlock(); return err; } @@ -12815,7 +12847,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, struct cfg80211_registered_device **rdev, struct wireless_dev **wdev) { - struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam); + struct nlattr **attrbuf; u32 vid, subcmd; unsigned int i; int vcmd_idx = -1; @@ -12846,24 +12878,32 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, return 0; } + attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL); + if (!attrbuf) + return -ENOMEM; + err = nlmsg_parse_deprecated(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, attrbuf, nl80211_fam.maxattr, nl80211_policy, NULL); if (err) - return err; + goto out; if (!attrbuf[NL80211_ATTR_VENDOR_ID] || - !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) - return -EINVAL; + !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) { + err = -EINVAL; + goto out; + } *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf); if (IS_ERR(*wdev)) *wdev = NULL; *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf); - if (IS_ERR(*rdev)) - return PTR_ERR(*rdev); + if (IS_ERR(*rdev)) { + err = PTR_ERR(*rdev); + goto out; + } vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]); subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); @@ -12876,15 +12916,19 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) continue; - if (!vcmd->dumpit) - return -EOPNOTSUPP; + if (!vcmd->dumpit) { + err = -EOPNOTSUPP; + goto out; + } vcmd_idx = i; break; } - if (vcmd_idx < 0) - return -EOPNOTSUPP; + if (vcmd_idx < 0) { + err = -EOPNOTSUPP; + goto out; + } if (attrbuf[NL80211_ATTR_VENDOR_DATA]) { data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]); @@ -12895,7 +12939,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, attrbuf[NL80211_ATTR_VENDOR_DATA], cb->extack); if (err) - return err; + goto out; } /* 0 is the first index - add 1 to parse only once */ @@ -12907,7 +12951,10 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, cb->args[4] = data_len; /* keep rtnl locked in successful case */ - return 0; + err = 0; +out: + kfree(attrbuf); + return err; } static int nl80211_vendor_cmd_dump(struct sk_buff *skb, @@ -14585,6 +14632,7 @@ static struct genl_family nl80211_fam __ro_after_init = { .n_ops = ARRAY_SIZE(nl80211_ops), .mcgrps = nl80211_mcgrps, .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps), + .parallel_ops = true, }; /* notification functions */ -- GitLab From 52dba8d7d5aba65f818bd27603ae10ebc006ab3b Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Wed, 24 Jul 2019 14:46:10 +0530 Subject: [PATCH 1356/7155] mac80211: reject zero MAC address in add station This came up in fuzz testing, and really we don't consider all-zeroes to be a valid MAC address in most places, so also reject it here to avoid confusion later on. Signed-off-by: Karthikeyan Periyasamy Link: https://lore.kernel.org/r/1563959770-21570-1-git-send-email-periyasa@codeaurora.org [rewrite commit message] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4d458067d80d..10b99b263c4f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1543,7 +1543,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, if (ether_addr_equal(mac, sdata->vif.addr)) return -EINVAL; - if (is_multicast_ether_addr(mac)) + if (!is_valid_ether_addr(mac)) return -EINVAL; sta = sta_info_alloc(sdata, mac, GFP_KERNEL); -- GitLab From 796e90f42b7e52cf1c88e978e1d5ee69c102d85d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 30 Jul 2019 18:37:00 +0200 Subject: [PATCH 1357/7155] cfg80211: add support for parsing OBBS_PD attributes Add the data structure, policy and parsing code allowing userland to send the OBSS PD information into the kernel. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190730163701.18836-2-john@phrozen.org Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 15 ++++++++++++ include/uapi/linux/nl80211.h | 27 ++++++++++++++++++++++ net/wireless/nl80211.c | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 45850a8391d9..35ec1f0a2bf9 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -246,6 +246,19 @@ struct ieee80211_rate { u16 hw_value, hw_value_short; }; +/** + * struct ieee80211_he_obss_pd - AP settings for spatial reuse + * + * @enable: is the feature enabled. + * @min_offset: minimal tx power offset an associated station shall use + * @max_offset: maximum tx power offset an associated station shall use + */ +struct ieee80211_he_obss_pd { + bool enable; + u8 min_offset; + u8 max_offset; +}; + /** * struct ieee80211_sta_ht_cap - STA's HT capabilities * @@ -896,6 +909,7 @@ enum cfg80211_ap_settings_flags { * @vht_required: stations must support VHT * @twt_responder: Enable Target Wait Time * @flags: flags, as defined in enum cfg80211_ap_settings_flags + * @he_obss_pd: OBSS Packet Detection settings */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; @@ -923,6 +937,7 @@ struct cfg80211_ap_settings { bool ht_required, vht_required; bool twt_responder; u32 flags; + struct ieee80211_he_obss_pd he_obss_pd; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c45587c2cf44..822851d369ab 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2358,6 +2358,9 @@ enum nl80211_commands { * * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. * + * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection + * functionality. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2815,6 +2818,8 @@ enum nl80211_attrs { NL80211_ATTR_TWT_RESPONDER, + NL80211_ATTR_HE_OBSS_PD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -6490,4 +6495,26 @@ enum nl80211_peer_measurement_ftm_resp { NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1 }; +/** + * enum nl80211_obss_pd_attributes - OBSS packet detection attributes + * @__NL80211_HE_OBSS_PD_ATTR_INVALID: Invalid + * + * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * + * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal + * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. + */ +enum nl80211_obss_pd_attributes { + __NL80211_HE_OBSS_PD_ATTR_INVALID, + + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + + /* keep last */ + __NL80211_HE_OBSS_PD_ATTR_LAST, + NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, +}; + + #endif /* __LINUX_NL80211_H */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1e78ed45a759..3006cfce7158 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -281,6 +281,14 @@ nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = { NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy), }; +static const struct nla_policy +he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = { + [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] = + NLA_POLICY_RANGE(NLA_U8, 1, 20), + [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] = + NLA_POLICY_RANGE(NLA_U8, 1, 20), +}; + const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, @@ -574,6 +582,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY, .len = SAE_PASSWORD_MAX_LEN }, [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG }, + [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy), }; /* policy for the key attributes */ @@ -4405,6 +4414,34 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, return 0; } +static int nl80211_parse_he_obss_pd(struct nlattr *attrs, + struct ieee80211_he_obss_pd *he_obss_pd) +{ + struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1]; + int err; + + err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs, + he_obss_pd_policy, NULL); + if (err) + return err; + + if (!tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] || + !tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]) + return -EINVAL; + + he_obss_pd->min_offset = + nla_get_u32(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]); + he_obss_pd->max_offset = + nla_get_u32(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]); + + if (he_obss_pd->min_offset >= he_obss_pd->max_offset) + return -EINVAL; + + he_obss_pd->enable = true; + + return 0; +} + static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params, const u8 *rates) { @@ -4689,6 +4726,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.twt_responder = nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]); + if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) { + err = nl80211_parse_he_obss_pd( + info->attrs[NL80211_ATTR_HE_OBSS_PD], + ¶ms.he_obss_pd); + if (err) + return err; + } + nl80211_calculate_ap_params(¶ms); if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT]) -- GitLab From 6d4dd4ef1a23cd2130d5c256aa698bf7e24d1e31 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Jul 2019 10:58:20 +0200 Subject: [PATCH 1358/7155] nl80211: add strict start type Add a strict start type so all new attributes starting from NL80211_ATTR_HE_OBSS_PD are validated strictly. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3006cfce7158..1a107f29016b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -290,6 +290,7 @@ he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = { }; const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, .len = 20-1 }, -- GitLab From 1ced169cc1c2f3e054fa14974443383ee02a8b6a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 30 Jul 2019 18:37:01 +0200 Subject: [PATCH 1359/7155] mac80211: allow setting spatial reuse parameters from bss_conf Store the OBSS PD parameters inside bss_conf when bringing up an AP and/or when a station connects to an AP. This allows the driver to configure the HW accordingly. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190730163701.18836-3-john@phrozen.org Signed-off-by: Johannes Berg --- include/net/mac80211.h | 4 ++++ net/mac80211/cfg.c | 5 ++++- net/mac80211/he.c | 24 ++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/mlme.c | 1 + 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bd91388797fc..6781d4637557 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -315,6 +315,7 @@ struct ieee80211_vif_chanctx_switch { * @BSS_CHANGED_FTM_RESPONDER: fime timing reasurement request responder * functionality changed for this BSS (AP mode). * @BSS_CHANGED_TWT: TWT status changed + * @BSS_CHANGED_HE_OBSS_PD: OBSS Packet Detection status changed. * */ enum ieee80211_bss_change { @@ -346,6 +347,7 @@ enum ieee80211_bss_change { BSS_CHANGED_MCAST_RATE = 1<<25, BSS_CHANGED_FTM_RESPONDER = 1<<26, BSS_CHANGED_TWT = 1<<27, + BSS_CHANGED_HE_OBSS_PD = 1<<28, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -601,6 +603,7 @@ struct ieee80211_ftm_responder_params { * @profile_periodicity: the least number of beacon frames need to be received * in order to discover all the nontransmitted BSSIDs in the set. * @he_operation: HE operation information of the AP we are connected to + * @he_obss_pd: OBSS Packet Detection parameters. */ struct ieee80211_bss_conf { const u8 *bssid; @@ -663,6 +666,7 @@ struct ieee80211_bss_conf { bool ema_ap; u8 profile_periodicity; struct ieee80211_he_operation he_operation; + struct ieee80211_he_obss_pd he_obss_pd; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 10b99b263c4f..ed56b0c6fe19 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -980,7 +980,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS | BSS_CHANGED_TXPOWER | - BSS_CHANGED_TWT; + BSS_CHANGED_TWT | + BSS_CHANGED_HE_OBSS_PD; int err; int prev_beacon_int; @@ -1051,6 +1052,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, sdata->vif.bss_conf.enable_beacon = true; sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p; sdata->vif.bss_conf.twt_responder = params->twt_responder; + memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd, + sizeof(struct ieee80211_he_obss_pd)); sdata->vif.bss_conf.ssid_len = params->ssid_len; if (params->ssid_len) diff --git a/net/mac80211/he.c b/net/mac80211/he.c index f910f730ad0d..a02abfc424aa 100644 --- a/net/mac80211/he.c +++ b/net/mac80211/he.c @@ -65,3 +65,27 @@ ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif, vif->bss_conf.he_operation = *he_op_ie_elem; } + +void +ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif, + const struct ieee80211_he_spr *he_spr_ie_elem) +{ + struct ieee80211_he_obss_pd *he_obss_pd = + &vif->bss_conf.he_obss_pd; + const u8 *data = he_spr_ie_elem->optional; + + memset(he_obss_pd, 0, sizeof(*he_obss_pd)); + + if (!he_spr_ie_elem) + return; + + if (he_spr_ie_elem->he_sr_control & + IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + data++; + if (he_spr_ie_elem->he_sr_control & + IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) { + he_obss_pd->max_offset = *data++; + he_obss_pd->min_offset = *data++; + he_obss_pd->enable = true; + } +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 38769f5c3da4..791ce58d0f09 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1873,6 +1873,9 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, const u8 *he_cap_ie, u8 he_cap_len, struct sta_info *sta); +void +ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif, + const struct ieee80211_he_spr *he_spr_ie_elem); void ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2b8a7428973d..225633d9e2d4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3382,6 +3382,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, bss_conf->uora_ocw_range = elems.uora_element[0]; ieee80211_he_op_ie_to_bss_conf(&sdata->vif, elems.he_operation); + ieee80211_he_spr_ie_to_bss_conf(&sdata->vif, elems.he_spr); /* TODO: OPEN: what happens if BSS color disable is set? */ } -- GitLab From 61059b7048ee1d635673f3014ea9f7e3e4b1532f Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Wed, 31 Jul 2019 17:47:54 +0800 Subject: [PATCH 1360/7155] gpio: ixp4xx: remove redundant dev_err message devm_ioremap_resource already contains error message, so remove the redundant dev_err message Signed-off-by: Ding Xiang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ixp4xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 670c2a85a35b..2b2b89b6cd18 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -321,10 +321,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); g->base = devm_ioremap_resource(dev, res); - if (IS_ERR(g->base)) { - dev_err(dev, "ioremap error\n"); + if (IS_ERR(g->base)) return PTR_ERR(g->base); - } /* * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on -- GitLab From 7dcddef6f769d7e60691c732eb6d09cdb1d9df76 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 31 Jul 2019 15:29:52 +1000 Subject: [PATCH 1361/7155] cpuidle: header file stubs must be "static inline" An x86_64 allmodconfig build produces these errors: x86_64-linux-gnu-ld: kernel/sched/core.o: in function `cpuidle_poll_time': core.c:(.text+0x230): multiple definition of `cpuidle_poll_time'; arch/x86/= kernel/process.o:process.c:(.text+0xc0): first defined here (and more) Fixes: 259231a04561 ("cpuidle: add poll_limit_ns to cpuidle_device structure") Signed-off-by: Stephen Rothwell Signed-off-by: Rafael J. Wysocki --- include/linux/cpuidle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index ba535a1a47d5..1a9f54eb3aa1 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -170,7 +170,7 @@ static inline int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) {return -ENODEV; } static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } -extern u64 cpuidle_poll_time(struct cpuidle_driver *drv, +static inline u64 cpuidle_poll_time(struct cpuidle_driver *drv, struct cpuidle_device *dev) {return 0; } static inline int cpuidle_register_driver(struct cpuidle_driver *drv) -- GitLab From 931c940fa5643d3d8cd62ba7bfa0c61077eb7b59 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 26 Jul 2019 21:19:04 +0300 Subject: [PATCH 1362/7155] crypto: s390/aes - fix name clash after AES library refactor The newly introduced AES library exposes aes_encrypt/aes_decrypt routines so rename existing occurrences of those identifiers in the s390 driver. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/s390/crypto/aes_s390.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index d00f84add5f4..dc0f72dd6e03 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -108,7 +108,7 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, return 0; } -static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); @@ -119,7 +119,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) cpacf_km(sctx->fc, &sctx->key, out, in, AES_BLOCK_SIZE); } -static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); @@ -172,8 +172,8 @@ static struct crypto_alg aes_alg = { .cia_min_keysize = AES_MIN_KEY_SIZE, .cia_max_keysize = AES_MAX_KEY_SIZE, .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt, + .cia_encrypt = crypto_aes_encrypt, + .cia_decrypt = crypto_aes_decrypt, } } }; -- GitLab From 2c4956bc1e9062e5e3c5ea7612294f24e6d4fbdd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 29 Jul 2019 10:01:39 +0200 Subject: [PATCH 1363/7155] ASoC: meson: g12a-tohdmitx: override codec2codec params So far, forwarding the hw_params of the input to output relied on the .hw_params() callback of the cpu side of the codec2codec link to be called first. This is a bit weak. Instead, override the stream params of the codec2codec to link to set it up correctly. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190729080139.32068-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/g12a-tohdmitx.c | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c index 707ccb192e4c..9943c807ec5d 100644 --- a/sound/soc/meson/g12a-tohdmitx.c +++ b/sound/soc/meson/g12a-tohdmitx.c @@ -28,7 +28,7 @@ #define CTRL0_SPDIF_CLK_SEL BIT(0) struct g12a_tohdmitx_input { - struct snd_pcm_hw_params params; + struct snd_soc_pcm_stream params; unsigned int fmt; }; @@ -225,26 +225,17 @@ static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream, { struct g12a_tohdmitx_input *data = dai->playback_dma_data; - /* Save the stream params for the downstream link */ - memcpy(&data->params, params, sizeof(*params)); + data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); + data->params.rate_min = params_rate(params); + data->params.rate_max = params_rate(params); + data->params.formats = 1 << params_format(params); + data->params.channels_min = params_channels(params); + data->params.channels_max = params_channels(params); + data->params.sig_bits = dai->driver->playback.sig_bits; return 0; } -static int g12a_tohdmitx_output_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct g12a_tohdmitx_input *in_data = - g12a_tohdmitx_get_input_data(dai->capture_widget); - - if (!in_data) - return -ENODEV; - - memcpy(params, &in_data->params, sizeof(*params)); - - return 0; -} static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) @@ -266,6 +257,14 @@ static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream, if (!in_data) return -ENODEV; + if (WARN_ON(!rtd->dai_link->params)) { + dev_warn(dai->dev, "codec2codec link expected\n"); + return -EINVAL; + } + + /* Replace link params with the input params */ + rtd->dai_link->params = &in_data->params; + if (!in_data->fmt) return 0; @@ -278,7 +277,6 @@ static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = { }; static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { - .hw_params = g12a_tohdmitx_output_hw_params, .startup = g12a_tohdmitx_output_startup, }; -- GitLab From 21cc4ea85879c1b424fb01caa6e481c14286f7f0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:05 +0800 Subject: [PATCH 1364/7155] ASoC: tegra20_das: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-2-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_das.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index 10f9c3b19c88..1070b2710d5e 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -120,7 +120,6 @@ static const struct regmap_config tegra20_das_regmap_config = { static int tegra20_das_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *regs; int ret = 0; @@ -134,8 +133,7 @@ static int tegra20_das_probe(struct platform_device *pdev) } das->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) { ret = PTR_ERR(regs); goto err; -- GitLab From 7d22808641cdea50baeae636acf5d592a7aa1239 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:06 +0800 Subject: [PATCH 1365/7155] ASoC: tegra: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-3-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index ac6983c6bd72..e6d548fa980b 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -368,7 +368,6 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) struct tegra30_i2s *i2s; const struct of_device_id *match; u32 cif_ids[2]; - struct resource *mem; void __iomem *regs; int ret; @@ -406,8 +405,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) goto err; } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, mem); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) { ret = PTR_ERR(regs); goto err_clk_put; -- GitLab From f052172a5bb474fef2d0c3911655c9e107a3c024 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:07 +0800 Subject: [PATCH 1366/7155] ASoC: rockchip: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-4-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rk3328_codec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 24f8f86d58e9..287c962ba00d 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -432,7 +432,6 @@ static int rk3328_platform_probe(struct platform_device *pdev) { struct device_node *rk3328_np = pdev->dev.of_node; struct rk3328_codec_priv *rk3328; - struct resource *res; struct regmap *grf; void __iomem *base; int ret = 0; @@ -482,8 +481,7 @@ static int rk3328_platform_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 4b3540074361fc7b97f2da54365c55ceca6333d2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:08 +0800 Subject: [PATCH 1367/7155] ASoC: ep93xx-i2s: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-5-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 0b4355e95f84..7d9cf67129d4 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -430,15 +430,13 @@ static const struct snd_soc_component_driver ep93xx_i2s_component = { static int ep93xx_i2s_probe(struct platform_device *pdev) { struct ep93xx_i2s_info *info; - struct resource *res; int err; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->regs = devm_ioremap_resource(&pdev->dev, res); + info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) return PTR_ERR(info->regs); -- GitLab From fceef72b68d63593d8543a8d608ccc8427e13d56 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:09 +0800 Subject: [PATCH 1368/7155] ASoC: mt8173: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-6-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 0382896c162e..90bd2c92cae7 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1056,7 +1056,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) int irq_id; struct mtk_base_afe *afe; struct mt8173_afe_private *afe_priv; - struct resource *res; ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); if (ret) @@ -1086,8 +1085,7 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - afe->base_addr = devm_ioremap_resource(&pdev->dev, res); + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(afe->base_addr)) return PTR_ERR(afe->base_addr); -- GitLab From 61e799e3658952397da80f6c2e3581e7b65209a8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:10 +0800 Subject: [PATCH 1369/7155] ASoC: mt6797: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-7-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 08a6532da322..e52c032d53aa 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -749,7 +749,6 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) { struct mtk_base_afe *afe; struct mt6797_afe_private *afe_priv; - struct resource *res; struct device *dev; int i, irq_id, ret; @@ -774,9 +773,7 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) } /* regmap init */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - afe->base_addr = devm_ioremap_resource(&pdev->dev, res); + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(afe->base_addr)) return PTR_ERR(afe->base_addr); -- GitLab From d003e3081c1d069b94d1b5f4c3bc8234d4603282 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:11 +0800 Subject: [PATCH 1370/7155] ASoC: imx-audmux: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-8-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index b2351cd33b0f..7595f24a006e 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -298,12 +298,10 @@ static int imx_audmux_parse_dt_defaults(struct platform_device *pdev, static int imx_audmux_probe(struct platform_device *pdev) { - struct resource *res; const struct of_device_id *of_id = of_match_device(imx_audmux_dt_ids, &pdev->dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - audmux_base = devm_ioremap_resource(&pdev->dev, res); + audmux_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(audmux_base)) return PTR_ERR(audmux_base); -- GitLab From 959bb6b54d708652fe06097feecc3acd4d6b8c89 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:12 +0800 Subject: [PATCH 1371/7155] ASoC: fsl_audmix: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-9-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 3897a54a11fe..c7e4e9757dce 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -458,7 +458,6 @@ static int fsl_audmix_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fsl_audmix *priv; - struct resource *res; const char *mdrv; const struct of_device_id *of_id; void __iomem *regs; @@ -475,8 +474,7 @@ static int fsl_audmix_probe(struct platform_device *pdev) return -ENOMEM; /* Get the addresses */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From d400b1b30cbff1c0962bbb3f895e839ccd120cb7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:13 +0800 Subject: [PATCH 1372/7155] ASoC: bcm2835-i2s: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-10-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 5ef80f3d446a..e6a12e271b07 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -828,7 +828,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) { struct bcm2835_i2s_dev *dev; int ret; - struct resource *mem; void __iomem *base; const __be32 *addr; dma_addr_t dma_base; @@ -848,8 +847,7 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) } /* Request ioarea */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From c9dbe688983b1d77a9a46cf6b7ac88348a1ca395 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:14 +0800 Subject: [PATCH 1373/7155] ASoC: sirf: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-11-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sirf/sirf-usp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 8bab119c753a..2af0c6f14ee6 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c @@ -359,7 +359,6 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) int ret; struct sirf_usp *usp; void __iomem *base; - struct resource *mem_res; usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp), GFP_KERNEL); @@ -368,8 +367,7 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, usp); - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem_res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, -- GitLab From 1327bfe2887c0e29bcdc0c5c3e445da107ccb4e2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:15 +0800 Subject: [PATCH 1374/7155] ASoC: mxs-saif: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-12-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 269b6d6df250..a2c79426513b 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -732,7 +732,6 @@ static int mxs_saif_mclk_init(struct platform_device *pdev) static int mxs_saif_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *iores; struct mxs_saif *saif; int irq, ret = 0; struct device_node *master; @@ -786,9 +785,7 @@ static int mxs_saif_probe(struct platform_device *pdev) return ret; } - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - saif->base = devm_ioremap_resource(&pdev->dev, iores); + saif->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(saif->base)) return PTR_ERR(saif->base); -- GitLab From 0fb46f541bb3e6e5bbb155c08b9e75f92c21acb9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:16 +0800 Subject: [PATCH 1375/7155] ASoC: spear: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-13-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/spear/spdif_in.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 78a6a360b4a6..4b68d6ee75da 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c @@ -202,12 +202,11 @@ static int spdif_in_probe(struct platform_device *pdev) { struct spdif_in_dev *host; struct spear_spdif_platform_data *pdata; - struct resource *res, *res_fifo; + struct resource *res_fifo; void __iomem *io_base; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - io_base = devm_ioremap_resource(&pdev->dev, res); + io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(io_base)) return PTR_ERR(io_base); -- GitLab From 89dd38bf130e661d92c6ab7e3b003907f1d3f367 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:17 +0800 Subject: [PATCH 1376/7155] ASoC: kirkwood-i2s: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-14-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3446a113f482..5076ec4cc7a6 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -523,7 +523,6 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai; struct kirkwood_dma_data *priv; - struct resource *mem; struct device_node *np = pdev->dev.of_node; int err; @@ -533,8 +532,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, priv); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->io = devm_ioremap_resource(&pdev->dev, mem); + priv->io = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->io)) return PTR_ERR(priv->io); -- GitLab From ebdd7be5415c7795c77609ad908222038e441835 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:18 +0800 Subject: [PATCH 1377/7155] ASoC: xtfpga-i2s: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-15-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 9ce2c75186b9..9da395d14a8d 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -531,7 +531,6 @@ static int xtfpga_i2s_runtime_resume(struct device *dev) static int xtfpga_i2s_probe(struct platform_device *pdev) { struct xtfpga_i2s *i2s; - struct resource *mem; int err, irq; i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); @@ -543,8 +542,7 @@ static int xtfpga_i2s_probe(struct platform_device *pdev) i2s->dev = &pdev->dev; dev_dbg(&pdev->dev, "dev: %p, i2s: %p\n", &pdev->dev, i2s); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2s->regs = devm_ioremap_resource(&pdev->dev, mem); + i2s->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2s->regs)) { err = PTR_ERR(i2s->regs); goto err; -- GitLab From 22581e7c51f50fbbadba70499bb5e2d09f830cbb Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 17:15:34 -0500 Subject: [PATCH 1378/7155] ASoC: ti: Mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: arm): sound/soc/ti/n810.c: In function ‘n810_ext_control’: sound/soc/ti/n810.c:48:10: warning: this statement may fall through [-Wimplicit-fallthrough=] line1l = 1; ~~~~~~~^~~ sound/soc/ti/n810.c:49:2: note: here case N810_JACK_HP: ^~~~ sound/soc/ti/rx51.c: In function ‘rx51_ext_control’: sound/soc/ti/rx51.c:57:6: warning: this statement may fall through [-Wimplicit-fallthrough=] hs = 1; ~~~^~~ sound/soc/ti/rx51.c:58:2: note: here case RX51_JACK_HP: ^~~~ Signed-off-by: Gustavo A. R. Silva Acked-by: Jarkko Nikula Link: https://lore.kernel.org/r/20190729221534.GA18696@embeddedor Signed-off-by: Mark Brown --- sound/soc/ti/n810.c | 1 + sound/soc/ti/rx51.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index 2c3f2a4c1700..3ad2b6daf31e 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -46,6 +46,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) switch (n810_jack_func) { case N810_JACK_HS: line1l = 1; + /* fall through */ case N810_JACK_HP: hp = 1; break; diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index bc6046534fa5..ccd0e8a07dd1 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -55,6 +55,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; case RX51_JACK_HS: hs = 1; + /* fall through */ case RX51_JACK_HP: hp = 1; break; -- GitLab From 0c03e37af47efcb8600f95f399783c082fcf2f93 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 24 Jul 2019 08:00:23 +0200 Subject: [PATCH 1379/7155] ASoC: cs4271: Fix a typo in the CS4171_NR_RATIOS This should be CS4271_NR_RATIOS. Fix it and use it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190724060023.31302-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 1d03a1348162..04b86a51e055 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -334,7 +334,7 @@ static struct cs4271_clk_cfg cs4271_clk_tab[] = { {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, }; -#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) +#define CS4271_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) static int cs4271_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, @@ -383,13 +383,13 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, val = CS4271_MODE1_MODE_4X; ratio = cs4271->mclk / cs4271->rate; - for (i = 0; i < CS4171_NR_RATIOS; i++) + for (i = 0; i < CS4271_NR_RATIOS; i++) if ((cs4271_clk_tab[i].master == cs4271->master) && (cs4271_clk_tab[i].speed_mode == val) && (cs4271_clk_tab[i].ratio == ratio)) break; - if (i == CS4171_NR_RATIOS) { + if (i == CS4271_NR_RATIOS) { dev_err(component->dev, "Invalid sample rate\n"); return -EINVAL; } -- GitLab From 2e73d98f2ecf61008926bb8a425c3281a89959c0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:31 +0800 Subject: [PATCH 1380/7155] ASoC: meson: axg-pdm: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-28-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-pdm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-pdm.c b/sound/soc/meson/axg-pdm.c index 9d5684493ffc..bfd37d49a73e 100644 --- a/sound/soc/meson/axg-pdm.c +++ b/sound/soc/meson/axg-pdm.c @@ -585,7 +585,6 @@ static int axg_pdm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct axg_pdm *priv; - struct resource *res; void __iomem *regs; int ret; @@ -600,8 +599,7 @@ static int axg_pdm_probe(struct platform_device *pdev) return -ENODEV; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From d61feec0f60c250c786a9e0069ce909979491c7b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:32 +0800 Subject: [PATCH 1381/7155] ASoC: meson: axg-spdifin: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-29-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-spdifin.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-spdifin.c b/sound/soc/meson/axg-spdifin.c index 01b2035fa841..d0d09f945b48 100644 --- a/sound/soc/meson/axg-spdifin.c +++ b/sound/soc/meson/axg-spdifin.c @@ -453,7 +453,6 @@ static int axg_spdifin_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct axg_spdifin *priv; struct snd_soc_dai_driver *dai_drv; - struct resource *res; void __iomem *regs; int ret; @@ -468,8 +467,7 @@ static int axg_spdifin_probe(struct platform_device *pdev) return -ENODEV; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From c43fd289dd58951f3cfddb3bb66a6ed7747c5986 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:33 +0800 Subject: [PATCH 1382/7155] ASoC: meson: axg-spdifout: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-30-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-spdifout.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-spdifout.c b/sound/soc/meson/axg-spdifout.c index 9dea528053ad..7ce6aa97ddf7 100644 --- a/sound/soc/meson/axg-spdifout.c +++ b/sound/soc/meson/axg-spdifout.c @@ -401,7 +401,6 @@ static int axg_spdifout_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct axg_spdifout *priv; - struct resource *res; void __iomem *regs; int ret; @@ -410,8 +409,7 @@ static int axg_spdifout_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, priv); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From 9b2089313156ad16bd257217cc67e10597a82923 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:34 +0800 Subject: [PATCH 1383/7155] ASoC: meson: axg-fifo: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-31-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-fifo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 01c1c7db2510..80a3dde35b5c 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -314,7 +314,6 @@ int axg_fifo_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; const struct axg_fifo_match_data *data; struct axg_fifo *fifo; - struct resource *res; void __iomem *regs; data = of_device_get_match_data(dev); @@ -328,8 +327,7 @@ int axg_fifo_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, fifo); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From cf80aa2c1359f5d014981e251049bcc21a2217bc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:35 +0800 Subject: [PATCH 1384/7155] ASoC: xlnx: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-32-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_i2s.c | 4 +--- sound/soc/xilinx/xlnx_spdif.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/xilinx/xlnx_i2s.c b/sound/soc/xilinx/xlnx_i2s.c index 8b353166ad44..cc641e582c82 100644 --- a/sound/soc/xilinx/xlnx_i2s.c +++ b/sound/soc/xilinx/xlnx_i2s.c @@ -95,7 +95,6 @@ MODULE_DEVICE_TABLE(of, xlnx_i2s_of_match); static int xlnx_i2s_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *base; struct snd_soc_dai_driver *dai_drv; int ret; @@ -107,8 +106,7 @@ static int xlnx_i2s_probe(struct platform_device *pdev) if (!dai_drv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/sound/soc/xilinx/xlnx_spdif.c b/sound/soc/xilinx/xlnx_spdif.c index 3b9000fd8c49..e2ca087adee6 100644 --- a/sound/soc/xilinx/xlnx_spdif.c +++ b/sound/soc/xilinx/xlnx_spdif.c @@ -260,8 +260,7 @@ static int xlnx_spdif_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ctx->base = devm_ioremap_resource(dev, res); + ctx->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ctx->base)) { ret = PTR_ERR(ctx->base); goto clk_err; -- GitLab From e12fd61fd7c1bbbb758ede9fdf58ac2bd5de6b33 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:36 +0800 Subject: [PATCH 1385/7155] ASoC: sun8i-codec-analog: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-33-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec-analog.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index e92aeedd6feb..be872eefa61e 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c @@ -819,12 +819,10 @@ MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match); static int sun8i_codec_analog_probe(struct platform_device *pdev) { - struct resource *res; struct regmap *regmap; void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_err(&pdev->dev, "Failed to map the registers\n"); return PTR_ERR(base); -- GitLab From 54dd39e4aca8edb231e13349ac3a3a44ef28d3d4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:37 +0800 Subject: [PATCH 1386/7155] ASoC: sunxi: sun50i-codec-analog: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-34-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-codec-analog.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index 6d1de565350e..f5b7069bcca2 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -459,12 +459,10 @@ MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match); static int sun50i_codec_analog_probe(struct platform_device *pdev) { - struct resource *res; struct regmap *regmap; void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_err(&pdev->dev, "Failed to map the registers\n"); return PTR_ERR(base); -- GitLab From 790b36578e23264ff05be2ba8466ebcf7d3db38a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:38 +0800 Subject: [PATCH 1387/7155] ASoC: sun8i-codec: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-35-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 0e0e8ebaa571..55798bc8eae2 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -533,7 +533,6 @@ static const struct regmap_config sun8i_codec_regmap_config = { static int sun8i_codec_probe(struct platform_device *pdev) { - struct resource *res_base; struct sun8i_codec *scodec; void __iomem *base; int ret; @@ -556,8 +555,7 @@ static int sun8i_codec_probe(struct platform_device *pdev) return PTR_ERR(scodec->clk_bus); } - res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res_base); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_err(&pdev->dev, "Failed to map the registers\n"); return PTR_ERR(base); -- GitLab From 1c63223cda84fb10643938e4e4eb02110f8ae9a2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:19 +0800 Subject: [PATCH 1388/7155] ASoC: stm32: sai: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-16-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 63f68e663676..1ac5103cea78 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -152,7 +152,6 @@ static int stm32_sai_probe(struct platform_device *pdev) { struct stm32_sai_data *sai; struct reset_control *rst; - struct resource *res; const struct of_device_id *of_id; u32 val; int ret; @@ -161,8 +160,7 @@ static int stm32_sai_probe(struct platform_device *pdev) if (!sai) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sai->base = devm_ioremap_resource(&pdev->dev, res); + sai->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sai->base)) return PTR_ERR(sai->base); -- GitLab From f62d6426718837663484bbf0ed94e56573cbc365 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:20 +0800 Subject: [PATCH 1389/7155] ASoC: codecs: msm8916-wcd: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-17-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-digital.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 1db7e43ec203..9fa5d44fdc79 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -1143,7 +1143,6 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev) struct msm8916_wcd_digital_priv *priv; struct device *dev = &pdev->dev; void __iomem *base; - struct resource *mem_res; struct regmap *digital_map; int ret; @@ -1151,8 +1150,7 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem_res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 94db63761576a98279e19f51173dec85f803bad4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:21 +0800 Subject: [PATCH 1390/7155] ASoC: codecs: jz4725b: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-18-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 766354c73076..2567a5d15b55 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -545,15 +545,13 @@ static int jz4725b_codec_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct jz_icdc *icdc; - struct resource *mem; int ret; icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); if (!icdc) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - icdc->base = devm_ioremap_resource(dev, mem); + icdc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(icdc->base)) return PTR_ERR(icdc->base); -- GitLab From 72d09322e709c5c2d7112d6a19ec9f3846d3609d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:22 +0800 Subject: [PATCH 1391/7155] ASoC: mmp-sspa: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-19-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 72f4364b2d20..e3e5425b5c62 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -399,7 +399,6 @@ static const struct snd_soc_component_driver mmp_sspa_component = { static int asoc_mmp_sspa_probe(struct platform_device *pdev) { struct sspa_priv *priv; - struct resource *res; priv = devm_kzalloc(&pdev->dev, sizeof(struct sspa_priv), GFP_KERNEL); @@ -417,8 +416,7 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) if (priv->dma_params == NULL) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res); + priv->sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->sspa->mmio_base)) return PTR_ERR(priv->sspa->mmio_base); -- GitLab From a8dc106410a2c3c87917447fb8c132b66062443e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:23 +0800 Subject: [PATCH 1392/7155] ASoC: jz4740: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-20-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4740.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 974e17fa1911..460aa1fd1efe 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -318,7 +318,6 @@ static int jz4740_codec_probe(struct platform_device *pdev) { int ret; struct jz4740_codec *jz4740_codec; - struct resource *mem; void __iomem *base; jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), @@ -326,8 +325,7 @@ static int jz4740_codec_probe(struct platform_device *pdev) if (!jz4740_codec) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 2d1ffc7d0f58f6a39a34854e952f5020fc655af0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:24 +0800 Subject: [PATCH 1393/7155] ASoC: inno_rk3036: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-21-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/inno_rk3036.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 7feedbb7bbed..14d8fe1c28a4 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -405,7 +405,6 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) { struct rk3036_codec_priv *priv; struct device_node *of_node = pdev->dev.of_node; - struct resource *res; void __iomem *base; struct regmap *grf; int ret; @@ -414,8 +413,7 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 4e5bc35988af2483138feb3c5c3bf5fb0cae4228 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:25 +0800 Subject: [PATCH 1394/7155] ASoC: uniphier: evea: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-22-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/uniphier/evea.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c index f9c10165fbc1..d27e9ca07856 100644 --- a/sound/soc/uniphier/evea.c +++ b/sound/soc/uniphier/evea.c @@ -451,7 +451,6 @@ static const struct regmap_config evea_regmap_config = { static int evea_probe(struct platform_device *pdev) { struct evea_priv *evea; - struct resource *res; void __iomem *preg; int ret; @@ -475,8 +474,7 @@ static int evea_probe(struct platform_device *pdev) if (IS_ERR(evea->rst_exiv)) return PTR_ERR(evea->rst_exiv); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - preg = devm_ioremap_resource(&pdev->dev, res); + preg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(preg)) return PTR_ERR(preg); -- GitLab From b885c9fa363fa4604d78ea00adfed64db656fb78 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:26 +0800 Subject: [PATCH 1395/7155] ASoC: uniphier: aio-dma: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-23-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-dma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index fa001d3c1a88..862346d66774 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -276,12 +276,10 @@ int uniphier_aiodma_soc_register_platform(struct platform_device *pdev) { struct uniphier_aio_chip *chip = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - struct resource *res; void __iomem *preg; int irq, ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - preg = devm_ioremap_resource(dev, res); + preg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(preg)) return PTR_ERR(preg); -- GitLab From b1abe8780041d568ae07013a3592519fca855a1c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:27 +0800 Subject: [PATCH 1396/7155] ASoC: psc-ac97: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-24-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/au1x/psc-ac97.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 21e5f6aed7f3..08bc04e2da2a 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -363,7 +363,7 @@ static const struct snd_soc_component_driver au1xpsc_ac97_component = { static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) { int ret; - struct resource *iores, *dmares; + struct resource *dmares; unsigned long sel; struct au1xpsc_audio_data *wd; @@ -374,8 +374,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) mutex_init(&wd->lock); - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wd->mmio = devm_ioremap_resource(&pdev->dev, iores); + wd->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wd->mmio)) return PTR_ERR(wd->mmio); -- GitLab From 12a63c0fa03691328b948690601dc7dde8fc527b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:28 +0800 Subject: [PATCH 1397/7155] ASoC: au1x: psc-i2s: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-25-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/au1x/psc-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 076303f96b8c..767ce950d0da 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -291,7 +291,7 @@ static const struct snd_soc_component_driver au1xpsc_i2s_component = { static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) { - struct resource *iores, *dmares; + struct resource *dmares; unsigned long sel; struct au1xpsc_audio_data *wd; @@ -300,8 +300,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) if (!wd) return -ENOMEM; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wd->mmio = devm_ioremap_resource(&pdev->dev, iores); + wd->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wd->mmio)) return PTR_ERR(wd->mmio); -- GitLab From a95c901248642d62dc7462a2d2190c8ac183c84f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:29 +0800 Subject: [PATCH 1398/7155] ASoC: meson: g12a-tohdmitx: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-26-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/g12a-tohdmitx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c index 9943c807ec5d..9cfbd343a00c 100644 --- a/sound/soc/meson/g12a-tohdmitx.c +++ b/sound/soc/meson/g12a-tohdmitx.c @@ -376,12 +376,10 @@ MODULE_DEVICE_TABLE(of, g12a_tohdmitx_of_match); static int g12a_tohdmitx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; void __iomem *regs; struct regmap *map; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From 10392fcad7dfc8ea38959b18327ff18b81b1c161 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 23:07:30 +0800 Subject: [PATCH 1399/7155] ASoC: meson: axg-tdm-formatter: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190727150738.54764-27-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-formatter.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 2e498201139f..21c735afab35 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -253,7 +253,6 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; const struct axg_tdm_formatter_driver *drv; struct axg_tdm_formatter *formatter; - struct resource *res; void __iomem *regs; int ret; @@ -269,8 +268,7 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) platform_set_drvdata(pdev, formatter); formatter->drv = drv; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); -- GitLab From d6de65fde51644f6ed6b1c0c05fef6a2da5ff768 Mon Sep 17 00:00:00 2001 From: Andra Danciu Date: Wed, 31 Jul 2019 14:19:29 +0300 Subject: [PATCH 1400/7155] dt-bindings: sound: Add bindings for UDA1334 codec The UDA1334 is an NXP audio codec, supports the I2S-bus data format and has basic features such as de-emphasis (at 44.1 kHz sampling rate) and mute. Product information can be found at: https://www.nxp.com/pages/low-power-audio-dac-with-pll:UDA1334 Cc: Daniel Baluta Signed-off-by: Andra Danciu Link: https://lore.kernel.org/r/20190731111930.20230-2-andradanciu1997@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/uda1334.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/uda1334.txt diff --git a/Documentation/devicetree/bindings/sound/uda1334.txt b/Documentation/devicetree/bindings/sound/uda1334.txt new file mode 100644 index 000000000000..f64071b25e8d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/uda1334.txt @@ -0,0 +1,17 @@ +UDA1334 audio CODEC + +This device uses simple GPIO pins for controlling codec settings. + +Required properties: + + - compatible : "nxp,uda1334" + - nxp,mute-gpios: a GPIO spec for the MUTE pin. + - nxp,deemph-gpios: a GPIO spec for the De-emphasis pin + +Example: + +uda1334: audio-codec { + compatible = "nxp,uda1334"; + nxp,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + nxp,deemph-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>; +}; -- GitLab From f39b07fdfb688724fedabf5507e15eaf398f2500 Mon Sep 17 00:00:00 2001 From: Shay Bar Date: Wed, 3 Jul 2019 16:18:48 +0300 Subject: [PATCH 1401/7155] mac80211: HE STA disassoc due to QOS NULL not sent In case of HE AP-STA link, ieee80211_send_nullfunc() will not send the QOS NULL packet to check if AP is still associated. In this case, probe_send_count will be non-zero and ieee80211_sta_work() will later disassociate the AP, even though no packet was ever sent. Fix this by decrementing probe_send_count and not calling ieee80211_send_nullfunc() in case of HE link, so that we still wait for some time for the AP beacon to reappear and don't disconnect right away. Signed-off-by: Shay Bar Link: https://lore.kernel.org/r/20190703131848.22879-1-shay.bar@celeno.com [clarify commit message] Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 225633d9e2d4..e89ed800f012 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2512,7 +2512,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) { ifmgd->nullfunc_failed = false; - ieee80211_send_nullfunc(sdata->local, sdata, false); + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) + ifmgd->probe_send_count--; + else + ieee80211_send_nullfunc(sdata->local, sdata, false); } else { int ssid_len; -- GitLab From caa918ef14065b812737f3ee4ac349dcfff196e6 Mon Sep 17 00:00:00 2001 From: Andra Danciu Date: Wed, 31 Jul 2019 14:19:30 +0300 Subject: [PATCH 1402/7155] ASoC: codecs: Add uda1334 codec driver The UDA1334BTS supports the I2S-bus data format with word lengths of up to 24 bits serial data format and has basic features such as de-emphasis (at 44.1 kHz sampling rate) and mute. Datasheet can be found at: https://www.nxp.com/docs/en/data-sheet/UDA1334BTS.pdf Cc: Daniel Baluta Signed-off-by: Andra Danciu Link: https://lore.kernel.org/r/20190731111930.20230-3-andradanciu1997@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 9 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/uda1334.c | 295 +++++++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 sound/soc/codecs/uda1334.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index da4c1ae89742..89238343e34d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -199,6 +199,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TS3A227E if I2C select SND_SOC_TWL4030 if TWL4030_CORE select SND_SOC_TWL6040 if TWL6040_CORE + select SND_SOC_UDA1334 if GPIOLIB select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WCD9335 if SLIMBUS @@ -1207,6 +1208,14 @@ config SND_SOC_TWL4030 config SND_SOC_TWL6040 tristate +config SND_SOC_UDA1334 + tristate "NXP UDA1334 DAC" + depends on GPIOLIB + help + The UDA1334 is an NXP audio codec, supports the I2S-bus data format + and has basic features such as de-emphasis (at 44.1 kHz sampling + rate) and mute. + config SND_SOC_UDA134X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9230016b0f9f..c498373dcc5f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -212,6 +212,7 @@ snd-soc-tscs454-objs := tscs454.o snd-soc-ts3a227e-objs := ts3a227e.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o +snd-soc-uda1334-objs := uda1334.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o @@ -494,6 +495,7 @@ obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o +obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o diff --git a/sound/soc/codecs/uda1334.c b/sound/soc/codecs/uda1334.c new file mode 100644 index 000000000000..21ab8c5487ba --- /dev/null +++ b/sound/soc/codecs/uda1334.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// uda1334.c -- UDA1334 ALSA SoC Audio driver +// +// Based on WM8523 ALSA SoC Audio driver written by Mark Brown + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UDA1334_NUM_RATES 6 + +/* codec private data */ +struct uda1334_priv { + struct gpio_desc *mute; + struct gpio_desc *deemph; + unsigned int sysclk; + unsigned int rate_constraint_list[UDA1334_NUM_RATES]; + struct snd_pcm_hw_constraint_list rate_constraint; +}; + +static const struct snd_soc_dapm_widget uda1334_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_OUTPUT("LINEVOUTL"), +SND_SOC_DAPM_OUTPUT("LINEVOUTR"), +}; + +static const struct snd_soc_dapm_route uda1334_dapm_routes[] = { + { "LINEVOUTL", NULL, "DAC" }, + { "LINEVOUTR", NULL, "DAC" }, +}; + +static int uda1334_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; + + gpiod_set_value_cansleep(uda1334->deemph, deemph); + + return 0; +}; + +static int uda1334_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + int ret; + + ret = gpiod_get_value_cansleep(uda1334->deemph); + if (ret < 0) + return -EINVAL; + + ucontrol->value.integer.value[0] = ret; + + return 0; +}; + +static const struct snd_kcontrol_new uda1334_snd_controls[] = { + SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, + uda1334_get_deemph, uda1334_put_deemph), +}; + +static const struct { + int value; + int ratio; +} lrclk_ratios[UDA1334_NUM_RATES] = { + { 1, 128 }, + { 2, 192 }, + { 3, 256 }, + { 4, 384 }, + { 5, 512 }, + { 6, 768 }, +}; + +static int uda1334_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + + /* + * The set of sample rates that can be supported depends on the + * MCLK supplied to the CODEC - enforce this. + */ + if (!uda1334->sysclk) { + dev_err(component->dev, + "No MCLK configured, call set_sysclk() on init\n"); + return -EINVAL; + } + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &uda1334->rate_constraint); + + gpiod_set_value_cansleep(uda1334->mute, 1); + + return 0; +} + +static void uda1334_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + + gpiod_set_value_cansleep(uda1334->mute, 0); +} + +static int uda1334_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = codec_dai->component; + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + unsigned int val; + int i, j = 0; + + uda1334->sysclk = freq; + + uda1334->rate_constraint.count = 0; + for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { + val = freq / lrclk_ratios[i].ratio; + /* + * Check that it's a standard rate since core can't + * cope with others and having the odd rates confuses + * constraint matching. + */ + + switch (val) { + case 8000: + case 32000: + case 44100: + case 48000: + case 64000: + case 88200: + case 96000: + dev_dbg(component->dev, "Supported sample rate: %dHz\n", + val); + uda1334->rate_constraint_list[j++] = val; + uda1334->rate_constraint.count++; + break; + default: + dev_dbg(component->dev, "Skipping sample rate: %dHz\n", + val); + } + } + + /* Need at least one supported rate... */ + if (uda1334->rate_constraint.count == 0) + return -EINVAL; + + return 0; +} + +static int uda1334_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | + SND_SOC_DAIFMT_MASTER_MASK); + + if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS)) { + dev_err(codec_dai->dev, "Invalid DAI format\n"); + return -EINVAL; + } + + return 0; +} + +static int uda1334_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(dai->component); + + if (uda1334->mute) + gpiod_set_value_cansleep(uda1334->mute, mute); + + return 0; +} + +#define UDA1334_RATES SNDRV_PCM_RATE_8000_96000 + +#define UDA1334_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops uda1334_dai_ops = { + .startup = uda1334_startup, + .shutdown = uda1334_shutdown, + .set_sysclk = uda1334_set_dai_sysclk, + .set_fmt = uda1334_set_fmt, + .mute_stream = uda1334_mute_stream, +}; + +static struct snd_soc_dai_driver uda1334_dai = { + .name = "uda1334-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = UDA1334_RATES, + .formats = UDA1334_FORMATS, + }, + .ops = &uda1334_dai_ops, +}; + +static int uda1334_probe(struct snd_soc_component *component) +{ + struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); + + uda1334->rate_constraint.list = &uda1334->rate_constraint_list[0]; + uda1334->rate_constraint.count = + ARRAY_SIZE(uda1334->rate_constraint_list); + + return 0; +} + +static const struct snd_soc_component_driver soc_component_dev_uda1334 = { + .probe = uda1334_probe, + .controls = uda1334_snd_controls, + .num_controls = ARRAY_SIZE(uda1334_snd_controls), + .dapm_widgets = uda1334_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1334_dapm_widgets), + .dapm_routes = uda1334_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(uda1334_dapm_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct of_device_id uda1334_of_match[] = { + { .compatible = "nxp,uda1334" }, + { /* sentinel*/ } +}; +MODULE_DEVICE_TABLE(of, uda1334_of_match); + +static int uda1334_codec_probe(struct platform_device *pdev) +{ + struct uda1334_priv *uda1334; + int ret; + + uda1334 = devm_kzalloc(&pdev->dev, sizeof(struct uda1334_priv), + GFP_KERNEL); + if (!uda1334) + return -ENOMEM; + + platform_set_drvdata(pdev, uda1334); + + uda1334->mute = devm_gpiod_get(&pdev->dev, "nxp,mute", GPIOD_OUT_LOW); + if (IS_ERR(uda1334->mute)) { + ret = PTR_ERR(uda1334->mute); + dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret); + return ret; + } + + uda1334->deemph = devm_gpiod_get(&pdev->dev, "nxp,deemph", GPIOD_OUT_LOW); + if (IS_ERR(uda1334->deemph)) { + ret = PTR_ERR(uda1334->deemph); + dev_err(&pdev->dev, "Failed to get deemph line: %d\n", ret); + return ret; + } + + ret = devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_uda1334, + &uda1334_dai, 1); + if (ret < 0) + dev_err(&pdev->dev, "Failed to register component: %d\n", ret); + + return ret; +} + +static struct platform_driver uda1334_codec_driver = { + .probe = uda1334_codec_probe, + .driver = { + .name = "uda1334-codec", + .of_match_table = uda1334_of_match, + }, +}; +module_platform_driver(uda1334_codec_driver); + +MODULE_DESCRIPTION("ASoC UDA1334 driver"); +MODULE_AUTHOR("Andra Danciu "); +MODULE_ALIAS("platform:uda1334-codec"); +MODULE_LICENSE("GPL v2"); -- GitLab From 82cb54856874b1b374f18420be013ff4057700a9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 29 Jul 2019 12:55:21 +0300 Subject: [PATCH 1403/7155] asm-generic: make simd.h a mandatory include/asm header The generic aegis128 software crypto driver recently gained support for using SIMD intrinsics to increase performance, for which it uncondionally #include's the header. Unfortunately, this header does not exist on many architectures, resulting in build failures. Since asm-generic already has a version of simd.h, let's make it a mandatory header so that it gets instantiated on all architectures that don't provide their own version. Signed-off-by: Ard Biesheuvel Acked-by: Arnd Bergmann Signed-off-by: Herbert Xu --- include/asm-generic/Kbuild | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild index 6f4536d70b8e..adff14fcb8e4 100644 --- a/include/asm-generic/Kbuild +++ b/include/asm-generic/Kbuild @@ -3,3 +3,5 @@ # asm headers that all architectures except um should have # (This file is not included when SRCARCH=um since UML borrows several # asm headers from the host architecutre.) + +mandatory-y += simd.h -- GitLab From f7d120d9e0b9cbdb20d45ff7998d5fe4820d1cdd Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Wed, 31 Jul 2019 18:35:17 +0800 Subject: [PATCH 1404/7155] staging: rtl8723bs: indicate disconnection when disconnecting The Realtek RTL8723BS only connects successfully at the very first time, then it always fails attempting to switch to another AP. No authentication/association observed from the air capture for each attempt due to the cfg80211 believes the device is still connected. Fix this by forcing to indicate the disconnection events during disconnection so the cfg80211_connect can connect to a different AP without problem. Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20190731103517.66903-1-chiu@endlessm.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 9bc685632651..57876463b9b2 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -2024,8 +2024,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - old_type = rtw_wdev->iftype; rtw_set_to_roam(padapter, 0); @@ -2047,8 +2045,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) } leave_ibss: - padapter->mlmepriv.not_indic_disco = false; - return 0; } @@ -2246,8 +2242,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - rtw_set_to_roam(padapter, 0); rtw_scan_abort(padapter); @@ -2261,8 +2255,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, rtw_free_assoc_resources(padapter, 1); rtw_pwr_wakeup(padapter); - padapter->mlmepriv.not_indic_disco = false; - DBG_871X(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev)); return 0; } -- GitLab From 9ba2986ff5799551e023d39fa3e8ebc6d0b148c3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 10:47:36 +0100 Subject: [PATCH 1405/7155] staging: rtl8188eu: remove redundant assignment to variable rtstatus Variable rtstatus is being initialized with a value that is never read and rtstatus is being re-assigned a little later on. The assignment is redundant and hence can be removed. Also, make rtstatus a bool to match the function return type. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190731094736.28637-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/bb_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index 11e0bb9c67d7..51882858fcf0 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -653,7 +653,7 @@ static bool config_parafile(struct adapter *adapt) bool rtl88eu_phy_bb_config(struct adapter *adapt) { - int rtstatus = true; + bool rtstatus; u32 regval; u8 crystal_cap; -- GitLab From 63643b5902c4bf096b504b0563f5426ba5baef15 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 29 Jul 2019 10:51:47 -0500 Subject: [PATCH 1406/7155] ASoC: Intel: Skylake: move NHLT header to common directory Prepare move from NHLT code to common directory, starting with header. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/soc/intel/skylake/skl-nhlt.h => include/sound/intel-nhlt.h | 0 sound/soc/intel/skylake/skl-nhlt.c | 1 + sound/soc/intel/skylake/skl-ssp-clk.c | 1 + sound/soc/intel/skylake/skl-topology.c | 1 + sound/soc/intel/skylake/skl.h | 1 - 5 files changed, 3 insertions(+), 1 deletion(-) rename sound/soc/intel/skylake/skl-nhlt.h => include/sound/intel-nhlt.h (100%) diff --git a/sound/soc/intel/skylake/skl-nhlt.h b/include/sound/intel-nhlt.h similarity index 100% rename from sound/soc/intel/skylake/skl-nhlt.h rename to include/sound/intel-nhlt.h diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 1132109cb992..aabc5d71650e 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -9,6 +9,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include +#include #include "skl.h" #include "skl-i2s.h" diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index 5bb6e40d4d3e..5bfcd46452f9 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "skl.h" #include "skl-ssp-clk.h" #include "skl-topology.h" diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 6241e35213af..f8a501cf5fbd 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 6070666a6392..928e8115a1a7 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -16,7 +16,6 @@ #include #include #include -#include "skl-nhlt.h" #include "skl-ssp-clk.h" #define SKL_SUSPEND_DELAY 2000 -- GitLab From 303681f4356d322232dd5f6d9eb4bc62666064c5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 29 Jul 2019 10:51:48 -0500 Subject: [PATCH 1407/7155] ALSA: hda: move parts of NHLT code to new module Move parts of the code outside of the Skylake driver to help detect the presence of DMICs (which are not supported by the HDaudio legacy driver). No functionality change (except for the removal of useless OR operations), only indentation and checkpatch fixes, making sure that the code compiles without ACPI and fixing an ACPI leak Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/intel-nhlt.h | 41 ++++++++++++--- sound/hda/Kconfig | 5 ++ sound/hda/Makefile | 3 ++ sound/hda/intel-nhlt.c | 103 +++++++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 sound/hda/intel-nhlt.c diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index f85fbf9c7ce4..857922f03931 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -1,18 +1,17 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * skl-nhlt.h - Intel HDA Platform NHLT header + * intel-nhlt.h - Intel HDA Platform NHLT header * - * Copyright (C) 2015 Intel Corp - * Author: Sanjiv Kumar - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Copyright (c) 2015-2019 Intel Corporation */ -#ifndef __SKL_NHLT_H__ -#define __SKL_NHLT_H__ + +#ifndef __INTEL_NHLT_H__ +#define __INTEL_NHLT_H__ #include +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) + struct wav_fmt { u16 fmt_tag; u16 channels; @@ -116,4 +115,30 @@ enum { NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, }; +struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); + +void intel_nhlt_free(struct nhlt_acpi_table *addr); + +int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); + +#else + +struct nhlt_acpi_table; + +static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) +{ + return NULL; +} + +static inline void intel_nhlt_free(struct nhlt_acpi_table *addr) +{ +} + +static inline int intel_nhlt_get_dmic_geo(struct device *dev, + struct nhlt_acpi_table *nhlt) +{ + return 0; +} +#endif + #endif diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index f6feced15f17..9ccbcb5a06bd 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -29,3 +29,8 @@ config SND_HDA_PREALLOC_SIZE Note that the pre-allocation size can be changed dynamically via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. + +config SND_INTEL_NHLT + tristate + # this config should be selected only for Intel ACPI platforms. + # A fallback is provided so that the code compiles in all cases. \ No newline at end of file diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 2160202e2dc1..8560f6ef1b19 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile @@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o #extended hda obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ + +snd-intel-nhlt-objs := intel-nhlt.o +obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c new file mode 100644 index 000000000000..7a62e03ba407 --- /dev/null +++ b/sound/hda/intel-nhlt.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2015-2019 Intel Corporation + +#include +#include + +#define NHLT_ACPI_HEADER_SIG "NHLT" + +/* Unique identification for getting NHLT blobs */ +static guid_t osc_guid = + GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, + 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); + +struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) +{ + acpi_handle handle; + union acpi_object *obj; + struct nhlt_resource_desc *nhlt_ptr; + struct nhlt_acpi_table *nhlt_table = NULL; + + handle = ACPI_HANDLE(dev); + if (!handle) { + dev_err(dev, "Didn't find ACPI_HANDLE\n"); + return NULL; + } + + obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); + + if (!obj) + return NULL; + + if (obj->type != ACPI_TYPE_BUFFER) { + dev_dbg(dev, "No NHLT table found\n"); + ACPI_FREE(obj); + return NULL; + } + + nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; + if (nhlt_ptr->length) + nhlt_table = (struct nhlt_acpi_table *) + memremap(nhlt_ptr->min_addr, nhlt_ptr->length, + MEMREMAP_WB); + ACPI_FREE(obj); + if (nhlt_table && + (strncmp(nhlt_table->header.signature, + NHLT_ACPI_HEADER_SIG, + strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { + memunmap(nhlt_table); + dev_err(dev, "NHLT ACPI header signature incorrect\n"); + return NULL; + } + return nhlt_table; +} +EXPORT_SYMBOL_GPL(intel_nhlt_init); + +void intel_nhlt_free(struct nhlt_acpi_table *nhlt) +{ + memunmap((void *)nhlt); +} +EXPORT_SYMBOL_GPL(intel_nhlt_free); + +int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) +{ + struct nhlt_endpoint *epnt; + struct nhlt_dmic_array_config *cfg; + unsigned int dmic_geo = 0; + u8 j; + + if (!nhlt) + return 0; + + epnt = (struct nhlt_endpoint *)nhlt->desc; + + for (j = 0; j < nhlt->endpoint_count; j++) { + if (epnt->linktype == NHLT_LINK_DMIC) { + cfg = (struct nhlt_dmic_array_config *) + (epnt->config.caps); + switch (cfg->array_type) { + case NHLT_MIC_ARRAY_2CH_SMALL: + case NHLT_MIC_ARRAY_2CH_BIG: + dmic_geo = MIC_ARRAY_2CH; + break; + + case NHLT_MIC_ARRAY_4CH_1ST_GEOM: + case NHLT_MIC_ARRAY_4CH_L_SHAPED: + case NHLT_MIC_ARRAY_4CH_2ND_GEOM: + dmic_geo = MIC_ARRAY_4CH; + break; + + default: + dev_warn(dev, "undefined DMIC array_type 0x%0x\n", + cfg->array_type); + } + } + epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); + } + + return dmic_geo; +} +EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel NHLT driver"); -- GitLab From 7a33ea70e1868ee578fe2e9a85dd300efa1a35d5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 29 Jul 2019 10:51:49 -0500 Subject: [PATCH 1408/7155] ALSA: hda: intel-nhlt: handle NHLT VENDOR_DEFINED DMIC geometry The NHLT spec defines a VENDOR_DEFINED geometry, which requires reading additional information to figure out the number of microphones. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/intel-nhlt.h | 10 ++++++++-- sound/hda/intel-nhlt.c | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index 857922f03931..f657fd8fc0ad 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -96,16 +96,22 @@ struct nhlt_resource_desc { #define MIC_ARRAY_2CH 2 #define MIC_ARRAY_4CH 4 -struct nhlt_tdm_config { +struct nhlt_device_specific_config { u8 virtual_slot; u8 config_type; } __packed; struct nhlt_dmic_array_config { - struct nhlt_tdm_config tdm_config; + struct nhlt_device_specific_config device_config; u8 array_type; } __packed; +struct nhlt_vendor_dmic_array_config { + struct nhlt_dmic_array_config dmic_config; + u8 nb_mics; + /* TODO add vendor mic config */ +} __packed; + enum { NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_BIG = 0xb, diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c index 7a62e03ba407..daede96f28ee 100644 --- a/sound/hda/intel-nhlt.c +++ b/sound/hda/intel-nhlt.c @@ -63,6 +63,7 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) { struct nhlt_endpoint *epnt; struct nhlt_dmic_array_config *cfg; + struct nhlt_vendor_dmic_array_config *cfg_vendor; unsigned int dmic_geo = 0; u8 j; @@ -86,7 +87,10 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) case NHLT_MIC_ARRAY_4CH_2ND_GEOM: dmic_geo = MIC_ARRAY_4CH; break; - + case NHLT_MIC_ARRAY_VENDOR_DEFINED: + cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; + dmic_geo = cfg_vendor->nb_mics; + break; default: dev_warn(dev, "undefined DMIC array_type 0x%0x\n", cfg->array_type); -- GitLab From 1169cbf6b98e11397715d457e42070e066325fc0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 29 Jul 2019 10:51:50 -0500 Subject: [PATCH 1409/7155] ASoC: Intel: Skylake: use common NHLT module No functionality change, only use common functions now. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/skylake/skl-nhlt.c | 90 ------------------------------ sound/soc/intel/skylake/skl.c | 12 ++-- sound/soc/intel/skylake/skl.h | 3 - 4 files changed, 9 insertions(+), 97 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 96a00a9d4cf8..a3ec17fd63cd 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -215,6 +215,7 @@ config SND_SOC_INTEL_SKYLAKE_COMMON select SND_SOC_INTEL_SST select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC select SND_SOC_ACPI_INTEL_MATCH + select SND_INTEL_NHLT help If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ GeminiLake or CannonLake platform with the DSP enabled in the BIOS diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index aabc5d71650e..6f57ceb9efb7 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -13,54 +13,6 @@ #include "skl.h" #include "skl-i2s.h" -#define NHLT_ACPI_HEADER_SIG "NHLT" - -/* Unique identification for getting NHLT blobs */ -static guid_t osc_guid = - GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, - 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); - - -struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) -{ - acpi_handle handle; - union acpi_object *obj; - struct nhlt_resource_desc *nhlt_ptr = NULL; - struct nhlt_acpi_table *nhlt_table = NULL; - - handle = ACPI_HANDLE(dev); - if (!handle) { - dev_err(dev, "Didn't find ACPI_HANDLE\n"); - return NULL; - } - - obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); - if (obj && obj->type == ACPI_TYPE_BUFFER) { - nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; - if (nhlt_ptr->length) - nhlt_table = (struct nhlt_acpi_table *) - memremap(nhlt_ptr->min_addr, nhlt_ptr->length, - MEMREMAP_WB); - ACPI_FREE(obj); - if (nhlt_table && (strncmp(nhlt_table->header.signature, - NHLT_ACPI_HEADER_SIG, - strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { - memunmap(nhlt_table); - dev_err(dev, "NHLT ACPI header signature incorrect\n"); - return NULL; - } - return nhlt_table; - } - - dev_err(dev, "device specific method to extract NHLT blob failed\n"); - return NULL; -} - -void skl_nhlt_free(struct nhlt_acpi_table *nhlt) -{ - memunmap((void *) nhlt); -} - static struct nhlt_specific_cfg *skl_get_specific_cfg( struct device *dev, struct nhlt_fmt *fmt, u8 no_ch, u32 rate, u16 bps, u8 linktype) @@ -163,48 +115,6 @@ struct nhlt_specific_cfg return NULL; } -int skl_get_dmic_geo(struct skl *skl) -{ - struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; - struct nhlt_endpoint *epnt; - struct nhlt_dmic_array_config *cfg; - struct device *dev = &skl->pci->dev; - unsigned int dmic_geo = 0; - u8 j; - - if (!nhlt) - return 0; - - epnt = (struct nhlt_endpoint *)nhlt->desc; - - for (j = 0; j < nhlt->endpoint_count; j++) { - if (epnt->linktype == NHLT_LINK_DMIC) { - cfg = (struct nhlt_dmic_array_config *) - (epnt->config.caps); - switch (cfg->array_type) { - case NHLT_MIC_ARRAY_2CH_SMALL: - case NHLT_MIC_ARRAY_2CH_BIG: - dmic_geo |= MIC_ARRAY_2CH; - break; - - case NHLT_MIC_ARRAY_4CH_1ST_GEOM: - case NHLT_MIC_ARRAY_4CH_L_SHAPED: - case NHLT_MIC_ARRAY_4CH_2ND_GEOM: - dmic_geo |= MIC_ARRAY_4CH; - break; - - default: - dev_warn(dev, "undefined DMIC array_type 0x%0x\n", - cfg->array_type); - - } - } - epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); - } - - return dmic_geo; -} - static void skl_nhlt_trim_space(char *trim) { char *s = trim; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 3362e71b4563..2b5159890a57 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -26,9 +26,11 @@ #include #include #include +#include #include "skl.h" #include "skl-sst-dsp.h" #include "skl-sst-ipc.h" + #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) #include "../../../soc/codecs/hdac_hda.h" #endif @@ -516,7 +518,9 @@ static int skl_find_machine(struct skl *skl, void *driver_data) if (pdata) { skl->use_tplg_pcm = pdata->use_tplg_pcm; - mach->mach_params.dmic_num = skl_get_dmic_geo(skl); + mach->mach_params.dmic_num = + intel_nhlt_get_dmic_geo(&skl->pci->dev, + skl->nhlt); } return 0; @@ -1029,7 +1033,7 @@ static int skl_probe(struct pci_dev *pci, device_disable_async_suspend(bus->dev); - skl->nhlt = skl_nhlt_init(bus->dev); + skl->nhlt = intel_nhlt_init(bus->dev); if (skl->nhlt == NULL) { #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) @@ -1095,7 +1099,7 @@ static int skl_probe(struct pci_dev *pci, out_clk_free: skl_clock_device_unregister(skl); out_nhlt_free: - skl_nhlt_free(skl->nhlt); + intel_nhlt_free(skl->nhlt); out_free: skl_free(bus); @@ -1144,7 +1148,7 @@ static void skl_remove(struct pci_dev *pci) skl_dmic_device_unregister(skl); skl_clock_device_unregister(skl); skl_nhlt_remove_sysfs(skl); - skl_nhlt_free(skl->nhlt); + intel_nhlt_free(skl->nhlt); skl_free(bus); dev_set_drvdata(&pci->dev, NULL); } diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 928e8115a1a7..f4dd6c767993 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -128,13 +128,10 @@ struct skl_dsp_ops { int skl_platform_unregister(struct device *dev); int skl_platform_register(struct device *dev); -struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); -void skl_nhlt_free(struct nhlt_acpi_table *addr); struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn, u8 dev_type); -int skl_get_dmic_geo(struct skl *skl); int skl_nhlt_update_topology_bin(struct skl *skl); int skl_init_dsp(struct skl *skl); int skl_free_dsp(struct skl *skl); -- GitLab From 8c57588313805d4e12a3d470dee3405c2236655f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 29 Jul 2019 10:51:51 -0500 Subject: [PATCH 1410/7155] ALSA: hda/intel: stop probe if DMICS are detected on Skylake+ platforms The legacy HD-Audio driver cannot handle Skylake+ platforms with digital microphones. For those platforms, the SOF or SST drivers need to be used. This patch provides an automatic way of detecting the presence of DMICs using NHTL information reported by the BIOS. A kernel kconfig option or a kernel module parameter provide an opt-in means of stopping the probe. The kernel would then look for an alternate driver registered for the same PCI ID to probe. With this capability, distros no longer have to blacklist snd-hda-intel, but still need to make sure the SOF/SST drivers are functional by providing the relevant firmware and topology files in /lib/firmware/intel The coexistence between SOF and SST drivers and their dynamic detection is not addressed by this patch, different mechanisms need to be used, e.g. DMI-based quirks. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/pci/hda/Kconfig | 10 ++++++++++ sound/pci/hda/hda_intel.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 35d934309cb2..b5966014b5f7 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -12,6 +12,7 @@ config SND_HDA_INTEL tristate "HD Audio PCI" depends on SND_PCI select SND_HDA + select SND_INTEL_NHLT if ACPI help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. @@ -22,6 +23,15 @@ config SND_HDA_INTEL To compile this driver as a module, choose M here: the module will be called snd-hda-intel. +config SND_HDA_INTEL_DETECT_DMIC + bool "DMIC detection and probe abort" + depends on SND_HDA_INTEL + help + Say Y to detect digital microphones on SKL+ devices. DMICs + cannot be handled by the HDaudio legacy driver and are + currently only supported by the SOF driver. + If unsure say N. + config SND_HDA_TEGRA tristate "NVIDIA Tegra HD Audio" depends on ARCH_TEGRA diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cb8b0945547c..ae9c13248a1d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -124,6 +125,7 @@ static char *patch[SNDRV_CARDS]; static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = CONFIG_SND_HDA_INPUT_BEEP_MODE}; #endif +static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC); module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -158,6 +160,8 @@ module_param_array(beep_mode, bool, NULL, 0444); MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " "(0=off, 1=on) (default=1)."); #endif +module_param(dmic_detect, bool, 0444); +MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms"); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -2025,6 +2029,25 @@ static const struct hda_controller_ops pci_hda_ops = { .position_check = azx_position_check, }; +static int azx_check_dmic(struct pci_dev *pci, struct azx *chip) +{ + struct nhlt_acpi_table *nhlt; + int ret = 0; + + if (chip->driver_type == AZX_DRIVER_SKL && + pci->class != 0x040300) { + nhlt = intel_nhlt_init(&pci->dev); + if (nhlt) { + if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) { + ret = -ENODEV; + dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n"); + } + intel_nhlt_free(nhlt); + } + } + return ret; +} + static int azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -2055,6 +2078,17 @@ static int azx_probe(struct pci_dev *pci, card->private_data = chip; hda = container_of(chip, struct hda_intel, chip); + /* + * stop probe if digital microphones detected on Skylake+ platform + * with the DSP enabled. This is an opt-in behavior defined at build + * time or at run-time with a module parameter + */ + if (dmic_detect) { + err = azx_check_dmic(pci, chip); + if (err < 0) + goto out_free; + } + pci_set_drvdata(pci, card); err = register_vga_switcheroo(chip); -- GitLab From a9afc9ea93995021f29025e62d83415a45c5f58b Mon Sep 17 00:00:00 2001 From: Jonathan Hunter Date: Wed, 31 Jul 2019 11:16:39 +0100 Subject: [PATCH 1411/7155] dmaengine: tegra210-adma: Don't program FIFO threshold The Tegra210 ADMA supports two modes for transferring data to a FIFO which are ... 1. Transfer data to/from the FIFO as soon as a single burst can be transferred. 2. Transfer data to/from the FIFO based upon FIFO thresholds, where the FIFO threshold is specified in terms on multiple bursts. Currently, the ADMA driver programs the FIFO threshold values in the FIFO_CTRL register, but never enables the transfer mode that uses these threshold values. Given that these have never been used so far, simplify the ADMA driver by removing the programming of these threshold values. Signed-off-by: Jonathan Hunter Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20190731101639.22755-1-jonathanh@nvidia.com Signed-off-by: Vinod Koul --- drivers/dma/tegra210-adma.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index 2805853e963f..d8646a49ba5b 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -42,12 +42,8 @@ #define ADMA_CH_CONFIG_MAX_BUFS 8 #define ADMA_CH_FIFO_CTRL 0x2c -#define TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(val) (((val) & 0xf) << 24) -#define TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(val) (((val) & 0xf) << 16) #define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0xf) << 8) #define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0xf) -#define TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(val) (((val) & 0x1f) << 24) -#define TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(val) (((val) & 0x1f) << 16) #define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0x1f) << 8) #define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0x1f) @@ -64,14 +60,10 @@ #define TEGRA_ADMA_BURST_COMPLETE_TIME 20 -#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \ - TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \ - TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ +#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3)) -#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \ - TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \ - TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ +#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3)) #define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift) -- GitLab From 7f5d7425748d1cc2dadb6966ec84363d3342b5a1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 17:52:21 -0500 Subject: [PATCH 1412/7155] dmaengine: imx-dma: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: arm): drivers/dma/imx-dma.c: In function ‘imxdma_xfer_desc’: drivers/dma/imx-dma.c:542:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (slot == IMX_DMA_2D_SLOT_A) { ^ drivers/dma/imx-dma.c:559:2: note: here case IMXDMA_DESC_MEMCPY: ^~~~ Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20190729225221.GA24269@embeddedor Reviewed-by: Kees Cook Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 00a089e24150..5c0fb3134825 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -556,6 +556,7 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) * We fall-through here intentionally, since a 2D transfer is * similar to MEMCPY just adding the 2D slot configuration. */ + /* Fall through */ case IMXDMA_DESC_MEMCPY: imx_dmav1_writel(imxdma, d->src, DMA_SAR(imxdmac->channel)); imx_dmav1_writel(imxdma, d->dest, DMA_DAR(imxdmac->channel)); -- GitLab From e17be6e1b713f188728a23ebfba15546a025c109 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:10 -0700 Subject: [PATCH 1413/7155] dmaengine: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Vinod Koul Cc: Dan Williams Cc: dmaengine@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-11-swboyd@chromium.org Signed-off-by: Vinod Koul --- drivers/dma/dma-jz4780.c | 4 +--- drivers/dma/fsl-edma.c | 8 ++------ drivers/dma/fsl-qdma.c | 9 ++------- drivers/dma/mediatek/mtk-uart-apdma.c | 4 +--- drivers/dma/qcom/hidma_mgmt.c | 1 - drivers/dma/s3c24xx-dma.c | 5 +---- drivers/dma/sh/rcar-dmac.c | 4 +--- drivers/dma/sh/usb-dmac.c | 4 +--- drivers/dma/st_fdma.c | 4 +--- drivers/dma/stm32-dma.c | 6 +----- drivers/dma/stm32-mdma.c | 4 +--- drivers/dma/sun4i-dma.c | 4 +--- drivers/dma/sun6i-dma.c | 4 +--- drivers/dma/uniphier-mdmac.c | 5 +---- drivers/dma/xgene-dma.c | 8 ++------ 15 files changed, 17 insertions(+), 57 deletions(-) diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 9a985a9710aa..cafb1cc065bb 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -886,10 +886,8 @@ static int jz4780_dma_probe(struct platform_device *pdev) } ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get IRQ: %d\n", ret); + if (ret < 0) return ret; - } jzdma->irq = ret; diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c index fcbad6ae954a..71650fa01f18 100644 --- a/drivers/dma/fsl-edma.c +++ b/drivers/dma/fsl-edma.c @@ -125,16 +125,12 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma int ret; fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx"); - if (fsl_edma->txirq < 0) { - dev_err(&pdev->dev, "Can't get edma-tx irq.\n"); + if (fsl_edma->txirq < 0) return fsl_edma->txirq; - } fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err"); - if (fsl_edma->errirq < 0) { - dev_err(&pdev->dev, "Can't get edma-err irq.\n"); + if (fsl_edma->errirq < 0) return fsl_edma->errirq; - } if (fsl_edma->txirq == fsl_edma->errirq) { ret = devm_request_irq(&pdev->dev, fsl_edma->txirq, diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c index 8e341c0c13bc..06664fbd2d91 100644 --- a/drivers/dma/fsl-qdma.c +++ b/drivers/dma/fsl-qdma.c @@ -758,10 +758,8 @@ fsl_qdma_irq_init(struct platform_device *pdev, fsl_qdma->error_irq = platform_get_irq_byname(pdev, "qdma-error"); - if (fsl_qdma->error_irq < 0) { - dev_err(&pdev->dev, "Can't get qdma controller irq.\n"); + if (fsl_qdma->error_irq < 0) return fsl_qdma->error_irq; - } ret = devm_request_irq(&pdev->dev, fsl_qdma->error_irq, fsl_qdma_error_handler, 0, @@ -776,11 +774,8 @@ fsl_qdma_irq_init(struct platform_device *pdev, fsl_qdma->queue_irq[i] = platform_get_irq_byname(pdev, irq_name); - if (fsl_qdma->queue_irq[i] < 0) { - dev_err(&pdev->dev, - "Can't get qdma queue %d irq.\n", i); + if (fsl_qdma->queue_irq[i] < 0) return fsl_qdma->queue_irq[i]; - } ret = devm_request_irq(&pdev->dev, fsl_qdma->queue_irq[i], diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c index 546995c20876..f40051d6aecb 100644 --- a/drivers/dma/mediatek/mtk-uart-apdma.c +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -547,10 +547,8 @@ static int mtk_uart_apdma_probe(struct platform_device *pdev) vchan_init(&c->vc, &mtkd->ddev); rc = platform_get_irq(pdev, i); - if (rc < 0) { - dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i); + if (rc < 0) goto err_no_dma; - } c->irq = rc; } diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 3022d66e7a33..7cb81a50f3f3 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -183,7 +183,6 @@ static int hidma_mgmt_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "irq resources not found\n"); rc = irq; goto out; } diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c index ad30f3d2c7f6..43da8eeb18ef 100644 --- a/drivers/dma/s3c24xx-dma.c +++ b/drivers/dma/s3c24xx-dma.c @@ -1237,11 +1237,8 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) phy->host = s3cdma; phy->irq = platform_get_irq(pdev, i); - if (phy->irq < 0) { - dev_err(&pdev->dev, "failed to get irq %d, err %d\n", - i, phy->irq); + if (phy->irq < 0) continue; - } ret = devm_request_irq(&pdev->dev, phy->irq, s3c24xx_dma_irq, 0, pdev->name, phy); diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 9c41a4e42575..eb6f2312a6a2 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1744,10 +1744,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, /* Request the channel interrupt. */ sprintf(pdev_irqname, "ch%u", index); rchan->irq = platform_get_irq_byname(pdev, pdev_irqname); - if (rchan->irq < 0) { - dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); + if (rchan->irq < 0) return -ENODEV; - } irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u", dev_name(dmac->dev), index); diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c index 17063aaf51bc..b218a013c260 100644 --- a/drivers/dma/sh/usb-dmac.c +++ b/drivers/dma/sh/usb-dmac.c @@ -717,10 +717,8 @@ static int usb_dmac_chan_probe(struct usb_dmac *dmac, /* Request the channel interrupt. */ sprintf(pdev_irqname, "ch%u", index); uchan->irq = platform_get_irq_byname(pdev, pdev_irqname); - if (uchan->irq < 0) { - dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); + if (uchan->irq < 0) return -ENODEV; - } irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u", dev_name(dmac->dev), index); diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c index a3ee0f6bb664..67087dbe2f9f 100644 --- a/drivers/dma/st_fdma.c +++ b/drivers/dma/st_fdma.c @@ -771,10 +771,8 @@ static int st_fdma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fdev); fdev->irq = platform_get_irq(pdev, 0); - if (fdev->irq < 0) { - dev_err(&pdev->dev, "Failed to get irq resource\n"); + if (fdev->irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0, dev_name(&pdev->dev), fdev); diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index ef4d109e7189..e4cbe38d1b83 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1366,12 +1366,8 @@ static int stm32_dma_probe(struct platform_device *pdev) for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) { chan = &dmadev->chan[i]; ret = platform_get_irq(pdev, i); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "No irq resource for chan %d\n", i); + if (ret < 0) goto err_unregister; - } chan->irq = ret; ret = devm_request_irq(&pdev->dev, chan->irq, diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 0d56fde78c1f..057811a7149c 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1637,10 +1637,8 @@ static int stm32_mdma_probe(struct platform_device *pdev) } dmadev->irq = platform_get_irq(pdev, 0); - if (dmadev->irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); + if (dmadev->irq < 0) return dmadev->irq; - } ret = devm_request_irq(&pdev->dev, dmadev->irq, stm32_mdma_irq_handler, 0, dev_name(&pdev->dev), dmadev); diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index 1f80568b2613..e397a50058c8 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -1132,10 +1132,8 @@ static int sun4i_dma_probe(struct platform_device *pdev) return PTR_ERR(priv->base); priv->irq = platform_get_irq(pdev, 0); - if (priv->irq < 0) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); + if (priv->irq < 0) return priv->irq; - } priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index ed5b68dcfe50..06cd7f867f7c 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -1251,10 +1251,8 @@ static int sun6i_dma_probe(struct platform_device *pdev) return PTR_ERR(sdc->base); sdc->irq = platform_get_irq(pdev, 0); - if (sdc->irq < 0) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); + if (sdc->irq < 0) return sdc->irq; - } sdc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(sdc->clk)) { diff --git a/drivers/dma/uniphier-mdmac.c b/drivers/dma/uniphier-mdmac.c index ec65a7430dc4..fde54687856b 100644 --- a/drivers/dma/uniphier-mdmac.c +++ b/drivers/dma/uniphier-mdmac.c @@ -354,11 +354,8 @@ static int uniphier_mdmac_chan_init(struct platform_device *pdev, int irq, ret; irq = platform_get_irq(pdev, chan_id); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ number for ch%d\n", - chan_id); + if (irq < 0) return irq; - } irq_name = devm_kasprintf(dev, GFP_KERNEL, "uniphier-mio-dmac-ch%d", chan_id); diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index 957c269ce1fd..cd60fa6d6750 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -1678,20 +1678,16 @@ static int xgene_dma_get_resources(struct platform_device *pdev, /* Get DMA error interrupt */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "Failed to get Error IRQ\n"); + if (irq <= 0) return -ENXIO; - } pdma->err_irq = irq; /* Get DMA Rx ring descriptor interrupts for all DMA channels */ for (i = 1; i <= XGENE_DMA_MAX_CHANNEL; i++) { irq = platform_get_irq(pdev, i); - if (irq <= 0) { - dev_err(&pdev->dev, "Failed to get Rx IRQ\n"); + if (irq <= 0) return -ENXIO; - } pdma->chan[i - 1].rx_irq = irq; } -- GitLab From 8d65f58021fbbc3fd5464697789bf015fcca03a4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 31 Jul 2019 15:55:47 +0100 Subject: [PATCH 1414/7155] ARM: dts: vexpress: add missing SPDX GPL-2.0 license identifier Commit b24413180f56 ("License cleanup: add SPDX GPL-2.0 license identifier to files with no license") seem to have missed this one file. Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index d6a1fc269241..dfae90adbb7c 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ARM Ltd. Versatile Express * -- GitLab From 7ff1154d459d25f8f674765a5ec575207516168c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 17 Jun 2019 16:35:47 +0200 Subject: [PATCH 1415/7155] ARM: dts: vexpress: Add missing newline at end of file "git diff" says: \ No newline at end of file after modifying the file. Signed-off-by: Geert Uytterhoeven Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/vexpress-v2m.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index 8e57e15307e2..2e29d7790497 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -451,4 +451,4 @@ }; }; }; -}; \ No newline at end of file +}; -- GitLab From ace4682635db252d40071f62af328c90508cafdd Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Tue, 25 Jun 2019 11:03:53 +0700 Subject: [PATCH 1416/7155] ARM: vexpress: Cleanup cppcheck shifting warning Fix below warning from cppcheck tool using BIT() macro: "Shifting signed 32-bit value by 31 bits is undefined behaviour errors" Signed-off-by: Phong Tran Signed-off-by: Sudeep Holla --- arch/arm/mach-vexpress/spc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index 0f5381d13494..354e0e7025ae 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -69,7 +69,7 @@ #define A7_PERFVAL_BASE 0xC30 /* Config interface control bits */ -#define SYSCFG_START (1 << 31) +#define SYSCFG_START BIT(31) #define SYSCFG_SCC (6 << 20) #define SYSCFG_STAT (14 << 20) @@ -162,7 +162,7 @@ void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set) if (cluster >= MAX_CLUSTERS) return; - mask = 1 << cpu; + mask = BIT(cpu); if (!cluster_is_a15(cluster)) mask <<= 4; -- GitLab From a9d41e7b8b1fe43c0beeab9a45d4c886a5e4ee85 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 31 Jul 2019 10:06:38 +0200 Subject: [PATCH 1417/7155] net: ag71xx: Slighly simplify code in 'ag71xx_rings_init()' A few lines above, we have: tx_size = BIT(tx->order); So use 'tx_size' directly to be consistent with the way 'rx->descs_cpu' and 'rx->descs_dma' are computed below. Signed-off-by: Christophe JAILLET Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/ag71xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 77542bd1e5bd..40a8717f51b1 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1148,7 +1148,7 @@ static int ag71xx_rings_init(struct ag71xx *ag) return -ENOMEM; } - rx->buf = &tx->buf[BIT(tx->order)]; + rx->buf = &tx->buf[tx_size]; rx->descs_cpu = ((void *)tx->descs_cpu) + tx_size * AG71XX_DESC_SIZE; rx->descs_dma = tx->descs_dma + tx_size * AG71XX_DESC_SIZE; -- GitLab From 7084148854e75090712439f73fbe2f4d6bfd96e1 Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Wed, 31 Jul 2019 16:53:46 +0800 Subject: [PATCH 1418/7155] myri10ge: remove unneeded variable "error" is unneeded,just return 0 Signed-off-by: Ding Xiang Signed-off-by: David S. Miller --- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 99eaadba555f..61fe92719982 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -3037,7 +3037,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr) static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) { struct myri10ge_priv *mgp = netdev_priv(dev); - int error = 0; netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu); if (mgp->running) { @@ -3049,7 +3048,7 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) } else dev->mtu = new_mtu; - return error; + return 0; } /* -- GitLab From 7700476f319844022f6e469e7acb578178ee29de Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 31 Jul 2019 10:30:26 +0000 Subject: [PATCH 1419/7155] selftests: mlxsw: Fix local variable declarations in DSCP tests These two tests have some problems in the global scope pollution and on contrary, contain unnecessary local declarations. Fix them. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh | 6 ++++-- .../testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh index 40f16f2a3afd..5cbff8038f84 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh @@ -36,8 +36,6 @@ source $lib_dir/lib.sh h1_create() { - local dscp; - simple_if_init $h1 192.0.2.1/28 tc qdisc add dev $h1 clsact dscp_capture_install $h1 10 @@ -67,6 +65,7 @@ h2_destroy() dscp_map() { local base=$1; shift + local prio for prio in {0..7}; do echo app=$prio,5,$((base + prio)) @@ -138,6 +137,7 @@ dscp_ping_test() local prio=$1; shift local dev_10=$1; shift local dev_20=$1; shift + local key local dscp_10=$(((prio + 10) << 2)) local dscp_20=$(((prio + 20) << 2)) @@ -175,6 +175,8 @@ dscp_ping_test() test_dscp() { + local prio + for prio in {0..7}; do dscp_ping_test v$h1 192.0.2.1 192.0.2.2 $prio $h1 $h2 done diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh index 9faf02e32627..f25e3229e1cc 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh @@ -52,8 +52,6 @@ reprioritize() h1_create() { - local dscp; - simple_if_init $h1 192.0.2.1/28 tc qdisc add dev $h1 clsact dscp_capture_install $h1 0 @@ -87,6 +85,7 @@ h2_destroy() dscp_map() { local base=$1; shift + local prio for prio in {0..7}; do echo app=$prio,5,$((base + prio)) @@ -156,6 +155,7 @@ dscp_ping_test() local reprio=$1; shift local dev1=$1; shift local dev2=$1; shift + local i local prio2=$($reprio $prio) # ICMP Request egress prio local prio3=$($reprio $prio2) # ICMP Response egress prio @@ -205,6 +205,7 @@ __test_update() { local update=$1; shift local reprio=$1; shift + local prio sysctl_restore net.ipv4.ip_forward_update_priority sysctl_set net.ipv4.ip_forward_update_priority $update -- GitLab From d11786bb9664a5bed47e7839265f49bb26d54a1b Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 31 Jul 2019 10:30:27 +0000 Subject: [PATCH 1420/7155] selftests: mlxsw: Add a test for leftover DSCP rule Commit dedfde2fe1c4 ("mlxsw: spectrum_dcb: Configure DSCP map as the last rule is removed") fixed a problem in mlxsw where last DSCP rule to be removed remained in effect when DSCP rewrite was applied. Add a selftest that covers this problem. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../drivers/net/mlxsw/qos_dscp_router.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh index f25e3229e1cc..c745ce3befee 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh @@ -31,6 +31,7 @@ ALL_TESTS=" ping_ipv4 test_update test_no_update + test_dscp_leftover " lib_dir=$(dirname $0)/../../../net/forwarding @@ -50,6 +51,11 @@ reprioritize() echo ${reprio[$in]} } +zero() +{ + echo 0 +} + h1_create() { simple_if_init $h1 192.0.2.1/28 @@ -225,6 +231,19 @@ test_no_update() __test_update 0 echo } +# Test that when the last APP rule is removed, the prio->DSCP map is properly +# set to zeroes, and that the last APP rule does not stay active in the ASIC. +test_dscp_leftover() +{ + lldptool -T -i $swp2 -V APP -d $(dscp_map 0) >/dev/null + lldpad_app_wait_del + + __test_update 0 zero + + lldptool -T -i $swp2 -V APP $(dscp_map 0) >/dev/null + lldpad_app_wait_set $swp2 +} + trap cleanup EXIT setup_prepare -- GitLab From 6a7ce95d752efa86a1a383385d4f8035c224dc3d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 31 Jul 2019 18:02:19 +0200 Subject: [PATCH 1421/7155] staging/octeon: Fix build error without CONFIG_NETDEVICES While do COMPILE_TEST build without CONFIG_NETDEVICES, we get Kconfig warning: WARNING: unmet direct dependencies detected for PHYLIB Depends on [n]: NETDEVICES [=n] Selected by [y]: - OCTEON_ETHERNET [=y] && STAGING [=y] && (CAVIUM_OCTEON_SOC && NETDEVICES [=n] || COMPILE_TEST [=y]) Reported-by: Hulk Robot Reported-by: Mark Brown Fixes: 171a9bae68c7 ("staging/octeon: Allow test build on !MIPS") Signed-off-by: YueHaibing Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/staging/octeon/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 5b3994649d99..5319909eb2f6 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CAVIUM_OCTEON_SOC && NETDEVICES || COMPILE_TEST + depends on CAVIUM_OCTEON_SOC || COMPILE_TEST + depends on NETDEVICES select PHYLIB select MDIO_OCTEON help -- GitLab From 4b9ace9c25dc5d672a548da34cebf3a39710017f Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 4 Jul 2019 11:53:20 +0300 Subject: [PATCH 1422/7155] perf/imx_ddr: Add MODULE_DEVICE_TABLE This is required for automatic probing when driver is built as a module. Fixes: 9a66d36cc7ac ("drivers/perf: imx_ddr: Add DDR performance counter support to perf") Acked-by: Frank Li Signed-off-by: Leonard Crestez Signed-off-by: Will Deacon --- drivers/perf/fsl_imx8_ddr_perf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c index 63fe21600072..0e3310dbb145 100644 --- a/drivers/perf/fsl_imx8_ddr_perf.c +++ b/drivers/perf/fsl_imx8_ddr_perf.c @@ -47,6 +47,7 @@ static const struct of_device_id imx_ddr_pmu_dt_ids[] = { { .compatible = "fsl,imx8m-ddr-pmu",}, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids); struct ddr_pmu { struct pmu pmu; -- GitLab From 228f855fb57ae25599eee64a3f3db4f7f405b34f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:32 -0700 Subject: [PATCH 1423/7155] perf: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Will Deacon Cc: Mark Rutland Cc: linux-arm-kernel@lists.infradead.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Will Deacon --- drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 4 +--- drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 4 +--- drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 4 +--- drivers/perf/qcom_l2_pmu.c | 6 +----- drivers/perf/xgene_pmu.c | 4 +--- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c index 6ad0823bcf23..e42d4464c2cf 100644 --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c @@ -217,10 +217,8 @@ static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu, /* Read and init IRQ */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "DDRC PMU get irq fail; irq:%d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr, IRQF_NOBALANCING | IRQF_NO_THREAD, diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c index 4f2917f3e25e..f28063873e11 100644 --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c @@ -207,10 +207,8 @@ static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu, /* Read and init IRQ */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "HHA PMU get irq fail; irq:%d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr, IRQF_NOBALANCING | IRQF_NO_THREAD, diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c index 9153e093f9df..078b8dc57250 100644 --- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c @@ -206,10 +206,8 @@ static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu, /* Read and init IRQ */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "L3C PMU get irq fail; irq:%d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr, IRQF_NOBALANCING | IRQF_NO_THREAD, diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c index d06182fe14b8..21d6991dbe0b 100644 --- a/drivers/perf/qcom_l2_pmu.c +++ b/drivers/perf/qcom_l2_pmu.c @@ -909,12 +909,8 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data) cluster->cluster_id = fw_cluster_id; irq = platform_get_irq(sdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, - "Failed to get valid irq for cluster %ld\n", - fw_cluster_id); + if (irq < 0) return irq; - } irq_set_status_flags(irq, IRQ_NOAUTOEN); cluster->irq = irq; diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c index 3259e2ebeb39..7e328d6385c3 100644 --- a/drivers/perf/xgene_pmu.c +++ b/drivers/perf/xgene_pmu.c @@ -1901,10 +1901,8 @@ static int xgene_pmu_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (irq < 0) return -EINVAL; - } rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr, IRQF_NOBALANCING | IRQF_NO_THREAD, -- GitLab From c1a280b68d4e6b6db4a65aa7865c22d8789ddf09 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:37 +0200 Subject: [PATCH 1424/7155] sched/preempt: Use CONFIG_PREEMPTION where appropriate CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch the preemption code, scheduler and init task over to use CONFIG_PREEMPTION. That's the first step towards RT in that area. The more complex changes are coming separately. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.117528401@linutronix.de Signed-off-by: Ingo Molnar --- include/asm-generic/preempt.h | 4 ++-- include/linux/preempt.h | 6 +++--- include/linux/sched.h | 6 +++--- init/init_task.c | 2 +- init/main.c | 2 +- kernel/sched/core.c | 14 +++++++------- kernel/sched/fair.c | 2 +- kernel/sched/sched.h | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index c3046c920063..d683f5e6d791 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -78,11 +78,11 @@ static __always_inline bool should_resched(int preempt_offset) tif_need_resched()); } -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION extern asmlinkage void preempt_schedule(void); #define __preempt_schedule() preempt_schedule() extern asmlinkage void preempt_schedule_notrace(void); #define __preempt_schedule_notrace() preempt_schedule_notrace() -#endif /* CONFIG_PREEMPT */ +#endif /* CONFIG_PREEMPTION */ #endif /* __ASM_PREEMPT_H */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index dd92b1a93919..bbb68dba37cc 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -182,7 +182,7 @@ do { \ #define preemptible() (preempt_count() == 0 && !irqs_disabled()) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION #define preempt_enable() \ do { \ barrier(); \ @@ -203,7 +203,7 @@ do { \ __preempt_schedule(); \ } while (0) -#else /* !CONFIG_PREEMPT */ +#else /* !CONFIG_PREEMPTION */ #define preempt_enable() \ do { \ barrier(); \ @@ -217,7 +217,7 @@ do { \ } while (0) #define preempt_check_resched() do { } while (0) -#endif /* CONFIG_PREEMPT */ +#endif /* CONFIG_PREEMPTION */ #define preempt_disable_notrace() \ do { \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 9f51932bd543..6947516a2d3e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1767,7 +1767,7 @@ static inline int test_tsk_need_resched(struct task_struct *tsk) * value indicates whether a reschedule was done in fact. * cond_resched_lock() will drop the spinlock before scheduling, */ -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION extern int _cond_resched(void); #else static inline int _cond_resched(void) { return 0; } @@ -1796,12 +1796,12 @@ static inline void cond_resched_rcu(void) /* * Does a critical section need to be broken due to another - * task waiting?: (technically does not depend on CONFIG_PREEMPT, + * task waiting?: (technically does not depend on CONFIG_PREEMPTION, * but a general need for low latency) */ static inline int spin_needbreak(spinlock_t *lock) { -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION return spin_is_contended(lock); #else return 0; diff --git a/init/init_task.c b/init/init_task.c index 7ab773b9b3cd..bfe06c53b14e 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -174,7 +174,7 @@ struct task_struct init_task #ifdef CONFIG_FUNCTION_GRAPH_TRACER .ret_stack = NULL, #endif -#if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPT) +#if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPTION) .trace_recursion = 0, #endif #ifdef CONFIG_LIVEPATCH diff --git a/init/main.c b/init/main.c index 96f8d5af52d6..653693da8da6 100644 --- a/init/main.c +++ b/init/main.c @@ -433,7 +433,7 @@ noinline void __ref rest_init(void) /* * Enable might_sleep() and smp_processor_id() checks. - * They cannot be enabled earlier because with CONFIG_PREEMPT=y + * They cannot be enabled earlier because with CONFIG_PREEMPTION=y * kernel_thread() would trigger might_sleep() splats. With * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled * already, but it's stuck on the kthreadd_done completion. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b037f195473..604a5e137efe 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3581,7 +3581,7 @@ static inline void sched_tick_start(int cpu) { } static inline void sched_tick_stop(int cpu) { } #endif -#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ +#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \ defined(CONFIG_TRACE_PREEMPT_TOGGLE)) /* * If the value passed in is equal to the current preempt count @@ -3782,7 +3782,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets * called on the nearest possible occasion: * - * - If the kernel is preemptible (CONFIG_PREEMPT=y): + * - If the kernel is preemptible (CONFIG_PREEMPTION=y): * * - in syscall or exception context, at the next outmost * preempt_enable(). (this might be as soon as the wake_up()'s @@ -3791,7 +3791,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) * - in IRQ context, return from interrupt-handler to * preemptible context * - * - If the kernel is not preemptible (CONFIG_PREEMPT is not set) + * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set) * then at the next: * * - cond_resched() call @@ -4033,7 +4033,7 @@ static void __sched notrace preempt_schedule_common(void) } while (need_resched()); } -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION /* * this is the entry point to schedule() from in-kernel preemption * off of preempt_enable. Kernel preemptions off return from interrupt @@ -4105,7 +4105,7 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) } EXPORT_SYMBOL_GPL(preempt_schedule_notrace); -#endif /* CONFIG_PREEMPT */ +#endif /* CONFIG_PREEMPTION */ /* * this is the entry point to schedule() from kernel preemption @@ -5416,7 +5416,7 @@ SYSCALL_DEFINE0(sched_yield) return 0; } -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION int __sched _cond_resched(void) { if (should_resched(0)) { @@ -5433,7 +5433,7 @@ EXPORT_SYMBOL(_cond_resched); * __cond_resched_lock() - if a reschedule is pending, drop the given lock, * call schedule, and on return reacquire the lock. * - * This works OK both with and without CONFIG_PREEMPT. We do strange low-level + * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level * operations here to prevent schedule() from being called twice (once via * spin_unlock(), once by hand). */ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index bc9cfeaac8bd..aff9d76d8d65 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7430,7 +7430,7 @@ static int detach_tasks(struct lb_env *env) detached++; env->imbalance -= load; -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION /* * NEWIDLE balancing is a source of latency, so preemptible * kernels will stop after the first task is detached to minimize diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 802b1f3405f2..f2ce6ba1c5d5 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1943,7 +1943,7 @@ unsigned long arch_scale_freq_capacity(int cpu) #endif #ifdef CONFIG_SMP -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION static inline void double_rq_lock(struct rq *rq1, struct rq *rq2); @@ -1995,7 +1995,7 @@ static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest) return ret; } -#endif /* CONFIG_PREEMPT */ +#endif /* CONFIG_PREEMPTION */ /* * double_lock_balance - lock the busiest runqueue, this_rq is locked already. -- GitLab From 01b1d88b09824bea1a75b0bac04dcf50d9893875 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:38 +0200 Subject: [PATCH 1425/7155] rcu: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch the conditionals in RCU to use CONFIG_PREEMPTION. That's the first step towards RCU on RT. The further tweaks are work in progress. This neither touches the selftest bits which need a closer look by Paul. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.210156346@linutronix.de Signed-off-by: Ingo Molnar --- arch/Kconfig | 2 +- include/linux/rcupdate.h | 2 +- include/linux/rcutree.h | 2 +- include/linux/torture.h | 2 +- kernel/rcu/Kconfig | 8 ++++---- kernel/rcu/tree.c | 6 +++--- kernel/rcu/tree_stall.h | 6 +++--- kernel/trace/Kconfig | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index a7b57dd42c26..c7efbc018f4f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -103,7 +103,7 @@ config STATIC_KEYS_SELFTEST config OPTPROBES def_bool y depends on KPROBES && HAVE_OPTPROBES - select TASKS_RCU if PREEMPT + select TASKS_RCU if PREEMPTION config KPROBES_ON_FTRACE def_bool y diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 8f7167478c1d..c4f76a310443 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -578,7 +578,7 @@ do { \ * * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU), * it is illegal to block while in an RCU read-side critical section. - * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPT + * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPTION * kernel builds, RCU read-side critical sections may be preempted, * but explicit blocking is illegal. Finally, in preemptible RCU * implementations in real-time (with -rt patchset) kernel builds, RCU diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 735601ac27d3..18b1ed9864b0 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -53,7 +53,7 @@ void rcu_scheduler_starting(void); extern int rcu_scheduler_active __read_mostly; void rcu_end_inkernel_boot(void); bool rcu_is_watching(void); -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION void rcu_all_qs(void); #endif diff --git a/include/linux/torture.h b/include/linux/torture.h index a620118385bb..6241f59e2d6f 100644 --- a/include/linux/torture.h +++ b/include/linux/torture.h @@ -86,7 +86,7 @@ void _torture_stop_kthread(char *m, struct task_struct **tp); #define torture_stop_kthread(n, tp) \ _torture_stop_kthread("Stopping " #n " task", &(tp)) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION #define torture_preempt_schedule() preempt_schedule() #else #define torture_preempt_schedule() diff --git a/kernel/rcu/Kconfig b/kernel/rcu/Kconfig index 480edf328b51..7644eda17d62 100644 --- a/kernel/rcu/Kconfig +++ b/kernel/rcu/Kconfig @@ -7,7 +7,7 @@ menu "RCU Subsystem" config TREE_RCU bool - default y if !PREEMPT && SMP + default y if !PREEMPTION && SMP help This option selects the RCU implementation that is designed for very large SMP system with hundreds or @@ -16,7 +16,7 @@ config TREE_RCU config PREEMPT_RCU bool - default y if PREEMPT + default y if PREEMPTION help This option selects the RCU implementation that is designed for very large SMP systems with hundreds or @@ -28,7 +28,7 @@ config PREEMPT_RCU config TINY_RCU bool - default y if !PREEMPT && !SMP + default y if !PREEMPTION && !SMP help This option selects the RCU implementation that is designed for UP systems from which real-time response @@ -70,7 +70,7 @@ config TREE_SRCU This option selects the full-fledged version of SRCU. config TASKS_RCU - def_bool PREEMPT + def_bool PREEMPTION select SRCU help This option enables a task-based RCU implementation that uses diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a14e5fbbea46..5962636502bc 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -1881,7 +1881,7 @@ rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) struct rcu_node *rnp_p; raw_lockdep_assert_held_rcu_node(rnp); - if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT)) || + if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPTION)) || WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp)) || rnp->qsmask != 0) { raw_spin_unlock_irqrestore_rcu_node(rnp, flags); @@ -2205,7 +2205,7 @@ static void force_qs_rnp(int (*f)(struct rcu_data *rdp)) mask = 0; raw_spin_lock_irqsave_rcu_node(rnp, flags); if (rnp->qsmask == 0) { - if (!IS_ENABLED(CONFIG_PREEMPT) || + if (!IS_ENABLED(CONFIG_PREEMPTION) || rcu_preempt_blocked_readers_cgp(rnp)) { /* * No point in scanning bits because they @@ -2622,7 +2622,7 @@ static int rcu_blocking_is_gp(void) { int ret; - if (IS_ENABLED(CONFIG_PREEMPT)) + if (IS_ENABLED(CONFIG_PREEMPTION)) return rcu_scheduler_active == RCU_SCHEDULER_INACTIVE; might_sleep(); /* Check for RCU read-side critical section. */ preempt_disable(); diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h index 065183391f75..9b92bf18b737 100644 --- a/kernel/rcu/tree_stall.h +++ b/kernel/rcu/tree_stall.h @@ -163,7 +163,7 @@ static void rcu_iw_handler(struct irq_work *iwp) // // Printing RCU CPU stall warnings -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION /* * Dump detailed information for all tasks blocking the current RCU @@ -215,7 +215,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp) return ndetected; } -#else /* #ifdef CONFIG_PREEMPT */ +#else /* #ifdef CONFIG_PREEMPTION */ /* * Because preemptible RCU does not exist, we never have to check for @@ -233,7 +233,7 @@ static int rcu_print_task_stall(struct rcu_node *rnp) { return 0; } -#endif /* #else #ifdef CONFIG_PREEMPT */ +#endif /* #else #ifdef CONFIG_PREEMPTION */ /* * Dump stacks of all tasks running on stalled CPUs. First try using diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 98da8998c25c..d2c1fe0b451d 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -146,7 +146,7 @@ config FUNCTION_TRACER select GENERIC_TRACER select CONTEXT_SWITCH_TRACER select GLOB - select TASKS_RCU if PREEMPT + select TASKS_RCU if PREEMPTION help Enable the kernel to trace every kernel function. This is done by using a compiler feature to insert a small, 5-byte No-Operation -- GitLab From 27972765bd0410fc2ef5e86a41de17c71440a2dd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:39 +0200 Subject: [PATCH 1426/7155] locking/spinlocks: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Adjust the comments in the locking code. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.302995288@linutronix.de Signed-off-by: Ingo Molnar --- include/linux/spinlock.h | 2 +- include/linux/spinlock_api_smp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index ed7c4d6b8235..031ce8617df8 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -214,7 +214,7 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock) /* * Define the various spin_lock methods. Note we define these - * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The + * regardless of whether CONFIG_SMP or CONFIG_PREEMPTION are set. The * various methods are defined as nops in the case they are not * required. */ diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index 42dfab89e740..b762eaba4cdf 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -96,7 +96,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) /* * If lockdep is enabled then we use the non-preemption spin-ops - * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are + * even on CONFIG_PREEMPTION, because lockdep assumes that interrupts are * not re-enabled during lock-acquire (which the preempt-spin-ops do): */ #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) -- GitLab From 30c937043b2db09ae3408f5534824f9ececdb581 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:40 +0200 Subject: [PATCH 1427/7155] tracing: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch the conditionals in the tracer over to CONFIG_PREEMPTION. This is the first step to make the tracer work on RT. The other small tweaks are submitted separately. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.409766323@linutronix.de Signed-off-by: Ingo Molnar --- kernel/trace/Kconfig | 4 ++-- kernel/trace/ftrace.c | 2 +- kernel/trace/ring_buffer_benchmark.c | 2 +- kernel/trace/trace_events.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index d2c1fe0b451d..6a64d7772870 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -179,7 +179,7 @@ config TRACE_PREEMPT_TOGGLE config PREEMPTIRQ_EVENTS bool "Enable trace events for preempt and irq disable/enable" select TRACE_IRQFLAGS - select TRACE_PREEMPT_TOGGLE if PREEMPT + select TRACE_PREEMPT_TOGGLE if PREEMPTION select GENERIC_TRACER default n help @@ -214,7 +214,7 @@ config PREEMPT_TRACER bool "Preemption-off Latency Tracer" default n depends on !ARCH_USES_GETTIMEOFFSET - depends on PREEMPT + depends on PREEMPTION select GENERIC_TRACER select TRACER_MAX_TRACE select RING_BUFFER_ALLOW_SWAP diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index eca34503f178..a800e867c1a3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2814,7 +2814,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command) * synchornize_rcu_tasks() will wait for those tasks to * execute and either schedule voluntarily or enter user space. */ - if (IS_ENABLED(CONFIG_PREEMPT)) + if (IS_ENABLED(CONFIG_PREEMPTION)) synchronize_rcu_tasks(); free_ops: diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index 0564f6db0561..09b0b49f346e 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -267,7 +267,7 @@ static void ring_buffer_producer(void) if (consumer && !(cnt % wakeup_interval)) wake_up_process(consumer); -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION /* * If we are a non preempt kernel, the 10 second run will * stop everything while it runs. Instead, we will call diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index c7506bc81b75..5a189fb8ec23 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -255,12 +255,12 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer, local_save_flags(fbuffer->flags); fbuffer->pc = preempt_count(); /* - * If CONFIG_PREEMPT is enabled, then the tracepoint itself disables + * If CONFIG_PREEMPTION is enabled, then the tracepoint itself disables * preemption (adding one to the preempt_count). Since we are * interested in the preempt_count at the time the tracepoint was * hit, we need to subtract one to offset the increment. */ - if (IS_ENABLED(CONFIG_PREEMPT)) + if (IS_ENABLED(CONFIG_PREEMPTION)) fbuffer->pc--; fbuffer->trace_file = trace_file; -- GitLab From 92616606368ee01f1163fcfc986116c810cd48ba Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:41 +0200 Subject: [PATCH 1428/7155] kprobes: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch kprobes conditional over to CONFIG_PREEMPTION. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.516286187@linutronix.de Signed-off-by: Ingo Molnar --- kernel/kprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9873fc627d61..8bc5f1ffd68e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1906,7 +1906,7 @@ int register_kretprobe(struct kretprobe *rp) /* Pre-allocate memory for max kretprobe instances */ if (rp->maxactive <= 0) { -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus()); #else rp->maxactive = num_possible_cpus(); -- GitLab From 48593975aeee548f25e256c515fd1d1e3fb2cc20 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:42 +0200 Subject: [PATCH 1429/7155] x86: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch the entry code, preempt and kprobes conditionals over to CONFIG_PREEMPTION. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.608488448@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_32.S | 6 +++--- arch/x86/entry/entry_64.S | 4 ++-- arch/x86/entry/thunk_32.S | 2 +- arch/x86/entry/thunk_64.S | 4 ++-- arch/x86/include/asm/preempt.h | 2 +- arch/x86/kernel/kprobes/core.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 4f86928246e7..f83ca5aa8b77 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -63,7 +63,7 @@ * enough to patch inline, increasing performance. */ -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION # define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF #else # define preempt_stop(clobbers) @@ -1084,7 +1084,7 @@ restore_all: INTERRUPT_RETURN restore_all_kernel: -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION DISABLE_INTERRUPTS(CLBR_ANY) cmpl $0, PER_CPU_VAR(__preempt_count) jnz .Lno_preempt @@ -1364,7 +1364,7 @@ ENTRY(xen_hypervisor_callback) ENTRY(xen_do_upcall) 1: mov %esp, %eax call xen_evtchn_do_upcall -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION call xen_maybe_preempt_hcall #endif jmp ret_from_intr diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 3f5a978a02a7..9701464341e4 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -662,7 +662,7 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode) /* Returning to kernel space */ retint_kernel: -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION /* Interrupts are off */ /* Check if we need preemption */ btl $9, EFLAGS(%rsp) /* were interrupts off? */ @@ -1113,7 +1113,7 @@ ENTRY(xen_do_hypervisor_callback) /* do_hypervisor_callback(struct *pt_regs) */ call xen_evtchn_do_upcall LEAVE_IRQ_STACK -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION call xen_maybe_preempt_hcall #endif jmp error_exit diff --git a/arch/x86/entry/thunk_32.S b/arch/x86/entry/thunk_32.S index cb3464525b37..2713490611a3 100644 --- a/arch/x86/entry/thunk_32.S +++ b/arch/x86/entry/thunk_32.S @@ -34,7 +34,7 @@ THUNK trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1 #endif -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION THUNK ___preempt_schedule, preempt_schedule THUNK ___preempt_schedule_notrace, preempt_schedule_notrace EXPORT_SYMBOL(___preempt_schedule) diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S index cc20465b2867..ea5c4167086c 100644 --- a/arch/x86/entry/thunk_64.S +++ b/arch/x86/entry/thunk_64.S @@ -46,7 +46,7 @@ THUNK lockdep_sys_exit_thunk,lockdep_sys_exit #endif -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION THUNK ___preempt_schedule, preempt_schedule THUNK ___preempt_schedule_notrace, preempt_schedule_notrace EXPORT_SYMBOL(___preempt_schedule) @@ -55,7 +55,7 @@ #if defined(CONFIG_TRACE_IRQFLAGS) \ || defined(CONFIG_DEBUG_LOCK_ALLOC) \ - || defined(CONFIG_PREEMPT) + || defined(CONFIG_PREEMPTION) .L_restore: popq %r11 popq %r10 diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h index 99a7fa9ab0a3..3d4cb83a8828 100644 --- a/arch/x86/include/asm/preempt.h +++ b/arch/x86/include/asm/preempt.h @@ -102,7 +102,7 @@ static __always_inline bool should_resched(int preempt_offset) return unlikely(raw_cpu_read_4(__preempt_count) == preempt_offset); } -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION extern asmlinkage void ___preempt_schedule(void); # define __preempt_schedule() \ asm volatile ("call ___preempt_schedule" : ASM_CALL_CONSTRAINT) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 0e0b08008b5a..43fc13c831af 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -580,7 +580,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, if (setup_detour_execution(p, regs, reenter)) return; -#if !defined(CONFIG_PREEMPT) +#if !defined(CONFIG_PREEMPTION) if (p->ainsn.boostable && !p->post_handler) { /* Boost up -- we can execute copied instructions directly */ if (!reenter) -- GitLab From cb376c26971ff54f25980ec1f0ae2f06d6a69df0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:43 +0200 Subject: [PATCH 1430/7155] x86/dumpstack: Indicate PREEMPT_RT in dumps Stack dumps print whether the kernel has preemption enabled or not. Extend it so a PREEMPT_RT enabled kernel can be identified. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.699136351@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 2b5886401e5f..e07424e19274 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -367,13 +367,18 @@ NOKPROBE_SYMBOL(oops_end); int __die(const char *str, struct pt_regs *regs, long err) { + const char *pr = ""; + /* Save the regs of the first oops for the executive summary later. */ if (!die_counter) exec_summary_regs = *regs; + if (IS_ENABLED(CONFIG_PREEMPTION)) + pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT"; + printk(KERN_DEFAULT "%s: %04lx [#%d]%s%s%s%s%s\n", str, err & 0xffff, ++die_counter, - IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "", + pr, IS_ENABLED(CONFIG_SMP) ? " SMP" : "", debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "", IS_ENABLED(CONFIG_KASAN) ? " KASAN" : "", -- GitLab From 09c7e8b21d67c3c78ab9701dbc0fb1e9f14a0ba5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 23:19:44 +0200 Subject: [PATCH 1431/7155] x86/kvm: Use CONFIG_PREEMPTION CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT. Switch the conditional for async pagefaults to use CONFIG_PREEMPTION. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Paolo Bonzini Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20190726212124.789755413@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b7f34fe2171e..3d07f84c4846 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -314,7 +314,7 @@ static void kvm_guest_cpu_init(void) if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) { u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason)); -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION pa |= KVM_ASYNC_PF_SEND_ALWAYS; #endif pa |= KVM_ASYNC_PF_ENABLED; -- GitLab From 5a056cd7ead2b72b00fea8a6819fb93eeb12e313 Mon Sep 17 00:00:00 2001 From: Paul Greenwalt Date: Wed, 26 Jun 2019 02:20:12 -0700 Subject: [PATCH 1432/7155] ice: add lp_advertising flow control support Add support for reporting link partner advertising when ETHTOOL_GLINKSETTINGS defined. Get pause param reports the Tx/Rx pause configured, and then ethtool issues ETHTOOL_GSET ioctl and ice_get_settings_link_up reports the negotiated Tx/Rx pause. Negotiated pause frame report per IEEE 802.3-2005 table 288-3. $ ethtool --show-pause ens6f0 Pause parameters for ens6f0: Autonegotiate: on RX: on TX: on RX negotiated: on TX negotiated: on $ ethtool ens6f0 Settings for ens6f0: Supported ports: [ FIBRE ] Supported link modes: 25000baseCR/Full Supported pause frame use: Symmetric Supports auto-negotiation: Yes Supported FEC modes: None BaseR RS Advertised link modes: 25000baseCR/Full Advertised pause frame use: Symmetric Receive-only Advertised auto-negotiation: Yes Advertised FEC modes: None BaseR RS Link partner advertised link modes: Not reported Link partner advertised pause frame use: Symmetric Link partner advertised auto-negotiation: Yes Link partner advertised FEC modes: Not reported Speed: 25000Mb/s Duplex: Full Port: Direct Attach Copper PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: g Wake-on: g Current message level: 0x00000007 (7) drv probe link Link detected: yes When ETHTOOL_GLINKSETTINGS is not defined, get pause param reports the negotiated Tx/Rx pause. Signed-off-by: Paul Greenwalt Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 104 +++++++++++++------ 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 52083a63dee6..d3ba535bd65a 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1716,6 +1716,7 @@ ice_get_settings_link_up(struct ethtool_link_ksettings *ks, struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_port_info *pi = np->vsi->port_info; struct ethtool_link_ksettings cap_ksettings; struct ice_link_status *link_info; struct ice_vsi *vsi = np->vsi; @@ -2040,6 +2041,33 @@ ice_get_settings_link_up(struct ethtool_link_ksettings *ks, break; } ks->base.duplex = DUPLEX_FULL; + + if (link_info->an_info & ICE_AQ_AN_COMPLETED) + ethtool_link_ksettings_add_link_mode(ks, lp_advertising, + Autoneg); + + /* Set flow control negotiated Rx/Tx pause */ + switch (pi->fc.current_mode) { + case ICE_FC_FULL: + ethtool_link_ksettings_add_link_mode(ks, lp_advertising, Pause); + break; + case ICE_FC_TX_PAUSE: + ethtool_link_ksettings_add_link_mode(ks, lp_advertising, Pause); + ethtool_link_ksettings_add_link_mode(ks, lp_advertising, + Asym_Pause); + break; + case ICE_FC_RX_PAUSE: + ethtool_link_ksettings_add_link_mode(ks, lp_advertising, + Asym_Pause); + break; + case ICE_FC_PFC: + /* fall through */ + default: + ethtool_link_ksettings_del_link_mode(ks, lp_advertising, Pause); + ethtool_link_ksettings_del_link_mode(ks, lp_advertising, + Asym_Pause); + break; + } } /** @@ -2078,9 +2106,12 @@ ice_get_link_ksettings(struct net_device *netdev, struct ice_aqc_get_phy_caps_data *caps; struct ice_link_status *hw_link_info; struct ice_vsi *vsi = np->vsi; + enum ice_status status; + int err = 0; ethtool_link_ksettings_zero_link_mode(ks, supported); ethtool_link_ksettings_zero_link_mode(ks, advertising); + ethtool_link_ksettings_zero_link_mode(ks, lp_advertising); hw_link_info = &vsi->port_info->phy.link_info; /* set speed and duplex */ @@ -2125,48 +2156,36 @@ ice_get_link_ksettings(struct net_device *netdev, /* flow control is symmetric and always supported */ ethtool_link_ksettings_add_link_mode(ks, supported, Pause); - switch (vsi->port_info->fc.req_mode) { - case ICE_FC_FULL: + caps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*caps), GFP_KERNEL); + if (!caps) + return -ENOMEM; + + status = ice_aq_get_phy_caps(vsi->port_info, false, + ICE_AQC_REPORT_SW_CFG, caps, NULL); + if (status) { + err = -EIO; + goto done; + } + + /* Set the advertised flow control based on the PHY capability */ + if ((caps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) && + (caps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)) { ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); - break; - case ICE_FC_TX_PAUSE: ethtool_link_ksettings_add_link_mode(ks, advertising, Asym_Pause); - break; - case ICE_FC_RX_PAUSE: + } else if (caps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) { + ethtool_link_ksettings_add_link_mode(ks, advertising, + Asym_Pause); + } else if (caps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) { ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); ethtool_link_ksettings_add_link_mode(ks, advertising, Asym_Pause); - break; - case ICE_FC_PFC: - default: + } else { ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); ethtool_link_ksettings_del_link_mode(ks, advertising, Asym_Pause); - break; } - caps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*caps), GFP_KERNEL); - if (!caps) - goto done; - - if (ice_aq_get_phy_caps(vsi->port_info, false, ICE_AQC_REPORT_TOPO_CAP, - caps, NULL)) - netdev_info(netdev, "Get phy capability failed.\n"); - - /* Set supported FEC modes based on PHY capability */ - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); - - if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || - caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN) - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); - if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - - if (ice_aq_get_phy_caps(vsi->port_info, false, ICE_AQC_REPORT_SW_CFG, - caps, NULL)) - netdev_info(netdev, "Get phy capability failed.\n"); - /* Set advertised FEC modes based on PHY capability */ ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); @@ -2178,9 +2197,25 @@ ice_get_link_ksettings(struct net_device *netdev, caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ) ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + status = ice_aq_get_phy_caps(vsi->port_info, false, + ICE_AQC_REPORT_TOPO_CAP, caps, NULL); + if (status) { + err = -EIO; + goto done; + } + + /* Set supported FEC modes based on PHY capability */ + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + + if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || + caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN) + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + done: devm_kfree(&vsi->back->pdev->dev, caps); - return 0; + return err; } /** @@ -2763,6 +2798,11 @@ static int ice_nway_reset(struct net_device *netdev) * ice_get_pauseparam - Get Flow Control status * @netdev: network interface device structure * @pause: ethernet pause (flow control) parameters + * + * Get requested flow control status from PHY capability. + * If autoneg is true, then ethtool will send the ETHTOOL_GSET ioctl which + * is handled by ice_get_link_ksettings. ice_get_link_ksettings will report + * the negotiated Rx/Tx pause via lp_advertising. */ static void ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -- GitLab From 36517fd397f124acfa396e770468530136f4207d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 26 Jun 2019 02:20:13 -0700 Subject: [PATCH 1433/7155] ice: track hardware stat registers past rollover Currently, ice_stat_update32 and ice_stat_update40 will limit the value of the software statistic to 32 or 40 bits wide, depending on which register is being read. This means that if a driver is running for a long time, the displayed software register values will roll over to zero at 40 bits or 32 bits. This occurs because the functions directly assign the difference between the previous value and current value of the hardware statistic. Instead, add this value to the current software statistic, and then update the previous value. In this way, each time ice_stat_update40 or ice_stat_update32 are called, they will increment the software tracking value by the difference of the hardware register from its last read. The software tracking value will correctly count up until it overflows a u64. The only requirement is that the ice_stat_update functions be called at least once each time the hardware register overflows. While we're fixing ice_stat_update40, modify it to use rd64 instead of two calls to rd32. Additionally, drop the now unnecessary hireg function parameter. Signed-off-by: Jacob Keller Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 57 +++++++----- drivers/net/ethernet/intel/ice/ice_common.h | 4 +- .../net/ethernet/intel/ice/ice_hw_autogen.h | 30 ------- drivers/net/ethernet/intel/ice/ice_lib.c | 40 ++++----- drivers/net/ethernet/intel/ice/ice_main.c | 90 ++++++++----------- 5 files changed, 91 insertions(+), 130 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 2e0731c1e1a3..4be3559de207 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -3240,40 +3240,44 @@ void ice_replay_post(struct ice_hw *hw) /** * ice_stat_update40 - read 40 bit stat from the chip and update stat values * @hw: ptr to the hardware info - * @hireg: high 32 bit HW register to read from - * @loreg: low 32 bit HW register to read from + * @reg: offset of 64 bit HW register to read from * @prev_stat_loaded: bool to specify if previous stats are loaded * @prev_stat: ptr to previous loaded stat value * @cur_stat: ptr to current stat value */ void -ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg, - bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat) +ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, + u64 *prev_stat, u64 *cur_stat) { - u64 new_data; - - new_data = rd32(hw, loreg); - new_data |= ((u64)(rd32(hw, hireg) & 0xFFFF)) << 32; + u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1); /* device stats are not reset at PFR, they likely will not be zeroed - * when the driver starts. So save the first values read and use them as - * offsets to be subtracted from the raw values in order to report stats - * that count from zero. + * when the driver starts. Thus, save the value from the first read + * without adding to the statistic value so that we report stats which + * count up from zero. */ - if (!prev_stat_loaded) + if (!prev_stat_loaded) { *prev_stat = new_data; + return; + } + + /* Calculate the difference between the new and old values, and then + * add it to the software stat value. + */ if (new_data >= *prev_stat) - *cur_stat = new_data - *prev_stat; + *cur_stat += new_data - *prev_stat; else /* to manage the potential roll-over */ - *cur_stat = (new_data + BIT_ULL(40)) - *prev_stat; - *cur_stat &= 0xFFFFFFFFFFULL; + *cur_stat += (new_data + BIT_ULL(40)) - *prev_stat; + + /* Update the previously stored value to prepare for next read */ + *prev_stat = new_data; } /** * ice_stat_update32 - read 32 bit stat from the chip and update stat values * @hw: ptr to the hardware info - * @reg: HW register to read from + * @reg: offset of HW register to read from * @prev_stat_loaded: bool to specify if previous stats are loaded * @prev_stat: ptr to previous loaded stat value * @cur_stat: ptr to current stat value @@ -3287,17 +3291,26 @@ ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, new_data = rd32(hw, reg); /* device stats are not reset at PFR, they likely will not be zeroed - * when the driver starts. So save the first values read and use them as - * offsets to be subtracted from the raw values in order to report stats - * that count from zero. + * when the driver starts. Thus, save the value from the first read + * without adding to the statistic value so that we report stats which + * count up from zero. */ - if (!prev_stat_loaded) + if (!prev_stat_loaded) { *prev_stat = new_data; + return; + } + + /* Calculate the difference between the new and old values, and then + * add it to the software stat value. + */ if (new_data >= *prev_stat) - *cur_stat = new_data - *prev_stat; + *cur_stat += new_data - *prev_stat; else /* to manage the potential roll-over */ - *cur_stat = (new_data + BIT_ULL(32)) - *prev_stat; + *cur_stat += (new_data + BIT_ULL(32)) - *prev_stat; + + /* Update the previously stored value to prepare for next read */ + *prev_stat = new_data; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index d1f8353fe6bb..68218e63afc2 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -123,8 +123,8 @@ enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle); void ice_replay_post(struct ice_hw *hw); void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf); void -ice_stat_update40(struct ice_hw *hw, u32 hireg, u32 loreg, - bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat); +ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, + u64 *prev_stat, u64 *cur_stat); void ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat); diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 6c5ce05742b1..3250dfc00002 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -281,14 +281,10 @@ #define GL_PWR_MODE_CTL 0x000B820C #define GL_PWR_MODE_CTL_CAR_MAX_BW_S 30 #define GL_PWR_MODE_CTL_CAR_MAX_BW_M ICE_M(0x3, 30) -#define GLPRT_BPRCH(_i) (0x00381384 + ((_i) * 8)) #define GLPRT_BPRCL(_i) (0x00381380 + ((_i) * 8)) -#define GLPRT_BPTCH(_i) (0x00381244 + ((_i) * 8)) #define GLPRT_BPTCL(_i) (0x00381240 + ((_i) * 8)) #define GLPRT_CRCERRS(_i) (0x00380100 + ((_i) * 8)) -#define GLPRT_GORCH(_i) (0x00380004 + ((_i) * 8)) #define GLPRT_GORCL(_i) (0x00380000 + ((_i) * 8)) -#define GLPRT_GOTCH(_i) (0x00380B44 + ((_i) * 8)) #define GLPRT_GOTCL(_i) (0x00380B40 + ((_i) * 8)) #define GLPRT_ILLERRC(_i) (0x003801C0 + ((_i) * 8)) #define GLPRT_LXOFFRXC(_i) (0x003802C0 + ((_i) * 8)) @@ -296,38 +292,22 @@ #define GLPRT_LXONRXC(_i) (0x00380280 + ((_i) * 8)) #define GLPRT_LXONTXC(_i) (0x00381140 + ((_i) * 8)) #define GLPRT_MLFC(_i) (0x00380040 + ((_i) * 8)) -#define GLPRT_MPRCH(_i) (0x00381344 + ((_i) * 8)) #define GLPRT_MPRCL(_i) (0x00381340 + ((_i) * 8)) -#define GLPRT_MPTCH(_i) (0x00381204 + ((_i) * 8)) #define GLPRT_MPTCL(_i) (0x00381200 + ((_i) * 8)) #define GLPRT_MRFC(_i) (0x00380080 + ((_i) * 8)) -#define GLPRT_PRC1023H(_i) (0x00380A04 + ((_i) * 8)) #define GLPRT_PRC1023L(_i) (0x00380A00 + ((_i) * 8)) -#define GLPRT_PRC127H(_i) (0x00380944 + ((_i) * 8)) #define GLPRT_PRC127L(_i) (0x00380940 + ((_i) * 8)) -#define GLPRT_PRC1522H(_i) (0x00380A44 + ((_i) * 8)) #define GLPRT_PRC1522L(_i) (0x00380A40 + ((_i) * 8)) -#define GLPRT_PRC255H(_i) (0x00380984 + ((_i) * 8)) #define GLPRT_PRC255L(_i) (0x00380980 + ((_i) * 8)) -#define GLPRT_PRC511H(_i) (0x003809C4 + ((_i) * 8)) #define GLPRT_PRC511L(_i) (0x003809C0 + ((_i) * 8)) -#define GLPRT_PRC64H(_i) (0x00380904 + ((_i) * 8)) #define GLPRT_PRC64L(_i) (0x00380900 + ((_i) * 8)) -#define GLPRT_PRC9522H(_i) (0x00380A84 + ((_i) * 8)) #define GLPRT_PRC9522L(_i) (0x00380A80 + ((_i) * 8)) -#define GLPRT_PTC1023H(_i) (0x00380C84 + ((_i) * 8)) #define GLPRT_PTC1023L(_i) (0x00380C80 + ((_i) * 8)) -#define GLPRT_PTC127H(_i) (0x00380BC4 + ((_i) * 8)) #define GLPRT_PTC127L(_i) (0x00380BC0 + ((_i) * 8)) -#define GLPRT_PTC1522H(_i) (0x00380CC4 + ((_i) * 8)) #define GLPRT_PTC1522L(_i) (0x00380CC0 + ((_i) * 8)) -#define GLPRT_PTC255H(_i) (0x00380C04 + ((_i) * 8)) #define GLPRT_PTC255L(_i) (0x00380C00 + ((_i) * 8)) -#define GLPRT_PTC511H(_i) (0x00380C44 + ((_i) * 8)) #define GLPRT_PTC511L(_i) (0x00380C40 + ((_i) * 8)) -#define GLPRT_PTC64H(_i) (0x00380B84 + ((_i) * 8)) #define GLPRT_PTC64L(_i) (0x00380B80 + ((_i) * 8)) -#define GLPRT_PTC9522H(_i) (0x00380D04 + ((_i) * 8)) #define GLPRT_PTC9522L(_i) (0x00380D00 + ((_i) * 8)) #define GLPRT_PXOFFRXC(_i, _j) (0x00380500 + ((_i) * 8 + (_j) * 64)) #define GLPRT_PXOFFTXC(_i, _j) (0x00380F40 + ((_i) * 8 + (_j) * 64)) @@ -340,27 +320,17 @@ #define GLPRT_RUC(_i) (0x00380200 + ((_i) * 8)) #define GLPRT_RXON2OFFCNT(_i, _j) (0x00380700 + ((_i) * 8 + (_j) * 64)) #define GLPRT_TDOLD(_i) (0x00381280 + ((_i) * 8)) -#define GLPRT_UPRCH(_i) (0x00381304 + ((_i) * 8)) #define GLPRT_UPRCL(_i) (0x00381300 + ((_i) * 8)) -#define GLPRT_UPTCH(_i) (0x003811C4 + ((_i) * 8)) #define GLPRT_UPTCL(_i) (0x003811C0 + ((_i) * 8)) -#define GLV_BPRCH(_i) (0x003B6004 + ((_i) * 8)) #define GLV_BPRCL(_i) (0x003B6000 + ((_i) * 8)) -#define GLV_BPTCH(_i) (0x0030E004 + ((_i) * 8)) #define GLV_BPTCL(_i) (0x0030E000 + ((_i) * 8)) -#define GLV_GORCH(_i) (0x003B0004 + ((_i) * 8)) #define GLV_GORCL(_i) (0x003B0000 + ((_i) * 8)) -#define GLV_GOTCH(_i) (0x00300004 + ((_i) * 8)) #define GLV_GOTCL(_i) (0x00300000 + ((_i) * 8)) -#define GLV_MPRCH(_i) (0x003B4004 + ((_i) * 8)) #define GLV_MPRCL(_i) (0x003B4000 + ((_i) * 8)) -#define GLV_MPTCH(_i) (0x0030C004 + ((_i) * 8)) #define GLV_MPTCL(_i) (0x0030C000 + ((_i) * 8)) #define GLV_RDPC(_i) (0x00294C04 + ((_i) * 4)) #define GLV_TEPC(_VSI) (0x00312000 + ((_VSI) * 4)) -#define GLV_UPRCH(_i) (0x003B2004 + ((_i) * 8)) #define GLV_UPRCL(_i) (0x003B2000 + ((_i) * 8)) -#define GLV_UPTCH(_i) (0x0030A004 + ((_i) * 8)) #define GLV_UPTCL(_i) (0x0030A000 + ((_i) * 8)) #define PF_VT_PFALLOC_HIF 0x0009DD80 #define VSIQF_HKEY_MAX_INDEX 12 diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index a19f5920733b..e9e8340b1ab7 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1477,40 +1477,32 @@ void ice_update_eth_stats(struct ice_vsi *vsi) prev_es = &vsi->eth_stats_prev; cur_es = &vsi->eth_stats; - ice_stat_update40(hw, GLV_GORCH(vsi_num), GLV_GORCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->rx_bytes, - &cur_es->rx_bytes); + ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->rx_bytes, &cur_es->rx_bytes); - ice_stat_update40(hw, GLV_UPRCH(vsi_num), GLV_UPRCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->rx_unicast, - &cur_es->rx_unicast); + ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->rx_unicast, &cur_es->rx_unicast); - ice_stat_update40(hw, GLV_MPRCH(vsi_num), GLV_MPRCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->rx_multicast, - &cur_es->rx_multicast); + ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->rx_multicast, &cur_es->rx_multicast); - ice_stat_update40(hw, GLV_BPRCH(vsi_num), GLV_BPRCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->rx_broadcast, - &cur_es->rx_broadcast); + ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->rx_broadcast, &cur_es->rx_broadcast); ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, &prev_es->rx_discards, &cur_es->rx_discards); - ice_stat_update40(hw, GLV_GOTCH(vsi_num), GLV_GOTCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->tx_bytes, - &cur_es->tx_bytes); + ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->tx_bytes, &cur_es->tx_bytes); - ice_stat_update40(hw, GLV_UPTCH(vsi_num), GLV_UPTCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->tx_unicast, - &cur_es->tx_unicast); + ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->tx_unicast, &cur_es->tx_unicast); - ice_stat_update40(hw, GLV_MPTCH(vsi_num), GLV_MPTCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->tx_multicast, - &cur_es->tx_multicast); + ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->tx_multicast, &cur_es->tx_multicast); - ice_stat_update40(hw, GLV_BPTCH(vsi_num), GLV_BPTCL(vsi_num), - vsi->stat_offsets_loaded, &prev_es->tx_broadcast, - &cur_es->tx_broadcast); + ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded, + &prev_es->tx_broadcast, &cur_es->tx_broadcast); ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, &prev_es->tx_errors, &cur_es->tx_errors); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 63db08d9bafa..f490e65c64bc 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3176,96 +3176,82 @@ static void ice_update_pf_stats(struct ice_pf *pf) cur_ps = &pf->stats; pf_id = hw->pf_id; - ice_stat_update40(hw, GLPRT_GORCH(pf_id), GLPRT_GORCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.rx_bytes, + ice_stat_update40(hw, GLPRT_GORCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.rx_bytes, &cur_ps->eth.rx_bytes); - ice_stat_update40(hw, GLPRT_UPRCH(pf_id), GLPRT_UPRCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.rx_unicast, + ice_stat_update40(hw, GLPRT_UPRCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.rx_unicast, &cur_ps->eth.rx_unicast); - ice_stat_update40(hw, GLPRT_MPRCH(pf_id), GLPRT_MPRCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.rx_multicast, + ice_stat_update40(hw, GLPRT_MPRCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.rx_multicast, &cur_ps->eth.rx_multicast); - ice_stat_update40(hw, GLPRT_BPRCH(pf_id), GLPRT_BPRCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.rx_broadcast, + ice_stat_update40(hw, GLPRT_BPRCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.rx_broadcast, &cur_ps->eth.rx_broadcast); - ice_stat_update40(hw, GLPRT_GOTCH(pf_id), GLPRT_GOTCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.tx_bytes, + ice_stat_update40(hw, GLPRT_GOTCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.tx_bytes, &cur_ps->eth.tx_bytes); - ice_stat_update40(hw, GLPRT_UPTCH(pf_id), GLPRT_UPTCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.tx_unicast, + ice_stat_update40(hw, GLPRT_UPTCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.tx_unicast, &cur_ps->eth.tx_unicast); - ice_stat_update40(hw, GLPRT_MPTCH(pf_id), GLPRT_MPTCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.tx_multicast, + ice_stat_update40(hw, GLPRT_MPTCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.tx_multicast, &cur_ps->eth.tx_multicast); - ice_stat_update40(hw, GLPRT_BPTCH(pf_id), GLPRT_BPTCL(pf_id), - pf->stat_prev_loaded, &prev_ps->eth.tx_broadcast, + ice_stat_update40(hw, GLPRT_BPTCL(pf_id), pf->stat_prev_loaded, + &prev_ps->eth.tx_broadcast, &cur_ps->eth.tx_broadcast); ice_stat_update32(hw, GLPRT_TDOLD(pf_id), pf->stat_prev_loaded, &prev_ps->tx_dropped_link_down, &cur_ps->tx_dropped_link_down); - ice_stat_update40(hw, GLPRT_PRC64H(pf_id), GLPRT_PRC64L(pf_id), - pf->stat_prev_loaded, &prev_ps->rx_size_64, - &cur_ps->rx_size_64); + ice_stat_update40(hw, GLPRT_PRC64L(pf_id), pf->stat_prev_loaded, + &prev_ps->rx_size_64, &cur_ps->rx_size_64); - ice_stat_update40(hw, GLPRT_PRC127H(pf_id), GLPRT_PRC127L(pf_id), - pf->stat_prev_loaded, &prev_ps->rx_size_127, - &cur_ps->rx_size_127); + ice_stat_update40(hw, GLPRT_PRC127L(pf_id), pf->stat_prev_loaded, + &prev_ps->rx_size_127, &cur_ps->rx_size_127); - ice_stat_update40(hw, GLPRT_PRC255H(pf_id), GLPRT_PRC255L(pf_id), - pf->stat_prev_loaded, &prev_ps->rx_size_255, - &cur_ps->rx_size_255); + ice_stat_update40(hw, GLPRT_PRC255L(pf_id), pf->stat_prev_loaded, + &prev_ps->rx_size_255, &cur_ps->rx_size_255); - ice_stat_update40(hw, GLPRT_PRC511H(pf_id), GLPRT_PRC511L(pf_id), - pf->stat_prev_loaded, &prev_ps->rx_size_511, - &cur_ps->rx_size_511); + ice_stat_update40(hw, GLPRT_PRC511L(pf_id), pf->stat_prev_loaded, + &prev_ps->rx_size_511, &cur_ps->rx_size_511); - ice_stat_update40(hw, GLPRT_PRC1023H(pf_id), - GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PRC1023L(pf_id), pf->stat_prev_loaded, &prev_ps->rx_size_1023, &cur_ps->rx_size_1023); - ice_stat_update40(hw, GLPRT_PRC1522H(pf_id), - GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PRC1522L(pf_id), pf->stat_prev_loaded, &prev_ps->rx_size_1522, &cur_ps->rx_size_1522); - ice_stat_update40(hw, GLPRT_PRC9522H(pf_id), - GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PRC9522L(pf_id), pf->stat_prev_loaded, &prev_ps->rx_size_big, &cur_ps->rx_size_big); - ice_stat_update40(hw, GLPRT_PTC64H(pf_id), GLPRT_PTC64L(pf_id), - pf->stat_prev_loaded, &prev_ps->tx_size_64, - &cur_ps->tx_size_64); + ice_stat_update40(hw, GLPRT_PTC64L(pf_id), pf->stat_prev_loaded, + &prev_ps->tx_size_64, &cur_ps->tx_size_64); - ice_stat_update40(hw, GLPRT_PTC127H(pf_id), GLPRT_PTC127L(pf_id), - pf->stat_prev_loaded, &prev_ps->tx_size_127, - &cur_ps->tx_size_127); + ice_stat_update40(hw, GLPRT_PTC127L(pf_id), pf->stat_prev_loaded, + &prev_ps->tx_size_127, &cur_ps->tx_size_127); - ice_stat_update40(hw, GLPRT_PTC255H(pf_id), GLPRT_PTC255L(pf_id), - pf->stat_prev_loaded, &prev_ps->tx_size_255, - &cur_ps->tx_size_255); + ice_stat_update40(hw, GLPRT_PTC255L(pf_id), pf->stat_prev_loaded, + &prev_ps->tx_size_255, &cur_ps->tx_size_255); - ice_stat_update40(hw, GLPRT_PTC511H(pf_id), GLPRT_PTC511L(pf_id), - pf->stat_prev_loaded, &prev_ps->tx_size_511, - &cur_ps->tx_size_511); + ice_stat_update40(hw, GLPRT_PTC511L(pf_id), pf->stat_prev_loaded, + &prev_ps->tx_size_511, &cur_ps->tx_size_511); - ice_stat_update40(hw, GLPRT_PTC1023H(pf_id), - GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PTC1023L(pf_id), pf->stat_prev_loaded, &prev_ps->tx_size_1023, &cur_ps->tx_size_1023); - ice_stat_update40(hw, GLPRT_PTC1522H(pf_id), - GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PTC1522L(pf_id), pf->stat_prev_loaded, &prev_ps->tx_size_1522, &cur_ps->tx_size_1522); - ice_stat_update40(hw, GLPRT_PTC9522H(pf_id), - GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded, + ice_stat_update40(hw, GLPRT_PTC9522L(pf_id), pf->stat_prev_loaded, &prev_ps->tx_size_big, &cur_ps->tx_size_big); ice_stat_update32(hw, GLPRT_LXONRXC(pf_id), pf->stat_prev_loaded, -- GitLab From 17bc6d07212c8bc4521056a7f871d143192d385c Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Wed, 26 Jun 2019 02:20:14 -0700 Subject: [PATCH 1434/7155] ice: Move vector base setup to PF VSI When interrupt tracking was refactored, during rebuild, the call to ice_vsi_setup_vector_base() was inadvertently removed from the PF VSI instead of being removed from the VF VSI. During reset, the failure to properly setup the vector base generates a call trace. Correct this so that resets/rebuilds properly complete. Fixes: cbe66bfee6a0 ("ice: Refactor interrupt tracking") Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index e9e8340b1ab7..01f38abd4277 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2978,6 +2978,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) if (ret) goto err_rings; + ret = ice_vsi_setup_vector_base(vsi); + if (ret) + goto err_vectors; + ret = ice_vsi_set_q_vectors_reg_idx(vsi); if (ret) goto err_vectors; @@ -2999,10 +3003,6 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) if (ret) goto err_rings; - ret = ice_vsi_setup_vector_base(vsi); - if (ret) - goto err_vectors; - ret = ice_vsi_set_q_vectors_reg_idx(vsi); if (ret) goto err_vectors; -- GitLab From c31a5c25bb19c62d1cea69d3abcc7e0405bd4596 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 26 Jun 2019 02:20:15 -0700 Subject: [PATCH 1435/7155] ice: Always set prefena when configuring an Rx queue Currently we are always setting prefena to 0. This is causing the hardware to only fetch descriptors when there are none free in the cache for a received packet instead of prefetching when it has used the last descriptor regardless of incoming packets. Fix this by allowing the hardware to prefetch Rx descriptors. Signed-off-by: Brett Creeley Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 9 ++++++++- drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 4be3559de207..01e5ecaaa322 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -1078,6 +1078,7 @@ static const struct ice_ctx_ele ice_rlan_ctx_info[] = { ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena, 1, 195), ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena, 1, 196), ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh, 3, 198), + ICE_CTX_STORE(ice_rlan_ctx, prefena, 1, 201), { 0 } }; @@ -1088,7 +1089,8 @@ static const struct ice_ctx_ele ice_rlan_ctx_info[] = { * @rxq_index: the index of the Rx queue * * Converts rxq context from sparse to dense structure and then writes - * it to HW register space + * it to HW register space and enables the hardware to prefetch descriptors + * instead of only fetching them on demand */ enum ice_status ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, @@ -1096,6 +1098,11 @@ ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, { u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; + if (!rlan_ctx) + return ICE_ERR_BAD_PTR; + + rlan_ctx->prefena = 1; + ice_set_ctx((u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info); return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index); } diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index 510a8c900e61..57ea6811fe2c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -290,6 +290,7 @@ struct ice_rlan_ctx { u8 tphdata_ena; u8 tphhead_ena; u16 lrxqthresh; /* bigger than needed, see above for reason */ + u8 prefena; /* NOTE: normally must be set to 1 at init */ }; struct ice_ctx_ele { -- GitLab From 5c91ecfda5a8bfbc4697b35fe875cbc43a0f9100 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 26 Jun 2019 02:20:16 -0700 Subject: [PATCH 1436/7155] ice: separate out control queue lock creation The ice_init_all_ctrlq and ice_shutdown_all_ctrlq functions create and destroy the locks used to protect the send and receive process of each control queue. This is problematic, as the driver may use these functions to shutdown and re-initialize the control queues at run time. For example, it may do this in response to a device reset. If the driver failed to recover from a reset, it might leave the control queues offline. In this case, the locks will no longer be initialized. A later call to ice_sq_send_cmd will then attempt to acquire a lock that has been destroyed. It is incorrect behavior to access a lock that has been destroyed. Indeed, ice_aq_send_cmd already tries to avoid accessing an offline control queue, but the check occurs inside the lock. The root of the problem is that the locks are destroyed at run time. Modify ice_init_all_ctrlq and ice_shutdown_all_ctrlq such that they no longer create or destroy the locks. Introduce new functions, ice_create_all_ctrlq and ice_destroy_all_ctrlq. Call these functions in ice_init_hw and ice_deinit_hw. Now, the control queue locks will remain valid for the life of the driver, and will not be destroyed until the driver unloads. This also allows removing a duplicate check of the sq.count and rq.count values when shutting down the controlqs. The ice_shutdown_ctrlq function already checks this value under the lock. Previously commit dec64ff10ed9 ("ice: use [sr]q.count when checking if queue is initialized") needed this check to happen outside the lock, because it prevented duplicate attempts at destroying the locks. The driver may now safely use ice_init_all_ctrlq and ice_shutdown_all_ctrlq while handling reset events, without causing the locks to be invalid. Signed-off-by: Jacob Keller Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 6 +- drivers/net/ethernet/intel/ice/ice_common.h | 2 + drivers/net/ethernet/intel/ice/ice_controlq.c | 112 ++++++++++++++---- 3 files changed, 91 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 01e5ecaaa322..5f9dc76699d2 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -740,7 +740,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw) ice_get_itr_intrl_gran(hw); - status = ice_init_all_ctrlq(hw); + status = ice_create_all_ctrlq(hw); if (status) goto err_unroll_cqinit; @@ -855,7 +855,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw) err_unroll_alloc: devm_kfree(ice_hw_to_dev(hw), hw->port_info); err_unroll_cqinit: - ice_shutdown_all_ctrlq(hw); + ice_destroy_all_ctrlq(hw); return status; } @@ -881,7 +881,7 @@ void ice_deinit_hw(struct ice_hw *hw) /* Attempt to disable FW logging before shutting down control queues */ ice_cfg_fw_log(hw, false); - ice_shutdown_all_ctrlq(hw); + ice_destroy_all_ctrlq(hw); /* Clear VSI contexts if not already cleared */ ice_clear_all_vsi_ctx(hw); diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 68218e63afc2..e376d1eadba4 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -17,8 +17,10 @@ enum ice_status ice_init_hw(struct ice_hw *hw); void ice_deinit_hw(struct ice_hw *hw); enum ice_status ice_check_reset(struct ice_hw *hw); enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req); +enum ice_status ice_create_all_ctrlq(struct ice_hw *hw); enum ice_status ice_init_all_ctrlq(struct ice_hw *hw); void ice_shutdown_all_ctrlq(struct ice_hw *hw); +void ice_destroy_all_ctrlq(struct ice_hw *hw); enum ice_status ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq, struct ice_rq_event_info *e, u16 *pending); diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c index e91ac4df0242..2353166c654e 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.c +++ b/drivers/net/ethernet/intel/ice/ice_controlq.c @@ -310,7 +310,7 @@ ice_cfg_rq_regs(struct ice_hw *hw, struct ice_ctl_q_info *cq) * @cq: pointer to the specific Control queue * * This is the main initialization routine for the Control Send Queue - * Prior to calling this function, drivers *MUST* set the following fields + * Prior to calling this function, the driver *MUST* set the following fields * in the cq->structure: * - cq->num_sq_entries * - cq->sq_buf_size @@ -369,7 +369,7 @@ static enum ice_status ice_init_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq) * @cq: pointer to the specific Control queue * * The main initialization routine for the Admin Receive (Event) Queue. - * Prior to calling this function, drivers *MUST* set the following fields + * Prior to calling this function, the driver *MUST* set the following fields * in the cq->structure: * - cq->num_rq_entries * - cq->rq_buf_size @@ -569,14 +569,8 @@ static enum ice_status ice_init_check_adminq(struct ice_hw *hw) return 0; init_ctrlq_free_rq: - if (cq->rq.count) { - ice_shutdown_rq(hw, cq); - mutex_destroy(&cq->rq_lock); - } - if (cq->sq.count) { - ice_shutdown_sq(hw, cq); - mutex_destroy(&cq->sq_lock); - } + ice_shutdown_rq(hw, cq); + ice_shutdown_sq(hw, cq); return status; } @@ -585,12 +579,14 @@ static enum ice_status ice_init_check_adminq(struct ice_hw *hw) * @hw: pointer to the hardware structure * @q_type: specific Control queue type * - * Prior to calling this function, drivers *MUST* set the following fields + * Prior to calling this function, the driver *MUST* set the following fields * in the cq->structure: * - cq->num_sq_entries * - cq->num_rq_entries * - cq->rq_buf_size * - cq->sq_buf_size + * + * NOTE: this function does not initialize the controlq locks */ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) { @@ -616,8 +612,6 @@ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) !cq->rq_buf_size || !cq->sq_buf_size) { return ICE_ERR_CFG; } - mutex_init(&cq->sq_lock); - mutex_init(&cq->rq_lock); /* setup SQ command write back timeout */ cq->sq_cmd_timeout = ICE_CTL_Q_SQ_CMD_TIMEOUT; @@ -625,7 +619,7 @@ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) /* allocate the ATQ */ ret_code = ice_init_sq(hw, cq); if (ret_code) - goto init_ctrlq_destroy_locks; + return ret_code; /* allocate the ARQ */ ret_code = ice_init_rq(hw, cq); @@ -637,9 +631,6 @@ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) init_ctrlq_free_sq: ice_shutdown_sq(hw, cq); -init_ctrlq_destroy_locks: - mutex_destroy(&cq->sq_lock); - mutex_destroy(&cq->rq_lock); return ret_code; } @@ -647,12 +638,14 @@ static enum ice_status ice_init_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) * ice_init_all_ctrlq - main initialization routine for all control queues * @hw: pointer to the hardware structure * - * Prior to calling this function, drivers *MUST* set the following fields + * Prior to calling this function, the driver MUST* set the following fields * in the cq->structure for all control queues: * - cq->num_sq_entries * - cq->num_rq_entries * - cq->rq_buf_size * - cq->sq_buf_size + * + * NOTE: this function does not initialize the controlq locks. */ enum ice_status ice_init_all_ctrlq(struct ice_hw *hw) { @@ -671,10 +664,48 @@ enum ice_status ice_init_all_ctrlq(struct ice_hw *hw) return ice_init_ctrlq(hw, ICE_CTL_Q_MAILBOX); } +/** + * ice_init_ctrlq_locks - Initialize locks for a control queue + * @cq: pointer to the control queue + * + * Initializes the send and receive queue locks for a given control queue. + */ +static void ice_init_ctrlq_locks(struct ice_ctl_q_info *cq) +{ + mutex_init(&cq->sq_lock); + mutex_init(&cq->rq_lock); +} + +/** + * ice_create_all_ctrlq - main initialization routine for all control queues + * @hw: pointer to the hardware structure + * + * Prior to calling this function, the driver *MUST* set the following fields + * in the cq->structure for all control queues: + * - cq->num_sq_entries + * - cq->num_rq_entries + * - cq->rq_buf_size + * - cq->sq_buf_size + * + * This function creates all the control queue locks and then calls + * ice_init_all_ctrlq. It should be called once during driver load. If the + * driver needs to re-initialize control queues at run time it should call + * ice_init_all_ctrlq instead. + */ +enum ice_status ice_create_all_ctrlq(struct ice_hw *hw) +{ + ice_init_ctrlq_locks(&hw->adminq); + ice_init_ctrlq_locks(&hw->mailboxq); + + return ice_init_all_ctrlq(hw); +} + /** * ice_shutdown_ctrlq - shutdown routine for any control queue * @hw: pointer to the hardware structure * @q_type: specific Control queue type + * + * NOTE: this function does not destroy the control queue locks. */ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) { @@ -693,19 +724,17 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) return; } - if (cq->sq.count) { - ice_shutdown_sq(hw, cq); - mutex_destroy(&cq->sq_lock); - } - if (cq->rq.count) { - ice_shutdown_rq(hw, cq); - mutex_destroy(&cq->rq_lock); - } + ice_shutdown_sq(hw, cq); + ice_shutdown_rq(hw, cq); } /** * ice_shutdown_all_ctrlq - shutdown routine for all control queues * @hw: pointer to the hardware structure + * + * NOTE: this function does not destroy the control queue locks. The driver + * may call this at runtime to shutdown and later restart control queues, such + * as in response to a reset event. */ void ice_shutdown_all_ctrlq(struct ice_hw *hw) { @@ -715,6 +744,37 @@ void ice_shutdown_all_ctrlq(struct ice_hw *hw) ice_shutdown_ctrlq(hw, ICE_CTL_Q_MAILBOX); } +/** + * ice_destroy_ctrlq_locks - Destroy locks for a control queue + * @cq: pointer to the control queue + * + * Destroys the send and receive queue locks for a given control queue. + */ +static void +ice_destroy_ctrlq_locks(struct ice_ctl_q_info *cq) +{ + mutex_destroy(&cq->sq_lock); + mutex_destroy(&cq->rq_lock); +} + +/** + * ice_destroy_all_ctrlq - exit routine for all control queues + * @hw: pointer to the hardware structure + * + * This function shuts down all the control queues and then destroys the + * control queue locks. It should be called once during driver unload. The + * driver should call ice_shutdown_all_ctrlq if it needs to shut down and + * reinitialize control queues, such as in response to a reset event. + */ +void ice_destroy_all_ctrlq(struct ice_hw *hw) +{ + /* shut down all the control queues first */ + ice_shutdown_all_ctrlq(hw); + + ice_destroy_ctrlq_locks(&hw->adminq); + ice_destroy_ctrlq_locks(&hw->mailboxq); +} + /** * ice_clean_sq - cleans Admin send queue (ATQ) * @hw: pointer to the hardware structure -- GitLab From 6d5999467df03d1d7fd64ac761ffa20d00ce9e52 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Wed, 26 Jun 2019 02:20:17 -0700 Subject: [PATCH 1437/7155] ice: Do not configure port with no media The firmware reports an error when trying to configure a port with no media. Instead of always configuring the port, check for media before attempting to configure it. In the absence of media, turn off link and poll for media to become available before re-enabling link. Move ice_force_phys_link_state() up to avoid forward declaration. Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_main.c | 239 ++++++++++++++-------- 2 files changed, 158 insertions(+), 82 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 9ee6b55553c0..596b09a905aa 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -337,6 +337,7 @@ enum ice_pf_flags { ICE_FLAG_DCB_CAPABLE, ICE_FLAG_DCB_ENA, ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, + ICE_FLAG_NO_MEDIA, ICE_FLAG_ENABLE_FW_LLDP, ICE_FLAG_ETHTOOL_CTXT, /* set when ethtool holds RTNL lock */ ICE_PF_FLAGS_NBITS /* must be last */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f490e65c64bc..91334d1e83ed 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -810,6 +810,20 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up, if (!vsi || !vsi->port_info) return -EINVAL; + /* turn off PHY if media was removed */ + if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags) && + !(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE)) { + set_bit(ICE_FLAG_NO_MEDIA, pf->flags); + + result = ice_aq_set_link_restart_an(pi, false, NULL); + if (result) { + dev_dbg(&pf->pdev->dev, + "Failed to set link down, VSI %d error %d\n", + vsi->vsi_num, result); + return result; + } + } + ice_vsi_link_event(vsi, link_up); ice_print_link_msg(vsi, link_up); @@ -1314,6 +1328,124 @@ static void ice_handle_mdd_event(struct ice_pf *pf) } } +/** + * ice_force_phys_link_state - Force the physical link state + * @vsi: VSI to force the physical link state to up/down + * @link_up: true/false indicates to set the physical link to up/down + * + * Force the physical link state by getting the current PHY capabilities from + * hardware and setting the PHY config based on the determined capabilities. If + * link changes a link event will be triggered because both the Enable Automatic + * Link Update and LESM Enable bits are set when setting the PHY capabilities. + * + * Returns 0 on success, negative on failure + */ +static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up) +{ + struct ice_aqc_get_phy_caps_data *pcaps; + struct ice_aqc_set_phy_cfg_data *cfg; + struct ice_port_info *pi; + struct device *dev; + int retcode; + + if (!vsi || !vsi->port_info || !vsi->back) + return -EINVAL; + if (vsi->type != ICE_VSI_PF) + return 0; + + dev = &vsi->back->pdev->dev; + + pi = vsi->port_info; + + pcaps = devm_kzalloc(dev, sizeof(*pcaps), GFP_KERNEL); + if (!pcaps) + return -ENOMEM; + + retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, + NULL); + if (retcode) { + dev_err(dev, + "Failed to get phy capabilities, VSI %d error %d\n", + vsi->vsi_num, retcode); + retcode = -EIO; + goto out; + } + + /* No change in link */ + if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) && + link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP)) + goto out; + + cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + retcode = -ENOMEM; + goto out; + } + + cfg->phy_type_low = pcaps->phy_type_low; + cfg->phy_type_high = pcaps->phy_type_high; + cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; + cfg->low_power_ctrl = pcaps->low_power_ctrl; + cfg->eee_cap = pcaps->eee_cap; + cfg->eeer_value = pcaps->eeer_value; + cfg->link_fec_opt = pcaps->link_fec_options; + if (link_up) + cfg->caps |= ICE_AQ_PHY_ENA_LINK; + else + cfg->caps &= ~ICE_AQ_PHY_ENA_LINK; + + retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL); + if (retcode) { + dev_err(dev, "Failed to set phy config, VSI %d error %d\n", + vsi->vsi_num, retcode); + retcode = -EIO; + } + + devm_kfree(dev, cfg); +out: + devm_kfree(dev, pcaps); + return retcode; +} + +/** + * ice_check_media_subtask - Check for media; bring link up if detected. + * @pf: pointer to PF struct + */ +static void ice_check_media_subtask(struct ice_pf *pf) +{ + struct ice_port_info *pi; + struct ice_vsi *vsi; + int err; + + vsi = ice_find_vsi_by_type(pf, ICE_VSI_PF); + if (!vsi) + return; + + /* No need to check for media if it's already present or the interface + * is down + */ + if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags) || + test_bit(__ICE_DOWN, vsi->state)) + return; + + /* Refresh link info and check if media is present */ + pi = vsi->port_info; + err = ice_update_link_info(pi); + if (err) + return; + + if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) { + err = ice_force_phys_link_state(vsi, true); + if (err) + return; + clear_bit(ICE_FLAG_NO_MEDIA, pf->flags); + + /* A Link Status Event will be generated; the event handler + * will complete bringing the interface up + */ + } +} + /** * ice_service_task - manage and run subtasks * @work: pointer to work_struct contained by the PF struct @@ -1336,6 +1468,7 @@ static void ice_service_task(struct work_struct *work) return; } + ice_check_media_subtask(pf); ice_check_for_hang_subtask(pf); ice_sync_fltr_subtask(pf); ice_handle_mdd_event(pf); @@ -3357,85 +3490,6 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) } } -/** - * ice_force_phys_link_state - Force the physical link state - * @vsi: VSI to force the physical link state to up/down - * @link_up: true/false indicates to set the physical link to up/down - * - * Force the physical link state by getting the current PHY capabilities from - * hardware and setting the PHY config based on the determined capabilities. If - * link changes a link event will be triggered because both the Enable Automatic - * Link Update and LESM Enable bits are set when setting the PHY capabilities. - * - * Returns 0 on success, negative on failure - */ -static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up) -{ - struct ice_aqc_get_phy_caps_data *pcaps; - struct ice_aqc_set_phy_cfg_data *cfg; - struct ice_port_info *pi; - struct device *dev; - int retcode; - - if (!vsi || !vsi->port_info || !vsi->back) - return -EINVAL; - if (vsi->type != ICE_VSI_PF) - return 0; - - dev = &vsi->back->pdev->dev; - - pi = vsi->port_info; - - pcaps = devm_kzalloc(dev, sizeof(*pcaps), GFP_KERNEL); - if (!pcaps) - return -ENOMEM; - - retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, - NULL); - if (retcode) { - dev_err(dev, - "Failed to get phy capabilities, VSI %d error %d\n", - vsi->vsi_num, retcode); - retcode = -EIO; - goto out; - } - - /* No change in link */ - if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) && - link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP)) - goto out; - - cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); - if (!cfg) { - retcode = -ENOMEM; - goto out; - } - - cfg->phy_type_low = pcaps->phy_type_low; - cfg->phy_type_high = pcaps->phy_type_high; - cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; - cfg->low_power_ctrl = pcaps->low_power_ctrl; - cfg->eee_cap = pcaps->eee_cap; - cfg->eeer_value = pcaps->eeer_value; - cfg->link_fec_opt = pcaps->link_fec_options; - if (link_up) - cfg->caps |= ICE_AQ_PHY_ENA_LINK; - else - cfg->caps &= ~ICE_AQ_PHY_ENA_LINK; - - retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL); - if (retcode) { - dev_err(dev, "Failed to set phy config, VSI %d error %d\n", - vsi->vsi_num, retcode); - retcode = -EIO; - } - - devm_kfree(dev, cfg); -out: - devm_kfree(dev, pcaps); - return retcode; -} - /** * ice_down - Shutdown the connection * @vsi: The VSI being stopped @@ -4281,6 +4335,7 @@ int ice_open(struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_vsi *vsi = np->vsi; + struct ice_port_info *pi; int err; if (test_bit(__ICE_NEEDS_RESTART, vsi->back->state)) { @@ -4290,13 +4345,33 @@ int ice_open(struct net_device *netdev) netif_carrier_off(netdev); - err = ice_force_phys_link_state(vsi, true); + pi = vsi->port_info; + err = ice_update_link_info(pi); if (err) { - netdev_err(netdev, - "Failed to set physical link up, error %d\n", err); + netdev_err(netdev, "Failed to get link info, error %d\n", + err); return err; } + /* Set PHY if there is media, otherwise, turn off PHY */ + if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) { + err = ice_force_phys_link_state(vsi, true); + if (err) { + netdev_err(netdev, + "Failed to set physical link up, error %d\n", + err); + return err; + } + } else { + err = ice_aq_set_link_restart_an(pi, false, NULL); + if (err) { + netdev_err(netdev, "Failed to set PHY state, VSI %d error %d\n", + vsi->vsi_num, err); + return err; + } + set_bit(ICE_FLAG_NO_MEDIA, vsi->back->flags); + } + err = ice_vsi_open(vsi); if (err) netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n", -- GitLab From c7aeb4d1b9bfdb4e07da1c77cb095f02e912a83f Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Wed, 26 Jun 2019 02:20:18 -0700 Subject: [PATCH 1438/7155] ice: Disable VFs until reset is completed This patch adds code to clear VFs enable status until reset is completed, and Tx/Rx rings are setup. Without this patch, the code flow request Tx queues to be disabled after reset, especially PFR - where VF VSI Tx rings have already been wiped off in the NVM and result to adminq error based on the call to disable Tx LAN queue in ice_reset_all_vfs function call. Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 91334d1e83ed..d13f56803658 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -488,6 +488,7 @@ static void ice_prepare_for_reset(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; + u8 i; /* already prepared for reset */ if (test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) @@ -497,6 +498,10 @@ ice_prepare_for_reset(struct ice_pf *pf) if (ice_check_sq_alive(hw, &hw->mailboxq)) ice_vc_notify_reset(pf); + /* Disable VFs until reset is completed */ + for (i = 0; i < pf->num_alloc_vfs; i++) + clear_bit(ICE_VF_STATE_ENA, pf->vf[i].vf_states); + /* disable the VSIs and their queues that are not already DOWN */ ice_pf_dis_all_vsi(pf, false); -- GitLab From 257e26c6403c23714db69d6e21c58b0d92636c4e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 11:02:11 +0200 Subject: [PATCH 1439/7155] docs: arm: Remove orphan sh-mobile directory This directory is empty, except for a .gitignore file, listing an executable file that can no longer be built since commit c6535e1e0361157e ("Documentation: Remove ZBOOT MMC/SDHI utility and docs"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/arm/sh-mobile/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Documentation/arm/sh-mobile/.gitignore diff --git a/Documentation/arm/sh-mobile/.gitignore b/Documentation/arm/sh-mobile/.gitignore deleted file mode 100644 index c928dbf3cc88..000000000000 --- a/Documentation/arm/sh-mobile/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vrl4 -- GitLab From 074b326ee5e73c8e7a10d0eebbc6a1b56e1253d2 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 31 Jul 2019 19:45:10 +0800 Subject: [PATCH 1440/7155] mailmap: add entry to connect my email addresses I've used several email accounts to contribute codes, samsung's one is obsolete, so let me add entry to map them, in order to let people find me easily when they blame my codes. Signed-off-by: Chao Yu Signed-off-by: Jonathan Corbet --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 0fef932de3db..477debe3d960 100644 --- a/.mailmap +++ b/.mailmap @@ -47,6 +47,8 @@ Boris Brezillon Boris Brezillon Brian Avery Brian King +Chao Yu +Chao Yu Christoph Hellwig Christophe Ricard Corey Minyard -- GitLab From 803deeaaea10a87b7d92bd2eccbc637711390a04 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Mon, 29 Jul 2019 23:58:56 +0200 Subject: [PATCH 1441/7155] doc:it_IT: align translation to mainline The patch translates the following patches in Italian: 1fb12b35e5ff kbuild: Raise the minimum required binutils version to 2.21 9c3c0c204814 isdn: remove isdn4linux Signed-off-by: Federico Vaga Signed-off-by: Jonathan Corbet --- .../translations/it_IT/process/changes.rst | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst index d0874327f301..94a6499742ac 100644 --- a/Documentation/translations/it_IT/process/changes.rst +++ b/Documentation/translations/it_IT/process/changes.rst @@ -26,16 +26,15 @@ Prima di pensare d'avere trovato un baco, aggiornate i seguenti programmi usando, il comando indicato dovrebbe dirvelo. Questa lista presume che abbiate già un kernel Linux funzionante. In aggiunta, -non tutti gli strumenti sono necessari ovunque; ovviamente, se non avete un -modem ISDN, per esempio, probabilmente non dovreste preoccuparvi di -isdn4k-utils. +non tutti gli strumenti sono necessari ovunque; ovviamente, se non avete una +PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils. ====================== ================= ======================================== Programma Versione minima Comando per verificare la versione ====================== ================= ======================================== GNU C 4.6 gcc --version GNU make 3.81 make --version -binutils 2.20 ld -v +binutils 2.21 ld -v flex 2.5.35 flex --version bison 2.0 bison --version util-linux 2.10o fdformat --version @@ -49,7 +48,6 @@ btrfs-progs 0.18 btrfsck pcmciautils 004 pccardctl -V quota-tools 3.09 quota -V PPP 2.4.0 pppd --version -isdn4k-utils 3.1pre1 isdnctrl 2>&1|grep version nfs-utils 1.0.5 showmount --version procps 3.2.0 ps --version oprofile 0.9 oprofiled --version @@ -81,10 +79,7 @@ Per compilare il kernel vi servirà GNU make 3.81 o successivo. Binutils -------- -Il sistema di compilazione, dalla versione 4.13, per la produzione dei passi -intermedi, si è convertito all'uso di *thin archive* (`ar T`) piuttosto che -all'uso del *linking* incrementale (`ld -r`). Questo richiede binutils 2.20 o -successivo. +Per generare il kernel è necessario avere Binutils 2.21 o superiore. pkg-config ---------- @@ -286,11 +281,6 @@ col seguente comando:: mknod /dev/ppp c 108 0 -Isdn4k-utils ------------- - -Per via della modifica del campo per il numero di telefono, il pacchetto -isdn4k-utils dev'essere ricompilato o (preferibilmente) aggiornato. NFS-utils --------- @@ -456,10 +446,6 @@ PPP - -Isdn4k-utils ------------- - -- NFS-utils --------- -- GitLab From 370910efdb6ece4a391afbc047c39e2d1b61374c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 16:29:10 -0300 Subject: [PATCH 1442/7155] MAINTAINERS: fix broken ref for ABI sysfs-bus-counter-ftm-quaddec There's a typo here: sysfs-bus-counter-ftm-quadddec -> sysfs-bus-counter-ftm-quaddec Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6d397fa03436..757b28717918 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6327,7 +6327,7 @@ FLEXTIMER FTM-QUADDEC DRIVER M: Patrick Havelange L: linux-iio@vger.kernel.org S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quadddec +F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt F: drivers/counter/ftm-quaddec.c -- GitLab From b26bb0faf8f5d7fccb2e1827f33012177ac9d217 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 16:29:11 -0300 Subject: [PATCH 1443/7155] MAINTAINERS: fix reference to net phy ABI file The file sysfs-bus-mdio got removed in favor of sysfs-class-net-phydev, with contained a duplicated set of information. Fixes: a6cd0d2d493a ("Documentation: net-sysfs: Remove duplicate PHY device documentation") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 757b28717918..f105a80f4d73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6071,7 +6071,7 @@ M: Florian Fainelli M: Heiner Kallweit L: netdev@vger.kernel.org S: Maintained -F: Documentation/ABI/testing/sysfs-bus-mdio +F: Documentation/ABI/testing/sysfs-class-net-phydev F: Documentation/devicetree/bindings/net/ethernet-phy.yaml F: Documentation/devicetree/bindings/net/mdio* F: Documentation/networking/phy.rst -- GitLab From 7530c497592e04f5da69fe968c09622b489f2921 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 16:29:12 -0300 Subject: [PATCH 1444/7155] MAINTAINERS: fix a renamed DT reference Fix this rename: Documentation/devicetree/bindings/i2c/{i2c-mv64xxx.txt -> marvell,mv64xxx-i2c.yaml} Fixes: f8bbde72ef44 ("dt-bindings: i2c: mv64xxx: Add YAML schemas") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index f105a80f4d73..811218cc2355 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7517,7 +7517,7 @@ I2C MV64XXX MARVELL AND ALLWINNER DRIVER M: Gregory CLEMENT L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt +F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml F: drivers/i2c/busses/i2c-mv64xxx.c I2C OVER PARALLEL PORT -- GitLab From 23aa16489c06e6739c7c99e9fdccf723d2691a5d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 16:29:13 -0300 Subject: [PATCH 1445/7155] docs: cgroup-v1/blkio-controller.rst: remove a CFQ left over changeset fb5772cbfe48 ("blkio-controller.txt: Remove references to CFQ") removed cgroup references to CFQ, but it kept one left. Get rid of it. Fixes: fb5772cbfe48 ("blkio-controller.txt: Remove references to CFQ") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/admin-guide/cgroup-v1/blkio-controller.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v1/blkio-controller.rst b/Documentation/admin-guide/cgroup-v1/blkio-controller.rst index 1d7d962933be..36d43ae7dc13 100644 --- a/Documentation/admin-guide/cgroup-v1/blkio-controller.rst +++ b/Documentation/admin-guide/cgroup-v1/blkio-controller.rst @@ -130,12 +130,6 @@ Proportional weight policy files dev weight 8:16 300 -- blkio.leaf_weight[_device] - - Equivalents of blkio.weight[_device] for the purpose of - deciding how much weight tasks in the given cgroup has while - competing with the cgroup's child cgroups. For details, - please refer to Documentation/block/cfq-iosched.txt. - - blkio.time - disk time allocated to cgroup per device in milliseconds. First two fields specify the major and minor number of the device and -- GitLab From 54bfe6feba0e9ead1172cf26381f7dce5df10e51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 16:29:14 -0300 Subject: [PATCH 1446/7155] docs: zh_CN: howto.rst: fix a broken reference There's a broken reference there pointing to the long gone DocBook dir. While I don't read chinese, Google translator translates it to: "The generated documentation will be placed in the Documentation/DocBook/ directory." Well, we know that the output will be Documentation/output dir. So, let's fix this one. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/translations/zh_CN/process/howto.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst index 5b671178b17b..c4ff8356b88d 100644 --- a/Documentation/translations/zh_CN/process/howto.rst +++ b/Documentation/translations/zh_CN/process/howto.rst @@ -147,7 +147,7 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍 内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何 -妥善处理加锁的规则。生成的文档会放在 Documentation/DocBook/目录下。在内 +妥善处理加锁的规则。生成的文档会放在 Documentation/output/目录下。在内 核源码的主目录中使用以下不同命令将会分别生成PDF、Postscript、HTML和手册 页等不同格式的文档:: -- GitLab From 638b642f82bb8ee81fe00bdbb70b5ff0885df1a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 18:01:55 -0300 Subject: [PATCH 1447/7155] docs: riscv: convert boot-image-header.txt to ReST Convert this small file to ReST format by: - Using a proper markup for the document title; - marking a code block as such; - use tags for Author and date; - use tables for bit map fields. While here, fix a broken reference for a document with is planned but is not here yet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Atish Patra Signed-off-by: Jonathan Corbet --- ...image-header.txt => boot-image-header.rst} | 39 ++++++++++++------- Documentation/riscv/index.rst | 1 + 2 files changed, 26 insertions(+), 14 deletions(-) rename Documentation/riscv/{boot-image-header.txt => boot-image-header.rst} (72%) diff --git a/Documentation/riscv/boot-image-header.txt b/Documentation/riscv/boot-image-header.rst similarity index 72% rename from Documentation/riscv/boot-image-header.txt rename to Documentation/riscv/boot-image-header.rst index 1b73fea23b39..43e9bd0731d5 100644 --- a/Documentation/riscv/boot-image-header.txt +++ b/Documentation/riscv/boot-image-header.rst @@ -1,22 +1,25 @@ - Boot image header in RISC-V Linux - ============================================= +================================= +Boot image header in RISC-V Linux +================================= -Author: Atish Patra -Date : 20 May 2019 +:Author: Atish Patra +:Date: 20 May 2019 This document only describes the boot image header details for RISC-V Linux. -The complete booting guide will be available at Documentation/riscv/booting.txt. -The following 64-byte header is present in decompressed Linux kernel image. +TODO: + Write a complete booting guide. + +The following 64-byte header is present in decompressed Linux kernel image:: u32 code0; /* Executable code */ - u32 code1; /* Executable code */ + u32 code1; /* Executable code */ u64 text_offset; /* Image load offset, little endian */ u64 image_size; /* Effective Image size, little endian */ u64 flags; /* kernel flags, little endian */ u32 version; /* Version of this header */ - u32 res1 = 0; /* Reserved */ - u64 res2 = 0; /* Reserved */ + u32 res1 = 0; /* Reserved */ + u64 res2 = 0; /* Reserved */ u64 magic = 0x5643534952; /* Magic number, little endian, "RISCV" */ u32 res3; /* Reserved for additional RISC-V specific header */ u32 res4; /* Reserved for PE COFF offset */ @@ -25,16 +28,21 @@ This header format is compliant with PE/COFF header and largely inspired from ARM64 header. Thus, both ARM64 & RISC-V header can be combined into one common header in future. -Notes: +Notes +===== + - This header can also be reused to support EFI stub for RISC-V in future. EFI specification needs PE/COFF image header in the beginning of the kernel image in order to load it as an EFI application. In order to support EFI stub, code0 should be replaced with "MZ" magic string and res5(at offset 0x3c) should point to the rest of the PE/COFF header. -- version field indicate header version number. - Bits 0:15 - Minor version - Bits 16:31 - Major version +- version field indicate header version number + + ========== ============= + Bits 0:15 Minor version + Bits 16:31 Major version + ========== ============= This preserves compatibility across newer and older version of the header. The current version is defined as 0.1. @@ -44,7 +52,10 @@ Notes: extension for RISC-V in future. For current version, it is set to be zero. - In current header, the flag field has only one field. - Bit 0: Kernel endianness. 1 if BE, 0 if LE. + + ===== ==================================== + Bit 0 Kernel endianness. 1 if BE, 0 if LE. + ===== ==================================== - Image size is mandatory for boot loader to load kernel image. Booting will fail otherwise. diff --git a/Documentation/riscv/index.rst b/Documentation/riscv/index.rst index e3ca0922a8c2..215fd3c1f2d5 100644 --- a/Documentation/riscv/index.rst +++ b/Documentation/riscv/index.rst @@ -5,6 +5,7 @@ RISC-V architecture .. toctree:: :maxdepth: 1 + boot-image-header pmu .. only:: subproject and html -- GitLab From e226b4f0e04f4cd5396041661a27eae5aa370bb3 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 6 Jul 2019 23:01:00 +0200 Subject: [PATCH 1448/7155] doc: email-clients miscellaneous fixes Fixed some style inconsistencies and remove old statement referring to kmail missing feature (saving email from the view window is possible). Signed-off-by: Federico Vaga Signed-off-by: Jonathan Corbet --- Documentation/process/email-clients.rst | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Documentation/process/email-clients.rst b/Documentation/process/email-clients.rst index 07faa5457bcb..5273d06c8ff6 100644 --- a/Documentation/process/email-clients.rst +++ b/Documentation/process/email-clients.rst @@ -40,7 +40,7 @@ Emailed patches should be in ASCII or UTF-8 encoding only. If you configure your email client to send emails with UTF-8 encoding, you avoid some possible charset problems. -Email clients should generate and maintain References: or In-Reply-To: +Email clients should generate and maintain "References:" or "In-Reply-To:" headers so that mail threading is not broken. Copy-and-paste (or cut-and-paste) usually does not work for patches @@ -89,7 +89,7 @@ Claws Mail (GUI) Works. Some people use this successfully for patches. -To insert a patch use :menuselection:`Message-->Insert` File (:kbd:`CTRL-I`) +To insert a patch use :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) or an external editor. If the inserted patch has to be edited in the Claws composition window @@ -132,8 +132,8 @@ wrapping. At the bottom of your email, put the commonly-used patch delimiter before inserting your patch: three hyphens (``---``). -Then from the :menuselection:`Message` menu item, select insert file and -choose your patch. +Then from the :menuselection:`Message` menu item, select +:menuselection:`insert file` and choose your patch. As an added bonus you can customise the message creation toolbar menu and put the :menuselection:`insert file` icon there. @@ -149,18 +149,16 @@ patches so do not GPG sign them. Signing patches that have been inserted as inlined text will make them tricky to extract from their 7-bit encoding. If you absolutely must send patches as attachments instead of inlining -them as text, right click on the attachment and select properties, and -highlight :menuselection:`Suggest automatic display` to make the attachment +them as text, right click on the attachment and select :menuselection:`properties`, +and highlight :menuselection:`Suggest automatic display` to make the attachment inlined to make it more viewable. When saving patches that are sent as inlined text, select the email that contains the patch from the message list pane, right click and select :menuselection:`save as`. You can use the whole email unmodified as a patch -if it was properly composed. There is no option currently to save the email -when you are actually viewing it in its own window -- there has been a request -filed at kmail's bugzilla and hopefully this will be addressed. Emails are -saved as read-write for user only so you will have to chmod them to make them -group and world readable if you copy them elsewhere. +if it was properly composed. Emails are saved as read-write for user only so +you will have to chmod them to make them group and world readable if you copy +them elsewhere. Lotus Notes (GUI) ***************** -- GitLab From ac841c4e457c1fae6f661108f811b554c8581976 Mon Sep 17 00:00:00 2001 From: Shobhit Kukreti Date: Wed, 10 Jul 2019 08:29:01 -0700 Subject: [PATCH 1449/7155] Documentation: filesystems: Convert jfs.txt to This converts the plain text documentation of jfs.txt to reStructuredText format. Added to documentation build process and verified with make htmldocs Signed-off-by: Shobhit Kukreti Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/admin-guide/index.rst | 1 + .../jfs.txt => admin-guide/jfs.rst} | 44 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) rename Documentation/{filesystems/jfs.txt => admin-guide/jfs.rst} (51%) diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 33feab2f4084..2376cb91b83c 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -78,6 +78,7 @@ configure specific aspects of kernel behavior to your liking. ext4 binderfs xfs + jfs pm/index thunderbolt LSM/index diff --git a/Documentation/filesystems/jfs.txt b/Documentation/admin-guide/jfs.rst similarity index 51% rename from Documentation/filesystems/jfs.txt rename to Documentation/admin-guide/jfs.rst index 41fd757997b3..9e12d936bc90 100644 --- a/Documentation/filesystems/jfs.txt +++ b/Documentation/admin-guide/jfs.rst @@ -1,45 +1,59 @@ +=========================================== IBM's Journaled File System (JFS) for Linux +=========================================== JFS Homepage: http://jfs.sourceforge.net/ The following mount options are supported: + (*) == default -iocharset=name Character set to use for converting from Unicode to +iocharset=name + Character set to use for converting from Unicode to ASCII. The default is to do no conversion. Use iocharset=utf8 for UTF-8 translations. This requires CONFIG_NLS_UTF8 to be set in the kernel .config file. iocharset=none specifies the default behavior explicitly. -resize=value Resize the volume to blocks. JFS only supports +resize=value + Resize the volume to blocks. JFS only supports growing a volume, not shrinking it. This option is only valid during a remount, when the volume is mounted read-write. The resize keyword with no value will grow the volume to the full size of the partition. -nointegrity Do not write to the journal. The primary use of this option +nointegrity + Do not write to the journal. The primary use of this option is to allow for higher performance when restoring a volume from backup media. The integrity of the volume is not guaranteed if the system abnormally abends. -integrity(*) Commit metadata changes to the journal. Use this option to +integrity(*) + Commit metadata changes to the journal. Use this option to remount a volume where the nointegrity option was previously specified in order to restore normal behavior. -errors=continue Keep going on a filesystem error. -errors=remount-ro(*) Remount the filesystem read-only on an error. -errors=panic Panic and halt the machine if an error occurs. +errors=continue + Keep going on a filesystem error. +errors=remount-ro(*) + Remount the filesystem read-only on an error. +errors=panic + Panic and halt the machine if an error occurs. -uid=value Override on-disk uid with specified value -gid=value Override on-disk gid with specified value -umask=value Override on-disk umask with specified octal value. For - directories, the execute bit will be set if the corresponding +uid=value + Override on-disk uid with specified value +gid=value + Override on-disk gid with specified value +umask=value + Override on-disk umask with specified octal value. For + directories, the execute bit will be set if the corresponding read bit is set. -discard=minlen This enables/disables the use of discard/TRIM commands. -discard The discard/TRIM commands are sent to the underlying -nodiscard(*) block device when blocks are freed. This is useful for SSD - devices and sparse/thinly-provisioned LUNs. The FITRIM ioctl +discard=minlen, discard/nodiscard(*) + This enables/disables the use of discard/TRIM commands. + The discard/TRIM commands are sent to the underlying + block device when blocks are freed. This is useful for SSD + devices and sparse/thinly-provisioned LUNs. The FITRIM ioctl command is also available together with the nodiscard option. The value of minlen specifies the minimum blockcount, when a TRIM command to the block device is considered useful. -- GitLab From 34d5f4f269a21c7b5d64b4db0391d36511f1ac1a Mon Sep 17 00:00:00 2001 From: Shobhit Kukreti Date: Wed, 10 Jul 2019 08:31:23 -0700 Subject: [PATCH 1450/7155] Documentation: filesystems: Convert ufs.txt to reStructuredText format This converts the plain text documentation of ufs.txt to reStructuredText format. Added to documentation build process and verified with make htmldocs Signed-off-by: Shobhit Kukreti Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/admin-guide/index.rst | 1 + .../ufs.txt => admin-guide/ufs.rst} | 36 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) rename Documentation/{filesystems/ufs.txt => admin-guide/ufs.rst} (69%) diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 2376cb91b83c..592107a3295f 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -79,6 +79,7 @@ configure specific aspects of kernel behavior to your liking. binderfs xfs jfs + ufs pm/index thunderbolt LSM/index diff --git a/Documentation/filesystems/ufs.txt b/Documentation/admin-guide/ufs.rst similarity index 69% rename from Documentation/filesystems/ufs.txt rename to Documentation/admin-guide/ufs.rst index 7a602adeca2b..55d15297f8d7 100644 --- a/Documentation/filesystems/ufs.txt +++ b/Documentation/admin-guide/ufs.rst @@ -1,37 +1,45 @@ -USING UFS +========= +Using UFS ========= mount -t ufs -o ufstype=type_of_ufs device dir -UFS OPTIONS +UFS Options =========== ufstype=type_of_ufs UFS is a file system widely used in different operating systems. The problem are differences among implementations. Features of some implementations are undocumented, so its hard to recognize - type of ufs automatically. That's why user must specify type of + type of ufs automatically. That's why user must specify type of ufs manually by mount option ufstype. Possible values are: - old old format of ufs + old + old format of ufs default value, supported as read-only - 44bsd used in FreeBSD, NetBSD, OpenBSD + 44bsd + used in FreeBSD, NetBSD, OpenBSD supported as read-write - ufs2 used in FreeBSD 5.x + ufs2 + used in FreeBSD 5.x supported as read-write - 5xbsd synonym for ufs2 + 5xbsd + synonym for ufs2 - sun used in SunOS (Solaris) + sun + used in SunOS (Solaris) supported as read-write - sunx86 used in SunOS for Intel (Solarisx86) + sunx86 + used in SunOS for Intel (Solarisx86) supported as read-write - hp used in HP-UX + hp + used in HP-UX supported as read-only nextstep @@ -47,14 +55,14 @@ ufstype=type_of_ufs supported as read-only -POSSIBLE PROBLEMS -================= +Possible Problems +----------------- See next section, if you have any. -BUG REPORTS -=========== +Bug Reports +----------- Any ufs bug report you can send to daniel.pirkl@email.cz or to dushistov@mail.ru (do not send partition tables bug reports). -- GitLab From fe13225fdc3f7b79e2921869a13386f48b30bf79 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Thu, 11 Jul 2019 23:52:01 +0700 Subject: [PATCH 1451/7155] Documentation: coresight: convert txt to rst This changes from plain text to reStructuredText as suggestion in doc-guide [1] [1] https://www.kernel.org/doc/html/latest/doc-guide/sphinx.html Some adaptations such as: literal block, ``inline literal`` and alignment text,... Signed-off-by: Phong Tran Reviewed-by: Mauro Carvalho Chehab Acked-by: Mathieu Poirier Signed-off-by: Jonathan Corbet --- ...-cpu-debug.txt => coresight-cpu-debug.rst} | 67 ++-- .../trace/{coresight.txt => coresight.rst} | 372 +++++++++--------- Documentation/trace/index.rst | 2 + MAINTAINERS | 4 +- 4 files changed, 234 insertions(+), 211 deletions(-) rename Documentation/trace/{coresight-cpu-debug.txt => coresight-cpu-debug.rst} (84%) rename Documentation/trace/{coresight.txt => coresight.rst} (56%) diff --git a/Documentation/trace/coresight-cpu-debug.txt b/Documentation/trace/coresight-cpu-debug.rst similarity index 84% rename from Documentation/trace/coresight-cpu-debug.txt rename to Documentation/trace/coresight-cpu-debug.rst index 1a660a39e3c0..993dd294b81b 100644 --- a/Documentation/trace/coresight-cpu-debug.txt +++ b/Documentation/trace/coresight-cpu-debug.rst @@ -1,8 +1,9 @@ - Coresight CPU Debug Module - ========================== +========================== +Coresight CPU Debug Module +========================== - Author: Leo Yan - Date: April 5th, 2017 + :Author: Leo Yan + :Date: April 5th, 2017 Introduction ------------ @@ -69,6 +70,7 @@ Before accessing debug registers, we should ensure the clock and power domain have been enabled properly. In ARMv8-a ARM (ARM DDI 0487A.k) chapter 'H9.1 Debug registers', the debug registers are spread into two domains: the debug domain and the CPU domain. +:: +---------------+ | | @@ -125,18 +127,21 @@ If you want to enable debugging functionality at boot time, you can add "coresight_cpu_debug.enable=1" to the kernel command line parameter. The driver also can work as module, so can enable the debugging when insmod -module: -# insmod coresight_cpu_debug.ko debug=1 +module:: + + # insmod coresight_cpu_debug.ko debug=1 When boot time or insmod module you have not enabled the debugging, the driver uses the debugfs file system to provide a knob to dynamically enable or disable debugging: -To enable it, write a '1' into /sys/kernel/debug/coresight_cpu_debug/enable: -# echo 1 > /sys/kernel/debug/coresight_cpu_debug/enable +To enable it, write a '1' into /sys/kernel/debug/coresight_cpu_debug/enable:: + + # echo 1 > /sys/kernel/debug/coresight_cpu_debug/enable + +To disable it, write a '0' into /sys/kernel/debug/coresight_cpu_debug/enable:: -To disable it, write a '0' into /sys/kernel/debug/coresight_cpu_debug/enable: -# echo 0 > /sys/kernel/debug/coresight_cpu_debug/enable + # echo 0 > /sys/kernel/debug/coresight_cpu_debug/enable As explained in chapter "Clock and power domain", if you are working on one platform which has idle states to power off debug logic and the power @@ -154,34 +159,34 @@ subsystem, more specifically by using the "/dev/cpu_dma_latency" interface (see Documentation/power/pm_qos_interface.rst for more details). As specified in the PM QoS documentation the requested parameter will stay in effect until the file descriptor is released. -For example: +For example:: -# exec 3<> /dev/cpu_dma_latency; echo 0 >&3 -... -Do some work... -... -# exec 3<>- + # exec 3<> /dev/cpu_dma_latency; echo 0 >&3 + ... + Do some work... + ... + # exec 3<>- The same can also be done from an application program. Disable specific CPU's specific idle state from cpuidle sysfs (see -Documentation/admin-guide/pm/cpuidle.rst): -# echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable +Documentation/admin-guide/pm/cpuidle.rst):: + # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable Output format ------------- -Here is an example of the debugging output format: - -ARM external debug module: -coresight-cpu-debug 850000.debug: CPU[0]: -coresight-cpu-debug 850000.debug: EDPRSR: 00000001 (Power:On DLK:Unlock) -coresight-cpu-debug 850000.debug: EDPCSR: handle_IPI+0x174/0x1d8 -coresight-cpu-debug 850000.debug: EDCIDSR: 00000000 -coresight-cpu-debug 850000.debug: EDVIDSR: 90000000 (State:Non-secure Mode:EL1/0 Width:64bits VMID:0) -coresight-cpu-debug 852000.debug: CPU[1]: -coresight-cpu-debug 852000.debug: EDPRSR: 00000001 (Power:On DLK:Unlock) -coresight-cpu-debug 852000.debug: EDPCSR: debug_notifier_call+0x23c/0x358 -coresight-cpu-debug 852000.debug: EDCIDSR: 00000000 -coresight-cpu-debug 852000.debug: EDVIDSR: 90000000 (State:Non-secure Mode:EL1/0 Width:64bits VMID:0) +Here is an example of the debugging output format:: + + ARM external debug module: + coresight-cpu-debug 850000.debug: CPU[0]: + coresight-cpu-debug 850000.debug: EDPRSR: 00000001 (Power:On DLK:Unlock) + coresight-cpu-debug 850000.debug: EDPCSR: handle_IPI+0x174/0x1d8 + coresight-cpu-debug 850000.debug: EDCIDSR: 00000000 + coresight-cpu-debug 850000.debug: EDVIDSR: 90000000 (State:Non-secure Mode:EL1/0 Width:64bits VMID:0) + coresight-cpu-debug 852000.debug: CPU[1]: + coresight-cpu-debug 852000.debug: EDPRSR: 00000001 (Power:On DLK:Unlock) + coresight-cpu-debug 852000.debug: EDPCSR: debug_notifier_call+0x23c/0x358 + coresight-cpu-debug 852000.debug: EDCIDSR: 00000000 + coresight-cpu-debug 852000.debug: EDVIDSR: 90000000 (State:Non-secure Mode:EL1/0 Width:64bits VMID:0) diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.rst similarity index 56% rename from Documentation/trace/coresight.txt rename to Documentation/trace/coresight.rst index b027d61b27a6..72f4b7ef1bad 100644 --- a/Documentation/trace/coresight.txt +++ b/Documentation/trace/coresight.rst @@ -1,8 +1,9 @@ - Coresight - HW Assisted Tracing on ARM - ====================================== +====================================== +Coresight - HW Assisted Tracing on ARM +====================================== - Author: Mathieu Poirier - Date: September 11th, 2014 + :Author: Mathieu Poirier + :Date: September 11th, 2014 Introduction ------------ @@ -26,7 +27,7 @@ implementation, either storing the compressed stream in a memory buffer or creating an interface to the outside world where data can be transferred to a host without fear of filling up the onboard coresight memory buffer. -At typical coresight system would look like this: +At typical coresight system would look like this:: ***************************************************************** **************************** AMBA AXI ****************************===|| @@ -95,15 +96,24 @@ Acronyms and Classification Acronyms: -PTM: Program Trace Macrocell -ETM: Embedded Trace Macrocell -STM: System trace Macrocell -ETB: Embedded Trace Buffer -ITM: Instrumentation Trace Macrocell -TPIU: Trace Port Interface Unit -TMC-ETR: Trace Memory Controller, configured as Embedded Trace Router -TMC-ETF: Trace Memory Controller, configured as Embedded Trace FIFO -CTI: Cross Trigger Interface +PTM: + Program Trace Macrocell +ETM: + Embedded Trace Macrocell +STM: + System trace Macrocell +ETB: + Embedded Trace Buffer +ITM: + Instrumentation Trace Macrocell +TPIU: + Trace Port Interface Unit +TMC-ETR: + Trace Memory Controller, configured as Embedded Trace Router +TMC-ETF: + Trace Memory Controller, configured as Embedded Trace FIFO +CTI: + Cross Trigger Interface Classification: @@ -118,7 +128,7 @@ Misc: Device Tree Bindings ----------------------- +-------------------- See Documentation/devicetree/bindings/arm/coresight.txt for details. @@ -133,79 +143,79 @@ The coresight framework provides a central point to represent, configure and manage coresight devices on a platform. Any coresight compliant device can register with the framework for as long as they use the right APIs: -struct coresight_device *coresight_register(struct coresight_desc *desc); -void coresight_unregister(struct coresight_device *csdev); +.. c:function:: struct coresight_device *coresight_register(struct coresight_desc *desc); +.. c:function:: void coresight_unregister(struct coresight_device *csdev); -The registering function is taking a "struct coresight_device *csdev" and -register the device with the core framework. The unregister function takes -a reference to a "struct coresight_device", obtained at registration time. +The registering function is taking a ``struct coresight_desc *desc`` and +register the device with the core framework. The unregister function takes +a reference to a ``struct coresight_device *csdev`` obtained at registration time. If everything goes well during the registration process the new devices will -show up under /sys/bus/coresight/devices, as showns here for a TC2 platform: +show up under /sys/bus/coresight/devices, as showns here for a TC2 platform:: -root:~# ls /sys/bus/coresight/devices/ -replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm -20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm -root:~# + root:~# ls /sys/bus/coresight/devices/ + replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm + 20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm + root:~# -The functions take a "struct coresight_device", which looks like this: +The functions take a ``struct coresight_device``, which looks like this:: -struct coresight_desc { - enum coresight_dev_type type; - struct coresight_dev_subtype subtype; - const struct coresight_ops *ops; - struct coresight_platform_data *pdata; - struct device *dev; - const struct attribute_group **groups; -}; + struct coresight_desc { + enum coresight_dev_type type; + struct coresight_dev_subtype subtype; + const struct coresight_ops *ops; + struct coresight_platform_data *pdata; + struct device *dev; + const struct attribute_group **groups; + }; The "coresight_dev_type" identifies what the device is, i.e, source link or sink while the "coresight_dev_subtype" will characterise that type further. -The "struct coresight_ops" is mandatory and will tell the framework how to +The ``struct coresight_ops`` is mandatory and will tell the framework how to perform base operations related to the components, each component having -a different set of requirement. For that "struct coresight_ops_sink", -"struct coresight_ops_link" and "struct coresight_ops_source" have been +a different set of requirement. For that ``struct coresight_ops_sink``, +``struct coresight_ops_link`` and ``struct coresight_ops_source`` have been provided. -The next field, "struct coresight_platform_data *pdata" is acquired by calling -"of_get_coresight_platform_data()", as part of the driver's _probe routine and -"struct device *dev" gets the device reference embedded in the "amba_device": +The next field ``struct coresight_platform_data *pdata`` is acquired by calling +``of_get_coresight_platform_data()``, as part of the driver's _probe routine and +``struct device *dev`` gets the device reference embedded in the ``amba_device``:: -static int etm_probe(struct amba_device *adev, const struct amba_id *id) -{ - ... - ... - drvdata->dev = &adev->dev; - ... -} + static int etm_probe(struct amba_device *adev, const struct amba_id *id) + { + ... + ... + drvdata->dev = &adev->dev; + ... + } Specific class of device (source, link, or sink) have generic operations -that can be performed on them (see "struct coresight_ops"). The -"**groups" is a list of sysfs entries pertaining to operations +that can be performed on them (see ``struct coresight_ops``). The ``**groups`` +is a list of sysfs entries pertaining to operations specific to that component only. "Implementation defined" customisations are expected to be accessed and controlled using those entries. - Device Naming scheme ------------------------- +-------------------- + The devices that appear on the "coresight" bus were named the same as their parent devices, i.e, the real devices that appears on AMBA bus or the platform bus. Thus the names were based on the Linux Open Firmware layer naming convention, which follows the base physical address of the device followed by the device -type. e.g: +type. e.g:: -root:~# ls /sys/bus/coresight/devices/ - 20010000.etf 20040000.funnel 20100000.stm 22040000.etm - 22140000.etm 230c0000.funnel 23240000.etm 20030000.tpiu - 20070000.etr 20120000.replicator 220c0000.funnel - 23040000.etm 23140000.etm 23340000.etm + root:~# ls /sys/bus/coresight/devices/ + 20010000.etf 20040000.funnel 20100000.stm 22040000.etm + 22140000.etm 230c0000.funnel 23240000.etm 20030000.tpiu + 20070000.etr 20120000.replicator 220c0000.funnel + 23040000.etm 23140000.etm 23340000.etm However, with the introduction of ACPI support, the names of the real devices are a bit cryptic and non-obvious. Thus, a new naming scheme was introduced to use more generic names based on the type of the device. The -following rules apply: +following rules apply:: 1) Devices that are bound to CPUs, are named based on the CPU logical number. @@ -220,11 +230,11 @@ following rules apply: e.g, tmc_etf0, tmc_etr0, funnel0, funnel1 -Thus, with the new scheme the devices could appear as : +Thus, with the new scheme the devices could appear as :: -root:~# ls /sys/bus/coresight/devices/ - etm0 etm1 etm2 etm3 etm4 etm5 funnel0 - funnel1 funnel2 replicator0 stm0 tmc_etf0 tmc_etr0 tpiu0 + root:~# ls /sys/bus/coresight/devices/ + etm0 etm1 etm2 etm3 etm4 etm5 funnel0 + funnel1 funnel2 replicator0 stm0 tmc_etf0 tmc_etr0 tpiu0 Some of the examples below might refer to old naming scheme and some to the newer scheme, to give a confirmation that what you see on your @@ -234,9 +244,12 @@ the system under specified locations. How to use the tracer modules ----------------------------- -There are two ways to use the Coresight framework: 1) using the perf cmd line -tools and 2) interacting directly with the Coresight devices using the sysFS -interface. Preference is given to the former as using the sysFS interface +There are two ways to use the Coresight framework: + +1. using the perf cmd line tools. +2. interacting directly with the Coresight devices using the sysFS interface. + +Preference is given to the former as using the sysFS interface requires a deep understanding of the Coresight HW. The following sections provide details on using both methods. @@ -245,107 +258,107 @@ provide details on using both methods. Before trace collection can start, a coresight sink needs to be identified. There is no limit on the amount of sinks (nor sources) that can be enabled at any given moment. As a generic operation, all device pertaining to the sink -class will have an "active" entry in sysfs: - -root:/sys/bus/coresight/devices# ls -replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm -20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm -root:/sys/bus/coresight/devices# ls 20010000.etb -enable_sink status trigger_cntr -root:/sys/bus/coresight/devices# echo 1 > 20010000.etb/enable_sink -root:/sys/bus/coresight/devices# cat 20010000.etb/enable_sink -1 -root:/sys/bus/coresight/devices# +class will have an "active" entry in sysfs:: + + root:/sys/bus/coresight/devices# ls + replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm + 20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm + root:/sys/bus/coresight/devices# ls 20010000.etb + enable_sink status trigger_cntr + root:/sys/bus/coresight/devices# echo 1 > 20010000.etb/enable_sink + root:/sys/bus/coresight/devices# cat 20010000.etb/enable_sink + 1 + root:/sys/bus/coresight/devices# At boot time the current etm3x driver will configure the first address comparator with "_stext" and "_etext", essentially tracing any instruction that falls within that range. As such "enabling" a source will immediately -trigger a trace capture: - -root:/sys/bus/coresight/devices# echo 1 > 2201c000.ptm/enable_source -root:/sys/bus/coresight/devices# cat 2201c000.ptm/enable_source -1 -root:/sys/bus/coresight/devices# cat 20010000.etb/status -Depth: 0x2000 -Status: 0x1 -RAM read ptr: 0x0 -RAM wrt ptr: 0x19d3 <----- The write pointer is moving -Trigger cnt: 0x0 -Control: 0x1 -Flush status: 0x0 -Flush ctrl: 0x2001 -root:/sys/bus/coresight/devices# - -Trace collection is stopped the same way: - -root:/sys/bus/coresight/devices# echo 0 > 2201c000.ptm/enable_source -root:/sys/bus/coresight/devices# - -The content of the ETB buffer can be harvested directly from /dev: - -root:/sys/bus/coresight/devices# dd if=/dev/20010000.etb \ -of=~/cstrace.bin - -64+0 records in -64+0 records out -32768 bytes (33 kB) copied, 0.00125258 s, 26.2 MB/s -root:/sys/bus/coresight/devices# +trigger a trace capture:: + + root:/sys/bus/coresight/devices# echo 1 > 2201c000.ptm/enable_source + root:/sys/bus/coresight/devices# cat 2201c000.ptm/enable_source + 1 + root:/sys/bus/coresight/devices# cat 20010000.etb/status + Depth: 0x2000 + Status: 0x1 + RAM read ptr: 0x0 + RAM wrt ptr: 0x19d3 <----- The write pointer is moving + Trigger cnt: 0x0 + Control: 0x1 + Flush status: 0x0 + Flush ctrl: 0x2001 + root:/sys/bus/coresight/devices# + +Trace collection is stopped the same way:: + + root:/sys/bus/coresight/devices# echo 0 > 2201c000.ptm/enable_source + root:/sys/bus/coresight/devices# + +The content of the ETB buffer can be harvested directly from /dev:: + + root:/sys/bus/coresight/devices# dd if=/dev/20010000.etb \ + of=~/cstrace.bin + 64+0 records in + 64+0 records out + 32768 bytes (33 kB) copied, 0.00125258 s, 26.2 MB/s + root:/sys/bus/coresight/devices# The file cstrace.bin can be decompressed using "ptm2human", DS-5 or Trace32. Following is a DS-5 output of an experimental loop that increments a variable up to a certain value. The example is simple and yet provides a glimpse of the wealth of possibilities that coresight provides. - -Info Tracing enabled -Instruction 106378866 0x8026B53C E52DE004 false PUSH {lr} -Instruction 0 0x8026B540 E24DD00C false SUB sp,sp,#0xc -Instruction 0 0x8026B544 E3A03000 false MOV r3,#0 -Instruction 0 0x8026B548 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Timestamp Timestamp: 17106715833 -Instruction 319 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Instruction 9 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Instruction 10 0x8026B54C E59D3004 false LDR r3,[sp,#4] -Instruction 0 0x8026B550 E3530004 false CMP r3,#4 -Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 -Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] -Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c -Instruction 6 0x8026B560 EE1D3F30 false MRC p15,#0x0,r3,c13,c0,#1 -Instruction 0 0x8026B564 E1A0100D false MOV r1,sp -Instruction 0 0x8026B568 E3C12D7F false BIC r2,r1,#0x1fc0 -Instruction 0 0x8026B56C E3C2203F false BIC r2,r2,#0x3f -Instruction 0 0x8026B570 E59D1004 false LDR r1,[sp,#4] -Instruction 0 0x8026B574 E59F0010 false LDR r0,[pc,#16] ; [0x8026B58C] = 0x80550368 -Instruction 0 0x8026B578 E592200C false LDR r2,[r2,#0xc] -Instruction 0 0x8026B57C E59221D0 false LDR r2,[r2,#0x1d0] -Instruction 0 0x8026B580 EB07A4CF true BL {pc}+0x1e9344 ; 0x804548c4 -Info Tracing enabled -Instruction 13570831 0x8026B584 E28DD00C false ADD sp,sp,#0xc -Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc} -Timestamp Timestamp: 17107041535 +:: + + Info Tracing enabled + Instruction 106378866 0x8026B53C E52DE004 false PUSH {lr} + Instruction 0 0x8026B540 E24DD00C false SUB sp,sp,#0xc + Instruction 0 0x8026B544 E3A03000 false MOV r3,#0 + Instruction 0 0x8026B548 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Timestamp Timestamp: 17106715833 + Instruction 319 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Instruction 9 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Instruction 10 0x8026B54C E59D3004 false LDR r3,[sp,#4] + Instruction 0 0x8026B550 E3530004 false CMP r3,#4 + Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 + Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] + Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c + Instruction 6 0x8026B560 EE1D3F30 false MRC p15,#0x0,r3,c13,c0,#1 + Instruction 0 0x8026B564 E1A0100D false MOV r1,sp + Instruction 0 0x8026B568 E3C12D7F false BIC r2,r1,#0x1fc0 + Instruction 0 0x8026B56C E3C2203F false BIC r2,r2,#0x3f + Instruction 0 0x8026B570 E59D1004 false LDR r1,[sp,#4] + Instruction 0 0x8026B574 E59F0010 false LDR r0,[pc,#16] ; [0x8026B58C] = 0x80550368 + Instruction 0 0x8026B578 E592200C false LDR r2,[r2,#0xc] + Instruction 0 0x8026B57C E59221D0 false LDR r2,[r2,#0x1d0] + Instruction 0 0x8026B580 EB07A4CF true BL {pc}+0x1e9344 ; 0x804548c4 + Info Tracing enabled + Instruction 13570831 0x8026B584 E28DD00C false ADD sp,sp,#0xc + Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc} + Timestamp Timestamp: 17107041535 2) Using perf framework: @@ -370,19 +383,18 @@ A Coresight PMU works the same way as any other PMU, i.e the name of the PMU is listed along with configuration options within forward slashes '/'. Since a Coresight system will typically have more than one sink, the name of the sink to work with needs to be specified as an event option. -On newer kernels the available sinks are listed in sysFS under: -($SYSFS)/bus/event_source/devices/cs_etm/sinks/ +On newer kernels the available sinks are listed in sysFS under +($SYSFS)/bus/event_source/devices/cs_etm/sinks/:: root@localhost:/sys/bus/event_source/devices/cs_etm/sinks# ls tmc_etf0 tmc_etr0 tpiu0 On older kernels, this may need to be found from the list of coresight devices, -available under ($SYSFS)/bus/coresight/devices/: +available under ($SYSFS)/bus/coresight/devices/:: root:~# ls /sys/bus/coresight/devices/ etm0 etm1 etm2 etm3 etm4 etm5 funnel0 funnel1 funnel2 replicator0 stm0 tmc_etf0 tmc_etr0 tpiu0 - root@linaro-nano:~# perf record -e cs_etm/@tmc_etr0/u --per-thread program As mentioned above in section "Device Naming scheme", the names of the devices could @@ -395,14 +407,14 @@ to use for the trace session. More information on the above and other example on how to use Coresight with the perf tools can be found in the "HOWTO.md" file of the openCSD gitHub -repository [3]. +repository [#third]_. 2.1) AutoFDO analysis using the perf tools: perf can be used to record and analyze trace of programs. Execution can be recorded using 'perf record' with the cs_etm event, -specifying the name of the sink to record to, e.g: +specifying the name of the sink to record to, e.g:: perf record -e cs_etm/@tmc_etr0/u --per-thread @@ -421,12 +433,14 @@ Generating coverage files for Feedback Directed Optimization: AutoFDO 'perf inject' accepts the --itrace option in which case tracing data is removed and replaced with the synthesized events. e.g. +:: perf inject --itrace --strip -i perf.data -o perf.data.new Below is an example of using ARM ETM for autoFDO. It requires autofdo (https://github.com/google/autofdo) and gcc version 5. The bubble sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial). +:: $ gcc-5 -O3 sort.c -o sort $ taskset -c 2 ./sort @@ -455,28 +469,30 @@ difference is that clients are driving the trace capture rather than the program flow through the code. As with any other CoreSight component, specifics about the STM tracer can be -found in sysfs with more information on each entry being found in [1]: +found in sysfs with more information on each entry being found in [#first]_:: -root@genericarmv8:~# ls /sys/bus/coresight/devices/stm0 -enable_source hwevent_select port_enable subsystem uevent -hwevent_enable mgmt port_select traceid -root@genericarmv8:~# + root@genericarmv8:~# ls /sys/bus/coresight/devices/stm0 + enable_source hwevent_select port_enable subsystem uevent + hwevent_enable mgmt port_select traceid + root@genericarmv8:~# Like any other source a sink needs to be identified and the STM enabled before -being used: +being used:: -root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink -root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/stm0/enable_source + root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink + root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/stm0/enable_source From there user space applications can request and use channels using the devfs -interface provided for that purpose by the generic STM API: +interface provided for that purpose by the generic STM API:: + + root@genericarmv8:~# ls -l /dev/stm0 + crw------- 1 root root 10, 61 Jan 3 18:11 /dev/stm0 + root@genericarmv8:~# + +Details on how to use the generic STM API can be found here [#second]_. -root@genericarmv8:~# ls -l /dev/stm0 -crw------- 1 root root 10, 61 Jan 3 18:11 /dev/stm0 -root@genericarmv8:~# +.. [#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm -Details on how to use the generic STM API can be found here [2]. +.. [#second] Documentation/trace/stm.rst -[1]. Documentation/ABI/testing/sysfs-bus-coresight-devices-stm -[2]. Documentation/trace/stm.rst -[3]. https://github.com/Linaro/perf-opencsd +.. [#third] https://github.com/Linaro/perf-opencsd diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 6b4107cf4b98..b7891cb1ab4d 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -23,3 +23,5 @@ Linux Tracing Technologies intel_th stm sys-t + coresight + coresight-cpu-debug diff --git a/MAINTAINERS b/MAINTAINERS index 811218cc2355..7a07cda43592 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1582,8 +1582,8 @@ R: Suzuki K Poulose L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: drivers/hwtracing/coresight/* -F: Documentation/trace/coresight.txt -F: Documentation/trace/coresight-cpu-debug.txt +F: Documentation/trace/coresight.rst +F: Documentation/trace/coresight-cpu-debug.rst F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* -- GitLab From eaf7b46083a7e341a23ab3d6042e0ccc115b0914 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:12 -0300 Subject: [PATCH 1452/7155] docs: thermal: add it to the driver API The file contents mostly describes driver internals. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/driver-api/index.rst | 1 + .../{ => driver-api}/thermal/cpu-cooling-api.rst | 0 .../{ => driver-api}/thermal/exynos_thermal.rst | 0 .../thermal/exynos_thermal_emulation.rst | 0 Documentation/{ => driver-api}/thermal/index.rst | 2 +- .../{ => driver-api}/thermal/intel_powerclamp.rst | 0 .../{ => driver-api}/thermal/nouveau_thermal.rst | 0 .../{ => driver-api}/thermal/power_allocator.rst | 0 Documentation/{ => driver-api}/thermal/sysfs-api.rst | 12 ++++++------ .../thermal/x86_pkg_temperature_thermal.rst | 2 +- MAINTAINERS | 2 +- include/linux/thermal.h | 4 ++-- 12 files changed, 12 insertions(+), 11 deletions(-) rename Documentation/{ => driver-api}/thermal/cpu-cooling-api.rst (100%) rename Documentation/{ => driver-api}/thermal/exynos_thermal.rst (100%) rename Documentation/{ => driver-api}/thermal/exynos_thermal_emulation.rst (100%) rename Documentation/{ => driver-api}/thermal/index.rst (86%) rename Documentation/{ => driver-api}/thermal/intel_powerclamp.rst (100%) rename Documentation/{ => driver-api}/thermal/nouveau_thermal.rst (100%) rename Documentation/{ => driver-api}/thermal/power_allocator.rst (100%) rename Documentation/{ => driver-api}/thermal/sysfs-api.rst (98%) rename Documentation/{ => driver-api}/thermal/x86_pkg_temperature_thermal.rst (94%) diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index d12a80f386a6..37ac052ded85 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -65,6 +65,7 @@ available subsections can be seen below. dmaengine/index slimbus soundwire/index + thermal/index fpga/index acpi/index backlight/lp855x-driver.rst diff --git a/Documentation/thermal/cpu-cooling-api.rst b/Documentation/driver-api/thermal/cpu-cooling-api.rst similarity index 100% rename from Documentation/thermal/cpu-cooling-api.rst rename to Documentation/driver-api/thermal/cpu-cooling-api.rst diff --git a/Documentation/thermal/exynos_thermal.rst b/Documentation/driver-api/thermal/exynos_thermal.rst similarity index 100% rename from Documentation/thermal/exynos_thermal.rst rename to Documentation/driver-api/thermal/exynos_thermal.rst diff --git a/Documentation/thermal/exynos_thermal_emulation.rst b/Documentation/driver-api/thermal/exynos_thermal_emulation.rst similarity index 100% rename from Documentation/thermal/exynos_thermal_emulation.rst rename to Documentation/driver-api/thermal/exynos_thermal_emulation.rst diff --git a/Documentation/thermal/index.rst b/Documentation/driver-api/thermal/index.rst similarity index 86% rename from Documentation/thermal/index.rst rename to Documentation/driver-api/thermal/index.rst index 8c1c00146cad..5ba61d19c6ae 100644 --- a/Documentation/thermal/index.rst +++ b/Documentation/driver-api/thermal/index.rst @@ -1,4 +1,4 @@ -:orphan: +.. SPDX-License-Identifier: GPL-2.0 ======= Thermal diff --git a/Documentation/thermal/intel_powerclamp.rst b/Documentation/driver-api/thermal/intel_powerclamp.rst similarity index 100% rename from Documentation/thermal/intel_powerclamp.rst rename to Documentation/driver-api/thermal/intel_powerclamp.rst diff --git a/Documentation/thermal/nouveau_thermal.rst b/Documentation/driver-api/thermal/nouveau_thermal.rst similarity index 100% rename from Documentation/thermal/nouveau_thermal.rst rename to Documentation/driver-api/thermal/nouveau_thermal.rst diff --git a/Documentation/thermal/power_allocator.rst b/Documentation/driver-api/thermal/power_allocator.rst similarity index 100% rename from Documentation/thermal/power_allocator.rst rename to Documentation/driver-api/thermal/power_allocator.rst diff --git a/Documentation/thermal/sysfs-api.rst b/Documentation/driver-api/thermal/sysfs-api.rst similarity index 98% rename from Documentation/thermal/sysfs-api.rst rename to Documentation/driver-api/thermal/sysfs-api.rst index e4930761d3e5..fab2c9b36d08 100644 --- a/Documentation/thermal/sysfs-api.rst +++ b/Documentation/driver-api/thermal/sysfs-api.rst @@ -552,7 +552,7 @@ emul_temp sustainable_power An estimate of the sustained power that can be dissipated by the thermal zone. Used by the power allocator governor. For - more information see Documentation/thermal/power_allocator.rst + more information see Documentation/driver-api/thermal/power_allocator.rst Unit: milliwatts @@ -563,7 +563,7 @@ k_po controller during temperature overshoot. Temperature overshoot is when the current temperature is above the "desired temperature" trip point. For more information see - Documentation/thermal/power_allocator.rst + Documentation/driver-api/thermal/power_allocator.rst RW, Optional @@ -572,7 +572,7 @@ k_pu controller during temperature undershoot. Temperature undershoot is when the current temperature is below the "desired temperature" trip point. For more information see - Documentation/thermal/power_allocator.rst + Documentation/driver-api/thermal/power_allocator.rst RW, Optional @@ -580,14 +580,14 @@ k_i The integral term of the power allocator governor's PID controller. This term allows the PID controller to compensate for long term drift. For more information see - Documentation/thermal/power_allocator.rst + Documentation/driver-api/thermal/power_allocator.rst RW, Optional k_d The derivative term of the power allocator governor's PID controller. For more information see - Documentation/thermal/power_allocator.rst + Documentation/driver-api/thermal/power_allocator.rst RW, Optional @@ -598,7 +598,7 @@ integral_cutoff example, if integral_cutoff is 0, then the integral term only accumulates error when temperature is above the desired temperature trip point. For more information see - Documentation/thermal/power_allocator.rst + Documentation/driver-api/thermal/power_allocator.rst Unit: millidegree Celsius diff --git a/Documentation/thermal/x86_pkg_temperature_thermal.rst b/Documentation/driver-api/thermal/x86_pkg_temperature_thermal.rst similarity index 94% rename from Documentation/thermal/x86_pkg_temperature_thermal.rst rename to Documentation/driver-api/thermal/x86_pkg_temperature_thermal.rst index f134dbd3f5a9..2ac42ccd236f 100644 --- a/Documentation/thermal/x86_pkg_temperature_thermal.rst +++ b/Documentation/driver-api/thermal/x86_pkg_temperature_thermal.rst @@ -40,7 +40,7 @@ This contains two trip points: - trip_point_1_temp User can set any temperature between 0 to TJ-Max temperature. Temperature units -are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.rst" for +are in milli-degree Celsius. Refer to "Documentation/driver-api/thermal/sysfs-api.rst" for thermal sys-fs details. Any value other than 0 in these trip points, can trigger thermal notifications. diff --git a/MAINTAINERS b/MAINTAINERS index 7a07cda43592..6326445952f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15916,7 +15916,7 @@ M: Viresh Kumar M: Javi Merino L: linux-pm@vger.kernel.org S: Supported -F: Documentation/thermal/cpu-cooling-api.rst +F: Documentation/driver-api/thermal/cpu-cooling-api.rst F: drivers/thermal/cpu_cooling.c F: include/linux/cpu_cooling.h diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 681047f8cc05..e45659c75920 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -251,7 +251,7 @@ struct thermal_bind_params { * platform characterization. This value is relative to the * rest of the weights so a cooling device whose weight is * double that of another cooling device is twice as - * effective. See Documentation/thermal/sysfs-api.rst for more + * effective. See Documentation/driver-api/thermal/sysfs-api.rst for more * information. */ int weight; @@ -259,7 +259,7 @@ struct thermal_bind_params { /* * This is a bit mask that gives the binding relation between this * thermal zone and cdev, for a particular trip point. - * See Documentation/thermal/sysfs-api.rst for more information. + * See Documentation/driver-api/thermal/sysfs-api.rst for more information. */ int trip_mask; -- GitLab From 09f4c750a8c7d1fc0b7bb3a7aa1de55de897a375 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:14 -0300 Subject: [PATCH 1453/7155] docs: ubifs-authentication.md: convert to ReST The documentation standard is ReST and not markdown. Signed-off-by: Mauro Carvalho Chehab Acked-by: Rob Herring Signed-off-by: Jonathan Corbet --- ...entication.md => ubifs-authentication.rst} | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) rename Documentation/filesystems/{ubifs-authentication.md => ubifs-authentication.rst} (95%) diff --git a/Documentation/filesystems/ubifs-authentication.md b/Documentation/filesystems/ubifs-authentication.rst similarity index 95% rename from Documentation/filesystems/ubifs-authentication.md rename to Documentation/filesystems/ubifs-authentication.rst index 23e698167141..6a9584f6ff46 100644 --- a/Documentation/filesystems/ubifs-authentication.md +++ b/Documentation/filesystems/ubifs-authentication.rst @@ -1,8 +1,11 @@ -% UBIFS Authentication -% sigma star gmbh -% 2018 +:orphan: -# Introduction +.. UBIFS Authentication +.. sigma star gmbh +.. 2018 + +Introduction +============ UBIFS utilizes the fscrypt framework to provide confidentiality for file contents and file names. This prevents attacks where an attacker is able to @@ -33,7 +36,8 @@ existing features like key derivation can be utilized. It should however also be possible to use UBIFS authentication without using encryption. -## MTD, UBI & UBIFS +MTD, UBI & UBIFS +---------------- On Linux, the MTD (Memory Technology Devices) subsystem provides a uniform interface to access raw flash devices. One of the more prominent subsystems that @@ -47,7 +51,7 @@ UBIFS is a filesystem for raw flash which operates on top of UBI. Thus, wear leveling and some flash specifics are left to UBI, while UBIFS focuses on scalability, performance and recoverability. - +:: +------------+ +*******+ +-----------+ +-----+ | | * UBIFS * | UBI-BLOCK | | ... | @@ -84,7 +88,8 @@ persisted onto the flash directly. More details on UBIFS can also be found in [UBIFS-WP]. -### UBIFS Index & Tree Node Cache +UBIFS Index & Tree Node Cache +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Basic on-flash UBIFS entities are called *nodes*. UBIFS knows different types of nodes. Eg. data nodes (`struct ubifs_data_node`) which store chunks of file @@ -118,17 +123,18 @@ on-flash filesystem structures like the index. On every commit, the TNC nodes marked as dirty are written to the flash to update the persisted index. -### Journal +Journal +~~~~~~~ To avoid wearing out the flash, the index is only persisted (*commited*) when -certain conditions are met (eg. `fsync(2)`). The journal is used to record +certain conditions are met (eg. ``fsync(2)``). The journal is used to record any changes (in form of inode nodes, data nodes etc.) between commits of the index. During mount, the journal is read from the flash and replayed onto the TNC (which will be created on-demand from the on-flash index). UBIFS reserves a bunch of LEBs just for the journal called *log area*. The amount of log area LEBs is configured on filesystem creation (using -`mkfs.ubifs`) and stored in the superblock node. The log area contains only +``mkfs.ubifs``) and stored in the superblock node. The log area contains only two types of nodes: *reference nodes* and *commit start nodes*. A commit start node is written whenever an index commit is performed. Reference nodes are written on every journal update. Each reference node points to the position of @@ -152,6 +158,7 @@ done for the last referenced LEB of the journal. Only this can become corrupt because of a power cut. If the recovery fails, UBIFS will not mount. An error for every other LEB will directly cause UBIFS to fail the mount operation. +:: | ---- LOG AREA ---- | ---------- MAIN AREA ------------ | @@ -172,10 +179,11 @@ for every other LEB will directly cause UBIFS to fail the mount operation. containing their buds -### LEB Property Tree/Table +LEB Property Tree/Table +~~~~~~~~~~~~~~~~~~~~~~~ The LEB property tree is used to store per-LEB information. This includes the -LEB type and amount of free and *dirty* (old, obsolete content) space [1] on +LEB type and amount of free and *dirty* (old, obsolete content) space [1]_ on the LEB. The type is important, because UBIFS never mixes index nodes with data nodes on a single LEB and thus each LEB has a specific purpose. This again is useful for free space calculations. See [UBIFS-WP] for more details. @@ -185,19 +193,21 @@ index. Due to its smaller size it is always written as one chunk on every commit. Thus, saving the LPT is an atomic operation. -[1] Since LEBs can only be appended and never overwritten, there is a -difference between free space ie. the remaining space left on the LEB to be -written to without erasing it and previously written content that is obsolete -but can't be overwritten without erasing the full LEB. +.. [1] Since LEBs can only be appended and never overwritten, there is a + difference between free space ie. the remaining space left on the LEB to be + written to without erasing it and previously written content that is obsolete + but can't be overwritten without erasing the full LEB. -# UBIFS Authentication +UBIFS Authentication +==================== This chapter introduces UBIFS authentication which enables UBIFS to verify the authenticity and integrity of metadata and file contents stored on flash. -## Threat Model +Threat Model +------------ UBIFS authentication enables detection of offline data modification. While it does not prevent it, it enables (trusted) code to check the integrity and @@ -224,7 +234,8 @@ Additional measures like secure boot and trusted boot have to be taken to ensure that only trusted code is executed on a device. -## Authentication +Authentication +-------------- To be able to fully trust data read from flash, all UBIFS data structures stored on flash are authenticated. That is: @@ -236,7 +247,8 @@ stored on flash are authenticated. That is: - The LPT which stores UBI LEB metadata which UBIFS uses for free space accounting -### Index Authentication +Index Authentication +~~~~~~~~~~~~~~~~~~~~ Through UBIFS' concept of a wandering tree, it already takes care of only updating and persisting changed parts from leaf node up to the root node @@ -260,6 +272,7 @@ include a hash. All other types of nodes will remain unchanged. This reduces the storage overhead which is precious for users of UBIFS (ie. embedded devices). +:: +---------------+ | Master Node | @@ -303,7 +316,8 @@ hashes to index nodes does not change this since each hash will be persisted atomically together with its respective node. -### Journal Authentication +Journal Authentication +~~~~~~~~~~~~~~~~~~~~~~ The journal is authenticated too. Since the journal is continuously written it is necessary to also add authentication information frequently to the @@ -316,7 +330,7 @@ of the hash chain. That way a journal can be authenticated up to the last authentication node. The tail of the journal which may not have a authentication node cannot be authenticated and is skipped during journal replay. -We get this picture for journal authentication: +We get this picture for journal authentication:: ,,,,,,,, ,......,........................................... @@ -352,7 +366,8 @@ the superblock struct. The superblock node is stored in LEB 0 and is only modified on feature flag or similar changes, but never on file changes. -### LPT Authentication +LPT Authentication +~~~~~~~~~~~~~~~~~~ The location of the LPT root node on the flash is stored in the UBIFS master node. Since the LPT is written and read atomically on every commit, there is @@ -363,7 +378,8 @@ be verified by verifying the authenticity of the master node and comparing the LTP hash stored there with the hash computed from the read on-flash LPT. -## Key Management +Key Management +-------------- For simplicity, UBIFS authentication uses a single key to compute the HMACs of superblock, master, commit start and reference nodes. This key has to be @@ -399,7 +415,8 @@ approach is similar to the approach proposed for fscrypt encryption policy v2 [FSCRYPT-POLICY2]. -# Future Extensions +Future Extensions +================= In certain cases where a vendor wants to provide an authenticated filesystem image to customers, it should be possible to do so without sharing the secret @@ -411,7 +428,8 @@ to the way the IMA/EVM subsystem deals with such situations. The HMAC key will then have to be provided beforehand in the normal way. -# References +References +========== [CRYPTSETUP2] http://www.saout.de/pipermail/dm-crypt/2017-November/005745.html -- GitLab From ccf988b66d697efcd0ceccc2398e0d9b909cd17c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:16 -0300 Subject: [PATCH 1454/7155] docs: i2c: convert to ReST and add to driver-api bookset Convert each file at I2C subsystem, renaming them to .rst and adding to the driver-api book. Signed-off-by: Mauro Carvalho Chehab Acked-by: Wolfram Sang Acked-by: Alexandre Belloni Acked-by: Jonathan Cameron Signed-off-by: Jonathan Corbet --- .../devicetree/bindings/i2c/i2c-mux-gpmux.txt | 2 +- Documentation/driver-api/ipmb.rst | 2 +- Documentation/hwmon/adm1021.rst | 2 +- Documentation/hwmon/adm1275.rst | 2 +- Documentation/hwmon/hih6130.rst | 2 +- Documentation/hwmon/ibm-cffps.rst | 2 +- Documentation/hwmon/lm25066.rst | 2 +- Documentation/hwmon/max16064.rst | 2 +- Documentation/hwmon/max16065.rst | 2 +- Documentation/hwmon/max20751.rst | 2 +- Documentation/hwmon/max34440.rst | 2 +- Documentation/hwmon/max6650.rst | 2 +- Documentation/hwmon/max8688.rst | 2 +- Documentation/hwmon/menf21bmc.rst | 2 +- Documentation/hwmon/pcf8591.rst | 2 +- Documentation/hwmon/sht3x.rst | 2 +- Documentation/hwmon/shtc1.rst | 2 +- Documentation/hwmon/tmp103.rst | 2 +- Documentation/hwmon/tps40422.rst | 2 +- Documentation/hwmon/ucd9000.rst | 2 +- Documentation/hwmon/ucd9200.rst | 2 +- Documentation/hwmon/via686a.rst | 2 +- Documentation/hwmon/zl6100.rst | 2 +- .../busses/{i2c-ali1535 => i2c-ali1535.rst} | 13 +- .../busses/{i2c-ali1563 => i2c-ali1563.rst} | 3 + .../busses/{i2c-ali15x3 => i2c-ali15x3.rst} | 64 +++--- Documentation/i2c/busses/i2c-amd-mp2 | 23 -- Documentation/i2c/busses/i2c-amd-mp2.rst | 25 +++ .../i2c/busses/{i2c-amd756 => i2c-amd756.rst} | 8 +- .../busses/{i2c-amd8111 => i2c-amd8111.rst} | 14 +- .../{i2c-diolan-u2c => i2c-diolan-u2c.rst} | 3 + .../i2c/busses/{i2c-i801 => i2c-i801.rst} | 33 +-- .../i2c/busses/{i2c-ismt => i2c-ismt.rst} | 20 +- .../busses/{i2c-mlxcpld => i2c-mlxcpld.rst} | 6 + .../busses/{i2c-nforce2 => i2c-nforce2.rst} | 33 +-- .../{i2c-nvidia-gpu => i2c-nvidia-gpu.rst} | 6 +- .../i2c/busses/{i2c-ocores => i2c-ocores.rst} | 22 +- Documentation/i2c/busses/i2c-parport | 178 --------------- ...2c-parport-light => i2c-parport-light.rst} | 8 +- Documentation/i2c/busses/i2c-parport.rst | 190 ++++++++++++++++ .../busses/{i2c-pca-isa => i2c-pca-isa.rst} | 9 +- .../i2c/busses/{i2c-piix4 => i2c-piix4.rst} | 18 +- .../busses/{i2c-sis5595 => i2c-sis5595.rst} | 19 +- Documentation/i2c/busses/i2c-sis630 | 58 ----- Documentation/i2c/busses/i2c-sis630.rst | 63 ++++++ .../i2c/busses/{i2c-sis96x => i2c-sis96x.rst} | 31 ++- .../busses/{i2c-taos-evm => i2c-taos-evm.rst} | 8 +- .../i2c/busses/{i2c-via => i2c-via.rst} | 28 ++- .../i2c/busses/{i2c-viapro => i2c-viapro.rst} | 12 +- Documentation/i2c/busses/index.rst | 33 +++ .../i2c/busses/{scx200_acb => scx200_acb.rst} | 9 +- .../i2c/{dev-interface => dev-interface.rst} | 104 ++++----- ...-considerations => dma-considerations.rst} | 0 .../i2c/{fault-codes => fault-codes.rst} | 5 +- .../i2c/{functionality => functionality.rst} | 22 +- ...ult-injection => gpio-fault-injection.rst} | 12 +- .../i2c/{i2c-protocol => i2c-protocol.rst} | 28 ++- Documentation/i2c/{i2c-stub => i2c-stub.rst} | 20 +- .../i2c/{i2c-topology => i2c-topology.rst} | 68 +++--- Documentation/i2c/index.rst | 37 ++++ ...ting-devices => instantiating-devices.rst} | 45 ++-- .../muxes/{i2c-mux-gpio => i2c-mux-gpio.rst} | 26 +-- ...e-parameters => old-module-parameters.rst} | 27 ++- ...eprom-backend => slave-eeprom-backend.rst} | 4 +- .../{slave-interface => slave-interface.rst} | 33 +-- .../{smbus-protocol => smbus-protocol.rst} | 86 +++++--- Documentation/i2c/{summary => summary.rst} | 6 +- ...en-bit-addresses => ten-bit-addresses.rst} | 5 + ...pgrading-clients => upgrading-clients.rst} | 204 +++++++++--------- .../{writing-clients => writing-clients.rst} | 94 ++++---- Documentation/index.rst | 1 + Documentation/spi/spi-sc18is602 | 2 +- MAINTAINERS | 48 ++--- drivers/hwmon/atxp1.c | 2 +- drivers/hwmon/smm665.c | 2 +- drivers/i2c/Kconfig | 4 +- drivers/i2c/busses/Kconfig | 2 +- drivers/i2c/busses/i2c-i801.c | 2 +- drivers/i2c/busses/i2c-taos-evm.c | 2 +- drivers/i2c/i2c-core-base.c | 4 +- drivers/iio/dummy/iio_simple_dummy.c | 2 +- drivers/rtc/rtc-ds1374.c | 2 +- include/linux/i2c.h | 2 +- 83 files changed, 1095 insertions(+), 789 deletions(-) rename Documentation/i2c/busses/{i2c-ali1535 => i2c-ali1535.rst} (82%) rename Documentation/i2c/busses/{i2c-ali1563 => i2c-ali1563.rst} (93%) rename Documentation/i2c/busses/{i2c-ali15x3 => i2c-ali15x3.rst} (72%) delete mode 100644 Documentation/i2c/busses/i2c-amd-mp2 create mode 100644 Documentation/i2c/busses/i2c-amd-mp2.rst rename Documentation/i2c/busses/{i2c-amd756 => i2c-amd756.rst} (79%) rename Documentation/i2c/busses/{i2c-amd8111 => i2c-amd8111.rst} (66%) rename Documentation/i2c/busses/{i2c-diolan-u2c => i2c-diolan-u2c.rst} (91%) rename Documentation/i2c/busses/{i2c-i801 => i2c-i801.rst} (89%) rename Documentation/i2c/busses/{i2c-ismt => i2c-ismt.rst} (81%) rename Documentation/i2c/busses/{i2c-mlxcpld => i2c-mlxcpld.rst} (88%) rename Documentation/i2c/busses/{i2c-nforce2 => i2c-nforce2.rst} (58%) rename Documentation/i2c/busses/{i2c-nvidia-gpu => i2c-nvidia-gpu.rst} (63%) rename Documentation/i2c/busses/{i2c-ocores => i2c-ocores.rst} (82%) delete mode 100644 Documentation/i2c/busses/i2c-parport rename Documentation/i2c/busses/{i2c-parport-light => i2c-parport-light.rst} (91%) create mode 100644 Documentation/i2c/busses/i2c-parport.rst rename Documentation/i2c/busses/{i2c-pca-isa => i2c-pca-isa.rst} (72%) rename Documentation/i2c/busses/{i2c-piix4 => i2c-piix4.rst} (92%) rename Documentation/i2c/busses/{i2c-sis5595 => i2c-sis5595.rst} (74%) delete mode 100644 Documentation/i2c/busses/i2c-sis630 create mode 100644 Documentation/i2c/busses/i2c-sis630.rst rename Documentation/i2c/busses/{i2c-sis96x => i2c-sis96x.rst} (74%) rename Documentation/i2c/busses/{i2c-taos-evm => i2c-taos-evm.rst} (91%) rename Documentation/i2c/busses/{i2c-via => i2c-via.rst} (54%) rename Documentation/i2c/busses/{i2c-viapro => i2c-viapro.rst} (87%) create mode 100644 Documentation/i2c/busses/index.rst rename Documentation/i2c/busses/{scx200_acb => scx200_acb.rst} (86%) rename Documentation/i2c/{dev-interface => dev-interface.rst} (71%) rename Documentation/i2c/{DMA-considerations => dma-considerations.rst} (100%) rename Documentation/i2c/{fault-codes => fault-codes.rst} (98%) rename Documentation/i2c/{functionality => functionality.rst} (91%) rename Documentation/i2c/{gpio-fault-injection => gpio-fault-injection.rst} (97%) rename Documentation/i2c/{i2c-protocol => i2c-protocol.rst} (83%) rename Documentation/i2c/{i2c-stub => i2c-stub.rst} (93%) rename Documentation/i2c/{i2c-topology => i2c-topology.rst} (89%) create mode 100644 Documentation/i2c/index.rst rename Documentation/i2c/{instantiating-devices => instantiating-devices.rst} (93%) rename Documentation/i2c/muxes/{i2c-mux-gpio => i2c-mux-gpio.rst} (85%) rename Documentation/i2c/{old-module-parameters => old-module-parameters.rst} (75%) rename Documentation/i2c/{slave-eeprom-backend => slave-eeprom-backend.rst} (90%) rename Documentation/i2c/{slave-interface => slave-interface.rst} (94%) rename Documentation/i2c/{smbus-protocol => smbus-protocol.rst} (82%) rename Documentation/i2c/{summary => summary.rst} (96%) rename Documentation/i2c/{ten-bit-addresses => ten-bit-addresses.rst} (95%) rename Documentation/i2c/{upgrading-clients => upgrading-clients.rst} (54%) rename Documentation/i2c/{writing-clients => writing-clients.rst} (91%) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt index 2907dab56298..8b444b94e92f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpmux.txt @@ -42,7 +42,7 @@ Optional properties: This means that no unrelated I2C transactions are allowed on the parent I2C adapter for the complete multiplexed I2C transaction. The properties of mux-locked and parent-locked multiplexers are discussed - in more detail in Documentation/i2c/i2c-topology. + in more detail in Documentation/i2c/i2c-topology.rst. For each i2c child node, an I2C child bus will be created. They will be numbered based on their order in the device tree. diff --git a/Documentation/driver-api/ipmb.rst b/Documentation/driver-api/ipmb.rst index 7e2265144157..3ec3baed84c4 100644 --- a/Documentation/driver-api/ipmb.rst +++ b/Documentation/driver-api/ipmb.rst @@ -83,7 +83,7 @@ Instantiate the device ---------------------- After loading the driver, you can instantiate the device as -described in 'Documentation/i2c/instantiating-devices'. +described in 'Documentation/i2c/instantiating-devices.rst'. If you have multiple BMCs, each connected to your Satellite MC via a different I2C bus, you can instantiate a device for each of those BMCs. diff --git a/Documentation/hwmon/adm1021.rst b/Documentation/hwmon/adm1021.rst index 6cbb0f75fe00..116fb2019956 100644 --- a/Documentation/hwmon/adm1021.rst +++ b/Documentation/hwmon/adm1021.rst @@ -142,7 +142,7 @@ loading the adm1021 module, then things are good. If nothing happens when loading the adm1021 module, and you are certain that your specific Xeon processor model includes compatible sensors, you will have to explicitly instantiate the sensor chips from user-space. See -method 4 in Documentation/i2c/instantiating-devices. Possible slave +method 4 in Documentation/i2c/instantiating-devices.rst. Possible slave addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that only temp2 will be correct and temp1 will have to be ignored. diff --git a/Documentation/hwmon/adm1275.rst b/Documentation/hwmon/adm1275.rst index 9a1913e5b4d9..49966ed70ec6 100644 --- a/Documentation/hwmon/adm1275.rst +++ b/Documentation/hwmon/adm1275.rst @@ -75,7 +75,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. The ADM1075, unlike many other PMBus devices, does not support internal voltage diff --git a/Documentation/hwmon/hih6130.rst b/Documentation/hwmon/hih6130.rst index 649bd4be4fc2..e95d373eb693 100644 --- a/Documentation/hwmon/hih6130.rst +++ b/Documentation/hwmon/hih6130.rst @@ -27,7 +27,7 @@ The devices communicate with the I2C protocol. All sensors are set to the same I2C address 0x27 by default, so an entry with I2C_BOARD_INFO("hih6130", 0x27) can be used in the board setup code. -Please see Documentation/i2c/instantiating-devices for details on how to +Please see Documentation/i2c/instantiating-devices.rst for details on how to instantiate I2C devices. sysfs-Interface diff --git a/Documentation/hwmon/ibm-cffps.rst b/Documentation/hwmon/ibm-cffps.rst index 52e74e39463a..ef8f3f806968 100644 --- a/Documentation/hwmon/ibm-cffps.rst +++ b/Documentation/hwmon/ibm-cffps.rst @@ -17,7 +17,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. Sysfs entries diff --git a/Documentation/hwmon/lm25066.rst b/Documentation/hwmon/lm25066.rst index da15e3094c8c..30e6e77fb3c8 100644 --- a/Documentation/hwmon/lm25066.rst +++ b/Documentation/hwmon/lm25066.rst @@ -76,7 +76,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/max16064.rst b/Documentation/hwmon/max16064.rst index 6d5e9538991f..c06249292557 100644 --- a/Documentation/hwmon/max16064.rst +++ b/Documentation/hwmon/max16064.rst @@ -28,7 +28,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/max16065.rst b/Documentation/hwmon/max16065.rst index fa5c852a178c..45f69f334f25 100644 --- a/Documentation/hwmon/max16065.rst +++ b/Documentation/hwmon/max16065.rst @@ -79,7 +79,7 @@ Usage Notes This driver does not probe for devices, since there is no register which can be safely used to identify the chip. You will have to instantiate -the devices explicitly. Please see Documentation/i2c/instantiating-devices for +the devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. WARNING: Do not access chip registers using the i2cdump command, and do not use diff --git a/Documentation/hwmon/max20751.rst b/Documentation/hwmon/max20751.rst index aa4469be6674..fe701e07eaf5 100644 --- a/Documentation/hwmon/max20751.rst +++ b/Documentation/hwmon/max20751.rst @@ -30,7 +30,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/max34440.rst b/Documentation/hwmon/max34440.rst index 939138e12b02..5744df100a5d 100644 --- a/Documentation/hwmon/max34440.rst +++ b/Documentation/hwmon/max34440.rst @@ -83,7 +83,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. For MAX34446, the value of the currX_crit attribute determines if current or diff --git a/Documentation/hwmon/max6650.rst b/Documentation/hwmon/max6650.rst index 253482add082..7952b6ecaa2d 100644 --- a/Documentation/hwmon/max6650.rst +++ b/Documentation/hwmon/max6650.rst @@ -55,7 +55,7 @@ Usage notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. Module parameters diff --git a/Documentation/hwmon/max8688.rst b/Documentation/hwmon/max8688.rst index 009487759c61..71e7f2cbe2e2 100644 --- a/Documentation/hwmon/max8688.rst +++ b/Documentation/hwmon/max8688.rst @@ -28,7 +28,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/menf21bmc.rst b/Documentation/hwmon/menf21bmc.rst index 1f0c6b2235ab..978691d5956d 100644 --- a/Documentation/hwmon/menf21bmc.rst +++ b/Documentation/hwmon/menf21bmc.rst @@ -28,7 +28,7 @@ Usage Notes This driver is part of the MFD driver named "menf21bmc" and does not auto-detect devices. You will have to instantiate the MFD driver explicitly. -Please see Documentation/i2c/instantiating-devices for +Please see Documentation/i2c/instantiating-devices.rst for details. Sysfs entries diff --git a/Documentation/hwmon/pcf8591.rst b/Documentation/hwmon/pcf8591.rst index e98bd542a441..5c4e85f53177 100644 --- a/Documentation/hwmon/pcf8591.rst +++ b/Documentation/hwmon/pcf8591.rst @@ -68,7 +68,7 @@ Accessing PCF8591 via /sys interface The PCF8591 is plainly impossible to detect! Thus the driver won't even try. You have to explicitly instantiate the device at the relevant address (in the interval [0x48..0x4f]) either through platform data, or -using the sysfs interface. See Documentation/i2c/instantiating-devices +using the sysfs interface. See Documentation/i2c/instantiating-devices.rst for details. Directories are being created for each instantiated PCF8591: diff --git a/Documentation/hwmon/sht3x.rst b/Documentation/hwmon/sht3x.rst index 978a7117e4b2..95a850d5b2c1 100644 --- a/Documentation/hwmon/sht3x.rst +++ b/Documentation/hwmon/sht3x.rst @@ -26,7 +26,7 @@ scaled by 1000, i.e. the value for 31.5 degrees celsius is 31500. The device communicates with the I2C protocol. Sensors can have the I2C addresses 0x44 or 0x45, depending on the wiring. See -Documentation/i2c/instantiating-devices for methods to instantiate the device. +Documentation/i2c/instantiating-devices.rst for methods to instantiate the device. There are two options configurable by means of sht3x_platform_data: diff --git a/Documentation/hwmon/shtc1.rst b/Documentation/hwmon/shtc1.rst index aa116332ba26..70c1192bbd8c 100644 --- a/Documentation/hwmon/shtc1.rst +++ b/Documentation/hwmon/shtc1.rst @@ -36,7 +36,7 @@ humidity is expressed as a percentage. Driver can be used as well for SHTW1 chip, which has the same electrical interface. The device communicates with the I2C protocol. All sensors are set to I2C -address 0x70. See Documentation/i2c/instantiating-devices for methods to +address 0x70. See Documentation/i2c/instantiating-devices.rst for methods to instantiate the device. There are two options configurable by means of shtc1_platform_data: diff --git a/Documentation/hwmon/tmp103.rst b/Documentation/hwmon/tmp103.rst index 15d25806d585..205de6148fcb 100644 --- a/Documentation/hwmon/tmp103.rst +++ b/Documentation/hwmon/tmp103.rst @@ -30,4 +30,4 @@ The driver provides the common sysfs-interface for temperatures (see Documentation/hwmon/sysfs-interface.rst under Temperatures). Please refer how to instantiate this driver: -Documentation/i2c/instantiating-devices +Documentation/i2c/instantiating-devices.rst diff --git a/Documentation/hwmon/tps40422.rst b/Documentation/hwmon/tps40422.rst index b691e30479dd..8fe3e1c3572e 100644 --- a/Documentation/hwmon/tps40422.rst +++ b/Documentation/hwmon/tps40422.rst @@ -28,7 +28,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/ucd9000.rst b/Documentation/hwmon/ucd9000.rst index ebc4f2b3bfea..746f21fcb48c 100644 --- a/Documentation/hwmon/ucd9000.rst +++ b/Documentation/hwmon/ucd9000.rst @@ -64,7 +64,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/ucd9200.rst b/Documentation/hwmon/ucd9200.rst index b819dfd75f71..4f0e7c3ca6f4 100644 --- a/Documentation/hwmon/ucd9200.rst +++ b/Documentation/hwmon/ucd9200.rst @@ -40,7 +40,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/via686a.rst b/Documentation/hwmon/via686a.rst index a343c35df740..7ab9ddebcf79 100644 --- a/Documentation/hwmon/via686a.rst +++ b/Documentation/hwmon/via686a.rst @@ -40,7 +40,7 @@ all as a 686A. The Via 686a southbridge has integrated hardware monitor functionality. It also has an I2C bus, but this driver only supports the hardware monitor. -For the I2C bus driver, see +For the I2C bus driver, see The Via 686a implements three temperature sensors, two fan rotation speed sensors, five voltage sensors and alarms. diff --git a/Documentation/hwmon/zl6100.rst b/Documentation/hwmon/zl6100.rst index 41513bb7fe51..968aff10ce0a 100644 --- a/Documentation/hwmon/zl6100.rst +++ b/Documentation/hwmon/zl6100.rst @@ -121,7 +121,7 @@ Usage Notes ----------- This driver does not auto-detect devices. You will have to instantiate the -devices explicitly. Please see Documentation/i2c/instantiating-devices for +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. .. warning:: diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535.rst similarity index 82% rename from Documentation/i2c/busses/i2c-ali1535 rename to Documentation/i2c/busses/i2c-ali1535.rst index 5d46342e486a..6941064730dc 100644 --- a/Documentation/i2c/busses/i2c-ali1535 +++ b/Documentation/i2c/busses/i2c-ali1535.rst @@ -1,16 +1,19 @@ +========================= Kernel driver i2c-ali1535 +========================= Supported adapters: * Acer Labs, Inc. ALI 1535 (south bridge) + Datasheet: Now under NDA http://www.ali.com.tw/ Authors: - Frodo Looijaard , - Philip Edelbrock , - Mark D. Studebaker , - Dan Eaton , - Stephen Rousset + - Frodo Looijaard , + - Philip Edelbrock , + - Mark D. Studebaker , + - Dan Eaton , + - Stephen Rousset Description ----------- diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563.rst similarity index 93% rename from Documentation/i2c/busses/i2c-ali1563 rename to Documentation/i2c/busses/i2c-ali1563.rst index 41b1a077e4c7..eec32c3ba92a 100644 --- a/Documentation/i2c/busses/i2c-ali1563 +++ b/Documentation/i2c/busses/i2c-ali1563.rst @@ -1,7 +1,10 @@ +========================= Kernel driver i2c-ali1563 +========================= Supported adapters: * Acer Labs, Inc. ALI 1563 (south bridge) + Datasheet: Now under NDA http://www.ali.com.tw/ diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3.rst similarity index 72% rename from Documentation/i2c/busses/i2c-ali15x3 rename to Documentation/i2c/busses/i2c-ali15x3.rst index 42888d8ac124..d4c1a2a419cb 100644 --- a/Documentation/i2c/busses/i2c-ali15x3 +++ b/Documentation/i2c/busses/i2c-ali15x3.rst @@ -1,20 +1,23 @@ +========================= Kernel driver i2c-ali15x3 +========================= Supported adapters: * Acer Labs, Inc. ALI 1533 and 1543C (south bridge) + Datasheet: Now under NDA http://www.ali.com.tw/ Authors: - Frodo Looijaard , - Philip Edelbrock , - Mark D. Studebaker + - Frodo Looijaard , + - Philip Edelbrock , + - Mark D. Studebaker Module Parameters ----------------- * force_addr: int - Initialize the base address of the i2c controller + Initialize the base address of the i2c controller Notes @@ -25,7 +28,9 @@ the BIOS. Does not do a PCI force; the device must still be present in lspci. Don't use this unless the driver complains that the base address is not set. -Example: 'modprobe i2c-ali15x3 force_addr=0xe800' +Example:: + + modprobe i2c-ali15x3 force_addr=0xe800 SMBus periodically hangs on ASUS P5A motherboards and can only be cleared by a power cycle. Cause unknown (see Issues below). @@ -38,47 +43,53 @@ This is the driver for the SMB Host controller on Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. The M1543C is a South bridge for desktop systems. + The M1541 is a South bridge for portable systems. + They are part of the following ALI chipsets: * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and - 100MHz CPU Front Side bus + 100MHz CPU Front Side bus * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz - CPU Front Side bus + CPU Front Side bus + Some Aladdin V motherboards: - Asus P5A - Atrend ATC-5220 - BCM/GVC VP1541 - Biostar M5ALA - Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't - enable the 7101 device! **) - Iwill XA100 Plus - Micronics C200 - Microstar (MSI) MS-5169 + - Asus P5A + - Atrend ATC-5220 + - BCM/GVC VP1541 + - Biostar M5ALA + - Gigabyte GA-5AX (Generally doesn't work because the BIOS doesn't + enable the 7101 device!) + - Iwill XA100 Plus + - Micronics C200 + - Microstar (MSI) MS-5169 * "Aladdin IV" includes the M1541 Socket 7 North bridge - with host bus up to 83.3 MHz. + with host bus up to 83.3 MHz. For an overview of these chips see http://www.acerlabs.com. At this time the full data sheets on the web site are password protected, however if you contact the ALI office in San Jose they may give you the password. The M1533/M1543C devices appear as FOUR separate devices on the PCI bus. An -output of lspci will show something similar to the following: +output of lspci will show something similar to the following:: 00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03) 00:03.0 Bridge: Acer Laboratories Inc. M7101 <= THIS IS THE ONE WE NEED 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3) 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1) -** IMPORTANT ** -** If you have a M1533 or M1543C on the board and you get -** "ali15x3: Error: Can't detect ali15x3!" -** then run lspci. -** If you see the 1533 and 5229 devices but NOT the 7101 device, -** then you must enable ACPI, the PMU, SMB, or something similar -** in the BIOS. -** The driver won't work if it can't find the M7101 device. +.. important:: + + If you have a M1533 or M1543C on the board and you get + "ali15x3: Error: Can't detect ali15x3!" + then run lspci. + + If you see the 1533 and 5229 devices but NOT the 7101 device, + then you must enable ACPI, the PMU, SMB, or something similar + in the BIOS. + + The driver won't work if it can't find the M7101 device. The SMB controller is part of the M7101 device, which is an ACPI-compliant Power Management Unit (PMU). @@ -109,4 +120,3 @@ There may be electrical problems on this board. On the P5A, the W83781D sensor chip is on both the ISA and SMBus. Therefore the SMBus hangs can generally be avoided by accessing the W83781D on the ISA bus only. - diff --git a/Documentation/i2c/busses/i2c-amd-mp2 b/Documentation/i2c/busses/i2c-amd-mp2 deleted file mode 100644 index 6571487171f4..000000000000 --- a/Documentation/i2c/busses/i2c-amd-mp2 +++ /dev/null @@ -1,23 +0,0 @@ -Kernel driver i2c-amd-mp2 - -Supported adapters: - * AMD MP2 PCIe interface - -Datasheet: not publicly available. - -Authors: - Shyam Sundar S K - Nehal Shah - Elie Morisse - -Description ------------ - -The MP2 is an ARM processor programmed as an I2C controller and communicating -with the x86 host through PCI. - -If you see something like this: - -03:00.7 MP2 I2C controller: Advanced Micro Devices, Inc. [AMD] Device 15e6 - -in your 'lspci -v', then this driver is for your device. diff --git a/Documentation/i2c/busses/i2c-amd-mp2.rst b/Documentation/i2c/busses/i2c-amd-mp2.rst new file mode 100644 index 000000000000..ebc2fa899325 --- /dev/null +++ b/Documentation/i2c/busses/i2c-amd-mp2.rst @@ -0,0 +1,25 @@ +========================= +Kernel driver i2c-amd-mp2 +========================= + +Supported adapters: + * AMD MP2 PCIe interface + +Datasheet: not publicly available. + +Authors: + - Shyam Sundar S K + - Nehal Shah + - Elie Morisse + +Description +----------- + +The MP2 is an ARM processor programmed as an I2C controller and communicating +with the x86 host through PCI. + +If you see something like this:: + + 03:00.7 MP2 I2C controller: Advanced Micro Devices, Inc. [AMD] Device 15e6 + +in your ``lspci -v``, then this driver is for your device. diff --git a/Documentation/i2c/busses/i2c-amd756 b/Documentation/i2c/busses/i2c-amd756.rst similarity index 79% rename from Documentation/i2c/busses/i2c-amd756 rename to Documentation/i2c/busses/i2c-amd756.rst index 67f30874d0bf..bc93f392a4fc 100644 --- a/Documentation/i2c/busses/i2c-amd756 +++ b/Documentation/i2c/busses/i2c-amd756.rst @@ -1,18 +1,22 @@ +======================== Kernel driver i2c-amd756 +======================== Supported adapters: * AMD 756 * AMD 766 * AMD 768 * AMD 8111 + Datasheets: Publicly available on AMD website * nVidia nForce + Datasheet: Unavailable Authors: - Frodo Looijaard , - Philip Edelbrock + - Frodo Looijaard , + - Philip Edelbrock Description ----------- diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111.rst similarity index 66% rename from Documentation/i2c/busses/i2c-amd8111 rename to Documentation/i2c/busses/i2c-amd8111.rst index 460dd6635fd2..d08bf0a7f0ac 100644 --- a/Documentation/i2c/busses/i2c-amd8111 +++ b/Documentation/i2c/busses/i2c-amd8111.rst @@ -1,4 +1,6 @@ +========================= Kernel driver i2c-adm8111 +========================= Supported adapters: * AMD-8111 SMBus 2.0 PCI interface @@ -13,14 +15,14 @@ Author: Vojtech Pavlik Description ----------- -If you see something like this: +If you see something like this:: -00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02) - Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 - Flags: medium devsel, IRQ 19 - I/O ports at d400 [size=32] + 00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02) + Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 + Flags: medium devsel, IRQ 19 + I/O ports at d400 [size=32] -in your 'lspci -v', then this driver is for your chipset. +in your ``lspci -v``, then this driver is for your chipset. Process Call Support -------------------- diff --git a/Documentation/i2c/busses/i2c-diolan-u2c b/Documentation/i2c/busses/i2c-diolan-u2c.rst similarity index 91% rename from Documentation/i2c/busses/i2c-diolan-u2c rename to Documentation/i2c/busses/i2c-diolan-u2c.rst index 0d6018c316c7..c18cbdcdf73c 100644 --- a/Documentation/i2c/busses/i2c-diolan-u2c +++ b/Documentation/i2c/busses/i2c-diolan-u2c.rst @@ -1,7 +1,10 @@ +============================ Kernel driver i2c-diolan-u2c +============================ Supported adapters: * Diolan U2C-12 I2C-USB adapter + Documentation: http://www.diolan.com/i2c/u2c12.html diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801.rst similarity index 89% rename from Documentation/i2c/busses/i2c-i801 rename to Documentation/i2c/busses/i2c-i801.rst index f426c13c63a9..2a570c214880 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801.rst @@ -1,4 +1,7 @@ +====================== Kernel driver i2c-i801 +====================== + Supported adapters: * Intel 82801AA and 82801AB (ICH and ICH0 - part of the @@ -39,28 +42,33 @@ Supported adapters: * Intel Comet Lake (PCH) * Intel Elkhart Lake (PCH) * Intel Tiger Lake (PCH) + Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller and the additional 'Integrated Device Function' controllers are supported. -Authors: - Mark Studebaker - Jean Delvare +Authors: + - Mark Studebaker + - Jean Delvare Module Parameters ----------------- * disable_features (bit vector) + Disable selected features normally supported by the device. This makes it possible to work around possible driver or hardware bugs if the feature in question doesn't work as intended for whatever reason. Bit values: + + ==== ========================================= 0x01 disable SMBus PEC 0x02 disable the block buffer 0x08 disable the I2C block read functionality 0x10 don't use interrupts 0x20 disable SMBus Host Notify + ==== ========================================= Description @@ -73,7 +81,7 @@ Pentium-based PCs, '815E' chipset, and others. The ICH chips contain at least SEVEN separate PCI functions in TWO logical PCI devices. An output of lspci will show something similar to the -following: +following:: 00:1e.0 PCI bridge: Intel Corporation: Unknown device 2418 (rev 01) 00:1f.0 ISA bridge: Intel Corporation: Unknown device 2410 (rev 01) @@ -139,14 +147,14 @@ and you think there's something interesting on the SMBus (e.g. a hardware monitoring chip), you need to add your board to the list. The motherboard is identified using the subvendor and subdevice IDs of the -host bridge PCI device. Get yours with "lspci -n -v -s 00:00.0": +host bridge PCI device. Get yours with ``lspci -n -v -s 00:00.0``:: -00:00.0 Class 0600: 8086:2570 (rev 02) - Subsystem: 1043:80f2 - Flags: bus master, fast devsel, latency 0 - Memory at fc000000 (32-bit, prefetchable) [size=32M] - Capabilities: [e4] #09 [2106] - Capabilities: [a0] AGP version 3.0 + 00:00.0 Class 0600: 8086:2570 (rev 02) + Subsystem: 1043:80f2 + Flags: bus master, fast devsel, latency 0 + Memory at fc000000 (32-bit, prefetchable) [size=32M] + Capabilities: [e4] #09 [2106] + Capabilities: [a0] AGP version 3.0 Here the host bridge ID is 2570 (82865G/PE/P), the subvendor ID is 1043 (Asus) and the subdevice ID is 80f2 (P4P800-X). You can find the symbolic @@ -165,7 +173,8 @@ kernel. It's very convenient if you just want to check if there's anything interesting on your hidden ICH SMBus. -********************** +---------------------------------------------------------------------------- + The lm_sensors project gratefully acknowledges the support of Texas Instruments in the initial development of this driver. diff --git a/Documentation/i2c/busses/i2c-ismt b/Documentation/i2c/busses/i2c-ismt.rst similarity index 81% rename from Documentation/i2c/busses/i2c-ismt rename to Documentation/i2c/busses/i2c-ismt.rst index 737355822c0b..8e74919a3fdf 100644 --- a/Documentation/i2c/busses/i2c-ismt +++ b/Documentation/i2c/busses/i2c-ismt.rst @@ -1,4 +1,7 @@ +====================== Kernel driver i2c-ismt +====================== + Supported adapters: * Intel S12xx series SOCs @@ -11,16 +14,21 @@ Module Parameters ----------------- * bus_speed (unsigned int) + Allows changing of the bus speed. Normally, the bus speed is set by the BIOS and never needs to be changed. However, some SMBus analyzers are too slow for monitoring the bus during debug, thus the need for this module parameter. Specify the bus speed in kHz. + Available bus frequency settings: - 0 no change - 80 kHz - 100 kHz - 400 kHz - 1000 kHz + + ==== ========= + 0 no change + 80 kHz + 100 kHz + 400 kHz + 1000 kHz + ==== ========= Description @@ -30,7 +38,7 @@ The S12xx series of SOCs have a pair of integrated SMBus 2.0 controllers targeted primarily at the microserver and storage markets. The S12xx series contain a pair of PCI functions. An output of lspci will show -something similar to the following: +something similar to the following:: 00:13.0 System peripheral: Intel Corporation Centerton SMBus 2.0 Controller 0 00:13.1 System peripheral: Intel Corporation Centerton SMBus 2.0 Controller 1 diff --git a/Documentation/i2c/busses/i2c-mlxcpld b/Documentation/i2c/busses/i2c-mlxcpld.rst similarity index 88% rename from Documentation/i2c/busses/i2c-mlxcpld rename to Documentation/i2c/busses/i2c-mlxcpld.rst index 925904aa9b57..9a0b2916aa71 100644 --- a/Documentation/i2c/busses/i2c-mlxcpld +++ b/Documentation/i2c/busses/i2c-mlxcpld.rst @@ -1,9 +1,12 @@ +================== Driver i2c-mlxcpld +================== Author: Michael Shych This is the Mellanox I2C controller logic, implemented in Lattice CPLD device. + Device supports: - Master mode. - One physical bus. @@ -20,6 +23,8 @@ The next transaction types are supported: - Write Byte/Block. Registers: + +=============== === ======================================================================= CPBLTY 0x0 - capability reg. Bits [6:5] - transaction length. b01 - 72B is supported, 36B in other case. @@ -49,3 +54,4 @@ DATAx 0xa - 0x54 - 68 bytes data buffer regs. For read transactions address is sent in a separate transaction and specified in the four first bytes (DATA0 - DATA3). Data is read starting from DATA0. +=============== === ======================================================================= diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2.rst similarity index 58% rename from Documentation/i2c/busses/i2c-nforce2 rename to Documentation/i2c/busses/i2c-nforce2.rst index 9698c396b830..83181445268f 100644 --- a/Documentation/i2c/busses/i2c-nforce2 +++ b/Documentation/i2c/busses/i2c-nforce2.rst @@ -1,10 +1,12 @@ +========================= Kernel driver i2c-nforce2 +========================= Supported adapters: - * nForce2 MCP 10de:0064 - * nForce2 Ultra 400 MCP 10de:0084 - * nForce3 Pro150 MCP 10de:00D4 - * nForce3 250Gb MCP 10de:00E4 + * nForce2 MCP 10de:0064 + * nForce2 Ultra 400 MCP 10de:0084 + * nForce3 Pro150 MCP 10de:00D4 + * nForce3 250Gb MCP 10de:00E4 * nForce4 MCP 10de:0052 * nForce4 MCP-04 10de:0034 * nForce MCP51 10de:0264 @@ -16,26 +18,27 @@ Supported adapters: * nForce MCP78S 10de:0752 * nForce MCP79 10de:0AA2 -Datasheet: not publicly available, but seems to be similar to the +Datasheet: + not publicly available, but seems to be similar to the AMD-8111 SMBus 2.0 adapter. Authors: - Hans-Frieder Vogt , - Thomas Leibold , - Patrick Dreker - + - Hans-Frieder Vogt , + - Thomas Leibold , + - Patrick Dreker + Description ----------- i2c-nforce2 is a driver for the SMBuses included in the nVidia nForce2 MCP. -If your 'lspci -v' listing shows something like the following, +If your ``lspci -v`` listing shows something like the following:: -00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2) - Subsystem: Asustek Computer, Inc.: Unknown device 0c11 - Flags: 66Mhz, fast devsel, IRQ 5 - I/O ports at c000 [size=32] - Capabilities: + 00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2) + Subsystem: Asustek Computer, Inc.: Unknown device 0c11 + Flags: 66Mhz, fast devsel, IRQ 5 + I/O ports at c000 [size=32] + Capabilities: then this driver should support the SMBuses of your motherboard. diff --git a/Documentation/i2c/busses/i2c-nvidia-gpu b/Documentation/i2c/busses/i2c-nvidia-gpu.rst similarity index 63% rename from Documentation/i2c/busses/i2c-nvidia-gpu rename to Documentation/i2c/busses/i2c-nvidia-gpu.rst index 31884d2b2eb5..38fb8a4c8756 100644 --- a/Documentation/i2c/busses/i2c-nvidia-gpu +++ b/Documentation/i2c/busses/i2c-nvidia-gpu.rst @@ -1,4 +1,6 @@ +============================ Kernel driver i2c-nvidia-gpu +============================ Datasheet: not publicly available. @@ -11,8 +13,8 @@ Description i2c-nvidia-gpu is a driver for I2C controller included in NVIDIA Turing and later GPUs and it is used to communicate with Type-C controller on GPUs. -If your 'lspci -v' listing shows something like the following, +If your ``lspci -v`` listing shows something like the following:: -01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1) + 01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1) then this driver should support the I2C controller of your GPU. diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores.rst similarity index 82% rename from Documentation/i2c/busses/i2c-ocores rename to Documentation/i2c/busses/i2c-ocores.rst index 9caaf7df1b2f..f5e175f2a2a6 100644 --- a/Documentation/i2c/busses/i2c-ocores +++ b/Documentation/i2c/busses/i2c-ocores.rst @@ -1,4 +1,6 @@ +======================== Kernel driver i2c-ocores +======================== Supported adapters: * OpenCores.org I2C controller by Richard Herveille (see datasheet link) @@ -23,9 +25,9 @@ distance between registers and the input clock speed. There is also a possibility to attach a list of i2c_board_info which the i2c-ocores driver will add to the bus upon creation. -E.G. something like: +E.G. something like:: -static struct resource ocores_resources[] = { + static struct resource ocores_resources[] = { [0] = { .start = MYI2C_BASEADDR, .end = MYI2C_BASEADDR + 8, @@ -36,10 +38,10 @@ static struct resource ocores_resources[] = { .end = MYI2C_IRQ, .flags = IORESOURCE_IRQ, }, -}; + }; -/* optional board info */ -struct i2c_board_info ocores_i2c_board_info[] = { + /* optional board info */ + struct i2c_board_info ocores_i2c_board_info[] = { { I2C_BOARD_INFO("tsc2003", 0x48), .platform_data = &tsc2003_platform_data, @@ -49,20 +51,20 @@ struct i2c_board_info ocores_i2c_board_info[] = { I2C_BOARD_INFO("adv7180", 0x42 >> 1), .irq = ADV_IRQ } -}; + }; -static struct ocores_i2c_platform_data myi2c_data = { + static struct ocores_i2c_platform_data myi2c_data = { .regstep = 2, /* two bytes between registers */ .clock_khz = 50000, /* input clock of 50MHz */ .devices = ocores_i2c_board_info, /* optional table of devices */ .num_devices = ARRAY_SIZE(ocores_i2c_board_info), /* table size */ -}; + }; -static struct platform_device myi2c = { + static struct platform_device myi2c = { .name = "ocores-i2c", .dev = { .platform_data = &myi2c_data, }, .num_resources = ARRAY_SIZE(ocores_resources), .resource = ocores_resources, -}; + }; diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport deleted file mode 100644 index c3dbb3bfd814..000000000000 --- a/Documentation/i2c/busses/i2c-parport +++ /dev/null @@ -1,178 +0,0 @@ -Kernel driver i2c-parport - -Author: Jean Delvare - -This is a unified driver for several i2c-over-parallel-port adapters, -such as the ones made by Philips, Velleman or ELV. This driver is -meant as a replacement for the older, individual drivers: - * i2c-philips-par - * i2c-elv - * i2c-velleman - * video/i2c-parport (NOT the same as this one, dedicated to home brew - teletext adapters) - -It currently supports the following devices: - * (type=0) Philips adapter - * (type=1) home brew teletext adapter - * (type=2) Velleman K8000 adapter - * (type=3) ELV adapter - * (type=4) Analog Devices ADM1032 evaluation board - * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031 - * (type=6) Barco LPT->DVI (K5800236) adapter - * (type=7) One For All JP1 parallel port adapter - * (type=8) VCT-jig - -These devices use different pinout configurations, so you have to tell -the driver what you have, using the type module parameter. There is no -way to autodetect the devices. Support for different pinout configurations -can be easily added when needed. - -Earlier kernels defaulted to type=0 (Philips). But now, if the type -parameter is missing, the driver will simply fail to initialize. - -SMBus alert support is available on adapters which have this line properly -connected to the parallel port's interrupt pin. - - -Building your own adapter -------------------------- - -If you want to build you own i2c-over-parallel-port adapter, here is -a sample electronics schema (credits go to Sylvain Munaut): - -Device PC -Side ___________________Vdd (+) Side - | | | - --- --- --- - | | | | | | - |R| |R| |R| - | | | | | | - --- --- --- - | | | - | | /| | -SCL ----------x--------o |-----------x------------------- pin 2 - | \| | | - | | | - | |\ | | -SDA ----------x----x---| o---x--------------------------- pin 13 - | |/ | - | | - | /| | - ---------o |----------------x-------------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - -Remarks: - - This is the exact pinout and electronics used on the Analog Devices - evaluation boards. - /| - - All inverters -o |- must be 74HC05, they must be open collector output. - \| - - All resitors are 10k. - - Pins 18-25 of the parallel port connected to GND. - - Pins 4-9 (D2-D7) could be used as VDD is the driver drives them high. - The ADM1032 evaluation board uses D4-D7. Beware that the amount of - current you can draw from the parallel port is limited. Also note that - all connected lines MUST BE driven at the same state, else you'll short - circuit the output buffers! So plugging the I2C adapter after loading - the i2c-parport module might be a good safety since data line state - prior to init may be unknown. - - This is 5V! - - Obviously you cannot read SCL (so it's not really standard-compliant). - Pretty easy to add, just copy the SDA part and use another input pin. - That would give (ELV compatible pinout): - - -Device PC -Side ______________________________Vdd (+) Side - | | | | - --- --- --- --- - | | | | | | | | - |R| |R| |R| |R| - | | | | | | | | - --- --- --- --- - | | | | - | | |\ | | -SCL ----------x--------x--| o---x------------------------ pin 15 - | | |/ | - | | | - | | /| | - | ---o |-------------x-------------- pin 2 - | \| | | - | | | - | | | - | |\ | | -SDA ---------------x---x--| o--------x------------------- pin 10 - | |/ | - | | - | /| | - ---o |------------------x--------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - - -If possible, you should use the same pinout configuration as existing -adapters do, so you won't even have to change the code. - - -Similar (but different) drivers -------------------------------- - -This driver is NOT the same as the i2c-pport driver found in the i2c -package. The i2c-pport driver makes use of modern parallel port features so -that you don't need additional electronics. It has other restrictions -however, and was not ported to Linux 2.6 (yet). - -This driver is also NOT the same as the i2c-pcf-epp driver found in the -lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port as -an I2C bus directly. Instead, it uses it to control an external I2C bus -master. That driver was not ported to Linux 2.6 (yet) either. - - -Legacy documentation for Velleman adapter ------------------------------------------ - -Useful links: -Velleman http://www.velleman.be/ -Velleman K8000 Howto http://howto.htlw16.ac.at/k8000-howto.html - -The project has lead to new libs for the Velleman K8000 and K8005: - LIBK8000 v1.99.1 and LIBK8005 v0.21 -With these libs, you can control the K8000 interface card and the K8005 -stepper motor card with the simple commands which are in the original -Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and -many more, using /dev/velleman. - http://home.wanadoo.nl/hihihi/libk8000.htm - http://home.wanadoo.nl/hihihi/libk8005.htm - http://struyve.mine.nu:8080/index.php?block=k8000 - http://sourceforge.net/projects/libk8005/ - - -One For All JP1 parallel port adapter -------------------------------------- - -The JP1 project revolves around a set of remote controls which expose -the I2C bus their internal configuration EEPROM lives on via a 6 pin -jumper in the battery compartment. More details can be found at: - -http://www.hifi-remote.com/jp1/ - -Details of the simple parallel port hardware can be found at: - -http://www.hifi-remote.com/jp1/hardware.shtml diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light.rst similarity index 91% rename from Documentation/i2c/busses/i2c-parport-light rename to Documentation/i2c/busses/i2c-parport-light.rst index 7071b8ba0af4..e73af975d2c8 100644 --- a/Documentation/i2c/busses/i2c-parport-light +++ b/Documentation/i2c/busses/i2c-parport-light.rst @@ -1,13 +1,15 @@ +=============================== Kernel driver i2c-parport-light +=============================== Author: Jean Delvare -This driver is a light version of i2c-parport. It doesn't depend +This driver is a light version of i2c-parport. It doesn't depend on the parport driver, and uses direct I/O access instead. This might be preferred on embedded systems where wasting memory for the clean but heavy parport handling is not an option. The drawback is a reduced portability -and the impossibility to daisy-chain other parallel port devices. - +and the impossibility to daisy-chain other parallel port devices. + Please see i2c-parport for documentation. Module parameters: diff --git a/Documentation/i2c/busses/i2c-parport.rst b/Documentation/i2c/busses/i2c-parport.rst new file mode 100644 index 000000000000..a9b4e8133700 --- /dev/null +++ b/Documentation/i2c/busses/i2c-parport.rst @@ -0,0 +1,190 @@ +========================= +Kernel driver i2c-parport +========================= + +Author: Jean Delvare + +This is a unified driver for several i2c-over-parallel-port adapters, +such as the ones made by Philips, Velleman or ELV. This driver is +meant as a replacement for the older, individual drivers: + + * i2c-philips-par + * i2c-elv + * i2c-velleman + * video/i2c-parport + (NOT the same as this one, dedicated to home brew teletext adapters) + +It currently supports the following devices: + + * (type=0) Philips adapter + * (type=1) home brew teletext adapter + * (type=2) Velleman K8000 adapter + * (type=3) ELV adapter + * (type=4) Analog Devices ADM1032 evaluation board + * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031 + * (type=6) Barco LPT->DVI (K5800236) adapter + * (type=7) One For All JP1 parallel port adapter + * (type=8) VCT-jig + +These devices use different pinout configurations, so you have to tell +the driver what you have, using the type module parameter. There is no +way to autodetect the devices. Support for different pinout configurations +can be easily added when needed. + +Earlier kernels defaulted to type=0 (Philips). But now, if the type +parameter is missing, the driver will simply fail to initialize. + +SMBus alert support is available on adapters which have this line properly +connected to the parallel port's interrupt pin. + + +Building your own adapter +------------------------- + +If you want to build you own i2c-over-parallel-port adapter, here is +a sample electronics schema (credits go to Sylvain Munaut):: + + Device PC + Side ___________________Vdd (+) Side + | | | + --- --- --- + | | | | | | + |R| |R| |R| + | | | | | | + --- --- --- + | | | + | | /| | + SCL ----------x--------o |-----------x------------------- pin 2 + | \| | | + | | | + | |\ | | + SDA ----------x----x---| o---x--------------------------- pin 13 + | |/ | + | | + | /| | + ---------o |----------------x-------------- pin 3 + \| | | + | | + --- --- + | | | | + |R| |R| + | | | | + --- --- + | | + ### ### + GND GND + +Remarks: + - This is the exact pinout and electronics used on the Analog Devices + evaluation boards. + - All inverters:: + + /| + -o |- + \| + + must be 74HC05, they must be open collector output. + - All resitors are 10k. + - Pins 18-25 of the parallel port connected to GND. + - Pins 4-9 (D2-D7) could be used as VDD is the driver drives them high. + The ADM1032 evaluation board uses D4-D7. Beware that the amount of + current you can draw from the parallel port is limited. Also note that + all connected lines MUST BE driven at the same state, else you'll short + circuit the output buffers! So plugging the I2C adapter after loading + the i2c-parport module might be a good safety since data line state + prior to init may be unknown. + - This is 5V! + - Obviously you cannot read SCL (so it's not really standard-compliant). + Pretty easy to add, just copy the SDA part and use another input pin. + That would give (ELV compatible pinout):: + + + Device PC + Side ______________________________Vdd (+) Side + | | | | + --- --- --- --- + | | | | | | | | + |R| |R| |R| |R| + | | | | | | | | + --- --- --- --- + | | | | + | | |\ | | + SCL ----------x--------x--| o---x------------------------ pin 15 + | | |/ | + | | | + | | /| | + | ---o |-------------x-------------- pin 2 + | \| | | + | | | + | | | + | |\ | | + SDA ---------------x---x--| o--------x------------------- pin 10 + | |/ | + | | + | /| | + ---o |------------------x--------- pin 3 + \| | | + | | + --- --- + | | | | + |R| |R| + | | | | + --- --- + | | + ### ### + GND GND + + +If possible, you should use the same pinout configuration as existing +adapters do, so you won't even have to change the code. + + +Similar (but different) drivers +------------------------------- + +This driver is NOT the same as the i2c-pport driver found in the i2c +package. The i2c-pport driver makes use of modern parallel port features so +that you don't need additional electronics. It has other restrictions +however, and was not ported to Linux 2.6 (yet). + +This driver is also NOT the same as the i2c-pcf-epp driver found in the +lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port as +an I2C bus directly. Instead, it uses it to control an external I2C bus +master. That driver was not ported to Linux 2.6 (yet) either. + + +Legacy documentation for Velleman adapter +----------------------------------------- + +Useful links: + +- Velleman http://www.velleman.be/ +- Velleman K8000 Howto http://howto.htlw16.ac.at/k8000-howto.html + +The project has lead to new libs for the Velleman K8000 and K8005: + + LIBK8000 v1.99.1 and LIBK8005 v0.21 + +With these libs, you can control the K8000 interface card and the K8005 +stepper motor card with the simple commands which are in the original +Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and +many more, using /dev/velleman. + + - http://home.wanadoo.nl/hihihi/libk8000.htm + - http://home.wanadoo.nl/hihihi/libk8005.htm + - http://struyve.mine.nu:8080/index.php?block=k8000 + - http://sourceforge.net/projects/libk8005/ + + +One For All JP1 parallel port adapter +------------------------------------- + +The JP1 project revolves around a set of remote controls which expose +the I2C bus their internal configuration EEPROM lives on via a 6 pin +jumper in the battery compartment. More details can be found at: + +http://www.hifi-remote.com/jp1/ + +Details of the simple parallel port hardware can be found at: + +http://www.hifi-remote.com/jp1/hardware.shtml diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa.rst similarity index 72% rename from Documentation/i2c/busses/i2c-pca-isa rename to Documentation/i2c/busses/i2c-pca-isa.rst index b044e5265488..a254010c8055 100644 --- a/Documentation/i2c/busses/i2c-pca-isa +++ b/Documentation/i2c/busses/i2c-pca-isa.rst @@ -1,6 +1,9 @@ +========================= Kernel driver i2c-pca-isa +========================= Supported adapters: + This driver supports ISA boards using the Philips PCA 9564 Parallel bus to I2C bus controller @@ -10,11 +13,11 @@ Module Parameters ----------------- * base int - I/O base address + I/O base address * irq int - IRQ interrupt + IRQ interrupt * clock int - Clock rate as described in table 1 of PCA9564 datasheet + Clock rate as described in table 1 of PCA9564 datasheet Description ----------- diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4.rst similarity index 92% rename from Documentation/i2c/busses/i2c-piix4 rename to Documentation/i2c/busses/i2c-piix4.rst index 2703bc3acad0..cc9000259223 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4.rst @@ -1,4 +1,6 @@ +======================= Kernel driver i2c-piix4 +======================= Supported adapters: * Intel 82371AB PIIX4 and PIIX4E @@ -20,9 +22,9 @@ Supported adapters: * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com -Authors: - Frodo Looijaard - Philip Edelbrock +Authors: + - Frodo Looijaard + - Philip Edelbrock Module Parameters @@ -39,16 +41,16 @@ Description The PIIX4 (properly known as the 82371AB) is an Intel chip with a lot of functionality. Among other things, it implements the PCI bus. One of its -minor functions is implementing a System Management Bus. This is a true +minor functions is implementing a System Management Bus. This is a true SMBus - you can not access it on I2C levels. The good news is that it natively understands SMBus commands and you do not have to worry about timing problems. The bad news is that non-SMBus devices connected to it can confuse it mightily. Yes, this is known to happen... -Do 'lspci -v' and see whether it contains an entry like this: +Do ``lspci -v`` and see whether it contains an entry like this:: -0000:00:02.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02) - Flags: medium devsel, IRQ 9 + 0000:00:02.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02) + Flags: medium devsel, IRQ 9 Bus and device numbers may differ, but the function number must be identical (like many PCI devices, the PIIX4 incorporates a number of @@ -91,7 +93,7 @@ the SMI mode. device is located at 00:0f.0. 2) Now you just need to change the value in 0xD2 register. Get it first with command: lspci -xxx -s 00:0f.0 - If the value is 0x3 then you need to change it to 0x1 + If the value is 0x3 then you need to change it to 0x1: setpci -s 00:0f.0 d2.b=1 Please note that you don't need to do that in all cases, just when the SMBus is diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595.rst similarity index 74% rename from Documentation/i2c/busses/i2c-sis5595 rename to Documentation/i2c/busses/i2c-sis5595.rst index ecd21fb49a8f..b85630c84a96 100644 --- a/Documentation/i2c/busses/i2c-sis5595 +++ b/Documentation/i2c/busses/i2c-sis5595.rst @@ -1,9 +1,11 @@ +========================= Kernel driver i2c-sis5595 +========================= Authors: - Frodo Looijaard , - Mark D. Studebaker , - Philip Edelbrock + - Frodo Looijaard , + - Mark D. Studebaker , + - Philip Edelbrock Supported adapters: * Silicon Integrated Systems Corp. SiS5595 Southbridge @@ -11,14 +13,19 @@ Supported adapters: Note: all have mfr. ID 0x1039. + ========= ====== SUPPORTED PCI ID + ========= ====== 5595 0008 + ========= ====== Note: these chips contain a 0008 device which is incompatible with the 5595. We recognize these by the presence of the listed "blacklist" PCI ID and refuse to load. + ============= ====== ================ NOT SUPPORTED PCI ID BLACKLIST PCI ID + ============= ====== ================ 540 0008 0540 550 0008 0550 5513 0008 5511 @@ -36,15 +43,18 @@ Note: all have mfr. ID 0x1039. 735 0008 0735 745 0008 0745 746 0008 0746 + ============= ====== ================ Module Parameters ----------------- -* force_addr=0xaddr Set the I/O base address. Useful for boards +================== ===================================================== +force_addr=0xaddr Set the I/O base address. Useful for boards that don't set the address in the BIOS. Does not do a PCI force; the device must still be present in lspci. Don't use this unless the driver complains that the base address is not set. +================== ===================================================== Description ----------- @@ -56,4 +66,3 @@ WARNING: If you are trying to access the integrated sensors on the SiS5595 chip, you want the sis5595 driver for those, not this driver. This driver is a BUS driver, not a CHIP driver. A BUS driver is used by other CHIP drivers to access chips on the bus. - diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630 deleted file mode 100644 index ee7943631074..000000000000 --- a/Documentation/i2c/busses/i2c-sis630 +++ /dev/null @@ -1,58 +0,0 @@ -Kernel driver i2c-sis630 - -Supported adapters: - * Silicon Integrated Systems Corp (SiS) - 630 chipset (Datasheet: available at http://www.sfr-fresh.com/linux) - 730 chipset - 964 chipset - * Possible other SiS chipsets ? - -Author: Alexander Malysh - Amaury Decrême - SiS964 support - -Module Parameters ------------------ - -* force = [1|0] Forcibly enable the SIS630. DANGEROUS! - This can be interesting for chipsets not named - above to check if it works for you chipset, but DANGEROUS! - -* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, - what your BIOS use). DANGEROUS! This should be a bit - faster, but freeze some systems (i.e. my Laptop). - SIS630/730 chip only. - - -Description ------------ - -This SMBus only driver is known to work on motherboards with the above -named chipsets. - -If you see something like this: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31) -00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 - -or like this: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02) -00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 - -or like this: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS] 760/M760 Host (rev 02) -00:02.0 ISA bridge: Silicon Integrated Systems [SiS] SiS964 [MuTIOL Media IO] - LPC Controller (rev 36) - -in your 'lspci' output , then this driver is for your chipset. - -Thank You ---------- -Philip Edelbrock -- testing SiS730 support -Mark M. Hoffman -- bug fixes - -To anyone else which I forgot here ;), thanks! - diff --git a/Documentation/i2c/busses/i2c-sis630.rst b/Documentation/i2c/busses/i2c-sis630.rst new file mode 100644 index 000000000000..9fcd74b18781 --- /dev/null +++ b/Documentation/i2c/busses/i2c-sis630.rst @@ -0,0 +1,63 @@ +======================== +Kernel driver i2c-sis630 +======================== + +Supported adapters: + * Silicon Integrated Systems Corp (SiS) + 630 chipset (Datasheet: available at http://www.sfr-fresh.com/linux) + 730 chipset + 964 chipset + * Possible other SiS chipsets ? + +Author: + - Alexander Malysh + - Amaury Decrême - SiS964 support + +Module Parameters +----------------- + +================== ===================================================== +force = [1|0] Forcibly enable the SIS630. DANGEROUS! + This can be interesting for chipsets not named + above to check if it works for you chipset, + but DANGEROUS! + +high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, + what your BIOS use). DANGEROUS! This should be a bit + faster, but freeze some systems (i.e. my Laptop). + SIS630/730 chip only. +================== ===================================================== + + +Description +----------- + +This SMBus only driver is known to work on motherboards with the above +named chipsets. + +If you see something like this:: + + 00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31) + 00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 + +or like this:: + + 00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02) + 00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 + +or like this:: + + 00:00.0 Host bridge: Silicon Integrated Systems [SiS] 760/M760 Host (rev 02) + 00:02.0 ISA bridge: Silicon Integrated Systems [SiS] SiS964 [MuTIOL Media IO] + LPC Controller (rev 36) + +in your ``lspci`` output , then this driver is for your chipset. + +Thank You +--------- +Philip Edelbrock +- testing SiS730 support +Mark M. Hoffman +- bug fixes + +To anyone else which I forgot here ;), thanks! diff --git a/Documentation/i2c/busses/i2c-sis96x b/Documentation/i2c/busses/i2c-sis96x.rst similarity index 74% rename from Documentation/i2c/busses/i2c-sis96x rename to Documentation/i2c/busses/i2c-sis96x.rst index 0b979f3252a4..437cc1d89588 100644 --- a/Documentation/i2c/busses/i2c-sis96x +++ b/Documentation/i2c/busses/i2c-sis96x.rst @@ -1,13 +1,18 @@ +======================== Kernel driver i2c-sis96x +======================== Replaces 2.4.x i2c-sis645 Supported adapters: + * Silicon Integrated Systems Corp (SiS) + Any combination of these host bridges: 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746 + and these south bridges: - 961, 962, 963(L) + 961, 962, 963(L) Author: Mark M. Hoffman @@ -21,17 +26,17 @@ those of the SiS630, although they are located in a completely different place. Thanks to Alexander Malysh for providing the SiS630 datasheet (and driver). -The command "lspci" as root should produce something like these lines: +The command ``lspci`` as root should produce something like these lines:: -00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 -00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 -00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 + 00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 + 00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 + 00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 -or perhaps this... +or perhaps this:: -00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 -00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961 -00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 + 00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 + 00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961 + 00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 (kernel versions later than 2.4.18 may fill in the "Unknown"s) @@ -50,7 +55,7 @@ TO DOs ------ * The driver does not support SMBus block reads/writes; I may add them if a -scenario is found where they're needed. + scenario is found where they're needed. Thank You @@ -58,16 +63,20 @@ Thank You Mark D. Studebaker - design hints and bug fixes + Alexander Maylsh - ditto, plus an important datasheet... almost the one I really wanted + Hans-Günter Lütke Uphues - patch for SiS735 + Robert Zwerus - testing for SiS645DX + Kianusch Sayah Karadji - patch for SiS645DX/962 + Ken Healy - patch for SiS655 To anyone else who has written w/ feedback, thanks! - diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm.rst similarity index 91% rename from Documentation/i2c/busses/i2c-taos-evm rename to Documentation/i2c/busses/i2c-taos-evm.rst index 60299555dcf0..f342e313ee3d 100644 --- a/Documentation/i2c/busses/i2c-taos-evm +++ b/Documentation/i2c/busses/i2c-taos-evm.rst @@ -1,4 +1,6 @@ +========================== Kernel driver i2c-taos-evm +========================== Author: Jean Delvare @@ -23,10 +25,10 @@ Using this driver In order to use this driver, you'll need the serport driver, and the inputattach tool, which is part of the input-utils package. The following commands will tell the kernel that you have a TAOS EVM on the first -serial port: +serial port:: -# modprobe serport -# inputattach --taos-evm /dev/ttyS0 + # modprobe serport + # inputattach --taos-evm /dev/ttyS0 Technical details diff --git a/Documentation/i2c/busses/i2c-via b/Documentation/i2c/busses/i2c-via.rst similarity index 54% rename from Documentation/i2c/busses/i2c-via rename to Documentation/i2c/busses/i2c-via.rst index 343870661ac3..846aa17d80a2 100644 --- a/Documentation/i2c/busses/i2c-via +++ b/Documentation/i2c/busses/i2c-via.rst @@ -1,4 +1,6 @@ +===================== Kernel driver i2c-via +===================== Supported adapters: * VIA Technologies, InC. VT82C586B @@ -12,23 +14,27 @@ Description i2c-via is an i2c bus driver for motherboards with VIA chipset. The following VIA pci chipsets are supported: - - MVP3, VP3, VP2/97, VPX/97 + - MVP3, VP3, VP2/97, VPX/97 - others with South bridge VT82C586B -Your lspci listing must show this : +Your ``lspci`` listing must show this :: Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10) - Problems? - - Q: You have VT82C586B on the motherboard, but not in the listing. - - A: Go to your BIOS setup, section PCI devices or similar. - Turn USB support on, and try again. +Problems? +--------- - Q: No error messages, but still i2c doesn't seem to work. + Q: + You have VT82C586B on the motherboard, but not in the listing. - A: This can happen. This driver uses the pins VIA recommends in their + A: + Go to your BIOS setup, section PCI devices or similar. + Turn USB support on, and try again. + + Q: + No error messages, but still i2c doesn't seem to work. + + A: + This can happen. This driver uses the pins VIA recommends in their datasheets, but there are several ways the motherboard manufacturer can actually wire the lines. - diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro.rst similarity index 87% rename from Documentation/i2c/busses/i2c-viapro rename to Documentation/i2c/busses/i2c-viapro.rst index ab64ce21c254..1762f0cf93d0 100644 --- a/Documentation/i2c/busses/i2c-viapro +++ b/Documentation/i2c/busses/i2c-viapro.rst @@ -1,4 +1,6 @@ +======================== Kernel driver i2c-viapro +======================== Supported adapters: * VIA Technologies, Inc. VT82C596A/B @@ -26,9 +28,9 @@ Supported adapters: Datasheet: available on http://linux.via.com.tw Authors: - Kyösti Mälkki , - Mark D. Studebaker , - Jean Delvare + - Kyösti Mälkki , + - Mark D. Studebaker , + - Jean Delvare Module Parameters ----------------- @@ -44,8 +46,9 @@ Description i2c-viapro is a true SMBus host driver for motherboards with one of the supported VIA south bridges. -Your lspci -n listing must show one of these : +Your ``lspci -n`` listing must show one of these : + ================ ====================== device 1106:3050 (VT82C596A function 3) device 1106:3051 (VT82C596B function 3) device 1106:3057 (VT82C686 function 4) @@ -61,6 +64,7 @@ Your lspci -n listing must show one of these : device 1106:8353 (VX800/VX820) device 1106:8409 (VX855/VX875) device 1106:8410 (VX900) + ================ ====================== If none of these show up, you should look in the BIOS for settings like enable ACPI / SMBus or even USB. diff --git a/Documentation/i2c/busses/index.rst b/Documentation/i2c/busses/index.rst new file mode 100644 index 000000000000..97ca4d510816 --- /dev/null +++ b/Documentation/i2c/busses/index.rst @@ -0,0 +1,33 @@ +. SPDX-License-Identifier: GPL-2.0 + +=============== +I2C Bus Drivers +=============== + +.. toctree:: + :maxdepth: 1 + + i2c-ali1535 + i2c-ali1563 + i2c-ali15x3 + i2c-amd756 + i2c-amd8111 + i2c-amd-mp2 + i2c-diolan-u2c + i2c-i801 + i2c-ismt + i2c-mlxcpld + i2c-nforce2 + i2c-nvidia-gpu + i2c-ocores + i2c-parport-light + i2c-parport + i2c-pca-isa + i2c-piix4 + i2c-sis5595 + i2c-sis630 + i2c-sis96x + i2c-taos-evm + i2c-viapro + i2c-via + scx200_acb diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb.rst similarity index 86% rename from Documentation/i2c/busses/scx200_acb rename to Documentation/i2c/busses/scx200_acb.rst index ce83c871fe95..8dc7c352508c 100644 --- a/Documentation/i2c/busses/scx200_acb +++ b/Documentation/i2c/busses/scx200_acb.rst @@ -1,4 +1,6 @@ +======================== Kernel driver scx200_acb +======================== Author: Christer Weinigel @@ -25,8 +27,11 @@ Device-specific notes The SC1100 WRAP boards are known to use base addresses 0x810 and 0x820. If the scx200_acb driver is built into the kernel, add the following -parameter to your boot command line: +parameter to your boot command line:: + scx200_acb.base=0x810,0x820 + If the scx200_acb driver is built as a module, add the following line to -a configuration file in /etc/modprobe.d/ instead: +a configuration file in /etc/modprobe.d/ instead:: + options scx200_acb base=0x810,0x820 diff --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface.rst similarity index 71% rename from Documentation/i2c/dev-interface rename to Documentation/i2c/dev-interface.rst index fbed645ccd75..69c23a3c2b1b 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface.rst @@ -1,3 +1,7 @@ +==================== +I2C Device Interface +==================== + Usually, i2c devices are controlled by a kernel driver. But it is also possible to access all devices on an adapter from userspace, through the /dev interface. You need to load module i2c-dev for this. @@ -18,7 +22,7 @@ C example ========= So let's say you want to access an i2c adapter from a C program. -First, you need to include these two headers: +First, you need to include these two headers:: #include #include @@ -28,7 +32,7 @@ inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this. Adapter numbers are assigned somewhat dynamically, so you can not assume much about them. They can even change from one boot to the next. -Next thing, open the device file, as follows: +Next thing, open the device file, as follows:: int file; int adapter_nr = 2; /* probably dynamically determined */ @@ -42,7 +46,7 @@ Next thing, open the device file, as follows: } When you have opened the device, you must specify with what device -address you want to communicate: +address you want to communicate:: int addr = 0x40; /* The I2C address */ @@ -53,7 +57,7 @@ address you want to communicate: Well, you are all set up now. You can now use SMBus commands or plain I2C to communicate with your device. SMBus commands are preferred if -the device supports them. Both are illustrated below. +the device supports them. Both are illustrated below:: __u8 reg = 0x10; /* Device register to access */ __s32 res; @@ -100,35 +104,35 @@ Full interface description The following IOCTLs are defined: -ioctl(file, I2C_SLAVE, long addr) +``ioctl(file, I2C_SLAVE, long addr)`` Change slave address. The address is passed in the 7 lower bits of the argument (except for 10 bit addresses, passed in the 10 lower bits in this case). -ioctl(file, I2C_TENBIT, long select) +``ioctl(file, I2C_TENBIT, long select)`` Selects ten bit addresses if select not equals 0, selects normal 7 bit addresses if select equals 0. Default 0. This request is only valid if the adapter has I2C_FUNC_10BIT_ADDR. -ioctl(file, I2C_PEC, long select) +``ioctl(file, I2C_PEC, long select)`` Selects SMBus PEC (packet error checking) generation and verification if select not equals 0, disables if select equals 0. Default 0. Used only for SMBus transactions. This request only has an effect if the the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just doesn't have any effect. -ioctl(file, I2C_FUNCS, unsigned long *funcs) - Gets the adapter functionality and puts it in *funcs. +``ioctl(file, I2C_FUNCS, unsigned long *funcs)`` + Gets the adapter functionality and puts it in ``*funcs``. -ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset) +``ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)`` Do combined read/write transaction without stop in between. Only valid if the adapter has I2C_FUNC_I2C. The argument is - a pointer to a + a pointer to a:: - struct i2c_rdwr_ioctl_data { + struct i2c_rdwr_ioctl_data { struct i2c_msg *msgs; /* ptr to array of simple messages */ int nmsgs; /* number of messages to exchange */ - } + } The msgs[] themselves contain further pointers into data buffers. The function will write or read data to or from that buffers depending @@ -136,8 +140,8 @@ ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset) The slave address and whether to use ten bit address mode has to be set in each message, overriding the values set with the above ioctl's. -ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args) - If possible, use the provided i2c_smbus_* methods described below instead +``ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)`` + If possible, use the provided ``i2c_smbus_*`` methods described below instead of issuing direct ioctls. You can do plain i2c transactions by using read(2) and write(2) calls. @@ -145,7 +149,8 @@ You do not need to pass the address byte; instead, set it through ioctl I2C_SLAVE before you try to access the device. You can do SMBus level transactions (see documentation file smbus-protocol -for details) through the following functions: +for details) through the following functions:: + __s32 i2c_smbus_write_quick(int file, __u8 value); __s32 i2c_smbus_read_byte(int file); __s32 i2c_smbus_write_byte(int file, __u8 value); @@ -157,6 +162,7 @@ for details) through the following functions: __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values); + All these transactions return -1 on failure; you can read errno to see what happened. The 'write' transactions return 0 on success; the 'read' transactions return the read value, except for read_block, which @@ -174,39 +180,39 @@ Implementation details For the interested, here's the code flow which happens inside the kernel when you use the /dev interface to I2C: -1* Your program opens /dev/i2c-N and calls ioctl() on it, as described in -section "C example" above. - -2* These open() and ioctl() calls are handled by the i2c-dev kernel -driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(), -respectively. You can think of i2c-dev as a generic I2C chip driver -that can be programmed from user-space. - -3* Some ioctl() calls are for administrative tasks and are handled by -i2c-dev directly. Examples include I2C_SLAVE (set the address of the -device you want to access) and I2C_PEC (enable or disable SMBus error -checking on future transactions.) - -4* Other ioctl() calls are converted to in-kernel function calls by -i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter -functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which -performs an SMBus transaction using i2c-core-smbus.c:i2c_smbus_xfer(). - -The i2c-dev driver is responsible for checking all the parameters that -come from user-space for validity. After this point, there is no -difference between these calls that came from user-space through i2c-dev -and calls that would have been performed by kernel I2C chip drivers -directly. This means that I2C bus drivers don't need to implement -anything special to support access from user-space. - -5* These i2c.h functions are wrappers to the actual implementation of -your I2C bus driver. Each adapter must declare callback functions -implementing these standard calls. i2c.h:i2c_get_functionality() calls -i2c_adapter.algo->functionality(), while -i2c-core-smbus.c:i2c_smbus_xfer() calls either -adapter.algo->smbus_xfer() if it is implemented, or if not, -i2c-core-smbus.c:i2c_smbus_xfer_emulated() which in turn calls -i2c_adapter.algo->master_xfer(). +1) Your program opens /dev/i2c-N and calls ioctl() on it, as described in + section "C example" above. + +2) These open() and ioctl() calls are handled by the i2c-dev kernel + driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(), + respectively. You can think of i2c-dev as a generic I2C chip driver + that can be programmed from user-space. + +3) Some ioctl() calls are for administrative tasks and are handled by + i2c-dev directly. Examples include I2C_SLAVE (set the address of the + device you want to access) and I2C_PEC (enable or disable SMBus error + checking on future transactions.) + +4) Other ioctl() calls are converted to in-kernel function calls by + i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter + functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which + performs an SMBus transaction using i2c-core-smbus.c:i2c_smbus_xfer(). + + The i2c-dev driver is responsible for checking all the parameters that + come from user-space for validity. After this point, there is no + difference between these calls that came from user-space through i2c-dev + and calls that would have been performed by kernel I2C chip drivers + directly. This means that I2C bus drivers don't need to implement + anything special to support access from user-space. + +5) These i2c.h functions are wrappers to the actual implementation of + your I2C bus driver. Each adapter must declare callback functions + implementing these standard calls. i2c.h:i2c_get_functionality() calls + i2c_adapter.algo->functionality(), while + i2c-core-smbus.c:i2c_smbus_xfer() calls either + adapter.algo->smbus_xfer() if it is implemented, or if not, + i2c-core-smbus.c:i2c_smbus_xfer_emulated() which in turn calls + i2c_adapter.algo->master_xfer(). After your I2C bus driver has processed these requests, execution runs up the call chain, with almost no processing done, except by i2c-dev to diff --git a/Documentation/i2c/DMA-considerations b/Documentation/i2c/dma-considerations.rst similarity index 100% rename from Documentation/i2c/DMA-considerations rename to Documentation/i2c/dma-considerations.rst diff --git a/Documentation/i2c/fault-codes b/Documentation/i2c/fault-codes.rst similarity index 98% rename from Documentation/i2c/fault-codes rename to Documentation/i2c/fault-codes.rst index 0cee0fc545b4..80b14e718b52 100644 --- a/Documentation/i2c/fault-codes +++ b/Documentation/i2c/fault-codes.rst @@ -1,3 +1,7 @@ +===================== +I2C/SMBUS Fault Codes +===================== + This is a summary of the most important conventions for use of fault codes in the I2C/SMBus stack. @@ -125,4 +129,3 @@ ETIMEDOUT when a slave stretches clocks too far. I2C has no such timeouts, but it's normal for I2C adapters to impose some arbitrary limits (much longer than SMBus!) too. - diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality.rst similarity index 91% rename from Documentation/i2c/functionality rename to Documentation/i2c/functionality.rst index 4aae8ed15873..377507c56162 100644 --- a/Documentation/i2c/functionality +++ b/Documentation/i2c/functionality.rst @@ -1,11 +1,15 @@ +======================= +I2C/SMBus Functionality +======================= + INTRODUCTION ------------ -Because not every I2C or SMBus adapter implements everything in the +Because not every I2C or SMBus adapter implements everything in the I2C specifications, a client can not trust that everything it needs is implemented when it is given the option to attach to an adapter: the client needs some way to check whether an adapter has the needed -functionality. +functionality. FUNCTIONALITY CONSTANTS @@ -14,6 +18,7 @@ FUNCTIONALITY CONSTANTS For the most up-to-date list of functionality constants, please check ! + =============================== ============================================== I2C_FUNC_I2C Plain i2c-level commands (Pure SMBus adapters typically can not do these) I2C_FUNC_10BIT_ADDR Handles the 10-bit address extensions @@ -33,9 +38,11 @@ For the most up-to-date list of functionality constants, please check I2C_FUNC_SMBUS_WRITE_BLOCK_DATA Handles the SMBus write_block_data command I2C_FUNC_SMBUS_READ_I2C_BLOCK Handles the SMBus read_i2c_block_data command I2C_FUNC_SMBUS_WRITE_I2C_BLOCK Handles the SMBus write_i2c_block_data command + =============================== ============================================== A few combinations of the above flags are also defined for your convenience: + ========================= ====================================== I2C_FUNC_SMBUS_BYTE Handles the SMBus read_byte and write_byte commands I2C_FUNC_SMBUS_BYTE_DATA Handles the SMBus read_byte_data @@ -49,6 +56,7 @@ A few combinations of the above flags are also defined for your convenience: I2C_FUNC_SMBUS_EMUL Handles all SMBus commands that can be emulated by a real I2C adapter (using the transparent emulation layer) + ========================= ====================================== In kernel versions prior to 3.5 I2C_FUNC_NOSTART was implemented as part of I2C_FUNC_PROTOCOL_MANGLING. @@ -58,11 +66,11 @@ ADAPTER IMPLEMENTATION ---------------------- When you write a new adapter driver, you will have to implement a -function callback `functionality'. Typical implementations are given +function callback ``functionality``. Typical implementations are given below. A typical SMBus-only adapter would list all the SMBus transactions it -supports. This example comes from the i2c-piix4 driver: +supports. This example comes from the i2c-piix4 driver:: static u32 piix4_func(struct i2c_adapter *adapter) { @@ -72,7 +80,7 @@ supports. This example comes from the i2c-piix4 driver: } A typical full-I2C adapter would use the following (from the i2c-pxa -driver): +driver):: static u32 i2c_pxa_functionality(struct i2c_adapter *adap) { @@ -94,7 +102,7 @@ CLIENT CHECKING Before a client tries to attach to an adapter, or even do tests to check whether one of the devices it supports is present on an adapter, it should check whether the needed functionality is present. The typical way to do -this is (from the lm75 driver): +this is (from the lm75 driver):: static int lm75_detect(...) { @@ -129,7 +137,7 @@ If you try to access an adapter from a userspace program, you will have to use the /dev interface. You will still have to check whether the functionality you need is supported, of course. This is done using the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is -below: +below:: int file; if (file = open("/dev/i2c-0", O_RDWR) < 0) { diff --git a/Documentation/i2c/gpio-fault-injection b/Documentation/i2c/gpio-fault-injection.rst similarity index 97% rename from Documentation/i2c/gpio-fault-injection rename to Documentation/i2c/gpio-fault-injection.rst index c87f416d53dd..9dca6ec7d266 100644 --- a/Documentation/i2c/gpio-fault-injection +++ b/Documentation/i2c/gpio-fault-injection.rst @@ -104,10 +104,10 @@ There doesn't need to be a device at this address because arbitration lost should be detected beforehand. Also note, that SCL going down is monitored using interrupts, so the interrupt latency might cause the first bits to be not corrupted. A good starting point for using this fault injector on an otherwise -idle bus is: +idle bus is:: -# echo 200 > lose_arbitration & -# i2cget -y 0x3f + # echo 200 > lose_arbitration & + # i2cget -y 0x3f Panic during transfer ===================== @@ -127,10 +127,10 @@ The calling process will then sleep and wait for the next bus clock. The process is interruptible, though. Start of a transfer is detected by waiting for SCL going down by the master -under test. A good starting point for using this fault injector is: +under test. A good starting point for using this fault injector is:: -# echo 0 > inject_panic & -# i2cget -y + # echo 0 > inject_panic & + # i2cget -y Note that there doesn't need to be a device listening to the address you are using. Results may vary depending on that, though. diff --git a/Documentation/i2c/i2c-protocol b/Documentation/i2c/i2c-protocol.rst similarity index 83% rename from Documentation/i2c/i2c-protocol rename to Documentation/i2c/i2c-protocol.rst index ff6d6cee6c7e..2f8fcf671b2e 100644 --- a/Documentation/i2c/i2c-protocol +++ b/Documentation/i2c/i2c-protocol.rst @@ -1,8 +1,13 @@ +============ +I2C Protocol +============ + This document describes the i2c protocol. Or will, when it is finished :-) Key to symbols ============== +=============== ============================================================= S (1 bit) : Start bit P (1 bit) : Stop bit Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. @@ -15,33 +20,35 @@ Data (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh for 16 bit data. Count (8 bits): A data byte containing the length of a block operation. -[..]: Data sent by I2C device, as opposed to data sent by the host adapter. +[..]: Data sent by I2C device, as opposed to data sent by the + host adapter. +=============== ============================================================= Simple send transaction -====================== +======================= -This corresponds to i2c_master_send. +This corresponds to i2c_master_send:: S Addr Wr [A] Data [A] Data [A] ... [A] Data [A] P Simple receive transaction -=========================== +========================== -This corresponds to i2c_master_recv +This corresponds to i2c_master_recv:: S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P Combined transactions -==================== +===================== This corresponds to i2c_transfer They are just like the above transactions, but instead of a stop bit P a start bit S is sent and the transaction continues. An example of -a byte read, followed by a byte write: +a byte read, followed by a byte write:: S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P @@ -65,8 +72,10 @@ I2C_M_NO_RD_ACK: I2C_M_NOSTART: In a combined transaction, no 'S Addr Wr/Rd [A]' is generated at some point. For example, setting I2C_M_NOSTART on the second partial message - generates something like: + generates something like:: + S Addr Rd [A] [Data] NA Data [A] P + If you set the I2C_M_NOSTART variable for the first partial message, we do not generate Addr, but we do generate the startbit S. This will probably confuse all other clients on your bus, so don't try this. @@ -79,7 +88,8 @@ I2C_M_NOSTART: I2C_M_REV_DIR_ADDR: This toggles the Rd/Wr flag. That is, if you want to do a write, but need to emit an Rd instead of a Wr, or vice versa, you set this - flag. For example: + flag. For example:: + S Addr Rd [A] Data [A] Data [A] ... [A] Data [A] P I2C_M_STOP: diff --git a/Documentation/i2c/i2c-stub b/Documentation/i2c/i2c-stub.rst similarity index 93% rename from Documentation/i2c/i2c-stub rename to Documentation/i2c/i2c-stub.rst index a16924fbd289..a6fc6916d6bc 100644 --- a/Documentation/i2c/i2c-stub +++ b/Documentation/i2c/i2c-stub.rst @@ -1,6 +1,9 @@ -MODULE: i2c-stub +======== +i2c-stub +======== -DESCRIPTION: +Description +=========== This module is a very simple fake I2C/SMBus driver. It implements six types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, (r/w) @@ -28,6 +31,7 @@ SMBus block operations. Writes can be partial. Block read commands always return the number of bytes selected with the largest write so far. The typical use-case is like this: + 1. load this module 2. use i2cset (from the i2c-tools project) to pre-load some data 3. load the target chip driver module @@ -36,7 +40,8 @@ The typical use-case is like this: There's a script named i2c-stub-from-dump in the i2c-tools package which can load register values automatically from a chip dump. -PARAMETERS: +Parameters +========== int chip_addr[10]: The SMBus addresses to emulate chips at. @@ -47,18 +52,15 @@ unsigned long functionality: value 0x1f0000 would only enable the quick, byte and byte data commands. -u8 bank_reg[10] -u8 bank_mask[10] -u8 bank_start[10] -u8 bank_end[10]: +u8 bank_reg[10], u8 bank_mask[10], u8 bank_start[10], u8 bank_end[10]: Optional bank settings. They tell which bits in which register select the active bank, as well as the range of banked registers. -CAVEATS: +Caveats +======= If your target driver polls some byte or word waiting for it to change, the stub could lock it up. Use i2cset to unlock it. If you spam it hard enough, printk can be lossy. This module really wants something like relayfs. - diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology.rst similarity index 89% rename from Documentation/i2c/i2c-topology rename to Documentation/i2c/i2c-topology.rst index f74d78b53d4d..0c1ae95f6a97 100644 --- a/Documentation/i2c/i2c-topology +++ b/Documentation/i2c/i2c-topology.rst @@ -1,3 +1,4 @@ +============ I2C topology ============ @@ -14,6 +15,7 @@ than a straight-forward i2c bus with one adapter and one or more devices. that has to be operated before the device can be accessed. Etc +=== These constructs are represented as i2c adapter trees by Linux, where each adapter has a parent adapter (except the root adapter) and zero or @@ -37,7 +39,9 @@ mux-locked or parent-locked muxes. As is evident from below, it can be useful to know if a mux is mux-locked or if it is parent-locked. The following list was correct at the time of writing: -In drivers/i2c/muxes/ +In drivers/i2c/muxes/: + +====================== ============================================= i2c-arb-gpio-challenge Parent-locked i2c-mux-gpio Normally parent-locked, mux-locked iff all involved gpio pins are controlled by the @@ -52,18 +56,25 @@ i2c-mux-pinctrl Normally parent-locked, mux-locked iff all involved pinctrl devices are controlled by the same i2c root adapter that they mux. i2c-mux-reg Parent-locked +====================== ============================================= + +In drivers/iio/: -In drivers/iio/ +====================== ============================================= gyro/mpu3050 Mux-locked imu/inv_mpu6050/ Mux-locked +====================== ============================================= -In drivers/media/ +In drivers/media/: + +======================= ============================================= dvb-frontends/lgdt3306a Mux-locked dvb-frontends/m88ds3103 Parent-locked dvb-frontends/rtl2830 Parent-locked dvb-frontends/rtl2832 Mux-locked dvb-frontends/si2168 Mux-locked usb/cx231xx/ Parent-locked +======================= ============================================= Mux-locked muxes @@ -78,6 +89,7 @@ full transaction, unrelated i2c transfers may interleave the different stages of the transaction. This has the benefit that the mux driver may be easier and cleaner to implement, but it has some caveats. +==== ===================================================================== ML1. If you build a topology with a mux-locked mux being the parent of a parent-locked mux, this might break the expectation from the parent-locked mux that the root adapter is locked during the @@ -105,11 +117,15 @@ ML4. If any non-i2c operation in the mux driver changes the i2c mux state, Otherwise garbage may appear on the bus as seen from devices behind the mux, when an unrelated i2c transfer is in flight during the non-i2c mux-changing operation. +==== ===================================================================== Mux-locked Example ------------------ + +:: + .----------. .--------. .--------. | mux- |-----| dev D1 | | root |--+--| locked | '--------' @@ -148,6 +164,7 @@ adapter during the transaction are unlocked i2c transfers (using e.g. __i2c_transfer), or a deadlock will follow. There are a couple of caveats. +==== ==================================================================== PL1. If you build a topology with a parent-locked mux being the child of another mux, this might break a possible assumption from the child mux that the root adapter is unused between its select op @@ -161,11 +178,14 @@ PL2. If select/deselect calls out to other subsystems such as gpio, caused by these subsystems are unlocked. This can be convoluted to accomplish, maybe even impossible if an acceptably clean solution is sought. +==== ==================================================================== Parent-locked Example --------------------- +:: + .----------. .--------. .--------. | parent- |-----| dev D1 | | root |--+--| locked | '--------' @@ -177,20 +197,20 @@ Parent-locked Example When there is an access to D1, this happens: - 1. Someone issues an i2c-transfer to D1. - 2. M1 locks muxes on its parent (the root adapter in this case). - 3. M1 locks its parent adapter. - 4. M1 calls ->select to ready the mux. - 5. If M1 does any i2c-transfers (on this root adapter) as part of - its select, those transfers must be unlocked i2c-transfers so - that they do not deadlock the root adapter. - 6. M1 feeds the i2c-transfer from step 1 to the root adapter as an - unlocked i2c-transfer, so that it does not deadlock the parent - adapter. - 7. M1 calls ->deselect, if it has one. - 8. Same rules as in step 5, but for ->deselect. - 9. M1 unlocks its parent adapter. -10. M1 unlocks muxes on its parent. + 1. Someone issues an i2c-transfer to D1. + 2. M1 locks muxes on its parent (the root adapter in this case). + 3. M1 locks its parent adapter. + 4. M1 calls ->select to ready the mux. + 5. If M1 does any i2c-transfers (on this root adapter) as part of + its select, those transfers must be unlocked i2c-transfers so + that they do not deadlock the root adapter. + 6. M1 feeds the i2c-transfer from step 1 to the root adapter as an + unlocked i2c-transfer, so that it does not deadlock the parent + adapter. + 7. M1 calls ->deselect, if it has one. + 8. Same rules as in step 5, but for ->deselect. + 9. M1 unlocks its parent adapter. + 10. M1 unlocks muxes on its parent. This means that accesses to both D2 and D3 are locked out for the full @@ -203,7 +223,7 @@ Complex Examples Parent-locked mux as parent of parent-locked mux ------------------------------------------------ -This is a useful topology, but it can be bad. +This is a useful topology, but it can be bad:: .----------. .----------. .--------. .--------. | parent- |-----| parent- |-----| dev D1 | @@ -227,7 +247,7 @@ through and be seen by the M2 adapter, thus closing M2 prematurely. Mux-locked mux as parent of mux-locked mux ------------------------------------------ -This is a good topology. +This is a good topology:: .----------. .----------. .--------. .--------. | mux- |-----| mux- |-----| dev D1 | @@ -248,7 +268,7 @@ are still possibly interleaved. Mux-locked mux as parent of parent-locked mux --------------------------------------------- -This is probably a bad topology. +This is probably a bad topology:: .----------. .----------. .--------. .--------. | mux- |-----| parent- |-----| dev D1 | @@ -282,7 +302,7 @@ auto-closing, the topology is fine. Parent-locked mux as parent of mux-locked mux --------------------------------------------- -This is a good topology. +This is a good topology:: .----------. .----------. .--------. .--------. | parent- |-----| mux- |-----| dev D1 | @@ -306,7 +326,7 @@ adapter is locked directly. Two mux-locked sibling muxes ---------------------------- -This is a good topology. +This is a good topology:: .--------. .----------. .--| dev D1 | @@ -330,7 +350,7 @@ accesses to D5 may be interleaved at any time. Two parent-locked sibling muxes ------------------------------- -This is a good topology. +This is a good topology:: .--------. .----------. .--| dev D1 | @@ -354,7 +374,7 @@ out. Mux-locked and parent-locked sibling muxes ------------------------------------------ -This is a good topology. +This is a good topology:: .--------. .----------. .--| dev D1 | diff --git a/Documentation/i2c/index.rst b/Documentation/i2c/index.rst new file mode 100644 index 000000000000..cd8d020f7ac5 --- /dev/null +++ b/Documentation/i2c/index.rst @@ -0,0 +1,37 @@ +. SPDX-License-Identifier: GPL-2.0 + +=================== +I2C/SMBus Subsystem +=================== + +.. toctree:: + :maxdepth: 1 + + dev-interface + dma-considerations + fault-codes + functionality + gpio-fault-injection + i2c-protocol + i2c-stub + i2c-topology + instantiating-devices + old-module-parameters + slave-eeprom-backend + slave-interface + smbus-protocol + summary + ten-bit-addresses + upgrading-clients + writing-clients + + muxes/i2c-mux-gpio + + busses/index + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices.rst similarity index 93% rename from Documentation/i2c/instantiating-devices rename to Documentation/i2c/instantiating-devices.rst index 345e9ea8281a..1238f1fa3382 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices.rst @@ -1,3 +1,4 @@ +============================== How to instantiate I2C devices ============================== @@ -17,9 +18,9 @@ which is known in advance. It is thus possible to pre-declare the I2C devices which live on this bus. This is done with an array of struct i2c_board_info which is registered by calling i2c_register_board_info(). -Example (from omap2 h4): +Example (from omap2 h4):: -static struct i2c_board_info h4_i2c_board_info[] __initdata = { + static struct i2c_board_info h4_i2c_board_info[] __initdata = { { I2C_BOARD_INFO("isp1301_omap", 0x2d), .irq = OMAP_GPIO_IRQ(125), @@ -32,15 +33,15 @@ static struct i2c_board_info h4_i2c_board_info[] __initdata = { I2C_BOARD_INFO("24c01", 0x57), .platform_data = &m24c01, }, -}; + }; -static void __init omap_h4_init(void) -{ + static void __init omap_h4_init(void) + { (...) i2c_register_board_info(1, h4_i2c_board_info, ARRAY_SIZE(h4_i2c_board_info)); (...) -} + } The above code declares 3 devices on I2C bus 1, including their respective addresses and custom data needed by their drivers. When the I2C bus in @@ -57,7 +58,7 @@ Method 1b: Declare the I2C devices via devicetree This method has the same implications as method 1a. The declaration of I2C devices is here done via devicetree as subnodes of the master controller. -Example: +Example:: i2c1: i2c@400a0000 { /* ... master properties skipped ... */ @@ -99,20 +100,20 @@ bus in advance, so the method 1 described above can't be used. Instead, you can instantiate your I2C devices explicitly. This is done by filling a struct i2c_board_info and calling i2c_new_device(). -Example (from the sfe4001 network driver): +Example (from the sfe4001 network driver):: -static struct i2c_board_info sfe4001_hwmon_info = { + static struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), -}; + }; -int sfe4001_init(struct efx_nic *efx) -{ + int sfe4001_init(struct efx_nic *efx) + { (...) efx->board_info.hwmon_client = i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info); (...) -} + } The above code instantiates 1 I2C device on the I2C bus which is on the network adapter in question. @@ -124,12 +125,12 @@ it may have different addresses from one board to the next (manufacturer changing its design without notice). In this case, you can call i2c_new_probed_device() instead of i2c_new_device(). -Example (from the nxp OHCI driver): +Example (from the nxp OHCI driver):: -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; + static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; -static int usb_hcd_nxp_probe(struct platform_device *pdev) -{ + static int usb_hcd_nxp_probe(struct platform_device *pdev) + { (...) struct i2c_adapter *i2c_adap; struct i2c_board_info i2c_info; @@ -142,7 +143,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev) normal_i2c, NULL); i2c_put_adapter(i2c_adap); (...) -} + } The above code instantiates up to 1 I2C device on the I2C bus which is on the OHCI adapter in question. It first tries at address 0x2c, if nothing @@ -172,6 +173,7 @@ explicitly. Instead, i2c-core will probe for such devices as soon as their drivers are loaded, and if any is found, an I2C device will be instantiated automatically. In order to prevent any misbehavior of this mechanism, the following restrictions apply: + * The I2C device driver must implement the detect() method, which identifies a supported device by reading from arbitrary registers. * Only buses which are likely to have a supported device and agree to be @@ -189,6 +191,7 @@ first. Those of you familiar with the i2c subsystem of 2.4 kernels and early 2.6 kernels will find out that this method 3 is essentially similar to what was done there. Two significant differences are: + * Probing is only one way to instantiate I2C devices now, while it was the only way back then. Where possible, methods 1 and 2 should be preferred. Method 3 should only be used when there is no other way, as it can have @@ -224,11 +227,13 @@ device. As no two devices can live at the same address on a given I2C segment, the address is sufficient to uniquely identify the device to be deleted. -Example: -# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device +Example:: + + # echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device While this interface should only be used when in-kernel device declaration can't be done, there is a variety of cases where it can be helpful: + * The I2C driver usually detects devices (method 3 above) but the bus segment your device lives on doesn't have the proper class bit set and thus detection doesn't trigger. diff --git a/Documentation/i2c/muxes/i2c-mux-gpio b/Documentation/i2c/muxes/i2c-mux-gpio.rst similarity index 85% rename from Documentation/i2c/muxes/i2c-mux-gpio rename to Documentation/i2c/muxes/i2c-mux-gpio.rst index 893ecdfe6e43..7d27444035c3 100644 --- a/Documentation/i2c/muxes/i2c-mux-gpio +++ b/Documentation/i2c/muxes/i2c-mux-gpio.rst @@ -1,4 +1,6 @@ +========================== Kernel driver i2c-mux-gpio +========================== Author: Peter Korsgaard @@ -8,7 +10,7 @@ Description i2c-mux-gpio is an i2c mux driver providing access to I2C bus segments from a master I2C bus and a hardware MUX controlled through GPIO pins. -E.G.: +E.G.:: ---------- ---------- Bus segment 1 - - - - - | | SCL/SDA | |-------------- | | @@ -33,20 +35,20 @@ bus, the number of bus segments to create and the GPIO pins used to control it. See include/linux/platform_data/i2c-mux-gpio.h for details. E.G. something like this for a MUX providing 4 bus segments -controlled through 3 GPIO pins: +controlled through 3 GPIO pins:: -#include -#include + #include + #include -static const unsigned myboard_gpiomux_gpios[] = { + static const unsigned myboard_gpiomux_gpios[] = { AT91_PIN_PC26, AT91_PIN_PC25, AT91_PIN_PC24 -}; + }; -static const unsigned myboard_gpiomux_values[] = { + static const unsigned myboard_gpiomux_values[] = { 0, 1, 2, 3 -}; + }; -static struct i2c_mux_gpio_platform_data myboard_i2cmux_data = { + static struct i2c_mux_gpio_platform_data myboard_i2cmux_data = { .parent = 1, .base_nr = 2, /* optional */ .values = myboard_gpiomux_values, @@ -54,15 +56,15 @@ static struct i2c_mux_gpio_platform_data myboard_i2cmux_data = { .gpios = myboard_gpiomux_gpios, .n_gpios = ARRAY_SIZE(myboard_gpiomux_gpios), .idle = 4, /* optional */ -}; + }; -static struct platform_device myboard_i2cmux = { + static struct platform_device myboard_i2cmux = { .name = "i2c-mux-gpio", .id = 0, .dev = { .platform_data = &myboard_i2cmux_data, }, -}; + }; If you don't know the absolute GPIO pin numbers at registration time, you can instead provide a chip name (.chip_name) and relative GPIO pin diff --git a/Documentation/i2c/old-module-parameters b/Documentation/i2c/old-module-parameters.rst similarity index 75% rename from Documentation/i2c/old-module-parameters rename to Documentation/i2c/old-module-parameters.rst index 8e2b629d533c..a1939512ad66 100644 --- a/Documentation/i2c/old-module-parameters +++ b/Documentation/i2c/old-module-parameters.rst @@ -1,3 +1,4 @@ +================================================= I2C device driver binding control from user-space ================================================= @@ -19,23 +20,27 @@ Below is a mapping from the old module parameters to the new interface. Attaching a driver to an I2C device ----------------------------------- -Old method (module parameters): -# modprobe probe=1,0x2d -# modprobe force=1,0x2d -# modprobe force_=1,0x2d +Old method (module parameters):: + + # modprobe probe=1,0x2d + # modprobe force=1,0x2d + # modprobe force_=1,0x2d + +New method (sysfs interface):: -New method (sysfs interface): -# echo 0x2d > /sys/bus/i2c/devices/i2c-1/new_device + # echo 0x2d > /sys/bus/i2c/devices/i2c-1/new_device Preventing a driver from attaching to an I2C device --------------------------------------------------- -Old method (module parameters): -# modprobe ignore=1,0x2f +Old method (module parameters):: + + # modprobe ignore=1,0x2f + +New method (sysfs interface):: -New method (sysfs interface): -# echo dummy 0x2f > /sys/bus/i2c/devices/i2c-1/new_device -# modprobe + # echo dummy 0x2f > /sys/bus/i2c/devices/i2c-1/new_device + # modprobe Of course, it is important to instantiate the "dummy" device before loading the driver. The dummy device will be handled by i2c-core itself, preventing diff --git a/Documentation/i2c/slave-eeprom-backend b/Documentation/i2c/slave-eeprom-backend.rst similarity index 90% rename from Documentation/i2c/slave-eeprom-backend rename to Documentation/i2c/slave-eeprom-backend.rst index 04f8d8a9b817..0b8cd83698e0 100644 --- a/Documentation/i2c/slave-eeprom-backend +++ b/Documentation/i2c/slave-eeprom-backend.rst @@ -1,3 +1,4 @@ +============================== Linux I2C slave eeprom backend ============================== @@ -5,10 +6,9 @@ by Wolfram Sang in 2014-15 This is a proof-of-concept backend which acts like an EEPROM on the connected I2C bus. The memory contents can be modified from userspace via this file -located in sysfs: +located in sysfs:: /sys/bus/i2c/devices//slave-eeprom As of 2015, Linux doesn't support poll on binary sysfs files, so there is no notification when another master changed the content. - diff --git a/Documentation/i2c/slave-interface b/Documentation/i2c/slave-interface.rst similarity index 94% rename from Documentation/i2c/slave-interface rename to Documentation/i2c/slave-interface.rst index 7e2a228f21bc..c769bd6a15bf 100644 --- a/Documentation/i2c/slave-interface +++ b/Documentation/i2c/slave-interface.rst @@ -1,3 +1,4 @@ +===================================== Linux I2C slave interface description ===================================== @@ -12,7 +13,7 @@ EEPROM, the Linux I2C slave can access the content via sysfs and handle data as needed. The backend driver and the I2C bus driver communicate via events. Here is a small graph visualizing the data flow and the means by which data is transported. The dotted line marks only one example. The backend could also -use a character device, be in-kernel only, or something completely different: +use a character device, be in-kernel only, or something completely different:: e.g. sysfs I2C slave events I/O registers @@ -35,7 +36,7 @@ them as described in the document 'instantiating-devices'. The only difference is that i2c slave backends have their own address space. So, you have to add 0x1000 to the address you would originally request. An example for instantiating the slave-eeprom driver from userspace at the 7 bit address 0x64 -on bus 1: +on bus 1:: # echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device @@ -54,7 +55,7 @@ drivers and writing backends will be given. I2C slave events ---------------- -The bus driver sends an event to the backend using the following function: +The bus driver sends an event to the backend using the following function:: ret = i2c_slave_event(client, event, &val) @@ -69,8 +70,9 @@ Event types: * I2C_SLAVE_WRITE_REQUESTED (mandatory) -'val': unused -'ret': always 0 + 'val': unused + + 'ret': always 0 Another I2C master wants to write data to us. This event should be sent once our own address and the write bit was detected. The data did not arrive yet, so @@ -79,8 +81,9 @@ to be done, though. * I2C_SLAVE_READ_REQUESTED (mandatory) -'val': backend returns first byte to be sent -'ret': always 0 + 'val': backend returns first byte to be sent + + 'ret': always 0 Another I2C master wants to read data from us. This event should be sent once our own address and the read bit was detected. After returning, the bus driver @@ -88,8 +91,9 @@ should transmit the first byte. * I2C_SLAVE_WRITE_RECEIVED (mandatory) -'val': bus driver delivers received byte -'ret': 0 if the byte should be acked, some errno if the byte should be nacked + 'val': bus driver delivers received byte + + 'ret': 0 if the byte should be acked, some errno if the byte should be nacked Another I2C master has sent a byte to us which needs to be set in 'val'. If 'ret' is zero, the bus driver should ack this byte. If 'ret' is an errno, then the byte @@ -97,8 +101,9 @@ should be nacked. * I2C_SLAVE_READ_PROCESSED (mandatory) -'val': backend returns next byte to be sent -'ret': always 0 + 'val': backend returns next byte to be sent + + 'ret': always 0 The bus driver requests the next byte to be sent to another I2C master in 'val'. Important: This does not mean that the previous byte has been acked, it @@ -111,8 +116,9 @@ your backend, though. * I2C_SLAVE_STOP (mandatory) -'val': unused -'ret': always 0 + 'val': unused + + 'ret': always 0 A stop condition was received. This can happen anytime and the backend should reset its state machine for I2C transfers to be able to receive new requests. @@ -190,4 +196,3 @@ this time of writing. Some points to keep in mind when using buffers: * A master can send STOP at any time. For partially transferred buffers, this means additional code to handle this exception. Such code tends to be error-prone. - diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol.rst similarity index 82% rename from Documentation/i2c/smbus-protocol rename to Documentation/i2c/smbus-protocol.rst index 092d474f5843..e30eb1d274c6 100644 --- a/Documentation/i2c/smbus-protocol +++ b/Documentation/i2c/smbus-protocol.rst @@ -1,3 +1,4 @@ +====================== SMBus Protocol Summary ====================== @@ -27,17 +28,18 @@ Each transaction type corresponds to a functionality flag. Before calling a transaction function, a device driver should always check (just once) for the corresponding functionality flag to ensure that the underlying I2C adapter supports the transaction in question. See - for the details. + for the details. Key to symbols ============== +=============== ============================================================= S (1 bit) : Start bit P (1 bit) : Stop bit Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. -A, NA (1 bit) : Accept and reverse accept bit. -Addr (7 bits): I2C 7 bit address. Note that this can be expanded as usual to +A, NA (1 bit) : Accept and reverse accept bit. +Addr (7 bits): I2C 7 bit address. Note that this can be expanded as usual to get a 10 bit I2C address. Comm (8 bits): Command byte, a data byte which often selects a register on the device. @@ -45,15 +47,17 @@ Data (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh for 16 bit data. Count (8 bits): A data byte containing the length of a block operation. -[..]: Data sent by I2C device, as opposed to data sent by the host adapter. +[..]: Data sent by I2C device, as opposed to data sent by the host + adapter. +=============== ============================================================= SMBus Quick Command =================== -This sends a single bit to the device, at the place of the Rd/Wr bit. +This sends a single bit to the device, at the place of the Rd/Wr bit:: -A Addr Rd/Wr [A] P + A Addr Rd/Wr [A] P Functionality flag: I2C_FUNC_SMBUS_QUICK @@ -64,9 +68,9 @@ SMBus Receive Byte: i2c_smbus_read_byte() This reads a single byte from a device, without specifying a device register. Some devices are so simple that this interface is enough; for others, it is a shorthand if you want to read the same register as in -the previous SMBus command. +the previous SMBus command:: -S Addr Rd [A] [Data] NA P + S Addr Rd [A] [Data] NA P Functionality flag: I2C_FUNC_SMBUS_READ_BYTE @@ -77,7 +81,9 @@ SMBus Send Byte: i2c_smbus_write_byte() This operation is the reverse of Receive Byte: it sends a single byte to a device. See Receive Byte for more information. -S Addr Wr [A] Data [A] P +:: + + S Addr Wr [A] Data [A] P Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE @@ -86,9 +92,9 @@ SMBus Read Byte: i2c_smbus_read_byte_data() ============================================ This reads a single byte from a device, from a designated register. -The register is specified through the Comm byte. +The register is specified through the Comm byte:: -S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P + S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA @@ -98,9 +104,9 @@ SMBus Read Word: i2c_smbus_read_word_data() This operation is very like Read Byte; again, data is read from a device, from a designated register that is specified through the Comm -byte. But this time, the data is a complete word (16 bits). +byte. But this time, the data is a complete word (16 bits):: -S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P + S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA @@ -116,7 +122,9 @@ This writes a single byte to a device, to a designated register. The register is specified through the Comm byte. This is the opposite of the Read Byte operation. -S Addr Wr [A] Comm [A] Data [A] P +:: + + S Addr Wr [A] Comm [A] Data [A] P Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA @@ -126,9 +134,9 @@ SMBus Write Word: i2c_smbus_write_word_data() This is the opposite of the Read Word operation. 16 bits of data is written to a device, to the designated register that is -specified through the Comm byte. +specified through the Comm byte.:: -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P + S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA @@ -141,10 +149,10 @@ SMBus Process Call: =================== This command selects a device register (through the Comm byte), sends -16 bits of data to it, and reads 16 bits of data in return. +16 bits of data to it, and reads 16 bits of data in return:: -S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] - S Addr Rd [A] [DataLow] A [DataHigh] NA P + S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] + S Addr Rd [A] [DataLow] A [DataHigh] NA P Functionality flag: I2C_FUNC_SMBUS_PROC_CALL @@ -152,12 +160,14 @@ Functionality flag: I2C_FUNC_SMBUS_PROC_CALL SMBus Block Read: i2c_smbus_read_block_data() ============================================== -This command reads a block of up to 32 bytes from a device, from a +This command reads a block of up to 32 bytes from a device, from a designated register that is specified through the Comm byte. The amount of data is specified by the device in the Count byte. -S Addr Wr [A] Comm [A] - S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P +:: + + S Addr Wr [A] Comm [A] + S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA @@ -165,11 +175,13 @@ Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA SMBus Block Write: i2c_smbus_write_block_data() ================================================ -The opposite of the Block Read command, this writes up to 32 bytes to +The opposite of the Block Read command, this writes up to 32 bytes to a device, to a designated register that is specified through the Comm byte. The amount of data is specified in the Count byte. -S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P +:: + + S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA @@ -181,10 +193,10 @@ SMBus Block Write - Block Read Process Call was introduced in Revision 2.0 of the specification. This command selects a device register (through the Comm byte), sends -1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return. +1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return:: -S Addr Wr [A] Comm [A] Count [A] Data [A] ... - S Addr Rd [A] [Count] A [Data] ... A P + S Addr Wr [A] Comm [A] Count [A] Data [A] ... + S Addr Rd [A] [Count] A [Data] ... A P Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL @@ -197,9 +209,12 @@ SMBus host acting as a slave. It is the same form as Write Word, with the command code replaced by the alerting device's address. -[S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P] +:: + + [S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P] This is implemented in the following way in the Linux kernel: + * I2C bus drivers which support SMBus Host Notify should report I2C_FUNC_SMBUS_HOST_NOTIFY. * I2C bus drivers trigger SMBus Host Notify by a call to @@ -241,6 +256,7 @@ single interrupt pin on the SMBus master, while still allowing the master to know which slave triggered the interrupt. This is implemented the following way in the Linux kernel: + * I2C bus drivers which support SMBus alert should call i2c_setup_smbus_alert() to setup SMBus alert support. * I2C drivers for devices which can trigger SMBus alerts should implement @@ -261,11 +277,11 @@ but the SMBus layer places a limit of 32 bytes. I2C Block Read: i2c_smbus_read_i2c_block_data() ================================================ -This command reads a block of bytes from a device, from a -designated register that is specified through the Comm byte. +This command reads a block of bytes from a device, from a +designated register that is specified through the Comm byte:: -S Addr Wr [A] Comm [A] - S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P + S Addr Wr [A] Comm [A] + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK @@ -273,11 +289,13 @@ Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK I2C Block Write: i2c_smbus_write_i2c_block_data() ================================================== -The opposite of the Block Read command, this writes bytes to +The opposite of the Block Read command, this writes bytes to a device, to a designated register that is specified through the Comm byte. Note that command lengths of 0, 2, or more bytes are supported as they are indistinguishable from data. -S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P +:: + + S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK diff --git a/Documentation/i2c/summary b/Documentation/i2c/summary.rst similarity index 96% rename from Documentation/i2c/summary rename to Documentation/i2c/summary.rst index 809541ab352f..3a24eac17375 100644 --- a/Documentation/i2c/summary +++ b/Documentation/i2c/summary.rst @@ -1,7 +1,8 @@ +============= I2C and SMBus ============= -I2C (pronounce: I squared C) is a protocol developed by Philips. It is a +I2C (pronounce: I squared C) is a protocol developed by Philips. It is a slow two-wire protocol (variable speed, up to 400 kHz), with a high speed extension (3.4 MHz). It provides an inexpensive bus for connecting many types of devices with infrequent or low bandwidth communications needs. @@ -24,7 +25,8 @@ implement all the common SMBus protocol semantics or messages. Terminology =========== -When we talk about I2C, we use the following terms: +When we talk about I2C, we use the following terms:: + Bus -> Algorithm Adapter Device -> Driver diff --git a/Documentation/i2c/ten-bit-addresses b/Documentation/i2c/ten-bit-addresses.rst similarity index 95% rename from Documentation/i2c/ten-bit-addresses rename to Documentation/i2c/ten-bit-addresses.rst index 7b2d11e53a49..5c765aff16d5 100644 --- a/Documentation/i2c/ten-bit-addresses +++ b/Documentation/i2c/ten-bit-addresses.rst @@ -1,3 +1,7 @@ +===================== +I2C Ten-bit Addresses +===================== + The I2C protocol knows about two kinds of device addresses: normal 7 bit addresses, and an extended set of 10 bit addresses. The sets of addresses do not intersect: the 7 bit address 0x10 is not the same as the 10 bit @@ -12,6 +16,7 @@ See the I2C specification for the details. The current 10 bit address support is minimal. It should work, however you can expect some problems along the way: + * Not all bus drivers support 10-bit addresses. Some don't because the hardware doesn't support them (SMBus doesn't require 10-bit address support for example), some don't because nobody bothered adding the diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients.rst similarity index 54% rename from Documentation/i2c/upgrading-clients rename to Documentation/i2c/upgrading-clients.rst index 96392cc5b5c7..27d29032c138 100644 --- a/Documentation/i2c/upgrading-clients +++ b/Documentation/i2c/upgrading-clients.rst @@ -1,3 +1,4 @@ +================================================= Upgrading I2C Drivers to the new 2.6 Driver Model ================================================= @@ -13,21 +14,22 @@ the old to the new new binding methods. Example old-style driver ------------------------ +:: -struct example_state { + struct example_state { struct i2c_client client; .... -}; + }; -static struct i2c_driver example_driver; + static struct i2c_driver example_driver; -static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; + static unsigned short ignore[] = { I2C_CLIENT_END }; + static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; -I2C_CLIENT_INSMOD; + I2C_CLIENT_INSMOD; -static int example_attach(struct i2c_adapter *adap, int addr, int kind) -{ + static int example_attach(struct i2c_adapter *adap, int addr, int kind) + { struct example_state *state; struct device *dev = &adap->dev; /* to use for dev_ reports */ int ret; @@ -59,31 +61,31 @@ static int example_attach(struct i2c_adapter *adap, int addr, int kind) dev_info(dev, "example client created\n"); return 0; -} + } -static int example_detach(struct i2c_client *client) -{ + static int example_detach(struct i2c_client *client) + { struct example_state *state = i2c_get_clientdata(client); i2c_detach_client(client); kfree(state); return 0; -} + } -static int example_attach_adapter(struct i2c_adapter *adap) -{ + static int example_attach_adapter(struct i2c_adapter *adap) + { return i2c_probe(adap, &addr_data, example_attach); -} + } -static struct i2c_driver example_driver = { - .driver = { + static struct i2c_driver example_driver = { + .driver = { .owner = THIS_MODULE, .name = "example", .pm = &example_pm_ops, }, .attach_adapter = example_attach_adapter, .detach_client = example_detach, -}; + }; Updating the client @@ -93,38 +95,38 @@ The new style binding model will check against a list of supported devices and their associated address supplied by the code registering the busses. This means that the driver .attach_adapter and .detach_client methods can be removed, along with the addr_data, -as follows: +as follows:: -- static struct i2c_driver example_driver; + - static struct i2c_driver example_driver; -- static unsigned short ignore[] = { I2C_CLIENT_END }; -- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; + - static unsigned short ignore[] = { I2C_CLIENT_END }; + - static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; -- I2C_CLIENT_INSMOD; + - I2C_CLIENT_INSMOD; -- static int example_attach_adapter(struct i2c_adapter *adap) -- { -- return i2c_probe(adap, &addr_data, example_attach); -- } + - static int example_attach_adapter(struct i2c_adapter *adap) + - { + - return i2c_probe(adap, &addr_data, example_attach); + - } - static struct i2c_driver example_driver = { -- .attach_adapter = example_attach_adapter, -- .detach_client = example_detach, - } + static struct i2c_driver example_driver = { + - .attach_adapter = example_attach_adapter, + - .detach_client = example_detach, + } -Add the probe and remove methods to the i2c_driver, as so: +Add the probe and remove methods to the i2c_driver, as so:: - static struct i2c_driver example_driver = { -+ .probe = example_probe, -+ .remove = example_remove, - } + static struct i2c_driver example_driver = { + + .probe = example_probe, + + .remove = example_remove, + } Change the example_attach method to accept the new parameters -which include the i2c_client that it will be working with: +which include the i2c_client that it will be working with:: -- static int example_attach(struct i2c_adapter *adap, int addr, int kind) -+ static int example_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) + - static int example_attach(struct i2c_adapter *adap, int addr, int kind) + + static int example_probe(struct i2c_client *client, + + const struct i2c_device_id *id) Change the name of example_attach to example_probe to align it with the i2c_driver entry names. The rest of the probe routine will now need to be @@ -132,57 +134,59 @@ changed as the i2c_client has already been setup for use. The necessary client fields have already been setup before the probe function is called, so the following client setup -can be removed: +can be removed:: -- example->client.addr = addr; -- example->client.flags = 0; -- example->client.adapter = adap; -- -- strscpy(client->i2c_client.name, "example", sizeof(client->i2c_client.name)); + - example->client.addr = addr; + - example->client.flags = 0; + - example->client.adapter = adap; + - + - strscpy(client->i2c_client.name, "example", sizeof(client->i2c_client.name)); -The i2c_set_clientdata is now: +The i2c_set_clientdata is now:: -- i2c_set_clientdata(&state->client, state); -+ i2c_set_clientdata(client, state); + - i2c_set_clientdata(&state->client, state); + + i2c_set_clientdata(client, state); The call to i2c_attach_client is no longer needed, if the probe routine exits successfully, then the driver will be automatically -attached by the core. Change the probe routine as so: +attached by the core. Change the probe routine as so:: -- ret = i2c_attach_client(&state->i2c_client); -- if (ret < 0) { -- dev_err(dev, "failed to attach client\n"); -- kfree(state); -- return ret; -- } + - ret = i2c_attach_client(&state->i2c_client); + - if (ret < 0) { + - dev_err(dev, "failed to attach client\n"); + - kfree(state); + - return ret; + - } Remove the storage of 'struct i2c_client' from the 'struct example_state' as we are provided with the i2c_client in our example_probe. Instead we store a pointer to it for when it is needed. -struct example_state { -- struct i2c_client client; -+ struct i2c_client *client; +:: + + struct example_state { + - struct i2c_client client; + + struct i2c_client *client; -the new i2c client as so: +the new i2c client as so:: -- struct device *dev = &adap->dev; /* to use for dev_ reports */ -+ struct device *dev = &i2c_client->dev; /* to use for dev_ reports */ + - struct device *dev = &adap->dev; /* to use for dev_ reports */ + + struct device *dev = &i2c_client->dev; /* to use for dev_ reports */ And remove the change after our client is attached, as the driver no -longer needs to register a new client structure with the core: +longer needs to register a new client structure with the core:: -- dev = &state->i2c_client.dev; + - dev = &state->i2c_client.dev; In the probe routine, ensure that the new state has the client stored -in it: +in it:: -static int example_probe(struct i2c_client *i2c_client, + static int example_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) -{ + { struct example_state *state; - struct device *dev = &i2c_client->dev; + struct device *dev = &i2c_client->dev; int ret; state = kzalloc(sizeof(struct example_state), GFP_KERNEL); @@ -191,48 +195,50 @@ static int example_probe(struct i2c_client *i2c_client, return -ENOMEM; } -+ state->client = i2c_client; + + state->client = i2c_client; Update the detach method, by changing the name to _remove and to delete the i2c_detach_client call. It is possible that you can also remove the ret variable as it is not needed for any of the core functions. -- static int example_detach(struct i2c_client *client) -+ static int example_remove(struct i2c_client *client) -{ +:: + + - static int example_detach(struct i2c_client *client) + + static int example_remove(struct i2c_client *client) + { struct example_state *state = i2c_get_clientdata(client); -- i2c_detach_client(client); + - i2c_detach_client(client); And finally ensure that we have the correct ID table for the i2c-core -and other utilities: +and other utilities:: -+ struct i2c_device_id example_idtable[] = { -+ { "example", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, example_idtable); + + struct i2c_device_id example_idtable[] = { + + { "example", 0 }, + + { } + +}; + + + +MODULE_DEVICE_TABLE(i2c, example_idtable); -static struct i2c_driver example_driver = { - .driver = { + static struct i2c_driver example_driver = { + .driver = { .owner = THIS_MODULE, .name = "example", }, -+ .id_table = example_ids, + + .id_table = example_ids, -Our driver should now look like this: +Our driver should now look like this:: -struct example_state { + struct example_state { struct i2c_client *client; .... -}; + }; -static int example_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ + static int example_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { struct example_state *state; struct device *dev = &client->dev; @@ -250,25 +256,25 @@ static int example_probe(struct i2c_client *client, dev_info(dev, "example client created\n"); return 0; -} + } -static int example_remove(struct i2c_client *client) -{ + static int example_remove(struct i2c_client *client) + { struct example_state *state = i2c_get_clientdata(client); kfree(state); return 0; -} + } -static struct i2c_device_id example_idtable[] = { + static struct i2c_device_id example_idtable[] = { { "example", 0 }, { } -}; + }; -MODULE_DEVICE_TABLE(i2c, example_idtable); + MODULE_DEVICE_TABLE(i2c, example_idtable); -static struct i2c_driver example_driver = { - .driver = { + static struct i2c_driver example_driver = { + .driver = { .owner = THIS_MODULE, .name = "example", .pm = &example_pm_ops, @@ -276,4 +282,4 @@ static struct i2c_driver example_driver = { .id_table = example_idtable, .probe = example_probe, .remove = example_remove, -}; + }; diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients.rst similarity index 91% rename from Documentation/i2c/writing-clients rename to Documentation/i2c/writing-clients.rst index a755b141fa4a..dddf0a14ab7c 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients.rst @@ -1,3 +1,7 @@ +=================== +Writing I2C Clients +=================== + This is a small guide for those who want to write kernel drivers for I2C or SMBus devices, using Linux as the protocol host/master (not slave). @@ -12,7 +16,7 @@ General remarks Try to keep the kernel namespace as clean as possible. The best way to do this is to use a unique prefix for all global symbols. This is especially important for exported symbols, but it is a good idea to do -it for non-exported symbols too. We will use the prefix `foo_' in this +it for non-exported symbols too. We will use the prefix ``foo_`` in this tutorial. @@ -25,15 +29,17 @@ routines, and should be zero-initialized except for fields with data you provide. A client structure holds device-specific information like the driver model device node, and its I2C address. -static struct i2c_device_id foo_idtable[] = { +:: + + static struct i2c_device_id foo_idtable[] = { { "foo", my_id_for_foo }, { "bar", my_id_for_bar }, { } -}; + }; -MODULE_DEVICE_TABLE(i2c, foo_idtable); + MODULE_DEVICE_TABLE(i2c, foo_idtable); -static struct i2c_driver foo_driver = { + static struct i2c_driver foo_driver = { .driver = { .name = "foo", .pm = &foo_pm_ops, /* optional */ @@ -49,7 +55,7 @@ static struct i2c_driver foo_driver = { .shutdown = foo_shutdown, /* optional */ .command = foo_command, /* optional, deprecated */ -} + } The name field is the driver name, and must not contain spaces. It should match the module name (if the driver can be compiled as a module), @@ -64,16 +70,18 @@ below. Extra client data ================= -Each client structure has a special `data' field that can point to any +Each client structure has a special ``data`` field that can point to any structure at all. You should use this to keep device-specific data. +:: + /* store the value */ void i2c_set_clientdata(struct i2c_client *client, void *data); /* retrieve the value */ void *i2c_get_clientdata(const struct i2c_client *client); -Note that starting with kernel 2.6.34, you don't have to set the `data' field +Note that starting with kernel 2.6.34, you don't have to set the ``data`` field to NULL in remove() or if probe() failed anymore. The i2c-core does this automatically on these occasions. Those are also the only times the core will touch this field. @@ -92,25 +100,25 @@ but many chips have some kind of register-value idea that can easily be encapsulated. The below functions are simple examples, and should not be copied -literally. +literally:: -int foo_read_value(struct i2c_client *client, u8 reg) -{ + int foo_read_value(struct i2c_client *client, u8 reg) + { if (reg < 0x10) /* byte-sized register */ return i2c_smbus_read_byte_data(client, reg); else /* word-sized register */ return i2c_smbus_read_word_data(client, reg); -} + } -int foo_write_value(struct i2c_client *client, u8 reg, u16 value) -{ + int foo_write_value(struct i2c_client *client, u8 reg, u16 value) + { if (reg == 0x10) /* Impossible to write - driver error! */ return -EINVAL; else if (reg < 0x10) /* byte-sized register */ return i2c_smbus_write_byte_data(client, reg, value); else /* word-sized register */ return i2c_smbus_write_word_data(client, reg, value); -} + } Probing and attaching @@ -145,6 +153,8 @@ I2C device drivers using this binding model work just like any other kind of driver in Linux: they provide a probe() method to bind to those devices, and a remove() method to unbind. +:: + static int foo_probe(struct i2c_client *client, const struct i2c_device_id *id); static int foo_remove(struct i2c_client *client); @@ -240,37 +250,41 @@ When the kernel is booted, or when your foo driver module is inserted, you have to do some initializing. Fortunately, just registering the driver module is usually enough. -static int __init foo_init(void) -{ +:: + + static int __init foo_init(void) + { return i2c_add_driver(&foo_driver); -} -module_init(foo_init); + } + module_init(foo_init); -static void __exit foo_cleanup(void) -{ + static void __exit foo_cleanup(void) + { i2c_del_driver(&foo_driver); -} -module_exit(foo_cleanup); + } + module_exit(foo_cleanup); -The module_i2c_driver() macro can be used to reduce above code. + The module_i2c_driver() macro can be used to reduce above code. -module_i2c_driver(foo_driver); + module_i2c_driver(foo_driver); -Note that some functions are marked by `__init'. These functions can +Note that some functions are marked by ``__init``. These functions can be removed after kernel booting (or module loading) is completed. -Likewise, functions marked by `__exit' are dropped by the compiler when +Likewise, functions marked by ``__exit`` are dropped by the compiler when the code is built into the kernel, as they would never be called. Driver Information ================== -/* Substitute your own name and email address */ -MODULE_AUTHOR("Frodo Looijaard " -MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); +:: -/* a few non-GPL license types are also allowed */ -MODULE_LICENSE("GPL"); + /* Substitute your own name and email address */ + MODULE_AUTHOR("Frodo Looijaard " + MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); + + /* a few non-GPL license types are also allowed */ + MODULE_LICENSE("GPL"); Power Management @@ -323,6 +337,8 @@ commands, but only some of them understand plain I2C! Plain I2C communication ----------------------- +:: + int i2c_master_send(struct i2c_client *client, const char *buf, int count); int i2c_master_recv(struct i2c_client *client, char *buf, int count); @@ -334,6 +350,8 @@ to read/write (must be less than the length of the buffer, also should be less than 64k since msg.len is u16.) Returned is the actual number of bytes read/written. +:: + int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num); @@ -343,13 +361,15 @@ stop bit is sent between transaction. The i2c_msg structure contains for each message the client address, the number of bytes of the message and the message data itself. -You can read the file `i2c-protocol' for more information about the +You can read the file ``i2c-protocol`` for more information about the actual I2C protocol. SMBus communication ------------------- +:: + s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); @@ -357,6 +377,8 @@ SMBus communication This is the generic SMBus function. All functions below are implemented in terms of it. Never use this function directly! +:: + s32 i2c_smbus_read_byte(struct i2c_client *client); s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value); s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command); @@ -376,7 +398,7 @@ in terms of it. Never use this function directly! const u8 *values); These ones were removed from i2c-core because they had no users, but could -be added back later if needed: +be added back later if needed:: s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value); s32 i2c_smbus_process_call(struct i2c_client *client, @@ -389,7 +411,7 @@ transactions return 0 on success; the 'read' transactions return the read value, except for block transactions, which return the number of values read. The block buffers need not be longer than 32 bytes. -You can read the file `smbus-protocol' for more information about the +You can read the file ``smbus-protocol`` for more information about the actual SMBus protocol. @@ -397,7 +419,7 @@ General purpose routines ======================== Below all general purpose routines are listed, that were not mentioned -before. +before:: /* Return the adapter number for a specific adapter */ int i2c_adapter_id(struct i2c_adapter *adap); diff --git a/Documentation/index.rst b/Documentation/index.rst index 2df5a3da563c..9b45af84fd29 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -104,6 +104,7 @@ needed). fb/index fpga/index hid/index + i2c/index iio/index infiniband/index leds/index diff --git a/Documentation/spi/spi-sc18is602 b/Documentation/spi/spi-sc18is602 index a45702865a38..0feffd5af411 100644 --- a/Documentation/spi/spi-sc18is602 +++ b/Documentation/spi/spi-sc18is602 @@ -17,7 +17,7 @@ kernel's SPI core subsystem. The driver does not probe for supported chips, since the SI18IS602/603 does not support Chip ID registers. You will have to instantiate the devices explicitly. -Please see Documentation/i2c/instantiating-devices for details. +Please see Documentation/i2c/instantiating-devices.rst for details. Usage Notes diff --git a/MAINTAINERS b/MAINTAINERS index 6326445952f6..a3d5dd341088 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -666,7 +666,7 @@ ALI1563 I2C DRIVER M: Rudolf Marek L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-ali1563 +F: Documentation/i2c/busses/i2c-ali1563.rst F: drivers/i2c/busses/i2c-ali1563.c ALLEGRO DVT VIDEO IP CORE DRIVER @@ -6741,7 +6741,7 @@ L: linux-i2c@vger.kernel.org S: Supported F: drivers/i2c/muxes/i2c-mux-gpio.c F: include/linux/platform_data/i2c-mux-gpio.h -F: Documentation/i2c/muxes/i2c-mux-gpio +F: Documentation/i2c/muxes/i2c-mux-gpio.rst GENERIC HDLC (WAN) DRIVERS M: Krzysztof Halasa @@ -7497,14 +7497,14 @@ I2C CONTROLLER DRIVER FOR NVIDIA GPU M: Ajay Gupta L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-nvidia-gpu +F: Documentation/i2c/busses/i2c-nvidia-gpu.rst F: drivers/i2c/busses/i2c-nvidia-gpu.c I2C MUXES M: Peter Rosin L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/i2c-topology +F: Documentation/i2c/i2c-topology.rst F: Documentation/i2c/muxes/ F: Documentation/devicetree/bindings/i2c/i2c-mux* F: Documentation/devicetree/bindings/i2c/i2c-arb* @@ -7524,8 +7524,8 @@ I2C OVER PARALLEL PORT M: Jean Delvare L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-parport -F: Documentation/i2c/busses/i2c-parport-light +F: Documentation/i2c/busses/i2c-parport.rst +F: Documentation/i2c/busses/i2c-parport-light.rst F: drivers/i2c/busses/i2c-parport.c F: drivers/i2c/busses/i2c-parport-light.c @@ -7559,7 +7559,7 @@ I2C-TAOS-EVM DRIVER M: Jean Delvare L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-taos-evm +F: Documentation/i2c/busses/i2c-taos-evm.rst F: drivers/i2c/busses/i2c-taos-evm.c I2C-TINY-USB DRIVER @@ -7573,19 +7573,19 @@ I2C/SMBUS CONTROLLER DRIVERS FOR PC M: Jean Delvare L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-ali1535 -F: Documentation/i2c/busses/i2c-ali1563 -F: Documentation/i2c/busses/i2c-ali15x3 -F: Documentation/i2c/busses/i2c-amd756 -F: Documentation/i2c/busses/i2c-amd8111 -F: Documentation/i2c/busses/i2c-i801 -F: Documentation/i2c/busses/i2c-nforce2 -F: Documentation/i2c/busses/i2c-piix4 -F: Documentation/i2c/busses/i2c-sis5595 -F: Documentation/i2c/busses/i2c-sis630 -F: Documentation/i2c/busses/i2c-sis96x -F: Documentation/i2c/busses/i2c-via -F: Documentation/i2c/busses/i2c-viapro +F: Documentation/i2c/busses/i2c-ali1535.rst +F: Documentation/i2c/busses/i2c-ali1563.rst +F: Documentation/i2c/busses/i2c-ali15x3.rst +F: Documentation/i2c/busses/i2c-amd756.rst +F: Documentation/i2c/busses/i2c-amd8111.rst +F: Documentation/i2c/busses/i2c-i801.rst +F: Documentation/i2c/busses/i2c-nforce2.rst +F: Documentation/i2c/busses/i2c-piix4.rst +F: Documentation/i2c/busses/i2c-sis5595.rst +F: Documentation/i2c/busses/i2c-sis630.rst +F: Documentation/i2c/busses/i2c-sis96x.rst +F: Documentation/i2c/busses/i2c-via.rst +F: Documentation/i2c/busses/i2c-viapro.rst F: drivers/i2c/busses/i2c-ali1535.c F: drivers/i2c/busses/i2c-ali1563.c F: drivers/i2c/busses/i2c-ali15x3.c @@ -7614,7 +7614,7 @@ M: Seth Heasley M: Neil Horman L: linux-i2c@vger.kernel.org F: drivers/i2c/busses/i2c-ismt.c -F: Documentation/i2c/busses/i2c-ismt +F: Documentation/i2c/busses/i2c-ismt.rst I2C/SMBUS STUB DRIVER M: Jean Delvare @@ -10355,7 +10355,7 @@ L: linux-i2c@vger.kernel.org S: Supported F: drivers/i2c/busses/i2c-mlxcpld.c F: drivers/i2c/muxes/i2c-mux-mlxcpld.c -F: Documentation/i2c/busses/i2c-mlxcpld +F: Documentation/i2c/busses/i2c-mlxcpld.rst MELLANOX MLXCPLD LED DRIVER M: Vadim Pasternak @@ -11976,7 +11976,7 @@ M: Andrew Lunn L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/i2c/i2c-ocores.txt -F: Documentation/i2c/busses/i2c-ocores +F: Documentation/i2c/busses/i2c-ocores.rst F: drivers/i2c/busses/i2c-ocores.c F: include/linux/platform_data/i2c-ocores.h @@ -14280,7 +14280,7 @@ F: net/sctp/ SCx200 CPU SUPPORT M: Jim Cromie S: Odd Fixes -F: Documentation/i2c/busses/scx200_acb +F: Documentation/i2c/busses/scx200_acb.rst F: arch/x86/platform/scx200/ F: drivers/watchdog/scx200_wdt.c F: drivers/i2c/busses/scx200* diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index e232fa948833..79b8df258371 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -5,7 +5,7 @@ * * The ATXP1 can reside on I2C addresses 0x37 or 0x4e. The chip is * not auto-detected by the driver and must be instantiated explicitly. - * See Documentation/i2c/instantiating-devices for more information. + * See Documentation/i2c/instantiating-devices.rst for more information. */ #include diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c index d8c91c2cb8cf..9ae0dc28b9cf 100644 --- a/drivers/hwmon/smm665.c +++ b/drivers/hwmon/smm665.c @@ -197,7 +197,7 @@ static int smm665_read_adc(struct smm665_data *data, int adc) if (rv != -ENXIO) { /* * We expect ENXIO to reflect NACK - * (per Documentation/i2c/fault-codes). + * (per Documentation/i2c/fault-codes.rst). * Everything else is an error. */ dev_dbg(&client->dev, diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index abedd55a1264..1474e57ecafc 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -54,7 +54,7 @@ config I2C_CHARDEV Say Y here to use i2c-* device files, usually found in the /dev directory on your system. They make it possible to have user-space programs use the I2C bus. Information on how to do this is - contained in the file . + contained in the file . This support is also available as a module. If so, the module will be called i2c-dev. @@ -107,7 +107,7 @@ config I2C_STUB especially for certain kinds of sensor chips. If you do build this module, be sure to read the notes and warnings - in . + in . If you don't know what to do here, definitely say N. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 09367fc014c3..22fcf554257b 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1206,7 +1206,7 @@ config I2C_PARPORT and makes it easier to add support for new devices. An adapter type parameter is now mandatory. Please read the file - Documentation/i2c/busses/i2c-parport for details. + Documentation/i2c/busses/i2c-parport.rst for details. Another driver exists, named i2c-parport-light, which doesn't depend on the parport driver. This is meant for embedded systems. Don't say diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f2956936c3f2..c2f087d20420 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -77,7 +77,7 @@ * SMBus Host Notify yes * Interrupt processing yes * - * See the file Documentation/i2c/busses/i2c-i801 for details. + * See the file Documentation/i2c/busses/i2c-i801.rst for details. */ #include diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index c82e78f57386..37347c93e8e0 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -125,7 +125,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, /* * Voluntarily dropping error code of kstrtou8 since all * error code that it could return are invalid according - * to Documentation/i2c/fault-codes. + * to Documentation/i2c/fault-codes.rst. */ if (kstrtou8(p + 1, 16, &data->byte)) return -EPROTO; diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index f26ed495d384..2e6dcf8ecbc9 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -2206,7 +2206,7 @@ static int i2c_detect_address(struct i2c_client *temp_client, dev_warn(&adapter->dev, "This adapter will soon drop class based instantiation of devices. " "Please make sure client 0x%02x gets instantiated by other means. " - "Check 'Documentation/i2c/instantiating-devices' for details.\n", + "Check 'Documentation/i2c/instantiating-devices.rst' for details.\n", info.addr); dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", @@ -2236,7 +2236,7 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) if (adapter->class == I2C_CLASS_DEPRECATED) { dev_dbg(&adapter->dev, "This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. " - "If you need it, check 'Documentation/i2c/instantiating-devices' for alternatives.\n", + "If you need it, check 'Documentation/i2c/instantiating-devices.rst' for alternatives.\n", driver->driver.name); return 0; } diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c index 8f99c005458a..d28974ad9e0e 100644 --- a/drivers/iio/dummy/iio_simple_dummy.c +++ b/drivers/iio/dummy/iio_simple_dummy.c @@ -693,7 +693,7 @@ static int iio_dummy_remove(struct iio_sw_device *swd) * Varies depending on bus type of the device. As there is no device * here, call probe directly. For information on device registration * i2c: - * Documentation/i2c/writing-clients + * Documentation/i2c/writing-clients.rst * spi: * Documentation/spi/spi-summary */ diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 225a8df1d4e9..367497914c10 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -14,7 +14,7 @@ */ /* * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section + * recommended in .../Documentation/i2c/writing-clients.rst section * "Sending and receiving", using SMBus level communication is preferred. */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index fa5552c2307b..c0a78c069117 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -521,7 +521,7 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info, * * The return codes from the @master_xfer{_atomic} fields should indicate the * type of error code that occurred during the transfer, as documented in the - * Kernel Documentation file Documentation/i2c/fault-codes. + * Kernel Documentation file Documentation/i2c/fault-codes.rst. */ struct i2c_algorithm { /* -- GitLab From f6ae22d64433fd8e08654adad7966299da931bb9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:19 -0300 Subject: [PATCH 1455/7155] docs: ipmb: place it at driver-api and convert to ReST No new doc should be added at the main Documentation/ directory. Instead, new docs should be added as ReST files, within the Kernel documentation body. Fixes: 51bd6f291583 ("Add support for IPMB driver") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/driver-api/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index 37ac052ded85..38e638abe3eb 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -76,6 +76,7 @@ available subsections can be seen below. dell_rbu edid eisa + ipmb isa isapnp generic-counter -- GitLab From 1ec779b9fabcdbfaa06971b5c2a4d9a6e4b45b3a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:20 -0300 Subject: [PATCH 1456/7155] docs: packing: move it to core-api book and adjust markups The packing.txt file was misplaced, as docs should be part of a documentation book, and not at the root dir. So, move it to the core-api directory and add to its index. Also, ensure that the file will be properly parsed and the bitmap ascii artwork will use a monotonic font. Fixes: 554aae35007e ("lib: Add support for generic packing operations") Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Vladimir Oltean Tested-by: Vladimir Oltean Reviewed-by: Mike Rapoport Signed-off-by: Jonathan Corbet --- Documentation/core-api/index.rst | 1 + .../{packing.txt => core-api/packing.rst} | 81 +++++++++++-------- MAINTAINERS | 2 +- 3 files changed, 51 insertions(+), 33 deletions(-) rename Documentation/{packing.txt => core-api/packing.rst} (61%) diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index da0ed972d224..dfd8fad1e1ec 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -25,6 +25,7 @@ Core utilities librs genalloc errseq + packing printk-formats circular-buffers generic-radix-tree diff --git a/Documentation/packing.txt b/Documentation/core-api/packing.rst similarity index 61% rename from Documentation/packing.txt rename to Documentation/core-api/packing.rst index f830c98645f1..d8c341fe383e 100644 --- a/Documentation/packing.txt +++ b/Documentation/core-api/packing.rst @@ -30,6 +30,7 @@ The solution ------------ This API deals with 2 basic operations: + - Packing a CPU-usable number into a memory buffer (with hardware constraints/quirks) - Unpacking a memory buffer (which has hardware constraints/quirks) @@ -49,10 +50,12 @@ What the examples show is where the logical bytes and bits sit. 1. Normally (no quirks), we would do it like this: -63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 -7 6 5 4 -31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -3 2 1 0 +:: + + 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + 7 6 5 4 + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + 3 2 1 0 That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the LSByte (0) of the u64 sits at memory offset 7. @@ -63,10 +66,12 @@ comments as "logical" notation. 2. If QUIRK_MSB_ON_THE_RIGHT is set, we do it like this: -56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 -7 6 5 4 -24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 -3 2 1 0 +:: + + 56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 + 7 6 5 4 + 24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 + 3 2 1 0 That is, QUIRK_MSB_ON_THE_RIGHT does not affect byte positioning, but inverts bit offsets inside a byte. @@ -74,10 +79,12 @@ inverts bit offsets inside a byte. 3. If QUIRK_LITTLE_ENDIAN is set, we do it like this: -39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 -4 5 6 7 -7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 -0 1 2 3 +:: + + 39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 + 4 5 6 7 + 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 + 0 1 2 3 Therefore, QUIRK_LITTLE_ENDIAN means that inside the memory region, every byte from each 4-byte word is placed at its mirrored position compared to @@ -86,18 +93,22 @@ the boundary of that word. 4. If QUIRK_MSB_ON_THE_RIGHT and QUIRK_LITTLE_ENDIAN are both set, we do it like this: -32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 -4 5 6 7 -0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -0 1 2 3 +:: + + 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + 4 5 6 7 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0 1 2 3 5. If just QUIRK_LSW32_IS_FIRST is set, we do it like this: -31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -3 2 1 0 -63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 -7 6 5 4 +:: + + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + 3 2 1 0 + 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + 7 6 5 4 In this case the 8 byte memory region is interpreted as follows: first 4 bytes correspond to the least significant 4-byte word, next 4 bytes to @@ -107,28 +118,34 @@ the more significant 4-byte word. 6. If QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like this: -24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 -3 2 1 0 -56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 -7 6 5 4 +:: + + 24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 + 3 2 1 0 + 56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 + 7 6 5 4 7. If QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like this: -7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 -0 1 2 3 -39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 -4 5 6 7 +:: + + 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 + 0 1 2 3 + 39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 + 4 5 6 7 8. If QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT are set, it looks like this: -0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -0 1 2 3 -32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 -4 5 6 7 +:: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0 1 2 3 + 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + 4 5 6 7 We always think of our offsets as if there were no quirk, and we translate diff --git a/MAINTAINERS b/MAINTAINERS index a3d5dd341088..11525de0bd16 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12099,7 +12099,7 @@ L: netdev@vger.kernel.org S: Supported F: lib/packing.c F: include/linux/packing.h -F: Documentation/packing.txt +F: Documentation/core-api/packing.rst PADATA PARALLEL EXECUTION MECHANISM M: Steffen Klassert -- GitLab From 76b5a6e8427159ad2b3b8764ebd6f3f5213be97e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:21 -0300 Subject: [PATCH 1457/7155] docs: admin-guide: add auxdisplay files to it after conversion to ReST Those two files describe userspace-faced information. While part of it might fit on uAPI, it sounds to me that the admin guide is the best place for them. Signed-off-by: Mauro Carvalho Chehab Acked-by: Miguel Ojeda Signed-off-by: Jonathan Corbet --- .../admin-guide/auxdisplay/cfag12864b.rst | 98 ++++++++++++++++ .../admin-guide/auxdisplay/index.rst | 16 +++ .../admin-guide/auxdisplay/ks0108.rst | 50 +++++++++ Documentation/admin-guide/index.rst | 1 + Documentation/auxdisplay/cfag12864b | 105 ------------------ Documentation/auxdisplay/ks0108 | 55 --------- MAINTAINERS | 2 +- drivers/auxdisplay/Kconfig | 2 +- 8 files changed, 167 insertions(+), 162 deletions(-) create mode 100644 Documentation/admin-guide/auxdisplay/cfag12864b.rst create mode 100644 Documentation/admin-guide/auxdisplay/index.rst create mode 100644 Documentation/admin-guide/auxdisplay/ks0108.rst delete mode 100644 Documentation/auxdisplay/cfag12864b delete mode 100644 Documentation/auxdisplay/ks0108 diff --git a/Documentation/admin-guide/auxdisplay/cfag12864b.rst b/Documentation/admin-guide/auxdisplay/cfag12864b.rst new file mode 100644 index 000000000000..18c2865bd322 --- /dev/null +++ b/Documentation/admin-guide/auxdisplay/cfag12864b.rst @@ -0,0 +1,98 @@ +=================================== +cfag12864b LCD Driver Documentation +=================================== + +:License: GPLv2 +:Author & Maintainer: Miguel Ojeda Sandonis +:Date: 2006-10-27 + + + +.. INDEX + + 1. DRIVER INFORMATION + 2. DEVICE INFORMATION + 3. WIRING + 4. USERSPACE PROGRAMMING + +1. Driver Information +--------------------- + +This driver supports a cfag12864b LCD. + + +2. Device Information +--------------------- + +:Manufacturer: Crystalfontz +:Device Name: Crystalfontz 12864b LCD Series +:Device Code: cfag12864b +:Webpage: http://www.crystalfontz.com +:Device Webpage: http://www.crystalfontz.com/products/12864b/ +:Type: LCD (Liquid Crystal Display) +:Width: 128 +:Height: 64 +:Colors: 2 (B/N) +:Controller: ks0108 +:Controllers: 2 +:Pages: 8 each controller +:Addresses: 64 each page +:Data size: 1 byte each address +:Memory size: 2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte + + +3. Wiring +--------- + +The cfag12864b LCD Series don't have official wiring. + +The common wiring is done to the parallel port as shown:: + + Parallel Port cfag12864b + + Name Pin# Pin# Name + + Strobe ( 1)------------------------------(17) Enable + Data 0 ( 2)------------------------------( 4) Data 0 + Data 1 ( 3)------------------------------( 5) Data 1 + Data 2 ( 4)------------------------------( 6) Data 2 + Data 3 ( 5)------------------------------( 7) Data 3 + Data 4 ( 6)------------------------------( 8) Data 4 + Data 5 ( 7)------------------------------( 9) Data 5 + Data 6 ( 8)------------------------------(10) Data 6 + Data 7 ( 9)------------------------------(11) Data 7 + (10) [+5v]---( 1) Vdd + (11) [GND]---( 2) Ground + (12) [+5v]---(14) Reset + (13) [GND]---(15) Read / Write + Line (14)------------------------------(13) Controller Select 1 + (15) + Init (16)------------------------------(12) Controller Select 2 + Select (17)------------------------------(16) Data / Instruction + Ground (18)---[GND] [+5v]---(19) LED + + Ground (19)---[GND] + Ground (20)---[GND] E A Values: + Ground (21)---[GND] [GND]---[P1]---(18) Vee - R = Resistor = 22 ohm + Ground (22)---[GND] | - P1 = Preset = 10 Kohm + Ground (23)---[GND] ---- S ------( 3) V0 - P2 = Preset = 1 Kohm + Ground (24)---[GND] | | + Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED - + + +4. Userspace Programming +------------------------ + +The cfag12864bfb describes a framebuffer device (/dev/fbX). + +It has a size of 1024 bytes = 1 Kbyte. +Each bit represents one pixel. If the bit is high, the pixel will +turn on. If the pixel is low, the pixel will turn off. + +You can use the framebuffer as a file: fopen, fwrite, fclose... +Although the LCD won't get updated until the next refresh time arrives. + +Also, you can mmap the framebuffer: open & mmap, munmap & close... +which is the best option for most uses. + +Check samples/auxdisplay/cfag12864b-example.c +for a real working userspace complete program with usage examples. diff --git a/Documentation/admin-guide/auxdisplay/index.rst b/Documentation/admin-guide/auxdisplay/index.rst new file mode 100644 index 000000000000..e466f0595248 --- /dev/null +++ b/Documentation/admin-guide/auxdisplay/index.rst @@ -0,0 +1,16 @@ +========================= +Auxiliary Display Support +========================= + +.. toctree:: + :maxdepth: 1 + + ks0108.rst + cfag12864b.rst + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/admin-guide/auxdisplay/ks0108.rst b/Documentation/admin-guide/auxdisplay/ks0108.rst new file mode 100644 index 000000000000..c0b7faf73136 --- /dev/null +++ b/Documentation/admin-guide/auxdisplay/ks0108.rst @@ -0,0 +1,50 @@ +========================================== +ks0108 LCD Controller Driver Documentation +========================================== + +:License: GPLv2 +:Author & Maintainer: Miguel Ojeda Sandonis +:Date: 2006-10-27 + + + +.. INDEX + + 1. DRIVER INFORMATION + 2. DEVICE INFORMATION + 3. WIRING + + +1. Driver Information +--------------------- + +This driver supports the ks0108 LCD controller. + + +2. Device Information +--------------------- + +:Manufacturer: Samsung +:Device Name: KS0108 LCD Controller +:Device Code: ks0108 +:Webpage: - +:Device Webpage: - +:Type: LCD Controller (Liquid Crystal Display Controller) +:Width: 64 +:Height: 64 +:Colors: 2 (B/N) +:Pages: 8 +:Addresses: 64 each page +:Data size: 1 byte each address +:Memory size: 8 * 64 * 1 = 512 bytes + + +3. Wiring +--------- + +The driver supports data parallel port wiring. + +If you aren't building LCD related hardware, you should check +your LCD specific wiring information in the same folder. + +For example, check Documentation/admin-guide/auxdisplay/cfag12864b.rst diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 592107a3295f..200e47820c37 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -100,6 +100,7 @@ configure specific aspects of kernel behavior to your liking. iostats kernel-per-CPU-kthreads laptops/index + auxdisplay/index lcd-panel-cgram ldm lockup-watchdogs diff --git a/Documentation/auxdisplay/cfag12864b b/Documentation/auxdisplay/cfag12864b deleted file mode 100644 index 12fd51b8de75..000000000000 --- a/Documentation/auxdisplay/cfag12864b +++ /dev/null @@ -1,105 +0,0 @@ - =================================== - cfag12864b LCD Driver Documentation - =================================== - -License: GPLv2 -Author & Maintainer: Miguel Ojeda Sandonis -Date: 2006-10-27 - - - --------- -0. INDEX --------- - - 1. DRIVER INFORMATION - 2. DEVICE INFORMATION - 3. WIRING - 4. USERSPACE PROGRAMMING - - ---------------------- -1. DRIVER INFORMATION ---------------------- - -This driver supports a cfag12864b LCD. - - ---------------------- -2. DEVICE INFORMATION ---------------------- - -Manufacturer: Crystalfontz -Device Name: Crystalfontz 12864b LCD Series -Device Code: cfag12864b -Webpage: http://www.crystalfontz.com -Device Webpage: http://www.crystalfontz.com/products/12864b/ -Type: LCD (Liquid Crystal Display) -Width: 128 -Height: 64 -Colors: 2 (B/N) -Controller: ks0108 -Controllers: 2 -Pages: 8 each controller -Addresses: 64 each page -Data size: 1 byte each address -Memory size: 2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte - - ---------- -3. WIRING ---------- - -The cfag12864b LCD Series don't have official wiring. - -The common wiring is done to the parallel port as shown: - -Parallel Port cfag12864b - - Name Pin# Pin# Name - -Strobe ( 1)------------------------------(17) Enable -Data 0 ( 2)------------------------------( 4) Data 0 -Data 1 ( 3)------------------------------( 5) Data 1 -Data 2 ( 4)------------------------------( 6) Data 2 -Data 3 ( 5)------------------------------( 7) Data 3 -Data 4 ( 6)------------------------------( 8) Data 4 -Data 5 ( 7)------------------------------( 9) Data 5 -Data 6 ( 8)------------------------------(10) Data 6 -Data 7 ( 9)------------------------------(11) Data 7 - (10) [+5v]---( 1) Vdd - (11) [GND]---( 2) Ground - (12) [+5v]---(14) Reset - (13) [GND]---(15) Read / Write - Line (14)------------------------------(13) Controller Select 1 - (15) - Init (16)------------------------------(12) Controller Select 2 -Select (17)------------------------------(16) Data / Instruction -Ground (18)---[GND] [+5v]---(19) LED + -Ground (19)---[GND] -Ground (20)---[GND] E A Values: -Ground (21)---[GND] [GND]---[P1]---(18) Vee - R = Resistor = 22 ohm -Ground (22)---[GND] | - P1 = Preset = 10 Kohm -Ground (23)---[GND] ---- S ------( 3) V0 - P2 = Preset = 1 Kohm -Ground (24)---[GND] | | -Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED - - - ------------------------- -4. USERSPACE PROGRAMMING ------------------------- - -The cfag12864bfb describes a framebuffer device (/dev/fbX). - -It has a size of 1024 bytes = 1 Kbyte. -Each bit represents one pixel. If the bit is high, the pixel will -turn on. If the pixel is low, the pixel will turn off. - -You can use the framebuffer as a file: fopen, fwrite, fclose... -Although the LCD won't get updated until the next refresh time arrives. - -Also, you can mmap the framebuffer: open & mmap, munmap & close... -which is the best option for most uses. - -Check samples/auxdisplay/cfag12864b-example.c -for a real working userspace complete program with usage examples. diff --git a/Documentation/auxdisplay/ks0108 b/Documentation/auxdisplay/ks0108 deleted file mode 100644 index 8ddda0c8ceef..000000000000 --- a/Documentation/auxdisplay/ks0108 +++ /dev/null @@ -1,55 +0,0 @@ - ========================================== - ks0108 LCD Controller Driver Documentation - ========================================== - -License: GPLv2 -Author & Maintainer: Miguel Ojeda Sandonis -Date: 2006-10-27 - - - --------- -0. INDEX --------- - - 1. DRIVER INFORMATION - 2. DEVICE INFORMATION - 3. WIRING - - ---------------------- -1. DRIVER INFORMATION ---------------------- - -This driver supports the ks0108 LCD controller. - - ---------------------- -2. DEVICE INFORMATION ---------------------- - -Manufacturer: Samsung -Device Name: KS0108 LCD Controller -Device Code: ks0108 -Webpage: - -Device Webpage: - -Type: LCD Controller (Liquid Crystal Display Controller) -Width: 64 -Height: 64 -Colors: 2 (B/N) -Pages: 8 -Addresses: 64 each page -Data size: 1 byte each address -Memory size: 8 * 64 * 1 = 512 bytes - - ---------- -3. WIRING ---------- - -The driver supports data parallel port wiring. - -If you aren't building LCD related hardware, you should check -your LCD specific wiring information in the same folder. - -For example, check Documentation/auxdisplay/cfag12864b. diff --git a/MAINTAINERS b/MAINTAINERS index 11525de0bd16..a27e36f491b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9001,7 +9001,7 @@ F: kernel/kprobes.c KS0108 LCD CONTROLLER DRIVER M: Miguel Ojeda Sandonis S: Maintained -F: Documentation/auxdisplay/ks0108 +F: Documentation/admin-guide/auxdisplay/ks0108.rst F: drivers/auxdisplay/ks0108.c F: include/linux/ks0108.h diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index dd61fdd400f0..6b476e663e80 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -97,7 +97,7 @@ config CFAG12864B say Y. You also need the ks0108 LCD Controller driver. For help about how to wire your LCD to the parallel port, - check Documentation/auxdisplay/cfag12864b + check Documentation/admin-guide/auxdisplay/cfag12864b.rst Depends on the x86 arch and the framebuffer support. -- GitLab From 6d6486a0c59759681e75d1a2bd6684c501fcbd0e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:22 -0300 Subject: [PATCH 1458/7155] docs: README.buddha: convert to ReST and add to m68k book Adjust the file for it to be properly parsed by Sphinx, adding it to the index of the book it belongs. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- .../m68k/{README.buddha => buddha-driver.rst} | 95 +++++++++---------- Documentation/m68k/index.rst | 1 + 2 files changed, 48 insertions(+), 48 deletions(-) rename Documentation/m68k/{README.buddha => buddha-driver.rst} (73%) diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/buddha-driver.rst similarity index 73% rename from Documentation/m68k/README.buddha rename to Documentation/m68k/buddha-driver.rst index 3ea9827ba3c7..20e401413991 100644 --- a/Documentation/m68k/README.buddha +++ b/Documentation/m68k/buddha-driver.rst @@ -1,3 +1,6 @@ +===================================== +Amiga Buddha and Catweasel IDE Driver +===================================== The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by Geert Uytterhoeven based on the following specifications: @@ -12,12 +15,12 @@ described in their manuals, no tricks have been used (for example leaving some address lines out of the equations...). If you want to configure the board yourself (for example let a Linux kernel configure the card), look at the Commodore -Docs. Reading the nibbles should give this information: +Docs. Reading the nibbles should give this information:: -Vendor number: 4626 ($1212) -product number: 0 (42 for Catweasel Z-II) -Serial number: 0 -Rom-vector: $1000 + Vendor number: 4626 ($1212) + product number: 0 (42 for Catweasel Z-II) + Serial number: 0 + Rom-vector: $1000 The card should be a Z-II board, size 64K, not for freemem list, Rom-Vektor is valid, no second Autoconfig-board on the @@ -34,6 +37,7 @@ otherwise your chance is only 1:16 to find the board :-). The local memory-map is even active when mapped to $e8: +============== =========================================== $0-$7e Autokonfig-space, see Z-II docs. $80-$7fd reserved @@ -50,50 +54,51 @@ $a00-$aff IDE-Select 2 (Port 1, Register set 0) $b00-$bff IDE-Select 3 (Port 1, Register set 1) $c00-$cff IDE-Select 4 (Port 2, Register set 0, - Catweasel only!) + Catweasel only!) $d00-$dff IDE-Select 5 (Port 3, Register set 1, - Catweasel only!) + Catweasel only!) -$e00-$eff local expansion port, on Catweasel Z-II the +$e00-$eff local expansion port, on Catweasel Z-II the Catweasel registers are also mapped here. Never touch, use multidisk.device! - -$f00 read only, Byte-access: Bit 7 shows the - level of the IRQ-line of IDE port 0. + +$f00 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 0. $f01-$f3f mirror of $f00 -$f40 read only, Byte-access: Bit 7 shows the - level of the IRQ-line of IDE port 1. +$f40 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 1. $f41-$f7f mirror of $f40 -$f80 read only, Byte-access: Bit 7 shows the - level of the IRQ-line of IDE port 2. +$f80 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 2. (Catweasel only!) $f81-$fbf mirror of $f80 $fc0 write-only: Writing any value to this - register enables IRQs to be passed from the - IDE ports to the Zorro bus. This mechanism - has been implemented to be compatible with + register enables IRQs to be passed from the + IDE ports to the Zorro bus. This mechanism + has been implemented to be compatible with harddisks that are either defective or have - a buggy firmware and pull the IRQ line up - while starting up. If interrupts would - always be passed to the bus, the computer - might not start up. Once enabled, this flag - can not be disabled again. The level of the - flag can not be determined by software + a buggy firmware and pull the IRQ line up + while starting up. If interrupts would + always be passed to the bus, the computer + might not start up. Once enabled, this flag + can not be disabled again. The level of the + flag can not be determined by software (what for? Write to me if it's necessary!). $fc1-$fff mirror of $fc0 $1000-$ffff Buddha-Rom with offset $1000 in the rom - chip. The addresses $0 to $fff of the rom + chip. The addresses $0 to $fff of the rom chip cannot be read. Rom is Byte-wide and mapped to even addresses. +============== =========================================== The IDE ports issue an INT2. You can read the level of the IRQ-lines of the IDE-ports by reading from the three (two @@ -128,7 +133,8 @@ must always be set to 1 to be compatible with later Buddha versions (if I'll ever update this one). I presume that I'll never use the lower four bits, but they have to be set to 1 by definition. - The values in this table have to be shifted 5 bits to the + +The values in this table have to be shifted 5 bits to the left and or'd with $1f (this sets the lower 5 bits). All the timings have in common: Select and IOR/IOW rise at @@ -138,44 +144,36 @@ values are no multiple of 71. One clock-cycle is 71ns long (exactly 70,5 at 14,18 Mhz on PAL systems). value 0 (Default after reset) - -497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles) -(same timing as the Amiga 1200 does on it's IDE port without -accelerator card) + 497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles) + (same timing as the Amiga 1200 does on it's IDE port without + accelerator card) value 1 - -639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles) + 639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles) value 2 - -781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles) + 781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles) value 3 - -355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) + 355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) value 4 - -355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles) + 355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles) value 5 - -355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles) + 355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles) value 6 - -1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles) + 1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles) value 7 - -355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) + 355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) When accessing IDE registers with A6=1 (for example $84x), the timing will always be mode 0 8-bit compatible, no matter what you have selected in the speed register: -781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive. +781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive. All the timings with a very short select-signal (the 355ns fast accesses) depend on the accelerator card used in the @@ -204,7 +202,8 @@ always shows a "no IRQ here" on the Buddha, and accesses to the third IDE port are going into data's Nirwana on the Buddha. - Jens Schönfeld february 19th, 1997 - updated may 27th, 1997 - eMail: sysop@nostlgic.tng.oche.de +Jens Schönfeld february 19th, 1997 + +updated may 27th, 1997 +eMail: sysop@nostlgic.tng.oche.de diff --git a/Documentation/m68k/index.rst b/Documentation/m68k/index.rst index 3a5ba7fe1703..b89cb6a86d9b 100644 --- a/Documentation/m68k/index.rst +++ b/Documentation/m68k/index.rst @@ -8,6 +8,7 @@ m68k Architecture :maxdepth: 2 kernel-options + buddha-driver .. only:: subproject and html -- GitLab From e77e9187ae1caf2d83dd5e7f0c1466254b644a4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:23 -0300 Subject: [PATCH 1459/7155] docs: parisc: convert to ReST and add to documentation body Manually convert the two PA-RISC documents to ReST, adding them to the Linux documentation body. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + .../parisc/{debugging => debugging.rst} | 7 +++ Documentation/parisc/index.rst | 18 ++++++ .../parisc/{registers => registers.rst} | 59 +++++++++++++------ 4 files changed, 68 insertions(+), 17 deletions(-) rename Documentation/parisc/{debugging => debugging.rst} (94%) create mode 100644 Documentation/parisc/index.rst rename Documentation/parisc/{registers => registers.rst} (70%) diff --git a/Documentation/index.rst b/Documentation/index.rst index 9b45af84fd29..771affb4dd3a 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -147,6 +147,7 @@ implementation. ia64/index m68k/index powerpc/index + parisc/index riscv/index s390/index sh/index diff --git a/Documentation/parisc/debugging b/Documentation/parisc/debugging.rst similarity index 94% rename from Documentation/parisc/debugging rename to Documentation/parisc/debugging.rst index 7d75223fa18d..de1b60402c5b 100644 --- a/Documentation/parisc/debugging +++ b/Documentation/parisc/debugging.rst @@ -1,8 +1,13 @@ +================= +PA-RISC Debugging +================= + okay, here are some hints for debugging the lower-level parts of linux/parisc. 1. Absolute addresses +===================== A lot of the assembly code currently runs in real mode, which means absolute addresses are used instead of virtual addresses as in the @@ -12,6 +17,7 @@ currently). 2. HPMCs +======== When real-mode code tries to access non-existent memory, you'll get an HPMC instead of a kernel oops. To debug an HPMC, try to find @@ -27,6 +33,7 @@ access it. 3. Q bit fun +============ Certain, very critical code has to clear the Q bit in the PSW. What happens when the Q bit is cleared is the CPU does not update the diff --git a/Documentation/parisc/index.rst b/Documentation/parisc/index.rst new file mode 100644 index 000000000000..aa3ee0470425 --- /dev/null +++ b/Documentation/parisc/index.rst @@ -0,0 +1,18 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +PA-RISC Architecture +==================== + +.. toctree:: + :maxdepth: 2 + + debugging + registers + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/parisc/registers b/Documentation/parisc/registers.rst similarity index 70% rename from Documentation/parisc/registers rename to Documentation/parisc/registers.rst index 10c7d1730f5d..59c8ecf3e856 100644 --- a/Documentation/parisc/registers +++ b/Documentation/parisc/registers.rst @@ -1,11 +1,16 @@ +================================ Register Usage for Linux/PA-RISC +================================ [ an asterisk is used for planned usage which is currently unimplemented ] - General Registers as specified by ABI +General Registers as specified by ABI +===================================== - Control Registers +Control Registers +----------------- +=============================== =============================================== CR 0 (Recovery Counter) used for ptrace CR 1-CR 7(undefined) unused CR 8 (Protection ID) per-process value* @@ -29,26 +34,35 @@ CR28 (TR 4) not used CR29 (TR 5) not used CR30 (TR 6) current / 0 CR31 (TR 7) Temporary register, used in various places +=============================== =============================================== - Space Registers (kernel mode) +Space Registers (kernel mode) +----------------------------- +=============================== =============================================== SR0 temporary space register SR4-SR7 set to 0 SR1 temporary space register SR2 kernel should not clobber this SR3 used for userspace accesses (current process) +=============================== =============================================== - Space Registers (user mode) +Space Registers (user mode) +--------------------------- +=============================== =============================================== SR0 temporary space register SR1 temporary space register SR2 holds space of linux gateway page SR3 holds user address space value while in kernel SR4-SR7 Defines short address space for user/kernel +=============================== =============================================== - Processor Status Word +Processor Status Word +--------------------- +=============================== =============================================== W (64-bit addresses) 0 E (Little-endian) 0 S (Secure Interval Timer) 0 @@ -69,15 +83,19 @@ Q (collect interruption state) 1 (0 in code directly preceding an rfi) P (Protection Identifiers) 1* D (Data address translation) 1, 0 while executing real-mode code I (external interrupt mask) used by cli()/sti() macros +=============================== =============================================== - "Invisible" Registers +"Invisible" Registers +--------------------- +=============================== =============================================== PSW default W value 0 PSW default E value 0 Shadow Registers used by interruption handler code TOC enable bit 1 +=============================== =============================================== -========================================================================= +------------------------------------------------------------------------- The PA-RISC architecture defines 7 registers as "shadow registers". Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce @@ -85,7 +103,8 @@ the state save and restore time by eliminating the need for general register (GR) saves and restores in interruption handlers. Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25. -========================================================================= +------------------------------------------------------------------------- + Register usage notes, originally from John Marvin, with some additional notes from Randolph Chung. @@ -96,10 +115,12 @@ course, you need to save them if you care about them, before calling another procedure. Some of the above registers do have special meanings that you should be aware of: - r1: The addil instruction is hardwired to place its result in r1, + r1: + The addil instruction is hardwired to place its result in r1, so if you use that instruction be aware of that. - r2: This is the return pointer. In general you don't want to + r2: + This is the return pointer. In general you don't want to use this, since you need the pointer to get back to your caller. However, it is grouped with this set of registers since the caller can't rely on the value being the same @@ -107,23 +128,27 @@ that you should be aware of: and return through that register after trashing r2, and that should not cause a problem for the calling routine. - r19-r22: these are generally regarded as temporary registers. + r19-r22: + these are generally regarded as temporary registers. Note that in 64 bit they are arg7-arg4. - r23-r26: these are arg3-arg0, i.e. you can use them if you + r23-r26: + these are arg3-arg0, i.e. you can use them if you don't care about the values that were passed in anymore. - r28,r29: are ret0 and ret1. They are what you pass return values + r28,r29: + are ret0 and ret1. They are what you pass return values in. r28 is the primary return. When returning small structures r29 may also be used to pass data back to the caller. - r30: stack pointer + r30: + stack pointer - r31: the ble instruction puts the return pointer in here. + r31: + the ble instruction puts the return pointer in here. -r3-r18,r27,r30 need to be saved and restored. r3-r18 are just + r3-r18,r27,r30 need to be saved and restored. r3-r18 are just general purpose registers. r27 is the data pointer, and is used to make references to global variables easier. r30 is the stack pointer. - -- GitLab From 32fc3cd8ba2375b0ee385a42ba2a1aad5547816e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:24 -0300 Subject: [PATCH 1460/7155] docs: openrisc: convert to ReST and add to documentation body Manually convert the two openRisc documents to ReST, adding them to the Linux documentation body. Signed-off-by: Mauro Carvalho Chehab Acked-by: Stafford Horne Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + Documentation/openrisc/index.rst | 18 +++++++++++++ .../openrisc/{README => openrisc_port.rst} | 25 +++++++++++++------ Documentation/openrisc/{TODO => todo.rst} | 9 ++++--- 4 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 Documentation/openrisc/index.rst rename Documentation/openrisc/{README => openrisc_port.rst} (80%) rename Documentation/openrisc/{TODO => todo.rst} (78%) diff --git a/Documentation/index.rst b/Documentation/index.rst index 771affb4dd3a..14ccbc499683 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -147,6 +147,7 @@ implementation. ia64/index m68k/index powerpc/index + openrisc/index parisc/index riscv/index s390/index diff --git a/Documentation/openrisc/index.rst b/Documentation/openrisc/index.rst new file mode 100644 index 000000000000..748b3eea1707 --- /dev/null +++ b/Documentation/openrisc/index.rst @@ -0,0 +1,18 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================== +OpenRISC Architecture +===================== + +.. toctree:: + :maxdepth: 2 + + openrisc_port + todo + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/openrisc/README b/Documentation/openrisc/openrisc_port.rst similarity index 80% rename from Documentation/openrisc/README rename to Documentation/openrisc/openrisc_port.rst index 777a893d533d..a18747a8d191 100644 --- a/Documentation/openrisc/README +++ b/Documentation/openrisc/openrisc_port.rst @@ -1,3 +1,4 @@ +============== OpenRISC Linux ============== @@ -6,8 +7,10 @@ target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k). For information about OpenRISC processors and ongoing development: + ======= ============================= website http://openrisc.io email openrisc@lists.librecores.org + ======= ============================= --------------------------------------------------------------------- @@ -24,13 +27,15 @@ Toolchain binaries can be obtained from openrisc.io or our github releases page. Instructions for building the different toolchains can be found on openrisc.io or Stafford's toolchain build and release scripts. + ========== ================================================= binaries https://github.com/openrisc/or1k-gcc/releases toolchains https://openrisc.io/software building https://github.com/stffrdhrn/or1k-toolchain-build + ========== ================================================= 2) Building -Build the Linux kernel as usual +Build the Linux kernel as usual:: make ARCH=openrisc defconfig make ARCH=openrisc @@ -43,6 +48,8 @@ development board with the OpenRISC SoC. During the build FPGA RTL is code downloaded from the FuseSoC IP cores repository and built using the FPGA vendor tools. Binaries are loaded onto the board with openocd. +:: + git clone https://github.com/olofk/fusesoc cd fusesoc sudo pip install -e . @@ -65,7 +72,9 @@ platform. Please follow the OpenRISC instructions on the QEMU website to get Linux running on QEMU. You can build QEMU yourself, but your Linux distribution likely provides binary packages to support OpenRISC. + ============= ====================================================== qemu openrisc https://wiki.qemu.org/Documentation/Platforms/OpenRISC + ============= ====================================================== --------------------------------------------------------------------- @@ -75,36 +84,38 @@ Terminology In the code, the following particles are used on symbols to limit the scope to more or less specific processor implementations: +========= ======================================= openrisc: the OpenRISC class of processors or1k: the OpenRISC 1000 family of processors or1200: the OpenRISC 1200 processor +========= ======================================= --------------------------------------------------------------------- History ======== -18. 11. 2003 Matjaz Breskvar (phoenix@bsemi.com) +18-11-2003 Matjaz Breskvar (phoenix@bsemi.com) initial port of linux to OpenRISC/or32 architecture. all the core stuff is implemented and seams usable. -08. 12. 2003 Matjaz Breskvar (phoenix@bsemi.com) +08-12-2003 Matjaz Breskvar (phoenix@bsemi.com) complete change of TLB miss handling. rewrite of exceptions handling. fully functional sash-3.6 in default initrd. a much improved version with changes all around. -10. 04. 2004 Matjaz Breskvar (phoenix@bsemi.com) +10-04-2004 Matjaz Breskvar (phoenix@bsemi.com) alot of bugfixes all over. ethernet support, functional http and telnet servers. running many standard linux apps. -26. 06. 2004 Matjaz Breskvar (phoenix@bsemi.com) +26-06-2004 Matjaz Breskvar (phoenix@bsemi.com) port to 2.6.x -30. 11. 2004 Matjaz Breskvar (phoenix@bsemi.com) +30-11-2004 Matjaz Breskvar (phoenix@bsemi.com) lots of bugfixes and enhancments. added opencores framebuffer driver. -09. 10. 2010 Jonas Bonn (jonas@southpole.se) +09-10-2010 Jonas Bonn (jonas@southpole.se) major rewrite to bring up to par with upstream Linux 2.6.36 diff --git a/Documentation/openrisc/TODO b/Documentation/openrisc/todo.rst similarity index 78% rename from Documentation/openrisc/TODO rename to Documentation/openrisc/todo.rst index c43d4e1d14eb..420b18b87eda 100644 --- a/Documentation/openrisc/TODO +++ b/Documentation/openrisc/todo.rst @@ -1,12 +1,15 @@ +==== +TODO +==== + The OpenRISC Linux port is fully functional and has been tracking upstream since 2.6.35. There are, however, remaining items to be completed within the coming months. Here's a list of known-to-be-less-than-stellar items that are due for investigation shortly, i.e. our TODO list: --- Implement the rest of the DMA API... dma_map_sg, etc. +- Implement the rest of the DMA API... dma_map_sg, etc. --- Finish the renaming cleanup... there are references to or32 in the code +- Finish the renaming cleanup... there are references to or32 in the code which was an older name for the architecture. The name we've settled on is or1k and this change is slowly trickling through the stack. For the time being, or32 is equivalent to or1k. - -- GitLab From 5a5e045bb3b839405e3a58b02a3333d33812214c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:25 -0300 Subject: [PATCH 1461/7155] docs: isdn: convert to ReST and add to kAPI bookset The ISDN documentation is a mix of admin guide, uAPI and kAPI. Ideally, it should be split. Yet, not sure if it would worth the troble. Anyway, we have the same kind of mix on several drivers specific documentation. So, just like the others, keep the directory at the root Documentation/ tree, just adding a pointer to it at the kAPI section, as the documentation was written with the Kernel developers in mind. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + .../isdn/{README.avmb1 => avmb1.rst} | 229 +++++++++----- Documentation/isdn/{CREDITS => credits.rst} | 7 +- .../isdn/{README.gigaset => gigaset.rst} | 292 +++++++++++------- .../isdn/{README.hysdn => hysdn.rst} | 125 ++++---- Documentation/isdn/index.rst | 24 ++ .../{INTERFACE.CAPI => interface_capi.rst} | 174 +++++++---- .../isdn/{README.mISDN => m_isdn.rst} | 5 +- drivers/staging/isdn/hysdn/Kconfig | 2 +- 9 files changed, 532 insertions(+), 327 deletions(-) rename Documentation/isdn/{README.avmb1 => avmb1.rst} (50%) rename Documentation/isdn/{CREDITS => credits.rst} (96%) rename Documentation/isdn/{README.gigaset => gigaset.rst} (74%) rename Documentation/isdn/{README.hysdn => hysdn.rst} (80%) create mode 100644 Documentation/isdn/index.rst rename Documentation/isdn/{INTERFACE.CAPI => interface_capi.rst} (75%) rename Documentation/isdn/{README.mISDN => m_isdn.rst} (89%) diff --git a/Documentation/index.rst b/Documentation/index.rst index 14ccbc499683..cd50e82710e0 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -106,6 +106,7 @@ needed). hid/index i2c/index iio/index + isdn/index infiniband/index leds/index media/index diff --git a/Documentation/isdn/README.avmb1 b/Documentation/isdn/avmb1.rst similarity index 50% rename from Documentation/isdn/README.avmb1 rename to Documentation/isdn/avmb1.rst index 9e075484ef1e..de3961e67553 100644 --- a/Documentation/isdn/README.avmb1 +++ b/Documentation/isdn/avmb1.rst @@ -1,4 +1,6 @@ -Driver for active AVM Controller. +================================ +Driver for active AVM Controller +================================ The driver provides a kernel capi2.0 Interface (kernelcapi) and on top of this a User-Level-CAPI2.0-interface (capi) @@ -11,25 +13,28 @@ The command avmcapictrl is part of the isdn4k-utils. t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware Currently supported cards: - B1 ISA (all versions) - B1 PCI - T1/T1B (HEMA card) - M1 - M2 - B1 PCMCIA + + - B1 ISA (all versions) + - B1 PCI + - T1/T1B (HEMA card) + - M1 + - M2 + - B1 PCMCIA Installing ---------- You need at least /dev/capi20 to load the firmware. -mknod /dev/capi20 c 68 0 -mknod /dev/capi20.00 c 68 1 -mknod /dev/capi20.01 c 68 2 -. -. -. -mknod /dev/capi20.19 c 68 20 +:: + + mknod /dev/capi20 c 68 0 + mknod /dev/capi20.00 c 68 1 + mknod /dev/capi20.01 c 68 2 + . + . + . + mknod /dev/capi20.19 c 68 20 Running ------- @@ -38,45 +43,58 @@ To use the card you need the t4-files to download the firmware. AVM GmbH provides several t4-files for the different D-channel protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn. -if you configure as modules load the modules this way: +if you configure as modules load the modules this way:: + + insmod /lib/modules/current/misc/capiutil.o + insmod /lib/modules/current/misc/b1.o + insmod /lib/modules/current/misc/kernelcapi.o + insmod /lib/modules/current/misc/capidrv.o + insmod /lib/modules/current/misc/capi.o -insmod /lib/modules/current/misc/capiutil.o -insmod /lib/modules/current/misc/b1.o -insmod /lib/modules/current/misc/kernelcapi.o -insmod /lib/modules/current/misc/capidrv.o -insmod /lib/modules/current/misc/capi.o +if you have an B1-PCI card load the module b1pci.o:: -if you have an B1-PCI card load the module b1pci.o -insmod /lib/modules/current/misc/b1pci.o -and load the firmware with -avmcapictrl load /lib/isdn/b1.t4 1 + insmod /lib/modules/current/misc/b1pci.o + +and load the firmware with:: + + avmcapictrl load /lib/isdn/b1.t4 1 if you have an B1-ISA card load the module b1isa.o -and add the card by calling -avmcapictrl add 0x150 15 -and load the firmware by calling -avmcapictrl load /lib/isdn/b1.t4 1 +and add the card by calling:: + + avmcapictrl add 0x150 15 + +and load the firmware by calling:: + + avmcapictrl load /lib/isdn/b1.t4 1 if you have an T1-ISA card load the module t1isa.o -and add the card by calling -avmcapictrl add 0x450 15 T1 0 -and load the firmware by calling -avmcapictrl load /lib/isdn/t1.t4 1 +and add the card by calling:: + + avmcapictrl add 0x450 15 T1 0 + +and load the firmware by calling:: + + avmcapictrl load /lib/isdn/t1.t4 1 if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o before you insert the card. Leased Lines with B1 -------------------- + Init card and load firmware. + For an D64S use "FV: 1" as phone number + For an D64S2 use "FV: 1" and "FV: 2" for multilink or "FV: 1,2" to use CAPI channel bundling. /proc-Interface ----------------- -/proc/capi: +/proc/capi:: + dr-xr-xr-x 2 root root 0 Jul 1 14:03 . dr-xr-xr-x 82 root root 0 Jun 30 19:08 .. -r--r--r-- 1 root root 0 Jul 1 14:03 applications @@ -91,84 +109,124 @@ or "FV: 1,2" to use CAPI channel bundling. /proc/capi/applications: applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen - level3cnt: capi_register parameter - datablkcnt: capi_register parameter - ncci-cnt: current number of nccis (connections) - recvqueuelen: number of messages on receive queue - for example: -1 -2 16 2048 1 0 -2 2 7 2048 1 0 + level3cnt: + capi_register parameter + datablkcnt: + capi_register parameter + ncci-cnt: + current number of nccis (connections) + recvqueuelen: + number of messages on receive queue + + for example:: + + 1 -2 16 2048 1 0 + 2 2 7 2048 1 0 /proc/capi/applstats: applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg - recvctlmsg: capi messages received without DATA_B3_IND - recvdatamsg: capi DATA_B3_IND received - sentctlmsg: capi messages sent without DATA_B3_REQ - sentdatamsg: capi DATA_B3_REQ sent - for example: -1 2057 1699 1721 1699 + recvctlmsg: + capi messages received without DATA_B3_IND + recvdatamsg: + capi DATA_B3_IND received + sentctlmsg: + capi messages sent without DATA_B3_REQ + sentdatamsg: + capi DATA_B3_REQ sent + + for example:: + + 1 2057 1699 1721 1699 /proc/capi/capi20: statistics of capi.o (/dev/capi20) minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - minor: minor device number of capi device - nopen: number of calls to devices open - nrecvdropmsg: capi messages dropped (messages in recvqueue in close) - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent - - for example: -1 2 18 0 16 2 + minor: + minor device number of capi device + nopen: + number of calls to devices open + nrecvdropmsg: + capi messages dropped (messages in recvqueue in close) + nrecvctlmsg: + capi messages received without DATA_B3_IND + nrecvdatamsg: + capi DATA_B3_IND received + nsentctlmsg: + capi messages sent without DATA_B3_REQ + nsentdatamsg: + capi DATA_B3_REQ sent + + for example:: + + 1 2 18 0 16 2 /proc/capi/capidrv: statistics of capidrv.o (capi messages) nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent + nrecvctlmsg: + capi messages received without DATA_B3_IND + nrecvdatamsg: + capi DATA_B3_IND received + nsentctlmsg: + capi messages sent without DATA_B3_REQ + nsentdatamsg: + capi DATA_B3_REQ sent + for example: -2780 2226 2256 2226 + 2780 2226 2256 2226 /proc/capi/controller: controller drivername state cardname controllerinfo - for example: -1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 -2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 -3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 + + for example:: + + 1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 + 2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 + 3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 /proc/capi/contrstats: controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent - for example: -1 2845 2272 2310 2274 -2 2 0 2 0 -3 2 0 2 0 + nrecvctlmsg: + capi messages received without DATA_B3_IND + nrecvdatamsg: + capi DATA_B3_IND received + nsentctlmsg: + capi messages sent without DATA_B3_REQ + nsentdatamsg: + capi DATA_B3_REQ sent + + for example:: + + 1 2845 2272 2310 2274 + 2 2 0 2 0 + 3 2 0 2 0 /proc/capi/driver: drivername ncontroller - for example: -b1pci 1 -t1isa 1 -b1pcmcia 1 -b1isa 0 + + for example:: + + b1pci 1 + t1isa 1 + b1pcmcia 1 + b1isa 0 /proc/capi/ncci: apllid ncci winsize sendwindow - for example: -1 0x10101 8 0 + + for example:: + + 1 0x10101 8 0 /proc/capi/users: kernelmodules that use the kernelcapi. name - for example: -capidrv -capi20 + + for example:: + + capidrv + capi20 Questions --------- + Check out the FAQ (ftp.isdn4linux.de) or subscribe to the linux-avmb1@calle.in-berlin.de mailing list by sending a mail to majordomo@calle.in-berlin.de with @@ -178,9 +236,10 @@ in the body. German documentation and several scripts can be found at ftp://ftp.avm.de/cardware/b1/linux/ -Bugs +Bugs ---- -If you find any please let me know. + +If you find any please let me know. Enjoy, diff --git a/Documentation/isdn/CREDITS b/Documentation/isdn/credits.rst similarity index 96% rename from Documentation/isdn/CREDITS rename to Documentation/isdn/credits.rst index c1679e913fca..319323f2091f 100644 --- a/Documentation/isdn/CREDITS +++ b/Documentation/isdn/credits.rst @@ -1,3 +1,7 @@ +======= +Credits +======= + I want to thank all who contributed to this project and especially to: (in alphabetical order) @@ -19,7 +23,7 @@ Matthias Hessler (hessler@isdn4linux.de) For creating and maintaining the FAQ. Bernhard Hailer (Bernhard.Hailer@lrz.uni-muenchen.de) - For creating the FAQ, and the leafsite HOWTO. + For creating the FAQ, and the leafsite HOWTO. Michael 'Ghandi' Herold (michael@abadonna.franken.de) For contribution of the vbox answering machine. @@ -67,4 +71,3 @@ Gerhard 'Fido' Schneider (fido@wuff.mayn.de) Thomas Uhl (uhl@think.de) For distributing the cards. For pushing me to work ;-) - diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/gigaset.rst similarity index 74% rename from Documentation/isdn/README.gigaset rename to Documentation/isdn/gigaset.rst index f6184b637182..98b4ec521c51 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/gigaset.rst @@ -1,33 +1,36 @@ +========================== GigaSet 307x Device Driver ========================== 1. Requirements - ------------ +================= + 1.1. Hardware - -------- +------------- + This driver supports the connection of the Gigaset 307x/417x family of ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB connection. The following devices are reported to be compatible: Bases: - Siemens Gigaset 3070/3075 isdn - Siemens Gigaset 4170/4175 isdn - Siemens Gigaset SX205/255 - Siemens Gigaset SX353 - T-Com Sinus 45 [AB] isdn - T-Com Sinus 721X[A] [SE] - Vox Chicago 390 ISDN (KPN Telecom) + - Siemens Gigaset 3070/3075 isdn + - Siemens Gigaset 4170/4175 isdn + - Siemens Gigaset SX205/255 + - Siemens Gigaset SX353 + - T-Com Sinus 45 [AB] isdn + - T-Com Sinus 721X[A] [SE] + - Vox Chicago 390 ISDN (KPN Telecom) RS232 data boxes: - Siemens Gigaset M101 Data - T-Com Sinus 45 Data 1 + - Siemens Gigaset M101 Data + - T-Com Sinus 45 Data 1 USB data boxes: - Siemens Gigaset M105 Data - Siemens Gigaset USB Adapter DECT - T-Com Sinus 45 Data 2 - T-Com Sinus 721 data - Chicago 390 USB (KPN) + - Siemens Gigaset M105 Data + - Siemens Gigaset USB Adapter DECT + - T-Com Sinus 45 Data 2 + - T-Com Sinus 721 data + - Chicago 390 USB (KPN) See also http://www.erbze.info/sinus_gigaset.htm (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) and @@ -37,17 +40,21 @@ GigaSet 307x Device Driver with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.5.) If you have another device that works with our driver, please let us know. - Chances of getting an USB device to work are good if the output of - lsusb - at the command line contains one of the following: - ID 0681:0001 - ID 0681:0002 - ID 0681:0009 - ID 0681:0021 - ID 0681:0022 + Chances of getting an USB device to work are good if the output of:: + + lsusb + + at the command line contains one of the following:: + + ID 0681:0001 + ID 0681:0002 + ID 0681:0009 + ID 0681:0021 + ID 0681:0022 1.2. Software - -------- +------------- + The driver works with the Kernel CAPI subsystem and can be used with any software which is able to use CAPI 2.0 for ISDN connections (voice or data). @@ -58,9 +65,11 @@ GigaSet 307x Device Driver 2. How to use the driver - --------------------- +========================== + 2.1. Modules - ------- +------------ + For the devices to work, the proper kernel modules have to be loaded. This normally happens automatically when the system detects the USB device (base, M105) or when the line discipline is attached (M101). It @@ -71,13 +80,17 @@ GigaSet 307x Device Driver which uses the regular serial port driver to access the device, and must therefore be attached to the serial device to which the M101 is connected. The ldattach(8) command (included in util-linux-ng release 2.14 or later) - can be used for that purpose, for example: + can be used for that purpose, for example:: + ldattach GIGASET_M101 /dev/ttyS1 + This will open the device file, attach the line discipline to it, and then sleep in the background, keeping the device open so that the line discipline remains active. To deactivate it, kill the daemon, for example - with + with:: + killall ldattach + before disconnecting the device. To have this happen automatically at system startup/shutdown on an LSB compatible system, create and activate an appropriate LSB startup script /etc/init.d/gigaset. (The init name @@ -86,9 +99,10 @@ GigaSet 307x Device Driver The modules accept the following parameters: - Module Parameter Meaning + =============== ========== ========================================== + Module Parameter Meaning - gigaset debug debug level (see section 3.2.) + gigaset debug debug level (see section 3.2.) startmode initial operation mode (see section 2.5.): bas_gigaset ) 1=CAPI (default), 0=Unimodem @@ -96,11 +110,14 @@ GigaSet 307x Device Driver usb_gigaset ) cidmode initial Call-ID mode setting (see section 2.5.): 1=on (default), 0=off + =============== ========== ========================================== + Depending on your distribution you may want to create a separate module configuration file like /etc/modprobe.d/gigaset.conf for these. 2.2. Device nodes for user space programs - ------------------------------------ +----------------------------------------- + The device can be accessed from user space (eg. by the user space tools mentioned in 1.2.) through the device nodes: @@ -113,46 +130,56 @@ GigaSet 307x Device Driver You can also set a "default device" for the user space tools to use when no device node is given as parameter, by creating a symlink /dev/ttyG to - one of them, eg.: + one of them, eg.:: ln -s /dev/ttyGB0 /dev/ttyG The devices accept the following device specific ioctl calls (defined in gigaset_dev.h): - ioctl(int fd, GIGASET_REDIR, int *cmd); + ``ioctl(int fd, GIGASET_REDIR, int *cmd);`` + If cmd==1, the device is set to be controlled exclusively through the character device node; access from the ISDN subsystem is blocked. + If cmd==0, the device is set to be used from the ISDN subsystem and does not communicate through the character device node. - ioctl(int fd, GIGASET_CONFIG, int *cmd); + ``ioctl(int fd, GIGASET_CONFIG, int *cmd);`` + (ser_gigaset and usb_gigaset only) + If cmd==1, the device is set to adapter configuration mode where commands are interpreted by the M10x DECT adapter itself instead of being forwarded to the base station. In this mode, the device accepts the commands described in Siemens document "AT-Kommando Alignment M10x Data" for setting the operation mode, associating with a base station and querying parameters like field strengh and signal quality. + Note that there is no ioctl command for leaving adapter configuration mode and returning to regular operation. In order to leave adapter configuration mode, write the command ATO to the device. - ioctl(int fd, GIGASET_BRKCHARS, unsigned char brkchars[6]); + ``ioctl(int fd, GIGASET_BRKCHARS, unsigned char brkchars[6]);`` + (usb_gigaset only) + Set the break characters on an M105's internal serial adapter to the six bytes stored in brkchars[]. Unused bytes should be set to zero. ioctl(int fd, GIGASET_VERSION, unsigned version[4]); Retrieve version information from the driver. version[0] must be set to one of: + - GIGVER_DRIVER: retrieve driver version - GIGVER_COMPAT: retrieve interface compatibility version - GIGVER_FWBASE: retrieve the firmware version of the base + Upon return, version[] is filled with the requested version information. 2.3. CAPI - ---- +--------- + The devices will show up as CAPI controllers as soon as the corresponding driver module is loaded, and can then be used with CAPI 2.0 kernel and user space applications. For user space access, @@ -165,21 +192,22 @@ GigaSet 307x Device Driver driver. 2.5. Unimodem mode - ------------- +------------------ + In this mode the device works like a modem connected to a serial port - (the /dev/ttyGU0, ... mentioned above) which understands the commands - - ATZ init, reset - => OK or ERROR - ATD - ATDT dial - => OK, CONNECT, - BUSY, - NO DIAL TONE, - NO CARRIER, - NO ANSWER - +++ change to command mode when connected - ATH hangup + (the /dev/ttyGU0, ... mentioned above) which understands the commands:: + + ATZ init, reset + => OK or ERROR + ATD + ATDT dial + => OK, CONNECT, + BUSY, + NO DIAL TONE, + NO CARRIER, + NO ANSWER + +++ change to command mode when connected + ATH hangup You can use some configuration tool of your distribution to configure this "modem" or configure pppd/wvdial manually. There are some example ppp @@ -189,40 +217,52 @@ GigaSet 307x Device Driver control lines. This means you must use "Stupid Mode" if you are using wvdial or you should use the nocrtscts option of pppd. You must also assure that the ppp_async module is loaded with the parameter - flag_time=0. You can do this e.g. by adding a line like + flag_time=0. You can do this e.g. by adding a line like:: + + options ppp_async flag_time=0 - options ppp_async flag_time=0 + to an appropriate module configuration file, like:: - to an appropriate module configuration file, like - /etc/modprobe.d/gigaset.conf. + /etc/modprobe.d/gigaset.conf. Unimodem mode is needed for making some devices [e.g. SX100] work which do not support the regular Gigaset command set. If debug output (see - section 3.2.) shows something like this when dialing: - CMD Received: ERROR - Available Params: 0 - Connection State: 0, Response: -1 - gigaset_process_response: resp_code -1 in ConState 0 ! - Timeout occurred + section 3.2.) shows something like this when dialing:: + + CMD Received: ERROR + Available Params: 0 + Connection State: 0, Response: -1 + gigaset_process_response: resp_code -1 in ConState 0 ! + Timeout occurred + then switching to unimodem mode may help. If you have installed the command line tool gigacontr, you can enter - unimodem mode using - gigacontr --mode unimodem - You can switch back using - gigacontr --mode isdn + unimodem mode using:: + + gigacontr --mode unimodem + + You can switch back using:: + + gigacontr --mode isdn You can also put the driver directly into Unimodem mode when it's loaded, by passing the module parameter startmode=0 to the hardware specific - module, e.g. + module, e.g.:: + modprobe usb_gigaset startmode=0 - or by adding a line like + + or by adding a line like:: + options usb_gigaset startmode=0 - to an appropriate module configuration file, like - /etc/modprobe.d/gigaset.conf + + to an appropriate module configuration file, like:: + + /etc/modprobe.d/gigaset.conf 2.6. Call-ID (CID) mode - ------------------ +----------------------- + Call-IDs are numbers used to tag commands to, and responses from, the Gigaset base in order to support the simultaneous handling of multiple ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem @@ -238,6 +278,7 @@ GigaSet 307x Device Driver During active operation, the driver switches to the necessary mode automatically. However, for the reasons above, the mode chosen when the device is not in use (idle) can be selected by the user. + - If you want to receive incoming calls, you can use the default settings (CID mode). - If you have several DECT data devices (M10x) which you want to use @@ -247,25 +288,27 @@ GigaSet 307x Device Driver If you want both of these at once, you are out of luck. You can also use the tty class parameter "cidmode" of the device to - change its CID mode while the driver is loaded, eg. - echo 0 > /sys/class/tty/ttyGU0/cidmode + change its CID mode while the driver is loaded, eg.:: + + echo 0 > /sys/class/tty/ttyGU0/cidmode 2.7. Dialing Numbers - --------------- - The called party number provided by an application for dialing out must +-------------------- +provided by an application for dialing out must be a public network number according to the local dialing plan, without any dial prefix for getting an outside line. Internal calls can be made by providing an internal extension number - prefixed with "**" (two asterisks) as the called party number. So to dial - eg. the first registered DECT handset, give "**11" as the called party - number. Dialing "***" (three asterisks) calls all extensions + prefixed with ``**`` (two asterisks) as the called party number. So to dial + eg. the first registered DECT handset, give ``**11`` as the called party + number. Dialing ``***`` (three asterisks) calls all extensions simultaneously (global call). Unimodem mode does not support internal calls. 2.8. Unregistered Wireless Devices (M101/M105) - ----------------------------------------- +---------------------------------------------- + The main purpose of the ser_gigaset and usb_gigaset drivers is to allow the M101 and M105 wireless devices to be used as ISDN devices for ISDN connections through a Gigaset base. Therefore they assume that the device @@ -279,73 +322,91 @@ GigaSet 307x Device Driver modes. See the gigacontr(8) manpage for details. 3. Troubleshooting - --------------- +==================== + 3.1. Solutions to frequently reported problems - ----------------------------------------- +---------------------------------------------- + Problem: - You have a slow provider and isdn4linux gives up dialing too early. + You have a slow provider and isdn4linux gives up dialing too early. Solution: - Load the isdn module using the dialtimeout option. You can do this e.g. - by adding a line like + Load the isdn module using the dialtimeout option. You can do this e.g. + by adding a line like:: - options isdn dialtimeout=15 + options isdn dialtimeout=15 - to /etc/modprobe.d/gigaset.conf or a similar file. + to /etc/modprobe.d/gigaset.conf or a similar file. Problem: - The isdnlog program emits error messages or just doesn't work. + The isdnlog program emits error messages or just doesn't work. Solution: - Isdnlog supports only the HiSax driver. Do not attempt to use it with + Isdnlog supports only the HiSax driver. Do not attempt to use it with other drivers such as Gigaset. Problem: - You have two or more DECT data adapters (M101/M105) and only the - first one you turn on works. + You have two or more DECT data adapters (M101/M105) and only the + first one you turn on works. Solution: - Select Unimodem mode for all DECT data adapters. (see section 2.5.) + Select Unimodem mode for all DECT data adapters. (see section 2.5.) Problem: - Messages like this: + Messages like this:: + usb_gigaset 3-2:1.0: Could not initialize the device. + appear in your syslog. Solution: Check whether your M10x wireless device is correctly registered to the Gigaset base. (see section 2.7.) 3.2. Telling the driver to provide more information - ---------------------------------------------- +--------------------------------------------------- Building the driver with the "Gigaset debugging" kernel configuration option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional information useful for debugging. You can control the amount of debugging information the driver produces by - writing an appropriate value to /sys/module/gigaset/parameters/debug, e.g. - echo 0 > /sys/module/gigaset/parameters/debug + writing an appropriate value to /sys/module/gigaset/parameters/debug, + e.g.:: + + echo 0 > /sys/module/gigaset/parameters/debug + switches off debugging output completely, - echo 0x302020 > /sys/module/gigaset/parameters/debug + + :: + + echo 0x302020 > /sys/module/gigaset/parameters/debug + enables a reasonable set of debugging output messages. These values are bit patterns where every bit controls a certain type of debugging output. See the constants DEBUG_* in the source file gigaset.h for details. The initial value can be set using the debug parameter when loading the - module "gigaset", e.g. by adding a line - options gigaset debug=0 + module "gigaset", e.g. by adding a line:: + + options gigaset debug=0 + to your module configuration file, eg. /etc/modprobe.d/gigaset.conf Generated debugging information can be found - - as output of the command - dmesg + - as output of the command:: + + dmesg + - in system log files written by your syslog daemon, usually in /var/log/, e.g. /var/log/messages. 3.3. Reporting problems and bugs - --------------------------- +-------------------------------- If you can't solve problems with the driver on your own, feel free to use one of the forums, bug trackers, or mailing lists on - https://sourceforge.net/projects/gigaset307x + + https://sourceforge.net/projects/gigaset307x + or write an electronic mail to the maintainers. Try to provide as much information as possible, such as + - distribution - kernel version (uname -r) - gcc version (gcc --version) @@ -362,7 +423,7 @@ GigaSet 307x Device Driver appropriate forums and newsgroups. 3.4. Reporting problem solutions - --------------------------- +-------------------------------- If you solved a problem with our drivers, wrote startup scripts for your distribution, ... feel free to contact us (using one of the places mentioned in 3.3.). We'd like to add scripts, hints, documentation @@ -370,34 +431,35 @@ GigaSet 307x Device Driver 4. Links, other software - --------------------- +========================== + - Sourceforge project developing this driver and associated tools - https://sourceforge.net/projects/gigaset307x + https://sourceforge.net/projects/gigaset307x - Yahoo! Group on the Siemens Gigaset family of devices - https://de.groups.yahoo.com/group/Siemens-Gigaset + https://de.groups.yahoo.com/group/Siemens-Gigaset - Siemens Gigaset/T-Sinus compatibility table - http://www.erbze.info/sinus_gigaset.htm + http://www.erbze.info/sinus_gigaset.htm (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) 5. Credits - ------- +============ + Thanks to Karsten Keil - for his help with isdn4linux + for his help with isdn4linux Deti Fliegl - for his base driver code + for his base driver code Dennis Dietrich - for his kernel 2.6 patches + for his kernel 2.6 patches Andreas Rummel - for his work and logs to get unimodem mode working + for his work and logs to get unimodem mode working Andreas Degert - for his logs and patches to get cx 100 working + for his logs and patches to get cx 100 working Dietrich Feist - for his generous donation of one M105 and two M101 cordless adapters + for his generous donation of one M105 and two M101 cordless adapters Christoph Schweers - for his generous donation of a M34 device + for his generous donation of a M34 device and all the other people who sent logs and other information. - diff --git a/Documentation/isdn/README.hysdn b/Documentation/isdn/hysdn.rst similarity index 80% rename from Documentation/isdn/README.hysdn rename to Documentation/isdn/hysdn.rst index eeca11f00ccd..0a168d1cbffc 100644 --- a/Documentation/isdn/README.hysdn +++ b/Documentation/isdn/hysdn.rst @@ -1,4 +1,7 @@ -$Id: README.hysdn,v 1.3.6.1 2001/02/10 14:41:19 kai Exp $ +============ +Hysdn Driver +============ + The hysdn driver has been written by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver @@ -22,28 +25,28 @@ for Hypercope GmbH Aachen, Germany. along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -Table of contents -================= +.. Table of contents -1. About the driver + 1. About the driver -2. Loading/Unloading the driver + 2. Loading/Unloading the driver -3. Entries in the /proc filesystem + 3. Entries in the /proc filesystem -4. The /proc/net/hysdn/cardconfX file + 4. The /proc/net/hysdn/cardconfX file -5. The /proc/net/hysdn/cardlogX file + 5. The /proc/net/hysdn/cardlogX file -6. Where to get additional info and help + 6. Where to get additional info and help 1. About the driver +=================== - The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active + The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active PCI isdn cards Champ, Ergo and Metro. To enable support for this cards enable ISDN support in the kernel config and support for HYSDN cards in - the active cards submenu. The driver may only be compiled and used if + the active cards submenu. The driver may only be compiled and used if support for loadable modules and the process filesystem have been enabled. These cards provide two different interfaces to the kernel. Without the @@ -52,22 +55,23 @@ Table of contents handlers for various protocols like ppp and others as well as config info and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de. - With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0 - compliant devices with either CAPI 2.0 applications + With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0 + compliant devices with either CAPI 2.0 applications (check isdn4k-utils) or -using the capidrv module- as a regular - isdn4linux device. This is done via the same mechanism as with the + isdn4linux device. This is done via the same mechanism as with the active AVM cards and in fact uses the same module. - + 2. Loading/Unloading the driver +=============================== The module has no command line parameters and auto detects up to 10 cards in the id-range 0-9. If a loaded driver shall be unloaded all open files in the /proc/net/hysdn - subdir need to be closed and all ethernet interfaces allocated by this + subdir need to be closed and all ethernet interfaces allocated by this driver must be shut down. Otherwise the module counter will avoid a module unload. - + If you are using the CAPI 2.0-interface, make sure to load/modprobe the kernelcapi-module first. @@ -76,52 +80,57 @@ Table of contents any avm-specific modules). 3. Entries in the /proc filesystem +================================== - When the module has been loaded it adds the directory hysdn in the - /proc/net tree. This directory contains exactly 2 file entries for each + When the module has been loaded it adds the directory hysdn in the + /proc/net tree. This directory contains exactly 2 file entries for each card. One is called cardconfX and the other cardlogX, where X is the - card id number from 0 to 9. + card id number from 0 to 9. The cards are numbered in the order found in the PCI config data. 4. The /proc/net/hysdn/cardconfX file +===================================== - This file may be read to get by everyone to get info about the cards type, + This file may be read to get by everyone to get info about the cards type, actual state, available features and used resources. The first 3 entries (id, bus and slot) are PCI info fields, the following type field gives the information about the cards type: - 4 -> Ergo card (server card with 2 b-chans) - 5 -> Metro card (server card with 4 or 8 b-chans) - 6 -> Champ card (client card with 2 b-chans) + - 4 -> Ergo card (server card with 2 b-chans) + - 5 -> Metro card (server card with 4 or 8 b-chans) + - 6 -> Champ card (client card with 2 b-chans) The following 3 fields show the hardware assignments for irq, iobase and the dual ported memory (dp-mem). + The fields b-chans and fax-chans announce the available card resources of this types for the user. + The state variable indicates the actual drivers state for this card with the following assignments. - 0 -> card has not been booted since driver load - 1 -> card booting is actually in progess - 2 -> card is in an error state due to a previous boot failure - 3 -> card is booted and active + - 0 -> card has not been booted since driver load + - 1 -> card booting is actually in progess + - 2 -> card is in an error state due to a previous boot failure + - 3 -> card is booted and active And the last field (device) shows the name of the ethernet device assigned to this card. Up to the first successful boot this field only shows a - to tell that no net device has been allocated up to now. Once a net device has been allocated it remains assigned to this card, even if a card is - rebooted and an boot error occurs. + rebooted and an boot error occurs. - Writing to the cardconfX file boots the card or transfers config lines to - the cards firmware. The type of data is automatically detected when the + Writing to the cardconfX file boots the card or transfers config lines to + the cards firmware. The type of data is automatically detected when the first data is written. Only root has write access to this file. The firmware boot files are normally called hyclient.pof for client cards and hyserver.pof for server cards. After successfully writing the boot file, complete config files or single config lines may be copied to this file. - If an error occurs the return value given to the writing process has the + If an error occurs the return value given to the writing process has the following additional codes (decimal): + ==== ============================================ 1000 Another process is currently bootng the card 1001 Invalid firmware header 1002 Boards dual-port RAM test failed @@ -131,34 +140,39 @@ Table of contents 1006 Second boot stage failure 1007 Timeout waiting for card ready during boot 1008 Operation only allowed in booted state - 1009 Config line too long - 1010 Invalid channel number + 1009 Config line too long + 1010 Invalid channel number 1011 Timeout sending config data + ==== ============================================ - Additional info about error reasons may be fetched from the log output. + Additional info about error reasons may be fetched from the log output. 5. The /proc/net/hysdn/cardlogX file - - The cardlogX file entry may be opened multiple for reading by everyone to +==================================== + + The cardlogX file entry may be opened multiple for reading by everyone to get the cards and drivers log data. Card messages always start with the - keyword LOG. All other lines are output from the driver. - The driver log data may be redirected to the syslog by selecting the + keyword LOG. All other lines are output from the driver. + The driver log data may be redirected to the syslog by selecting the appropriate bitmask. The cards log messages will always be send to this interface but never to the syslog. A root user may write a decimal or hex (with 0x) value t this file to select - desired output options. As mentioned above the cards log dat is always + desired output options. As mentioned above the cards log dat is always written to the cardlog file independent of the following options only used to check and debug the driver itself: - For example: - echo "0x34560078" > /proc/net/hysdn/cardlog0 + For example:: + + echo "0x34560078" > /proc/net/hysdn/cardlog0 + to output the hex log mask 34560078 for card 0. - - The written value is regarded as an unsigned 32-Bit value, bit ored for + + The written value is regarded as an unsigned 32-Bit value, bit ored for desired output. The following bits are already assigned: - 0x80000000 All driver log data is alternatively via syslog + ========== ============================================================ + 0x80000000 All driver log data is alternatively via syslog 0x00000001 Log memory allocation errors 0x00000010 Firmware load start and close are logged 0x00000020 Log firmware record parser @@ -171,25 +185,12 @@ Table of contents 0x00100000 Log all open and close actions to /proc/net/hysdn/card files 0x00200000 Log all actions from /proc file entries 0x00010000 Log network interface init and deinit - + ========== ============================================================ + 6. Where to get additional info and help +======================================== - If you have any problems concerning the driver or configuration contact + If you have any problems concerning the driver or configuration contact the Hypercope support team (support@hypercope.de) and or the authors Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or Ulrich Albrecht (ualbrecht@hypercope.de). - - - - - - - - - - - - - - - diff --git a/Documentation/isdn/index.rst b/Documentation/isdn/index.rst new file mode 100644 index 000000000000..407e74b78372 --- /dev/null +++ b/Documentation/isdn/index.rst @@ -0,0 +1,24 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==== +ISDN +==== + +.. toctree:: + :maxdepth: 2 + + interface_capi + + avmb1 + gigaset + hysdn + m_isdn + + credits + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/interface_capi.rst similarity index 75% rename from Documentation/isdn/INTERFACE.CAPI rename to Documentation/isdn/interface_capi.rst index 021aa9cf139d..01a4b5ade9a4 100644 --- a/Documentation/isdn/INTERFACE.CAPI +++ b/Documentation/isdn/interface_capi.rst @@ -1,7 +1,9 @@ +========================================= Kernel CAPI Interface to Hardware Drivers ------------------------------------------ +========================================= 1. Overview +=========== From the CAPI 2.0 specification: COMMON-ISDN-API (CAPI) is an application programming interface standard used @@ -22,6 +24,7 @@ This standard is freely available from https://www.capi.org. 2. Driver and Device Registration +================================= CAPI drivers optionally register themselves with Kernel CAPI by calling the Kernel CAPI function register_capi_driver() with a pointer to a struct @@ -50,6 +53,7 @@ callback functions by Kernel CAPI. 3. Application Registration and Communication +============================================= Kernel CAPI forwards registration requests from applications (calls to CAPI operation CAPI_REGISTER) to an appropriate hardware driver by calling its @@ -71,23 +75,26 @@ messages for that application may be passed to or from the device anymore. 4. Data Structures +================== 4.1 struct capi_driver +---------------------- This structure describes a Kernel CAPI driver itself. It is used in the register_capi_driver() and unregister_capi_driver() functions, and contains the following non-private fields, all to be set by the driver before calling register_capi_driver(): -char name[32] +``char name[32]`` the name of the driver, as a zero-terminated ASCII string -char revision[32] +``char revision[32]`` the revision number of the driver, as a zero-terminated ASCII string -int (*add_card)(struct capi_driver *driver, capicardparams *data) +``int (*add_card)(struct capi_driver *driver, capicardparams *data)`` a callback function pointer (may be NULL) 4.2 struct capi_ctr +------------------- This structure describes an ISDN device (controller) handled by a Kernel CAPI driver. After registration via the attach_capi_ctr() function it is passed to @@ -96,88 +103,109 @@ identify the controller to operate on. It contains the following non-private fields: -- to be set by the driver before calling attach_capi_ctr(): +to be set by the driver before calling attach_capi_ctr(): +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -struct module *owner +``struct module *owner`` pointer to the driver module owning the device -void *driverdata +``void *driverdata`` an opaque pointer to driver specific data, not touched by Kernel CAPI -char name[32] +``char name[32]`` the name of the controller, as a zero-terminated ASCII string -char *driver_name +``char *driver_name`` the name of the driver, as a zero-terminated ASCII string -int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata) +``int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)`` (optional) pointer to a callback function for sending firmware and configuration data to the device + The function may return before the operation has completed. + Completion must be signalled by a call to capi_ctr_ready(). + Return value: 0 on success, error code on error Called in process context. -void (*reset_ctr)(struct capi_ctr *ctrlr) +``void (*reset_ctr)(struct capi_ctr *ctrlr)`` (optional) pointer to a callback function for stopping the device, releasing all registered applications + The function may return before the operation has completed. + Completion must be signalled by a call to capi_ctr_down(). + Called in process context. -void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, - capi_register_params *rparam) -void (*release_appl)(struct capi_ctr *ctrlr, u16 applid) - pointers to callback functions for registration and deregistration of +``void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, capi_register_params *rparam)`` + pointers to callback function for registration of applications with the device + Calls to these functions are serialized by Kernel CAPI so that only one call to any of them is active at any time. -u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) +``void (*release_appl)(struct capi_ctr *ctrlr, u16 applid)`` + pointers to callback functions deregistration of + applications with the device + + Calls to these functions are serialized by Kernel CAPI so that only + one call to any of them is active at any time. + +``u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)`` pointer to a callback function for sending a CAPI message to the device + Return value: CAPI error code + If the method returns 0 (CAPI_NOERROR) the driver has taken ownership of the skb and the caller may no longer access it. If it returns a non-zero (error) value then ownership of the skb returns to the caller who may reuse or free it. + The return value should only be used to signal problems with respect to accepting or queueing the message. Errors occurring during the actual processing of the message should be signaled with an appropriate reply message. + May be called in process or interrupt context. + Calls to this function are not serialized by Kernel CAPI, ie. it must be prepared to be re-entered. -char *(*procinfo)(struct capi_ctr *ctrlr) +``char *(*procinfo)(struct capi_ctr *ctrlr)`` pointer to a callback function returning the entry for the device in the CAPI controller info table, /proc/capi/controller -const struct file_operations *proc_fops +``const struct file_operations *proc_fops`` pointers to callback functions for the device's proc file system entry, /proc/capi/controllers/; pointer to the device's capi_ctr structure is available from struct proc_dir_entry::data which is available from struct inode. -Note: Callback functions except send_message() are never called in interrupt -context. +Note: + Callback functions except send_message() are never called in interrupt + context. -- to be filled in before calling capi_ctr_ready(): +to be filled in before calling capi_ctr_ready(): +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -u8 manu[CAPI_MANUFACTURER_LEN] +``u8 manu[CAPI_MANUFACTURER_LEN]`` value to return for CAPI_GET_MANUFACTURER -capi_version version +``capi_version version`` value to return for CAPI_GET_VERSION -capi_profile profile +``capi_profile profile`` value to return for CAPI_GET_PROFILE -u8 serial[CAPI_SERIAL_LEN] +``u8 serial[CAPI_SERIAL_LEN]`` value to return for CAPI_GET_SERIAL 4.3 SKBs +-------- CAPI messages are passed between Kernel CAPI and the driver via send_message() and capi_ctr_handle_message(), stored in the data portion of a socket buffer @@ -192,6 +220,7 @@ instead of 30. 4.4 The _cmsg Structure +----------------------- (declared in ) @@ -216,6 +245,7 @@ Members are named after the CAPI 2.0 standard names of the parameters they represent. See for the exact spelling. Member data types are: +=========== ================================================================= u8 for CAPI parameters of type 'byte' u16 for CAPI parameters of type 'word' @@ -235,6 +265,7 @@ _cmstruct alternative representation for CAPI parameters of type 'struct' CAPI_COMPOSE: The parameter is present. Subparameter values are stored individually in the corresponding _cmsg structure members. +=========== ================================================================= Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert messages between their transport encoding described in the CAPI 2.0 standard @@ -244,51 +275,71 @@ sure it is big enough to accommodate the resulting CAPI message. 5. Lower Layer Interface Functions +================================== (declared in ) -void register_capi_driver(struct capi_driver *drvr) -void unregister_capi_driver(struct capi_driver *drvr) - register/unregister a driver with Kernel CAPI +:: + + void register_capi_driver(struct capi_driver *drvr) + void unregister_capi_driver(struct capi_driver *drvr) + +register/unregister a driver with Kernel CAPI + +:: + + int attach_capi_ctr(struct capi_ctr *ctrlr) + int detach_capi_ctr(struct capi_ctr *ctrlr) + +register/unregister a device (controller) with Kernel CAPI -int attach_capi_ctr(struct capi_ctr *ctrlr) -int detach_capi_ctr(struct capi_ctr *ctrlr) - register/unregister a device (controller) with Kernel CAPI +:: -void capi_ctr_ready(struct capi_ctr *ctrlr) -void capi_ctr_down(struct capi_ctr *ctrlr) - signal controller ready/not ready + void capi_ctr_ready(struct capi_ctr *ctrlr) + void capi_ctr_down(struct capi_ctr *ctrlr) -void capi_ctr_suspend_output(struct capi_ctr *ctrlr) -void capi_ctr_resume_output(struct capi_ctr *ctrlr) - signal suspend/resume +signal controller ready/not ready -void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, - struct sk_buff *skb) - pass a received CAPI message to Kernel CAPI - for forwarding to the specified application +:: + + void capi_ctr_suspend_output(struct capi_ctr *ctrlr) + void capi_ctr_resume_output(struct capi_ctr *ctrlr) + +signal suspend/resume + +:: + + void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, + struct sk_buff *skb) + +pass a received CAPI message to Kernel CAPI +for forwarding to the specified application 6. Helper Functions and Macros +============================== Library functions (from ): -void capilib_new_ncci(struct list_head *head, u16 applid, +:: + + void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize) -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) -void capilib_release_appl(struct list_head *head, u16 applid) -void capilib_release(struct list_head *head) -void capilib_data_b3_conf(struct list_head *head, u16 applid, + void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) + void capilib_release_appl(struct list_head *head, u16 applid) + void capilib_release(struct list_head *head) + void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -u16 capilib_data_b3_req(struct list_head *head, u16 applid, + u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid) Macros to extract/set element values from/in a CAPI message header (from ): +====================== ============================= ==================== Get Macro Set Macro Element (Type) - +====================== ============================= ==================== CAPIMSG_LEN(m) CAPIMSG_SETLEN(m, len) Total Length (u16) CAPIMSG_APPID(m) CAPIMSG_SETAPPID(m, applid) ApplID (u16) CAPIMSG_COMMAND(m) CAPIMSG_SETCOMMAND(m,cmd) Command (u8) @@ -300,31 +351,31 @@ CAPIMSG_MSGID(m) CAPIMSG_SETMSGID(m, msgid) Message Number (u16) CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI (u32) CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) +====================== ============================= ==================== Library functions for working with _cmsg structures (from ): -unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg) - Assembles a CAPI 2.0 message from the parameters in *cmsg, storing the - result in *msg. +``unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)`` + Assembles a CAPI 2.0 message from the parameters in ``*cmsg``, + storing the result in ``*msg``. -unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg) - Disassembles the CAPI 2.0 message in *msg, storing the parameters in - *cmsg. +``unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)`` + Disassembles the CAPI 2.0 message in ``*msg``, storing the parameters + in ``*cmsg``. -unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand, - u16 Messagenumber, u32 Controller) - Fills the header part and address field of the _cmsg structure *cmsg +``unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand, u16 Messagenumber, u32 Controller)`` + Fills the header part and address field of the _cmsg structure ``*cmsg`` with the given values, zeroing the remainder of the structure so only parameters with non-default values need to be changed before sending the message. -void capi_cmsg_answer(_cmsg *cmsg) - Sets the low bit of the Subcommand field in *cmsg, thereby converting - _REQ to _CONF and _IND to _RESP. +``void capi_cmsg_answer(_cmsg *cmsg)`` + Sets the low bit of the Subcommand field in ``*cmsg``, thereby + converting ``_REQ`` to ``_CONF`` and ``_IND`` to ``_RESP``. -char *capi_cmd2str(u8 Command, u8 Subcommand) +``char *capi_cmd2str(u8 Command, u8 Subcommand)`` Returns the CAPI 2.0 message name corresponding to the given command and subcommand values, as a static ASCII string. The return value may be NULL if the command/subcommand is not one of those defined in the @@ -332,6 +383,7 @@ char *capi_cmd2str(u8 Command, u8 Subcommand) 7. Debugging +============ The module kernelcapi has a module parameter showcapimsgs controlling some debugging output produced by the module. It can only be set when the module is diff --git a/Documentation/isdn/README.mISDN b/Documentation/isdn/m_isdn.rst similarity index 89% rename from Documentation/isdn/README.mISDN rename to Documentation/isdn/m_isdn.rst index cd8bf920e77b..9957de349e69 100644 --- a/Documentation/isdn/README.mISDN +++ b/Documentation/isdn/m_isdn.rst @@ -1,6 +1,9 @@ +============ +mISDN Driver +============ + mISDN is a new modular ISDN driver, in the long term it should replace the old I4L driver architecture for passiv ISDN cards. It was designed to allow a broad range of applications and interfaces but only have the basic function in kernel, the interface to the user space is based on sockets with a own address family AF_ISDN. - diff --git a/drivers/staging/isdn/hysdn/Kconfig b/drivers/staging/isdn/hysdn/Kconfig index 1971ef850c9a..4c8a9283b9dd 100644 --- a/drivers/staging/isdn/hysdn/Kconfig +++ b/drivers/staging/isdn/hysdn/Kconfig @@ -5,7 +5,7 @@ config HYSDN help Say Y here if you have one of Hypercope's active PCI ISDN cards Champ, Ergo and Metro. You will then get a module called hysdn. - Please read the file for more + Please read the file for more information. config HYSDN_CAPI -- GitLab From ec23eb54fbc7a07405d416d77e8115e575ce3adc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:27 -0300 Subject: [PATCH 1462/7155] docs: fs: convert docs without extension to ReST There are 3 remaining files without an extension inside the fs docs dir. Manually convert them to ReST. In the case of the nfs/exporting.rst file, as the nfs docs aren't ported yet, I opted to convert and add a :orphan: there, with should be removed when it gets added into a nfs-specific part of the fs documentation. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- ...irectory-locking => directory-locking.rst} | 40 ++- Documentation/filesystems/index.rst | 2 + .../filesystems/{Locking => locking.rst} | 259 ++++++++++++------ .../nfs/{Exporting => exporting.rst} | 31 ++- Documentation/filesystems/vfs.rst | 2 +- fs/cifs/export.c | 2 +- fs/exportfs/expfs.c | 2 +- fs/isofs/export.c | 2 +- fs/orangefs/file.c | 2 +- include/linux/dcache.h | 2 +- include/linux/exportfs.h | 2 +- 11 files changed, 226 insertions(+), 120 deletions(-) rename Documentation/filesystems/{directory-locking => directory-locking.rst} (86%) rename Documentation/filesystems/{Locking => locking.rst} (79%) rename Documentation/filesystems/nfs/{Exporting => exporting.rst} (91%) diff --git a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking.rst similarity index 86% rename from Documentation/filesystems/directory-locking rename to Documentation/filesystems/directory-locking.rst index 4e32cb961e5b..de12016ee419 100644 --- a/Documentation/filesystems/directory-locking +++ b/Documentation/filesystems/directory-locking.rst @@ -1,12 +1,17 @@ - Locking scheme used for directory operations is based on two +================= +Directory Locking +================= + + +Locking scheme used for directory operations is based on two kinds of locks - per-inode (->i_rwsem) and per-filesystem (->s_vfs_rename_mutex). - When taking the i_rwsem on multiple non-directory objects, we +When taking the i_rwsem on multiple non-directory objects, we always acquire the locks in order by increasing address. We'll call that "inode pointer" order in the following. - For our purposes all operations fall in 5 classes: +For our purposes all operations fall in 5 classes: 1) read access. Locking rules: caller locks directory we are accessing. The lock is taken shared. @@ -27,25 +32,29 @@ NB: we might get away with locking the the source (and target in exchange case) shared. 5) link creation. Locking rules: + * lock parent * check that source is not a directory * lock source * call the method. + All locks are exclusive. 6) cross-directory rename. The trickiest in the whole bunch. Locking rules: + * lock the filesystem * lock parents in "ancestors first" order. * find source and target. * if old parent is equal to or is a descendent of target - fail with -ENOTEMPTY + fail with -ENOTEMPTY * if new parent is equal to or is a descendent of source - fail with -ELOOP + fail with -ELOOP * If it's an exchange, lock both the source and the target. * If the target exists, lock it. If the source is a non-directory, lock it. If we need to lock both, do so in inode pointer order. * call the method. + All ->i_rwsem are taken exclusive. Again, we might get away with locking the the source (and target in exchange case) shared. @@ -54,10 +63,11 @@ read, modified or removed by method will be locked by caller. If no directory is its own ancestor, the scheme above is deadlock-free. + Proof: First of all, at any moment we have a partial ordering of the -objects - A < B iff A is an ancestor of B. + objects - A < B iff A is an ancestor of B. That ordering can change. However, the following is true: @@ -77,32 +87,32 @@ objects - A < B iff A is an ancestor of B. non-directory object, except renames, which take locks on source and target in inode pointer order in the case they are not directories.) - Now consider the minimal deadlock. Each process is blocked on +Now consider the minimal deadlock. Each process is blocked on attempt to acquire some lock and already holds at least one lock. Let's consider the set of contended locks. First of all, filesystem lock is not contended, since any process blocked on it is not holding any locks. Thus all processes are blocked on ->i_rwsem. - By (3), any process holding a non-directory lock can only be +By (3), any process holding a non-directory lock can only be waiting on another non-directory lock with a larger address. Therefore the process holding the "largest" such lock can always make progress, and non-directory objects are not included in the set of contended locks. - Thus link creation can't be a part of deadlock - it can't be +Thus link creation can't be a part of deadlock - it can't be blocked on source and it means that it doesn't hold any locks. - Any contended object is either held by cross-directory rename or +Any contended object is either held by cross-directory rename or has a child that is also contended. Indeed, suppose that it is held by operation other than cross-directory rename. Then the lock this operation is blocked on belongs to child of that object due to (1). - It means that one of the operations is cross-directory rename. +It means that one of the operations is cross-directory rename. Otherwise the set of contended objects would be infinite - each of them would have a contended child and we had assumed that no object is its own descendent. Moreover, there is exactly one cross-directory rename (see above). - Consider the object blocking the cross-directory rename. One +Consider the object blocking the cross-directory rename. One of its descendents is locked by cross-directory rename (otherwise we would again have an infinite set of contended objects). But that means that cross-directory rename is taking locks out of order. Due @@ -112,7 +122,7 @@ try to acquire lock on descendent before the lock on ancestor. Contradiction. I.e. deadlock is impossible. Q.E.D. - These operations are guaranteed to avoid loop creation. Indeed, +These operations are guaranteed to avoid loop creation. Indeed, the only operation that could introduce loops is cross-directory rename. Since the only new (parent, child) pair added by rename() is (new parent, source), such loop would have to contain these objects and the rest of it @@ -123,13 +133,13 @@ new parent had been equal to or a descendent of source since the moment when we had acquired filesystem lock and rename() would fail with -ELOOP in that case. - While this locking scheme works for arbitrary DAGs, it relies on +While this locking scheme works for arbitrary DAGs, it relies on ability to check that directory is a descendent of another object. Current implementation assumes that directory graph is a tree. This assumption is also preserved by all operations (cross-directory rename on a tree that would not introduce a cycle will leave it a tree and link() fails for directories). - Notice that "directory" in the above == "anything that might have +Notice that "directory" in the above == "anything that might have children", so if we are going to introduce hybrid objects we will need either to make sure that link(2) doesn't work for them or to make changes in is_subdir() that would make it work even in presence of such beasts. diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index 2de2fe2ab078..08320c35d03b 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -20,6 +20,8 @@ algorithms work. path-lookup api-summary splice + locking + directory-locking Filesystem support layers ========================= diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/locking.rst similarity index 79% rename from Documentation/filesystems/Locking rename to Documentation/filesystems/locking.rst index 204dd3ea36bb..fc3a0704553c 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/locking.rst @@ -1,14 +1,22 @@ - The text below describes the locking rules for VFS-related methods. +======= +Locking +======= + +The text below describes the locking rules for VFS-related methods. It is (believed to be) up-to-date. *Please*, if you change anything in prototypes or locking protocols - update this file. And update the relevant instances in the tree, don't leave that to maintainers of filesystems/devices/ etc. At the very least, put the list of dubious cases in the end of this file. Don't turn it into log - maintainers of out-of-the-tree code are supposed to be able to use diff(1). - Thing currently missing here: socket operations. Alexey? ---------------------------- dentry_operations -------------------------- -prototypes: +Thing currently missing here: socket operations. Alexey? + +dentry_operations +================= + +prototypes:: + int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, struct qstr *); @@ -24,23 +32,30 @@ prototypes: struct dentry *(*d_real)(struct dentry *, const struct inode *); locking rules: - rename_lock ->d_lock may block rcu-walk -d_revalidate: no no yes (ref-walk) maybe -d_weak_revalidate:no no yes no -d_hash no no no maybe -d_compare: yes no no maybe -d_delete: no yes no no -d_init: no no yes no -d_release: no no yes no -d_prune: no yes no no -d_iput: no no yes no -d_dname: no no no no -d_automount: no no yes no -d_manage: no no yes (ref-walk) maybe -d_real no no yes no - ---------------------------- inode_operations --------------------------- -prototypes: + +================== =========== ======== ============== ======== +ops rename_lock ->d_lock may block rcu-walk +================== =========== ======== ============== ======== +d_revalidate: no no yes (ref-walk) maybe +d_weak_revalidate: no no yes no +d_hash no no no maybe +d_compare: yes no no maybe +d_delete: no yes no no +d_init: no no yes no +d_release: no no yes no +d_prune: no yes no no +d_iput: no no yes no +d_dname: no no no no +d_automount: no no yes no +d_manage: no no yes (ref-walk) maybe +d_real no no yes no +================== =========== ======== ============== ======== + +inode_operations +================ + +prototypes:: + int (*create) (struct inode *,struct dentry *,umode_t, bool); struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); int (*link) (struct dentry *,struct inode *,struct dentry *); @@ -68,7 +83,10 @@ prototypes: locking rules: all may block - i_rwsem(inode) + +============ ============================================= +ops i_rwsem(inode) +============ ============================================= lookup: shared create: exclusive link: exclusive (both) @@ -89,17 +107,21 @@ fiemap: no update_time: no atomic_open: exclusive tmpfile: no +============ ============================================= Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_rwsem exclusive on victim. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. -See Documentation/filesystems/directory-locking for more detailed discussion +See Documentation/filesystems/directory-locking.rst for more detailed discussion of the locking scheme for directory operations. ------------------------ xattr_handler operations ----------------------- -prototypes: +xattr_handler operations +======================== + +prototypes:: + bool (*list)(struct dentry *dentry); int (*get)(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, void *buffer, @@ -110,13 +132,20 @@ prototypes: locking rules: all may block - i_rwsem(inode) + +===== ============== +ops i_rwsem(inode) +===== ============== list: no get: no set: exclusive +===== ============== + +super_operations +================ + +prototypes:: ---------------------------- super_operations --------------------------- -prototypes: struct inode *(*alloc_inode)(struct super_block *sb); void (*free_inode)(struct inode *); void (*destroy_inode)(struct inode *); @@ -138,7 +167,10 @@ prototypes: locking rules: All may block [not true, see below] - s_umount + +====================== ============ ======================== +ops s_umount note +====================== ============ ======================== alloc_inode: free_inode: called from RCU callback destroy_inode: @@ -157,6 +189,7 @@ show_options: no (namespace_sem) quota_read: no (see below) quota_write: no (see below) bdev_try_to_free_page: no (see below) +====================== ============ ======================== ->statfs() has s_umount (shared) when called by ustat(2) (native or compat), but that's an accident of bad API; s_umount is used to pin @@ -164,31 +197,44 @@ the superblock down when we only have dev_t given us by userland to identify the superblock. Everything else (statfs(), fstatfs(), etc.) doesn't hold it when calling ->statfs() - superblock is pinned down by resolving the pathname passed to syscall. + ->quota_read() and ->quota_write() functions are both guaranteed to be the only ones operating on the quota file by the quota code (via dqio_sem) (unless an admin really wants to screw up something and writes to quota files with quotas on). For other details about locking see also dquot_operations section. + ->bdev_try_to_free_page is called from the ->releasepage handler of the block device inode. See there for more details. ---------------------------- file_system_type --------------------------- -prototypes: +file_system_type +================ + +prototypes:: + struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); + locking rules: - may block + +======= ========= +ops may block +======= ========= mount yes kill_sb yes +======= ========= ->mount() returns ERR_PTR or the root dentry; its superblock should be locked on return. + ->kill_sb() takes a write-locked superblock, does all shutdown work on it, unlocks and drops the reference. ---------------------------- address_space_operations -------------------------- -prototypes: +address_space_operations +======================== +prototypes:: + int (*writepage)(struct page *page, struct writeback_control *wbc); int (*readpage)(struct file *, struct page *); int (*writepages)(struct address_space *, struct writeback_control *); @@ -218,14 +264,16 @@ prototypes: locking rules: All except set_page_dirty and freepage may block - PageLocked(page) i_rwsem +====================== ======================== ========= +ops PageLocked(page) i_rwsem +====================== ======================== ========= writepage: yes, unlocks (see below) readpage: yes, unlocks writepages: set_page_dirty no readpages: -write_begin: locks the page exclusive -write_end: yes, unlocks exclusive +write_begin: locks the page exclusive +write_end: yes, unlocks exclusive bmap: invalidatepage: yes releasepage: yes @@ -239,17 +287,18 @@ is_partially_uptodate: yes error_remove_page: yes swap_activate: no swap_deactivate: no +====================== ======================== ========= - ->write_begin(), ->write_end() and ->readpage() may be called from +->write_begin(), ->write_end() and ->readpage() may be called from the request handler (/dev/loop). - ->readpage() unlocks the page, either synchronously or via I/O +->readpage() unlocks the page, either synchronously or via I/O completion. - ->readpages() populates the pagecache with the passed pages and starts +->readpages() populates the pagecache with the passed pages and starts I/O against them. They come unlocked upon I/O completion. - ->writepage() is used for two purposes: for "memory cleansing" and for +->writepage() is used for two purposes: for "memory cleansing" and for "sync". These are quite different operations and the behaviour may differ depending upon the mode. @@ -297,70 +346,81 @@ will leave the page itself marked clean but it will be tagged as dirty in the radix tree. This incoherency can lead to all sorts of hard-to-debug problems in the filesystem like having dirty inodes at umount and losing written data. - ->writepages() is used for periodic writeback and for syscall-initiated +->writepages() is used for periodic writeback and for syscall-initiated sync operations. The address_space should start I/O against at least -*nr_to_write pages. *nr_to_write must be decremented for each page which is -written. The address_space implementation may write more (or less) pages -than *nr_to_write asks for, but it should try to be reasonably close. If -nr_to_write is NULL, all dirty pages must be written. +``*nr_to_write`` pages. ``*nr_to_write`` must be decremented for each page +which is written. The address_space implementation may write more (or less) +pages than ``*nr_to_write`` asks for, but it should try to be reasonably close. +If nr_to_write is NULL, all dirty pages must be written. writepages should _only_ write pages which are present on mapping->io_pages. - ->set_page_dirty() is called from various places in the kernel +->set_page_dirty() is called from various places in the kernel when the target page is marked as needing writeback. It may be called under spinlock (it cannot block) and is sometimes called with the page not locked. - ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some +->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some filesystems and by the swapper. The latter will eventually go away. Please, keep it that way and don't breed new callers. - ->invalidatepage() is called when the filesystem must attempt to drop +->invalidatepage() is called when the filesystem must attempt to drop some or all of the buffers from the page when it is being truncated. It returns zero on success. If ->invalidatepage is zero, the kernel uses block_invalidatepage() instead. - ->releasepage() is called when the kernel is about to try to drop the +->releasepage() is called when the kernel is about to try to drop the buffers from the page in preparation for freeing it. It returns zero to indicate that the buffers are (or may be) freeable. If ->releasepage is zero, the kernel assumes that the fs has no private interest in the buffers. - ->freepage() is called when the kernel is done dropping the page +->freepage() is called when the kernel is done dropping the page from the page cache. - ->launder_page() may be called prior to releasing a page if +->launder_page() may be called prior to releasing a page if it is still found to be dirty. It returns zero if the page was successfully cleaned, or an error value if not. Note that in order to prevent the page getting mapped back in and redirtied, it needs to be kept locked across the entire operation. - ->swap_activate will be called with a non-zero argument on +->swap_activate will be called with a non-zero argument on files backing (non block device backed) swapfiles. A return value of zero indicates success, in which case this file can be used for backing swapspace. The swapspace operations will be proxied to the address space operations. - ->swap_deactivate() will be called in the sys_swapoff() +->swap_deactivate() will be called in the sys_swapoff() path after ->swap_activate() returned success. ------------------------ file_lock_operations ------------------------------ -prototypes: +file_lock_operations +==================== + +prototypes:: + void (*fl_copy_lock)(struct file_lock *, struct file_lock *); void (*fl_release_private)(struct file_lock *); locking rules: - inode->i_lock may block + +=================== ============= ========= +ops inode->i_lock may block +=================== ============= ========= fl_copy_lock: yes no -fl_release_private: maybe maybe[1] +fl_release_private: maybe maybe[1]_ +=================== ============= ========= + +.. [1]: + ->fl_release_private for flock or POSIX locks is currently allowed + to block. Leases however can still be freed while the i_lock is held and + so fl_release_private called on a lease should not block. -[1]: ->fl_release_private for flock or POSIX locks is currently allowed -to block. Leases however can still be freed while the i_lock is held and -so fl_release_private called on a lease should not block. +lock_manager_operations +======================= + +prototypes:: ------------------------ lock_manager_operations --------------------------- -prototypes: void (*lm_notify)(struct file_lock *); /* unblock callback */ int (*lm_grant)(struct file_lock *, struct file_lock *, int); void (*lm_break)(struct file_lock *); /* break_lease callback */ @@ -368,24 +428,33 @@ prototypes: locking rules: - inode->i_lock blocked_lock_lock may block +========== ============= ================= ========= +ops inode->i_lock blocked_lock_lock may block +========== ============= ================= ========= lm_notify: yes yes no lm_grant: no no no lm_break: yes no no lm_change yes no no +========== ============= ================= ========= + +buffer_head +=========== + +prototypes:: ---------------------------- buffer_head ----------------------------------- -prototypes: void (*b_end_io)(struct buffer_head *bh, int uptodate); locking rules: - called from interrupts. In other words, extreme care is needed here. + +called from interrupts. In other words, extreme care is needed here. bh is locked, but that's all warranties we have here. Currently only RAID1, highmem, fs/buffer.c, and fs/ntfs/aops.c are providing these. Block devices call this method upon the IO completion. ---------------------------- block_device_operations ----------------------- -prototypes: +block_device_operations +======================= +prototypes:: + int (*open) (struct block_device *, fmode_t); int (*release) (struct gendisk *, fmode_t); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); @@ -399,7 +468,10 @@ prototypes: void (*swap_slot_free_notify) (struct block_device *, unsigned long); locking rules: - bd_mutex + +======================= =================== +ops bd_mutex +======================= =================== open: yes release: yes ioctl: no @@ -410,6 +482,7 @@ unlock_native_capacity: no revalidate_disk: no getgeo: no swap_slot_free_notify: no (see below) +======================= =================== media_changed, unlock_native_capacity and revalidate_disk are called only from check_disk_change(). @@ -418,8 +491,11 @@ swap_slot_free_notify is called with swap_lock and sometimes the page lock held. ---------------------------- file_operations ------------------------------- -prototypes: +file_operations +=============== + +prototypes:: + loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); @@ -455,7 +531,6 @@ prototypes: size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **, void **); long (*fallocate)(struct file *, int, loff_t, loff_t); -}; locking rules: All may block. @@ -490,8 +565,11 @@ in sys_read() and friends. the lease within the individual filesystem to record the result of the operation ---------------------------- dquot_operations ------------------------------- -prototypes: +dquot_operations +================ + +prototypes:: + int (*write_dquot) (struct dquot *); int (*acquire_dquot) (struct dquot *); int (*release_dquot) (struct dquot *); @@ -503,20 +581,26 @@ a proper locking wrt the filesystem and call the generic quota operations. What filesystem should expect from the generic quota functions: - FS recursion Held locks when called +============== ============ ========================= +ops FS recursion Held locks when called +============== ============ ========================= write_dquot: yes dqonoff_sem or dqptr_sem acquire_dquot: yes dqonoff_sem or dqptr_sem release_dquot: yes dqonoff_sem or dqptr_sem mark_dirty: no - write_info: yes dqonoff_sem +============== ============ ========================= FS recursion means calling ->quota_read() and ->quota_write() from superblock operations. More details about quota locking can be found in fs/dquot.c. ---------------------------- vm_operations_struct ----------------------------- -prototypes: +vm_operations_struct +==================== + +prototypes:: + void (*open)(struct vm_area_struct*); void (*close)(struct vm_area_struct*); vm_fault_t (*fault)(struct vm_area_struct*, struct vm_fault *); @@ -525,7 +609,10 @@ prototypes: int (*access)(struct vm_area_struct *, unsigned long, void*, int, int); locking rules: - mmap_sem PageLocked(page) + +============= ======== =========================== +ops mmap_sem PageLocked(page) +============= ======== =========================== open: yes close: yes fault: yes can return with page locked @@ -533,8 +620,9 @@ map_pages: yes page_mkwrite: yes can return with page locked pfn_mkwrite: yes access: yes +============= ======== =========================== - ->fault() is called when a previously not present pte is about +->fault() is called when a previously not present pte is about to be faulted in. The filesystem must find and return the page associated with the passed in "pgoff" in the vm_fault structure. If it is possible that the page may be truncated and/or invalidated, then the filesystem must lock @@ -542,7 +630,7 @@ the page, then ensure it is not already truncated (the page lock will block subsequent truncate), and then return with VM_FAULT_LOCKED, and the page locked. The VM will unlock the page. - ->map_pages() is called when VM asks to map easy accessible pages. +->map_pages() is called when VM asks to map easy accessible pages. Filesystem should find and map pages associated with offsets from "start_pgoff" till "end_pgoff". ->map_pages() is called with page table locked and must not block. If it's not possible to reach a page without blocking, @@ -551,25 +639,26 @@ page table entry. Pointer to entry associated with the page is passed in "pte" field in vm_fault structure. Pointers to entries for other offsets should be calculated relative to "pte". - ->page_mkwrite() is called when a previously read-only pte is +->page_mkwrite() is called when a previously read-only pte is about to become writeable. The filesystem again must ensure that there are no truncate/invalidate races, and then return with the page locked. If the page has been truncated, the filesystem should not look up a new page like the ->fault() handler, but simply return with VM_FAULT_NOPAGE, which will cause the VM to retry the fault. - ->pfn_mkwrite() is the same as page_mkwrite but when the pte is +->pfn_mkwrite() is the same as page_mkwrite but when the pte is VM_PFNMAP or VM_MIXEDMAP with a page-less entry. Expected return is VM_FAULT_NOPAGE. Or one of the VM_FAULT_ERROR types. The default behavior after this call is to make the pte read-write, unless pfn_mkwrite returns an error. - ->access() is called when get_user_pages() fails in +->access() is called when get_user_pages() fails in access_process_vm(), typically used to debug a process through /proc/pid/mem or ptrace. This function is needed only for VM_IO | VM_PFNMAP VMAs. -================================================================================ +-------------------------------------------------------------------------------- + Dubious stuff (if you break something or notice that it is broken and do not fix it yourself diff --git a/Documentation/filesystems/nfs/Exporting b/Documentation/filesystems/nfs/exporting.rst similarity index 91% rename from Documentation/filesystems/nfs/Exporting rename to Documentation/filesystems/nfs/exporting.rst index 63889149f532..33d588a01ace 100644 --- a/Documentation/filesystems/nfs/Exporting +++ b/Documentation/filesystems/nfs/exporting.rst @@ -1,3 +1,4 @@ +:orphan: Making Filesystems Exportable ============================= @@ -42,9 +43,9 @@ filehandle fragment, there is no automatic creation of a path prefix for the object. This leads to two related but distinct features of the dcache that are not needed for normal filesystem access. -1/ The dcache must sometimes contain objects that are not part of the +1. The dcache must sometimes contain objects that are not part of the proper prefix. i.e that are not connected to the root. -2/ The dcache must be prepared for a newly found (via ->lookup) directory +2. The dcache must be prepared for a newly found (via ->lookup) directory to already have a (non-connected) dentry, and must be able to move that dentry into place (based on the parent and name in the ->lookup). This is particularly needed for directories as @@ -52,7 +53,7 @@ the dcache that are not needed for normal filesystem access. To implement these features, the dcache has: -a/ A dentry flag DCACHE_DISCONNECTED which is set on +a. A dentry flag DCACHE_DISCONNECTED which is set on any dentry that might not be part of the proper prefix. This is set when anonymous dentries are created, and cleared when a dentry is noticed to be a child of a dentry which is in the proper @@ -71,48 +72,52 @@ a/ A dentry flag DCACHE_DISCONNECTED which is set on dentries. That guarantees that we won't need to hunt them down upon umount. -b/ A primitive for creation of secondary roots - d_obtain_root(inode). +b. A primitive for creation of secondary roots - d_obtain_root(inode). Those do _not_ bear DCACHE_DISCONNECTED. They are placed on the per-superblock list (->s_roots), so they can be located at umount time for eviction purposes. -c/ Helper routines to allocate anonymous dentries, and to help attach +c. Helper routines to allocate anonymous dentries, and to help attach loose directory dentries at lookup time. They are: + d_obtain_alias(inode) will return a dentry for the given inode. If the inode already has a dentry, one of those is returned. + If it doesn't, a new anonymous (IS_ROOT and - DCACHE_DISCONNECTED) dentry is allocated and attached. + DCACHE_DISCONNECTED) dentry is allocated and attached. + In the case of a directory, care is taken that only one dentry can ever be attached. + d_splice_alias(inode, dentry) will introduce a new dentry into the tree; either the passed-in dentry or a preexisting alias for the given inode (such as an anonymous one created by d_obtain_alias), if appropriate. It returns NULL when the passed-in dentry is used, following the calling convention of ->lookup. - + Filesystem Issues ----------------- For a filesystem to be exportable it must: - - 1/ provide the filehandle fragment routines described below. - 2/ make sure that d_splice_alias is used rather than d_add + + 1. provide the filehandle fragment routines described below. + 2. make sure that d_splice_alias is used rather than d_add when ->lookup finds an inode for a given parent and name. - If inode is NULL, d_splice_alias(inode, dentry) is equivalent to + If inode is NULL, d_splice_alias(inode, dentry) is equivalent to:: d_add(dentry, inode), NULL Similarly, d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err) - Typically the ->lookup routine will simply end with a: + Typically the ->lookup routine will simply end with a:: return d_splice_alias(inode, dentry); } - A file system implementation declares that instances of the filesystem +A file system implementation declares that instances of the filesystem are exportable by setting the s_export_op field in the struct super_block. This field must point to a "struct export_operations" struct which has the following members: diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 0f85ab21c2ca..7d4d09dd5e6d 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -20,7 +20,7 @@ kernel which allows different filesystem implementations to coexist. VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so on are called from a process context. Filesystem locking is described in -the document Documentation/filesystems/Locking. +the document Documentation/filesystems/locking.rst. Directory Entry Cache (dcache) diff --git a/fs/cifs/export.c b/fs/cifs/export.c index ce8b7f677c58..eb0bb8ca8e63 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c @@ -24,7 +24,7 @@ */ /* - * See Documentation/filesystems/nfs/Exporting + * See Documentation/filesystems/nfs/exporting.rst * and examples in fs/exportfs * * Since cifs is a network file system, an "fsid" must be included for diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index f0e549783caf..09bc68708d28 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -7,7 +7,7 @@ * and for mapping back from file handles to dentries. * * For details on why we do all the strange and hairy things in here - * take a look at Documentation/filesystems/nfs/Exporting. + * take a look at Documentation/filesystems/nfs/exporting.rst. */ #include #include diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 85a9093769a9..35768a63fb1d 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -10,7 +10,7 @@ * * The following files are helpful: * - * Documentation/filesystems/nfs/Exporting + * Documentation/filesystems/nfs/exporting.rst * fs/exportfs/expfs.c. */ diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index 960f9a3c012d..a5612abc0936 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -555,7 +555,7 @@ static int orangefs_fsync(struct file *file, * Change the file pointer position for an instance of an open file. * * \note If .llseek is overriden, we must acquire lock as described in - * Documentation/filesystems/Locking. + * Documentation/filesystems/locking.rst. * * Future upgrade could support SEEK_DATA and SEEK_HOLE but would * require much changes to the FS diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 9451011ac014..10090f11ab95 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -151,7 +151,7 @@ struct dentry_operations { /* * Locking rules for dentry_operations callbacks are to be found in - * Documentation/filesystems/Locking. Keep it updated! + * Documentation/filesystems/locking.rst. Keep it updated! * * FUrther descriptions are found in Documentation/filesystems/vfs.rst. * Keep it updated too! diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 0d3037419bc7..cf6571fc9c01 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -139,7 +139,7 @@ struct fid { * @get_parent: find the parent of a given directory * @commit_metadata: commit metadata changes to stable storage * - * See Documentation/filesystems/nfs/Exporting for details on how to use + * See Documentation/filesystems/nfs/exporting.rst for details on how to use * this interface correctly. * * encode_fh: -- GitLab From 25b532cec59ee119bf1c4081fe06fac43722f61f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:28 -0300 Subject: [PATCH 1463/7155] docs: fs: convert porting to ReST This file has its own proper style, except that, after a while, the coding style gets violated and whitespaces are placed on different ways. As Sphinx and ReST are very sentitive to whitespace differences, I had to opt if each entry after required/mandatory/... fields should start with zero spaces or with a tab. I opted to start them all from the zero position, in order to avoid needing to break lines with more than 80 columns, with would make harder for review. Most of the other changes at porting.rst were made to use an unified notation with works nice as a text file while also produce a good html output after being parsed. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/filesystems/index.rst | 2 + Documentation/filesystems/porting | 686 --------------------- Documentation/filesystems/porting.rst | 852 ++++++++++++++++++++++++++ fs/orangefs/orangefs-kernel.h | 2 +- 4 files changed, 855 insertions(+), 687 deletions(-) delete mode 100644 Documentation/filesystems/porting create mode 100644 Documentation/filesystems/porting.rst diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index 08320c35d03b..96653ebefd7e 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -23,6 +23,8 @@ algorithms work. locking directory-locking + porting + Filesystem support layers ========================= diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting deleted file mode 100644 index 6b7a41cfcaed..000000000000 --- a/Documentation/filesystems/porting +++ /dev/null @@ -1,686 +0,0 @@ -Changes since 2.5.0: - ---- -[recommended] - -New helpers: sb_bread(), sb_getblk(), sb_find_get_block(), set_bh(), - sb_set_blocksize() and sb_min_blocksize(). - -Use them. - -(sb_find_get_block() replaces 2.4's get_hash_table()) - ---- -[recommended] - -New methods: ->alloc_inode() and ->destroy_inode(). - -Remove inode->u.foo_inode_i -Declare - struct foo_inode_info { - /* fs-private stuff */ - struct inode vfs_inode; - }; - static inline struct foo_inode_info *FOO_I(struct inode *inode) - { - return list_entry(inode, struct foo_inode_info, vfs_inode); - } - -Use FOO_I(inode) instead of &inode->u.foo_inode_i; - -Add foo_alloc_inode() and foo_destroy_inode() - the former should allocate -foo_inode_info and return the address of ->vfs_inode, the latter should free -FOO_I(inode) (see in-tree filesystems for examples). - -Make them ->alloc_inode and ->destroy_inode in your super_operations. - -Keep in mind that now you need explicit initialization of private data -typically between calling iget_locked() and unlocking the inode. - -At some point that will become mandatory. - ---- -[mandatory] - -Change of file_system_type method (->read_super to ->get_sb) - -->read_super() is no more. Ditto for DECLARE_FSTYPE and DECLARE_FSTYPE_DEV. - -Turn your foo_read_super() into a function that would return 0 in case of -success and negative number in case of error (-EINVAL unless you have more -informative error value to report). Call it foo_fill_super(). Now declare - -int foo_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) -{ - return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super, - mnt); -} - -(or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of -filesystem). - -Replace DECLARE_FSTYPE... with explicit initializer and have ->get_sb set as -foo_get_sb. - ---- -[mandatory] - -Locking change: ->s_vfs_rename_sem is taken only by cross-directory renames. -Most likely there is no need to change anything, but if you relied on -global exclusion between renames for some internal purpose - you need to -change your internal locking. Otherwise exclusion warranties remain the -same (i.e. parents and victim are locked, etc.). - ---- -[informational] - -Now we have the exclusion between ->lookup() and directory removal (by -->rmdir() and ->rename()). If you used to need that exclusion and do -it by internal locking (most of filesystems couldn't care less) - you -can relax your locking. - ---- -[mandatory] - -->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(), -->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename() -and ->readdir() are called without BKL now. Grab it on entry, drop upon return -- that will guarantee the same locking you used to have. If your method or its -parts do not need BKL - better yet, now you can shift lock_kernel() and -unlock_kernel() so that they would protect exactly what needs to be -protected. - ---- -[mandatory] - -BKL is also moved from around sb operations. BKL should have been shifted into -individual fs sb_op functions. If you don't need it, remove it. - ---- -[informational] - -check for ->link() target not being a directory is done by callers. Feel -free to drop it... - ---- -[informational] - -->link() callers hold ->i_mutex on the object we are linking to. Some of your -problems might be over... - ---- -[mandatory] - -new file_system_type method - kill_sb(superblock). If you are converting -an existing filesystem, set it according to ->fs_flags: - FS_REQUIRES_DEV - kill_block_super - FS_LITTER - kill_litter_super - neither - kill_anon_super -FS_LITTER is gone - just remove it from fs_flags. - ---- -[mandatory] - - FS_SINGLE is gone (actually, that had happened back when ->get_sb() -went in - and hadn't been documented ;-/). Just remove it from fs_flags -(and see ->get_sb() entry for other actions). - ---- -[mandatory] - -->setattr() is called without BKL now. Caller _always_ holds ->i_mutex, so -watch for ->i_mutex-grabbing code that might be used by your ->setattr(). -Callers of notify_change() need ->i_mutex now. - ---- -[recommended] - -New super_block field "struct export_operations *s_export_op" for -explicit support for exporting, e.g. via NFS. The structure is fully -documented at its declaration in include/linux/fs.h, and in -Documentation/filesystems/nfs/Exporting. - -Briefly it allows for the definition of decode_fh and encode_fh operations -to encode and decode filehandles, and allows the filesystem to use -a standard helper function for decode_fh, and provide file-system specific -support for this helper, particularly get_parent. - -It is planned that this will be required for exporting once the code -settles down a bit. - -[mandatory] - -s_export_op is now required for exporting a filesystem. -isofs, ext2, ext3, resierfs, fat -can be used as examples of very different filesystems. - ---- -[mandatory] - -iget4() and the read_inode2 callback have been superseded by iget5_locked() -which has the following prototype, - - struct inode *iget5_locked(struct super_block *sb, unsigned long ino, - int (*test)(struct inode *, void *), - int (*set)(struct inode *, void *), - void *data); - -'test' is an additional function that can be used when the inode -number is not sufficient to identify the actual file object. 'set' -should be a non-blocking function that initializes those parts of a -newly created inode to allow the test function to succeed. 'data' is -passed as an opaque value to both test and set functions. - -When the inode has been created by iget5_locked(), it will be returned with the -I_NEW flag set and will still be locked. The filesystem then needs to finalize -the initialization. Once the inode is initialized it must be unlocked by -calling unlock_new_inode(). - -The filesystem is responsible for setting (and possibly testing) i_ino -when appropriate. There is also a simpler iget_locked function that -just takes the superblock and inode number as arguments and does the -test and set for you. - -e.g. - inode = iget_locked(sb, ino); - if (inode->i_state & I_NEW) { - err = read_inode_from_disk(inode); - if (err < 0) { - iget_failed(inode); - return err; - } - unlock_new_inode(inode); - } - -Note that if the process of setting up a new inode fails, then iget_failed() -should be called on the inode to render it dead, and an appropriate error -should be passed back to the caller. - ---- -[recommended] - -->getattr() finally getting used. See instances in nfs, minix, etc. - ---- -[mandatory] - -->revalidate() is gone. If your filesystem had it - provide ->getattr() -and let it call whatever you had as ->revlidate() + (for symlinks that -had ->revalidate()) add calls in ->follow_link()/->readlink(). - ---- -[mandatory] - -->d_parent changes are not protected by BKL anymore. Read access is safe -if at least one of the following is true: - * filesystem has no cross-directory rename() - * we know that parent had been locked (e.g. we are looking at -->d_parent of ->lookup() argument). - * we are called from ->rename(). - * the child's ->d_lock is held -Audit your code and add locking if needed. Notice that any place that is -not protected by the conditions above is risky even in the old tree - you -had been relying on BKL and that's prone to screwups. Old tree had quite -a few holes of that kind - unprotected access to ->d_parent leading to -anything from oops to silent memory corruption. - ---- -[mandatory] - - FS_NOMOUNT is gone. If you use it - just set SB_NOUSER in flags -(see rootfs for one kind of solution and bdev/socket/pipe for another). - ---- -[recommended] - - Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter -is still alive, but only because of the mess in drivers/s390/block/dasd.c. -As soon as it gets fixed is_read_only() will die. - ---- -[mandatory] - -->permission() is called without BKL now. Grab it on entry, drop upon -return - that will guarantee the same locking you used to have. If -your method or its parts do not need BKL - better yet, now you can -shift lock_kernel() and unlock_kernel() so that they would protect -exactly what needs to be protected. - ---- -[mandatory] - -->statfs() is now called without BKL held. BKL should have been -shifted into individual fs sb_op functions where it's not clear that -it's safe to remove it. If you don't need it, remove it. - ---- -[mandatory] - - is_read_only() is gone; use bdev_read_only() instead. - ---- -[mandatory] - - destroy_buffers() is gone; use invalidate_bdev(). - ---- -[mandatory] - - fsync_dev() is gone; use fsync_bdev(). NOTE: lvm breakage is -deliberate; as soon as struct block_device * is propagated in a reasonable -way by that code fixing will become trivial; until then nothing can be -done. - -[mandatory] - - block truncatation on error exit from ->write_begin, and ->direct_IO -moved from generic methods (block_write_begin, cont_write_begin, -nobh_write_begin, blockdev_direct_IO*) to callers. Take a look at -ext2_write_failed and callers for an example. - -[mandatory] - - ->truncate is gone. The whole truncate sequence needs to be -implemented in ->setattr, which is now mandatory for filesystems -implementing on-disk size changes. Start with a copy of the old inode_setattr -and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to -be in order of zeroing blocks using block_truncate_page or similar helpers, -size update and on finally on-disk truncation which should not fail. -setattr_prepare (which used to be inode_change_ok) now includes the size checks -for ATTR_SIZE and must be called in the beginning of ->setattr unconditionally. - -[mandatory] - - ->clear_inode() and ->delete_inode() are gone; ->evict_inode() should -be used instead. It gets called whenever the inode is evicted, whether it has -remaining links or not. Caller does *not* evict the pagecache or inode-associated -metadata buffers; the method has to use truncate_inode_pages_final() to get rid -of those. Caller makes sure async writeback cannot be running for the inode while -(or after) ->evict_inode() is called. - - ->drop_inode() returns int now; it's called on final iput() with -inode->i_lock held and it returns true if filesystems wants the inode to be -dropped. As before, generic_drop_inode() is still the default and it's been -updated appropriately. generic_delete_inode() is also alive and it consists -simply of return 1. Note that all actual eviction work is done by caller after -->drop_inode() returns. - - As before, clear_inode() must be called exactly once on each call of -->evict_inode() (as it used to be for each call of ->delete_inode()). Unlike -before, if you are using inode-associated metadata buffers (i.e. -mark_buffer_dirty_inode()), it's your responsibility to call -invalidate_inode_buffers() before clear_inode(). - - NOTE: checking i_nlink in the beginning of ->write_inode() and bailing out -if it's zero is not *and* *never* *had* *been* enough. Final unlink() and iput() -may happen while the inode is in the middle of ->write_inode(); e.g. if you blindly -free the on-disk inode, you may end up doing that while ->write_inode() is writing -to it. - ---- -[mandatory] - - .d_delete() now only advises the dcache as to whether or not to cache -unreferenced dentries, and is now only called when the dentry refcount goes to -0. Even on 0 refcount transition, it must be able to tolerate being called 0, -1, or more times (eg. constant, idempotent). - ---- -[mandatory] - - .d_compare() calling convention and locking rules are significantly -changed. Read updated documentation in Documentation/filesystems/vfs.rst (and -look at examples of other filesystems) for guidance. - ---- -[mandatory] - - .d_hash() calling convention and locking rules are significantly -changed. Read updated documentation in Documentation/filesystems/vfs.rst (and -look at examples of other filesystems) for guidance. - ---- -[mandatory] - dcache_lock is gone, replaced by fine grained locks. See fs/dcache.c -for details of what locks to replace dcache_lock with in order to protect -particular things. Most of the time, a filesystem only needs ->d_lock, which -protects *all* the dcache state of a given dentry. - --- -[mandatory] - - Filesystems must RCU-free their inodes, if they can have been accessed -via rcu-walk path walk (basically, if the file can have had a path name in the -vfs namespace). - - Even though i_dentry and i_rcu share storage in a union, we will -initialize the former in inode_init_always(), so just leave it alone in -the callback. It used to be necessary to clean it there, but not anymore -(starting at 3.2). - --- -[recommended] - vfs now tries to do path walking in "rcu-walk mode", which avoids -atomic operations and scalability hazards on dentries and inodes (see -Documentation/filesystems/path-lookup.txt). d_hash and d_compare changes -(above) are examples of the changes required to support this. For more complex -filesystem callbacks, the vfs drops out of rcu-walk mode before the fs call, so -no changes are required to the filesystem. However, this is costly and loses -the benefits of rcu-walk mode. We will begin to add filesystem callbacks that -are rcu-walk aware, shown below. Filesystems should take advantage of this -where possible. - --- -[mandatory] - d_revalidate is a callback that is made on every path element (if -the filesystem provides it), which requires dropping out of rcu-walk mode. This -may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be -returned if the filesystem cannot handle rcu-walk. See -Documentation/filesystems/vfs.rst for more details. - - permission is an inode permission check that is called on many or all -directory inodes on the way down a path walk (to check for exec permission). It -must now be rcu-walk aware (mask & MAY_NOT_BLOCK). See -Documentation/filesystems/vfs.rst for more details. - --- -[mandatory] - In ->fallocate() you must check the mode option passed in. If your -filesystem does not support hole punching (deallocating space in the middle of a -file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode. -Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set, -so the i_size should not change when hole punching, even when puching the end of -a file off. - --- -[mandatory] - ->get_sb() is gone. Switch to use of ->mount(). Typically it's just -a matter of switching from calling get_sb_... to mount_... and changing the -function type. If you were doing it manually, just switch from setting ->mnt_root -to some pointer to returning that pointer. On errors return ERR_PTR(...). - --- -[mandatory] - ->permission() and generic_permission()have lost flags -argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask. - generic_permission() has also lost the check_acl argument; ACL checking -has been taken to VFS and filesystems need to provide a non-NULL ->i_op->get_acl -to read an ACL from disk. - --- -[mandatory] - If you implement your own ->llseek() you must handle SEEK_HOLE and -SEEK_DATA. You can hanle this by returning -EINVAL, but it would be nicer to -support it in some way. The generic handler assumes that the entire file is -data and there is a virtual hole at the end of the file. So if the provided -offset is less than i_size and SEEK_DATA is specified, return the same offset. -If the above is true for the offset and you are given SEEK_HOLE, return the end -of the file. If the offset is i_size or greater return -ENXIO in either case. - -[mandatory] - If you have your own ->fsync() you must make sure to call -filemap_write_and_wait_range() so that all dirty pages are synced out properly. -You must also keep in mind that ->fsync() is not called with i_mutex held -anymore, so if you require i_mutex locking you must make sure to take it and -release it yourself. - --- -[mandatory] - d_alloc_root() is gone, along with a lot of bugs caused by code -misusing it. Replacement: d_make_root(inode). On success d_make_root(inode) -allocates and returns a new dentry instantiated with the passed in inode. -On failure NULL is returned and the passed in inode is dropped so the reference -to inode is consumed in all cases and failure handling need not do any cleanup -for the inode. If d_make_root(inode) is passed a NULL inode it returns NULL -and also requires no further error handling. Typical usage is: - - inode = foofs_new_inode(....); - s->s_root = d_make_root(inode); - if (!s->s_root) - /* Nothing needed for the inode cleanup */ - return -ENOMEM; - ... - --- -[mandatory] - The witch is dead! Well, 2/3 of it, anyway. ->d_revalidate() and -->lookup() do *not* take struct nameidata anymore; just the flags. --- -[mandatory] - ->create() doesn't take struct nameidata *; unlike the previous -two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that -local filesystems can ignore tha argument - they are guaranteed that the -object doesn't exist. It's remote/distributed ones that might care... --- -[mandatory] - FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate() -in your dentry operations instead. --- -[mandatory] - vfs_readdir() is gone; switch to iterate_dir() instead --- -[mandatory] - ->readdir() is gone now; switch to ->iterate() -[mandatory] - vfs_follow_link has been removed. Filesystems must use nd_set_link - from ->follow_link for normal symlinks, or nd_jump_link for magic - /proc/ style links. --- -[mandatory] - iget5_locked()/ilookup5()/ilookup5_nowait() test() callback used to be - called with both ->i_lock and inode_hash_lock held; the former is *not* - taken anymore, so verify that your callbacks do not rely on it (none - of the in-tree instances did). inode_hash_lock is still held, - of course, so they are still serialized wrt removal from inode hash, - as well as wrt set() callback of iget5_locked(). --- -[mandatory] - d_materialise_unique() is gone; d_splice_alias() does everything you - need now. Remember that they have opposite orders of arguments ;-/ --- -[mandatory] - f_dentry is gone; use f_path.dentry, or, better yet, see if you can avoid - it entirely. --- -[mandatory] - never call ->read() and ->write() directly; use __vfs_{read,write} or - wrappers; instead of checking for ->write or ->read being NULL, look for - FMODE_CAN_{WRITE,READ} in file->f_mode. --- -[mandatory] - do _not_ use new_sync_{read,write} for ->read/->write; leave it NULL - instead. --- -[mandatory] - ->aio_read/->aio_write are gone. Use ->read_iter/->write_iter. ---- -[recommended] - for embedded ("fast") symlinks just set inode->i_link to wherever the - symlink body is and use simple_follow_link() as ->follow_link(). --- -[mandatory] - calling conventions for ->follow_link() have changed. Instead of returning - cookie and using nd_set_link() to store the body to traverse, we return - the body to traverse and store the cookie using explicit void ** argument. - nameidata isn't passed at all - nd_jump_link() doesn't need it and - nd_[gs]et_link() is gone. --- -[mandatory] - calling conventions for ->put_link() have changed. It gets inode instead of - dentry, it does not get nameidata at all and it gets called only when cookie - is non-NULL. Note that link body isn't available anymore, so if you need it, - store it as cookie. --- -[mandatory] - any symlink that might use page_follow_link_light/page_put_link() must - have inode_nohighmem(inode) called before anything might start playing with - its pagecache. No highmem pages should end up in the pagecache of such - symlinks. That includes any preseeding that might be done during symlink - creation. __page_symlink() will honour the mapping gfp flags, so once - you've done inode_nohighmem() it's safe to use, but if you allocate and - insert the page manually, make sure to use the right gfp flags. --- -[mandatory] - ->follow_link() is replaced with ->get_link(); same API, except that - * ->get_link() gets inode as a separate argument - * ->get_link() may be called in RCU mode - in that case NULL - dentry is passed --- -[mandatory] - ->get_link() gets struct delayed_call *done now, and should do - set_delayed_call() where it used to set *cookie. - ->put_link() is gone - just give the destructor to set_delayed_call() - in ->get_link(). --- -[mandatory] - ->getxattr() and xattr_handler.get() get dentry and inode passed separately. - dentry might be yet to be attached to inode, so do _not_ use its ->d_inode - in the instances. Rationale: !@#!@# security_d_instantiate() needs to be - called before we attach dentry to inode. --- -[mandatory] - symlinks are no longer the only inodes that do *not* have i_bdev/i_cdev/ - i_pipe/i_link union zeroed out at inode eviction. As the result, you can't - assume that non-NULL value in ->i_nlink at ->destroy_inode() implies that - it's a symlink. Checking ->i_mode is really needed now. In-tree we had - to fix shmem_destroy_callback() that used to take that kind of shortcut; - watch out, since that shortcut is no longer valid. --- -[mandatory] - ->i_mutex is replaced with ->i_rwsem now. inode_lock() et.al. work as - they used to - they just take it exclusive. However, ->lookup() may be - called with parent locked shared. Its instances must not - * use d_instantiate) and d_rehash() separately - use d_add() or - d_splice_alias() instead. - * use d_rehash() alone - call d_add(new_dentry, NULL) instead. - * in the unlikely case when (read-only) access to filesystem - data structures needs exclusion for some reason, arrange it - yourself. None of the in-tree filesystems needed that. - * rely on ->d_parent and ->d_name not changing after dentry has - been fed to d_add() or d_splice_alias(). Again, none of the - in-tree instances relied upon that. - We are guaranteed that lookups of the same name in the same directory - will not happen in parallel ("same" in the sense of your ->d_compare()). - Lookups on different names in the same directory can and do happen in - parallel now. --- -[recommended] - ->iterate_shared() is added; it's a parallel variant of ->iterate(). - Exclusion on struct file level is still provided (as well as that - between it and lseek on the same struct file), but if your directory - has been opened several times, you can get these called in parallel. - Exclusion between that method and all directory-modifying ones is - still provided, of course. - - Often enough ->iterate() can serve as ->iterate_shared() without any - changes - it is a read-only operation, after all. If you have any - per-inode or per-dentry in-core data structures modified by ->iterate(), - you might need something to serialize the access to them. If you - do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for - that; look for in-tree examples. - - Old method is only used if the new one is absent; eventually it will - be removed. Switch while you still can; the old one won't stay. --- -[mandatory] - ->atomic_open() calls without O_CREAT may happen in parallel. --- -[mandatory] - ->setxattr() and xattr_handler.set() get dentry and inode passed separately. - dentry might be yet to be attached to inode, so do _not_ use its ->d_inode - in the instances. Rationale: !@#!@# security_d_instantiate() needs to be - called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack - ->d_instantiate() uses not just ->getxattr() but ->setxattr() as well. --- -[mandatory] - ->d_compare() doesn't get parent as a separate argument anymore. If you - used it for finding the struct super_block involved, dentry->d_sb will - work just as well; if it's something more complicated, use dentry->d_parent. - Just be careful not to assume that fetching it more than once will yield - the same value - in RCU mode it could change under you. --- -[mandatory] - ->rename() has an added flags argument. Any flags not handled by the - filesystem should result in EINVAL being returned. --- -[recommended] - ->readlink is optional for symlinks. Don't set, unless filesystem needs - to fake something for readlink(2). --- -[mandatory] - ->getattr() is now passed a struct path rather than a vfsmount and - dentry separately, and it now has request_mask and query_flags arguments - to specify the fields and sync type requested by statx. Filesystems not - supporting any statx-specific features may ignore the new arguments. --- -[mandatory] - ->atomic_open() calling conventions have changed. Gone is int *opened, - along with FILE_OPENED/FILE_CREATED. In place of those we have - FMODE_OPENED/FMODE_CREATED, set in file->f_mode. Additionally, return - value for 'called finish_no_open(), open it yourself' case has become - 0, not 1. Since finish_no_open() itself is returning 0 now, that part - does not need any changes in ->atomic_open() instances. --- -[mandatory] - alloc_file() has become static now; two wrappers are to be used instead. - alloc_file_pseudo(inode, vfsmount, name, flags, ops) is for the cases - when dentry needs to be created; that's the majority of old alloc_file() - users. Calling conventions: on success a reference to new struct file - is returned and callers reference to inode is subsumed by that. On - failure, ERR_PTR() is returned and no caller's references are affected, - so the caller needs to drop the inode reference it held. - alloc_file_clone(file, flags, ops) does not affect any caller's references. - On success you get a new struct file sharing the mount/dentry with the - original, on failure - ERR_PTR(). --- -[mandatory] - ->clone_file_range() and ->dedupe_file_range have been replaced with - ->remap_file_range(). See Documentation/filesystems/vfs.rst for more - information. --- -[recommended] - ->lookup() instances doing an equivalent of - if (IS_ERR(inode)) - return ERR_CAST(inode); - return d_splice_alias(inode, dentry); - don't need to bother with the check - d_splice_alias() will do the - right thing when given ERR_PTR(...) as inode. Moreover, passing NULL - inode to d_splice_alias() will also do the right thing (equivalent of - d_add(dentry, NULL); return NULL;), so that kind of special cases - also doesn't need a separate treatment. --- -[strongly recommended] - take the RCU-delayed parts of ->destroy_inode() into a new method - - ->free_inode(). If ->destroy_inode() becomes empty - all the better, - just get rid of it. Synchronous work (e.g. the stuff that can't - be done from an RCU callback, or any WARN_ON() where we want the - stack trace) *might* be movable to ->evict_inode(); however, - that goes only for the things that are not needed to balance something - done by ->alloc_inode(). IOW, if it's cleaning up the stuff that - might have accumulated over the life of in-core inode, ->evict_inode() - might be a fit. - - Rules for inode destruction: - * if ->destroy_inode() is non-NULL, it gets called - * if ->free_inode() is non-NULL, it gets scheduled by call_rcu() - * combination of NULL ->destroy_inode and NULL ->free_inode is - treated as NULL/free_inode_nonrcu, to preserve the compatibility. - - Note that the callback (be it via ->free_inode() or explicit call_rcu() - in ->destroy_inode()) is *NOT* ordered wrt superblock destruction; - as the matter of fact, the superblock and all associated structures - might be already gone. The filesystem driver is guaranteed to be still - there, but that's it. Freeing memory in the callback is fine; doing - more than that is possible, but requires a lot of care and is best - avoided. --- -[mandatory] - DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the - default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any - business doing so. --- -[mandatory] - d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are - very suspect (and won't work in modules). Such uses are very likely to - be misspelled d_alloc_anon(). diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst new file mode 100644 index 000000000000..66aa521e6376 --- /dev/null +++ b/Documentation/filesystems/porting.rst @@ -0,0 +1,852 @@ +==================== +Changes since 2.5.0: +==================== + +--- + +**recommended** + +New helpers: sb_bread(), sb_getblk(), sb_find_get_block(), set_bh(), +sb_set_blocksize() and sb_min_blocksize(). + +Use them. + +(sb_find_get_block() replaces 2.4's get_hash_table()) + +--- + +**recommended** + +New methods: ->alloc_inode() and ->destroy_inode(). + +Remove inode->u.foo_inode_i + +Declare:: + + struct foo_inode_info { + /* fs-private stuff */ + struct inode vfs_inode; + }; + static inline struct foo_inode_info *FOO_I(struct inode *inode) + { + return list_entry(inode, struct foo_inode_info, vfs_inode); + } + +Use FOO_I(inode) instead of &inode->u.foo_inode_i; + +Add foo_alloc_inode() and foo_destroy_inode() - the former should allocate +foo_inode_info and return the address of ->vfs_inode, the latter should free +FOO_I(inode) (see in-tree filesystems for examples). + +Make them ->alloc_inode and ->destroy_inode in your super_operations. + +Keep in mind that now you need explicit initialization of private data +typically between calling iget_locked() and unlocking the inode. + +At some point that will become mandatory. + +--- + +**mandatory** + +Change of file_system_type method (->read_super to ->get_sb) + +->read_super() is no more. Ditto for DECLARE_FSTYPE and DECLARE_FSTYPE_DEV. + +Turn your foo_read_super() into a function that would return 0 in case of +success and negative number in case of error (-EINVAL unless you have more +informative error value to report). Call it foo_fill_super(). Now declare:: + + int foo_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) + { + return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super, + mnt); + } + +(or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of +filesystem). + +Replace DECLARE_FSTYPE... with explicit initializer and have ->get_sb set as +foo_get_sb. + +--- + +**mandatory** + +Locking change: ->s_vfs_rename_sem is taken only by cross-directory renames. +Most likely there is no need to change anything, but if you relied on +global exclusion between renames for some internal purpose - you need to +change your internal locking. Otherwise exclusion warranties remain the +same (i.e. parents and victim are locked, etc.). + +--- + +**informational** + +Now we have the exclusion between ->lookup() and directory removal (by +->rmdir() and ->rename()). If you used to need that exclusion and do +it by internal locking (most of filesystems couldn't care less) - you +can relax your locking. + +--- + +**mandatory** + +->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(), +->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename() +and ->readdir() are called without BKL now. Grab it on entry, drop upon return +- that will guarantee the same locking you used to have. If your method or its +parts do not need BKL - better yet, now you can shift lock_kernel() and +unlock_kernel() so that they would protect exactly what needs to be +protected. + +--- + +**mandatory** + +BKL is also moved from around sb operations. BKL should have been shifted into +individual fs sb_op functions. If you don't need it, remove it. + +--- + +**informational** + +check for ->link() target not being a directory is done by callers. Feel +free to drop it... + +--- + +**informational** + +->link() callers hold ->i_mutex on the object we are linking to. Some of your +problems might be over... + +--- + +**mandatory** + +new file_system_type method - kill_sb(superblock). If you are converting +an existing filesystem, set it according to ->fs_flags:: + + FS_REQUIRES_DEV - kill_block_super + FS_LITTER - kill_litter_super + neither - kill_anon_super + +FS_LITTER is gone - just remove it from fs_flags. + +--- + +**mandatory** + +FS_SINGLE is gone (actually, that had happened back when ->get_sb() +went in - and hadn't been documented ;-/). Just remove it from fs_flags +(and see ->get_sb() entry for other actions). + +--- + +**mandatory** + +->setattr() is called without BKL now. Caller _always_ holds ->i_mutex, so +watch for ->i_mutex-grabbing code that might be used by your ->setattr(). +Callers of notify_change() need ->i_mutex now. + +--- + +**recommended** + +New super_block field ``struct export_operations *s_export_op`` for +explicit support for exporting, e.g. via NFS. The structure is fully +documented at its declaration in include/linux/fs.h, and in +Documentation/filesystems/nfs/Exporting. + +Briefly it allows for the definition of decode_fh and encode_fh operations +to encode and decode filehandles, and allows the filesystem to use +a standard helper function for decode_fh, and provide file-system specific +support for this helper, particularly get_parent. + +It is planned that this will be required for exporting once the code +settles down a bit. + +**mandatory** + +s_export_op is now required for exporting a filesystem. +isofs, ext2, ext3, resierfs, fat +can be used as examples of very different filesystems. + +--- + +**mandatory** + +iget4() and the read_inode2 callback have been superseded by iget5_locked() +which has the following prototype:: + + struct inode *iget5_locked(struct super_block *sb, unsigned long ino, + int (*test)(struct inode *, void *), + int (*set)(struct inode *, void *), + void *data); + +'test' is an additional function that can be used when the inode +number is not sufficient to identify the actual file object. 'set' +should be a non-blocking function that initializes those parts of a +newly created inode to allow the test function to succeed. 'data' is +passed as an opaque value to both test and set functions. + +When the inode has been created by iget5_locked(), it will be returned with the +I_NEW flag set and will still be locked. The filesystem then needs to finalize +the initialization. Once the inode is initialized it must be unlocked by +calling unlock_new_inode(). + +The filesystem is responsible for setting (and possibly testing) i_ino +when appropriate. There is also a simpler iget_locked function that +just takes the superblock and inode number as arguments and does the +test and set for you. + +e.g.:: + + inode = iget_locked(sb, ino); + if (inode->i_state & I_NEW) { + err = read_inode_from_disk(inode); + if (err < 0) { + iget_failed(inode); + return err; + } + unlock_new_inode(inode); + } + +Note that if the process of setting up a new inode fails, then iget_failed() +should be called on the inode to render it dead, and an appropriate error +should be passed back to the caller. + +--- + +**recommended** + +->getattr() finally getting used. See instances in nfs, minix, etc. + +--- + +**mandatory** + +->revalidate() is gone. If your filesystem had it - provide ->getattr() +and let it call whatever you had as ->revlidate() + (for symlinks that +had ->revalidate()) add calls in ->follow_link()/->readlink(). + +--- + +**mandatory** + +->d_parent changes are not protected by BKL anymore. Read access is safe +if at least one of the following is true: + + * filesystem has no cross-directory rename() + * we know that parent had been locked (e.g. we are looking at + ->d_parent of ->lookup() argument). + * we are called from ->rename(). + * the child's ->d_lock is held + +Audit your code and add locking if needed. Notice that any place that is +not protected by the conditions above is risky even in the old tree - you +had been relying on BKL and that's prone to screwups. Old tree had quite +a few holes of that kind - unprotected access to ->d_parent leading to +anything from oops to silent memory corruption. + +--- + +**mandatory** + +FS_NOMOUNT is gone. If you use it - just set SB_NOUSER in flags +(see rootfs for one kind of solution and bdev/socket/pipe for another). + +--- + +**recommended** + +Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter +is still alive, but only because of the mess in drivers/s390/block/dasd.c. +As soon as it gets fixed is_read_only() will die. + +--- + +**mandatory** + +->permission() is called without BKL now. Grab it on entry, drop upon +return - that will guarantee the same locking you used to have. If +your method or its parts do not need BKL - better yet, now you can +shift lock_kernel() and unlock_kernel() so that they would protect +exactly what needs to be protected. + +--- + +**mandatory** + +->statfs() is now called without BKL held. BKL should have been +shifted into individual fs sb_op functions where it's not clear that +it's safe to remove it. If you don't need it, remove it. + +--- + +**mandatory** + +is_read_only() is gone; use bdev_read_only() instead. + +--- + +**mandatory** + +destroy_buffers() is gone; use invalidate_bdev(). + +--- + +**mandatory** + +fsync_dev() is gone; use fsync_bdev(). NOTE: lvm breakage is +deliberate; as soon as struct block_device * is propagated in a reasonable +way by that code fixing will become trivial; until then nothing can be +done. + +**mandatory** + +block truncatation on error exit from ->write_begin, and ->direct_IO +moved from generic methods (block_write_begin, cont_write_begin, +nobh_write_begin, blockdev_direct_IO*) to callers. Take a look at +ext2_write_failed and callers for an example. + +**mandatory** + +->truncate is gone. The whole truncate sequence needs to be +implemented in ->setattr, which is now mandatory for filesystems +implementing on-disk size changes. Start with a copy of the old inode_setattr +and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to +be in order of zeroing blocks using block_truncate_page or similar helpers, +size update and on finally on-disk truncation which should not fail. +setattr_prepare (which used to be inode_change_ok) now includes the size checks +for ATTR_SIZE and must be called in the beginning of ->setattr unconditionally. + +**mandatory** + +->clear_inode() and ->delete_inode() are gone; ->evict_inode() should +be used instead. It gets called whenever the inode is evicted, whether it has +remaining links or not. Caller does *not* evict the pagecache or inode-associated +metadata buffers; the method has to use truncate_inode_pages_final() to get rid +of those. Caller makes sure async writeback cannot be running for the inode while +(or after) ->evict_inode() is called. + +->drop_inode() returns int now; it's called on final iput() with +inode->i_lock held and it returns true if filesystems wants the inode to be +dropped. As before, generic_drop_inode() is still the default and it's been +updated appropriately. generic_delete_inode() is also alive and it consists +simply of return 1. Note that all actual eviction work is done by caller after +->drop_inode() returns. + +As before, clear_inode() must be called exactly once on each call of +->evict_inode() (as it used to be for each call of ->delete_inode()). Unlike +before, if you are using inode-associated metadata buffers (i.e. +mark_buffer_dirty_inode()), it's your responsibility to call +invalidate_inode_buffers() before clear_inode(). + +NOTE: checking i_nlink in the beginning of ->write_inode() and bailing out +if it's zero is not *and* *never* *had* *been* enough. Final unlink() and iput() +may happen while the inode is in the middle of ->write_inode(); e.g. if you blindly +free the on-disk inode, you may end up doing that while ->write_inode() is writing +to it. + +--- + +**mandatory** + +.d_delete() now only advises the dcache as to whether or not to cache +unreferenced dentries, and is now only called when the dentry refcount goes to +0. Even on 0 refcount transition, it must be able to tolerate being called 0, +1, or more times (eg. constant, idempotent). + +--- + +**mandatory** + +.d_compare() calling convention and locking rules are significantly +changed. Read updated documentation in Documentation/filesystems/vfs.rst (and +look at examples of other filesystems) for guidance. + +--- + +**mandatory** + +.d_hash() calling convention and locking rules are significantly +changed. Read updated documentation in Documentation/filesystems/vfs.rst (and +look at examples of other filesystems) for guidance. + +--- + +**mandatory** + +dcache_lock is gone, replaced by fine grained locks. See fs/dcache.c +for details of what locks to replace dcache_lock with in order to protect +particular things. Most of the time, a filesystem only needs ->d_lock, which +protects *all* the dcache state of a given dentry. + +--- + +**mandatory** + +Filesystems must RCU-free their inodes, if they can have been accessed +via rcu-walk path walk (basically, if the file can have had a path name in the +vfs namespace). + +Even though i_dentry and i_rcu share storage in a union, we will +initialize the former in inode_init_always(), so just leave it alone in +the callback. It used to be necessary to clean it there, but not anymore +(starting at 3.2). + +--- + +**recommended** + +vfs now tries to do path walking in "rcu-walk mode", which avoids +atomic operations and scalability hazards on dentries and inodes (see +Documentation/filesystems/path-lookup.txt). d_hash and d_compare changes +(above) are examples of the changes required to support this. For more complex +filesystem callbacks, the vfs drops out of rcu-walk mode before the fs call, so +no changes are required to the filesystem. However, this is costly and loses +the benefits of rcu-walk mode. We will begin to add filesystem callbacks that +are rcu-walk aware, shown below. Filesystems should take advantage of this +where possible. + +--- + +**mandatory** + +d_revalidate is a callback that is made on every path element (if +the filesystem provides it), which requires dropping out of rcu-walk mode. This +may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be +returned if the filesystem cannot handle rcu-walk. See +Documentation/filesystems/vfs.rst for more details. + +permission is an inode permission check that is called on many or all +directory inodes on the way down a path walk (to check for exec permission). It +must now be rcu-walk aware (mask & MAY_NOT_BLOCK). See +Documentation/filesystems/vfs.rst for more details. + +--- + +**mandatory** + +In ->fallocate() you must check the mode option passed in. If your +filesystem does not support hole punching (deallocating space in the middle of a +file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode. +Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set, +so the i_size should not change when hole punching, even when puching the end of +a file off. + +--- + +**mandatory** + +->get_sb() is gone. Switch to use of ->mount(). Typically it's just +a matter of switching from calling ``get_sb_``... to ``mount_``... and changing +the function type. If you were doing it manually, just switch from setting +->mnt_root to some pointer to returning that pointer. On errors return +ERR_PTR(...). + +--- + +**mandatory** + +->permission() and generic_permission()have lost flags +argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask. + +generic_permission() has also lost the check_acl argument; ACL checking +has been taken to VFS and filesystems need to provide a non-NULL ->i_op->get_acl +to read an ACL from disk. + +--- + +**mandatory** + +If you implement your own ->llseek() you must handle SEEK_HOLE and +SEEK_DATA. You can hanle this by returning -EINVAL, but it would be nicer to +support it in some way. The generic handler assumes that the entire file is +data and there is a virtual hole at the end of the file. So if the provided +offset is less than i_size and SEEK_DATA is specified, return the same offset. +If the above is true for the offset and you are given SEEK_HOLE, return the end +of the file. If the offset is i_size or greater return -ENXIO in either case. + +**mandatory** + +If you have your own ->fsync() you must make sure to call +filemap_write_and_wait_range() so that all dirty pages are synced out properly. +You must also keep in mind that ->fsync() is not called with i_mutex held +anymore, so if you require i_mutex locking you must make sure to take it and +release it yourself. + +--- + +**mandatory** + +d_alloc_root() is gone, along with a lot of bugs caused by code +misusing it. Replacement: d_make_root(inode). On success d_make_root(inode) +allocates and returns a new dentry instantiated with the passed in inode. +On failure NULL is returned and the passed in inode is dropped so the reference +to inode is consumed in all cases and failure handling need not do any cleanup +for the inode. If d_make_root(inode) is passed a NULL inode it returns NULL +and also requires no further error handling. Typical usage is:: + + inode = foofs_new_inode(....); + s->s_root = d_make_root(inode); + if (!s->s_root) + /* Nothing needed for the inode cleanup */ + return -ENOMEM; + ... + +--- + +**mandatory** + +The witch is dead! Well, 2/3 of it, anyway. ->d_revalidate() and +->lookup() do *not* take struct nameidata anymore; just the flags. + +--- + +**mandatory** + +->create() doesn't take ``struct nameidata *``; unlike the previous +two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that +local filesystems can ignore tha argument - they are guaranteed that the +object doesn't exist. It's remote/distributed ones that might care... + +--- + +**mandatory** + +FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate() +in your dentry operations instead. + +--- + +**mandatory** + +vfs_readdir() is gone; switch to iterate_dir() instead + +--- + +**mandatory** + +->readdir() is gone now; switch to ->iterate() + +**mandatory** + +vfs_follow_link has been removed. Filesystems must use nd_set_link +from ->follow_link for normal symlinks, or nd_jump_link for magic +/proc/ style links. + +--- + +**mandatory** + +iget5_locked()/ilookup5()/ilookup5_nowait() test() callback used to be +called with both ->i_lock and inode_hash_lock held; the former is *not* +taken anymore, so verify that your callbacks do not rely on it (none +of the in-tree instances did). inode_hash_lock is still held, +of course, so they are still serialized wrt removal from inode hash, +as well as wrt set() callback of iget5_locked(). + +--- + +**mandatory** + +d_materialise_unique() is gone; d_splice_alias() does everything you +need now. Remember that they have opposite orders of arguments ;-/ + +--- + +**mandatory** + +f_dentry is gone; use f_path.dentry, or, better yet, see if you can avoid +it entirely. + +--- + +**mandatory** + +never call ->read() and ->write() directly; use __vfs_{read,write} or +wrappers; instead of checking for ->write or ->read being NULL, look for +FMODE_CAN_{WRITE,READ} in file->f_mode. + +--- + +**mandatory** + +do _not_ use new_sync_{read,write} for ->read/->write; leave it NULL +instead. + +--- + +**mandatory** + ->aio_read/->aio_write are gone. Use ->read_iter/->write_iter. + +--- + +**recommended** + +for embedded ("fast") symlinks just set inode->i_link to wherever the +symlink body is and use simple_follow_link() as ->follow_link(). + +--- + +**mandatory** + +calling conventions for ->follow_link() have changed. Instead of returning +cookie and using nd_set_link() to store the body to traverse, we return +the body to traverse and store the cookie using explicit void ** argument. +nameidata isn't passed at all - nd_jump_link() doesn't need it and +nd_[gs]et_link() is gone. + +--- + +**mandatory** + +calling conventions for ->put_link() have changed. It gets inode instead of +dentry, it does not get nameidata at all and it gets called only when cookie +is non-NULL. Note that link body isn't available anymore, so if you need it, +store it as cookie. + +--- + +**mandatory** + +any symlink that might use page_follow_link_light/page_put_link() must +have inode_nohighmem(inode) called before anything might start playing with +its pagecache. No highmem pages should end up in the pagecache of such +symlinks. That includes any preseeding that might be done during symlink +creation. __page_symlink() will honour the mapping gfp flags, so once +you've done inode_nohighmem() it's safe to use, but if you allocate and +insert the page manually, make sure to use the right gfp flags. + +--- + +**mandatory** + +->follow_link() is replaced with ->get_link(); same API, except that + + * ->get_link() gets inode as a separate argument + * ->get_link() may be called in RCU mode - in that case NULL + dentry is passed + +--- + +**mandatory** + +->get_link() gets struct delayed_call ``*done`` now, and should do +set_delayed_call() where it used to set ``*cookie``. + +->put_link() is gone - just give the destructor to set_delayed_call() +in ->get_link(). + +--- + +**mandatory** + +->getxattr() and xattr_handler.get() get dentry and inode passed separately. +dentry might be yet to be attached to inode, so do _not_ use its ->d_inode +in the instances. Rationale: !@#!@# security_d_instantiate() needs to be +called before we attach dentry to inode. + +--- + +**mandatory** + +symlinks are no longer the only inodes that do *not* have i_bdev/i_cdev/ +i_pipe/i_link union zeroed out at inode eviction. As the result, you can't +assume that non-NULL value in ->i_nlink at ->destroy_inode() implies that +it's a symlink. Checking ->i_mode is really needed now. In-tree we had +to fix shmem_destroy_callback() that used to take that kind of shortcut; +watch out, since that shortcut is no longer valid. + +--- + +**mandatory** + +->i_mutex is replaced with ->i_rwsem now. inode_lock() et.al. work as +they used to - they just take it exclusive. However, ->lookup() may be +called with parent locked shared. Its instances must not + + * use d_instantiate) and d_rehash() separately - use d_add() or + d_splice_alias() instead. + * use d_rehash() alone - call d_add(new_dentry, NULL) instead. + * in the unlikely case when (read-only) access to filesystem + data structures needs exclusion for some reason, arrange it + yourself. None of the in-tree filesystems needed that. + * rely on ->d_parent and ->d_name not changing after dentry has + been fed to d_add() or d_splice_alias(). Again, none of the + in-tree instances relied upon that. + +We are guaranteed that lookups of the same name in the same directory +will not happen in parallel ("same" in the sense of your ->d_compare()). +Lookups on different names in the same directory can and do happen in +parallel now. + +--- + +**recommended** + +->iterate_shared() is added; it's a parallel variant of ->iterate(). +Exclusion on struct file level is still provided (as well as that +between it and lseek on the same struct file), but if your directory +has been opened several times, you can get these called in parallel. +Exclusion between that method and all directory-modifying ones is +still provided, of course. + +Often enough ->iterate() can serve as ->iterate_shared() without any +changes - it is a read-only operation, after all. If you have any +per-inode or per-dentry in-core data structures modified by ->iterate(), +you might need something to serialize the access to them. If you +do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for +that; look for in-tree examples. + +Old method is only used if the new one is absent; eventually it will +be removed. Switch while you still can; the old one won't stay. + +--- + +**mandatory** + +->atomic_open() calls without O_CREAT may happen in parallel. + +--- + +**mandatory** + +->setxattr() and xattr_handler.set() get dentry and inode passed separately. +dentry might be yet to be attached to inode, so do _not_ use its ->d_inode +in the instances. Rationale: !@#!@# security_d_instantiate() needs to be +called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack +->d_instantiate() uses not just ->getxattr() but ->setxattr() as well. + +--- + +**mandatory** + +->d_compare() doesn't get parent as a separate argument anymore. If you +used it for finding the struct super_block involved, dentry->d_sb will +work just as well; if it's something more complicated, use dentry->d_parent. +Just be careful not to assume that fetching it more than once will yield +the same value - in RCU mode it could change under you. + +--- + +**mandatory** + +->rename() has an added flags argument. Any flags not handled by the +filesystem should result in EINVAL being returned. + +--- + + +**recommended** + +->readlink is optional for symlinks. Don't set, unless filesystem needs +to fake something for readlink(2). + +--- + +**mandatory** + +->getattr() is now passed a struct path rather than a vfsmount and +dentry separately, and it now has request_mask and query_flags arguments +to specify the fields and sync type requested by statx. Filesystems not +supporting any statx-specific features may ignore the new arguments. + +--- + +**mandatory** + +->atomic_open() calling conventions have changed. Gone is ``int *opened``, +along with FILE_OPENED/FILE_CREATED. In place of those we have +FMODE_OPENED/FMODE_CREATED, set in file->f_mode. Additionally, return +value for 'called finish_no_open(), open it yourself' case has become +0, not 1. Since finish_no_open() itself is returning 0 now, that part +does not need any changes in ->atomic_open() instances. + +--- + +**mandatory** + +alloc_file() has become static now; two wrappers are to be used instead. +alloc_file_pseudo(inode, vfsmount, name, flags, ops) is for the cases +when dentry needs to be created; that's the majority of old alloc_file() +users. Calling conventions: on success a reference to new struct file +is returned and callers reference to inode is subsumed by that. On +failure, ERR_PTR() is returned and no caller's references are affected, +so the caller needs to drop the inode reference it held. +alloc_file_clone(file, flags, ops) does not affect any caller's references. +On success you get a new struct file sharing the mount/dentry with the +original, on failure - ERR_PTR(). + +--- + +**mandatory** + +->clone_file_range() and ->dedupe_file_range have been replaced with +->remap_file_range(). See Documentation/filesystems/vfs.rst for more +information. + +--- + +**recommended** + +->lookup() instances doing an equivalent of:: + + if (IS_ERR(inode)) + return ERR_CAST(inode); + return d_splice_alias(inode, dentry); + +don't need to bother with the check - d_splice_alias() will do the +right thing when given ERR_PTR(...) as inode. Moreover, passing NULL +inode to d_splice_alias() will also do the right thing (equivalent of +d_add(dentry, NULL); return NULL;), so that kind of special cases +also doesn't need a separate treatment. + +--- + +**strongly recommended** + +take the RCU-delayed parts of ->destroy_inode() into a new method - +->free_inode(). If ->destroy_inode() becomes empty - all the better, +just get rid of it. Synchronous work (e.g. the stuff that can't +be done from an RCU callback, or any WARN_ON() where we want the +stack trace) *might* be movable to ->evict_inode(); however, +that goes only for the things that are not needed to balance something +done by ->alloc_inode(). IOW, if it's cleaning up the stuff that +might have accumulated over the life of in-core inode, ->evict_inode() +might be a fit. + +Rules for inode destruction: + + * if ->destroy_inode() is non-NULL, it gets called + * if ->free_inode() is non-NULL, it gets scheduled by call_rcu() + * combination of NULL ->destroy_inode and NULL ->free_inode is + treated as NULL/free_inode_nonrcu, to preserve the compatibility. + +Note that the callback (be it via ->free_inode() or explicit call_rcu() +in ->destroy_inode()) is *NOT* ordered wrt superblock destruction; +as the matter of fact, the superblock and all associated structures +might be already gone. The filesystem driver is guaranteed to be still +there, but that's it. Freeing memory in the callback is fine; doing +more than that is possible, but requires a lot of care and is best +avoided. + +--- + +**mandatory** + +DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the +default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any +business doing so. + +--- + +**mandatory** + +d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are +very suspect (and won't work in modules). Such uses are very likely to +be misspelled d_alloc_anon(). diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 572dd29fbd54..34a6c99fa29b 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -246,7 +246,7 @@ struct orangefs_read_options { extern struct orangefs_stats orangefs_stats; /* - * NOTE: See Documentation/filesystems/porting for information + * NOTE: See Documentation/filesystems/porting.rst for information * on implementing FOO_I and properly accessing fs private data */ static inline struct orangefs_inode_s *ORANGEFS_I(struct inode *inode) -- GitLab From 9c970ab54c336340429fcd2570f3c577610078e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:29 -0300 Subject: [PATCH 1464/7155] docs: index.rst: don't use genindex for pdf output The genindex logic is meant to be used only for html output, as pdf build has its own way to generate indexes. Signed-off-by: Mauro Carvalho Chehab Acked-by: Vinod Koul # dmaengine and soundwire Signed-off-by: Jonathan Corbet --- Documentation/core-api/index.rst | 2 +- Documentation/driver-api/dmaengine/index.rst | 2 +- Documentation/driver-api/soundwire/index.rst | 2 +- Documentation/networking/device_drivers/index.rst | 2 +- Documentation/networking/index.rst | 2 +- Documentation/sound/index.rst | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index dfd8fad1e1ec..fa16a0538dcb 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -49,7 +49,7 @@ Interfaces for kernel debugging debug-objects tracepoint -.. only:: subproject +.. only:: subproject and html Indices ======= diff --git a/Documentation/driver-api/dmaengine/index.rst b/Documentation/driver-api/dmaengine/index.rst index 3026fa975937..b9df904d0a79 100644 --- a/Documentation/driver-api/dmaengine/index.rst +++ b/Documentation/driver-api/dmaengine/index.rst @@ -47,7 +47,7 @@ This book adds some notes about PXA DMA pxa_dma -.. only:: subproject +.. only:: subproject and html Indices ======= diff --git a/Documentation/driver-api/soundwire/index.rst b/Documentation/driver-api/soundwire/index.rst index 6db026028f27..234911a0db99 100644 --- a/Documentation/driver-api/soundwire/index.rst +++ b/Documentation/driver-api/soundwire/index.rst @@ -10,7 +10,7 @@ SoundWire Documentation error_handling locking -.. only:: subproject +.. only:: subproject and html Indices ======= diff --git a/Documentation/networking/device_drivers/index.rst b/Documentation/networking/device_drivers/index.rst index 2b7fefe72351..f724b7c69b9e 100644 --- a/Documentation/networking/device_drivers/index.rst +++ b/Documentation/networking/device_drivers/index.rst @@ -24,7 +24,7 @@ Contents: google/gve mellanox/mlx5 -.. only:: subproject +.. only:: subproject and html Indices ======= diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index a46fca264bee..6739066acadb 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -31,7 +31,7 @@ Contents: tls tls-offload -.. only:: subproject +.. only:: subproject and html Indices ======= diff --git a/Documentation/sound/index.rst b/Documentation/sound/index.rst index 47b89f014e69..4d7d42acf6df 100644 --- a/Documentation/sound/index.rst +++ b/Documentation/sound/index.rst @@ -12,7 +12,7 @@ Linux Sound Subsystem Documentation hd-audio/index cards/index -.. only:: subproject +.. only:: subproject and html Indices ======= -- GitLab From ff497db295c8939c4badf9cbaf5f0679af8ada0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:30 -0300 Subject: [PATCH 1465/7155] docs: wimax: convert to ReST and add to admin-guide Manually convert wimax documentation to ReST and add theit to the Kernel doc body, inside the admin-guide. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/admin-guide/index.rst | 1 + .../wimax/i2400m.rst} | 145 ++++++++++-------- Documentation/admin-guide/wimax/index.rst | 19 +++ .../wimax/wimax.rst} | 38 +++-- MAINTAINERS | 4 +- 5 files changed, 129 insertions(+), 78 deletions(-) rename Documentation/{wimax/README.i2400m => admin-guide/wimax/i2400m.rst} (69%) create mode 100644 Documentation/admin-guide/wimax/index.rst rename Documentation/{wimax/README.wimax => admin-guide/wimax/wimax.rst} (74%) diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 200e47820c37..534373816d7f 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -108,6 +108,7 @@ configure specific aspects of kernel behavior to your liking. pnp rtc svga + wimax/index video-output .. only:: subproject and html diff --git a/Documentation/wimax/README.i2400m b/Documentation/admin-guide/wimax/i2400m.rst similarity index 69% rename from Documentation/wimax/README.i2400m rename to Documentation/admin-guide/wimax/i2400m.rst index 7dffd8919cb0..194388c0c351 100644 --- a/Documentation/wimax/README.i2400m +++ b/Documentation/admin-guide/wimax/i2400m.rst @@ -1,18 +1,23 @@ +.. include:: - Driver for the Intel Wireless Wimax Connection 2400m +==================================================== +Driver for the Intel Wireless Wimax Connection 2400m +==================================================== - (C) 2008 Intel Corporation < linux-wimax@intel.com > +:Copyright: |copy| 2008 Intel Corporation < linux-wimax@intel.com > This provides a driver for the Intel Wireless WiMAX Connection 2400m and a basic Linux kernel WiMAX stack. 1. Requirements +=============== * Linux installation with Linux kernel 2.6.22 or newer (if building from a separate tree) * Intel i2400m Echo Peak or Baxter Peak; this includes the Intel Wireless WiMAX/WiFi Link 5x50 series. * build tools: + + Linux kernel development package for the target kernel; to build against your currently running kernel, you need to have the kernel development package corresponding to the running @@ -22,8 +27,10 @@ + GNU C Compiler, make 2. Compilation and installation +=============================== 2.1. Compilation of the drivers included in the kernel +------------------------------------------------------ Configure the kernel; to enable the WiMAX drivers select Drivers > Networking Drivers > WiMAX device support. Enable all of them as @@ -36,37 +43,39 @@ Compile and install your kernel as usual. 2.2. Compilation of the drivers distributed as an standalone module +------------------------------------------------------------------- - To compile + To compile:: -$ cd source/directory -$ make + $ cd source/directory + $ make Once built you can load and unload using the provided load.sh script; load.sh will load the modules, load.sh u will unload them. To install in the default kernel directories (and enable auto loading - when the device is plugged): + when the device is plugged):: -$ make install -$ depmod -a + $ make install + $ depmod -a If your kernel development files are located in a non standard directory or if you want to build for a kernel that is not the - currently running one, set KDIR to the right location: + currently running one, set KDIR to the right location:: -$ make KDIR=/path/to/kernel/dev/tree + $ make KDIR=/path/to/kernel/dev/tree For more information, please contact linux-wimax@intel.com. 3. Installing the firmware +-------------------------- The firmware can be obtained from http://linuxwimax.org or might have been supplied with your hardware. - It has to be installed in the target system: - * -$ cp FIRMWAREFILE.sbcf /lib/firmware/i2400m-fw-BUSTYPE-1.3.sbcf + It has to be installed in the target system:: + + $ cp FIRMWAREFILE.sbcf /lib/firmware/i2400m-fw-BUSTYPE-1.3.sbcf * NOTE: if your firmware came in an .rpm or .deb file, just install it as normal, with the rpm (rpm -i FIRMWARE.rpm) or dpkg @@ -76,6 +85,7 @@ $ cp FIRMWAREFILE.sbcf /lib/firmware/i2400m-fw-BUSTYPE-1.3.sbcf with other types. 4. Design +========= This package contains two major parts: a WiMAX kernel stack and a driver for the Intel i2400m. @@ -102,16 +112,17 @@ $ cp FIRMWAREFILE.sbcf /lib/firmware/i2400m-fw-BUSTYPE-1.3.sbcf API calls should be replaced with the target OS's. 5. Usage +======== To load the driver, follow the instructions in the install section; once the driver is loaded, plug in the device (unless it is permanently plugged in). The driver will enumerate the device, upload the firmware and output messages in the kernel log (dmesg, /var/log/messages or - /var/log/kern.log) such as: + /var/log/kern.log) such as:: -... -i2400m_usb 5-4:1.0: firmware interface version 8.0.0 -i2400m_usb 5-4:1.0: WiMAX interface wmx0 (00:1d:e1:01:94:2c) ready + ... + i2400m_usb 5-4:1.0: firmware interface version 8.0.0 + i2400m_usb 5-4:1.0: WiMAX interface wmx0 (00:1d:e1:01:94:2c) ready At this point the device is ready to work. @@ -120,38 +131,42 @@ i2400m_usb 5-4:1.0: WiMAX interface wmx0 (00:1d:e1:01:94:2c) ready on how to scan, connect and disconnect. 5.1. Module parameters +---------------------- Module parameters can be set at kernel or module load time or by - echoing values: + echoing values:: -$ echo VALUE > /sys/module/MODULENAME/parameters/PARAMETERNAME + $ echo VALUE > /sys/module/MODULENAME/parameters/PARAMETERNAME To make changes permanent, for example, for the i2400m module, you can - also create a file named /etc/modprobe.d/i2400m containing: + also create a file named /etc/modprobe.d/i2400m containing:: -options i2400m idle_mode_disabled=1 + options i2400m idle_mode_disabled=1 - To find which parameters are supported by a module, run: + To find which parameters are supported by a module, run:: -$ modinfo path/to/module.ko + $ modinfo path/to/module.ko During kernel bootup (if the driver is linked in the kernel), specify - the following to the kernel command line: + the following to the kernel command line:: -i2400m.PARAMETER=VALUE + i2400m.PARAMETER=VALUE 5.1.1. i2400m: idle_mode_disabled +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The i2400m module supports a parameter to disable idle mode. This parameter, once set, will take effect only when the device is reinitialized by the driver (eg: following a reset or a reconnect). 5.2. Debug operations: debugfs entries +-------------------------------------- The driver will register debugfs entries that allow the user to tweak debug settings. There are three main container directories where entries are placed, which correspond to the three blocks a i2400m WiMAX driver has: + * /sys/kernel/debug/wimax:DEVNAME/ for the generic WiMAX stack controls * /sys/kernel/debug/wimax:DEVNAME/i2400m for the i2400m generic @@ -163,52 +178,55 @@ i2400m.PARAMETER=VALUE /sys/kernel/debug, those paths will change. 5.2.1. Increasing debug output +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The files named *dl_* indicate knobs for controlling the debug output - of different submodules: - * -# find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\* -/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_tx -/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_rx -/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_notif -/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_fw -/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_usb -/sys/kernel/debug/wimax:wmx0/i2400m/dl_tx -/sys/kernel/debug/wimax:wmx0/i2400m/dl_rx -/sys/kernel/debug/wimax:wmx0/i2400m/dl_rfkill -/sys/kernel/debug/wimax:wmx0/i2400m/dl_netdev -/sys/kernel/debug/wimax:wmx0/i2400m/dl_fw -/sys/kernel/debug/wimax:wmx0/i2400m/dl_debugfs -/sys/kernel/debug/wimax:wmx0/i2400m/dl_driver -/sys/kernel/debug/wimax:wmx0/i2400m/dl_control -/sys/kernel/debug/wimax:wmx0/wimax_dl_stack -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg -/sys/kernel/debug/wimax:wmx0/wimax_dl_id_table -/sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs + of different submodules:: + + # find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\* + /sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_tx + /sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_rx + /sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_notif + /sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_fw + /sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_usb + /sys/kernel/debug/wimax:wmx0/i2400m/dl_tx + /sys/kernel/debug/wimax:wmx0/i2400m/dl_rx + /sys/kernel/debug/wimax:wmx0/i2400m/dl_rfkill + /sys/kernel/debug/wimax:wmx0/i2400m/dl_netdev + /sys/kernel/debug/wimax:wmx0/i2400m/dl_fw + /sys/kernel/debug/wimax:wmx0/i2400m/dl_debugfs + /sys/kernel/debug/wimax:wmx0/i2400m/dl_driver + /sys/kernel/debug/wimax:wmx0/i2400m/dl_control + /sys/kernel/debug/wimax:wmx0/wimax_dl_stack + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg + /sys/kernel/debug/wimax:wmx0/wimax_dl_id_table + /sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs By reading the file you can obtain the current value of said debug level; by writing to it, you can set it. To increase the debug level of, for example, the i2400m's generic TX - engine, just write: + engine, just write:: -$ echo 3 > /sys/kernel/debug/wimax:wmx0/i2400m/dl_tx + $ echo 3 > /sys/kernel/debug/wimax:wmx0/i2400m/dl_tx Increasing numbers yield increasing debug information; for details of what is printed and the available levels, check the source. The code uses 0 for disabled and increasing values until 8. 5.2.2. RX and TX statistics +^^^^^^^^^^^^^^^^^^^^^^^^^^^ The i2400m/rx_stats and i2400m/tx_stats provide statistics about the - data reception/delivery from the device: + data reception/delivery from the device:: -$ cat /sys/kernel/debug/wimax:wmx0/i2400m/rx_stats -45 1 3 34 3104 48 480 + $ cat /sys/kernel/debug/wimax:wmx0/i2400m/rx_stats + 45 1 3 34 3104 48 480 + + The numbers reported are: - The numbers reported are * packets/RX-buffer: total, min, max * RX-buffers: total RX buffers received, accumulated RX buffer size in bytes, min size received, max size received @@ -216,9 +234,9 @@ $ cat /sys/kernel/debug/wimax:wmx0/i2400m/rx_stats Thus, to find the average buffer size received, divide accumulated RX-buffer / total RX-buffers. - To clear the statistics back to 0, write anything to the rx_stats file: + To clear the statistics back to 0, write anything to the rx_stats file:: -$ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m_rx_stats + $ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m_rx_stats Likewise for TX. @@ -227,14 +245,16 @@ $ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m_rx_stats to the host. See drivers/net/wimax/i2400m/tx.c. 5.2.3. Tracing messages received from user space +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To echo messages received from user space into the trace pipe that the i2400m driver creates, set the debug file i2400m/trace_msg_from_user to - 1: - * -$ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m/trace_msg_from_user + 1:: + + $ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m/trace_msg_from_user 5.2.4. Performing a device reset +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By writing a 0, a 1 or a 2 to the file /sys/kernel/debug/wimax:wmx0/reset, the driver performs a warm (without @@ -242,18 +262,21 @@ $ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m/trace_msg_from_user (bus specific) reset on the device. 5.2.5. Asking the device to enter power saving mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By writing any value to the /sys/kernel/debug/wimax:wmx0 file, the device will attempt to enter power saving mode. 6. Troubleshooting +================== -6.1. Driver complains about 'i2400m-fw-usb-1.2.sbcf: request failed' +6.1. Driver complains about ``i2400m-fw-usb-1.2.sbcf: request failed`` +---------------------------------------------------------------------- If upon connecting the device, the following is output in the kernel - log: + log:: -i2400m_usb 5-4:1.0: fw i2400m-fw-usb-1.3.sbcf: request failed: -2 + i2400m_usb 5-4:1.0: fw i2400m-fw-usb-1.3.sbcf: request failed: -2 This means that the driver cannot locate the firmware file named /lib/firmware/i2400m-fw-usb-1.2.sbcf. Check that the file is present in diff --git a/Documentation/admin-guide/wimax/index.rst b/Documentation/admin-guide/wimax/index.rst new file mode 100644 index 000000000000..fdf7c1f99ff5 --- /dev/null +++ b/Documentation/admin-guide/wimax/index.rst @@ -0,0 +1,19 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +WiMAX subsystem +=============== + +.. toctree:: + :maxdepth: 2 + + wimax + + i2400m + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/wimax/README.wimax b/Documentation/admin-guide/wimax/wimax.rst similarity index 74% rename from Documentation/wimax/README.wimax rename to Documentation/admin-guide/wimax/wimax.rst index b78c4378084e..817ee8ba2732 100644 --- a/Documentation/wimax/README.wimax +++ b/Documentation/admin-guide/wimax/wimax.rst @@ -1,12 +1,16 @@ +.. include:: - Linux kernel WiMAX stack +======================== +Linux kernel WiMAX stack +======================== - (C) 2008 Intel Corporation < linux-wimax@intel.com > +:Copyright: |copy| 2008 Intel Corporation < linux-wimax@intel.com > This provides a basic Linux kernel WiMAX stack to provide a common control API for WiMAX devices, usable from kernel and user space. 1. Design +========= The WiMAX stack is designed to provide for common WiMAX control services to current and future WiMAX devices from any vendor. @@ -31,6 +35,7 @@ include/linux/wimax.h. 2. Usage +======== For usage in a driver (registration, API, etc) please refer to the instructions in the header file include/linux/wimax.h. @@ -40,6 +45,7 @@ control. 2.1. Obtaining debug information: debugfs entries +------------------------------------------------- The WiMAX stack is compiled, by default, with debug messages that can be used to diagnose issues. By default, said messages are disabled. @@ -52,20 +58,22 @@ create more subentries below it. 2.1.1. Increasing debug output +------------------------------ The files named *dl_* indicate knobs for controlling the debug output - of different submodules of the WiMAX stack: - * -# find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\* -/sys/kernel/debug/wimax:wmx0/wimax_dl_stack -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset -/sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg -/sys/kernel/debug/wimax:wmx0/wimax_dl_id_table -/sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs -/sys/kernel/debug/wimax:wmx0/.... # other driver specific files - - NOTE: Of course, if debugfs is mounted in a directory other than + of different submodules of the WiMAX stack:: + + # find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\* + /sys/kernel/debug/wimax:wmx0/wimax_dl_stack + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset + /sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg + /sys/kernel/debug/wimax:wmx0/wimax_dl_id_table + /sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs + /sys/kernel/debug/wimax:wmx0/.... # other driver specific files + + NOTE: + Of course, if debugfs is mounted in a directory other than /sys/kernel/debug, those paths will change. By reading the file you can obtain the current value of said debug @@ -74,7 +82,7 @@ To increase the debug level of, for example, the id-table submodule, just write: -$ echo 3 > /sys/kernel/debug/wimax:wmx0/wimax_dl_id_table + $ echo 3 > /sys/kernel/debug/wimax:wmx0/wimax_dl_id_table Increasing numbers yield increasing debug information; for details of what is printed and the available levels, check the source. The code diff --git a/MAINTAINERS b/MAINTAINERS index a27e36f491b3..6fa76e6a93cd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8356,7 +8356,7 @@ M: linux-wimax@intel.com L: wimax@linuxwimax.org (subscribers-only) S: Supported W: http://linuxwimax.org -F: Documentation/wimax/README.i2400m +F: Documentation/admin-guide/wimax/i2400m.rst F: drivers/net/wimax/i2400m/ F: include/uapi/linux/wimax/i2400m.h @@ -17358,7 +17358,7 @@ M: linux-wimax@intel.com L: wimax@linuxwimax.org (subscribers-only) S: Supported W: http://linuxwimax.org -F: Documentation/wimax/README.wimax +F: Documentation/admin-guide/wimax/wimax.rst F: include/linux/wimax/debug.h F: include/net/wimax.h F: include/uapi/linux/wimax.h -- GitLab From 80b1505893b60608e1525fc63caf16fd128f1b4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:31 -0300 Subject: [PATCH 1466/7155] docs: mips: add to the documentation body as ReST Manually convert the AU1xxx_IDE.README file to ReST and add to a MIPS book as part of the main documentation body. Signed-off-by: Mauro Carvalho Chehab Acked-by: Paul Burton Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + .../{AU1xxx_IDE.README => au1xxx_ide.rst} | 89 +++++++++++-------- Documentation/mips/index.rst | 17 ++++ 3 files changed, 70 insertions(+), 37 deletions(-) rename Documentation/mips/{AU1xxx_IDE.README => au1xxx_ide.rst} (67%) create mode 100644 Documentation/mips/index.rst diff --git a/Documentation/index.rst b/Documentation/index.rst index cd50e82710e0..633c951f6932 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -148,6 +148,7 @@ implementation. ia64/index m68k/index powerpc/index + mips/index openrisc/index parisc/index riscv/index diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/au1xxx_ide.rst similarity index 67% rename from Documentation/mips/AU1xxx_IDE.README rename to Documentation/mips/au1xxx_ide.rst index ff675a1b1422..2f9c2cff6738 100644 --- a/Documentation/mips/AU1xxx_IDE.README +++ b/Documentation/mips/au1xxx_ide.rst @@ -1,7 +1,14 @@ -README for MIPS AU1XXX IDE driver - Released 2005-07-15 +.. include:: + +====================== +MIPS AU1XXX IDE driver +====================== + +Released 2005-07-15 + +About +===== -ABOUT ------ This file describes the 'drivers/ide/au1xxx-ide.c', related files and the services they provide. @@ -10,17 +17,17 @@ the white or black list, go to the 'ADD NEW HARD DISC TO WHITE OR BLACK LIST' section. -LICENSE -------- +License +======= -Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions +:Copyright: |copy| 2003-2005 AMD, Personal Connectivity Solutions This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +THIS SOFTWARE IS PROVIDED ``AS IS`` AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR @@ -35,31 +42,35 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE +Note: + for more information, please refer "AMD Alchemy Au1200/Au1550 IDE Interface and Linux Device Driver" Application Note. -FILES, CONFIGS AND COMPATIBILITY --------------------------------- +Files, Configs and Compatibility +================================ Two files are introduced: a) 'arch/mips/include/asm/mach-au1x00/au1xxx_ide.h' contains : struct _auide_hwif - timing parameters for PIO mode 0/1/2/3/4 - timing parameters for MWDMA 0/1/2 + + - timing parameters for PIO mode 0/1/2/3/4 + - timing parameters for MWDMA 0/1/2 b) 'drivers/ide/mips/au1xxx-ide.c' contains the functionality of the AU1XXX IDE driver Following extra configs variables are introduced: - CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - enable the PIO+DBDMA mode - CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - enable the MWDMA mode + CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA + - enable the PIO+DBDMA mode + CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + - enable the MWDMA mode -SUPPORTED IDE MODES -------------------- +Supported IDE Modes +=================== The AU1XXX IDE driver supported all PIO modes - PIO mode 0/1/2/3/4 - and all MWDMA modes - MWDMA 0/1/2 -. There is no support for SWDMA and UDMA mode. @@ -69,20 +80,21 @@ To change the PIO mode use the program hdparm with option -p, e.g. -X, e.g. 'hdparm -X32 [device]' for MWDMA mode 0. -PERFORMANCE CONFIGURATIONS --------------------------- +Performance Configurations +========================== -If the used system doesn't need USB support enable the following kernel configs: +If the used system doesn't need USB support enable the following kernel +configs:: -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_IDE_AU1XXX=y -CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y -CONFIG_BLK_DEV_IDEDMA=y + CONFIG_IDE=y + CONFIG_BLK_DEV_IDE=y + CONFIG_IDE_GENERIC=y + CONFIG_BLK_DEV_IDEPCI=y + CONFIG_BLK_DEV_GENERIC=y + CONFIG_BLK_DEV_IDEDMA_PCI=y + CONFIG_BLK_DEV_IDE_AU1XXX=y + CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y + CONFIG_BLK_DEV_IDEDMA=y Also define 'IDE_AU1XXX_BURSTMODE' in 'drivers/ide/mips/au1xxx-ide.c' to enable the burst support on DBDMA controller. @@ -90,20 +102,22 @@ the burst support on DBDMA controller. If the used system need the USB support enable the following kernel configs for high IDE to USB throughput. -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_IDE_AU1XXX=y -CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y -CONFIG_BLK_DEV_IDEDMA=y +:: + + CONFIG_IDE_GENERIC=y + CONFIG_BLK_DEV_IDEPCI=y + CONFIG_BLK_DEV_GENERIC=y + CONFIG_BLK_DEV_IDEDMA_PCI=y + CONFIG_BLK_DEV_IDE_AU1XXX=y + CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y + CONFIG_BLK_DEV_IDEDMA=y Also undefine 'IDE_AU1XXX_BURSTMODE' in 'drivers/ide/mips/au1xxx-ide.c' to disable the burst support on DBDMA controller. -ACKNOWLEDGMENTS ---------------- +Acknowledgments +=============== These drivers wouldn't have been done without the base of kernel 2.4.x AU1XXX IDE driver from AMD. @@ -112,4 +126,5 @@ Additional input also from: Matthias Lenk Happy hacking! + Enrico Walther diff --git a/Documentation/mips/index.rst b/Documentation/mips/index.rst new file mode 100644 index 000000000000..fd9023c8a89f --- /dev/null +++ b/Documentation/mips/index.rst @@ -0,0 +1,17 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================= +MIPS architecture +================= + +.. toctree:: + :maxdepth: 2 + + au1xxx_ide + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` -- GitLab From bfc8a222d3bca4c09a63de8b321bf7f825fa59ff Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:32 -0300 Subject: [PATCH 1467/7155] docs: hwmon: pxe1610: convert to ReST format and add to the index This document was recently introduced. Convert it to ReST just like the other hwmon documents, adding it to the hwmon index. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/hwmon/index.rst | 1 + Documentation/hwmon/{pxe1610 => pxe1610.rst} | 33 +++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) rename Documentation/hwmon/{pxe1610 => pxe1610.rst} (82%) diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index ee090e51653a..4d5f5fec43a3 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -130,6 +130,7 @@ Hardware Monitoring Kernel Drivers pcf8591 pmbus powr1220 + pxe1610 pwm-fan raspberrypi-hwmon sch5627 diff --git a/Documentation/hwmon/pxe1610 b/Documentation/hwmon/pxe1610.rst similarity index 82% rename from Documentation/hwmon/pxe1610 rename to Documentation/hwmon/pxe1610.rst index 211cedeefb44..4f2388840d06 100644 --- a/Documentation/hwmon/pxe1610 +++ b/Documentation/hwmon/pxe1610.rst @@ -2,19 +2,29 @@ Kernel driver pxe1610 ===================== Supported chips: + * Infineon PXE1610 + Prefix: 'pxe1610' + Addresses scanned: - + Datasheet: Datasheet is not publicly available. * Infineon PXE1110 + Prefix: 'pxe1110' + Addresses scanned: - + Datasheet: Datasheet is not publicly available. * Infineon PXM1310 + Prefix: 'pxm1310' + Addresses scanned: - + Datasheet: Datasheet is not publicly available. Author: Vijay Khemka @@ -25,14 +35,19 @@ Description PXE1610/PXE1110 are Multi-rail/Multiphase Digital Controllers and compliant to - -- Intel VR13 DC-DC converter specifications. - -- Intel SVID protocol. + + - Intel VR13 DC-DC converter specifications. + - Intel SVID protocol. + Used for Vcore power regulation for Intel VR13 based microprocessors - -- Servers, Workstations, and High-end desktops + + - Servers, Workstations, and High-end desktops PXM1310 is a Multi-rail Controller and it is compliant to - -- Intel VR13 DC-DC converter specifications. - -- Intel SVID protocol. + + - Intel VR13 DC-DC converter specifications. + - Intel SVID protocol. + Used for DDR3/DDR4 Memory power regulation for Intel VR13 and IMVP8 based systems @@ -44,10 +59,10 @@ This driver does not probe for PMBus devices. You will have to instantiate devices explicitly. Example: the following commands will load the driver for an PXE1610 -at address 0x70 on I2C bus #4: +at address 0x70 on I2C bus #4:: -# modprobe pxe1610 -# echo pxe1610 0x70 > /sys/bus/i2c/devices/i2c-4/new_device + # modprobe pxe1610 + # echo pxe1610 0x70 > /sys/bus/i2c/devices/i2c-4/new_device It can also be instantiated by declaring in device tree @@ -55,6 +70,7 @@ It can also be instantiated by declaring in device tree Sysfs attributes ---------------- +====================== ==================================== curr1_label "iin" curr1_input Measured input current curr1_alarm Current high alarm @@ -88,3 +104,4 @@ temp[1-3]_crit Critical high temperature temp[1-3]_crit_alarm Chip temperature critical high alarm temp[1-3]_max Maximum temperature temp[1-3]_max_alarm Chip temperature high alarm +====================== ==================================== -- GitLab From 47359e5734f1df0301ee3f0c46da9954f15b7bd9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:33 -0300 Subject: [PATCH 1468/7155] docs: nios2: add it to the main Documentation body Rename and add the nios2 documentation to the documentation body. The nios2 document is already on an ReST compatible format. All it needs is that the title of the document to be promoted one level. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + Documentation/nios2/{README => nios2.rst} | 1 + 2 files changed, 2 insertions(+) rename Documentation/nios2/{README => nios2.rst} (96%) diff --git a/Documentation/index.rst b/Documentation/index.rst index 633c951f6932..6217acab92db 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -149,6 +149,7 @@ implementation. m68k/index powerpc/index mips/index + nios2/nios2 openrisc/index parisc/index riscv/index diff --git a/Documentation/nios2/README b/Documentation/nios2/nios2.rst similarity index 96% rename from Documentation/nios2/README rename to Documentation/nios2/nios2.rst index 054a67d55563..43da3f7cee76 100644 --- a/Documentation/nios2/README +++ b/Documentation/nios2/nios2.rst @@ -1,3 +1,4 @@ +================================= Linux on the Nios II architecture ================================= -- GitLab From e15d5a53ea3239e537d3a0c4bdfce8a4ea4e0da6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Jul 2019 09:51:34 -0300 Subject: [PATCH 1469/7155] docs: net: convert two README files to ReST format There are two README files there with doesn't have a .txt extension nor are at ReST format. In order to help with the docs conversion to ReST, rename those and manually convert them to ReST format. As there are lot more to be done for networking to be part of the documentation body, for now mark those two files with :orphan:, in order to supress a build warning. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- .../networking/caif/{README => caif.rst} | 88 +++++++++++++------ .../{README => mac80211_hwsim.rst} | 28 ++++-- MAINTAINERS | 2 +- 3 files changed, 81 insertions(+), 37 deletions(-) rename Documentation/networking/caif/{README => caif.rst} (70%) rename Documentation/networking/mac80211_hwsim/{README => mac80211_hwsim.rst} (81%) diff --git a/Documentation/networking/caif/README b/Documentation/networking/caif/caif.rst similarity index 70% rename from Documentation/networking/caif/README rename to Documentation/networking/caif/caif.rst index 757ccfaa1385..07afc8063d4d 100644 --- a/Documentation/networking/caif/README +++ b/Documentation/networking/caif/caif.rst @@ -1,18 +1,31 @@ -Copyright (C) ST-Ericsson AB 2010 -Author: Sjur Brendeland/ sjur.brandeland@stericsson.com -License terms: GNU General Public License (GPL) version 2 ---------------------------------------------------------- +:orphan: -=== Start === -If you have compiled CAIF for modules do: +.. SPDX-License-Identifier: GPL-2.0 +.. include:: -$modprobe crc_ccitt -$modprobe caif -$modprobe caif_socket -$modprobe chnl_net +================ +Using Linux CAIF +================ -=== Preparing the setup with a STE modem === + +:Copyright: |copy| ST-Ericsson AB 2010 + +:Author: Sjur Brendeland/ sjur.brandeland@stericsson.com + +Start +===== + +If you have compiled CAIF for modules do:: + + $modprobe crc_ccitt + $modprobe caif + $modprobe caif_socket + $modprobe chnl_net + + +Preparing the setup with a STE modem +==================================== If you are working on integration of CAIF you should make sure that the kernel is built with module support. @@ -32,24 +45,30 @@ module parameter "ser_use_stx". Normally Frame Checksum is always used on UART, but this is also provided as a module parameter "ser_use_fcs". -$ modprobe caif_serial ser_ttyname=/dev/ttyS0 ser_use_stx=yes -$ ifconfig caif_ttyS0 up +:: + + $ modprobe caif_serial ser_ttyname=/dev/ttyS0 ser_use_stx=yes + $ ifconfig caif_ttyS0 up -PLEASE NOTE: There is a limitation in Android shell. +PLEASE NOTE: + There is a limitation in Android shell. It only accepts one argument to insmod/modprobe! -=== Trouble shooting === +Trouble shooting +================ There are debugfs parameters provided for serial communication. /sys/kernel/debug/caif_serial// * ser_state: Prints the bit-mask status where + - 0x02 means SENDING, this is a transient state. - 0x10 means FLOW_OFF_SENT, i.e. the previous frame has not been sent - and is blocking further send operation. Flow OFF has been propagated - to all CAIF Channels using this TTY. + and is blocking further send operation. Flow OFF has been propagated + to all CAIF Channels using this TTY. * tty_status: Prints the bit-mask tty status information + - 0x01 - tty->warned is on. - 0x02 - tty->low_latency is on. - 0x04 - tty->packed is on. @@ -58,13 +77,17 @@ There are debugfs parameters provided for serial communication. - 0x20 - tty->stopped is on. * last_tx_msg: Binary blob Prints the last transmitted frame. - This can be printed with + + This can be printed with:: + $od --format=x1 /sys/kernel/debug/caif_serial//last_rx_msg. - The first two tx messages sent look like this. Note: The initial - byte 02 is start of frame extension (STX) used for re-syncing - upon errors. - - Enumeration: + The first two tx messages sent look like this. Note: The initial + byte 02 is start of frame extension (STX) used for re-syncing + upon errors. + + - Enumeration:: + 0000000 02 05 00 00 03 01 d2 02 | | | | | | STX(1) | | | | @@ -73,7 +96,9 @@ There are debugfs parameters provided for serial communication. Command:Enumeration(1) Link-ID(1) Checksum(2) - - Channel Setup: + + - Channel Setup:: + 0000000 02 07 00 00 00 21 a1 00 48 df | | | | | | | | STX(1) | | | | | | @@ -86,13 +111,18 @@ There are debugfs parameters provided for serial communication. Checksum(2) * last_rx_msg: Prints the last transmitted frame. - The RX messages for LinkSetup look almost identical but they have the - bit 0x20 set in the command bit, and Channel Setup has added one byte - before Checksum containing Channel ID. - NOTE: Several CAIF Messages might be concatenated. The maximum debug + + The RX messages for LinkSetup look almost identical but they have the + bit 0x20 set in the command bit, and Channel Setup has added one byte + before Checksum containing Channel ID. + + NOTE: + Several CAIF Messages might be concatenated. The maximum debug buffer size is 128 bytes. -== Error Scenarios: +Error Scenarios +=============== + - last_tx_msg contains channel setup message and last_rx_msg is empty -> The host seems to be able to send over the UART, at least the CAIF ldisc get notified that sending is completed. @@ -103,7 +133,9 @@ There are debugfs parameters provided for serial communication. - if /sys/kernel/debug/caif_serial//tty_status is non-zero there might be problems transmitting over UART. + E.g. host and modem wiring is not correct you will typically see tty_status = 0x10 (hw_stopped) and ser_state = 0x10 (FLOW_OFF_SENT). + You will probably see the enumeration message in last_tx_message and empty last_rx_message. diff --git a/Documentation/networking/mac80211_hwsim/README b/Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst similarity index 81% rename from Documentation/networking/mac80211_hwsim/README rename to Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst index 3566a725d19c..d2266ce5534e 100644 --- a/Documentation/networking/mac80211_hwsim/README +++ b/Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst @@ -1,5 +1,13 @@ +:orphan: + +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +=================================================================== mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 -Copyright (c) 2008, Jouni Malinen +=================================================================== + +:Copyright: |copy| 2008, Jouni Malinen 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 @@ -7,6 +15,7 @@ published by the Free Software Foundation. Introduction +============ mac80211_hwsim is a Linux kernel module that can be used to simulate arbitrary number of IEEE 802.11 radios for mac80211. It can be used to @@ -43,6 +52,7 @@ regardless of channel. Simple example +============== This example shows how to use mac80211_hwsim to simulate two radios: one to act as an access point and the other as a station that @@ -50,17 +60,19 @@ associates with the AP. hostapd and wpa_supplicant are used to take care of WPA2-PSK authentication. In addition, hostapd is also processing access point side of association. +:: + -# Build mac80211_hwsim as part of kernel configuration + # Build mac80211_hwsim as part of kernel configuration -# Load the module -modprobe mac80211_hwsim + # Load the module + modprobe mac80211_hwsim -# Run hostapd (AP) for wlan0 -hostapd hostapd.conf + # Run hostapd (AP) for wlan0 + hostapd hostapd.conf -# Run wpa_supplicant (station) for wlan1 -wpa_supplicant -Dnl80211 -iwlan1 -c wpa_supplicant.conf + # Run wpa_supplicant (station) for wlan1 + wpa_supplicant -Dnl80211 -iwlan1 -c wpa_supplicant.conf More test cases are available in hostap.git: diff --git a/MAINTAINERS b/MAINTAINERS index 6fa76e6a93cd..6de82f019a52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9578,7 +9578,7 @@ F: Documentation/networking/mac80211-injection.txt F: include/net/mac80211.h F: net/mac80211/ F: drivers/net/wireless/mac80211_hwsim.[ch] -F: Documentation/networking/mac80211_hwsim/README +F: Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst MAILBOX API M: Jassi Brar -- GitLab From 2ef5a7f1482c21579d556f31a605a7ca32f251e7 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Jul 2019 18:44:32 +0300 Subject: [PATCH 1470/7155] tpm: Document UEFI event log quirks There are some weird quirks when it comes to UEFI event log. Provide a brief introduction to TPM event log mechanism and describe the quirks and how they can be sorted out. Signed-off-by: Jarkko Sakkinen Signed-off-by: Jonathan Corbet --- Documentation/security/tpm/index.rst | 1 + Documentation/security/tpm/tpm_event_log.rst | 55 ++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 Documentation/security/tpm/tpm_event_log.rst diff --git a/Documentation/security/tpm/index.rst b/Documentation/security/tpm/index.rst index 3296533e54cf..2bae8e8ca4bc 100644 --- a/Documentation/security/tpm/index.rst +++ b/Documentation/security/tpm/index.rst @@ -4,5 +4,6 @@ Trusted Platform Module documentation .. toctree:: + tpm_event_log tpm_vtpm_proxy xen-tpmfront diff --git a/Documentation/security/tpm/tpm_event_log.rst b/Documentation/security/tpm/tpm_event_log.rst new file mode 100644 index 000000000000..f00f7a1d5e92 --- /dev/null +++ b/Documentation/security/tpm/tpm_event_log.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +TPM Event Log +============= + +This document briefly describes what TPM log is and how it is handed +over from the preboot firmware to the operating system. + +Introduction +============ + +The preboot firmware maintains an event log that gets new entries every +time something gets hashed by it to any of the PCR registers. The events +are segregated by their type and contain the value of the hashed PCR +register. Typically, the preboot firmware will hash the components to +who execution is to be handed over or actions relevant to the boot +process. + +The main application for this is remote attestation and the reason why +it is useful is nicely put in the very first section of [1]: + +"Attestation is used to provide information about the platform’s state +to a challenger. However, PCR contents are difficult to interpret; +therefore, attestation is typically more useful when the PCR contents +are accompanied by a measurement log. While not trusted on their own, +the measurement log contains a richer set of information than do the PCR +contents. The PCR contents are used to provide the validation of the +measurement log." + +UEFI event log +============== + +UEFI provided event log has a few somewhat weird quirks. + +Before calling ExitBootServices() Linux EFI stub copies the event log to +a custom configuration table defined by the stub itself. Unfortunately, +the events generated by ExitBootServices() don't end up in the table. + +The firmware provides so called final events configuration table to sort +out this issue. Events gets mirrored to this table after the first time +EFI_TCG2_PROTOCOL.GetEventLog() gets called. + +This introduces another problem: nothing guarantees that it is not called +before the Linux EFI stub gets to run. Thus, it needs to calculate and save the +final events table size while the stub is still running to the custom +configuration table so that the TPM driver can later on skip these events when +concatenating two halves of the event log from the custom configuration table +and the final events table. + +References +========== + +- [1] https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/ +- [2] The final concatenation is done in drivers/char/tpm/eventlog/efi.c -- GitLab From aa95b4a960ab53234863d4ae0d1a09ad74253104 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:08:48 -0300 Subject: [PATCH 1471/7155] docs: fix a couple of new broken references Those are due to recent changes. Most of the issues can be automatically fixed with: $ ./scripts/documentation-file-ref-check --fix The only exception was the sound binding with required manual work. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt | 2 +- MAINTAINERS | 4 ++-- drivers/hwtracing/coresight/Kconfig | 2 +- fs/jfs/Kconfig | 2 +- fs/ufs/Kconfig | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt index 2ca3d138528e..7ecf6bd60d27 100644 --- a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt +++ b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt @@ -4,7 +4,7 @@ Allwinner SUN8I audio codec On Sun8i-A33 SoCs, the audio is separated in different parts: - A DAI driver. It uses the "sun4i-i2s" driver which is documented here: - Documentation/devicetree/bindings/sound/sun4i-i2s.txt + Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml - An analog part of the codec which is handled as PRCM registers. See Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt - An digital part of the codec which is documented in this current diff --git a/MAINTAINERS b/MAINTAINERS index 6de82f019a52..f109a8bcffda 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8659,7 +8659,7 @@ L: jfs-discussion@lists.sourceforge.net W: http://jfs.sourceforge.net/ T: git git://github.com/kleikamp/linux-shaggy.git S: Maintained -F: Documentation/filesystems/jfs.txt +F: Documentation/admin-guide/jfs.rst F: fs/jfs/ JME NETWORK DRIVER @@ -16439,7 +16439,7 @@ F: drivers/hid/hid-udraw-ps3.c UFS FILESYSTEM M: Evgeniy Dushistov S: Maintained -F: Documentation/filesystems/ufs.txt +F: Documentation/admin-guide/ufs.rst F: fs/ufs/ UHID USERSPACE HID IO DRIVER: diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 14638db4991d..7a9f5fb08330 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -106,7 +106,7 @@ config CORESIGHT_CPU_DEBUG can quickly get to know program counter (PC), secure state, exception level, etc. Before use debugging functionality, platform needs to ensure the clock domain and power domain are enabled - properly, please refer Documentation/trace/coresight-cpu-debug.txt + properly, please refer Documentation/trace/coresight-cpu-debug.rst for detailed description and the example for usage. endif diff --git a/fs/jfs/Kconfig b/fs/jfs/Kconfig index 22a273bd4648..05cb0e8e4382 100644 --- a/fs/jfs/Kconfig +++ b/fs/jfs/Kconfig @@ -5,7 +5,7 @@ config JFS_FS select CRC32 help This is a port of IBM's Journaled Filesystem . More information is - available in the file . + available in the file . If you do not intend to use the JFS filesystem, say N. diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig index fcb41516ea59..6d30adb6b890 100644 --- a/fs/ufs/Kconfig +++ b/fs/ufs/Kconfig @@ -9,7 +9,7 @@ config UFS_FS this file system as well. Saying Y here will allow you to read from these partitions; if you also want to write to them, say Y to the experimental "UFS file system write support", below. Please read the - file for more information. + file for more information. The recently released UFS2 variant (used in FreeBSD 5.x) is READ-ONLY supported. -- GitLab From d2fd3732e4acd6ab72960e7f8e00845438803f3e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:08:49 -0300 Subject: [PATCH 1472/7155] docs: writing-schema.md: convert from markdown to ReST The documentation standard is ReST and not markdown. Signed-off-by: Mauro Carvalho Chehab Acked-by: Rob Herring Signed-off-by: Jonathan Corbet --- Documentation/devicetree/writing-schema.md | 130 ----------------- Documentation/devicetree/writing-schema.rst | 153 ++++++++++++++++++++ 2 files changed, 153 insertions(+), 130 deletions(-) delete mode 100644 Documentation/devicetree/writing-schema.md create mode 100644 Documentation/devicetree/writing-schema.rst diff --git a/Documentation/devicetree/writing-schema.md b/Documentation/devicetree/writing-schema.md deleted file mode 100644 index dc032db36262..000000000000 --- a/Documentation/devicetree/writing-schema.md +++ /dev/null @@ -1,130 +0,0 @@ -# Writing DeviceTree Bindings in json-schema - -Devicetree bindings are written using json-schema vocabulary. Schema files are -written in a JSON compatible subset of YAML. YAML is used instead of JSON as it -considered more human readable and has some advantages such as allowing -comments (Prefixed with '#'). - -## Schema Contents - -Each schema doc is a structured json-schema which is defined by a set of -top-level properties. Generally, there is one binding defined per file. The -top-level json-schema properties used are: - -- __$id__ - A json-schema unique identifier string. The string must be a valid -URI typically containing the binding's filename and path. For DT schema, it must -begin with "http://devicetree.org/schemas/". The URL is used in constructing -references to other files specified in schema "$ref" properties. A $ref values -with a leading '/' will have the hostname prepended. A $ref value a relative -path or filename only will be prepended with the hostname and path components -of the current schema file's '$id' value. A URL is used even for local files, -but there may not actually be files present at those locations. - -- __$schema__ - Indicates the meta-schema the schema file adheres to. - -- __title__ - A one line description on the contents of the binding schema. - -- __maintainers__ - A DT specific property. Contains a list of email address(es) -for maintainers of this binding. - -- __description__ - Optional. A multi-line text block containing any detailed -information about this binding. It should contain things such as what the block -or device does, standards the device conforms to, and links to datasheets for -more information. - -- __select__ - Optional. A json-schema used to match nodes for applying the -schema. By default without 'select', nodes are matched against their possible -compatible string values or node name. Most bindings should not need select. - -- __allOf__ - Optional. A list of other schemas to include. This is used to -include other schemas the binding conforms to. This may be schemas for a -particular class of devices such as I2C or SPI controllers. - -- __properties__ - A set of sub-schema defining all the DT properties for the -binding. The exact schema syntax depends on whether properties are known, -common properties (e.g. 'interrupts') or are binding/vendor specific properties. - - A property can also define a child DT node with child properties defined -under it. - - For more details on properties sections, see 'Property Schema' section. - -- __patternProperties__ - Optional. Similar to 'properties', but names are regex. - -- __required__ - A list of DT properties from the 'properties' section that -must always be present. - -- __examples__ - Optional. A list of one or more DTS hunks implementing the -binding. Note: YAML doesn't allow leading tabs, so spaces must be used instead. - -Unless noted otherwise, all properties are required. - -## Property Schema - -The 'properties' section of the schema contains all the DT properties for a -binding. Each property contains a set of constraints using json-schema -vocabulary for that property. The properties schemas are what is used for -validation of DT files. - -For common properties, only additional constraints not covered by the common -binding schema need to be defined such as how many values are valid or what -possible values are valid. - -Vendor specific properties will typically need more detailed schema. With the -exception of boolean properties, they should have a reference to a type in -schemas/types.yaml. A "description" property is always required. - -The Devicetree schemas don't exactly match the YAML encoded DT data produced by -dtc. They are simplified to make them more compact and avoid a bunch of -boilerplate. The tools process the schema files to produce the final schema for -validation. There are currently 2 transformations the tools perform. - -The default for arrays in json-schema is they are variable sized and allow more -entries than explicitly defined. This can be restricted by defining 'minItems', -'maxItems', and 'additionalItems'. However, for DeviceTree Schemas, a fixed -size is desired in most cases, so these properties are added based on the -number of entries in an 'items' list. - -The YAML Devicetree format also makes all string values an array and scalar -values a matrix (in order to define groupings) even when only a single value -is present. Single entries in schemas are fixed up to match this encoding. - -## Testing - -### Dependencies - -The DT schema project must be installed in order to validate the DT schema -binding documents and validate DTS files using the DT schema. The DT schema -project can be installed with pip: - -`pip3 install git+https://github.com/devicetree-org/dt-schema.git@master` - -dtc must also be built with YAML output support enabled. This requires that -libyaml and its headers be installed on the host system. - -### Running checks - -The DT schema binding documents must be validated using the meta-schema (the -schema for the schema) to ensure they are both valid json-schema and valid -binding schema. All of the DT binding documents can be validated using the -`dt_binding_check` target: - -`make dt_binding_check` - -In order to perform validation of DT source files, use the `dtbs_check` target: - -`make dtbs_check` - -This will first run the `dt_binding_check` which generates the processed schema. - -It is also possible to run checks with a single schema file by setting the -'DT_SCHEMA_FILES' variable to a specific schema file. - -`make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/trivial-devices.yaml` - - -## json-schema Resources - -[JSON-Schema Specifications](http://json-schema.org/) - -[Using JSON Schema Book](http://usingjsonschema.com/) diff --git a/Documentation/devicetree/writing-schema.rst b/Documentation/devicetree/writing-schema.rst new file mode 100644 index 000000000000..8f71d1e2ac52 --- /dev/null +++ b/Documentation/devicetree/writing-schema.rst @@ -0,0 +1,153 @@ +:orphan: + +Writing DeviceTree Bindings in json-schema +========================================== + +Devicetree bindings are written using json-schema vocabulary. Schema files are +written in a JSON compatible subset of YAML. YAML is used instead of JSON as it +considered more human readable and has some advantages such as allowing +comments (Prefixed with '#'). + +Schema Contents +--------------- + +Each schema doc is a structured json-schema which is defined by a set of +top-level properties. Generally, there is one binding defined per file. The +top-level json-schema properties used are: + +$id + A json-schema unique identifier string. The string must be a valid + URI typically containing the binding's filename and path. For DT schema, it must + begin with "http://devicetree.org/schemas/". The URL is used in constructing + references to other files specified in schema "$ref" properties. A $ref values + with a leading '/' will have the hostname prepended. A $ref value a relative + path or filename only will be prepended with the hostname and path components + of the current schema file's '$id' value. A URL is used even for local files, + but there may not actually be files present at those locations. + +$schema + Indicates the meta-schema the schema file adheres to. + +title + A one line description on the contents of the binding schema. + +maintainers + A DT specific property. Contains a list of email address(es) + for maintainers of this binding. + +description + Optional. A multi-line text block containing any detailed + information about this binding. It should contain things such as what the block + or device does, standards the device conforms to, and links to datasheets for + more information. + +select + Optional. A json-schema used to match nodes for applying the + schema. By default without 'select', nodes are matched against their possible + compatible string values or node name. Most bindings should not need select. + + allOf + Optional. A list of other schemas to include. This is used to + include other schemas the binding conforms to. This may be schemas for a + particular class of devices such as I2C or SPI controllers. + + properties + A set of sub-schema defining all the DT properties for the + binding. The exact schema syntax depends on whether properties are known, + common properties (e.g. 'interrupts') or are binding/vendor specific properties. + +A property can also define a child DT node with child properties defined +under it. + +For more details on properties sections, see 'Property Schema' section. + +patternProperties + Optional. Similar to 'properties', but names are regex. + +required + A list of DT properties from the 'properties' section that + must always be present. + +examples + Optional. A list of one or more DTS hunks implementing the + binding. Note: YAML doesn't allow leading tabs, so spaces must be used instead. + +Unless noted otherwise, all properties are required. + +Property Schema +--------------- + +The 'properties' section of the schema contains all the DT properties for a +binding. Each property contains a set of constraints using json-schema +vocabulary for that property. The properties schemas are what is used for +validation of DT files. + +For common properties, only additional constraints not covered by the common +binding schema need to be defined such as how many values are valid or what +possible values are valid. + +Vendor specific properties will typically need more detailed schema. With the +exception of boolean properties, they should have a reference to a type in +schemas/types.yaml. A "description" property is always required. + +The Devicetree schemas don't exactly match the YAML encoded DT data produced by +dtc. They are simplified to make them more compact and avoid a bunch of +boilerplate. The tools process the schema files to produce the final schema for +validation. There are currently 2 transformations the tools perform. + +The default for arrays in json-schema is they are variable sized and allow more +entries than explicitly defined. This can be restricted by defining 'minItems', +'maxItems', and 'additionalItems'. However, for DeviceTree Schemas, a fixed +size is desired in most cases, so these properties are added based on the +number of entries in an 'items' list. + +The YAML Devicetree format also makes all string values an array and scalar +values a matrix (in order to define groupings) even when only a single value +is present. Single entries in schemas are fixed up to match this encoding. + +Testing +------- + +Dependencies +~~~~~~~~~~~~ + +The DT schema project must be installed in order to validate the DT schema +binding documents and validate DTS files using the DT schema. The DT schema +project can be installed with pip:: + + pip3 install git+https://github.com/devicetree-org/dt-schema.git@master + +dtc must also be built with YAML output support enabled. This requires that +libyaml and its headers be installed on the host system. + +Running checks +~~~~~~~~~~~~~~ + +The DT schema binding documents must be validated using the meta-schema (the +schema for the schema) to ensure they are both valid json-schema and valid +binding schema. All of the DT binding documents can be validated using the +``dt_binding_check`` target:: + + make dt_binding_check + +In order to perform validation of DT source files, use the `dtbs_check` target:: + + make dtbs_check + +This will first run the `dt_binding_check` which generates the processed schema. + +It is also possible to run checks with a single schema file by setting the +``DT_SCHEMA_FILES`` variable to a specific schema file. + +:: + + make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/trivial-devices.yaml + + +json-schema Resources +--------------------- + + +`JSON-Schema Specifications `_ + +`Using JSON Schema Book `_ -- GitLab From 9cdd273e29f3b901712ec3c298b1d506861f48e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:08:50 -0300 Subject: [PATCH 1473/7155] spi: docs: convert to ReST and add it to the kABI bookset While there's one file there with briefily describes the uAPI, the documentation was written just like most subsystems: focused on kernel developers. So, add it together with driver-api books. Signed-off-by: Mauro Carvalho Chehab Acked-by: Jonathan Cameron # for iio Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 1 + .../spi/{butterfly => butterfly.rst} | 44 ++++---- Documentation/spi/index.rst | 22 ++++ Documentation/spi/{pxa2xx => pxa2xx.rst} | 95 ++++++++-------- .../spi/{spi-lm70llp => spi-lm70llp.rst} | 17 ++- .../spi/{spi-sc18is602 => spi-sc18is602.rst} | 3 + .../spi/{spi-summary => spi-summary.rst} | 105 ++++++++++-------- Documentation/spi/{spidev => spidev.rst} | 30 +++-- drivers/iio/dummy/iio_simple_dummy.c | 2 +- drivers/spi/Kconfig | 2 +- drivers/spi/spi-butterfly.c | 2 +- drivers/spi/spi-lm70llp.c | 2 +- include/linux/platform_data/sc18is602.h | 2 +- 13 files changed, 198 insertions(+), 129 deletions(-) rename Documentation/spi/{butterfly => butterfly.rst} (71%) create mode 100644 Documentation/spi/index.rst rename Documentation/spi/{pxa2xx => pxa2xx.rst} (83%) rename Documentation/spi/{spi-lm70llp => spi-lm70llp.rst} (88%) rename Documentation/spi/{spi-sc18is602 => spi-sc18is602.rst} (97%) rename Documentation/spi/{spi-summary => spi-summary.rst} (93%) rename Documentation/spi/{spidev => spidev.rst} (90%) diff --git a/Documentation/index.rst b/Documentation/index.rst index 6217acab92db..472b8abe52e9 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -116,6 +116,7 @@ needed). power/index target/index timers/index + spi/index watchdog/index virtual/index input/index diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly.rst similarity index 71% rename from Documentation/spi/butterfly rename to Documentation/spi/butterfly.rst index 9927af7a629c..e614a589547c 100644 --- a/Documentation/spi/butterfly +++ b/Documentation/spi/butterfly.rst @@ -1,3 +1,4 @@ +=================================================== spi_butterfly - parport-to-butterfly adapter driver =================================================== @@ -27,25 +28,29 @@ need to reflash the firmware, and the pins are the standard Atmel "ISP" connector pins (used also on non-Butterfly AVR boards). On the parport side this is like "sp12" programming cables. + ====== ============= =================== Signal Butterfly Parport (DB-25) - ------ --------- --------------- - SCK = J403.PB1/SCK = pin 2/D0 - RESET = J403.nRST = pin 3/D1 - VCC = J403.VCC_EXT = pin 8/D6 - MOSI = J403.PB2/MOSI = pin 9/D7 - MISO = J403.PB3/MISO = pin 11/S7,nBUSY - GND = J403.GND = pin 23/GND + ====== ============= =================== + SCK J403.PB1/SCK pin 2/D0 + RESET J403.nRST pin 3/D1 + VCC J403.VCC_EXT pin 8/D6 + MOSI J403.PB2/MOSI pin 9/D7 + MISO J403.PB3/MISO pin 11/S7,nBUSY + GND J403.GND pin 23/GND + ====== ============= =================== Then to let Linux master that bus to talk to the DataFlash chip, you must (a) flash new firmware that disables SPI (set PRR.2, and disable pullups by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and (c) cable in the chipselect. + ====== ============ =================== Signal Butterfly Parport (DB-25) - ------ --------- --------------- - VCC = J400.VCC_EXT = pin 7/D5 - SELECT = J400.PB0/nSS = pin 17/C3,nSELECT - GND = J400.GND = pin 24/GND + ====== ============ =================== + VCC J400.VCC_EXT pin 7/D5 + SELECT J400.PB0/nSS pin 17/C3,nSELECT + GND J400.GND pin 24/GND + ====== ============ =================== Or you could flash firmware making the AVR into an SPI slave (keeping the DataFlash in reset) and tweak the spi_butterfly driver to make it bind to @@ -56,13 +61,14 @@ That would let you talk to the AVR using custom SPI-with-USI firmware, while letting either Linux or the AVR use the DataFlash. There are plenty of spare parport pins to wire this one up, such as: + ====== ============= =================== Signal Butterfly Parport (DB-25) - ------ --------- --------------- - SCK = J403.PE4/USCK = pin 5/D3 - MOSI = J403.PE5/DI = pin 6/D4 - MISO = J403.PE6/DO = pin 12/S5,nPAPEROUT - GND = J403.GND = pin 22/GND - - IRQ = J402.PF4 = pin 10/S6,ACK - GND = J402.GND(P2) = pin 25/GND + ====== ============= =================== + SCK J403.PE4/USCK pin 5/D3 + MOSI J403.PE5/DI pin 6/D4 + MISO J403.PE6/DO pin 12/S5,nPAPEROUT + GND J403.GND pin 22/GND + IRQ J402.PF4 pin 10/S6,ACK + GND J402.GND(P2) pin 25/GND + ====== ============= =================== diff --git a/Documentation/spi/index.rst b/Documentation/spi/index.rst new file mode 100644 index 000000000000..06c34ea11bcf --- /dev/null +++ b/Documentation/spi/index.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================= +Serial Peripheral Interface (SPI) +================================= + +.. toctree:: + :maxdepth: 1 + + spi-summary + spidev + butterfly + pxa2xx + spi-lm70llp + spi-sc18is602 + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx.rst similarity index 83% rename from Documentation/spi/pxa2xx rename to Documentation/spi/pxa2xx.rst index 551325b66b23..882d3cc72cc2 100644 --- a/Documentation/spi/pxa2xx +++ b/Documentation/spi/pxa2xx.rst @@ -1,8 +1,10 @@ +============================== PXA2xx SPI on SSP driver HOWTO -=================================================== +============================== + This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx synchronous serial port into a SPI master controller -(see Documentation/spi/spi-summary). The driver has the following features +(see Documentation/spi/spi-summary.rst). The driver has the following features - Support for any PXA2xx SSP - SSP PIO and SSP DMA data transfers. @@ -19,12 +21,12 @@ Declaring PXA2xx Master Controllers ----------------------------------- Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a "platform device". The master configuration is passed to the driver via a table -found in include/linux/spi/pxa2xx_spi.h: +found in include/linux/spi/pxa2xx_spi.h:: -struct pxa2xx_spi_controller { + struct pxa2xx_spi_controller { u16 num_chipselect; u8 enable_dma; -}; + }; The "pxa2xx_spi_controller.num_chipselect" field is used to determine the number of slave device (chips) attached to this SPI master. @@ -36,9 +38,9 @@ See the "PXA2xx Developer Manual" section "DMA Controller". NSSP MASTER SAMPLE ------------------ -Below is a sample configuration using the PXA255 NSSP. +Below is a sample configuration using the PXA255 NSSP:: -static struct resource pxa_spi_nssp_resources[] = { + static struct resource pxa_spi_nssp_resources[] = { [0] = { .start = __PREG(SSCR0_P(2)), /* Start address of NSSP */ .end = __PREG(SSCR0_P(2)) + 0x2c, /* Range of registers */ @@ -49,14 +51,14 @@ static struct resource pxa_spi_nssp_resources[] = { .end = IRQ_NSSP, .flags = IORESOURCE_IRQ, }, -}; + }; -static struct pxa2xx_spi_controller pxa_nssp_master_info = { + static struct pxa2xx_spi_controller pxa_nssp_master_info = { .num_chipselect = 1, /* Matches the number of chips attached to NSSP */ .enable_dma = 1, /* Enables NSSP DMA */ -}; + }; -static struct platform_device pxa_spi_nssp = { + static struct platform_device pxa_spi_nssp = { .name = "pxa2xx-spi", /* MUST BE THIS VALUE, so device match driver */ .id = 2, /* Bus number, MUST MATCH SSP number 1..n */ .resource = pxa_spi_nssp_resources, @@ -64,22 +66,22 @@ static struct platform_device pxa_spi_nssp = { .dev = { .platform_data = &pxa_nssp_master_info, /* Passed to driver */ }, -}; + }; -static struct platform_device *devices[] __initdata = { + static struct platform_device *devices[] __initdata = { &pxa_spi_nssp, -}; + }; -static void __init board_init(void) -{ + static void __init board_init(void) + { (void)platform_add_device(devices, ARRAY_SIZE(devices)); -} + } Declaring Slave Devices ----------------------- Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c using the "spi_board_info" structure found in "linux/spi/spi.h". See -"Documentation/spi/spi-summary" for additional information. +"Documentation/spi/spi-summary.rst" for additional information. Each slave device attached to the PXA must provide slave specific configuration information via the structure "pxa2xx_spi_chip" found in @@ -87,19 +89,21 @@ information via the structure "pxa2xx_spi_chip" found in will uses the configuration whenever the driver communicates with the slave device. All fields are optional. -struct pxa2xx_spi_chip { +:: + + struct pxa2xx_spi_chip { u8 tx_threshold; u8 rx_threshold; u8 dma_burst_size; u32 timeout; u8 enable_loopback; void (*cs_control)(u32 command); -}; + }; The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are used to configure the SSP hardware fifo. These fields are critical to the performance of pxa2xx_spi driver and misconfiguration will result in rx -fifo overruns (especially in PIO mode transfers). Good default values are +fifo overruns (especially in PIO mode transfers). Good default values are:: .tx_threshold = 8, .rx_threshold = 8, @@ -141,41 +145,43 @@ The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the "spi_board_info.controller_data" field. Below is a sample configuration using the PXA255 NSSP. -/* Chip Select control for the CS8415A SPI slave device */ -static void cs8415a_cs_control(u32 command) -{ +:: + + /* Chip Select control for the CS8415A SPI slave device */ + static void cs8415a_cs_control(u32 command) + { if (command & PXA2XX_CS_ASSERT) GPCR(2) = GPIO_bit(2); else GPSR(2) = GPIO_bit(2); -} + } -/* Chip Select control for the CS8405A SPI slave device */ -static void cs8405a_cs_control(u32 command) -{ + /* Chip Select control for the CS8405A SPI slave device */ + static void cs8405a_cs_control(u32 command) + { if (command & PXA2XX_CS_ASSERT) GPCR(3) = GPIO_bit(3); else GPSR(3) = GPIO_bit(3); -} + } -static struct pxa2xx_spi_chip cs8415a_chip_info = { + static struct pxa2xx_spi_chip cs8415a_chip_info = { .tx_threshold = 8, /* SSP hardward FIFO threshold */ .rx_threshold = 8, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .timeout = 235, /* See Intel documentation */ .cs_control = cs8415a_cs_control, /* Use external chip select */ -}; + }; -static struct pxa2xx_spi_chip cs8405a_chip_info = { + static struct pxa2xx_spi_chip cs8405a_chip_info = { .tx_threshold = 8, /* SSP hardward FIFO threshold */ .rx_threshold = 8, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .timeout = 235, /* See Intel documentation */ .cs_control = cs8405a_cs_control, /* Use external chip select */ -}; + }; -static struct spi_board_info streetracer_spi_board_info[] __initdata = { + static struct spi_board_info streetracer_spi_board_info[] __initdata = { { .modalias = "cs8415a", /* Name of spi_driver for this device */ .max_speed_hz = 3686400, /* Run SSP as fast a possbile */ @@ -193,13 +199,13 @@ static struct spi_board_info streetracer_spi_board_info[] __initdata = { .controller_data = &cs8405a_chip_info, /* Master chip config */ .irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */ }, -}; + }; -static void __init streetracer_init(void) -{ + static void __init streetracer_init(void) + { spi_register_board_info(streetracer_spi_board_info, ARRAY_SIZE(streetracer_spi_board_info)); -} + } DMA and PIO I/O Support @@ -210,26 +216,25 @@ by setting the "enable_dma" flag in the "pxa2xx_spi_controller" structure. The mode supports both coherent and stream based DMA mappings. The following logic is used to determine the type of I/O to be used on -a per "spi_transfer" basis: +a per "spi_transfer" basis:: -if !enable_dma then + if !enable_dma then always use PIO transfers -if spi_message.len > 8191 then + if spi_message.len > 8191 then print "rate limited" warning use PIO transfers -if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then + if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then use coherent DMA mode -if rx_buf and tx_buf are aligned on 8 byte boundary then + if rx_buf and tx_buf are aligned on 8 byte boundary then use streaming DMA mode -otherwise + otherwise use PIO transfer THANKS TO --------- David Brownell and others for mentoring the development of this driver. - diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp.rst similarity index 88% rename from Documentation/spi/spi-lm70llp rename to Documentation/spi/spi-lm70llp.rst index 463f6d01fa15..07631aef4343 100644 --- a/Documentation/spi/spi-lm70llp +++ b/Documentation/spi/spi-lm70llp.rst @@ -1,8 +1,11 @@ +============================================== spi_lm70llp : LM70-LLP parport-to-SPI adapter ============================================== Supported board/chip: + * National Semiconductor LM70 LLP evaluation board + Datasheet: http://www.national.com/pf/LM/LM70.html Author: @@ -29,9 +32,10 @@ available (on page 4) here: The hardware interfacing on the LM70 LLP eval board is as follows: + ======== == ========= ========== Parallel LM70 LLP - Port Direction JP2 Header - ----------- --------- ---------------- + Port . Direction JP2 Header + ======== == ========= ========== D0 2 - - D1 3 --> V+ 5 D2 4 --> V+ 5 @@ -42,7 +46,7 @@ The hardware interfacing on the LM70 LLP eval board is as follows: D7 9 --> SI/O 5 GND 25 - GND 7 Select 13 <-- SI/O 1 - ----------- --------- ---------------- + ======== == ========= ========== Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin is connected to both pin D7 (as Master Out) and Select (as Master In) @@ -74,6 +78,7 @@ inverting the value read at pin 13. Thanks to --------- -o David Brownell for mentoring the SPI-side driver development. -o Dr.Craig Hollabaugh for the (early) "manual" bitbanging driver version. -o Nadir Billimoria for help interpreting the circuit schematic. + +- David Brownell for mentoring the SPI-side driver development. +- Dr.Craig Hollabaugh for the (early) "manual" bitbanging driver version. +- Nadir Billimoria for help interpreting the circuit schematic. diff --git a/Documentation/spi/spi-sc18is602 b/Documentation/spi/spi-sc18is602.rst similarity index 97% rename from Documentation/spi/spi-sc18is602 rename to Documentation/spi/spi-sc18is602.rst index 0feffd5af411..2a31dc722321 100644 --- a/Documentation/spi/spi-sc18is602 +++ b/Documentation/spi/spi-sc18is602.rst @@ -1,8 +1,11 @@ +=========================== Kernel driver spi-sc18is602 =========================== Supported chips: + * NXP SI18IS602/602B/603 + Datasheet: http://www.nxp.com/documents/data_sheet/SC18IS602_602B_603.pdf Author: diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary.rst similarity index 93% rename from Documentation/spi/spi-summary rename to Documentation/spi/spi-summary.rst index 1a63194b74d7..f1daffe10d78 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary.rst @@ -1,3 +1,4 @@ +==================================== Overview of Linux kernel SPI support ==================================== @@ -139,12 +140,14 @@ a command and then reading its response. There are two types of SPI driver, here called: - Controller drivers ... controllers may be built into System-On-Chip + Controller drivers ... + controllers may be built into System-On-Chip processors, and often support both Master and Slave roles. These drivers touch hardware registers and may use DMA. Or they can be PIO bitbangers, needing just GPIO pins. - Protocol drivers ... these pass messages through the controller + Protocol drivers ... + these pass messages through the controller driver to communicate with a Slave or Master device on the other side of an SPI link. @@ -160,7 +163,7 @@ those two types of drivers. There is a minimal core of SPI programming interfaces, focussing on using the driver model to connect controller and protocol drivers using device tables provided by board specific initialization code. SPI -shows up in sysfs in several locations: +shows up in sysfs in several locations:: /sys/devices/.../CTLR ... physical node for a given SPI controller @@ -168,7 +171,7 @@ shows up in sysfs in several locations: chipselect C, accessed through CTLR. /sys/bus/spi/devices/spiB.C ... symlink to that physical - .../CTLR/spiB.C device + .../CTLR/spiB.C device /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver that should be used with this device (for hotplug/coldplug) @@ -206,7 +209,8 @@ Linux needs several kinds of information to properly configure SPI devices. That information is normally provided by board-specific code, even for chips that do support some of automated discovery/enumeration. -DECLARE CONTROLLERS +Declare Controllers +^^^^^^^^^^^^^^^^^^^ The first kind of information is a list of what SPI controllers exist. For System-on-Chip (SOC) based boards, these will usually be platform @@ -221,7 +225,7 @@ same basic controller setup code. This is because most SOCs have several SPI-capable controllers, and only the ones actually usable on a given board should normally be set up and registered. -So for example arch/.../mach-*/board-*.c files might have code like: +So for example arch/.../mach-*/board-*.c files might have code like:: #include /* for mysoc_spi_data */ @@ -238,7 +242,7 @@ So for example arch/.../mach-*/board-*.c files might have code like: ... } -And SOC-specific utility code might look something like: +And SOC-specific utility code might look something like:: #include @@ -269,8 +273,8 @@ same SOC controller is used. For example, on one board SPI might use an external clock, where another derives the SPI clock from current settings of some master clock. - -DECLARE SLAVE DEVICES +Declare Slave Devices +^^^^^^^^^^^^^^^^^^^^^ The second kind of information is a list of what SPI slave devices exist on the target board, often with some board-specific data needed for the @@ -278,7 +282,7 @@ driver to work correctly. Normally your arch/.../mach-*/board-*.c files would provide a small table listing the SPI devices on each board. (This would typically be only a -small handful.) That might look like: +small handful.) That might look like:: static struct ads7846_platform_data ads_info = { .vref_delay_usecs = 100, @@ -316,7 +320,7 @@ not possible until the infrastructure knows how to deselect it. Then your board initialization code would register that table with the SPI infrastructure, so that it's available later when the SPI master controller -driver is registered: +driver is registered:: spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); @@ -324,12 +328,13 @@ Like with other static board-specific setup, you won't unregister those. The widely used "card" style computers bundle memory, cpu, and little else onto a card that's maybe just thirty square centimeters. On such systems, -your arch/.../mach-.../board-*.c file would primarily provide information +your ``arch/.../mach-.../board-*.c`` file would primarily provide information about the devices on the mainboard into which such a card is plugged. That certainly includes SPI devices hooked up through the card connectors! -NON-STATIC CONFIGURATIONS +Non-static Configurations +^^^^^^^^^^^^^^^^^^^^^^^^^ Developer boards often play by different rules than product boards, and one example is the potential need to hotplug SPI devices and/or controllers. @@ -349,7 +354,7 @@ How do I write an "SPI Protocol Driver"? Most SPI drivers are currently kernel drivers, but there's also support for userspace drivers. Here we talk only about kernel drivers. -SPI protocol drivers somewhat resemble platform device drivers: +SPI protocol drivers somewhat resemble platform device drivers:: static struct spi_driver CHIP_driver = { .driver = { @@ -367,6 +372,8 @@ device whose board_info gave a modalias of "CHIP". Your probe() code might look like this unless you're creating a device which is managing a bus (appearing under /sys/class/spi_master). +:: + static int CHIP_probe(struct spi_device *spi) { struct CHIP *chip; @@ -479,6 +486,8 @@ The main task of this type of driver is to provide an "spi_master". Use spi_alloc_master() to allocate the master, and spi_master_get_devdata() to get the driver-private data allocated for that device. +:: + struct spi_master *master; struct CONTROLLER *c; @@ -503,7 +512,8 @@ If you need to remove your SPI controller driver, spi_unregister_master() will reverse the effect of spi_register_master(). -BUS NUMBERING +Bus Numbering +^^^^^^^^^^^^^ Bus numbering is important, since that's how Linux identifies a given SPI bus (shared SCK, MOSI, MISO). Valid bus numbers start at zero. On @@ -517,9 +527,10 @@ then be replaced by a dynamically assigned number. You'd then need to treat this as a non-static configuration (see above). -SPI MASTER METHODS +SPI Master Methods +^^^^^^^^^^^^^^^^^^ - master->setup(struct spi_device *spi) +``master->setup(struct spi_device *spi)`` This sets up the device clock rate, SPI mode, and word sizes. Drivers may change the defaults provided by board_info, and then call spi_setup(spi) to invoke this routine. It may sleep. @@ -528,37 +539,37 @@ SPI MASTER METHODS change them right away ... otherwise drivers could corrupt I/O that's in progress for other SPI devices. - ** BUG ALERT: for some reason the first version of - ** many spi_master drivers seems to get this wrong. - ** When you code setup(), ASSUME that the controller - ** is actively processing transfers for another device. + .. note:: + + BUG ALERT: for some reason the first version of + many spi_master drivers seems to get this wrong. + When you code setup(), ASSUME that the controller + is actively processing transfers for another device. - master->cleanup(struct spi_device *spi) +``master->cleanup(struct spi_device *spi)`` Your controller driver may use spi_device.controller_state to hold state it dynamically associates with that device. If you do that, be sure to provide the cleanup() method to free that state. - master->prepare_transfer_hardware(struct spi_master *master) +``master->prepare_transfer_hardware(struct spi_master *master)`` This will be called by the queue mechanism to signal to the driver that a message is coming in soon, so the subsystem requests the driver to prepare the transfer hardware by issuing this call. This may sleep. - master->unprepare_transfer_hardware(struct spi_master *master) +``master->unprepare_transfer_hardware(struct spi_master *master)`` This will be called by the queue mechanism to signal to the driver that there are no more messages pending in the queue and it may relax the hardware (e.g. by power management calls). This may sleep. - master->transfer_one_message(struct spi_master *master, - struct spi_message *mesg) +``master->transfer_one_message(struct spi_master *master, struct spi_message *mesg)`` The subsystem calls the driver to transfer a single message while queuing transfers that arrive in the meantime. When the driver is finished with this message, it must call spi_finalize_current_message() so the subsystem can issue the next message. This may sleep. - master->transfer_one(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *transfer) +``master->transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer)`` The subsystem calls the driver to transfer a single transfer while queuing transfers that arrive in the meantime. When the driver is finished with this transfer, it must call @@ -568,19 +579,20 @@ SPI MASTER METHODS not call your transfer_one callback. Return values: - negative errno: error - 0: transfer is finished - 1: transfer is still in progress - master->set_cs_timing(struct spi_device *spi, u8 setup_clk_cycles, - u8 hold_clk_cycles, u8 inactive_clk_cycles) + * negative errno: error + * 0: transfer is finished + * 1: transfer is still in progress + +``master->set_cs_timing(struct spi_device *spi, u8 setup_clk_cycles, u8 hold_clk_cycles, u8 inactive_clk_cycles)`` This method allows SPI client drivers to request SPI master controller for configuring device specific CS setup, hold and inactive timing requirements. - DEPRECATED METHODS +Deprecated Methods +^^^^^^^^^^^^^^^^^^ - master->transfer(struct spi_device *spi, struct spi_message *message) +``master->transfer(struct spi_device *spi, struct spi_message *message)`` This must not sleep. Its responsibility is to arrange that the transfer happens and its complete() callback is issued. The two will normally happen later, after other transfers complete, and @@ -590,7 +602,8 @@ SPI MASTER METHODS implemented. -SPI MESSAGE QUEUE +SPI Message Queue +^^^^^^^^^^^^^^^^^ If you are happy with the standard queueing mechanism provided by the SPI subsystem, just implement the queued methods specified above. Using @@ -619,13 +632,13 @@ THANKS TO Contributors to Linux-SPI discussions include (in alphabetical order, by last name): -Mark Brown -David Brownell -Russell King -Grant Likely -Dmitry Pervushin -Stephen Street -Mark Underwood -Andrew Victor -Linus Walleij -Vitaly Wool +- Mark Brown +- David Brownell +- Russell King +- Grant Likely +- Dmitry Pervushin +- Stephen Street +- Mark Underwood +- Andrew Victor +- Linus Walleij +- Vitaly Wool diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev.rst similarity index 90% rename from Documentation/spi/spidev rename to Documentation/spi/spidev.rst index 3d14035b1766..f05dbc5ccdbc 100644 --- a/Documentation/spi/spidev +++ b/Documentation/spi/spidev.rst @@ -1,7 +1,13 @@ +================= +SPI userspace API +================= + SPI devices have a limited userspace API, supporting basic half-duplex read() and write() access to SPI slave devices. Using ioctl() requests, full duplex transfers and device I/O configuration are also available. +:: + #include #include #include @@ -39,14 +45,17 @@ device node with a "dev" attribute that will be understood by udev or mdev. busybox; it's less featureful, but often enough.) For a SPI device with chipselect C on bus B, you should see: - /dev/spidevB.C ... character special device, major number 153 with + /dev/spidevB.C ... + character special device, major number 153 with a dynamically chosen minor device number. This is the node that userspace programs will open, created by "udev" or "mdev". - /sys/devices/.../spiB.C ... as usual, the SPI device node will + /sys/devices/.../spiB.C ... + as usual, the SPI device node will be a child of its SPI master controller. - /sys/class/spidev/spidevB.C ... created when the "spidev" driver + /sys/class/spidev/spidevB.C ... + created when the "spidev" driver binds to that device. (Directory or symlink, based on whether or not you enabled the "deprecated sysfs files" Kconfig option.) @@ -80,7 +89,8 @@ the SPI_IOC_MESSAGE(N) request. Several ioctl() requests let your driver read or override the device's current settings for data transfer parameters: - SPI_IOC_RD_MODE, SPI_IOC_WR_MODE ... pass a pointer to a byte which will + SPI_IOC_RD_MODE, SPI_IOC_WR_MODE ... + pass a pointer to a byte which will return (RD) or assign (WR) the SPI transfer mode. Use the constants SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase, @@ -88,22 +98,26 @@ settings for data transfer parameters: Note that this request is limited to SPI mode flags that fit in a single byte. - SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t + SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... + pass a pointer to a uin32_t which will return (RD) or assign (WR) the full SPI transfer mode, not limited to the bits that fit in one byte. - SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte + SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... + pass a pointer to a byte which will return (RD) or assign (WR) the bit justification used to transfer SPI words. Zero indicates MSB-first; other values indicate the less common LSB-first encoding. In both cases the specified value is right-justified in each word, so that unused (TX) or undefined (RX) bits are in the MSBs. - SPI_IOC_RD_BITS_PER_WORD, SPI_IOC_WR_BITS_PER_WORD ... pass a pointer to + SPI_IOC_RD_BITS_PER_WORD, SPI_IOC_WR_BITS_PER_WORD ... + pass a pointer to a byte which will return (RD) or assign (WR) the number of bits in each SPI transfer word. The value zero signifies eight bits. - SPI_IOC_RD_MAX_SPEED_HZ, SPI_IOC_WR_MAX_SPEED_HZ ... pass a pointer to a + SPI_IOC_RD_MAX_SPEED_HZ, SPI_IOC_WR_MAX_SPEED_HZ ... + pass a pointer to a u32 which will return (RD) or assign (WR) the maximum SPI transfer speed, in Hz. The controller can't necessarily assign that specific clock speed. diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c index d28974ad9e0e..6cb02299a215 100644 --- a/drivers/iio/dummy/iio_simple_dummy.c +++ b/drivers/iio/dummy/iio_simple_dummy.c @@ -695,7 +695,7 @@ static int iio_dummy_remove(struct iio_sw_device *swd) * i2c: * Documentation/i2c/writing-clients.rst * spi: - * Documentation/spi/spi-summary + * Documentation/spi/spi-summary.rst */ static const struct iio_sw_device_ops iio_dummy_device_ops = { .probe = iio_dummy_probe, diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3a1d8f1170de..d5a24fe983e7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -543,7 +543,7 @@ config SPI_PXA2XX help This enables using a PXA2xx or Sodaville SSP port as a SPI master controller. The driver can be configured to use any SSP port and - additional documentation can be found a Documentation/spi/pxa2xx. + additional documentation can be found a Documentation/spi/pxa2xx.rst. config SPI_PXA2XX_PCI def_tristate SPI_PXA2XX && PCI && COMMON_CLK diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 8c77d1114ad3..7e71a351f3b7 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -23,7 +23,7 @@ * with a battery powered AVR microcontroller and lots of goodies. You * can use GCC to develop firmware for this. * - * See Documentation/spi/butterfly for information about how to build + * See Documentation/spi/butterfly.rst for information about how to build * and use this custom parallel port cable. */ diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index f18f912c9dea..174dba29b1dd 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -34,7 +34,7 @@ * available (on page 4) here: * http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf * - * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is + * Also see Documentation/spi/spi-lm70llp.rst. The SPI<->parport code here is * (heavily) based on spi-butterfly by David Brownell. * * The LM70 LLP connects to the PC parallel port in the following manner: diff --git a/include/linux/platform_data/sc18is602.h b/include/linux/platform_data/sc18is602.h index e066d3b0d6d8..0e91489edfe6 100644 --- a/include/linux/platform_data/sc18is602.h +++ b/include/linux/platform_data/sc18is602.h @@ -4,7 +4,7 @@ * * Copyright (C) 2012 Guenter Roeck * - * For further information, see the Documentation/spi/spi-sc18is602 file. + * For further information, see the Documentation/spi/spi-sc18is602.rst file. */ /** -- GitLab From f139291c713069b5fa826ff509190efb5df83860 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:08:51 -0300 Subject: [PATCH 1474/7155] docs: fs: cifs: convert to ReST and add to admin-guide book The filenames for cifs documentation is not using the same convention as almost all Kernel documents is using. So, rename them to a more appropriate name. Then, manually convert the documentation files for CIFS to ReST. By doing a manual conversion, we can preserve the original author's style, while making it to look more like the other Kernel documents. Most of the conversion here is trivial. The most complex one was the README file (which was renamed to usage.rst). Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- .../AUTHORS => admin-guide/cifs/authors.rst} | 64 +- .../CHANGES => admin-guide/cifs/changes.rst} | 4 + Documentation/admin-guide/cifs/index.rst | 21 + .../cifs/introduction.rst} | 8 + .../cifs/TODO => admin-guide/cifs/todo.rst} | 87 +-- .../README => admin-guide/cifs/usage.rst} | 562 +++++++++++------- .../cifs/winucase_convert.pl | 0 Documentation/admin-guide/index.rst | 1 + MAINTAINERS | 2 +- 9 files changed, 461 insertions(+), 288 deletions(-) rename Documentation/{filesystems/cifs/AUTHORS => admin-guide/cifs/authors.rst} (60%) rename Documentation/{filesystems/cifs/CHANGES => admin-guide/cifs/changes.rst} (91%) create mode 100644 Documentation/admin-guide/cifs/index.rst rename Documentation/{filesystems/cifs/cifs.txt => admin-guide/cifs/introduction.rst} (98%) rename Documentation/{filesystems/cifs/TODO => admin-guide/cifs/todo.rst} (58%) rename Documentation/{filesystems/cifs/README => admin-guide/cifs/usage.rst} (72%) rename Documentation/{filesystems => admin-guide}/cifs/winucase_convert.pl (100%) diff --git a/Documentation/filesystems/cifs/AUTHORS b/Documentation/admin-guide/cifs/authors.rst similarity index 60% rename from Documentation/filesystems/cifs/AUTHORS rename to Documentation/admin-guide/cifs/authors.rst index 75865da2ce14..b02d6dd6c070 100644 --- a/Documentation/filesystems/cifs/AUTHORS +++ b/Documentation/admin-guide/cifs/authors.rst @@ -1,5 +1,10 @@ +======= +Authors +======= + Original Author -=============== +--------------- + Steve French (sfrench@samba.org) The author wishes to express his appreciation and thanks to: @@ -12,7 +17,7 @@ side of the original CIFS Unix extensions and reviewing and implementing portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) for proving years ago that very good smb/cifs clients could be done on Unix-like -operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John +operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin and others for their work on the Linux smbfs module. Thanks to the other members of the Storage Network Industry Association CIFS Technical Workgroup for their work specifying this highly complex protocol and finally @@ -20,33 +25,34 @@ thanks to the Samba team for their technical advice and encouragement. Patch Contributors ------------------ -Zwane Mwaikambo -Andi Kleen -Amrut Joshi -Shobhit Dayal -Sergey Vlasov -Richard Hughes -Yury Umanets -Mark Hamzy (for some of the early cifs IPv6 work) -Domen Puncer -Jesper Juhl (in particular for lots of whitespace/formatting cleanup) -Vince Negri and Dave Stahl (for finding an important caching bug) -Adrian Bunk (kcalloc cleanups) -Miklos Szeredi -Kazeon team for various fixes especially for 2.4 version. -Asser Ferno (Change Notify support) -Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanup -Gunter Kukkukk (testing and suggestions for support of old servers) -Igor Mammedov (DFS support) -Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) -Scott Lovenberg -Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features) -Aurelien Aptel (for DFS SMB3 work and some key bug fixes) -Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding) -Shirish Pargaonkar (for many ACL patches over the years) -Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security) -Paulo Alcantara -Long Li (some great work on RDMA, SMB Direct) + +- Zwane Mwaikambo +- Andi Kleen +- Amrut Joshi +- Shobhit Dayal +- Sergey Vlasov +- Richard Hughes +- Yury Umanets +- Mark Hamzy (for some of the early cifs IPv6 work) +- Domen Puncer +- Jesper Juhl (in particular for lots of whitespace/formatting cleanup) +- Vince Negri and Dave Stahl (for finding an important caching bug) +- Adrian Bunk (kcalloc cleanups) +- Miklos Szeredi +- Kazeon team for various fixes especially for 2.4 version. +- Asser Ferno (Change Notify support) +- Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanup +- Gunter Kukkukk (testing and suggestions for support of old servers) +- Igor Mammedov (DFS support) +- Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) +- Scott Lovenberg +- Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features) +- Aurelien Aptel (for DFS SMB3 work and some key bug fixes) +- Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding) +- Shirish Pargaonkar (for many ACL patches over the years) +- Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security) +- Paulo Alcantara +- Long Li (some great work on RDMA, SMB Direct) Test case and Bug Report contributors diff --git a/Documentation/filesystems/cifs/CHANGES b/Documentation/admin-guide/cifs/changes.rst similarity index 91% rename from Documentation/filesystems/cifs/CHANGES rename to Documentation/admin-guide/cifs/changes.rst index 1df7f4910eb2..71f2ecb62299 100644 --- a/Documentation/filesystems/cifs/CHANGES +++ b/Documentation/admin-guide/cifs/changes.rst @@ -1,3 +1,7 @@ +======= +Changes +======= + See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary information (that may be easier to read than parsing the output of "git log fs/cifs") about fixes/improvements to CIFS/SMB2/SMB3 support (changes diff --git a/Documentation/admin-guide/cifs/index.rst b/Documentation/admin-guide/cifs/index.rst new file mode 100644 index 000000000000..fad5268635f5 --- /dev/null +++ b/Documentation/admin-guide/cifs/index.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==== +CIFS +==== + +.. toctree:: + :maxdepth: 2 + + introduction + usage + todo + changes + authors + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/filesystems/cifs/cifs.txt b/Documentation/admin-guide/cifs/introduction.rst similarity index 98% rename from Documentation/filesystems/cifs/cifs.txt rename to Documentation/admin-guide/cifs/introduction.rst index 1be3d21c286e..0b98f672d36f 100644 --- a/Documentation/filesystems/cifs/cifs.txt +++ b/Documentation/admin-guide/cifs/introduction.rst @@ -1,3 +1,7 @@ +============ +Introduction +============ + This is the client VFS module for the SMB3 NAS protocol as well as for older dialects such as the Common Internet File System (CIFS) protocol which was the successor to the Server Message Block @@ -33,7 +37,9 @@ tools (including smbinfo and setcifsacl) that can be obtained from https://git.samba.org/?p=cifs-utils.git + or + git://git.samba.org/cifs-utils.git mount.cifs should be installed in the directory with the other mount helpers. @@ -41,5 +47,7 @@ For more information on the module see the project wiki page at https://wiki.samba.org/index.php/LinuxCIFS + and + https://wiki.samba.org/index.php/LinuxCIFS_utils diff --git a/Documentation/filesystems/cifs/TODO b/Documentation/admin-guide/cifs/todo.rst similarity index 58% rename from Documentation/filesystems/cifs/TODO rename to Documentation/admin-guide/cifs/todo.rst index 9267f3fb131f..95f18e8c9b8a 100644 --- a/Documentation/filesystems/cifs/TODO +++ b/Documentation/admin-guide/cifs/todo.rst @@ -1,3 +1,7 @@ +==== +TODO +==== + Version 2.14 December 21, 2018 A Partial List of Missing Features @@ -8,6 +12,7 @@ for visible, important contributions to this module. Here is a partial list of the known problems and missing features: a) SMB3 (and SMB3.1.1) missing optional features: + - multichannel (started), integration with RDMA - directory leases (improved metadata caching), started (root dir only) - T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl @@ -16,45 +21,46 @@ a) SMB3 (and SMB3.1.1) missing optional features: b) improved sparse file support c) Directory entry caching relies on a 1 second timer, rather than -using Directory Leases, currently only the root file handle is cached longer + using Directory Leases, currently only the root file handle is cached longer d) quota support (needs minor kernel change since quota calls -to make it to network filesystems or deviceless filesystems) + to make it to network filesystems or deviceless filesystems) e) Additional use cases where we use "compoounding" (e.g. open/query/close -and open/setinfo/close) to reduce the number of roundtrips, and also -open to reduce redundant opens (using deferred close and reference counts more). + and open/setinfo/close) to reduce the number of roundtrips, and also + open to reduce redundant opens (using deferred close and reference counts + more). f) Finish inotify support so kde and gnome file list windows -will autorefresh (partially complete by Asser). Needs minor kernel -vfs change to support removing D_NOTIFY on a file. + will autorefresh (partially complete by Asser). Needs minor kernel + vfs change to support removing D_NOTIFY on a file. g) Add GUI tool to configure /proc/fs/cifs settings and for display of -the CIFS statistics (started) + the CIFS statistics (started) h) implement support for security and trusted categories of xattrs -(requires minor protocol extension) to enable better support for SELINUX + (requires minor protocol extension) to enable better support for SELINUX i) Add support for tree connect contexts (see MS-SMB2) a new SMB3.1.1 protocol feature (may be especially useful for virtualization). j) Create UID mapping facility so server UIDs can be mapped on a per -mount or a per server basis to client UIDs or nobody if no mapping -exists. Also better integration with winbind for resolving SID owners + mount or a per server basis to client UIDs or nobody if no mapping + exists. Also better integration with winbind for resolving SID owners k) Add tools to take advantage of more smb3 specific ioctls and features -(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server -is in progress, and a passthrough query_info call is already implemented -in cifs.ko to allow smb3 info levels queries to be sent from userspace) + (passthrough ioctl/fsctl for sending various SMB3 fsctls to the server + is in progress, and a passthrough query_info call is already implemented + in cifs.ko to allow smb3 info levels queries to be sent from userspace) l) encrypted file support m) improved stats gathering tools (perhaps integration with nfsometer?) -to extend and make easier to use what is currently in /proc/fs/cifs/Stats + to extend and make easier to use what is currently in /proc/fs/cifs/Stats -n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed -file attribute via chflags) and improve user space tools for managing and -viewing them. +n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to + compressed file attribute via chflags) and improve user space tools for + managing and viewing them. o) mount helper GUI (to simplify the various configuration options on mount) @@ -65,55 +71,56 @@ p) Add support for witness protocol (perhaps ioctl to cifs.ko from user space different servers, and the server we are connected to has gone down. q) Allow mount.cifs to be more verbose in reporting errors with dialect -or unsupported feature errors. + or unsupported feature errors. r) updating cifs documentation, and user guide. s) Addressing bugs found by running a broader set of xfstests in standard -file system xfstest suite. + file system xfstest suite. t) split cifs and smb3 support into separate modules so legacy (and less -secure) CIFS dialect can be disabled in environments that don't need it -and simplify the code. + secure) CIFS dialect can be disabled in environments that don't need it + and simplify the code. v) POSIX Extensions for SMB3.1.1 (started, create and mkdir support added -so far). + so far). w) Add support for additional strong encryption types, and additional spnego -authentication mechanisms (see MS-SMB2) + authentication mechanisms (see MS-SMB2) + +Known Bugs +========== -KNOWN BUGS -==================================== See http://bugzilla.samba.org - search on product "CifsVFS" for current bug list. Also check http://bugzilla.kernel.org (Product = File System, Component = CIFS) 1) existing symbolic links (Windows reparse points) are recognized but -can not be created remotely. They are implemented for Samba and those that -support the CIFS Unix extensions, although earlier versions of Samba -overly restrict the pathnames. + can not be created remotely. They are implemented for Samba and those that + support the CIFS Unix extensions, although earlier versions of Samba + overly restrict the pathnames. 2) follow_link and readdir code does not follow dfs junctions -but recognizes them + but recognizes them Misc testing to do ================== 1) check out max path names and max path name components against various server -types. Try nested symlinks (8 deep). Return max path name in stat -f information + types. Try nested symlinks (8 deep). Return max path name in stat -f information 2) Improve xfstest's cifs/smb3 enablement and adapt xfstests where needed to test -cifs/smb3 better + cifs/smb3 better -3) Additional performance testing and optimization using iozone and similar - -there are some easy changes that can be done to parallelize sequential writes, -and when signing is disabled to request larger read sizes (larger than -negotiated size) and send larger write sizes to modern servers. +3) Additional performance testing and optimization using iozone and similar - + there are some easy changes that can be done to parallelize sequential writes, + and when signing is disabled to request larger read sizes (larger than + negotiated size) and send larger write sizes to modern servers. 4) More exhaustively test against less common servers 5) Continue to extend the smb3 "buildbot" which does automated xfstesting -against Windows, Samba and Azure currently - to add additional tests and -to allow the buildbot to execute the tests faster. The URL for the -buildbot is: http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com + against Windows, Samba and Azure currently - to add additional tests and + to allow the buildbot to execute the tests faster. The URL for the + buildbot is: http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com 6) Address various coverity warnings (most are not bugs per-se, but -the more warnings are addressed, the easier it is to spot real -problems that static analyzers will point out in the future). + the more warnings are addressed, the easier it is to spot real + problems that static analyzers will point out in the future). diff --git a/Documentation/filesystems/cifs/README b/Documentation/admin-guide/cifs/usage.rst similarity index 72% rename from Documentation/filesystems/cifs/README rename to Documentation/admin-guide/cifs/usage.rst index 4a804619cff2..d3fb67b8a976 100644 --- a/Documentation/filesystems/cifs/README +++ b/Documentation/admin-guide/cifs/usage.rst @@ -1,53 +1,61 @@ +===== +Usage +===== + This module supports the SMB3 family of advanced network protocols (as well as older dialects, originally called "CIFS" or SMB1). The CIFS VFS module for Linux supports many advanced network filesystem features such as hierarchical DFS like namespace, hardlinks, locking and more. -It was designed to comply with the SNIA CIFS Technical Reference (which -supersedes the 1992 X/Open SMB Standard) as well as to perform best practice -practical interoperability with Windows 2000, Windows XP, Samba and equivalent +It was designed to comply with the SNIA CIFS Technical Reference (which +supersedes the 1992 X/Open SMB Standard) as well as to perform best practice +practical interoperability with Windows 2000, Windows XP, Samba and equivalent servers. This code was developed in participation with the Protocol Freedom Information Foundation. CIFS and now SMB3 has now become a defacto standard for interoperating between Macs and Windows and major NAS appliances. Please see - MS-SMB2 (for detailed SMB2/SMB3/SMB3.1.1 protocol specification) - http://protocolfreedom.org/ and - http://samba.org/samba/PFIF/ +MS-SMB2 (for detailed SMB2/SMB3/SMB3.1.1 protocol specification) +http://protocolfreedom.org/ and +http://samba.org/samba/PFIF/ for more details. For questions or bug reports please contact: + smfrench@gmail.com See the project page at: https://wiki.samba.org/index.php/LinuxCIFS_utils -Build instructions: +Build instructions ================== + For Linux: + 1) Download the kernel (e.g. from http://www.kernel.org) -and change directory into the top of the kernel directory tree -(e.g. /usr/src/linux-2.5.73) + and change directory into the top of the kernel directory tree + (e.g. /usr/src/linux-2.5.73) 2) make menuconfig (or make xconfig) 3) select cifs from within the network filesystem choices 4) save and exit 5) make -Installation instructions: +Installation instructions ========================= + If you have built the CIFS vfs as module (successfully) simply -type "make modules_install" (or if you prefer, manually copy the file to +type ``make modules_install`` (or if you prefer, manually copy the file to the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko). If you have built the CIFS vfs into the kernel itself, follow the instructions for your distribution on how to install a new kernel (usually you -would simply type "make install"). +would simply type ``make install``). If you do not have the utility mount.cifs (in the Samba 4.x source tree and on the CIFS VFS web site) copy it to the same directory in which mount helpers reside (usually /sbin). Although the helper software is not -required, mount.cifs is recommended. Most distros include a "cifs-utils" +required, mount.cifs is recommended. Most distros include a ``cifs-utils`` package that includes this utility so it is recommended to install this. Note that running the Winbind pam/nss module (logon service) on all of your @@ -57,13 +65,16 @@ found at cifs-utils.git on git.samba.org If cifs is built as a module, then the size and number of network buffers and maximum number of simultaneous requests to one server can be configured. -Changing these from their defaults is not recommended. By executing modinfo +Changing these from their defaults is not recommended. By executing modinfo:: + modinfo kernel/fs/cifs/cifs.ko + on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made at module initialization time (by running insmod cifs.ko) can be seen. Recommendations =============== + To improve security the SMB2.1 dialect or later (usually will get SMB3) is now the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0" on mount (or vers=2.0 for Windows Vista). Note that the CIFS (vers=1.0) is @@ -72,156 +83,168 @@ many advanced security features such as downgrade attack detection and encrypted shares and stronger signing and authentication algorithms. There are additional mount options that may be helpful for SMB3 to get improved POSIX behavior (NB: can use vers=3.0 to force only SMB3, never 2.1): - "mfsymlinks" and "cifsacl" and "idsfromsid" + + ``mfsymlinks`` and ``cifsacl`` and ``idsfromsid`` Allowing User Mounts ==================== + To permit users to mount and unmount over directories they own is possible with the cifs vfs. A way to enable such mounting is to mark the mount.cifs -utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to +utility as suid (e.g. ``chmod +s /sbin/mount.cifs``). To enable users to umount shares they mount requires + 1) mount.cifs version 1.4 or later 2) an entry for the share in /etc/fstab indicating that a user may -unmount it e.g. -//server/usersharename /mnt/username cifs user 0 0 + unmount it e.g.:: + + //server/usersharename /mnt/username cifs user 0 0 -Note that when the mount.cifs utility is run suid (allowing user mounts), -in order to reduce risks, the "nosuid" mount flag is passed in on mount to +Note that when the mount.cifs utility is run suid (allowing user mounts), +in order to reduce risks, the ``nosuid`` mount flag is passed in on mount to disallow execution of an suid program mounted on the remote target. When mount is executed as root, nosuid is not passed in by default, and execution of suid programs on the remote target would be enabled -by default. This can be changed, as with nfs and other filesystems, -by simply specifying "nosuid" among the mount options. For user mounts -though to be able to pass the suid flag to mount requires rebuilding +by default. This can be changed, as with nfs and other filesystems, +by simply specifying ``nosuid`` among the mount options. For user mounts +though to be able to pass the suid flag to mount requires rebuilding mount.cifs with the following flag: CIFS_ALLOW_USR_SUID There is a corresponding manual page for cifs mounting in the Samba 3.0 and -later source tree in docs/manpages/mount.cifs.8 +later source tree in docs/manpages/mount.cifs.8 Allowing User Unmounts ====================== + To permit users to ummount directories that they have user mounted (see above), -the utility umount.cifs may be used. It may be invoked directly, or if +the utility umount.cifs may be used. It may be invoked directly, or if umount.cifs is placed in /sbin, umount can invoke the cifs umount helper (at least for most versions of the umount utility) for umount of cifs mounts, unless umount is invoked with -i (which will avoid invoking a umount helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked -as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions +as suid (e.g. ``chmod +s /sbin/umount.cifs``) or equivalent (some distributions allow adding entries to a file to the /etc/permissions file to achieve the equivalent suid effect). For this utility to succeed the target path must be a cifs mount, and the uid of the current user must match the uid of the user who mounted the resource. -Also note that the customary way of allowing user mounts and unmounts is +Also note that the customary way of allowing user mounts and unmounts is (instead of using mount.cifs and unmount.cifs as suid) to add a line to the file /etc/fstab for each //server/share you wish to mount, but this can become unwieldy when potential mount targets include many or unpredictable UNC names. -Samba Considerations +Samba Considerations ==================== + Most current servers support SMB2.1 and SMB3 which are more secure, but there are useful protocol extensions for the older less secure CIFS dialect, so to get the maximum benefit if mounting using the older dialect (CIFS/SMB1), we recommend using a server that supports the SNIA CIFS Unix Extensions standard (e.g. almost any version of Samba ie version 2.2.5 or later) but the CIFS vfs works fine with a wide variety of CIFS servers. -Note that uid, gid and file permissions will display default values if you do -not have a server that supports the Unix extensions for CIFS (such as Samba -2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add -the line: +Note that uid, gid and file permissions will display default values if you do +not have a server that supports the Unix extensions for CIFS (such as Samba +2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add +the line:: unix extensions = yes - -to your smb.conf file on the server. Note that the following smb.conf settings -are also useful (on the Samba server) when the majority of clients are Unix or -Linux: + +to your smb.conf file on the server. Note that the following smb.conf settings +are also useful (on the Samba server) when the majority of clients are Unix or +Linux:: case sensitive = yes - delete readonly = yes + delete readonly = yes ea support = yes Note that server ea support is required for supporting xattrs from the Linux -cifs client, and that EA support is present in later versions of Samba (e.g. +cifs client, and that EA support is present in later versions of Samba (e.g. 3.0.6 and later (also EA support works in all versions of Windows, at least to shares on NTFS filesystems). Extended Attribute (xattr) support is an optional feature of most Linux filesystems which may require enabling via make menuconfig. Client support for extended attributes (user xattr) can be -disabled on a per-mount basis by specifying "nouser_xattr" on mount. +disabled on a per-mount basis by specifying ``nouser_xattr`` on mount. The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers -version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and +version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and then POSIX support in the CIFS configuration options when building the cifs module. POSIX ACL support can be disabled on a per mount basic by specifying -"noacl" on mount. - -Some administrators may want to change Samba's smb.conf "map archive" and -"create mask" parameters from the default. Unless the create mask is changed +``noacl`` on mount. + +Some administrators may want to change Samba's smb.conf ``map archive`` and +``create mask`` parameters from the default. Unless the create mask is changed newly created files can end up with an unnecessarily restrictive default mode, which may not be what you want, although if the CIFS Unix extensions are enabled on the server and client, subsequent setattr calls (e.g. chmod) can -fix the mode. Note that creating special devices (mknod) remotely -may require specifying a mkdev function to Samba if you are not using +fix the mode. Note that creating special devices (mknod) remotely +may require specifying a mkdev function to Samba if you are not using Samba 3.0.6 or later. For more information on these see the manual pages -("man smb.conf") on the Samba server system. Note that the cifs vfs, -unlike the smbfs vfs, does not read the smb.conf on the client system -(the few optional settings are passed in on mount via -o parameters instead). +(``man smb.conf``) on the Samba server system. Note that the cifs vfs, +unlike the smbfs vfs, does not read the smb.conf on the client system +(the few optional settings are passed in on mount via -o parameters instead). Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete -open files (required for strict POSIX compliance). Windows Servers already +open files (required for strict POSIX compliance). Windows Servers already supported this feature. Samba server does not allow symlinks that refer to files outside of the share, so in Samba versions prior to 3.0.6, most symlinks to -files with absolute paths (ie beginning with slash) such as: +files with absolute paths (ie beginning with slash) such as:: + ln -s /mnt/foo bar -would be forbidden. Samba 3.0.6 server or later includes the ability to create -such symlinks safely by converting unsafe symlinks (ie symlinks to server + +would be forbidden. Samba 3.0.6 server or later includes the ability to create +such symlinks safely by converting unsafe symlinks (ie symlinks to server files that are outside of the share) to a samba specific format on the server that is ignored by local server applications and non-cifs clients and that will not be traversed by the Samba server). This is opaque to the Linux client application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or later, but only for remote clients using the CIFS Unix extensions, and will be invisbile to Windows clients and typically will not affect local -applications running on the same server as Samba. +applications running on the same server as Samba. -Use instructions: +Use instructions ================ -Once the CIFS VFS support is built into the kernel or installed as a module + +Once the CIFS VFS support is built into the kernel or installed as a module (cifs.ko), you can use mount syntax like the following to access Samba or -Mac or Windows servers: +Mac or Windows servers:: mount -t cifs //9.53.216.11/e$ /mnt -o username=myname,password=mypassword Before -o the option -v may be specified to make the mount.cifs -mount helper display the mount steps more verbosely. +mount helper display the mount steps more verbosely. After -o the following commonly used cifs vfs specific options -are supported: +are supported:: username= password= domain= - + Other cifs mount options are described below. Use of TCP names (in addition to ip addresses) is available if the mount helper (mount.cifs) is installed. If you do not trust the server to which are mounted, or if you do not have cifs signing enabled (and the physical network is insecure), consider use -of the standard mount options "noexec" and "nosuid" to reduce the risk of +of the standard mount options ``noexec`` and ``nosuid`` to reduce the risk of running an altered binary on your local system (downloaded from a hostile server or altered by a hostile router). Although mounting using format corresponding to the CIFS URL specification is not possible in mount.cifs yet, it is possible to use an alternate format for the server and sharename (which is somewhat similar to NFS style mount -syntax) instead of the more widely used UNC format (i.e. \\server\share): +syntax) instead of the more widely used UNC format (i.e. \\server\share):: + mount -t cifs tcp_name_of_server:share_name /mnt -o user=myname,pass=mypasswd When using the mount helper mount.cifs, passwords may be specified via alternate -mechanisms, instead of specifying it after -o using the normal "pass=" syntax +mechanisms, instead of specifying it after -o using the normal ``pass=`` syntax on the command line: 1) By including it in a credential file. Specify credentials=filename as one -of the mount options. Credential files contain two lines - username=someuser - password=your_password +of the mount options. Credential files contain two lines:: + + username=someuser + password=your_password + 2) By specifying the password in the PASSWD environment variable (similarly -the user name can be taken from the USER environment variable). + the user name can be taken from the USER environment variable). 3) By specifying the password in a file by name via PASSWD_FILE 4) By specifying the password in a file by file descriptor via PASSWD_FD @@ -229,39 +252,47 @@ If no password is provided, mount.cifs will prompt for password entry Restrictions ============ -Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC -1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a + +Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC +1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a problem as most servers support this. Valid filenames differ between Windows and Linux. Windows typically restricts -filenames which contain certain reserved characters (e.g.the character : +filenames which contain certain reserved characters (e.g.the character : which is used to delimit the beginning of a stream name by Windows), while Linux allows a slightly wider set of valid characters in filenames. Windows servers can remap such characters when an explicit mapping is specified in -the Server's registry. Samba starting with version 3.10 will allow such +the Server's registry. Samba starting with version 3.10 will allow such filenames (ie those which contain valid Linux characters, which normally would be forbidden for Windows/CIFS semantics) as long as the server is configured for Unix Extensions (and the client has not disabled /proc/fs/cifs/LinuxExtensionsEnabled). In addition the mount option -"mapposix" can be used on CIFS (vers=1.0) to force the mapping of +``mapposix`` can be used on CIFS (vers=1.0) to force the mapping of illegal Windows/NTFS/SMB characters to a remap range (this mount parm -is the default for SMB3). This remap ("mapposix") range is also +is the default for SMB3). This remap (``mapposix``) range is also compatible with Mac (and "Services for Mac" on some older Windows). CIFS VFS Mount Options ====================== A partial list of the supported mount options follows: - username The user name to use when trying to establish + + username + The user name to use when trying to establish the CIFS session. - password The user password. If the mount helper is + password + The user password. If the mount helper is installed, the user will be prompted for password if not supplied. - ip The ip address of the target server - unc The target server Universal Network Name (export) to - mount. - domain Set the SMB/CIFS workgroup name prepended to the + ip + The ip address of the target server + unc + The target server Universal Network Name (export) to + mount. + domain + Set the SMB/CIFS workgroup name prepended to the username during CIFS session establishment - forceuid Set the default uid for inodes to the uid + forceuid + Set the default uid for inodes to the uid passed in on mount. For mounts to servers which do support the CIFS Unix extensions, such as a properly configured Samba server, the server provides @@ -276,32 +307,39 @@ A partial list of the supported mount options follows: extensions, the default uid (and gid) returned on lookup of existing files will be the uid (gid) of the person who executed the mount (root, except when mount.cifs - is configured setuid for user mounts) unless the "uid=" + is configured setuid for user mounts) unless the ``uid=`` (gid) mount option is specified. Also note that permission checks (authorization checks) on accesses to a file occur at the server, but there are cases in which an administrator may want to restrict at the client as well. For those servers which do not report a uid/gid owner (such as Windows), permissions can also be checked at the - client, and a crude form of client side permission checking - can be enabled by specifying file_mode and dir_mode on + client, and a crude form of client side permission checking + can be enabled by specifying file_mode and dir_mode on the client. (default) - forcegid (similar to above but for the groupid instead of uid) (default) - noforceuid Fill in file owner information (uid) by requesting it from + forcegid + (similar to above but for the groupid instead of uid) (default) + noforceuid + Fill in file owner information (uid) by requesting it from the server if possible. With this option, the value given in the uid= option (on mount) will only be used if the server can not support returning uids on inodes. - noforcegid (similar to above but for the group owner, gid, instead of uid) - uid Set the default uid for inodes, and indicate to the + noforcegid + (similar to above but for the group owner, gid, instead of uid) + uid + Set the default uid for inodes, and indicate to the cifs kernel driver which local user mounted. If the server supports the unix extensions the default uid is not used to fill in the owner fields of inodes (files) - unless the "forceuid" parameter is specified. - gid Set the default gid for inodes (similar to above). - file_mode If CIFS Unix extensions are not supported by the server + unless the ``forceuid`` parameter is specified. + gid + Set the default gid for inodes (similar to above). + file_mode + If CIFS Unix extensions are not supported by the server this overrides the default mode for file inodes. - fsc Enable local disk caching using FS-Cache (off by default). This - option could be useful to improve performance on a slow link, + fsc + Enable local disk caching using FS-Cache (off by default). This + option could be useful to improve performance on a slow link, heavily loaded server and/or network where reading from the disk is faster than reading from the server (over the network). This could also impact scalability positively as the @@ -310,18 +348,22 @@ A partial list of the supported mount options follows: type workloads. So, you need to consider carefully your workload/scenario before using this option. Currently, local disk caching is functional for CIFS files opened as read-only. - dir_mode If CIFS Unix extensions are not supported by the server + dir_mode + If CIFS Unix extensions are not supported by the server this overrides the default mode for directory inodes. - port attempt to contact the server on this tcp port, before + port + attempt to contact the server on this tcp port, before trying the usual ports (port 445, then 139). - iocharset Codepage used to convert local path names to and from + iocharset + Codepage used to convert local path names to and from Unicode. Unicode is used by default for network path names if the server supports it. If iocharset is not specified then the nls_default specified during the local client kernel build will be used. If server does not support Unicode, this parameter is unused. - rsize default read size (usually 16K). The client currently + rsize + default read size (usually 16K). The client currently can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize defaults to 16K and may be changed (from 8K to the maximum kmalloc size allowed by your kernel) at module install time @@ -333,10 +375,12 @@ A partial list of the supported mount options follows: newer servers (e.g. Samba 3.0.26 or later) do. rsize can be set from a minimum of 2048 to a maximum of 130048 (127K or CIFSMaxBufSize, whichever is smaller) - wsize default write size (default 57344) + wsize + default write size (default 57344) maximum wsize currently allowed by CIFS is 57344 (fourteen 4096 byte pages) - actimeo=n attribute cache timeout in seconds (default 1 second). + actimeo=n + attribute cache timeout in seconds (default 1 second). After this timeout, the cifs client requests fresh attribute information from the server. This option allows to tune the attribute cache timeout to suit the workload needs. Shorter @@ -345,49 +389,67 @@ A partial list of the supported mount options follows: of calls to the server at the expense of less stricter cache coherency checks (i.e. incorrect attribute cache for a short period of time). - rw mount the network share read-write (note that the + rw + mount the network share read-write (note that the server may still consider the share read-only) - ro mount network share read-only - version used to distinguish different versions of the + ro + mount network share read-only + version + used to distinguish different versions of the mount helper utility (not typically needed) - sep if first mount option (after the -o), overrides + sep + if first mount option (after the -o), overrides the comma as the separator between the mount - parms. e.g. + parms. e.g.:: + -o user=myname,password=mypassword,domain=mydom - could be passed instead with period as the separator by + + could be passed instead with period as the separator by:: + -o sep=.user=myname.password=mypassword.domain=mydom + this might be useful when comma is contained within username or password or domain. This option is less important when the cifs mount helper cifs.mount (version 1.1 or later) is used. - nosuid Do not allow remote executables with the suid bit + nosuid + Do not allow remote executables with the suid bit program to be executed. This is only meaningful for mounts to servers such as Samba which support the CIFS Unix Extensions. If you do not trust the servers in your network (your mount targets) it is recommended that you specify this option for greater security. - exec Permit execution of binaries on the mount. - noexec Do not permit execution of binaries on the mount. - dev Recognize block devices on the remote mount. - nodev Do not recognize devices on the remote mount. - suid Allow remote files on this mountpoint with suid enabled to + exec + Permit execution of binaries on the mount. + noexec + Do not permit execution of binaries on the mount. + dev + Recognize block devices on the remote mount. + nodev + Do not recognize devices on the remote mount. + suid + Allow remote files on this mountpoint with suid enabled to be executed (default for mounts when executed as root, nosuid is default for user mounts). - credentials Although ignored by the cifs kernel component, it is used by + credentials + Although ignored by the cifs kernel component, it is used by the mount helper, mount.cifs. When mount.cifs is installed it - opens and reads the credential file specified in order + opens and reads the credential file specified in order to obtain the userid and password arguments which are passed to the cifs vfs. - guest Although ignored by the kernel component, the mount.cifs + guest + Although ignored by the kernel component, the mount.cifs mount helper will not prompt the user for a password if guest is specified on the mount options. If no password is specified a null password will be used. - perm Client does permission checks (vfs_permission check of uid + perm + Client does permission checks (vfs_permission check of uid and gid of the file against the mode and desired operation), Note that this is in addition to the normal ACL check on the - target machine done by the server software. + target machine done by the server software. Client permission checking is enabled by default. - noperm Client does not do permission checks. This can expose + noperm + Client does not do permission checks. This can expose files on this mount to access by other users on the local client system. It is typically only needed when the server supports the CIFS Unix Extensions but the UIDs/GIDs on the @@ -399,7 +461,8 @@ A partial list of the supported mount options follows: Note that this does not affect the normal ACL check on the target machine done by the server software (of the server ACL against the user name provided at mount time). - serverino Use server's inode numbers instead of generating automatically + serverino + Use server's inode numbers instead of generating automatically incrementing inode numbers on the client. Although this will make it easier to spot hardlinked files (as they will have the same inode numbers) and inode numbers may be persistent, @@ -412,14 +475,16 @@ A partial list of the supported mount options follows: or the CIFS Unix Extensions equivalent and for those this mount option will have no effect. Exporting cifs mounts under nfsd requires this mount option on the cifs mount. - This is now the default if server supports the + This is now the default if server supports the required network operation. - noserverino Client generates inode numbers (rather than using the actual one + noserverino + Client generates inode numbers (rather than using the actual one from the server). These inode numbers will vary after unmount or reboot which can confuse some applications, but not all server filesystems support unique inode numbers. - setuids If the CIFS Unix extensions are negotiated with the server + setuids + If the CIFS Unix extensions are negotiated with the server the client will attempt to set the effective uid and gid of the local process on newly created files, directories, and devices (create, mkdir, mknod). If the CIFS Unix Extensions @@ -427,9 +492,10 @@ A partial list of the supported mount options follows: instead of using the default uid and gid specified on the mount, cache the new file's uid and gid locally which means that the uid for the file can change when the inode is - reloaded (or the user remounts the share). - nosetuids The client will not attempt to set the uid and gid on - on newly created files, directories, and devices (create, + reloaded (or the user remounts the share). + nosetuids + The client will not attempt to set the uid and gid on + on newly created files, directories, and devices (create, mkdir, mknod) which will result in the server setting the uid and gid to the default (usually the server uid of the user who mounted the share). Letting the server (rather than @@ -437,38 +503,49 @@ A partial list of the supported mount options follows: Unix Extensions are not negotiated then the uid and gid for new files will appear to be the uid (gid) of the mounter or the uid (gid) parameter specified on the mount. - netbiosname When mounting to servers via port 139, specifies the RFC1001 - source name to use to represent the client netbios machine + netbiosname + When mounting to servers via port 139, specifies the RFC1001 + source name to use to represent the client netbios machine name when doing the RFC1001 netbios session initialize. - direct Do not do inode data caching on files opened on this mount. + direct + Do not do inode data caching on files opened on this mount. This precludes mmapping files on this mount. In some cases with fast networks and little or no caching benefits on the client (e.g. when the application is doing large sequential - reads bigger than page size without rereading the same data) + reads bigger than page size without rereading the same data) this can provide better performance than the default - behavior which caches reads (readahead) and writes - (writebehind) through the local Linux client pagecache + behavior which caches reads (readahead) and writes + (writebehind) through the local Linux client pagecache if oplock (caching token) is granted and held. Note that direct allows write operations larger than page size to be sent to the server. - strictcache Use for switching on strict cache mode. In this mode the + strictcache + Use for switching on strict cache mode. In this mode the client read from the cache all the time it has Oplock Level II, otherwise - read from the server. All written data are stored in the cache, but if the client doesn't have Exclusive Oplock, it writes the data to the server. - rwpidforward Forward pid of a process who opened a file to any read or write + rwpidforward + Forward pid of a process who opened a file to any read or write operation on that file. This prevent applications like WINE from failing on read and write if we use mandatory brlock style. - acl Allow setfacl and getfacl to manage posix ACLs if server + acl + Allow setfacl and getfacl to manage posix ACLs if server supports them. (default) - noacl Do not allow setfacl and getfacl calls on this mount - user_xattr Allow getting and setting user xattrs (those attributes whose - name begins with "user." or "os2.") as OS/2 EAs (extended + noacl + Do not allow setfacl and getfacl calls on this mount + user_xattr + Allow getting and setting user xattrs (those attributes whose + name begins with ``user.`` or ``os2.``) as OS/2 EAs (extended attributes) to the server. This allows support of the setfattr and getfattr utilities. (default) - nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs - mapchars Translate six of the seven reserved characters (not backslash) + nouser_xattr + Do not allow getfattr/setfattr to get/set/list xattrs + mapchars + Translate six of the seven reserved characters (not backslash):: + *?<>|: + to the remap range (above 0xF000), which also allows the CIFS client to recognize files created with such characters by Windows's POSIX emulation. This can @@ -477,39 +554,47 @@ A partial list of the supported mount options follows: whose names contain any of these seven characters). This has no effect if the server does not support Unicode on the wire. - nomapchars Do not translate any of these seven characters (default). - nocase Request case insensitive path name matching (case + nomapchars + Do not translate any of these seven characters (default). + nocase + Request case insensitive path name matching (case sensitive is the default if the server supports it). - (mount option "ignorecase" is identical to "nocase") - posixpaths If CIFS Unix extensions are supported, attempt to + (mount option ``ignorecase`` is identical to ``nocase``) + posixpaths + If CIFS Unix extensions are supported, attempt to negotiate posix path name support which allows certain characters forbidden in typical CIFS filenames, without requiring remapping. (default) - noposixpaths If CIFS Unix extensions are supported, do not request + noposixpaths + If CIFS Unix extensions are supported, do not request posix path name support (this may cause servers to reject creatingfile with certain reserved characters). - nounix Disable the CIFS Unix Extensions for this mount (tree + nounix + Disable the CIFS Unix Extensions for this mount (tree connection). This is rarely needed, but it may be useful in order to turn off multiple settings all at once (ie posix acls, posix locks, posix paths, symlink support and retrieving uids/gids/mode from the server) or to work around a bug in server which implement the Unix Extensions. - nobrl Do not send byte range lock requests to the server. + nobrl + Do not send byte range lock requests to the server. This is necessary for certain applications that break with cifs style mandatory byte range locks (and most cifs servers do not yet support requesting advisory byte range locks). - forcemandatorylock Even if the server supports posix (advisory) byte range + forcemandatorylock + Even if the server supports posix (advisory) byte range locking, send only mandatory lock requests. For some (presumably rare) applications, originally coded for DOS/Windows, which require Windows style mandatory byte range locking, they may be able to take advantage of this option, forcing the cifs client to only send mandatory locks even if the cifs server would support posix advisory locks. - "forcemand" is accepted as a shorter form of this mount + ``forcemand`` is accepted as a shorter form of this mount option. - nostrictsync If this mount option is set, when an application does an + nostrictsync + If this mount option is set, when an application does an fsync call then the cifs client does not send an SMB Flush to the server (to force the server to write all dirty data for this file immediately to disk), although cifs still sends @@ -522,41 +607,50 @@ A partial list of the supported mount options follows: crash. If this mount option is not set, by default cifs will send an SMB flush request (and wait for a response) on every fsync call. - nodfs Disable DFS (global name space support) even if the + nodfs + Disable DFS (global name space support) even if the server claims to support it. This can help work around a problem with parsing of DFS paths with Samba server versions 3.0.24 and 3.0.25. - remount remount the share (often used to change from ro to rw mounts - or vice versa) - cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for - the file. (EXPERIMENTAL) - servern Specify the server 's netbios name (RFC1001 name) to use - when attempting to setup a session to the server. + remount + remount the share (often used to change from ro to rw mounts + or vice versa) + cifsacl + Report mode bits (e.g. on stat) based on the Windows ACL for + the file. (EXPERIMENTAL) + servern + Specify the server 's netbios name (RFC1001 name) to use + when attempting to setup a session to the server. This is needed for mounting to some older servers (such as OS/2 or Windows 98 and Windows ME) since they do not support a default server name. A server name can be up to 15 characters long and is usually uppercased. - sfu When the CIFS Unix Extensions are not negotiated, attempt to + sfu + When the CIFS Unix Extensions are not negotiated, attempt to create device files and fifos in a format compatible with Services for Unix (SFU). In addition retrieve bits 10-12 of the mode via the SETFILEBITS extended attribute (as SFU does). In the future the bottom 9 bits of the mode also will be emulated using queries of the security descriptor (ACL). - mfsymlinks Enable support for Minshall+French symlinks + mfsymlinks + Enable support for Minshall+French symlinks (see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks) This option is ignored when specified together with the 'sfu' option. Minshall+French symlinks are used even if the server supports the CIFS Unix Extensions. - sign Must use packet signing (helps avoid unwanted data modification + sign + Must use packet signing (helps avoid unwanted data modification by intermediate systems in the route). Note that signing does not work with lanman or plaintext authentication. - seal Must seal (encrypt) all data on this mounted share before + seal + Must seal (encrypt) all data on this mounted share before sending on the network. Requires support for Unix Extensions. Note that this differs from the sign mount option in that it causes encryption of data sent over this mounted share but other shares mounted to the same server are unaffected. - locallease This option is rarely needed. Fcntl F_SETLEASE is + locallease + This option is rarely needed. Fcntl F_SETLEASE is used by some applications such as Samba and NFSv4 server to check to see whether a file is cacheable. CIFS has no way to explicitly request a lease, but can check whether a file @@ -569,51 +663,73 @@ A partial list of the supported mount options follows: will allow the cifs client to check for leases (only) locally for files which are not oplocked instead of denying leases in that case. (EXPERIMENTAL) - sec Security mode. Allowed values are: - none attempt to connection as a null user (no name) - krb5 Use Kerberos version 5 authentication - krb5i Use Kerberos authentication and packet signing - ntlm Use NTLM password hashing (default) - ntlmi Use NTLM password hashing with signing (if + sec + Security mode. Allowed values are: + + none + attempt to connection as a null user (no name) + krb5 + Use Kerberos version 5 authentication + krb5i + Use Kerberos authentication and packet signing + ntlm + Use NTLM password hashing (default) + ntlmi + Use NTLM password hashing with signing (if /proc/fs/cifs/PacketSigningEnabled on or if - server requires signing also can be the default) - ntlmv2 Use NTLMv2 password hashing - ntlmv2i Use NTLMv2 password hashing with packet signing - lanman (if configured in kernel config) use older + server requires signing also can be the default) + ntlmv2 + Use NTLMv2 password hashing + ntlmv2i + Use NTLMv2 password hashing with packet signing + lanman + (if configured in kernel config) use older lanman hash -hard Retry file operations if server is not responding -soft Limit retries to unresponsive servers (usually only + hard + Retry file operations if server is not responding + soft + Limit retries to unresponsive servers (usually only one retry) before returning an error. (default) The mount.cifs mount helper also accepts a few mount options before -o including: +=============== =============================================================== -S take password from stdin (equivalent to setting the environment - variable "PASSWD_FD=0" + variable ``PASSWD_FD=0`` -V print mount.cifs version -? display simple usage information +=============== =============================================================== With most 2.6 kernel versions of modutils, the version of the cifs kernel module can be displayed via modinfo. Misc /proc/fs/cifs Flags and Debug Info ======================================= + Informational pseudo-files: + +======================= ======================================================= DebugData Displays information about active CIFS sessions and shares, features enabled as well as the cifs.ko version. Stats Lists summary resource usage information as well as per share statistics. +======================= ======================================================= Configuration pseudo-files: + +======================= ======================================================= SecurityFlags Flags which control security negotiation and also packet signing. Authentication (may/must) flags (e.g. for NTLM and/or NTLMv2) may be combined with the signing flags. Specifying two different password - hashing mechanisms (as "must use") on the other hand - does not make much sense. Default flags are - 0x07007 - (NTLM, NTLMv2 and packet signing allowed). The maximum + hashing mechanisms (as "must use") on the other hand + does not make much sense. Default flags are:: + + 0x07007 + + (NTLM, NTLMv2 and packet signing allowed). The maximum allowable flags if you want to allow mounts to servers using weaker password hashes is 0x37037 (lanman, plaintext, ntlm, ntlmv2, signing allowed). Some @@ -626,21 +742,21 @@ SecurityFlags Flags which control security negotiation and laintext passwords using the older lanman dialect form of the session setup SMB. (e.g. for authentication using plain text passwords, set the SecurityFlags - to 0x30030): - - may use packet signing 0x00001 - must use packet signing 0x01001 - may use NTLM (most common password hash) 0x00002 - must use NTLM 0x02002 - may use NTLMv2 0x00004 - must use NTLMv2 0x04004 - may use Kerberos security 0x00008 - must use Kerberos 0x08008 - may use lanman (weak) password hash 0x00010 - must use lanman password hash 0x10010 - may use plaintext passwords 0x00020 - must use plaintext passwords 0x20020 - (reserved for future packet encryption) 0x00040 + to 0x30030):: + + may use packet signing 0x00001 + must use packet signing 0x01001 + may use NTLM (most common password hash) 0x00002 + must use NTLM 0x02002 + may use NTLMv2 0x00004 + must use NTLMv2 0x04004 + may use Kerberos security 0x00008 + must use Kerberos 0x08008 + may use lanman (weak) password hash 0x00010 + must use lanman password hash 0x10010 + may use plaintext passwords 0x00020 + must use plaintext passwords 0x20020 + (reserved for future packet encryption) 0x00040 cifsFYI If set to non-zero value, additional debug information will be logged to the system error log. This field @@ -650,14 +766,19 @@ cifsFYI If set to non-zero value, additional debug information Some debugging statements are not compiled into the cifs kernel unless CONFIG_CIFS_DEBUG2 is enabled in the kernel configuration. cifsFYI may be set to one or - nore of the following flags (7 sets them all): - - log cifs informational messages 0x01 - log return codes from cifs entry points 0x02 - log slow responses (ie which take longer than 1 second) - CONFIG_CIFS_STATS2 must be enabled in .config 0x04 - - + nore of the following flags (7 sets them all):: + + +-----------------------------------------------+------+ + | log cifs informational messages | 0x01 | + +-----------------------------------------------+------+ + | log return codes from cifs entry points | 0x02 | + +-----------------------------------------------+------+ + | log slow responses | 0x04 | + | (ie which take longer than 1 second) | | + | | | + | CONFIG_CIFS_STATS2 must be enabled in .config | | + +-----------------------------------------------+------+ + traceSMB If set to one, debug information is logged to the system error log with the start of smb requests and responses (default 0) @@ -671,24 +792,25 @@ LinuxExtensionsEnabled If set to one then the client will attempt to as support symbolic links. If you use servers such as Samba that support the CIFS Unix extensions but do not want to use symbolic link - support and want to map the uid and gid fields - to values supplied at mount (rather than the + support and want to map the uid and gid fields + to values supplied at mount (rather than the actual values, then set this to zero. (default 1) +======================= ======================================================= -These experimental features and tracing can be enabled by changing flags in -/proc/fs/cifs (after the cifs module has been installed or built into the -kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable -tracing to the kernel message log type: +These experimental features and tracing can be enabled by changing flags in +/proc/fs/cifs (after the cifs module has been installed or built into the +kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable +tracing to the kernel message log type:: echo 7 > /proc/fs/cifs/cifsFYI - + cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel logging of various informational messages. 2 enables logging of non-zero SMB return codes while 4 enables logging of requests that take longer -than one second to complete (except for byte range lock requests). +than one second to complete (except for byte range lock requests). Setting it to 4 requires CONFIG_CIFS_STATS2 to be set in kernel configuration (.config). Setting it to seven enables all three. Finally, tracing -the start of smb requests and responses can be enabled via: +the start of smb requests and responses can be enabled via:: echo 1 > /proc/fs/cifs/traceSMB @@ -700,10 +822,10 @@ server) SMB3 (or cifs) requests grouped by request type (read, write, close etc. Also recorded is the total bytes read and bytes written to the server for that share. Note that due to client caching effects this can be less than the number of bytes read and written by the application running on the client. -Statistics can be reset to zero by "echo 0 > /proc/fs/cifs/Stats" which may be +Statistics can be reset to zero by ``echo 0 > /proc/fs/cifs/Stats`` which may be useful if comparing performance of two different scenarios. - -Also note that "cat /proc/fs/cifs/DebugData" will display information about + +Also note that ``cat /proc/fs/cifs/DebugData`` will display information about the active sessions and the shares that are mounted. Enabling Kerberos (extended security) works but requires version 1.2 or later @@ -725,19 +847,23 @@ space to ease network configuration and improve reliability. To use cifs Kerberos and DFS support, the Linux keyutils package should be installed and something like the following lines should be added to the -/etc/request-key.conf file: +/etc/request-key.conf file:: -create cifs.spnego * * /usr/local/sbin/cifs.upcall %k -create dns_resolver * * /usr/local/sbin/cifs.upcall %k + create cifs.spnego * * /usr/local/sbin/cifs.upcall %k + create dns_resolver * * /usr/local/sbin/cifs.upcall %k CIFS kernel module parameters ============================= These module parameters can be specified or modified either during the time of -module loading or during the runtime by using the interface +module loading or during the runtime by using the interface:: + /proc/module/cifs/parameters/ -i.e. echo "value" > /sys/module/cifs/parameters/ +i.e.:: -1. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default. - [Y/y/1]. To disable use any of [N/n/0]. + echo "value" > /sys/module/cifs/parameters/ +================= ========================================================== +1. enable_oplocks Enable or disable oplocks. Oplocks are enabled by default. + [Y/y/1]. To disable use any of [N/n/0]. +================= ========================================================== diff --git a/Documentation/filesystems/cifs/winucase_convert.pl b/Documentation/admin-guide/cifs/winucase_convert.pl similarity index 100% rename from Documentation/filesystems/cifs/winucase_convert.pl rename to Documentation/admin-guide/cifs/winucase_convert.pl diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index 534373816d7f..34cc20ee7f3a 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -77,6 +77,7 @@ configure specific aspects of kernel behavior to your liking. blockdev/index ext4 binderfs + cifs/index xfs jfs ufs diff --git a/MAINTAINERS b/MAINTAINERS index f109a8bcffda..0abd3b598a1e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4099,7 +4099,7 @@ L: samba-technical@lists.samba.org (moderated for non-subscribers) W: http://linux-cifs.samba.org/ T: git git://git.samba.org/sfrench/cifs-2.6.git S: Supported -F: Documentation/filesystems/cifs/ +F: Documentation/admin-guide/cifs/ F: fs/cifs/ COMPACTPCI HOTPLUG CORE -- GitLab From e9bb627561535dd584b43a8c0afe93a67bc6a2c5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:08:53 -0300 Subject: [PATCH 1475/7155] docs: w1: convert to ReST and add to the kAPI group of docs The 1wire documentation was written with w1 developers in mind, so, it makes sense to add it together with the driver-api set. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/ABI/stable/sysfs-bus-w1 | 2 +- .../ABI/stable/sysfs-driver-w1_ds28e04 | 4 +- .../ABI/stable/sysfs-driver-w1_ds28ea00 | 2 +- Documentation/index.rst | 1 + Documentation/w1/index.rst | 21 +++++ .../w1/masters/{ds2482 => ds2482.rst} | 16 +++- .../w1/masters/{ds2490 => ds2490.rst} | 6 +- Documentation/w1/masters/index.rst | 14 +++ Documentation/w1/masters/mxc-w1 | 12 --- Documentation/w1/masters/mxc-w1.rst | 17 ++++ .../w1/masters/{omap-hdq => omap-hdq.rst} | 12 +-- .../w1/masters/{w1-gpio => w1-gpio.rst} | 21 +++-- Documentation/w1/slaves/index.rst | 16 ++++ .../w1/slaves/{w1_ds2406 => w1_ds2406.rst} | 4 +- .../w1/slaves/{w1_ds2413 => w1_ds2413.rst} | 9 ++ Documentation/w1/slaves/w1_ds2423 | 47 ---------- Documentation/w1/slaves/w1_ds2423.rst | 54 +++++++++++ .../w1/slaves/{w1_ds2438 => w1_ds2438.rst} | 10 ++- .../w1/slaves/{w1_ds28e04 => w1_ds28e04.rst} | 5 ++ .../w1/slaves/{w1_ds28e17 => w1_ds28e17.rst} | 16 ++-- .../w1/slaves/{w1_therm => w1_therm.rst} | 11 ++- .../w1/{w1.generic => w1-generic.rst} | 88 ++++++++++-------- .../w1/{w1.netlink => w1-netlink.rst} | 89 +++++++++++-------- 23 files changed, 308 insertions(+), 169 deletions(-) create mode 100644 Documentation/w1/index.rst rename Documentation/w1/masters/{ds2482 => ds2482.rst} (71%) rename Documentation/w1/masters/{ds2490 => ds2490.rst} (98%) create mode 100644 Documentation/w1/masters/index.rst delete mode 100644 Documentation/w1/masters/mxc-w1 create mode 100644 Documentation/w1/masters/mxc-w1.rst rename Documentation/w1/masters/{omap-hdq => omap-hdq.rst} (90%) rename Documentation/w1/masters/{w1-gpio => w1-gpio.rst} (75%) create mode 100644 Documentation/w1/slaves/index.rst rename Documentation/w1/slaves/{w1_ds2406 => w1_ds2406.rst} (96%) rename Documentation/w1/slaves/{w1_ds2413 => w1_ds2413.rst} (81%) delete mode 100644 Documentation/w1/slaves/w1_ds2423 create mode 100644 Documentation/w1/slaves/w1_ds2423.rst rename Documentation/w1/slaves/{w1_ds2438 => w1_ds2438.rst} (93%) rename Documentation/w1/slaves/{w1_ds28e04 => w1_ds28e04.rst} (93%) rename Documentation/w1/slaves/{w1_ds28e17 => w1_ds28e17.rst} (88%) rename Documentation/w1/slaves/{w1_therm => w1_therm.rst} (95%) rename Documentation/w1/{w1.generic => w1-generic.rst} (59%) rename Documentation/w1/{w1.netlink => w1-netlink.rst} (77%) diff --git a/Documentation/ABI/stable/sysfs-bus-w1 b/Documentation/ABI/stable/sysfs-bus-w1 index 140d85b4ae92..992dfb183ed0 100644 --- a/Documentation/ABI/stable/sysfs-bus-w1 +++ b/Documentation/ABI/stable/sysfs-bus-w1 @@ -6,6 +6,6 @@ Description: Bus scanning interval, microseconds component. control systems are attached/generate presence for as short as 100 ms - hence the tens-to-hundreds milliseconds scan intervals are required. - see Documentation/w1/w1.generic for detailed information. + see Documentation/w1/w1-generic.rst for detailed information. Users: any user space application which wants to know bus scanning interval diff --git a/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 index 26579ee868c9..3e1c1fa8d54d 100644 --- a/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 +++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 @@ -2,7 +2,7 @@ What: /sys/bus/w1/devices/.../pio Date: May 2012 Contact: Markus Franke Description: read/write the contents of the two PIO's of the DS28E04-100 - see Documentation/w1/slaves/w1_ds28e04 for detailed information + see Documentation/w1/slaves/w1_ds28e04.rst for detailed information Users: any user space application which wants to communicate with DS28E04-100 @@ -11,5 +11,5 @@ What: /sys/bus/w1/devices/.../eeprom Date: May 2012 Contact: Markus Franke Description: read/write the contents of the EEPROM memory of the DS28E04-100 - see Documentation/w1/slaves/w1_ds28e04 for detailed information + see Documentation/w1/slaves/w1_ds28e04.rst for detailed information Users: any user space application which wants to communicate with DS28E04-100 diff --git a/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 b/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 index e928def14f28..534e63731a49 100644 --- a/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 +++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 @@ -2,5 +2,5 @@ What: /sys/bus/w1/devices/.../w1_seq Date: Apr 2015 Contact: Matt Campbell Description: Support for the DS28EA00 chain sequence function - see Documentation/w1/slaves/w1_therm for detailed information + see Documentation/w1/slaves/w1_therm.rst for detailed information Users: any user space application which wants to communicate with DS28EA00 diff --git a/Documentation/index.rst b/Documentation/index.rst index 472b8abe52e9..0a564f3c336e 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -117,6 +117,7 @@ needed). target/index timers/index spi/index + w1/index watchdog/index virtual/index input/index diff --git a/Documentation/w1/index.rst b/Documentation/w1/index.rst new file mode 100644 index 000000000000..57cba81865e2 --- /dev/null +++ b/Documentation/w1/index.rst @@ -0,0 +1,21 @@ +. SPDX-License-Identifier: GPL-2.0 + +================ +1-Wire Subsystem +================ + +.. toctree:: + :maxdepth: 1 + + + w1-generic.rst + w1-netlink.rst + masters/index + slaves/index + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/w1/masters/ds2482 b/Documentation/w1/masters/ds2482.rst similarity index 71% rename from Documentation/w1/masters/ds2482 rename to Documentation/w1/masters/ds2482.rst index 56f8edace6ac..17ebe8f660cd 100644 --- a/Documentation/w1/masters/ds2482 +++ b/Documentation/w1/masters/ds2482.rst @@ -1,13 +1,19 @@ +==================== Kernel driver ds2482 ==================== Supported chips: + * Maxim DS2482-100, Maxim DS2482-800 + Prefix: 'ds2482' + Addresses scanned: None + Datasheets: - http://datasheets.maxim-ic.com/en/ds/DS2482-100.pdf - http://datasheets.maxim-ic.com/en/ds/DS2482-800.pdf + + - http://datasheets.maxim-ic.com/en/ds/DS2482-100.pdf + - http://datasheets.maxim-ic.com/en/ds/DS2482-800.pdf Author: Ben Gardner @@ -23,9 +29,11 @@ General Remarks --------------- Valid addresses are 0x18, 0x19, 0x1a, and 0x1b. + However, the device cannot be detected without writing to the i2c bus, so no detection is done. You should instantiate the device explicitly. -$ modprobe ds2482 -$ echo ds2482 0x18 > /sys/bus/i2c/devices/i2c-0/new_device +:: + $ modprobe ds2482 + $ echo ds2482 0x18 > /sys/bus/i2c/devices/i2c-0/new_device diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490.rst similarity index 98% rename from Documentation/w1/masters/ds2490 rename to Documentation/w1/masters/ds2490.rst index 3e091151dd80..7e5b50f9c0f5 100644 --- a/Documentation/w1/masters/ds2490 +++ b/Documentation/w1/masters/ds2490.rst @@ -1,7 +1,9 @@ +==================== Kernel driver ds2490 ==================== Supported chips: + * Maxim DS2490 based Author: Evgeniy Polyakov @@ -18,6 +20,7 @@ which has 0x81 family ID integrated chip and DS2490 low-level operational chip. Notes and limitations. + - The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA. - The 5V strong pullup is supported with a minimum of 5.9mA and a maximum of 30.4 mA. (From DS2490.pdf) @@ -65,4 +68,5 @@ Notes and limitations. reattaching would clear the problem. usbmon output in the guest and host did not explain the problem. My guess is a bug in either qemu or the host OS and more likely the host OS. --- 03-06-2008 David Fries + +03-06-2008 David Fries diff --git a/Documentation/w1/masters/index.rst b/Documentation/w1/masters/index.rst new file mode 100644 index 000000000000..4442a98850ad --- /dev/null +++ b/Documentation/w1/masters/index.rst @@ -0,0 +1,14 @@ +. SPDX-License-Identifier: GPL-2.0 + +===================== +1-wire Master Drivers +===================== + +.. toctree:: + :maxdepth: 1 + + ds2482 + ds2490 + mxc-w1 + omap-hdq + w1-gpio diff --git a/Documentation/w1/masters/mxc-w1 b/Documentation/w1/masters/mxc-w1 deleted file mode 100644 index 38be1ad65532..000000000000 --- a/Documentation/w1/masters/mxc-w1 +++ /dev/null @@ -1,12 +0,0 @@ -Kernel driver mxc_w1 -==================== - -Supported chips: - * Freescale MX27, MX31 and probably other i.MX SoCs - Datasheets: - http://www.freescale.com/files/32bit/doc/data_sheet/MCIMX31.pdf?fpsp=1 - http://cache.freescale.com/files/dsp/doc/archive/MCIMX27.pdf?fsrch=1&WT_TYPE= - Data%20Sheets&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation - -Author: Originally based on Freescale code, prepared for mainline by - Sascha Hauer diff --git a/Documentation/w1/masters/mxc-w1.rst b/Documentation/w1/masters/mxc-w1.rst new file mode 100644 index 000000000000..334f9893103f --- /dev/null +++ b/Documentation/w1/masters/mxc-w1.rst @@ -0,0 +1,17 @@ +==================== +Kernel driver mxc_w1 +==================== + +Supported chips: + + * Freescale MX27, MX31 and probably other i.MX SoCs + + Datasheets: + + - http://www.freescale.com/files/32bit/doc/data_sheet/MCIMX31.pdf?fpsp=1 + - http://cache.freescale.com/files/dsp/doc/archive/MCIMX27.pdf?fsrch=1&WT_TYPE=Data%20Sheets&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation + +Author: + + Originally based on Freescale code, prepared for mainline by + Sascha Hauer diff --git a/Documentation/w1/masters/omap-hdq b/Documentation/w1/masters/omap-hdq.rst similarity index 90% rename from Documentation/w1/masters/omap-hdq rename to Documentation/w1/masters/omap-hdq.rst index 234522709a5f..345298a59e50 100644 --- a/Documentation/w1/masters/omap-hdq +++ b/Documentation/w1/masters/omap-hdq.rst @@ -1,9 +1,10 @@ -Kernel driver for omap HDQ/1-wire module. +======================================== +Kernel driver for omap HDQ/1-wire module ======================================== Supported chips: ================ - HDQ/1-wire controller on the TI OMAP 2430/3430 platforms. +HDQ/1-wire controller on the TI OMAP 2430/3430 platforms. A useful link about HDQ basics: =============================== @@ -40,9 +41,10 @@ driver(drivers/w1/slaves/w1_bq27000.c) sets the ID to 1. Please note to load both the modules with a different ID if required, but note that the ID used should be same for both master and slave driver loading. -e.g: -insmod omap_hdq.ko W1_ID=2 -inamod w1_bq27000.ko F_ID=2 +e.g:: + + insmod omap_hdq.ko W1_ID=2 + inamod w1_bq27000.ko F_ID=2 The driver also supports 1-wire mode. In this mode, there is no need to pass slave ID as parameter. The driver will auto-detect slaves connected diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio.rst similarity index 75% rename from Documentation/w1/masters/w1-gpio rename to Documentation/w1/masters/w1-gpio.rst index 623961d9e83f..18fdb7366372 100644 --- a/Documentation/w1/masters/w1-gpio +++ b/Documentation/w1/masters/w1-gpio.rst @@ -1,3 +1,4 @@ +===================== Kernel driver w1-gpio ===================== @@ -16,28 +17,30 @@ Documentation/devicetree/bindings/w1/w1-gpio.txt Example (mach-at91) ------------------- -#include -#include +:: + + #include + #include -static struct gpiod_lookup_table foo_w1_gpiod_table = { + static struct gpiod_lookup_table foo_w1_gpiod_table = { .dev_id = "w1-gpio", .table = { GPIO_LOOKUP_IDX("at91-gpio", AT91_PIN_PB20, NULL, 0, GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN), }, -}; + }; -static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + static struct w1_gpio_platform_data foo_w1_gpio_pdata = { .ext_pullup_enable_pin = -EINVAL, -}; + }; -static struct platform_device foo_w1_device = { + static struct platform_device foo_w1_device = { .name = "w1-gpio", .id = -1, .dev.platform_data = &foo_w1_gpio_pdata, -}; + }; -... + ... at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); gpiod_add_lookup_table(&foo_w1_gpiod_table); diff --git a/Documentation/w1/slaves/index.rst b/Documentation/w1/slaves/index.rst new file mode 100644 index 000000000000..d0697b202f09 --- /dev/null +++ b/Documentation/w1/slaves/index.rst @@ -0,0 +1,16 @@ +. SPDX-License-Identifier: GPL-2.0 + +==================== +1-wire Slave Drivers +==================== + +.. toctree:: + :maxdepth: 1 + + w1_ds2406 + w1_ds2413 + w1_ds2423 + w1_ds2438 + w1_ds28e04 + w1_ds28e17 + w1_therm diff --git a/Documentation/w1/slaves/w1_ds2406 b/Documentation/w1/slaves/w1_ds2406.rst similarity index 96% rename from Documentation/w1/slaves/w1_ds2406 rename to Documentation/w1/slaves/w1_ds2406.rst index 8137fe6f6c3d..d3e68266084f 100644 --- a/Documentation/w1/slaves/w1_ds2406 +++ b/Documentation/w1/slaves/w1_ds2406.rst @@ -1,7 +1,9 @@ +======================= w1_ds2406 kernel driver ======================= Supported chips: + * Maxim DS2406 (and other family 0x12) addressable switches Author: Scott Alfter @@ -9,7 +11,7 @@ Author: Scott Alfter Description ----------- -The w1_ds2406 driver allows connected devices to be switched on and off. +The w1_ds2406 driver allows connected devices to be switched on and off. These chips also provide 128 bytes of OTP EPROM, but reading/writing it is not supported. In TSOC-6 form, the DS2406 provides two switch outputs and can be provided with power on a dedicated input. In TO-92 form, it provides diff --git a/Documentation/w1/slaves/w1_ds2413 b/Documentation/w1/slaves/w1_ds2413.rst similarity index 81% rename from Documentation/w1/slaves/w1_ds2413 rename to Documentation/w1/slaves/w1_ds2413.rst index 936263a8ccb4..c15bb5b919b7 100644 --- a/Documentation/w1/slaves/w1_ds2413 +++ b/Documentation/w1/slaves/w1_ds2413.rst @@ -1,11 +1,16 @@ +======================= Kernel driver w1_ds2413 ======================= Supported chips: + * Maxim DS2413 1-Wire Dual Channel Addressable Switch supported family codes: + + ================ ==== W1_FAMILY_DS2413 0x3A + ================ ==== Author: Mariusz Bialonczyk @@ -20,11 +25,13 @@ Reading state The "state" file provides one-byte value which is in the same format as for the chip PIO_ACCESS_READ command (refer the datasheet for details): +======== ============================================================= Bit 0: PIOA Pin State Bit 1: PIOA Output Latch State Bit 2: PIOB Pin State Bit 3: PIOB Output Latch State Bit 4-7: Complement of Bit 3 to Bit 0 (verified by the kernel module) +======== ============================================================= This file is readonly. @@ -34,9 +41,11 @@ You can set the PIO pins using the "output" file. It is writable, you can write one-byte value to this sysfs file. Similarly the byte format is the same as for the PIO_ACCESS_WRITE command: +======== ====================================== Bit 0: PIOA Bit 1: PIOB Bit 2-7: No matter (driver will set it to "1"s) +======== ====================================== The chip has some kind of basic protection against transmission errors. diff --git a/Documentation/w1/slaves/w1_ds2423 b/Documentation/w1/slaves/w1_ds2423 deleted file mode 100644 index 3f98b505a0ee..000000000000 --- a/Documentation/w1/slaves/w1_ds2423 +++ /dev/null @@ -1,47 +0,0 @@ -Kernel driver w1_ds2423 -======================= - -Supported chips: - * Maxim DS2423 based counter devices. - -supported family codes: - W1_THERM_DS2423 0x1D - -Author: Mika Laitio - -Description ------------ - -Support is provided through the sysfs w1_slave file. Each opening and -read sequence of w1_slave file initiates the read of counters and ram -available in DS2423 pages 12 - 15. - -Result of each page is provided as an ASCII output where each counter -value and associated ram buffer is outpputed to own line. - -Each lines will contain the values of 42 bytes read from the counter and -memory page along the crc=YES or NO for indicating whether the read operation -was successful and CRC matched. -If the operation was successful, there is also in the end of each line -a counter value expressed as an integer after c= - -Meaning of 42 bytes represented is following: - - 1 byte from ram page - - 4 bytes for the counter value - - 4 zero bytes - - 2 bytes for crc16 which was calculated from the data read since the previous crc bytes - - 31 remaining bytes from the ram page - - crc=YES/NO indicating whether read was ok and crc matched - - c= current counter value - -example from the successful read: -00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 -00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 -00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761 -00 05 00 00 00 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=YES c=5 - -example from the read with crc errors: -00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 -00 02 00 00 22 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO -00 e1 61 5d 19 00 00 00 00 df 0b 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO -00 05 00 00 20 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=NO diff --git a/Documentation/w1/slaves/w1_ds2423.rst b/Documentation/w1/slaves/w1_ds2423.rst new file mode 100644 index 000000000000..755d659ad997 --- /dev/null +++ b/Documentation/w1/slaves/w1_ds2423.rst @@ -0,0 +1,54 @@ +Kernel driver w1_ds2423 +======================= + +Supported chips: + + * Maxim DS2423 based counter devices. + +supported family codes: + + =============== ==== + W1_THERM_DS2423 0x1D + =============== ==== + +Author: Mika Laitio + +Description +----------- + +Support is provided through the sysfs w1_slave file. Each opening and +read sequence of w1_slave file initiates the read of counters and ram +available in DS2423 pages 12 - 15. + +Result of each page is provided as an ASCII output where each counter +value and associated ram buffer is outpputed to own line. + +Each lines will contain the values of 42 bytes read from the counter and +memory page along the crc=YES or NO for indicating whether the read operation +was successful and CRC matched. +If the operation was successful, there is also in the end of each line +a counter value expressed as an integer after c= + +Meaning of 42 bytes represented is following: + + - 1 byte from ram page + - 4 bytes for the counter value + - 4 zero bytes + - 2 bytes for crc16 which was calculated from the data read since the previous crc bytes + - 31 remaining bytes from the ram page + - crc=YES/NO indicating whether read was ok and crc matched + - c= current counter value + +example from the successful read:: + + 00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 + 00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 + 00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761 + 00 05 00 00 00 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=YES c=5 + +example from the read with crc errors:: + + 00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 + 00 02 00 00 22 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO + 00 e1 61 5d 19 00 00 00 00 df 0b 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO + 00 05 00 00 20 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=NO diff --git a/Documentation/w1/slaves/w1_ds2438 b/Documentation/w1/slaves/w1_ds2438.rst similarity index 93% rename from Documentation/w1/slaves/w1_ds2438 rename to Documentation/w1/slaves/w1_ds2438.rst index e64f65a09387..a29309a3f8e5 100644 --- a/Documentation/w1/slaves/w1_ds2438 +++ b/Documentation/w1/slaves/w1_ds2438.rst @@ -2,10 +2,13 @@ Kernel driver w1_ds2438 ======================= Supported chips: + * Maxim DS2438 Smart Battery Monitor supported family codes: + ================ ==== W1_FAMILY_DS2438 0x26 + ================ ==== Author: Mariusz Bialonczyk @@ -56,8 +59,11 @@ Opening and reading this file initiates the CONVERT_V (voltage conversion) command of the chip. Depending on a sysfs filename a different input for the A/D will be selected: -vad: general purpose A/D input (VAD) -vdd: battery input (VDD) + +vad: + general purpose A/D input (VAD) +vdd: + battery input (VDD) After the voltage conversion the value is returned as decimal ASCII. Note: To get a volts the value has to be divided by 100. diff --git a/Documentation/w1/slaves/w1_ds28e04 b/Documentation/w1/slaves/w1_ds28e04.rst similarity index 93% rename from Documentation/w1/slaves/w1_ds28e04 rename to Documentation/w1/slaves/w1_ds28e04.rst index 7819b65cfa48..b12b118890d3 100644 --- a/Documentation/w1/slaves/w1_ds28e04 +++ b/Documentation/w1/slaves/w1_ds28e04.rst @@ -1,11 +1,16 @@ +======================== Kernel driver w1_ds28e04 ======================== Supported chips: + * Maxim DS28E04-100 4096-Bit Addressable 1-Wire EEPROM with PIO supported family codes: + + ================= ==== W1_FAMILY_DS28E04 0x1C + ================= ==== Author: Markus Franke, diff --git a/Documentation/w1/slaves/w1_ds28e17 b/Documentation/w1/slaves/w1_ds28e17.rst similarity index 88% rename from Documentation/w1/slaves/w1_ds28e17 rename to Documentation/w1/slaves/w1_ds28e17.rst index 7fcfad5b4a37..e2d9f96d8f2c 100644 --- a/Documentation/w1/slaves/w1_ds28e17 +++ b/Documentation/w1/slaves/w1_ds28e17.rst @@ -1,11 +1,16 @@ +======================== Kernel driver w1_ds28e17 ======================== Supported chips: + * Maxim DS28E17 1-Wire-to-I2C Master Bridge supported family codes: + + ================= ==== W1_FAMILY_DS28E17 0x19 + ================= ==== Author: Jan Kandziora @@ -20,11 +25,11 @@ a DS28E17 can be accessed by the kernel or userspace tools as if they were connected to a "native" I2C bus master. -An udev rule like the following -------------------------------------------------------------------------------- -SUBSYSTEM=="i2c-dev", KERNEL=="i2c-[0-9]*", ATTRS{name}=="w1-19-*", \ - SYMLINK+="i2c-$attr{name}" -------------------------------------------------------------------------------- +An udev rule like the following:: + + SUBSYSTEM=="i2c-dev", KERNEL=="i2c-[0-9]*", ATTRS{name}=="w1-19-*", \ + SYMLINK+="i2c-$attr{name}" + may be used to create stable /dev/i2c- entries based on the unique id of the DS28E17 chip. @@ -65,4 +70,3 @@ structure is created. See https://github.com/ianka/w1_ds28e17 for even more information. - diff --git a/Documentation/w1/slaves/w1_therm b/Documentation/w1/slaves/w1_therm.rst similarity index 95% rename from Documentation/w1/slaves/w1_therm rename to Documentation/w1/slaves/w1_therm.rst index d1f93af36f38..90531c340a07 100644 --- a/Documentation/w1/slaves/w1_therm +++ b/Documentation/w1/slaves/w1_therm.rst @@ -1,7 +1,9 @@ +====================== Kernel driver w1_therm -==================== +====================== Supported chips: + * Maxim ds18*20 based temperature sensors. * Maxim ds1825 based temperature sensors. @@ -13,12 +15,16 @@ Description w1_therm provides basic temperature conversion for ds18*20 devices, and the ds28ea00 device. -supported family codes: + +Supported family codes: + +==================== ==== W1_THERM_DS18S20 0x10 W1_THERM_DS1822 0x22 W1_THERM_DS18B20 0x28 W1_THERM_DS1825 0x3B W1_THERM_DS28EA00 0x42 +==================== ==== Support is provided through the sysfs w1_slave file. Each open and read sequence will initiate a temperature conversion then provide two @@ -51,6 +57,7 @@ If so, it will activate the master's strong pullup. In case the detection of parasite devices using this command fails (seems to be the case with some DS18S20) the strong pullup can be force-enabled. + If the strong pullup is enabled, the master's strong pullup will be driven when the conversion is taking place, provided the master driver does support the strong pullup (or it falls back to a pullup diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1-generic.rst similarity index 59% rename from Documentation/w1/w1.generic rename to Documentation/w1/w1-generic.rst index c51b1ab012d0..da4e8b4e9b01 100644 --- a/Documentation/w1/w1.generic +++ b/Documentation/w1/w1-generic.rst @@ -1,5 +1,7 @@ -The 1-wire (w1) subsystem ------------------------------------------------------------------- +========================================= +Introduction to the 1-wire (w1) subsystem +========================================= + The 1-wire bus is a simple master-slave bus that communicates via a single signal wire (plus ground, so two wires). @@ -12,14 +14,16 @@ communication with slaves. All w1 slave devices must be connected to a w1 bus master device. Example w1 master devices: - DS9490 usb device - W1-over-GPIO - DS2482 (i2c to w1 bridge) - Emulated devices, such as a RS232 converter, parallel port adapter, etc + + - DS9490 usb device + - W1-over-GPIO + - DS2482 (i2c to w1 bridge) + - Emulated devices, such as a RS232 converter, parallel port adapter, etc What does the w1 subsystem do? ------------------------------------------------------------------- +------------------------------ + When a w1 master driver registers with the w1 subsystem, the following occurs: - sysfs entries for that w1 master are created @@ -43,24 +47,28 @@ be read, since no device was selected. W1 device families ------------------------------------------------------------------- +------------------ + Slave devices are handled by a driver written for a family of w1 devices. A family driver populates a struct w1_family_ops (see w1_family.h) and registers with the w1 subsystem. Current family drivers: -w1_therm - (ds18?20 thermal sensor family driver) + +w1_therm + - (ds18?20 thermal sensor family driver) provides temperature reading function which is bound to ->rbin() method of the above w1_family_ops structure. -w1_smem - driver for simple 64bit memory cell provides ID reading method. +w1_smem + - driver for simple 64bit memory cell provides ID reading method. You can call above methods by reading appropriate sysfs files. What does a w1 master driver need to implement? ------------------------------------------------------------------- +----------------------------------------------- The driver for w1 bus master must provide at minimum two functions. @@ -75,25 +83,26 @@ See struct w1_bus_master definition in w1.h for details. w1 master sysfs interface ------------------------------------------------------------------- - - A directory for a found device. The format is family-serial -bus - (standard) symlink to the w1 bus -driver - (standard) symlink to the w1 driver -w1_master_add - (rw) manually register a slave device -w1_master_attempts - (ro) the number of times a search was attempted -w1_master_max_slave_count - - (rw) maximum number of slaves to search for at a time -w1_master_name - (ro) the name of the device (w1_bus_masterX) -w1_master_pullup - (rw) 5V strong pullup 0 enabled, 1 disabled -w1_master_remove - (rw) manually remove a slave device -w1_master_search - (rw) the number of searches left to do, - -1=continual (default) -w1_master_slave_count - - (ro) the number of slaves found -w1_master_slaves - (ro) the names of the slaves, one per line -w1_master_timeout - (ro) the delay in seconds between searches -w1_master_timeout_us - - (ro) the delay in microseconds beetwen searches +------------------------- + +========================= ===================================================== + A directory for a found device. The format is + family-serial +bus (standard) symlink to the w1 bus +driver (standard) symlink to the w1 driver +w1_master_add (rw) manually register a slave device +w1_master_attempts (ro) the number of times a search was attempted +w1_master_max_slave_count (rw) maximum number of slaves to search for at a time +w1_master_name (ro) the name of the device (w1_bus_masterX) +w1_master_pullup (rw) 5V strong pullup 0 enabled, 1 disabled +w1_master_remove (rw) manually remove a slave device +w1_master_search (rw) the number of searches left to do, + -1=continual (default) +w1_master_slave_count (ro) the number of slaves found +w1_master_slaves (ro) the names of the slaves, one per line +w1_master_timeout (ro) the delay in seconds between searches +w1_master_timeout_us (ro) the delay in microseconds beetwen searches +========================= ===================================================== If you have a w1 bus that never changes (you don't add or remove devices), you can set the module parameter search_count to a small positive number @@ -111,11 +120,14 @@ decrements w1_master_search by 1 (down to 0) and increments w1_master_attempts by 1. w1 slave sysfs interface ------------------------------------------------------------------- -bus - (standard) symlink to the w1 bus -driver - (standard) symlink to the w1 driver -name - the device name, usually the same as the directory name -w1_slave - (optional) a binary file whose meaning depends on the - family driver -rw - (optional) created for slave devices which do not have - appropriate family driver. Allows to read/write binary data. +------------------------ + +=================== ============================================================ +bus (standard) symlink to the w1 bus +driver (standard) symlink to the w1 driver +name the device name, usually the same as the directory name +w1_slave (optional) a binary file whose meaning depends on the + family driver +rw (optional) created for slave devices which do not have + appropriate family driver. Allows to read/write binary data. +=================== ============================================================ diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1-netlink.rst similarity index 77% rename from Documentation/w1/w1.netlink rename to Documentation/w1/w1-netlink.rst index 94ad4c420828..aaa13243a5e4 100644 --- a/Documentation/w1/w1.netlink +++ b/Documentation/w1/w1-netlink.rst @@ -1,22 +1,26 @@ -Userspace communication protocol over connector [1]. +=============================================== +Userspace communication protocol over connector +=============================================== - -Message types. +Message types ============= There are three types of messages between w1 core and userspace: + 1. Events. They are generated each time a new master or slave device - is found either due to automatic or requested search. + is found either due to automatic or requested search. 2. Userspace commands. 3. Replies to userspace commands. -Protocol. +Protocol ======== -[struct cn_msg] - connector header. +:: + + [struct cn_msg] - connector header. Its length field is equal to size of the attached data -[struct w1_netlink_msg] - w1 netlink header. + [struct w1_netlink_msg] - w1 netlink header. __u8 type - message type. W1_LIST_MASTERS list current bus masters @@ -40,7 +44,7 @@ Protocol. } mst; } id; -[struct w1_netlink_cmd] - command for given master or slave device. + [struct w1_netlink_cmd] - command for given master or slave device. __u8 cmd - command opcode. W1_CMD_READ - read command W1_CMD_WRITE - write command @@ -71,18 +75,18 @@ when it is added to w1 core. Currently replies to userspace commands are only generated for read command request. One reply is generated exactly for one w1_netlink_cmd read request. Replies are not combined when sent - i.e. typical reply -messages looks like the following: +messages looks like the following:: -[cn_msg][w1_netlink_msg][w1_netlink_cmd] -cn_msg.len = sizeof(struct w1_netlink_msg) + + [cn_msg][w1_netlink_msg][w1_netlink_cmd] + cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; -w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len; -w1_netlink_cmd.len = cmd->len; + w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len; + w1_netlink_cmd.len = cmd->len; Replies to W1_LIST_MASTERS should send a message back to the userspace which will contain list of all registered master ids in the following -format: +format:: cn_msg (CN_W1_IDX.CN_W1_VAL as id, len is equal to sizeof(struct w1_netlink_msg) plus number of masters multiplied by 4) @@ -90,39 +94,47 @@ format: number of masters multiplied by 4 (u32 size)) id0 ... idN - Each message is at most 4k in size, so if number of master devices - exceeds this, it will be split into several messages. +Each message is at most 4k in size, so if number of master devices +exceeds this, it will be split into several messages. W1 search and alarm search commands. -request: -[cn_msg] - [w1_netlink_msg type = W1_MASTER_CMD - id is equal to the bus master id to use for searching] - [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH] -reply: +request:: + + [cn_msg] + [w1_netlink_msg type = W1_MASTER_CMD + id is equal to the bus master id to use for searching] + [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH] + +reply:: + [cn_msg, ack = 1 and increasing, 0 means the last message, - seq is equal to the request seq] + seq is equal to the request seq] [w1_netlink_msg type = W1_MASTER_CMD] [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH len is equal to number of IDs multiplied by 8] [64bit-id0 ... 64bit-idN] + Length in each header corresponds to the size of the data behind it, so w1_netlink_cmd->len = N * 8; where N is number of IDs in this message. - Can be zero. -w1_netlink_msg->len = sizeof(struct w1_netlink_cmd) + N * 8; -cn_msg->len = sizeof(struct w1_netlink_msg) + +Can be zero. + +:: + + w1_netlink_msg->len = sizeof(struct w1_netlink_cmd) + N * 8; + cn_msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + N*8; -W1 reset command. -[cn_msg] - [w1_netlink_msg type = W1_MASTER_CMD - id is equal to the bus master id to use for searching] - [w1_netlink_cmd cmd = W1_CMD_RESET] +W1 reset command:: + [cn_msg] + [w1_netlink_msg type = W1_MASTER_CMD + id is equal to the bus master id to use for searching] + [w1_netlink_cmd cmd = W1_CMD_RESET] -Command status replies. + +Command status replies ====================== Each command (either root, master or slave with or without w1_netlink_cmd @@ -150,7 +162,7 @@ All w1_netlink_cmd command structures are handled in every w1_netlink_msg, even if there were errors, only length mismatch interrupts message processing. -Operation steps in w1 core when new command is received. +Operation steps in w1 core when new command is received ======================================================= When new message (w1_netlink_msg) is received w1 core detects if it is @@ -167,7 +179,7 @@ When all commands (w1_netlink_cmd) are processed master device is unlocked and next w1_netlink_msg header processing started. -Connector [1] specific documentation. +Connector [1] specific documentation ==================================== Each connector message includes two u32 fields as "address". @@ -180,10 +192,11 @@ Sequence number for reply is the same as was in request, and acknowledge number is set to seq+1. -Additional documantion, source code examples. -============================================ +Additional documentation, source code examples +============================================== 1. Documentation/driver-api/connector.rst 2. http://www.ioremap.net/archive/w1 -This archive includes userspace application w1d.c which uses -read/write/search commands for all master/slave devices found on the bus. + + This archive includes userspace application w1d.c which uses + read/write/search commands for all master/slave devices found on the bus. -- GitLab From 9195c3e8d58a258344a33e0e05359564e8f8e538 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Jul 2019 17:27:56 -0300 Subject: [PATCH 1476/7155] docs: fs: porting.rst: fix a broken reference to another doc With all those document shifts, references to documents get broken. Fix one such occurrence at porting.rst. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/filesystems/porting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst index 66aa521e6376..f18506083ced 100644 --- a/Documentation/filesystems/porting.rst +++ b/Documentation/filesystems/porting.rst @@ -158,7 +158,7 @@ Callers of notify_change() need ->i_mutex now. New super_block field ``struct export_operations *s_export_op`` for explicit support for exporting, e.g. via NFS. The structure is fully documented at its declaration in include/linux/fs.h, and in -Documentation/filesystems/nfs/Exporting. +Documentation/filesystems/nfs/exporting.rst. Briefly it allows for the definition of decode_fh and encode_fh operations to encode and decode filehandles, and allows the filesystem to use -- GitLab From cb7db35641c9a508247bdcd73831c855c8758cd3 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 26 Jun 2019 02:20:19 -0700 Subject: [PATCH 1477/7155] ice: Only bump Rx tail and release buffers once per napi_poll Currently we bump the Rx tail and release/give buffers to hardware every 16 descriptors. This causes us to bump Rx tail up to 4 times per napi_poll call. Also we are always bumping tail on an odd index and this is a problem because hardware ignores the lower 3 bits in the QRX_TAIL register. This is making it so hardware sees tail bumps only every 8 descriptors. Instead lets only bump Rx tail once per napi_poll if the value aligns with hardware's expectations of the lower 3 bits being cleared. Also only release/give Rx buffers once per napi_poll call. Signed-off-by: Brett Creeley Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_txrx.c | 42 +++++++++++++++-------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index dd7392f293bf..0c459305c12f 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -377,18 +377,28 @@ int ice_setup_rx_ring(struct ice_ring *rx_ring) */ static void ice_release_rx_desc(struct ice_ring *rx_ring, u32 val) { + u16 prev_ntu = rx_ring->next_to_use; + rx_ring->next_to_use = val; /* update next to alloc since we have filled the ring */ rx_ring->next_to_alloc = val; - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). + /* QRX_TAIL will be updated with any tail value, but hardware ignores + * the lower 3 bits. This makes it so we only bump tail on meaningful + * boundaries. Also, this allows us to bump tail on intervals of 8 up to + * the budget depending on the current traffic load. */ - wmb(); - writel(val, rx_ring->tail); + val &= ~0x7; + if (prev_ntu != val) { + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + writel(val, rx_ring->tail); + } } /** @@ -445,7 +455,13 @@ ice_alloc_mapped_page(struct ice_ring *rx_ring, struct ice_rx_buf *bi) * @rx_ring: ring to place buffers on * @cleaned_count: number of buffers to replace * - * Returns false if all allocations were successful, true if any fail + * Returns false if all allocations were successful, true if any fail. Returning + * true signals to the caller that we didn't replace cleaned_count buffers and + * there is more work to do. + * + * First, try to clean "cleaned_count" Rx buffers. Then refill the cleaned Rx + * buffers. Then bump tail at most one time. Grouping like this lets us avoid + * multiple tail writes per call. */ bool ice_alloc_rx_bufs(struct ice_ring *rx_ring, u16 cleaned_count) { @@ -990,7 +1006,7 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget) { unsigned int total_rx_bytes = 0, total_rx_pkts = 0; u16 cleaned_count = ICE_DESC_UNUSED(rx_ring); - bool failure = false; + bool failure; /* start the loop to process Rx packets bounded by 'budget' */ while (likely(total_rx_pkts < (unsigned int)budget)) { @@ -1002,13 +1018,6 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget) u16 vlan_tag = 0; u8 rx_ptype; - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= ICE_RX_BUF_WRITE) { - failure = failure || - ice_alloc_rx_bufs(rx_ring, cleaned_count); - cleaned_count = 0; - } - /* get the Rx desc from Rx ring based on 'next_to_clean' */ rx_desc = ICE_RX_DESC(rx_ring, rx_ring->next_to_clean); @@ -1085,6 +1094,9 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget) total_rx_pkts++; } + /* return up to cleaned_count buffers to hardware */ + failure = ice_alloc_rx_bufs(rx_ring, cleaned_count); + /* update queue and vector specific stats */ u64_stats_update_begin(&rx_ring->syncp); rx_ring->stats.pkts += total_rx_pkts; -- GitLab From d5a46359171a00539179aefa04115c9c30002617 Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Wed, 26 Jun 2019 02:20:20 -0700 Subject: [PATCH 1478/7155] ice: Set up Tx scheduling tree based on alloc VSI Tx queues This patch uses allocated number of Tx queues per VSI to set up its scheduling tree instead of using total number of available Tx queues. Only PF VSIs have total number of allocated Tx queues equal to number of available Tx queues, other VSIs have different number of queues configured. Signed-off-by: Akeem G Abodunrin Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 01f38abd4277..e28478215810 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2511,7 +2511,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, /* configure VSI nodes based on number of queues and TC's */ for (i = 0; i < vsi->tc_cfg.numtc; i++) - max_txqs[i] = pf->num_lan_tx; + max_txqs[i] = vsi->alloc_txq; status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, max_txqs); @@ -3020,7 +3020,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) /* configure VSI nodes based on number of queues and TC's */ for (i = 0; i < vsi->tc_cfg.numtc; i++) - max_txqs[i] = pf->num_lan_tx; + max_txqs[i] = vsi->alloc_txq; status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, max_txqs); @@ -3137,7 +3137,7 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) if (ena_tc & BIT(i)) num_tc++; /* populate max_txqs per TC */ - max_txqs[i] = pf->num_lan_tx; + max_txqs[i] = vsi->alloc_txq; } vsi->tc_cfg.ena_tc = ena_tc; -- GitLab From 66b29e7a884e53e7e32ffb893d9897b299cd5cdf Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Wed, 26 Jun 2019 02:20:21 -0700 Subject: [PATCH 1479/7155] ice: Update number of VF queue before setting VSI resources In case there is a request from a VF to change its number of queues, and the request was successful, we need to update number of queues configured on the VF before updating corresponding VSI for that VF, especially LAN Tx queue tree and TC update, otherwise, we would continued to use old value of vf->num_vf_qs for allocated Tx/Rx queues... Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 5d24b539648f..00aa6364124a 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -567,11 +567,6 @@ static int ice_alloc_vf_res(struct ice_vf *vf) int tx_rx_queue_left; int status; - /* setup VF VSI and necessary resources */ - status = ice_alloc_vsi_res(vf); - if (status) - goto ice_alloc_vf_res_exit; - /* Update number of VF queues, in case VF had requested for queue * changes */ @@ -581,6 +576,11 @@ static int ice_alloc_vf_res(struct ice_vf *vf) vf->num_req_qs != vf->num_vf_qs) vf->num_vf_qs = vf->num_req_qs; + /* setup VF VSI and necessary resources */ + status = ice_alloc_vsi_res(vf); + if (status) + goto ice_alloc_vf_res_exit; + if (vf->trusted) set_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); else -- GitLab From 56923ab66467c2edbd1ff97240ff14805e0b1cdc Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 26 Jun 2019 02:20:22 -0700 Subject: [PATCH 1480/7155] ice: Add stats for Rx drops at the port level Currently we are not reporting dropped counts at the port level to ethtool or netlink. This was found when debugging Rx dropped issues and the total packets sent did not equal the total packets received minus the rx_dropped, which was very confusing. To determine dropped counts at the port level we need to read the PRTRPB_RDPC register. To fix reporting we will store the dropped counts in the PF's rx_discards. This will be reported to netlink by storing it in the PF VSI's rx_missed_errors signaling that the receiver missed the packet. Also, we will report this to ethtool in the rx_dropped.nic field. Signed-off-by: Brett Creeley Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 1 + drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 3250dfc00002..87652d722a30 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -337,5 +337,6 @@ #define VSIQF_HLUT_MAX_INDEX 15 #define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4)) #define VFINT_DYN_CTLN_CLEARPBA_M BIT(1) +#define PRTRPB_RDPC 0x000AC260 #endif /* _ICE_HW_AUTOGEN_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index d13f56803658..e4be9aa79337 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3297,6 +3297,8 @@ static void ice_update_vsi_stats(struct ice_vsi *vsi) cur_ns->rx_errors = pf->stats.crc_errors + pf->stats.illegal_bytes; cur_ns->rx_length_errors = pf->stats.rx_len_errors; + /* record drops from the port level */ + cur_ns->rx_missed_errors = pf->stats.eth.rx_discards; } } @@ -3330,6 +3332,10 @@ static void ice_update_pf_stats(struct ice_pf *pf) &prev_ps->eth.rx_broadcast, &cur_ps->eth.rx_broadcast); + ice_stat_update32(hw, PRTRPB_RDPC, pf->stat_prev_loaded, + &prev_ps->eth.rx_discards, + &cur_ps->eth.rx_discards); + ice_stat_update40(hw, GLPRT_GOTCL(pf_id), pf->stat_prev_loaded, &prev_ps->eth.tx_bytes, &cur_ps->eth.tx_bytes); -- GitLab From a1e9968593234c179fcb3e71875897ae585c8362 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 26 Jun 2019 02:20:23 -0700 Subject: [PATCH 1481/7155] ice: Remove duplicate code in ice_alloc_rx_bufs Currently if the call to ice_alloc_mapped_page() fails we jump to the no_buf label, possibly call ice_release_rx_desc(), and return true indicating that there is more work to do. In the success case we just fall out of the while loop, possibly call ice_alloc_mapped_page(), and return false saying we exhausted cleaned_count. This flow can be improved by breaking if ice_alloc_mapped_page() fails and then the flow outside of the while loop is the same for the failure and success case. Signed-off-by: Brett Creeley Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_txrx.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 0c459305c12f..020dac283f07 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -478,8 +478,9 @@ bool ice_alloc_rx_bufs(struct ice_ring *rx_ring, u16 cleaned_count) bi = &rx_ring->rx_buf[ntu]; do { + /* if we fail here, we have work remaining */ if (!ice_alloc_mapped_page(rx_ring, bi)) - goto no_bufs; + break; /* sync the buffer for use by the device */ dma_sync_single_range_for_device(rx_ring->dev, bi->dma, @@ -510,16 +511,7 @@ bool ice_alloc_rx_bufs(struct ice_ring *rx_ring, u16 cleaned_count) if (rx_ring->next_to_use != ntu) ice_release_rx_desc(rx_ring, ntu); - return false; - -no_bufs: - if (rx_ring->next_to_use != ntu) - ice_release_rx_desc(rx_ring, ntu); - - /* make sure to come back via polling to try again after - * allocation failure - */ - return true; + return !!cleaned_count; } /** -- GitLab From 992149446353bc22dff8edf231f2a5d8c5a3bd50 Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Wed, 26 Jun 2019 02:20:24 -0700 Subject: [PATCH 1482/7155] ice: Don't return error for disabling LAN Tx queue that does exist Since Tx rings are being managed by FW/NVM, Tx rings might have not been set up or driver had already wiped them off - In that case, call to disable LAN Tx queue is being returned as not in existence. This patch makes sure we don't return unnecessary error for such scenario. Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index e28478215810..2add10e02280 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2148,6 +2148,9 @@ ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, if (status == ICE_ERR_RESET_ONGOING) { dev_dbg(&pf->pdev->dev, "Reset in progress. LAN Tx queues already disabled\n"); + } else if (status == ICE_ERR_DOES_NOT_EXIST) { + dev_dbg(&pf->pdev->dev, + "LAN Tx queues does not exist, nothing to disabled\n"); } else if (status) { dev_err(&pf->pdev->dev, "Failed to disable LAN Tx queues, error: %d\n", -- GitLab From ba880734ba9c24eca589b3f734d38309568301b2 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 26 Jun 2019 02:20:25 -0700 Subject: [PATCH 1483/7155] ice: Remove unnecessary flag ICE_FLAG_MSIX_ENA This flag is not needed and is called every time we re-enable interrupts in the hotpath so remove it. Also remove ice_vsi_req_irq() because it was a wrapper function for ice_vsi_req_irq_msix() whose sole purpose was checking the ICE_FLAG_MSIX_ENA flag. Signed-off-by: Brett Creeley Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 1 - drivers/net/ethernet/intel/ice/ice_lib.c | 71 +++++++++------------- drivers/net/ethernet/intel/ice/ice_main.c | 74 ++++++----------------- drivers/net/ethernet/intel/ice/ice_txrx.c | 4 +- 4 files changed, 48 insertions(+), 102 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 596b09a905aa..794d97460fc7 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -329,7 +329,6 @@ struct ice_q_vector { } ____cacheline_internodealigned_in_smp; enum ice_pf_flags { - ICE_FLAG_MSIX_ENA, ICE_FLAG_FLTR_SYNC, ICE_FLAG_RSS_ENA, ICE_FLAG_SRIOV_ENA, diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 2add10e02280..6e34c40e7840 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1129,12 +1129,7 @@ static int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi) return -EEXIST; } - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - num_q_vectors = vsi->num_q_vectors; - } else { - err = -EINVAL; - goto err_out; - } + num_q_vectors = vsi->num_q_vectors; for (v_idx = 0; v_idx < num_q_vectors; v_idx++) { err = ice_vsi_alloc_q_vector(vsi, v_idx); @@ -1180,9 +1175,6 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) return -EEXIST; } - if (!test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - return -ENOENT; - num_q_vectors = vsi->num_q_vectors; /* reserve slots from OS requested IRQs */ vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors, @@ -2605,39 +2597,36 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) { struct ice_pf *pf = vsi->back; int base = vsi->base_vector; + int i; - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - int i; - - if (!vsi->q_vectors || !vsi->irqs_ready) - return; + if (!vsi->q_vectors || !vsi->irqs_ready) + return; - ice_vsi_release_msix(vsi); - if (vsi->type == ICE_VSI_VF) - return; + ice_vsi_release_msix(vsi); + if (vsi->type == ICE_VSI_VF) + return; - vsi->irqs_ready = false; - ice_for_each_q_vector(vsi, i) { - u16 vector = i + base; - int irq_num; + vsi->irqs_ready = false; + ice_for_each_q_vector(vsi, i) { + u16 vector = i + base; + int irq_num; - irq_num = pf->msix_entries[vector].vector; + irq_num = pf->msix_entries[vector].vector; - /* free only the irqs that were actually requested */ - if (!vsi->q_vectors[i] || - !(vsi->q_vectors[i]->num_ring_tx || - vsi->q_vectors[i]->num_ring_rx)) - continue; + /* free only the irqs that were actually requested */ + if (!vsi->q_vectors[i] || + !(vsi->q_vectors[i]->num_ring_tx || + vsi->q_vectors[i]->num_ring_rx)) + continue; - /* clear the affinity notifier in the IRQ descriptor */ - irq_set_affinity_notifier(irq_num, NULL); + /* clear the affinity notifier in the IRQ descriptor */ + irq_set_affinity_notifier(irq_num, NULL); - /* clear the affinity_mask in the IRQ descriptor */ - irq_set_affinity_hint(irq_num, NULL); - synchronize_irq(irq_num); - devm_free_irq(&pf->pdev->dev, irq_num, - vsi->q_vectors[i]); - } + /* clear the affinity_mask in the IRQ descriptor */ + irq_set_affinity_hint(irq_num, NULL); + synchronize_irq(irq_num); + devm_free_irq(&pf->pdev->dev, irq_num, + vsi->q_vectors[i]); } } @@ -2816,15 +2805,13 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) } /* disable each interrupt */ - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - ice_for_each_q_vector(vsi, i) - wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); + ice_for_each_q_vector(vsi, i) + wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); - ice_flush(hw); + ice_flush(hw); - ice_for_each_q_vector(vsi, i) - synchronize_irq(pf->msix_entries[i + base].vector); - } + ice_for_each_q_vector(vsi, i) + synchronize_irq(pf->msix_entries[i + base].vector); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e4be9aa79337..8a8f9170e219 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1547,15 +1547,11 @@ static void ice_irq_affinity_release(struct kref __always_unused *ref) {} */ static int ice_vsi_ena_irq(struct ice_vsi *vsi) { - struct ice_pf *pf = vsi->back; - struct ice_hw *hw = &pf->hw; - - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - int i; + struct ice_hw *hw = &vsi->back->hw; + int i; - ice_for_each_q_vector(vsi, i) - ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]); - } + ice_for_each_q_vector(vsi, i) + ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]); ice_flush(hw); return 0; @@ -1803,7 +1799,7 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) wr32(hw, PFINT_OICR_ENA, 0); ice_flush(hw); - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { + if (pf->msix_entries) { synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); devm_free_irq(&pf->pdev->dev, pf->msix_entries[pf->oicr_idx].vector, pf); @@ -2229,7 +2225,6 @@ static void ice_deinit_pf(struct ice_pf *pf) static void ice_init_pf(struct ice_pf *pf) { bitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS); - set_bit(ICE_FLAG_MSIX_ENA, pf->flags); #ifdef CONFIG_PCI_IOV if (pf->hw.func_caps.common_cap.sr_iov_1_1) { struct ice_hw *hw = &pf->hw; @@ -2329,7 +2324,6 @@ static int ice_ena_msix_range(struct ice_pf *pf) exit_err: pf->num_lan_msix = 0; - clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); return err; } @@ -2342,7 +2336,6 @@ static void ice_dis_msix(struct ice_pf *pf) pci_disable_msix(pf->pdev); devm_kfree(&pf->pdev->dev, pf->msix_entries); pf->msix_entries = NULL; - clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); } /** @@ -2351,8 +2344,7 @@ static void ice_dis_msix(struct ice_pf *pf) */ static void ice_clear_interrupt_scheme(struct ice_pf *pf) { - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - ice_dis_msix(pf); + ice_dis_msix(pf); if (pf->irq_tracker) { devm_kfree(&pf->pdev->dev, pf->irq_tracker); @@ -2368,10 +2360,7 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) { int vectors; - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - vectors = ice_ena_msix_range(pf); - else - return -ENODEV; + vectors = ice_ena_msix_range(pf); if (vectors < 0) return vectors; @@ -2528,12 +2517,10 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) * the misc functionality and queue processing is combined in * the same vector and that gets setup at open. */ - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - err = ice_req_irq_msix_misc(pf); - if (err) { - dev_err(dev, "setup of misc vector failed: %d\n", err); - goto err_init_interrupt_unroll; - } + err = ice_req_irq_msix_misc(pf); + if (err) { + dev_err(dev, "setup of misc vector failed: %d\n", err); + goto err_init_interrupt_unroll; } /* create switch struct for the switch element created by FW on boot */ @@ -3146,10 +3133,7 @@ static int ice_up_complete(struct ice_vsi *vsi) struct ice_pf *pf = vsi->back; int err; - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - ice_vsi_cfg_msix(vsi); - else - return -ENOTSUPP; + ice_vsi_cfg_msix(vsi); /* Enable only Rx rings, Tx rings were enabled by the FW when the * Tx queue group list was configured and the context bits were @@ -3609,24 +3593,6 @@ int ice_vsi_setup_rx_rings(struct ice_vsi *vsi) return err; } -/** - * ice_vsi_req_irq - Request IRQ from the OS - * @vsi: The VSI IRQ is being requested for - * @basename: name for the vector - * - * Return 0 on success and a negative value on error - */ -static int ice_vsi_req_irq(struct ice_vsi *vsi, char *basename) -{ - struct ice_pf *pf = vsi->back; - int err = -EINVAL; - - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - err = ice_vsi_req_irq_msix(vsi, basename); - - return err; -} - /** * ice_vsi_open - Called when a network interface is made active * @vsi: the VSI to open @@ -3656,7 +3622,7 @@ static int ice_vsi_open(struct ice_vsi *vsi) snprintf(int_name, sizeof(int_name) - 1, "%s-%s", dev_driver_string(&pf->pdev->dev), vsi->netdev->name); - err = ice_vsi_req_irq(vsi, int_name); + err = ice_vsi_req_irq_msix(vsi, int_name); if (err) goto err_setup_rx; @@ -3893,12 +3859,10 @@ static void ice_rebuild(struct ice_pf *pf) } /* start misc vector */ - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { - err = ice_req_irq_msix_misc(pf); - if (err) { - dev_err(dev, "misc vector setup failed: %d\n", err); - goto err_vsi_rebuild; - } + err = ice_req_irq_msix_misc(pf); + if (err) { + dev_err(dev, "misc vector setup failed: %d\n", err); + goto err_vsi_rebuild; } /* restart the VSIs that were rebuilt and running before the reset */ @@ -4295,9 +4259,7 @@ static void ice_tx_timeout(struct net_device *netdev) head = (rd32(hw, QTX_COMM_HEAD(vsi->txq_map[hung_queue])) & QTX_COMM_HEAD_HEAD_M) >> QTX_COMM_HEAD_HEAD_S; /* Read interrupt register */ - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - val = rd32(hw, - GLINT_DYN_CTL(tx_ring->q_vector->reg_idx)); + val = rd32(hw, GLINT_DYN_CTL(tx_ring->q_vector->reg_idx)); netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HW_HEAD: 0x%x, NTU: 0x%x, INT: 0x%x\n", vsi->vsi_num, hung_queue, tx_ring->next_to_clean, diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 020dac283f07..9234fd203929 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1413,7 +1413,6 @@ int ice_napi_poll(struct napi_struct *napi, int budget) struct ice_q_vector *q_vector = container_of(napi, struct ice_q_vector, napi); struct ice_vsi *vsi = q_vector->vsi; - struct ice_pf *pf = vsi->back; bool clean_complete = true; int budget_per_ring = 0; struct ice_ring *ring; @@ -1454,8 +1453,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget) * poll us due to busy-polling */ if (likely(napi_complete_done(napi, work_done))) - if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - ice_update_ena_itr(vsi, q_vector); + ice_update_ena_itr(vsi, q_vector); return min_t(int, work_done, budget - 1); } -- GitLab From b67f25d76e9f5e73024b8782acb47f7e7bd339b8 Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Wed, 26 Jun 2019 02:20:26 -0700 Subject: [PATCH 1484/7155] ice: Remove flag to track VF interrupt status As a result of refactoring of VF VSIs interrupts code, there is no need to track its configuration status again with ICE_VF_STATE_CFG_INTR flag - In fact, it is not being checked anywhere in the code right now, so this patch removes the dead code as applicable to the flag. Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 11 ----------- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h | 5 ----- 2 files changed, 16 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 00aa6364124a..ce01cbe70ea4 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -297,13 +297,6 @@ void ice_free_vfs(struct ice_pf *pf) if (test_bit(ICE_VF_STATE_INIT, pf->vf[i].vf_states)) { /* disable VF qp mappings */ ice_dis_vf_mappings(&pf->vf[i]); - - /* Set this state so that assigned VF vectors can be - * reclaimed by PF for reuse in ice_vsi_release(). No - * need to clear this bit since pf->vf array is being - * freed anyways after this for loop - */ - set_bit(ICE_VF_STATE_CFG_INTR, pf->vf[i].vf_states); ice_free_vf_res(&pf->vf[i]); } } @@ -551,7 +544,6 @@ static int ice_alloc_vsi_res(struct ice_vf *vf) * expect vector assignment to be changed unless there is a request for * more vectors. */ - clear_bit(ICE_VF_STATE_CFG_INTR, vf->vf_states); ice_alloc_vsi_res_exit: ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); return status; @@ -1283,9 +1275,6 @@ static int ice_alloc_vfs(struct ice_pf *pf, u16 num_alloc_vfs) /* assign default capabilities */ set_bit(ICE_VIRTCHNL_VF_CAP_L2, &vfs[i].vf_caps); vfs[i].spoofchk = true; - - /* Set this state so that PF driver does VF vector assignment */ - set_bit(ICE_VF_STATE_CFG_INTR, vfs[i].vf_states); } pf->num_alloc_vfs = num_alloc_vfs; diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h index c3ca522c245a..ada69120ff38 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h @@ -30,11 +30,6 @@ enum ice_vf_states { ICE_VF_STATE_DIS, ICE_VF_STATE_MC_PROMISC, ICE_VF_STATE_UC_PROMISC, - /* state to indicate if PF needs to do vector assignment for VF. - * This needs to be set during first time VF initialization or later - * when VF asks for more Vectors through virtchnl OP. - */ - ICE_VF_STATE_CFG_INTR, ICE_VF_STATES_NBITS }; -- GitLab From 3015b8fcb60d448a9521b49359e068d021aaec97 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Wed, 26 Jun 2019 02:20:27 -0700 Subject: [PATCH 1485/7155] ice: Bump version number Update driver version to 0.7.5 Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 8a8f9170e219..c26e6a102dac 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -9,7 +9,7 @@ #include "ice_lib.h" #include "ice_dcb_lib.h" -#define DRV_VERSION "0.7.4-k" +#define DRV_VERSION "0.7.5-k" #define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver" const char ice_drv_ver[] = DRV_VERSION; static const char ice_driver_string[] = DRV_SUMMARY; -- GitLab From 0eba31ef5c8913adfd103c45c32d4856f1aa85cc Mon Sep 17 00:00:00 2001 From: Lucas Bates Date: Mon, 29 Jul 2019 19:18:12 -0400 Subject: [PATCH 1486/7155] tc-testing: Clarify the use of tdc's -d option The -d command line argument to tdc requires the name of a physical device on the system where the tests will be run. If -d has not been used, tdc will skip tests that require a physical device. This patch is intended to better document what the -d option does and how it is used. Signed-off-by: Lucas Bates Signed-off-by: David S. Miller --- tools/testing/selftests/tc-testing/README | 4 +++- tools/testing/selftests/tc-testing/tdc.py | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/tc-testing/README b/tools/testing/selftests/tc-testing/README index 22e5da9008fd..b0954c873e2f 100644 --- a/tools/testing/selftests/tc-testing/README +++ b/tools/testing/selftests/tc-testing/README @@ -128,7 +128,9 @@ optional arguments: -v, --verbose Show the commands that are being run -N, --notap Suppress tap results for command under test -d DEVICE, --device DEVICE - Execute the test case in flower category + Execute test cases that use a physical device, where + DEVICE is its name. (If not defined, tests that require + a physical device will be skipped) -P, --pause Pause execution just before post-suite stage selection: diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py index f04321ace9fb..e566c70e64a1 100755 --- a/tools/testing/selftests/tc-testing/tdc.py +++ b/tools/testing/selftests/tc-testing/tdc.py @@ -356,12 +356,14 @@ def test_runner(pm, args, filtered_tests): time.sleep(2) for tidx in testlist: if "flower" in tidx["category"] and args.device == None: + errmsg = "Tests using the DEV2 variable must define the name of a " + errmsg += "physical NIC with the -d option when running tdc.\n" + errmsg += "Test has been skipped." if args.verbose > 1: - print('Not executing test {} {} because DEV2 not defined'. - format(tidx['id'], tidx['name'])) + print(errmsg) res = TestResult(tidx['id'], tidx['name']) res.set_result(ResultState.skip) - res.set_errormsg('Not executed because DEV2 is not defined') + res.set_errormsg(errmsg) tsr.add_resultdata(res) continue try: @@ -499,7 +501,9 @@ def set_args(parser): choices=['none', 'xunit', 'tap'], help='Specify the format for test results. (Default: TAP)') parser.add_argument('-d', '--device', - help='Execute the test case in flower category') + help='Execute test cases that use a physical device, ' + + 'where DEVICE is its name. (If not defined, tests ' + + 'that require a physical device will be skipped)') parser.add_argument( '-P', '--pause', action='store_true', help='Pause execution just before post-suite stage') -- GitLab From 3247b272048ffefc12c7dcfa3169bd03047a49bc Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Tue, 30 Jul 2019 15:20:41 +0300 Subject: [PATCH 1487/7155] net: bridge: mcast: add delete due to fast-leave mdb flag In user-space there's no way to distinguish why an mdb entry was deleted and that is a problem for daemons which would like to keep the mdb in sync with remote ends (e.g. mlag) but would also like to converge faster. In almost all cases we'd like to age-out the remote entry for performance and convergence reasons except when fast-leave is enabled. In that case we want explicit immediate remote delete, thus add mdb flag which is set only when the entry is being deleted due to fast-leave. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- include/uapi/linux/if_bridge.h | 1 + net/bridge/br_mdb.c | 2 ++ net/bridge/br_multicast.c | 2 +- net/bridge/br_private.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 773e476a8e54..1b3c2b643a02 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -237,6 +237,7 @@ struct br_mdb_entry { #define MDB_PERMANENT 1 __u8 state; #define MDB_FLAGS_OFFLOAD (1 << 0) +#define MDB_FLAGS_FAST_LEAVE (1 << 1) __u8 flags; __u16 vid; struct { diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index bf6acd34234d..428af1abf8cc 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -60,6 +60,8 @@ static void __mdb_entry_fill_flags(struct br_mdb_entry *e, unsigned char flags) e->flags = 0; if (flags & MDB_PG_FLAGS_OFFLOAD) e->flags |= MDB_FLAGS_OFFLOAD; + if (flags & MDB_PG_FLAGS_FAST_LEAVE) + e->flags |= MDB_FLAGS_FAST_LEAVE; } static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 3d8deac2353d..3d4b2817687f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1393,7 +1393,7 @@ br_multicast_leave_group(struct net_bridge *br, del_timer(&p->timer); kfree_rcu(p, rcu); br_mdb_notify(br->dev, port, group, RTM_DELMDB, - p->flags); + p->flags | MDB_PG_FLAGS_FAST_LEAVE); if (!mp->ports && !mp->host_joined && netif_running(br->dev)) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e8cf03b43b7d..c4fd307fbfdc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -199,6 +199,7 @@ struct net_bridge_fdb_entry { #define MDB_PG_FLAGS_PERMANENT BIT(0) #define MDB_PG_FLAGS_OFFLOAD BIT(1) +#define MDB_PG_FLAGS_FAST_LEAVE BIT(2) struct net_bridge_port_group { struct net_bridge_port *port; -- GitLab From 45640a383adc83331250f6fc7bf7e2c04f3e7879 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Jul 2019 18:47:20 +0200 Subject: [PATCH 1488/7155] mfd: ab3100: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Linus Walleij Cc: Lee Jones Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20190706164722.18766-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/ab3100-core.c | 45 ++++++--------------------------------- drivers/mfd/ab3100-otp.c | 21 ++++++------------ 2 files changed, 13 insertions(+), 53 deletions(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index e350ab64238e..9f3dbc31d3e9 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -575,58 +575,27 @@ static const struct file_operations ab3100_get_set_reg_fops = { .llseek = noop_llseek, }; -static struct dentry *ab3100_dir; -static struct dentry *ab3100_reg_file; static struct ab3100_get_set_reg_priv ab3100_get_priv; -static struct dentry *ab3100_get_reg_file; static struct ab3100_get_set_reg_priv ab3100_set_priv; -static struct dentry *ab3100_set_reg_file; static void ab3100_setup_debugfs(struct ab3100 *ab3100) { - int err; + struct dentry *ab3100_dir; ab3100_dir = debugfs_create_dir("ab3100", NULL); - if (!ab3100_dir) - goto exit_no_debugfs; - ab3100_reg_file = debugfs_create_file("registers", - S_IRUGO, ab3100_dir, ab3100, - &ab3100_registers_fops); - if (!ab3100_reg_file) { - err = -ENOMEM; - goto exit_destroy_dir; - } + debugfs_create_file("registers", S_IRUGO, ab3100_dir, ab3100, + &ab3100_registers_fops); ab3100_get_priv.ab3100 = ab3100; ab3100_get_priv.mode = false; - ab3100_get_reg_file = debugfs_create_file("get_reg", - S_IWUSR, ab3100_dir, &ab3100_get_priv, - &ab3100_get_set_reg_fops); - if (!ab3100_get_reg_file) { - err = -ENOMEM; - goto exit_destroy_reg; - } + debugfs_create_file("get_reg", S_IWUSR, ab3100_dir, &ab3100_get_priv, + &ab3100_get_set_reg_fops); ab3100_set_priv.ab3100 = ab3100; ab3100_set_priv.mode = true; - ab3100_set_reg_file = debugfs_create_file("set_reg", - S_IWUSR, ab3100_dir, &ab3100_set_priv, - &ab3100_get_set_reg_fops); - if (!ab3100_set_reg_file) { - err = -ENOMEM; - goto exit_destroy_get_reg; - } - return; - - exit_destroy_get_reg: - debugfs_remove(ab3100_get_reg_file); - exit_destroy_reg: - debugfs_remove(ab3100_reg_file); - exit_destroy_dir: - debugfs_remove(ab3100_dir); - exit_no_debugfs: - return; + debugfs_create_file("set_reg", S_IWUSR, ab3100_dir, &ab3100_set_priv, + &ab3100_get_set_reg_fops); } #else static inline void ab3100_setup_debugfs(struct ab3100 *ab3100) diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index b3f8d359f409..c4751fb9bc22 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c @@ -122,17 +122,11 @@ static const struct file_operations ab3100_otp_operations = { .release = single_release, }; -static int __init ab3100_otp_init_debugfs(struct device *dev, - struct ab3100_otp *otp) +static void __init ab3100_otp_init_debugfs(struct device *dev, + struct ab3100_otp *otp) { otp->debugfs = debugfs_create_file("ab3100_otp", S_IFREG | S_IRUGO, - NULL, otp, - &ab3100_otp_operations); - if (!otp->debugfs) { - dev_err(dev, "AB3100 debugfs OTP file registration failed!\n"); - return -ENOENT; - } - return 0; + NULL, otp, &ab3100_otp_operations); } static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp) @@ -141,10 +135,9 @@ static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp) } #else /* Compile this out if debugfs not selected */ -static inline int __init ab3100_otp_init_debugfs(struct device *dev, - struct ab3100_otp *otp) +static inline void __init ab3100_otp_init_debugfs(struct device *dev, + struct ab3100_otp *otp) { - return 0; } static inline void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp) @@ -211,9 +204,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) } /* debugfs entries */ - err = ab3100_otp_init_debugfs(&pdev->dev, otp); - if (err) - goto err; + ab3100_otp_init_debugfs(&pdev->dev, otp); return 0; -- GitLab From b11f75d032d8706bd39390a63107828985a61de3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Jul 2019 18:47:21 +0200 Subject: [PATCH 1489/7155] mfd: ab8500: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Linus Walleij Cc: Lee Jones Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20190706164722.18766-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/ab8500-debugfs.c | 324 +++++++++++------------------------ 1 file changed, 98 insertions(+), 226 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index d24c6ecccb88..567a34b073dd 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2644,12 +2644,10 @@ static const struct file_operations ab8500_hwreg_fops = { .owner = THIS_MODULE, }; -static struct dentry *ab8500_dir; -static struct dentry *ab8500_gpadc_dir; - static int ab8500_debug_probe(struct platform_device *plf) { - struct dentry *file; + struct dentry *ab8500_dir; + struct dentry *ab8500_gpadc_dir; struct ab8500 *ab8500; struct resource *res; @@ -2694,47 +2692,22 @@ static int ab8500_debug_probe(struct platform_device *plf) } ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); - if (!ab8500_dir) - goto err; ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, ab8500_dir); - if (!ab8500_gpadc_dir) - goto err; - - file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir, - &plf->dev, &ab8500_bank_registers_fops); - if (!file) - goto err; - - file = debugfs_create_file("all-banks", S_IRUGO, ab8500_dir, - &plf->dev, &ab8500_all_banks_fops); - if (!file) - goto err; - - file = debugfs_create_file("register-bank", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_dir, &plf->dev, &ab8500_bank_fops); - if (!file) - goto err; - - file = debugfs_create_file("register-address", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_dir, &plf->dev, &ab8500_address_fops); - if (!file) - goto err; - - file = debugfs_create_file("register-value", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_dir, &plf->dev, &ab8500_val_fops); - if (!file) - goto err; - - file = debugfs_create_file("irq-subscribe", - (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir, - &plf->dev, &ab8500_subscribe_fops); - if (!file) - goto err; + + debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir, + &plf->dev, &ab8500_bank_registers_fops); + debugfs_create_file("all-banks", S_IRUGO, ab8500_dir, + &plf->dev, &ab8500_all_banks_fops); + debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_bank_fops); + debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_address_fops); + debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_val_fops); + debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_subscribe_fops); if (is_ab8500(ab8500)) { debug_ranges = ab8500_debug_ranges; @@ -2750,194 +2723,93 @@ static int ab8500_debug_probe(struct platform_device *plf) num_interrupt_lines = AB8540_NR_IRQS; } - file = debugfs_create_file("interrupts", (S_IRUGO), ab8500_dir, - &plf->dev, &ab8500_interrupts_fops); - if (!file) - goto err; - - file = debugfs_create_file("irq-unsubscribe", - (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir, - &plf->dev, &ab8500_unsubscribe_fops); - if (!file) - goto err; - - file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_dir, &plf->dev, &ab8500_hwreg_fops); - if (!file) - goto err; - - file = debugfs_create_file("all-modem-registers", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_dir, &plf->dev, &ab8500_modem_fops); - if (!file) - goto err; - - file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_bat_ctrl_fops); - if (!file) - goto err; - - file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, - &plf->dev, &ab8500_gpadc_btemp_ball_fops); - if (!file) - goto err; - - file = debugfs_create_file("main_charger_v", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_charger_v_fops); - if (!file) - goto err; - - file = debugfs_create_file("acc_detect1", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_acc_detect1_fops); - if (!file) - goto err; - - file = debugfs_create_file("acc_detect2", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_acc_detect2_fops); - if (!file) - goto err; - - file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_aux1_fops); - if (!file) - goto err; - - file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_aux2_fops); - if (!file) - goto err; - - file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_bat_v_fops); - if (!file) - goto err; - - file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_vbus_v_fops); - if (!file) - goto err; - - file = debugfs_create_file("main_charger_c", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_main_charger_c_fops); - if (!file) - goto err; - - file = debugfs_create_file("usb_charger_c", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, - &plf->dev, &ab8500_gpadc_usb_charger_c_fops); - if (!file) - goto err; - - file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_bk_bat_v_fops); - if (!file) - goto err; - - file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_die_temp_fops); - if (!file) - goto err; - - file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_usb_id_fops); - if (!file) - goto err; - + debugfs_create_file("interrupts", (S_IRUGO), ab8500_dir, &plf->dev, + &ab8500_interrupts_fops); + debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); + debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir, + &plf->dev, &ab8500_hwreg_fops); + debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_dir, &plf->dev, &ab8500_modem_fops); + debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_bat_ctrl_fops); + debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_btemp_ball_fops); + debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_main_charger_v_fops); + debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_acc_detect1_fops); + debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_acc_detect2_fops); + debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_aux1_fops); + debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_aux2_fops); + debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_main_bat_v_fops); + debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_vbus_v_fops); + debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_main_charger_c_fops); + debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_usb_charger_c_fops); + debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_bk_bat_v_fops); + debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_die_temp_fops); + debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_usb_id_fops); if (is_ab8540(ab8500)) { - file = debugfs_create_file("xtal_temp", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_xtal_temp_fops); - if (!file) - goto err; - file = debugfs_create_file("vbattruemeas", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_vbat_true_meas_fops); - if (!file) - goto err; - file = debugfs_create_file("batctrl_and_ibat", - (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, - &plf->dev, - &ab8540_gpadc_bat_ctrl_and_ibat_fops); - if (!file) - goto err; - file = debugfs_create_file("vbatmeas_and_ibat", - (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, &plf->dev, - &ab8540_gpadc_vbat_meas_and_ibat_fops); - if (!file) - goto err; - file = debugfs_create_file("vbattruemeas_and_ibat", - (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, - &plf->dev, - &ab8540_gpadc_vbat_true_meas_and_ibat_fops); - if (!file) - goto err; - file = debugfs_create_file("battemp_and_ibat", - (S_IRUGO | S_IWUGO), - ab8500_gpadc_dir, - &plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops); - if (!file) - goto err; - file = debugfs_create_file("otp_calib", - (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, - &plf->dev, &ab8540_gpadc_otp_calib_fops); - if (!file) - goto err; + debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_xtal_temp_fops); + debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_vbat_true_meas_fops); + debugfs_create_file("batctrl_and_ibat", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_bat_ctrl_and_ibat_fops); + debugfs_create_file("vbatmeas_and_ibat", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_vbat_meas_and_ibat_fops); + debugfs_create_file("vbattruemeas_and_ibat", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_vbat_true_meas_and_ibat_fops); + debugfs_create_file("battemp_and_ibat", (S_IRUGO | S_IWUGO), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_bat_temp_and_ibat_fops); + debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8540_gpadc_otp_calib_fops); } - file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_avg_sample_fops); - if (!file) - goto err; - - file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_trig_edge_fops); - if (!file) - goto err; - - file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_trig_timer_fops); - if (!file) - goto err; - - file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP), - ab8500_gpadc_dir, &plf->dev, - &ab8500_gpadc_conv_type_fops); - if (!file) - goto err; + debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_avg_sample_fops); + debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_trig_edge_fops); + debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_trig_timer_fops); + debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP), + ab8500_gpadc_dir, &plf->dev, + &ab8500_gpadc_conv_type_fops); return 0; - -err: - debugfs_remove_recursive(ab8500_dir); - dev_err(&plf->dev, "failed to create debugfs entries.\n"); - - return -ENOMEM; } static struct platform_driver ab8500_debug_driver = { -- GitLab From dc607f6bbafd2d8bf1d518c346560ba9577e402f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Jul 2019 18:47:22 +0200 Subject: [PATCH 1490/7155] mfd: aat2870: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Lee Jones Link: https://lore.kernel.org/r/20190706164722.18766-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/aat2870-core.c | 13 ++----------- include/linux/mfd/aat2870.h | 1 - 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 9f58cb2d3789..78ee4b28fca2 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -321,18 +321,9 @@ static const struct file_operations aat2870_reg_fops = { static void aat2870_init_debugfs(struct aat2870_data *aat2870) { aat2870->dentry_root = debugfs_create_dir("aat2870", NULL); - if (!aat2870->dentry_root) { - dev_warn(aat2870->dev, - "Failed to create debugfs root directory\n"); - return; - } - aat2870->dentry_reg = debugfs_create_file("regs", 0644, - aat2870->dentry_root, - aat2870, &aat2870_reg_fops); - if (!aat2870->dentry_reg) - dev_warn(aat2870->dev, - "Failed to create debugfs register file\n"); + debugfs_create_file("regs", 0644, aat2870->dentry_root, aat2870, + &aat2870_reg_fops); } #else diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h index af7267c480ee..2445842d482d 100644 --- a/include/linux/mfd/aat2870.h +++ b/include/linux/mfd/aat2870.h @@ -136,7 +136,6 @@ struct aat2870_data { /* for debugfs */ struct dentry *dentry_root; - struct dentry *dentry_reg; }; struct aat2870_subdev_info { -- GitLab From 49281a222ac42724b94f6c874f43a284ec58d37e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 1 Aug 2019 00:28:26 +0200 Subject: [PATCH 1491/7155] gpio: of: Fix hard-assigned valid_mask for OF case The recent refactoring to break out OF code to its own file contained a bug letting the need_valid_mask be overridden by the need of the device tree range check, and if there were no ranges, but device tree was active and the reserved GPIO used in another way, things likely crash. Cc: Mark Brown Cc: Bjorn Andersson Cc: Stephen Boyd Fixes: f626d6dfb709 ("gpio: of: Break out OF-only code") Reported-by: Mark Brown Suggested-by: Stephen Boyd Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- drivers/gpio/gpiolib-of.h | 4 ++-- drivers/gpio/gpiolib.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index b10d04dd9296..e39b4290b80c 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -87,7 +87,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, * @dev: the device for the GPIO provider * @return: true if the valid mask needs to be set */ -bool of_gpio_need_valid_mask(struct gpio_chip *gc) +bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { int size; struct device_node *np = gc->of_node; diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 34954921d96e..454d1658ee2d 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -16,7 +16,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, int of_gpiochip_add(struct gpio_chip *gc); void of_gpiochip_remove(struct gpio_chip *gc); int of_gpio_get_count(struct device *dev, const char *con_id); -bool of_gpio_need_valid_mask(struct gpio_chip *gc); +bool of_gpio_need_valid_mask(const struct gpio_chip *gc); #else static inline struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, @@ -36,7 +36,7 @@ static inline int of_gpio_get_count(struct device *dev, const char *con_id) { return 0; } -static inline bool of_gpio_need_valid_mask(struct gpio_chip *gc) +static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { return false; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f83870a18ae7..20f13129cdaa 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -363,8 +363,8 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { - if (IS_ENABLED(CONFIG_OF_GPIO)) - gc->need_valid_mask = of_gpio_need_valid_mask(gc); + if (of_gpio_need_valid_mask(gc)) + gc->need_valid_mask = true; if (!gc->need_valid_mask) return 0; -- GitLab From e2557157a9dd47b0335cac325b4eb438db2320d2 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Jul 2019 16:54:05 +0800 Subject: [PATCH 1492/7155] dt-bindings: reset: imx7: Add support for i.MX8MM i.MX8MM can reuse i.MX8MQ's reset driver, update the compatible property and related info to support i.MX8MM. Signed-off-by: Anson Huang Signed-off-by: Philipp Zabel --- .../bindings/reset/fsl,imx7-src.txt | 6 ++-- include/dt-bindings/reset/imx8mq-reset.h | 28 +++++++++---------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt index 13e095182db4..c2489e41a801 100644 --- a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt +++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt @@ -8,6 +8,7 @@ Required properties: - compatible: - For i.MX7 SoCs should be "fsl,imx7d-src", "syscon" - For i.MX8MQ SoCs should be "fsl,imx8mq-src", "syscon" + - For i.MX8MM SoCs should be "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon" - reg: should be register base and length as documented in the datasheet - interrupts: Should contain SRC interrupt @@ -46,5 +47,6 @@ Example: For list of all valid reset indices see - for i.MX7 and - for i.MX8MQ + for i.MX7, + for i.MX8MQ and + for i.MX8MM diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h index 57c592498aa0..f17ef2a972f6 100644 --- a/include/dt-bindings/reset/imx8mq-reset.h +++ b/include/dt-bindings/reset/imx8mq-reset.h @@ -38,26 +38,26 @@ #define IMX8MQ_RESET_PCIEPHY_PERST 27 #define IMX8MQ_RESET_PCIE_CTRL_APPS_EN 28 #define IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF 29 -#define IMX8MQ_RESET_HDMI_PHY_APB_RESET 30 +#define IMX8MQ_RESET_HDMI_PHY_APB_RESET 30 /* i.MX8MM does NOT support */ #define IMX8MQ_RESET_DISP_RESET 31 #define IMX8MQ_RESET_GPU_RESET 32 #define IMX8MQ_RESET_VPU_RESET 33 -#define IMX8MQ_RESET_PCIEPHY2 34 -#define IMX8MQ_RESET_PCIEPHY2_PERST 35 -#define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN 36 -#define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF 37 -#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET 38 -#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET 39 -#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET 40 -#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET 41 -#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET 42 -#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET 43 +#define IMX8MQ_RESET_PCIEPHY2 34 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_PCIEPHY2_PERST 35 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_PCIE2_CTRL_APPS_EN 36 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF 37 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI1_CORE_RESET 38 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET 39 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI1_ESC_RESET 40 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI2_CORE_RESET 41 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET 42 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_MIPI_CSI2_ESC_RESET 43 /* i.MX8MM does NOT support */ #define IMX8MQ_RESET_DDRC1_PRST 44 #define IMX8MQ_RESET_DDRC1_CORE_RESET 45 #define IMX8MQ_RESET_DDRC1_PHY_RESET 46 -#define IMX8MQ_RESET_DDRC2_PRST 47 -#define IMX8MQ_RESET_DDRC2_CORE_RESET 48 -#define IMX8MQ_RESET_DDRC2_PHY_RESET 49 +#define IMX8MQ_RESET_DDRC2_PRST 47 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_DDRC2_CORE_RESET 48 /* i.MX8MM does NOT support */ +#define IMX8MQ_RESET_DDRC2_PHY_RESET 49 /* i.MX8MM does NOT support */ #define IMX8MQ_RESET_NUM 50 -- GitLab From 942b4c10b11bced65c0e553d8355b58bb3d9cdb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Thu, 1 Aug 2019 10:20:59 +0200 Subject: [PATCH 1493/7155] dt-bindings: reset: Fix typo in imx8mq resets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the mipi dsi resets were called IMX8MQ_RESET_MIPI_DIS__ instead of IMX8MQ_RESET_MIPI_DSI__ Since they're DSI related this looks like a typo. This fixes the only in tree user as well to not break bisecting. Signed-off-by: Guido Günther Reviewed-by: Lucas Stach Signed-off-by: Philipp Zabel --- drivers/reset/reset-imx7.c | 12 ++++++------ include/dt-bindings/reset/imx8mq-reset.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index 3ecd770f910b..1443a55a0c29 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -169,9 +169,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = { [IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) }, [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) }, [IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) }, - [IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) }, - [IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) }, - [IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) }, + [IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) }, + [IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) }, + [IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) }, [IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) }, [IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) }, @@ -220,9 +220,9 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev, case IMX8MQ_RESET_PCIE_CTRL_APPS_EN: case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N: /* fallthrough */ + case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N: /* fallthrough */ + case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */ + case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */ case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */ case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */ value = assert ? 0 : bit; diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h index f17ef2a972f6..9a301082d361 100644 --- a/include/dt-bindings/reset/imx8mq-reset.h +++ b/include/dt-bindings/reset/imx8mq-reset.h @@ -31,9 +31,9 @@ #define IMX8MQ_RESET_OTG2_PHY_RESET 20 #define IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N 21 #define IMX8MQ_RESET_MIPI_DSI_RESET_N 22 -#define IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N 23 -#define IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N 24 -#define IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N 25 +#define IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N 23 +#define IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N 24 +#define IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N 25 #define IMX8MQ_RESET_PCIEPHY 26 #define IMX8MQ_RESET_PCIEPHY_PERST 27 #define IMX8MQ_RESET_PCIE_CTRL_APPS_EN 28 -- GitLab From 7c61ccf643a9aa308c96508dceb93afe2083afa5 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 1 Aug 2019 09:54:52 +0200 Subject: [PATCH 1494/7155] reset: reset-meson: update with SPDX Licence identifier Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 51 +------------------------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 5242e0679df7..7d05d766e1ea 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -1,58 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Amlogic Meson Reset Controller driver * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright (c) 2016 BayLibre, SAS. - * Author: Neil Armstrong - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * BSD LICENSE - * * Copyright (c) 2016 BayLibre, SAS. * Author: Neil Armstrong - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include -- GitLab From b16a0063654516bde54a95262d02207d79f1bf53 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 1 Aug 2019 09:54:53 +0200 Subject: [PATCH 1495/7155] dt-bindings: reset: amlogic,meson-gxbb-reset: update with SPDX Licence identifier Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- .../reset/amlogic,meson-gxbb-reset.h | 51 +------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h index 524d6077ac1b..ea5058618863 100644 --- a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h +++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h @@ -1,56 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright (c) 2016 BayLibre, SAS. * Author: Neil Armstrong - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * BSD LICENSE - * - * Copyright (c) 2016 BayLibre, SAS. - * Author: Neil Armstrong - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H #define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H -- GitLab From fb0d72c7ac5d1a3578e15cb56b4f453730790ba6 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 1 Aug 2019 09:54:54 +0200 Subject: [PATCH 1496/7155] dt-bindings: reset: amlogic,meson8b-reset: update with SPDX Licence identifier Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- .../dt-bindings/reset/amlogic,meson8b-reset.h | 51 +------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h index 614aff2c7aff..c614438bcbdb 100644 --- a/include/dt-bindings/reset/amlogic,meson8b-reset.h +++ b/include/dt-bindings/reset/amlogic,meson8b-reset.h @@ -1,56 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright (c) 2016 BayLibre, SAS. * Author: Neil Armstrong - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * BSD LICENSE - * - * Copyright (c) 2016 BayLibre, SAS. - * Author: Neil Armstrong - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H #define _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H -- GitLab From a342031cdd0818cb0fbcb44798211c7a02c7ca27 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:47 +0200 Subject: [PATCH 1497/7155] ASoC: create pcm for codec2codec links as well At the moment, codec to codec links uses an ephemeral variable for the struct snd_pcm_substream. Also the struct snd_soc_pcm_runtime does not have real struct snd_pcm. This might a problem if the functions used by a codec on codec to codec link expect these structures to exist, and keep on existing during the life of the codec. For example, it is the case of the hdmi-codec, which uses snd_pcm_add_chmap_ctls(). For the controls to works, the pcm and substream must to exist. This change is first step, it create pcm (and substreams) for codec to codec links, in the same way as dpcm backend links. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-5-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 42 ++++++++++++------------------------------ sound/soc/soc-pcm.c | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 06697b2d96b1..da11e44b01aa 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -447,16 +447,6 @@ static void snd_soc_flush_all_delayed_work(struct snd_soc_card *card) flush_delayed_work(&rtd->delayed_work); } -static void codec2codec_close_delayed_work(struct work_struct *work) -{ - /* - * Currently nothing to do for c2c links - * Since c2c links are internal nodes in the DAPM graph and - * don't interface with the outside world or application layer - * we don't have to do any special handling on close. - */ -} - #ifdef CONFIG_PM_SLEEP /* powers down audio subsystem for suspend */ int snd_soc_suspend(struct device *dev) @@ -1555,27 +1545,19 @@ static int soc_probe_link_dais(struct snd_soc_card *card, return ret; } - if (!dai_link->params) { - /* create the pcm */ - ret = soc_new_pcm(rtd, num); - if (ret < 0) { - dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", - dai_link->stream_name, ret); - return ret; - } - ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); - if (ret < 0) - return ret; - ret = soc_link_dai_pcm_new(rtd->codec_dais, - rtd->num_codecs, rtd); - if (ret < 0) - return ret; - } else { - INIT_DELAYED_WORK(&rtd->delayed_work, - codec2codec_close_delayed_work); + /* create the pcm */ + ret = soc_new_pcm(rtd, num); + if (ret < 0) { + dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", + dai_link->stream_name, ret); + return ret; } - - return 0; + ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); + if (ret < 0) + return ret; + ret = soc_link_dai_pcm_new(rtd->codec_dais, + rtd->num_codecs, rtd); + return ret; } static int soc_bind_aux_dev(struct snd_soc_card *card, int num) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fabeac164a6c..30264bc592f6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -678,6 +678,16 @@ static void close_delayed_work(struct work_struct *work) mutex_unlock(&rtd->pcm_mutex); } +static void codec2codec_close_delayed_work(struct work_struct *work) +{ + /* + * Currently nothing to do for c2c links + * Since c2c links are internal nodes in the DAPM graph and + * don't interface with the outside world or application layer + * we don't have to do any special handling on close. + */ +} + /* * Called by ALSA when a PCM substream is closed. Private data can be * freed here. The cpu DAI, codec DAI, machine and components are also @@ -3011,6 +3021,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) playback = rtd->dai_link->dpcm_playback; capture = rtd->dai_link->dpcm_capture; } else { + /* Adapt stream for codec2codec links */ + struct snd_soc_pcm_stream *cpu_capture = rtd->dai_link->params ? + &cpu_dai->driver->playback : &cpu_dai->driver->capture; + struct snd_soc_pcm_stream *cpu_playback = rtd->dai_link->params ? + &cpu_dai->driver->capture : &cpu_dai->driver->playback; + for_each_rtd_codec_dai(rtd, i, codec_dai) { if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) @@ -3019,6 +3035,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) capture = 1; } + + capture = capture && cpu_capture->channels_min; + playback = playback && cpu_playback->channels_min; } if (rtd->dai_link->playback_only) { @@ -3032,7 +3051,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) } /* create the PCM */ - if (rtd->dai_link->no_pcm) { + if (rtd->dai_link->params) { + snprintf(new_name, sizeof(new_name), "codec2codec(%s)", + rtd->dai_link->stream_name); + + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, + playback, capture, &pcm); + } else if (rtd->dai_link->no_pcm) { snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); @@ -3059,13 +3084,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); /* DAPM dai link stream work */ - INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); + if (rtd->dai_link->params) + INIT_DELAYED_WORK(&rtd->delayed_work, + codec2codec_close_delayed_work); + else + INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); pcm->nonatomic = rtd->dai_link->nonatomic; rtd->pcm = pcm; pcm->private_data = rtd; - if (rtd->dai_link->no_pcm) { + if (rtd->dai_link->no_pcm || rtd->dai_link->params) { if (playback) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; if (capture) -- GitLab From a72706ed8208ac3f72d1c3ebbc6509e368b0dcb0 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:48 +0200 Subject: [PATCH 1498/7155] ASoC: codec2codec: remove ephemeral variables Now that codec to codec links struct snd_soc_pcm_runtime have lasting pcm and substreams, let's use them. Alsa allocate and keep the struct snd_pcm_runtime as long as the link is powered. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-6-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 72 ++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2d183e2d23de..1c953a1b46ce 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3775,6 +3775,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_hw_params *params = NULL; const struct snd_soc_pcm_stream *config = NULL; + struct snd_pcm_runtime *runtime = NULL; unsigned int fmt; int ret = 0; @@ -3782,6 +3783,14 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, if (!params) return -ENOMEM; + runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); + if (!runtime) { + ret = -ENOMEM; + goto out; + } + + substream->runtime = runtime; + substream->stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; @@ -3808,6 +3817,8 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, sink->active++; } + substream->hw_opened = 1; + /* * Note: getting the config after .startup() gives a chance to * either party on the link to alter the configuration if @@ -3864,6 +3875,9 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, } out: + if (ret < 0) + kfree(runtime); + kfree(params); return ret; } @@ -3873,29 +3887,16 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, { struct snd_soc_dapm_path *path; struct snd_soc_dai *source, *sink; - struct snd_soc_pcm_runtime *rtd = w->priv; - struct snd_pcm_substream substream; - struct snd_pcm_runtime *runtime = NULL; - int ret = 0; + struct snd_pcm_substream *substream = w->priv; + int ret = 0, saved_stream = substream->stream; if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) return -EINVAL; - memset(&substream, 0, sizeof(substream)); - - /* Allocate a dummy snd_pcm_runtime for startup() and other ops() */ - runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); - if (!runtime) { - ret = -ENOMEM; - goto out; - } - substream.runtime = runtime; - substream.private_data = rtd; - switch (event) { case SND_SOC_DAPM_PRE_PMU: - ret = snd_soc_dai_link_event_pre_pmu(w, &substream); + ret = snd_soc_dai_link_event_pre_pmu(w, substream); if (ret < 0) goto out; @@ -3926,40 +3927,45 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ret = 0; } - substream.stream = SNDRV_PCM_STREAM_CAPTURE; + substream->stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; - snd_soc_dai_hw_free(source, &substream); + snd_soc_dai_hw_free(source, substream); } - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - snd_soc_dai_hw_free(sink, &substream); + snd_soc_dai_hw_free(sink, substream); } - substream.stream = SNDRV_PCM_STREAM_CAPTURE; + substream->stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; source->active--; - snd_soc_dai_shutdown(source, &substream); + snd_soc_dai_shutdown(source, substream); } - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; sink->active--; - snd_soc_dai_shutdown(sink, &substream); + snd_soc_dai_shutdown(sink, substream); } break; + case SND_SOC_DAPM_POST_PMD: + kfree(substream->runtime); + break; + default: WARN(1, "Unknown event %d\n", event); ret = -EINVAL; } out: - kfree(runtime); + /* Restore the substream direction */ + substream->stream = saved_stream; return ret; } @@ -4082,9 +4088,11 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, } static struct snd_soc_dapm_widget * -snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, +snd_soc_dapm_new_dai(struct snd_soc_card *card, + struct snd_pcm_substream *substream, char *id) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dapm_widget template; struct snd_soc_dapm_widget *w; const char **w_param_text; @@ -4103,7 +4111,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, template.name = link_name; template.event = snd_soc_dai_link_event; template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD; + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD; template.kcontrol_news = NULL; /* allocate memory for control, only in case of multiple configs */ @@ -4138,7 +4146,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, goto outfree_kcontrol_news; } - w->priv = rtd; + w->priv = substream; return w; @@ -4260,6 +4268,8 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, struct snd_soc_dai *codec_dai; struct snd_soc_dapm_widget *playback = NULL, *capture = NULL; struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu; + struct snd_pcm_substream *substream; + struct snd_pcm_str *streams = rtd->pcm->streams; int i; if (rtd->dai_link->params) { @@ -4278,7 +4288,8 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, if (playback_cpu && codec) { if (!playback) { - playback = snd_soc_dapm_new_dai(card, rtd, + substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + playback = snd_soc_dapm_new_dai(card, substream, "playback"); if (IS_ERR(playback)) { dev_err(rtd->dev, @@ -4307,7 +4318,8 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, if (codec && capture_cpu) { if (!capture) { - capture = snd_soc_dapm_new_dai(card, rtd, + substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; + capture = snd_soc_dapm_new_dai(card, substream, "capture"); if (IS_ERR(capture)) { dev_err(rtd->dev, -- GitLab From 9de98628c895d15427138073986eab1e3ce39cb4 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 25 Jul 2019 18:59:49 +0200 Subject: [PATCH 1499/7155] ASoC: codec2codec: fill some of the runtime stream parameters Set the information provided struct snd_soc_pcm_stream in the struct snd_pcm_runtime of the codec to codec link. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20190725165949.29699-7-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1c953a1b46ce..e16838e1bda2 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3874,6 +3874,11 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, dapm_update_dai_unlocked(substream, params, sink); } + runtime->format = params_format(params); + runtime->subformat = params_subformat(params); + runtime->channels = params_channels(params); + runtime->rate = params_rate(params); + out: if (ret < 0) kfree(runtime); -- GitLab From d8701fae95c0e6cb587b293cb8e01acc96dd1095 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 15:17:14 +0200 Subject: [PATCH 1500/7155] ASoC: Intel: SoC: skylake: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Also, if a debugfs call fails, userspace is notified with an error in the log, so no need to log the error again. Cc: Pierre-Louis Bossart Cc: Liam Girdwood Cc: Jie Yang Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: alsa-devel@alsa-project.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731131716.9764-1-gregkh@linuxfoundation.org Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-debug.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index fb232428109f..212370bf704c 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -164,10 +164,8 @@ void skl_debug_init_module(struct skl_debug *d, struct snd_soc_dapm_widget *w, struct skl_module_cfg *mconfig) { - if (!debugfs_create_file(w->name, 0444, - d->modules, mconfig, - &mcfg_fops)) - dev_err(d->dev, "%s: module debugfs init failed\n", w->name); + debugfs_create_file(w->name, 0444, d->modules, mconfig, + &mcfg_fops); } static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, @@ -224,34 +222,18 @@ struct skl_debug *skl_debugfs_init(struct skl_dev *skl) return NULL; /* create the debugfs dir with platform component's debugfs as parent */ - d->fs = debugfs_create_dir("dsp", - skl->component->debugfs_root); - if (IS_ERR(d->fs) || !d->fs) { - dev_err(&skl->pci->dev, "debugfs root creation failed\n"); - return NULL; - } + d->fs = debugfs_create_dir("dsp", skl->component->debugfs_root); d->skl = skl; d->dev = &skl->pci->dev; /* now create the module dir */ d->modules = debugfs_create_dir("modules", d->fs); - if (IS_ERR(d->modules) || !d->modules) { - dev_err(&skl->pci->dev, "modules debugfs create failed\n"); - goto err; - } - if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, - &soft_regs_ctrl_fops)) { - dev_err(d->dev, "fw soft regs control debugfs init failed\n"); - goto err; - } + debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, + &soft_regs_ctrl_fops); return d; - -err: - debugfs_remove_recursive(d->fs); - return NULL; } void skl_debugfs_exit(struct skl_dev *skl) -- GitLab From fee531d6fc49b9a616525e30955c4cf3b403f632 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 15:17:15 +0200 Subject: [PATCH 1501/7155] ASoC: core: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Also, there is no need to store the individual debugfs file name, just remove the whole directory all at once, saving a local variable. Note, the soc-pcm "state" file has now moved to a subdirectory, as it is only a good idea to save the dentries for debugfs directories, not individual files, as the individual file debugfs functions are changing to not return a dentry. Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: alsa-devel@alsa-project.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731131716.9764-2-gregkh@linuxfoundation.org Signed-off-by: Mark Brown --- include/sound/soc.h | 1 - sound/soc/soc-core.c | 43 ++++++------------------------------------- sound/soc/soc-dapm.c | 30 ++++-------------------------- sound/soc/soc-pcm.c | 14 ++++---------- 4 files changed, 14 insertions(+), 74 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index d770606732cd..f0797792dd8d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1220,7 +1220,6 @@ struct snd_soc_card { #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_card_root; - struct dentry *debugfs_pop_time; #endif u32 pop_time; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index da11e44b01aa..ed66d2c68d10 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -165,13 +165,6 @@ static void soc_init_component_debugfs(struct snd_soc_component *component) component->card->debugfs_card_root); } - if (IS_ERR(component->debugfs_root)) { - dev_warn(component->dev, - "ASoC: Failed to create component debugfs directory: %ld\n", - PTR_ERR(component->debugfs_root)); - return; - } - snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component), component->debugfs_root); } @@ -215,32 +208,15 @@ DEFINE_SHOW_ATTRIBUTE(component_list); static void soc_init_card_debugfs(struct snd_soc_card *card) { - if (!snd_soc_debugfs_root) - return; - card->debugfs_card_root = debugfs_create_dir(card->name, snd_soc_debugfs_root); - if (IS_ERR(card->debugfs_card_root)) { - dev_warn(card->dev, - "ASoC: Failed to create card debugfs directory: %ld\n", - PTR_ERR(card->debugfs_card_root)); - card->debugfs_card_root = NULL; - return; - } - card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, - card->debugfs_card_root, - &card->pop_time); - if (IS_ERR(card->debugfs_pop_time)) - dev_warn(card->dev, - "ASoC: Failed to create pop time debugfs file: %ld\n", - PTR_ERR(card->debugfs_pop_time)); + debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root, + &card->pop_time); } static void soc_cleanup_card_debugfs(struct snd_soc_card *card) { - if (!card->debugfs_card_root) - return; debugfs_remove_recursive(card->debugfs_card_root); card->debugfs_card_root = NULL; } @@ -248,19 +224,12 @@ static void soc_cleanup_card_debugfs(struct snd_soc_card *card) static void snd_soc_debugfs_init(void) { snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); - if (IS_ERR_OR_NULL(snd_soc_debugfs_root)) { - pr_warn("ASoC: Failed to create debugfs directory\n"); - snd_soc_debugfs_root = NULL; - return; - } - if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, - &dai_list_fops)) - pr_warn("ASoC: Failed to create DAI list debugfs file\n"); + debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, + &dai_list_fops); - if (!debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL, - &component_list_fops)) - pr_warn("ASoC: Failed to create component list debugfs file\n"); + debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL, + &component_list_fops); } static void snd_soc_debugfs_exit(void) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e16838e1bda2..d93c1038fab0 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2154,50 +2154,28 @@ static const struct file_operations dapm_bias_fops = { void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent) { - struct dentry *d; - if (!parent || IS_ERR(parent)) return; dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); - if (IS_ERR(dapm->debugfs_dapm)) { - dev_warn(dapm->dev, - "ASoC: Failed to create DAPM debugfs directory %ld\n", - PTR_ERR(dapm->debugfs_dapm)); - return; - } - - d = debugfs_create_file("bias_level", 0444, - dapm->debugfs_dapm, dapm, - &dapm_bias_fops); - if (IS_ERR(d)) - dev_warn(dapm->dev, - "ASoC: Failed to create bias level debugfs file: %ld\n", - PTR_ERR(d)); + debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm, + &dapm_bias_fops); } static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) { struct snd_soc_dapm_context *dapm = w->dapm; - struct dentry *d; if (!dapm->debugfs_dapm || !w->name) return; - d = debugfs_create_file(w->name, 0444, - dapm->debugfs_dapm, w, - &dapm_widget_power_fops); - if (IS_ERR(d)) - dev_warn(w->dapm->dev, - "ASoC: Failed to create %s debugfs file: %ld\n", - w->name, PTR_ERR(d)); + debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w, + &dapm_widget_power_fops); } static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) { - if (!dapm->debugfs_dapm) - return; debugfs_remove_recursive(dapm->debugfs_dapm); dapm->debugfs_dapm = NULL; } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 30264bc592f6..ce7297c37537 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1205,9 +1205,9 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, stream ? "<-" : "->", be->dai_link->name); #ifdef CONFIG_DEBUG_FS - if (fe->debugfs_dpcm_root) - dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644, - fe->debugfs_dpcm_root, &dpcm->state); + dpcm->debugfs_state = debugfs_create_dir(be->dai_link->name, + fe->debugfs_dpcm_root); + debugfs_create_u32("state", 0644, dpcm->debugfs_state, &dpcm->state); #endif return 1; } @@ -1262,7 +1262,7 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) dpcm_be_reparent(fe, dpcm->be, stream); #ifdef CONFIG_DEBUG_FS - debugfs_remove(dpcm->debugfs_state); + debugfs_remove_recursive(dpcm->debugfs_state); #endif spin_lock_irqsave(&fe->card->dpcm_lock, flags); list_del(&dpcm->list_be); @@ -3415,12 +3415,6 @@ void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, rtd->card->debugfs_card_root); - if (!rtd->debugfs_dpcm_root) { - dev_dbg(rtd->dev, - "ASoC: Failed to create dpcm debugfs directory %s\n", - rtd->dai_link->name); - return; - } debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, rtd, &dpcm_state_fops); -- GitLab From 3ff3a4f657b3fab2d56247983c2ebed180ef2fbb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 15:17:16 +0200 Subject: [PATCH 1502/7155] ASoC: SOF: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Also, if a debugfs call fails, userspace is notified with an error in the log, so no need to log the error again. Because we no longer need to check the return value, there's no need to save the dentry returned by debugfs. Just use the dentry in the file pointer if we really need to figure out the "name" of the file being opened. Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Ranjani Sridharan Cc: Pierre-Louis Bossart Cc: alsa-devel@alsa-project.org Signed-off-by: Greg Kroah-Hartman Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20190731131716.9764-3-gregkh@linuxfoundation.org Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 49 +++++++++++++++------------------------- sound/soc/sof/sof-priv.h | 1 - sound/soc/sof/trace.c | 9 ++------ 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 2388477a965e..40940b2fe9d5 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -128,6 +128,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, unsigned long ipc_duration_ms = 0; bool flood_duration_test = false; unsigned long ipc_count = 0; + struct dentry *dentry; int err; #endif size_t size; @@ -149,11 +150,12 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, * ipc_duration_ms test floods the DSP for the time specified * in the debugfs entry. */ - if (strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") && - strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) + dentry = file->f_path.dentry; + if (strcmp(dentry->d_name.name, "ipc_flood_count") && + strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) return -EINVAL; - if (!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) + if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) flood_duration_test = true; /* test completion criterion */ @@ -219,6 +221,7 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, { struct snd_sof_dfsentry *dfse = file->private_data; struct snd_sof_dev *sdev = dfse->sdev; + struct dentry *dentry; loff_t pos = *ppos; size_t size_ret; int skip = 0; @@ -226,8 +229,9 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, u8 *buf; #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - if ((!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") || - !strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) && + dentry = file->f_path.dentry; + if ((!strcmp(dentry->d_name.name, "ipc_flood_count") || + !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) && dfse->cache_buf) { if (*ppos) return 0; @@ -290,8 +294,7 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, if (!pm_runtime_active(sdev->dev) && dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) { dev_err(sdev->dev, - "error: debugfs entry %s cannot be read in DSP D3\n", - dfse->dfsentry->d_name.name); + "error: debugfs entry cannot be read in DSP D3\n"); kfree(buf); return -EINVAL; } @@ -356,17 +359,11 @@ int snd_sof_debugfs_io_item(struct snd_sof_dev *sdev, } #endif - dfse->dfsentry = debugfs_create_file(name, 0444, sdev->debugfs_root, - dfse, &sof_dfs_fops); - if (!dfse->dfsentry) { - /* can't rely on debugfs, only log error and keep going */ - dev_err(sdev->dev, "error: cannot create debugfs entry %s\n", - name); - } else { - /* add to dfsentry list */ - list_add(&dfse->list, &sdev->dfsentry_list); + debugfs_create_file(name, 0444, sdev->debugfs_root, dfse, + &sof_dfs_fops); - } + /* add to dfsentry list */ + list_add(&dfse->list, &sdev->dfsentry_list); return 0; } @@ -402,16 +399,10 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, return -ENOMEM; #endif - dfse->dfsentry = debugfs_create_file(name, mode, sdev->debugfs_root, - dfse, &sof_dfs_fops); - if (!dfse->dfsentry) { - /* can't rely on debugfs, only log error and keep going */ - dev_err(sdev->dev, "error: cannot create debugfs entry %s\n", - name); - } else { - /* add to dfsentry list */ - list_add(&dfse->list, &sdev->dfsentry_list); - } + debugfs_create_file(name, mode, sdev->debugfs_root, dfse, + &sof_dfs_fops); + /* add to dfsentry list */ + list_add(&dfse->list, &sdev->dfsentry_list); return 0; } @@ -426,10 +417,6 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) /* use "sof" as top level debugFS dir */ sdev->debugfs_root = debugfs_create_dir("sof", NULL); - if (IS_ERR_OR_NULL(sdev->debugfs_root)) { - dev_err(sdev->dev, "error: failed to create debugfs directory\n"); - return 0; - } /* init dfsentry list */ INIT_LIST_HEAD(&sdev->dfsentry_list); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 983eadef4b30..1cec3f23f9cd 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -230,7 +230,6 @@ enum sof_debugfs_access_type { /* FS entry for debug files that can expose DSP memories, registers */ struct snd_sof_dfsentry { - struct dentry *dfsentry; size_t size; enum sof_dfsentry_type type; /* diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index befed975161c..4c3cff031fd6 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -148,13 +148,8 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev) dfse->size = sdev->dmatb.bytes; dfse->sdev = sdev; - dfse->dfsentry = debugfs_create_file("trace", 0444, sdev->debugfs_root, - dfse, &sof_dfs_trace_fops); - if (!dfse->dfsentry) { - /* can't rely on debugfs, only log error and keep going */ - dev_err(sdev->dev, - "error: cannot create debugfs entry for trace\n"); - } + debugfs_create_file("trace", 0444, sdev->debugfs_root, dfse, + &sof_dfs_trace_fops); return 0; } -- GitLab From f24e41d3d04f326613d8a7ebecf72c3019826f71 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 23:32:34 +0100 Subject: [PATCH 1503/7155] ASoC: zx-tdm: remove redundant assignment to ts_width on error return path The value assigned to ts_width is never read on the error return path so the assignment is redundant and can be removed. Remove it. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190731223234.16153-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/zte/zx-tdm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c index 5e877fe9ba7b..0e5a05b25a77 100644 --- a/sound/soc/zte/zx-tdm.c +++ b/sound/soc/zte/zx-tdm.c @@ -211,7 +211,6 @@ static int zx_tdm_hw_params(struct snd_pcm_substream *substream, ts_width = 1; break; default: - ts_width = 0; dev_err(socdai->dev, "Unknown data format\n"); return -EINVAL; } -- GitLab From 9d52a35ebd4bb6e495ab06e4ce1f568daa0f70e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 15:29:23 +0200 Subject: [PATCH 1504/7155] regmap: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. The debugfs core will warn if a file or directory can not be created, so there's no need to duplicate the warning, nor really do anything else. Cc: Mark Brown Cc: "Rafael J. Wysocki" Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731132923.GA13829@kroah.com Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index e5e1b3a01b1a..e72843fe41df 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -588,14 +588,6 @@ void regmap_debugfs_init(struct regmap *map, const char *name) } map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); - if (!map->debugfs) { - dev_warn(map->dev, - "Failed to create %s debugfs directory\n", name); - - kfree(map->debugfs_name); - map->debugfs_name = NULL; - return; - } debugfs_create_file("name", 0400, map->debugfs, map, ®map_name_fops); @@ -672,10 +664,6 @@ void regmap_debugfs_initcall(void) struct regmap_debugfs_node *node, *tmp; regmap_debugfs_root = debugfs_create_dir("regmap", NULL); - if (!regmap_debugfs_root) { - pr_warn("regmap: Failed to create debugfs root\n"); - return; - } mutex_lock(®map_debugfs_early_lock); list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) { -- GitLab From cc8b4659491d23577eb8992449d82c7f4f4fc170 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 14:47:38 +0200 Subject: [PATCH 1505/7155] spi: core: Use DEVICE_ATTR_RW() for SPI slave control sysfs attribute Convert the SPI slave control sysfs attribute from DEVICE_ATTR() to DEVICE_ATTR_RW(), to reduce boilerplate. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190731124738.14519-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/spi/spi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 75ac046cae52..9fd7926e80c0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2105,8 +2105,8 @@ static int match_true(struct device *dev, void *data) return 1; } -static ssize_t spi_slave_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t slave_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2117,9 +2117,8 @@ static ssize_t spi_slave_show(struct device *dev, child ? to_spi_device(child)->modalias : NULL); } -static ssize_t spi_slave_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t slave_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2157,7 +2156,7 @@ static ssize_t spi_slave_store(struct device *dev, return count; } -static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store); +static DEVICE_ATTR_RW(slave); static struct attribute *spi_slave_attrs[] = { &dev_attr_slave.attr, -- GitLab From 644bf60088955421051e716ab9c8fe7fb7997fd7 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Thu, 1 Aug 2019 11:20:24 +0100 Subject: [PATCH 1506/7155] i2c: Revert incorrect conversion to use generic helper The patch "drivers: Introduce device lookup variants by ACPI_COMPANION device" converted an incorrect instance in i2c driver to a new helper. Revert this change. Reported-by: Stephen Rothwell Cc: Mika Westerberg Cc: Wolfram Sang Fixes: 00500147cbd3 ("drivers: Introduce device lookup variants by ACPI_COMPANION device") Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190801102026.27312-1-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core-acpi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index bc80aafb521f..f60f7a95d48e 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -357,7 +357,10 @@ static int i2c_acpi_find_match_adapter(struct device *dev, const void *data) struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) { - struct device *dev = bus_find_device_by_acpi_dev(&i2c_bus_type, handle); + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, handle, + i2c_acpi_find_match_adapter); return dev ? i2c_verify_adapter(dev) : NULL; } -- GitLab From b9515ecbf6caef2ea911ca59801eff84d034fa48 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Thu, 1 Aug 2019 11:20:25 +0100 Subject: [PATCH 1507/7155] drivers: Fix typo in parameter description for driver_find_device_by_acpi_dev Fix a typo in the comment describing the parameters for the new API, which triggers the following warning for htmldocs: include/linux/device.h:479: warning: Function parameter or member 'drv' not described in 'driver_find_device_by_acpi_dev' Reported-by: kbuild test robot Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190801102026.27312-2-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/device.h b/include/linux/device.h index 23ef6eba7213..8e1b2ead5d96 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -467,7 +467,7 @@ driver_find_device_by_fwnode(struct device_driver *drv, /** * driver_find_device_by_devt- device iterator for locating a particular device * by devt. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @devt: devt pointer to match. */ static inline struct device *driver_find_device_by_devt(struct device_driver *drv, -- GitLab From 313b46d831189f593840c625d7972092cb0088fc Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Thu, 1 Aug 2019 11:20:26 +0100 Subject: [PATCH 1508/7155] drivers: Fix htmldocs warnings with bus_find_next_device() Document the parameters for bus_find_next_device() to avoid htmldocs build warnings as reported below : include/linux/device.h:236: warning: Function parameter or member 'bus' not described in 'bus_find_next_device' include/linux/device.h:236: warning: Function parameter or member 'cur' not described in 'bus_find_next_device' Reported-by: kbuild test robot Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190801102026.27312-3-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/device.h b/include/linux/device.h index 8e1b2ead5d96..bff46ce3bc3b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -229,6 +229,8 @@ static inline struct device *bus_find_device_by_devt(struct bus_type *bus, /** * bus_find_next_device - Find the next device after a given device in a * given bus. + * @bus: bus type + * @cur: device to begin the search with. */ static inline struct device * bus_find_next_device(struct bus_type *bus,struct device *cur) -- GitLab From 5302dd7dd0b6d04c63cdce51d1e9fda9ef0be886 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:14 -0700 Subject: [PATCH 1509/7155] driver core: Add support for linking devices during device addition When devices are added, the bus might want to create device links to track functional dependencies between supplier and consumer devices. This tracking of supplier-consumer relationship allows optimizing device probe order and tracking whether all consumers of a supplier are active. The add_links bus callback is added to support this. However, when consumer devices are added, they might not have a supplier device to link to despite needing mandatory resources/functionality from one or more suppliers. A waiting_for_suppliers list is created to track such consumers and retry linking them when new devices get added. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 83 ++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 14 +++++++ 2 files changed, 97 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 90f2dd4661f5..18e04ca1de13 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -44,6 +44,8 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup); #endif /* Device links support. */ +static LIST_HEAD(wait_for_suppliers); +static DEFINE_MUTEX(wfs_lock); #ifdef CONFIG_SRCU static DEFINE_MUTEX(device_links_lock); @@ -418,6 +420,51 @@ struct device_link *device_link_add(struct device *consumer, } EXPORT_SYMBOL_GPL(device_link_add); +/** + * device_link_wait_for_supplier - Mark device as waiting for supplier + * @consumer: Consumer device + * + * Marks the consumer device as waiting for suppliers to become available. The + * consumer device will never be probed until it's unmarked as waiting for + * suppliers. The caller is responsible for adding the link to the supplier + * once the supplier device is present. + * + * This function is NOT meant to be called from the probe function of the + * consumer but rather from code that creates/adds the consumer device. + */ +static void device_link_wait_for_supplier(struct device *consumer) +{ + mutex_lock(&wfs_lock); + list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers); + mutex_unlock(&wfs_lock); +} + +/** + * device_link_check_waiting_consumers - Try to unmark waiting consumers + * + * Loops through all consumers waiting on suppliers and tries to add all their + * supplier links. If that succeeds, the consumer device is unmarked as waiting + * for suppliers. Otherwise, they are left marked as waiting on suppliers, + * + * The add_links bus callback is expected to return 0 if it has found and added + * all the supplier links for the consumer device. It should return an error if + * it isn't able to do so. + * + * The caller of device_link_wait_for_supplier() is expected to call this once + * it's aware of potential suppliers becoming available. + */ +static void device_link_check_waiting_consumers(void) +{ + struct device *dev, *tmp; + + mutex_lock(&wfs_lock); + list_for_each_entry_safe(dev, tmp, &wait_for_suppliers, + links.needs_suppliers) + if (!dev->bus->add_links(dev)) + list_del_init(&dev->links.needs_suppliers); + mutex_unlock(&wfs_lock); +} + static void device_link_free(struct device_link *link) { while (refcount_dec_not_one(&link->rpm_active)) @@ -552,6 +599,19 @@ int device_links_check_suppliers(struct device *dev) struct device_link *link; int ret = 0; + /* + * If a device is waiting for one or more suppliers (in + * wait_for_suppliers list), it is not ready to probe yet. So just + * return -EPROBE_DEFER without having to check the links with existing + * suppliers. + */ + mutex_lock(&wfs_lock); + if (!list_empty(&dev->links.needs_suppliers)) { + mutex_unlock(&wfs_lock); + return -EPROBE_DEFER; + } + mutex_unlock(&wfs_lock); + device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { @@ -836,6 +896,10 @@ static void device_links_purge(struct device *dev) { struct device_link *link, *ln; + mutex_lock(&wfs_lock); + list_del(&dev->links.needs_suppliers); + mutex_unlock(&wfs_lock); + /* * Delete all of the remaining links from this device to any other * devices (either consumers or suppliers). @@ -1697,6 +1761,7 @@ void device_initialize(struct device *dev) #endif INIT_LIST_HEAD(&dev->links.consumers); INIT_LIST_HEAD(&dev->links.suppliers); + INIT_LIST_HEAD(&dev->links.needs_suppliers); dev->links.status = DL_DEV_NO_DRIVER; } EXPORT_SYMBOL_GPL(device_initialize); @@ -2132,6 +2197,24 @@ int device_add(struct device *dev) BUS_NOTIFY_ADD_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_ADD); + + /* + * Check if any of the other devices (consumers) have been waiting for + * this device (supplier) to be added so that they can create a device + * link to it. + * + * This needs to happen after device_pm_add() because device_link_add() + * requires the supplier be registered before it's called. + * + * But this also needs to happe before bus_probe_device() to make sure + * waiting consumers can link to it before the driver is bound to the + * device and the driver sync_state callback is called for this device. + */ + device_link_check_waiting_consumers(); + + if (dev->bus && dev->bus->add_links && dev->bus->add_links(dev)) + device_link_wait_for_supplier(dev); + bus_probe_device(dev); if (parent) klist_add_tail(&dev->p->knode_parent, diff --git a/include/linux/device.h b/include/linux/device.h index bff46ce3bc3b..1e05911325f0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -78,6 +78,17 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * -EPROBE_DEFER it will queue the device for deferred probing. * @uevent: Called when a device is added, removed, or a few other things * that generate uevents to add the environment variables. + * @add_links: Called, perhaps multiple times per device, after a device is + * added to this bus. The function is expected to create device + * links to all the suppliers of the input device that are + * available at the time this function is called. As in, the + * function should NOT stop at the first failed device link if + * other unlinked supplier devices are present in the system. + * + * Return 0 if device links have been successfully created to all + * the suppliers of this device. Return an error if some of the + * suppliers are not yet available and this function needs to be + * reattempted in the future. * @probe: Called when a new device or driver add to this bus, and callback * the specific driver's probe to initial the matched device. * @remove: Called when a device removed from this bus. @@ -122,6 +133,7 @@ struct bus_type { int (*match)(struct device *dev, struct device_driver *drv); int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + int (*add_links)(struct device *dev); int (*probe)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown)(struct device *dev); @@ -1128,11 +1140,13 @@ enum dl_dev_state { * struct dev_links_info - Device data related to device links. * @suppliers: List of links to supplier devices. * @consumers: List of links to consumer devices. + * @needs_suppliers: Hook to global list of devices waiting for suppliers. * @status: Driver status information. */ struct dev_links_info { struct list_head suppliers; struct list_head consumers; + struct list_head needs_suppliers; enum dl_dev_state status; }; -- GitLab From 134b23eec9e3a3c795a6ceb0efe2fa63e87983b2 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:15 -0700 Subject: [PATCH 1510/7155] driver core: Add edit_links() callback for drivers The driver core/bus adding supplier-consumer dependencies by default enables functional dependencies to be tracked correctly even when the consumer devices haven't had their drivers registered or loaded (if they are modules). However, when the bus incorrectly adds dependencies that it shouldn't have added, the devices might never probe. For example, if device-C is a consumer of device-S and they have phandles to each other in DT, the following could happen: 1. Device-S get added first. 2. The bus add_links() callback will (incorrectly) try to link it as a consumer of device-C. 3. Since device-C isn't present, device-S will be put in "waiting-for-supplier" list. 4. Device-C gets added next. 5. All devices in "waiting-for-supplier" list are retried for linking. 6. Device-S gets linked as consumer to Device-C. 7. The bus add_links() callback will (correctly) try to link it as a consumer of device-S. 8. This isn't allowed because it would create a cyclic device links. Neither devices will get probed since the supplier is marked as dependent on the consumer. And the consumer will never probe because the consumer can't get resources from the supplier. Without this patch, things stay in this broken state. However, with this patch, the execution will continue like this: 9. Device-C's driver is loaded. 10. Device-C's driver removes Device-S as a consumer of Device-C. 11. Device-C's driver adds Device-C as a consumer of Device-S. 12. Device-S probes. 14. Device-C probes. kbuild test robot reported missing documentation for device.has_edit_links Reported-by: kbuild test robot Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-3-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 24 ++++++++++++++++++++++-- drivers/base/dd.c | 29 +++++++++++++++++++++++++++++ include/linux/device.h | 20 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 18e04ca1de13..feec8dee1e91 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -439,6 +439,19 @@ static void device_link_wait_for_supplier(struct device *consumer) mutex_unlock(&wfs_lock); } +/** + * device_link_remove_from_wfs - Unmark device as waiting for supplier + * @consumer: Consumer device + * + * Unmark the consumer device as waiting for suppliers to become available. + */ +void device_link_remove_from_wfs(struct device *consumer) +{ + mutex_lock(&wfs_lock); + list_del_init(&consumer->links.needs_suppliers); + mutex_unlock(&wfs_lock); +} + /** * device_link_check_waiting_consumers - Try to unmark waiting consumers * @@ -456,12 +469,19 @@ static void device_link_wait_for_supplier(struct device *consumer) static void device_link_check_waiting_consumers(void) { struct device *dev, *tmp; + int ret; mutex_lock(&wfs_lock); list_for_each_entry_safe(dev, tmp, &wait_for_suppliers, - links.needs_suppliers) - if (!dev->bus->add_links(dev)) + links.needs_suppliers) { + ret = 0; + if (dev->has_edit_links) + ret = driver_edit_links(dev); + else if (dev->bus->add_links) + ret = dev->bus->add_links(dev); + if (!ret) list_del_init(&dev->links.needs_suppliers); + } mutex_unlock(&wfs_lock); } diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 994a90747420..5e7041ede0d7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -698,6 +698,12 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); + if (drv->edit_links) { + if (drv->edit_links(dev)) + dev->has_edit_links = true; + else + device_link_remove_from_wfs(dev); + } pm_runtime_get_suppliers(dev); if (dev->parent) pm_runtime_get_sync(dev->parent); @@ -786,6 +792,29 @@ struct device_attach_data { bool have_async; }; +static int __driver_edit_links(struct device_driver *drv, void *data) +{ + struct device *dev = data; + + if (!drv->edit_links) + return 0; + + if (driver_match_device(drv, dev) <= 0) + return 0; + + return drv->edit_links(dev); +} + +int driver_edit_links(struct device *dev) +{ + int ret; + + device_lock(dev); + ret = bus_for_each_drv(dev->bus, NULL, dev, __driver_edit_links); + device_unlock(dev); + return ret; +} + static int __device_attach_driver(struct device_driver *drv, void *_data) { struct device_attach_data *data = _data; diff --git a/include/linux/device.h b/include/linux/device.h index 1e05911325f0..d3991810f39d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -349,6 +349,20 @@ enum probe_type { * @probe_type: Type of the probe (synchronous or asynchronous) to use. * @of_match_table: The open firmware table. * @acpi_match_table: The ACPI match table. + * @edit_links: Called to allow a matched driver to edit the device links the + * bus might have added incorrectly. This will be useful to handle + * cases where the bus incorrectly adds functional dependencies + * that aren't true or tries to create cyclic dependencies. But + * doesn't correctly handle functional dependencies that are + * missed by the bus as the supplier's sync_state might get to + * execute before the driver for a missing consumer is loaded and + * gets to edit the device links for the consumer. + * + * This function might be called multiple times after a new device + * is added. The function is expected to create all the device + * links for the new device and return 0 if it was completed + * successfully or return an error if it needs to be reattempted + * in the future. * @probe: Called to query the existence of a specific device, * whether this driver can work with it, and bind the driver * to a specific device. @@ -388,6 +402,7 @@ struct device_driver { const struct of_device_id *of_match_table; const struct acpi_device_id *acpi_match_table; + int (*edit_links)(struct device *dev); int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); @@ -1220,6 +1235,8 @@ struct dev_links_info { * @offline: Set after successful invocation of bus type's .offline(). * @of_node_reused: Set if the device-tree node is shared with an ancestor * device. + * @has_edit_links: This device has a driver than is capable of + * editing the device links created by driver core. * @dma_coherent: this particular device is dma coherent, even if the * architecture supports non-coherent devices. * @@ -1313,6 +1330,7 @@ struct device { bool offline_disabled:1; bool offline:1; bool of_node_reused:1; + bool has_edit_links:1; #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) @@ -1564,6 +1582,7 @@ extern int __must_check device_attach(struct device *dev); extern int __must_check driver_attach(struct device_driver *drv); extern void device_initial_probe(struct device *dev); extern int __must_check device_reprobe(struct device *dev); +extern int driver_edit_links(struct device *dev); extern bool device_is_bound(struct device *dev); @@ -1654,6 +1673,7 @@ struct device_link *device_link_add(struct device *consumer, struct device *supplier, u32 flags); void device_link_del(struct device_link *link); void device_link_remove(void *consumer, struct device *supplier); +void device_link_remove_from_wfs(struct device *consumer); #ifndef dev_fmt #define dev_fmt(fmt) fmt -- GitLab From 690ff7881b2681afca1c3c063f4a5cb7c71d9d8b Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:16 -0700 Subject: [PATCH 1511/7155] of/platform: Add functional dependency link from DT bindings Add device-links after the devices are created (but before they are probed) by looking at common DT bindings like clocks and interconnects. Automatically adding device-links for functional dependencies at the framework level provides the following benefits: - Optimizes device probe order and avoids the useless work of attempting probes of devices that will not probe successfully (because their suppliers aren't present or haven't probed yet). For example, in a commonly available mobile SoC, registering just one consumer device's driver at an initcall level earlier than the supplier device's driver causes 11 failed probe attempts before the consumer device probes successfully. This was with a kernel with all the drivers statically compiled in. This problem gets a lot worse if all the drivers are loaded as modules without direct symbol dependencies. - Supplier devices like clock providers, interconnect providers, etc need to keep the resources they provide active and at a particular state(s) during boot up even if their current set of consumers don't request the resource to be active. This is because the rest of the consumers might not have probed yet and turning off the resource before all the consumers have probed could lead to a hang or undesired user experience. Some frameworks (Eg: regulator) handle this today by turning off "unused" resources at late_initcall_sync and hoping all the devices have probed by then. This is not a valid assumption for systems with loadable modules. Other frameworks (Eg: clock) just don't handle this due to the lack of a clear signal for when they can turn off resources. This leads to downstream hacks to handle cases like this that can easily be solved in the upstream kernel. By linking devices before they are probed, we give suppliers a clear count of the number of dependent consumers. Once all of the consumers are active, the suppliers can turn off the unused resources without making assumptions about the number of consumers. By default we just add device-links to track "driver presence" (probe succeeded) of the supplier device. If any other functionality provided by device-links are needed, it is left to the consumer/supplier devices to change the link when they probe. kbuild test robot reported clang error about missing const Reported-by: kbuild test robot Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-4-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- .../admin-guide/kernel-parameters.txt | 5 + drivers/of/platform.c | 165 ++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 46b826fcb5ad..12937349d79d 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3170,6 +3170,11 @@ This can be set from sysctl after boot. See Documentation/admin-guide/sysctl/vm.rst for details. + of_devlink [KNL] Make device links from common DT bindings. Useful + for optimizing probe order and making sure resources + aren't turned off before the consumer devices have + probed. + ohci1394_dma=early [HW] enable debugging via the ohci1394 driver. See Documentation/debugging-via-ohci1394.txt for more info. diff --git a/drivers/of/platform.c b/drivers/of/platform.c index b47a2292fe8e..c1c433333124 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -503,6 +503,170 @@ int of_platform_default_populate(struct device_node *root, } EXPORT_SYMBOL_GPL(of_platform_default_populate); +bool of_link_is_valid(struct device_node *con, struct device_node *sup) +{ + of_node_get(sup); + /* + * Don't allow linking a device node as a consumer of one of its + * descendant nodes. By definition, a child node can't be a functional + * dependency for the parent node. + */ + while (sup) { + if (sup == con) { + of_node_put(sup); + return false; + } + sup = of_get_next_parent(sup); + } + return true; +} + +static int of_link_to_phandle(struct device *dev, struct device_node *sup_np) +{ + struct platform_device *sup_dev; + u32 dl_flags = DL_FLAG_AUTOPROBE_CONSUMER; + int ret = 0; + + /* + * Since we are trying to create device links, we need to find + * the actual device node that owns this supplier phandle. + * Often times it's the same node, but sometimes it can be one + * of the parents. So walk up the parent till you find a + * device. + */ + while (sup_np && !of_find_property(sup_np, "compatible", NULL)) + sup_np = of_get_next_parent(sup_np); + if (!sup_np) + return 0; + + if (!of_link_is_valid(dev->of_node, sup_np)) { + of_node_put(sup_np); + return 0; + } + sup_dev = of_find_device_by_node(sup_np); + of_node_put(sup_np); + if (!sup_dev) + return -ENODEV; + if (!device_link_add(dev, &sup_dev->dev, dl_flags)) + ret = -ENODEV; + put_device(&sup_dev->dev); + return ret; +} + +static struct device_node *parse_prop_cells(struct device_node *np, + const char *prop, int index, + const char *binding, + const char *cell) +{ + struct of_phandle_args sup_args; + + /* Don't need to check property name for every index. */ + if (!index && strcmp(prop, binding)) + return NULL; + + if (of_parse_phandle_with_args(np, binding, cell, index, &sup_args)) + return NULL; + + return sup_args.np; +} + +static struct device_node *parse_clocks(struct device_node *np, + const char *prop, int index) +{ + return parse_prop_cells(np, prop, index, "clocks", "#clock-cells"); +} + +static struct device_node *parse_interconnects(struct device_node *np, + const char *prop, int index) +{ + return parse_prop_cells(np, prop, index, "interconnects", + "#interconnect-cells"); +} + +static int strcmp_suffix(const char *str, const char *suffix) +{ + unsigned int len, suffix_len; + + len = strlen(str); + suffix_len = strlen(suffix); + if (len <= suffix_len) + return -1; + return strcmp(str + len - suffix_len, suffix); +} + +static struct device_node *parse_regulators(struct device_node *np, + const char *prop, int index) +{ + if (index || strcmp_suffix(prop, "-supply")) + return NULL; + + return of_parse_phandle(np, prop, 0); +} + +/** + * struct supplier_bindings - Information for parsing supplier DT binding + * + * @parse_prop: If the function cannot parse the property, return NULL. + * Otherwise, return the phandle listed in the property + * that corresponds to the index. + */ +struct supplier_bindings { + struct device_node *(*parse_prop)(struct device_node *np, + const char *name, int index); +}; + +static const struct supplier_bindings bindings[] = { + { .parse_prop = parse_clocks, }, + { .parse_prop = parse_interconnects, }, + { .parse_prop = parse_regulators, }, + { }, +}; + +static bool of_link_property(struct device *dev, struct device_node *con_np, + const char *prop) +{ + struct device_node *phandle; + const struct supplier_bindings *s = bindings; + unsigned int i = 0; + bool done = true, matched = false; + + while (!matched && s->parse_prop) { + while ((phandle = s->parse_prop(con_np, prop, i))) { + matched = true; + i++; + if (of_link_to_phandle(dev, phandle)) + /* + * Don't stop at the first failure. See + * Documentation for bus_type.add_links for + * more details. + */ + done = false; + } + s++; + } + return done ? 0 : -ENODEV; +} + +static bool of_devlink; +core_param(of_devlink, of_devlink, bool, 0); + +static int of_link_to_suppliers(struct device *dev) +{ + struct property *p; + bool done = true; + + if (!of_devlink) + return 0; + if (unlikely(!dev->of_node)) + return 0; + + for_each_property_of_node(dev->of_node, p) + if (of_link_property(dev, dev->of_node, p->name)) + done = false; + + return done ? 0 : -ENODEV; +} + #ifndef CONFIG_PPC static const struct of_device_id reserved_mem_matches[] = { { .compatible = "qcom,rmtfs-mem" }, @@ -518,6 +682,7 @@ static int __init of_platform_default_populate_init(void) if (!of_have_populated_dt()) return -ENODEV; + platform_bus_type.add_links = of_link_to_suppliers; /* * Handle certain compatibles explicitly, since we don't want to create * platform_devices for every node in /reserved-memory with a -- GitLab From 8f8184d6bf676a8680d6f441e40317d166b46f73 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:17 -0700 Subject: [PATCH 1512/7155] driver core: Add sync_state driver/bus callback This sync_state driver/bus callback is called once all the consumers of a supplier have probed successfully. This allows the supplier device's driver/bus to sync the supplier device's state to the software state with the guarantee that all the consumers are actively managing the resources provided by the supplier device. To maintain backwards compatibility and ease transition from existing frameworks and resource cleanup schemes, late_initcall_sync is the earliest when the sync_state callback might be called. There is no upper bound on the time by which the sync_state callback has to be called. This is because if a consumer device never probes, the supplier has to maintain its resources in the state left by the bootloader. For example, if the bootloader leaves the display backlight at a fixed voltage and the backlight driver is never probed, you don't want the backlight to ever be turned off after boot up. Also, when multiple devices are added after kernel init, some suppliers could be added before their consumer devices get added. In these instances, the supplier devices could get their sync_state callback called right after they probe because the consumers devices haven't had a chance to create device links to the suppliers. To handle this correctly, this change also provides APIs to pause/resume sync state callbacks so that when multiple devices are added, their sync_state callback evaluation can be postponed to happen after all of them are added. kbuild test robot reported missing documentation for device.state_synced Reported-by: kbuild test robot Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-5-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 65 ++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 26 +++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index feec8dee1e91..5b1795cd116a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -46,6 +46,8 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup); /* Device links support. */ static LIST_HEAD(wait_for_suppliers); static DEFINE_MUTEX(wfs_lock); +static LIST_HEAD(deferred_sync); +static unsigned int supplier_sync_state_disabled; #ifdef CONFIG_SRCU static DEFINE_MUTEX(device_links_lock); @@ -651,6 +653,62 @@ int device_links_check_suppliers(struct device *dev) return ret; } +static void __device_links_supplier_sync_state(struct device *dev) +{ + struct device_link *link; + + if (dev->state_synced) + return; + + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (!(link->flags & DL_FLAG_MANAGED)) + continue; + if (link->status != DL_STATE_ACTIVE) + return; + } + + if (dev->bus->sync_state) + dev->bus->sync_state(dev); + else if (dev->driver && dev->driver->sync_state) + dev->driver->sync_state(dev); + + dev->state_synced = true; +} + +void device_links_supplier_sync_state_pause(void) +{ + device_links_write_lock(); + supplier_sync_state_disabled++; + device_links_write_unlock(); +} + +void device_links_supplier_sync_state_resume(void) +{ + struct device *dev, *tmp; + + device_links_write_lock(); + if (!supplier_sync_state_disabled) { + WARN(true, "Unmatched sync_state pause/resume!"); + goto out; + } + supplier_sync_state_disabled--; + if (supplier_sync_state_disabled) + goto out; + + list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) { + __device_links_supplier_sync_state(dev); + list_del_init(&dev->links.defer_sync); + } +out: + device_links_write_unlock(); +} + +static void __device_links_supplier_defer_sync(struct device *sup) +{ + if (list_empty(&sup->links.defer_sync)) + list_add_tail(&sup->links.defer_sync, &deferred_sync); +} + /** * device_links_driver_bound - Update device links after probing its driver. * @dev: Device to update the links for. @@ -695,6 +753,11 @@ void device_links_driver_bound(struct device *dev) WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); WRITE_ONCE(link->status, DL_STATE_ACTIVE); + + if (supplier_sync_state_disabled) + __device_links_supplier_defer_sync(link->supplier); + else + __device_links_supplier_sync_state(link->supplier); } dev->links.status = DL_DEV_DRIVER_BOUND; @@ -811,6 +874,7 @@ void device_links_driver_cleanup(struct device *dev) WRITE_ONCE(link->status, DL_STATE_DORMANT); } + list_del_init(&dev->links.defer_sync); __device_links_no_driver(dev); device_links_write_unlock(); @@ -1782,6 +1846,7 @@ void device_initialize(struct device *dev) INIT_LIST_HEAD(&dev->links.consumers); INIT_LIST_HEAD(&dev->links.suppliers); INIT_LIST_HEAD(&dev->links.needs_suppliers); + INIT_LIST_HEAD(&dev->links.defer_sync); dev->links.status = DL_DEV_NO_DRIVER; } EXPORT_SYMBOL_GPL(device_initialize); diff --git a/include/linux/device.h b/include/linux/device.h index d3991810f39d..63a3aafabcd6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -84,6 +84,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * available at the time this function is called. As in, the * function should NOT stop at the first failed device link if * other unlinked supplier devices are present in the system. + * This is necessary for the sync_state() callback to work + * correctly. * * Return 0 if device links have been successfully created to all * the suppliers of this device. Return an error if some of the @@ -91,6 +93,13 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * reattempted in the future. * @probe: Called when a new device or driver add to this bus, and callback * the specific driver's probe to initial the matched device. + * @sync_state: Called to sync device state to software state after all the + * state tracking consumers linked to this device (present at + * the time of late_initcall) have successfully bound to a + * driver. If the device has no consumers, this function will + * be called at late_initcall_sync level. If the device has + * consumers that are never bound to a driver, this function + * will never get called until they do. * @remove: Called when a device removed from this bus. * @shutdown: Called at shut-down time to quiesce the device. * @@ -135,6 +144,7 @@ struct bus_type { int (*uevent)(struct device *dev, struct kobj_uevent_env *env); int (*add_links)(struct device *dev); int (*probe)(struct device *dev); + void (*sync_state)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown)(struct device *dev); @@ -366,6 +376,13 @@ enum probe_type { * @probe: Called to query the existence of a specific device, * whether this driver can work with it, and bind the driver * to a specific device. + * @sync_state: Called to sync device state to software state after all the + * state tracking consumers linked to this device (present at + * the time of late_initcall) have successfully bound to a + * driver. If the device has no consumers, this function will + * be called at late_initcall_sync level. If the device has + * consumers that are never bound to a driver, this function + * will never get called until they do. * @remove: Called when the device is removed from the system to * unbind a device from this driver. * @shutdown: Called at shut-down time to quiesce the device. @@ -404,6 +421,7 @@ struct device_driver { int (*edit_links)(struct device *dev); int (*probe) (struct device *dev); + void (*sync_state)(struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); @@ -1156,12 +1174,14 @@ enum dl_dev_state { * @suppliers: List of links to supplier devices. * @consumers: List of links to consumer devices. * @needs_suppliers: Hook to global list of devices waiting for suppliers. + * @defer_sync: Hook to global list of devices that have deferred sync_state. * @status: Driver status information. */ struct dev_links_info { struct list_head suppliers; struct list_head consumers; struct list_head needs_suppliers; + struct list_head defer_sync; enum dl_dev_state status; }; @@ -1237,6 +1257,9 @@ struct dev_links_info { * device. * @has_edit_links: This device has a driver than is capable of * editing the device links created by driver core. + * @state_synced: The hardware state of this device has been synced to match + * the software state of this device by calling the driver/bus + * sync_state() callback. * @dma_coherent: this particular device is dma coherent, even if the * architecture supports non-coherent devices. * @@ -1331,6 +1354,7 @@ struct device { bool offline:1; bool of_node_reused:1; bool has_edit_links:1; + bool state_synced:1; #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) @@ -1674,6 +1698,8 @@ struct device_link *device_link_add(struct device *consumer, void device_link_del(struct device_link *link); void device_link_remove(void *consumer, struct device *supplier); void device_link_remove_from_wfs(struct device *consumer); +void device_links_supplier_sync_state_pause(void); +void device_links_supplier_sync_state_resume(void); #ifndef dev_fmt #define dev_fmt(fmt) fmt -- GitLab From 21871a99b34c65c56a24193c277a4981529c306f Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:18 -0700 Subject: [PATCH 1513/7155] of/platform: Pause/resume sync state during init and of_platform_populate() When all the top level devices are populated from DT during kernel init, the supplier devices could be added and probed before the consumer devices are added and linked to the suppliers. To avoid the sync_state() callback from being called prematurely, pause the sync_state() callbacks before populating the devices and resume them at late_initcall_sync(). Similarly, when children devices are populated after kernel init using of_platform_populate(), there could be supplier-consumer dependencies between the children devices that are populated. To avoid the same problem with sync_state() being called prematurely, pause and resume sync_state() callbacks across of_platform_populate(). Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-6-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index c1c433333124..ae85a88ba53e 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -480,6 +480,7 @@ int of_platform_populate(struct device_node *root, pr_debug("%s()\n", __func__); pr_debug(" starting at: %pOF\n", root); + device_links_supplier_sync_state_pause(); for_each_child_of_node(root, child) { rc = of_platform_bus_create(child, matches, lookup, parent, true); if (rc) { @@ -487,6 +488,8 @@ int of_platform_populate(struct device_node *root, break; } } + device_links_supplier_sync_state_resume(); + of_node_set_flag(root, OF_POPULATED_BUS); of_node_put(root); @@ -683,6 +686,7 @@ static int __init of_platform_default_populate_init(void) return -ENODEV; platform_bus_type.add_links = of_link_to_suppliers; + device_links_supplier_sync_state_pause(); /* * Handle certain compatibles explicitly, since we don't want to create * platform_devices for every node in /reserved-memory with a @@ -703,6 +707,13 @@ static int __init of_platform_default_populate_init(void) return 0; } arch_initcall_sync(of_platform_default_populate_init); + +static int __init of_platform_sync_state_init(void) +{ + device_links_supplier_sync_state_resume(); + return 0; +} +late_initcall_sync(of_platform_sync_state_init); #endif int of_platform_device_destroy(struct device *dev, void *data) -- GitLab From 709fb8297358f08a125b770d1518a95d03b541db Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:19 -0700 Subject: [PATCH 1514/7155] of/platform: Create device links for all child-supplier depencencies A parent device can have child devices that it adds when it probes. But this probing of the parent device can happen way after kernel init is done -- for example, when the parent device's driver is loaded as a module. In such cases, if the child devices depend on a supplier in the system, we need to make sure the supplier gets the sync_state() callback only after these child devices are added and probed. To achieve this, when creating device links for a device by looking at its DT node, don't just look at DT references at the top node level. Look at DT references in all the descendant nodes too and create device links from the ancestor device to all these supplier devices. This way, when the parent device probes and adds child devices, the child devices can then create their own device links to the suppliers and further delay the supplier's sync_state() callback to after the child devices are probed. Example: In this illustration, -> denotes DT references and indentation represents child status. Device node A Device node B -> D Device node C -> B, D Device node D Assume all these devices have their drivers loaded as modules. Without this patch, this is the sequence of events: 1. D is added. 2. A is added. 3. Device D probes. 4. Device D gets its sync_state() callback. 5. Device B and C might malfunction because their resources got altered/turned off before they can make active requests for them. With this patch, this is the sequence of events: 1. D is added. 2. A is added and creates device links to D. 3. Device link from A to B is not added because A is a parent of B. 4. Device D probes. 5. Device D does not get it's sync_state() callback because consumer A hasn't probed yet. 5. Device A probes. 5. a. Devices B and C are added. 5. b. Device links from B and C to D are added. 5. c. Device A's probe completes. 6. Device D does not get it's sync_state() callback because consumer A has probed but consumers B and C haven't probed yet. 7. Device B and C probe. 8. Device D gets it's sync_state() callback because all its consumers have probed. 9. None of the devices malfunction. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-7-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ae85a88ba53e..52590fb20422 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -650,24 +650,35 @@ static bool of_link_property(struct device *dev, struct device_node *con_np, return done ? 0 : -ENODEV; } +static int __of_link_to_suppliers(struct device *dev, + struct device_node *con_np) +{ + struct device_node *child; + struct property *p; + bool done = true; + + for_each_property_of_node(con_np, p) + if (of_link_property(dev, con_np, p->name)) + done = false; + + for_each_child_of_node(con_np, child) + if (__of_link_to_suppliers(dev, child)) + done = false; + + return done ? 0 : -ENODEV; +} + static bool of_devlink; core_param(of_devlink, of_devlink, bool, 0); static int of_link_to_suppliers(struct device *dev) { - struct property *p; - bool done = true; - if (!of_devlink) return 0; if (unlikely(!dev->of_node)) return 0; - for_each_property_of_node(dev->of_node, p) - if (of_link_property(dev, dev->of_node, p->name)) - done = false; - - return done ? 0 : -ENODEV; + return __of_link_to_suppliers(dev, dev->of_node); } #ifndef CONFIG_PPC -- GitLab From b3173c2292fbaf24ff7062d366830b012ed04269 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 31 Jul 2019 15:17:20 -0700 Subject: [PATCH 1515/7155] of/platform: Don't create device links for default busses Default busses also have devices created for them. But there's no point in creating device links for them. It's especially wasteful as it'll cause the traversal of the entire device tree and also spend a lot of time checking and figuring out that creating those links isn't allowed. So check for default busses and skip trying to create device links for them. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190731221721.187713-8-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 52590fb20422..21838226d68a 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -677,6 +677,8 @@ static int of_link_to_suppliers(struct device *dev) return 0; if (unlikely(!dev->of_node)) return 0; + if (of_match_node(of_default_bus_match_table, dev->of_node)) + return 0; return __of_link_to_suppliers(dev, dev->of_node); } -- GitLab From 50944213062f7605ef79604418c7e3468d97b109 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:52 -0700 Subject: [PATCH 1516/7155] platform/x86: intel_pmc_ipc: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Enric Balletbo i Serra Cc: Hans de Goede Cc: "Darren Hart (VMware)" Cc: Roman Kiryanov Cc: Vadim Pasternak Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_ipc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index 55037ff258f8..5c1da2bb1435 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -936,10 +936,8 @@ static int ipc_plat_probe(struct platform_device *pdev) spin_lock_init(&ipcdev.gcr_lock); ipcdev.irq = platform_get_irq(pdev, 0); - if (ipcdev.irq < 0) { - dev_err(&pdev->dev, "Failed to get irq\n"); + if (ipcdev.irq < 0) return -EINVAL; - } ret = ipc_plat_get_res(pdev); if (ret) { -- GitLab From eaae882c4a77c8aa2ca20d4447aeb81d9d5eec97 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:53 -0700 Subject: [PATCH 1517/7155] platform/mellanox: mlxreg-hotplug: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Enric Balletbo i Serra Cc: Hans de Goede Cc: "Darren Hart (VMware)" Cc: Roman Kiryanov Cc: Vadim Pasternak Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Andy Shevchenko --- drivers/platform/mellanox/mlxreg-hotplug.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index f85a1b9d129b..706207d192ae 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -642,11 +642,8 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) priv->irq = pdata->irq; } else { priv->irq = platform_get_irq(pdev, 0); - if (priv->irq < 0) { - dev_err(&pdev->dev, "Failed to get platform irq: %d\n", - priv->irq); + if (priv->irq < 0) return priv->irq; - } } priv->regmap = pdata->regmap; -- GitLab From b2dd2d9a49e0a9251badde3363efc9e7be2d0bde Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:54 -0700 Subject: [PATCH 1518/7155] platform/x86: intel_bxtwc_tmu: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Enric Balletbo i Serra Cc: Hans de Goede Cc: "Darren Hart (VMware)" Cc: Roman Kiryanov Cc: Vadim Pasternak Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_bxtwc_tmu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel_bxtwc_tmu.c b/drivers/platform/x86/intel_bxtwc_tmu.c index 951c105bafc1..7ccf583649e6 100644 --- a/drivers/platform/x86/intel_bxtwc_tmu.c +++ b/drivers/platform/x86/intel_bxtwc_tmu.c @@ -60,11 +60,8 @@ static int bxt_wcove_tmu_probe(struct platform_device *pdev) wctmu->regmap = pmic->regmap; irq = platform_get_irq(pdev, 0); - - if (irq < 0) { - dev_err(&pdev->dev, "invalid irq %d\n", irq); + if (irq < 0) return irq; - } regmap_irq_chip = pmic->irq_chip_data_tmu; virq = regmap_irq_get_virq(regmap_irq_chip, irq); -- GitLab From f839b4b549a65e1c611f911654012ac65e6d1610 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:55 -0700 Subject: [PATCH 1519/7155] platform/x86: intel_int0002_vgpio: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Enric Balletbo i Serra Cc: Hans de Goede Cc: "Darren Hart (VMware)" Cc: Roman Kiryanov Cc: Vadim Pasternak Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_int0002_vgpio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c index d9542c661ddc..4f3f30152a27 100644 --- a/drivers/platform/x86/intel_int0002_vgpio.c +++ b/drivers/platform/x86/intel_int0002_vgpio.c @@ -166,10 +166,8 @@ static int int0002_probe(struct platform_device *pdev) return -ENODEV; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "Error getting IRQ: %d\n", irq); + if (irq < 0) return irq; - } chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) -- GitLab From 7455cdd1a0fe9a1367ee99596ea2564031daec00 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 11 Feb 2019 12:13:57 -0800 Subject: [PATCH 1520/7155] tools/memory-model: Make scripts be executable This commit simplifies life a bit by making all of the scripts in tools/memory-model/scripts be executable. Signed-off-by: Paul E. McKenney --- tools/memory-model/scripts/checkghlitmus.sh | 0 tools/memory-model/scripts/checklitmushist.sh | 0 tools/memory-model/scripts/cmplitmushist.sh | 0 tools/memory-model/scripts/initlitmushist.sh | 0 tools/memory-model/scripts/judgelitmus.sh | 0 tools/memory-model/scripts/newlitmushist.sh | 0 tools/memory-model/scripts/parseargs.sh | 0 tools/memory-model/scripts/runlitmushist.sh | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/memory-model/scripts/checkghlitmus.sh mode change 100644 => 100755 tools/memory-model/scripts/checklitmushist.sh mode change 100644 => 100755 tools/memory-model/scripts/cmplitmushist.sh mode change 100644 => 100755 tools/memory-model/scripts/initlitmushist.sh mode change 100644 => 100755 tools/memory-model/scripts/judgelitmus.sh mode change 100644 => 100755 tools/memory-model/scripts/newlitmushist.sh mode change 100644 => 100755 tools/memory-model/scripts/parseargs.sh mode change 100644 => 100755 tools/memory-model/scripts/runlitmushist.sh diff --git a/tools/memory-model/scripts/checkghlitmus.sh b/tools/memory-model/scripts/checkghlitmus.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/checklitmushist.sh b/tools/memory-model/scripts/checklitmushist.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/cmplitmushist.sh b/tools/memory-model/scripts/cmplitmushist.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/initlitmushist.sh b/tools/memory-model/scripts/initlitmushist.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/judgelitmus.sh b/tools/memory-model/scripts/judgelitmus.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/newlitmushist.sh b/tools/memory-model/scripts/newlitmushist.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/parseargs.sh b/tools/memory-model/scripts/parseargs.sh old mode 100644 new mode 100755 diff --git a/tools/memory-model/scripts/runlitmushist.sh b/tools/memory-model/scripts/runlitmushist.sh old mode 100644 new mode 100755 -- GitLab From dbc1625fc9deefb352f6ff26a575ae4b3ddef23a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:50 +0200 Subject: [PATCH 1521/7155] hrtimer: Consolidate hrtimer_init() + hrtimer_init_sleeper() calls hrtimer_init_sleeper() calls require prior initialisation of the hrtimer object which is embedded into the hrtimer_sleeper. Combine the initialization and spare a function call. Fixup all call sites. This is also a preparatory change for PREEMPT_RT to do hrtimer sleeper specific initializations of the embedded hrtimer without modifying any of the call sites. No functional change. [ anna-maria: Minor cleanups ] [ tglx: Adopted to the removal of the task argument of hrtimer_init_sleeper() and trivial polishing. Folded a fix from Stephen Rothwell for the vsoc code ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Anna-Maria Gleixner Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185752.887468908@linutronix.de --- block/blk-mq.c | 3 +-- drivers/staging/android/vsoc.c | 6 ++--- include/linux/hrtimer.h | 17 +++++++++++--- include/linux/wait.h | 4 ++-- kernel/futex.c | 8 +++---- kernel/time/hrtimer.c | 43 +++++++++++++++++++++++++--------- net/core/pktgen.c | 4 +--- 7 files changed, 55 insertions(+), 30 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 5f647cb8c695..df3fafbfe9a9 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3415,10 +3415,9 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q, kt = nsecs; mode = HRTIMER_MODE_REL; - hrtimer_init_on_stack(&hs.timer, CLOCK_MONOTONIC, mode); + hrtimer_init_sleeper_on_stack(&hs, CLOCK_MONOTONIC, mode); hrtimer_set_expires(&hs.timer, kt); - hrtimer_init_sleeper(&hs); do { if (blk_mq_rq_state(rq) == MQ_RQ_COMPLETE) break; diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c index ce480bcf20d2..2d6b3981afb8 100644 --- a/drivers/staging/android/vsoc.c +++ b/drivers/staging/android/vsoc.c @@ -437,12 +437,10 @@ static int handle_vsoc_cond_wait(struct file *filp, struct vsoc_cond_wait *arg) return -EINVAL; wake_time = ktime_set(arg->wake_time_sec, arg->wake_time_nsec); - hrtimer_init_on_stack(&to->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_ABS); + hrtimer_init_sleeper_on_stack(to, CLOCK_MONOTONIC, + HRTIMER_MODE_ABS); hrtimer_set_expires_range_ns(&to->timer, wake_time, current->timer_slack_ns); - - hrtimer_init_sleeper(to); } while (1) { diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 3c74f89367c4..0df373bed3d7 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -347,10 +347,15 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device); /* Initialize timers: */ extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, enum hrtimer_mode mode); +extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, + enum hrtimer_mode mode); #ifdef CONFIG_DEBUG_OBJECTS_TIMERS extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock, enum hrtimer_mode mode); +extern void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, + clockid_t clock_id, + enum hrtimer_mode mode); extern void destroy_hrtimer_on_stack(struct hrtimer *timer); #else @@ -360,6 +365,14 @@ static inline void hrtimer_init_on_stack(struct hrtimer *timer, { hrtimer_init(timer, which_clock, mode); } + +static inline void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, + clockid_t clock_id, + enum hrtimer_mode mode) +{ + hrtimer_init_sleeper(sl, clock_id, mode); +} + static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { } #endif @@ -463,10 +476,8 @@ extern long hrtimer_nanosleep(const struct timespec64 *rqtp, const enum hrtimer_mode mode, const clockid_t clockid); -extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl); - extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta, - const enum hrtimer_mode mode); + const enum hrtimer_mode mode); extern int schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, const enum hrtimer_mode mode, diff --git a/include/linux/wait.h b/include/linux/wait.h index d57832774ca6..4707543ef575 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -488,8 +488,8 @@ do { \ int __ret = 0; \ struct hrtimer_sleeper __t; \ \ - hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); \ - hrtimer_init_sleeper(&__t); \ + hrtimer_init_sleeper_on_stack(&__t, CLOCK_MONOTONIC, \ + HRTIMER_MODE_REL); \ if ((timeout) != KTIME_MAX) \ hrtimer_start_range_ns(&__t.timer, timeout, \ current->timer_slack_ns, \ diff --git a/kernel/futex.c b/kernel/futex.c index 5e9842ea4012..c8561aa5338e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -487,11 +487,9 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout, if (!time) return NULL; - hrtimer_init_on_stack(&timeout->timer, (flags & FLAGS_CLOCKRT) ? - CLOCK_REALTIME : CLOCK_MONOTONIC, - HRTIMER_MODE_ABS); - hrtimer_init_sleeper(timeout); - + hrtimer_init_sleeper_on_stack(timeout, (flags & FLAGS_CLOCKRT) ? + CLOCK_REALTIME : CLOCK_MONOTONIC, + HRTIMER_MODE_ABS); /* * If range_ns is 0, calling hrtimer_set_expires_range_ns() is * effectively the same as calling hrtimer_set_expires(). diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index de895d86800c..bb55d62f631e 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -427,6 +427,17 @@ void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t clock_id, } EXPORT_SYMBOL_GPL(hrtimer_init_on_stack); +static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, + clockid_t clock_id, enum hrtimer_mode mode); + +void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, + clockid_t clock_id, enum hrtimer_mode mode) +{ + debug_object_init_on_stack(&sl->timer, &hrtimer_debug_descr); + __hrtimer_init_sleeper(sl, clock_id, mode); +} +EXPORT_SYMBOL_GPL(hrtimer_init_sleeper_on_stack); + void destroy_hrtimer_on_stack(struct hrtimer *timer) { debug_object_free(timer, &hrtimer_debug_descr); @@ -1639,11 +1650,27 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer) return HRTIMER_NORESTART; } -void hrtimer_init_sleeper(struct hrtimer_sleeper *sl) +static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, + clockid_t clock_id, enum hrtimer_mode mode) { + __hrtimer_init(&sl->timer, clock_id, mode); sl->timer.function = hrtimer_wakeup; sl->task = current; } + +/** + * hrtimer_init_sleeper - initialize sleeper to the given clock + * @sl: sleeper to be initialized + * @clock_id: the clock to be used + * @mode: timer mode abs/rel + */ +void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, + enum hrtimer_mode mode) +{ + debug_init(&sl->timer, clock_id, mode); + __hrtimer_init_sleeper(sl, clock_id, mode); + +} EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); int nanosleep_copyout(struct restart_block *restart, struct timespec64 *ts) @@ -1669,8 +1696,6 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod { struct restart_block *restart; - hrtimer_init_sleeper(t); - do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start_expires(&t->timer, mode); @@ -1707,10 +1732,9 @@ static long __sched hrtimer_nanosleep_restart(struct restart_block *restart) struct hrtimer_sleeper t; int ret; - hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid, - HRTIMER_MODE_ABS); + hrtimer_init_sleeper_on_stack(&t, restart->nanosleep.clockid, + HRTIMER_MODE_ABS); hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires); - ret = do_nanosleep(&t, HRTIMER_MODE_ABS); destroy_hrtimer_on_stack(&t.timer); return ret; @@ -1728,7 +1752,7 @@ long hrtimer_nanosleep(const struct timespec64 *rqtp, if (dl_task(current) || rt_task(current)) slack = 0; - hrtimer_init_on_stack(&t.timer, clockid, mode); + hrtimer_init_sleeper_on_stack(&t, clockid, mode); hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack); ret = do_nanosleep(&t, mode); if (ret != -ERESTART_RESTARTBLOCK) @@ -1927,11 +1951,8 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, return -EINTR; } - hrtimer_init_on_stack(&t.timer, clock_id, mode); + hrtimer_init_sleeper_on_stack(&t, clock_id, mode); hrtimer_set_expires_range_ns(&t.timer, *expires, delta); - - hrtimer_init_sleeper(&t); - hrtimer_start_expires(&t.timer, mode); if (likely(t.task)) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 7f3cf2381f27..a5905975bc12 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2156,7 +2156,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) s64 remaining; struct hrtimer_sleeper t; - hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + hrtimer_init_sleeper_on_stack(&t, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_set_expires(&t.timer, spin_until); remaining = ktime_to_ns(hrtimer_expires_remaining(&t.timer)); @@ -2170,8 +2170,6 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) end_time = ktime_get(); } while (ktime_compare(end_time, spin_until) < 0); } else { - /* see do_nanosleep */ - hrtimer_init_sleeper(&t); do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS); -- GitLab From 01656464fce946f70b02a84ab218e562ceb1662e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 Jul 2019 21:03:53 +0200 Subject: [PATCH 1522/7155] hrtimer: Provide hrtimer_sleeper_start_expires() hrtimer_sleepers will gain a scheduling class dependent treatment on PREEMPT_RT. Create a wrapper around hrtimer_start_expires() to make that possible. Signed-off-by: Thomas Gleixner --- include/linux/hrtimer.h | 3 +++ kernel/time/hrtimer.c | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 0df373bed3d7..24072a0942c0 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -408,6 +408,9 @@ static inline void hrtimer_start_expires(struct hrtimer *timer, hrtimer_start_range_ns(timer, soft, delta, mode); } +void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, + enum hrtimer_mode mode); + static inline void hrtimer_restart(struct hrtimer *timer) { hrtimer_start_expires(timer, HRTIMER_MODE_ABS); diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index bb55d62f631e..dab1ea1a99d0 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1650,6 +1650,21 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer) return HRTIMER_NORESTART; } +/** + * hrtimer_sleeper_start_expires - Start a hrtimer sleeper timer + * @sl: sleeper to be started + * @mode: timer mode abs/rel + * + * Wrapper around hrtimer_start_expires() for hrtimer_sleeper based timers + * to allow PREEMPT_RT to tweak the delivery mode (soft/hardirq context) + */ +void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, + enum hrtimer_mode mode) +{ + hrtimer_start_expires(&sl->timer, mode); +} +EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires); + static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, enum hrtimer_mode mode) { @@ -1698,7 +1713,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod do { set_current_state(TASK_INTERRUPTIBLE); - hrtimer_start_expires(&t->timer, mode); + hrtimer_sleeper_start_expires(t, mode); if (likely(t->task)) freezable_schedule(); @@ -1953,7 +1968,7 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, hrtimer_init_sleeper_on_stack(&t, clock_id, mode); hrtimer_set_expires_range_ns(&t.timer, *expires, delta); - hrtimer_start_expires(&t.timer, mode); + hrtimer_sleeper_start_expires(&t, mode); if (likely(t.task)) schedule(); -- GitLab From 9dd8813ed9f6e2bba75434abc6c8bb06c3d87fdc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 Jul 2019 21:16:55 +0200 Subject: [PATCH 1523/7155] hrtimer/treewide: Use hrtimer_sleeper_start_expires() hrtimer_sleepers will gain a scheduling class dependent treatment on PREEMPT_RT. Use the new hrtimer_sleeper_start_expires() function to make that possible. Signed-off-by: Thomas Gleixner --- block/blk-mq.c | 2 +- drivers/staging/android/vsoc.c | 2 +- kernel/futex.c | 4 ++-- net/core/pktgen.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index df3fafbfe9a9..f567146f9ed7 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3422,7 +3422,7 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q, if (blk_mq_rq_state(rq) == MQ_RQ_COMPLETE) break; set_current_state(TASK_UNINTERRUPTIBLE); - hrtimer_start_expires(&hs.timer, mode); + hrtimer_sleeper_start_expires(&hs, mode); if (hs.task) io_schedule(); hrtimer_cancel(&hs.timer); diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c index 2d6b3981afb8..1240bb0317d9 100644 --- a/drivers/staging/android/vsoc.c +++ b/drivers/staging/android/vsoc.c @@ -458,7 +458,7 @@ static int handle_vsoc_cond_wait(struct file *filp, struct vsoc_cond_wait *arg) break; } if (to) { - hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS); + hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS); if (likely(to->task)) freezable_schedule(); hrtimer_cancel(&to->timer); diff --git a/kernel/futex.c b/kernel/futex.c index c8561aa5338e..bd18f60e4c6c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2611,7 +2611,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q, /* Arm the timer */ if (timeout) - hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS); + hrtimer_sleeper_start_expires(timeout, HRTIMER_MODE_ABS); /* * If we have been removed from the hash list, then another task @@ -2897,7 +2897,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, } if (unlikely(to)) - hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS); + hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS); ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index a5905975bc12..1d0c1b4886d7 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2172,7 +2172,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) } else { do { set_current_state(TASK_INTERRUPTIBLE); - hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS); + hrtimer_sleeper_start_expires(&t, HRTIMER_MODE_ABS); if (likely(t.task)) schedule(); -- GitLab From ae6683d815895c2be1e60e1942630fa99488055b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:51 +0200 Subject: [PATCH 1524/7155] hrtimer: Introduce HARD expiry mode On PREEMPT_RT not all hrtimers can be expired in hard interrupt context even if that is perfectly fine on a PREEMPT_RT=n kernel, e.g. because they take regular spinlocks. Also for latency reasons PREEMPT_RT tries to defer most hrtimers' expiry into soft interrupt context. But there are hrtimers which must be expired in hard interrupt context even when PREEMPT_RT is enabled: - hrtimers which must expiry in hard interrupt context, e.g. scheduler, perf, watchdog related hrtimers - latency critical hrtimers, e.g. nanosleep, ..., kvm lapic timer Add a new mode flag HRTIMER_MODE_HARD which allows to mark these timers so PREEMPT_RT will not move them into softirq expiry mode. [ tglx: Split out of a larger combo patch. Added changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185752.981398465@linutronix.de --- include/linux/hrtimer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 24072a0942c0..15c2ba6b6316 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -38,6 +38,7 @@ enum hrtimer_mode { HRTIMER_MODE_REL = 0x01, HRTIMER_MODE_PINNED = 0x02, HRTIMER_MODE_SOFT = 0x04, + HRTIMER_MODE_HARD = 0x08, HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED, HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED, @@ -48,6 +49,11 @@ enum hrtimer_mode { HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT, HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT, + HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD, + HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD, + + HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD, + HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD, }; /* -- GitLab From 82e17a09c412ad981dd29c0243b73b363835899e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 23:39:17 +0100 Subject: [PATCH 1525/7155] usb: musb: remove redundant assignment to variable ret Variable ret is being initialized with a value that is never read and ret is being re-assigned a little later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190731223917.16532-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 9f5a4819a744..2bc55e0ceace 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1721,7 +1721,7 @@ mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct musb *musb = dev_to_musb(dev); unsigned long flags; - int ret = -EINVAL; + int ret; spin_lock_irqsave(&musb->lock, flags); ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->otg->state)); -- GitLab From d1f54df4fbb5e525bea4ecc60ceb1e5cf2387689 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 15:42:41 +0200 Subject: [PATCH 1526/7155] usb: wusbcore: Spelling s/disconenct/disconnect/ Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190731134241.18647-1-geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/devconnect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index a93837d57d53..1170f8baf608 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -49,7 +49,7 @@ * for processing a DN_Alive pong from a device. * * wusb_handle_dn_disconnect()Called by notif.c:wusb_handle_dn() to - * process a disconenct request from a + * process a disconnect request from a * device. * * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when -- GitLab From eb6c2eb6c7fbd24b51fba2fa4b270c839b8b8349 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 31 Jul 2019 14:11:50 +0200 Subject: [PATCH 1527/7155] usb: host: xhci-plat: Prevent an abnormally restrictive PHY init skipping In the past, USB PHY handling has been moved in the HCD core. Some host controller drivers needing more control of the PHYs, they have been granted the freedom to handle themselves the PHY states and to prevent the HCD core to do so in commit 4e88d4c08301 ("usb: add a flag to skip PHY initialization to struct usb_hcd"). With this change, any USB host controller could set the hcd->skip_phy_initialization flag so that the HCD core would just skip the PHY initialization sequence. However, in the USB subsystem, there are currently two entirely different forms of PHY: one is called 'usb_phy' and is USB-subsystem-wide, while there is also the generic and kernel-wide 'phy' from the (recent) generic PHY framework. When the commit above was introduced, both type of PHYs where handled by the HCD core. Later, commit bc40f5341741 ("USB: core: hcd: drop support for legacy phys") removed the support for the former type of PHYs in the HCD core. These 'usb_phy' are still present though, but managed from the controller drivers only. Hence, setting the hcd->skip_phy_initialization flag just because a 'usb_phy' is initialized by a controller driver is a non-sense. For instance on Armada CP110, a 'usb_phy' is there to enable the power supply to the USB host, while there is also a COMPHY block providing SERDES lanes configuration that is referenced as a PHY from the common PHY framework. Right now, users of the xhci-plat.c driver either use a 'usb_phy' only and do not care about the attempt of generic PHY initialization within the HCD core (as there is none); or they use a single 'phy' and the code flow does not pass through the block setting hcd->skip_phy_initialization anyway. While there is not users of both PHY types at the same time, drop this limitation from the xhci-plat.c driver. Note that the tegra driver probably has the same limitation and could definitely benefit from a similar change. Cc: Johan Hovold Cc: Martin Blumenstingl Signed-off-by: Miquel Raynal Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20190731121150.2253-1-miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 998241f5fce3..a1e5ce484bf8 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -307,7 +307,6 @@ static int xhci_plat_probe(struct platform_device *pdev) ret = usb_phy_init(hcd->usb_phy); if (ret) goto put_usb3_hcd; - hcd->skip_phy_initialization = 1; } hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); -- GitLab From 572d8be0d4dd2251396dca38d176354180be7683 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 09:53:07 +0800 Subject: [PATCH 1528/7155] staging: rtl8723bs: remove set but not used variable 'bEEPROMCheck' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs//hal/odm_CfoTracking.c: In function 'odm_SetCrystalCap': drivers/staging/rtl8723bs//hal/odm_CfoTracking.c:14:7: warning: variable 'bEEPROMCheck' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190801015307.44572-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm_CfoTracking.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c index a73304639226..95edd148ac24 100644 --- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c +++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c @@ -11,11 +11,6 @@ static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap) { PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; - bool bEEPROMCheck; - struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - - bEEPROMCheck = pHalData->EEPROMVersion >= 0x01; if (pCfoTrack->CrystalCap == CrystalCap) return; -- GitLab From 09acf29c8246a20c6e255969df7e1131317181da Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Wed, 31 Jul 2019 09:19:21 -0500 Subject: [PATCH 1529/7155] staging: rtl8192u: null check the kzalloc In rtl8192_init_priv_variable allocation for priv->pFirmware may fail, so a null check is necessary.priv->pFirmware is accessed later in rtl8192_adapter_start. I added the check and made appropriate changes to propagate the errno to the caller. Signed-off-by: Navid Emamdoost Link: https://lore.kernel.org/r/20190731141925.29268-1-navid.emamdoost@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index fe1f279ca368..569d02240bf5 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2096,7 +2096,7 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) } /* init priv variables here. only non_zero value should be initialized here. */ -static void rtl8192_init_priv_variable(struct net_device *dev) +static int rtl8192_init_priv_variable(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u8 i; @@ -2223,6 +2223,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) priv->AcmControl = 0; priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL); + if (!priv->pFirmware) + return -ENOMEM; /* rx related queue */ skb_queue_head_init(&priv->rx_queue); @@ -2236,6 +2238,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) for (i = 0; i < MAX_QUEUE_SIZE; i++) skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]); priv->rf_set_chan = rtl8192_phy_SwChnl; + + return 0; } /* init lock here */ @@ -2605,7 +2609,10 @@ static short rtl8192_init(struct net_device *dev) memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9); } #endif - rtl8192_init_priv_variable(dev); + err = rtl8192_init_priv_variable(dev); + if (err) + return err; + rtl8192_init_priv_lock(priv); rtl8192_init_priv_task(dev); rtl8192_get_eeprom_size(dev); -- GitLab From d698b0a09656818beafd8ea7295d7c20bc74f9bc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 31 Jul 2019 21:59:53 +0800 Subject: [PATCH 1530/7155] staging: rtl8723bs: remove set but not used variables 'prspbuf' and 'auth' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/core/rtw_cmd.c: In function rtw_cmd_thread: drivers/staging/rtl8723bs/core/rtw_cmd.c:405:16: warning: variable prspbuf set but not used [-Wunused-but-set-variable] drivers/staging/rtl8723bs/core/rtw_cmd.c: In function rtw_joinbss_cmd: drivers/staging/rtl8723bs/core/rtw_cmd.c:771:6: warning: variable auth set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190731135953.16784-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_cmd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index addc55706a3c..c6565b0e502c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -402,7 +402,7 @@ int rtw_cmd_thread(void *context) { u8 ret; struct cmd_obj *pcmd; - u8 *pcmdbuf, *prspbuf; + u8 *pcmdbuf; unsigned long cmd_start_time; unsigned long cmd_process_time; u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); @@ -414,7 +414,6 @@ int rtw_cmd_thread(void *context) thread_enter("RTW_CMD_THREAD"); pcmdbuf = pcmdpriv->cmd_buf; - prspbuf = pcmdpriv->rsp_buf; pcmdpriv->stop_req = 0; atomic_set(&(pcmdpriv->cmdthd_running), true); @@ -768,7 +767,7 @@ int rtw_startbss_cmd(struct adapter *padapter, int flags) u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) { - u8 *auth, res = _SUCCESS; + u8 res = _SUCCESS; uint t_len = 0; struct wlan_bssid_ex *psecnetwork; struct cmd_obj *pcmd; @@ -825,7 +824,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); - auth = &psecuritypriv->authenticator_ie[0]; psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; if ((psecnetwork->IELength-12) < (256-1)) { -- GitLab From b0d08afda84dde941226f67cb12dd9cbde40ede4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 31 Jul 2019 22:09:03 +0800 Subject: [PATCH 1531/7155] staging: rtl8723bs: remove set but not used variable 'FirstConnect' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/odm.c: In function 'odm_RSSIMonitorCheckCE': drivers/staging/rtl8723bs/hal/odm.c:1258:7: warning: variable 'FirstConnect' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190731140903.304-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index dd9a16fb83a4..aa6631ee4ea7 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -1255,13 +1255,11 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; u8 sta_cnt = 0; u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - bool FirstConnect = false; pRA_T pRA_Table = &pDM_Odm->DM_RA_Table; if (pDM_Odm->bLinked != true) return; - FirstConnect = (pDM_Odm->bLinked) && (pRA_Table->firstconnect == false); pRA_Table->firstconnect = pDM_Odm->bLinked; /* if (check_fwstate(&Adapter->mlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true) */ -- GitLab From 3230a55b3633aa09c91bd83b794cbdfff5f7c680 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:22:02 +0800 Subject: [PATCH 1532/7155] mvpp2: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 937e4b928b94..e9d8ffe897e9 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -5014,7 +5014,6 @@ static int mvpp2_port_probe(struct platform_device *pdev, struct device_node *port_node = to_of_node(port_fwnode); netdev_features_t features; struct net_device *dev; - struct resource *res; struct phylink *phylink; char *mac_from = ""; unsigned int ntxqs, nrxqs, thread; @@ -5118,8 +5117,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, port->comphy = comphy; if (priv->hw_version == MVPP21) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 2 + id); - port->base = devm_ioremap_resource(&pdev->dev, res); + port->base = devm_platform_ioremap_resource(pdev, 2 + id); if (IS_ERR(port->base)) { err = PTR_ERR(port->base); goto err_free_irq; @@ -5551,14 +5549,12 @@ static int mvpp2_probe(struct platform_device *pdev) if (priv->hw_version == MVPP21) queue_mode = MVPP2_QDIST_SINGLE_MODE; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); if (priv->hw_version == MVPP21) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->lms_base = devm_ioremap_resource(&pdev->dev, res); + priv->lms_base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->lms_base)) return PTR_ERR(priv->lms_base); } else { -- GitLab From 6551c8c807b8d35b404f5a4bfeb02b20bf8c1fad Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:25:46 +0800 Subject: [PATCH 1533/7155] net: dsa: lantiq: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 4e64835deac2..2175ec13bb2c 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1822,7 +1822,6 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv, static int gswip_probe(struct platform_device *pdev) { struct gswip_priv *priv; - struct resource *gswip_res, *mdio_res, *mii_res; struct device_node *mdio_np, *gphy_fw_np; struct device *dev = &pdev->dev; int err; @@ -1833,18 +1832,15 @@ static int gswip_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - gswip_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->gswip = devm_ioremap_resource(dev, gswip_res); + priv->gswip = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->gswip)) return PTR_ERR(priv->gswip); - mdio_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->mdio = devm_ioremap_resource(dev, mdio_res); + priv->mdio = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->mdio)) return PTR_ERR(priv->mdio); - mii_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - priv->mii = devm_ioremap_resource(dev, mii_res); + priv->mii = devm_platform_ioremap_resource(pdev, 2); if (IS_ERR(priv->mii)) return PTR_ERR(priv->mii); -- GitLab From 291f4b6de48aa8a4140a189ab974d7c398d72bea Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:27:32 +0800 Subject: [PATCH 1534/7155] net: dsa: b53: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/dsa/b53/b53_srab.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c index d9c56a779c08..0a1be5259be0 100644 --- a/drivers/net/dsa/b53/b53_srab.c +++ b/drivers/net/dsa/b53/b53_srab.c @@ -536,7 +536,6 @@ static void b53_srab_mux_init(struct platform_device *pdev) struct b53_device *dev = platform_get_drvdata(pdev); struct b53_srab_priv *priv = dev->priv; struct b53_srab_port_priv *p; - struct resource *r; unsigned int port; u32 reg, off = 0; int ret; @@ -544,8 +543,7 @@ static void b53_srab_mux_init(struct platform_device *pdev) if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID) return; - r = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->mux_config = devm_ioremap_resource(&pdev->dev, r); + priv->mux_config = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->mux_config)) return; @@ -593,7 +591,6 @@ static int b53_srab_probe(struct platform_device *pdev) const struct of_device_id *of_id = NULL; struct b53_srab_priv *priv; struct b53_device *dev; - struct resource *r; if (dn) of_id = of_match_node(b53_srab_of_match, dn); @@ -610,8 +607,7 @@ static int b53_srab_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = devm_ioremap_resource(&pdev->dev, r); + priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) return -ENOMEM; -- GitLab From 42376788469bb3d543f9e287796465166d2b40fe Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:29:11 +0800 Subject: [PATCH 1535/7155] net: dsa: bcm_sf2: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 3811fdbda13e..49f99436018a 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1041,7 +1041,6 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) struct b53_device *dev; struct dsa_switch *ds; void __iomem **base; - struct resource *r; unsigned int i; u32 reg, rev; int ret; @@ -1107,8 +1106,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) base = &priv->core; for (i = 0; i < BCM_SF2_REGS_NUM; i++) { - r = platform_get_resource(pdev, IORESOURCE_MEM, i); - *base = devm_ioremap_resource(&pdev->dev, r); + *base = devm_platform_ioremap_resource(pdev, i); if (IS_ERR(*base)) { pr_err("unable to find register: %s\n", reg_names[i]); return PTR_ERR(*base); -- GitLab From 566495de16580a3cb730b7975f1ae75fa1308fd5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:33:08 +0800 Subject: [PATCH 1536/7155] net: mediatek: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index e529d86468b8..ddbffeb5701b 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -2447,7 +2447,6 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) static int mtk_probe(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct device_node *mac_np; struct mtk_eth *eth; int err; @@ -2460,7 +2459,7 @@ static int mtk_probe(struct platform_device *pdev) eth->soc = of_device_get_match_data(&pdev->dev); eth->dev = &pdev->dev; - eth->base = devm_ioremap_resource(&pdev->dev, res); + eth->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(eth->base)) return PTR_ERR(eth->base); -- GitLab From c792c0081db67252c52de4d4b82356edf0dc71c5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:34:30 +0800 Subject: [PATCH 1537/7155] net: qcom/emac: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index bfe10464c81f..c84ab052ef26 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -544,7 +544,6 @@ static int emac_probe_resources(struct platform_device *pdev, struct emac_adapter *adpt) { struct net_device *netdev = adpt->netdev; - struct resource *res; char maddr[ETH_ALEN]; int ret = 0; @@ -561,14 +560,12 @@ static int emac_probe_resources(struct platform_device *pdev, adpt->irq.irq = ret; /* base register address */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adpt->base = devm_ioremap_resource(&pdev->dev, res); + adpt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adpt->base)) return PTR_ERR(adpt->base); /* CSR register address */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - adpt->csr = devm_ioremap_resource(&pdev->dev, res); + adpt->csr = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(adpt->csr)) return PTR_ERR(adpt->csr); -- GitLab From 9d26cfa5b0d221e8655592e93b86f2e5e5cb4570 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:39:08 +0800 Subject: [PATCH 1538/7155] bcm63xx_enet: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 291e4afd4a1a..620cd3fc1fbc 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1693,7 +1693,7 @@ static int bcm_enet_probe(struct platform_device *pdev) struct bcm_enet_priv *priv; struct net_device *dev; struct bcm63xx_enet_platform_data *pd; - struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx; + struct resource *res_irq, *res_irq_rx, *res_irq_tx; struct mii_bus *bus; int i, ret; @@ -1719,8 +1719,7 @@ static int bcm_enet_probe(struct platform_device *pdev) if (ret) goto out; - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res_mem); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto out; @@ -2762,15 +2761,13 @@ struct platform_driver bcm63xx_enetsw_driver = { /* reserve & remap memory space shared between all macs */ static int bcm_enet_shared_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *p[3]; unsigned int i; memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base)); for (i = 0; i < 3; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - p[i] = devm_ioremap_resource(&pdev->dev, res); + p[i] = devm_platform_ioremap_resource(pdev, i); if (IS_ERR(p[i])) return PTR_ERR(p[i]); } -- GitLab From 0ae9fce32c5e5dafcbc7a5ed97a962d021423d31 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 20:46:30 +0800 Subject: [PATCH 1539/7155] net: phy: xgene: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/phy/mdio-xgene.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c index 717cc2a056e8..34990eaa3298 100644 --- a/drivers/net/phy/mdio-xgene.c +++ b/drivers/net/phy/mdio-xgene.c @@ -328,7 +328,6 @@ static int xgene_mdio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mii_bus *mdio_bus; const struct of_device_id *of_id; - struct resource *res; struct xgene_mdio_pdata *pdata; void __iomem *csr_base; int mdio_id = 0, ret = 0; @@ -355,8 +354,7 @@ static int xgene_mdio_probe(struct platform_device *pdev) pdata->mdio_id = mdio_id; pdata->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - csr_base = devm_ioremap_resource(dev, res); + csr_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(csr_base)) return PTR_ERR(csr_base); pdata->mac_csr_addr = csr_base; -- GitLab From ed8fb4b262aed95974ccd624402a482c4d59c888 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 1 Aug 2019 11:55:34 +0800 Subject: [PATCH 1540/7155] net: hns3: add link change event report Previously, PF updates link status per second. For some scenario, it requires link down event being reported more quickly. To solve it, firmware pushes the link change event to PF with CMDQ message, and driver updates the link status directly. Signed-off-by: Jian Shen Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 1 + .../hisilicon/hns3/hns3pf/hclge_cmd.c | 25 ++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_cmd.h | 7 ++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 9 ++--- .../hisilicon/hns3/hns3pf/hclge_main.h | 8 +++++ .../hisilicon/hns3/hns3pf/hclge_mbx.c | 33 +++++++++++++++++++ 6 files changed, 79 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 75329ab775a6..1564be5e148b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -47,6 +47,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_GET_MEDIA_TYPE, /* (VF -> PF) get media type */ HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */ + HCLGE_MBX_PUSH_LINK_STATUS, /* (M7 -> PF) get port link status */ }; /* below are per-VF mac-vlan subcodes */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index d9858f285460..538d1017592a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -383,6 +383,22 @@ int hclge_cmd_queue_init(struct hclge_dev *hdev) return ret; } +static int hclge_firmware_compat_config(struct hclge_dev *hdev) +{ + struct hclge_firmware_compat_cmd *req; + struct hclge_desc desc; + u32 compat = 0; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_M7_COMPAT_CFG, false); + + req = (struct hclge_firmware_compat_cmd *)desc.data; + + hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); + req->compat = cpu_to_le32(compat); + + return hclge_cmd_send(&hdev->hw, &desc, 1); +} + int hclge_cmd_init(struct hclge_dev *hdev) { u32 version; @@ -429,6 +445,15 @@ int hclge_cmd_init(struct hclge_dev *hdev) hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK, HNAE3_FW_VERSION_BYTE0_SHIFT)); + /* ask the firmware to enable some features, driver can work without + * it. + */ + ret = hclge_firmware_compat_config(hdev); + if (ret) + dev_warn(&hdev->pdev->dev, + "Firmware compatible features not enabled(%d).\n", + ret); + return 0; err_cmd_init: diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 96840d8f3e24..743c9f41c67e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -257,6 +257,7 @@ enum hclge_opcode_type { /* M7 stats command */ HCLGE_OPC_M7_STATS_BD = 0x7012, HCLGE_OPC_M7_STATS_INFO = 0x7013, + HCLGE_OPC_M7_COMPAT_CFG = 0x701A, /* SFP command */ HCLGE_OPC_GET_SFP_INFO = 0x7104, @@ -1009,6 +1010,12 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd { u8 rsv[4]; }; +#define HCLGE_LINK_EVENT_REPORT_EN_B 0 +struct hclge_firmware_compat_cmd { + __le32 compat; + u8 rsv[20]; +}; + int hclge_cmd_init(struct hclge_dev *hdev); static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4138780fca39..855b65e8ebf6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2517,7 +2517,7 @@ static void hclge_reset_task_schedule(struct hclge_dev *hdev) &hdev->rst_service_task); } -static void hclge_task_schedule(struct hclge_dev *hdev) +void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time) { if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) && !test_bit(HCLGE_STATE_REMOVING, &hdev->state) && @@ -2526,7 +2526,7 @@ static void hclge_task_schedule(struct hclge_dev *hdev) hdev->fd_arfs_expire_timer++; mod_delayed_work_on(cpumask_first(&hdev->affinity_mask), system_wq, &hdev->service_task, - round_jiffies_relative(HZ)); + delay_time); } } @@ -3636,7 +3636,7 @@ static void hclge_service_task(struct work_struct *work) hdev->fd_arfs_expire_timer = 0; } - hclge_task_schedule(hdev); + hclge_task_schedule(hdev, round_jiffies_relative(HZ)); } struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle) @@ -6175,7 +6175,7 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable) struct hclge_dev *hdev = vport->back; if (enable) { - hclge_task_schedule(hdev); + hclge_task_schedule(hdev, round_jiffies_relative(HZ)); } else { /* Set the DOWN flag here to disable the service to be * scheduled again @@ -6220,6 +6220,7 @@ static void hclge_ae_stop(struct hnae3_handle *handle) if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) && hdev->reset_type != HNAE3_FUNC_RESET) { hclge_mac_stop_phy(hdev); + hclge_update_link_status(hdev); return; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 688e4250491d..c9b9867fc226 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -302,6 +302,13 @@ enum hclge_fc_mode { HCLGE_FC_DEFAULT }; +enum hclge_link_fail_code { + HCLGE_LF_NORMAL, + HCLGE_LF_REF_CLOCK_LOST, + HCLGE_LF_XSFP_TX_DISABLE, + HCLGE_LF_XSFP_ABSENT, +}; + #define HCLGE_PG_NUM 4 #define HCLGE_SCH_MODE_SP 0 #define HCLGE_SCH_MODE_DWRR 1 @@ -1021,4 +1028,5 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, u16 state, u16 vlan_tag, u16 qos, u16 vlan_proto); +void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 690b9990215c..87de32dfa6c8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -545,6 +545,36 @@ static int hclge_get_rss_key(struct hclge_vport *vport, HCLGE_RSS_MBX_RESP_LEN); } +static void hclge_link_fail_parse(struct hclge_dev *hdev, u8 link_fail_code) +{ + switch (link_fail_code) { + case HCLGE_LF_REF_CLOCK_LOST: + dev_warn(&hdev->pdev->dev, "Reference clock lost!\n"); + break; + case HCLGE_LF_XSFP_TX_DISABLE: + dev_warn(&hdev->pdev->dev, "SFP tx is disabled!\n"); + break; + case HCLGE_LF_XSFP_ABSENT: + dev_warn(&hdev->pdev->dev, "SFP is absent!\n"); + break; + default: + break; + } +} + +static void hclge_handle_link_change_event(struct hclge_dev *hdev, + struct hclge_mbx_vf_to_pf_cmd *req) +{ +#define LINK_STATUS_OFFSET 1 +#define LINK_FAIL_CODE_OFFSET 2 + + clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); + hclge_task_schedule(hdev, 0); + + if (!req->msg[LINK_STATUS_OFFSET]) + hclge_link_fail_parse(hdev, req->msg[LINK_FAIL_CODE_OFFSET]); +} + static bool hclge_cmd_crq_empty(struct hclge_hw *hw) { u32 tail = hclge_read_dev(hw, HCLGE_NIC_CRQ_TAIL_REG); @@ -707,6 +737,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev) "PF fail(%d) to media type for VF\n", ret); break; + case HCLGE_MBX_PUSH_LINK_STATUS: + hclge_handle_link_change_event(hdev, req); + break; default: dev_err(&hdev->pdev->dev, "un-supported mailbox message, code = %d\n", -- GitLab From b18bf305c46c20e289c6d030b21b13b632e8a459 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 1 Aug 2019 11:55:35 +0800 Subject: [PATCH 1541/7155] net: hns3: add handler for NCSI error mailbox When NCSI has HW error, the IMP will report this error to the driver by sending a mailbox. After received this message, the driver should assert a global reset to fix this kind of HW error. Signed-off-by: Huazhong Tan Reviewed-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 1 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 1 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 12 ++++++++++++ 4 files changed, 15 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 1564be5e148b..f8a87f8ca983 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -48,6 +48,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */ HCLGE_MBX_PUSH_LINK_STATUS, /* (M7 -> PF) get port link status */ + HCLGE_MBX_NCSI_ERROR, /* (M7 -> PF) receive a NCSI error */ }; /* below are per-VF mac-vlan subcodes */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 538d1017592a..c20b972d21f7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -394,6 +394,7 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev) req = (struct hclge_firmware_compat_cmd *)desc.data; hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); + hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); req->compat = cpu_to_le32(compat); return hclge_cmd_send(&hdev->hw, &desc, 1); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 743c9f41c67e..070b9ddb6ffe 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -1011,6 +1011,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd { }; #define HCLGE_LINK_EVENT_REPORT_EN_B 0 +#define HCLGE_NCSI_ERROR_REPORT_EN_B 1 struct hclge_firmware_compat_cmd { __le32 compat; u8 rsv[20]; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 87de32dfa6c8..5a7221ee6bb9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -582,6 +582,15 @@ static bool hclge_cmd_crq_empty(struct hclge_hw *hw) return tail == hw->cmq.crq.next_to_use; } +static void hclge_handle_ncsi_error(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = hdev->ae_dev; + + ae_dev->ops->set_default_reset_request(ae_dev, HNAE3_GLOBAL_RESET); + dev_warn(&hdev->pdev->dev, "requesting reset due to NCSI error\n"); + ae_dev->ops->reset_event(hdev->pdev, NULL); +} + void hclge_mbx_handler(struct hclge_dev *hdev) { struct hclge_cmq_ring *crq = &hdev->hw.cmq.crq; @@ -740,6 +749,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev) case HCLGE_MBX_PUSH_LINK_STATUS: hclge_handle_link_change_event(hdev, req); break; + case HCLGE_MBX_NCSI_ERROR: + hclge_handle_ncsi_error(hdev); + break; default: dev_err(&hdev->pdev->dev, "un-supported mailbox message, code = %d\n", -- GitLab From 3f0f325309aca23cb241c1aded0056d78d7366a1 Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Thu, 1 Aug 2019 11:55:36 +0800 Subject: [PATCH 1542/7155] net: hns3: do not query unsupported commands in debugfs Some commands are not supported on DCB-unsupported ports. This patch distinguishes these commands and does not query unsupported commands in debugfs. This patch also fix an error in the dump "qos buf cfg" command in debugfs. Fixes: 2849d4e7a1be ("net: hns3: Add "tc config" info query function") Fixes: 7d9d7f8864ba ("net: hns3: Add "qos buffer" config info query function") Signed-off-by: Yufeng Mo Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 70 ++++++++++++------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index ab625c757a95..e987d18ae18d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -325,6 +325,12 @@ static void hclge_dbg_dump_tc(struct hclge_dev *hdev) struct hclge_desc desc; int i, ret; + if (!hnae3_dev_dcb_supported(hdev)) { + dev_info(&hdev->pdev->dev, + "Only DCB-supported dev supports tc\n"); + return; + } + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -409,6 +415,12 @@ static void hclge_dbg_dump_tm_pg(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "QS_SCH qs_id: %u\n", desc.data[0]); + if (!hnae3_dev_dcb_supported(hdev)) { + dev_info(&hdev->pdev->dev, + "Only DCB-supported dev supports tm mapping\n"); + return; + } + cmd = HCLGE_OPC_TM_BP_TO_QSET_MAPPING; hclge_cmd_setup_basic_desc(&desc, cmd, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -590,6 +602,12 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, dev_info(&hdev->pdev->dev, "%04d | %04d | %02d | %02d\n", queue_id, qset_id, pri_id, tc_id); + if (!hnae3_dev_dcb_supported(hdev)) { + dev_info(&hdev->pdev->dev, + "Only DCB-supported dev supports tm mapping\n"); + return; + } + cmd = HCLGE_OPC_TM_BP_TO_QSET_MAPPING; bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; for (group_id = 0; group_id < 32; group_id++) { @@ -715,6 +733,34 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "rx_share_buf: 0x%x\n", rx_buf_cmd->shared_buf); + cmd = HCLGE_OPC_RX_COM_WL_ALLOC; + hclge_cmd_setup_basic_desc(desc, cmd, true); + ret = hclge_cmd_send(&hdev->hw, desc, 1); + if (ret) + goto err_qos_cmd_send; + + rx_com_wl = (struct hclge_rx_com_wl *)desc[0].data; + dev_info(&hdev->pdev->dev, "\n"); + dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n", + rx_com_wl->com_wl.high, rx_com_wl->com_wl.low); + + cmd = HCLGE_OPC_RX_GBL_PKT_CNT; + hclge_cmd_setup_basic_desc(desc, cmd, true); + ret = hclge_cmd_send(&hdev->hw, desc, 1); + if (ret) + goto err_qos_cmd_send; + + rx_packet_cnt = (struct hclge_rx_com_wl *)desc[0].data; + dev_info(&hdev->pdev->dev, + "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n", + rx_packet_cnt->com_wl.high, rx_packet_cnt->com_wl.low); + dev_info(&hdev->pdev->dev, "\n"); + + if (!hnae3_dev_dcb_supported(hdev)) { + dev_info(&hdev->pdev->dev, + "Only DCB-supported dev supports rx priv wl\n"); + return; + } cmd = HCLGE_OPC_RX_PRIV_WL_ALLOC; hclge_cmd_setup_basic_desc(&desc[0], cmd, true); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); @@ -723,7 +769,6 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) if (ret) goto err_qos_cmd_send; - dev_info(&hdev->pdev->dev, "\n"); rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[0].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) dev_info(&hdev->pdev->dev, @@ -758,29 +803,6 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i + 4, rx_com_thrd->com_thrd[i].high, rx_com_thrd->com_thrd[i].low); - - cmd = HCLGE_OPC_RX_COM_WL_ALLOC; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); - if (ret) - goto err_qos_cmd_send; - - rx_com_wl = (struct hclge_rx_com_wl *)desc[0].data; - dev_info(&hdev->pdev->dev, "\n"); - dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n", - rx_com_wl->com_wl.high, rx_com_wl->com_wl.low); - - cmd = HCLGE_OPC_RX_GBL_PKT_CNT; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); - if (ret) - goto err_qos_cmd_send; - - rx_packet_cnt = (struct hclge_rx_com_wl *)desc[0].data; - dev_info(&hdev->pdev->dev, - "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n", - rx_packet_cnt->com_wl.high, rx_packet_cnt->com_wl.low); - return; err_qos_cmd_send: -- GitLab From a723fb8efe29d3912d2be41edcf38b76f8d6ed36 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 1 Aug 2019 11:55:37 +0800 Subject: [PATCH 1543/7155] net: hns3: refine for set ring parameters Previously, when changing the ring parameters, we free the old ring resources firstly, and then setup the new ring resources. In some case of an memory allocation fail, there will be no resources to use. This patch refines it by setup new ring resources and free the old ring resources in order. Also reduce the max ring BD number to 32760 according to UM. Signed-off-by: Jian Shen Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 3 +- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 88 +++++++++++++------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index d2df42d30d88..79973a016762 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3588,7 +3588,7 @@ static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring) return ret; } -static void hns3_fini_ring(struct hns3_enet_ring *ring) +void hns3_fini_ring(struct hns3_enet_ring *ring) { hns3_free_desc(ring); devm_kfree(ring_to_dev(ring), ring->desc_cb); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 1a17856f9a3b..0a970f5fed10 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -75,7 +75,7 @@ enum hns3_nic_state { #define HNS3_TX_TIMEOUT (5 * HZ) #define HNS3_RING_NAME_LEN 16 #define HNS3_BUFFER_SIZE_2048 2048 -#define HNS3_RING_MAX_PENDING 32768 +#define HNS3_RING_MAX_PENDING 32760 #define HNS3_RING_MIN_PENDING 24 #define HNS3_RING_BD_MULTIPLE 8 /* max frame size of mac */ @@ -642,6 +642,7 @@ void hns3_clean_tx_ring(struct hns3_enet_ring *ring); int hns3_init_all_ring(struct hns3_nic_priv *priv); int hns3_uninit_all_ring(struct hns3_nic_priv *priv); int hns3_nic_reset_all_ring(struct hnae3_handle *h); +void hns3_fini_ring(struct hns3_enet_ring *ring); netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev); bool hns3_is_phys_func(struct pci_dev *pdev); int hns3_clean_rx_ring( diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index fe0f82a97234..02f46c73ac3b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -867,8 +867,8 @@ static int hns3_get_rxnfc(struct net_device *netdev, } } -static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, - u32 tx_desc_num, u32 rx_desc_num) +static void hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, + u32 tx_desc_num, u32 rx_desc_num) { struct hnae3_handle *h = priv->ae_handle; int i; @@ -881,21 +881,29 @@ static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, priv->ring_data[i + h->kinfo.num_tqps].ring->desc_num = rx_desc_num; } - - return hns3_init_all_ring(priv); } -static int hns3_set_ringparam(struct net_device *ndev, - struct ethtool_ringparam *param) +static struct hns3_enet_ring *hns3_backup_ringparam(struct hns3_nic_priv *priv) { - struct hns3_nic_priv *priv = netdev_priv(ndev); - struct hnae3_handle *h = priv->ae_handle; - bool if_running = netif_running(ndev); - u32 old_tx_desc_num, new_tx_desc_num; - u32 old_rx_desc_num, new_rx_desc_num; - int queue_num = h->kinfo.num_tqps; - int ret; + struct hnae3_handle *handle = priv->ae_handle; + struct hns3_enet_ring *tmp_rings; + int i; + tmp_rings = kcalloc(handle->kinfo.num_tqps * 2, + sizeof(struct hns3_enet_ring), GFP_KERNEL); + if (!tmp_rings) + return NULL; + + for (i = 0; i < handle->kinfo.num_tqps * 2; i++) + memcpy(&tmp_rings[i], priv->ring_data[i].ring, + sizeof(struct hns3_enet_ring)); + + return tmp_rings; +} + +static int hns3_check_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +{ if (hns3_nic_resetting(ndev)) return -EBUSY; @@ -911,6 +919,25 @@ static int hns3_set_ringparam(struct net_device *ndev, return -EINVAL; } + return 0; +} + +static int hns3_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +{ + struct hns3_nic_priv *priv = netdev_priv(ndev); + struct hnae3_handle *h = priv->ae_handle; + struct hns3_enet_ring *tmp_rings; + bool if_running = netif_running(ndev); + u32 old_tx_desc_num, new_tx_desc_num; + u32 old_rx_desc_num, new_rx_desc_num; + u16 queue_num = h->kinfo.num_tqps; + int ret, i; + + ret = hns3_check_ringparam(ndev, param); + if (ret) + return ret; + /* Hardware requires that its descriptors must be multiple of eight */ new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE); new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE); @@ -920,6 +947,13 @@ static int hns3_set_ringparam(struct net_device *ndev, old_rx_desc_num == new_rx_desc_num) return 0; + tmp_rings = hns3_backup_ringparam(priv); + if (!tmp_rings) { + netdev_err(ndev, + "backup ring param failed by allocating memory fail\n"); + return -ENOMEM; + } + netdev_info(ndev, "Changing Tx/Rx ring depth from %d/%d to %d/%d\n", old_tx_desc_num, old_rx_desc_num, @@ -928,22 +962,24 @@ static int hns3_set_ringparam(struct net_device *ndev, if (if_running) ndev->netdev_ops->ndo_stop(ndev); - ret = hns3_uninit_all_ring(priv); - if (ret) - return ret; - - ret = hns3_change_all_ring_bd_num(priv, new_tx_desc_num, - new_rx_desc_num); + hns3_change_all_ring_bd_num(priv, new_tx_desc_num, new_rx_desc_num); + ret = hns3_init_all_ring(priv); if (ret) { - ret = hns3_change_all_ring_bd_num(priv, old_tx_desc_num, - old_rx_desc_num); - if (ret) { - netdev_err(ndev, - "Revert to old bd num fail, ret=%d.\n", ret); - return ret; - } + netdev_err(ndev, "Change bd num fail, revert to old value(%d)\n", + ret); + + hns3_change_all_ring_bd_num(priv, old_tx_desc_num, + old_rx_desc_num); + for (i = 0; i < h->kinfo.num_tqps * 2; i++) + memcpy(priv->ring_data[i].ring, &tmp_rings[i], + sizeof(struct hns3_enet_ring)); + } else { + for (i = 0; i < h->kinfo.num_tqps * 2; i++) + hns3_fini_ring(&tmp_rings[i]); } + kfree(tmp_rings); + if (if_running) ret = ndev->netdev_ops->ndo_open(ndev); -- GitLab From 6e4139f69163fb5769c92a97b969ea0d9a114ced Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 1 Aug 2019 11:55:38 +0800 Subject: [PATCH 1544/7155] net: hns3: remove unnecessary variable in hclge_get_mac_vlan_cmd_status() The local variable return_status in hclge_get_mac_val_cmd_status() is useless. So this patch returns the error code directly, instead of using this variable. Also, replace some '%d' with '%u' in hclge_get_mac_val_cmd_status(). Signed-off-by: Jian Shen Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 855b65e8ebf6..4317c8fe68f3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6268,7 +6268,6 @@ static int hclge_get_mac_vlan_cmd_status(struct hclge_vport *vport, enum hclge_mac_vlan_tbl_opcode op) { struct hclge_dev *hdev = vport->back; - int return_status = -EIO; if (cmdq_resp) { dev_err(&hdev->pdev->dev, @@ -6279,52 +6278,53 @@ static int hclge_get_mac_vlan_cmd_status(struct hclge_vport *vport, if (op == HCLGE_MAC_VLAN_ADD) { if ((!resp_code) || (resp_code == 1)) { - return_status = 0; + return 0; } else if (resp_code == HCLGE_ADD_UC_OVERFLOW) { - return_status = -ENOSPC; dev_err(&hdev->pdev->dev, "add mac addr failed for uc_overflow.\n"); + return -ENOSPC; } else if (resp_code == HCLGE_ADD_MC_OVERFLOW) { - return_status = -ENOSPC; dev_err(&hdev->pdev->dev, "add mac addr failed for mc_overflow.\n"); - } else { - dev_err(&hdev->pdev->dev, - "add mac addr failed for undefined, code=%d.\n", - resp_code); + return -ENOSPC; } + + dev_err(&hdev->pdev->dev, + "add mac addr failed for undefined, code=%u.\n", + resp_code); + return -EIO; } else if (op == HCLGE_MAC_VLAN_REMOVE) { if (!resp_code) { - return_status = 0; + return 0; } else if (resp_code == 1) { - return_status = -ENOENT; dev_dbg(&hdev->pdev->dev, "remove mac addr failed for miss.\n"); - } else { - dev_err(&hdev->pdev->dev, - "remove mac addr failed for undefined, code=%d.\n", - resp_code); + return -ENOENT; } + + dev_err(&hdev->pdev->dev, + "remove mac addr failed for undefined, code=%u.\n", + resp_code); + return -EIO; } else if (op == HCLGE_MAC_VLAN_LKUP) { if (!resp_code) { - return_status = 0; + return 0; } else if (resp_code == 1) { - return_status = -ENOENT; dev_dbg(&hdev->pdev->dev, "lookup mac addr failed for miss.\n"); - } else { - dev_err(&hdev->pdev->dev, - "lookup mac addr failed for undefined, code=%d.\n", - resp_code); + return -ENOENT; } - } else { - return_status = -EINVAL; + dev_err(&hdev->pdev->dev, - "unknown opcode for get_mac_vlan_cmd_status,opcode=%d.\n", - op); + "lookup mac addr failed for undefined, code=%u.\n", + resp_code); + return -EIO; } - return return_status; + dev_err(&hdev->pdev->dev, + "unknown opcode for get_mac_vlan_cmd_status, opcode=%d.\n", op); + + return -EINVAL; } static int hclge_update_desc_vfid(struct hclge_desc *desc, int vfid, bool clr) -- GitLab From a4ee7624c003cc73a2eac9d9d5317b0c9fed89c4 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Thu, 1 Aug 2019 11:55:39 +0800 Subject: [PATCH 1545/7155] net: hns3: minor cleanup in hns3_clean_rx_ring The unused_count variable is used to indicate how many RX BD need attaching new buffer in hns3_clean_rx_ring, and the clean_count variable has the similar meaning. This patch removes the clean_count variable and use unused_count to uniformly indicate the RX BD that need attaching new buffer. This patch also clean up some coding style related to variable assignment in hns3_clean_rx_ring. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 79973a016762..ed05fb9f04ed 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2909,24 +2909,22 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget, void (*rx_fn)(struct hns3_enet_ring *, struct sk_buff *)) { #define RCB_NOF_ALLOC_RX_BUFF_ONCE 16 - int recv_pkts, recv_bds, clean_count, err; int unused_count = hns3_desc_unused(ring); struct sk_buff *skb = ring->skb; - int num; + int recv_pkts = 0; + int recv_bds = 0; + int err, num; num = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_FBDNUM_REG); rmb(); /* Make sure num taken effect before the other data is touched */ - recv_pkts = 0, recv_bds = 0, clean_count = 0; num -= unused_count; unused_count -= ring->pending_buf; while (recv_pkts < budget && recv_bds < num) { /* Reuse or realloc buffers */ - if (clean_count + unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) { - hns3_nic_alloc_rx_buffers(ring, - clean_count + unused_count); - clean_count = 0; + if (unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) { + hns3_nic_alloc_rx_buffers(ring, unused_count); unused_count = hns3_desc_unused(ring) - ring->pending_buf; } @@ -2940,7 +2938,7 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget, goto out; } else if (unlikely(err)) { /* Do jump the err */ recv_bds += ring->pending_buf; - clean_count += ring->pending_buf; + unused_count += ring->pending_buf; ring->skb = NULL; ring->pending_buf = 0; continue; @@ -2948,7 +2946,7 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget, rx_fn(ring, skb); recv_bds += ring->pending_buf; - clean_count += ring->pending_buf; + unused_count += ring->pending_buf; ring->skb = NULL; ring->pending_buf = 0; @@ -2957,8 +2955,8 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget, out: /* Make all data has been write before submit */ - if (clean_count + unused_count > 0) - hns3_nic_alloc_rx_buffers(ring, clean_count + unused_count); + if (unused_count > 0) + hns3_nic_alloc_rx_buffers(ring, unused_count); return recv_pkts; } -- GitLab From b6872fd361056f3bce3e9fcfe9535c4b6b737531 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Thu, 1 Aug 2019 11:55:40 +0800 Subject: [PATCH 1546/7155] net: hns3: minior error handling change for hclge_tm_schd_info_init When hclge_tm_schd_info_update calls hclge_tm_schd_info_init to initialize the schedule info, hdev->tm_info.num_pg and hdev->tx_sch_mode is not changed, which makes the checking in hclge_tm_schd_info_init unnecessary. So this patch moves the hdev->tm_info.num_pg and hdev->tx_sch_mode checking into hclge_tm_schd_init and changes the return type of hclge_tm_schd_info_init from int to void. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 3f41fa2bc414..f30d1126d378 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -650,12 +650,8 @@ static void hclge_pfc_info_init(struct hclge_dev *hdev) } } -static int hclge_tm_schd_info_init(struct hclge_dev *hdev) +static void hclge_tm_schd_info_init(struct hclge_dev *hdev) { - if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && - (hdev->tm_info.num_pg != 1)) - return -EINVAL; - hclge_tm_pg_info_init(hdev); hclge_tm_tc_info_init(hdev); @@ -663,8 +659,6 @@ static int hclge_tm_schd_info_init(struct hclge_dev *hdev) hclge_tm_vport_info_update(hdev); hclge_pfc_info_init(hdev); - - return 0; } static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev) @@ -1428,15 +1422,15 @@ int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) int hclge_tm_schd_init(struct hclge_dev *hdev) { - int ret; - /* fc_mode is HCLGE_FC_FULL on reset */ hdev->tm_info.fc_mode = HCLGE_FC_FULL; hdev->fc_mode_last_time = hdev->tm_info.fc_mode; - ret = hclge_tm_schd_info_init(hdev); - if (ret) - return ret; + if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE && + hdev->tm_info.num_pg != 1) + return -EINVAL; + + hclge_tm_schd_info_init(hdev); return hclge_tm_init_hw(hdev, true); } -- GitLab From dbae56a33f5881bad631b0121f9b4a5e7b2a454d Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Thu, 1 Aug 2019 11:55:41 +0800 Subject: [PATCH 1547/7155] net: hns3: simplify hclge_cmd_query_error() The 4th and 5th parameter of hclge_cmd_query_error is useless, so this patch removes them. Signed-off-by: Weihang Li Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_err.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 0a7243825e7b..05a4cdbf903a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -652,16 +652,11 @@ static void hclge_log_error(struct device *dev, char *reg, * @desc: descriptor for describing the command * @cmd: command opcode * @flag: flag for extended command structure - * @w_num: offset for setting the read interrupt type. - * @int_type: select which type of the interrupt for which the error - * info will be read(RAS-CE/RAS-NFE/RAS-FE etc). * * This function query the error info from hw register/s using command */ static int hclge_cmd_query_error(struct hclge_dev *hdev, - struct hclge_desc *desc, u32 cmd, - u16 flag, u8 w_num, - enum hclge_err_int_type int_type) + struct hclge_desc *desc, u32 cmd, u16 flag) { struct device *dev = &hdev->pdev->dev; int desc_num = 1; @@ -673,8 +668,6 @@ static int hclge_cmd_query_error(struct hclge_dev *hdev, hclge_cmd_setup_basic_desc(&desc[1], cmd, true); desc_num = 2; } - if (w_num) - desc[0].data[w_num] = cpu_to_le32(int_type); ret = hclge_cmd_send(&hdev->hw, &desc[0], desc_num); if (ret) @@ -872,8 +865,7 @@ static int hclge_config_tm_hw_err_int(struct hclge_dev *hdev, bool en) } /* configure TM QCN hw errors */ - ret = hclge_cmd_query_error(hdev, &desc, HCLGE_TM_QCN_MEM_INT_CFG, - 0, 0, 0); + ret = hclge_cmd_query_error(hdev, &desc, HCLGE_TM_QCN_MEM_INT_CFG, 0); if (ret) { dev_err(dev, "fail(%d) to read TM QCN CFG status\n", ret); return ret; @@ -1410,7 +1402,7 @@ static int hclge_log_rocee_ecc_error(struct hclge_dev *hdev) ret = hclge_cmd_query_error(hdev, &desc[0], HCLGE_QUERY_ROCEE_ECC_RAS_INFO_CMD, - HCLGE_CMD_FLAG_NEXT, 0, 0); + HCLGE_CMD_FLAG_NEXT); if (ret) { dev_err(dev, "failed(%d) to query ROCEE ECC error sts\n", ret); return ret; @@ -1434,7 +1426,7 @@ static int hclge_log_rocee_ovf_error(struct hclge_dev *hdev) /* read overflow error status */ ret = hclge_cmd_query_error(hdev, &desc[0], HCLGE_ROCEE_PF_RAS_INT_CMD, - 0, 0, 0); + 0); if (ret) { dev_err(dev, "failed(%d) to query ROCEE OVF error sts\n", ret); return ret; @@ -1483,8 +1475,7 @@ hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) /* read RAS error interrupt status */ ret = hclge_cmd_query_error(hdev, &desc[0], - HCLGE_QUERY_CLEAR_ROCEE_RAS_INT, - 0, 0, 0); + HCLGE_QUERY_CLEAR_ROCEE_RAS_INT, 0); if (ret) { dev_err(dev, "failed(%d) to query ROCEE RAS INT SRC\n", ret); /* reset everything for now */ -- GitLab From 6e6e7680630c1b80042a79f62509aab5f49e3e88 Mon Sep 17 00:00:00 2001 From: Guojia Liao Date: Thu, 1 Aug 2019 11:55:42 +0800 Subject: [PATCH 1548/7155] net: hns3: rename a member in struct hclge_mac_ethertype_idx_rd_cmd The member 'mac_add' defined in hclge_mac_ethertype_idx_rd_cmd means MAC address, so 'mac_addr' is a better name for it. Signed-off-by: Guojia Liao Signed-off-by: Guangbin Huang Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 070b9ddb6ffe..cfa77dd19a7e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -828,7 +828,7 @@ struct hclge_mac_ethertype_idx_rd_cmd { u8 flags; u8 resp_code; __le16 vlan_tag; - u8 mac_add[6]; + u8 mac_addr[6]; __le16 index; __le16 ethter_type; __le16 egress_port; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index e987d18ae18d..f16bfc67412a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -847,9 +847,9 @@ static void hclge_dbg_dump_mng_table(struct hclge_dev *hdev) memset(printf_buf, 0, HCLGE_DBG_BUF_LEN); snprintf(printf_buf, HCLGE_DBG_BUF_LEN, "%02u |%02x:%02x:%02x:%02x:%02x:%02x|", - req0->index, req0->mac_add[0], req0->mac_add[1], - req0->mac_add[2], req0->mac_add[3], req0->mac_add[4], - req0->mac_add[5]); + req0->index, req0->mac_addr[0], req0->mac_addr[1], + req0->mac_addr[2], req0->mac_addr[3], + req0->mac_addr[4], req0->mac_addr[5]); snprintf(printf_buf + strlen(printf_buf), HCLGE_DBG_BUF_LEN - strlen(printf_buf), -- GitLab From 6b428b4fbf986077d218287dd6f805f371cdf48f Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 1 Aug 2019 11:55:43 +0800 Subject: [PATCH 1549/7155] net: hns3: fix some reset handshake issue Currently, the driver sets handshake status to tell the hardware that the driver have downed the netdev and it can continue with reset process. The driver will clear the handshake status when re-initializing the CMDQ, and does not recover this status when reset fail, which may cause the hardware to wait for the handshake status to be set and not being able to continue with reset process. So this patch delays clearing handshake status just before UP, and recovers this status when reset fail. BTW, this patch adds a new function hclge(vf)_reset_handshake() to deal with the reset handshake issue, and renames HCLGE(VF)_NIC_CMQ_ENABLE to HCLGE(VF)_NIC_SW_RST_RDY which represents this register bit more accurately. Fixes: ada13ee3db7b ("net: hns3: add handshake with hardware while doing reset") Signed-off-by: Huazhong Tan Reviewed-by: Peng Li Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 7 +++-- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 7 +++-- .../hisilicon/hns3/hns3pf/hclge_main.c | 23 ++++++++++++-- .../hisilicon/hns3/hns3vf/hclgevf_cmd.c | 4 ++- .../hisilicon/hns3/hns3vf/hclgevf_cmd.h | 7 +++-- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 31 +++++++++++++++---- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index c20b972d21f7..ecf58cfd253d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -103,14 +103,17 @@ static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring) dma_addr_t dma = ring->desc_dma_addr; struct hclge_dev *hdev = ring->dev; struct hclge_hw *hw = &hdev->hw; + u32 reg_val; if (ring->ring_type == HCLGE_TYPE_CSQ) { hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG, lower_32_bits(dma)); hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG, upper_32_bits(dma)); - hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, - ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S); + reg_val = hclge_read_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG); + reg_val &= HCLGE_NIC_SW_RST_RDY; + reg_val |= ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S; + hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, reg_val); hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0); hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0); } else { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index cfa77dd19a7e..63cf9a7d5720 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -907,8 +907,11 @@ struct hclge_serdes_lb_cmd { #define HCLGE_NIC_CRQ_DEPTH_REG 0x27020 #define HCLGE_NIC_CRQ_TAIL_REG 0x27024 #define HCLGE_NIC_CRQ_HEAD_REG 0x27028 -#define HCLGE_NIC_CMQ_EN_B 16 -#define HCLGE_NIC_CMQ_ENABLE BIT(HCLGE_NIC_CMQ_EN_B) + +/* this bit indicates that the driver is ready for hardware reset */ +#define HCLGE_NIC_SW_RST_RDY_B 16 +#define HCLGE_NIC_SW_RST_RDY BIT(HCLGE_NIC_SW_RST_RDY_B) + #define HCLGE_NIC_CMQ_DESC_NUM 1024 #define HCLGE_NIC_CMQ_DESC_NUM_S 3 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4317c8fe68f3..abe4cee06d4a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3274,6 +3274,19 @@ static int hclge_reset_prepare_down(struct hclge_dev *hdev) return ret; } +static void hclge_reset_handshake(struct hclge_dev *hdev, bool enable) +{ + u32 reg_val; + + reg_val = hclge_read_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG); + if (enable) + reg_val |= HCLGE_NIC_SW_RST_RDY; + else + reg_val &= ~HCLGE_NIC_SW_RST_RDY; + + hclge_write_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG, reg_val); +} + static int hclge_reset_prepare_wait(struct hclge_dev *hdev) { #define HCLGE_RESET_SYNC_TIME 100 @@ -3322,8 +3335,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) /* inform hardware that preparatory work is done */ msleep(HCLGE_RESET_SYNC_TIME); - hclge_write_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG, - HCLGE_NIC_CMQ_ENABLE); + hclge_reset_handshake(hdev, true); dev_info(&hdev->pdev->dev, "prepare wait ok\n"); return ret; @@ -3354,6 +3366,10 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) } hclge_clear_reset_cause(hdev); + + /* recover the handshake status when reset fail */ + hclge_reset_handshake(hdev, true); + dev_err(&hdev->pdev->dev, "Reset fail!\n"); return false; } @@ -3372,6 +3388,9 @@ static int hclge_reset_prepare_up(struct hclge_dev *hdev) break; } + /* clear up the handshake status after re-initialize done */ + hclge_reset_handshake(hdev, false); + return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 8f21eb3d9bd2..55d3c784f2d4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -97,7 +97,9 @@ static void hclgevf_cmd_config_regs(struct hclgevf_cmq_ring *ring) reg_val = (u32)((ring->desc_dma_addr >> 31) >> 1); hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, reg_val); - reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S); + reg_val = hclgevf_read_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG); + reg_val &= HCLGEVF_NIC_SW_RST_RDY; + reg_val |= (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S); hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, reg_val); hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 127a434a56f3..f830eef02e5c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -244,8 +244,11 @@ struct hclgevf_cfg_tx_queue_pointer_cmd { #define HCLGEVF_NIC_CRQ_DEPTH_REG 0x27020 #define HCLGEVF_NIC_CRQ_TAIL_REG 0x27024 #define HCLGEVF_NIC_CRQ_HEAD_REG 0x27028 -#define HCLGEVF_NIC_CMQ_EN_B 16 -#define HCLGEVF_NIC_CMQ_ENABLE BIT(HCLGEVF_NIC_CMQ_EN_B) + +/* this bit indicates that the driver is ready for hardware reset */ +#define HCLGEVF_NIC_SW_RST_RDY_B 16 +#define HCLGEVF_NIC_SW_RST_RDY BIT(HCLGEVF_NIC_SW_RST_RDY_B) + #define HCLGEVF_NIC_CMQ_DESC_NUM 1024 #define HCLGEVF_NIC_CMQ_DESC_NUM_S 3 #define HCLGEVF_NIC_CMDQ_INT_SRC_REG 0x27100 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index ae0e6a69d54b..340d89eea2a8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1426,6 +1426,20 @@ static int hclgevf_reset_wait(struct hclgevf_dev *hdev) return 0; } +static void hclgevf_reset_handshake(struct hclgevf_dev *hdev, bool enable) +{ + u32 reg_val; + + reg_val = hclgevf_read_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG); + if (enable) + reg_val |= HCLGEVF_NIC_SW_RST_RDY; + else + reg_val &= ~HCLGEVF_NIC_SW_RST_RDY; + + hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG, + reg_val); +} + static int hclgevf_reset_stack(struct hclgevf_dev *hdev) { int ret; @@ -1448,7 +1462,14 @@ static int hclgevf_reset_stack(struct hclgevf_dev *hdev) if (ret) return ret; - return hclgevf_notify_client(hdev, HNAE3_RESTORE_CLIENT); + ret = hclgevf_notify_client(hdev, HNAE3_RESTORE_CLIENT); + if (ret) + return ret; + + /* clear handshake status with IMP */ + hclgevf_reset_handshake(hdev, false); + + return 0; } static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev) @@ -1474,8 +1495,7 @@ static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev) set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state); /* inform hardware that preparatory work is done */ msleep(HCLGEVF_RESET_SYNC_TIME); - hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG, - HCLGEVF_NIC_CMQ_ENABLE); + hclgevf_reset_handshake(hdev, true); dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done, ret:%d\n", hdev->reset_type, ret); @@ -1484,6 +1504,8 @@ static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev) static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev) { + /* recover handshake status with IMP when reset fail */ + hclgevf_reset_handshake(hdev, true); hdev->rst_stats.rst_fail_cnt++; dev_err(&hdev->pdev->dev, "failed to reset VF(%d)\n", hdev->rst_stats.rst_fail_cnt); @@ -1494,9 +1516,6 @@ static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev) if (hclgevf_is_reset_pending(hdev)) { set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); hclgevf_reset_task_schedule(hdev); - } else { - hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG, - HCLGEVF_NIC_CMQ_ENABLE); } } -- GitLab From 72e2fb07997c5ca2c73114624fd64c41be013bdc Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 1 Aug 2019 11:55:44 +0800 Subject: [PATCH 1550/7155] net: hns3: clear reset interrupt status in hclge_irq_handle() Currently, the reset interrupt is cleared in the reset task, which is too late. Since, when the hardware finish the previous reset, it can begin to do a new global/IMP reset, if this new coming reset type is same as the previous one, the driver will clear them together, then driver can not get that there is another reset, but the hardware still wait for the driver to deal with the second one. So this patch clears PF's reset interrupt status in the hclge_irq_handle(), the hardware waits for handshaking from driver before doing reset, so the driver and hardware deal with reset one by one. BTW, when VF doing global/IMP reset, it reads PF's reset interrupt register to get that whether PF driver's re-initialization is done, since VF's re-initialization should be done after PF's. So we add a new command and a register bit to do that. When VF receive reset interrupt, it sets up this bit, and PF finishes re-initialization send command to clear this bit, then VF do re-initialization. Fixes: 4ed340ab8f49 ("net: hns3: Add reset process in hclge_main") Signed-off-by: Huazhong Tan Reviewed-by: Yunsheng Lin Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 8 +++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 34 +++++++++++++++++-- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 29 ++++++++++------ .../hisilicon/hns3/hns3vf/hclgevf_main.h | 3 ++ 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 63cf9a7d5720..dade20a37d40 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -86,6 +86,7 @@ enum hclge_opcode_type { HCLGE_OPC_QUERY_PF_RSRC = 0x0023, HCLGE_OPC_QUERY_VF_RSRC = 0x0024, HCLGE_OPC_GET_CFG_PARAM = 0x0025, + HCLGE_OPC_PF_RST_DONE = 0x0026, HCLGE_OPC_STATS_64_BIT = 0x0030, HCLGE_OPC_STATS_32_BIT = 0x0031, @@ -878,6 +879,13 @@ struct hclge_reset_cmd { u8 rsv[22]; }; +#define HCLGE_PF_RESET_DONE_BIT BIT(0) + +struct hclge_pf_rst_done_cmd { + u8 pf_rst_done; + u8 rsv[23]; +}; + #define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0) #define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2) #define HCLGE_CMD_SERDES_DONE_B BIT(0) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index abe4cee06d4a..c4841c3ea2e5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2876,10 +2876,15 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) break; } - /* clear the source of interrupt if it is not cause by reset */ + hclge_clear_event_cause(hdev, event_cause, clearval); + + /* Enable interrupt if it is not cause by reset. And when + * clearval equal to 0, it means interrupt status may be + * cleared by hardware before driver reads status register. + * For this case, vector0 interrupt also should be enabled. + */ if (!clearval || event_cause == HCLGE_VECTOR0_EVENT_MBX) { - hclge_clear_event_cause(hdev, event_cause, clearval); hclge_enable_vector(&hdev->misc_vector, true); } @@ -3253,7 +3258,13 @@ static void hclge_clear_reset_cause(struct hclge_dev *hdev) if (!clearval) return; - hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, clearval); + /* For revision 0x20, the reset interrupt source + * can only be cleared after hardware reset done + */ + if (hdev->pdev->revision == 0x20) + hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, + clearval); + hclge_enable_vector(&hdev->misc_vector, true); } @@ -3374,6 +3385,18 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) return false; } +static int hclge_set_rst_done(struct hclge_dev *hdev) +{ + struct hclge_pf_rst_done_cmd *req; + struct hclge_desc desc; + + req = (struct hclge_pf_rst_done_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PF_RST_DONE, false); + req->pf_rst_done |= HCLGE_PF_RESET_DONE_BIT; + + return hclge_cmd_send(&hdev->hw, &desc, 1); +} + static int hclge_reset_prepare_up(struct hclge_dev *hdev) { int ret = 0; @@ -3384,6 +3407,11 @@ static int hclge_reset_prepare_up(struct hclge_dev *hdev) case HNAE3_FLR_RESET: ret = hclge_set_all_vf_rst(hdev, false); break; + case HNAE3_GLOBAL_RESET: + /* fall through */ + case HNAE3_IMP_RESET: + ret = hclge_set_rst_done(hdev); + break; default: break; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 340d89eea2a8..ce82b2b0f8f5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1396,19 +1396,22 @@ static int hclgevf_reset_wait(struct hclgevf_dev *hdev) u32 val; int ret; - /* wait to check the hardware reset completion status */ - val = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING); - dev_info(&hdev->pdev->dev, "checking vf resetting status: %x\n", val); - if (hdev->reset_type == HNAE3_FLR_RESET) return hclgevf_flr_poll_timeout(hdev, HCLGEVF_RESET_WAIT_US, HCLGEVF_RESET_WAIT_CNT); - - ret = readl_poll_timeout(hdev->hw.io_base + HCLGEVF_RST_ING, val, - !(val & HCLGEVF_RST_ING_BITS), - HCLGEVF_RESET_WAIT_US, - HCLGEVF_RESET_WAIT_TIMEOUT_US); + else if (hdev->reset_type == HNAE3_VF_RESET) + ret = readl_poll_timeout(hdev->hw.io_base + + HCLGEVF_VF_RST_ING, val, + !(val & HCLGEVF_VF_RST_ING_BIT), + HCLGEVF_RESET_WAIT_US, + HCLGEVF_RESET_WAIT_TIMEOUT_US); + else + ret = readl_poll_timeout(hdev->hw.io_base + + HCLGEVF_RST_ING, val, + !(val & HCLGEVF_RST_ING_BITS), + HCLGEVF_RESET_WAIT_US, + HCLGEVF_RESET_WAIT_TIMEOUT_US); /* hardware completion status should be available by this time */ if (ret) { @@ -1886,7 +1889,7 @@ static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr) static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, u32 *clearval) { - u32 cmdq_src_reg, rst_ing_reg; + u32 val, cmdq_src_reg, rst_ing_reg; /* fetch the events from their corresponding regs */ cmdq_src_reg = hclgevf_read_dev(&hdev->hw, @@ -1902,6 +1905,12 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RST_INT_B); *clearval = cmdq_src_reg; hdev->rst_stats.vf_rst_cnt++; + /* set up VF hardware reset status, its PF will clear + * this status when PF has initialized done. + */ + val = hclgevf_read_dev(&hdev->hw, HCLGEVF_VF_RST_ING); + hclgevf_write_dev(&hdev->hw, HCLGEVF_VF_RST_ING, + val | HCLGEVF_VF_RST_ING_BIT); return HCLGEVF_VECTOR0_EVENT_RST; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 5a9e30998a8f..f0736b060884 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -103,6 +103,9 @@ (HCLGEVF_FUN_RST_ING_BIT | HCLGEVF_GLOBAL_RST_ING_BIT | \ HCLGEVF_CORE_RST_ING_BIT | HCLGEVF_IMP_RST_ING_BIT) +#define HCLGEVF_VF_RST_ING 0x07008 +#define HCLGEVF_VF_RST_ING_BIT BIT(16) + #define HCLGEVF_RSS_IND_TBL_SIZE 512 #define HCLGEVF_RSS_SET_BITMAP_MSK 0xffff #define HCLGEVF_RSS_KEY_SIZE 40 -- GitLab From 012fcb52f67cbba95c3e85010a4a9c40ea43866f Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 1 Aug 2019 11:55:45 +0800 Subject: [PATCH 1551/7155] net: hns3: activate reset timer when calling reset_event When calling hclge_reset_event() within HCLGE_RESET_INTERVAL, it returns directly now. If no one call it again, then the error which needs a reset to fix it can not be fixed. So this patch activates the reset timer for this case, and adds checking in the end of the reset procedure to make this error fixed earlier. Signed-off-by: Huazhong Tan Reviewed-by: Peng Li Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c4841c3ea2e5..b7399f5ba2c3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3517,7 +3517,15 @@ static void hclge_reset(struct hclge_dev *hdev) hdev->reset_fail_cnt = 0; hdev->rst_stats.reset_done_cnt++; ae_dev->reset_type = HNAE3_NONE_RESET; - del_timer(&hdev->reset_timer); + + /* if default_reset_request has a higher level reset request, + * it should be handled as soon as possible. since some errors + * need this kind of reset to fix. + */ + hdev->reset_level = hclge_get_reset_level(ae_dev, + &hdev->default_reset_request); + if (hdev->reset_level != HNAE3_NONE_RESET) + set_bit(hdev->reset_level, &hdev->reset_request); return; @@ -3552,9 +3560,10 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) handle = &hdev->vport[0].nic; if (time_before(jiffies, (hdev->last_reset_time + - HCLGE_RESET_INTERVAL))) + HCLGE_RESET_INTERVAL))) { + mod_timer(&hdev->reset_timer, jiffies + HCLGE_RESET_INTERVAL); return; - else if (hdev->default_reset_request) + } else if (hdev->default_reset_request) hdev->reset_level = hclge_get_reset_level(ae_dev, &hdev->default_reset_request); @@ -3584,6 +3593,12 @@ static void hclge_reset_timer(struct timer_list *t) { struct hclge_dev *hdev = from_timer(hdev, t, reset_timer); + /* if default_reset_request has no value, it means that this reset + * request has already be handled, so just return here + */ + if (!hdev->default_reset_request) + return; + dev_info(&hdev->pdev->dev, "triggering reset in reset timer\n"); hclge_reset_event(hdev->pdev, NULL); -- GitLab From 6f06e04b67baa1c9da61c8b15b1335a1dbb98bcb Mon Sep 17 00:00:00 2001 From: Gavi Teitz Date: Mon, 29 Jul 2019 21:12:52 +0000 Subject: [PATCH 1552/7155] net/mlx5: Refactor and optimize flow counter bulk query Towards introducing the ability to allocate bulks of flow counters, refactor the flow counter bulk query process, removing functions and structs whose names indicated being used for flow counter bulk allocation FW commands, despite them actually only being used to support bulk querying, and migrate their functionality to correctly named functions in their natural location, fs_counters.c. Additionally, optimize the bulk query process by: * Extracting the memory used for the query to mlx5_fc_stats so that it is only allocated once, and not for each bulk query. * Querying all the counters in one function call. Signed-off-by: Gavi Teitz Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/fs_cmd.c | 61 ++------- .../net/ethernet/mellanox/mlx5/core/fs_cmd.h | 13 +- .../ethernet/mellanox/mlx5/core/fs_counters.c | 125 ++++++++++-------- include/linux/mlx5/driver.h | 1 + 4 files changed, 81 insertions(+), 119 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 7ac1249eadc3..51f6972f4c70 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -615,67 +615,24 @@ int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, return 0; } -struct mlx5_cmd_fc_bulk { - u32 id; - int num; - int outlen; - u32 out[0]; -}; - -struct mlx5_cmd_fc_bulk * -mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u32 id, int num) +int mlx5_cmd_fc_get_bulk_query_out_len(int bulk_len) { - struct mlx5_cmd_fc_bulk *b; - int outlen = - MLX5_ST_SZ_BYTES(query_flow_counter_out) + - MLX5_ST_SZ_BYTES(traffic_counter) * num; - - b = kzalloc(sizeof(*b) + outlen, GFP_KERNEL); - if (!b) - return NULL; - - b->id = id; - b->num = num; - b->outlen = outlen; - - return b; + return MLX5_ST_SZ_BYTES(query_flow_counter_out) + + MLX5_ST_SZ_BYTES(traffic_counter) * bulk_len; } -void mlx5_cmd_fc_bulk_free(struct mlx5_cmd_fc_bulk *b) -{ - kfree(b); -} - -int -mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, struct mlx5_cmd_fc_bulk *b) +int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len, + u32 *out) { + int outlen = mlx5_cmd_fc_get_bulk_query_out_len(bulk_len); u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0}; MLX5_SET(query_flow_counter_in, in, opcode, MLX5_CMD_OP_QUERY_FLOW_COUNTER); MLX5_SET(query_flow_counter_in, in, op_mod, 0); - MLX5_SET(query_flow_counter_in, in, flow_counter_id, b->id); - MLX5_SET(query_flow_counter_in, in, num_of_counters, b->num); - return mlx5_cmd_exec(dev, in, sizeof(in), b->out, b->outlen); -} - -void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev, - struct mlx5_cmd_fc_bulk *b, u32 id, - u64 *packets, u64 *bytes) -{ - int index = id - b->id; - void *stats; - - if (index < 0 || index >= b->num) { - mlx5_core_warn(dev, "Flow counter id (0x%x) out of range (0x%x..0x%x). Counter ignored.\n", - id, b->id, b->id + b->num - 1); - return; - } - - stats = MLX5_ADDR_OF(query_flow_counter_out, b->out, - flow_statistics[index]); - *packets = MLX5_GET64(traffic_counter, stats, packets); - *bytes = MLX5_GET64(traffic_counter, stats, octets); + MLX5_SET(query_flow_counter_in, in, flow_counter_id, base_id); + MLX5_SET(query_flow_counter_in, in, num_of_counters, bulk_len); + return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); } int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index e340f9af2f5a..db49eabba98d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -82,16 +82,9 @@ int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id); int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, u64 *packets, u64 *bytes); -struct mlx5_cmd_fc_bulk; - -struct mlx5_cmd_fc_bulk * -mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u32 id, int num); -void mlx5_cmd_fc_bulk_free(struct mlx5_cmd_fc_bulk *b); -int -mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, struct mlx5_cmd_fc_bulk *b); -void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev, - struct mlx5_cmd_fc_bulk *b, u32 id, - u64 *packets, u64 *bytes); +int mlx5_cmd_fc_get_bulk_query_out_len(int bulk_len); +int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len, + u32 *out); const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type type); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index b3762123a69c..067a4b56498b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -75,7 +75,7 @@ struct mlx5_fc { * access to counter list: * - create (user context) * - mlx5_fc_create() only adds to an addlist to be used by - * mlx5_fc_stats_query_work(). addlist is a lockless single linked list + * mlx5_fc_stats_work(). addlist is a lockless single linked list * that doesn't require any additional synchronization when adding single * node. * - spawn thread to do the actual destroy @@ -136,72 +136,69 @@ static void mlx5_fc_stats_remove(struct mlx5_core_dev *dev, spin_unlock(&fc_stats->counters_idr_lock); } -/* The function returns the last counter that was queried so the caller - * function can continue calling it till all counters are queried. - */ -static struct mlx5_fc *mlx5_fc_stats_query(struct mlx5_core_dev *dev, - struct mlx5_fc *first, - u32 last_id) +static int get_max_bulk_query_len(struct mlx5_core_dev *dev) { - struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; - struct mlx5_fc *counter = NULL; - struct mlx5_cmd_fc_bulk *b; - bool more = false; - u32 afirst_id; - int num; - int err; + return min_t(int, MLX5_SW_MAX_COUNTERS_BULK, + (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk))); +} - int max_bulk = min_t(int, MLX5_SW_MAX_COUNTERS_BULK, - (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk))); +static void update_counter_cache(int index, u32 *bulk_raw_data, + struct mlx5_fc_cache *cache) +{ + void *stats = MLX5_ADDR_OF(query_flow_counter_out, bulk_raw_data, + flow_statistics[index]); + u64 packets = MLX5_GET64(traffic_counter, stats, packets); + u64 bytes = MLX5_GET64(traffic_counter, stats, octets); - /* first id must be aligned to 4 when using bulk query */ - afirst_id = first->id & ~0x3; + if (cache->packets == packets) + return; - /* number of counters to query inc. the last counter */ - num = ALIGN(last_id - afirst_id + 1, 4); - if (num > max_bulk) { - num = max_bulk; - last_id = afirst_id + num - 1; - } + cache->packets = packets; + cache->bytes = bytes; + cache->lastuse = jiffies; +} - b = mlx5_cmd_fc_bulk_alloc(dev, afirst_id, num); - if (!b) { - mlx5_core_err(dev, "Error allocating resources for bulk query\n"); - return NULL; - } +static void mlx5_fc_stats_query_counter_range(struct mlx5_core_dev *dev, + struct mlx5_fc *first, + u32 last_id) +{ + struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; + bool query_more_counters = (first->id <= last_id); + int max_bulk_len = get_max_bulk_query_len(dev); + u32 *data = fc_stats->bulk_query_out; + struct mlx5_fc *counter = first; + u32 bulk_base_id; + int bulk_len; + int err; - err = mlx5_cmd_fc_bulk_query(dev, b); - if (err) { - mlx5_core_err(dev, "Error doing bulk query: %d\n", err); - goto out; - } + while (query_more_counters) { + /* first id must be aligned to 4 when using bulk query */ + bulk_base_id = counter->id & ~0x3; - counter = first; - list_for_each_entry_from(counter, &fc_stats->counters, list) { - struct mlx5_fc_cache *c = &counter->cache; - u64 packets; - u64 bytes; + /* number of counters to query inc. the last counter */ + bulk_len = min_t(int, max_bulk_len, + ALIGN(last_id - bulk_base_id + 1, 4)); - if (counter->id > last_id) { - more = true; - break; + err = mlx5_cmd_fc_bulk_query(dev, bulk_base_id, bulk_len, + data); + if (err) { + mlx5_core_err(dev, "Error doing bulk query: %d\n", err); + return; } + query_more_counters = false; - mlx5_cmd_fc_bulk_get(dev, b, - counter->id, &packets, &bytes); + list_for_each_entry_from(counter, &fc_stats->counters, list) { + int counter_index = counter->id - bulk_base_id; + struct mlx5_fc_cache *cache = &counter->cache; - if (c->packets == packets) - continue; + if (counter->id >= bulk_base_id + bulk_len) { + query_more_counters = true; + break; + } - c->packets = packets; - c->bytes = bytes; - c->lastuse = jiffies; + update_counter_cache(counter_index, data, cache); + } } - -out: - mlx5_cmd_fc_bulk_free(b); - - return more ? counter : NULL; } static void mlx5_free_fc(struct mlx5_core_dev *dev, @@ -244,8 +241,8 @@ static void mlx5_fc_stats_work(struct work_struct *work) counter = list_first_entry(&fc_stats->counters, struct mlx5_fc, list); - while (counter) - counter = mlx5_fc_stats_query(dev, counter, last->id); + if (counter) + mlx5_fc_stats_query_counter_range(dev, counter, last->id); fc_stats->next_query = now + fc_stats->sampling_interval; } @@ -324,6 +321,8 @@ EXPORT_SYMBOL(mlx5_fc_destroy); int mlx5_init_fc_stats(struct mlx5_core_dev *dev) { struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; + int max_bulk_len; + int max_out_len; spin_lock_init(&fc_stats->counters_idr_lock); idr_init(&fc_stats->counters_idr); @@ -331,14 +330,24 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev) init_llist_head(&fc_stats->addlist); init_llist_head(&fc_stats->dellist); + max_bulk_len = get_max_bulk_query_len(dev); + max_out_len = mlx5_cmd_fc_get_bulk_query_out_len(max_bulk_len); + fc_stats->bulk_query_out = kzalloc(max_out_len, GFP_KERNEL); + if (!fc_stats->bulk_query_out) + return -ENOMEM; + fc_stats->wq = create_singlethread_workqueue("mlx5_fc"); if (!fc_stats->wq) - return -ENOMEM; + goto err_wq_create; fc_stats->sampling_interval = MLX5_FC_STATS_PERIOD; INIT_DELAYED_WORK(&fc_stats->work, mlx5_fc_stats_work); return 0; + +err_wq_create: + kfree(fc_stats->bulk_query_out); + return -ENOMEM; } void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev) @@ -352,6 +361,8 @@ void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev) destroy_workqueue(dev->priv.fc_stats.wq); dev->priv.fc_stats.wq = NULL; + kfree(fc_stats->bulk_query_out); + idr_destroy(&fc_stats->counters_idr); tmplist = llist_del_all(&fc_stats->addlist); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 0e6da1840c7d..267b2bc0ca4a 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -488,6 +488,7 @@ struct mlx5_fc_stats { struct delayed_work work; unsigned long next_query; unsigned long sampling_interval; /* jiffies */ + u32 *bulk_query_out; }; struct mlx5_events; -- GitLab From 8536a6bf2ea1f3bf4e3159b590fbecce4d854796 Mon Sep 17 00:00:00 2001 From: Gavi Teitz Date: Mon, 29 Jul 2019 21:12:54 +0000 Subject: [PATCH 1553/7155] net/mlx5: Add flow counter bulk allocation hardware bits and command Add a handle to invoke the new FW capability of allocating a bulk of flow counters. Signed-off-by: Gavi Teitz Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/fs_cmd.c | 10 ++++++++- .../net/ethernet/mellanox/mlx5/core/fs_cmd.h | 3 +++ include/linux/mlx5/mlx5_ifc.h | 21 +++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 51f6972f4c70..b84a225bbe86 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -566,7 +566,9 @@ static int mlx5_cmd_delete_fte(struct mlx5_flow_root_namespace *ns, return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } -int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) +int mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, + enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask, + u32 *id) { u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {0}; u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0}; @@ -574,6 +576,7 @@ int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) MLX5_SET(alloc_flow_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_FLOW_COUNTER); + MLX5_SET(alloc_flow_counter_in, in, flow_counter_bulk, alloc_bitmask); err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); if (!err) @@ -581,6 +584,11 @@ int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) return err; } +int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) +{ + return mlx5_cmd_fc_bulk_alloc(dev, 0, id); +} + int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id) { u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {0}; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index db49eabba98d..bc4606306009 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -78,6 +78,9 @@ struct mlx5_flow_cmds { }; int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id); +int mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, + enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask, + u32 *id); int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id); int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, u64 *packets, u64 *bytes); diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index b3d5752657d9..196987f14a3f 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -1040,6 +1040,21 @@ enum { MLX5_UCTX_CAP_INTERNAL_DEV_RES = 1UL << 1, }; +#define MLX5_FC_BULK_SIZE_FACTOR 128 + +enum mlx5_fc_bulk_alloc_bitmask { + MLX5_FC_BULK_128 = (1 << 0), + MLX5_FC_BULK_256 = (1 << 1), + MLX5_FC_BULK_512 = (1 << 2), + MLX5_FC_BULK_1024 = (1 << 3), + MLX5_FC_BULK_2048 = (1 << 4), + MLX5_FC_BULK_4096 = (1 << 5), + MLX5_FC_BULK_8192 = (1 << 6), + MLX5_FC_BULK_16384 = (1 << 7), +}; + +#define MLX5_FC_BULK_NUM_FCS(fc_enum) (MLX5_FC_BULK_SIZE_FACTOR * (fc_enum)) + struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_0[0x30]; u8 vhca_id[0x10]; @@ -1244,7 +1259,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_2e0[0x7]; u8 max_qp_mcg[0x19]; - u8 reserved_at_300[0x18]; + u8 reserved_at_300[0x10]; + u8 flow_counter_bulk_alloc[0x8]; u8 log_max_mcg[0x8]; u8 reserved_at_320[0x3]; @@ -7815,7 +7831,8 @@ struct mlx5_ifc_alloc_flow_counter_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 reserved_at_40[0x38]; + u8 flow_counter_bulk[0x8]; }; struct mlx5_ifc_add_vxlan_udp_dport_out_bits { -- GitLab From 7761f9eef3f09f2f4c579313e0c536770b5ecff4 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 29 Jul 2019 21:12:56 +0000 Subject: [PATCH 1554/7155] net/mlx5: Fix offset of tisc bits reserved field First reserved field is off by one instead of reserved_at_1 it should be reserved_at_2, fix that. Fixes: a12ff35e0fb7 ("net/mlx5: Introduce TLS TX offload hardware bits and structures") Signed-off-by: Saeed Mahameed Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- include/linux/mlx5/mlx5_ifc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 196987f14a3f..9265c84ad353 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -2782,7 +2782,7 @@ struct mlx5_ifc_traffic_counter_bits { struct mlx5_ifc_tisc_bits { u8 strict_lag_tx_port_affinity[0x1]; u8 tls_en[0x1]; - u8 reserved_at_1[0x2]; + u8 reserved_at_2[0x2]; u8 lag_tx_port_affinity[0x04]; u8 reserved_at_8[0x4]; -- GitLab From 0000a5f2507deef8668d23d6406e9d19ba371def Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:12:58 +0000 Subject: [PATCH 1555/7155] net/mlx5: Make load_one() and unload_one() symmetric Currently mlx5_load_one() perform device registration using mlx5_register_device(). But mlx5_unload_one() doesn't unregister. Make them symmetric by doing device unregistration in mlx5_unload_one(). Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index b15b27a497fc..fa0e991f1983 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1217,8 +1217,10 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup) { int err = 0; - if (cleanup) + if (cleanup) { + mlx5_unregister_device(dev); mlx5_drain_health_wq(dev); + } mutex_lock(&dev->intf_state_mutex); if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { @@ -1369,7 +1371,6 @@ static void remove_one(struct pci_dev *pdev) mlx5_crdump_disable(dev); mlx5_devlink_unregister(devlink); - mlx5_unregister_device(dev); if (mlx5_unload_one(dev, true)) { mlx5_core_err(dev, "mlx5_unload_one failed\n"); -- GitLab From 6cedde4513990af7191afa43528533f80e92c989 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 29 Jul 2019 21:13:00 +0000 Subject: [PATCH 1556/7155] net/mlx5: E-Switch, Verify support QoS element type Check if firmware supports the requested element type before attempting to create the element type. In addition, explicitly specify the request element type and tsar type. Signed-off-by: Eli Cohen Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 31 +++++++++++++++++++ include/linux/mlx5/mlx5_ifc.h | 7 +++++ 2 files changed, 38 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 1f3891fde2eb..2927fa1da92f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1393,19 +1393,50 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, return err; } +static bool element_type_supported(struct mlx5_eswitch *esw, int type) +{ + struct mlx5_core_dev *dev = esw->dev = esw->dev; + + switch (type) { + case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR: + return MLX5_CAP_QOS(dev, esw_element_type) & + ELEMENT_TYPE_CAP_MASK_TASR; + case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT: + return MLX5_CAP_QOS(dev, esw_element_type) & + ELEMENT_TYPE_CAP_MASK_VPORT; + case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC: + return MLX5_CAP_QOS(dev, esw_element_type) & + ELEMENT_TYPE_CAP_MASK_VPORT_TC; + case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC: + return MLX5_CAP_QOS(dev, esw_element_type) & + ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC; + } + return false; +} + /* Vport QoS management */ static int esw_create_tsar(struct mlx5_eswitch *esw) { u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; struct mlx5_core_dev *dev = esw->dev; + __be32 *attr; int err; if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) return 0; + if (!element_type_supported(esw, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR)) + return 0; + if (esw->qos.enabled) return -EEXIST; + MLX5_SET(scheduling_context, tsar_ctx, element_type, + SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); + + attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); + *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16); + err = mlx5_create_scheduling_element_cmd(dev, SCHEDULING_HIERARCHY_E_SWITCH, tsar_ctx, diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 9265c84ad353..30d15e80bcc7 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -2957,6 +2957,13 @@ enum { SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC = 0x3, }; +enum { + ELEMENT_TYPE_CAP_MASK_TASR = 1 << 0, + ELEMENT_TYPE_CAP_MASK_VPORT = 1 << 1, + ELEMENT_TYPE_CAP_MASK_VPORT_TC = 1 << 2, + ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC = 1 << 3, +}; + struct mlx5_ifc_scheduling_context_bits { u8 element_type[0x8]; u8 reserved_at_8[0x18]; -- GitLab From 332bd3a5b931eb67deb370db62d59f9cc7f76dac Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:13:02 +0000 Subject: [PATCH 1557/7155] net/mlx5: E-switch, Combine metadata enable/disable functionality Except bit toggling code, rest of the code is same to enable/disable metadata passing functionality. Hence, combine them to single function and control using enable flag. Also instead of checking metadata supported at multiple places, fold into the helper function. Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/eswitch_offloads.c | 48 +++++-------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 089ae4d48a82..4be19890f725 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -587,38 +587,15 @@ void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule) mlx5_del_flow_rules(rule); } -static int mlx5_eswitch_enable_passing_vport_metadata(struct mlx5_eswitch *esw) +static int esw_set_passing_vport_metadata(struct mlx5_eswitch *esw, bool enable) { u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {}; u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {}; u8 fdb_to_vport_reg_c_id; int err; - err = mlx5_eswitch_query_esw_vport_context(esw, esw->manager_vport, - out, sizeof(out)); - if (err) - return err; - - fdb_to_vport_reg_c_id = MLX5_GET(query_esw_vport_context_out, out, - esw_vport_context.fdb_to_vport_reg_c_id); - - fdb_to_vport_reg_c_id |= MLX5_FDB_TO_VPORT_REG_C_0; - MLX5_SET(modify_esw_vport_context_in, in, - esw_vport_context.fdb_to_vport_reg_c_id, fdb_to_vport_reg_c_id); - - MLX5_SET(modify_esw_vport_context_in, in, - field_select.fdb_to_vport_reg_c_id, 1); - - return mlx5_eswitch_modify_esw_vport_context(esw, esw->manager_vport, - in, sizeof(in)); -} - -static int mlx5_eswitch_disable_passing_vport_metadata(struct mlx5_eswitch *esw) -{ - u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {}; - u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {}; - u8 fdb_to_vport_reg_c_id; - int err; + if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) + return 0; err = mlx5_eswitch_query_esw_vport_context(esw, esw->manager_vport, out, sizeof(out)); @@ -628,7 +605,10 @@ static int mlx5_eswitch_disable_passing_vport_metadata(struct mlx5_eswitch *esw) fdb_to_vport_reg_c_id = MLX5_GET(query_esw_vport_context_out, out, esw_vport_context.fdb_to_vport_reg_c_id); - fdb_to_vport_reg_c_id &= ~MLX5_FDB_TO_VPORT_REG_C_0; + if (enable) + fdb_to_vport_reg_c_id |= MLX5_FDB_TO_VPORT_REG_C_0; + else + fdb_to_vport_reg_c_id &= ~MLX5_FDB_TO_VPORT_REG_C_0; MLX5_SET(modify_esw_vport_context_in, in, esw_vport_context.fdb_to_vport_reg_c_id, fdb_to_vport_reg_c_id); @@ -2138,11 +2118,9 @@ int esw_offloads_init(struct mlx5_eswitch *esw) if (err) return err; - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { - err = mlx5_eswitch_enable_passing_vport_metadata(esw); - if (err) - goto err_vport_metadata; - } + err = esw_set_passing_vport_metadata(esw, true); + if (err) + goto err_vport_metadata; err = esw_offloads_load_all_reps(esw); if (err) @@ -2156,8 +2134,7 @@ int esw_offloads_init(struct mlx5_eswitch *esw) return 0; err_reps: - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) - mlx5_eswitch_disable_passing_vport_metadata(esw); + esw_set_passing_vport_metadata(esw, false); err_vport_metadata: esw_offloads_steering_cleanup(esw); return err; @@ -2187,8 +2164,7 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw) mlx5_rdma_disable_roce(esw->dev); esw_offloads_devcom_cleanup(esw); esw_offloads_unload_all_reps(esw); - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) - mlx5_eswitch_disable_passing_vport_metadata(esw); + esw_set_passing_vport_metadata(esw, false); esw_offloads_steering_cleanup(esw); esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; } -- GitLab From 610090ebce92ab6a3e1e623344be5a9dd72a8b6d Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:13:04 +0000 Subject: [PATCH 1558/7155] net/mlx5: E-switch, Initialize TSAR Qos hardware block before its user vports First enable TSAR Qos hardware block in device before enabling its user vports. This refactor is needed so that vports can be enabled before their representor netdevice can be created. While at it, esw_create_tsar() returns error code which was used only to print error. However esw_create_tsar() already prints warning if it hits an error. Hence, remove the redundant warning. Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 2927fa1da92f..820970911f8b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1415,7 +1415,7 @@ static bool element_type_supported(struct mlx5_eswitch *esw, int type) } /* Vport QoS management */ -static int esw_create_tsar(struct mlx5_eswitch *esw) +static void esw_create_tsar(struct mlx5_eswitch *esw) { u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; struct mlx5_core_dev *dev = esw->dev; @@ -1423,13 +1423,13 @@ static int esw_create_tsar(struct mlx5_eswitch *esw) int err; if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) - return 0; + return; if (!element_type_supported(esw, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR)) - return 0; + return; if (esw->qos.enabled) - return -EEXIST; + return; MLX5_SET(scheduling_context, tsar_ctx, element_type, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); @@ -1443,11 +1443,10 @@ static int esw_create_tsar(struct mlx5_eswitch *esw) &esw->qos.root_tsar_id); if (err) { esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err); - return err; + return; } esw->qos.enabled = true; - return 0; } static void esw_destroy_tsar(struct mlx5_eswitch *esw) @@ -1819,6 +1818,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support)) esw_warn(esw->dev, "engress ACL is not supported by FW\n"); + esw_create_tsar(esw); + esw->mode = mode; mlx5_lag_update(esw->dev); @@ -1836,10 +1837,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) if (err) goto abort; - err = esw_create_tsar(esw); - if (err) - esw_warn(esw->dev, "Failed to create eswitch TSAR"); - enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? SRIOV_VPORT_EVENTS : UC_ADDR_CHANGE; @@ -1899,13 +1896,13 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw) if (mc_promisc && mc_promisc->uplink_rule) mlx5_del_flow_rules(mc_promisc->uplink_rule); - esw_destroy_tsar(esw); - if (esw->mode == MLX5_ESWITCH_LEGACY) esw_destroy_legacy_table(esw); else if (esw->mode == MLX5_ESWITCH_OFFLOADS) esw_offloads_cleanup(esw); + esw_destroy_tsar(esw); + old_mode = esw->mode; esw->mode = MLX5_ESWITCH_NONE; -- GitLab From 5019833d661f5edb6bd63abd3da064d2517966b4 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:13:06 +0000 Subject: [PATCH 1559/7155] net/mlx5: E-switch, Introduce helper function to enable/disable vports vports needs to be enabled in switchdev and legacy mode. In switchdev mode, vports should be enabled after initializing the FDB tables and before creating their represntors so that representor works on an initialized vport object. Prepare a helper function which can be called when enabling either of the eswitch modes. Similarly, have disable vports helper function. Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 96 +++++++++++-------- .../net/ethernet/mellanox/mlx5/core/eswitch.h | 19 +++- 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 820970911f8b..6d82aefae6e1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -58,20 +58,9 @@ struct vport_addr { bool mc_promisc; }; -enum { - UC_ADDR_CHANGE = BIT(0), - MC_ADDR_CHANGE = BIT(1), - PROMISC_CHANGE = BIT(3), -}; - static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw); static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw); -/* Vport context events */ -#define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \ - MC_ADDR_CHANGE | \ - PROMISC_CHANGE) - struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) { @@ -108,13 +97,13 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1); - if (events_mask & UC_ADDR_CHANGE) + if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE) MLX5_SET(nic_vport_context, nic_vport_ctx, event_on_uc_address_change, 1); - if (events_mask & MC_ADDR_CHANGE) + if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE) MLX5_SET(nic_vport_context, nic_vport_ctx, event_on_mc_address_change, 1); - if (events_mask & PROMISC_CHANGE) + if (events_mask & MLX5_VPORT_PROMISC_CHANGE) MLX5_SET(nic_vport_context, nic_vport_ctx, event_on_promisc_change, 1); @@ -901,21 +890,21 @@ static void esw_vport_change_handle_locked(struct mlx5_vport *vport) esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", vport->vport, mac); - if (vport->enabled_events & UC_ADDR_CHANGE) { + if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) { esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); } - if (vport->enabled_events & MC_ADDR_CHANGE) + if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE) esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); - if (vport->enabled_events & PROMISC_CHANGE) { + if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) { esw_update_vport_rx_mode(esw, vport); if (!IS_ERR_OR_NULL(vport->allmulti_rule)) esw_update_vport_mc_promisc(esw, vport); } - if (vport->enabled_events & (PROMISC_CHANGE | MC_ADDR_CHANGE)) + if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE)) esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport); @@ -1649,7 +1638,7 @@ static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport) } static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, - int enable_events) + enum mlx5_eswitch_vport_event enabled_events) { u16 vport_num = vport->vport; @@ -1671,7 +1660,7 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num); /* Sync with current vport context */ - vport->enabled_events = enable_events; + vport->enabled_events = enabled_events; vport->enabled = true; /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well @@ -1800,11 +1789,51 @@ static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw) /* Public E-Switch API */ #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev)) -int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) +/* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs + * whichever are present on the eswitch. + */ +void +mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, + enum mlx5_eswitch_vport_event enabled_events) +{ + struct mlx5_vport *vport; + int i; + + /* Enable PF vport */ + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); + esw_enable_vport(esw, vport, enabled_events); + + /* Enable ECPF vports */ + if (mlx5_ecpf_vport_exists(esw->dev)) { + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); + esw_enable_vport(esw, vport, enabled_events); + } + + /* Enable VF vports */ + mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) + esw_enable_vport(esw, vport, enabled_events); +} + +/* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs + * whichever are previously enabled on the eswitch. + */ +void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) { struct mlx5_vport *vport; + int i; + + mlx5_esw_for_all_vports_reverse(esw, i, vport) + esw_disable_vport(esw, vport); +} + +#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \ + MLX5_VPORT_MC_ADDR_CHANGE | \ + MLX5_VPORT_PROMISC_CHANGE) + +int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) +{ + int enabled_events; int err; - int i, enabled_events; if (!ESW_ALLOWED(esw) || !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { @@ -1837,22 +1866,10 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) if (err) goto abort; - enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? SRIOV_VPORT_EVENTS : - UC_ADDR_CHANGE; + enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? MLX5_LEGACY_SRIOV_VPORT_EVENTS : + MLX5_VPORT_UC_ADDR_CHANGE; - /* Enable PF vport */ - vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); - esw_enable_vport(esw, vport, enabled_events); - - /* Enable ECPF vports */ - if (mlx5_ecpf_vport_exists(esw->dev)) { - vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); - esw_enable_vport(esw, vport, enabled_events); - } - - /* Enable VF vports */ - mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) - esw_enable_vport(esw, vport, enabled_events); + mlx5_eswitch_enable_pf_vf_vports(esw, enabled_events); mlx5_eswitch_event_handlers_register(esw); @@ -1876,9 +1893,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) void mlx5_eswitch_disable(struct mlx5_eswitch *esw) { struct esw_mc_addr *mc_promisc; - struct mlx5_vport *vport; int old_mode; - int i; if (!ESW_ALLOWED(esw) || esw->mode == MLX5_ESWITCH_NONE) return; @@ -1890,8 +1905,7 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw) mc_promisc = &esw->mc_promisc; mlx5_eswitch_event_handlers_unregister(esw); - mlx5_esw_for_all_vports(esw, i, vport) - esw_disable_vport(esw, vport); + mlx5_eswitch_disable_pf_vf_vports(esw); if (mc_promisc && mc_promisc->uplink_rule) mlx5_del_flow_rules(mc_promisc->uplink_rule); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index a38e8a3c7c9a..3103a34c619c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -101,6 +101,13 @@ struct mlx5_vport_info { bool trusted; }; +/* Vport context events */ +enum mlx5_eswitch_vport_event { + MLX5_VPORT_UC_ADDR_CHANGE = BIT(0), + MLX5_VPORT_MC_ADDR_CHANGE = BIT(1), + MLX5_VPORT_PROMISC_CHANGE = BIT(3), +}; + struct mlx5_vport { struct mlx5_core_dev *dev; int vport; @@ -122,7 +129,7 @@ struct mlx5_vport { } qos; bool enabled; - u16 enabled_events; + enum mlx5_eswitch_vport_event enabled_events; }; enum offloads_fdb_flags { @@ -513,6 +520,11 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw); (vport) = &(esw)->vports[i], \ (i) < (esw)->total_vports; (i)++) +#define mlx5_esw_for_all_vports_reverse(esw, i, vport) \ + for ((i) = (esw)->total_vports - 1; \ + (vport) = &(esw)->vports[i], \ + (i) >= MLX5_VPORT_PF; (i)--) + #define mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs) \ for ((i) = MLX5_VPORT_FIRST_VF; \ (vport) = &(esw)->vports[(i)], \ @@ -574,6 +586,11 @@ bool mlx5_eswitch_is_vf_vport(const struct mlx5_eswitch *esw, u16 vport_num); void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, const int num_vfs); int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data); +void +mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, + enum mlx5_eswitch_vport_event enabled_events); +void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw); + #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } -- GitLab From 9ddb830a14dbd88308354d27cd17009fc97d3a6f Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 29 Jul 2019 21:13:08 +0000 Subject: [PATCH 1560/7155] net/mlx5: E-Switch, remove redundant error handling We don't need to handle error flow of esw_create_legacy_table() in the same branch, it is already being handled directly after the if statement, for both legacy and switchdev modes in one place. Signed-off-by: Saeed Mahameed Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 6d82aefae6e1..17fb982b3489 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1855,8 +1855,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) if (mode == MLX5_ESWITCH_LEGACY) { err = esw_create_legacy_table(esw); - if (err) - goto abort; } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); -- GitLab From 131ce7014043087fbeddbcb3b8dac8891cd0e0fe Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:13:10 +0000 Subject: [PATCH 1561/7155] net/mlx5: E-Switch, Remove redundant mc_promisc NULL check mc_promisc pointer points to an instance of struct esw_mc_addr allocated as part of the esw structure. Hence it cannot be NULL. Removed such redundant check and assign where it is actually used. While at it, add comment around legacy mode fields and move mc_promisc close to other legacy mode structures to improve code redability. Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 17fb982b3489..90d150be237b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1900,12 +1900,12 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw) esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", esw->esw_funcs.num_vfs, esw->enabled_vports); - mc_promisc = &esw->mc_promisc; mlx5_eswitch_event_handlers_unregister(esw); mlx5_eswitch_disable_pf_vf_vports(esw); - if (mc_promisc && mc_promisc->uplink_rule) + mc_promisc = &esw->mc_promisc; + if (mc_promisc->uplink_rule) mlx5_del_flow_rules(mc_promisc->uplink_rule); if (esw->mode == MLX5_ESWITCH_LEGACY) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 3103a34c619c..51b6d29466f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -214,8 +214,11 @@ enum { struct mlx5_eswitch { struct mlx5_core_dev *dev; struct mlx5_nb nb; + /* legacy data structures */ struct mlx5_eswitch_fdb fdb_table; struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE]; + struct esw_mc_addr mc_promisc; + /* end of legacy */ struct workqueue_struct *work_queue; struct mlx5_vport *vports; u32 flags; @@ -225,7 +228,6 @@ struct mlx5_eswitch { * and async SRIOV admin state changes */ struct mutex state_lock; - struct esw_mc_addr mc_promisc; struct { bool enabled; -- GitLab From 5896b97296a7928035590ff3f477629774dce250 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 29 Jul 2019 21:13:12 +0000 Subject: [PATCH 1562/7155] net/mlx5: E-switch, Tide up eswitch config sequence Currently for PF and ECPF vports, representors are created before their eswitch hardware ports are initialized in below flow. mlx5_eswitch_enable() esw_offloads_init() esw_offloads_load_all_reps() [..] esw_enable_vport() However for VFs, vports are initialized before creating their respective netdev represnetors in event handling context. Similarly while disabling eswitch, first hardware vports are disabled, followed by destroying their representors. Here while underlying vports gets destroyed but its respective user facing netdevice can still exist on which user can continue to perform more offload operations. Instead, its more accurate to do enable_eswitch switchdev mode: 1. perform FDB tables initialization 2. initialize hw vport 3. create and publish representor for this vport disable_eswitch switchdev mode: 1. destroy user facing representor for the vport 2. disable hw vport 3. perform FDB tables cleanup Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 54 +++++++++++-------- .../net/ethernet/mellanox/mlx5/core/eswitch.h | 4 +- .../mellanox/mlx5/core/eswitch_offloads.c | 8 ++- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 90d150be237b..d4465dd18c11 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -452,6 +452,22 @@ static int esw_create_legacy_table(struct mlx5_eswitch *esw) return err; } +#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \ + MLX5_VPORT_MC_ADDR_CHANGE | \ + MLX5_VPORT_PROMISC_CHANGE) + +static int esw_legacy_enable(struct mlx5_eswitch *esw) +{ + int ret; + + ret = esw_create_legacy_table(esw); + if (ret) + return ret; + + mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS); + return 0; +} + static void esw_destroy_legacy_table(struct mlx5_eswitch *esw) { esw_cleanup_vepa_rules(esw); @@ -459,6 +475,19 @@ static void esw_destroy_legacy_table(struct mlx5_eswitch *esw) esw_destroy_legacy_vepa_table(esw); } +static void esw_legacy_disable(struct mlx5_eswitch *esw) +{ + struct esw_mc_addr *mc_promisc; + + mlx5_eswitch_disable_pf_vf_vports(esw); + + mc_promisc = &esw->mc_promisc; + if (mc_promisc->uplink_rule) + mlx5_del_flow_rules(mc_promisc->uplink_rule); + + esw_destroy_legacy_table(esw); +} + /* E-Switch vport UC/MC lists management */ typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, struct vport_addr *vaddr); @@ -1826,13 +1855,8 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) esw_disable_vport(esw, vport); } -#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \ - MLX5_VPORT_MC_ADDR_CHANGE | \ - MLX5_VPORT_PROMISC_CHANGE) - int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) { - int enabled_events; int err; if (!ESW_ALLOWED(esw) || @@ -1854,21 +1878,16 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) mlx5_lag_update(esw->dev); if (mode == MLX5_ESWITCH_LEGACY) { - err = esw_create_legacy_table(esw); + err = esw_legacy_enable(esw); } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); - err = esw_offloads_init(esw); + err = esw_offloads_enable(esw); } if (err) goto abort; - enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? MLX5_LEGACY_SRIOV_VPORT_EVENTS : - MLX5_VPORT_UC_ADDR_CHANGE; - - mlx5_eswitch_enable_pf_vf_vports(esw, enabled_events); - mlx5_eswitch_event_handlers_register(esw); esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n", @@ -1890,7 +1909,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) void mlx5_eswitch_disable(struct mlx5_eswitch *esw) { - struct esw_mc_addr *mc_promisc; int old_mode; if (!ESW_ALLOWED(esw) || esw->mode == MLX5_ESWITCH_NONE) @@ -1902,16 +1920,10 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw) mlx5_eswitch_event_handlers_unregister(esw); - mlx5_eswitch_disable_pf_vf_vports(esw); - - mc_promisc = &esw->mc_promisc; - if (mc_promisc->uplink_rule) - mlx5_del_flow_rules(mc_promisc->uplink_rule); - if (esw->mode == MLX5_ESWITCH_LEGACY) - esw_destroy_legacy_table(esw); + esw_legacy_disable(esw); else if (esw->mode == MLX5_ESWITCH_OFFLOADS) - esw_offloads_cleanup(esw); + esw_offloads_disable(esw); esw_destroy_tsar(esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 51b6d29466f1..d447e1e44d59 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -242,8 +242,8 @@ struct mlx5_eswitch { struct mlx5_esw_functions esw_funcs; }; -void esw_offloads_cleanup(struct mlx5_eswitch *esw); -int esw_offloads_init(struct mlx5_eswitch *esw); +void esw_offloads_disable(struct mlx5_eswitch *esw); +int esw_offloads_enable(struct mlx5_eswitch *esw); void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw); int esw_offloads_init_reps(struct mlx5_eswitch *esw); void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 4be19890f725..db01b8ee9385 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2104,7 +2104,7 @@ int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type return NOTIFY_OK; } -int esw_offloads_init(struct mlx5_eswitch *esw) +int esw_offloads_enable(struct mlx5_eswitch *esw) { int err; @@ -2122,6 +2122,8 @@ int esw_offloads_init(struct mlx5_eswitch *esw) if (err) goto err_vport_metadata; + mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_VPORT_UC_ADDR_CHANGE); + err = esw_offloads_load_all_reps(esw); if (err) goto err_reps; @@ -2134,6 +2136,7 @@ int esw_offloads_init(struct mlx5_eswitch *esw) return 0; err_reps: + mlx5_eswitch_disable_pf_vf_vports(esw); esw_set_passing_vport_metadata(esw, false); err_vport_metadata: esw_offloads_steering_cleanup(esw); @@ -2159,11 +2162,12 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, return err; } -void esw_offloads_cleanup(struct mlx5_eswitch *esw) +void esw_offloads_disable(struct mlx5_eswitch *esw) { mlx5_rdma_disable_roce(esw->dev); esw_offloads_devcom_cleanup(esw); esw_offloads_unload_all_reps(esw); + mlx5_eswitch_disable_pf_vf_vports(esw); esw_set_passing_vport_metadata(esw, false); esw_offloads_steering_cleanup(esw); esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; -- GitLab From 0ab6a3ddbad40ef5b6b8c2353fd53fa4ecf9c479 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 Jul 2019 20:15:25 +0200 Subject: [PATCH 1563/7155] hrtimer: Make enqueue mode check work on RT hrtimer_start_range_ns() has a WARN_ONCE() which verifies that a timer which is marker for softirq expiry is not queued in the hard interrupt base and vice versa. When PREEMPT_RT is enabled, timers which are not explicitely marked to expire in hard interrupt context are deferrred to the soft interrupt. So the regular check would trigger. Change the check, so when PREEMPT_RT is enabled, it is verified that the timers marked for hard interrupt expiry are not tried to be queued for soft interrupt expiry or any of the unmarked and softirq marked is tried to be expired in hard interrupt context. Signed-off-by: Thomas Gleixner --- include/linux/hrtimer.h | 3 +++ kernel/time/hrtimer.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 15c2ba6b6316..7d0d0a36a8f4 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -107,6 +107,8 @@ enum hrtimer_restart { * @state: state information (See bit values above) * @is_rel: Set if the timer was armed relative * @is_soft: Set if hrtimer will be expired in soft interrupt context. + * @is_hard: Set if hrtimer will be expired in hard interrupt context + * even on RT. * * The hrtimer structure must be initialized by hrtimer_init() */ @@ -118,6 +120,7 @@ struct hrtimer { u8 state; u8 is_rel; u8 is_soft; + u8 is_hard; }; /** diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index dab1ea1a99d0..0ace301a56f4 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1107,9 +1107,13 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, /* * Check whether the HRTIMER_MODE_SOFT bit and hrtimer.is_soft - * match. + * match on CONFIG_PREEMPT_RT = n. With PREEMPT_RT check the hard + * expiry mode because unmarked timers are moved to softirq expiry. */ - WARN_ON_ONCE(!(mode & HRTIMER_MODE_SOFT) ^ !timer->is_soft); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + WARN_ON_ONCE(!(mode & HRTIMER_MODE_SOFT) ^ !timer->is_soft); + else + WARN_ON_ONCE(!(mode & HRTIMER_MODE_HARD) ^ !timer->is_hard); base = lock_hrtimer_base(timer, &flags); @@ -1288,6 +1292,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, base += hrtimer_clockid_to_base(clock_id); timer->is_soft = softtimer; + timer->is_hard = !softtimer; timer->base = &cpu_base->clock_base[base]; timerqueue_init(&timer->node); } -- GitLab From d5096aa65acd0ef2d18ac8247260ab4481ade399 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:52 +0200 Subject: [PATCH 1564/7155] sched: Mark hrtimers to expire in hard interrupt context The scheduler related hrtimers need to expire in hard interrupt context even on PREEMPT_RT enabled kernels. Mark then as such. No functional change. [ tglx: Split out from larger combo patch. Add changelog. ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.077004842@linutronix.de --- kernel/sched/core.c | 6 +++--- kernel/sched/deadline.c | 4 ++-- kernel/sched/rt.c | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b037f195473..389e0993fbb4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -255,7 +255,7 @@ static void __hrtick_restart(struct rq *rq) { struct hrtimer *timer = &rq->hrtick_timer; - hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED_HARD); } /* @@ -314,7 +314,7 @@ void hrtick_start(struct rq *rq, u64 delay) */ delay = max_t(u64, delay, 10000LL); hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), - HRTIMER_MODE_REL_PINNED); + HRTIMER_MODE_REL_PINNED_HARD); } #endif /* CONFIG_SMP */ @@ -328,7 +328,7 @@ static void hrtick_rq_init(struct rq *rq) rq->hrtick_csd.info = rq; #endif - hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); rq->hrtick_timer.function = hrtick; } #else /* CONFIG_SCHED_HRTICK */ diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index ef5b9f6b1d42..0359612d5443 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -923,7 +923,7 @@ static int start_dl_timer(struct task_struct *p) */ if (!hrtimer_is_queued(timer)) { get_task_struct(p); - hrtimer_start(timer, act, HRTIMER_MODE_ABS); + hrtimer_start(timer, act, HRTIMER_MODE_ABS_HARD); } return 1; @@ -1053,7 +1053,7 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se) { struct hrtimer *timer = &dl_se->dl_timer; - hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); timer->function = dl_task_timer; } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index a532558a5176..da3e85e61013 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -45,8 +45,8 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) raw_spin_lock_init(&rt_b->rt_runtime_lock); - hrtimer_init(&rt_b->rt_period_timer, - CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&rt_b->rt_period_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_HARD); rt_b->rt_period_timer.function = sched_rt_period_timer; } @@ -67,7 +67,8 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b) * to update the period. */ hrtimer_forward_now(&rt_b->rt_period_timer, ns_to_ktime(0)); - hrtimer_start_expires(&rt_b->rt_period_timer, HRTIMER_MODE_ABS_PINNED); + hrtimer_start_expires(&rt_b->rt_period_timer, + HRTIMER_MODE_ABS_PINNED_HARD); } raw_spin_unlock(&rt_b->rt_runtime_lock); } -- GitLab From 30f9028b6c43fd17c006550594ea3dbb87afbf80 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:53 +0200 Subject: [PATCH 1565/7155] perf/core: Mark hrtimers to expire in hard interrupt context To guarantee that the multiplexing mechanism and the hrtimer driven events work on PREEMPT_RT enabled kernels it's required that the related hrtimers expire in hard interrupt context. Mark them so PREEMPT_RT kernels wont defer them to soft interrupt context. No functional change. [ tglx: Split out of larger combo patch. Added changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.169509224@linutronix.de --- kernel/events/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 026a14541a38..9d623e257a51 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1103,7 +1103,7 @@ static void __perf_mux_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu) cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * interval); raw_spin_lock_init(&cpuctx->hrtimer_lock); - hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); + hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); timer->function = perf_mux_hrtimer_handler; } @@ -1121,7 +1121,7 @@ static int perf_mux_hrtimer_restart(struct perf_cpu_context *cpuctx) if (!cpuctx->hrtimer_active) { cpuctx->hrtimer_active = 1; hrtimer_forward_now(timer, cpuctx->hrtimer_interval); - hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED_HARD); } raw_spin_unlock_irqrestore(&cpuctx->hrtimer_lock, flags); @@ -9491,7 +9491,7 @@ static void perf_swevent_start_hrtimer(struct perf_event *event) period = max_t(u64, 10000, hwc->sample_period); } hrtimer_start(&hwc->hrtimer, ns_to_ktime(period), - HRTIMER_MODE_REL_PINNED); + HRTIMER_MODE_REL_PINNED_HARD); } static void perf_swevent_cancel_hrtimer(struct perf_event *event) @@ -9513,7 +9513,7 @@ static void perf_swevent_init_hrtimer(struct perf_event *event) if (!is_sampling_event(event)) return; - hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); hwc->hrtimer.function = perf_swevent_hrtimer; /* -- GitLab From d2ab4cf4943576fb060b8a69341d9e0c2a952ba7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:54 +0200 Subject: [PATCH 1566/7155] watchdog: Mark watchdog_hrtimer to expire in hard interrupt context The watchdog hrtimer must expire in hard interrupt context even on PREEMPT_RT=y kernels as otherwise the hard/softlockup detection logic would not work. No functional change. [ tglx: Split out from larger combo patch. Added changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.262895510@linutronix.de --- kernel/watchdog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 7f9e7b9306fe..f41334ef0971 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -490,10 +490,10 @@ static void watchdog_enable(unsigned int cpu) * Start the timer first to prevent the NMI watchdog triggering * before the timer has a chance to fire. */ - hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); hrtimer->function = watchdog_timer_fn; hrtimer_start(hrtimer, ns_to_ktime(sample_period), - HRTIMER_MODE_REL_PINNED); + HRTIMER_MODE_REL_PINNED_HARD); /* Initialize timestamp */ __touch_watchdog(); -- GitLab From 2c0d278f3293fc59da0d183075415ca1e8c93b40 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:55 +0200 Subject: [PATCH 1567/7155] KVM: LAPIC: Mark hrtimer to expire in hard interrupt context On PREEMPT_RT enabled kernels unmarked hrtimers are moved into soft interrupt expiry mode by default. While that's not a functional requirement for the KVM local APIC timer emulation, it's a latency issue which can be avoided by marking the timer so hard interrupt context expiry is enforced. No functional change. [ tglx: Split out from larger combo patch. Add changelog. ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Paolo Bonzini Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.363363474@linutronix.de --- arch/x86/kvm/lapic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0aa158657f20..b9e516099d07 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1601,7 +1601,7 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic) likely(ns > apic->lapic_timer.timer_advance_ns)) { expire = ktime_add_ns(now, ns); expire = ktime_sub_ns(expire, ktimer->timer_advance_ns); - hrtimer_start(&ktimer->timer, expire, HRTIMER_MODE_ABS); + hrtimer_start(&ktimer->timer, expire, HRTIMER_MODE_ABS_HARD); } else apic_timer_expired(apic); @@ -2302,7 +2302,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns) apic->vcpu = vcpu; hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC, - HRTIMER_MODE_ABS); + HRTIMER_MODE_ABS_HARD); apic->lapic_timer.timer.function = apic_timer_fn; if (timer_advance_ns == -1) { apic->lapic_timer.timer_advance_ns = LAPIC_TIMER_ADVANCE_ADJUST_INIT; @@ -2487,7 +2487,7 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) timer = &vcpu->arch.apic->lapic_timer.timer; if (hrtimer_cancel(timer)) - hrtimer_start_expires(timer, HRTIMER_MODE_ABS); + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_HARD); } /* -- GitLab From 902a9f9c509053161e987778dc5836d2628f53b7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:56 +0200 Subject: [PATCH 1568/7155] tick: Mark tick related hrtimers to expiry in hard interrupt context The tick related hrtimers, which drive the scheduler tick and hrtimer based broadcasting are required to expire in hard interrupt context for obvious reasons. Mark them so PREEMPT_RT kernels wont move them to soft interrupt expiry. Make the horribly formatted RCU_NONIDLE bracket maze readable while at it. No functional change, [ tglx: Split out from larger combo patch. Add changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.459144407@linutronix.de --- kernel/time/tick-broadcast-hrtimer.c | 13 +++++++++---- kernel/time/tick-sched.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c index 5be6154e2fd2..c1f5bb590b5e 100644 --- a/kernel/time/tick-broadcast-hrtimer.c +++ b/kernel/time/tick-broadcast-hrtimer.c @@ -59,11 +59,16 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) * hrtimer_{start/cancel} functions call into tracing, * calls to these functions must be bound within RCU_NONIDLE. */ - RCU_NONIDLE({ + RCU_NONIDLE( + { bc_moved = hrtimer_try_to_cancel(&bctimer) >= 0; - if (bc_moved) + if (bc_moved) { hrtimer_start(&bctimer, expires, - HRTIMER_MODE_ABS_PINNED);}); + HRTIMER_MODE_ABS_PINNED_HARD); + } + } + ); + if (bc_moved) { /* Bind the "device" to the cpu */ bc->bound_on = smp_processor_id(); @@ -104,7 +109,7 @@ static enum hrtimer_restart bc_handler(struct hrtimer *t) void tick_setup_hrtimer_broadcast(void) { - hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); bctimer.function = bc_handler; clockevents_register_device(&ce_broadcast_hrtimer); } diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index be9707f68024..01ff32a02af2 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -634,10 +634,12 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) /* Forward the time to expire in the future */ hrtimer_forward(&ts->sched_timer, now, tick_period); - if (ts->nohz_mode == NOHZ_MODE_HIGHRES) - hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED); - else + if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { + hrtimer_start_expires(&ts->sched_timer, + HRTIMER_MODE_ABS_PINNED_HARD); + } else { tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1); + } /* * Reset to make sure next tick stop doesn't get fooled by past @@ -802,7 +804,8 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu) } if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { - hrtimer_start(&ts->sched_timer, tick, HRTIMER_MODE_ABS_PINNED); + hrtimer_start(&ts->sched_timer, tick, + HRTIMER_MODE_ABS_PINNED_HARD); } else { hrtimer_set_expires(&ts->sched_timer, tick); tick_program_event(tick, 1); @@ -1327,7 +1330,7 @@ void tick_setup_sched_timer(void) /* * Emulate tick processing via per-CPU hrtimers: */ - hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); ts->sched_timer.function = tick_sched_timer; /* Get the next period (per-CPU) */ @@ -1342,7 +1345,7 @@ void tick_setup_sched_timer(void) } hrtimer_forward(&ts->sched_timer, now, tick_period); - hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED); + hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED_HARD); tick_nohz_activate(ts, NOHZ_MODE_HIGHRES); } #endif /* HIGH_RES_TIMERS */ -- GitLab From f5c2f0215e36d76fbb9605283dd7535af09f5770 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:57 +0200 Subject: [PATCH 1569/7155] hrtimer: Move unmarked hrtimers to soft interrupt expiry on RT On PREEMPT_RT not all hrtimers can be expired in hard interrupt context even if that is perfectly fine on a PREEMPT_RT=n kernel, e.g. because they take regular spinlocks. Also for latency reasons PREEMPT_RT tries to defer most hrtimers' expiry into softirq context. hrtimers marked with HRTIMER_MODE_HARD must be kept in hard interrupt context expiry mode. Add the required logic. No functional change for PREEMPT_RT=n kernels. [ tglx: Split out of a larger combo patch. Added changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.551967692@linutronix.de --- kernel/time/hrtimer.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 0ace301a56f4..90dcc4d95e91 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1275,8 +1275,17 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode) { bool softtimer = !!(mode & HRTIMER_MODE_SOFT); - int base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0; struct hrtimer_cpu_base *cpu_base; + int base; + + /* + * On PREEMPT_RT enabled kernels hrtimers which are not explicitely + * marked for hard interrupt expiry mode are moved into soft + * interrupt context for latency reasons and because the callbacks + * can invoke functions which might sleep on RT, e.g. spin_lock(). + */ + if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(mode & HRTIMER_MODE_HARD)) + softtimer = true; memset(timer, 0, sizeof(struct hrtimer)); @@ -1290,6 +1299,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, if (clock_id == CLOCK_REALTIME && mode & HRTIMER_MODE_REL) clock_id = CLOCK_MONOTONIC; + base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0; base += hrtimer_clockid_to_base(clock_id); timer->is_soft = softtimer; timer->is_hard = !softtimer; -- GitLab From 1842f5a427f5323f5c19ab99b55d09b3ab5172a5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 20:30:58 +0200 Subject: [PATCH 1570/7155] hrtimer: Determine hard/soft expiry mode for hrtimer sleepers on RT On PREEMPT_RT enabled kernels hrtimers which are not explicitely marked for hard interrupt expiry mode are moved into soft interrupt context either for latency reasons or because the hrtimer callback takes regular spinlocks or invokes other functions which are not suitable for hard interrupt context on PREEMPT_RT. The hrtimer_sleeper callback is RT compatible in hard interrupt context, but there is a latency concern: Untrusted userspace can spawn many threads which arm timers for the same expiry time on the same CPU. On expiry that causes a latency spike due to the wakeup of a gazillion threads. OTOH, priviledged real-time user space applications rely on the low latency of hard interrupt wakeups. These syscall related wakeups are all based on hrtimer sleepers. If the current task is in a real-time scheduling class, mark the mode for hard interrupt expiry. [ tglx: Split out of a larger combo patch. Added changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Reviewed-by: Steven Rostedt (VMware) Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.645792403@linutronix.de --- kernel/time/hrtimer.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 90dcc4d95e91..c101f88ae8aa 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1676,6 +1676,16 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer) void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, enum hrtimer_mode mode) { + /* + * Make the enqueue delivery mode check work on RT. If the sleeper + * was initialized for hard interrupt delivery, force the mode bit. + * This is a special case for hrtimer_sleepers because + * hrtimer_init_sleeper() determines the delivery mode on RT so the + * fiddling with this decision is avoided at the call sites. + */ + if (IS_ENABLED(CONFIG_PREEMPT_RT) && sl->timer.is_hard) + mode |= HRTIMER_MODE_HARD; + hrtimer_start_expires(&sl->timer, mode); } EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires); @@ -1683,6 +1693,30 @@ EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires); static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, enum hrtimer_mode mode) { + /* + * On PREEMPT_RT enabled kernels hrtimers which are not explicitely + * marked for hard interrupt expiry mode are moved into soft + * interrupt context either for latency reasons or because the + * hrtimer callback takes regular spinlocks or invokes other + * functions which are not suitable for hard interrupt context on + * PREEMPT_RT. + * + * The hrtimer_sleeper callback is RT compatible in hard interrupt + * context, but there is a latency concern: Untrusted userspace can + * spawn many threads which arm timers for the same expiry time on + * the same CPU. That causes a latency spike due to the wakeup of + * a gazillion threads. + * + * OTOH, priviledged real-time user space applications rely on the + * low latency of hard interrupt wakeups. If the current task is in + * a real-time scheduling class, mark the mode for hard interrupt + * expiry. + */ + if (IS_ENABLED(CONFIG_PREEMPT_RT)) { + if (task_is_realtime(current) && !(mode & HRTIMER_MODE_SOFT)) + mode |= HRTIMER_MODE_HARD; + } + __hrtimer_init(&sl->timer, clock_id, mode); sl->timer.function = hrtimer_wakeup; sl->task = current; -- GitLab From f61eff83cec9cfab31fd30a2ca8856be379cdcd5 Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Fri, 26 Jul 2019 20:30:59 +0200 Subject: [PATCH 1571/7155] hrtimer: Prepare support for PREEMPT_RT When PREEMPT_RT is enabled, the soft interrupt thread can be preempted. If the soft interrupt thread is preempted in the middle of a timer callback, then calling hrtimer_cancel() can lead to two issues: - If the caller is on a remote CPU then it has to spin wait for the timer handler to complete. This can result in unbound priority inversion. - If the caller originates from the task which preempted the timer handler on the same CPU, then spin waiting for the timer handler to complete is never going to end. To avoid these issues, add a new lock to the timer base which is held around the execution of the timer callbacks. If hrtimer_cancel() detects that the timer callback is currently running, it blocks on the expiry lock. When the callback is finished, the expiry lock is dropped by the softirq thread which wakes up the waiter and the system makes progress. This addresses both the priority inversion and the life lock issues. The same issue can happen in virtual machines when the vCPU which runs a timer callback is scheduled out. If a second vCPU of the same guest calls hrtimer_cancel() it will spin wait for the other vCPU to be scheduled back in. The expiry lock mechanism would avoid that. It'd be trivial to enable this when paravirt spinlocks are enabled in a guest, but it's not clear whether this is an actual problem in the wild, so for now it's an RT only mechanism. [ tglx: Refactored it for mainline ] Signed-off-by: Anna-Maria Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.737767218@linutronix.de --- include/linux/hrtimer.h | 16 +++++++ kernel/time/hrtimer.c | 95 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 7d0d0a36a8f4..5df4bcff96d5 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -192,6 +192,10 @@ enum hrtimer_base_type { * @nr_retries: Total number of hrtimer interrupt retries * @nr_hangs: Total number of hrtimer interrupt hangs * @max_hang_time: Maximum time spent in hrtimer_interrupt + * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are + * expired + * @timer_waiters: A hrtimer_cancel() invocation waits for the timer + * callback to finish. * @expires_next: absolute time of the next event, is required for remote * hrtimer enqueue; it is the total first expiry time (hard * and soft hrtimer are taken into account) @@ -218,6 +222,10 @@ struct hrtimer_cpu_base { unsigned short nr_retries; unsigned short nr_hangs; unsigned int max_hang_time; +#endif +#ifdef CONFIG_PREEMPT_RT + spinlock_t softirq_expiry_lock; + atomic_t timer_waiters; #endif ktime_t expires_next; struct hrtimer *next_timer; @@ -350,6 +358,14 @@ extern void hrtimers_resume(void); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); +#ifdef CONFIG_PREEMPT_RT +void hrtimer_cancel_wait_running(const struct hrtimer *timer); +#else +static inline void hrtimer_cancel_wait_running(struct hrtimer *timer) +{ + cpu_relax(); +} +#endif /* Exported timer functions: */ diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index c101f88ae8aa..499122752649 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1162,6 +1162,82 @@ int hrtimer_try_to_cancel(struct hrtimer *timer) } EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel); +#ifdef CONFIG_PREEMPT_RT +static void hrtimer_cpu_base_init_expiry_lock(struct hrtimer_cpu_base *base) +{ + spin_lock_init(&base->softirq_expiry_lock); +} + +static void hrtimer_cpu_base_lock_expiry(struct hrtimer_cpu_base *base) +{ + spin_lock(&base->softirq_expiry_lock); +} + +static void hrtimer_cpu_base_unlock_expiry(struct hrtimer_cpu_base *base) +{ + spin_unlock(&base->softirq_expiry_lock); +} + +/* + * The counterpart to hrtimer_cancel_wait_running(). + * + * If there is a waiter for cpu_base->expiry_lock, then it was waiting for + * the timer callback to finish. Drop expiry_lock and reaquire it. That + * allows the waiter to acquire the lock and make progress. + */ +static void hrtimer_sync_wait_running(struct hrtimer_cpu_base *cpu_base, + unsigned long flags) +{ + if (atomic_read(&cpu_base->timer_waiters)) { + raw_spin_unlock_irqrestore(&cpu_base->lock, flags); + spin_unlock(&cpu_base->softirq_expiry_lock); + spin_lock(&cpu_base->softirq_expiry_lock); + raw_spin_lock_irq(&cpu_base->lock); + } +} + +/* + * This function is called on PREEMPT_RT kernels when the fast path + * deletion of a timer failed because the timer callback function was + * running. + * + * This prevents priority inversion, if the softirq thread on a remote CPU + * got preempted, and it prevents a life lock when the task which tries to + * delete a timer preempted the softirq thread running the timer callback + * function. + */ +void hrtimer_cancel_wait_running(const struct hrtimer *timer) +{ + struct hrtimer_clock_base *base = timer->base; + + if (!timer->is_soft || !base || !base->cpu_base) { + cpu_relax(); + return; + } + + /* + * Mark the base as contended and grab the expiry lock, which is + * held by the softirq across the timer callback. Drop the lock + * immediately so the softirq can expire the next timer. In theory + * the timer could already be running again, but that's more than + * unlikely and just causes another wait loop. + */ + atomic_inc(&base->cpu_base->timer_waiters); + spin_lock_bh(&base->cpu_base->softirq_expiry_lock); + atomic_dec(&base->cpu_base->timer_waiters); + spin_unlock_bh(&base->cpu_base->softirq_expiry_lock); +} +#else +static inline void +hrtimer_cpu_base_init_expiry_lock(struct hrtimer_cpu_base *base) { } +static inline void +hrtimer_cpu_base_lock_expiry(struct hrtimer_cpu_base *base) { } +static inline void +hrtimer_cpu_base_unlock_expiry(struct hrtimer_cpu_base *base) { } +static inline void hrtimer_sync_wait_running(struct hrtimer_cpu_base *base, + unsigned long flags) { } +#endif + /** * hrtimer_cancel - cancel a timer and wait for the handler to finish. * @timer: the timer to be cancelled @@ -1172,13 +1248,15 @@ EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel); */ int hrtimer_cancel(struct hrtimer *timer) { - for (;;) { - int ret = hrtimer_try_to_cancel(timer); + int ret; - if (ret >= 0) - return ret; - cpu_relax(); - } + do { + ret = hrtimer_try_to_cancel(timer); + + if (ret < 0) + hrtimer_cancel_wait_running(timer); + } while (ret < 0); + return ret; } EXPORT_SYMBOL_GPL(hrtimer_cancel); @@ -1475,6 +1553,8 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now, break; __run_hrtimer(cpu_base, base, timer, &basenow, flags); + if (active_mask == HRTIMER_ACTIVE_SOFT) + hrtimer_sync_wait_running(cpu_base, flags); } } } @@ -1485,6 +1565,7 @@ static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h) unsigned long flags; ktime_t now; + hrtimer_cpu_base_lock_expiry(cpu_base); raw_spin_lock_irqsave(&cpu_base->lock, flags); now = hrtimer_update_base(cpu_base); @@ -1494,6 +1575,7 @@ static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h) hrtimer_update_softirq_timer(cpu_base, true); raw_spin_unlock_irqrestore(&cpu_base->lock, flags); + hrtimer_cpu_base_unlock_expiry(cpu_base); } #ifdef CONFIG_HIGH_RES_TIMERS @@ -1897,6 +1979,7 @@ int hrtimers_prepare_cpu(unsigned int cpu) cpu_base->softirq_next_timer = NULL; cpu_base->expires_next = KTIME_MAX; cpu_base->softirq_expires_next = KTIME_MAX; + hrtimer_cpu_base_init_expiry_lock(cpu_base); return 0; } -- GitLab From 030dcdd197d77374879bb5603d091eee7d8aba80 Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Fri, 26 Jul 2019 20:31:00 +0200 Subject: [PATCH 1572/7155] timers: Prepare support for PREEMPT_RT When PREEMPT_RT is enabled, the soft interrupt thread can be preempted. If the soft interrupt thread is preempted in the middle of a timer callback, then calling del_timer_sync() can lead to two issues: - If the caller is on a remote CPU then it has to spin wait for the timer handler to complete. This can result in unbound priority inversion. - If the caller originates from the task which preempted the timer handler on the same CPU, then spin waiting for the timer handler to complete is never going to end. To avoid these issues, add a new lock to the timer base which is held around the execution of the timer callbacks. If del_timer_sync() detects that the timer callback is currently running, it blocks on the expiry lock. When the callback is finished, the expiry lock is dropped by the softirq thread which wakes up the waiter and the system makes progress. This addresses both the priority inversion and the life lock issues. This mechanism is not used for timers which are marked IRQSAFE as for those preemption is disabled accross the callback and therefore this situation cannot happen. The callbacks for such timers need to be individually audited for RT compliance. The same issue can happen in virtual machines when the vCPU which runs a timer callback is scheduled out. If a second vCPU of the same guest calls del_timer_sync() it will spin wait for the other vCPU to be scheduled back in. The expiry lock mechanism would avoid that. It'd be trivial to enable this when paravirt spinlocks are enabled in a guest, but it's not clear whether this is an actual problem in the wild, so for now it's an RT only mechanism. As the softirq thread can be preempted with PREEMPT_RT=y, the SMP variant of del_timer_sync() needs to be used on UP as well. [ tglx: Refactored it for mainline ] Signed-off-by: Anna-Maria Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190726185753.832418500@linutronix.de --- include/linux/timer.h | 2 +- kernel/time/timer.c | 103 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/include/linux/timer.h b/include/linux/timer.h index 282e4f2a532a..1e6650ed066d 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -183,7 +183,7 @@ extern void add_timer(struct timer_list *timer); extern int try_to_del_timer_sync(struct timer_list *timer); -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) extern int del_timer_sync(struct timer_list *timer); #else # define del_timer_sync(t) del_timer(t) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 343c7ba33b1c..673c6a0f0c45 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -196,6 +196,10 @@ EXPORT_SYMBOL(jiffies_64); struct timer_base { raw_spinlock_t lock; struct timer_list *running_timer; +#ifdef CONFIG_PREEMPT_RT + spinlock_t expiry_lock; + atomic_t timer_waiters; +#endif unsigned long clk; unsigned long next_expiry; unsigned int cpu; @@ -1227,7 +1231,78 @@ int try_to_del_timer_sync(struct timer_list *timer) } EXPORT_SYMBOL(try_to_del_timer_sync); -#ifdef CONFIG_SMP +#ifdef CONFIG_PREEMPT_RT +static __init void timer_base_init_expiry_lock(struct timer_base *base) +{ + spin_lock_init(&base->expiry_lock); +} + +static inline void timer_base_lock_expiry(struct timer_base *base) +{ + spin_lock(&base->expiry_lock); +} + +static inline void timer_base_unlock_expiry(struct timer_base *base) +{ + spin_unlock(&base->expiry_lock); +} + +/* + * The counterpart to del_timer_wait_running(). + * + * If there is a waiter for base->expiry_lock, then it was waiting for the + * timer callback to finish. Drop expiry_lock and reaquire it. That allows + * the waiter to acquire the lock and make progress. + */ +static void timer_sync_wait_running(struct timer_base *base) +{ + if (atomic_read(&base->timer_waiters)) { + spin_unlock(&base->expiry_lock); + spin_lock(&base->expiry_lock); + } +} + +/* + * This function is called on PREEMPT_RT kernels when the fast path + * deletion of a timer failed because the timer callback function was + * running. + * + * This prevents priority inversion, if the softirq thread on a remote CPU + * got preempted, and it prevents a life lock when the task which tries to + * delete a timer preempted the softirq thread running the timer callback + * function. + */ +static void del_timer_wait_running(struct timer_list *timer) +{ + u32 tf; + + tf = READ_ONCE(timer->flags); + if (!(tf & TIMER_MIGRATING)) { + struct timer_base *base = get_timer_base(tf); + + /* + * Mark the base as contended and grab the expiry lock, + * which is held by the softirq across the timer + * callback. Drop the lock immediately so the softirq can + * expire the next timer. In theory the timer could already + * be running again, but that's more than unlikely and just + * causes another wait loop. + */ + atomic_inc(&base->timer_waiters); + spin_lock_bh(&base->expiry_lock); + atomic_dec(&base->timer_waiters); + spin_unlock_bh(&base->expiry_lock); + } +} +#else +static inline void timer_base_init_expiry_lock(struct timer_base *base) { } +static inline void timer_base_lock_expiry(struct timer_base *base) { } +static inline void timer_base_unlock_expiry(struct timer_base *base) { } +static inline void timer_sync_wait_running(struct timer_base *base) { } +static inline void del_timer_wait_running(struct timer_list *timer) { } +#endif + +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) /** * del_timer_sync - deactivate a timer and wait for the handler to finish. * @timer: the timer to be deactivated @@ -1266,6 +1341,8 @@ EXPORT_SYMBOL(try_to_del_timer_sync); */ int del_timer_sync(struct timer_list *timer) { + int ret; + #ifdef CONFIG_LOCKDEP unsigned long flags; @@ -1283,12 +1360,17 @@ int del_timer_sync(struct timer_list *timer) * could lead to deadlock. */ WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE)); - for (;;) { - int ret = try_to_del_timer_sync(timer); - if (ret >= 0) - return ret; - cpu_relax(); - } + + do { + ret = try_to_del_timer_sync(timer); + + if (unlikely(ret < 0)) { + del_timer_wait_running(timer); + cpu_relax(); + } + } while (ret < 0); + + return ret; } EXPORT_SYMBOL(del_timer_sync); #endif @@ -1360,10 +1442,13 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head) if (timer->flags & TIMER_IRQSAFE) { raw_spin_unlock(&base->lock); call_timer_fn(timer, fn, baseclk); + base->running_timer = NULL; raw_spin_lock(&base->lock); } else { raw_spin_unlock_irq(&base->lock); call_timer_fn(timer, fn, baseclk); + base->running_timer = NULL; + timer_sync_wait_running(base); raw_spin_lock_irq(&base->lock); } } @@ -1658,6 +1743,7 @@ static inline void __run_timers(struct timer_base *base) if (!time_after_eq(jiffies, base->clk)) return; + timer_base_lock_expiry(base); raw_spin_lock_irq(&base->lock); /* @@ -1684,8 +1770,8 @@ static inline void __run_timers(struct timer_base *base) while (levels--) expire_timers(base, heads + levels); } - base->running_timer = NULL; raw_spin_unlock_irq(&base->lock); + timer_base_unlock_expiry(base); } /* @@ -1930,6 +2016,7 @@ static void __init init_timer_cpu(int cpu) base->cpu = cpu; raw_spin_lock_init(&base->lock); base->clk = jiffies; + timer_base_init_expiry_lock(base); } } -- GitLab From 850377a875a481c393ce59111b0c9725005e0eb4 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 Jul 2019 12:37:15 +0200 Subject: [PATCH 1573/7155] sched/deadline: Ensure inactive_timer runs in hardirq context SCHED_DEADLINE inactive timer needs to run in hardirq context (as dl_task_timer already does) on PREEMPT_RT Change the mode to HRTIMER_MODE_REL_HARD. [ tglx: Fixed up the start site, so mode debugging works ] Signed-off-by: Juri Lelli Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190731103715.4047-1-juri.lelli@redhat.com --- kernel/sched/deadline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 0359612d5443..83a663a34196 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -287,7 +287,7 @@ static void task_non_contending(struct task_struct *p) dl_se->dl_non_contending = 1; get_task_struct(p); - hrtimer_start(timer, ns_to_ktime(zerolag_time), HRTIMER_MODE_REL); + hrtimer_start(timer, ns_to_ktime(zerolag_time), HRTIMER_MODE_REL_HARD); } static void task_contending(struct sched_dl_entity *dl_se, int flags) @@ -1292,7 +1292,7 @@ void init_dl_inactive_task_timer(struct sched_dl_entity *dl_se) { struct hrtimer *timer = &dl_se->inactive_timer; - hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); timer->function = inactive_task_timer; } -- GitLab From 51ae33092bb8320497ec75ddc5ab383d8fafd55c Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Wed, 31 Jul 2019 00:33:49 +0200 Subject: [PATCH 1574/7155] alarmtimer: Prepare for PREEMPT_RT Use the hrtimer_cancel_wait_running() synchronization mechanism to prevent priority inversion and live locks on PREEMPT_RT. [ tglx: Split out of combo patch ] Signed-off-by: Anna-Maria Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.508744705@linutronix.de --- kernel/time/alarmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 57518efc3810..36947449dba2 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -432,7 +432,7 @@ int alarm_cancel(struct alarm *alarm) int ret = alarm_try_to_cancel(alarm); if (ret >= 0) return ret; - cpu_relax(); + hrtimer_cancel_wait_running(&alarm->timer); } } EXPORT_SYMBOL_GPL(alarm_cancel); -- GitLab From a125ecc16453a4fe0ba865c7df87b9c722991fdf Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Wed, 31 Jul 2019 00:33:50 +0200 Subject: [PATCH 1575/7155] timerfd: Prepare for PREEMPT_RT Use the hrtimer_cancel_wait_running() synchronization mechanism to prevent priority inversion and live locks on PREEMPT_RT. [ tglx: Split out of combo patch ] Signed-off-by: Anna-Maria Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.600085866@linutronix.de --- fs/timerfd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/timerfd.c b/fs/timerfd.c index 6a6fc8aa1de7..48305ba41e3c 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -471,7 +471,11 @@ static int do_timerfd_settime(int ufd, int flags, break; } spin_unlock_irq(&ctx->wqh.lock); - cpu_relax(); + + if (isalarm(ctx)) + hrtimer_cancel_wait_running(&ctx->t.alarm.timer); + else + hrtimer_cancel_wait_running(&ctx->t.tmr); } /* -- GitLab From c7e6d704a0097e59667495cf52dcc4e1085e620b Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Wed, 31 Jul 2019 00:33:51 +0200 Subject: [PATCH 1576/7155] itimers: Prepare for PREEMPT_RT Use the hrtimer_cancel_wait_running() synchronization mechanism to prevent priority inversion and live locks on PREEMPT_RT. As a benefit the retry loop gains the missing cpu_relax() on !RT. [ tglx: Split out of combo patch ] Signed-off-by: Anna-Maria Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.690771827@linutronix.de --- kernel/time/itimer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 02068b2d5862..9d26fd4ba4c0 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c @@ -213,6 +213,7 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) /* We are sharing ->siglock with it_real_fn() */ if (hrtimer_try_to_cancel(timer) < 0) { spin_unlock_irq(&tsk->sighand->siglock); + hrtimer_cancel_wait_running(timer); goto again; } expires = timeval_to_ktime(value->it_value); -- GitLab From 21670ee44f1e3565030bcabc62178b8e5eb2fce7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 31 Jul 2019 00:33:52 +0200 Subject: [PATCH 1577/7155] posix-timers: Cleanup the flag/flags confusion do_timer_settime() has a 'flags' argument and uses 'flag' for the interrupt flags, which is confusing at best. Rename the argument so 'flags' can be used for interrupt flags as usual. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.782664411@linutronix.de --- kernel/time/posix-timers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index d7f2d91acdac..f5aedd2f60df 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -844,13 +844,13 @@ int common_timer_set(struct k_itimer *timr, int flags, return 0; } -static int do_timer_settime(timer_t timer_id, int flags, +static int do_timer_settime(timer_t timer_id, int tmr_flags, struct itimerspec64 *new_spec64, struct itimerspec64 *old_spec64) { const struct k_clock *kc; struct k_itimer *timr; - unsigned long flag; + unsigned long flags; int error = 0; if (!timespec64_valid(&new_spec64->it_interval) || @@ -860,7 +860,7 @@ static int do_timer_settime(timer_t timer_id, int flags, if (old_spec64) memset(old_spec64, 0, sizeof(*old_spec64)); retry: - timr = lock_timer(timer_id, &flag); + timr = lock_timer(timer_id, &flags); if (!timr) return -EINVAL; @@ -868,9 +868,9 @@ static int do_timer_settime(timer_t timer_id, int flags, if (WARN_ON_ONCE(!kc || !kc->timer_set)) error = -EINVAL; else - error = kc->timer_set(timr, flags, new_spec64, old_spec64); + error = kc->timer_set(timr, tmr_flags, new_spec64, old_spec64); - unlock_timer(timr, flag); + unlock_timer(timr, flags); if (error == TIMER_RETRY) { old_spec64 = NULL; // We already got the old time... goto retry; -- GitLab From 6945e5c2abe008302b20266248d6de95575311a8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 31 Jul 2019 00:33:53 +0200 Subject: [PATCH 1578/7155] posix-timers: Rework cancel retry loops As a preparatory step for adding the PREEMPT RT specific synchronization mechanism to wait for a running timer callback, rework the timer cancel retry loops so they call a common function. This allows trivial substitution in one place. Originally-by: Anna-Maria Gleixner Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.874901027@linutronix.de --- kernel/time/posix-timers.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index f5aedd2f60df..bbe8f9686a70 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -805,6 +805,17 @@ static int common_hrtimer_try_to_cancel(struct k_itimer *timr) return hrtimer_try_to_cancel(&timr->it.real.timer); } +static struct k_itimer *timer_wait_running(struct k_itimer *timer, + unsigned long *flags) +{ + timer_t timer_id = READ_ONCE(timer->it_id); + + unlock_timer(timer, *flags); + cpu_relax(); + /* Relock the timer. It might be not longer hashed. */ + return lock_timer(timer_id, flags); +} + /* Set a POSIX.1b interval timer. */ int common_timer_set(struct k_itimer *timr, int flags, struct itimerspec64 *new_setting, @@ -859,8 +870,9 @@ static int do_timer_settime(timer_t timer_id, int tmr_flags, if (old_spec64) memset(old_spec64, 0, sizeof(*old_spec64)); -retry: + timr = lock_timer(timer_id, &flags); +retry: if (!timr) return -EINVAL; @@ -870,11 +882,14 @@ static int do_timer_settime(timer_t timer_id, int tmr_flags, else error = kc->timer_set(timr, tmr_flags, new_spec64, old_spec64); - unlock_timer(timr, flags); if (error == TIMER_RETRY) { - old_spec64 = NULL; // We already got the old time... + // We already got the old time... + old_spec64 = NULL; + /* Unlocks and relocks the timer if it still exists */ + timr = timer_wait_running(timr, &flags); goto retry; } + unlock_timer(timr, flags); return error; } @@ -951,13 +966,15 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id) struct k_itimer *timer; unsigned long flags; -retry_delete: timer = lock_timer(timer_id, &flags); + +retry_delete: if (!timer) return -EINVAL; - if (timer_delete_hook(timer) == TIMER_RETRY) { - unlock_timer(timer, flags); + if (unlikely(timer_delete_hook(timer) == TIMER_RETRY)) { + /* Unlocks and relocks the timer if it still exists */ + timer = timer_wait_running(timer, &flags); goto retry_delete; } -- GitLab From 5d99b32a009e900a561f6a42ea7afe5b21288b8a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 31 Jul 2019 00:33:54 +0200 Subject: [PATCH 1579/7155] posix-timers: Move rcu_head out of it union Timer deletion on PREEMPT_RT is prone to priority inversion and live locks. The hrtimer code has a synchronization mechanism for this. Posix CPU timers will grow one. But that mechanism cannot be invoked while holding the k_itimer lock because that can deadlock against the running timer callback. So the lock must be dropped which allows the timer to be freed. The timer free can be prevented by taking RCU readlock before dropping the lock, but because the rcu_head is part of the 'it' union a concurrent free will overwrite the hrtimer on which the task is trying to synchronize. Move the rcu_head out of the union to prevent this. [ tglx: Fixed up kernel-doc. Rewrote changelog ] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20190730223828.965541887@linutronix.de --- include/linux/posix-timers.h | 5 +++-- kernel/time/posix-timers.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index b20798fc5191..604cec0e41ba 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -85,7 +85,8 @@ static inline int clockid_to_fd(const clockid_t clk) * @it_process: The task to wakeup on clock_nanosleep (CPU timers) * @sigq: Pointer to preallocated sigqueue * @it: Union representing the various posix timer type - * internals. Also used for rcu freeing the timer. + * internals. + * @rcu: RCU head for freeing the timer. */ struct k_itimer { struct list_head list; @@ -114,8 +115,8 @@ struct k_itimer { struct { struct alarm alarmtimer; } alarm; - struct rcu_head rcu; } it; + struct rcu_head rcu; }; void run_posix_cpu_timers(struct task_struct *task); diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index bbe8f9686a70..3e663f982c82 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -442,7 +442,7 @@ static struct k_itimer * alloc_posix_timer(void) static void k_itimer_rcu_free(struct rcu_head *head) { - struct k_itimer *tmr = container_of(head, struct k_itimer, it.rcu); + struct k_itimer *tmr = container_of(head, struct k_itimer, rcu); kmem_cache_free(posix_timers_cache, tmr); } @@ -459,7 +459,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) } put_pid(tmr->it_pid); sigqueue_free(tmr->sigq); - call_rcu(&tmr->it.rcu, k_itimer_rcu_free); + call_rcu(&tmr->rcu, k_itimer_rcu_free); } static int common_timer_create(struct k_itimer *new_timer) -- GitLab From fcb64c0f5640e629bd77c2cb088f9fd70ff5bde7 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 8 May 2019 11:44:56 +0300 Subject: [PATCH 1580/7155] net/mlx5: E-Switch, add ingress rate support Use the scheduling elements to implement ingress rate limiter on an eswitch ports ingress traffic. Since the ingress of eswitch port is the egress of VF port, we control eswitch ingress by controlling VF egress. Configuration is done using the ports' representor net devices. Please note that burst size configuration is not supported by devices ConnectX-5 and earlier generations. Configuration examples: tc: tc filter add dev enp59s0f0_0 root protocol ip matchall action police rate 1mbit burst 20k ovs: ovs-vsctl set interface eth0 ingress_policing_rate=1000 Signed-off-by: Eli Cohen Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 19 ++++ .../net/ethernet/mellanox/mlx5/core/en_rep.h | 1 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 100 ++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tc.h | 7 ++ .../net/ethernet/mellanox/mlx5/core/eswitch.c | 16 +++ .../net/ethernet/mellanox/mlx5/core/eswitch.h | 2 + 6 files changed, 145 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 6edf0aeb1e26..bf6f4835457e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1156,6 +1156,23 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv, } } +static +int mlx5e_rep_setup_tc_cls_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma) +{ + switch (ma->command) { + case TC_CLSMATCHALL_REPLACE: + return mlx5e_tc_configure_matchall(priv, ma); + case TC_CLSMATCHALL_DESTROY: + return mlx5e_tc_delete_matchall(priv, ma); + case TC_CLSMATCHALL_STATS: + mlx5e_tc_stats_matchall(priv, ma); + return 0; + default: + return -EOPNOTSUPP; + } +} + static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -1165,6 +1182,8 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data, switch (type) { case TC_SETUP_CLSFLOWER: return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags); + case TC_SETUP_CLSMATCHALL: + return mlx5e_rep_setup_tc_cls_matchall(priv, type_data); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 10fafd5fa17b..43eeebe9c8d2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -88,6 +88,7 @@ struct mlx5e_rep_priv { struct mlx5_flow_handle *vport_rx_rule; struct list_head vport_sqs_list; struct mlx5_rep_uplink_priv uplink_priv; /* valid for uplink rep */ + struct rtnl_link_stats64 prev_vf_vport_stats; struct devlink_port dl_port; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index f3ed028d5017..dc5fc3350b65 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3638,6 +3638,106 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, return err; } +static int apply_police_params(struct mlx5e_priv *priv, u32 rate, + struct netlink_ext_ack *extack) +{ + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_eswitch *esw; + u16 vport_num; + u32 rate_mbps; + int err; + + esw = priv->mdev->priv.eswitch; + /* rate is given in bytes/sec. + * First convert to bits/sec and then round to the nearest mbit/secs. + * mbit means million bits. + * Moreover, if rate is non zero we choose to configure to a minimum of + * 1 mbit/sec. + */ + rate_mbps = rate ? max_t(u32, (rate * 8 + 500000) / 1000000, 1) : 0; + vport_num = rpriv->rep->vport; + + err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps); + if (err) + NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware"); + + return err; +} + +static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv, + struct flow_action *flow_action, + struct netlink_ext_ack *extack) +{ + struct mlx5e_rep_priv *rpriv = priv->ppriv; + const struct flow_action_entry *act; + int err; + int i; + + if (!flow_action_has_entries(flow_action)) { + NL_SET_ERR_MSG_MOD(extack, "matchall called with no action"); + return -EINVAL; + } + + if (!flow_offload_has_one_action(flow_action)) { + NL_SET_ERR_MSG_MOD(extack, "matchall policing support only a single action"); + return -EOPNOTSUPP; + } + + flow_action_for_each(i, act, flow_action) { + switch (act->id) { + case FLOW_ACTION_POLICE: + err = apply_police_params(priv, act->police.rate_bytes_ps, extack); + if (err) + return err; + + rpriv->prev_vf_vport_stats = priv->stats.vf_vport; + break; + default: + NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall"); + return -EOPNOTSUPP; + } + } + + return 0; +} + +int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma) +{ + struct netlink_ext_ack *extack = ma->common.extack; + int prio = TC_H_MAJ(ma->common.prio) >> 16; + + if (prio != 1) { + NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported"); + return -EINVAL; + } + + return scan_tc_matchall_fdb_actions(priv, &ma->rule->action, extack); +} + +int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma) +{ + struct netlink_ext_ack *extack = ma->common.extack; + + return apply_police_params(priv, 0, extack); +} + +void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma) +{ + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct rtnl_link_stats64 cur_stats; + u64 dbytes; + u64 dpkts; + + cur_stats = priv->stats.vf_vport; + dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets; + dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes; + rpriv->prev_vf_vport_stats = cur_stats; + flow_stats_update(&ma->stats, dpkts, dbytes, jiffies); +} + static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index 1cb66bf76997..20f045e96c92 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -63,6 +63,13 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, struct flow_cls_offload *f, unsigned long flags); +int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *f); +int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *f); +void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma); + struct mlx5e_encap_entry; void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index f4ace5f8e884..5fbebee7254d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1585,6 +1585,22 @@ static int esw_vport_qos_config(struct mlx5_eswitch *esw, return 0; } +int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, + u32 rate_mbps) +{ + u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps); + + return mlx5_modify_scheduling_element_cmd(esw->dev, + SCHEDULING_HIERARCHY_E_SWITCH, + ctx, + vport->qos.esw_tsar_ix, + MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW); +} + static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN]) { ((u8 *)node_guid)[7] = mac[0]; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 4a03fdadb47e..804912e38dee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -261,6 +261,8 @@ void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw, struct mlx5_vport *vport); void esw_vport_del_ingress_acl_modify_metadata(struct mlx5_eswitch *esw, struct mlx5_vport *vport); +int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, + u32 rate_mbps); /* E-Switch API */ int mlx5_eswitch_init(struct mlx5_core_dev *dev); -- GitLab From 5d8a02536545080a555fe37064d24a402fd00d6a Mon Sep 17 00:00:00 2001 From: Gavi Teitz Date: Thu, 27 Jun 2019 13:58:56 +0300 Subject: [PATCH 1581/7155] net/mlx5: Add flow counter bulk infrastructure Add infrastructure to track bulks of flow counters, providing the means to allocate and deallocate bulks, and to acquire and release individual counters from the bulks. Signed-off-by: Gavi Teitz Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/fs_counters.c | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index 067a4b56498b..3e734e62a6cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -58,6 +58,7 @@ struct mlx5_fc { u64 lastpackets; u64 lastbytes; + struct mlx5_fc_bulk *bulk; u32 id; bool aging; @@ -412,3 +413,107 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev, fc_stats->sampling_interval = min_t(unsigned long, interval, fc_stats->sampling_interval); } + +/* Flow counter bluks */ + +struct mlx5_fc_bulk { + u32 base_id; + int bulk_len; + unsigned long *bitmask; + struct mlx5_fc fcs[0]; +}; + +static void +mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, u32 id) +{ + counter->bulk = bulk; + counter->id = id; +} + +static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk) +{ + return bitmap_weight(bulk->bitmask, bulk->bulk_len); +} + +static struct mlx5_fc_bulk __attribute__((unused)) +*mlx5_fc_bulk_create(struct mlx5_core_dev *dev) +{ + enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask; + struct mlx5_fc_bulk *bulk; + int err = -ENOMEM; + int bulk_len; + u32 base_id; + int i; + + alloc_bitmask = MLX5_CAP_GEN(dev, flow_counter_bulk_alloc); + bulk_len = alloc_bitmask > 0 ? MLX5_FC_BULK_NUM_FCS(alloc_bitmask) : 1; + + bulk = kzalloc(sizeof(*bulk) + bulk_len * sizeof(struct mlx5_fc), + GFP_KERNEL); + if (!bulk) + goto err_alloc_bulk; + + bulk->bitmask = kcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long), + GFP_KERNEL); + if (!bulk->bitmask) + goto err_alloc_bitmask; + + err = mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id); + if (err) + goto err_mlx5_cmd_bulk_alloc; + + bulk->base_id = base_id; + bulk->bulk_len = bulk_len; + for (i = 0; i < bulk_len; i++) { + mlx5_fc_init(&bulk->fcs[i], bulk, base_id + i); + set_bit(i, bulk->bitmask); + } + + return bulk; + +err_mlx5_cmd_bulk_alloc: + kfree(bulk->bitmask); +err_alloc_bitmask: + kfree(bulk); +err_alloc_bulk: + return ERR_PTR(err); +} + +static int __attribute__((unused)) +mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk) +{ + if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) { + mlx5_core_err(dev, "Freeing bulk before all counters were released\n"); + return -EBUSY; + } + + mlx5_cmd_fc_free(dev, bulk->base_id); + kfree(bulk->bitmask); + kfree(bulk); + + return 0; +} + +static struct mlx5_fc __attribute__((unused)) +*mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk) +{ + int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len); + + if (free_fc_index >= bulk->bulk_len) + return ERR_PTR(-ENOSPC); + + clear_bit(free_fc_index, bulk->bitmask); + return &bulk->fcs[free_fc_index]; +} + +static int __attribute__((unused)) +mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc) +{ + int fc_index = fc->id - bulk->base_id; + + if (test_bit(fc_index, bulk->bitmask)) + return -EINVAL; + + set_bit(fc_index, bulk->bitmask); + return 0; +} -- GitLab From 558101f1b9807b34d8eeefb352d11e642b7e98dd Mon Sep 17 00:00:00 2001 From: Gavi Teitz Date: Thu, 27 Jun 2019 20:53:03 +0300 Subject: [PATCH 1582/7155] net/mlx5: Add flow counter pool Add a pool of flow counters, based on flow counter bulks, removing the need to allocate a new counter via a costly FW command during the flow creation process. The time it takes to acquire/release a flow counter is cut from ~50 [us] to ~50 [ns]. The pool is part of the mlx5 driver instance, and provides flow counters for aging flows. mlx5_fc_create() was modified to provide counters for aging flows from the pool by default, and mlx5_destroy_fc() was modified to release counters back to the pool for later reuse. If bulk allocation is not supported or fails, and for non-aging flows, the fallback behavior is to allocate and free individual counters. The pool is comprised of three lists of flow counter bulks, one of fully used bulks, one of partially used bulks, and one of unused bulks. Counters are provided from the partially used bulks first, to help limit bulk fragmentation. The pool maintains a threshold, and strives to maintain the amount of available counters below it. The pool is increased in size when a counter acquisition request is made and there are no available counters, and it is decreased in size when the last counter in a bulk is released and there are more available counters than the threshold. All pool size changes are done in the context of the acquiring/releasing process. The value of the threshold is directly correlated to the amount of used counters the pool is providing, while constrained by a hard maximum, and is recalculated every time a bulk is allocated/freed. This ensures that the pool only consumes large amounts of memory for available counters if the pool is being used heavily. When fully populated and at the hard maximum, the buffer of available counters consumes ~40 [MB]. Signed-off-by: Gavi Teitz Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/fs_counters.c | 231 ++++++++++++++++-- include/linux/mlx5/driver.h | 12 + 2 files changed, 218 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index 3e734e62a6cd..51f1736c455d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -40,6 +40,8 @@ #define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000) /* Max number of counters to query in bulk read is 32K */ #define MLX5_SW_MAX_COUNTERS_BULK BIT(15) +#define MLX5_FC_POOL_MAX_THRESHOLD BIT(18) +#define MLX5_FC_POOL_USED_BUFF_RATIO 10 struct mlx5_fc_cache { u64 packets; @@ -65,6 +67,11 @@ struct mlx5_fc { struct mlx5_fc_cache cache ____cacheline_aligned_in_smp; }; +static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev); +static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool); +static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool); +static void mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc); + /* locking scheme: * * It is the responsibility of the user to prevent concurrent calls or bad @@ -202,13 +209,22 @@ static void mlx5_fc_stats_query_counter_range(struct mlx5_core_dev *dev, } } -static void mlx5_free_fc(struct mlx5_core_dev *dev, - struct mlx5_fc *counter) +static void mlx5_fc_free(struct mlx5_core_dev *dev, struct mlx5_fc *counter) { mlx5_cmd_fc_free(dev, counter->id); kfree(counter); } +static void mlx5_fc_release(struct mlx5_core_dev *dev, struct mlx5_fc *counter) +{ + struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; + + if (counter->bulk) + mlx5_fc_pool_release_counter(&fc_stats->fc_pool, counter); + else + mlx5_fc_free(dev, counter); +} + static void mlx5_fc_stats_work(struct work_struct *work) { struct mlx5_core_dev *dev = container_of(work, struct mlx5_core_dev, @@ -232,7 +248,7 @@ static void mlx5_fc_stats_work(struct work_struct *work) llist_for_each_entry_safe(counter, tmp, dellist, dellist) { mlx5_fc_stats_remove(dev, counter); - mlx5_free_fc(dev, counter); + mlx5_fc_release(dev, counter); } if (time_before(now, fc_stats->next_query) || @@ -248,26 +264,56 @@ static void mlx5_fc_stats_work(struct work_struct *work) fc_stats->next_query = now + fc_stats->sampling_interval; } -struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging) +static struct mlx5_fc *mlx5_fc_single_alloc(struct mlx5_core_dev *dev) { - struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; struct mlx5_fc *counter; int err; counter = kzalloc(sizeof(*counter), GFP_KERNEL); if (!counter) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&counter->list); err = mlx5_cmd_fc_alloc(dev, &counter->id); - if (err) - goto err_out; + if (err) { + kfree(counter); + return ERR_PTR(err); + } + + return counter; +} + +static struct mlx5_fc *mlx5_fc_acquire(struct mlx5_core_dev *dev, bool aging) +{ + struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; + struct mlx5_fc *counter; + + if (aging && MLX5_CAP_GEN(dev, flow_counter_bulk_alloc) != 0) { + counter = mlx5_fc_pool_acquire_counter(&fc_stats->fc_pool); + if (!IS_ERR(counter)) + return counter; + } + + return mlx5_fc_single_alloc(dev); +} + +struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging) +{ + struct mlx5_fc *counter = mlx5_fc_acquire(dev, aging); + struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats; + int err; + + if (IS_ERR(counter)) + return counter; + + INIT_LIST_HEAD(&counter->list); + counter->aging = aging; if (aging) { u32 id = counter->id; counter->cache.lastuse = jiffies; - counter->aging = true; + counter->lastbytes = counter->cache.bytes; + counter->lastpackets = counter->cache.packets; idr_preload(GFP_KERNEL); spin_lock(&fc_stats->counters_idr_lock); @@ -288,10 +334,7 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging) return counter; err_out_alloc: - mlx5_cmd_fc_free(dev, counter->id); -err_out: - kfree(counter); - + mlx5_fc_release(dev, counter); return ERR_PTR(err); } EXPORT_SYMBOL(mlx5_fc_create); @@ -315,7 +358,7 @@ void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter) return; } - mlx5_free_fc(dev, counter); + mlx5_fc_release(dev, counter); } EXPORT_SYMBOL(mlx5_fc_destroy); @@ -344,6 +387,7 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev) fc_stats->sampling_interval = MLX5_FC_STATS_PERIOD; INIT_DELAYED_WORK(&fc_stats->work, mlx5_fc_stats_work); + mlx5_fc_pool_init(&fc_stats->fc_pool, dev); return 0; err_wq_create: @@ -358,6 +402,7 @@ void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev) struct mlx5_fc *counter; struct mlx5_fc *tmp; + mlx5_fc_pool_cleanup(&fc_stats->fc_pool); cancel_delayed_work_sync(&dev->priv.fc_stats.work); destroy_workqueue(dev->priv.fc_stats.wq); dev->priv.fc_stats.wq = NULL; @@ -368,10 +413,10 @@ void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev) tmplist = llist_del_all(&fc_stats->addlist); llist_for_each_entry_safe(counter, tmp, tmplist, addlist) - mlx5_free_fc(dev, counter); + mlx5_fc_release(dev, counter); list_for_each_entry_safe(counter, tmp, &fc_stats->counters, list) - mlx5_free_fc(dev, counter); + mlx5_fc_release(dev, counter); } int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter, @@ -417,14 +462,15 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev, /* Flow counter bluks */ struct mlx5_fc_bulk { + struct list_head pool_list; u32 base_id; int bulk_len; unsigned long *bitmask; struct mlx5_fc fcs[0]; }; -static void -mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, u32 id) +static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, + u32 id) { counter->bulk = bulk; counter->id = id; @@ -435,8 +481,7 @@ static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk) return bitmap_weight(bulk->bitmask, bulk->bulk_len); } -static struct mlx5_fc_bulk __attribute__((unused)) -*mlx5_fc_bulk_create(struct mlx5_core_dev *dev) +static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev) { enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask; struct mlx5_fc_bulk *bulk; @@ -479,7 +524,7 @@ static struct mlx5_fc_bulk __attribute__((unused)) return ERR_PTR(err); } -static int __attribute__((unused)) +static int mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk) { if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) { @@ -494,8 +539,7 @@ mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk) return 0; } -static struct mlx5_fc __attribute__((unused)) -*mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk) +static struct mlx5_fc *mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk) { int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len); @@ -506,8 +550,7 @@ static struct mlx5_fc __attribute__((unused)) return &bulk->fcs[free_fc_index]; } -static int __attribute__((unused)) -mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc) +static int mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc) { int fc_index = fc->id - bulk->base_id; @@ -517,3 +560,141 @@ mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc) set_bit(fc_index, bulk->bitmask); return 0; } + +/* Flow counters pool API */ + +static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev) +{ + fc_pool->dev = dev; + mutex_init(&fc_pool->pool_lock); + INIT_LIST_HEAD(&fc_pool->fully_used); + INIT_LIST_HEAD(&fc_pool->partially_used); + INIT_LIST_HEAD(&fc_pool->unused); + fc_pool->available_fcs = 0; + fc_pool->used_fcs = 0; + fc_pool->threshold = 0; +} + +static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool) +{ + struct mlx5_core_dev *dev = fc_pool->dev; + struct mlx5_fc_bulk *bulk; + struct mlx5_fc_bulk *tmp; + + list_for_each_entry_safe(bulk, tmp, &fc_pool->fully_used, pool_list) + mlx5_fc_bulk_destroy(dev, bulk); + list_for_each_entry_safe(bulk, tmp, &fc_pool->partially_used, pool_list) + mlx5_fc_bulk_destroy(dev, bulk); + list_for_each_entry_safe(bulk, tmp, &fc_pool->unused, pool_list) + mlx5_fc_bulk_destroy(dev, bulk); +} + +static void mlx5_fc_pool_update_threshold(struct mlx5_fc_pool *fc_pool) +{ + fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD, + fc_pool->used_fcs / MLX5_FC_POOL_USED_BUFF_RATIO); +} + +static struct mlx5_fc_bulk * +mlx5_fc_pool_alloc_new_bulk(struct mlx5_fc_pool *fc_pool) +{ + struct mlx5_core_dev *dev = fc_pool->dev; + struct mlx5_fc_bulk *new_bulk; + + new_bulk = mlx5_fc_bulk_create(dev); + if (!IS_ERR(new_bulk)) + fc_pool->available_fcs += new_bulk->bulk_len; + mlx5_fc_pool_update_threshold(fc_pool); + return new_bulk; +} + +static void +mlx5_fc_pool_free_bulk(struct mlx5_fc_pool *fc_pool, struct mlx5_fc_bulk *bulk) +{ + struct mlx5_core_dev *dev = fc_pool->dev; + + fc_pool->available_fcs -= bulk->bulk_len; + mlx5_fc_bulk_destroy(dev, bulk); + mlx5_fc_pool_update_threshold(fc_pool); +} + +static struct mlx5_fc * +mlx5_fc_pool_acquire_from_list(struct list_head *src_list, + struct list_head *next_list, + bool move_non_full_bulk) +{ + struct mlx5_fc_bulk *bulk; + struct mlx5_fc *fc; + + if (list_empty(src_list)) + return ERR_PTR(-ENODATA); + + bulk = list_first_entry(src_list, struct mlx5_fc_bulk, pool_list); + fc = mlx5_fc_bulk_acquire_fc(bulk); + if (move_non_full_bulk || mlx5_fc_bulk_get_free_fcs_amount(bulk) == 0) + list_move(&bulk->pool_list, next_list); + return fc; +} + +static struct mlx5_fc * +mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool) +{ + struct mlx5_fc_bulk *new_bulk; + struct mlx5_fc *fc; + + mutex_lock(&fc_pool->pool_lock); + + fc = mlx5_fc_pool_acquire_from_list(&fc_pool->partially_used, + &fc_pool->fully_used, false); + if (IS_ERR(fc)) + fc = mlx5_fc_pool_acquire_from_list(&fc_pool->unused, + &fc_pool->partially_used, + true); + if (IS_ERR(fc)) { + new_bulk = mlx5_fc_pool_alloc_new_bulk(fc_pool); + if (IS_ERR(new_bulk)) { + fc = ERR_CAST(new_bulk); + goto out; + } + fc = mlx5_fc_bulk_acquire_fc(new_bulk); + list_add(&new_bulk->pool_list, &fc_pool->partially_used); + } + fc_pool->available_fcs--; + fc_pool->used_fcs++; + +out: + mutex_unlock(&fc_pool->pool_lock); + return fc; +} + +static void +mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc) +{ + struct mlx5_core_dev *dev = fc_pool->dev; + struct mlx5_fc_bulk *bulk = fc->bulk; + int bulk_free_fcs_amount; + + mutex_lock(&fc_pool->pool_lock); + + if (mlx5_fc_bulk_release_fc(bulk, fc)) { + mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n"); + goto unlock; + } + + fc_pool->available_fcs++; + fc_pool->used_fcs--; + + bulk_free_fcs_amount = mlx5_fc_bulk_get_free_fcs_amount(bulk); + if (bulk_free_fcs_amount == 1) + list_move_tail(&bulk->pool_list, &fc_pool->partially_used); + if (bulk_free_fcs_amount == bulk->bulk_len) { + list_del(&bulk->pool_list); + if (fc_pool->available_fcs > fc_pool->threshold) + mlx5_fc_pool_free_bulk(fc_pool, bulk); + else + list_add(&bulk->pool_list, &fc_pool->unused); + } + +unlock: + mutex_unlock(&fc_pool->pool_lock); +} diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 267b2bc0ca4a..d8f348ef9c33 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -477,6 +477,17 @@ struct mlx5_core_sriov { u16 max_vfs; }; +struct mlx5_fc_pool { + struct mlx5_core_dev *dev; + struct mutex pool_lock; /* protects pool lists */ + struct list_head fully_used; + struct list_head partially_used; + struct list_head unused; + int available_fcs; + int used_fcs; + int threshold; +}; + struct mlx5_fc_stats { spinlock_t counters_idr_lock; /* protects counters_idr */ struct idr counters_idr; @@ -489,6 +500,7 @@ struct mlx5_fc_stats { unsigned long next_query; unsigned long sampling_interval; /* jiffies */ u32 *bulk_query_out; + struct mlx5_fc_pool fc_pool; }; struct mlx5_events; -- GitLab From 68865419ba1bf502a5bd279a500deda64000249d Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 11 Jul 2019 11:20:22 +0300 Subject: [PATCH 1583/7155] net/mlx5e: Tx, Strict the room needed for SQ edge NOPs We use NOPs to populate the WQ fragment edge if the WQE does not fit in frag, to avoid WQEs crossing a page boundary (or wrap-around the WQ). The upper bound on the needed number of NOPs is one WQEBB less than the largest possible WQE, for otherwise the WQE would certainly fit. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index ddfe19adb3d9..7da22b413a48 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -6,7 +6,7 @@ #include "en.h" -#define MLX5E_SQ_NOPS_ROOM MLX5_SEND_WQE_MAX_WQEBBS +#define MLX5E_SQ_NOPS_ROOM (MLX5_SEND_WQE_MAX_WQEBBS - 1) #define MLX5E_SQ_STOP_ROOM (MLX5_SEND_WQE_MAX_WQEBBS +\ MLX5E_SQ_NOPS_ROOM) -- GitLab From 6c085a8aab5183d8658c9a692bcfda3e24195b7a Mon Sep 17 00:00:00 2001 From: Shay Agroskin Date: Sun, 12 May 2019 18:28:27 +0300 Subject: [PATCH 1584/7155] net/mlx5e: XDP, Close TX MPWQE session when no room for inline packet left In MPWQE mode, when transmitting packets with XDP, a packet that is smaller than a certain size (set to 256 bytes) would be sent inline within its WQE TX descriptor (mem-copied), in case the hardware tx queue is congested beyond a pre-defined water-mark. If a MPWQE cannot contain an additional inline packet, we close this MPWQE session, and send the packet inlined within the next MPWQE. To save some MPWQE session close+open operations, we don't open MPWQE sessions that are contiguously smaller than certain size (set to the HW MPWQE maximum size). If there isn't enough contiguous room in the send queue, we fill it with NOPs and wrap the send queue index around. This way, qualified packets are always sent inline. Perf tests: Tested packet rate for UDP 64Byte multi-stream over two dual port ConnectX-5 100Gbps NICs. CPU: Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz XDP_TX: With 24 channels: | ------ | bounced packets | inlined packets | inline ratio | | before | 113.6Mpps | 96.3Mpps | 84% | | after | 115Mpps | 99.5Mpps | 86% | With one channel: | ------ | bounced packets | inlined packets | inline ratio | | before | 6.7Mpps | 0pps | 0% | | after | 6.8Mpps | 0pps | 0% | As we can see, there is improvement in both inline ratio and overall packet rate for 24 channels. Also, we see no degradation for the one-channel case. Signed-off-by: Shay Agroskin Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 - .../net/ethernet/mellanox/mlx5/core/en/xdp.c | 32 ++++------- .../net/ethernet/mellanox/mlx5/core/en/xdp.h | 53 +++++++++++++++---- .../ethernet/mellanox/mlx5/core/en_stats.c | 6 +++ .../ethernet/mellanox/mlx5/core/en_stats.h | 3 ++ 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 79d93d6c7d7a..745bcc25c6f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -483,8 +483,6 @@ struct mlx5e_xdp_mpwqe { struct mlx5e_tx_wqe *wqe; u8 ds_count; u8 pkt_count; - u8 max_ds_count; - u8 complete; u8 inline_on; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index b0b982cf69bb..8cb98326531f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -179,34 +179,22 @@ static void mlx5e_xdp_mpwqe_session_start(struct mlx5e_xdpsq *sq) struct mlx5e_xdp_mpwqe *session = &sq->mpwqe; struct mlx5e_xdpsq_stats *stats = sq->stats; struct mlx5_wq_cyc *wq = &sq->wq; - u8 wqebbs; - u16 pi; + u16 pi, contig_wqebbs; + + pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); + contig_wqebbs = mlx5_wq_cyc_get_contig_wqebbs(wq, pi); + + if (unlikely(contig_wqebbs < MLX5_SEND_WQE_MAX_WQEBBS)) + mlx5e_fill_xdpsq_frag_edge(sq, wq, pi, contig_wqebbs); mlx5e_xdpsq_fetch_wqe(sq, &session->wqe); prefetchw(session->wqe->data); session->ds_count = MLX5E_XDP_TX_EMPTY_DS_COUNT; session->pkt_count = 0; - session->complete = 0; pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); -/* The mult of MLX5_SEND_WQE_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS - * (16 * 4 == 64) does not fit in the 6-bit DS field of Ctrl Segment. - * We use a bound lower that MLX5_SEND_WQE_MAX_WQEBBS to let a - * full-session WQE be cache-aligned. - */ -#if L1_CACHE_BYTES < 128 -#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 1) -#else -#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 2) -#endif - - wqebbs = min_t(u16, mlx5_wq_cyc_get_contig_wqebbs(wq, pi), - MLX5E_XDP_MPW_MAX_WQEBBS); - - session->max_ds_count = MLX5_SEND_WQEBB_NUM_DS * wqebbs; - mlx5e_xdp_update_inline_state(sq); stats->mpwqe++; @@ -244,7 +232,7 @@ static int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq) { if (unlikely(!sq->mpwqe.wqe)) { if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, - MLX5_SEND_WQE_MAX_WQEBBS))) { + MLX5E_XDPSQ_STOP_ROOM))) { /* SQ is full, ring doorbell */ mlx5e_xmit_xdp_doorbell(sq); sq->stats->full++; @@ -285,8 +273,8 @@ static bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, mlx5e_xdp_mpwqe_add_dseg(sq, xdptxd, stats); - if (unlikely(session->complete || - session->ds_count == session->max_ds_count)) + if (unlikely(mlx5e_xdp_no_room_for_inline_pkt(session) || + session->ds_count == MLX5E_XDP_MPW_MAX_NUM_DS)) mlx5e_xdp_mpwqe_complete(sq); mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, xdpi); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h index b90923932668..e0ed7710f5f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h @@ -40,6 +40,26 @@ (sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) #define MLX5E_XDP_TX_DS_COUNT (MLX5E_XDP_TX_EMPTY_DS_COUNT + 1 /* SG DS */) +#define MLX5E_XDPSQ_STOP_ROOM (MLX5E_SQ_STOP_ROOM) + +#define MLX5E_XDP_INLINE_WQE_SZ_THRSD (256 - sizeof(struct mlx5_wqe_inline_seg)) +#define MLX5E_XDP_INLINE_WQE_MAX_DS_CNT \ + DIV_ROUND_UP(MLX5E_XDP_INLINE_WQE_SZ_THRSD, MLX5_SEND_WQE_DS) + +/* The mult of MLX5_SEND_WQE_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS + * (16 * 4 == 64) does not fit in the 6-bit DS field of Ctrl Segment. + * We use a bound lower that MLX5_SEND_WQE_MAX_WQEBBS to let a + * full-session WQE be cache-aligned. + */ +#if L1_CACHE_BYTES < 128 +#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 1) +#else +#define MLX5E_XDP_MPW_MAX_WQEBBS (MLX5_SEND_WQE_MAX_WQEBBS - 2) +#endif + +#define MLX5E_XDP_MPW_MAX_NUM_DS \ + (MLX5E_XDP_MPW_MAX_WQEBBS * MLX5_SEND_WQEBB_NUM_DS) + struct mlx5e_xsk_param; int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk); bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di, @@ -114,6 +134,30 @@ static inline void mlx5e_xdp_update_inline_state(struct mlx5e_xdpsq *sq) session->inline_on = 1; } +static inline bool +mlx5e_xdp_no_room_for_inline_pkt(struct mlx5e_xdp_mpwqe *session) +{ + return session->inline_on && + session->ds_count + MLX5E_XDP_INLINE_WQE_MAX_DS_CNT > MLX5E_XDP_MPW_MAX_NUM_DS; +} + +static inline void +mlx5e_fill_xdpsq_frag_edge(struct mlx5e_xdpsq *sq, struct mlx5_wq_cyc *wq, + u16 pi, u16 nnops) +{ + struct mlx5e_xdp_wqe_info *edge_wi, *wi = &sq->db.wqe_info[pi]; + + edge_wi = wi + nnops; + /* fill sq frag edge with nops to avoid wqe wrapping two pages */ + for (; wi < edge_wi; wi++) { + wi->num_wqebbs = 1; + wi->num_pkts = 0; + mlx5e_post_nop(wq, sq->sqn, &sq->pc); + } + + sq->stats->nops += nnops; +} + static inline void mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq, struct mlx5e_xdp_xmit_data *xdptxd, @@ -126,20 +170,12 @@ mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq, session->pkt_count++; -#define MLX5E_XDP_INLINE_WQE_SZ_THRSD (256 - sizeof(struct mlx5_wqe_inline_seg)) - if (session->inline_on && dma_len <= MLX5E_XDP_INLINE_WQE_SZ_THRSD) { struct mlx5_wqe_inline_seg *inline_dseg = (struct mlx5_wqe_inline_seg *)dseg; u16 ds_len = sizeof(*inline_dseg) + dma_len; u16 ds_cnt = DIV_ROUND_UP(ds_len, MLX5_SEND_WQE_DS); - if (unlikely(session->ds_count + ds_cnt > session->max_ds_count)) { - /* Not enough space for inline wqe, send with memory pointer */ - session->complete = true; - goto no_inline; - } - inline_dseg->byte_count = cpu_to_be32(dma_len | MLX5_INLINE_SEG); memcpy(inline_dseg->data, xdptxd->data, dma_len); @@ -148,7 +184,6 @@ mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq, return; } -no_inline: dseg->addr = cpu_to_be64(xdptxd->dma_addr); dseg->byte_count = cpu_to_be32(dma_len); dseg->lkey = sq->mkey_be; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 539b4d3656da..6eee3c7d4b06 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -74,6 +74,7 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_xmit) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_mpwqe) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_inlnw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_nops) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_full) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_err) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_cqe) }, @@ -90,6 +91,7 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_xmit) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_mpwqe) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_inlnw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_nops) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_full) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_err) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xdp_cqes) }, @@ -200,6 +202,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) s->rx_xdp_tx_xmit += xdpsq_stats->xmit; s->rx_xdp_tx_mpwqe += xdpsq_stats->mpwqe; s->rx_xdp_tx_inlnw += xdpsq_stats->inlnw; + s->rx_xdp_tx_nops += xdpsq_stats->nops; s->rx_xdp_tx_full += xdpsq_stats->full; s->rx_xdp_tx_err += xdpsq_stats->err; s->rx_xdp_tx_cqe += xdpsq_stats->cqes; @@ -227,6 +230,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) s->tx_xdp_xmit += xdpsq_red_stats->xmit; s->tx_xdp_mpwqe += xdpsq_red_stats->mpwqe; s->tx_xdp_inlnw += xdpsq_red_stats->inlnw; + s->tx_xdp_nops += xdpsq_red_stats->nops; s->tx_xdp_full += xdpsq_red_stats->full; s->tx_xdp_err += xdpsq_red_stats->err; s->tx_xdp_cqes += xdpsq_red_stats->cqes; @@ -1331,6 +1335,7 @@ static const struct counter_desc rq_xdpsq_stats_desc[] = { { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, xmit) }, { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, mpwqe) }, { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, inlnw) }, + { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, nops) }, { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, full) }, { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, err) }, { MLX5E_DECLARE_RQ_XDPSQ_STAT(struct mlx5e_xdpsq_stats, cqes) }, @@ -1340,6 +1345,7 @@ static const struct counter_desc xdpsq_stats_desc[] = { { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, xmit) }, { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, mpwqe) }, { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, inlnw) }, + { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, nops) }, { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, full) }, { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, err) }, { MLX5E_DECLARE_XDPSQ_STAT(struct mlx5e_xdpsq_stats, cqes) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 76ac111e14d0..bf645d42c833 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -81,6 +81,7 @@ struct mlx5e_sw_stats { u64 rx_xdp_tx_xmit; u64 rx_xdp_tx_mpwqe; u64 rx_xdp_tx_inlnw; + u64 rx_xdp_tx_nops; u64 rx_xdp_tx_full; u64 rx_xdp_tx_err; u64 rx_xdp_tx_cqe; @@ -97,6 +98,7 @@ struct mlx5e_sw_stats { u64 tx_xdp_xmit; u64 tx_xdp_mpwqe; u64 tx_xdp_inlnw; + u64 tx_xdp_nops; u64 tx_xdp_full; u64 tx_xdp_err; u64 tx_xdp_cqes; @@ -288,6 +290,7 @@ struct mlx5e_xdpsq_stats { u64 xmit; u64 mpwqe; u64 inlnw; + u64 nops; u64 full; u64 err; /* dirtied @completion */ -- GitLab From 7cf6f811b72aced0c48e1065fe059d604ef6363d Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Sun, 14 Jul 2019 17:50:51 +0300 Subject: [PATCH 1585/7155] net/mlx5e: XDP, Slight enhancement for WQE fetch function Instead of passing an output param, let function return the WQE pointer. In addition, pass &pi so it gets its value in the function, and save the redundant assignment that comes after it. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 4 +--- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 13 ++++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 8cb98326531f..1ed5c33e022f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -187,14 +187,12 @@ static void mlx5e_xdp_mpwqe_session_start(struct mlx5e_xdpsq *sq) if (unlikely(contig_wqebbs < MLX5_SEND_WQE_MAX_WQEBBS)) mlx5e_fill_xdpsq_frag_edge(sq, wq, pi, contig_wqebbs); - mlx5e_xdpsq_fetch_wqe(sq, &session->wqe); + session->wqe = mlx5e_xdpsq_fetch_wqe(sq, &pi); prefetchw(session->wqe->data); session->ds_count = MLX5E_XDP_TX_EMPTY_DS_COUNT; session->pkt_count = 0; - pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); - mlx5e_xdp_update_inline_state(sq); stats->mpwqe++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h index e0ed7710f5f1..36ac1e3816b9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h @@ -190,14 +190,17 @@ mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq, session->ds_count++; } -static inline void mlx5e_xdpsq_fetch_wqe(struct mlx5e_xdpsq *sq, - struct mlx5e_tx_wqe **wqe) +static inline struct mlx5e_tx_wqe * +mlx5e_xdpsq_fetch_wqe(struct mlx5e_xdpsq *sq, u16 *pi) { struct mlx5_wq_cyc *wq = &sq->wq; - u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); + struct mlx5e_tx_wqe *wqe; - *wqe = mlx5_wq_cyc_get_wqe(wq, pi); - memset(*wqe, 0, sizeof(**wqe)); + *pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); + wqe = mlx5_wq_cyc_get_wqe(wq, *pi); + memset(wqe, 0, sizeof(*wqe)); + + return wqe; } static inline void -- GitLab From b431302e92f00b7acd5617a4d289f8006394bfc2 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Mon, 1 Jul 2019 12:08:08 +0300 Subject: [PATCH 1586/7155] net/mlx5e: Tx, Soften inline mode VLAN dependencies If capable, use zero inline mode in TX WQE for non-VLAN packets. For VLAN ones, keep the enforcement of at least L2 inline mode, unless the WQE VLAN insertion offload cap is on. Performance: Tested single core packet rate of 64Bytes. NIC: ConnectX-5 CPU: Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz pktgen: Before: 12.46 Mpps After: 14.65 Mpps (+17.5%) XDP_TX: The MPWQE flow is not affected, as it already has this optimization. So we test with priv-flag xdp_tx_mpwqe: off. Before: 9.90 Mpps After: 10.20 Mpps (+3%) Signed-off-by: Tariq Toukan Tested-by: Noam Stolero Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +- .../net/ethernet/mellanox/mlx5/core/en/txrx.h | 22 +++++++++++++++++-- .../ethernet/mellanox/mlx5/core/en_common.c | 12 ---------- .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 4 +++- .../net/ethernet/mellanox/mlx5/core/en_tx.c | 7 +++--- .../net/ethernet/mellanox/mlx5/core/vport.c | 7 +++--- 7 files changed, 33 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 745bcc25c6f8..30f13f81c965 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -359,6 +359,7 @@ enum { MLX5E_SQ_STATE_IPSEC, MLX5E_SQ_STATE_AM, MLX5E_SQ_STATE_TLS, + MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, }; struct mlx5e_sq_wqe_info { @@ -1132,7 +1133,6 @@ void mlx5e_build_rq_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params); void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params, u16 num_channels); -u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev); void mlx5e_rx_dim_work(struct work_struct *work); void mlx5e_tx_dim_work(struct work_struct *work); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 7da22b413a48..87be96747902 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -117,9 +117,27 @@ mlx5e_notify_hw(struct mlx5_wq_cyc *wq, u16 pc, void __iomem *uar_map, mlx5_write64((__be32 *)ctrl, uar_map); } -static inline bool mlx5e_transport_inline_tx_wqe(struct mlx5e_tx_wqe *wqe) +static inline bool mlx5e_transport_inline_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg) { - return !!wqe->ctrl.tisn; + return cseg && !!cseg->tisn; +} + +static inline u8 +mlx5e_tx_wqe_inline_mode(struct mlx5e_txqsq *sq, struct mlx5_wqe_ctrl_seg *cseg, + struct sk_buff *skb) +{ + u8 mode; + + if (mlx5e_transport_inline_tx_wqe(cseg)) + return MLX5_INLINE_MODE_TCP_UDP; + + mode = sq->min_inline_mode; + + if (skb_vlan_tag_present(skb) && + test_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state)) + mode = max_t(u8, MLX5_INLINE_MODE_L2, mode); + + return mode; } static inline void mlx5e_cq_arm(struct mlx5e_cq *cq) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c index 1539cf3de5dc..f7890e0ce96c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c @@ -180,15 +180,3 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb) return err; } - -u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev) -{ - u8 min_inline_mode; - - mlx5_query_min_inline(mdev, &min_inline_mode); - if (min_inline_mode == MLX5_INLINE_MODE_NONE && - !MLX5_CAP_ETH(mdev, wqe_vlan_insert)) - min_inline_mode = MLX5_INLINE_MODE_L2; - - return min_inline_mode; -} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 8dd31b5c740c..01f2918063af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -1101,7 +1101,7 @@ void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv) static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv, struct mlx5e_params *params) { - params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev); + mlx5_query_min_inline(priv->mdev, ¶ms->tx_min_inline_mode); if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP && params->tx_min_inline_mode == MLX5_INLINE_MODE_L2) params->tx_min_inline_mode = MLX5_INLINE_MODE_IP; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index b2618dd6dd10..e75cb18c2256 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1131,6 +1131,8 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; sq->stop_room = MLX5E_SQ_STOP_ROOM; INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); + if (!MLX5_CAP_ETH(mdev, wqe_vlan_insert)) + set_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state); if (MLX5_IPSEC_DEV(c->priv->mdev)) set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state); if (mlx5_accel_is_tls_device(c->priv->mdev)) { @@ -4777,7 +4779,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev, mlx5e_set_tx_cq_mode_params(params, MLX5_CQ_PERIOD_MODE_START_FROM_EQE); /* TX inline */ - params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(mdev); + mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode); /* RSS */ mlx5e_build_rss_params(rss_params, params->num_channels); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index acf25cc38fa1..d3a67a9b4eba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -292,8 +292,7 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs; stats->packets += skb_shinfo(skb)->gso_segs; } else { - u8 mode = mlx5e_transport_inline_tx_wqe(wqe) ? - MLX5_INLINE_MODE_TCP_UDP : sq->min_inline_mode; + u8 mode = mlx5e_tx_wqe_inline_mode(sq, &wqe->ctrl, skb); opcode = MLX5_OPCODE_SEND; mss = 0; @@ -608,9 +607,11 @@ netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs; stats->packets += skb_shinfo(skb)->gso_segs; } else { + u8 mode = mlx5e_tx_wqe_inline_mode(sq, NULL, skb); + opcode = MLX5_OPCODE_SEND; mss = 0; - ihs = mlx5e_calc_min_inline(sq->min_inline_mode, skb); + ihs = mlx5e_calc_min_inline(mode, skb); num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN); stats->packets++; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index c912d82ca64b..30f7848a6f88 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -122,12 +122,13 @@ void mlx5_query_min_inline(struct mlx5_core_dev *mdev, u8 *min_inline_mode) { switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) { + case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: + if (!mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode)) + break; + /* fall through */ case MLX5_CAP_INLINE_MODE_L2: *min_inline_mode = MLX5_INLINE_MODE_L2; break; - case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: - mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode); - break; case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: *min_inline_mode = MLX5_INLINE_MODE_NONE; break; -- GitLab From 8c7698d5caa7852bebae0cf7402b7d3a1f30423b Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 3 May 2019 15:12:46 -0700 Subject: [PATCH 1587/7155] net/mlx5e: Rx, checksum handling refactoring Move vlan checksum fixup flow into mlx5e_skb_padding_csum(), which is supposed to fixup SKB checksum if needed. And rename mlx5e_skb_padding_csum() to mlx5e_skb_csum_fixup(). Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rx.c | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index ac6e586d403d..60570b442fff 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -859,13 +859,24 @@ tail_padding_csum(struct sk_buff *skb, int offset, } static void -mlx5e_skb_padding_csum(struct sk_buff *skb, int network_depth, __be16 proto, - struct mlx5e_rq_stats *stats) +mlx5e_skb_csum_fixup(struct sk_buff *skb, int network_depth, __be16 proto, + struct mlx5e_rq_stats *stats) { struct ipv6hdr *ip6; struct iphdr *ip4; int pkt_len; + /* Fixup vlan headers, if any */ + if (network_depth > ETH_HLEN) + /* CQE csum is calculated from the IP header and does + * not cover VLAN headers (if present). This will add + * the checksum manually. + */ + skb->csum = csum_partial(skb->data + ETH_HLEN, + network_depth - ETH_HLEN, + skb->csum); + + /* Fixup tail padding, if any */ switch (proto) { case htons(ETH_P_IP): ip4 = (struct iphdr *)(skb->data + network_depth); @@ -931,16 +942,7 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, return; /* CQE csum covers all received bytes */ /* csum might need some fixups ...*/ - if (network_depth > ETH_HLEN) - /* CQE csum is calculated from the IP header and does - * not cover VLAN headers (if present). This will add - * the checksum manually. - */ - skb->csum = csum_partial(skb->data + ETH_HLEN, - network_depth - ETH_HLEN, - skb->csum); - - mlx5e_skb_padding_csum(skb, network_depth, proto, stats); + mlx5e_skb_csum_fixup(skb, network_depth, proto, stats); return; } -- GitLab From 7f7cc235c2dfc2a9208a743492b80d6cdfee50a6 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Wed, 3 Jul 2019 09:16:52 +0300 Subject: [PATCH 1588/7155] net/mlx5e: Fix mlx5e_tx_reporter_create return value Return error when failing to create a reporter in devlink. Since NET_DEVLINK mandatory to MLX5_CORE in Kconfig, returned pointer can't be NULL and can only hold an error in bad path. Signed-off-by: Aya Levin Reviewed-by: Tariq Toukan Acked-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index f3d98748b211..383ecfd85d8a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -296,11 +296,13 @@ int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, MLX5_REPORTER_TX_GRACEFUL_PERIOD, true, priv); - if (IS_ERR(priv->tx_reporter)) + if (IS_ERR(priv->tx_reporter)) { netdev_warn(priv->netdev, "Failed to create tx reporter, err = %ld\n", PTR_ERR(priv->tx_reporter)); - return IS_ERR_OR_NULL(priv->tx_reporter); + return PTR_ERR(priv->tx_reporter); + } + return 0; } void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) -- GitLab From baf6dfdb10e9695637d72429159fd26fc36d30c3 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Mon, 24 Jun 2019 19:34:42 +0300 Subject: [PATCH 1589/7155] net/mlx5e: Set tx reporter only on successful creation When failing to create tx reporter, don't set the reporter's pointer. Creating a reporter is not mandatory for driver load, avoid garbage/error pointer. Signed-off-by: Aya Levin Reviewed-by: Tariq Toukan Acked-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 14 ++++++++------ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 383ecfd85d8a..f1c652f75718 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -117,7 +117,7 @@ static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter, char *err_str, struct mlx5e_tx_err_ctx *err_ctx) { - if (IS_ERR_OR_NULL(tx_reporter)) { + if (!tx_reporter) { netdev_err(err_ctx->sq->channel->netdev, err_str); return err_ctx->recover(err_ctx->sq); } @@ -289,25 +289,27 @@ static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) { + struct devlink_health_reporter *reporter; struct mlx5_core_dev *mdev = priv->mdev; struct devlink *devlink = priv_to_devlink(mdev); - priv->tx_reporter = + reporter = devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, MLX5_REPORTER_TX_GRACEFUL_PERIOD, true, priv); - if (IS_ERR(priv->tx_reporter)) { + if (IS_ERR(reporter)) { netdev_warn(priv->netdev, "Failed to create tx reporter, err = %ld\n", - PTR_ERR(priv->tx_reporter)); - return PTR_ERR(priv->tx_reporter); + PTR_ERR(reporter)); + return PTR_ERR(reporter); } + priv->tx_reporter = reporter; return 0; } void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) { - if (IS_ERR_OR_NULL(priv->tx_reporter)) + if (!priv->tx_reporter) return; devlink_health_reporter_destroy(priv->tx_reporter); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index e75cb18c2256..4db595a7eb03 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2325,7 +2325,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv, goto err_close_channels; } - if (!IS_ERR_OR_NULL(priv->tx_reporter)) + if (priv->tx_reporter) devlink_health_reporter_state_update(priv->tx_reporter, DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); -- GitLab From c9e6c7209a9a26a0281b311c6880b9e2382ad635 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Mon, 24 Jun 2019 20:33:52 +0300 Subject: [PATCH 1590/7155] net/mlx5e: TX reporter cleanup Remove redundant include files. Signed-off-by: Aya Levin Reviewed-by: Tariq Toukan Acked-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h | 1 - drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h index e78e92753d73..ed7a3881d2c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h @@ -4,7 +4,6 @@ #ifndef __MLX5E_EN_REPORTER_H #define __MLX5E_EN_REPORTER_H -#include #include "en.h" int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index f1c652f75718..6e54fefea410 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2019 Mellanox Technologies. */ -#include #include "reporter.h" #include "lib/eq.h" -- GitLab From 6830b468259b45e3b73070474b8cec9388aa8c11 Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Thu, 1 Aug 2019 16:40:59 +0800 Subject: [PATCH 1591/7155] net/mlx5e: Allow dropping specific tunnel packets In some case, we don't want to allow specific tunnel packets to host that can avoid to take up high CPU (e.g network attacks). But other tunnel packets which not matched in hardware will be sent to host too. $ tc filter add dev vxlan_sys_4789 \ protocol ip chain 0 parent ffff: prio 1 handle 1 \ flower dst_ip 1.1.1.100 ip_proto tcp dst_port 80 \ enc_dst_ip 2.2.2.100 enc_key_id 100 enc_dst_port 4789 \ action tunnel_key unset pipe action drop Signed-off-by: Tonghao Zhang Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index dc5fc3350b65..c5d75e2ecf54 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2485,7 +2485,8 @@ static bool actions_match_supported(struct mlx5e_priv *priv, if (flow_flag_test(flow, EGRESS) && !((actions & MLX5_FLOW_CONTEXT_ACTION_DECAP) || - (actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP))) + (actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) || + (actions & MLX5_FLOW_CONTEXT_ACTION_DROP))) return false; if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) -- GitLab From 3695eae5fee0605f316fbaad0b9e3de791d7dfaf Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 28 Jul 2019 00:22:29 +0200 Subject: [PATCH 1592/7155] pidfd: add P_PIDFD to waitid() This adds the P_PIDFD type to waitid(). One of the last remaining bits for the pidfd api is to make it possible to wait on pidfds. With P_PIDFD added to waitid() the parts of userspace that want to use the pidfd api to exclusively manage processes can do so now. One of the things this will unblock in the future is the ability to make it possible to retrieve the exit status via waitid(P_PIDFD) for non-parent processes if handed a _suitable_ pidfd that has this feature set. This is similar to what you can do on FreeBSD with kqueue(). It might even end up being possible to wait on a process as a non-parent if an appropriate property is enabled on the pidfd. With P_PIDFD no scoping of the process identified by the pidfd is possible, i.e. it explicitly blocks things such as wait4(-1), wait4(0), waitid(P_ALL), waitid(P_PGID) etc. It only allows for semantics equivalent to wait4(pid), waitid(P_PID). Users that need scoping should rely on pid-based wait*() syscalls for now. Signed-off-by: Christian Brauner Reviewed-by: Kees Cook Reviewed-by: Oleg Nesterov Cc: Arnd Bergmann Cc: "Eric W. Biederman" Cc: Joel Fernandes (Google) Cc: Thomas Gleixner Cc: David Howells Cc: Jann Horn Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Aleksa Sarai Cc: Linus Torvalds Cc: Al Viro Link: https://lore.kernel.org/r/20190727222229.6516-2-christian@brauner.io --- include/linux/pid.h | 4 ++++ include/uapi/linux/wait.h | 1 + kernel/exit.c | 33 ++++++++++++++++++++++++++++++--- kernel/fork.c | 8 ++++++++ kernel/signal.c | 7 +++++-- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/linux/pid.h b/include/linux/pid.h index 2a83e434db9d..9645b1194c98 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -72,6 +72,10 @@ extern struct pid init_struct_pid; extern const struct file_operations pidfd_fops; +struct file; + +extern struct pid *pidfd_pid(const struct file *file); + static inline struct pid *get_pid(struct pid *pid) { if (pid) diff --git a/include/uapi/linux/wait.h b/include/uapi/linux/wait.h index ac49a220cf2a..85b809fc9f11 100644 --- a/include/uapi/linux/wait.h +++ b/include/uapi/linux/wait.h @@ -17,6 +17,7 @@ #define P_ALL 0 #define P_PID 1 #define P_PGID 2 +#define P_PIDFD 3 #endif /* _UAPI_LINUX_WAIT_H */ diff --git a/kernel/exit.c b/kernel/exit.c index a75b6a7f458a..64bb6893a37d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1552,6 +1552,23 @@ static long do_wait(struct wait_opts *wo) return retval; } +static struct pid *pidfd_get_pid(unsigned int fd) +{ + struct fd f; + struct pid *pid; + + f = fdget(fd); + if (!f.file) + return ERR_PTR(-EBADF); + + pid = pidfd_pid(f.file); + if (!IS_ERR(pid)) + get_pid(pid); + + fdput(f); + return pid; +} + static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop, int options, struct rusage *ru) { @@ -1574,19 +1591,29 @@ static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop, type = PIDTYPE_PID; if (upid <= 0) return -EINVAL; + + pid = find_get_pid(upid); break; case P_PGID: type = PIDTYPE_PGID; if (upid <= 0) return -EINVAL; + + pid = find_get_pid(upid); + break; + case P_PIDFD: + type = PIDTYPE_PID; + if (upid < 0) + return -EINVAL; + + pid = pidfd_get_pid(upid); + if (IS_ERR(pid)) + return PTR_ERR(pid); break; default: return -EINVAL; } - if (type < PIDTYPE_MAX) - pid = find_get_pid(upid); - wo.wo_type = type; wo.wo_pid = pid; wo.wo_flags = options; diff --git a/kernel/fork.c b/kernel/fork.c index d8ae0f1b4148..b169e2ca2d84 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1690,6 +1690,14 @@ static inline void rcu_copy_process(struct task_struct *p) #endif /* #ifdef CONFIG_TASKS_RCU */ } +struct pid *pidfd_pid(const struct file *file) +{ + if (file->f_op == &pidfd_fops) + return file->private_data; + + return ERR_PTR(-EBADF); +} + static int pidfd_release(struct inode *inode, struct file *file) { struct pid *pid = file->private_data; diff --git a/kernel/signal.c b/kernel/signal.c index 91b789dd6e72..2e567f64812f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3672,8 +3672,11 @@ static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo, siginfo_t *info) static struct pid *pidfd_to_pid(const struct file *file) { - if (file->f_op == &pidfd_fops) - return file->private_data; + struct pid *pid; + + pid = pidfd_pid(file); + if (!IS_ERR(pid)) + return pid; return tgid_pidfd_to_pid(file); } -- GitLab From 7095a4c497adb5aca30141f43c7ba00ce18bea74 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 1 Aug 2019 14:36:33 -0400 Subject: [PATCH 1593/7155] net: dsa: mv88e6xxx: lock mutex in vlan_prepare Lock the mutex in the mv88e6xxx_port_vlan_prepare function called by the DSA stack, instead of doing it in the internal mv88e6xxx_port_check_hw_vlan helper. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 2e500428670c..1b2cb46d3b53 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1453,12 +1453,10 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, if (!vid_begin) return -EOPNOTSUPP; - mv88e6xxx_reg_lock(chip); - do { err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) - goto unlock; + return err; if (!vlan.valid) break; @@ -1487,15 +1485,11 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n", port, vlan.vid, i, netdev_name(dsa_to_port(ds, i)->bridge_dev)); - err = -EOPNOTSUPP; - goto unlock; + return -EOPNOTSUPP; } } while (vlan.vid < vid_end); -unlock: - mv88e6xxx_reg_unlock(chip); - - return err; + return 0; } static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, @@ -1529,15 +1523,15 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, /* If the requested port doesn't belong to the same bridge as the VLAN * members, do not support it (yet) and fallback to software VLAN. */ + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin, vlan->vid_end); - if (err) - return err; + mv88e6xxx_reg_unlock(chip); /* We don't need any dynamic resource from the kernel (yet), * so skip the prepare phase. */ - return 0; + return err; } static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, -- GitLab From 425d2d37aba6710c6fe3ad9f8c6755c49986f3e5 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 1 Aug 2019 14:36:34 -0400 Subject: [PATCH 1594/7155] net: dsa: mv88e6xxx: explicit entry passed to vtu_getnext mv88e6xxx_vtu_getnext interprets two members from the input mv88e6xxx_vtu_entry structure: the (excluded) vid member to start the iteration from, and the valid argument specifying whether the VID must be written or not (only required once at the start of a loop). Explicit the assignation of these two fields right before calling mv88e6xxx_vtu_getnext, as it is done in the mv88e6xxx_vtu_get wrapper. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 1b2cb46d3b53..c825fa3477fa 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1361,9 +1361,7 @@ static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip, static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid) { DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); - struct mv88e6xxx_vtu_entry vlan = { - .vid = chip->info->max_vid, - }; + struct mv88e6xxx_vtu_entry vlan; int i, err; bitmap_zero(fid_bitmap, MV88E6XXX_N_FID); @@ -1378,6 +1376,9 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid) } /* Set every FID bit used by the VLAN entries */ + vlan.vid = chip->info->max_vid; + vlan.valid = false; + do { err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) @@ -1441,9 +1442,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, u16 vid_begin, u16 vid_end) { struct mv88e6xxx_chip *chip = ds->priv; - struct mv88e6xxx_vtu_entry vlan = { - .vid = vid_begin - 1, - }; + struct mv88e6xxx_vtu_entry vlan; int i, err; /* DSA and CPU ports have to be members of multiple vlans */ @@ -1453,6 +1452,9 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, if (!vid_begin) return -EOPNOTSUPP; + vlan.vid = vid_begin - 1; + vlan.valid = false; + do { err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) @@ -1789,9 +1791,7 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, dsa_fdb_dump_cb_t *cb, void *data) { - struct mv88e6xxx_vtu_entry vlan = { - .vid = chip->info->max_vid, - }; + struct mv88e6xxx_vtu_entry vlan; u16 fid; int err; @@ -1805,6 +1805,9 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, return err; /* Dump VLANs' Filtering Information Databases */ + vlan.vid = chip->info->max_vid; + vlan.valid = false; + do { err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) -- GitLab From 5ef8d249f8743325832a99fdaf997a28cbd0f78b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 1 Aug 2019 14:36:35 -0400 Subject: [PATCH 1595/7155] net: dsa: mv88e6xxx: call vtu_getnext directly in db load/purge mv88e6xxx_vtu_getnext is simple enough to call it directly in the mv88e6xxx_port_db_load_purge function and explicit the return code expected by switchdev for software VLANs when an hardware VLAN does not exist. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c825fa3477fa..42ab57dbc790 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1540,23 +1540,36 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, const unsigned char *addr, u16 vid, u8 state) { - struct mv88e6xxx_vtu_entry vlan; struct mv88e6xxx_atu_entry entry; + struct mv88e6xxx_vtu_entry vlan; + u16 fid; int err; /* Null VLAN ID corresponds to the port private database */ - if (vid == 0) - err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid); - else - err = mv88e6xxx_vtu_get(chip, vid, &vlan, false); - if (err) - return err; + if (vid == 0) { + err = mv88e6xxx_port_get_fid(chip, port, &fid); + if (err) + return err; + } else { + vlan.vid = vid - 1; + vlan.valid = false; + + err = mv88e6xxx_vtu_getnext(chip, &vlan); + if (err) + return err; + + /* switchdev expects -EOPNOTSUPP to honor software VLANs */ + if (vlan.vid != vid || !vlan.valid) + return -EOPNOTSUPP; + + fid = vlan.fid; + } entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED; ether_addr_copy(entry.mac, addr); eth_addr_dec(entry.mac); - err = mv88e6xxx_g1_atu_getnext(chip, vlan.fid, &entry); + err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry); if (err) return err; @@ -1577,7 +1590,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, entry.state = state; } - return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, &entry); + return mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry); } static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port, -- GitLab From 5210989283c28b909e13efb61c0e298c178bb76f Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 1 Aug 2019 14:36:36 -0400 Subject: [PATCH 1596/7155] net: dsa: mv88e6xxx: call vtu_getnext directly in vlan_del Wrapping mv88e6xxx_vtu_getnext makes the code less easy to read. Explicit the call to mv88e6xxx_vtu_getnext in _mv88e6xxx_port_vlan_del and the return value expected by switchdev in case of software VLANs. At the same time, rename the helper using an old underscore convention. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 42ab57dbc790..50a6dbcc669c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1671,18 +1671,27 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, mv88e6xxx_reg_unlock(chip); } -static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip, - int port, u16 vid) +static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip, + int port, u16 vid) { struct mv88e6xxx_vtu_entry vlan; int i, err; - err = mv88e6xxx_vtu_get(chip, vid, &vlan, false); + if (!vid) + return -EOPNOTSUPP; + + vlan.vid = vid - 1; + vlan.valid = false; + + err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) return err; - /* Tell switchdev if this VLAN is handled in software */ - if (vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) + /* If the VLAN doesn't exist in hardware or the port isn't a member, + * tell switchdev that this VLAN is likely handled in software. + */ + if (vlan.vid != vid || !vlan.valid || + vlan.member[port] == MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) return -EOPNOTSUPP; vlan.member[port] = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; @@ -1721,7 +1730,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - err = _mv88e6xxx_port_vlan_del(chip, port, vid); + err = mv88e6xxx_port_vlan_leave(chip, port, vid); if (err) goto unlock; -- GitLab From b1ac6fb440d6abf77ae82667b57126c6059c7bd6 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 1 Aug 2019 14:36:37 -0400 Subject: [PATCH 1597/7155] net: dsa: mv88e6xxx: call vtu_getnext directly in vlan_add Wrapping mv88e6xxx_vtu_getnext makes the code less easy to read and _mv88e6xxx_port_vlan_add is the only function requiring the preparation of a new VLAN entry. To simplify things up, remove the mv88e6xxx_vtu_get wrapper and explicit the VLAN lookup in _mv88e6xxx_port_vlan_add. This rework also avoids programming the broadcast entries again when changing a port's membership, e.g. from tagged to untagged. At the same time, rename the helper using an old underscore convention. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 93 +++++++++++++++----------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 50a6dbcc669c..b9dd5c4461b6 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1401,43 +1401,6 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid) return mv88e6xxx_g1_atu_flush(chip, *fid, true); } -static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid, - struct mv88e6xxx_vtu_entry *entry, bool new) -{ - int err; - - if (!vid) - return -EOPNOTSUPP; - - entry->vid = vid - 1; - entry->valid = false; - - err = mv88e6xxx_vtu_getnext(chip, entry); - if (err) - return err; - - if (entry->vid == vid && entry->valid) - return 0; - - if (new) { - int i; - - /* Initialize a fresh VLAN entry */ - memset(entry, 0, sizeof(*entry)); - entry->vid = vid; - - /* Exclude all ports */ - for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) - entry->member[i] = - MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; - - return mv88e6xxx_atu_new(chip, &entry->fid); - } - - /* switchdev expects -EOPNOTSUPP to honor software VLANs */ - return -EOPNOTSUPP; -} - static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, u16 vid_begin, u16 vid_end) { @@ -1616,26 +1579,58 @@ static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid) return 0; } -static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port, +static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, u16 vid, u8 member) { + const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; struct mv88e6xxx_vtu_entry vlan; - int err; + int i, err; - err = mv88e6xxx_vtu_get(chip, vid, &vlan, true); - if (err) - return err; + if (!vid) + return -EOPNOTSUPP; - if (vlan.valid && vlan.member[port] == member) - return 0; - vlan.valid = true; - vlan.member[port] = member; + vlan.vid = vid - 1; + vlan.valid = false; - err = mv88e6xxx_vtu_loadpurge(chip, &vlan); + err = mv88e6xxx_vtu_getnext(chip, &vlan); if (err) return err; - return mv88e6xxx_broadcast_setup(chip, vid); + if (vlan.vid != vid || !vlan.valid) { + memset(&vlan, 0, sizeof(vlan)); + + err = mv88e6xxx_atu_new(chip, &vlan.fid); + if (err) + return err; + + for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) + if (i == port) + vlan.member[i] = member; + else + vlan.member[i] = non_member; + + vlan.vid = vid; + vlan.valid = true; + + err = mv88e6xxx_vtu_loadpurge(chip, &vlan); + if (err) + return err; + + err = mv88e6xxx_broadcast_setup(chip, vlan.vid); + if (err) + return err; + } else if (vlan.member[port] != member) { + vlan.member[port] = member; + + err = mv88e6xxx_vtu_loadpurge(chip, &vlan); + if (err) + return err; + } else { + dev_info(chip->dev, "p%d: already a member of VLAN %d\n", + port, vid); + } + + return 0; } static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, @@ -1660,7 +1655,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, mv88e6xxx_reg_lock(chip); for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) - if (_mv88e6xxx_port_vlan_add(chip, port, vid, member)) + if (mv88e6xxx_port_vlan_join(chip, port, vid, member)) dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, vid, untagged ? 'u' : 't'); -- GitLab From 9babe825da769cfbd7080f95e6bddbe98ce6b95d Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Mon, 29 Jul 2019 14:51:10 -0700 Subject: [PATCH 1598/7155] bpf: always allocate at least 16 bytes for setsockopt hook Since we always allocate memory, allocate just a little bit more for the BPF program in case it need to override user input with bigger value. The canonical example is TCP_CONGESTION where input string might be too small to override (nv -> bbr or cubic). 16 bytes are chosen to match the size of TCP_CA_NAME_MAX and can be extended in the future if needed. Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- kernel/bpf/cgroup.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 0a00eaca6fae..6a6a154cfa7b 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -964,7 +964,6 @@ static int sockopt_alloc_buf(struct bpf_sockopt_kern *ctx, int max_optlen) return -ENOMEM; ctx->optval_end = ctx->optval + max_optlen; - ctx->optlen = max_optlen; return 0; } @@ -984,7 +983,7 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level, .level = *level, .optname = *optname, }; - int ret; + int ret, max_optlen; /* Opportunistic check to see whether we have any BPF program * attached to the hook so we don't waste time allocating @@ -994,10 +993,18 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level, __cgroup_bpf_prog_array_is_empty(cgrp, BPF_CGROUP_SETSOCKOPT)) return 0; - ret = sockopt_alloc_buf(&ctx, *optlen); + /* Allocate a bit more than the initial user buffer for + * BPF program. The canonical use case is overriding + * TCP_CONGESTION(nv) to TCP_CONGESTION(cubic). + */ + max_optlen = max_t(int, 16, *optlen); + + ret = sockopt_alloc_buf(&ctx, max_optlen); if (ret) return ret; + ctx.optlen = *optlen; + if (copy_from_user(ctx.optval, optval, *optlen) != 0) { ret = -EFAULT; goto out; @@ -1016,7 +1023,7 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level, if (ctx.optlen == -1) { /* optlen set to -1, bypass kernel */ ret = 1; - } else if (ctx.optlen > *optlen || ctx.optlen < -1) { + } else if (ctx.optlen > max_optlen || ctx.optlen < -1) { /* optlen is out of bounds */ ret = -EFAULT; } else { @@ -1063,6 +1070,8 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, if (ret) return ret; + ctx.optlen = max_optlen; + if (!retval) { /* If kernel getsockopt finished successfully, * copy whatever was returned to the user back -- GitLab From fd5ef31f370a8b7000794cd8a428b349dbfbbb80 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Mon, 29 Jul 2019 14:51:11 -0700 Subject: [PATCH 1599/7155] selftests/bpf: extend sockopt_sk selftest with TCP_CONGESTION use case Ignore SOL_TCP:TCP_CONGESTION in getsockopt and always override SOL_TCP:TCP_CONGESTION with "cubic" in setsockopt hook. Call setsockopt(SOL_TCP, TCP_CONGESTION) with short optval ("nv") to make sure BPF program has enough buffer space to replace it with "cubic". Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- .../testing/selftests/bpf/progs/sockopt_sk.c | 22 ++++++++++++++++ tools/testing/selftests/bpf/test_sockopt_sk.c | 25 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/sockopt_sk.c b/tools/testing/selftests/bpf/progs/sockopt_sk.c index 076122c898e9..9a3d1c79e6fe 100644 --- a/tools/testing/selftests/bpf/progs/sockopt_sk.c +++ b/tools/testing/selftests/bpf/progs/sockopt_sk.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include +#include #include #include "bpf_helpers.h" @@ -42,6 +44,14 @@ int _getsockopt(struct bpf_sockopt *ctx) return 1; } + if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) { + /* Not interested in SOL_TCP:TCP_CONGESTION; + * let next BPF program in the cgroup chain or kernel + * handle it. + */ + return 1; + } + if (ctx->level != SOL_CUSTOM) return 0; /* EPERM, deny everything except custom level */ @@ -91,6 +101,18 @@ int _setsockopt(struct bpf_sockopt *ctx) return 1; } + if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) { + /* Always use cubic */ + + if (optval + 5 > optval_end) + return 0; /* EPERM, bounds check */ + + memcpy(optval, "cubic", 5); + ctx->optlen = 5; + + return 1; + } + if (ctx->level != SOL_CUSTOM) return 0; /* EPERM, deny everything except custom level */ diff --git a/tools/testing/selftests/bpf/test_sockopt_sk.c b/tools/testing/selftests/bpf/test_sockopt_sk.c index 036b652e5ca9..e4f6055d92e9 100644 --- a/tools/testing/selftests/bpf/test_sockopt_sk.c +++ b/tools/testing/selftests/bpf/test_sockopt_sk.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,7 @@ static int getsetsockopt(void) union { char u8[4]; __u32 u32; + char cc[16]; /* TCP_CA_NAME_MAX */ } buf = {}; socklen_t optlen; @@ -115,6 +117,29 @@ static int getsetsockopt(void) goto err; } + /* TCP_CONGESTION can extend the string */ + + strcpy(buf.cc, "nv"); + err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv")); + if (err) { + log_err("Failed to call setsockopt(TCP_CONGESTION)"); + goto err; + } + + + optlen = sizeof(buf.cc); + err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen); + if (err) { + log_err("Failed to call getsockopt(TCP_CONGESTION)"); + goto err; + } + + if (strcmp(buf.cc, "cubic") != 0) { + log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s", + buf.cc, "cubic"); + goto err; + } + close(fd); return 0; err: -- GitLab From 30b1b498d7568ea8db387308087d30292fb32b8b Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:18 -0700 Subject: [PATCH 1600/7155] fm10k: reduce scope of the err variable Reduce the scope of the err local variable in the fm10k_dcbnl_ieee_setets function. This was detected using cppcheck, and resolves the following style warning: [fm10k_dcbnl.c:37]: (style) The scope of the variable 'err' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c b/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c index 20768ac7f17e..c45315472245 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k.h" @@ -36,7 +36,7 @@ static int fm10k_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) static int fm10k_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) { u8 num_tc = 0; - int i, err; + int i; /* verify type and determine num_tcs needed */ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { @@ -57,7 +57,7 @@ static int fm10k_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) /* update TC hardware mapping if necessary */ if (num_tc != netdev_get_num_tc(dev)) { - err = fm10k_setup_tc(dev, num_tc); + int err = fm10k_setup_tc(dev, num_tc); if (err) return err; } -- GitLab From a5c0d861280dc7d596d875213e691a046b430597 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:19 -0700 Subject: [PATCH 1601/7155] fm10k: reduce scope of *p local variable Reduce the scope of the char *p local variable to only the block where it is used. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_ethtool.c:229]: (style) The scope of the variable 'p' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 4895dd83dd08..7b9440c0aee1 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include @@ -222,7 +222,6 @@ static void __fm10k_add_ethtool_stats(u64 **data, void *pointer, const unsigned int size) { unsigned int i; - char *p; if (!pointer) { /* memory is not zero allocated so we have to clear it */ @@ -232,7 +231,7 @@ static void __fm10k_add_ethtool_stats(u64 **data, void *pointer, } for (i = 0; i < size; i++) { - p = (char *)pointer + stats[i].stat_offset; + char *p = (char *)pointer + stats[i].stat_offset; switch (stats[i].sizeof_stat) { case sizeof(u64): -- GitLab From d143b3d1cd89f6bcab67dc88160914aa3536c663 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 22 Jun 2019 12:05:54 -0700 Subject: [PATCH 1602/7155] rcu: Simplify rcu_read_unlock_special() deferred wakeups In !use_softirq runs, we clearly cannot rely on raise_softirq() and its lightweight bit setting, so we must instead do some form of wakeup. In the absence of a self-IPI when interrupts are disabled, these wakeups can be delayed until the next interrupt occurs. This means that calling invoke_rcu_core() doesn't actually do any expediting. In this case, it is better to take the "else" clause, which sets the current CPU's resched bits and, if there is an expedited grace period in flight, uses IRQ-work to force the needed self-IPI. This commit therefore removes the "else if" clause that calls invoke_rcu_core(). Reported-by: Scott Wood Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_plugin.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index acb225023ed1..3f0701e860e4 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -631,17 +631,12 @@ static void rcu_read_unlock_special(struct task_struct *t) // Using softirq, safe to awaken, and we get // no help from enabling irqs, unlike bh/preempt. raise_softirq_irqoff(RCU_SOFTIRQ); - } else if (exp && irqs_were_disabled && !use_softirq && - !t->rcu_read_unlock_special.b.deferred_qs) { - // Safe to awaken and we get no help from enabling - // irqs, unlike bh/preempt. - invoke_rcu_core(); } else { // Enabling BH or preempt does reschedule, so... // Also if no expediting or NO_HZ_FULL, slow is OK. set_tsk_need_resched(current); set_preempt_need_resched(); - if (IS_ENABLED(CONFIG_IRQ_WORK) && + if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled && !rdp->defer_qs_iw_pending && exp) { // Get scheduler to re-evaluate and call hooks. // If !IRQ_WORK, FQS scan will eventually IPI. -- GitLab From 87446b48748b49dd34900904649a5ec95a591699 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 28 Jun 2019 11:25:26 -0700 Subject: [PATCH 1603/7155] rcu: Make rcu_read_unlock_special() checks match raise_softirq_irqoff() Threaded interrupts provide additional interesting interactions between RCU and raise_softirq() that can result in self-deadlocks in v5.0-2 of the Linux kernel. These self-deadlocks can be provoked in susceptible kernels within a few minutes using the following rcutorture command on an 8-CPU system: tools/testing/selftests/rcutorture/bin/kvm.sh --duration 5 --configs "TREE03" --bootargs "threadirqs" Although post-v5.2 RCU commits have at least greatly reduced the probability of these self-deadlocks, this was entirely by accident. Although this sort of accident should be rowdily celebrated on those rare occasions when it does occur, such celebrations should be quickly followed by a principled patch, which is what this patch purports to be. The key point behind this patch is that when in_interrupt() returns true, __raise_softirq_irqoff() will never attempt a wakeup. Therefore, if in_interrupt(), calls to raise_softirq*() are both safe and extremely cheap. This commit therefore replaces the in_irq() calls in the "if" statement in rcu_read_unlock_special() with in_interrupt() and simplifies the "if" condition to the following: if (irqs_were_disabled && use_softirq && (in_interrupt() || (exp && !t->rcu_read_unlock_special.b.deferred_qs))) { raise_softirq_irqoff(RCU_SOFTIRQ); } else { /* Appeal to the scheduler. */ } The rationale behind the "if" condition is as follows: 1. irqs_were_disabled: If interrupts are enabled, we should instead appeal to the scheduler so as to let the upcoming irq_enable()/local_bh_enable() do the rescheduling for us. 2. use_softirq: If this kernel isn't using softirq, then raise_softirq_irqoff() will be unhelpful. 3. a. in_interrupt(): If this returns true, the subsequent call to raise_softirq_irqoff() is guaranteed not to do a wakeup, so that call will be both very cheap and quite safe. b. Otherwise, if !in_interrupt() the raise_softirq_irqoff() might do a wakeup, which is expensive and, in some contexts, unsafe. i. The "exp" (an expedited RCU grace period is being blocked) says that the wakeup is worthwhile, and: ii. The !.deferred_qs says that scheduler locks cannot be held, so the wakeup will be safe. Backporting this requires considerable care, so no auto-backport, please! Fixes: 05f415715ce45 ("rcu: Speed up expedited GPs when interrupting RCU reader") Reported-by: Sebastian Andrzej Siewior Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_plugin.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 3f0701e860e4..1fd3ca4ffc1d 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -626,8 +626,9 @@ static void rcu_read_unlock_special(struct task_struct *t) (rdp->grpmask & rnp->expmask) || tick_nohz_full_cpu(rdp->cpu); // Need to defer quiescent state until everything is enabled. - if ((exp || in_irq()) && irqs_were_disabled && use_softirq && - (in_irq() || !t->rcu_read_unlock_special.b.deferred_qs)) { + if (irqs_were_disabled && use_softirq && + (in_interrupt() || + (exp && !t->rcu_read_unlock_special.b.deferred_qs))) { // Using softirq, safe to awaken, and we get // no help from enabling irqs, unlike bh/preempt. raise_softirq_irqoff(RCU_SOFTIRQ); -- GitLab From cb4dbbfaa1f5a190f041b174177699a009ab2ecd Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Mon, 1 Jul 2019 00:04:14 -0400 Subject: [PATCH 1604/7155] rcu: Simplify rcu_note_context_switch exit from critical section Because __rcu_read_unlock() can be preempted just before the call to rcu_read_unlock_special(), it is possible for a task to be preempted just before it would have fully exited its RCU read-side critical section. This would result in a needless extension of that critical section until that task was resumed, which might in turn result in a needlessly long grace period, needless RCU priority boosting, and needless force-quiescent-state actions. Therefore, rcu_note_context_switch() invokes __rcu_read_unlock() followed by rcu_preempt_deferred_qs() when it detects this situation. This action by rcu_note_context_switch() ends the RCU read-side critical section immediately. Of course, once the task resumes, it will invoke rcu_read_unlock_special() redundantly. This is harmless because the fact that a preemption happened means that interrupts, preemption, and softirqs cannot have been disabled, so there would be no deferred quiescent state. While ->rcu_read_lock_nesting remains less than zero, none of the ->rcu_read_unlock_special.b bits can be set, and they were all zeroed by the call to rcu_note_context_switch() at task-preemption time. Therefore, setting ->rcu_read_unlock_special.b.exp_hint to false has no effect. Therefore, the extra call to rcu_preempt_deferred_qs_irqrestore() would return immediately. With one possible exception, which is if an expedited grace period started just as the task was being resumed, which could leave ->exp_deferred_qs set. This will cause rcu_preempt_deferred_qs_irqrestore() to invoke rcu_report_exp_rdp(), reporting the quiescent state, just as it should. (Such an expedited grace period won't affect the preemption code path due to interrupts having already been disabled.) But when rcu_note_context_switch() invokes __rcu_read_unlock(), it is doing so with preemption disabled, hence __rcu_read_unlock() will unconditionally defer the quiescent state, only to immediately invoke rcu_preempt_deferred_qs(), thus immediately reporting the deferred quiescent state. It turns out to be safe (and faster) to instead just invoke rcu_preempt_deferred_qs() without the __rcu_read_unlock() middleman. Because this is the invocation during the preemption (as opposed to the invocation just after the resume), at least one of the bits in ->rcu_read_unlock_special.b must be set and ->rcu_read_lock_nesting must be negative. This means that rcu_preempt_need_deferred_qs() must return true, avoiding the early exit from rcu_preempt_deferred_qs(). Thus, rcu_preempt_deferred_qs_irqrestore() will be invoked immediately, as required. This commit therefore simplifies the CONFIG_PREEMPT=y version of rcu_note_context_switch() by removing the "else if" branch of its "if" statement. This change means that all callers that would have invoked rcu_read_unlock_special() followed by rcu_preempt_deferred_qs() will now simply invoke rcu_preempt_deferred_qs(), thus avoiding the rcu_read_unlock_special() middleman when __rcu_read_unlock() is preempted. Cc: rcu@vger.kernel.org Cc: kernel-team@android.com Signed-off-by: Joel Fernandes (Google) Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_plugin.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 1fd3ca4ffc1d..ce6ef345102b 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -314,15 +314,6 @@ void rcu_note_context_switch(bool preempt) ? rnp->gp_seq : rcu_seq_snap(&rnp->gp_seq)); rcu_preempt_ctxt_queue(rnp, rdp); - } else if (t->rcu_read_lock_nesting < 0 && - t->rcu_read_unlock_special.s) { - - /* - * Complete exit from RCU read-side critical section on - * behalf of preempted instance of __rcu_read_unlock(). - */ - rcu_read_unlock_special(t); - rcu_preempt_deferred_qs(t); } else { rcu_preempt_deferred_qs(t); } -- GitLab From 519248f36d6f3c80e176f6fa844c10d94f1f5990 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 30 May 2019 05:39:25 -0700 Subject: [PATCH 1605/7155] lockdep: Make print_lock() address visible Security is a wonderful thing, but so is the ability to debug based on lockdep warnings. This commit therefore makes lockdep lock addresses visible in the clear. Signed-off-by: Paul E. McKenney --- kernel/locking/lockdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 4861cf8e274b..4aca3f4379d2 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -620,7 +620,7 @@ static void print_lock(struct held_lock *hlock) return; } - printk(KERN_CONT "%p", hlock->instance); + printk(KERN_CONT "%px", hlock->instance); print_lock_name(lock); printk(KERN_CONT ", at: %pS\n", (void *)hlock->acquire_ip); } -- GitLab From b55bd585551ed2220eefdab96b31e6f935310eec Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 30 May 2019 05:39:25 -0700 Subject: [PATCH 1606/7155] time/tick-broadcast: Fix tick_broadcast_offline() lockdep complaint The TASKS03 and TREE04 rcutorture scenarios produce the following lockdep complaint: ------------------------------------------------------------------------ ================================ WARNING: inconsistent lock state 5.2.0-rc1+ #513 Not tainted -------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. migration/1/14 [HC0[0]:SC0[0]:HE1:SE1] takes: (____ptrval____) (tick_broadcast_lock){?...}, at: tick_broadcast_offline+0xf/0x70 {IN-HARDIRQ-W} state was registered at: lock_acquire+0xb0/0x1c0 _raw_spin_lock_irqsave+0x3c/0x50 tick_broadcast_switch_to_oneshot+0xd/0x40 tick_switch_to_oneshot+0x4f/0xd0 hrtimer_run_queues+0xf3/0x130 run_local_timers+0x1c/0x50 update_process_times+0x1c/0x50 tick_periodic+0x26/0xc0 tick_handle_periodic+0x1a/0x60 smp_apic_timer_interrupt+0x80/0x2a0 apic_timer_interrupt+0xf/0x20 _raw_spin_unlock_irqrestore+0x4e/0x60 rcu_nocb_gp_kthread+0x15d/0x590 kthread+0xf3/0x130 ret_from_fork+0x3a/0x50 irq event stamp: 171 hardirqs last enabled at (171): [] trace_hardirqs_on_thunk+0x1a/0x1c hardirqs last disabled at (170): [] trace_hardirqs_off_thunk+0x1a/0x1c softirqs last enabled at (0): [] copy_process.part.56+0x650/0x1cb0 softirqs last disabled at (0): [<0000000000000000>] 0x0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(tick_broadcast_lock); lock(tick_broadcast_lock); *** DEADLOCK *** 1 lock held by migration/1/14: #0: (____ptrval____) (clockevents_lock){+.+.}, at: tick_offline_cpu+0xf/0x30 stack backtrace: CPU: 1 PID: 14 Comm: migration/1 Not tainted 5.2.0-rc1+ #513 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0x5e/0x8b print_usage_bug+0x1fc/0x216 ? print_shortest_lock_dependencies+0x1b0/0x1b0 mark_lock+0x1f2/0x280 __lock_acquire+0x1e0/0x18f0 ? __lock_acquire+0x21b/0x18f0 ? _raw_spin_unlock_irqrestore+0x4e/0x60 lock_acquire+0xb0/0x1c0 ? tick_broadcast_offline+0xf/0x70 _raw_spin_lock+0x33/0x40 ? tick_broadcast_offline+0xf/0x70 tick_broadcast_offline+0xf/0x70 tick_offline_cpu+0x16/0x30 take_cpu_down+0x7d/0xa0 multi_cpu_stop+0xa2/0xe0 ? cpu_stop_queue_work+0xc0/0xc0 cpu_stopper_thread+0x6d/0x100 smpboot_thread_fn+0x169/0x240 kthread+0xf3/0x130 ? sort_range+0x20/0x20 ? kthread_cancel_delayed_work_sync+0x10/0x10 ret_from_fork+0x3a/0x50 ------------------------------------------------------------------------ To reproduce, run the following rcutorture test: tools/testing/selftests/rcutorture/bin/kvm.sh --duration 5 --kconfig "CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y" --configs "TASKS03 TREE04" It turns out that tick_broadcast_offline() was an innocent bystander. After all, interrupts are supposed to be disabled throughout take_cpu_down(), and therefore should have been disabled upon entry to tick_offline_cpu() and thus to tick_broadcast_offline(). This suggests that one of the CPU-hotplug notifiers was incorrectly enabling interrupts, and leaving them enabled on return. Some debugging code showed that the culprit was sched_cpu_dying(). It had irqs enabled after return from sched_tick_stop(). Which in turn had irqs enabled after return from cancel_delayed_work_sync(). Which is a wrapper around __cancel_work_timer(). Which can sleep in the case where something else is concurrently trying to cancel the same delayed work, and as Thomas Gleixner pointed out on IRC, sleeping is a decidedly bad idea when you are invoked from take_cpu_down(), regardless of the state you leave interrupts in upon return. Code inspection located no reason why the delayed work absolutely needed to be canceled from sched_tick_stop(): The work is not bound to the outgoing CPU by design, given that the whole point is to collect statistics without disturbing the outgoing CPU. This commit therefore simply drops the cancel_delayed_work_sync() from sched_tick_stop(). Instead, a new ->state field is added to the tick_work structure so that the delayed-work handler function sched_tick_remote() can avoid reposting itself. A cpu_is_offline() check is also added to sched_tick_remote() to avoid mucking with the state of an offlined CPU (though it does appear safe to do so). The sched_tick_start() and sched_tick_stop() functions also update ->state, and sched_tick_start() also schedules the delayed work if ->state indicates that it is not already in flight. Signed-off-by: Paul E. McKenney Cc: Ingo Molnar Cc: Peter Zijlstra Reviewed-by: Frederic Weisbecker [ paulmck: Apply Peter Zijlstra and Frederic Weisbecker atomics feedback. ] Acked-by: Peter Zijlstra (Intel) --- kernel/sched/core.c | 57 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b037f195473..0b22e55cebe8 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3486,8 +3486,36 @@ void scheduler_tick(void) struct tick_work { int cpu; + atomic_t state; struct delayed_work work; }; +/* Values for ->state, see diagram below. */ +#define TICK_SCHED_REMOTE_OFFLINE 0 +#define TICK_SCHED_REMOTE_OFFLINING 1 +#define TICK_SCHED_REMOTE_RUNNING 2 + +/* + * State diagram for ->state: + * + * + * TICK_SCHED_REMOTE_OFFLINE + * | ^ + * | | + * | | sched_tick_remote() + * | | + * | | + * +--TICK_SCHED_REMOTE_OFFLINING + * | ^ + * | | + * sched_tick_start() | | sched_tick_stop() + * | | + * V | + * TICK_SCHED_REMOTE_RUNNING + * + * + * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote() + * and sched_tick_start() are happy to leave the state in RUNNING. + */ static struct tick_work __percpu *tick_work_cpu; @@ -3500,6 +3528,7 @@ static void sched_tick_remote(struct work_struct *work) struct task_struct *curr; struct rq_flags rf; u64 delta; + int os; /* * Handle the tick only if it appears the remote CPU is running in full @@ -3513,7 +3542,7 @@ static void sched_tick_remote(struct work_struct *work) rq_lock_irq(rq, &rf); curr = rq->curr; - if (is_idle_task(curr)) + if (is_idle_task(curr) || cpu_is_offline(cpu)) goto out_unlock; update_rq_clock(rq); @@ -3533,13 +3562,18 @@ static void sched_tick_remote(struct work_struct *work) /* * Run the remote tick once per second (1Hz). This arbitrary * frequency is large enough to avoid overload but short enough - * to keep scheduler internal stats reasonably up to date. + * to keep scheduler internal stats reasonably up to date. But + * first update state to reflect hotplug activity if required. */ - queue_delayed_work(system_unbound_wq, dwork, HZ); + os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING); + WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE); + if (os == TICK_SCHED_REMOTE_RUNNING) + queue_delayed_work(system_unbound_wq, dwork, HZ); } static void sched_tick_start(int cpu) { + int os; struct tick_work *twork; if (housekeeping_cpu(cpu, HK_FLAG_TICK)) @@ -3548,15 +3582,20 @@ static void sched_tick_start(int cpu) WARN_ON_ONCE(!tick_work_cpu); twork = per_cpu_ptr(tick_work_cpu, cpu); - twork->cpu = cpu; - INIT_DELAYED_WORK(&twork->work, sched_tick_remote); - queue_delayed_work(system_unbound_wq, &twork->work, HZ); + os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING); + WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING); + if (os == TICK_SCHED_REMOTE_OFFLINE) { + twork->cpu = cpu; + INIT_DELAYED_WORK(&twork->work, sched_tick_remote); + queue_delayed_work(system_unbound_wq, &twork->work, HZ); + } } #ifdef CONFIG_HOTPLUG_CPU static void sched_tick_stop(int cpu) { struct tick_work *twork; + int os; if (housekeeping_cpu(cpu, HK_FLAG_TICK)) return; @@ -3564,7 +3603,10 @@ static void sched_tick_stop(int cpu) WARN_ON_ONCE(!tick_work_cpu); twork = per_cpu_ptr(tick_work_cpu, cpu); - cancel_delayed_work_sync(&twork->work); + /* There cannot be competing actions, but don't rely on stop-machine. */ + os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING); + WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING); + /* Don't cancel, as this would mess up the state machine. */ } #endif /* CONFIG_HOTPLUG_CPU */ @@ -3572,7 +3614,6 @@ int __init sched_tick_offload_init(void) { tick_work_cpu = alloc_percpu(struct tick_work); BUG_ON(!tick_work_cpu); - return 0; } -- GitLab From 1f3ebc8253ee56bfaa883c5114fb5569c56f6197 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 4 Jun 2019 14:05:52 -0700 Subject: [PATCH 1607/7155] rcu: Restore barrier() to rcu_read_lock() and rcu_read_unlock() Commit bb73c52bad36 ("rcu: Don't disable preemption for Tiny and Tree RCU readers") removed the barrier() calls from rcu_read_lock() and rcu_write_lock() in CONFIG_PREEMPT=n&&CONFIG_PREEMPT_COUNT=n kernels. Within RCU, this commit was OK, but it failed to account for things like get_user() that can pagefault and that can be reordered by the compiler. Lack of the barrier() calls in rcu_read_lock() and rcu_read_unlock() can cause these page faults to migrate into RCU read-side critical sections, which in CONFIG_PREEMPT=n kernels could result in too-short grace periods and arbitrary misbehavior. Please see commit 386afc91144b ("spinlocks and preemption points need to be at least compiler barriers") and Linus's commit 66be4e66a7f4 ("rcu: locking and unlocking need to always be at least barriers"), this last of which restores the barrier() call to both rcu_read_lock() and rcu_read_unlock(). This commit removes barrier() calls that are no longer needed given that the addition of them in Linus's commit noted above. The combination of this commit and Linus's commit effectively reverts commit bb73c52bad36 ("rcu: Don't disable preemption for Tiny and Tree RCU readers"). Reported-by: Herbert Xu Reported-by: Linus Torvalds Signed-off-by: Paul E. McKenney [ paulmck: Fix embarrassing typo located by Alan Stern. ] --- .../RCU/Design/Requirements/Requirements.html | 71 +++++++++++++++++++ kernel/rcu/tree_plugin.h | 11 --- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 5a9238a2883c..f04c467e55c5 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -2129,6 +2129,8 @@ Some of the relevant points of interest are as follows:
  • Hotplug CPU.
  • Scheduler and RCU.
  • Tracing and RCU. +
  • +Accesses to User Memory and RCU.
  • Energy Efficiency.
  • Scheduling-Clock Interrupts and RCU. @@ -2521,6 +2523,75 @@ cannot be used. The tracing folks both located the requirement and provided the needed fix, so this surprise requirement was relatively painless. +

    +Accesses to User Memory and RCU

    + +

    +The kernel needs to access user-space memory, for example, to access +data referenced by system-call parameters. +The get_user() macro does this job. + +

    +However, user-space memory might well be paged out, which means +that get_user() might well page-fault and thus block while +waiting for the resulting I/O to complete. +It would be a very bad thing for the compiler to reorder +a get_user() invocation into an RCU read-side critical +section. +For example, suppose that the source code looked like this: + +

    +
    + 1 rcu_read_lock();
    + 2 p = rcu_dereference(gp);
    + 3 v = p->value;
    + 4 rcu_read_unlock();
    + 5 get_user(user_v, user_p);
    + 6 do_something_with(v, user_v);
    +
    +
    + +

    +The compiler must not be permitted to transform this source code into +the following: + +

    +
    + 1 rcu_read_lock();
    + 2 p = rcu_dereference(gp);
    + 3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
    + 4 v = p->value;
    + 5 rcu_read_unlock();
    + 6 do_something_with(v, user_v);
    +
    +
    + +

    +If the compiler did make this transformation in a +CONFIG_PREEMPT=n kernel build, and if get_user() did +page fault, the result would be a quiescent state in the middle +of an RCU read-side critical section. +This misplaced quiescent state could result in line 4 being +a use-after-free access, which could be bad for your kernel's +actuarial statistics. +Similar examples can be constructed with the call to get_user() +preceding the rcu_read_lock(). + +

    +Unfortunately, get_user() doesn't have any particular +ordering properties, and in some architectures the underlying asm +isn't even marked volatile. +And even if it was marked volatile, the above access to +p->value is not volatile, so the compiler would not have any +reason to keep those two accesses in order. + +

    +Therefore, the Linux-kernel definitions of rcu_read_lock() +and rcu_read_unlock() must act as compiler barriers, +at least for outermost instances of rcu_read_lock() and +rcu_read_unlock() within a nested set of RCU read-side critical +sections. +

    Energy Efficiency

    diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index acb225023ed1..3f1b5041de9b 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -288,7 +288,6 @@ void rcu_note_context_switch(bool preempt) struct rcu_data *rdp = this_cpu_ptr(&rcu_data); struct rcu_node *rnp; - barrier(); /* Avoid RCU read-side critical sections leaking down. */ trace_rcu_utilization(TPS("Start context switch")); lockdep_assert_irqs_disabled(); WARN_ON_ONCE(!preempt && t->rcu_read_lock_nesting > 0); @@ -340,7 +339,6 @@ void rcu_note_context_switch(bool preempt) if (rdp->exp_deferred_qs) rcu_report_exp_rdp(rdp); trace_rcu_utilization(TPS("End context switch")); - barrier(); /* Avoid RCU read-side critical sections leaking up. */ } EXPORT_SYMBOL_GPL(rcu_note_context_switch); @@ -828,11 +826,6 @@ static void rcu_qs(void) * dyntick-idle quiescent state visible to other CPUs, which will in * some cases serve for expedited as well as normal grace periods. * Either way, register a lightweight quiescent state. - * - * The barrier() calls are redundant in the common case when this is - * called externally, but just in case this is called from within this - * file. - * */ void rcu_all_qs(void) { @@ -847,14 +840,12 @@ void rcu_all_qs(void) return; } this_cpu_write(rcu_data.rcu_urgent_qs, false); - barrier(); /* Avoid RCU read-side critical sections leaking down. */ if (unlikely(raw_cpu_read(rcu_data.rcu_need_heavy_qs))) { local_irq_save(flags); rcu_momentary_dyntick_idle(); local_irq_restore(flags); } rcu_qs(); - barrier(); /* Avoid RCU read-side critical sections leaking up. */ preempt_enable(); } EXPORT_SYMBOL_GPL(rcu_all_qs); @@ -864,7 +855,6 @@ EXPORT_SYMBOL_GPL(rcu_all_qs); */ void rcu_note_context_switch(bool preempt) { - barrier(); /* Avoid RCU read-side critical sections leaking down. */ trace_rcu_utilization(TPS("Start context switch")); rcu_qs(); /* Load rcu_urgent_qs before other flags. */ @@ -877,7 +867,6 @@ void rcu_note_context_switch(bool preempt) rcu_tasks_qs(current); out: trace_rcu_utilization(TPS("End context switch")); - barrier(); /* Avoid RCU read-side critical sections leaking up. */ } EXPORT_SYMBOL_GPL(rcu_note_context_switch); -- GitLab From cdc694b2359d52cd6d0465d5a6263d97c786fb0c Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 13 Jun 2019 15:30:49 -0700 Subject: [PATCH 1608/7155] rcu: Add kernel parameter to dump trace after RCU CPU stall warning This commit adds a rcu_cpu_stall_ftrace_dump kernel boot parameter, that, when set, causes the trace buffer to be dumped after an RCU CPU stall warning is printed. This kernel boot parameter is disabled by default, maintaining compatibility with previous behavior. Signed-off-by: Paul E. McKenney --- Documentation/admin-guide/kernel-parameters.txt | 4 ++++ kernel/rcu/rcu.h | 1 + kernel/rcu/tree_stall.h | 4 ++++ kernel/rcu/update.c | 2 ++ 4 files changed, 11 insertions(+) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 7ccd158b3894..f3fcd6140ee1 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4047,6 +4047,10 @@ rcutorture.verbose= [KNL] Enable additional printk() statements. + rcupdate.rcu_cpu_stall_ftrace_dump= [KNL] + Dump ftrace buffer after reporting RCU CPU + stall warning. + rcupdate.rcu_cpu_stall_suppress= [KNL] Suppress RCU CPU stall warning messages. diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index 5290b01de534..8fd4f82c9b3d 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h @@ -227,6 +227,7 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) #ifdef CONFIG_RCU_STALL_COMMON +extern int rcu_cpu_stall_ftrace_dump; extern int rcu_cpu_stall_suppress; extern int rcu_cpu_stall_timeout; int rcu_jiffies_till_stall_check(void); diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h index 065183391f75..0627a66699a6 100644 --- a/kernel/rcu/tree_stall.h +++ b/kernel/rcu/tree_stall.h @@ -527,6 +527,8 @@ static void check_cpu_stall(struct rcu_data *rdp) /* We haven't checked in, so go dump stack. */ print_cpu_stall(); + if (rcu_cpu_stall_ftrace_dump) + rcu_ftrace_dump(DUMP_ALL); } else if (rcu_gp_in_progress() && ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY) && @@ -534,6 +536,8 @@ static void check_cpu_stall(struct rcu_data *rdp) /* They had a few time units to dump stack, so complain. */ print_other_cpu_stall(gs2); + if (rcu_cpu_stall_ftrace_dump) + rcu_ftrace_dump(DUMP_ALL); } } diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 61df2bf08563..249517058b13 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -437,6 +437,8 @@ EXPORT_SYMBOL_GPL(rcutorture_sched_setaffinity); #endif #ifdef CONFIG_RCU_STALL_COMMON +int rcu_cpu_stall_ftrace_dump __read_mostly; +module_param(rcu_cpu_stall_ftrace_dump, int, 0644); int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ EXPORT_SYMBOL_GPL(rcu_cpu_stall_suppress); module_param(rcu_cpu_stall_suppress, int, 0644); -- GitLab From fbad01af8c3bb9618848abde8054ab7e0c2330fe Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 19 Jun 2019 15:42:51 -0700 Subject: [PATCH 1609/7155] rcu: Add destroy_work_on_stack() to match INIT_WORK_ONSTACK() The synchronize_rcu_expedited() function has an INIT_WORK_ONSTACK(), but lacks the corresponding destroy_work_on_stack(). This commit therefore adds destroy_work_on_stack(). Reported-by: Andrea Arcangeli Signed-off-by: Paul E. McKenney Acked-by: Andrea Arcangeli --- kernel/rcu/tree_exp.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h index af7e7b9c86af..513b403b683b 100644 --- a/kernel/rcu/tree_exp.h +++ b/kernel/rcu/tree_exp.h @@ -792,6 +792,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp) */ void synchronize_rcu_expedited(void) { + bool boottime = (rcu_scheduler_active == RCU_SCHEDULER_INIT); struct rcu_exp_work rew; struct rcu_node *rnp; unsigned long s; @@ -817,7 +818,7 @@ void synchronize_rcu_expedited(void) return; /* Someone else did our work for us. */ /* Ensure that load happens before action based on it. */ - if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) { + if (unlikely(boottime)) { /* Direct call during scheduler init and early_initcalls(). */ rcu_exp_sel_wait_wake(s); } else { @@ -835,5 +836,8 @@ void synchronize_rcu_expedited(void) /* Let the next expedited grace period start. */ mutex_unlock(&rcu_state.exp_mutex); + + if (likely(!boottime)) + destroy_work_on_stack(&rew.rew_work); } EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); -- GitLab From 7e210a653ec9445512534cd235cac29e7301af2a Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 28 Jun 2019 17:11:10 -0700 Subject: [PATCH 1610/7155] srcu: Avoid srcutorture security-based pointer obfuscation Because pointer output is now obfuscated, and because what you really want to know is whether or not the callback lists are empty, this commit replaces the srcu_data structure's head callback pointer printout with a single character that is "." is the callback list is empty or "C" otherwise. This is the only remaining user of rcu_segcblist_head(), so this commit also removes this function's definition. It also turns out that rcu_segcblist_tail() no longer has any callers, so this commit removes that function's definition while in the area. They were both marked "Interim", and their end has come. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcu_segcblist.h | 21 --------------------- kernel/rcu/srcutree.c | 5 +++-- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h index 71b64648464e..822a39da0533 100644 --- a/kernel/rcu/rcu_segcblist.h +++ b/kernel/rcu/rcu_segcblist.h @@ -76,27 +76,6 @@ static inline bool rcu_segcblist_restempty(struct rcu_segcblist *rsclp, int seg) return !*rsclp->tails[seg]; } -/* - * Interim function to return rcu_segcblist head pointer. Longer term, the - * rcu_segcblist will be used more pervasively, removing the need for this - * function. - */ -static inline struct rcu_head *rcu_segcblist_head(struct rcu_segcblist *rsclp) -{ - return rsclp->head; -} - -/* - * Interim function to return rcu_segcblist head pointer. Longer term, the - * rcu_segcblist will be used more pervasively, removing the need for this - * function. - */ -static inline struct rcu_head **rcu_segcblist_tail(struct rcu_segcblist *rsclp) -{ - WARN_ON_ONCE(rcu_segcblist_empty(rsclp)); - return rsclp->tails[RCU_NEXT_TAIL]; -} - void rcu_segcblist_init(struct rcu_segcblist *rsclp); void rcu_segcblist_disable(struct rcu_segcblist *rsclp); bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp); diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index cf0e886314f2..5dffade2d7cd 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c @@ -1279,8 +1279,9 @@ void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf) c0 = l0 - u0; c1 = l1 - u1; - pr_cont(" %d(%ld,%ld %1p)", - cpu, c0, c1, rcu_segcblist_head(&sdp->srcu_cblist)); + pr_cont(" %d(%ld,%ld %c)", + cpu, c0, c1, + "C."[rcu_segcblist_empty(&sdp->srcu_cblist)]); s0 += c0; s1 += c1; } -- GitLab From 3545832fc22e2316d9c289f6ba825710a268bfa6 Mon Sep 17 00:00:00 2001 From: Byungchul Park Date: Mon, 1 Jul 2019 09:40:39 +0900 Subject: [PATCH 1611/7155] rcu: Change return type of rcu_spawn_one_boost_kthread() The return value of rcu_spawn_one_boost_kthread() is not used any longer. This commit therefore changes its return type from int to void, and removes the cast to void from its callers. Signed-off-by: Byungchul Park Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_plugin.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 3f1b5041de9b..307ae6ebb804 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -1123,7 +1123,7 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) * already exist. We only create this kthread for preemptible RCU. * Returns zero if all is well, a negated errno otherwise. */ -static int rcu_spawn_one_boost_kthread(struct rcu_node *rnp) +static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp) { int rnp_index = rnp - rcu_get_root(); unsigned long flags; @@ -1131,25 +1131,27 @@ static int rcu_spawn_one_boost_kthread(struct rcu_node *rnp) struct task_struct *t; if (!IS_ENABLED(CONFIG_PREEMPT_RCU)) - return 0; + return; if (!rcu_scheduler_fully_active || rcu_rnp_online_cpus(rnp) == 0) - return 0; + return; rcu_state.boost = 1; + if (rnp->boost_kthread_task != NULL) - return 0; + return; + t = kthread_create(rcu_boost_kthread, (void *)rnp, "rcub/%d", rnp_index); - if (IS_ERR(t)) - return PTR_ERR(t); + if (WARN_ON_ONCE(IS_ERR(t))) + return; + raw_spin_lock_irqsave_rcu_node(rnp, flags); rnp->boost_kthread_task = t; raw_spin_unlock_irqrestore_rcu_node(rnp, flags); sp.sched_priority = kthread_prio; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ - return 0; } /* @@ -1190,7 +1192,7 @@ static void __init rcu_spawn_boost_kthreads(void) struct rcu_node *rnp; rcu_for_each_leaf_node(rnp) - (void)rcu_spawn_one_boost_kthread(rnp); + rcu_spawn_one_boost_kthread(rnp); } static void rcu_prepare_kthreads(int cpu) @@ -1200,7 +1202,7 @@ static void rcu_prepare_kthreads(int cpu) /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ if (rcu_scheduler_fully_active) - (void)rcu_spawn_one_boost_kthread(rnp); + rcu_spawn_one_boost_kthread(rnp); } #else /* #ifdef CONFIG_RCU_BOOST */ -- GitLab From 0500873de968df6fdef5752d7bbdca317ddc220b Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 8 Jul 2019 08:01:50 -0700 Subject: [PATCH 1612/7155] doc: Add rcutree.kthread_prio pointer to stallwarn.txt This commit adds mention of the rcutree.kthread_prio kernel boot parameter to the discussion of how high-priority real-time tasks can result in RCU CPU stall warnings. (However, this does not necessarily help when the high-priority real-time tasks are using dubious deadlines.) Signed-off-by: Paul E. McKenney --- Documentation/RCU/stallwarn.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt index 13e88fc00f01..f48f4621ccbc 100644 --- a/Documentation/RCU/stallwarn.txt +++ b/Documentation/RCU/stallwarn.txt @@ -57,6 +57,12 @@ o A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that CONFIG_PREEMPT_RCU case, you might see stall-warning messages. + You can use the rcutree.kthread_prio kernel boot parameter to + increase the scheduling priority of RCU's kthreads, which can + help avoid this problem. However, please note that doing this + can increase your system's context-switch rate and thus degrade + performance. + o A periodic interrupt whose handler takes longer than the time interval between successive pairs of interrupts. This can prevent RCU's kthreads and softirq handlers from running. -- GitLab From 4f9e05fb44f7fca787586f99a8b7f0da6c15eadf Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:20 -0700 Subject: [PATCH 1613/7155] fm10k: reduce the scope of qv local variable Reduce the scope of the qv vector pointer local variable in the fm10k_set_coalesce function. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_ethtool.c:658]: (style) The scope of the variable 'qv' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 7b9440c0aee1..1f7e4a8f4557 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -650,7 +650,6 @@ static int fm10k_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) { struct fm10k_intfc *interface = netdev_priv(dev); - struct fm10k_q_vector *qv; u16 tx_itr, rx_itr; int i; @@ -676,7 +675,8 @@ static int fm10k_set_coalesce(struct net_device *dev, /* update q_vectors */ for (i = 0; i < interface->num_q_vectors; i++) { - qv = interface->q_vector[i]; + struct fm10k_q_vector *qv = interface->q_vector[i]; + qv->tx.itr = tx_itr; qv->rx.itr = rx_itr; } -- GitLab From 57928c583ded1077c68168b0c7d34943612458da Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:21 -0700 Subject: [PATCH 1614/7155] fm10k: reduce the scope of local err variable Reduce the scope of the local err variable in the fm10k_iov_alloc_data function. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_iov.c:426]: (style) The scope of the variable 'err' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 8de77155f2e7..afe1fafd2447 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k.h" #include "fm10k_vf.h" @@ -426,7 +426,7 @@ static s32 fm10k_iov_alloc_data(struct pci_dev *pdev, int num_vfs) struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_hw *hw = &interface->hw; size_t size; - int i, err; + int i; /* return error if iov_data is already populated */ if (iov_data) @@ -452,6 +452,7 @@ static s32 fm10k_iov_alloc_data(struct pci_dev *pdev, int num_vfs) /* loop through vf_info structures initializing each entry */ for (i = 0; i < num_vfs; i++) { struct fm10k_vf_info *vf_info = &iov_data->vf_info[i]; + int err; /* Record VF VSI value */ vf_info->vsi = i + 1; -- GitLab From 7a432d57e080ac16645a08e93dbf1159d31f405f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:22 -0700 Subject: [PATCH 1615/7155] fm10k: reduce the scope of the q_idx local variable Reduce the scope of the q_idx local variable in the fm10k_cache_ring_qos function. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_main.c:2016]: (style) The scope of the variable 'q_idx' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 9ffff7886085..9e6bddff7625 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include #include @@ -17,7 +17,7 @@ const char fm10k_driver_version[] = DRV_VERSION; char fm10k_driver_name[] = "fm10k"; static const char fm10k_driver_string[] = DRV_SUMMARY; static const char fm10k_copyright[] = - "Copyright(c) 2013 - 2018 Intel Corporation."; + "Copyright(c) 2013 - 2019 Intel Corporation."; MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION(DRV_SUMMARY); @@ -1870,7 +1870,7 @@ static int fm10k_init_msix_capability(struct fm10k_intfc *interface) static bool fm10k_cache_ring_qos(struct fm10k_intfc *interface) { struct net_device *dev = interface->netdev; - int pc, offset, rss_i, i, q_idx; + int pc, offset, rss_i, i; u16 pc_stride = interface->ring_feature[RING_F_QOS].mask + 1; u8 num_pcs = netdev_get_num_tc(dev); @@ -1880,7 +1880,8 @@ static bool fm10k_cache_ring_qos(struct fm10k_intfc *interface) rss_i = interface->ring_feature[RING_F_RSS].indices; for (pc = 0, offset = 0; pc < num_pcs; pc++, offset += rss_i) { - q_idx = pc; + int q_idx = pc; + for (i = 0; i < rss_i; i++) { interface->tx_ring[offset + i]->reg_idx = q_idx; interface->tx_ring[offset + i]->qos_pc = pc; -- GitLab From 0a5b99f57873e233ad42ef71e23c629f6ea1fcfe Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Thu, 11 Jul 2019 16:45:41 -0400 Subject: [PATCH 1616/7155] treewide: Rename rcu_dereference_raw_notrace() to _check() The rcu_dereference_raw_notrace() API name is confusing. It is equivalent to rcu_dereference_raw() except that it also does sparse pointer checking. There are only a few users of rcu_dereference_raw_notrace(). This patches renames all of them to be rcu_dereference_raw_check() with the "_check()" indicating sparse checking. Signed-off-by: Joel Fernandes (Google) [ paulmck: Fix checkpatch warnings about parentheses. ] Signed-off-by: Paul E. McKenney --- Documentation/RCU/Design/Requirements/Requirements.html | 2 +- arch/powerpc/include/asm/kvm_book3s_64.h | 2 +- include/linux/rculist.h | 6 +++--- include/linux/rcupdate.h | 2 +- kernel/trace/ftrace_internal.h | 8 ++++---- kernel/trace/trace.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 5a9238a2883c..bdbc84f1b949 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -2512,7 +2512,7 @@ disabled across the entire RCU read-side critical section.

    It is possible to use tracing on RCU code, but tracing itself uses RCU. -For this reason, rcu_dereference_raw_notrace() +For this reason, rcu_dereference_raw_check() is provided for use by tracing, which avoids the destructive recursion that could otherwise ensue. This API is also used by virtualization in some architectures, diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index bb7c8cc77f1a..04b2b927bb5a 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -535,7 +535,7 @@ static inline void note_hpte_modification(struct kvm *kvm, */ static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm) { - return rcu_dereference_raw_notrace(kvm->memslots[0]); + return rcu_dereference_raw_check(kvm->memslots[0]); } extern void kvmppc_mmu_debugfs_init(struct kvm *kvm); diff --git a/include/linux/rculist.h b/include/linux/rculist.h index e91ec9ddcd30..932296144131 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -622,7 +622,7 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n, * as long as the traversal is guarded by rcu_read_lock(). */ #define hlist_for_each_entry_rcu(pos, head, member) \ - for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\ + for (pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\ typeof(*(pos)), member); \ pos; \ pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\ @@ -642,10 +642,10 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n, * not do any RCU debugging or tracing. */ #define hlist_for_each_entry_rcu_notrace(pos, head, member) \ - for (pos = hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\ + for (pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_first_rcu(head)),\ typeof(*(pos)), member); \ pos; \ - pos = hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\ + pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_next_rcu(\ &(pos)->member)), typeof(*(pos)), member)) /** diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 8f7167478c1d..bfcafbc1e301 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -476,7 +476,7 @@ do { \ * The no-tracing version of rcu_dereference_raw() must not call * rcu_read_lock_held(). */ -#define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu) +#define rcu_dereference_raw_check(p) __rcu_dereference_check((p), 1, __rcu) /** * rcu_dereference_protected() - fetch RCU pointer when updates prevented diff --git a/kernel/trace/ftrace_internal.h b/kernel/trace/ftrace_internal.h index 0515a2096f90..0456e0a3dab1 100644 --- a/kernel/trace/ftrace_internal.h +++ b/kernel/trace/ftrace_internal.h @@ -6,22 +6,22 @@ /* * Traverse the ftrace_global_list, invoking all entries. The reason that we - * can use rcu_dereference_raw_notrace() is that elements removed from this list + * can use rcu_dereference_raw_check() is that elements removed from this list * are simply leaked, so there is no need to interact with a grace-period - * mechanism. The rcu_dereference_raw_notrace() calls are needed to handle + * mechanism. The rcu_dereference_raw_check() calls are needed to handle * concurrent insertions into the ftrace_global_list. * * Silly Alpha and silly pointer-speculation compiler optimizations! */ #define do_for_each_ftrace_op(op, list) \ - op = rcu_dereference_raw_notrace(list); \ + op = rcu_dereference_raw_check(list); \ do /* * Optimized for just a single item in the list (as that is the normal case). */ #define while_for_each_ftrace_op(op) \ - while (likely(op = rcu_dereference_raw_notrace((op)->next)) && \ + while (likely(op = rcu_dereference_raw_check((op)->next)) && \ unlikely((op) != &ftrace_list_end)) extern struct ftrace_ops __rcu *ftrace_ops_list; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 525a97fbbc60..642474b26ba7 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2642,10 +2642,10 @@ static void ftrace_exports(struct ring_buffer_event *event) preempt_disable_notrace(); - export = rcu_dereference_raw_notrace(ftrace_exports_list); + export = rcu_dereference_raw_check(ftrace_exports_list); while (export) { trace_process_export(export, event); - export = rcu_dereference_raw_notrace(export->next); + export = rcu_dereference_raw_check(export->next); } preempt_enable_notrace(); -- GitLab From 9147089bee3a6b504821dd8462e2be229e6dbfae Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Tue, 16 Jul 2019 18:12:21 -0400 Subject: [PATCH 1617/7155] rcu: Remove redundant debug_locks check in rcu_read_lock_sched_held() The debug_locks flag can never be true at the end of rcu_read_lock_sched_held() because it is already checked by the earlier call todebug_lockdep_rcu_enabled(). This commit therefore removes this redundant check. Signed-off-by: Joel Fernandes (Google) Signed-off-by: Paul E. McKenney --- kernel/rcu/update.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 61df2bf08563..9dd5aeef6e70 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -93,17 +93,13 @@ module_param(rcu_normal_after_boot, int, 0); */ int rcu_read_lock_sched_held(void) { - int lockdep_opinion = 0; - if (!debug_lockdep_rcu_enabled()) return 1; if (!rcu_is_watching()) return 0; if (!rcu_lockdep_current_cpu_online()) return 0; - if (debug_locks) - lockdep_opinion = lock_is_held(&rcu_sched_lock_map); - return lockdep_opinion || !preemptible(); + return lock_is_held(&rcu_sched_lock_map) || !preemptible(); } EXPORT_SYMBOL(rcu_read_lock_sched_held); #endif -- GitLab From b3f3886c59f649ace424d132bd8c06e3611c71a8 Mon Sep 17 00:00:00 2001 From: Xiao Yang Date: Fri, 31 May 2019 23:15:45 +0800 Subject: [PATCH 1618/7155] rcuperf: Fix perf_type module-parameter description The rcu_bh rcuperf type was removed by commit 620d246065cd("rcuperf: Remove the "rcu_bh" and "sched" torture types"), but it lives on in the MODULE_PARM_DESC() of perf_type. This commit therefore changes that module-parameter description to substitute srcu for rcu_bh. Signed-off-by: Xiao Yang Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 7a6890b23c5f..4513807cd4c4 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -89,7 +89,7 @@ torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable static char *perf_type = "rcu"; module_param(perf_type, charp, 0444); -MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, rcu_bh, ...)"); +MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, srcu, ...)"); static int nrealreaders; static int nrealwriters; -- GitLab From 2c667e5eae232f7f4a4fc30f58e51abdb0dc43c5 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 21 Jun 2019 10:32:57 -0700 Subject: [PATCH 1619/7155] torture: Expand last_ts variable in kvm-test-1-run.sh The kvm-test-1-run.sh script says 'test -z "last_ts"' which always evaluates to true (AKA zero) regardless of the value of the last_ts shell variable. This commit therefore inserts the needed dollar sign ("$"). Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index 27b7b5693ede..33c669619736 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -227,7 +227,7 @@ then must_continue=yes fi last_ts="`tail $resdir/console.log | grep '^\[ *[0-9]\+\.[0-9]\+]' | tail -1 | sed -e 's/^\[ *//' -e 's/\..*$//'`" - if test -z "last_ts" + if test -z "$last_ts" then last_ts=0 fi -- GitLab From f4e8352928587ef8772df3d269a328efa609daaa Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 27 Jun 2019 14:05:54 -0700 Subject: [PATCH 1620/7155] rcutorture: Test TREE03 with the threadirqs kernel boot parameter Since commit 05f415715ce45 ("rcu: Speed up expedited GPs when interrupting RCU reader") in v5.0 and through v5.1, booting with the threadirqs kernel boot parameter caused self-deadlocks, which can be reproduced using the following command on an 8-CPU system: tools/testing/selftests/rcutorture/bin/kvm.sh --duration 5 --configs "TREE03" --bootargs "threadirqs" This commit therefore adds the threadirqs kernel boot parameter to the TREE03 rcutorture scenario in order to more quickly detect future similar bugs. Link: http://lkml.kernel.org/r/20190626135447.y24mvfuid5fifwjc@linutronix.de Signed-off-by: Paul E. McKenney Cc: Sebastian Andrzej Siewior Cc: Joel Fernandes --- tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot index 5c3213cc3ad7..1c218944b1e9 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot @@ -3,3 +3,4 @@ rcutree.gp_preinit_delay=12 rcutree.gp_init_delay=3 rcutree.gp_cleanup_delay=3 rcutree.kthread_prio=2 +threadirqs -- GitLab From bd1bfc51a36f334270b886db6d8467e55fe294ca Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 22 Jun 2019 14:35:59 -0700 Subject: [PATCH 1621/7155] rcutorture: Emulate userspace sojourn during call_rcu() floods During an actual call_rcu() flood, there would be frequent trips to userspace (in-kernel call_rcu() floods must be otherwise housebroken). Userspace execution allows a great many things to interrupt execution, and rcutorture needs to also allow such interruptions. This commit therefore causes call_rcu() floods to occasionally invoke schedule(), thus preventing spurious rcutorture failures due to other parts of the kernel becoming irate at the call_rcu() flood events. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index fce4e7e6f502..c44e5307afcc 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1713,12 +1713,14 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp) } // Give the scheduler a chance, even on nohz_full CPUs. -static void rcu_torture_fwd_prog_cond_resched(void) +static void rcu_torture_fwd_prog_cond_resched(unsigned long iter) { if (IS_ENABLED(CONFIG_PREEMPT) && IS_ENABLED(CONFIG_NO_HZ_FULL)) { - if (need_resched()) + // Real call_rcu() floods hit userspace, so emulate that. + if (need_resched() || (iter & 0xfff)) schedule(); } else { + // No userspace emulation: CB invocation throttles call_rcu() cond_resched(); } } @@ -1746,7 +1748,7 @@ static unsigned long rcu_torture_fwd_prog_cbfree(void) spin_unlock_irqrestore(&rcu_fwd_lock, flags); kfree(rfcp); freed++; - rcu_torture_fwd_prog_cond_resched(); + rcu_torture_fwd_prog_cond_resched(freed); } return freed; } @@ -1790,7 +1792,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries) udelay(10); cur_ops->readunlock(idx); if (!fwd_progress_need_resched || need_resched()) - rcu_torture_fwd_prog_cond_resched(); + rcu_torture_fwd_prog_cond_resched(1); } (*tested_tries)++; if (!time_before(jiffies, stopat) && @@ -1875,7 +1877,7 @@ static void rcu_torture_fwd_prog_cr(void) rfcp->rfc_gps = 0; } cur_ops->call(&rfcp->rh, rcu_torture_fwd_cb_cr); - rcu_torture_fwd_prog_cond_resched(); + rcu_torture_fwd_prog_cond_resched(n_launders + n_max_cbs); } stoppedat = jiffies; n_launders_cb_snap = READ_ONCE(n_launders_cb); -- GitLab From 21f57546ceaf4c5537a617f55b809a843b109210 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Thu, 4 Jul 2019 15:57:19 +0300 Subject: [PATCH 1622/7155] torture: Remove exporting of internal functions The functions torture_onoff_cleanup() and torture_shuffle_cleanup() are declared static and marked EXPORT_SYMBOL_GPL(), which is at best an odd combination. Because these functions are not used outside of the kernel/torture.c file they are defined in, this commit removes their EXPORT_SYMBOL_GPL() marking. Fixes: cc47ae083026 ("rcutorture: Abstract torture-test cleanup") Signed-off-by: Denis Efremov Signed-off-by: Paul E. McKenney --- kernel/torture.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/torture.c b/kernel/torture.c index a8d9bdfba7c3..7c13f5558b71 100644 --- a/kernel/torture.c +++ b/kernel/torture.c @@ -263,7 +263,6 @@ static void torture_onoff_cleanup(void) onoff_task = NULL; #endif /* #ifdef CONFIG_HOTPLUG_CPU */ } -EXPORT_SYMBOL_GPL(torture_onoff_cleanup); /* * Print online/offline testing statistics. @@ -449,7 +448,6 @@ static void torture_shuffle_cleanup(void) } shuffler_task = NULL; } -EXPORT_SYMBOL_GPL(torture_shuffle_cleanup); /* * Variables for auto-shutdown. This allows "lights out" torture runs -- GitLab From 77e9752ce69f36f1be4e366373727fb7921f5909 Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Thu, 4 Jul 2019 00:34:30 -0400 Subject: [PATCH 1623/7155] rcuperf: Make rcuperf kernel test more robust for !expedited mode It is possible that the rcuperf kernel test runs concurrently with init starting up. During this time, the system is running all grace periods as expedited. However, rcuperf can also be run for normal GP tests. Right now, it depends on a holdoff time before starting the test to ensure grace periods start later. This works fine with the default holdoff time however it is not robust in situations where init takes greater than the holdoff time to finish running. Or, as in my case: I modified the rcuperf test locally to also run a thread that did preempt disable/enable in a loop. This had the effect of slowing down init. The end result was that the "batches:" counter in rcuperf was 0 causing a division by 0 error in the results. This counter was 0 because only expedited GPs seem to happen, not normal ones which led to the rcu_state.gp_seq counter remaining constant across grace periods which unexpectedly happen to be expedited. The system was running expedited RCU all the time because rcu_unexpedited_gp() would not have run yet from init. In other words, the test would concurrently with init booting in expedited GP mode. To fix this properly, this commit waits until system_state is set to SYSTEM_RUNNING before starting the test. This change is made just before kernel_init() invokes rcu_end_inkernel_boot(), and this latter is what turns off boot-time expediting of RCU grace periods. Signed-off-by: Joel Fernandes (Google) Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 4513807cd4c4..5a879d073c1c 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -375,6 +375,14 @@ rcu_perf_writer(void *arg) if (holdoff) schedule_timeout_uninterruptible(holdoff * HZ); + /* + * Wait until rcu_end_inkernel_boot() is called for normal GP tests + * so that RCU is not always expedited for normal GP tests. + * The system_state test is approximate, but works well in practice. + */ + while (!gp_exp && system_state != SYSTEM_RUNNING) + schedule_timeout_uninterruptible(1); + t = ktime_get_mono_fast_ns(); if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) { t_rcu_perf_writer_started = t; -- GitLab From 60013d5d2b4031e6027005e5e2dcb6ee6da6b186 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 10 Jul 2019 08:30:00 -0700 Subject: [PATCH 1624/7155] rcutorture: Aggressive forward-progress tests shouldn't block shutdown The more aggressive forward-progress tests can interfere with rcutorture shutdown, resulting in false-positive diagnostics. This commit therefore ends any such tests 30 seconds prior to shutdown. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index c44e5307afcc..b22947324423 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -161,6 +161,7 @@ static atomic_long_t n_rcu_torture_timers; static long n_barrier_attempts; static long n_barrier_successes; /* did rcu_barrier test succeed? */ static struct list_head rcu_torture_removed; +static unsigned long shutdown_jiffies; static int rcu_torture_writer_state; #define RTWS_FIXED_DELAY 0 @@ -228,6 +229,15 @@ static u64 notrace rcu_trace_clock_local(void) } #endif /* #else #ifdef CONFIG_RCU_TRACE */ +/* + * Stop aggressive CPU-hog tests a bit before the end of the test in order + * to avoid interfering with test shutdown. + */ +static bool shutdown_time_arrived(void) +{ + return shutdown_secs && time_after(jiffies, shutdown_jiffies - 30 * HZ); +} + static unsigned long boost_starttime; /* jiffies of next boost test start. */ static DEFINE_MUTEX(boost_mutex); /* protect setting boost_starttime */ /* and boost task create/destroy. */ @@ -1787,6 +1797,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries) WRITE_ONCE(rcu_fwd_startat, jiffies); stopat = rcu_fwd_startat + dur; while (time_before(jiffies, stopat) && + !shutdown_time_arrived() && !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { idx = cur_ops->readlock(); udelay(10); @@ -1796,6 +1807,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries) } (*tested_tries)++; if (!time_before(jiffies, stopat) && + !shutdown_time_arrived() && !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { (*tested)++; cver = READ_ONCE(rcu_torture_current_version) - cver; @@ -1854,6 +1866,7 @@ static void rcu_torture_fwd_prog_cr(void) gps = cur_ops->get_gp_seq(); rcu_launder_gp_seq_start = gps; while (time_before(jiffies, stopat) && + !shutdown_time_arrived() && !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { rfcp = READ_ONCE(rcu_fwd_cb_head); rfcpn = NULL; @@ -1886,7 +1899,8 @@ static void rcu_torture_fwd_prog_cr(void) cur_ops->cb_barrier(); /* Wait for callbacks to be invoked. */ (void)rcu_torture_fwd_prog_cbfree(); - if (!torture_must_stop() && !READ_ONCE(rcu_fwd_emergency_stop)) { + if (!torture_must_stop() && !READ_ONCE(rcu_fwd_emergency_stop) && + !shutdown_time_arrived()) { WARN_ON(n_max_gps < MIN_FWD_CBS_LAUNDERED); pr_alert("%s Duration %lu barrier: %lu pending %ld n_launders: %ld n_launders_sa: %ld n_max_gps: %ld n_max_cbs: %ld cver %ld gps %ld\n", __func__, @@ -2467,6 +2481,7 @@ rcu_torture_init(void) goto unwind; rcutor_hp = firsterr; } + shutdown_jiffies = jiffies + shutdown_secs * HZ; firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup); if (firsterr) goto unwind; -- GitLab From fb381e60b8eb1eea61db07bdca436409229a8743 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:23 -0700 Subject: [PATCH 1625/7155] fm10k: reduce the scope of the tx_buffer variable The tx_buffer local variable in the function fm10k_clean_tx_ring is not used except inside a smaller block scope. Reduce the scope to its point of use. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_netdev.c:179]: (style) The scope of the variable 'tx_buffer' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 538a8467f434..c73fb38be678 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -169,7 +169,6 @@ void fm10k_unmap_and_free_tx_resource(struct fm10k_ring *ring, **/ static void fm10k_clean_tx_ring(struct fm10k_ring *tx_ring) { - struct fm10k_tx_buffer *tx_buffer; unsigned long size; u16 i; @@ -179,7 +178,8 @@ static void fm10k_clean_tx_ring(struct fm10k_ring *tx_ring) /* Free all the Tx ring sk_buffs */ for (i = 0; i < tx_ring->count; i++) { - tx_buffer = &tx_ring->tx_buffer[i]; + struct fm10k_tx_buffer *tx_buffer = &tx_ring->tx_buffer[i]; + fm10k_unmap_and_free_tx_resource(tx_ring, tx_buffer); } -- GitLab From b731d079e1baa18137fff3daed59c7f0d5ab2424 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:24 -0700 Subject: [PATCH 1626/7155] fm10k: reduce the scope of the err variable Reduce the scope of the local variable err in the fm10k_detach_subtask function. This was detected by cppcheck and resolves the following warning produced by that tool: [fm10k_pci.c:403]: (style) The scope of the variable 'err' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 7bfc8a5b6f55..9421832c2480 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include #include @@ -344,7 +344,6 @@ static void fm10k_detach_subtask(struct fm10k_intfc *interface) struct net_device *netdev = interface->netdev; u32 __iomem *hw_addr; u32 value; - int err; /* do nothing if netdev is still present or hw_addr is set */ if (netif_device_present(netdev) || interface->hw.hw_addr) @@ -362,6 +361,8 @@ static void fm10k_detach_subtask(struct fm10k_intfc *interface) hw_addr = READ_ONCE(interface->uc_addr); value = readl(hw_addr); if (~value) { + int err; + /* Make sure the reset was initiated because we detached, * otherwise we might race with a different reset flow. */ -- GitLab From d56b47791d3464178be2aa2d61db694331d50d5a Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:25 -0700 Subject: [PATCH 1627/7155] fm10k: reduce the scope of the local i variable Reduce the scope of the local loop variable in the fm10k_check_hang_subtask function. This was detected by cppcheck and resolves the following warning produced by that tool: [driver/fm10k_pci.c:852]: (style) The scope of the variable 'i' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 9421832c2480..9522e9f8f8b8 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -698,8 +698,6 @@ static void fm10k_watchdog_subtask(struct fm10k_intfc *interface) */ static void fm10k_check_hang_subtask(struct fm10k_intfc *interface) { - int i; - /* If we're down or resetting, just bail */ if (test_bit(__FM10K_DOWN, interface->state) || test_bit(__FM10K_RESETTING, interface->state)) @@ -711,6 +709,8 @@ static void fm10k_check_hang_subtask(struct fm10k_intfc *interface) interface->next_tx_hang_check = jiffies + (2 * HZ); if (netif_carrier_ok(interface->netdev)) { + int i; + /* Force detection of hung controller */ for (i = 0; i < interface->num_tx_queues; i++) set_check_for_tx_hang(interface->tx_ring[i]); -- GitLab From 71974d7e8556860c5ebe9bb37d598975f1e0c4e3 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:26 -0700 Subject: [PATCH 1628/7155] fm10k: reduce the scope of the local msg variable The msg variable in the fm10k_mbx_validate_msg_size and fm10k_sm_mbx_transmit functions is only used within the do {} loop scope. Reduce its scope only to where it is used. This was detected by cppcheck, and resolves the following warnings produced by that tool: [fm10k_mbx.c:299]: (style) The scope of the variable 'msg' can be reduced. [fm10k_mbx.c:2004]: (style) The scope of the variable 'msg' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 21021fe4f1c3..aece335b41f8 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -297,13 +297,14 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len) { struct fm10k_mbx_fifo *fifo = &mbx->rx; u16 total_len = 0, msg_len; - u32 *msg; /* length should include previous amounts pushed */ len += mbx->pushed; /* offset in message is based off of current message size */ do { + u32 *msg; + msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len); msg_len = FM10K_TLV_DWORD_LEN(*msg); total_len += msg_len; @@ -1920,7 +1921,6 @@ static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw, /* reduce length by 1 to convert to a mask */ u16 mbmem_len = mbx->mbmem_len - 1; u16 tail_len, len = 0; - u32 *msg; /* push head behind tail */ if (mbx->tail < head) @@ -1930,6 +1930,8 @@ static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw, /* determine msg aligned offset for end of buffer */ do { + u32 *msg; + msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len); tail_len = len; len += FM10K_TLV_DWORD_LEN(*msg); -- GitLab From 8e03f26b716f87c3bd1da212ec0fb3869ea47e64 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:27 -0700 Subject: [PATCH 1629/7155] fm10k: reduce the scope of the result local variable Reduce the scope of the result local variable in the fm10k_iov_msg_lport_state_pf function. This was detected by cppcheck and resolves the following warning produced by that tool: [fm10k_pf.c:1435]: (style) The scope of the variable 'result' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index cb4d02629b86..e85b2f2eef05 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1352,7 +1352,6 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; - u32 *result; s32 err = 0; u32 msg[2]; u8 mode = 0; @@ -1362,7 +1361,7 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, return FM10K_ERR_PARAM; if (!!results[FM10K_LPORT_STATE_MSG_XCAST_MODE]) { - result = results[FM10K_LPORT_STATE_MSG_XCAST_MODE]; + u32 *result = results[FM10K_LPORT_STATE_MSG_XCAST_MODE]; /* XCAST mode update requested */ err = fm10k_tlv_attr_get_u8(result, &mode); -- GitLab From df87b8fcf8fe658518fa8e75c9379e5bdfaf908c Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:28 -0700 Subject: [PATCH 1630/7155] fm10k: reduce scope of the ring variable Reduce the scope of the ring local variable in the fm10k_assign_l2_accel function. This was detected by cppcheck and resolves the following warning produced by that tool: [fm10k_netdev.c:1447]: (style) The scope of the variable 'ring' can be reduced. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index c73fb38be678..259da075093f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1444,11 +1444,11 @@ static int __fm10k_setup_tc(struct net_device *dev, enum tc_setup_type type, static void fm10k_assign_l2_accel(struct fm10k_intfc *interface, struct fm10k_l2_accel *l2_accel) { - struct fm10k_ring *ring; int i; for (i = 0; i < interface->num_rx_queues; i++) { - ring = interface->rx_ring[i]; + struct fm10k_ring *ring = interface->rx_ring[i]; + rcu_assign_pointer(ring->l2_accel, l2_accel); } -- GitLab From 7c5b42055964f587e55bd87ef334c3a27e95d144 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Tue, 30 Jul 2019 16:23:18 +0200 Subject: [PATCH 1631/7155] tipc: reduce risk of wakeup queue starvation In commit 365ad353c256 ("tipc: reduce risk of user starvation during link congestion") we allowed senders to add exactly one list of extra buffers to the link backlog queues during link congestion (aka "oversubscription"). However, the criteria for when to stop adding wakeup messages to the input queue when the overload abates is inaccurate, and may cause starvation problems during very high load. Currently, we stop adding wakeup messages after 10 total failed attempts where we find that there is no space left in the backlog queue for a certain importance level. The counter for this is accumulated across all levels, which may lead the algorithm to leave the loop prematurely, although there may still be plenty of space available at some levels. The result is sometimes that messages near the wakeup queue tail are not added to the input queue as they should be. We now introduce a more exact algorithm, where we keep adding wakeup messages to a level as long as the backlog queue has free slots for the corresponding level, and stop at the moment there are no more such slots or when there are no more wakeup messages to dequeue. Fixes: 365ad35 ("tipc: reduce risk of user starvation during link congestion") Reported-by: Tung Nguyen Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 2c274777b2dd..dd3155b14654 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -854,18 +854,31 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr) */ static void link_prepare_wakeup(struct tipc_link *l) { + struct sk_buff_head *wakeupq = &l->wakeupq; + struct sk_buff_head *inputq = l->inputq; struct sk_buff *skb, *tmp; - int imp, i = 0; + struct sk_buff_head tmpq; + int avail[5] = {0,}; + int imp = 0; + + __skb_queue_head_init(&tmpq); - skb_queue_walk_safe(&l->wakeupq, skb, tmp) { + for (; imp <= TIPC_SYSTEM_IMPORTANCE; imp++) + avail[imp] = l->backlog[imp].limit - l->backlog[imp].len; + + skb_queue_walk_safe(wakeupq, skb, tmp) { imp = TIPC_SKB_CB(skb)->chain_imp; - if (l->backlog[imp].len < l->backlog[imp].limit) { - skb_unlink(skb, &l->wakeupq); - skb_queue_tail(l->inputq, skb); - } else if (i++ > 10) { - break; - } + if (avail[imp] <= 0) + continue; + avail[imp]--; + __skb_unlink(skb, wakeupq); + __skb_queue_tail(&tmpq, skb); } + + spin_lock_bh(&inputq->lock); + skb_queue_splice_tail(&tmpq, inputq); + spin_unlock_bh(&inputq->lock); + } void tipc_link_reset(struct tipc_link *l) -- GitLab From c9f1fd4f2f74f322d5bdc4ec2c6a38ab7462967b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 2 Aug 2019 13:31:35 +1000 Subject: [PATCH 1632/7155] Revert "crypto: aegis128 - add support for SIMD acceleration" This reverts commit ecc8bc81f2fb3976737ef312f824ba6053aa3590 ("crypto: aegis128 - provide a SIMD implementation based on NEON intrinsics") and commit 7cdc0ddbf74a19cecb2f0e9efa2cae9d3c665189 ("crypto: aegis128 - add support for SIMD acceleration"). They cause compile errors on platforms other than ARM because the mechanism to selectively compile the SIMD code is broken. Repoted-by: Heiko Carstens Reported-by: Stephen Rothwell Signed-off-by: Herbert Xu --- crypto/Kconfig | 5 - crypto/Makefile | 12 -- crypto/aegis128-neon-inner.c | 149 ------------------------- crypto/aegis128-neon.c | 43 ------- crypto/{aegis128-core.c => aegis128.c} | 42 +------ 5 files changed, 4 insertions(+), 247 deletions(-) delete mode 100644 crypto/aegis128-neon-inner.c delete mode 100644 crypto/aegis128-neon.c rename crypto/{aegis128-core.c => aegis128.c} (89%) diff --git a/crypto/Kconfig b/crypto/Kconfig index 455a3354e291..8880c1fc51d8 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -306,11 +306,6 @@ config CRYPTO_AEGIS128 help Support for the AEGIS-128 dedicated AEAD algorithm. -config CRYPTO_AEGIS128_SIMD - bool "Support SIMD acceleration for AEGIS-128" - depends on CRYPTO_AEGIS128 && ((ARM || ARM64) && KERNEL_MODE_NEON) - default y - config CRYPTO_AEGIS128_AESNI_SSE2 tristate "AEGIS-128 AEAD algorithm (x86_64 AESNI+SSE2 implementation)" depends on X86 && 64BIT diff --git a/crypto/Makefile b/crypto/Makefile index b3e16b4fb414..93375e124ff7 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -90,18 +90,6 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o -aegis128-y := aegis128-core.o - -ifeq ($(ARCH),arm) -CFLAGS_aegis128-neon-inner.o += -ffreestanding -march=armv7-a -mfloat-abi=softfp -mfpu=crypto-neon-fp-armv8 -aegis128-$(CONFIG_CRYPTO_AEGIS128_SIMD) += aegis128-neon.o aegis128-neon-inner.o -endif -ifeq ($(ARCH),arm64) -CFLAGS_aegis128-neon-inner.o += -ffreestanding -mcpu=generic+crypto -CFLAGS_REMOVE_aegis128-neon-inner.o += -mgeneral-regs-only -aegis128-$(CONFIG_CRYPTO_AEGIS128_SIMD) += aegis128-neon.o aegis128-neon-inner.o -endif - obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o obj-$(CONFIG_CRYPTO_DES) += des_generic.o diff --git a/crypto/aegis128-neon-inner.c b/crypto/aegis128-neon-inner.c deleted file mode 100644 index 26e9450a5833..000000000000 --- a/crypto/aegis128-neon-inner.c +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2019 Linaro, Ltd. - */ - -#ifdef CONFIG_ARM64 -#include - -#define AES_ROUND "aese %0.16b, %1.16b \n\t aesmc %0.16b, %0.16b" -#else -#include - -#define AES_ROUND "aese.8 %q0, %q1 \n\t aesmc.8 %q0, %q0" -#endif - -#define AEGIS_BLOCK_SIZE 16 - -#include - -void *memcpy(void *dest, const void *src, size_t n); -void *memset(void *s, int c, size_t n); - -struct aegis128_state { - uint8x16_t v[5]; -}; - -static struct aegis128_state aegis128_load_state_neon(const void *state) -{ - return (struct aegis128_state){ { - vld1q_u8(state), - vld1q_u8(state + 16), - vld1q_u8(state + 32), - vld1q_u8(state + 48), - vld1q_u8(state + 64) - } }; -} - -static void aegis128_save_state_neon(struct aegis128_state st, void *state) -{ - vst1q_u8(state, st.v[0]); - vst1q_u8(state + 16, st.v[1]); - vst1q_u8(state + 32, st.v[2]); - vst1q_u8(state + 48, st.v[3]); - vst1q_u8(state + 64, st.v[4]); -} - -static uint8x16_t aegis_aes_round(uint8x16_t w) -{ - uint8x16_t z = {}; - - /* - * We use inline asm here instead of the vaeseq_u8/vaesmcq_u8 intrinsics - * to force the compiler to issue the aese/aesmc instructions in pairs. - * This is much faster on many cores, where the instruction pair can - * execute in a single cycle. - */ - asm(AES_ROUND : "+w"(w) : "w"(z)); - return w; -} - -static struct aegis128_state aegis128_update_neon(struct aegis128_state st, - uint8x16_t m) -{ - uint8x16_t t; - - t = aegis_aes_round(st.v[3]); - st.v[3] ^= aegis_aes_round(st.v[2]); - st.v[2] ^= aegis_aes_round(st.v[1]); - st.v[1] ^= aegis_aes_round(st.v[0]); - st.v[0] ^= aegis_aes_round(st.v[4]) ^ m; - st.v[4] ^= t; - - return st; -} - -void crypto_aegis128_update_neon(void *state, const void *msg) -{ - struct aegis128_state st = aegis128_load_state_neon(state); - - st = aegis128_update_neon(st, vld1q_u8(msg)); - - aegis128_save_state_neon(st, state); -} - -void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size) -{ - struct aegis128_state st = aegis128_load_state_neon(state); - uint8x16_t tmp; - - while (size >= AEGIS_BLOCK_SIZE) { - uint8x16_t s = vld1q_u8(src); - - tmp = s ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; - st = aegis128_update_neon(st, s); - vst1q_u8(dst, tmp); - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - - if (size > 0) { - uint8_t buf[AEGIS_BLOCK_SIZE] = {}; - uint8x16_t msg; - - memcpy(buf, src, size); - msg = vld1q_u8(buf); - tmp = msg ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; - st = aegis128_update_neon(st, msg); - vst1q_u8(buf, tmp); - memcpy(dst, buf, size); - } - - aegis128_save_state_neon(st, state); -} - -void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size) -{ - struct aegis128_state st = aegis128_load_state_neon(state); - uint8x16_t tmp; - - while (size >= AEGIS_BLOCK_SIZE) { - tmp = vld1q_u8(src) ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; - st = aegis128_update_neon(st, tmp); - vst1q_u8(dst, tmp); - - size -= AEGIS_BLOCK_SIZE; - src += AEGIS_BLOCK_SIZE; - dst += AEGIS_BLOCK_SIZE; - } - - if (size > 0) { - uint8_t buf[AEGIS_BLOCK_SIZE] = {}; - uint8x16_t msg; - - memcpy(buf, src, size); - msg = vld1q_u8(buf) ^ st.v[1] ^ (st.v[2] & st.v[3]) ^ st.v[4]; - vst1q_u8(buf, msg); - memcpy(dst, buf, size); - - memset(buf + size, 0, AEGIS_BLOCK_SIZE - size); - msg = vld1q_u8(buf); - st = aegis128_update_neon(st, msg); - } - - aegis128_save_state_neon(st, state); -} diff --git a/crypto/aegis128-neon.c b/crypto/aegis128-neon.c deleted file mode 100644 index c1c0a1686f67..000000000000 --- a/crypto/aegis128-neon.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2019 Linaro Ltd - */ - -#include -#include - -#include "aegis.h" - -void crypto_aegis128_update_neon(void *state, const void *msg); -void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size); -void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size); - -bool crypto_aegis128_have_simd(void) -{ - return cpu_have_feature(cpu_feature(AES)); -} - -void crypto_aegis128_update_simd(union aegis_block *state, const void *msg) -{ - kernel_neon_begin(); - crypto_aegis128_update_neon(state, msg); - kernel_neon_end(); -} - -void crypto_aegis128_encrypt_chunk_simd(union aegis_block *state, u8 *dst, - const u8 *src, unsigned int size) -{ - kernel_neon_begin(); - crypto_aegis128_encrypt_chunk_neon(state, dst, src, size); - kernel_neon_end(); -} - -void crypto_aegis128_decrypt_chunk_simd(union aegis_block *state, u8 *dst, - const u8 *src, unsigned int size) -{ - kernel_neon_begin(); - crypto_aegis128_decrypt_chunk_neon(state, dst, src, size); - kernel_neon_end(); -} diff --git a/crypto/aegis128-core.c b/crypto/aegis128.c similarity index 89% rename from crypto/aegis128-core.c rename to crypto/aegis128.c index f815b4685156..32840d5e7f65 100644 --- a/crypto/aegis128-core.c +++ b/crypto/aegis128.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -16,7 +15,6 @@ #include #include #include -#include #include "aegis.h" @@ -42,15 +40,6 @@ struct aegis128_ops { const u8 *src, unsigned int size); }; -static bool have_simd; - -bool crypto_aegis128_have_simd(void); -void crypto_aegis128_update_simd(struct aegis_state *state, const void *msg); -void crypto_aegis128_encrypt_chunk_simd(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size); -void crypto_aegis128_decrypt_chunk_simd(struct aegis_state *state, u8 *dst, - const u8 *src, unsigned int size); - static void crypto_aegis128_update(struct aegis_state *state) { union aegis_block tmp; @@ -66,22 +55,12 @@ static void crypto_aegis128_update(struct aegis_state *state) static void crypto_aegis128_update_a(struct aegis_state *state, const union aegis_block *msg) { - if (have_simd && crypto_simd_usable()) { - crypto_aegis128_update_simd(state, msg); - return; - } - crypto_aegis128_update(state); crypto_aegis_block_xor(&state->blocks[0], msg); } static void crypto_aegis128_update_u(struct aegis_state *state, const void *msg) { - if (have_simd && crypto_simd_usable()) { - crypto_aegis128_update_simd(state, msg); - return; - } - crypto_aegis128_update(state); crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE); } @@ -386,7 +365,7 @@ static void crypto_aegis128_crypt(struct aead_request *req, static int crypto_aegis128_encrypt(struct aead_request *req) { - const struct aegis128_ops *ops = &(struct aegis128_ops){ + static const struct aegis128_ops ops = { .skcipher_walk_init = skcipher_walk_aead_encrypt, .crypt_chunk = crypto_aegis128_encrypt_chunk, }; @@ -396,12 +375,7 @@ static int crypto_aegis128_encrypt(struct aead_request *req) unsigned int authsize = crypto_aead_authsize(tfm); unsigned int cryptlen = req->cryptlen; - if (have_simd && crypto_simd_usable()) - ops = &(struct aegis128_ops){ - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_chunk = crypto_aegis128_encrypt_chunk_simd }; - - crypto_aegis128_crypt(req, &tag, cryptlen, ops); + crypto_aegis128_crypt(req, &tag, cryptlen, &ops); scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, authsize, 1); @@ -410,7 +384,7 @@ static int crypto_aegis128_encrypt(struct aead_request *req) static int crypto_aegis128_decrypt(struct aead_request *req) { - const struct aegis128_ops *ops = &(struct aegis128_ops){ + static const struct aegis128_ops ops = { .skcipher_walk_init = skcipher_walk_aead_decrypt, .crypt_chunk = crypto_aegis128_decrypt_chunk, }; @@ -424,12 +398,7 @@ static int crypto_aegis128_decrypt(struct aead_request *req) scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, authsize, 0); - if (have_simd && crypto_simd_usable()) - ops = &(struct aegis128_ops){ - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_chunk = crypto_aegis128_decrypt_chunk_simd }; - - crypto_aegis128_crypt(req, &tag, cryptlen, ops); + crypto_aegis128_crypt(req, &tag, cryptlen, &ops); return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; } @@ -460,9 +429,6 @@ static struct aead_alg crypto_aegis128_alg = { static int __init crypto_aegis128_module_init(void) { - if (IS_ENABLED(CONFIG_CRYPTO_AEGIS128_SIMD)) - have_simd = crypto_aegis128_have_simd(); - return crypto_register_aead(&crypto_aegis128_alg); } -- GitLab From 5cb98b41abb38249eef04fa2884660cd772a0520 Mon Sep 17 00:00:00 2001 From: Tao Ren Date: Thu, 1 Aug 2019 21:06:50 -0700 Subject: [PATCH 1633/7155] ARM: dts: aspeed: Add Facebook Wedge40 BMC Add initial version of device tree for Facebook Wedge40 AST2400 BMC platform. Signed-off-by: Tao Ren Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/aspeed-bmc-facebook-wedge40.dts | 141 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 39a05a10a2a2..dfc1011eb3f2 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1273,6 +1273,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-facebook-cmm.dtb \ aspeed-bmc-facebook-minipack.dtb \ aspeed-bmc-facebook-tiogapass.dtb \ + aspeed-bmc-facebook-wedge40.dtb \ aspeed-bmc-facebook-yamp.dtb \ aspeed-bmc-intel-s2600wf.dtb \ aspeed-bmc-inspur-fp5280g2.dtb \ diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts new file mode 100644 index 000000000000..aaa77a597d1a --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Facebook Inc. +/dts-v1/; + +#include "aspeed-g4.dtsi" + +/ { + model = "Facebook Wedge 40 BMC"; + compatible = "facebook,wedge40-bmc", "aspeed,ast2400"; + + aliases { + /* + * Override the default uart aliases to avoid breaking + * the legacy applications. + */ + serial0 = &uart5; + serial1 = &uart1; + serial2 = &uart3; + serial3 = &uart4; + }; + + chosen { + stdout-path = &uart3; + bootargs = "console=ttyS2,9600n8 root=/dev/ram rw"; + }; + + memory@40000000 { + reg = <0x40000000 0x20000000>; + }; +}; + +&wdt1 { + status = "okay"; + aspeed,reset-type = "system"; +}; + +&wdt2 { + status = "disabled"; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "fmc0"; +#include "facebook-bmc-flash-layout.dtsi" + }; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default>; +}; + +&uart3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd3_default + &pinctrl_rxd3_default>; +}; + +&uart4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd4_default + &pinctrl_rxd4_default>; +}; + +&uart5 { + status = "okay"; +}; + +&mac1 { + status = "okay"; + no-hw-checksum; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; +}; + +&i2c7 { + status = "okay"; +}; + +&i2c8 { + status = "okay"; +}; + +&i2c9 { + status = "okay"; +}; + +&i2c10 { + status = "okay"; +}; + +&i2c11 { + status = "okay"; +}; + +&i2c12 { + status = "okay"; +}; + +&i2c13 { + status = "okay"; +}; + +&vhub { + status = "okay"; +}; -- GitLab From fdc0417be5260d5f2aa796ed5e1ac98d327888fc Mon Sep 17 00:00:00 2001 From: Tao Ren Date: Thu, 1 Aug 2019 21:10:10 -0700 Subject: [PATCH 1634/7155] ARM: dts: aspeed: Add Facebook Wedge100 BMC Add initial version of device tree for Facebook Wedge100 AST2400 BMC platform. Signed-off-by: Tao Ren Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/aspeed-bmc-facebook-wedge100.dts | 149 ++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index dfc1011eb3f2..72da035503c2 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1274,6 +1274,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-facebook-minipack.dtb \ aspeed-bmc-facebook-tiogapass.dtb \ aspeed-bmc-facebook-wedge40.dtb \ + aspeed-bmc-facebook-wedge100.dtb \ aspeed-bmc-facebook-yamp.dtb \ aspeed-bmc-intel-s2600wf.dtb \ aspeed-bmc-inspur-fp5280g2.dtb \ diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts new file mode 100644 index 000000000000..b1e10f0c85c9 --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Facebook Inc. +/dts-v1/; + +#include "aspeed-g4.dtsi" + +/ { + model = "Facebook Wedge 100 BMC"; + compatible = "facebook,wedge100-bmc", "aspeed,ast2400"; + + aliases { + /* + * Override the default uart aliases to avoid breaking + * the legacy applications. + */ + serial0 = &uart5; + serial1 = &uart1; + serial2 = &uart3; + serial3 = &uart4; + }; + + chosen { + stdout-path = &uart3; + bootargs = "console=ttyS2,9600n8 root=/dev/ram rw"; + }; + + memory@40000000 { + reg = <0x40000000 0x20000000>; + }; +}; + +&wdt1 { + status = "okay"; + aspeed,reset-type = "system"; +}; + +&wdt2 { + status = "okay"; + aspeed,reset-type = "system"; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "fmc0"; +#include "facebook-bmc-flash-layout.dtsi" + }; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default>; +}; + +&uart3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd3_default + &pinctrl_rxd3_default>; +}; + +&uart4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd4_default + &pinctrl_rxd4_default>; +}; + +&uart5 { + status = "okay"; +}; + +&mac1 { + status = "okay"; + no-hw-checksum; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; +}; + +&i2c7 { + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + }; +}; + +&i2c8 { + status = "okay"; +}; + +&i2c9 { + status = "okay"; +}; + +&i2c10 { + status = "okay"; +}; + +&i2c11 { + status = "okay"; +}; + +&i2c12 { + status = "okay"; +}; + +&i2c13 { + status = "okay"; +}; + +&vhub { + status = "okay"; +}; -- GitLab From 01970282a4ce0a049eddeb85bbe677e765111ee5 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 15:19:36 +0800 Subject: [PATCH 1635/7155] crypto: atmel-sha204a - Use device-managed registration API Use devm_hwrng_register to get rid of manual unregistration. Signed-off-by: Chuhong Yuan Acked-by: Ludovic Desroches Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index ea0d2068ea4f..c96c14e7dab1 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -109,7 +109,7 @@ static int atmel_sha204a_probe(struct i2c_client *client, i2c_priv->hwrng.read = atmel_sha204a_rng_read; i2c_priv->hwrng.quality = 1024; - ret = hwrng_register(&i2c_priv->hwrng); + ret = devm_hwrng_register(&client->dev, &i2c_priv->hwrng); if (ret) dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); @@ -127,7 +127,6 @@ static int atmel_sha204a_remove(struct i2c_client *client) if (i2c_priv->hwrng.priv) kfree((void *)i2c_priv->hwrng.priv); - hwrng_unregister(&i2c_priv->hwrng); return 0; } -- GitLab From 1b82feb6c5e1996513d0fb0bbb475417088b4954 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 23 Jul 2019 07:24:01 +0000 Subject: [PATCH 1636/7155] crypto: qat - Silence smp_processor_id() warning It seems that smp_processor_id() is only used for a best-effort load-balancing, refer to qat_crypto_get_instance_node(). It's not feasible to disable preemption for the duration of the crypto requests. Therefore, just silence the warning. This commit is similar to e7a9b05ca4 ("crypto: cavium - Fix smp_processor_id() warnings"). Silences the following splat: BUG: using smp_processor_id() in preemptible [00000000] code: cryptomgr_test/2904 caller is qat_alg_ablkcipher_setkey+0x300/0x4a0 [intel_qat] CPU: 1 PID: 2904 Comm: cryptomgr_test Tainted: P O 4.14.69 #1 ... Call Trace: dump_stack+0x5f/0x86 check_preemption_disabled+0xd3/0xe0 qat_alg_ablkcipher_setkey+0x300/0x4a0 [intel_qat] skcipher_setkey_ablkcipher+0x2b/0x40 __test_skcipher+0x1f3/0xb20 ? cpumask_next_and+0x26/0x40 ? find_busiest_group+0x10e/0x9d0 ? preempt_count_add+0x49/0xa0 ? try_module_get+0x61/0xf0 ? crypto_mod_get+0x15/0x30 ? __kmalloc+0x1df/0x1f0 ? __crypto_alloc_tfm+0x116/0x180 ? crypto_skcipher_init_tfm+0xa6/0x180 ? crypto_create_tfm+0x4b/0xf0 test_skcipher+0x21/0xa0 alg_test_skcipher+0x3f/0xa0 alg_test.part.6+0x126/0x2a0 ? finish_task_switch+0x21b/0x260 ? __schedule+0x1e9/0x800 ? __wake_up_common+0x8d/0x140 cryptomgr_test+0x40/0x50 kthread+0xff/0x130 ? cryptomgr_notify+0x540/0x540 ? kthread_create_on_node+0x70/0x70 ret_from_fork+0x24/0x50 Fixes: ed8ccaef52 ("crypto: qat - Add support for SRIOV") Cc: stable@vger.kernel.org Signed-off-by: Alexander Sverdlin Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_common_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index 5c4c0a253129..d78f8d5c89c3 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -95,7 +95,7 @@ struct service_hndl { static inline int get_current_node(void) { - return topology_physical_package_id(smp_processor_id()); + return topology_physical_package_id(raw_smp_processor_id()); } int adf_service_register(struct service_hndl *service); -- GitLab From 1c0ab408bb6e16285fcddc9b4ce74507081d053f Mon Sep 17 00:00:00 2001 From: Vakul Garg Date: Tue, 23 Jul 2019 09:14:24 +0000 Subject: [PATCH 1637/7155] crypto: caam/qi2 - Add printing dpseci fq stats using debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support of printing the dpseci frame queue statistics using debugfs. Signed-off-by: Vakul Garg Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/Makefile | 1 + drivers/crypto/caam/caamalg_qi2.c | 5 ++ drivers/crypto/caam/caamalg_qi2.h | 2 + drivers/crypto/caam/dpseci-debugfs.c | 79 ++++++++++++++++++++++++++++ drivers/crypto/caam/dpseci-debugfs.h | 18 +++++++ 5 files changed, 105 insertions(+) create mode 100644 drivers/crypto/caam/dpseci-debugfs.c create mode 100644 drivers/crypto/caam/dpseci-debugfs.h diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index 9ab4e81ea21e..68d5cc0f28e2 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -30,3 +30,4 @@ endif obj-$(CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM) += dpaa2_caam.o dpaa2_caam-y := caamalg_qi2.o dpseci.o +dpaa2_caam-$(CONFIG_DEBUG_FS) += dpseci-debugfs.o diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 06bf32c32cbd..a78a36dfa7b9 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -15,6 +15,7 @@ #include "key_gen.h" #include "caamalg_desc.h" #include "caamhash_desc.h" +#include "dpseci-debugfs.h" #include #include #include @@ -5098,6 +5099,8 @@ static int dpaa2_caam_probe(struct fsl_mc_device *dpseci_dev) goto err_bind; } + dpaa2_dpseci_debugfs_init(priv); + /* register crypto algorithms the device supports */ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { struct caam_skcipher_alg *t_alg = driver_algs + i; @@ -5265,6 +5268,8 @@ static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) dev = &ls_dev->dev; priv = dev_get_drvdata(dev); + dpaa2_dpseci_debugfs_exit(priv); + for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) { struct caam_aead_alg *t_alg = driver_aeads + i; diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h index 973f6296bc6f..b450e2a25c1f 100644 --- a/drivers/crypto/caam/caamalg_qi2.h +++ b/drivers/crypto/caam/caamalg_qi2.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "dpseci.h" #include "desc_constr.h" @@ -64,6 +65,7 @@ struct dpaa2_caam_priv { struct iommu_domain *domain; struct dpaa2_caam_priv_per_cpu __percpu *ppriv; + struct dentry *dfs_root; }; /** diff --git a/drivers/crypto/caam/dpseci-debugfs.c b/drivers/crypto/caam/dpseci-debugfs.c new file mode 100644 index 000000000000..c5bfc923abd8 --- /dev/null +++ b/drivers/crypto/caam/dpseci-debugfs.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2019 NXP */ + +#include +#include +#include +#include "dpseci-debugfs.h" + +static int dpseci_dbg_fqs_show(struct seq_file *file, void *offset) +{ + struct dpaa2_caam_priv *priv = (struct dpaa2_caam_priv *)file->private; + u32 fqid, fcnt, bcnt; + int i, err; + + seq_printf(file, "FQ stats for %s:\n", dev_name(priv->dev)); + seq_printf(file, "%s%16s%16s\n", + "Rx-VFQID", + "Pending frames", + "Pending bytes"); + + for (i = 0; i < priv->num_pairs; i++) { + fqid = priv->rx_queue_attr[i].fqid; + err = dpaa2_io_query_fq_count(NULL, fqid, &fcnt, &bcnt); + if (err) + continue; + + seq_printf(file, "%5d%16u%16u\n", fqid, fcnt, bcnt); + } + + seq_printf(file, "%s%16s%16s\n", + "Tx-VFQID", + "Pending frames", + "Pending bytes"); + + for (i = 0; i < priv->num_pairs; i++) { + fqid = priv->tx_queue_attr[i].fqid; + err = dpaa2_io_query_fq_count(NULL, fqid, &fcnt, &bcnt); + if (err) + continue; + + seq_printf(file, "%5d%16u%16u\n", fqid, fcnt, bcnt); + } + + return 0; +} + +static int dpseci_dbg_fqs_open(struct inode *inode, struct file *file) +{ + int err; + struct dpaa2_caam_priv *priv; + + priv = (struct dpaa2_caam_priv *)inode->i_private; + + err = single_open(file, dpseci_dbg_fqs_show, priv); + if (err < 0) + dev_err(priv->dev, "single_open() failed\n"); + + return err; +} + +static const struct file_operations dpseci_dbg_fq_ops = { + .open = dpseci_dbg_fqs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void dpaa2_dpseci_debugfs_init(struct dpaa2_caam_priv *priv) +{ + priv->dfs_root = debugfs_create_dir(dev_name(priv->dev), NULL); + + debugfs_create_file("fq_stats", 0444, priv->dfs_root, priv, + &dpseci_dbg_fq_ops); +} + +void dpaa2_dpseci_debugfs_exit(struct dpaa2_caam_priv *priv) +{ + debugfs_remove_recursive(priv->dfs_root); +} diff --git a/drivers/crypto/caam/dpseci-debugfs.h b/drivers/crypto/caam/dpseci-debugfs.h new file mode 100644 index 000000000000..bc22af7bec37 --- /dev/null +++ b/drivers/crypto/caam/dpseci-debugfs.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2019 NXP */ + +#ifndef DPSECI_DEBUGFS_H +#define DPSECI_DEBUGFS_H + +#include +#include "caamalg_qi2.h" + +#ifdef CONFIG_DEBUG_FS +void dpaa2_dpseci_debugfs_init(struct dpaa2_caam_priv *priv); +void dpaa2_dpseci_debugfs_exit(struct dpaa2_caam_priv *priv); +#else +static inline void dpaa2_dpseci_debugfs_init(struct dpaa2_caam_priv *priv) {} +static inline void dpaa2_dpseci_debugfs_exit(struct dpaa2_caam_priv *priv) {} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* DPSECI_DEBUGFS_H */ -- GitLab From 68289c634344431d6f97480eb5384516f37e39b8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 23 Jul 2019 20:43:43 +0900 Subject: [PATCH 1638/7155] crypto: add header include guards Add header include guards in case they are included multiple times. Signed-off-by: Masahiro Yamada Signed-off-by: Herbert Xu --- include/crypto/sha1_base.h | 5 +++++ include/crypto/sha256_base.h | 5 +++++ include/crypto/sha512_base.h | 5 +++++ include/crypto/sm3_base.h | 5 +++++ include/uapi/linux/cryptouser.h | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/include/crypto/sha1_base.h b/include/crypto/sha1_base.h index 63c14f2dc7bd..20fd1f7468af 100644 --- a/include/crypto/sha1_base.h +++ b/include/crypto/sha1_base.h @@ -5,6 +5,9 @@ * Copyright (C) 2015 Linaro Ltd */ +#ifndef _CRYPTO_SHA1_BASE_H +#define _CRYPTO_SHA1_BASE_H + #include #include #include @@ -101,3 +104,5 @@ static inline int sha1_base_finish(struct shash_desc *desc, u8 *out) *sctx = (struct sha1_state){}; return 0; } + +#endif /* _CRYPTO_SHA1_BASE_H */ diff --git a/include/crypto/sha256_base.h b/include/crypto/sha256_base.h index 59159bc944f5..b50a035a2bc7 100644 --- a/include/crypto/sha256_base.h +++ b/include/crypto/sha256_base.h @@ -5,6 +5,9 @@ * Copyright (C) 2015 Linaro Ltd */ +#ifndef _CRYPTO_SHA256_BASE_H +#define _CRYPTO_SHA256_BASE_H + #include #include #include @@ -123,3 +126,5 @@ static inline int sha256_base_finish(struct shash_desc *desc, u8 *out) *sctx = (struct sha256_state){}; return 0; } + +#endif /* _CRYPTO_SHA256_BASE_H */ diff --git a/include/crypto/sha512_base.h b/include/crypto/sha512_base.h index 099be8027f3f..fb19c77494dc 100644 --- a/include/crypto/sha512_base.h +++ b/include/crypto/sha512_base.h @@ -5,6 +5,9 @@ * Copyright (C) 2015 Linaro Ltd */ +#ifndef _CRYPTO_SHA512_BASE_H +#define _CRYPTO_SHA512_BASE_H + #include #include #include @@ -126,3 +129,5 @@ static inline int sha512_base_finish(struct shash_desc *desc, u8 *out) *sctx = (struct sha512_state){}; return 0; } + +#endif /* _CRYPTO_SHA512_BASE_H */ diff --git a/include/crypto/sm3_base.h b/include/crypto/sm3_base.h index 31891b0dc7e3..1cbf9aa1fe52 100644 --- a/include/crypto/sm3_base.h +++ b/include/crypto/sm3_base.h @@ -6,6 +6,9 @@ * Written by Gilad Ben-Yossef */ +#ifndef _CRYPTO_SM3_BASE_H +#define _CRYPTO_SM3_BASE_H + #include #include #include @@ -104,3 +107,5 @@ static inline int sm3_base_finish(struct shash_desc *desc, u8 *out) *sctx = (struct sm3_state){}; return 0; } + +#endif /* _CRYPTO_SM3_BASE_H */ diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h index 4dc1603919ce..5730c67f0617 100644 --- a/include/uapi/linux/cryptouser.h +++ b/include/uapi/linux/cryptouser.h @@ -19,6 +19,9 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifndef _UAPI_LINUX_CRYPTOUSER_H +#define _UAPI_LINUX_CRYPTOUSER_H + #include /* Netlink configuration messages. */ @@ -198,3 +201,5 @@ struct crypto_report_acomp { #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \ sizeof(struct crypto_report_blkcipher)) + +#endif /* _UAPI_LINUX_CRYPTOUSER_H */ -- GitLab From 939f146b89c22c387d51f69b27ef031664f64cbe Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 23 Jul 2019 20:43:44 +0900 Subject: [PATCH 1639/7155] crypto: user - fix potential warnings in cryptouser.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function definitions in headers are usually marked as 'static inline'. Since 'inline' is missing for crypto_reportstat(), if it were not referenced from a .c file that includes this header, it would produce a warning. Also, 'struct crypto_user_alg' is not declared in this header. I included instead of adding the forward declaration as suggested [1]. Detected by compile-testing this header as a standalone unit: ./include/crypto/internal/cryptouser.h:6:44: warning: ‘struct crypto_user_alg’ declared inside parameter list will not be visible outside of this definition or declaration struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact); ^~~~~~~~~~~~~~~ ./include/crypto/internal/cryptouser.h:11:12: warning: ‘crypto_reportstat’ defined but not used [-Wunused-function] static int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs) ^~~~~~~~~~~~~~~~~ [1] https://lkml.org/lkml/2019/6/13/1121 Signed-off-by: Masahiro Yamada Signed-off-by: Herbert Xu --- include/crypto/internal/cryptouser.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/crypto/internal/cryptouser.h b/include/crypto/internal/cryptouser.h index 40623f4457df..fd54074332f5 100644 --- a/include/crypto/internal/cryptouser.h +++ b/include/crypto/internal/cryptouser.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include #include struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact); @@ -6,7 +7,9 @@ struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact); #ifdef CONFIG_CRYPTO_STATS int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs); #else -static int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs) +static inline int crypto_reportstat(struct sk_buff *in_skb, + struct nlmsghdr *in_nlh, + struct nlattr **attrs) { return -ENOTSUPP; } -- GitLab From 3bd4952853d69659e58d1d4a4964383cb536b5be Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Wed, 24 Jul 2019 13:24:33 +0530 Subject: [PATCH 1640/7155] crypto: nx - Add of_node_put() before return in 842 Each iteration of for_each_compatible_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Add an of_node_put before the return. Issue found with Coccinelle. Acked-by: Stewart Smith Signed-off-by: Nishka Dasgupta Signed-off-by: Herbert Xu --- drivers/crypto/nx/nx-842-powernv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/nx/nx-842-powernv.c b/drivers/crypto/nx/nx-842-powernv.c index e78ff5c65ed6..c037a2403b82 100644 --- a/drivers/crypto/nx/nx-842-powernv.c +++ b/drivers/crypto/nx/nx-842-powernv.c @@ -1020,6 +1020,7 @@ static __init int nx842_powernv_init(void) ret = nx842_powernv_probe_vas(dn); if (ret) { nx842_delete_coprocs(); + of_node_put(dn); return ret; } } -- GitLab From dec0fb3946c478e7bb6165a1b7a03092ceefd419 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 24 Jul 2019 20:51:55 +0200 Subject: [PATCH 1641/7155] crypto: jitterentropy - build without sanitizer Recent clang-9 snapshots double the kernel stack usage when building this file with -O0 -fsanitize=kernel-hwaddress, compared to clang-8 and older snapshots, this changed between commits svn364966 and svn366056: crypto/jitterentropy.c:516:5: error: stack frame size of 2640 bytes in function 'jent_entropy_init' [-Werror,-Wframe-larger-than=] int jent_entropy_init(void) ^ crypto/jitterentropy.c:185:14: error: stack frame size of 2224 bytes in function 'jent_lfsr_time' [-Werror,-Wframe-larger-than=] static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt) ^ I prepared a reduced test case in case any clang developers want to take a closer look, but from looking at the earlier output it seems that even with clang-8, something was very wrong here. Turn off any KASAN and UBSAN sanitizing for this file, as that likely clashes with -O0 anyway. Turning off just KASAN avoids the warning already, but I suspect both of these have undesired side-effects for jitterentropy. Link: https://godbolt.org/z/fDcwZ5 Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- crypto/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/Makefile b/crypto/Makefile index 93375e124ff7..cfcc954e59f9 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -132,6 +132,8 @@ obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o obj-$(CONFIG_CRYPTO_DRBG) += drbg.o obj-$(CONFIG_CRYPTO_JITTERENTROPY) += jitterentropy_rng.o CFLAGS_jitterentropy.o = -O0 +KASAN_SANITIZE_jitterentropy.o = n +UBSAN_SANITIZE_jitterentropy.o = n jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o -- GitLab From 3e75241be8081f22f7382f4041496b10a4d9aed0 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 25 Jul 2019 16:01:55 +0800 Subject: [PATCH 1642/7155] hwrng: drivers - Use device-managed registration API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use devm_hwrng_register to simplify the implementation. Manual unregistration and some remove functions can be removed now. Signed-off-by: Chuhong Yuan Acked-by: Łukasz Stelmach Acked-by: Ludovic Desroches Signed-off-by: Herbert Xu --- drivers/char/hw_random/atmel-rng.c | 3 +-- drivers/char/hw_random/cavium-rng-vf.c | 11 +---------- drivers/char/hw_random/exynos-trng.c | 3 +-- drivers/char/hw_random/n2-drv.c | 4 +--- drivers/char/hw_random/nomadik-rng.c | 3 +-- drivers/char/hw_random/omap-rng.c | 3 +-- drivers/char/hw_random/powernv-rng.c | 10 +--------- drivers/char/hw_random/st-rng.c | 4 +--- drivers/char/hw_random/xgene-rng.c | 4 +--- 9 files changed, 9 insertions(+), 36 deletions(-) diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 433426242b87..e55705745d5e 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -86,7 +86,7 @@ static int atmel_trng_probe(struct platform_device *pdev) trng->rng.name = pdev->name; trng->rng.read = atmel_trng_read; - ret = hwrng_register(&trng->rng); + ret = devm_hwrng_register(&pdev->dev, &trng->rng); if (ret) goto err_register; @@ -103,7 +103,6 @@ static int atmel_trng_remove(struct platform_device *pdev) { struct atmel_trng *trng = platform_get_drvdata(pdev); - hwrng_unregister(&trng->rng); atmel_trng_disable(trng); clk_disable_unprepare(trng->clk); diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c index 2d1352b67168..3de4a6a443ef 100644 --- a/drivers/char/hw_random/cavium-rng-vf.c +++ b/drivers/char/hw_random/cavium-rng-vf.c @@ -67,7 +67,7 @@ static int cavium_rng_probe_vf(struct pci_dev *pdev, pci_set_drvdata(pdev, rng); - ret = hwrng_register(&rng->ops); + ret = devm_hwrng_register(&pdev->dev, &rng->ops); if (ret) { dev_err(&pdev->dev, "Error registering device as HWRNG.\n"); return ret; @@ -76,14 +76,6 @@ static int cavium_rng_probe_vf(struct pci_dev *pdev, return 0; } -/* Remove the VF */ -static void cavium_rng_remove_vf(struct pci_dev *pdev) -{ - struct cavium_rng *rng; - - rng = pci_get_drvdata(pdev); - hwrng_unregister(&rng->ops); -} static const struct pci_device_id cavium_rng_vf_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0}, @@ -95,7 +87,6 @@ static struct pci_driver cavium_rng_vf_driver = { .name = "cavium_rng_vf", .id_table = cavium_rng_vf_id_table, .probe = cavium_rng_probe_vf, - .remove = cavium_rng_remove_vf, }; module_pci_driver(cavium_rng_vf_driver); diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c index 94235761955c..b4b52ab23b6b 100644 --- a/drivers/char/hw_random/exynos-trng.c +++ b/drivers/char/hw_random/exynos-trng.c @@ -153,7 +153,7 @@ static int exynos_trng_probe(struct platform_device *pdev) goto err_clock; } - ret = hwrng_register(&trng->rng); + ret = devm_hwrng_register(&pdev->dev, &trng->rng); if (ret) { dev_err(&pdev->dev, "Could not register hwrng device.\n"); goto err_register; @@ -179,7 +179,6 @@ static int exynos_trng_remove(struct platform_device *pdev) { struct exynos_trng_dev *trng = platform_get_drvdata(pdev); - hwrng_unregister(&trng->rng); clk_disable_unprepare(trng->clk); pm_runtime_put_sync(&pdev->dev); diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index d4cab105796f..2d256b3470db 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -768,7 +768,7 @@ static int n2rng_probe(struct platform_device *op) np->hwrng.data_read = n2rng_data_read; np->hwrng.priv = (unsigned long) np; - err = hwrng_register(&np->hwrng); + err = devm_hwrng_register(&pdev->dev, &np->hwrng); if (err) goto out_hvapi_unregister; @@ -793,8 +793,6 @@ static int n2rng_remove(struct platform_device *op) cancel_delayed_work_sync(&np->work); - hwrng_unregister(&np->hwrng); - sun4v_hvapi_unregister(HV_GRP_RNG); return 0; diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index fc0f6b0cb80d..74ed29f42e4f 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -57,7 +57,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) if (!base) goto out_release; nmk_rng.priv = (unsigned long)base; - ret = hwrng_register(&nmk_rng); + ret = devm_hwrng_register(&dev->dev, &nmk_rng); if (ret) goto out_release; return 0; @@ -71,7 +71,6 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) static int nmk_rng_remove(struct amba_device *dev) { - hwrng_unregister(&nmk_rng); amba_release_regions(dev); clk_disable(rng_clk); return 0; diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index e9b6ac61fb7f..b27f39688b5e 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -500,7 +500,7 @@ static int omap_rng_probe(struct platform_device *pdev) if (ret) goto err_register; - ret = hwrng_register(&priv->rng); + ret = devm_hwrng_register(&pdev->dev, &priv->rng); if (ret) goto err_register; @@ -525,7 +525,6 @@ static int omap_rng_remove(struct platform_device *pdev) { struct omap_rng_dev *priv = platform_get_drvdata(pdev); - hwrng_unregister(&priv->rng); priv->pdata->cleanup(priv); diff --git a/drivers/char/hw_random/powernv-rng.c b/drivers/char/hw_random/powernv-rng.c index f2e8272e276a..8da1d7917bdc 100644 --- a/drivers/char/hw_random/powernv-rng.c +++ b/drivers/char/hw_random/powernv-rng.c @@ -33,18 +33,11 @@ static struct hwrng powernv_hwrng = { .read = powernv_rng_read, }; -static int powernv_rng_remove(struct platform_device *pdev) -{ - hwrng_unregister(&powernv_hwrng); - - return 0; -} - static int powernv_rng_probe(struct platform_device *pdev) { int rc; - rc = hwrng_register(&powernv_hwrng); + rc = devm_hwrng_register(&pdev->dev, &powernv_hwrng); if (rc) { /* We only register one device, ignore any others */ if (rc == -EEXIST) @@ -70,7 +63,6 @@ static struct platform_driver powernv_rng_driver = { .of_match_table = powernv_rng_match, }, .probe = powernv_rng_probe, - .remove = powernv_rng_remove, }; module_platform_driver(powernv_rng_driver); diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c index bd6a98b3479b..863448360a7d 100644 --- a/drivers/char/hw_random/st-rng.c +++ b/drivers/char/hw_random/st-rng.c @@ -102,7 +102,7 @@ static int st_rng_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, ddata); - ret = hwrng_register(&ddata->ops); + ret = devm_hwrng_register(&pdev->dev, &ddata->ops); if (ret) { dev_err(&pdev->dev, "Failed to register HW RNG\n"); clk_disable_unprepare(clk); @@ -118,8 +118,6 @@ static int st_rng_remove(struct platform_device *pdev) { struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev); - hwrng_unregister(&ddata->ops); - clk_disable_unprepare(ddata->clk); return 0; diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c index 8c6f9f63da5e..7e568db87ae2 100644 --- a/drivers/char/hw_random/xgene-rng.c +++ b/drivers/char/hw_random/xgene-rng.c @@ -361,7 +361,7 @@ static int xgene_rng_probe(struct platform_device *pdev) xgene_rng_func.priv = (unsigned long) ctx; - rc = hwrng_register(&xgene_rng_func); + rc = devm_hwrng_register(&pdev->dev, &xgene_rng_func); if (rc) { dev_err(&pdev->dev, "RNG registering failed error %d\n", rc); if (!IS_ERR(ctx->clk)) @@ -375,7 +375,6 @@ static int xgene_rng_probe(struct platform_device *pdev) rc); if (!IS_ERR(ctx->clk)) clk_disable_unprepare(ctx->clk); - hwrng_unregister(&xgene_rng_func); return rc; } @@ -392,7 +391,6 @@ static int xgene_rng_remove(struct platform_device *pdev) dev_err(&pdev->dev, "RNG init wakeup failed error %d\n", rc); if (!IS_ERR(ctx->clk)) clk_disable_unprepare(ctx->clk); - hwrng_unregister(&xgene_rng_func); return rc; } -- GitLab From f9981bc53825de2c001659d35c870786771f1e90 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 26 Jul 2019 22:19:07 +0200 Subject: [PATCH 1643/7155] crypto: api - Remove redundant #ifdef in crypto_yield() While looking at CONFIG_PREEMPT dependencies treewide the #ifdef in crypto_yield() matched. CONFIG_PREEMPT and CONFIG_PREEMPT_VOLUNTARY are mutually exclusive so the extra !CONFIG_PREEMPT conditional is redundant. cond_resched() has only an effect when CONFIG_PREEMPT_VOLUNTARY is set, otherwise it's a stub which the compiler optimizes out. Remove the whole conditional. No functional change. Signed-off-by: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Cc: Herbert Xu Cc: "David S. Miller" Signed-off-by: Herbert Xu --- include/crypto/algapi.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index dc1106af95c3..e5bd302f2c49 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -409,10 +409,8 @@ static inline int crypto_memneq(const void *a, const void *b, size_t size) static inline void crypto_yield(u32 flags) { -#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PREEMPT_VOLUNTARY) if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) cond_resched(); -#endif } int crypto_register_notifier(struct notifier_block *nb); -- GitLab From 2ef540476e0077ca2f9992fde9a014891000c4b5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Jul 2019 00:32:36 +0900 Subject: [PATCH 1644/7155] hwrng: timeriomem - add include guard to timeriomem-rng.h Add a header include guard just in case. Signed-off-by: Masahiro Yamada Signed-off-by: Herbert Xu --- include/linux/timeriomem-rng.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/timeriomem-rng.h b/include/linux/timeriomem-rng.h index fd4a6e6ec831..672df7fbf6c1 100644 --- a/include/linux/timeriomem-rng.h +++ b/include/linux/timeriomem-rng.h @@ -5,6 +5,9 @@ * Copyright (c) 2009 Alexander Clouter */ +#ifndef _LINUX_TIMERIOMEM_RNG_H +#define _LINUX_TIMERIOMEM_RNG_H + struct timeriomem_rng_data { void __iomem *address; @@ -14,3 +17,5 @@ struct timeriomem_rng_data { /* bits of entropy per 1024 bits read */ unsigned int quality; }; + +#endif /* _LINUX_TIMERIOMEM_RNG_H */ -- GitLab From 176435ad2ac7733014d6429369130ddb78f14ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Sun, 28 Jul 2019 22:26:38 +0300 Subject: [PATCH 1645/7155] crypto: caam - defer probing until QMan is available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QI (Queue Interface) support is enabled on DPAA 1.x platforms, defer probing if dependencies (QMan drivers) are not available yet. Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/ctrl.c | 74 ++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 4e43ca4d3656..e0590beae240 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -527,15 +527,54 @@ static int caam_probe(struct platform_device *pdev) dev_set_drvdata(dev, ctrlpriv); nprop = pdev->dev.of_node; + /* Get configuration properties from device tree */ + /* First, get register page */ + ctrl = of_iomap(nprop, 0); + if (!ctrl) { + dev_err(dev, "caam: of_iomap() failed\n"); + return -ENOMEM; + } + + caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) & + (CSTA_PLEND | CSTA_ALT_PLEND)); caam_imx = (bool)soc_device_match(imx_soc); + comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms); + caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2); + ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK); + +#ifdef CONFIG_CAAM_QI + /* If (DPAA 1.x) QI present, check whether dependencies are available */ + if (ctrlpriv->qi_present && !caam_dpaa2) { + ret = qman_is_probed(); + if (!ret) { + ret = -EPROBE_DEFER; + goto iounmap_ctrl; + } else if (ret < 0) { + dev_err(dev, "failing probe due to qman probe error\n"); + ret = -ENODEV; + goto iounmap_ctrl; + } + + ret = qman_portals_probed(); + if (!ret) { + ret = -EPROBE_DEFER; + goto iounmap_ctrl; + } else if (ret < 0) { + dev_err(dev, "failing probe due to qman portals probe error\n"); + ret = -ENODEV; + goto iounmap_ctrl; + } + } +#endif + /* Enable clocking */ clk = caam_drv_identify_clk(&pdev->dev, "ipg"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "can't identify CAAM ipg clk: %d\n", ret); - return ret; + goto iounmap_ctrl; } ctrlpriv->caam_ipg = clk; @@ -547,7 +586,7 @@ static int caam_probe(struct platform_device *pdev) ret = PTR_ERR(clk); dev_err(&pdev->dev, "can't identify CAAM mem clk: %d\n", ret); - return ret; + goto iounmap_ctrl; } ctrlpriv->caam_mem = clk; } @@ -557,7 +596,7 @@ static int caam_probe(struct platform_device *pdev) ret = PTR_ERR(clk); dev_err(&pdev->dev, "can't identify CAAM aclk clk: %d\n", ret); - return ret; + goto iounmap_ctrl; } ctrlpriv->caam_aclk = clk; @@ -570,7 +609,7 @@ static int caam_probe(struct platform_device *pdev) ret = PTR_ERR(clk); dev_err(&pdev->dev, "can't identify CAAM emi_slow clk: %d\n", ret); - return ret; + goto iounmap_ctrl; } ctrlpriv->caam_emi_slow = clk; } @@ -578,7 +617,7 @@ static int caam_probe(struct platform_device *pdev) ret = clk_prepare_enable(ctrlpriv->caam_ipg); if (ret < 0) { dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret); - return ret; + goto iounmap_ctrl; } if (ctrlpriv->caam_mem) { @@ -605,25 +644,10 @@ static int caam_probe(struct platform_device *pdev) } } - /* Get configuration properties from device tree */ - /* First, get register page */ - ctrl = of_iomap(nprop, 0); - if (ctrl == NULL) { - dev_err(dev, "caam: of_iomap() failed\n"); - ret = -ENOMEM; - goto disable_caam_emi_slow; - } - - caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) & - (CSTA_PLEND | CSTA_ALT_PLEND)); - - /* Finding the page size for using the CTPR_MS register */ - comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms); - pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT; - /* Allocating the BLOCK_OFFSET based on the supported page size on * the platform */ + pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT; if (pg_size == 0) BLOCK_OFFSET = PG_SIZE_4K; else @@ -648,7 +672,6 @@ static int caam_probe(struct platform_device *pdev) * In case of SoCs with Management Complex, MC f/w performs * the configuration. */ - caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2); np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-mc"); ctrlpriv->mc_en = !!np; of_node_put(np); @@ -700,7 +723,7 @@ static int caam_probe(struct platform_device *pdev) } if (ret) { dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret); - goto iounmap_ctrl; + goto disable_caam_emi_slow; } ctrlpriv->era = caam_get_era(ctrl); @@ -719,7 +742,6 @@ static int caam_probe(struct platform_device *pdev) #endif /* Check to see if (DPAA 1.x) QI present. If so, enable */ - ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK); if (ctrlpriv->qi_present && !caam_dpaa2) { ctrlpriv->qi = (struct caam_queue_if __iomem __force *) ((__force uint8_t *)ctrl + @@ -906,8 +928,6 @@ static int caam_probe(struct platform_device *pdev) if (ctrlpriv->qi_init) caam_qi_shutdown(dev); #endif -iounmap_ctrl: - iounmap(ctrl); disable_caam_emi_slow: if (ctrlpriv->caam_emi_slow) clk_disable_unprepare(ctrlpriv->caam_emi_slow); @@ -918,6 +938,8 @@ static int caam_probe(struct platform_device *pdev) clk_disable_unprepare(ctrlpriv->caam_mem); disable_caam_ipg: clk_disable_unprepare(ctrlpriv->caam_ipg); +iounmap_ctrl: + iounmap(ctrl); return ret; } -- GitLab From 155e4db324874d22aa8d3892da2a37fb39c89578 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 1 Aug 2019 12:11:33 +1000 Subject: [PATCH 1646/7155] asm-generic: Remove redundant arch-specific rules for simd.h Now that simd.h is in include/asm-generic/Kbuild we don't need the arch-specific Kbuild rules for them. Reported-by: Stephen Rothwell Fixes: 82cb54856874 ("asm-generic: make simd.h a mandatory...") Signed-off-by: Herbert Xu Acked-by: Ard Biesheuvel Acked-by: Arnd Bergmann --- arch/arm/include/asm/Kbuild | 1 - arch/powerpc/include/asm/Kbuild | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 6b2dc15b6dff..68ca86f85eb7 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -17,7 +17,6 @@ generic-y += parport.h generic-y += preempt.h generic-y += seccomp.h generic-y += serial.h -generic-y += simd.h generic-y += trace_clock.h generated-y += mach-types.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 9a1d2fc6ceb7..64870c7be4a3 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -11,4 +11,3 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += vtime.h generic-y += msi.h -generic-y += simd.h -- GitLab From 3bb4aefd2aed628452b8ce544b76abda0ce531f0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 1 Aug 2019 17:28:24 +0100 Subject: [PATCH 1647/7155] ALSA: isa/wavefront: remove redundant assignment to pointer bptr The pointer bptr is being assigned a value that is never read and it is being updated in the next statement with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai --- sound/isa/wavefront/wavefront_synth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index aec1c46e6697..c5b1d5900eed 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -788,7 +788,6 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header) dev->patch_status[header->number] |= WF_SLOT_FILLED; - bptr = buf; bptr = munge_int32 (header->number, buf, 2); munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); -- GitLab From b6fcab14ff027c4d54505d9cdff41535c3daf077 Mon Sep 17 00:00:00 2001 From: Tony W Wang-oc Date: Fri, 2 Aug 2019 03:04:08 +0000 Subject: [PATCH 1648/7155] ALSA: hda: Add support of Zhaoxin controller Add the new PCI ID 0x1d17 0x3288 Zhaoxin controller support Signed-off-by: Tony W Wang-oc Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 635d971b003b..151f206e1c02 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -270,6 +270,7 @@ enum { AZX_DRIVER_CTX, AZX_DRIVER_CTHDA, AZX_DRIVER_CMEDIA, + AZX_DRIVER_ZHAOXIN, AZX_DRIVER_GENERIC, AZX_NUM_DRIVERS, /* keep this as last entry */ }; @@ -384,6 +385,7 @@ static char *driver_short_names[] = { [AZX_DRIVER_CTX] = "HDA Creative", [AZX_DRIVER_CTHDA] = "HDA Creative", [AZX_DRIVER_CMEDIA] = "HDA C-Media", + [AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin", [AZX_DRIVER_GENERIC] = "HD-Audio Generic", }; @@ -2624,6 +2626,8 @@ static const struct pci_device_id azx_ids[] = { .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, + /* Zhaoxin */ + { PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids); -- GitLab From 46a9f947b3f65e488d03056765523291dc8bf4f6 Mon Sep 17 00:00:00 2001 From: Vijay Khemka Date: Thu, 25 Jul 2019 10:45:11 -0700 Subject: [PATCH 1649/7155] ARM: dts: aspeed: tiogapass: Move battery sensor Moved adc7 hwmon battery sensor to correct label to be read by single applications for all adc sensors. Signed-off-by: Vijay Khemka Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts index e722e9aef907..bd394e1739f5 100644 --- a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts @@ -25,13 +25,9 @@ iio-hwmon { compatible = "iio-hwmon"; io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, - <&adc 4>, <&adc 5>, <&adc 6>; + <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>; }; - iio-hwmon-battery { - compatible = "iio-hwmon"; - io-channels = <&adc 7>; - }; }; &fmc { -- GitLab From 4c349c7dafad613366574b89a9245f07504822ad Mon Sep 17 00:00:00 2001 From: Vijay Khemka Date: Tue, 23 Jul 2019 10:58:20 -0700 Subject: [PATCH 1650/7155] ARM: dts: aspeed: tiogapass: Add Riser card Added i2c mux for riser card and multiple ava card and its sensor components for Facebook tiogapass platform Signed-off-by: Vijay Khemka Signed-off-by: Joel Stanley --- .../dts/aspeed-bmc-facebook-tiogapass.dts | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts index bd394e1739f5..682f729ea25e 100644 --- a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts @@ -12,6 +12,27 @@ aliases { serial0 = &uart1; serial4 = &uart5; + + /* + * Hardcode the bus number of i2c switches' channels to + * avoid breaking the legacy applications. + */ + i2c16 = &imux16; + i2c17 = &imux17; + i2c18 = &imux18; + i2c19 = &imux19; + i2c20 = &imux20; + i2c21 = &imux21; + i2c22 = &imux22; + i2c23 = &imux23; + i2c24 = &imux24; + i2c25 = &imux25; + i2c26 = &imux26; + i2c27 = &imux27; + i2c28 = &imux28; + i2c29 = &imux29; + i2c30 = &imux30; + i2c31 = &imux31; }; chosen { stdout-path = &uart5; @@ -120,6 +141,215 @@ &i2c1 { status = "okay"; //X24 Riser + i2c-switch@71 { + compatible = "nxp,pca9544"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x71>; + + imux16: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + ina230@45 { + compatible = "ti,ina230"; + reg = <0x45>; + }; + + tmp75@48 { + compatible = "ti,tmp75"; + reg = <0x48>; + }; + + tmp421@49 { + compatible = "ti,tmp75"; + reg = <0x49>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + pagesize = <32>; + }; + + i2c-switch@73 { + compatible = "nxp,pca9546"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x73>; + + imux20: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux21: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux22: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux23: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + }; + + }; + + imux17: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + ina230@45 { + compatible = "ti,ina230"; + reg = <0x45>; + }; + + tmp421@48 { + compatible = "ti,tmp75"; + reg = <0x48>; + }; + + tmp421@49 { + compatible = "ti,tmp75"; + reg = <0x49>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + pagesize = <32>; + }; + + i2c-switch@73 { + compatible = "nxp,pca9546"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x73>; + + imux24: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux25: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux26: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux27: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + }; + + }; + + imux18: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + ina230@45 { + compatible = "ti,ina230"; + reg = <0x45>; + }; + + tmp421@48 { + compatible = "ti,tmp75"; + reg = <0x48>; + }; + + tmp421@49 { + compatible = "ti,tmp75"; + reg = <0x49>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + pagesize = <32>; + }; + + i2c-switch@73 { + compatible = "nxp,pca9546"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x73>; + + imux28: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + imux29: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + imux30: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + imux31: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + + }; + + }; + + imux19: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + i2c-switch@40 { + compatible = "ti,ina230"; + reg = <0x40>; + }; + + i2c-switch@41 { + compatible = "ti,ina230"; + reg = <0x41>; + }; + + i2c-switch@45 { + compatible = "ti,ina230"; + reg = <0x45>; + }; + + }; + + }; }; &i2c2 { -- GitLab From 7beb620f805dcb6757b5e7870bebd75e3e9b37e0 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 1 Aug 2019 16:44:39 +0800 Subject: [PATCH 1651/7155] gpio: mxc: Use devm_clk_get_optional instead of devm_clk_get i.MX SoC's GPIO clock is optional, so it is better to use devm_clk_get_optional instead of devm_clk_get. Signed-off-by: Anson Huang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mxc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index b2813580c582..7907a8755866 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -435,12 +435,9 @@ static int mxc_gpio_probe(struct platform_device *pdev) return port->irq; /* the controller clock is optional */ - port->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(port->clk)) { - if (PTR_ERR(port->clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - port->clk = NULL; - } + port->clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(port->clk)) + return PTR_ERR(port->clk); err = clk_prepare_enable(port->clk); if (err) { -- GitLab From 8eeb467d3b4f8a5f05e49dd88e7674a2d6c0f346 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:35 +0300 Subject: [PATCH 1652/7155] gpio: pca953x: Switch to use device_get_match_data() Instead of open coded variants, switch to direct use of device_get_match_data(). Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 378b206d2dc9..54cf01901320 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -949,19 +949,15 @@ static int pca953x_probe(struct i2c_client *client, if (i2c_id) { chip->driver_data = i2c_id->driver_data; } else { - const struct acpi_device_id *acpi_id; - struct device *dev = &client->dev; - - chip->driver_data = (uintptr_t)of_device_get_match_data(dev); - if (!chip->driver_data) { - acpi_id = acpi_match_device(pca953x_acpi_ids, dev); - if (!acpi_id) { - ret = -ENODEV; - goto err_exit; - } - - chip->driver_data = acpi_id->driver_data; + const void *match; + + match = device_get_match_data(&client->dev); + if (!match) { + ret = -ENODEV; + goto err_exit; } + + chip->driver_data = (uintptr_t)match; } i2c_set_clientdata(client, chip); -- GitLab From 63b484c2a69a4a98a22e072ea2ad1317a85e3abf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:36 +0300 Subject: [PATCH 1653/7155] gpio: pca953x: Use GENMASK() consistently Use GENMASK() macro for all definitions where it's appropriate. No functional change intended. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 54cf01901320..aaba0b394d2f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -28,9 +29,9 @@ #define PCA953X_INVERT 0x02 #define PCA953X_DIRECTION 0x03 -#define REG_ADDR_MASK 0x3f -#define REG_ADDR_EXT 0x40 -#define REG_ADDR_AI 0x80 +#define REG_ADDR_MASK GENMASK(5, 0) +#define REG_ADDR_EXT BIT(6) +#define REG_ADDR_AI BIT(7) #define PCA957X_IN 0x00 #define PCA957X_INVRT 0x01 @@ -55,17 +56,17 @@ #define PCAL6524_OUT_INDCONF 0x2c #define PCAL6524_DEBOUNCE 0x2d -#define PCA_GPIO_MASK 0x00FF +#define PCA_GPIO_MASK GENMASK(7, 0) -#define PCAL_GPIO_MASK 0x1f -#define PCAL_PINCTRL_MASK 0x60 +#define PCAL_GPIO_MASK GENMASK(4, 0) +#define PCAL_PINCTRL_MASK GENMASK(6, 5) -#define PCA_INT 0x0100 -#define PCA_PCAL 0x0200 +#define PCA_INT BIT(8) +#define PCA_PCAL BIT(9) #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) -#define PCA953X_TYPE 0x1000 -#define PCA957X_TYPE 0x2000 -#define PCA_TYPE_MASK 0xF000 +#define PCA953X_TYPE BIT(12) +#define PCA957X_TYPE BIT(13) +#define PCA_TYPE_MASK GENMASK(15, 12) #define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) @@ -565,7 +566,7 @@ static void pca953x_irq_mask(struct irq_data *d) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); + chip->irq_mask[d->hwirq / BANK_SZ] &= ~BIT(d->hwirq % BANK_SZ); } static void pca953x_irq_unmask(struct irq_data *d) @@ -573,7 +574,7 @@ static void pca953x_irq_unmask(struct irq_data *d) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); + chip->irq_mask[d->hwirq / BANK_SZ] |= BIT(d->hwirq % BANK_SZ); } static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) @@ -641,7 +642,7 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); int bank_nb = d->hwirq / BANK_SZ; - u8 mask = 1 << (d->hwirq % BANK_SZ); + u8 mask = BIT(d->hwirq % BANK_SZ); if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", @@ -666,7 +667,7 @@ static void pca953x_irq_shutdown(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - u8 mask = 1 << (d->hwirq % BANK_SZ); + u8 mask = BIT(d->hwirq % BANK_SZ); chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; -- GitLab From 6dd6a2d27e5a0d192b542389f4c9a035d1b77b8e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:37 +0300 Subject: [PATCH 1654/7155] gpio: pca953x: Remove explicit comparison with 0 There is no need to explicitly compare return code with 0. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index aaba0b394d2f..454bbe2fb41f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -850,12 +850,12 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); - if (ret != 0) + if (ret) goto out; ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); - if (ret != 0) + if (ret) goto out; /* set platform specific polarity inversion */ @@ -1061,14 +1061,14 @@ static int pca953x_regcache_sync(struct device *dev) */ ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); return ret; } @@ -1077,7 +1077,7 @@ static int pca953x_regcache_sync(struct device *dev) if (chip->driver_data & PCA_PCAL) { ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, PCAL953X_IN_LATCH + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync INT latch registers: %d\n", ret); return ret; @@ -1085,7 +1085,7 @@ static int pca953x_regcache_sync(struct device *dev) ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, PCAL953X_INT_MASK + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync INT mask registers: %d\n", ret); return ret; @@ -1117,7 +1117,7 @@ static int pca953x_resume(struct device *dev) if (!atomic_read(&chip->wakeup_path)) { ret = regulator_enable(chip->regulator); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to enable regulator: %d\n", ret); return 0; } @@ -1130,7 +1130,7 @@ static int pca953x_resume(struct device *dev) return ret; ret = regcache_sync(chip->regmap); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to restore register map: %d\n", ret); return ret; } -- GitLab From f4160faac98c36556231621b03b44b646508b08e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:38 +0300 Subject: [PATCH 1655/7155] gpio: pca953x: Drop %s for constant string literals There is no need to use %s for constant string literals w/o special characters inside. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 454bbe2fb41f..64d02ca60f53 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1038,8 +1038,7 @@ static int pca953x_remove(struct i2c_client *client) ret = pdata->teardown(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) - dev_err(&client->dev, "%s failed, %d\n", - "teardown", ret); + dev_err(&client->dev, "teardown failed, %d\n", ret); } else { ret = 0; } -- GitLab From 23b6904442d08b7dbed7622ed33b236d41a3aa8b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 31 Jul 2019 14:43:40 +0200 Subject: [PATCH 1656/7155] driver core: add dev_groups to all drivers Add the ability for the driver core to create and remove a list of attribute groups automatically when the device is bound/unbound from a specific driver. Signed-off-by: Dmitry Torokhov Tested-by: Richard Gong Link: https://lore.kernel.org/r/20190731124349.4474-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 14 ++++++++++++++ include/linux/device.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 994a90747420..d811e60610d3 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -554,9 +554,16 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto probe_failed; } + if (device_add_groups(dev, drv->dev_groups)) { + dev_err(dev, "device_add_groups() failed\n"); + goto dev_groups_failed; + } + if (test_remove) { test_remove = false; + device_remove_groups(dev, drv->dev_groups); + if (dev->bus->remove) dev->bus->remove(dev); else if (drv->remove) @@ -584,6 +591,11 @@ static int really_probe(struct device *dev, struct device_driver *drv) drv->bus->name, __func__, dev_name(dev), drv->name); goto done; +dev_groups_failed: + if (dev->bus->remove) + dev->bus->remove(dev); + else if (drv->remove) + drv->remove(dev); probe_failed: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, @@ -1114,6 +1126,8 @@ static void __device_release_driver(struct device *dev, struct device *parent) pm_runtime_put_sync(dev); + device_remove_groups(dev, drv->dev_groups); + if (dev->bus && dev->bus->remove) dev->bus->remove(dev); else if (drv->remove) diff --git a/include/linux/device.h b/include/linux/device.h index c330b75c6c57..98c00b71b598 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -262,6 +262,8 @@ enum probe_type { * @resume: Called to bring a device from sleep mode. * @groups: Default attributes that get created by the driver core * automatically. + * @dev_groups: Additional attributes attached to device instance once the + * it is bound to the driver. * @pm: Power management operations of the device which matched * this driver. * @coredump: Called when sysfs entry is written to. The device driver @@ -296,6 +298,7 @@ struct device_driver { int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; + const struct attribute_group **dev_groups; const struct dev_pm_ops *pm; void (*coredump) (struct device *dev); -- GitLab From 0682e005d1705a740a36860cc75199a411f46025 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:41 +0200 Subject: [PATCH 1657/7155] uio: uio_fsl_elbc_gpcm: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a sysfs group of attributes. Link: https://lore.kernel.org/r/20190731124349.4474-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_fsl_elbc_gpcm.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/uio/uio_fsl_elbc_gpcm.c b/drivers/uio/uio_fsl_elbc_gpcm.c index 450e2f5c9b43..be8a6905f507 100644 --- a/drivers/uio/uio_fsl_elbc_gpcm.c +++ b/drivers/uio/uio_fsl_elbc_gpcm.c @@ -71,6 +71,13 @@ static ssize_t reg_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(reg_br, 0664, reg_show, reg_store); static DEVICE_ATTR(reg_or, 0664, reg_show, reg_store); +static struct attribute *uio_fsl_elbc_gpcm_attrs[] = { + &dev_attr_reg_br.attr, + &dev_attr_reg_or.attr, + NULL, +}; +ATTRIBUTE_GROUPS(uio_fsl_elbc_gpcm); + static ssize_t reg_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -411,25 +418,12 @@ static int uio_fsl_elbc_gpcm_probe(struct platform_device *pdev) /* store private data */ platform_set_drvdata(pdev, info); - /* create sysfs files */ - ret = device_create_file(priv->dev, &dev_attr_reg_br); - if (ret) - goto out_err3; - ret = device_create_file(priv->dev, &dev_attr_reg_or); - if (ret) - goto out_err4; - dev_info(priv->dev, "eLBC/GPCM device (%s) at 0x%llx, bank %d, irq=%d\n", priv->name, (unsigned long long)res.start, priv->bank, irq != NO_IRQ ? irq : -1); return 0; -out_err4: - device_remove_file(priv->dev, &dev_attr_reg_br); -out_err3: - platform_set_drvdata(pdev, NULL); - uio_unregister_device(info); out_err2: if (priv->shutdown) priv->shutdown(info, true); @@ -448,8 +442,6 @@ static int uio_fsl_elbc_gpcm_remove(struct platform_device *pdev) struct uio_info *info = platform_get_drvdata(pdev); struct fsl_elbc_gpcm *priv = info->priv; - device_remove_file(priv->dev, &dev_attr_reg_or); - device_remove_file(priv->dev, &dev_attr_reg_br); platform_set_drvdata(pdev, NULL); uio_unregister_device(info); if (priv->shutdown) @@ -474,6 +466,7 @@ static struct platform_driver uio_fsl_elbc_gpcm_driver = { .driver = { .name = "fsl,elbc-gpcm-uio", .of_match_table = uio_fsl_elbc_gpcm_match, + .dev_groups = uio_fsl_elbc_gpcm_groups, }, .probe = uio_fsl_elbc_gpcm_probe, .remove = uio_fsl_elbc_gpcm_remove, -- GitLab From cf9441adb1a35506d7606866c382b9d8614169b5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:49 -0700 Subject: [PATCH 1658/7155] ASoC: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: alsa-devel@alsa-project.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-50-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 7 ++----- sound/soc/atmel/atmel-pdmic.c | 7 ++----- sound/soc/bcm/cygnus-ssp.c | 7 ++----- sound/soc/codecs/msm8916-wcd-analog.c | 12 +++--------- sound/soc/codecs/twl6040.c | 4 +--- sound/soc/fsl/fsl_asrc.c | 4 +--- sound/soc/fsl/fsl_esai.c | 4 +--- sound/soc/fsl/fsl_sai.c | 4 +--- sound/soc/fsl/fsl_spdif.c | 4 +--- sound/soc/fsl/fsl_ssi.c | 4 +--- sound/soc/fsl/imx-ssi.c | 4 +--- sound/soc/kirkwood/kirkwood-i2s.c | 4 +--- sound/soc/mediatek/common/mtk-btcvsd.c | 4 +--- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 4 +--- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 4 +--- sound/soc/mxs/mxs-saif.c | 8 ++------ sound/soc/qcom/lpass-platform.c | 5 +---- sound/soc/sof/intel/bdw.c | 5 +---- sound/soc/sof/intel/byt.c | 5 +---- sound/soc/sprd/sprd-mcdt.c | 4 +--- sound/soc/sti/sti_uniperif.c | 4 +--- sound/soc/stm/stm32_i2s.c | 5 +---- sound/soc/stm/stm32_sai.c | 4 +--- sound/soc/stm/stm32_spdifrx.c | 4 +--- sound/soc/sunxi/sun4i-i2s.c | 4 +--- sound/soc/uniphier/aio-dma.c | 4 +--- sound/soc/xilinx/xlnx_formatter_pcm.c | 2 -- sound/soc/xtensa/xtfpga-i2s.c | 1 - 28 files changed, 32 insertions(+), 100 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 0f2c574f27f1..e98601eccfa3 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -571,11 +571,8 @@ static int atmel_classd_probe(struct platform_device *pdev) dd->pdata = pdata; dd->irq = platform_get_irq(pdev, 0); - if (dd->irq < 0) { - ret = dd->irq; - dev_err(dev, "failed to could not get irq: %d\n", ret); - return ret; - } + if (dd->irq < 0) + return dd->irq; dd->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dd->pclk)) { diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index e09c28349e0d..04ec6f0af179 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -612,11 +612,8 @@ static int atmel_pdmic_probe(struct platform_device *pdev) dd->dev = dev; dd->irq = platform_get_irq(pdev, 0); - if (dd->irq < 0) { - ret = dd->irq; - dev_err(dev, "failed to get irq: %d\n", ret); - return ret; - } + if (dd->irq < 0) + return dd->irq; dd->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dd->pclk)) { diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index b7c358b48d8d..2f9357d7da96 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1342,11 +1342,8 @@ static int cygnus_ssp_probe(struct platform_device *pdev) } cygaud->irq_num = platform_get_irq(pdev, 0); - if (cygaud->irq_num <= 0) { - dev_err(dev, "platform_get_irq failed\n"); - err = cygaud->irq_num; - return err; - } + if (cygaud->irq_num <= 0) + return cygaud->irq_num; err = audio_clk_init(pdev, cygaud); if (err) { diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 368b6c09474b..667e9f73aba3 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -1185,10 +1185,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) } irq = platform_get_irq_byname(pdev, "mbhc_switch_int"); - if (irq < 0) { - dev_err(dev, "failed to get mbhc switch irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_mbhc_switch_irq_handler, @@ -1200,10 +1198,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) if (priv->mbhc_btn_enabled) { irq = platform_get_irq_byname(pdev, "mbhc_but_press_det"); - if (irq < 0) { - dev_err(dev, "failed to get button press irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, mbhc_btn_press_irq_handler, @@ -1214,10 +1210,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) dev_err(dev, "cannot request mbhc button press irq\n"); irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det"); - if (irq < 0) { - dev_err(dev, "failed to get button release irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, mbhc_btn_release_irq_handler, diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 472c2fff34a8..f34637afee51 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1108,10 +1108,8 @@ static int twl6040_probe(struct snd_soc_component *component) priv->component = component; priv->plug_irq = platform_get_irq(pdev, 0); - if (priv->plug_irq < 0) { - dev_err(component->dev, "invalid irq: %d\n", priv->plug_irq); + if (priv->plug_irq < 0) return priv->plug_irq; - } INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index cbbf6257f08a..cfa40ef6b1ca 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -885,10 +885,8 @@ static int fsl_asrc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, dev_name(&pdev->dev), asrc_priv); diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 4ce8ac769244..5832144beb9f 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -962,10 +962,8 @@ static int fsl_esai_probe(struct platform_device *pdev) PTR_ERR(esai_priv->spbaclk)); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, esai_priv->name, esai_priv); diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 6d3c6c8d50ce..8f4d9fa95599 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -831,10 +831,8 @@ static int fsl_sai_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai); if (ret) { diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4842e6df9a2d..7858a5499ac5 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1248,10 +1248,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, dev_name(&pdev->dev), spdif_priv); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index fa862af25c1a..b0a6fead1a6a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1510,10 +1510,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) } ssi->irq = platform_get_irq(pdev, 0); - if (ssi->irq < 0) { - dev_err(dev, "no irq for node %s\n", pdev->name); + if (ssi->irq < 0) return ssi->irq; - } /* Set software limitations for synchronous mode except AC97 */ if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) { diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 9038b61317be..42031ba7da31 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -520,10 +520,8 @@ static int imx_ssi_probe(struct platform_device *pdev) } ssi->irq = platform_get_irq(pdev, 0); - if (ssi->irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", ssi->irq); + if (ssi->irq < 0) return ssi->irq; - } ssi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi->clk)) { diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 5076ec4cc7a6..61226fefe1c4 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -537,10 +537,8 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) return PTR_ERR(priv->io); priv->irq = platform_get_irq(pdev, 0); - if (priv->irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed: %d\n", priv->irq); + if (priv->irq < 0) return priv->irq; - } if (np) { priv->burst = 128; /* might be 32 or 128 */ diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index c7a81c4be068..d00608c73c6e 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -1335,10 +1335,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) /* irq */ irq_id = platform_get_irq(pdev, 0); - if (irq_id <= 0) { - dev_err(dev, "%pOFn no irq found\n", dev->of_node); + if (irq_id <= 0) return irq_id < 0 ? irq_id : -ENXIO; - } ret = devm_request_irq(dev, irq_id, mtk_btcvsd_snd_irq_handler, IRQF_TRIGGER_LOW, "BTCVSD_ISR_Handle", diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 7064a9fd6f74..9af76ae315a5 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -1342,10 +1342,8 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) return -ENOMEM; irq_id = platform_get_irq_byname(pdev, "asys"); - if (irq_id < 0) { - dev_err(dev, "unable to get ASYS IRQ\n"); + if (irq_id < 0) return irq_id; - } ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 90bd2c92cae7..0ee29255e731 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1074,10 +1074,8 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) afe->dev = &pdev->dev; irq_id = platform_get_irq(pdev, 0); - if (irq_id <= 0) { - dev_err(afe->dev, "np %pOFn no irq\n", afe->dev->of_node); + if (irq_id <= 0) return irq_id < 0 ? irq_id : -ENXIO; - } ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, 0, "Afe_ISR_Handle", (void *)afe); if (ret) { diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index a2c79426513b..1e38ce858326 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -790,12 +790,8 @@ static int mxs_saif_probe(struct platform_device *pdev) return PTR_ERR(saif->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - dev_err(&pdev->dev, "failed to get irq resource: %d\n", - ret); - return ret; - } + if (irq < 0) + return irq; saif->dev = &pdev->dev; ret = devm_request_irq(&pdev->dev, irq, mxs_saif_irq, 0, diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index cf7a299f4547..4c745baa39f7 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -564,11 +564,8 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) int ret; drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); - if (drvdata->lpaif_irq < 0) { - dev_err(&pdev->dev, "error getting irq handle: %d\n", - drvdata->lpaif_irq); + if (drvdata->lpaif_irq < 0) return -ENODEV; - } /* ensure audio hardware is disabled */ ret = regmap_write(drvdata->lpaif_map, diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 70d524ef9bc0..4bb9636da990 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -613,11 +613,8 @@ static int bdw_probe(struct snd_sof_dev *sdev) /* register our IRQ */ sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); - if (sdev->ipc_irq < 0) { - dev_err(sdev->dev, "error: failed to get IRQ at index %d\n", - desc->irqindex_host_ipc); + if (sdev->ipc_irq < 0) return sdev->ipc_irq; - } dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 107d711efc3f..000d576f6a8d 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -728,11 +728,8 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev) irq: /* register our IRQ */ sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); - if (sdev->ipc_irq < 0) { - dev_err(sdev->dev, "error: failed to get IRQ at index %d\n", - desc->irqindex_host_ipc); + if (sdev->ipc_irq < 0) return sdev->ipc_irq; - } dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index 7448015a4935..f439e5503a3c 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -959,10 +959,8 @@ static int sprd_mcdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mcdt); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get MCDT interrupt\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, sprd_mcdt_irq_handler, 0, "sprd-mcdt", mcdt); diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 645bcbe91601..ee4a0151e63e 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -426,10 +426,8 @@ static int sti_uniperiph_cpu_dai_of(struct device_node *node, UNIPERIF_FIFO_DATA_OFFSET(uni); uni->irq = platform_get_irq(priv->pdev, 0); - if (uni->irq < 0) { - dev_err(dev, "Failed to get IRQ resource\n"); + if (uni->irq < 0) return -ENXIO; - } uni->type = dev_data->type; diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index ba6452dab69b..3e7226a53e53 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -855,11 +855,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, /* Get irqs */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, dev_name(&pdev->dev), i2s); diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 1ac5103cea78..ef4273361d0d 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -193,10 +193,8 @@ static int stm32_sai_probe(struct platform_device *pdev) /* init irqs */ sai->irq = platform_get_irq(pdev, 0); - if (sai->irq < 0) { - dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); + if (sai->irq < 0) return sai->irq; - } /* reset */ rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index ee71b898897b..cd4b235fce57 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -909,10 +909,8 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, } spdifrx->irq = platform_get_irq(pdev, 0); - if (spdifrx->irq < 0) { - dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); + if (spdifrx->irq < 0) return spdifrx->irq; - } return 0; } diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 9b2232908b65..d97d694c48df 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1087,10 +1087,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev) return PTR_ERR(regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Can't retrieve our interrupt\n"); + if (irq < 0) return irq; - } i2s->variant = of_device_get_match_data(&pdev->dev); if (!i2s->variant) { diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index 862346d66774..e8446cc4e8f8 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -289,10 +289,8 @@ int uniphier_aiodma_soc_register_platform(struct platform_device *pdev) return PTR_ERR(chip->regmap); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "Could not get irq.\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, aiodma_irq, IRQF_SHARED, dev_name(dev), pdev); diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c index dc8721f4f56b..48970efe7838 100644 --- a/sound/soc/xilinx/xlnx_formatter_pcm.c +++ b/sound/soc/xilinx/xlnx_formatter_pcm.c @@ -613,7 +613,6 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev) aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev, "irq_mm2s"); if (aud_drv_data->mm2s_irq < 0) { - dev_err(dev, "xlnx audio mm2s irq resource failed\n"); ret = aud_drv_data->mm2s_irq; goto clk_err; } @@ -640,7 +639,6 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev) aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev, "irq_s2mm"); if (aud_drv_data->s2mm_irq < 0) { - dev_err(dev, "xlnx audio s2mm irq resource failed\n"); ret = aud_drv_data->s2mm_irq; goto clk_err; } diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 9da395d14a8d..efd374f114a0 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -570,7 +570,6 @@ static int xtfpga_i2s_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); err = irq; goto err; } -- GitLab From 47241933b43dec5b10d067e6e094f4d31a1cf3e7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:37 -0700 Subject: [PATCH 1659/7155] regulator: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Liam Girdwood Cc: Mark Brown Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-38-swboyd@chromium.org Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 4 +--- drivers/regulator/da9063-regulator.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 2ffc64622451..56f3f72d7707 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -1032,10 +1032,8 @@ static int da9062_regulator_probe(struct platform_device *pdev) /* LDOs overcurrent event support */ irq = platform_get_irq_byname(pdev, "LDO_LIM"); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ.\n"); + if (irq < 0) return irq; - } regulators->irq_ldo_lim = irq; ret = devm_request_threaded_irq(&pdev->dev, irq, diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 02f816318fba..28b1b20f45bd 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -863,10 +863,8 @@ static int da9063_regulator_probe(struct platform_device *pdev) /* LDOs overcurrent event support */ irq = platform_get_irq_byname(pdev, "LDO_LIM"); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ.\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, da9063_ldo_lim_event, -- GitLab From 4ff13d00ebd5533947b083c66d44da3243a2d559 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Aug 2019 13:13:53 +0200 Subject: [PATCH 1660/7155] spi: Reduce kthread priority The SPI thingies request FIFO-99 by default, reduce this to FIFO-50. FIFO-99 is the very highest priority available to SCHED_FIFO and it not a suitable default; it would indicate the SPI work is the most important work on the machine. Cc: Benson Leung Cc: Enric Balletbo i Serra Cc: Guenter Roeck Cc: Mark Brown Cc: linux-spi@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20190801111541.917256884@infradead.org Signed-off-by: Mark Brown --- drivers/platform/chrome/cros_ec_spi.c | 2 +- drivers/spi/spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 006a8ff64057..714306bc3f79 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -706,7 +706,7 @@ static int cros_ec_spi_devm_high_pri_alloc(struct device *dev, struct cros_ec_spi *ec_spi) { struct sched_param sched_priority = { - .sched_priority = MAX_RT_PRIO - 1, + .sched_priority = MAX_RT_PRIO / 2, }; int err; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9fd7926e80c0..8e83c9567353 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1434,7 +1434,7 @@ static void spi_pump_messages(struct kthread_work *work) */ static void spi_set_thread_rt(struct spi_controller *ctlr) { - struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 }; dev_info(&ctlr->dev, "will run message pump with realtime priority\n"); -- GitLab From 6b8ac10e0dd4b49eda513c1aa5045b3b1660d350 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:41 -0700 Subject: [PATCH 1661/7155] spi: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Mark Brown Cc: linux-spi@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-42-swboyd@chromium.org Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 1 - drivers/spi/spi-armada-3700.c | 1 - drivers/spi/spi-bcm2835.c | 1 - drivers/spi/spi-bcm2835aux.c | 1 - drivers/spi/spi-bcm63xx-hsspi.c | 4 +--- drivers/spi/spi-bcm63xx.c | 4 +--- drivers/spi/spi-cadence.c | 1 - drivers/spi/spi-dw-mmio.c | 4 +--- drivers/spi/spi-efm32.c | 4 +--- drivers/spi/spi-ep93xx.c | 4 +--- drivers/spi/spi-fsl-dspi.c | 1 - drivers/spi/spi-fsl-qspi.c | 4 +--- drivers/spi/spi-geni-qcom.c | 4 +--- drivers/spi/spi-lantiq-ssc.c | 12 +++--------- drivers/spi/spi-mt65xx.c | 1 - drivers/spi/spi-npcm-pspi.c | 1 - drivers/spi/spi-nuc900.c | 1 - drivers/spi/spi-nxp-fspi.c | 4 +--- drivers/spi/spi-pic32-sqi.c | 1 - drivers/spi/spi-pic32.c | 12 +++--------- drivers/spi/spi-qcom-qspi.c | 4 +--- drivers/spi/spi-s3c24xx.c | 1 - drivers/spi/spi-sh-msiof.c | 1 - drivers/spi/spi-sh.c | 4 +--- drivers/spi/spi-sifive.c | 1 - drivers/spi/spi-slave-mt27xx.c | 1 - drivers/spi/spi-sprd.c | 4 +--- drivers/spi/spi-stm32-qspi.c | 5 +---- drivers/spi/spi-sun4i.c | 1 - drivers/spi/spi-sun6i.c | 1 - drivers/spi/spi-synquacer.c | 2 -- drivers/spi/spi-ti-qspi.c | 1 - drivers/spi/spi-uniphier.c | 1 - drivers/spi/spi-xlp.c | 4 +--- drivers/spi/spi-zynq-qspi.c | 1 - drivers/spi/spi-zynqmp-gqspi.c | 1 - 36 files changed, 19 insertions(+), 80 deletions(-) diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 6a7d7b553d95..fd8007ebb145 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -526,7 +526,6 @@ static int atmel_qspi_probe(struct platform_device *pdev) /* Request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "missing IRQ\n"); err = irq; goto disable_qspick; } diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 032888344822..119ae87cc26e 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -864,7 +864,6 @@ static int a3700_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "could not get irq: %d\n", irq); ret = -ENXIO; goto error; } diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 6f243a90c844..c96797844688 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1015,7 +1015,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_controller_put; } diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index bb57035c5770..b18ce69c0375 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -540,7 +540,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_master_put; } diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 9a06ffdb73b8..373cb53579e0 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -338,10 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res_mem); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index df1c94a131e6..fdd7eaa0b8ed 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -520,10 +520,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } clk = devm_clk_get(dev, "spi"); if (IS_ERR(clk)) { diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 7c41e4e82849..1c35eaaac838 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -540,7 +540,6 @@ static int cdns_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq number is invalid\n"); goto clk_dis_all; } diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4fa7e7a52ebd..edb3cf6be201 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -156,10 +156,8 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) } dws->irq = platform_get_irq(pdev, 0); - if (dws->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (dws->irq < 0) return dws->irq; /* -ENXIO */ - } dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index eb1f2142a335..64d4c441b641 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -400,10 +400,8 @@ static int efm32_spi_probe(struct platform_device *pdev) } ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret); + if (ret <= 0) goto err; - } ddata->rxirq = ret; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4034e3ec0ba2..4e1ccd4e52b6 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -656,10 +656,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resources\n"); + if (irq < 0) return -EBUSY; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 53335ccc98f6..96eacbe6ae27 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1105,7 +1105,6 @@ static int dspi_probe(struct platform_device *pdev) dspi_init(dspi); dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { - dev_err(&pdev->dev, "can't get platform irq\n"); ret = dspi->irq; goto out_clk_put; } diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 41a49b93ca60..443d4c1196c2 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -860,10 +860,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 5f0b0d5bfef4..242b6c86cf12 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -539,10 +539,8 @@ static int spi_geni_probe(struct platform_device *pdev) struct clk *clk; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Err getting IRQ %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 8f01858c0ae6..9dfe8b04e688 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -819,22 +819,16 @@ static int lantiq_ssc_probe(struct platform_device *pdev) } rx_irq = platform_get_irq_byname(pdev, LTQ_SPI_RX_IRQ_NAME); - if (rx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_RX_IRQ_NAME); + if (rx_irq < 0) return -ENXIO; - } tx_irq = platform_get_irq_byname(pdev, LTQ_SPI_TX_IRQ_NAME); - if (tx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_TX_IRQ_NAME); + if (tx_irq < 0) return -ENXIO; - } err_irq = platform_get_irq_byname(pdev, LTQ_SPI_ERR_IRQ_NAME); - if (err_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_ERR_IRQ_NAME); + if (err_irq < 0) return -ENXIO; - } master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi)); if (!master) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 45d8a7048b6c..1f5f716016a2 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -664,7 +664,6 @@ static int mtk_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_master; } diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 734a2b956959..5c56caea04f0 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -388,7 +388,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 37e2034ad4d5..f65a029e3fe9 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -367,7 +367,6 @@ static int nuc900_spi_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); err = -ENOENT; goto err_pdata; } diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 8894f98cc99c..501b923f2c27 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -1007,10 +1007,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, nxp_fspi_irq_handler, 0, pdev->name, f); diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index b635526ad414..11b692923fd7 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -590,7 +590,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) /* irq */ sqi->irq = platform_get_irq(pdev, 0); if (sqi->irq < 0) { - dev_err(&pdev->dev, "no irq found\n"); ret = sqi->irq; goto err_free_master; } diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 10cebeaa1e6b..69f517ec59c6 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -711,22 +711,16 @@ static int pic32_spi_hw_probe(struct platform_device *pdev, /* get irq resources: err-irq, rx-irq, tx-irq */ pic32s->fault_irq = platform_get_irq_byname(pdev, "fault"); - if (pic32s->fault_irq < 0) { - dev_err(&pdev->dev, "fault-irq not found\n"); + if (pic32s->fault_irq < 0) return pic32s->fault_irq; - } pic32s->rx_irq = platform_get_irq_byname(pdev, "rx"); - if (pic32s->rx_irq < 0) { - dev_err(&pdev->dev, "rx-irq not found\n"); + if (pic32s->rx_irq < 0) return pic32s->rx_irq; - } pic32s->tx_irq = platform_get_irq_byname(pdev, "tx"); - if (pic32s->tx_irq < 0) { - dev_err(&pdev->dev, "tx-irq not found\n"); + if (pic32s->tx_irq < 0) return pic32s->tx_irq; - } /* get clock */ pic32s->clk = devm_clk_get(&pdev->dev, "mck0"); diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index e0f061139c8f..a0ad73f1cc01 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -454,10 +454,8 @@ static int qcom_qspi_probe(struct platform_device *pdev) goto exit_probe_master_put; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Failed to get irq %d\n", ret); + if (ret < 0) goto exit_probe_master_put; - } ret = devm_request_irq(dev, ret, qcom_qspi_irq, IRQF_TRIGGER_HIGH, dev_name(dev), ctrl); if (ret) { diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 48d8dff05a3a..aea8fd98a31f 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -545,7 +545,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); err = -ENOENT; goto err_no_pdata; } diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index b50bdbc27e58..f73f811c9ba7 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1346,7 +1346,6 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) i = platform_get_irq(pdev, 0); if (i < 0) { - dev_err(&pdev->dev, "cannot get IRQ\n"); ret = i; goto err1; } diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index f1ee58208216..20bdae5fdf3b 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -437,10 +437,8 @@ static int spi_sh_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq error: %d\n", irq); + if (irq < 0) return irq; - } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); if (master == NULL) { diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 93ec2c6cdbfd..5bf2b57e6929 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -323,7 +323,6 @@ static int sifive_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "Unable to find interrupt\n"); ret = irq; goto put_master; } diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index d1075433f6a6..61bc43b0fe57 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -410,7 +410,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_ctlr; } diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 1b7eebb72c07..8c9021b7f7a9 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -843,10 +843,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss) int ret; ss->irq = platform_get_irq(pdev, 0); - if (ss->irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (ss->irq < 0) return ss->irq; - } ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq, 0, pdev->name, ss); diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 655e4afbfb2a..9ac6f9fe13cf 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -570,11 +570,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "IRQ error missing or invalid\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, dev_name(dev), qspi); diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 5194bc07fd60..92e5c667b6a1 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -449,7 +449,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index ee2bdaf5b856..1cf3051bba5e 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -456,7 +456,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index f99abd85c50a..ae17c99cce03 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) rx_irq = platform_get_irq(pdev, 0); if (rx_irq <= 0) { - dev_err(&pdev->dev, "get rx_irq failed (%d)\n", rx_irq); ret = rx_irq; goto put_spi; } @@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) tx_irq = platform_get_irq(pdev, 1); if (tx_irq <= 0) { - dev_err(&pdev->dev, "get tx_irq failed (%d)\n", tx_irq); ret = tx_irq; goto put_spi; } diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 6ca600702470..3cb65371ae3b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -717,7 +717,6 @@ static int ti_qspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); ret = irq; goto free_master; } diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index b32c77df5d49..c1e6f3245557 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -454,7 +454,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c index 1dc479fab98c..4eb5bc9250fc 100644 --- a/drivers/spi/spi-xlp.c +++ b/drivers/spi/spi-xlp.c @@ -384,10 +384,8 @@ static int xlp_spi_probe(struct platform_device *pdev) return PTR_ERR(xspi->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq); + if (irq < 0) return irq; - } err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0, pdev->name, xspi); if (err) { diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index c6bee67decb5..3155e2cabb1e 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -671,7 +671,6 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq resource not found\n"); goto remove_master; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 07a83ca164c2..5e9ea8a38163 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1077,7 +1077,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(dev, "irq resource not found\n"); goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq, -- GitLab From 3c0448d507d42605ab6811bcd61c1cd94390d2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 1 Aug 2019 22:47:10 +0200 Subject: [PATCH 1662/7155] spi: atmel: add tracing to custom .transfer_one_message callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver specific implementations for .transfer_one_message need to call the tracing stuff themself. This is necessary to make spi tracing actually useful. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190801204710.27309-1-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index f00b367523cd..acf318e7330c 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -23,6 +23,7 @@ #include #include #include +#include /* SPI register offsets */ #define SPI_CR 0x0000 @@ -1409,9 +1410,13 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, msg->actual_length = 0; list_for_each_entry(xfer, &msg->transfers, transfer_list) { + trace_spi_transfer_start(msg, xfer); + ret = atmel_spi_one_transfer(master, msg, xfer); if (ret) goto msg_done; + + trace_spi_transfer_stop(msg, xfer); } if (as->use_pdc) -- GitLab From 43b9ac937be6f2afb2f0cf060d40cea365c09d07 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:44 +0200 Subject: [PATCH 1663/7155] firmware: arm_scpi: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a sysfs group of attributes. Acked-by: Sudeep Holla Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/arm_scpi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 725164b83242..a80c331c3a6e 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -1011,10 +1011,6 @@ static int scpi_probe(struct platform_device *pdev) scpi_info->firmware_version)); scpi_info->scpi_ops = &scpi_ops; - ret = devm_device_add_groups(dev, versions_groups); - if (ret) - dev_err(dev, "unable to create sysfs version group\n"); - return devm_of_platform_populate(dev); } @@ -1030,6 +1026,7 @@ static struct platform_driver scpi_driver = { .driver = { .name = "scpi_protocol", .of_match_table = scpi_of_match, + .dev_groups = versions_groups, }, .probe = scpi_probe, .remove = scpi_remove, -- GitLab From 0abd02ede7dfd0f3ea7a6ac68e00ca6946827889 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:47 +0200 Subject: [PATCH 1664/7155] video: fbdev: wm8505fb: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a sysfs file. Cc: Tony Prisk Cc: Bartlomiej Zolnierkiewicz Cc: linux-arm-kernel@lists.infradead.org Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-9-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbdev/wm8505fb.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c index ff752635a31c..17c780315ca5 100644 --- a/drivers/video/fbdev/wm8505fb.c +++ b/drivers/video/fbdev/wm8505fb.c @@ -176,6 +176,12 @@ static ssize_t contrast_store(struct device *dev, static DEVICE_ATTR_RW(contrast); +static struct attribute *wm8505fb_attrs[] = { + &dev_attr_contrast.attr, + NULL, +}; +ATTRIBUTE_GROUPS(wm8505fb); + static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) { chan &= 0xffff; @@ -361,10 +367,6 @@ static int wm8505fb_probe(struct platform_device *pdev) return ret; } - ret = device_create_file(&pdev->dev, &dev_attr_contrast); - if (ret < 0) - fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret); - fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n", fbi->fb.fix.id, fbi->fb.fix.smem_start, fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); @@ -376,8 +378,6 @@ static int wm8505fb_remove(struct platform_device *pdev) { struct wm8505fb_info *fbi = platform_get_drvdata(pdev); - device_remove_file(&pdev->dev, &dev_attr_contrast); - unregister_framebuffer(&fbi->fb); writel(0, fbi->regbase); @@ -399,6 +399,7 @@ static struct platform_driver wm8505fb_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = wmt_dt_ids, + .dev_groups = wm8505fb_groups, }, }; -- GitLab From e14018cc34d633a55e8fabd2085f1da51d6c60fb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:48 +0200 Subject: [PATCH 1665/7155] video: fbdev: w100fb: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a bunch of sysfs files. Cc: Tony Prisk Cc: linux-arm-kernel@lists.infradead.org Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-10-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbdev/w100fb.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c index 597ffaa13cd2..3be07807edcd 100644 --- a/drivers/video/fbdev/w100fb.c +++ b/drivers/video/fbdev/w100fb.c @@ -164,6 +164,15 @@ static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *att static DEVICE_ATTR_RW(fastpllclk); +static struct attribute *w100fb_attrs[] = { + &dev_attr_fastpllclk.attr, + &dev_attr_reg_read.attr, + &dev_attr_reg_write.attr, + &dev_attr_flip.attr, + NULL, +}; +ATTRIBUTE_GROUPS(w100fb); + /* * Some touchscreens need hsync information from the video driver to * function correctly. We export it here. @@ -752,14 +761,6 @@ int w100fb_probe(struct platform_device *pdev) goto out; } - err = device_create_file(&pdev->dev, &dev_attr_fastpllclk); - err |= device_create_file(&pdev->dev, &dev_attr_reg_read); - err |= device_create_file(&pdev->dev, &dev_attr_reg_write); - err |= device_create_file(&pdev->dev, &dev_attr_flip); - - if (err != 0) - fb_warn(info, "failed to register attributes (%d)\n", err); - fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; out: @@ -784,11 +785,6 @@ static int w100fb_remove(struct platform_device *pdev) struct fb_info *info = platform_get_drvdata(pdev); struct w100fb_par *par=info->par; - device_remove_file(&pdev->dev, &dev_attr_fastpllclk); - device_remove_file(&pdev->dev, &dev_attr_reg_read); - device_remove_file(&pdev->dev, &dev_attr_reg_write); - device_remove_file(&pdev->dev, &dev_attr_flip); - unregister_framebuffer(info); vfree(par->saved_intmem); @@ -1625,6 +1621,7 @@ static struct platform_driver w100fb_driver = { .resume = w100fb_resume, .driver = { .name = "w100fb", + .dev_groups = w100fb_groups, }, }; -- GitLab From de3dacf0347e3dc6f63cd5abe944bc60077c5abf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:49 +0200 Subject: [PATCH 1666/7155] video: fbdev: sm501fb: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a bunch of sysfs files. Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-11-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbdev/sm501fb.c | 37 +++++++++-------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index 6edb4492e675..3dd1b1d76e98 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1271,6 +1271,14 @@ static ssize_t sm501fb_debug_show_pnl(struct device *dev, static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); +static struct attribute *sm501fb_attrs[] = { + &dev_attr_crt_src.attr, + &dev_attr_fbregs_pnl.attr, + &dev_attr_fbregs_crt.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sm501fb); + /* acceleration operations */ static int sm501fb_sync(struct fb_info *info) { @@ -2011,33 +2019,9 @@ static int sm501fb_probe(struct platform_device *pdev) goto err_started_crt; } - /* create device files */ - - ret = device_create_file(dev, &dev_attr_crt_src); - if (ret) - goto err_started_panel; - - ret = device_create_file(dev, &dev_attr_fbregs_pnl); - if (ret) - goto err_attached_crtsrc_file; - - ret = device_create_file(dev, &dev_attr_fbregs_crt); - if (ret) - goto err_attached_pnlregs_file; - /* we registered, return ok */ return 0; -err_attached_pnlregs_file: - device_remove_file(dev, &dev_attr_fbregs_pnl); - -err_attached_crtsrc_file: - device_remove_file(dev, &dev_attr_crt_src); - -err_started_panel: - unregister_framebuffer(info->fb[HEAD_PANEL]); - sm501_free_init_fb(info, HEAD_PANEL); - err_started_crt: unregister_framebuffer(info->fb[HEAD_CRT]); sm501_free_init_fb(info, HEAD_CRT); @@ -2067,10 +2051,6 @@ static int sm501fb_remove(struct platform_device *pdev) struct fb_info *fbinfo_crt = info->fb[0]; struct fb_info *fbinfo_pnl = info->fb[1]; - device_remove_file(&pdev->dev, &dev_attr_fbregs_crt); - device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); - device_remove_file(&pdev->dev, &dev_attr_crt_src); - sm501_free_init_fb(info, HEAD_CRT); sm501_free_init_fb(info, HEAD_PANEL); @@ -2234,6 +2214,7 @@ static struct platform_driver sm501fb_driver = { .resume = sm501fb_resume, .driver = { .name = "sm501-fb", + .dev_groups = sm501fb_groups, }, }; -- GitLab From 5bd08a4ae3d06cf598b91444c2d727aa25045bf0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:46 +0200 Subject: [PATCH 1667/7155] platform: x86: hp-wmi: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a bunch of sysfs files. Cc: Darren Hart Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: platform-driver-x86@vger.kernel.org Acked-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-8-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/hp-wmi.c | 47 +++++++++-------------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 2521e45280b8..6bcbbb375401 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -502,6 +502,17 @@ static DEVICE_ATTR_RO(dock); static DEVICE_ATTR_RO(tablet); static DEVICE_ATTR_RW(postcode); +static struct attribute *hp_wmi_attrs[] = { + &dev_attr_display.attr, + &dev_attr_hddtemp.attr, + &dev_attr_als.attr, + &dev_attr_dock.attr, + &dev_attr_tablet.attr, + &dev_attr_postcode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(hp_wmi); + static void hp_wmi_notify(u32 value, void *context) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -678,16 +689,6 @@ static void hp_wmi_input_destroy(void) input_unregister_device(hp_wmi_input_dev); } -static void cleanup_sysfs(struct platform_device *device) -{ - device_remove_file(&device->dev, &dev_attr_display); - device_remove_file(&device->dev, &dev_attr_hddtemp); - device_remove_file(&device->dev, &dev_attr_als); - device_remove_file(&device->dev, &dev_attr_dock); - device_remove_file(&device->dev, &dev_attr_tablet); - device_remove_file(&device->dev, &dev_attr_postcode); -} - static int __init hp_wmi_rfkill_setup(struct platform_device *device) { int err, wireless; @@ -858,8 +859,6 @@ static int __init hp_wmi_rfkill2_setup(struct platform_device *device) static int __init hp_wmi_bios_setup(struct platform_device *device) { - int err; - /* clear detected rfkill devices */ wifi_rfkill = NULL; bluetooth_rfkill = NULL; @@ -869,35 +868,12 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) if (hp_wmi_rfkill_setup(device)) hp_wmi_rfkill2_setup(device); - err = device_create_file(&device->dev, &dev_attr_display); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_hddtemp); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_als); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_dock); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_tablet); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_postcode); - if (err) - goto add_sysfs_error; return 0; - -add_sysfs_error: - cleanup_sysfs(device); - return err; } static int __exit hp_wmi_bios_remove(struct platform_device *device) { int i; - cleanup_sysfs(device); for (i = 0; i < rfkill2_count; i++) { rfkill_unregister(rfkill2[i].rfkill); @@ -966,6 +942,7 @@ static struct platform_driver hp_wmi_driver = { .driver = { .name = "hp-wmi", .pm = &hp_wmi_pm_ops, + .dev_groups = hp_wmi_groups, }, .remove = __exit_p(hp_wmi_bios_remove), }; -- GitLab From 0fbb93fce79b938643889862e74ee30213e1d5fe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 14:43:45 +0200 Subject: [PATCH 1668/7155] olpc: x01: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a lid sysfs file. Cc: Darren Hart Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: platform-driver-x86@vger.kernel.org Acked-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-7-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/olpc/olpc-xo1-sci.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 25ce1b3b0732..99a28ce2244c 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -157,6 +157,12 @@ static ssize_t lid_wake_mode_set(struct device *dev, static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show, lid_wake_mode_set); +static struct attribute *lid_attrs[] = { + &dev_attr_lid_wake_mode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(lid); + /* * Process all items in the EC's SCI queue. * @@ -510,17 +516,8 @@ static int setup_lid_switch(struct platform_device *pdev) goto err_register; } - r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode); - if (r) { - dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r); - goto err_create_attr; - } - return 0; -err_create_attr: - input_unregister_device(lid_switch_idev); - lid_switch_idev = NULL; err_register: input_free_device(lid_switch_idev); return r; @@ -528,7 +525,6 @@ static int setup_lid_switch(struct platform_device *pdev) static void free_lid_switch(void) { - device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode); input_unregister_device(lid_switch_idev); } @@ -624,6 +620,7 @@ static int xo1_sci_remove(struct platform_device *pdev) static struct platform_driver xo1_sci_driver = { .driver = { .name = "olpc-xo1-sci-acpi", + .dev_groups = lid_groups, }, .probe = xo1_sci_probe, .remove = xo1_sci_remove, -- GitLab From 29b24f6ca112d168ae17c66343464a2581c573e0 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:31 +0800 Subject: [PATCH 1669/7155] staging: erofs: update source file headers - Use the correct style for all SPDX License Identifiers; - Get rid of the unnecessary license boilerplate; - Use "GPL-2.0-only" instead of "GPL-2.0" suggested-by Stephen. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 2 +- drivers/staging/erofs/Makefile | 2 +- drivers/staging/erofs/compress.h | 2 +- drivers/staging/erofs/data.c | 6 +----- drivers/staging/erofs/decompressor.c | 2 +- drivers/staging/erofs/dir.c | 6 +----- drivers/staging/erofs/erofs_fs.h | 8 ++------ drivers/staging/erofs/include/linux/tagptr.h | 6 +++--- drivers/staging/erofs/include/trace/events/erofs.h | 2 +- drivers/staging/erofs/inode.c | 6 +----- drivers/staging/erofs/internal.h | 8 ++------ drivers/staging/erofs/namei.c | 6 +----- drivers/staging/erofs/super.c | 6 +----- drivers/staging/erofs/unzip_pagevec.h | 8 ++------ drivers/staging/erofs/unzip_vle.c | 6 +----- drivers/staging/erofs/unzip_vle.h | 8 ++------ drivers/staging/erofs/utils.c | 7 +------ drivers/staging/erofs/xattr.c | 6 +----- drivers/staging/erofs/xattr.h | 8 ++------ drivers/staging/erofs/zmap.c | 2 +- 20 files changed, 27 insertions(+), 80 deletions(-) diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index d04b798a8efb..2577cbb46a5b 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only config EROFS_FS tristate "EROFS filesystem support" diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile index e704d9e51514..3ade87e78d06 100644 --- a/drivers/staging/erofs/Makefile +++ b/drivers/staging/erofs/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only EROFS_VERSION = "1.0pre1" diff --git a/drivers/staging/erofs/compress.h b/drivers/staging/erofs/compress.h index c43aa3374d28..043013f9ef1b 100644 --- a/drivers/staging/erofs/compress.h +++ b/drivers/staging/erofs/compress.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * linux/drivers/staging/erofs/compress.h * diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index f73e4720cd3e..75b859e48084 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/data.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" #include diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index 1fb0abb98dff..b75524d0b322 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/decompressor.c * diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index dbf6a151886c..2fbfc4935077 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/dir.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index 9f61abb7c1ca..9cd749d56920 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ +/* * linux/drivers/staging/erofs/erofs_fs.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is dual-licensed; you may select either the GNU General Public - * License version 2 or Apache License, Version 2.0. See the file COPYING - * in the main directory of the Linux distribution for more details. */ #ifndef __EROFS_FS_H #define __EROFS_FS_H diff --git a/drivers/staging/erofs/include/linux/tagptr.h b/drivers/staging/erofs/include/linux/tagptr.h index ccd106dbd48e..b3f13773fb99 100644 --- a/drivers/staging/erofs/include/linux/tagptr.h +++ b/drivers/staging/erofs/include/linux/tagptr.h @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Tagged pointer implementation +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * A tagged pointer implementation * * Copyright (C) 2018 Gao Xiang */ diff --git a/drivers/staging/erofs/include/trace/events/erofs.h b/drivers/staging/erofs/include/trace/events/erofs.h index 660c92fc1803..bfb2da9c4eee 100644 --- a/drivers/staging/erofs/include/trace/events/erofs.h +++ b/drivers/staging/erofs/include/trace/events/erofs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #undef TRACE_SYSTEM #define TRACE_SYSTEM erofs diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 4c3d8bf8d249..c13d66ccc74a 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/inode.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "xattr.h" diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 0ebc294120c2..501429ec0f91 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/internal.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __INTERNAL_H #define __INTERNAL_H diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index fd3ae78d0ba5..50816b4c05fc 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/namei.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" #include "xattr.h" diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 3e2a65ba1945..38cd7a59750a 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/super.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include #include diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h index e65dbca93ae8..f07302c3c3f5 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/unzip_pagevec.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/unzip_pagevec.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_UNZIP_PAGEVEC_H #define __EROFS_UNZIP_PAGEVEC_H diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index 56c009cf611e..28a98e79c1e9 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/unzip_vle.c * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "unzip_vle.h" #include "compress.h" diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h index df91ad149439..d92515cd1c06 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/unzip_vle.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/unzip_vle.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_FS_UNZIP_VLE_H #define __EROFS_FS_UNZIP_VLE_H diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 4bbd3bf34acd..a68dbe375fa0 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -1,16 +1,11 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/utils.c * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ - #include "internal.h" #include diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index df40654b9fbb..b29177a17347 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/xattr.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include #include "xattr.h" diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 3990805dfc6c..fbcd57bdf886 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/xattr.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_XATTR_H #define __EROFS_XATTR_H diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 9c0bd65c46bf..205e884ca4e0 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/zmap.c * -- GitLab From 57b78c9fd9ce4df7281d36b0e642bee9b06a4071 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:32 +0800 Subject: [PATCH 1670/7155] staging: erofs: rename source files for better understanding Keep in line with erofs-outofstaging patchset as well, see https://lore.kernel.org/linux-fsdevel/20190725095658.155779-1-gaoxiang25@huawei.com/ Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Makefile | 2 +- drivers/staging/erofs/{include/linux => }/tagptr.h | 6 +++--- drivers/staging/erofs/{unzip_vle.c => zdata.c} | 4 ++-- drivers/staging/erofs/{unzip_vle.h => zdata.h} | 8 ++++---- drivers/staging/erofs/{unzip_pagevec.h => zpvec.h} | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) rename drivers/staging/erofs/{include/linux => }/tagptr.h (97%) rename drivers/staging/erofs/{unzip_vle.c => zdata.c} (99%) rename drivers/staging/erofs/{unzip_vle.h => zdata.h} (97%) rename drivers/staging/erofs/{unzip_pagevec.h => zpvec.h} (96%) diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile index 3ade87e78d06..5cdae21cb5af 100644 --- a/drivers/staging/erofs/Makefile +++ b/drivers/staging/erofs/Makefile @@ -9,5 +9,5 @@ obj-$(CONFIG_EROFS_FS) += erofs.o ccflags-y += -I $(srctree)/$(src)/include erofs-objs := super.o inode.o data.o namei.o dir.o utils.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o -erofs-$(CONFIG_EROFS_FS_ZIP) += unzip_vle.o zmap.o decompressor.o +erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o diff --git a/drivers/staging/erofs/include/linux/tagptr.h b/drivers/staging/erofs/tagptr.h similarity index 97% rename from drivers/staging/erofs/include/linux/tagptr.h rename to drivers/staging/erofs/tagptr.h index b3f13773fb99..a72897c86744 100644 --- a/drivers/staging/erofs/include/linux/tagptr.h +++ b/drivers/staging/erofs/tagptr.h @@ -4,8 +4,8 @@ * * Copyright (C) 2018 Gao Xiang */ -#ifndef _LINUX_TAGPTR_H -#define _LINUX_TAGPTR_H +#ifndef __EROFS_FS_TAGPTR_H +#define __EROFS_FS_TAGPTR_H #include #include @@ -106,5 +106,5 @@ tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) ptptr->v &= ~tags; \ *ptptr; }) -#endif +#endif /* __EROFS_FS_TAGPTR_H */ diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/zdata.c similarity index 99% rename from drivers/staging/erofs/unzip_vle.c rename to drivers/staging/erofs/zdata.c index 28a98e79c1e9..f7667628bbf1 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/zdata.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/unzip_vle.c + * linux/drivers/staging/erofs/zdata.c * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang */ -#include "unzip_vle.h" +#include "zdata.h" #include "compress.h" #include diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/zdata.h similarity index 97% rename from drivers/staging/erofs/unzip_vle.h rename to drivers/staging/erofs/zdata.h index d92515cd1c06..8d0119d697da 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/zdata.h @@ -1,16 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/unzip_vle.h + * linux/drivers/staging/erofs/zdata.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang */ -#ifndef __EROFS_FS_UNZIP_VLE_H -#define __EROFS_FS_UNZIP_VLE_H +#ifndef __EROFS_FS_ZDATA_H +#define __EROFS_FS_ZDATA_H #include "internal.h" -#include "unzip_pagevec.h" +#include "zpvec.h" #define Z_EROFS_NR_INLINE_PAGEVECS 3 diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/zpvec.h similarity index 96% rename from drivers/staging/erofs/unzip_pagevec.h rename to drivers/staging/erofs/zpvec.h index f07302c3c3f5..77bf6877bad8 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/zpvec.h @@ -1,15 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/unzip_pagevec.h + * linux/drivers/staging/erofs/zpvec.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang */ -#ifndef __EROFS_UNZIP_PAGEVEC_H -#define __EROFS_UNZIP_PAGEVEC_H +#ifndef __EROFS_FS_ZPVEC_H +#define __EROFS_FS_ZPVEC_H -#include +#include "tagptr.h" /* page type in pagevec for unzip subsystem */ enum z_erofs_page_type { -- GitLab From 5734fa217f27bc08667930e862dbe536ed6a77ea Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:33 +0800 Subject: [PATCH 1671/7155] staging: erofs: fix dummy functions erofs_{get, list}xattr dummy functions erofs_{get,list}xattr should be inlined without xattr enabled. Signed-off-by: Yue Hu [ Gao Xiang : this patch was "staging: erofs: remove needless dummy functions of erofs_{get,list}xattr. "] Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-4-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/xattr.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index fbcd57bdf886..63cc87e3d3f4 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -39,6 +39,7 @@ static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; } +#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler erofs_xattr_user_handler; extern const struct xattr_handler erofs_xattr_trusted_handler; #ifdef CONFIG_EROFS_FS_SECURITY @@ -64,25 +65,24 @@ static const struct xattr_handler *xattr_handler_map[] = { xattr_handler_map[idx] : NULL; } -#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler *erofs_xattr_handlers[]; int erofs_getxattr(struct inode *, int, const char *, void *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t); #else -static int __maybe_unused erofs_getxattr(struct inode *inode, int index, - const char *name, - void *buffer, size_t buffer_size) +static inline int erofs_getxattr(struct inode *inode, int index, + const char *name, void *buffer, + size_t buffer_size) { return -ENOTSUPP; } -static ssize_t __maybe_unused erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) +static inline ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) { return -ENOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_XATTR */ #ifdef CONFIG_EROFS_FS_POSIX_ACL struct posix_acl *erofs_get_acl(struct inode *inode, int type); -- GitLab From cead56f85baa783a1ed56bea235a4c1c2556c3fa Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:34 +0800 Subject: [PATCH 1672/7155] staging: erofs: keep up erofs_fs.h with erofs-outofstaging patchset The main change is to reserve all checksums except for superblock, since it's more useful to do block-based verity for read-only fs. Some comments change as well, which is minor. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-5-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/erofs_fs.h | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index 9cd749d56920..e82e833985e4 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -96,7 +96,7 @@ struct erofs_inode_v1 { /* 20 */__le32 i_ino; /* only used for 32-bit stat compatibility */ /* 24 */__le16 i_uid; /* 26 */__le16 i_gid; -/* 28 */__le32 i_checksum; +/* 28 */__le32 i_reserved2; } __packed; /* 32 bytes on-disk inode */ @@ -105,14 +105,14 @@ struct erofs_inode_v1 { #define EROFS_INODE_LAYOUT_V2 1 struct erofs_inode_v2 { - __le16 i_advise; +/* 0 */__le16 i_advise; - /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ - __le16 i_xattr_icount; - __le16 i_mode; - __le16 i_reserved; /* 8 bytes */ - __le64 i_size; /* 16 bytes */ - union { +/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ +/* 2 */__le16 i_xattr_icount; +/* 4 */__le16 i_mode; +/* 6 */__le16 i_reserved; +/* 8 */__le64 i_size; +/* 16 */union { /* file total compressed blocks for data mapping 1 */ __le32 compressed_blocks; __le32 raw_blkaddr; @@ -122,16 +122,15 @@ struct erofs_inode_v2 { } i_u __packed; /* only used for 32-bit stat compatibility */ - __le32 i_ino; /* 24 bytes */ - - __le32 i_uid; - __le32 i_gid; - __le64 i_ctime; /* 32 bytes */ - __le32 i_ctime_nsec; - __le32 i_nlink; - __u8 i_reserved2[12]; - __le32 i_checksum; /* 64 bytes */ -} __packed; +/* 20 */__le32 i_ino; + +/* 24 */__le32 i_uid; +/* 28 */__le32 i_gid; +/* 32 */__le64 i_ctime; +/* 40 */__le32 i_ctime_nsec; +/* 44 */__le32 i_nlink; +/* 48 */__u8 i_reserved2[16]; +} __packed; /* 64 bytes */ #define EROFS_MAX_SHARED_XATTRS (128) /* h_shared_count between 129 ... 255 are special # */ @@ -149,9 +148,9 @@ struct erofs_inode_v2 { * for read-only fs, no need to introduce h_refcount */ struct erofs_xattr_ibody_header { - __le32 h_checksum; + __le32 h_reserved; __u8 h_shared_count; - __u8 h_reserved[7]; + __u8 h_reserved2[7]; __le32 h_shared_xattrs[0]; /* shared xattr id array */ } __packed; -- GitLab From b1897c60b14dc565e9a308c09bbb696faf9d1944 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:35 +0800 Subject: [PATCH 1673/7155] staging: erofs: sunset erofs_workstn_{lock,unlock} It was used for Linux backward compatibility, and no use for upstream kernel. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-6-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 3 --- drivers/staging/erofs/utils.c | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 501429ec0f91..ed487ee56f74 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -179,9 +179,6 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP -#define erofs_workstn_lock(sbi) xa_lock(&(sbi)->workstn_tree) -#define erofs_workstn_unlock(sbi) xa_unlock(&(sbi)->workstn_tree) - /* basic unit of the workstation of a super_block */ struct erofs_workgroup { /* the workgroup index in the workstation */ diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index a68dbe375fa0..024806003297 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -102,14 +102,14 @@ int erofs_register_workgroup(struct super_block *sb, return err; sbi = EROFS_SB(sb); - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); grp = xa_tag_pointer(grp, tag); /* * Bump up reference count before making this workgroup * visible to other users in order to avoid potential UAF - * without serialized by erofs_workstn_lock. + * without serialized by workstn_lock. */ __erofs_workgroup_get(grp); @@ -122,7 +122,7 @@ int erofs_register_workgroup(struct super_block *sb, */ __erofs_workgroup_put(grp); - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); radix_tree_preload_end(); return err; } @@ -225,7 +225,7 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, int i, found; repeat: - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); found = radix_tree_gang_lookup(&sbi->workstn_tree, batch, first_index, PAGEVEC_SIZE); @@ -243,7 +243,7 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, if (unlikely(!--nr_shrink)) break; } - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); if (i && nr_shrink) goto repeat; -- GitLab From 14f362b4f405804e219ac016b9e771d8f5dff5db Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:36 +0800 Subject: [PATCH 1674/7155] staging: erofs: clean up internal.h Tidy up relative order of variables / declarations in internal.h, move some local static functions out into other files and add tags at the end of #endif acrossing several lines. No logic change. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-7-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/decompressor.c | 27 +++++ drivers/staging/erofs/internal.h | 157 ++++++++------------------- drivers/staging/erofs/super.c | 2 +- drivers/staging/erofs/zdata.c | 8 +- drivers/staging/erofs/zdata.h | 13 +++ 5 files changed, 92 insertions(+), 115 deletions(-) diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index b75524d0b322..ee5762351f80 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -223,6 +223,33 @@ static void copy_from_pcpubuf(struct page **out, const char *dst, } } +static void *erofs_vmap(struct page **pages, unsigned int count) +{ +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM + int i = 0; + + while (1) { + void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); + /* retry two more times (totally 3 times) */ + if (addr || ++i >= 3) + return addr; + vm_unmap_aliases(); + } + return NULL; +#else + return vmap(pages, count, VM_MAP, PAGE_KERNEL); +#endif +} + +static void erofs_vunmap(const void *mem, unsigned int count) +{ +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM + vm_unmap_ram(mem, count); +#else + vunmap(mem); +#endif +} + static int decompress_generic(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index ed487ee56f74..959bd0ae9d74 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -6,8 +6,8 @@ * http://www.huawei.com/ * Created by Gao Xiang */ -#ifndef __INTERNAL_H -#define __INTERNAL_H +#ifndef __EROFS_INTERNAL_H +#define __EROFS_INTERNAL_H #include #include @@ -28,15 +28,11 @@ #define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) #ifdef CONFIG_EROFS_FS_DEBUG #define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) - -#define dbg_might_sleep might_sleep #define DBG_BUGON BUG_ON #else #define debugln(x, ...) ((void)0) - -#define dbg_might_sleep() ((void)0) #define DBG_BUGON(x) ((void)(x)) -#endif +#endif /* !CONFIG_EROFS_FS_DEBUG */ enum { FAULT_KMALLOC, @@ -53,7 +49,7 @@ struct erofs_fault_info { unsigned int inject_rate; unsigned int inject_type; }; -#endif +#endif /* CONFIG_EROFS_FAULT_INJECTION */ #ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR #define EROFS_FS_ZIP_CACHE_LVL (2) @@ -71,6 +67,9 @@ struct erofs_fault_info { #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 typedef u64 erofs_nid_t; +typedef u64 erofs_off_t; +/* data type for filesystem-wide blocks number */ +typedef u32 erofs_blk_t; struct erofs_sb_info { /* list for all registered superblocks, mainly for shrinker */ @@ -154,7 +153,7 @@ static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) static inline void erofs_show_injection_info(int type) { } -#endif +#endif /* !CONFIG_EROFS_FAULT_INJECTION */ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, size_t size, gfp_t flags) @@ -179,6 +178,8 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP +#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) + /* basic unit of the workstation of a super_block */ struct erofs_workgroup { /* the workgroup index in the workstation */ @@ -188,8 +189,6 @@ struct erofs_workgroup { atomic_t refcount; }; -#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) - #if defined(CONFIG_SMP) static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, int val) @@ -246,50 +245,24 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) DBG_BUGON(v == EROFS_LOCKED_MAGIC); return v; } -#endif - -int erofs_workgroup_put(struct erofs_workgroup *grp); -struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag); -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp); -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page); - -#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) -{ - return page->mapping == MNGD_MAPPING(sbi); -} -#else -#define MNGD_MAPPING(sbi) (NULL) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) { return false; } -#endif +#endif /* !CONFIG_SMP */ -#define DEFAULT_MAX_SYNC_DECOMPRESS_PAGES 3 +/* hard limit of pages per compressed cluster */ +#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) +#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -static inline bool __should_decompress_synchronously(struct erofs_sb_info *sbi, - unsigned int nr) -{ - return nr <= sbi->max_sync_decompress_pages; -} +/* page count of a compressed cluster */ +#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) int __init z_erofs_init_zip_subsystem(void); void z_erofs_exit_zip_subsystem(void); #else +#define EROFS_PCPUBUF_NR_PAGES 0 + /* dummy initializer/finalizer for the decompression subsystem */ static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} -#endif +#endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ #define LOG_BLOCK_SIZE PAGE_SHIFT @@ -308,23 +281,6 @@ static inline void z_erofs_exit_zip_subsystem(void) {} #define ROOT_NID(sb) ((sb)->root_nid) -#ifdef CONFIG_EROFS_FS_ZIP -/* hard limit of pages per compressed cluster */ -#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) - -/* page count of a compressed cluster */ -#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) - -#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -#else -#define EROFS_PCPUBUF_NR_PAGES 0 -#endif - -typedef u64 erofs_off_t; - -/* data type for filesystem-wide blocks number */ -typedef u32 erofs_blk_t; - #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) #define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) #define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) @@ -364,7 +320,7 @@ struct erofs_vnode { unsigned char z_logical_clusterbits; unsigned char z_physical_clusterbits[2]; }; -#endif +#endif /* CONFIG_EROFS_FS_ZIP */ }; /* the corresponding vfs inode */ struct inode vfs_inode; @@ -472,13 +428,14 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, { return -ENOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_ZIP */ /* data.c */ -static inline struct bio * -erofs_grab_bio(struct super_block *sb, - erofs_blk_t blkaddr, unsigned int nr_pages, void *bi_private, - bio_end_io_t endio, bool nofail) +static inline struct bio *erofs_grab_bio(struct super_block *sb, + erofs_blk_t blkaddr, + unsigned int nr_pages, + void *bi_private, bio_end_io_t endio, + bool nofail) { const gfp_t gfp = GFP_NOIO; struct bio *bio; @@ -525,20 +482,13 @@ static inline struct page *erofs_get_meta_page(struct super_block *sb, return __erofs_get_meta_page(sb, blkaddr, prio, false); } -static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb, - erofs_blk_t blkaddr, bool prio) -{ - return __erofs_get_meta_page(sb, blkaddr, prio, true); -} - int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); -static inline struct page * -erofs_get_inline_page(struct inode *inode, - erofs_blk_t blkaddr) +static inline struct page *erofs_get_inline_page(struct inode *inode, + erofs_blk_t blkaddr) { - return erofs_get_meta_page(inode->i_sb, - blkaddr, S_ISDIR(inode->i_mode)); + return erofs_get_meta_page(inode->i_sb, blkaddr, + S_ISDIR(inode->i_mode)); } /* inode.c */ @@ -578,34 +528,7 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -static inline void *erofs_vmap(struct page **pages, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - int i = 0; - - while (1) { - void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); - /* retry two more times (totally 3 times) */ - if (addr || ++i >= 3) - return addr; - vm_unmap_aliases(); - } - return NULL; -#else - return vmap(pages, count, VM_MAP, PAGE_KERNEL); -#endif -} - -static inline void erofs_vunmap(const void *mem, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - vm_unmap_ram(mem, count); -#else - vunmap(mem); -#endif -} - -/* utils.c */ +/* utils.c / zdata.c */ extern struct shrinker erofs_shrinker_info; struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); @@ -625,12 +548,20 @@ static inline void *erofs_get_pcpubuf(unsigned int pagenr) #define erofs_put_pcpubuf(buf) do {} while (0) #endif +int erofs_workgroup_put(struct erofs_workgroup *grp); +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); +unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, bool cleanup); +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp); +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page); void erofs_register_super(struct super_block *sb); void erofs_unregister_super(struct super_block *sb); -#ifndef lru_to_page -#define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) -#endif - -#endif +#endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 38cd7a59750a..55f51d2b3930 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -211,7 +211,7 @@ static void default_options(struct erofs_sb_info *sbi) { /* set up some FS parameters */ #ifdef CONFIG_EROFS_FS_ZIP - sbi->max_sync_decompress_pages = DEFAULT_MAX_SYNC_DECOMPRESS_PAGES; + sbi->max_sync_decompress_pages = 3; #endif #ifdef CONFIG_EROFS_FS_XATTR diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index f7667628bbf1..bc478eebf509 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -1509,6 +1509,12 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, return 0; } +static bool should_decompress_synchronously(struct erofs_sb_info *sbi, + unsigned int nr) +{ + return nr <= sbi->max_sync_decompress_pages; +} + static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct address_space *mapping, struct list_head *pages, @@ -1517,7 +1523,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct inode *const inode = mapping->host; struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - bool sync = __should_decompress_synchronously(sbi, nr_pages); + bool sync = should_decompress_synchronously(sbi, nr_pages); struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); struct page *head = NULL; diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 8d0119d697da..6574d43ba877 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -104,6 +104,19 @@ struct z_erofs_vle_unzip_io_sb { struct super_block *sb; }; +#ifdef EROFS_FS_HAS_MANAGED_CACHE +#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) +{ + return page->mapping == MNGD_MAPPING(sbi); +} +#else +#define MNGD_MAPPING(sbi) (NULL) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) { return false; } +#endif /* !EROFS_FS_HAS_MANAGED_CACHE */ + #define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 #define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) -- GitLab From 22ee1347a8fb6d3eba91aacad7c691dee274cc1f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:37 +0800 Subject: [PATCH 1675/7155] staging: erofs: remove redundant #include "internal.h" Because #include "internal.h" is included in xattr.h Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-8-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/namei.c | 1 - drivers/staging/erofs/super.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index 50816b4c05fc..8e06526da023 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -6,7 +6,6 @@ * http://www.huawei.com/ * Created by Gao Xiang */ -#include "internal.h" #include "xattr.h" #include diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 55f51d2b3930..c20a94b035a7 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -11,7 +11,6 @@ #include #include #include -#include "internal.h" #include "xattr.h" #define CREATE_TRACE_POINTS -- GitLab From beb5f3c4a1f8daa9175f0044d2fa4185c7813a30 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:38 +0800 Subject: [PATCH 1676/7155] staging: erofs: kill CONFIG_EROFS_FS_IO_MAX_RETRIES CONFIG_EROFS_FS_IO_MAX_RETRIES seems a runtime setting and users have no idea about the change in behaviour. Let's remove the setting currently and could turn it into a module parameter if it's really needed. Suggested-by: David Sterba Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-9-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 9 --------- drivers/staging/erofs/internal.h | 8 ++------ 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 2577cbb46a5b..747e9eebfaa5 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -78,15 +78,6 @@ config EROFS_FAULT_INJECTION Test EROFS to inject faults such as ENOMEM, EIO, and so on. If unsure, say N. -config EROFS_FS_IO_MAX_RETRIES - int "EROFS IO Maximum Retries" - depends on EROFS_FS - default "5" - help - Maximum retry count of IO Errors. - - If unsure, leave the default value (5 retries, 6 IOs at most). - config EROFS_FS_ZIP bool "EROFS Data Compresssion Support" depends on EROFS_FS diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 959bd0ae9d74..a3b9fcdd0c27 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -279,6 +279,8 @@ static inline void z_erofs_exit_zip_subsystem(void) {} #error erofs cannot be used in this platform #endif +#define EROFS_IO_MAX_RETRIES_NOFAIL 5 + #define ROOT_NID(sb) ((sb)->root_nid) #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) @@ -467,12 +469,6 @@ static inline void __submit_bio(struct bio *bio, unsigned int op, submit_bio(bio); } -#ifndef CONFIG_EROFS_FS_IO_MAX_RETRIES -#define EROFS_IO_MAX_RETRIES_NOFAIL 0 -#else -#define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES -#endif - struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, bool prio, bool nofail); -- GitLab From 22fe04a77d104996d838a487a1d031eda8d439b7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:39 +0800 Subject: [PATCH 1677/7155] staging: erofs: clean up shrinker stuffs - rename erofs_register_super / erofs_unregister_super to erofs_shrinker_register / erofs_shrinker_unregister; - fold the only erofs_shrink_workstation external call to erofs_shrinker_unregister; - localize erofs_shrink_workstation; - localize erofs_shrinker_info by introducing erofs_init_shrinker and erofs_exit_shrinker. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-10-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 50 +++++++++++++++++--------------- drivers/staging/erofs/super.c | 20 ++++--------- drivers/staging/erofs/utils.c | 37 +++++++++++++++-------- 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index a3b9fcdd0c27..e149cf9fc23f 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -72,34 +72,35 @@ typedef u64 erofs_off_t; typedef u32 erofs_blk_t; struct erofs_sb_info { +#ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; struct mutex umount_mutex; - u32 blocks; - u32 meta_blkaddr; -#ifdef CONFIG_EROFS_FS_XATTR - u32 xattr_blkaddr; -#endif - - /* inode slot unit size in bit shift */ - unsigned char islotbits; -#ifdef CONFIG_EROFS_FS_ZIP /* cluster size in bit shift */ unsigned char clusterbits; - /* the dedicated workstation for compression */ struct radix_tree_root workstn_tree; /* threshold for decompression synchronously */ unsigned int max_sync_decompress_pages; + unsigned int shrinker_run_no; + #ifdef EROFS_FS_HAS_MANAGED_CACHE struct inode *managed_cache; #endif +#endif /* CONFIG_EROFS_FS_ZIP */ + u32 blocks; + u32 meta_blkaddr; +#ifdef CONFIG_EROFS_FS_XATTR + u32 xattr_blkaddr; #endif + /* inode slot unit size in bit shift */ + unsigned char islotbits; + u32 build_time_nsec; u64 build_time; @@ -115,7 +116,6 @@ struct erofs_sb_info { char *dev_name; unsigned int mount_opt; - unsigned int shrinker_run_no; #ifdef CONFIG_EROFS_FAULT_INJECTION struct erofs_fault_info fault_info; /* For fault injection */ @@ -253,15 +253,8 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) /* page count of a compressed cluster */ #define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) - -int __init z_erofs_init_zip_subsystem(void); -void z_erofs_exit_zip_subsystem(void); #else #define EROFS_PCPUBUF_NR_PAGES 0 - -/* dummy initializer/finalizer for the decompression subsystem */ -static inline int z_erofs_init_zip_subsystem(void) { return 0; } -static inline void z_erofs_exit_zip_subsystem(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ @@ -525,8 +518,6 @@ int erofs_namei(struct inode *dir, struct qstr *name, extern const struct file_operations erofs_dir_fops; /* utils.c / zdata.c */ -extern struct shrinker erofs_shrinker_info; - struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); #if (EROFS_PCPUBUF_NR_PAGES > 0) @@ -544,20 +535,31 @@ static inline void *erofs_get_pcpubuf(unsigned int pagenr) #define erofs_put_pcpubuf(buf) do {} while (0) #endif +#ifdef CONFIG_EROFS_FS_ZIP int erofs_workgroup_put(struct erofs_workgroup *grp); struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, pgoff_t index, bool *tag); int erofs_register_workgroup(struct super_block *sb, struct erofs_workgroup *grp, bool tag); -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +void erofs_shrinker_register(struct super_block *sb); +void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); +int __init z_erofs_init_zip_subsystem(void); +void z_erofs_exit_zip_subsystem(void); int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct erofs_workgroup *egrp); int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page); -void erofs_register_super(struct super_block *sb); -void erofs_unregister_super(struct super_block *sb); +#else +static inline void erofs_shrinker_register(struct super_block *sb) {} +static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} +static inline int z_erofs_init_zip_subsystem(void) { return 0; } +static inline void z_erofs_exit_zip_subsystem(void) {} +#endif /* !CONFIG_EROFS_FS_ZIP */ #endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index c20a94b035a7..7e6fe9cd45e7 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -458,7 +458,7 @@ static int erofs_read_super(struct super_block *sb, snprintf(sbi->dev_name, PATH_MAX, "%s", dev_name); sbi->dev_name[PATH_MAX - 1] = '\0'; - erofs_register_super(sb); + erofs_shrinker_register(sb); if (!silent) infoln("mounted on %s with opts: %s.", dev_name, @@ -502,20 +502,10 @@ static void erofs_put_super(struct super_block *sb) infoln("unmounted for %s", sbi->dev_name); __putname(sbi->dev_name); + erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); #endif - - mutex_lock(&sbi->umount_mutex); - -#ifdef CONFIG_EROFS_FS_ZIP - /* clean up the compression space of this sb */ - erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); -#endif - - erofs_unregister_super(sb); - mutex_unlock(&sbi->umount_mutex); - kfree(sbi); sb->s_fs_info = NULL; } @@ -569,7 +559,7 @@ static int __init erofs_module_init(void) if (err) goto icache_err; - err = register_shrinker(&erofs_shrinker_info); + err = erofs_init_shrinker(); if (err) goto shrinker_err; @@ -587,7 +577,7 @@ static int __init erofs_module_init(void) fs_err: z_erofs_exit_zip_subsystem(); zip_err: - unregister_shrinker(&erofs_shrinker_info); + erofs_exit_shrinker(); shrinker_err: erofs_exit_inode_cache(); icache_err: @@ -598,7 +588,7 @@ static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); z_erofs_exit_zip_subsystem(); - unregister_shrinker(&erofs_shrinker_info); + erofs_exit_shrinker(); erofs_exit_inode_cache(); infoln("successfully finalize erofs"); } diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 024806003297..0e86e44d60d0 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -34,10 +34,10 @@ void *erofs_get_pcpubuf(unsigned int pagenr) } #endif +#ifdef CONFIG_EROFS_FS_ZIP /* global shrink count (for all mounted EROFS instances) */ static atomic_long_t erofs_global_shrink_cnt; -#ifdef CONFIG_EROFS_FS_ZIP #define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) #define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) @@ -215,9 +215,9 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, #endif -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, - bool cleanup) +static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, + bool cleanup) { pgoff_t first_index = 0; void *batch[PAGEVEC_SIZE]; @@ -250,8 +250,6 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, return freed; } -#endif - /* protected by 'erofs_sb_list_lock' */ static unsigned int shrinker_run_no; @@ -259,7 +257,7 @@ static unsigned int shrinker_run_no; static DEFINE_SPINLOCK(erofs_sb_list_lock); static LIST_HEAD(erofs_sb_list); -void erofs_register_super(struct super_block *sb) +void erofs_shrinker_register(struct super_block *sb) { struct erofs_sb_info *sbi = EROFS_SB(sb); @@ -270,11 +268,17 @@ void erofs_register_super(struct super_block *sb) spin_unlock(&erofs_sb_list_lock); } -void erofs_unregister_super(struct super_block *sb) +void erofs_shrinker_unregister(struct super_block *sb) { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + erofs_shrink_workstation(sbi, ~0UL, true); + spin_lock(&erofs_sb_list_lock); - list_del(&EROFS_SB(sb)->list); + list_del(&sbi->list); spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); } static unsigned long erofs_shrink_count(struct shrinker *shrink, @@ -318,9 +322,7 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, spin_unlock(&erofs_sb_list_lock); sbi->shrinker_run_no = run_no; -#ifdef CONFIG_EROFS_FS_ZIP freed += erofs_shrink_workstation(sbi, nr, false); -#endif spin_lock(&erofs_sb_list_lock); /* Get the next list element before we move this one */ @@ -340,9 +342,20 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, return freed; } -struct shrinker erofs_shrinker_info = { +static struct shrinker erofs_shrinker_info = { .scan_objects = erofs_shrink_scan, .count_objects = erofs_shrink_count, .seeks = DEFAULT_SEEKS, }; +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); +} +#endif /* !CONFIG_EROFS_FS_ZIP */ + -- GitLab From 9e794de573d7d54e3742628227e585bd90acc38a Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:40 +0800 Subject: [PATCH 1678/7155] staging: erofs: kill sbi->dev_name As Al said, "the only use of sbi->dev_name is debugging printks and all of those have sb->s_id available, with device name stored in there. Which makes the whole thing bloody weird". sbi->dev_name was used for our debugging use and it's better to just use s_id in community and delete the whole erofs_mount_private stuff. Suggested-by: Al Viro Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-11-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 2 -- drivers/staging/erofs/super.c | 54 +++++--------------------------- 2 files changed, 7 insertions(+), 49 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index e149cf9fc23f..5e1ef2b5a458 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -113,8 +113,6 @@ struct erofs_sb_info { u8 volume_name[16]; /* volume name */ u32 requirements; - char *dev_name; - unsigned int mount_opt; #ifdef CONFIG_EROFS_FAULT_INJECTION diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 7e6fe9cd45e7..bfb6e1e09781 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -362,15 +362,13 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) #endif -static int erofs_read_super(struct super_block *sb, - const char *dev_name, - void *data, int silent) +static int erofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; int err = -EINVAL; - infoln("read_super, device -> %s", dev_name); + infoln("fill_super, device -> %s", sb->s_id); infoln("options -> %s", (char *)data); if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { @@ -448,30 +446,16 @@ static int erofs_read_super(struct super_block *sb, goto err_iget; } - /* save the device name to sbi */ - sbi->dev_name = __getname(); - if (!sbi->dev_name) { - err = -ENOMEM; - goto err_devname; - } - - snprintf(sbi->dev_name, PATH_MAX, "%s", dev_name); - sbi->dev_name[PATH_MAX - 1] = '\0'; - erofs_shrinker_register(sb); if (!silent) - infoln("mounted on %s with opts: %s.", dev_name, - (char *)data); + infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); return 0; /* * please add a label for each exit point and use * the following name convention, thus new features * can be integrated easily without renaming labels. */ -err_devname: - dput(sb->s_root); - sb->s_root = NULL; err_iget: #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); @@ -499,8 +483,7 @@ static void erofs_put_super(struct super_block *sb) WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); - infoln("unmounted for %s", sbi->dev_name); - __putname(sbi->dev_name); + infoln("unmounted for %s", sb->s_id); erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE @@ -510,33 +493,10 @@ static void erofs_put_super(struct super_block *sb) sb->s_fs_info = NULL; } - -struct erofs_mount_private { - const char *dev_name; - char *options; -}; - -/* support mount_bdev() with options */ -static int erofs_fill_super(struct super_block *sb, - void *_priv, int silent) -{ - struct erofs_mount_private *priv = _priv; - - return erofs_read_super(sb, priv->dev_name, - priv->options, silent); -} - -static struct dentry *erofs_mount( - struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) { - struct erofs_mount_private priv = { - .dev_name = dev_name, - .options = data - }; - - return mount_bdev(fs_type, flags, dev_name, - &priv, erofs_fill_super); + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } static struct file_system_type erofs_fs_type = { -- GitLab From 8f7acdae2cd4b843d1fcb49e449cc7860556e3ef Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:41 +0800 Subject: [PATCH 1679/7155] staging: erofs: kill all failure handling in fill_super() .kill_sb() will do that instead in order to remove duplicated code. Note that the initialzation of managed_cache is now moved after s_root is assigned since it's more preferred to iput() in .put_super() and all inodes should be evicted before the end of generic_shutdown_super(sb). Suggested-by: Al Viro Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-12-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 118 +++++++++++++++------------------- 1 file changed, 52 insertions(+), 66 deletions(-) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index bfb6e1e09781..7c31030daf4e 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -343,12 +343,13 @@ static const struct address_space_operations managed_cache_aops = { .invalidatepage = managed_cache_invalidatepage, }; -static struct inode *erofs_init_managed_cache(struct super_block *sb) +static int erofs_init_managed_cache(struct super_block *sb) { - struct inode *inode = new_inode(sb); + struct erofs_sb_info *const sbi = EROFS_SB(sb); + struct inode *const inode = new_inode(sb); if (unlikely(!inode)) - return ERR_PTR(-ENOMEM); + return -ENOMEM; set_nlink(inode, 1); inode->i_size = OFFSET_MAX; @@ -357,37 +358,38 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE | __GFP_NOFAIL); - return inode; + sbi->managed_cache = inode; + return 0; } - +#else +static int erofs_init_managed_cache(struct super_block *sb) { return 0; } #endif static int erofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; - int err = -EINVAL; + int err; infoln("fill_super, device -> %s", sb->s_id); infoln("options -> %s", (char *)data); + sb->s_magic = EROFS_SUPER_MAGIC; + if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { errln("failed to set erofs blksize"); - goto err; + return -EINVAL; } sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (unlikely(!sbi)) { - err = -ENOMEM; - goto err; - } - sb->s_fs_info = sbi; + if (unlikely(!sbi)) + return -ENOMEM; + sb->s_fs_info = sbi; err = superblock_read(sb); if (err) - goto err_sbread; + return err; - sb->s_magic = EROFS_SUPER_MAGIC; sb->s_flags |= SB_RDONLY | SB_NOATIME; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_time_gran = 1; @@ -397,13 +399,12 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_EROFS_FS_XATTR sb->s_xattr = erofs_xattr_handlers; #endif - /* set erofs default mount options */ default_options(sbi); err = parse_options(sb, data); - if (err) - goto err_parseopt; + if (unlikely(err)) + return err; if (!silent) infoln("root inode @ nid %llu", ROOT_NID(sbi)); @@ -417,93 +418,78 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); #endif -#ifdef EROFS_FS_HAS_MANAGED_CACHE - sbi->managed_cache = erofs_init_managed_cache(sb); - if (IS_ERR(sbi->managed_cache)) { - err = PTR_ERR(sbi->managed_cache); - goto err_init_managed_cache; - } -#endif - /* get the root inode */ inode = erofs_iget(sb, ROOT_NID(sbi), true); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto err_iget; - } + if (IS_ERR(inode)) + return PTR_ERR(inode); - if (!S_ISDIR(inode->i_mode)) { + if (unlikely(!S_ISDIR(inode->i_mode))) { errln("rootino(nid %llu) is not a directory(i_mode %o)", ROOT_NID(sbi), inode->i_mode); - err = -EINVAL; iput(inode); - goto err_iget; + return -EINVAL; } sb->s_root = d_make_root(inode); - if (!sb->s_root) { - err = -ENOMEM; - goto err_iget; - } + if (unlikely(!sb->s_root)) + return -ENOMEM; erofs_shrinker_register(sb); + /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ + err = erofs_init_managed_cache(sb); + if (unlikely(err)) + return err; if (!silent) infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); return 0; - /* - * please add a label for each exit point and use - * the following name convention, thus new features - * can be integrated easily without renaming labels. - */ -err_iget: -#ifdef EROFS_FS_HAS_MANAGED_CACHE - iput(sbi->managed_cache); -err_init_managed_cache: -#endif -err_parseopt: -err_sbread: - sb->s_fs_info = NULL; - kfree(sbi); -err: - return err; +} + +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } /* * could be triggered after deactivate_locked_super() * is called, thus including umount and failed to initialize. */ -static void erofs_put_super(struct super_block *sb) +static void erofs_kill_sb(struct super_block *sb) { - struct erofs_sb_info *sbi = EROFS_SB(sb); + struct erofs_sb_info *sbi; + + WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); + infoln("unmounting for %s", sb->s_id); - /* for cases which are failed in "read_super" */ + kill_block_super(sb); + + sbi = EROFS_SB(sb); if (!sbi) return; + kfree(sbi); + sb->s_fs_info = NULL; +} - WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); +/* called when ->s_root is non-NULL */ +static void erofs_put_super(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); - infoln("unmounted for %s", sb->s_id); + DBG_BUGON(!sbi); erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); + sbi->managed_cache = NULL; #endif - kfree(sbi); - sb->s_fs_info = NULL; -} - -static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", .mount = erofs_mount, - .kill_sb = kill_block_super, + .kill_sb = erofs_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("erofs"); -- GitLab From 8494c29ffe22dcd166a86b490dce10ecf1c20065 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:42 +0800 Subject: [PATCH 1680/7155] staging: erofs: drop __GFP_NOFAIL for managed inode For historical reasons, __GFP_NOFAIL was set for managed inode. It's no need using that since EROFS can handle it properly. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-13-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 7c31030daf4e..af5d87793e4d 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -356,8 +356,7 @@ static int erofs_init_managed_cache(struct super_block *sb) inode->i_mapping->a_ops = &managed_cache_aops; mapping_set_gfp_mask(inode->i_mapping, - GFP_NOFS | __GFP_HIGHMEM | - __GFP_MOVABLE | __GFP_NOFAIL); + GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); sbi->managed_cache = inode; return 0; } -- GitLab From b25a15191c5cf090f79fd220238b93f30b022b0d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:43 +0800 Subject: [PATCH 1681/7155] staging: erofs: refine erofs_allocpage() remove duplicated code in decompressor by introducing failable erofs_allocpage(). Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-14-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/decompressor.c | 12 +++--------- drivers/staging/erofs/internal.h | 2 +- drivers/staging/erofs/utils.c | 5 +++-- drivers/staging/erofs/zdata.c | 5 +---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index ee5762351f80..744c43a456e9 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -74,15 +74,9 @@ static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, victim = availables[--top]; get_page(victim); } else { - if (!list_empty(pagepool)) { - victim = lru_to_page(pagepool); - list_del(&victim->lru); - DBG_BUGON(page_ref_count(victim) != 1); - } else { - victim = alloc_pages(GFP_KERNEL, 0); - if (!victim) - return -ENOMEM; - } + victim = erofs_allocpage(pagepool, GFP_KERNEL, false); + if (unlikely(!victim)) + return -ENOMEM; victim->mapping = Z_EROFS_MAPPING_STAGING; } rq->out[i] = victim; diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 5e1ef2b5a458..a631acd0dc62 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -516,7 +516,7 @@ int erofs_namei(struct inode *dir, struct qstr *name, extern const struct file_operations erofs_dir_fops; /* utils.c / zdata.c */ -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); #if (EROFS_PCPUBUF_NR_PAGES > 0) void *erofs_get_pcpubuf(unsigned int pagenr); diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 0e86e44d60d0..260ea2970b4b 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -9,15 +9,16 @@ #include "internal.h" #include -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) { struct page *page; if (!list_empty(pool)) { page = lru_to_page(pool); + DBG_BUGON(page_ref_count(page) != 1); list_del(&page->lru); } else { - page = alloc_pages(gfp | __GFP_NOFAIL, 0); + page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); } return page; } diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index bc478eebf509..3078510e350d 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -634,10 +634,7 @@ z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) static inline struct page *__stagingpage_alloc(struct list_head *pagepool, gfp_t gfp) { - struct page *page = erofs_allocpage(pagepool, gfp); - - if (unlikely(!page)) - return NULL; + struct page *page = erofs_allocpage(pagepool, gfp, true); page->mapping = Z_EROFS_MAPPING_STAGING; return page; -- GitLab From 46c2d1494332ece4f136d167b62afe91a63796fb Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:44 +0800 Subject: [PATCH 1682/7155] staging: erofs: kill CONFIG_EROFS_FS_USE_VM_MAP_RAM Turn into a module parameter ("use_vmap") as it can be set at runtime. Suggested-by: David Sterba Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-15-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- .../erofs/Documentation/filesystems/erofs.txt | 4 ++++ drivers/staging/erofs/Kconfig | 8 ------- drivers/staging/erofs/decompressor.c | 22 +++++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt index 74cf84ac48a3..04cf47865c50 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -66,6 +66,10 @@ fault_injection=%d Enable fault injection in all supported types with (no)acl Setup POSIX Access Control List. Note: acl is enabled by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +Module parameters +================= +use_vmap=[0|1] Use vmap() instead of vm_map_ram() (default 0). + On-disk details =============== diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 747e9eebfaa5..788beebf3f7d 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -63,14 +63,6 @@ config EROFS_FS_SECURITY If you are not using a security module, say N. -config EROFS_FS_USE_VM_MAP_RAM - bool "EROFS VM_MAP_RAM Support" - depends on EROFS_FS - help - use vm_map_ram/vm_unmap_ram instead of vmap/vunmap. - - If you don't know what these are, say N. - config EROFS_FAULT_INJECTION bool "EROFS fault injection facility" depends on EROFS_FS diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index 744c43a456e9..5361a2bbedb6 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -7,6 +7,7 @@ * Created by Gao Xiang */ #include "compress.h" +#include #include #ifndef LZ4_DISTANCE_MAX /* history window size */ @@ -29,6 +30,10 @@ struct z_erofs_decompressor { char *name; }; +static bool use_vmap; +module_param(use_vmap, bool, 0444); +MODULE_PARM_DESC(use_vmap, "Use vmap() instead of vm_map_ram() (default 0)"); + static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { @@ -219,29 +224,28 @@ static void copy_from_pcpubuf(struct page **out, const char *dst, static void *erofs_vmap(struct page **pages, unsigned int count) { -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM int i = 0; + if (use_vmap) + return vmap(pages, count, VM_MAP, PAGE_KERNEL); + while (1) { void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); + /* retry two more times (totally 3 times) */ if (addr || ++i >= 3) return addr; vm_unmap_aliases(); } return NULL; -#else - return vmap(pages, count, VM_MAP, PAGE_KERNEL); -#endif } static void erofs_vunmap(const void *mem, unsigned int count) { -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - vm_unmap_ram(mem, count); -#else - vunmap(mem); -#endif + if (!use_vmap) + vm_unmap_ram(mem, count); + else + vunmap(mem); } static int decompress_generic(struct z_erofs_decompress_req *rq, -- GitLab From 046d64e1189fea79eb8705015ccc621a2f25e1da Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:45 +0800 Subject: [PATCH 1683/7155] staging: erofs: tidy up zpvec.h - use shorter function names: z_erofs_pagevec_enqueue and z_erofs_pagevec_dequeue; - minor code cleanup. In order to keep in line with erofs-outofstaging patchset. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-16-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 6 +++--- drivers/staging/erofs/zpvec.h | 25 +++++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 3078510e350d..88c8c4082498 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -314,8 +314,8 @@ static int z_erofs_vle_work_add_page( try_to_reuse_as_compressed_page(builder, page)) return 0; - ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, - page, type, &occupied); + ret = z_erofs_pagevec_enqueue(&builder->vector, + page, type, &occupied); builder->work->vcnt += (unsigned int)ret; return ret ? 0 : -EAGAIN; @@ -938,7 +938,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, for (i = 0; i < work->vcnt; ++i) { unsigned int pagenr; - page = z_erofs_pagevec_ctor_dequeue(&ctor, &page_type); + page = z_erofs_pagevec_dequeue(&ctor, &page_type); /* all pages in pagevec ought to be valid */ DBG_BUGON(!page); diff --git a/drivers/staging/erofs/zpvec.h b/drivers/staging/erofs/zpvec.h index 77bf6877bad8..9798f5627786 100644 --- a/drivers/staging/erofs/zpvec.h +++ b/drivers/staging/erofs/zpvec.h @@ -11,7 +11,7 @@ #include "tagptr.h" -/* page type in pagevec for unzip subsystem */ +/* page type in pagevec for decompress subsystem */ enum z_erofs_page_type { /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ Z_EROFS_PAGE_TYPE_EXCLUSIVE, @@ -103,16 +103,14 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, z_erofs_pagevec_ctor_pagedown(ctor, false); } } - ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); ctor->index = i; } -static inline bool -z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, - enum z_erofs_page_type type, - bool *occupied) +static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, + bool *occupied) { *occupied = false; if (unlikely(!ctor->next && type)) @@ -131,15 +129,13 @@ z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, ctor->next = page; *occupied = true; } - - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, page, type); + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); return true; } static inline struct page * -z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, - enum z_erofs_page_type *type) +z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor, + enum z_erofs_page_type *type) { erofs_vtptr_t t; @@ -156,11 +152,8 @@ z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, if (*type == (uintptr_t)ctor->next) ctor->next = tagptr_unfold_ptr(t); - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, NULL, 0); - + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0); return tagptr_unfold_ptr(t); } - #endif -- GitLab From febde7b3ac4de7d12f03a555e400d08ae3237a01 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:46 +0800 Subject: [PATCH 1684/7155] staging: erofs: remove redundant braces in inode.c Remove redundant braces in inode.c since these are all single statements. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-17-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index c13d66ccc74a..286729143365 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -35,16 +35,15 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v2->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = new_decode_dev(le32_to_cpu(v2->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; - } else { + else return -EIO; - } i_uid_write(inode, le32_to_cpu(v2->i_uid)); i_gid_write(inode, le32_to_cpu(v2->i_gid)); @@ -69,16 +68,15 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v1->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; - } else { + else return -EIO; - } i_uid_write(inode, le16_to_cpu(v1->i_uid)); i_gid_write(inode, le16_to_cpu(v1->i_gid)); -- GitLab From 97e86a858bc360c9cded74ce9a06595d40f7ad81 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:47 +0800 Subject: [PATCH 1685/7155] staging: erofs: tidy up decompression frontend Although this patch has an amount of changes, it is hard to separate into smaller patches. Most changes are due to structure renaming for better understand and straightforward, z_erofs_vle_workgroup to z_erofs_pcluster since it represents a physical cluster; z_erofs_vle_work to z_erofs_collection since it represents a collection of logical pages; z_erofs_vle_work_builder to z_erofs_collector since it's used to fill z_erofs_{pcluster,collection}. struct z_erofs_vle_work_finder has no extra use compared with struct z_erofs_collector, delete it. FULL_LENGTH bit is integrated into .length of pcluster so that it can be updated with the corresponding length change in atomic. Minor, add comments for better description. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-18-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 983 +++++++++++++++------------------- drivers/staging/erofs/zdata.h | 96 ++-- 2 files changed, 465 insertions(+), 614 deletions(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 88c8c4082498..6ebee2ca8dc5 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -18,7 +18,7 @@ */ #define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) -/* how to allocate cached pages for a workgroup */ +/* how to allocate cached pages for a pcluster */ enum z_erofs_cache_alloctype { DONTALLOC, /* don't allocate any cached pages */ DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ @@ -34,156 +34,158 @@ typedef tagptr1_t compressed_page_t; tagptr_fold(compressed_page_t, page, 1) static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *z_erofs_workgroup_cachep __read_mostly; +static struct kmem_cache *pcluster_cachep __read_mostly; void z_erofs_exit_zip_subsystem(void) { destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(z_erofs_workgroup_cachep); + kmem_cache_destroy(pcluster_cachep); } static inline int init_unzip_workqueue(void) { const unsigned int onlinecpus = num_possible_cpus(); + const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; /* - * we don't need too many threads, limiting threads - * could improve scheduling performance. + * no need to spawn too many threads, limiting threads could minimum + * scheduling overhead, perhaps per-CPU threads should be better? */ - z_erofs_workqueue = - alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, - onlinecpus + onlinecpus / 4); - + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, + onlinecpus + onlinecpus / 4); return z_erofs_workqueue ? 0 : -ENOMEM; } static void init_once(void *ptr) { - struct z_erofs_vle_workgroup *grp = ptr; - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); + struct z_erofs_pcluster *pcl = ptr; + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); unsigned int i; - mutex_init(&work->lock); - work->nr_pages = 0; - work->vcnt = 0; + mutex_init(&cl->lock); + cl->nr_pages = 0; + cl->vcnt = 0; for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - grp->compressed_pages[i] = NULL; + pcl->compressed_pages[i] = NULL; } -static void init_always(struct z_erofs_vle_workgroup *grp) +static void init_always(struct z_erofs_pcluster *pcl) { - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - atomic_set(&grp->obj.refcount, 1); - grp->flags = 0; + atomic_set(&pcl->obj.refcount, 1); - DBG_BUGON(work->nr_pages); - DBG_BUGON(work->vcnt); + DBG_BUGON(cl->nr_pages); + DBG_BUGON(cl->vcnt); } int __init z_erofs_init_zip_subsystem(void) { - z_erofs_workgroup_cachep = - kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, init_once); - - if (z_erofs_workgroup_cachep) { + pcluster_cachep = kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, init_once); + if (pcluster_cachep) { if (!init_unzip_workqueue()) return 0; - kmem_cache_destroy(z_erofs_workgroup_cachep); + kmem_cache_destroy(pcluster_cachep); } return -ENOMEM; } -enum z_erofs_vle_work_role { - Z_EROFS_VLE_WORK_SECONDARY, - Z_EROFS_VLE_WORK_PRIMARY, +enum z_erofs_collectmode { + COLLECT_SECONDARY, + COLLECT_PRIMARY, /* - * The current work was the tail of an exist chain, and the previous - * processed chained works are all decided to be hooked up to it. - * A new chain should be created for the remaining unprocessed works, - * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - * the next work cannot reuse the whole page in the following scenario: + * The current collection was the tail of an exist chain, in addition + * that the previous processed chained collections are all decided to + * be hooked up to it. + * A new chain will be created for the remaining collections which are + * not processed yet, therefore different from COLLECT_PRIMARY_FOLLOWED, + * the next collection cannot reuse the whole page safely in + * the following scenario: * ________________________________________________________________ * | tail (partial) page | head (partial) page | - * | (belongs to the next work) | (belongs to the current work) | + * | (belongs to the next cl) | (belongs to the current cl) | * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| */ - Z_EROFS_VLE_WORK_PRIMARY_HOOKED, + COLLECT_PRIMARY_HOOKED, + COLLECT_PRIMARY_FOLLOWED_NOINPLACE, /* - * The current work has been linked with the processed chained works, - * and could be also linked with the potential remaining works, which - * means if the processing page is the tail partial page of the work, - * the current work can safely use the whole page (since the next work - * is under control) for in-place decompression, as illustrated below: + * The current collection has been linked with the owned chain, and + * could also be linked with the remaining collections, which means + * if the processing page is the tail page of the collection, thus + * the current collection can safely use the whole page (since + * the previous collection is under control) for in-place I/O, as + * illustrated below: * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (of the current work) | (of the previous work) | - * | PRIMARY_FOLLOWED or | | - * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________| + * | tail (partial) page | head (partial) page | + * | (of the current cl) | (of the previous collection) | + * | PRIMARY_FOLLOWED or | | + * |_____PRIMARY_HOOKED___|____________PRIMARY_FOLLOWED____________| * - * [ (*) the above page can be used for the current work itself. ] + * [ (*) the above page can be used as inplace I/O. ] */ - Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - Z_EROFS_VLE_WORK_MAX + COLLECT_PRIMARY_FOLLOWED, }; -struct z_erofs_vle_work_builder { - enum z_erofs_vle_work_role role; - /* - * 'hosted = false' means that the current workgroup doesn't belong to - * the owned chained workgroups. In the other words, it is none of our - * business to submit this workgroup. - */ - bool hosted; - - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; +struct z_erofs_collector { struct z_erofs_pagevec_ctor vector; - /* pages used for reading the compressed data */ - struct page **compressed_pages; - unsigned int compressed_deficit; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + struct page **compressedpages; + z_erofs_next_pcluster_t owned_head; + + enum z_erofs_collectmode mode; }; -#define VLE_WORK_BUILDER_INIT() \ - { .work = NULL, .role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED } +struct z_erofs_decompress_frontend { + struct inode *const inode; + + struct z_erofs_collector clt; + struct erofs_map_blocks map; + + /* used for applying cache strategy on the fly */ + bool backmost; + erofs_off_t headoffset; +}; + +#define COLLECTOR_INIT() { \ + .owned_head = Z_EROFS_PCLUSTER_TAIL, \ + .mode = COLLECT_PRIMARY_FOLLOWED } + +#define DECOMPRESS_FRONTEND_INIT(__i) { \ + .inode = __i, .clt = COLLECTOR_INIT(), \ + .backmost = true, } + +static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; +static DEFINE_MUTEX(z_pagemap_global_lock); #ifdef EROFS_FS_HAS_MANAGED_CACHE -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, +static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) + struct list_head *pagepool) { - struct page **const pages = bl->compressed_pages; - const unsigned int remaining = bl->compressed_deficit; + const struct z_erofs_pcluster *pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct page **pages = clt->compressedpages; + pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); bool standalone = true; - unsigned int i, j = 0; - if (bl->role < Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + if (clt->mode < COLLECT_PRIMARY_FOLLOWED) return; - gfp = mapping_gfp_constraint(mc, gfp) & ~__GFP_RECLAIM; - - index += clusterpages - remaining; - - for (i = 0; i < remaining; ++i) { + for (; pages < pcl->compressed_pages + clusterpages; ++pages) { struct page *page; compressed_page_t t; /* the compressed page was loaded before */ - if (READ_ONCE(pages[i])) + if (READ_ONCE(*pages)) continue; - page = find_get_page(mc, index + i); + page = find_get_page(mc, index); if (page) { t = tag_compressed_page_justfound(page); @@ -191,32 +193,30 @@ static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); } else { /* DONTALLOC */ if (standalone) - j = i; + clt->compressedpages = pages; standalone = false; continue; } - if (!cmpxchg_relaxed(&pages[i], NULL, tagptr_cast_ptr(t))) + if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) continue; if (page) put_page(page); } - bl->compressed_pages += j; - bl->compressed_deficit = remaining - j; - if (standalone) - bl->role = Z_EROFS_VLE_WORK_PRIMARY; + if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ + clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; } /* called by erofs_shrinker to get rid of all compressed_pages */ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp) + struct erofs_workgroup *grp) { - struct z_erofs_vle_workgroup *const grp = - container_of(egrp, struct z_erofs_vle_workgroup, obj); + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); struct address_space *const mapping = MNGD_MAPPING(sbi); - const int clusterpages = erofs_clusterpages(sbi); + const unsigned int clusterpages = BIT(pcl->clusterbits); int i; /* @@ -224,18 +224,20 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, * therefore no need to worry about available decompression users. */ for (i = 0; i < clusterpages; ++i) { - struct page *page = grp->compressed_pages[i]; + struct page *page = pcl->compressed_pages[i]; - if (!page || page->mapping != mapping) + if (!page) continue; /* block other users from reclaiming or migrating the page */ if (!trylock_page(page)) return -EBUSY; - /* barrier is implied in the following 'unlock_page' */ - WRITE_ONCE(grp->compressed_pages[i], NULL); + if (unlikely(page->mapping != mapping)) + continue; + /* barrier is implied in the following 'unlock_page' */ + WRITE_ONCE(pcl->compressed_pages[i], NULL); set_page_private(page, 0); ClearPagePrivate(page); @@ -248,22 +250,21 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page) { - struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - struct z_erofs_vle_workgroup *const grp = (void *)page_private(page); + struct z_erofs_pcluster *const pcl = (void *)page_private(page); + const unsigned int clusterpages = BIT(pcl->clusterbits); int ret = 0; /* 0 - busy */ - if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) { + if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { unsigned int i; for (i = 0; i < clusterpages; ++i) { - if (grp->compressed_pages[i] == page) { - WRITE_ONCE(grp->compressed_pages[i], NULL); + if (pcl->compressed_pages[i] == page) { + WRITE_ONCE(pcl->compressed_pages[i], NULL); ret = 1; break; } } - erofs_workgroup_unfreeze(&grp->obj, 1); + erofs_workgroup_unfreeze(&pcl->obj, 1); if (ret) { ClearPagePrivate(page); @@ -273,361 +274,267 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, return ret; } #else -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, +static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) + struct list_head *pagepool) { /* nowhere to load compressed pages from */ } #endif /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool try_to_reuse_as_compressed_page( - struct z_erofs_vle_work_builder *b, - struct page *page) +static inline bool try_inplace_io(struct z_erofs_collector *clt, + struct page *page) { - while (b->compressed_deficit) { - --b->compressed_deficit; - if (!cmpxchg(b->compressed_pages++, NULL, page)) + struct z_erofs_pcluster *const pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + + while (clt->compressedpages < pcl->compressed_pages + clusterpages) { + if (!cmpxchg(clt->compressedpages++, NULL, page)) return true; } - return false; } -/* callers must be with work->lock held */ -static int z_erofs_vle_work_add_page( - struct z_erofs_vle_work_builder *builder, - struct page *page, - enum z_erofs_page_type type) +/* callers must be with collection lock held */ +static int z_erofs_attach_page(struct z_erofs_collector *clt, + struct page *page, + enum z_erofs_page_type type) { int ret; bool occupied; - /* give priority for the compressed data storage */ - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && + /* give priority for inplaceio */ + if (clt->mode >= COLLECT_PRIMARY && type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_to_reuse_as_compressed_page(builder, page)) + try_inplace_io(clt, page)) return 0; - ret = z_erofs_pagevec_enqueue(&builder->vector, + ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, &occupied); - builder->work->vcnt += (unsigned int)ret; + clt->cl->vcnt += (unsigned int)ret; return ret ? 0 : -EAGAIN; } -static enum z_erofs_vle_work_role -try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t *owned_head, - bool *hosted) +static enum z_erofs_collectmode +try_to_claim_pcluster(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t *owned_head) { - DBG_BUGON(*hosted); - - /* let's claim these following types of workgroup */ + /* let's claim these following types of pclusters */ retry: - if (grp->next == Z_EROFS_VLE_WORKGRP_NIL) { - /* type 1, nil workgroup */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_NIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_NIL) + if (pcl->next == Z_EROFS_PCLUSTER_NIL) { + /* type 1, nil pcluster */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_NIL, + *owned_head) != Z_EROFS_PCLUSTER_NIL) goto retry; - *owned_head = &grp->next; - *hosted = true; + *owned_head = &pcl->next; /* lucky, I am the followee :) */ - return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - - } else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) { + return COLLECT_PRIMARY_FOLLOWED; + } else if (pcl->next == Z_EROFS_PCLUSTER_TAIL) { /* * type 2, link to the end of a existing open chain, * be careful that its submission itself is governed * by the original owned chain. */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_TAIL) + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + *owned_head) != Z_EROFS_PCLUSTER_TAIL) goto retry; - *owned_head = Z_EROFS_VLE_WORKGRP_TAIL; - return Z_EROFS_VLE_WORK_PRIMARY_HOOKED; + *owned_head = Z_EROFS_PCLUSTER_TAIL; + return COLLECT_PRIMARY_HOOKED; } - - return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */ + return COLLECT_PRIMARY; /* :( better luck next time */ } -struct z_erofs_vle_work_finder { - struct super_block *sb; - pgoff_t idx; - unsigned int pageofs; - - struct z_erofs_vle_workgroup **grp_ret; - enum z_erofs_vle_work_role *role; - z_erofs_vle_owned_workgrp_t *owned_head; - bool *hosted; -}; - -static struct z_erofs_vle_work * -z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f) +static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - bool tag, primary; - struct erofs_workgroup *egrp; - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - - egrp = erofs_find_workgroup(f->sb, f->idx, &tag); - if (!egrp) { - *f->grp_ret = NULL; + struct erofs_workgroup *grp; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + unsigned int length; + bool tag; + + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); + if (!grp) return NULL; - } - grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); - *f->grp_ret = grp; + pcl = container_of(grp, struct z_erofs_pcluster, obj); + + cl = z_erofs_primarycollection(pcl); + if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { + DBG_BUGON(1); + return ERR_PTR(-EIO); + } - work = z_erofs_vle_grab_work(grp, f->pageofs); - /* if multiref is disabled, `primary' is always true */ - primary = true; + length = READ_ONCE(pcl->length); + if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { + if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { + DBG_BUGON(1); + return ERR_PTR(-EIO); + } + } else { + unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; - DBG_BUGON(work->pageofs != f->pageofs); + if (map->m_flags & EROFS_MAP_FULL_MAPPED) + llen |= Z_EROFS_PCLUSTER_FULL_LENGTH; - /* - * lock must be taken first to avoid grp->next == NIL between - * claiming workgroup and adding pages: - * grp->next != NIL - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(&work->lock) - * add all pages to pagevec - * - * [correct locking case 1]: - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[b]) mutex_lock(grp->work[c]) - * ... *role = SECONDARY - * add all pages to pagevec - * ... - * mutex_unlock(grp->work[c]) - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * - * [correct locking case 2]: - * mutex_lock(grp->work[b]) - * ... - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(grp->work[a]) - * *role = PRIMARY_OWNER - * add all pages to pagevec - * ... - */ - mutex_lock(&work->lock); - - *f->hosted = false; - if (!primary) - *f->role = Z_EROFS_VLE_WORK_SECONDARY; - else /* claim the workgroup if possible */ - *f->role = try_to_claim_workgroup(grp, f->owned_head, - f->hosted); - return work; + while (llen > length && + length != cmpxchg_relaxed(&pcl->length, length, llen)) { + cpu_relax(); + length = READ_ONCE(pcl->length); + } + } + mutex_lock(&cl->lock); + clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + clt->pcl = pcl; + clt->cl = cl; + return cl; } -static struct z_erofs_vle_work * -z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, - struct erofs_map_blocks *map) +static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - bool gnew = false; - struct z_erofs_vle_workgroup *grp = *f->grp_ret; - struct z_erofs_vle_work *work; - - /* if multiref is disabled, grp should never be nullptr */ - if (unlikely(grp)) { - DBG_BUGON(1); - return ERR_PTR(-EINVAL); - } + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + int err; /* no available workgroup, let's allocate one */ - grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS); - if (unlikely(!grp)) + pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); + if (unlikely(!pcl)) return ERR_PTR(-ENOMEM); - init_always(grp); - grp->obj.index = f->idx; - grp->llen = map->m_llen; + init_always(pcl); + pcl->obj.index = map->m_pa >> PAGE_SHIFT; - z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? - Z_EROFS_VLE_WORKGRP_FMT_LZ4 : - Z_EROFS_VLE_WORKGRP_FMT_PLAIN); + pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | + (map->m_flags & EROFS_MAP_FULL_MAPPED ? + Z_EROFS_PCLUSTER_FULL_LENGTH : 0); - if (map->m_flags & EROFS_MAP_FULL_MAPPED) - grp->flags |= Z_EROFS_VLE_WORKGRP_FULL_LENGTH; + if (map->m_flags & EROFS_MAP_ZIPPED) + pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4; + else + pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + + pcl->clusterbits = EROFS_V(inode)->z_physical_clusterbits[0]; + pcl->clusterbits -= PAGE_SHIFT; - /* new workgrps have been claimed as type 1 */ - WRITE_ONCE(grp->next, *f->owned_head); - /* primary and followed work for all new workgrps */ - *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - /* it should be submitted by ourselves */ - *f->hosted = true; + /* new pclusters should be claimed as type 1, primary and followed */ + pcl->next = clt->owned_head; + clt->mode = COLLECT_PRIMARY_FOLLOWED; - gnew = true; - work = z_erofs_vle_grab_primary_work(grp); - work->pageofs = f->pageofs; + cl = z_erofs_primarycollection(pcl); + cl->pageofs = map->m_la & ~PAGE_MASK; /* * lock all primary followed works before visible to others - * and mutex_trylock *never* fails for a new workgroup. + * and mutex_trylock *never* fails for a new pcluster. */ - mutex_trylock(&work->lock); + mutex_trylock(&cl->lock); - if (gnew) { - int err = erofs_register_workgroup(f->sb, &grp->obj, 0); - - if (err) { - mutex_unlock(&work->lock); - kmem_cache_free(z_erofs_workgroup_cachep, grp); - return ERR_PTR(-EAGAIN); - } + err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); + if (err) { + mutex_unlock(&cl->lock); + kmem_cache_free(pcluster_cachep, pcl); + return ERR_PTR(-EAGAIN); } - - *f->owned_head = &grp->next; - *f->grp_ret = grp; - return work; + clt->owned_head = &pcl->next; + clt->pcl = pcl; + clt->cl = cl; + return cl; } -#define builder_is_hooked(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED) +static int z_erofs_collector_begin(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_collection *cl; -#define builder_is_followed(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + DBG_BUGON(clt->cl); -static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, - struct super_block *sb, - struct erofs_map_blocks *map, - z_erofs_vle_owned_workgrp_t *owned_head) -{ - const unsigned int clusterpages = erofs_clusterpages(EROFS_SB(sb)); - struct z_erofs_vle_workgroup *grp; - const struct z_erofs_vle_work_finder finder = { - .sb = sb, - .idx = erofs_blknr(map->m_pa), - .pageofs = map->m_la & ~PAGE_MASK, - .grp_ret = &grp, - .role = &builder->role, - .owned_head = owned_head, - .hosted = &builder->hosted - }; - struct z_erofs_vle_work *work; - - DBG_BUGON(builder->work); - - /* must be Z_EROFS_WORK_TAIL or the next chained work */ - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_NIL); - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - DBG_BUGON(erofs_blkoff(map->m_pa)); + /* must be Z_EROFS_PCLUSTER_TAIL or pointed to previous collection */ + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_NIL); + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); -repeat: - work = z_erofs_vle_work_lookup(&finder); - if (work) { - unsigned int orig_llen; - - /* increase workgroup `llen' if needed */ - while ((orig_llen = READ_ONCE(grp->llen)) < map->m_llen && - orig_llen != cmpxchg_relaxed(&grp->llen, - orig_llen, map->m_llen)) - cpu_relax(); - goto got_it; + if (!PAGE_ALIGNED(map->m_pa)) { + DBG_BUGON(1); + return -EINVAL; } - work = z_erofs_vle_work_register(&finder, map); - if (unlikely(work == ERR_PTR(-EAGAIN))) - goto repeat; - - if (IS_ERR(work)) - return PTR_ERR(work); -got_it: - z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, work->vcnt); +repeat: + cl = cllookup(clt, inode, map); + if (!cl) { + cl = clregister(clt, inode, map); - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { - /* enable possibly in-place decompression */ - builder->compressed_pages = grp->compressed_pages; - builder->compressed_deficit = clusterpages; - } else { - builder->compressed_pages = NULL; - builder->compressed_deficit = 0; + if (unlikely(cl == ERR_PTR(-EAGAIN))) + goto repeat; } - builder->grp = grp; - builder->work = work; + if (IS_ERR(cl)) + return PTR_ERR(cl); + + z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, cl->vcnt); + + clt->compressedpages = clt->pcl->compressed_pages; + if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ + clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; return 0; } /* - * keep in mind that no referenced workgroups will be freed - * only after a RCU grace period, so rcu_read_lock() could - * prevent a workgroup from being freed. + * keep in mind that no referenced pclusters will be freed + * only after a RCU grace period. */ static void z_erofs_rcu_callback(struct rcu_head *head) { - struct z_erofs_vle_work *work = container_of(head, - struct z_erofs_vle_work, rcu); - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); + struct z_erofs_collection *const cl = + container_of(head, struct z_erofs_collection, rcu); - kmem_cache_free(z_erofs_workgroup_cachep, grp); + kmem_cache_free(pcluster_cachep, + container_of(cl, struct z_erofs_pcluster, + primary_collection)); } void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) { - struct z_erofs_vle_workgroup *const vgrp = container_of(grp, - struct z_erofs_vle_workgroup, obj); - struct z_erofs_vle_work *const work = &vgrp->work; + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct z_erofs_collection *const cl = z_erofs_primarycollection(pcl); - call_rcu(&work->rcu, z_erofs_rcu_callback); + call_rcu(&cl->rcu, z_erofs_rcu_callback); } -static void -__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, - struct z_erofs_vle_work *work __maybe_unused) +static void z_erofs_collection_put(struct z_erofs_collection *cl) { - erofs_workgroup_put(&grp->obj); -} + struct z_erofs_pcluster *const pcl = + container_of(cl, struct z_erofs_pcluster, primary_collection); -static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) -{ - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - __z_erofs_vle_work_release(grp, work); + erofs_workgroup_put(&pcl->obj); } -static inline bool -z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) +static bool z_erofs_collector_end(struct z_erofs_collector *clt) { - struct z_erofs_vle_work *work = builder->work; + struct z_erofs_collection *cl = clt->cl; - if (!work) + if (!cl) return false; - z_erofs_pagevec_ctor_exit(&builder->vector, false); - mutex_unlock(&work->lock); + z_erofs_pagevec_ctor_exit(&clt->vector, false); + mutex_unlock(&cl->lock); /* - * if all pending pages are added, don't hold work reference - * any longer if the current work isn't hosted by ourselves. + * if all pending pages are added, don't hold its reference + * any longer if the pcluster isn't hosted by ourselves. */ - if (!builder->hosted) - __z_erofs_vle_work_release(builder->grp, work); + if (clt->mode < COLLECT_PRIMARY_FOLLOWED_NOINPLACE) + z_erofs_collection_put(cl); - builder->work = NULL; - builder->grp = NULL; + clt->cl = NULL; return true; } @@ -640,33 +547,9 @@ static inline struct page *__stagingpage_alloc(struct list_head *pagepool, return page; } -struct z_erofs_vle_frontend { - struct inode *const inode; - - struct z_erofs_vle_work_builder builder; - struct erofs_map_blocks map; - - z_erofs_vle_owned_workgrp_t owned_head; - - /* used for applying cache strategy on the fly */ - bool backmost; - erofs_off_t headoffset; -}; - -#define VLE_FRONTEND_INIT(__i) { \ - .inode = __i, \ - .map = { \ - .m_llen = 0, \ - .m_plen = 0, \ - .mpage = NULL \ - }, \ - .builder = VLE_WORK_BUILDER_INIT(), \ - .owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \ - .backmost = true, } - #ifdef EROFS_FS_HAS_MANAGED_CACHE -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + erofs_off_t la) { if (fe->backmost) return true; @@ -677,25 +560,23 @@ should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) return false; } #else -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + erofs_off_t la) { return false; } #endif -static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, +static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, struct page *page, - struct list_head *page_pool) + struct list_head *pagepool) { - struct super_block *const sb = fe->inode->i_sb; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + struct inode *const inode = fe->inode; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); struct erofs_map_blocks *const map = &fe->map; - struct z_erofs_vle_work_builder *const builder = &fe->builder; + struct z_erofs_collector *const clt = &fe->clt; const loff_t offset = page_offset(page); - - bool tight = builder_is_hooked(builder); - struct z_erofs_vle_work *work = builder->work; + bool tight = (clt->mode >= COLLECT_PRIMARY_HOOKED); enum z_erofs_cache_alloctype cache_strategy; enum z_erofs_page_type page_type; @@ -713,8 +594,8 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, /* lucky, within the range of the current map_blocks */ if (offset + cur >= map->m_la && offset + cur < map->m_la + map->m_llen) { - /* didn't get a valid unzip work previously (very rare) */ - if (!builder->work) + /* didn't get a valid collection previously (very rare) */ + if (!clt->cl) goto restart_now; goto hitted; } @@ -722,12 +603,12 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, /* go ahead the next map_blocks */ debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); - if (z_erofs_vle_work_iter_end(builder)) + if (z_erofs_collector_end(clt)) fe->backmost = false; map->m_la = offset + cur; map->m_llen = 0; - err = z_erofs_map_blocks_iter(fe->inode, map, 0); + err = z_erofs_map_blocks_iter(inode, map, 0); if (unlikely(err)) goto err_out; @@ -735,10 +616,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) goto hitted; - DBG_BUGON(map->m_plen != 1 << sbi->clusterbits); - DBG_BUGON(erofs_blkoff(map->m_pa)); - - err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head); + err = z_erofs_collector_begin(clt, inode, map); if (unlikely(err)) goto err_out; @@ -748,13 +626,10 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, else cache_strategy = DONTALLOC; - preload_compressed_pages(builder, MNGD_MAPPING(sbi), - map->m_pa / PAGE_SIZE, - map->m_plen / PAGE_SIZE, - cache_strategy, page_pool, GFP_KERNEL); + preload_compressed_pages(clt, MNGD_MAPPING(sbi), + cache_strategy, pagepool); - tight &= builder_is_hooked(builder); - work = builder->work; + tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED); hitted: cur = end - min_t(unsigned int, offset + end - map->m_la, end); if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { @@ -769,17 +644,17 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); if (cur) - tight &= builder_is_followed(builder); + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); retry: - err = z_erofs_vle_work_add_page(builder, page, page_type); + err = z_erofs_attach_page(clt, page, page_type); /* should allocate an additional staging page for pagevec */ if (err == -EAGAIN) { struct page *const newpage = - __stagingpage_alloc(page_pool, GFP_NOFS); + __stagingpage_alloc(pagepool, GFP_NOFS); - err = z_erofs_vle_work_add_page(builder, newpage, - Z_EROFS_PAGE_TYPE_EXCLUSIVE); + err = z_erofs_attach_page(clt, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); if (likely(!err)) goto retry; } @@ -787,15 +662,14 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, if (unlikely(err)) goto err_out; - index = page->index - map->m_la / PAGE_SIZE; + index = page->index - (map->m_la >> PAGE_SHIFT); - /* FIXME! avoid the last relundant fixup & endio */ z_erofs_onlinepage_fixup(page, index, true); /* bump up the number of spiltted parts of a page */ ++spiltted; /* also update nr_pages */ - work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1); + clt->cl->nr_pages = max_t(pgoff_t, clt->cl->nr_pages, index + 1); next_part: /* can be used for verification */ map->m_llen = offset + cur - map->m_la; @@ -805,7 +679,6 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, goto repeat; out: - /* FIXME! avoid the last relundant fixup & endio */ z_erofs_onlinepage_endio(page); debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", @@ -821,7 +694,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) { tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t); + struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); bool background = tagptr_unfold_tags(t); if (!background) { @@ -878,45 +751,38 @@ static inline void z_erofs_vle_read_endio(struct bio *bio) bio_put(bio); } -static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; -static DEFINE_MUTEX(z_pagemap_global_lock); - -static int z_erofs_vle_unzip(struct super_block *sb, - struct z_erofs_vle_workgroup *grp, - struct list_head *page_pool) +static int z_erofs_decompress_pcluster(struct super_block *sb, + struct z_erofs_pcluster *pcl, + struct list_head *pagepool) { struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - + const unsigned int clusterpages = BIT(pcl->clusterbits); struct z_erofs_pagevec_ctor ctor; - unsigned int nr_pages; - unsigned int sparsemem_pages = 0; - struct page *pages_onstack[Z_EROFS_VLE_VMAP_ONSTACK_PAGES]; + unsigned int i, outputsize, llen, nr_pages; + struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; struct page **pages, **compressed_pages, *page; - unsigned int algorithm; - unsigned int i, outputsize; enum z_erofs_page_type page_type; bool overlapped, partial; - struct z_erofs_vle_work *work; + struct z_erofs_collection *cl; int err; might_sleep(); - work = z_erofs_vle_grab_primary_work(grp); - DBG_BUGON(!READ_ONCE(work->nr_pages)); + cl = z_erofs_primarycollection(pcl); + DBG_BUGON(!READ_ONCE(cl->nr_pages)); - mutex_lock(&work->lock); - nr_pages = work->nr_pages; + mutex_lock(&cl->lock); + nr_pages = cl->nr_pages; - if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) + if (likely(nr_pages <= Z_EROFS_VMAP_ONSTACK_PAGES)) { pages = pages_onstack; - else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) + } else if (nr_pages <= Z_EROFS_VMAP_GLOBAL_PAGES && + mutex_trylock(&z_pagemap_global_lock)) { pages = z_pagemap_global; - else { + } else { gfp_t gfp_flags = GFP_KERNEL; - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) + if (nr_pages > Z_EROFS_VMAP_GLOBAL_PAGES) gfp_flags |= __GFP_NOFAIL; pages = kvmalloc_array(nr_pages, sizeof(struct page *), @@ -933,9 +799,9 @@ static int z_erofs_vle_unzip(struct super_block *sb, pages[i] = NULL; z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, 0); + cl->pagevec, 0); - for (i = 0; i < work->vcnt; ++i) { + for (i = 0; i < cl->vcnt; ++i) { unsigned int pagenr; page = z_erofs_pagevec_dequeue(&ctor, &page_type); @@ -944,7 +810,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, DBG_BUGON(!page); DBG_BUGON(!page->mapping); - if (z_erofs_put_stagingpage(page_pool, page)) + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) @@ -957,12 +823,10 @@ static int z_erofs_vle_unzip(struct super_block *sb, pages[pagenr] = page; } - sparsemem_pages = i; - z_erofs_pagevec_ctor_exit(&ctor, true); overlapped = false; - compressed_pages = grp->compressed_pages; + compressed_pages = pcl->compressed_pages; err = 0; for (i = 0; i < clusterpages; ++i) { @@ -989,7 +853,6 @@ static int z_erofs_vle_unzip(struct super_block *sb, DBG_BUGON(pagenr >= nr_pages); DBG_BUGON(pages[pagenr]); - ++sparsemem_pages; pages[pagenr] = page; overlapped = true; @@ -1005,30 +868,26 @@ static int z_erofs_vle_unzip(struct super_block *sb, if (unlikely(err)) goto out; - if (nr_pages << PAGE_SHIFT >= work->pageofs + grp->llen) { - outputsize = grp->llen; - partial = !(grp->flags & Z_EROFS_VLE_WORKGRP_FULL_LENGTH); + llen = pcl->length >> Z_EROFS_PCLUSTER_LENGTH_BIT; + if (nr_pages << PAGE_SHIFT >= cl->pageofs + llen) { + outputsize = llen; + partial = !(pcl->length & Z_EROFS_PCLUSTER_FULL_LENGTH); } else { - outputsize = (nr_pages << PAGE_SHIFT) - work->pageofs; + outputsize = (nr_pages << PAGE_SHIFT) - cl->pageofs; partial = true; } - if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) - algorithm = Z_EROFS_COMPRESSION_SHIFTED; - else - algorithm = Z_EROFS_COMPRESSION_LZ4; - err = z_erofs_decompress(&(struct z_erofs_decompress_req) { .sb = sb, .in = compressed_pages, .out = pages, - .pageofs_out = work->pageofs, + .pageofs_out = cl->pageofs, .inputsize = PAGE_SIZE, .outputsize = outputsize, - .alg = algorithm, + .alg = pcl->algorithmformat, .inplace_io = overlapped, .partial_decoding = partial - }, page_pool); + }, pagepool); out: /* must handle all compressed pages before endding pages */ @@ -1039,7 +898,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, continue; /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(page_pool, page); + (void)z_erofs_put_stagingpage(pagepool, page); WRITE_ONCE(compressed_pages[i], NULL); } @@ -1052,7 +911,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, DBG_BUGON(!page->mapping); /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(page_pool, page)) + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (unlikely(err < 0)) @@ -1066,65 +925,63 @@ static int z_erofs_vle_unzip(struct super_block *sb, else if (unlikely(pages != pages_onstack)) kvfree(pages); - work->nr_pages = 0; - work->vcnt = 0; + cl->nr_pages = 0; + cl->vcnt = 0; - /* all work locks MUST be taken before the following line */ + /* all cl locks MUST be taken before the following line */ + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_NIL); - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_NIL); + /* all cl locks SHOULD be released right now */ + mutex_unlock(&cl->lock); - /* all work locks SHOULD be released right now */ - mutex_unlock(&work->lock); - - z_erofs_vle_work_release(work); + z_erofs_collection_put(cl); return err; } static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - struct list_head *page_pool) + struct z_erofs_unzip_io *io, + struct list_head *pagepool) { - z_erofs_vle_owned_workgrp_t owned = io->head; + z_erofs_next_pcluster_t owned = io->head; - while (owned != Z_EROFS_VLE_WORKGRP_TAIL_CLOSED) { - struct z_erofs_vle_workgroup *grp; + while (owned != Z_EROFS_PCLUSTER_TAIL_CLOSED) { + struct z_erofs_pcluster *pcl; /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_TAIL); + DBG_BUGON(owned == Z_EROFS_PCLUSTER_TAIL); /* no possible that 'owned' equals NULL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_NIL); + DBG_BUGON(owned == Z_EROFS_PCLUSTER_NIL); - grp = container_of(owned, struct z_erofs_vle_workgroup, next); - owned = READ_ONCE(grp->next); + pcl = container_of(owned, struct z_erofs_pcluster, next); + owned = READ_ONCE(pcl->next); - z_erofs_vle_unzip(sb, grp, page_pool); + z_erofs_decompress_pcluster(sb, pcl, pagepool); } } static void z_erofs_vle_unzip_wq(struct work_struct *work) { - struct z_erofs_vle_unzip_io_sb *iosb = container_of(work, - struct z_erofs_vle_unzip_io_sb, io.u.work); - LIST_HEAD(page_pool); + struct z_erofs_unzip_io_sb *iosb = + container_of(work, struct z_erofs_unzip_io_sb, io.u.work); + LIST_HEAD(pagepool); - DBG_BUGON(iosb->io.head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &page_pool); + DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); - put_pages_list(&page_pool); + put_pages_list(&pagepool); kvfree(iosb); } -static struct page * -pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, - unsigned int nr, - struct list_head *pagepool, - struct address_space *mc, - gfp_t gfp) +static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + unsigned int nr, + struct list_head *pagepool, + struct address_space *mc, + gfp_t gfp) { /* determined at compile time to avoid too many #ifdefs */ const bool nocache = __builtin_constant_p(mc) ? !mc : false; - const pgoff_t index = grp->obj.index; + const pgoff_t index = pcl->obj.index; bool tocache = false; struct address_space *mapping; @@ -1134,7 +991,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, int justfound; repeat: - page = READ_ONCE(grp->compressed_pages[nr]); + page = READ_ONCE(pcl->compressed_pages[nr]); oldpage = page; if (!page) @@ -1186,7 +1043,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, /* the page is still in manage cache */ if (page->mapping == mc) { - WRITE_ONCE(grp->compressed_pages[nr], page); + WRITE_ONCE(pcl->compressed_pages[nr], page); ClearPageError(page); if (!PagePrivate(page)) { @@ -1198,7 +1055,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, DBG_BUGON(!justfound); justfound = 0; - set_page_private(page, (unsigned long)grp); + set_page_private(page, (unsigned long)pcl); SetPagePrivate(page); } @@ -1222,7 +1079,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, put_page(page); out_allocpage: page = __stagingpage_alloc(pagepool, gfp); - if (oldpage != cmpxchg(&grp->compressed_pages[nr], oldpage, page)) { + if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { list_add(&page->lru, pagepool); cpu_relax(); goto repeat; @@ -1234,18 +1091,17 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, goto out; } - set_page_private(page, (unsigned long)grp); + set_page_private(page, (unsigned long)pcl); SetPagePrivate(page); out: /* the only exit (for tracing and debugging) */ return page; } -static struct z_erofs_vle_unzip_io * -jobqueue_init(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - bool foreground) +static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, + struct z_erofs_unzip_io *io, + bool foreground) { - struct z_erofs_vle_unzip_io_sb *iosb; + struct z_erofs_unzip_io_sb *iosb; if (foreground) { /* waitqueue available for foreground io */ @@ -1264,11 +1120,11 @@ jobqueue_init(struct super_block *sb, iosb->sb = sb; INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); out: - io->head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; return io; } -/* define workgroup jobqueue types */ +/* define decompression jobqueue types */ enum { #ifdef EROFS_FS_HAS_MANAGED_CACHE JQ_BYPASS, @@ -1278,15 +1134,15 @@ enum { }; static void *jobqueueset_init(struct super_block *sb, - z_erofs_vle_owned_workgrp_t qtail[], - struct z_erofs_vle_unzip_io *q[], - struct z_erofs_vle_unzip_io *fgq, + z_erofs_next_pcluster_t qtail[], + struct z_erofs_unzip_io *q[], + struct z_erofs_unzip_io *fgq, bool forcefg) { #ifdef EROFS_FS_HAS_MANAGED_CACHE /* * if managed cache is enabled, bypass jobqueue is needed, - * no need to read from device for all workgroups in this queue. + * no need to read from device for all pclusters in this queue. */ q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; @@ -1299,26 +1155,26 @@ static void *jobqueueset_init(struct super_block *sb, } #ifdef EROFS_FS_HAS_MANAGED_CACHE -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) { - z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT]; - z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS]; + z_erofs_next_pcluster_t *const submit_qtail = qtail[JQ_SUBMIT]; + z_erofs_next_pcluster_t *const bypass_qtail = qtail[JQ_BYPASS]; - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL) - owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + owned_head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_TAIL_CLOSED); WRITE_ONCE(*submit_qtail, owned_head); - WRITE_ONCE(*bypass_qtail, &grp->next); + WRITE_ONCE(*bypass_qtail, &pcl->next); - qtail[JQ_BYPASS] = &grp->next; + qtail[JQ_BYPASS] = &pcl->next; } -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], unsigned int nr_bios, bool force_fg) { @@ -1329,21 +1185,19 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], if (force_fg || nr_bios) return false; - kvfree(container_of(q[JQ_SUBMIT], - struct z_erofs_vle_unzip_io_sb, - io)); + kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); return true; } #else -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) { /* impossible to bypass submission for managed cache disabled */ DBG_BUGON(1); } -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], unsigned int nr_bios, bool force_fg) { @@ -1354,17 +1208,14 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], #endif static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_vle_owned_workgrp_t owned_head, + z_erofs_next_pcluster_t owned_head, struct list_head *pagepool, - struct z_erofs_vle_unzip_io *fgq, + struct z_erofs_unzip_io *fgq, bool force_fg) { - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - const gfp_t gfp = GFP_NOFS; - - z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES]; - struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES]; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; + struct z_erofs_unzip_io *q[NR_JOBQUEUES]; struct bio *bio; void *bi_private; /* since bio will be NULL, no need to initialize last_index */ @@ -1372,7 +1223,7 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, bool force_submit = false; unsigned int nr_bios; - if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL)) + if (unlikely(owned_head == Z_EROFS_PCLUSTER_TAIL)) return false; force_submit = false; @@ -1384,29 +1235,32 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, q[JQ_SUBMIT]->head = owned_head; do { - struct z_erofs_vle_workgroup *grp; + struct z_erofs_pcluster *pcl; + unsigned int clusterpages; pgoff_t first_index; struct page *page; unsigned int i = 0, bypass = 0; int err; /* no possible 'owned_head' equals the following */ - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_NIL); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned_head, struct z_erofs_pcluster, next); - grp = container_of(owned_head, - struct z_erofs_vle_workgroup, next); + clusterpages = BIT(pcl->clusterbits); /* close the main owned chain at first */ - owned_head = cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + Z_EROFS_PCLUSTER_TAIL_CLOSED); - first_index = grp->obj.index; + first_index = pcl->obj.index; force_submit |= (first_index != last_index + 1); repeat: - page = pickup_page_for_submission(grp, i, pagepool, - MNGD_MAPPING(sbi), gfp); + page = pickup_page_for_submission(pcl, i, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); if (!page) { force_submit = true; ++bypass; @@ -1437,10 +1291,10 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, goto repeat; if (bypass < clusterpages) - qtail[JQ_SUBMIT] = &grp->next; + qtail[JQ_SUBMIT] = &pcl->next; else - move_to_bypass_jobqueue(grp, qtail, owned_head); - } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL); + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); if (bio) __submit_bio(bio, REQ_OP_READ, 0); @@ -1452,17 +1306,19 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, return true; } -static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f, +static void z_erofs_submit_and_unzip(struct super_block *sb, + struct z_erofs_collector *clt, struct list_head *pagepool, bool force_fg) { - struct super_block *sb = f->inode->i_sb; - struct z_erofs_vle_unzip_io io[NR_JOBQUEUES]; + struct z_erofs_unzip_io io[NR_JOBQUEUES]; - if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg)) + if (!z_erofs_vle_submit_all(sb, clt->owned_head, + pagepool, io, force_fg)) return; #ifdef EROFS_FS_HAS_MANAGED_CACHE + /* decompress no I/O pclusters immediately */ z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); #endif if (!force_fg) @@ -1480,7 +1336,7 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, struct page *page) { struct inode *const inode = page->mapping->host; - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); int err; LIST_HEAD(pagepool); @@ -1489,14 +1345,14 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; err = z_erofs_do_read_page(&f, page, &pagepool); - (void)z_erofs_vle_work_iter_end(&f.builder); + (void)z_erofs_collector_end(&f.clt); if (err) { errln("%s, failed to read, err [%d]", __func__, err); goto out; } - z_erofs_submit_and_unzip(&f, &pagepool, true); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); out: if (f.map.mpage) put_page(f.map.mpage); @@ -1521,7 +1377,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct erofs_sb_info *const sbi = EROFS_I_SB(inode); bool sync = should_decompress_synchronously(sbi, nr_pages); - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); struct page *head = NULL; LIST_HEAD(pagepool); @@ -1567,13 +1423,12 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, errln("%s, readahead error at page %lu of nid %llu", __func__, page->index, vi->nid); } - put_page(page); } - (void)z_erofs_vle_work_iter_end(&f.builder); + (void)z_erofs_collector_end(&f.clt); - z_erofs_submit_and_unzip(&f, &pagepool, sync); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); if (f.map.mpage) put_page(f.map.mpage); diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 6574d43ba877..1f51d80fa89f 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -18,80 +18,77 @@ * Structure fields follow one of the following exclusion rules. * * I: Modifiable by initialization/destruction paths and read-only - * for everyone else. + * for everyone else; * + * L: Field should be protected by pageset lock; + * + * A: Field should be accessed / updated in atomic for parallelized code. */ - -struct z_erofs_vle_work { +struct z_erofs_collection { struct mutex lock; - /* I: decompression offset in page */ + /* I: page offset of start position of decompression */ unsigned short pageofs; + + /* L: maximum relative page index in pagevec[] */ unsigned short nr_pages; - /* L: queued pages in pagevec[] */ + /* L: total number of pages in pagevec[] */ unsigned int vcnt; union { - /* L: pagevec */ + /* L: inline a certain number of pagevecs for bootstrap */ erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; + + /* I: can be used to free the pcluster by RCU. */ struct rcu_head rcu; }; }; -#define Z_EROFS_VLE_WORKGRP_FMT_PLAIN 0 -#define Z_EROFS_VLE_WORKGRP_FMT_LZ4 1 -#define Z_EROFS_VLE_WORKGRP_FMT_MASK 1 -#define Z_EROFS_VLE_WORKGRP_FULL_LENGTH 2 +#define Z_EROFS_PCLUSTER_FULL_LENGTH 0x00000001 +#define Z_EROFS_PCLUSTER_LENGTH_BIT 1 -typedef void *z_erofs_vle_owned_workgrp_t; +/* + * let's leave a type here in case of introducing + * another tagged pointer later. + */ +typedef void *z_erofs_next_pcluster_t; -struct z_erofs_vle_workgroup { +struct z_erofs_pcluster { struct erofs_workgroup obj; - struct z_erofs_vle_work work; + struct z_erofs_collection primary_collection; - /* point to next owned_workgrp_t */ - z_erofs_vle_owned_workgrp_t next; + /* A: point to next chained pcluster or TAILs */ + z_erofs_next_pcluster_t next; - /* compressed pages (including multi-usage pages) */ + /* A: compressed pages (including multi-usage pages) */ struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - unsigned int llen, flags; + + /* A: lower limit of decompressed length and if full length or not */ + unsigned int length; + + /* I: compression algorithm format */ + unsigned char algorithmformat; + /* I: bit shift of physical cluster size */ + unsigned char clusterbits; }; +#define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) + /* let's avoid the valid 32-bit kernel addresses */ /* the chained workgroup has't submitted io (still open) */ -#define Z_EROFS_VLE_WORKGRP_TAIL ((void *)0x5F0ECAFE) +#define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE) /* the chained workgroup has already submitted io */ -#define Z_EROFS_VLE_WORKGRP_TAIL_CLOSED ((void *)0x5F0EDEAD) +#define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD) -#define Z_EROFS_VLE_WORKGRP_NIL (NULL) +#define Z_EROFS_PCLUSTER_NIL (NULL) -#define z_erofs_vle_workgrp_fmt(grp) \ - ((grp)->flags & Z_EROFS_VLE_WORKGRP_FMT_MASK) +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) -static inline void z_erofs_vle_set_workgrp_fmt( - struct z_erofs_vle_workgroup *grp, - unsigned int fmt) -{ - grp->flags = fmt | (grp->flags & ~Z_EROFS_VLE_WORKGRP_FMT_MASK); -} - - -/* definitions if multiref is disabled */ -#define z_erofs_vle_grab_primary_work(grp) (&(grp)->work) -#define z_erofs_vle_grab_work(grp, pageofs) (&(grp)->work) -#define z_erofs_vle_work_workgroup(wrk, primary) \ - ((primary) ? container_of(wrk, \ - struct z_erofs_vle_workgroup, work) : \ - ({ BUG(); (void *)NULL; })) - - -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_vle_workgroup) - -struct z_erofs_vle_unzip_io { +struct z_erofs_unzip_io { atomic_t pending_bios; - z_erofs_vle_owned_workgrp_t head; + z_erofs_next_pcluster_t head; union { wait_queue_head_t wait; @@ -99,8 +96,8 @@ struct z_erofs_vle_unzip_io { } u; }; -struct z_erofs_vle_unzip_io_sb { - struct z_erofs_vle_unzip_io io; +struct z_erofs_unzip_io_sb { + struct z_erofs_unzip_io io; struct super_block *sb; }; @@ -117,8 +114,8 @@ static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) { return false; } #endif /* !EROFS_FS_HAS_MANAGED_CACHE */ -#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 -#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) +#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 +#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) /* @@ -193,13 +190,12 @@ static inline void z_erofs_onlinepage_endio(struct page *page) SetPageUptodate(page); unlock_page(page); } - debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); } -#define Z_EROFS_VLE_VMAP_ONSTACK_PAGES \ +#define Z_EROFS_VMAP_ONSTACK_PAGES \ min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) -#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 +#define Z_EROFS_VMAP_GLOBAL_PAGES 2048 #endif -- GitLab From eace994a116c9704738be3388f5777c740d9558d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:48 +0800 Subject: [PATCH 1686/7155] staging: erofs: remove clusterbits in sbi clustersize can now be set on per-file basis rather than per-filesystem basis. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-19-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 5 ----- drivers/staging/erofs/super.c | 9 --------- drivers/staging/erofs/zmap.c | 3 +-- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index a631acd0dc62..3176c350779e 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -77,8 +77,6 @@ struct erofs_sb_info { struct list_head list; struct mutex umount_mutex; - /* cluster size in bit shift */ - unsigned char clusterbits; /* the dedicated workstation for compression */ struct radix_tree_root workstn_tree; @@ -248,9 +246,6 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) /* hard limit of pages per compressed cluster */ #define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) #define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES - -/* page count of a compressed cluster */ -#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) #else #define EROFS_PCPUBUF_NR_PAGES 0 #endif /* !CONFIG_EROFS_FS_ZIP */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index af5d87793e4d..dad5a3137988 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -124,15 +124,6 @@ static int superblock_read(struct super_block *sb) sbi->xattr_blkaddr = le32_to_cpu(layout->xattr_blkaddr); #endif sbi->islotbits = ffs(sizeof(struct erofs_inode_v1)) - 1; -#ifdef CONFIG_EROFS_FS_ZIP - /* TODO: clusterbits should be related to inode */ - sbi->clusterbits = blkszbits; - - if (1 << (sbi->clusterbits - PAGE_SHIFT) > Z_EROFS_CLUSTER_MAX_PAGES) - errln("clusterbits %u is not supported on this kernel", - sbi->clusterbits); -#endif - sbi->root_nid = le16_to_cpu(layout->root_nid); sbi->inos = le64_to_cpu(layout->inos); diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 205e884ca4e0..aeed5c674d9e 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -13,13 +13,12 @@ int z_erofs_fill_inode(struct inode *inode) { struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; if (vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; - vi->z_logical_clusterbits = EROFS_SB(sb)->clusterbits; + vi->z_logical_clusterbits = LOG_BLOCK_SIZE; vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); -- GitLab From 4279f3f9889f26bcdc4d35c0bf868a08e09470c7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:49 +0800 Subject: [PATCH 1687/7155] staging: erofs: turn cache strategies into mount options Kill all kconfig cache strategies and turn them into mount options "cache_strategy={disable|readahead|readaround}". As the first step, cached pages can still be usable after cache is disabled by remounting, and these pages will be fallen out over time, which can be refined in the later version if some requirement is needed. Update related document as well. Suggested-by: Theodore Ts'o Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-20-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- .../erofs/Documentation/filesystems/erofs.txt | 10 +++ drivers/staging/erofs/Kconfig | 38 ----------- drivers/staging/erofs/internal.h | 25 +++----- drivers/staging/erofs/super.c | 64 +++++++++++++++++-- drivers/staging/erofs/utils.c | 26 -------- drivers/staging/erofs/zdata.c | 56 +++------------- drivers/staging/erofs/zdata.h | 6 -- 7 files changed, 85 insertions(+), 140 deletions(-) diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt index 04cf47865c50..0eab600ca7ca 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -65,6 +65,16 @@ fault_injection=%d Enable fault injection in all supported types with by default if CONFIG_EROFS_FS_XATTR is selected. (no)acl Setup POSIX Access Control List. Note: acl is enabled by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +cache_strategy=%s Select a strategy for cached decompression from now on: + disabled: In-place I/O decompression only; + readahead: Cache the last incomplete compressed physical + cluster for further reading. It still does + in-place I/O decompression for the rest + compressed physical clusters; + readaround: Cache the both ends of incomplete compressed + physical clusters for further reading. + It still does in-place I/O decompression + for the rest compressed physical clusters. Module parameters ================= diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 788beebf3f7d..1a8e48943e50 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -94,41 +94,3 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT than 2. Otherwise, the image cannot be mounted correctly on this kernel. -choice - prompt "EROFS VLE Data Decompression mode" - depends on EROFS_FS_ZIP - default EROFS_FS_ZIP_CACHE_BIPOLAR - help - EROFS supports three options for VLE decompression. - "In-place Decompression Only" consumes the minimum memory - with lowest random read. - - "Bipolar Cached Decompression" consumes the maximum memory - with highest random read. - - If unsure, select "Bipolar Cached Decompression" - -config EROFS_FS_ZIP_NO_CACHE - bool "In-place Decompression Only" - help - Read compressed data into page cache and do in-place - decompression directly. - -config EROFS_FS_ZIP_CACHE_UNIPOLAR - bool "Unipolar Cached Decompression" - help - For each request, it caches the last compressed page - for further reading. - It still decompresses in place for the rest compressed pages. - -config EROFS_FS_ZIP_CACHE_BIPOLAR - bool "Bipolar Cached Decompression" - help - For each request, it caches the both end compressed pages - for further reading. - It still decompresses in place for the rest compressed pages. - - Recommended for performance priority. - -endchoice - diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 3176c350779e..118e7c7e4d4d 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -51,18 +51,6 @@ struct erofs_fault_info { }; #endif /* CONFIG_EROFS_FAULT_INJECTION */ -#ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR -#define EROFS_FS_ZIP_CACHE_LVL (2) -#elif defined(EROFS_FS_ZIP_CACHE_UNIPOLAR) -#define EROFS_FS_ZIP_CACHE_LVL (1) -#else -#define EROFS_FS_ZIP_CACHE_LVL (0) -#endif - -#if (!defined(EROFS_FS_HAS_MANAGED_CACHE) && (EROFS_FS_ZIP_CACHE_LVL > 0)) -#define EROFS_FS_HAS_MANAGED_CACHE -#endif - /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 @@ -85,10 +73,11 @@ struct erofs_sb_info { unsigned int shrinker_run_no; -#ifdef EROFS_FS_HAS_MANAGED_CACHE - struct inode *managed_cache; -#endif + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; + /* pseudo inode to manage cached pages */ + struct inode *managed_cache; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -174,6 +163,12 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP +enum { + EROFS_ZIP_CACHE_DISABLED, + EROFS_ZIP_CACHE_READAHEAD, + EROFS_ZIP_CACHE_READAROUND +}; + #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) /* basic unit of the workstation of a super_block */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index dad5a3137988..a14fa5228bca 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -197,17 +197,50 @@ static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) } #endif +#ifdef CONFIG_EROFS_FS_ZIP +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + const char *cs = match_strdup(args); + int err = 0; + + if (!cs) { + errln("Not enough memory to store cache strategy"); + return -ENOMEM; + } + + if (!strcmp(cs, "disabled")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; + } else if (!strcmp(cs, "readahead")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; + } else if (!strcmp(cs, "readaround")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + } else { + errln("Unrecognized cache strategy \"%s\"", cs); + err = -EINVAL; + } + kfree(cs); + return err; +} +#else +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + infoln("EROFS compression is disabled, so cache strategy is ignored"); + return 0; +} +#endif + +/* set up default EROFS parameters */ static void default_options(struct erofs_sb_info *sbi) { - /* set up some FS parameters */ #ifdef CONFIG_EROFS_FS_ZIP + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; sbi->max_sync_decompress_pages = 3; #endif - #ifdef CONFIG_EROFS_FS_XATTR set_opt(sbi, XATTR_USER); #endif - #ifdef CONFIG_EROFS_FS_POSIX_ACL set_opt(sbi, POSIX_ACL); #endif @@ -219,6 +252,7 @@ enum { Opt_acl, Opt_noacl, Opt_fault_injection, + Opt_cache_strategy, Opt_err }; @@ -228,6 +262,7 @@ static match_table_t erofs_tokens = { {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_fault_injection, "fault_injection=%u"}, + {Opt_cache_strategy, "cache_strategy=%s"}, {Opt_err, NULL} }; @@ -285,7 +320,11 @@ static int parse_options(struct super_block *sb, char *options) if (err) return err; break; - + case Opt_cache_strategy: + err = erofs_build_cache_strategy(EROFS_SB(sb), args); + if (err) + return err; + break; default: errln("Unrecognized mount option \"%s\" " "or missing value", p); @@ -295,8 +334,7 @@ static int parse_options(struct super_block *sb, char *options) return 0; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE - +#ifdef CONFIG_EROFS_FS_ZIP static const struct address_space_operations managed_cache_aops; static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) @@ -469,7 +507,7 @@ static void erofs_put_super(struct super_block *sb) DBG_BUGON(!sbi); erofs_shrinker_unregister(sb); -#ifdef EROFS_FS_HAS_MANAGED_CACHE +#ifdef CONFIG_EROFS_FS_ZIP iput(sbi->managed_cache); sbi->managed_cache = NULL; #endif @@ -570,6 +608,18 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root) if (test_opt(sbi, FAULT_INJECTION)) seq_printf(seq, ",fault_injection=%u", erofs_get_fault_rate(sbi)); +#ifdef CONFIG_EROFS_FS_ZIP + if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { + seq_puts(seq, ",cache_strategy=disabled"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { + seq_puts(seq, ",cache_strategy=readahead"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { + seq_puts(seq, ",cache_strategy=readaround"); + } else { + seq_puts(seq, ",cache_strategy=(unknown)"); + DBG_BUGON(1); + } +#endif return 0; } diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 260ea2970b4b..0e6308b15717 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -145,8 +145,6 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE -/* for cache-managed case, customized reclaim paths exist */ static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) { erofs_workgroup_unfreeze(grp, 0); @@ -192,30 +190,6 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, return true; } -#else -/* for nocache case, no customized reclaim path at all */ -static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) -{ - int cnt = atomic_read(&grp->refcount); - - DBG_BUGON(cnt <= 0); - DBG_BUGON(cleanup && cnt != 1); - - if (cnt > 1) - return false; - - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, - grp->index)) != grp); - - /* (rarely) could be grabbed again when freeing */ - erofs_workgroup_put(grp); - return true; -} - -#endif - static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, unsigned long nr_shrink, bool cleanup) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 6ebee2ca8dc5..2d7aaf98f7de 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -162,7 +162,6 @@ struct z_erofs_decompress_frontend { static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; static DEFINE_MUTEX(z_pagemap_global_lock); -#ifdef EROFS_FS_HAS_MANAGED_CACHE static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, enum z_erofs_cache_alloctype type, @@ -273,15 +272,6 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, } return ret; } -#else -static void preload_compressed_pages(struct z_erofs_collector *clt, - struct address_space *mc, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool) -{ - /* nowhere to load compressed pages from */ -} -#endif /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ static inline bool try_inplace_io(struct z_erofs_collector *clt, @@ -547,25 +537,19 @@ static inline struct page *__stagingpage_alloc(struct list_head *pagepool, return page; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + unsigned int cachestrategy, erofs_off_t la) { + if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED) + return false; + if (fe->backmost) return true; - if (EROFS_FS_ZIP_CACHE_LVL >= 2) - return la < fe->headoffset; - - return false; -} -#else -static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, - erofs_off_t la) -{ - return false; + return cachestrategy >= EROFS_ZIP_CACHE_READAROUND && + la < fe->headoffset; } -#endif static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, struct page *page, @@ -621,7 +605,7 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, goto err_out; /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, map->m_la)) + if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) cache_strategy = DELAYEDALLOC; else cache_strategy = DONTALLOC; @@ -1126,9 +1110,7 @@ static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, /* define decompression jobqueue types */ enum { -#ifdef EROFS_FS_HAS_MANAGED_CACHE JQ_BYPASS, -#endif JQ_SUBMIT, NR_JOBQUEUES, }; @@ -1139,14 +1121,12 @@ static void *jobqueueset_init(struct super_block *sb, struct z_erofs_unzip_io *fgq, bool forcefg) { -#ifdef EROFS_FS_HAS_MANAGED_CACHE /* * if managed cache is enabled, bypass jobqueue is needed, * no need to read from device for all pclusters in this queue. */ q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; -#endif q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; @@ -1154,7 +1134,6 @@ static void *jobqueueset_init(struct super_block *sb, return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); } -#ifdef EROFS_FS_HAS_MANAGED_CACHE static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, z_erofs_next_pcluster_t qtail[], z_erofs_next_pcluster_t owned_head) @@ -1188,24 +1167,6 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); return true; } -#else -static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, - z_erofs_next_pcluster_t qtail[], - z_erofs_next_pcluster_t owned_head) -{ - /* impossible to bypass submission for managed cache disabled */ - DBG_BUGON(1); -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* bios should be >0 if managed cache is disabled */ - DBG_BUGON(!nr_bios); - return false; -} -#endif static bool z_erofs_vle_submit_all(struct super_block *sb, z_erofs_next_pcluster_t owned_head, @@ -1317,10 +1278,9 @@ static void z_erofs_submit_and_unzip(struct super_block *sb, pagepool, io, force_fg)) return; -#ifdef EROFS_FS_HAS_MANAGED_CACHE /* decompress no I/O pclusters immediately */ z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); -#endif + if (!force_fg) return; diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 1f51d80fa89f..e11fe1959ca2 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -101,18 +101,12 @@ struct z_erofs_unzip_io_sb { struct super_block *sb; }; -#ifdef EROFS_FS_HAS_MANAGED_CACHE #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) { return page->mapping == MNGD_MAPPING(sbi); } -#else -#define MNGD_MAPPING(sbi) (NULL) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) { return false; } -#endif /* !EROFS_FS_HAS_MANAGED_CACHE */ #define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 #define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) -- GitLab From 2bb90cc275e242eb3965a9091c359c2c8327a1e7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:50 +0800 Subject: [PATCH 1688/7155] staging: erofs: tidy up utils.c Keep in line with erofs-outofstaging patchset: - Update comments in erofs_try_to_release_workgroup; - code style cleanup. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-21-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/utils.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 0e6308b15717..814c2ee037ae 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -114,8 +114,7 @@ int erofs_register_workgroup(struct super_block *sb, */ __erofs_workgroup_get(grp); - err = radix_tree_insert(&sbi->workstn_tree, - grp->index, grp); + err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); if (unlikely(err)) /* * it's safe to decrease since the workgroup isn't visible @@ -156,18 +155,18 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, bool cleanup) { /* - * for managed cache enabled, the refcount of workgroups - * themselves could be < 0 (freezed). So there is no guarantee - * that all refcount > 0 if managed cache is enabled. + * If managed cache is on, refcount of workgroups + * themselves could be < 0 (freezed). In other words, + * there is no guarantee that all refcounts > 0. */ if (!erofs_workgroup_try_to_freeze(grp, 1)) return false; /* - * note that all cached pages should be unlinked - * before delete it from the radix tree. - * Otherwise some cached pages of an orphan old workgroup - * could be still linked after the new one is available. + * Note that all cached pages should be unattached + * before deleted from the radix tree. Otherwise some + * cached pages could be still attached to the orphan + * old workgroup when the new one is available in the tree. */ if (erofs_try_to_free_all_cached_pages(sbi, grp)) { erofs_workgroup_unfreeze(grp, 1); @@ -175,7 +174,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, } /* - * it is impossible to fail after the workgroup is freezed, + * It's impossible to fail after the workgroup is freezed, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ @@ -183,8 +182,8 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, grp->index)) != grp); /* - * if managed cache is enable, the last refcount - * should indicate the related workstation. + * If managed cache is on, last refcount should indicate + * the related workstation. */ erofs_workgroup_unfreeze_final(grp); return true; @@ -273,9 +272,9 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, unsigned long freed = 0; spin_lock(&erofs_sb_list_lock); - do + do { run_no = ++shrinker_run_no; - while (run_no == 0); + } while (run_no == 0); /* Iterate over all mounted superblocks and try to shrink them */ p = erofs_sb_list.next; -- GitLab From bc33d9f35da87cccd73fe5d3e007acb084411309 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:51 +0800 Subject: [PATCH 1689/7155] staging: erofs: update super.c Keep in line with erofs-outofstaging patchset: - "Chao Yu" is most commonly used in Linux community; - quoted string split across lines. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-22-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index a14fa5228bca..f65a1ff9f42f 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -326,8 +326,7 @@ static int parse_options(struct super_block *sb, char *options) return err; break; default: - errln("Unrecognized mount option \"%s\" " - "or missing value", p); + errln("Unrecognized mount option \"%s\" or missing value", p); return -EINVAL; } } @@ -662,6 +661,6 @@ module_init(erofs_module_init); module_exit(erofs_module_exit); MODULE_DESCRIPTION("Enhanced ROM File System"); -MODULE_AUTHOR("Gao Xiang, Yu Chao, Miao Xie, CONSUMER BG, HUAWEI Inc."); +MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); MODULE_LICENSE("GPL"); -- GitLab From 0b800f3dbae710ed72ad544d17fd186ea5b5e504 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:52 +0800 Subject: [PATCH 1690/7155] staging: erofs: update Kconfig Keep in line with erofs-outofstaging patchset: - turn on CONFIG_EROFS_FS_ZIP by default; - turn on CONFIG_EROFS_FS_SECURITY by default suggested by David; - update Kconfig description. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-23-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 54 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 1a8e48943e50..16316d1adca3 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -4,16 +4,16 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK help - EROFS(Enhanced Read-Only File System) is a lightweight + EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (eg. page-sized blocks, inline xattrs/data, etc.) for scenarios which need - high-performance read-only requirements, eg. firmwares in - mobile phone or LIVECDs. + high-performance read-only requirements, e.g. Android OS + for mobile phones and LIVECDs. - It also provides VLE compression support, focusing on - random read improvements, keeping relatively lower - compression ratios, which is useful for high-performance - devices with limited memory and ROM space. + It also provides fixed-sized output compression support, + which improves storage density, keeps relatively higher + compression ratios, which is more useful to achieve high + performance for embedded devices with limited memory. If unsure, say N. @@ -21,11 +21,19 @@ config EROFS_FS_DEBUG bool "EROFS debugging feature" depends on EROFS_FS help - Print EROFS debugging messages and enable more BUG_ONs - which check the filesystem consistency aggressively. + Print debugging messages and enable more BUG_ONs which check + filesystem consistency and find potential issues aggressively, + which can be used for Android eng build, for example. For daily use, say N. +config EROFS_FAULT_INJECTION + bool "EROFS fault injection facility" + depends on EROFS_FS + help + Test EROFS to inject faults such as ENOMEM, EIO, and so on. + If unsure, say N. + config EROFS_FS_XATTR bool "EROFS extended attributes" depends on EROFS_FS @@ -54,6 +62,7 @@ config EROFS_FS_POSIX_ACL config EROFS_FS_SECURITY bool "EROFS Security Labels" depends on EROFS_FS_XATTR + default y help Security labels provide an access control facility to support Linux Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO @@ -63,22 +72,15 @@ config EROFS_FS_SECURITY If you are not using a security module, say N. -config EROFS_FAULT_INJECTION - bool "EROFS fault injection facility" - depends on EROFS_FS - help - Test EROFS to inject faults such as ENOMEM, EIO, and so on. - If unsure, say N. - config EROFS_FS_ZIP - bool "EROFS Data Compresssion Support" + bool "EROFS Data Compression Support" depends on EROFS_FS select LZ4_DECOMPRESS + default y help - Currently we support LZ4 VLE Compression only. - Play at your own risk. + Enable fixed-sized output compression for EROFS. - If you don't want to use compression feature, say N. + If you don't want to enable compression feature, say N. config EROFS_FS_CLUSTER_PAGE_LIMIT int "EROFS Cluster Pages Hard Limit" @@ -86,11 +88,11 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT range 1 256 default "1" help - Indicates VLE compressed pages hard limit of a - compressed cluster. + Indicates maximum # of pages of a compressed + physical cluster. - For example, if files of a image are compressed - into 8k-unit, the hard limit should not be less - than 2. Otherwise, the image cannot be mounted - correctly on this kernel. + For example, if files in a image were compressed + into 8k-unit, hard limit should not be configured + less than 2. Otherwise, the image will be refused + to mount on this kernel. -- GitLab From a5589269e660a14ab8580235909100f245d73cb9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 2 Aug 2019 01:31:49 +0000 Subject: [PATCH 1691/7155] staging: fsl-dpaa2/ethsw: Remove useless set memory to zero use memset() The memory return by kzalloc() has already be set to zero, so remove useless memset(0). Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20190802013149.80952-1-weiyongjun1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 4b94a01513a7..aac98ece2335 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -641,8 +641,6 @@ static int port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, if (!dma_mem) return -ENOMEM; - memset(dma_mem, 0, fdb_dump_size); - fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, DMA_FROM_DEVICE); if (dma_mapping_error(dev, fdb_dump_iova)) { -- GitLab From 129d0561a3e81836aeeba2bbdb89249c0012af24 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 15:42:07 +0200 Subject: [PATCH 1692/7155] staging: bcm2835-camera: Spelling s/conencted/connected/ Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190731134207.18549-1-geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h index f738e7f99e96..47897e81ec58 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h @@ -56,7 +56,7 @@ struct vchiq_mmal_port { /* component port belongs to, allows simple deref */ struct vchiq_mmal_component *component; - struct vchiq_mmal_port *connected; /* port conencted to */ + struct vchiq_mmal_port *connected; /* port connected to */ /* buffer info */ struct vchiq_mmal_port_buffer minimum_buffer; -- GitLab From b7a40c32f18a88b2a1e894a4406cf9d97423c078 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:39:13 +0530 Subject: [PATCH 1693/7155] staging: wlan-ng: Remove function prism2mib_excludeunencrypted() Remove function prism2mib_excludeunencrypted as all it does is call prism2mib_flag. Modify call sites accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802060913.30241-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mib.c | 44 +---------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 1eba5fa28d8f..7d7d77b04255 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -126,13 +126,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, struct p80211msg_dot11req_mibset *msg, void *data); -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data); - static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, @@ -176,7 +169,7 @@ static struct mibrec mibtab[] = { {DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, F_STA | F_READ | F_WRITE, HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, - prism2mib_excludeunencrypted}, + prism2mib_flag}, /* dot11mac MIB's */ @@ -593,41 +586,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/* - * prism2mib_excludeunencrypted - * - * Get/set the dot11ExcludeUnencrypted value. - * - * MIB record parameters: - * parm1 Prism2 RID value. - * parm2 Bit value for ExcludeUnencrypted flag. - * parm3 Not used. - * - * Arguments: - * mib MIB record. - * isget MIBGET/MIBSET flag. - * wlandev wlan device structure. - * priv "priv" structure. - * hw "hw" structure. - * msg Message structure. - * data Data buffer. - * - * Returns: - * 0 - Success. - * ~0 - Error. - * - */ - -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data) -{ - return prism2mib_flag(mib, isget, wlandev, hw, msg, data); -} - /* * prism2mib_fragmentationthreshold * -- GitLab From 4b1b8b08ab9f4db41e30e3a1bbdba1d58aa624a3 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 1 Aug 2019 20:15:11 +0000 Subject: [PATCH 1694/7155] staging: wilc1000: merge drv_handle and operation_mode wids wilc_set_wfi_drv_handler and wilc_set_operation_mode sends the same parameters to the FW, so it's better to combine them together. Kept wilc_set_wfi_drv_handler implementation since it sends all the required parameters, and renamed it to wilc_set_operation_mode to be more descriptive. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190801200909.12605-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 32 ++----------------- drivers/staging/wilc1000/wilc_hif.h | 5 ++- drivers/staging/wilc1000/wilc_netdev.c | 6 ++-- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 26 +++++++-------- drivers/staging/wilc1000/wilc_wlan_if.h | 3 +- 5 files changed, 21 insertions(+), 51 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index f8646ea3b0c4..2b4c83b225a4 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -1409,18 +1409,14 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) return result; } -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id) +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id) { struct wid wid; - struct host_if_drv *hif_drv = vif->hif_drv; int result; struct wilc_drv_handler drv; - if (!hif_drv) - return -EFAULT; - - wid.id = WID_SET_DRV_HANDLER; + wid.id = WID_SET_OPERATION_MODE; wid.type = WID_STR; wid.size = sizeof(drv); wid.val = (u8 *)&drv; @@ -1435,26 +1431,6 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, return result; } -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) -{ - struct wid wid; - struct wilc_op_mode op_mode; - int result; - - wid.id = WID_SET_OPERATION_MODE; - wid.type = WID_INT; - wid.size = sizeof(op_mode); - wid.val = (u8 *)&op_mode; - - op_mode.mode = cpu_to_le32(mode); - - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, "Failed to set operation mode\n"); - - return result; -} - s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) { struct wid wid; @@ -1630,8 +1606,6 @@ int wilc_deinit(struct wilc_vif *vif) del_timer_sync(&vif->periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, hif_drv->usr_scan_req.arg); diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/wilc_hif.h index be1d2497cde9..3bc305151651 100644 --- a/drivers/staging/wilc1000/wilc_hif.h +++ b/drivers/staging/wilc1000/wilc_hif.h @@ -219,9 +219,8 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie); void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id); -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 68129a0ba55f..57510400f243 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -626,10 +626,8 @@ static int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), vif->iftype, - vif->idx); - wilc_set_operation_mode(vif, vif->iftype); - + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, + vif->idx); wilc_get_mac_address(vif, mac_add); netdev_dbg(ndev, "Mac address: %pM\n", mac_add); ether_addr_copy(ndev->dev_addr, mac_add); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index e2d9efed36b0..f3b12f3b6d61 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1419,7 +1419,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) wilc_wfi_deinit_mon_interface(wl, true); vif->iftype = WILC_STATION_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); memset(priv->assoc_stainfo.sta_associated_bss, 0, WILC_MAX_NUM_STA * ETH_ALEN); @@ -1431,8 +1432,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev.iftype = type; vif->monitor_flag = 0; vif->iftype = WILC_CLIENT_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); - + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); break; case NL80211_IFTYPE_AP: @@ -1440,18 +1441,17 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev.iftype = type; vif->iftype = WILC_AP_MODE; - if (wl->initialized) { - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - 0, vif->idx); - wilc_set_operation_mode(vif, WILC_AP_MODE); - } + if (wl->initialized) + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; case NL80211_IFTYPE_P2P_GO: - wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_GO_MODE; + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; default: @@ -1659,16 +1659,16 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) vif->monitor_flag = 0; mutex_lock(&wl->vif_mutex); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - for (i = vif->idx; i < wl->vif_num ; i++) { + wilc_set_operation_mode(vif, 0, 0, 0); + for (i = vif->idx; i < wl->vif_num; i++) { if ((i + 1) >= wl->vif_num) { wl->vif[i] = NULL; } else { vif = wl->vif[i + 1]; vif->idx = i; wl->vif[i] = vif; - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - vif->iftype, vif->idx); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + vif->iftype, vif->idx); } } wl->vif_num--; diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index b89d0e0f04cc..70eac586f80c 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -724,7 +724,6 @@ enum { /* NMAC Integer WID list */ /* Custom Integer WID list */ WID_GET_INACTIVE_TIME = 0x2084, - WID_SET_OPERATION_MODE = 0X2086, /* EMAC String WID list */ WID_SSID = 0x3000, WID_FIRMWARE_VERSION = 0x3001, @@ -755,9 +754,9 @@ enum { WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ - WID_SET_DRV_HANDLER = 0x3079, /* NMAC String WID list */ + WID_SET_OPERATION_MODE = 0x3079, WID_11N_P_ACTION_REQ = 0x3080, WID_HUT_TEST_ID = 0x3081, WID_PMKID_INFO = 0x3082, -- GitLab From 9104688c321a7e82ec95fddff6c98729f4e4fefd Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 1 Aug 2019 20:15:12 +0000 Subject: [PATCH 1695/7155] staging: wilc1000: remove unused function function wilc_resolve_disconnect_aberration isn't referenced, so removing it Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190801200909.12605-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 9 --------- drivers/staging/wilc1000/wilc_hif.h | 1 - 2 files changed, 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 2b4c83b225a4..f2b7d5a1be17 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -798,15 +798,6 @@ int wilc_disconnect(struct wilc_vif *vif) return 0; } -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) -{ - if (!vif->hif_drv) - return; - if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || - vif->hif_drv->hif_state == HOST_IF_CONNECTING) - wilc_disconnect(vif); -} - int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { struct wid wid_list[5]; diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/wilc_hif.h index 3bc305151651..ac5fe57f872b 100644 --- a/drivers/staging/wilc1000/wilc_hif.h +++ b/drivers/staging/wilc1000/wilc_hif.h @@ -222,7 +222,6 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, u8 ifc_id); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); -- GitLab From 42755adcce8897a60a766bc102fcb23f1dd28f43 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:41 +0530 Subject: [PATCH 1696/7155] staging: rtl8723bs: Change return type of hal_btcoex_IsBtExist() Change return type of hal_btcoex_IsBtExist from u8 to bool as its only possible return values are true and false. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 2 +- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 8987b5f892c0..73f3d93d2d1a 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1335,7 +1335,7 @@ void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist) *true Enable BT co-exist mechanism *false Disable BT co-exist mechanism */ -u8 hal_btcoex_IsBtExist(struct adapter *padapter) +bool hal_btcoex_IsBtExist(struct adapter *padapter) { struct hal_com_data *pHalData; diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index 6f7514be998f..a91116e5c549 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -22,7 +22,7 @@ typedef struct _BT_COEXIST void DBG_BT_INFO(u8 *dbgmsg); void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist); -u8 hal_btcoex_IsBtExist(struct adapter *padapter); +bool hal_btcoex_IsBtExist(struct adapter *padapter); bool hal_btcoex_IsBtDisabled(struct adapter *); void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType); void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum); -- GitLab From 84881dd37beb0626d2622ccbfbdcfdc4bda2546d Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:42 +0530 Subject: [PATCH 1697/7155] staging: rtl8723bs: Change return type of hal_btcoex_IsBtControlLps() Change return type of hal_btcoex_IsBtControlLps from u8 to bool as it only returns boolean values. Change comparison to false within this function; check the boolean variable directly instead. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 ++-- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 73f3d93d2d1a..85f5371d349b 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1475,9 +1475,9 @@ void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual) GLBtCoexist.bManualControl = bmanual; } -u8 hal_btcoex_IsBtControlLps(struct adapter *padapter) +bool hal_btcoex_IsBtControlLps(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index a91116e5c549..da25f8e98ec7 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -47,7 +47,7 @@ void hal_btcoex_Handler(struct adapter *padapter); s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter); void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual); -u8 hal_btcoex_IsBtControlLps(struct adapter *); +bool hal_btcoex_IsBtControlLps(struct adapter *padapter); u8 hal_btcoex_IsLpsOn(struct adapter *); u8 hal_btcoex_RpwmVal(struct adapter *); u8 hal_btcoex_LpsVal(struct adapter *); -- GitLab From 365231fcd67c97ea464c17d8d413f0860400547b Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:43 +0530 Subject: [PATCH 1698/7155] staging: rtl8723bs: Change return type of hal_btcoex_IsLpsOn() Change return type of hal_btcoex_IsLpsOn from u8 to bool as the function only returns boolean values. Modify a comparison of a boolean value to false to instead check that boolean value directly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 ++-- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 85f5371d349b..d2147a65c1cd 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1489,9 +1489,9 @@ bool hal_btcoex_IsBtControlLps(struct adapter *padapter) return false; } -u8 hal_btcoex_IsLpsOn(struct adapter *padapter) +bool hal_btcoex_IsLpsOn(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index da25f8e98ec7..a0b502c34a25 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -48,7 +48,7 @@ void hal_btcoex_Handler(struct adapter *padapter); s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter); void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual); bool hal_btcoex_IsBtControlLps(struct adapter *padapter); -u8 hal_btcoex_IsLpsOn(struct adapter *); +bool hal_btcoex_IsLpsOn(struct adapter *padapter); u8 hal_btcoex_RpwmVal(struct adapter *); u8 hal_btcoex_LpsVal(struct adapter *); u32 hal_btcoex_GetRaMask(struct adapter *); -- GitLab From 6250a57e6cf45440e2230bda226162532b0130e4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:44 +0530 Subject: [PATCH 1699/7155] staging: rtl8723bs: Replace hal_btcoex_Initialize() Remove hal_btcoex_Initialize as all it does is perform a memset and call EXhalbtcoutsrc_InitlizeVariables. Rename EXhalbtcoutsrc_InitlizeVariables to hal_btcoex_Initialize and add the memset of hal_btcoex_Initialize in order to maintain compatibility with call sites of the latter (EXhalbtcoutsrc is not called anywhere else except in now-removed old hal_btcoex_Initialize). Change return type of new hal_btcoex_Initialize from u8 to void and remove its return statement as the return value of hal_btcoex_Initialize is never used. Change the type of function argument at call site to match the function parameter of new hal_btcoex_Initialize. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h | 1 - drivers/staging/rtl8723bs/hal/hal_btcoex.c | 16 ++++++---------- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h index aad86570b59c..7150d54d49ab 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h +++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h @@ -532,7 +532,6 @@ typedef struct _BTC_COEXIST { extern BTC_COEXIST GLBtCoexist; -u8 EXhalbtcoutsrc_InitlizeVariables(void *Adapter); void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist); void EXhalbtcoutsrc_InitHwConfig(PBTC_COEXIST pBtCoexist, u8 bWifiOnly); void EXhalbtcoutsrc_InitCoexDm(PBTC_COEXIST pBtCoexist); diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index d2147a65c1cd..19486f0e0ead 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -957,9 +957,13 @@ static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter) return true; } -u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) +void hal_btcoex_Initialize(void *padapter) { - PBTC_COEXIST pBtCoexist = &GLBtCoexist; + PBTC_COEXIST pBtCoexist; + + memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); + + pBtCoexist = &GLBtCoexist; /* pBtCoexist->statistics.cntBind++; */ @@ -999,8 +1003,6 @@ u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) GLBtcWiFiInScanState = false; GLBtcWiFiInIQKState = false; - - return true; } void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist) @@ -1382,12 +1384,6 @@ void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath) EXhalbtcoutsrc_SetSingleAntPath(singleAntPath); } -u8 hal_btcoex_Initialize(struct adapter *padapter) -{ - memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); - return EXhalbtcoutsrc_InitlizeVariables((void *)padapter); -} - void hal_btcoex_PowerOnSetting(struct adapter *padapter) { EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist); diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index a0b502c34a25..eb03813fdcb9 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -28,7 +28,7 @@ void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType); void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum); void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath); -u8 hal_btcoex_Initialize(struct adapter *padapter); +void hal_btcoex_Initialize(void *padapter); void hal_btcoex_PowerOnSetting(struct adapter *padapter); void hal_btcoex_InitHwConfig(struct adapter *padapter, u8 bWifiOnly); diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 540a7eed621d..65ffb807eda2 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -371,7 +371,7 @@ static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct rtw_hal_chip_configure(padapter); - hal_btcoex_Initialize(padapter); + hal_btcoex_Initialize((void *) padapter); /* 3 6. read efuse/eeprom data */ rtw_hal_read_chip_info(padapter); -- GitLab From a0afad481b83690449a119a9384a3b0f54cacf11 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:04 +0530 Subject: [PATCH 1700/7155] staging: rtl8712: r8712_os_recv_resource_alloc(): Change return type Change return type of function r8712_os_recv_resource_alloc from int to void as its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 5 ++--- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 70a4dcd4a1e5..aaa77823115a 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -29,12 +29,11 @@ /*init os related resource in struct recv_priv*/ /*alloc os related resource in union recv_frame*/ -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe) +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe) { precvframe->u.hdr.pkt_newalloc = NULL; precvframe->u.hdr.pkt = NULL; - return _SUCCESS; } /*alloc os related resource in struct recv_buf*/ diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index dcd3b484c793..c93ba4c3eb9b 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -28,8 +28,8 @@ void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void r8712_free_recv_priv(struct recv_priv *precvpriv); -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe); +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe); int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); int r8712_os_recvbuf_resource_free(struct _adapter *padapter, -- GitLab From 1ce0212ab8c103f36aa8d7b43ff8d738bc98699b Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:05 +0530 Subject: [PATCH 1701/7155] staging: rtl8712: _r8712_init_recv_priv(): Change return type Change return type of _r8712_init_recv_priv as its return value is never checked or used. Modify return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index c93ba4c3eb9b..7a0fa227de73 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -18,7 +18,7 @@ #include "drv_types.h" #include -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void _r8712_free_recv_priv(struct recv_priv *precvpriv); s32 r8712_recv_entry(union recv_frame *precv_frame); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 9969e5265a40..79c7a329e9f6 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -48,7 +48,7 @@ void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) _init_queue(&psta_recvpriv->defrag_q); } -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) { sint i; @@ -64,7 +64,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, sizeof(union recv_frame) + RXFRAME_ALIGN_SZ, GFP_ATOMIC); if (precvpriv->pallocated_frame_buf == NULL) - return _FAIL; + return; kmemleak_not_leak(precvpriv->pallocated_frame_buf); precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - @@ -80,7 +80,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, precvframe++; } precvpriv->rx_pending_cnt = 1; - return r8712_init_recv_priv(precvpriv, padapter); + r8712_init_recv_priv(precvpriv, padapter); } void _r8712_free_recv_priv(struct recv_priv *precvpriv) -- GitLab From 0bf36e605286eaa53ec90c09a2f8eaac5d4d1cc4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:06 +0530 Subject: [PATCH 1702/7155] staging: rtl8712: r8712_init_recv_priv(): Change return type Change return type of r8712_init_recv_priv from int to void as its return value is never used. Remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 7a0fa227de73..3cfafef1af91 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -25,8 +25,8 @@ s32 r8712_recv_entry(union recv_frame *precv_frame); void r8712_recv_indicatepkt(struct _adapter *adapter, union recv_frame *precv_frame); void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); -int r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter); +void r8712_init_recv_priv(struct recv_priv *precvpriv, + struct _adapter *padapter); void r8712_free_recv_priv(struct recv_priv *precvpriv); void r8712_os_recv_resource_alloc(struct _adapter *padapter, union recv_frame *precvframe); diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index d9574ea3ffb2..bb0407cac1ae 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -35,7 +35,7 @@ static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; static void recv_tasklet(void *priv); -int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) +void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) { int i; struct recv_buf *precvbuf; @@ -83,7 +83,6 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) } pskb = NULL; } - return res; } void r8712_free_recv_priv(struct recv_priv *precvpriv) -- GitLab From 14b4302ff028afc5fc09f243a21ee6cad6118c40 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:07 +0530 Subject: [PATCH 1703/7155] staging: rtl8712: r8712_os_recvbuf_resource_alloc(): Change return values Change return values of r8712_os_recvbuf_resource_alloc from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify check at call site to check for non-zero return value instead of _FAIL. Thereafter remove variable at call site that stored the return value and perform the check directly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 4 ++-- drivers/staging/rtl8712/rtl8712_recv.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index aaa77823115a..682f5b2802ee 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -40,12 +40,12 @@ void r8712_os_recv_resource_alloc(struct _adapter *padapter, int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf) { - int res = _SUCCESS; + int res = 0; precvbuf->irp_pending = false; precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); if (!precvbuf->purb) - res = _FAIL; + res = -ENOMEM; precvbuf->pskb = NULL; precvbuf->pallocated_buf = NULL; precvbuf->pbuf = NULL; diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index bb0407cac1ae..eb9a4a5ed740 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -39,7 +39,6 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter { int i; struct recv_buf *precvbuf; - int res = _SUCCESS; addr_t tmpaddr = 0; int alignment = 0; struct sk_buff *pskb = NULL; @@ -49,15 +48,14 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); if (!precvpriv->pallocated_recv_buf) - return _FAIL; + return; precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - ((addr_t)(precvpriv->pallocated_recv_buf) & 3); precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { INIT_LIST_HEAD(&precvbuf->list); spin_lock_init(&precvbuf->recvbuf_lock); - res = r8712_os_recvbuf_resource_alloc(padapter, precvbuf); - if (res == _FAIL) + if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf)) break; precvbuf->ref_cnt = 0; precvbuf->adapter = padapter; -- GitLab From dcca75a495f9a8b7a6a0fd66bdbe0ed08ffe4884 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:08 +0530 Subject: [PATCH 1704/7155] staging: rtl8712: r8712_os_recvbuf_resource_free(): Change return type Change return type of r8712_os_recvbuf_resource_free from int to void as it always returns _SUCCESS and this return value is never stored, checked or otherwise used. Remove return statement accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 5 ++--- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 682f5b2802ee..215fca4abb3a 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -59,8 +59,8 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, } /*free os related resource in struct recv_buf*/ -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf) +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf) { if (precvbuf->pskb) dev_kfree_skb_any(precvbuf->pskb); @@ -68,7 +68,6 @@ int r8712_os_recvbuf_resource_free(struct _adapter *padapter, usb_kill_urb(precvbuf->purb); usb_free_urb(precvbuf->purb); } - return _SUCCESS; } void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup) diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 3cfafef1af91..792f9cfbacd9 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -32,8 +32,8 @@ void r8712_os_recv_resource_alloc(struct _adapter *padapter, union recv_frame *precvframe); int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf); +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf); void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); #endif -- GitLab From f8dbe3f0acaff86c8c12540bb1b76c34d32a563f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:09 +0530 Subject: [PATCH 1705/7155] staging: rtl8712: r8712_tkip_decrypt(): Change return type Change return type of r8712_tkip_decrypt from u8 to void as the return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 12 ++---------- drivers/staging/rtl8712/rtl871x_security.h | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 693008bba83e..66586a9d9f73 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -636,7 +636,7 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe) } /* The hlen doesn't include the IV */ -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ u16 pnl; u32 pnh; @@ -670,7 +670,7 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; } @@ -686,16 +686,8 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) arcfour_encrypt(&mycontext, payload, payload, length); *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, length - 4)); - if (crc[3] != payload[length - 1] || - crc[2] != payload[length - 2] || - crc[1] != payload[length - 3] || - crc[0] != payload[length - 4]) - return _FAIL; - } else { - return _FAIL; } } - return _SUCCESS; } /* 3 =====AES related===== */ diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 25b4d379766d..25220afa61e9 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -210,7 +210,7 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_use_tkipkey_handler(struct timer_list *t); -- GitLab From e48a3add05d1b3e0c2ead1e809edd4d02f2f5f10 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:10 +0530 Subject: [PATCH 1706/7155] staging: rtl8712: aes_cipher(): Change return type Change return type of aes_cipher from sint to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 66586a9d9f73..8f3781c5dd25 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1011,8 +1011,8 @@ static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) out[i] = ina[i] ^ inb[i]; } -static sint aes_cipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_cipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { uint qc_exists, a4_exists, i, j, payload_remainder; uint num_blocks, payload_index; @@ -1132,7 +1132,6 @@ static sint aes_cipher(u8 *key, uint hdrlen, bitwise_xor(aes_out, padded_buffer, chain_buffer); for (j = 0; j < 8; j++) pframe[payload_index++] = chain_buffer[j]; - return _SUCCESS; } u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) -- GitLab From eb43590f50a393ec4156be59eec9287fb711ffd8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:11 +0530 Subject: [PATCH 1707/7155] staging: rtl8712: aes_decipher(): Change return type Change return type of aes_decipher from sint to void as it always returns _SUCCESS and this value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 8f3781c5dd25..bf55a697dd5f 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1184,8 +1184,8 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) return res; } -static sint aes_decipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_decipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { static u8 message[MAX_MSG_SIZE]; uint qc_exists, a4_exists, i, j, payload_remainder; @@ -1339,7 +1339,6 @@ static sint aes_decipher(u8 *key, uint hdrlen, for (j = 0; j < 8; j++) message[payload_index++] = chain_buffer[j]; /* compare the mic */ - return _SUCCESS; } u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) -- GitLab From b35105a3a32343ecdd777497a300a7680f15bf08 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:12 +0530 Subject: [PATCH 1708/7155] staging: rtl8712: r8712_aes_decrypt(): Change return type Change return type of r8712_aes_decrypt from u8 to void as its return value is never checked. Modify return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 7 ++----- drivers/staging/rtl8712/rtl871x_security.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index bf55a697dd5f..73e3d5ef3af2 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1341,7 +1341,7 @@ static void aes_decipher(u8 *key, uint hdrlen, /* compare the mic */ } -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ /* Intermediate Buffers */ sint length; @@ -1364,7 +1364,7 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; @@ -1374,11 +1374,8 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prxattrib->iv_len; aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); - } else { - return _FAIL; } } - return _SUCCESS; } void r8712_use_tkipkey_handler(struct timer_list *t) diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 25220afa61e9..b2dda16cbd0a 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -209,7 +209,7 @@ void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst); u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_use_tkipkey_handler(struct timer_list *t); -- GitLab From 2040f414d12f31be3e73eb3f5048d2b1cdec48f6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 31 Jul 2019 17:15:23 +0200 Subject: [PATCH 1709/7155] KVM: selftests: Split ucall.c into architecture specific files The way we exit from a guest to userspace is very specific to the architecture: On x86, we use PIO, on aarch64 we are using MMIO and on s390x we're going to use an instruction instead. The possibility to select a type via the ucall_type_t enum is currently also completely unused, so the code in ucall.c currently looks more complex than required. Let's split this up into architecture specific ucall.c files instead, so we can get rid of the #ifdefs and the unnecessary ucall_type_t handling. Reviewed-by: Andrew Jones Signed-off-by: Thomas Huth Acked-by: Paolo Bonzini Link: https://lore.kernel.org/r/20190731151525.17156-2-thuth@redhat.com Signed-off-by: Christian Borntraeger --- tools/testing/selftests/kvm/Makefile | 6 +- tools/testing/selftests/kvm/dirty_log_test.c | 2 +- .../testing/selftests/kvm/include/kvm_util.h | 8 +- .../testing/selftests/kvm/lib/aarch64/ucall.c | 112 +++++++++++++ tools/testing/selftests/kvm/lib/ucall.c | 157 ------------------ .../testing/selftests/kvm/lib/x86_64/ucall.c | 56 +++++++ 6 files changed, 173 insertions(+), 168 deletions(-) create mode 100644 tools/testing/selftests/kvm/lib/aarch64/ucall.c delete mode 100644 tools/testing/selftests/kvm/lib/ucall.c create mode 100644 tools/testing/selftests/kvm/lib/x86_64/ucall.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index ba7849751989..a51e3b83df40 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -7,9 +7,9 @@ top_srcdir = ../../../.. KSFT_KHDR_INSTALL := 1 UNAME_M := $(shell uname -m) -LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/ucall.c lib/sparsebit.c -LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c -LIBKVM_aarch64 = lib/aarch64/processor.c +LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c +LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/ucall.c +LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c LIBKVM_s390x = lib/s390x/processor.c TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c index ceb52b952637..5d5ae1be4984 100644 --- a/tools/testing/selftests/kvm/dirty_log_test.c +++ b/tools/testing/selftests/kvm/dirty_log_test.c @@ -337,7 +337,7 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations, vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); #endif #ifdef __aarch64__ - ucall_init(vm, UCALL_MMIO, NULL); + ucall_init(vm, NULL); #endif /* Export the shared variables to the guest */ diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index e0e66b115ef2..5463b7896a0a 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -165,12 +165,6 @@ int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd); memcpy(&(g), _p, sizeof(g)); \ }) -/* ucall implementation types */ -typedef enum { - UCALL_PIO, - UCALL_MMIO, -} ucall_type_t; - /* Common ucalls */ enum { UCALL_NONE, @@ -186,7 +180,7 @@ struct ucall { uint64_t args[UCALL_MAX_ARGS]; }; -void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg); +void ucall_init(struct kvm_vm *vm, void *arg); void ucall_uninit(struct kvm_vm *vm); void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc); diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testing/selftests/kvm/lib/aarch64/ucall.c new file mode 100644 index 000000000000..6cd91970fbad --- /dev/null +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ucall support. A ucall is a "hypercall to userspace". + * + * Copyright (C) 2018, Red Hat, Inc. + */ +#include "kvm_util.h" +#include "../kvm_util_internal.h" + +static vm_vaddr_t *ucall_exit_mmio_addr; + +static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa) +{ + if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1)) + return false; + + virt_pg_map(vm, gpa, gpa, 0); + + ucall_exit_mmio_addr = (vm_vaddr_t *)gpa; + sync_global_to_guest(vm, ucall_exit_mmio_addr); + + return true; +} + +void ucall_init(struct kvm_vm *vm, void *arg) +{ + vm_paddr_t gpa, start, end, step, offset; + unsigned int bits; + bool ret; + + if (arg) { + gpa = (vm_paddr_t)arg; + ret = ucall_mmio_init(vm, gpa); + TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa); + return; + } + + /* + * Find an address within the allowed physical and virtual address + * spaces, that does _not_ have a KVM memory region associated with + * it. Identity mapping an address like this allows the guest to + * access it, but as KVM doesn't know what to do with it, it + * will assume it's something userspace handles and exit with + * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. + * Here we start with a guess that the addresses around 5/8th + * of the allowed space are unmapped and then work both down and + * up from there in 1/16th allowed space sized steps. + * + * Note, we need to use VA-bits - 1 when calculating the allowed + * virtual address space for an identity mapping because the upper + * half of the virtual address space is the two's complement of the + * lower and won't match physical addresses. + */ + bits = vm->va_bits - 1; + bits = vm->pa_bits < bits ? vm->pa_bits : bits; + end = 1ul << bits; + start = end * 5 / 8; + step = end / 16; + for (offset = 0; offset < end - start; offset += step) { + if (ucall_mmio_init(vm, start - offset)) + return; + if (ucall_mmio_init(vm, start + offset)) + return; + } + TEST_ASSERT(false, "Can't find a ucall mmio address"); +} + +void ucall_uninit(struct kvm_vm *vm) +{ + ucall_exit_mmio_addr = 0; + sync_global_to_guest(vm, ucall_exit_mmio_addr); +} + +void ucall(uint64_t cmd, int nargs, ...) +{ + struct ucall uc = { + .cmd = cmd, + }; + va_list va; + int i; + + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; + + va_start(va, nargs); + for (i = 0; i < nargs; ++i) + uc.args[i] = va_arg(va, uint64_t); + va_end(va); + + *ucall_exit_mmio_addr = (vm_vaddr_t)&uc; +} + +uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) +{ + struct kvm_run *run = vcpu_state(vm, vcpu_id); + struct ucall ucall = {}; + + if (run->exit_reason == KVM_EXIT_MMIO && + run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) { + vm_vaddr_t gva; + + TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8, + "Unexpected ucall exit mmio address access"); + memcpy(&gva, run->mmio.data, sizeof(gva)); + memcpy(&ucall, addr_gva2hva(vm, gva), sizeof(ucall)); + + vcpu_run_complete_io(vm, vcpu_id); + if (uc) + memcpy(uc, &ucall, sizeof(ucall)); + } + + return ucall.cmd; +} diff --git a/tools/testing/selftests/kvm/lib/ucall.c b/tools/testing/selftests/kvm/lib/ucall.c deleted file mode 100644 index dd9a66700f96..000000000000 --- a/tools/testing/selftests/kvm/lib/ucall.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ucall support. A ucall is a "hypercall to userspace". - * - * Copyright (C) 2018, Red Hat, Inc. - */ -#include "kvm_util.h" -#include "kvm_util_internal.h" - -#define UCALL_PIO_PORT ((uint16_t)0x1000) - -static ucall_type_t ucall_type; -static vm_vaddr_t *ucall_exit_mmio_addr; - -static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa) -{ - if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1)) - return false; - - virt_pg_map(vm, gpa, gpa, 0); - - ucall_exit_mmio_addr = (vm_vaddr_t *)gpa; - sync_global_to_guest(vm, ucall_exit_mmio_addr); - - return true; -} - -void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg) -{ - ucall_type = type; - sync_global_to_guest(vm, ucall_type); - - if (type == UCALL_PIO) - return; - - if (type == UCALL_MMIO) { - vm_paddr_t gpa, start, end, step, offset; - unsigned bits; - bool ret; - - if (arg) { - gpa = (vm_paddr_t)arg; - ret = ucall_mmio_init(vm, gpa); - TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa); - return; - } - - /* - * Find an address within the allowed physical and virtual address - * spaces, that does _not_ have a KVM memory region associated with - * it. Identity mapping an address like this allows the guest to - * access it, but as KVM doesn't know what to do with it, it - * will assume it's something userspace handles and exit with - * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. - * Here we start with a guess that the addresses around 5/8th - * of the allowed space are unmapped and then work both down and - * up from there in 1/16th allowed space sized steps. - * - * Note, we need to use VA-bits - 1 when calculating the allowed - * virtual address space for an identity mapping because the upper - * half of the virtual address space is the two's complement of the - * lower and won't match physical addresses. - */ - bits = vm->va_bits - 1; - bits = vm->pa_bits < bits ? vm->pa_bits : bits; - end = 1ul << bits; - start = end * 5 / 8; - step = end / 16; - for (offset = 0; offset < end - start; offset += step) { - if (ucall_mmio_init(vm, start - offset)) - return; - if (ucall_mmio_init(vm, start + offset)) - return; - } - TEST_ASSERT(false, "Can't find a ucall mmio address"); - } -} - -void ucall_uninit(struct kvm_vm *vm) -{ - ucall_type = 0; - sync_global_to_guest(vm, ucall_type); - ucall_exit_mmio_addr = 0; - sync_global_to_guest(vm, ucall_exit_mmio_addr); -} - -static void ucall_pio_exit(struct ucall *uc) -{ -#ifdef __x86_64__ - asm volatile("in %[port], %%al" - : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax"); -#endif -} - -static void ucall_mmio_exit(struct ucall *uc) -{ - *ucall_exit_mmio_addr = (vm_vaddr_t)uc; -} - -void ucall(uint64_t cmd, int nargs, ...) -{ - struct ucall uc = { - .cmd = cmd, - }; - va_list va; - int i; - - nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; - - va_start(va, nargs); - for (i = 0; i < nargs; ++i) - uc.args[i] = va_arg(va, uint64_t); - va_end(va); - - switch (ucall_type) { - case UCALL_PIO: - ucall_pio_exit(&uc); - break; - case UCALL_MMIO: - ucall_mmio_exit(&uc); - break; - }; -} - -uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) -{ - struct kvm_run *run = vcpu_state(vm, vcpu_id); - struct ucall ucall = {}; - bool got_ucall = false; - -#ifdef __x86_64__ - if (ucall_type == UCALL_PIO && run->exit_reason == KVM_EXIT_IO && - run->io.port == UCALL_PIO_PORT) { - struct kvm_regs regs; - vcpu_regs_get(vm, vcpu_id, ®s); - memcpy(&ucall, addr_gva2hva(vm, (vm_vaddr_t)regs.rdi), sizeof(ucall)); - got_ucall = true; - } -#endif - if (ucall_type == UCALL_MMIO && run->exit_reason == KVM_EXIT_MMIO && - run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) { - vm_vaddr_t gva; - TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8, - "Unexpected ucall exit mmio address access"); - memcpy(&gva, run->mmio.data, sizeof(gva)); - memcpy(&ucall, addr_gva2hva(vm, gva), sizeof(ucall)); - got_ucall = true; - } - - if (got_ucall) { - vcpu_run_complete_io(vm, vcpu_id); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); - } - - return ucall.cmd; -} diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing/selftests/kvm/lib/x86_64/ucall.c new file mode 100644 index 000000000000..4bfc9a90b1de --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ucall support. A ucall is a "hypercall to userspace". + * + * Copyright (C) 2018, Red Hat, Inc. + */ +#include "kvm_util.h" + +#define UCALL_PIO_PORT ((uint16_t)0x1000) + +void ucall_init(struct kvm_vm *vm, void *arg) +{ +} + +void ucall_uninit(struct kvm_vm *vm) +{ +} + +void ucall(uint64_t cmd, int nargs, ...) +{ + struct ucall uc = { + .cmd = cmd, + }; + va_list va; + int i; + + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; + + va_start(va, nargs); + for (i = 0; i < nargs; ++i) + uc.args[i] = va_arg(va, uint64_t); + va_end(va); + + asm volatile("in %[port], %%al" + : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax"); +} + +uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) +{ + struct kvm_run *run = vcpu_state(vm, vcpu_id); + struct ucall ucall = {}; + + if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) { + struct kvm_regs regs; + + vcpu_regs_get(vm, vcpu_id, ®s); + memcpy(&ucall, addr_gva2hva(vm, (vm_vaddr_t)regs.rdi), + sizeof(ucall)); + + vcpu_run_complete_io(vm, vcpu_id); + if (uc) + memcpy(uc, &ucall, sizeof(ucall)); + } + + return ucall.cmd; +} -- GitLab From f90f57b3971a3370be5a3cf02ae783b4bf728b7f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 31 Jul 2019 17:15:24 +0200 Subject: [PATCH 1710/7155] KVM: selftests: Implement ucall() for s390x On s390x, we can neither exit via PIO nor MMIO, but have to use an instruction like DIAGNOSE. Now that ucall() is implemented, we can use it in the sync_reg_test on s390x, too. Reviewed-by: Andrew Jones Signed-off-by: Thomas Huth Link: https://lore.kernel.org/r/20190731151525.17156-3-thuth@redhat.com Signed-off-by: Christian Borntraeger --- tools/testing/selftests/kvm/Makefile | 2 +- tools/testing/selftests/kvm/lib/s390x/ucall.c | 56 +++++++++++++++++++ .../selftests/kvm/s390x/sync_regs_test.c | 6 +- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/kvm/lib/s390x/ucall.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index a51e3b83df40..75ea1ecbf85a 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -10,7 +10,7 @@ UNAME_M := $(shell uname -m) LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/ucall.c LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c -LIBKVM_s390x = lib/s390x/processor.c +LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test TEST_GEN_PROGS_x86_64 += x86_64/evmcs_test diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/selftests/kvm/lib/s390x/ucall.c new file mode 100644 index 000000000000..fd589dc9bfab --- /dev/null +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ucall support. A ucall is a "hypercall to userspace". + * + * Copyright (C) 2019 Red Hat, Inc. + */ +#include "kvm_util.h" + +void ucall_init(struct kvm_vm *vm, void *arg) +{ +} + +void ucall_uninit(struct kvm_vm *vm) +{ +} + +void ucall(uint64_t cmd, int nargs, ...) +{ + struct ucall uc = { + .cmd = cmd, + }; + va_list va; + int i; + + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; + + va_start(va, nargs); + for (i = 0; i < nargs; ++i) + uc.args[i] = va_arg(va, uint64_t); + va_end(va); + + /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ + asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); +} + +uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) +{ + struct kvm_run *run = vcpu_state(vm, vcpu_id); + struct ucall ucall = {}; + + if (run->exit_reason == KVM_EXIT_S390_SIEIC && + run->s390_sieic.icptcode == 4 && + (run->s390_sieic.ipa >> 8) == 0x83 && /* 0x83 means DIAGNOSE */ + (run->s390_sieic.ipb >> 16) == 0x501) { + int reg = run->s390_sieic.ipa & 0xf; + + memcpy(&ucall, addr_gva2hva(vm, run->s.regs.gprs[reg]), + sizeof(ucall)); + + vcpu_run_complete_io(vm, vcpu_id); + if (uc) + memcpy(uc, &ucall, sizeof(ucall)); + } + + return ucall.cmd; +} diff --git a/tools/testing/selftests/kvm/s390x/sync_regs_test.c b/tools/testing/selftests/kvm/s390x/sync_regs_test.c index e85ff0d69548..bbc93094519b 100644 --- a/tools/testing/selftests/kvm/s390x/sync_regs_test.c +++ b/tools/testing/selftests/kvm/s390x/sync_regs_test.c @@ -25,9 +25,11 @@ static void guest_code(void) { + register u64 stage asm("11") = 0; + for (;;) { - asm volatile ("diag 0,0,0x501"); - asm volatile ("ahi 11,1"); + GUEST_SYNC(0); + asm volatile ("ahi %0,1" : : "r"(stage)); } } -- GitLab From a049a377164c3eca7d5323cd9896b64d2120c415 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 31 Jul 2019 17:15:25 +0200 Subject: [PATCH 1711/7155] KVM: selftests: Enable dirty_log_test on s390x To run the dirty_log_test on s390x, we have to make sure that we access the dirty log bitmap with little endian byte ordering and we have to properly align the memslot of the guest. Also all dirty bits of a segment are set once on s390x when one of the pages of a segment are written to for the first time, so we have to make sure that we touch all pages during the first iteration to keep the test in sync here. DEFAULT_GUEST_TEST_MEM needs an adjustment, too. On some s390x distributions, the ELF binary is linked to address 0x80000000, so we have to avoid that our test region overlaps into this area. 0xc0000000 seems to be a good alternative that should work on x86 and aarch64, too. Acked-by: Paolo Bonzini Reviewed-by: Andrew Jones Signed-off-by: Thomas Huth Link: https://lore.kernel.org/r/20190731151525.17156-4-thuth@redhat.com Signed-off-by: Christian Borntraeger --- tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/dirty_log_test.c | 59 +++++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 75ea1ecbf85a..1b48a94b4350 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -33,6 +33,7 @@ TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus TEST_GEN_PROGS_s390x += s390x/sync_regs_test +TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpus TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M)) diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c index 5d5ae1be4984..dc3346e090f5 100644 --- a/tools/testing/selftests/kvm/dirty_log_test.c +++ b/tools/testing/selftests/kvm/dirty_log_test.c @@ -26,8 +26,8 @@ /* The memory slot index to track dirty pages */ #define TEST_MEM_SLOT_INDEX 1 -/* Default guest test memory offset, 1G */ -#define DEFAULT_GUEST_TEST_MEM 0x40000000 +/* Default guest test virtual memory offset */ +#define DEFAULT_GUEST_TEST_MEM 0xc0000000 /* How many pages to dirty for each guest loop */ #define TEST_PAGES_PER_LOOP 1024 @@ -38,6 +38,27 @@ /* Interval for each host loop (ms) */ #define TEST_HOST_LOOP_INTERVAL 10UL +/* Dirty bitmaps are always little endian, so we need to swap on big endian */ +#if defined(__s390x__) +# define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) +# define test_bit_le(nr, addr) \ + test_bit((nr) ^ BITOP_LE_SWIZZLE, addr) +# define set_bit_le(nr, addr) \ + set_bit((nr) ^ BITOP_LE_SWIZZLE, addr) +# define clear_bit_le(nr, addr) \ + clear_bit((nr) ^ BITOP_LE_SWIZZLE, addr) +# define test_and_set_bit_le(nr, addr) \ + test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, addr) +# define test_and_clear_bit_le(nr, addr) \ + test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, addr) +#else +# define test_bit_le test_bit +# define set_bit_le set_bit +# define clear_bit_le clear_bit +# define test_and_set_bit_le test_and_set_bit +# define test_and_clear_bit_le test_and_clear_bit +#endif + /* * Guest/Host shared variables. Ensure addr_gva2hva() and/or * sync_global_to/from_guest() are used when accessing from @@ -69,11 +90,23 @@ static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM; */ static void guest_code(void) { + uint64_t addr; int i; + /* + * On s390x, all pages of a 1M segment are initially marked as dirty + * when a page of the segment is written to for the very first time. + * To compensate this specialty in this test, we need to touch all + * pages during the first iteration. + */ + for (i = 0; i < guest_num_pages; i++) { + addr = guest_test_virt_mem + i * guest_page_size; + *(uint64_t *)addr = READ_ONCE(iteration); + } + while (true) { for (i = 0; i < TEST_PAGES_PER_LOOP; i++) { - uint64_t addr = guest_test_virt_mem; + addr = guest_test_virt_mem; addr += (READ_ONCE(random_array[i]) % guest_num_pages) * guest_page_size; addr &= ~(host_page_size - 1); @@ -158,15 +191,15 @@ static void vm_dirty_log_verify(unsigned long *bmap) value_ptr = host_test_mem + page * host_page_size; /* If this is a special page that we were tracking... */ - if (test_and_clear_bit(page, host_bmap_track)) { + if (test_and_clear_bit_le(page, host_bmap_track)) { host_track_next_count++; - TEST_ASSERT(test_bit(page, bmap), + TEST_ASSERT(test_bit_le(page, bmap), "Page %"PRIu64" should have its dirty bit " "set in this iteration but it is missing", page); } - if (test_bit(page, bmap)) { + if (test_bit_le(page, bmap)) { host_dirty_count++; /* * If the bit is set, the value written onto @@ -209,7 +242,7 @@ static void vm_dirty_log_verify(unsigned long *bmap) * should report its dirtyness in the * next run */ - set_bit(page, host_bmap_track); + set_bit_le(page, host_bmap_track); } } } @@ -293,6 +326,10 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations, * case where the size is not aligned to 64 pages. */ guest_num_pages = (1ul << (30 - guest_page_shift)) + 16; +#ifdef __s390x__ + /* Round up to multiple of 1M (segment size) */ + guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; +#endif host_page_size = getpagesize(); host_num_pages = (guest_num_pages * guest_page_size) / host_page_size + !!((guest_num_pages * guest_page_size) % host_page_size); @@ -304,6 +341,11 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations, guest_test_phys_mem = phys_offset; } +#ifdef __s390x__ + /* Align to 1M (segment size) */ + guest_test_phys_mem &= ~((1 << 20) - 1); +#endif + DEBUG("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem); bmap = bitmap_alloc(host_num_pages); @@ -454,6 +496,9 @@ int main(int argc, char *argv[]) vm_guest_mode_params_init(VM_MODE_P48V48_64K, true, true); } #endif +#ifdef __s390x__ + vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); +#endif while ((opt = getopt(argc, argv, "hi:I:p:m:")) != -1) { switch (opt) { -- GitLab From bb06b54721fb58f51f051dc925263f480500b506 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 14:29:56 +0200 Subject: [PATCH 1712/7155] ARM: dts: stm32: remove fixed regulator unit address on stm32429i-eval vref fixed regulator shouldn't have unit address and reg properties. Rename the label and phandle to "vref" according to the schematics. Also remove it from simple-bus. Fixes: 7465d81191a1 ("ARM: dts: stm32: enable ADC on stm32f429i-eval board") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32429i-eval.dts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts index 73ea84df7bf4..d79f58f03387 100644 --- a/arch/arm/boot/dts/stm32429i-eval.dts +++ b/arch/arm/boot/dts/stm32429i-eval.dts @@ -81,18 +81,12 @@ dma-ranges = <0xc0000000 0x0 0x10000000>; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - reg_vref: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "vref"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; + vref: regulator-vref { + compatible = "regulator-fixed"; + regulator-name = "vref"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; }; leds { @@ -157,7 +151,7 @@ &adc { pinctrl-names = "default"; pinctrl-0 = <&adc3_in8_pin>; - vref-supply = <®_vref>; + vref-supply = <&vref>; status = "okay"; adc3: adc@200 { st,adc-channels = <8>; -- GitLab From 1425d00aff015ca1b0ecd6d6c112b7802be1383c Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 14:29:57 +0200 Subject: [PATCH 1713/7155] ARM: dts: stm32: add missing vdda-supply to adc on stm32429i-eval Add missing vdda-supply required by STM32 ADC. Fixes: 7465d81191a1 ("ARM: dts: stm32: enable ADC on stm32f429i-eval board") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32429i-eval.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts index d79f58f03387..ba08624c6237 100644 --- a/arch/arm/boot/dts/stm32429i-eval.dts +++ b/arch/arm/boot/dts/stm32429i-eval.dts @@ -81,6 +81,12 @@ dma-ranges = <0xc0000000 0x0 0x10000000>; }; + vdda: regulator-vdda { + compatible = "regulator-fixed"; + regulator-name = "vdda"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; vref: regulator-vref { compatible = "regulator-fixed"; @@ -151,6 +157,7 @@ &adc { pinctrl-names = "default"; pinctrl-0 = <&adc3_in8_pin>; + vdda-supply = <&vdda>; vref-supply = <&vref>; status = "okay"; adc3: adc@200 { -- GitLab From 493e84c5dc4d703d976b5875f5db22dae08a0782 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 14:29:58 +0200 Subject: [PATCH 1714/7155] ARM: dts: stm32: add missing vdda-supply to adc on stm32h743i-eval Add missing vdda-supply required by STM32 ADC. Fixes: 090992a9ca54 ("ARM: dts: stm32: enable ADC on stm32h743i-eval board") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32h743i-eval.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts index ab78ad532375..e4d3c58f3d97 100644 --- a/arch/arm/boot/dts/stm32h743i-eval.dts +++ b/arch/arm/boot/dts/stm32h743i-eval.dts @@ -87,6 +87,7 @@ }; &adc_12 { + vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "okay"; adc1: adc@0 { -- GitLab From c19335e2af91dabdb5b0c8b130bad6f8fb7af5c5 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Tue, 14 May 2019 10:26:59 +0200 Subject: [PATCH 1715/7155] ARM: dts: stm32: add m4 remoteproc support on STM32MP157c Declare the M4 remote processor in a sub-node of the mlahb simple bus. Signed-off-by: Fabien Dessenne Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index 247334a6c144..c0dad0fd2c69 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -1470,4 +1470,24 @@ status = "disabled"; }; }; + + mlahb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x00000000 0x38000000 0x10000>, + <0x10000000 0x10000000 0x60000>, + <0x30000000 0x30000000 0x60000>; + + m4_rproc: m4@10000000 { + compatible = "st,stm32mp1-m4"; + reg = <0x10000000 0x40000>, + <0x30000000 0x40000>, + <0x38000000 0x10000>; + resets = <&rcc MCU_R>; + st,syscfg-holdboot = <&rcc 0x10C 0x1>; + st,syscfg-tz = <&rcc 0x000 0x1>; + status = "disabled"; + }; + }; }; -- GitLab From 037dc38a25b4d98210d9b5a433da7302a8e474c7 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Fri, 26 Jul 2019 18:06:57 +0200 Subject: [PATCH 1716/7155] ARM: dts: stm32: declare copro reserved memories on STM32MP157c-ed1 Declare reserved memories shared by the processors for STM32MP157c-ed1 board. Signed-off-by: Fabien Dessenne Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ed1.dts | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts index 4fe7f71a74d3..c57173374fea 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts @@ -28,6 +28,42 @@ #size-cells = <1>; ranges; + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + gpu_reserved: gpu@e8000000 { reg = <0xe8000000 0x8000000>; no-map; -- GitLab From f2d0ea33d251e6aa2f29c4a84c7a74aea0f02da1 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Tue, 14 May 2019 10:27:01 +0200 Subject: [PATCH 1717/7155] ARM: dts: stm32: enable m4 coprocessor support on STM32MP157c-ed1 Enable m4 coprocessor for STM32MP157c-ed1 board. Signed-off-by: Fabien Dessenne Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ed1.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts index c57173374fea..1d426ea8bdaf 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts @@ -269,6 +269,16 @@ status = "okay"; }; +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + &rng1 { status = "okay"; }; -- GitLab From c39ca797fff9c843def5f66081ea60646e579702 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Fri, 26 Jul 2019 18:08:35 +0200 Subject: [PATCH 1718/7155] ARM: dts: stm32: declare copro reserved memories on STM32MP157a-dk1 Declare reserved memories shared by the processors for STM32MP157a-dk1 Signed-off-by: Fabien Dessenne Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157a-dk1.dts | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts index f3f0e37aad4d..557dff1c2b1b 100644 --- a/arch/arm/boot/dts/stm32mp157a-dk1.dts +++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts @@ -33,6 +33,42 @@ #size-cells = <1>; ranges; + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + gpu_reserved: gpu@d4000000 { reg = <0xd4000000 0x4000000>; no-map; -- GitLab From ae5dda2d1d05f7c6263c87bc461bf6a6e12220e2 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Fri, 26 Jul 2019 18:09:53 +0200 Subject: [PATCH 1719/7155] ARM: dts: stm32: enable m4 coprocessor support on STM32MP157a-dk1 Enable m4 coprocessor for STM32MP157a-dk1 board. Signed-off-by: Fabien Dessenne Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157a-dk1.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts index 557dff1c2b1b..279bf2f729fc 100644 --- a/arch/arm/boot/dts/stm32mp157a-dk1.dts +++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts @@ -325,6 +325,16 @@ }; }; +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + &rng1 { status = "okay"; }; -- GitLab From e7c3a5beb31e88acfedb07244b51fbe345bedc25 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 1 Jul 2019 10:14:25 +0200 Subject: [PATCH 1720/7155] ARM: dts: stm32: add booster for ADC analog switches on stm32mp157c Booster for ADC analog input switches can be used when Vdda is below 2.7V to get maximum ADC analog performances. Add booster for ADC analog switches on stm32mp157c. Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index c0dad0fd2c69..b27aff04dc6d 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -109,6 +109,12 @@ }; }; + booster: regulator-booster { + compatible = "st,stm32mp1-booster"; + st,syscfg = <&syscfg>; + status = "disabled"; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; -- GitLab From 1f9510c2ff74645dd0779cdc3fba095458443d9e Mon Sep 17 00:00:00 2001 From: Erwan Le Ray Date: Mon, 1 Jul 2019 11:18:06 +0200 Subject: [PATCH 1721/7155] ARM: dts: stm32: fix -Wall W=1 compilation in stm32mp157 pinctrl for mcan Fix compilations warnings detected by -Wall W=1 compilation option: - node has a unit name, but no reg property Signed-off-by: Erwan Le Ray Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi index c4f2b23f307f..9eaec9bf8cb8 100644 --- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi @@ -574,7 +574,7 @@ }; }; - m_can1_sleep_pins_a: m_can1-sleep@0 { + m_can1_sleep_pins_a: m_can1-sleep-0 { pins { pinmux = , /* CAN1_TX */ ; /* CAN1_RX */ -- GitLab From eb5f46e54910e76c95f4251e767b5ac15532763b Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 11:52:03 +0200 Subject: [PATCH 1722/7155] ARM: dts: stm32: add pwm cells to stm32mp157c STM32 Timers support generic 3 cells PWM to encode PWM number, period and polarity. Fixes: 61fc211c484d ("ARM: dts: stm32: add timers support to stm32mp157c") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index b27aff04dc6d..c21dd9f31503 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -139,6 +139,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -167,6 +168,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -193,6 +195,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -221,6 +224,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -278,6 +282,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -299,6 +304,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -320,6 +326,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -573,6 +580,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -603,6 +611,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -676,6 +685,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -700,6 +710,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; timer@15 { @@ -723,6 +734,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; -- GitLab From 289459737869b55f8a6b4618184cb827c88e097c Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 11:52:04 +0200 Subject: [PATCH 1723/7155] ARM: dts: stm32: add pwm cells to stm32f429 STM32 Timers support generic 3 cells PWM to encode PWM number, period and polarity. Fixes: c0e14fc712d9 ("ARM: dts: stm32: add Timers driver for stm32f429 MCU") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32f429.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi index 4a4954492ed1..5c8a826b3195 100644 --- a/arch/arm/boot/dts/stm32f429.dtsi +++ b/arch/arm/boot/dts/stm32f429.dtsi @@ -112,6 +112,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -141,6 +142,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -170,6 +172,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -198,6 +201,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -267,6 +271,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -288,6 +293,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -303,6 +309,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -448,6 +455,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -469,6 +477,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -602,6 +611,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -623,6 +633,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -638,6 +649,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; -- GitLab From 4f0f89dd9060cc04de48f3efc4358b687f406158 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 19 Jun 2019 11:52:05 +0200 Subject: [PATCH 1724/7155] ARM: dts: stm32: add pwm cells to stm32f746 STM32 Timers support generic 3 cells PWM to encode PWM number, period and polarity. Fixes: 9bd7b77af8e4 ("ARM: dts: stm32: add Timers driver for stm32f746 MCU") Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32f746.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi index a25b7000a3a1..d26f93f8b9c2 100644 --- a/arch/arm/boot/dts/stm32f746.dtsi +++ b/arch/arm/boot/dts/stm32f746.dtsi @@ -94,6 +94,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -123,6 +124,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -152,6 +154,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -180,6 +183,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -249,6 +253,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -270,6 +275,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -285,6 +291,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -419,6 +426,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -440,6 +448,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -512,6 +521,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; @@ -533,6 +543,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -548,6 +559,7 @@ pwm { compatible = "st,stm32-pwm"; + #pwm-cells = <3>; status = "disabled"; }; }; -- GitLab From 92edf0a2851d44d0f456a4f177736bd45f059c26 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 3 Jul 2019 12:08:16 +0200 Subject: [PATCH 1725/7155] ARM: dts: stm32: add syscfg to ADC on stm32mp157c On stm32mp157c, the ADC inputs are multiplexed with analog switches which have reduced performances when their supply is below 2.7V (vdda by default). Add syscfg registers that can be used on stm32mp157c, to get full ADC analog performances. Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index c21dd9f31503..9b11654a0a39 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -1001,6 +1001,7 @@ clocks = <&rcc ADC12>, <&rcc ADC12_K>; clock-names = "bus", "adc"; interrupt-controller; + st,syscfg = <&syscfg>; #interrupt-cells = <1>; #address-cells = <1>; #size-cells = <0>; -- GitLab From 08b9092ff3b6ef4c53fba46f5844c054f25c2c15 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 5 Jul 2019 13:53:00 +0200 Subject: [PATCH 1726/7155] ARM: dts: stm32: add audio codec support on stm32mp157a-dk1 board Add support of Cirrus cs42l51 audio codec on stm32mp157a-dk1 board. Configuration overview: - SAI2A is the CPU interface used for the codec audio playback - SAI2B is the CPU interface used for the codec audio record - SAI2A is configured as a clock provider for the audio codec - SAI2A&B are configured as slave of the audio codec - SAI2A&B share the same interface of the audio codec Note: In master mode, cs42l51 audio codec provides a bitclock at 64 x FS, regardless of data width. This means that slot width is always 32 bits. Set slot width to 32 bits and slot number to 2 in SAI2A&B endpoint nodes, to match this constraint. dai-tdm-slot-num and dai-tdm-slot-width properties are used here, assuming that i2s is a special case of tdm, where slot number is 2. Signed-off-by: Olivier Moysan Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157a-dk1.dts | 89 +++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts index 279bf2f729fc..0615d1c8a6fc 100644 --- a/arch/arm/boot/dts/stm32mp157a-dk1.dts +++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts @@ -84,6 +84,17 @@ default-state = "off"; }; }; + + sound { + compatible = "audio-graph-card"; + label = "STM32MP1-DK"; + routing = + "Playback" , "MCLK", + "Capture" , "MCLK", + "MICL" , "Mic Bias"; + dais = <&sai2a_port &sai2b_port>; + status = "okay"; + }; }; &cec { @@ -152,6 +163,39 @@ }; }; }; + + cs42l51: cs42l51@4a { + compatible = "cirrus,cs42l51"; + reg = <0x4a>; + #sound-dai-cells = <0>; + VL-supply = <&v3v3>; + VD-supply = <&v1v8_audio>; + VA-supply = <&v1v8_audio>; + VAHP-supply = <&v1v8_audio>; + reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; + clocks = <&sai2a>; + clock-names = "MCLK"; + status = "okay"; + + cs42l51_port: port { + #address-cells = <1>; + #size-cells = <0>; + + cs42l51_tx_endpoint: endpoint@0 { + reg = <0>; + remote-endpoint = <&sai2a_endpoint>; + frame-master; + bitclock-master; + }; + + cs42l51_rx_endpoint: endpoint@1 { + reg = <1>; + remote-endpoint = <&sai2b_endpoint>; + frame-master; + bitclock-master; + }; + }; + }; }; &i2c4 { @@ -343,6 +387,51 @@ status = "okay"; }; +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; + pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; + status = "okay"; + + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&cs42l51_tx_endpoint>; + format = "i2s"; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; + }; + }; + + sai2b: audio-controller@4400b024 { + dma-names = "rx"; + st,sync = <&sai2a 2>; + clocks = <&rcc SAI2_K>, <&sai2a>; + clock-names = "sai_ck", "MCLK"; + status = "okay"; + + sai2b_port: port { + sai2b_endpoint: endpoint { + remote-endpoint = <&cs42l51_rx_endpoint>; + format = "i2s"; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; + }; + }; +}; + &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc1_b4_pins_a>; -- GitLab From 98414811d773e86187d3ece2c47c79df928d8a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Fertr=C3=A9?= Date: Mon, 29 Jul 2019 16:29:08 +0200 Subject: [PATCH 1727/7155] ARM: dts: stm32: add phy-dsi-supply property on stm32mp157c-ev1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dsi physical layer is powered by the 1v8 power controller supply. Signed-off-by: Yannick Fertré Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ev1.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts index 9ab25dabcff7..89d29b50c3f4 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -101,6 +101,7 @@ &dsi { #address-cells = <1>; #size-cells = <0>; + phy-dsi-supply = <®18>; status = "okay"; ports { -- GitLab From 49490d51743cedad368f3d76f76406bc4b75fd51 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Wed, 31 Jul 2019 17:26:09 +0200 Subject: [PATCH 1728/7155] ARM: dts: stm32: remove useless pinctrl entries in stm32mp157-pinctrl This patch removes "ngpios" and "gpio-ranges" information from stm32mp157-pinctrl.dtsi file as it is now filled in stm32mp157 pinctrl package files. Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 24 ----------------------- 1 file changed, 24 deletions(-) diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi index 9eaec9bf8cb8..e4a0d51ec3a8 100644 --- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi @@ -24,8 +24,6 @@ reg = <0x0 0x400>; clocks = <&rcc GPIOA>; st,bank-name = "GPIOA"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 0 16>; status = "disabled"; }; @@ -37,8 +35,6 @@ reg = <0x1000 0x400>; clocks = <&rcc GPIOB>; st,bank-name = "GPIOB"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 16 16>; status = "disabled"; }; @@ -50,8 +46,6 @@ reg = <0x2000 0x400>; clocks = <&rcc GPIOC>; st,bank-name = "GPIOC"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 32 16>; status = "disabled"; }; @@ -63,8 +57,6 @@ reg = <0x3000 0x400>; clocks = <&rcc GPIOD>; st,bank-name = "GPIOD"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 48 16>; status = "disabled"; }; @@ -76,8 +68,6 @@ reg = <0x4000 0x400>; clocks = <&rcc GPIOE>; st,bank-name = "GPIOE"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 64 16>; status = "disabled"; }; @@ -89,8 +79,6 @@ reg = <0x5000 0x400>; clocks = <&rcc GPIOF>; st,bank-name = "GPIOF"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 80 16>; status = "disabled"; }; @@ -102,8 +90,6 @@ reg = <0x6000 0x400>; clocks = <&rcc GPIOG>; st,bank-name = "GPIOG"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 96 16>; status = "disabled"; }; @@ -115,8 +101,6 @@ reg = <0x7000 0x400>; clocks = <&rcc GPIOH>; st,bank-name = "GPIOH"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 112 16>; status = "disabled"; }; @@ -128,8 +112,6 @@ reg = <0x8000 0x400>; clocks = <&rcc GPIOI>; st,bank-name = "GPIOI"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 128 16>; status = "disabled"; }; @@ -141,8 +123,6 @@ reg = <0x9000 0x400>; clocks = <&rcc GPIOJ>; st,bank-name = "GPIOJ"; - ngpios = <16>; - gpio-ranges = <&pinctrl 0 144 16>; status = "disabled"; }; @@ -154,8 +134,6 @@ reg = <0xa000 0x400>; clocks = <&rcc GPIOK>; st,bank-name = "GPIOK"; - ngpios = <8>; - gpio-ranges = <&pinctrl 0 160 8>; status = "disabled"; }; @@ -893,8 +871,6 @@ clocks = <&rcc GPIOZ>; st,bank-name = "GPIOZ"; st,bank-ioport = <11>; - ngpios = <8>; - gpio-ranges = <&pinctrl_z 0 400 8>; status = "disabled"; }; -- GitLab From 320b96e41bb7579ebdc1e852e39a7cb18627bec3 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Fri, 21 Jun 2019 16:49:50 +0200 Subject: [PATCH 1729/7155] ARM: multi_v7_defconfig: add FMC2 NAND controller support This patch adds FMC2 NAND controller support used by STM32MP SOCs. Signed-off-by: Christophe Kerello Signed-off-by: Alexandre Torgue --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6a40bc2ef271..13f8524eb986 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -197,6 +197,7 @@ CONFIG_MTD_NAND_GPMI_NAND=y CONFIG_MTD_NAND_BRCMNAND=y CONFIG_MTD_NAND_VF610_NFC=y CONFIG_MTD_NAND_DAVINCI=y +CONFIG_MTD_NAND_STM32_FMC2=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y -- GitLab From b343037de48f1da690364609bfdfba81005b49a4 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 1 Jul 2019 10:14:24 +0200 Subject: [PATCH 1730/7155] ARM: multi_v7_defconfig: enable STM32 booster regulator This enables the driver for STM32 booster regulator found on stm32mp1. Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre Torgue --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 13f8524eb986..8f589f4bff92 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -570,6 +570,7 @@ CONFIG_REGULATOR_RK808=y CONFIG_REGULATOR_RN5T618=y CONFIG_REGULATOR_S2MPS11=y CONFIG_REGULATOR_S5M8767=y +CONFIG_REGULATOR_STM32_BOOSTER=m CONFIG_REGULATOR_STM32_VREFBUF=m CONFIG_REGULATOR_STPMIC1=y CONFIG_REGULATOR_TI_ABB=y -- GitLab From b5deabd439ed644c7e22e3217883550d86791851 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Wed, 31 Jul 2019 09:22:04 +0200 Subject: [PATCH 1731/7155] ARM: multi_v7_defconfig: Enable SPI_STM32_QSPI support Enable support for QSPI block on STM32 SoCs. Signed-off-by: Patrice Chotard Signed-off-by: Alexandre Torgue --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 8f589f4bff92..c5d37dfafe98 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -404,6 +404,7 @@ CONFIG_SPI_SH_MSIOF=m CONFIG_SPI_SH_HSPI=y CONFIG_SPI_SIRF=y CONFIG_SPI_STM32=m +CONFIG_SPI_STM32_QSPI=m CONFIG_SPI_SUN4I=y CONFIG_SPI_SUN6I=y CONFIG_SPI_TEGRA114=y -- GitLab From bd4bd337039df9d5c6a3c11c439511fd99e11f52 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 18 Jul 2019 17:49:02 +0800 Subject: [PATCH 1732/7155] gpio: mpc8xxx: Add ls1028a device specify function. There is a device specify register(named GPIO_IBE) on ls1028a need to enable in initial stage. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190718094902.15562-2-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mpc8xxx.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index c8673a5d9412..1a680aa28769 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -32,6 +32,7 @@ #define GPIO_IMR 0x10 #define GPIO_ICR 0x14 #define GPIO_ICR2 0x18 +#define GPIO_IBE 0x18 struct mpc8xxx_gpio_chip { struct gpio_chip gc; @@ -45,6 +46,27 @@ struct mpc8xxx_gpio_chip { unsigned int irqn; }; +/* The GPIO Input Buffer Enable register(GPIO_IBE) is used to + * control the input enable of each individual GPIO port. + * When an individual GPIO port’s direction is set to + * input (GPIO_GPDIR[DRn=0]), the associated input enable must be + * set (GPIOxGPIE[IEn]=1) to propagate the port value to the GPIO + * Data Register. + */ +static int ls1028a_gpio_dir_in_init(struct gpio_chip *gc) +{ + unsigned long flags; + struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc); + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + /* * This hardware has a big endian bit assignment such that GPIO line 0 is * connected to bit 31, line 1 to bit 30 ... line 31 to bit 0. @@ -261,6 +283,7 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = { }; struct mpc8xxx_gpio_devtype { + int (*gpio_dir_in_init)(struct gpio_chip *chip); int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int); int (*gpio_get)(struct gpio_chip *, unsigned int); int (*irq_set_type)(struct irq_data *, unsigned int); @@ -271,6 +294,10 @@ static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = { .irq_set_type = mpc512x_irq_set_type, }; +static const struct mpc8xxx_gpio_devtype ls1028a_gpio_devtype = { + .gpio_dir_in_init = ls1028a_gpio_dir_in_init, +}; + static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = { .gpio_dir_out = mpc5125_gpio_dir_out, .irq_set_type = mpc512x_irq_set_type, @@ -291,6 +318,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = { { .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, }, { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,pq3-gpio", }, + { .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, }, { .compatible = "fsl,qoriq-gpio", }, {} }; @@ -376,6 +404,9 @@ static int mpc8xxx_probe(struct platform_device *pdev) /* ack and mask all irqs */ gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff); gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0); + /* enable input buffer */ + if (devtype->gpio_dir_in_init) + devtype->gpio_dir_in_init(gc); irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); -- GitLab From 7bdbd1eccc9fb3875f33af1a2257001128824e81 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Jul 2019 15:51:01 +0900 Subject: [PATCH 1733/7155] gpio: refactor gpiochip_allocate_mask() with bitmap_alloc() Refactor gpiochip_allocate_mask() slightly by using bitmap_alloc(). I used bitmap_free() for the corresponding free parts. Actually, bitmap_free() is a wrapper of kfree(), but I did this for consistency. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190718065101.26994-1-yamada.masahiro@socionext.com Reviewed-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20f13129cdaa..537a37a89891 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -351,7 +351,7 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) { unsigned long *p; - p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL); + p = bitmap_alloc(chip->ngpio, GFP_KERNEL); if (!p) return NULL; @@ -385,7 +385,7 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) { - kfree(gpiochip->valid_mask); + bitmap_free(gpiochip->valid_mask); gpiochip->valid_mask = NULL; } @@ -1620,7 +1620,7 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) { - kfree(gpiochip->irq.valid_mask); + bitmap_free(gpiochip->irq.valid_mask); gpiochip->irq.valid_mask = NULL; } -- GitLab From 94562040da08611ca15eecb39c68be8caac4bf06 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 31 Jul 2019 08:15:27 -0700 Subject: [PATCH 1734/7155] ARM: dts: rockchip: A few fixes for veyron-{fievel,tiger} Fix/improve a few things for veyron fievel/tiger: - move 'vccsys' regulator from tiger to fievel, both boards have it (and tiger includes the fievel .dtsi) - move 'ext_gmac' node below regulators - fix GPIO ids of vcc5_host1 and vcc5_host2 regulators - remove reset configuration from 'gmac' node, this is already done in rk3288.dtsi - fixed style issues of some multi-line comments - switch 'vcc18_lcdt', 'vdd10_lcd' and 'vcc33_ccd' regulators off during suspend - no pull-up on the Bluetooth wake-up pin, there is an external pull-up. The signal is active low, add the 'bt_host_wake_l' pinctrl config - move BC 1.2 pins up in the pinctrl config to keep 'wake only' pins separate - add BC 1.2 pins to sleep config Fixes: 0067692b662e ("ARM: dts: rockchip: add veyron-fievel board") Reviewed-by: Douglas Anderson Signed-off-by: Matthias Kaehlcke Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-fievel.dts | 58 +++++++++++++--------- arch/arm/boot/dts/rk3288-veyron-tiger.dts | 7 --- arch/arm/boot/dts/rk3288-veyron.dtsi | 4 ++ 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rk3288-veyron-fievel.dts index 696566f72d30..65d029ccc907 100644 --- a/arch/arm/boot/dts/rk3288-veyron-fievel.dts +++ b/arch/arm/boot/dts/rk3288-veyron-fievel.dts @@ -20,11 +20,11 @@ /delete-node/ bt-activity; - ext_gmac: external-gmac-clock { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <125000000>; - clock-output-names = "ext_gmac"; + vccsys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vccsys"; + regulator-boot-on; + regulator-always-on; }; /* @@ -41,7 +41,7 @@ vcc5_host1: vcc5-host1-regulator { compatible = "regulator-fixed"; enable-active-high; - gpio = <&gpio5 RK_PC1 GPIO_ACTIVE_HIGH>; + gpio = <&gpio5 RK_PC2 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&hub_usb1_pwr_en>; regulator-name = "vcc5_host1"; @@ -52,7 +52,7 @@ vcc5_host2: vcc5-host2-regulator { compatible = "regulator-fixed"; enable-active-high; - gpio = <&gpio5 RK_PC2 GPIO_ACTIVE_HIGH>; + gpio = <&gpio5 RK_PB6 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&hub_usb2_pwr_en>; regulator-name = "vcc5_host2"; @@ -70,6 +70,13 @@ regulator-always-on; regulator-boot-on; }; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + }; }; &gmac { @@ -83,13 +90,13 @@ phy-supply = <&vcc33_lan>; pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>; - resets = <&cru SRST_MAC>; - reset-names = "stmmaceth"; rx_delay = <0x10>; tx_delay = <0x30>; - /* Reset for the RTL8211 PHY which requires a 10-ms reset pulse (low) - * with a 30ms settling time. */ + /* + * Reset for the RTL8211 PHY which requires a 10-ms reset pulse (low) + * with a 30ms settling time. + */ snps,reset-gpio = <&gpio4 RK_PB0 0>; snps,reset-active-low; snps,reset-delays-us = <0 10000 30000>; @@ -120,7 +127,8 @@ regulators { /delete-node/ LDO_REG1; - /* According to the schematic, vcc18_lcdt is for + /* + * According to the schematic, vcc18_lcdt is for * HDMI_AVDD_1V8 */ vcc18_lcdt: LDO_REG2 { @@ -130,12 +138,12 @@ regulator-max-microvolt = <1800000>; regulator-name = "vdd18_lcdt"; regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; + regulator-off-in-suspend; }; }; - /* This is not a pwren anymore, but the real power supply, + /* + * This is not a pwren anymore, but the real power supply, * vdd10_lcd for HDMI_AVDD_1V0 */ vdd10_lcd: LDO_REG7 { @@ -145,8 +153,7 @@ regulator-max-microvolt = <1000000>; regulator-name = "vdd10_lcd"; regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; + regulator-off-in-suspend; }; }; @@ -158,8 +165,7 @@ regulator-max-microvolt = <3300000>; regulator-name = "vcc33_ccd"; regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; + regulator-off-in-suspend; }; }; @@ -180,7 +186,7 @@ interrupts = ; marvell,wakeup-pin = /bits/ 16 <13>; pinctrl-names = "default"; - pinctrl-0 = <&bt_host_wake>; + pinctrl-0 = <&bt_host_wake_l>; }; }; @@ -206,13 +212,13 @@ &ddrio_pwroff &global_pwroff - /* Wake only */ - &bt_dev_wake_awake - &pwr_led1_on - /* For usb bc1.2 */ &usb_otg_ilim_sel &usb_usb_ilim_sel + + /* Wake only */ + &bt_dev_wake_awake + &pwr_led1_on >; pinctrl-1 = < @@ -221,6 +227,10 @@ &ddrio_pwroff &global_pwroff + /* For usb bc1.2 */ + &usb_otg_ilim_sel + &usb_usb_ilim_sel + /* Sleep only */ &bt_dev_wake_sleep &pwr_led1_blink diff --git a/arch/arm/boot/dts/rk3288-veyron-tiger.dts b/arch/arm/boot/dts/rk3288-veyron-tiger.dts index fae26d530841..27557203ae33 100644 --- a/arch/arm/boot/dts/rk3288-veyron-tiger.dts +++ b/arch/arm/boot/dts/rk3288-veyron-tiger.dts @@ -19,13 +19,6 @@ "google,veyron", "rockchip,rk3288"; /delete-node/ vcc18-lcd; - - vccsys: vccsys { - compatible = "regulator-fixed"; - regulator-name = "vccsys"; - regulator-boot-on; - regulator-always-on; - }; }; &backlight { diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi index 8fc8eac699bf..7525e3dd1fc1 100644 --- a/arch/arm/boot/dts/rk3288-veyron.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi @@ -586,6 +586,10 @@ rockchip,pins = <4 RK_PD7 RK_FUNC_GPIO &pcfg_pull_down>; }; + bt_host_wake_l: bt-host-wake-l { + rockchip,pins = <4 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + /* * We run sdio0 at max speed; bump up drive strength. * We also have external pulls, so disable the internal ones. -- GitLab From 6f79fcc6c9e311d489989e0909d86c0762d3ac61 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 1 Aug 2019 15:03:54 -0700 Subject: [PATCH 1735/7155] ARM: dts: rockchip: Add pin names for rk3288-veyron fievel This is like commit 0ca87bd5baa6 ("ARM: dts: rockchip: Add pin names for rk3288-veyron-jerry") and other similar commits, but for the veyron fievel board (and tiger, which includes the fievel .dtsi). Signed-off-by: Matthias Kaehlcke Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-veyron-fievel.dts | 214 +++++++++++++++++++++ 1 file changed, 214 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rk3288-veyron-fievel.dts index 65d029ccc907..9a0f55085839 100644 --- a/arch/arm/boot/dts/rk3288-veyron-fievel.dts +++ b/arch/arm/boot/dts/rk3288-veyron-fievel.dts @@ -204,6 +204,220 @@ pinctrl-0 = <&drv_5v>; }; +&gpio0 { + gpio-line-names = "PMIC_SLEEP_AP", + "DDRIO_PWROFF", + "DDRIO_RETEN", + "TS3A227E_INT_L", + "PMIC_INT_L", + "PWR_KEY_L", + "HUB_USB1_nFALUT", + "PHY_PMEB", + + "PHY_INT", + "REC_MODE_L", + "OTP_OUT", + "", + "USB_OTG_POWER_EN", + "AP_WARM_RESET_H", + "USB_OTG_nFALUT", + "I2C0_SDA_PMIC", + + "I2C0_SCL_PMIC", + "DEVMODE_L", + "USB_INT"; +}; + +&gpio2 { + gpio-line-names = "CONFIG0", + "CONFIG1", + "CONFIG2", + "", + "", + "", + "", + "CONFIG3", + + "", + "EMMC_RST_L", + "", + "", + "BL_PWR_EN", + "", + "TOUCH_INT", + "TOUCH_RST", + + "I2C3_SCL_TP", + "I2C3_SDA_TP"; +}; + +&gpio3 { + gpio-line-names = "FLASH0_D0", + "FLASH0_D1", + "FLASH0_D2", + "FLASH0_D3", + "FLASH0_D4", + "FLASH0_D5", + "FLASH0_D6", + "FLASH0_D7", + + "VCC5V_GOOD_H", + "", + "", + "", + "", + "", + "", + "", + + "FLASH0_CS2/EMMC_CMD", + "", + "FLASH0_DQS/EMMC_CLKO", + "", + "", + "", + "", + "", + + "PHY_TXD2", + "PHY_TXD3", + "MAC_RXD2", + "MAC_RXD3", + "PHY_TXD0", + "PHY_TXD1", + "MAC_RXD0", + "MAC_RXD1"; +}; + +&gpio4 { + gpio-line-names = "MAC_MDC", + "MAC_RXDV", + "MAC_RXER", + "MAC_CLK", + "PHY_TXEN", + "MAC_MDIO", + "MAC_RXCLK", + "", + + "PHY_RST", + "PHY_TXCLK", + "", + "", + "", + "", + "", + "", + + "UART0_RXD", + "UART0_TXD", + "UART0_CTS_L", + "UART0_RTS_L", + "SDIO0_D0", + "SDIO0_D1", + "SDIO0_D2", + "SDIO0_D3", + + "SDIO0_CMD", + "SDIO0_CLK", + "BT_DEV_WAKE", + "", + "WIFI_ENABLE_H", + "BT_ENABLE_L", + "WIFI_HOST_WAKE", + "BT_HOST_WAKE"; +}; + +&gpio5 { + gpio-line-names = "", + "", + "", + "", + "", + "", + "", + "", + + "", + "", + "", + "", + "USB_OTG_CTL1", + "HUB_USB2_CTL1", + "HUB_USB2_PWR_EN", + "HUB_USB_ILIM_SEL", + + "USB_OTG_STATUS_L", + "HUB_USB1_CTL1", + "HUB_USB1_PWR_EN", + "VCC50_HDMI_EN"; +}; + +&gpio6 { + gpio-line-names = "I2S0_SCLK", + "I2S0_LRCK_RX", + "I2S0_LRCK_TX", + "I2S0_SDI", + "I2S0_SDO0", + "HP_DET_H", + "", + "INT_CODEC", + + "I2S0_CLK", + "I2C2_SDA", + "I2C2_SCL", + "MICDET", + "", + "", + "", + "", + + "HUB_USB2_nFALUT", + "USB_OTG_ILIM_SEL"; +}; + +&gpio7 { + gpio-line-names = "LCD_BL_PWM", + "PWM_LOG", + "BL_EN", + "PWR_LED1", + "TPM_INT_H", + "SPK_ON", + "FW_WP_AP", + "", + + "CPU_NMI", + "DVSOK", + "", + "EDP_HPD", + "DVS1", + "", + "LCD_EN", + "DVS2", + + "HDMI_CEC", + "I2C4_SDA", + "I2C4_SCL", + "I2C5_SDA_HDMI", + "I2C5_SCL_HDMI", + "5V_DRV", + "UART2_RXD", + "UART2_TXD"; +}; + +&gpio8 { + gpio-line-names = "RAM_ID0", + "RAM_ID1", + "RAM_ID2", + "RAM_ID3", + "I2C1_SDA_TPM", + "I2C1_SCL_TPM", + "SPI2_CLK", + "SPI2_CS0", + + "SPI2_RXD", + "SPI2_TXD"; +}; + &pinctrl { pinctrl-names = "default", "sleep"; pinctrl-0 = < -- GitLab From 94166fd21af318be13aa9b66c4de381a4817ed3d Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 31 Jul 2019 15:09:56 +0930 Subject: [PATCH 1736/7155] dt-bindings: net: Add aspeed, ast2600-mdio binding The AST2600 splits out the MDIO bus controller from the MAC into its own IP block and rearranges the register layout. Add a new binding to describe the new hardware. Signed-off-by: Andrew Jeffery Reviewed-by: Rob Herring Signed-off-by: David S. Miller --- .../bindings/net/aspeed,ast2600-mdio.yaml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/aspeed,ast2600-mdio.yaml diff --git a/Documentation/devicetree/bindings/net/aspeed,ast2600-mdio.yaml b/Documentation/devicetree/bindings/net/aspeed,ast2600-mdio.yaml new file mode 100644 index 000000000000..71808e78a495 --- /dev/null +++ b/Documentation/devicetree/bindings/net/aspeed,ast2600-mdio.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/aspeed,ast2600-mdio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ASPEED AST2600 MDIO Controller + +maintainers: + - Andrew Jeffery + +description: |+ + The ASPEED AST2600 MDIO controller is the third iteration of ASPEED's MDIO + bus register interface, this time also separating out the controller from the + MAC. + +allOf: + - $ref: "mdio.yaml#" + +properties: + compatible: + const: aspeed,ast2600-mdio + reg: + maxItems: 1 + description: The register range of the MDIO controller instance + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +examples: + - | + mdio0: mdio@1e650000 { + compatible = "aspeed,ast2600-mdio"; + reg = <0x1e650000 0x8>; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + }; -- GitLab From f160e99462c68ab5b9e2b9097a4867459730b49a Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 31 Jul 2019 15:09:57 +0930 Subject: [PATCH 1737/7155] net: phy: Add mdio-aspeed The AST2600 design separates the MDIO controllers from the MAC, which is where they were placed in the AST2400 and AST2500. Further, the register interface is reworked again, so now we have three possible different interface implementations, however this driver only supports the interface provided by the AST2600. The AST2400 and AST2500 will continue to be supported by the MDIO support embedded in the FTGMAC100 driver. The hardware supports both C22 and C45 mode, but for the moment only C22 support is implemented. Signed-off-by: Andrew Jeffery Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 13 +++ drivers/net/phy/Makefile | 1 + drivers/net/phy/mdio-aspeed.c | 157 ++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/net/phy/mdio-aspeed.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 20f14c5fbb7e..206d8650ee7f 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -21,6 +21,19 @@ config MDIO_BUS if MDIO_BUS +config MDIO_ASPEED + tristate "ASPEED MDIO bus controller" + depends on ARCH_ASPEED || COMPILE_TEST + depends on OF_MDIO && HAS_IOMEM + help + This module provides a driver for the independent MDIO bus + controllers found in the ASPEED AST2600 SoC. This is a driver for the + third revision of the ASPEED MDIO register interface - the first two + revisions are the "old" and "new" interfaces found in the AST2400 and + AST2500, embedded in the MAC. For legacy reasons, FTGMAC100 driver + continues to drive the embedded MDIO controller for the AST2400 and + AST2500 SoCs, so say N if AST2600 support is not required. + config MDIO_BCM_IPROC tristate "Broadcom iProc MDIO bus controller" depends on ARCH_BCM_IPROC || COMPILE_TEST diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 839acb292c38..ba07c27e4208 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -22,6 +22,7 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o obj-$(CONFIG_PHYLINK) += phylink.o obj-$(CONFIG_PHYLIB) += libphy.o +obj-$(CONFIG_MDIO_ASPEED) += mdio-aspeed.o obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o diff --git a/drivers/net/phy/mdio-aspeed.c b/drivers/net/phy/mdio-aspeed.c new file mode 100644 index 000000000000..cad820568f75 --- /dev/null +++ b/drivers/net/phy/mdio-aspeed.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (C) 2019 IBM Corp. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "mdio-aspeed" + +#define ASPEED_MDIO_CTRL 0x0 +#define ASPEED_MDIO_CTRL_FIRE BIT(31) +#define ASPEED_MDIO_CTRL_ST BIT(28) +#define ASPEED_MDIO_CTRL_ST_C45 0 +#define ASPEED_MDIO_CTRL_ST_C22 1 +#define ASPEED_MDIO_CTRL_OP GENMASK(27, 26) +#define MDIO_C22_OP_WRITE 0b01 +#define MDIO_C22_OP_READ 0b10 +#define ASPEED_MDIO_CTRL_PHYAD GENMASK(25, 21) +#define ASPEED_MDIO_CTRL_REGAD GENMASK(20, 16) +#define ASPEED_MDIO_CTRL_MIIWDATA GENMASK(15, 0) + +#define ASPEED_MDIO_DATA 0x4 +#define ASPEED_MDIO_DATA_MDC_THRES GENMASK(31, 24) +#define ASPEED_MDIO_DATA_MDIO_EDGE BIT(23) +#define ASPEED_MDIO_DATA_MDIO_LATCH GENMASK(22, 20) +#define ASPEED_MDIO_DATA_IDLE BIT(16) +#define ASPEED_MDIO_DATA_MIIRDATA GENMASK(15, 0) + +#define ASPEED_MDIO_INTERVAL_US 100 +#define ASPEED_MDIO_TIMEOUT_US (ASPEED_MDIO_INTERVAL_US * 10) + +struct aspeed_mdio { + void __iomem *base; +}; + +static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum) +{ + struct aspeed_mdio *ctx = bus->priv; + u32 ctrl; + u32 data; + int rc; + + dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d\n", __func__, addr, + regnum); + + /* Just clause 22 for the moment */ + if (regnum & MII_ADDR_C45) + return -EOPNOTSUPP; + + ctrl = ASPEED_MDIO_CTRL_FIRE + | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22) + | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_READ) + | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr) + | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum); + + iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); + + rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data, + data & ASPEED_MDIO_DATA_IDLE, + ASPEED_MDIO_INTERVAL_US, + ASPEED_MDIO_TIMEOUT_US); + if (rc < 0) + return rc; + + return FIELD_GET(ASPEED_MDIO_DATA_MIIRDATA, data); +} + +static int aspeed_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val) +{ + struct aspeed_mdio *ctx = bus->priv; + u32 ctrl; + + dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d, val: 0x%x\n", + __func__, addr, regnum, val); + + /* Just clause 22 for the moment */ + if (regnum & MII_ADDR_C45) + return -EOPNOTSUPP; + + ctrl = ASPEED_MDIO_CTRL_FIRE + | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22) + | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_WRITE) + | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr) + | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum) + | FIELD_PREP(ASPEED_MDIO_CTRL_MIIWDATA, val); + + iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); + + return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl, + !(ctrl & ASPEED_MDIO_CTRL_FIRE), + ASPEED_MDIO_INTERVAL_US, + ASPEED_MDIO_TIMEOUT_US); +} + +static int aspeed_mdio_probe(struct platform_device *pdev) +{ + struct aspeed_mdio *ctx; + struct mii_bus *bus; + int rc; + + bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*ctx)); + if (!bus) + return -ENOMEM; + + ctx = bus->priv; + ctx->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ctx->base)) + return PTR_ERR(ctx->base); + + bus->name = DRV_NAME; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); + bus->parent = &pdev->dev; + bus->read = aspeed_mdio_read; + bus->write = aspeed_mdio_write; + + rc = of_mdiobus_register(bus, pdev->dev.of_node); + if (rc) { + dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); + return rc; + } + + platform_set_drvdata(pdev, bus); + + return 0; +} + +static int aspeed_mdio_remove(struct platform_device *pdev) +{ + mdiobus_unregister(platform_get_drvdata(pdev)); + + return 0; +} + +static const struct of_device_id aspeed_mdio_of_match[] = { + { .compatible = "aspeed,ast2600-mdio", }, + { }, +}; + +static struct platform_driver aspeed_mdio_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = aspeed_mdio_of_match, + }, + .probe = aspeed_mdio_probe, + .remove = aspeed_mdio_remove, +}; + +module_platform_driver(aspeed_mdio_driver); + +MODULE_AUTHOR("Andrew Jeffery "); +MODULE_LICENSE("GPL"); -- GitLab From 39bfab8844a0fabea812f99dc6aa88734323a920 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 31 Jul 2019 15:09:58 +0930 Subject: [PATCH 1738/7155] net: ftgmac100: Add support for DT phy-handle property phy-handle is necessary for the AST2600 which separates the MDIO controllers from the MAC. I've tried to minimise the intrusion of supporting the AST2600 to the FTGMAC100 by leaving in place the existing MDIO support for the embedded MDIO interface. The AST2400 and AST2500 continue to be supported this way, as it avoids breaking/reworking existing devicetrees. The AST2600 support by contrast requires the presence of the phy-handle property in the MAC devicetree node to specify the appropriate PHY to associate with the MAC. In the event that someone wants to specify the MDIO bus topology under the MAC node on an AST2400 or AST2500, the current auto-probe approach is done conditional on the absence of an "mdio" child node of the MAC. Signed-off-by: Andrew Jeffery Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/faraday/ftgmac100.c | 37 +++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index dc8d3e726e75..9b7af94a40bb 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1619,8 +1620,13 @@ static int ftgmac100_setup_mdio(struct net_device *netdev) if (!priv->mii_bus) return -EIO; - if (priv->is_aspeed) { - /* This driver supports the old MDIO interface */ + if (of_device_is_compatible(np, "aspeed,ast2400-mac") || + of_device_is_compatible(np, "aspeed,ast2500-mac")) { + /* The AST2600 has a separate MDIO controller */ + + /* For the AST2400 and AST2500 this driver only supports the + * old MDIO interface + */ reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR); reg &= ~FTGMAC100_REVR_NEW_MDIO_INTERFACE; iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR); @@ -1797,7 +1803,8 @@ static int ftgmac100_probe(struct platform_device *pdev) np = pdev->dev.of_node; if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac") || - of_device_is_compatible(np, "aspeed,ast2500-mac"))) { + of_device_is_compatible(np, "aspeed,ast2500-mac") || + of_device_is_compatible(np, "aspeed,ast2600-mac"))) { priv->rxdes0_edorr_mask = BIT(30); priv->txdes0_edotr_mask = BIT(30); priv->is_aspeed = true; @@ -1817,7 +1824,29 @@ static int ftgmac100_probe(struct platform_device *pdev) priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler); if (!priv->ndev) goto err_ncsi_dev; - } else { + } else if (np && of_get_property(np, "phy-handle", NULL)) { + struct phy_device *phy; + + phy = of_phy_get_and_connect(priv->netdev, np, + &ftgmac100_adjust_link); + if (!phy) { + dev_err(&pdev->dev, "Failed to connect to phy\n"); + goto err_setup_mdio; + } + + /* Indicate that we support PAUSE frames (see comment in + * Documentation/networking/phy.txt) + */ + phy_support_asym_pause(phy); + + /* Display what we found */ + phy_attached_info(phy); + } else if (np && !of_get_child_by_name(np, "mdio")) { + /* Support legacy ASPEED devicetree descriptions that decribe a + * MAC with an embedded MDIO controller but have no "mdio" + * child node. Automatically scan the MDIO bus for available + * PHYs. + */ priv->use_ncsi = false; err = ftgmac100_setup_mdio(netdev); if (err) -- GitLab From 82f151def2153f34a1f6f58499f22ceb2bc94042 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 31 Jul 2019 15:09:59 +0930 Subject: [PATCH 1739/7155] net: ftgmac100: Select ASPEED MDIO driver for the AST2600 Ensures we can talk to a PHY via MDIO on the AST2600, as the MDIO controller is now separate from the MAC. Signed-off-by: Andrew Jeffery Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/faraday/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig index a9b105803fb7..73e4f2648e49 100644 --- a/drivers/net/ethernet/faraday/Kconfig +++ b/drivers/net/ethernet/faraday/Kconfig @@ -32,6 +32,7 @@ config FTGMAC100 depends on ARM || NDS32 || COMPILE_TEST depends on !64BIT || BROKEN select PHYLIB + select MDIO_ASPEED if MACH_ASPEED_G6 ---help--- This driver supports the FTGMAC100 Gigabit Ethernet controller from Faraday. It is used on Faraday A369, Andes AG102 and some -- GitLab From 4902264745b524ae61d5d2df379d5c74577af823 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:46 +0200 Subject: [PATCH 1740/7155] net: dsa: mv88e6xxx: add support for MV88E6220 The MV88E6220 is almost the same as MV88E6250 except that the ports 2-4 are not routed to pins. So the usable ports are 0, 1, 5 and 6. Signed-off-by: Hubert Feurstein Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 25 +++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- drivers/net/dsa/mv88e6xxx/port.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b9dd5c4461b6..390b61651e10 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4275,6 +4275,31 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .ops = &mv88e6191_ops, }, + [MV88E6220] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6220, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6220", + .num_databases = 64, + + /* Ports 2-4 are not routed to pins + * => usable ports 0, 1, 5, 6 + */ + .num_ports = 7, + .num_internal_phys = 2, + .max_vid = 4095, + .port_base_addr = 0x08, + .phy_base_addr = 0x00, + .global1_addr = 0x0f, + .global2_addr = 0x07, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 10, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .tag_protocol = DSA_TAG_PROTO_DSA, + .ops = &mv88e6250_ops, + }, + [MV88E6240] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240, .family = MV88E6XXX_FAMILY_6352, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 4646e46d47f2..2cc508a1cc32 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -57,6 +57,7 @@ enum mv88e6xxx_model { MV88E6190, MV88E6190X, MV88E6191, + MV88E6220, MV88E6240, MV88E6250, MV88E6290, @@ -77,7 +78,7 @@ enum mv88e6xxx_family { MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ - MV88E6XXX_FAMILY_6250, /* 6250 */ + MV88E6XXX_FAMILY_6250, /* 6220 6250 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 8d5a6cd6fb19..ceec771f8bfc 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -117,6 +117,7 @@ #define MV88E6XXX_PORT_SWITCH_ID_PROD_6190 0x1900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 -- GitLab From 83c5ee315f73048d0c06c5736eb8ffe4ded2b7cc Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:47 +0200 Subject: [PATCH 1741/7155] dt-bindings: net: dsa: marvell: add 6220 model to the 6250 family The MV88E6220 is part of the MV88E6250 family. Signed-off-by: Hubert Feurstein Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/dsa/marvell.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt index 6f9538974bb9..30c11fea491b 100644 --- a/Documentation/devicetree/bindings/net/dsa/marvell.txt +++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt @@ -22,7 +22,7 @@ which is at a different MDIO base address in different switch families. - "marvell,mv88e6190" : Switch has base address 0x00. Use with models: 6190, 6190X, 6191, 6290, 6390, 6390X - "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model: - 6250 + 6220, 6250 Required properties: - compatible : Should be one of "marvell,mv88e6085", -- GitLab From c857486a4b6d5c9250832315341e5889fdcb03c3 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:48 +0200 Subject: [PATCH 1742/7155] net: dsa: mv88e6xxx: introduce invalid_port_mask in mv88e6xxx_info With this it is possible to mark certain chip ports as invalid. This is required for example for the MV88E6220 (which is in general a MV88E6250 with 7 ports) but the ports 2-4 are not routed to pins. If a user configures an invalid port, an error is returned. Signed-off-by: Hubert Feurstein Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 9 +++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 390b61651e10..7fd13468b8da 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2485,6 +2485,14 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) /* Setup Switch Port Registers */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { + /* Prevent the use of an invalid port. */ + if (mv88e6xxx_is_invalid_port(chip, i) && + !dsa_is_unused_port(ds, i)) { + dev_err(chip->dev, "port %d is invalid\n", i); + err = -EINVAL; + goto unlock; + } + if (dsa_is_unused_port(ds, i)) { err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED); @@ -4286,6 +4294,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { */ .num_ports = 7, .num_internal_phys = 2, + .invalid_port_mask = BIT(2) | BIT(3) | BIT(4), .max_vid = 4095, .port_base_addr = 0x08, .phy_base_addr = 0x00, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 2cc508a1cc32..359d258d7151 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -106,6 +106,11 @@ struct mv88e6xxx_info { unsigned int g2_irqs; bool pvt; + /* Mark certain ports as invalid. This is required for example for the + * MV88E6220 (which is in general a MV88E6250 with 7 ports) but the + * ports 2-4 are not routet to pins. + */ + unsigned int invalid_port_mask; /* Multi-chip Addressing Mode. * Some chips respond to only 2 registers of its own SMI device address * when it is non-zero, and use indirect access to internal registers. @@ -571,6 +576,11 @@ static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip) return chip->info->num_gpio; } +static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int port) +{ + return (chip->info->invalid_port_mask & BIT(port)) != 0; +} + int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, -- GitLab From 121b8fe2fdc931a60f7437a94db3b8af8c62ee54 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:49 +0200 Subject: [PATCH 1743/7155] net: dsa: mv88e6xxx: setup message port is not supported in the 6250 familiy The MV88E6250 family doesn't support the MV88E6XXX_PORT_CTL1_MESSAGE_PORT bit. Signed-off-by: Hubert Feurstein Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 34 +++++++++++++++++++++++++++++--- drivers/net/dsa/mv88e6xxx/chip.h | 1 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7fd13468b8da..ae0134d85436 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2268,9 +2268,11 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) return err; } - err = mv88e6xxx_setup_message_port(chip, port); - if (err) - return err; + if (chip->info->ops->port_setup_message_port) { + err = chip->info->ops->port_setup_message_port(chip, port); + if (err) + return err; + } /* Port based VLAN map: give each port the same default address * database, and allow bidirectional communication between the @@ -2821,6 +2823,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -2855,6 +2858,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .port_set_upstream_port = mv88e6095_port_set_upstream_port, .port_link_state = mv88e6185_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -2891,6 +2895,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -2925,6 +2930,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -2962,6 +2968,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .port_set_pause = mv88e6185_port_set_pause, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3006,6 +3013,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3046,6 +3054,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3079,6 +3088,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3120,6 +3130,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3161,6 +3172,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3203,6 +3215,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3244,6 +3257,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3282,6 +3296,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .port_set_pause = mv88e6185_port_set_pause, .port_link_state = mv88e6185_port_link_state, .port_get_cmode = mv88e6185_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3324,6 +3339,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3369,6 +3385,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390x_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3414,6 +3431,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3461,6 +3479,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3546,6 +3565,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3593,6 +3613,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3636,6 +3657,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3679,6 +3701,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3722,6 +3745,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3761,6 +3785,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3804,6 +3829,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_set_histogram = mv88e6095_g1_stats_set_histogram, .stats_get_sset_count = mv88e6095_stats_get_sset_count, @@ -3856,6 +3882,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3905,6 +3932,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .port_link_state = mv88e6352_port_link_state, .port_get_cmode = mv88e6352_port_get_cmode, .port_set_cmode = mv88e6390x_port_set_cmode, + .port_setup_message_port = mv88e6xxx_setup_message_port, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 359d258d7151..e7b88e9643b9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -395,6 +395,7 @@ struct mv88e6xxx_ops { u8 out); int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port); int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port); + int (*port_setup_message_port)(struct mv88e6xxx_chip *chip, int port); /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc. * Some chips allow this to be configured on specific ports. -- GitLab From 8858ccc837e6e89c917f4b4bb1d7335d62e1baab Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:50 +0200 Subject: [PATCH 1744/7155] net: dsa: mv88e6xxx: order ptp structs numerically ascending As it is done for all the other structs within this driver. Signed-off-by: Hubert Feurstein Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/ptp.c | 32 ++++++++++++++++---------------- drivers/net/dsa/mv88e6xxx/ptp.h | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c index 768d256f7c9f..a1ff182c8737 100644 --- a/drivers/net/dsa/mv88e6xxx/ptp.c +++ b/drivers/net/dsa/mv88e6xxx/ptp.c @@ -310,6 +310,22 @@ static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, return 0; } +const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = { + .clock_read = mv88e6165_ptp_clock_read, + .global_enable = mv88e6165_global_enable, + .global_disable = mv88e6165_global_disable, + .arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS, + .arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS, + .dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS, + .rx_filters = (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), +}; + const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { .clock_read = mv88e6352_ptp_clock_read, .ptp_enable = mv88e6352_ptp_enable, @@ -333,22 +349,6 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), }; -const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = { - .clock_read = mv88e6165_ptp_clock_read, - .global_enable = mv88e6165_global_enable, - .global_disable = mv88e6165_global_disable, - .arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS, - .arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS, - .dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS, - .rx_filters = (1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), -}; - static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc) { struct mv88e6xxx_chip *chip = cc_to_chip(cc); diff --git a/drivers/net/dsa/mv88e6xxx/ptp.h b/drivers/net/dsa/mv88e6xxx/ptp.h index 0a1f8de8f062..58cbd21d58f6 100644 --- a/drivers/net/dsa/mv88e6xxx/ptp.h +++ b/drivers/net/dsa/mv88e6xxx/ptp.h @@ -148,8 +148,8 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip); #define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip, \ ptp_clock_info) -extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops; extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops; +extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops; #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */ @@ -167,8 +167,8 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip) { } -static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {}; static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {}; +static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {}; #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */ -- GitLab From 7150961487c5b4521ef5b6557373546e370709d2 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Wed, 31 Jul 2019 10:23:51 +0200 Subject: [PATCH 1745/7155] net: dsa: mv88e6xxx: add PTP support for MV88E6250 family This adds PTP support for the MV88E6250 family. Signed-off-by: Hubert Feurstein Acked-by: Richard Cochran Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 4 ++ drivers/net/dsa/mv88e6xxx/chip.h | 4 ++ drivers/net/dsa/mv88e6xxx/ptp.c | 79 +++++++++++++++++++++++++++----- drivers/net/dsa/mv88e6xxx/ptp.h | 2 + 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ae0134d85436..467e61ced82c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3538,6 +3538,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { .reset = mv88e6250_g1_reset, .vtu_getnext = mv88e6250_g1_vtu_getnext, .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6250_ptp_ops, .phylink_validate = mv88e6065_phylink_validate, }; @@ -4334,6 +4336,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .atu_move_port_mask = 0xf, .dual_chip = true, .tag_protocol = DSA_TAG_PROTO_DSA, + .ptp_support = true, .ops = &mv88e6250_ops, }, @@ -4379,6 +4382,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .atu_move_port_mask = 0xf, .dual_chip = true, .tag_protocol = DSA_TAG_PROTO_DSA, + .ptp_support = true, .ops = &mv88e6250_ops, }, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index e7b88e9643b9..8c6d3c906197 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -539,6 +539,10 @@ struct mv88e6xxx_ptp_ops { int arr1_sts_reg; int dep_sts_reg; u32 rx_filters; + u32 cc_shift; + u32 cc_mult; + u32 cc_mult_num; + u32 cc_mult_dem; }; #define STATS_TYPE_PORT BIT(0) diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c index a1ff182c8737..073cbd0bb91b 100644 --- a/drivers/net/dsa/mv88e6xxx/ptp.c +++ b/drivers/net/dsa/mv88e6xxx/ptp.c @@ -15,11 +15,31 @@ #include "hwtstamp.h" #include "ptp.h" -/* Raw timestamps are in units of 8-ns clock periods. */ -#define CC_SHIFT 28 -#define CC_MULT (8 << CC_SHIFT) -#define CC_MULT_NUM (1 << 9) -#define CC_MULT_DEM 15625ULL +#define MV88E6XXX_MAX_ADJ_PPB 1000000 + +/* Family MV88E6250: + * Raw timestamps are in units of 10-ns clock periods. + * + * clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16) + * simplifies to + * clkadj = scaled_ppm * 2^7 / 5^5 + */ +#define MV88E6250_CC_SHIFT 28 +#define MV88E6250_CC_MULT (10 << MV88E6250_CC_SHIFT) +#define MV88E6250_CC_MULT_NUM (1 << 7) +#define MV88E6250_CC_MULT_DEM 3125ULL + +/* Other families: + * Raw timestamps are in units of 8-ns clock periods. + * + * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16) + * simplifies to + * clkadj = scaled_ppm * 2^9 / 5^6 + */ +#define MV88E6XXX_CC_SHIFT 28 +#define MV88E6XXX_CC_MULT (8 << MV88E6XXX_CC_SHIFT) +#define MV88E6XXX_CC_MULT_NUM (1 << 9) +#define MV88E6XXX_CC_MULT_DEM 15625ULL #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100) @@ -179,6 +199,7 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly) static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) { struct mv88e6xxx_chip *chip = ptp_to_chip(ptp); + const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops; int neg_adj = 0; u32 diff, mult; u64 adj; @@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) neg_adj = 1; scaled_ppm = -scaled_ppm; } - mult = CC_MULT; - adj = CC_MULT_NUM; + + mult = ptp_ops->cc_mult; + adj = ptp_ops->cc_mult_num; adj *= scaled_ppm; - diff = div_u64(adj, CC_MULT_DEM); + diff = div_u64(adj, ptp_ops->cc_mult_dem); mv88e6xxx_reg_lock(chip); @@ -324,6 +346,37 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = { (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), + .cc_shift = MV88E6XXX_CC_SHIFT, + .cc_mult = MV88E6XXX_CC_MULT, + .cc_mult_num = MV88E6XXX_CC_MULT_NUM, + .cc_mult_dem = MV88E6XXX_CC_MULT_DEM, +}; + +const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = { + .clock_read = mv88e6352_ptp_clock_read, + .ptp_enable = mv88e6352_ptp_enable, + .ptp_verify = mv88e6352_ptp_verify, + .event_work = mv88e6352_tai_event_work, + .port_enable = mv88e6352_hwtstamp_port_enable, + .port_disable = mv88e6352_hwtstamp_port_disable, + .n_ext_ts = 1, + .arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS, + .arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS, + .dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS, + .rx_filters = (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), + .cc_shift = MV88E6250_CC_SHIFT, + .cc_mult = MV88E6250_CC_MULT, + .cc_mult_num = MV88E6250_CC_MULT_NUM, + .cc_mult_dem = MV88E6250_CC_MULT_DEM, }; const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { @@ -347,6 +400,10 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), + .cc_shift = MV88E6XXX_CC_SHIFT, + .cc_mult = MV88E6XXX_CC_MULT, + .cc_mult_num = MV88E6XXX_CC_MULT_NUM, + .cc_mult_dem = MV88E6XXX_CC_MULT_DEM, }; static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc) @@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc)); chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read; chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32); - chip->tstamp_cc.mult = CC_MULT; - chip->tstamp_cc.shift = CC_SHIFT; + chip->tstamp_cc.mult = ptp_ops->cc_mult; + chip->tstamp_cc.shift = ptp_ops->cc_shift; timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, ktime_to_ns(ktime_get_real())); @@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) chip->ptp_clock_info.owner = THIS_MODULE; snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name), "%s", dev_name(chip->dev)); - chip->ptp_clock_info.max_adj = 1000000; chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts; chip->ptp_clock_info.n_per_out = 0; @@ -413,6 +469,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) } chip->ptp_clock_info.pin_config = chip->pin_config; + chip->ptp_clock_info.max_adj = MV88E6XXX_MAX_ADJ_PPB; chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine; chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime; chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime; diff --git a/drivers/net/dsa/mv88e6xxx/ptp.h b/drivers/net/dsa/mv88e6xxx/ptp.h index 58cbd21d58f6..269d5d16a466 100644 --- a/drivers/net/dsa/mv88e6xxx/ptp.h +++ b/drivers/net/dsa/mv88e6xxx/ptp.h @@ -149,6 +149,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip); ptp_clock_info) extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops; +extern const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops; extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops; #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */ @@ -168,6 +169,7 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip) } static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {}; +static const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {}; static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {}; #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */ -- GitLab From 2152e7a2d9a8c29e8850adabd2175fa042ad5bb8 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 1 Aug 2019 14:52:49 +0300 Subject: [PATCH 1746/7155] enetc: Clean up local mdio bus allocation What's needed is basically a pointer to the mdio registers. This is one way to store it inside bus->priv allocated space, without upsetting sparse. Reworked accessors to avoid __iomem casting. Used devm_* variant to further clean up the init error / remove paths. Fixes following sparse warning: warning: incorrect type in assignment (different address spaces) expected void *priv got struct enetc_mdio_regs [noderef] *[assigned] regs Fixes: ebfcb23d62ab ("enetc: Add ENETC PF level external MDIO support") Signed-off-by: Claudiu Manoil Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- .../net/ethernet/freescale/enetc/enetc_mdio.c | 94 +++++++++---------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c index 77b9cd10ba2b..05094601ece8 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c @@ -8,16 +8,22 @@ #include "enetc_pf.h" -struct enetc_mdio_regs { - u32 mdio_cfg; /* MDIO configuration and status */ - u32 mdio_ctl; /* MDIO control */ - u32 mdio_data; /* MDIO data */ - u32 mdio_addr; /* MDIO address */ +#define ENETC_MDIO_REG_OFFSET 0x1c00 +#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */ +#define ENETC_MDIO_CTL 0x4 /* MDIO control */ +#define ENETC_MDIO_DATA 0x8 /* MDIO data */ +#define ENETC_MDIO_ADDR 0xc /* MDIO address */ + +#define enetc_mdio_rd(hw, off) \ + enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET) +#define enetc_mdio_wr(hw, off, val) \ + enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val) +#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off) + +struct enetc_mdio_priv { + struct enetc_hw *hw; }; -#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv) - -#define ENETC_MDIO_REG_OFFSET 0x1c00 #define ENETC_MDC_DIV 258 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8) @@ -33,18 +39,19 @@ struct enetc_mdio_regs { #define MDIO_DATA(x) ((x) & 0xffff) #define TIMEOUT 1000 -static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs) +static int enetc_mdio_wait_complete(struct enetc_hw *hw) { u32 val; - return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val, + return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val, !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT); } static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) { - struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + struct enetc_mdio_priv *mdio_priv = bus->priv; + struct enetc_hw *hw = mdio_priv->hw; u32 mdio_ctl, mdio_cfg; u16 dev_addr; int ret; @@ -59,29 +66,29 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, mdio_cfg &= ~MDIO_CFG_ENC45; } - enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* set port and dev addr */ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); - enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl); /* set the register address */ if (regnum & MII_ADDR_C45) { - enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; } /* write the value */ - enetc_wr_reg(®s->mdio_data, MDIO_DATA(value)); + enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value)); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; @@ -90,7 +97,8 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) { - struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + struct enetc_mdio_priv *mdio_priv = bus->priv; + struct enetc_hw *hw = mdio_priv->hw; u32 mdio_ctl, mdio_cfg; u16 dev_addr, value; int ret; @@ -104,41 +112,41 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) mdio_cfg &= ~MDIO_CFG_ENC45; } - enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* set port and device addr */ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); - enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl); /* set the register address */ if (regnum & MII_ADDR_C45) { - enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; } /* initiate the read */ - enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ); + enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ); - ret = enetc_mdio_wait_complete(regs); + ret = enetc_mdio_wait_complete(hw); if (ret) return ret; /* return all Fs if nothing was there */ - if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) { + if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) { dev_dbg(&bus->dev, "Error while reading PHY%d reg at %d.%hhu\n", phy_id, dev_addr, regnum); return 0xffff; } - value = enetc_rd_reg(®s->mdio_data) & 0xffff; + value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff; return value; } @@ -146,12 +154,12 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) int enetc_mdio_probe(struct enetc_pf *pf) { struct device *dev = &pf->si->pdev->dev; - struct enetc_mdio_regs __iomem *regs; + struct enetc_mdio_priv *mdio_priv; struct device_node *np; struct mii_bus *bus; - int ret; + int err; - bus = mdiobus_alloc_size(sizeof(regs)); + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); if (!bus) return -ENOMEM; @@ -159,41 +167,31 @@ int enetc_mdio_probe(struct enetc_pf *pf) bus->read = enetc_mdio_read; bus->write = enetc_mdio_write; bus->parent = dev; + mdio_priv = bus->priv; + mdio_priv->hw = &pf->si->hw; snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); - /* store the enetc mdio base address for this bus */ - regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET; - bus->priv = regs; - np = of_get_child_by_name(dev->of_node, "mdio"); if (!np) { dev_err(dev, "MDIO node missing\n"); - ret = -EINVAL; - goto err_registration; + return -EINVAL; } - ret = of_mdiobus_register(bus, np); - if (ret) { + err = of_mdiobus_register(bus, np); + if (err) { of_node_put(np); dev_err(dev, "cannot register MDIO bus\n"); - goto err_registration; + return err; } of_node_put(np); pf->mdio = bus; return 0; - -err_registration: - mdiobus_free(bus); - - return ret; } void enetc_mdio_remove(struct enetc_pf *pf) { - if (pf->mdio) { + if (pf->mdio) mdiobus_unregister(pf->mdio); - mdiobus_free(pf->mdio); - } } -- GitLab From 0c010a9deb33179169fa867d3c76833ce80165b7 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 1 Aug 2019 14:52:50 +0300 Subject: [PATCH 1747/7155] enetc: Clean up makefile Clean up overcomplicated makefile to make it more maintainable. Basically, there's a set of common objects shared between the PF and VF driver modules. This can be implemented in a simpler way, without conditionals, less repetition, allowing also for easier updates in the future. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Makefile | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 7139e414dccf..164453a5dc1d 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -1,19 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 + +common-objs := enetc.o enetc_cbdr.o enetc_ethtool.o + obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o -fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o \ - enetc_mdio.o +fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs) fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o -fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y) obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o - -ifeq ($(CONFIG_FSL_ENETC)$(CONFIG_FSL_ENETC_VF), yy) -fsl-enetc-vf-objs := enetc_vf.o -else -fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \ - enetc_ethtool.o -fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y) -endif +fsl-enetc-vf-y := enetc_vf.o $(common-objs) obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o -fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o +fsl-enetc-ptp-y := enetc_ptp.o -- GitLab From 231ece36f50df5d0d648011c58d4255d112a8bbf Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 1 Aug 2019 14:52:51 +0300 Subject: [PATCH 1748/7155] enetc: Add mdio bus driver for the PCIe MDIO endpoint ENETC ports can manage the MDIO bus via local register interface. However there's also a centralized way to manage the MDIO bus, via the MDIO PCIe endpoint device integrated by the same root complex that also integrates the ENETC ports (eth controllers). Depending on board design and use case, centralized access to MDIO may be better than using local ENETC port registers. For instance, on the LS1028A QDS board where MDIO muxing is required. Also, the LS1028A on-chip switch doesn't have a local MDIO register interface. The current patch registers the above PCIe endpoint as a separate MDIO bus and provides a driver for it by re-using the code used for local MDIO access. It also allows the ENETC port PHYs to be managed by this driver if the local "mdio" node is missing from the ENETC port node. Signed-off-by: Claudiu Manoil Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Kconfig | 9 ++ drivers/net/ethernet/freescale/enetc/Makefile | 3 + .../net/ethernet/freescale/enetc/enetc_mdio.c | 11 +- .../net/ethernet/freescale/enetc/enetc_mdio.h | 12 +++ .../ethernet/freescale/enetc/enetc_pci_mdio.c | 101 ++++++++++++++++++ .../net/ethernet/freescale/enetc/enetc_pf.c | 5 +- 6 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_mdio.h create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index ed0d010c7cf2..9c530f75134f 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -18,6 +18,15 @@ config FSL_ENETC_VF If compiled as module (M), the module name is fsl-enetc-vf. +config FSL_ENETC_MDIO + tristate "ENETC MDIO driver" + depends on PCI && (ARCH_LAYERSCAPE || COMPILE_TEST) + help + This driver supports NXP ENETC Central MDIO controller as a PCIe + physical function (PF) device. + + If compiled as module (M), the module name is fsl-enetc-mdio. + config FSL_ENETC_PTP_CLOCK tristate "ENETC PTP clock driver" depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF) diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 164453a5dc1d..d200c27c3bf6 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -9,5 +9,8 @@ fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o fsl-enetc-vf-y := enetc_vf.o $(common-objs) +obj-$(CONFIG_FSL_ENETC_MDIO) += fsl-enetc-mdio.o +fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o + obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o fsl-enetc-ptp-y := enetc_ptp.o diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c index 05094601ece8..149883c8f0b8 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c @@ -6,7 +6,7 @@ #include #include -#include "enetc_pf.h" +#include "enetc_mdio.h" #define ENETC_MDIO_REG_OFFSET 0x1c00 #define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */ @@ -20,10 +20,6 @@ enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val) #define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off) -struct enetc_mdio_priv { - struct enetc_hw *hw; -}; - #define ENETC_MDC_DIV 258 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8) @@ -47,8 +43,7 @@ static int enetc_mdio_wait_complete(struct enetc_hw *hw) !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT); } -static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, - u16 value) +int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) { struct enetc_mdio_priv *mdio_priv = bus->priv; struct enetc_hw *hw = mdio_priv->hw; @@ -95,7 +90,7 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, return 0; } -static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) +int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) { struct enetc_mdio_priv *mdio_priv = bus->priv; struct enetc_hw *hw = mdio_priv->hw; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.h b/drivers/net/ethernet/freescale/enetc/enetc_mdio.h new file mode 100644 index 000000000000..60c9a3889824 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2019 NXP */ + +#include +#include "enetc_pf.h" + +struct enetc_mdio_priv { + struct enetc_hw *hw; +}; + +int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value); +int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c new file mode 100644 index 000000000000..fbd41ce01f06 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2019 NXP */ +#include +#include "enetc_mdio.h" + +#define ENETC_MDIO_DEV_ID 0xee01 +#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO" +#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus" +#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver" + +static int enetc_pci_mdio_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct enetc_mdio_priv *mdio_priv; + struct device *dev = &pdev->dev; + struct enetc_hw *hw; + struct mii_bus *bus; + int err; + + hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); + if (!hw) + return -ENOMEM; + + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); + if (!bus) + return -ENOMEM; + + bus->name = ENETC_MDIO_BUS_NAME; + bus->read = enetc_mdio_read; + bus->write = enetc_mdio_write; + bus->parent = dev; + mdio_priv = bus->priv; + mdio_priv->hw = hw; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + + pcie_flr(pdev); + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(dev, "device enable failed\n"); + return err; + } + + err = pci_request_region(pdev, 0, KBUILD_MODNAME); + if (err) { + dev_err(dev, "pci_request_region failed\n"); + goto err_pci_mem_reg; + } + + hw->port = pci_iomap(pdev, 0, 0); + if (!hw->port) { + err = -ENXIO; + dev_err(dev, "iomap failed\n"); + goto err_ioremap; + } + + err = of_mdiobus_register(bus, dev->of_node); + if (err) + goto err_mdiobus_reg; + + pci_set_drvdata(pdev, bus); + + return 0; + +err_mdiobus_reg: + iounmap(mdio_priv->hw->port); +err_ioremap: + pci_release_mem_regions(pdev); +err_pci_mem_reg: + pci_disable_device(pdev); + + return err; +} + +static void enetc_pci_mdio_remove(struct pci_dev *pdev) +{ + struct mii_bus *bus = pci_get_drvdata(pdev); + struct enetc_mdio_priv *mdio_priv; + + mdiobus_unregister(bus); + mdio_priv = bus->priv; + iounmap(mdio_priv->hw->port); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id enetc_pci_mdio_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table); + +static struct pci_driver enetc_pci_mdio_driver = { + .name = KBUILD_MODNAME, + .id_table = enetc_pci_mdio_id_table, + .probe = enetc_pci_mdio_probe, + .remove = enetc_pci_mdio_remove, +}; +module_pci_driver(enetc_pci_mdio_driver); + +MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 258b3cb38a6f..7d6513ff8507 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) { struct enetc_pf *pf = enetc_si_priv(priv->si); struct device_node *np = priv->dev->of_node; + struct device_node *mdio_np; int err; if (!np) { @@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) priv->phy_node = of_node_get(np); } - if (!of_phy_is_fixed_link(np)) { + mdio_np = of_get_child_by_name(np, "mdio"); + if (mdio_np) { + of_node_put(mdio_np); err = enetc_mdio_probe(pf); if (err) { of_node_put(priv->phy_node); -- GitLab From 288a91d5cd0c947cfd0cf8430f588974ea697c5e Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 1 Aug 2019 14:52:52 +0300 Subject: [PATCH 1749/7155] dt-bindings: net: fsl: enetc: Add bindings for the central MDIO PCIe endpoint The on-chip PCIe root complex that integrates the ENETC ethernet controllers also integrates a PCIe endpoint for the MDIO controller providing for centralized control of the ENETC mdio bus. Add bindings for this "central" MDIO Integrated PCIe Endpoint. Signed-off-by: Claudiu Manoil Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- .../devicetree/bindings/net/fsl-enetc.txt | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/net/fsl-enetc.txt b/Documentation/devicetree/bindings/net/fsl-enetc.txt index 25fc687419db..b7034ccbc1bd 100644 --- a/Documentation/devicetree/bindings/net/fsl-enetc.txt +++ b/Documentation/devicetree/bindings/net/fsl-enetc.txt @@ -11,7 +11,9 @@ Required properties: to parent node bindings. - compatible : Should be "fsl,enetc". -1) The ENETC external port is connected to a MDIO configurable phy: +1. The ENETC external port is connected to a MDIO configurable phy + +1.1. Using the local ENETC Port MDIO interface In this case, the ENETC node should include a "mdio" sub-node that in turn should contain the "ethernet-phy" node describing the @@ -47,8 +49,42 @@ Example: }; }; -2) The ENETC port is an internal port or has a fixed-link external -connection: +1.2. Using the central MDIO PCIe endpoint device + +In this case, the mdio node should be defined as another PCIe +endpoint node, at the same level with the ENETC port nodes. + +Required properties: + +- reg : Specifies PCIe Device Number and Function + Number of the ENETC endpoint device, according + to parent node bindings. +- compatible : Should be "fsl,enetc-mdio". + +The remaining required mdio bus properties are standard, their bindings +already defined in Documentation/devicetree/bindings/net/mdio.txt. + +Example: + + ethernet@0,0 { + compatible = "fsl,enetc"; + reg = <0x000000 0 0 0 0>; + phy-handle = <&sgmii_phy0>; + phy-connection-type = "sgmii"; + }; + + mdio@0,3 { + compatible = "fsl,enetc-mdio"; + reg = <0x000300 0 0 0 0>; + #address-cells = <1>; + #size-cells = <0>; + sgmii_phy0: ethernet-phy@2 { + reg = <0x2>; + }; + }; + +2. The ENETC port is an internal port or has a fixed-link external +connection In this case, the ENETC port node defines a fixed link connection, as specified by Documentation/devicetree/bindings/net/fixed-link.txt. -- GitLab From 8488d8e90c03983912318deaae41546f950667d6 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 1 Aug 2019 14:52:53 +0300 Subject: [PATCH 1750/7155] arm64: dts: fsl: ls1028a: Enable eth port1 on the ls1028a QDS board LS1028a has one Ethernet management interface. On the QDS board, the MDIO signals are multiplexed to either on-board AR8035 PHY device or to 4 PCIe slots allowing for SGMII cards. To enable the Ethernet ENETC Port 1, which can only be connected to a RGMII PHY, the multiplexer needs to be configured to route the MDIO to the AR8035 PHY. The MDIO/MDC routing is controlled by bits 7:4 of FPGA board config register 0x54, and value 0 selects the on-board RGMII PHY. The FPGA board config registers are accessible on the i2c bus, at address 0x66. The PF3 MDIO PCIe integrated endpoint device allows for centralized access to the MDIO bus. Add the corresponding devicetree node and set it to be the MDIO bus parent. Signed-off-by: Alex Marginean Signed-off-by: Claudiu Manoil Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- .../boot/dts/freescale/fsl-ls1028a-qds.dts | 40 +++++++++++++++++++ .../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 6 +++ 2 files changed, 46 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts index de6ef39f3118..663c4b728c07 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts @@ -85,6 +85,26 @@ system-clock-frequency = <25000000>; }; }; + + mdio-mux { + compatible = "mdio-mux-multiplexer"; + mux-controls = <&mux 0>; + mdio-parent-bus = <&enetc_mdio_pf3>; + #address-cells=<1>; + #size-cells = <0>; + + /* on-board RGMII PHY */ + mdio@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + qds_phy1: ethernet-phy@5 { + /* Atheros 8035 */ + reg = <5>; + }; + }; + }; }; &duart0 { @@ -164,6 +184,26 @@ }; }; }; + + fpga@66 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c", + "simple-mfd"; + reg = <0x66>; + + mux: mux-controller { + compatible = "reg-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */ + }; + }; + +}; + +&enetc_port1 { + phy-handle = <&qds_phy1>; + phy-connection-type = "rgmii-id"; }; &sai1 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 7975519b4f56..de71153fda00 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -536,6 +536,12 @@ compatible = "fsl,enetc"; reg = <0x000100 0 0 0 0>; }; + enetc_mdio_pf3: mdio@0,3 { + compatible = "fsl,enetc-mdio"; + reg = <0x000300 0 0 0 0>; + #address-cells = <1>; + #size-cells = <0>; + }; ethernet@0,4 { compatible = "fsl,enetc-ptp"; reg = <0x000400 0 0 0 0>; -- GitLab From d562aca37a543cc3de85be6a6946771a27d50c6a Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 23 Jul 2019 22:37:51 +0200 Subject: [PATCH 1751/7155] parisc/ftrace: Add ARCH_SUPPORTS_FTRACE_OPS support Pass ftrace_ops to ftrace functions to ftrace_trace_function(). Signed-off-by: Sven Schnelle Signed-off-by: Helge Deller --- arch/parisc/include/asm/ftrace.h | 1 + arch/parisc/kernel/ftrace.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h index 958c0aa5dbb2..a7cf0d05ccf4 100644 --- a/arch/parisc/include/asm/ftrace.h +++ b/arch/parisc/include/asm/ftrace.h @@ -8,6 +8,7 @@ extern void mcount(void); #define MCOUNT_ADDR ((unsigned long)mcount) #define MCOUNT_INSN_SIZE 4 #define CC_USING_NOP_MCOUNT +#define ARCH_SUPPORTS_FTRACE_OPS 1 extern unsigned long sys_call_table[]; extern unsigned long return_address(unsigned int); diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c index b6fb30f2e4bf..23ce416787ac 100644 --- a/arch/parisc/kernel/ftrace.c +++ b/arch/parisc/kernel/ftrace.c @@ -53,8 +53,12 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent, #ifndef CONFIG_DYNAMIC_FTRACE extern ftrace_func_t ftrace_trace_function; #endif - if (ftrace_trace_function != ftrace_stub) - ftrace_trace_function(self_addr, parent, NULL, NULL); + extern struct ftrace_ops *function_trace_op; + + if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED && + ftrace_trace_function != ftrace_stub) + ftrace_trace_function(self_addr, parent, + function_trace_op, NULL); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || -- GitLab From 52a22e6c27be9089fdd9c4e1857939f0dec8f57c Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 23 Jul 2019 22:37:52 +0200 Subject: [PATCH 1752/7155] parisc/ftrace: Add KPROBES_ON_FTRACE Allow KPROBES to use the ftrace infrastructure on PA-RISC. Signed-off-by: Sven Schnelle Signed-off-by: Helge Deller --- .../debug/kprobes-on-ftrace/arch-support.txt | 2 +- arch/parisc/Kconfig | 2 + arch/parisc/kernel/entry.S | 99 +++++++++++++++++++ arch/parisc/kernel/ftrace.c | 58 ++++++++++- 4 files changed, 157 insertions(+), 4 deletions(-) diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt index 68f266944d5f..4fae0464ddff 100644 --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt @@ -21,7 +21,7 @@ | nds32: | TODO | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | TODO | | s390: | TODO | diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 6d732e451071..ee59171edffe 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -61,6 +61,8 @@ config PARISC select HAVE_KRETPROBES select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1) select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE + select HAVE_KPROBES_ON_FTRACE + select HAVE_DYNAMIC_FTRACE_WITH_REGS help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index d9d3387f7c47..1d1d748c227f 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1996,6 +1996,7 @@ _mcount: * calling mcount(), and 2 instructions for ftrace_stub(). That way we * have all on one L1 cacheline. */ + ldi 0, %arg3 b ftrace_function_trampoline copy %r3, %arg2 /* caller original %sp */ ftrace_stub: @@ -2048,6 +2049,7 @@ ftrace_caller: LDREG 0(%r3), %r25 copy %rp, %r26 ldo -8(%r25), %r25 + ldi 0, %r23 /* no pt_regs */ b,l ftrace_function_trampoline, %rp copy %r3, %r24 @@ -2075,6 +2077,103 @@ ftrace_caller: ENDPROC_CFI(ftrace_caller) +#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS +ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN, + CALLS,SAVE_RP,SAVE_SP) +ftrace_regs_caller: + .global ftrace_regs_caller + + ldo -FTRACE_FRAME_SIZE(%sp), %r1 + STREG %rp, -RP_OFFSET(%r1) + + copy %sp, %r1 + ldo PT_SZ_ALGN(%sp), %sp + + STREG %rp, PT_GR2(%r1) + STREG %r3, PT_GR3(%r1) + STREG %r4, PT_GR4(%r1) + STREG %r5, PT_GR5(%r1) + STREG %r6, PT_GR6(%r1) + STREG %r7, PT_GR7(%r1) + STREG %r8, PT_GR8(%r1) + STREG %r9, PT_GR9(%r1) + STREG %r10, PT_GR10(%r1) + STREG %r11, PT_GR11(%r1) + STREG %r12, PT_GR12(%r1) + STREG %r13, PT_GR13(%r1) + STREG %r14, PT_GR14(%r1) + STREG %r15, PT_GR15(%r1) + STREG %r16, PT_GR16(%r1) + STREG %r17, PT_GR17(%r1) + STREG %r18, PT_GR18(%r1) + STREG %r19, PT_GR19(%r1) + STREG %r20, PT_GR20(%r1) + STREG %r21, PT_GR21(%r1) + STREG %r22, PT_GR22(%r1) + STREG %r23, PT_GR23(%r1) + STREG %r24, PT_GR24(%r1) + STREG %r25, PT_GR25(%r1) + STREG %r26, PT_GR26(%r1) + STREG %r27, PT_GR27(%r1) + STREG %r28, PT_GR28(%r1) + STREG %r29, PT_GR29(%r1) + STREG %r30, PT_GR30(%r1) + STREG %r31, PT_GR31(%r1) + mfctl %cr11, %r26 + STREG %r26, PT_SAR(%r1) + + copy %rp, %r26 + LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25 + ldo -8(%r25), %r25 + copy %r3, %arg2 + b,l ftrace_function_trampoline, %rp + copy %r1, %arg3 /* struct pt_regs */ + + ldo -PT_SZ_ALGN(%sp), %r1 + + LDREG PT_SAR(%r1), %rp + mtctl %rp, %cr11 + + LDREG PT_GR2(%r1), %rp + LDREG PT_GR3(%r1), %r3 + LDREG PT_GR4(%r1), %r4 + LDREG PT_GR5(%r1), %r5 + LDREG PT_GR6(%r1), %r6 + LDREG PT_GR7(%r1), %r7 + LDREG PT_GR8(%r1), %r8 + LDREG PT_GR9(%r1), %r9 + LDREG PT_GR10(%r1),%r10 + LDREG PT_GR11(%r1),%r11 + LDREG PT_GR12(%r1),%r12 + LDREG PT_GR13(%r1),%r13 + LDREG PT_GR14(%r1),%r14 + LDREG PT_GR15(%r1),%r15 + LDREG PT_GR16(%r1),%r16 + LDREG PT_GR17(%r1),%r17 + LDREG PT_GR18(%r1),%r18 + LDREG PT_GR19(%r1),%r19 + LDREG PT_GR20(%r1),%r20 + LDREG PT_GR21(%r1),%r21 + LDREG PT_GR22(%r1),%r22 + LDREG PT_GR23(%r1),%r23 + LDREG PT_GR24(%r1),%r24 + LDREG PT_GR25(%r1),%r25 + LDREG PT_GR26(%r1),%r26 + LDREG PT_GR27(%r1),%r27 + LDREG PT_GR28(%r1),%r28 + LDREG PT_GR29(%r1),%r29 + LDREG PT_GR30(%r1),%r30 + LDREG PT_GR31(%r1),%r31 + + ldo -PT_SZ_ALGN(%sp), %sp + LDREGM -FTRACE_FRAME_SIZE(%sp), %r1 + /* Adjust return point to jump back to beginning of traced function */ + ldo -4(%r1), %r1 + bv,n (%r1) + +ENDPROC_CFI(ftrace_regs_caller) + +#endif #endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c index 23ce416787ac..b836fc61a24f 100644 --- a/arch/parisc/kernel/ftrace.c +++ b/arch/parisc/kernel/ftrace.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -48,7 +50,8 @@ static void __hot prepare_ftrace_return(unsigned long *parent, void notrace __hot ftrace_function_trampoline(unsigned long parent, unsigned long self_addr, - unsigned long org_sp_gr3) + unsigned long org_sp_gr3, + struct pt_regs *regs) { #ifndef CONFIG_DYNAMIC_FTRACE extern ftrace_func_t ftrace_trace_function; @@ -58,11 +61,11 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent, if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED && ftrace_trace_function != ftrace_stub) ftrace_trace_function(self_addr, parent, - function_trace_op, NULL); + function_trace_op, regs); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || - ftrace_graph_entry != ftrace_graph_entry_stub) { + ftrace_graph_entry != ftrace_graph_entry_stub) { unsigned long *parent_rp; /* calculate pointer to %rp in stack */ @@ -100,6 +103,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return 0; } +int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, + unsigned long addr) +{ + return 0; +} + unsigned long ftrace_call_adjust(unsigned long addr) { return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4; @@ -191,3 +200,46 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, return 0; } #endif + +#ifdef CONFIG_KPROBES_ON_FTRACE +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *ops, struct pt_regs *regs) +{ + struct kprobe_ctlblk *kcb; + struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip); + + if (unlikely(!p) || kprobe_disabled(p)) + return; + + if (kprobe_running()) { + kprobes_inc_nmissed_count(p); + return; + } + + __this_cpu_write(current_kprobe, p); + + kcb = get_kprobe_ctlblk(); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + + regs->iaoq[0] = ip; + regs->iaoq[1] = ip + 4; + + if (!p->pre_handler || !p->pre_handler(p, regs)) { + regs->iaoq[0] = ip + 4; + regs->iaoq[1] = ip + 8; + + if (unlikely(p->post_handler)) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + p->post_handler(p, regs, 0); + } + } + __this_cpu_write(current_kprobe, NULL); +} +NOKPROBE_SYMBOL(kprobe_ftrace_handler); + +int arch_prepare_kprobe_ftrace(struct kprobe *p) +{ + p->ainsn.insn = NULL; + return 0; +} +#endif -- GitLab From c8bbbc67cb314981e7ba22af0bd703225f0add80 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 23 Jul 2019 22:37:53 +0200 Subject: [PATCH 1753/7155] parisc: Update feature list Add jump labels to the list of supported features. Signed-off-by: Sven Schnelle Signed-off-by: Helge Deller --- Documentation/features/core/jump-labels/arch-support.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt index 7fc2e243dee9..cae7be2f7725 100644 --- a/Documentation/features/core/jump-labels/arch-support.txt +++ b/Documentation/features/core/jump-labels/arch-support.txt @@ -21,7 +21,7 @@ | nds32: | TODO | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | TODO | | s390: | ok | -- GitLab From ec4d396b635070e0caf5888d58cb9eedc8dd73d9 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Thu, 1 Aug 2019 22:08:42 +0200 Subject: [PATCH 1754/7155] parisc: trigger die notifier chain in parisc_terminate() This will trigger kgdb/kdb when they are enabled. Signed-off-by: Sven Schnelle Signed-off-by: Helge Deller --- arch/parisc/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 58dcf445e32f..82fc01189488 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -414,6 +415,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o { static DEFINE_SPINLOCK(terminate_lock); + (void)notify_die(DIE_OOPS, msg, regs, 0, code, SIGTRAP); bust_spinlocks(1); set_eiem(0); -- GitLab From 83af58f8068ea3f7b3c537c37a30887bfa585069 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 6 Feb 2019 23:21:10 +0100 Subject: [PATCH 1755/7155] parisc: Add assembly implementations for memset, strlen, strcpy, strncpy and strcat Add performance-optimized versions of some string functions. Signed-off-by: Helge Deller Tested-by: Sven Schnelle --- arch/parisc/include/asm/string.h | 15 ++++ arch/parisc/kernel/parisc_ksyms.c | 4 + arch/parisc/lib/Makefile | 4 +- arch/parisc/lib/memset.c | 91 -------------------- arch/parisc/lib/string.S | 136 ++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 93 deletions(-) delete mode 100644 arch/parisc/lib/memset.c create mode 100644 arch/parisc/lib/string.S diff --git a/arch/parisc/include/asm/string.h b/arch/parisc/include/asm/string.h index f6e1132f4e35..4a0c9dbd62fd 100644 --- a/arch/parisc/include/asm/string.h +++ b/arch/parisc/include/asm/string.h @@ -8,4 +8,19 @@ extern void * memset(void *, int, size_t); #define __HAVE_ARCH_MEMCPY void * memcpy(void * dest,const void *src,size_t count); +#define __HAVE_ARCH_STRLEN +extern size_t strlen(const char *s); + +#define __HAVE_ARCH_STRCPY +extern char *strcpy(char *dest, const char *src); + +#define __HAVE_ARCH_STRNCPY +extern char *strncpy(char *dest, const char *src, size_t count); + +#define __HAVE_ARCH_STRCAT +extern char *strcat(char *dest, const char *src); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, size_t); + #endif diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index e8a6a751dfd8..8ed409ecec93 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -17,6 +17,10 @@ #include EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); #include EXPORT_SYMBOL(__xchg8); diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 7b197667faf6..2d7a9974dbae 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile @@ -3,7 +3,7 @@ # Makefile for parisc-specific library files # -lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \ - ucmpdi2.o delay.o +lib-y := lusercopy.o bitops.o checksum.o io.o memcpy.o \ + ucmpdi2.o delay.o string.o obj-y := iomap.o diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c deleted file mode 100644 index 1d7929bd7642..000000000000 --- a/arch/parisc/lib/memset.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* Slight modifications for pa-risc linux - Paul Bame */ - -#include -#include - -#define OPSIZ (BITS_PER_LONG/8) -typedef unsigned long op_t; - -void * -memset (void *dstpp, int sc, size_t len) -{ - unsigned int c = sc; - long int dstp = (long int) dstpp; - - if (len >= 8) - { - size_t xlen; - op_t cccc; - - cccc = (unsigned char) c; - cccc |= cccc << 8; - cccc |= cccc << 16; - if (OPSIZ > 4) - /* Do the shift in two steps to avoid warning if long has 32 bits. */ - cccc |= (cccc << 16) << 16; - - /* There are at least some bytes to set. - No need to test for LEN == 0 in this alignment loop. */ - while (dstp % OPSIZ != 0) - { - ((unsigned char *) dstp)[0] = c; - dstp += 1; - len -= 1; - } - - /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ - xlen = len / (OPSIZ * 8); - while (xlen > 0) - { - ((op_t *) dstp)[0] = cccc; - ((op_t *) dstp)[1] = cccc; - ((op_t *) dstp)[2] = cccc; - ((op_t *) dstp)[3] = cccc; - ((op_t *) dstp)[4] = cccc; - ((op_t *) dstp)[5] = cccc; - ((op_t *) dstp)[6] = cccc; - ((op_t *) dstp)[7] = cccc; - dstp += 8 * OPSIZ; - xlen -= 1; - } - len %= OPSIZ * 8; - - /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ - xlen = len / OPSIZ; - while (xlen > 0) - { - ((op_t *) dstp)[0] = cccc; - dstp += OPSIZ; - xlen -= 1; - } - len %= OPSIZ; - } - - /* Write the last few bytes. */ - while (len > 0) - { - ((unsigned char *) dstp)[0] = c; - dstp += 1; - len -= 1; - } - - return dstpp; -} diff --git a/arch/parisc/lib/string.S b/arch/parisc/lib/string.S new file mode 100644 index 000000000000..4a64264427a6 --- /dev/null +++ b/arch/parisc/lib/string.S @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PA-RISC assembly string functions + * + * Copyright (C) 2019 Helge Deller + */ + +#include +#include + + .section .text.hot + .level PA_ASM_LEVEL + + t0 = r20 + t1 = r21 + t2 = r22 + +ENTRY_CFI(strlen, frame=0,no_calls) + or,COND(<>) arg0,r0,ret0 + b,l,n .Lstrlen_null_ptr,r0 + depwi 0,31,2,ret0 + cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned + ldw,ma 4(ret0),t0 + cmpib,tr 0,r0,.Lstrlen_loop + uxor,nbz r0,t0,r0 +.Lstrlen_not_aligned: + uaddcm arg0,ret0,t1 + shladd t1,3,r0,t1 + mtsar t1 + depwi -1,%sar,32,t0 + uxor,nbz r0,t0,r0 +.Lstrlen_loop: + b,l,n .Lstrlen_end_loop,r0 + ldw,ma 4(ret0),t0 + cmpib,tr 0,r0,.Lstrlen_loop + uxor,nbz r0,t0,r0 +.Lstrlen_end_loop: + extrw,u,<> t0,7,8,r0 + addib,tr,n -3,ret0,.Lstrlen_out + extrw,u,<> t0,15,8,r0 + addib,tr,n -2,ret0,.Lstrlen_out + extrw,u,<> t0,23,8,r0 + addi -1,ret0,ret0 +.Lstrlen_out: + bv r0(rp) + uaddcm ret0,arg0,ret0 +.Lstrlen_null_ptr: + bv,n r0(rp) +ENDPROC_CFI(strlen) + + +ENTRY_CFI(strcpy, frame=0,no_calls) + ldb 0(arg1),t0 + stb t0,0(arg0) + ldo 0(arg0),ret0 + ldo 1(arg1),t1 + cmpb,= r0,t0,2f + ldo 1(arg0),t2 +1: ldb 0(t1),arg1 + stb arg1,0(t2) + ldo 1(t1),t1 + cmpb,<> r0,arg1,1b + ldo 1(t2),t2 +2: bv,n r0(rp) +ENDPROC_CFI(strcpy) + + +ENTRY_CFI(strncpy, frame=0,no_calls) + ldb 0(arg1),t0 + stb t0,0(arg0) + ldo 1(arg1),t1 + ldo 0(arg0),ret0 + cmpb,= r0,t0,2f + ldo 1(arg0),arg1 +1: ldo -1(arg2),arg2 + cmpb,COND(=),n r0,arg2,2f + ldb 0(t1),arg0 + stb arg0,0(arg1) + ldo 1(t1),t1 + cmpb,<> r0,arg0,1b + ldo 1(arg1),arg1 +2: bv,n r0(rp) +ENDPROC_CFI(strncpy) + + +ENTRY_CFI(strcat, frame=0,no_calls) + ldb 0(arg0),t0 + cmpb,= t0,r0,2f + ldo 0(arg0),ret0 + ldo 1(arg0),arg0 +1: ldb 0(arg0),t1 + cmpb,<>,n r0,t1,1b + ldo 1(arg0),arg0 +2: ldb 0(arg1),t2 + stb t2,0(arg0) + ldo 1(arg0),arg0 + ldb 0(arg1),t0 + cmpb,<> r0,t0,2b + ldo 1(arg1),arg1 + bv,n r0(rp) +ENDPROC_CFI(strcat) + + +ENTRY_CFI(memset, frame=0,no_calls) + copy arg0,ret0 + cmpb,COND(=) r0,arg0,4f + copy arg0,t2 + cmpb,COND(=) r0,arg2,4f + ldo -1(arg2),arg3 + subi -1,arg3,t0 + subi 0,t0,t1 + cmpiclr,COND(>=) 0,t1,arg2 + ldo -1(t1),arg2 + extru arg2,31,2,arg0 +2: stb arg1,0(t2) + ldo 1(t2),t2 + addib,>= -1,arg0,2b + ldo -1(arg3),arg3 + cmpiclr,COND(<=) 4,arg2,r0 + b,l,n 4f,r0 +#ifdef CONFIG_64BIT + depd,* r0,63,2,arg2 +#else + depw r0,31,2,arg2 +#endif + ldo 1(t2),t2 +3: stb arg1,-1(t2) + stb arg1,0(t2) + stb arg1,1(t2) + stb arg1,2(t2) + addib,COND(>) -4,arg2,3b + ldo 4(t2),t2 +4: bv,n r0(rp) +ENDPROC_CFI(memset) + + .end -- GitLab From 8ca9d8ad30f39651d6ff9428aaeb1940489a7754 Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sat, 3 Aug 2019 12:14:12 +0530 Subject: [PATCH 1756/7155] staging: rtl8188eu: core: rtw_recv.c: Remove Unnecessary parentheses Remove Unnecessary parentheses around precvframe->list, pmlmeext->mlmext_info and precvpriv->free_recv_queue Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803064408.GA30111@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 9caf7041ad60..620da6c003d8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -145,8 +145,8 @@ int rtw_free_recvframe(struct recv_frame *precvframe, int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) { - list_del_init(&(precvframe->list)); - list_add_tail(&(precvframe->list), get_list_head(queue)); + list_del_init(&precvframe->list); + list_add_tail(&precvframe->list, get_list_head(queue)); return _SUCCESS; } @@ -219,7 +219,7 @@ static int recvframe_chkmic(struct adapter *adapter, struct security_priv *psecuritypriv = &adapter->securitypriv; struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); @@ -1500,7 +1500,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) struct rx_pkt_attrib *pattrib; struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue); + struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; nr_subframes = 0; pattrib = &prframe->attrib; -- GitLab From 7cbf0108247da2001a591583d2fc6433918b8a47 Mon Sep 17 00:00:00 2001 From: Thiago Bonotto Date: Fri, 2 Aug 2019 20:23:23 +0000 Subject: [PATCH 1757/7155] staging: isdn: remove unnecessary parentheses Fix the following checkpatch error: ERROR: return is not a function, parentheses are not required FILE: drivers/staging/isdn/hysdn/hysdn_net.c:289: + return (0); /* and return success */ Signed-off-by: Thiago Bonotto Link: https://lore.kernel.org/r/20190802202323.27117-1-thbonotto@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/isdn/hysdn/hysdn_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c index bea37ae30ebb..dcb9ef7a2651 100644 --- a/drivers/staging/isdn/hysdn/hysdn_net.c +++ b/drivers/staging/isdn/hysdn/hysdn_net.c @@ -286,7 +286,7 @@ hysdn_net_create(hysdn_card *card) if (card->debug_flags & LOG_NET_INIT) hysdn_addlog(card, "network device created"); - return (0); /* and return success */ + return 0; /* and return success */ } /* hysdn_net_create */ /***************************************************************************/ -- GitLab From 9fd827c699aaaac8521a3246638850913d140854 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Fri, 2 Aug 2019 16:47:37 -0300 Subject: [PATCH 1758/7155] staging: rtl8712: Add spaces around << Fix checkpatch error "CHECK: spaces preferred around that '<<'". Signed-off-by: Marco Villegas Link: https://lore.kernel.org/r/20190802194737.12252-1-git@marvil07.net Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 4199cb586fb1..c5c55967164b 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -41,7 +41,7 @@ do { \ pattrib_iv[0] = txpn._byte_.TSC0;\ pattrib_iv[1] = txpn._byte_.TSC1;\ pattrib_iv[2] = txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3)<<6);\ + pattrib_iv[3] = ((keyidx & 0x3) << 6);\ txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val+1);\ } while (0) -- GitLab From 1e80936a42e16b7a7c4265de666c472256b7cf36 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 13:52:43 +0800 Subject: [PATCH 1759/7155] dt-bindings: imx: Add clock binding doc for i.MX8MN Add the clock binding doc for i.MX8MN. Signed-off-by: Anson Huang Reviewed-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- .../bindings/clock/imx8mn-clock.yaml | 112 +++++++++ include/dt-bindings/clock/imx8mn-clock.h | 215 ++++++++++++++++++ 2 files changed, 327 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/imx8mn-clock.yaml create mode 100644 include/dt-bindings/clock/imx8mn-clock.h diff --git a/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml new file mode 100644 index 000000000000..622f3658bd9f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/imx8mn-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX8M Nano Clock Control Module Binding + +maintainers: + - Anson Huang + +description: | + NXP i.MX8M Nano clock control module is an integrated clock controller, which + generates and supplies to all modules. + +properties: + compatible: + const: fsl,imx8mn-ccm + + reg: + maxItems: 1 + + clocks: + items: + - description: 32k osc + - description: 24m osc + - description: ext1 clock input + - description: ext2 clock input + - description: ext3 clock input + - description: ext4 clock input + + clock-names: + items: + - const: osc_32k + - const: osc_24m + - const: clk_ext1 + - const: clk_ext2 + - const: clk_ext3 + - const: clk_ext4 + + '#clock-cells': + const: 1 + description: | + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mn-clock.h + for the full list of i.MX8M Nano clock IDs. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +examples: + # Clock Control Module node: + - | + clk: clock-controller@30380000 { + compatible = "fsl,imx8mn-ccm"; + reg = <0x0 0x30380000 0x0 0x10000>; + #clock-cells = <1>; + clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, + <&clk_ext2>, <&clk_ext3>, <&clk_ext4>; + clock-names = "osc_32k", "osc_24m", "clk_ext1", + "clk_ext2", "clk_ext3", "clk_ext4"; + }; + + # Required external clocks for Clock Control Module node: + - | + osc_32k: clock-osc-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "osc_32k"; + }; + + osc_24m: clock-osc-24m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "osc_24m"; + }; + + clk_ext1: clock-ext1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext1"; + }; + + clk_ext2: clock-ext2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext2"; + }; + + clk_ext3: clock-ext3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext3"; + }; + + clk_ext4: clock-ext4 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency= <133000000>; + clock-output-names = "clk_ext4"; + }; + +... diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h new file mode 100644 index 000000000000..5255b1c2420e --- /dev/null +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2018-2019 NXP + */ + +#ifndef __DT_BINDINGS_CLOCK_IMX8MN_H +#define __DT_BINDINGS_CLOCK_IMX8MN_H + +#define IMX8MN_CLK_DUMMY 0 +#define IMX8MN_CLK_32K 1 +#define IMX8MN_CLK_24M 2 +#define IMX8MN_OSC_HDMI_CLK 3 +#define IMX8MN_CLK_EXT1 4 +#define IMX8MN_CLK_EXT2 5 +#define IMX8MN_CLK_EXT3 6 +#define IMX8MN_CLK_EXT4 7 +#define IMX8MN_AUDIO_PLL1_REF_SEL 8 +#define IMX8MN_AUDIO_PLL2_REF_SEL 9 +#define IMX8MN_VIDEO_PLL1_REF_SEL 10 +#define IMX8MN_DRAM_PLL_REF_SEL 11 +#define IMX8MN_GPU_PLL_REF_SEL 12 +#define IMX8MN_VPU_PLL_REF_SEL 13 +#define IMX8MN_ARM_PLL_REF_SEL 14 +#define IMX8MN_SYS_PLL1_REF_SEL 15 +#define IMX8MN_SYS_PLL2_REF_SEL 16 +#define IMX8MN_SYS_PLL3_REF_SEL 17 +#define IMX8MN_AUDIO_PLL1 18 +#define IMX8MN_AUDIO_PLL2 19 +#define IMX8MN_VIDEO_PLL1 20 +#define IMX8MN_DRAM_PLL 21 +#define IMX8MN_GPU_PLL 22 +#define IMX8MN_VPU_PLL 23 +#define IMX8MN_ARM_PLL 24 +#define IMX8MN_SYS_PLL1 25 +#define IMX8MN_SYS_PLL2 26 +#define IMX8MN_SYS_PLL3 27 +#define IMX8MN_AUDIO_PLL1_BYPASS 28 +#define IMX8MN_AUDIO_PLL2_BYPASS 29 +#define IMX8MN_VIDEO_PLL1_BYPASS 30 +#define IMX8MN_DRAM_PLL_BYPASS 31 +#define IMX8MN_GPU_PLL_BYPASS 32 +#define IMX8MN_VPU_PLL_BYPASS 33 +#define IMX8MN_ARM_PLL_BYPASS 34 +#define IMX8MN_SYS_PLL1_BYPASS 35 +#define IMX8MN_SYS_PLL2_BYPASS 36 +#define IMX8MN_SYS_PLL3_BYPASS 37 +#define IMX8MN_AUDIO_PLL1_OUT 38 +#define IMX8MN_AUDIO_PLL2_OUT 39 +#define IMX8MN_VIDEO_PLL1_OUT 40 +#define IMX8MN_DRAM_PLL_OUT 41 +#define IMX8MN_GPU_PLL_OUT 42 +#define IMX8MN_VPU_PLL_OUT 43 +#define IMX8MN_ARM_PLL_OUT 44 +#define IMX8MN_SYS_PLL1_OUT 45 +#define IMX8MN_SYS_PLL2_OUT 46 +#define IMX8MN_SYS_PLL3_OUT 47 +#define IMX8MN_SYS_PLL1_40M 48 +#define IMX8MN_SYS_PLL1_80M 49 +#define IMX8MN_SYS_PLL1_100M 50 +#define IMX8MN_SYS_PLL1_133M 51 +#define IMX8MN_SYS_PLL1_160M 52 +#define IMX8MN_SYS_PLL1_200M 53 +#define IMX8MN_SYS_PLL1_266M 54 +#define IMX8MN_SYS_PLL1_400M 55 +#define IMX8MN_SYS_PLL1_800M 56 +#define IMX8MN_SYS_PLL2_50M 57 +#define IMX8MN_SYS_PLL2_100M 58 +#define IMX8MN_SYS_PLL2_125M 59 +#define IMX8MN_SYS_PLL2_166M 60 +#define IMX8MN_SYS_PLL2_200M 61 +#define IMX8MN_SYS_PLL2_250M 62 +#define IMX8MN_SYS_PLL2_333M 63 +#define IMX8MN_SYS_PLL2_500M 64 +#define IMX8MN_SYS_PLL2_1000M 65 + +/* CORE CLOCK ROOT */ +#define IMX8MN_CLK_A53_SRC 66 +#define IMX8MN_CLK_GPU_CORE_SRC 67 +#define IMX8MN_CLK_GPU_SHADER_SRC 68 +#define IMX8MN_CLK_A53_CG 69 +#define IMX8MN_CLK_GPU_CORE_CG 70 +#define IMX8MN_CLK_GPU_SHADER_CG 71 +#define IMX8MN_CLK_A53_DIV 72 +#define IMX8MN_CLK_GPU_CORE_DIV 73 +#define IMX8MN_CLK_GPU_SHADER_DIV 74 + +/* BUS CLOCK ROOT */ +#define IMX8MN_CLK_MAIN_AXI 75 +#define IMX8MN_CLK_ENET_AXI 76 +#define IMX8MN_CLK_NAND_USDHC_BUS 77 +#define IMX8MN_CLK_DISP_AXI 78 +#define IMX8MN_CLK_DISP_APB 79 +#define IMX8MN_CLK_USB_BUS 80 +#define IMX8MN_CLK_GPU_AXI 81 +#define IMX8MN_CLK_GPU_AHB 82 +#define IMX8MN_CLK_NOC 83 +#define IMX8MN_CLK_AHB 84 +#define IMX8MN_CLK_AUDIO_AHB 85 + +/* IPG CLOCK ROOT */ +#define IMX8MN_CLK_IPG_ROOT 86 +#define IMX8MN_CLK_IPG_AUDIO_ROOT 87 + +/* IP */ +#define IMX8MN_CLK_DRAM_CORE 88 +#define IMX8MN_CLK_DRAM_ALT 89 +#define IMX8MN_CLK_DRAM_APB 90 +#define IMX8MN_CLK_DRAM_ALT_ROOT 91 +#define IMX8MN_CLK_DISP_PIXEL 92 +#define IMX8MN_CLK_SAI2 93 +#define IMX8MN_CLK_SAI3 94 +#define IMX8MN_CLK_SAI5 95 +#define IMX8MN_CLK_SAI6 96 +#define IMX8MN_CLK_SPDIF1 97 +#define IMX8MN_CLK_ENET_REF 98 +#define IMX8MN_CLK_ENET_TIMER 99 +#define IMX8MN_CLK_ENET_PHY_REF 100 +#define IMX8MN_CLK_NAND 101 +#define IMX8MN_CLK_QSPI 102 +#define IMX8MN_CLK_USDHC1 103 +#define IMX8MN_CLK_USDHC2 104 +#define IMX8MN_CLK_I2C1 105 +#define IMX8MN_CLK_I2C2 106 +#define IMX8MN_CLK_I2C3 107 +#define IMX8MN_CLK_I2C4 118 +#define IMX8MN_CLK_UART1 119 +#define IMX8MN_CLK_UART2 110 +#define IMX8MN_CLK_UART3 111 +#define IMX8MN_CLK_UART4 112 +#define IMX8MN_CLK_USB_CORE_REF 113 +#define IMX8MN_CLK_USB_PHY_REF 114 +#define IMX8MN_CLK_ECSPI1 115 +#define IMX8MN_CLK_ECSPI2 116 +#define IMX8MN_CLK_PWM1 117 +#define IMX8MN_CLK_PWM2 118 +#define IMX8MN_CLK_PWM3 119 +#define IMX8MN_CLK_PWM4 120 +#define IMX8MN_CLK_WDOG 121 +#define IMX8MN_CLK_WRCLK 122 +#define IMX8MN_CLK_CLKO1 123 +#define IMX8MN_CLK_CLKO2 124 +#define IMX8MN_CLK_DSI_CORE 125 +#define IMX8MN_CLK_DSI_PHY_REF 126 +#define IMX8MN_CLK_DSI_DBI 127 +#define IMX8MN_CLK_USDHC3 128 +#define IMX8MN_CLK_CAMERA_PIXEL 129 +#define IMX8MN_CLK_CSI1_PHY_REF 130 +#define IMX8MN_CLK_CSI2_PHY_REF 131 +#define IMX8MN_CLK_CSI2_ESC 132 +#define IMX8MN_CLK_ECSPI3 133 +#define IMX8MN_CLK_PDM 134 +#define IMX8MN_CLK_SAI7 135 + +#define IMX8MN_CLK_ECSPI1_ROOT 136 +#define IMX8MN_CLK_ECSPI2_ROOT 137 +#define IMX8MN_CLK_ECSPI3_ROOT 138 +#define IMX8MN_CLK_ENET1_ROOT 139 +#define IMX8MN_CLK_GPIO1_ROOT 140 +#define IMX8MN_CLK_GPIO2_ROOT 141 +#define IMX8MN_CLK_GPIO3_ROOT 142 +#define IMX8MN_CLK_GPIO4_ROOT 143 +#define IMX8MN_CLK_GPIO5_ROOT 144 +#define IMX8MN_CLK_I2C1_ROOT 145 +#define IMX8MN_CLK_I2C2_ROOT 146 +#define IMX8MN_CLK_I2C3_ROOT 147 +#define IMX8MN_CLK_I2C4_ROOT 148 +#define IMX8MN_CLK_MU_ROOT 149 +#define IMX8MN_CLK_OCOTP_ROOT 150 +#define IMX8MN_CLK_PWM1_ROOT 151 +#define IMX8MN_CLK_PWM2_ROOT 152 +#define IMX8MN_CLK_PWM3_ROOT 153 +#define IMX8MN_CLK_PWM4_ROOT 154 +#define IMX8MN_CLK_QSPI_ROOT 155 +#define IMX8MN_CLK_NAND_ROOT 156 +#define IMX8MN_CLK_SAI2_ROOT 157 +#define IMX8MN_CLK_SAI2_IPG 158 +#define IMX8MN_CLK_SAI3_ROOT 159 +#define IMX8MN_CLK_SAI3_IPG 160 +#define IMX8MN_CLK_SAI5_ROOT 161 +#define IMX8MN_CLK_SAI5_IPG 162 +#define IMX8MN_CLK_SAI6_ROOT 163 +#define IMX8MN_CLK_SAI6_IPG 164 +#define IMX8MN_CLK_SAI7_ROOT 165 +#define IMX8MN_CLK_SAI7_IPG 166 +#define IMX8MN_CLK_SDMA1_ROOT 167 +#define IMX8MN_CLK_SDMA2_ROOT 168 +#define IMX8MN_CLK_UART1_ROOT 169 +#define IMX8MN_CLK_UART2_ROOT 170 +#define IMX8MN_CLK_UART3_ROOT 171 +#define IMX8MN_CLK_UART4_ROOT 172 +#define IMX8MN_CLK_USB1_CTRL_ROOT 173 +#define IMX8MN_CLK_USDHC1_ROOT 174 +#define IMX8MN_CLK_USDHC2_ROOT 175 +#define IMX8MN_CLK_WDOG1_ROOT 176 +#define IMX8MN_CLK_WDOG2_ROOT 177 +#define IMX8MN_CLK_WDOG3_ROOT 178 +#define IMX8MN_CLK_GPU_BUS_ROOT 179 +#define IMX8MN_CLK_ASRC_ROOT 180 +#define IMX8MN_CLK_GPU3D_ROOT 181 +#define IMX8MN_CLK_PDM_ROOT 182 +#define IMX8MN_CLK_PDM_IPG 183 +#define IMX8MN_CLK_DISP_AXI_ROOT 184 +#define IMX8MN_CLK_DISP_APB_ROOT 185 +#define IMX8MN_CLK_DISP_PIXEL_ROOT 186 +#define IMX8MN_CLK_CAMERA_PIXEL_ROOT 187 +#define IMX8MN_CLK_USDHC3_ROOT 188 +#define IMX8MN_CLK_SDMA3_ROOT 189 +#define IMX8MN_CLK_TMU_ROOT 190 +#define IMX8MN_CLK_ARM 191 +#define IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK 192 +#define IMX8MN_CLK_GPU_CORE_ROOT 193 + +#define IMX8MN_CLK_END 194 + +#endif -- GitLab From 34af5179d239e42698e2aff0be94de2aeac9a733 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 13:52:44 +0800 Subject: [PATCH 1760/7155] clk: imx8mm: Make 1416X/1443X PLL macro definitions common for usage 1416X/1443X PLL are used on i.MX8MM and i.MX8MN and maybe other i.MX8M series SoC later, the macro definitions of these PLLs' initialization should be common for usage. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 17 ----------------- drivers/clk/imx/clk.h | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 6b8e75df994d..43fa9c361fcb 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -26,23 +26,6 @@ static u32 share_count_dcss; static u32 share_count_pdm; static u32 share_count_nand; -#define PLL_1416X_RATE(_rate, _m, _p, _s) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - } - -#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ - { \ - .rate = (_rate), \ - .mdiv = (_m), \ - .pdiv = (_p), \ - .sdiv = (_s), \ - .kdiv = (_k), \ - } - static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = { PLL_1416X_RATE(1800000000U, 225, 3, 0), PLL_1416X_RATE(1600000000U, 200, 3, 0), diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index d94d9cb079d3..19d7b8b0a00e 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -153,6 +153,23 @@ enum imx_pllv3_type { struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, const char *parent_name, void __iomem *base, u32 div_mask); +#define PLL_1416X_RATE(_rate, _m, _p, _s) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + } + struct clk_hw *imx_clk_pllv4(const char *name, const char *parent_name, void __iomem *base); -- GitLab From fd6ef2857b7484ab947beb2f2a1bbb3662553298 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 13:52:45 +0800 Subject: [PATCH 1761/7155] clk: imx: Add API for clk unregister when driver probe fail For i.MX clock drivers probe fail case, clks should be unregistered in the return path, this patch adds a common API for i.MX clock drivers to unregister clocks when fail. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk.c | 8 ++++++++ drivers/clk/imx/clk.h | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c index f628071f6605..cfc05e43c343 100644 --- a/drivers/clk/imx/clk.c +++ b/drivers/clk/imx/clk.c @@ -14,6 +14,14 @@ DEFINE_SPINLOCK(imx_ccm_lock); +void imx_unregister_clocks(struct clk *clks[], unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + clk_unregister(clks[i]); +} + void __init imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn) { diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 19d7b8b0a00e..bb4ec1b33faf 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -12,6 +12,7 @@ void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count); void imx_register_uart_clocks(struct clk ** const clks[]); void imx_register_uart_clocks_hws(struct clk_hw ** const hws[]); void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn); +void imx_unregister_clocks(struct clk *clks[], unsigned int count); extern void imx_cscmr1_fixup(u32 *val); -- GitLab From 96d6392b54dbb1ff2b39448a2516fa6abb33114b Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 13:52:46 +0800 Subject: [PATCH 1762/7155] clk: imx: Add support for i.MX8MN clock driver This patch adds i.MX8MN clock driver support. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/Kconfig | 6 + drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-imx8mn.c | 636 +++++++++++++++++++++++++++++++++++ 3 files changed, 643 insertions(+) create mode 100644 drivers/clk/imx/clk-imx8mn.c diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index 0eaf41848280..1ac0c7990392 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -14,6 +14,12 @@ config CLK_IMX8MM help Build the driver for i.MX8MM CCM Clock Driver +config CLK_IMX8MN + bool "IMX8MN CCM Clock Driver" + depends on ARCH_MXC && ARM64 + help + Build the driver for i.MX8MN CCM Clock Driver + config CLK_IMX8MQ bool "IMX8MQ CCM Clock Driver" depends on ARCH_MXC && ARM64 diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 05641c64b317..77a3d714f1d5 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MXC_CLK_SCU) += \ clk-lpcg-scu.o obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o +obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c new file mode 100644 index 000000000000..07481a53e336 --- /dev/null +++ b/drivers/clk/imx/clk-imx8mn.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018-2019 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +static u32 share_count_sai2; +static u32 share_count_sai3; +static u32 share_count_sai5; +static u32 share_count_sai6; +static u32 share_count_sai7; +static u32 share_count_disp; +static u32 share_count_pdm; +static u32 share_count_nand; + +enum { + ARM_PLL, + GPU_PLL, + VPU_PLL, + SYS_PLL1, + SYS_PLL2, + SYS_PLL3, + DRAM_PLL, + AUDIO_PLL1, + AUDIO_PLL2, + VIDEO_PLL2, + NR_PLLS, +}; + +static const struct imx_pll14xx_rate_table imx8mn_pll1416x_tbl[] = { + PLL_1416X_RATE(1800000000U, 225, 3, 0), + PLL_1416X_RATE(1600000000U, 200, 3, 0), + PLL_1416X_RATE(1200000000U, 300, 3, 1), + PLL_1416X_RATE(1000000000U, 250, 3, 1), + PLL_1416X_RATE(800000000U, 200, 3, 1), + PLL_1416X_RATE(750000000U, 250, 2, 2), + PLL_1416X_RATE(700000000U, 350, 3, 2), + PLL_1416X_RATE(600000000U, 300, 3, 2), +}; + +static const struct imx_pll14xx_rate_table imx8mn_audiopll_tbl[] = { + PLL_1443X_RATE(786432000U, 655, 5, 2, 23593), + PLL_1443X_RATE(722534400U, 301, 5, 1, 3670), +}; + +static const struct imx_pll14xx_rate_table imx8mn_videopll_tbl[] = { + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), + PLL_1443X_RATE(594000000U, 198, 2, 2, 0), +}; + +static const struct imx_pll14xx_rate_table imx8mn_drampll_tbl[] = { + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), +}; + +static struct imx_pll14xx_clk imx8mn_audio_pll = { + .type = PLL_1443X, + .rate_table = imx8mn_audiopll_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_video_pll = { + .type = PLL_1443X, + .rate_table = imx8mn_videopll_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_dram_pll = { + .type = PLL_1443X, + .rate_table = imx8mn_drampll_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_arm_pll = { + .type = PLL_1416X, + .rate_table = imx8mn_pll1416x_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_gpu_pll = { + .type = PLL_1416X, + .rate_table = imx8mn_pll1416x_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_vpu_pll = { + .type = PLL_1416X, + .rate_table = imx8mn_pll1416x_tbl, +}; + +static struct imx_pll14xx_clk imx8mn_sys_pll = { + .type = PLL_1416X, + .rate_table = imx8mn_pll1416x_tbl, +}; + +static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", }; +static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", }; +static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; +static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; +static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; +static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", }; +static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", }; +static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", }; + +static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", + "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", + "audio_pll1_out", "sys_pll3_out", }; + +static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", + "video_pll1_out", "audio_pll2_out", }; + +static const char * const imx8mn_gpu_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", + "video_pll1_out", "audio_pll2_out", }; + +static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out", + "video_pll1_out", "sys_pll1_100m",}; + +static const char * const imx8mn_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out", + "video_pll1_out", "sys_pll3_out", }; + +static const char * const imx8mn_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll1_out", }; + +static const char * const imx8mn_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m", + "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out", + "clk_ext1", "clk_ext4", }; + +static const char * const imx8mn_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m", + "sys_pll3_out", "sys1_pll_40m", "audio_pll2_out", + "clk_ext1", "clk_ext3", }; + +static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char * const imx8mn_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", + "video_pll1_out", "audio_pll2_out", }; + +static const char * const imx8mn_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", + "video_pll1_out", "audio_pll2_out", }; + +static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out", + "video_pll1_out", "audio_pll2_out", }; + +static const char * const imx8mn_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", + "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out", + "audio_pll1_out", "video_pll1_out", }; + +static const char * const imx8mn_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", + "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out", + "audio_pll1_out", "video_pll1_out", }; + +static const char * const imx8mn_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m", + "sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out", + "audio_pll1_out", "sys_pll1_266m", }; + +static const char * const imx8mn_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", + "audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m", + "sys_pll3_out", "clk_ext4", }; + +static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext3", "clk_ext4", }; + +static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext3", "clk_ext4", }; + +static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext2", "clk_ext3", }; + +static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext3", "clk_ext4", }; + +static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext3", "clk_ext4", }; + +static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "osc_hdmi", + "clk_ext2", "clk_ext3", }; + +static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", + "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out", + "video_pll1_out", "clk_ext4", }; + +static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", + "clk_ext1", "clk_ext2", "clk_ext3", + "clk_ext4", "video_pll1_out", }; + +static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", + "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out", + "audio_pll2_out", }; + +static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", + "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out", + "sys_pll2_250m", "video_pll1_out", }; + +static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys1_pll_400m", "sys_pll1_800m", + "sys2_pll_500m", "audio_pll2_out", "sys1_pll_266m", + "sys3_pll2_out", "sys1_pll_100m", }; + +static const char * const imx8mn_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char * const imx8mn_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_out", "sys_pll1_100m", }; + +static const char * const imx8mn_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char * const imx8mn_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char * const imx8mn_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char * const imx8mn_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", + "audio_pll2_out", "sys_pll1_133m", }; + +static const char * const imx8mn_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char * const imx8mn_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext4", "audio_pll2_out", }; + +static const char * const imx8mn_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", + "sys_pll2_100m", "sys_pll3_out", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_usb_core_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", + "sys_pll2_100m", "sys_pll2_200m", "clk_ext2", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char * const imx8mn_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char * const imx8mn_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext1", + "sys_pll1_80m", "video_pll1_out", }; + +static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext1", + "sys_pll1_80m", "video_pll1_out", }; + +static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys3_pll2_out", "clk_ext2", + "sys_pll1_80m", "video_pll1_out", }; + +static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext2", + "sys_pll1_80m", "video_pll1_out", }; + +static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", + "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", + "sys_pll1_80m", "sys_pll2_166m", }; + +static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out", + "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m", + "sys_pll2_500m", "sys_pll1_100m", }; + +static const char * const imx8mn_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", + "audio_pll2_clk", "sys_pll1_100m", }; + +static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", + "audio_pll2_out", "video_pll1_out", }; + +static const char * const imx8mn_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", + "clk_ext3", "audio_pll2_out", }; + +static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }; + +static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", + "sys_pll1_200m", "audio_pll2_clk", "vpu_pll", + "sys_pll1_80m", }; +static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", + "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", + "video_pll1_out", "osc_32k", }; + +static struct clk *clks[IMX8MN_CLK_END]; +static struct clk_onecell_data clk_data; + +static int imx8mn_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + void __iomem *base; + int ret; + + clks[IMX8MN_CLK_DUMMY] = imx_clk_fixed("dummy", 0); + clks[IMX8MN_CLK_24M] = of_clk_get_by_name(np, "osc_24m"); + clks[IMX8MN_CLK_32K] = of_clk_get_by_name(np, "osc_32k"); + clks[IMX8MN_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1"); + clks[IMX8MN_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2"); + clks[IMX8MN_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3"); + clks[IMX8MN_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4"); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop"); + base = of_iomap(np, 0); + if (WARN_ON(!base)) { + ret = -ENOMEM; + goto unregister_clks; + } + + clks[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_SYS_PLL1_REF_SEL] = imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_SYS_PLL2_REF_SEL] = imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + clks[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + + clks[IMX8MN_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx8mn_audio_pll); + clks[IMX8MN_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx8mn_audio_pll); + clks[IMX8MN_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx8mn_video_pll); + clks[IMX8MN_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mn_dram_pll); + clks[IMX8MN_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx8mn_gpu_pll); + clks[IMX8MN_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx8mn_vpu_pll); + clks[IMX8MN_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mn_arm_pll); + clks[IMX8MN_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mn_sys_pll); + clks[IMX8MN_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mn_sys_pll); + clks[IMX8MN_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mn_sys_pll); + + /* PLL bypass out */ + clks[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT); + clks[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT); + + /* unbypass all the plls */ + clk_set_parent(clks[IMX8MN_AUDIO_PLL1_BYPASS], clks[IMX8MN_AUDIO_PLL1]); + clk_set_parent(clks[IMX8MN_AUDIO_PLL2_BYPASS], clks[IMX8MN_AUDIO_PLL2]); + clk_set_parent(clks[IMX8MN_VIDEO_PLL1_BYPASS], clks[IMX8MN_VIDEO_PLL1]); + clk_set_parent(clks[IMX8MN_DRAM_PLL_BYPASS], clks[IMX8MN_DRAM_PLL]); + clk_set_parent(clks[IMX8MN_GPU_PLL_BYPASS], clks[IMX8MN_GPU_PLL]); + clk_set_parent(clks[IMX8MN_VPU_PLL_BYPASS], clks[IMX8MN_VPU_PLL]); + clk_set_parent(clks[IMX8MN_ARM_PLL_BYPASS], clks[IMX8MN_ARM_PLL]); + clk_set_parent(clks[IMX8MN_SYS_PLL1_BYPASS], clks[IMX8MN_SYS_PLL1]); + clk_set_parent(clks[IMX8MN_SYS_PLL2_BYPASS], clks[IMX8MN_SYS_PLL2]); + clk_set_parent(clks[IMX8MN_SYS_PLL3_BYPASS], clks[IMX8MN_SYS_PLL3]); + + /* PLL out gate */ + clks[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13); + clks[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13); + clks[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13); + clks[IMX8MN_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13); + clks[IMX8MN_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13); + clks[IMX8MN_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13); + clks[IMX8MN_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13); + clks[IMX8MN_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13); + clks[IMX8MN_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13); + clks[IMX8MN_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13); + + /* SYS PLL fixed output */ + clks[IMX8MN_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20); + clks[IMX8MN_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10); + clks[IMX8MN_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8); + clks[IMX8MN_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6); + clks[IMX8MN_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5); + clks[IMX8MN_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4); + clks[IMX8MN_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3); + clks[IMX8MN_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2); + clks[IMX8MN_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1); + + clks[IMX8MN_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20); + clks[IMX8MN_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10); + clks[IMX8MN_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8); + clks[IMX8MN_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6); + clks[IMX8MN_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5); + clks[IMX8MN_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4); + clks[IMX8MN_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3); + clks[IMX8MN_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); + clks[IMX8MN_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); + + np = dev->of_node; + base = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(base))) { + ret = PTR_ERR(base); + goto unregister_clks; + } + + /* CORE */ + clks[IMX8MN_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mn_a53_sels, ARRAY_SIZE(imx8mn_a53_sels)); + clks[IMX8MN_CLK_GPU_CORE_SRC] = imx_clk_mux2("gpu_core_src", base + 0x8180, 24, 3, imx8mn_gpu_core_sels, ARRAY_SIZE(imx8mn_gpu_core_sels)); + clks[IMX8MN_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mn_gpu_shader_sels, ARRAY_SIZE(imx8mn_gpu_shader_sels)); + clks[IMX8MN_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28); + clks[IMX8MN_CLK_GPU_CORE_CG] = imx_clk_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28); + clks[IMX8MN_CLK_GPU_SHADER_CG] = imx_clk_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28); + + clks[IMX8MN_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3); + clks[IMX8MN_CLK_GPU_CORE_DIV] = imx_clk_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3); + clks[IMX8MN_CLK_GPU_SHADER_DIV] = imx_clk_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3); + + /* BUS */ + clks[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800); + clks[IMX8MN_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mn_enet_axi_sels, base + 0x8880); + clks[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_composite("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900); + clks[IMX8MN_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00); + clks[IMX8MN_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mn_disp_apb_sels, base + 0x8a80); + clks[IMX8MN_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80); + clks[IMX8MN_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00); + clks[IMX8MN_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80); + clks[IMX8MN_CLK_NOC] = imx8m_clk_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00); + + clks[IMX8MN_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mn_ahb_sels, base + 0x9000); + clks[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100); + clks[IMX8MN_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1); + clks[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1); + clks[IMX8MN_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mn_dram_core_sels, ARRAY_SIZE(imx8mn_dram_core_sels), CLK_IS_CRITICAL); + clks[IMX8MN_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000); + clks[IMX8MN_CLK_DRAM_APB] = imx8m_clk_composite_critical("dram_apb", imx8mn_dram_apb_sels, base + 0xa080); + clks[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500); + clks[IMX8MN_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mn_sai2_sels, base + 0xa600); + clks[IMX8MN_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mn_sai3_sels, base + 0xa680); + clks[IMX8MN_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mn_sai5_sels, base + 0xa780); + clks[IMX8MN_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mn_sai6_sels, base + 0xa800); + clks[IMX8MN_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mn_spdif1_sels, base + 0xa880); + clks[IMX8MN_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mn_enet_ref_sels, base + 0xa980); + clks[IMX8MN_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mn_enet_timer_sels, base + 0xaa00); + clks[IMX8MN_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mn_enet_phy_sels, base + 0xaa80); + clks[IMX8MN_CLK_NAND] = imx8m_clk_composite("nand", imx8mn_nand_sels, base + 0xab00); + clks[IMX8MN_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mn_qspi_sels, base + 0xab80); + clks[IMX8MN_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mn_usdhc1_sels, base + 0xac00); + clks[IMX8MN_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mn_usdhc2_sels, base + 0xac80); + clks[IMX8MN_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mn_i2c1_sels, base + 0xad00); + clks[IMX8MN_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mn_i2c2_sels, base + 0xad80); + clks[IMX8MN_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mn_i2c3_sels, base + 0xae00); + clks[IMX8MN_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mn_i2c4_sels, base + 0xae80); + clks[IMX8MN_CLK_UART1] = imx8m_clk_composite("uart1", imx8mn_uart1_sels, base + 0xaf00); + clks[IMX8MN_CLK_UART2] = imx8m_clk_composite("uart2", imx8mn_uart2_sels, base + 0xaf80); + clks[IMX8MN_CLK_UART3] = imx8m_clk_composite("uart3", imx8mn_uart3_sels, base + 0xb000); + clks[IMX8MN_CLK_UART4] = imx8m_clk_composite("uart4", imx8mn_uart4_sels, base + 0xb080); + clks[IMX8MN_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mn_usb_core_sels, base + 0xb100); + clks[IMX8MN_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mn_usb_phy_sels, base + 0xb180); + clks[IMX8MN_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mn_ecspi1_sels, base + 0xb280); + clks[IMX8MN_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mn_ecspi2_sels, base + 0xb300); + clks[IMX8MN_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mn_pwm1_sels, base + 0xb380); + clks[IMX8MN_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mn_pwm2_sels, base + 0xb400); + clks[IMX8MN_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mn_pwm3_sels, base + 0xb480); + clks[IMX8MN_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mn_pwm4_sels, base + 0xb500); + clks[IMX8MN_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mn_wdog_sels, base + 0xb900); + clks[IMX8MN_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mn_wrclk_sels, base + 0xb980); + clks[IMX8MN_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mn_clko1_sels, base + 0xba00); + clks[IMX8MN_CLK_CLKO2] = imx8m_clk_composite("clko2", imx8mn_clko2_sels, base + 0xba80); + clks[IMX8MN_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mn_dsi_core_sels, base + 0xbb00); + clks[IMX8MN_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mn_dsi_phy_sels, base + 0xbb80); + clks[IMX8MN_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mn_dsi_dbi_sels, base + 0xbc00); + clks[IMX8MN_CLK_USDHC3] = imx8m_clk_composite("usdhc3", imx8mn_usdhc3_sels, base + 0xbc80); + clks[IMX8MN_CLK_CAMERA_PIXEL] = imx8m_clk_composite("camera_pixel", imx8mn_camera_pixel_sels, base + 0xbd00); + clks[IMX8MN_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mn_csi1_phy_sels, base + 0xbd80); + clks[IMX8MN_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mn_csi2_phy_sels, base + 0xbf00); + clks[IMX8MN_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mn_csi2_esc_sels, base + 0xbf80); + clks[IMX8MN_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mn_ecspi3_sels, base + 0xc180); + clks[IMX8MN_CLK_PDM] = imx8m_clk_composite("pdm", imx8mn_pdm_sels, base + 0xc200); + clks[IMX8MN_CLK_SAI7] = imx8m_clk_composite("sai7", imx8mn_sai7_sels, base + 0xc300); + + clks[IMX8MN_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0); + clks[IMX8MN_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0); + clks[IMX8MN_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0); + clks[IMX8MN_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0); + clks[IMX8MN_CLK_GPIO1_ROOT] = imx_clk_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0); + clks[IMX8MN_CLK_GPIO2_ROOT] = imx_clk_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0); + clks[IMX8MN_CLK_GPIO3_ROOT] = imx_clk_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0); + clks[IMX8MN_CLK_GPIO4_ROOT] = imx_clk_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0); + clks[IMX8MN_CLK_GPIO5_ROOT] = imx_clk_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0); + clks[IMX8MN_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0); + clks[IMX8MN_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0); + clks[IMX8MN_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0); + clks[IMX8MN_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0); + clks[IMX8MN_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0); + clks[IMX8MN_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0); + clks[IMX8MN_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0); + clks[IMX8MN_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0); + clks[IMX8MN_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0); + clks[IMX8MN_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0); + clks[IMX8MN_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0); + clks[IMX8MN_CLK_NAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand); + clks[IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0, &share_count_nand); + clks[IMX8MN_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", base + 0x4340, 0, &share_count_sai2); + clks[IMX8MN_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_audio_root", base + 0x4340, 0, &share_count_sai2); + clks[IMX8MN_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", base + 0x4350, 0, &share_count_sai3); + clks[IMX8MN_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_audio_root", base + 0x4350, 0, &share_count_sai3); + clks[IMX8MN_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", base + 0x4370, 0, &share_count_sai5); + clks[IMX8MN_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); + clks[IMX8MN_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); + clks[IMX8MN_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); + clks[IMX8MN_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); + clks[IMX8MN_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); + clks[IMX8MN_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); + clks[IMX8MN_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0); + clks[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0); + clks[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_gate4("gpu_core_root_clk", "gpu_core_div", base + 0x44f0, 0); + clks[IMX8MN_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0); + clks[IMX8MN_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0); + clks[IMX8MN_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0); + clks[IMX8MN_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0); + clks[IMX8MN_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0); + clks[IMX8MN_CLK_GPU_BUS_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_axi", base + 0x4570, 0); + clks[IMX8MN_CLK_ASRC_ROOT] = imx_clk_gate4("asrc_root_clk", "audio_ahb", base + 0x4580, 0); + clks[IMX8MN_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", base + 0x45b0, 0, &share_count_pdm); + clks[IMX8MN_CLK_PDM_IPG] = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", base + 0x45b0, 0, &share_count_pdm); + clks[IMX8MN_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_disp); + clks[IMX8MN_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_disp); + clks[IMX8MN_CLK_CAMERA_PIXEL_ROOT] = imx_clk_gate2_shared2("camera_pixel_clk", "camera_pixel", base + 0x45d0, 0, &share_count_disp); + clks[IMX8MN_CLK_DISP_PIXEL_ROOT] = imx_clk_gate2_shared2("disp_pixel_clk", "disp_pixel", base + 0x45d0, 0, &share_count_disp); + clks[IMX8MN_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0); + clks[IMX8MN_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0); + clks[IMX8MN_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0); + clks[IMX8MN_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0); + clks[IMX8MN_CLK_SDMA3_ROOT] = imx_clk_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0); + clks[IMX8MN_CLK_SAI7_ROOT] = imx_clk_gate2_shared2("sai7_root_clk", "sai7", base + 0x4650, 0, &share_count_sai7); + + clks[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4); + + clks[IMX8MN_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div", + clks[IMX8MN_CLK_A53_DIV], + clks[IMX8MN_CLK_A53_SRC], + clks[IMX8MN_ARM_PLL_OUT], + clks[IMX8MN_CLK_24M]); + + imx_check_clocks(clks, ARRAY_SIZE(clks)); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + if (ret < 0) { + dev_err(dev, "failed to register clks for i.MX8MN\n"); + goto unregister_clks; + } + + return 0; + +unregister_clks: + imx_unregister_clocks(clks, ARRAY_SIZE(clks)); + + return ret; +} + +static const struct of_device_id imx8mn_clk_of_match[] = { + { .compatible = "fsl,imx8mn-ccm" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx8mn_clk_of_match); + +static struct platform_driver imx8mn_clk_driver = { + .probe = imx8mn_clocks_probe, + .driver = { + .name = "imx8mn-ccm", + .of_match_table = of_match_ptr(imx8mn_clk_of_match), + }, +}; +module_platform_driver(imx8mn_clk_driver); -- GitLab From 6ad7cb7122cee4d3e672e58bf542b070b9363c15 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 2 Jul 2019 18:20:07 +0300 Subject: [PATCH 1763/7155] clk: imx8: Add DSP related clocks i.MX8QXP contains Hifi4 DSP. There are four clocks associated with DSP: * dsp_lpcg_core_clk * dsp_lpcg_ipg_clk * dsp_lpcg_adb_aclk * ocram_lpcg_ipg_clk Signed-off-by: Daniel Baluta Reviewed-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 5 +++++ include/dt-bindings/clock/imx8-clock.h | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index fb6edf1b8aa2..c0aff7ca6374 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -72,6 +72,11 @@ static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = { { IMX_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, }, { IMX_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, }, { IMX_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, }, + + { IMX_ADMA_LPCG_DSP_CORE_CLK, "dsp_lpcg_core_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 28, 0, }, + { IMX_ADMA_LPCG_DSP_IPG_CLK, "dsp_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 20, 0, }, + { IMX_ADMA_LPCG_DSP_ADB_CLK, "dsp_lpcg_adb_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 16, 0, }, + { IMX_ADMA_LPCG_OCRAM_IPG_CLK, "ocram_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_OCRAM_LPCG, 16, 0, }, }; static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = { diff --git a/include/dt-bindings/clock/imx8-clock.h b/include/dt-bindings/clock/imx8-clock.h index 4236818e3be5..673a8c662340 100644 --- a/include/dt-bindings/clock/imx8-clock.h +++ b/include/dt-bindings/clock/imx8-clock.h @@ -283,7 +283,11 @@ #define IMX_ADMA_LPCG_PWM_IPG_CLK 38 #define IMX_ADMA_LPCG_LCD_PIX_CLK 39 #define IMX_ADMA_LPCG_LCD_APB_CLK 40 +#define IMX_ADMA_LPCG_DSP_ADB_CLK 41 +#define IMX_ADMA_LPCG_DSP_IPG_CLK 42 +#define IMX_ADMA_LPCG_DSP_CORE_CLK 43 +#define IMX_ADMA_LPCG_OCRAM_IPG_CLK 44 -#define IMX_ADMA_LPCG_CLK_END 41 +#define IMX_ADMA_LPCG_CLK_END 45 #endif /* __DT_BINDINGS_CLOCK_IMX_H */ -- GitLab From 0008c1f3bc274fcea3b9654a07718d6012773e25 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Fri, 12 Jul 2019 16:43:16 -0400 Subject: [PATCH 1764/7155] dt-bindings: bus: imx-weim: document optional burst clock mode An optional devicetree property was added to the imx-weim driver, which if present instructs it to operate in burst clock mode. Update the dt-bindings to reflect this. Signed-off-by: Sven Van Asbroeck Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/bus/imx-weim.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt index dda7d6d66479..1b1d1c5c21ea 100644 --- a/Documentation/devicetree/bindings/bus/imx-weim.txt +++ b/Documentation/devicetree/bindings/bus/imx-weim.txt @@ -44,6 +44,10 @@ Optional properties: what bootloader sets up in IOMUXC_GPR1[11:0] will be used. + - fsl,burst-clk-enable For "fsl,imx50-weim" and "fsl,imx6q-weim" type of + devices, the presence of this property indicates that + the weim bus should operate in Burst Clock Mode. + Timing property for child nodes. It is mandatory, not optional. - fsl,weim-cs-timing: The timing array, contains timing values for the -- GitLab From 77266e722feabb6eefc8a7e84ac2415837d91c5f Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Fri, 12 Jul 2019 16:43:15 -0400 Subject: [PATCH 1765/7155] bus: imx-weim: optionally enable burst clock mode To enable burst clock mode, add the fsl,burst-clk-enable property to the weim bus's devicetree node. Example: weim: weim@21b8000 { compatible = "fsl,imx6q-weim"; reg = <0x021b8000 0x4000>; clocks = <&clks 196>; #address-cells = <2>; #size-cells = <1>; ranges = <0 0 0x08000000 0x08000000>; fsl,weim-cs-gpr = <&gpr>; fsl,burst-clk-enable; client-device@0,0 { compatible = "something"; reg = <0 0 0x02000000>; #address-cells = <1>; #size-cells = <1>; bank-width = <2>; fsl,weim-cs-timing = <0x00620081 0x00000001 0x1c022000 0x0000c000 0x1404a38e 0x00000000>; }; }; Signed-off-by: Sven Van Asbroeck Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- drivers/bus/imx-weim.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c index db74334ca5ef..cb7d5504a22a 100644 --- a/drivers/bus/imx-weim.c +++ b/drivers/bus/imx-weim.c @@ -19,6 +19,8 @@ struct imx_weim_devtype { unsigned int cs_count; unsigned int cs_regs_count; unsigned int cs_stride; + unsigned int wcr_offset; + unsigned int wcr_bcm; }; static const struct imx_weim_devtype imx1_weim_devtype = { @@ -37,6 +39,8 @@ static const struct imx_weim_devtype imx50_weim_devtype = { .cs_count = 4, .cs_regs_count = 6, .cs_stride = 0x18, + .wcr_offset = 0x90, + .wcr_bcm = BIT(0), }; static const struct imx_weim_devtype imx51_weim_devtype = { @@ -192,6 +196,7 @@ static int __init weim_parse_dt(struct platform_device *pdev, struct device_node *child; int ret, have_child = 0; struct cs_timing_state ts = {}; + u32 reg; if (devtype == &imx50_weim_devtype) { ret = imx_weim_gpr_setup(pdev); @@ -199,6 +204,17 @@ static int __init weim_parse_dt(struct platform_device *pdev, return ret; } + if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) { + if (devtype->wcr_bcm) { + reg = readl(base + devtype->wcr_offset); + writel(reg | devtype->wcr_bcm, + base + devtype->wcr_offset); + } else { + dev_err(&pdev->dev, "burst clk mode not supported.\n"); + return -EINVAL; + } + } + for_each_available_child_of_node(pdev->dev.of_node, child) { ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts); if (ret) -- GitLab From 8ad2d1dcce5493d422de9f38a83ad2e879f490c8 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 22 Jul 2019 10:45:45 -0300 Subject: [PATCH 1766/7155] ARM: dts: imx6qdl-wandboard: Add OV5645 camera support imx6qdl-wandboard can be connected to a OV5645 camera via MIPI CSI port. Add support for it. PAD_GPIO_6 has been originally used for the Ethernet FEC ERR006687 workaround, but it needs to be used to provide the camera sensor clock, so adjust it accordingly. Signed-off-by: Ezequiel Garcia Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 73 ++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi index 50d9a989e06a..2cfb4112a467 100644 --- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi @@ -33,6 +33,30 @@ spdif-out; }; + reg_1p5v: regulator-1p5v { + compatible = "regulator-fixed"; + regulator-name = "1P5V"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "1P8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + reg_2p8v: regulator-2p8v { + compatible = "regulator-fixed"; + regulator-name = "2P8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + reg_2p5v: regulator-2p5v { compatible = "regulator-fixed"; regulator-name = "2P5V"; @@ -94,6 +118,29 @@ VDDIO-supply = <®_3p3v>; lrclk-strength = <3>; }; + + camera@3c { + compatible = "ovti,ov5645"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ov5645>; + reg = <0x3c>; + clocks = <&clks IMX6QDL_CLK_CKO2>; + clock-names = "xclk"; + clock-frequency = <24000000>; + vdddo-supply = <®_1p8v>; + vdda-supply = <®_2p8v>; + vddd-supply = <®_1p5v>; + enable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>; + + port { + ov5645_to_mipi_csi2: endpoint { + remote-endpoint = <&mipi_csi2_in>; + clock-lanes = <0>; + data-lanes = <1 2>; + }; + }; + }; }; &iomuxc { @@ -128,7 +175,6 @@ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030 MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 - MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 >; }; @@ -152,6 +198,14 @@ >; }; + pinctrl_ov5645: ov5645grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0 + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 + MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0 + >; + }; + pinctrl_spdif: spdifgrp { fsl,pins = < MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0 @@ -226,12 +280,23 @@ pinctrl-0 = <&pinctrl_enet>; phy-mode = "rgmii-id"; phy-reset-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>; - interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, - <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; - fsl,err006687-workaround-present; status = "okay"; }; +&mipi_csi { + status = "okay"; + + port@0 { + reg = <0>; + + mipi_csi2_in: endpoint { + remote-endpoint = <&ov5645_to_mipi_csi2>; + clock-lanes = <0>; + data-lanes = <1 2>; + }; + }; +}; + &spdif { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spdif>; -- GitLab From f27c3a359e6ed0f220fa767f6c965d581e7a7c6d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 22 Jul 2019 10:45:46 -0300 Subject: [PATCH 1767/7155] ARM: imx_v6_v7_defconfig: Select the OV5645 camera driver OV5645 camera sensor can be used on several i.MX boards, such as imx6qdl-wandboard, imx7d-pico, imx6ul-pico, etc. Select the OV5645 driver by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index a53b29251ed4..bd2e2f5d1c3a 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -272,6 +272,7 @@ CONFIG_VIDEO_IMX_PXP=y CONFIG_VIDEO_ADV7180=m CONFIG_VIDEO_OV2680=m CONFIG_VIDEO_OV5640=m +CONFIG_VIDEO_OV5645=m CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_LVDS=y -- GitLab From 3724ace582d9f675134985727fd5e9811f23c059 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 24 Jun 2019 15:08:55 +0000 Subject: [PATCH 1768/7155] EDAC/mc: Fix grain_bits calculation The grain in EDAC is defined as "minimum granularity for an error report, in bytes". The following calculation of the grain_bits in edac_mc is wrong: grain_bits = fls_long(e->grain) + 1; Where grain_bits is defined as: grain = 1 << grain_bits Example: grain = 8 # 64 bit (8 bytes) grain_bits = fls_long(8) + 1 grain_bits = 4 + 1 = 5 grain = 1 << grain_bits grain = 1 << 5 = 32 Replace it with the correct calculation: grain_bits = fls_long(e->grain - 1); The example gives now: grain_bits = fls_long(8 - 1) grain_bits = fls_long(7) grain_bits = 3 grain = 1 << 3 = 8 Also, check if the hardware reports a reasonable grain != 0 and fallback with a warning to 1 byte granularity otherwise. [ bp: massage a bit. ] Signed-off-by: Robert Richter Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190624150758.6695-2-rrichter@marvell.com --- drivers/edac/edac_mc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 64922c8fa7e3..d899d86897d0 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1235,9 +1235,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, if (p > e->location) *(p - 1) = '\0'; - /* Report the error via the trace interface */ - grain_bits = fls_long(e->grain) + 1; + /* Sanity-check driver-supplied grain value. */ + if (WARN_ON_ONCE(!e->grain)) + e->grain = 1; + + grain_bits = fls_long(e->grain - 1); + /* Report the error via the trace interface */ if (IS_ENABLED(CONFIG_RAS)) trace_mc_event(type, e->msg, e->label, e->error_count, mci->mc_idx, e->top_layer, e->mid_layer, -- GitLab From 6b392e16307f967c6922522b04a77c76174a4296 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 3 Jul 2019 15:08:22 +0300 Subject: [PATCH 1769/7155] arm64: dts: imx8mm: Init rates and parents configs for clocks Add the initial configuration for clocks that need default parent and rate setting. This is based on the vendor tree clock provider parents and rates configuration except this is doing the setup in dts rather than using clock consumer API in a clock provider driver. Signed-off-by: Abel Vesa Acked-by: Daniel Baluta Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 232a7412755a..b0304872c408 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -451,6 +451,18 @@ <&clk_ext3>, <&clk_ext4>; clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4"; + assigned-clocks = <&clk IMX8MM_CLK_NOC>, + <&clk IMX8MM_CLK_AUDIO_AHB>, + <&clk IMX8MM_CLK_IPG_AUDIO_ROOT>, + <&clk IMX8MM_SYS_PLL3>, + <&clk IMX8MM_VIDEO_PLL1>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL3_OUT>, + <&clk IMX8MM_SYS_PLL1_800M>; + assigned-clock-rates = <0>, + <400000000>, + <400000000>, + <750000000>, + <594000000>; }; src: reset-controller@30390000 { -- GitLab From 26c2f55a6a15153eed977e94dd42f8565b159526 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 2 Jul 2019 09:43:59 +0800 Subject: [PATCH 1770/7155] arm64: dts: imx8mq: Add gpio-ranges property Add "gpio-ranges" property to establish connections between GPIOs and PINs on i.MX8MQ pinctrl driver. Signed-off-by: Anson Huang Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 891ee7578c2d..9b82e944c6c7 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -288,6 +288,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 10 30>; }; gpio2: gpio@30210000 { @@ -300,6 +301,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 40 21>; }; gpio3: gpio@30220000 { @@ -312,6 +314,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 61 26>; }; gpio4: gpio@30230000 { @@ -324,6 +327,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 87 32>; }; gpio5: gpio@30240000 { @@ -336,6 +340,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 119 30>; }; tmu: tmu@30260000 { -- GitLab From 156263599e9e8956af86ebeba35a73f367d40af7 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 2 Jul 2019 09:44:00 +0800 Subject: [PATCH 1771/7155] arm64: dts: imx8mm: Add gpio-ranges property Add "gpio-ranges" property to establish connections between GPIOs and PINs on i.MX8MM pinctrl driver. Signed-off-by: Anson Huang Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index b0304872c408..0eb85561cfa3 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -295,6 +295,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 10 30>; }; gpio2: gpio@30210000 { @@ -307,6 +308,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 40 21>; }; gpio3: gpio@30220000 { @@ -319,6 +321,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 61 26>; }; gpio4: gpio@30230000 { @@ -331,6 +334,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 87 32>; }; gpio5: gpio@30240000 { @@ -343,6 +347,7 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 119 30>; }; wdog1: watchdog@30280000 { -- GitLab From 8b01840edcfcbc5d099996693f488875d0f6aba0 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Wed, 3 Jul 2019 15:23:26 +0800 Subject: [PATCH 1772/7155] arm64: dts: imx8mm: Remove setting for IMX8MM_CLK_USB_CORE_REF Since IMX8MM_CLK_USB_CORE_REF is not used at all, so remove the setting for it. Signed-off-by: Li Jun Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 0eb85561cfa3..a4cefae9d0a6 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -760,10 +760,8 @@ interrupts = ; clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>; clock-names = "usb1_ctrl_root_clk"; - assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>, - <&clk IMX8MM_CLK_USB_CORE_REF>; - assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>, - <&clk IMX8MM_SYS_PLL1_100M>; + assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; fsl,usbphy = <&usbphynop1>; fsl,usbmisc = <&usbmisc1 0>; status = "disabled"; @@ -781,10 +779,8 @@ interrupts = ; clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>; clock-names = "usb1_ctrl_root_clk"; - assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>, - <&clk IMX8MM_CLK_USB_CORE_REF>; - assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>, - <&clk IMX8MM_SYS_PLL1_100M>; + assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; fsl,usbphy = <&usbphynop2>; fsl,usbmisc = <&usbmisc2 0>; status = "disabled"; -- GitLab From ef4c47ab888af4da0a3b52562a3e60ab93e7bded Mon Sep 17 00:00:00 2001 From: Li Jun Date: Wed, 3 Jul 2019 15:23:27 +0800 Subject: [PATCH 1773/7155] arm64: dts: imx8mm-evk: enable usb1 and typec support USB1 port has typec connector with power delivery support: - Dual data role: host and device. - Dual power role: source and sink, prefer power sink. Signed-off-by: Li Jun Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm-evk.dts | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts index ee7f2b2fc1ff..fcfee8b1f6e3 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts @@ -5,6 +5,7 @@ /dts-v1/; +#include #include "imx8mm.dtsi" / { @@ -115,6 +116,21 @@ status = "okay"; }; +&usbotg1 { + dr_mode = "otg"; + hnp-disable; + srp-disable; + adp-disable; + usb-role-switch; + status = "okay"; + + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&typec1_dr_sw>; + }; + }; +}; + &usdhc2 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; @@ -257,6 +273,42 @@ }; }; +&i2c2 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + ptn5110: tcpc@50 { + compatible = "nxp,ptn5110"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_typec1>; + reg = <0x50>; + interrupt-parent = <&gpio2>; + interrupts = <11 8>; + status = "okay"; + + port { + typec1_dr_sw: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + + typec1_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <15000000>; + self-powered; + }; + }; +}; + &iomuxc { pinctrl-names = "default"; @@ -299,6 +351,13 @@ >; }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3 + MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3 + >; + }; + pinctrl_pmic: pmicirq { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41 @@ -320,6 +379,12 @@ >; }; + pinctrl_typec1: typec1grp { + fsl,pins = < + MX8MM_IOMUXC_SD1_STROBE_GPIO2_IO11 0x159 + >; + }; + pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 -- GitLab From 1efe85c9056af0f20d8440a841bd89f4ec7ba735 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 4 Jul 2019 11:53:21 +0300 Subject: [PATCH 1774/7155] arm64: dts: imx8m: Add ddr-pmu nodes The same ddr perfomance counter IP from 8qxp is also available on imx8m series so add it to dts. Tested with `perf stat` and `memtester` on imx8mm-evk and obtained plausible results. Signed-off-by: Leonard Crestez Acked-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 7 +++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index a4cefae9d0a6..7e92717823c6 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -831,5 +831,12 @@ interrupt-controller; interrupts = ; }; + + ddr-pmu@3d800000 { + compatible = "fsl,imx8mm-ddr-pmu", "fsl,imx8m-ddr-pmu"; + reg = <0x3d800000 0x400000>; + interrupt-parent = <&gic>; + interrupts = ; + }; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 9b82e944c6c7..19805b15af21 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -1051,5 +1051,12 @@ interrupts = ; interrupt-parent = <&gic>; }; + + ddr-pmu@3d800000 { + compatible = "fsl,imx8mq-ddr-pmu", "fsl,imx8m-ddr-pmu"; + reg = <0x3d800000 0x400000>; + interrupt-parent = <&gic>; + interrupts = ; + }; }; }; -- GitLab From 46b29f4bd67e1007a2372abcfc48e41ab1d5bf7b Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Jul 2019 16:54:06 +0800 Subject: [PATCH 1775/7155] arm64: dts: imx8mm: Add "fsl,imx8mq-src" as src's fallback compatible i.MX8MM can reuse i.MX8MQ's src driver, add "fsl,imx8mq-src" as src's fallback compatible to enable it. Signed-off-by: Anson Huang Reviewed-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 7e92717823c6..2b1c45228664 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -471,7 +471,7 @@ }; src: reset-controller@30390000 { - compatible = "fsl,imx8mm-src", "syscon"; + compatible = "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon"; reg = <0x30390000 0x10000>; interrupts = ; #reset-cells = <1>; -- GitLab From cd7c2ddfda3629a18fcf6d20779bdcc73eda6bec Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Jun 2019 18:21:56 +0800 Subject: [PATCH 1776/7155] arm64: dts: imx8mm: Correct OPP table according to latest datasheet According to latest datasheet (Rev.0.2, 04/2019) from below links, 1.8GHz is ONLY available for consumer part, so the market segment bits for 1.8GHz opp should ONLY available for consumer part accordingly. https://www.nxp.com/docs/en/data-sheet/IMX8MMIEC.pdf https://www.nxp.com/docs/en/data-sheet/IMX8MMCEC.pdf Fixes: f403a26c865b (arm64: dts: imx8mm: Add cpu speed grading and all OPPs) Signed-off-by: Anson Huang Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 2b1c45228664..7bbdcebc6b57 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -116,8 +116,7 @@ opp-1800000000 { opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <1000000>; - /* Consumer only but rely on speed grading */ - opp-supported-hw = <0x8>, <0x7>; + opp-supported-hw = <0x8>, <0x3>; clock-latency-ns = <150000>; }; }; -- GitLab From 9eced3a2f224a62a233761e8af18c907c532e192 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Jun 2019 18:21:57 +0800 Subject: [PATCH 1777/7155] arm64: dts: imx8mq: Correct OPP table according to latest datasheet According to latest datasheet (Rev.1, 10/2018) from below links, in the consumer datasheet, 1.5GHz is mentioned as highest opp but depends on speed grading fuse, and in the industrial datasheet, 1.3GHz is mentioned as highest opp but depends on speed grading fuse. 1.5GHz and 1.3GHz opp use same voltage, so no need for consumer part to support 1.3GHz opp, with same voltage, CPU should run at highest frequency in order to go into idle as quick as possible, this can save power. That means for consumer part, 1GHz/1.5GHz are supported, for industrial part, 800MHz/1.3GHz are supported, and then check the speed grading fuse to limit the highest CPU frequency further. Correct the market segment bits in opp table to make them work according to datasheets. https://www.nxp.com/docs/en/data-sheet/IMX8MDQLQIEC.pdf https://www.nxp.com/docs/en/data-sheet/IMX8MDQLQCEC.pdf Fixes: 12629c5c3749 ("arm64: dts: imx8mq: Add cpu speed grading and all OPPs") Signed-off-by: Anson Huang Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 19805b15af21..e032eb9a7507 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -169,15 +169,14 @@ opp-1300000000 { opp-hz = /bits/ 64 <1300000000>; opp-microvolt = <1000000>; - opp-supported-hw = <0xc>, <0x7>; + opp-supported-hw = <0xc>, <0x4>; clock-latency-ns = <150000>; }; opp-1500000000 { opp-hz = /bits/ 64 <1500000000>; opp-microvolt = <1000000>; - /* Consumer only but rely on speed grading */ - opp-supported-hw = <0x8>, <0x7>; + opp-supported-hw = <0x8>, <0x3>; clock-latency-ns = <150000>; }; }; -- GitLab From 150736b88a7eab51b6950f179c0df4dedfe20bbf Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Jul 2019 12:56:12 +0800 Subject: [PATCH 1778/7155] arm64: dts: imx8mq: Add clock for TMU node i.MX8MQ has clock gate for TMU module, add clock info to TMU node for clock management. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index e032eb9a7507..178e3309e452 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -346,6 +346,7 @@ compatible = "fsl,imx8mq-tmu"; reg = <0x30260000 0x10000>; interrupt = ; + clocks = <&clk IMX8MQ_CLK_TMU_ROOT>; little-endian; fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>; fsl,tmu-calibration = <0x00000000 0x00000023 -- GitLab From 74bd5951dd357c8cce6e74dccb182afb68bb5720 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Wed, 10 Jul 2019 19:19:17 +0800 Subject: [PATCH 1779/7155] arm64: dts: imx8mq: correct usb controller clocks The correct clock for "bus_early", "ref", "suspend" should be: IMX8MQ_CLK_USB1_CTRL_ROOT, IMX8MQ_CLK_USB_CORE_REF, IMX8MQ_CLK_32K, especially we may need the right suspend clock rate to set register in controller driver. Signed-off-by: Li Jun Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 178e3309e452..d6c954bfd822 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -919,9 +919,9 @@ usb_dwc3_0: usb@38100000 { compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; reg = <0x38100000 0x10000>; - clocks = <&clk IMX8MQ_CLK_USB_BUS>, + clocks = <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>, <&clk IMX8MQ_CLK_USB_CORE_REF>, - <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>; + <&clk IMX8MQ_CLK_32K>; clock-names = "bus_early", "ref", "suspend"; assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>, <&clk IMX8MQ_CLK_USB_CORE_REF>; @@ -951,9 +951,9 @@ usb_dwc3_1: usb@38200000 { compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; reg = <0x38200000 0x10000>; - clocks = <&clk IMX8MQ_CLK_USB_BUS>, + clocks = <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>, <&clk IMX8MQ_CLK_USB_CORE_REF>, - <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>; + <&clk IMX8MQ_CLK_32K>; clock-names = "bus_early", "ref", "suspend"; assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>, <&clk IMX8MQ_CLK_USB_CORE_REF>; -- GitLab From 9ae303f9edde61ebc9870b5a486dfbd46f1037b1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 12 Jul 2019 15:59:48 +0200 Subject: [PATCH 1780/7155] arm64: dts: rdu3: add UCS1002 charge controller node Add the charge controller node. With the controller driver loaded the VBUS of the user USB socket is controlled exclusively via i2c with the GPIO controls ignored, so vbus-supply for the user USB port must be linked to the charge controller. Hog the previously used GPIO control to unconditionally enable VBUS until the driver is loaded. Signed-off-by: Lucas Stach Signed-off-by: Shawn Guo --- .../boot/dts/freescale/imx8mq-zii-ultra.dtsi | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi index 7a1706f969f0..af99473ada04 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi @@ -68,18 +68,6 @@ regulator-always-on; }; - reg_5p0_user_usb: regulator-5p0-user-usb { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_user_usb>; - vin-supply = <®_5p0_main>; - regulator-name = "5V_USER_USB"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio3 12 GPIO_ACTIVE_LOW>; - startup-delay-us = <1000>; - }; - reg_usdhc2_vmmc: regulator-vsd-3v3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_reg_usdhc2>; @@ -244,6 +232,13 @@ line-name = "usb-mode1"; }; + usb-pwr { + gpio-hog; + gpios = <12 GPIO_ACTIVE_LOW>; + output-high; + line-name = "usb-pwr-ctrl-en-n"; + }; + usb-mode2 { gpio-hog; gpios = <13 GPIO_ACTIVE_HIGH>; @@ -257,6 +252,17 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; + + ucs1002: charger@32 { + compatible = "microchip,ucs1002"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ucs1002>; + reg = <0x32>; + interrupt-parent = <&gpio3>; + interrupts = <17 IRQ_TYPE_EDGE_BOTH>, + <18 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "a_det", "alert"; + }; }; &i2c2 { @@ -428,7 +434,7 @@ }; &usb3_phy0 { - vbus-supply = <®_5p0_user_usb>; + vbus-supply = <&ucs1002>; status = "okay"; }; @@ -532,6 +538,7 @@ fsl,pins = < MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10 0x6 MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x6 + MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x6 MX8MQ_IOMUXC_NAND_DATA07_GPIO3_IO13 0x6 >; }; @@ -597,12 +604,6 @@ >; }; - pinctrl_reg_user_usb: reguserusbgrp { - fsl,pins = < - MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x6 - >; - }; - pinctrl_switch_irq: switchgrp { fsl,pins = < MX8MQ_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x41 @@ -630,6 +631,13 @@ >; }; + pinctrl_ucs1002: ucs1002grp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_WE_B_GPIO3_IO17 0x41 + MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18 0x41 + >; + }; + pinctrl_usbhub: usbhubgrp { fsl,pins = < MX8MQ_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x41 -- GitLab From bf95c394f5a32ffc5aa1184de3aa398e1d9d574a Mon Sep 17 00:00:00 2001 From: Pramod Kumar Date: Tue, 16 Jul 2019 13:43:31 +0000 Subject: [PATCH 1781/7155] arm64: dts: nxp: add ls1046a-frwy board support ls1046afrwy board is based on nxp ls1046a SoC. Board support's 4GB ddr memory, i2c, microSD card, serial console,qspi nor flash,ifc nand flash,qsgmii network interface, usb 3.0 and serdes interface to support two x1gen3 pcie interface. Signed-off-by: Vabhav Sharma Signed-off-by: Pramod Kumar Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../boot/dts/freescale/fsl-ls1046a-frwy.dts | 155 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index c043aca66572..23cfd2710196 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-frwy.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-qds.dtb diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts new file mode 100644 index 000000000000..3595be0f2527 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2019 NXP. + * + */ + +/dts-v1/; + +#include "fsl-ls1046a.dtsi" + +/ { + model = "LS1046A FRWY Board"; + compatible = "fsl,ls1046a-frwy", "fsl,ls1046a"; + + aliases { + serial0 = &duart0; + serial1 = &duart1; + serial2 = &duart2; + serial3 = &duart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + sb_3v3: regulator-sb3v3 { + compatible = "regulator-fixed"; + regulator-name = "LT8642SEV-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&duart0 { + status = "okay"; +}; + +&duart1 { + status = "okay"; +}; + +&duart2 { + status = "okay"; +}; + +&duart3 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + i2c-mux@77 { + compatible = "nxp,pca9546"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + power-monitor@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4c { + compatible = "nxp,sa56004"; + reg = <0x4c>; + vcc-supply = <&sb_3v3>; + }; + + rtc@51 { + compatible = "nxp,pcf2129"; + reg = <0x51>; + }; + + eeprom@52 { + compatible = "atmel,24c512"; + reg = <0x52>; + }; + + eeprom@53 { + compatible = "atmel,24c512"; + reg = <0x53>; + }; + + }; + }; +}; + +&ifc { + #address-cells = <2>; + #size-cells = <1>; + /* NAND Flash */ + ranges = <0x0 0x0 0x0 0x7e800000 0x00010000>; + status = "okay"; + + nand@0,0 { + compatible = "fsl,ifc-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x0 0x10000>; + }; + +}; + +#include "fsl-ls1046-post.dtsi" + +&fman0 { + ethernet@e0000 { + phy-handle = <&qsgmii_phy4>; + phy-connection-type = "qsgmii"; + }; + + ethernet@e8000 { + phy-handle = <&qsgmii_phy2>; + phy-connection-type = "qsgmii"; + }; + + ethernet@ea000 { + phy-handle = <&qsgmii_phy1>; + phy-connection-type = "qsgmii"; + }; + + ethernet@f2000 { + phy-handle = <&qsgmii_phy3>; + phy-connection-type = "qsgmii"; + }; + + mdio@fd000 { + qsgmii_phy1: ethernet-phy@1c { + reg = <0x1c>; + }; + + qsgmii_phy2: ethernet-phy@1d { + reg = <0x1d>; + }; + + qsgmii_phy3: ethernet-phy@1e { + reg = <0x1e>; + }; + + qsgmii_phy4: ethernet-phy@1f { + reg = <0x1f>; + }; + }; +}; -- GitLab From b5547e22be7298bbc8685c5becc7195be275e5d2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 18 Jul 2019 21:17:17 -0300 Subject: [PATCH 1782/7155] arm64: dts: imx8mm-evk: Remove invalid properties All these at803x properties are not documented anywhere, so just remove them. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm-evk.dts | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts index fcfee8b1f6e3..f7a15f3904c2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts @@ -90,9 +90,6 @@ ethphy0: ethernet-phy@0 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <0>; - at803x,led-act-blind-workaround; - at803x,eee-okay; - at803x,vddio-1p8v; }; }; }; -- GitLab From 56838644f9ddbaf8100051a7a7d5c5b0a028c3d0 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 19 Jul 2019 12:39:26 +0530 Subject: [PATCH 1783/7155] arm64: dts: freescale: Add support for i.MX8QXP AI_ML board Add support for i.MX8QXP AI_ML board from Einfochips. This board is one of the Consumer Edition boards of the 96Boards family based on i.MX8QXP SoC from NXP/Freescale. The initial support includes following peripherals which are tested and known to be working: 1. Debug serial via UART2 2. uSD 3. WiFi 4. Ethernet More information about this board can be found in Arrow website: https://www.arrow.com/en/products/imx8-ai-ml/arrow-development-tools Signed-off-by: Manivannan Sadhasivam Reviewed-by: Dong Aisheng Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../boot/dts/freescale/imx8qxp-ai_ml.dts | 249 ++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 23cfd2710196..2a88dae42af5 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -26,4 +26,5 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8qxp-ai_ml.dtb dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts new file mode 100644 index 000000000000..91eef9754101 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Einfochips + * Copyright 2019 Linaro Ltd. + */ + +/dts-v1/; + +#include "imx8qxp.dtsi" + +/ { + model = "Einfochips i.MX8QXP AI_ML"; + compatible = "einfochips,imx8qxp-ai_ml", "fsl,imx8qxp"; + + aliases { + serial1 = &adma_lpuart1; + serial2 = &adma_lpuart2; + serial3 = &adma_lpuart3; + }; + + chosen { + stdout-path = &adma_lpuart2; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x80000000>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + user-led1 { + label = "green:user1"; + gpios = <&lsio_gpio4 16 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + + user-led2 { + label = "green:user2"; + gpios = <&lsio_gpio0 6 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + }; + + user-led3 { + label = "green:user3"; + gpios = <&lsio_gpio0 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + + user-led4 { + label = "green:user4"; + gpios = <&lsio_gpio4 21 GPIO_ACTIVE_HIGH>; + panic-indicator; + linux,default-trigger = "none"; + }; + + wlan-active-led { + label = "yellow:wlan"; + gpios = <&lsio_gpio4 17 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + + bt-active-led { + label = "blue:bt"; + gpios = <&lsio_gpio4 18 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "hci0-power"; + default-state = "off"; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wifi_reg_on>; + reset-gpios = <&lsio_gpio3 24 GPIO_ACTIVE_LOW>; + }; +}; + +/* BT */ +&adma_lpuart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart0>; + uart-has-rtscts; + status = "okay"; +}; + +/* LS-UART0 */ +&adma_lpuart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart1>; + status = "okay"; +}; + +/* Debug */ +&adma_lpuart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart2>; + status = "okay"; +}; + +/* PCI-E UART */ +&adma_lpuart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart3>; + status = "okay"; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + }; +}; + +/* WiFi */ +&usdhc1 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + bus-width = <4>; + no-sd; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + status = "okay"; + + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; +}; + +/* SD */ +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + cd-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&iomuxc { + pinctrl_fec1: fec1grp { + fsl,pins = < + IMX8QXP_ENET0_MDC_CONN_ENET0_MDC 0x06000020 + IMX8QXP_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020 + IMX8QXP_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x06000020 + IMX8QXP_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x06000020 + IMX8QXP_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x06000020 + IMX8QXP_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x06000020 + IMX8QXP_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x06000020 + IMX8QXP_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x06000020 + IMX8QXP_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x06000020 + IMX8QXP_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x06000020 + IMX8QXP_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x06000020 + IMX8QXP_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x06000020 + IMX8QXP_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x06000020 + IMX8QXP_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x06000020 + >; + }; + + pinctrl_leds: ledsgrp{ + fsl,pins = < + IMX8QXP_ESAI0_TX2_RX3_LSIO_GPIO0_IO06 0x00000021 + IMX8QXP_ESAI0_TX3_RX2_LSIO_GPIO0_IO07 0x00000021 + IMX8QXP_EMMC0_DATA7_LSIO_GPIO4_IO16 0x00000021 + IMX8QXP_USDHC1_WP_LSIO_GPIO4_IO21 0x00000021 + IMX8QXP_EMMC0_STROBE_LSIO_GPIO4_IO17 0x00000021 + IMX8QXP_EMMC0_RESET_B_LSIO_GPIO4_IO18 0x00000021 + >; + }; + + pinctrl_lpuart0: lpuart0grp { + fsl,pins = < + IMX8QXP_UART0_RX_ADMA_UART0_RX 0X06000020 + IMX8QXP_UART0_TX_ADMA_UART0_TX 0X06000020 + IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020 + IMX8QXP_FLEXCAN0_RX_ADMA_UART0_RTS_B 0x06000020 + >; + }; + + pinctrl_lpuart1: lpuart1grp { + fsl,pins = < + IMX8QXP_UART1_RX_ADMA_UART1_RX 0X06000020 + IMX8QXP_UART1_TX_ADMA_UART1_TX 0X06000020 + >; + }; + + pinctrl_lpuart2: lpuart2grp { + fsl,pins = < + IMX8QXP_UART2_RX_ADMA_UART2_RX 0X06000020 + IMX8QXP_UART2_TX_ADMA_UART2_TX 0X06000020 + >; + }; + + pinctrl_lpuart3: lpuart3grp { + fsl,pins = < + IMX8QXP_FLEXCAN2_RX_ADMA_UART3_RX 0X06000020 + IMX8QXP_FLEXCAN2_TX_ADMA_UART3_TX 0X06000020 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041 + IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x00000021 + IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000021 + IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000021 + IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000021 + IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000021 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 + IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x00000021 + IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x00000021 + IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x00000021 + IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x00000021 + IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x00000021 + IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x00000021 + IMX8QXP_USDHC1_CD_B_LSIO_GPIO4_IO22 0x00000021 + >; + }; + + pinctrl_wifi_reg_on: wifiregongrp { + fsl,pins = < + IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 0x00000021 + >; + }; +}; -- GitLab From 3a3f06085fac791f3f949063c1da9fd244168ba1 Mon Sep 17 00:00:00 2001 From: Wen He Date: Fri, 19 Jul 2019 17:59:56 +0800 Subject: [PATCH 1784/7155] arm64: dts: ls1028a: Add optional property node for Mali DP500 This patch use the optional property node "arm,malidp-arqos-value" to can be dynamic configure QoS signaling. Signed-off-by: Wen He Reviewed-by: Liviu Dudau Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 7975519b4f56..aef5b06a98d5 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -554,6 +554,7 @@ clocks = <&dpclk>, <&aclk>, <&aclk>, <&pclk>; clock-names = "pxlclk", "mclk", "aclk", "pclk"; arm,malidp-output-port-lines = /bits/ 8 <8 8 8>; + arm,malidp-arqos-value = <0xd000d000>; port { dp0_out: endpoint { -- GitLab From d04fd0b423f40643209e7ee9261692a32964326f Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 22 Jul 2019 16:28:23 +0800 Subject: [PATCH 1785/7155] arm64: dts: imx8qxp: add lpuart baud clock Add imx8qxp lpuart baud clock. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi index 05fa0b7f36bb..21bdd4d00f91 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi @@ -209,8 +209,9 @@ reg = <0x5a060000 0x1000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adma_lpcg IMX_ADMA_LPCG_UART0_BAUD_CLK>; - clock-names = "ipg"; + clocks = <&adma_lpcg IMX_ADMA_LPCG_UART0_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_UART0_BAUD_CLK>; + clock-names = "ipg", "baud"; power-domains = <&pd IMX_SC_R_UART_0>; status = "disabled"; }; @@ -220,8 +221,9 @@ reg = <0x5a070000 0x1000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adma_lpcg IMX_ADMA_LPCG_UART1_BAUD_CLK>; - clock-names = "ipg"; + clocks = <&adma_lpcg IMX_ADMA_LPCG_UART1_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_UART1_BAUD_CLK>; + clock-names = "ipg", "baud"; power-domains = <&pd IMX_SC_R_UART_1>; status = "disabled"; }; @@ -231,8 +233,9 @@ reg = <0x5a080000 0x1000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adma_lpcg IMX_ADMA_LPCG_UART2_BAUD_CLK>; - clock-names = "ipg"; + clocks = <&adma_lpcg IMX_ADMA_LPCG_UART2_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_UART2_BAUD_CLK>; + clock-names = "ipg", "baud"; power-domains = <&pd IMX_SC_R_UART_2>; status = "disabled"; }; @@ -242,8 +245,9 @@ reg = <0x5a090000 0x1000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adma_lpcg IMX_ADMA_LPCG_UART3_BAUD_CLK>; - clock-names = "ipg"; + clocks = <&adma_lpcg IMX_ADMA_LPCG_UART3_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_UART3_BAUD_CLK>; + clock-names = "ipg", "baud"; power-domains = <&pd IMX_SC_R_UART_3>; status = "disabled"; }; -- GitLab From adc898e3d11ab2c28c760a05b40b8f2372dc44f5 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 22 Jul 2019 16:28:24 +0800 Subject: [PATCH 1786/7155] arm64: dts: imx8qxp: add serial alias Add i.MX8QXP serial alias for lpuart ports. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi index 21bdd4d00f91..4402b2ed2642 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi @@ -30,6 +30,9 @@ mmc2 = &usdhc3; mu1 = &lsio_mu1; serial0 = &adma_lpuart0; + serial1 = &adma_lpuart1; + serial2 = &adma_lpuart2; + serial3 = &adma_lpuart3; }; cpus { -- GitLab From 356c27227b3b6aa824dcf11ffe632095e3cffe8a Mon Sep 17 00:00:00 2001 From: Richard Hu Date: Mon, 22 Jul 2019 13:27:29 +0300 Subject: [PATCH 1787/7155] arm64: dts: fsl: pico-pi: Add a device tree for the PICO-PI-IMX8M TechNexion PICO-PI-IMX8M-DEV evaluation and development kit based on NXP i.MX8M Quad applications processor. Datasheet can be found at: https://s3.us-east-2.amazonaws.com/technexion/datasheets/picopiimx8m.pdf The current level of support yields a working console and is able to boot userspace from NFS or init ramdisk. Additional subsystems that are active : - Ethernet - USB Cc: Daniel Baluta Signed-off-by: Richard Hu Signed-off-by: Andra Danciu Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../boot/dts/freescale/imx8mq-pico-pi.dts | 413 ++++++++++++++++++ 2 files changed, 414 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 2a88dae42af5..9efa96924c69 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -24,6 +24,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb dtb-$(CONFIG_ARCH_MXC) += imx8qxp-ai_ml.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts new file mode 100644 index 000000000000..8a4aee2348ee --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Wandboard, Org. + * Copyright 2017 NXP + * + * Author: Richard Hu + */ + +/dts-v1/; + +#include "imx8mq.dtsi" + +/ { + model = "TechNexion PICO-PI-8M"; + compatible = "technexion,pico-pi-imx8m", "fsl,imx8mq"; + + chosen { + stdout-path = &uart1; + }; + + pmic_osc: clock-pmic { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "pmic_osc"; + }; + + reg_usb_otg_vbus: regulator-usb-otg-vbus { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_otg_vbus>; + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 14 GPIO_ACTIVE_LOW>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1 &pinctrl_enet_3v3>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic: pmic@4b { + reg = <0x4b>; + compatible = "rohm,bd71837"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pmic>; + clocks = <&pmic_osc>; + clock-names = "osc"; + clock-output-names = "pmic_clk"; + interrupt-parent = <&gpio1>; + interrupts = <3 GPIO_ACTIVE_LOW>; + interrupt-names = "irq"; + + regulators { + buck1: BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + regulator-ramp-delay = <1250>; + rohm,dvs-run-voltage = <900000>; + rohm,dvs-idle-voltage = <850000>; + rohm,dvs-suspend-voltage = <800000>; + }; + + buck2: BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + regulator-ramp-delay = <1250>; + rohm,dvs-run-voltage = <1000000>; + rohm,dvs-idle-voltage = <900000>; + }; + + buck3: BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + rohm,dvs-run-voltage = <1000000>; + }; + + buck4: BUCK4 { + regulator-name = "buck4"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + rohm,dvs-run-voltage = <1000000>; + }; + + buck5: BUCK5 { + regulator-name = "buck5"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1350000>; + regulator-boot-on; + }; + + buck6: BUCK6 { + regulator-name = "buck6"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + buck7: BUCK7 { + regulator-name = "buck7"; + regulator-min-microvolt = <1605000>; + regulator-max-microvolt = <1995000>; + regulator-boot-on; + }; + + buck8: BUCK8 { + regulator-name = "buck8"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + + ldo1: LDO1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2: LDO2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3: LDO3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + ldo4: LDO4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + + ldo5: LDO5 { + regulator-name = "ldo5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + ldo6: LDO6 { + regulator-name = "ldo6"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + + ldo7: LDO7 { + regulator-name = "ldo7"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + }; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&uart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + bus-width = <4>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +&usb3_phy1 { + status = "okay"; +}; + +&usb_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_enet_3v3: enet3v3grp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19 + >; + }; + + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 + MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f + MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f + MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f + >; + }; + + pinctrl_otg_vbus: otgvbusgrp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* USB OTG VBUS Enable */ + >; + }; + + pinctrl_pmic: pmicirq { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 + MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49 + MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49 + MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x49 + MX8MQ_IOMUXC_UART4_TXD_UART2_DCE_RTS_B 0x49 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2grpgpio { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x85 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; +}; -- GitLab From 546d92d34f3c60e0165f405ce2156d23f29aeca1 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 22 Jul 2019 13:30:43 +0300 Subject: [PATCH 1788/7155] arm64: dts: add the console node for DPAA2 platforms Add the console device tree node for the following DPAA2 based platforms: LS1088A, LS2080A, LS2088A and LX2160A. Signed-off-by: Ioana Ciornei Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 5 +++++ arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 5 +++++ arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index dacd8cf03a7f..20f5ebd74200 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -609,6 +609,11 @@ ; }; + console@8340020 { + compatible = "fsl,dpaa2-console"; + reg = <0x00000000 0x08340020 0 0x2>; + }; + ptp-timer@8b95000 { compatible = "fsl,dpaa2-ptp"; reg = <0x0 0x8b95000 0x0 0x100>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi index 3ace91945b72..64101c9962ce 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi @@ -321,6 +321,11 @@ }; }; + console@8340020 { + compatible = "fsl,dpaa2-console"; + reg = <0x00000000 0x08340020 0 0x2>; + }; + ptp-timer@8b95000 { compatible = "fsl,dpaa2-ptp"; reg = <0x0 0x8b95000 0x0 0x100>; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index e6fdba39453c..4720a8e7304c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -848,6 +848,11 @@ dma-coherent; }; + console@8340020 { + compatible = "fsl,dpaa2-console"; + reg = <0x00000000 0x08340020 0 0x2>; + }; + ptp-timer@8b95000 { compatible = "fsl,dpaa2-ptp"; reg = <0x0 0x8b95000 0x0 0x100>; -- GitLab From 66f1f58055a4d3a25b9fcb93c2a3c894092094aa Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Wed, 29 May 2019 16:32:54 +0800 Subject: [PATCH 1789/7155] arm64: dts: ls1088a: Revise gpio registers to little-endian Since fsl-ls1088a Soc GPIO registers are used as little endian, the patch adds the little-endian attribute to each gpio node. Signed-off-by: Chuanhua Han Acked-by: Li Yang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index 20f5ebd74200..dfbead405783 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -272,6 +272,7 @@ compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; + little-endian; gpio-controller; #gpio-cells = <2>; interrupt-controller; @@ -282,6 +283,7 @@ compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; + little-endian; gpio-controller; #gpio-cells = <2>; interrupt-controller; @@ -292,6 +294,7 @@ compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; + little-endian; gpio-controller; #gpio-cells = <2>; interrupt-controller; @@ -302,6 +305,7 @@ compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2330000 0x0 0x10000>; interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; + little-endian; gpio-controller; #gpio-cells = <2>; interrupt-controller; -- GitLab From db4cfe2fef509cf46c4de4869104eb47347436e6 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 9 Jul 2019 16:00:14 +0800 Subject: [PATCH 1790/7155] arm64: dts: imx8mq: Add opp-suspend property to OPP table Add opp-suspend property to each OPP, the of opp core will select the OPP HW supported and with highest rate to be suspend opp, it will speed up the suspend/resume process. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index d6c954bfd822..f5d4b12a5fa8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -156,6 +156,7 @@ /* Industrial only */ opp-supported-hw = <0xf>, <0x4>; clock-latency-ns = <150000>; + opp-suspend; }; opp-1000000000 { @@ -164,6 +165,7 @@ /* Consumer only */ opp-supported-hw = <0xe>, <0x3>; clock-latency-ns = <150000>; + opp-suspend; }; opp-1300000000 { @@ -171,6 +173,7 @@ opp-microvolt = <1000000>; opp-supported-hw = <0xc>, <0x4>; clock-latency-ns = <150000>; + opp-suspend; }; opp-1500000000 { @@ -178,6 +181,7 @@ opp-microvolt = <1000000>; opp-supported-hw = <0x8>, <0x3>; clock-latency-ns = <150000>; + opp-suspend; }; }; -- GitLab From 0d9df5815ccc9c5e4822b4e52e0a2da63e9c1adb Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 9 Jul 2019 16:00:15 +0800 Subject: [PATCH 1791/7155] arm64: dts: imx8mm: Add opp-suspend property to OPP table Add opp-suspend property to each OPP, the of opp core will select the OPP HW supported and with highest rate to be suspend opp, it will speed up the suspend/resume process. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 7bbdcebc6b57..e8560d15c130 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -104,6 +104,7 @@ opp-microvolt = <850000>; opp-supported-hw = <0xe>, <0x7>; clock-latency-ns = <150000>; + opp-suspend; }; opp-1600000000 { @@ -111,6 +112,7 @@ opp-microvolt = <900000>; opp-supported-hw = <0xc>, <0x7>; clock-latency-ns = <150000>; + opp-suspend; }; opp-1800000000 { @@ -118,6 +120,7 @@ opp-microvolt = <1000000>; opp-supported-hw = <0x8>, <0x3>; clock-latency-ns = <150000>; + opp-suspend; }; }; -- GitLab From 7d545e779a982d0b96939611db1bd8004f926ade Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Sat, 3 Aug 2019 17:50:13 +0530 Subject: [PATCH 1792/7155] arm64: dts: bitmain: Add reset controller support for BM1880 SoC Add reset controller support for Bitmain BM1880 SoC. This commit also adds reset support to UART peripherals. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Philipp Zabel --- arch/arm64/boot/dts/bitmain/bm1880.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/bitmain/bm1880.dtsi b/arch/arm64/boot/dts/bitmain/bm1880.dtsi index 7726fd4c6be6..cfa59a30bad4 100644 --- a/arch/arm64/boot/dts/bitmain/bm1880.dtsi +++ b/arch/arm64/boot/dts/bitmain/bm1880.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { compatible = "bitmain,bm1880"; @@ -92,6 +93,12 @@ compatible = "bitmain,bm1880-pinctrl"; reg = <0x50 0x4B0>; }; + + rst: reset-controller@c00 { + compatible = "bitmain,bm1880-reset"; + reg = <0xc00 0x8>; + #reset-cells = <1>; + }; }; gpio0: gpio@50027000 { @@ -154,6 +161,7 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; + resets = <&rst BM1880_RST_UART0_1_CLK>; status = "disabled"; }; @@ -163,6 +171,7 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; + resets = <&rst BM1880_RST_UART0_1_ACLK>; status = "disabled"; }; @@ -172,6 +181,7 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; + resets = <&rst BM1880_RST_UART2_3_CLK>; status = "disabled"; }; @@ -181,6 +191,7 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; + resets = <&rst BM1880_RST_UART2_3_ACLK>; status = "disabled"; }; }; -- GitLab From ca33f735b1195e9bafaa66f24dec40ea666e9840 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 16 May 2019 16:12:43 +0530 Subject: [PATCH 1793/7155] arm64: dts: bitmain: Modify pin controller memory map Earlier, the PWM registers were included as part of the pinctrl memory map, but this turned to be useless as the muxing is being handled by the SoC pin controller itself. Hence, this commit removes the pwm register mapping from the pinctrl node to make it more clean. Fixes: af2ff87de413 ("arm64: dts: bitmain: Add pinctrl support for BM1880 SoC") Signed-off-by: Manivannan Sadhasivam Acked-by: Linus Walleij --- arch/arm64/boot/dts/bitmain/bm1880.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/bitmain/bm1880.dtsi b/arch/arm64/boot/dts/bitmain/bm1880.dtsi index cfa59a30bad4..d65453f99a99 100644 --- a/arch/arm64/boot/dts/bitmain/bm1880.dtsi +++ b/arch/arm64/boot/dts/bitmain/bm1880.dtsi @@ -89,9 +89,9 @@ #size-cells = <1>; ranges = <0x0 0x0 0x50010000 0x1000>; - pinctrl: pinctrl@50 { + pinctrl: pinctrl@400 { compatible = "bitmain,bm1880-pinctrl"; - reg = <0x50 0x4B0>; + reg = <0x400 0x120>; }; rst: reset-controller@c00 { -- GitLab From 13f138d3fcbcb7d22b341522512844bf50cffd82 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 25 Jul 2019 10:44:12 -0300 Subject: [PATCH 1794/7155] ARM: dts: imx6qdl-nit6xlite: Remove invalid properties The "vqmmc-1-8-v" and "ocr-limit" properties are not documented anywhere, so just remove them. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi index 7a85116ef1d2..2418cf8f2317 100644 --- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi @@ -556,8 +556,6 @@ non-removable; vmmc-supply = <®_3p3v>; vqmmc-supply = <®_wlan_vmmc>; - vqmmc-1-8-v; - ocr-limit = <0x180>; /* 1.65v - 2.1v */ cap-power-off-card; keep-power-in-suspend; status = "okay"; -- GitLab From 2a44db130351877733938f0283b0dda9828a71b7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 27 Jul 2019 16:26:40 +0200 Subject: [PATCH 1795/7155] ARM: dts: imx: Cleanup style around assignment operator Use a space before and after assignment operator to have consistent style. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sll.dtsi | 4 ++-- arch/arm/boot/dts/imx6sx.dtsi | 4 ++-- arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi | 2 +- arch/arm/boot/dts/imx6ul.dtsi | 12 ++++++------ arch/arm/boot/dts/imx7d.dtsi | 4 ++-- arch/arm/boot/dts/imx7s.dtsi | 6 +++--- arch/arm/boot/dts/imx7ulp.dtsi | 8 ++++---- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index 365e591e7878..13c7ba7fa6bc 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -234,7 +234,7 @@ compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart"; reg = <0x02018000 0x4000>; - interrupts =; + interrupts = ; dmas = <&sdma 31 4 0>, <&sdma 32 4 0>; dma-names = "rx", "tx"; clocks = <&clks IMX6SLL_CLK_UART4_IPG>, @@ -801,7 +801,7 @@ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart"; reg = <0x021f4000 0x4000>; - interrupts =; + interrupts = ; dmas = <&sdma 33 4 0>, <&sdma 34 4 0>; dma-names = "rx", "tx"; clocks = <&clks IMX6SLL_CLK_UART5_IPG>, diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index fe00f9a8accd..531a52c1e987 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -926,8 +926,8 @@ <&clks IMX6SX_CLK_ENET_PTP>; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; - fsl,num-tx-queues=<3>; - fsl,num-rx-queues=<3>; + fsl,num-tx-queues = <3>; + fsl,num-rx-queues = <3>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi index 92bf91674056..41f3b7f62bbf 100644 --- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi @@ -69,7 +69,7 @@ &i2c1 { pinctrl-names = "default"; - pinctrl-0 =<&pinctrl_i2c1>; + pinctrl-0 = <&pinctrl_i2c1>; clock-frequency = <100000>; status = "okay"; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 6dff2784abe6..228d22013132 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -518,8 +518,8 @@ <&clks IMX6UL_CLK_ENET2_REF_125M>; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; - fsl,num-tx-queues=<1>; - fsl,num-rx-queues=<1>; + fsl,num-tx-queues = <1>; + fsl,num-rx-queues = <1>; status = "disabled"; }; @@ -853,8 +853,8 @@ <&clks IMX6UL_CLK_ENET_REF>; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; - fsl,num-tx-queues=<1>; - fsl,num-rx-queues=<1>; + fsl,num-tx-queues = <1>; + fsl,num-rx-queues = <1>; status = "disabled"; }; @@ -866,7 +866,7 @@ <&clks IMX6UL_CLK_USDHC1>, <&clks IMX6UL_CLK_USDHC1>; clock-names = "ipg", "ahb", "per"; - fsl,tuning-step= <2>; + fsl,tuning-step = <2>; fsl,tuning-start-tap = <20>; bus-width = <4>; status = "disabled"; @@ -881,7 +881,7 @@ <&clks IMX6UL_CLK_USDHC2>; clock-names = "ipg", "ahb", "per"; bus-width = <4>; - fsl,tuning-step= <2>; + fsl,tuning-step = <2>; fsl,tuning-start-tap = <20>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 42528d2812a2..9c8dd32cc035 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -147,8 +147,8 @@ <&clks IMX7D_ENET_PHY_REF_ROOT_CLK>; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; - fsl,num-tx-queues=<3>; - fsl,num-rx-queues=<3>; + fsl,num-tx-queues = <3>; + fsl,num-rx-queues = <3>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index c1a4fff5ceda..710f850e785c 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -151,7 +151,7 @@ compatible = "fsl,imx7d-tempmon"; interrupt-parent = <&gpc>; interrupts = ; - fsl,tempmon =<&anatop>; + fsl,tempmon = <&anatop>; nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>; nvmem-cell-names = "calib", "temp_grade"; @@ -1184,8 +1184,8 @@ <&clks IMX7D_ENET_PHY_REF_ROOT_CLK>; clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out"; - fsl,num-tx-queues=<3>; - fsl,num-rx-queues=<3>; + fsl,num-tx-queues = <3>; + fsl,num-rx-queues = <3>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi index f689ce596080..c7c96fe0c80a 100644 --- a/arch/arm/boot/dts/imx7ulp.dtsi +++ b/arch/arm/boot/dts/imx7ulp.dtsi @@ -229,12 +229,12 @@ clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>, <&scg1 IMX7ULP_CLK_NIC1_DIV>, <&pcc2 IMX7ULP_CLK_USDHC0>; - clock-names ="ipg", "ahb", "per"; + clock-names = "ipg", "ahb", "per"; assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC0>; assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>; bus-width = <4>; fsl,tuning-start-tap = <20>; - fsl,tuning-step= <2>; + fsl,tuning-step = <2>; status = "disabled"; }; @@ -245,12 +245,12 @@ clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>, <&scg1 IMX7ULP_CLK_NIC1_DIV>, <&pcc2 IMX7ULP_CLK_USDHC1>; - clock-names ="ipg", "ahb", "per"; + clock-names = "ipg", "ahb", "per"; assigned-clocks = <&pcc2 IMX7ULP_CLK_USDHC1>; assigned-clock-parents = <&scg1 IMX7ULP_CLK_NIC1_DIV>; bus-width = <4>; fsl,tuning-start-tap = <20>; - fsl,tuning-step= <2>; + fsl,tuning-step = <2>; status = "disabled"; }; -- GitLab From ba7372fbba5e3c592d4e646c22b2d4e63f60a2a2 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Sun, 28 Jul 2019 17:08:17 +0300 Subject: [PATCH 1796/7155] arm64: dts: imx8mq-evk: Unbypass audio_pll1 Making audio_pll1 parent of audio_pll1_bypass, will allow setting rates multiple of 8000 for children. After unbypass clk hierarchy looks like this: * osc_25m * audio_pll1 * audio_pll1_bypass * audio_pll1_out * sai2 * sai2_root_clk Signed-off-by: Daniel Baluta Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts index e3df9b8cd9ca..05958124f173 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts @@ -118,9 +118,9 @@ &sai2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai2>; - assigned-clocks = <&clk IMX8MQ_CLK_SAI2>; - assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>; - assigned-clock-rates = <24576000>; + assigned-clocks = <&clk IMX8MQ_AUDIO_PLL1_BYPASS>, <&clk IMX8MQ_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1>, <&clk IMX8MQ_AUDIO_PLL1_OUT>; + assigned-clock-rates = <0>, <24576000>; status = "okay"; }; -- GitLab From 2c1a3f4dc4b927d182f725c83e31bb055c9eb881 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Mon, 29 Jul 2019 16:23:16 +0200 Subject: [PATCH 1797/7155] ARM: dts: imx25-pdk: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-pdk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts index f8544a9e4633..05cccd12624c 100644 --- a/arch/arm/boot/dts/imx25-pdk.dts +++ b/arch/arm/boot/dts/imx25-pdk.dts @@ -76,8 +76,8 @@ bits-per-pixel = <16>; fsl,pcr = <0xfa208b80>; bus-width = <18>; - native-mode = <&wvga_timings>; display-timings { + native-mode = <&wvga_timings>; wvga_timings: 640x480 { hactive = <640>; vactive = <480>; -- GitLab From cd1b1264632a3fe739016843005e49e42c60be55 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 2 Aug 2019 14:20:28 +0200 Subject: [PATCH 1798/7155] arm64: defconfig: CONFIG_DRM_ETNAVIV=m For imx8 we want to enable etnaviv, let's enable it in defconfig, it will be useful to have it enabled for KernelCI boot and runtime testing. Signed-off-by: Christian Gmeiner Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 121aeb205247..8b03a22a3ab3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -534,6 +534,7 @@ CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_SII902X=m CONFIG_DRM_I2C_ADV7511=m CONFIG_DRM_VC4=m +CONFIG_DRM_ETNAVIV=m CONFIG_DRM_HISI_HIBMC=m CONFIG_DRM_HISI_KIRIN=m CONFIG_DRM_MESON=m -- GitLab From d81765d693db67ee9afab40b4476e205723defe3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 3 Aug 2019 15:49:40 +0200 Subject: [PATCH 1799/7155] ARM: dts: imx53: Update LCD panel node on M53Menlo Update the panel node with latest version of the panel used on the system. Add missing pincontrol phandle to the panel node. Signed-off-by: Marek Vasut Cc: Shawn Guo Cc: Fabio Estevam Cc: NXP Linux Team To: linux-arm-kernel@lists.infradead.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx53-m53menlo.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx53-m53menlo.dts b/arch/arm/boot/dts/imx53-m53menlo.dts index 10acc5331ba6..719ed5ca454a 100644 --- a/arch/arm/boot/dts/imx53-m53menlo.dts +++ b/arch/arm/boot/dts/imx53-m53menlo.dts @@ -54,7 +54,8 @@ }; panel { - compatible = "edt,etm070080dh6"; + compatible = "edt,etm0700g0dh6"; + pinctrl-0 = <&pinctrl_display_gpio>; enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; port { -- GitLab From 8c0bb7873815bf8c3c4dfb24e8ebf4fefb4c35d2 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Wed, 10 Jul 2019 12:05:59 +0200 Subject: [PATCH 1800/7155] netfilter: synproxy: rename mss synproxy_options field After introduce "mss_encode" field in the synproxy_options struct the field "mss" is a little confusing. It has been renamed to "mss_option". Signed-off-by: Fernando Fernandez Mancera Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_synproxy.h | 2 +- net/ipv4/netfilter/ipt_SYNPROXY.c | 4 ++-- net/ipv6/netfilter/ip6t_SYNPROXY.c | 4 ++-- net/netfilter/nf_synproxy_core.c | 8 ++++---- net/netfilter/nft_synproxy.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_synproxy.h b/include/net/netfilter/nf_conntrack_synproxy.h index 44513b93bd55..2f0171d24997 100644 --- a/include/net/netfilter/nf_conntrack_synproxy.h +++ b/include/net/netfilter/nf_conntrack_synproxy.h @@ -67,7 +67,7 @@ static inline struct synproxy_net *synproxy_pernet(struct net *net) struct synproxy_options { u8 options; u8 wscale; - u16 mss; + u16 mss_option; u16 mss_encode; u32 tsval; u32 tsecr; diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index 0e70f3f65f6f..748dc3ce58d3 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c @@ -36,8 +36,8 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par) opts.options |= XT_SYNPROXY_OPT_ECN; opts.options &= info->options; - opts.mss_encode = opts.mss; - opts.mss = info->mss; + opts.mss_encode = opts.mss_option; + opts.mss_option = info->mss; if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP) synproxy_init_timestamp_cookie(info, &opts); else diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 5cdb4a69d277..fd1f52a21bf1 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c @@ -36,8 +36,8 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) opts.options |= XT_SYNPROXY_OPT_ECN; opts.options &= info->options; - opts.mss_encode = opts.mss; - opts.mss = info->mss; + opts.mss_encode = opts.mss_option; + opts.mss_option = info->mss; if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP) synproxy_init_timestamp_cookie(info, &opts); else diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index c769462a839e..b0930d4aba22 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c @@ -56,7 +56,7 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, switch (opcode) { case TCPOPT_MSS: if (opsize == TCPOLEN_MSS) { - opts->mss = get_unaligned_be16(ptr); + opts->mss_option = get_unaligned_be16(ptr); opts->options |= NF_SYNPROXY_OPT_MSS; } break; @@ -115,7 +115,7 @@ synproxy_build_options(struct tcphdr *th, const struct synproxy_options *opts) if (options & NF_SYNPROXY_OPT_MSS) *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | - opts->mss); + opts->mss_option); if (options & NF_SYNPROXY_OPT_TIMESTAMP) { if (options & NF_SYNPROXY_OPT_SACK_PERM) @@ -642,7 +642,7 @@ synproxy_recv_client_ack(struct net *net, } this_cpu_inc(snet->stats->cookie_valid); - opts->mss = mss; + opts->mss_option = mss; opts->options |= NF_SYNPROXY_OPT_MSS; if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) @@ -1060,7 +1060,7 @@ synproxy_recv_client_ack_ipv6(struct net *net, } this_cpu_inc(snet->stats->cookie_valid); - opts->mss = mss; + opts->mss_option = mss; opts->options |= NF_SYNPROXY_OPT_MSS; if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c index 928e661d1517..db4c23f5dfcb 100644 --- a/net/netfilter/nft_synproxy.c +++ b/net/netfilter/nft_synproxy.c @@ -31,8 +31,8 @@ static void nft_synproxy_tcp_options(struct synproxy_options *opts, opts->options |= NF_SYNPROXY_OPT_ECN; opts->options &= priv->info.options; - opts->mss_encode = opts->mss; - opts->mss = info->mss; + opts->mss_encode = opts->mss_option; + opts->mss_option = info->mss; if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) synproxy_init_timestamp_cookie(info, opts); else -- GitLab From e84fb4b3666dabd3917952fb33588daa891a6ad3 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Tue, 23 Jul 2019 03:23:03 +0200 Subject: [PATCH 1801/7155] netfilter: conntrack: use shared sysctl constants Use shared sysctl variables for zero and one constants, as in commit eec4844fae7c ("proc/sysctl: add shared variables for range check") Fixes: 8f14c99c7eda ("netfilter: conntrack: limit sysctl setting for boolean options") Signed-off-by: Matteo Croce Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_standalone.c | 34 ++++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index e0d392cb3075..d97f4ea47cf3 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -511,8 +511,6 @@ static void nf_conntrack_standalone_fini_proc(struct net *net) /* Log invalid packets of a given protocol */ static int log_invalid_proto_min __read_mostly; static int log_invalid_proto_max __read_mostly = 255; -static int zero; -static int one = 1; /* size the user *wants to set */ static unsigned int nf_conntrack_htable_size_user __read_mostly; @@ -629,8 +627,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_LOG_INVALID] = { .procname = "nf_conntrack_log_invalid", @@ -654,8 +652,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_HELPER] = { .procname = "nf_conntrack_helper", @@ -663,8 +661,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #ifdef CONFIG_NF_CONNTRACK_EVENTS [NF_SYSCTL_CT_EVENTS] = { @@ -673,8 +671,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP @@ -684,8 +682,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif [NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC] = { @@ -759,16 +757,16 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_PROTO_TCP_LIBERAL] = { .procname = "nf_conntrack_tcp_be_liberal", .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS] = { .procname = "nf_conntrack_tcp_max_retrans", @@ -904,8 +902,8 @@ static struct ctl_table nf_ct_sysctl_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif #ifdef CONFIG_NF_CT_PROTO_GRE -- GitLab From 1b90af292e71b20d03b837d39406acfbdc5d4b2a Mon Sep 17 00:00:00 2001 From: Junwei Hu Date: Thu, 1 Aug 2019 00:03:30 +0800 Subject: [PATCH 1802/7155] ipvs: Improve robustness to the ipvs sysctl The ipvs module parse the user buffer and save it to sysctl, then check if the value is valid. invalid value occurs over a period of time. Here, I add a variable, struct ctl_table tmp, used to read the value from the user buffer, and save only when it is valid. I delete proc_do_sync_mode and use extra1/2 in table for the proc_dointvec_minmax call. Fixes: f73181c8288f ("ipvs: add support for sync threads") Signed-off-by: Junwei Hu Acked-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 69 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 060565e7d227..3d5922c47ec2 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1737,12 +1737,18 @@ proc_do_defense_mode(struct ctl_table *table, int write, int val = *valp; int rc; - rc = proc_dointvec(table, write, buffer, lenp, ppos); + struct ctl_table tmp = { + .data = &val, + .maxlen = sizeof(int), + .mode = table->mode, + }; + + rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); if (write && (*valp != val)) { - if ((*valp < 0) || (*valp > 3)) { - /* Restore the correct value */ - *valp = val; + if (val < 0 || val > 3) { + rc = -EINVAL; } else { + *valp = val; update_defense_level(ipvs); } } @@ -1756,33 +1762,20 @@ proc_do_sync_threshold(struct ctl_table *table, int write, int *valp = table->data; int val[2]; int rc; + struct ctl_table tmp = { + .data = &val, + .maxlen = table->maxlen, + .mode = table->mode, + }; - /* backup the value first */ memcpy(val, valp, sizeof(val)); - - rc = proc_dointvec(table, write, buffer, lenp, ppos); - if (write && (valp[0] < 0 || valp[1] < 0 || - (valp[0] >= valp[1] && valp[1]))) { - /* Restore the correct value */ - memcpy(valp, val, sizeof(val)); - } - return rc; -} - -static int -proc_do_sync_mode(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int *valp = table->data; - int val = *valp; - int rc; - - rc = proc_dointvec(table, write, buffer, lenp, ppos); - if (write && (*valp != val)) { - if ((*valp < 0) || (*valp > 1)) { - /* Restore the correct value */ - *valp = val; - } + rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); + if (write) { + if (val[0] < 0 || val[1] < 0 || + (val[0] >= val[1] && val[1])) + rc = -EINVAL; + else + memcpy(valp, val, sizeof(val)); } return rc; } @@ -1795,12 +1788,18 @@ proc_do_sync_ports(struct ctl_table *table, int write, int val = *valp; int rc; - rc = proc_dointvec(table, write, buffer, lenp, ppos); + struct ctl_table tmp = { + .data = &val, + .maxlen = sizeof(int), + .mode = table->mode, + }; + + rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); if (write && (*valp != val)) { - if (*valp < 1 || !is_power_of_2(*valp)) { - /* Restore the correct value */ + if (val < 1 || !is_power_of_2(val)) + rc = -EINVAL; + else *valp = val; - } } return rc; } @@ -1860,7 +1859,9 @@ static struct ctl_table vs_vars[] = { .procname = "sync_version", .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_do_sync_mode, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, { .procname = "sync_ports", -- GitLab From acda655fefae352a48eec87c8f8487de1608a48b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:34 -0700 Subject: [PATCH 1803/7155] selftests: Add nettest Add nettest - a simple program with an implementation for various networking APIs. nettest is used for tcp, udp and raw functional tests for both IPv4 and IPv6. Point of this command versus existing utilities: - controlled implementation of the APIs and the order in which they are called, - ability to verify ingress device, local and remote addresses, - timeout for controlled test length, - ability to discriminate a timeout from a system call failure, and - simplicity with test scripts. The command returns: 0 on success, 1 for any system call failure, and 2 on timeout. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/nettest.c | 1756 +++++++++++++++++++++++++ 2 files changed, 1757 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/net/nettest.c diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 1b24e36b4047..ba9ee36c9e94 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -12,7 +12,7 @@ TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_a TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh TEST_PROGS += tcp_fastopen_backup_key.sh TEST_PROGS_EXTENDED := in_netns.sh -TEST_GEN_FILES = socket +TEST_GEN_FILES = socket nettest TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite TEST_GEN_FILES += udpgso udpgso_bench_tx udpgso_bench_rx ip_defrag diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c new file mode 100644 index 000000000000..9278f8460d75 --- /dev/null +++ b/tools/testing/selftests/net/nettest.c @@ -0,0 +1,1756 @@ +// SPDX-License-Identifier: GPL-2.0 +/* nettest - used for functional tests of networking APIs + * + * Copyright (c) 2013-2019 David Ahern . All rights reserved. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef IPV6_UNICAST_IF +#define IPV6_UNICAST_IF 76 +#endif +#ifndef IPV6_MULTICAST_IF +#define IPV6_MULTICAST_IF 17 +#endif + +#define DEFAULT_PORT 12345 + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +struct sock_args { + /* local address */ + union { + struct in_addr in; + struct in6_addr in6; + } local_addr; + + /* remote address */ + union { + struct in_addr in; + struct in6_addr in6; + } remote_addr; + int scope_id; /* remote scope; v6 send only */ + + struct in_addr grp; /* multicast group */ + + unsigned int has_local_ip:1, + has_remote_ip:1, + has_grp:1, + has_expected_laddr:1, + has_expected_raddr:1, + bind_test_only:1; + + unsigned short port; + + int type; /* DGRAM, STREAM, RAW */ + int protocol; + int version; /* AF_INET/AF_INET6 */ + + int use_setsockopt; + int use_cmsg; + const char *dev; + int ifindex; + const char *password; + + /* expected addresses and device index for connection */ + int expected_ifindex; + + /* local address */ + union { + struct in_addr in; + struct in6_addr in6; + } expected_laddr; + + /* remote address */ + union { + struct in_addr in; + struct in6_addr in6; + } expected_raddr; +}; + +static int server_mode; +static unsigned int prog_timeout = 5; +static unsigned int interactive; +static int iter = 1; +static char *msg = "Hello world!"; +static int msglen; +static int quiet; +static int try_broadcast = 1; + +static char *timestamp(char *timebuf, int buflen) +{ + time_t now; + + now = time(NULL); + if (strftime(timebuf, buflen, "%T", localtime(&now)) == 0) { + memset(timebuf, 0, buflen); + strncpy(timebuf, "00:00:00", buflen-1); + } + + return timebuf; +} + +static void log_msg(const char *format, ...) +{ + char timebuf[64]; + va_list args; + + if (quiet) + return; + + fprintf(stdout, "%s %s:", + timestamp(timebuf, sizeof(timebuf)), + server_mode ? "server" : "client"); + va_start(args, format); + vfprintf(stdout, format, args); + va_end(args); + + fflush(stdout); +} + +static void log_error(const char *format, ...) +{ + char timebuf[64]; + va_list args; + + if (quiet) + return; + + fprintf(stderr, "%s %s:", + timestamp(timebuf, sizeof(timebuf)), + server_mode ? "server" : "client"); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fflush(stderr); +} + +static void log_err_errno(const char *fmt, ...) +{ + char timebuf[64]; + va_list args; + + if (quiet) + return; + + fprintf(stderr, "%s %s: ", + timestamp(timebuf, sizeof(timebuf)), + server_mode ? "server" : "client"); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, ": %d: %s\n", errno, strerror(errno)); + fflush(stderr); +} + +static void log_address(const char *desc, struct sockaddr *sa) +{ + char addrstr[64]; + + if (quiet) + return; + + if (sa->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *) sa; + + log_msg("%s %s:%d", + desc, + inet_ntop(AF_INET, &s->sin_addr, addrstr, + sizeof(addrstr)), + ntohs(s->sin_port)); + + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa; + + log_msg("%s [%s]:%d", + desc, + inet_ntop(AF_INET6, &s6->sin6_addr, addrstr, + sizeof(addrstr)), + ntohs(s6->sin6_port)); + } + + printf("\n"); + + fflush(stdout); +} + +static int tcp_md5sig(int sd, void *addr, socklen_t alen, const char *password) +{ + struct tcp_md5sig md5sig; + int keylen = password ? strlen(password) : 0; + int rc; + + memset(&md5sig, 0, sizeof(md5sig)); + memcpy(&md5sig.tcpm_addr, addr, alen); + md5sig.tcpm_keylen = keylen; + + if (keylen) + memcpy(md5sig.tcpm_key, password, keylen); + + rc = setsockopt(sd, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof(md5sig)); + if (rc < 0) { + /* ENOENT is harmless. Returned when a password is cleared */ + if (errno == ENOENT) + rc = 0; + else + log_err_errno("setsockopt(TCP_MD5SIG)"); + } + + return rc; +} + +static int tcp_md5_remote(int sd, struct sock_args *args) +{ + struct sockaddr_in sin = { + .sin_family = AF_INET, + }; + struct sockaddr_in6 sin6 = { + .sin6_family = AF_INET6, + }; + void *addr; + int alen; + + switch (args->version) { + case AF_INET: + sin.sin_port = htons(args->port); + sin.sin_addr = args->remote_addr.in; + addr = &sin; + alen = sizeof(sin); + break; + case AF_INET6: + sin6.sin6_port = htons(args->port); + sin6.sin6_addr = args->remote_addr.in6; + addr = &sin6; + alen = sizeof(sin6); + break; + default: + log_error("unknown address family\n"); + exit(1); + } + + if (tcp_md5sig(sd, addr, alen, args->password)) + return -1; + + return 0; +} + +static int get_ifidx(const char *ifname) +{ + struct ifreq ifdata; + int sd, rc; + + if (!ifname || *ifname == '\0') + return 0; + + memset(&ifdata, 0, sizeof(ifdata)); + + strcpy(ifdata.ifr_name, ifname); + + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + log_err_errno("socket failed"); + return 0; + } + + rc = ioctl(sd, SIOCGIFINDEX, (char *)&ifdata); + close(sd); + if (rc != 0) { + log_err_errno("ioctl(SIOCGIFINDEX) failed"); + return 0; + } + + return ifdata.ifr_ifindex; +} + +static int bind_to_device(int sd, const char *name) +{ + int rc; + + rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1); + if (rc < 0) + log_err_errno("setsockopt(SO_BINDTODEVICE)"); + + return rc; +} + +static int get_bind_to_device(int sd, char *name, size_t len) +{ + int rc; + socklen_t optlen = len; + + name[0] = '\0'; + rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen); + if (rc < 0) + log_err_errno("setsockopt(SO_BINDTODEVICE)"); + + return rc; +} + +static int check_device(int sd, struct sock_args *args) +{ + int ifindex = 0; + char name[32]; + + if (get_bind_to_device(sd, name, sizeof(name))) + *name = '\0'; + else + ifindex = get_ifidx(name); + + log_msg(" bound to device %s/%d\n", + *name ? name : "", ifindex); + + if (!args->expected_ifindex) + return 0; + + if (args->expected_ifindex != ifindex) { + log_error("Device index mismatch: expected %d have %d\n", + args->expected_ifindex, ifindex); + return 1; + } + + log_msg("Device index matches: expected %d have %d\n", + args->expected_ifindex, ifindex); + + return 0; +} + +static int set_pktinfo_v4(int sd) +{ + int one = 1; + int rc; + + rc = setsockopt(sd, SOL_IP, IP_PKTINFO, &one, sizeof(one)); + if (rc < 0 && rc != -ENOTSUP) + log_err_errno("setsockopt(IP_PKTINFO)"); + + return rc; +} + +static int set_recvpktinfo_v6(int sd) +{ + int one = 1; + int rc; + + rc = setsockopt(sd, SOL_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); + if (rc < 0 && rc != -ENOTSUP) + log_err_errno("setsockopt(IPV6_RECVPKTINFO)"); + + return rc; +} + +static int set_recverr_v4(int sd) +{ + int one = 1; + int rc; + + rc = setsockopt(sd, SOL_IP, IP_RECVERR, &one, sizeof(one)); + if (rc < 0 && rc != -ENOTSUP) + log_err_errno("setsockopt(IP_RECVERR)"); + + return rc; +} + +static int set_recverr_v6(int sd) +{ + int one = 1; + int rc; + + rc = setsockopt(sd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one)); + if (rc < 0 && rc != -ENOTSUP) + log_err_errno("setsockopt(IPV6_RECVERR)"); + + return rc; +} + +static int set_unicast_if(int sd, int ifindex, int version) +{ + int opt = IP_UNICAST_IF; + int level = SOL_IP; + int rc; + + ifindex = htonl(ifindex); + + if (version == AF_INET6) { + opt = IPV6_UNICAST_IF; + level = SOL_IPV6; + } + rc = setsockopt(sd, level, opt, &ifindex, sizeof(ifindex)); + if (rc < 0) + log_err_errno("setsockopt(IP_UNICAST_IF)"); + + return rc; +} + +static int set_multicast_if(int sd, int ifindex) +{ + struct ip_mreqn mreq = { .imr_ifindex = ifindex }; + int rc; + + rc = setsockopt(sd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)); + if (rc < 0) + log_err_errno("setsockopt(IP_MULTICAST_IF)"); + + return rc; +} + +static int set_membership(int sd, uint32_t grp, uint32_t addr, const char *dev) +{ + uint32_t if_addr = addr; + struct ip_mreqn mreq; + int rc; + + if (addr == htonl(INADDR_ANY) && !dev) { + log_error("Either local address or device needs to be given for multicast membership\n"); + return -1; + } + + mreq.imr_multiaddr.s_addr = grp; + mreq.imr_address.s_addr = if_addr; + mreq.imr_ifindex = dev ? get_ifidx(dev) : 0; + + rc = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (rc < 0) { + log_err_errno("setsockopt(IP_ADD_MEMBERSHIP)"); + return -1; + } + + return 0; +} + +static int set_broadcast(int sd) +{ + unsigned int one = 1; + int rc = 0; + + if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) != 0) { + log_err_errno("setsockopt(SO_BROADCAST)"); + rc = -1; + } + + return rc; +} + +static int set_reuseport(int sd) +{ + unsigned int one = 1; + int rc = 0; + + if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != 0) { + log_err_errno("setsockopt(SO_REUSEPORT)"); + rc = -1; + } + + return rc; +} + +static int set_reuseaddr(int sd) +{ + unsigned int one = 1; + int rc = 0; + + if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) { + log_err_errno("setsockopt(SO_REUSEADDR)"); + rc = -1; + } + + return rc; +} + +static int str_to_uint(const char *str, int min, int max, unsigned int *value) +{ + int number; + char *end; + + errno = 0; + number = (unsigned int) strtoul(str, &end, 0); + + /* entire string should be consumed by conversion + * and value should be between min and max + */ + if (((*end == '\0') || (*end == '\n')) && (end != str) && + (errno != ERANGE) && (min <= number) && (number <= max)) { + *value = number; + return 0; + } + + return -1; +} + +static int expected_addr_match(struct sockaddr *sa, void *expected, + const char *desc) +{ + char addrstr[64]; + int rc = 0; + + if (sa->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *) sa; + struct in_addr *exp_in = (struct in_addr *) expected; + + if (s->sin_addr.s_addr != exp_in->s_addr) { + log_error("%s address does not match expected %s", + desc, + inet_ntop(AF_INET, exp_in, + addrstr, sizeof(addrstr))); + rc = 1; + } + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa; + struct in6_addr *exp_in = (struct in6_addr *) expected; + + if (memcmp(&s6->sin6_addr, exp_in, sizeof(*exp_in))) { + log_error("%s address does not match expected %s", + desc, + inet_ntop(AF_INET6, exp_in, + addrstr, sizeof(addrstr))); + rc = 1; + } + } else { + log_error("%s address does not match expected - unknown family", + desc); + rc = 1; + } + + if (!rc) + log_msg("%s address matches expected\n", desc); + + return rc; +} + +static int show_sockstat(int sd, struct sock_args *args) +{ + struct sockaddr_in6 local_addr, remote_addr; + socklen_t alen = sizeof(local_addr); + struct sockaddr *sa; + const char *desc; + int rc = 0; + + desc = server_mode ? "server local:" : "client local:"; + sa = (struct sockaddr *) &local_addr; + if (getsockname(sd, sa, &alen) == 0) { + log_address(desc, sa); + + if (args->has_expected_laddr) { + rc = expected_addr_match(sa, &args->expected_laddr, + "local"); + } + } else { + log_err_errno("getsockname failed"); + } + + sa = (struct sockaddr *) &remote_addr; + desc = server_mode ? "server peer:" : "client peer:"; + if (getpeername(sd, sa, &alen) == 0) { + log_address(desc, sa); + + if (args->has_expected_raddr) { + rc |= expected_addr_match(sa, &args->expected_raddr, + "remote"); + } + } else { + log_err_errno("getpeername failed"); + } + + return rc; +} + +static int get_index_from_cmsg(struct msghdr *m) +{ + struct cmsghdr *cm; + int ifindex = 0; + char buf[64]; + + for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(m); + m->msg_controllen != 0 && cm; + cm = (struct cmsghdr *)CMSG_NXTHDR(m, cm)) { + + if (cm->cmsg_level == SOL_IP && + cm->cmsg_type == IP_PKTINFO) { + struct in_pktinfo *pi; + + pi = (struct in_pktinfo *)(CMSG_DATA(cm)); + inet_ntop(AF_INET, &pi->ipi_addr, buf, sizeof(buf)); + ifindex = pi->ipi_ifindex; + } else if (cm->cmsg_level == SOL_IPV6 && + cm->cmsg_type == IPV6_PKTINFO) { + struct in6_pktinfo *pi6; + + pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm)); + inet_ntop(AF_INET6, &pi6->ipi6_addr, buf, sizeof(buf)); + ifindex = pi6->ipi6_ifindex; + } + } + + if (ifindex) { + log_msg(" pktinfo: ifindex %d dest addr %s\n", + ifindex, buf); + } + return ifindex; +} + +static int send_msg_no_cmsg(int sd, void *addr, socklen_t alen) +{ + int err; + +again: + err = sendto(sd, msg, msglen, 0, addr, alen); + if (err < 0) { + if (errno == EACCES && try_broadcast) { + try_broadcast = 0; + if (!set_broadcast(sd)) + goto again; + errno = EACCES; + } + + log_err_errno("sendto failed"); + return 1; + } + + return 0; +} + +static int send_msg_cmsg(int sd, void *addr, socklen_t alen, + int ifindex, int version) +{ + unsigned char cmsgbuf[64]; + struct iovec iov[2]; + struct cmsghdr *cm; + struct msghdr m; + int err; + + iov[0].iov_base = msg; + iov[0].iov_len = msglen; + m.msg_iov = iov; + m.msg_iovlen = 1; + m.msg_name = (caddr_t)addr; + m.msg_namelen = alen; + + memset(cmsgbuf, 0, sizeof(cmsgbuf)); + cm = (struct cmsghdr *)cmsgbuf; + m.msg_control = (caddr_t)cm; + + if (version == AF_INET) { + struct in_pktinfo *pi; + + cm->cmsg_level = SOL_IP; + cm->cmsg_type = IP_PKTINFO; + cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + pi = (struct in_pktinfo *)(CMSG_DATA(cm)); + pi->ipi_ifindex = ifindex; + + m.msg_controllen = cm->cmsg_len; + + } else if (version == AF_INET6) { + struct in6_pktinfo *pi6; + + cm->cmsg_level = SOL_IPV6; + cm->cmsg_type = IPV6_PKTINFO; + cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + + pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm)); + pi6->ipi6_ifindex = ifindex; + + m.msg_controllen = cm->cmsg_len; + } + +again: + err = sendmsg(sd, &m, 0); + if (err < 0) { + if (errno == EACCES && try_broadcast) { + try_broadcast = 0; + if (!set_broadcast(sd)) + goto again; + errno = EACCES; + } + + log_err_errno("sendmsg failed"); + return 1; + } + + return 0; +} + + +static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args) +{ + if (args->type == SOCK_STREAM) { + if (write(sd, msg, msglen) < 0) { + log_err_errno("write failed sending msg to peer"); + return 1; + } + } else if (args->ifindex && args->use_cmsg) { + if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version)) + return 1; + } else { + if (send_msg_no_cmsg(sd, addr, alen)) + return 1; + } + + log_msg("Sent message:\n"); + log_msg(" %.24s%s\n", msg, msglen > 24 ? " ..." : ""); + + return 0; +} + +static int socket_read_dgram(int sd, struct sock_args *args) +{ + unsigned char addr[sizeof(struct sockaddr_in6)]; + struct sockaddr *sa = (struct sockaddr *) addr; + socklen_t alen = sizeof(addr); + struct iovec iov[2]; + struct msghdr m = { + .msg_name = (caddr_t)addr, + .msg_namelen = alen, + .msg_iov = iov, + .msg_iovlen = 1, + }; + unsigned char cmsgbuf[256]; + struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf; + char buf[16*1024]; + int ifindex; + int len; + + iov[0].iov_base = (caddr_t)buf; + iov[0].iov_len = sizeof(buf); + + memset(cmsgbuf, 0, sizeof(cmsgbuf)); + m.msg_control = (caddr_t)cm; + m.msg_controllen = sizeof(cmsgbuf); + + len = recvmsg(sd, &m, 0); + if (len == 0) { + log_msg("peer closed connection.\n"); + return 0; + } else if (len < 0) { + log_msg("failed to read message: %d: %s\n", + errno, strerror(errno)); + return -1; + } + + buf[len] = '\0'; + + log_address("Message from:", sa); + log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : ""); + + ifindex = get_index_from_cmsg(&m); + if (args->expected_ifindex) { + if (args->expected_ifindex != ifindex) { + log_error("Device index mismatch: expected %d have %d\n", + args->expected_ifindex, ifindex); + return -1; + } + log_msg("Device index matches: expected %d have %d\n", + args->expected_ifindex, ifindex); + } + + if (!interactive && server_mode) { + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa; + struct in6_addr *in6 = &s6->sin6_addr; + + if (IN6_IS_ADDR_V4MAPPED(in6)) { + const uint32_t *pa = (uint32_t *) &in6->s6_addr; + struct in_addr in4; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *) addr; + pa += 3; + in4.s_addr = *pa; + sin->sin_addr = in4; + sin->sin_family = AF_INET; + if (send_msg_cmsg(sd, addr, alen, + ifindex, AF_INET) < 0) + goto out_err; + } + } +again: + iov[0].iov_len = len; + + if (args->version == AF_INET6) { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa; + + if (args->dev) { + /* avoid PKTINFO conflicts with bindtodev */ + if (sendto(sd, buf, len, 0, + (void *) addr, alen) < 0) + goto out_err; + } else { + /* kernel is allowing scope_id to be set to VRF + * index for LLA. for sends to global address + * reset scope id + */ + s6->sin6_scope_id = ifindex; + if (sendmsg(sd, &m, 0) < 0) + goto out_err; + } + } else { + int err; + + err = sendmsg(sd, &m, 0); + if (err < 0) { + if (errno == EACCES && try_broadcast) { + try_broadcast = 0; + if (!set_broadcast(sd)) + goto again; + errno = EACCES; + } + goto out_err; + } + } + log_msg("Sent message:\n"); + log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : ""); + } + + return 1; +out_err: + log_err_errno("failed to send msg to peer"); + return -1; +} + +static int socket_read_stream(int sd) +{ + char buf[1024]; + int len; + + len = read(sd, buf, sizeof(buf)-1); + if (len == 0) { + log_msg("client closed connection.\n"); + return 0; + } else if (len < 0) { + log_msg("failed to read message\n"); + return -1; + } + + buf[len] = '\0'; + log_msg("Incoming message:\n"); + log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : ""); + + if (!interactive && server_mode) { + if (write(sd, buf, len) < 0) { + log_err_errno("failed to send buf"); + return -1; + } + log_msg("Sent message:\n"); + log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : ""); + } + + return 1; +} + +static int socket_read(int sd, struct sock_args *args) +{ + if (args->type == SOCK_STREAM) + return socket_read_stream(sd); + + return socket_read_dgram(sd, args); +} + +static int stdin_to_socket(int sd, int type, void *addr, socklen_t alen) +{ + char buf[1024]; + int len; + + if (fgets(buf, sizeof(buf), stdin) == NULL) + return 0; + + len = strlen(buf); + if (type == SOCK_STREAM) { + if (write(sd, buf, len) < 0) { + log_err_errno("failed to send buf"); + return -1; + } + } else { + int err; + +again: + err = sendto(sd, buf, len, 0, addr, alen); + if (err < 0) { + if (errno == EACCES && try_broadcast) { + try_broadcast = 0; + if (!set_broadcast(sd)) + goto again; + errno = EACCES; + } + log_err_errno("failed to send msg to peer"); + return -1; + } + } + log_msg("Sent message:\n"); + log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : ""); + + return 1; +} + +static void set_recv_attr(int sd, int version) +{ + if (version == AF_INET6) { + set_recvpktinfo_v6(sd); + set_recverr_v6(sd); + } else { + set_pktinfo_v4(sd); + set_recverr_v4(sd); + } +} + +static int msg_loop(int client, int sd, void *addr, socklen_t alen, + struct sock_args *args) +{ + struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL; + fd_set rfds; + int nfds; + int rc; + + if (args->type != SOCK_STREAM) + set_recv_attr(sd, args->version); + + if (msg) { + msglen = strlen(msg); + + /* client sends first message */ + if (client) { + if (send_msg(sd, addr, alen, args)) + return 1; + } + if (!interactive) { + ptval = &timeout; + if (!prog_timeout) + timeout.tv_sec = 5; + } + } + + nfds = interactive ? MAX(fileno(stdin), sd) + 1 : sd + 1; + while (1) { + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + if (interactive) + FD_SET(fileno(stdin), &rfds); + + rc = select(nfds, &rfds, NULL, NULL, ptval); + if (rc < 0) { + if (errno == EINTR) + continue; + + rc = 1; + log_err_errno("select failed"); + break; + } else if (rc == 0) { + log_error("Timed out waiting for response\n"); + rc = 2; + break; + } + + if (FD_ISSET(sd, &rfds)) { + rc = socket_read(sd, args); + if (rc < 0) { + rc = 1; + break; + } + if (rc == 0) + break; + } + + rc = 0; + + if (FD_ISSET(fileno(stdin), &rfds)) { + if (stdin_to_socket(sd, args->type, addr, alen) <= 0) + break; + } + + if (interactive) + continue; + + if (iter != -1) { + --iter; + if (iter == 0) + break; + } + + log_msg("Going into quiet mode\n"); + quiet = 1; + + if (client) { + if (send_msg(sd, addr, alen, args)) { + rc = 1; + break; + } + } + } + + return rc; +} + +static int msock_init(struct sock_args *args, int server) +{ + uint32_t if_addr = htonl(INADDR_ANY); + struct sockaddr_in laddr = { + .sin_family = AF_INET, + .sin_port = htons(args->port), + }; + int one = 1; + int sd; + + if (!server && args->has_local_ip) + if_addr = args->local_addr.in.s_addr; + + sd = socket(PF_INET, SOCK_DGRAM, 0); + if (sd < 0) { + log_err_errno("socket"); + return -1; + } + + if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, + (char *)&one, sizeof(one)) < 0) { + log_err_errno("Setting SO_REUSEADDR error"); + goto out_err; + } + + if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, + (char *)&one, sizeof(one)) < 0) + log_err_errno("Setting SO_BROADCAST error"); + + if (args->dev && bind_to_device(sd, args->dev) != 0) + goto out_err; + else if (args->use_setsockopt && + set_multicast_if(sd, args->ifindex)) + goto out_err; + + laddr.sin_addr.s_addr = if_addr; + + if (bind(sd, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) { + log_err_errno("bind failed"); + goto out_err; + } + + if (server && + set_membership(sd, args->grp.s_addr, + args->local_addr.in.s_addr, args->dev)) + goto out_err; + + return sd; +out_err: + close(sd); + return -1; +} + +static int msock_server(struct sock_args *args) +{ + return msock_init(args, 1); +} + +static int msock_client(struct sock_args *args) +{ + return msock_init(args, 0); +} + +static int bind_socket(int sd, struct sock_args *args) +{ + struct sockaddr_in serv_addr = { + .sin_family = AF_INET, + }; + struct sockaddr_in6 serv6_addr = { + .sin6_family = AF_INET6, + }; + void *addr; + socklen_t alen; + + if (!args->has_local_ip && args->type == SOCK_RAW) + return 0; + + switch (args->version) { + case AF_INET: + serv_addr.sin_port = htons(args->port); + serv_addr.sin_addr = args->local_addr.in; + addr = &serv_addr; + alen = sizeof(serv_addr); + break; + + case AF_INET6: + serv6_addr.sin6_port = htons(args->port); + serv6_addr.sin6_addr = args->local_addr.in6; + addr = &serv6_addr; + alen = sizeof(serv6_addr); + break; + + default: + log_error("Invalid address family\n"); + return -1; + } + + if (bind(sd, addr, alen) < 0) { + log_err_errno("error binding socket"); + return -1; + } + + return 0; +} + +static int lsock_init(struct sock_args *args) +{ + long flags; + int sd; + + sd = socket(args->version, args->type, args->protocol); + if (sd < 0) { + log_err_errno("Error opening socket"); + return -1; + } + + if (set_reuseaddr(sd) != 0) + goto err; + + if (set_reuseport(sd) != 0) + goto err; + + if (args->dev && bind_to_device(sd, args->dev) != 0) + goto err; + else if (args->use_setsockopt && + set_unicast_if(sd, args->ifindex, args->version)) + goto err; + + if (bind_socket(sd, args)) + goto err; + + if (args->bind_test_only) + goto out; + + if (args->type == SOCK_STREAM && listen(sd, 1) < 0) { + log_err_errno("listen failed"); + goto err; + } + + flags = fcntl(sd, F_GETFL); + if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) { + log_err_errno("Failed to set non-blocking option"); + goto err; + } + + if (fcntl(sd, F_SETFD, FD_CLOEXEC) < 0) + log_err_errno("Failed to set close-on-exec flag"); + +out: + return sd; + +err: + close(sd); + return -1; +} + +static int do_server(struct sock_args *args) +{ + struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL; + unsigned char addr[sizeof(struct sockaddr_in6)] = {}; + socklen_t alen = sizeof(addr); + int lsd, csd = -1; + + fd_set rfds; + int rc; + + if (prog_timeout) + ptval = &timeout; + + if (args->has_grp) + lsd = msock_server(args); + else + lsd = lsock_init(args); + + if (lsd < 0) + return 1; + + if (args->bind_test_only) { + close(lsd); + return 0; + } + + if (args->type != SOCK_STREAM) { + rc = msg_loop(0, lsd, (void *) addr, alen, args); + close(lsd); + return rc; + } + + if (args->password && tcp_md5_remote(lsd, args)) { + close(lsd); + return -1; + } + + while (1) { + log_msg("\n"); + log_msg("waiting for client connection.\n"); + FD_ZERO(&rfds); + FD_SET(lsd, &rfds); + + rc = select(lsd+1, &rfds, NULL, NULL, ptval); + if (rc == 0) { + rc = 2; + break; + } + + if (rc < 0) { + if (errno == EINTR) + continue; + + log_err_errno("select failed"); + break; + } + + if (FD_ISSET(lsd, &rfds)) { + + csd = accept(lsd, (void *) addr, &alen); + if (csd < 0) { + log_err_errno("accept failed"); + break; + } + + rc = show_sockstat(csd, args); + if (rc) + break; + + rc = check_device(csd, args); + if (rc) + break; + } + + rc = msg_loop(0, csd, (void *) addr, alen, args); + close(csd); + + if (!interactive) + break; + } + + close(lsd); + + return rc; +} + +static int wait_for_connect(int sd) +{ + struct timeval _tv = { .tv_sec = prog_timeout }, *tv = NULL; + fd_set wfd; + int val = 0, sz = sizeof(val); + int rc; + + FD_ZERO(&wfd); + FD_SET(sd, &wfd); + + if (prog_timeout) + tv = &_tv; + + rc = select(FD_SETSIZE, NULL, &wfd, NULL, tv); + if (rc == 0) { + log_error("connect timed out\n"); + return -2; + } else if (rc < 0) { + log_err_errno("select failed"); + return -3; + } + + if (getsockopt(sd, SOL_SOCKET, SO_ERROR, &val, (socklen_t *)&sz) < 0) { + log_err_errno("getsockopt(SO_ERROR) failed"); + return -4; + } + + if (val != 0) { + log_error("connect failed: %d: %s\n", val, strerror(val)); + return -1; + } + + return 0; +} + +static int connectsock(void *addr, socklen_t alen, struct sock_args *args) +{ + int sd, rc = -1; + long flags; + + sd = socket(args->version, args->type, args->protocol); + if (sd < 0) { + log_err_errno("Failed to create socket"); + return -1; + } + + flags = fcntl(sd, F_GETFL); + if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) { + log_err_errno("Failed to set non-blocking option"); + goto err; + } + + if (set_reuseport(sd) != 0) + goto err; + + if (args->dev && bind_to_device(sd, args->dev) != 0) + goto err; + else if (args->use_setsockopt && + set_unicast_if(sd, args->ifindex, args->version)) + goto err; + + if (args->has_local_ip && bind_socket(sd, args)) + goto err; + + if (args->type != SOCK_STREAM) + goto out; + + if (args->password && tcp_md5sig(sd, addr, alen, args->password)) + goto err; + + if (args->bind_test_only) + goto out; + + if (connect(sd, addr, alen) < 0) { + if (errno != EINPROGRESS) { + log_err_errno("Failed to connect to remote host"); + rc = -1; + goto err; + } + rc = wait_for_connect(sd); + if (rc < 0) + goto err; + } +out: + return sd; + +err: + close(sd); + return rc; +} + +static int do_client(struct sock_args *args) +{ + struct sockaddr_in sin = { + .sin_family = AF_INET, + }; + struct sockaddr_in6 sin6 = { + .sin6_family = AF_INET6, + }; + void *addr; + int alen; + int rc = 0; + int sd; + + if (!args->has_remote_ip && !args->has_grp) { + fprintf(stderr, "remote IP or multicast group not given\n"); + return 1; + } + + switch (args->version) { + case AF_INET: + sin.sin_port = htons(args->port); + if (args->has_grp) + sin.sin_addr = args->grp; + else + sin.sin_addr = args->remote_addr.in; + addr = &sin; + alen = sizeof(sin); + break; + case AF_INET6: + sin6.sin6_port = htons(args->port); + sin6.sin6_addr = args->remote_addr.in6; + sin6.sin6_scope_id = args->scope_id; + addr = &sin6; + alen = sizeof(sin6); + break; + } + + if (args->has_grp) + sd = msock_client(args); + else + sd = connectsock(addr, alen, args); + + if (sd < 0) + return -sd; + + if (args->bind_test_only) + goto out; + + if (args->type == SOCK_STREAM) { + rc = show_sockstat(sd, args); + if (rc != 0) + goto out; + } + + rc = msg_loop(1, sd, addr, alen, args); + +out: + close(sd); + + return rc; +} + +enum addr_type { + ADDR_TYPE_LOCAL, + ADDR_TYPE_REMOTE, + ADDR_TYPE_MCAST, + ADDR_TYPE_EXPECTED_LOCAL, + ADDR_TYPE_EXPECTED_REMOTE, +}; + +static int convert_addr(struct sock_args *args, const char *_str, + enum addr_type atype) +{ + int family = args->version; + struct in6_addr *in6; + struct in_addr *in; + const char *desc; + char *str, *dev; + void *addr; + int rc = 0; + + str = strdup(_str); + if (!str) + return -ENOMEM; + + switch (atype) { + case ADDR_TYPE_LOCAL: + desc = "local"; + addr = &args->local_addr; + break; + case ADDR_TYPE_REMOTE: + desc = "remote"; + addr = &args->remote_addr; + break; + case ADDR_TYPE_MCAST: + desc = "mcast grp"; + addr = &args->grp; + break; + case ADDR_TYPE_EXPECTED_LOCAL: + desc = "expected local"; + addr = &args->expected_laddr; + break; + case ADDR_TYPE_EXPECTED_REMOTE: + desc = "expected remote"; + addr = &args->expected_raddr; + break; + default: + log_error("unknown address type"); + exit(1); + } + + switch (family) { + case AF_INET: + in = (struct in_addr *) addr; + if (str) { + if (inet_pton(AF_INET, str, in) == 0) { + log_error("Invalid %s IP address\n", desc); + rc = -1; + goto out; + } + } else { + in->s_addr = htonl(INADDR_ANY); + } + break; + + case AF_INET6: + dev = strchr(str, '%'); + if (dev) { + *dev = '\0'; + dev++; + } + + in6 = (struct in6_addr *) addr; + if (str) { + if (inet_pton(AF_INET6, str, in6) == 0) { + log_error("Invalid %s IPv6 address\n", desc); + rc = -1; + goto out; + } + } else { + *in6 = in6addr_any; + } + if (dev) { + args->scope_id = get_ifidx(dev); + if (args->scope_id < 0) { + log_error("Invalid scope on %s IPv6 address\n", + desc); + rc = -1; + goto out; + } + } + break; + + default: + log_error("Invalid address family\n"); + } + +out: + free(str); + return rc; +} + +static char *random_msg(int len) +{ + int i, n = 0, olen = len + 1; + char *m; + + if (len <= 0) + return NULL; + + m = malloc(olen); + if (!m) + return NULL; + + while (len > 26) { + i = snprintf(m + n, olen - n, "%.26s", + "abcdefghijklmnopqrstuvwxyz"); + n += i; + len -= i; + } + i = snprintf(m + n, olen - n, "%.*s", len, + "abcdefghijklmnopqrstuvwxyz"); + return m; +} + +#define GETOPT_STR "sr:l:p:t:g:P:DRn:M:d:SCi6L:0:1:2:Fbq" + +static void print_usage(char *prog) +{ + printf( + "usage: %s OPTS\n" + "Required:\n" + " -r addr remote address to connect to (client mode only)\n" + " -p port port to connect to (client mode)/listen on (server mode)\n" + " (default: %d)\n" + " -s server mode (default: client mode)\n" + " -t timeout seconds (default: none)\n" + "\n" + "Optional:\n" + " -F Restart server loop\n" + " -6 IPv6 (default is IPv4)\n" + " -P proto protocol for socket: icmp, ospf (default: none)\n" + " -D|R datagram (D) / raw (R) socket (default stream)\n" + " -l addr local address to bind to\n" + "\n" + " -d dev bind socket to given device name\n" + " -S use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n" + " to set device binding\n" + " -C use cmsg and IP_PKTINFO to specify device binding\n" + "\n" + " -L len send random message of given length\n" + " -n num number of times to send message\n" + "\n" + " -M password use MD5 sum protection\n" + " -g grp multicast group (e.g., 239.1.1.1)\n" + " -i interactive mode (default is echo and terminate)\n" + "\n" + " -0 addr Expected local address\n" + " -1 addr Expected remote address\n" + " -2 dev Expected device name (or index) to receive packet\n" + "\n" + " -b Bind test only.\n" + " -q Be quiet. Run test without printing anything.\n" + , prog, DEFAULT_PORT); +} + +int main(int argc, char *argv[]) +{ + struct sock_args args = { + .version = AF_INET, + .type = SOCK_STREAM, + .port = DEFAULT_PORT, + }; + struct protoent *pe; + unsigned int tmp; + int forever = 0; + + /* process inputs */ + extern char *optarg; + int rc = 0; + + /* + * process input args + */ + + while ((rc = getopt(argc, argv, GETOPT_STR)) != -1) { + switch (rc) { + case 's': + server_mode = 1; + break; + case 'F': + forever = 1; + break; + case 'l': + args.has_local_ip = 1; + if (convert_addr(&args, optarg, ADDR_TYPE_LOCAL) < 0) + return 1; + break; + case 'r': + args.has_remote_ip = 1; + if (convert_addr(&args, optarg, ADDR_TYPE_REMOTE) < 0) + return 1; + break; + case 'p': + if (str_to_uint(optarg, 1, 65535, &tmp) != 0) { + fprintf(stderr, "Invalid port\n"); + return 1; + } + args.port = (unsigned short) tmp; + break; + case 't': + if (str_to_uint(optarg, 0, INT_MAX, + &prog_timeout) != 0) { + fprintf(stderr, "Invalid timeout\n"); + return 1; + } + break; + case 'D': + args.type = SOCK_DGRAM; + break; + case 'R': + args.type = SOCK_RAW; + args.port = 0; + break; + case 'P': + pe = getprotobyname(optarg); + if (pe) { + args.protocol = pe->p_proto; + } else { + if (str_to_uint(optarg, 0, 0xffff, &tmp) != 0) { + fprintf(stderr, "Invalid potocol\n"); + return 1; + } + args.protocol = tmp; + } + break; + case 'n': + iter = atoi(optarg); + break; + case 'L': + msg = random_msg(atoi(optarg)); + break; + case 'M': + args.password = optarg; + break; + case 'S': + args.use_setsockopt = 1; + break; + case 'C': + args.use_cmsg = 1; + break; + case 'd': + args.dev = optarg; + args.ifindex = get_ifidx(optarg); + if (args.ifindex < 0) { + fprintf(stderr, "Invalid device name\n"); + return 1; + } + break; + case 'i': + interactive = 1; + break; + case 'g': + args.has_grp = 1; + if (convert_addr(&args, optarg, ADDR_TYPE_MCAST) < 0) + return 1; + args.type = SOCK_DGRAM; + break; + case '6': + args.version = AF_INET6; + break; + case 'b': + args.bind_test_only = 1; + break; + case '0': + args.has_expected_laddr = 1; + if (convert_addr(&args, optarg, + ADDR_TYPE_EXPECTED_LOCAL)) + return 1; + break; + case '1': + args.has_expected_raddr = 1; + if (convert_addr(&args, optarg, + ADDR_TYPE_EXPECTED_REMOTE)) + return 1; + + break; + case '2': + if (str_to_uint(optarg, 0, 0x7ffffff, &tmp) != 0) { + tmp = get_ifidx(optarg); + if (tmp < 0) { + fprintf(stderr, + "Invalid device index\n"); + return 1; + } + } + args.expected_ifindex = (int)tmp; + break; + case 'q': + quiet = 1; + break; + default: + print_usage(argv[0]); + return 1; + } + } + + if (args.password && + (!args.has_remote_ip || args.type != SOCK_STREAM)) { + log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n"); + return 1; + } + + if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) { + fprintf(stderr, "Device binding not specified\n"); + return 1; + } + if (args.use_setsockopt || args.use_cmsg) + args.dev = NULL; + + if (iter == 0) { + fprintf(stderr, "Invalid number of messages to send\n"); + return 1; + } + + if (args.type == SOCK_STREAM && !args.protocol) + args.protocol = IPPROTO_TCP; + if (args.type == SOCK_DGRAM && !args.protocol) + args.protocol = IPPROTO_UDP; + + if ((args.type == SOCK_STREAM || args.type == SOCK_DGRAM) && + args.port == 0) { + fprintf(stderr, "Invalid port number\n"); + return 1; + } + + if (!server_mode && !args.has_grp && + !args.has_remote_ip && !args.has_local_ip) { + fprintf(stderr, + "Local (server mode) or remote IP (client IP) required\n"); + return 1; + } + + if (interactive) { + prog_timeout = 0; + msg = NULL; + } + + if (server_mode) { + do { + rc = do_server(&args); + } while (forever); + + return rc; + } + return do_client(&args); +} -- GitLab From 6f9d5cacfe07308fd4007ebdcb76861752d0a1ad Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:35 -0700 Subject: [PATCH 1804/7155] selftests: Setup for functional tests for fib and socket lookups Initial commit for functional test suite for fib and socket lookups. This commit contains the namespace setup, networking config, test options and other basic infrastructure. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/fcnal-test.sh | 520 ++++++++++++++++++++++ 2 files changed, 521 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/net/fcnal-test.sh diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index ba9ee36c9e94..70f2d6656170 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -10,7 +10,7 @@ TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_any.sh TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh -TEST_PROGS += tcp_fastopen_backup_key.sh +TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh TEST_PROGS_EXTENDED := in_netns.sh TEST_GEN_FILES = socket nettest TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh new file mode 100755 index 000000000000..22cfbd2fd09c --- /dev/null +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -0,0 +1,520 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2019 David Ahern . All rights reserved. +# +# IPv4 and IPv6 functional tests focusing on VRF and routing lookups +# for various permutations: +# 1. icmp, tcp, udp and netfilter +# 2. client, server, no-server +# 3. global address on interface +# 4. global address on 'lo' +# 5. remote and local traffic +# 6. VRF and non-VRF permutations +# +# Setup: +# ns-A | ns-B +# No VRF case: +# [ lo ] [ eth1 ]---|---[ eth1 ] [ lo ] +# remote address +# VRF case: +# [ red ]---[ eth1 ]---|---[ eth1 ] [ lo ] +# +# ns-A: +# eth1: 172.16.1.1/24, 2001:db8:1::1/64 +# lo: 127.0.0.1/8, ::1/128 +# 172.16.2.1/32, 2001:db8:2::1/128 +# red: 127.0.0.1/8, ::1/128 +# 172.16.3.1/32, 2001:db8:3::1/128 +# +# ns-B: +# eth1: 172.16.1.2/24, 2001:db8:1::2/64 +# lo2: 127.0.0.1/8, ::1/128 +# 172.16.2.2/32, 2001:db8:2::2/128 +# +# server / client nomenclature relative to ns-A + +VERBOSE=0 + +NSA_DEV=eth1 +NSB_DEV=eth1 +VRF=red +VRF_TABLE=1101 + +# IPv4 config +NSA_IP=172.16.1.1 +NSB_IP=172.16.1.2 +VRF_IP=172.16.3.1 + +# IPv6 config +NSA_IP6=2001:db8:1::1 +NSB_IP6=2001:db8:1::2 +VRF_IP6=2001:db8:3::1 + +NSA_LO_IP=172.16.2.1 +NSB_LO_IP=172.16.2.2 +NSA_LO_IP6=2001:db8:2::1 +NSB_LO_IP6=2001:db8:2::2 + +MCAST=ff02::1 +# set after namespace create +NSA_LINKIP6= +NSB_LINKIP6= + +NSA=ns-A +NSB=ns-B + +NSA_CMD="ip netns exec ${NSA}" +NSB_CMD="ip netns exec ${NSB}" + +which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping) + +################################################################################ +# utilities + +log_test() +{ + local rc=$1 + local expected=$2 + local msg="$3" + + [ "${VERBOSE}" = "1" ] && echo + + if [ ${rc} -eq ${expected} ]; then + nsuccess=$((nsuccess+1)) + printf "TEST: %-70s [ OK ]\n" "${msg}" + else + nfail=$((nfail+1)) + printf "TEST: %-70s [FAIL]\n" "${msg}" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then + echo + echo "hit enter to continue, 'q' to quit" + read a + [ "$a" = "q" ] && exit 1 + fi + fi + + if [ "${PAUSE}" = "yes" ]; then + echo + echo "hit enter to continue, 'q' to quit" + read a + [ "$a" = "q" ] && exit 1 + fi + + kill_procs +} + +log_test_addr() +{ + local addr=$1 + local rc=$2 + local expected=$3 + local msg="$4" + local astr + + astr=$(addr2str ${addr}) + log_test $rc $expected "$msg - ${astr}" +} + +log_section() +{ + echo + echo "###########################################################################" + echo "$*" + echo "###########################################################################" + echo +} + +log_subsection() +{ + echo + echo "#################################################################" + echo "$*" + echo +} + +log_start() +{ + # make sure we have no test instances running + kill_procs + + if [ "${VERBOSE}" = "1" ]; then + echo + echo "#######################################################" + fi +} + +log_debug() +{ + if [ "${VERBOSE}" = "1" ]; then + echo + echo "$*" + echo + fi +} + +show_hint() +{ + if [ "${VERBOSE}" = "1" ]; then + echo "HINT: $*" + echo + fi +} + +kill_procs() +{ + killall nettest ping ping6 >/dev/null 2>&1 + sleep 1 +} + +do_run_cmd() +{ + local cmd="$*" + local out + + if [ "$VERBOSE" = "1" ]; then + echo "COMMAND: ${cmd}" + fi + + out=$($cmd 2>&1) + rc=$? + if [ "$VERBOSE" = "1" -a -n "$out" ]; then + echo "$out" + fi + + return $rc +} + +run_cmd() +{ + do_run_cmd ${NSA_CMD} $* +} + +run_cmd_nsb() +{ + do_run_cmd ${NSB_CMD} $* +} + +setup_cmd() +{ + local cmd="$*" + local rc + + run_cmd ${cmd} + rc=$? + if [ $rc -ne 0 ]; then + # show user the command if not done so already + if [ "$VERBOSE" = "0" ]; then + echo "setup command: $cmd" + fi + echo "failed. stopping tests" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then + echo + echo "hit enter to continue" + read a + fi + exit $rc + fi +} + +setup_cmd_nsb() +{ + local cmd="$*" + local rc + + run_cmd_nsb ${cmd} + rc=$? + if [ $rc -ne 0 ]; then + # show user the command if not done so already + if [ "$VERBOSE" = "0" ]; then + echo "setup command: $cmd" + fi + echo "failed. stopping tests" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then + echo + echo "hit enter to continue" + read a + fi + exit $rc + fi +} + +# set sysctl values in NS-A +set_sysctl() +{ + echo "SYSCTL: $*" + echo + run_cmd sysctl -q -w $* +} + +################################################################################ +# Setup for tests + +addr2str() +{ + case "$1" in + 127.0.0.1) echo "loopback";; + ::1) echo "IPv6 loopback";; + + ${NSA_IP}) echo "ns-A IP";; + ${NSA_IP6}) echo "ns-A IPv6";; + ${NSA_LO_IP}) echo "ns-A loopback IP";; + ${NSA_LO_IP6}) echo "ns-A loopback IPv6";; + ${NSA_LINKIP6}|${NSA_LINKIP6}%*) echo "ns-A IPv6 LLA";; + + ${NSB_IP}) echo "ns-B IP";; + ${NSB_IP6}) echo "ns-B IPv6";; + ${NSB_LO_IP}) echo "ns-B loopback IP";; + ${NSB_LO_IP6}) echo "ns-B loopback IPv6";; + ${NSB_LINKIP6}|${NSB_LINKIP6}%*) echo "ns-B IPv6 LLA";; + + ${VRF_IP}) echo "VRF IP";; + ${VRF_IP6}) echo "VRF IPv6";; + + ${MCAST}%*) echo "multicast IP";; + + *) echo "unknown";; + esac +} + +get_linklocal() +{ + local ns=$1 + local dev=$2 + local addr + + addr=$(ip -netns ${ns} -6 -br addr show dev ${dev} | \ + awk '{ + for (i = 3; i <= NF; ++i) { + if ($i ~ /^fe80/) + print $i + } + }' + ) + addr=${addr/\/*} + + [ -z "$addr" ] && return 1 + + echo $addr + + return 0 +} + +################################################################################ +# create namespaces and vrf + +create_vrf() +{ + local ns=$1 + local vrf=$2 + local table=$3 + local addr=$4 + local addr6=$5 + + ip -netns ${ns} link add ${vrf} type vrf table ${table} + ip -netns ${ns} link set ${vrf} up + ip -netns ${ns} route add vrf ${vrf} unreachable default metric 8192 + ip -netns ${ns} -6 route add vrf ${vrf} unreachable default metric 8192 + + ip -netns ${ns} addr add 127.0.0.1/8 dev ${vrf} + ip -netns ${ns} -6 addr add ::1 dev ${vrf} nodad + if [ "${addr}" != "-" ]; then + ip -netns ${ns} addr add dev ${vrf} ${addr} + fi + if [ "${addr6}" != "-" ]; then + ip -netns ${ns} -6 addr add dev ${vrf} ${addr6} + fi + + ip -netns ${ns} ru del pref 0 + ip -netns ${ns} ru add pref 32765 from all lookup local + ip -netns ${ns} -6 ru del pref 0 + ip -netns ${ns} -6 ru add pref 32765 from all lookup local +} + +create_ns() +{ + local ns=$1 + local addr=$2 + local addr6=$3 + + ip netns add ${ns} + + ip -netns ${ns} link set lo up + if [ "${addr}" != "-" ]; then + ip -netns ${ns} addr add dev lo ${addr} + fi + if [ "${addr6}" != "-" ]; then + ip -netns ${ns} -6 addr add dev lo ${addr6} + fi + + ip -netns ${ns} ro add unreachable default metric 8192 + ip -netns ${ns} -6 ro add unreachable default metric 8192 + + ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1 +} + +# create veth pair to connect namespaces and apply addresses. +connect_ns() +{ + local ns1=$1 + local ns1_dev=$2 + local ns1_addr=$3 + local ns1_addr6=$4 + local ns2=$5 + local ns2_dev=$6 + local ns2_addr=$7 + local ns2_addr6=$8 + + ip -netns ${ns1} li add ${ns1_dev} type veth peer name tmp + ip -netns ${ns1} li set ${ns1_dev} up + ip -netns ${ns1} li set tmp netns ${ns2} name ${ns2_dev} + ip -netns ${ns2} li set ${ns2_dev} up + + if [ "${ns1_addr}" != "-" ]; then + ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr} + ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr} + fi + + if [ "${ns1_addr6}" != "-" ]; then + ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr6} + ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr6} + fi +} + +cleanup() +{ + # explicit cleanups to check those code paths + ip netns | grep -q ${NSA} + if [ $? -eq 0 ]; then + ip -netns ${NSA} link delete ${VRF} + ip -netns ${NSA} ro flush table ${VRF_TABLE} + + ip -netns ${NSA} addr flush dev ${NSA_DEV} + ip -netns ${NSA} -6 addr flush dev ${NSA_DEV} + ip -netns ${NSA} link set dev ${NSA_DEV} down + ip -netns ${NSA} link del dev ${NSA_DEV} + + ip netns del ${NSA} + fi + + ip netns del ${NSB} +} + +setup() +{ + local with_vrf=${1} + + # make sure we are starting with a clean slate + kill_procs + cleanup 2>/dev/null + + log_debug "Configuring network namespaces" + set -e + + create_ns ${NSA} ${NSA_LO_IP}/32 ${NSA_LO_IP6}/128 + create_ns ${NSB} ${NSB_LO_IP}/32 ${NSB_LO_IP6}/128 + connect_ns ${NSA} ${NSA_DEV} ${NSA_IP}/24 ${NSA_IP6}/64 \ + ${NSB} ${NSB_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 + + NSA_LINKIP6=$(get_linklocal ${NSA} ${NSA_DEV}) + NSB_LINKIP6=$(get_linklocal ${NSB} ${NSB_DEV}) + + # tell ns-A how to get to remote addresses of ns-B + if [ "${with_vrf}" = "yes" ]; then + create_vrf ${NSA} ${VRF} ${VRF_TABLE} ${VRF_IP} ${VRF_IP6} + + ip -netns ${NSA} link set dev ${NSA_DEV} vrf ${VRF} + ip -netns ${NSA} ro add vrf ${VRF} ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV} + ip -netns ${NSA} -6 ro add vrf ${VRF} ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV} + + ip -netns ${NSB} ro add ${VRF_IP}/32 via ${NSA_IP} dev ${NSB_DEV} + ip -netns ${NSB} -6 ro add ${VRF_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV} + else + ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV} + ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV} + fi + + + # tell ns-B how to get to remote addresses of ns-A + ip -netns ${NSB} ro add ${NSA_LO_IP}/32 via ${NSA_IP} dev ${NSB_DEV} + ip -netns ${NSB} ro add ${NSA_LO_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV} + + set +e + + sleep 1 +} + +################################################################################ +# usage + +usage() +{ + cat < Test name/set to run + -p Pause on fail + -P Pause after each test + -v Be verbose +EOF +} + +################################################################################ +# main + +TESTS_IPV4="" +TESTS_IPV6="" +PAUSE_ON_FAIL=no +PAUSE=no + +while getopts :46t:pPvh o +do + case $o in + 4) TESTS=ipv4;; + 6) TESTS=ipv6;; + t) TESTS=$OPTARG;; + p) PAUSE_ON_FAIL=yes;; + P) PAUSE=yes;; + v) VERBOSE=1;; + h) usage; exit 0;; + *) usage; exit 1;; + esac +done + +# make sure we don't pause twice +[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no + +# +# show user test config +# +if [ -z "$TESTS" ]; then + TESTS="$TESTS_IPV4 $TESTS_IPV6 $TESTS_OTHER" +elif [ "$TESTS" = "ipv4" ]; then + TESTS="$TESTS_IPV4" +elif [ "$TESTS" = "ipv6" ]; then + TESTS="$TESTS_IPV6" +fi + +declare -i nfail=0 +declare -i nsuccess=0 + +for t in $TESTS +do + case $t in + # setup namespaces and config, but do not run any tests + setup) setup; exit 0;; + vrf_setup) setup "yes"; exit 0;; + + help) echo "Test names: $TESTS"; exit 0;; + esac +done + +cleanup 2>/dev/null + +printf "\nTests passed: %3d\n" ${nsuccess} +printf "Tests failed: %3d\n" ${nfail} -- GitLab From c032dd8cc7e23bbcc53e00b262594657ff1b7532 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:36 -0700 Subject: [PATCH 1805/7155] selftests: Add ipv4 ping tests to fcnal-test Add ping tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures. Setup includes unreachable routes and fib rules blocking traffic. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 268 +++++++++++++++++++++- 1 file changed, 267 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 22cfbd2fd09c..3f6e786b34ae 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -447,6 +447,270 @@ setup() sleep 1 } +################################################################################ +# IPv4 + +ipv4_ping_novrf() +{ + local a + + # + # out + # + for a in ${NSB_IP} ${NSB_LO_IP} + do + log_start + run_cmd ping -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping out" + + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping out, device bind" + + log_start + run_cmd ping -c1 -w1 -I ${NSA_LO_IP} ${a} + log_test_addr ${a} $? 0 "ping out, address bind" + done + + # + # in + # + for a in ${NSA_IP} ${NSA_LO_IP} + do + log_start + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping in" + done + + # + # local traffic + # + for a in ${NSA_IP} ${NSA_LO_IP} 127.0.0.1 + do + log_start + run_cmd ping -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping local" + done + + # + # local traffic, socket bound to device + # + # address on device + a=${NSA_IP} + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping local, device bind" + + # loopback addresses not reachable from device bind + # fails in a really weird way though because ipv4 special cases + # route lookups with oif set. + for a in ${NSA_LO_IP} 127.0.0.1 + do + log_start + show_hint "Fails since address on loopback device is out of device scope" + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 1 "ping local, device bind" + done + + # + # ip rule blocks reachability to remote address + # + log_start + setup_cmd ip rule add pref 32765 from all lookup local + setup_cmd ip rule del pref 0 from all lookup local + setup_cmd ip rule add pref 50 to ${NSB_LO_IP} prohibit + setup_cmd ip rule add pref 51 from ${NSB_IP} prohibit + + a=${NSB_LO_IP} + run_cmd ping -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, blocked by rule" + + # NOTE: ipv4 actually allows the lookup to fail and yet still create + # a viable rtable if the oif (e.g., bind to device) is set, so this + # case succeeds despite the rule + # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + + a=${NSA_LO_IP} + log_start + show_hint "Response generates ICMP (or arp request is ignored) due to ip rule" + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by rule" + + [ "$VERBOSE" = "1" ] && echo + setup_cmd ip rule del pref 32765 from all lookup local + setup_cmd ip rule add pref 0 from all lookup local + setup_cmd ip rule del pref 50 to ${NSB_LO_IP} prohibit + setup_cmd ip rule del pref 51 from ${NSB_IP} prohibit + + # + # route blocks reachability to remote address + # + log_start + setup_cmd ip route replace unreachable ${NSB_LO_IP} + setup_cmd ip route replace unreachable ${NSB_IP} + + a=${NSB_LO_IP} + run_cmd ping -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, blocked by route" + + # NOTE: ipv4 actually allows the lookup to fail and yet still create + # a viable rtable if the oif (e.g., bind to device) is set, so this + # case succeeds despite not having a route for the address + # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + + a=${NSA_LO_IP} + log_start + show_hint "Response is dropped (or arp request is ignored) due to ip route" + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by route" + + # + # remove 'remote' routes; fallback to default + # + log_start + setup_cmd ip ro del ${NSB_LO_IP} + + a=${NSB_LO_IP} + run_cmd ping -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, unreachable default route" + + # NOTE: ipv4 actually allows the lookup to fail and yet still create + # a viable rtable if the oif (e.g., bind to device) is set, so this + # case succeeds despite not having a route for the address + # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} +} + +ipv4_ping_vrf() +{ + local a + + # should default on; does not exist on older kernels + set_sysctl net.ipv4.raw_l3mdev_accept=1 2>/dev/null + + # + # out + # + for a in ${NSB_IP} ${NSB_LO_IP} + do + log_start + run_cmd ping -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 0 "ping out, VRF bind" + + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping out, device bind" + + log_start + run_cmd ip vrf exec ${VRF} ping -c1 -w1 -I ${NSA_IP} ${a} + log_test_addr ${a} $? 0 "ping out, vrf device + dev address bind" + + log_start + run_cmd ip vrf exec ${VRF} ping -c1 -w1 -I ${VRF_IP} ${a} + log_test_addr ${a} $? 0 "ping out, vrf device + vrf address bind" + done + + # + # in + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping in" + done + + # + # local traffic, local address + # + for a in ${NSA_IP} ${VRF_IP} 127.0.0.1 + do + log_start + show_hint "Source address should be ${a}" + run_cmd ping -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 0 "ping local, VRF bind" + done + + # + # local traffic, socket bound to device + # + # address on device + a=${NSA_IP} + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping local, device bind" + + # vrf device is out of scope + for a in ${VRF_IP} 127.0.0.1 + do + log_start + show_hint "Fails since address on vrf device is out of device scope" + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 1 "ping local, device bind" + done + + # + # ip rule blocks address + # + log_start + setup_cmd ip rule add pref 50 to ${NSB_LO_IP} prohibit + setup_cmd ip rule add pref 51 from ${NSB_IP} prohibit + + a=${NSB_LO_IP} + run_cmd ping -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 2 "ping out, vrf bind, blocked by rule" + + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, blocked by rule" + + a=${NSA_LO_IP} + log_start + show_hint "Response lost due to ip rule" + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by rule" + + [ "$VERBOSE" = "1" ] && echo + setup_cmd ip rule del pref 50 to ${NSB_LO_IP} prohibit + setup_cmd ip rule del pref 51 from ${NSB_IP} prohibit + + # + # remove 'remote' routes; fallback to default + # + log_start + setup_cmd ip ro del vrf ${VRF} ${NSB_LO_IP} + + a=${NSB_LO_IP} + run_cmd ping -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 2 "ping out, vrf bind, unreachable route" + + log_start + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, unreachable route" + + a=${NSA_LO_IP} + log_start + show_hint "Response lost by unreachable route" + run_cmd_nsb ping -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, unreachable route" +} + +ipv4_ping() +{ + log_section "IPv4 ping" + + log_subsection "No VRF" + setup + set_sysctl net.ipv4.raw_l3mdev_accept=0 2>/dev/null + ipv4_ping_novrf + setup + set_sysctl net.ipv4.raw_l3mdev_accept=1 2>/dev/null + ipv4_ping_novrf + + log_subsection "With VRF" + setup "yes" + ipv4_ping_vrf +} + ################################################################################ # usage @@ -467,7 +731,7 @@ EOF ################################################################################ # main -TESTS_IPV4="" +TESTS_IPV4="ipv4_ping" TESTS_IPV6="" PAUSE_ON_FAIL=no PAUSE=no @@ -506,6 +770,8 @@ declare -i nsuccess=0 for t in $TESTS do case $t in + ipv4_ping|ping) ipv4_ping;; + # setup namespaces and config, but do not run any tests setup) setup; exit 0;; vrf_setup) setup "yes"; exit 0;; -- GitLab From c0644e71df3302ce44ef4572d3df9fb4758bcb8b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:37 -0700 Subject: [PATCH 1806/7155] selftests: Add ipv6 ping tests to fcnal-test Add IPv6 ping tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures. Setup includes unreachable routes and fib rules blocking traffic. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 284 +++++++++++++++++++++- 1 file changed, 283 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 3f6e786b34ae..4da510f6d625 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -711,6 +711,287 @@ ipv4_ping() ipv4_ping_vrf } +################################################################################ +# IPv6 + +ipv6_ping_novrf() +{ + local a + + # should not have an impact, but make a known state + set_sysctl net.ipv4.raw_l3mdev_accept=0 2>/dev/null + + # + # out + # + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} + do + log_start + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping out" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} + do + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping out, device bind" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_LO_IP6} ${a} + log_test_addr ${a} $? 0 "ping out, loopback address bind" + done + + # + # in + # + for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV} ${MCAST}%${NSB_DEV} + do + log_start + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping in" + done + + # + # local traffic, local address + # + for a in ${NSA_IP6} ${NSA_LO_IP6} ::1 ${NSA_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} + do + log_start + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping local, no bind" + done + + for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} + do + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping local, device bind" + done + + for a in ${NSA_LO_IP6} ::1 + do + log_start + show_hint "Fails since address on loopback is out of device scope" + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping local, device bind" + done + + # + # ip rule blocks address + # + log_start + setup_cmd ip -6 rule add pref 32765 from all lookup local + setup_cmd ip -6 rule del pref 0 from all lookup local + setup_cmd ip -6 rule add pref 50 to ${NSB_LO_IP6} prohibit + setup_cmd ip -6 rule add pref 51 from ${NSB_IP6} prohibit + + a=${NSB_LO_IP6} + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, blocked by rule" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, blocked by rule" + + a=${NSA_LO_IP6} + log_start + show_hint "Response lost due to ip rule" + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by rule" + + setup_cmd ip -6 rule add pref 0 from all lookup local + setup_cmd ip -6 rule del pref 32765 from all lookup local + setup_cmd ip -6 rule del pref 50 to ${NSB_LO_IP6} prohibit + setup_cmd ip -6 rule del pref 51 from ${NSB_IP6} prohibit + + # + # route blocks reachability to remote address + # + log_start + setup_cmd ip -6 route del ${NSB_LO_IP6} + setup_cmd ip -6 route add unreachable ${NSB_LO_IP6} metric 10 + setup_cmd ip -6 route add unreachable ${NSB_IP6} metric 10 + + a=${NSB_LO_IP6} + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, blocked by route" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, blocked by route" + + a=${NSA_LO_IP6} + log_start + show_hint "Response lost due to ip route" + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by route" + + + # + # remove 'remote' routes; fallback to default + # + log_start + setup_cmd ip -6 ro del unreachable ${NSB_LO_IP6} + setup_cmd ip -6 ro del unreachable ${NSB_IP6} + + a=${NSB_LO_IP6} + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, unreachable route" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, unreachable route" +} + +ipv6_ping_vrf() +{ + local a + + # should default on; does not exist on older kernels + set_sysctl net.ipv4.raw_l3mdev_accept=1 2>/dev/null + + # + # out + # + for a in ${NSB_IP6} ${NSB_LO_IP6} + do + log_start + run_cmd ${ping6} -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 0 "ping out, VRF bind" + done + + for a in ${NSB_LINKIP6}%${VRF} ${MCAST}%${VRF} + do + log_start + show_hint "Fails since VRF device does not support linklocal or multicast" + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, VRF bind" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} + do + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping out, device bind" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} + do + log_start + run_cmd ip vrf exec ${VRF} ${ping6} -c1 -w1 -I ${VRF_IP6} ${a} + log_test_addr ${a} $? 0 "ping out, vrf device+address bind" + done + + # + # in + # + for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} ${MCAST}%${NSB_DEV} + do + log_start + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 0 "ping in" + done + + a=${NSA_LO_IP6} + log_start + show_hint "Fails since loopback address is out of VRF scope" + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in" + + # + # local traffic, local address + # + for a in ${NSA_IP6} ${VRF_IP6} ::1 + do + log_start + show_hint "Source address should be ${a}" + run_cmd ${ping6} -c1 -w1 -I ${VRF} ${a} + log_test_addr ${a} $? 0 "ping local, VRF bind" + done + + for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} + do + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 0 "ping local, device bind" + done + + # LLA to GUA - remove ipv6 global addresses from ns-B + setup_cmd_nsb ip -6 addr del ${NSB_IP6}/64 dev ${NSB_DEV} + setup_cmd_nsb ip -6 addr del ${NSB_LO_IP6}/128 dev lo + setup_cmd_nsb ip -6 ro add ${NSA_IP6}/128 via ${NSA_LINKIP6} dev ${NSB_DEV} + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd_nsb ${ping6} -c1 -w1 ${NSA_IP6} + log_test_addr ${a} $? 0 "ping in, LLA to GUA" + done + + setup_cmd_nsb ip -6 ro del ${NSA_IP6}/128 via ${NSA_LINKIP6} dev ${NSB_DEV} + setup_cmd_nsb ip -6 addr add ${NSB_IP6}/64 dev ${NSB_DEV} + setup_cmd_nsb ip -6 addr add ${NSB_LO_IP6}/128 dev lo + + # + # ip rule blocks address + # + log_start + setup_cmd ip -6 rule add pref 50 to ${NSB_LO_IP6} prohibit + setup_cmd ip -6 rule add pref 51 from ${NSB_IP6} prohibit + + a=${NSB_LO_IP6} + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, blocked by rule" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, blocked by rule" + + a=${NSA_LO_IP6} + log_start + show_hint "Response lost due to ip rule" + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 1 "ping in, blocked by rule" + + log_start + setup_cmd ip -6 rule del pref 50 to ${NSB_LO_IP6} prohibit + setup_cmd ip -6 rule del pref 51 from ${NSB_IP6} prohibit + + # + # remove 'remote' routes; fallback to default + # + log_start + setup_cmd ip -6 ro del ${NSB_LO_IP6} vrf ${VRF} + + a=${NSB_LO_IP6} + run_cmd ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping out, unreachable route" + + log_start + run_cmd ${ping6} -c1 -w1 -I ${NSA_DEV} ${a} + log_test_addr ${a} $? 2 "ping out, device bind, unreachable route" + + ip -netns ${NSB} -6 ro del ${NSA_LO_IP6} + a=${NSA_LO_IP6} + log_start + run_cmd_nsb ${ping6} -c1 -w1 ${a} + log_test_addr ${a} $? 2 "ping in, unreachable route" +} + +ipv6_ping() +{ + log_section "IPv6 ping" + + log_subsection "No VRF" + setup + ipv6_ping_novrf + + log_subsection "With VRF" + setup "yes" + ipv6_ping_vrf +} + ################################################################################ # usage @@ -732,7 +1013,7 @@ EOF # main TESTS_IPV4="ipv4_ping" -TESTS_IPV6="" +TESTS_IPV6="ipv6_ping" PAUSE_ON_FAIL=no PAUSE=no @@ -771,6 +1052,7 @@ for t in $TESTS do case $t in ipv4_ping|ping) ipv4_ping;; + ipv6_ping|ping6) ipv6_ping;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From bbd7c764086b4e6bea8c37e94914f6e5fee34f7d Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:38 -0700 Subject: [PATCH 1807/7155] selftests: Add ipv4 tcp tests to fcnal-test Add tcp tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures for both clients and servers. Includes permutations with net.ipv4.tcp_l3mdev_accept set to 0 and 1. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 315 +++++++++++++++++++++- 1 file changed, 314 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 4da510f6d625..f9e2f1464dcd 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -711,6 +711,317 @@ ipv4_ping() ipv4_ping_vrf } +################################################################################ +# IPv4 TCP + +ipv4_tcp_novrf() +{ + local a + + # + # server tests + # + for a in ${NSA_IP} ${NSA_LO_IP} + do + log_start + run_cmd nettest -s & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "Global server" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -d ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "Device server" + + # verify TCP reset sent and received + for a in ${NSA_IP} ${NSA_LO_IP} + do + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # client + # + for a in ${NSB_IP} ${NSB_LO_IP} + do + log_start + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -r ${a} -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client" + + log_start + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 0 "Client, device bind" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -r ${a} + log_test_addr ${a} $? 1 "No server, unbound client" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + # + # local address tests + # + for a in ${NSA_IP} ${NSA_LO_IP} 127.0.0.1 + do + log_start + run_cmd nettest -s & + sleep 1 + run_cmd nettest -r ${a} -0 ${a} -1 ${a} + log_test_addr ${a} $? 0 "Global server, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -d ${NSA_DEV} & + sleep 1 + run_cmd nettest -r ${a} -0 ${a} + log_test_addr ${a} $? 0 "Device server, unbound client, local connection" + + for a in ${NSA_LO_IP} 127.0.0.1 + do + log_start + show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope" + run_cmd nettest -s -d ${NSA_DEV} & + sleep 1 + run_cmd nettest -r ${a} + log_test_addr ${a} $? 1 "Device server, unbound client, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s & + sleep 1 + run_cmd nettest -r ${a} -0 ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 0 "Global server, device client, local connection" + + for a in ${NSA_LO_IP} 127.0.0.1 + do + log_start + show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope" + run_cmd nettest -s & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "Global server, device client, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -d ${NSA_DEV} -r ${a} -0 ${a} + log_test_addr ${a} $? 0 "Device server, device client, local connection" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 1 "No server, device client, local conn" +} + +ipv4_tcp_vrf() +{ + local a + + # disable global server + log_subsection "Global server disabled" + + set_sysctl net.ipv4.tcp_l3mdev_accept=0 + + # + # server tests + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + show_hint "Should fail 'Connection refused' since global server with VRF is disabled" + run_cmd nettest -s & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 1 "Global server" + + log_start + run_cmd nettest -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + log_start + run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "Device server" + + # verify TCP reset received + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # local address tests + # (${VRF_IP} and 127.0.0.1 both timeout) + a=${NSA_IP} + log_start + show_hint "Should fail 'Connection refused' since global server with VRF is disabled" + run_cmd nettest -s & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "Global server, local connection" + + # + # enable VRF global server + # + log_subsection "VRF Global server enabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=1 + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + show_hint "client socket should be bound to VRF" + run_cmd nettest -s -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "Global server" + + log_start + show_hint "client socket should be bound to VRF" + run_cmd nettest -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + # verify TCP reset received + log_start + show_hint "Should fail 'Connection refused'" + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + a=${NSA_IP} + log_start + show_hint "client socket should be bound to device" + run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 0 "Device server" + + # local address tests + for a in ${NSA_IP} ${VRF_IP} + do + log_start + show_hint "Should fail 'No route to host' since client is not bound to VRF" + run_cmd nettest -s -2 ${VRF} & + sleep 1 + run_cmd nettest -r ${a} + log_test_addr ${a} $? 1 "Global server, local connection" + done + + # + # client + # + for a in ${NSB_IP} ${NSB_LO_IP} + do + log_start + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -r ${a} -d ${VRF} + log_test_addr ${a} $? 0 "Client, VRF bind" + + log_start + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 0 "Client, device bind" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -r ${a} -d ${VRF} + log_test_addr ${a} $? 1 "No server, VRF client" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + for a in ${NSA_IP} ${VRF_IP} 127.0.0.1 + do + log_start + run_cmd nettest -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd nettest -r ${a} -d ${VRF} -0 ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a} + log_test_addr ${a} $? 0 "VRF server, device client, local connection" + + log_start + show_hint "Should fail 'No route to host' since client is out of VRF scope" + run_cmd nettest -s -d ${VRF} & + sleep 1 + run_cmd nettest -r ${a} + log_test_addr ${a} $? 1 "VRF server, unbound client, local connection" + + log_start + run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -r ${a} -d ${VRF} -0 ${a} + log_test_addr ${a} $? 0 "Device server, VRF client, local connection" + + log_start + run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a} + log_test_addr ${a} $? 0 "Device server, device client, local connection" +} + +ipv4_tcp() +{ + log_section "IPv4/TCP" + + which nettest >/dev/null + if [ $? -ne 0 ]; then + log_error "nettest not found; skipping tests" + return + fi + + log_subsection "No VRF" + setup + + # tcp_l3mdev_accept should have no affect without VRF; + # run tests with it enabled and disabled to verify + log_subsection "tcp_l3mdev_accept disabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=0 + ipv4_tcp_novrf + log_subsection "tcp_l3mdev_accept enabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=1 + ipv4_tcp_novrf + + log_subsection "With VRF" + setup "yes" + ipv4_tcp_vrf +} + ################################################################################ # IPv6 @@ -1012,7 +1323,7 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping" +TESTS_IPV4="ipv4_ping ipv4_tcp" TESTS_IPV6="ipv6_ping" PAUSE_ON_FAIL=no PAUSE=no @@ -1052,6 +1363,8 @@ for t in $TESTS do case $t in ipv4_ping|ping) ipv4_ping;; + ipv4_tcp|tcp) ipv4_tcp;; + ipv6_ping|ping6) ipv6_ping;; # setup namespaces and config, but do not run any tests -- GitLab From a071bbf20539fa9166820c34c71cf2167dc23833 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:39 -0700 Subject: [PATCH 1808/7155] selftests: Add ipv6 tcp tests to fcnal-test Add IPv6 tcp tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures for both clients and servers. Includes permutations with net.ipv4.tcp_l3mdev_accept set to 0 and 1. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 370 +++++++++++++++++++++- 1 file changed, 369 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index f9e2f1464dcd..97291c6d17c5 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -1303,6 +1303,373 @@ ipv6_ping() ipv6_ping_vrf } +################################################################################ +# IPv6 TCP + +ipv6_tcp_novrf() +{ + local a + + # + # server tests + # + for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + run_cmd nettest -6 -s & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Global server" + done + + # verify TCP reset received + for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # client + # + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} + do + log_start + run_cmd_nsb nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Client" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} + do + log_start + run_cmd_nsb nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 0 "Client, device bind" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + # + # local address tests + # + for a in ${NSA_IP6} ${NSA_LO_IP6} ::1 + do + log_start + run_cmd nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Global server, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -r ${a} -0 ${a} + log_test_addr ${a} $? 0 "Device server, unbound client, local connection" + + for a in ${NSA_LO_IP6} ::1 + do + log_start + show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope" + run_cmd nettest -6 -s -d ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -r ${a} + log_test_addr ${a} $? 1 "Device server, unbound client, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a} + log_test_addr ${a} $? 0 "Global server, device client, local connection" + + for a in ${NSA_LO_IP6} ::1 + do + log_start + show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope" + run_cmd nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "Global server, device client, local connection" + done + + for a in ${NSA_IP6} ${NSA_LINKIP6} + do + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Device server, device client, local conn" + done + + for a in ${NSA_IP6} ${NSA_LINKIP6} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 1 "No server, device client, local conn" + done +} + +ipv6_tcp_vrf() +{ + local a + + # disable global server + log_subsection "Global server disabled" + + set_sysctl net.ipv4.tcp_l3mdev_accept=0 + + # + # server tests + # + for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + show_hint "Should fail 'Connection refused' since global server with VRF is disabled" + run_cmd nettest -6 -s & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 1 "Global server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "VRF server" + done + + # link local is always bound to ingress device + a=${NSA_LINKIP6}%${NSB_DEV} + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Device server" + done + + # verify TCP reset received + for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # local address tests + a=${NSA_IP6} + log_start + show_hint "Should fail 'Connection refused' since global server with VRF is disabled" + run_cmd nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "Global server, local connection" + + # + # enable VRF global server + # + log_subsection "VRF Global server enabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=1 + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Global server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "VRF server" + done + + # For LLA, child socket is bound to device + a=${NSA_LINKIP6}%${NSB_DEV} + log_start + run_cmd nettest -6 -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Global server" + + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 0 "Device server" + done + + # verify TCP reset received + for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # local address tests + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + show_hint "Fails 'No route to host' since client is not in VRF" + run_cmd nettest -6 -s -2 ${VRF} & + sleep 1 + run_cmd nettest -6 -r ${a} + log_test_addr ${a} $? 1 "Global server, local connection" + done + + + # + # client + # + for a in ${NSB_IP6} ${NSB_LO_IP6} + do + log_start + run_cmd_nsb nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${VRF} + log_test_addr ${a} $? 0 "Client, VRF bind" + done + + a=${NSB_LINKIP6} + log_start + show_hint "Fails since VRF device does not allow linklocal addresses" + run_cmd_nsb nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${VRF} + log_test_addr ${a} $? 1 "Client, VRF bind" + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6} + do + log_start + run_cmd_nsb nettest -6 -s & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 0 "Client, device bind" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -r ${a} -d ${VRF} + log_test_addr ${a} $? 1 "No server, VRF client" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6} + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + for a in ${NSA_IP6} ${VRF_IP6} ::1 + do + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a} + log_test_addr ${a} $? 0 "VRF server, device client, local connection" + + a=${NSA_IP6} + log_start + show_hint "Should fail since unbound client is out of VRF scope" + run_cmd nettest -6 -s -d ${VRF} & + sleep 1 + run_cmd nettest -6 -r ${a} + log_test_addr ${a} $? 1 "VRF server, unbound client, local connection" + + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a} + log_test_addr ${a} $? 0 "Device server, VRF client, local connection" + + for a in ${NSA_IP6} ${NSA_LINKIP6} + do + log_start + run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a} + log_test_addr ${a} $? 0 "Device server, device client, local connection" + done +} + +ipv6_tcp() +{ + log_section "IPv6/TCP" + + which nettest >/dev/null + if [ $? -ne 0 ]; then + log_error "nettest not found; skipping tests" + return + fi + + log_subsection "No VRF" + setup + + # tcp_l3mdev_accept should have no affect without VRF; + # run tests with it enabled and disabled to verify + log_subsection "tcp_l3mdev_accept disabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=0 + ipv6_tcp_novrf + log_subsection "tcp_l3mdev_accept enabled" + set_sysctl net.ipv4.tcp_l3mdev_accept=1 + ipv6_tcp_novrf + + log_subsection "With VRF" + setup "yes" + ipv6_tcp_vrf +} + ################################################################################ # usage @@ -1324,7 +1691,7 @@ EOF # main TESTS_IPV4="ipv4_ping ipv4_tcp" -TESTS_IPV6="ipv6_ping" +TESTS_IPV6="ipv6_ping ipv6_tcp" PAUSE_ON_FAIL=no PAUSE=no @@ -1366,6 +1733,7 @@ do ipv4_tcp|tcp) ipv4_tcp;; ipv6_ping|ping6) ipv6_ping;; + ipv6_tcp|tcp6) ipv6_tcp;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From a4368be9ad23d2a8e13c2b98409f9df166a4c9c5 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:40 -0700 Subject: [PATCH 1809/7155] selftests: Add ipv4 udp tests to fcnal-test Add udp tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures for both clients and servers. Includes permutations with net.ipv4.udp_l3mdev_accept set to 0 and 1. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 381 +++++++++++++++++++++- 1 file changed, 380 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 97291c6d17c5..afe9eb55d04a 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -1022,6 +1022,384 @@ ipv4_tcp() ipv4_tcp_vrf } +################################################################################ +# IPv4 UDP + +ipv4_udp_novrf() +{ + local a + + # + # server tests + # + for a in ${NSA_IP} ${NSA_LO_IP} + do + log_start + run_cmd nettest -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "Global server" + + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + a=${NSA_IP} + log_start + run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "Device server" + + # + # client + # + for a in ${NSB_IP} ${NSB_LO_IP} + do + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client" + + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client, device bind" + + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -C -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client, device send via cmsg" + + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -r ${a} + log_test_addr ${a} $? 1 "No server, unbound client" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + # + # local address tests + # + for a in ${NSA_IP} ${NSA_LO_IP} 127.0.0.1 + do + log_start + run_cmd nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -0 ${a} -1 ${a} + log_test_addr ${a} $? 0 "Global server, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -r ${a} + log_test_addr ${a} $? 0 "Device server, unbound client, local connection" + + for a in ${NSA_LO_IP} 127.0.0.1 + do + log_start + show_hint "Should fail 'Connection refused' since address is out of device scope" + run_cmd nettest -s -D -d ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -r ${a} + log_test_addr ${a} $? 1 "Device server, unbound client, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -D & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Global server, device client, local connection" + + log_start + run_cmd nettest -s -D & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -C -r ${a} + log_test_addr ${a} $? 0 "Global server, device send via cmsg, local connection" + + log_start + run_cmd nettest -s -D & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -S -r ${a} + log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection" + + # IPv4 with device bind has really weird behavior - it overrides the + # fib lookup, generates an rtable and tries to send the packet. This + # causes failures for local traffic at different places + for a in ${NSA_LO_IP} 127.0.0.1 + do + log_start + show_hint "Should fail since addresses on loopback are out of device scope" + run_cmd nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 2 "Global server, device client, local connection" + + log_start + show_hint "Should fail since addresses on loopback are out of device scope" + run_cmd nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -C + log_test_addr ${a} $? 1 "Global server, device send via cmsg, local connection" + + log_start + show_hint "Should fail since addresses on loopback are out of device scope" + run_cmd nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S + log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -D -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} -0 ${a} + log_test_addr ${a} $? 0 "Device server, device client, local conn" + + log_start + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 2 "No server, device client, local conn" +} + +ipv4_udp_vrf() +{ + local a + + # disable global server + log_subsection "Global server disabled" + set_sysctl net.ipv4.udp_l3mdev_accept=0 + + # + # server tests + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + show_hint "Fails because ingress is in a VRF and global server is disabled" + run_cmd nettest -D -s & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 1 "Global server" + + log_start + run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + log_start + run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server" + + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 1 "No server" + + log_start + show_hint "Should fail 'Connection refused' since global server is out of scope" + run_cmd nettest -D -s & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 1 "Global server, VRF client, local connection" + done + + a=${NSA_IP} + log_start + run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + + log_start + run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "VRF server, enslaved device client, local connection" + + a=${NSA_IP} + log_start + run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" + + log_start + run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" + + # enable global server + log_subsection "Global server enabled" + set_sysctl net.ipv4.udp_l3mdev_accept=1 + + # + # server tests + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "Global server" + + log_start + run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "VRF server" + + log_start + run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd_nsb nettest -D -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # client tests + # + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -d ${VRF} -D -r ${NSB_IP} -1 ${NSA_IP} + log_test $? 0 "VRF client" + + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -d ${NSA_DEV} -D -r ${NSB_IP} -1 ${NSA_IP} + log_test $? 0 "Enslaved device client" + + # negative test - should fail + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -d ${VRF} -r ${NSB_IP} + log_test $? 1 "No server, VRF client" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -d ${NSA_DEV} -r ${NSB_IP} + log_test $? 1 "No server, enslaved device client" + + # + # local address tests + # + a=${NSA_IP} + log_start + run_cmd nettest -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Global server, VRF client, local conn" + + log_start + run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + + log_start + run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "VRF server, device client, local conn" + + log_start + run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" + + log_start + run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" + + for a in ${VRF_IP} 127.0.0.1 + do + log_start + run_cmd nettest -D -s -2 ${VRF} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Global server, VRF client, local conn" + done + + for a in ${VRF_IP} 127.0.0.1 + do + log_start + run_cmd nettest -s -D -d ${VRF} -2 ${VRF} & + sleep 1 + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + done + + # negative test - should fail + # verifies ECONNREFUSED + for a in ${NSA_IP} ${VRF_IP} 127.0.0.1 + do + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 1 "No server, VRF client, local conn" + done +} + +ipv4_udp() +{ + which nettest >/dev/null + if [ $? -ne 0 ]; then + log_error "nettest not found; skipping tests" + return + fi + + log_section "IPv4/UDP" + log_subsection "No VRF" + + setup + + # udp_l3mdev_accept should have no affect without VRF; + # run tests with it enabled and disabled to verify + log_subsection "udp_l3mdev_accept disabled" + set_sysctl net.ipv4.udp_l3mdev_accept=0 + ipv4_udp_novrf + log_subsection "udp_l3mdev_accept enabled" + set_sysctl net.ipv4.udp_l3mdev_accept=1 + ipv4_udp_novrf + + log_subsection "With VRF" + setup "yes" + ipv4_udp_vrf +} + ################################################################################ # IPv6 @@ -1690,7 +2068,7 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping ipv4_tcp" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp" TESTS_IPV6="ipv6_ping ipv6_tcp" PAUSE_ON_FAIL=no PAUSE=no @@ -1731,6 +2109,7 @@ do case $t in ipv4_ping|ping) ipv4_ping;; ipv4_tcp|tcp) ipv4_tcp;; + ipv4_udp|udp) ipv4_udp;; ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; -- GitLab From 6abdb651255784f1907d8c8fcbf7e4ba4196b1da Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:41 -0700 Subject: [PATCH 1810/7155] selftests: Add ipv6 udp tests to fcnal-test Add IPv6 udp tests to fcnal-test.sh. Covers the permutations of directly connected addresses, routed destinations, VRF and non-VRF, and expected failures for both clients and servers. Includes permutations with net.ipv4.udp_l3mdev_accept set to 0 and 1. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 492 +++++++++++++++++++++- 1 file changed, 491 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index afe9eb55d04a..2a2e692bc242 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -2048,6 +2048,495 @@ ipv6_tcp() ipv6_tcp_vrf } +################################################################################ +# IPv6 UDP + +ipv6_udp_novrf() +{ + local a + + # + # server tests + # + for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Global server" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Device server" + done + + a=${NSA_LO_IP6} + log_start + run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Global server" + + # should fail since loopback address is out of scope for a device + # bound server, but it does not - hence this is more documenting + # behavior. + #log_start + #show_hint "Should fail since loopback address is out of scope" + #run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + #sleep 1 + #run_cmd_nsb nettest -6 -D -r ${a} + #log_test_addr ${a} $? 1 "Device server" + + # negative test - should fail + for a in ${NSA_IP6} ${NSA_LO_IP6} ${NSA_LINKIP6}%${NSB_DEV} + do + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # client + # + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} + do + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -0 ${NSA_IP6} + log_test_addr ${a} $? 0 "Client" + + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -0 ${NSA_IP6} + log_test_addr ${a} $? 0 "Client, device bind" + + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -C -0 ${NSA_IP6} + log_test_addr ${a} $? 0 "Client, device send via cmsg" + + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP6} + log_test_addr ${a} $? 0 "Client, device bind via IPV6_UNICAST_IF" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "No server, unbound client" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "No server, device client" + done + + # + # local address tests + # + for a in ${NSA_IP6} ${NSA_LO_IP6} ::1 + do + log_start + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -0 ${a} -1 ${a} + log_test_addr ${a} $? 0 "Global server, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Device server, unbound client, local connection" + + for a in ${NSA_LO_IP6} ::1 + do + log_start + show_hint "Should fail 'Connection refused' since address is out of device scope" + run_cmd nettest -6 -s -D -d ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "Device server, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -D & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Global server, device client, local connection" + + log_start + run_cmd nettest -6 -s -D & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -C -r ${a} + log_test_addr ${a} $? 0 "Global server, device send via cmsg, local connection" + + log_start + run_cmd nettest -6 -s -D & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -S -r ${a} + log_test_addr ${a} $? 0 "Global server, device client via IPV6_UNICAST_IF, local connection" + + for a in ${NSA_LO_IP6} ::1 + do + log_start + show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} + log_test_addr ${a} $? 1 "Global server, device client, local connection" + + log_start + show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -C + log_test_addr ${a} $? 1 "Global server, device send via cmsg, local connection" + + log_start + show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S + log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -D -s -d ${NSA_DEV} -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} -0 ${a} + log_test_addr ${a} $? 0 "Device server, device client, local conn" + + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 1 "No server, device client, local conn" + + # LLA to GUA + run_cmd_nsb ip -6 addr del ${NSB_IP6}/64 dev ${NSB_DEV} + run_cmd_nsb ip -6 ro add ${NSA_IP6}/128 dev ${NSB_DEV} + log_start + run_cmd nettest -6 -s -D & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${NSA_IP6} + log_test $? 0 "UDP in - LLA to GUA" + + run_cmd_nsb ip -6 ro del ${NSA_IP6}/128 dev ${NSB_DEV} + run_cmd_nsb ip -6 addr add ${NSB_IP6}/64 dev ${NSB_DEV} nodad +} + +ipv6_udp_vrf() +{ + local a + + # disable global server + log_subsection "Global server disabled" + set_sysctl net.ipv4.udp_l3mdev_accept=0 + + # + # server tests + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + show_hint "Should fail 'Connection refused' since global server is disabled" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "Global server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "VRF server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server" + done + + # negative test - should fail + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + show_hint "Should fail 'Connection refused' since there is no server" + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # local address tests + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + show_hint "Should fail 'Connection refused' since global server is disabled" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 1 "Global server, VRF client, local conn" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${VRF} -s & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + done + + a=${NSA_IP6} + log_start + show_hint "Should fail 'Connection refused' since global server is disabled" + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 1 "Global server, device client, local conn" + + log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "VRF server, device client, local conn" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" + + # disable global server + log_subsection "Global server enabled" + set_sysctl net.ipv4.udp_l3mdev_accept=1 + + # + # server tests + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Global server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "VRF server" + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 0 "Enslaved device server" + done + + # negative test - should fail + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd_nsb nettest -6 -D -r ${a} + log_test_addr ${a} $? 1 "No server" + done + + # + # client tests + # + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${NSB_IP6} + log_test $? 0 "VRF client" + + # negative test - should fail + log_start + run_cmd nettest -6 -D -d ${VRF} -r ${NSB_IP6} + log_test $? 1 "No server, VRF client" + + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_IP6} + log_test $? 0 "Enslaved device client" + + # negative test - should fail + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_IP6} + log_test $? 1 "No server, enslaved device client" + + # + # local address tests + # + a=${NSA_IP6} + log_start + run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Global server, VRF client, local conn" + + #log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + + + a=${VRF_IP6} + log_start + run_cmd nettest -6 -D -s -2 ${VRF} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Global server, VRF client, local conn" + + log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${VRF} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" + + # negative test - should fail + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 1 "No server, VRF client, local conn" + done + + # device to global IP + a=${NSA_IP6} + log_start + run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Global server, device client, local conn" + + log_start + run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "VRF server, device client, local conn" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${VRF} -r ${a} + log_test_addr ${a} $? 0 "Device server, VRF client, local conn" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 0 "Device server, device client, local conn" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} + log_test_addr ${a} $? 1 "No server, device client, local conn" + + + # link local addresses + log_start + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd_nsb nettest -6 -D -d ${NSB_DEV} -r ${NSA_LINKIP6} + log_test $? 0 "Global server, linklocal IP" + + log_start + run_cmd_nsb nettest -6 -D -d ${NSB_DEV} -r ${NSA_LINKIP6} + log_test $? 1 "No server, linklocal IP" + + + log_start + run_cmd_nsb nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_LINKIP6} + log_test $? 0 "Enslaved device client, linklocal IP" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSB_LINKIP6} + log_test $? 1 "No server, device client, peer linklocal IP" + + + log_start + run_cmd nettest -6 -D -s & + sleep 1 + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSA_LINKIP6} + log_test $? 0 "Enslaved device client, local conn - linklocal IP" + + log_start + run_cmd nettest -6 -D -d ${NSA_DEV} -r ${NSA_LINKIP6} + log_test $? 1 "No server, device client, local conn - linklocal IP" + + # LLA to GUA + run_cmd_nsb ip -6 addr del ${NSB_IP6}/64 dev ${NSB_DEV} + run_cmd_nsb ip -6 ro add ${NSA_IP6}/128 dev ${NSB_DEV} + log_start + run_cmd nettest -6 -s -D & + sleep 1 + run_cmd_nsb nettest -6 -D -r ${NSA_IP6} + log_test $? 0 "UDP in - LLA to GUA" + + run_cmd_nsb ip -6 ro del ${NSA_IP6}/128 dev ${NSB_DEV} + run_cmd_nsb ip -6 addr add ${NSB_IP6}/64 dev ${NSB_DEV} nodad +} + +ipv6_udp() +{ + # should not matter, but set to known state + set_sysctl net.ipv4.udp_early_demux=1 + + log_section "IPv6/UDP" + log_subsection "No VRF" + setup + + # udp_l3mdev_accept should have no affect without VRF; + # run tests with it enabled and disabled to verify + log_subsection "udp_l3mdev_accept disabled" + set_sysctl net.ipv4.udp_l3mdev_accept=0 + ipv6_udp_novrf + log_subsection "udp_l3mdev_accept enabled" + set_sysctl net.ipv4.udp_l3mdev_accept=1 + ipv6_udp_novrf + + log_subsection "With VRF" + setup "yes" + ipv6_udp_vrf +} + ################################################################################ # usage @@ -2069,7 +2558,7 @@ EOF # main TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp" -TESTS_IPV6="ipv6_ping ipv6_tcp" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp" PAUSE_ON_FAIL=no PAUSE=no @@ -2113,6 +2602,7 @@ do ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; + ipv6_udp|udp6) ipv6_udp;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From 75b2b2b3db4ce660541709c52e826e2ac5c602ad Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:42 -0700 Subject: [PATCH 1811/7155] selftests: Add ipv4 address bind tests to fcnal-test Add address bind tests to fcnal-test.sh. Verifies socket binding to local addresses for raw, tcp and udp including device and VRF cases. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 111 +++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 2a2e692bc242..6023ee1c6980 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -1400,6 +1400,114 @@ ipv4_udp() ipv4_udp_vrf } +################################################################################ +# IPv4 address bind +# +# verifies ability or inability to bind to an address / device + +ipv4_addr_bind_novrf() +{ + # + # raw socket + # + for a in ${NSA_IP} ${NSA_LO_IP} + do + log_start + run_cmd nettest -s -R -P icmp -l ${a} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address" + + log_start + run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" + done + + # + # tcp sockets + # + a=${NSA_IP} + log_start + run_cmd nettest -l ${a} -r ${NSB_IP} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address" + + log_start + run_cmd nettest -l ${a} -r ${NSB_IP} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" + + # Sadly, the kernel allows binding a socket to a device and then + # binding to an address not on the device. The only restriction + # is that the address is valid in the L3 domain. So this test + # passes when it really should not + #a=${NSA_LO_IP} + #log_start + #show_hint "Should fail with 'Cannot assign requested address'" + #run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + #log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" +} + +ipv4_addr_bind_vrf() +{ + # + # raw socket + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest -s -R -P icmp -l ${a} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address" + + log_start + run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" + log_start + run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after VRF bind" + done + + a=${NSA_LO_IP} + log_start + show_hint "Address on loopback is out of VRF scope" + run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b + log_test_addr ${a} $? 1 "Raw socket bind to out of scope address after VRF bind" + + # + # tcp sockets + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address" + + log_start + run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" + done + + a=${NSA_LO_IP} + log_start + show_hint "Address on loopback out of scope for VRF" + run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for VRF" + + log_start + show_hint "Address on loopback out of scope for device in VRF" + run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for device bind" +} + +ipv4_addr_bind() +{ + log_section "IPv4 address binds" + + log_subsection "No VRF" + setup + ipv4_addr_bind_novrf + + log_subsection "With VRF" + setup "yes" + ipv4_addr_bind_vrf +} + ################################################################################ # IPv6 @@ -2557,7 +2665,7 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind" TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp" PAUSE_ON_FAIL=no PAUSE=no @@ -2599,6 +2707,7 @@ do ipv4_ping|ping) ipv4_ping;; ipv4_tcp|tcp) ipv4_tcp;; ipv4_udp|udp) ipv4_udp;; + ipv4_bind|bind) ipv4_addr_bind;; ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; -- GitLab From 34d0302ab86172b373e38ef02ea10519ab1c2388 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:43 -0700 Subject: [PATCH 1812/7155] selftests: Add ipv6 address bind tests to fcnal-test Add IPv6 address bind tests to fcnal-test.sh. Verifies socket binding to local addresses for raw, tcp and udp including device and VRF cases. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 110 +++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 6023ee1c6980..48e74d62e009 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -2645,6 +2645,113 @@ ipv6_udp() ipv6_udp_vrf } +################################################################################ +# IPv6 address bind + +ipv6_addr_bind_novrf() +{ + # + # raw socket + # + for a in ${NSA_IP6} ${NSA_LO_IP6} + do + log_start + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address" + + log_start + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${NSA_DEV} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" + done + + # + # tcp sockets + # + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -l ${a} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address" + + log_start + run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" + + a=${NSA_LO_IP6} + log_start + show_hint "Should fail with 'Cannot assign requested address'" + run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" +} + +ipv6_addr_bind_vrf() +{ + # + # raw socket + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${VRF} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after vrf bind" + + log_start + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${NSA_DEV} -b + log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" + done + + a=${NSA_LO_IP6} + log_start + show_hint "Address on loopback is out of VRF scope" + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${VRF} -b + log_test_addr ${a} $? 1 "Raw socket bind to invalid local address after vrf bind" + + # + # tcp sockets + # + # address on enslaved device is valid for the VRF or device in a VRF + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s -l ${a} -d ${VRF} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address with VRF bind" + done + + a=${NSA_IP6} + log_start + run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind" + + a=${VRF_IP6} + log_start + run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to VRF address with device bind" + + a=${NSA_LO_IP6} + log_start + show_hint "Address on loopback out of scope for VRF" + run_cmd nettest -6 -s -l ${a} -d ${VRF} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for VRF" + + log_start + show_hint "Address on loopback out of scope for device in VRF" + run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for device bind" + +} + +ipv6_addr_bind() +{ + log_section "IPv6 address binds" + + log_subsection "No VRF" + setup + ipv6_addr_bind_novrf + + log_subsection "With VRF" + setup "yes" + ipv6_addr_bind_vrf +} + ################################################################################ # usage @@ -2666,7 +2773,7 @@ EOF # main TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind" -TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind" PAUSE_ON_FAIL=no PAUSE=no @@ -2712,6 +2819,7 @@ do ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; ipv6_udp|udp6) ipv6_udp;; + ipv6_bind|bind6) ipv6_addr_bind;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From 0113f726856e389461fb0fc8d519fc2e8fe52d46 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:44 -0700 Subject: [PATCH 1813/7155] selftests: Add ipv4 runtime tests to fcnal-test Add runtime tests where passive (no traffic flowing) and active (with traffic) sockets are expected to be reset on device deletes. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 185 +++++++++++++++++++++- 1 file changed, 184 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 48e74d62e009..b8bdab733ecd 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -1508,6 +1508,188 @@ ipv4_addr_bind() ipv4_addr_bind_vrf } +################################################################################ +# IPv4 runtime tests + +ipv4_rt() +{ + local desc="$1" + local varg="$2" + local with_vrf="yes" + local a + + # + # server tests + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server" + + setup ${with_vrf} + done + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest ${varg} -s -d ${VRF} & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server" + + setup ${with_vrf} + done + + a=${NSA_IP} + log_start + run_cmd nettest ${varg} -s -d ${NSA_DEV} & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, enslaved device server" + + setup ${with_vrf} + + # + # client test + # + log_start + run_cmd_nsb nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${NSB_IP} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF client" + + setup ${with_vrf} + + log_start + run_cmd_nsb nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${NSB_IP} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, enslaved device client" + + setup ${with_vrf} + + # + # local address tests + # + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server, VRF client, local" + + setup ${with_vrf} + done + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest ${varg} -d ${VRF} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server and client, local" + + setup ${with_vrf} + done + + a=${NSA_IP} + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server, enslaved device client, local" + + setup ${with_vrf} + + log_start + run_cmd nettest ${varg} -d ${VRF} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server, enslaved device client, local" + + setup ${with_vrf} + + log_start + run_cmd nettest ${varg} -d ${NSA_DEV} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, enslaved device server and client, local" +} + +ipv4_ping_rt() +{ + local with_vrf="yes" + local a + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd_nsb ping -f ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "Device delete with active traffic - ping in" + + setup ${with_vrf} + done + + a=${NSB_IP} + log_start + run_cmd ping -f -I ${VRF} ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "Device delete with active traffic - ping out" +} + +ipv4_runtime() +{ + log_section "Run time tests - ipv4" + + setup "yes" + ipv4_ping_rt + + setup "yes" + ipv4_rt "TCP active socket" "-n -1" + + setup "yes" + ipv4_rt "TCP passive socket" "-i" +} + ################################################################################ # IPv6 @@ -2772,7 +2954,7 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime" TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind" PAUSE_ON_FAIL=no PAUSE=no @@ -2815,6 +2997,7 @@ do ipv4_tcp|tcp) ipv4_tcp;; ipv4_udp|udp) ipv4_udp;; ipv4_bind|bind) ipv4_addr_bind;; + ipv4_runtime) ipv4_runtime;; ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; -- GitLab From 4cd12f61b55bc6a670900d75806a2f0122fc6658 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:45 -0700 Subject: [PATCH 1814/7155] selftests: Add ipv6 runtime tests to fcnal-test Add IPv6 runtime tests where passive (no traffic flowing) and active (with traffic) sockets are expected to be reset on device deletes. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 188 +++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index b8bdab733ecd..dcfe0b13dfe9 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -2934,6 +2934,191 @@ ipv6_addr_bind() ipv6_addr_bind_vrf } +################################################################################ +# IPv6 runtime tests + +ipv6_rt() +{ + local desc="$1" + local varg="-6 $2" + local with_vrf="yes" + local a + + # + # server tests + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server" + + setup ${with_vrf} + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest ${varg} -d ${VRF} -s & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server" + + setup ${with_vrf} + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest ${varg} -d ${NSA_DEV} -s & + sleep 1 + run_cmd_nsb nettest ${varg} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, enslaved device server" + + setup ${with_vrf} + done + + # + # client test + # + log_start + run_cmd_nsb nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${NSB_IP6} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test 0 0 "${desc}, VRF client" + + setup ${with_vrf} + + log_start + run_cmd_nsb nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${NSB_IP6} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test 0 0 "${desc}, enslaved device client" + + setup ${with_vrf} + + + # + # local address tests + # + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server, VRF client" + + setup ${with_vrf} + done + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest ${varg} -d ${VRF} -s & + sleep 1 + run_cmd nettest ${varg} -d ${VRF} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server and client" + + setup ${with_vrf} + done + + a=${NSA_IP6} + log_start + run_cmd nettest ${varg} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, global server, device client" + + setup ${with_vrf} + + log_start + run_cmd nettest ${varg} -d ${VRF} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, VRF server, device client" + + setup ${with_vrf} + + log_start + run_cmd nettest ${varg} -d ${NSA_DEV} -s & + sleep 1 + run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "${desc}, device server, device client" +} + +ipv6_ping_rt() +{ + local with_vrf="yes" + local a + + a=${NSA_IP6} + log_start + run_cmd_nsb ${ping6} -f ${a} & + sleep 3 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "Device delete with active traffic - ping in" + + setup ${with_vrf} + + log_start + run_cmd ${ping6} -f ${NSB_IP6} -I ${VRF} & + sleep 1 + run_cmd ip link del ${VRF} + sleep 1 + log_test_addr ${a} 0 0 "Device delete with active traffic - ping out" +} + +ipv6_runtime() +{ + log_section "Run time tests - ipv6" + + setup "yes" + ipv6_ping_rt + + setup "yes" + ipv6_rt "TCP active socket" "-n -1" + + setup "yes" + ipv6_rt "TCP passive socket" "-i" + + setup "yes" + ipv6_rt "UDP active socket" "-D -n -1" +} + ################################################################################ # usage @@ -2955,7 +3140,7 @@ EOF # main TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime" -TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime" PAUSE_ON_FAIL=no PAUSE=no @@ -3003,6 +3188,7 @@ do ipv6_tcp|tcp6) ipv6_tcp;; ipv6_udp|udp6) ipv6_udp;; ipv6_bind|bind6) ipv6_addr_bind;; + ipv6_runtime) ipv6_runtime;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From 88f2b36053b97d3299976dd3af1c768a7f5d9c55 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:46 -0700 Subject: [PATCH 1815/7155] selftests: Add ipv4 netfilter tests to fcnal-test Add netfilter tests to send tcp reset or icmp unreachable for a port. Initial tests are VRF only. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 69 ++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index dcfe0b13dfe9..6f56c91e2d66 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -3119,6 +3119,72 @@ ipv6_runtime() ipv6_rt "UDP active socket" "-D -n -1" } +################################################################################ +# netfilter blocking connections + +netfilter_tcp_reset() +{ + local a + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest -s & + sleep 1 + run_cmd_nsb nettest -r ${a} + log_test_addr ${a} $? 1 "Global server, reject with TCP-reset on Rx" + done +} + +netfilter_icmp() +{ + local stype="$1" + local arg + local a + + [ "${stype}" = "UDP" ] && arg="-D" + + for a in ${NSA_IP} ${VRF_IP} + do + log_start + run_cmd nettest ${arg} -s & + sleep 1 + run_cmd_nsb nettest ${arg} -r ${a} + log_test_addr ${a} $? 1 "Global ${stype} server, Rx reject icmp-port-unreach" + done +} + +ipv4_netfilter() +{ + which nettest >/dev/null + if [ $? -ne 0 ]; then + log_error "nettest not found; skipping tests" + return + fi + + log_section "IPv4 Netfilter" + log_subsection "TCP reset" + + setup "yes" + run_cmd iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with tcp-reset + + netfilter_tcp_reset + + log_start + log_subsection "ICMP unreachable" + + log_start + run_cmd iptables -F + run_cmd iptables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with icmp-port-unreachable + run_cmd iptables -A INPUT -p udp --dport 12345 -j REJECT --reject-with icmp-port-unreachable + + netfilter_icmp "TCP" + netfilter_icmp "UDP" + + log_start + iptables -F +} + ################################################################################ # usage @@ -3139,7 +3205,7 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime" PAUSE_ON_FAIL=no PAUSE=no @@ -3183,6 +3249,7 @@ do ipv4_udp|udp) ipv4_udp;; ipv4_bind|bind) ipv4_addr_bind;; ipv4_runtime) ipv4_runtime;; + ipv4_netfilter) ipv4_netfilter;; ipv6_ping|ping6) ipv6_ping;; ipv6_tcp|tcp6) ipv6_tcp;; -- GitLab From db6641ee6e9e728efb71bda93740559dc55f696c Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:47 -0700 Subject: [PATCH 1816/7155] selftests: Add ipv6 netfilter tests to fcnal-test Add IPv6 netfilter tests to send tcp reset or icmp unreachable for a port. Initial tests are VRF only. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 65 ++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 6f56c91e2d66..17eec10e06bf 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -3185,6 +3185,68 @@ ipv4_netfilter() iptables -F } +netfilter_tcp6_reset() +{ + local a + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s & + sleep 1 + run_cmd_nsb nettest -6 -r ${a} + log_test_addr ${a} $? 1 "Global server, reject with TCP-reset on Rx" + done +} + +netfilter_icmp6() +{ + local stype="$1" + local arg + local a + + [ "${stype}" = "UDP" ] && arg="$arg -D" + + for a in ${NSA_IP6} ${VRF_IP6} + do + log_start + run_cmd nettest -6 -s ${arg} & + sleep 1 + run_cmd_nsb nettest -6 ${arg} -r ${a} + log_test_addr ${a} $? 1 "Global ${stype} server, Rx reject icmp-port-unreach" + done +} + +ipv6_netfilter() +{ + which nettest >/dev/null + if [ $? -ne 0 ]; then + log_error "nettest not found; skipping tests" + return + fi + + log_section "IPv6 Netfilter" + log_subsection "TCP reset" + + setup "yes" + run_cmd ip6tables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with tcp-reset + + netfilter_tcp6_reset + + log_subsection "ICMP unreachable" + + log_start + run_cmd ip6tables -F + run_cmd ip6tables -A INPUT -p tcp --dport 12345 -j REJECT --reject-with icmp6-port-unreachable + run_cmd ip6tables -A INPUT -p udp --dport 12345 -j REJECT --reject-with icmp6-port-unreachable + + netfilter_icmp6 "TCP" + netfilter_icmp6 "UDP" + + log_start + ip6tables -F +} + ################################################################################ # usage @@ -3206,7 +3268,7 @@ EOF # main TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" -TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" PAUSE_ON_FAIL=no PAUSE=no @@ -3256,6 +3318,7 @@ do ipv6_udp|udp6) ipv6_udp;; ipv6_bind|bind6) ipv6_addr_bind;; ipv6_runtime) ipv6_runtime;; + ipv6_netfilter) ipv6_netfilter;; # setup namespaces and config, but do not run any tests setup) setup; exit 0;; -- GitLab From 56eba15d1c601d7e8a40b2997c9aff72bdae9b0f Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 11:56:48 -0700 Subject: [PATCH 1817/7155] selftests: Add use case section to fcnal-test Add use case section to fcnal-test. Initial test is VRF based with a bridge and vlans. The commands stem from bug reports fixed by: a173f066c7cf ("netfilter: bridge: Don't sabotage nf_hook calls from an l3mdev") cd6428988bf4 ("netfilter: bridge: Don't sabotage nf_hook calls for an l3mdev slave") Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 124 ++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 17eec10e06bf..bd6b564382ec 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -3247,6 +3247,126 @@ ipv6_netfilter() ip6tables -F } +################################################################################ +# specific use cases + +# VRF only. +# ns-A device enslaved to bridge. Verify traffic with and without +# br_netfilter module loaded. Repeat with SVI on bridge. +use_case_br() +{ + setup "yes" + + setup_cmd ip link set ${NSA_DEV} down + setup_cmd ip addr del dev ${NSA_DEV} ${NSA_IP}/24 + setup_cmd ip -6 addr del dev ${NSA_DEV} ${NSA_IP6}/64 + + setup_cmd ip link add br0 type bridge + setup_cmd ip addr add dev br0 ${NSA_IP}/24 + setup_cmd ip -6 addr add dev br0 ${NSA_IP6}/64 nodad + + setup_cmd ip li set ${NSA_DEV} master br0 + setup_cmd ip li set ${NSA_DEV} up + setup_cmd ip li set br0 up + setup_cmd ip li set br0 vrf ${VRF} + + rmmod br_netfilter 2>/dev/null + sleep 5 # DAD + + run_cmd ip neigh flush all + run_cmd ping -c1 -w1 -I br0 ${NSB_IP} + log_test $? 0 "Bridge into VRF - IPv4 ping out" + + run_cmd ip neigh flush all + run_cmd ${ping6} -c1 -w1 -I br0 ${NSB_IP6} + log_test $? 0 "Bridge into VRF - IPv6 ping out" + + run_cmd ip neigh flush all + run_cmd_nsb ping -c1 -w1 ${NSA_IP} + log_test $? 0 "Bridge into VRF - IPv4 ping in" + + run_cmd ip neigh flush all + run_cmd_nsb ${ping6} -c1 -w1 ${NSA_IP6} + log_test $? 0 "Bridge into VRF - IPv6 ping in" + + modprobe br_netfilter + if [ $? -eq 0 ]; then + run_cmd ip neigh flush all + run_cmd ping -c1 -w1 -I br0 ${NSB_IP} + log_test $? 0 "Bridge into VRF with br_netfilter - IPv4 ping out" + + run_cmd ip neigh flush all + run_cmd ${ping6} -c1 -w1 -I br0 ${NSB_IP6} + log_test $? 0 "Bridge into VRF with br_netfilter - IPv6 ping out" + + run_cmd ip neigh flush all + run_cmd_nsb ping -c1 -w1 ${NSA_IP} + log_test $? 0 "Bridge into VRF with br_netfilter - IPv4 ping in" + + run_cmd ip neigh flush all + run_cmd_nsb ${ping6} -c1 -w1 ${NSA_IP6} + log_test $? 0 "Bridge into VRF with br_netfilter - IPv6 ping in" + fi + + setup_cmd ip li set br0 nomaster + setup_cmd ip li add br0.100 link br0 type vlan id 100 + setup_cmd ip li set br0.100 vrf ${VRF} up + setup_cmd ip addr add dev br0.100 172.16.101.1/24 + setup_cmd ip -6 addr add dev br0.100 2001:db8:101::1/64 nodad + + setup_cmd_nsb ip li add vlan100 link ${NSB_DEV} type vlan id 100 + setup_cmd_nsb ip addr add dev vlan100 172.16.101.2/24 + setup_cmd_nsb ip -6 addr add dev vlan100 2001:db8:101::2/64 nodad + setup_cmd_nsb ip li set vlan100 up + sleep 1 + + rmmod br_netfilter 2>/dev/null + + run_cmd ip neigh flush all + run_cmd ping -c1 -w1 -I br0.100 172.16.101.2 + log_test $? 0 "Bridge vlan into VRF - IPv4 ping out" + + run_cmd ip neigh flush all + run_cmd ${ping6} -c1 -w1 -I br0.100 2001:db8:101::2 + log_test $? 0 "Bridge vlan into VRF - IPv6 ping out" + + run_cmd ip neigh flush all + run_cmd_nsb ping -c1 -w1 172.16.101.1 + log_test $? 0 "Bridge vlan into VRF - IPv4 ping in" + + run_cmd ip neigh flush all + run_cmd_nsb ${ping6} -c1 -w1 2001:db8:101::1 + log_test $? 0 "Bridge vlan into VRF - IPv6 ping in" + + modprobe br_netfilter + if [ $? -eq 0 ]; then + run_cmd ip neigh flush all + run_cmd ping -c1 -w1 -I br0.100 172.16.101.2 + log_test $? 0 "Bridge vlan into VRF with br_netfilter - IPv4 ping out" + + run_cmd ip neigh flush all + run_cmd ${ping6} -c1 -w1 -I br0.100 2001:db8:101::2 + log_test $? 0 "Bridge vlan into VRF with br_netfilter - IPv6 ping out" + + run_cmd ip neigh flush all + run_cmd_nsb ping -c1 -w1 172.16.101.1 + log_test $? 0 "Bridge vlan into VRF - IPv4 ping in" + + run_cmd ip neigh flush all + run_cmd_nsb ${ping6} -c1 -w1 2001:db8:101::1 + log_test $? 0 "Bridge vlan into VRF - IPv6 ping in" + fi + + setup_cmd ip li del br0 2>/dev/null + setup_cmd_nsb ip li del vlan100 2>/dev/null +} + +use_cases() +{ + log_section "Use cases" + use_case_br +} + ################################################################################ # usage @@ -3269,6 +3389,8 @@ EOF TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" +TESTS_OTHER="use_cases" + PAUSE_ON_FAIL=no PAUSE=no @@ -3320,6 +3442,8 @@ do ipv6_runtime) ipv6_runtime;; ipv6_netfilter) ipv6_netfilter;; + use_cases) use_cases;; + # setup namespaces and config, but do not run any tests setup) setup; exit 0;; vrf_setup) setup "yes"; exit 0;; -- GitLab From ea77388b02270b0af8dc57f668f311235ea068f0 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Wed, 31 Jul 2019 14:40:13 +0300 Subject: [PATCH 1818/7155] net/mlx5: Fix mlx5_ifc_query_lag_out_bits Remove the "reserved_at_40" field to match the device specification. Fixes: 84df61ebc69b ("net/mlx5: Add HW interfaces used by LAG") Signed-off-by: Mark Zhang Reviewed-by: Yishai Hadas Signed-off-by: Leon Romanovsky --- include/linux/mlx5/mlx5_ifc.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 30d15e80bcc7..1f9d4a8e6227 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -9592,8 +9592,6 @@ struct mlx5_ifc_query_lag_out_bits { u8 syndrome[0x20]; - u8 reserved_at_40[0x40]; - struct mlx5_ifc_lagc_bits ctx; }; -- GitLab From 7084ed30ae2aba4efb4d3ef72c0e7042644e7637 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Wed, 31 Jul 2019 14:40:14 +0300 Subject: [PATCH 1819/7155] IB/mlx5: Support MLX5_CMD_OP_QUERY_LAG as a DEVX general command The "MLX5_CMD_OP_QUERY_LAG" is one of the DEVX general commands, add it. Fixes: 8aa8c95ce4cc ("IB/mlx5: Add support for DEVX general command") Signed-off-by: Mark Zhang Reviewed-by: Yishai Hadas Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/devx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c index ec4370f99381..48968b4d561d 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -922,6 +922,7 @@ static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev) case MLX5_CMD_OP_QUERY_CONG_STATUS: case MLX5_CMD_OP_QUERY_CONG_PARAMS: case MLX5_CMD_OP_QUERY_CONG_STATISTICS: + case MLX5_CMD_OP_QUERY_LAG: return true; default: return false; -- GitLab From 14e3cdbb00a885eedc95c0cf8eda8fe28d26d6b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 19 Jun 2019 10:24:17 -0300 Subject: [PATCH 1820/7155] media: don't drop front-end reference count for ->detach A bugfix introduce a link failure in configurations without CONFIG_MODULES: In file included from drivers/media/usb/dvb-usb/pctv452e.c:20:0: drivers/media/usb/dvb-usb/pctv452e.c: In function 'pctv452e_frontend_attach': drivers/media/dvb-frontends/stb0899_drv.h:151:36: error: weak declaration of 'stb0899_attach' being applied to a already existing, static definition The problem is that the !IS_REACHABLE() declaration of stb0899_attach() is a 'static inline' definition that clashes with the weak definition. I further observed that the bugfix was only done for one of the five users of stb0899_attach(), the other four still have the problem. This reverts the bugfix and instead addresses the problem by not dropping the reference count when calling '->detach()', instead we call this function directly in dvb_frontend_put() before dropping the kref on the front-end. I first submitted this in early 2018, and after some discussion it was apparently discarded. While there is a long-term plan in place, that plan is obviously not nearing completion yet, and the current kernel is still broken unless this patch is applied. Link: https://patchwork.kernel.org/patch/10140175/ Link: https://patchwork.linuxtv.org/patch/54831/ Cc: Max Kellermann Cc: Wolfgang Rohdewald Cc: stable@vger.kernel.org Fixes: f686c14364ad ("[media] stb0899: move code to "detach" callback") Fixes: 6cdeaed3b142 ("media: dvb_usb_pctv452e: module refcount changes were unbalanced") Signed-off-by: Arnd Bergmann Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 4 +++- drivers/media/usb/dvb-usb/pctv452e.c | 8 -------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 209186c5cd9b..06ea30a689d7 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -152,6 +152,9 @@ static void dvb_frontend_free(struct kref *ref) static void dvb_frontend_put(struct dvb_frontend *fe) { + /* call detach before dropping the reference count */ + if (fe->ops.detach) + fe->ops.detach(fe); /* * Check if the frontend was registered, as otherwise * kref was not initialized yet. @@ -3040,7 +3043,6 @@ void dvb_frontend_detach(struct dvb_frontend *fe) dvb_frontend_invoke_release(fe, fe->ops.release_sec); dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release); dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release); - dvb_frontend_invoke_release(fe, fe->ops.detach); dvb_frontend_put(fe); } EXPORT_SYMBOL(dvb_frontend_detach); diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index d6b36e4f33d2..441d878fc22c 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -909,14 +909,6 @@ static int pctv452e_frontend_attach(struct dvb_usb_adapter *a) &a->dev->i2c_adap); if (!a->fe_adap[0].fe) return -ENODEV; - - /* - * dvb_frontend will call dvb_detach for both stb0899_detach - * and stb0899_release but we only do dvb_attach(stb0899_attach). - * Increment the module refcount instead. - */ - symbol_get(stb0899_attach); - if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe, &a->dev->i2c_adap)) == NULL) err("Cannot attach lnbp22\n"); -- GitLab From 16407a6af464301f1d5c32599ab07e6f89a98e62 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 25 Jul 2019 09:49:45 -0300 Subject: [PATCH 1821/7155] media: lirc: document BPF IR decoding This is just a start. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/rc/lirc-dev-intro.rst | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/Documentation/media/uapi/rc/lirc-dev-intro.rst b/Documentation/media/uapi/rc/lirc-dev-intro.rst index 1a901d8e1797..a8733c8df2e7 100644 --- a/Documentation/media/uapi/rc/lirc-dev-intro.rst +++ b/Documentation/media/uapi/rc/lirc-dev-intro.rst @@ -20,6 +20,9 @@ data between userspace and kernelspace. Fundamentally, it is just a chardev file_operations defined on it. With respect to transporting raw IR and decoded scancodes to and fro, the essential fops are read, write and ioctl. +It is also possible to attach a BPF program to a LIRC device for decoding +raw IR into scancodes. + Example dmesg output upon a driver registering w/LIRC: .. code-block:: none @@ -34,6 +37,16 @@ What you should see for a chardev: $ ls -l /dev/lirc* crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0 +Note that the package `v4l-utils `_ +contains tools for working with LIRC devices: + + - ir-ctl: can receive raw IR and transmit IR, as well as query LIRC + device features. + + - ir-keytable: can load keymaps; allows you to set IR kernel protocols; load + BPF IR decoders and test IR decoding. Some BPF IR decoders are also + provided. + .. _lirc_modes: ********** @@ -129,12 +142,28 @@ on the following table. This mode is used only for IR send. - -************************** -Remote Controller protocol -************************** - -An enum :c:type:`rc_proto` in the :ref:`lirc_header` lists all the -supported IR protocols: - -.. kernel-doc:: include/uapi/linux/lirc.h +******************** +BPF based IR decoder +******************** + +The kernel has support for decoding the most common IR protocols, but there +are many protocols which are not supported. To support these, it is possible +to load an BPF program which does the decoding. This can only be done on +LIRC devices which support reading raw IR. + +First, using the `bpf(2)`_ syscall with the ``BPF_LOAD_PROG`` argument, +program must be loaded of type ``BPF_PROG_TYPE_LIRC_MODE2``. Once attached +to the LIRC device, this program will be called for each pulse, space or +timeout event on the LIRC device. The context for the BPF program is a +pointer to a unsigned int, which is a :ref:`LIRC_MODE_MODE2 ` +value. When the program has decoded the scancode, it can be submitted using +the BPF functions ``bpf_rc_keydown()`` or ``bpf_rc_repeat()``. Mouse or pointer +movements can be reported using ``bpf_rc_pointer_rel()``. + +Once you have the file descriptor for the ``BPF_PROG_TYPE_LIRC_MODE2`` BPF +program, it can be attached to the LIRC device using the `bpf(2)`_ syscall. +The target must be the file descriptor for the LIRC device, and the +attach type must be ``BPF_LIRC_MODE2``. No more than 64 BPF programs can be +attached to a single LIRC device at a time. + +.. _bpf(2): http://man7.org/linux/man-pages/man2/bpf.2.html -- GitLab From 7328d682371722433c96416c33fa5e2b7a6d97bc Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 25 Jul 2019 16:32:31 -0300 Subject: [PATCH 1822/7155] media: rc: describe rc protocols and their scancodes This lists the rc protocols the kernel knows about and how they are converted to and from scancodes. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/rc/lirc-dev-intro.rst | 12 +- Documentation/media/uapi/rc/lirc-read.rst | 3 +- Documentation/media/uapi/rc/lirc-write.rst | 3 +- Documentation/media/uapi/rc/rc-protos.rst | 456 ++++++++++++++++++ .../media/uapi/rc/remote_controllers.rst | 1 + 5 files changed, 468 insertions(+), 7 deletions(-) create mode 100644 Documentation/media/uapi/rc/rc-protos.rst diff --git a/Documentation/media/uapi/rc/lirc-dev-intro.rst b/Documentation/media/uapi/rc/lirc-dev-intro.rst index a8733c8df2e7..b68c01693939 100644 --- a/Documentation/media/uapi/rc/lirc-dev-intro.rst +++ b/Documentation/media/uapi/rc/lirc-dev-intro.rst @@ -66,11 +66,12 @@ on the following table. For transmitting (aka sending), create a ``struct lirc_scancode`` with the desired scancode set in the ``scancode`` member, :c:type:`rc_proto` - set the IR protocol, and all other members set to 0. Write this struct to - the lirc device. + set to the :ref:`IR protocol `, and all other + members set to 0. Write this struct to the lirc device. - For receiving, you read ``struct lirc_scancode`` from the lirc device, - with ``scancode`` set to the received scancode and the IR protocol + For receiving, you read ``struct lirc_scancode`` from the LIRC device. + The ``scancode`` field is set to the received scancode and the + :ref:`IR protocol ` is set in :c:type:`rc_proto`. If the scancode maps to a valid key code, this is set in the ``keycode`` field, else it is set to ``KEY_RESERVED``. @@ -146,7 +147,8 @@ on the following table. BPF based IR decoder ******************** -The kernel has support for decoding the most common IR protocols, but there +The kernel has support for decoding the most common +:ref:`IR protocols `, but there are many protocols which are not supported. To support these, it is possible to load an BPF program which does the decoding. This can only be done on LIRC devices which support reading raw IR. diff --git a/Documentation/media/uapi/rc/lirc-read.rst b/Documentation/media/uapi/rc/lirc-read.rst index a8fedfaaf0ab..256e520bc27e 100644 --- a/Documentation/media/uapi/rc/lirc-read.rst +++ b/Documentation/media/uapi/rc/lirc-read.rst @@ -62,7 +62,8 @@ read from the chardev. Alternatively, :ref:`LIRC_MODE_SCANCODE ` can be available, in this mode scancodes which are either decoded by software decoders, or by hardware decoders. The :c:type:`rc_proto` member is set to the -protocol used for transmission, and ``scancode`` to the decoded scancode, +:ref:`IR protocol ` +used for transmission, and ``scancode`` to the decoded scancode, and the ``keycode`` set to the keycode or ``KEY_RESERVED``. diff --git a/Documentation/media/uapi/rc/lirc-write.rst b/Documentation/media/uapi/rc/lirc-write.rst index 6adf5ddbac99..eafe13203ea3 100644 --- a/Documentation/media/uapi/rc/lirc-write.rst +++ b/Documentation/media/uapi/rc/lirc-write.rst @@ -64,7 +64,8 @@ driver returns ``EINVAL``. When in :ref:`LIRC_MODE_SCANCODE ` mode, one ``struct lirc_scancode`` must be written to the chardev at a time, else ``EINVAL`` is returned. Set the desired scancode in the ``scancode`` member, -and the protocol in the :c:type:`rc_proto`: member. All other members must be +and the :ref:`IR protocol ` in the +:c:type:`rc_proto`: member. All other members must be set to 0, else ``EINVAL`` is returned. If there is no protocol encoder for the protocol or the scancode is not valid for the specified protocol, ``EINVAL`` is returned. The write function blocks until the scancode diff --git a/Documentation/media/uapi/rc/rc-protos.rst b/Documentation/media/uapi/rc/rc-protos.rst new file mode 100644 index 000000000000..b250ebe301d5 --- /dev/null +++ b/Documentation/media/uapi/rc/rc-protos.rst @@ -0,0 +1,456 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. +.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections + +.. _Remote_controllers_Protocols: + +***************************************** +Remote Controller Protocols and Scancodes +***************************************** + +IR is encoded as a series of pulses and spaces, using a protocol. These +protocols can encode e.g. an address (which device should respond) and a +command: what it should do. The values for these are not always consistent +across different devices for a given protocol. + +Therefore out the output of the IR decoder is a scancode; a single u32 +value. Using keymap tables this can be mapped to linux key codes. + +Other things can be encoded too. Some IR protocols encode a toggle bit; this +is to distinguish whether the same button is being held down, or has been +released and pressed again. If has been released and pressed again, the +toggle bit will invert from one IR message to the next. + +Some remotes have a pointer-type device which can used to control the +mouse; some air conditioning systems can have their target temperature +target set in IR. + +The following are the protocols the kernel knows about and also lists +how scancodes are encoded for each protocol. + +rc-5 (RC_PROTO_RC5) +------------------- + +This IR protocol uses manchester encoding to encode 14 bits. There is a +detailed description here https://www.sbprojects.net/knowledge/ir/rc5.php. + +The scancode encoding is *not* consistent with the lirc daemon (lircd) rc5 +protocol, or the manchester BPF decoder. + +.. flat-table:: rc5 bits scancode mapping + :widths: 1 1 2 + + * - rc-5 bit + + - scancode bit + + - description + + * - 1 + + - none + + - Start bit, always set + + * - 1 + + - 6 (inverted) + + - 2nd start bit in rc5, re-used as 6th command bit + + * - 1 + + - none + + - Toggle bit + + * - 5 + + - 8 to 13 + + - Address + + * - 6 + + - 0 to 5 + + - Command + +There is a variant of rc5 called either rc5x or extended rc5 +where there the second stop bit is the 6th commmand bit, but inverted. +This is done so it the scancodes and encoding is compatible with existing +schemes. This bit is stored in bit 6 of the scancode, inverted. This is +done to keep it compatible with plain rc-5 where there are two start bits. + +rc-5-sz (RC_PROTO_RC5_SZ) +------------------------- +This is much like rc-5 but one bit longer. The scancode is encoded +differently. + +.. flat-table:: rc-5-sz bits scancode mapping + :widths: 1 1 2 + + * - rc-5-sz bits + + - scancode bit + + - description + + * - 1 + + - none + + - Start bit, always set + + * - 1 + + - 13 + + - Address bit + + * - 1 + + - none + + - Toggle bit + + * - 6 + + - 6 to 11 + + - Address + + * - 6 + + - 0 to 5 + + - Command + +rc-5x-20 (RC_PROTO_RC5X_20) +--------------------------- + +This rc-5 extended to encoded 20 bits. The is a 3555 microseconds space +after the 8th bit. + +.. flat-table:: rc-5x-20 bits scancode mapping + :widths: 1 1 2 + + * - rc-5-sz bits + + - scancode bit + + - description + + * - 1 + + - none + + - Start bit, always set + + * - 1 + + - 14 + + - Address bit + + * - 1 + + - none + + - Toggle bit + + * - 5 + + - 16 to 20 + + - Address + + * - 6 + + - 8 to 13 + + - Address + + * - 6 + + - 0 to 5 + + - Command + + +jvc (RC_PROTO_JVC) +------------------ + +The jvc protocol is much like nec, without the inverted values. It is +described here https://www.sbprojects.net/knowledge/ir/jvc.php. + +The scancode is a 16 bits value, where the address is the lower 8 bits +and the command the higher 8 bits; this is reversed from IR order. + +sony-12 (RC_PROTO_SONY12) +------------------------- + +The sony protocol is a pulse-width encoding. There are three variants, +which just differ in number of bits and scancode encoding. + +.. flat-table:: sony-12 bits scancode mapping + :widths: 1 1 2 + + * - sony-12 bits + + - scancode bit + + - description + + * - 5 + + - 16 to 20 + + - device + + * - 7 + + - 0 to 6 + + - function + +sony-15 (RC_PROTO_SONY15) +------------------------- + +The sony protocol is a pulse-width encoding. There are three variants, +which just differ in number of bits and scancode encoding. + +.. flat-table:: sony-12 bits scancode mapping + :widths: 1 1 2 + + * - sony-12 bits + + - scancode bit + + - description + + * - 8 + + - 16 to 23 + + - device + + * - 7 + + - 0 to 6 + + - function + +sony-20 (RC_PROTO_SONY20) +------------------------- + +The sony protocol is a pulse-width encoding. There are three variants, +which just differ in number of bits and scancode encoding. + +.. flat-table:: sony-20 bits scancode mapping + :widths: 1 1 2 + + * - sony-20 bits + + - scancode bit + + - description + + * - 5 + + - 16 to 20 + + - device + + * - 7 + + - 0 to 7 + + - device + + * - 8 + + - 8 to 15 + + - extended bits + +nec (RC_PROTO_NEC) +------------------ + +The nec protocol encodes an 8 bit address and an 8 bit command. It is +described here https://www.sbprojects.net/knowledge/ir/nec.php. Note +that the protocol sends least significant bit first. + +As a check, the nec protocol sends the address and command twice; the +second time it is inverted. This is done for verification. + +A plain nec IR message has 16 bits; the high 8 bits are the address +and the low 8 bits are the command. + +nec-x (RC_PROTO_NECX) +--------------------- + +Extended nec has a 16 bit address and a 8 bit command. This is encoded +as a 24 bit value as you would expect, with the lower 8 bits the command +and the upper 16 bits the address. + +nec-32 (RC_PROTO_NEC32) +----------------------- + +nec-32 does not send an inverted address or an inverted command; the +entire message, all 32 bits, are used. + +For this to be decoded correctly, the second 8 bits must not be the +inverted value of the first, and also the last 8 bits must not be the +inverted value of the third 8 bit value. + +The scancode has a somewhat unusual encoding. + +.. flat-table:: nec-32 bits scancode mapping + + * - nec-32 bits + + - scancode bit + + * - First 8 bits + + - 16 to 23 + + * - Second 8 bits + + - 24 to 31 + + * - Third 8 bits + + - 0 to 7 + + * - Fourth 8 bits + + - 8 to 15 + +sanyo (RC_PROTO_SANYO) +---------------------- + +The sanyo protocol is like the nec protocol, but with 13 bits address +rather than 8 bits. Both the address and the command are followed by +their inverted versions, but these are not present in the scancodes. + +Bis 8 to 20 of the scancode is the 13 bits address, and the lower 8 +bits are the command. + +mcir2-kbd (RC_PROTO_MCIR2_KBD) +------------------------------ + +This protocol is generated by the Microsoft MCE keyboard for keyboard +events. Refer to the ir-mce_kbd-decoder.c to see how it is encoded. + +mcir2-mse (RC_PROTO_MCIR2_MSE) +------------------------------ + +This protocol is generated by the Microsoft MCE keyboard for pointer +events. Refer to the ir-mce_kbd-decoder.c to see how it is encoded. + +rc-6-0 (RC_PROTO_RC6_0) +----------------------- + +This is the rc-6 in mode 0. rc-6 is described here +https://www.sbprojects.net/knowledge/ir/rc6.php. +The scancode is the exact 16 bits as in the protocol. There is also a +toggle bit. + +rc-6-6a-20 (RC_PROTO_RC6_6A_20) +------------------------------- + +This is the rc-6 in mode 6a, 20 bits. rc-6 is described here +https://www.sbprojects.net/knowledge/ir/rc6.php. +The scancode is the exact 20 bits +as in the protocol. There is also a toggle bit. + +rc-6-6a-24 (RC_PROTO_RC6_6A_24) +------------------------------- + +This is the rc-6 in mode 6a, 24 bits. rc-6 is described here +https://www.sbprojects.net/knowledge/ir/rc6.php. +The scancode is the exact 24 bits +as in the protocol. There is also a toggle bit. + +rc-6-6a-32 (RC_PROTO_RC6_6A_32) +------------------------------- + +This is the rc-6 in mode 6a, 32 bits. rc-6 is described here +https://www.sbprojects.net/knowledge/ir/rc6.php. +The upper 16 bits are the vendor, +and the lower 16 bits are the vendor-specific bits. This protocol is +for the non-Microsoft MCE variant (vendor != 0x800f). + + +rc-6-mce (RC_PROTO_RC6_MCE) +--------------------------- + +This is the rc-6 in mode 6a, 32 bits. The upper 16 bits are the vendor, +and the lower 16 bits are the vendor-specific bits. This protocol is +for the Microsoft MCE variant (vendor = 0x800f). The toggle bit in the +protocol itself is ignored, and the 16th bit should be takes as the toggle +bit. + +sharp (RC_PROTO_SHARP) +---------------------- + +This is a protocol used by Sharp VCRs, is described here +https://www.sbprojects.net/knowledge/ir/sharp.php. There is a very long +(40ms) space between the normal and inverted values, and some IR receivers +cannot decode this. + +There is a 5 bit address and a 8 bit command. In the scancode the address is +in bits 8 to 12, and the command in bits 0 to 7. + +xmp (RC_PROTO_XMP) +------------------ + +This protocol has several versions and only version 1 is supported. Refer +to the decoder (ir-xmp-decoder.c) to see how it is encoded. + + +cec (RC_PROTO_CEC) +------------------ + +This is not an IR protocol, this is a protocol over CEC. The CEC +infrastructure uses rc-core for handling CEC commands, so that they +can easily be remapped. + +imon (RC_PROTO_IMON) +-------------------- + +This protocol is used by Antec Veris/SoundGraph iMON remotes. + +The protocol +describes both button presses and pointer movements. The protocol encodes +31 bits, and the scancode is simply the 31 bits with the top bit always 0. + +rc-mm-12 (RC_PROTO_RCMM12) +-------------------------- + +The rc-mm protocol is described here +https://www.sbprojects.net/knowledge/ir/rcmm.php. The scancode is simply +the 12 bits. + +rc-mm-24 (RC_PROTO_RCMM24) +-------------------------- + +The rc-mm protocol is described here +https://www.sbprojects.net/knowledge/ir/rcmm.php. The scancode is simply +the 24 bits. + +rc-mm-32 (RC_PROTO_RCMM32) +-------------------------- + +The rc-mm protocol is described here +https://www.sbprojects.net/knowledge/ir/rcmm.php. The scancode is simply +the 32 bits. + +xbox-dvd (RC_PROTO_XBOX_DVD) +---------------------------- + +This protocol is used by XBox DVD Remote, which was made for the original +XBox. There is no in-kernel decoder or encoder for this protocol. The usb +device decodes the protocol. There is a BPF decoder available in v4l-utils. diff --git a/Documentation/media/uapi/rc/remote_controllers.rst b/Documentation/media/uapi/rc/remote_controllers.rst index 3051f7abe11d..20e0f986df49 100644 --- a/Documentation/media/uapi/rc/remote_controllers.rst +++ b/Documentation/media/uapi/rc/remote_controllers.rst @@ -27,6 +27,7 @@ Part III - Remote Controller API rc-intro rc-sysfs-nodes + rc-protos rc-tables rc-table-change lirc-dev -- GitLab From ab1cbdf159beba7395a13ab70bc71180929ca064 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 30 Jul 2019 05:50:44 -0300 Subject: [PATCH 1823/7155] media: iguanair: add sanity checks The driver needs to check the endpoint types, too, as opposed to the number of endpoints. This also requires moving the check earlier. Reported-by: syzbot+01a77b82edaa374068e1@syzkaller.appspotmail.com Signed-off-by: Oliver Neukum Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/iguanair.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index ea05e125016a..872d6441e512 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -413,6 +413,10 @@ static int iguanair_probe(struct usb_interface *intf, int ret, pipein, pipeout; struct usb_host_interface *idesc; + idesc = intf->altsetting; + if (idesc->desc.bNumEndpoints < 2) + return -ENODEV; + ir = kzalloc(sizeof(*ir), GFP_KERNEL); rc = rc_allocate_device(RC_DRIVER_IR_RAW); if (!ir || !rc) { @@ -427,18 +431,13 @@ static int iguanair_probe(struct usb_interface *intf, ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); ir->urb_out = usb_alloc_urb(0, GFP_KERNEL); - if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) { + if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out || + !usb_endpoint_is_int_in(&idesc->endpoint[0].desc) || + !usb_endpoint_is_int_out(&idesc->endpoint[1].desc)) { ret = -ENOMEM; goto out; } - idesc = intf->altsetting; - - if (idesc->desc.bNumEndpoints < 2) { - ret = -ENODEV; - goto out; - } - ir->rc = rc; ir->dev = &intf->dev; ir->udev = udev; -- GitLab From b3185ab502749539872402b6e7198c5229ff20d6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Jul 2019 14:55:55 -0300 Subject: [PATCH 1824/7155] media: ir-kbd-i2c: remove outdated comments The "free memory" comment is obsolete since 2013 and the other ones explain the obvious. Just remove the comments. Signed-off-by: Wolfram Sang Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ir-kbd-i2c.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 876d7587a1da..96932779ca37 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -916,16 +916,13 @@ static int ir_remove(struct i2c_client *client) { struct IR_i2c *ir = i2c_get_clientdata(client); - /* kill outstanding polls */ cancel_delayed_work_sync(&ir->work); if (ir->tx_c) i2c_unregister_device(ir->tx_c); - /* unregister device */ rc_unregister_device(ir->rc); - /* free memory */ return 0; } -- GitLab From 47fabc9cbc05bd5ebc70e1953d118d2a424df841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:48 -0300 Subject: [PATCH 1825/7155] media: dt-bindings: media: sunxi-ir: Add A31 compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner A31 has introduced a new memory mapping and a reset line. The difference in memory mapping are : - In the configure register there is a new sample bit and Allwinner has introduced the active threshold feature. - In the status register a new STAT bit is present. Note: CGPO and DRQ_EN bits are removed on A31 but present on A13 and on new SoCs like A64/H6. This is actually not an issue as these bits are togglable and new SoCs have a dedicated bindings. Introduce this bindings to make a difference since this generation. And declare the reset line required since A31. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/sunxi-ir.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 278098987edb..2e59a32a7e33 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -1,16 +1,21 @@ Device-Tree bindings for SUNXI IR controller found in sunXi SoC family Required properties: -- compatible : "allwinner,sun4i-a10-ir" or "allwinner,sun5i-a13-ir" +- compatible : + "allwinner,sun4i-a10-ir" + "allwinner,sun5i-a13-ir" + "allwinner,sun6i-a31-ir" - clocks : list of clock specifiers, corresponding to entries in clock-names property; - clock-names : should contain "apb" and "ir" entries; - interrupts : should contain IR IRQ number; - reg : should contain IO map address for IR. +Required properties since A31: +- resets : phandle + reset specifier pair + Optional properties: - linux,rc-map-name: see rc.txt file in the same directory. -- resets : phandle + reset specifier pair - clock-frequency : IR Receiver clock frequency, in Hertz. Defaults to 8 MHz if missing. -- GitLab From 6b197cb5b4dc7be463599daeb28dfb8d24674746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:49 -0300 Subject: [PATCH 1826/7155] media: rc: Introduce sunxi_ir_quirks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver is used in various Allwinner SoC with different configuration. Introduce a quirks struct to know the fifo size and if a reset is required. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/sunxi-cir.c | 61 +++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index aa719d0ae6b0..29fe152fd9bc 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -72,6 +72,17 @@ /* Time after which device stops sending data in ms */ #define SUNXI_IR_TIMEOUT 120 +/** + * struct sunxi_ir_quirks - Differences between SoC variants. + * + * @has_reset: SoC needs reset deasserted. + * @fifo_size: size of the fifo. + */ +struct sunxi_ir_quirks { + bool has_reset; + int fifo_size; +}; + struct sunxi_ir { spinlock_t ir_lock; struct rc_dev *rc; @@ -134,6 +145,7 @@ static int sunxi_ir_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *dn = dev->of_node; + const struct sunxi_ir_quirks *quirks; struct resource *res; struct sunxi_ir *ir; u32 b_clk_freq = SUNXI_IR_BASE_CLK; @@ -142,12 +154,15 @@ static int sunxi_ir_probe(struct platform_device *pdev) if (!ir) return -ENOMEM; + quirks = of_device_get_match_data(&pdev->dev); + if (!quirks) { + dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); + return -ENODEV; + } + spin_lock_init(&ir->ir_lock); - if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir")) - ir->fifo_size = 64; - else - ir->fifo_size = 16; + ir->fifo_size = quirks->fifo_size; /* Clock */ ir->apb_clk = devm_clk_get(dev, "apb"); @@ -164,13 +179,15 @@ static int sunxi_ir_probe(struct platform_device *pdev) /* Base clock frequency (optional) */ of_property_read_u32(dn, "clock-frequency", &b_clk_freq); - /* Reset (optional) */ - ir->rst = devm_reset_control_get_optional_exclusive(dev, NULL); - if (IS_ERR(ir->rst)) - return PTR_ERR(ir->rst); - ret = reset_control_deassert(ir->rst); - if (ret) - return ret; + /* Reset */ + if (quirks->has_reset) { + ir->rst = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(ir->rst)) + return PTR_ERR(ir->rst); + ret = reset_control_deassert(ir->rst); + if (ret) + return ret; + } ret = clk_set_rate(ir->clk, b_clk_freq); if (ret) { @@ -306,10 +323,26 @@ static int sunxi_ir_remove(struct platform_device *pdev) return 0; } +static const struct sunxi_ir_quirks sun4i_a10_ir_quirks = { + .has_reset = false, + .fifo_size = 16, +}; + +static const struct sunxi_ir_quirks sun5i_a13_ir_quirks = { + .has_reset = false, + .fifo_size = 64, +}; + static const struct of_device_id sunxi_ir_match[] = { - { .compatible = "allwinner,sun4i-a10-ir", }, - { .compatible = "allwinner,sun5i-a13-ir", }, - {}, + { + .compatible = "allwinner,sun4i-a10-ir", + .data = &sun4i_a10_ir_quirks, + }, + { + .compatible = "allwinner,sun5i-a13-ir", + .data = &sun5i_a13_ir_quirks, + }, + {} }; MODULE_DEVICE_TABLE(of, sunxi_ir_match); -- GitLab From 87d0609801ebcdf18639bb30ec5ec9a380f15be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:50 -0300 Subject: [PATCH 1827/7155] media: rc: sunxi: Add A31 compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwiner A31 has a different memory mapping so add the compatible we will need it later. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/sunxi-cir.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index 29fe152fd9bc..e9b9c582f818 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -333,6 +333,11 @@ static const struct sunxi_ir_quirks sun5i_a13_ir_quirks = { .fifo_size = 64, }; +static const struct sunxi_ir_quirks sun6i_a31_ir_quirks = { + .has_reset = true, + .fifo_size = 64, +}; + static const struct of_device_id sunxi_ir_match[] = { { .compatible = "allwinner,sun4i-a10-ir", @@ -342,6 +347,10 @@ static const struct of_device_id sunxi_ir_match[] = { .compatible = "allwinner,sun5i-a13-ir", .data = &sun5i_a13_ir_quirks, }, + { + .compatible = "allwinner,sun6i-a31-ir", + .data = &sun6i_a31_ir_quirks, + }, {} }; MODULE_DEVICE_TABLE(of, sunxi_ir_match); -- GitLab From b136d72cb89dc2bd11ba001c90cdc65b5f5a1034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:51 -0300 Subject: [PATCH 1828/7155] media: rc: sunxi: Add RXSTA bits definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are using RXINT bits definition when looking at RXSTA register. These bits are equal but it's not really proper. Introduce the RXSTA bits and use them to have coherency. Signed-off-by: Clément Péron Acked-by: Maxime Ripard Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/sunxi-cir.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index e9b9c582f818..f91154c2f45c 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -39,11 +39,11 @@ /* Rx Interrupt Enable */ #define SUNXI_IR_RXINT_REG 0x2C -/* Rx FIFO Overflow */ +/* Rx FIFO Overflow Interrupt Enable */ #define REG_RXINT_ROI_EN BIT(0) -/* Rx Packet End */ +/* Rx Packet End Interrupt Enable */ #define REG_RXINT_RPEI_EN BIT(1) -/* Rx FIFO Data Available */ +/* Rx FIFO Data Available Interrupt Enable */ #define REG_RXINT_RAI_EN BIT(4) /* Rx FIFO available byte level */ @@ -51,6 +51,12 @@ /* Rx Interrupt Status */ #define SUNXI_IR_RXSTA_REG 0x30 +/* Rx FIFO Overflow */ +#define REG_RXSTA_ROI REG_RXINT_ROI_EN +/* Rx Packet End */ +#define REG_RXSTA_RPE REG_RXINT_RPEI_EN +/* Rx FIFO Data Available */ +#define REG_RXSTA_RA REG_RXINT_RAI_EN /* RX FIFO Get Available Counter */ #define REG_RXSTA_GET_AC(val) (((val) >> 8) & (ir->fifo_size * 2 - 1)) /* Clear all interrupt status value */ @@ -110,7 +116,7 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) /* clean all pending statuses */ writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG); - if (status & (REG_RXINT_RAI_EN | REG_RXINT_RPEI_EN)) { + if (status & (REG_RXSTA_RA | REG_RXSTA_RPE)) { /* How many messages in fifo */ rc = REG_RXSTA_GET_AC(status); /* Sanity check */ @@ -126,9 +132,9 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) } } - if (status & REG_RXINT_ROI_EN) { + if (status & REG_RXSTA_ROI) { ir_raw_event_reset(ir->rc); - } else if (status & REG_RXINT_RPEI_EN) { + } else if (status & REG_RXSTA_RPE) { ir_raw_event_set_idle(ir->rc, true); ir_raw_event_handle(ir->rc); } -- GitLab From 020826f4ec57eb957d3f1a01902371d83dfce174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:54 -0300 Subject: [PATCH 1829/7155] media: dt-bindings: media: sunxi-ir: Add A64 compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some minor differences between A31 and A64 driver. But A31 IR driver is compatible with A64. Signed-off-by: Clément Péron Reviewed-by: Rob Herring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/sunxi-ir.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 2e59a32a7e33..1dd287a4ab3a 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -5,6 +5,7 @@ Required properties: "allwinner,sun4i-a10-ir" "allwinner,sun5i-a13-ir" "allwinner,sun6i-a31-ir" + "allwinner,sun50i-a64-ir", "allwinner,sun6i-a31-ir" - clocks : list of clock specifiers, corresponding to entries in clock-names property; - clock-names : should contain "apb" and "ir" entries; -- GitLab From d3dd552da3eb16e369d2459e3fa927542f11d17c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 7 Jun 2019 20:10:57 -0300 Subject: [PATCH 1830/7155] media: dt-bindings: media: sunxi-ir: Add H6 compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some minor differences between A31 or A64 with H6 IR peripheral. But A31 IR driver is compatible with H6. Signed-off-by: Clément Péron Reviewed-by: Rob Herring Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/sunxi-ir.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 1dd287a4ab3a..81eaf95fb764 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -6,6 +6,7 @@ Required properties: "allwinner,sun5i-a13-ir" "allwinner,sun6i-a31-ir" "allwinner,sun50i-a64-ir", "allwinner,sun6i-a31-ir" + "allwinner,sun50i-h6-ir", "allwinner,sun6i-a31-ir" - clocks : list of clock specifiers, corresponding to entries in clock-names property; - clock-names : should contain "apb" and "ir" entries; -- GitLab From d9ecd1f748f2ddb7cc15d56acadbc90b3ce235a9 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:29 -0700 Subject: [PATCH 1831/7155] fm10k: remove unnecessary variable initializer The err variable in the fm10k_tlv_attr_parse function is initialized with zero. However, the function never reads err without first assigning it from a function call. Remove this unnecessary initialization. This was detected by cppcheck and resolves the following warning produced by that tool: [fm10k_tlv.c:498]: (style) Variable 'err' is assigned a value that is never used. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c index 2a7a40bf2b1c..f4c42a40f934 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c @@ -472,7 +472,7 @@ static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, const struct fm10k_tlv_attr *tlv_attr) { u32 i, attr_id, offset = 0; - s32 err = 0; + s32 err; u16 len; /* verify pointers are not NULL */ -- GitLab From 4d12002fd29ad8d8c3da0232153217bee4f10326 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:30 -0700 Subject: [PATCH 1832/7155] fm10k: remove needless assignment of err local variable The local variable err in several functions in the fm10k_netdev.c file is initialized with a value that is never used. The err value is immediately re-assigned in all cases where it will be checked. Remove the unnecessary initializers. This was detected by cppcheck and resolves the following warnings produced by that tool: [fm10k_netdev.c:999] -> [fm10k_netdev.c:1004]: (style) Variable 'err' is reassigned a value before the old one has been used. [fm10k_netdev.c:1019] -> [fm10k_netdev.c:1024]: (style) Variable 'err' is reassigned a value before the old one has been used. [fm10k_netdev.c:64]: (style) Variable 'err' is assigned a value that is never used. [fm10k_netdev.c:131]: (style) Variable 'err' is assigned a value that is never used. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 259da075093f..4704395c0f66 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k.h" #include @@ -54,7 +54,7 @@ int fm10k_setup_tx_resources(struct fm10k_ring *tx_ring) **/ static int fm10k_setup_all_tx_resources(struct fm10k_intfc *interface) { - int i, err = 0; + int i, err; for (i = 0; i < interface->num_tx_queues; i++) { err = fm10k_setup_tx_resources(interface->tx_ring[i]); @@ -121,7 +121,7 @@ int fm10k_setup_rx_resources(struct fm10k_ring *rx_ring) **/ static int fm10k_setup_all_rx_resources(struct fm10k_intfc *interface) { - int i, err = 0; + int i, err; for (i = 0; i < interface->num_rx_queues; i++) { err = fm10k_setup_rx_resources(interface->rx_ring[i]); @@ -871,7 +871,7 @@ static int fm10k_uc_vlan_unsync(struct net_device *netdev, u16 glort = interface->glort; u16 vid = interface->vid; bool set = !!(vid / VLAN_N_VID); - int err = -EHOSTDOWN; + int err; /* drop any leading bits on the VLAN ID */ vid &= VLAN_N_VID - 1; @@ -891,7 +891,7 @@ static int fm10k_mc_vlan_unsync(struct net_device *netdev, u16 glort = interface->glort; u16 vid = interface->vid; bool set = !!(vid / VLAN_N_VID); - int err = -EHOSTDOWN; + int err; /* drop any leading bits on the VLAN ID */ vid &= VLAN_N_VID - 1; -- GitLab From cb1b5226cbdf0bc01dcdd8d422d4051fec1b77ef Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:31 -0700 Subject: [PATCH 1833/7155] fm10k: remove needless initialization of size local variable The local variable 'size' in fm10k_dfwd_add_station is initialized, but is always re-assigned immediately before use. Remove this unnecessary initialization. This was detected by cppcheck and resolves the following warning produced by that tool: [fm10k_netdev.c:1466]: (style) Variable 'size' is assigned a value that is never used. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 4704395c0f66..d3e85480f46d 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1463,7 +1463,7 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, struct fm10k_l2_accel *old_l2_accel = NULL; struct fm10k_dglort_cfg dglort = { 0 }; struct fm10k_hw *hw = &interface->hw; - int size = 0, i; + int size, i; u16 vid, glort; /* The hardware supported by fm10k only filters on the destination MAC -- GitLab From 9aac0fbd471bf09b614b2038faddc91f53b788bb Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:32 -0700 Subject: [PATCH 1834/7155] fm10k: explicitly return 0 on success path in function In the fm10k_handle_resume function, return 0 explicitly at the end of the function instead of returning the err value. This was detected by cppcheck and resolves the following style warning produced by that tool: [fm10k_pci.c:2768] -> [fm10k_pci.c:2787]: (warning) Identical condition 'err', second condition is always false Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 9522e9f8f8b8..73928dbe714f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2340,7 +2340,7 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface) /* Restart the MAC/VLAN request queue in-case of outstanding events */ fm10k_macvlan_schedule(interface); - return err; + return 0; } /** -- GitLab From 27429be75e0d291a74b57f9753537e727b7635b7 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:33 -0700 Subject: [PATCH 1835/7155] fm10k: cast page_addr to u8 * when incrementing it The page_addr variable is a void pointer. Incrementing it before calling prefetch is technically undefined. Fix this by casting it to a u8* pointer before incrementing it. This ensures that we increment the pointer value in byte units, instead of relying on this undefined behavior. This was detected by cppcheck, and resolves the following warning produced by that tool: [fm10k_main.c:328]: (portability) 'page_addr' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 9e6bddff7625..17a96a49174b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -315,7 +315,7 @@ static struct sk_buff *fm10k_fetch_rx_buffer(struct fm10k_ring *rx_ring, /* prefetch first cache line of first page */ prefetch(page_addr); #if L1_CACHE_BYTES < 128 - prefetch(page_addr + L1_CACHE_BYTES); + prefetch((void *)((u8 *)page_addr + L1_CACHE_BYTES)); #endif /* allocate a skb to store the frags */ -- GitLab From d5c2f39500549a7e2cd397f3ec713bd8d85af3e1 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:34 -0700 Subject: [PATCH 1836/7155] fm10k: mark unused parameters with __always_unused Several functions in the fm10k driver have specific function templates, as they are used as function pointers. The parameters in these functions are not always used. Explicitly mark unused parameters with the __always_unused macro, so that the compiler will not warn about them when building with the -Wunused-parameter warning enabled. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 5 ++-- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 10 ++++---- drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 7 +++--- drivers/net/ethernet/intel/fm10k/fm10k_type.h | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 25 +++++++++++-------- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index aece335b41f8..75e51f91036c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k_common.h" @@ -2134,7 +2134,8 @@ static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw, * DWORDs, not bytes. Any invalid values will cause the mailbox to return * error. **/ -s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, +s32 fm10k_sm_mbx_init(struct fm10k_hw __always_unused *hw, + struct fm10k_mbx_info *mbx, const struct fm10k_msg_data *msg_data) { mbx->mbx_reg = FM10K_GMBX; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index e85b2f2eef05..095c5b0e4096 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k_pf.h" #include "fm10k_vf.h" @@ -1152,7 +1152,7 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, * assumption is that in this case it is acceptable to just directly * hand off the message from the VF to the underlying shared code. **/ -s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, +s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 __always_unused **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; @@ -1641,7 +1641,7 @@ const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = { * switch API. **/ s32 fm10k_msg_lport_map_pf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) + struct fm10k_mbx_info __always_unused *mbx) { u16 glort, mask; u32 dglort_map; @@ -1684,7 +1684,7 @@ const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = { * This handler configures the default VLAN for the PF **/ static s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) + struct fm10k_mbx_info __always_unused *mbx) { u16 glort, pvid; u32 pvid_update; @@ -1745,7 +1745,7 @@ const struct fm10k_tlv_attr fm10k_err_msg_attr[] = { * messages that the PF has sent. **/ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) + struct fm10k_mbx_info __always_unused *mbx) { struct fm10k_swapi_error err_msg; s32 err; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c index f4c42a40f934..21eff0895a7a 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k_tlv.h" @@ -587,8 +587,9 @@ s32 fm10k_tlv_msg_parse(struct fm10k_hw *hw, u32 *msg, * a minimum it just indicates that the message requested was * unimplemented. **/ -s32 fm10k_tlv_msg_error(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) +s32 fm10k_tlv_msg_error(struct fm10k_hw __always_unused *hw, + u32 __always_unused **results, + struct fm10k_mbx_info __always_unused *mbx) { return FM10K_NOT_IMPLEMENTED; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 9fb9fca375e3..15ac1c7885bc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #ifndef _FM10K_TYPE_H_ #define _FM10K_TYPE_H_ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index a8519c1f0406..dc8ccd378ec9 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #include "fm10k_vf.h" @@ -198,7 +198,7 @@ static s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) * This function should determine the MAC address for the VF **/ s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) + struct fm10k_mbx_info __always_unused *mbx) { u8 perm_addr[ETH_ALEN]; u16 vid; @@ -267,8 +267,10 @@ static s32 fm10k_read_mac_addr_vf(struct fm10k_hw *hw) * This function is used to add or remove unicast MAC addresses for * the VF. **/ -static s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, u16 glort, - const u8 *mac, u16 vid, bool add, u8 flags) +static s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, + u16 __always_unused glort, + const u8 *mac, u16 vid, bool add, + u8 __always_unused flags) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[7]; @@ -309,7 +311,8 @@ static s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, u16 glort, * This function is used to add or remove multicast MAC addresses for * the VF. **/ -static s32 fm10k_update_mc_addr_vf(struct fm10k_hw *hw, u16 glort, +static s32 fm10k_update_mc_addr_vf(struct fm10k_hw *hw, + u16 __always_unused glort, const u8 *mac, u16 vid, bool add) { struct fm10k_mbx_info *mbx = &hw->mbx; @@ -373,7 +376,7 @@ const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[] = { * are ready to bring up the interface. **/ s32 fm10k_msg_lport_state_vf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) + struct fm10k_mbx_info __always_unused *mbx) { hw->mac.dglort_map = !results[FM10K_LPORT_STATE_MSG_READY] ? FM10K_DGLORTMAP_NONE : FM10K_DGLORTMAP_ZERO; @@ -392,8 +395,9 @@ s32 fm10k_msg_lport_state_vf(struct fm10k_hw *hw, u32 **results, * enabled we can add filters, if it is disabled all filters for this * logical port are flushed. **/ -static s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, u16 glort, - u16 count, bool enable) +static s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, + u16 __always_unused glort, + u16 __always_unused count, bool enable) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[2]; @@ -420,7 +424,8 @@ static s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, u16 glort, * so that it can enable either multicast, multicast promiscuous, or * promiscuous mode of operation. **/ -static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode) +static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, + u16 __always_unused glort, u8 mode) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[3]; @@ -475,7 +480,7 @@ static void fm10k_rebind_hw_stats_vf(struct fm10k_hw *hw, * that information to then populate a DGLORTMAP/DEC entry and the queues * to which it has been assigned. **/ -static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw, +static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw __always_unused *hw, struct fm10k_dglort_cfg *dglort) { /* verify the dglort pointer */ -- GitLab From a3ffeaf7c2bedb5b8658f06e4ca09dc8a352ead6 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:35 -0700 Subject: [PATCH 1837/7155] fm10k: convert NON_Q_VECTORS(hw) into NON_Q_VECTORS The driver currently uses a macro to decide whether we should use NON_Q_VECTORS_PF or NON_Q_VECTORS_VF. However, we also define NON_Q_VECTORS_VF to the same value as NON_Q_VECTORS_PF. This means that the macro NON_Q_VECTORS(hw) will always return the same value. Let's just remove this macro, and replace it directly with an enum value on the enum non_q_vectors. This was detected by cppcheck and fixes the following warnings when building with BUILD=KERNEL [fm10k_ethtool.c:1123]: (style) Same value in both branches of ternary operator. [fm10k_ethtool.c:1142]: (style) Same value in both branches of ternary operator. [fm10k_main.c:1826]: (style) Same value in both branches of ternary operator. [fm10k_main.c:1849]: (style) Same value in both branches of ternary operator. [fm10k_main.c:1858]: (style) Same value in both branches of ternary operator. [fm10k_pci.c:901]: (style) Same value in both branches of ternary operator. [fm10k_pci.c:1040]: (style) Same value in both branches of ternary operator. [fm10k_pci.c:1726]: (style) Same value in both branches of ternary operator. [fm10k_pci.c:1763]: (style) Same value in both branches of ternary operator. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k.h | 10 +++------- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 6 ++---- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 9 ++++----- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index 7d42582ed48d..b14441944b4b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2013 - 2018 Intel Corporation. */ +/* Copyright(c) 2013 - 2019 Intel Corporation. */ #ifndef _FM10K_H_ #define _FM10K_H_ @@ -177,14 +177,10 @@ static inline struct netdev_queue *txring_txq(const struct fm10k_ring *ring) #define MIN_Q_VECTORS 1 enum fm10k_non_q_vectors { FM10K_MBX_VECTOR, -#define NON_Q_VECTORS_VF NON_Q_VECTORS_PF - NON_Q_VECTORS_PF + NON_Q_VECTORS }; -#define NON_Q_VECTORS(hw) (((hw)->mac.type == fm10k_mac_pf) ? \ - NON_Q_VECTORS_PF : \ - NON_Q_VECTORS_VF) -#define MIN_MSIX_COUNT(hw) (MIN_Q_VECTORS + NON_Q_VECTORS(hw)) +#define MIN_MSIX_COUNT(hw) (MIN_Q_VECTORS + NON_Q_VECTORS) struct fm10k_q_vector { struct fm10k_intfc *interface; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 1f7e4a8f4557..c681d2d28107 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -1114,13 +1114,12 @@ static void fm10k_get_channels(struct net_device *dev, struct ethtool_channels *ch) { struct fm10k_intfc *interface = netdev_priv(dev); - struct fm10k_hw *hw = &interface->hw; /* report maximum channels */ ch->max_combined = fm10k_max_channels(dev); /* report info for other vector */ - ch->max_other = NON_Q_VECTORS(hw); + ch->max_other = NON_Q_VECTORS; ch->other_count = ch->max_other; /* record RSS queues */ @@ -1132,14 +1131,13 @@ static int fm10k_set_channels(struct net_device *dev, { struct fm10k_intfc *interface = netdev_priv(dev); unsigned int count = ch->combined_count; - struct fm10k_hw *hw = &interface->hw; /* verify they are not requesting separate vectors */ if (!count || ch->rx_count || ch->tx_count) return -EINVAL; /* verify other_count has not changed */ - if (ch->other_count != NON_Q_VECTORS(hw)) + if (ch->other_count != NON_Q_VECTORS) return -EINVAL; /* verify the number of channels does not exceed hardware limits */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 17a96a49174b..e0a2be534b20 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1824,7 +1824,7 @@ static int fm10k_init_msix_capability(struct fm10k_intfc *interface) v_budget = min_t(u16, v_budget, num_online_cpus()); /* account for vectors not related to queues */ - v_budget += NON_Q_VECTORS(hw); + v_budget += NON_Q_VECTORS; /* At the same time, hardware can only support a maximum of * hw.mac->max_msix_vectors vectors. With features @@ -1856,7 +1856,7 @@ static int fm10k_init_msix_capability(struct fm10k_intfc *interface) } /* record the number of queues available for q_vectors */ - interface->num_q_vectors = v_budget - NON_Q_VECTORS(hw); + interface->num_q_vectors = v_budget - NON_Q_VECTORS; return 0; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 73928dbe714f..bb236fa44048 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -898,7 +898,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface, /* Map interrupt */ if (ring->q_vector) { - txint = ring->q_vector->v_idx + NON_Q_VECTORS(hw); + txint = ring->q_vector->v_idx + NON_Q_VECTORS; txint |= FM10K_INT_MAP_TIMER0; } @@ -1037,7 +1037,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, /* Map interrupt */ if (ring->q_vector) { - rxint = ring->q_vector->v_idx + NON_Q_VECTORS(hw); + rxint = ring->q_vector->v_idx + NON_Q_VECTORS; rxint |= FM10K_INT_MAP_TIMER1; } @@ -1720,10 +1720,9 @@ int fm10k_mbx_request_irq(struct fm10k_intfc *interface) void fm10k_qv_free_irq(struct fm10k_intfc *interface) { int vector = interface->num_q_vectors; - struct fm10k_hw *hw = &interface->hw; struct msix_entry *entry; - entry = &interface->msix_entries[NON_Q_VECTORS(hw) + vector]; + entry = &interface->msix_entries[NON_Q_VECTORS + vector]; while (vector) { struct fm10k_q_vector *q_vector; @@ -1760,7 +1759,7 @@ int fm10k_qv_request_irq(struct fm10k_intfc *interface) unsigned int ri = 0, ti = 0; int vector, err; - entry = &interface->msix_entries[NON_Q_VECTORS(hw)]; + entry = &interface->msix_entries[NON_Q_VECTORS]; for (vector = 0; vector < interface->num_q_vectors; vector++) { struct fm10k_q_vector *q_vector = interface->q_vector[vector]; -- GitLab From 1fa475fee4909777a83f1c46832dde1141b09364 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 8 Jul 2019 16:12:36 -0700 Subject: [PATCH 1838/7155] fm10k: fix fm10k_get_fault_pf to read correct address Fix assignment of the FM10K_FAULT_ADDR_LO register into fault->address by using a bit-wise |= operation. Without this, the low address is completely overwriting the high potion of the address. This caused the fault to incorrectly return only the lower 32 bits of the fault address. This issue was detected by cppcheck and resolves the following warnings produced by that tool: [fm10k_pf.c:1668] -> [fm10k_pf.c:1670]: (style) Variable 'fault->address' is reassigned a value before the old one has been used. [fm10k_pf.c:1669] -> [fm10k_pf.c:1670]: (style) Variable 'fault->address' is reassigned a value before the old one has been used. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 095c5b0e4096..be07bfdb0bb4 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1565,7 +1565,7 @@ static s32 fm10k_get_fault_pf(struct fm10k_hw *hw, int type, /* read remaining fields */ fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_HI); fault->address <<= 32; - fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_LO); + fault->address |= fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_LO); fault->specinfo = fm10k_read_reg(hw, type + FM10K_FAULT_SPECINFO); /* clear valid bit to allow for next error */ -- GitLab From f89255a02f1d75d8e1b9d1c31435fcb64840cb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Sun, 4 Aug 2019 20:54:53 +0200 Subject: [PATCH 1839/7155] batman-adv: BATMAN_V: introduce per hard-iface OGMv2 queues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for the OGMv2 packet aggregation, hold OGMv2 packets for up to BATADV_MAX_AGGREGATION_MS milliseconds (100ms) on per hard-interface queues, before transmitting. This allows us to later squash multiple OGMs into a single frame and transmission for reduced overhead. Signed-off-by: Linus Lüssing Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/bat_v.c | 7 ++ net/batman-adv/bat_v_ogm.c | 153 ++++++++++++++++++++++++++++++++++++- net/batman-adv/bat_v_ogm.h | 3 + net/batman-adv/types.h | 12 +++ 4 files changed, 173 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 22672cb3e25d..64054edc2e3c 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c @@ -79,6 +79,7 @@ static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface) { + batadv_v_ogm_iface_disable(hard_iface); batadv_v_elp_iface_disable(hard_iface); } @@ -1081,6 +1082,12 @@ void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface) */ atomic_set(&hard_iface->bat_v.throughput_override, 0); atomic_set(&hard_iface->bat_v.elp_interval, 500); + + hard_iface->bat_v.aggr_len = 0; + skb_queue_head_init(&hard_iface->bat_v.aggr_list); + spin_lock_init(&hard_iface->bat_v.aggr_list_lock); + INIT_DELAYED_WORK(&hard_iface->bat_v.aggr_wq, + batadv_v_ogm_aggr_work); } /** diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index fad95ef64e01..52c990b54de5 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -17,12 +17,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -76,6 +78,20 @@ struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv, return orig_node; } +/** + * batadv_v_ogm_start_queue_timer() - restart the OGM aggregation timer + * @hard_iface: the interface to use to send the OGM + */ +static void batadv_v_ogm_start_queue_timer(struct batadv_hard_iface *hard_iface) +{ + unsigned int msecs = BATADV_MAX_AGGREGATION_MS * 1000; + + /* msecs * [0.9, 1.1] */ + msecs += prandom_u32() % (msecs / 5) - (msecs / 10); + queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.aggr_wq, + msecs_to_jiffies(msecs / 1000)); +} + /** * batadv_v_ogm_start_timer() - restart the OGM sending timer * @bat_priv: the bat priv with all the soft interface information @@ -115,6 +131,104 @@ static void batadv_v_ogm_send_to_if(struct sk_buff *skb, batadv_send_broadcast_skb(skb, hard_iface); } +/** + * batadv_v_ogm_len() - OGMv2 packet length + * @skb: the OGM to check + * + * Return: Length of the given OGMv2 packet, including tvlv length, excluding + * ethernet header length. + */ +static unsigned int batadv_v_ogm_len(struct sk_buff *skb) +{ + struct batadv_ogm2_packet *ogm_packet; + + ogm_packet = (struct batadv_ogm2_packet *)skb->data; + return BATADV_OGM2_HLEN + ntohs(ogm_packet->tvlv_len); +} + +/** + * batadv_v_ogm_queue_left() - check if given OGM still fits aggregation queue + * @skb: the OGM to check + * @hard_iface: the interface to use to send the OGM + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + * + * Return: True, if the given OGMv2 packet still fits, false otherwise. + */ +static bool batadv_v_ogm_queue_left(struct sk_buff *skb, + struct batadv_hard_iface *hard_iface) +{ + unsigned int max = min_t(unsigned int, hard_iface->net_dev->mtu, + BATADV_MAX_AGGREGATION_BYTES); + unsigned int ogm_len = batadv_v_ogm_len(skb); + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + return hard_iface->bat_v.aggr_len + ogm_len <= max; +} + +/** + * batadv_v_ogm_aggr_list_free - free all elements in an aggregation queue + * @hard_iface: the interface holding the aggregation queue + * + * Empties the OGMv2 aggregation queue and frees all the skbs it contained. + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + */ +static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface) +{ + struct sk_buff *skb; + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + while ((skb = skb_dequeue(&hard_iface->bat_v.aggr_list))) + kfree_skb(skb); + + hard_iface->bat_v.aggr_len = 0; +} + +/** + * batadv_v_ogm_aggr_send() - flush & send aggregation queue + * @hard_iface: the interface with the aggregation queue to flush + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + */ +static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface) +{ + struct sk_buff *skb; + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + while ((skb = skb_dequeue(&hard_iface->bat_v.aggr_list))) { + hard_iface->bat_v.aggr_len -= batadv_v_ogm_len(skb); + batadv_v_ogm_send_to_if(skb, hard_iface); + } +} + +/** + * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface + * @skb: the OGM to queue + * @hard_iface: the interface to queue the OGM on + */ +static void batadv_v_ogm_queue_on_if(struct sk_buff *skb, + struct batadv_hard_iface *hard_iface) +{ + struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + + if (!atomic_read(&bat_priv->aggregated_ogms)) { + batadv_v_ogm_send_to_if(skb, hard_iface); + return; + } + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + if (!batadv_v_ogm_queue_left(skb, hard_iface)) + batadv_v_ogm_aggr_send(hard_iface); + + hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb); + skb_queue_tail(&hard_iface->bat_v.aggr_list, skb); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); +} + /** * batadv_v_ogm_send() - periodic worker broadcasting the own OGM * @work: work queue item @@ -210,7 +324,7 @@ static void batadv_v_ogm_send(struct work_struct *work) break; } - batadv_v_ogm_send_to_if(skb_tmp, hard_iface); + batadv_v_ogm_queue_on_if(skb_tmp, hard_iface); batadv_hardif_put(hard_iface); } rcu_read_unlock(); @@ -223,6 +337,27 @@ static void batadv_v_ogm_send(struct work_struct *work) return; } +/** + * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface + * @work: work queue item + * + * Emits aggregated OGM message in regular intervals. + */ +void batadv_v_ogm_aggr_work(struct work_struct *work) +{ + struct batadv_hard_iface_bat_v *batv; + struct batadv_hard_iface *hard_iface; + + batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work); + hard_iface = container_of(batv, struct batadv_hard_iface, bat_v); + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + batadv_v_ogm_aggr_send(hard_iface); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); + + batadv_v_ogm_start_queue_timer(hard_iface); +} + /** * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V * @hard_iface: the interface to prepare @@ -235,11 +370,25 @@ int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + batadv_v_ogm_start_queue_timer(hard_iface); batadv_v_ogm_start_timer(bat_priv); return 0; } +/** + * batadv_v_ogm_iface_disable() - release OGM interface private resources + * @hard_iface: interface for which the resources have to be released + */ +void batadv_v_ogm_iface_disable(struct batadv_hard_iface *hard_iface) +{ + cancel_delayed_work_sync(&hard_iface->bat_v.aggr_wq); + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + batadv_v_ogm_aggr_list_free(hard_iface); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); +} + /** * batadv_v_ogm_primary_iface_set() - set a new primary interface * @primary_iface: the new primary interface @@ -382,7 +531,7 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv, if_outgoing->net_dev->name, ntohl(ogm_forward->throughput), ogm_forward->ttl, if_incoming->net_dev->name); - batadv_v_ogm_send_to_if(skb, if_outgoing); + batadv_v_ogm_queue_on_if(skb, if_outgoing); out: if (orig_ifinfo) diff --git a/net/batman-adv/bat_v_ogm.h b/net/batman-adv/bat_v_ogm.h index 2a50df7fc2bf..bf16d040461d 100644 --- a/net/batman-adv/bat_v_ogm.h +++ b/net/batman-adv/bat_v_ogm.h @@ -11,10 +11,13 @@ #include #include +#include int batadv_v_ogm_init(struct batadv_priv *bat_priv); void batadv_v_ogm_free(struct batadv_priv *bat_priv); +void batadv_v_ogm_aggr_work(struct work_struct *work); int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface); +void batadv_v_ogm_iface_disable(struct batadv_hard_iface *hard_iface); struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr); void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 6ae139d74e0f..be7c02aa91e2 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -117,6 +117,18 @@ struct batadv_hard_iface_bat_v { /** @elp_wq: workqueue used to schedule ELP transmissions */ struct delayed_work elp_wq; + /** @aggr_wq: workqueue used to transmit queued OGM packets */ + struct delayed_work aggr_wq; + + /** @aggr_list: queue for to be aggregated OGM packets */ + struct sk_buff_head aggr_list; + + /** @aggr_len: size of the OGM aggregate (excluding ethernet header) */ + unsigned int aggr_len; + + /** @aggr_list_lock: protects aggr_list */ + spinlock_t aggr_list_lock; + /** * @throughput_override: throughput override to disable link * auto-detection -- GitLab From 9cb9a17813bf0de1f8ad6deb9538296d5148b5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Sun, 4 Aug 2019 20:54:54 +0200 Subject: [PATCH 1840/7155] batman-adv: BATMAN_V: aggregate OGMv2 packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of transmitting individual OGMv2 packets from the aggregation queue merge those OGMv2 packets into a single one and transmit this aggregate instead. This reduces overhead as it saves an ethernet header and a transmission per aggregated OGMv2 packet. Signed-off-by: Linus Lüssing Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/bat_v_ogm.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index 52c990b54de5..319249f0f85f 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -191,18 +191,44 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface) * batadv_v_ogm_aggr_send() - flush & send aggregation queue * @hard_iface: the interface with the aggregation queue to flush * + * Aggregates all OGMv2 packets currently in the aggregation queue into a + * single OGMv2 packet and transmits this aggregate. + * + * The aggregation queue is empty after this call. + * * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. */ static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface) { + unsigned int aggr_len = hard_iface->bat_v.aggr_len; + struct sk_buff *skb_aggr; + unsigned int ogm_len; struct sk_buff *skb; lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + if (!aggr_len) + return; + + skb_aggr = dev_alloc_skb(aggr_len + ETH_HLEN + NET_IP_ALIGN); + if (!skb_aggr) { + batadv_v_ogm_aggr_list_free(hard_iface); + return; + } + + skb_reserve(skb_aggr, ETH_HLEN + NET_IP_ALIGN); + skb_reset_network_header(skb_aggr); + while ((skb = skb_dequeue(&hard_iface->bat_v.aggr_list))) { hard_iface->bat_v.aggr_len -= batadv_v_ogm_len(skb); - batadv_v_ogm_send_to_if(skb, hard_iface); + + ogm_len = batadv_v_ogm_len(skb); + skb_put_data(skb_aggr, skb->data, ogm_len); + + consume_skb(skb); } + + batadv_v_ogm_send_to_if(skb_aggr, hard_iface); } /** -- GitLab From aa306ab703e9452b1e25cc8e8f04b8df523d0bb8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 24 Jul 2019 11:48:39 +0800 Subject: [PATCH 1841/7155] blk-mq: introduce blk_mq_request_completed() NVMe needs this function to decide if one request to be aborted has been completed in normal IO path already. So introduce it. Cc: Max Gurtovoy Cc: Sagi Grimberg Cc: Keith Busch Cc: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk-mq.c | 6 ++++++ include/linux/blk-mq.h | 1 + 2 files changed, 7 insertions(+) diff --git a/block/blk-mq.c b/block/blk-mq.c index f78d3287dd82..8bb5854a62f3 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -665,6 +665,12 @@ int blk_mq_request_started(struct request *rq) } EXPORT_SYMBOL_GPL(blk_mq_request_started); +int blk_mq_request_completed(struct request *rq) +{ + return blk_mq_rq_state(rq) == MQ_RQ_COMPLETE; +} +EXPORT_SYMBOL_GPL(blk_mq_request_completed); + void blk_mq_start_request(struct request *rq) { struct request_queue *q = rq->q; diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 3fa1fa59f9b2..baac2926e54a 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -296,6 +296,7 @@ static inline u16 blk_mq_unique_tag_to_tag(u32 unique_tag) int blk_mq_request_started(struct request *rq); +int blk_mq_request_completed(struct request *rq); void blk_mq_start_request(struct request *rq); void blk_mq_end_request(struct request *rq, blk_status_t error); void __blk_mq_end_request(struct request *rq, blk_status_t error); -- GitLab From f9934a80f91dba8c7029ba7601459e41ea7770aa Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 24 Jul 2019 11:48:40 +0800 Subject: [PATCH 1842/7155] blk-mq: introduce blk_mq_tagset_wait_completed_request() blk-mq may schedule to call queue's complete function on remote CPU via IPI, but doesn't provide any way to synchronize the request's complete fn. The current queue freeze interface can't provide the synchonization because aborted requests stay at blk-mq queues during EH. In some driver's EH(such as NVMe), hardware queue's resource may be freed & re-allocated. If the completed request's complete fn is run finally after the hardware queue's resource is released, kernel crash will be triggered. Prepare for fixing this kind of issue by introducing blk_mq_tagset_wait_completed_request(). Cc: Max Gurtovoy Cc: Sagi Grimberg Cc: Keith Busch Cc: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk-mq-tag.c | 32 ++++++++++++++++++++++++++++++++ include/linux/blk-mq.h | 1 + 2 files changed, 33 insertions(+) diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index da19f0bc8876..008388e82b5c 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -10,6 +10,7 @@ #include #include +#include #include "blk.h" #include "blk-mq.h" #include "blk-mq-tag.h" @@ -354,6 +355,37 @@ void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, } EXPORT_SYMBOL(blk_mq_tagset_busy_iter); +static bool blk_mq_tagset_count_completed_rqs(struct request *rq, + void *data, bool reserved) +{ + unsigned *count = data; + + if (blk_mq_request_completed(rq)) + (*count)++; + return true; +} + +/** + * blk_mq_tagset_wait_completed_request - wait until all completed req's + * complete funtion is run + * @tagset: Tag set to drain completed request + * + * Note: This function has to be run after all IO queues are shutdown + */ +void blk_mq_tagset_wait_completed_request(struct blk_mq_tag_set *tagset) +{ + while (true) { + unsigned count = 0; + + blk_mq_tagset_busy_iter(tagset, + blk_mq_tagset_count_completed_rqs, &count); + if (!count) + break; + msleep(5); + } +} +EXPORT_SYMBOL(blk_mq_tagset_wait_completed_request); + /** * blk_mq_queue_tag_busy_iter - iterate over all requests with a driver tag * @q: Request queue to examine. diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index baac2926e54a..ee0719b649b6 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -322,6 +322,7 @@ bool blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async); void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv); +void blk_mq_tagset_wait_completed_request(struct blk_mq_tag_set *tagset); void blk_mq_freeze_queue(struct request_queue *q); void blk_mq_unfreeze_queue(struct request_queue *q); void blk_freeze_queue_start(struct request_queue *q); -- GitLab From 78ca40724713bd422873cb4ebee86f9f499650f7 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 24 Jul 2019 11:48:41 +0800 Subject: [PATCH 1843/7155] nvme: don't abort completed request in nvme_cancel_request Before aborting in-flight requests, all IO queues and their interrupts have been shutdown. However, request's completion function may not be done yet because it can be scheduled to run via IPI. So don't abort one request if it is marked as completed, otherwise we may abort one normal completed request. Cc: Max Gurtovoy Cc: Sagi Grimberg Cc: Keith Busch Cc: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 8f3fbe5ca937..bcede8c879d1 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -288,6 +288,10 @@ bool nvme_cancel_request(struct request *req, void *data, bool reserved) dev_dbg_ratelimited(((struct nvme_ctrl *) data)->device, "Cancelling I/O %d", req->tag); + /* don't abort one completed request */ + if (blk_mq_request_completed(req)) + return true; + nvme_req(req)->status = NVME_SC_ABORT_REQ; blk_mq_complete_request_sync(req); return true; -- GitLab From 622b8b6893ff3096e130250c1298adf57a0cab03 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 24 Jul 2019 11:48:42 +0800 Subject: [PATCH 1844/7155] nvme: wait until all completed request's complete fn is called When aborting in-flight request for recovering controller, we have to make sure that queue's complete function is called on completed request before moving on. Otherwise, for example, the warning of WARN_ON_ONCE(qp->mrs_used > 0) in ib_destroy_qp_user() may be triggered on nvme-rdma. Fix this issue by using blk_mq_tagset_wait_completed_request. Cc: Max Gurtovoy Cc: Sagi Grimberg Cc: Keith Busch Cc: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/nvme/host/fc.c | 2 ++ drivers/nvme/host/pci.c | 2 ++ drivers/nvme/host/rdma.c | 8 ++++++-- drivers/nvme/host/tcp.c | 8 ++++++-- drivers/nvme/target/loop.c | 2 ++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 232d8094091b..f39ed8cc23a2 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2774,6 +2774,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) nvme_stop_queues(&ctrl->ctrl); blk_mq_tagset_busy_iter(&ctrl->tag_set, nvme_fc_terminate_exchange, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(&ctrl->tag_set); } /* @@ -2796,6 +2797,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) blk_mq_quiesce_queue(ctrl->ctrl.admin_q); blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, nvme_fc_terminate_exchange, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set); /* kill the aens as they are a separate path */ nvme_fc_abort_aen_ops(ctrl); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index db160cee42ad..45a80b708ef4 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2401,6 +2401,8 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl); blk_mq_tagset_busy_iter(&dev->admin_tagset, nvme_cancel_request, &dev->ctrl); + blk_mq_tagset_wait_completed_request(&dev->tagset); + blk_mq_tagset_wait_completed_request(&dev->admin_tagset); /* * The driver will not be starting up queues again if shutting down so diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index a249db528d54..b313a60be1ca 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -901,9 +901,11 @@ static void nvme_rdma_teardown_admin_queue(struct nvme_rdma_ctrl *ctrl, { blk_mq_quiesce_queue(ctrl->ctrl.admin_q); nvme_rdma_stop_queue(&ctrl->queues[0]); - if (ctrl->ctrl.admin_tagset) + if (ctrl->ctrl.admin_tagset) { blk_mq_tagset_busy_iter(ctrl->ctrl.admin_tagset, nvme_cancel_request, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(ctrl->ctrl.admin_tagset); + } blk_mq_unquiesce_queue(ctrl->ctrl.admin_q); nvme_rdma_destroy_admin_queue(ctrl, remove); } @@ -914,9 +916,11 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl, if (ctrl->ctrl.queue_count > 1) { nvme_stop_queues(&ctrl->ctrl); nvme_rdma_stop_io_queues(ctrl); - if (ctrl->ctrl.tagset) + if (ctrl->ctrl.tagset) { blk_mq_tagset_busy_iter(ctrl->ctrl.tagset, nvme_cancel_request, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(ctrl->ctrl.tagset); + } if (remove) nvme_start_queues(&ctrl->ctrl); nvme_rdma_destroy_io_queues(ctrl, remove); diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 606b13d35d16..cf2eaf834b36 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1748,9 +1748,11 @@ static void nvme_tcp_teardown_admin_queue(struct nvme_ctrl *ctrl, { blk_mq_quiesce_queue(ctrl->admin_q); nvme_tcp_stop_queue(ctrl, 0); - if (ctrl->admin_tagset) + if (ctrl->admin_tagset) { blk_mq_tagset_busy_iter(ctrl->admin_tagset, nvme_cancel_request, ctrl); + blk_mq_tagset_wait_completed_request(ctrl->admin_tagset); + } blk_mq_unquiesce_queue(ctrl->admin_q); nvme_tcp_destroy_admin_queue(ctrl, remove); } @@ -1762,9 +1764,11 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl, return; nvme_stop_queues(ctrl); nvme_tcp_stop_io_queues(ctrl); - if (ctrl->tagset) + if (ctrl->tagset) { blk_mq_tagset_busy_iter(ctrl->tagset, nvme_cancel_request, ctrl); + blk_mq_tagset_wait_completed_request(ctrl->tagset); + } if (remove) nvme_start_queues(ctrl); nvme_tcp_destroy_io_queues(ctrl, remove); diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c index b16dc3981c69..95c8f1732215 100644 --- a/drivers/nvme/target/loop.c +++ b/drivers/nvme/target/loop.c @@ -407,6 +407,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) nvme_stop_queues(&ctrl->ctrl); blk_mq_tagset_busy_iter(&ctrl->tag_set, nvme_cancel_request, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(&ctrl->tag_set); nvme_loop_destroy_io_queues(ctrl); } @@ -416,6 +417,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) blk_mq_quiesce_queue(ctrl->ctrl.admin_q); blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, nvme_cancel_request, &ctrl->ctrl); + blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set); blk_mq_unquiesce_queue(ctrl->ctrl.admin_q); nvme_loop_destroy_admin_queue(ctrl); } -- GitLab From a87ccce0b5a06ee546931859fa62e10f1bce54f9 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 24 Jul 2019 11:48:43 +0800 Subject: [PATCH 1845/7155] blk-mq: remove blk_mq_complete_request_sync blk_mq_tagset_wait_completed_request() has been applied for waiting for completed request's fn, so not necessary to use blk_mq_complete_request_sync() any more. Cc: Max Gurtovoy Cc: Sagi Grimberg Cc: Keith Busch Cc: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk-mq.c | 7 ------- drivers/nvme/host/core.c | 2 +- include/linux/blk-mq.h | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 8bb5854a62f3..6968de9d7402 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -652,13 +652,6 @@ bool blk_mq_complete_request(struct request *rq) } EXPORT_SYMBOL(blk_mq_complete_request); -void blk_mq_complete_request_sync(struct request *rq) -{ - WRITE_ONCE(rq->state, MQ_RQ_COMPLETE); - rq->q->mq_ops->complete(rq); -} -EXPORT_SYMBOL_GPL(blk_mq_complete_request_sync); - int blk_mq_request_started(struct request *rq) { return blk_mq_rq_state(rq) != MQ_RQ_IDLE; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index bcede8c879d1..4ba374633dc8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -293,7 +293,7 @@ bool nvme_cancel_request(struct request *req, void *data, bool reserved) return true; nvme_req(req)->status = NVME_SC_ABORT_REQ; - blk_mq_complete_request_sync(req); + blk_mq_complete_request(req); return true; } EXPORT_SYMBOL_GPL(nvme_cancel_request); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index ee0719b649b6..1cdd2788cfa6 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -305,7 +305,6 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); bool blk_mq_complete_request(struct request *rq); -void blk_mq_complete_request_sync(struct request *rq); bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, struct bio *bio, unsigned int nr_segs); bool blk_mq_queue_stopped(struct request_queue *q); -- GitLab From af2c68fe94e8c0a628519b60ba070c5cf6526a99 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:50:40 -0700 Subject: [PATCH 1846/7155] block: Declare several function pointer arguments 'const' Make it clear to the compiler and also to humans that the functions that query request queue properties do not modify any member of the request_queue data structure. Reviewed-by: Johannes Thumshirn Cc: Christoph Hellwig Cc: Ming Lei Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-merge.c | 7 ++++--- include/linux/blkdev.h | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 57f7990b342d..8344d94f13e0 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -144,7 +144,7 @@ static inline unsigned get_max_io_size(struct request_queue *q, return sectors; } -static unsigned get_max_segment_size(struct request_queue *q, +static unsigned get_max_segment_size(const struct request_queue *q, unsigned offset) { unsigned long mask = queue_segment_boundary(q); @@ -161,8 +161,9 @@ static unsigned get_max_segment_size(struct request_queue *q, * Split the bvec @bv into segments, and update all kinds of * variables. */ -static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv, - unsigned *nsegs, unsigned *sectors, unsigned max_segs) +static bool bvec_split_segs(const struct request_queue *q, + const struct bio_vec *bv, unsigned *nsegs, + unsigned *sectors, unsigned max_segs) { unsigned len = bv->bv_len; unsigned total_len = 0; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1ef375dafb1c..96a29a72fd4a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1232,42 +1232,42 @@ enum blk_default_limits { BLK_SEG_BOUNDARY_MASK = 0xFFFFFFFFUL, }; -static inline unsigned long queue_segment_boundary(struct request_queue *q) +static inline unsigned long queue_segment_boundary(const struct request_queue *q) { return q->limits.seg_boundary_mask; } -static inline unsigned long queue_virt_boundary(struct request_queue *q) +static inline unsigned long queue_virt_boundary(const struct request_queue *q) { return q->limits.virt_boundary_mask; } -static inline unsigned int queue_max_sectors(struct request_queue *q) +static inline unsigned int queue_max_sectors(const struct request_queue *q) { return q->limits.max_sectors; } -static inline unsigned int queue_max_hw_sectors(struct request_queue *q) +static inline unsigned int queue_max_hw_sectors(const struct request_queue *q) { return q->limits.max_hw_sectors; } -static inline unsigned short queue_max_segments(struct request_queue *q) +static inline unsigned short queue_max_segments(const struct request_queue *q) { return q->limits.max_segments; } -static inline unsigned short queue_max_discard_segments(struct request_queue *q) +static inline unsigned short queue_max_discard_segments(const struct request_queue *q) { return q->limits.max_discard_segments; } -static inline unsigned int queue_max_segment_size(struct request_queue *q) +static inline unsigned int queue_max_segment_size(const struct request_queue *q) { return q->limits.max_segment_size; } -static inline unsigned short queue_logical_block_size(struct request_queue *q) +static inline unsigned short queue_logical_block_size(const struct request_queue *q) { int retval = 512; @@ -1282,7 +1282,7 @@ static inline unsigned short bdev_logical_block_size(struct block_device *bdev) return queue_logical_block_size(bdev_get_queue(bdev)); } -static inline unsigned int queue_physical_block_size(struct request_queue *q) +static inline unsigned int queue_physical_block_size(const struct request_queue *q) { return q->limits.physical_block_size; } @@ -1292,7 +1292,7 @@ static inline unsigned int bdev_physical_block_size(struct block_device *bdev) return queue_physical_block_size(bdev_get_queue(bdev)); } -static inline unsigned int queue_io_min(struct request_queue *q) +static inline unsigned int queue_io_min(const struct request_queue *q) { return q->limits.io_min; } @@ -1302,7 +1302,7 @@ static inline int bdev_io_min(struct block_device *bdev) return queue_io_min(bdev_get_queue(bdev)); } -static inline unsigned int queue_io_opt(struct request_queue *q) +static inline unsigned int queue_io_opt(const struct request_queue *q) { return q->limits.io_opt; } @@ -1312,7 +1312,7 @@ static inline int bdev_io_opt(struct block_device *bdev) return queue_io_opt(bdev_get_queue(bdev)); } -static inline int queue_alignment_offset(struct request_queue *q) +static inline int queue_alignment_offset(const struct request_queue *q) { if (q->limits.misaligned) return -1; @@ -1342,7 +1342,7 @@ static inline int bdev_alignment_offset(struct block_device *bdev) return q->limits.alignment_offset; } -static inline int queue_discard_alignment(struct request_queue *q) +static inline int queue_discard_alignment(const struct request_queue *q) { if (q->limits.discard_misaligned) return -1; @@ -1432,7 +1432,7 @@ static inline sector_t bdev_zone_sectors(struct block_device *bdev) return 0; } -static inline int queue_dma_alignment(struct request_queue *q) +static inline int queue_dma_alignment(const struct request_queue *q) { return q ? q->dma_alignment : 511; } @@ -1543,7 +1543,7 @@ static inline void blk_queue_max_integrity_segments(struct request_queue *q, } static inline unsigned short -queue_max_integrity_segments(struct request_queue *q) +queue_max_integrity_segments(const struct request_queue *q) { return q->limits.max_integrity_segments; } @@ -1626,7 +1626,7 @@ static inline void blk_queue_max_integrity_segments(struct request_queue *q, unsigned int segs) { } -static inline unsigned short queue_max_integrity_segments(struct request_queue *q) +static inline unsigned short queue_max_integrity_segments(const struct request_queue *q) { return 0; } -- GitLab From dad7758459bc6097115f5e783eda232f36b1ad99 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:50:41 -0700 Subject: [PATCH 1847/7155] block: Document the bio splitting functions Since what the bio splitting functions do is nontrivial, document these functions. Reviewed-by: Johannes Thumshirn Cc: Christoph Hellwig Cc: Ming Lei Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/bio.c | 4 ++-- block/blk-merge.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/block/bio.c b/block/bio.c index 299a0e7651ec..0fff4eb9eb1e 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1842,8 +1842,8 @@ EXPORT_SYMBOL(bio_endio); * @bio, and updates @bio to represent the remaining sectors. * * Unless this is a discard request the newly allocated bio will point - * to @bio's bi_io_vec; it is the caller's responsibility to ensure that - * @bio is not freed before the split. + * to @bio's bi_io_vec. It is the caller's responsibility to ensure that + * neither @bio nor @bs are freed before the split bio. */ struct bio *bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs) diff --git a/block/blk-merge.c b/block/blk-merge.c index 8344d94f13e0..51ed971709c3 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -195,6 +195,25 @@ static bool bvec_split_segs(const struct request_queue *q, return !!len; } +/** + * blk_bio_segment_split - split a bio in two bios + * @q: [in] request queue pointer + * @bio: [in] bio to be split + * @bs: [in] bio set to allocate the clone from + * @segs: [out] number of segments in the bio with the first half of the sectors + * + * Clone @bio, update the bi_iter of the clone to represent the first sectors + * of @bio and update @bio->bi_iter to represent the remaining sectors. The + * following is guaranteed for the cloned bio: + * - That it has at most get_max_io_size(@q, @bio) sectors. + * - That it has at most queue_max_segments(@q) segments. + * + * Except for discard requests the cloned bio will point at the bi_io_vec of + * the original bio. It is the responsibility of the caller to ensure that the + * original bio is not freed before the cloned bio. The caller is also + * responsible for ensuring that @bs is only destroyed after processing of the + * split bio has finished. + */ static struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *bio, struct bio_set *bs, @@ -251,6 +270,19 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, return bio_split(bio, sectors, GFP_NOIO, bs); } +/** + * __blk_queue_split - split a bio and submit the second half + * @q: [in] request queue pointer + * @bio: [in, out] bio to be split + * @nr_segs: [out] number of segments in the first bio + * + * Split a bio into two bios, chain the two bios, submit the second half and + * store a pointer to the first half in *@bio. If the second bio is still too + * big it will be split by a recursive call to this function. Since this + * function may allocate a new bio from @q->bio_split, it is the responsibility + * of the caller to ensure that @q is only released after processing of the + * split bio has finished. + */ void __blk_queue_split(struct request_queue *q, struct bio **bio, unsigned int *nr_segs) { @@ -295,6 +327,17 @@ void __blk_queue_split(struct request_queue *q, struct bio **bio, } } +/** + * blk_queue_split - split a bio and submit the second half + * @q: [in] request queue pointer + * @bio: [in, out] bio to be split + * + * Split a bio into two bios, chains the two bios, submit the second half and + * store a pointer to the first half in *@bio. Since this function may allocate + * a new bio from @q->bio_split, it is the responsibility of the caller to + * ensure that @q is only released after processing of the split bio has + * finished. + */ void blk_queue_split(struct request_queue *q, struct bio **bio) { unsigned int nr_segs; -- GitLab From ff9811b3cf2092fe6c39cf694e5e7f949f3b2c16 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:50:42 -0700 Subject: [PATCH 1848/7155] block: Simplify bvec_split_segs() Simplify this function by by removing two if-tests. Other than requiring that the @sectors pointer is not NULL, this patch does not change the behavior of bvec_split_segs(). Reviewed-by: Johannes Thumshirn Cc: Christoph Hellwig Cc: Ming Lei Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-merge.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 51ed971709c3..7cea5050bbcf 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -167,17 +167,17 @@ static bool bvec_split_segs(const struct request_queue *q, { unsigned len = bv->bv_len; unsigned total_len = 0; - unsigned new_nsegs = 0, seg_size = 0; + unsigned seg_size = 0; /* * Multi-page bvec may be too big to hold in one segment, so the * current bvec has to be splitted as multiple segments. */ - while (len && new_nsegs + *nsegs < max_segs) { + while (len && *nsegs < max_segs) { seg_size = get_max_segment_size(q, bv->bv_offset + total_len); seg_size = min(seg_size, len); - new_nsegs++; + (*nsegs)++; total_len += seg_size; len -= seg_size; @@ -185,11 +185,7 @@ static bool bvec_split_segs(const struct request_queue *q, break; } - if (new_nsegs) { - *nsegs += new_nsegs; - if (sectors) - *sectors += total_len >> 9; - } + *sectors += total_len >> 9; /* split in the middle of the bvec if len != 0 */ return !!len; @@ -349,6 +345,7 @@ EXPORT_SYMBOL(blk_queue_split); unsigned int blk_recalc_rq_segments(struct request *rq) { unsigned int nr_phys_segs = 0; + unsigned int nr_sectors = 0; struct req_iterator iter; struct bio_vec bv; @@ -365,7 +362,8 @@ unsigned int blk_recalc_rq_segments(struct request *rq) } rq_for_each_bvec(bv, rq, iter) - bvec_split_segs(rq->q, &bv, &nr_phys_segs, NULL, UINT_MAX); + bvec_split_segs(rq->q, &bv, &nr_phys_segs, &nr_sectors, + UINT_MAX); return nr_phys_segs; } -- GitLab From 708b25b344fd9bedd02ccc0f8eee71f7006d7d07 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:50:43 -0700 Subject: [PATCH 1849/7155] block: Simplify blk_bio_segment_split() Move the max_sectors check into bvec_split_segs() such that a single call to that function can do all the necessary checks. This patch optimizes the fast path further, namely if a bvec fits in a page. Cc: Christoph Hellwig Cc: Ming Lei Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-merge.c | 68 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 7cea5050bbcf..a6bc08255b1b 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -157,22 +157,36 @@ static unsigned get_max_segment_size(const struct request_queue *q, queue_max_segment_size(q)); } -/* - * Split the bvec @bv into segments, and update all kinds of - * variables. +/** + * bvec_split_segs - verify whether or not a bvec should be split in the middle + * @q: [in] request queue associated with the bio associated with @bv + * @bv: [in] bvec to examine + * @nsegs: [in,out] Number of segments in the bio being built. Incremented + * by the number of segments from @bv that may be appended to that + * bio without exceeding @max_segs + * @sectors: [in,out] Number of sectors in the bio being built. Incremented + * by the number of sectors from @bv that may be appended to that + * bio without exceeding @max_sectors + * @max_segs: [in] upper bound for *@nsegs + * @max_sectors: [in] upper bound for *@sectors + * + * When splitting a bio, it can happen that a bvec is encountered that is too + * big to fit in a single segment and hence that it has to be split in the + * middle. This function verifies whether or not that should happen. The value + * %true is returned if and only if appending the entire @bv to a bio with + * *@nsegs segments and *@sectors sectors would make that bio unacceptable for + * the block driver. */ static bool bvec_split_segs(const struct request_queue *q, const struct bio_vec *bv, unsigned *nsegs, - unsigned *sectors, unsigned max_segs) + unsigned *sectors, unsigned max_segs, + unsigned max_sectors) { - unsigned len = bv->bv_len; + unsigned max_len = (min(max_sectors, UINT_MAX >> 9) - *sectors) << 9; + unsigned len = min(bv->bv_len, max_len); unsigned total_len = 0; unsigned seg_size = 0; - /* - * Multi-page bvec may be too big to hold in one segment, so the - * current bvec has to be splitted as multiple segments. - */ while (len && *nsegs < max_segs) { seg_size = get_max_segment_size(q, bv->bv_offset + total_len); seg_size = min(seg_size, len); @@ -187,8 +201,8 @@ static bool bvec_split_segs(const struct request_queue *q, *sectors += total_len >> 9; - /* split in the middle of the bvec if len != 0 */ - return !!len; + /* tell the caller to split the bvec if it is too big to fit */ + return len > 0 || bv->bv_len > max_len; } /** @@ -229,34 +243,18 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset)) goto split; - if (sectors + (bv.bv_len >> 9) > max_sectors) { - /* - * Consider this a new segment if we're splitting in - * the middle of this vector. - */ - if (nsegs < max_segs && - sectors < max_sectors) { - /* split in the middle of bvec */ - bv.bv_len = (max_sectors - sectors) << 9; - bvec_split_segs(q, &bv, &nsegs, - §ors, max_segs); - } + if (nsegs < max_segs && + sectors + (bv.bv_len >> 9) <= max_sectors && + bv.bv_offset + bv.bv_len <= PAGE_SIZE) { + nsegs++; + sectors += bv.bv_len >> 9; + } else if (bvec_split_segs(q, &bv, &nsegs, §ors, max_segs, + max_sectors)) { goto split; } - if (nsegs == max_segs) - goto split; - bvprv = bv; bvprvp = &bvprv; - - if (bv.bv_offset + bv.bv_len <= PAGE_SIZE) { - nsegs++; - sectors += bv.bv_len >> 9; - } else if (bvec_split_segs(q, &bv, &nsegs, §ors, - max_segs)) { - goto split; - } } *segs = nsegs; @@ -363,7 +361,7 @@ unsigned int blk_recalc_rq_segments(struct request *rq) rq_for_each_bvec(bv, rq, iter) bvec_split_segs(rq->q, &bv, &nr_phys_segs, &nr_sectors, - UINT_MAX); + UINT_MAX, UINT_MAX); return nr_phys_segs; } -- GitLab From 9cc5169cd478bc596902a57580804f1da3dfd74e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:50:44 -0700 Subject: [PATCH 1850/7155] block: Improve physical block alignment of split bios Consider the following example: * The logical block size is 4 KB. * The physical block size is 8 KB. * max_sectors equals (16 KB >> 9) sectors. * A non-aligned 4 KB and an aligned 64 KB bio are merged into a single non-aligned 68 KB bio. The current behavior is to split such a bio into (16 KB + 16 KB + 16 KB + 16 KB + 4 KB). The start of none of these five bio's is aligned to a physical block boundary. This patch ensures that such a bio is split into four aligned and one non-aligned bio instead of being split into five non-aligned bios. This improves performance because most block devices can handle aligned requests faster than non-aligned requests. Since the physical block size is larger than or equal to the logical block size, this patch preserves the guarantee that the returned value is a multiple of the logical block size. Cc: Christoph Hellwig Cc: Ming Lei Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-merge.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index a6bc08255b1b..48e6725b32ee 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -132,16 +132,29 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q, return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs); } +/* + * Return the maximum number of sectors from the start of a bio that may be + * submitted as a single request to a block device. If enough sectors remain, + * align the end to the physical block size. Otherwise align the end to the + * logical block size. This approach minimizes the number of non-aligned + * requests that are submitted to a block device if the start of a bio is not + * aligned to a physical block boundary. + */ static inline unsigned get_max_io_size(struct request_queue *q, struct bio *bio) { unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector); - unsigned mask = queue_logical_block_size(q) - 1; + unsigned max_sectors = sectors; + unsigned pbs = queue_physical_block_size(q) >> SECTOR_SHIFT; + unsigned lbs = queue_logical_block_size(q) >> SECTOR_SHIFT; + unsigned start_offset = bio->bi_iter.bi_sector & (pbs - 1); - /* aligned to logical block size */ - sectors &= ~(mask >> 9); + max_sectors += start_offset; + max_sectors &= ~(pbs - 1); + if (max_sectors > start_offset) + return max_sectors - start_offset; - return sectors; + return sectors & (lbs - 1); } static unsigned get_max_segment_size(const struct request_queue *q, -- GitLab From 012d4a652ca172d93315cb69f2adf7df37ea77e6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:39:07 -0700 Subject: [PATCH 1851/7155] block: Fix spelling in the header above blkg_lookup() See also commit 8f4236d9008b ("block: remove QUEUE_FLAG_BYPASS and ->bypass") # v5.0. Cc: Christoph Hellwig Cc: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- include/linux/blk-cgroup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 12811091fd50..0bb79d858a13 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -375,7 +375,7 @@ static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, * @q: request_queue of interest * * Lookup blkg for the @blkcg - @q pair. This function should be called - * under RCU read loc. + * under RCU read lock. */ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, struct request_queue *q) -- GitLab From 67ed8b738633f8c309cfdbfdf501e09d3759ce0c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 1 Aug 2019 15:39:55 -0700 Subject: [PATCH 1852/7155] block: Fix a comment in blk_cleanup_queue() Change a reference to the legacy block layer into a reference to blk-mq. Reviewed-by: Chaitanya Kulkarni Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: James Smart Cc: Ming Lei Cc: Jianchao Wang Cc: Dongli Zhang Signed-off-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index d0cc6e14d2f0..5878504a29af 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -344,7 +344,8 @@ void blk_cleanup_queue(struct request_queue *q) /* * Drain all requests queued before DYING marking. Set DEAD flag to - * prevent that q->request_fn() gets invoked after draining finished. + * prevent that blk_mq_run_hw_queues() accesses the hardware queues + * after draining finished. */ blk_freeze_queue(q); -- GitLab From e84e8f0663956f45c747df5629046794cff93893 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 1 Aug 2019 10:26:35 -0700 Subject: [PATCH 1853/7155] block: add req op to reset all zones and flag This patch introduces a new request operation REQ_OP_ZONE_RESET_ALL. This is useful for the applications like mkfs where it needs to reset all the zones present on the underlying block device. As part for this patch we also introduce new QUEUE_FLAG_ZONE_RESETALL which indicates the queue zone reset all capability and corresponding helper macro. Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- include/linux/blk_types.h | 2 ++ include/linux/blkdev.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 1b1fa1557e68..d6ce7b3ec8b1 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -282,6 +282,8 @@ enum req_opf { REQ_OP_ZONE_RESET = 6, /* write the same sector many times */ REQ_OP_WRITE_SAME = 7, + /* reset all the zone present on the device */ + REQ_OP_ZONE_RESET_ALL = 8, /* write the zero filled sector many times */ REQ_OP_WRITE_ZEROES = 9, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 96a29a72fd4a..167bf879f072 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -611,6 +611,7 @@ struct request_queue { #define QUEUE_FLAG_SCSI_PASSTHROUGH 23 /* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 24 /* queue has been quiesced */ #define QUEUE_FLAG_PCI_P2PDMA 25 /* device supports PCI p2p requests */ +#define QUEUE_FLAG_ZONE_RESETALL 26 /* supports Zone Reset All */ #define QUEUE_FLAG_MQ_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_SAME_COMP)) @@ -630,6 +631,8 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q); #define blk_queue_io_stat(q) test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags) #define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags) #define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags) +#define blk_queue_zone_resetall(q) \ + test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags) #define blk_queue_secure_erase(q) \ (test_bit(QUEUE_FLAG_SECERASE, &(q)->queue_flags)) #define blk_queue_dax(q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags) -- GitLab From 6e33dbf280d60db8c1c11dbf99c0bc475946f9c8 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 1 Aug 2019 10:26:36 -0700 Subject: [PATCH 1854/7155] blk-zoned: implement REQ_OP_ZONE_RESET_ALL This implements REQ_OP_ZONE_RESET_ALL as a special case of the block device zone reset operations where we just simply issue bio with the newly introduced req op. We issue this req op when the number of sectors is equal to the device's partition's number of sectors and device has no partitions. We also add support so that blk_op_str() can print the new reset-all zone operation. This patch also adds a generic make request check for newly introduced REQ_OP_ZONE_RESET_ALL req_opf. We simply return error when queue is zoned and reset-all flag is not set for REQ_OP_ZONE_RESET_ALL. Reviewed-by: Hannes Reinecke Reviewed-by: Damien Le Moal Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- block/blk-core.c | 5 +++++ block/blk-zoned.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 5878504a29af..919629ce4015 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -129,6 +129,7 @@ static const char *const blk_op_name[] = { REQ_OP_NAME(DISCARD), REQ_OP_NAME(SECURE_ERASE), REQ_OP_NAME(ZONE_RESET), + REQ_OP_NAME(ZONE_RESET_ALL), REQ_OP_NAME(WRITE_SAME), REQ_OP_NAME(WRITE_ZEROES), REQ_OP_NAME(SCSI_IN), @@ -932,6 +933,10 @@ generic_make_request_checks(struct bio *bio) if (!blk_queue_is_zoned(q)) goto not_supported; break; + case REQ_OP_ZONE_RESET_ALL: + if (!blk_queue_is_zoned(q) || !blk_queue_zone_resetall(q)) + goto not_supported; + break; case REQ_OP_WRITE_ZEROES: if (!q->limits.max_write_zeroes_sectors) goto not_supported; diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 6c503824ba3f..4bc5f260248a 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -202,6 +202,42 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, } EXPORT_SYMBOL_GPL(blkdev_report_zones); +/* + * Special case of zone reset operation to reset all zones in one command, + * useful for applications like mkfs. + */ +static int __blkdev_reset_all_zones(struct block_device *bdev, gfp_t gfp_mask) +{ + struct bio *bio = bio_alloc(gfp_mask, 0); + int ret; + + /* across the zones operations, don't need any sectors */ + bio_set_dev(bio, bdev); + bio_set_op_attrs(bio, REQ_OP_ZONE_RESET_ALL, 0); + + ret = submit_bio_wait(bio); + bio_put(bio); + + return ret; +} + +static inline bool blkdev_allow_reset_all_zones(struct block_device *bdev, + sector_t nr_sectors) +{ + if (!blk_queue_zone_resetall(bdev_get_queue(bdev))) + return false; + + if (nr_sectors != part_nr_sects_read(bdev->bd_part)) + return false; + /* + * REQ_OP_ZONE_RESET_ALL can be executed only if the block device is + * the entire disk, that is, if the blocks device start offset is 0 and + * its capacity is the same as the entire disk. + */ + return get_start_sect(bdev) == 0 && + part_nr_sects_read(bdev->bd_part) == get_capacity(bdev->bd_disk); +} + /** * blkdev_reset_zones - Reset zones write pointer * @bdev: Target block device @@ -235,6 +271,9 @@ int blkdev_reset_zones(struct block_device *bdev, /* Out of range */ return -EINVAL; + if (blkdev_allow_reset_all_zones(bdev, nr_sectors)) + return __blkdev_reset_all_zones(bdev, gfp_mask); + /* Check alignment (handle eventual smaller last zone) */ zone_sectors = blk_queue_zone_sectors(q); if (sector & (zone_sectors - 1)) -- GitLab From d81e9d494354064cd0a99d08401097dd16f335c0 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 1 Aug 2019 10:26:37 -0700 Subject: [PATCH 1855/7155] scsi: implement REQ_OP_ZONE_RESET_ALL This patch implements the zone reset all operation for sd_zbc.c. We add a new boolean parameter for the sd_zbc_setup_reset_cmd() to indicate REQ_OP_ZONE_RESET_ALL command setup. Along with that we add support in the completion path for the zone reset all. Reviewed-by: Hannes Reinecke Reviewed-by: Damien Le Moal Signed-off-by: Chaitanya Kulkarni Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 5 ++++- drivers/scsi/sd.h | 5 +++-- drivers/scsi/sd_zbc.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 149d406aacc9..4b925552458f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1293,7 +1293,9 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd) case REQ_OP_WRITE: return sd_setup_read_write_cmnd(cmd); case REQ_OP_ZONE_RESET: - return sd_zbc_setup_reset_cmnd(cmd); + return sd_zbc_setup_reset_cmnd(cmd, false); + case REQ_OP_ZONE_RESET_ALL: + return sd_zbc_setup_reset_cmnd(cmd, true); default: WARN_ON_ONCE(1); return BLK_STS_NOTSUPP; @@ -1959,6 +1961,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) case REQ_OP_WRITE_ZEROES: case REQ_OP_WRITE_SAME: case REQ_OP_ZONE_RESET: + case REQ_OP_ZONE_RESET_ALL: if (!result) { good_bytes = blk_rq_bytes(req); scsi_set_resid(SCpnt, 0); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 38c50946fc42..1eab779f812b 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -209,7 +209,7 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp) extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer); extern void sd_zbc_print_zones(struct scsi_disk *sdkp); -extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd); +extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all); extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes, struct scsi_sense_hdr *sshdr); extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, @@ -225,7 +225,8 @@ static inline int sd_zbc_read_zones(struct scsi_disk *sdkp, static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {} -static inline blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd) +static inline blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, + bool all) { return BLK_STS_TARGET; } diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 5d6ff3931632..367614f0e34f 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -209,10 +209,11 @@ static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) /** * sd_zbc_setup_reset_cmnd - Prepare a RESET WRITE POINTER scsi command. * @cmd: the command to setup + * @all: Reset all zones control. * * Called from sd_init_command() for a REQ_OP_ZONE_RESET request. */ -blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd) +blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all) { struct request *rq = cmd->request; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); @@ -234,7 +235,10 @@ blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd) memset(cmd->cmnd, 0, cmd->cmd_len); cmd->cmnd[0] = ZBC_OUT; cmd->cmnd[1] = ZO_RESET_WRITE_POINTER; - put_unaligned_be64(block, &cmd->cmnd[2]); + if (all) + cmd->cmnd[14] = 0x1; + else + put_unaligned_be64(block, &cmd->cmnd[2]); rq->timeout = SD_TIMEOUT; cmd->sc_data_direction = DMA_NONE; @@ -261,6 +265,7 @@ void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes, switch (req_op(rq)) { case REQ_OP_ZONE_RESET: + case REQ_OP_ZONE_RESET_ALL: if (result && sshdr->sense_key == ILLEGAL_REQUEST && @@ -487,6 +492,7 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) /* The drive satisfies the kernel restrictions: set it up */ blk_queue_chunk_sectors(sdkp->disk->queue, logical_to_sectors(sdkp->device, zone_blocks)); + blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, sdkp->disk->queue); nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks); /* READ16/WRITE16 is mandatory for ZBC disks */ -- GitLab From a61dbfb12bc6dadce91600fe3409a3675751c716 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 1 Aug 2019 10:26:38 -0700 Subject: [PATCH 1856/7155] null_blk: implement REQ_OP_ZONE_RESET_ALL This patch implements newly introduced zone reset all operation for null_blk driver. Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 3 +++ drivers/block/null_blk_zoned.c | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 99328ded60d1..99c56d72ff78 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1214,6 +1214,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) null_zone_write(cmd, sector, nr_sectors); else if (op == REQ_OP_ZONE_RESET) null_zone_reset(cmd, sector); + else if (op == REQ_OP_ZONE_RESET_ALL) + null_zone_reset(cmd, 0); } out: /* Complete IO by inline, softirq or timer */ @@ -1688,6 +1690,7 @@ static int null_add_dev(struct nullb_device *dev) blk_queue_chunk_sectors(nullb->q, dev->zone_size_sects); nullb->q->limits.zoned = BLK_ZONED_HM; + blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, nullb->q); } nullb->q->queuedata = nullb; diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index cb28d93f2bd1..8c7f5bf81975 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -125,12 +125,28 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) struct nullb_device *dev = cmd->nq->dev; unsigned int zno = null_zone_no(dev, sector); struct blk_zone *zone = &dev->zones[zno]; + size_t i; + + switch (req_op(cmd->rq)) { + case REQ_OP_ZONE_RESET_ALL: + for (i = 0; i < dev->nr_zones; i++) { + if (zone[i].type == BLK_ZONE_TYPE_CONVENTIONAL) + continue; + zone[i].cond = BLK_ZONE_COND_EMPTY; + zone[i].wp = zone[i].start; + } + break; + case REQ_OP_ZONE_RESET: + if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) { + cmd->error = BLK_STS_IOERR; + return; + } - if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) { - cmd->error = BLK_STS_IOERR; - return; + zone->cond = BLK_ZONE_COND_EMPTY; + zone->wp = zone->start; + break; + default: + cmd->error = BLK_STS_NOTSUPP; + break; } - - zone->cond = BLK_ZONE_COND_EMPTY; - zone->wp = zone->start; } -- GitLab From 226b4fc75c78f9c497c5182d939101b260cfb9f3 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 25 Jul 2019 10:04:59 +0800 Subject: [PATCH 1857/7155] blk-mq: add callback of .cleanup_rq SCSI maintains its own driver private data hooked off of each SCSI request, and the pridate data won't be freed after scsi_queue_rq() returns BLK_STS_RESOURCE or BLK_STS_DEV_RESOURCE. An upper layer driver (e.g. dm-rq) may need to retry these SCSI requests, before SCSI has fully dispatched them, due to a lower level SCSI driver's resource limitation identified in scsi_queue_rq(). Currently SCSI's per-request private data is leaked when the upper layer driver (dm-rq) frees and then retries these requests in response to BLK_STS_RESOURCE or BLK_STS_DEV_RESOURCE returns from scsi_queue_rq(). This usecase is so specialized that it doesn't warrant training an existing blk-mq interface (e.g. blk_mq_free_request) to allow SCSI to account for freeing its driver private data -- doing so would add an extra branch for handling a special case that all other consumers of SCSI (and blk-mq) won't ever need to worry about. So the most pragmatic way forward is to delegate freeing SCSI driver private data to the upper layer driver (dm-rq). Do so by adding new .cleanup_rq callback and calling a new blk_mq_cleanup_rq() method from dm-rq. A following commit will implement the .cleanup_rq() hook in scsi_mq_ops. Cc: Ewan D. Milne Cc: Bart Van Assche Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Mike Snitzer Cc: dm-devel@redhat.com Cc: Fixes: 396eaf21ee17 ("blk-mq: improve DM's blk-mq IO merging via blk_insert_cloned_request feedback") Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/md/dm-rq.c | 1 + include/linux/blk-mq.h | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index c9e44ac1f9a6..21d5c1784d0c 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -408,6 +408,7 @@ static int map_request(struct dm_rq_target_io *tio) ret = dm_dispatch_clone_request(clone, rq); if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) { blk_rq_unprep_clone(clone); + blk_mq_cleanup_rq(clone); tio->ti->type->release_clone_rq(clone, &tio->info); tio->clone = NULL; return DM_MAPIO_REQUEUE; diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 1cdd2788cfa6..21cebe901ac0 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -140,6 +140,7 @@ typedef int (poll_fn)(struct blk_mq_hw_ctx *); typedef int (map_queues_fn)(struct blk_mq_tag_set *set); typedef bool (busy_fn)(struct request_queue *); typedef void (complete_fn)(struct request *); +typedef void (cleanup_rq_fn)(struct request *); struct blk_mq_ops { @@ -200,6 +201,12 @@ struct blk_mq_ops { /* Called from inside blk_get_request() */ void (*initialize_rq_fn)(struct request *rq); + /* + * Called before freeing one request which isn't completed yet, + * and usually for freeing the driver private data + */ + cleanup_rq_fn *cleanup_rq; + /* * If set, returns whether or not this queue currently is busy */ @@ -367,4 +374,10 @@ static inline blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, BLK_QC_T_INTERNAL; } +static inline void blk_mq_cleanup_rq(struct request *rq) +{ + if (rq->q->mq_ops->cleanup_rq) + rq->q->mq_ops->cleanup_rq(rq); +} + #endif -- GitLab From b7e9e1fb7a9227be34ad4a5e778022c3164494cf Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 25 Jul 2019 10:05:00 +0800 Subject: [PATCH 1858/7155] scsi: implement .cleanup_rq callback Implement .cleanup_rq() callback for freeing driver private part of the request. Then we can avoid to leak this part if the request isn't completed by SCSI, and freed by blk-mq or upper layer(such as dm-rq) finally. Cc: Ewan D. Milne Cc: Bart Van Assche Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Mike Snitzer Cc: dm-devel@redhat.com Cc: Fixes: 396eaf21ee17 ("blk-mq: improve DM's blk-mq IO merging via blk_insert_cloned_request feedback") Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/scsi/scsi_lib.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 11e64b50497f..4e88d7e9cf9a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1089,6 +1089,18 @@ static void scsi_initialize_rq(struct request *rq) cmd->retries = 0; } +/* + * Only called when the request isn't completed by SCSI, and not freed by + * SCSI + */ +static void scsi_cleanup_rq(struct request *rq) +{ + if (rq->rq_flags & RQF_DONTPREP) { + scsi_mq_uninit_cmd(blk_mq_rq_to_pdu(rq)); + rq->rq_flags &= ~RQF_DONTPREP; + } +} + /* Add a command to the list used by the aacraid and dpt_i2o drivers */ void scsi_add_cmd_to_list(struct scsi_cmnd *cmd) { @@ -1821,6 +1833,7 @@ static const struct blk_mq_ops scsi_mq_ops = { .init_request = scsi_mq_init_request, .exit_request = scsi_mq_exit_request, .initialize_rq_fn = scsi_initialize_rq, + .cleanup_rq = scsi_cleanup_rq, .busy = scsi_mq_lld_busy, .map_queues = scsi_map_queues, }; -- GitLab From 556f36e90dbe7dded81f4fac084d2bc8a2458330 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 25 Jul 2019 17:41:46 +0800 Subject: [PATCH 1859/7155] blk-mq: balance mapping between present CPUs and queues Spread queues among present CPUs first, then building mapping on other non-present CPUs. So we can minimize count of dead queues which are mapped by un-present CPUs only. Then bad IO performance can be avoided by unbalanced mapping between present CPUs and queues. The similar policy has been applied on Managed IRQ affinity. Cc: Yi Zhang Reported-by: Yi Zhang Reviewed-by: Bob Liu Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk-mq-cpumap.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c index f945621a0e8f..0157f2b3485a 100644 --- a/block/blk-mq-cpumap.c +++ b/block/blk-mq-cpumap.c @@ -15,10 +15,10 @@ #include "blk.h" #include "blk-mq.h" -static int cpu_to_queue_index(struct blk_mq_queue_map *qmap, - unsigned int nr_queues, const int cpu) +static int queue_index(struct blk_mq_queue_map *qmap, + unsigned int nr_queues, const int q) { - return qmap->queue_offset + (cpu % nr_queues); + return qmap->queue_offset + (q % nr_queues); } static int get_first_sibling(unsigned int cpu) @@ -36,21 +36,36 @@ int blk_mq_map_queues(struct blk_mq_queue_map *qmap) { unsigned int *map = qmap->mq_map; unsigned int nr_queues = qmap->nr_queues; - unsigned int cpu, first_sibling; + unsigned int cpu, first_sibling, q = 0; + + for_each_possible_cpu(cpu) + map[cpu] = -1; + + /* + * Spread queues among present CPUs first for minimizing + * count of dead queues which are mapped by all un-present CPUs + */ + for_each_present_cpu(cpu) { + if (q >= nr_queues) + break; + map[cpu] = queue_index(qmap, nr_queues, q++); + } for_each_possible_cpu(cpu) { + if (map[cpu] != -1) + continue; /* * First do sequential mapping between CPUs and queues. * In case we still have CPUs to map, and we have some number of * threads per cores then map sibling threads to the same queue * for performance optimizations. */ - if (cpu < nr_queues) { - map[cpu] = cpu_to_queue_index(qmap, nr_queues, cpu); + if (q < nr_queues) { + map[cpu] = queue_index(qmap, nr_queues, q++); } else { first_sibling = get_first_sibling(cpu); if (first_sibling == cpu) - map[cpu] = cpu_to_queue_index(qmap, nr_queues, cpu); + map[cpu] = queue_index(qmap, nr_queues, q++); else map[cpu] = map[first_sibling]; } -- GitLab From aaefca8e30d9df7a4ca13c9c8e135dd227b8ff19 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 18 Jul 2019 11:29:20 -0700 Subject: [PATCH 1860/7155] x86/mce: Don't check for the overflow bit on action optional machine checks We currently do not process SRAO (Software Recoverable Action Optional) machine checks if they are logged with the overflow bit set to 1 in the machine check bank status register. This is overly conservative. There are two cases where we could end up with an SRAO+OVER log based on the SDM volume 3 overwrite rules in "Table 15-8. Overwrite Rules for UC, CE, and UCR Errors" 1) First a corrected error is logged, then the SRAO error overwrites. The second error overwrites the first because uncorrected errors have a higher severity than corrected errors. 2) The SRAO error was logged first, followed by a correcetd error. In this case the first error is retained in the bank. So in either case the machine check bank will contain the address of the SRAO error. So we can process that even if the overflow bit was set. Reported-by: Yongkai Wu Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: linux-edac Cc: Thomas Gleixner Cc: x86-ml Link: https://lkml.kernel.org/r/20190718182920.32621-1-tony.luck@intel.com --- arch/x86/kernel/cpu/mce/severity.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c index 210f1f5db5f7..87bcdc6dc2f0 100644 --- a/arch/x86/kernel/cpu/mce/severity.c +++ b/arch/x86/kernel/cpu/mce/severity.c @@ -107,11 +107,11 @@ static struct severity { */ MCESEV( AO, "Action optional: memory scrubbing error", - SER, MASK(MCI_STATUS_OVER|MCI_UC_AR|MCACOD_SCRUBMSK, MCI_STATUS_UC|MCACOD_SCRUB) + SER, MASK(MCI_UC_AR|MCACOD_SCRUBMSK, MCI_STATUS_UC|MCACOD_SCRUB) ), MCESEV( AO, "Action optional: last level cache writeback error", - SER, MASK(MCI_STATUS_OVER|MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB) + SER, MASK(MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB) ), /* ignore OVER for UCNA */ -- GitLab From 0d1e16c640ee67dcae65ae8e3c6f58e6d8101047 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 16 Jul 2019 11:43:20 +0200 Subject: [PATCH 1861/7155] PM / Domains: Align in-parameter names for some genpd functions Align in-parameter names for the declarations of pm_genpd_add| remove_subdomain() and of_genpd_add_subdomain() according to their implementations, as to improve consistency. Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 91d9bf497071..baf02ff91a31 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -197,9 +197,9 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev); int pm_genpd_remove_device(struct device *dev); int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *new_subdomain); + struct generic_pm_domain *subdomain); int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *target); + struct generic_pm_domain *subdomain); int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); int pm_genpd_remove(struct generic_pm_domain *genpd); @@ -226,12 +226,12 @@ static inline int pm_genpd_remove_device(struct device *dev) return -ENOSYS; } static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *new_sd) + struct generic_pm_domain *subdomain) { return -ENOSYS; } static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *target) + struct generic_pm_domain *subdomain) { return -ENOSYS; } @@ -282,8 +282,8 @@ int of_genpd_add_provider_onecell(struct device_node *np, struct genpd_onecell_data *data); void of_genpd_del_provider(struct device_node *np); int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); -int of_genpd_add_subdomain(struct of_phandle_args *parent, - struct of_phandle_args *new_subdomain); +int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec); struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n); @@ -316,8 +316,8 @@ static inline int of_genpd_add_device(struct of_phandle_args *args, return -ENODEV; } -static inline int of_genpd_add_subdomain(struct of_phandle_args *parent, - struct of_phandle_args *new_subdomain) +static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec) { return -ENODEV; } -- GitLab From 32b91ca15353b2803d27cfc747156e72dd2cd5d8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 18 Jul 2019 10:53:21 +0200 Subject: [PATCH 1862/7155] cpuidle: menu: Allow tick to be stopped if PM QoS is used After commit 554c8aa8ecad ("sched: idle: Select idle state before stopping the tick") the menu governor prevents the scheduler tick from being stopped (unless stopped already) if there is a PM QoS latency constraint for the given CPU and the target residency of the deepest idle state matching that constraint is below the tick boundary. However, that is problematic if CPUs with PM QoS latency constraints are idle for long times, because it effectively causes the tick to run on them all the time which is wasteful. [It is also confusing and questionable if they are full dynticks CPUs.] To address that issue, make the menu governor allow the tick to be stopped only if the idle duration predicted by it is beyond the tick boundary, except when the shallowest idle state is selected upfront and it is not a "polling" one. Fixes: 554c8aa8ecad ("sched: idle: Select idle state before stopping the tick") Link: https://lore.kernel.org/lkml/79b247b3-e056-610e-9a07-e685dfdaa6c9@gmail.com/ Reported-by: Thomas Lindroth Tested-by: Thomas Lindroth Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index dace4c7f830c..e5a5d0c8d66b 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -301,9 +301,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, !drv->states[0].disabled && !dev->states_usage[0].disable)) { /* * In this case state[0] will be used no matter what, so return - * it right away and keep the tick running. + * it right away and keep the tick running if state[0] is a + * polling one. */ - *stop_tick = false; + *stop_tick = !(drv->states[0].flags & CPUIDLE_FLAG_POLLING); return 0; } @@ -394,16 +395,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, return idx; } - if (s->exit_latency > latency_req) { - /* - * If we break out of the loop for latency reasons, use - * the target residency of the selected state as the - * expected idle duration so that the tick is retained - * as long as that target residency is low enough. - */ - predicted_us = drv->states[idx].target_residency; + if (s->exit_latency > latency_req) break; - } + idx = i; } -- GitLab From cab09f3d2d2a0a6cb3dfb678660d67a2c3764f50 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 19 Jul 2019 12:12:42 +0200 Subject: [PATCH 1863/7155] cpuidle: teo: Allow tick to be stopped if PM QoS is used The TEO goveror prevents the scheduler tick from being stopped (unless stopped already) if there is a PM QoS latency constraint for the given CPU and the target residency of the deepest idle state matching that constraint is below the tick boundary. However, that is problematic if CPUs with PM QoS latency constraints are idle for long times, because it effectively causes the tick to run on them all the time which is wasteful. [It is also confusing and questionable if they are full dynticks CPUs.] To address that issue, modify the TEO governor to carry out the entire search for the most suitable idle state (from the target residency perspective) even if a latency constraint is present, to allow it to determine the expected idle duration in all cases. Also, when using the last several measured idle duration values to refine the idle state selection, make it compare those values with the current expected idle duration value (instead of comparing them with the target residency of the idle state selected so far) which should prevent the tick from being retained when it makes sense to stop it sometimes (especially in the presence of PM QoS latency constraints). Fixes: b26bf6ab716f ("cpuidle: New timer events oriented governor for tickless systems") Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/teo.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c index a2fd81067a13..4d7a60c5b24a 100644 --- a/drivers/cpuidle/governors/teo.c +++ b/drivers/cpuidle/governors/teo.c @@ -242,7 +242,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); int latency_req = cpuidle_governor_latency_req(dev->cpu); unsigned int duration_us, count; - int max_early_idx, idx, i; + int max_early_idx, constraint_idx, idx, i; ktime_t delta_tick; if (dev->last_state_idx >= 0) { @@ -257,6 +257,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, count = 0; max_early_idx = -1; + constraint_idx = drv->state_count; idx = -1; for (i = 0; i < drv->state_count; i++) { @@ -286,16 +287,8 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (s->target_residency > duration_us) break; - if (s->exit_latency > latency_req) { - /* - * If we break out of the loop for latency reasons, use - * the target residency of the selected state as the - * expected idle duration to avoid stopping the tick - * as long as that target residency is low enough. - */ - duration_us = drv->states[idx].target_residency; - goto refine; - } + if (s->exit_latency > latency_req && constraint_idx > i) + constraint_idx = i; idx = i; @@ -321,7 +314,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, duration_us = drv->states[idx].target_residency; } -refine: + /* + * If there is a latency constraint, it may be necessary to use a + * shallower idle state than the one selected so far. + */ + if (constraint_idx < idx) + idx = constraint_idx; + if (idx < 0) { idx = 0; /* No states enabled. Must use 0. */ } else if (idx > 0) { @@ -331,13 +330,12 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, /* * Count and sum the most recent idle duration values less than - * the target residency of the state selected so far, find the - * max. + * the current expected idle duration value. */ for (i = 0; i < INTERVALS; i++) { unsigned int val = cpu_data->intervals[i]; - if (val >= drv->states[idx].target_residency) + if (val >= duration_us) continue; count++; @@ -356,8 +354,10 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, * would be too shallow. */ if (!(tick_nohz_tick_stopped() && avg_us < TICK_USEC)) { - idx = teo_find_shallower_state(drv, dev, idx, avg_us); duration_us = avg_us; + if (drv->states[idx].target_residency > avg_us) + idx = teo_find_shallower_state(drv, dev, + idx, avg_us); } } } -- GitLab From d111e7a387d71b444b9a785d754f348d9a623204 Mon Sep 17 00:00:00 2001 From: Hennie Muller Date: Sun, 21 Jul 2019 14:52:58 +0200 Subject: [PATCH 1864/7155] gpio: viperboard: Replace 'unsigned' with 'unsigned int' Fixes a couple of warnings by checkpatch and sparse. Signed-off-by: Hennie Muller Link: https://lore.kernel.org/r/20190721125259.13990-1-hm@bitlabs.co.za Signed-off-by: Linus Walleij --- drivers/gpio/gpio-viperboard.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 9b604f13e302..c301c1d56dd2 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -79,7 +79,7 @@ MODULE_PARM_DESC(gpioa_freq, /* ----- begin of gipo a chip -------------------------------------------- */ static int vprbrd_gpioa_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret, answer, error = 0; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -129,7 +129,7 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip, } static void vprbrd_gpioa_set(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -170,7 +170,7 @@ static void vprbrd_gpioa_set(struct gpio_chip *chip, } static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -207,7 +207,7 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, } static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -251,8 +251,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, /* ----- begin of gipo b chip -------------------------------------------- */ -static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, - unsigned dir) +static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset, + unsigned int dir) { struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; int ret; @@ -273,7 +273,7 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, } static int vprbrd_gpiob_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; u16 val; @@ -305,7 +305,7 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip, } static void vprbrd_gpiob_set(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -338,7 +338,7 @@ static void vprbrd_gpiob_set(struct gpio_chip *chip, } static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -359,7 +359,7 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, } static int vprbrd_gpiob_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); -- GitLab From 72ce665f170ee22069726840cd13ccf5af4ef34d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:45 +0100 Subject: [PATCH 1865/7155] gpio: arizona: Use local copy of pdata A local copy of the pdata exists and it should be used rather than pulling a fresh copy. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-1-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-arizona.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index c07fad975049..5640efe5e750 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -142,7 +142,7 @@ static const struct gpio_chip template_chip = { static int arizona_gpio_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); - struct arizona_pdata *pdata = dev_get_platdata(arizona->dev); + struct arizona_pdata *pdata = &arizona->pdata; struct arizona_gpio *arizona_gpio; int ret; @@ -177,7 +177,7 @@ static int arizona_gpio_probe(struct platform_device *pdev) return -EINVAL; } - if (pdata && pdata->gpio_base) + if (pdata->gpio_base) arizona_gpio->gpio_chip.base = pdata->gpio_base; else arizona_gpio->gpio_chip.base = -1; -- GitLab From fe2afa0d7b5ce05f8d2c4508e4041f3a216a5539 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:46 +0100 Subject: [PATCH 1866/7155] gpio: madera: Use local copy of pdata A local copy of the pdata exists and it should be used rather than pulling a fresh copy. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-2-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index 4dbc837d1215..fa3441df0a5d 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -120,7 +120,7 @@ static const struct gpio_chip madera_gpio_chip = { static int madera_gpio_probe(struct platform_device *pdev) { struct madera *madera = dev_get_drvdata(pdev->dev.parent); - struct madera_pdata *pdata = dev_get_platdata(madera->dev); + struct madera_pdata *pdata = &madera->pdata; struct madera_gpio *madera_gpio; int ret; @@ -153,7 +153,7 @@ static int madera_gpio_probe(struct platform_device *pdev) } /* We want to be usable on systems that don't use devicetree or acpi */ - if (pdata && pdata->gpio_base) + if (pdata->gpio_base) madera_gpio->gpio_chip.base = pdata->gpio_base; else madera_gpio->gpio_chip.base = -1; -- GitLab From d06be8bc290aa255b9fd8602e60fb9f487aa0f48 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 22 Jul 2019 10:07:47 +0100 Subject: [PATCH 1867/7155] gpio: madera: Add support for Cirrus Logic CS47L15 As the gpio is common to all madera codecs all that is needed is to setup the correct number of GPIO pins for the CS47L15. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-3-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index fa3441df0a5d..c403899ff450 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -136,6 +136,9 @@ static int madera_gpio_probe(struct platform_device *pdev) madera_gpio->gpio_chip.parent = pdev->dev.parent; switch (madera->type) { + case CS47L15: + madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS; + break; case CS47L35: madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS; break; -- GitLab From 74d2d0e68701bcd53d2cf771dd3b3cb9f84bed5c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:48 +0100 Subject: [PATCH 1868/7155] gpio: madera: Add support for Cirrus Logic CS47L92 As the gpio is common to all madera codecs all that is needed is to setup the correct number of GPIO pins for the CS47L92. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-4-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index c403899ff450..7086f8b5388f 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -150,6 +150,11 @@ static int madera_gpio_probe(struct platform_device *pdev) case CS47L91: madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS; break; + case CS42L92: + case CS47L92: + case CS47L93: + madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS; + break; default: dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type); return -EINVAL; -- GitLab From bb100b64763c5f93a4d5e97d3a1abedadfaaf384 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 17 Jul 2019 13:55:43 +0300 Subject: [PATCH 1869/7155] ACPI / APEI: Get rid of NULL_UUID_LE constant This is a missed part of the commit 5b53696a30d5 ("ACPI / APEI: Switch to use new generic UUID API"), i.e. replacing old definition with a global constant variable. Signed-off-by: Andy Shevchenko Reviewed-by: James Morse Signed-off-by: Rafael J. Wysocki --- drivers/acpi/apei/ghes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index a66e00fe31fe..451269a2f47c 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -483,7 +483,7 @@ static void ghes_do_proc(struct ghes *ghes, int sev, sec_sev; struct acpi_hest_generic_data *gdata; guid_t *sec_type; - guid_t *fru_id = &NULL_UUID_LE; + const guid_t *fru_id = &guid_null; char *fru_text = ""; sev = ghes_severity(estatus->error_severity); -- GitLab From 2c8db5bef9fb442a5a0d2fee28aed20100362ce3 Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Wed, 31 Jul 2019 14:29:33 -0700 Subject: [PATCH 1870/7155] PM/sleep: Expose suspend stats in sysfs Userspace can get suspend stats from the suspend stats debugfs node. Since debugfs doesn't have stable ABI, expose suspend stats in sysfs under /sys/power/suspend_stats. Signed-off-by: Kalesh Singh Reviewed-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-power | 106 ++++++++++++++++++++++++++ kernel/power/main.c | 97 ++++++++++++++++++++++- 2 files changed, 201 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power index 3c5130355011..6f87b9dd384b 100644 --- a/Documentation/ABI/testing/sysfs-power +++ b/Documentation/ABI/testing/sysfs-power @@ -301,3 +301,109 @@ Description: Using this sysfs file will override any values that were set using the kernel command line for disk offset. + +What: /sys/power/suspend_stats +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats directory contains suspend related + statistics. + +What: /sys/power/suspend_stats/success +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/success file contains the number + of times entering system sleep state succeeded. + +What: /sys/power/suspend_stats/fail +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/fail file contains the number + of times entering system sleep state failed. + +What: /sys/power/suspend_stats/failed_freeze +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_freeze file contains the + number of times freezing processes failed. + +What: /sys/power/suspend_stats/failed_prepare +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_prepare file contains the + number of times preparing all non-sysdev devices for + a system PM transition failed. + +What: /sys/power/suspend_stats/failed_resume +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_resume file contains the + number of times executing "resume" callbacks of + non-sysdev devices failed. + +What: /sys/power/suspend_stats/failed_resume_early +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_resume_early file contains + the number of times executing "early resume" callbacks + of devices failed. + +What: /sys/power/suspend_stats/failed_resume_noirq +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_resume_noirq file contains + the number of times executing "noirq resume" callbacks + of devices failed. + +What: /sys/power/suspend_stats/failed_suspend +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_suspend file contains + the number of times executing "suspend" callbacks + of all non-sysdev devices failed. + +What: /sys/power/suspend_stats/failed_suspend_late +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_suspend_late file contains + the number of times executing "late suspend" callbacks + of all devices failed. + +What: /sys/power/suspend_stats/failed_suspend_noirq +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/failed_suspend_noirq file contains + the number of times executing "noirq suspend" callbacks + of all devices failed. + +What: /sys/power/suspend_stats/last_failed_dev +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/last_failed_dev file contains + the last device for which a suspend/resume callback failed. + +What: /sys/power/suspend_stats/last_failed_errno +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/last_failed_errno file contains + the errno of the last failed attempt at entering + system sleep state. + +What: /sys/power/suspend_stats/last_failed_step +Date: July 2019 +Contact: Kalesh Singh +Description: + The /sys/power/suspend_stats/last_failed_step file contains + the last failed step in the suspend/resume path. diff --git a/kernel/power/main.c b/kernel/power/main.c index bdbd605c4215..938dc53a8b94 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -254,7 +254,6 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr, power_attr(pm_test); #endif /* CONFIG_PM_SLEEP_DEBUG */ -#ifdef CONFIG_DEBUG_FS static char *suspend_step_name(enum suspend_stat_step step) { switch (step) { @@ -275,6 +274,92 @@ static char *suspend_step_name(enum suspend_stat_step step) } } +#define suspend_attr(_name) \ +static ssize_t _name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%d\n", suspend_stats._name); \ +} \ +static struct kobj_attribute _name = __ATTR_RO(_name) + +suspend_attr(success); +suspend_attr(fail); +suspend_attr(failed_freeze); +suspend_attr(failed_prepare); +suspend_attr(failed_suspend); +suspend_attr(failed_suspend_late); +suspend_attr(failed_suspend_noirq); +suspend_attr(failed_resume); +suspend_attr(failed_resume_early); +suspend_attr(failed_resume_noirq); + +static ssize_t last_failed_dev_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int index; + char *last_failed_dev = NULL; + + index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; + index %= REC_FAILED_NUM; + last_failed_dev = suspend_stats.failed_devs[index]; + + return sprintf(buf, "%s\n", last_failed_dev); +} +static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev); + +static ssize_t last_failed_errno_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int index; + int last_failed_errno; + + index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1; + index %= REC_FAILED_NUM; + last_failed_errno = suspend_stats.errno[index]; + + return sprintf(buf, "%d\n", last_failed_errno); +} +static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno); + +static ssize_t last_failed_step_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int index; + enum suspend_stat_step step; + char *last_failed_step = NULL; + + index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1; + index %= REC_FAILED_NUM; + step = suspend_stats.failed_steps[index]; + last_failed_step = suspend_step_name(step); + + return sprintf(buf, "%s\n", last_failed_step); +} +static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step); + +static struct attribute *suspend_attrs[] = { + &success.attr, + &fail.attr, + &failed_freeze.attr, + &failed_prepare.attr, + &failed_suspend.attr, + &failed_suspend_late.attr, + &failed_suspend_noirq.attr, + &failed_resume.attr, + &failed_resume_early.attr, + &failed_resume_noirq.attr, + &last_failed_dev.attr, + &last_failed_errno.attr, + &last_failed_step.attr, + NULL, +}; + +static struct attribute_group suspend_attr_group = { + .name = "suspend_stats", + .attrs = suspend_attrs, +}; + +#ifdef CONFIG_DEBUG_FS static int suspend_stats_show(struct seq_file *s, void *unused) { int i, index, last_dev, last_errno, last_step; @@ -794,6 +879,14 @@ static const struct attribute_group attr_group = { .attrs = g, }; +static const struct attribute_group *attr_groups[] = { + &attr_group, +#ifdef CONFIG_PM_SLEEP + &suspend_attr_group, +#endif + NULL, +}; + struct workqueue_struct *pm_wq; EXPORT_SYMBOL_GPL(pm_wq); @@ -815,7 +908,7 @@ static int __init pm_init(void) power_kobj = kobject_create_and_add("power", NULL); if (!power_kobj) return -ENOMEM; - error = sysfs_create_group(power_kobj, &attr_group); + error = sysfs_create_groups(power_kobj, attr_groups); if (error) return error; pm_print_times_init(); -- GitLab From c87857945b0e61c46222798b56fb1b0f4868088b Mon Sep 17 00:00:00 2001 From: Julien Thierry Date: Thu, 4 Jul 2019 14:44:04 +0100 Subject: [PATCH 1871/7155] arm64: Remove unused assembly macro As of commit 4141c857fd09dbed480f021b3eece4f46c653161 ("arm64: convert raw syscall invocation to C"), moving syscall handling from assembly to C, the macro mask_nospec64 is no longer referenced. Acked-by: Mark Rutland Signed-off-by: Julien Thierry Signed-off-by: Will Deacon --- arch/arm64/include/asm/assembler.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index e3a15c751b13..9f7395a1177f 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -123,17 +123,6 @@ alternative_else alternative_endif .endm -/* - * Sanitise a 64-bit bounded index wrt speculation, returning zero if out - * of bounds. - */ - .macro mask_nospec64, idx, limit, tmp - sub \tmp, \idx, \limit - bic \tmp, \tmp, \idx - and \idx, \idx, \tmp, asr #63 - csdb - .endm - /* * NOP sequence */ -- GitLab From b907b80d7ae7b2b65ef9f534f3e9a32ce6a4b539 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 8 Jul 2019 17:36:40 +0100 Subject: [PATCH 1872/7155] arm64: remove pointless __KERNEL__ guards For a number of years, UAPI headers have been split from kernel-internal headers. The latter are never exposed to userspace, and always built with __KERNEL__ defined. Most headers under arch/arm64 don't have __KERNEL__ guards, but there are a few stragglers lying around. To make things more consistent, and to set a good example going forward, let's remove these redundant __KERNEL__ guards. In a couple of cases, a trailing #endif lacked a comment describing its corresponding #if or #ifdef, so these are fixes up at the same time. Guards in auto-generated crypto code are left as-is, as these guards are generated by scripting imported from the upstream openssl project scripts. Guards in UAPI headers are left as-is, as these can be included by userspace or the kernel. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: Will Deacon Signed-off-by: Will Deacon --- arch/arm64/include/asm/atomic.h | 5 +---- arch/arm64/include/asm/compat.h | 2 -- arch/arm64/include/asm/debug-monitors.h | 3 --- arch/arm64/include/asm/dma-mapping.h | 3 --- arch/arm64/include/asm/fpsimd.h | 2 +- arch/arm64/include/asm/futex.h | 3 --- arch/arm64/include/asm/hw_breakpoint.h | 3 --- arch/arm64/include/asm/io.h | 3 --- arch/arm64/include/asm/irqflags.h | 5 +---- arch/arm64/include/asm/pci.h | 2 -- arch/arm64/include/asm/proc-fns.h | 2 -- arch/arm64/include/asm/processor.h | 3 --- arch/arm64/include/asm/signal32.h | 2 -- arch/arm64/include/asm/thread_info.h | 3 --- arch/arm64/include/asm/vdso.h | 4 ---- arch/arm64/include/asm/vdso_datapage.h | 4 ---- 16 files changed, 3 insertions(+), 46 deletions(-) diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h index 657b0457d83c..a5ca23950cfd 100644 --- a/arch/arm64/include/asm/atomic.h +++ b/arch/arm64/include/asm/atomic.h @@ -15,8 +15,6 @@ #include #include -#ifdef __KERNEL__ - #define __ARM64_IN_ATOMIC_IMPL #if defined(CONFIG_ARM64_LSE_ATOMICS) && defined(CONFIG_AS_LSE) @@ -157,5 +155,4 @@ #include -#endif -#endif +#endif /* __ASM_ATOMIC_H */ diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index fb8ad4616b3b..b0d53a265f1d 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -4,7 +4,6 @@ */ #ifndef __ASM_COMPAT_H #define __ASM_COMPAT_H -#ifdef __KERNEL__ #ifdef CONFIG_COMPAT /* @@ -215,5 +214,4 @@ static inline int is_compat_thread(struct thread_info *thread) } #endif /* CONFIG_COMPAT */ -#endif /* __KERNEL__ */ #endif /* __ASM_COMPAT_H */ diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index d8ec5bb881c2..7619f473155f 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -5,8 +5,6 @@ #ifndef __ASM_DEBUG_MONITORS_H #define __ASM_DEBUG_MONITORS_H -#ifdef __KERNEL__ - #include #include #include @@ -128,5 +126,4 @@ static inline int reinstall_suspended_bps(struct pt_regs *regs) int aarch32_break_handler(struct pt_regs *regs); #endif /* __ASSEMBLY */ -#endif /* __KERNEL__ */ #endif /* __ASM_DEBUG_MONITORS_H */ diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index bdcb0922a40c..fb3e5044f473 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h @@ -5,8 +5,6 @@ #ifndef __ASM_DMA_MAPPING_H #define __ASM_DMA_MAPPING_H -#ifdef __KERNEL__ - #include #include @@ -27,5 +25,4 @@ static inline bool is_device_dma_coherent(struct device *dev) return dev->dma_coherent; } -#endif /* __KERNEL__ */ #endif /* __ASM_DMA_MAPPING_H */ diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index b6a2c352f4c3..59f10dd13f12 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -21,7 +21,7 @@ #include #include -#if defined(__KERNEL__) && defined(CONFIG_COMPAT) +#ifdef CONFIG_COMPAT /* Masks for extracting the FPSR and FPCR from the FPSCR */ #define VFP_FPSCR_STAT_MASK 0xf800009f #define VFP_FPSCR_CTRL_MASK 0x07f79f00 diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h index 6211e3105491..6cc26a127819 100644 --- a/arch/arm64/include/asm/futex.h +++ b/arch/arm64/include/asm/futex.h @@ -5,8 +5,6 @@ #ifndef __ASM_FUTEX_H #define __ASM_FUTEX_H -#ifdef __KERNEL__ - #include #include @@ -129,5 +127,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr, return ret; } -#endif /* __KERNEL__ */ #endif /* __ASM_FUTEX_H */ diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index db9ab760e6fd..bc7aaed4b34e 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h @@ -10,8 +10,6 @@ #include #include -#ifdef __KERNEL__ - struct arch_hw_breakpoint_ctrl { u32 __reserved : 19, len : 8, @@ -156,5 +154,4 @@ static inline int get_num_wrps(void) ID_AA64DFR0_WRPS_SHIFT); } -#endif /* __KERNEL__ */ #endif /* __ASM_BREAKPOINT_H */ diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 7ed92626949d..179a4c65c0d4 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -8,8 +8,6 @@ #ifndef __ASM_IO_H #define __ASM_IO_H -#ifdef __KERNEL__ - #include #include @@ -207,5 +205,4 @@ extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); extern int devmem_is_allowed(unsigned long pfn); -#endif /* __KERNEL__ */ #endif /* __ASM_IO_H */ diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h index 7872f260c9ee..1a59f0ed1ae3 100644 --- a/arch/arm64/include/asm/irqflags.h +++ b/arch/arm64/include/asm/irqflags.h @@ -5,8 +5,6 @@ #ifndef __ASM_IRQFLAGS_H #define __ASM_IRQFLAGS_H -#ifdef __KERNEL__ - #include #include #include @@ -128,5 +126,4 @@ static inline void arch_local_irq_restore(unsigned long flags) : "memory"); } -#endif -#endif +#endif /* __ASM_IRQFLAGS_H */ diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h index 9e690686e8aa..70b323cf8300 100644 --- a/arch/arm64/include/asm/pci.h +++ b/arch/arm64/include/asm/pci.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __ASM_PCI_H #define __ASM_PCI_H -#ifdef __KERNEL__ #include #include @@ -35,5 +34,4 @@ static inline int pci_proc_domain(struct pci_bus *bus) } #endif /* CONFIG_PCI */ -#endif /* __KERNEL__ */ #endif /* __ASM_PCI_H */ diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h index 368d90a9d0e5..a2ce65a0c1fa 100644 --- a/arch/arm64/include/asm/proc-fns.h +++ b/arch/arm64/include/asm/proc-fns.h @@ -9,7 +9,6 @@ #ifndef __ASM_PROCFNS_H #define __ASM_PROCFNS_H -#ifdef __KERNEL__ #ifndef __ASSEMBLY__ #include @@ -25,5 +24,4 @@ extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr); #include #endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */ #endif /* __ASM_PROCFNS_H */ diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 844e2964b0f5..fa7a6f63308f 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -20,7 +20,6 @@ #define NET_IP_ALIGN 0 #ifndef __ASSEMBLY__ -#ifdef __KERNEL__ #include #include @@ -283,8 +282,6 @@ static inline void spin_lock_prefetch(const void *ptr) #define HAVE_ARCH_PICK_MMAP_LAYOUT -#endif - extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ extern void __init minsigstksz_setup(void); diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h index bd43d1cf724b..7e9f163d02ec 100644 --- a/arch/arm64/include/asm/signal32.h +++ b/arch/arm64/include/asm/signal32.h @@ -5,7 +5,6 @@ #ifndef __ASM_SIGNAL32_H #define __ASM_SIGNAL32_H -#ifdef __KERNEL__ #ifdef CONFIG_COMPAT #include @@ -79,5 +78,4 @@ static inline void compat_setup_restart_syscall(struct pt_regs *regs) { } #endif /* CONFIG_COMPAT */ -#endif /* __KERNEL__ */ #endif /* __ASM_SIGNAL32_H */ diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 180b34ec5965..e35cd84b102c 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -8,8 +8,6 @@ #ifndef __ASM_THREAD_INFO_H #define __ASM_THREAD_INFO_H -#ifdef __KERNEL__ - #include #ifndef __ASSEMBLY__ @@ -121,5 +119,4 @@ void arch_release_task_struct(struct task_struct *tsk); .addr_limit = KERNEL_DS, \ } -#endif /* __KERNEL__ */ #endif /* __ASM_THREAD_INFO_H */ diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h index 9c15e0a06301..07468428fd29 100644 --- a/arch/arm64/include/asm/vdso.h +++ b/arch/arm64/include/asm/vdso.h @@ -5,8 +5,6 @@ #ifndef __ASM_VDSO_H #define __ASM_VDSO_H -#ifdef __KERNEL__ - /* * Default link address for the vDSO. * Since we randomise the VDSO mapping, there's little point in trying @@ -28,6 +26,4 @@ #endif /* !__ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* __ASM_VDSO_H */ diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h index ba6dbc3de864..1f38bf330a6e 100644 --- a/arch/arm64/include/asm/vdso_datapage.h +++ b/arch/arm64/include/asm/vdso_datapage.h @@ -5,8 +5,6 @@ #ifndef __ASM_VDSO_DATAPAGE_H #define __ASM_VDSO_DATAPAGE_H -#ifdef __KERNEL__ - #ifndef __ASSEMBLY__ struct vdso_data { @@ -32,6 +30,4 @@ struct vdso_data { #endif /* !__ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* __ASM_VDSO_DATAPAGE_H */ -- GitLab From c19d050f80881296aab3ba90fe5b2c107a238dcb Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Thu, 11 Jul 2019 17:27:32 +0530 Subject: [PATCH 1873/7155] arm64/kexec: Use consistent convention of initializing 'kxec_buf.mem' with KEXEC_BUF_MEM_UNKNOWN With commit b6664ba42f14 ("s390, kexec_file: drop arch_kexec_mem_walk()"), we introduced the KEXEC_BUF_MEM_UNKNOWN macro. If kexec_buf.mem is set to this value, kexec_locate_mem_hole() will try to allocate free memory. While other arch(s) like s390 and x86_64 already use this macro to initialize kexec_buf.mem with, arm64 uses an equivalent value of 0. Replace it with KEXEC_BUF_MEM_UNKNOWN, to keep the convention of initializing 'kxec_buf.mem' consistent across various archs. Cc: takahiro.akashi@linaro.org Cc: james.morse@arm.com Reviewed-by: Matthias Brugger Signed-off-by: Bhupesh Sharma Signed-off-by: Will Deacon --- arch/arm64/kernel/kexec_image.c | 2 +- arch/arm64/kernel/machine_kexec_file.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c index 2514fd6f12cb..29a9428486a5 100644 --- a/arch/arm64/kernel/kexec_image.c +++ b/arch/arm64/kernel/kexec_image.c @@ -84,7 +84,7 @@ static void *image_load(struct kimage *image, kbuf.buffer = kernel; kbuf.bufsz = kernel_len; - kbuf.mem = 0; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.memsz = le64_to_cpu(h->image_size); text_offset = le64_to_cpu(h->text_offset); kbuf.buf_align = MIN_KIMG_ALIGN; diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c index 58871333737a..ba78ee7ca990 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -177,7 +177,7 @@ int load_other_segments(struct kimage *image, if (initrd) { kbuf.buffer = initrd; kbuf.bufsz = initrd_len; - kbuf.mem = 0; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.memsz = initrd_len; kbuf.buf_align = 0; /* within 1GB-aligned window of up to 32GB in size */ @@ -204,7 +204,7 @@ int load_other_segments(struct kimage *image, dtb_len = fdt_totalsize(dtb); kbuf.buffer = dtb; kbuf.bufsz = dtb_len; - kbuf.mem = 0; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.memsz = dtb_len; /* not across 2MB boundary */ kbuf.buf_align = SZ_2M; -- GitLab From b717480f5415201286cc9b5e3244513f54a327c4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 23 Jul 2019 20:29:22 +0900 Subject: [PATCH 1874/7155] arm64: remove unneeded uapi/asm/stat.h stat.h is listed in include/uapi/asm-generic/Kbuild, so Kbuild will automatically generate it. Signed-off-by: Masahiro Yamada Signed-off-by: Will Deacon --- arch/arm64/include/uapi/asm/stat.h | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 arch/arm64/include/uapi/asm/stat.h diff --git a/arch/arm64/include/uapi/asm/stat.h b/arch/arm64/include/uapi/asm/stat.h deleted file mode 100644 index 313325fa22fa..000000000000 --- a/arch/arm64/include/uapi/asm/stat.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * Copyright (C) 2012 ARM Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -- GitLab From 3e77eeb7a27fc3dcf6b65e7ee01ac00bf5d2b4fb Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 22 Jul 2019 17:14:33 +0100 Subject: [PATCH 1875/7155] ACPI/IORT: Rename arm_smmu_v3_set_proximity() 'node' local variable Commit 36a2ba07757d ("ACPI/IORT: Reject platform device creation on NUMA node mapping failure") introduced a local variable 'node' in arm_smmu_v3_set_proximity() that shadows the struct acpi_iort_node pointer function parameter. Execution was unaffected but it is prone to errors and can lead to subtle bugs. Rename the local variable to prevent any issue. Reviewed-by: Hanjun Guo Reported-by: Will Deacon Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Hanjun Guo Cc: Sudeep Holla Cc: Catalin Marinas Cc: Robin Murphy Cc: Kefeng Wang Signed-off-by: Will Deacon --- drivers/acpi/arm64/iort.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 8569b79e8b58..5a7551d060f2 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -1256,12 +1256,12 @@ static int __init arm_smmu_v3_set_proximity(struct device *dev, smmu = (struct acpi_iort_smmu_v3 *)node->node_data; if (smmu->flags & ACPI_IORT_SMMU_V3_PXM_VALID) { - int node = acpi_map_pxm_to_node(smmu->pxm); + int dev_node = acpi_map_pxm_to_node(smmu->pxm); - if (node != NUMA_NO_NODE && !node_online(node)) + if (dev_node != NUMA_NO_NODE && !node_online(dev_node)) return -EINVAL; - set_dev_node(dev, node); + set_dev_node(dev, dev_node); pr_info("SMMU-v3[%llx] Mapped to Proximity domain %d\n", smmu->base_address, smmu->pxm); -- GitLab From b3e089cd446b26bb1e12860e1afb9da314453fd6 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 30 Jul 2019 10:44:15 +0800 Subject: [PATCH 1876/7155] arm64: Replace strncmp with str_has_prefix In commit b6b2735514bc ("tracing: Use str_has_prefix() instead of using fixed sizes") the newly introduced str_has_prefix() was used to replace error-prone strncmp(str, const, len). Here fix codes with the same pattern. Signed-off-by: Chuhong Yuan Signed-off-by: Will Deacon --- arch/arm64/kernel/module-plts.c | 2 +- arch/arm64/mm/numa.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c index 044c0ae4d6c8..b182442b87a3 100644 --- a/arch/arm64/kernel/module-plts.c +++ b/arch/arm64/kernel/module-plts.c @@ -302,7 +302,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, /* sort by type, symbol index and addend */ sort(rels, numrels, sizeof(Elf64_Rela), cmp_rela, NULL); - if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0) + if (!str_has_prefix(secstrings + dstsec->sh_name, ".init")) core_plts += count_plts(syms, rels, numrels, sechdrs[i].sh_info, dstsec); else diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 4f241cc7cc3b..4decf1659700 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -29,7 +29,7 @@ static __init int numa_parse_early_param(char *opt) { if (!opt) return -EINVAL; - if (!strncmp(opt, "off", 3)) + if (str_has_prefix(opt, "off")) numa_off = true; return 0; -- GitLab From 332e5281a4e8269b96233a7babc98b03596b7e6d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 16 Jul 2019 08:14:19 +0100 Subject: [PATCH 1877/7155] arm64: esr: Add ESR exception class encoding for trapped ERET The ESR.EC encoding of 0b011010 (0x1a) describes an exception generated by an ERET, ERETAA or ERETAB instruction as a result of a nested virtualisation trap to EL2. Add an encoding for this EC and a string description so that we identify it correctly if we take one unexpectedly. Acked-by: Mark Rutland Acked-by: Marc Zyngier Signed-off-by: Will Deacon --- arch/arm64/include/asm/esr.h | 3 ++- arch/arm64/kernel/traps.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 65ac18400979..cb29253ae86b 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -34,7 +34,8 @@ #define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */ #define ESR_ELx_EC_SYS64 (0x18) #define ESR_ELx_EC_SVE (0x19) -/* Unallocated EC: 0x1A - 0x1E */ +#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */ +/* Unallocated EC: 0x1b - 0x1E */ #define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */ #define ESR_ELx_EC_IABT_LOW (0x20) #define ESR_ELx_EC_IABT_CUR (0x21) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index d3313797cca9..42c8422cdf4a 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -743,6 +743,7 @@ static const char *esr_class_str[] = { [ESR_ELx_EC_SMC64] = "SMC (AArch64)", [ESR_ELx_EC_SYS64] = "MSR/MRS (AArch64)", [ESR_ELx_EC_SVE] = "SVE", + [ESR_ELx_EC_ERET] = "ERET/ERETAA/ERETAB", [ESR_ELx_EC_IMP_DEF] = "EL3 IMP DEF", [ESR_ELx_EC_IABT_LOW] = "IABT (lower EL)", [ESR_ELx_EC_IABT_CUR] = "IABT (current EL)", -- GitLab From 73961dc1182ed7e1eb80a90ee28871ab3547af7e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 15 Jul 2019 14:28:17 +0100 Subject: [PATCH 1878/7155] arm64: sysreg: Remove unused and rotting SCTLR_ELx field definitions Our SCTLR_ELx field definitions are somewhat over-engineered in that they carefully define masks describing the RES0/RES1 bits and then use these to construct further masks representing bits to be set/cleared for the _EL1 and _EL2 registers. However, most of the resulting definitions aren't actually used by anybody and have subsequently started to bit-rot when new fields have been added by the architecture, resulting in fields being part of the RES0 mask despite being defined and used elsewhere. Rather than fix up these masks, simply remove the unused parts entirely so that we can drop the maintenance burden. We can always add things back if we need them in the future. Acked-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/include/asm/sysreg.h | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 06ebcfef73df..1df45c7ffcf7 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -499,28 +499,11 @@ #define SCTLR_EL2_RES1 ((BIT(4)) | (BIT(5)) | (BIT(11)) | (BIT(16)) | \ (BIT(18)) | (BIT(22)) | (BIT(23)) | (BIT(28)) | \ (BIT(29))) -#define SCTLR_EL2_RES0 ((BIT(6)) | (BIT(7)) | (BIT(8)) | (BIT(9)) | \ - (BIT(10)) | (BIT(13)) | (BIT(14)) | (BIT(15)) | \ - (BIT(17)) | (BIT(20)) | (BIT(24)) | (BIT(26)) | \ - (BIT(27)) | (BIT(30)) | (BIT(31)) | \ - (0xffffefffUL << 32)) #ifdef CONFIG_CPU_BIG_ENDIAN #define ENDIAN_SET_EL2 SCTLR_ELx_EE -#define ENDIAN_CLEAR_EL2 0 #else #define ENDIAN_SET_EL2 0 -#define ENDIAN_CLEAR_EL2 SCTLR_ELx_EE -#endif - -/* SCTLR_EL2 value used for the hyp-stub */ -#define SCTLR_EL2_SET (SCTLR_ELx_IESB | ENDIAN_SET_EL2 | SCTLR_EL2_RES1) -#define SCTLR_EL2_CLEAR (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \ - SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_WXN | \ - SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0) - -#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffffUL -#error "Inconsistent SCTLR_EL2 set/clear bits" #endif /* SCTLR_EL1 specific flags. */ @@ -539,16 +522,11 @@ #define SCTLR_EL1_RES1 ((BIT(11)) | (BIT(20)) | (BIT(22)) | (BIT(28)) | \ (BIT(29))) -#define SCTLR_EL1_RES0 ((BIT(6)) | (BIT(10)) | (BIT(13)) | (BIT(17)) | \ - (BIT(27)) | (BIT(30)) | (BIT(31)) | \ - (0xffffefffUL << 32)) #ifdef CONFIG_CPU_BIG_ENDIAN #define ENDIAN_SET_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE) -#define ENDIAN_CLEAR_EL1 0 #else #define ENDIAN_SET_EL1 0 -#define ENDIAN_CLEAR_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE) #endif #define SCTLR_EL1_SET (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA |\ @@ -556,13 +534,6 @@ SCTLR_EL1_DZE | SCTLR_EL1_UCT |\ SCTLR_EL1_NTWE | SCTLR_ELx_IESB | SCTLR_EL1_SPAN |\ ENDIAN_SET_EL1 | SCTLR_EL1_UCI | SCTLR_EL1_RES1) -#define SCTLR_EL1_CLEAR (SCTLR_ELx_A | SCTLR_EL1_CP15BEN | SCTLR_EL1_ITD |\ - SCTLR_EL1_UMA | SCTLR_ELx_WXN | ENDIAN_CLEAR_EL1 |\ - SCTLR_ELx_DSSBS | SCTLR_EL1_NTWI | SCTLR_EL1_RES0) - -#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffffUL -#error "Inconsistent SCTLR_EL1 set/clear bits" -#endif /* id_aa64isar0 */ #define ID_AA64ISAR0_TS_SHIFT 52 -- GitLab From 2f8f180b3ceed7a16a92cc3c164368c26e1f9320 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 30 Jul 2019 11:26:31 +0100 Subject: [PATCH 1879/7155] arm64: Remove unused cpucap_multi_entry_cap_cpu_enable() The function cpucap_multi_entry_cap_cpu_enable() is unused, remove it to avoid any confusion reading the code and potential for bit rot. Signed-off-by: Mark Brown Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index c96ffa4722d3..cf65a47ee6b4 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -363,21 +363,6 @@ cpucap_multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry, return false; } -/* - * Take appropriate action for all matching entries in the shared capability - * entry. - */ -static inline void -cpucap_multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry) -{ - const struct arm64_cpu_capabilities *caps; - - for (caps = entry->match_list; caps->matches; caps++) - if (caps->matches(caps, SCOPE_LOCAL_CPU) && - caps->cpu_enable) - caps->cpu_enable(caps); -} - extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; extern struct static_key_false arm64_const_caps_ready; -- GitLab From a24810673638d5da0336ccae5407c3fd59da14ac Mon Sep 17 00:00:00 2001 From: Kevin Brodsky Date: Thu, 25 Jul 2019 18:12:14 +0100 Subject: [PATCH 1880/7155] arm64: dts: fast models: Remove clcd's max-memory-bandwidth It is unclear why max-memory-bandwidth should be set for CLCD on the fast model. Removing that property allows allocating and using 32bpp buffers, which may be desirable on certain platforms such as Android. Reported-by: Ruben Ayrapetyan Reviewed-by: Linus Walleij Signed-off-by: Kevin Brodsky Signed-off-by: Sudeep Holla --- arch/arm64/boot/dts/arm/fvp-base-revc.dts | 8 -------- arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi | 2 -- 2 files changed, 10 deletions(-) diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts index 687707020ec1..62ab0d54ff71 100644 --- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts +++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts @@ -265,13 +265,5 @@ <0 0 42 &gic 0 0 GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, <0 0 43 &gic 0 0 GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, <0 0 44 &gic 0 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; - - motherboard { - iofpga@3,00000000 { - clcd@1f0000 { - max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */ - }; - }; - }; }; }; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi index 454cf6c44c49..03a7bf079c8f 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi +++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi @@ -188,8 +188,6 @@ interrupts = <14>; clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; clock-names = "clcdclk", "apb_pclk"; - /* 800x600 16bpp @36MHz works fine */ - max-memory-bandwidth = <54000000>; memory-region = <&vram>; port { -- GitLab From 15bddb7d787aebc837912cecf107b7eaccf03913 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:15 -0700 Subject: [PATCH 1881/7155] gpio: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: linux-gpio@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-16-swboyd@chromium.org Acked-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 4 +--- drivers/gpio/gpio-eic-sprd.c | 4 +--- drivers/gpio/gpio-grgpio.c | 2 -- drivers/gpio/gpio-max77620.c | 4 +--- drivers/gpio/gpio-pmic-eic-sprd.c | 4 +--- drivers/gpio/gpio-sprd.c | 4 +--- drivers/gpio/gpio-tb10x.c | 4 +--- drivers/gpio/gpio-tegra.c | 4 +--- drivers/gpio/gpio-zx.c | 1 - drivers/gpio/gpio-zynq.c | 4 +--- 10 files changed, 8 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index af936dcca659..05e3f99ae59c 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -636,10 +636,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) if (of_property_read_bool(np, "interrupt-controller")) { priv->parent_irq = platform_get_irq(pdev, 0); - if (priv->parent_irq <= 0) { - dev_err(dev, "Couldn't get IRQ"); + if (priv->parent_irq <= 0) return -ENOENT; - } } else { priv->parent_irq = -ENOENT; } diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 7b9ac4a12c20..fe7a73f52329 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -584,10 +584,8 @@ static int sprd_eic_probe(struct platform_device *pdev) sprd_eic->type = pdata->type; sprd_eic->irq = platform_get_irq(pdev, 0); - if (sprd_eic->irq < 0) { - dev_err(&pdev->dev, "Failed to get EIC interrupt.\n"); + if (sprd_eic->irq < 0) return sprd_eic->irq; - } for (i = 0; i < SPRD_EIC_MAX_BANK; i++) { /* diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 0937b605e134..08234e64993a 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -408,8 +408,6 @@ static int grgpio_probe(struct platform_device *ofdev) * Continue without irq functionality for that * gpio line */ - dev_err(priv->dev, - "Failed to get irq for offset %d\n", i); continue; } priv->uirqs[lirq->index].uirq = ret; diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index b7d89e30131e..47d05e357e61 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -270,10 +270,8 @@ static int max77620_gpio_probe(struct platform_device *pdev) int ret; gpio_irq = platform_get_irq(pdev, 0); - if (gpio_irq <= 0) { - dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq); + if (gpio_irq <= 0) return -ENODEV; - } mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL); if (!mgpio) diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index 24228cf79afc..05000cace9b2 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -305,10 +305,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) mutex_init(&pmic_eic->buslock); pmic_eic->irq = platform_get_irq(pdev, 0); - if (pmic_eic->irq < 0) { - dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n"); + if (pmic_eic->irq < 0) return pmic_eic->irq; - } pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL); if (!pmic_eic->map) diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index f5c8b3a351d5..d7314d39ab65 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -226,10 +226,8 @@ static int sprd_gpio_probe(struct platform_device *pdev) return -ENOMEM; sprd_gpio->irq = platform_get_irq(pdev, 0); - if (sprd_gpio->irq < 0) { - dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n"); + if (sprd_gpio->irq < 0) return sprd_gpio->irq; - } sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sprd_gpio->base)) diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index bd1f3f775ce9..5e375186f90e 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -171,10 +171,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) struct irq_chip_generic *gc; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "No interrupt specified.\n"); + if (ret < 0) return ret; - } tb10x_gpio->gc.to_irq = tb10x_gpio_to_irq; tb10x_gpio->irq = ret; diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 0f59161a4701..8a01d3694b28 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -624,10 +624,8 @@ static int tegra_gpio_probe(struct platform_device *pdev) for (i = 0; i < tgi->bank_count; i++) { ret = platform_get_irq(pdev, i); - if (ret < 0) { - dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret); + if (ret < 0) return ret; - } bank = &tgi->bank_info[i]; bank->bank = i; diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 8637adb6bc20..8d9b9bf8510a 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -253,7 +253,6 @@ static int zx_gpio_probe(struct platform_device *pdev) writew_relaxed(0, chip->base + ZX_GPIO_IE); irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "invalid IRQ\n"); gpiochip_remove(&chip->gc); return -ENODEV; } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index f241b6c13dbe..86b0bd256c13 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -849,10 +849,8 @@ static int zynq_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio->base_addr); gpio->irq = platform_get_irq(pdev, 0); - if (gpio->irq < 0) { - dev_err(&pdev->dev, "invalid IRQ\n"); + if (gpio->irq < 0) return gpio->irq; - } /* configure the gpio chip */ chip = &gpio->chip; -- GitLab From 22ec71615d824f4f11d38d0e55a88d8956b7e45f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Jun 2019 15:48:58 +0100 Subject: [PATCH 1882/7155] arm64: io: Relax implicit barriers in default I/O accessors The arm64 implementation of the default I/O accessors requires barrier instructions to satisfy the memory ordering requirements documented in memory-barriers.txt [1], which are largely derived from the behaviour of I/O accesses on x86. Of particular interest are the requirements that a write to a device must be ordered against prior writes to memory, and a read from a device must be ordered against subsequent reads from memory. We satisfy these requirements using various flavours of DSB: the most expensive barrier we have, since it implies completion of prior accesses. This was deemed necessary when we first implemented the accessors, since accesses to different endpoints could propagate independently and therefore the only way to enforce order is to rely on completion guarantees [2]. Since then, the Armv8 memory model has been retrospectively strengthened to require "other-multi-copy atomicity", a property that requires memory accesses from an observer to become visible to all other observers simultaneously [3]. In other words, propagation of accesses is limited to transitioning from locally observed to globally observed. It recently became apparent that this change also has a subtle impact on our I/O accessors for shared peripherals, allowing us to use the cheaper DMB instruction instead. As a concrete example, consider the following: memcpy(dma_buffer, data, bufsz); writel(DMA_START, dev->ctrl_reg); A DMB ST instruction between the final write to the DMA buffer and the write to the control register will ensure that the writes to the DMA buffer are observed before the write to the control register by all observers. Put another way, if an observer can see the write to the control register, it can also see the writes to memory. This has always been the case and is not sufficient to provide the ordering required by Linux, since there is no guarantee that the master interface of the DMA-capable device has observed either of the accesses. However, in an other-multi-copy atomic world, we can infer two things: 1. A write arriving at an endpoint shared between multiple CPUs is visible to all CPUs 2. A write that is visible to all CPUs is also visible to all other observers in the shareability domain Pieced together, this allows us to use DMB OSHST for our default I/O write accessors and DMB OSHLD for our default I/O read accessors (the outer-shareability is for handling non-cacheable mappings) for shared devices. Memory-mapped, DMA-capable peripherals that are private to a CPU (i.e. inaccessible to other CPUs) still require the DSB, however these are few and far between and typically require special treatment anyway which is outside of the scope of the portable driver API (e.g. GIC, page-table walker, SPE profiler). Note that our mandatory barriers remain as DSBs, since there are cases where they are used to flush the store buffer of the CPU, e.g. when publishing page table updates to the SMMU. [1] https://git.kernel.org/linus/4614bbdee357 [2] https://www.youtube.com/watch?v=i6DayghhA8Q [3] https://www.cl.cam.ac.uk/~pes20/armv8-mca/ Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/include/asm/io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 179a4c65c0d4..e9763831186a 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -95,7 +95,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) ({ \ unsigned long tmp; \ \ - rmb(); \ + dma_rmb(); \ \ /* \ * Create a dummy control dependency from the IO read to any \ @@ -109,7 +109,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) }) #define __io_par(v) __iormb(v) -#define __iowmb() wmb() +#define __iowmb() dma_wmb() /* * Relaxed I/O memory access primitives. These follow the Device memory -- GitLab From 13776f9d40a028a245bb766269e360f5b7a62721 Mon Sep 17 00:00:00 2001 From: Junhua Huang Date: Sat, 6 Jul 2019 14:41:15 +0800 Subject: [PATCH 1883/7155] arm64: mm: free the initrd reserved memblock in a aligned manner We should free the initrd reserved memblock in an aligned manner, because the initrd reserves the memblock in an aligned manner in arm64_memblock_init(). Otherwise there are some fragments in memblock_reserved regions after free_initrd_mem(). e.g.: /sys/kernel/debug/memblock # cat reserved 0: 0x0000000080080000..0x00000000817fafff 1: 0x0000000083400000..0x0000000083ffffff 2: 0x0000000090000000..0x000000009000407f 3: 0x00000000b0000000..0x00000000b000003f 4: 0x00000000b26184ea..0x00000000b2618fff The fragments like the ranges from b0000000 to b000003f and from b26184ea to b2618fff should be freed. And we can do free_reserved_area() after memblock_free(), as free_reserved_area() calls __free_pages(), once we've done that it could be allocated somewhere else, but memblock and iomem still say this is reserved memory. Fixes: 05c58752f9dc ("arm64: To remove initrd reserved area entry from memblock") Signed-off-by: Junhua Huang Signed-off-by: Will Deacon --- arch/arm64/mm/init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f3c795278def..b1ee6cb4b17f 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -570,8 +570,12 @@ void free_initmem(void) #ifdef CONFIG_BLK_DEV_INITRD void __init free_initrd_mem(unsigned long start, unsigned long end) { + unsigned long aligned_start, aligned_end; + + aligned_start = __virt_to_phys(start) & PAGE_MASK; + aligned_end = PAGE_ALIGN(__virt_to_phys(end)); + memblock_free(aligned_start, aligned_end - aligned_start); free_reserved_area((void *)start, (void *)end, 0, "initrd"); - memblock_free(__virt_to_phys(start), end - start); } #endif -- GitLab From 66cbdf5d0c96f5fe570b548e764583ea9d793077 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 15:35:20 +0200 Subject: [PATCH 1884/7155] arm64: Move TIF_* documentation to individual definitions Some TIF_* flags are documented in the comment block at the top, some next to their definitions, some in both places. Move all documentation to the individual definitions for consistency, and for easy lookup. Acked-by: Mark Rutland Signed-off-by: Geert Uytterhoeven Signed-off-by: Will Deacon --- arch/arm64/include/asm/thread_info.h | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index e35cd84b102c..2a408dd64f5c 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -57,29 +57,18 @@ void arch_release_task_struct(struct task_struct *tsk); #endif -/* - * thread information flags: - * TIF_SYSCALL_TRACE - syscall trace active - * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace - * TIF_SYSCALL_AUDIT - syscall auditing - * TIF_SECCOMP - syscall secure computing - * TIF_SYSCALL_EMU - syscall emulation active - * TIF_SIGPENDING - signal pending - * TIF_NEED_RESCHED - rescheduling necessary - * TIF_NOTIFY_RESUME - callback before returning to user - */ -#define TIF_SIGPENDING 0 -#define TIF_NEED_RESCHED 1 +#define TIF_SIGPENDING 0 /* signal pending */ +#define TIF_NEED_RESCHED 1 /* rescheduling necessary */ #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */ #define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */ #define TIF_FSCHECK 5 /* Check FS is USER_DS on return */ #define TIF_NOHZ 7 -#define TIF_SYSCALL_TRACE 8 -#define TIF_SYSCALL_AUDIT 9 -#define TIF_SYSCALL_TRACEPOINT 10 -#define TIF_SECCOMP 11 -#define TIF_SYSCALL_EMU 12 +#define TIF_SYSCALL_TRACE 8 /* syscall trace active */ +#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */ +#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */ +#define TIF_SECCOMP 11 /* syscall secure computing */ +#define TIF_SYSCALL_EMU 12 /* syscall emulation active */ #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_FREEZE 19 #define TIF_RESTORE_SIGMASK 20 -- GitLab From 5cf896fb6be3effd9aea455b22213e27be8bdb1d Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 31 Jul 2019 18:18:42 -0700 Subject: [PATCH 1885/7155] arm64: Add support for relocating the kernel with RELR relocations RELR is a relocation packing format for relative relocations. The format is described in a generic-abi proposal: https://groups.google.com/d/topic/generic-abi/bX460iggiKg/discussion The LLD linker can be instructed to pack relocations in the RELR format by passing the flag --pack-dyn-relocs=relr. This patch adds a new config option, CONFIG_RELR. Enabling this option instructs the linker to pack vmlinux's relative relocations in the RELR format, and causes the kernel to apply the relocations at startup along with the RELA relocations. RELA relocations still need to be applied because the linker will emit RELA relative relocations if they are unrepresentable in the RELR format (i.e. address not a multiple of 2). Enabling CONFIG_RELR reduces the size of a defconfig kernel image with CONFIG_RANDOMIZE_BASE by 3.5MB/16% uncompressed, or 550KB/5% compressed (lz4). Signed-off-by: Peter Collingbourne Tested-by: Nick Desaulniers Reviewed-by: Nick Desaulniers Signed-off-by: Will Deacon --- Makefile | 4 ++ arch/Kconfig | 14 +++++ arch/arm64/Kconfig | 1 + arch/arm64/kernel/head.S | 96 ++++++++++++++++++++++++++++++--- arch/arm64/kernel/vmlinux.lds.S | 9 ++++ init/Kconfig | 3 ++ scripts/tools-support-relr.sh | 16 ++++++ 7 files changed, 137 insertions(+), 6 deletions(-) create mode 100755 scripts/tools-support-relr.sh diff --git a/Makefile b/Makefile index 23cdf1f41364..9e6ec0c9962c 100644 --- a/Makefile +++ b/Makefile @@ -912,6 +912,10 @@ ifeq ($(CONFIG_STRIP_ASM_SYMS),y) LDFLAGS_vmlinux += $(call ld-option, -X,) endif +ifeq ($(CONFIG_RELR),y) +LDFLAGS_vmlinux += --pack-dyn-relocs=relr +endif + # insure the checker run with the right endianness CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian) diff --git a/arch/Kconfig b/arch/Kconfig index a7b57dd42c26..aa6bdb3df5c1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -925,6 +925,20 @@ config LOCK_EVENT_COUNTS the chance of application behavior change because of timing differences. The counts are reported via debugfs. +# Select if the architecture has support for applying RELR relocations. +config ARCH_HAS_RELR + bool + +config RELR + bool "Use RELR relocation packing" + depends on ARCH_HAS_RELR && TOOLS_SUPPORT_RELR + default y + help + Store the kernel's dynamic relocations in the RELR relocation packing + format. Requires a compatible linker (LLD supports this feature), as + well as compatible NM and OBJCOPY utilities (llvm-nm and llvm-objcopy + are compatible). + source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3adcec05b1f6..2681eb79c40b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1467,6 +1467,7 @@ endif config RELOCATABLE bool + select ARCH_HAS_RELR help This builds the kernel as a Position Independent Executable (PIE), which retains all relocation metadata required to relocate the diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 2cdacd1c141b..cc23302e9d95 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -102,6 +102,8 @@ pe_header: * x23 stext() .. start_kernel() physical misalignment/KASLR offset * x28 __create_page_tables() callee preserved temp register * x19/x20 __primary_switch() callee preserved temp registers + * x24 __primary_switch() .. relocate_kernel() + * current RELR displacement */ ENTRY(stext) bl preserve_boot_args @@ -834,14 +836,93 @@ __relocate_kernel: 0: cmp x9, x10 b.hs 1f - ldp x11, x12, [x9], #24 - ldr x13, [x9, #-8] - cmp w12, #R_AARCH64_RELATIVE + ldp x12, x13, [x9], #24 + ldr x14, [x9, #-8] + cmp w13, #R_AARCH64_RELATIVE b.ne 0b - add x13, x13, x23 // relocate - str x13, [x11, x23] + add x14, x14, x23 // relocate + str x14, [x12, x23] b 0b -1: ret + +1: +#ifdef CONFIG_RELR + /* + * Apply RELR relocations. + * + * RELR is a compressed format for storing relative relocations. The + * encoded sequence of entries looks like: + * [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] + * + * i.e. start with an address, followed by any number of bitmaps. The + * address entry encodes 1 relocation. The subsequent bitmap entries + * encode up to 63 relocations each, at subsequent offsets following + * the last address entry. + * + * The bitmap entries must have 1 in the least significant bit. The + * assumption here is that an address cannot have 1 in lsb. Odd + * addresses are not supported. Any odd addresses are stored in the RELA + * section, which is handled above. + * + * Excluding the least significant bit in the bitmap, each non-zero + * bit in the bitmap represents a relocation to be applied to + * a corresponding machine word that follows the base address + * word. The second least significant bit represents the machine + * word immediately following the initial address, and each bit + * that follows represents the next word, in linear order. As such, + * a single bitmap can encode up to 63 relocations in a 64-bit object. + * + * In this implementation we store the address of the next RELR table + * entry in x9, the address being relocated by the current address or + * bitmap entry in x13 and the address being relocated by the current + * bit in x14. + * + * Because addends are stored in place in the binary, RELR relocations + * cannot be applied idempotently. We use x24 to keep track of the + * currently applied displacement so that we can correctly relocate if + * __relocate_kernel is called twice with non-zero displacements (i.e. + * if there is both a physical misalignment and a KASLR displacement). + */ + ldr w9, =__relr_offset // offset to reloc table + ldr w10, =__relr_size // size of reloc table + add x9, x9, x11 // __va(.relr) + add x10, x9, x10 // __va(.relr) + sizeof(.relr) + + sub x15, x23, x24 // delta from previous offset + cbz x15, 7f // nothing to do if unchanged + mov x24, x23 // save new offset + +2: cmp x9, x10 + b.hs 7f + ldr x11, [x9], #8 + tbnz x11, #0, 3f // branch to handle bitmaps + add x13, x11, x23 + ldr x12, [x13] // relocate address entry + add x12, x12, x15 + str x12, [x13], #8 // adjust to start of bitmap + b 2b + +3: mov x14, x13 +4: lsr x11, x11, #1 + cbz x11, 6f + tbz x11, #0, 5f // skip bit if not set + ldr x12, [x14] // relocate bit + add x12, x12, x15 + str x12, [x14] + +5: add x14, x14, #8 // move to next bit's address + b 4b + +6: /* + * Move to the next bitmap's address. 8 is the word size, and 63 is the + * number of significant bits in a bitmap entry. + */ + add x13, x13, #(8 * 63) + b 2b + +7: +#endif + ret + ENDPROC(__relocate_kernel) #endif @@ -854,6 +935,9 @@ __primary_switch: adrp x1, init_pg_dir bl __enable_mmu #ifdef CONFIG_RELOCATABLE +#ifdef CONFIG_RELR + mov x24, #0 // no RELR displacement yet +#endif bl __relocate_kernel #ifdef CONFIG_RANDOMIZE_BASE ldr x8, =__primary_switched diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 7fa008374907..31716afa30f6 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -200,6 +200,15 @@ SECTIONS __rela_offset = ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR); __rela_size = SIZEOF(.rela.dyn); +#ifdef CONFIG_RELR + .relr.dyn : ALIGN(8) { + *(.relr.dyn) + } + + __relr_offset = ABSOLUTE(ADDR(.relr.dyn) - KIMAGE_VADDR); + __relr_size = SIZEOF(.relr.dyn); +#endif + . = ALIGN(SEGMENT_ALIGN); __initdata_end = .; __init_end = .; diff --git a/init/Kconfig b/init/Kconfig index bd7d650d4a99..d96127ebc44e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -30,6 +30,9 @@ config CC_CAN_LINK config CC_HAS_ASM_GOTO def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC)) +config TOOLS_SUPPORT_RELR + def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh) + config CC_HAS_WARN_MAYBE_UNINITIALIZED def_bool $(cc-option,-Wmaybe-uninitialized) help diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh new file mode 100755 index 000000000000..97a2c844a95e --- /dev/null +++ b/scripts/tools-support-relr.sh @@ -0,0 +1,16 @@ +#!/bin/sh -eu +# SPDX-License-Identifier: GPL-2.0 + +tmp_file=$(mktemp) +trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT + +cat << "END" | "$CC" -c -x c - -o $tmp_file.o >/dev/null 2>&1 +void *p = &p; +END +"$LD" $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file + +# Despite printing an error message, GNU nm still exits with exit code 0 if it +# sees a relr section. So we need to check that nothing is printed to stderr. +test -z "$("$NM" $tmp_file 2>&1 >/dev/null)" + +"$OBJCOPY" -O binary $tmp_file $tmp_file.bin -- GitLab From 425c6f1063955fd2335b44b6ba628de3e3a81b4d Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Wed, 31 Jul 2019 16:07:05 +0200 Subject: [PATCH 1886/7155] iio: potentiometer: add a driver for Maxim 5432-5435 Add a driver for the Maxim Integrated MAX5432-MAX5435 family of digital potentiometers. These potentiometers are connected via I2C and have 32 wiper positions. Supported functionality - set the volatile wiper position - read the potentiometer scale Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf Signed-off-by: Martin Kaiser Signed-off-by: Jonathan Cameron --- drivers/iio/potentiometer/Kconfig | 11 +++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/max5432.c | 135 ++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 drivers/iio/potentiometer/max5432.c diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index ebc7c72a5e36..4cac0173db8b 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -26,6 +26,17 @@ config DS1803 To compile this driver as a module, choose M here: the module will be called ds1803. +config MAX5432 + tristate "Maxim MAX5432-MAX5435 Digital Potentiometer driver" + depends on I2C + help + Say yes here to build support for the Maxim + MAX5432, MAX5433, MAX5434 and MAX5435 digital + potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called max5432. + config MAX5481 tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver" depends on SPI diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 8ff55138cf12..091adf3cdd0b 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -6,6 +6,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AD5272) += ad5272.o obj-$(CONFIG_DS1803) += ds1803.o +obj-$(CONFIG_MAX5432) += max5432.o obj-$(CONFIG_MAX5481) += max5481.o obj-$(CONFIG_MAX5487) += max5487.o obj-$(CONFIG_MCP4018) += mcp4018.o diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c new file mode 100644 index 000000000000..641b1821fdf6 --- /dev/null +++ b/drivers/iio/potentiometer/max5432.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Maxim Integrated MAX5432-MAX5435 digital potentiometer driver + * Copyright (C) 2019 Martin Kaiser + * + * Datasheet: + * https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf + */ + +#include +#include +#include +#include +#include +#include + +/* All chip variants have 32 wiper positions. */ +#define MAX5432_MAX_POS 31 + +#define MAX5432_OHM_50K (50 * 1000) +#define MAX5432_OHM_100K (100 * 1000) + +/* Update the volatile (currently active) setting. */ +#define MAX5432_CMD_VREG 0x11 + +struct max5432_data { + struct i2c_client *client; + unsigned long ohm; +}; + +static const struct iio_chan_spec max5432_channels[] = { + { + .type = IIO_RESISTANCE, + .indexed = 1, + .output = 1, + .channel = 0, + .address = MAX5432_CMD_VREG, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + } +}; + +static int max5432_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct max5432_data *data = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_SCALE) + return -EINVAL; + + if (unlikely(data->ohm > INT_MAX)) + return -ERANGE; + + *val = data->ohm; + *val2 = MAX5432_MAX_POS; + + return IIO_VAL_FRACTIONAL; +} + +static int max5432_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct max5432_data *data = iio_priv(indio_dev); + u8 data_byte; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val < 0 || val > MAX5432_MAX_POS) + return -EINVAL; + + if (val2 != 0) + return -EINVAL; + + /* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */ + data_byte = val << 3; + return i2c_smbus_write_byte_data(data->client, chan->address, + data_byte); +} + +static const struct iio_info max5432_info = { + .read_raw = max5432_read_raw, + .write_raw = max5432_write_raw, +}; + +static int max5432_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct iio_dev *indio_dev; + struct max5432_data *data; + + indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data)); + if (!indio_dev) + return -ENOMEM; + + i2c_set_clientdata(client, indio_dev); + + data = iio_priv(indio_dev); + data->client = client; + data->ohm = (unsigned long)of_device_get_match_data(dev); + + indio_dev->dev.parent = dev; + indio_dev->info = &max5432_info; + indio_dev->channels = max5432_channels; + indio_dev->num_channels = ARRAY_SIZE(max5432_channels); + indio_dev->name = client->name; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id max5432_dt_ids[] = { + { .compatible = "maxim,max5432", .data = (void *)MAX5432_OHM_50K }, + { .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K }, + { .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K }, + { .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, max5432_dt_ids); + +static struct i2c_driver max5432_driver = { + .driver = { + .name = "max5432", + .of_match_table = of_match_ptr(max5432_dt_ids), + }, + .probe = max5432_probe, +}; + +module_i2c_driver(max5432_driver); + +MODULE_AUTHOR("Martin Kaiser "); +MODULE_DESCRIPTION("max5432-max5435 digital potentiometers"); +MODULE_LICENSE("GPL v2"); -- GitLab From 5e8447d1b0a79c318a8a71cf5e6533a5a5e1b02c Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Wed, 31 Jul 2019 16:07:06 +0200 Subject: [PATCH 1887/7155] dt-bindings: iio: potentiometer: add max5432.yaml binding Add a binding for the Maxim Integrated MAX5432-MAX5435 family of digital potentiometers. Signed-off-by: Martin Kaiser Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/potentiometer/max5432.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml diff --git a/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml new file mode 100644 index 000000000000..5082f919df2a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/potentiometer/max5432.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX5432-MAX5435 Digital Potentiometers + +maintainers: + - Martin Kaiser + +description: | + Maxim Integrated MAX5432-MAX5435 Digital Potentiometers connected via I2C + + Datasheet: + https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf + +properties: + compatible: + enum: + - maxim,max5432 + - maxim,max5433 + - maxim,max5434 + - maxim,max5435 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + max5434@28 { + compatible = "maxim,max5434"; + reg = <0x28>; + }; + }; -- GitLab From d162aea8f633f885ebdd1d235764afe601d97458 Mon Sep 17 00:00:00 2001 From: Malathi Gottam Date: Mon, 26 Nov 2018 08:12:53 -0200 Subject: [PATCH 1888/7155] media: venus: venc: amend buffer size for bitstream plane Accept the buffer size requested by client and compare it against driver calculated size and set the maximum to bitstream plane. Signed-off-by: Malathi Gottam Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/venc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index a5f3d2c46bea..1b7fb2d5887c 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -294,6 +294,7 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; const struct venus_format *fmt; + u32 sizeimage; memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); @@ -325,9 +326,10 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) pixmp->num_planes = fmt->num_planes; pixmp->flags = 0; - pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat, - pixmp->width, - pixmp->height); + sizeimage = venus_helper_get_framesz(pixmp->pixelformat, + pixmp->width, + pixmp->height); + pfmt[0].sizeimage = max(ALIGN(pfmt[0].sizeimage, SZ_4K), sizeimage); if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) pfmt[0].bytesperline = ALIGN(pixmp->width, 128); @@ -399,8 +401,10 @@ static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) inst->fmt_out = fmt; - else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { inst->fmt_cap = fmt; + inst->output_buf_size = pixmp->plane_fmt[0].sizeimage; + } return 0; } @@ -918,6 +922,7 @@ static int venc_queue_setup(struct vb2_queue *q, sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt, inst->width, inst->height); + sizes[0] = max(sizes[0], inst->output_buf_size); inst->output_buf_size = sizes[0]; break; default: -- GitLab From 1e485ee5a7240b1c230ef0b74899253a512deb60 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 10:56:33 -0200 Subject: [PATCH 1889/7155] media: venus: helpers: export few helper functions Here we export few helper function to use them from decoder to implement more granular control needed for stateful Codec API compliance. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 29 ++++++++++++--------- drivers/media/platform/qcom/venus/helpers.h | 6 +++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 71b06dfc6dc4..63af69acc068 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -79,7 +79,7 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_check_codec); -static int venus_helper_queue_dpb_bufs(struct venus_inst *inst) +int venus_helper_queue_dpb_bufs(struct venus_inst *inst) { struct intbuf *buf; int ret = 0; @@ -100,6 +100,7 @@ static int venus_helper_queue_dpb_bufs(struct venus_inst *inst) fail: return ret; } +EXPORT_SYMBOL_GPL(venus_helper_queue_dpb_bufs); int venus_helper_free_dpb_bufs(struct venus_inst *inst) { @@ -278,7 +279,7 @@ static const unsigned int intbuf_types_4xx[] = { HFI_BUFFER_INTERNAL_PERSIST_1, }; -static int intbufs_alloc(struct venus_inst *inst) +int venus_helper_intbufs_alloc(struct venus_inst *inst) { const unsigned int *intbuf; size_t arr_sz, i; @@ -304,11 +305,13 @@ static int intbufs_alloc(struct venus_inst *inst) intbufs_unset_buffers(inst); return ret; } +EXPORT_SYMBOL_GPL(venus_helper_intbufs_alloc); -static int intbufs_free(struct venus_inst *inst) +int venus_helper_intbufs_free(struct venus_inst *inst) { return intbufs_unset_buffers(inst); } +EXPORT_SYMBOL_GPL(venus_helper_intbufs_free); static u32 load_per_instance(struct venus_inst *inst) { @@ -339,7 +342,7 @@ static u32 load_per_type(struct venus_core *core, u32 session_type) return mbs_per_sec; } -static int load_scale_clocks(struct venus_core *core) +int venus_helper_load_scale_clocks(struct venus_core *core) { const struct freq_tbl *table = core->res->freq_tbl; unsigned int num_rows = core->res->freq_tbl_size; @@ -388,6 +391,7 @@ static int load_scale_clocks(struct venus_core *core) dev_err(dev, "failed to set clock rate %lu (%d)\n", freq, ret); return ret; } +EXPORT_SYMBOL_GPL(venus_helper_load_scale_clocks); static void fill_buffer_desc(const struct venus_buffer *buf, struct hfi_buffer_desc *bd, bool response) @@ -472,7 +476,7 @@ static bool is_dynamic_bufmode(struct venus_inst *inst) return caps->cap_bufs_mode_dynamic; } -static int session_unregister_bufs(struct venus_inst *inst) +int venus_helper_unregister_bufs(struct venus_inst *inst) { struct venus_buffer *buf, *n; struct hfi_buffer_desc bd; @@ -489,6 +493,7 @@ static int session_unregister_bufs(struct venus_inst *inst) return ret; } +EXPORT_SYMBOL_GPL(venus_helper_unregister_bufs); static int session_register_bufs(struct venus_inst *inst) { @@ -1009,8 +1014,8 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) if (inst->streamon_out & inst->streamon_cap) { ret = hfi_session_stop(inst); ret |= hfi_session_unload_res(inst); - ret |= session_unregister_bufs(inst); - ret |= intbufs_free(inst); + ret |= venus_helper_unregister_bufs(inst); + ret |= venus_helper_intbufs_free(inst); ret |= hfi_session_deinit(inst); if (inst->session_error || core->sys_error) @@ -1021,7 +1026,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) venus_helper_free_dpb_bufs(inst); - load_scale_clocks(core); + venus_helper_load_scale_clocks(core); INIT_LIST_HEAD(&inst->registeredbufs); } @@ -1041,7 +1046,7 @@ int venus_helper_vb2_start_streaming(struct venus_inst *inst) struct venus_core *core = inst->core; int ret; - ret = intbufs_alloc(inst); + ret = venus_helper_intbufs_alloc(inst); if (ret) return ret; @@ -1049,7 +1054,7 @@ int venus_helper_vb2_start_streaming(struct venus_inst *inst) if (ret) goto err_bufs_free; - load_scale_clocks(core); + venus_helper_load_scale_clocks(core); ret = hfi_session_load_res(inst); if (ret) @@ -1070,9 +1075,9 @@ int venus_helper_vb2_start_streaming(struct venus_inst *inst) err_unload_res: hfi_session_unload_res(inst); err_unreg_bufs: - session_unregister_bufs(inst); + venus_helper_unregister_bufs(inst); err_bufs_free: - intbufs_free(inst); + venus_helper_intbufs_free(inst); return ret; } EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 153783687a0c..70288dc860ff 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -9,6 +9,7 @@ #include struct venus_inst; +struct venus_core; bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt); struct vb2_v4l2_buffer *venus_helper_find_buf(struct venus_inst *inst, @@ -53,4 +54,9 @@ int venus_helper_alloc_dpb_bufs(struct venus_inst *inst); int venus_helper_free_dpb_bufs(struct venus_inst *inst); int venus_helper_power_enable(struct venus_core *core, u32 session_type, bool enable); +int venus_helper_intbufs_alloc(struct venus_inst *inst); +int venus_helper_intbufs_free(struct venus_inst *inst); +int venus_helper_queue_dpb_bufs(struct venus_inst *inst); +int venus_helper_unregister_bufs(struct venus_inst *inst); +int venus_helper_load_scale_clocks(struct venus_core *core); #endif -- GitLab From 05dea7980d0b9eba9f7fc5b269985d94a108e133 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 11:08:36 -0200 Subject: [PATCH 1890/7155] media: venus: hfi: add type argument to hfi flush function Make hfi_flush function to receive an argument for the type of flush. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi.c | 4 ++-- drivers/media/platform/qcom/venus/hfi.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 6ad0c1772ea7..7c5bf5cb32de 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -375,14 +375,14 @@ int hfi_session_unload_res(struct venus_inst *inst) return 0; } -int hfi_session_flush(struct venus_inst *inst) +int hfi_session_flush(struct venus_inst *inst, u32 type) { const struct hfi_ops *ops = inst->core->ops; int ret; reinit_completion(&inst->done); - ret = ops->session_flush(inst, HFI_FLUSH_ALL); + ret = ops->session_flush(inst, type); if (ret) return ret; diff --git a/drivers/media/platform/qcom/venus/hfi.h b/drivers/media/platform/qcom/venus/hfi.h index b121cb1427ac..855822c9f39b 100644 --- a/drivers/media/platform/qcom/venus/hfi.h +++ b/drivers/media/platform/qcom/venus/hfi.h @@ -161,7 +161,7 @@ int hfi_session_continue(struct venus_inst *inst); int hfi_session_abort(struct venus_inst *inst); int hfi_session_load_res(struct venus_inst *inst); int hfi_session_unload_res(struct venus_inst *inst); -int hfi_session_flush(struct venus_inst *inst); +int hfi_session_flush(struct venus_inst *inst, u32 type); int hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd); int hfi_session_unset_buffers(struct venus_inst *inst, -- GitLab From e42dbe8e86e89f77921bd117873604b9e26bbb19 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 11:39:08 -0200 Subject: [PATCH 1891/7155] media: venus: hfi: export few HFI functions Export few HFI functions to use them from decoder to implement more granular control needed for stateful Codec API compliance. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 7c5bf5cb32de..82eb889ab541 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -276,6 +276,7 @@ int hfi_session_start(struct venus_inst *inst) return 0; } +EXPORT_SYMBOL_GPL(hfi_session_start); int hfi_session_stop(struct venus_inst *inst) { @@ -299,6 +300,7 @@ int hfi_session_stop(struct venus_inst *inst) return 0; } +EXPORT_SYMBOL_GPL(hfi_session_stop); int hfi_session_continue(struct venus_inst *inst) { @@ -328,6 +330,7 @@ int hfi_session_abort(struct venus_inst *inst) return 0; } +EXPORT_SYMBOL_GPL(hfi_session_abort); int hfi_session_load_res(struct venus_inst *inst) { @@ -374,6 +377,7 @@ int hfi_session_unload_res(struct venus_inst *inst) return 0; } +EXPORT_SYMBOL_GPL(hfi_session_unload_res); int hfi_session_flush(struct venus_inst *inst, u32 type) { -- GitLab From a367b9ab3eb5de3836af1ce2a6cae4d56e7de4bd Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 11:41:14 -0200 Subject: [PATCH 1892/7155] media: venus: hfi: return an error if session_init is already called This makes hfi_session_init to return an error when it is already called without a call to hfi_session_deinit. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 82eb889ab541..3d8b1284d1f3 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -198,6 +198,9 @@ int hfi_session_init(struct venus_inst *inst, u32 pixfmt) const struct hfi_ops *ops = core->ops; int ret; + if (inst->state != INST_UNINIT) + return -EINVAL; + inst->hfi_codec = to_codec_type(pixfmt); reinit_completion(&inst->done); -- GitLab From 14ea00d65c657707b425d5cd8035c6c94ad9fe56 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 11:48:04 -0200 Subject: [PATCH 1893/7155] media: venus: helpers: add three more helper functions This adds three more helper functions: * for internal buffers reallocation, applicable when we are doing dynamic resolution change * for initial buffer processing of capture and output queue buffer types All of them will be needed for stateful Codec API support. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 82 +++++++++++++++++++++ drivers/media/platform/qcom/venus/helpers.h | 3 + 2 files changed, 85 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 63af69acc068..ab20fd3b36d9 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -313,6 +313,52 @@ int venus_helper_intbufs_free(struct venus_inst *inst) } EXPORT_SYMBOL_GPL(venus_helper_intbufs_free); +int venus_helper_intbufs_realloc(struct venus_inst *inst) +{ + enum hfi_version ver = inst->core->res->hfi_version; + struct hfi_buffer_desc bd; + struct intbuf *buf, *n; + int ret; + + list_for_each_entry_safe(buf, n, &inst->internalbufs, list) { + if (buf->type == HFI_BUFFER_INTERNAL_PERSIST || + buf->type == HFI_BUFFER_INTERNAL_PERSIST_1) + continue; + + memset(&bd, 0, sizeof(bd)); + bd.buffer_size = buf->size; + bd.buffer_type = buf->type; + bd.num_buffers = 1; + bd.device_addr = buf->da; + bd.response_required = true; + + ret = hfi_session_unset_buffers(inst, &bd); + + dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, + buf->attrs); + + list_del_init(&buf->list); + kfree(buf); + } + + ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH(ver)); + if (ret) + goto err; + + ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_1(ver)); + if (ret) + goto err; + + ret = intbufs_set_buffer(inst, HFI_BUFFER_INTERNAL_SCRATCH_2(ver)); + if (ret) + goto err; + + return 0; +err: + return ret; +} +EXPORT_SYMBOL_GPL(venus_helper_intbufs_realloc); + static u32 load_per_instance(struct venus_inst *inst) { u32 mbs; @@ -1041,6 +1087,42 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming); +int venus_helper_process_initial_cap_bufs(struct venus_inst *inst) +{ + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *buf, *n; + int ret; + + v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { + ret = session_process_buf(inst, &buf->vb); + if (ret) { + return_buf_error(inst, &buf->vb); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_process_initial_cap_bufs); + +int venus_helper_process_initial_out_bufs(struct venus_inst *inst) +{ + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *buf, *n; + int ret; + + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { + ret = session_process_buf(inst, &buf->vb); + if (ret) { + return_buf_error(inst, &buf->vb); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_process_initial_out_bufs); + int venus_helper_vb2_start_streaming(struct venus_inst *inst) { struct venus_core *core = inst->core; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 70288dc860ff..486598d52811 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -56,7 +56,10 @@ int venus_helper_power_enable(struct venus_core *core, u32 session_type, bool enable); int venus_helper_intbufs_alloc(struct venus_inst *inst); int venus_helper_intbufs_free(struct venus_inst *inst); +int venus_helper_intbufs_realloc(struct venus_inst *inst); int venus_helper_queue_dpb_bufs(struct venus_inst *inst); int venus_helper_unregister_bufs(struct venus_inst *inst); int venus_helper_load_scale_clocks(struct venus_core *core); +int venus_helper_process_initial_cap_bufs(struct venus_inst *inst); +int venus_helper_process_initial_out_bufs(struct venus_inst *inst); #endif -- GitLab From cef697d8a0632f649c9b0450e14a370b85d2d10d Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 14:40:58 -0200 Subject: [PATCH 1894/7155] media: venus: vdec_ctrls: get real minimum buffers for capture Until now we returned num_output_bufs set during reqbuf but that could be wrong when we implement stateful Codec API. So get the minimum buffers for capture from HFI. This is supposed to be called after stream header parsing, i.e. after dequeue v4l2 event for change resolution. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/vdec_ctrls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/vdec_ctrls.c b/drivers/media/platform/qcom/venus/vdec_ctrls.c index 300350bfe8bd..3a963cbd342a 100644 --- a/drivers/media/platform/qcom/venus/vdec_ctrls.c +++ b/drivers/media/platform/qcom/venus/vdec_ctrls.c @@ -7,6 +7,7 @@ #include #include "core.h" +#include "helpers.h" #include "vdec.h" static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) @@ -38,7 +39,9 @@ static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) { struct venus_inst *inst = ctrl_to_inst(ctrl); struct vdec_controls *ctr = &inst->controls.dec; + struct hfi_buffer_requirements bufreq; union hfi_get_property hprop; + enum hfi_version ver = inst->core->res->hfi_version; u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; int ret; @@ -62,7 +65,9 @@ static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ctrl->val = ctr->post_loop_deb_mode; break; case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - ctrl->val = inst->num_output_bufs; + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); + if (!ret) + ctrl->val = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); break; default: return -EINVAL; -- GitLab From dff38165a5a873741c67e728f80d5e923852cc67 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Sun, 28 Jul 2019 22:36:30 +0800 Subject: [PATCH 1895/7155] iio: light: cm3323: Use device-managed APIs Use device-managed APIs to simplify the code. The remove functions are redundant now and can be deleted. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/light/cm3323.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 50f3438c2b49..0443861ba1ec 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -101,15 +101,16 @@ static int cm3323_init(struct iio_dev *indio_dev) return 0; } -static void cm3323_disable(struct iio_dev *indio_dev) +static void cm3323_disable(void *data) { int ret; - struct cm3323_data *data = iio_priv(indio_dev); + struct iio_dev *indio_dev = data; + struct cm3323_data *cm_data = iio_priv(indio_dev); - ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, + ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF, CM3323_CONF_SD_BIT); if (ret < 0) - dev_err(&data->client->dev, "Error writing reg_conf\n"); + dev_err(&cm_data->client->dev, "Error writing reg_conf\n"); } static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) @@ -243,26 +244,11 @@ static int cm3323_probe(struct i2c_client *client, return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "failed to register iio dev\n"); - goto err_init; - } - - return 0; -err_init: - cm3323_disable(indio_dev); - return ret; -} - -static int cm3323_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - cm3323_disable(indio_dev); + ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); + if (ret < 0) + return ret; - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id cm3323_id[] = { @@ -276,7 +262,6 @@ static struct i2c_driver cm3323_driver = { .name = CM3323_DRV_NAME, }, .probe = cm3323_probe, - .remove = cm3323_remove, .id_table = cm3323_id, }; -- GitLab From be76f150bcadec1707e3718b0750a8b2261b3c20 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 16 Jan 2019 14:48:47 -0200 Subject: [PATCH 1896/7155] media: venus: vdec: allow bigger sizeimage set by clients In most of the cases the client will know better what could be the maximum size for compressed data buffers. Change the driver to permit the user to set bigger size for the compressed buffer but make reasonable sanitation. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/vdec.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index e1f998656c07..fb9afee76793 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -133,6 +133,7 @@ vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; const struct venus_format *fmt; + u32 szimage; memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); @@ -161,14 +162,17 @@ vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) pixmp->num_planes = fmt->num_planes; pixmp->flags = 0; - pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat, - pixmp->width, - pixmp->height); + szimage = venus_helper_get_framesz(pixmp->pixelformat, pixmp->width, + pixmp->height); - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + pfmt[0].sizeimage = szimage; pfmt[0].bytesperline = ALIGN(pixmp->width, 128); - else + } else { + pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M); + pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage); pfmt[0].bytesperline = 0; + } return fmt; } @@ -266,6 +270,7 @@ static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) inst->ycbcr_enc = pixmp->ycbcr_enc; inst->quantization = pixmp->quantization; inst->xfer_func = pixmp->xfer_func; + inst->input_buf_size = pixmp->plane_fmt[0].sizeimage; } memset(&format, 0, sizeof(format)); @@ -728,6 +733,7 @@ static int vdec_queue_setup(struct vb2_queue *q, sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt, inst->out_width, inst->out_height); + sizes[0] = max(sizes[0], inst->input_buf_size); inst->input_buf_size = sizes[0]; *num_buffers = max(*num_buffers, in_num); inst->num_input_bufs = *num_buffers; -- GitLab From beac82904a870b220d45b883e493b869d8d0dce5 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Thu, 17 Jan 2019 07:43:31 -0200 Subject: [PATCH 1897/7155] media: venus: make decoder compliant with stateful codec API This refactors code for start/stop streaming vb2 operations and adds a state machine handling similar to the one in stateful codec API documentation. One major change is that now the HFI session is started on STREAMON(OUTPUT) and stopped on REQBUF(OUTPUT,count=0), during that time STREAMOFF(CAP,OUT) just flush buffers but doesn't stop the session. The other major change is that now the capture and output queues are completely separated. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 23 +- drivers/media/platform/qcom/venus/helpers.c | 23 +- drivers/media/platform/qcom/venus/vdec.c | 519 +++++++++++++++----- 3 files changed, 433 insertions(+), 132 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 9ab95fd57760..1a28ca07cd84 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -209,6 +209,17 @@ struct venus_buffer { #define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb) +enum venus_dec_state { + VENUS_DEC_STATE_DEINIT = 0, + VENUS_DEC_STATE_INIT = 1, + VENUS_DEC_STATE_CAPTURE_SETUP = 2, + VENUS_DEC_STATE_STOPPED = 3, + VENUS_DEC_STATE_SEEK = 4, + VENUS_DEC_STATE_DRAIN = 5, + VENUS_DEC_STATE_DECODING = 6, + VENUS_DEC_STATE_DRC = 7 +}; + /** * struct venus_inst - holds per instance parameters * @@ -232,6 +243,10 @@ struct venus_buffer { * @colorspace: current color space * @quantization: current quantization * @xfer_func: current xfer function + * @codec_state: current codec API state (see DEC/ENC_STATE_) + * @reconf_wait: wait queue for resolution change event + * @subscriptions: used to hold current events subscriptions + * @buf_count: used to count number of buffers (reqbuf(0)) * @fps: holds current FPS * @timeperframe: holds current time per frame structure * @fmt_out: a reference to output format structure @@ -246,8 +261,6 @@ struct venus_buffer { * @opb_buftype: output picture buffer type * @opb_fmt: output picture buffer raw format * @reconfig: a flag raised by decoder when the stream resolution changed - * @reconfig_width: holds the new width - * @reconfig_height: holds the new height * @hfi_codec: current codec for this instance in HFI space * @sequence_cap: a sequence counter for capture queue * @sequence_out: a sequence counter for output queue @@ -287,6 +300,10 @@ struct venus_inst { u8 ycbcr_enc; u8 quantization; u8 xfer_func; + enum venus_dec_state codec_state; + wait_queue_head_t reconf_wait; + unsigned int subscriptions; + int buf_count; u64 fps; struct v4l2_fract timeperframe; const struct venus_format *fmt_out; @@ -301,8 +318,6 @@ struct venus_inst { u32 opb_buftype; u32 opb_fmt; bool reconfig; - u32 reconfig_width; - u32 reconfig_height; u32 hfi_codec; u32 sequence_cap; u32 sequence_out; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index ab20fd3b36d9..176facdd415d 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1021,16 +1021,19 @@ void venus_helper_vb2_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(m2m_ctx, vbuf); - if (!(inst->streamon_out & inst->streamon_cap)) + if (inst->session_type == VIDC_SESSION_TYPE_ENC && + !(inst->streamon_out && inst->streamon_cap)) goto unlock; - ret = is_buf_refed(inst, vbuf); - if (ret) - goto unlock; + if (vb2_start_streaming_called(vb->vb2_queue)) { + ret = is_buf_refed(inst, vbuf); + if (ret) + goto unlock; - ret = session_process_buf(inst, vbuf); - if (ret) - return_buf_error(inst, vbuf); + ret = session_process_buf(inst, vbuf); + if (ret) + return_buf_error(inst, vbuf); + } unlock: mutex_unlock(&inst->lock); @@ -1146,14 +1149,8 @@ int venus_helper_vb2_start_streaming(struct venus_inst *inst) if (ret) goto err_unload_res; - ret = venus_helper_queue_dpb_bufs(inst); - if (ret) - goto err_session_stop; - return 0; -err_session_stop: - hfi_session_stop(inst); err_unload_res: hfi_session_unload_res(inst); err_unreg_bufs: diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index fb9afee76793..336d49132d19 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -186,33 +186,56 @@ static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) return 0; } +static int vdec_check_src_change(struct venus_inst *inst) +{ + int ret; + + if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE && + inst->codec_state == VENUS_DEC_STATE_INIT && + !inst->reconfig) + return -EINVAL; + + if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE) + return 0; + + /* + * The code snippet below is a workaround for backward compatibility + * with applications which doesn't support V4L2 events. It will be + * dropped in future once those applications are fixed. + */ + + if (inst->codec_state != VENUS_DEC_STATE_INIT) + goto done; + + ret = wait_event_timeout(inst->reconf_wait, inst->reconfig, + msecs_to_jiffies(100)); + if (!ret) + return -EINVAL; + + if (!(inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) || + !inst->reconfig) + dev_dbg(inst->core->dev, "%s: wrong state\n", __func__); + +done: + return 0; +} + static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { struct venus_inst *inst = to_inst(file); const struct venus_format *fmt = NULL; struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; + int ret; if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) fmt = inst->fmt_cap; else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) fmt = inst->fmt_out; - if (inst->reconfig) { - struct v4l2_format format = {}; - - inst->out_width = inst->reconfig_width; - inst->out_height = inst->reconfig_height; - inst->reconfig = false; - - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt; - format.fmt.pix_mp.width = inst->out_width; - format.fmt.pix_mp.height = inst->out_height; - - vdec_try_fmt_common(inst, &format); - - inst->width = format.fmt.pix_mp.width; - inst->height = format.fmt.pix_mp.height; + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vdec_check_src_change(inst); + if (ret) + return ret; } pixmp->pixelformat = fmt->pixfmt; @@ -427,11 +450,18 @@ static int vdec_enum_framesizes(struct file *file, void *fh, static int vdec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { + struct venus_inst *inst = container_of(fh, struct venus_inst, fh); + int ret; + switch (sub->type) { case V4L2_EVENT_EOS: return v4l2_event_subscribe(fh, sub, 2, NULL); case V4L2_EVENT_SOURCE_CHANGE: - return v4l2_src_change_event_subscribe(fh, sub); + ret = v4l2_src_change_event_subscribe(fh, sub); + if (ret) + return ret; + inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE; + return 0; case V4L2_EVENT_CTRL: return v4l2_ctrl_subscribe_event(fh, sub); default: @@ -439,21 +469,6 @@ static int vdec_subscribe_event(struct v4l2_fh *fh, } } -static int -vdec_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) -{ - switch (cmd->cmd) { - case V4L2_DEC_CMD_STOP: - if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) - return -EINVAL; - break; - default: - return -EINVAL; - } - - return 0; -} - static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { @@ -461,24 +476,29 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) struct hfi_frame_data fdata = {0}; int ret; - ret = vdec_try_decoder_cmd(file, fh, cmd); + ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd); if (ret) return ret; mutex_lock(&inst->lock); - /* - * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder - * input to signal EOS. - */ - if (!(inst->streamon_out & inst->streamon_cap)) - goto unlock; + if (cmd->cmd == V4L2_DEC_CMD_STOP) { + /* + * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on + * decoder input to signal EOS. + */ + if (!(inst->streamon_out && inst->streamon_cap)) + goto unlock; - fdata.buffer_type = HFI_BUFFER_INPUT; - fdata.flags |= HFI_BUFFERFLAG_EOS; - fdata.device_addr = 0xdeadbeef; + fdata.buffer_type = HFI_BUFFER_INPUT; + fdata.flags |= HFI_BUFFERFLAG_EOS; + fdata.device_addr = 0xdeadb000; - ret = hfi_session_process_buf(inst, &fdata); + ret = hfi_session_process_buf(inst, &fdata); + + if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) + inst->codec_state = VENUS_DEC_STATE_DRAIN; + } unlock: mutex_unlock(&inst->lock); @@ -509,7 +529,7 @@ static const struct v4l2_ioctl_ops vdec_ioctl_ops = { .vidioc_enum_framesizes = vdec_enum_framesizes, .vidioc_subscribe_event = vdec_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_try_decoder_cmd = vdec_try_decoder_cmd, + .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, .vidioc_decoder_cmd = vdec_decoder_cmd, }; @@ -639,20 +659,18 @@ static int vdec_output_conf(struct venus_inst *inst) return 0; } -static int vdec_init_session(struct venus_inst *inst) +static int vdec_session_init(struct venus_inst *inst) { int ret; ret = hfi_session_init(inst, inst->fmt_out->pixfmt); - if (ret) + if (ret == -EINVAL) + return 0; + else if (ret) return ret; - ret = venus_helper_set_input_resolution(inst, inst->out_width, - inst->out_height); - if (ret) - goto deinit; - - ret = venus_helper_set_color_format(inst, inst->fmt_cap->pixfmt); + ret = venus_helper_set_input_resolution(inst, frame_width_min(inst), + frame_height_min(inst)); if (ret) goto deinit; @@ -671,26 +689,19 @@ static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num, *in_num = *out_num = 0; - ret = vdec_init_session(inst); - if (ret) - return ret; - ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); if (ret) - goto deinit; + return ret; *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); if (ret) - goto deinit; + return ret; *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); -deinit: - hfi_session_deinit(inst); - - return ret; + return 0; } static int vdec_queue_setup(struct vb2_queue *q, @@ -723,6 +734,10 @@ static int vdec_queue_setup(struct vb2_queue *q, return 0; } + ret = vdec_session_init(inst); + if (ret) + return ret; + ret = vdec_num_buffers(inst, &in_num, &out_num); if (ret) return ret; @@ -747,6 +762,11 @@ static int vdec_queue_setup(struct vb2_queue *q, inst->output_buf_size = sizes[0]; *num_buffers = max(*num_buffers, out_num); inst->num_output_bufs = *num_buffers; + + mutex_lock(&inst->lock); + if (inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) + inst->codec_state = VENUS_DEC_STATE_STOPPED; + mutex_unlock(&inst->lock); break; default: ret = -EINVAL; @@ -783,80 +803,295 @@ static int vdec_verify_conf(struct venus_inst *inst) return 0; } -static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) +static int vdec_start_capture(struct venus_inst *inst) { - struct venus_inst *inst = vb2_get_drv_priv(q); int ret; - mutex_lock(&inst->lock); + if (!inst->streamon_out) + return 0; - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - inst->streamon_out = 1; - else - inst->streamon_cap = 1; + if (inst->codec_state == VENUS_DEC_STATE_DECODING) { + if (inst->reconfig) + goto reconfigure; - if (!(inst->streamon_out & inst->streamon_cap)) { - mutex_unlock(&inst->lock); + venus_helper_queue_dpb_bufs(inst); + venus_helper_process_initial_cap_bufs(inst); + inst->streamon_cap = 1; return 0; } - venus_helper_init_instance(inst); + if (inst->codec_state != VENUS_DEC_STATE_STOPPED) + return 0; - inst->reconfig = false; - inst->sequence_cap = 0; - inst->sequence_out = 0; +reconfigure: + ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT); + if (ret) + return ret; + + ret = vdec_output_conf(inst); + if (ret) + return ret; + + ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, + VB2_MAX_FRAME, VB2_MAX_FRAME); + if (ret) + return ret; + + ret = venus_helper_intbufs_realloc(inst); + if (ret) + goto err; + + ret = venus_helper_alloc_dpb_bufs(inst); + if (ret) + goto err; + + ret = venus_helper_queue_dpb_bufs(inst); + if (ret) + goto free_dpb_bufs; - ret = vdec_init_session(inst); + ret = venus_helper_process_initial_cap_bufs(inst); if (ret) - goto bufs_done; + goto free_dpb_bufs; + + venus_helper_load_scale_clocks(inst->core); + + ret = hfi_session_continue(inst); + if (ret) + goto free_dpb_bufs; + + inst->codec_state = VENUS_DEC_STATE_DECODING; + + inst->streamon_cap = 1; + inst->sequence_cap = 0; + inst->reconfig = false; + + return 0; + +free_dpb_bufs: + venus_helper_free_dpb_bufs(inst); +err: + return ret; +} + +static int vdec_start_output(struct venus_inst *inst) +{ + int ret; + + if (inst->codec_state == VENUS_DEC_STATE_SEEK) { + ret = venus_helper_process_initial_out_bufs(inst); + inst->codec_state = VENUS_DEC_STATE_DECODING; + goto done; + } + + if (inst->codec_state == VENUS_DEC_STATE_INIT || + inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) { + ret = venus_helper_process_initial_out_bufs(inst); + goto done; + } + + if (inst->codec_state != VENUS_DEC_STATE_DEINIT) + return -EINVAL; + + venus_helper_init_instance(inst); + inst->sequence_out = 0; + inst->reconfig = false; ret = vdec_set_properties(inst); if (ret) - goto deinit_sess; + return ret; ret = vdec_output_conf(inst); if (ret) - goto deinit_sess; + return ret; ret = vdec_verify_conf(inst); if (ret) - goto deinit_sess; + return ret; ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, VB2_MAX_FRAME, VB2_MAX_FRAME); if (ret) - goto deinit_sess; + return ret; - ret = venus_helper_alloc_dpb_bufs(inst); + ret = venus_helper_vb2_start_streaming(inst); + if (ret) + return ret; + + ret = venus_helper_process_initial_out_bufs(inst); if (ret) - goto deinit_sess; + return ret; + + inst->codec_state = VENUS_DEC_STATE_INIT; + +done: + inst->streamon_out = 1; + return ret; +} + +static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct venus_inst *inst = vb2_get_drv_priv(q); + int ret; + + mutex_lock(&inst->lock); + + if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + ret = vdec_start_capture(inst); + else + ret = vdec_start_output(inst); - ret = venus_helper_vb2_start_streaming(inst); if (ret) - goto deinit_sess; + goto error; mutex_unlock(&inst->lock); - return 0; -deinit_sess: - hfi_session_deinit(inst); -bufs_done: +error: venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED); + mutex_unlock(&inst->lock); + return ret; +} + +static void vdec_cancel_dst_buffers(struct venus_inst *inst) +{ + struct vb2_v4l2_buffer *buf; + + while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx))) + v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); +} + +static int vdec_stop_capture(struct venus_inst *inst) +{ + int ret = 0; + + switch (inst->codec_state) { + case VENUS_DEC_STATE_DECODING: + ret = hfi_session_flush(inst, HFI_FLUSH_ALL); + /* fallthrough */ + case VENUS_DEC_STATE_DRAIN: + vdec_cancel_dst_buffers(inst); + inst->codec_state = VENUS_DEC_STATE_STOPPED; + break; + case VENUS_DEC_STATE_DRC: + ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT); + vdec_cancel_dst_buffers(inst); + inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP; + INIT_LIST_HEAD(&inst->registeredbufs); + venus_helper_free_dpb_bufs(inst); + break; + default: + return 0; + } + + return ret; +} + +static int vdec_stop_output(struct venus_inst *inst) +{ + int ret = 0; + + switch (inst->codec_state) { + case VENUS_DEC_STATE_DECODING: + case VENUS_DEC_STATE_DRAIN: + case VENUS_DEC_STATE_STOPPED: + ret = hfi_session_flush(inst, HFI_FLUSH_ALL); + inst->codec_state = VENUS_DEC_STATE_SEEK; + break; + case VENUS_DEC_STATE_INIT: + case VENUS_DEC_STATE_CAPTURE_SETUP: + ret = hfi_session_flush(inst, HFI_FLUSH_INPUT); + break; + default: + break; + } + + return ret; +} + +static void vdec_stop_streaming(struct vb2_queue *q) +{ + struct venus_inst *inst = vb2_get_drv_priv(q); + int ret = -EINVAL; + + mutex_lock(&inst->lock); + + if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + ret = vdec_stop_capture(inst); + else + ret = vdec_stop_output(inst); + + venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR); + + if (ret) + goto unlock; + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) inst->streamon_out = 0; else inst->streamon_cap = 0; + +unlock: + mutex_unlock(&inst->lock); +} + +static void vdec_session_release(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + int ret, abort = 0; + + mutex_lock(&inst->lock); + + inst->codec_state = VENUS_DEC_STATE_DEINIT; + + ret = hfi_session_stop(inst); + abort = (ret && ret != -EINVAL) ? 1 : 0; + ret = hfi_session_unload_res(inst); + abort = (ret && ret != -EINVAL) ? 1 : 0; + ret = venus_helper_unregister_bufs(inst); + abort = (ret && ret != -EINVAL) ? 1 : 0; + ret = venus_helper_intbufs_free(inst); + abort = (ret && ret != -EINVAL) ? 1 : 0; + ret = hfi_session_deinit(inst); + abort = (ret && ret != -EINVAL) ? 1 : 0; + + if (inst->session_error || core->sys_error) + abort = 1; + + if (abort) + hfi_session_abort(inst); + + venus_helper_free_dpb_bufs(inst); + venus_helper_load_scale_clocks(core); + INIT_LIST_HEAD(&inst->registeredbufs); + mutex_unlock(&inst->lock); - return ret; +} + +static int vdec_buf_init(struct vb2_buffer *vb) +{ + struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); + + inst->buf_count++; + + return venus_helper_vb2_buf_init(vb); +} + +static void vdec_buf_cleanup(struct vb2_buffer *vb) +{ + struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); + + inst->buf_count--; + if (!inst->buf_count) + vdec_session_release(inst); } static const struct vb2_ops vdec_vb2_ops = { .queue_setup = vdec_queue_setup, - .buf_init = venus_helper_vb2_buf_init, + .buf_init = vdec_buf_init, + .buf_cleanup = vdec_buf_cleanup, .buf_prepare = venus_helper_vb2_buf_prepare, .start_streaming = vdec_start_streaming, - .stop_streaming = venus_helper_vb2_stop_streaming, + .stop_streaming = vdec_stop_streaming, .buf_queue = venus_helper_vb2_buf_queue, }; @@ -880,9 +1115,9 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, vbuf->flags = flags; vbuf->field = V4L2_FIELD_NONE; + vb = &vbuf->vb2_buf; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - vb = &vbuf->vb2_buf; vb2_set_plane_payload(vb, 0, bytesused); vb->planes[0].data_offset = data_offset; vb->timestamp = timestamp_us * NSEC_PER_USEC; @@ -892,6 +1127,9 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; v4l2_event_queue_fh(&inst->fh, &ev); + + if (inst->codec_state == VENUS_DEC_STATE_DRAIN) + inst->codec_state = VENUS_DEC_STATE_STOPPED; } } else { vbuf->sequence = inst->sequence_out++; @@ -903,17 +1141,69 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT) state = VB2_BUF_STATE_ERROR; + if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) { + state = VB2_BUF_STATE_ERROR; + vb2_set_plane_payload(vb, 0, 0); + vb->timestamp = 0; + } + v4l2_m2m_buf_done(vbuf, state); } +static void vdec_event_change(struct venus_inst *inst, + struct hfi_event_data *ev_data, bool sufficient) +{ + static const struct v4l2_event ev = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION }; + struct device *dev = inst->core->dev_dec; + struct v4l2_format format = {}; + + mutex_lock(&inst->lock); + + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt; + format.fmt.pix_mp.width = ev_data->width; + format.fmt.pix_mp.height = ev_data->height; + + vdec_try_fmt_common(inst, &format); + + inst->width = format.fmt.pix_mp.width; + inst->height = format.fmt.pix_mp.height; + + inst->out_width = ev_data->width; + inst->out_height = ev_data->height; + + dev_dbg(dev, "event %s sufficient resources (%ux%u)\n", + sufficient ? "" : "not", ev_data->width, ev_data->height); + + if (sufficient) { + hfi_session_continue(inst); + } else { + switch (inst->codec_state) { + case VENUS_DEC_STATE_INIT: + inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP; + break; + case VENUS_DEC_STATE_DECODING: + inst->codec_state = VENUS_DEC_STATE_DRC; + break; + default: + break; + } + } + + inst->reconfig = true; + v4l2_event_queue_fh(&inst->fh, &ev); + wake_up(&inst->reconf_wait); + + mutex_unlock(&inst->lock); +} + static void vdec_event_notify(struct venus_inst *inst, u32 event, struct hfi_event_data *data) { struct venus_core *core = inst->core; struct device *dev = core->dev_dec; - static const struct v4l2_event ev = { - .type = V4L2_EVENT_SOURCE_CHANGE, - .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION }; switch (event) { case EVT_SESSION_ERROR: @@ -923,18 +1213,10 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event, case EVT_SYS_EVENT_CHANGE: switch (data->event_type) { case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: - hfi_session_continue(inst); - dev_dbg(dev, "event sufficient resources\n"); + vdec_event_change(inst, data, true); break; case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: - inst->reconfig_height = data->height; - inst->reconfig_width = data->width; - inst->reconfig = true; - - v4l2_event_queue_fh(&inst->fh, &ev); - - dev_dbg(dev, "event not sufficient resources (%ux%u)\n", - data->width, data->height); + vdec_event_change(inst, data, false); break; case HFI_EVENT_RELEASE_BUFFER_REFERENCE: venus_helper_release_buf_ref(inst, data->tag); @@ -955,20 +1237,25 @@ static const struct hfi_inst_ops vdec_hfi_ops = { static void vdec_inst_init(struct venus_inst *inst) { + inst->hfi_codec = HFI_VIDEO_CODEC_H264; inst->fmt_out = &vdec_formats[6]; inst->fmt_cap = &vdec_formats[0]; - inst->width = 1280; - inst->height = ALIGN(720, 32); - inst->out_width = 1280; - inst->out_height = 720; + inst->width = frame_width_min(inst); + inst->height = ALIGN(frame_height_min(inst), 32); + inst->out_width = frame_width_min(inst); + inst->out_height = frame_height_min(inst); inst->fps = 30; inst->timeperframe.numerator = 1; inst->timeperframe.denominator = 30; - inst->hfi_codec = HFI_VIDEO_CODEC_H264; + inst->opb_buftype = HFI_BUFFER_OUTPUT; +} + +static void vdec_m2m_device_run(void *priv) +{ } static const struct v4l2_m2m_ops vdec_m2m_ops = { - .device_run = venus_helper_m2m_device_run, + .device_run = vdec_m2m_device_run, .job_abort = venus_helper_m2m_job_abort, }; @@ -986,7 +1273,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->drv_priv = inst; src_vq->buf_struct_size = sizeof(struct venus_buffer); src_vq->allow_zero_bytesused = 1; - src_vq->min_buffers_needed = 1; + src_vq->min_buffers_needed = 0; src_vq->dev = inst->core->dev; ret = vb2_queue_init(src_vq); if (ret) @@ -1000,7 +1287,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->drv_priv = inst; dst_vq->buf_struct_size = sizeof(struct venus_buffer); dst_vq->allow_zero_bytesused = 1; - dst_vq->min_buffers_needed = 1; + dst_vq->min_buffers_needed = 0; dst_vq->dev = inst->core->dev; ret = vb2_queue_init(dst_vq); if (ret) { @@ -1030,7 +1317,9 @@ static int vdec_open(struct file *file) inst->core = core; inst->session_type = VIDC_SESSION_TYPE_DEC; inst->num_output_bufs = 1; - + inst->codec_state = VENUS_DEC_STATE_DEINIT; + inst->buf_count = 0; + init_waitqueue_head(&inst->reconf_wait); venus_helper_init_instance(inst); ret = pm_runtime_get_sync(core->dev_dec); -- GitLab From 059790467bf4a75441615c69e5efd2b4bac3cba4 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Thu, 27 Jun 2019 09:09:34 -0300 Subject: [PATCH 1898/7155] media: venus: helpers: handle correctly vbuf field Correct handling of OUTPUT buffers field and make v4l2-compliance happy. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 176facdd415d..c948c4e809b5 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -998,6 +998,17 @@ int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb) { struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); unsigned int out_buf_size = venus_helper_get_opb_size(inst); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) { + dev_err(inst->core->dev, "%s field isn't supported\n", + __func__); + return -EINVAL; + } + } if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_plane_size(vb, 0) < out_buf_size) -- GitLab From d42974e438feebda372fe4a39d7761cc596abc57 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Thu, 27 Jun 2019 12:59:11 -0300 Subject: [PATCH 1899/7155] media: venus: dec: populate properly timestamps and flags for capture buffers Cache flags, timestamps and timecode structure of OUTPUT buffers in per-instance structure array and fill correctly the same when the CAPTURE buffers are done. This will make v4l2-compliance decoder streaming test happy. Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 9 ++++ drivers/media/platform/qcom/venus/helpers.c | 54 +++++++++++++++++++++ drivers/media/platform/qcom/venus/helpers.h | 2 + drivers/media/platform/qcom/venus/vdec.c | 2 + 4 files changed, 67 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 1a28ca07cd84..959eaa550f4e 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -220,6 +220,14 @@ enum venus_dec_state { VENUS_DEC_STATE_DRC = 7 }; +struct venus_ts_metadata { + bool used; + u64 ts_ns; + u64 ts_us; + u32 flags; + struct v4l2_timecode tc; +}; + /** * struct venus_inst - holds per instance parameters * @@ -304,6 +312,7 @@ struct venus_inst { wait_queue_head_t reconf_wait; unsigned int subscriptions; int buf_count; + struct venus_ts_metadata tss[VIDEO_MAX_FRAME]; u64 fps; struct v4l2_fract timeperframe; const struct venus_format *fmt_out; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index c948c4e809b5..1ad96c25ab09 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -463,6 +463,57 @@ static void return_buf_error(struct venus_inst *inst, v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); } +static void +put_ts_metadata(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) +{ + struct vb2_buffer *vb = &vbuf->vb2_buf; + unsigned int i; + int slot = -1; + u64 ts_us = vb->timestamp; + + for (i = 0; i < ARRAY_SIZE(inst->tss); i++) { + if (!inst->tss[i].used) { + slot = i; + break; + } + } + + if (slot == -1) { + dev_dbg(inst->core->dev, "%s: no free slot\n", __func__); + return; + } + + do_div(ts_us, NSEC_PER_USEC); + + inst->tss[slot].used = true; + inst->tss[slot].flags = vbuf->flags; + inst->tss[slot].tc = vbuf->timecode; + inst->tss[slot].ts_us = ts_us; + inst->tss[slot].ts_ns = vb->timestamp; +} + +void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, + struct vb2_v4l2_buffer *vbuf) +{ + struct vb2_buffer *vb = &vbuf->vb2_buf; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) { + if (!inst->tss[i].used) + continue; + + if (inst->tss[i].ts_us != timestamp_us) + continue; + + inst->tss[i].used = false; + vbuf->flags |= inst->tss[i].flags; + vbuf->timecode = inst->tss[i].tc; + vb->timestamp = inst->tss[i].ts_ns; + break; + } +} +EXPORT_SYMBOL_GPL(venus_helper_get_ts_metadata); + static int session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) { @@ -487,6 +538,9 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len) fdata.flags |= HFI_BUFFERFLAG_EOS; + + if (inst->session_type == VIDC_SESSION_TYPE_DEC) + put_ts_metadata(inst, vbuf); } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (inst->session_type == VIDC_SESSION_TYPE_ENC) fdata.buffer_type = HFI_BUFFER_OUTPUT; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 486598d52811..01f411b12f81 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -62,4 +62,6 @@ int venus_helper_unregister_bufs(struct venus_inst *inst); int venus_helper_load_scale_clocks(struct venus_core *core); int venus_helper_process_initial_cap_bufs(struct venus_inst *inst); int venus_helper_process_initial_out_bufs(struct venus_inst *inst); +void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us, + struct vb2_v4l2_buffer *vbuf); #endif diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 336d49132d19..0b7d65db5cdc 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1135,6 +1135,8 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, vbuf->sequence = inst->sequence_out++; } + venus_helper_get_ts_metadata(inst, timestamp_us, vbuf); + if (hfi_flags & HFI_BUFFERFLAG_READONLY) venus_helper_acquire_buf_ref(vbuf); -- GitLab From 40dd7343897760c4b617faa78d213e25652de9a6 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 29 Jul 2019 21:22:28 +0200 Subject: [PATCH 1900/7155] iio: imu: st_lsm6dsx: move odr_table in st_lsm6dsx_sensor_settings Move sensor odr table in st_lsm6dsx_sensor_settings in order to support sensors with different odr maps. This is a preliminary patch to add support for LSM9DS1 sensor to st_lsm6dsx driver Tested-by: Martin Kepplinger Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 196 ++++++++++++++++--- 2 files changed, 166 insertions(+), 32 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index af379a5429ed..3a89f3f6e2c7 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -200,6 +200,7 @@ struct st_lsm6dsx_ext_dev_settings { * @wai: Sensor WhoAmI default value. * @max_fifo_size: Sensor max fifo length in FIFO words. * @id: List of hw id/device name supported by the driver configuration. + * @odr_table: Hw sensors odr table (Hz + val). * @decimator: List of decimator register info (addr + mask). * @batch: List of FIFO batching register info (addr + mask). * @fifo_ops: Sensor hw FIFO parameters. @@ -213,6 +214,7 @@ struct st_lsm6dsx_settings { enum st_lsm6dsx_hw_id hw_id; const char *name; } id[ST_LSM6DSX_MAX_ID]; + struct st_lsm6dsx_odr_table_entry odr_table[2]; struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_fifo_ops fifo_ops; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index d8c4417cf4eb..b3c6c9792913 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -69,33 +69,6 @@ #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 -static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 13, 0x01 }, - .odr_avl[1] = { 26, 0x02 }, - .odr_avl[2] = { 52, 0x03 }, - .odr_avl[3] = { 104, 0x04 }, - .odr_avl[4] = { 208, 0x05 }, - .odr_avl[5] = { 416, 0x06 }, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 13, 0x01 }, - .odr_avl[1] = { 26, 0x02 }, - .odr_avl[2] = { 52, 0x03 }, - .odr_avl[3] = { 104, 0x04 }, - .odr_avl[4] = { 208, 0x05 }, - .odr_avl[5] = { 416, 0x06 }, - } -}; - static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -129,6 +102,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -179,6 +178,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3H_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -238,6 +263,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3TRC_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -291,6 +342,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DSOX_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -359,6 +436,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_ASM330LHH_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -401,6 +504,32 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DSR_DEV_NAME, }, }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -563,20 +692,22 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val) { + const struct st_lsm6dsx_odr_table_entry *odr_table; int i; + odr_table = &sensor->hw->settings->odr_table[sensor->id]; for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) /* * ext devices can run at different odr respect to * accel sensor */ - if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz >= odr) + if (odr_table->odr_avl[i].hz >= odr) break; if (i == ST_LSM6DSX_ODR_LIST_SIZE) return -EINVAL; - *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val; + *val = odr_table->odr_avl[i].val; return 0; } @@ -641,7 +772,7 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr) return err; } - reg = &st_lsm6dsx_odr_table[ref_sensor->id].reg; + reg = &hw->settings->odr_table[ref_sensor->id].reg; data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); } @@ -786,11 +917,12 @@ st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, { struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); enum st_lsm6dsx_sensor_id id = sensor->id; + struct st_lsm6dsx_hw *hw = sensor->hw; int i, len = 0; for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", - st_lsm6dsx_odr_table[id].odr_avl[i].hz); + hw->settings->odr_table[id].odr_avl[i].hz); buf[len - 1] = '\n'; return len; @@ -1040,7 +1172,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, sensor = iio_priv(iio_dev); sensor->id = id; sensor->hw = hw; - sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz; + sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz; sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; sensor->watermark = 1; -- GitLab From 640aca3fb897866297402f1387c12317d084b492 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 29 Jul 2019 21:22:29 +0200 Subject: [PATCH 1901/7155] iio: imu: st_lsm6dsx: move fs_table in st_lsm6dsx_sensor_settings Move fs_table in st_lsm6dsx_sensor_settings in order to support sensors with different gain maps. This is a preliminary patch to add support for LSM9DS1 sensor to st_lsm6dsx driver Tested-by: Martin Kepplinger Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 175 +++++++++++++++---- 2 files changed, 144 insertions(+), 33 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 3a89f3f6e2c7..ab1c66615d67 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -201,6 +201,7 @@ struct st_lsm6dsx_ext_dev_settings { * @max_fifo_size: Sensor max fifo length in FIFO words. * @id: List of hw id/device name supported by the driver configuration. * @odr_table: Hw sensors odr table (Hz + val). + * @fs_table: Hw sensors gain table (gain + val). * @decimator: List of decimator register info (addr + mask). * @batch: List of FIFO batching register info (addr + mask). * @fifo_ops: Sensor hw FIFO parameters. @@ -215,6 +216,7 @@ struct st_lsm6dsx_settings { const char *name; } id[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_odr_table_entry odr_table[2]; + struct st_lsm6dsx_fs_table_entry fs_table[2]; struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_fifo_ops fifo_ops; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index b3c6c9792913..9aa109428a52 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -69,29 +69,6 @@ #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 -static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, - } -}; - static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .wai = 0x69, @@ -128,6 +105,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -204,6 +203,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -289,6 +310,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -368,6 +411,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -462,6 +527,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -530,6 +617,28 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .odr_avl[5] = { 416, 0x06 }, }, }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -665,23 +774,22 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id, static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, u32 gain) { - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *reg; + const struct st_lsm6dsx_fs_table_entry *fs_table; unsigned int data; int i, err; - u8 val; + fs_table = &sensor->hw->settings->fs_table[sensor->id]; for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) - if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain) + if (fs_table->fs_avl[i].gain == gain) break; if (i == ST_LSM6DSX_FS_LIST_SIZE) return -EINVAL; - val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val; - reg = &st_lsm6dsx_fs_table[sensor->id].reg; - data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); + data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, + fs_table->reg.mask); + err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, + fs_table->reg.mask, data); if (err < 0) return err; @@ -934,11 +1042,12 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, { struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); enum st_lsm6dsx_sensor_id id = sensor->id; + struct st_lsm6dsx_hw *hw = sensor->hw; int i, len = 0; for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - st_lsm6dsx_fs_table[id].fs_avl[i].gain); + hw->settings->fs_table[id].fs_avl[i].gain); buf[len - 1] = '\n'; return len; @@ -1173,7 +1282,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, sensor->id = id; sensor->hw = hw; sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz; - sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; + sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; sensor->watermark = 1; switch (id) { -- GitLab From ec19a6f4999344fcd5e3a3bf8037f8c9e8c24433 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 29 Jul 2019 21:22:30 +0200 Subject: [PATCH 1902/7155] iio: imu: st_lsm6dsx: inline output acc/gyro output regs Remove output register definition and inline register value since they are used only for iio channel definition. This is a preliminary patch to add support for LSM9DS1 sensor to st_lsm6dsx driver Signed-off-by: Lorenzo Bianconi Tested-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 26 +++++--------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 9aa109428a52..0abd5b85b398 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -61,14 +61,6 @@ #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) -#define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28 -#define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a -#define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c - -#define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22 -#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 -#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 - static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .wai = 0x69, @@ -701,22 +693,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }; static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR, - IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR, - IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR, - IIO_MOD_Z, 2), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), IIO_CHAN_SOFT_TIMESTAMP(3), }; static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR, - IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR, - IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR, - IIO_MOD_Z, 2), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), IIO_CHAN_SOFT_TIMESTAMP(3), }; -- GitLab From f48bc49b97470bbd27fcdaab159973e0c26c3d4f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 29 Jul 2019 21:22:31 +0200 Subject: [PATCH 1903/7155] iio: imu: st_lsm6dsx: move iio chan definitions in st_lsm6dsx_sensor_settings Move IIO channel definitions in st_lsm6dsx_sensor_settings in order to support sensors with different channels maps. This is a preliminary patch to add support for LSM9DS1 sensor to st_lsm6dsx driver. Signed-off-by: Lorenzo Bianconi Tested-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 5 + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 96 ++++++++++++++++---- 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index ab1c66615d67..5090f1b3525a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -200,6 +200,7 @@ struct st_lsm6dsx_ext_dev_settings { * @wai: Sensor WhoAmI default value. * @max_fifo_size: Sensor max fifo length in FIFO words. * @id: List of hw id/device name supported by the driver configuration. + * @channels: IIO channels supported by the device. * @odr_table: Hw sensors odr table (Hz + val). * @fs_table: Hw sensors gain table (gain + val). * @decimator: List of decimator register info (addr + mask). @@ -215,6 +216,10 @@ struct st_lsm6dsx_settings { enum st_lsm6dsx_hw_id hw_id; const char *name; } id[ST_LSM6DSX_MAX_ID]; + struct { + const struct iio_chan_spec *chan; + int len; + } channels[2]; struct st_lsm6dsx_odr_table_entry odr_table[2]; struct st_lsm6dsx_fs_table_entry fs_table[2]; struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 0abd5b85b398..fc4d18b58c97 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -61,6 +61,20 @@ #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) +static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .wai = 0x69, @@ -71,6 +85,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -169,6 +193,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3H_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -276,6 +310,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3TRC_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -377,6 +421,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DSOX_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -493,6 +547,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_ASM330LHH_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -583,6 +647,16 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DSR_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, .odr_table = { [ST_LSM6DSX_ID_ACC] = { .reg = { @@ -692,20 +766,6 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }; -static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) { const struct st_lsm6dsx_shub_settings *hub_settings; @@ -1263,6 +1323,8 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->dev.parent = hw->dev; iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; + iio_dev->channels = hw->settings->channels[id].chan; + iio_dev->num_channels = hw->settings->channels[id].len; sensor = iio_priv(iio_dev); sensor->id = id; @@ -1273,18 +1335,12 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, switch (id) { case ST_LSM6DSX_ID_ACC: - iio_dev->channels = st_lsm6dsx_acc_channels; - iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels); iio_dev->info = &st_lsm6dsx_acc_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", name); break; case ST_LSM6DSX_ID_GYRO: - iio_dev->channels = st_lsm6dsx_gyro_channels; - iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels); iio_dev->info = &st_lsm6dsx_gyro_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", name); break; -- GitLab From db947a79fc3aa78e995d0d4879f4aa7d9927e171 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 5 Aug 2019 12:18:43 +0200 Subject: [PATCH 1904/7155] iio: imu: st_lsm6dsx: add support to ISM330DHCX Add support to STM ISM330DHCX 6-axis (acc + gyro) Mems sensor https://www.st.com/resource/en/datasheet/ism330dhcx.pdf Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/Kconfig | 3 ++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 7 ++++--- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 5 ++++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 5 +++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 5 +++++ 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 6cbf65a7e11e..939058b27746 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -11,7 +11,8 @@ config IIO_ST_LSM6DSX help Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, - ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c + ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c, + ism330dhcx To compile this driver as a module, choose M here: the module will be called st_lsm6dsx. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 5090f1b3525a..4d47ba36de84 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -23,6 +23,7 @@ #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" #define ST_LSM6DSR_DEV_NAME "lsm6dsr" #define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" +#define ST_ISM330DHCX_DEV_NAME "ism330dhcx" enum st_lsm6dsx_hw_id { ST_LSM6DS3_ID, @@ -35,6 +36,7 @@ enum st_lsm6dsx_hw_id { ST_LSM6DSOX_ID, ST_LSM6DSR_ID, ST_LSM6DS3TRC_ID, + ST_ISM330DHCX_ID, ST_LSM6DSX_MAX_ID, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 1be1cec2ab23..2c03a5b80f80 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -14,9 +14,10 @@ * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the * value of the decimation factor and ODR set for each FIFO data set. * - * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR: The FIFO buffer can be configured to - * store data from gyroscope and accelerometer. Each sample is queued with - * a tag (1B) indicating data source (gyroscope, accelerometer, hw timer). + * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be + * configured to store data from gyroscope and accelerometer. Each sample + * is queued with a tag (1B) indicating data source (gyroscope, accelerometer, + * hw timer). * * FIFO supported modes: * - BYPASS: FIFO disabled diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index fc4d18b58c97..85824d6739ee 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -24,7 +24,7 @@ * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 4KB * - * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR + * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 @@ -645,6 +645,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .hw_id = ST_LSM6DSR_ID, .name = ST_LSM6DSR_DEV_NAME, + }, { + .hw_id = ST_ISM330DHCX_ID, + .name = ST_ISM330DHCX_DEV_NAME, }, }, .channels = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 28581eb0532c..15c6aa5b6caa 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -79,6 +79,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,lsm6ds3tr-c", .data = (void *)ST_LSM6DS3TRC_ID, }, + { + .compatible = "st,ism330dhcx", + .data = (void *)ST_ISM330DHCX_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); @@ -94,6 +98,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, {}, }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index 0371e8b94a3e..a8430ee11310 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -79,6 +79,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,lsm6ds3tr-c", .data = (void *)ST_LSM6DS3TRC_ID, }, + { + .compatible = "st,ism330dhcx", + .data = (void *)ST_ISM330DHCX_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -94,6 +98,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, {}, }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); -- GitLab From 5a57a9bf52b0ab3fca3e14265b98c8051b288e1b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 5 Aug 2019 12:18:44 +0200 Subject: [PATCH 1905/7155] dt-bindings: iio: imu: st_lsm6dsx: add ism330dhcx device bindings Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index 92b48f242356..87407d110bb7 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -12,6 +12,7 @@ Required properties: "st,lsm6dsox" "st,lsm6dsr" "st,lsm6ds3tr-c" + "st,ism330dhcx" - reg: i2c address of the sensor / spi cs line Optional properties: -- GitLab From d4e851983beec3c2c9f20f8be8d819ba4fcf3489 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Wed, 31 Jul 2019 14:48:57 -0700 Subject: [PATCH 1906/7155] iio:accel: preenable/postenable/predisable fixup for ST accel buffer This patch is trying to cleanup for good the buffers operation functions. There is no need of using preenable, all can be done into postenable. Let's also rename the goto label using operation to perform and not where it fails. Note, not stable material. This is cleaning up the logic flow rather than fixing a bug. Signed-off-by: Denis Ciocca Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_buffer.c | 45 +++++++++++++---------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c index 05f9aea431e2..59dcef02ec19 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -29,56 +29,52 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_accel_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_accel_buffer_postenable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *adata = iio_priv(indio_dev); + int err; adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_DMA | GFP_KERNEL); - if (adata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } + if (!adata->buffer_data) + return -ENOMEM; err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_accel_buffer_postenable_error; + goto st_accel_free_buffer; err = st_sensors_set_axis_enable(indio_dev, - (u8)indio_dev->active_scan_mask[0]); + (u8)indio_dev->active_scan_mask[0]); if (err < 0) - goto st_sensors_set_axis_enable_error; + goto st_accel_buffer_predisable; - return err; + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_accel_buffer_enable_all_axis; + + return 0; -st_sensors_set_axis_enable_error: +st_accel_buffer_enable_all_axis: + st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); +st_accel_buffer_predisable: iio_triggered_buffer_predisable(indio_dev); -st_accel_buffer_postenable_error: +st_accel_free_buffer: kfree(adata->buffer_data); -allocate_memory_error: return err; } static int st_accel_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; struct st_sensor_data *adata = iio_priv(indio_dev); - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - if (err < 0) - goto st_accel_buffer_predisable_error; + int err, err2; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_accel_buffer_predisable_error; + goto st_accel_buffer_predisable; + + err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_accel_buffer_predisable_error: +st_accel_buffer_predisable: err2 = iio_triggered_buffer_predisable(indio_dev); if (!err) err = err2; @@ -88,7 +84,6 @@ static int st_accel_buffer_predisable(struct iio_dev *indio_dev) } static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { - .preenable = &st_accel_buffer_preenable, .postenable = &st_accel_buffer_postenable, .predisable = &st_accel_buffer_predisable, }; -- GitLab From 21b1ee3190340007378448fa1cae2f46046c2d35 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Wed, 31 Jul 2019 14:48:58 -0700 Subject: [PATCH 1907/7155] iio:gyro: preenable/postenable/predisable fixup for ST gyro buffer This patch is trying to cleanup for good the buffers operation functions. There is no need of using preenable, all can be done into postenable. Let's also use logical sequence of operations as already done in accel driver. Finally also rename the goto label using operation to perform and not where it fails. Not stable material as not fixing a 'bug' but rather bringing the driver in line with general 'patterns' to allow a subsystem wide cleanup. Signed-off-by: Denis Ciocca Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro_buffer.c | 49 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c index 21360681d4dd..c6ddfecc1fc3 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -29,62 +29,61 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_gyro_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *gdata = iio_priv(indio_dev); + int err; gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_DMA | GFP_KERNEL); - if (gdata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } + if (!gdata->buffer_data) + return -ENOMEM; + + err = iio_triggered_buffer_postenable(indio_dev); + if (err < 0) + goto st_gyro_free_buffer; err = st_sensors_set_axis_enable(indio_dev, - (u8)indio_dev->active_scan_mask[0]); + (u8)indio_dev->active_scan_mask[0]); if (err < 0) - goto st_gyro_buffer_postenable_error; + goto st_gyro_buffer_predisable; - err = iio_triggered_buffer_postenable(indio_dev); + err = st_sensors_set_enable(indio_dev, true); if (err < 0) - goto st_gyro_buffer_postenable_error; + goto st_gyro_buffer_enable_all_axis; - return err; + return 0; -st_gyro_buffer_postenable_error: +st_gyro_buffer_enable_all_axis: + st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); +st_gyro_buffer_predisable: + iio_triggered_buffer_predisable(indio_dev); +st_gyro_free_buffer: kfree(gdata->buffer_data); -allocate_memory_error: return err; } static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) { - int err; + int err, err2; struct st_sensor_data *gdata = iio_priv(indio_dev); - err = iio_triggered_buffer_predisable(indio_dev); + err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_gyro_buffer_predisable_error; + goto st_gyro_buffer_predisable; err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - if (err < 0) - goto st_gyro_buffer_predisable_error; - err = st_sensors_set_enable(indio_dev, false); +st_gyro_buffer_predisable: + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; -st_gyro_buffer_predisable_error: kfree(gdata->buffer_data); return err; } static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { - .preenable = &st_gyro_buffer_preenable, .postenable = &st_gyro_buffer_postenable, .predisable = &st_gyro_buffer_predisable, }; -- GitLab From 6ee19af415c55f8fee565613a2fa7892030ca9ac Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Wed, 31 Jul 2019 14:48:59 -0700 Subject: [PATCH 1908/7155] iio:magn: preenable/postenable/predisable fixup for ST magn buffer This patch is trying to cleanup for good the buffers operation functions. Let's rename the goto label using operation to perform and not where it fails. Not stable material as not fixing a 'bug' but rather bringing the driver in line with general 'patterns' to allow a subsystem wide cleanup. Signed-off-by: Denis Ciocca Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/st_magn_buffer.c | 30 ++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index 9dba93539a99..658d627dad8e 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -31,40 +31,42 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state) static int st_magn_buffer_postenable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *mdata = iio_priv(indio_dev); + int err; mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_DMA | GFP_KERNEL); - if (mdata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } + if (!mdata->buffer_data) + return -ENOMEM; err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_magn_buffer_postenable_error; + goto st_magn_free_buffer; + + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_magn_buffer_predisable; - return st_sensors_set_enable(indio_dev, true); + return 0; -st_magn_buffer_postenable_error: +st_magn_buffer_predisable: + iio_triggered_buffer_predisable(indio_dev); +st_magn_free_buffer: kfree(mdata->buffer_data); -allocate_memory_error: return err; } static int st_magn_buffer_predisable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *mdata = iio_priv(indio_dev); + int err, err2; err = st_sensors_set_enable(indio_dev, false); - if (err < 0) - goto st_magn_buffer_predisable_error; - err = iio_triggered_buffer_predisable(indio_dev); + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; -st_magn_buffer_predisable_error: kfree(mdata->buffer_data); return err; } -- GitLab From eb1d8ebf2d0a5648a4e13e44d2906f9bb4e28352 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Wed, 31 Jul 2019 14:49:00 -0700 Subject: [PATCH 1909/7155] iio:pressure: preenable/postenable/predisable fixup for ST press buffer This patch is trying to cleanup for good the buffers operation functions. There is no need of using preenable, all can be done into postenable. Let's also use logical sequence of operations as already done in accel driver. Finally also rename the goto label using operation to perform and not where it fails. Not stable material as not fixing a 'bug' but rather bringing the driver in line with general 'patterns' to allow a subsystem wide cleanup. Signed-off-by: Denis Ciocca Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_buffer.c | 38 ++++++++++------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c index f21b630abaa0..77cb2d862f19 100644 --- a/drivers/iio/pressure/st_pressure_buffer.c +++ b/drivers/iio/pressure/st_pressure_buffer.c @@ -29,53 +29,49 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_press_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_press_buffer_postenable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *press_data = iio_priv(indio_dev); + int err; press_data->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_DMA | GFP_KERNEL); - if (press_data->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } + if (!press_data->buffer_data) + return -ENOMEM; err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_press_buffer_postenable_error; + goto st_press_free_buffer; - return err; + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_press_buffer_predisable; + + return 0; -st_press_buffer_postenable_error: +st_press_buffer_predisable: + iio_triggered_buffer_predisable(indio_dev); +st_press_free_buffer: kfree(press_data->buffer_data); -allocate_memory_error: return err; } static int st_press_buffer_predisable(struct iio_dev *indio_dev) { - int err; struct st_sensor_data *press_data = iio_priv(indio_dev); - - err = iio_triggered_buffer_predisable(indio_dev); - if (err < 0) - goto st_press_buffer_predisable_error; + int err, err2; err = st_sensors_set_enable(indio_dev, false); -st_press_buffer_predisable_error: + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; + kfree(press_data->buffer_data); return err; } static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { - .preenable = &st_press_buffer_preenable, .postenable = &st_press_buffer_postenable, .predisable = &st_press_buffer_predisable, }; -- GitLab From d3017f5fbb2dc597b8cc9b59144c63d9a1396392 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Mon, 29 Jul 2019 09:43:01 +0800 Subject: [PATCH 1910/7155] iio: light: si1145: Use device-managed APIs Use device-managed APIs to simplify the code. The remove functions are redundant now and can be deleted. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/light/si1145.c | 42 +++++--------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 6579d2418814..982bba0c54e7 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1261,7 +1261,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) return ret; } - ret = iio_trigger_register(trig); + ret = devm_iio_trigger_register(&client->dev, trig); if (ret) return ret; @@ -1271,16 +1271,6 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) return 0; } -static void si1145_remove_trigger(struct iio_dev *indio_dev) -{ - struct si1145_data *data = iio_priv(indio_dev); - - if (data->trig) { - iio_trigger_unregister(data->trig); - data->trig = NULL; - } -} - static int si1145_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1332,7 +1322,8 @@ static int si1145_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, NULL, si1145_trigger_handler, &si1145_buffer_setup_ops); if (ret < 0) return ret; @@ -1340,23 +1331,12 @@ static int si1145_probe(struct i2c_client *client, if (client->irq) { ret = si1145_probe_trigger(indio_dev); if (ret < 0) - goto error_free_buffer; + return ret; } else { dev_info(&client->dev, "no irq, using polling\n"); } - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_free_trigger; - - return 0; - -error_free_trigger: - si1145_remove_trigger(indio_dev); -error_free_buffer: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id si1145_ids[] = { @@ -1371,23 +1351,11 @@ static const struct i2c_device_id si1145_ids[] = { }; MODULE_DEVICE_TABLE(i2c, si1145_ids); -static int si1145_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - si1145_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; -} - static struct i2c_driver si1145_driver = { .driver = { .name = "si1145", }, .probe = si1145_probe, - .remove = si1145_remove, .id_table = si1145_ids, }; -- GitLab From 7c279229f980e5423c946fd692860b4071e0c708 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:19 -0700 Subject: [PATCH 1911/7155] iio: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: linux-iio@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606_par.c | 4 +--- drivers/iio/adc/at91_adc.c | 4 +--- drivers/iio/adc/axp288_adc.c | 4 +--- drivers/iio/adc/bcm_iproc_adc.c | 7 ++----- drivers/iio/adc/da9150-gpadc.c | 4 +--- drivers/iio/adc/envelope-detector.c | 5 +---- drivers/iio/adc/exynos_adc.c | 4 +--- drivers/iio/adc/fsl-imx25-gcq.c | 1 - drivers/iio/adc/imx7d_adc.c | 4 +--- drivers/iio/adc/lpc32xx_adc.c | 4 +--- drivers/iio/adc/npcm_adc.c | 1 - drivers/iio/adc/rockchip_saradc.c | 4 +--- drivers/iio/adc/sc27xx_adc.c | 4 +--- drivers/iio/adc/spear_adc.c | 1 - drivers/iio/adc/stm32-adc-core.c | 1 - drivers/iio/adc/stm32-adc.c | 4 +--- drivers/iio/adc/stm32-dfsdm-adc.c | 5 +---- drivers/iio/adc/sun4i-gpadc-iio.c | 4 +--- drivers/iio/adc/twl6030-gpadc.c | 4 +--- drivers/iio/adc/vf610_adc.c | 4 +--- 20 files changed, 17 insertions(+), 56 deletions(-) diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c index 1b08028facde..f732b3ac7878 100644 --- a/drivers/iio/adc/ad7606_par.c +++ b/drivers/iio/adc/ad7606_par.c @@ -53,10 +53,8 @@ static int ad7606_par_probe(struct platform_device *pdev) int irq; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 32f1c4a33b20..abe99856c823 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -1179,10 +1179,8 @@ static int at91_adc_probe(struct platform_device *pdev) idev->info = &at91_adc_info; st->irq = platform_get_irq(pdev, 0); - if (st->irq < 0) { - dev_err(&pdev->dev, "No IRQ ID is designated\n"); + if (st->irq < 0) return -ENODEV; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 31d51bcc5f2c..adc9cf7a075d 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -225,10 +225,8 @@ static int axp288_adc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (info->irq < 0) return info->irq; - } platform_set_drvdata(pdev, indio_dev); info->regmap = axp20x->regmap; /* diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index c46c0aa15376..646ebdc0a8b4 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -540,11 +540,8 @@ static int iproc_adc_probe(struct platform_device *pdev) } adc_priv->irqno = platform_get_irq(pdev, 0); - if (adc_priv->irqno <= 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - ret = -ENODEV; - return ret; - } + if (adc_priv->irqno <= 0) + return -ENODEV; ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, IPROC_ADC_AUXIN_SCAN_ENA, 0); diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c index 354433996101..ae8bcc32f63d 100644 --- a/drivers/iio/adc/da9150-gpadc.c +++ b/drivers/iio/adc/da9150-gpadc.c @@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev) init_completion(&gpadc->complete); irq = platform_get_irq_byname(pdev, "GPADC"); - if (irq < 0) { - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, IRQF_ONESHOT, "GPADC", gpadc); diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index 2f2b563c1162..28f3d6758eb5 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -357,11 +357,8 @@ static int envelope_detector_probe(struct platform_device *pdev) } env->comp_irq = platform_get_irq_byname(pdev, "comp"); - if (env->comp_irq < 0) { - if (env->comp_irq != -EPROBE_DEFER) - dev_err(dev, "failed to get compare interrupt\n"); + if (env->comp_irq < 0) return env->comp_irq; - } ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, 0, "envelope-detector", env); diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index d4c3ece21679..42a3ced11fbd 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -805,10 +805,8 @@ static int exynos_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } info->irq = irq; irq = platform_get_irq(pdev, 1); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index df19ecae52f7..fa71489195c6 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -340,7 +340,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) priv->irq = platform_get_irq(pdev, 0); if (priv->irq <= 0) { - dev_err(dev, "Failed to get IRQ\n"); ret = priv->irq; if (!ret) ret = -ENXIO; diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 26a7bbe4d534..2a2fbf788e95 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "No irq resource?\n"); + if (irq < 0) return irq; - } info->clk = devm_clk_get(dev, "adc"); if (IS_ERR(info->clk)) { diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index a6ee1c3a9064..b896f7ff4572 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -172,10 +172,8 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "failed getting interrupt resource\n"); + if (irq <= 0) return -ENXIO; - } retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, LPC32XXAD_NAME, st); diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index 193b3b81de4d..910f3585fa54 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -225,7 +225,6 @@ static int npcm_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto err_disable_clk; } diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index dd8299831e09..582ba047c4a6 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) init_completion(&info->completion); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, 0, dev_name(&pdev->dev), info); diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index d7ca002cbb17..c2203a46f0d8 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -529,10 +529,8 @@ static int sc27xx_adc_probe(struct platform_device *pdev) } sc27xx_data->irq = platform_get_irq(pdev, 0); - if (sc27xx_data->irq < 0) { - dev_err(dev, "failed to get ADC irq number\n"); + if (sc27xx_data->irq < 0) return sc27xx_data->irq; - } ret = of_hwspin_lock_get_id(np, 0); if (ret < 0) { diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index a33d0a4cc088..592b97c464da 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -301,7 +301,6 @@ static int spear_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto errout2; } diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 4299cef69385..9b85fefc0a96 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -374,7 +374,6 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, */ if (i && priv->irq[i] == -ENXIO) continue; - dev_err(&pdev->dev, "failed to get irq\n"); return priv->irq[i]; } diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 205e1699f954..6a7dd08b1e0b 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1919,10 +1919,8 @@ static int stm32_adc_probe(struct platform_device *pdev) } adc->irq = platform_get_irq(pdev, 0); - if (adc->irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (adc->irq < 0) return adc->irq; - } ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, 0, pdev->name, adc); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index ee1e0569d0e1..e493242c266e 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1601,11 +1601,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) * So IRQ associated to filter instance 0 is dedicated to the Filter 0. */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, 0, pdev->name, adc); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index f13c6248a662..176e1cb4abb1 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -460,10 +460,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, atomic_set(atomic, 1); ret = platform_get_irq_byname(pdev, name); - if (ret < 0) { - dev_err(&pdev->dev, "no %s interrupt registered\n", name); + if (ret < 0) return ret; - } ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); if (ret < 0) { diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 2fa6ec83bb13..f24148bd15de 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -905,10 +905,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, twl6030_gpadc_irq_handler, diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 41d3621c4787..98b30475bbc6 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -821,10 +821,8 @@ static int vf610_adc_probe(struct platform_device *pdev) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(info->dev, irq, vf610_adc_isr, 0, -- GitLab From fe4e6e0368885f77fef81adff486f4f7116e9e8f Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sat, 3 Aug 2019 18:48:42 +0530 Subject: [PATCH 1912/7155] staging: rtl8188eu: core: add spaces around '-', '+', '>>','<<' and '*' in rtw_efuse.c Add spaces around '-', '+', '>>','<<' and '*' to improve readability and follow kernel coding style. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803131839.GA14077@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 128 ++++++++++----------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 533ca1ddffb0..02c476f45b33 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -108,7 +108,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 1. Read the first byte to check if efuse is empty!!! */ /* */ /* */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF) { efuse_utilized++; eFuse_Addr++; @@ -124,10 +124,10 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* Check PG header for section num. */ if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ u1temp = (rtemp8 & 0xE0) >> 5; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if ((rtemp8 & 0x0F) == 0x0F) { eFuse_Addr++; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) eFuse_Addr++; @@ -147,13 +147,13 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { /* Check word enable condition in the section */ if (!(wren & 0x01)) { - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] = (rtemp8 & 0xff); if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) break; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); @@ -165,7 +165,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) } } /* Read next PG header */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { efuse_utilized++; @@ -178,8 +178,8 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* */ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); + efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); } } @@ -187,7 +187,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 4. Copy from Efuse map to output pointer memory!!! */ /* */ for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset+i]; + pbuf[i] = efuseTbl[_offset + i]; /* */ /* 5. Calculate Efuse utilization. */ @@ -218,16 +218,16 @@ static void efuse_read_phymap_from_txpktbuf( u8 *pos = content; if (bcnhead < 0) /* if not valid */ - bcnhead = usb_read8(adapter, REG_TDECTRL+1); + bcnhead = usb_read8(adapter, REG_TDECTRL + 1); DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ + dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */ while (1) { - usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); + usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i); usb_write8(adapter, REG_TXPKTBUF_DBG, 0); start = jiffies; @@ -246,34 +246,34 @@ static void efuse_read_phymap_from_txpktbuf( u16 aaa; lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); - lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); + lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); aaabak = le16_to_cpup((__le16 *)lenc); lenbak = le16_to_cpu(*((__le16 *)lenc)); aaa = le16_to_cpup((__le16 *)&lo32); len = le16_to_cpu(*((__le16 *)&lo32)); - limit = min_t(u16, len-2, limit); + limit = min_t(u16, len - 2, limit); DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); - memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); - count += (limit >= count+2) ? 2 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); + count += (limit >= count + 2) ? 2 : limit - count; + pos = content + count; } else { - memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit > count && len-2 > count) { - memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + if (limit > count && len - 2 > count) { + memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit <= count || len-2 <= count) + if (limit <= count || len - 2 <= count) break; i++; } @@ -288,7 +288,7 @@ static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset u8 physical_map[512]; u16 size = 512; - usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); memset(physical_map, 0xFF, 512); usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); status = iol_execute(padapter, CMD_READ_EFUSE_MAP); @@ -323,7 +323,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[1]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1]); if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) badworden &= (~BIT(0)); } @@ -333,7 +333,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[3]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3]); if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) badworden &= (~BIT(1)); } @@ -343,7 +343,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[5]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5]); if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) badworden &= (~BIT(2)); } @@ -353,7 +353,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[7]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7]); if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) badworden &= (~BIT(3)); } @@ -371,7 +371,7 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) while (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && AVAILABLE_EFUSE_ADDR(efuse_addr)) { if (efuse_data != 0xFF) { - if ((efuse_data&0x1F) == 0x0F) { /* extended header */ + if ((efuse_data & 0x1F) == 0x0F) { /* extended header */ hoffset = efuse_data; efuse_addr++; efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); @@ -383,12 +383,12 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) hworden = efuse_data & 0x0F; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); /* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; } else { break; } @@ -439,15 +439,15 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) continue; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); bDataEmpty = true; if (hoffset == offset) { - for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { - if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { + for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { + if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) bDataEmpty = false; @@ -456,11 +456,11 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (!bDataEmpty) { ReadState = PG_STATE_DATA; } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else { @@ -469,7 +469,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) } else if (ReadState & PG_STATE_DATA) { /* Data section Read ------------- */ efuse_WordEnableDataRead(hworden, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } @@ -491,7 +491,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { /* check if data exist */ - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata); if (badworden != 0xf) { /* write fail */ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); @@ -501,10 +501,10 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st else efuse_addr = Efuse_GetCurrentSize(pAdapter); } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } *pAddr = efuse_addr; return true; @@ -601,7 +601,7 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse } else { struct pgpkt fixPkt; - fixPkt.offset = (tmp_header>>4) & 0x0F; + fixPkt.offset = (tmp_header >> 4) & 0x0F; fixPkt.word_en = tmp_header & 0x0F; fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) @@ -619,7 +619,7 @@ static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u u32 PgWriteSuccess = 0; badworden = 0x0f; - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data); if (badworden == 0x0F) { /* write ok */ return true; @@ -681,8 +681,8 @@ static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, bool ret = false; u8 i, efuse_data; - for (i = 0; i < (word_cnts*2); i++) { - if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) + for (i = 0; i < (word_cnts * 2); i++) { + if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data) && (efuse_data != 0xFF)) ret = true; } return ret; @@ -721,7 +721,7 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } } else { cur_header = efuse_data; - curPkt.offset = (cur_header>>4) & 0x0F; + curPkt.offset = (cur_header >> 4) & 0x0F; curPkt.word_en = cur_header & 0x0F; } @@ -729,10 +729,10 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u /* if same header is found but no data followed */ /* write some part of data followed by the header. */ if ((curPkt.offset == pTargetPkt->offset) && - (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && + (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1)) && wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { /* Here to write partial data */ - badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data); if (badworden != 0x0F) { u32 PgWriteSuccess = 0; /* if write fail on some words, write these bad words again */ @@ -746,13 +746,13 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } /* partial write ok, update the target packet for later use */ for (i = 0; i < 4; i++) { - if ((matched_wden & (0x1<word_en |= (0x1<word_en |= (0x1 << i); /* disable the word */ } pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); } /* read from next header */ - startAddr = startAddr + (curPkt.word_cnts*2) + 1; + startAddr = startAddr + (curPkt.word_cnts * 2) + 1; } else { /* not used header, 0xff */ *pAddr = startAddr; @@ -765,7 +765,7 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) { - memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); + memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8); pTargetPkt->offset = offset; pTargetPkt->word_en = word_en; efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); @@ -815,13 +815,13 @@ u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) | - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) | + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */ - while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) { *data = usb_read8(pAdapter, EFUSE_CTRL); @@ -838,15 +838,15 @@ u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) | - (u8)((addr>>8) & 0x03)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | + (u8)((addr >> 8) & 0x03)); usb_write8(pAdapter, EFUSE_CTRL, data);/* data */ - usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */ - while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) -- GitLab From 783f9a6a2d2c2b1e5c5bc51f6407e66473385b3a Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:00:54 +0530 Subject: [PATCH 1913/7155] staging: rtl8723bs: core: correct spelling mistake in rtw_ap.c Correct spelling mistake in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803183051.GA23151@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 7bd5c61b055c..78b5782fb675 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -94,7 +94,7 @@ static void update_BCNTIM(struct adapter *padapter) } else { tim_ielen = 0; - /* calucate head_len */ + /* calculate head_len */ offset = _FIXED_IE_LENGTH_; /* get ssid_ie len */ @@ -143,7 +143,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = tim_ielen; *dst_ie++ = 0;/* DTIM count */ - *dst_ie++ = 1;/* DTIM peroid */ + *dst_ie++ = 1;/* DTIM period */ if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */ *dst_ie++ = BIT(0);/* bitmap ctrl */ @@ -292,7 +292,7 @@ void expire_timeout_chk(struct adapter *padapter) if (psta->state & WIFI_SLEEP_STATE) { if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* to check if alive by another methods if staion is at ps mode. */ + /* to check if alive by another methods if station is at ps mode. */ psta->expire_to = pstapriv->expire_to; psta->state |= WIFI_STA_ALIVE_CHK_STATE; @@ -916,7 +916,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) UpdateBrateTbl(padapter, pnetwork->SupportedRates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); - /* udpate capability after cur_wireless_mode updated */ + /* update capability after cur_wireless_mode updated */ update_capinfo( padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork) @@ -1015,7 +1015,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->Ssid.SsidLength = ie_len; } - /* chnnel */ + /* channel */ channel = 0; pbss_network->Configuration.Length = 0; p = rtw_get_ie( @@ -1827,7 +1827,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) /* op_mode -Set to 0 (HT pure) under the followign conditions +Set to 0 (HT pure) under the following conditions - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - all STAs in the BSS are 20 MHz HT in 20 MHz BSS Set to 1 (HT non-member protection) if there may be non-HT STAs -- GitLab From 67ca96bbd0315cc804668d42568934b88fe1d968 Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:17:54 +0530 Subject: [PATCH 1914/7155] staging: rtl8723bs: core: Remove Unnecessary parentheses Remove Unnecessary parentheses around padapter->mlmepriv, pmlmeext->mlmext_info and pmlmeinfo->network in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803184750.GA23507@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 78b5782fb675..45a745696af6 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -17,7 +17,7 @@ extern unsigned char WFD_OUI[]; void init_mlme_ap_info(struct adapter *padapter) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; @@ -34,9 +34,9 @@ void init_mlme_ap_info(struct adapter *padapter) void free_mlme_ap_info(struct adapter *padapter) { struct sta_info *psta = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; /* stop_ap_mode(padapter); */ @@ -58,9 +58,9 @@ void free_mlme_ap_info(struct adapter *padapter) static void update_BCNTIM(struct adapter *padapter) { struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; unsigned char *pie = pnetwork_mlmeext->IEs; /* DBG_871X("%s\n", __func__); */ -- GitLab From d8ba499d53d92fbee87638f3313b2281d04300bd Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:55:55 +0530 Subject: [PATCH 1915/7155] staging: rtl8723bs: core: add spaces around '-', '+', '&','|' and '?' Add spaces around '-', '+', '&','|' and '?' to improve readability and follow kernel coding style in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803192551.GA24041@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 88 ++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 45a745696af6..02f5478845b4 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -83,7 +83,7 @@ static void update_BCNTIM(struct adapter *padapter) if (p != NULL && tim_ielen > 0) { tim_ielen += 2; - premainder_ie = p+tim_ielen; + premainder_ie = p + tim_ielen; tim_ie_offset = (sint)(p - pie); @@ -105,7 +105,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* get supported rates len */ p = rtw_get_ie( @@ -114,7 +114,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* DS Parameter Set IE, len =3 */ offset += 3; @@ -135,7 +135,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = _TIM_IE_; - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe)) + if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) tim_ielen = 5; else tim_ielen = 4; @@ -145,7 +145,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = 0;/* DTIM count */ *dst_ie++ = 1;/* DTIM period */ - if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */ + if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ *dst_ie++ = BIT(0);/* bitmap ctrl */ else *dst_ie++ = 0; @@ -153,7 +153,7 @@ static void update_BCNTIM(struct adapter *padapter) if (tim_ielen == 4) { __le16 pvb; - if (pstapriv->tim_bitmap&0xff00) + if (pstapriv->tim_bitmap & 0xff00) pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); else pvb = tim_bitmap_le; @@ -188,8 +188,8 @@ u8 chk_sta_is_alive(struct sta_info *psta) /* STA_RX_PKTS_ARG(psta) */ , STA_RX_PKTS_DIFF_ARG(psta) , psta->expire_to - , psta->state&WIFI_SLEEP_STATE?"PS, ":"" - , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":"" + , psta->state & WIFI_SLEEP_STATE ? "PS, " : "" + , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : "" , psta->sleepq_len ); #endif @@ -325,10 +325,10 @@ void expire_timeout_chk(struct adapter *padapter) updated = ap_free_sta(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); } else { /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ - if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) + if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && padapter->xmitpriv.free_xmitframe_cnt < (( - NR_XMITFRAME/pstapriv->asoc_list_cnt - )/2) + NR_XMITFRAME / pstapriv->asoc_list_cnt + ) / 2) ) { DBG_871X( "%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", @@ -586,8 +586,8 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; phtpriv_sta->rx_ampdu_min_spacing = ( - phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY - )>>2; + phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY + ) >> 2; /* bwmode */ if (( @@ -782,8 +782,8 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) /* check if there is wps ie, */ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ - if (!rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, - pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL)) + if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, + pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ @@ -861,7 +861,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) (pnetwork->IELength - sizeof(struct ndis_802_11_fix_ie)) ); if (p && ie_len) { - pht_info = (struct HT_info_element *)(p+2); + pht_info = (struct HT_info_element *)(p + 2); if (cur_channel > 14) { if ((pregpriv->bw_mode & 0xf0) > 0) @@ -1037,7 +1037,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) (pbss_network->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) { - memcpy(supportRate, p+2, ie_len); + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } @@ -1049,7 +1049,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->IELength - _BEACON_IE_OFFSET_ ); if (p != NULL) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -1088,7 +1088,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { if (rtw_parse_wpa2_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1115,10 +1115,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && (!memcmp(p+2, OUI1, 4))) { + if ((p) && (!memcmp(p + 2, OUI1, 4))) { if (rtw_parse_wpa_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1151,10 +1151,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { + if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; - *(p+8) |= BIT(7);/* QoS Info, support U-APSD */ + *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */ /* disable all ACM bits since the WMM admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ @@ -1180,7 +1180,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { u8 rf_type = 0; u8 max_rx_ampdu_factor = 0; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); + struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; @@ -1205,14 +1205,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R)); pht_cap->ampdu_params_info &= ~( - IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY + IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY ); if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); } else { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); } rtw_hal_get_def_var( @@ -1230,7 +1230,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->supp_mcs_set[1] = 0x0; } - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); + memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); } /* parsing HT_INFO_IE */ @@ -1265,8 +1265,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pmlmepriv->htpriv.ht_option = false; - if ((psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || - (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP)) { + if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || + (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { /* todo: */ /* ht_cap = false; */ } @@ -1341,7 +1341,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) MAC_ARG(addr) ); - if ((NUM_ACL-1) < pacl_list->num) + if ((NUM_ACL - 1) < pacl_list->num) return (-1); spin_lock_bh(&(pacl_node_q->lock)); @@ -1454,7 +1454,7 @@ u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta) psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); if (psetstakey_para == NULL) { - kfree((u8 *) ph2c); + kfree((u8 *)ph2c); res = _FAIL; goto exit; } @@ -1604,10 +1604,10 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter) struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p; if (pmlmepriv->num_sta_non_erp == 1) - pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION; + pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; else pIE->data[0] &= ~( - RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION + RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION ); if (pmlmepriv->num_sta_no_short_preamble > 0) @@ -1662,8 +1662,8 @@ static void update_bcn_wps_ie(struct adapter *padapter) DBG_871X("%s\n", __func__); pwps_ie = rtw_get_wps_ie( - ie+_FIXED_IE_LENGTH_, - ielen-_FIXED_IE_LENGTH_, + ie + _FIXED_IE_LENGTH_, + ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen ); @@ -1675,7 +1675,7 @@ static void update_bcn_wps_ie(struct adapter *padapter) if (pwps_ie_src == NULL) return; - wps_offset = (uint)(pwps_ie-ie); + wps_offset = (uint)(pwps_ie - ie); premainder_ie = pwps_ie + wps_ielen; @@ -1688,22 +1688,22 @@ static void update_bcn_wps_ie(struct adapter *padapter) } wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ - if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { - memcpy(pwps_ie, pwps_ie_src, wps_ielen+2); + if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { + memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); pwps_ie += (wps_ielen+2); if (pbackup_remainder_ie) memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); /* update IELength */ - pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen; + pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen; } kfree(pbackup_remainder_ie); /* deal with the case without set_tx_beacon_cmd() in update_beacon() */ #if defined(CONFIG_INTERRUPT_BASED_TXBCN) - if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { u8 sr = 0; rtw_get_wps_attr_content( @@ -2196,7 +2196,7 @@ void rtw_sta_flush(struct adapter *padapter) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return; spin_lock_bh(&pstapriv->asoc_list_lock); @@ -2230,7 +2230,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); /* update wmm cap. */ - if (WLAN_STA_WME&flags) + if (WLAN_STA_WME & flags) psta->qos_option = 1; else psta->qos_option = 0; @@ -2239,7 +2239,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) psta->qos_option = 0; /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { + if (WLAN_STA_HT & flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; } else { -- GitLab From 36d042bd6865ada4fc5b14e2cb5fd325eeb248db Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 4 Aug 2019 08:18:32 +0530 Subject: [PATCH 1916/7155] staging: rtl8192e: Make use kmemdup As kmemdup API does kmalloc + memcpy . We can make use of it instead of calling kmalloc and memcpy independetly. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190804024832.GA14352@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 24 +++++++---------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index e29e8d6f4611..f2f7529e7c80 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -1382,15 +1382,10 @@ rtllib_association_req(struct rtllib_network *beacon, ieee->assocreq_ies = NULL; ies = &(hdr->info_element[0].id); ieee->assocreq_ies_len = (skb->data + skb->len) - ies; - ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC); - if (ieee->assocreq_ies) - memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocreq_ies\n", - __func__); + ieee->assocreq_ies = kmemdup(ies, ieee->assocreq_ies_len, GFP_ATOMIC); + if (!ieee->assocreq_ies) ieee->assocreq_ies_len = 0; - } + return skb; } @@ -2259,17 +2254,12 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, ieee->assocresp_ies = NULL; ies = &(assoc_resp->info_element[0].id); ieee->assocresp_ies_len = (skb->data + skb->len) - ies; - ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len, + ieee->assocresp_ies = kmemdup(ies, + ieee->assocresp_ies_len, GFP_ATOMIC); - if (ieee->assocresp_ies) - memcpy(ieee->assocresp_ies, ies, - ieee->assocresp_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocresp_ies\n", - __func__); + if (!ieee->assocresp_ies) ieee->assocresp_ies_len = 0; - } + rtllib_associate_complete(ieee); } else { /* aid could not been allocated */ -- GitLab From 18bd7b5ef3a313a9af1314508bca1ed982c05f75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:49:23 +0900 Subject: [PATCH 1917/7155] ASoC: soc-pcm: remove soc_rtdcom_ack() No ALSA SoC driver has .ack at component->driver->ops. We can revive it if some-driver want to use it, but let's remove it so far to avoid maintaining complex code Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87muh15roz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ce7297c37537..bf04b69d6878 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2873,26 +2873,6 @@ static void soc_pcm_private_free(struct snd_pcm *pcm) } } -static int soc_rtdcom_ack(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->ack) - continue; - - /* FIXME. it returns 1st ask now */ - return component->driver->ops->ack(substream); - } - - return -EINVAL; -} - static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel, unsigned long pos, void __user *buf, unsigned long bytes) @@ -3129,8 +3109,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (!ops) continue; - if (ops->ack) - rtd->ops.ack = soc_rtdcom_ack; if (ops->copy_user) rtd->ops.copy_user = soc_rtdcom_copy_user; if (ops->copy_kernel) -- GitLab From 4efbb20971af527990f3c51056d142e3f7dc6b4a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:49:29 +0900 Subject: [PATCH 1918/7155] ASoC: soc-pcm: remove soc_rtdcom_copy_kernel() No ALSA SoC driver has .copy_kernel at component->driver->ops. We can revive it if some-driver want to use it, but let's remove it so far to avoid maintaining complex code Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfwl5rot.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index bf04b69d6878..e85548244b55 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2896,28 +2896,6 @@ static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel return -EINVAL; } -static int soc_rtdcom_copy_kernel(struct snd_pcm_substream *substream, int channel, - unsigned long pos, void *buf, unsigned long bytes) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->copy_kernel) - continue; - - /* FIXME. it returns 1st copy now */ - return component->driver->ops->copy_kernel(substream, channel, - pos, buf, bytes); - } - - return -EINVAL; -} - static int soc_rtdcom_fill_silence(struct snd_pcm_substream *substream, int channel, unsigned long pos, unsigned long bytes) { @@ -3111,8 +3089,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (ops->copy_user) rtd->ops.copy_user = soc_rtdcom_copy_user; - if (ops->copy_kernel) - rtd->ops.copy_kernel = soc_rtdcom_copy_kernel; if (ops->fill_silence) rtd->ops.fill_silence = soc_rtdcom_fill_silence; if (ops->page) -- GitLab From 57cb28856ed8db11faa7cc1c751eb6ad00e7c3f0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:49:43 +0900 Subject: [PATCH 1919/7155] ASoC: soc-pcm: remove soc_fill_silence() No ALSA SoC driver has .fill_silence at component->driver->ops. We can revive it if some-driver want to use it, but let's remove it so far to avoid maintaining complex code Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k1c55rof.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e85548244b55..1e6c4e226933 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2896,28 +2896,6 @@ static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel return -EINVAL; } -static int soc_rtdcom_fill_silence(struct snd_pcm_substream *substream, int channel, - unsigned long pos, unsigned long bytes) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->fill_silence) - continue; - - /* FIXME. it returns 1st silence now */ - return component->driver->ops->fill_silence(substream, channel, - pos, bytes); - } - - return -EINVAL; -} - static struct page *soc_rtdcom_page(struct snd_pcm_substream *substream, unsigned long offset) { @@ -3089,8 +3067,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (ops->copy_user) rtd->ops.copy_user = soc_rtdcom_copy_user; - if (ops->fill_silence) - rtd->ops.fill_silence = soc_rtdcom_fill_silence; if (ops->page) rtd->ops.page = soc_rtdcom_page; if (ops->mmap) -- GitLab From 4ff1fef10f353b928bcc9d56d31fda53f2c43191 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:49:48 +0900 Subject: [PATCH 1920/7155] ASoC: add soc-component.c ALSA SoC has many snd_soc_component_xxx(), but these are randomly located in many files. Because of it, code is difficult to read. This patch creates new soc-component.c, and moves existing snd_soc_component_xxx() into it. But not yet fully. We need more cleanup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87imrp5roa.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 328 ++++++++++++++++++++++++++++++++++ include/sound/soc.h | 306 +------------------------------ sound/soc/Makefile | 2 +- sound/soc/soc-component.c | 269 ++++++++++++++++++++++++++++ sound/soc/soc-core.c | 44 ----- sound/soc/soc-jack.c | 18 -- sound/soc/soc-utils.c | 199 --------------------- 7 files changed, 599 insertions(+), 567 deletions(-) create mode 100644 include/sound/soc-component.h create mode 100644 sound/soc/soc-component.c diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h new file mode 100644 index 000000000000..a97d499e5d7a --- /dev/null +++ b/include/sound/soc-component.h @@ -0,0 +1,328 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-component.h + * + * Copyright (c) 2019 Kuninori Morimoto + * + * 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. + */ +#ifndef __SOC_COMPONENT_H +#define __SOC_COMPONENT_H + +#include + +/* + * Component probe and remove ordering levels for components with runtime + * dependencies. + */ +#define SND_SOC_COMP_ORDER_FIRST -2 +#define SND_SOC_COMP_ORDER_EARLY -1 +#define SND_SOC_COMP_ORDER_NORMAL 0 +#define SND_SOC_COMP_ORDER_LATE 1 +#define SND_SOC_COMP_ORDER_LAST 2 + +#define for_each_comp_order(order) \ + for (order = SND_SOC_COMP_ORDER_FIRST; \ + order <= SND_SOC_COMP_ORDER_LAST; \ + order++) + +/* component interface */ +struct snd_soc_component_driver { + const char *name; + + /* Default control and setup, added after probe() is run */ + const struct snd_kcontrol_new *controls; + unsigned int num_controls; + const struct snd_soc_dapm_widget *dapm_widgets; + unsigned int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + unsigned int num_dapm_routes; + + int (*probe)(struct snd_soc_component *component); + void (*remove)(struct snd_soc_component *component); + int (*suspend)(struct snd_soc_component *component); + int (*resume)(struct snd_soc_component *component); + + unsigned int (*read)(struct snd_soc_component *component, + unsigned int reg); + int (*write)(struct snd_soc_component *component, + unsigned int reg, unsigned int val); + + /* pcm creation and destruction */ + int (*pcm_new)(struct snd_soc_pcm_runtime *rtd); + void (*pcm_free)(struct snd_pcm *pcm); + + /* component wide operations */ + int (*set_sysclk)(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir); + int (*set_pll)(struct snd_soc_component *component, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out); + int (*set_jack)(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data); + + /* DT */ + int (*of_xlate_dai_name)(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name); + int (*of_xlate_dai_id)(struct snd_soc_component *comment, + struct device_node *endpoint); + void (*seq_notifier)(struct snd_soc_component *component, + enum snd_soc_dapm_type type, int subseq); + int (*stream_event)(struct snd_soc_component *component, int event); + int (*set_bias_level)(struct snd_soc_component *component, + enum snd_soc_bias_level level); + + const struct snd_pcm_ops *ops; + const struct snd_compr_ops *compr_ops; + + /* probe ordering - for components with runtime dependencies */ + int probe_order; + int remove_order; + + /* + * signal if the module handling the component should not be removed + * if a pcm is open. Setting this would prevent the module + * refcount being incremented in probe() but allow it be incremented + * when a pcm is opened and decremented when it is closed. + */ + unsigned int module_get_upon_open:1; + + /* bits */ + unsigned int idle_bias_on:1; + unsigned int suspend_bias_off:1; + unsigned int use_pmdown_time:1; /* care pmdown_time at stop */ + unsigned int endianness:1; + unsigned int non_legacy_dai_naming:1; + + /* this component uses topology and ignore machine driver FEs */ + const char *ignore_machine; + const char *topology_name_prefix; + int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */ + int be_pcm_base; /* base device ID for all BE PCMs */ +}; + +struct snd_soc_component { + const char *name; + int id; + const char *name_prefix; + struct device *dev; + struct snd_soc_card *card; + + unsigned int active; + + unsigned int suspended:1; /* is in suspend PM state */ + + struct list_head list; + struct list_head card_aux_list; /* for auxiliary bound components */ + struct list_head card_list; + + const struct snd_soc_component_driver *driver; + + struct list_head dai_list; + int num_dai; + + struct regmap *regmap; + int val_bytes; + + struct mutex io_mutex; + + /* attached dynamic objects */ + struct list_head dobj_list; + + /* + * DO NOT use any of the fields below in drivers, they are temporary and + * are going to be removed again soon. If you use them in driver code + * the driver will be marked as BROKEN when these fields are removed. + */ + + /* Don't use these, use snd_soc_component_get_dapm() */ + struct snd_soc_dapm_context dapm; + + /* machine specific init */ + int (*init)(struct snd_soc_component *component); + +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; + const char *debugfs_prefix; +#endif +}; + +#define for_each_component_dais(component, dai)\ + list_for_each_entry(dai, &(component)->dai_list, list) +#define for_each_component_dais_safe(component, dai, _dai)\ + list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) + +/** + * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is + * embedded in + * @dapm: The DAPM context to cast to the component + * + * This function must only be used on DAPM contexts that are known to be part of + * a component (e.g. in a component driver). Otherwise the behavior is + * undefined. + */ +static inline struct snd_soc_component *snd_soc_dapm_to_component( + struct snd_soc_dapm_context *dapm) +{ + return container_of(dapm, struct snd_soc_component, dapm); +} + +/** + * snd_soc_component_get_dapm() - Returns the DAPM context associated with a + * component + * @component: The component for which to get the DAPM context + */ +static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( + struct snd_soc_component *component) +{ + return &component->dapm; +} + +/** + * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level + * @component: The COMPONENT for which to initialize the DAPM bias level + * @level: The DAPM level to initialize to + * + * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level() + */ +static inline void +snd_soc_component_init_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + snd_soc_dapm_init_bias_level( + snd_soc_component_get_dapm(component), level); +} + +/** + * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level + * @component: The COMPONENT for which to get the DAPM bias level + * + * Returns: The current DAPM bias level of the COMPONENT. + */ +static inline enum snd_soc_bias_level +snd_soc_component_get_bias_level(struct snd_soc_component *component) +{ + return snd_soc_dapm_get_bias_level( + snd_soc_component_get_dapm(component)); +} + +/** + * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level + * @component: The COMPONENT for which to set the level + * @level: The level to set to + * + * Forces the COMPONENT bias level to a specific state. See + * snd_soc_dapm_force_bias_level(). + */ +static inline int +snd_soc_component_force_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + return snd_soc_dapm_force_bias_level( + snd_soc_component_get_dapm(component), + level); +} + +/** + * snd_soc_dapm_kcontrol_component() - Returns the component associated to a + * kcontrol + * @kcontrol: The kcontrol + * + * This function must only be used on DAPM contexts that are known to be part of + * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined + */ +static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( + struct snd_kcontrol *kcontrol) +{ + return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); +} + +/** + * snd_soc_component_cache_sync() - Sync the register cache with the hardware + * @component: COMPONENT to sync + * + * Note: This function will call regcache_sync() + */ +static inline int snd_soc_component_cache_sync( + struct snd_soc_component *component) +{ + return regcache_sync(component->regmap); +} + +/* component IO */ +int snd_soc_component_read(struct snd_soc_component *component, + unsigned int reg, unsigned int *val); +unsigned int snd_soc_component_read32(struct snd_soc_component *component, + unsigned int reg); +int snd_soc_component_write(struct snd_soc_component *component, + unsigned int reg, unsigned int val); +int snd_soc_component_update_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int val); +int snd_soc_component_update_bits_async(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int val); +void snd_soc_component_async_complete(struct snd_soc_component *component); +int snd_soc_component_test_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int value); + +/* component wide operations */ +int snd_soc_component_set_sysclk(struct snd_soc_component *component, + int clk_id, int source, + unsigned int freq, int dir); +int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, + int source, unsigned int freq_in, + unsigned int freq_out); +int snd_soc_component_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data); + +#ifdef CONFIG_REGMAP +void snd_soc_component_init_regmap(struct snd_soc_component *component, + struct regmap *regmap); +void snd_soc_component_exit_regmap(struct snd_soc_component *component); +#endif + +static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, + void *data) +{ + dev_set_drvdata(c->dev, data); +} + +static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) +{ + return dev_get_drvdata(c->dev); +} + +static inline bool snd_soc_component_is_active( + struct snd_soc_component *component) +{ + return component->active != 0; +} + +/* component pin */ +int snd_soc_component_enable_pin(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_disable_pin(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_nc_pin(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_get_pin_status(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_force_enable_pin(struct snd_soc_component *component, + const char *pin); +int snd_soc_component_force_enable_pin_unlocked( + struct snd_soc_component *component, + const char *pin); + +#endif /* __SOC_COMPONENT_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index f0797792dd8d..6ac6481b4882 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -362,21 +362,6 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -/* - * Component probe and remove ordering levels for components with runtime - * dependencies. - */ -#define SND_SOC_COMP_ORDER_FIRST -2 -#define SND_SOC_COMP_ORDER_EARLY -1 -#define SND_SOC_COMP_ORDER_NORMAL 0 -#define SND_SOC_COMP_ORDER_LATE 1 -#define SND_SOC_COMP_ORDER_LAST 2 - -#define for_each_comp_order(order) \ - for (order = SND_SOC_COMP_ORDER_FIRST; \ - order <= SND_SOC_COMP_ORDER_LAST; \ - order++) - /* * Bias levels * @@ -747,132 +732,6 @@ struct snd_soc_compr_ops { int (*trigger)(struct snd_compr_stream *); }; -/* component interface */ -struct snd_soc_component_driver { - const char *name; - - /* Default control and setup, added after probe() is run */ - const struct snd_kcontrol_new *controls; - unsigned int num_controls; - const struct snd_soc_dapm_widget *dapm_widgets; - unsigned int num_dapm_widgets; - const struct snd_soc_dapm_route *dapm_routes; - unsigned int num_dapm_routes; - - int (*probe)(struct snd_soc_component *); - void (*remove)(struct snd_soc_component *); - int (*suspend)(struct snd_soc_component *); - int (*resume)(struct snd_soc_component *); - - unsigned int (*read)(struct snd_soc_component *, unsigned int); - int (*write)(struct snd_soc_component *, unsigned int, unsigned int); - - /* pcm creation and destruction */ - int (*pcm_new)(struct snd_soc_pcm_runtime *); - void (*pcm_free)(struct snd_pcm *); - - /* component wide operations */ - int (*set_sysclk)(struct snd_soc_component *component, - int clk_id, int source, unsigned int freq, int dir); - int (*set_pll)(struct snd_soc_component *component, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out); - int (*set_jack)(struct snd_soc_component *component, - struct snd_soc_jack *jack, void *data); - - /* DT */ - int (*of_xlate_dai_name)(struct snd_soc_component *component, - struct of_phandle_args *args, - const char **dai_name); - int (*of_xlate_dai_id)(struct snd_soc_component *comment, - struct device_node *endpoint); - void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, - int subseq); - int (*stream_event)(struct snd_soc_component *, int event); - int (*set_bias_level)(struct snd_soc_component *component, - enum snd_soc_bias_level level); - - const struct snd_pcm_ops *ops; - const struct snd_compr_ops *compr_ops; - - /* probe ordering - for components with runtime dependencies */ - int probe_order; - int remove_order; - - /* - * signal if the module handling the component should not be removed - * if a pcm is open. Setting this would prevent the module - * refcount being incremented in probe() but allow it be incremented - * when a pcm is opened and decremented when it is closed. - */ - unsigned int module_get_upon_open:1; - - /* bits */ - unsigned int idle_bias_on:1; - unsigned int suspend_bias_off:1; - unsigned int use_pmdown_time:1; /* care pmdown_time at stop */ - unsigned int endianness:1; - unsigned int non_legacy_dai_naming:1; - - /* this component uses topology and ignore machine driver FEs */ - const char *ignore_machine; - const char *topology_name_prefix; - int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params); - bool use_dai_pcm_id; /* use the DAI link PCM ID as PCM device number */ - int be_pcm_base; /* base device ID for all BE PCMs */ -}; - -struct snd_soc_component { - const char *name; - int id; - const char *name_prefix; - struct device *dev; - struct snd_soc_card *card; - - unsigned int active; - - unsigned int suspended:1; /* is in suspend PM state */ - - struct list_head list; - struct list_head card_aux_list; /* for auxiliary bound components */ - struct list_head card_list; - - const struct snd_soc_component_driver *driver; - - struct list_head dai_list; - int num_dai; - - struct regmap *regmap; - int val_bytes; - - struct mutex io_mutex; - - /* attached dynamic objects */ - struct list_head dobj_list; - - /* - * DO NOT use any of the fields below in drivers, they are temporary and - * are going to be removed again soon. If you use them in driver code the - * driver will be marked as BROKEN when these fields are removed. - */ - - /* Don't use these, use snd_soc_component_get_dapm() */ - struct snd_soc_dapm_context dapm; - - /* machine specific init */ - int (*init)(struct snd_soc_component *component); - -#ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_root; - const char *debugfs_prefix; -#endif -}; - -#define for_each_component_dais(component, dai)\ - list_for_each_entry(dai, &(component)->dai_list, list) -#define for_each_component_dais_safe(component, dai, _dai)\ - list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) - struct snd_soc_rtdcom_list { struct snd_soc_component *component; struct list_head list; /* rtd::component_list */ @@ -1337,134 +1196,6 @@ struct soc_enum { struct snd_soc_dobj dobj; }; -/** - * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is - * embedded in - * @dapm: The DAPM context to cast to the component - * - * This function must only be used on DAPM contexts that are known to be part of - * a component (e.g. in a component driver). Otherwise the behavior is - * undefined. - */ -static inline struct snd_soc_component *snd_soc_dapm_to_component( - struct snd_soc_dapm_context *dapm) -{ - return container_of(dapm, struct snd_soc_component, dapm); -} - -/** - * snd_soc_component_get_dapm() - Returns the DAPM context associated with a - * component - * @component: The component for which to get the DAPM context - */ -static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( - struct snd_soc_component *component) -{ - return &component->dapm; -} - -/** - * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level - * @component: The COMPONENT for which to initialize the DAPM bias level - * @level: The DAPM level to initialize to - * - * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level(). - */ -static inline void -snd_soc_component_init_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - snd_soc_dapm_init_bias_level( - snd_soc_component_get_dapm(component), level); -} - -/** - * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level - * @component: The COMPONENT for which to get the DAPM bias level - * - * Returns: The current DAPM bias level of the COMPONENT. - */ -static inline enum snd_soc_bias_level -snd_soc_component_get_bias_level(struct snd_soc_component *component) -{ - return snd_soc_dapm_get_bias_level( - snd_soc_component_get_dapm(component)); -} - -/** - * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level - * @component: The COMPONENT for which to set the level - * @level: The level to set to - * - * Forces the COMPONENT bias level to a specific state. See - * snd_soc_dapm_force_bias_level(). - */ -static inline int -snd_soc_component_force_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - return snd_soc_dapm_force_bias_level( - snd_soc_component_get_dapm(component), - level); -} - -/** - * snd_soc_dapm_kcontrol_component() - Returns the component associated to a kcontrol - * @kcontrol: The kcontrol - * - * This function must only be used on DAPM contexts that are known to be part of - * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined. - */ -static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( - struct snd_kcontrol *kcontrol) -{ - return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); -} - -/** - * snd_soc_component_cache_sync() - Sync the register cache with the hardware - * @component: COMPONENT to sync - * - * Note: This function will call regcache_sync() - */ -static inline int snd_soc_component_cache_sync( - struct snd_soc_component *component) -{ - return regcache_sync(component->regmap); -} - -/* component IO */ -int snd_soc_component_read(struct snd_soc_component *component, - unsigned int reg, unsigned int *val); -unsigned int snd_soc_component_read32(struct snd_soc_component *component, - unsigned int reg); -int snd_soc_component_write(struct snd_soc_component *component, - unsigned int reg, unsigned int val); -int snd_soc_component_update_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val); -int snd_soc_component_update_bits_async(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val); -void snd_soc_component_async_complete(struct snd_soc_component *component); -int snd_soc_component_test_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int value); - -/* component wide operations */ -int snd_soc_component_set_sysclk(struct snd_soc_component *component, - int clk_id, int source, unsigned int freq, int dir); -int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out); -int snd_soc_component_set_jack(struct snd_soc_component *component, - struct snd_soc_jack *jack, void *data); - -#ifdef CONFIG_REGMAP - -void snd_soc_component_init_regmap(struct snd_soc_component *component, - struct regmap *regmap); -void snd_soc_component_exit_regmap(struct snd_soc_component *component); - -#endif - /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, @@ -1478,17 +1209,6 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) return card->drvdata; } -static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, - void *data) -{ - dev_set_drvdata(c->dev, data); -} - -static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) -{ - return dev_get_drvdata(c->dev); -} - static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) { INIT_LIST_HEAD(&card->widgets); @@ -1535,12 +1255,6 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, return e->values[item]; } -static inline bool snd_soc_component_is_active( - struct snd_soc_component *component) -{ - return component->active != 0; -} - /** * snd_soc_kcontrol_component() - Returns the component that registered the * control @@ -1676,24 +1390,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) mutex_unlock(&dapm->card->dapm_mutex); } -int snd_soc_component_enable_pin(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_disable_pin(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_nc_pin(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_get_pin_status(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_force_enable_pin(struct snd_soc_component *component, - const char *pin); -int snd_soc_component_force_enable_pin_unlocked( - struct snd_soc_component *component, - const char *pin); +#include #endif diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 919c3c027c62..250a0dea9294 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c new file mode 100644 index 000000000000..e19f78bfb919 --- /dev/null +++ b/sound/soc/soc-component.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-component.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// +#include + +/** + * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. + * @component: COMPONENT + * @clk_id: DAI specific clock ID + * @source: Source for the clock + * @freq: new clock frequency in Hz + * @dir: new clock direction - input/output. + * + * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. + */ +int snd_soc_component_set_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, + int dir) +{ + if (component->driver->set_sysclk) + return component->driver->set_sysclk(component, clk_id, source, + freq, dir); + + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); + +/* + * snd_soc_component_set_pll - configure component PLL. + * @component: COMPONENT + * @pll_id: DAI specific PLL ID + * @source: DAI specific source for the PLL + * @freq_in: PLL input clock frequency in Hz + * @freq_out: requested PLL output clock frequency in Hz + * + * Configures and enables PLL to generate output clock based on input clock. + */ +int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, + int source, unsigned int freq_in, + unsigned int freq_out) +{ + if (component->driver->set_pll) + return component->driver->set_pll(component, pll_id, source, + freq_in, freq_out); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); + +int snd_soc_component_enable_pin(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_enable_pin(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_enable_pin(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); + +int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_enable_pin_unlocked(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); + +int snd_soc_component_disable_pin(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_disable_pin(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_disable_pin(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); + +int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_disable_pin_unlocked(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); + +int snd_soc_component_nc_pin(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_nc_pin(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_nc_pin(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); + +int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_nc_pin_unlocked(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); + +int snd_soc_component_get_pin_status(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_get_pin_status(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_get_pin_status(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); + +int snd_soc_component_force_enable_pin(struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_force_enable_pin(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_force_enable_pin(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); + +int snd_soc_component_force_enable_pin_unlocked( + struct snd_soc_component *component, + const char *pin) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char *full_name; + int ret; + + if (!component->name_prefix) + return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); + + full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); + if (!full_name) + return -ENOMEM; + + ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); + kfree(full_name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); + +/** + * snd_soc_component_set_jack - configure component jack. + * @component: COMPONENTs + * @jack: structure to use for the jack + * @data: can be used if codec driver need extra data for configuring jack + * + * Configures and enables jack detection function. + */ +int snd_soc_component_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + if (component->driver->set_jack) + return component->driver->set_jack(component, jack, data); + + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ed66d2c68d10..dc3e45547da2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2345,50 +2345,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); -/** - * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. - * @component: COMPONENT - * @clk_id: DAI specific clock ID - * @source: Source for the clock - * @freq: new clock frequency in Hz - * @dir: new clock direction - input/output. - * - * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. - */ -int snd_soc_component_set_sysclk(struct snd_soc_component *component, - int clk_id, int source, unsigned int freq, - int dir) -{ - if (component->driver->set_sysclk) - return component->driver->set_sysclk(component, clk_id, source, - freq, dir); - - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); - -/* - * snd_soc_component_set_pll - configure component PLL. - * @component: COMPONENT - * @pll_id: DAI specific PLL ID - * @source: DAI specific source for the PLL - * @freq_in: PLL input clock frequency in Hz - * @freq_out: requested PLL output clock frequency in Hz - * - * Configures and enables PLL to generate output clock based on input clock. - */ -int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out) -{ - if (component->driver->set_pll) - return component->driver->set_pll(component, pll_id, source, - freq_in, freq_out); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); - static int snd_soc_bind_card(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index c7b990abdbaa..a71d2340eb05 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -23,24 +23,6 @@ struct jack_gpio_tbl { struct snd_soc_jack_gpio *gpios; }; -/** - * snd_soc_component_set_jack - configure component jack. - * @component: COMPONENTs - * @jack: structure to use for the jack - * @data: can be used if codec driver need extra data for configuring jack - * - * Configures and enables jack detection function. - */ -int snd_soc_component_set_jack(struct snd_soc_component *component, - struct snd_soc_jack *jack, void *data) -{ - if (component->driver->set_jack) - return component->driver->set_jack(component, jack, data); - - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); - /** * snd_soc_card_jack_new - Create a new jack * @card: ASoC card diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e3b9dd634c6d..54dcece52b0c 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -52,205 +52,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) } EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); -int snd_soc_component_enable_pin(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_enable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_enable_pin(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); - -int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); - -int snd_soc_component_disable_pin(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); - -int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); - -int snd_soc_component_nc_pin(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); - -int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); - -int snd_soc_component_get_pin_status(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_get_pin_status(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_get_pin_status(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); - -int snd_soc_component_force_enable_pin(struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); - -int snd_soc_component_force_enable_pin_unlocked( - struct snd_soc_component *component, - const char *pin) -{ - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); - static const struct snd_pcm_hardware dummy_dma_hardware = { /* Random values to keep userspace happy when checking constraints */ .info = SNDRV_PCM_INFO_INTERLEAVED | -- GitLab From 4a81e8f30d0b422b7f10562952124d719f73b071 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:49:54 +0900 Subject: [PATCH 1921/7155] ASoC: soc-component: add snd_soc_component_get/put() ALSA SoC is calling try_module_get()/module_put() based on component->driver->module_get_upon_open. To keep simple and readable code, we should create its function. This patch adds new snd_soc_component_get/put(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h8795ro4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 13 +++++++++++++ sound/soc/soc-component.c | 18 ++++++++++++++++++ sound/soc/soc-core.c | 9 ++++----- sound/soc/soc-pcm.c | 10 ++++------ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index a97d499e5d7a..a76cadf49a16 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -287,6 +287,19 @@ void snd_soc_component_init_regmap(struct snd_soc_component *component, void snd_soc_component_exit_regmap(struct snd_soc_component *component); #endif +#define snd_soc_component_module_get_when_probe(component)\ + snd_soc_component_module_get(component, 0) +#define snd_soc_component_module_get_when_open(component) \ + snd_soc_component_module_get(component, 1) +int snd_soc_component_module_get(struct snd_soc_component *component, + int upon_open); +#define snd_soc_component_module_put_when_remove(component) \ + snd_soc_component_module_put(component, 0) +#define snd_soc_component_module_put_when_close(component) \ + snd_soc_component_module_put(component, 1) +void snd_soc_component_module_put(struct snd_soc_component *component, + int upon_open); + static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, void *data) { diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index e19f78bfb919..ac2d7bd5d844 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -5,6 +5,7 @@ // Copyright (C) 2019 Renesas Electronics Corp. // Kuninori Morimoto // +#include #include /** @@ -267,3 +268,20 @@ int snd_soc_component_set_jack(struct snd_soc_component *component, return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); + +int snd_soc_component_module_get(struct snd_soc_component *component, + int upon_open) +{ + if (component->driver->module_get_upon_open == !!upon_open && + !try_module_get(component->dev->driver->owner)) + return -ENODEV; + + return 0; +} + +void snd_soc_component_module_put(struct snd_soc_component *component, + int upon_open) +{ + if (component->driver->module_get_upon_open == !!upon_open) + module_put(component->dev->driver->owner); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index dc3e45547da2..9ba19efcc56c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -926,8 +926,7 @@ static void soc_cleanup_component(struct snd_soc_component *component) snd_soc_dapm_free(snd_soc_component_get_dapm(component)); soc_cleanup_component_debugfs(component); component->card = NULL; - if (!component->driver->module_get_upon_open) - module_put(component->dev->driver->owner); + snd_soc_component_module_put_when_close(component); } static void soc_remove_component(struct snd_soc_component *component) @@ -1255,9 +1254,9 @@ static int soc_probe_component(struct snd_soc_card *card, return 0; } - if (!component->driver->module_get_upon_open && - !try_module_get(component->dev->driver->owner)) - return -ENODEV; + ret = snd_soc_component_module_get_when_probe(component); + if (ret < 0) + return ret; component->card = card; dapm->card = card; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1e6c4e226933..5fef18507286 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -440,12 +439,12 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, component = rtdcom->component; *last = component; - if (component->driver->module_get_upon_open && - !try_module_get(component->dev->driver->owner)) { + ret = snd_soc_component_module_get_when_open(component); + if (ret < 0) { dev_err(component->dev, "ASoC: can't get module %s\n", component->name); - return -ENODEV; + return ret; } if (!component->driver->ops || @@ -481,8 +480,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, component->driver->ops->close) component->driver->ops->close(substream); - if (component->driver->module_get_upon_open) - module_put(component->dev->driver->owner); + snd_soc_component_module_put_when_close(component); } return 0; -- GitLab From ae2f4849286eed48a3aa79a7b73bb5bcd0c9213b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:01 +0900 Subject: [PATCH 1922/7155] ASoC: soc-component: add snd_soc_component_open() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_open() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ftmt5rnx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 4 ++++ sound/soc/soc-component.c | 10 ++++++++++ sound/soc/soc-pcm.c | 6 +----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index a76cadf49a16..156b1a5b6ddd 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -338,4 +338,8 @@ int snd_soc_component_force_enable_pin_unlocked( struct snd_soc_component *component, const char *pin); +/* component driver ops */ +int snd_soc_component_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index ac2d7bd5d844..ada46f9729b2 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -285,3 +285,13 @@ void snd_soc_component_module_put(struct snd_soc_component *component, if (component->driver->module_get_upon_open == !!upon_open) module_put(component->dev->driver->owner); } + +int snd_soc_component_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + if (component->driver->ops && + component->driver->ops->open) + return component->driver->ops->open(substream); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5fef18507286..caf7028cee62 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -447,11 +447,7 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, return ret; } - if (!component->driver->ops || - !component->driver->ops->open) - continue; - - ret = component->driver->ops->open(substream); + ret = snd_soc_component_open(component, substream); if (ret < 0) { dev_err(component->dev, "ASoC: can't open component %s: %d\n", -- GitLab From 3672beb8cad6beb7b8c017514aef0f4f507debcf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:07 +0900 Subject: [PATCH 1923/7155] ASoC: soc-component: add snd_soc_component_close() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_close() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ef2d5rnr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 10 ++++++++++ sound/soc/soc-pcm.c | 8 +++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 156b1a5b6ddd..8dacac953884 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -341,5 +341,7 @@ int snd_soc_component_force_enable_pin_unlocked( /* component driver ops */ int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream); +int snd_soc_component_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index ada46f9729b2..cee66183470d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -295,3 +295,13 @@ int snd_soc_component_open(struct snd_soc_component *component, return 0; } + +int snd_soc_component_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + if (component->driver->ops && + component->driver->ops->close) + return component->driver->ops->close(substream); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index caf7028cee62..4848642ef159 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -465,6 +465,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_rtdcom_list *rtdcom; struct snd_soc_component *component; + int ret = 0; for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; @@ -472,14 +473,11 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, if (component == last) break; - if (component->driver->ops && - component->driver->ops->close) - component->driver->ops->close(substream); - + ret |= snd_soc_component_close(component, substream); snd_soc_component_module_put_when_close(component); } - return 0; + return ret; } /* -- GitLab From 6d53723380ed73a2ced648d6e92774b39e5af1bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:13 +0900 Subject: [PATCH 1924/7155] ASoC: soc-component: add snd_soc_component_prepare() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_prepare() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87d0hx5rnm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 10 ++++++++++ sound/soc/soc-pcm.c | 6 +----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 8dacac953884..ff8233014444 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -343,5 +343,7 @@ int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream); int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream); +int snd_soc_component_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index cee66183470d..733d7139d875 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -305,3 +305,13 @@ int snd_soc_component_close(struct snd_soc_component *component, return 0; } + +int snd_soc_component_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + if (component->driver->ops && + component->driver->ops->prepare) + return component->driver->ops->prepare(substream); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4848642ef159..c7fee67bc0dc 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -785,11 +785,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; - if (!component->driver->ops || - !component->driver->ops->prepare) - continue; - - ret = component->driver->ops->prepare(substream); + ret = snd_soc_component_prepare(component, substream); if (ret < 0) { dev_err(component->dev, "ASoC: platform prepare error: %d\n", ret); -- GitLab From 245c539a1206d74e8508a07550fb7c99d0817b8c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:19 +0900 Subject: [PATCH 1925/7155] ASoC: soc-component: add snd_soc_component_hw_params() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_hw_params() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blxh5rnf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ sound/soc/soc-component.c | 11 +++++++++++ sound/soc/soc-pcm.c | 6 +----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index ff8233014444..778a6e7d352d 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -345,5 +345,8 @@ int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream); int snd_soc_component_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream); +int snd_soc_component_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 733d7139d875..7b6456370da5 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -315,3 +315,14 @@ int snd_soc_component_prepare(struct snd_soc_component *component, return 0; } + +int snd_soc_component_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + if (component->driver->ops && + component->driver->ops->hw_params) + return component->driver->ops->hw_params(substream, params); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index c7fee67bc0dc..8be1d22dc87a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -951,11 +951,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; - if (!component->driver->ops || - !component->driver->ops->hw_params) - continue; - - ret = component->driver->ops->hw_params(substream, params); + ret = snd_soc_component_hw_params(component, substream, params); if (ret < 0) { dev_err(component->dev, "ASoC: %s hw params failed: %d\n", -- GitLab From eae7136aa2083699c69de5890fd6c32c501952b5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:24 +0900 Subject: [PATCH 1926/7155] ASoC: soc-component: add snd_soc_component_hw_free() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_hw_free() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a7d15rna.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 10 ++++++++++ sound/soc/soc-pcm.c | 9 +++------ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 778a6e7d352d..fbcd911ac25e 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -348,5 +348,7 @@ int snd_soc_component_prepare(struct snd_soc_component *component, int snd_soc_component_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); +int snd_soc_component_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 7b6456370da5..e2bc34efe547 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -326,3 +326,13 @@ int snd_soc_component_hw_params(struct snd_soc_component *component, return 0; } + +int snd_soc_component_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + if (component->driver->ops && + component->driver->ops->hw_free) + return component->driver->ops->hw_free(substream); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8be1d22dc87a..8c5289904f20 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -847,6 +847,7 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_rtdcom_list *rtdcom; struct snd_soc_component *component; + int ret = 0; for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; @@ -854,14 +855,10 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, if (component == last) break; - if (!component->driver->ops || - !component->driver->ops->hw_free) - continue; - - component->driver->ops->hw_free(substream); + ret |= snd_soc_component_hw_free(component, substream); } - return 0; + return ret; } /* -- GitLab From d3523b631403897bf560927321ca8c2ea0aed873 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:04:08 +0800 Subject: [PATCH 1927/7155] usb: dwc3: meson-g12a: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Neil Armstrong Link: https://lore.kernel.org/r/20190802130408.20336-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-meson-g12a.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index bca7e92a10e9..d73ccd9e1366 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -386,7 +386,6 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; void __iomem *base; - struct resource *res; enum phy_mode otg_id; int ret, i, irq; @@ -394,8 +393,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 582ee9c5ad2661b359309f379f5c411fd33e511a Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Mon, 5 Aug 2019 22:24:12 +0800 Subject: [PATCH 1928/7155] USB: Disable USB2 LPM at shutdown The QCA Rome USB Bluetooth controller has several issues once LPM gets enabled: - Fails to get enumerated in coldboot. [1] - Drains more power (~ 0.2W) when the system is in S5. [2] - Disappears after a warmboot. [2] The issue happens because the device lingers at LPM L1 in S5, so device can't get enumerated even after a reboot. Disable LPM at shutdown to solve the issue. [1] https://bugs.launchpad.net/bugs/1757218 [2] https://patchwork.kernel.org/patch/10607097/ Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20190805142412.23965-1-kai.heng.feng@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/port.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 1a06a4b5fbb1..bbbb35fa639f 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -285,6 +285,14 @@ static int usb_port_runtime_suspend(struct device *dev) } #endif +static void usb_port_shutdown(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + if (port_dev->child) + usb_disable_usb2_hardware_lpm(port_dev->child); +} + static const struct dev_pm_ops usb_port_pm_ops = { #ifdef CONFIG_PM .runtime_suspend = usb_port_runtime_suspend, @@ -301,6 +309,7 @@ struct device_type usb_port_device_type = { static struct device_driver usb_port_driver = { .name = "usb", .owner = THIS_MODULE, + .shutdown = usb_port_shutdown, }; static int link_peers(struct usb_port *left, struct usb_port *right) -- GitLab From 5693d50c830272cb3c4a04d2ce4db502debd1259 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:29 +0900 Subject: [PATCH 1929/7155] ASoC: soc-component: add snd_soc_component_trigger() Current ALSA SoC is directly using component->driver->ops->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_trigger() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878ssl5rn5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ sound/soc/soc-component.c | 11 +++++++++++ sound/soc/soc-pcm.c | 6 +----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index fbcd911ac25e..302e27a89d47 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -350,5 +350,8 @@ int snd_soc_component_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params); int snd_soc_component_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream); +int snd_soc_component_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int cmd); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index e2bc34efe547..cf0d20a877e6 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -336,3 +336,14 @@ int snd_soc_component_hw_free(struct snd_soc_component *component, return 0; } + +int snd_soc_component_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int cmd) +{ + if (component->driver->ops && + component->driver->ops->trigger) + return component->driver->ops->trigger(substream, cmd); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8c5289904f20..cd49c2d688c3 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1065,11 +1065,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) for_each_rtdcom(rtd, rtdcom) { component = rtdcom->component; - if (!component->driver->ops || - !component->driver->ops->trigger) - continue; - - ret = component->driver->ops->trigger(substream, cmd); + ret = snd_soc_component_trigger(component, substream, cmd); if (ret < 0) return ret; } -- GitLab From 66c51573b89d0a5c1089139a2f0dd029a755c37d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:50:34 +0900 Subject: [PATCH 1930/7155] ASoC: soc-component: add snd_soc_component_suspend() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_suspend() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877e855rn0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 7 +++++++ sound/soc/soc-core.c | 4 +--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 302e27a89d47..cdb014f41fd1 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -353,5 +353,6 @@ int snd_soc_component_hw_free(struct snd_soc_component *component, int snd_soc_component_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd); +void snd_soc_component_suspend(struct snd_soc_component *component); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index cf0d20a877e6..f0e63cd991c8 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -347,3 +347,10 @@ int snd_soc_component_trigger(struct snd_soc_component *component, return 0; } + +void snd_soc_component_suspend(struct snd_soc_component *component) +{ + if (component->driver->suspend) + component->driver->suspend(component); + component->suspended = 1; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9ba19efcc56c..855b19abc1d2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -520,9 +520,7 @@ int snd_soc_suspend(struct device *dev) /* fall through */ case SND_SOC_BIAS_OFF: - if (component->driver->suspend) - component->driver->suspend(component); - component->suspended = 1; + snd_soc_component_suspend(component); if (component->regmap) regcache_mark_dirty(component->regmap); /* deactivate pins to sleep state */ -- GitLab From 9a840cbac77a90e8406296aaa132ebf2c84ed9e3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:08 +0900 Subject: [PATCH 1931/7155] ASoC: soc-component: add snd_soc_component_resume() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_resume() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875znp5rm2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 7 +++++++ sound/soc/soc-core.c | 4 +--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index cdb014f41fd1..1e3b70855ba7 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -354,5 +354,6 @@ int snd_soc_component_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd); void snd_soc_component_suspend(struct snd_soc_component *component); +void snd_soc_component_resume(struct snd_soc_component *component); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index f0e63cd991c8..cbae7672b72d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -354,3 +354,10 @@ void snd_soc_component_suspend(struct snd_soc_component *component) component->driver->suspend(component); component->suspended = 1; } + +void snd_soc_component_resume(struct snd_soc_component *component) +{ + if (component->driver->resume) + component->driver->resume(component); + component->suspended = 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 855b19abc1d2..6cdfe7b2fe06 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -593,9 +593,7 @@ static void soc_resume_deferred(struct work_struct *work) for_each_card_components(card, component) { if (component->suspended) { - if (component->driver->resume) - component->driver->resume(component); - component->suspended = 0; + snd_soc_component_resume(component); } } -- GitLab From e40fadbcef583808c11d2e86b8ac1c652731468e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:13 +0900 Subject: [PATCH 1932/7155] ASoC: soc-component: add snd_soc_component_is_suspended() Current ALSA SoC is directly using component->xxx, But, it is not good for encapsulation. This patch adds new snd_soc_component_is_suspended() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874l395rlx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 5 +++++ sound/soc/soc-core.c | 5 ++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 1e3b70855ba7..9600dc4ca6b4 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -355,5 +355,6 @@ int snd_soc_component_trigger(struct snd_soc_component *component, int cmd); void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); +int snd_soc_component_is_suspended(struct snd_soc_component *component); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index cbae7672b72d..0a9ca84d7ac6 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -361,3 +361,8 @@ void snd_soc_component_resume(struct snd_soc_component *component) component->driver->resume(component); component->suspended = 0; } + +int snd_soc_component_is_suspended(struct snd_soc_component *component) +{ + return component->suspended; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6cdfe7b2fe06..ea93edd328a2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -503,7 +503,7 @@ int snd_soc_suspend(struct device *dev) * If there are paths active then the COMPONENT will be held * with bias _ON and should not be suspended. */ - if (!component->suspended) { + if (!snd_soc_component_is_suspended(component)) { switch (snd_soc_dapm_get_bias_level(dapm)) { case SND_SOC_BIAS_STANDBY: /* @@ -592,9 +592,8 @@ static void soc_resume_deferred(struct work_struct *work) } for_each_card_components(card, component) { - if (component->suspended) { + if (snd_soc_component_is_suspended(component)) snd_soc_component_resume(component); - } } for_each_card_rtds(card, rtd) { -- GitLab From 08e837dd9e39bd3e25b1fa1a13f6ba44040e3f0d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:17 +0900 Subject: [PATCH 1933/7155] ASoC: soc-component: add snd_soc_component_probe() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_probe() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8736it5rlt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 8 ++++++++ sound/soc/soc-core.c | 12 +++++------- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 9600dc4ca6b4..34e774efcf69 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -356,5 +356,6 @@ int snd_soc_component_trigger(struct snd_soc_component *component, void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); +int snd_soc_component_probe(struct snd_soc_component *component); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 0a9ca84d7ac6..b2bfc0375193 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -366,3 +366,11 @@ int snd_soc_component_is_suspended(struct snd_soc_component *component) { return component->suspended; } + +int snd_soc_component_probe(struct snd_soc_component *component) +{ + if (component->driver->probe) + return component->driver->probe(component); + + return 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ea93edd328a2..6a422ddae130 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1282,13 +1282,11 @@ static int soc_probe_component(struct snd_soc_card *card, } } - if (component->driver->probe) { - ret = component->driver->probe(component); - if (ret < 0) { - dev_err(component->dev, - "ASoC: failed to probe component %d\n", ret); - goto err_probe; - } + ret = snd_soc_component_probe(component); + if (ret < 0) { + dev_err(component->dev, + "ASoC: failed to probe component %d\n", ret); + goto err_probe; } WARN(dapm->idle_bias_off && dapm->bias_level != SND_SOC_BIAS_OFF, -- GitLab From 03b34dd7d87ce3493cb1837c9e59c3b3aac4724f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:22 +0900 Subject: [PATCH 1934/7155] ASoC: soc-component: add snd_soc_component_remove() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_remove() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871ryd5rlo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 6 ++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 34e774efcf69..b8480d947901 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -357,5 +357,6 @@ void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); int snd_soc_component_probe(struct snd_soc_component *component); +void snd_soc_component_remove(struct snd_soc_component *component); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index b2bfc0375193..eba77ea2b62d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -374,3 +374,9 @@ int snd_soc_component_probe(struct snd_soc_component *component) return 0; } + +void snd_soc_component_remove(struct snd_soc_component *component) +{ + if (component->driver->remove) + component->driver->remove(component); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6a422ddae130..6a6403ddf62d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -929,8 +929,7 @@ static void soc_remove_component(struct snd_soc_component *component) if (!component->card) return; - if (component->driver->remove) - component->driver->remove(component); + snd_soc_component_remove(component); soc_cleanup_component(component); } -- GitLab From 2c7b1704819435d188c7697c6815f788bf9e6200 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:26 +0900 Subject: [PATCH 1935/7155] ASoC: soc-component: add snd_soc_component_of_xlate_dai_id() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_of_xlate_dai_id() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zhl14d14.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 9 +++++++++ sound/soc/soc-core.c | 5 ++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index b8480d947901..3f4acd337c4a 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -358,5 +358,7 @@ void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); int snd_soc_component_probe(struct snd_soc_component *component); void snd_soc_component_remove(struct snd_soc_component *component); +int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, + struct device_node *ep); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index eba77ea2b62d..faf49992f661 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -380,3 +380,12 @@ void snd_soc_component_remove(struct snd_soc_component *component) if (component->driver->remove) component->driver->remove(component); } + +int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, + struct device_node *ep) +{ + if (component->driver->of_xlate_dai_id) + return component->driver->of_xlate_dai_id(component, ep); + + return -ENOTSUPP; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6a6403ddf62d..f63d09dd55f4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3334,9 +3334,8 @@ int snd_soc_get_dai_id(struct device_node *ep) ret = -ENOTSUPP; mutex_lock(&client_mutex); component = soc_find_component(&dlc); - if (component && - component->driver->of_xlate_dai_id) - ret = component->driver->of_xlate_dai_id(component, ep); + if (component) + ret = snd_soc_component_of_xlate_dai_id(component, ep); mutex_unlock(&client_mutex); of_node_put(dlc.of_node); -- GitLab From a2a341752558cc67d6fe5c8ada7c16f9c3690f89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:31 +0900 Subject: [PATCH 1936/7155] ASoC: soc-component: add snd_soc_component_of_xlate_dai_name() Current ALSA SoC is directly using component->driver->xxx, thus, it is deep nested, and makes code difficult to read, and is not good for encapsulation. This patch adds new snd_soc_component_of_xlate_dai_name() and use it Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y30l4d0z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ sound/soc/soc-component.c | 10 ++++++++++ sound/soc/soc-core.c | 7 ++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 3f4acd337c4a..3ed2c39e45c2 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -360,5 +360,8 @@ int snd_soc_component_probe(struct snd_soc_component *component); void snd_soc_component_remove(struct snd_soc_component *component); int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep); +int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index faf49992f661..de1bc5196f67 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -389,3 +389,13 @@ int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, return -ENOTSUPP; } + +int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + if (component->driver->of_xlate_dai_name) + return component->driver->of_xlate_dai_name(component, + args, dai_name); + return -ENOTSUPP; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f63d09dd55f4..2f068c239f34 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3358,11 +3358,8 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, if (component_of_node != args->np) continue; - if (pos->driver->of_xlate_dai_name) { - ret = pos->driver->of_xlate_dai_name(pos, - args, - dai_name); - } else { + ret = snd_soc_component_of_xlate_dai_name(pos, args, dai_name); + if (ret == -ENOTSUPP) { struct snd_soc_dai *dai; int id = -1; -- GitLab From 9d415fbf773f162a5c274e671741c6fa94b74287 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:35 +0900 Subject: [PATCH 1937/7155] ASoC: soc-component: move snd_soc_component_seq_notifier() Current soc-dapm / soc-core are using a long way round to call .seq_notifier. if (driver->seq_notifier) dapm->seq_notifier = ...; ... if (dapm->seq_notifier) ret = dapm->seq_notifier(...); We can directly call it via driver->seq_notifier. One note here is that both Card and Component have dapm, but, Card's dapm doesn't have dapm->component. We need to check it. This patch moves snd_soc_component_seq_notifier() to soc-component.c, and updates parameters. dapm->seq_notifier is no longer needed Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wog54d0v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ include/sound/soc-dapm.h | 2 -- sound/soc/soc-component.c | 7 +++++++ sound/soc/soc-core.c | 10 ---------- sound/soc/soc-dapm.c | 15 ++++++++------- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 3ed2c39e45c2..7ac903c1e33f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -281,6 +281,9 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, int snd_soc_component_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *data); +void snd_soc_component_seq_notifier(struct snd_soc_component *component, + enum snd_soc_dapm_type type, int subseq); + #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, struct regmap *regmap); diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 6c6694160130..a03db6f8faa8 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -661,8 +661,6 @@ struct snd_soc_dapm_context { unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ /* Go to BIAS_OFF in suspend if the DAPM context is idle */ unsigned int suspend_bias_off:1; - void (*seq_notifier)(struct snd_soc_dapm_context *, - enum snd_soc_dapm_type, int); struct device *dev; /* from parent - for debug */ struct snd_soc_component *component; /* parent component */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index de1bc5196f67..ca0b28b1d918 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -52,6 +52,13 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, } EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); +void snd_soc_component_seq_notifier(struct snd_soc_component *component, + enum snd_soc_dapm_type type, int subseq) +{ + if (component->driver->seq_notifier) + component->driver->seq_notifier(component, type, subseq); +} + int snd_soc_component_enable_pin(struct snd_soc_component *component, const char *pin) { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2f068c239f34..c618fecc3d45 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2646,14 +2646,6 @@ int snd_soc_register_dai(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_register_dai); -static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, - enum snd_soc_dapm_type type, int subseq) -{ - struct snd_soc_component *component = dapm->component; - - component->driver->seq_notifier(component, type, subseq); -} - static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, int event) { @@ -2690,8 +2682,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, dapm->bias_level = SND_SOC_BIAS_OFF; dapm->idle_bias_off = !driver->idle_bias_on; dapm->suspend_bias_off = driver->suspend_bias_off; - if (driver->seq_notifier) - dapm->seq_notifier = snd_soc_component_seq_notifier; if (driver->stream_event) dapm->stream_event = snd_soc_component_stream_event; if (driver->set_bias_level) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d93c1038fab0..0b60f688b433 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1611,12 +1611,12 @@ static void dapm_seq_run(struct snd_soc_card *card, if (!list_empty(&pending)) dapm_seq_run_coalesced(card, &pending); - if (cur_dapm && cur_dapm->seq_notifier) { + if (cur_dapm && cur_dapm->component) { for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) if (sort[i] == cur_sort) - cur_dapm->seq_notifier(cur_dapm, - i, - cur_subseq); + snd_soc_component_seq_notifier( + cur_dapm->component, + i, cur_subseq); } if (cur_dapm && w->dapm != cur_dapm) @@ -1674,11 +1674,12 @@ static void dapm_seq_run(struct snd_soc_card *card, if (!list_empty(&pending)) dapm_seq_run_coalesced(card, &pending); - if (cur_dapm && cur_dapm->seq_notifier) { + if (cur_dapm && cur_dapm->component) { for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) if (sort[i] == cur_sort) - cur_dapm->seq_notifier(cur_dapm, - i, cur_subseq); + snd_soc_component_seq_notifier( + cur_dapm->component, + i, cur_subseq); } list_for_each_entry(d, &card->dapm_list, list) { -- GitLab From 6b9ab1cf4b21b92c4b3bbebe1b5dc4f6d44f35b6 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 1 Aug 2019 15:35:57 +0800 Subject: [PATCH 1938/7155] iio: tsl2772: Use devm_add_action_or_reset Use devm_add_action_or_reset to remove the call to tsl2772_disable_regulators_action to simplify the error path. Signed-off-by: Chuhong Yuan Reviewed-by: Brian Masney Tested-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2772.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 83cece921843..29cfd8ae2700 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1807,10 +1807,10 @@ static int tsl2772_probe(struct i2c_client *clientp, return PTR_ERR(chip->vdd_supply); } - ret = devm_add_action(&clientp->dev, tsl2772_disable_regulators_action, - chip); + ret = devm_add_action_or_reset(&clientp->dev, + tsl2772_disable_regulators_action, + chip); if (ret < 0) { - tsl2772_disable_regulators_action(chip); dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n", ret); return ret; -- GitLab From 8e2a990d76aced95c6f01c2d67d8835c86f0ca67 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:39 +0900 Subject: [PATCH 1939/7155] ASoC: soc-component: move snd_soc_component_stream_event() Current soc-dapm / soc-core are using a long way round to call .stream_event. if (driver->stream_event) dapm->stream_event = ...; ... if (dapm->stream_event) ret = dapm->stream_event(...); We can directly call it via driver->stream_event. One note here is that both Card and Component have dapm, but, Card's dapm doesn't have dapm->component. We need to check it. This patch moves snd_soc_component_stream_event() to soc-component.c and updates parameters. dapm->stream_event is no longer needed Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9vp4d0r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ include/sound/soc-dapm.h | 1 - sound/soc/soc-component.c | 9 +++++++++ sound/soc/soc-core.c | 10 ---------- sound/soc/soc-dapm.c | 9 +++++++-- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 7ac903c1e33f..1f84f04e2670 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -283,6 +283,8 @@ int snd_soc_component_set_jack(struct snd_soc_component *component, void snd_soc_component_seq_notifier(struct snd_soc_component *component, enum snd_soc_dapm_type type, int subseq); +int snd_soc_component_stream_event(struct snd_soc_component *component, + int event); #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index a03db6f8faa8..c2f14a335891 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -670,7 +670,6 @@ struct snd_soc_dapm_context { enum snd_soc_bias_level target_bias_level; struct list_head list; - int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); int (*set_bias_level)(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index ca0b28b1d918..f33dda8023ec 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -59,6 +59,15 @@ void snd_soc_component_seq_notifier(struct snd_soc_component *component, component->driver->seq_notifier(component, type, subseq); } +int snd_soc_component_stream_event(struct snd_soc_component *component, + int event) +{ + if (component->driver->stream_event) + return component->driver->stream_event(component, event); + + return 0; +} + int snd_soc_component_enable_pin(struct snd_soc_component *component, const char *pin) { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c618fecc3d45..8cfbe5fb5921 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2646,14 +2646,6 @@ int snd_soc_register_dai(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_register_dai); -static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, - int event) -{ - struct snd_soc_component *component = dapm->component; - - return component->driver->stream_event(component, event); -} - static int snd_soc_component_set_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { @@ -2682,8 +2674,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, dapm->bias_level = SND_SOC_BIAS_OFF; dapm->idle_bias_off = !driver->idle_bias_on; dapm->suspend_bias_off = driver->suspend_bias_off; - if (driver->stream_event) - dapm->stream_event = snd_soc_component_stream_event; if (driver->set_bias_level) dapm->set_bias_level = snd_soc_component_set_bias_level; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 0b60f688b433..9288b2b43f98 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1913,6 +1913,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) LIST_HEAD(down_list); ASYNC_DOMAIN_EXCLUSIVE(async_domain); enum snd_soc_bias_level bias; + int ret; lockdep_assert_held(&card->dapm_mutex); @@ -2029,8 +2030,12 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) /* do we need to notify any clients that DAPM event is complete */ list_for_each_entry(d, &card->dapm_list, list) { - if (d->stream_event) - d->stream_event(d, event); + if (!d->component) + continue; + + ret = snd_soc_component_stream_event(d->component, event); + if (ret < 0) + return ret; } pop_dbg(card->dev, card->pop_time, -- GitLab From 7951b14611851bdae18e9bca18015b1d84731d0d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:43 +0900 Subject: [PATCH 1940/7155] ASoC: soc-component: move snd_soc_component_set_bias_level() Current soc-dapm / soc-core are using a long way round to call .set_bias_level. if (driver->set_bias_level) dapm->set_bias_level = ...; ... if (dapm->set_bias_level) ret = dapm->set_bias_level(...); We can directly call it via driver->set_bias_level. One note here is that both Card and Component have dapm, but, Card's dapm doesn't have dapm->component. We need to check it. This patch moves snd_soc_component_set_bias_level() to soc-component.c and updates parameters. dapm->set_bias_level is no longer needed Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tvb94d0n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ include/sound/soc-dapm.h | 3 --- sound/soc/soc-component.c | 9 +++++++++ sound/soc/soc-core.c | 10 ---------- sound/soc/soc-dapm.c | 4 ++-- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 1f84f04e2670..2aaf12bbbed0 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -285,6 +285,8 @@ void snd_soc_component_seq_notifier(struct snd_soc_component *component, enum snd_soc_dapm_type type, int subseq); int snd_soc_component_stream_event(struct snd_soc_component *component, int event); +int snd_soc_component_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level); #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c2f14a335891..2aa73d6dd7be 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -670,9 +670,6 @@ struct snd_soc_dapm_context { enum snd_soc_bias_level target_bias_level; struct list_head list; - int (*set_bias_level)(struct snd_soc_dapm_context *dapm, - enum snd_soc_bias_level level); - struct snd_soc_dapm_wcache path_sink_cache; struct snd_soc_dapm_wcache path_source_cache; diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index f33dda8023ec..cb63df6e46eb 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -68,6 +68,15 @@ int snd_soc_component_stream_event(struct snd_soc_component *component, return 0; } +int snd_soc_component_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + if (component->driver->set_bias_level) + return component->driver->set_bias_level(component, level); + + return 0; +} + int snd_soc_component_enable_pin(struct snd_soc_component *component, const char *pin) { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8cfbe5fb5921..0f75dac4bb26 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2646,14 +2646,6 @@ int snd_soc_register_dai(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_register_dai); -static int snd_soc_component_set_bias_level(struct snd_soc_dapm_context *dapm, - enum snd_soc_bias_level level) -{ - struct snd_soc_component *component = dapm->component; - - return component->driver->set_bias_level(component, level); -} - static int snd_soc_component_initialize(struct snd_soc_component *component, const struct snd_soc_component_driver *driver, struct device *dev) { @@ -2674,8 +2666,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, dapm->bias_level = SND_SOC_BIAS_OFF; dapm->idle_bias_off = !driver->idle_bias_on; dapm->suspend_bias_off = driver->suspend_bias_off; - if (driver->set_bias_level) - dapm->set_bias_level = snd_soc_component_set_bias_level; INIT_LIST_HEAD(&component->dai_list); mutex_init(&component->io_mutex); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 9288b2b43f98..d09bdca63c62 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -684,8 +684,8 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, { int ret = 0; - if (dapm->set_bias_level) - ret = dapm->set_bias_level(dapm, level); + if (dapm->component) + ret = snd_soc_component_set_bias_level(dapm->component, level); if (ret == 0) dapm->bias_level = level; -- GitLab From 0035e2565b93e0902a06320ba1716bc1ddd753b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:47 +0900 Subject: [PATCH 1941/7155] ASoC: soc-component: add snd_soc_pcm_component_pointer() Current ALSA SoC is directly using component->driver->ops->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_pointer() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sgqt4d0j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 18 ++++++++++++++++++ sound/soc/soc-pcm.c | 13 +------------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 2aaf12bbbed0..38b4be1d99f5 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -371,4 +371,6 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, struct of_phandle_args *args, const char **dai_name); +int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); + #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index cb63df6e46eb..e2053c8bf1f0 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -424,3 +424,21 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, args, dai_name); return -ENOTSUPP; } + +int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *component; + struct snd_soc_rtdcom_list *rtdcom; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + /* FIXME: use 1st pointer */ + if (component->driver->ops && + component->driver->ops->pointer) + return component->driver->ops->pointer(substream); + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index cd49c2d688c3..020e1d275076 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1111,8 +1111,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - struct snd_soc_rtdcom_list *rtdcom; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai; struct snd_pcm_runtime *runtime = substream->runtime; @@ -1124,17 +1122,8 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) /* clearing the previous total delay */ runtime->delay = 0; - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; + offset = snd_soc_pcm_component_pointer(substream); - if (!component->driver->ops || - !component->driver->ops->pointer) - continue; - - /* FIXME: use 1st pointer */ - offset = component->driver->ops->pointer(substream); - break; - } /* base delay if assigned in pointer callback */ delay = runtime->delay; -- GitLab From 96a47908d8769479f5217bf3f432ccdc06a29747 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:51 +0900 Subject: [PATCH 1942/7155] ASoC: soc-component: add snd_soc_pcm_component_ioctrl() Current ALSA SoC is directly using component->driver->ops->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_ioctrl() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r26d4d0f.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 20 ++++++++++++++++++++ sound/soc/soc-pcm.c | 25 ++----------------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 38b4be1d99f5..5db4e5d028d0 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -372,5 +372,7 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, const char **dai_name); int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); +int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index e2053c8bf1f0..a6c0857a9e90 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -442,3 +442,23 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) return 0; } + +int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *component; + struct snd_soc_rtdcom_list *rtdcom; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + /* FIXME: use 1st ioctl */ + if (component->driver->ops && + component->driver->ops->ioctl) + return component->driver->ops->ioctl(substream, + cmd, arg); + } + + return snd_pcm_lib_ioctl(substream, cmd, arg); +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 020e1d275076..12377b8d41c2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2453,27 +2453,6 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) return ret; } -static int soc_pcm_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - struct snd_soc_rtdcom_list *rtdcom; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->ioctl) - continue; - - /* FIXME: use 1st ioctl */ - return component->driver->ops->ioctl(substream, cmd, arg); - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_pcm_substream *substream = @@ -3013,7 +2992,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.hw_free = dpcm_fe_dai_hw_free; rtd->ops.close = dpcm_fe_dai_close; rtd->ops.pointer = soc_pcm_pointer; - rtd->ops.ioctl = soc_pcm_ioctl; + rtd->ops.ioctl = snd_soc_pcm_component_ioctl; } else { rtd->ops.open = soc_pcm_open; rtd->ops.hw_params = soc_pcm_hw_params; @@ -3022,7 +3001,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.hw_free = soc_pcm_hw_free; rtd->ops.close = soc_pcm_close; rtd->ops.pointer = soc_pcm_pointer; - rtd->ops.ioctl = soc_pcm_ioctl; + rtd->ops.ioctl = snd_soc_pcm_component_ioctl; } for_each_rtdcom(rtd, rtdcom) { -- GitLab From 82d81f5cced36e480b581ae51c595e2deb9f2d56 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:51:56 +0900 Subject: [PATCH 1943/7155] ASoC: soc-component: add snd_soc_pcm_component_copy_user() Current ALSA SoC is directly using component->driver->ops->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_copy_user() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pnlx4d0a.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ sound/soc/soc-component.c | 21 +++++++++++++++++++++ sound/soc/soc-pcm.c | 25 +------------------------ 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5db4e5d028d0..6b95d2467053 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -374,5 +374,8 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); +int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *buf, unsigned long bytes); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index a6c0857a9e90..20897dce1bec 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -462,3 +462,24 @@ int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, return snd_pcm_lib_ioctl(substream, cmd, arg); } + +int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *buf, unsigned long bytes) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + /* FIXME. it returns 1st copy now */ + if (component->driver->ops && + component->driver->ops->copy_user) + return component->driver->ops->copy_user( + substream, channel, pos, buf, bytes); + } + + return -EINVAL; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 12377b8d41c2..b0e6ce89b012 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2818,29 +2818,6 @@ static void soc_pcm_private_free(struct snd_pcm *pcm) } } -static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel, - unsigned long pos, void __user *buf, - unsigned long bytes) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->copy_user) - continue; - - /* FIXME. it returns 1st copy now */ - return component->driver->ops->copy_user(substream, channel, - pos, buf, bytes); - } - - return -EINVAL; -} - static struct page *soc_rtdcom_page(struct snd_pcm_substream *substream, unsigned long offset) { @@ -3011,7 +2988,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) continue; if (ops->copy_user) - rtd->ops.copy_user = soc_rtdcom_copy_user; + rtd->ops.copy_user = snd_soc_pcm_component_copy_user; if (ops->page) rtd->ops.page = soc_rtdcom_page; if (ops->mmap) -- GitLab From 9c712e4f57229081e837d593fc1e4183b068a41c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:52:00 +0900 Subject: [PATCH 1944/7155] ASoC: soc-component: add snd_soc_pcm_component_page() Current ALSA SoC is directly using component->driver->ops->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_page() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o91h4d06.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 23 +++++++++++++++++++++++ sound/soc/soc-pcm.c | 26 +------------------------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 6b95d2467053..4cab257962a6 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -377,5 +377,7 @@ int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, int channel, unsigned long pos, void __user *buf, unsigned long bytes); +struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, + unsigned long offset); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 20897dce1bec..d503bc9b0850 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -483,3 +483,26 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, return -EINVAL; } + +struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, + unsigned long offset) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + struct page *page; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + /* FIXME. it returns 1st page now */ + if (component->driver->ops && + component->driver->ops->page) { + page = component->driver->ops->page(substream, offset); + if (page) + return page; + } + } + + return NULL; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b0e6ce89b012..fe34f2e5d75e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2818,30 +2818,6 @@ static void soc_pcm_private_free(struct snd_pcm *pcm) } } -static struct page *soc_rtdcom_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - struct page *page; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->page) - continue; - - /* FIXME. it returns 1st page now */ - page = component->driver->ops->page(substream, offset); - if (page) - return page; - } - - return NULL; -} - static int soc_rtdcom_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { @@ -2990,7 +2966,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (ops->copy_user) rtd->ops.copy_user = snd_soc_pcm_component_copy_user; if (ops->page) - rtd->ops.page = soc_rtdcom_page; + rtd->ops.page = snd_soc_pcm_component_page; if (ops->mmap) rtd->ops.mmap = soc_rtdcom_mmap; } -- GitLab From 205875e1a12ef9c61e939db9ded90fe3f6352e75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:52:04 +0900 Subject: [PATCH 1945/7155] ASoC: soc-component: add snd_soc_pcm_component_mmap() Current ALSA SoC is directly using component->driver->ops->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_mmap() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87muh14d02.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ sound/soc/soc-component.c | 19 +++++++++++++++++++ sound/soc/soc-pcm.c | 23 +---------------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 4cab257962a6..dd1ea5d71998 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -379,5 +379,7 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, void __user *buf, unsigned long bytes); struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, unsigned long offset); +int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index d503bc9b0850..2aff1b087522 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -506,3 +506,22 @@ struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, return NULL; } + +int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + /* FIXME. it returns 1st mmap now */ + if (component->driver->ops && + component->driver->ops->mmap) + return component->driver->ops->mmap(substream, vma); + } + + return -EINVAL; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fe34f2e5d75e..7bbee0d71942 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2818,27 +2818,6 @@ static void soc_pcm_private_free(struct snd_pcm *pcm) } } -static int soc_rtdcom_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; - - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->ops || - !component->driver->ops->mmap) - continue; - - /* FIXME. it returns 1st mmap now */ - return component->driver->ops->mmap(substream, vma); - } - - return -EINVAL; -} - /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { @@ -2968,7 +2947,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (ops->page) rtd->ops.page = snd_soc_pcm_component_page; if (ops->mmap) - rtd->ops.mmap = soc_rtdcom_mmap; + rtd->ops.mmap = snd_soc_pcm_component_mmap; } if (playback) -- GitLab From 7484291e9b7564af65b2581dcdebeeaf98bc86d0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:52:08 +0900 Subject: [PATCH 1946/7155] ASoC: soc-component: add snd_soc_pcm_component_pcm_new() Current ALSA SoC is directly using component->driver->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_pcm() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfwl4czy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 20 ++++++++++++++++++++ sound/soc/soc-pcm.c | 18 ++++-------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index dd1ea5d71998..d3048ad06582 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -381,5 +381,6 @@ struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, unsigned long offset); int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); +int snd_soc_pcm_component_new(struct snd_pcm *pcm); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 2aff1b087522..ff13d901bbab 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -525,3 +525,23 @@ int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, return -EINVAL; } + +int snd_soc_pcm_component_new(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + int ret; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (component->driver->pcm_new) { + ret = component->driver->pcm_new(rtd); + if (ret < 0) + return ret; + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7bbee0d71942..955c49fd3bda 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2823,7 +2823,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_component *component; struct snd_soc_rtdcom_list *rtdcom; struct snd_pcm *pcm; char new_name[64]; @@ -2956,19 +2955,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (capture) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (!component->driver->pcm_new) - continue; - - ret = component->driver->pcm_new(rtd); - if (ret < 0) { - dev_err(component->dev, - "ASoC: pcm constructor failed: %d\n", - ret); - return ret; - } + ret = snd_soc_pcm_component_new(pcm); + if (ret < 0) { + dev_err(rtd->dev, "ASoC: pcm constructor failed: %d\n", ret); + return ret; } pcm->private_free = soc_pcm_private_free; -- GitLab From 79776da0989733a5bac0a1e635e3a284c3f5c745 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Jul 2019 13:52:12 +0900 Subject: [PATCH 1947/7155] ASoC: soc-component: add snd_soc_pcm_component_pcm_free() Current ALSA SoC is directly using component->driver->xxx, thus, the code nested deeply, and it makes code difficult to read, and is not good for encapsulation. We want to implement component related function at soc-component.c, but, some of them need to care whole snd_soc_pcm_runtime (= rtd) connected component. Let's call component related function which need to care with for_each_rtdcom() loop as snd_soc_pcm_component_xxx(). This patch adds new snd_soc_pcm_component_pcm_free() and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k1c54czu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-component.c | 14 ++++++++++++++ sound/soc/soc-pcm.c | 9 +-------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index d3048ad06582..5d80b2eef525 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -382,5 +382,6 @@ struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); int snd_soc_pcm_component_new(struct snd_pcm *pcm); +void snd_soc_pcm_component_free(struct snd_pcm *pcm); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index ff13d901bbab..79ffc2820ba9 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -545,3 +545,17 @@ int snd_soc_pcm_component_new(struct snd_pcm *pcm) return 0; } + +void snd_soc_pcm_component_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (component->driver->pcm_free) + component->driver->pcm_free(pcm); + } +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 955c49fd3bda..77c986fe08d0 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2805,17 +2805,10 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) static void soc_pcm_private_free(struct snd_pcm *pcm) { struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_component *component; /* need to sync the delayed work before releasing resources */ flush_delayed_work(&rtd->delayed_work); - for_each_rtdcom(rtd, rtdcom) { - component = rtdcom->component; - - if (component->driver->pcm_free) - component->driver->pcm_free(pcm); - } + snd_soc_pcm_component_free(pcm); } /* create a new pcm */ -- GitLab From db2a17320a25a63b46ddb081a306af9ded1b906e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Sun, 4 Aug 2019 21:50:23 +0530 Subject: [PATCH 1948/7155] regulator: core: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190804162023.5673-1-nishkadg.linux@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0c0cf462004..7a5d52948703 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -380,9 +380,12 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, if (!regnode) { regnode = of_get_child_regulator(child, prop_name); - if (regnode) + if (regnode) { + of_node_put(child); return regnode; + } } else { + of_node_put(child); return regnode; } } -- GitLab From 338084135aeddb103624a6841972fb8588295cc6 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 1 Aug 2019 15:36:05 +0800 Subject: [PATCH 1949/7155] iio: tsl2772: Use devm_add_action_or_reset for tsl2772_chip_off Use devm_add_action_or_reset to call tsl2772_chip_off when the device is removed. This also fixes the issue that the chip is turned off before the device is unregistered. Not marked for stable as fairly hard to hit the bug and this is in the middle of a set making other cleanups to the driver. Hence will probably need explicit backporting. Signed-off-by: Chuhong Yuan Fixes: c06c4d793584 ("staging: iio: tsl2x7x/tsl2772: move out of staging") Reviewed-by: Brian Masney Tested-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2772.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 29cfd8ae2700..e866ae40f157 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -860,6 +860,13 @@ static int tsl2772_chip_off(struct iio_dev *indio_dev) return tsl2772_write_control_reg(chip, 0x00); } +static void tsl2772_chip_off_action(void *data) +{ + struct iio_dev *indio_dev = data; + + tsl2772_chip_off(indio_dev); +} + /** * tsl2772_invoke_change - power cycle the device to implement the user * parameters @@ -1877,9 +1884,14 @@ static int tsl2772_probe(struct i2c_client *clientp, if (ret < 0) return ret; + ret = devm_add_action_or_reset(&clientp->dev, + tsl2772_chip_off_action, + indio_dev); + if (ret < 0) + return ret; + ret = iio_device_register(indio_dev); if (ret) { - tsl2772_chip_off(indio_dev); dev_err(&clientp->dev, "%s: iio registration failed\n", __func__); return ret; @@ -1926,8 +1938,6 @@ static int tsl2772_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); - tsl2772_chip_off(indio_dev); - iio_device_unregister(indio_dev); return 0; -- GitLab From 7e7f631c95467bcf01e7bc94ec69df9feaed7751 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 1 Aug 2019 15:36:12 +0800 Subject: [PATCH 1950/7155] iio: tsl2772: Use devm_iio_device_register Use devm_iio_device_register, which removes the tsl2772_remove function. Signed-off-by: Chuhong Yuan Reviewed-by: Brian Masney Tested-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2772.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index e866ae40f157..680afdb078d2 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1890,14 +1890,7 @@ static int tsl2772_probe(struct i2c_client *clientp, if (ret < 0) return ret; - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&clientp->dev, - "%s: iio registration failed\n", __func__); - return ret; - } - - return 0; + return devm_iio_device_register(&clientp->dev, indio_dev); } static int tsl2772_suspend(struct device *dev) @@ -1934,15 +1927,6 @@ static int tsl2772_resume(struct device *dev) return tsl2772_chip_on(indio_dev); } -static int tsl2772_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct i2c_device_id tsl2772_idtable[] = { { "tsl2571", tsl2571 }, { "tsl2671", tsl2671 }, @@ -1989,7 +1973,6 @@ static struct i2c_driver tsl2772_driver = { }, .id_table = tsl2772_idtable, .probe = tsl2772_probe, - .remove = tsl2772_remove, }; module_i2c_driver(tsl2772_driver); -- GitLab From a6513a878e2115911f8aff656ca3beac7bb8242c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 1 Aug 2019 15:36:19 +0800 Subject: [PATCH 1951/7155] iio: tsl2772: Use regulator_bulk_() APIs Use regulator_bulk_() APIs to shrink driver size. Signed-off-by: Chuhong Yuan Reviewed-by: Brian Masney Tested-by: Brian Masney Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2772.c | 87 +++++++++++++------------------------ 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 680afdb078d2..be37fcbd4654 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -134,6 +134,12 @@ enum { TSL2772_CHIP_SUSPENDED = 2 }; +enum { + TSL2772_SUPPLY_VDD = 0, + TSL2772_SUPPLY_VDDIO = 1, + TSL2772_NUM_SUPPLIES = 2 +}; + /* Per-device data */ struct tsl2772_als_info { u16 als_ch0; @@ -161,8 +167,7 @@ struct tsl2772_chip { struct mutex prox_mutex; struct mutex als_mutex; struct i2c_client *client; - struct regulator *vdd_supply; - struct regulator *vddio_supply; + struct regulator_bulk_data supplies[TSL2772_NUM_SUPPLIES]; u16 prox_data; struct tsl2772_als_info als_cur_info; struct tsl2772_settings settings; @@ -697,46 +702,7 @@ static void tsl2772_disable_regulators_action(void *_data) { struct tsl2772_chip *chip = _data; - regulator_disable(chip->vdd_supply); - regulator_disable(chip->vddio_supply); -} - -static int tsl2772_enable_regulator(struct tsl2772_chip *chip, - struct regulator *regulator) -{ - int ret; - - ret = regulator_enable(regulator); - if (ret < 0) { - dev_err(&chip->client->dev, "Failed to enable regulator: %d\n", - ret); - return ret; - } - - return 0; -} - -static struct regulator *tsl2772_get_regulator(struct tsl2772_chip *chip, - char *name) -{ - struct regulator *regulator; - int ret; - - regulator = devm_regulator_get(&chip->client->dev, name); - if (IS_ERR(regulator)) { - if (PTR_ERR(regulator) != -EPROBE_DEFER) - dev_err(&chip->client->dev, - "Failed to get %s regulator %d\n", - name, (int)PTR_ERR(regulator)); - - return regulator; - } - - ret = tsl2772_enable_regulator(chip, regulator); - if (ret < 0) - return ERR_PTR(ret); - - return regulator; + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); } static int tsl2772_chip_on(struct iio_dev *indio_dev) @@ -1804,14 +1770,26 @@ static int tsl2772_probe(struct i2c_client *clientp, chip->client = clientp; i2c_set_clientdata(clientp, indio_dev); - chip->vddio_supply = tsl2772_get_regulator(chip, "vddio"); - if (IS_ERR(chip->vddio_supply)) - return PTR_ERR(chip->vddio_supply); + chip->supplies[TSL2772_SUPPLY_VDD].supply = "vdd"; + chip->supplies[TSL2772_SUPPLY_VDDIO].supply = "vddio"; - chip->vdd_supply = tsl2772_get_regulator(chip, "vdd"); - if (IS_ERR(chip->vdd_supply)) { - regulator_disable(chip->vddio_supply); - return PTR_ERR(chip->vdd_supply); + ret = devm_regulator_bulk_get(&clientp->dev, + ARRAY_SIZE(chip->supplies), + chip->supplies); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(&clientp->dev, + "Failed to get regulators: %d\n", + ret); + + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); + if (ret < 0) { + dev_err(&clientp->dev, "Failed to enable regulators: %d\n", + ret); + return ret; } ret = devm_add_action_or_reset(&clientp->dev, @@ -1900,8 +1878,7 @@ static int tsl2772_suspend(struct device *dev) int ret; ret = tsl2772_chip_off(indio_dev); - regulator_disable(chip->vdd_supply); - regulator_disable(chip->vddio_supply); + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); return ret; } @@ -1912,16 +1889,10 @@ static int tsl2772_resume(struct device *dev) struct tsl2772_chip *chip = iio_priv(indio_dev); int ret; - ret = tsl2772_enable_regulator(chip, chip->vddio_supply); + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); if (ret < 0) return ret; - ret = tsl2772_enable_regulator(chip, chip->vdd_supply); - if (ret < 0) { - regulator_disable(chip->vddio_supply); - return ret; - } - usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME); return tsl2772_chip_on(indio_dev); -- GitLab From 48cceecfa7625e700ed9c57392bd17923c4832c0 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 1 Aug 2019 16:39:08 +0200 Subject: [PATCH 1952/7155] iio: imu: st_lsm6dsx: make IIO_CHAN_INFO_SCALE shared by type in_accel_x_scale, in_accel_y_scale and in_accel_z_scale are always the same. The scale is still defined to be in "info_mask_separate". Userspace (iio-sensor-proxy and others) is not used to that and only looks for "in_accel_scale" for the scaling factor to apply. Change IIO_CHAN_INFO_SCALE from being separate in all channel to be shared by type. This removes in_accel_x_scale, in_accel_y_scale and in_accel_z_scale and makes available in_accel_scale. This is an ABI change, but hopefully in the 'no one will notice' category. The cleanup in interface is worth the small risk that there is a custom script out there somewhere that this will break. Signed-off-by: Martin Kepplinger Acked-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 4d47ba36de84..4e8e67ae1632 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -58,8 +58,8 @@ enum st_lsm6dsx_hw_id { .address = addr, \ .modified = 1, \ .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = scan_idx, \ .scan_type = { \ -- GitLab From 83c5cf19a3f2d249e180a7b45a2559dd6b514f54 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:21:53 +0900 Subject: [PATCH 1953/7155] arm64: dts: renesas: r8a77970: eagle: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- .../arm64/boot/dts/renesas/r8a77970-eagle.dts | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts index 233f26fbec17..2afb91ec9c8d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts @@ -23,10 +23,13 @@ stdout-path = "serial0:115200n8"; }; - memory@48000000 { - device_type = "memory"; - /* first 128MB is reserved for secure area. */ - reg = <0x0 0x48000000 0x0 0x38000000>; + d3p3: regulator-fixed { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; }; hdmi-out { @@ -40,15 +43,6 @@ }; }; - d3p3: regulator-fixed { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - lvds-decoder { compatible = "thine,thc63lvd1024"; @@ -73,6 +67,12 @@ }; }; }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; }; &avb { @@ -102,6 +102,10 @@ }; }; +&du { + status = "okay"; +}; + &extal_clk { clock-frequency = <16666666>; }; @@ -157,6 +161,18 @@ }; }; +&lvds0 { + status = "okay"; + + ports { + port@1 { + lvds0_out: endpoint { + remote-endpoint = <&thc63lvd1024_in>; + }; + }; + }; +}; + &pfc { avb_pins: avb0 { groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk"; @@ -190,19 +206,3 @@ status = "okay"; }; - -&du { - status = "okay"; -}; - -&lvds0 { - status = "okay"; - - ports { - port@1 { - lvds0_out: endpoint { - remote-endpoint = <&thc63lvd1024_in>; - }; - }; - }; -}; -- GitLab From 43afe2062267332fbb253924de0f3522b02d1a66 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:23:17 +0900 Subject: [PATCH 1954/7155] arm64: dts: renesas: r8a77970: v3msk: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- .../arm64/boot/dts/renesas/r8a77970-v3msk.dts | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts index 15cc9fed2e16..d7c7b9156e08 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts @@ -21,6 +21,41 @@ stdout-path = "serial0:115200n8"; }; + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7511_out>; + }; + }; + }; + + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <&vcc_d3_3v>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + thc63lvd1024_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + + port@2 { + reg = <2>; + thc63lvd1024_out: endpoint { + remote-endpoint = <&adv7511_in>; + }; + }; + }; + }; + memory@48000000 { device_type = "memory"; /* first 128MB is reserved for secure area. */ @@ -59,41 +94,6 @@ regulator-boot-on; regulator-always-on; }; - - lvds-decoder { - compatible = "thine,thc63lvd1024"; - vcc-supply = <&vcc_d3_3v>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - thc63lvd1024_in: endpoint { - remote-endpoint = <&lvds0_out>; - }; - }; - - port@2 { - reg = <2>; - thc63lvd1024_out: endpoint { - remote-endpoint = <&adv7511_in>; - }; - }; - }; - }; - - hdmi-out { - compatible = "hdmi-connector"; - type = "a"; - - port { - hdmi_con: endpoint { - remote-endpoint = <&adv7511_out>; - }; - }; - }; }; &avb { @@ -128,29 +128,6 @@ clock-frequency = <32768>; }; -&pfc { - avb_pins: avb0 { - groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk"; - function = "avb0"; - }; - - i2c0_pins: i2c0 { - groups = "i2c0"; - function = "i2c0"; - }; - - mmc_pins: mmc_3_3v { - groups = "mmc_data8", "mmc_ctrl"; - function = "mmc"; - power-source = <3300>; - }; - - scif0_pins: scif0 { - groups = "scif0_data"; - function = "scif0"; - }; -}; - &i2c0 { pinctrl-0 = <&i2c0_pins>; pinctrl-names = "default"; @@ -220,6 +197,29 @@ status = "okay"; }; +&pfc { + avb_pins: avb0 { + groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk"; + function = "avb0"; + }; + + i2c0_pins: i2c0 { + groups = "i2c0"; + function = "i2c0"; + }; + + mmc_pins: mmc_3_3v { + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; + power-source = <3300>; + }; + + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; + }; +}; + &scif0 { pinctrl-0 = <&scif0_pins>; pinctrl-names = "default"; -- GitLab From 8ccb4c9788814b95c059d9663949aaea03957ac9 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:23:34 +0900 Subject: [PATCH 1955/7155] arm64: dts: renesas: r8a77980: condor: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a77980-condor.dts | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts index 5a7012be0d6a..3dde028e22a6 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts @@ -22,35 +22,20 @@ stdout-path = "serial0:115200n8"; }; - memory@48000000 { - device_type = "memory"; - /* first 128MB is reserved for secure area. */ - reg = <0 0x48000000 0 0x78000000>; - }; - - d3_3v: regulator-0 { - compatible = "regulator-fixed"; - regulator-name = "D3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - vddq_vin01: regulator-1 { + d1_8v: regulator-2 { compatible = "regulator-fixed"; - regulator-name = "VDDQ_VIN01"; + regulator-name = "D1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-boot-on; regulator-always-on; }; - d1_8v: regulator-2 { + d3_3v: regulator-0 { compatible = "regulator-fixed"; - regulator-name = "D1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; + regulator-name = "D3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; @@ -90,6 +75,21 @@ }; }; + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0 0x48000000 0 0x78000000>; + }; + + vddq_vin01: regulator-1 { + compatible = "regulator-fixed"; + regulator-name = "VDDQ_VIN01"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + x1_clk: x1-clock { compatible = "fixed-clock"; #clock-cells = <0>; -- GitLab From 52f95a0935c1a0c8073ffe3b44f0c30d62b05b37 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:23:52 +0900 Subject: [PATCH 1956/7155] arm64: dts: renesas: r8a77980: v3hsk: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts index dd14a41b32cd..adbfd8f07d06 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts @@ -22,12 +22,6 @@ stdout-path = "serial0:115200n8"; }; - memory@48000000 { - device_type = "memory"; - /* first 128MB is reserved for secure area. */ - reg = <0 0x48000000 0 0x78000000>; - }; - hdmi-out { compatible = "hdmi-connector"; type = "a"; @@ -63,6 +57,12 @@ }; }; + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0 0x48000000 0 0x78000000>; + }; + osc1_clk: osc1-clock { compatible = "fixed-clock"; #clock-cells = <0>; -- GitLab From 880925e84dbea9786c23cebd51dfa7861129da4f Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:24:12 +0900 Subject: [PATCH 1957/7155] arm64: dts: renesas: r8a77990: ebisu: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko [geert: Sort sound child nodes] Signed-off-by: Geert Uytterhoeven --- .../arm64/boot/dts/renesas/r8a77990-ebisu.dts | 208 +++++++++--------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts index 83fc13ac3fa1..81db803f4389 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts @@ -23,12 +23,6 @@ stdout-path = "serial0:115200n8"; }; - memory@48000000 { - device_type = "memory"; - /* first 128MB is reserved for secure area. */ - reg = <0x0 0x48000000 0x0 0x38000000>; - }; - audio_clkout: audio-clkout { /* * This is same as <&rcar_sound 0> @@ -107,36 +101,10 @@ }; }; - vga { - compatible = "vga-connector"; - - port { - vga_in: endpoint { - remote-endpoint = <&adv7123_out>; - }; - }; - }; - - vga-encoder { - compatible = "adi,adv7123"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - adv7123_in: endpoint { - remote-endpoint = <&du_out_rgb>; - }; - }; - port@1 { - reg = <1>; - adv7123_out: endpoint { - remote-endpoint = <&vga_in>; - }; - }; - }; + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x38000000>; }; reg_1p8v: regulator0 { @@ -157,15 +125,13 @@ regulator-always-on; }; - vbus0_usb2: regulator-vbus0-usb2 { + reg_12p0v: regulator2 { compatible = "regulator-fixed"; - - regulator-name = "USB20_VBUS_CN"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - - gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>; - enable-active-high; + regulator-name = "D12.0V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-boot-on; + regulator-always-on; }; rsnd_ak4613: sound { @@ -176,34 +142,24 @@ simple-audio-card,bitclock-master = <&sndcpu>; simple-audio-card,frame-master = <&sndcpu>; - sndcpu: simple-audio-card,cpu { - sound-dai = <&rcar_sound>; - }; - sndcodec: simple-audio-card,codec { sound-dai = <&ak4613>; }; - }; - x12_clk: x12 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <24576000>; + sndcpu: simple-audio-card,cpu { + sound-dai = <&rcar_sound>; + }; }; - reg_12p0v: regulator2 { + vbus0_usb2: regulator-vbus0-usb2 { compatible = "regulator-fixed"; - regulator-name = "D12.0V"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - regulator-boot-on; - regulator-always-on; - }; - x13_clk: x13 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <74250000>; + regulator-name = "USB20_VBUS_CN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>; + enable-active-high; }; vcc_sdhi0: regulator-vcc-sdhi0 { @@ -253,6 +209,50 @@ states = <3300000 1 1800000 0>; }; + + vga { + compatible = "vga-connector"; + + port { + vga_in: endpoint { + remote-endpoint = <&adv7123_out>; + }; + }; + }; + + vga-encoder { + compatible = "adi,adv7123"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7123_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + port@1 { + reg = <1>; + adv7123_out: endpoint { + remote-endpoint = <&vga_in>; + }; + }; + }; + }; + + x12_clk: x12 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; + }; + + x13_clk: x13 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <74250000>; + }; }; &audio_clk_a { @@ -547,6 +547,11 @@ function = "pwm5"; }; + scif2_pins: scif2 { + groups = "scif2_data_a"; + function = "scif2"; + }; + sdhi0_pins: sd0 { groups = "sdhi0_data4", "sdhi0_ctrl"; function = "sdhi0"; @@ -577,20 +582,15 @@ power-source = <1800>; }; - sound_pins: sound { - groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data"; - function = "ssi"; - }; - sound_clk_pins: sound_clk { groups = "audio_clk_a", "audio_clk_b_a", "audio_clk_c_a", "audio_clkout_a", "audio_clkout1_a"; function = "audio_clk"; }; - scif2_pins: scif2 { - groups = "scif2_data_a"; - function = "scif2"; + sound_pins: sound { + groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data"; + function = "ssi"; }; usb0_pins: usb { @@ -671,38 +671,6 @@ status = "okay"; }; -&ssi1 { - shared-pin; -}; - -&usb2_phy0 { - pinctrl-0 = <&usb0_pins>; - pinctrl-names = "default"; - - vbus-supply = <&vbus0_usb2>; - status = "okay"; -}; - -&usb3_peri0 { - companion = <&xhci0>; - status = "okay"; -}; - -&vin4 { - status = "okay"; -}; - -&vin5 { - status = "okay"; -}; - -&xhci0 { - pinctrl-0 = <&usb30_pins>; - pinctrl-names = "default"; - - status = "okay"; -}; - &sdhi0 { pinctrl-0 = <&sdhi0_pins>; pinctrl-1 = <&sdhi0_pins_uhs>; @@ -746,3 +714,35 @@ non-removable; status = "okay"; }; + +&ssi1 { + shared-pin; +}; + +&usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; + + vbus-supply = <&vbus0_usb2>; + status = "okay"; +}; + +&usb3_peri0 { + companion = <&xhci0>; + status = "okay"; +}; + +&vin4 { + status = "okay"; +}; + +&vin5 { + status = "okay"; +}; + +&xhci0 { + pinctrl-0 = <&usb30_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; -- GitLab From ddd56410dac00cb9cf36ead6b795242952a4ed6d Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:24:36 +0900 Subject: [PATCH 1958/7155] arm64: dts: renesas: r8a77990: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77990.dtsi | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index 84d1f58e73e7..e51bc4c8a0bb 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1326,6 +1326,17 @@ "ssi.1", "ssi.0"; status = "disabled"; + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + rcar_sound,dvc { dvc0: dvc-0 { dmas = <&audma0 0xbc>; @@ -1342,17 +1353,6 @@ mix1: mix-1 { }; }; - rcar_sound,ctu { - ctu00: ctu-0 { }; - ctu01: ctu-1 { }; - ctu02: ctu-2 { }; - ctu03: ctu-3 { }; - ctu10: ctu-4 { }; - ctu11: ctu-5 { }; - ctu12: ctu-6 { }; - ctu13: ctu-7 { }; - }; - rcar_sound,src { src0: src-0 { interrupts = ; @@ -1866,25 +1866,25 @@ thermal-sensors = <&thermal 0>; sustainable-power = <717>; - trips { - target: trip-point1 { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; + cooling-maps { + map0 { + trip = <&target>; + cooling-device = <&a53_0 0 2>; + contribution = <1024>; }; + }; + trips { sensor1_crit: sensor1-crit { temperature = <120000>; hysteresis = <2000>; type = "critical"; }; - }; - cooling-maps { - map0 { - trip = <&target>; - cooling-device = <&a53_0 0 2>; - contribution = <1024>; + target: trip-point1 { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; }; }; }; -- GitLab From 1ab0a43afdfb6683cfd76216d3361a3813bcb75e Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:24:55 +0900 Subject: [PATCH 1959/7155] arm64: dts: renesas: r8a77995: draak: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts index 0711170b26b1..fe14792cedfb 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts +++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts @@ -19,11 +19,6 @@ ethernet0 = &avb; }; - chosen { - bootargs = "ignore_loglevel rw root=/dev/nfs ip=on"; - stdout-path = "serial0:115200n8"; - }; - backlight: backlight { compatible = "pwm-backlight"; pwms = <&pwm1 0 50000>; @@ -35,6 +30,11 @@ enable-gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; }; + chosen { + bootargs = "ignore_loglevel rw root=/dev/nfs ip=on"; + stdout-path = "serial0:115200n8"; + }; + composite-in { compatible = "composite-video-connector"; -- GitLab From c070bf341093652fd82ebd1de5f1dcf5e10afbb6 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Thu, 1 Aug 2019 23:25:13 +0900 Subject: [PATCH 1960/7155] arm64: dts: renesas: r8a77995: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 76 +++++++++++------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index bcd54421796d..b3dbf557bc97 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -242,41 +242,6 @@ resets = <&cpg 407>; }; - hscif0: serial@e6540000 { - compatible = "renesas,hscif-r8a77995", - "renesas,rcar-gen3-hscif", - "renesas,hscif"; - reg = <0 0xe6540000 0 0x60>; - interrupts = ; - clocks = <&cpg CPG_MOD 520>, - <&cpg CPG_CORE R8A77995_CLK_S3D1C>, - <&scif_clk>; - clock-names = "fck", "brg_int", "scif_clk"; - dmas = <&dmac1 0x31>, <&dmac1 0x30>, - <&dmac2 0x31>, <&dmac2 0x30>; - dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; - resets = <&cpg 520>; - status = "disabled"; - }; - - hscif3: serial@e66a0000 { - compatible = "renesas,hscif-r8a77995", - "renesas,rcar-gen3-hscif", - "renesas,hscif"; - reg = <0 0xe66a0000 0 0x60>; - interrupts = ; - clocks = <&cpg CPG_MOD 517>, - <&cpg CPG_CORE R8A77995_CLK_S3D1C>, - <&scif_clk>; - clock-names = "fck", "brg_int", "scif_clk"; - dmas = <&dmac0 0x37>, <&dmac0 0x36>; - dma-names = "tx", "rx"; - power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; - resets = <&cpg 517>; - status = "disabled"; - }; - i2c0: i2c@e6500000 { #address-cells = <1>; #size-cells = <0>; @@ -344,6 +309,41 @@ status = "disabled"; }; + hscif0: serial@e6540000 { + compatible = "renesas,hscif-r8a77995", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe6540000 0 0x60>; + interrupts = ; + clocks = <&cpg CPG_MOD 520>, + <&cpg CPG_CORE R8A77995_CLK_S3D1C>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x31>, <&dmac1 0x30>, + <&dmac2 0x31>, <&dmac2 0x30>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; + resets = <&cpg 520>; + status = "disabled"; + }; + + hscif3: serial@e66a0000 { + compatible = "renesas,hscif-r8a77995", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe66a0000 0 0x60>; + interrupts = ; + clocks = <&cpg CPG_MOD 517>, + <&cpg CPG_CORE R8A77995_CLK_S3D1C>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x37>, <&dmac0 0x36>; + dma-names = "tx", "rx"; + power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; + resets = <&cpg 517>; + status = "disabled"; + }; + hsusb: usb@e6590000 { compatible = "renesas,usbhs-r8a77995", "renesas,rcar-gen3-usbhs"; @@ -1100,6 +1100,9 @@ polling-delay = <1000>; thermal-sensors = <&thermal>; + cooling-maps { + }; + trips { cpu-crit { temperature = <120000>; @@ -1107,9 +1110,6 @@ type = "critical"; }; }; - - cooling-maps { - }; }; }; -- GitLab From a2fe2cd26285061fd9ef2649bac529f1db33d50b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 2 Aug 2019 08:34:07 +0100 Subject: [PATCH 1961/7155] arm64: dts: renesas: r8a774c0: Point LVDS0 to its companion LVDS1 Add the new renesas,companion property to the LVDS0 node to point to the companion LVDS encoder LVDS1. Based on similar work from Laurent Pinchart for the r8a7799[05]. Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index bdf555f48268..746775f4ab99 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1848,6 +1848,8 @@ resets = <&cpg 727>; status = "disabled"; + renesas,companion = <&lvds1>; + ports { #address-cells = <1>; #size-cells = <0>; -- GitLab From 7fc009cbd7d11d6b27ba5443dbfa80a0513829e4 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 2 Aug 2019 08:34:08 +0100 Subject: [PATCH 1962/7155] arm64: dts: renesas: r8a774c0: cat874: Add definition for 12V regulator Power rail "D12.0V" comes straight from the power barrel connector, and it's used in both main board and sub board. Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts index 46a77eefa536..651383cd048c 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts +++ b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts @@ -65,6 +65,15 @@ reg = <0x0 0x48000000 0x0 0x78000000>; }; + reg_12p0v: regulator-12p0v { + compatible = "regulator-fixed"; + regulator-name = "D12.0V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-boot-on; + regulator-always-on; + }; + sound: sound { compatible = "simple-audio-card"; -- GitLab From 9cd15d521a3adcb687a0f9a312e32caaa94f44c2 Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Fri, 2 Aug 2019 10:59:13 -0700 Subject: [PATCH 1963/7155] iio: remove get_irq_data_ready() function pointer and use IRQ number directly Not even sure why it was there since the beginning. Just use IRQ number in the sensor_data struct. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 7 +++---- .../iio/common/st_sensors/st_sensors_i2c.c | 9 +------- .../iio/common/st_sensors/st_sensors_spi.c | 9 +------- .../common/st_sensors/st_sensors_trigger.c | 21 +++++++++---------- drivers/iio/gyro/st_gyro_core.c | 7 +++---- drivers/iio/magnetometer/st_magn_core.c | 7 +++---- drivers/iio/pressure/st_pressure_core.c | 7 +++---- include/linux/iio/common/st_sensors.h | 5 ++--- 8 files changed, 26 insertions(+), 46 deletions(-) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 0b17004cb12e..2e37f8a6d8cf 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1169,7 +1169,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev) struct st_sensor_data *adata = iio_priv(indio_dev); struct st_sensors_platform_data *pdata = (struct st_sensors_platform_data *)adata->dev->platform_data; - int irq = adata->get_irq_data_ready(indio_dev); struct iio_chan_spec *channels; size_t channels_size; int err; @@ -1217,7 +1216,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_accel_power_off; - if (irq > 0) { + if (adata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_ACCEL_TRIGGER_OPS); if (err < 0) @@ -1234,7 +1233,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) return 0; st_accel_device_register_error: - if (irq > 0) + if (adata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_accel_probe_trigger_error: st_accel_deallocate_ring(indio_dev); @@ -1252,7 +1251,7 @@ void st_accel_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (adata->get_irq_data_ready(indio_dev) > 0) + if (adata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_accel_deallocate_ring(indio_dev); diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index 9240625534df..aa89d54a7c59 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -20,13 +20,6 @@ #define ST_SENSORS_I2C_MULTIREAD 0x80 -static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); - - return to_i2c_client(sdata->dev)->irq; -} - static const struct regmap_config st_sensors_i2c_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -69,7 +62,7 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev, indio_dev->name = client->name; sdata->dev = &client->dev; - sdata->get_irq_data_ready = st_sensors_i2c_get_irq; + sdata->irq = client->irq; return 0; } diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 9c0661a283d0..2262f81b07c2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -18,13 +18,6 @@ #define ST_SENSORS_SPI_MULTIREAD 0xc0 -static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); - - return to_spi_device(sdata->dev)->irq; -} - static const struct regmap_config st_sensors_spi_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -117,7 +110,7 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev, indio_dev->name = spi->modalias; sdata->dev = &spi->dev; - sdata->get_irq_data_ready = st_sensors_spi_get_irq; + sdata->irq = spi->irq; return 0; } diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index bed7b8682b17..4a2efa00f7f2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -121,9 +121,9 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p) int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { - int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned long irq_trig; + int err; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { @@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig->ops = trigger_ops; sdata->trig->dev.parent = sdata->dev; - irq = sdata->get_irq_data_ready(indio_dev); - irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); /* * If the IRQ is triggered on falling edge, we need to mark the * interrupt as active low, if the hardware supports this. @@ -206,12 +205,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->sensor_settings->drdy_irq.stat_drdy.addr) irq_trig |= IRQF_SHARED; - err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), - st_sensors_irq_handler, - st_sensors_irq_thread, - irq_trig, - sdata->trig->name, - sdata->trig); + err = request_threaded_irq(sdata->irq, + st_sensors_irq_handler, + st_sensors_irq_thread, + irq_trig, + sdata->trig->name, + sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); goto iio_trigger_free; @@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, return 0; iio_trigger_register_error: - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free: iio_trigger_free(sdata->trig); return err; @@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev) struct st_sensor_data *sdata = iio_priv(indio_dev); iio_trigger_unregister(sdata->trig); - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free(sdata->trig); } EXPORT_SYMBOL(st_sensors_deallocate_trigger); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 02e42c945181..c0acbb5d2ffb 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -388,7 +388,6 @@ EXPORT_SYMBOL(st_gyro_get_settings); int st_gyro_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *gdata = iio_priv(indio_dev); - int irq = gdata->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; @@ -419,7 +418,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_gyro_power_off; - if (irq > 0) { + if (gdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_GYRO_TRIGGER_OPS); if (err < 0) @@ -436,7 +435,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) return 0; st_gyro_device_register_error: - if (irq > 0) + if (gdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_gyro_probe_trigger_error: st_gyro_deallocate_ring(indio_dev); @@ -454,7 +453,7 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (gdata->get_irq_data_ready(indio_dev) > 0) + if (gdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_gyro_deallocate_ring(indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 804353a483c7..a3a268ee2896 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -490,7 +490,6 @@ EXPORT_SYMBOL(st_magn_get_settings); int st_magn_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *mdata = iio_priv(indio_dev); - int irq = mdata->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; @@ -520,7 +519,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_magn_power_off; - if (irq > 0) { + if (mdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_MAGN_TRIGGER_OPS); if (err < 0) @@ -537,7 +536,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) return 0; st_magn_device_register_error: - if (irq > 0) + if (mdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_magn_probe_trigger_error: st_magn_deallocate_ring(indio_dev); @@ -555,7 +554,7 @@ void st_magn_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (mdata->get_irq_data_ready(indio_dev) > 0) + if (mdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_magn_deallocate_ring(indio_dev); diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 9ef92a501286..ca6863b32a5f 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -686,7 +686,6 @@ int st_press_common_probe(struct iio_dev *indio_dev) struct st_sensor_data *press_data = iio_priv(indio_dev); struct st_sensors_platform_data *pdata = (struct st_sensors_platform_data *)press_data->dev->platform_data; - int irq = press_data->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; @@ -729,7 +728,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_press_power_off; - if (irq > 0) { + if (press_data->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_PRESS_TRIGGER_OPS); if (err < 0) @@ -746,7 +745,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) return err; st_press_device_register_error: - if (irq > 0) + if (press_data->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_press_probe_trigger_error: st_press_deallocate_ring(indio_dev); @@ -764,7 +763,7 @@ void st_press_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (press_data->get_irq_data_ready(indio_dev) > 0) + if (press_data->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_press_deallocate_ring(indio_dev); diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 28fc1f9fa7d5..4d0889bf1c6c 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -220,7 +220,7 @@ struct st_sensor_settings { * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * @int_pin_open_drain: Set the interrupt/DRDY to open drain. - * @get_irq_data_ready: Function to get the IRQ used for data ready signal. + * @irq: the IRQ number. * @edge_irq: the IRQ triggers on edges and need special handling. * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. @@ -244,8 +244,7 @@ struct st_sensor_data { u8 drdy_int_pin; bool int_pin_open_drain; - - unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); + int irq; bool edge_irq; bool hw_irq_trigger; -- GitLab From 1441beda92e7c0ab0759d28fa0472456e929803e Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Fri, 2 Aug 2019 12:42:27 +0100 Subject: [PATCH 1964/7155] dt-bindings: Add binding document for NOA1305 Document the ON Semiconductor NOA1305 ambient light sensor devicetree bindings. Signed-off-by: Martyn Welch Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/light/noa1305.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/noa1305.yaml diff --git a/Documentation/devicetree/bindings/iio/light/noa1305.yaml b/Documentation/devicetree/bindings/iio/light/noa1305.yaml new file mode 100644 index 000000000000..17e7f140b69b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/noa1305.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/noa1305.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ON Semiconductor NOA1305 Ambient Light Sensor + +maintainers: + - Martyn Welch + +description: | + Ambient sensing with an i2c interface. + + https://www.onsemi.com/pub/Collateral/NOA1305-D.PDF + +properties: + compatible: + enum: + - onnn,noa1305 + + reg: + maxItems: 1 + + vin-supply: + description: Regulator that provides power to the sensor + +required: + - compatible + - reg + +examples: + - | + i2c { + + #address-cells = <1>; + #size-cells = <0>; + + light@39 { + compatible = "onnn,noa1305"; + reg = <0x39>; + }; + }; +... -- GitLab From 5b25380d906af3be2489066295ea8c832efc71e8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Aug 2019 20:14:06 +0100 Subject: [PATCH 1965/7155] parport: Add missing newline at end of file "git diff" says: \ No newline at end of file after modifying the file. Signed-off-by: Geert Uytterhoeven Signed-off-by: Sudip Mukherjee Link: https://lore.kernel.org/r/20190801191408.10977-1-sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/parport/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile index 6fa41f8173b6..022c566c0f32 100644 --- a/drivers/parport/Makefile +++ b/drivers/parport/Makefile @@ -19,4 +19,4 @@ obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o obj-$(CONFIG_PARPORT_AX88796) += parport_ax88796.o -obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o \ No newline at end of file +obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o -- GitLab From 9e18a80c2e06c154c9c745091f7caec487423519 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 1 Aug 2019 20:14:08 +0100 Subject: [PATCH 1966/7155] parport: parport_serial: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Sudip Mukherjee Link: https://lore.kernel.org/r/20190801191408.10977-3-sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_serial.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 461fd8a24278..b11f5d238eda 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -660,8 +660,7 @@ static void parport_serial_pci_remove(struct pci_dev *dev) static int __maybe_unused parport_serial_pci_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct parport_serial_private *priv = pci_get_drvdata(pdev); + struct parport_serial_private *priv = dev_get_drvdata(dev); if (priv->serial) pciserial_suspend_ports(priv->serial); @@ -672,8 +671,7 @@ static int __maybe_unused parport_serial_pci_suspend(struct device *dev) static int __maybe_unused parport_serial_pci_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct parport_serial_private *priv = pci_get_drvdata(pdev); + struct parport_serial_private *priv = dev_get_drvdata(dev); if (priv->serial) pciserial_resume_ports(priv->serial); -- GitLab From b0a523fa9e9d61febb9e817f07b28927190c3c2f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:48:19 +0800 Subject: [PATCH 1967/7155] w1: mxc_w1: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190802134819.9088-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/mxc_w1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index c3b2095ef6a9..1ca880e01476 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -92,7 +92,6 @@ static int mxc_w1_probe(struct platform_device *pdev) { struct mxc_w1_device *mdev; unsigned long clkrate; - struct resource *res; unsigned int clkdiv; int err; @@ -120,8 +119,7 @@ static int mxc_w1_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "Incorrect time base frequency %lu Hz\n", clkrate); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdev->regs = devm_ioremap_resource(&pdev->dev, res); + mdev->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdev->regs)) { err = PTR_ERR(mdev->regs); goto out_disable_clk; -- GitLab From 7008aff290e1dba6618b18219967fd0d58783127 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:50:10 +0800 Subject: [PATCH 1968/7155] w1: omap-hdq: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190802135010.24052-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/omap_hdq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 3099052e1243..4164045866b3 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -660,7 +660,6 @@ static int omap_hdq_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct hdq_data *hdq_data; - struct resource *res; int ret, irq; u8 rev; const char *mode; @@ -674,8 +673,7 @@ static int omap_hdq_probe(struct platform_device *pdev) hdq_data->dev = dev; platform_set_drvdata(pdev, hdq_data); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hdq_data->hdq_base = devm_ioremap_resource(dev, res); + hdq_data->hdq_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hdq_data->hdq_base)) return PTR_ERR(hdq_data->hdq_base); -- GitLab From 69bb18ddfc4331ba1dea9db811caf93e95726408 Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:11 +0800 Subject: [PATCH 1969/7155] fpga: dfl: fme: add DFL_FPGA_FME_PORT_RELEASE/ASSIGN ioctl support. In order to support virtualization usage via PCIe SRIOV, this patch adds two ioctls under FPGA Management Engine (FME) to release and assign back the port device. In order to safely turn Port from PF into VF and enable PCIe SRIOV, it requires user to invoke this PORT_RELEASE ioctl to release port firstly to remove userspace interfaces, and then configure the PF/VF access register in FME. After disable SRIOV, it requires user to invoke this PORT_ASSIGN ioctl to attach the port back to PF. Ioctl interfaces: * DFL_FPGA_FME_PORT_RELEASE Release platform device of given port, it deletes port platform device to remove related userspace interfaces on PF. After this function, then it's safe to configure PF/VF access mode to VF, and enable VFs via SRIOV. * DFL_FPGA_FME_PORT_ASSIGN Assign platform device of given port back to PF. After configure PF/VF access mode to PF, this ioctl adds port platform device back to re-enable related userspace interfaces on PF. Signed-off-by: Zhang Yi Z Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-2-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl-fme-main.c | 42 +++++++++++++ drivers/fpga/dfl.c | 113 ++++++++++++++++++++++++++++++---- drivers/fpga/dfl.h | 10 +++ include/uapi/linux/fpga-dfl.h | 18 ++++++ 4 files changed, 171 insertions(+), 12 deletions(-) diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index 0be4635583d5..dfea2dee78c3 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "dfl.h" @@ -104,9 +105,50 @@ static void fme_hdr_uinit(struct platform_device *pdev, device_remove_groups(&pdev->dev, fme_hdr_groups); } +static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata, + unsigned long arg) +{ + struct dfl_fpga_cdev *cdev = pdata->dfl_cdev; + int port_id; + + if (get_user(port_id, (int __user *)arg)) + return -EFAULT; + + return dfl_fpga_cdev_release_port(cdev, port_id); +} + +static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata, + unsigned long arg) +{ + struct dfl_fpga_cdev *cdev = pdata->dfl_cdev; + int port_id; + + if (get_user(port_id, (int __user *)arg)) + return -EFAULT; + + return dfl_fpga_cdev_assign_port(cdev, port_id); +} + +static long fme_hdr_ioctl(struct platform_device *pdev, + struct dfl_feature *feature, + unsigned int cmd, unsigned long arg) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); + + switch (cmd) { + case DFL_FPGA_FME_PORT_RELEASE: + return fme_hdr_ioctl_release_port(pdata, arg); + case DFL_FPGA_FME_PORT_ASSIGN: + return fme_hdr_ioctl_assign_port(pdata, arg); + } + + return -ENODEV; +} + static const struct dfl_feature_ops fme_hdr_ops = { .init = fme_hdr_init, .uinit = fme_hdr_uinit, + .ioctl = fme_hdr_ioctl, }; static struct dfl_feature_driver fme_feature_drvs[] = { diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 4b66aaa32b5a..70ffe8b4c157 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -231,16 +231,20 @@ EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del); */ int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id) { - struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev); - int port_id; + struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct dfl_fpga_port_ops *port_ops; + + if (pdata->id != FEATURE_DEV_ID_UNUSED) + return pdata->id == *(int *)pport_id; + port_ops = dfl_fpga_port_ops_get(pdev); if (!port_ops || !port_ops->get_id) return 0; - port_id = port_ops->get_id(pdev); + pdata->id = port_ops->get_id(pdev); dfl_fpga_port_ops_put(port_ops); - return port_id == *(int *)pport_id; + return pdata->id == *(int *)pport_id; } EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id); @@ -474,6 +478,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo) pdata->dev = fdev; pdata->num = binfo->feature_num; pdata->dfl_cdev = binfo->cdev; + pdata->id = FEATURE_DEV_ID_UNUSED; mutex_init(&pdata->lock); lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type], dfl_pdata_key_strings[type]); @@ -973,25 +978,27 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev) { struct dfl_feature_platform_data *pdata, *ptmp; - remove_feature_devs(cdev); - mutex_lock(&cdev->lock); - if (cdev->fme_dev) { - /* the fme should be unregistered. */ - WARN_ON(device_is_registered(cdev->fme_dev)); + if (cdev->fme_dev) put_device(cdev->fme_dev); - } list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { struct platform_device *port_dev = pdata->dev; - /* the port should be unregistered. */ - WARN_ON(device_is_registered(&port_dev->dev)); + /* remove released ports */ + if (!device_is_registered(&port_dev->dev)) { + dfl_id_free(feature_dev_id_type(port_dev), + port_dev->id); + platform_device_put(port_dev); + } + list_del(&pdata->node); put_device(&port_dev->dev); } mutex_unlock(&cdev->lock); + remove_feature_devs(cdev); + fpga_region_unregister(cdev->region); devm_kfree(cdev->parent, cdev); } @@ -1042,6 +1049,88 @@ static int __init dfl_fpga_init(void) return ret; } +/** + * dfl_fpga_cdev_release_port - release a port platform device + * + * @cdev: parent container device. + * @port_id: id of the port platform device. + * + * This function allows user to release a port platform device. This is a + * mandatory step before turn a port from PF into VF for SRIOV support. + * + * Return: 0 on success, negative error code otherwise. + */ +int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id) +{ + struct platform_device *port_pdev; + int ret = -ENODEV; + + mutex_lock(&cdev->lock); + port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id, + dfl_fpga_check_port_id); + if (!port_pdev) + goto unlock_exit; + + if (!device_is_registered(&port_pdev->dev)) { + ret = -EBUSY; + goto put_dev_exit; + } + + ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev)); + if (ret) + goto put_dev_exit; + + platform_device_del(port_pdev); + cdev->released_port_num++; +put_dev_exit: + put_device(&port_pdev->dev); +unlock_exit: + mutex_unlock(&cdev->lock); + return ret; +} +EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port); + +/** + * dfl_fpga_cdev_assign_port - assign a port platform device back + * + * @cdev: parent container device. + * @port_id: id of the port platform device. + * + * This function allows user to assign a port platform device back. This is + * a mandatory step after disable SRIOV support. + * + * Return: 0 on success, negative error code otherwise. + */ +int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id) +{ + struct platform_device *port_pdev; + int ret = -ENODEV; + + mutex_lock(&cdev->lock); + port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id, + dfl_fpga_check_port_id); + if (!port_pdev) + goto unlock_exit; + + if (device_is_registered(&port_pdev->dev)) { + ret = -EBUSY; + goto put_dev_exit; + } + + ret = platform_device_add(port_pdev); + if (ret) + goto put_dev_exit; + + dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev)); + cdev->released_port_num--; +put_dev_exit: + put_device(&port_pdev->dev); +unlock_exit: + mutex_unlock(&cdev->lock); + return ret; +} +EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port); + static void __exit dfl_fpga_exit(void) { dfl_chardev_uinit(); diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index a8b869e9e5b7..6f7855e57869 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -183,6 +183,8 @@ struct dfl_feature { #define DEV_STATUS_IN_USE 0 +#define FEATURE_DEV_ID_UNUSED (-1) + /** * struct dfl_feature_platform_data - platform data for feature devices * @@ -191,6 +193,7 @@ struct dfl_feature { * @cdev: cdev of feature dev. * @dev: ptr to platform device linked with this platform data. * @dfl_cdev: ptr to container device. + * @id: id used for this feature device. * @disable_count: count for port disable. * @num: number for sub features. * @dev_status: dev status (e.g. DEV_STATUS_IN_USE). @@ -203,6 +206,7 @@ struct dfl_feature_platform_data { struct cdev cdev; struct platform_device *dev; struct dfl_fpga_cdev *dfl_cdev; + int id; unsigned int disable_count; unsigned long dev_status; void *private; @@ -373,6 +377,7 @@ void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info); * @fme_dev: FME feature device under this container device. * @lock: mutex lock to protect the port device list. * @port_dev_list: list of all port feature devices under this container device. + * @released_port_num: released port number under this container device. */ struct dfl_fpga_cdev { struct device *parent; @@ -380,6 +385,7 @@ struct dfl_fpga_cdev { struct device *fme_dev; struct mutex lock; struct list_head port_dev_list; + int released_port_num; }; struct dfl_fpga_cdev * @@ -407,4 +413,8 @@ dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data, return pdev; } + +int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id); +int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id); + #endif /* __FPGA_DFL_H */ diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h index 2e324e515c41..ec70a0746e59 100644 --- a/include/uapi/linux/fpga-dfl.h +++ b/include/uapi/linux/fpga-dfl.h @@ -176,4 +176,22 @@ struct dfl_fpga_fme_port_pr { #define DFL_FPGA_FME_PORT_PR _IO(DFL_FPGA_MAGIC, DFL_FME_BASE + 0) +/** + * DFL_FPGA_FME_PORT_RELEASE - _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 1, + * int port_id) + * + * Driver releases the port per Port ID provided by caller. + * Return: 0 on success, -errno on failure. + */ +#define DFL_FPGA_FME_PORT_RELEASE _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 1, int) + +/** + * DFL_FPGA_FME_PORT_ASSIGN - _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 2, + * int port_id) + * + * Driver assigns the port back per Port ID provided by caller. + * Return: 0 on success, -errno on failure. + */ +#define DFL_FPGA_FME_PORT_ASSIGN _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 2, int) + #endif /* _UAPI_LINUX_FPGA_DFL_H */ -- GitLab From bdd4f307956ae7c80a831aed67b0ddd131537481 Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:12 +0800 Subject: [PATCH 1970/7155] fpga: dfl: pci: enable SRIOV support. This patch enables the standard sriov support. It allows user to enable SRIOV (and VFs), then user could pass through accelerators (VFs) into virtual machine or use VFs directly in host. Signed-off-by: Zhang Yi Z Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-3-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl-pci.c | 36 +++++++++++++++++++ drivers/fpga/dfl.c | 82 ++++++++++++++++++++++++++++++++++++++++++ drivers/fpga/dfl.h | 3 +- 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c index 66b5720582bb..89ca292236ad 100644 --- a/drivers/fpga/dfl-pci.c +++ b/drivers/fpga/dfl-pci.c @@ -223,8 +223,43 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid) return ret; } +static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs) +{ + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); + struct dfl_fpga_cdev *cdev = drvdata->cdev; + int ret = 0; + + if (!num_vfs) { + /* + * disable SRIOV and then put released ports back to default + * PF access mode. + */ + pci_disable_sriov(pcidev); + + dfl_fpga_cdev_config_ports_pf(cdev); + + } else { + /* + * before enable SRIOV, put released ports into VF access mode + * first of all. + */ + ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs); + if (ret) + return ret; + + ret = pci_enable_sriov(pcidev, num_vfs); + if (ret) + dfl_fpga_cdev_config_ports_pf(cdev); + } + + return ret; +} + static void cci_pci_remove(struct pci_dev *pcidev) { + if (dev_is_pf(&pcidev->dev)) + cci_pci_sriov_configure(pcidev, 0); + cci_remove_feature_devs(pcidev); pci_disable_pcie_error_reporting(pcidev); } @@ -234,6 +269,7 @@ static struct pci_driver cci_pci_driver = { .id_table = cci_pcie_id_tbl, .probe = cci_pci_probe, .remove = cci_pci_remove, + .sriov_configure = cci_pci_sriov_configure, }; module_pci_driver(cci_pci_driver); diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 70ffe8b4c157..b9137044b667 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -1131,6 +1131,88 @@ int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id) } EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port); +static void config_port_access_mode(struct device *fme_dev, int port_id, + bool is_vf) +{ + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER); + + v = readq(base + FME_HDR_PORT_OFST(port_id)); + + v &= ~FME_PORT_OFST_ACC_CTRL; + v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL, + is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF); + + writeq(v, base + FME_HDR_PORT_OFST(port_id)); +} + +#define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true) +#define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false) + +/** + * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode + * + * @cdev: parent container device. + * + * This function is needed in sriov configuration routine. It could be used to + * configure the all released ports from VF access mode to PF. + */ +void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev) +{ + struct dfl_feature_platform_data *pdata; + + mutex_lock(&cdev->lock); + list_for_each_entry(pdata, &cdev->port_dev_list, node) { + if (device_is_registered(&pdata->dev->dev)) + continue; + + config_port_pf_mode(cdev->fme_dev, pdata->id); + } + mutex_unlock(&cdev->lock); +} +EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf); + +/** + * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode + * + * @cdev: parent container device. + * @num_vfs: VF device number. + * + * This function is needed in sriov configuration routine. It could be used to + * configure the released ports from PF access mode to VF. + * + * Return: 0 on success, negative error code otherwise. + */ +int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs) +{ + struct dfl_feature_platform_data *pdata; + int ret = 0; + + mutex_lock(&cdev->lock); + /* + * can't turn multiple ports into 1 VF device, only 1 port for 1 VF + * device, so if released port number doesn't match VF device number, + * then reject the request with -EINVAL error code. + */ + if (cdev->released_port_num != num_vfs) { + ret = -EINVAL; + goto done; + } + + list_for_each_entry(pdata, &cdev->port_dev_list, node) { + if (device_is_registered(&pdata->dev->dev)) + continue; + + config_port_vf_mode(cdev->fme_dev, pdata->id); + } +done: + mutex_unlock(&cdev->lock); + return ret; +} +EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf); + static void __exit dfl_fpga_exit(void) { dfl_chardev_uinit(); diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index 6f7855e57869..b3f2f53a75d3 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -416,5 +416,6 @@ dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data, int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id); int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id); - +void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev); +int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf); #endif /* __FPGA_DFL_H */ -- GitLab From d2ad5ac1cda7c30c9ded04d0e21aba528f1f96ec Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:13 +0800 Subject: [PATCH 1971/7155] fpga: dfl: afu: add AFU state related sysfs interfaces This patch introduces more sysfs interfaces for Accelerated Function Unit (AFU). These interfaces allow users to read current AFU Power State (APx), read / clear AFU Power (APx) events which are sticky to identify transient APx state, and manage AFU's LTR (latency tolerance reporting). Signed-off-by: Ananda Ravuri Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Alan Tull Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-4-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-platform-dfl-port | 32 ++++ drivers/fpga/dfl-afu-main.c | 137 ++++++++++++++++++ drivers/fpga/dfl.h | 11 ++ 3 files changed, 180 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-platform-dfl-port b/Documentation/ABI/testing/sysfs-platform-dfl-port index 6a92dda517b0..1ab3e6f6154a 100644 --- a/Documentation/ABI/testing/sysfs-platform-dfl-port +++ b/Documentation/ABI/testing/sysfs-platform-dfl-port @@ -14,3 +14,35 @@ Description: Read-only. User can program different PR bitstreams to FPGA Accelerator Function Unit (AFU) for different functions. It returns uuid which could be used to identify which PR bitstream is programmed in this AFU. + +What: /sys/bus/platform/devices/dfl-port.0/power_state +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-only. It reports the APx (AFU Power) state, different APx + means different throttling level. When reading this file, it + returns "0" - Normal / "1" - AP1 / "2" - AP2 / "6" - AP6. + +What: /sys/bus/platform/devices/dfl-port.0/ap1_event +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-write. Read this file for AP1 (AFU Power State 1) event. + It's used to indicate transient AP1 state. Write 1 to this + file to clear AP1 event. + +What: /sys/bus/platform/devices/dfl-port.0/ap2_event +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-write. Read this file for AP2 (AFU Power State 2) event. + It's used to indicate transient AP2 state. Write 1 to this + file to clear AP2 event. + +What: /sys/bus/platform/devices/dfl-port.0/ltr +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-write. Read or set AFU latency tolerance reporting value. + Set ltr to 1 if the AFU can tolerate latency >= 40us or set it + to 0 if it is latency sensitive. diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 68b4d0874b93..12175bbd90c1 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -141,8 +141,145 @@ id_show(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR_RO(id); +static ssize_t +ltr_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_CTRL); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v)); +} + +static ssize_t +ltr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool ltr; + u64 v; + + if (kstrtobool(buf, <r)) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_CTRL); + v &= ~PORT_CTRL_LATENCY; + v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0); + writeq(v, base + PORT_HDR_CTRL); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ltr); + +static ssize_t +ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v)); +} + +static ssize_t +ap1_event_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool clear; + + if (kstrtobool(buf, &clear) || !clear) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ap1_event); + +static ssize_t +ap2_event_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v)); +} + +static ssize_t +ap2_event_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool clear; + + if (kstrtobool(buf, &clear) || !clear) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ap2_event); + +static ssize_t +power_state_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v)); +} +static DEVICE_ATTR_RO(power_state); + static struct attribute *port_hdr_attrs[] = { &dev_attr_id.attr, + &dev_attr_ltr.attr, + &dev_attr_ap1_event.attr, + &dev_attr_ap2_event.attr, + &dev_attr_power_state.attr, NULL, }; ATTRIBUTE_GROUPS(port_hdr); diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index b3f2f53a75d3..6625d73bade8 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -119,6 +119,7 @@ #define PORT_HDR_NEXT_AFU NEXT_AFU #define PORT_HDR_CAP 0x30 #define PORT_HDR_CTRL 0x38 +#define PORT_HDR_STS 0x40 /* Port Capability Register Bitfield */ #define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */ @@ -130,6 +131,16 @@ /* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/ #define PORT_CTRL_LATENCY BIT_ULL(2) #define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */ + +/* Port Status Register Bitfield */ +#define PORT_STS_AP2_EVT BIT_ULL(13) /* AP2 event detected */ +#define PORT_STS_AP1_EVT BIT_ULL(12) /* AP1 event detected */ +#define PORT_STS_PWR_STATE GENMASK_ULL(11, 8) /* AFU power states */ +#define PORT_STS_PWR_STATE_NORM 0 +#define PORT_STS_PWR_STATE_AP1 1 /* 50% throttling */ +#define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */ +#define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */ + /** * struct dfl_fpga_port_ops - port ops * -- GitLab From 15bbb300fcef4e62e4f6063cc29e698796027b98 Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:15 +0800 Subject: [PATCH 1972/7155] fpga: dfl: add id_table for dfl private feature driver This patch adds id_table for each dfl private feature driver, it allows to reuse same private feature driver to match and support multiple dfl private features. Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Moritz Fischer Acked-by: Alan Tull Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-6-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl-afu-main.c | 14 ++++++++++++-- drivers/fpga/dfl-fme-main.c | 11 ++++++++--- drivers/fpga/dfl-fme-pr.c | 7 ++++++- drivers/fpga/dfl-fme.h | 3 ++- drivers/fpga/dfl.c | 18 ++++++++++++++++-- drivers/fpga/dfl.h | 21 +++++++++++++++------ 6 files changed, 59 insertions(+), 15 deletions(-) diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 12175bbd90c1..e50c45ed40ac 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -323,6 +323,11 @@ port_hdr_ioctl(struct platform_device *pdev, struct dfl_feature *feature, return ret; } +static const struct dfl_feature_id port_hdr_id_table[] = { + {.id = PORT_FEATURE_ID_HEADER,}, + {0,} +}; + static const struct dfl_feature_ops port_hdr_ops = { .init = port_hdr_init, .uinit = port_hdr_uinit, @@ -384,6 +389,11 @@ static void port_afu_uinit(struct platform_device *pdev, device_remove_groups(&pdev->dev, port_afu_groups); } +static const struct dfl_feature_id port_afu_id_table[] = { + {.id = PORT_FEATURE_ID_AFU,}, + {0,} +}; + static const struct dfl_feature_ops port_afu_ops = { .init = port_afu_init, .uinit = port_afu_uinit, @@ -391,11 +401,11 @@ static const struct dfl_feature_ops port_afu_ops = { static struct dfl_feature_driver port_feature_drvs[] = { { - .id = PORT_FEATURE_ID_HEADER, + .id_table = port_hdr_id_table, .ops = &port_hdr_ops, }, { - .id = PORT_FEATURE_ID_AFU, + .id_table = port_afu_id_table, .ops = &port_afu_ops, }, { diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index dfea2dee78c3..5fdce548f821 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -145,6 +145,11 @@ static long fme_hdr_ioctl(struct platform_device *pdev, return -ENODEV; } +static const struct dfl_feature_id fme_hdr_id_table[] = { + {.id = FME_FEATURE_ID_HEADER,}, + {0,} +}; + static const struct dfl_feature_ops fme_hdr_ops = { .init = fme_hdr_init, .uinit = fme_hdr_uinit, @@ -153,12 +158,12 @@ static const struct dfl_feature_ops fme_hdr_ops = { static struct dfl_feature_driver fme_feature_drvs[] = { { - .id = FME_FEATURE_ID_HEADER, + .id_table = fme_hdr_id_table, .ops = &fme_hdr_ops, }, { - .id = FME_FEATURE_ID_PR_MGMT, - .ops = &pr_mgmt_ops, + .id_table = fme_pr_mgmt_id_table, + .ops = &fme_pr_mgmt_ops, }, { .ops = NULL, diff --git a/drivers/fpga/dfl-fme-pr.c b/drivers/fpga/dfl-fme-pr.c index 3c71dc3faaf5..a233a53db708 100644 --- a/drivers/fpga/dfl-fme-pr.c +++ b/drivers/fpga/dfl-fme-pr.c @@ -470,7 +470,12 @@ static long fme_pr_ioctl(struct platform_device *pdev, return ret; } -const struct dfl_feature_ops pr_mgmt_ops = { +const struct dfl_feature_id fme_pr_mgmt_id_table[] = { + {.id = FME_FEATURE_ID_PR_MGMT,}, + {0} +}; + +const struct dfl_feature_ops fme_pr_mgmt_ops = { .init = pr_mgmt_init, .uinit = pr_mgmt_uinit, .ioctl = fme_pr_ioctl, diff --git a/drivers/fpga/dfl-fme.h b/drivers/fpga/dfl-fme.h index 5394a216c5c0..e4131e857dae 100644 --- a/drivers/fpga/dfl-fme.h +++ b/drivers/fpga/dfl-fme.h @@ -33,6 +33,7 @@ struct dfl_fme { struct dfl_feature_platform_data *pdata; }; -extern const struct dfl_feature_ops pr_mgmt_ops; +extern const struct dfl_feature_ops fme_pr_mgmt_ops; +extern const struct dfl_feature_id fme_pr_mgmt_id_table[]; #endif /* __DFL_FME_H */ diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index b9137044b667..87eaef6d2723 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -281,6 +281,21 @@ static int dfl_feature_instance_init(struct platform_device *pdev, return ret; } +static bool dfl_feature_drv_match(struct dfl_feature *feature, + struct dfl_feature_driver *driver) +{ + const struct dfl_feature_id *ids = driver->id_table; + + if (ids) { + while (ids->id) { + if (ids->id == feature->id) + return true; + ids++; + } + } + return false; +} + /** * dfl_fpga_dev_feature_init - init for sub features of dfl feature device * @pdev: feature device. @@ -301,8 +316,7 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev, while (drv->ops) { dfl_fpga_dev_for_each_feature(pdata, feature) { - /* match feature and drv using id */ - if (feature->id == drv->id) { + if (dfl_feature_drv_match(feature, drv)) { ret = dfl_feature_instance_init(pdev, pdata, feature, drv); if (ret) diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index 6625d73bade8..856ea4ebc445 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -30,8 +30,8 @@ /* plus one for fme device */ #define MAX_DFL_FEATURE_DEV_NUM (MAX_DFL_FPGA_PORT_NUM + 1) -/* Reserved 0x0 for Header Group Register and 0xff for AFU */ -#define FEATURE_ID_FIU_HEADER 0x0 +/* Reserved 0xfe for Header Group Register and 0xff for AFU */ +#define FEATURE_ID_FIU_HEADER 0xfe #define FEATURE_ID_AFU 0xff #define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER @@ -165,13 +165,22 @@ void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops); int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id); /** - * struct dfl_feature_driver - sub feature's driver + * struct dfl_feature_id - dfl private feature id * - * @id: sub feature id. - * @ops: ops of this sub feature. + * @id: unique dfl private feature id. */ -struct dfl_feature_driver { +struct dfl_feature_id { u64 id; +}; + +/** + * struct dfl_feature_driver - dfl private feature driver + * + * @id_table: id_table for dfl private features supported by this driver. + * @ops: ops of this dfl private feature driver. + */ +struct dfl_feature_driver { + const struct dfl_feature_id *id_table; const struct dfl_feature_ops *ops; }; -- GitLab From 3c51ff772278d291117dae9cad09ddef07e0d504 Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:18 +0800 Subject: [PATCH 1973/7155] fpga: dfl: make uinit callback optional This patch makes uinit callback of sub features optional. With this change, people don't need to prepare any empty uinit callback. Signed-off-by: Wu Hao Link: https://lore.kernel.org/r/1564914022-3710-9-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 87eaef6d2723..c0512afc4ed7 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -259,7 +259,8 @@ void dfl_fpga_dev_feature_uinit(struct platform_device *pdev) dfl_fpga_dev_for_each_feature(pdata, feature) if (feature->ops) { - feature->ops->uinit(pdev, feature); + if (feature->ops->uinit) + feature->ops->uinit(pdev, feature); feature->ops = NULL; } } -- GitLab From 52eb6d31a1c2e85a3eaf08ab599c9ad58c890c28 Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:20 +0800 Subject: [PATCH 1974/7155] fpga: dfl: fme: add capability sysfs interfaces This patch adds 3 read-only sysfs interfaces for FPGA Management Engine (FME) block for capabilities including cache_size, fabric_version and socket_id. Signed-off-by: Luwei Kang Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Alan Tull Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-11-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-platform-dfl-fme | 23 +++++++++ drivers/fpga/dfl-fme-main.c | 48 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-platform-dfl-fme b/Documentation/ABI/testing/sysfs-platform-dfl-fme index 8fa4febfa4b2..65372aae4a7e 100644 --- a/Documentation/ABI/testing/sysfs-platform-dfl-fme +++ b/Documentation/ABI/testing/sysfs-platform-dfl-fme @@ -21,3 +21,26 @@ Contact: Wu Hao Description: Read-only. It returns Bitstream (static FPGA region) meta data, which includes the synthesis date, seed and other information of this static FPGA region. + +What: /sys/bus/platform/devices/dfl-fme.0/cache_size +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-only. It returns cache size of this FPGA device. + +What: /sys/bus/platform/devices/dfl-fme.0/fabric_version +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-only. It returns fabric version of this FPGA device. + Userspace applications need this information to select + best data channels per different fabric design. + +What: /sys/bus/platform/devices/dfl-fme.0/socket_id +Date: August 2019 +KernelVersion: 5.4 +Contact: Wu Hao +Description: Read-only. It returns socket_id to indicate which socket + this FPGA belongs to, only valid for integrated solution. + User only needs this information, in case standard numa node + can't provide correct information. diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index 5fdce548f821..f033f1cfd3ed 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -73,10 +73,58 @@ static ssize_t bitstream_metadata_show(struct device *dev, } static DEVICE_ATTR_RO(bitstream_metadata); +static ssize_t cache_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); + + v = readq(base + FME_HDR_CAP); + + return sprintf(buf, "%u\n", + (unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v)); +} +static DEVICE_ATTR_RO(cache_size); + +static ssize_t fabric_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); + + v = readq(base + FME_HDR_CAP); + + return sprintf(buf, "%u\n", + (unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v)); +} +static DEVICE_ATTR_RO(fabric_version); + +static ssize_t socket_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); + + v = readq(base + FME_HDR_CAP); + + return sprintf(buf, "%u\n", + (unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v)); +} +static DEVICE_ATTR_RO(socket_id); + static struct attribute *fme_hdr_attrs[] = { &dev_attr_ports_num.attr, &dev_attr_bitstream_id.attr, &dev_attr_bitstream_metadata.attr, + &dev_attr_cache_size.attr, + &dev_attr_fabric_version.attr, + &dev_attr_socket_id.attr, NULL, }; ATTRIBUTE_GROUPS(fme_hdr); -- GitLab From f51cf9e23b70aa01fff2473d7bc8535570a8afc8 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 31 Jul 2019 07:16:22 -0700 Subject: [PATCH 1975/7155] misc: Remove spear13xx pcie gadget driver This driver has been marked broken since 2013, see commit 98097858ccf3 ("misc: mark spear13xx-pcie-gadget as broken"). Let's remove this file now that it's been more than 5 years of existing in a broken state. Cc: Arnd Bergmann Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/5d41a2b7.1c69fb81.c8d56.edb6@mx.google.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 9 - drivers/misc/Makefile | 1 - drivers/misc/spear13xx_pcie_gadget.c | 797 --------------------------- 3 files changed, 807 deletions(-) delete mode 100644 drivers/misc/spear13xx_pcie_gadget.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6abfc8e92fcc..964e2242f772 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -375,15 +375,6 @@ config DS1682 This driver can also be built as a module. If so, the module will be called ds1682. -config SPEAR13XX_PCIE_GADGET - bool "PCIe gadget support for SPEAr13XX platform" - depends on ARCH_SPEAR13XX && BROKEN - help - This option enables gadget support for PCIe controller. If - board file defines any controller as PCIe endpoint then a sysfs - entry will be created for that controller. User can use these - sysfs node to configure PCIe EP as per his requirements. - config VMWARE_BALLOON tristate "VMware Balloon Driver" depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index abd8ae249746..9e1eaf523d6e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-y += eeprom/ obj-y += cb710/ -obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o obj-$(CONFIG_PCH_PHUB) += pch_phub.o obj-y += ti-st/ diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c deleted file mode 100644 index ee120dcbb3e6..000000000000 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * drivers/misc/spear13xx_pcie_gadget.c - * - * Copyright (C) 2010 ST Microelectronics - * Pratyush Anand - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IN0_MEM_SIZE (200 * 1024 * 1024 - 1) -/* In current implementation address translation is done using IN0 only. - * So IN1 start address and IN0 end address has been kept same -*/ -#define IN1_MEM_SIZE (0 * 1024 * 1024 - 1) -#define IN_IO_SIZE (20 * 1024 * 1024 - 1) -#define IN_CFG0_SIZE (12 * 1024 * 1024 - 1) -#define IN_CFG1_SIZE (12 * 1024 * 1024 - 1) -#define IN_MSG_SIZE (12 * 1024 * 1024 - 1) -/* Keep default BAR size as 4K*/ -/* AORAM would be mapped by default*/ -#define INBOUND_ADDR_MASK (SPEAR13XX_SYSRAM1_SIZE - 1) - -#define INT_TYPE_NO_INT 0 -#define INT_TYPE_INTX 1 -#define INT_TYPE_MSI 2 -struct spear_pcie_gadget_config { - void __iomem *base; - void __iomem *va_app_base; - void __iomem *va_dbi_base; - char int_type[10]; - ulong requested_msi; - ulong configured_msi; - ulong bar0_size; - ulong bar0_rw_offset; - void __iomem *va_bar0_address; -}; - -struct pcie_gadget_target { - struct configfs_subsystem subsys; - struct spear_pcie_gadget_config config; -}; - -struct pcie_gadget_target_attr { - struct configfs_attribute attr; - ssize_t (*show)(struct spear_pcie_gadget_config *config, - char *buf); - ssize_t (*store)(struct spear_pcie_gadget_config *config, - const char *buf, - size_t count); -}; - -static void enable_dbi_access(struct pcie_app_reg __iomem *app_reg) -{ - /* Enable DBI access */ - writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID), - &app_reg->slv_armisc); - writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID), - &app_reg->slv_awmisc); - -} - -static void disable_dbi_access(struct pcie_app_reg __iomem *app_reg) -{ - /* disable DBI access */ - writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID), - &app_reg->slv_armisc); - writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID), - &app_reg->slv_awmisc); - -} - -static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config, - int where, int size, u32 *val) -{ - struct pcie_app_reg __iomem *app_reg = config->va_app_base; - ulong va_address; - - /* Enable DBI access */ - enable_dbi_access(app_reg); - - va_address = (ulong)config->va_dbi_base + (where & ~0x3); - - *val = readl(va_address); - - if (size == 1) - *val = (*val >> (8 * (where & 3))) & 0xff; - else if (size == 2) - *val = (*val >> (8 * (where & 3))) & 0xffff; - - /* Disable DBI access */ - disable_dbi_access(app_reg); -} - -static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config, - int where, int size, u32 val) -{ - struct pcie_app_reg __iomem *app_reg = config->va_app_base; - ulong va_address; - - /* Enable DBI access */ - enable_dbi_access(app_reg); - - va_address = (ulong)config->va_dbi_base + (where & ~0x3); - - if (size == 4) - writel(val, va_address); - else if (size == 2) - writew(val, va_address + (where & 2)); - else if (size == 1) - writeb(val, va_address + (where & 3)); - - /* Disable DBI access */ - disable_dbi_access(app_reg); -} - -#define PCI_FIND_CAP_TTL 48 - -static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config, - u32 pos, int cap, int *ttl) -{ - u32 id; - - while ((*ttl)--) { - spear_dbi_read_reg(config, pos, 1, &pos); - if (pos < 0x40) - break; - pos &= ~3; - spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id); - if (id == 0xff) - break; - if (id == cap) - return pos; - pos += PCI_CAP_LIST_NEXT; - } - return 0; -} - -static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config, - u32 pos, int cap) -{ - int ttl = PCI_FIND_CAP_TTL; - - return pci_find_own_next_cap_ttl(config, pos, cap, &ttl); -} - -static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config, - u8 hdr_type) -{ - u32 status; - - spear_dbi_read_reg(config, PCI_STATUS, 2, &status); - if (!(status & PCI_STATUS_CAP_LIST)) - return 0; - - switch (hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - case PCI_HEADER_TYPE_BRIDGE: - return PCI_CAPABILITY_LIST; - case PCI_HEADER_TYPE_CARDBUS: - return PCI_CB_CAPABILITY_LIST; - default: - return 0; - } - - return 0; -} - -/* - * Tell if a device supports a given PCI capability. - * Returns the address of the requested capability structure within the - * device's PCI configuration space or 0 in case the device does not - * support it. Possible values for @cap: - * - * %PCI_CAP_ID_PM Power Management - * %PCI_CAP_ID_AGP Accelerated Graphics Port - * %PCI_CAP_ID_VPD Vital Product Data - * %PCI_CAP_ID_SLOTID Slot Identification - * %PCI_CAP_ID_MSI Message Signalled Interrupts - * %PCI_CAP_ID_CHSWP CompactPCI HotSwap - * %PCI_CAP_ID_PCIX PCI-X - * %PCI_CAP_ID_EXP PCI Express - */ -static int pci_find_own_capability(struct spear_pcie_gadget_config *config, - int cap) -{ - u32 pos; - u32 hdr_type; - - spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type); - - pos = pci_find_own_cap_start(config, hdr_type); - if (pos) - pos = pci_find_own_next_cap(config, pos, cap); - - return pos; -} - -static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id) -{ - return 0; -} - -/* - * configfs interfaces show/store functions - */ - -static struct pcie_gadget_target *to_target(struct config_item *item) -{ - return item ? - container_of(to_configfs_subsystem(to_config_group(item)), - struct pcie_gadget_target, subsys) : NULL; -} - -static ssize_t pcie_gadget_link_show(struct config_item *item, char *buf) -{ - struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base; - - if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID)) - return sprintf(buf, "UP"); - else - return sprintf(buf, "DOWN"); -} - -static ssize_t pcie_gadget_link_store(struct config_item *item, - const char *buf, size_t count) -{ - struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base; - - if (sysfs_streq(buf, "UP")) - writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID), - &app_reg->app_ctrl_0); - else if (sysfs_streq(buf, "DOWN")) - writel(readl(&app_reg->app_ctrl_0) - & ~(1 << APP_LTSSM_ENABLE_ID), - &app_reg->app_ctrl_0); - else - return -EINVAL; - return count; -} - -static ssize_t pcie_gadget_int_type_show(struct config_item *item, char *buf) -{ - return sprintf(buf, "%s", to_target(item)->int_type); -} - -static ssize_t pcie_gadget_int_type_store(struct config_item *item, - const char *buf, size_t count) -{ - struct spear_pcie_gadget_config *config = to_target(item) - u32 cap, vec, flags; - ulong vector; - - if (sysfs_streq(buf, "INTA")) - spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1); - - else if (sysfs_streq(buf, "MSI")) { - vector = config->requested_msi; - vec = 0; - while (vector > 1) { - vector /= 2; - vec++; - } - spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0); - cap = pci_find_own_capability(config, PCI_CAP_ID_MSI); - spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags); - flags &= ~PCI_MSI_FLAGS_QMASK; - flags |= vec << 1; - spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags); - } else - return -EINVAL; - - strcpy(config->int_type, buf); - - return count; -} - -static ssize_t pcie_gadget_no_of_msi_show(struct config_item *item, char *buf) -{ - struct spear_pcie_gadget_config *config = to_target(item) - struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base; - u32 cap, vec, flags; - ulong vector; - - if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID)) - != (1 << CFG_MSI_EN_ID)) - vector = 0; - else { - cap = pci_find_own_capability(config, PCI_CAP_ID_MSI); - spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags); - flags &= ~PCI_MSI_FLAGS_QSIZE; - vec = flags >> 4; - vector = 1; - while (vec--) - vector *= 2; - } - config->configured_msi = vector; - - return sprintf(buf, "%lu", vector); -} - -static ssize_t pcie_gadget_no_of_msi_store(struct config_item *item, - const char *buf, size_t count) -{ - int ret; - - ret = kstrtoul(buf, 0, &to_target(item)->requested_msi); - if (ret) - return ret; - - if (config->requested_msi > 32) - config->requested_msi = 32; - - return count; -} - -static ssize_t pcie_gadget_inta_store(struct config_item *item, - const char *buf, size_t count) -{ - struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base; - ulong en; - int ret; - - ret = kstrtoul(buf, 0, &en); - if (ret) - return ret; - - if (en) - writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID), - &app_reg->app_ctrl_0); - else - writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID), - &app_reg->app_ctrl_0); - - return count; -} - -static ssize_t pcie_gadget_send_msi_store(struct config_item *item, - const char *buf, size_t count) -{ - struct spear_pcie_gadget_config *config = to_target(item) - struct pcie_app_reg __iomem *app_reg = config->va_app_base; - ulong vector; - u32 ven_msi; - int ret; - - ret = kstrtoul(buf, 0, &vector); - if (ret) - return ret; - - if (!config->configured_msi) - return -EINVAL; - - if (vector >= config->configured_msi) - return -EINVAL; - - ven_msi = readl(&app_reg->ven_msi_1); - ven_msi &= ~VEN_MSI_FUN_NUM_MASK; - ven_msi |= 0 << VEN_MSI_FUN_NUM_ID; - ven_msi &= ~VEN_MSI_TC_MASK; - ven_msi |= 0 << VEN_MSI_TC_ID; - ven_msi &= ~VEN_MSI_VECTOR_MASK; - ven_msi |= vector << VEN_MSI_VECTOR_ID; - - /* generating interrupt for msi vector */ - ven_msi |= VEN_MSI_REQ_EN; - writel(ven_msi, &app_reg->ven_msi_1); - udelay(1); - ven_msi &= ~VEN_MSI_REQ_EN; - writel(ven_msi, &app_reg->ven_msi_1); - - return count; -} - -static ssize_t pcie_gadget_vendor_id_show(struct config_item *item, char *buf) -{ - u32 id; - - spear_dbi_read_reg(to_target(item), PCI_VENDOR_ID, 2, &id); - - return sprintf(buf, "%x", id); -} - -static ssize_t pcie_gadget_vendor_id_store(struct config_item *item, - const char *buf, size_t count) -{ - ulong id; - int ret; - - ret = kstrtoul(buf, 0, &id); - if (ret) - return ret; - - spear_dbi_write_reg(to_target(item), PCI_VENDOR_ID, 2, id); - - return count; -} - -static ssize_t pcie_gadget_device_id_show(struct config_item *item, char *buf) -{ - u32 id; - - spear_dbi_read_reg(to_target(item), PCI_DEVICE_ID, 2, &id); - - return sprintf(buf, "%x", id); -} - -static ssize_t pcie_gadget_device_id_store(struct config_item *item, - const char *buf, size_t count) -{ - ulong id; - int ret; - - ret = kstrtoul(buf, 0, &id); - if (ret) - return ret; - - spear_dbi_write_reg(to_target(item), PCI_DEVICE_ID, 2, id); - - return count; -} - -static ssize_t pcie_gadget_bar0_size_show(struct config_item *item, char *buf) -{ - return sprintf(buf, "%lx", to_target(item)->bar0_size); -} - -static ssize_t pcie_gadget_bar0_size_store(struct config_item *item, - const char *buf, size_t count) -{ - struct spear_pcie_gadget_config *config = to_target(item) - ulong size; - u32 pos, pos1; - u32 no_of_bit = 0; - int ret; - - ret = kstrtoul(buf, 0, &size); - if (ret) - return ret; - - /* min bar size is 256 */ - if (size <= 0x100) - size = 0x100; - /* max bar size is 1MB*/ - else if (size >= 0x100000) - size = 0x100000; - else { - pos = 0; - pos1 = 0; - while (pos < 21) { - pos = find_next_bit((ulong *)&size, 21, pos); - if (pos != 21) - pos1 = pos + 1; - pos++; - no_of_bit++; - } - if (no_of_bit == 2) - pos1--; - - size = 1 << pos1; - } - config->bar0_size = size; - spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1); - - return count; -} - -static ssize_t pcie_gadget_bar0_address_show(struct config_item *item, - char *buf) -{ - struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base; - - u32 address = readl(&app_reg->pim0_mem_addr_start); - - return sprintf(buf, "%x", address); -} - -static ssize_t pcie_gadget_bar0_address_store(struct config_item *item, - const char *buf, size_t count) -{ - struct spear_pcie_gadget_config *config = to_target(item) - struct pcie_app_reg __iomem *app_reg = config->va_app_base; - ulong address; - int ret; - - ret = kstrtoul(buf, 0, &address); - if (ret) - return ret; - - address &= ~(config->bar0_size - 1); - if (config->va_bar0_address) - iounmap(config->va_bar0_address); - config->va_bar0_address = ioremap(address, config->bar0_size); - if (!config->va_bar0_address) - return -ENOMEM; - - writel(address, &app_reg->pim0_mem_addr_start); - - return count; -} - -static ssize_t pcie_gadget_bar0_rw_offset_show(struct config_item *item, - char *buf) -{ - return sprintf(buf, "%lx", to_target(item)->bar0_rw_offset); -} - -static ssize_t pcie_gadget_bar0_rw_offset_store(struct config_item *item, - const char *buf, size_t count) -{ - ulong offset; - int ret; - - ret = kstrtoul(buf, 0, &offset); - if (ret) - return ret; - - if (offset % 4) - return -EINVAL; - - to_target(item)->bar0_rw_offset = offset; - - return count; -} - -static ssize_t pcie_gadget_bar0_data_show(struct config_item *item, char *buf) -{ - struct spear_pcie_gadget_config *config = to_target(item) - ulong data; - - if (!config->va_bar0_address) - return -ENOMEM; - - data = readl((ulong)config->va_bar0_address + config->bar0_rw_offset); - - return sprintf(buf, "%lx", data); -} - -static ssize_t pcie_gadget_bar0_data_store(struct config_item *item, - const char *buf, size_t count) -{ - struct spear_pcie_gadget_config *config = to_target(item) - ulong data; - int ret; - - ret = kstrtoul(buf, 0, &data); - if (ret) - return ret; - - if (!config->va_bar0_address) - return -ENOMEM; - - writel(data, (ulong)config->va_bar0_address + config->bar0_rw_offset); - - return count; -} - -CONFIGFS_ATTR(pcie_gadget_, link); -CONFIGFS_ATTR(pcie_gadget_, int_type); -CONFIGFS_ATTR(pcie_gadget_, no_of_msi); -CONFIGFS_ATTR_WO(pcie_gadget_, inta); -CONFIGFS_ATTR_WO(pcie_gadget_, send_msi); -CONFIGFS_ATTR(pcie_gadget_, vendor_id); -CONFIGFS_ATTR(pcie_gadget_, device_id); -CONFIGFS_ATTR(pcie_gadget_, bar0_size); -CONFIGFS_ATTR(pcie_gadget_, bar0_address); -CONFIGFS_ATTR(pcie_gadget_, bar0_rw_offset); -CONFIGFS_ATTR(pcie_gadget_, bar0_data); - -static struct configfs_attribute *pcie_gadget_target_attrs[] = { - &pcie_gadget_attr_link, - &pcie_gadget_attr_int_type, - &pcie_gadget_attr_no_of_msi, - &pcie_gadget_attr_inta, - &pcie_gadget_attr_send_msi, - &pcie_gadget_attr_vendor_id, - &pcie_gadget_attr_device_id, - &pcie_gadget_attr_bar0_size, - &pcie_gadget_attr_bar0_address, - &pcie_gadget_attr_bar0_rw_offset, - &pcie_gadget_attr_bar0_data, - NULL, -}; - -static struct config_item_type pcie_gadget_target_type = { - .ct_attrs = pcie_gadget_target_attrs, - .ct_owner = THIS_MODULE, -}; - -static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config) -{ - struct pcie_app_reg __iomem *app_reg = config->va_app_base; - - /*setup registers for outbound translation */ - - writel(config->base, &app_reg->in0_mem_addr_start); - writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE, - &app_reg->in0_mem_addr_limit); - writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start); - writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE, - &app_reg->in1_mem_addr_limit); - writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start); - writel(app_reg->in_io_addr_start + IN_IO_SIZE, - &app_reg->in_io_addr_limit); - writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start); - writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE, - &app_reg->in_cfg0_addr_limit); - writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start); - writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE, - &app_reg->in_cfg1_addr_limit); - writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start); - writel(app_reg->in_msg_addr_start + IN_MSG_SIZE, - &app_reg->in_msg_addr_limit); - - writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start); - writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start); - writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start); - - /*setup registers for inbound translation */ - - /* Keep AORAM mapped at BAR0 as default */ - config->bar0_size = INBOUND_ADDR_MASK + 1; - spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK); - spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC); - config->va_bar0_address = ioremap(SPEAR13XX_SYSRAM1_BASE, - config->bar0_size); - - writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start); - writel(0, &app_reg->pim1_mem_addr_start); - writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit); - - writel(0x0, &app_reg->pim_io_addr_start); - writel(0x0, &app_reg->pim_io_addr_start); - writel(0x0, &app_reg->pim_rom_addr_start); - - writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID) - | ((u32)1 << REG_TRANSLATION_ENABLE), - &app_reg->app_ctrl_0); - /* disable all rx interrupts */ - writel(0, &app_reg->int_mask); - - /* Select INTA as default*/ - spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1); -} - -static int spear_pcie_gadget_probe(struct platform_device *pdev) -{ - struct resource *res0, *res1; - unsigned int status = 0; - int irq; - struct clk *clk; - static struct pcie_gadget_target *target; - struct spear_pcie_gadget_config *config; - struct config_item *cg_item; - struct configfs_subsystem *subsys; - - target = devm_kzalloc(&pdev->dev, sizeof(*target), GFP_KERNEL); - if (!target) { - dev_err(&pdev->dev, "out of memory\n"); - return -ENOMEM; - } - - cg_item = &target->subsys.su_group.cg_item; - sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id); - cg_item->ci_type = &pcie_gadget_target_type; - config = &target->config; - - /* get resource for application registers*/ - res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - config->va_app_base = devm_ioremap_resource(&pdev->dev, res0); - if (IS_ERR(config->va_app_base)) { - dev_err(&pdev->dev, "ioremap fail\n"); - return PTR_ERR(config->va_app_base); - } - - /* get resource for dbi registers*/ - res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - config->base = (void __iomem *)res1->start; - - config->va_dbi_base = devm_ioremap_resource(&pdev->dev, res1); - if (IS_ERR(config->va_dbi_base)) { - dev_err(&pdev->dev, "ioremap fail\n"); - return PTR_ERR(config->va_dbi_base); - } - - platform_set_drvdata(pdev, target); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no update irq?\n"); - return irq; - } - - status = devm_request_irq(&pdev->dev, irq, spear_pcie_gadget_irq, - 0, pdev->name, NULL); - if (status) { - dev_err(&pdev->dev, - "pcie gadget interrupt IRQ%d already claimed\n", irq); - return status; - } - - /* Register configfs hooks */ - subsys = &target->subsys; - config_group_init(&subsys->su_group); - mutex_init(&subsys->su_mutex); - status = configfs_register_subsystem(subsys); - if (status) - return status; - - /* - * init basic pcie application registers - * do not enable clock if it is PCIE0.Ideally , all controller should - * have been independent from others with respect to clock. But PCIE1 - * and 2 depends on PCIE0.So PCIE0 clk is provided during board init. - */ - if (pdev->id == 1) { - /* - * Ideally CFG Clock should have been also enabled here. But - * it is done currently during board init routne - */ - clk = clk_get_sys("pcie1", NULL); - if (IS_ERR(clk)) { - pr_err("%s:couldn't get clk for pcie1\n", __func__); - return PTR_ERR(clk); - } - status = clk_enable(clk); - if (status) { - pr_err("%s:couldn't enable clk for pcie1\n", __func__); - return status; - } - } else if (pdev->id == 2) { - /* - * Ideally CFG Clock should have been also enabled here. But - * it is done currently during board init routne - */ - clk = clk_get_sys("pcie2", NULL); - if (IS_ERR(clk)) { - pr_err("%s:couldn't get clk for pcie2\n", __func__); - return PTR_ERR(clk); - } - status = clk_enable(clk); - if (status) { - pr_err("%s:couldn't enable clk for pcie2\n", __func__); - return status; - } - } - spear13xx_pcie_device_init(config); - - return 0; -} - -static int spear_pcie_gadget_remove(struct platform_device *pdev) -{ - static struct pcie_gadget_target *target; - - target = platform_get_drvdata(pdev); - - configfs_unregister_subsystem(&target->subsys); - - return 0; -} - -static void spear_pcie_gadget_shutdown(struct platform_device *pdev) -{ -} - -static struct platform_driver spear_pcie_gadget_driver = { - .probe = spear_pcie_gadget_probe, - .remove = spear_pcie_gadget_remove, - .shutdown = spear_pcie_gadget_shutdown, - .driver = { - .name = "pcie-gadget-spear", - .bus = &platform_bus_type - }, -}; - -module_platform_driver(spear_pcie_gadget_driver); - -MODULE_ALIAS("platform:pcie-gadget-spear"); -MODULE_AUTHOR("Pratyush Anand"); -MODULE_LICENSE("GPL"); -- GitLab From 741172d18e8a9cffb5c9c9c236d1311b6fcf6111 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Fri, 2 Aug 2019 12:42:28 +0100 Subject: [PATCH 1976/7155] iio: light: noa1305: Add support for NOA1305 This driver adds the initial support for the ON Semiconductor NOA1305 Ambient Light Sensor. Originally written by Sergei Miroshnichenko. Found here: https://github.com/EmcraftSystems/linux-upstream/commit/196d6cf897e632d2cb82d45484bd7a1bfdd5b6d9 Signed-off-by: Sergei M Signed-off-by: Martyn Welch Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 11 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/noa1305.c | 312 ++++++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 drivers/iio/light/noa1305.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index e3fd00b595d0..08d7e1ef2186 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -303,6 +303,7 @@ config MAX44000 config MAX44009 tristate "MAX44009 Ambient Light Sensor" depends on I2C + select REGMAP_I2C help Say Y here if you want to build support for Maxim Integrated's MAX44009 ambient light sensor device. @@ -310,6 +311,16 @@ config MAX44009 To compile this driver as a module, choose M here: the module will be called max44009. +config NOA1305 + tristate "ON Semiconductor NOA1305 ambient light sensor" + depends on I2C + help + Say Y here if you want to build support for the ON Semiconductor + NOA1305 ambient light sensor. + + To compile this driver as a module, choose M here: + The module will be called noa1305. + config OPT3001 tristate "Texas Instruments OPT3001 Light Sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index e40794fbb435..00d1f9b98f39 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_LV0104CS) += lv0104cs.o obj-$(CONFIG_MAX44000) += max44000.o obj-$(CONFIG_MAX44009) += max44009.o +obj-$(CONFIG_NOA1305) += noa1305.o obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_RPR0521) += rpr0521.o diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c new file mode 100644 index 000000000000..7b859ae1044d --- /dev/null +++ b/drivers/iio/light/noa1305.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for ON Semiconductor NOA1305 ambient light sensor + * + * Copyright (C) 2016 Emcraft Systems + * Copyright (C) 2019 Collabora Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOA1305_REG_POWER_CONTROL 0x0 +#define NOA1305_POWER_CONTROL_DOWN 0x00 +#define NOA1305_POWER_CONTROL_ON 0x08 +#define NOA1305_REG_RESET 0x1 +#define NOA1305_RESET_RESET 0x10 +#define NOA1305_REG_INTEGRATION_TIME 0x2 +#define NOA1305_INTEGR_TIME_800MS 0x00 +#define NOA1305_INTEGR_TIME_400MS 0x01 +#define NOA1305_INTEGR_TIME_200MS 0x02 +#define NOA1305_INTEGR_TIME_100MS 0x03 +#define NOA1305_INTEGR_TIME_50MS 0x04 +#define NOA1305_INTEGR_TIME_25MS 0x05 +#define NOA1305_INTEGR_TIME_12_5MS 0x06 +#define NOA1305_INTEGR_TIME_6_25MS 0x07 +#define NOA1305_REG_INT_SELECT 0x3 +#define NOA1305_INT_SEL_ACTIVE_HIGH 0x01 +#define NOA1305_INT_SEL_ACTIVE_LOW 0x02 +#define NOA1305_INT_SEL_INACTIVE 0x03 +#define NOA1305_REG_INT_THRESH_LSB 0x4 +#define NOA1305_REG_INT_THRESH_MSB 0x5 +#define NOA1305_REG_ALS_DATA_LSB 0x6 +#define NOA1305_REG_ALS_DATA_MSB 0x7 +#define NOA1305_REG_DEVICE_ID_LSB 0x8 +#define NOA1305_REG_DEVICE_ID_MSB 0x9 + +#define NOA1305_DEVICE_ID 0x0519 +#define NOA1305_DRIVER_NAME "noa1305" + +struct noa1305_priv { + struct i2c_client *client; + struct regmap *regmap; + struct regulator *vin_reg; +}; + +static int noa1305_measure(struct noa1305_priv *priv) +{ + __le16 data; + int ret; + + ret = regmap_bulk_read(priv->regmap, NOA1305_REG_ALS_DATA_LSB, &data, + 2); + if (ret < 0) + return ret; + + return le16_to_cpu(data); +} + +static int noa1305_scale(struct noa1305_priv *priv, int *val, int *val2) +{ + int data; + int ret; + + ret = regmap_read(priv->regmap, NOA1305_REG_INTEGRATION_TIME, &data); + if (ret < 0) + return ret; + + /* + * Lux = count / ( * ) + * + * Integration Constant = 7.7 + * Integration Time in Seconds + */ + switch (data) { + case NOA1305_INTEGR_TIME_800MS: + *val = 100; + *val2 = 77 * 8; + break; + case NOA1305_INTEGR_TIME_400MS: + *val = 100; + *val2 = 77 * 4; + case NOA1305_INTEGR_TIME_200MS: + *val = 100; + *val2 = 77 * 2; + break; + case NOA1305_INTEGR_TIME_100MS: + *val = 100; + *val2 = 77; + break; + case NOA1305_INTEGR_TIME_50MS: + *val = 1000; + *val2 = 77 * 5; + break; + case NOA1305_INTEGR_TIME_25MS: + *val = 10000; + *val2 = 77 * 25; + break; + case NOA1305_INTEGR_TIME_12_5MS: + *val = 100000; + *val2 = 77 * 125; + break; + case NOA1305_INTEGR_TIME_6_25MS: + *val = 1000000; + *val2 = 77 * 625; + break; + default: + return -EINVAL; + } + + return IIO_VAL_FRACTIONAL; +} + +static const struct iio_chan_spec noa1305_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + } +}; + +static int noa1305_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = -EINVAL; + struct noa1305_priv *priv = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_LIGHT: + ret = noa1305_measure(priv); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + default: + break; + } + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_LIGHT: + return noa1305_scale(priv, val, val2); + default: + break; + } + break; + default: + break; + } + + return ret; +} + +static const struct iio_info noa1305_info = { + .read_raw = noa1305_read_raw, +}; + +static bool noa1305_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NOA1305_REG_POWER_CONTROL: + case NOA1305_REG_RESET: + case NOA1305_REG_INTEGRATION_TIME: + case NOA1305_REG_INT_SELECT: + case NOA1305_REG_INT_THRESH_LSB: + case NOA1305_REG_INT_THRESH_MSB: + return true; + default: + return false; + } +} + +static const struct regmap_config noa1305_regmap_config = { + .name = NOA1305_DRIVER_NAME, + .reg_bits = 8, + .val_bits = 8, + .max_register = NOA1305_REG_DEVICE_ID_MSB, + .writeable_reg = noa1305_writable_reg, +}; + +static void noa1305_reg_remove(void *data) +{ + struct noa1305_priv *priv = data; + + regulator_disable(priv->vin_reg); +} + +static int noa1305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct noa1305_priv *priv; + struct iio_dev *indio_dev; + struct regmap *regmap; + __le16 data; + unsigned int dev_id; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &noa1305_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Regmap initialization failed.\n"); + return PTR_ERR(regmap); + } + + priv = iio_priv(indio_dev); + + priv->vin_reg = devm_regulator_get(&client->dev, "vin"); + if (IS_ERR(priv->vin_reg)) { + dev_err(&client->dev, "get regulator vin failed\n"); + return PTR_ERR(priv->vin_reg); + } + + ret = regulator_enable(priv->vin_reg); + if (ret) { + dev_err(&client->dev, "enable regulator vin failed\n"); + return ret; + } + + ret = devm_add_action_or_reset(&client->dev, noa1305_reg_remove, priv); + if (ret) { + dev_err(&client->dev, "addition of devm action failed\n"); + return ret; + } + + i2c_set_clientdata(client, indio_dev); + priv->client = client; + priv->regmap = regmap; + + ret = regmap_bulk_read(regmap, NOA1305_REG_DEVICE_ID_LSB, &data, 2); + if (ret < 0) { + dev_err(&client->dev, "ID reading failed: %d\n", ret); + return ret; + } + + dev_id = le16_to_cpu(data); + if (dev_id != NOA1305_DEVICE_ID) { + dev_err(&client->dev, "Unknown device ID: 0x%x\n", dev_id); + return -ENODEV; + } + + ret = regmap_write(regmap, NOA1305_REG_POWER_CONTROL, + NOA1305_POWER_CONTROL_ON); + if (ret < 0) { + dev_err(&client->dev, "Enabling power control failed\n"); + return ret; + } + + ret = regmap_write(regmap, NOA1305_REG_RESET, NOA1305_RESET_RESET); + if (ret < 0) { + dev_err(&client->dev, "Device reset failed\n"); + return ret; + } + + ret = regmap_write(regmap, NOA1305_REG_INTEGRATION_TIME, + NOA1305_INTEGR_TIME_800MS); + if (ret < 0) { + dev_err(&client->dev, "Setting integration time failed\n"); + return ret; + } + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &noa1305_info; + indio_dev->channels = noa1305_channels; + indio_dev->num_channels = ARRAY_SIZE(noa1305_channels); + indio_dev->name = NOA1305_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_iio_device_register(&client->dev, indio_dev); + if (ret) + dev_err(&client->dev, "registering device failed\n"); + + return ret; +} + +static const struct of_device_id noa1305_of_match[] = { + { .compatible = "onnn,noa1305" }, + { } +}; +MODULE_DEVICE_TABLE(of, noa1305_of_match); + +static const struct i2c_device_id noa1305_ids[] = { + { "noa1305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, noa1305_ids); + +static struct i2c_driver noa1305_driver = { + .driver = { + .name = NOA1305_DRIVER_NAME, + .of_match_table = noa1305_of_match, + }, + .probe = noa1305_probe, + .id_table = noa1305_ids, +}; + +module_i2c_driver(noa1305_driver); + +MODULE_AUTHOR("Sergei Miroshnichenko "); +MODULE_AUTHOR("Martyn Welch Date: Mon, 5 Aug 2019 12:26:50 +0000 Subject: [PATCH 1977/7155] iio: imu: inv_mpu6050: be more explicit on supported chips Since every chip has a different whoami, we are not supporting all existing variant of all chips. Add an explicit supported chips list in Kconfig description. Signed-off-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 395f3bd7de0a..e4c4c12236a7 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -14,8 +14,9 @@ config INV_MPU6050_I2C select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6050/6500/9150 and - ICM20608/20602 motion tracking devices over I2C. + This driver supports the Invensense MPU6000/6050/6500/6515, + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c. @@ -25,7 +26,8 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6050/6500/9150 and - ICM20608/20602 motion tracking devices over SPI. + This driver supports the Invensense MPU6000/6050/6500/6515, + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. -- GitLab From a9e21bea1f815c2ec917ecc0efe0a7049c825d5b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 5 Aug 2019 11:52:11 +0100 Subject: [PATCH 1978/7155] ][next] selftests: nettest: fix spelling mistake: "potocol" -> "protocol" There is a spelling mistake in an error messgae. Fix it. Signed-off-by: Colin Ian King Acked-by: Shuah Khan Signed-off-by: David S. Miller --- tools/testing/selftests/net/nettest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c index 9278f8460d75..83515e5ea4dc 100644 --- a/tools/testing/selftests/net/nettest.c +++ b/tools/testing/selftests/net/nettest.c @@ -1627,7 +1627,7 @@ int main(int argc, char *argv[]) args.protocol = pe->p_proto; } else { if (str_to_uint(optarg, 0, 0xffff, &tmp) != 0) { - fprintf(stderr, "Invalid potocol\n"); + fprintf(stderr, "Invalid protocol\n"); return 1; } args.protocol = tmp; -- GitLab From 3ec3d7a3ff10692d4f8a2baa0ff18fe10a9b6ad4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:20 +0900 Subject: [PATCH 1979/7155] ALSA: firewire-lib: add AMDTP domain structure to handle several isoc contexts This commit adds 'struct amdtp_domain' structure. This structure has list of instance of AMDTP stream to handle a couple of isochronous contexts. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 22 ++++++++++++++++++++++ sound/firewire/amdtp-stream.h | 7 +++++++ 2 files changed, 29 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 369e75e33120..02077696fa77 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1136,3 +1136,25 @@ void amdtp_stream_pcm_abort(struct amdtp_stream *s) snd_pcm_stop_xrun(pcm); } EXPORT_SYMBOL(amdtp_stream_pcm_abort); + +/** + * amdtp_domain_init - initialize an AMDTP domain structure + * @d: the AMDTP domain to initialize. + */ +int amdtp_domain_init(struct amdtp_domain *d) +{ + INIT_LIST_HEAD(&d->streams); + + return 0; +} +EXPORT_SYMBOL_GPL(amdtp_domain_init); + +/** + * amdtp_domain_destroy - destroy an AMDTP domain structure + * @d: the AMDTP domain to destroy. + */ +void amdtp_domain_destroy(struct amdtp_domain *d) +{ + WARN_ON(!list_empty(&d->streams)); +} +EXPORT_SYMBOL_GPL(amdtp_domain_destroy); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 50041fa884d9..2378db4b4195 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -267,4 +267,11 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s, msecs_to_jiffies(timeout)) > 0; } +struct amdtp_domain { + struct list_head streams; +}; + +int amdtp_domain_init(struct amdtp_domain *d); +void amdtp_domain_destroy(struct amdtp_domain *d); + #endif -- GitLab From 6261f90bdb0b605ffb158717ec7a03b1753aded5 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:21 +0900 Subject: [PATCH 1980/7155] ALSA: firewire-lib: add a kernel API to stop a couple of AMDTP streams in AMDTP domain This commit adds a kernel API to stop a couple of isochronous contexts for AMDTP streams. The API is not protected with any lock primitive. Callers should use this with enough lock against concurrent access. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 16 ++++++++++++++++ sound/firewire/amdtp-stream.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 02077696fa77..31fc90f76443 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1158,3 +1158,19 @@ void amdtp_domain_destroy(struct amdtp_domain *d) WARN_ON(!list_empty(&d->streams)); } EXPORT_SYMBOL_GPL(amdtp_domain_destroy); + +/** + * amdtp_domain_stop - stop sending packets for isoc context in the same domain. + * @d: the AMDTP domain to which the isoc contexts belong. + */ +void amdtp_domain_stop(struct amdtp_domain *d) +{ + struct amdtp_stream *s, *next; + + list_for_each_entry_safe(s, next, &d->streams, list) { + list_del(&s->list); + + amdtp_stream_stop(s); + } +} +EXPORT_SYMBOL_GPL(amdtp_domain_stop); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 2378db4b4195..ab2a69180240 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -170,6 +170,9 @@ struct amdtp_stream { /* For backends to process data blocks. */ void *protocol; amdtp_stream_process_ctx_payloads_t process_ctx_payloads; + + // For domain. + struct list_head list; }; int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, @@ -274,4 +277,6 @@ struct amdtp_domain { int amdtp_domain_init(struct amdtp_domain *d); void amdtp_domain_destroy(struct amdtp_domain *d); +void amdtp_domain_stop(struct amdtp_domain *d); + #endif -- GitLab From 157a53eef6a016e6938d9fd266b85221fcd4eaa3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:22 +0900 Subject: [PATCH 1981/7155] ALSA: firewire-lib: add a kernel API to add AMDTP stream into AMDTP domain This commit adds a kernel API to insert AMDTP stream to list in AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 26 ++++++++++++++++++++++++++ sound/firewire/amdtp-stream.h | 5 +++++ 2 files changed, 31 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 31fc90f76443..fa7989ee4769 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1159,6 +1159,32 @@ void amdtp_domain_destroy(struct amdtp_domain *d) } EXPORT_SYMBOL_GPL(amdtp_domain_destroy); +/** + * amdtp_domain_add_stream - register isoc context into the domain. + * @d: the AMDTP domain. + * @s: the AMDTP stream. + * @channel: the isochronous channel on the bus. + * @speed: firewire speed code. + */ +int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, + int channel, int speed) +{ + struct amdtp_stream *tmp; + + list_for_each_entry(tmp, &d->streams, list) { + if (s == tmp) + return -EBUSY; + } + + list_add(&s->list, &d->streams); + + s->channel = channel; + s->speed = speed; + + return 0; +} +EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); + /** * amdtp_domain_stop - stop sending packets for isoc context in the same domain. * @d: the AMDTP domain to which the isoc contexts belong. diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index ab2a69180240..4b102fd7529d 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -172,6 +172,8 @@ struct amdtp_stream { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; // For domain. + int channel; + int speed; struct list_head list; }; @@ -277,6 +279,9 @@ struct amdtp_domain { int amdtp_domain_init(struct amdtp_domain *d); void amdtp_domain_destroy(struct amdtp_domain *d); +int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, + int channel, int speed); + void amdtp_domain_stop(struct amdtp_domain *d); #endif -- GitLab From 9b4702b06c0e25abc612e6f02f3e25a51c684a01 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:23 +0900 Subject: [PATCH 1982/7155] ALSA: firewire-lib: add a kernel API to start AMDTP streams in AMDTP domain This commit adds a kernel API to start a couple of isochronous contexts for some AMDTP streams. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 24 ++++++++++++++++++++++++ sound/firewire/amdtp-stream.h | 1 + 2 files changed, 25 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fa7989ee4769..158d210caea7 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1185,6 +1185,30 @@ int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, } EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); +/** + * amdtp_domain_start - start sending packets for isoc context in the domain. + * @d: the AMDTP domain. + */ +int amdtp_domain_start(struct amdtp_domain *d) +{ + struct amdtp_stream *s; + int err = 0; + + list_for_each_entry(s, &d->streams, list) { + err = amdtp_stream_start(s, s->channel, s->speed); + if (err < 0) + break; + } + + if (err < 0) { + list_for_each_entry(s, &d->streams, list) + amdtp_stream_stop(s); + } + + return err; +} +EXPORT_SYMBOL_GPL(amdtp_domain_start); + /** * amdtp_domain_stop - stop sending packets for isoc context in the same domain. * @d: the AMDTP domain to which the isoc contexts belong. diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 4b102fd7529d..15d471660a43 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -282,6 +282,7 @@ void amdtp_domain_destroy(struct amdtp_domain *d); int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, int channel, int speed); +int amdtp_domain_start(struct amdtp_domain *d); void amdtp_domain_stop(struct amdtp_domain *d); #endif -- GitLab From 94491c175d6bf4b838043a3fb5adabd731d8fbab Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:24 +0900 Subject: [PATCH 1983/7155] ALSA: fireworks: code refactoring for initialization/destruction of AMDTP streams This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_stream.c | 77 ++++++++++----------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 385fc9686365..0f62c50055e9 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -8,8 +8,7 @@ #define CALLBACK_TIMEOUT 100 -static int -init_stream(struct snd_efw *efw, struct amdtp_stream *stream) +static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) { struct cmp_connection *conn; enum cmp_direction c_dir; @@ -28,14 +27,37 @@ init_stream(struct snd_efw *efw, struct amdtp_stream *stream) err = cmp_connection_init(conn, efw->unit, c_dir, 0); if (err < 0) - goto end; + return err; err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING); if (err < 0) { amdtp_stream_destroy(stream); cmp_connection_destroy(conn); + return err; } -end: + + if (stream == &efw->tx_stream) { + // Fireworks transmits NODATA packets with TAG0. + efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; + // Fireworks has its own meaning for dbc. + efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; + // Fireworks reset dbc at bus reset. + efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; + // But Recent firmwares starts packets with non-zero dbc. + // Driver version 5.7.6 installs firmware version 5.7.3. + if (efw->is_fireworks3 && + (efw->firmware_version == 0x5070000 || + efw->firmware_version == 0x5070300 || + efw->firmware_version == 0x5080000)) + efw->tx_stream.flags |= CIP_UNALIGHED_DBC; + // AudioFire9 always reports wrong dbs. + if (efw->is_af9) + efw->tx_stream.flags |= CIP_WRONG_DBS; + // Firmware version 5.5 reports fixed interval for dbc. + if (efw->firmware_version == 0x5050000) + efw->tx_stream.ctx_data.tx.dbc_interval = 8; + } + return err; } @@ -83,22 +105,16 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, return 0; } -/* - * This function should be called before starting the stream or after stopping - * the streams. - */ -static void -destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) +// This function should be called before starting the stream or after stopping +// the streams. +static void destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) { - struct cmp_connection *conn; + amdtp_stream_destroy(stream); if (stream == &efw->tx_stream) - conn = &efw->out_conn; + cmp_connection_destroy(&efw->out_conn); else - conn = &efw->in_conn; - - amdtp_stream_destroy(stream); - cmp_connection_destroy(conn); + cmp_connection_destroy(&efw->in_conn); } static int @@ -131,42 +147,21 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) err = init_stream(efw, &efw->tx_stream); if (err < 0) - goto end; - /* Fireworks transmits NODATA packets with TAG0. */ - efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; - /* Fireworks has its own meaning for dbc. */ - efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; - /* Fireworks reset dbc at bus reset. */ - efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; - /* - * But Recent firmwares starts packets with non-zero dbc. - * Driver version 5.7.6 installs firmware version 5.7.3. - */ - if (efw->is_fireworks3 && - (efw->firmware_version == 0x5070000 || - efw->firmware_version == 0x5070300 || - efw->firmware_version == 0x5080000)) - efw->tx_stream.flags |= CIP_UNALIGHED_DBC; - /* AudioFire9 always reports wrong dbs. */ - if (efw->is_af9) - efw->tx_stream.flags |= CIP_WRONG_DBS; - /* Firmware version 5.5 reports fixed interval for dbc. */ - if (efw->firmware_version == 0x5050000) - efw->tx_stream.ctx_data.tx.dbc_interval = 8; + return err; err = init_stream(efw, &efw->rx_stream); if (err < 0) { destroy_stream(efw, &efw->tx_stream); - goto end; + return err; } - /* set IEC61883 compliant mode (actually not fully compliant...) */ + // set IEC61883 compliant mode (actually not fully compliant...). err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); if (err < 0) { destroy_stream(efw, &efw->tx_stream); destroy_stream(efw, &efw->rx_stream); } -end: + return err; } -- GitLab From 7eb7b18e9fc7c8dc3d3c186ec6b0cfa9147299f8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:25 +0900 Subject: [PATCH 1984/7155] ALSA: fireworks: code refactoring for bus reset handler This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks_stream.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 0f62c50055e9..af340491dc43 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -299,14 +299,11 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) void snd_efw_stream_update_duplex(struct snd_efw *efw) { - if (cmp_connection_update(&efw->out_conn) < 0 || - cmp_connection_update(&efw->in_conn) < 0) { - stop_stream(efw, &efw->rx_stream); - stop_stream(efw, &efw->tx_stream); - } else { - amdtp_stream_update(&efw->rx_stream); - amdtp_stream_update(&efw->tx_stream); - } + stop_stream(efw, &efw->rx_stream); + stop_stream(efw, &efw->tx_stream); + + amdtp_stream_pcm_abort(&efw->rx_stream); + amdtp_stream_pcm_abort(&efw->tx_stream); } void snd_efw_stream_destroy_duplex(struct snd_efw *efw) -- GitLab From d79360ebe9c8668caf0e3932216f236fffbfa1b6 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:26 +0900 Subject: [PATCH 1985/7155] ALSA: firewire-digi00x: code refactoring for initialization/destruction of AMDTP stream This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 65 ++++++++++++++++--------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 3e77dbd3ee22..cff193f00a97 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -218,43 +218,62 @@ static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream, fw_parent_device(dg00x->unit)->max_speed); } -int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) +static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s) { + struct fw_iso_resources *resources; + enum amdtp_stream_direction dir; int err; - /* For out-stream. */ - err = fw_iso_resources_init(&dg00x->rx_resources, dg00x->unit); + if (s == &dg00x->tx_stream) { + resources = &dg00x->tx_resources; + dir = AMDTP_IN_STREAM; + } else { + resources = &dg00x->rx_resources; + dir = AMDTP_OUT_STREAM; + } + + err = fw_iso_resources_init(resources, dg00x->unit); if (err < 0) - goto error; - err = amdtp_dot_init(&dg00x->rx_stream, dg00x->unit, AMDTP_OUT_STREAM); + return err; + + err = amdtp_dot_init(s, dg00x->unit, dir); if (err < 0) - goto error; + fw_iso_resources_destroy(resources); + + return err; +} - /* For in-stream. */ - err = fw_iso_resources_init(&dg00x->tx_resources, dg00x->unit); +static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s) +{ + amdtp_stream_destroy(s); + + if (s == &dg00x->tx_stream) + fw_iso_resources_destroy(&dg00x->tx_resources); + else + fw_iso_resources_destroy(&dg00x->rx_resources); +} + +int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) +{ + int err; + + err = init_stream(dg00x, &dg00x->rx_stream); if (err < 0) - goto error; - err = amdtp_dot_init(&dg00x->tx_stream, dg00x->unit, AMDTP_IN_STREAM); + return err; + + err = init_stream(dg00x, &dg00x->tx_stream); if (err < 0) - goto error; + destroy_stream(dg00x, &dg00x->rx_stream); - return 0; -error: - snd_dg00x_stream_destroy_duplex(dg00x); return err; } -/* - * This function should be called before starting streams or after stopping - * streams. - */ +// This function should be called before starting streams or after stopping +// streams. void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) { - amdtp_stream_destroy(&dg00x->rx_stream); - fw_iso_resources_destroy(&dg00x->rx_resources); - - amdtp_stream_destroy(&dg00x->tx_stream); - fw_iso_resources_destroy(&dg00x->tx_resources); + destroy_stream(dg00x, &dg00x->rx_stream); + destroy_stream(dg00x, &dg00x->tx_stream); } int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) -- GitLab From 5f9625a5ba5dcf1815f123fced65f289b558aca4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:27 +0900 Subject: [PATCH 1986/7155] ALSA: firewire-tascam: code refactoring for initialization/destruction of AMDTP stream This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 71 +++++++++++++++++---------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index e852e46ebe6f..d5e77036e0ee 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -287,38 +287,60 @@ static int keep_resources(struct snd_tscm *tscm, unsigned int rate, fw_parent_device(tscm->unit)->max_speed); } -int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) +static int init_stream(struct snd_tscm *tscm, struct amdtp_stream *s) { + struct fw_iso_resources *resources; + enum amdtp_stream_direction dir; unsigned int pcm_channels; int err; - /* For out-stream. */ - err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit); - if (err < 0) - return err; - pcm_channels = tscm->spec->pcm_playback_analog_channels; + if (s == &tscm->tx_stream) { + resources = &tscm->tx_resources; + dir = AMDTP_IN_STREAM; + pcm_channels = tscm->spec->pcm_capture_analog_channels; + } else { + resources = &tscm->rx_resources; + dir = AMDTP_OUT_STREAM; + pcm_channels = tscm->spec->pcm_playback_analog_channels; + } + if (tscm->spec->has_adat) pcm_channels += 8; if (tscm->spec->has_spdif) pcm_channels += 2; - err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM, - pcm_channels); + + err = fw_iso_resources_init(resources, tscm->unit); if (err < 0) return err; - /* For in-stream. */ - err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit); + err = amdtp_tscm_init(s, tscm->unit, dir, pcm_channels); + if (err < 0) + fw_iso_resources_free(resources); + + return err; +} + +static void destroy_stream(struct snd_tscm *tscm, struct amdtp_stream *s) +{ + amdtp_stream_destroy(s); + + if (s == &tscm->tx_stream) + fw_iso_resources_destroy(&tscm->tx_resources); + else + fw_iso_resources_destroy(&tscm->rx_resources); +} + +int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) +{ + int err; + + err = init_stream(tscm, &tscm->tx_stream); if (err < 0) return err; - pcm_channels = tscm->spec->pcm_capture_analog_channels; - if (tscm->spec->has_adat) - pcm_channels += 8; - if (tscm->spec->has_spdif) - pcm_channels += 2; - err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM, - pcm_channels); + + err = init_stream(tscm, &tscm->rx_stream); if (err < 0) - amdtp_stream_destroy(&tscm->rx_stream); + destroy_stream(tscm, &tscm->tx_stream); return err; } @@ -333,17 +355,12 @@ void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) amdtp_stream_stop(&tscm->rx_stream); } -/* - * This function should be called before starting streams or after stopping - * streams. - */ +// This function should be called before starting streams or after stopping +// streams. void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) { - amdtp_stream_destroy(&tscm->rx_stream); - amdtp_stream_destroy(&tscm->tx_stream); - - fw_iso_resources_destroy(&tscm->rx_resources); - fw_iso_resources_destroy(&tscm->tx_resources); + destroy_stream(tscm, &tscm->rx_stream); + destroy_stream(tscm, &tscm->tx_stream); } int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) -- GitLab From 39e522a5a45fe805a2925aaddc30a4b2c6ded642 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:28 +0900 Subject: [PATCH 1987/7155] ALSA: firewire-motu: code refactoring for initialization/destruction of AMDTP stream This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 48 ++++++++++++------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 2bbb335e8de1..cc9f34426a47 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -300,62 +300,52 @@ void snd_motu_stream_stop_duplex(struct snd_motu *motu) } } -static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) +static int init_stream(struct snd_motu *motu, struct amdtp_stream *s) { - int err; - struct amdtp_stream *stream; struct fw_iso_resources *resources; + enum amdtp_stream_direction dir; + int err; - if (dir == AMDTP_IN_STREAM) { - stream = &motu->tx_stream; + if (s == &motu->tx_stream) { resources = &motu->tx_resources; + dir = AMDTP_IN_STREAM; } else { - stream = &motu->rx_stream; resources = &motu->rx_resources; + dir = AMDTP_OUT_STREAM; } err = fw_iso_resources_init(resources, motu->unit); if (err < 0) return err; - err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol); - if (err < 0) { - amdtp_stream_destroy(stream); + err = amdtp_motu_init(s, motu->unit, dir, motu->spec->protocol); + if (err < 0) fw_iso_resources_destroy(resources); - } return err; } -static void destroy_stream(struct snd_motu *motu, - enum amdtp_stream_direction dir) +static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s) { - struct amdtp_stream *stream; - struct fw_iso_resources *resources; + amdtp_stream_destroy(s); - if (dir == AMDTP_IN_STREAM) { - stream = &motu->tx_stream; - resources = &motu->tx_resources; - } else { - stream = &motu->rx_stream; - resources = &motu->rx_resources; - } - - amdtp_stream_destroy(stream); - fw_iso_resources_destroy(resources); + if (s == &motu->tx_stream) + fw_iso_resources_destroy(&motu->tx_resources); + else + fw_iso_resources_destroy(&motu->rx_resources); } int snd_motu_stream_init_duplex(struct snd_motu *motu) { int err; - err = init_stream(motu, AMDTP_IN_STREAM); + err = init_stream(motu, &motu->tx_stream); if (err < 0) return err; - err = init_stream(motu, AMDTP_OUT_STREAM); + err = init_stream(motu, &motu->rx_stream); if (err < 0) - destroy_stream(motu, AMDTP_IN_STREAM); + destroy_stream(motu, &motu->tx_stream); return err; } @@ -366,8 +356,8 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu) */ void snd_motu_stream_destroy_duplex(struct snd_motu *motu) { - destroy_stream(motu, AMDTP_IN_STREAM); - destroy_stream(motu, AMDTP_OUT_STREAM); + destroy_stream(motu, &motu->rx_stream); + destroy_stream(motu, &motu->tx_stream); motu->substreams_counter = 0; } -- GitLab From 42355abb9c33503f7b5889d71e1432fabdf2fd7f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:29 +0900 Subject: [PATCH 1988/7155] ALSA: fireface: code refactoring for initialization/destruction of AMDTP stream This commit is a preparation to support AMDTP domain. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-stream.c | 39 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 4208b8004d1a..e4710204f481 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -39,54 +39,53 @@ static inline void finish_session(struct snd_ff *ff) ff->spec->protocol->switch_fetching_mode(ff, false); } -static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) +static int init_stream(struct snd_ff *ff, struct amdtp_stream *s) { - int err; struct fw_iso_resources *resources; - struct amdtp_stream *stream; + enum amdtp_stream_direction dir; + int err; - if (dir == AMDTP_IN_STREAM) { + if (s == &ff->tx_stream) { resources = &ff->tx_resources; - stream = &ff->tx_stream; + dir = AMDTP_IN_STREAM; } else { resources = &ff->rx_resources; - stream = &ff->rx_stream; + dir = AMDTP_OUT_STREAM; } err = fw_iso_resources_init(resources, ff->unit); if (err < 0) return err; - err = amdtp_ff_init(stream, ff->unit, dir); + err = amdtp_ff_init(s, ff->unit, dir); if (err < 0) fw_iso_resources_destroy(resources); return err; } -static void destroy_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) +static void destroy_stream(struct snd_ff *ff, struct amdtp_stream *s) { - if (dir == AMDTP_IN_STREAM) { - amdtp_stream_destroy(&ff->tx_stream); + amdtp_stream_destroy(s); + + if (s == &ff->tx_stream) fw_iso_resources_destroy(&ff->tx_resources); - } else { - amdtp_stream_destroy(&ff->rx_stream); + else fw_iso_resources_destroy(&ff->rx_resources); - } } int snd_ff_stream_init_duplex(struct snd_ff *ff) { int err; - err = init_stream(ff, AMDTP_OUT_STREAM); + err = init_stream(ff, &ff->rx_stream); if (err < 0) - goto end; + return err; - err = init_stream(ff, AMDTP_IN_STREAM); + err = init_stream(ff, &ff->tx_stream); if (err < 0) - destroy_stream(ff, AMDTP_OUT_STREAM); -end: + destroy_stream(ff, &ff->rx_stream); + return err; } @@ -96,8 +95,8 @@ int snd_ff_stream_init_duplex(struct snd_ff *ff) */ void snd_ff_stream_destroy_duplex(struct snd_ff *ff) { - destroy_stream(ff, AMDTP_IN_STREAM); - destroy_stream(ff, AMDTP_OUT_STREAM); + destroy_stream(ff, &ff->rx_stream); + destroy_stream(ff, &ff->tx_stream); } int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) -- GitLab From b0db4d512941455894e7a13f71594b7d4638b94b Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:30 +0900 Subject: [PATCH 1989/7155] ALSA: bebob: support AMDTP domain This commit adds AMDTP domain support for ALSA bebob driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.h | 2 + sound/firewire/bebob/bebob_stream.c | 62 +++++++++++++---------------- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 9e0b689fe34a..356d6ba60959 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -115,6 +115,8 @@ struct snd_bebob { /* For BeBoB version quirk. */ unsigned int version; + + struct amdtp_domain domain; }; static inline int diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 334dc7c96e1d..73fee991bd75 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -445,10 +445,9 @@ start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) goto end; } - /* start amdtp stream */ - err = amdtp_stream_start(stream, - conn->resources.channel, - conn->speed); + // start amdtp stream. + err = amdtp_domain_add_stream(&bebob->domain, stream, + conn->resources.channel, conn->speed); end: return err; } @@ -523,7 +522,13 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) return err; } - return 0; + err = amdtp_domain_init(&bebob->domain); + if (err < 0) { + destroy_stream(bebob, &bebob->tx_stream); + destroy_stream(bebob, &bebob->rx_stream); + } + + return err; } static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, @@ -566,9 +571,7 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) if (rate == 0) rate = curr_rate; if (curr_rate != rate) { - amdtp_stream_stop(&bebob->tx_stream); - amdtp_stream_stop(&bebob->rx_stream); - + amdtp_domain_stop(&bebob->domain); break_both_connections(bebob); cmp_connection_release(&bebob->out_conn); @@ -620,9 +623,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) // packet queueing error or detecting discontinuity if (amdtp_streaming_error(&bebob->rx_stream) || amdtp_streaming_error(&bebob->tx_stream)) { - amdtp_stream_stop(&bebob->rx_stream); - amdtp_stream_stop(&bebob->tx_stream); - + amdtp_domain_stop(&bebob->domain); break_both_connections(bebob); } @@ -640,11 +641,16 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) return err; err = start_stream(bebob, &bebob->rx_stream); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to run AMDTP master stream:%d\n", err); + if (err < 0) + goto error; + + err = start_stream(bebob, &bebob->tx_stream); + if (err < 0) + goto error; + + err = amdtp_domain_start(&bebob->domain); + if (err < 0) goto error; - } // NOTE: // The firmware customized by M-Audio uses these commands to @@ -660,21 +666,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) } if (!amdtp_stream_wait_callback(&bebob->rx_stream, - CALLBACK_TIMEOUT)) { - err = -ETIMEDOUT; - goto error; - } - } - - if (!amdtp_stream_running(&bebob->tx_stream)) { - err = start_stream(bebob, &bebob->tx_stream); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to run AMDTP slave stream:%d\n", err); - goto error; - } - - if (!amdtp_stream_wait_callback(&bebob->tx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&bebob->tx_stream, CALLBACK_TIMEOUT)) { err = -ETIMEDOUT; goto error; @@ -683,8 +676,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) return 0; error: - amdtp_stream_stop(&bebob->tx_stream); - amdtp_stream_stop(&bebob->rx_stream); + amdtp_domain_stop(&bebob->domain); break_both_connections(bebob); return err; } @@ -692,9 +684,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) { if (bebob->substreams_counter == 0) { - amdtp_stream_stop(&bebob->rx_stream); - amdtp_stream_stop(&bebob->tx_stream); - + amdtp_domain_stop(&bebob->domain); break_both_connections(bebob); cmp_connection_release(&bebob->out_conn); @@ -708,6 +698,8 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) */ void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) { + amdtp_domain_destroy(&bebob->domain); + destroy_stream(bebob, &bebob->tx_stream); destroy_stream(bebob, &bebob->rx_stream); } -- GitLab From db40eeb2469fef4efe26789ea2596372ee43ae2f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:31 +0900 Subject: [PATCH 1990/7155] ALSA: fireworks: support AMDTP domain This commit adds AMDTP domain support for ALSA fireworks driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.h | 2 + sound/firewire/fireworks/fireworks_stream.c | 92 +++++++++++---------- 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 31efd4b53b4f..4cda297f8438 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -107,6 +107,8 @@ struct snd_efw { u8 *resp_buf; u8 *pull_ptr; u8 *push_ptr; + + struct amdtp_domain domain; }; int snd_efw_transaction_cmd(struct fw_unit *unit, diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index af340491dc43..f2de304d2f26 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -61,17 +61,6 @@ static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) return err; } -static void -stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) -{ - amdtp_stream_stop(stream); - - if (stream == &efw->tx_stream) - cmp_connection_break(&efw->out_conn); - else - cmp_connection_break(&efw->in_conn); -} - static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, unsigned int rate) { @@ -89,19 +78,13 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, return err; // Start amdtp stream. - err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); + err = amdtp_domain_add_stream(&efw->domain, stream, + conn->resources.channel, conn->speed); if (err < 0) { cmp_connection_break(conn); return err; } - // Wait first callback. - if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(stream); - cmp_connection_break(conn); - return -ETIMEDOUT; - } - return 0; } @@ -155,6 +138,13 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) return err; } + err = amdtp_domain_init(&efw->domain); + if (err < 0) { + destroy_stream(efw, &efw->tx_stream); + destroy_stream(efw, &efw->rx_stream); + return err; + } + // set IEC61883 compliant mode (actually not fully compliant...). err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); if (err < 0) { @@ -209,8 +199,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) if (rate == 0) rate = curr_rate; if (rate != curr_rate) { - stop_stream(efw, &efw->tx_stream); - stop_stream(efw, &efw->rx_stream); + amdtp_domain_stop(&efw->domain); + + cmp_connection_break(&efw->out_conn); + cmp_connection_break(&efw->in_conn); cmp_connection_release(&efw->out_conn); cmp_connection_release(&efw->in_conn); @@ -250,47 +242,57 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw) if (efw->substreams_counter == 0) return -EIO; - err = snd_efw_command_get_sampling_rate(efw, &rate); - if (err < 0) - return err; - if (amdtp_streaming_error(&efw->rx_stream) || amdtp_streaming_error(&efw->tx_stream)) { - stop_stream(efw, &efw->rx_stream); - stop_stream(efw, &efw->tx_stream); + amdtp_domain_stop(&efw->domain); + cmp_connection_break(&efw->out_conn); + cmp_connection_break(&efw->in_conn); } - /* master should be always running */ + err = snd_efw_command_get_sampling_rate(efw, &rate); + if (err < 0) + return err; + if (!amdtp_stream_running(&efw->rx_stream)) { err = start_stream(efw, &efw->rx_stream, rate); - if (err < 0) { - dev_err(&efw->unit->device, - "fail to start AMDTP master stream:%d\n", err); + if (err < 0) goto error; - } - } - if (!amdtp_stream_running(&efw->tx_stream)) { err = start_stream(efw, &efw->tx_stream, rate); - if (err < 0) { - dev_err(&efw->unit->device, - "fail to start AMDTP slave stream:%d\n", err); + if (err < 0) + goto error; + + err = amdtp_domain_start(&efw->domain); + if (err < 0) + goto error; + + // Wait first callback. + if (!amdtp_stream_wait_callback(&efw->rx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&efw->tx_stream, + CALLBACK_TIMEOUT)) { + err = -ETIMEDOUT; goto error; } } return 0; error: - stop_stream(efw, &efw->rx_stream); - stop_stream(efw, &efw->tx_stream); + amdtp_domain_stop(&efw->domain); + + cmp_connection_break(&efw->out_conn); + cmp_connection_break(&efw->in_conn); + return err; } void snd_efw_stream_stop_duplex(struct snd_efw *efw) { if (efw->substreams_counter == 0) { - stop_stream(efw, &efw->tx_stream); - stop_stream(efw, &efw->rx_stream); + amdtp_domain_stop(&efw->domain); + + cmp_connection_break(&efw->out_conn); + cmp_connection_break(&efw->in_conn); cmp_connection_release(&efw->out_conn); cmp_connection_release(&efw->in_conn); @@ -299,8 +301,10 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) void snd_efw_stream_update_duplex(struct snd_efw *efw) { - stop_stream(efw, &efw->rx_stream); - stop_stream(efw, &efw->tx_stream); + amdtp_domain_stop(&efw->domain); + + cmp_connection_break(&efw->out_conn); + cmp_connection_break(&efw->in_conn); amdtp_stream_pcm_abort(&efw->rx_stream); amdtp_stream_pcm_abort(&efw->tx_stream); @@ -308,6 +312,8 @@ void snd_efw_stream_update_duplex(struct snd_efw *efw) void snd_efw_stream_destroy_duplex(struct snd_efw *efw) { + amdtp_domain_destroy(&efw->domain); + destroy_stream(efw, &efw->rx_stream); destroy_stream(efw, &efw->tx_stream); } -- GitLab From ac5d77864cfcb0f034221c2b3dac828ae24c722e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:32 +0900 Subject: [PATCH 1991/7155] ALSA: oxfw: support AMDTP domain This commit adds AMDTP domain support for ALSA oxfw driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-stream.c | 72 ++++++++++++++++++------------- sound/firewire/oxfw/oxfw.h | 2 + 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 74c972d25c66..0318dc4dcc55 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -114,19 +114,13 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) if (err < 0) return err; - err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); + err = amdtp_domain_add_stream(&oxfw->domain, stream, + conn->resources.channel, conn->speed); if (err < 0) { cmp_connection_break(conn); return err; } - // Wait first packet. - if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { - amdtp_stream_stop(stream); - cmp_connection_break(conn); - return -ETIMEDOUT; - } - return 0; } @@ -280,12 +274,12 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, pcm_channels = formation.pcm; } if (formation.rate != rate || formation.pcm != pcm_channels) { - amdtp_stream_stop(&oxfw->rx_stream); + amdtp_domain_stop(&oxfw->domain); + cmp_connection_break(&oxfw->in_conn); cmp_connection_release(&oxfw->in_conn); if (oxfw->has_output) { - amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); cmp_connection_release(&oxfw->out_conn); } @@ -325,55 +319,66 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) if (amdtp_streaming_error(&oxfw->rx_stream) || amdtp_streaming_error(&oxfw->tx_stream)) { - amdtp_stream_stop(&oxfw->rx_stream); - cmp_connection_break(&oxfw->in_conn); + amdtp_domain_stop(&oxfw->domain); - if (oxfw->has_output) { - amdtp_stream_stop(&oxfw->tx_stream); + cmp_connection_break(&oxfw->in_conn); + if (oxfw->has_output) cmp_connection_break(&oxfw->out_conn); - } } if (!amdtp_stream_running(&oxfw->rx_stream)) { err = start_stream(oxfw, &oxfw->rx_stream); if (err < 0) { dev_err(&oxfw->unit->device, - "fail to start rx stream: %d\n", err); + "fail to prepare rx stream: %d\n", err); goto error; } - } - if (oxfw->has_output) { - if (!amdtp_stream_running(&oxfw->tx_stream)) { + if (oxfw->has_output && + !amdtp_stream_running(&oxfw->tx_stream)) { err = start_stream(oxfw, &oxfw->tx_stream); if (err < 0) { dev_err(&oxfw->unit->device, - "fail to start tx stream: %d\n", err); + "fail to prepare tx stream: %d\n", err); goto error; } } + + err = amdtp_domain_start(&oxfw->domain); + if (err < 0) + goto error; + + // Wait first packet. + if (!amdtp_stream_wait_callback(&oxfw->rx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&oxfw->tx_stream, + CALLBACK_TIMEOUT)) { + err = -ETIMEDOUT; + goto error; + } + } return 0; error: - amdtp_stream_stop(&oxfw->rx_stream); + amdtp_domain_stop(&oxfw->domain); + cmp_connection_break(&oxfw->in_conn); - if (oxfw->has_output) { - amdtp_stream_stop(&oxfw->tx_stream); + if (oxfw->has_output) cmp_connection_break(&oxfw->out_conn); - } + return err; } void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) { if (oxfw->substreams_count == 0) { - amdtp_stream_stop(&oxfw->rx_stream); + amdtp_domain_stop(&oxfw->domain); + cmp_connection_break(&oxfw->in_conn); cmp_connection_release(&oxfw->in_conn); if (oxfw->has_output) { - amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); cmp_connection_release(&oxfw->out_conn); } @@ -409,13 +414,22 @@ int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw) } } - return 0; + err = amdtp_domain_init(&oxfw->domain); + if (err < 0) { + destroy_stream(oxfw, &oxfw->rx_stream); + if (oxfw->has_output) + destroy_stream(oxfw, &oxfw->tx_stream); + } + + return err; } // This function should be called before starting the stream or after stopping // the streams. void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) { + amdtp_domain_destroy(&oxfw->domain); + destroy_stream(oxfw, &oxfw->rx_stream); if (oxfw->has_output) @@ -424,13 +438,13 @@ void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw) { - amdtp_stream_stop(&oxfw->rx_stream); + amdtp_domain_stop(&oxfw->domain); + cmp_connection_break(&oxfw->in_conn); amdtp_stream_pcm_abort(&oxfw->rx_stream); if (oxfw->has_output) { - amdtp_stream_stop(&oxfw->tx_stream); cmp_connection_break(&oxfw->out_conn); amdtp_stream_pcm_abort(&oxfw->tx_stream); diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index cb69ab87bb14..c9627b8c5d6e 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -63,6 +63,8 @@ struct snd_oxfw { const struct ieee1394_device_id *entry; void *spec; + + struct amdtp_domain domain; }; /* -- GitLab From e9f21129b8d84debf53e06f73d340d5af136270f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:33 +0900 Subject: [PATCH 1992/7155] ALSA: dice: support AMDTP domain This commit adds AMDTP domain support for ALSA dice driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 32 ++++++++++++++++++++++++------- sound/firewire/dice/dice.h | 2 ++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index a9f0c77734c3..af8c5a2c28f3 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -154,14 +154,10 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, for (i = 0; i < params->count; i++) { reg = cpu_to_be32((u32)-1); if (dir == AMDTP_IN_STREAM) { - amdtp_stream_stop(&dice->tx_stream[i]); - snd_dice_transaction_write_tx(dice, params->size * i + TX_ISOCHRONOUS, ®, sizeof(reg)); } else { - amdtp_stream_stop(&dice->rx_stream[i]); - snd_dice_transaction_write_rx(dice, params->size * i + RX_ISOCHRONOUS, ®, sizeof(reg)); @@ -297,10 +293,11 @@ int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate) if (dice->substreams_counter == 0 || curr_rate != rate) { struct reg_params tx_params, rx_params; + amdtp_domain_stop(&dice->domain); + err = get_register_params(dice, &tx_params, &rx_params); if (err < 0) return err; - finish_session(dice, &tx_params, &rx_params); release_resources(dice); @@ -377,7 +374,8 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, return err; } - err = amdtp_stream_start(stream, resources->channel, max_speed); + err = amdtp_domain_add_stream(&dice->domain, stream, + resources->channel, max_speed); if (err < 0) return err; } @@ -410,6 +408,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) for (i = 0; i < MAX_STREAMS; ++i) { if (amdtp_streaming_error(&dice->tx_stream[i]) || amdtp_streaming_error(&dice->rx_stream[i])) { + amdtp_domain_stop(&dice->domain); finish_session(dice, &tx_params, &rx_params); break; } @@ -456,6 +455,10 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) goto error; } + err = amdtp_domain_start(&dice->domain); + if (err < 0) + goto error; + for (i = 0; i < MAX_STREAMS; i++) { if ((i < tx_params.count && !amdtp_stream_wait_callback(&dice->tx_stream[i], @@ -471,6 +474,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) return 0; error: + amdtp_domain_stop(&dice->domain); finish_session(dice, &tx_params, &rx_params); return err; } @@ -485,8 +489,10 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice) struct reg_params tx_params, rx_params; if (dice->substreams_counter == 0) { - if (get_register_params(dice, &tx_params, &rx_params) >= 0) + if (get_register_params(dice, &tx_params, &rx_params) >= 0) { + amdtp_domain_stop(&dice->domain); finish_session(dice, &tx_params, &rx_params); + } release_resources(dice); } @@ -567,6 +573,14 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice) break; } } + + err = amdtp_domain_init(&dice->domain); + if (err < 0) { + for (i = 0; i < MAX_STREAMS; ++i) { + destroy_stream(dice, AMDTP_OUT_STREAM, i); + destroy_stream(dice, AMDTP_IN_STREAM, i); + } + } end: return err; } @@ -579,6 +593,8 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice) destroy_stream(dice, AMDTP_IN_STREAM, i); destroy_stream(dice, AMDTP_OUT_STREAM, i); } + + amdtp_domain_destroy(&dice->domain); } void snd_dice_stream_update_duplex(struct snd_dice *dice) @@ -596,6 +612,8 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice) dice->global_enabled = false; if (get_register_params(dice, &tx_params, &rx_params) == 0) { + amdtp_domain_stop(&dice->domain); + stop_streams(dice, AMDTP_IN_STREAM, &tx_params); stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); } diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index c6304e5e9fc4..fa6d74303f54 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -112,6 +112,8 @@ struct snd_dice { bool global_enabled; struct completion clock_accepted; unsigned int substreams_counter; + + struct amdtp_domain domain; }; enum snd_dice_addr_type { -- GitLab From 9a08067ec318cbeaf0caa2d104cf677e723e02a3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:34 +0900 Subject: [PATCH 1993/7155] ALSA: firewire-digi00x: support AMDTP domain This commit adds AMDTP domain support for ALSA firewire-digi00x driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-stream.c | 55 ++++++++++++++----------- sound/firewire/digi00x/digi00x.h | 2 + 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index cff193f00a97..d6a92460060f 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -126,9 +126,6 @@ static void finish_session(struct snd_dg00x *dg00x) { __be32 data; - amdtp_stream_stop(&dg00x->tx_stream); - amdtp_stream_stop(&dg00x->rx_stream); - data = cpu_to_be32(0x00000003); snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, @@ -265,13 +262,23 @@ int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) if (err < 0) destroy_stream(dg00x, &dg00x->rx_stream); + err = amdtp_domain_init(&dg00x->domain); + if (err < 0) { + destroy_stream(dg00x, &dg00x->rx_stream); + destroy_stream(dg00x, &dg00x->tx_stream); + } + return err; } -// This function should be called before starting streams or after stopping -// streams. +/* + * This function should be called before starting streams or after stopping + * streams. + */ void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) { + amdtp_domain_destroy(&dg00x->domain); + destroy_stream(dg00x, &dg00x->rx_stream); destroy_stream(dg00x, &dg00x->tx_stream); } @@ -288,6 +295,8 @@ int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) rate = curr_rate; if (dg00x->substreams_counter == 0 || curr_rate != rate) { + amdtp_domain_stop(&dg00x->domain); + finish_session(dg00x); fw_iso_resources_free(&dg00x->tx_resources); @@ -320,8 +329,10 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) return 0; if (amdtp_streaming_error(&dg00x->tx_stream) || - amdtp_streaming_error(&dg00x->rx_stream)) + amdtp_streaming_error(&dg00x->rx_stream)) { + amdtp_domain_stop(&dg00x->domain); finish_session(dg00x); + } if (generation != fw_parent_device(dg00x->unit)->card->generation) { err = fw_iso_resources_update(&dg00x->tx_resources); @@ -338,36 +349,30 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) * which source of clock is used. */ if (!amdtp_stream_running(&dg00x->rx_stream)) { + int spd = fw_parent_device(dg00x->unit)->max_speed; + err = begin_session(dg00x); if (err < 0) goto error; - err = amdtp_stream_start(&dg00x->rx_stream, - dg00x->rx_resources.channel, - fw_parent_device(dg00x->unit)->max_speed); + err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream, + dg00x->rx_resources.channel, spd); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&dg00x->rx_stream, - CALLBACK_TIMEOUT)) { - err = -ETIMEDOUT; + err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream, + dg00x->tx_resources.channel, spd); + if (err < 0) goto error; - } - } - /* - * The value of SYT field in transmitted packets is always 0x0000. Thus, - * duplex streams with timestamp synchronization cannot be built. - */ - if (!amdtp_stream_running(&dg00x->tx_stream)) { - err = amdtp_stream_start(&dg00x->tx_stream, - dg00x->tx_resources.channel, - fw_parent_device(dg00x->unit)->max_speed); + err = amdtp_domain_start(&dg00x->domain); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&dg00x->tx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_stream_wait_callback(&dg00x->rx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&dg00x->tx_stream, + CALLBACK_TIMEOUT)) { err = -ETIMEDOUT; goto error; } @@ -375,6 +380,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) return 0; error: + amdtp_domain_stop(&dg00x->domain); finish_session(dg00x); return err; @@ -383,6 +389,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) { if (dg00x->substreams_counter == 0) { + amdtp_domain_stop(&dg00x->domain); finish_session(dg00x); fw_iso_resources_free(&dg00x->tx_resources); diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 0994d191ccda..8041c65f2736 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -59,6 +59,8 @@ struct snd_dg00x { /* Console models have additional MIDI ports for control surface. */ bool is_console; + + struct amdtp_domain domain; }; #define DG00X_ADDR_BASE 0xffffe0000000ull -- GitLab From c281d46a51e31703183aa66ed9315446a0a10953 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:35 +0900 Subject: [PATCH 1994/7155] ALSA: firewire-tascam: support AMDTP domain This commit adds AMDTP domain support for ALSA firewire-tascam driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-stream.c | 54 ++++++++++++++++----------- sound/firewire/tascam/tascam.h | 2 + 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index d5e77036e0ee..9e2dc2fe3271 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -180,9 +180,6 @@ static void finish_session(struct snd_tscm *tscm) { __be32 reg; - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - reg = 0; snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, @@ -339,8 +336,16 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) return err; err = init_stream(tscm, &tscm->rx_stream); - if (err < 0) + if (err < 0) { + destroy_stream(tscm, &tscm->tx_stream); + return err; + } + + err = amdtp_domain_init(&tscm->domain); + if (err < 0) { destroy_stream(tscm, &tscm->tx_stream); + destroy_stream(tscm, &tscm->rx_stream); + } return err; } @@ -348,17 +353,18 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) // At bus reset, streaming is stopped and some registers are clear. void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) { - amdtp_stream_pcm_abort(&tscm->tx_stream); - amdtp_stream_stop(&tscm->tx_stream); + amdtp_domain_stop(&tscm->domain); + amdtp_stream_pcm_abort(&tscm->tx_stream); amdtp_stream_pcm_abort(&tscm->rx_stream); - amdtp_stream_stop(&tscm->rx_stream); } // This function should be called before starting streams or after stopping // streams. void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) { + amdtp_domain_destroy(&tscm->domain); + destroy_stream(tscm, &tscm->rx_stream); destroy_stream(tscm, &tscm->tx_stream); } @@ -373,6 +379,8 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) return err; if (tscm->substreams_counter == 0 || rate != curr_rate) { + amdtp_domain_stop(&tscm->domain); + finish_session(tscm); fw_iso_resources_free(&tscm->tx_resources); @@ -405,8 +413,10 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) return 0; if (amdtp_streaming_error(&tscm->rx_stream) || - amdtp_streaming_error(&tscm->tx_stream)) + amdtp_streaming_error(&tscm->tx_stream)) { + amdtp_domain_stop(&tscm->domain); finish_session(tscm); + } if (generation != fw_parent_device(tscm->unit)->card->generation) { err = fw_iso_resources_update(&tscm->tx_resources); @@ -419,6 +429,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) } if (!amdtp_stream_running(&tscm->rx_stream)) { + int spd = fw_parent_device(tscm->unit)->max_speed; + err = set_stream_formats(tscm, rate); if (err < 0) goto error; @@ -427,27 +439,23 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) if (err < 0) goto error; - err = amdtp_stream_start(&tscm->rx_stream, - tscm->rx_resources.channel, - fw_parent_device(tscm->unit)->max_speed); + err = amdtp_domain_add_stream(&tscm->domain, &tscm->rx_stream, + tscm->rx_resources.channel, spd); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&tscm->rx_stream, - CALLBACK_TIMEOUT)) { - err = -ETIMEDOUT; + err = amdtp_domain_add_stream(&tscm->domain, &tscm->tx_stream, + tscm->tx_resources.channel, spd); + if (err < 0) goto error; - } - } - if (!amdtp_stream_running(&tscm->tx_stream)) { - err = amdtp_stream_start(&tscm->tx_stream, - tscm->tx_resources.channel, - fw_parent_device(tscm->unit)->max_speed); + err = amdtp_domain_start(&tscm->domain); if (err < 0) - goto error; + return err; - if (!amdtp_stream_wait_callback(&tscm->tx_stream, + if (!amdtp_stream_wait_callback(&tscm->rx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&tscm->tx_stream, CALLBACK_TIMEOUT)) { err = -ETIMEDOUT; goto error; @@ -456,6 +464,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) return 0; error: + amdtp_domain_stop(&tscm->domain); finish_session(tscm); return err; @@ -464,6 +473,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) { if (tscm->substreams_counter == 0) { + amdtp_domain_stop(&tscm->domain); finish_session(tscm); fw_iso_resources_free(&tscm->tx_resources); diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 734e5bb9c3da..64a2e4d2bbfe 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -97,6 +97,8 @@ struct snd_tscm { struct snd_firewire_tascam_change queue[SND_TSCM_QUEUE_COUNT]; unsigned int pull_pos; unsigned int push_pos; + + struct amdtp_domain domain; }; #define TSCM_ADDR_BASE 0xffff00000000ull -- GitLab From ccc6c1b0e604144d4d068eb676b444397cecf1b3 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:36 +0900 Subject: [PATCH 1995/7155] ALSA: firewire-motu: support AMDTP domain This commit adds AMDTP domain support for ALSA firewire-motu driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/motu/motu-stream.c | 83 +++++++++++++++---------------- sound/firewire/motu/motu.h | 2 + 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index cc9f34426a47..813e38e6a86e 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -92,9 +92,6 @@ static void finish_session(struct snd_motu *motu) if (err < 0) return; - amdtp_stream_stop(&motu->tx_stream); - amdtp_stream_stop(&motu->rx_stream); - err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, sizeof(reg)); if (err < 0) @@ -109,27 +106,6 @@ static void finish_session(struct snd_motu *motu) sizeof(reg)); } -static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) -{ - struct fw_iso_resources *resources; - int err; - - if (stream == &motu->rx_stream) - resources = &motu->rx_resources; - else - resources = &motu->tx_resources; - - err = amdtp_stream_start(stream, resources->channel, - fw_parent_device(motu->unit)->max_speed); - if (err < 0) - return err; - - if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) - return -ETIMEDOUT; - - return 0; -} - int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) { int err; @@ -169,6 +145,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate) rate = curr_rate; if (motu->substreams_counter == 0 || curr_rate != rate) { + amdtp_domain_stop(&motu->domain); finish_session(motu); fw_iso_resources_free(&motu->tx_resources); @@ -234,8 +211,10 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) return 0; if (amdtp_streaming_error(&motu->rx_stream) || - amdtp_streaming_error(&motu->tx_stream)) + amdtp_streaming_error(&motu->tx_stream)) { + amdtp_domain_stop(&motu->domain); finish_session(motu); + } if (generation != fw_parent_device(motu->unit)->card->generation) { err = fw_iso_resources_update(&motu->rx_resources); @@ -248,6 +227,8 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) } if (!amdtp_stream_running(&motu->rx_stream)) { + int spd = fw_parent_device(motu->unit)->max_speed; + err = ensure_packet_formats(motu); if (err < 0) return err; @@ -259,26 +240,32 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) goto stop_streams; } - err = start_isoc_ctx(motu, &motu->rx_stream); - if (err < 0) { - dev_err(&motu->unit->device, - "fail to start IT context: %d\n", err); + err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream, + motu->tx_resources.channel, spd); + if (err < 0) goto stop_streams; - } - err = motu->spec->protocol->switch_fetching_mode(motu, true); - if (err < 0) { - dev_err(&motu->unit->device, - "fail to enable frame fetching: %d\n", err); + err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream, + motu->rx_resources.channel, spd); + if (err < 0) + goto stop_streams; + + err = amdtp_domain_start(&motu->domain); + if (err < 0) + goto stop_streams; + + if (!amdtp_stream_wait_callback(&motu->tx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&motu->rx_stream, + CALLBACK_TIMEOUT)) { + err = -ETIMEDOUT; goto stop_streams; } - } - if (!amdtp_stream_running(&motu->tx_stream)) { - err = start_isoc_ctx(motu, &motu->tx_stream); + err = motu->spec->protocol->switch_fetching_mode(motu, true); if (err < 0) { dev_err(&motu->unit->device, - "fail to start IR context: %d", err); + "fail to enable frame fetching: %d\n", err); goto stop_streams; } } @@ -286,6 +273,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) return 0; stop_streams: + amdtp_domain_stop(&motu->domain); finish_session(motu); return err; } @@ -293,6 +281,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) void snd_motu_stream_stop_duplex(struct snd_motu *motu) { if (motu->substreams_counter == 0) { + amdtp_domain_stop(&motu->domain); finish_session(motu); fw_iso_resources_free(&motu->tx_resources); @@ -344,18 +333,26 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu) return err; err = init_stream(motu, &motu->rx_stream); - if (err < 0) + if (err < 0) { destroy_stream(motu, &motu->tx_stream); + return err; + } + + err = amdtp_domain_init(&motu->domain); + if (err < 0) { + destroy_stream(motu, &motu->tx_stream); + destroy_stream(motu, &motu->rx_stream); + } return err; } -/* - * This function should be called before starting streams or after stopping - * streams. - */ +// This function should be called before starting streams or after stopping +// streams. void snd_motu_stream_destroy_duplex(struct snd_motu *motu) { + amdtp_domain_destroy(&motu->domain); + destroy_stream(motu, &motu->rx_stream); destroy_stream(motu, &motu->tx_stream); diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 09d1451d7de4..350ee2c16f4a 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -69,6 +69,8 @@ struct snd_motu { int dev_lock_count; bool dev_lock_changed; wait_queue_head_t hwdep_wait; + + struct amdtp_domain domain; }; enum snd_motu_spec_flags { -- GitLab From c9a9ce899cd1798f054f264043bddc021b47cb1e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:37 +0900 Subject: [PATCH 1996/7155] ALSA: fireface: support AMDTP domain This commit adds AMDTP domain support for ALSA fireface driver. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-stream.c | 57 +++++++++++++++++------------ sound/firewire/fireface/ff.h | 2 + 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index e4710204f481..e8e6f9fd6433 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -32,9 +32,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, static inline void finish_session(struct snd_ff *ff) { - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - ff->spec->protocol->finish_session(ff); ff->spec->protocol->switch_fetching_mode(ff, false); } @@ -83,8 +80,16 @@ int snd_ff_stream_init_duplex(struct snd_ff *ff) return err; err = init_stream(ff, &ff->tx_stream); - if (err < 0) + if (err < 0) { destroy_stream(ff, &ff->rx_stream); + return err; + } + + err = amdtp_domain_init(&ff->domain); + if (err < 0) { + destroy_stream(ff, &ff->rx_stream); + destroy_stream(ff, &ff->tx_stream); + } return err; } @@ -95,6 +100,8 @@ int snd_ff_stream_init_duplex(struct snd_ff *ff) */ void snd_ff_stream_destroy_duplex(struct snd_ff *ff) { + amdtp_domain_destroy(&ff->domain); + destroy_stream(ff, &ff->rx_stream); destroy_stream(ff, &ff->tx_stream); } @@ -113,6 +120,7 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) enum snd_ff_stream_mode mode; int i; + amdtp_domain_stop(&ff->domain); finish_session(ff); fw_iso_resources_free(&ff->tx_resources); @@ -155,51 +163,52 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) return 0; if (amdtp_streaming_error(&ff->tx_stream) || - amdtp_streaming_error(&ff->rx_stream)) + amdtp_streaming_error(&ff->rx_stream)) { + amdtp_domain_stop(&ff->domain); finish_session(ff); + } /* * Regardless of current source of clock signal, drivers transfer some * packets. Then, the device transfers packets. */ if (!amdtp_stream_running(&ff->rx_stream)) { + int spd = fw_parent_device(ff->unit)->max_speed; + err = ff->spec->protocol->begin_session(ff, rate); if (err < 0) goto error; - err = amdtp_stream_start(&ff->rx_stream, - ff->rx_resources.channel, - fw_parent_device(ff->unit)->max_speed); + err = amdtp_domain_add_stream(&ff->domain, &ff->rx_stream, + ff->rx_resources.channel, spd); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&ff->rx_stream, - CALLBACK_TIMEOUT_MS)) { - err = -ETIMEDOUT; - goto error; - } - - err = ff->spec->protocol->switch_fetching_mode(ff, true); + err = amdtp_domain_add_stream(&ff->domain, &ff->tx_stream, + ff->tx_resources.channel, spd); if (err < 0) goto error; - } - if (!amdtp_stream_running(&ff->tx_stream)) { - err = amdtp_stream_start(&ff->tx_stream, - ff->tx_resources.channel, - fw_parent_device(ff->unit)->max_speed); + err = amdtp_domain_start(&ff->domain); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&ff->tx_stream, + if (!amdtp_stream_wait_callback(&ff->rx_stream, + CALLBACK_TIMEOUT_MS) || + !amdtp_stream_wait_callback(&ff->tx_stream, CALLBACK_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } + + err = ff->spec->protocol->switch_fetching_mode(ff, true); + if (err < 0) + goto error; } return 0; error: + amdtp_domain_stop(&ff->domain); finish_session(ff); return err; @@ -208,6 +217,7 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) void snd_ff_stream_stop_duplex(struct snd_ff *ff) { if (ff->substreams_counter == 0) { + amdtp_domain_stop(&ff->domain); finish_session(ff); fw_iso_resources_free(&ff->tx_resources); @@ -217,12 +227,11 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff) void snd_ff_stream_update_duplex(struct snd_ff *ff) { + amdtp_domain_stop(&ff->domain); + // The device discontinue to transfer packets. amdtp_stream_pcm_abort(&ff->tx_stream); - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_pcm_abort(&ff->rx_stream); - amdtp_stream_stop(&ff->rx_stream); } void snd_ff_stream_lock_changed(struct snd_ff *ff) diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 36dd0c75b9f7..b4c22ca6079e 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -91,6 +91,8 @@ struct snd_ff { int dev_lock_count; bool dev_lock_changed; wait_queue_head_t hwdep_wait; + + struct amdtp_domain domain; }; enum snd_ff_clock_src { -- GitLab From 74f94e41825549638a5b24410c1f62d5ea57134e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 4 Aug 2019 15:21:38 +0900 Subject: [PATCH 1997/7155] ALSA: firewire-lib: localize kernel APIs to start/stop each AMDTP stream As a result to support AMDTP domain, no drivers call kernel APIs to start/stop each AMDTP stream. This commit localize these APIs. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 6 ++---- sound/firewire/amdtp-stream.h | 2 -- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 158d210caea7..1a92855c7647 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -894,7 +894,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI * device can be started. */ -int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) +static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) { static const struct { unsigned int data_block; @@ -1027,7 +1027,6 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) return err; } -EXPORT_SYMBOL(amdtp_stream_start); /** * amdtp_stream_pcm_pointer - get the PCM buffer position @@ -1098,7 +1097,7 @@ EXPORT_SYMBOL(amdtp_stream_update); * All PCM and MIDI devices of the stream must be stopped before the stream * itself can be stopped. */ -void amdtp_stream_stop(struct amdtp_stream *s) +static void amdtp_stream_stop(struct amdtp_stream *s) { mutex_lock(&s->mutex); @@ -1118,7 +1117,6 @@ void amdtp_stream_stop(struct amdtp_stream *s) mutex_unlock(&s->mutex); } -EXPORT_SYMBOL(amdtp_stream_stop); /** * amdtp_stream_pcm_abort - abort the running PCM device diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 15d471660a43..bbbca964b9b4 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -188,9 +188,7 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, unsigned int data_block_quadlets); unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s); -int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed); void amdtp_stream_update(struct amdtp_stream *s); -void amdtp_stream_stop(struct amdtp_stream *s); int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, struct snd_pcm_runtime *runtime); -- GitLab From f21fa0606c383e8c7289ad89b4a610b441707d08 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Tue, 2 Jul 2019 08:22:51 -0400 Subject: [PATCH 1998/7155] i40e: fix incorrect ethtool statistics veb and veb.tc_ This patch fixes missing call of i40e_update_veb_stats() in function i40e_get_ethtool_stats() to update stats data of VEB and VEB TC counters before they are written into ethtool buffer. Before the patch ethtool counters may fell behind interface counters. Signed-off-by: Dmitrii Golovanov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 +++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 84bd06901014..3e535d3263b3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -1021,6 +1021,7 @@ i40e_find_vsi_by_type(struct i40e_pf *pf, u16 type) return NULL; } void i40e_update_stats(struct i40e_vsi *vsi); +void i40e_update_veb_stats(struct i40e_veb *veb); void i40e_update_eth_stats(struct i40e_vsi *vsi); struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi); int i40e_fetch_switch_configuration(struct i40e_pf *pf, diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 527eb52c5401..65e016f54f58 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2250,7 +2250,7 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; - struct i40e_veb *veb = pf->veb[pf->lan_veb]; + struct i40e_veb *veb = NULL; unsigned int i; bool veb_stats; u64 *p = data; @@ -2273,8 +2273,14 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, goto check_data_pointer; veb_stats = ((pf->lan_veb != I40E_NO_VEB) && + (pf->lan_veb < I40E_MAX_VEB) && (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)); + if (veb_stats) { + veb = pf->veb[pf->lan_veb]; + i40e_update_veb_stats(veb); + } + /* If veb stats aren't enabled, pass NULL instead of the veb so that * we initialize stats to zero and update the data pointer * intelligently diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 44da407e0bf9..d39940b9c8b7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -677,7 +677,7 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi) * i40e_update_veb_stats - Update Switch component statistics * @veb: the VEB being updated **/ -static void i40e_update_veb_stats(struct i40e_veb *veb) +void i40e_update_veb_stats(struct i40e_veb *veb) { struct i40e_pf *pf = veb->pf; struct i40e_hw *hw = &pf->hw; -- GitLab From d9f78ceb8ffacb825b1660a510ceb04258653615 Mon Sep 17 00:00:00 2001 From: Slawomir Laba Date: Tue, 2 Jul 2019 08:22:53 -0400 Subject: [PATCH 1999/7155] i40e: Log disable-fw-lldp flag change by ethtool Add logging for disable-fw-lldp flag by ethtool. Added check for I40E_FLAG_DISABLE_FW_LLDP and logging state in dmesg. Without this commit there was no clear statement in dmesg about FW LLDP state in dmesg. Signed-off-by: Slawomir Laba Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d39940b9c8b7..423a4820af4c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8486,6 +8486,11 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired) dev_dbg(&pf->pdev->dev, "PFR requested\n"); i40e_handle_reset_warning(pf, lock_acquired); + dev_info(&pf->pdev->dev, + pf->flags & I40E_FLAG_DISABLE_FW_LLDP ? + "FW LLDP is disabled\n" : + "FW LLDP is enabled\n"); + } else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) { int v; -- GitLab From 2ad1274fa35ace5c6360762ba48d33b63da2396c Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 2 Jul 2019 08:22:54 -0400 Subject: [PATCH 2000/7155] i40e: don't report link up for a VF who hasn't enabled queues Commit d3d657a90850 ("i40e: update VFs of link state after GET_VF_RESOURCES") modified the PF driver to notify a VF of its link status immediately after it requests resources. This was intended to fix reporting on VF drivers, so that they would properly report link status. However, some older VF drivers do not respond well to receiving a link up notification before queues are enabled. This can cause their state machine to think that it is safe to send traffic. This results in a Tx hang on the VF. More recent versions of the old i40evf and all versions of iavf are resilient to these early link status messages. However, if a VM happens to run an older version of the VF driver, this can be problematic. Record whether the PF has actually enabled queues for the VF. When reporting link status, always report link down if the queues aren't enabled. In this way, the VF driver will never receive a link up notification until after its queues are enabled. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 13 ++++++++++++- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 02b09a8ad54c..12f04f36e357 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -55,7 +55,12 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf) pfe.event = VIRTCHNL_EVENT_LINK_CHANGE; pfe.severity = PF_EVENT_SEVERITY_INFO; - if (vf->link_forced) { + + /* Always report link is down if the VF queues aren't enabled */ + if (!vf->queues_enabled) { + pfe.event_data.link_event.link_status = false; + pfe.event_data.link_event.link_speed = 0; + } else if (vf->link_forced) { pfe.event_data.link_event.link_status = vf->link_up; pfe.event_data.link_event.link_speed = (vf->link_up ? VIRTCHNL_LINK_SPEED_40GB : 0); @@ -65,6 +70,7 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf) pfe.event_data.link_event.link_speed = i40e_virtchnl_link_speed(ls->link_speed); } + i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT, 0, (u8 *)&pfe, sizeof(pfe), NULL); } @@ -2364,6 +2370,8 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg) } } + vf->queues_enabled = true; + error_param: /* send the response to the VF */ return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES, @@ -2385,6 +2393,9 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) struct i40e_pf *pf = vf->pf; i40e_status aq_ret = 0; + /* Immediately mark queues as disabled */ + vf->queues_enabled = false; + if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { aq_ret = I40E_ERR_PARAM; goto error_param; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index f65cc0c16550..7164b9bb294f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -99,6 +99,7 @@ struct i40e_vf { unsigned int tx_rate; /* Tx bandwidth limit in Mbps */ bool link_forced; bool link_up; /* only valid if VF link is forced */ + bool queues_enabled; /* true if the VF queues are enabled */ bool spoofchk; u16 num_mac; u16 num_vlan; -- GitLab From 6db6032298d2d7c919742e24a4bc59744bd72d62 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 2 Jul 2019 08:22:55 -0400 Subject: [PATCH 2001/7155] i40e: fix code comments Found a code comment that needed TLC to correct their formatting. Signed-off-by: Jeff Kirsher Tested-by: Andrew Bowers --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 12f04f36e357..6d0289e60e01 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2159,7 +2159,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) * VF does not know about these additional VSIs and all * it cares is about its own queues. PF configures these queues * to its appropriate VSIs based on TC mapping - **/ + */ if (vf->adq_enabled) { if (idx >= ARRAY_SIZE(vf->ch)) { aq_ret = I40E_ERR_NO_AVAILABLE_VSI; -- GitLab From 0969402fd5dd57268bb7547d7e5ece8fcd81157d Mon Sep 17 00:00:00 2001 From: Czeslaw Zagorski Date: Tue, 2 Jul 2019 08:22:56 -0400 Subject: [PATCH 2002/7155] i40e: Update visual effect for advertised FEC mode. Updates visual effect for advertised mode after setting desired mode. The mode appears in advertised FEC mode correctly, when ethtool interface command is called. Without this commit advertised FEC is displayed regardless of the settings as "None BaseR RS". Signed-off-by: Czeslaw Zagorski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 65e016f54f58..ceca57a261dc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -710,6 +710,35 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, } } +/** + * i40e_get_settings_link_up_fec - Get the FEC mode encoding from mask + * @req_fec_info: mask request FEC info + * @ks: ethtool ksettings to fill in + **/ +static void i40e_get_settings_link_up_fec(u8 req_fec_info, + struct ethtool_link_ksettings *ks) +{ + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + + if (I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) { + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + } else if (I40E_AQ_SET_FEC_REQUEST_KR & req_fec_info) { + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); + } else { + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_NONE); + if (I40E_AQ_SET_FEC_AUTO & req_fec_info) { + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); + } + } +} + /** * i40e_get_settings_link_up - Get the Link settings for when link is up * @hw: hw structure @@ -769,13 +798,7 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 25000baseSR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseSR_Full); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, advertising, - FEC_BASER); + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); ethtool_link_ksettings_add_link_mode(ks, supported, 10000baseSR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, @@ -892,9 +915,6 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 40000baseKR4_Full); ethtool_link_ksettings_add_link_mode(ks, supported, 25000baseKR_Full); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, 20000baseKR2_Full); ethtool_link_ksettings_add_link_mode(ks, supported, @@ -908,10 +928,7 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 40000baseKR4_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseKR_Full); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, advertising, - FEC_BASER); + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); ethtool_link_ksettings_add_link_mode(ks, advertising, 20000baseKR2_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, @@ -929,13 +946,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 25000baseCR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseCR_Full); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, advertising, - FEC_BASER); + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); + break; case I40E_PHY_TYPE_25GBASE_AOC: case I40E_PHY_TYPE_25GBASE_ACC: @@ -945,13 +957,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 25000baseCR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseCR_Full); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); - ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); - ethtool_link_ksettings_add_link_mode(ks, advertising, - FEC_BASER); + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); + ethtool_link_ksettings_add_link_mode(ks, supported, 10000baseCR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, -- GitLab From b603f9dc20afed5e4666642c8713cafb94a23058 Mon Sep 17 00:00:00 2001 From: Czeslaw Zagorski Date: Tue, 2 Jul 2019 08:22:57 -0400 Subject: [PATCH 2003/7155] i40e: Log info when PF is entering and leaving Allmulti mode. Add log when PF is entering and leaving allmulti mode. The change of PF state is visible in dmesg now. Without this commit, entering and leaving allmulti mode is not logged in dmesg. Signed-off-by: Czeslaw Zagorski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 423a4820af4c..6d456e579314 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2530,6 +2530,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) vsi_name, i40e_stat_str(hw, aq_ret), i40e_aq_str(hw, hw->aq.asq_last_status)); + } else { + dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n", + vsi->netdev->name, + cur_multipromisc ? "entering" : "leaving"); } } -- GitLab From b27223591606f59c1f7c042b8e3dc74affadf492 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 2 Jul 2019 08:22:58 -0400 Subject: [PATCH 2004/7155] i40e: verify string count matches even on early return Similar to i40e_get_ethtool_stats, add a goto to verify that the data pointer for the strings lines up with the expected stats count. This helps ensure that bugs are not introduced when adding stats. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index ceca57a261dc..01e4615b1b4b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2342,7 +2342,7 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) } if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) - return; + goto check_data_pointer; i40e_add_stat_strings(&data, i40e_gstrings_veb_stats); @@ -2354,6 +2354,7 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) i40e_add_stat_strings(&data, i40e_gstrings_pfc_stats, i); +check_data_pointer: WARN_ONCE(data - p != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN, "stat strings count mismatch!"); } -- GitLab From 558e93c93f7843297752db6c491517b311bfb19a Mon Sep 17 00:00:00 2001 From: Czeslaw Zagorski Date: Tue, 2 Jul 2019 08:22:59 -0400 Subject: [PATCH 2005/7155] i40e: Remove unicast log when VF is leaving multicast mode. This patch removes unicast log when VF is leaving multicast mode. Added check of vf->vf_states & I40E_VF_STATE_MC_PROMISC/I40E_VF_STATE_UC_PROMISC. Without this commit, leaving multicast mode logs "unset unicast" in dmsg. Signed-off-by: Czeslaw Zagorski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 6d0289e60e01..4601f9e4e998 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2043,30 +2043,33 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) alluni = true; aq_ret = i40e_config_vf_promiscuous_mode(vf, info->vsi_id, allmulti, alluni); - if (!aq_ret) { - if (allmulti) { + if (aq_ret) + goto err_out; + + if (allmulti) { + if (!test_and_set_bit(I40E_VF_STATE_MC_PROMISC, + &vf->vf_states)) dev_info(&pf->pdev->dev, "VF %d successfully set multicast promiscuous mode\n", vf->vf_id); - set_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states); - } else { - dev_info(&pf->pdev->dev, - "VF %d successfully unset multicast promiscuous mode\n", - vf->vf_id); - clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states); - } - if (alluni) { + } else if (test_and_clear_bit(I40E_VF_STATE_MC_PROMISC, + &vf->vf_states)) + dev_info(&pf->pdev->dev, + "VF %d successfully unset multicast promiscuous mode\n", + vf->vf_id); + + if (alluni) { + if (!test_and_set_bit(I40E_VF_STATE_UC_PROMISC, + &vf->vf_states)) dev_info(&pf->pdev->dev, "VF %d successfully set unicast promiscuous mode\n", vf->vf_id); - set_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states); - } else { - dev_info(&pf->pdev->dev, - "VF %d successfully unset unicast promiscuous mode\n", - vf->vf_id); - clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states); - } - } + } else if (test_and_clear_bit(I40E_VF_STATE_UC_PROMISC, + &vf->vf_states)) + dev_info(&pf->pdev->dev, + "VF %d successfully unset unicast promiscuous mode\n", + vf->vf_id); + err_out: /* send the response to the VF */ return i40e_vc_send_resp_to_vf(vf, -- GitLab From 43a4b60d04362185cd5475fd77a02bf6c56c07e4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 1 Aug 2019 15:18:08 -0700 Subject: [PATCH 2006/7155] ipv6: have a single rcu unlock point in __ip6_rt_update_pmtu Simplify the unlock path in __ip6_rt_update_pmtu by using a single point where rcu_read_unlock is called. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- net/ipv6/route.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e49fec767a10..3c5c331b50f1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2725,10 +2725,9 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, rcu_read_lock(); res.f6i = rcu_dereference(rt6->from); - if (!res.f6i) { - rcu_read_unlock(); - return; - } + if (!res.f6i) + goto out_unlock; + res.fib6_flags = res.f6i->fib6_flags; res.fib6_type = res.f6i->fib6_type; @@ -2744,10 +2743,8 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, /* fib6_info uses a nexthop that does not have fib6_nh * using the dst->dev + gw. Should be impossible. */ - if (!arg.match) { - rcu_read_unlock(); - return; - } + if (!arg.match) + goto out_unlock; res.nh = arg.match; } else { @@ -2760,6 +2757,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, if (rt6_insert_exception(nrt6, &res)) dst_release_immediate(&nrt6->dst); } +out_unlock: rcu_read_unlock(); } } -- GitLab From 0dfa0bed9662db680db2cc06457b8d152a2f22af Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 2 Aug 2019 02:17:51 -0400 Subject: [PATCH 2007/7155] cnic: Explicitly initialize all reference counts to 0. The driver is relying on zero'ed allocated memory and does not explicitly call atomic_set() to initialize the ref counts to 0. Add these atomic_set() calls so that it will be more straight forward to convert atomic ref counts to refcount_t. Reported-by: Chuhong Yuan Cc: Rasesh Mody Cc: Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/cnic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 57dc3cbff36e..155599dcee76 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -4096,12 +4096,16 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; u32 port_id; + int i; cp->csk_tbl = kvcalloc(MAX_CM_SK_TBL_SZ, sizeof(struct cnic_sock), GFP_KERNEL); if (!cp->csk_tbl) return -ENOMEM; + for (i = 0; i < MAX_CM_SK_TBL_SZ; i++) + atomic_set(&cp->csk_tbl[i].ref_count, 0); + port_id = prandom_u32(); port_id %= CNIC_LOCAL_PORT_RANGE; if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE, @@ -5480,6 +5484,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev, cdev->unregister_device = cnic_unregister_device; cdev->iscsi_nl_msg_recv = cnic_iscsi_nl_msg_recv; cdev->get_fc_npiv_tbl = cnic_get_fc_npiv_tbl; + atomic_set(&cdev->ref_count, 0); cp = cdev->cnic_priv; cp->dev = cdev; -- GitLab From 3a760d986568b67d1f8411dab64608075817b90d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:02:17 +0200 Subject: [PATCH 2008/7155] soc: amlogic: meson-clk-measure: protect measure with a mutex In order to protect clock measuring when multiple process asks for a measure, protect the main measure function with mutexes. Reviewed-by: Kevin Hilman Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman --- drivers/soc/amlogic/meson-clk-measure.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 19d4cbc93a17..c470e24f1dfa 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -11,6 +11,8 @@ #include #include +static DEFINE_MUTEX(measure_lock); + #define MSR_CLK_DUTY 0x0 #define MSR_CLK_REG0 0x4 #define MSR_CLK_REG1 0x8 @@ -360,6 +362,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id, unsigned int val; int ret; + ret = mutex_lock_interruptible(&measure_lock); + if (ret) + return ret; + regmap_write(priv->regmap, MSR_CLK_REG0, 0); /* Set measurement duration */ @@ -377,8 +383,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id, ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0, val, !(val & MSR_BUSY), 10, 10000); - if (ret) + if (ret) { + mutex_unlock(&measure_lock); return ret; + } /* Disable */ regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0); @@ -386,6 +394,8 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id, /* Get the value in multiple of gate time counts */ regmap_read(priv->regmap, MSR_CLK_REG2, &val); + mutex_unlock(&measure_lock); + if (val >= MSR_VAL_MASK) return -EINVAL; -- GitLab From c33b2777d01eb0039a53f14f8c0e4cca8df501c7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:02:18 +0200 Subject: [PATCH 2009/7155] soc: amlogic: meson-clk-measure: add G12B second cluster cpu clk Add the G12B second CPU cluster CPU and SYS_PLL measure IDs. These IDs returns 0Hz on G12A. Reviewed-by: Kevin Hilman Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman --- drivers/soc/amlogic/meson-clk-measure.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index c470e24f1dfa..f09b404b39d3 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -324,6 +324,8 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = { CLK_MSR_ID(84, "co_tx"), CLK_MSR_ID(89, "hdmi_todig"), CLK_MSR_ID(90, "hdmitx_sys"), + CLK_MSR_ID(91, "sys_cpub_div16"), + CLK_MSR_ID(92, "sys_pll_cpub_div16"), CLK_MSR_ID(94, "eth_phy_rx"), CLK_MSR_ID(95, "eth_phy_pll"), CLK_MSR_ID(96, "vpu_b"), -- GitLab From 4f0303d43973a4086d6355db0c653a5a369b5dbe Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 18 Jul 2019 11:36:23 +0200 Subject: [PATCH 2010/7155] ARM: dts: meson8b: add ethernet fifo sizes If unspecified in DT, the fifo sizes are not automatically detected by the dwmac1000 dma driver and the reported fifo sizes default to 0. Because of this, flow control will be turned off on the device. Add the fifo sizes provided by the datasheet in the SoC in DT so flow control may be enabled if necessary. Signed-off-by: Jerome Brunet Reviewed-by: Martin Blumenstingl Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index fba2c70c2fda..b044ad78b475 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -410,6 +410,8 @@ <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL2>; clock-names = "stmmaceth", "clkin0", "clkin1"; + rx-fifo-depth = <4096>; + tx-fifo-depth = <2048>; resets = <&reset RESET_ETHERNET>; reset-names = "stmmaceth"; -- GitLab From ea241bdfa0ba632416a828ddaa2fde33f30de530 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:12:54 +0200 Subject: [PATCH 2011/7155] ARM: dts: meson8b: add the PWM_D output pin The PWM_D output is used for the VDDEE PWM regulator which supplies for example the Mali GPU on the EC-100 and Odroid-C1 boards. Add the output pin the VDDEE regulators can be added. Signed-off-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index b044ad78b475..099bf8e711c9 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -361,6 +361,14 @@ }; }; + pwm_d_pins: pwm-d { + mux { + groups = "pwm_d"; + function = "pwm_d"; + bias-disable; + }; + }; + uart_b0_pins: uart-b0 { mux { groups = "uart_tx_b0", -- GitLab From 087a1d8b4e4cd0f84bde82e21bad83ea3d00a216 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:12:55 +0200 Subject: [PATCH 2012/7155] ARM: dts: meson8b: ec100: add the VDDEE regulator The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b-ec100.dts | 31 ++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/meson8b-ec100.dts index 96d239d8334e..bed1dfef1985 100644 --- a/arch/arm/boot/dts/meson8b-ec100.dts +++ b/arch/arm/boot/dts/meson8b-ec100.dts @@ -219,6 +219,27 @@ */ vin-supply = <&vcc_3v3>; }; + + vddee: regulator-vddee { + /* + * Silergy SY8089AAC-GP 2A continuous, 3A peak, 1MHz + * Synchronous Step Down Regulator. Also called VDDAO + * in a part of the schematics. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1140000>; + + vin-supply = <&vcc_5v>; + + pwms = <&pwm_cd 1 1148 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; }; &cpu0 { @@ -269,6 +290,10 @@ }; }; +&mali { + mali-supply = <&vddee>; +}; + &saradc { status = "okay"; vref-supply = <&vcc_1v8>; @@ -350,10 +375,10 @@ &pwm_cd { status = "okay"; - pinctrl-0 = <&pwm_c1_pins>; + pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>; pinctrl-names = "default"; - clocks = <&clkc CLKID_XTAL>; - clock-names = "clkin0"; + clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; &rtc { -- GitLab From 8bdf38be712d49093e51e3cf754fd427d4685ba0 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:12:56 +0200 Subject: [PATCH 2013/7155] ARM: dts: meson8b: odroidc1: add the VDDEE regulator The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b-odroidc1.dts | 27 +++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts index 86c4614e0a38..90f66dc45115 100644 --- a/arch/arm/boot/dts/meson8b-odroidc1.dts +++ b/arch/arm/boot/dts/meson8b-odroidc1.dts @@ -154,6 +154,23 @@ vin-supply = <&p5v0>; }; + vddee: regulator-vddee { + /* Monolithic Power Systems MP2161 */ + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1140000>; + + vin-supply = <&p5v0>; + + pwms = <&pwm_cd 1 12218 0>; + pwm-dutycycle-range = <91 0>; + + regulator-boot-on; + regulator-always-on; + }; + vdd_rtc: regulator-vdd-rtc { /* * Torex Semiconductor XC6215 configured for a fixed output of @@ -276,6 +293,10 @@ pinctrl-names = "default"; }; +&mali { + mali-supply = <&vddee>; +}; + &saradc { status = "okay"; vref-supply = <&vcc_1v8>; @@ -308,10 +329,10 @@ &pwm_cd { status = "okay"; - pinctrl-0 = <&pwm_c1_pins>; + pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>; pinctrl-names = "default"; - clocks = <&clkc CLKID_XTAL>; - clock-names = "clkin0"; + clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; &rtc { -- GitLab From dee51cd0d2e8af08c74e5bbb10673af1cf0ee4a3 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:12:57 +0200 Subject: [PATCH 2014/7155] ARM: dts: meson8b: mxq: add the VDDEE regulator The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b-mxq.dts | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts index bb27b34eb346..6e39ad52e42d 100644 --- a/arch/arm/boot/dts/meson8b-mxq.dts +++ b/arch/arm/boot/dts/meson8b-mxq.dts @@ -76,6 +76,22 @@ regulator-boot-on; regulator-always-on; }; + + vddee: regulator-vddee { + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1140000>; + + vin-supply = <&vcc_5v>; + + pwms = <&pwm_cd 1 1148 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; }; &cpu0 { @@ -112,6 +128,10 @@ }; }; +&mali { + mali-supply = <&vddee>; +}; + &saradc { status = "okay"; vref-supply = <&vcc_1v8>; @@ -143,10 +163,10 @@ &pwm_cd { status = "okay"; - pinctrl-0 = <&pwm_c1_pins>; + pinctrl-0 = <&pwm_c1_pins>, <&pwm_d_pins>; pinctrl-names = "default"; - clocks = <&clkc CLKID_XTAL>; - clock-names = "clkin0"; + clocks = <&clkc CLKID_XTAL>, <&clkc CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; &uart_AO { -- GitLab From 887e54218183a2665c4dc59aa10477185145fad9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 18 Jun 2019 17:16:02 -0700 Subject: [PATCH 2015/7155] arm64: dts: qcom: msm8996: Rename smmu nodes Node names shouldn't include a vendor prefix and should whenever possible use a generic identifier. Resolve this by renaming the smmu nodes "iommu". Reviewed-by: Vivek Gautam Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 96c0a481f454..1a139cfb240d 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -1163,7 +1163,7 @@ }; }; - vfe_smmu: arm,smmu@da0000 { + vfe_smmu: iommu@da0000 { compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; reg = <0xda0000 0x10000>; @@ -1314,7 +1314,7 @@ }; }; - adreno_smmu: arm,smmu@b40000 { + adreno_smmu: iommu@b40000 { compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; reg = <0xb40000 0x10000>; @@ -1331,7 +1331,7 @@ power-domains = <&mmcc GPU_GDSC>; }; - mdp_smmu: arm,smmu@d00000 { + mdp_smmu: iommu@d00000 { compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; reg = <0xd00000 0x10000>; @@ -1347,7 +1347,7 @@ power-domains = <&mmcc MDSS_GDSC>; }; - lpass_q6_smmu: arm,smmu-lpass_q6@1600000 { + lpass_q6_smmu: iommu@1600000 { compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; reg = <0x1600000 0x20000>; #iommu-cells = <1>; -- GitLab From 0baf212eab4daf8e4882afd624e1403846418610 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Wed, 31 Jul 2019 14:39:55 +0200 Subject: [PATCH 2016/7155] soc: amlogic: meson-gx-socinfo: add A311D id Add the SoC ID for the A311D Amlogic SoC. Signed-off-by: Christian Hewitt Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/soc/amlogic/meson-gx-socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c index bca34954518e..ff86a75939e8 100644 --- a/drivers/soc/amlogic/meson-gx-socinfo.c +++ b/drivers/soc/amlogic/meson-gx-socinfo.c @@ -65,6 +65,7 @@ static const struct meson_gx_package_id { { "S905D2", 0x28, 0x10, 0xf0 }, { "S905X2", 0x28, 0x40, 0xf0 }, { "S922X", 0x29, 0x40, 0xf0 }, + { "A311D", 0x29, 0x10, 0xf0 }, }; static inline unsigned int socinfo_to_major(u32 socinfo) -- GitLab From ba0411ddd133b34fd715f17b9c0c29027bfa92a8 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Wed, 10 Jul 2019 16:59:24 +0530 Subject: [PATCH 2017/7155] arm64: dts: sdm845: Add device node for Last level cache controller Last level cache (aka. system cache) controller provides control over the last level cache present on SDM845. This cache lies after the memory noc, right before the DDR. Signed-off-by: Sai Prakash Ranjan Signed-off-by: Vivek Gautam Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index c8ebe21f7673..40ec8231b585 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1275,6 +1275,13 @@ }; }; + cache-controller@1100000 { + compatible = "qcom,sdm845-llcc"; + reg = <0 0x01100000 0 0x200000>, <0 0x01300000 0 0x50000>; + reg-names = "llcc_base", "llcc_broadcast_base"; + interrupts = ; + }; + ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; -- GitLab From f65018264cb1ae2777b39a3c36cea012c5684bac Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 1 Aug 2019 15:20:47 +0530 Subject: [PATCH 2018/7155] arm64: dts: qcom: pms405: add unit name adc nodes The adc nodes have reg property but were missing the unit name, so add that to fix these warnings: arch/arm64/boot/dts/qcom/pms405.dtsi:91.12-94.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/ref_gnd: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:96.14-99.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/vref_1p25: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:101.19-104.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/vph_pwr: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:106.13-109.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/die_temp: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:111.27-116.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/thermistor1: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:118.27-123.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/thermistor3: node has a reg or ranges property, but no unit name arch/arm64/boot/dts/qcom/pms405.dtsi:125.22-130.6: Warning (unit_address_vs_reg): /soc@0/spmi@200f000/pms405@0/adc@3100/xo_temp: node has a reg or ranges property, but no unit name Reviewed-by: Amit Kucheria Signed-off-by: Vinod Koul Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pms405.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi index 14240fedd916..a28386900a3b 100644 --- a/arch/arm64/boot/dts/qcom/pms405.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405.dtsi @@ -88,41 +88,41 @@ #size-cells = <0>; #io-channel-cells = <1>; - ref_gnd { + ref_gnd@0 { reg = ; qcom,pre-scaling = <1 1>; }; - vref_1p25 { + vref_1p25@1 { reg = ; qcom,pre-scaling = <1 1>; }; - pon_1: vph_pwr { + pon_1: vph_pwr@131 { reg = ; qcom,pre-scaling = <1 3>; }; - die_temp { + die_temp@6 { reg = ; qcom,pre-scaling = <1 1>; }; - pa_therm1: thermistor1 { + pa_therm1: thermistor1@77 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; qcom,pre-scaling = <1 1>; }; - pa_therm3: thermistor3 { + pa_therm3: thermistor3@79 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; qcom,pre-scaling = <1 1>; }; - xo_therm: xo_temp { + xo_therm: xo_temp@76 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; -- GitLab From cbf7f748f27684fee169252070e7b2d76fe81f22 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 1 Aug 2019 15:20:48 +0530 Subject: [PATCH 2019/7155] arm64: dts: qcom: pms405: remove reduandant properties pms405@1 nodes specified unnecessary #address-cells/#size-cells but the subnodes dont have "ranges" or "reg" so remove it arch/arm64/boot/dts/qcom/pms405.dtsi:141.21-150.4: Warning (avoid_unnecessary_addr_size): /soc@0/spmi@200f000/pms405@1: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property Signed-off-by: Vinod Koul Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pms405.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi index a28386900a3b..ff4005186895 100644 --- a/arch/arm64/boot/dts/qcom/pms405.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405.dtsi @@ -141,8 +141,6 @@ pms405_1: pms405@1 { compatible = "qcom,spmi-pmic"; reg = <0x1 SPMI_USID>; - #address-cells = <1>; - #size-cells = <0>; pms405_spmi_regulators: regulators { compatible = "qcom,pms405-regulators"; -- GitLab From e8c48eb08ab1446b8bc2b99c2254b4505945adb1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 1 Aug 2019 15:20:49 +0530 Subject: [PATCH 2020/7155] arm64: dts: qcom: qcs404: remove unit name for thermal trip points The thermal trip points have unit name but no reg property, so we can remove them arch/arm64/boot/dts/qcom/qcs404.dtsi:1080.31-1084.7: Warning (unit_address_vs_reg): /thermal-zones/aoss-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1095.33-1099.7: Warning (unit_address_vs_reg): /thermal-zones/q6-hvx-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1110.32-1114.7: Warning (unit_address_vs_reg): /thermal-zones/lpass-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1125.31-1129.7: Warning (unit_address_vs_reg): /thermal-zones/wlan-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1140.34-1144.7: Warning (unit_address_vs_reg): /thermal-zones/cluster-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1145.34-1149.7: Warning (unit_address_vs_reg): /thermal-zones/cluster-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1174.31-1178.7: Warning (unit_address_vs_reg): /thermal-zones/cpu0-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1179.31-1183.7: Warning (unit_address_vs_reg): /thermal-zones/cpu0-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1208.31-1212.7: Warning (unit_address_vs_reg): /thermal-zones/cpu1-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1213.31-1217.7: Warning (unit_address_vs_reg): /thermal-zones/cpu1-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1242.31-1246.7: Warning (unit_address_vs_reg): /thermal-zones/cpu2-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1247.31-1251.7: Warning (unit_address_vs_reg): /thermal-zones/cpu2-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1276.31-1280.7: Warning (unit_address_vs_reg): /thermal-zones/cpu3-thermal/trips/trip-point@0: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1281.31-1285.7: Warning (unit_address_vs_reg): /thermal-zones/cpu3-thermal/trips/trip-point@1: node has a unit name, but no reg property arch/arm64/boot/dts/qcom/qcs404.dtsi:1310.30-1314.7: Warning (unit_address_vs_reg): /thermal-zones/gpu-thermal/trips/trip-point@0: node has a unit name, but no reg property Signed-off-by: Vinod Koul Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/qcs404.dtsi | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi index 3d0789775009..6d91dae5aee0 100644 --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi @@ -1077,7 +1077,7 @@ thermal-sensors = <&tsens 0>; trips { - aoss_alert0: trip-point@0 { + aoss_alert0: trip-point0 { temperature = <105000>; hysteresis = <2000>; type = "hot"; @@ -1092,7 +1092,7 @@ thermal-sensors = <&tsens 1>; trips { - q6_hvx_alert0: trip-point@0 { + q6_hvx_alert0: trip-point0 { temperature = <105000>; hysteresis = <2000>; type = "hot"; @@ -1107,7 +1107,7 @@ thermal-sensors = <&tsens 2>; trips { - lpass_alert0: trip-point@0 { + lpass_alert0: trip-point0 { temperature = <105000>; hysteresis = <2000>; type = "hot"; @@ -1122,7 +1122,7 @@ thermal-sensors = <&tsens 3>; trips { - wlan_alert0: trip-point@0 { + wlan_alert0: trip-point0 { temperature = <105000>; hysteresis = <2000>; type = "hot"; @@ -1137,12 +1137,12 @@ thermal-sensors = <&tsens 4>; trips { - cluster_alert0: trip-point@0 { + cluster_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; }; - cluster_alert1: trip-point@1 { + cluster_alert1: trip-point1 { temperature = <105000>; hysteresis = <2000>; type = "passive"; @@ -1171,12 +1171,12 @@ thermal-sensors = <&tsens 5>; trips { - cpu0_alert0: trip-point@0 { + cpu0_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; }; - cpu0_alert1: trip-point@1 { + cpu0_alert1: trip-point1 { temperature = <105000>; hysteresis = <2000>; type = "passive"; @@ -1205,12 +1205,12 @@ thermal-sensors = <&tsens 6>; trips { - cpu1_alert0: trip-point@0 { + cpu1_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; }; - cpu1_alert1: trip-point@1 { + cpu1_alert1: trip-point1 { temperature = <105000>; hysteresis = <2000>; type = "passive"; @@ -1239,12 +1239,12 @@ thermal-sensors = <&tsens 7>; trips { - cpu2_alert0: trip-point@0 { + cpu2_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; }; - cpu2_alert1: trip-point@1 { + cpu2_alert1: trip-point1 { temperature = <105000>; hysteresis = <2000>; type = "passive"; @@ -1273,12 +1273,12 @@ thermal-sensors = <&tsens 8>; trips { - cpu3_alert0: trip-point@0 { + cpu3_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; }; - cpu3_alert1: trip-point@1 { + cpu3_alert1: trip-point1 { temperature = <105000>; hysteresis = <2000>; type = "passive"; @@ -1307,7 +1307,7 @@ thermal-sensors = <&tsens 9>; trips { - gpu_alert0: trip-point@0 { + gpu_alert0: trip-point0 { temperature = <95000>; hysteresis = <2000>; type = "hot"; -- GitLab From d32bb89c9a45a95b8fa0a731352062814805cc3c Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 31 Jul 2019 17:37:04 +0530 Subject: [PATCH 2021/7155] arm64: dts: qcom: qcs404: Add wifi rails in QCS404 dt node for proxy votes Add wifi regulators in qcs404 dt node for proxy vote. Proxy votes are required for handling driver recovery scenarios to prevent un-clocked register access during driver recovery. Signed-off-by: Govind Singh Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/qcs404-evb.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi index 11c0a7137823..2289b01ee9f0 100644 --- a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi @@ -270,6 +270,9 @@ &wifi { status = "okay"; + vdd-0.8-cx-mx-supply = <&vreg_l2_1p275>; + vdd-1.8-xo-supply = <&vreg_l5_1p8>; + vdd-1.3-rfa-supply = <&vreg_l1_1p3>; }; /* PINCTRL - additions to nodes defined in qcs404.dtsi */ -- GitLab From e3c5bc562a5f38b76affc89bdeb2dd83a0014b3e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 15:40:20 +0200 Subject: [PATCH 2022/7155] arm64: dts: qcom: sdm845-cheza: Spelling s/conenctors/connectors/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi index 9b27b8346ba1..34881c0113cb 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi @@ -745,7 +745,7 @@ ap_ts_i2c: &i2c14 { * All the hardware muxes would allow us to hook things up in different * ways to some potential benefit for static configurations (you could * achieve extra USB2 bandwidth by using two different ports for the - * two conenctors or possibly even get USB3 peripheral mode), but in + * two connectors or possibly even get USB3 peripheral mode), but in * each case you end up forcing to disconnect/reconnect an in-use * USB session in some cases depending on what you hotplug into the * other connector. Thus hardcoding this as peripheral makes sense. -- GitLab From 9aebf4de220344e2f03ae6386272bf98f80fd295 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 24 Jul 2019 04:05:11 +0530 Subject: [PATCH 2023/7155] base: soc: Add serial_number attribute to soc Add new attribute named "serial_number" as a standard interface for user space to acquire the serial number of the device. For ST-Ericsson SoCs this is exposed by the cryptically named "soc_id" attribute, but this provides a human readable standardized name for this property. Tested-by: Vinod Koul Signed-off-by: Bjorn Andersson Signed-off-by: Vaishali Thakkar Reviewed-by: Greg Kroah-Hartman Reviewed-by: Stephen Boyd Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson --- Documentation/ABI/testing/sysfs-devices-soc | 7 +++++++ drivers/base/soc.c | 7 +++++++ include/linux/sys_soc.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-devices-soc b/Documentation/ABI/testing/sysfs-devices-soc index 6d9cc253f2b2..ba3a3fac0ee1 100644 --- a/Documentation/ABI/testing/sysfs-devices-soc +++ b/Documentation/ABI/testing/sysfs-devices-soc @@ -26,6 +26,13 @@ Description: Read-only attribute common to all SoCs. Contains SoC family name (e.g. DB8500). +What: /sys/devices/socX/serial_number +Date: January 2019 +contact: Bjorn Andersson +Description: + Read-only attribute supported by most SoCs. Contains the SoC's + serial number, if available. + What: /sys/devices/socX/soc_id Date: January 2012 contact: Lee Jones diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 10b280f30217..b0933b9fe67f 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -33,6 +33,7 @@ static struct bus_type soc_bus_type = { static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL); static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL); +static DEVICE_ATTR(serial_number, S_IRUGO, soc_info_get, NULL); static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL); static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL); @@ -57,6 +58,9 @@ static umode_t soc_attribute_mode(struct kobject *kobj, if ((attr == &dev_attr_revision.attr) && (soc_dev->attr->revision != NULL)) return attr->mode; + if ((attr == &dev_attr_serial_number.attr) + && (soc_dev->attr->serial_number != NULL)) + return attr->mode; if ((attr == &dev_attr_soc_id.attr) && (soc_dev->attr->soc_id != NULL)) return attr->mode; @@ -77,6 +81,8 @@ static ssize_t soc_info_get(struct device *dev, return sprintf(buf, "%s\n", soc_dev->attr->family); if (attr == &dev_attr_revision) return sprintf(buf, "%s\n", soc_dev->attr->revision); + if (attr == &dev_attr_serial_number) + return sprintf(buf, "%s\n", soc_dev->attr->serial_number); if (attr == &dev_attr_soc_id) return sprintf(buf, "%s\n", soc_dev->attr->soc_id); @@ -87,6 +93,7 @@ static ssize_t soc_info_get(struct device *dev, static struct attribute *soc_attr[] = { &dev_attr_machine.attr, &dev_attr_family.attr, + &dev_attr_serial_number.attr, &dev_attr_soc_id.attr, &dev_attr_revision.attr, NULL, diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h index b7c70c3e953f..48ceea867dd6 100644 --- a/include/linux/sys_soc.h +++ b/include/linux/sys_soc.h @@ -12,6 +12,7 @@ struct soc_device_attribute { const char *machine; const char *family; const char *revision; + const char *serial_number; const char *soc_id; const void *data; }; -- GitLab From f7ccc7a397cf2ef64aebb2f726970b93203858d2 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Jul 2019 04:05:12 +0530 Subject: [PATCH 2024/7155] base: soc: Export soc_device_register/unregister APIs Qcom Socinfo driver can be built as a module, so export these two APIs. Tested-by: Vinod Koul Signed-off-by: Vinod Koul Signed-off-by: Vaishali Thakkar Reviewed-by: Greg Kroah-Hartman Reviewed-by: Stephen Boyd Reviewed-by: Bjorn Andersson Signed-off-by: Bjorn Andersson --- drivers/base/soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/soc.c b/drivers/base/soc.c index b0933b9fe67f..7c0c5ca5953d 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -164,6 +164,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr out1: return ERR_PTR(ret); } +EXPORT_SYMBOL_GPL(soc_device_register); /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ void soc_device_unregister(struct soc_device *soc_dev) @@ -173,6 +174,7 @@ void soc_device_unregister(struct soc_device *soc_dev) device_unregister(&soc_dev->dev); early_soc_dev_attr = NULL; } +EXPORT_SYMBOL_GPL(soc_device_unregister); static int __init soc_bus_register(void) { -- GitLab From efb448d0a3fca01bb987dd70963da6185b81751e Mon Sep 17 00:00:00 2001 From: Imran Khan Date: Wed, 24 Jul 2019 04:05:13 +0530 Subject: [PATCH 2025/7155] soc: qcom: Add socinfo driver The Qualcomm socinfo driver exposes information about the SoC, its version and its serial number to user space. Tested-by: Vinod Koul Reviewed-by: Vinod Koul Signed-off-by: Imran Khan [Bjorn: Extract code to platform_driver, split patch in multiple] Signed-off-by: Bjorn Andersson [Vaishali: Simplify declarations, introduce qcom_socinfo struct, Fix memory leak, Remove extra code and Misc code refactoring] Signed-off-by: Vaishali Thakkar Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/Kconfig | 8 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/smem.c | 9 ++ drivers/soc/qcom/socinfo.c | 194 +++++++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/soc/qcom/socinfo.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index a6d1bfb17279..661e47acc354 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -175,6 +175,14 @@ config QCOM_SMSM Say yes here to support the Qualcomm Shared Memory State Machine. The state machine is represented by bits in shared memory. +config QCOM_SOCINFO + tristate "Qualcomm socinfo driver" + depends on QCOM_SMEM + select SOC_BUS + help + Say yes here to support the Qualcomm socinfo driver, providing + information about the SoC to user space. + config QCOM_WCNSS_CTRL tristate "Qualcomm WCNSS control driver" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index eeb088beb15f..162788701a77 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_QCOM_SMEM) += smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QCOM_SMSM) += smsm.o +obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o obj-$(CONFIG_QCOM_APR) += apr.o obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index f27c00d82ae4..0caf67e2f037 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -268,6 +268,7 @@ struct qcom_smem { struct smem_partition_header *partitions[SMEM_HOST_COUNT]; size_t cacheline[SMEM_HOST_COUNT]; u32 item_count; + struct platform_device *socinfo; unsigned num_regions; struct smem_region regions[]; @@ -963,11 +964,19 @@ static int qcom_smem_probe(struct platform_device *pdev) __smem = smem; + smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", + PLATFORM_DEVID_NONE, NULL, + 0); + if (IS_ERR(smem->socinfo)) + dev_dbg(&pdev->dev, "failed to register socinfo device\n"); + return 0; } static int qcom_smem_remove(struct platform_device *pdev) { + platform_device_unregister(__smem->socinfo); + hwspin_lock_free(__smem->hwlock); __smem = NULL; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c new file mode 100644 index 000000000000..1b9eb44df7fe --- /dev/null +++ b/drivers/soc/qcom/socinfo.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * SoC version type with major number in the upper 16 bits and minor + * number in the lower 16 bits. + */ +#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff) +#define SOCINFO_MINOR(ver) ((ver) & 0xffff) + +#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 + +/* + * SMEM item id, used to acquire handles to respective + * SMEM region. + */ +#define SMEM_HW_SW_BUILD_ID 137 + +/* Socinfo SMEM item structure */ +struct socinfo { + __le32 fmt; + __le32 id; + __le32 ver; + char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; + /* Version 2 */ + __le32 raw_id; + __le32 raw_ver; + /* Version 3 */ + __le32 hw_plat; + /* Version 4 */ + __le32 plat_ver; + /* Version 5 */ + __le32 accessory_chip; + /* Version 6 */ + __le32 hw_plat_subtype; + /* Version 7 */ + __le32 pmic_model; + __le32 pmic_die_rev; + /* Version 8 */ + __le32 pmic_model_1; + __le32 pmic_die_rev_1; + __le32 pmic_model_2; + __le32 pmic_die_rev_2; + /* Version 9 */ + __le32 foundry_id; + /* Version 10 */ + __le32 serial_num; + /* Version 11 */ + __le32 num_pmics; + __le32 pmic_array_offset; + /* Version 12 */ + __le32 chip_family; + __le32 raw_device_family; + __le32 raw_device_num; +}; + +struct qcom_socinfo { + struct soc_device *soc_dev; + struct soc_device_attribute attr; +}; + +struct soc_id { + unsigned int id; + const char *name; +}; + +static const struct soc_id soc_id[] = { + { 87, "MSM8960" }, + { 109, "APQ8064" }, + { 122, "MSM8660A" }, + { 123, "MSM8260A" }, + { 124, "APQ8060A" }, + { 126, "MSM8974" }, + { 130, "MPQ8064" }, + { 138, "MSM8960AB" }, + { 139, "APQ8060AB" }, + { 140, "MSM8260AB" }, + { 141, "MSM8660AB" }, + { 178, "APQ8084" }, + { 184, "APQ8074" }, + { 185, "MSM8274" }, + { 186, "MSM8674" }, + { 194, "MSM8974PRO" }, + { 206, "MSM8916" }, + { 208, "APQ8074-AA" }, + { 209, "APQ8074-AB" }, + { 210, "APQ8074PRO" }, + { 211, "MSM8274-AA" }, + { 212, "MSM8274-AB" }, + { 213, "MSM8274PRO" }, + { 214, "MSM8674-AA" }, + { 215, "MSM8674-AB" }, + { 216, "MSM8674PRO" }, + { 217, "MSM8974-AA" }, + { 218, "MSM8974-AB" }, + { 246, "MSM8996" }, + { 247, "APQ8016" }, + { 248, "MSM8216" }, + { 249, "MSM8116" }, + { 250, "MSM8616" }, + { 291, "APQ8096" }, + { 305, "MSM8996SG" }, + { 310, "MSM8996AU" }, + { 311, "APQ8096AU" }, + { 312, "APQ8096SG" }, +}; + +static const char *socinfo_machine(struct device *dev, unsigned int id) +{ + int idx; + + for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) { + if (soc_id[idx].id == id) + return soc_id[idx].name; + } + + return NULL; +} + +static int qcom_socinfo_probe(struct platform_device *pdev) +{ + struct qcom_socinfo *qs; + struct socinfo *info; + size_t item_size; + + info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, + &item_size); + if (IS_ERR(info)) { + dev_err(&pdev->dev, "Couldn't find socinfo\n"); + return PTR_ERR(info); + } + + qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL); + if (!qs) + return -ENOMEM; + + qs->attr.family = "Snapdragon"; + qs->attr.machine = socinfo_machine(&pdev->dev, + le32_to_cpu(info->id)); + qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u", + SOCINFO_MAJOR(le32_to_cpu(info->ver)), + SOCINFO_MINOR(le32_to_cpu(info->ver))); + if (offsetof(struct socinfo, serial_num) <= item_size) + qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%u", + le32_to_cpu(info->serial_num)); + + qs->soc_dev = soc_device_register(&qs->attr); + if (IS_ERR(qs->soc_dev)) + return PTR_ERR(qs->soc_dev); + + /* Feed the soc specific unique data into entropy pool */ + add_device_randomness(info, item_size); + + platform_set_drvdata(pdev, qs->soc_dev); + + return 0; +} + +static int qcom_socinfo_remove(struct platform_device *pdev) +{ + struct qcom_socinfo *qs = platform_get_drvdata(pdev); + + soc_device_unregister(qs->soc_dev); + + return 0; +} + +static struct platform_driver qcom_socinfo_driver = { + .probe = qcom_socinfo_probe, + .remove = qcom_socinfo_remove, + .driver = { + .name = "qcom-socinfo", + }, +}; + +module_platform_driver(qcom_socinfo_driver); + +MODULE_DESCRIPTION("Qualcomm SoCinfo driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:qcom-socinfo"); -- GitLab From 9c84c1e78634bd7f93541ad9ad88e99b21495da7 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Wed, 24 Jul 2019 04:05:14 +0530 Subject: [PATCH 2026/7155] soc: qcom: socinfo: Expose custom attributes The Qualcomm socinfo provides a number of additional attributes, add these to the socinfo driver and expose them via debugfs functionality. Tested-by: Vinod Koul Reviewed-by: Vinod Koul Signed-off-by: Vaishali Thakkar Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 190 +++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 1b9eb44df7fe..6a4795433d57 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -4,6 +4,7 @@ * Copyright (c) 2017-2019, Linaro Ltd. */ +#include #include #include #include @@ -20,6 +21,7 @@ */ #define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff) #define SOCINFO_MINOR(ver) ((ver) & 0xffff) +#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) #define SMEM_SOCINFO_BUILD_ID_LENGTH 32 @@ -29,6 +31,27 @@ */ #define SMEM_HW_SW_BUILD_ID 137 +#ifdef CONFIG_DEBUG_FS +static const char *const pmic_models[] = { + [0] = "Unknown PMIC model", + [9] = "PM8994", + [11] = "PM8916", + [13] = "PM8058", + [14] = "PM8028", + [15] = "PM8901", + [16] = "PM8027", + [17] = "ISL9519", + [18] = "PM8921", + [19] = "PM8018", + [20] = "PM8015", + [21] = "PM8014", + [22] = "PM8821", + [23] = "PM8038", + [24] = "PM8922", + [25] = "PM8917", +}; +#endif /* CONFIG_DEBUG_FS */ + /* Socinfo SMEM item structure */ struct socinfo { __le32 fmt; @@ -67,9 +90,28 @@ struct socinfo { __le32 raw_device_num; }; +#ifdef CONFIG_DEBUG_FS +struct socinfo_params { + u32 raw_device_family; + u32 hw_plat_subtype; + u32 accessory_chip; + u32 raw_device_num; + u32 chip_family; + u32 foundry_id; + u32 plat_ver; + u32 raw_ver; + u32 hw_plat; + u32 fmt; +}; +#endif /* CONFIG_DEBUG_FS */ + struct qcom_socinfo { struct soc_device *soc_dev; struct soc_device_attribute attr; +#ifdef CONFIG_DEBUG_FS + struct dentry *dbg_root; + struct socinfo_params info; +#endif /* CONFIG_DEBUG_FS */ }; struct soc_id { @@ -130,6 +172,150 @@ static const char *socinfo_machine(struct device *dev, unsigned int id) return NULL; } +#ifdef CONFIG_DEBUG_FS + +#define QCOM_OPEN(name, _func) \ +static int qcom_open_##name(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, _func, inode->i_private); \ +} \ + \ +static const struct file_operations qcom_ ##name## _ops = { \ + .open = qcom_open_##name, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +#define DEBUGFS_ADD(info, name) \ + debugfs_create_file(__stringify(name), 0400, \ + qcom_socinfo->dbg_root, \ + info, &qcom_ ##name## _ops) + + +static int qcom_show_build_id(struct seq_file *seq, void *p) +{ + struct socinfo *socinfo = seq->private; + + seq_printf(seq, "%s\n", socinfo->build_id); + + return 0; +} + +static int qcom_show_pmic_model(struct seq_file *seq, void *p) +{ + struct socinfo *socinfo = seq->private; + int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model)); + + if (model < 0) + return -EINVAL; + + seq_printf(seq, "%s\n", pmic_models[model]); + + return 0; +} + +static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p) +{ + struct socinfo *socinfo = seq->private; + + seq_printf(seq, "%u.%u\n", + SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)), + SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev))); + + return 0; +} + +QCOM_OPEN(build_id, qcom_show_build_id); +QCOM_OPEN(pmic_model, qcom_show_pmic_model); +QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); + +static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, + struct socinfo *info) +{ + size_t size; + + qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL); + + qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt); + + switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 12): + qcom_socinfo->info.chip_family = + __le32_to_cpu(info->chip_family); + qcom_socinfo->info.raw_device_family = + __le32_to_cpu(info->raw_device_family); + qcom_socinfo->info.raw_device_num = + __le32_to_cpu(info->raw_device_num); + + debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root, + &qcom_socinfo->info.chip_family); + debugfs_create_x32("raw_device_family", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.raw_device_family); + debugfs_create_x32("raw_device_number", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.raw_device_num); + case SOCINFO_VERSION(0, 11): + case SOCINFO_VERSION(0, 10): + case SOCINFO_VERSION(0, 9): + qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id); + + debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root, + &qcom_socinfo->info.foundry_id); + case SOCINFO_VERSION(0, 8): + case SOCINFO_VERSION(0, 7): + DEBUGFS_ADD(info, pmic_model); + DEBUGFS_ADD(info, pmic_die_rev); + case SOCINFO_VERSION(0, 6): + qcom_socinfo->info.hw_plat_subtype = + __le32_to_cpu(info->hw_plat_subtype); + + debugfs_create_u32("hardware_platform_subtype", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.hw_plat_subtype); + case SOCINFO_VERSION(0, 5): + qcom_socinfo->info.accessory_chip = + __le32_to_cpu(info->accessory_chip); + + debugfs_create_u32("accessory_chip", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.accessory_chip); + case SOCINFO_VERSION(0, 4): + qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); + + debugfs_create_u32("platform_version", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.plat_ver); + case SOCINFO_VERSION(0, 3): + qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); + + debugfs_create_u32("hardware_platform", 0400, + qcom_socinfo->dbg_root, + &qcom_socinfo->info.hw_plat); + case SOCINFO_VERSION(0, 2): + qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); + + debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root, + &qcom_socinfo->info.raw_ver); + case SOCINFO_VERSION(0, 1): + DEBUGFS_ADD(info, build_id); + break; + } +} + +static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) +{ + debugfs_remove_recursive(qcom_socinfo->dbg_root); +} +#else +static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, + struct socinfo *info) +{ +} +static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { } +#endif /* CONFIG_DEBUG_FS */ + static int qcom_socinfo_probe(struct platform_device *pdev) { struct qcom_socinfo *qs; @@ -162,6 +348,8 @@ static int qcom_socinfo_probe(struct platform_device *pdev) if (IS_ERR(qs->soc_dev)) return PTR_ERR(qs->soc_dev); + socinfo_debugfs_init(qs, info); + /* Feed the soc specific unique data into entropy pool */ add_device_randomness(info, item_size); @@ -176,6 +364,8 @@ static int qcom_socinfo_remove(struct platform_device *pdev) soc_device_unregister(qs->soc_dev); + socinfo_debugfs_exit(qs); + return 0; } -- GitLab From cd23d1405be666a7c43045abe339bc1acaa3400b Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Wed, 24 Jul 2019 04:05:15 +0530 Subject: [PATCH 2027/7155] soc: qcom: socinfo: Expose image information The socinfo driver provides information about version of the various images loaded in the system. Expose this to user space for debugging purpose. Tested-by: Vinod Koul Reviewed-by: Vinod Koul Signed-off-by: Vaishali Thakkar Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 84 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 6a4795433d57..855353bed19e 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -32,6 +32,39 @@ #define SMEM_HW_SW_BUILD_ID 137 #ifdef CONFIG_DEBUG_FS +#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 +#define SMEM_IMAGE_VERSION_SIZE 4096 +#define SMEM_IMAGE_VERSION_NAME_SIZE 75 +#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 +#define SMEM_IMAGE_VERSION_OEM_SIZE 32 + +/* + * SMEM Image table indices + */ +#define SMEM_IMAGE_TABLE_BOOT_INDEX 0 +#define SMEM_IMAGE_TABLE_TZ_INDEX 1 +#define SMEM_IMAGE_TABLE_RPM_INDEX 3 +#define SMEM_IMAGE_TABLE_APPS_INDEX 10 +#define SMEM_IMAGE_TABLE_MPSS_INDEX 11 +#define SMEM_IMAGE_TABLE_ADSP_INDEX 12 +#define SMEM_IMAGE_TABLE_CNSS_INDEX 13 +#define SMEM_IMAGE_TABLE_VIDEO_INDEX 14 +#define SMEM_IMAGE_VERSION_TABLE 469 + +/* + * SMEM Image table names + */ +static const char *const socinfo_image_names[] = { + [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp", + [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps", + [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot", + [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss", + [SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss", + [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm", + [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz", + [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video", +}; + static const char *const pmic_models[] = { [0] = "Unknown PMIC model", [9] = "PM8994", @@ -103,6 +136,13 @@ struct socinfo_params { u32 hw_plat; u32 fmt; }; + +struct smem_image_version { + char name[SMEM_IMAGE_VERSION_NAME_SIZE]; + char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE]; + char pad; + char oem[SMEM_IMAGE_VERSION_OEM_SIZE]; +}; #endif /* CONFIG_DEBUG_FS */ struct qcom_socinfo { @@ -230,10 +270,37 @@ QCOM_OPEN(build_id, qcom_show_build_id); QCOM_OPEN(pmic_model, qcom_show_pmic_model); QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); +#define DEFINE_IMAGE_OPS(type) \ +static int show_image_##type(struct seq_file *seq, void *p) \ +{ \ + struct smem_image_version *image_version = seq->private; \ + seq_puts(seq, image_version->type); \ + seq_puts(seq, "\n"); \ + return 0; \ +} \ +static int open_image_##type(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, show_image_##type, inode->i_private); \ +} \ + \ +static const struct file_operations qcom_image_##type##_ops = { \ + .open = open_image_##type, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +DEFINE_IMAGE_OPS(name); +DEFINE_IMAGE_OPS(variant); +DEFINE_IMAGE_OPS(oem); + static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, struct socinfo *info) { + struct smem_image_version *versions; + struct dentry *dentry; size_t size; + int i; qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL); @@ -302,6 +369,23 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, DEBUGFS_ADD(info, build_id); break; } + + versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE, + &size); + + for (i = 0; i < ARRAY_SIZE(socinfo_image_names); i++) { + if (!socinfo_image_names[i]) + continue; + + dentry = debugfs_create_dir(socinfo_image_names[i], + qcom_socinfo->dbg_root); + debugfs_create_file("name", 0400, dentry, &versions[i], + &qcom_image_name_ops); + debugfs_create_file("variant", 0400, dentry, &versions[i], + &qcom_image_variant_ops); + debugfs_create_file("oem", 0400, dentry, &versions[i], + &qcom_image_oem_ops); + } } static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) -- GitLab From 32a5da21dd1cea8e76cf354dee8858da24820292 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Mon, 22 Jul 2019 09:58:23 -0700 Subject: [PATCH 2028/7155] arm64: dts: qcom: msm8998: Node ordering, address cleanups DT nodes should be ordered by address, then node name, and finally label. The msm8998 dtsi does not follow this, so clean it up by reordering the nodes. While we are at it, extend the addresses to be fully 32-bits wide so that ordering is easy to determine when adding new nodes. Also, two or so nodes had the wrong address value in their node name (did not match the reg property), so fix those up as well. Hopefully going forward, things can be maintained so that a cleanup like this is not needed. Reviewed-by: Vinod Koul Reviewed-by: Marc Gonzalez Signed-off-by: Jeffrey Hugo Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8998.dtsi | 254 +++++++++++++------------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index c13ed7aeb1e0..4b66a1c588f8 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -787,14 +787,22 @@ ranges = <0 0 0 0xffffffff>; compatible = "simple-bus"; - rpm_msg_ram: memory@68000 { + gcc: clock-controller@100000 { + compatible = "qcom,gcc-msm8998"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + reg = <0x00100000 0xb0000>; + }; + + rpm_msg_ram: memory@778000 { compatible = "qcom,rpm-msg-ram"; - reg = <0x778000 0x7000>; + reg = <0x00778000 0x7000>; }; qfprom: qfprom@780000 { compatible = "qcom,qfprom"; - reg = <0x780000 0x621c>; + reg = <0x00780000 0x621c>; #address-cells = <1>; #size-cells = <1>; @@ -804,47 +812,10 @@ }; }; - gcc: clock-controller@100000 { - compatible = "qcom,gcc-msm8998"; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - reg = <0x100000 0xb0000>; - }; - - tlmm: pinctrl@3400000 { - compatible = "qcom,msm8998-pinctrl"; - reg = <0x3400000 0xc00000>; - interrupts = ; - gpio-controller; - #gpio-cells = <0x2>; - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - spmi_bus: spmi@800f000 { - compatible = "qcom,spmi-pmic-arb"; - reg = <0x800f000 0x1000>, - <0x8400000 0x1000000>, - <0x9400000 0x1000000>, - <0xa400000 0x220000>, - <0x800a000 0x3000>; - reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; - interrupt-names = "periph_irq"; - interrupts = ; - qcom,ee = <0>; - qcom,channel = <0>; - #address-cells = <2>; - #size-cells = <0>; - interrupt-controller; - #interrupt-cells = <4>; - cell-index = <0>; - }; - tsens0: thermal@10ab000 { compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; - reg = <0x10ab000 0x1000>, /* TM */ - <0x10aa000 0x1000>; /* SROT */ + reg = <0x010ab000 0x1000>, /* TM */ + <0x010aa000 0x1000>; /* SROT */ #qcom,sensors = <14>; #thermal-sensor-cells = <1>; @@ -852,8 +823,8 @@ tsens1: thermal@10ae000 { compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; - reg = <0x10ae000 0x1000>, /* TM */ - <0x10ad000 0x1000>; /* SROT */ + reg = <0x010ae000 0x1000>, /* TM */ + <0x010ad000 0x1000>; /* SROT */ #qcom,sensors = <8>; #thermal-sensor-cells = <1>; @@ -943,16 +914,107 @@ }; }; + ufshc: ufshc@1da4000 { + compatible = "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; + reg = <0x01da4000 0x2500>; + interrupts = ; + phys = <&ufsphy_lanes>; + phy-names = "ufsphy"; + lanes-per-direction = <2>; + power-domains = <&gcc UFS_GDSC>; + #reset-cells = <1>; + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + clocks = + <&gcc GCC_UFS_AXI_CLK>, + <&gcc GCC_AGGRE1_UFS_AXI_CLK>, + <&gcc GCC_UFS_AHB_CLK>, + <&gcc GCC_UFS_UNIPRO_CORE_CLK>, + <&rpmcc RPM_SMD_LN_BB_CLK1>, + <&gcc GCC_UFS_TX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_RX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_RX_SYMBOL_1_CLK>; + freq-table-hz = + <50000000 200000000>, + <0 0>, + <0 0>, + <37500000 150000000>, + <0 0>, + <0 0>, + <0 0>, + <0 0>; + + resets = <&gcc GCC_UFS_BCR>; + reset-names = "rst"; + }; + + ufsphy: phy@1da7000 { + compatible = "qcom,msm8998-qmp-ufs-phy"; + reg = <0x01da7000 0x18c>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clock-names = + "ref", + "ref_aux"; + clocks = + <&gcc GCC_UFS_CLKREF_CLK>, + <&gcc GCC_UFS_PHY_AUX_CLK>; + + reset-names = "ufsphy"; + resets = <&ufshc 0>; + + ufsphy_lanes: lanes@1da7400 { + reg = <0x01da7400 0x128>, + <0x01da7600 0x1fc>, + <0x01da7c00 0x1dc>, + <0x01da7800 0x128>, + <0x01da7a00 0x1fc>; + #phy-cells = <0>; + }; + }; + tcsr_mutex_regs: syscon@1f40000 { compatible = "syscon"; - reg = <0x1f40000 0x20000>; + reg = <0x01f40000 0x20000>; }; - apcs_glb: mailbox@9820000 { - compatible = "qcom,msm8998-apcs-hmss-global"; - reg = <0x17911000 0x1000>; + tlmm: pinctrl@3400000 { + compatible = "qcom,msm8998-pinctrl"; + reg = <0x03400000 0xc00000>; + interrupts = ; + gpio-controller; + #gpio-cells = <0x2>; + interrupt-controller; + #interrupt-cells = <0x2>; + }; - #mbox-cells = <1>; + spmi_bus: spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0800f000 0x1000>, + <0x08400000 0x1000000>, + <0x09400000 0x1000000>, + <0x0a400000 0x220000>, + <0x0800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; }; usb3: usb@a8f8800 { @@ -1044,7 +1106,7 @@ sdhc2: sdhci@c0a4900 { compatible = "qcom,sdhci-msm-v4"; - reg = <0xc0a4900 0x314>, <0xc0a4000 0x800>; + reg = <0x0c0a4900 0x314>, <0x0c0a4000 0x800>; reg-names = "hc_mem", "core_mem"; interrupts = , @@ -1149,6 +1211,16 @@ #size-cells = <0>; }; + blsp2_uart1: serial@c1b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x0c1b0000 0x1000>; + interrupts = ; + clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + blsp2_i2c0: i2c@c1b5000 { compatible = "qcom,i2c-qup-v2.2.1"; reg = <0x0c1b5000 0x600>; @@ -1239,14 +1311,11 @@ #size-cells = <0>; }; - blsp2_uart1: serial@c1b0000 { - compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; - reg = <0xc1b0000 0x1000>; - interrupts = ; - clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>, - <&gcc GCC_BLSP2_AHB_CLK>; - clock-names = "core", "iface"; - status = "disabled"; + apcs_glb: mailbox@17911000 { + compatible = "qcom,msm8998-apcs-hmss-global"; + reg = <0x17911000 0x1000>; + + #mbox-cells = <1>; }; timer@17920000 { @@ -1320,75 +1389,6 @@ redistributor-stride = <0x0 0x20000>; interrupts = ; }; - - ufshc: ufshc@1da4000 { - compatible = "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; - reg = <0x01da4000 0x2500>; - interrupts = ; - phys = <&ufsphy_lanes>; - phy-names = "ufsphy"; - lanes-per-direction = <2>; - power-domains = <&gcc UFS_GDSC>; - #reset-cells = <1>; - - clock-names = - "core_clk", - "bus_aggr_clk", - "iface_clk", - "core_clk_unipro", - "ref_clk", - "tx_lane0_sync_clk", - "rx_lane0_sync_clk", - "rx_lane1_sync_clk"; - clocks = - <&gcc GCC_UFS_AXI_CLK>, - <&gcc GCC_AGGRE1_UFS_AXI_CLK>, - <&gcc GCC_UFS_AHB_CLK>, - <&gcc GCC_UFS_UNIPRO_CORE_CLK>, - <&rpmcc RPM_SMD_LN_BB_CLK1>, - <&gcc GCC_UFS_TX_SYMBOL_0_CLK>, - <&gcc GCC_UFS_RX_SYMBOL_0_CLK>, - <&gcc GCC_UFS_RX_SYMBOL_1_CLK>; - freq-table-hz = - <50000000 200000000>, - <0 0>, - <0 0>, - <37500000 150000000>, - <0 0>, - <0 0>, - <0 0>, - <0 0>; - - resets = <&gcc GCC_UFS_BCR>; - reset-names = "rst"; - }; - - ufsphy: phy@1da7000 { - compatible = "qcom,msm8998-qmp-ufs-phy"; - reg = <0x01da7000 0x18c>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - clock-names = - "ref", - "ref_aux"; - clocks = - <&gcc GCC_UFS_CLKREF_CLK>, - <&gcc GCC_UFS_PHY_AUX_CLK>; - - reset-names = "ufsphy"; - resets = <&ufshc 0>; - - ufsphy_lanes: lanes@1da7400 { - reg = <0x01da7400 0x128>, - <0x01da7600 0x1fc>, - <0x01da7c00 0x1dc>, - <0x01da7800 0x128>, - <0x01da7a00 0x1fc>; - #phy-cells = <0>; - }; - }; }; }; -- GitLab From ed7d6110c110730cac33a0c9e1cf5b83092fc2dc Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Wed, 31 Jul 2019 11:28:00 +0530 Subject: [PATCH 2029/7155] arm64: dts: qcom: sdm845: Add Coresight support Add coresight components found on Qualcomm SDM845 SoC. Signed-off-by: Sai Prakash Ranjan Reviewed-by: Mathieu Poirier Acked-by: Suzuki K Poulose Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 451 +++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 40ec8231b585..e12ecf4f6f18 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1822,6 +1822,457 @@ clock-names = "xo"; }; + stm@6002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0 0x06002000 0 0x1000>, + <0 0x16280000 0 0x180000>; + reg-names = "stm-base", "stm-stimulus-base"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + stm_out: endpoint { + remote-endpoint = + <&funnel0_in7>; + }; + }; + }; + }; + + funnel@6041000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0 0x06041000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + funnel0_out: endpoint { + remote-endpoint = + <&merge_funnel_in0>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + funnel0_in7: endpoint { + remote-endpoint = <&stm_out>; + }; + }; + }; + }; + + funnel@6043000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0 0x06043000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + funnel2_out: endpoint { + remote-endpoint = + <&merge_funnel_in2>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@5 { + reg = <5>; + funnel2_in5: endpoint { + remote-endpoint = + <&apss_merge_funnel_out>; + }; + }; + }; + }; + + funnel@6045000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0 0x06045000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + merge_funnel_out: endpoint { + remote-endpoint = <&etf_in>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + merge_funnel_in0: endpoint { + remote-endpoint = + <&funnel0_out>; + }; + }; + + port@2 { + reg = <2>; + merge_funnel_in2: endpoint { + remote-endpoint = + <&funnel2_out>; + }; + }; + }; + }; + + replicator@6046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0 0x06046000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + replicator_out: endpoint { + remote-endpoint = <&etr_in>; + }; + }; + }; + + in-ports { + port { + replicator_in: endpoint { + remote-endpoint = <&etf_out>; + }; + }; + }; + }; + + etf@6047000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0 0x06047000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etf_out: endpoint { + remote-endpoint = + <&replicator_in>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + etf_in: endpoint { + remote-endpoint = + <&merge_funnel_out>; + }; + }; + }; + }; + + etr@6048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0 0x06048000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + arm,scatter-gather; + + in-ports { + port { + etr_in: endpoint { + remote-endpoint = + <&replicator_out>; + }; + }; + }; + }; + + etm@7040000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07040000 0 0x1000>; + + cpu = <&CPU0>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = + <&apss_funnel_in0>; + }; + }; + }; + }; + + etm@7140000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07140000 0 0x1000>; + + cpu = <&CPU1>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = + <&apss_funnel_in1>; + }; + }; + }; + }; + + etm@7240000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07240000 0 0x1000>; + + cpu = <&CPU2>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = + <&apss_funnel_in2>; + }; + }; + }; + }; + + etm@7340000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07340000 0 0x1000>; + + cpu = <&CPU3>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = + <&apss_funnel_in3>; + }; + }; + }; + }; + + etm@7440000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07440000 0 0x1000>; + + cpu = <&CPU4>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = + <&apss_funnel_in4>; + }; + }; + }; + }; + + etm@7540000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07540000 0 0x1000>; + + cpu = <&CPU5>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = + <&apss_funnel_in5>; + }; + }; + }; + }; + + etm@7640000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07640000 0 0x1000>; + + cpu = <&CPU6>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = + <&apss_funnel_in6>; + }; + }; + }; + }; + + etm@7740000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0 0x07740000 0 0x1000>; + + cpu = <&CPU7>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = + <&apss_funnel_in7>; + }; + }; + }; + }; + + funnel@7800000 { /* APSS Funnel */ + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0 0x07800000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = + <&apss_merge_funnel_in>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + apss_funnel_in0: endpoint { + remote-endpoint = + <&etm0_out>; + }; + }; + + port@1 { + reg = <1>; + apss_funnel_in1: endpoint { + remote-endpoint = + <&etm1_out>; + }; + }; + + port@2 { + reg = <2>; + apss_funnel_in2: endpoint { + remote-endpoint = + <&etm2_out>; + }; + }; + + port@3 { + reg = <3>; + apss_funnel_in3: endpoint { + remote-endpoint = + <&etm3_out>; + }; + }; + + port@4 { + reg = <4>; + apss_funnel_in4: endpoint { + remote-endpoint = + <&etm4_out>; + }; + }; + + port@5 { + reg = <5>; + apss_funnel_in5: endpoint { + remote-endpoint = + <&etm5_out>; + }; + }; + + port@6 { + reg = <6>; + apss_funnel_in6: endpoint { + remote-endpoint = + <&etm6_out>; + }; + }; + + port@7 { + reg = <7>; + apss_funnel_in7: endpoint { + remote-endpoint = + <&etm7_out>; + }; + }; + }; + }; + + funnel@7810000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0 0x07810000 0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + apss_merge_funnel_out: endpoint { + remote-endpoint = + <&funnel2_in5>; + }; + }; + }; + + in-ports { + port { + apss_merge_funnel_in: endpoint { + remote-endpoint = + <&apss_funnel_out>; + }; + }; + }; + }; + sdhc_2: sdhci@8804000 { compatible = "qcom,sdm845-sdhci", "qcom,sdhci-msm-v5"; reg = <0 0x08804000 0 0x1000>; -- GitLab From 783abfa2249a0a354fdba5d232714c448a5312ca Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Wed, 31 Jul 2019 11:28:01 +0530 Subject: [PATCH 2030/7155] arm64: dts: qcom: msm8998: Add Coresight support Enable coresight support by adding device nodes for the available source, sinks and channel blocks on MSM8998. Signed-off-by: Sai Prakash Ranjan Reviewed-by: Mathieu Poirier Acked-by: Suzuki K Poulose Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8998.dtsi | 435 ++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index 4b66a1c588f8..c6f81431983e 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -998,6 +998,441 @@ #interrupt-cells = <0x2>; }; + stm@6002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x06002000 0x1000>, + <0x16280000 0x180000>; + reg-names = "stm-base", "stm-data-base"; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + stm_out: endpoint { + remote-endpoint = <&funnel0_in7>; + }; + }; + }; + }; + + funnel@6041000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x06041000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + funnel0_out: endpoint { + remote-endpoint = + <&merge_funnel_in0>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + funnel0_in7: endpoint { + remote-endpoint = <&stm_out>; + }; + }; + }; + }; + + funnel@6042000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x06042000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + funnel1_out: endpoint { + remote-endpoint = + <&merge_funnel_in1>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@6 { + reg = <6>; + funnel1_in6: endpoint { + remote-endpoint = + <&apss_merge_funnel_out>; + }; + }; + }; + }; + + funnel@6045000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x06045000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + merge_funnel_out: endpoint { + remote-endpoint = + <&etf_in>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + merge_funnel_in0: endpoint { + remote-endpoint = + <&funnel0_out>; + }; + }; + + port@1 { + reg = <1>; + merge_funnel_in1: endpoint { + remote-endpoint = + <&funnel1_out>; + }; + }; + }; + }; + + replicator@6046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x06046000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + replicator_out: endpoint { + remote-endpoint = <&etr_in>; + }; + }; + }; + + in-ports { + port { + replicator_in: endpoint { + remote-endpoint = <&etf_out>; + }; + }; + }; + }; + + etf@6047000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x06047000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + etf_out: endpoint { + remote-endpoint = + <&replicator_in>; + }; + }; + }; + + in-ports { + port { + etf_in: endpoint { + remote-endpoint = + <&merge_funnel_out>; + }; + }; + }; + }; + + etr@6048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x06048000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + arm,scatter-gather; + + in-ports { + port { + etr_in: endpoint { + remote-endpoint = + <&replicator_out>; + }; + }; + }; + }; + + etm@7840000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07840000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU0>; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = + <&apss_funnel_in0>; + }; + }; + }; + }; + + etm@7940000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07940000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU1>; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = + <&apss_funnel_in1>; + }; + }; + }; + }; + + etm@7a40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07a40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU2>; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = + <&apss_funnel_in2>; + }; + }; + }; + }; + + etm@7b40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07b40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU3>; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = + <&apss_funnel_in3>; + }; + }; + }; + }; + + funnel@7b60000 { /* APSS Funnel */ + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07b60000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = + <&apss_merge_funnel_in>; + }; + }; + }; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + apss_funnel_in0: endpoint { + remote-endpoint = + <&etm0_out>; + }; + }; + + port@1 { + reg = <1>; + apss_funnel_in1: endpoint { + remote-endpoint = + <&etm1_out>; + }; + }; + + port@2 { + reg = <2>; + apss_funnel_in2: endpoint { + remote-endpoint = + <&etm2_out>; + }; + }; + + port@3 { + reg = <3>; + apss_funnel_in3: endpoint { + remote-endpoint = + <&etm3_out>; + }; + }; + + port@4 { + reg = <4>; + apss_funnel_in4: endpoint { + remote-endpoint = + <&etm4_out>; + }; + }; + + port@5 { + reg = <5>; + apss_funnel_in5: endpoint { + remote-endpoint = + <&etm5_out>; + }; + }; + + port@6 { + reg = <6>; + apss_funnel_in6: endpoint { + remote-endpoint = + <&etm6_out>; + }; + }; + + port@7 { + reg = <7>; + apss_funnel_in7: endpoint { + remote-endpoint = + <&etm7_out>; + }; + }; + }; + }; + + funnel@7b70000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x07b70000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + apss_merge_funnel_out: endpoint { + remote-endpoint = + <&funnel1_in6>; + }; + }; + }; + + in-ports { + port { + apss_merge_funnel_in: endpoint { + remote-endpoint = + <&apss_funnel_out>; + }; + }; + }; + }; + + etm@7c40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07c40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU4>; + + port{ + etm4_out: endpoint { + remote-endpoint = <&apss_funnel_in4>; + }; + }; + }; + + etm@7d40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07d40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU5>; + + port{ + etm5_out: endpoint { + remote-endpoint = <&apss_funnel_in5>; + }; + }; + }; + + etm@7e40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07e40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU6>; + + port{ + etm6_out: endpoint { + remote-endpoint = <&apss_funnel_in6>; + }; + }; + }; + + etm@7f40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x07f40000 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU7>; + + port{ + etm7_out: endpoint { + remote-endpoint = <&apss_funnel_in7>; + }; + }; + }; + spmi_bus: spmi@800f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0800f000 0x1000>, -- GitLab From d98de8efa19fb753ca39e6c1c26d8f2bedb6e2d4 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Wed, 31 Jul 2019 11:28:02 +0530 Subject: [PATCH 2031/7155] arm64: dts: qcom: msm8996: Add Coresight support Enable coresight support by adding device nodes for the available source, sinks and channel blocks on msm8996. This also adds coresight cpu debug nodes. Signed-off-by: Vivek Gautam Signed-off-by: Sai Prakash Ranjan Reviewed-by: Mathieu Poirier Acked-by: Suzuki K Poulose Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 468 ++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 1a139cfb240d..766abed0d440 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -633,6 +633,474 @@ reg = <0x300000 0x90000>; }; + stm@3002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x3002000 0x1000>, + <0x8280000 0x180000>; + reg-names = "stm-base", "stm-stimulus-base"; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + out-ports { + port { + stm_out: endpoint { + remote-endpoint = + <&funnel0_in>; + }; + }; + }; + }; + + tpiu@3020000 { + compatible = "arm,coresight-tpiu", "arm,primecell"; + reg = <0x3020000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + port { + tpiu_in: endpoint { + remote-endpoint = + <&replicator_out1>; + }; + }; + }; + }; + + funnel@3021000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3021000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + funnel0_in: endpoint { + remote-endpoint = + <&stm_out>; + }; + }; + }; + + out-ports { + port { + funnel0_out: endpoint { + remote-endpoint = + <&merge_funnel_in0>; + }; + }; + }; + }; + + funnel@3022000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3022000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@6 { + reg = <6>; + funnel1_in: endpoint { + remote-endpoint = + <&apss_merge_funnel_out>; + }; + }; + }; + + out-ports { + port { + funnel1_out: endpoint { + remote-endpoint = + <&merge_funnel_in1>; + }; + }; + }; + }; + + funnel@3023000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3023000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + + out-ports { + port { + funnel2_out: endpoint { + remote-endpoint = + <&merge_funnel_in2>; + }; + }; + }; + }; + + funnel@3025000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3025000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + merge_funnel_in0: endpoint { + remote-endpoint = + <&funnel0_out>; + }; + }; + + port@1 { + reg = <1>; + merge_funnel_in1: endpoint { + remote-endpoint = + <&funnel1_out>; + }; + }; + + port@2 { + reg = <2>; + merge_funnel_in2: endpoint { + remote-endpoint = + <&funnel2_out>; + }; + }; + }; + + out-ports { + port { + merge_funnel_out: endpoint { + remote-endpoint = + <&etf_in>; + }; + }; + }; + }; + + replicator@3026000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x3026000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + port { + replicator_in: endpoint { + remote-endpoint = + <&etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + replicator_out0: endpoint { + remote-endpoint = + <&etr_in>; + }; + }; + + port@1 { + reg = <1>; + replicator_out1: endpoint { + remote-endpoint = + <&tpiu_in>; + }; + }; + }; + }; + + etf@3027000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x3027000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + port { + etf_in: endpoint { + remote-endpoint = + <&merge_funnel_out>; + }; + }; + }; + + out-ports { + port { + etf_out: endpoint { + remote-endpoint = + <&replicator_in>; + }; + }; + }; + }; + + etr@3028000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x3028000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + arm,scatter-gather; + + in-ports { + port { + etr_in: endpoint { + remote-endpoint = + <&replicator_out0>; + }; + }; + }; + }; + + debug@3810000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0x3810000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; + clock-names = "apb_pclk"; + + cpu = <&CPU0>; + }; + + etm@3840000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x3840000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU0>; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = + <&apss_funnel0_in0>; + }; + }; + }; + }; + + debug@3910000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0x3910000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; + clock-names = "apb_pclk"; + + cpu = <&CPU1>; + }; + + etm@3940000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x3940000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU1>; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = + <&apss_funnel0_in1>; + }; + }; + }; + }; + + funnel@39b0000 { /* APSS Funnel 0 */ + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x39b0000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + apss_funnel0_in0: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + + port@1 { + reg = <1>; + apss_funnel0_in1: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel0_out: endpoint { + remote-endpoint = + <&apss_merge_funnel_in0>; + }; + }; + }; + }; + + debug@3a10000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0x3a10000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; + clock-names = "apb_pclk"; + + cpu = <&CPU2>; + }; + + etm@3a40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x3a40000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU2>; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = + <&apss_funnel1_in0>; + }; + }; + }; + }; + + debug@3b10000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0x3b10000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; + clock-names = "apb_pclk"; + + cpu = <&CPU3>; + }; + + etm@3b40000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x3b40000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + cpu = <&CPU3>; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = + <&apss_funnel1_in1>; + }; + }; + }; + }; + + funnel@3bb0000 { /* APSS Funnel 1 */ + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3bb0000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + apss_funnel1_in0: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + + port@1 { + reg = <1>; + apss_funnel1_in1: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel1_out: endpoint { + remote-endpoint = + <&apss_merge_funnel_in1>; + }; + }; + }; + }; + + funnel@3bc0000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x3bc0000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "atclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + apss_merge_funnel_in0: endpoint { + remote-endpoint = + <&apss_funnel0_out>; + }; + }; + + port@1 { + reg = <1>; + apss_merge_funnel_in1: endpoint { + remote-endpoint = + <&apss_funnel1_out>; + }; + }; + }; + + out-ports { + port { + apss_merge_funnel_out: endpoint { + remote-endpoint = + <&funnel1_in>; + }; + }; + }; + }; + kryocc: clock-controller@6400000 { compatible = "qcom,apcc-msm8996"; reg = <0x6400000 0x90000>; -- GitLab From 7e4b5f241a91e2e15cd1e19024c3b6a0664beadc Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Tue, 30 Jul 2019 11:24:43 -0400 Subject: [PATCH 2032/7155] arm64: dts: qcom: Extend AOSS QMP node AOSS hosts resources that can be used to warm up the SoC. Add nodes for these resources. Signed-off-by: Thara Gopinath Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index e12ecf4f6f18..9be6acb0650e 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2893,6 +2893,14 @@ #clock-cells = <0>; #power-domain-cells = <1>; + + cx_cdev: cx { + #cooling-cells = <2>; + }; + + ebi_cdev: ebi { + #cooling-cells = <2>; + }; }; spmi_bus: spmi@c440000 { -- GitLab From 4e300e439af31ae39669f970121022743980bbce Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Thu, 25 Jul 2019 15:39:49 +0300 Subject: [PATCH 2033/7155] arm64: dts: qcom: msm8996: Add Venus video codec DT node This adds Qualcomm Venus video codec DT node for the video codec hardware found in MSM8996 platforms. Signed-off-by: Stanimir Varbanov Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 68 +++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 766abed0d440..87f4d9c1b0d4 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -2262,6 +2262,74 @@ "ref"; }; }; + + venus_smmu: arm,smmu-venus@d40000 { + compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2"; + reg = <0xd40000 0x20000>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + ; + power-domains = <&mmcc MMAGIC_VIDEO_GDSC>; + clocks = <&mmcc SMMU_VIDEO_AHB_CLK>, + <&mmcc SMMU_VIDEO_AXI_CLK>; + clock-names = "iface", "bus"; + #iommu-cells = <1>; + status = "okay"; + }; + + video-codec@c00000 { + compatible = "qcom,msm8996-venus"; + reg = <0x00c00000 0xff000>; + interrupts = ; + power-domains = <&mmcc VENUS_GDSC>; + clocks = <&mmcc VIDEO_CORE_CLK>, + <&mmcc VIDEO_AHB_CLK>, + <&mmcc VIDEO_AXI_CLK>, + <&mmcc VIDEO_MAXI_CLK>; + clock-names = "core", "iface", "bus", "mbus"; + iommus = <&venus_smmu 0x00>, + <&venus_smmu 0x01>, + <&venus_smmu 0x0a>, + <&venus_smmu 0x07>, + <&venus_smmu 0x0e>, + <&venus_smmu 0x0f>, + <&venus_smmu 0x08>, + <&venus_smmu 0x09>, + <&venus_smmu 0x0b>, + <&venus_smmu 0x0c>, + <&venus_smmu 0x0d>, + <&venus_smmu 0x10>, + <&venus_smmu 0x11>, + <&venus_smmu 0x21>, + <&venus_smmu 0x28>, + <&venus_smmu 0x29>, + <&venus_smmu 0x2b>, + <&venus_smmu 0x2c>, + <&venus_smmu 0x2d>, + <&venus_smmu 0x31>; + memory-region = <&venus_region>; + status = "okay"; + + video-decoder { + compatible = "venus-decoder"; + clocks = <&mmcc VIDEO_SUBCORE0_CLK>; + clock-names = "core"; + power-domains = <&mmcc VENUS_CORE0_GDSC>; + }; + + video-encoder { + compatible = "venus-encoder"; + clocks = <&mmcc VIDEO_SUBCORE1_CLK>; + clock-names = "core"; + power-domains = <&mmcc VENUS_CORE1_GDSC>; + }; + }; }; sound: sound { -- GitLab From 3af1e2aa1855d976337752c95ac0c4971d8fc9e6 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 22 Jul 2019 11:22:08 +0200 Subject: [PATCH 2034/7155] dt-bindings: vendor-prefixes: Add Longcheer Technology Co., Ltd. Add the "longcheer" vendor prefix for Longcheer Technology Co., Ltd., an "industry-leading service provider of mobile phone design and product delivery". (http://www.longcheer.com) Reviewed-by: Rob Herring Signed-off-by: Stephan Gerhold Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6992bbbbffab..7bcf340b6f38 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -529,6 +529,8 @@ patternProperties: description: Linear Technology Corporation "^logicpd,.*": description: Logic PD, Inc. + "^longcheer,.*": + description: Longcheer Technology (Shanghai) Co., Ltd. "^lsi,.*": description: LSI Corp. (LSI Logic) "^lwn,.*": -- GitLab From b72160fa886d757611b1c7f1127d5585fce43af2 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 22 Jul 2019 11:22:09 +0200 Subject: [PATCH 2035/7155] dt-bindings: qcom: Document bindings for new MSM8916 devices Document the new samsung,a3u/a5u-eur and longcheer,l8150 device tree bindings used in their device trees. Reviewed-by: Rob Herring Signed-off-by: Stephan Gerhold Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/qcom.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 54ef6b6b9189..e39d8f02e33c 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -45,6 +45,7 @@ description: | mtp sbc hk01 + qrd The 'soc_version' and 'board_version' elements take the form of v. where the minor number may be omitted when it's zero, i.e. v1.0 is the same @@ -115,6 +116,13 @@ properties: - const: qcom,msm8916-mtp - const: qcom,msm8916 + - items: + - enum: + - longcheer,l8150 + - samsung,a3u-eur + - samsung,a5u-eur + - const: qcom,msm8916 + - items: - const: qcom,msm8996-mtp -- GitLab From 1329c1ab0730b521e6cd3051c56a2ff3d55f21e6 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 22 Jul 2019 11:22:10 +0200 Subject: [PATCH 2036/7155] arm64: dts: qcom: Add device tree for Samsung Galaxy A3U/A5U Samsung Galaxy A3 (SM-A300FU) and Samsung Galaxy A5 (SM-A500FU) are smartphones using the MSM8916 SoC released in 2015. Add a device tree for A3U and A5U with initial support for: - SDHCI (internal and external storage) - USB Device Mode - UART (on USB connector via the SM5502 MUIC) - Regulators The two devices (and all other variants of A3/A5 released in 2015) are very similar, with some differences in display, touchscreen and sensors. The common parts are shared in msm8916-samsung-a2015-common.dtsi to reduce duplication. The device tree is loosely based on apq8016-sbc.dtsi and the downstream kernel provided by Samsung, mixed with a lot of own research. Co-developed-by: Michael Srba Signed-off-by: Michael Srba Signed-off-by: Stephan Gerhold Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../qcom/msm8916-samsung-a2015-common.dtsi | 236 ++++++++++++++++++ .../boot/dts/qcom/msm8916-samsung-a3u-eur.dts | 10 + .../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 10 + 4 files changed, 258 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi create mode 100644 arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts create mode 100644 arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 954d75de617b..9189996d1fa5 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -3,6 +3,8 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a3u-eur.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a5u-eur.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi new file mode 100644 index 000000000000..e675ff48fdd2 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "msm8916.dtsi" +#include "pm8916.dtsi" +#include +#include + +/ { + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + sdhci@7824000 { + status = "okay"; + + vmmc-supply = <&pm8916_l8>; + vqmmc-supply = <&pm8916_l5>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; + }; + + sdhci@7864000 { + status = "okay"; + + vmmc-supply = <&pm8916_l11>; + vqmmc-supply = <&pm8916_l12>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + }; + + serial@78b0000 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp1_uart2_default>; + pinctrl-1 = <&blsp1_uart2_sleep>; + }; + + usb@78d9000 { + status = "okay"; + extcon = <&muic>, <&muic>; + + hnp-disable; + srp-disable; + adp-disable; + + ulpi { + phy { + extcon = <&muic>; + v1p8-supply = <&pm8916_l7>; + v3p3-supply = <&pm8916_l13>; + }; + }; + }; + + /* + * Attempting to enable these devices causes a "synchronous + * external abort". Suspected cause is that the debug power + * domain is not enabled by default on this device. + * Disable these devices for now to avoid the crash. + * + * See: https://lore.kernel.org/linux-arm-msm/20190618202623.GA53651@gerhold.net/ + */ + tpiu@820000 { status = "disabled"; }; + funnel@821000 { status = "disabled"; }; + replicator@824000 { status = "disabled"; }; + etf@825000 { status = "disabled"; }; + etr@826000 { status = "disabled"; }; + funnel@841000 { status = "disabled"; }; + debug@850000 { status = "disabled"; }; + debug@852000 { status = "disabled"; }; + debug@854000 { status = "disabled"; }; + debug@856000 { status = "disabled"; }; + etm@85c000 { status = "disabled"; }; + etm@85d000 { status = "disabled"; }; + etm@85e000 { status = "disabled"; }; + etm@85f000 { status = "disabled"; }; + }; + + i2c-muic { + compatible = "i2c-gpio"; + sda-gpios = <&msmgpio 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&msmgpio 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + + #address-cells = <1>; + #size-cells = <0>; + + muic: sm5502@25 { + compatible = "siliconmitus,sm5502-muic"; + + reg = <0x25>; + interrupt-parent = <&msmgpio>; + interrupts = <12 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-names = "default"; + pinctrl-0 = <&muic_int_default>; + }; + }; +}; + +&msmgpio { + muic_int_default: muic_int_default { + pinmux { + function = "gpio"; + pins = "gpio12"; + }; + pinconf { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + }; + }; +}; + +&smd_rpm_regulators { + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; + + s1 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1300000>; + }; + + s3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1300000>; + }; + + s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2100000>; + }; + + l1 { + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + }; + + l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + l3 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1287500>; + }; + + l4 { + regulator-min-microvolt = <2050000>; + regulator-max-microvolt = <2050000>; + }; + + l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l8 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2900000>; + }; + + l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2800000>; + }; + + l11 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + l18 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2700000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts new file mode 100644 index 000000000000..d10f7ac5089f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-samsung-a2015-common.dtsi" + +/ { + model = "Samsung Galaxy A3U (EUR)"; + compatible = "samsung,a3u-eur", "qcom,msm8916"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts new file mode 100644 index 000000000000..1aa59da98495 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-samsung-a2015-common.dtsi" + +/ { + model = "Samsung Galaxy A5U (EUR)"; + compatible = "samsung,a5u-eur", "qcom,msm8916"; +}; -- GitLab From 16e8e8072108426029f0c16dff7fbe77fae3df8f Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 22 Jul 2019 11:22:11 +0200 Subject: [PATCH 2037/7155] arm64: dts: qcom: Add device tree for Longcheer L8150 Longcheer L8150 is a smartphone based on MSM8916 which is used in several rebrands like the Snapdragon 410 Android One devices or the Wileyfox Swift. Add a device tree for L8150 with initial support for: - SDHCI (internal and external storage) - USB Device Mode - UART - Regulators Co-developed-by: Nikita Travkin Signed-off-by: Nikita Travkin Signed-off-by: Stephan Gerhold Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/msm8916-longcheer-l8150.dts | 228 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9189996d1fa5..90ae31513e98 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8150.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a3u-eur.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a5u-eur.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts new file mode 100644 index 000000000000..2b28e383fd0b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916.dtsi" +#include "pm8916.dtsi" +#include + +/ { + model = "Longcheer L8150"; + compatible = "longcheer,l8150", "qcom,msm8916-v1-qrd/9-v1", "qcom,msm8916"; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + sdhci@7824000 { + status = "okay"; + + vmmc-supply = <&pm8916_l8>; + vqmmc-supply = <&pm8916_l5>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; + }; + + sdhci@7864000 { + status = "okay"; + + vmmc-supply = <&pm8916_l11>; + vqmmc-supply = <&pm8916_l12>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; + + non-removable; + }; + + serial@78b0000 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp1_uart2_default>; + pinctrl-1 = <&blsp1_uart2_sleep>; + }; + + usb@78d9000 { + status = "okay"; + dr_mode = "peripheral"; + extcon = <&usb_vbus>; + + hnp-disable; + srp-disable; + adp-disable; + + ulpi { + phy { + extcon = <&usb_vbus>; + v1p8-supply = <&pm8916_l7>; + v3p3-supply = <&pm8916_l13>; + }; + }; + }; + + /* + * Attempting to enable these devices causes a "synchronous + * external abort". Suspected cause is that the debug power + * domain is not enabled by default on this device. + * Disable these devices for now to avoid the crash. + * + * See: https://lore.kernel.org/linux-arm-msm/20190618202623.GA53651@gerhold.net/ + */ + tpiu@820000 { status = "disabled"; }; + funnel@821000 { status = "disabled"; }; + replicator@824000 { status = "disabled"; }; + etf@825000 { status = "disabled"; }; + etr@826000 { status = "disabled"; }; + funnel@841000 { status = "disabled"; }; + debug@850000 { status = "disabled"; }; + debug@852000 { status = "disabled"; }; + debug@854000 { status = "disabled"; }; + debug@856000 { status = "disabled"; }; + etm@85c000 { status = "disabled"; }; + etm@85d000 { status = "disabled"; }; + etm@85e000 { status = "disabled"; }; + etm@85f000 { status = "disabled"; }; + }; + + // FIXME: Use extcon device provided by charger driver when available + usb_vbus: usb-vbus { + compatible = "linux,extcon-usb-gpio"; + vbus-gpio = <&msmgpio 62 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_vbus_default>; + }; +}; + +&msmgpio { + usb_vbus_default: usb-vbus-default { + pinmux { + function = "gpio"; + pins = "gpio62"; + }; + pinconf { + pins = "gpio62"; + bias-pull-up; + }; + }; +}; + +&smd_rpm_regulators { + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; + + s1 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1300000>; + }; + + s3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1300000>; + }; + + s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2100000>; + }; + + l1 { + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + }; + + l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + l3 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1287500>; + }; + + l4 { + regulator-min-microvolt = <2050000>; + regulator-max-microvolt = <2050000>; + }; + + l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + l8 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2900000>; + }; + + l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2800000>; + }; + + l11 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + l18 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2700000>; + }; +}; -- GitLab From 05589b30b21ac0273970b61edd50c07d2ba156af Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Tue, 30 Jul 2019 11:24:42 -0400 Subject: [PATCH 2038/7155] soc: qcom: Extend AOSS QMP driver to support resources that are used to wake up the SoC. The AOSS QMP driver is extended to communicate with the additional resources. These resources are then registered as cooling devices with the thermal framework. Signed-off-by: Thara Gopinath Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 131 +++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 5f885196f4d0..443dab2207de 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #define QMP_DESC_MAGIC 0x0 #define QMP_DESC_VERSION 0x4 @@ -40,6 +42,17 @@ /* 64 bytes is enough to store the requests and provides padding to 4 bytes */ #define QMP_MSG_LEN 64 +#define QMP_NUM_COOLING_RESOURCES 2 + +static bool qmp_cdev_init_state = 1; + +struct qmp_cooling_device { + struct thermal_cooling_device *cdev; + struct qmp *qmp; + char *name; + bool state; +}; + /** * struct qmp - driver state for QMP implementation * @msgram: iomem referencing the message RAM used for communication @@ -69,6 +82,7 @@ struct qmp { struct clk_hw qdss_clk; struct genpd_onecell_data pd_data; + struct qmp_cooling_device *cooling_devs; }; struct qmp_pd { @@ -385,6 +399,118 @@ static void qmp_pd_remove(struct qmp *qmp) pm_genpd_remove(data->domains[i]); } +static int qmp_cdev_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + *state = qmp_cdev_init_state; + return 0; +} + +static int qmp_cdev_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct qmp_cooling_device *qmp_cdev = cdev->devdata; + + *state = qmp_cdev->state; + return 0; +} + +static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + struct qmp_cooling_device *qmp_cdev = cdev->devdata; + char buf[QMP_MSG_LEN] = {}; + bool cdev_state; + int ret; + + /* Normalize state */ + cdev_state = !!state; + + if (qmp_cdev->state == state) + return 0; + + snprintf(buf, sizeof(buf), + "{class: volt_flr, event:zero_temp, res:%s, value:%s}", + qmp_cdev->name, + cdev_state ? "off" : "on"); + + ret = qmp_send(qmp_cdev->qmp, buf, sizeof(buf)); + + if (!ret) + qmp_cdev->state = cdev_state; + + return ret; +} + +static struct thermal_cooling_device_ops qmp_cooling_device_ops = { + .get_max_state = qmp_cdev_get_max_state, + .get_cur_state = qmp_cdev_get_cur_state, + .set_cur_state = qmp_cdev_set_cur_state, +}; + +static int qmp_cooling_device_add(struct qmp *qmp, + struct qmp_cooling_device *qmp_cdev, + struct device_node *node) +{ + char *cdev_name = (char *)node->name; + + qmp_cdev->qmp = qmp; + qmp_cdev->state = qmp_cdev_init_state; + qmp_cdev->name = cdev_name; + qmp_cdev->cdev = devm_thermal_of_cooling_device_register + (qmp->dev, node, + cdev_name, + qmp_cdev, &qmp_cooling_device_ops); + + if (IS_ERR(qmp_cdev->cdev)) + dev_err(qmp->dev, "unable to register %s cooling device\n", + cdev_name); + + return PTR_ERR_OR_ZERO(qmp_cdev->cdev); +} + +static int qmp_cooling_devices_register(struct qmp *qmp) +{ + struct device_node *np, *child; + int count = QMP_NUM_COOLING_RESOURCES; + int ret; + + np = qmp->dev->of_node; + + qmp->cooling_devs = devm_kcalloc(qmp->dev, count, + sizeof(*qmp->cooling_devs), + GFP_KERNEL); + + if (!qmp->cooling_devs) + return -ENOMEM; + + for_each_available_child_of_node(np, child) { + if (!of_find_property(child, "#cooling-cells", NULL)) + continue; + ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++], + child); + if (ret) + goto unroll; + } + + return 0; + +unroll: + while (--count >= 0) + thermal_cooling_device_unregister + (qmp->cooling_devs[count].cdev); + + return ret; +} + +static void qmp_cooling_devices_remove(struct qmp *qmp) +{ + int i; + + for (i = 0; i < QMP_NUM_COOLING_RESOURCES; i++) + thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev); +} + static int qmp_probe(struct platform_device *pdev) { struct resource *res; @@ -433,6 +559,10 @@ static int qmp_probe(struct platform_device *pdev) if (ret) goto err_remove_qdss_clk; + ret = qmp_cooling_devices_register(qmp); + if (ret) + dev_err(&pdev->dev, "failed to register aoss cooling devices\n"); + platform_set_drvdata(pdev, qmp); return 0; @@ -453,6 +583,7 @@ static int qmp_remove(struct platform_device *pdev) qmp_qdss_clk_remove(qmp); qmp_pd_remove(qmp); + qmp_cooling_devices_remove(qmp); qmp_close(qmp); mbox_free_channel(qmp->mbox_chan); -- GitLab From 9d4db2f5f0e6dc4c0dfb94110fe488e9eb191748 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:02 -0700 Subject: [PATCH 2039/7155] bus: sunxi-rsb: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Greg Kroah-Hartman Cc: Maxime Ripard Cc: Chen-Yu Tsai Signed-off-by: Stephen Boyd Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 1b76d9585902..be79d6c6a4e4 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -651,10 +651,8 @@ static int sunxi_rsb_probe(struct platform_device *pdev) return PTR_ERR(rsb->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to retrieve irq: %d\n", irq); + if (irq < 0) return irq; - } rsb->clk = devm_clk_get(dev, NULL); if (IS_ERR(rsb->clk)) { -- GitLab From 91148dbad80bb6024389287be4aefcbf20b2d0e4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:35 +0200 Subject: [PATCH 2040/7155] USB: usbip: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Cc: Valentina Manea Acked-by: Shuah Khan Link: https://lore.kernel.org/r/20190805193636.25560-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc.h | 2 +- drivers/usb/usbip/vudc_dev.c | 9 --------- drivers/usb/usbip/vudc_main.c | 1 + drivers/usb/usbip/vudc_sysfs.c | 7 ++++++- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/usb/usbip/vudc.h b/drivers/usb/usbip/vudc.h index cf968192e59f..1bd4bc005829 100644 --- a/drivers/usb/usbip/vudc.h +++ b/drivers/usb/usbip/vudc.h @@ -115,7 +115,7 @@ struct vudc_device { struct list_head dev_entry; }; -extern const struct attribute_group vudc_attr_group; +extern const struct attribute_group *vudc_groups[]; /* visible everywhere */ diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c index a72c17ff1c6a..c8eeabdd9b56 100644 --- a/drivers/usb/usbip/vudc_dev.c +++ b/drivers/usb/usbip/vudc_dev.c @@ -616,18 +616,10 @@ int vudc_probe(struct platform_device *pdev) if (ret < 0) goto err_add_udc; - ret = sysfs_create_group(&pdev->dev.kobj, &vudc_attr_group); - if (ret) { - dev_err(&udc->pdev->dev, "create sysfs files\n"); - goto err_sysfs; - } - platform_set_drvdata(pdev, udc); return ret; -err_sysfs: - usb_del_gadget_udc(&udc->gadget); err_add_udc: cleanup_vudc_hw(udc); err_init_vudc_hw: @@ -640,7 +632,6 @@ int vudc_remove(struct platform_device *pdev) { struct vudc *udc = platform_get_drvdata(pdev); - sysfs_remove_group(&pdev->dev.kobj, &vudc_attr_group); usb_del_gadget_udc(&udc->gadget); cleanup_vudc_hw(udc); kfree(udc); diff --git a/drivers/usb/usbip/vudc_main.c b/drivers/usb/usbip/vudc_main.c index 390733e6937e..678faa82598c 100644 --- a/drivers/usb/usbip/vudc_main.c +++ b/drivers/usb/usbip/vudc_main.c @@ -22,6 +22,7 @@ static struct platform_driver vudc_driver = { .remove = vudc_remove, .driver = { .name = GADGET_NAME, + .dev_groups = vudc_groups, }, }; diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 6dcd3ff655c3..100f680c572a 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -215,7 +215,12 @@ static struct bin_attribute *dev_bin_attrs[] = { NULL, }; -const struct attribute_group vudc_attr_group = { +static const struct attribute_group vudc_attr_group = { .attrs = dev_attrs, .bin_attrs = dev_bin_attrs, }; + +const struct attribute_group *vudc_groups[] = { + &vudc_attr_group, + NULL, +}; -- GitLab From c1ae5e7f057beb1daa72831ab22ec06e71669af7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 27 Jul 2019 10:55:49 +0200 Subject: [PATCH 2041/7155] ALSA: usb-audio: Unify audioformat release code There are many open code for releasing audioformat object. Provide a unified helper and call it from the all places. Only a cleanup, no functional changes. Signed-off-by: Takashi Iwai --- sound/usb/stream.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index e852c7fd6109..963d425004f8 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -28,6 +28,14 @@ #include "power.h" #include "media.h" +static void audioformat_free(struct audioformat *fp) +{ + list_del(&fp->list); /* unlink for avoiding double-free */ + kfree(fp->rate_table); + kfree(fp->chmap); + kfree(fp); +} + /* * free a substream */ @@ -37,11 +45,8 @@ static void free_substream(struct snd_usb_substream *subs) if (!subs->num_formats) return; /* not initialized */ - list_for_each_entry_safe(fp, n, &subs->fmt_list, list) { - kfree(fp->rate_table); - kfree(fp->chmap); - kfree(fp); - } + list_for_each_entry_safe(fp, n, &subs->fmt_list, list) + audioformat_free(fp); kfree(subs->rate_list.list); kfree(subs->str_pd); snd_media_stream_delete(subs); @@ -832,8 +837,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, /* ok, let's parse further... */ if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) { - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } @@ -1043,9 +1047,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) { - kfree(fp->chmap); - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -1064,9 +1066,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, /* ok, let's parse further... */ if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { kfree(pd); - kfree(fp->chmap); - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } } @@ -1185,11 +1185,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { - list_del(&fp->list); /* unlink for avoiding double-free */ + audioformat_free(fp); kfree(pd); - kfree(fp->rate_table); - kfree(fp->chmap); - kfree(fp); return err; } /* try to set the interface... */ -- GitLab From f7f530181461aaf6afa0b3f0be4d239dea410896 Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Fri, 11 Aug 2017 02:36:14 +0300 Subject: [PATCH 2042/7155] ALSA: usb-audio: fix PCM device order Some cards have alternate setting with non-PCM format as the first altsetting in the interface descriptors. This confuses userspace, since alsa-lib uses device 0 by default. So lets parse interfaces in two steps: 1. Parse altsettings with PCM formats. 2. Parse altsettings with non-PCM formats. This fixes at least following cards: - Audinst HUD-mx2 - Audinst HUD-mini [ Adapted to 5.3 kernel by tiwai ] Signed-off-by: Alexander Tsoy Signed-off-by: Takashi Iwai --- sound/usb/stream.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 963d425004f8..fc3e9fcfbc38 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1077,7 +1077,9 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, return fp; } -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, + int iface_no, + bool *has_non_pcm, bool non_pcm) { struct usb_device *dev; struct usb_interface *iface; @@ -1178,6 +1180,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) else if (IS_ERR(fp)) return PTR_ERR(fp); + if (fp->fmt_type != UAC_FORMAT_TYPE_I) + *has_non_pcm = true; + if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) { + audioformat_free(fp); + kfree(pd); + fp = NULL; + pd = NULL; + continue; + } + dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); if (protocol == UAC_VERSION_3) err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); @@ -1197,3 +1209,23 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) return 0; } +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +{ + int err; + bool has_non_pcm = false; + + /* parse PCM formats */ + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false); + if (err < 0) + return err; + + if (has_non_pcm) { + /* parse non-PCM formats */ + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true); + if (err < 0) + return err; + } + + return 0; +} + -- GitLab From 91d2a812dfb98b3b4dad661529c33bc38d303461 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Tue, 25 Jun 2019 10:39:13 -0400 Subject: [PATCH 2043/7155] locking/rwsem: Make handoff writer optimistically spin on owner When the handoff bit is set by a writer, no other tasks other than the setting writer itself is allowed to acquire the lock. If the to-be-handoff'ed writer goes to sleep, there will be a wakeup latency period where the lock is free, but no one can acquire it. That is less than ideal. To reduce that latency, the handoff writer will now optimistically spin on the owner if it happens to be a on-cpu writer. It will spin until it releases the lock and the to-be-handoff'ed writer can then acquire the lock immediately without any delay. Of course, if the owner is not a on-cpu writer, the to-be-handoff'ed writer will have to sleep anyway. The optimistic spinning code is also modified to not stop spinning when the handoff bit is set. This will prevent an occasional setting of handoff bit from causing a bunch of optimistic spinners from entering into the wait queue causing significant reduction in throughput. On a 1-socket 22-core 44-thread Skylake system, the AIM7 shared_memory workload was run with 7000 users. The throughput (jobs/min) of the following kernels were as follows: 1) 5.2-rc6 - 8,092,486 2) 5.2-rc6 + tip's rwsem patches - 7,567,568 3) 5.2-rc6 + tip's rwsem patches + this patch - 7,954,545 Using perf-record(1), the %cpu time used by rwsem_down_write_slowpath(), rwsem_down_write_failed() and their callees for the 3 kernels were 1.70%, 5.46% and 2.08% respectively. Signed-off-by: Waiman Long Signed-off-by: Peter Zijlstra (Intel) Cc: x86@kernel.org Cc: Ingo Molnar Cc: Will Deacon Cc: huang ying Cc: Tim Chen Cc: Linus Torvalds Cc: Borislav Petkov Cc: Thomas Gleixner Cc: Davidlohr Bueso Cc: "H. Peter Anvin" Link: https://lkml.kernel.org/r/20190625143913.24154-1-longman@redhat.com --- kernel/locking/rwsem.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index bd0f0d05724c..354238a08b7a 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -724,11 +724,12 @@ rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable) rcu_read_lock(); for (;;) { - if (atomic_long_read(&sem->count) & RWSEM_FLAG_HANDOFF) { - state = OWNER_NONSPINNABLE; - break; - } - + /* + * When a waiting writer set the handoff flag, it may spin + * on the owner as well. Once that writer acquires the lock, + * we can spin on it. So we don't need to quit even when the + * handoff bit is set. + */ new = rwsem_owner_flags(sem, &new_flags); if ((new != owner) || (new_flags != flags)) { state = rwsem_owner_state(new, new_flags, nonspinnable); @@ -974,6 +975,13 @@ static inline bool rwsem_reader_phase_trylock(struct rw_semaphore *sem, { return false; } + +static inline int +rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable) +{ + return 0; +} +#define OWNER_NULL 1 #endif /* @@ -1206,6 +1214,18 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) raw_spin_unlock_irq(&sem->wait_lock); + /* + * After setting the handoff bit and failing to acquire + * the lock, attempt to spin on owner to accelerate lock + * transfer. If the previous owner is a on-cpu writer and it + * has just released the lock, OWNER_NULL will be returned. + * In this case, we attempt to acquire the lock again + * without sleeping. + */ + if ((wstate == WRITER_HANDOFF) && + (rwsem_spin_on_owner(sem, 0) == OWNER_NULL)) + goto trylock_again; + /* Block until there are no active lockers. */ for (;;) { if (signal_pending_state(state, current)) @@ -1240,7 +1260,7 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) break; } } - +trylock_again: raw_spin_lock_irq(&sem->wait_lock); } __set_current_state(TASK_RUNNING); -- GitLab From fce45cd41101f1a9620267146b21f09b3454d8db Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Sun, 28 Jul 2019 21:47:35 -0700 Subject: [PATCH 2044/7155] locking/rwsem: Check for operations on an uninitialized rwsem Currently rwsems is the only locking primitive that lacks this debug feature. Add it under CONFIG_DEBUG_RWSEMS and do the magic checking in the locking fastpath (trylock) operation such that we cover all cases. The unlocking part is pretty straightforward. Signed-off-by: Davidlohr Bueso Signed-off-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Cc: mingo@kernel.org Cc: Davidlohr Bueso Link: https://lkml.kernel.org/r/20190729044735.9632-1-dave@stgolabs.net --- include/linux/rwsem.h | 10 ++++++++++ kernel/locking/rwsem.c | 22 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 9d9c663987d8..00d6054687dd 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -45,6 +45,9 @@ struct rw_semaphore { #endif raw_spinlock_t wait_lock; struct list_head wait_list; +#ifdef CONFIG_DEBUG_RWSEMS + void *magic; +#endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif @@ -73,6 +76,12 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) # define __RWSEM_DEP_MAP_INIT(lockname) #endif +#ifdef CONFIG_DEBUG_RWSEMS +# define __DEBUG_RWSEM_INITIALIZER(lockname) , .magic = &lockname +#else +# define __DEBUG_RWSEM_INITIALIZER(lockname) +#endif + #ifdef CONFIG_RWSEM_SPIN_ON_OWNER #define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED #else @@ -85,6 +94,7 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) .wait_list = LIST_HEAD_INIT((name).wait_list), \ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \ __RWSEM_OPT_INIT(name) \ + __DEBUG_RWSEM_INITIALIZER(name) \ __RWSEM_DEP_MAP_INIT(name) } #define DECLARE_RWSEM(name) \ diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index 354238a08b7a..eef04551eae7 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -105,8 +105,9 @@ #ifdef CONFIG_DEBUG_RWSEMS # define DEBUG_RWSEMS_WARN_ON(c, sem) do { \ if (!debug_locks_silent && \ - WARN_ONCE(c, "DEBUG_RWSEMS_WARN_ON(%s): count = 0x%lx, owner = 0x%lx, curr 0x%lx, list %sempty\n",\ + WARN_ONCE(c, "DEBUG_RWSEMS_WARN_ON(%s): count = 0x%lx, magic = 0x%lx, owner = 0x%lx, curr 0x%lx, list %sempty\n",\ #c, atomic_long_read(&(sem)->count), \ + (unsigned long) sem->magic, \ atomic_long_read(&(sem)->owner), (long)current, \ list_empty(&(sem)->wait_list) ? "" : "not ")) \ debug_locks_off(); \ @@ -329,6 +330,9 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, */ debug_check_no_locks_freed((void *)sem, sizeof(*sem)); lockdep_init_map(&sem->dep_map, name, key, 0); +#endif +#ifdef CONFIG_DEBUG_RWSEMS + sem->magic = sem; #endif atomic_long_set(&sem->count, RWSEM_UNLOCKED_VALUE); raw_spin_lock_init(&sem->wait_lock); @@ -1358,11 +1362,14 @@ static inline int __down_read_killable(struct rw_semaphore *sem) static inline int __down_read_trylock(struct rw_semaphore *sem) { + long tmp; + + DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem); + /* * Optimize for the case when the rwsem is not locked at all. */ - long tmp = RWSEM_UNLOCKED_VALUE; - + tmp = RWSEM_UNLOCKED_VALUE; do { if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp, tmp + RWSEM_READER_BIAS)) { @@ -1403,8 +1410,11 @@ static inline int __down_write_killable(struct rw_semaphore *sem) static inline int __down_write_trylock(struct rw_semaphore *sem) { - long tmp = RWSEM_UNLOCKED_VALUE; + long tmp; + DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem); + + tmp = RWSEM_UNLOCKED_VALUE; if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp, RWSEM_WRITER_LOCKED)) { rwsem_set_owner(sem); @@ -1420,7 +1430,9 @@ inline void __up_read(struct rw_semaphore *sem) { long tmp; + DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem); DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem); + rwsem_clear_reader_owned(sem); tmp = atomic_long_add_return_release(-RWSEM_READER_BIAS, &sem->count); DEBUG_RWSEMS_WARN_ON(tmp < 0, sem); @@ -1438,12 +1450,14 @@ static inline void __up_write(struct rw_semaphore *sem) { long tmp; + DEBUG_RWSEMS_WARN_ON(sem->magic != sem, sem); /* * sem->owner may differ from current if the ownership is transferred * to an anonymous writer by setting the RWSEM_NONSPINNABLE bits. */ DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE), sem); + rwsem_clear_owner(sem); tmp = atomic_long_fetch_add_release(-RWSEM_WRITER_LOCKED, &sem->count); if (unlikely(tmp & RWSEM_FLAG_WAITERS)) -- GitLab From 24a376d65177009a4dd8d846543c5dc69f5c4ced Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Aug 2019 15:30:28 +0200 Subject: [PATCH 2045/7155] locking/qspinlock,x86: Clarify virt_spin_lock_key Add a few comments to clarify how this is supposed to work. Reported-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Juergen Gross --- arch/x86/include/asm/qspinlock.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h index bd5ac6cc37db..444d6fd9a6d8 100644 --- a/arch/x86/include/asm/qspinlock.h +++ b/arch/x86/include/asm/qspinlock.h @@ -63,10 +63,25 @@ static inline bool vcpu_is_preempted(long cpu) #endif #ifdef CONFIG_PARAVIRT +/* + * virt_spin_lock_key - enables (by default) the virt_spin_lock() hijack. + * + * Native (and PV wanting native due to vCPU pinning) should disable this key. + * It is done in this backwards fashion to only have a single direction change, + * which removes ordering between native_pv_spin_init() and HV setup. + */ DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key); void native_pv_lock_init(void) __init; +/* + * Shortcut for the queued_spin_lock_slowpath() function that allows + * virt to hijack it. + * + * Returns: + * true - lock has been negotiated, all done; + * false - queued_spin_lock_slowpath() will do its thing. + */ #define virt_spin_lock virt_spin_lock static inline bool virt_spin_lock(struct qspinlock *lock) { -- GitLab From 5f35d5a66b3ec62cb5ec4ec2ad9aebe2ac325673 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 31 Jul 2019 20:35:03 +0530 Subject: [PATCH 2046/7155] locking/mutex: Make __mutex_owner static to mutex.c __mutex_owner() should only be used by the mutex api's. So, to put this restiction let's move the __mutex_owner() function definition from linux/mutex.h to mutex.c file. There exist functions that uses __mutex_owner() like mutex_is_locked() and mutex_trylock_recursive(), So to keep legacy thing intact move them as well and export them. Move mutex_waiter structure also to keep it private to the file. Signed-off-by: Mukesh Ojha Signed-off-by: Peter Zijlstra (Intel) Cc: mingo@redhat.com Cc: will@kernel.org Link: https://lkml.kernel.org/r/1564585504-3543-1-git-send-email-mojha@codeaurora.org --- include/linux/mutex.h | 38 +++----------------------------------- kernel/locking/mutex.c | 39 +++++++++++++++++++++++++++++++++++++++ kernel/locking/mutex.h | 2 ++ 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/include/linux/mutex.h b/include/linux/mutex.h index dcd03fee6e01..eb8c62aba263 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -65,29 +65,6 @@ struct mutex { #endif }; -/* - * Internal helper function; C doesn't allow us to hide it :/ - * - * DO NOT USE (outside of mutex code). - */ -static inline struct task_struct *__mutex_owner(struct mutex *lock) -{ - return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07); -} - -/* - * This is the control structure for tasks blocked on mutex, - * which resides on the blocked task's kernel stack: - */ -struct mutex_waiter { - struct list_head list; - struct task_struct *task; - struct ww_acquire_ctx *ww_ctx; -#ifdef CONFIG_DEBUG_MUTEXES - void *magic; -#endif -}; - #ifdef CONFIG_DEBUG_MUTEXES #define __DEBUG_MUTEX_INITIALIZER(lockname) \ @@ -144,10 +121,7 @@ extern void __mutex_init(struct mutex *lock, const char *name, * * Returns true if the mutex is locked, false if unlocked. */ -static inline bool mutex_is_locked(struct mutex *lock) -{ - return __mutex_owner(lock) != NULL; -} +extern bool mutex_is_locked(struct mutex *lock); /* * See kernel/locking/mutex.c for detailed documentation of these APIs. @@ -220,13 +194,7 @@ enum mutex_trylock_recursive_enum { * - MUTEX_TRYLOCK_SUCCESS - lock acquired, * - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock. */ -static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum -mutex_trylock_recursive(struct mutex *lock) -{ - if (unlikely(__mutex_owner(lock) == current)) - return MUTEX_TRYLOCK_RECURSIVE; - - return mutex_trylock(lock); -} +extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum +mutex_trylock_recursive(struct mutex *lock); #endif /* __LINUX_MUTEX_H */ diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 5e069734363c..ac4929f1e085 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -36,6 +36,19 @@ # include "mutex.h" #endif +/* + * This is the control structure for tasks blocked on mutex, + * which resides on the blocked task's kernel stack: + */ +struct mutex_waiter { + struct list_head list; + struct task_struct *task; + struct ww_acquire_ctx *ww_ctx; +#ifdef CONFIG_DEBUG_MUTEXES + void *magic; +#endif +}; + void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) { @@ -65,11 +78,37 @@ EXPORT_SYMBOL(__mutex_init); #define MUTEX_FLAGS 0x07 +/* + * Internal helper function; C doesn't allow us to hide it :/ + * + * DO NOT USE (outside of mutex code). + */ +static inline struct task_struct *__mutex_owner(struct mutex *lock) +{ + return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07); +} + static inline struct task_struct *__owner_task(unsigned long owner) { return (struct task_struct *)(owner & ~MUTEX_FLAGS); } +bool mutex_is_locked(struct mutex *lock) +{ + return __mutex_owner(lock) != NULL; +} +EXPORT_SYMBOL(mutex_is_locked); + +__must_check enum mutex_trylock_recursive_enum +mutex_trylock_recursive(struct mutex *lock) +{ + if (unlikely(__mutex_owner(lock) == current)) + return MUTEX_TRYLOCK_RECURSIVE; + + return mutex_trylock(lock); +} +EXPORT_SYMBOL(mutex_trylock_recursive); + static inline unsigned long __owner_flags(unsigned long owner) { return owner & MUTEX_FLAGS; diff --git a/kernel/locking/mutex.h b/kernel/locking/mutex.h index 1c2287d3fa71..7cde5c6d414e 100644 --- a/kernel/locking/mutex.h +++ b/kernel/locking/mutex.h @@ -19,6 +19,8 @@ #define debug_mutex_unlock(lock) do { } while (0) #define debug_mutex_init(lock, name, key) do { } while (0) +struct mutex_waiter; + static inline void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) { -- GitLab From a037d269221c0ae15f47046757afcbd1a7177bbf Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 31 Jul 2019 20:35:04 +0530 Subject: [PATCH 2047/7155] locking/mutex: Use mutex flags macro instead of hard code Use the mutex flag macro instead of hard code value inside __mutex_owner(). Signed-off-by: Mukesh Ojha Signed-off-by: Peter Zijlstra (Intel) Cc: mingo@redhat.com Cc: will@kernel.org Link: https://lkml.kernel.org/r/1564585504-3543-2-git-send-email-mojha@codeaurora.org --- kernel/locking/mutex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index ac4929f1e085..b4bcb0236d7a 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -85,7 +85,7 @@ EXPORT_SYMBOL(__mutex_init); */ static inline struct task_struct *__mutex_owner(struct mutex *lock) { - return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07); + return (struct task_struct *)(atomic_long_read(&lock->owner) & ~MUTEX_FLAGS); } static inline struct task_struct *__owner_task(unsigned long owner) -- GitLab From 1b34121d9f26d272b0b2334209af6b6fc82d4bf1 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Fri, 2 Aug 2019 13:52:14 +0200 Subject: [PATCH 2048/7155] ALSA: usb-audio: Skip bSynchAddress endpoint check if it is invalid The Linux kernel assumes that get_endpoint(alts,0) and get_endpoint(alts,1) are eachothers feedback endpoints. To reassure that validity it will test bsynchaddress to comply with that assumption. But if the bsyncaddress is 0 (invalid), it will flag that as a wrong assumption and return an error. Fix: Skip the test if bSynchAddress is 0. Note: those with a valid bSynchAddress should have a code quirck added. Signed-off-by: Ard van Breemen Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 75b96929f76c..51a8faf25ed8 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -456,6 +456,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, } ep = get_endpoint(alts, 1)->bEndpointAddress; if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && + get_endpoint(alts, 0)->bSynchAddress != 0 && ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { dev_err(&dev->dev, -- GitLab From 118b2806a07605d6e3c880e35a5c472bfda7582f Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Fri, 2 Aug 2019 13:52:15 +0200 Subject: [PATCH 2049/7155] ALSA: usb-audio: Add Pioneer DDJ-SX3 PCM quirck The Pioneer DDJ-SX3 is a plain 12 32bit channel out and 10 channel in PCM/midi controller. The PCM part is "vendor specific". It needs the "ignore invalid bsynchaddress" patch as it uses 0 for that. Signed-off-by: Ard van Breemen Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index e918ce346027..70c338f3ae24 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3534,5 +3534,62 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * PIONEER DJ DDJ-SX3 + * PCM is 12 channels out, 10 channels in @ 44.1 fixed + * interface 0, vendor class alt setting 1 for endpoints 5 and 0x86 + * The feedback for the output is the input. + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0023), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 12, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x05, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_44100, + .rate_min = 44100, + .rate_max = 44100, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 44100 } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 10, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x86, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_44100, + .rate_min = 44100, + .rate_max = 44100, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 44100 } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC -- GitLab From 100c12f20dfa463d52f9327b71c1806dcde82852 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:21:54 +0300 Subject: [PATCH 2050/7155] thunderbolt: Switch to use device_property_count_uXX() Use device_property_count_uXX() directly, that makes code neater. Signed-off-by: Andy Shevchenko Acked-by: Yehezkel Bernat Signed-off-by: Mika Westerberg --- drivers/thunderbolt/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 81e8ac4c5805..2366406e49ac 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -414,7 +414,7 @@ static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size) struct device *dev = &sw->tb->nhi->pdev->dev; int len, res; - len = device_property_read_u8_array(dev, "ThunderboltDROM", NULL, 0); + len = device_property_count_u8(dev, "ThunderboltDROM"); if (len < 0 || len < sizeof(struct tb_drom_header)) return -EINVAL; -- GitLab From 3457f86da60de73705bce8fe32a36651441e639e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 12 Jul 2019 18:32:32 -0700 Subject: [PATCH 2051/7155] rtw88: use txpwr_lmt_cfg_pair struct, not arrays We're just trusting that these tables are of the right dimensions, when we could do better by just using the struct directly. Let's expose the struct txpwr_lmt_cfg_pair instead. The table changes were made by using some Vim macros, so that should help prevent any translation mistakes along the way. Remaining work: get the 'void *data' out of the generic struct rtw_table; all of these tables really deserve to be their own data structure, with proper type fields. Signed-off-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/phy.c | 15 +- drivers/net/wireless/realtek/rtw88/phy.h | 9 + .../wireless/realtek/rtw88/rtw8822b_table.c | 1564 +++++++--- .../wireless/realtek/rtw88/rtw8822c_table.c | 2635 +++++++++++------ 4 files changed, 2939 insertions(+), 1284 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 4ec8dcf17361..528ee1ee2fd2 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -29,15 +29,6 @@ struct phy_pg_cfg_pair { u32 data; }; -struct txpwr_lmt_cfg_pair { - u8 regd; - u8 band; - u8 bw; - u8 rs; - u8 ch; - s8 txpwr_lmt; -}; - static const u32 db_invert_table[12][8] = { {10, 13, 16, 20, 25, 32, 40, 50}, @@ -1267,10 +1258,8 @@ static void rtw_xref_txpwr_lmt(struct rtw_dev *rtwdev) void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, const struct rtw_table *tbl) { - const struct txpwr_lmt_cfg_pair *p = tbl->data; - const struct txpwr_lmt_cfg_pair *end = p + tbl->size / 6; - - BUILD_BUG_ON(sizeof(struct txpwr_lmt_cfg_pair) != sizeof(u8) * 6); + const struct rtw_txpwr_lmt_cfg_pair *p = tbl->data; + const struct rtw_txpwr_lmt_cfg_pair *end = p + tbl->size; for (; p < end; p++) { rtw_phy_set_tx_power_limit(rtwdev, p->regd, p->band, diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index 7c8eb732b13c..cc87b157f23e 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -45,6 +45,15 @@ void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel); void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal); void rtw_phy_tx_power_limit_config(struct rtw_hal *hal); +struct rtw_txpwr_lmt_cfg_pair { + u8 regd; + u8 band; + u8 bw; + u8 rs; + u8 ch; + s8 txpwr_lmt; +}; + #define RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, path) \ const struct rtw_table name ## _tbl = { \ .data = name, \ diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c index 2d2dfb495ce1..465f58411cab 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c @@ -20382,402 +20382,1182 @@ static const u32 rtw8822b_rf_b[] = { RTW_DECL_TABLE_RF_RADIO(rtw8822b_rf_b, B); -static const u8 rtw8822b_txpwr_lmt_type2[] = { - 0, 0, 0, 0, 1, 32, 2, 0, 0, 0, 1, 28, 1, 0, 0, 0, 1, 30, - 0, 0, 0, 0, 2, 32, 2, 0, 0, 0, 2, 28, 1, 0, 0, 0, 2, 30, - 0, 0, 0, 0, 3, 32, 2, 0, 0, 0, 3, 28, 1, 0, 0, 0, 3, 30, - 0, 0, 0, 0, 4, 32, 2, 0, 0, 0, 4, 28, 1, 0, 0, 0, 4, 30, - 0, 0, 0, 0, 5, 32, 2, 0, 0, 0, 5, 28, 1, 0, 0, 0, 5, 30, - 0, 0, 0, 0, 6, 32, 2, 0, 0, 0, 6, 28, 1, 0, 0, 0, 6, 30, - 0, 0, 0, 0, 7, 32, 2, 0, 0, 0, 7, 28, 1, 0, 0, 0, 7, 30, - 0, 0, 0, 0, 8, 32, 2, 0, 0, 0, 8, 28, 1, 0, 0, 0, 8, 30, - 0, 0, 0, 0, 9, 32, 2, 0, 0, 0, 9, 28, 1, 0, 0, 0, 9, 30, - 0, 0, 0, 0, 10, 32, 2, 0, 0, 0, 10, 28, 1, 0, 0, 0, 10, 30, - 0, 0, 0, 0, 11, 32, 2, 0, 0, 0, 11, 28, 1, 0, 0, 0, 11, 30, - 0, 0, 0, 0, 12, 26, 2, 0, 0, 0, 12, 28, 1, 0, 0, 0, 12, 30, - 0, 0, 0, 0, 13, 20, 2, 0, 0, 0, 13, 28, 1, 0, 0, 0, 13, 28, - 0, 0, 0, 0, 14, 63, 2, 0, 0, 0, 14, 63, 1, 0, 0, 0, 14, 32, - 0, 0, 0, 1, 1, 26, 2, 0, 0, 1, 1, 30, 1, 0, 0, 1, 1, 34, - 0, 0, 0, 1, 2, 30, 2, 0, 0, 1, 2, 30, 1, 0, 0, 1, 2, 34, - 0, 0, 0, 1, 3, 32, 2, 0, 0, 1, 3, 30, 1, 0, 0, 1, 3, 34, - 0, 0, 0, 1, 4, 34, 2, 0, 0, 1, 4, 30, 1, 0, 0, 1, 4, 34, - 0, 0, 0, 1, 5, 34, 2, 0, 0, 1, 5, 30, 1, 0, 0, 1, 5, 34, - 0, 0, 0, 1, 6, 34, 2, 0, 0, 1, 6, 30, 1, 0, 0, 1, 6, 34, - 0, 0, 0, 1, 7, 34, 2, 0, 0, 1, 7, 30, 1, 0, 0, 1, 7, 34, - 0, 0, 0, 1, 8, 34, 2, 0, 0, 1, 8, 30, 1, 0, 0, 1, 8, 34, - 0, 0, 0, 1, 9, 32, 2, 0, 0, 1, 9, 30, 1, 0, 0, 1, 9, 34, - 0, 0, 0, 1, 10, 30, 2, 0, 0, 1, 10, 30, 1, 0, 0, 1, 10, 34, - 0, 0, 0, 1, 11, 28, 2, 0, 0, 1, 11, 30, 1, 0, 0, 1, 11, 34, - 0, 0, 0, 1, 12, 22, 2, 0, 0, 1, 12, 30, 1, 0, 0, 1, 12, 34, - 0, 0, 0, 1, 13, 14, 2, 0, 0, 1, 13, 30, 1, 0, 0, 1, 13, 34, - 0, 0, 0, 1, 14, 63, 2, 0, 0, 1, 14, 63, 1, 0, 0, 1, 14, 63, - 0, 0, 0, 2, 1, 26, 2, 0, 0, 2, 1, 30, 1, 0, 0, 2, 1, 34, - 0, 0, 0, 2, 2, 30, 2, 0, 0, 2, 2, 30, 1, 0, 0, 2, 2, 34, - 0, 0, 0, 2, 3, 32, 2, 0, 0, 2, 3, 30, 1, 0, 0, 2, 3, 34, - 0, 0, 0, 2, 4, 34, 2, 0, 0, 2, 4, 30, 1, 0, 0, 2, 4, 34, - 0, 0, 0, 2, 5, 34, 2, 0, 0, 2, 5, 30, 1, 0, 0, 2, 5, 34, - 0, 0, 0, 2, 6, 34, 2, 0, 0, 2, 6, 30, 1, 0, 0, 2, 6, 34, - 0, 0, 0, 2, 7, 34, 2, 0, 0, 2, 7, 30, 1, 0, 0, 2, 7, 34, - 0, 0, 0, 2, 8, 34, 2, 0, 0, 2, 8, 30, 1, 0, 0, 2, 8, 34, - 0, 0, 0, 2, 9, 32, 2, 0, 0, 2, 9, 30, 1, 0, 0, 2, 9, 34, - 0, 0, 0, 2, 10, 30, 2, 0, 0, 2, 10, 30, 1, 0, 0, 2, 10, 34, - 0, 0, 0, 2, 11, 26, 2, 0, 0, 2, 11, 30, 1, 0, 0, 2, 11, 34, - 0, 0, 0, 2, 12, 20, 2, 0, 0, 2, 12, 30, 1, 0, 0, 2, 12, 34, - 0, 0, 0, 2, 13, 14, 2, 0, 0, 2, 13, 30, 1, 0, 0, 2, 13, 34, - 0, 0, 0, 2, 14, 63, 2, 0, 0, 2, 14, 63, 1, 0, 0, 2, 14, 63, - 0, 0, 0, 3, 1, 26, 2, 0, 0, 3, 1, 18, 1, 0, 0, 3, 1, 30, - 0, 0, 0, 3, 2, 28, 2, 0, 0, 3, 2, 18, 1, 0, 0, 3, 2, 30, - 0, 0, 0, 3, 3, 30, 2, 0, 0, 3, 3, 18, 1, 0, 0, 3, 3, 30, - 0, 0, 0, 3, 4, 30, 2, 0, 0, 3, 4, 18, 1, 0, 0, 3, 4, 30, - 0, 0, 0, 3, 5, 32, 2, 0, 0, 3, 5, 18, 1, 0, 0, 3, 5, 30, - 0, 0, 0, 3, 6, 32, 2, 0, 0, 3, 6, 18, 1, 0, 0, 3, 6, 30, - 0, 0, 0, 3, 7, 32, 2, 0, 0, 3, 7, 18, 1, 0, 0, 3, 7, 30, - 0, 0, 0, 3, 8, 30, 2, 0, 0, 3, 8, 18, 1, 0, 0, 3, 8, 30, - 0, 0, 0, 3, 9, 30, 2, 0, 0, 3, 9, 18, 1, 0, 0, 3, 9, 30, - 0, 0, 0, 3, 10, 28, 2, 0, 0, 3, 10, 18, 1, 0, 0, 3, 10, 30, - 0, 0, 0, 3, 11, 26, 2, 0, 0, 3, 11, 18, 1, 0, 0, 3, 11, 30, - 0, 0, 0, 3, 12, 20, 2, 0, 0, 3, 12, 18, 1, 0, 0, 3, 12, 30, - 0, 0, 0, 3, 13, 14, 2, 0, 0, 3, 13, 18, 1, 0, 0, 3, 13, 30, - 0, 0, 0, 3, 14, 63, 2, 0, 0, 3, 14, 63, 1, 0, 0, 3, 14, 63, - 0, 0, 1, 2, 1, 63, 2, 0, 1, 2, 1, 63, 1, 0, 1, 2, 1, 63, - 0, 0, 1, 2, 2, 63, 2, 0, 1, 2, 2, 63, 1, 0, 1, 2, 2, 63, - 0, 0, 1, 2, 3, 26, 2, 0, 1, 2, 3, 30, 1, 0, 1, 2, 3, 34, - 0, 0, 1, 2, 4, 26, 2, 0, 1, 2, 4, 30, 1, 0, 1, 2, 4, 34, - 0, 0, 1, 2, 5, 30, 2, 0, 1, 2, 5, 30, 1, 0, 1, 2, 5, 34, - 0, 0, 1, 2, 6, 32, 2, 0, 1, 2, 6, 30, 1, 0, 1, 2, 6, 34, - 0, 0, 1, 2, 7, 30, 2, 0, 1, 2, 7, 30, 1, 0, 1, 2, 7, 34, - 0, 0, 1, 2, 8, 26, 2, 0, 1, 2, 8, 30, 1, 0, 1, 2, 8, 34, - 0, 0, 1, 2, 9, 26, 2, 0, 1, 2, 9, 30, 1, 0, 1, 2, 9, 34, - 0, 0, 1, 2, 10, 20, 2, 0, 1, 2, 10, 30, 1, 0, 1, 2, 10, 34, - 0, 0, 1, 2, 11, 14, 2, 0, 1, 2, 11, 30, 1, 0, 1, 2, 11, 34, - 0, 0, 1, 2, 12, 63, 2, 0, 1, 2, 12, 63, 1, 0, 1, 2, 12, 63, - 0, 0, 1, 2, 13, 63, 2, 0, 1, 2, 13, 63, 1, 0, 1, 2, 13, 63, - 0, 0, 1, 2, 14, 63, 2, 0, 1, 2, 14, 63, 1, 0, 1, 2, 14, 63, - 0, 0, 1, 3, 1, 63, 2, 0, 1, 3, 1, 63, 1, 0, 1, 3, 1, 63, - 0, 0, 1, 3, 2, 63, 2, 0, 1, 3, 2, 63, 1, 0, 1, 3, 2, 63, - 0, 0, 1, 3, 3, 24, 2, 0, 1, 3, 3, 18, 1, 0, 1, 3, 3, 30, - 0, 0, 1, 3, 4, 24, 2, 0, 1, 3, 4, 18, 1, 0, 1, 3, 4, 30, - 0, 0, 1, 3, 5, 26, 2, 0, 1, 3, 5, 18, 1, 0, 1, 3, 5, 30, - 0, 0, 1, 3, 6, 28, 2, 0, 1, 3, 6, 18, 1, 0, 1, 3, 6, 30, - 0, 0, 1, 3, 7, 26, 2, 0, 1, 3, 7, 18, 1, 0, 1, 3, 7, 30, - 0, 0, 1, 3, 8, 26, 2, 0, 1, 3, 8, 18, 1, 0, 1, 3, 8, 30, - 0, 0, 1, 3, 9, 26, 2, 0, 1, 3, 9, 18, 1, 0, 1, 3, 9, 30, - 0, 0, 1, 3, 10, 20, 2, 0, 1, 3, 10, 18, 1, 0, 1, 3, 10, 30, - 0, 0, 1, 3, 11, 14, 2, 0, 1, 3, 11, 18, 1, 0, 1, 3, 11, 30, - 0, 0, 1, 3, 12, 63, 2, 0, 1, 3, 12, 63, 1, 0, 1, 3, 12, 63, - 0, 0, 1, 3, 13, 63, 2, 0, 1, 3, 13, 63, 1, 0, 1, 3, 13, 63, - 0, 0, 1, 3, 14, 63, 2, 0, 1, 3, 14, 63, 1, 0, 1, 3, 14, 63, - 0, 1, 0, 1, 36, 36, 2, 1, 0, 1, 36, 32, 1, 1, 0, 1, 36, 30, - 0, 1, 0, 1, 40, 38, 2, 1, 0, 1, 40, 32, 1, 1, 0, 1, 40, 30, - 0, 1, 0, 1, 44, 38, 2, 1, 0, 1, 44, 32, 1, 1, 0, 1, 44, 30, - 0, 1, 0, 1, 48, 38, 2, 1, 0, 1, 48, 32, 1, 1, 0, 1, 48, 30, - 0, 1, 0, 1, 52, 38, 2, 1, 0, 1, 52, 32, 1, 1, 0, 1, 52, 28, - 0, 1, 0, 1, 56, 38, 2, 1, 0, 1, 56, 32, 1, 1, 0, 1, 56, 28, - 0, 1, 0, 1, 60, 38, 2, 1, 0, 1, 60, 32, 1, 1, 0, 1, 60, 28, - 0, 1, 0, 1, 64, 34, 2, 1, 0, 1, 64, 32, 1, 1, 0, 1, 64, 28, - 0, 1, 0, 1, 100, 32, 2, 1, 0, 1, 100, 32, 1, 1, 0, 1, 100, 32, - 0, 1, 0, 1, 104, 38, 2, 1, 0, 1, 104, 32, 1, 1, 0, 1, 104, 32, - 0, 1, 0, 1, 108, 38, 2, 1, 0, 1, 108, 32, 1, 1, 0, 1, 108, 32, - 0, 1, 0, 1, 112, 38, 2, 1, 0, 1, 112, 32, 1, 1, 0, 1, 112, 32, - 0, 1, 0, 1, 116, 38, 2, 1, 0, 1, 116, 32, 1, 1, 0, 1, 116, 32, - 0, 1, 0, 1, 120, 38, 2, 1, 0, 1, 120, 32, 1, 1, 0, 1, 120, 32, - 0, 1, 0, 1, 124, 38, 2, 1, 0, 1, 124, 32, 1, 1, 0, 1, 124, 32, - 0, 1, 0, 1, 128, 38, 2, 1, 0, 1, 128, 32, 1, 1, 0, 1, 128, 32, - 0, 1, 0, 1, 132, 38, 2, 1, 0, 1, 132, 32, 1, 1, 0, 1, 132, 32, - 0, 1, 0, 1, 136, 38, 2, 1, 0, 1, 136, 32, 1, 1, 0, 1, 136, 32, - 0, 1, 0, 1, 140, 34, 2, 1, 0, 1, 140, 32, 1, 1, 0, 1, 140, 32, - 0, 1, 0, 1, 144, 34, 2, 1, 0, 1, 144, 32, 1, 1, 0, 1, 144, 63, - 0, 1, 0, 1, 149, 38, 2, 1, 0, 1, 149, 63, 1, 1, 0, 1, 149, 63, - 0, 1, 0, 1, 153, 38, 2, 1, 0, 1, 153, 63, 1, 1, 0, 1, 153, 63, - 0, 1, 0, 1, 157, 38, 2, 1, 0, 1, 157, 63, 1, 1, 0, 1, 157, 63, - 0, 1, 0, 1, 161, 38, 2, 1, 0, 1, 161, 63, 1, 1, 0, 1, 161, 63, - 0, 1, 0, 1, 165, 38, 2, 1, 0, 1, 165, 63, 1, 1, 0, 1, 165, 63, - 0, 1, 0, 2, 36, 36, 2, 1, 0, 2, 36, 32, 1, 1, 0, 2, 36, 28, - 0, 1, 0, 2, 40, 38, 2, 1, 0, 2, 40, 32, 1, 1, 0, 2, 40, 28, - 0, 1, 0, 2, 44, 38, 2, 1, 0, 2, 44, 32, 1, 1, 0, 2, 44, 28, - 0, 1, 0, 2, 48, 38, 2, 1, 0, 2, 48, 32, 1, 1, 0, 2, 48, 28, - 0, 1, 0, 2, 52, 38, 2, 1, 0, 2, 52, 32, 1, 1, 0, 2, 52, 28, - 0, 1, 0, 2, 56, 38, 2, 1, 0, 2, 56, 32, 1, 1, 0, 2, 56, 28, - 0, 1, 0, 2, 60, 38, 2, 1, 0, 2, 60, 32, 1, 1, 0, 2, 60, 28, - 0, 1, 0, 2, 64, 34, 2, 1, 0, 2, 64, 32, 1, 1, 0, 2, 64, 28, - 0, 1, 0, 2, 100, 32, 2, 1, 0, 2, 100, 32, 1, 1, 0, 2, 100, 32, - 0, 1, 0, 2, 104, 38, 2, 1, 0, 2, 104, 32, 1, 1, 0, 2, 104, 32, - 0, 1, 0, 2, 108, 38, 2, 1, 0, 2, 108, 32, 1, 1, 0, 2, 108, 32, - 0, 1, 0, 2, 112, 38, 2, 1, 0, 2, 112, 32, 1, 1, 0, 2, 112, 32, - 0, 1, 0, 2, 116, 38, 2, 1, 0, 2, 116, 32, 1, 1, 0, 2, 116, 32, - 0, 1, 0, 2, 120, 38, 2, 1, 0, 2, 120, 32, 1, 1, 0, 2, 120, 32, - 0, 1, 0, 2, 124, 38, 2, 1, 0, 2, 124, 32, 1, 1, 0, 2, 124, 32, - 0, 1, 0, 2, 128, 38, 2, 1, 0, 2, 128, 32, 1, 1, 0, 2, 128, 32, - 0, 1, 0, 2, 132, 38, 2, 1, 0, 2, 132, 32, 1, 1, 0, 2, 132, 32, - 0, 1, 0, 2, 136, 38, 2, 1, 0, 2, 136, 32, 1, 1, 0, 2, 136, 32, - 0, 1, 0, 2, 140, 32, 2, 1, 0, 2, 140, 32, 1, 1, 0, 2, 140, 32, - 0, 1, 0, 2, 144, 26, 2, 1, 0, 2, 144, 63, 1, 1, 0, 2, 144, 63, - 0, 1, 0, 2, 149, 38, 2, 1, 0, 2, 149, 63, 1, 1, 0, 2, 149, 63, - 0, 1, 0, 2, 153, 38, 2, 1, 0, 2, 153, 63, 1, 1, 0, 2, 153, 63, - 0, 1, 0, 2, 157, 38, 2, 1, 0, 2, 157, 63, 1, 1, 0, 2, 157, 63, - 0, 1, 0, 2, 161, 38, 2, 1, 0, 2, 161, 63, 1, 1, 0, 2, 161, 63, - 0, 1, 0, 2, 165, 38, 2, 1, 0, 2, 165, 63, 1, 1, 0, 2, 165, 63, - 0, 1, 0, 3, 36, 34, 2, 1, 0, 3, 36, 20, 1, 1, 0, 3, 36, 22, - 0, 1, 0, 3, 40, 36, 2, 1, 0, 3, 40, 20, 1, 1, 0, 3, 40, 22, - 0, 1, 0, 3, 44, 36, 2, 1, 0, 3, 44, 20, 1, 1, 0, 3, 44, 22, - 0, 1, 0, 3, 48, 36, 2, 1, 0, 3, 48, 20, 1, 1, 0, 3, 48, 22, - 0, 1, 0, 3, 52, 36, 2, 1, 0, 3, 52, 20, 1, 1, 0, 3, 52, 22, - 0, 1, 0, 3, 56, 36, 2, 1, 0, 3, 56, 20, 1, 1, 0, 3, 56, 22, - 0, 1, 0, 3, 60, 36, 2, 1, 0, 3, 60, 20, 1, 1, 0, 3, 60, 22, - 0, 1, 0, 3, 64, 34, 2, 1, 0, 3, 64, 20, 1, 1, 0, 3, 64, 22, - 0, 1, 0, 3, 100, 32, 2, 1, 0, 3, 100, 20, 1, 1, 0, 3, 100, 30, - 0, 1, 0, 3, 104, 36, 2, 1, 0, 3, 104, 20, 1, 1, 0, 3, 104, 30, - 0, 1, 0, 3, 108, 38, 2, 1, 0, 3, 108, 20, 1, 1, 0, 3, 108, 30, - 0, 1, 0, 3, 112, 38, 2, 1, 0, 3, 112, 20, 1, 1, 0, 3, 112, 30, - 0, 1, 0, 3, 116, 38, 2, 1, 0, 3, 116, 20, 1, 1, 0, 3, 116, 30, - 0, 1, 0, 3, 120, 38, 2, 1, 0, 3, 120, 20, 1, 1, 0, 3, 120, 30, - 0, 1, 0, 3, 124, 38, 2, 1, 0, 3, 124, 20, 1, 1, 0, 3, 124, 30, - 0, 1, 0, 3, 128, 38, 2, 1, 0, 3, 128, 20, 1, 1, 0, 3, 128, 30, - 0, 1, 0, 3, 132, 38, 2, 1, 0, 3, 132, 20, 1, 1, 0, 3, 132, 30, - 0, 1, 0, 3, 136, 36, 2, 1, 0, 3, 136, 20, 1, 1, 0, 3, 136, 30, - 0, 1, 0, 3, 140, 32, 2, 1, 0, 3, 140, 20, 1, 1, 0, 3, 140, 30, - 0, 1, 0, 3, 144, 26, 2, 1, 0, 3, 144, 63, 1, 1, 0, 3, 144, 63, - 0, 1, 0, 3, 149, 38, 2, 1, 0, 3, 149, 63, 1, 1, 0, 3, 149, 63, - 0, 1, 0, 3, 153, 38, 2, 1, 0, 3, 153, 63, 1, 1, 0, 3, 153, 63, - 0, 1, 0, 3, 157, 38, 2, 1, 0, 3, 157, 63, 1, 1, 0, 3, 157, 63, - 0, 1, 0, 3, 161, 38, 2, 1, 0, 3, 161, 63, 1, 1, 0, 3, 161, 63, - 0, 1, 0, 3, 165, 38, 2, 1, 0, 3, 165, 63, 1, 1, 0, 3, 165, 63, - 0, 1, 1, 2, 38, 28, 2, 1, 1, 2, 38, 30, 1, 1, 1, 2, 38, 30, - 0, 1, 1, 2, 46, 36, 2, 1, 1, 2, 46, 30, 1, 1, 1, 2, 46, 30, - 0, 1, 1, 2, 54, 36, 2, 1, 1, 2, 54, 30, 1, 1, 1, 2, 54, 30, - 0, 1, 1, 2, 62, 30, 2, 1, 1, 2, 62, 30, 1, 1, 1, 2, 62, 30, - 0, 1, 1, 2, 102, 30, 2, 1, 1, 2, 102, 30, 1, 1, 1, 2, 102, 30, - 0, 1, 1, 2, 110, 36, 2, 1, 1, 2, 110, 30, 1, 1, 1, 2, 110, 30, - 0, 1, 1, 2, 118, 36, 2, 1, 1, 2, 118, 30, 1, 1, 1, 2, 118, 30, - 0, 1, 1, 2, 126, 36, 2, 1, 1, 2, 126, 30, 1, 1, 1, 2, 126, 30, - 0, 1, 1, 2, 134, 36, 2, 1, 1, 2, 134, 30, 1, 1, 1, 2, 134, 30, - 0, 1, 1, 2, 142, 30, 2, 1, 1, 2, 142, 63, 1, 1, 1, 2, 142, 63, - 0, 1, 1, 2, 151, 36, 2, 1, 1, 2, 151, 63, 1, 1, 1, 2, 151, 63, - 0, 1, 1, 2, 159, 36, 2, 1, 1, 2, 159, 63, 1, 1, 1, 2, 159, 63, - 0, 1, 1, 3, 38, 26, 2, 1, 1, 3, 38, 20, 1, 1, 1, 3, 38, 22, - 0, 1, 1, 3, 46, 36, 2, 1, 1, 3, 46, 20, 1, 1, 1, 3, 46, 22, - 0, 1, 1, 3, 54, 36, 2, 1, 1, 3, 54, 20, 1, 1, 1, 3, 54, 22, - 0, 1, 1, 3, 62, 28, 2, 1, 1, 3, 62, 20, 1, 1, 1, 3, 62, 22, - 0, 1, 1, 3, 102, 28, 2, 1, 1, 3, 102, 20, 1, 1, 1, 3, 102, 30, - 0, 1, 1, 3, 110, 36, 2, 1, 1, 3, 110, 20, 1, 1, 1, 3, 110, 30, - 0, 1, 1, 3, 118, 36, 2, 1, 1, 3, 118, 20, 1, 1, 1, 3, 118, 30, - 0, 1, 1, 3, 126, 36, 2, 1, 1, 3, 126, 20, 1, 1, 1, 3, 126, 30, - 0, 1, 1, 3, 134, 36, 2, 1, 1, 3, 134, 20, 1, 1, 1, 3, 134, 30, - 0, 1, 1, 3, 142, 30, 2, 1, 1, 3, 142, 63, 1, 1, 1, 3, 142, 63, - 0, 1, 1, 3, 151, 36, 2, 1, 1, 3, 151, 63, 1, 1, 1, 3, 151, 63, - 0, 1, 1, 3, 159, 36, 2, 1, 1, 3, 159, 63, 1, 1, 1, 3, 159, 63, - 0, 1, 2, 4, 42, 26, 2, 1, 2, 4, 42, 30, 1, 1, 2, 4, 42, 28, - 0, 1, 2, 4, 58, 26, 2, 1, 2, 4, 58, 30, 1, 1, 2, 4, 58, 28, - 0, 1, 2, 4, 106, 26, 2, 1, 2, 4, 106, 30, 1, 1, 2, 4, 106, 30, - 0, 1, 2, 4, 122, 36, 2, 1, 2, 4, 122, 30, 1, 1, 2, 4, 122, 30, - 0, 1, 2, 4, 138, 36, 2, 1, 2, 4, 138, 63, 1, 1, 2, 4, 138, 63, - 0, 1, 2, 4, 155, 36, 2, 1, 2, 4, 155, 63, 1, 1, 2, 4, 155, 63, - 0, 1, 2, 5, 42, 24, 2, 1, 2, 5, 42, 20, 1, 1, 2, 5, 42, 22, - 0, 1, 2, 5, 58, 24, 2, 1, 2, 5, 58, 20, 1, 1, 2, 5, 58, 22, - 0, 1, 2, 5, 106, 26, 2, 1, 2, 5, 106, 20, 1, 1, 2, 5, 106, 30, - 0, 1, 2, 5, 122, 36, 2, 1, 2, 5, 122, 20, 1, 1, 2, 5, 122, 30, - 0, 1, 2, 5, 138, 36, 2, 1, 2, 5, 138, 63, 1, 1, 2, 5, 138, 63, - 0, 1, 2, 5, 155, 36, 2, 1, 2, 5, 155, 63, 1, 1, 2, 5, 155, 63 +static const struct rtw_txpwr_lmt_cfg_pair rtw8822b_txpwr_lmt_type2[] = { + { 0, 0, 0, 0, 1, 32, }, + { 2, 0, 0, 0, 1, 28, }, + { 1, 0, 0, 0, 1, 30, }, + { 0, 0, 0, 0, 2, 32, }, + { 2, 0, 0, 0, 2, 28, }, + { 1, 0, 0, 0, 2, 30, }, + { 0, 0, 0, 0, 3, 32, }, + { 2, 0, 0, 0, 3, 28, }, + { 1, 0, 0, 0, 3, 30, }, + { 0, 0, 0, 0, 4, 32, }, + { 2, 0, 0, 0, 4, 28, }, + { 1, 0, 0, 0, 4, 30, }, + { 0, 0, 0, 0, 5, 32, }, + { 2, 0, 0, 0, 5, 28, }, + { 1, 0, 0, 0, 5, 30, }, + { 0, 0, 0, 0, 6, 32, }, + { 2, 0, 0, 0, 6, 28, }, + { 1, 0, 0, 0, 6, 30, }, + { 0, 0, 0, 0, 7, 32, }, + { 2, 0, 0, 0, 7, 28, }, + { 1, 0, 0, 0, 7, 30, }, + { 0, 0, 0, 0, 8, 32, }, + { 2, 0, 0, 0, 8, 28, }, + { 1, 0, 0, 0, 8, 30, }, + { 0, 0, 0, 0, 9, 32, }, + { 2, 0, 0, 0, 9, 28, }, + { 1, 0, 0, 0, 9, 30, }, + { 0, 0, 0, 0, 10, 32, }, + { 2, 0, 0, 0, 10, 28, }, + { 1, 0, 0, 0, 10, 30, }, + { 0, 0, 0, 0, 11, 32, }, + { 2, 0, 0, 0, 11, 28, }, + { 1, 0, 0, 0, 11, 30, }, + { 0, 0, 0, 0, 12, 26, }, + { 2, 0, 0, 0, 12, 28, }, + { 1, 0, 0, 0, 12, 30, }, + { 0, 0, 0, 0, 13, 20, }, + { 2, 0, 0, 0, 13, 28, }, + { 1, 0, 0, 0, 13, 28, }, + { 0, 0, 0, 0, 14, 63, }, + { 2, 0, 0, 0, 14, 63, }, + { 1, 0, 0, 0, 14, 32, }, + { 0, 0, 0, 1, 1, 26, }, + { 2, 0, 0, 1, 1, 30, }, + { 1, 0, 0, 1, 1, 34, }, + { 0, 0, 0, 1, 2, 30, }, + { 2, 0, 0, 1, 2, 30, }, + { 1, 0, 0, 1, 2, 34, }, + { 0, 0, 0, 1, 3, 32, }, + { 2, 0, 0, 1, 3, 30, }, + { 1, 0, 0, 1, 3, 34, }, + { 0, 0, 0, 1, 4, 34, }, + { 2, 0, 0, 1, 4, 30, }, + { 1, 0, 0, 1, 4, 34, }, + { 0, 0, 0, 1, 5, 34, }, + { 2, 0, 0, 1, 5, 30, }, + { 1, 0, 0, 1, 5, 34, }, + { 0, 0, 0, 1, 6, 34, }, + { 2, 0, 0, 1, 6, 30, }, + { 1, 0, 0, 1, 6, 34, }, + { 0, 0, 0, 1, 7, 34, }, + { 2, 0, 0, 1, 7, 30, }, + { 1, 0, 0, 1, 7, 34, }, + { 0, 0, 0, 1, 8, 34, }, + { 2, 0, 0, 1, 8, 30, }, + { 1, 0, 0, 1, 8, 34, }, + { 0, 0, 0, 1, 9, 32, }, + { 2, 0, 0, 1, 9, 30, }, + { 1, 0, 0, 1, 9, 34, }, + { 0, 0, 0, 1, 10, 30, }, + { 2, 0, 0, 1, 10, 30, }, + { 1, 0, 0, 1, 10, 34, }, + { 0, 0, 0, 1, 11, 28, }, + { 2, 0, 0, 1, 11, 30, }, + { 1, 0, 0, 1, 11, 34, }, + { 0, 0, 0, 1, 12, 22, }, + { 2, 0, 0, 1, 12, 30, }, + { 1, 0, 0, 1, 12, 34, }, + { 0, 0, 0, 1, 13, 14, }, + { 2, 0, 0, 1, 13, 30, }, + { 1, 0, 0, 1, 13, 34, }, + { 0, 0, 0, 1, 14, 63, }, + { 2, 0, 0, 1, 14, 63, }, + { 1, 0, 0, 1, 14, 63, }, + { 0, 0, 0, 2, 1, 26, }, + { 2, 0, 0, 2, 1, 30, }, + { 1, 0, 0, 2, 1, 34, }, + { 0, 0, 0, 2, 2, 30, }, + { 2, 0, 0, 2, 2, 30, }, + { 1, 0, 0, 2, 2, 34, }, + { 0, 0, 0, 2, 3, 32, }, + { 2, 0, 0, 2, 3, 30, }, + { 1, 0, 0, 2, 3, 34, }, + { 0, 0, 0, 2, 4, 34, }, + { 2, 0, 0, 2, 4, 30, }, + { 1, 0, 0, 2, 4, 34, }, + { 0, 0, 0, 2, 5, 34, }, + { 2, 0, 0, 2, 5, 30, }, + { 1, 0, 0, 2, 5, 34, }, + { 0, 0, 0, 2, 6, 34, }, + { 2, 0, 0, 2, 6, 30, }, + { 1, 0, 0, 2, 6, 34, }, + { 0, 0, 0, 2, 7, 34, }, + { 2, 0, 0, 2, 7, 30, }, + { 1, 0, 0, 2, 7, 34, }, + { 0, 0, 0, 2, 8, 34, }, + { 2, 0, 0, 2, 8, 30, }, + { 1, 0, 0, 2, 8, 34, }, + { 0, 0, 0, 2, 9, 32, }, + { 2, 0, 0, 2, 9, 30, }, + { 1, 0, 0, 2, 9, 34, }, + { 0, 0, 0, 2, 10, 30, }, + { 2, 0, 0, 2, 10, 30, }, + { 1, 0, 0, 2, 10, 34, }, + { 0, 0, 0, 2, 11, 26, }, + { 2, 0, 0, 2, 11, 30, }, + { 1, 0, 0, 2, 11, 34, }, + { 0, 0, 0, 2, 12, 20, }, + { 2, 0, 0, 2, 12, 30, }, + { 1, 0, 0, 2, 12, 34, }, + { 0, 0, 0, 2, 13, 14, }, + { 2, 0, 0, 2, 13, 30, }, + { 1, 0, 0, 2, 13, 34, }, + { 0, 0, 0, 2, 14, 63, }, + { 2, 0, 0, 2, 14, 63, }, + { 1, 0, 0, 2, 14, 63, }, + { 0, 0, 0, 3, 1, 26, }, + { 2, 0, 0, 3, 1, 18, }, + { 1, 0, 0, 3, 1, 30, }, + { 0, 0, 0, 3, 2, 28, }, + { 2, 0, 0, 3, 2, 18, }, + { 1, 0, 0, 3, 2, 30, }, + { 0, 0, 0, 3, 3, 30, }, + { 2, 0, 0, 3, 3, 18, }, + { 1, 0, 0, 3, 3, 30, }, + { 0, 0, 0, 3, 4, 30, }, + { 2, 0, 0, 3, 4, 18, }, + { 1, 0, 0, 3, 4, 30, }, + { 0, 0, 0, 3, 5, 32, }, + { 2, 0, 0, 3, 5, 18, }, + { 1, 0, 0, 3, 5, 30, }, + { 0, 0, 0, 3, 6, 32, }, + { 2, 0, 0, 3, 6, 18, }, + { 1, 0, 0, 3, 6, 30, }, + { 0, 0, 0, 3, 7, 32, }, + { 2, 0, 0, 3, 7, 18, }, + { 1, 0, 0, 3, 7, 30, }, + { 0, 0, 0, 3, 8, 30, }, + { 2, 0, 0, 3, 8, 18, }, + { 1, 0, 0, 3, 8, 30, }, + { 0, 0, 0, 3, 9, 30, }, + { 2, 0, 0, 3, 9, 18, }, + { 1, 0, 0, 3, 9, 30, }, + { 0, 0, 0, 3, 10, 28, }, + { 2, 0, 0, 3, 10, 18, }, + { 1, 0, 0, 3, 10, 30, }, + { 0, 0, 0, 3, 11, 26, }, + { 2, 0, 0, 3, 11, 18, }, + { 1, 0, 0, 3, 11, 30, }, + { 0, 0, 0, 3, 12, 20, }, + { 2, 0, 0, 3, 12, 18, }, + { 1, 0, 0, 3, 12, 30, }, + { 0, 0, 0, 3, 13, 14, }, + { 2, 0, 0, 3, 13, 18, }, + { 1, 0, 0, 3, 13, 30, }, + { 0, 0, 0, 3, 14, 63, }, + { 2, 0, 0, 3, 14, 63, }, + { 1, 0, 0, 3, 14, 63, }, + { 0, 0, 1, 2, 1, 63, }, + { 2, 0, 1, 2, 1, 63, }, + { 1, 0, 1, 2, 1, 63, }, + { 0, 0, 1, 2, 2, 63, }, + { 2, 0, 1, 2, 2, 63, }, + { 1, 0, 1, 2, 2, 63, }, + { 0, 0, 1, 2, 3, 26, }, + { 2, 0, 1, 2, 3, 30, }, + { 1, 0, 1, 2, 3, 34, }, + { 0, 0, 1, 2, 4, 26, }, + { 2, 0, 1, 2, 4, 30, }, + { 1, 0, 1, 2, 4, 34, }, + { 0, 0, 1, 2, 5, 30, }, + { 2, 0, 1, 2, 5, 30, }, + { 1, 0, 1, 2, 5, 34, }, + { 0, 0, 1, 2, 6, 32, }, + { 2, 0, 1, 2, 6, 30, }, + { 1, 0, 1, 2, 6, 34, }, + { 0, 0, 1, 2, 7, 30, }, + { 2, 0, 1, 2, 7, 30, }, + { 1, 0, 1, 2, 7, 34, }, + { 0, 0, 1, 2, 8, 26, }, + { 2, 0, 1, 2, 8, 30, }, + { 1, 0, 1, 2, 8, 34, }, + { 0, 0, 1, 2, 9, 26, }, + { 2, 0, 1, 2, 9, 30, }, + { 1, 0, 1, 2, 9, 34, }, + { 0, 0, 1, 2, 10, 20, }, + { 2, 0, 1, 2, 10, 30, }, + { 1, 0, 1, 2, 10, 34, }, + { 0, 0, 1, 2, 11, 14, }, + { 2, 0, 1, 2, 11, 30, }, + { 1, 0, 1, 2, 11, 34, }, + { 0, 0, 1, 2, 12, 63, }, + { 2, 0, 1, 2, 12, 63, }, + { 1, 0, 1, 2, 12, 63, }, + { 0, 0, 1, 2, 13, 63, }, + { 2, 0, 1, 2, 13, 63, }, + { 1, 0, 1, 2, 13, 63, }, + { 0, 0, 1, 2, 14, 63, }, + { 2, 0, 1, 2, 14, 63, }, + { 1, 0, 1, 2, 14, 63, }, + { 0, 0, 1, 3, 1, 63, }, + { 2, 0, 1, 3, 1, 63, }, + { 1, 0, 1, 3, 1, 63, }, + { 0, 0, 1, 3, 2, 63, }, + { 2, 0, 1, 3, 2, 63, }, + { 1, 0, 1, 3, 2, 63, }, + { 0, 0, 1, 3, 3, 24, }, + { 2, 0, 1, 3, 3, 18, }, + { 1, 0, 1, 3, 3, 30, }, + { 0, 0, 1, 3, 4, 24, }, + { 2, 0, 1, 3, 4, 18, }, + { 1, 0, 1, 3, 4, 30, }, + { 0, 0, 1, 3, 5, 26, }, + { 2, 0, 1, 3, 5, 18, }, + { 1, 0, 1, 3, 5, 30, }, + { 0, 0, 1, 3, 6, 28, }, + { 2, 0, 1, 3, 6, 18, }, + { 1, 0, 1, 3, 6, 30, }, + { 0, 0, 1, 3, 7, 26, }, + { 2, 0, 1, 3, 7, 18, }, + { 1, 0, 1, 3, 7, 30, }, + { 0, 0, 1, 3, 8, 26, }, + { 2, 0, 1, 3, 8, 18, }, + { 1, 0, 1, 3, 8, 30, }, + { 0, 0, 1, 3, 9, 26, }, + { 2, 0, 1, 3, 9, 18, }, + { 1, 0, 1, 3, 9, 30, }, + { 0, 0, 1, 3, 10, 20, }, + { 2, 0, 1, 3, 10, 18, }, + { 1, 0, 1, 3, 10, 30, }, + { 0, 0, 1, 3, 11, 14, }, + { 2, 0, 1, 3, 11, 18, }, + { 1, 0, 1, 3, 11, 30, }, + { 0, 0, 1, 3, 12, 63, }, + { 2, 0, 1, 3, 12, 63, }, + { 1, 0, 1, 3, 12, 63, }, + { 0, 0, 1, 3, 13, 63, }, + { 2, 0, 1, 3, 13, 63, }, + { 1, 0, 1, 3, 13, 63, }, + { 0, 0, 1, 3, 14, 63, }, + { 2, 0, 1, 3, 14, 63, }, + { 1, 0, 1, 3, 14, 63, }, + { 0, 1, 0, 1, 36, 36, }, + { 2, 1, 0, 1, 36, 32, }, + { 1, 1, 0, 1, 36, 30, }, + { 0, 1, 0, 1, 40, 38, }, + { 2, 1, 0, 1, 40, 32, }, + { 1, 1, 0, 1, 40, 30, }, + { 0, 1, 0, 1, 44, 38, }, + { 2, 1, 0, 1, 44, 32, }, + { 1, 1, 0, 1, 44, 30, }, + { 0, 1, 0, 1, 48, 38, }, + { 2, 1, 0, 1, 48, 32, }, + { 1, 1, 0, 1, 48, 30, }, + { 0, 1, 0, 1, 52, 38, }, + { 2, 1, 0, 1, 52, 32, }, + { 1, 1, 0, 1, 52, 28, }, + { 0, 1, 0, 1, 56, 38, }, + { 2, 1, 0, 1, 56, 32, }, + { 1, 1, 0, 1, 56, 28, }, + { 0, 1, 0, 1, 60, 38, }, + { 2, 1, 0, 1, 60, 32, }, + { 1, 1, 0, 1, 60, 28, }, + { 0, 1, 0, 1, 64, 34, }, + { 2, 1, 0, 1, 64, 32, }, + { 1, 1, 0, 1, 64, 28, }, + { 0, 1, 0, 1, 100, 32, }, + { 2, 1, 0, 1, 100, 32, }, + { 1, 1, 0, 1, 100, 32, }, + { 0, 1, 0, 1, 104, 38, }, + { 2, 1, 0, 1, 104, 32, }, + { 1, 1, 0, 1, 104, 32, }, + { 0, 1, 0, 1, 108, 38, }, + { 2, 1, 0, 1, 108, 32, }, + { 1, 1, 0, 1, 108, 32, }, + { 0, 1, 0, 1, 112, 38, }, + { 2, 1, 0, 1, 112, 32, }, + { 1, 1, 0, 1, 112, 32, }, + { 0, 1, 0, 1, 116, 38, }, + { 2, 1, 0, 1, 116, 32, }, + { 1, 1, 0, 1, 116, 32, }, + { 0, 1, 0, 1, 120, 38, }, + { 2, 1, 0, 1, 120, 32, }, + { 1, 1, 0, 1, 120, 32, }, + { 0, 1, 0, 1, 124, 38, }, + { 2, 1, 0, 1, 124, 32, }, + { 1, 1, 0, 1, 124, 32, }, + { 0, 1, 0, 1, 128, 38, }, + { 2, 1, 0, 1, 128, 32, }, + { 1, 1, 0, 1, 128, 32, }, + { 0, 1, 0, 1, 132, 38, }, + { 2, 1, 0, 1, 132, 32, }, + { 1, 1, 0, 1, 132, 32, }, + { 0, 1, 0, 1, 136, 38, }, + { 2, 1, 0, 1, 136, 32, }, + { 1, 1, 0, 1, 136, 32, }, + { 0, 1, 0, 1, 140, 34, }, + { 2, 1, 0, 1, 140, 32, }, + { 1, 1, 0, 1, 140, 32, }, + { 0, 1, 0, 1, 144, 34, }, + { 2, 1, 0, 1, 144, 32, }, + { 1, 1, 0, 1, 144, 63, }, + { 0, 1, 0, 1, 149, 38, }, + { 2, 1, 0, 1, 149, 63, }, + { 1, 1, 0, 1, 149, 63, }, + { 0, 1, 0, 1, 153, 38, }, + { 2, 1, 0, 1, 153, 63, }, + { 1, 1, 0, 1, 153, 63, }, + { 0, 1, 0, 1, 157, 38, }, + { 2, 1, 0, 1, 157, 63, }, + { 1, 1, 0, 1, 157, 63, }, + { 0, 1, 0, 1, 161, 38, }, + { 2, 1, 0, 1, 161, 63, }, + { 1, 1, 0, 1, 161, 63, }, + { 0, 1, 0, 1, 165, 38, }, + { 2, 1, 0, 1, 165, 63, }, + { 1, 1, 0, 1, 165, 63, }, + { 0, 1, 0, 2, 36, 36, }, + { 2, 1, 0, 2, 36, 32, }, + { 1, 1, 0, 2, 36, 28, }, + { 0, 1, 0, 2, 40, 38, }, + { 2, 1, 0, 2, 40, 32, }, + { 1, 1, 0, 2, 40, 28, }, + { 0, 1, 0, 2, 44, 38, }, + { 2, 1, 0, 2, 44, 32, }, + { 1, 1, 0, 2, 44, 28, }, + { 0, 1, 0, 2, 48, 38, }, + { 2, 1, 0, 2, 48, 32, }, + { 1, 1, 0, 2, 48, 28, }, + { 0, 1, 0, 2, 52, 38, }, + { 2, 1, 0, 2, 52, 32, }, + { 1, 1, 0, 2, 52, 28, }, + { 0, 1, 0, 2, 56, 38, }, + { 2, 1, 0, 2, 56, 32, }, + { 1, 1, 0, 2, 56, 28, }, + { 0, 1, 0, 2, 60, 38, }, + { 2, 1, 0, 2, 60, 32, }, + { 1, 1, 0, 2, 60, 28, }, + { 0, 1, 0, 2, 64, 34, }, + { 2, 1, 0, 2, 64, 32, }, + { 1, 1, 0, 2, 64, 28, }, + { 0, 1, 0, 2, 100, 32, }, + { 2, 1, 0, 2, 100, 32, }, + { 1, 1, 0, 2, 100, 32, }, + { 0, 1, 0, 2, 104, 38, }, + { 2, 1, 0, 2, 104, 32, }, + { 1, 1, 0, 2, 104, 32, }, + { 0, 1, 0, 2, 108, 38, }, + { 2, 1, 0, 2, 108, 32, }, + { 1, 1, 0, 2, 108, 32, }, + { 0, 1, 0, 2, 112, 38, }, + { 2, 1, 0, 2, 112, 32, }, + { 1, 1, 0, 2, 112, 32, }, + { 0, 1, 0, 2, 116, 38, }, + { 2, 1, 0, 2, 116, 32, }, + { 1, 1, 0, 2, 116, 32, }, + { 0, 1, 0, 2, 120, 38, }, + { 2, 1, 0, 2, 120, 32, }, + { 1, 1, 0, 2, 120, 32, }, + { 0, 1, 0, 2, 124, 38, }, + { 2, 1, 0, 2, 124, 32, }, + { 1, 1, 0, 2, 124, 32, }, + { 0, 1, 0, 2, 128, 38, }, + { 2, 1, 0, 2, 128, 32, }, + { 1, 1, 0, 2, 128, 32, }, + { 0, 1, 0, 2, 132, 38, }, + { 2, 1, 0, 2, 132, 32, }, + { 1, 1, 0, 2, 132, 32, }, + { 0, 1, 0, 2, 136, 38, }, + { 2, 1, 0, 2, 136, 32, }, + { 1, 1, 0, 2, 136, 32, }, + { 0, 1, 0, 2, 140, 32, }, + { 2, 1, 0, 2, 140, 32, }, + { 1, 1, 0, 2, 140, 32, }, + { 0, 1, 0, 2, 144, 26, }, + { 2, 1, 0, 2, 144, 63, }, + { 1, 1, 0, 2, 144, 63, }, + { 0, 1, 0, 2, 149, 38, }, + { 2, 1, 0, 2, 149, 63, }, + { 1, 1, 0, 2, 149, 63, }, + { 0, 1, 0, 2, 153, 38, }, + { 2, 1, 0, 2, 153, 63, }, + { 1, 1, 0, 2, 153, 63, }, + { 0, 1, 0, 2, 157, 38, }, + { 2, 1, 0, 2, 157, 63, }, + { 1, 1, 0, 2, 157, 63, }, + { 0, 1, 0, 2, 161, 38, }, + { 2, 1, 0, 2, 161, 63, }, + { 1, 1, 0, 2, 161, 63, }, + { 0, 1, 0, 2, 165, 38, }, + { 2, 1, 0, 2, 165, 63, }, + { 1, 1, 0, 2, 165, 63, }, + { 0, 1, 0, 3, 36, 34, }, + { 2, 1, 0, 3, 36, 20, }, + { 1, 1, 0, 3, 36, 22, }, + { 0, 1, 0, 3, 40, 36, }, + { 2, 1, 0, 3, 40, 20, }, + { 1, 1, 0, 3, 40, 22, }, + { 0, 1, 0, 3, 44, 36, }, + { 2, 1, 0, 3, 44, 20, }, + { 1, 1, 0, 3, 44, 22, }, + { 0, 1, 0, 3, 48, 36, }, + { 2, 1, 0, 3, 48, 20, }, + { 1, 1, 0, 3, 48, 22, }, + { 0, 1, 0, 3, 52, 36, }, + { 2, 1, 0, 3, 52, 20, }, + { 1, 1, 0, 3, 52, 22, }, + { 0, 1, 0, 3, 56, 36, }, + { 2, 1, 0, 3, 56, 20, }, + { 1, 1, 0, 3, 56, 22, }, + { 0, 1, 0, 3, 60, 36, }, + { 2, 1, 0, 3, 60, 20, }, + { 1, 1, 0, 3, 60, 22, }, + { 0, 1, 0, 3, 64, 34, }, + { 2, 1, 0, 3, 64, 20, }, + { 1, 1, 0, 3, 64, 22, }, + { 0, 1, 0, 3, 100, 32, }, + { 2, 1, 0, 3, 100, 20, }, + { 1, 1, 0, 3, 100, 30, }, + { 0, 1, 0, 3, 104, 36, }, + { 2, 1, 0, 3, 104, 20, }, + { 1, 1, 0, 3, 104, 30, }, + { 0, 1, 0, 3, 108, 38, }, + { 2, 1, 0, 3, 108, 20, }, + { 1, 1, 0, 3, 108, 30, }, + { 0, 1, 0, 3, 112, 38, }, + { 2, 1, 0, 3, 112, 20, }, + { 1, 1, 0, 3, 112, 30, }, + { 0, 1, 0, 3, 116, 38, }, + { 2, 1, 0, 3, 116, 20, }, + { 1, 1, 0, 3, 116, 30, }, + { 0, 1, 0, 3, 120, 38, }, + { 2, 1, 0, 3, 120, 20, }, + { 1, 1, 0, 3, 120, 30, }, + { 0, 1, 0, 3, 124, 38, }, + { 2, 1, 0, 3, 124, 20, }, + { 1, 1, 0, 3, 124, 30, }, + { 0, 1, 0, 3, 128, 38, }, + { 2, 1, 0, 3, 128, 20, }, + { 1, 1, 0, 3, 128, 30, }, + { 0, 1, 0, 3, 132, 38, }, + { 2, 1, 0, 3, 132, 20, }, + { 1, 1, 0, 3, 132, 30, }, + { 0, 1, 0, 3, 136, 36, }, + { 2, 1, 0, 3, 136, 20, }, + { 1, 1, 0, 3, 136, 30, }, + { 0, 1, 0, 3, 140, 32, }, + { 2, 1, 0, 3, 140, 20, }, + { 1, 1, 0, 3, 140, 30, }, + { 0, 1, 0, 3, 144, 26, }, + { 2, 1, 0, 3, 144, 63, }, + { 1, 1, 0, 3, 144, 63, }, + { 0, 1, 0, 3, 149, 38, }, + { 2, 1, 0, 3, 149, 63, }, + { 1, 1, 0, 3, 149, 63, }, + { 0, 1, 0, 3, 153, 38, }, + { 2, 1, 0, 3, 153, 63, }, + { 1, 1, 0, 3, 153, 63, }, + { 0, 1, 0, 3, 157, 38, }, + { 2, 1, 0, 3, 157, 63, }, + { 1, 1, 0, 3, 157, 63, }, + { 0, 1, 0, 3, 161, 38, }, + { 2, 1, 0, 3, 161, 63, }, + { 1, 1, 0, 3, 161, 63, }, + { 0, 1, 0, 3, 165, 38, }, + { 2, 1, 0, 3, 165, 63, }, + { 1, 1, 0, 3, 165, 63, }, + { 0, 1, 1, 2, 38, 28, }, + { 2, 1, 1, 2, 38, 30, }, + { 1, 1, 1, 2, 38, 30, }, + { 0, 1, 1, 2, 46, 36, }, + { 2, 1, 1, 2, 46, 30, }, + { 1, 1, 1, 2, 46, 30, }, + { 0, 1, 1, 2, 54, 36, }, + { 2, 1, 1, 2, 54, 30, }, + { 1, 1, 1, 2, 54, 30, }, + { 0, 1, 1, 2, 62, 30, }, + { 2, 1, 1, 2, 62, 30, }, + { 1, 1, 1, 2, 62, 30, }, + { 0, 1, 1, 2, 102, 30, }, + { 2, 1, 1, 2, 102, 30, }, + { 1, 1, 1, 2, 102, 30, }, + { 0, 1, 1, 2, 110, 36, }, + { 2, 1, 1, 2, 110, 30, }, + { 1, 1, 1, 2, 110, 30, }, + { 0, 1, 1, 2, 118, 36, }, + { 2, 1, 1, 2, 118, 30, }, + { 1, 1, 1, 2, 118, 30, }, + { 0, 1, 1, 2, 126, 36, }, + { 2, 1, 1, 2, 126, 30, }, + { 1, 1, 1, 2, 126, 30, }, + { 0, 1, 1, 2, 134, 36, }, + { 2, 1, 1, 2, 134, 30, }, + { 1, 1, 1, 2, 134, 30, }, + { 0, 1, 1, 2, 142, 30, }, + { 2, 1, 1, 2, 142, 63, }, + { 1, 1, 1, 2, 142, 63, }, + { 0, 1, 1, 2, 151, 36, }, + { 2, 1, 1, 2, 151, 63, }, + { 1, 1, 1, 2, 151, 63, }, + { 0, 1, 1, 2, 159, 36, }, + { 2, 1, 1, 2, 159, 63, }, + { 1, 1, 1, 2, 159, 63, }, + { 0, 1, 1, 3, 38, 26, }, + { 2, 1, 1, 3, 38, 20, }, + { 1, 1, 1, 3, 38, 22, }, + { 0, 1, 1, 3, 46, 36, }, + { 2, 1, 1, 3, 46, 20, }, + { 1, 1, 1, 3, 46, 22, }, + { 0, 1, 1, 3, 54, 36, }, + { 2, 1, 1, 3, 54, 20, }, + { 1, 1, 1, 3, 54, 22, }, + { 0, 1, 1, 3, 62, 28, }, + { 2, 1, 1, 3, 62, 20, }, + { 1, 1, 1, 3, 62, 22, }, + { 0, 1, 1, 3, 102, 28, }, + { 2, 1, 1, 3, 102, 20, }, + { 1, 1, 1, 3, 102, 30, }, + { 0, 1, 1, 3, 110, 36, }, + { 2, 1, 1, 3, 110, 20, }, + { 1, 1, 1, 3, 110, 30, }, + { 0, 1, 1, 3, 118, 36, }, + { 2, 1, 1, 3, 118, 20, }, + { 1, 1, 1, 3, 118, 30, }, + { 0, 1, 1, 3, 126, 36, }, + { 2, 1, 1, 3, 126, 20, }, + { 1, 1, 1, 3, 126, 30, }, + { 0, 1, 1, 3, 134, 36, }, + { 2, 1, 1, 3, 134, 20, }, + { 1, 1, 1, 3, 134, 30, }, + { 0, 1, 1, 3, 142, 30, }, + { 2, 1, 1, 3, 142, 63, }, + { 1, 1, 1, 3, 142, 63, }, + { 0, 1, 1, 3, 151, 36, }, + { 2, 1, 1, 3, 151, 63, }, + { 1, 1, 1, 3, 151, 63, }, + { 0, 1, 1, 3, 159, 36, }, + { 2, 1, 1, 3, 159, 63, }, + { 1, 1, 1, 3, 159, 63, }, + { 0, 1, 2, 4, 42, 26, }, + { 2, 1, 2, 4, 42, 30, }, + { 1, 1, 2, 4, 42, 28, }, + { 0, 1, 2, 4, 58, 26, }, + { 2, 1, 2, 4, 58, 30, }, + { 1, 1, 2, 4, 58, 28, }, + { 0, 1, 2, 4, 106, 26, }, + { 2, 1, 2, 4, 106, 30, }, + { 1, 1, 2, 4, 106, 30, }, + { 0, 1, 2, 4, 122, 36, }, + { 2, 1, 2, 4, 122, 30, }, + { 1, 1, 2, 4, 122, 30, }, + { 0, 1, 2, 4, 138, 36, }, + { 2, 1, 2, 4, 138, 63, }, + { 1, 1, 2, 4, 138, 63, }, + { 0, 1, 2, 4, 155, 36, }, + { 2, 1, 2, 4, 155, 63, }, + { 1, 1, 2, 4, 155, 63, }, + { 0, 1, 2, 5, 42, 24, }, + { 2, 1, 2, 5, 42, 20, }, + { 1, 1, 2, 5, 42, 22, }, + { 0, 1, 2, 5, 58, 24, }, + { 2, 1, 2, 5, 58, 20, }, + { 1, 1, 2, 5, 58, 22, }, + { 0, 1, 2, 5, 106, 26, }, + { 2, 1, 2, 5, 106, 20, }, + { 1, 1, 2, 5, 106, 30, }, + { 0, 1, 2, 5, 122, 36, }, + { 2, 1, 2, 5, 122, 20, }, + { 1, 1, 2, 5, 122, 30, }, + { 0, 1, 2, 5, 138, 36, }, + { 2, 1, 2, 5, 138, 63, }, + { 1, 1, 2, 5, 138, 63, }, + { 0, 1, 2, 5, 155, 36, }, + { 2, 1, 2, 5, 155, 63, }, + { 1, 1, 2, 5, 155, 63 }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8822b_txpwr_lmt_type2); -static const u8 rtw8822b_txpwr_lmt_type5[] = { - 0, 0, 0, 0, 1, 32, 2, 0, 0, 0, 1, 28, 1, 0, 0, 0, 1, 30, - 0, 0, 0, 0, 2, 32, 2, 0, 0, 0, 2, 28, 1, 0, 0, 0, 2, 30, - 0, 0, 0, 0, 3, 32, 2, 0, 0, 0, 3, 28, 1, 0, 0, 0, 3, 30, - 0, 0, 0, 0, 4, 32, 2, 0, 0, 0, 4, 28, 1, 0, 0, 0, 4, 30, - 0, 0, 0, 0, 5, 32, 2, 0, 0, 0, 5, 28, 1, 0, 0, 0, 5, 30, - 0, 0, 0, 0, 6, 32, 2, 0, 0, 0, 6, 28, 1, 0, 0, 0, 6, 30, - 0, 0, 0, 0, 7, 32, 2, 0, 0, 0, 7, 28, 1, 0, 0, 0, 7, 30, - 0, 0, 0, 0, 8, 32, 2, 0, 0, 0, 8, 28, 1, 0, 0, 0, 8, 30, - 0, 0, 0, 0, 9, 32, 2, 0, 0, 0, 9, 28, 1, 0, 0, 0, 9, 30, - 0, 0, 0, 0, 10, 32, 2, 0, 0, 0, 10, 28, 1, 0, 0, 0, 10, 30, - 0, 0, 0, 0, 11, 32, 2, 0, 0, 0, 11, 28, 1, 0, 0, 0, 11, 30, - 0, 0, 0, 0, 12, 26, 2, 0, 0, 0, 12, 28, 1, 0, 0, 0, 12, 30, - 0, 0, 0, 0, 13, 20, 2, 0, 0, 0, 13, 28, 1, 0, 0, 0, 13, 28, - 0, 0, 0, 0, 14, 63, 2, 0, 0, 0, 14, 63, 1, 0, 0, 0, 14, 32, - 0, 0, 0, 1, 1, 26, 2, 0, 0, 1, 1, 30, 1, 0, 0, 1, 1, 34, - 0, 0, 0, 1, 2, 30, 2, 0, 0, 1, 2, 30, 1, 0, 0, 1, 2, 34, - 0, 0, 0, 1, 3, 32, 2, 0, 0, 1, 3, 30, 1, 0, 0, 1, 3, 34, - 0, 0, 0, 1, 4, 34, 2, 0, 0, 1, 4, 30, 1, 0, 0, 1, 4, 34, - 0, 0, 0, 1, 5, 34, 2, 0, 0, 1, 5, 30, 1, 0, 0, 1, 5, 34, - 0, 0, 0, 1, 6, 34, 2, 0, 0, 1, 6, 30, 1, 0, 0, 1, 6, 34, - 0, 0, 0, 1, 7, 34, 2, 0, 0, 1, 7, 30, 1, 0, 0, 1, 7, 34, - 0, 0, 0, 1, 8, 34, 2, 0, 0, 1, 8, 30, 1, 0, 0, 1, 8, 34, - 0, 0, 0, 1, 9, 32, 2, 0, 0, 1, 9, 30, 1, 0, 0, 1, 9, 34, - 0, 0, 0, 1, 10, 30, 2, 0, 0, 1, 10, 30, 1, 0, 0, 1, 10, 34, - 0, 0, 0, 1, 11, 28, 2, 0, 0, 1, 11, 30, 1, 0, 0, 1, 11, 34, - 0, 0, 0, 1, 12, 22, 2, 0, 0, 1, 12, 30, 1, 0, 0, 1, 12, 34, - 0, 0, 0, 1, 13, 14, 2, 0, 0, 1, 13, 30, 1, 0, 0, 1, 13, 34, - 0, 0, 0, 1, 14, 63, 2, 0, 0, 1, 14, 63, 1, 0, 0, 1, 14, 63, - 0, 0, 0, 2, 1, 26, 2, 0, 0, 2, 1, 30, 1, 0, 0, 2, 1, 34, - 0, 0, 0, 2, 2, 30, 2, 0, 0, 2, 2, 30, 1, 0, 0, 2, 2, 34, - 0, 0, 0, 2, 3, 32, 2, 0, 0, 2, 3, 30, 1, 0, 0, 2, 3, 34, - 0, 0, 0, 2, 4, 34, 2, 0, 0, 2, 4, 30, 1, 0, 0, 2, 4, 34, - 0, 0, 0, 2, 5, 34, 2, 0, 0, 2, 5, 30, 1, 0, 0, 2, 5, 34, - 0, 0, 0, 2, 6, 34, 2, 0, 0, 2, 6, 30, 1, 0, 0, 2, 6, 34, - 0, 0, 0, 2, 7, 34, 2, 0, 0, 2, 7, 30, 1, 0, 0, 2, 7, 34, - 0, 0, 0, 2, 8, 34, 2, 0, 0, 2, 8, 30, 1, 0, 0, 2, 8, 34, - 0, 0, 0, 2, 9, 32, 2, 0, 0, 2, 9, 30, 1, 0, 0, 2, 9, 34, - 0, 0, 0, 2, 10, 30, 2, 0, 0, 2, 10, 30, 1, 0, 0, 2, 10, 34, - 0, 0, 0, 2, 11, 26, 2, 0, 0, 2, 11, 30, 1, 0, 0, 2, 11, 34, - 0, 0, 0, 2, 12, 20, 2, 0, 0, 2, 12, 30, 1, 0, 0, 2, 12, 34, - 0, 0, 0, 2, 13, 14, 2, 0, 0, 2, 13, 30, 1, 0, 0, 2, 13, 34, - 0, 0, 0, 2, 14, 63, 2, 0, 0, 2, 14, 63, 1, 0, 0, 2, 14, 63, - 0, 0, 0, 3, 1, 26, 2, 0, 0, 3, 1, 18, 1, 0, 0, 3, 1, 30, - 0, 0, 0, 3, 2, 28, 2, 0, 0, 3, 2, 18, 1, 0, 0, 3, 2, 30, - 0, 0, 0, 3, 3, 30, 2, 0, 0, 3, 3, 18, 1, 0, 0, 3, 3, 30, - 0, 0, 0, 3, 4, 30, 2, 0, 0, 3, 4, 18, 1, 0, 0, 3, 4, 30, - 0, 0, 0, 3, 5, 32, 2, 0, 0, 3, 5, 18, 1, 0, 0, 3, 5, 30, - 0, 0, 0, 3, 6, 32, 2, 0, 0, 3, 6, 18, 1, 0, 0, 3, 6, 30, - 0, 0, 0, 3, 7, 32, 2, 0, 0, 3, 7, 18, 1, 0, 0, 3, 7, 30, - 0, 0, 0, 3, 8, 30, 2, 0, 0, 3, 8, 18, 1, 0, 0, 3, 8, 30, - 0, 0, 0, 3, 9, 30, 2, 0, 0, 3, 9, 18, 1, 0, 0, 3, 9, 30, - 0, 0, 0, 3, 10, 28, 2, 0, 0, 3, 10, 18, 1, 0, 0, 3, 10, 30, - 0, 0, 0, 3, 11, 26, 2, 0, 0, 3, 11, 18, 1, 0, 0, 3, 11, 30, - 0, 0, 0, 3, 12, 20, 2, 0, 0, 3, 12, 18, 1, 0, 0, 3, 12, 30, - 0, 0, 0, 3, 13, 14, 2, 0, 0, 3, 13, 18, 1, 0, 0, 3, 13, 30, - 0, 0, 0, 3, 14, 63, 2, 0, 0, 3, 14, 63, 1, 0, 0, 3, 14, 63, - 0, 0, 1, 2, 1, 63, 2, 0, 1, 2, 1, 63, 1, 0, 1, 2, 1, 63, - 0, 0, 1, 2, 2, 63, 2, 0, 1, 2, 2, 63, 1, 0, 1, 2, 2, 63, - 0, 0, 1, 2, 3, 26, 2, 0, 1, 2, 3, 30, 1, 0, 1, 2, 3, 34, - 0, 0, 1, 2, 4, 26, 2, 0, 1, 2, 4, 30, 1, 0, 1, 2, 4, 34, - 0, 0, 1, 2, 5, 30, 2, 0, 1, 2, 5, 30, 1, 0, 1, 2, 5, 34, - 0, 0, 1, 2, 6, 32, 2, 0, 1, 2, 6, 30, 1, 0, 1, 2, 6, 34, - 0, 0, 1, 2, 7, 30, 2, 0, 1, 2, 7, 30, 1, 0, 1, 2, 7, 34, - 0, 0, 1, 2, 8, 26, 2, 0, 1, 2, 8, 30, 1, 0, 1, 2, 8, 34, - 0, 0, 1, 2, 9, 26, 2, 0, 1, 2, 9, 30, 1, 0, 1, 2, 9, 34, - 0, 0, 1, 2, 10, 20, 2, 0, 1, 2, 10, 30, 1, 0, 1, 2, 10, 34, - 0, 0, 1, 2, 11, 14, 2, 0, 1, 2, 11, 30, 1, 0, 1, 2, 11, 34, - 0, 0, 1, 2, 12, 63, 2, 0, 1, 2, 12, 63, 1, 0, 1, 2, 12, 63, - 0, 0, 1, 2, 13, 63, 2, 0, 1, 2, 13, 63, 1, 0, 1, 2, 13, 63, - 0, 0, 1, 2, 14, 63, 2, 0, 1, 2, 14, 63, 1, 0, 1, 2, 14, 63, - 0, 0, 1, 3, 1, 63, 2, 0, 1, 3, 1, 63, 1, 0, 1, 3, 1, 63, - 0, 0, 1, 3, 2, 63, 2, 0, 1, 3, 2, 63, 1, 0, 1, 3, 2, 63, - 0, 0, 1, 3, 3, 24, 2, 0, 1, 3, 3, 18, 1, 0, 1, 3, 3, 30, - 0, 0, 1, 3, 4, 24, 2, 0, 1, 3, 4, 18, 1, 0, 1, 3, 4, 30, - 0, 0, 1, 3, 5, 26, 2, 0, 1, 3, 5, 18, 1, 0, 1, 3, 5, 30, - 0, 0, 1, 3, 6, 28, 2, 0, 1, 3, 6, 18, 1, 0, 1, 3, 6, 30, - 0, 0, 1, 3, 7, 26, 2, 0, 1, 3, 7, 18, 1, 0, 1, 3, 7, 30, - 0, 0, 1, 3, 8, 26, 2, 0, 1, 3, 8, 18, 1, 0, 1, 3, 8, 30, - 0, 0, 1, 3, 9, 26, 2, 0, 1, 3, 9, 18, 1, 0, 1, 3, 9, 30, - 0, 0, 1, 3, 10, 20, 2, 0, 1, 3, 10, 18, 1, 0, 1, 3, 10, 30, - 0, 0, 1, 3, 11, 14, 2, 0, 1, 3, 11, 18, 1, 0, 1, 3, 11, 30, - 0, 0, 1, 3, 12, 63, 2, 0, 1, 3, 12, 63, 1, 0, 1, 3, 12, 63, - 0, 0, 1, 3, 13, 63, 2, 0, 1, 3, 13, 63, 1, 0, 1, 3, 13, 63, - 0, 0, 1, 3, 14, 63, 2, 0, 1, 3, 14, 63, 1, 0, 1, 3, 14, 63, - 0, 1, 0, 1, 36, 30, 2, 1, 0, 1, 36, 32, 1, 1, 0, 1, 36, 30, - 0, 1, 0, 1, 40, 32, 2, 1, 0, 1, 40, 32, 1, 1, 0, 1, 40, 30, - 0, 1, 0, 1, 44, 32, 2, 1, 0, 1, 44, 32, 1, 1, 0, 1, 44, 30, - 0, 1, 0, 1, 48, 32, 2, 1, 0, 1, 48, 32, 1, 1, 0, 1, 48, 30, - 0, 1, 0, 1, 52, 32, 2, 1, 0, 1, 52, 32, 1, 1, 0, 1, 52, 28, - 0, 1, 0, 1, 56, 32, 2, 1, 0, 1, 56, 32, 1, 1, 0, 1, 56, 28, - 0, 1, 0, 1, 60, 32, 2, 1, 0, 1, 60, 32, 1, 1, 0, 1, 60, 28, - 0, 1, 0, 1, 64, 28, 2, 1, 0, 1, 64, 32, 1, 1, 0, 1, 64, 28, - 0, 1, 0, 1, 100, 26, 2, 1, 0, 1, 100, 32, 1, 1, 0, 1, 100, 32, - 0, 1, 0, 1, 104, 32, 2, 1, 0, 1, 104, 32, 1, 1, 0, 1, 104, 32, - 0, 1, 0, 1, 108, 32, 2, 1, 0, 1, 108, 32, 1, 1, 0, 1, 108, 32, - 0, 1, 0, 1, 112, 32, 2, 1, 0, 1, 112, 32, 1, 1, 0, 1, 112, 32, - 0, 1, 0, 1, 116, 32, 2, 1, 0, 1, 116, 32, 1, 1, 0, 1, 116, 32, - 0, 1, 0, 1, 120, 32, 2, 1, 0, 1, 120, 32, 1, 1, 0, 1, 120, 32, - 0, 1, 0, 1, 124, 32, 2, 1, 0, 1, 124, 32, 1, 1, 0, 1, 124, 32, - 0, 1, 0, 1, 128, 32, 2, 1, 0, 1, 128, 32, 1, 1, 0, 1, 128, 32, - 0, 1, 0, 1, 132, 32, 2, 1, 0, 1, 132, 32, 1, 1, 0, 1, 132, 32, - 0, 1, 0, 1, 136, 32, 2, 1, 0, 1, 136, 32, 1, 1, 0, 1, 136, 32, - 0, 1, 0, 1, 140, 28, 2, 1, 0, 1, 140, 32, 1, 1, 0, 1, 140, 32, - 0, 1, 0, 1, 144, 28, 2, 1, 0, 1, 144, 63, 1, 1, 0, 1, 144, 63, - 0, 1, 0, 1, 149, 32, 2, 1, 0, 1, 149, 63, 1, 1, 0, 1, 149, 63, - 0, 1, 0, 1, 153, 32, 2, 1, 0, 1, 153, 63, 1, 1, 0, 1, 153, 63, - 0, 1, 0, 1, 157, 32, 2, 1, 0, 1, 157, 63, 1, 1, 0, 1, 157, 63, - 0, 1, 0, 1, 161, 32, 2, 1, 0, 1, 161, 63, 1, 1, 0, 1, 161, 63, - 0, 1, 0, 1, 165, 32, 2, 1, 0, 1, 165, 63, 1, 1, 0, 1, 165, 63, - 0, 1, 0, 2, 36, 30, 2, 1, 0, 2, 36, 32, 1, 1, 0, 2, 36, 28, - 0, 1, 0, 2, 40, 32, 2, 1, 0, 2, 40, 32, 1, 1, 0, 2, 40, 28, - 0, 1, 0, 2, 44, 32, 2, 1, 0, 2, 44, 32, 1, 1, 0, 2, 44, 28, - 0, 1, 0, 2, 48, 32, 2, 1, 0, 2, 48, 32, 1, 1, 0, 2, 48, 28, - 0, 1, 0, 2, 52, 32, 2, 1, 0, 2, 52, 32, 1, 1, 0, 2, 52, 28, - 0, 1, 0, 2, 56, 32, 2, 1, 0, 2, 56, 32, 1, 1, 0, 2, 56, 28, - 0, 1, 0, 2, 60, 32, 2, 1, 0, 2, 60, 32, 1, 1, 0, 2, 60, 28, - 0, 1, 0, 2, 64, 28, 2, 1, 0, 2, 64, 32, 1, 1, 0, 2, 64, 28, - 0, 1, 0, 2, 100, 26, 2, 1, 0, 2, 100, 32, 1, 1, 0, 2, 100, 32, - 0, 1, 0, 2, 104, 32, 2, 1, 0, 2, 104, 32, 1, 1, 0, 2, 104, 32, - 0, 1, 0, 2, 108, 32, 2, 1, 0, 2, 108, 32, 1, 1, 0, 2, 108, 32, - 0, 1, 0, 2, 112, 32, 2, 1, 0, 2, 112, 32, 1, 1, 0, 2, 112, 32, - 0, 1, 0, 2, 116, 32, 2, 1, 0, 2, 116, 32, 1, 1, 0, 2, 116, 32, - 0, 1, 0, 2, 120, 32, 2, 1, 0, 2, 120, 32, 1, 1, 0, 2, 120, 32, - 0, 1, 0, 2, 124, 32, 2, 1, 0, 2, 124, 32, 1, 1, 0, 2, 124, 32, - 0, 1, 0, 2, 128, 32, 2, 1, 0, 2, 128, 32, 1, 1, 0, 2, 128, 32, - 0, 1, 0, 2, 132, 32, 2, 1, 0, 2, 132, 32, 1, 1, 0, 2, 132, 32, - 0, 1, 0, 2, 136, 32, 2, 1, 0, 2, 136, 32, 1, 1, 0, 2, 136, 32, - 0, 1, 0, 2, 140, 26, 2, 1, 0, 2, 140, 32, 1, 1, 0, 2, 140, 32, - 0, 1, 0, 2, 144, 26, 2, 1, 0, 2, 144, 63, 1, 1, 0, 2, 144, 63, - 0, 1, 0, 2, 149, 32, 2, 1, 0, 2, 149, 63, 1, 1, 0, 2, 149, 63, - 0, 1, 0, 2, 153, 32, 2, 1, 0, 2, 153, 63, 1, 1, 0, 2, 153, 63, - 0, 1, 0, 2, 157, 32, 2, 1, 0, 2, 157, 63, 1, 1, 0, 2, 157, 63, - 0, 1, 0, 2, 161, 32, 2, 1, 0, 2, 161, 63, 1, 1, 0, 2, 161, 63, - 0, 1, 0, 2, 165, 32, 2, 1, 0, 2, 165, 63, 1, 1, 0, 2, 165, 63, - 0, 1, 0, 3, 36, 28, 2, 1, 0, 3, 36, 20, 1, 1, 0, 3, 36, 22, - 0, 1, 0, 3, 40, 30, 2, 1, 0, 3, 40, 20, 1, 1, 0, 3, 40, 22, - 0, 1, 0, 3, 44, 30, 2, 1, 0, 3, 44, 20, 1, 1, 0, 3, 44, 22, - 0, 1, 0, 3, 48, 30, 2, 1, 0, 3, 48, 20, 1, 1, 0, 3, 48, 22, - 0, 1, 0, 3, 52, 30, 2, 1, 0, 3, 52, 20, 1, 1, 0, 3, 52, 22, - 0, 1, 0, 3, 56, 30, 2, 1, 0, 3, 56, 20, 1, 1, 0, 3, 56, 22, - 0, 1, 0, 3, 60, 30, 2, 1, 0, 3, 60, 20, 1, 1, 0, 3, 60, 22, - 0, 1, 0, 3, 64, 28, 2, 1, 0, 3, 64, 20, 1, 1, 0, 3, 64, 22, - 0, 1, 0, 3, 100, 26, 2, 1, 0, 3, 100, 20, 1, 1, 0, 3, 100, 30, - 0, 1, 0, 3, 104, 30, 2, 1, 0, 3, 104, 20, 1, 1, 0, 3, 104, 30, - 0, 1, 0, 3, 108, 32, 2, 1, 0, 3, 108, 20, 1, 1, 0, 3, 108, 30, - 0, 1, 0, 3, 112, 32, 2, 1, 0, 3, 112, 20, 1, 1, 0, 3, 112, 30, - 0, 1, 0, 3, 116, 32, 2, 1, 0, 3, 116, 20, 1, 1, 0, 3, 116, 30, - 0, 1, 0, 3, 120, 32, 2, 1, 0, 3, 120, 20, 1, 1, 0, 3, 120, 30, - 0, 1, 0, 3, 124, 32, 2, 1, 0, 3, 124, 20, 1, 1, 0, 3, 124, 30, - 0, 1, 0, 3, 128, 32, 2, 1, 0, 3, 128, 20, 1, 1, 0, 3, 128, 30, - 0, 1, 0, 3, 132, 32, 2, 1, 0, 3, 132, 20, 1, 1, 0, 3, 132, 30, - 0, 1, 0, 3, 136, 30, 2, 1, 0, 3, 136, 20, 1, 1, 0, 3, 136, 30, - 0, 1, 0, 3, 140, 26, 2, 1, 0, 3, 140, 20, 1, 1, 0, 3, 140, 30, - 0, 1, 0, 3, 144, 26, 2, 1, 0, 3, 144, 63, 1, 1, 0, 3, 144, 63, - 0, 1, 0, 3, 149, 32, 2, 1, 0, 3, 149, 63, 1, 1, 0, 3, 149, 63, - 0, 1, 0, 3, 153, 32, 2, 1, 0, 3, 153, 63, 1, 1, 0, 3, 153, 63, - 0, 1, 0, 3, 157, 32, 2, 1, 0, 3, 157, 63, 1, 1, 0, 3, 157, 63, - 0, 1, 0, 3, 161, 32, 2, 1, 0, 3, 161, 63, 1, 1, 0, 3, 161, 63, - 0, 1, 0, 3, 165, 32, 2, 1, 0, 3, 165, 63, 1, 1, 0, 3, 165, 63, - 0, 1, 1, 2, 38, 22, 2, 1, 1, 2, 38, 30, 1, 1, 1, 2, 38, 30, - 0, 1, 1, 2, 46, 30, 2, 1, 1, 2, 46, 30, 1, 1, 1, 2, 46, 30, - 0, 1, 1, 2, 54, 30, 2, 1, 1, 2, 54, 30, 1, 1, 1, 2, 54, 30, - 0, 1, 1, 2, 62, 24, 2, 1, 1, 2, 62, 30, 1, 1, 1, 2, 62, 30, - 0, 1, 1, 2, 102, 24, 2, 1, 1, 2, 102, 30, 1, 1, 1, 2, 102, 30, - 0, 1, 1, 2, 110, 30, 2, 1, 1, 2, 110, 30, 1, 1, 1, 2, 110, 30, - 0, 1, 1, 2, 118, 30, 2, 1, 1, 2, 118, 30, 1, 1, 1, 2, 118, 30, - 0, 1, 1, 2, 126, 30, 2, 1, 1, 2, 126, 30, 1, 1, 1, 2, 126, 30, - 0, 1, 1, 2, 134, 30, 2, 1, 1, 2, 134, 30, 1, 1, 1, 2, 134, 30, - 0, 1, 1, 2, 142, 30, 2, 1, 1, 2, 142, 63, 1, 1, 1, 2, 142, 63, - 0, 1, 1, 2, 151, 30, 2, 1, 1, 2, 151, 63, 1, 1, 1, 2, 151, 63, - 0, 1, 1, 2, 159, 30, 2, 1, 1, 2, 159, 63, 1, 1, 1, 2, 159, 63, - 0, 1, 1, 3, 38, 20, 2, 1, 1, 3, 38, 20, 1, 1, 1, 3, 38, 22, - 0, 1, 1, 3, 46, 30, 2, 1, 1, 3, 46, 20, 1, 1, 1, 3, 46, 22, - 0, 1, 1, 3, 54, 30, 2, 1, 1, 3, 54, 20, 1, 1, 1, 3, 54, 22, - 0, 1, 1, 3, 62, 22, 2, 1, 1, 3, 62, 20, 1, 1, 1, 3, 62, 22, - 0, 1, 1, 3, 102, 22, 2, 1, 1, 3, 102, 20, 1, 1, 1, 3, 102, 30, - 0, 1, 1, 3, 110, 30, 2, 1, 1, 3, 110, 20, 1, 1, 1, 3, 110, 30, - 0, 1, 1, 3, 118, 30, 2, 1, 1, 3, 118, 20, 1, 1, 1, 3, 118, 30, - 0, 1, 1, 3, 126, 30, 2, 1, 1, 3, 126, 20, 1, 1, 1, 3, 126, 30, - 0, 1, 1, 3, 134, 30, 2, 1, 1, 3, 134, 20, 1, 1, 1, 3, 134, 30, - 0, 1, 1, 3, 142, 30, 2, 1, 1, 3, 142, 63, 1, 1, 1, 3, 142, 63, - 0, 1, 1, 3, 151, 30, 2, 1, 1, 3, 151, 63, 1, 1, 1, 3, 151, 63, - 0, 1, 1, 3, 159, 30, 2, 1, 1, 3, 159, 63, 1, 1, 1, 3, 159, 63, - 0, 1, 2, 4, 42, 20, 2, 1, 2, 4, 42, 30, 1, 1, 2, 4, 42, 28, - 0, 1, 2, 4, 58, 20, 2, 1, 2, 4, 58, 30, 1, 1, 2, 4, 58, 28, - 0, 1, 2, 4, 106, 20, 2, 1, 2, 4, 106, 30, 1, 1, 2, 4, 106, 30, - 0, 1, 2, 4, 122, 30, 2, 1, 2, 4, 122, 30, 1, 1, 2, 4, 122, 30, - 0, 1, 2, 4, 138, 30, 2, 1, 2, 4, 138, 63, 1, 1, 2, 4, 138, 63, - 0, 1, 2, 4, 155, 30, 2, 1, 2, 4, 155, 63, 1, 1, 2, 4, 155, 63, - 0, 1, 2, 5, 42, 18, 2, 1, 2, 5, 42, 20, 1, 1, 2, 5, 42, 22, - 0, 1, 2, 5, 58, 18, 2, 1, 2, 5, 58, 20, 1, 1, 2, 5, 58, 22, - 0, 1, 2, 5, 106, 20, 2, 1, 2, 5, 106, 20, 1, 1, 2, 5, 106, 30, - 0, 1, 2, 5, 122, 30, 2, 1, 2, 5, 122, 20, 1, 1, 2, 5, 122, 30, - 0, 1, 2, 5, 138, 30, 2, 1, 2, 5, 138, 63, 1, 1, 2, 5, 138, 63, - 0, 1, 2, 5, 155, 30, 2, 1, 2, 5, 155, 63, 1, 1, 2, 5, 155, 63, +static const struct rtw_txpwr_lmt_cfg_pair rtw8822b_txpwr_lmt_type5[] = { + { 0, 0, 0, 0, 1, 32, }, + { 2, 0, 0, 0, 1, 28, }, + { 1, 0, 0, 0, 1, 30, }, + { 0, 0, 0, 0, 2, 32, }, + { 2, 0, 0, 0, 2, 28, }, + { 1, 0, 0, 0, 2, 30, }, + { 0, 0, 0, 0, 3, 32, }, + { 2, 0, 0, 0, 3, 28, }, + { 1, 0, 0, 0, 3, 30, }, + { 0, 0, 0, 0, 4, 32, }, + { 2, 0, 0, 0, 4, 28, }, + { 1, 0, 0, 0, 4, 30, }, + { 0, 0, 0, 0, 5, 32, }, + { 2, 0, 0, 0, 5, 28, }, + { 1, 0, 0, 0, 5, 30, }, + { 0, 0, 0, 0, 6, 32, }, + { 2, 0, 0, 0, 6, 28, }, + { 1, 0, 0, 0, 6, 30, }, + { 0, 0, 0, 0, 7, 32, }, + { 2, 0, 0, 0, 7, 28, }, + { 1, 0, 0, 0, 7, 30, }, + { 0, 0, 0, 0, 8, 32, }, + { 2, 0, 0, 0, 8, 28, }, + { 1, 0, 0, 0, 8, 30, }, + { 0, 0, 0, 0, 9, 32, }, + { 2, 0, 0, 0, 9, 28, }, + { 1, 0, 0, 0, 9, 30, }, + { 0, 0, 0, 0, 10, 32, }, + { 2, 0, 0, 0, 10, 28, }, + { 1, 0, 0, 0, 10, 30, }, + { 0, 0, 0, 0, 11, 32, }, + { 2, 0, 0, 0, 11, 28, }, + { 1, 0, 0, 0, 11, 30, }, + { 0, 0, 0, 0, 12, 26, }, + { 2, 0, 0, 0, 12, 28, }, + { 1, 0, 0, 0, 12, 30, }, + { 0, 0, 0, 0, 13, 20, }, + { 2, 0, 0, 0, 13, 28, }, + { 1, 0, 0, 0, 13, 28, }, + { 0, 0, 0, 0, 14, 63, }, + { 2, 0, 0, 0, 14, 63, }, + { 1, 0, 0, 0, 14, 32, }, + { 0, 0, 0, 1, 1, 26, }, + { 2, 0, 0, 1, 1, 30, }, + { 1, 0, 0, 1, 1, 34, }, + { 0, 0, 0, 1, 2, 30, }, + { 2, 0, 0, 1, 2, 30, }, + { 1, 0, 0, 1, 2, 34, }, + { 0, 0, 0, 1, 3, 32, }, + { 2, 0, 0, 1, 3, 30, }, + { 1, 0, 0, 1, 3, 34, }, + { 0, 0, 0, 1, 4, 34, }, + { 2, 0, 0, 1, 4, 30, }, + { 1, 0, 0, 1, 4, 34, }, + { 0, 0, 0, 1, 5, 34, }, + { 2, 0, 0, 1, 5, 30, }, + { 1, 0, 0, 1, 5, 34, }, + { 0, 0, 0, 1, 6, 34, }, + { 2, 0, 0, 1, 6, 30, }, + { 1, 0, 0, 1, 6, 34, }, + { 0, 0, 0, 1, 7, 34, }, + { 2, 0, 0, 1, 7, 30, }, + { 1, 0, 0, 1, 7, 34, }, + { 0, 0, 0, 1, 8, 34, }, + { 2, 0, 0, 1, 8, 30, }, + { 1, 0, 0, 1, 8, 34, }, + { 0, 0, 0, 1, 9, 32, }, + { 2, 0, 0, 1, 9, 30, }, + { 1, 0, 0, 1, 9, 34, }, + { 0, 0, 0, 1, 10, 30, }, + { 2, 0, 0, 1, 10, 30, }, + { 1, 0, 0, 1, 10, 34, }, + { 0, 0, 0, 1, 11, 28, }, + { 2, 0, 0, 1, 11, 30, }, + { 1, 0, 0, 1, 11, 34, }, + { 0, 0, 0, 1, 12, 22, }, + { 2, 0, 0, 1, 12, 30, }, + { 1, 0, 0, 1, 12, 34, }, + { 0, 0, 0, 1, 13, 14, }, + { 2, 0, 0, 1, 13, 30, }, + { 1, 0, 0, 1, 13, 34, }, + { 0, 0, 0, 1, 14, 63, }, + { 2, 0, 0, 1, 14, 63, }, + { 1, 0, 0, 1, 14, 63, }, + { 0, 0, 0, 2, 1, 26, }, + { 2, 0, 0, 2, 1, 30, }, + { 1, 0, 0, 2, 1, 34, }, + { 0, 0, 0, 2, 2, 30, }, + { 2, 0, 0, 2, 2, 30, }, + { 1, 0, 0, 2, 2, 34, }, + { 0, 0, 0, 2, 3, 32, }, + { 2, 0, 0, 2, 3, 30, }, + { 1, 0, 0, 2, 3, 34, }, + { 0, 0, 0, 2, 4, 34, }, + { 2, 0, 0, 2, 4, 30, }, + { 1, 0, 0, 2, 4, 34, }, + { 0, 0, 0, 2, 5, 34, }, + { 2, 0, 0, 2, 5, 30, }, + { 1, 0, 0, 2, 5, 34, }, + { 0, 0, 0, 2, 6, 34, }, + { 2, 0, 0, 2, 6, 30, }, + { 1, 0, 0, 2, 6, 34, }, + { 0, 0, 0, 2, 7, 34, }, + { 2, 0, 0, 2, 7, 30, }, + { 1, 0, 0, 2, 7, 34, }, + { 0, 0, 0, 2, 8, 34, }, + { 2, 0, 0, 2, 8, 30, }, + { 1, 0, 0, 2, 8, 34, }, + { 0, 0, 0, 2, 9, 32, }, + { 2, 0, 0, 2, 9, 30, }, + { 1, 0, 0, 2, 9, 34, }, + { 0, 0, 0, 2, 10, 30, }, + { 2, 0, 0, 2, 10, 30, }, + { 1, 0, 0, 2, 10, 34, }, + { 0, 0, 0, 2, 11, 26, }, + { 2, 0, 0, 2, 11, 30, }, + { 1, 0, 0, 2, 11, 34, }, + { 0, 0, 0, 2, 12, 20, }, + { 2, 0, 0, 2, 12, 30, }, + { 1, 0, 0, 2, 12, 34, }, + { 0, 0, 0, 2, 13, 14, }, + { 2, 0, 0, 2, 13, 30, }, + { 1, 0, 0, 2, 13, 34, }, + { 0, 0, 0, 2, 14, 63, }, + { 2, 0, 0, 2, 14, 63, }, + { 1, 0, 0, 2, 14, 63, }, + { 0, 0, 0, 3, 1, 26, }, + { 2, 0, 0, 3, 1, 18, }, + { 1, 0, 0, 3, 1, 30, }, + { 0, 0, 0, 3, 2, 28, }, + { 2, 0, 0, 3, 2, 18, }, + { 1, 0, 0, 3, 2, 30, }, + { 0, 0, 0, 3, 3, 30, }, + { 2, 0, 0, 3, 3, 18, }, + { 1, 0, 0, 3, 3, 30, }, + { 0, 0, 0, 3, 4, 30, }, + { 2, 0, 0, 3, 4, 18, }, + { 1, 0, 0, 3, 4, 30, }, + { 0, 0, 0, 3, 5, 32, }, + { 2, 0, 0, 3, 5, 18, }, + { 1, 0, 0, 3, 5, 30, }, + { 0, 0, 0, 3, 6, 32, }, + { 2, 0, 0, 3, 6, 18, }, + { 1, 0, 0, 3, 6, 30, }, + { 0, 0, 0, 3, 7, 32, }, + { 2, 0, 0, 3, 7, 18, }, + { 1, 0, 0, 3, 7, 30, }, + { 0, 0, 0, 3, 8, 30, }, + { 2, 0, 0, 3, 8, 18, }, + { 1, 0, 0, 3, 8, 30, }, + { 0, 0, 0, 3, 9, 30, }, + { 2, 0, 0, 3, 9, 18, }, + { 1, 0, 0, 3, 9, 30, }, + { 0, 0, 0, 3, 10, 28, }, + { 2, 0, 0, 3, 10, 18, }, + { 1, 0, 0, 3, 10, 30, }, + { 0, 0, 0, 3, 11, 26, }, + { 2, 0, 0, 3, 11, 18, }, + { 1, 0, 0, 3, 11, 30, }, + { 0, 0, 0, 3, 12, 20, }, + { 2, 0, 0, 3, 12, 18, }, + { 1, 0, 0, 3, 12, 30, }, + { 0, 0, 0, 3, 13, 14, }, + { 2, 0, 0, 3, 13, 18, }, + { 1, 0, 0, 3, 13, 30, }, + { 0, 0, 0, 3, 14, 63, }, + { 2, 0, 0, 3, 14, 63, }, + { 1, 0, 0, 3, 14, 63, }, + { 0, 0, 1, 2, 1, 63, }, + { 2, 0, 1, 2, 1, 63, }, + { 1, 0, 1, 2, 1, 63, }, + { 0, 0, 1, 2, 2, 63, }, + { 2, 0, 1, 2, 2, 63, }, + { 1, 0, 1, 2, 2, 63, }, + { 0, 0, 1, 2, 3, 26, }, + { 2, 0, 1, 2, 3, 30, }, + { 1, 0, 1, 2, 3, 34, }, + { 0, 0, 1, 2, 4, 26, }, + { 2, 0, 1, 2, 4, 30, }, + { 1, 0, 1, 2, 4, 34, }, + { 0, 0, 1, 2, 5, 30, }, + { 2, 0, 1, 2, 5, 30, }, + { 1, 0, 1, 2, 5, 34, }, + { 0, 0, 1, 2, 6, 32, }, + { 2, 0, 1, 2, 6, 30, }, + { 1, 0, 1, 2, 6, 34, }, + { 0, 0, 1, 2, 7, 30, }, + { 2, 0, 1, 2, 7, 30, }, + { 1, 0, 1, 2, 7, 34, }, + { 0, 0, 1, 2, 8, 26, }, + { 2, 0, 1, 2, 8, 30, }, + { 1, 0, 1, 2, 8, 34, }, + { 0, 0, 1, 2, 9, 26, }, + { 2, 0, 1, 2, 9, 30, }, + { 1, 0, 1, 2, 9, 34, }, + { 0, 0, 1, 2, 10, 20, }, + { 2, 0, 1, 2, 10, 30, }, + { 1, 0, 1, 2, 10, 34, }, + { 0, 0, 1, 2, 11, 14, }, + { 2, 0, 1, 2, 11, 30, }, + { 1, 0, 1, 2, 11, 34, }, + { 0, 0, 1, 2, 12, 63, }, + { 2, 0, 1, 2, 12, 63, }, + { 1, 0, 1, 2, 12, 63, }, + { 0, 0, 1, 2, 13, 63, }, + { 2, 0, 1, 2, 13, 63, }, + { 1, 0, 1, 2, 13, 63, }, + { 0, 0, 1, 2, 14, 63, }, + { 2, 0, 1, 2, 14, 63, }, + { 1, 0, 1, 2, 14, 63, }, + { 0, 0, 1, 3, 1, 63, }, + { 2, 0, 1, 3, 1, 63, }, + { 1, 0, 1, 3, 1, 63, }, + { 0, 0, 1, 3, 2, 63, }, + { 2, 0, 1, 3, 2, 63, }, + { 1, 0, 1, 3, 2, 63, }, + { 0, 0, 1, 3, 3, 24, }, + { 2, 0, 1, 3, 3, 18, }, + { 1, 0, 1, 3, 3, 30, }, + { 0, 0, 1, 3, 4, 24, }, + { 2, 0, 1, 3, 4, 18, }, + { 1, 0, 1, 3, 4, 30, }, + { 0, 0, 1, 3, 5, 26, }, + { 2, 0, 1, 3, 5, 18, }, + { 1, 0, 1, 3, 5, 30, }, + { 0, 0, 1, 3, 6, 28, }, + { 2, 0, 1, 3, 6, 18, }, + { 1, 0, 1, 3, 6, 30, }, + { 0, 0, 1, 3, 7, 26, }, + { 2, 0, 1, 3, 7, 18, }, + { 1, 0, 1, 3, 7, 30, }, + { 0, 0, 1, 3, 8, 26, }, + { 2, 0, 1, 3, 8, 18, }, + { 1, 0, 1, 3, 8, 30, }, + { 0, 0, 1, 3, 9, 26, }, + { 2, 0, 1, 3, 9, 18, }, + { 1, 0, 1, 3, 9, 30, }, + { 0, 0, 1, 3, 10, 20, }, + { 2, 0, 1, 3, 10, 18, }, + { 1, 0, 1, 3, 10, 30, }, + { 0, 0, 1, 3, 11, 14, }, + { 2, 0, 1, 3, 11, 18, }, + { 1, 0, 1, 3, 11, 30, }, + { 0, 0, 1, 3, 12, 63, }, + { 2, 0, 1, 3, 12, 63, }, + { 1, 0, 1, 3, 12, 63, }, + { 0, 0, 1, 3, 13, 63, }, + { 2, 0, 1, 3, 13, 63, }, + { 1, 0, 1, 3, 13, 63, }, + { 0, 0, 1, 3, 14, 63, }, + { 2, 0, 1, 3, 14, 63, }, + { 1, 0, 1, 3, 14, 63, }, + { 0, 1, 0, 1, 36, 30, }, + { 2, 1, 0, 1, 36, 32, }, + { 1, 1, 0, 1, 36, 30, }, + { 0, 1, 0, 1, 40, 32, }, + { 2, 1, 0, 1, 40, 32, }, + { 1, 1, 0, 1, 40, 30, }, + { 0, 1, 0, 1, 44, 32, }, + { 2, 1, 0, 1, 44, 32, }, + { 1, 1, 0, 1, 44, 30, }, + { 0, 1, 0, 1, 48, 32, }, + { 2, 1, 0, 1, 48, 32, }, + { 1, 1, 0, 1, 48, 30, }, + { 0, 1, 0, 1, 52, 32, }, + { 2, 1, 0, 1, 52, 32, }, + { 1, 1, 0, 1, 52, 28, }, + { 0, 1, 0, 1, 56, 32, }, + { 2, 1, 0, 1, 56, 32, }, + { 1, 1, 0, 1, 56, 28, }, + { 0, 1, 0, 1, 60, 32, }, + { 2, 1, 0, 1, 60, 32, }, + { 1, 1, 0, 1, 60, 28, }, + { 0, 1, 0, 1, 64, 28, }, + { 2, 1, 0, 1, 64, 32, }, + { 1, 1, 0, 1, 64, 28, }, + { 0, 1, 0, 1, 100, 26, }, + { 2, 1, 0, 1, 100, 32, }, + { 1, 1, 0, 1, 100, 32, }, + { 0, 1, 0, 1, 104, 32, }, + { 2, 1, 0, 1, 104, 32, }, + { 1, 1, 0, 1, 104, 32, }, + { 0, 1, 0, 1, 108, 32, }, + { 2, 1, 0, 1, 108, 32, }, + { 1, 1, 0, 1, 108, 32, }, + { 0, 1, 0, 1, 112, 32, }, + { 2, 1, 0, 1, 112, 32, }, + { 1, 1, 0, 1, 112, 32, }, + { 0, 1, 0, 1, 116, 32, }, + { 2, 1, 0, 1, 116, 32, }, + { 1, 1, 0, 1, 116, 32, }, + { 0, 1, 0, 1, 120, 32, }, + { 2, 1, 0, 1, 120, 32, }, + { 1, 1, 0, 1, 120, 32, }, + { 0, 1, 0, 1, 124, 32, }, + { 2, 1, 0, 1, 124, 32, }, + { 1, 1, 0, 1, 124, 32, }, + { 0, 1, 0, 1, 128, 32, }, + { 2, 1, 0, 1, 128, 32, }, + { 1, 1, 0, 1, 128, 32, }, + { 0, 1, 0, 1, 132, 32, }, + { 2, 1, 0, 1, 132, 32, }, + { 1, 1, 0, 1, 132, 32, }, + { 0, 1, 0, 1, 136, 32, }, + { 2, 1, 0, 1, 136, 32, }, + { 1, 1, 0, 1, 136, 32, }, + { 0, 1, 0, 1, 140, 28, }, + { 2, 1, 0, 1, 140, 32, }, + { 1, 1, 0, 1, 140, 32, }, + { 0, 1, 0, 1, 144, 28, }, + { 2, 1, 0, 1, 144, 63, }, + { 1, 1, 0, 1, 144, 63, }, + { 0, 1, 0, 1, 149, 32, }, + { 2, 1, 0, 1, 149, 63, }, + { 1, 1, 0, 1, 149, 63, }, + { 0, 1, 0, 1, 153, 32, }, + { 2, 1, 0, 1, 153, 63, }, + { 1, 1, 0, 1, 153, 63, }, + { 0, 1, 0, 1, 157, 32, }, + { 2, 1, 0, 1, 157, 63, }, + { 1, 1, 0, 1, 157, 63, }, + { 0, 1, 0, 1, 161, 32, }, + { 2, 1, 0, 1, 161, 63, }, + { 1, 1, 0, 1, 161, 63, }, + { 0, 1, 0, 1, 165, 32, }, + { 2, 1, 0, 1, 165, 63, }, + { 1, 1, 0, 1, 165, 63, }, + { 0, 1, 0, 2, 36, 30, }, + { 2, 1, 0, 2, 36, 32, }, + { 1, 1, 0, 2, 36, 28, }, + { 0, 1, 0, 2, 40, 32, }, + { 2, 1, 0, 2, 40, 32, }, + { 1, 1, 0, 2, 40, 28, }, + { 0, 1, 0, 2, 44, 32, }, + { 2, 1, 0, 2, 44, 32, }, + { 1, 1, 0, 2, 44, 28, }, + { 0, 1, 0, 2, 48, 32, }, + { 2, 1, 0, 2, 48, 32, }, + { 1, 1, 0, 2, 48, 28, }, + { 0, 1, 0, 2, 52, 32, }, + { 2, 1, 0, 2, 52, 32, }, + { 1, 1, 0, 2, 52, 28, }, + { 0, 1, 0, 2, 56, 32, }, + { 2, 1, 0, 2, 56, 32, }, + { 1, 1, 0, 2, 56, 28, }, + { 0, 1, 0, 2, 60, 32, }, + { 2, 1, 0, 2, 60, 32, }, + { 1, 1, 0, 2, 60, 28, }, + { 0, 1, 0, 2, 64, 28, }, + { 2, 1, 0, 2, 64, 32, }, + { 1, 1, 0, 2, 64, 28, }, + { 0, 1, 0, 2, 100, 26, }, + { 2, 1, 0, 2, 100, 32, }, + { 1, 1, 0, 2, 100, 32, }, + { 0, 1, 0, 2, 104, 32, }, + { 2, 1, 0, 2, 104, 32, }, + { 1, 1, 0, 2, 104, 32, }, + { 0, 1, 0, 2, 108, 32, }, + { 2, 1, 0, 2, 108, 32, }, + { 1, 1, 0, 2, 108, 32, }, + { 0, 1, 0, 2, 112, 32, }, + { 2, 1, 0, 2, 112, 32, }, + { 1, 1, 0, 2, 112, 32, }, + { 0, 1, 0, 2, 116, 32, }, + { 2, 1, 0, 2, 116, 32, }, + { 1, 1, 0, 2, 116, 32, }, + { 0, 1, 0, 2, 120, 32, }, + { 2, 1, 0, 2, 120, 32, }, + { 1, 1, 0, 2, 120, 32, }, + { 0, 1, 0, 2, 124, 32, }, + { 2, 1, 0, 2, 124, 32, }, + { 1, 1, 0, 2, 124, 32, }, + { 0, 1, 0, 2, 128, 32, }, + { 2, 1, 0, 2, 128, 32, }, + { 1, 1, 0, 2, 128, 32, }, + { 0, 1, 0, 2, 132, 32, }, + { 2, 1, 0, 2, 132, 32, }, + { 1, 1, 0, 2, 132, 32, }, + { 0, 1, 0, 2, 136, 32, }, + { 2, 1, 0, 2, 136, 32, }, + { 1, 1, 0, 2, 136, 32, }, + { 0, 1, 0, 2, 140, 26, }, + { 2, 1, 0, 2, 140, 32, }, + { 1, 1, 0, 2, 140, 32, }, + { 0, 1, 0, 2, 144, 26, }, + { 2, 1, 0, 2, 144, 63, }, + { 1, 1, 0, 2, 144, 63, }, + { 0, 1, 0, 2, 149, 32, }, + { 2, 1, 0, 2, 149, 63, }, + { 1, 1, 0, 2, 149, 63, }, + { 0, 1, 0, 2, 153, 32, }, + { 2, 1, 0, 2, 153, 63, }, + { 1, 1, 0, 2, 153, 63, }, + { 0, 1, 0, 2, 157, 32, }, + { 2, 1, 0, 2, 157, 63, }, + { 1, 1, 0, 2, 157, 63, }, + { 0, 1, 0, 2, 161, 32, }, + { 2, 1, 0, 2, 161, 63, }, + { 1, 1, 0, 2, 161, 63, }, + { 0, 1, 0, 2, 165, 32, }, + { 2, 1, 0, 2, 165, 63, }, + { 1, 1, 0, 2, 165, 63, }, + { 0, 1, 0, 3, 36, 28, }, + { 2, 1, 0, 3, 36, 20, }, + { 1, 1, 0, 3, 36, 22, }, + { 0, 1, 0, 3, 40, 30, }, + { 2, 1, 0, 3, 40, 20, }, + { 1, 1, 0, 3, 40, 22, }, + { 0, 1, 0, 3, 44, 30, }, + { 2, 1, 0, 3, 44, 20, }, + { 1, 1, 0, 3, 44, 22, }, + { 0, 1, 0, 3, 48, 30, }, + { 2, 1, 0, 3, 48, 20, }, + { 1, 1, 0, 3, 48, 22, }, + { 0, 1, 0, 3, 52, 30, }, + { 2, 1, 0, 3, 52, 20, }, + { 1, 1, 0, 3, 52, 22, }, + { 0, 1, 0, 3, 56, 30, }, + { 2, 1, 0, 3, 56, 20, }, + { 1, 1, 0, 3, 56, 22, }, + { 0, 1, 0, 3, 60, 30, }, + { 2, 1, 0, 3, 60, 20, }, + { 1, 1, 0, 3, 60, 22, }, + { 0, 1, 0, 3, 64, 28, }, + { 2, 1, 0, 3, 64, 20, }, + { 1, 1, 0, 3, 64, 22, }, + { 0, 1, 0, 3, 100, 26, }, + { 2, 1, 0, 3, 100, 20, }, + { 1, 1, 0, 3, 100, 30, }, + { 0, 1, 0, 3, 104, 30, }, + { 2, 1, 0, 3, 104, 20, }, + { 1, 1, 0, 3, 104, 30, }, + { 0, 1, 0, 3, 108, 32, }, + { 2, 1, 0, 3, 108, 20, }, + { 1, 1, 0, 3, 108, 30, }, + { 0, 1, 0, 3, 112, 32, }, + { 2, 1, 0, 3, 112, 20, }, + { 1, 1, 0, 3, 112, 30, }, + { 0, 1, 0, 3, 116, 32, }, + { 2, 1, 0, 3, 116, 20, }, + { 1, 1, 0, 3, 116, 30, }, + { 0, 1, 0, 3, 120, 32, }, + { 2, 1, 0, 3, 120, 20, }, + { 1, 1, 0, 3, 120, 30, }, + { 0, 1, 0, 3, 124, 32, }, + { 2, 1, 0, 3, 124, 20, }, + { 1, 1, 0, 3, 124, 30, }, + { 0, 1, 0, 3, 128, 32, }, + { 2, 1, 0, 3, 128, 20, }, + { 1, 1, 0, 3, 128, 30, }, + { 0, 1, 0, 3, 132, 32, }, + { 2, 1, 0, 3, 132, 20, }, + { 1, 1, 0, 3, 132, 30, }, + { 0, 1, 0, 3, 136, 30, }, + { 2, 1, 0, 3, 136, 20, }, + { 1, 1, 0, 3, 136, 30, }, + { 0, 1, 0, 3, 140, 26, }, + { 2, 1, 0, 3, 140, 20, }, + { 1, 1, 0, 3, 140, 30, }, + { 0, 1, 0, 3, 144, 26, }, + { 2, 1, 0, 3, 144, 63, }, + { 1, 1, 0, 3, 144, 63, }, + { 0, 1, 0, 3, 149, 32, }, + { 2, 1, 0, 3, 149, 63, }, + { 1, 1, 0, 3, 149, 63, }, + { 0, 1, 0, 3, 153, 32, }, + { 2, 1, 0, 3, 153, 63, }, + { 1, 1, 0, 3, 153, 63, }, + { 0, 1, 0, 3, 157, 32, }, + { 2, 1, 0, 3, 157, 63, }, + { 1, 1, 0, 3, 157, 63, }, + { 0, 1, 0, 3, 161, 32, }, + { 2, 1, 0, 3, 161, 63, }, + { 1, 1, 0, 3, 161, 63, }, + { 0, 1, 0, 3, 165, 32, }, + { 2, 1, 0, 3, 165, 63, }, + { 1, 1, 0, 3, 165, 63, }, + { 0, 1, 1, 2, 38, 22, }, + { 2, 1, 1, 2, 38, 30, }, + { 1, 1, 1, 2, 38, 30, }, + { 0, 1, 1, 2, 46, 30, }, + { 2, 1, 1, 2, 46, 30, }, + { 1, 1, 1, 2, 46, 30, }, + { 0, 1, 1, 2, 54, 30, }, + { 2, 1, 1, 2, 54, 30, }, + { 1, 1, 1, 2, 54, 30, }, + { 0, 1, 1, 2, 62, 24, }, + { 2, 1, 1, 2, 62, 30, }, + { 1, 1, 1, 2, 62, 30, }, + { 0, 1, 1, 2, 102, 24, }, + { 2, 1, 1, 2, 102, 30, }, + { 1, 1, 1, 2, 102, 30, }, + { 0, 1, 1, 2, 110, 30, }, + { 2, 1, 1, 2, 110, 30, }, + { 1, 1, 1, 2, 110, 30, }, + { 0, 1, 1, 2, 118, 30, }, + { 2, 1, 1, 2, 118, 30, }, + { 1, 1, 1, 2, 118, 30, }, + { 0, 1, 1, 2, 126, 30, }, + { 2, 1, 1, 2, 126, 30, }, + { 1, 1, 1, 2, 126, 30, }, + { 0, 1, 1, 2, 134, 30, }, + { 2, 1, 1, 2, 134, 30, }, + { 1, 1, 1, 2, 134, 30, }, + { 0, 1, 1, 2, 142, 30, }, + { 2, 1, 1, 2, 142, 63, }, + { 1, 1, 1, 2, 142, 63, }, + { 0, 1, 1, 2, 151, 30, }, + { 2, 1, 1, 2, 151, 63, }, + { 1, 1, 1, 2, 151, 63, }, + { 0, 1, 1, 2, 159, 30, }, + { 2, 1, 1, 2, 159, 63, }, + { 1, 1, 1, 2, 159, 63, }, + { 0, 1, 1, 3, 38, 20, }, + { 2, 1, 1, 3, 38, 20, }, + { 1, 1, 1, 3, 38, 22, }, + { 0, 1, 1, 3, 46, 30, }, + { 2, 1, 1, 3, 46, 20, }, + { 1, 1, 1, 3, 46, 22, }, + { 0, 1, 1, 3, 54, 30, }, + { 2, 1, 1, 3, 54, 20, }, + { 1, 1, 1, 3, 54, 22, }, + { 0, 1, 1, 3, 62, 22, }, + { 2, 1, 1, 3, 62, 20, }, + { 1, 1, 1, 3, 62, 22, }, + { 0, 1, 1, 3, 102, 22, }, + { 2, 1, 1, 3, 102, 20, }, + { 1, 1, 1, 3, 102, 30, }, + { 0, 1, 1, 3, 110, 30, }, + { 2, 1, 1, 3, 110, 20, }, + { 1, 1, 1, 3, 110, 30, }, + { 0, 1, 1, 3, 118, 30, }, + { 2, 1, 1, 3, 118, 20, }, + { 1, 1, 1, 3, 118, 30, }, + { 0, 1, 1, 3, 126, 30, }, + { 2, 1, 1, 3, 126, 20, }, + { 1, 1, 1, 3, 126, 30, }, + { 0, 1, 1, 3, 134, 30, }, + { 2, 1, 1, 3, 134, 20, }, + { 1, 1, 1, 3, 134, 30, }, + { 0, 1, 1, 3, 142, 30, }, + { 2, 1, 1, 3, 142, 63, }, + { 1, 1, 1, 3, 142, 63, }, + { 0, 1, 1, 3, 151, 30, }, + { 2, 1, 1, 3, 151, 63, }, + { 1, 1, 1, 3, 151, 63, }, + { 0, 1, 1, 3, 159, 30, }, + { 2, 1, 1, 3, 159, 63, }, + { 1, 1, 1, 3, 159, 63, }, + { 0, 1, 2, 4, 42, 20, }, + { 2, 1, 2, 4, 42, 30, }, + { 1, 1, 2, 4, 42, 28, }, + { 0, 1, 2, 4, 58, 20, }, + { 2, 1, 2, 4, 58, 30, }, + { 1, 1, 2, 4, 58, 28, }, + { 0, 1, 2, 4, 106, 20, }, + { 2, 1, 2, 4, 106, 30, }, + { 1, 1, 2, 4, 106, 30, }, + { 0, 1, 2, 4, 122, 30, }, + { 2, 1, 2, 4, 122, 30, }, + { 1, 1, 2, 4, 122, 30, }, + { 0, 1, 2, 4, 138, 30, }, + { 2, 1, 2, 4, 138, 63, }, + { 1, 1, 2, 4, 138, 63, }, + { 0, 1, 2, 4, 155, 30, }, + { 2, 1, 2, 4, 155, 63, }, + { 1, 1, 2, 4, 155, 63, }, + { 0, 1, 2, 5, 42, 18, }, + { 2, 1, 2, 5, 42, 20, }, + { 1, 1, 2, 5, 42, 22, }, + { 0, 1, 2, 5, 58, 18, }, + { 2, 1, 2, 5, 58, 20, }, + { 1, 1, 2, 5, 58, 22, }, + { 0, 1, 2, 5, 106, 20, }, + { 2, 1, 2, 5, 106, 20, }, + { 1, 1, 2, 5, 106, 30, }, + { 0, 1, 2, 5, 122, 30, }, + { 2, 1, 2, 5, 122, 20, }, + { 1, 1, 2, 5, 122, 30, }, + { 0, 1, 2, 5, 138, 30, }, + { 2, 1, 2, 5, 138, 63, }, + { 1, 1, 2, 5, 138, 63, }, + { 0, 1, 2, 5, 155, 30, }, + { 2, 1, 2, 5, 155, 63, }, + { 1, 1, 2, 5, 155, 63, }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8822b_txpwr_lmt_type5); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c index 18e609a69829..6c7eaa75b98b 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c @@ -9403,885 +9403,1762 @@ static const u32 rtw8822c_rf_b[] = { RTW_DECL_TABLE_RF_RADIO(rtw8822c_rf_b, B); -static const u8 rtw8822c_txpwr_lmt_type0[] = { - 0, 0, 0, 0, 1, 72, 2, 0, 0, 0, 1, 60, - 0, 0, 0, 0, 2, 72, 2, 0, 0, 0, 2, 60, - 0, 0, 0, 0, 3, 76, 2, 0, 0, 0, 3, 60, - 0, 0, 0, 0, 4, 76, 2, 0, 0, 0, 4, 60, - 0, 0, 0, 0, 5, 76, 2, 0, 0, 0, 5, 60, - 0, 0, 0, 0, 6, 76, 2, 0, 0, 0, 6, 60, - 0, 0, 0, 0, 7, 76, 2, 0, 0, 0, 7, 60, - 0, 0, 0, 0, 8, 76, 2, 0, 0, 0, 8, 60, - 0, 0, 0, 0, 9, 76, 2, 0, 0, 0, 9, 60, - 0, 0, 0, 0, 10, 72, 2, 0, 0, 0, 10, 60, - 0, 0, 0, 0, 11, 72, 2, 0, 0, 0, 11, 60, - 0, 0, 0, 0, 12, 52, 2, 0, 0, 0, 12, 60, - 0, 0, 0, 0, 13, 48, 2, 0, 0, 0, 13, 60, - 0, 0, 0, 0, 14, 127, 2, 0, 0, 0, 14, 127, - 0, 0, 0, 1, 1, 52, 2, 0, 0, 1, 1, 60, - 0, 0, 0, 1, 2, 60, 2, 0, 0, 1, 2, 60, - 0, 0, 0, 1, 3, 64, 2, 0, 0, 1, 3, 60, - 0, 0, 0, 1, 4, 68, 2, 0, 0, 1, 4, 60, - 0, 0, 0, 1, 5, 76, 2, 0, 0, 1, 5, 60, - 0, 0, 0, 1, 6, 76, 2, 0, 0, 1, 6, 60, - 0, 0, 0, 1, 7, 76, 2, 0, 0, 1, 7, 60, - 0, 0, 0, 1, 8, 68, 2, 0, 0, 1, 8, 60, - 0, 0, 0, 1, 9, 64, 2, 0, 0, 1, 9, 60, - 0, 0, 0, 1, 10, 60, 2, 0, 0, 1, 10, 60, - 0, 0, 0, 1, 11, 52, 2, 0, 0, 1, 11, 60, - 0, 0, 0, 1, 12, 40, 2, 0, 0, 1, 12, 60, - 0, 0, 0, 1, 13, 28, 2, 0, 0, 1, 13, 60, - 0, 0, 0, 1, 14, 127, 2, 0, 0, 1, 14, 127, - 0, 0, 0, 2, 1, 52, 2, 0, 0, 2, 1, 60, - 0, 0, 0, 2, 2, 60, 2, 0, 0, 2, 2, 60, - 0, 0, 0, 2, 3, 64, 2, 0, 0, 2, 3, 60, - 0, 0, 0, 2, 4, 68, 2, 0, 0, 2, 4, 60, - 0, 0, 0, 2, 5, 76, 2, 0, 0, 2, 5, 60, - 0, 0, 0, 2, 6, 76, 2, 0, 0, 2, 6, 60, - 0, 0, 0, 2, 7, 76, 2, 0, 0, 2, 7, 60, - 0, 0, 0, 2, 8, 68, 2, 0, 0, 2, 8, 60, - 0, 0, 0, 2, 9, 64, 2, 0, 0, 2, 9, 60, - 0, 0, 0, 2, 10, 60, 2, 0, 0, 2, 10, 60, - 0, 0, 0, 2, 11, 52, 2, 0, 0, 2, 11, 60, - 0, 0, 0, 2, 12, 40, 2, 0, 0, 2, 12, 60, - 0, 0, 0, 2, 13, 28, 2, 0, 0, 2, 13, 60, - 0, 0, 0, 2, 14, 127, 2, 0, 0, 2, 14, 127, - 0, 0, 0, 3, 1, 52, 2, 0, 0, 3, 1, 36, - 0, 0, 0, 3, 2, 60, 2, 0, 0, 3, 2, 36, - 0, 0, 0, 3, 3, 64, 2, 0, 0, 3, 3, 36, - 0, 0, 0, 3, 4, 68, 2, 0, 0, 3, 4, 36, - 0, 0, 0, 3, 5, 76, 2, 0, 0, 3, 5, 36, - 0, 0, 0, 3, 6, 76, 2, 0, 0, 3, 6, 36, - 0, 0, 0, 3, 7, 76, 2, 0, 0, 3, 7, 36, - 0, 0, 0, 3, 8, 68, 2, 0, 0, 3, 8, 36, - 0, 0, 0, 3, 9, 64, 2, 0, 0, 3, 9, 36, - 0, 0, 0, 3, 10, 60, 2, 0, 0, 3, 10, 36, - 0, 0, 0, 3, 11, 52, 2, 0, 0, 3, 11, 36, - 0, 0, 0, 3, 12, 40, 2, 0, 0, 3, 12, 36, - 0, 0, 0, 3, 13, 28, 2, 0, 0, 3, 13, 36, - 0, 0, 0, 3, 14, 127, 2, 0, 0, 3, 14, 127, - 0, 0, 1, 2, 1, 127, 2, 0, 1, 2, 1, 127, - 0, 0, 1, 2, 2, 127, 2, 0, 1, 2, 2, 127, - 0, 0, 1, 2, 3, 52, 2, 0, 1, 2, 3, 60, - 0, 0, 1, 2, 4, 52, 2, 0, 1, 2, 4, 60, - 0, 0, 1, 2, 5, 60, 2, 0, 1, 2, 5, 60, - 0, 0, 1, 2, 6, 64, 2, 0, 1, 2, 6, 60, - 0, 0, 1, 2, 7, 60, 2, 0, 1, 2, 7, 60, - 0, 0, 1, 2, 8, 52, 2, 0, 1, 2, 8, 60, - 0, 0, 1, 2, 9, 52, 2, 0, 1, 2, 9, 60, - 0, 0, 1, 2, 10, 40, 2, 0, 1, 2, 10, 60, - 0, 0, 1, 2, 11, 28, 2, 0, 1, 2, 11, 60, - 0, 0, 1, 2, 12, 127, 2, 0, 1, 2, 12, 127, - 0, 0, 1, 2, 13, 127, 2, 0, 1, 2, 13, 127, - 0, 0, 1, 2, 14, 127, 2, 0, 1, 2, 14, 127, - 0, 0, 1, 3, 1, 127, 2, 0, 1, 3, 1, 127, - 0, 0, 1, 3, 2, 127, 2, 0, 1, 3, 2, 127, - 0, 0, 1, 3, 3, 48, 2, 0, 1, 3, 3, 36, - 0, 0, 1, 3, 4, 48, 2, 0, 1, 3, 4, 36, - 0, 0, 1, 3, 5, 60, 2, 0, 1, 3, 5, 36, - 0, 0, 1, 3, 6, 64, 2, 0, 1, 3, 6, 36, - 0, 0, 1, 3, 7, 60, 2, 0, 1, 3, 7, 36, - 0, 0, 1, 3, 8, 52, 2, 0, 1, 3, 8, 36, - 0, 0, 1, 3, 9, 52, 2, 0, 1, 3, 9, 36, - 0, 0, 1, 3, 10, 40, 2, 0, 1, 3, 10, 36, - 0, 0, 1, 3, 11, 26, 2, 0, 1, 3, 11, 36, - 0, 0, 1, 3, 12, 127, 2, 0, 1, 3, 12, 127, - 0, 0, 1, 3, 13, 127, 2, 0, 1, 3, 13, 127, - 0, 0, 1, 3, 14, 127, 2, 0, 1, 3, 14, 127, - 0, 1, 0, 1, 36, 74, 2, 1, 0, 1, 36, 62, - 0, 1, 0, 1, 40, 76, 2, 1, 0, 1, 40, 62, - 0, 1, 0, 1, 44, 76, 2, 1, 0, 1, 44, 62, - 0, 1, 0, 1, 48, 76, 2, 1, 0, 1, 48, 62, - 0, 1, 0, 1, 52, 76, 2, 1, 0, 1, 52, 62, - 0, 1, 0, 1, 56, 76, 2, 1, 0, 1, 56, 62, - 0, 1, 0, 1, 60, 76, 2, 1, 0, 1, 60, 62, - 0, 1, 0, 1, 64, 74, 2, 1, 0, 1, 64, 62, - 0, 1, 0, 1, 100, 72, 2, 1, 0, 1, 100, 62, - 0, 1, 0, 1, 104, 76, 2, 1, 0, 1, 104, 62, - 0, 1, 0, 1, 108, 76, 2, 1, 0, 1, 108, 62, - 0, 1, 0, 1, 112, 76, 2, 1, 0, 1, 112, 62, - 0, 1, 0, 1, 116, 76, 2, 1, 0, 1, 116, 62, - 0, 1, 0, 1, 120, 76, 2, 1, 0, 1, 120, 62, - 0, 1, 0, 1, 124, 76, 2, 1, 0, 1, 124, 62, - 0, 1, 0, 1, 128, 76, 2, 1, 0, 1, 128, 62, - 0, 1, 0, 1, 132, 76, 2, 1, 0, 1, 132, 62, - 0, 1, 0, 1, 136, 76, 2, 1, 0, 1, 136, 62, - 0, 1, 0, 1, 140, 72, 2, 1, 0, 1, 140, 62, - 0, 1, 0, 1, 144, 76, 2, 1, 0, 1, 144, 127, - 0, 1, 0, 1, 149, 76, 2, 1, 0, 1, 149, -128, - 0, 1, 0, 1, 153, 76, 2, 1, 0, 1, 153, -128, - 0, 1, 0, 1, 157, 76, 2, 1, 0, 1, 157, -128, - 0, 1, 0, 1, 161, 76, 2, 1, 0, 1, 161, -128, - 0, 1, 0, 1, 165, 76, 2, 1, 0, 1, 165, -128, - 0, 1, 0, 2, 36, 72, 2, 1, 0, 2, 36, 62, - 0, 1, 0, 2, 40, 76, 2, 1, 0, 2, 40, 62, - 0, 1, 0, 2, 44, 76, 2, 1, 0, 2, 44, 62, - 0, 1, 0, 2, 48, 76, 2, 1, 0, 2, 48, 62, - 0, 1, 0, 2, 52, 76, 2, 1, 0, 2, 52, 62, - 0, 1, 0, 2, 56, 76, 2, 1, 0, 2, 56, 62, - 0, 1, 0, 2, 60, 76, 2, 1, 0, 2, 60, 62, - 0, 1, 0, 2, 64, 74, 2, 1, 0, 2, 64, 62, - 0, 1, 0, 2, 100, 70, 2, 1, 0, 2, 100, 62, - 0, 1, 0, 2, 104, 76, 2, 1, 0, 2, 104, 62, - 0, 1, 0, 2, 108, 76, 2, 1, 0, 2, 108, 62, - 0, 1, 0, 2, 112, 76, 2, 1, 0, 2, 112, 62, - 0, 1, 0, 2, 116, 76, 2, 1, 0, 2, 116, 62, - 0, 1, 0, 2, 120, 76, 2, 1, 0, 2, 120, 62, - 0, 1, 0, 2, 124, 76, 2, 1, 0, 2, 124, 62, - 0, 1, 0, 2, 128, 76, 2, 1, 0, 2, 128, 62, - 0, 1, 0, 2, 132, 76, 2, 1, 0, 2, 132, 62, - 0, 1, 0, 2, 136, 76, 2, 1, 0, 2, 136, 62, - 0, 1, 0, 2, 140, 70, 2, 1, 0, 2, 140, 62, - 0, 1, 0, 2, 144, 76, 2, 1, 0, 2, 144, 127, - 0, 1, 0, 2, 149, 76, 2, 1, 0, 2, 149, -128, - 0, 1, 0, 2, 153, 76, 2, 1, 0, 2, 153, -128, - 0, 1, 0, 2, 157, 76, 2, 1, 0, 2, 157, -128, - 0, 1, 0, 2, 161, 76, 2, 1, 0, 2, 161, -128, - 0, 1, 0, 2, 165, 76, 2, 1, 0, 2, 165, -128, - 0, 1, 0, 3, 36, 68, 2, 1, 0, 3, 36, 38, - 0, 1, 0, 3, 40, 68, 2, 1, 0, 3, 40, 38, - 0, 1, 0, 3, 44, 68, 2, 1, 0, 3, 44, 38, - 0, 1, 0, 3, 48, 68, 2, 1, 0, 3, 48, 38, - 0, 1, 0, 3, 52, 68, 2, 1, 0, 3, 52, 38, - 0, 1, 0, 3, 56, 68, 2, 1, 0, 3, 56, 38, - 0, 1, 0, 3, 60, 66, 2, 1, 0, 3, 60, 38, - 0, 1, 0, 3, 64, 68, 2, 1, 0, 3, 64, 38, - 0, 1, 0, 3, 100, 60, 2, 1, 0, 3, 100, 38, - 0, 1, 0, 3, 104, 68, 2, 1, 0, 3, 104, 38, - 0, 1, 0, 3, 108, 68, 2, 1, 0, 3, 108, 38, - 0, 1, 0, 3, 112, 68, 2, 1, 0, 3, 112, 38, - 0, 1, 0, 3, 116, 68, 2, 1, 0, 3, 116, 38, - 0, 1, 0, 3, 120, 68, 2, 1, 0, 3, 120, 38, - 0, 1, 0, 3, 124, 68, 2, 1, 0, 3, 124, 38, - 0, 1, 0, 3, 128, 68, 2, 1, 0, 3, 128, 38, - 0, 1, 0, 3, 132, 68, 2, 1, 0, 3, 132, 38, - 0, 1, 0, 3, 136, 68, 2, 1, 0, 3, 136, 38, - 0, 1, 0, 3, 140, 60, 2, 1, 0, 3, 140, 38, - 0, 1, 0, 3, 144, 68, 2, 1, 0, 3, 144, 127, - 0, 1, 0, 3, 149, 76, 2, 1, 0, 3, 149, -128, - 0, 1, 0, 3, 153, 76, 2, 1, 0, 3, 153, -128, - 0, 1, 0, 3, 157, 76, 2, 1, 0, 3, 157, -128, - 0, 1, 0, 3, 161, 76, 2, 1, 0, 3, 161, -128, - 0, 1, 0, 3, 165, 76, 2, 1, 0, 3, 165, -128, - 0, 1, 1, 2, 38, 66, 2, 1, 1, 2, 38, 64, - 0, 1, 1, 2, 46, 72, 2, 1, 1, 2, 46, 64, - 0, 1, 1, 2, 54, 72, 2, 1, 1, 2, 54, 64, - 0, 1, 1, 2, 62, 64, 2, 1, 1, 2, 62, 64, - 0, 1, 1, 2, 102, 58, 2, 1, 1, 2, 102, 64, - 0, 1, 1, 2, 110, 72, 2, 1, 1, 2, 110, 64, - 0, 1, 1, 2, 118, 72, 2, 1, 1, 2, 118, 64, - 0, 1, 1, 2, 126, 72, 2, 1, 1, 2, 126, 64, - 0, 1, 1, 2, 134, 72, 2, 1, 1, 2, 134, 64, - 0, 1, 1, 2, 142, 72, 2, 1, 1, 2, 142, 127, - 0, 1, 1, 2, 151, 72, 2, 1, 1, 2, 151, -128, - 0, 1, 1, 2, 159, 72, 2, 1, 1, 2, 159, -128, - 0, 1, 1, 3, 38, 60, 2, 1, 1, 3, 38, 40, - 0, 1, 1, 3, 46, 68, 2, 1, 1, 3, 46, 40, - 0, 1, 1, 3, 54, 68, 2, 1, 1, 3, 54, 40, - 0, 1, 1, 3, 62, 58, 2, 1, 1, 3, 62, 40, - 0, 1, 1, 3, 102, 54, 2, 1, 1, 3, 102, 40, - 0, 1, 1, 3, 110, 68, 2, 1, 1, 3, 110, 40, - 0, 1, 1, 3, 118, 68, 2, 1, 1, 3, 118, 40, - 0, 1, 1, 3, 126, 68, 2, 1, 1, 3, 126, 40, - 0, 1, 1, 3, 134, 68, 2, 1, 1, 3, 134, 40, - 0, 1, 1, 3, 142, 68, 2, 1, 1, 3, 142, 127, - 0, 1, 1, 3, 151, 72, 2, 1, 1, 3, 151, -128, - 0, 1, 1, 3, 159, 72, 2, 1, 1, 3, 159, -128, - 0, 1, 2, 4, 42, 64, 2, 1, 2, 4, 42, 64, - 0, 1, 2, 4, 58, 62, 2, 1, 2, 4, 58, 64, - 0, 1, 2, 4, 106, 58, 2, 1, 2, 4, 106, 64, - 0, 1, 2, 4, 122, 72, 2, 1, 2, 4, 122, 64, - 0, 1, 2, 4, 138, 72, 2, 1, 2, 4, 138, 127, - 0, 1, 2, 4, 155, 72, 2, 1, 2, 4, 155, -128, - 0, 1, 2, 5, 42, 54, 2, 1, 2, 5, 42, 40, - 0, 1, 2, 5, 58, 52, 2, 1, 2, 5, 58, 40, - 0, 1, 2, 5, 106, 50, 2, 1, 2, 5, 106, 40, - 0, 1, 2, 5, 122, 66, 2, 1, 2, 5, 122, 40, - 0, 1, 2, 5, 138, 66, 2, 1, 2, 5, 138, 127, - 0, 1, 2, 5, 155, 62, 2, 1, 2, 5, 155, -128, - 1, 0, 0, 0, 1, 68, 3, 0, 0, 0, 1, 72, - 4, 0, 0, 0, 1, 76, 5, 0, 0, 0, 1, 60, - 6, 0, 0, 0, 1, 72, 7, 0, 0, 0, 1, 60, - 8, 0, 0, 0, 1, 72, 1, 0, 0, 0, 2, 68, - 3, 0, 0, 0, 2, 72, 4, 0, 0, 0, 2, 76, - 5, 0, 0, 0, 2, 60, 6, 0, 0, 0, 2, 72, - 7, 0, 0, 0, 2, 60, 8, 0, 0, 0, 2, 72, - 1, 0, 0, 0, 3, 68, 3, 0, 0, 0, 3, 76, - 4, 0, 0, 0, 3, 76, 5, 0, 0, 0, 3, 60, - 6, 0, 0, 0, 3, 76, 7, 0, 0, 0, 3, 60, - 8, 0, 0, 0, 3, 76, 1, 0, 0, 0, 4, 68, - 3, 0, 0, 0, 4, 76, 4, 0, 0, 0, 4, 76, - 5, 0, 0, 0, 4, 60, 6, 0, 0, 0, 4, 76, - 7, 0, 0, 0, 4, 60, 8, 0, 0, 0, 4, 76, - 1, 0, 0, 0, 5, 68, 3, 0, 0, 0, 5, 76, - 4, 0, 0, 0, 5, 76, 5, 0, 0, 0, 5, 60, - 6, 0, 0, 0, 5, 76, 7, 0, 0, 0, 5, 60, - 8, 0, 0, 0, 5, 76, 1, 0, 0, 0, 6, 68, - 3, 0, 0, 0, 6, 76, 4, 0, 0, 0, 6, 76, - 5, 0, 0, 0, 6, 60, 6, 0, 0, 0, 6, 76, - 7, 0, 0, 0, 6, 60, 8, 0, 0, 0, 6, 76, - 1, 0, 0, 0, 7, 68, 3, 0, 0, 0, 7, 76, - 4, 0, 0, 0, 7, 76, 5, 0, 0, 0, 7, 60, - 6, 0, 0, 0, 7, 76, 7, 0, 0, 0, 7, 60, - 8, 0, 0, 0, 7, 76, 1, 0, 0, 0, 8, 68, - 3, 0, 0, 0, 8, 76, 4, 0, 0, 0, 8, 76, - 5, 0, 0, 0, 8, 60, 6, 0, 0, 0, 8, 76, - 7, 0, 0, 0, 8, 60, 8, 0, 0, 0, 8, 76, - 1, 0, 0, 0, 9, 68, 3, 0, 0, 0, 9, 76, - 4, 0, 0, 0, 9, 76, 5, 0, 0, 0, 9, 60, - 6, 0, 0, 0, 9, 76, 7, 0, 0, 0, 9, 60, - 8, 0, 0, 0, 9, 76, 1, 0, 0, 0, 10, 68, - 3, 0, 0, 0, 10, 72, 4, 0, 0, 0, 10, 76, - 5, 0, 0, 0, 10, 60, 6, 0, 0, 0, 10, 72, - 7, 0, 0, 0, 10, 60, 8, 0, 0, 0, 10, 72, - 1, 0, 0, 0, 11, 68, 3, 0, 0, 0, 11, 72, - 4, 0, 0, 0, 11, 76, 5, 0, 0, 0, 11, 60, - 6, 0, 0, 0, 11, 72, 7, 0, 0, 0, 11, 60, - 8, 0, 0, 0, 11, 72, 1, 0, 0, 0, 12, 68, - 3, 0, 0, 0, 12, 52, 4, 0, 0, 0, 12, 76, - 5, 0, 0, 0, 12, 60, 6, 0, 0, 0, 12, 52, - 7, 0, 0, 0, 12, 60, 8, 0, 0, 0, 12, 52, - 1, 0, 0, 0, 13, 68, 3, 0, 0, 0, 13, 48, - 4, 0, 0, 0, 13, 76, 5, 0, 0, 0, 13, 60, - 6, 0, 0, 0, 13, 48, 7, 0, 0, 0, 13, 60, - 8, 0, 0, 0, 13, 48, 1, 0, 0, 0, 14, 68, - 3, 0, 0, 0, 14, 127, 4, 0, 0, 0, 14, 127, - 5, 0, 0, 0, 14, 127, 6, 0, 0, 0, 14, 127, - 7, 0, 0, 0, 14, 127, 8, 0, 0, 0, 14, 127, - 1, 0, 0, 1, 1, 76, 3, 0, 0, 1, 1, 52, - 4, 0, 0, 1, 1, 76, 5, 0, 0, 1, 1, 60, - 6, 0, 0, 1, 1, 52, 7, 0, 0, 1, 1, 60, - 8, 0, 0, 1, 1, 52, 1, 0, 0, 1, 2, 76, - 3, 0, 0, 1, 2, 60, 4, 0, 0, 1, 2, 76, - 5, 0, 0, 1, 2, 60, 6, 0, 0, 1, 2, 60, - 7, 0, 0, 1, 2, 60, 8, 0, 0, 1, 2, 60, - 1, 0, 0, 1, 3, 76, 3, 0, 0, 1, 3, 64, - 4, 0, 0, 1, 3, 76, 5, 0, 0, 1, 3, 60, - 6, 0, 0, 1, 3, 64, 7, 0, 0, 1, 3, 60, - 8, 0, 0, 1, 3, 64, 1, 0, 0, 1, 4, 76, - 3, 0, 0, 1, 4, 68, 4, 0, 0, 1, 4, 76, - 5, 0, 0, 1, 4, 60, 6, 0, 0, 1, 4, 68, - 7, 0, 0, 1, 4, 60, 8, 0, 0, 1, 4, 68, - 1, 0, 0, 1, 5, 76, 3, 0, 0, 1, 5, 76, - 4, 0, 0, 1, 5, 76, 5, 0, 0, 1, 5, 60, - 6, 0, 0, 1, 5, 76, 7, 0, 0, 1, 5, 60, - 8, 0, 0, 1, 5, 76, 1, 0, 0, 1, 6, 76, - 3, 0, 0, 1, 6, 76, 4, 0, 0, 1, 6, 76, - 5, 0, 0, 1, 6, 60, 6, 0, 0, 1, 6, 76, - 7, 0, 0, 1, 6, 60, 8, 0, 0, 1, 6, 76, - 1, 0, 0, 1, 7, 76, 3, 0, 0, 1, 7, 76, - 4, 0, 0, 1, 7, 76, 5, 0, 0, 1, 7, 60, - 6, 0, 0, 1, 7, 76, 7, 0, 0, 1, 7, 60, - 8, 0, 0, 1, 7, 76, 1, 0, 0, 1, 8, 76, - 3, 0, 0, 1, 8, 68, 4, 0, 0, 1, 8, 76, - 5, 0, 0, 1, 8, 60, 6, 0, 0, 1, 8, 68, - 7, 0, 0, 1, 8, 60, 8, 0, 0, 1, 8, 68, - 1, 0, 0, 1, 9, 76, 3, 0, 0, 1, 9, 64, - 4, 0, 0, 1, 9, 76, 5, 0, 0, 1, 9, 60, - 6, 0, 0, 1, 9, 64, 7, 0, 0, 1, 9, 60, - 8, 0, 0, 1, 9, 64, 1, 0, 0, 1, 10, 76, - 3, 0, 0, 1, 10, 60, 4, 0, 0, 1, 10, 76, - 5, 0, 0, 1, 10, 60, 6, 0, 0, 1, 10, 60, - 7, 0, 0, 1, 10, 60, 8, 0, 0, 1, 10, 60, - 1, 0, 0, 1, 11, 76, 3, 0, 0, 1, 11, 52, - 4, 0, 0, 1, 11, 76, 5, 0, 0, 1, 11, 60, - 6, 0, 0, 1, 11, 52, 7, 0, 0, 1, 11, 60, - 8, 0, 0, 1, 11, 52, 1, 0, 0, 1, 12, 76, - 3, 0, 0, 1, 12, 40, 4, 0, 0, 1, 12, 76, - 5, 0, 0, 1, 12, 60, 6, 0, 0, 1, 12, 40, - 7, 0, 0, 1, 12, 60, 8, 0, 0, 1, 12, 40, - 1, 0, 0, 1, 13, 76, 3, 0, 0, 1, 13, 28, - 4, 0, 0, 1, 13, 70, 5, 0, 0, 1, 13, 60, - 6, 0, 0, 1, 13, 28, 7, 0, 0, 1, 13, 60, - 8, 0, 0, 1, 13, 28, 1, 0, 0, 1, 14, 127, - 3, 0, 0, 1, 14, 127, 4, 0, 0, 1, 14, 127, - 5, 0, 0, 1, 14, 127, 6, 0, 0, 1, 14, 127, - 7, 0, 0, 1, 14, 127, 8, 0, 0, 1, 14, 127, - 1, 0, 0, 2, 1, 76, 3, 0, 0, 2, 1, 52, - 4, 0, 0, 2, 1, 76, 5, 0, 0, 2, 1, 60, - 6, 0, 0, 2, 1, 52, 7, 0, 0, 2, 1, 60, - 8, 0, 0, 2, 1, 52, 1, 0, 0, 2, 2, 76, - 3, 0, 0, 2, 2, 60, 4, 0, 0, 2, 2, 76, - 5, 0, 0, 2, 2, 60, 6, 0, 0, 2, 2, 60, - 7, 0, 0, 2, 2, 60, 8, 0, 0, 2, 2, 60, - 1, 0, 0, 2, 3, 76, 3, 0, 0, 2, 3, 64, - 4, 0, 0, 2, 3, 76, 5, 0, 0, 2, 3, 60, - 6, 0, 0, 2, 3, 64, 7, 0, 0, 2, 3, 60, - 8, 0, 0, 2, 3, 64, 1, 0, 0, 2, 4, 76, - 3, 0, 0, 2, 4, 68, 4, 0, 0, 2, 4, 76, - 5, 0, 0, 2, 4, 60, 6, 0, 0, 2, 4, 68, - 7, 0, 0, 2, 4, 60, 8, 0, 0, 2, 4, 68, - 1, 0, 0, 2, 5, 76, 3, 0, 0, 2, 5, 76, - 4, 0, 0, 2, 5, 76, 5, 0, 0, 2, 5, 60, - 6, 0, 0, 2, 5, 76, 7, 0, 0, 2, 5, 60, - 8, 0, 0, 2, 5, 76, 1, 0, 0, 2, 6, 76, - 3, 0, 0, 2, 6, 76, 4, 0, 0, 2, 6, 76, - 5, 0, 0, 2, 6, 60, 6, 0, 0, 2, 6, 76, - 7, 0, 0, 2, 6, 60, 8, 0, 0, 2, 6, 76, - 1, 0, 0, 2, 7, 76, 3, 0, 0, 2, 7, 76, - 4, 0, 0, 2, 7, 76, 5, 0, 0, 2, 7, 60, - 6, 0, 0, 2, 7, 76, 7, 0, 0, 2, 7, 60, - 8, 0, 0, 2, 7, 76, 1, 0, 0, 2, 8, 76, - 3, 0, 0, 2, 8, 68, 4, 0, 0, 2, 8, 76, - 5, 0, 0, 2, 8, 60, 6, 0, 0, 2, 8, 68, - 7, 0, 0, 2, 8, 60, 8, 0, 0, 2, 8, 68, - 1, 0, 0, 2, 9, 76, 3, 0, 0, 2, 9, 64, - 4, 0, 0, 2, 9, 76, 5, 0, 0, 2, 9, 60, - 6, 0, 0, 2, 9, 64, 7, 0, 0, 2, 9, 60, - 8, 0, 0, 2, 9, 64, 1, 0, 0, 2, 10, 76, - 3, 0, 0, 2, 10, 60, 4, 0, 0, 2, 10, 76, - 5, 0, 0, 2, 10, 60, 6, 0, 0, 2, 10, 60, - 7, 0, 0, 2, 10, 60, 8, 0, 0, 2, 10, 60, - 1, 0, 0, 2, 11, 76, 3, 0, 0, 2, 11, 52, - 4, 0, 0, 2, 11, 76, 5, 0, 0, 2, 11, 60, - 6, 0, 0, 2, 11, 52, 7, 0, 0, 2, 11, 60, - 8, 0, 0, 2, 11, 52, 1, 0, 0, 2, 12, 76, - 3, 0, 0, 2, 12, 40, 4, 0, 0, 2, 12, 76, - 5, 0, 0, 2, 12, 60, 6, 0, 0, 2, 12, 40, - 7, 0, 0, 2, 12, 60, 8, 0, 0, 2, 12, 40, - 1, 0, 0, 2, 13, 76, 3, 0, 0, 2, 13, 28, - 4, 0, 0, 2, 13, 72, 5, 0, 0, 2, 13, 60, - 6, 0, 0, 2, 13, 28, 7, 0, 0, 2, 13, 60, - 8, 0, 0, 2, 13, 28, 1, 0, 0, 2, 14, 127, - 3, 0, 0, 2, 14, 127, 4, 0, 0, 2, 14, 127, - 5, 0, 0, 2, 14, 127, 6, 0, 0, 2, 14, 127, - 7, 0, 0, 2, 14, 127, 8, 0, 0, 2, 14, 127, - 1, 0, 0, 3, 1, 66, 3, 0, 0, 3, 1, 52, - 4, 0, 0, 3, 1, 68, 5, 0, 0, 3, 1, 36, - 6, 0, 0, 3, 1, 52, 7, 0, 0, 3, 1, 36, - 8, 0, 0, 3, 1, 52, 1, 0, 0, 3, 2, 66, - 3, 0, 0, 3, 2, 60, 4, 0, 0, 3, 2, 70, - 5, 0, 0, 3, 2, 36, 6, 0, 0, 3, 2, 60, - 7, 0, 0, 3, 2, 36, 8, 0, 0, 3, 2, 60, - 1, 0, 0, 3, 3, 66, 3, 0, 0, 3, 3, 64, - 4, 0, 0, 3, 3, 70, 5, 0, 0, 3, 3, 36, - 6, 0, 0, 3, 3, 64, 7, 0, 0, 3, 3, 36, - 8, 0, 0, 3, 3, 64, 1, 0, 0, 3, 4, 66, - 3, 0, 0, 3, 4, 68, 4, 0, 0, 3, 4, 70, - 5, 0, 0, 3, 4, 36, 6, 0, 0, 3, 4, 68, - 7, 0, 0, 3, 4, 36, 8, 0, 0, 3, 4, 68, - 1, 0, 0, 3, 5, 66, 3, 0, 0, 3, 5, 76, - 4, 0, 0, 3, 5, 70, 5, 0, 0, 3, 5, 36, - 6, 0, 0, 3, 5, 76, 7, 0, 0, 3, 5, 36, - 8, 0, 0, 3, 5, 76, 1, 0, 0, 3, 6, 66, - 3, 0, 0, 3, 6, 76, 4, 0, 0, 3, 6, 70, - 5, 0, 0, 3, 6, 36, 6, 0, 0, 3, 6, 76, - 7, 0, 0, 3, 6, 36, 8, 0, 0, 3, 6, 76, - 1, 0, 0, 3, 7, 66, 3, 0, 0, 3, 7, 76, - 4, 0, 0, 3, 7, 70, 5, 0, 0, 3, 7, 36, - 6, 0, 0, 3, 7, 76, 7, 0, 0, 3, 7, 36, - 8, 0, 0, 3, 7, 76, 1, 0, 0, 3, 8, 66, - 3, 0, 0, 3, 8, 68, 4, 0, 0, 3, 8, 70, - 5, 0, 0, 3, 8, 36, 6, 0, 0, 3, 8, 68, - 7, 0, 0, 3, 8, 36, 8, 0, 0, 3, 8, 68, - 1, 0, 0, 3, 9, 66, 3, 0, 0, 3, 9, 64, - 4, 0, 0, 3, 9, 70, 5, 0, 0, 3, 9, 36, - 6, 0, 0, 3, 9, 64, 7, 0, 0, 3, 9, 36, - 8, 0, 0, 3, 9, 64, 1, 0, 0, 3, 10, 66, - 3, 0, 0, 3, 10, 60, 4, 0, 0, 3, 10, 70, - 5, 0, 0, 3, 10, 36, 6, 0, 0, 3, 10, 60, - 7, 0, 0, 3, 10, 36, 8, 0, 0, 3, 10, 60, - 1, 0, 0, 3, 11, 66, 3, 0, 0, 3, 11, 52, - 4, 0, 0, 3, 11, 70, 5, 0, 0, 3, 11, 36, - 6, 0, 0, 3, 11, 52, 7, 0, 0, 3, 11, 36, - 8, 0, 0, 3, 11, 52, 1, 0, 0, 3, 12, 66, - 3, 0, 0, 3, 12, 40, 4, 0, 0, 3, 12, 70, - 5, 0, 0, 3, 12, 36, 6, 0, 0, 3, 12, 40, - 7, 0, 0, 3, 12, 36, 8, 0, 0, 3, 12, 40, - 1, 0, 0, 3, 13, 66, 3, 0, 0, 3, 13, 28, - 4, 0, 0, 3, 13, 62, 5, 0, 0, 3, 13, 36, - 6, 0, 0, 3, 13, 28, 7, 0, 0, 3, 13, 36, - 8, 0, 0, 3, 13, 28, 1, 0, 0, 3, 14, 127, - 3, 0, 0, 3, 14, 127, 4, 0, 0, 3, 14, 127, - 5, 0, 0, 3, 14, 127, 6, 0, 0, 3, 14, 127, - 7, 0, 0, 3, 14, 127, 8, 0, 0, 3, 14, 127, - 1, 0, 1, 2, 1, 127, 3, 0, 1, 2, 1, 127, - 4, 0, 1, 2, 1, 127, 5, 0, 1, 2, 1, 127, - 6, 0, 1, 2, 1, 127, 7, 0, 1, 2, 1, 127, - 8, 0, 1, 2, 1, 127, 1, 0, 1, 2, 2, 127, - 3, 0, 1, 2, 2, 127, 4, 0, 1, 2, 2, 127, - 5, 0, 1, 2, 2, 127, 6, 0, 1, 2, 2, 127, - 7, 0, 1, 2, 2, 127, 8, 0, 1, 2, 2, 127, - 1, 0, 1, 2, 3, 72, 3, 0, 1, 2, 3, 52, - 4, 0, 1, 2, 3, 72, 5, 0, 1, 2, 3, 60, - 6, 0, 1, 2, 3, 52, 7, 0, 1, 2, 3, 60, - 8, 0, 1, 2, 3, 52, 1, 0, 1, 2, 4, 72, - 3, 0, 1, 2, 4, 52, 4, 0, 1, 2, 4, 72, - 5, 0, 1, 2, 4, 60, 6, 0, 1, 2, 4, 52, - 7, 0, 1, 2, 4, 60, 8, 0, 1, 2, 4, 52, - 1, 0, 1, 2, 5, 72, 3, 0, 1, 2, 5, 60, - 4, 0, 1, 2, 5, 72, 5, 0, 1, 2, 5, 60, - 6, 0, 1, 2, 5, 60, 7, 0, 1, 2, 5, 60, - 8, 0, 1, 2, 5, 60, 1, 0, 1, 2, 6, 72, - 3, 0, 1, 2, 6, 64, 4, 0, 1, 2, 6, 72, - 5, 0, 1, 2, 6, 60, 6, 0, 1, 2, 6, 64, - 7, 0, 1, 2, 6, 60, 8, 0, 1, 2, 6, 64, - 1, 0, 1, 2, 7, 72, 3, 0, 1, 2, 7, 60, - 4, 0, 1, 2, 7, 72, 5, 0, 1, 2, 7, 60, - 6, 0, 1, 2, 7, 60, 7, 0, 1, 2, 7, 60, - 8, 0, 1, 2, 7, 60, 1, 0, 1, 2, 8, 72, - 3, 0, 1, 2, 8, 52, 4, 0, 1, 2, 8, 72, - 5, 0, 1, 2, 8, 60, 6, 0, 1, 2, 8, 52, - 7, 0, 1, 2, 8, 60, 8, 0, 1, 2, 8, 52, - 1, 0, 1, 2, 9, 72, 3, 0, 1, 2, 9, 52, - 4, 0, 1, 2, 9, 72, 5, 0, 1, 2, 9, 60, - 6, 0, 1, 2, 9, 52, 7, 0, 1, 2, 9, 60, - 8, 0, 1, 2, 9, 52, 1, 0, 1, 2, 10, 72, - 3, 0, 1, 2, 10, 40, 4, 0, 1, 2, 10, 72, - 5, 0, 1, 2, 10, 60, 6, 0, 1, 2, 10, 40, - 7, 0, 1, 2, 10, 60, 8, 0, 1, 2, 10, 40, - 1, 0, 1, 2, 11, 72, 3, 0, 1, 2, 11, 28, - 4, 0, 1, 2, 11, 70, 5, 0, 1, 2, 11, 60, - 6, 0, 1, 2, 11, 28, 7, 0, 1, 2, 11, 60, - 8, 0, 1, 2, 11, 28, 1, 0, 1, 2, 12, 127, - 3, 0, 1, 2, 12, 127, 4, 0, 1, 2, 12, 127, - 5, 0, 1, 2, 12, 127, 6, 0, 1, 2, 12, 127, - 7, 0, 1, 2, 12, 127, 8, 0, 1, 2, 12, 127, - 1, 0, 1, 2, 13, 127, 3, 0, 1, 2, 13, 127, - 4, 0, 1, 2, 13, 127, 5, 0, 1, 2, 13, 127, - 6, 0, 1, 2, 13, 127, 7, 0, 1, 2, 13, 127, - 8, 0, 1, 2, 13, 127, 1, 0, 1, 2, 14, 127, - 3, 0, 1, 2, 14, 127, 4, 0, 1, 2, 14, 127, - 5, 0, 1, 2, 14, 127, 6, 0, 1, 2, 14, 127, - 7, 0, 1, 2, 14, 127, 8, 0, 1, 2, 14, 127, - 1, 0, 1, 3, 1, 127, 3, 0, 1, 3, 1, 127, - 4, 0, 1, 3, 1, 127, 5, 0, 1, 3, 1, 127, - 6, 0, 1, 3, 1, 127, 7, 0, 1, 3, 1, 127, - 8, 0, 1, 3, 1, 127, 1, 0, 1, 3, 2, 127, - 3, 0, 1, 3, 2, 127, 4, 0, 1, 3, 2, 127, - 5, 0, 1, 3, 2, 127, 6, 0, 1, 3, 2, 127, - 7, 0, 1, 3, 2, 127, 8, 0, 1, 3, 2, 127, - 1, 0, 1, 3, 3, 66, 3, 0, 1, 3, 3, 48, - 4, 0, 1, 3, 3, 66, 5, 0, 1, 3, 3, 36, - 6, 0, 1, 3, 3, 48, 7, 0, 1, 3, 3, 36, - 8, 0, 1, 3, 3, 48, 1, 0, 1, 3, 4, 66, - 3, 0, 1, 3, 4, 48, 4, 0, 1, 3, 4, 70, - 5, 0, 1, 3, 4, 36, 6, 0, 1, 3, 4, 48, - 7, 0, 1, 3, 4, 36, 8, 0, 1, 3, 4, 48, - 1, 0, 1, 3, 5, 66, 3, 0, 1, 3, 5, 60, - 4, 0, 1, 3, 5, 70, 5, 0, 1, 3, 5, 36, - 6, 0, 1, 3, 5, 60, 7, 0, 1, 3, 5, 36, - 8, 0, 1, 3, 5, 60, 1, 0, 1, 3, 6, 66, - 3, 0, 1, 3, 6, 64, 4, 0, 1, 3, 6, 70, - 5, 0, 1, 3, 6, 36, 6, 0, 1, 3, 6, 64, - 7, 0, 1, 3, 6, 36, 8, 0, 1, 3, 6, 64, - 1, 0, 1, 3, 7, 66, 3, 0, 1, 3, 7, 60, - 4, 0, 1, 3, 7, 70, 5, 0, 1, 3, 7, 36, - 6, 0, 1, 3, 7, 60, 7, 0, 1, 3, 7, 36, - 8, 0, 1, 3, 7, 60, 1, 0, 1, 3, 8, 66, - 3, 0, 1, 3, 8, 52, 4, 0, 1, 3, 8, 70, - 5, 0, 1, 3, 8, 36, 6, 0, 1, 3, 8, 52, - 7, 0, 1, 3, 8, 36, 8, 0, 1, 3, 8, 52, - 1, 0, 1, 3, 9, 66, 3, 0, 1, 3, 9, 52, - 4, 0, 1, 3, 9, 70, 5, 0, 1, 3, 9, 36, - 6, 0, 1, 3, 9, 52, 7, 0, 1, 3, 9, 36, - 8, 0, 1, 3, 9, 52, 1, 0, 1, 3, 10, 66, - 3, 0, 1, 3, 10, 40, 4, 0, 1, 3, 10, 70, - 5, 0, 1, 3, 10, 36, 6, 0, 1, 3, 10, 40, - 7, 0, 1, 3, 10, 36, 8, 0, 1, 3, 10, 40, - 1, 0, 1, 3, 11, 66, 3, 0, 1, 3, 11, 26, - 4, 0, 1, 3, 11, 66, 5, 0, 1, 3, 11, 36, - 6, 0, 1, 3, 11, 26, 7, 0, 1, 3, 11, 36, - 8, 0, 1, 3, 11, 26, 1, 0, 1, 3, 12, 127, - 3, 0, 1, 3, 12, 127, 4, 0, 1, 3, 12, 127, - 5, 0, 1, 3, 12, 127, 6, 0, 1, 3, 12, 127, - 7, 0, 1, 3, 12, 127, 8, 0, 1, 3, 12, 127, - 1, 0, 1, 3, 13, 127, 3, 0, 1, 3, 13, 127, - 4, 0, 1, 3, 13, 127, 5, 0, 1, 3, 13, 127, - 6, 0, 1, 3, 13, 127, 7, 0, 1, 3, 13, 127, - 8, 0, 1, 3, 13, 127, 1, 0, 1, 3, 14, 127, - 3, 0, 1, 3, 14, 127, 4, 0, 1, 3, 14, 127, - 5, 0, 1, 3, 14, 127, 6, 0, 1, 3, 14, 127, - 7, 0, 1, 3, 14, 127, 8, 0, 1, 3, 14, 127, - 1, 1, 0, 1, 36, 60, 3, 1, 0, 1, 36, 62, - 4, 1, 0, 1, 36, 76, 5, 1, 0, 1, 36, 62, - 6, 1, 0, 1, 36, 64, 7, 1, 0, 1, 36, 54, - 8, 1, 0, 1, 36, 62, 1, 1, 0, 1, 40, 62, - 3, 1, 0, 1, 40, 62, 4, 1, 0, 1, 40, 76, - 5, 1, 0, 1, 40, 62, 6, 1, 0, 1, 40, 64, - 7, 1, 0, 1, 40, 54, 8, 1, 0, 1, 40, 62, - 1, 1, 0, 1, 44, 62, 3, 1, 0, 1, 44, 62, - 4, 1, 0, 1, 44, 76, 5, 1, 0, 1, 44, 62, - 6, 1, 0, 1, 44, 64, 7, 1, 0, 1, 44, 54, - 8, 1, 0, 1, 44, 62, 1, 1, 0, 1, 48, 62, - 3, 1, 0, 1, 48, 62, 4, 1, 0, 1, 48, 76, - 5, 1, 0, 1, 48, 62, 6, 1, 0, 1, 48, 64, - 7, 1, 0, 1, 48, 54, 8, 1, 0, 1, 48, 62, - 1, 1, 0, 1, 52, 62, 3, 1, 0, 1, 52, 64, - 4, 1, 0, 1, 52, 76, 5, 1, 0, 1, 52, 62, - 6, 1, 0, 1, 52, 76, 7, 1, 0, 1, 52, 54, - 8, 1, 0, 1, 52, 76, 1, 1, 0, 1, 56, 62, - 3, 1, 0, 1, 56, 64, 4, 1, 0, 1, 56, 76, - 5, 1, 0, 1, 56, 62, 6, 1, 0, 1, 56, 76, - 7, 1, 0, 1, 56, 54, 8, 1, 0, 1, 56, 76, - 1, 1, 0, 1, 60, 62, 3, 1, 0, 1, 60, 64, - 4, 1, 0, 1, 60, 76, 5, 1, 0, 1, 60, 62, - 6, 1, 0, 1, 60, 76, 7, 1, 0, 1, 60, 54, - 8, 1, 0, 1, 60, 76, 1, 1, 0, 1, 64, 60, - 3, 1, 0, 1, 64, 64, 4, 1, 0, 1, 64, 76, - 5, 1, 0, 1, 64, 62, 6, 1, 0, 1, 64, 74, - 7, 1, 0, 1, 64, 54, 8, 1, 0, 1, 64, 74, - 1, 1, 0, 1, 100, 76, 3, 1, 0, 1, 100, 72, - 4, 1, 0, 1, 100, 76, 5, 1, 0, 1, 100, 62, - 6, 1, 0, 1, 100, 72, 7, 1, 0, 1, 100, 54, - 8, 1, 0, 1, 100, 72, 1, 1, 0, 1, 104, 76, - 3, 1, 0, 1, 104, 76, 4, 1, 0, 1, 104, 76, - 5, 1, 0, 1, 104, 62, 6, 1, 0, 1, 104, 76, - 7, 1, 0, 1, 104, 54, 8, 1, 0, 1, 104, 76, - 1, 1, 0, 1, 108, 76, 3, 1, 0, 1, 108, 76, - 4, 1, 0, 1, 108, 76, 5, 1, 0, 1, 108, 62, - 6, 1, 0, 1, 108, 76, 7, 1, 0, 1, 108, 54, - 8, 1, 0, 1, 108, 76, 1, 1, 0, 1, 112, 76, - 3, 1, 0, 1, 112, 76, 4, 1, 0, 1, 112, 76, - 5, 1, 0, 1, 112, 62, 6, 1, 0, 1, 112, 76, - 7, 1, 0, 1, 112, 54, 8, 1, 0, 1, 112, 76, - 1, 1, 0, 1, 116, 76, 3, 1, 0, 1, 116, 76, - 4, 1, 0, 1, 116, 76, 5, 1, 0, 1, 116, 62, - 6, 1, 0, 1, 116, 76, 7, 1, 0, 1, 116, 54, - 8, 1, 0, 1, 116, 76, 1, 1, 0, 1, 120, 76, - 3, 1, 0, 1, 120, 127, 4, 1, 0, 1, 120, 76, - 5, 1, 0, 1, 120, 127, 6, 1, 0, 1, 120, 76, - 7, 1, 0, 1, 120, 54, 8, 1, 0, 1, 120, 76, - 1, 1, 0, 1, 124, 76, 3, 1, 0, 1, 124, 127, - 4, 1, 0, 1, 124, 76, 5, 1, 0, 1, 124, 127, - 6, 1, 0, 1, 124, 76, 7, 1, 0, 1, 124, 54, - 8, 1, 0, 1, 124, 76, 1, 1, 0, 1, 128, 76, - 3, 1, 0, 1, 128, 127, 4, 1, 0, 1, 128, 76, - 5, 1, 0, 1, 128, 127, 6, 1, 0, 1, 128, 76, - 7, 1, 0, 1, 128, 54, 8, 1, 0, 1, 128, 76, - 1, 1, 0, 1, 132, 76, 3, 1, 0, 1, 132, 76, - 4, 1, 0, 1, 132, 76, 5, 1, 0, 1, 132, 62, - 6, 1, 0, 1, 132, 76, 7, 1, 0, 1, 132, 54, - 8, 1, 0, 1, 132, 76, 1, 1, 0, 1, 136, 76, - 3, 1, 0, 1, 136, 76, 4, 1, 0, 1, 136, 76, - 5, 1, 0, 1, 136, 62, 6, 1, 0, 1, 136, 76, - 7, 1, 0, 1, 136, 127, 8, 1, 0, 1, 136, 76, - 1, 1, 0, 1, 140, 76, 3, 1, 0, 1, 140, 72, - 4, 1, 0, 1, 140, 76, 5, 1, 0, 1, 140, 62, - 6, 1, 0, 1, 140, 72, 7, 1, 0, 1, 140, 127, - 8, 1, 0, 1, 140, 72, 1, 1, 0, 1, 144, 127, - 3, 1, 0, 1, 144, 76, 4, 1, 0, 1, 144, 76, - 5, 1, 0, 1, 144, 127, 6, 1, 0, 1, 144, 76, - 7, 1, 0, 1, 144, 127, 8, 1, 0, 1, 144, 76, - 1, 1, 0, 1, 149, 127, 3, 1, 0, 1, 149, 76, - 4, 1, 0, 1, 149, 74, 5, 1, 0, 1, 149, 76, - 6, 1, 0, 1, 149, 76, 7, 1, 0, 1, 149, 54, - 8, 1, 0, 1, 149, 76, 1, 1, 0, 1, 153, 127, - 3, 1, 0, 1, 153, 76, 4, 1, 0, 1, 153, 74, - 5, 1, 0, 1, 153, 76, 6, 1, 0, 1, 153, 76, - 7, 1, 0, 1, 153, 54, 8, 1, 0, 1, 153, 76, - 1, 1, 0, 1, 157, 127, 3, 1, 0, 1, 157, 76, - 4, 1, 0, 1, 157, 74, 5, 1, 0, 1, 157, 76, - 6, 1, 0, 1, 157, 76, 7, 1, 0, 1, 157, 54, - 8, 1, 0, 1, 157, 76, 1, 1, 0, 1, 161, 127, - 3, 1, 0, 1, 161, 76, 4, 1, 0, 1, 161, 74, - 5, 1, 0, 1, 161, 76, 6, 1, 0, 1, 161, 76, - 7, 1, 0, 1, 161, 54, 8, 1, 0, 1, 161, 76, - 1, 1, 0, 1, 165, 127, 3, 1, 0, 1, 165, 76, - 4, 1, 0, 1, 165, 74, 5, 1, 0, 1, 165, 76, - 6, 1, 0, 1, 165, 76, 7, 1, 0, 1, 165, 54, - 8, 1, 0, 1, 165, 76, 1, 1, 0, 2, 36, 62, - 3, 1, 0, 2, 36, 62, 4, 1, 0, 2, 36, 76, - 5, 1, 0, 2, 36, 62, 6, 1, 0, 2, 36, 64, - 7, 1, 0, 2, 36, 54, 8, 1, 0, 2, 36, 62, - 1, 1, 0, 2, 40, 62, 3, 1, 0, 2, 40, 62, - 4, 1, 0, 2, 40, 76, 5, 1, 0, 2, 40, 62, - 6, 1, 0, 2, 40, 64, 7, 1, 0, 2, 40, 54, - 8, 1, 0, 2, 40, 62, 1, 1, 0, 2, 44, 62, - 3, 1, 0, 2, 44, 62, 4, 1, 0, 2, 44, 76, - 5, 1, 0, 2, 44, 62, 6, 1, 0, 2, 44, 64, - 7, 1, 0, 2, 44, 54, 8, 1, 0, 2, 44, 62, - 1, 1, 0, 2, 48, 62, 3, 1, 0, 2, 48, 62, - 4, 1, 0, 2, 48, 76, 5, 1, 0, 2, 48, 62, - 6, 1, 0, 2, 48, 64, 7, 1, 0, 2, 48, 54, - 8, 1, 0, 2, 48, 62, 1, 1, 0, 2, 52, 62, - 3, 1, 0, 2, 52, 64, 4, 1, 0, 2, 52, 76, - 5, 1, 0, 2, 52, 62, 6, 1, 0, 2, 52, 76, - 7, 1, 0, 2, 52, 54, 8, 1, 0, 2, 52, 76, - 1, 1, 0, 2, 56, 62, 3, 1, 0, 2, 56, 64, - 4, 1, 0, 2, 56, 76, 5, 1, 0, 2, 56, 62, - 6, 1, 0, 2, 56, 76, 7, 1, 0, 2, 56, 54, - 8, 1, 0, 2, 56, 76, 1, 1, 0, 2, 60, 62, - 3, 1, 0, 2, 60, 64, 4, 1, 0, 2, 60, 76, - 5, 1, 0, 2, 60, 62, 6, 1, 0, 2, 60, 76, - 7, 1, 0, 2, 60, 54, 8, 1, 0, 2, 60, 76, - 1, 1, 0, 2, 64, 60, 3, 1, 0, 2, 64, 64, - 4, 1, 0, 2, 64, 74, 5, 1, 0, 2, 64, 62, - 6, 1, 0, 2, 64, 74, 7, 1, 0, 2, 64, 54, - 8, 1, 0, 2, 64, 74, 1, 1, 0, 2, 100, 76, - 3, 1, 0, 2, 100, 70, 4, 1, 0, 2, 100, 76, - 5, 1, 0, 2, 100, 62, 6, 1, 0, 2, 100, 70, - 7, 1, 0, 2, 100, 54, 8, 1, 0, 2, 100, 70, - 1, 1, 0, 2, 104, 76, 3, 1, 0, 2, 104, 76, - 4, 1, 0, 2, 104, 76, 5, 1, 0, 2, 104, 62, - 6, 1, 0, 2, 104, 76, 7, 1, 0, 2, 104, 54, - 8, 1, 0, 2, 104, 76, 1, 1, 0, 2, 108, 76, - 3, 1, 0, 2, 108, 76, 4, 1, 0, 2, 108, 76, - 5, 1, 0, 2, 108, 62, 6, 1, 0, 2, 108, 76, - 7, 1, 0, 2, 108, 54, 8, 1, 0, 2, 108, 76, - 1, 1, 0, 2, 112, 76, 3, 1, 0, 2, 112, 76, - 4, 1, 0, 2, 112, 76, 5, 1, 0, 2, 112, 62, - 6, 1, 0, 2, 112, 76, 7, 1, 0, 2, 112, 54, - 8, 1, 0, 2, 112, 76, 1, 1, 0, 2, 116, 76, - 3, 1, 0, 2, 116, 76, 4, 1, 0, 2, 116, 76, - 5, 1, 0, 2, 116, 62, 6, 1, 0, 2, 116, 76, - 7, 1, 0, 2, 116, 54, 8, 1, 0, 2, 116, 76, - 1, 1, 0, 2, 120, 76, 3, 1, 0, 2, 120, 127, - 4, 1, 0, 2, 120, 76, 5, 1, 0, 2, 120, 127, - 6, 1, 0, 2, 120, 76, 7, 1, 0, 2, 120, 54, - 8, 1, 0, 2, 120, 76, 1, 1, 0, 2, 124, 76, - 3, 1, 0, 2, 124, 127, 4, 1, 0, 2, 124, 76, - 5, 1, 0, 2, 124, 127, 6, 1, 0, 2, 124, 76, - 7, 1, 0, 2, 124, 54, 8, 1, 0, 2, 124, 76, - 1, 1, 0, 2, 128, 76, 3, 1, 0, 2, 128, 127, - 4, 1, 0, 2, 128, 76, 5, 1, 0, 2, 128, 127, - 6, 1, 0, 2, 128, 76, 7, 1, 0, 2, 128, 54, - 8, 1, 0, 2, 128, 76, 1, 1, 0, 2, 132, 76, - 3, 1, 0, 2, 132, 76, 4, 1, 0, 2, 132, 76, - 5, 1, 0, 2, 132, 62, 6, 1, 0, 2, 132, 76, - 7, 1, 0, 2, 132, 54, 8, 1, 0, 2, 132, 76, - 1, 1, 0, 2, 136, 76, 3, 1, 0, 2, 136, 76, - 4, 1, 0, 2, 136, 76, 5, 1, 0, 2, 136, 62, - 6, 1, 0, 2, 136, 76, 7, 1, 0, 2, 136, 127, - 8, 1, 0, 2, 136, 76, 1, 1, 0, 2, 140, 76, - 3, 1, 0, 2, 140, 70, 4, 1, 0, 2, 140, 76, - 5, 1, 0, 2, 140, 62, 6, 1, 0, 2, 140, 70, - 7, 1, 0, 2, 140, 127, 8, 1, 0, 2, 140, 70, - 1, 1, 0, 2, 144, 127, 3, 1, 0, 2, 144, 76, - 4, 1, 0, 2, 144, 76, 5, 1, 0, 2, 144, 127, - 6, 1, 0, 2, 144, 76, 7, 1, 0, 2, 144, 127, - 8, 1, 0, 2, 144, 76, 1, 1, 0, 2, 149, 127, - 3, 1, 0, 2, 149, 76, 4, 1, 0, 2, 149, 74, - 5, 1, 0, 2, 149, 76, 6, 1, 0, 2, 149, 76, - 7, 1, 0, 2, 149, 54, 8, 1, 0, 2, 149, 76, - 1, 1, 0, 2, 153, 127, 3, 1, 0, 2, 153, 76, - 4, 1, 0, 2, 153, 74, 5, 1, 0, 2, 153, 76, - 6, 1, 0, 2, 153, 76, 7, 1, 0, 2, 153, 54, - 8, 1, 0, 2, 153, 76, 1, 1, 0, 2, 157, 127, - 3, 1, 0, 2, 157, 76, 4, 1, 0, 2, 157, 74, - 5, 1, 0, 2, 157, 76, 6, 1, 0, 2, 157, 76, - 7, 1, 0, 2, 157, 54, 8, 1, 0, 2, 157, 76, - 1, 1, 0, 2, 161, 127, 3, 1, 0, 2, 161, 76, - 4, 1, 0, 2, 161, 74, 5, 1, 0, 2, 161, 76, - 6, 1, 0, 2, 161, 76, 7, 1, 0, 2, 161, 54, - 8, 1, 0, 2, 161, 76, 1, 1, 0, 2, 165, 127, - 3, 1, 0, 2, 165, 76, 4, 1, 0, 2, 165, 74, - 5, 1, 0, 2, 165, 76, 6, 1, 0, 2, 165, 76, - 7, 1, 0, 2, 165, 54, 8, 1, 0, 2, 165, 76, - 1, 1, 0, 3, 36, 50, 3, 1, 0, 3, 36, 38, - 4, 1, 0, 3, 36, 66, 5, 1, 0, 3, 36, 38, - 6, 1, 0, 3, 36, 52, 7, 1, 0, 3, 36, 30, - 8, 1, 0, 3, 36, 50, 1, 1, 0, 3, 40, 50, - 3, 1, 0, 3, 40, 38, 4, 1, 0, 3, 40, 66, - 5, 1, 0, 3, 40, 38, 6, 1, 0, 3, 40, 52, - 7, 1, 0, 3, 40, 30, 8, 1, 0, 3, 40, 50, - 1, 1, 0, 3, 44, 50, 3, 1, 0, 3, 44, 38, - 4, 1, 0, 3, 44, 66, 5, 1, 0, 3, 44, 38, - 6, 1, 0, 3, 44, 52, 7, 1, 0, 3, 44, 30, - 8, 1, 0, 3, 44, 50, 1, 1, 0, 3, 48, 50, - 3, 1, 0, 3, 48, 38, 4, 1, 0, 3, 48, 66, - 5, 1, 0, 3, 48, 38, 6, 1, 0, 3, 48, 52, - 7, 1, 0, 3, 48, 30, 8, 1, 0, 3, 48, 50, - 1, 1, 0, 3, 52, 50, 3, 1, 0, 3, 52, 40, - 4, 1, 0, 3, 52, 66, 5, 1, 0, 3, 52, 38, - 6, 1, 0, 3, 52, 68, 7, 1, 0, 3, 52, 30, - 8, 1, 0, 3, 52, 68, 1, 1, 0, 3, 56, 50, - 3, 1, 0, 3, 56, 40, 4, 1, 0, 3, 56, 66, - 5, 1, 0, 3, 56, 38, 6, 1, 0, 3, 56, 68, - 7, 1, 0, 3, 56, 30, 8, 1, 0, 3, 56, 68, - 1, 1, 0, 3, 60, 50, 3, 1, 0, 3, 60, 40, - 4, 1, 0, 3, 60, 66, 5, 1, 0, 3, 60, 38, - 6, 1, 0, 3, 60, 66, 7, 1, 0, 3, 60, 30, - 8, 1, 0, 3, 60, 66, 1, 1, 0, 3, 64, 50, - 3, 1, 0, 3, 64, 40, 4, 1, 0, 3, 64, 66, - 5, 1, 0, 3, 64, 38, 6, 1, 0, 3, 64, 68, - 7, 1, 0, 3, 64, 30, 8, 1, 0, 3, 64, 68, - 1, 1, 0, 3, 100, 70, 3, 1, 0, 3, 100, 60, - 4, 1, 0, 3, 100, 64, 5, 1, 0, 3, 100, 38, - 6, 1, 0, 3, 100, 60, 7, 1, 0, 3, 100, 30, - 8, 1, 0, 3, 100, 60, 1, 1, 0, 3, 104, 70, - 3, 1, 0, 3, 104, 68, 4, 1, 0, 3, 104, 64, - 5, 1, 0, 3, 104, 38, 6, 1, 0, 3, 104, 68, - 7, 1, 0, 3, 104, 30, 8, 1, 0, 3, 104, 68, - 1, 1, 0, 3, 108, 70, 3, 1, 0, 3, 108, 68, - 4, 1, 0, 3, 108, 64, 5, 1, 0, 3, 108, 38, - 6, 1, 0, 3, 108, 68, 7, 1, 0, 3, 108, 30, - 8, 1, 0, 3, 108, 68, 1, 1, 0, 3, 112, 70, - 3, 1, 0, 3, 112, 68, 4, 1, 0, 3, 112, 64, - 5, 1, 0, 3, 112, 38, 6, 1, 0, 3, 112, 68, - 7, 1, 0, 3, 112, 30, 8, 1, 0, 3, 112, 68, - 1, 1, 0, 3, 116, 70, 3, 1, 0, 3, 116, 68, - 4, 1, 0, 3, 116, 64, 5, 1, 0, 3, 116, 38, - 6, 1, 0, 3, 116, 68, 7, 1, 0, 3, 116, 30, - 8, 1, 0, 3, 116, 68, 1, 1, 0, 3, 120, 70, - 3, 1, 0, 3, 120, 127, 4, 1, 0, 3, 120, 64, - 5, 1, 0, 3, 120, 127, 6, 1, 0, 3, 120, 68, - 7, 1, 0, 3, 120, 30, 8, 1, 0, 3, 120, 68, - 1, 1, 0, 3, 124, 70, 3, 1, 0, 3, 124, 127, - 4, 1, 0, 3, 124, 64, 5, 1, 0, 3, 124, 127, - 6, 1, 0, 3, 124, 68, 7, 1, 0, 3, 124, 30, - 8, 1, 0, 3, 124, 68, 1, 1, 0, 3, 128, 70, - 3, 1, 0, 3, 128, 127, 4, 1, 0, 3, 128, 64, - 5, 1, 0, 3, 128, 127, 6, 1, 0, 3, 128, 68, - 7, 1, 0, 3, 128, 30, 8, 1, 0, 3, 128, 68, - 1, 1, 0, 3, 132, 70, 3, 1, 0, 3, 132, 68, - 4, 1, 0, 3, 132, 64, 5, 1, 0, 3, 132, 38, - 6, 1, 0, 3, 132, 68, 7, 1, 0, 3, 132, 30, - 8, 1, 0, 3, 132, 68, 1, 1, 0, 3, 136, 70, - 3, 1, 0, 3, 136, 68, 4, 1, 0, 3, 136, 64, - 5, 1, 0, 3, 136, 38, 6, 1, 0, 3, 136, 68, - 7, 1, 0, 3, 136, 127, 8, 1, 0, 3, 136, 68, - 1, 1, 0, 3, 140, 70, 3, 1, 0, 3, 140, 60, - 4, 1, 0, 3, 140, 64, 5, 1, 0, 3, 140, 38, - 6, 1, 0, 3, 140, 60, 7, 1, 0, 3, 140, 127, - 8, 1, 0, 3, 140, 60, 1, 1, 0, 3, 144, 127, - 3, 1, 0, 3, 144, 68, 4, 1, 0, 3, 144, 64, - 5, 1, 0, 3, 144, 127, 6, 1, 0, 3, 144, 68, - 7, 1, 0, 3, 144, 127, 8, 1, 0, 3, 144, 68, - 1, 1, 0, 3, 149, 127, 3, 1, 0, 3, 149, 76, - 4, 1, 0, 3, 149, 60, 5, 1, 0, 3, 149, 76, - 6, 1, 0, 3, 149, 76, 7, 1, 0, 3, 149, 30, - 8, 1, 0, 3, 149, 72, 1, 1, 0, 3, 153, 127, - 3, 1, 0, 3, 153, 76, 4, 1, 0, 3, 153, 60, - 5, 1, 0, 3, 153, 76, 6, 1, 0, 3, 153, 76, - 7, 1, 0, 3, 153, 30, 8, 1, 0, 3, 153, 76, - 1, 1, 0, 3, 157, 127, 3, 1, 0, 3, 157, 76, - 4, 1, 0, 3, 157, 60, 5, 1, 0, 3, 157, 76, - 6, 1, 0, 3, 157, 76, 7, 1, 0, 3, 157, 30, - 8, 1, 0, 3, 157, 76, 1, 1, 0, 3, 161, 127, - 3, 1, 0, 3, 161, 76, 4, 1, 0, 3, 161, 60, - 5, 1, 0, 3, 161, 76, 6, 1, 0, 3, 161, 76, - 7, 1, 0, 3, 161, 30, 8, 1, 0, 3, 161, 76, - 1, 1, 0, 3, 165, 127, 3, 1, 0, 3, 165, 76, - 4, 1, 0, 3, 165, 60, 5, 1, 0, 3, 165, 76, - 6, 1, 0, 3, 165, 76, 7, 1, 0, 3, 165, 30, - 8, 1, 0, 3, 165, 76, 1, 1, 1, 2, 38, 62, - 3, 1, 1, 2, 38, 64, 4, 1, 1, 2, 38, 72, - 5, 1, 1, 2, 38, 64, 6, 1, 1, 2, 38, 64, - 7, 1, 1, 2, 38, 54, 8, 1, 1, 2, 38, 62, - 1, 1, 1, 2, 46, 62, 3, 1, 1, 2, 46, 64, - 4, 1, 1, 2, 46, 72, 5, 1, 1, 2, 46, 64, - 6, 1, 1, 2, 46, 64, 7, 1, 1, 2, 46, 54, - 8, 1, 1, 2, 46, 62, 1, 1, 1, 2, 54, 62, - 3, 1, 1, 2, 54, 64, 4, 1, 1, 2, 54, 72, - 5, 1, 1, 2, 54, 64, 6, 1, 1, 2, 54, 72, - 7, 1, 1, 2, 54, 54, 8, 1, 1, 2, 54, 72, - 1, 1, 1, 2, 62, 62, 3, 1, 1, 2, 62, 64, - 4, 1, 1, 2, 62, 70, 5, 1, 1, 2, 62, 64, - 6, 1, 1, 2, 62, 64, 7, 1, 1, 2, 62, 54, - 8, 1, 1, 2, 62, 64, 1, 1, 1, 2, 102, 72, - 3, 1, 1, 2, 102, 58, 4, 1, 1, 2, 102, 72, - 5, 1, 1, 2, 102, 64, 6, 1, 1, 2, 102, 58, - 7, 1, 1, 2, 102, 54, 8, 1, 1, 2, 102, 58, - 1, 1, 1, 2, 110, 72, 3, 1, 1, 2, 110, 72, - 4, 1, 1, 2, 110, 72, 5, 1, 1, 2, 110, 64, - 6, 1, 1, 2, 110, 72, 7, 1, 1, 2, 110, 54, - 8, 1, 1, 2, 110, 72, 1, 1, 1, 2, 118, 72, - 3, 1, 1, 2, 118, 127, 4, 1, 1, 2, 118, 72, - 5, 1, 1, 2, 118, 127, 6, 1, 1, 2, 118, 72, - 7, 1, 1, 2, 118, 54, 8, 1, 1, 2, 118, 72, - 1, 1, 1, 2, 126, 72, 3, 1, 1, 2, 126, 127, - 4, 1, 1, 2, 126, 72, 5, 1, 1, 2, 126, 127, - 6, 1, 1, 2, 126, 72, 7, 1, 1, 2, 126, 54, - 8, 1, 1, 2, 126, 72, 1, 1, 1, 2, 134, 72, - 3, 1, 1, 2, 134, 72, 4, 1, 1, 2, 134, 72, - 5, 1, 1, 2, 134, 64, 6, 1, 1, 2, 134, 72, - 7, 1, 1, 2, 134, 127, 8, 1, 1, 2, 134, 72, - 1, 1, 1, 2, 142, 127, 3, 1, 1, 2, 142, 72, - 4, 1, 1, 2, 142, 72, 5, 1, 1, 2, 142, 127, - 6, 1, 1, 2, 142, 72, 7, 1, 1, 2, 142, 127, - 8, 1, 1, 2, 142, 72, 1, 1, 1, 2, 151, 127, - 3, 1, 1, 2, 151, 72, 4, 1, 1, 2, 151, 72, - 5, 1, 1, 2, 151, 72, 6, 1, 1, 2, 151, 72, - 7, 1, 1, 2, 151, 54, 8, 1, 1, 2, 151, 72, - 1, 1, 1, 2, 159, 127, 3, 1, 1, 2, 159, 72, - 4, 1, 1, 2, 159, 72, 5, 1, 1, 2, 159, 72, - 6, 1, 1, 2, 159, 72, 7, 1, 1, 2, 159, 54, - 8, 1, 1, 2, 159, 72, 1, 1, 1, 3, 38, 50, - 3, 1, 1, 3, 38, 40, 4, 1, 1, 3, 38, 62, - 5, 1, 1, 3, 38, 40, 6, 1, 1, 3, 38, 52, - 7, 1, 1, 3, 38, 30, 8, 1, 1, 3, 38, 50, - 1, 1, 1, 3, 46, 50, 3, 1, 1, 3, 46, 40, - 4, 1, 1, 3, 46, 62, 5, 1, 1, 3, 46, 40, - 6, 1, 1, 3, 46, 52, 7, 1, 1, 3, 46, 30, - 8, 1, 1, 3, 46, 50, 1, 1, 1, 3, 54, 50, - 3, 1, 1, 3, 54, 40, 4, 1, 1, 3, 54, 62, - 5, 1, 1, 3, 54, 40, 6, 1, 1, 3, 54, 68, - 7, 1, 1, 3, 54, 30, 8, 1, 1, 3, 54, 68, - 1, 1, 1, 3, 62, 48, 3, 1, 1, 3, 62, 40, - 4, 1, 1, 3, 62, 58, 5, 1, 1, 3, 62, 40, - 6, 1, 1, 3, 62, 58, 7, 1, 1, 3, 62, 30, - 8, 1, 1, 3, 62, 58, 1, 1, 1, 3, 102, 70, - 3, 1, 1, 3, 102, 54, 4, 1, 1, 3, 102, 64, - 5, 1, 1, 3, 102, 40, 6, 1, 1, 3, 102, 54, - 7, 1, 1, 3, 102, 30, 8, 1, 1, 3, 102, 54, - 1, 1, 1, 3, 110, 70, 3, 1, 1, 3, 110, 68, - 4, 1, 1, 3, 110, 64, 5, 1, 1, 3, 110, 40, - 6, 1, 1, 3, 110, 68, 7, 1, 1, 3, 110, 30, - 8, 1, 1, 3, 110, 68, 1, 1, 1, 3, 118, 70, - 3, 1, 1, 3, 118, 127, 4, 1, 1, 3, 118, 64, - 5, 1, 1, 3, 118, 127, 6, 1, 1, 3, 118, 68, - 7, 1, 1, 3, 118, 30, 8, 1, 1, 3, 118, 68, - 1, 1, 1, 3, 126, 70, 3, 1, 1, 3, 126, 127, - 4, 1, 1, 3, 126, 64, 5, 1, 1, 3, 126, 127, - 6, 1, 1, 3, 126, 68, 7, 1, 1, 3, 126, 30, - 8, 1, 1, 3, 126, 68, 1, 1, 1, 3, 134, 70, - 3, 1, 1, 3, 134, 68, 4, 1, 1, 3, 134, 64, - 5, 1, 1, 3, 134, 40, 6, 1, 1, 3, 134, 68, - 7, 1, 1, 3, 134, 127, 8, 1, 1, 3, 134, 68, - 1, 1, 1, 3, 142, 127, 3, 1, 1, 3, 142, 68, - 4, 1, 1, 3, 142, 64, 5, 1, 1, 3, 142, 127, - 6, 1, 1, 3, 142, 68, 7, 1, 1, 3, 142, 127, - 8, 1, 1, 3, 142, 68, 1, 1, 1, 3, 151, 127, - 3, 1, 1, 3, 151, 72, 4, 1, 1, 3, 151, 66, - 5, 1, 1, 3, 151, 72, 6, 1, 1, 3, 151, 72, - 7, 1, 1, 3, 151, 30, 8, 1, 1, 3, 151, 68, - 1, 1, 1, 3, 159, 127, 3, 1, 1, 3, 159, 72, - 4, 1, 1, 3, 159, 66, 5, 1, 1, 3, 159, 72, - 6, 1, 1, 3, 159, 72, 7, 1, 1, 3, 159, 30, - 8, 1, 1, 3, 159, 72, 1, 1, 2, 4, 42, 64, - 3, 1, 2, 4, 42, 64, 4, 1, 2, 4, 42, 68, - 5, 1, 2, 4, 42, 64, 6, 1, 2, 4, 42, 64, - 7, 1, 2, 4, 42, 54, 8, 1, 2, 4, 42, 62, - 1, 1, 2, 4, 58, 64, 3, 1, 2, 4, 58, 62, - 4, 1, 2, 4, 58, 64, 5, 1, 2, 4, 58, 64, - 6, 1, 2, 4, 58, 62, 7, 1, 2, 4, 58, 54, - 8, 1, 2, 4, 58, 62, 1, 1, 2, 4, 106, 72, - 3, 1, 2, 4, 106, 58, 4, 1, 2, 4, 106, 66, - 5, 1, 2, 4, 106, 64, 6, 1, 2, 4, 106, 58, - 7, 1, 2, 4, 106, 54, 8, 1, 2, 4, 106, 58, - 1, 1, 2, 4, 122, 72, 3, 1, 2, 4, 122, 127, - 4, 1, 2, 4, 122, 68, 5, 1, 2, 4, 122, 127, - 6, 1, 2, 4, 122, 72, 7, 1, 2, 4, 122, 54, - 8, 1, 2, 4, 122, 72, 1, 1, 2, 4, 138, 127, - 3, 1, 2, 4, 138, 72, 4, 1, 2, 4, 138, 68, - 5, 1, 2, 4, 138, 127, 6, 1, 2, 4, 138, 72, - 7, 1, 2, 4, 138, 127, 8, 1, 2, 4, 138, 72, - 1, 1, 2, 4, 155, 127, 3, 1, 2, 4, 155, 72, - 4, 1, 2, 4, 155, 68, 5, 1, 2, 4, 155, 72, - 6, 1, 2, 4, 155, 72, 7, 1, 2, 4, 155, 54, - 8, 1, 2, 4, 155, 68, 1, 1, 2, 5, 42, 50, - 3, 1, 2, 5, 42, 40, 4, 1, 2, 5, 42, 58, - 5, 1, 2, 5, 42, 40, 6, 1, 2, 5, 42, 52, - 7, 1, 2, 5, 42, 30, 8, 1, 2, 5, 42, 50, - 1, 1, 2, 5, 58, 50, 3, 1, 2, 5, 58, 40, - 4, 1, 2, 5, 58, 56, 5, 1, 2, 5, 58, 40, - 6, 1, 2, 5, 58, 52, 7, 1, 2, 5, 58, 30, - 8, 1, 2, 5, 58, 52, 1, 1, 2, 5, 106, 72, - 3, 1, 2, 5, 106, 50, 4, 1, 2, 5, 106, 56, - 5, 1, 2, 5, 106, 40, 6, 1, 2, 5, 106, 50, - 7, 1, 2, 5, 106, 30, 8, 1, 2, 5, 106, 50, - 1, 1, 2, 5, 122, 72, 3, 1, 2, 5, 122, 127, - 4, 1, 2, 5, 122, 56, 5, 1, 2, 5, 122, 127, - 6, 1, 2, 5, 122, 66, 7, 1, 2, 5, 122, 30, - 8, 1, 2, 5, 122, 66, 1, 1, 2, 5, 138, 127, - 3, 1, 2, 5, 138, 66, 4, 1, 2, 5, 138, 58, - 5, 1, 2, 5, 138, 127, 6, 1, 2, 5, 138, 66, - 7, 1, 2, 5, 138, 127, 8, 1, 2, 5, 138, 66, - 1, 1, 2, 5, 155, 127, 3, 1, 2, 5, 155, 62, - 4, 1, 2, 5, 155, 58, 5, 1, 2, 5, 155, 72, - 6, 1, 2, 5, 155, 62, 7, 1, 2, 5, 155, 30, - 8, 1, 2, 5, 155, 62 +static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { + { 0, 0, 0, 0, 1, 72, }, + { 2, 0, 0, 0, 1, 60, }, + { 0, 0, 0, 0, 2, 72, }, + { 2, 0, 0, 0, 2, 60, }, + { 0, 0, 0, 0, 3, 76, }, + { 2, 0, 0, 0, 3, 60, }, + { 0, 0, 0, 0, 4, 76, }, + { 2, 0, 0, 0, 4, 60, }, + { 0, 0, 0, 0, 5, 76, }, + { 2, 0, 0, 0, 5, 60, }, + { 0, 0, 0, 0, 6, 76, }, + { 2, 0, 0, 0, 6, 60, }, + { 0, 0, 0, 0, 7, 76, }, + { 2, 0, 0, 0, 7, 60, }, + { 0, 0, 0, 0, 8, 76, }, + { 2, 0, 0, 0, 8, 60, }, + { 0, 0, 0, 0, 9, 76, }, + { 2, 0, 0, 0, 9, 60, }, + { 0, 0, 0, 0, 10, 72, }, + { 2, 0, 0, 0, 10, 60, }, + { 0, 0, 0, 0, 11, 72, }, + { 2, 0, 0, 0, 11, 60, }, + { 0, 0, 0, 0, 12, 52, }, + { 2, 0, 0, 0, 12, 60, }, + { 0, 0, 0, 0, 13, 48, }, + { 2, 0, 0, 0, 13, 60, }, + { 0, 0, 0, 0, 14, 127, }, + { 2, 0, 0, 0, 14, 127, }, + { 0, 0, 0, 1, 1, 52, }, + { 2, 0, 0, 1, 1, 60, }, + { 0, 0, 0, 1, 2, 60, }, + { 2, 0, 0, 1, 2, 60, }, + { 0, 0, 0, 1, 3, 64, }, + { 2, 0, 0, 1, 3, 60, }, + { 0, 0, 0, 1, 4, 68, }, + { 2, 0, 0, 1, 4, 60, }, + { 0, 0, 0, 1, 5, 76, }, + { 2, 0, 0, 1, 5, 60, }, + { 0, 0, 0, 1, 6, 76, }, + { 2, 0, 0, 1, 6, 60, }, + { 0, 0, 0, 1, 7, 76, }, + { 2, 0, 0, 1, 7, 60, }, + { 0, 0, 0, 1, 8, 68, }, + { 2, 0, 0, 1, 8, 60, }, + { 0, 0, 0, 1, 9, 64, }, + { 2, 0, 0, 1, 9, 60, }, + { 0, 0, 0, 1, 10, 60, }, + { 2, 0, 0, 1, 10, 60, }, + { 0, 0, 0, 1, 11, 52, }, + { 2, 0, 0, 1, 11, 60, }, + { 0, 0, 0, 1, 12, 40, }, + { 2, 0, 0, 1, 12, 60, }, + { 0, 0, 0, 1, 13, 28, }, + { 2, 0, 0, 1, 13, 60, }, + { 0, 0, 0, 1, 14, 127, }, + { 2, 0, 0, 1, 14, 127, }, + { 0, 0, 0, 2, 1, 52, }, + { 2, 0, 0, 2, 1, 60, }, + { 0, 0, 0, 2, 2, 60, }, + { 2, 0, 0, 2, 2, 60, }, + { 0, 0, 0, 2, 3, 64, }, + { 2, 0, 0, 2, 3, 60, }, + { 0, 0, 0, 2, 4, 68, }, + { 2, 0, 0, 2, 4, 60, }, + { 0, 0, 0, 2, 5, 76, }, + { 2, 0, 0, 2, 5, 60, }, + { 0, 0, 0, 2, 6, 76, }, + { 2, 0, 0, 2, 6, 60, }, + { 0, 0, 0, 2, 7, 76, }, + { 2, 0, 0, 2, 7, 60, }, + { 0, 0, 0, 2, 8, 68, }, + { 2, 0, 0, 2, 8, 60, }, + { 0, 0, 0, 2, 9, 64, }, + { 2, 0, 0, 2, 9, 60, }, + { 0, 0, 0, 2, 10, 60, }, + { 2, 0, 0, 2, 10, 60, }, + { 0, 0, 0, 2, 11, 52, }, + { 2, 0, 0, 2, 11, 60, }, + { 0, 0, 0, 2, 12, 40, }, + { 2, 0, 0, 2, 12, 60, }, + { 0, 0, 0, 2, 13, 28, }, + { 2, 0, 0, 2, 13, 60, }, + { 0, 0, 0, 2, 14, 127, }, + { 2, 0, 0, 2, 14, 127, }, + { 0, 0, 0, 3, 1, 52, }, + { 2, 0, 0, 3, 1, 36, }, + { 0, 0, 0, 3, 2, 60, }, + { 2, 0, 0, 3, 2, 36, }, + { 0, 0, 0, 3, 3, 64, }, + { 2, 0, 0, 3, 3, 36, }, + { 0, 0, 0, 3, 4, 68, }, + { 2, 0, 0, 3, 4, 36, }, + { 0, 0, 0, 3, 5, 76, }, + { 2, 0, 0, 3, 5, 36, }, + { 0, 0, 0, 3, 6, 76, }, + { 2, 0, 0, 3, 6, 36, }, + { 0, 0, 0, 3, 7, 76, }, + { 2, 0, 0, 3, 7, 36, }, + { 0, 0, 0, 3, 8, 68, }, + { 2, 0, 0, 3, 8, 36, }, + { 0, 0, 0, 3, 9, 64, }, + { 2, 0, 0, 3, 9, 36, }, + { 0, 0, 0, 3, 10, 60, }, + { 2, 0, 0, 3, 10, 36, }, + { 0, 0, 0, 3, 11, 52, }, + { 2, 0, 0, 3, 11, 36, }, + { 0, 0, 0, 3, 12, 40, }, + { 2, 0, 0, 3, 12, 36, }, + { 0, 0, 0, 3, 13, 28, }, + { 2, 0, 0, 3, 13, 36, }, + { 0, 0, 0, 3, 14, 127, }, + { 2, 0, 0, 3, 14, 127, }, + { 0, 0, 1, 2, 1, 127, }, + { 2, 0, 1, 2, 1, 127, }, + { 0, 0, 1, 2, 2, 127, }, + { 2, 0, 1, 2, 2, 127, }, + { 0, 0, 1, 2, 3, 52, }, + { 2, 0, 1, 2, 3, 60, }, + { 0, 0, 1, 2, 4, 52, }, + { 2, 0, 1, 2, 4, 60, }, + { 0, 0, 1, 2, 5, 60, }, + { 2, 0, 1, 2, 5, 60, }, + { 0, 0, 1, 2, 6, 64, }, + { 2, 0, 1, 2, 6, 60, }, + { 0, 0, 1, 2, 7, 60, }, + { 2, 0, 1, 2, 7, 60, }, + { 0, 0, 1, 2, 8, 52, }, + { 2, 0, 1, 2, 8, 60, }, + { 0, 0, 1, 2, 9, 52, }, + { 2, 0, 1, 2, 9, 60, }, + { 0, 0, 1, 2, 10, 40, }, + { 2, 0, 1, 2, 10, 60, }, + { 0, 0, 1, 2, 11, 28, }, + { 2, 0, 1, 2, 11, 60, }, + { 0, 0, 1, 2, 12, 127, }, + { 2, 0, 1, 2, 12, 127, }, + { 0, 0, 1, 2, 13, 127, }, + { 2, 0, 1, 2, 13, 127, }, + { 0, 0, 1, 2, 14, 127, }, + { 2, 0, 1, 2, 14, 127, }, + { 0, 0, 1, 3, 1, 127, }, + { 2, 0, 1, 3, 1, 127, }, + { 0, 0, 1, 3, 2, 127, }, + { 2, 0, 1, 3, 2, 127, }, + { 0, 0, 1, 3, 3, 48, }, + { 2, 0, 1, 3, 3, 36, }, + { 0, 0, 1, 3, 4, 48, }, + { 2, 0, 1, 3, 4, 36, }, + { 0, 0, 1, 3, 5, 60, }, + { 2, 0, 1, 3, 5, 36, }, + { 0, 0, 1, 3, 6, 64, }, + { 2, 0, 1, 3, 6, 36, }, + { 0, 0, 1, 3, 7, 60, }, + { 2, 0, 1, 3, 7, 36, }, + { 0, 0, 1, 3, 8, 52, }, + { 2, 0, 1, 3, 8, 36, }, + { 0, 0, 1, 3, 9, 52, }, + { 2, 0, 1, 3, 9, 36, }, + { 0, 0, 1, 3, 10, 40, }, + { 2, 0, 1, 3, 10, 36, }, + { 0, 0, 1, 3, 11, 26, }, + { 2, 0, 1, 3, 11, 36, }, + { 0, 0, 1, 3, 12, 127, }, + { 2, 0, 1, 3, 12, 127, }, + { 0, 0, 1, 3, 13, 127, }, + { 2, 0, 1, 3, 13, 127, }, + { 0, 0, 1, 3, 14, 127, }, + { 2, 0, 1, 3, 14, 127, }, + { 0, 1, 0, 1, 36, 74, }, + { 2, 1, 0, 1, 36, 62, }, + { 0, 1, 0, 1, 40, 76, }, + { 2, 1, 0, 1, 40, 62, }, + { 0, 1, 0, 1, 44, 76, }, + { 2, 1, 0, 1, 44, 62, }, + { 0, 1, 0, 1, 48, 76, }, + { 2, 1, 0, 1, 48, 62, }, + { 0, 1, 0, 1, 52, 76, }, + { 2, 1, 0, 1, 52, 62, }, + { 0, 1, 0, 1, 56, 76, }, + { 2, 1, 0, 1, 56, 62, }, + { 0, 1, 0, 1, 60, 76, }, + { 2, 1, 0, 1, 60, 62, }, + { 0, 1, 0, 1, 64, 74, }, + { 2, 1, 0, 1, 64, 62, }, + { 0, 1, 0, 1, 100, 72, }, + { 2, 1, 0, 1, 100, 62, }, + { 0, 1, 0, 1, 104, 76, }, + { 2, 1, 0, 1, 104, 62, }, + { 0, 1, 0, 1, 108, 76, }, + { 2, 1, 0, 1, 108, 62, }, + { 0, 1, 0, 1, 112, 76, }, + { 2, 1, 0, 1, 112, 62, }, + { 0, 1, 0, 1, 116, 76, }, + { 2, 1, 0, 1, 116, 62, }, + { 0, 1, 0, 1, 120, 76, }, + { 2, 1, 0, 1, 120, 62, }, + { 0, 1, 0, 1, 124, 76, }, + { 2, 1, 0, 1, 124, 62, }, + { 0, 1, 0, 1, 128, 76, }, + { 2, 1, 0, 1, 128, 62, }, + { 0, 1, 0, 1, 132, 76, }, + { 2, 1, 0, 1, 132, 62, }, + { 0, 1, 0, 1, 136, 76, }, + { 2, 1, 0, 1, 136, 62, }, + { 0, 1, 0, 1, 140, 72, }, + { 2, 1, 0, 1, 140, 62, }, + { 0, 1, 0, 1, 144, 76, }, + { 2, 1, 0, 1, 144, 127, }, + { 0, 1, 0, 1, 149, 76, }, + { 2, 1, 0, 1, 149, -128, }, + { 0, 1, 0, 1, 153, 76, }, + { 2, 1, 0, 1, 153, -128, }, + { 0, 1, 0, 1, 157, 76, }, + { 2, 1, 0, 1, 157, -128, }, + { 0, 1, 0, 1, 161, 76, }, + { 2, 1, 0, 1, 161, -128, }, + { 0, 1, 0, 1, 165, 76, }, + { 2, 1, 0, 1, 165, -128, }, + { 0, 1, 0, 2, 36, 72, }, + { 2, 1, 0, 2, 36, 62, }, + { 0, 1, 0, 2, 40, 76, }, + { 2, 1, 0, 2, 40, 62, }, + { 0, 1, 0, 2, 44, 76, }, + { 2, 1, 0, 2, 44, 62, }, + { 0, 1, 0, 2, 48, 76, }, + { 2, 1, 0, 2, 48, 62, }, + { 0, 1, 0, 2, 52, 76, }, + { 2, 1, 0, 2, 52, 62, }, + { 0, 1, 0, 2, 56, 76, }, + { 2, 1, 0, 2, 56, 62, }, + { 0, 1, 0, 2, 60, 76, }, + { 2, 1, 0, 2, 60, 62, }, + { 0, 1, 0, 2, 64, 74, }, + { 2, 1, 0, 2, 64, 62, }, + { 0, 1, 0, 2, 100, 70, }, + { 2, 1, 0, 2, 100, 62, }, + { 0, 1, 0, 2, 104, 76, }, + { 2, 1, 0, 2, 104, 62, }, + { 0, 1, 0, 2, 108, 76, }, + { 2, 1, 0, 2, 108, 62, }, + { 0, 1, 0, 2, 112, 76, }, + { 2, 1, 0, 2, 112, 62, }, + { 0, 1, 0, 2, 116, 76, }, + { 2, 1, 0, 2, 116, 62, }, + { 0, 1, 0, 2, 120, 76, }, + { 2, 1, 0, 2, 120, 62, }, + { 0, 1, 0, 2, 124, 76, }, + { 2, 1, 0, 2, 124, 62, }, + { 0, 1, 0, 2, 128, 76, }, + { 2, 1, 0, 2, 128, 62, }, + { 0, 1, 0, 2, 132, 76, }, + { 2, 1, 0, 2, 132, 62, }, + { 0, 1, 0, 2, 136, 76, }, + { 2, 1, 0, 2, 136, 62, }, + { 0, 1, 0, 2, 140, 70, }, + { 2, 1, 0, 2, 140, 62, }, + { 0, 1, 0, 2, 144, 76, }, + { 2, 1, 0, 2, 144, 127, }, + { 0, 1, 0, 2, 149, 76, }, + { 2, 1, 0, 2, 149, -128, }, + { 0, 1, 0, 2, 153, 76, }, + { 2, 1, 0, 2, 153, -128, }, + { 0, 1, 0, 2, 157, 76, }, + { 2, 1, 0, 2, 157, -128, }, + { 0, 1, 0, 2, 161, 76, }, + { 2, 1, 0, 2, 161, -128, }, + { 0, 1, 0, 2, 165, 76, }, + { 2, 1, 0, 2, 165, -128, }, + { 0, 1, 0, 3, 36, 68, }, + { 2, 1, 0, 3, 36, 38, }, + { 0, 1, 0, 3, 40, 68, }, + { 2, 1, 0, 3, 40, 38, }, + { 0, 1, 0, 3, 44, 68, }, + { 2, 1, 0, 3, 44, 38, }, + { 0, 1, 0, 3, 48, 68, }, + { 2, 1, 0, 3, 48, 38, }, + { 0, 1, 0, 3, 52, 68, }, + { 2, 1, 0, 3, 52, 38, }, + { 0, 1, 0, 3, 56, 68, }, + { 2, 1, 0, 3, 56, 38, }, + { 0, 1, 0, 3, 60, 66, }, + { 2, 1, 0, 3, 60, 38, }, + { 0, 1, 0, 3, 64, 68, }, + { 2, 1, 0, 3, 64, 38, }, + { 0, 1, 0, 3, 100, 60, }, + { 2, 1, 0, 3, 100, 38, }, + { 0, 1, 0, 3, 104, 68, }, + { 2, 1, 0, 3, 104, 38, }, + { 0, 1, 0, 3, 108, 68, }, + { 2, 1, 0, 3, 108, 38, }, + { 0, 1, 0, 3, 112, 68, }, + { 2, 1, 0, 3, 112, 38, }, + { 0, 1, 0, 3, 116, 68, }, + { 2, 1, 0, 3, 116, 38, }, + { 0, 1, 0, 3, 120, 68, }, + { 2, 1, 0, 3, 120, 38, }, + { 0, 1, 0, 3, 124, 68, }, + { 2, 1, 0, 3, 124, 38, }, + { 0, 1, 0, 3, 128, 68, }, + { 2, 1, 0, 3, 128, 38, }, + { 0, 1, 0, 3, 132, 68, }, + { 2, 1, 0, 3, 132, 38, }, + { 0, 1, 0, 3, 136, 68, }, + { 2, 1, 0, 3, 136, 38, }, + { 0, 1, 0, 3, 140, 60, }, + { 2, 1, 0, 3, 140, 38, }, + { 0, 1, 0, 3, 144, 68, }, + { 2, 1, 0, 3, 144, 127, }, + { 0, 1, 0, 3, 149, 76, }, + { 2, 1, 0, 3, 149, -128, }, + { 0, 1, 0, 3, 153, 76, }, + { 2, 1, 0, 3, 153, -128, }, + { 0, 1, 0, 3, 157, 76, }, + { 2, 1, 0, 3, 157, -128, }, + { 0, 1, 0, 3, 161, 76, }, + { 2, 1, 0, 3, 161, -128, }, + { 0, 1, 0, 3, 165, 76, }, + { 2, 1, 0, 3, 165, -128, }, + { 0, 1, 1, 2, 38, 66, }, + { 2, 1, 1, 2, 38, 64, }, + { 0, 1, 1, 2, 46, 72, }, + { 2, 1, 1, 2, 46, 64, }, + { 0, 1, 1, 2, 54, 72, }, + { 2, 1, 1, 2, 54, 64, }, + { 0, 1, 1, 2, 62, 64, }, + { 2, 1, 1, 2, 62, 64, }, + { 0, 1, 1, 2, 102, 58, }, + { 2, 1, 1, 2, 102, 64, }, + { 0, 1, 1, 2, 110, 72, }, + { 2, 1, 1, 2, 110, 64, }, + { 0, 1, 1, 2, 118, 72, }, + { 2, 1, 1, 2, 118, 64, }, + { 0, 1, 1, 2, 126, 72, }, + { 2, 1, 1, 2, 126, 64, }, + { 0, 1, 1, 2, 134, 72, }, + { 2, 1, 1, 2, 134, 64, }, + { 0, 1, 1, 2, 142, 72, }, + { 2, 1, 1, 2, 142, 127, }, + { 0, 1, 1, 2, 151, 72, }, + { 2, 1, 1, 2, 151, -128, }, + { 0, 1, 1, 2, 159, 72, }, + { 2, 1, 1, 2, 159, -128, }, + { 0, 1, 1, 3, 38, 60, }, + { 2, 1, 1, 3, 38, 40, }, + { 0, 1, 1, 3, 46, 68, }, + { 2, 1, 1, 3, 46, 40, }, + { 0, 1, 1, 3, 54, 68, }, + { 2, 1, 1, 3, 54, 40, }, + { 0, 1, 1, 3, 62, 58, }, + { 2, 1, 1, 3, 62, 40, }, + { 0, 1, 1, 3, 102, 54, }, + { 2, 1, 1, 3, 102, 40, }, + { 0, 1, 1, 3, 110, 68, }, + { 2, 1, 1, 3, 110, 40, }, + { 0, 1, 1, 3, 118, 68, }, + { 2, 1, 1, 3, 118, 40, }, + { 0, 1, 1, 3, 126, 68, }, + { 2, 1, 1, 3, 126, 40, }, + { 0, 1, 1, 3, 134, 68, }, + { 2, 1, 1, 3, 134, 40, }, + { 0, 1, 1, 3, 142, 68, }, + { 2, 1, 1, 3, 142, 127, }, + { 0, 1, 1, 3, 151, 72, }, + { 2, 1, 1, 3, 151, -128, }, + { 0, 1, 1, 3, 159, 72, }, + { 2, 1, 1, 3, 159, -128, }, + { 0, 1, 2, 4, 42, 64, }, + { 2, 1, 2, 4, 42, 64, }, + { 0, 1, 2, 4, 58, 62, }, + { 2, 1, 2, 4, 58, 64, }, + { 0, 1, 2, 4, 106, 58, }, + { 2, 1, 2, 4, 106, 64, }, + { 0, 1, 2, 4, 122, 72, }, + { 2, 1, 2, 4, 122, 64, }, + { 0, 1, 2, 4, 138, 72, }, + { 2, 1, 2, 4, 138, 127, }, + { 0, 1, 2, 4, 155, 72, }, + { 2, 1, 2, 4, 155, -128, }, + { 0, 1, 2, 5, 42, 54, }, + { 2, 1, 2, 5, 42, 40, }, + { 0, 1, 2, 5, 58, 52, }, + { 2, 1, 2, 5, 58, 40, }, + { 0, 1, 2, 5, 106, 50, }, + { 2, 1, 2, 5, 106, 40, }, + { 0, 1, 2, 5, 122, 66, }, + { 2, 1, 2, 5, 122, 40, }, + { 0, 1, 2, 5, 138, 66, }, + { 2, 1, 2, 5, 138, 127, }, + { 0, 1, 2, 5, 155, 62, }, + { 2, 1, 2, 5, 155, -128, }, + { 1, 0, 0, 0, 1, 68, }, + { 3, 0, 0, 0, 1, 72, }, + { 4, 0, 0, 0, 1, 76, }, + { 5, 0, 0, 0, 1, 60, }, + { 6, 0, 0, 0, 1, 72, }, + { 7, 0, 0, 0, 1, 60, }, + { 8, 0, 0, 0, 1, 72, }, + { 1, 0, 0, 0, 2, 68, }, + { 3, 0, 0, 0, 2, 72, }, + { 4, 0, 0, 0, 2, 76, }, + { 5, 0, 0, 0, 2, 60, }, + { 6, 0, 0, 0, 2, 72, }, + { 7, 0, 0, 0, 2, 60, }, + { 8, 0, 0, 0, 2, 72, }, + { 1, 0, 0, 0, 3, 68, }, + { 3, 0, 0, 0, 3, 76, }, + { 4, 0, 0, 0, 3, 76, }, + { 5, 0, 0, 0, 3, 60, }, + { 6, 0, 0, 0, 3, 76, }, + { 7, 0, 0, 0, 3, 60, }, + { 8, 0, 0, 0, 3, 76, }, + { 1, 0, 0, 0, 4, 68, }, + { 3, 0, 0, 0, 4, 76, }, + { 4, 0, 0, 0, 4, 76, }, + { 5, 0, 0, 0, 4, 60, }, + { 6, 0, 0, 0, 4, 76, }, + { 7, 0, 0, 0, 4, 60, }, + { 8, 0, 0, 0, 4, 76, }, + { 1, 0, 0, 0, 5, 68, }, + { 3, 0, 0, 0, 5, 76, }, + { 4, 0, 0, 0, 5, 76, }, + { 5, 0, 0, 0, 5, 60, }, + { 6, 0, 0, 0, 5, 76, }, + { 7, 0, 0, 0, 5, 60, }, + { 8, 0, 0, 0, 5, 76, }, + { 1, 0, 0, 0, 6, 68, }, + { 3, 0, 0, 0, 6, 76, }, + { 4, 0, 0, 0, 6, 76, }, + { 5, 0, 0, 0, 6, 60, }, + { 6, 0, 0, 0, 6, 76, }, + { 7, 0, 0, 0, 6, 60, }, + { 8, 0, 0, 0, 6, 76, }, + { 1, 0, 0, 0, 7, 68, }, + { 3, 0, 0, 0, 7, 76, }, + { 4, 0, 0, 0, 7, 76, }, + { 5, 0, 0, 0, 7, 60, }, + { 6, 0, 0, 0, 7, 76, }, + { 7, 0, 0, 0, 7, 60, }, + { 8, 0, 0, 0, 7, 76, }, + { 1, 0, 0, 0, 8, 68, }, + { 3, 0, 0, 0, 8, 76, }, + { 4, 0, 0, 0, 8, 76, }, + { 5, 0, 0, 0, 8, 60, }, + { 6, 0, 0, 0, 8, 76, }, + { 7, 0, 0, 0, 8, 60, }, + { 8, 0, 0, 0, 8, 76, }, + { 1, 0, 0, 0, 9, 68, }, + { 3, 0, 0, 0, 9, 76, }, + { 4, 0, 0, 0, 9, 76, }, + { 5, 0, 0, 0, 9, 60, }, + { 6, 0, 0, 0, 9, 76, }, + { 7, 0, 0, 0, 9, 60, }, + { 8, 0, 0, 0, 9, 76, }, + { 1, 0, 0, 0, 10, 68, }, + { 3, 0, 0, 0, 10, 72, }, + { 4, 0, 0, 0, 10, 76, }, + { 5, 0, 0, 0, 10, 60, }, + { 6, 0, 0, 0, 10, 72, }, + { 7, 0, 0, 0, 10, 60, }, + { 8, 0, 0, 0, 10, 72, }, + { 1, 0, 0, 0, 11, 68, }, + { 3, 0, 0, 0, 11, 72, }, + { 4, 0, 0, 0, 11, 76, }, + { 5, 0, 0, 0, 11, 60, }, + { 6, 0, 0, 0, 11, 72, }, + { 7, 0, 0, 0, 11, 60, }, + { 8, 0, 0, 0, 11, 72, }, + { 1, 0, 0, 0, 12, 68, }, + { 3, 0, 0, 0, 12, 52, }, + { 4, 0, 0, 0, 12, 76, }, + { 5, 0, 0, 0, 12, 60, }, + { 6, 0, 0, 0, 12, 52, }, + { 7, 0, 0, 0, 12, 60, }, + { 8, 0, 0, 0, 12, 52, }, + { 1, 0, 0, 0, 13, 68, }, + { 3, 0, 0, 0, 13, 48, }, + { 4, 0, 0, 0, 13, 76, }, + { 5, 0, 0, 0, 13, 60, }, + { 6, 0, 0, 0, 13, 48, }, + { 7, 0, 0, 0, 13, 60, }, + { 8, 0, 0, 0, 13, 48, }, + { 1, 0, 0, 0, 14, 68, }, + { 3, 0, 0, 0, 14, 127, }, + { 4, 0, 0, 0, 14, 127, }, + { 5, 0, 0, 0, 14, 127, }, + { 6, 0, 0, 0, 14, 127, }, + { 7, 0, 0, 0, 14, 127, }, + { 8, 0, 0, 0, 14, 127, }, + { 1, 0, 0, 1, 1, 76, }, + { 3, 0, 0, 1, 1, 52, }, + { 4, 0, 0, 1, 1, 76, }, + { 5, 0, 0, 1, 1, 60, }, + { 6, 0, 0, 1, 1, 52, }, + { 7, 0, 0, 1, 1, 60, }, + { 8, 0, 0, 1, 1, 52, }, + { 1, 0, 0, 1, 2, 76, }, + { 3, 0, 0, 1, 2, 60, }, + { 4, 0, 0, 1, 2, 76, }, + { 5, 0, 0, 1, 2, 60, }, + { 6, 0, 0, 1, 2, 60, }, + { 7, 0, 0, 1, 2, 60, }, + { 8, 0, 0, 1, 2, 60, }, + { 1, 0, 0, 1, 3, 76, }, + { 3, 0, 0, 1, 3, 64, }, + { 4, 0, 0, 1, 3, 76, }, + { 5, 0, 0, 1, 3, 60, }, + { 6, 0, 0, 1, 3, 64, }, + { 7, 0, 0, 1, 3, 60, }, + { 8, 0, 0, 1, 3, 64, }, + { 1, 0, 0, 1, 4, 76, }, + { 3, 0, 0, 1, 4, 68, }, + { 4, 0, 0, 1, 4, 76, }, + { 5, 0, 0, 1, 4, 60, }, + { 6, 0, 0, 1, 4, 68, }, + { 7, 0, 0, 1, 4, 60, }, + { 8, 0, 0, 1, 4, 68, }, + { 1, 0, 0, 1, 5, 76, }, + { 3, 0, 0, 1, 5, 76, }, + { 4, 0, 0, 1, 5, 76, }, + { 5, 0, 0, 1, 5, 60, }, + { 6, 0, 0, 1, 5, 76, }, + { 7, 0, 0, 1, 5, 60, }, + { 8, 0, 0, 1, 5, 76, }, + { 1, 0, 0, 1, 6, 76, }, + { 3, 0, 0, 1, 6, 76, }, + { 4, 0, 0, 1, 6, 76, }, + { 5, 0, 0, 1, 6, 60, }, + { 6, 0, 0, 1, 6, 76, }, + { 7, 0, 0, 1, 6, 60, }, + { 8, 0, 0, 1, 6, 76, }, + { 1, 0, 0, 1, 7, 76, }, + { 3, 0, 0, 1, 7, 76, }, + { 4, 0, 0, 1, 7, 76, }, + { 5, 0, 0, 1, 7, 60, }, + { 6, 0, 0, 1, 7, 76, }, + { 7, 0, 0, 1, 7, 60, }, + { 8, 0, 0, 1, 7, 76, }, + { 1, 0, 0, 1, 8, 76, }, + { 3, 0, 0, 1, 8, 68, }, + { 4, 0, 0, 1, 8, 76, }, + { 5, 0, 0, 1, 8, 60, }, + { 6, 0, 0, 1, 8, 68, }, + { 7, 0, 0, 1, 8, 60, }, + { 8, 0, 0, 1, 8, 68, }, + { 1, 0, 0, 1, 9, 76, }, + { 3, 0, 0, 1, 9, 64, }, + { 4, 0, 0, 1, 9, 76, }, + { 5, 0, 0, 1, 9, 60, }, + { 6, 0, 0, 1, 9, 64, }, + { 7, 0, 0, 1, 9, 60, }, + { 8, 0, 0, 1, 9, 64, }, + { 1, 0, 0, 1, 10, 76, }, + { 3, 0, 0, 1, 10, 60, }, + { 4, 0, 0, 1, 10, 76, }, + { 5, 0, 0, 1, 10, 60, }, + { 6, 0, 0, 1, 10, 60, }, + { 7, 0, 0, 1, 10, 60, }, + { 8, 0, 0, 1, 10, 60, }, + { 1, 0, 0, 1, 11, 76, }, + { 3, 0, 0, 1, 11, 52, }, + { 4, 0, 0, 1, 11, 76, }, + { 5, 0, 0, 1, 11, 60, }, + { 6, 0, 0, 1, 11, 52, }, + { 7, 0, 0, 1, 11, 60, }, + { 8, 0, 0, 1, 11, 52, }, + { 1, 0, 0, 1, 12, 76, }, + { 3, 0, 0, 1, 12, 40, }, + { 4, 0, 0, 1, 12, 76, }, + { 5, 0, 0, 1, 12, 60, }, + { 6, 0, 0, 1, 12, 40, }, + { 7, 0, 0, 1, 12, 60, }, + { 8, 0, 0, 1, 12, 40, }, + { 1, 0, 0, 1, 13, 76, }, + { 3, 0, 0, 1, 13, 28, }, + { 4, 0, 0, 1, 13, 70, }, + { 5, 0, 0, 1, 13, 60, }, + { 6, 0, 0, 1, 13, 28, }, + { 7, 0, 0, 1, 13, 60, }, + { 8, 0, 0, 1, 13, 28, }, + { 1, 0, 0, 1, 14, 127, }, + { 3, 0, 0, 1, 14, 127, }, + { 4, 0, 0, 1, 14, 127, }, + { 5, 0, 0, 1, 14, 127, }, + { 6, 0, 0, 1, 14, 127, }, + { 7, 0, 0, 1, 14, 127, }, + { 8, 0, 0, 1, 14, 127, }, + { 1, 0, 0, 2, 1, 76, }, + { 3, 0, 0, 2, 1, 52, }, + { 4, 0, 0, 2, 1, 76, }, + { 5, 0, 0, 2, 1, 60, }, + { 6, 0, 0, 2, 1, 52, }, + { 7, 0, 0, 2, 1, 60, }, + { 8, 0, 0, 2, 1, 52, }, + { 1, 0, 0, 2, 2, 76, }, + { 3, 0, 0, 2, 2, 60, }, + { 4, 0, 0, 2, 2, 76, }, + { 5, 0, 0, 2, 2, 60, }, + { 6, 0, 0, 2, 2, 60, }, + { 7, 0, 0, 2, 2, 60, }, + { 8, 0, 0, 2, 2, 60, }, + { 1, 0, 0, 2, 3, 76, }, + { 3, 0, 0, 2, 3, 64, }, + { 4, 0, 0, 2, 3, 76, }, + { 5, 0, 0, 2, 3, 60, }, + { 6, 0, 0, 2, 3, 64, }, + { 7, 0, 0, 2, 3, 60, }, + { 8, 0, 0, 2, 3, 64, }, + { 1, 0, 0, 2, 4, 76, }, + { 3, 0, 0, 2, 4, 68, }, + { 4, 0, 0, 2, 4, 76, }, + { 5, 0, 0, 2, 4, 60, }, + { 6, 0, 0, 2, 4, 68, }, + { 7, 0, 0, 2, 4, 60, }, + { 8, 0, 0, 2, 4, 68, }, + { 1, 0, 0, 2, 5, 76, }, + { 3, 0, 0, 2, 5, 76, }, + { 4, 0, 0, 2, 5, 76, }, + { 5, 0, 0, 2, 5, 60, }, + { 6, 0, 0, 2, 5, 76, }, + { 7, 0, 0, 2, 5, 60, }, + { 8, 0, 0, 2, 5, 76, }, + { 1, 0, 0, 2, 6, 76, }, + { 3, 0, 0, 2, 6, 76, }, + { 4, 0, 0, 2, 6, 76, }, + { 5, 0, 0, 2, 6, 60, }, + { 6, 0, 0, 2, 6, 76, }, + { 7, 0, 0, 2, 6, 60, }, + { 8, 0, 0, 2, 6, 76, }, + { 1, 0, 0, 2, 7, 76, }, + { 3, 0, 0, 2, 7, 76, }, + { 4, 0, 0, 2, 7, 76, }, + { 5, 0, 0, 2, 7, 60, }, + { 6, 0, 0, 2, 7, 76, }, + { 7, 0, 0, 2, 7, 60, }, + { 8, 0, 0, 2, 7, 76, }, + { 1, 0, 0, 2, 8, 76, }, + { 3, 0, 0, 2, 8, 68, }, + { 4, 0, 0, 2, 8, 76, }, + { 5, 0, 0, 2, 8, 60, }, + { 6, 0, 0, 2, 8, 68, }, + { 7, 0, 0, 2, 8, 60, }, + { 8, 0, 0, 2, 8, 68, }, + { 1, 0, 0, 2, 9, 76, }, + { 3, 0, 0, 2, 9, 64, }, + { 4, 0, 0, 2, 9, 76, }, + { 5, 0, 0, 2, 9, 60, }, + { 6, 0, 0, 2, 9, 64, }, + { 7, 0, 0, 2, 9, 60, }, + { 8, 0, 0, 2, 9, 64, }, + { 1, 0, 0, 2, 10, 76, }, + { 3, 0, 0, 2, 10, 60, }, + { 4, 0, 0, 2, 10, 76, }, + { 5, 0, 0, 2, 10, 60, }, + { 6, 0, 0, 2, 10, 60, }, + { 7, 0, 0, 2, 10, 60, }, + { 8, 0, 0, 2, 10, 60, }, + { 1, 0, 0, 2, 11, 76, }, + { 3, 0, 0, 2, 11, 52, }, + { 4, 0, 0, 2, 11, 76, }, + { 5, 0, 0, 2, 11, 60, }, + { 6, 0, 0, 2, 11, 52, }, + { 7, 0, 0, 2, 11, 60, }, + { 8, 0, 0, 2, 11, 52, }, + { 1, 0, 0, 2, 12, 76, }, + { 3, 0, 0, 2, 12, 40, }, + { 4, 0, 0, 2, 12, 76, }, + { 5, 0, 0, 2, 12, 60, }, + { 6, 0, 0, 2, 12, 40, }, + { 7, 0, 0, 2, 12, 60, }, + { 8, 0, 0, 2, 12, 40, }, + { 1, 0, 0, 2, 13, 76, }, + { 3, 0, 0, 2, 13, 28, }, + { 4, 0, 0, 2, 13, 72, }, + { 5, 0, 0, 2, 13, 60, }, + { 6, 0, 0, 2, 13, 28, }, + { 7, 0, 0, 2, 13, 60, }, + { 8, 0, 0, 2, 13, 28, }, + { 1, 0, 0, 2, 14, 127, }, + { 3, 0, 0, 2, 14, 127, }, + { 4, 0, 0, 2, 14, 127, }, + { 5, 0, 0, 2, 14, 127, }, + { 6, 0, 0, 2, 14, 127, }, + { 7, 0, 0, 2, 14, 127, }, + { 8, 0, 0, 2, 14, 127, }, + { 1, 0, 0, 3, 1, 66, }, + { 3, 0, 0, 3, 1, 52, }, + { 4, 0, 0, 3, 1, 68, }, + { 5, 0, 0, 3, 1, 36, }, + { 6, 0, 0, 3, 1, 52, }, + { 7, 0, 0, 3, 1, 36, }, + { 8, 0, 0, 3, 1, 52, }, + { 1, 0, 0, 3, 2, 66, }, + { 3, 0, 0, 3, 2, 60, }, + { 4, 0, 0, 3, 2, 70, }, + { 5, 0, 0, 3, 2, 36, }, + { 6, 0, 0, 3, 2, 60, }, + { 7, 0, 0, 3, 2, 36, }, + { 8, 0, 0, 3, 2, 60, }, + { 1, 0, 0, 3, 3, 66, }, + { 3, 0, 0, 3, 3, 64, }, + { 4, 0, 0, 3, 3, 70, }, + { 5, 0, 0, 3, 3, 36, }, + { 6, 0, 0, 3, 3, 64, }, + { 7, 0, 0, 3, 3, 36, }, + { 8, 0, 0, 3, 3, 64, }, + { 1, 0, 0, 3, 4, 66, }, + { 3, 0, 0, 3, 4, 68, }, + { 4, 0, 0, 3, 4, 70, }, + { 5, 0, 0, 3, 4, 36, }, + { 6, 0, 0, 3, 4, 68, }, + { 7, 0, 0, 3, 4, 36, }, + { 8, 0, 0, 3, 4, 68, }, + { 1, 0, 0, 3, 5, 66, }, + { 3, 0, 0, 3, 5, 76, }, + { 4, 0, 0, 3, 5, 70, }, + { 5, 0, 0, 3, 5, 36, }, + { 6, 0, 0, 3, 5, 76, }, + { 7, 0, 0, 3, 5, 36, }, + { 8, 0, 0, 3, 5, 76, }, + { 1, 0, 0, 3, 6, 66, }, + { 3, 0, 0, 3, 6, 76, }, + { 4, 0, 0, 3, 6, 70, }, + { 5, 0, 0, 3, 6, 36, }, + { 6, 0, 0, 3, 6, 76, }, + { 7, 0, 0, 3, 6, 36, }, + { 8, 0, 0, 3, 6, 76, }, + { 1, 0, 0, 3, 7, 66, }, + { 3, 0, 0, 3, 7, 76, }, + { 4, 0, 0, 3, 7, 70, }, + { 5, 0, 0, 3, 7, 36, }, + { 6, 0, 0, 3, 7, 76, }, + { 7, 0, 0, 3, 7, 36, }, + { 8, 0, 0, 3, 7, 76, }, + { 1, 0, 0, 3, 8, 66, }, + { 3, 0, 0, 3, 8, 68, }, + { 4, 0, 0, 3, 8, 70, }, + { 5, 0, 0, 3, 8, 36, }, + { 6, 0, 0, 3, 8, 68, }, + { 7, 0, 0, 3, 8, 36, }, + { 8, 0, 0, 3, 8, 68, }, + { 1, 0, 0, 3, 9, 66, }, + { 3, 0, 0, 3, 9, 64, }, + { 4, 0, 0, 3, 9, 70, }, + { 5, 0, 0, 3, 9, 36, }, + { 6, 0, 0, 3, 9, 64, }, + { 7, 0, 0, 3, 9, 36, }, + { 8, 0, 0, 3, 9, 64, }, + { 1, 0, 0, 3, 10, 66, }, + { 3, 0, 0, 3, 10, 60, }, + { 4, 0, 0, 3, 10, 70, }, + { 5, 0, 0, 3, 10, 36, }, + { 6, 0, 0, 3, 10, 60, }, + { 7, 0, 0, 3, 10, 36, }, + { 8, 0, 0, 3, 10, 60, }, + { 1, 0, 0, 3, 11, 66, }, + { 3, 0, 0, 3, 11, 52, }, + { 4, 0, 0, 3, 11, 70, }, + { 5, 0, 0, 3, 11, 36, }, + { 6, 0, 0, 3, 11, 52, }, + { 7, 0, 0, 3, 11, 36, }, + { 8, 0, 0, 3, 11, 52, }, + { 1, 0, 0, 3, 12, 66, }, + { 3, 0, 0, 3, 12, 40, }, + { 4, 0, 0, 3, 12, 70, }, + { 5, 0, 0, 3, 12, 36, }, + { 6, 0, 0, 3, 12, 40, }, + { 7, 0, 0, 3, 12, 36, }, + { 8, 0, 0, 3, 12, 40, }, + { 1, 0, 0, 3, 13, 66, }, + { 3, 0, 0, 3, 13, 28, }, + { 4, 0, 0, 3, 13, 62, }, + { 5, 0, 0, 3, 13, 36, }, + { 6, 0, 0, 3, 13, 28, }, + { 7, 0, 0, 3, 13, 36, }, + { 8, 0, 0, 3, 13, 28, }, + { 1, 0, 0, 3, 14, 127, }, + { 3, 0, 0, 3, 14, 127, }, + { 4, 0, 0, 3, 14, 127, }, + { 5, 0, 0, 3, 14, 127, }, + { 6, 0, 0, 3, 14, 127, }, + { 7, 0, 0, 3, 14, 127, }, + { 8, 0, 0, 3, 14, 127, }, + { 1, 0, 1, 2, 1, 127, }, + { 3, 0, 1, 2, 1, 127, }, + { 4, 0, 1, 2, 1, 127, }, + { 5, 0, 1, 2, 1, 127, }, + { 6, 0, 1, 2, 1, 127, }, + { 7, 0, 1, 2, 1, 127, }, + { 8, 0, 1, 2, 1, 127, }, + { 1, 0, 1, 2, 2, 127, }, + { 3, 0, 1, 2, 2, 127, }, + { 4, 0, 1, 2, 2, 127, }, + { 5, 0, 1, 2, 2, 127, }, + { 6, 0, 1, 2, 2, 127, }, + { 7, 0, 1, 2, 2, 127, }, + { 8, 0, 1, 2, 2, 127, }, + { 1, 0, 1, 2, 3, 72, }, + { 3, 0, 1, 2, 3, 52, }, + { 4, 0, 1, 2, 3, 72, }, + { 5, 0, 1, 2, 3, 60, }, + { 6, 0, 1, 2, 3, 52, }, + { 7, 0, 1, 2, 3, 60, }, + { 8, 0, 1, 2, 3, 52, }, + { 1, 0, 1, 2, 4, 72, }, + { 3, 0, 1, 2, 4, 52, }, + { 4, 0, 1, 2, 4, 72, }, + { 5, 0, 1, 2, 4, 60, }, + { 6, 0, 1, 2, 4, 52, }, + { 7, 0, 1, 2, 4, 60, }, + { 8, 0, 1, 2, 4, 52, }, + { 1, 0, 1, 2, 5, 72, }, + { 3, 0, 1, 2, 5, 60, }, + { 4, 0, 1, 2, 5, 72, }, + { 5, 0, 1, 2, 5, 60, }, + { 6, 0, 1, 2, 5, 60, }, + { 7, 0, 1, 2, 5, 60, }, + { 8, 0, 1, 2, 5, 60, }, + { 1, 0, 1, 2, 6, 72, }, + { 3, 0, 1, 2, 6, 64, }, + { 4, 0, 1, 2, 6, 72, }, + { 5, 0, 1, 2, 6, 60, }, + { 6, 0, 1, 2, 6, 64, }, + { 7, 0, 1, 2, 6, 60, }, + { 8, 0, 1, 2, 6, 64, }, + { 1, 0, 1, 2, 7, 72, }, + { 3, 0, 1, 2, 7, 60, }, + { 4, 0, 1, 2, 7, 72, }, + { 5, 0, 1, 2, 7, 60, }, + { 6, 0, 1, 2, 7, 60, }, + { 7, 0, 1, 2, 7, 60, }, + { 8, 0, 1, 2, 7, 60, }, + { 1, 0, 1, 2, 8, 72, }, + { 3, 0, 1, 2, 8, 52, }, + { 4, 0, 1, 2, 8, 72, }, + { 5, 0, 1, 2, 8, 60, }, + { 6, 0, 1, 2, 8, 52, }, + { 7, 0, 1, 2, 8, 60, }, + { 8, 0, 1, 2, 8, 52, }, + { 1, 0, 1, 2, 9, 72, }, + { 3, 0, 1, 2, 9, 52, }, + { 4, 0, 1, 2, 9, 72, }, + { 5, 0, 1, 2, 9, 60, }, + { 6, 0, 1, 2, 9, 52, }, + { 7, 0, 1, 2, 9, 60, }, + { 8, 0, 1, 2, 9, 52, }, + { 1, 0, 1, 2, 10, 72, }, + { 3, 0, 1, 2, 10, 40, }, + { 4, 0, 1, 2, 10, 72, }, + { 5, 0, 1, 2, 10, 60, }, + { 6, 0, 1, 2, 10, 40, }, + { 7, 0, 1, 2, 10, 60, }, + { 8, 0, 1, 2, 10, 40, }, + { 1, 0, 1, 2, 11, 72, }, + { 3, 0, 1, 2, 11, 28, }, + { 4, 0, 1, 2, 11, 70, }, + { 5, 0, 1, 2, 11, 60, }, + { 6, 0, 1, 2, 11, 28, }, + { 7, 0, 1, 2, 11, 60, }, + { 8, 0, 1, 2, 11, 28, }, + { 1, 0, 1, 2, 12, 127, }, + { 3, 0, 1, 2, 12, 127, }, + { 4, 0, 1, 2, 12, 127, }, + { 5, 0, 1, 2, 12, 127, }, + { 6, 0, 1, 2, 12, 127, }, + { 7, 0, 1, 2, 12, 127, }, + { 8, 0, 1, 2, 12, 127, }, + { 1, 0, 1, 2, 13, 127, }, + { 3, 0, 1, 2, 13, 127, }, + { 4, 0, 1, 2, 13, 127, }, + { 5, 0, 1, 2, 13, 127, }, + { 6, 0, 1, 2, 13, 127, }, + { 7, 0, 1, 2, 13, 127, }, + { 8, 0, 1, 2, 13, 127, }, + { 1, 0, 1, 2, 14, 127, }, + { 3, 0, 1, 2, 14, 127, }, + { 4, 0, 1, 2, 14, 127, }, + { 5, 0, 1, 2, 14, 127, }, + { 6, 0, 1, 2, 14, 127, }, + { 7, 0, 1, 2, 14, 127, }, + { 8, 0, 1, 2, 14, 127, }, + { 1, 0, 1, 3, 1, 127, }, + { 3, 0, 1, 3, 1, 127, }, + { 4, 0, 1, 3, 1, 127, }, + { 5, 0, 1, 3, 1, 127, }, + { 6, 0, 1, 3, 1, 127, }, + { 7, 0, 1, 3, 1, 127, }, + { 8, 0, 1, 3, 1, 127, }, + { 1, 0, 1, 3, 2, 127, }, + { 3, 0, 1, 3, 2, 127, }, + { 4, 0, 1, 3, 2, 127, }, + { 5, 0, 1, 3, 2, 127, }, + { 6, 0, 1, 3, 2, 127, }, + { 7, 0, 1, 3, 2, 127, }, + { 8, 0, 1, 3, 2, 127, }, + { 1, 0, 1, 3, 3, 66, }, + { 3, 0, 1, 3, 3, 48, }, + { 4, 0, 1, 3, 3, 66, }, + { 5, 0, 1, 3, 3, 36, }, + { 6, 0, 1, 3, 3, 48, }, + { 7, 0, 1, 3, 3, 36, }, + { 8, 0, 1, 3, 3, 48, }, + { 1, 0, 1, 3, 4, 66, }, + { 3, 0, 1, 3, 4, 48, }, + { 4, 0, 1, 3, 4, 70, }, + { 5, 0, 1, 3, 4, 36, }, + { 6, 0, 1, 3, 4, 48, }, + { 7, 0, 1, 3, 4, 36, }, + { 8, 0, 1, 3, 4, 48, }, + { 1, 0, 1, 3, 5, 66, }, + { 3, 0, 1, 3, 5, 60, }, + { 4, 0, 1, 3, 5, 70, }, + { 5, 0, 1, 3, 5, 36, }, + { 6, 0, 1, 3, 5, 60, }, + { 7, 0, 1, 3, 5, 36, }, + { 8, 0, 1, 3, 5, 60, }, + { 1, 0, 1, 3, 6, 66, }, + { 3, 0, 1, 3, 6, 64, }, + { 4, 0, 1, 3, 6, 70, }, + { 5, 0, 1, 3, 6, 36, }, + { 6, 0, 1, 3, 6, 64, }, + { 7, 0, 1, 3, 6, 36, }, + { 8, 0, 1, 3, 6, 64, }, + { 1, 0, 1, 3, 7, 66, }, + { 3, 0, 1, 3, 7, 60, }, + { 4, 0, 1, 3, 7, 70, }, + { 5, 0, 1, 3, 7, 36, }, + { 6, 0, 1, 3, 7, 60, }, + { 7, 0, 1, 3, 7, 36, }, + { 8, 0, 1, 3, 7, 60, }, + { 1, 0, 1, 3, 8, 66, }, + { 3, 0, 1, 3, 8, 52, }, + { 4, 0, 1, 3, 8, 70, }, + { 5, 0, 1, 3, 8, 36, }, + { 6, 0, 1, 3, 8, 52, }, + { 7, 0, 1, 3, 8, 36, }, + { 8, 0, 1, 3, 8, 52, }, + { 1, 0, 1, 3, 9, 66, }, + { 3, 0, 1, 3, 9, 52, }, + { 4, 0, 1, 3, 9, 70, }, + { 5, 0, 1, 3, 9, 36, }, + { 6, 0, 1, 3, 9, 52, }, + { 7, 0, 1, 3, 9, 36, }, + { 8, 0, 1, 3, 9, 52, }, + { 1, 0, 1, 3, 10, 66, }, + { 3, 0, 1, 3, 10, 40, }, + { 4, 0, 1, 3, 10, 70, }, + { 5, 0, 1, 3, 10, 36, }, + { 6, 0, 1, 3, 10, 40, }, + { 7, 0, 1, 3, 10, 36, }, + { 8, 0, 1, 3, 10, 40, }, + { 1, 0, 1, 3, 11, 66, }, + { 3, 0, 1, 3, 11, 26, }, + { 4, 0, 1, 3, 11, 66, }, + { 5, 0, 1, 3, 11, 36, }, + { 6, 0, 1, 3, 11, 26, }, + { 7, 0, 1, 3, 11, 36, }, + { 8, 0, 1, 3, 11, 26, }, + { 1, 0, 1, 3, 12, 127, }, + { 3, 0, 1, 3, 12, 127, }, + { 4, 0, 1, 3, 12, 127, }, + { 5, 0, 1, 3, 12, 127, }, + { 6, 0, 1, 3, 12, 127, }, + { 7, 0, 1, 3, 12, 127, }, + { 8, 0, 1, 3, 12, 127, }, + { 1, 0, 1, 3, 13, 127, }, + { 3, 0, 1, 3, 13, 127, }, + { 4, 0, 1, 3, 13, 127, }, + { 5, 0, 1, 3, 13, 127, }, + { 6, 0, 1, 3, 13, 127, }, + { 7, 0, 1, 3, 13, 127, }, + { 8, 0, 1, 3, 13, 127, }, + { 1, 0, 1, 3, 14, 127, }, + { 3, 0, 1, 3, 14, 127, }, + { 4, 0, 1, 3, 14, 127, }, + { 5, 0, 1, 3, 14, 127, }, + { 6, 0, 1, 3, 14, 127, }, + { 7, 0, 1, 3, 14, 127, }, + { 8, 0, 1, 3, 14, 127, }, + { 1, 1, 0, 1, 36, 60, }, + { 3, 1, 0, 1, 36, 62, }, + { 4, 1, 0, 1, 36, 76, }, + { 5, 1, 0, 1, 36, 62, }, + { 6, 1, 0, 1, 36, 64, }, + { 7, 1, 0, 1, 36, 54, }, + { 8, 1, 0, 1, 36, 62, }, + { 1, 1, 0, 1, 40, 62, }, + { 3, 1, 0, 1, 40, 62, }, + { 4, 1, 0, 1, 40, 76, }, + { 5, 1, 0, 1, 40, 62, }, + { 6, 1, 0, 1, 40, 64, }, + { 7, 1, 0, 1, 40, 54, }, + { 8, 1, 0, 1, 40, 62, }, + { 1, 1, 0, 1, 44, 62, }, + { 3, 1, 0, 1, 44, 62, }, + { 4, 1, 0, 1, 44, 76, }, + { 5, 1, 0, 1, 44, 62, }, + { 6, 1, 0, 1, 44, 64, }, + { 7, 1, 0, 1, 44, 54, }, + { 8, 1, 0, 1, 44, 62, }, + { 1, 1, 0, 1, 48, 62, }, + { 3, 1, 0, 1, 48, 62, }, + { 4, 1, 0, 1, 48, 76, }, + { 5, 1, 0, 1, 48, 62, }, + { 6, 1, 0, 1, 48, 64, }, + { 7, 1, 0, 1, 48, 54, }, + { 8, 1, 0, 1, 48, 62, }, + { 1, 1, 0, 1, 52, 62, }, + { 3, 1, 0, 1, 52, 64, }, + { 4, 1, 0, 1, 52, 76, }, + { 5, 1, 0, 1, 52, 62, }, + { 6, 1, 0, 1, 52, 76, }, + { 7, 1, 0, 1, 52, 54, }, + { 8, 1, 0, 1, 52, 76, }, + { 1, 1, 0, 1, 56, 62, }, + { 3, 1, 0, 1, 56, 64, }, + { 4, 1, 0, 1, 56, 76, }, + { 5, 1, 0, 1, 56, 62, }, + { 6, 1, 0, 1, 56, 76, }, + { 7, 1, 0, 1, 56, 54, }, + { 8, 1, 0, 1, 56, 76, }, + { 1, 1, 0, 1, 60, 62, }, + { 3, 1, 0, 1, 60, 64, }, + { 4, 1, 0, 1, 60, 76, }, + { 5, 1, 0, 1, 60, 62, }, + { 6, 1, 0, 1, 60, 76, }, + { 7, 1, 0, 1, 60, 54, }, + { 8, 1, 0, 1, 60, 76, }, + { 1, 1, 0, 1, 64, 60, }, + { 3, 1, 0, 1, 64, 64, }, + { 4, 1, 0, 1, 64, 76, }, + { 5, 1, 0, 1, 64, 62, }, + { 6, 1, 0, 1, 64, 74, }, + { 7, 1, 0, 1, 64, 54, }, + { 8, 1, 0, 1, 64, 74, }, + { 1, 1, 0, 1, 100, 76, }, + { 3, 1, 0, 1, 100, 72, }, + { 4, 1, 0, 1, 100, 76, }, + { 5, 1, 0, 1, 100, 62, }, + { 6, 1, 0, 1, 100, 72, }, + { 7, 1, 0, 1, 100, 54, }, + { 8, 1, 0, 1, 100, 72, }, + { 1, 1, 0, 1, 104, 76, }, + { 3, 1, 0, 1, 104, 76, }, + { 4, 1, 0, 1, 104, 76, }, + { 5, 1, 0, 1, 104, 62, }, + { 6, 1, 0, 1, 104, 76, }, + { 7, 1, 0, 1, 104, 54, }, + { 8, 1, 0, 1, 104, 76, }, + { 1, 1, 0, 1, 108, 76, }, + { 3, 1, 0, 1, 108, 76, }, + { 4, 1, 0, 1, 108, 76, }, + { 5, 1, 0, 1, 108, 62, }, + { 6, 1, 0, 1, 108, 76, }, + { 7, 1, 0, 1, 108, 54, }, + { 8, 1, 0, 1, 108, 76, }, + { 1, 1, 0, 1, 112, 76, }, + { 3, 1, 0, 1, 112, 76, }, + { 4, 1, 0, 1, 112, 76, }, + { 5, 1, 0, 1, 112, 62, }, + { 6, 1, 0, 1, 112, 76, }, + { 7, 1, 0, 1, 112, 54, }, + { 8, 1, 0, 1, 112, 76, }, + { 1, 1, 0, 1, 116, 76, }, + { 3, 1, 0, 1, 116, 76, }, + { 4, 1, 0, 1, 116, 76, }, + { 5, 1, 0, 1, 116, 62, }, + { 6, 1, 0, 1, 116, 76, }, + { 7, 1, 0, 1, 116, 54, }, + { 8, 1, 0, 1, 116, 76, }, + { 1, 1, 0, 1, 120, 76, }, + { 3, 1, 0, 1, 120, 127, }, + { 4, 1, 0, 1, 120, 76, }, + { 5, 1, 0, 1, 120, 127, }, + { 6, 1, 0, 1, 120, 76, }, + { 7, 1, 0, 1, 120, 54, }, + { 8, 1, 0, 1, 120, 76, }, + { 1, 1, 0, 1, 124, 76, }, + { 3, 1, 0, 1, 124, 127, }, + { 4, 1, 0, 1, 124, 76, }, + { 5, 1, 0, 1, 124, 127, }, + { 6, 1, 0, 1, 124, 76, }, + { 7, 1, 0, 1, 124, 54, }, + { 8, 1, 0, 1, 124, 76, }, + { 1, 1, 0, 1, 128, 76, }, + { 3, 1, 0, 1, 128, 127, }, + { 4, 1, 0, 1, 128, 76, }, + { 5, 1, 0, 1, 128, 127, }, + { 6, 1, 0, 1, 128, 76, }, + { 7, 1, 0, 1, 128, 54, }, + { 8, 1, 0, 1, 128, 76, }, + { 1, 1, 0, 1, 132, 76, }, + { 3, 1, 0, 1, 132, 76, }, + { 4, 1, 0, 1, 132, 76, }, + { 5, 1, 0, 1, 132, 62, }, + { 6, 1, 0, 1, 132, 76, }, + { 7, 1, 0, 1, 132, 54, }, + { 8, 1, 0, 1, 132, 76, }, + { 1, 1, 0, 1, 136, 76, }, + { 3, 1, 0, 1, 136, 76, }, + { 4, 1, 0, 1, 136, 76, }, + { 5, 1, 0, 1, 136, 62, }, + { 6, 1, 0, 1, 136, 76, }, + { 7, 1, 0, 1, 136, 127, }, + { 8, 1, 0, 1, 136, 76, }, + { 1, 1, 0, 1, 140, 76, }, + { 3, 1, 0, 1, 140, 72, }, + { 4, 1, 0, 1, 140, 76, }, + { 5, 1, 0, 1, 140, 62, }, + { 6, 1, 0, 1, 140, 72, }, + { 7, 1, 0, 1, 140, 127, }, + { 8, 1, 0, 1, 140, 72, }, + { 1, 1, 0, 1, 144, 127, }, + { 3, 1, 0, 1, 144, 76, }, + { 4, 1, 0, 1, 144, 76, }, + { 5, 1, 0, 1, 144, 127, }, + { 6, 1, 0, 1, 144, 76, }, + { 7, 1, 0, 1, 144, 127, }, + { 8, 1, 0, 1, 144, 76, }, + { 1, 1, 0, 1, 149, 127, }, + { 3, 1, 0, 1, 149, 76, }, + { 4, 1, 0, 1, 149, 74, }, + { 5, 1, 0, 1, 149, 76, }, + { 6, 1, 0, 1, 149, 76, }, + { 7, 1, 0, 1, 149, 54, }, + { 8, 1, 0, 1, 149, 76, }, + { 1, 1, 0, 1, 153, 127, }, + { 3, 1, 0, 1, 153, 76, }, + { 4, 1, 0, 1, 153, 74, }, + { 5, 1, 0, 1, 153, 76, }, + { 6, 1, 0, 1, 153, 76, }, + { 7, 1, 0, 1, 153, 54, }, + { 8, 1, 0, 1, 153, 76, }, + { 1, 1, 0, 1, 157, 127, }, + { 3, 1, 0, 1, 157, 76, }, + { 4, 1, 0, 1, 157, 74, }, + { 5, 1, 0, 1, 157, 76, }, + { 6, 1, 0, 1, 157, 76, }, + { 7, 1, 0, 1, 157, 54, }, + { 8, 1, 0, 1, 157, 76, }, + { 1, 1, 0, 1, 161, 127, }, + { 3, 1, 0, 1, 161, 76, }, + { 4, 1, 0, 1, 161, 74, }, + { 5, 1, 0, 1, 161, 76, }, + { 6, 1, 0, 1, 161, 76, }, + { 7, 1, 0, 1, 161, 54, }, + { 8, 1, 0, 1, 161, 76, }, + { 1, 1, 0, 1, 165, 127, }, + { 3, 1, 0, 1, 165, 76, }, + { 4, 1, 0, 1, 165, 74, }, + { 5, 1, 0, 1, 165, 76, }, + { 6, 1, 0, 1, 165, 76, }, + { 7, 1, 0, 1, 165, 54, }, + { 8, 1, 0, 1, 165, 76, }, + { 1, 1, 0, 2, 36, 62, }, + { 3, 1, 0, 2, 36, 62, }, + { 4, 1, 0, 2, 36, 76, }, + { 5, 1, 0, 2, 36, 62, }, + { 6, 1, 0, 2, 36, 64, }, + { 7, 1, 0, 2, 36, 54, }, + { 8, 1, 0, 2, 36, 62, }, + { 1, 1, 0, 2, 40, 62, }, + { 3, 1, 0, 2, 40, 62, }, + { 4, 1, 0, 2, 40, 76, }, + { 5, 1, 0, 2, 40, 62, }, + { 6, 1, 0, 2, 40, 64, }, + { 7, 1, 0, 2, 40, 54, }, + { 8, 1, 0, 2, 40, 62, }, + { 1, 1, 0, 2, 44, 62, }, + { 3, 1, 0, 2, 44, 62, }, + { 4, 1, 0, 2, 44, 76, }, + { 5, 1, 0, 2, 44, 62, }, + { 6, 1, 0, 2, 44, 64, }, + { 7, 1, 0, 2, 44, 54, }, + { 8, 1, 0, 2, 44, 62, }, + { 1, 1, 0, 2, 48, 62, }, + { 3, 1, 0, 2, 48, 62, }, + { 4, 1, 0, 2, 48, 76, }, + { 5, 1, 0, 2, 48, 62, }, + { 6, 1, 0, 2, 48, 64, }, + { 7, 1, 0, 2, 48, 54, }, + { 8, 1, 0, 2, 48, 62, }, + { 1, 1, 0, 2, 52, 62, }, + { 3, 1, 0, 2, 52, 64, }, + { 4, 1, 0, 2, 52, 76, }, + { 5, 1, 0, 2, 52, 62, }, + { 6, 1, 0, 2, 52, 76, }, + { 7, 1, 0, 2, 52, 54, }, + { 8, 1, 0, 2, 52, 76, }, + { 1, 1, 0, 2, 56, 62, }, + { 3, 1, 0, 2, 56, 64, }, + { 4, 1, 0, 2, 56, 76, }, + { 5, 1, 0, 2, 56, 62, }, + { 6, 1, 0, 2, 56, 76, }, + { 7, 1, 0, 2, 56, 54, }, + { 8, 1, 0, 2, 56, 76, }, + { 1, 1, 0, 2, 60, 62, }, + { 3, 1, 0, 2, 60, 64, }, + { 4, 1, 0, 2, 60, 76, }, + { 5, 1, 0, 2, 60, 62, }, + { 6, 1, 0, 2, 60, 76, }, + { 7, 1, 0, 2, 60, 54, }, + { 8, 1, 0, 2, 60, 76, }, + { 1, 1, 0, 2, 64, 60, }, + { 3, 1, 0, 2, 64, 64, }, + { 4, 1, 0, 2, 64, 74, }, + { 5, 1, 0, 2, 64, 62, }, + { 6, 1, 0, 2, 64, 74, }, + { 7, 1, 0, 2, 64, 54, }, + { 8, 1, 0, 2, 64, 74, }, + { 1, 1, 0, 2, 100, 76, }, + { 3, 1, 0, 2, 100, 70, }, + { 4, 1, 0, 2, 100, 76, }, + { 5, 1, 0, 2, 100, 62, }, + { 6, 1, 0, 2, 100, 70, }, + { 7, 1, 0, 2, 100, 54, }, + { 8, 1, 0, 2, 100, 70, }, + { 1, 1, 0, 2, 104, 76, }, + { 3, 1, 0, 2, 104, 76, }, + { 4, 1, 0, 2, 104, 76, }, + { 5, 1, 0, 2, 104, 62, }, + { 6, 1, 0, 2, 104, 76, }, + { 7, 1, 0, 2, 104, 54, }, + { 8, 1, 0, 2, 104, 76, }, + { 1, 1, 0, 2, 108, 76, }, + { 3, 1, 0, 2, 108, 76, }, + { 4, 1, 0, 2, 108, 76, }, + { 5, 1, 0, 2, 108, 62, }, + { 6, 1, 0, 2, 108, 76, }, + { 7, 1, 0, 2, 108, 54, }, + { 8, 1, 0, 2, 108, 76, }, + { 1, 1, 0, 2, 112, 76, }, + { 3, 1, 0, 2, 112, 76, }, + { 4, 1, 0, 2, 112, 76, }, + { 5, 1, 0, 2, 112, 62, }, + { 6, 1, 0, 2, 112, 76, }, + { 7, 1, 0, 2, 112, 54, }, + { 8, 1, 0, 2, 112, 76, }, + { 1, 1, 0, 2, 116, 76, }, + { 3, 1, 0, 2, 116, 76, }, + { 4, 1, 0, 2, 116, 76, }, + { 5, 1, 0, 2, 116, 62, }, + { 6, 1, 0, 2, 116, 76, }, + { 7, 1, 0, 2, 116, 54, }, + { 8, 1, 0, 2, 116, 76, }, + { 1, 1, 0, 2, 120, 76, }, + { 3, 1, 0, 2, 120, 127, }, + { 4, 1, 0, 2, 120, 76, }, + { 5, 1, 0, 2, 120, 127, }, + { 6, 1, 0, 2, 120, 76, }, + { 7, 1, 0, 2, 120, 54, }, + { 8, 1, 0, 2, 120, 76, }, + { 1, 1, 0, 2, 124, 76, }, + { 3, 1, 0, 2, 124, 127, }, + { 4, 1, 0, 2, 124, 76, }, + { 5, 1, 0, 2, 124, 127, }, + { 6, 1, 0, 2, 124, 76, }, + { 7, 1, 0, 2, 124, 54, }, + { 8, 1, 0, 2, 124, 76, }, + { 1, 1, 0, 2, 128, 76, }, + { 3, 1, 0, 2, 128, 127, }, + { 4, 1, 0, 2, 128, 76, }, + { 5, 1, 0, 2, 128, 127, }, + { 6, 1, 0, 2, 128, 76, }, + { 7, 1, 0, 2, 128, 54, }, + { 8, 1, 0, 2, 128, 76, }, + { 1, 1, 0, 2, 132, 76, }, + { 3, 1, 0, 2, 132, 76, }, + { 4, 1, 0, 2, 132, 76, }, + { 5, 1, 0, 2, 132, 62, }, + { 6, 1, 0, 2, 132, 76, }, + { 7, 1, 0, 2, 132, 54, }, + { 8, 1, 0, 2, 132, 76, }, + { 1, 1, 0, 2, 136, 76, }, + { 3, 1, 0, 2, 136, 76, }, + { 4, 1, 0, 2, 136, 76, }, + { 5, 1, 0, 2, 136, 62, }, + { 6, 1, 0, 2, 136, 76, }, + { 7, 1, 0, 2, 136, 127, }, + { 8, 1, 0, 2, 136, 76, }, + { 1, 1, 0, 2, 140, 76, }, + { 3, 1, 0, 2, 140, 70, }, + { 4, 1, 0, 2, 140, 76, }, + { 5, 1, 0, 2, 140, 62, }, + { 6, 1, 0, 2, 140, 70, }, + { 7, 1, 0, 2, 140, 127, }, + { 8, 1, 0, 2, 140, 70, }, + { 1, 1, 0, 2, 144, 127, }, + { 3, 1, 0, 2, 144, 76, }, + { 4, 1, 0, 2, 144, 76, }, + { 5, 1, 0, 2, 144, 127, }, + { 6, 1, 0, 2, 144, 76, }, + { 7, 1, 0, 2, 144, 127, }, + { 8, 1, 0, 2, 144, 76, }, + { 1, 1, 0, 2, 149, 127, }, + { 3, 1, 0, 2, 149, 76, }, + { 4, 1, 0, 2, 149, 74, }, + { 5, 1, 0, 2, 149, 76, }, + { 6, 1, 0, 2, 149, 76, }, + { 7, 1, 0, 2, 149, 54, }, + { 8, 1, 0, 2, 149, 76, }, + { 1, 1, 0, 2, 153, 127, }, + { 3, 1, 0, 2, 153, 76, }, + { 4, 1, 0, 2, 153, 74, }, + { 5, 1, 0, 2, 153, 76, }, + { 6, 1, 0, 2, 153, 76, }, + { 7, 1, 0, 2, 153, 54, }, + { 8, 1, 0, 2, 153, 76, }, + { 1, 1, 0, 2, 157, 127, }, + { 3, 1, 0, 2, 157, 76, }, + { 4, 1, 0, 2, 157, 74, }, + { 5, 1, 0, 2, 157, 76, }, + { 6, 1, 0, 2, 157, 76, }, + { 7, 1, 0, 2, 157, 54, }, + { 8, 1, 0, 2, 157, 76, }, + { 1, 1, 0, 2, 161, 127, }, + { 3, 1, 0, 2, 161, 76, }, + { 4, 1, 0, 2, 161, 74, }, + { 5, 1, 0, 2, 161, 76, }, + { 6, 1, 0, 2, 161, 76, }, + { 7, 1, 0, 2, 161, 54, }, + { 8, 1, 0, 2, 161, 76, }, + { 1, 1, 0, 2, 165, 127, }, + { 3, 1, 0, 2, 165, 76, }, + { 4, 1, 0, 2, 165, 74, }, + { 5, 1, 0, 2, 165, 76, }, + { 6, 1, 0, 2, 165, 76, }, + { 7, 1, 0, 2, 165, 54, }, + { 8, 1, 0, 2, 165, 76, }, + { 1, 1, 0, 3, 36, 50, }, + { 3, 1, 0, 3, 36, 38, }, + { 4, 1, 0, 3, 36, 66, }, + { 5, 1, 0, 3, 36, 38, }, + { 6, 1, 0, 3, 36, 52, }, + { 7, 1, 0, 3, 36, 30, }, + { 8, 1, 0, 3, 36, 50, }, + { 1, 1, 0, 3, 40, 50, }, + { 3, 1, 0, 3, 40, 38, }, + { 4, 1, 0, 3, 40, 66, }, + { 5, 1, 0, 3, 40, 38, }, + { 6, 1, 0, 3, 40, 52, }, + { 7, 1, 0, 3, 40, 30, }, + { 8, 1, 0, 3, 40, 50, }, + { 1, 1, 0, 3, 44, 50, }, + { 3, 1, 0, 3, 44, 38, }, + { 4, 1, 0, 3, 44, 66, }, + { 5, 1, 0, 3, 44, 38, }, + { 6, 1, 0, 3, 44, 52, }, + { 7, 1, 0, 3, 44, 30, }, + { 8, 1, 0, 3, 44, 50, }, + { 1, 1, 0, 3, 48, 50, }, + { 3, 1, 0, 3, 48, 38, }, + { 4, 1, 0, 3, 48, 66, }, + { 5, 1, 0, 3, 48, 38, }, + { 6, 1, 0, 3, 48, 52, }, + { 7, 1, 0, 3, 48, 30, }, + { 8, 1, 0, 3, 48, 50, }, + { 1, 1, 0, 3, 52, 50, }, + { 3, 1, 0, 3, 52, 40, }, + { 4, 1, 0, 3, 52, 66, }, + { 5, 1, 0, 3, 52, 38, }, + { 6, 1, 0, 3, 52, 68, }, + { 7, 1, 0, 3, 52, 30, }, + { 8, 1, 0, 3, 52, 68, }, + { 1, 1, 0, 3, 56, 50, }, + { 3, 1, 0, 3, 56, 40, }, + { 4, 1, 0, 3, 56, 66, }, + { 5, 1, 0, 3, 56, 38, }, + { 6, 1, 0, 3, 56, 68, }, + { 7, 1, 0, 3, 56, 30, }, + { 8, 1, 0, 3, 56, 68, }, + { 1, 1, 0, 3, 60, 50, }, + { 3, 1, 0, 3, 60, 40, }, + { 4, 1, 0, 3, 60, 66, }, + { 5, 1, 0, 3, 60, 38, }, + { 6, 1, 0, 3, 60, 66, }, + { 7, 1, 0, 3, 60, 30, }, + { 8, 1, 0, 3, 60, 66, }, + { 1, 1, 0, 3, 64, 50, }, + { 3, 1, 0, 3, 64, 40, }, + { 4, 1, 0, 3, 64, 66, }, + { 5, 1, 0, 3, 64, 38, }, + { 6, 1, 0, 3, 64, 68, }, + { 7, 1, 0, 3, 64, 30, }, + { 8, 1, 0, 3, 64, 68, }, + { 1, 1, 0, 3, 100, 70, }, + { 3, 1, 0, 3, 100, 60, }, + { 4, 1, 0, 3, 100, 64, }, + { 5, 1, 0, 3, 100, 38, }, + { 6, 1, 0, 3, 100, 60, }, + { 7, 1, 0, 3, 100, 30, }, + { 8, 1, 0, 3, 100, 60, }, + { 1, 1, 0, 3, 104, 70, }, + { 3, 1, 0, 3, 104, 68, }, + { 4, 1, 0, 3, 104, 64, }, + { 5, 1, 0, 3, 104, 38, }, + { 6, 1, 0, 3, 104, 68, }, + { 7, 1, 0, 3, 104, 30, }, + { 8, 1, 0, 3, 104, 68, }, + { 1, 1, 0, 3, 108, 70, }, + { 3, 1, 0, 3, 108, 68, }, + { 4, 1, 0, 3, 108, 64, }, + { 5, 1, 0, 3, 108, 38, }, + { 6, 1, 0, 3, 108, 68, }, + { 7, 1, 0, 3, 108, 30, }, + { 8, 1, 0, 3, 108, 68, }, + { 1, 1, 0, 3, 112, 70, }, + { 3, 1, 0, 3, 112, 68, }, + { 4, 1, 0, 3, 112, 64, }, + { 5, 1, 0, 3, 112, 38, }, + { 6, 1, 0, 3, 112, 68, }, + { 7, 1, 0, 3, 112, 30, }, + { 8, 1, 0, 3, 112, 68, }, + { 1, 1, 0, 3, 116, 70, }, + { 3, 1, 0, 3, 116, 68, }, + { 4, 1, 0, 3, 116, 64, }, + { 5, 1, 0, 3, 116, 38, }, + { 6, 1, 0, 3, 116, 68, }, + { 7, 1, 0, 3, 116, 30, }, + { 8, 1, 0, 3, 116, 68, }, + { 1, 1, 0, 3, 120, 70, }, + { 3, 1, 0, 3, 120, 127, }, + { 4, 1, 0, 3, 120, 64, }, + { 5, 1, 0, 3, 120, 127, }, + { 6, 1, 0, 3, 120, 68, }, + { 7, 1, 0, 3, 120, 30, }, + { 8, 1, 0, 3, 120, 68, }, + { 1, 1, 0, 3, 124, 70, }, + { 3, 1, 0, 3, 124, 127, }, + { 4, 1, 0, 3, 124, 64, }, + { 5, 1, 0, 3, 124, 127, }, + { 6, 1, 0, 3, 124, 68, }, + { 7, 1, 0, 3, 124, 30, }, + { 8, 1, 0, 3, 124, 68, }, + { 1, 1, 0, 3, 128, 70, }, + { 3, 1, 0, 3, 128, 127, }, + { 4, 1, 0, 3, 128, 64, }, + { 5, 1, 0, 3, 128, 127, }, + { 6, 1, 0, 3, 128, 68, }, + { 7, 1, 0, 3, 128, 30, }, + { 8, 1, 0, 3, 128, 68, }, + { 1, 1, 0, 3, 132, 70, }, + { 3, 1, 0, 3, 132, 68, }, + { 4, 1, 0, 3, 132, 64, }, + { 5, 1, 0, 3, 132, 38, }, + { 6, 1, 0, 3, 132, 68, }, + { 7, 1, 0, 3, 132, 30, }, + { 8, 1, 0, 3, 132, 68, }, + { 1, 1, 0, 3, 136, 70, }, + { 3, 1, 0, 3, 136, 68, }, + { 4, 1, 0, 3, 136, 64, }, + { 5, 1, 0, 3, 136, 38, }, + { 6, 1, 0, 3, 136, 68, }, + { 7, 1, 0, 3, 136, 127, }, + { 8, 1, 0, 3, 136, 68, }, + { 1, 1, 0, 3, 140, 70, }, + { 3, 1, 0, 3, 140, 60, }, + { 4, 1, 0, 3, 140, 64, }, + { 5, 1, 0, 3, 140, 38, }, + { 6, 1, 0, 3, 140, 60, }, + { 7, 1, 0, 3, 140, 127, }, + { 8, 1, 0, 3, 140, 60, }, + { 1, 1, 0, 3, 144, 127, }, + { 3, 1, 0, 3, 144, 68, }, + { 4, 1, 0, 3, 144, 64, }, + { 5, 1, 0, 3, 144, 127, }, + { 6, 1, 0, 3, 144, 68, }, + { 7, 1, 0, 3, 144, 127, }, + { 8, 1, 0, 3, 144, 68, }, + { 1, 1, 0, 3, 149, 127, }, + { 3, 1, 0, 3, 149, 76, }, + { 4, 1, 0, 3, 149, 60, }, + { 5, 1, 0, 3, 149, 76, }, + { 6, 1, 0, 3, 149, 76, }, + { 7, 1, 0, 3, 149, 30, }, + { 8, 1, 0, 3, 149, 72, }, + { 1, 1, 0, 3, 153, 127, }, + { 3, 1, 0, 3, 153, 76, }, + { 4, 1, 0, 3, 153, 60, }, + { 5, 1, 0, 3, 153, 76, }, + { 6, 1, 0, 3, 153, 76, }, + { 7, 1, 0, 3, 153, 30, }, + { 8, 1, 0, 3, 153, 76, }, + { 1, 1, 0, 3, 157, 127, }, + { 3, 1, 0, 3, 157, 76, }, + { 4, 1, 0, 3, 157, 60, }, + { 5, 1, 0, 3, 157, 76, }, + { 6, 1, 0, 3, 157, 76, }, + { 7, 1, 0, 3, 157, 30, }, + { 8, 1, 0, 3, 157, 76, }, + { 1, 1, 0, 3, 161, 127, }, + { 3, 1, 0, 3, 161, 76, }, + { 4, 1, 0, 3, 161, 60, }, + { 5, 1, 0, 3, 161, 76, }, + { 6, 1, 0, 3, 161, 76, }, + { 7, 1, 0, 3, 161, 30, }, + { 8, 1, 0, 3, 161, 76, }, + { 1, 1, 0, 3, 165, 127, }, + { 3, 1, 0, 3, 165, 76, }, + { 4, 1, 0, 3, 165, 60, }, + { 5, 1, 0, 3, 165, 76, }, + { 6, 1, 0, 3, 165, 76, }, + { 7, 1, 0, 3, 165, 30, }, + { 8, 1, 0, 3, 165, 76, }, + { 1, 1, 1, 2, 38, 62, }, + { 3, 1, 1, 2, 38, 64, }, + { 4, 1, 1, 2, 38, 72, }, + { 5, 1, 1, 2, 38, 64, }, + { 6, 1, 1, 2, 38, 64, }, + { 7, 1, 1, 2, 38, 54, }, + { 8, 1, 1, 2, 38, 62, }, + { 1, 1, 1, 2, 46, 62, }, + { 3, 1, 1, 2, 46, 64, }, + { 4, 1, 1, 2, 46, 72, }, + { 5, 1, 1, 2, 46, 64, }, + { 6, 1, 1, 2, 46, 64, }, + { 7, 1, 1, 2, 46, 54, }, + { 8, 1, 1, 2, 46, 62, }, + { 1, 1, 1, 2, 54, 62, }, + { 3, 1, 1, 2, 54, 64, }, + { 4, 1, 1, 2, 54, 72, }, + { 5, 1, 1, 2, 54, 64, }, + { 6, 1, 1, 2, 54, 72, }, + { 7, 1, 1, 2, 54, 54, }, + { 8, 1, 1, 2, 54, 72, }, + { 1, 1, 1, 2, 62, 62, }, + { 3, 1, 1, 2, 62, 64, }, + { 4, 1, 1, 2, 62, 70, }, + { 5, 1, 1, 2, 62, 64, }, + { 6, 1, 1, 2, 62, 64, }, + { 7, 1, 1, 2, 62, 54, }, + { 8, 1, 1, 2, 62, 64, }, + { 1, 1, 1, 2, 102, 72, }, + { 3, 1, 1, 2, 102, 58, }, + { 4, 1, 1, 2, 102, 72, }, + { 5, 1, 1, 2, 102, 64, }, + { 6, 1, 1, 2, 102, 58, }, + { 7, 1, 1, 2, 102, 54, }, + { 8, 1, 1, 2, 102, 58, }, + { 1, 1, 1, 2, 110, 72, }, + { 3, 1, 1, 2, 110, 72, }, + { 4, 1, 1, 2, 110, 72, }, + { 5, 1, 1, 2, 110, 64, }, + { 6, 1, 1, 2, 110, 72, }, + { 7, 1, 1, 2, 110, 54, }, + { 8, 1, 1, 2, 110, 72, }, + { 1, 1, 1, 2, 118, 72, }, + { 3, 1, 1, 2, 118, 127, }, + { 4, 1, 1, 2, 118, 72, }, + { 5, 1, 1, 2, 118, 127, }, + { 6, 1, 1, 2, 118, 72, }, + { 7, 1, 1, 2, 118, 54, }, + { 8, 1, 1, 2, 118, 72, }, + { 1, 1, 1, 2, 126, 72, }, + { 3, 1, 1, 2, 126, 127, }, + { 4, 1, 1, 2, 126, 72, }, + { 5, 1, 1, 2, 126, 127, }, + { 6, 1, 1, 2, 126, 72, }, + { 7, 1, 1, 2, 126, 54, }, + { 8, 1, 1, 2, 126, 72, }, + { 1, 1, 1, 2, 134, 72, }, + { 3, 1, 1, 2, 134, 72, }, + { 4, 1, 1, 2, 134, 72, }, + { 5, 1, 1, 2, 134, 64, }, + { 6, 1, 1, 2, 134, 72, }, + { 7, 1, 1, 2, 134, 127, }, + { 8, 1, 1, 2, 134, 72, }, + { 1, 1, 1, 2, 142, 127, }, + { 3, 1, 1, 2, 142, 72, }, + { 4, 1, 1, 2, 142, 72, }, + { 5, 1, 1, 2, 142, 127, }, + { 6, 1, 1, 2, 142, 72, }, + { 7, 1, 1, 2, 142, 127, }, + { 8, 1, 1, 2, 142, 72, }, + { 1, 1, 1, 2, 151, 127, }, + { 3, 1, 1, 2, 151, 72, }, + { 4, 1, 1, 2, 151, 72, }, + { 5, 1, 1, 2, 151, 72, }, + { 6, 1, 1, 2, 151, 72, }, + { 7, 1, 1, 2, 151, 54, }, + { 8, 1, 1, 2, 151, 72, }, + { 1, 1, 1, 2, 159, 127, }, + { 3, 1, 1, 2, 159, 72, }, + { 4, 1, 1, 2, 159, 72, }, + { 5, 1, 1, 2, 159, 72, }, + { 6, 1, 1, 2, 159, 72, }, + { 7, 1, 1, 2, 159, 54, }, + { 8, 1, 1, 2, 159, 72, }, + { 1, 1, 1, 3, 38, 50, }, + { 3, 1, 1, 3, 38, 40, }, + { 4, 1, 1, 3, 38, 62, }, + { 5, 1, 1, 3, 38, 40, }, + { 6, 1, 1, 3, 38, 52, }, + { 7, 1, 1, 3, 38, 30, }, + { 8, 1, 1, 3, 38, 50, }, + { 1, 1, 1, 3, 46, 50, }, + { 3, 1, 1, 3, 46, 40, }, + { 4, 1, 1, 3, 46, 62, }, + { 5, 1, 1, 3, 46, 40, }, + { 6, 1, 1, 3, 46, 52, }, + { 7, 1, 1, 3, 46, 30, }, + { 8, 1, 1, 3, 46, 50, }, + { 1, 1, 1, 3, 54, 50, }, + { 3, 1, 1, 3, 54, 40, }, + { 4, 1, 1, 3, 54, 62, }, + { 5, 1, 1, 3, 54, 40, }, + { 6, 1, 1, 3, 54, 68, }, + { 7, 1, 1, 3, 54, 30, }, + { 8, 1, 1, 3, 54, 68, }, + { 1, 1, 1, 3, 62, 48, }, + { 3, 1, 1, 3, 62, 40, }, + { 4, 1, 1, 3, 62, 58, }, + { 5, 1, 1, 3, 62, 40, }, + { 6, 1, 1, 3, 62, 58, }, + { 7, 1, 1, 3, 62, 30, }, + { 8, 1, 1, 3, 62, 58, }, + { 1, 1, 1, 3, 102, 70, }, + { 3, 1, 1, 3, 102, 54, }, + { 4, 1, 1, 3, 102, 64, }, + { 5, 1, 1, 3, 102, 40, }, + { 6, 1, 1, 3, 102, 54, }, + { 7, 1, 1, 3, 102, 30, }, + { 8, 1, 1, 3, 102, 54, }, + { 1, 1, 1, 3, 110, 70, }, + { 3, 1, 1, 3, 110, 68, }, + { 4, 1, 1, 3, 110, 64, }, + { 5, 1, 1, 3, 110, 40, }, + { 6, 1, 1, 3, 110, 68, }, + { 7, 1, 1, 3, 110, 30, }, + { 8, 1, 1, 3, 110, 68, }, + { 1, 1, 1, 3, 118, 70, }, + { 3, 1, 1, 3, 118, 127, }, + { 4, 1, 1, 3, 118, 64, }, + { 5, 1, 1, 3, 118, 127, }, + { 6, 1, 1, 3, 118, 68, }, + { 7, 1, 1, 3, 118, 30, }, + { 8, 1, 1, 3, 118, 68, }, + { 1, 1, 1, 3, 126, 70, }, + { 3, 1, 1, 3, 126, 127, }, + { 4, 1, 1, 3, 126, 64, }, + { 5, 1, 1, 3, 126, 127, }, + { 6, 1, 1, 3, 126, 68, }, + { 7, 1, 1, 3, 126, 30, }, + { 8, 1, 1, 3, 126, 68, }, + { 1, 1, 1, 3, 134, 70, }, + { 3, 1, 1, 3, 134, 68, }, + { 4, 1, 1, 3, 134, 64, }, + { 5, 1, 1, 3, 134, 40, }, + { 6, 1, 1, 3, 134, 68, }, + { 7, 1, 1, 3, 134, 127, }, + { 8, 1, 1, 3, 134, 68, }, + { 1, 1, 1, 3, 142, 127, }, + { 3, 1, 1, 3, 142, 68, }, + { 4, 1, 1, 3, 142, 64, }, + { 5, 1, 1, 3, 142, 127, }, + { 6, 1, 1, 3, 142, 68, }, + { 7, 1, 1, 3, 142, 127, }, + { 8, 1, 1, 3, 142, 68, }, + { 1, 1, 1, 3, 151, 127, }, + { 3, 1, 1, 3, 151, 72, }, + { 4, 1, 1, 3, 151, 66, }, + { 5, 1, 1, 3, 151, 72, }, + { 6, 1, 1, 3, 151, 72, }, + { 7, 1, 1, 3, 151, 30, }, + { 8, 1, 1, 3, 151, 68, }, + { 1, 1, 1, 3, 159, 127, }, + { 3, 1, 1, 3, 159, 72, }, + { 4, 1, 1, 3, 159, 66, }, + { 5, 1, 1, 3, 159, 72, }, + { 6, 1, 1, 3, 159, 72, }, + { 7, 1, 1, 3, 159, 30, }, + { 8, 1, 1, 3, 159, 72, }, + { 1, 1, 2, 4, 42, 64, }, + { 3, 1, 2, 4, 42, 64, }, + { 4, 1, 2, 4, 42, 68, }, + { 5, 1, 2, 4, 42, 64, }, + { 6, 1, 2, 4, 42, 64, }, + { 7, 1, 2, 4, 42, 54, }, + { 8, 1, 2, 4, 42, 62, }, + { 1, 1, 2, 4, 58, 64, }, + { 3, 1, 2, 4, 58, 62, }, + { 4, 1, 2, 4, 58, 64, }, + { 5, 1, 2, 4, 58, 64, }, + { 6, 1, 2, 4, 58, 62, }, + { 7, 1, 2, 4, 58, 54, }, + { 8, 1, 2, 4, 58, 62, }, + { 1, 1, 2, 4, 106, 72, }, + { 3, 1, 2, 4, 106, 58, }, + { 4, 1, 2, 4, 106, 66, }, + { 5, 1, 2, 4, 106, 64, }, + { 6, 1, 2, 4, 106, 58, }, + { 7, 1, 2, 4, 106, 54, }, + { 8, 1, 2, 4, 106, 58, }, + { 1, 1, 2, 4, 122, 72, }, + { 3, 1, 2, 4, 122, 127, }, + { 4, 1, 2, 4, 122, 68, }, + { 5, 1, 2, 4, 122, 127, }, + { 6, 1, 2, 4, 122, 72, }, + { 7, 1, 2, 4, 122, 54, }, + { 8, 1, 2, 4, 122, 72, }, + { 1, 1, 2, 4, 138, 127, }, + { 3, 1, 2, 4, 138, 72, }, + { 4, 1, 2, 4, 138, 68, }, + { 5, 1, 2, 4, 138, 127, }, + { 6, 1, 2, 4, 138, 72, }, + { 7, 1, 2, 4, 138, 127, }, + { 8, 1, 2, 4, 138, 72, }, + { 1, 1, 2, 4, 155, 127, }, + { 3, 1, 2, 4, 155, 72, }, + { 4, 1, 2, 4, 155, 68, }, + { 5, 1, 2, 4, 155, 72, }, + { 6, 1, 2, 4, 155, 72, }, + { 7, 1, 2, 4, 155, 54, }, + { 8, 1, 2, 4, 155, 68, }, + { 1, 1, 2, 5, 42, 50, }, + { 3, 1, 2, 5, 42, 40, }, + { 4, 1, 2, 5, 42, 58, }, + { 5, 1, 2, 5, 42, 40, }, + { 6, 1, 2, 5, 42, 52, }, + { 7, 1, 2, 5, 42, 30, }, + { 8, 1, 2, 5, 42, 50, }, + { 1, 1, 2, 5, 58, 50, }, + { 3, 1, 2, 5, 58, 40, }, + { 4, 1, 2, 5, 58, 56, }, + { 5, 1, 2, 5, 58, 40, }, + { 6, 1, 2, 5, 58, 52, }, + { 7, 1, 2, 5, 58, 30, }, + { 8, 1, 2, 5, 58, 52, }, + { 1, 1, 2, 5, 106, 72, }, + { 3, 1, 2, 5, 106, 50, }, + { 4, 1, 2, 5, 106, 56, }, + { 5, 1, 2, 5, 106, 40, }, + { 6, 1, 2, 5, 106, 50, }, + { 7, 1, 2, 5, 106, 30, }, + { 8, 1, 2, 5, 106, 50, }, + { 1, 1, 2, 5, 122, 72, }, + { 3, 1, 2, 5, 122, 127, }, + { 4, 1, 2, 5, 122, 56, }, + { 5, 1, 2, 5, 122, 127, }, + { 6, 1, 2, 5, 122, 66, }, + { 7, 1, 2, 5, 122, 30, }, + { 8, 1, 2, 5, 122, 66, }, + { 1, 1, 2, 5, 138, 127, }, + { 3, 1, 2, 5, 138, 66, }, + { 4, 1, 2, 5, 138, 58, }, + { 5, 1, 2, 5, 138, 127, }, + { 6, 1, 2, 5, 138, 66, }, + { 7, 1, 2, 5, 138, 127, }, + { 8, 1, 2, 5, 138, 66, }, + { 1, 1, 2, 5, 155, 127, }, + { 3, 1, 2, 5, 155, 62, }, + { 4, 1, 2, 5, 155, 58, }, + { 5, 1, 2, 5, 155, 72, }, + { 6, 1, 2, 5, 155, 62, }, + { 7, 1, 2, 5, 155, 30, }, + { 8, 1, 2, 5, 155, 62, }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type0); -- GitLab From 9236c1250cb7c6c645a658485efc2f99d57e96c2 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 16:29:19 +0800 Subject: [PATCH 2052/7155] bcma: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Kalle Valo --- drivers/bcma/host_pci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index f52239feb4cb..69c10a7b7c61 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -260,8 +260,7 @@ static void bcma_host_pci_remove(struct pci_dev *dev) #ifdef CONFIG_PM_SLEEP static int bcma_host_pci_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct bcma_bus *bus = pci_get_drvdata(pdev); + struct bcma_bus *bus = dev_get_drvdata(dev); bus->mapped_core = NULL; @@ -270,8 +269,7 @@ static int bcma_host_pci_suspend(struct device *dev) static int bcma_host_pci_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct bcma_bus *bus = pci_get_drvdata(pdev); + struct bcma_bus *bus = dev_get_drvdata(dev); return bcma_bus_resume(bus); } -- GitLab From 6334dea8880a4add8e5e0e4d3c311e7886c26f1c Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 24 Jul 2019 11:50:15 +0200 Subject: [PATCH 2053/7155] mwifiex: make error values consistent in mwifiex_update_bss_desc_with_ie() Surrounding code uses -ERRNO as a result, so don't pass plain -1. Signed-off-by: Pavel Machek Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 0d6d41727037..ddf75a58d314 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1243,7 +1243,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, mwifiex_dbg(adapter, ERROR, "err: InterpretIE: in processing\t" "IE, bytes left < IE length\n"); - return -1; + return -EINVAL; } switch (element_id) { case WLAN_EID_SSID: -- GitLab From 8f9af6309b84a33db2c790c9df77017d865d3983 Mon Sep 17 00:00:00 2001 From: Ganapathi Kondraju Date: Wed, 24 Jul 2019 16:07:21 +0530 Subject: [PATCH 2054/7155] rsi: fix for sdio interface setup in 9116 Issue: RS-9116 Card is not responding after firmware got loaded. Root cause: After firmware got loaded, we need to reset the program counter and few device specific registers. Those registers were not resetted properly. Fix: Properly resetting those registers. Signed-off-by: Ganapathi Kondraju Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 2a3577d8fb61..693be867a84a 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -944,7 +944,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter) put_unaligned_le32(TA_HOLD_THREAD_VALUE, data); addr = TA_HOLD_THREAD_REG | RSI_SD_REQUEST_MASTER; status = rsi_sdio_write_register_multiple(adapter, addr, - (u8 *)&data, + (u8 *)data, RSI_9116_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n"); @@ -954,7 +954,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter) put_unaligned_le32(TA_SOFT_RST_CLR, data); addr = TA_SOFT_RESET_REG | RSI_SD_REQUEST_MASTER; status = rsi_sdio_write_register_multiple(adapter, addr, - (u8 *)&data, + (u8 *)data, RSI_9116_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n"); @@ -964,7 +964,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter) put_unaligned_le32(TA_PC_ZERO, data); addr = TA_TH0_PC_REG | RSI_SD_REQUEST_MASTER; status = rsi_sdio_write_register_multiple(adapter, addr, - (u8 *)&data, + (u8 *)data, RSI_9116_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n"); @@ -975,7 +975,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter) put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data); addr = TA_RELEASE_THREAD_REG | RSI_SD_REQUEST_MASTER; status = rsi_sdio_write_register_multiple(adapter, addr, - (u8 *)&data, + (u8 *)data, RSI_9116_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "Unable to release TA threads\n"); -- GitLab From a40c28700d98d955f0d8fc96b5feb00b23fd8a6a Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:27:30 +0800 Subject: [PATCH 2055/7155] iwlegacy: Use dev_get_drvdata where possible Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 4a88e35d58d7..73f7bbf742bc 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -4942,8 +4942,7 @@ EXPORT_SYMBOL(il_add_beacon_time); static int il_pci_suspend(struct device *device) { - struct pci_dev *pdev = to_pci_dev(device); - struct il_priv *il = pci_get_drvdata(pdev); + struct il_priv *il = dev_get_drvdata(device); /* * This function is called when system goes into suspend state -- GitLab From ffa4d78cbc2644b4867b8129b3fbb5ddcdfcdba2 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:27:45 +0800 Subject: [PATCH 2056/7155] mwifiex: pcie: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index b54f73e3d508..eff06d59e9df 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -150,10 +150,8 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) static int mwifiex_pcie_suspend(struct device *dev) { struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - struct pci_dev *pdev = to_pci_dev(dev); + struct pcie_service_card *card = dev_get_drvdata(dev); - card = pci_get_drvdata(pdev); /* Might still be loading firmware */ wait_for_completion(&card->fw_done); @@ -195,10 +193,8 @@ static int mwifiex_pcie_suspend(struct device *dev) static int mwifiex_pcie_resume(struct device *dev) { struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - struct pci_dev *pdev = to_pci_dev(dev); + struct pcie_service_card *card = dev_get_drvdata(dev); - card = pci_get_drvdata(pdev); if (!card->adapter) { dev_err(dev, "adapter structure is not valid\n"); -- GitLab From 1f5f5ea72fc993a1ffdc8f7c16430c921cc16e16 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:27:53 +0800 Subject: [PATCH 2057/7155] qtnfmac_pcie: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c index e4e9344b6982..8ae318b5fe54 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c @@ -430,7 +430,7 @@ static int qtnf_pcie_suspend(struct device *dev) struct qtnf_pcie_bus_priv *priv; struct qtnf_bus *bus; - bus = pci_get_drvdata(to_pci_dev(dev)); + bus = dev_get_drvdata(dev); if (!bus) return -EFAULT; @@ -443,7 +443,7 @@ static int qtnf_pcie_resume(struct device *dev) struct qtnf_pcie_bus_priv *priv; struct qtnf_bus *bus; - bus = pci_get_drvdata(to_pci_dev(dev)); + bus = dev_get_drvdata(dev); if (!bus) return -EFAULT; -- GitLab From e7338e0319854e4bab7a6767c95d258f32cd18ea Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 19:28:02 +0800 Subject: [PATCH 2058/7155] rtlwifi: rtl_pci: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/pci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 4055e0ab75ba..7d96fe5f1a44 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -2409,8 +2409,7 @@ EXPORT_SYMBOL(rtl_pci_disconnect); ****************************************/ int rtl_pci_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ieee80211_hw *hw = dev_get_drvdata(dev); struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->cfg->ops->hw_suspend(hw); @@ -2422,8 +2421,7 @@ EXPORT_SYMBOL(rtl_pci_suspend); int rtl_pci_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ieee80211_hw *hw = dev_get_drvdata(dev); struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->cfg->ops->hw_resume(hw); -- GitLab From a4a68f727fb8be4cd738a45e01b3781d3fed79f9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 24 Jul 2019 22:10:20 +0800 Subject: [PATCH 2059/7155] rtlwifi: remove unneeded function _rtl_dump_channel_map() Now _rtl_dump_channel_map() does not do any actual thing using the channel. So remove it. Signed-off-by: YueHaibing Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/regd.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index 6ccb5b93a595..c10432cd703e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -276,22 +276,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, return; } -static void _rtl_dump_channel_map(struct wiphy *wiphy) -{ - enum nl80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - unsigned int i; - - for (band = 0; band < NUM_NL80211_BANDS; band++) { - if (!wiphy->bands[band]) - continue; - sband = wiphy->bands[band]; - for (i = 0; i < sband->n_channels; i++) - ch = &sband->channels[i]; - } -} - static int _rtl_reg_notifier_apply(struct wiphy *wiphy, struct regulatory_request *request, struct rtl_regulatory *reg) @@ -309,8 +293,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy, break; } - _rtl_dump_channel_map(wiphy); - return 0; } -- GitLab From cddecd92d1ec2fd05ed1123455e7c6cf6906b5a5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 24 Jul 2019 22:12:01 +0800 Subject: [PATCH 2060/7155] brcmfmac: remove set but not used variable 'dtim_period' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c: In function brcmf_update_bss_info: drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2962:5: warning: variable dtim_period set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c: In function brcmf_update_bss_info: drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2961:6: warning: variable beacon_interval set but not used [-Wunused-but-set-variable] They are never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index a5447519e1ab..581d0013f33e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -2982,8 +2982,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, struct brcmf_pub *drvr = cfg->pub; struct brcmf_bss_info_le *bi; const struct brcmf_tlv *tim; - u16 beacon_interval; - u8 dtim_period; size_t ie_len; u8 *ie; s32 err = 0; @@ -3007,12 +3005,9 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset); ie_len = le32_to_cpu(bi->ie_length); - beacon_interval = le16_to_cpu(bi->beacon_period); tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM); - if (tim) - dtim_period = tim->data[1]; - else { + if (!tim) { /* * active scan was done so we could not get dtim * information out of probe response. @@ -3024,7 +3019,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, bphy_err(drvr, "wl dtim_assoc failed (%d)\n", err); goto update_bss_info_out; } - dtim_period = (u8)var; } update_bss_info_out: -- GitLab From b95c732234fa40319c6aae2db6b35e9a7f41d79c Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Wed, 24 Jul 2019 09:17:36 -0500 Subject: [PATCH 2061/7155] mt7601u: null check the allocation devm_kzalloc may fail and return NULL. So the null check is needed. Signed-off-by: Navid Emamdoost Acked-by: Jakub Kicinski Signed-off-by: Kalle Valo --- drivers/net/wireless/mediatek/mt7601u/init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c index 9bfac9f1d47f..cada48800928 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c @@ -557,6 +557,9 @@ mt76_init_sband_2g(struct mt7601u_dev *dev) { dev->sband_2g = devm_kzalloc(dev->dev, sizeof(*dev->sband_2g), GFP_KERNEL); + if (!dev->sband_2g) + return -ENOMEM; + dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = dev->sband_2g; WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num > -- GitLab From 04f7745300edbb3fbb9447586b0aafeef28abd51 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 6 Aug 2019 06:57:50 -0400 Subject: [PATCH 2062/7155] thunderbolt: Show key using %*pE not %*pEp %*pEp (without "h" or "o") is a no-op. This string could contain arbitrary (non-NULL) characters, so we do want escaping. Use %*pE like every other caller. Signed-off-by: J. Bruce Fields Signed-off-by: Mika Westerberg --- drivers/thunderbolt/xdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index 5118d46702d5..4e17a7c7bf0a 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -636,7 +636,7 @@ static ssize_t key_show(struct device *dev, struct device_attribute *attr, * It should be null terminated but anything else is pretty much * allowed. */ - return sprintf(buf, "%*pEp\n", (int)strlen(svc->key), svc->key); + return sprintf(buf, "%*pE\n", (int)strlen(svc->key), svc->key); } static DEVICE_ATTR_RO(key); -- GitLab From 3915a252ce71b836a830bcc537220389a3acf3a5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 24 Jul 2019 09:38:15 -0500 Subject: [PATCH 2063/7155] libertas: Fix a double free in if_spi_c2h_data() The lbs_process_rxed_packet() frees the skb. It didn't originally, but we fixed it in commit f54930f36311 ("libertas: don't leak skb on receive error"). Reported-by: Dan Carpenter Signed-off-by: Dan Williams Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/if_spi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 27067e79e83f..d07fe82c557e 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -766,19 +766,15 @@ static int if_spi_c2h_data(struct if_spi_card *card) /* Read the data from the WLAN module into our skb... */ err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4)); - if (err) - goto free_skb; + if (err) { + dev_kfree_skb(skb); + goto out; + } /* pass the SKB to libertas */ err = lbs_process_rxed_packet(card->priv, skb); - if (err) - goto free_skb; - - /* success */ - goto out; + /* lbs_process_rxed_packet() consumes the skb */ -free_skb: - dev_kfree_skb(skb); out: if (err) netdev_err(priv->dev, "%s: err=%d\n", __func__, err); -- GitLab From dfc7a8f7c857369c3cee4aa4c12d6c8da7aa1597 Mon Sep 17 00:00:00 2001 From: Ganapathi Kondraju Date: Thu, 25 Jul 2019 16:21:50 +0530 Subject: [PATCH 2064/7155] rsi: fix for sdio reset card issue Issue: While removing and inserting the driver module, observed driver loading is not successful. Root cause: Card is not resetted completely without issuing cmd5. Fix: Issued cmd5 properly. Signed-off-by: Ganapathi Kondraju Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 693be867a84a..1bebba4e8527 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -230,19 +230,16 @@ static void rsi_reset_card(struct sdio_func *pfunction) rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err); /* Issue CMD5, arg = 0 */ - if (!host->ocr_avail) { - err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0, - (MMC_RSP_R4 | MMC_CMD_BCR), &resp); - if (err) - rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", - __func__, err); - - host->ocr_avail = resp; - } + err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0, + (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) + rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", + __func__, err); + card->ocr = resp; /* Issue CMD5, arg = ocr. Wait till card is ready */ for (i = 0; i < 100; i++) { err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, - host->ocr_avail, + card->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); if (err) { rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", -- GitLab From 937a194ae8651b434c4b4c62fe94099f41a93e14 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Jul 2019 11:06:14 +0100 Subject: [PATCH 2065/7155] ipw2x00: remove redundant assignment to err Variable err is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index 75c0c29d81f0..8dfbaff2d1fe 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -4413,7 +4413,7 @@ static void ipw2100_kill_works(struct ipw2100_priv *priv) static int ipw2100_tx_allocate(struct ipw2100_priv *priv) { - int i, j, err = -EINVAL; + int i, j, err; void *v; dma_addr_t p; -- GitLab From de019a3bdd6e68552e061f8c66b7cf7a18109c54 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:15:35 +0800 Subject: [PATCH 2066/7155] brcmsmac: remove three set but not used variables Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c: In function 'brcms_c_set_gmode': drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c:5257:7: warning: variable 'preamble_restrict' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c:5256:6: warning: variable 'preamble' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c:5251:7: warning: variable 'shortslot_restrict' set but not used [-Wunused-but-set-variable] They are never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../net/wireless/broadcom/brcm80211/brcmsmac/main.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 7d4e8f589fdc..080e829da9b3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -5248,15 +5248,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) /* Default to 54g Auto */ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */ s8 shortslot = BRCMS_SHORTSLOT_AUTO; - bool shortslot_restrict = false; /* Restrict association to stations - * that support shortslot - */ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */ - /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */ - int preamble = BRCMS_PLCP_LONG; - bool preamble_restrict = false; /* Restrict association to stations - * that support short preambles - */ struct brcms_band *band; /* if N-support is enabled, allow Gmode set as long as requested @@ -5297,16 +5289,11 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) case GMODE_ONLY: ofdm_basic = true; - preamble = BRCMS_PLCP_SHORT; - preamble_restrict = true; break; case GMODE_PERFORMANCE: shortslot = BRCMS_SHORTSLOT_ON; - shortslot_restrict = true; ofdm_basic = true; - preamble = BRCMS_PLCP_SHORT; - preamble_restrict = true; break; default: -- GitLab From d1b68c1182380e50cad4b7bd76ee68f64951a64b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:20:18 +0800 Subject: [PATCH 2067/7155] rtw88: pci: remove set but not used variable 'ip_sel' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtw88/pci.c: In function 'rtw_pci_phy_cfg': drivers/net/wireless/realtek/rtw88/pci.c:993:6: warning: variable 'ip_sel' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 23dd06afef3d..c56251539874 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -990,7 +990,6 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) u16 cut; u16 value; u16 offset; - u16 ip_sel; int i; cut = BIT(0) << rtwdev->hal.cut_version; @@ -1003,7 +1002,6 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) break; offset = para->offset; value = para->value; - ip_sel = para->ip_sel; if (para->ip_sel == RTW_IP_SEL_PHY) rtw_mdio_write(rtwdev, offset, value, true); else @@ -1018,7 +1016,6 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) break; offset = para->offset; value = para->value; - ip_sel = para->ip_sel; if (para->ip_sel == RTW_IP_SEL_PHY) rtw_mdio_write(rtwdev, offset, value, false); else -- GitLab From 706f0182b1add0fc41a8c40662f659b7426f0629 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 28 Jul 2019 23:07:42 +0900 Subject: [PATCH 2068/7155] rt2800usb: Add new rt2800usb device PLANEX GW-USMicroN This patch add a device ID for PLANEX GW-USMicroN. Without this patch, I had to echo the device IDs in order to recognize the device. # lsusb |grep PLANEX Bus 002 Device 005: ID 2019:ed14 PLANEX GW-USMicroN Signed-off-by: Masanari Iida Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index fdf0504b5f1d..0dfb55c69b73 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -1086,6 +1086,7 @@ static const struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0846, 0x9013) }, { USB_DEVICE(0x0846, 0x9019) }, /* Planex */ + { USB_DEVICE(0x2019, 0xed14) }, { USB_DEVICE(0x2019, 0xed19) }, /* Ralink */ { USB_DEVICE(0x148f, 0x3573) }, -- GitLab From b97494f48d5a0cf0b5a8bfec861c7311db987ad2 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 Jul 2019 19:33:00 -0500 Subject: [PATCH 2069/7155] rtlwifi: rtl8188ee: Remove unused GET_XXX and SET_XXX descriptor macros As the first step in converting from macros that get/set information in the RX and TX descriptors, unused macros are being removed. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8188ee/trx.h | 267 +----------------- 1 file changed, 6 insertions(+), 261 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index c29d9bfa5bd4..60efabc6f87a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -28,31 +28,9 @@ SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) #define SET_TX_DESC_LINIP(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) #define SET_TX_DESC_OWN(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) #define GET_TX_DESC_OWN(__pdesc) \ LE_BITS_TO_4BYTE(__pdesc, 31, 1) @@ -60,144 +38,39 @@ SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) -#define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) + #define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_BT_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) #define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) #define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) + #define SET_TX_DESC_SEQ(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) -#define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val) -#define SET_TX_DESC_TAG1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val) -#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) - #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) #define SET_TX_DESC_QOS(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) -#define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ @@ -206,20 +79,10 @@ SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) #define SET_TX_DESC_TX_STBC(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ @@ -231,152 +94,34 @@ #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) - #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) + #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val) -#define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) + #define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) -#define SET_TX_DESC_NULL_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) -#define SET_TX_DESC_NULL_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) #define GET_RX_DESC_PKT_LEN(__pdesc) \ LE_BITS_TO_4BYTE(__pdesc, 0, 14) -- GitLab From 66b2b064ee54fea02a68589b0513a2586c7a482b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 Jul 2019 19:33:01 -0500 Subject: [PATCH 2070/7155] rtlwifi: rtl88188ee: Replace local bit manipulation macros This driver uses a set of local macros to manipulate the RX and TX descriptors, which are all little-endian quantities. These macros are replaced by the bitfield macros le32p_replace_bits() and le32_get_bits(). In several places, the macros operated on an entire 32-bit word. In these cases, a direct read or replacement is used. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8188ee/trx.h | 213 +++++++++--------- 1 file changed, 106 insertions(+), 107 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 60efabc6f87a..8147e95a4cc6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -15,241 +15,240 @@ #define CRCLENGTH 4 #define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)) #define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)) #define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)) #define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)) #define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)) #define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)) #define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)) #define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) #define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(31)) #define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(5, 0)) #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)) #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)) #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(20)) #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)) #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(30, 26)) #define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(12)) #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(13)) #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)) #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)) #define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(24)) #define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(25)) #define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)) #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, BIT(31)) #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)) #define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)) #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)) #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)) #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)) #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)) #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)) #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)) #define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(23, 22)) #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)) #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)) #define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)) #define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)) #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)) #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)) #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)) #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)) #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)) #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)) #define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) - + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, BIT(29)) #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)) #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) + le32_get_bits(*((__le32 *)(__pdesc + 28)), GENMASK(15, 0)) #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) + *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val) #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 32))) #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) + *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val) #define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)) #define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(14)) #define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(15)) #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)) #define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(22, 20)) #define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(23)) #define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)) #define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(26)) #define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(27)) #define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(28)) #define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(29)) #define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(30)) #define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(31)) #define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)) #define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)) #define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) #define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 6) + le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(5, 0)) #define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)) #define GET_RX_DESC_FAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)) #define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) + le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(19, 16)) #define GET_RX_DESC_A2_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) + le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(23, 20)) #define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(24)) #define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(25)) #define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(26)) #define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(27)) #define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) + le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(29, 28)) #define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(30)) #define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(31)) #define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) + le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(11, 0)) #define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) + le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(15, 12)) #define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) + le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)) #define GET_RX_DESC_RXHT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)) #define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(7)) #define GET_RX_DESC_SPLCP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)) #define GET_RX_DESC_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)) #define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(10)) #define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(11)) #define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) + le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(13, 12)) #define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 14, 2) + le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(15, 14)) #define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(29)) #define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(30)) #define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(31)) #define GET_RX_DESC_IV1(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 16))) #define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 20))) #define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 24))) #define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 28))) #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) + *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val) #define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + *(__le32 *)(__pdesc + 28) = cpu_to_le32(__val) /* TX report 2 format in Rx desc*/ #define GET_RX_RPT2_DESC_PKT_LEN(__status) \ - LE_BITS_TO_4BYTE(__status, 0, 9) + le32_get_bits(*((__le32 *)__status), GENMASK(8, 0)) #define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ - LE_BITS_TO_4BYTE(__status+16, 0, 32) + le32_to_cpu(*((__le32 *)(__status + 16))) #define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ - LE_BITS_TO_4BYTE(__status+20, 0, 32) + le32_to_cpu(*((__le32 *)(__status + 20))) #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(3, 0)) #define SET_EARLYMODE_LEN0(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4)) #define SET_EARLYMODE_LEN1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16)) #define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28)) #define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0)) #define SET_EARLYMODE_LEN3(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8)) #define SET_EARLYMODE_LEN4(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20)) #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ do { \ -- GitLab From 36eda7568f2e4e18ba248974f73767de7778f43a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 Jul 2019 19:33:02 -0500 Subject: [PATCH 2071/7155] rtlwifi: rtl8188ee: Convert macros that set descriptor As a first step in the conversion, the macros that set the RX and TX descriptors are converted to static inline routines, and the names are changed from upper to lower case. To minimize the changes in a given step, the input descriptor information is left as as a byte array (u8 *), even though it should be a little-endian word array (__le32 *). That will be changed in the next patch. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8188ee/dm.c | 6 +- .../wireless/realtek/rtlwifi/rtl8188ee/trx.c | 222 ++--- .../wireless/realtek/rtlwifi/rtl8188ee/trx.h | 760 ++++++++++++------ 3 files changed, 642 insertions(+), 346 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c index 85360353f557..1ba339788d3a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c @@ -1414,9 +1414,9 @@ void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)) { - SET_TX_DESC_ANTSEL_A(pdesc, pfat_table->antsel_a[mac_id]); - SET_TX_DESC_ANTSEL_B(pdesc, pfat_table->antsel_b[mac_id]); - SET_TX_DESC_ANTSEL_C(pdesc, pfat_table->antsel_c[mac_id]); + set_tx_desc_antsel_a(pdesc, pfat_table->antsel_a[mac_id]); + set_tx_desc_antsel_b(pdesc, pfat_table->antsel_b[mac_id]); + set_tx_desc_antsel_c(pdesc, pfat_table->antsel_c[mac_id]); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 483dc8bdc555..d5be69e72838 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -319,7 +319,7 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, u32 dwtmp = 0; memset(virtualaddress, 0, 8); - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + set_earlymode_pktnum(virtualaddress, ptcb_desc->empkt_num); if (ptcb_desc->empkt_num == 1) { dwtmp = ptcb_desc->empkt_len[0]; } else { @@ -327,7 +327,7 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; dwtmp += ptcb_desc->empkt_len[1]; } - SET_EARLYMODE_LEN0(virtualaddress, dwtmp); + set_earlymode_len0(virtualaddress, dwtmp); if (ptcb_desc->empkt_num <= 3) { dwtmp = ptcb_desc->empkt_len[2]; @@ -336,7 +336,7 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; dwtmp += ptcb_desc->empkt_len[3]; } - SET_EARLYMODE_LEN1(virtualaddress, dwtmp); + set_earlymode_len1(virtualaddress, dwtmp); if (ptcb_desc->empkt_num <= 5) { dwtmp = ptcb_desc->empkt_len[4]; } else { @@ -344,8 +344,8 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; dwtmp += ptcb_desc->empkt_len[5]; } - SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); + set_earlymode_len2_1(virtualaddress, dwtmp & 0xF); + set_earlymode_len2_2(virtualaddress, dwtmp >> 4); if (ptcb_desc->empkt_num <= 7) { dwtmp = ptcb_desc->empkt_len[6]; } else { @@ -353,7 +353,7 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; dwtmp += ptcb_desc->empkt_len[7]; } - SET_EARLYMODE_LEN3(virtualaddress, dwtmp); + set_earlymode_len3(virtualaddress, dwtmp); if (ptcb_desc->empkt_num <= 9) { dwtmp = ptcb_desc->empkt_len[8]; } else { @@ -361,7 +361,7 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; dwtmp += ptcb_desc->empkt_len[9]; } - SET_EARLYMODE_LEN4(virtualaddress, dwtmp); + set_earlymode_len4(virtualaddress, dwtmp); } bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, @@ -373,38 +373,38 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, struct rx_fwinfo_88e *p_drvinfo; struct ieee80211_hdr *hdr; u8 wake_match; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); + u32 phystatus = get_rx_desc_physt(pdesc); - status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); + status->packet_report_type = (u8)get_rx_status_desc_rpt_sel(pdesc); if (status->packet_report_type == TX_REPORT2) - status->length = (u16)GET_RX_RPT2_DESC_PKT_LEN(pdesc); + status->length = (u16)get_rx_rpt2_desc_pkt_len(pdesc); else - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + status->length = (u16)get_rx_desc_pkt_len(pdesc); + status->rx_drvinfo_size = (u8)get_rx_desc_drv_info_size(pdesc) * RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16)GET_RX_DESC_ICV(pdesc); - status->crc = (u16)GET_RX_DESC_CRC32(pdesc); + status->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03); + status->icv = (u16)get_rx_desc_icv(pdesc); + status->crc = (u16)get_rx_desc_crc32(pdesc); status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); - status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && - (GET_RX_DESC_FAGGR(pdesc) == 1)); + status->decrypted = !get_rx_desc_swdec(pdesc); + status->rate = (u8)get_rx_desc_rxmcs(pdesc); + status->shortpreamble = (u16)get_rx_desc_splcp(pdesc); + status->isampdu = (bool) (get_rx_desc_paggr(pdesc) == 1); + status->isfirst_ampdu = (bool)((get_rx_desc_paggr(pdesc) == 1) && + (get_rx_desc_faggr(pdesc) == 1)); if (status->packet_report_type == NORMAL_RX) - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); - status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + status->timestamp_low = get_rx_desc_tsfl(pdesc); + status->rx_is40mhzpacket = (bool)get_rx_desc_bw(pdesc); + status->is_ht = (bool)get_rx_desc_rxht(pdesc); status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); - status->macid = GET_RX_DESC_MACID(pdesc); - if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) + status->macid = get_rx_desc_macid(pdesc); + if (get_rx_status_desc_pattern_match(pdesc)) wake_match = BIT(2); - else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + else if (get_rx_status_desc_magic_match(pdesc)) wake_match = BIT(1); - else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) + else if (get_rx_status_desc_unicast_match(pdesc)) wake_match = BIT(0); else wake_match = 0; @@ -465,9 +465,9 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, rx_status->signal = status->recvsignalpower + 10; if (status->packet_report_type == TX_REPORT2) { status->macid_valid_entry[0] = - GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); + get_rx_rpt2_desc_macid_valid_1(pdesc); status->macid_valid_entry[1] = - GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); + get_rx_rpt2_desc_macid_valid_2(pdesc); } return true; } @@ -528,8 +528,8 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, } if (firstseg) { if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + + set_tx_desc_pkt_offset(pdesc, 1); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN + EM_HDR_LEN); if (ptcb_desc->empkt_num) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, @@ -539,59 +539,59 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, (u8 *)(skb->data)); } } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); } ptcb_desc->use_driver_rate = true; - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + set_tx_desc_tx_rate(pdesc, ptcb_desc->hw_rate); if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; else short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; - SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); + set_tx_desc_data_shortgi(pdesc, short_gi); if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + set_tx_desc_agg_enable(pdesc, 1); + set_tx_desc_max_agg_num(pdesc, 0x14); } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + set_tx_desc_seq(pdesc, seq_number); + set_tx_desc_rts_enable(pdesc, ((ptcb_desc->rts_enable && !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); - SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, + set_tx_desc_hw_rts_enable(pdesc, 0); + set_tx_desc_cts2self(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); + set_tx_desc_rts_stbc(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); + + set_tx_desc_rts_rate(pdesc, ptcb_desc->rts_rate); + set_tx_desc_rts_bw(pdesc, 0); + set_tx_desc_rts_sc(pdesc, ptcb_desc->rts_sc); + set_tx_desc_rts_short(pdesc, ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); if (ptcb_desc->tx_enable_sw_calc_duration) - SET_TX_DESC_NAV_USE_HDR(pdesc, 1); + set_tx_desc_nav_use_hdr(pdesc, 1); if (bw_40) { if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + set_tx_desc_data_bw(pdesc, 1); + set_tx_desc_tx_sub_carrier(pdesc, 3); } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, + set_tx_desc_data_bw(pdesc, 0); + set_tx_desc_tx_sub_carrier(pdesc, mac->cur_40_prime_sc); } } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + set_tx_desc_data_bw(pdesc, 0); + set_tx_desc_tx_sub_carrier(pdesc, 0); } - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb_len); + set_tx_desc_linip(pdesc, 0); + set_tx_desc_pkt_size(pdesc, (u16)skb_len); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + set_tx_desc_ampdu_density(pdesc, ampdu_density); } if (info->control.hw_key) { struct ieee80211_key_conf *keyconf; @@ -601,63 +601,63 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + set_tx_desc_sec_type(pdesc, 0x1); break; case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + set_tx_desc_sec_type(pdesc, 0x3); break; default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + set_tx_desc_sec_type(pdesc, 0x0); break; } } - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? + set_tx_desc_queue_sel(pdesc, fw_qsel); + set_tx_desc_data_rate_fb_limit(pdesc, 0x1F); + set_tx_desc_rts_rate_fb_limit(pdesc, 0xF); + set_tx_desc_disable_fb(pdesc, ptcb_desc->disable_ratefallback ? 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + set_tx_desc_use_rate(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ + /*set_tx_desc_pwr_status(pdesc, pwr_status);*/ /* Set TxRate and RTSRate in TxDesc */ /* This prevent Tx initial rate of new-coming packets */ /* from being overwritten by retried packet rate.*/ if (!ptcb_desc->use_driver_rate) { - /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ - /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ + /*set_tx_desc_rts_rate(pdesc, 0x08); */ + /* set_tx_desc_tx_rate(pdesc, 0x0b); */ } if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); + set_tx_desc_rdg_enable(pdesc, 1); + set_tx_desc_htc(pdesc, 1); } } } - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)buf_len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + set_tx_desc_first_seg(pdesc, (firstseg ? 1 : 0)); + set_tx_desc_last_seg(pdesc, (lastseg ? 1 : 0)); + set_tx_desc_tx_buffer_size(pdesc, (u16)buf_len); + set_tx_desc_tx_buffer_address(pdesc, mapping); if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + set_tx_desc_rate_id(pdesc, ptcb_desc->ratr_index); + set_tx_desc_macid(pdesc, ptcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); + set_tx_desc_rate_id(pdesc, 0xC + ptcb_desc->ratr_index); + set_tx_desc_macid(pdesc, ptcb_desc->ratr_index); } if (ieee80211_is_data_qos(fc)) - SET_TX_DESC_QOS(pdesc, 1); + set_tx_desc_qos(pdesc, 1); if (!ieee80211_is_data_qos(fc)) - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + set_tx_desc_hwseq_en(pdesc, 1); + set_tx_desc_more_frag(pdesc, (lastseg ? 0 : 1)); if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); + set_tx_desc_bmc(pdesc, 1); } rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); @@ -687,39 +687,39 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + set_tx_desc_tx_rate(pdesc, DESC92C_RATE1M); - SET_TX_DESC_SEQ(pdesc, 0); + set_tx_desc_seq(pdesc, 0); - SET_TX_DESC_LINIP(pdesc, 0); + set_tx_desc_linip(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + set_tx_desc_queue_sel(pdesc, fw_queue); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); + set_tx_desc_first_seg(pdesc, 1); + set_tx_desc_last_seg(pdesc, 1); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + set_tx_desc_tx_buffer_size(pdesc, (u16)(skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + set_tx_desc_tx_buffer_address(pdesc, mapping); - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); + set_tx_desc_rate_id(pdesc, 7); + set_tx_desc_macid(pdesc, 0); - SET_TX_DESC_OWN(pdesc, 1); + set_tx_desc_own(pdesc, 1); - SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + set_tx_desc_pkt_size(pdesc, (u16)(skb->len)); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); + set_tx_desc_first_seg(pdesc, 1); + set_tx_desc_last_seg(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, 0x20); + set_tx_desc_offset(pdesc, 0x20); - SET_TX_DESC_USE_RATE(pdesc, 1); + set_tx_desc_use_rate(pdesc, 1); if (!ieee80211_is_data_qos(fc)) - SET_TX_DESC_HWSEQ_EN(pdesc, 1); + set_tx_desc_hwseq_en(pdesc, 1); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content\n", @@ -732,10 +732,10 @@ void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, if (istx == true) { switch (desc_name) { case HW_DESC_OWN: - SET_TX_DESC_OWN(pdesc, 1); + set_tx_desc_own(pdesc, 1); break; case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); + set_tx_desc_next_desc_address(pdesc, *(u32 *)val); break; default: WARN_ONCE(true, "rtl8188ee: ERR txdesc :%d not processed\n", @@ -745,16 +745,16 @@ void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, } else { switch (desc_name) { case HW_DESC_RXOWN: - SET_RX_DESC_OWN(pdesc, 1); + set_rx_desc_own(pdesc, 1); break; case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); + set_rx_desc_buff_addr(pdesc, *(u32 *)val); break; case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); + set_rx_desc_pkt_len(pdesc, *(u32 *)val); break; case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); + set_rx_desc_eor(pdesc, 1); break; default: WARN_ONCE(true, "rtl8188ee: ERR rxdesc :%d not processed\n", @@ -772,10 +772,10 @@ u64 rtl88ee_get_desc(struct ieee80211_hw *hw, if (istx == true) { switch (desc_name) { case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); + ret = get_tx_desc_own(pdesc); break; case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); + ret = get_tx_desc_tx_buffer_address(pdesc); break; default: WARN_ONCE(true, "rtl8188ee: ERR txdesc :%d not processed\n", @@ -785,13 +785,13 @@ u64 rtl88ee_get_desc(struct ieee80211_hw *hw, } else { switch (desc_name) { case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); + ret = get_rx_desc_own(pdesc); break; case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); + ret = get_rx_desc_pkt_len(pdesc); break; case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); + ret = get_rx_desc_buff_addr(pdesc); break; default: WARN_ONCE(true, "rtl8188ee: ERR rxdesc :%d not processed\n", diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 8147e95a4cc6..6b054361ed5d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -14,241 +14,537 @@ #define USB_HWDESC_HEADER_LEN 32 #define CRCLENGTH 4 -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) - -#define GET_TX_DESC_OWN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(31)) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(5, 0)) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(20)) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(30, 26)) - -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(12)) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(13)) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(24)) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(25)) - -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, BIT(31)) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(23, 22)) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)) - -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)) - -#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, BIT(29)) -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)) -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 28)), GENMASK(15, 0)) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 32))) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)) -#define GET_RX_DESC_CRC32(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(14)) -#define GET_RX_DESC_ICV(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(15)) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)) -#define GET_RX_DESC_SECURITY(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(22, 20)) -#define GET_RX_DESC_QOS(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(23)) -#define GET_RX_DESC_SHIFT(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)) -#define GET_RX_DESC_PHYST(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(26)) -#define GET_RX_DESC_SWDEC(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(27)) -#define GET_RX_DESC_LS(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(28)) -#define GET_RX_DESC_FS(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(29)) -#define GET_RX_DESC_EOR(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(30)) -#define GET_RX_DESC_OWN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(31)) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) - -#define GET_RX_DESC_MACID(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(5, 0)) -#define GET_RX_DESC_PAGGR(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)) -#define GET_RX_DESC_FAGGR(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(19, 16)) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(23, 20)) -#define GET_RX_DESC_PAM(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(24)) -#define GET_RX_DESC_PWR(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(25)) -#define GET_RX_DESC_MD(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(26)) -#define GET_RX_DESC_MF(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(27)) -#define GET_RX_DESC_TYPE(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(29, 28)) -#define GET_RX_DESC_MC(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(30)) -#define GET_RX_DESC_BC(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(31)) -#define GET_RX_DESC_SEQ(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(11, 0)) -#define GET_RX_DESC_FRAG(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(15, 12)) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)) -#define GET_RX_DESC_RXHT(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)) -#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(7)) -#define GET_RX_DESC_SPLCP(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)) -#define GET_RX_DESC_BW(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)) -#define GET_RX_DESC_HTC(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(10)) -#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(11)) -#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(13, 12)) -#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(15, 14)) - -#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(29)) -#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(30)) -#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(31)) - -#define GET_RX_DESC_IV1(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 16))) -#define GET_RX_DESC_TSFL(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 20))) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 24))) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 28))) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - *(__le32 *)(__pdesc + 28) = cpu_to_le32(__val) +static inline void set_tx_desc_pkt_size(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)); +} + +static inline void set_tx_desc_offset(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)); +} + +static inline void set_tx_desc_bmc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)); +} + +static inline void set_tx_desc_htc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)); +} + +static inline void set_tx_desc_last_seg(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)); +} + +static inline void set_tx_desc_first_seg(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)); +} + +static inline void set_tx_desc_linip(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)); +} + +static inline void set_tx_desc_own(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); +} + +static inline int get_tx_desc_own(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); +} + +static inline void set_tx_desc_macid(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(5, 0)); +} + +static inline void set_tx_desc_queue_sel(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)); +} + +static inline void set_tx_desc_rate_id(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)); +} + +static inline void set_tx_desc_nav_use_hdr(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(20)); +} + +static inline void set_tx_desc_sec_type(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)); +} + +static inline void set_tx_desc_pkt_offset(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(30, 26)); +} + +static inline void set_tx_desc_agg_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(12)); +} + +static inline void set_tx_desc_rdg_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(13)); +} + +static inline void set_tx_desc_more_frag(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)); +} + +static inline void set_tx_desc_ampdu_density(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)); +} + +static inline void set_tx_desc_antsel_a(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(24)); +} + +static inline void set_tx_desc_antsel_b(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(25)); +} + +static inline void set_tx_desc_seq(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)); +} + +static inline void set_tx_desc_hwseq_en(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, BIT(31)); +} + +static inline void set_tx_desc_rts_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)); +} + +static inline void set_tx_desc_qos(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)); +} + +static inline void set_tx_desc_use_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)); +} + +static inline void set_tx_desc_disable_fb(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)); +} + +static inline void set_tx_desc_cts2self(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)); +} + +static inline void set_tx_desc_rts_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)); +} + +static inline void set_tx_desc_hw_rts_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)); +} + +static inline void set_tx_desc_tx_sub_carrier(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)); +} + +static inline void set_tx_desc_tx_stbc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(23, 22)); +} + +static inline void set_tx_desc_data_bw(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)); +} + +static inline void set_tx_desc_rts_short(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)); +} + +static inline void set_tx_desc_rts_bw(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)); +} + +static inline void set_tx_desc_rts_sc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)); +} + +static inline void set_tx_desc_rts_stbc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)); +} + +static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)); +} + +static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)); +} + +static inline void set_tx_desc_data_rate_fb_limit(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)); +} + +static inline void set_tx_desc_rts_rate_fb_limit(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)); +} + +static inline void set_tx_desc_max_agg_num(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)); +} + +static inline void set_tx_desc_antsel_c(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, BIT(29)); +} + +static inline void set_tx_desc_tx_buffer_size(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)); +} + +static inline int get_tx_desc_tx_buffer_size(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 28)), GENMASK(15, 0)); +} + +static inline void set_tx_desc_tx_buffer_address(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val); +} + +static inline int get_tx_desc_tx_buffer_address(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 32))); +} + +static inline void set_tx_desc_next_desc_address(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val); +} + +static inline int get_rx_desc_pkt_len(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)); +} + +static inline int get_rx_desc_crc32(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(14)); +} + +static inline int get_rx_desc_icv(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(15)); +} + +static inline int get_rx_desc_drv_info_size(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)); +} + +static inline int get_rx_desc_security(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(22, 20)); +} + +static inline int get_rx_desc_qos(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(23)); +} + +static inline int get_rx_desc_shift(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)); +} + +static inline int get_rx_desc_physt(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(26)); +} + +static inline int get_rx_desc_swdec(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(27)); +} + +static inline int get_rx_desc_ls(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(28)); +} + +static inline int get_rx_desc_fs(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(29)); +} + +static inline int get_rx_desc_eor(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(30)); +} + +static inline int get_rx_desc_own(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); +} + +static inline void set_rx_desc_pkt_len(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)); +} + +static inline void set_rx_desc_eor(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)); +} + +static inline void set_rx_desc_own(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); +} + +static inline int get_rx_desc_macid(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(5, 0)); +} + +static inline int get_rx_desc_paggr(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)); +} + +static inline int get_rx_desc_faggr(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)); +} + +static inline int get_rx_desc_a1_fit(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(19, 16)); +} + +static inline int get_rx_desc_a2_fit(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(23, 20)); +} + +static inline int get_rx_desc_pam(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(24)); +} + +static inline int get_rx_desc_pwr(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(25)); +} + +static inline int get_rx_desc_md(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(26)); +} + +static inline int get_rx_desc_mf(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(27)); +} + +static inline int get_rx_desc_type(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(29, 28)); +} + +static inline int get_rx_desc_mc(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(30)); +} + +static inline int get_rx_desc_bc(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(31)); +} + +static inline int get_rx_desc_seq(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(11, 0)); +} + +static inline int get_rx_desc_frag(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(15, 12)); +} + +static inline int get_rx_desc_rxmcs(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)); +} + +static inline int get_rx_desc_rxht(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)); +} + +static inline int get_rx_status_desc_rx_gf(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(7)); +} + +static inline int get_rx_desc_splcp(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)); +} + +static inline int get_rx_desc_bw(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)); +} + +static inline int get_rx_desc_htc(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(10)); +} + +static inline int get_rx_status_desc_eosp(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(11)); +} + +static inline int get_rx_status_desc_bssid_fit(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(13, 12)); +} + +static inline int get_rx_status_desc_rpt_sel(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(15, 14)); +} + +static inline int get_rx_status_desc_pattern_match(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(29)); +} + +static inline int get_rx_status_desc_unicast_match(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(30)); +} + +static inline int get_rx_status_desc_magic_match(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(31)); +} + +static inline int get_rx_desc_iv1(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 16))); +} + +static inline int get_rx_desc_tsfl(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 20))); +} + +static inline int get_rx_desc_buff_addr(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 24))); +} + +static inline int get_rx_desc_buff_addr64(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 28))); +} + +static inline void set_rx_desc_buff_addr(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val); +} + +static inline void set_rx_desc_buff_addr64(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 28) = cpu_to_le32(__val); +} /* TX report 2 format in Rx desc*/ -#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ - le32_get_bits(*((__le32 *)__status), GENMASK(8, 0)) -#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ - le32_to_cpu(*((__le32 *)(__status + 16))) -#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ - le32_to_cpu(*((__le32 *)(__status + 20))) - -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(3, 0)) -#define SET_EARLYMODE_LEN0(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4)) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16)) -#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28)) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0)) -#define SET_EARLYMODE_LEN3(__paddr, __value) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8)) -#define SET_EARLYMODE_LEN4(__paddr, __value) \ - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20)) +static inline int get_rx_rpt2_desc_pkt_len(u8 *__status) +{ + return le32_get_bits(*((__le32 *)__status), GENMASK(8, 0)); +} + +static inline int get_rx_rpt2_desc_macid_valid_1(u8 *__status) +{ + return le32_to_cpu(*((__le32 *)(__status + 16))); +} + +static inline int get_rx_rpt2_desc_macid_valid_2(u8 *__status) +{ + return le32_to_cpu(*((__le32 *)(__status + 20))); +} + +static inline void set_earlymode_pktnum(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(3, 0)); +} + +static inline void set_earlymode_len0(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4)); +} + +static inline void set_earlymode_len1(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16)); +} + +static inline void set_earlymode_len2_1(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28)); +} + +static inline void set_earlymode_len2_2(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0)); +} + +static inline void set_earlymode_len3(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8)); +} + +static inline void set_earlymode_len4(u8 *__paddr, u32 __value) +{ + le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20)); +} #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ do { \ -- GitLab From e53e30ba15da85a21195573db28ac35ba4e6ecf0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 Jul 2019 19:33:03 -0500 Subject: [PATCH 2072/7155] rtlwifi: rtl8188ee: Convert inline routines to little-endian words In this step, the read/write routines for the descriptors are converted to use __le32 quantities, thus a lot of casts can be removed. Callback routines still use the 8-bit arrays, but these are changed within the specified routine. The macro that cleared a descriptor has now been converted into an inline routine. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8188ee/dm.c | 7 +- .../wireless/realtek/rtlwifi/rtl8188ee/trx.c | 35 +- .../wireless/realtek/rtlwifi/rtl8188ee/trx.h | 438 +++++++++--------- 3 files changed, 243 insertions(+), 237 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c index 1ba339788d3a..333e355c9281 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c @@ -1411,12 +1411,13 @@ void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); struct fast_ant_training *pfat_table = &rtldm->fat_table; + __le32 *pdesc32 = (__le32 *)pdesc; if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)) { - set_tx_desc_antsel_a(pdesc, pfat_table->antsel_a[mac_id]); - set_tx_desc_antsel_b(pdesc, pfat_table->antsel_b[mac_id]); - set_tx_desc_antsel_c(pdesc, pfat_table->antsel_c[mac_id]); + set_tx_desc_antsel_a(pdesc32, pfat_table->antsel_a[mac_id]); + set_tx_desc_antsel_b(pdesc32, pfat_table->antsel_b[mac_id]); + set_tx_desc_antsel_c(pdesc32, pfat_table->antsel_c[mac_id]); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index d5be69e72838..aa2e9e88be53 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -25,7 +25,7 @@ static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) } static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, + struct rtl_stats *pstatus, __le32 *pdesc, struct rx_fwinfo_88e *p_drvinfo, bool bpacket_match_bssid, bool bpacket_toself, bool packet_beacon) @@ -271,7 +271,7 @@ static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw, static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_stats *pstatus, - u8 *pdesc, + __le32 *pdesc, struct rx_fwinfo_88e *p_drvinfo) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -313,8 +313,8 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, rtl_process_phyinfo(hw, tmp_buf, pstatus); } -static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) +static void rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + __le32 *virtualaddress) { u32 dwtmp = 0; memset(virtualaddress, 0, 8); @@ -367,12 +367,13 @@ static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *status, struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) + u8 *pdesc8, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rx_fwinfo_88e *p_drvinfo; struct ieee80211_hdr *hdr; u8 wake_match; + __le32 *pdesc = (__le32 *)pdesc8; u32 phystatus = get_rx_desc_physt(pdesc); status->packet_report_type = (u8)get_rx_status_desc_rpt_sel(pdesc); @@ -473,7 +474,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, } void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_hdr *hdr, u8 *pdesc8, u8 *txbd, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, @@ -484,7 +485,6 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; unsigned int buf_len = 0; @@ -497,6 +497,7 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, dma_addr_t mapping; u8 bw_40 = 0; u8 short_gi = 0; + __le32 *pdesc = (u32 *)pdesc8; if (mac->opmode == NL80211_IFTYPE_STATION) { bw_40 = mac->bw_40; @@ -521,7 +522,7 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, "DMA mapping error\n"); return; } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e)); + clear_pci_tx_desc_content(pdesc, sizeof(struct tx_desc_88e)); if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { firstseg = true; lastseg = true; @@ -535,8 +536,8 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "Insert 8 byte.pTcb->EMPktNum:%d\n", ptcb_desc->empkt_num); - _rtl88ee_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); + rtl88ee_insert_emcontent(ptcb_desc, + (__le32 *)(skb->data)); } } else { set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); @@ -660,17 +661,18 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, set_tx_desc_bmc(pdesc, 1); } - rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); + rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc8, ptcb_desc->mac_id); RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, + u8 *pdesc8, bool firstseg, bool lastseg, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 fw_queue = QSLT_BEACON; + __le32 *pdesc = (__le32 *)pdesc8; dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, @@ -684,7 +686,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, "DMA mapping error\n"); return; } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); if (firstseg) set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); @@ -726,9 +728,11 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, pdesc, TX_DESC_SIZE); } -void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, +void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc8, bool istx, u8 desc_name, u8 *val) { + __le32 *pdesc = (__le32 *)pdesc8; + if (istx == true) { switch (desc_name) { case HW_DESC_OWN: @@ -765,9 +769,10 @@ void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, } u64 rtl88ee_get_desc(struct ieee80211_hw *hw, - u8 *pdesc, bool istx, u8 desc_name) + u8 *pdesc8, bool istx, u8 desc_name) { u32 ret = 0; + __le32 *pdesc = (__le32 *)pdesc8; if (istx == true) { switch (desc_name) { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 6b054361ed5d..4e3682ded89e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -14,545 +14,545 @@ #define USB_HWDESC_HEADER_LEN 32 #define CRCLENGTH 4 -static inline void set_tx_desc_pkt_size(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_pkt_size(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)); + le32p_replace_bits(__pdesc, __val, GENMASK(15, 0)); } -static inline void set_tx_desc_offset(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_offset(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)); + le32p_replace_bits(__pdesc, __val, GENMASK(23, 16)); } -static inline void set_tx_desc_bmc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_bmc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)); + le32p_replace_bits(__pdesc, __val, BIT(24)); } -static inline void set_tx_desc_htc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_htc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)); + le32p_replace_bits(__pdesc, __val, BIT(25)); } -static inline void set_tx_desc_last_seg(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_last_seg(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)); + le32p_replace_bits(__pdesc, __val, BIT(26)); } -static inline void set_tx_desc_first_seg(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_first_seg(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)); + le32p_replace_bits(__pdesc, __val, BIT(27)); } -static inline void set_tx_desc_linip(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_linip(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)); + le32p_replace_bits(__pdesc, __val, BIT(28)); } -static inline void set_tx_desc_own(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_own(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); + le32p_replace_bits(__pdesc, __val, BIT(31)); } -static inline int get_tx_desc_own(u8 *__pdesc) +static inline int get_tx_desc_own(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); + return le32_get_bits(*(__pdesc), BIT(31)); } -static inline void set_tx_desc_macid(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_macid(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(5, 0)); + le32p_replace_bits(__pdesc + 1, __val, GENMASK(5, 0)); } -static inline void set_tx_desc_queue_sel(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_queue_sel(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)); + le32p_replace_bits(__pdesc + 1, __val, GENMASK(12, 8)); } -static inline void set_tx_desc_rate_id(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rate_id(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)); + le32p_replace_bits(__pdesc + 1, __val, GENMASK(19, 16)); } -static inline void set_tx_desc_nav_use_hdr(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_nav_use_hdr(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(20)); + le32p_replace_bits(__pdesc + 1, __val, BIT(20)); } -static inline void set_tx_desc_sec_type(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_sec_type(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)); + le32p_replace_bits(__pdesc + 1, __val, GENMASK(23, 22)); } -static inline void set_tx_desc_pkt_offset(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_pkt_offset(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(30, 26)); + le32p_replace_bits(__pdesc + 1, __val, GENMASK(30, 26)); } -static inline void set_tx_desc_agg_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_agg_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(12)); + le32p_replace_bits(__pdesc + 2, __val, BIT(12)); } -static inline void set_tx_desc_rdg_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rdg_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(13)); + le32p_replace_bits(__pdesc + 2, __val, BIT(13)); } -static inline void set_tx_desc_more_frag(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_more_frag(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)); + le32p_replace_bits(__pdesc + 2, __val, BIT(17)); } -static inline void set_tx_desc_ampdu_density(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_ampdu_density(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)); + le32p_replace_bits(__pdesc + 2, __val, GENMASK(22, 20)); } -static inline void set_tx_desc_antsel_a(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_antsel_a(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(24)); + le32p_replace_bits(__pdesc + 2, __val, BIT(24)); } -static inline void set_tx_desc_antsel_b(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_antsel_b(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(25)); + le32p_replace_bits(__pdesc + 2, __val, BIT(25)); } -static inline void set_tx_desc_seq(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_seq(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)); + le32p_replace_bits(__pdesc + 3, __val, GENMASK(27, 16)); } -static inline void set_tx_desc_hwseq_en(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_hwseq_en(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, BIT(31)); + le32p_replace_bits(__pdesc + 3, __val, BIT(31)); } -static inline void set_tx_desc_rts_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)); + le32p_replace_bits(__pdesc + 4, __val, GENMASK(4, 0)); } -static inline void set_tx_desc_qos(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_qos(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)); + le32p_replace_bits(__pdesc + 4, __val, BIT(6)); } -static inline void set_tx_desc_use_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_use_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)); + le32p_replace_bits(__pdesc + 4, __val, BIT(8)); } -static inline void set_tx_desc_disable_fb(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_disable_fb(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)); + le32p_replace_bits(__pdesc + 4, __val, BIT(10)); } -static inline void set_tx_desc_cts2self(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_cts2self(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)); + le32p_replace_bits(__pdesc + 4, __val, BIT(11)); } -static inline void set_tx_desc_rts_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)); + le32p_replace_bits(__pdesc + 4, __val, BIT(12)); } -static inline void set_tx_desc_hw_rts_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_hw_rts_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)); + le32p_replace_bits(__pdesc + 4, __val, BIT(13)); } -static inline void set_tx_desc_tx_sub_carrier(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_sub_carrier(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)); + le32p_replace_bits(__pdesc + 4, __val, GENMASK(21, 20)); } -static inline void set_tx_desc_tx_stbc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_stbc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(23, 22)); + le32p_replace_bits(__pdesc + 4, __val, GENMASK(23, 22)); } -static inline void set_tx_desc_data_bw(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_bw(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)); + le32p_replace_bits(__pdesc + 4, __val, BIT(25)); } -static inline void set_tx_desc_rts_short(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_short(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)); + le32p_replace_bits(__pdesc + 4, __val, BIT(26)); } -static inline void set_tx_desc_rts_bw(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_bw(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)); + le32p_replace_bits(__pdesc + 4, __val, BIT(27)); } -static inline void set_tx_desc_rts_sc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_sc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)); + le32p_replace_bits(__pdesc + 4, __val, GENMASK(29, 28)); } -static inline void set_tx_desc_rts_stbc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_stbc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)); + le32p_replace_bits(__pdesc + 4, __val, GENMASK(31, 30)); } -static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)); + le32p_replace_bits(__pdesc + 5, __val, GENMASK(5, 0)); } -static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_shortgi(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)); + le32p_replace_bits(__pdesc + 5, __val, BIT(6)); } -static inline void set_tx_desc_data_rate_fb_limit(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_rate_fb_limit(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)); + le32p_replace_bits(__pdesc + 5, __val, GENMASK(12, 8)); } -static inline void set_tx_desc_rts_rate_fb_limit(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_rate_fb_limit(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)); + le32p_replace_bits(__pdesc + 5, __val, GENMASK(16, 13)); } -static inline void set_tx_desc_max_agg_num(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_max_agg_num(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)); + le32p_replace_bits(__pdesc + 6, __val, GENMASK(15, 11)); } -static inline void set_tx_desc_antsel_c(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_antsel_c(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, BIT(29)); + le32p_replace_bits(__pdesc + 7, __val, BIT(29)); } -static inline void set_tx_desc_tx_buffer_size(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_buffer_size(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)); + le32p_replace_bits(__pdesc + 7, __val, GENMASK(15, 0)); } -static inline int get_tx_desc_tx_buffer_size(u8 *__pdesc) +static inline int get_tx_desc_tx_buffer_size(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 28)), GENMASK(15, 0)); + return le32_get_bits(*(__pdesc + 7), GENMASK(15, 0)); } -static inline void set_tx_desc_tx_buffer_address(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_buffer_address(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val); + *(__pdesc + 8) = cpu_to_le32(__val); } -static inline int get_tx_desc_tx_buffer_address(u8 *__pdesc) +static inline int get_tx_desc_tx_buffer_address(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 32))); + return le32_to_cpu(*(__pdesc + 8)); } -static inline void set_tx_desc_next_desc_address(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_next_desc_address(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val); + *(__pdesc + 10) = cpu_to_le32(__val); } -static inline int get_rx_desc_pkt_len(u8 *__pdesc) +static inline int get_rx_desc_pkt_len(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)); + return le32_get_bits(*(__pdesc), GENMASK(13, 0)); } -static inline int get_rx_desc_crc32(u8 *__pdesc) +static inline int get_rx_desc_crc32(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(14)); + return le32_get_bits(*(__pdesc), BIT(14)); } -static inline int get_rx_desc_icv(u8 *__pdesc) +static inline int get_rx_desc_icv(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(15)); + return le32_get_bits(*(__pdesc), BIT(15)); } -static inline int get_rx_desc_drv_info_size(u8 *__pdesc) +static inline int get_rx_desc_drv_info_size(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)); + return le32_get_bits(*(__pdesc), GENMASK(19, 16)); } -static inline int get_rx_desc_security(u8 *__pdesc) +static inline int get_rx_desc_security(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(22, 20)); + return le32_get_bits(*(__pdesc), GENMASK(22, 20)); } -static inline int get_rx_desc_qos(u8 *__pdesc) +static inline int get_rx_desc_qos(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(23)); + return le32_get_bits(*(__pdesc), BIT(23)); } -static inline int get_rx_desc_shift(u8 *__pdesc) +static inline int get_rx_desc_shift(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)); + return le32_get_bits(*(__pdesc), GENMASK(25, 24)); } -static inline int get_rx_desc_physt(u8 *__pdesc) +static inline int get_rx_desc_physt(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(26)); + return le32_get_bits(*(__pdesc), BIT(26)); } -static inline int get_rx_desc_swdec(u8 *__pdesc) +static inline int get_rx_desc_swdec(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(27)); + return le32_get_bits(*(__pdesc), BIT(27)); } -static inline int get_rx_desc_ls(u8 *__pdesc) +static inline int get_rx_desc_ls(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(28)); + return le32_get_bits(*(__pdesc), BIT(28)); } -static inline int get_rx_desc_fs(u8 *__pdesc) +static inline int get_rx_desc_fs(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(29)); + return le32_get_bits(*(__pdesc), BIT(29)); } -static inline int get_rx_desc_eor(u8 *__pdesc) +static inline int get_rx_desc_eor(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(30)); + return le32_get_bits(*(__pdesc), BIT(30)); } -static inline int get_rx_desc_own(u8 *__pdesc) +static inline int get_rx_desc_own(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); + return le32_get_bits(*(__pdesc), BIT(31)); } -static inline void set_rx_desc_pkt_len(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_pkt_len(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)); + le32p_replace_bits(__pdesc, __val, GENMASK(13, 0)); } -static inline void set_rx_desc_eor(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_eor(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)); + le32p_replace_bits(__pdesc, __val, BIT(30)); } -static inline void set_rx_desc_own(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_own(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); + le32p_replace_bits(__pdesc, __val, BIT(31)); } -static inline int get_rx_desc_macid(u8 *__pdesc) +static inline int get_rx_desc_macid(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(5, 0)); + return le32_get_bits(*(__pdesc + 1), GENMASK(5, 0)); } -static inline int get_rx_desc_paggr(u8 *__pdesc) +static inline int get_rx_desc_paggr(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)); + return le32_get_bits(*(__pdesc + 1), BIT(14)); } -static inline int get_rx_desc_faggr(u8 *__pdesc) +static inline int get_rx_desc_faggr(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)); + return le32_get_bits(*(__pdesc + 1), BIT(15)); } -static inline int get_rx_desc_a1_fit(u8 *__pdesc) +static inline int get_rx_desc_a1_fit(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(19, 16)); + return le32_get_bits(*(__pdesc + 1), GENMASK(19, 16)); } -static inline int get_rx_desc_a2_fit(u8 *__pdesc) +static inline int get_rx_desc_a2_fit(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(23, 20)); + return le32_get_bits(*(__pdesc + 1), GENMASK(23, 20)); } -static inline int get_rx_desc_pam(u8 *__pdesc) +static inline int get_rx_desc_pam(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(24)); + return le32_get_bits(*(__pdesc + 1), BIT(24)); } -static inline int get_rx_desc_pwr(u8 *__pdesc) +static inline int get_rx_desc_pwr(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(25)); + return le32_get_bits(*(__pdesc + 1), BIT(25)); } -static inline int get_rx_desc_md(u8 *__pdesc) +static inline int get_rx_desc_md(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(26)); + return le32_get_bits(*(__pdesc + 1), BIT(26)); } -static inline int get_rx_desc_mf(u8 *__pdesc) +static inline int get_rx_desc_mf(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(27)); + return le32_get_bits(*(__pdesc + 1), BIT(27)); } -static inline int get_rx_desc_type(u8 *__pdesc) +static inline int get_rx_desc_type(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), GENMASK(29, 28)); + return le32_get_bits(*(__pdesc + 1), GENMASK(29, 28)); } -static inline int get_rx_desc_mc(u8 *__pdesc) +static inline int get_rx_desc_mc(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(30)); + return le32_get_bits(*(__pdesc + 1), BIT(30)); } -static inline int get_rx_desc_bc(u8 *__pdesc) +static inline int get_rx_desc_bc(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(31)); + return le32_get_bits(*(__pdesc + 1), BIT(31)); } -static inline int get_rx_desc_seq(u8 *__pdesc) +static inline int get_rx_desc_seq(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(11, 0)); + return le32_get_bits(*(__pdesc + 2), GENMASK(11, 0)); } -static inline int get_rx_desc_frag(u8 *__pdesc) +static inline int get_rx_desc_frag(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 8)), GENMASK(15, 12)); + return le32_get_bits(*(__pdesc + 2), GENMASK(15, 12)); } -static inline int get_rx_desc_rxmcs(u8 *__pdesc) +static inline int get_rx_desc_rxmcs(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)); + return le32_get_bits(*(__pdesc + 3), GENMASK(5, 0)); } -static inline int get_rx_desc_rxht(u8 *__pdesc) +static inline int get_rx_desc_rxht(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)); + return le32_get_bits(*(__pdesc + 3), BIT(6)); } -static inline int get_rx_status_desc_rx_gf(u8 *__pdesc) +static inline int get_rx_status_desc_rx_gf(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(7)); + return le32_get_bits(*(__pdesc + 3), BIT(7)); } -static inline int get_rx_desc_splcp(u8 *__pdesc) +static inline int get_rx_desc_splcp(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)); + return le32_get_bits(*(__pdesc + 3), BIT(8)); } -static inline int get_rx_desc_bw(u8 *__pdesc) +static inline int get_rx_desc_bw(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)); + return le32_get_bits(*(__pdesc + 3), BIT(9)); } -static inline int get_rx_desc_htc(u8 *__pdesc) +static inline int get_rx_desc_htc(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(10)); + return le32_get_bits(*(__pdesc + 3), BIT(10)); } -static inline int get_rx_status_desc_eosp(u8 *__pdesc) +static inline int get_rx_status_desc_eosp(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(11)); + return le32_get_bits(*(__pdesc + 3), BIT(11)); } -static inline int get_rx_status_desc_bssid_fit(u8 *__pdesc) +static inline int get_rx_status_desc_bssid_fit(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(13, 12)); + return le32_get_bits(*(__pdesc + 3), GENMASK(13, 12)); } -static inline int get_rx_status_desc_rpt_sel(u8 *__pdesc) +static inline int get_rx_status_desc_rpt_sel(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(15, 14)); + return le32_get_bits(*(__pdesc + 3), GENMASK(15, 14)); } -static inline int get_rx_status_desc_pattern_match(u8 *__pdesc) +static inline int get_rx_status_desc_pattern_match(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(29)); + return le32_get_bits(*(__pdesc + 3), BIT(29)); } -static inline int get_rx_status_desc_unicast_match(u8 *__pdesc) +static inline int get_rx_status_desc_unicast_match(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(30)); + return le32_get_bits(*(__pdesc + 3), BIT(30)); } -static inline int get_rx_status_desc_magic_match(u8 *__pdesc) +static inline int get_rx_status_desc_magic_match(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(31)); + return le32_get_bits(*(__pdesc + 3), BIT(31)); } -static inline int get_rx_desc_iv1(u8 *__pdesc) +static inline int get_rx_desc_iv1(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 16))); + return le32_to_cpu(*(__pdesc + 4)); } -static inline int get_rx_desc_tsfl(u8 *__pdesc) +static inline int get_rx_desc_tsfl(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 20))); + return le32_to_cpu(*(__pdesc + 5)); } -static inline int get_rx_desc_buff_addr(u8 *__pdesc) +static inline int get_rx_desc_buff_addr(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 24))); + return le32_to_cpu(*(__pdesc + 6)); } -static inline int get_rx_desc_buff_addr64(u8 *__pdesc) +static inline int get_rx_desc_buff_addr64(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 28))); + return le32_to_cpu(*(__pdesc + 7)); } -static inline void set_rx_desc_buff_addr(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_buff_addr(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val); + *(__pdesc + 6) = cpu_to_le32(__val); } -static inline void set_rx_desc_buff_addr64(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_buff_addr64(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 28) = cpu_to_le32(__val); + *(__pdesc + 7) = cpu_to_le32(__val); } /* TX report 2 format in Rx desc*/ -static inline int get_rx_rpt2_desc_pkt_len(u8 *__status) +static inline int get_rx_rpt2_desc_pkt_len(__le32 *__status) { - return le32_get_bits(*((__le32 *)__status), GENMASK(8, 0)); + return le32_get_bits(*(__status), GENMASK(8, 0)); } -static inline int get_rx_rpt2_desc_macid_valid_1(u8 *__status) +static inline int get_rx_rpt2_desc_macid_valid_1(__le32 *__status) { - return le32_to_cpu(*((__le32 *)(__status + 16))); + return le32_to_cpu(*(__status + 4)); } -static inline int get_rx_rpt2_desc_macid_valid_2(u8 *__status) +static inline int get_rx_rpt2_desc_macid_valid_2(__le32 *__status) { - return le32_to_cpu(*((__le32 *)(__status + 20))); + return le32_to_cpu(*(__status + 5)); } -static inline void set_earlymode_pktnum(u8 *__paddr, u32 __value) +static inline void set_earlymode_pktnum(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(3, 0)); + le32p_replace_bits(__paddr, __value, GENMASK(3, 0)); } -static inline void set_earlymode_len0(u8 *__paddr, u32 __value) +static inline void set_earlymode_len0(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4)); + le32p_replace_bits(__paddr, __value, GENMASK(15, 4)); } -static inline void set_earlymode_len1(u8 *__paddr, u32 __value) +static inline void set_earlymode_len1(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16)); + le32p_replace_bits(__paddr, __value, GENMASK(27, 16)); } -static inline void set_earlymode_len2_1(u8 *__paddr, u32 __value) +static inline void set_earlymode_len2_1(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28)); + le32p_replace_bits(__paddr, __value, GENMASK(31, 28)); } -static inline void set_earlymode_len2_2(u8 *__paddr, u32 __value) +static inline void set_earlymode_len2_2(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0)); + le32p_replace_bits(__paddr + 1, __value, GENMASK(7, 0)); } -static inline void set_earlymode_len3(u8 *__paddr, u32 __value) +static inline void set_earlymode_len3(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8)); + le32p_replace_bits(__paddr + 1, __value, GENMASK(19, 8)); } -static inline void set_earlymode_len4(u8 *__paddr, u32 __value) +static inline void set_earlymode_len4(__le32 *__paddr, u32 __value) { - le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20)); + le32p_replace_bits(__paddr + 1, __value, GENMASK(31, 20)); } -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) +static inline void clear_pci_tx_desc_content(__le32 *__pdesc, int _size) +{ + if (_size > TX_DESC_NEXT_DESC_OFFSET) + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); + else + memset(__pdesc, 0, _size); +} #define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\ (rxmcs == DESC92C_RATE1M ||\ -- GitLab From d1d1a96bdb4408d02e2bfcb32b71aba165458a80 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 30 Jul 2019 19:33:04 -0500 Subject: [PATCH 2073/7155] rtlwifi: rtl8188ee: Remove local configuration variable The configuration variable IS_LITTLE_ENDIAN is replaced by the standard __LITTLE_ENDIAN. In addition, an unused struct is removed. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 4e3682ded89e..bd862732d6ae 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -560,17 +560,7 @@ static inline void clear_pci_tx_desc_content(__le32 *__pdesc, int _size) rxmcs == DESC92C_RATE5_5M ||\ rxmcs == DESC92C_RATE11M) -#define IS_LITTLE_ENDIAN 1 - -struct phy_rx_agc_info_t { - #if IS_LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; struct phy_status_rpt { - struct phy_rx_agc_info_t path_agc[2]; u8 ch_corr[2]; u8 cck_sig_qual_ofdm_pwdb_all; u8 cck_agc_rpt_ofdm_cfosho_a; @@ -587,7 +577,7 @@ struct phy_status_rpt { u8 stream_target_csi[2]; u8 sig_evm; u8 rsvd_3; -#if IS_LITTLE_ENDIAN +#if defined(__LITTLE_ENDIAN) u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ u8 sgi_en:1; u8 rxsc:2; @@ -595,7 +585,7 @@ struct phy_status_rpt { u8 r_ant_train_en:1; u8 ant_sel_b:1; u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ +#else /* __BIG_ENDIAN */ u8 ant_sel:1; u8 ant_sel_b:1; u8 r_ant_train_en:1; -- GitLab From 0d762f031d702272a17910fbeb45ab15b9673617 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 31 Jul 2019 20:22:45 +0800 Subject: [PATCH 2074/7155] rtw88: allow c2h operation in irq context Some of the c2h operations are small and can be done under interrupt context. For the rest that requires more operations or can go sleep, enqueue onto c2h queue. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 27 +++++++++++++++++++++--- drivers/net/wireless/realtek/rtw88/fw.h | 2 ++ drivers/net/wireless/realtek/rtw88/pci.c | 6 ++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 628477971213..3c4dcb7cf69e 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -36,9 +36,6 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset); len = skb->len - pkt_offset - 2; - rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n", - c2h->id, c2h->seq, len); - switch (c2h->id) { case C2H_HALMAC: rtw_fw_c2h_cmd_handle_ext(rtwdev, skb); @@ -48,6 +45,30 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) } } +void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, + struct sk_buff *skb) +{ + struct rtw_c2h_cmd *c2h; + u8 len; + + c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset); + len = skb->len - pkt_offset - 2; + *((u32 *)skb->cb) = pkt_offset; + + rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n", + c2h->id, c2h->seq, len); + + switch (c2h->id) { + default: + /* pass offset for further operation */ + *((u32 *)skb->cb) = pkt_offset; + skb_queue_tail(&rtwdev->c2h_queue, skb); + ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work); + break; + } +} +EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe); + static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c) { diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 703466393ecb..67f6cf770ced 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -200,6 +200,8 @@ static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) return (struct rtw_c2h_cmd *)(skb->data + pkt_offset); } +void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, + struct sk_buff *skb); void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); void rtw_fw_send_general_info(struct rtw_dev *rtwdev); void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index c56251539874..00ef229552d5 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -8,6 +8,7 @@ #include "pci.h" #include "tx.h" #include "rx.h" +#include "fw.h" #include "debug.h" static u32 rtw_pci_tx_queue_idx_addr[] = { @@ -822,10 +823,7 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, skb_put_data(new, skb->data, new_len); if (pkt_stat.is_c2h) { - /* pass rx_desc & offset for further operation */ - *((u32 *)new->cb) = pkt_offset; - skb_queue_tail(&rtwdev->c2h_queue, new); - ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work); + rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, new); } else { /* remove rx_desc */ skb_pull(new, pkt_offset); -- GitLab From 713a30de45a2ec8619228280e4832b5d6a34e759 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 31 Jul 2019 20:22:46 +0800 Subject: [PATCH 2075/7155] rtw88: enclose c2h cmd handle with mutex C2H commands that cannot be handled in IRQ context should be protected by rtwdev->mutex. Because they might have a sequece of hardware operations that does not want to be interfered. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 3c4dcb7cf69e..3b06f7150c41 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -36,6 +36,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset); len = skb->len - pkt_offset - 2; + mutex_lock(&rtwdev->mutex); + switch (c2h->id) { case C2H_HALMAC: rtw_fw_c2h_cmd_handle_ext(rtwdev, skb); @@ -43,6 +45,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) default: break; } + + mutex_unlock(&rtwdev->mutex); } void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, -- GitLab From 4136214f7c46839c15f0f177fe1d5052302c0205 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 31 Jul 2019 20:22:47 +0800 Subject: [PATCH 2076/7155] rtw88: add BT co-existence support Both RTL8822BE/RTL8822CE are WiFi + BT combo chips. Since WiFi and BT use 2.4GHz to transmit, it is important to make sure they run concurrently without interfering each other. To achieve this, WiFi driver requires a mechanism to collaborate with BT, whether they share the antenna(s) or not. The final decision made by the co-existence mechanism is to choose a proper strategy, or called "tdma/table", and inform either firmware or hardware of the strategy. To choose a strategy, co-existence mechanism needs to have enough information from WiFi and BT. BT information is provided through firmware C2H. The contents describe the current status of BT, such as if BT is connected or is idle, or the profile that is being used. WiFi information can be provided by WiFi itself. The WiFi driver will call various of "notify" functions each time the state of WiFi changed, such as WiFi is going to switch channel or is connected. Also WiFi driver can know if it shares antenna with BT by reading efuse content. Antenna configuration of the module will finally get a different strategy. Upon receiving any information from WiFi or BT, the WiFi driver will run the co-existence mechanism immediately. It will set the RF antenna configuration according to the strategy through the TDMA H2C to firmware and a hardware table. Based on the tdma/table, WiFi + BT should work with each other, and having a better user experience. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/Makefile | 1 + drivers/net/wireless/realtek/rtw88/coex.c | 2507 +++++++++++++++++ drivers/net/wireless/realtek/rtw88/coex.h | 369 +++ drivers/net/wireless/realtek/rtw88/fw.c | 106 + drivers/net/wireless/realtek/rtw88/fw.h | 71 + drivers/net/wireless/realtek/rtw88/mac80211.c | 19 + drivers/net/wireless/realtek/rtw88/main.c | 45 +- drivers/net/wireless/realtek/rtw88/main.h | 233 ++ drivers/net/wireless/realtek/rtw88/ps.c | 9 + drivers/net/wireless/realtek/rtw88/reg.h | 62 + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 460 ++- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 355 ++- 12 files changed, 4209 insertions(+), 28 deletions(-) create mode 100644 drivers/net/wireless/realtek/rtw88/coex.c create mode 100644 drivers/net/wireless/realtek/rtw88/coex.h diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index e0bfefd154af..77edee2df8b8 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -9,6 +9,7 @@ rtw88-y += main.o \ rx.o \ mac.o \ phy.o \ + coex.o \ efuse.o \ fw.o \ ps.o \ diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c new file mode 100644 index 000000000000..4577fceddc5e --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -0,0 +1,2507 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "coex.h" +#include "fw.h" +#include "ps.h" +#include "debug.h" +#include "reg.h" + +static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, + u8 rssi, u8 rssi_thresh) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u8 tol = chip->rssi_tolerance; + u8 next_state; + + if (pre_state == COEX_RSSI_STATE_LOW || + pre_state == COEX_RSSI_STATE_STAY_LOW) { + if (rssi >= (rssi_thresh + tol)) + next_state = COEX_RSSI_STATE_HIGH; + else + next_state = COEX_RSSI_STATE_STAY_LOW; + } else { + if (rssi < rssi_thresh) + next_state = COEX_RSSI_STATE_LOW; + else + next_state = COEX_RSSI_STATE_STAY_HIGH; + } + + return next_state; +} + +static void rtw_coex_limited_tx(struct rtw_dev *rtwdev, + bool tx_limit_en, bool ampdu_limit_en) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + bool wifi_under_b_mode = false; + + if (!chip->scbd_support) + return; + + /* force max tx retry limit = 8 */ + if (coex_stat->wl_tx_limit_en == tx_limit_en && + coex_stat->wl_ampdu_limit_en == ampdu_limit_en) + return; + + if (!coex_stat->wl_tx_limit_en) { + coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC); + coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH); + coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT); + } + + if (!coex_stat->wl_ampdu_limit_en) + coex_stat->ampdu_max_time = + rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1); + + coex_stat->wl_tx_limit_en = tx_limit_en; + coex_stat->wl_ampdu_limit_en = ampdu_limit_en; + + if (tx_limit_en) { + /* set BT polluted packet on for tx rate adaptive, + * not including tx retry broken by PTA + */ + rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); + + /* set queue life time to avoid can't reach tx retry limit + * if tx is always broken by GNT_BT + */ + rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); + rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808); + + /* auto rate fallback step within 8 retries */ + if (wifi_under_b_mode) { + rtw_write32(rtwdev, REG_DARFRC, 0x1000000); + rtw_write32(rtwdev, REG_DARFRCH, 0x1010101); + } else { + rtw_write32(rtwdev, REG_DARFRC, 0x1000000); + rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); + } + } else { + rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); + rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf); + + rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit); + rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc); + rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch); + } + + if (ampdu_limit_en) + rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20); + else + rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, + coex_stat->ampdu_max_time); +} + +static void rtw_coex_limited_wl(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_coex_stat *coex_stat = &coex->stat; + bool tx_limit = false; + bool tx_agg_ctrl = false; + + if (coex->under_5g || + coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + /* no need to limit tx */ + } else { + tx_limit = true; + if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist || + coex_stat->bt_hid_pair_num > 0) + tx_agg_ctrl = true; + } + + rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl); +} + +static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 para[6] = {0}; + + if (coex->stop_dm) + return; + + para[0] = COEX_H2C69_WL_LEAKAP; + + if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) { + para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */ + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + coex_stat->wl_slot_extend = false; + coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; + return; + } + + if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl && + !coex_stat->wl_cck_lock_ever) { + if (coex_stat->wl_fw_dbg_info[7] <= 5) + coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++; + else + coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; + + if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) { + para[1] = 0x1; /* disable 5ms extend */ + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + coex_stat->wl_slot_extend = false; + coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; + } + } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) { + para[1] = 0x0; /* enable 5ms extend */ + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + coex_stat->wl_slot_extend = true; + } +} + +static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + /* TODO: wait for rx_rate_change_notify implement */ + coex_stat->wl_cck_lock = false; + coex_stat->wl_cck_lock_pre = false; + coex_stat->wl_cck_lock_ever = false; +} + +static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 cnt_cck; + + /* wifi noisy environment identification */ + cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt; + + if (!coex_stat->wl_gl_busy) { + if (cnt_cck > 250) { + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5) + coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++; + + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) { + coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; + coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; + } + } else if (cnt_cck < 100) { + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5) + coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++; + + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) { + coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; + coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; + } + } else { + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5) + coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++; + + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) { + coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; + coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; + } + } + + if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) + coex_stat->wl_noisy_level = 2; + else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) + coex_stat->wl_noisy_level = 1; + else + coex_stat->wl_noisy_level = 0; + } +} + +static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 para[2] = {0}; + + if (coex_stat->tdma_timer_base == type) + return; + + coex_stat->tdma_timer_base = type; + + para[0] = COEX_H2C69_TDMA_SLOT; + + if (type == 3) /* 4-slot */ + para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */ + else /* 2-slot */ + para[1] = PARA1_H2C69_TDMA_2SLOT; + + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + + /* no 5ms_wl_slot_extend for 4-slot mode */ + if (coex_stat->tdma_timer_base == 3) + rtw_coex_wl_ccklock_action(rtwdev); +} + +static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap, + u8 data) +{ + u32 addr; + + addr = REG_BT_COEX_TABLE_H + (bitmap / 8); + bitmap = bitmap % 8; + + rtw_write8_mask(rtwdev, addr, BIT(bitmap), data); +} + +void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u16 val = 0x2; + + if (!chip->scbd_support) + return; + + val |= coex_stat->score_board; + + /* for 8822b, scbd[10] is CQDDR on + * for 8822c, scbd[10] is no fix 2M + */ + if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) { + if (set) + val &= ~COEX_SCBD_FIX2M; + else + val |= COEX_SCBD_FIX2M; + } else { + if (set) + val |= bitpos; + else + val &= ~bitpos; + } + + if (val != coex_stat->score_board) { + coex_stat->score_board = val; + val |= BIT_BT_INT_EN; + rtw_write16(rtwdev, REG_WIFI_BT_INFO, val); + } +} + +static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->scbd_support) + return 0; + + return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN); +} + +static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + u8 cnt = 0; + u32 wait_cnt; + bool btk, wlk; + + if (coex_rfe->wlg_at_btg && chip->scbd_support && + coex_stat->bt_iqk_state != 0xff) { + wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY; + do { + /* BT RFK */ + btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK); + + /* WL RFK */ + wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK); + + if (!btk && !wlk) + break; + + mdelay(COEX_MIN_DELAY); + } while (++cnt < wait_cnt); + + if (cnt >= wait_cnt) + coex_stat->bt_iqk_state = 0xff; + } +} + +static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + if (coex_stat->bt_disabled) + return; + + rtw_fw_query_bt_info(rtwdev); +} + +static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + bool bt_disabled = false; + u16 score_board; + + if (chip->scbd_support) { + score_board = rtw_coex_read_scbd(rtwdev); + bt_disabled = !(score_board & COEX_SCBD_ONOFF); + } + + if (coex_stat->bt_disabled != bt_disabled) { + rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n", + coex_stat->bt_disabled, bt_disabled); + + coex_stat->bt_disabled = bt_disabled; + coex_stat->bt_ble_scan_type = 0; + coex_dm->cur_bt_lna_lvl = 0; + } + + if (!coex_stat->bt_disabled) { + coex_stat->bt_reenable = true; + ieee80211_queue_delayed_work(rtwdev->hw, + &coex->bt_reenable_work, 15 * HZ); + } else { + coex_stat->bt_mailbox_reply = false; + coex_stat->bt_reenable = false; + } +} + +static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_traffic_stats *stats = &rtwdev->stats; + bool is_5G = false; + bool scan = false, link = false; + int i; + u8 rssi_state; + u8 rssi_step; + u8 rssi; + + scan = rtw_flag_check(rtwdev, RTW_FLAG_SCANNING); + coex_stat->wl_connected = !!rtwdev->sta_cnt; + coex_stat->wl_gl_busy = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC); + + if (stats->tx_throughput > stats->rx_throughput) + coex_stat->wl_tput_dir = COEX_WL_TPUT_TX; + else + coex_stat->wl_tput_dir = COEX_WL_TPUT_RX; + + if (scan || link || reason == COEX_RSN_2GCONSTART || + reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND) + coex_stat->wl_linkscan_proc = true; + else + coex_stat->wl_linkscan_proc = false; + + rtw_coex_wl_noisy_detect(rtwdev); + + for (i = 0; i < 4; i++) { + rssi_state = coex_dm->wl_rssi_state[i]; + rssi_step = chip->wl_rssi_step[i]; + rssi = rtwdev->dm_info.min_rssi; + rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, + rssi, rssi_step); + coex_dm->wl_rssi_state[i] = rssi_state; + } + + switch (reason) { + case COEX_RSN_5GSCANSTART: + case COEX_RSN_5GSWITCHBAND: + case COEX_RSN_5GCONSTART: + + is_5G = true; + break; + case COEX_RSN_2GSCANSTART: + case COEX_RSN_2GSWITCHBAND: + case COEX_RSN_2GCONSTART: + + is_5G = false; + break; + default: + if (rtwdev->hal.current_band_type == RTW_BAND_5G) + is_5G = true; + else + is_5G = false; + break; + } + + coex->under_5g = is_5G; +} + +static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp) +{ + struct rtw_c2h_cmd *c2h; + u32 pkt_offset; + + pkt_offset = *((u32 *)resp->cb); + c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset); + + return c2h->payload; +} + +void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw_coex *coex = &rtwdev->coex; + u8 *payload = get_payload_from_coex_resp(skb); + + if (payload[0] != COEX_RESP_ACK_BY_WL_FW) + return; + + skb_queue_tail(&coex->queue, skb); + wake_up(&coex->wait); +} + +static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, + struct rtw_coex_info_req *req) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct sk_buff *skb_resp = NULL; + + mutex_lock(&coex->mutex); + + rtw_fw_query_bt_mp_info(rtwdev, req); + + if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue), + COEX_REQUEST_TIMEOUT)) { + rtw_err(rtwdev, "coex request time out\n"); + goto out; + } + + skb_resp = skb_dequeue(&coex->queue); + if (!skb_resp) { + rtw_err(rtwdev, "failed to get coex info response\n"); + goto out; + } + +out: + mutex_unlock(&coex->mutex); + return skb_resp; +} + +static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; + bool ret = false; + + req.op_code = BT_MP_INFO_OP_SCAN_TYPE; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) + goto out; + + payload = get_payload_from_coex_resp(skb); + *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload); + dev_kfree_skb_any(skb); + ret = true; + +out: + return ret; +} + +static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, + u8 lna_constrain_level) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + bool ret = false; + + req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT; + req.para1 = lna_constrain_level; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) + goto out; + + dev_kfree_skb_any(skb); + ret = true; + +out: + return ret; +} + +static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_chip_info *chip = rtwdev->chip; + u8 i; + u8 rssi_state; + u8 rssi_step; + u8 rssi; + + /* update wl/bt rssi by btinfo */ + for (i = 0; i < COEX_RSSI_STEP; i++) { + rssi_state = coex_dm->bt_rssi_state[i]; + rssi_step = chip->bt_rssi_step[i]; + rssi = coex_stat->bt_rssi; + rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, + rssi, rssi_step); + coex_dm->bt_rssi_state[i] = rssi_state; + } + + for (i = 0; i < COEX_RSSI_STEP; i++) { + rssi_state = coex_dm->wl_rssi_state[i]; + rssi_step = chip->wl_rssi_step[i]; + rssi = rtwdev->dm_info.min_rssi; + rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, + rssi, rssi_step); + coex_dm->wl_rssi_state[i] = rssi_state; + } + + if (coex_stat->bt_ble_scan_en && + coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) { + u8 scan_type; + + if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) { + coex_stat->bt_ble_scan_type = scan_type; + if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1) + coex_stat->bt_init_scan = true; + else + coex_stat->bt_init_scan = false; + } + } + + coex_stat->bt_profile_num = 0; + + /* set link exist status */ + if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { + coex_stat->bt_link_exist = false; + coex_stat->bt_pan_exist = false; + coex_stat->bt_a2dp_exist = false; + coex_stat->bt_hid_exist = false; + coex_stat->bt_hfp_exist = false; + } else { + /* connection exists */ + coex_stat->bt_link_exist = true; + if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) { + coex_stat->bt_pan_exist = true; + coex_stat->bt_profile_num++; + } else { + coex_stat->bt_pan_exist = false; + } + + if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) { + coex_stat->bt_a2dp_exist = true; + coex_stat->bt_profile_num++; + } else { + coex_stat->bt_a2dp_exist = false; + } + + if (coex_stat->bt_info_lb2 & COEX_INFO_HID) { + coex_stat->bt_hid_exist = true; + coex_stat->bt_profile_num++; + } else { + coex_stat->bt_hid_exist = false; + } + + if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) { + coex_stat->bt_hfp_exist = true; + coex_stat->bt_profile_num++; + } else { + coex_stat->bt_hfp_exist = false; + } + } + + if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) { + coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE; + } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { + coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE; + } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) { + coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE; + } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) || + (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) { + if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) + coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY; + else + coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY; + } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) { + coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY; + } else { + coex_dm->bt_status = COEX_BTSTATUS_MAX; + } + + coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++; + + rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status); +} + +static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 link = 0; + u8 center_chan = 0; + u8 bw; + int i; + + bw = rtwdev->hal.current_band_width; + + if (type != COEX_MEDIA_DISCONNECT) + center_chan = rtwdev->hal.current_channel; + + if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) { + link = 0; + } else if (center_chan <= 14) { + link = 0x1; + + if (bw == RTW_CHANNEL_WIDTH_40) + bw = chip->bt_afh_span_bw40; + else + bw = chip->bt_afh_span_bw20; + } else if (chip->afh_5g_num > 1) { + for (i = 0; i < chip->afh_5g_num; i++) { + if (center_chan == chip->afh_5g[i].wl_5g_ch) { + link = 0x3; + center_chan = chip->afh_5g[i].bt_skip_ch; + bw = chip->afh_5g[i].bt_skip_span; + break; + } + } + } + + coex_dm->wl_ch_info[0] = link; + coex_dm->wl_ch_info[1] = center_chan; + coex_dm->wl_ch_info[2] = bw; + + rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw); +} + +static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + + if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl) + return; + + coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl; + + rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl); +} + +static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + + if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl) + return; + + coex_dm->cur_bt_lna_lvl = bt_lna_lvl; + + /* notify BT rx gain table changed */ + if (bt_lna_lvl < 7) { + rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true); + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false); + } +} + +static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, + struct coex_rf_para para) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 offset = 0; + + if (coex->freerun && coex_stat->wl_noisy_level <= 1) + offset = 3; + + rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl); + rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset); + rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en); + rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl); +} + +static u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr) +{ + u32 val; + + if (!ltecoex_read_reg(rtwdev, addr, &val)) { + rtw_err(rtwdev, "failed to read indirect register\n"); + return 0; + } + + return val; +} + +void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, + u32 mask, u32 val) +{ + u32 shift = __ffs(mask); + u32 tmp; + + tmp = rtw_coex_read_indirect_reg(rtwdev, addr); + tmp = (tmp & (~mask)) | ((val << shift) & mask); + + if (!ltecoex_reg_write(rtwdev, addr, tmp)) + rtw_err(rtwdev, "failed to write indirect register\n"); +} + +static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) +{ + if (wifi_control) + rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); + else + rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); +} + +static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) +{ + rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state); + rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state); +} + +static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) +{ + rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state); + rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state); +} + +static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1) +{ +#define DEF_BRK_TABLE_VAL 0xf0ffffff + rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0); + rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1); + rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL); +} + +static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + + coex_dm->cur_table = type; + + if (efuse->share_ant) { + if (type < chip->table_sant_num) + rtw_coex_set_table(rtwdev, + chip->table_sant[type].bt, + chip->table_sant[type].wl); + } else { + type = type - 100; + if (type < chip->table_nsant_num) + rtw_coex_set_table(rtwdev, + chip->table_nsant[type].bt, + chip->table_nsant[type].wl); + } +} + +static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable) +{ + struct rtw_coex *coex = &rtwdev->coex; + + if (coex->stop_dm) + return; + + rtw_fw_bt_ignore_wlan_action(rtwdev, enable); +} + +static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, + u8 lps_val, u8 rpwm_val) +{ + struct rtw_lps_conf *lps_conf = &rtwdev->lps_conf; + struct rtw_vif *rtwvif; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 lps_mode = 0x0; + + lps_mode = rtwdev->lps_conf.mode; + + switch (ps_type) { + case COEX_PS_WIFI_NATIVE: + /* recover to original 32k low power setting */ + coex_stat->wl_force_lps_ctrl = false; + + rtwvif = lps_conf->rtwvif; + if (rtwvif && rtw_in_lps(rtwdev)) + rtw_leave_lps(rtwdev, rtwvif); + break; + case COEX_PS_LPS_OFF: + coex_stat->wl_force_lps_ctrl = true; + if (lps_mode) + rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0); + + rtwvif = lps_conf->rtwvif; + if (rtwvif && rtw_in_lps(rtwdev)) + rtw_leave_lps(rtwdev, rtwvif); + break; + default: + break; + } +} + +static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, + u8 byte3, u8 byte4, u8 byte5) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_chip_info *chip = rtwdev->chip; + u8 ps_type = COEX_PS_WIFI_NATIVE; + bool ap_enable = false; + + if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { + byte1 &= ~BIT(4); + byte1 |= BIT(5); + + byte5 |= BIT(5); + byte5 &= ~BIT(6); + + ps_type = COEX_PS_WIFI_NATIVE; + rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); + } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) { + if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) + ps_type = COEX_PS_LPS_OFF; + else + ps_type = COEX_PS_LPS_ON; + rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); + } else { + ps_type = COEX_PS_WIFI_NATIVE; + rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); + } + + coex_dm->ps_tdma_para[0] = byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = byte5; + + rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); +} + +static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 n, type; + bool turn_on; + + if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */ + rtw_coex_tdma_timer_base(rtwdev, 3); + else + rtw_coex_tdma_timer_base(rtwdev, 0); + + type = (u8)(tcase & 0xff); + + turn_on = (type == 0 || type == 100) ? false : true; + + if (!force) { + if (turn_on == coex_dm->cur_ps_tdma_on && + type == coex_dm->cur_ps_tdma) { + return; + } + } + + if (turn_on) { + /* enable TBTT interrupt */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false); + } + + if (efuse->share_ant) { + if (type < chip->tdma_sant_num) + rtw_coex_set_tdma(rtwdev, + chip->tdma_sant[type].para[0], + chip->tdma_sant[type].para[1], + chip->tdma_sant[type].para[2], + chip->tdma_sant[type].para[3], + chip->tdma_sant[type].para[4]); + } else { + n = type - 100; + if (n < chip->tdma_nsant_num) + rtw_coex_set_tdma(rtwdev, + chip->tdma_nsant[n].para[0], + chip->tdma_nsant[n].para[1], + chip->tdma_nsant[n].para[2], + chip->tdma_nsant[n].para[3], + chip->tdma_nsant[n].para[4]); + } + + /* update pre state */ + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type); +} + +static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + u8 ctrl_type = COEX_SWITCH_CTRL_MAX; + u8 pos_type = COEX_SWITCH_TO_MAX; + + if (!force && coex_dm->cur_ant_pos_type == phase) + return; + + coex_dm->cur_ant_pos_type = phase; + + /* avoid switch coex_ctrl_owner during BT IQK */ + rtw_coex_check_rfk(rtwdev); + + switch (phase) { + case COEX_SET_ANT_POWERON: + /* set path control owner to BT at power-on */ + if (coex_stat->bt_disabled) + rtw_coex_coex_ctrl_owner(rtwdev, true); + else + rtw_coex_coex_ctrl_owner(rtwdev, false); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_BT; + break; + case COEX_SET_ANT_INIT: + if (coex_stat->bt_disabled) { + /* set GNT_BT to SW low */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); + + /* set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); + } else { + /* set GNT_BT to SW high */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set GNT_WL to SW low */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW); + } + + /* set path control owner to wl at initial step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_BT; + break; + case COEX_SET_ANT_WONLY: + /* set GNT_BT to SW Low */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); + + /* Set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set path control owner to wl at initial step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_WLG; + break; + case COEX_SET_ANT_WOFF: + /* set path control owner to BT */ + rtw_coex_coex_ctrl_owner(rtwdev, false); + + ctrl_type = COEX_SWITCH_CTRL_BY_BT; + pos_type = COEX_SWITCH_TO_NOCARE; + break; + case COEX_SET_ANT_2G: + /* set GNT_BT to PTA */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + + /* set GNT_WL to PTA */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); + + /* set path control owner to wl at runtime step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_PTA; + pos_type = COEX_SWITCH_TO_NOCARE; + break; + case COEX_SET_ANT_5G: + /* set GNT_BT to PTA */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set path control owner to wl at runtime step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_WLA; + break; + case COEX_SET_ANT_2G_FREERUN: + /* set GNT_BT to SW high */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* Set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); + + /* set path control owner to wl at runtime step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_WLG_BT; + break; + case COEX_SET_ANT_2G_WLBT: + /* set GNT_BT to SW high */ + rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); + + /* Set GNT_WL to SW high */ + rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); + + /* set path control owner to wl at runtime step */ + rtw_coex_coex_ctrl_owner(rtwdev, true); + + ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; + pos_type = COEX_SWITCH_TO_WLG_BT; + break; + default: + WARN_ON("unknown phase when setting antenna path\n"); + return; + } + + if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX) + rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); +} + +static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 algorithm = COEX_ALGO_NOPROFILE; + u8 profile_map = 0; + + if (coex_stat->bt_hfp_exist) + profile_map |= BPM_HFP; + if (coex_stat->bt_hid_exist) + profile_map |= BPM_HID; + if (coex_stat->bt_a2dp_exist) + profile_map |= BPM_A2DP; + if (coex_stat->bt_pan_exist) + profile_map |= BPM_PAN; + + switch (profile_map) { + case BPM_HFP: + algorithm = COEX_ALGO_HFP; + break; + case BPM_HID: + case BPM_HFP + BPM_HID: + algorithm = COEX_ALGO_HID; + break; + case BPM_HFP + BPM_A2DP: + case BPM_HID + BPM_A2DP: + case BPM_HFP + BPM_HID + BPM_A2DP: + algorithm = COEX_ALGO_A2DP_HID; + break; + case BPM_HFP + BPM_PAN: + case BPM_HID + BPM_PAN: + case BPM_HFP + BPM_HID + BPM_PAN: + algorithm = COEX_ALGO_PAN_HID; + break; + case BPM_HFP + BPM_A2DP + BPM_PAN: + case BPM_HID + BPM_A2DP + BPM_PAN: + case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN: + algorithm = COEX_ALGO_A2DP_PAN_HID; + break; + case BPM_PAN: + algorithm = COEX_ALGO_PAN; + break; + case BPM_A2DP + BPM_PAN: + algorithm = COEX_ALGO_A2DP_PAN; + break; + case BPM_A2DP: + if (coex_stat->bt_multi_link) { + if (coex_stat->bt_hid_pair_num > 0) + algorithm = COEX_ALGO_A2DP_HID; + else + algorithm = COEX_ALGO_A2DP_PAN; + } else { + algorithm = COEX_ALGO_A2DP; + } + break; + default: + algorithm = COEX_ALGO_NOPROFILE; + break; + } + + return algorithm; +} + +static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 2; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 level = 0; + + if (efuse->share_ant) + return; + + coex->freerun = true; + + if (coex_stat->wl_connected) + rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); + + rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); + + if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0])) + level = 2; + else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) + level = 3; + else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2])) + level = 4; + else + level = 5; + + if (level > chip->wl_rf_para_num - 1) + level = chip->wl_rf_para_num - 1; + + if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]); + else + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); + + rtw_coex_table(rtwdev, 100); + rtw_coex_tdma(rtwdev, false, 100); +} + +static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 2; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 1; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + u8 table_case = 0xff, tdma_case = 0xff; + + if (coex_rfe->ant_switch_with_bt && + coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + if (efuse->share_ant && + COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) { + table_case = 0; + tdma_case = 0; + } else if (!efuse->share_ant) { + table_case = 100; + tdma_case = 100; + } + } + + if (table_case != 0xff && tdma_case != 0xff) { + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + return; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + + if (efuse->share_ant) { + /* Shared-Ant */ + if (!coex_stat->wl_gl_busy) { + table_case = 10; + tdma_case = 3; + } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + table_case = 6; + tdma_case = 7; + } else { + table_case = 12; + tdma_case = 7; + } + } else { + /* Non-Shared-Ant */ + if (!coex_stat->wl_gl_busy) { + table_case = 112; + tdma_case = 104; + } else if ((coex_stat->bt_ble_scan_type & 0x2) && + coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { + table_case = 114; + tdma_case = 103; + } else { + table_case = 112; + tdma_case = 103; + } + } + + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + bool wl_hi_pri = false; + u8 table_case, tdma_case; + + if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || + coex_stat->wl_hi_pri_task2) + wl_hi_pri = true; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (wl_hi_pri) { + table_case = 15; + if (coex_stat->bt_a2dp_exist && + !coex_stat->bt_pan_exist) + tdma_case = 11; + else if (coex_stat->wl_hi_pri_task1) + tdma_case = 6; + else if (!coex_stat->bt_page) + tdma_case = 8; + else + tdma_case = 9; + } else if (coex_stat->wl_connected) { + table_case = 10; + tdma_case = 10; + } else { + table_case = 1; + tdma_case = 0; + } + } else { + /* Non_Shared-Ant */ + if (wl_hi_pri) { + table_case = 113; + if (coex_stat->bt_a2dp_exist && + !coex_stat->bt_pan_exist) + tdma_case = 111; + else if (coex_stat->wl_hi_pri_task1) + tdma_case = 106; + else if (!coex_stat->bt_page) + tdma_case = 108; + else + tdma_case = 109; + } else if (coex_stat->wl_connected) { + table_case = 101; + tdma_case = 110; + } else { + table_case = 100; + tdma_case = 100; + } + } + + rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n", + wl_hi_pri, coex_stat->bt_page); + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->bt_multi_link) { + table_case = 10; + tdma_case = 17; + } else { + table_case = 10; + tdma_case = 5; + } + } else { + /* Non-Shared-Ant */ + if (coex_stat->bt_multi_link) { + table_case = 112; + tdma_case = 117; + } else { + table_case = 105; + tdma_case = 100; + } + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + u32 wl_bw; + + wl_bw = rtwdev->hal.current_band_width; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->bt_ble_exist) { + /* RCU */ + if (!coex_stat->wl_gl_busy) + table_case = 14; + else + table_case = 15; + + if (coex_stat->bt_a2dp_active || wl_bw == 0) + tdma_case = 18; + else if (coex_stat->wl_gl_busy) + tdma_case = 8; + else + tdma_case = 4; + } else { + if (coex_stat->bt_a2dp_active || wl_bw == 0) { + table_case = 8; + tdma_case = 4; + } else { + /* for 4/18 HID */ + if (coex_stat->bt_418_hid_exist && + coex_stat->wl_gl_busy) + table_case = 12; + else + table_case = 10; + tdma_case = 4; + } + } + } else { + /* Non-Shared-Ant */ + if (coex_stat->bt_a2dp_active) { + table_case = 113; + tdma_case = 118; + } else if (coex_stat->bt_ble_exist) { + /* BLE */ + table_case = 113; + + if (coex_stat->wl_gl_busy) + tdma_case = 106; + else + tdma_case = 104; + } else { + table_case = 113; + tdma_case = 104; + } + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + u32 slot_type = 0; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) + table_case = 10; + else + table_case = 9; + + slot_type = TDMA_4SLOT; + + if (coex_stat->wl_gl_busy) + tdma_case = 13; + else + tdma_case = 14; + } else { + /* Non-Shared-Ant */ + table_case = 112; + + if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) + tdma_case = 112; + else + tdma_case = 113; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); +} + +static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + bool ap_enable = false; + + if (efuse->share_ant) { /* Shared-Ant */ + if (ap_enable) { + table_case = 2; + tdma_case = 0; + } else if (coex_stat->wl_gl_busy) { + table_case = 28; + tdma_case = 20; + } else { + table_case = 28; + tdma_case = 26; + } + } else { /* Non-Shared-Ant */ + if (ap_enable) { + table_case = 100; + tdma_case = 100; + } else { + table_case = 119; + tdma_case = 120; + } + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) + table_case = 14; + else + table_case = 10; + + if (coex_stat->wl_gl_busy) + tdma_case = 17; + else + tdma_case = 19; + } else { + /* Non-Shared-Ant */ + table_case = 112; + + if (coex_stat->wl_gl_busy) + tdma_case = 117; + else + tdma_case = 119; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + u32 slot_type = 0; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->bt_ble_exist) + table_case = 26; + else + table_case = 9; + + if (coex_stat->wl_gl_busy) { + slot_type = TDMA_4SLOT; + tdma_case = 13; + } else { + tdma_case = 14; + } + } else { + /* Non-Shared-Ant */ + if (coex_stat->bt_ble_exist) + table_case = 121; + else + table_case = 113; + + if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) + tdma_case = 112; + else + tdma_case = 113; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); +} + +static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->wl_gl_busy && + coex_stat->wl_noisy_level == 0) + table_case = 14; + else + table_case = 10; + + if (coex_stat->wl_gl_busy) + tdma_case = 15; + else + tdma_case = 20; + } else { + /* Non-Shared-Ant */ + table_case = 112; + + if (coex_stat->wl_gl_busy) + tdma_case = 115; + else + tdma_case = 120; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 9; + + if (coex_stat->wl_gl_busy) + tdma_case = 18; + else + tdma_case = 19; + } else { + /* Non-Shared-Ant */ + table_case = 113; + + if (coex_stat->wl_gl_busy) + tdma_case = 117; + else + tdma_case = 119; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 10; + + if (coex_stat->wl_gl_busy) + tdma_case = 15; + else + tdma_case = 20; + } else { + /* Non-Shared-Ant */ + table_case = 113; + + if (coex_stat->wl_gl_busy) + tdma_case = 115; + else + tdma_case = 120; + } + + rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 0; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 2; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (coex->under_5g) + return; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 28; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + if (coex_stat->bt_a2dp_exist) { + table_case = 9; + tdma_case = 11; + } else { + table_case = 9; + tdma_case = 7; + } + } else { + /* Non-Shared-Ant */ + if (coex_stat->bt_a2dp_exist) { + table_case = 112; + tdma_case = 111; + } else { + table_case = 112; + tdma_case = 107; + } + } + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_chip_info *chip = rtwdev->chip; + u8 table_case, tdma_case; + + if (efuse->share_ant) { + /* Shared-Ant */ + table_case = 1; + tdma_case = 0; + } else { + /* Non-Shared-Ant */ + table_case = 100; + tdma_case = 100; + } + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); +} + +static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 algorithm; + + /* Non-Shared-Ant */ + if (!efuse->share_ant && coex_stat->wl_gl_busy && + COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && + COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) { + rtw_coex_action_freerun(rtwdev); + return; + } + + algorithm = rtw_coex_algorithm(rtwdev); + + switch (algorithm) { + case COEX_ALGO_HFP: + rtw_coex_action_bt_hfp(rtwdev); + break; + case COEX_ALGO_HID: + rtw_coex_action_bt_hid(rtwdev); + break; + case COEX_ALGO_A2DP: + if (coex_stat->bt_a2dp_sink) + rtw_coex_action_bt_a2dpsink(rtwdev); + else + rtw_coex_action_bt_a2dp(rtwdev); + break; + case COEX_ALGO_PAN: + rtw_coex_action_bt_pan(rtwdev); + break; + case COEX_ALGO_A2DP_HID: + rtw_coex_action_bt_a2dp_hid(rtwdev); + break; + case COEX_ALGO_A2DP_PAN: + rtw_coex_action_bt_a2dp_pan(rtwdev); + break; + case COEX_ALGO_PAN_HID: + rtw_coex_action_bt_pan_hid(rtwdev); + break; + case COEX_ALGO_A2DP_PAN_HID: + rtw_coex_action_bt_a2dp_pan_hid(rtwdev); + break; + default: + case COEX_ALGO_NOPROFILE: + rtw_coex_action_bt_idle(rtwdev); + break; + } +} + +static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_coex_stat *coex_stat = &coex->stat; + + lockdep_assert_held(&rtwdev->mutex); + + coex_dm->reason = reason; + + /* update wifi_link_info_ext variable */ + rtw_coex_update_wl_link_info(rtwdev, reason); + + rtw_coex_monitor_bt_enable(rtwdev); + + if (coex->stop_dm) + return; + + if (coex_stat->wl_under_ips) + return; + + if (coex->freeze && !coex_stat->bt_setup_link) + return; + + coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++; + coex->freerun = false; + + /* Pure-5G Coex Process */ + if (coex->under_5g) { + coex_stat->wl_coex_mode = COEX_WLINK_5G; + rtw_coex_action_wl_under5g(rtwdev); + goto exit; + } + + coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT; + rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); + if (coex_stat->bt_disabled) { + rtw_coex_action_wl_only(rtwdev); + goto exit; + } + + if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) { + rtw_coex_action_wl_native_lps(rtwdev); + goto exit; + } + + if (coex_stat->bt_whck_test) { + rtw_coex_action_bt_whql_test(rtwdev); + goto exit; + } + + if (coex_stat->bt_setup_link) { + rtw_coex_action_bt_relink(rtwdev); + goto exit; + } + + if (coex_stat->bt_inq_page) { + rtw_coex_action_bt_inquiry(rtwdev); + goto exit; + } + + if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE || + coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) && + coex_stat->wl_connected) { + rtw_coex_action_bt_idle(rtwdev); + goto exit; + } + + if (coex_stat->wl_linkscan_proc) { + rtw_coex_action_wl_linkscan(rtwdev); + goto exit; + } + + if (coex_stat->wl_connected) + rtw_coex_action_wl_connected(rtwdev); + else + rtw_coex_action_wl_not_connected(rtwdev); + +exit: + rtw_coex_set_gnt_fix(rtwdev); + rtw_coex_limited_wl(rtwdev); +} + +static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + u8 i; + + memset(coex_dm, 0, sizeof(*coex_dm)); + memset(coex_stat, 0, sizeof(*coex_stat)); + + for (i = 0; i < COEX_CNT_WL_MAX; i++) + coex_stat->cnt_wl[i] = 0; + + for (i = 0; i < COEX_CNT_BT_MAX; i++) + coex_stat->cnt_bt[i] = 0; + + for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++) + coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW; + + for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++) + coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW; + + coex_stat->wl_coex_mode = COEX_WLINK_MAX; +} + +static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) +{ + struct rtw_coex *coex = &rtwdev->coex; + + rtw_coex_init_coex_var(rtwdev); + rtw_coex_monitor_bt_enable(rtwdev); + rtw_coex_set_rfe_type(rtwdev); + rtw_coex_set_init(rtwdev); + + /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */ + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1); + + /* set Tx beacon = Hi-Pri */ + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1); + + /* set Tx beacon queue = Hi-Pri */ + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1); + + /* antenna config */ + if (coex->wl_rf_off) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); + coex->stop_dm = true; + } else if (wifi_only) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, + true); + coex->stop_dm = true; + } else { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT); + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, + true); + coex->stop_dm = false; + coex->freeze = true; + } + + /* PTA parameter */ + rtw_coex_table(rtwdev, 0); + rtw_coex_tdma(rtwdev, true, 0); + rtw_coex_query_bt_info(rtwdev); +} + +void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + + coex->stop_dm = true; + coex->wl_rf_off = false; + + /* enable BB, we can write 0x948 */ + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1)); + + rtw_coex_monitor_bt_enable(rtwdev); + rtw_coex_set_rfe_type(rtwdev); + + /* set antenna path to BT */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON); + + /* red x issue */ + rtw_write8(rtwdev, 0xff1a, 0x0); +} + +void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) +{ + __rtw_coex_init_hw_config(rtwdev, wifi_only); +} + +void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + if (coex->stop_dm) + return; + + if (type == COEX_IPS_ENTER) { + coex_stat->wl_under_ips = true; + + /* for lps off */ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); + rtw_coex_action_coex_all_off(rtwdev); + } else if (type == COEX_IPS_LEAVE) { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); + + /* run init hw config (exclude wifi only) */ + __rtw_coex_init_hw_config(rtwdev, false); + /* sw all off */ + + coex_stat->wl_under_ips = false; + } +} + +void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + if (coex->stop_dm) + return; + + if (type == COEX_LPS_ENABLE) { + coex_stat->wl_under_lps = true; + + if (coex_stat->wl_force_lps_ctrl) { + /* for ps-tdma */ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + } else { + /* for native ps */ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); + + rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); + } + } else if (type == COEX_LPS_DISABLE) { + coex_stat->wl_under_lps = false; + + /* for lps off */ + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + + if (!coex_stat->wl_force_lps_ctrl) + rtw_coex_query_bt_info(rtwdev); + } +} + +void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + if (coex->stop_dm) + return; + + coex->freeze = false; + + if (type != COEX_SCAN_FINISH) + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | + COEX_SCBD_ONOFF, true); + + if (type == COEX_SCAN_START_5G) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART); + } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) { + coex_stat->wl_hi_pri_task2 = true; + + /* Force antenna setup for no scan result issue */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART); + } else { + coex_stat->wl_hi_pri_task2 = false; + rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH); + } +} + +void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + + if (coex->stop_dm) + return; + + if (type == COEX_SWITCH_TO_5G) + rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND); + else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) + rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND); + else + rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G); +} + +void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + + if (coex->stop_dm) + return; + + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | + COEX_SCBD_ONOFF, true); + + if (type == COEX_ASSOCIATE_5G_START) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART); + } else if (type == COEX_ASSOCIATE_5G_FINISH) { + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH); + } else if (type == COEX_ASSOCIATE_START) { + coex_stat->wl_hi_pri_task1 = true; + coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2; + + /* Force antenna setup for no scan result issue */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + + rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART); + + /* To keep TDMA case during connect process, + * to avoid changed by Btinfo and runcoexmechanism + */ + coex->freeze = true; + ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work, + 5 * HZ); + } else { + coex_stat->wl_hi_pri_task1 = false; + coex->freeze = false; + + rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH); + } +} + +void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 para[6] = {0}; + + if (coex->stop_dm) + return; + + if (type == COEX_MEDIA_CONNECT_5G) { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); + rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA); + } else if (type == COEX_MEDIA_CONNECT) { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); + + /* Force antenna setup for no scan result issue */ + rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); + + /* Set CCK Rx high Pri */ + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1); + + /* always enable 5ms extend if connect */ + para[0] = COEX_H2C69_WL_LEAKAP; + para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */ + rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); + coex_stat->wl_slot_extend = true; + rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA); + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); + + rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0); + + rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON); + } + + rtw_coex_update_wl_ch_info(rtwdev, type); +} + +void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_chip_info *chip = rtwdev->chip; + unsigned long bt_relink_time; + u8 i, rsp_source = 0, type; + + rsp_source = buf[0] & 0xf; + if (rsp_source >= COEX_BTINFO_SRC_MAX) + rsp_source = COEX_BTINFO_SRC_WL_FW; + + if (rsp_source == COEX_BTINFO_SRC_BT_IQK) { + coex_stat->bt_iqk_state = buf[1]; + if (coex_stat->bt_iqk_state == 1) + coex_stat->cnt_bt[COEX_CNT_BT_IQK]++; + else if (coex_stat->bt_iqk_state == 2) + coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++; + + return; + } + + if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) { + rtw_coex_monitor_bt_enable(rtwdev); + if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) { + coex_stat->bt_disabled_pre = coex_stat->bt_disabled; + rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); + } + return; + } + + if (rsp_source == COEX_BTINFO_SRC_BT_RSP || + rsp_source == COEX_BTINFO_SRC_BT_ACT) { + if (coex_stat->bt_disabled) { + coex_stat->bt_disabled = false; + coex_stat->bt_reenable = true; + ieee80211_queue_delayed_work(rtwdev->hw, + &coex->bt_reenable_work, + 15 * HZ); + } + } + + for (i = 0; i < length; i++) { + if (i < COEX_BTINFO_LENGTH_MAX) + coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; + else + break; + } + + if (rsp_source == COEX_BTINFO_SRC_WL_FW) { + rtw_coex_update_bt_link_info(rtwdev); + rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); + return; + } + + /* get the same info from bt, skip it */ + if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 && + coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 && + coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 && + coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 && + coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 && + coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) + return; + + coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1]; + coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2]; + coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3]; + coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4]; + coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5]; + coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6]; + + /* 0xff means BT is under WHCK test */ + coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff); + coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2)); + coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3)); + coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf; + if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1) + coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++; + + coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4)); + coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5)); + if (coex_stat->bt_inq) + coex_stat->cnt_bt[COEX_CNT_BT_INQ]++; + + coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7)); + if (coex_stat->bt_page) { + coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++; + if (coex_stat->wl_linkscan_proc || + coex_stat->wl_hi_pri_task1 || + coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) + rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); + else + rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); + } + + /* unit: % (value-100 to translate to unit: dBm in coex info) */ + if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) { + coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10; + } else { /* original unit: dbm -> unit: % -> value-100 in coex info */ + if (coex_stat->bt_info_hb0 <= 127) + coex_stat->bt_rssi = 100; + else if (256 - coex_stat->bt_info_hb0 <= 100) + coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0); + else + coex_stat->bt_rssi = 0; + } + + coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0)); + if (coex_stat->bt_info_hb1 & BIT(1)) + coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++; + + if (coex_stat->bt_info_hb1 & BIT(2)) { + coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++; + coex_stat->bt_setup_link = true; + if (coex_stat->bt_reenable) + bt_relink_time = 6 * HZ; + else + bt_relink_time = 2 * HZ; + + ieee80211_queue_delayed_work(rtwdev->hw, + &coex->bt_relink_work, + bt_relink_time); + } + + if (coex_stat->bt_info_hb1 & BIT(3)) + coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++; + + coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4)); + coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5)); + if (coex_stat->bt_info_hb1 & BIT(6)) + coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++; + + coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7)); + /* resend wifi info to bt, it is reset and lost the info */ + if ((coex_stat->bt_info_hb1 & BIT(1))) { + if (coex_stat->wl_connected) + type = COEX_MEDIA_CONNECT; + else + type = COEX_MEDIA_DISCONNECT; + rtw_coex_update_wl_ch_info(rtwdev, type); + } + + /* if ignore_wlan_act && not set_up_link */ + if ((coex_stat->bt_info_hb1 & BIT(3)) && + (!(coex_stat->bt_info_hb1 & BIT(2)))) + rtw_coex_ignore_wlan_act(rtwdev, false); + + coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0)); + if (coex_stat->bt_info_hb2 & BIT(1)) + coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++; + + coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2); + coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3)); + coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4; + coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6; + if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2) + coex_stat->bt_418_hid_exist = true; + else if (coex_stat->bt_hid_pair_num == 0) + coex_stat->bt_418_hid_exist = false; + + if ((coex_stat->bt_info_lb2 & 0x49) == 0x49) + coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f); + else + coex_stat->bt_a2dp_bitpool = 0; + + coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7)); + + rtw_coex_update_bt_link_info(rtwdev); + rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); +} + +void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + u8 val; + int i; + + if (WARN(length < 8, "invalid wl info c2h length\n")) + return; + + if (buf[0] != 0x08) + return; + + for (i = 1; i < 8; i++) { + val = coex_stat->wl_fw_dbg_info_pre[i]; + if (buf[i] >= val) + coex_stat->wl_fw_dbg_info[i] = buf[i] - val; + else + coex_stat->wl_fw_dbg_info[i] = val - buf[i]; + + coex_stat->wl_fw_dbg_info_pre[i] = buf[i]; + } + + coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++; + rtw_coex_wl_ccklock_action(rtwdev); + rtw_coex_wl_ccklock_detect(rtwdev); +} + +void rtw_coex_coex_dm_reset(struct rtw_dev *rtwdev) +{ + __rtw_coex_init_hw_config(rtwdev, false); +} + +void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + + if (coex->stop_dm) + return; + + rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); +} + +void rtw_coex_bt_relink_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + coex.bt_relink_work.work); + struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; + + mutex_lock(&rtwdev->mutex); + coex_stat->bt_setup_link = false; + rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); + mutex_unlock(&rtwdev->mutex); +} + +void rtw_coex_bt_reenable_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + coex.bt_reenable_work.work); + struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; + + mutex_lock(&rtwdev->mutex); + coex_stat->bt_reenable = false; + mutex_unlock(&rtwdev->mutex); +} + +void rtw_coex_defreeze_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + coex.defreeze_work.work); + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; + + mutex_lock(&rtwdev->mutex); + coex->freeze = false; + coex_stat->wl_hi_pri_task1 = false; + rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); + mutex_unlock(&rtwdev->mutex); +} diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h new file mode 100644 index 000000000000..56e871b2d6c2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/coex.h @@ -0,0 +1,369 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_COEX_H__ +#define __RTW_COEX_H__ + +/* BT profile map bit definition */ +#define BPM_HFP BIT(0) +#define BPM_HID BIT(1) +#define BPM_A2DP BIT(2) +#define BPM_PAN BIT(3) + +#define COEX_RESP_ACK_BY_WL_FW 0x1 +#define COEX_REQUEST_TIMEOUT msecs_to_jiffies(10) + +#define COEX_MIN_DELAY 10 /* delay unit in ms */ +#define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */ + +#define COEX_RF_OFF 0x0 +#define COEX_RF_ON 0x1 + +#define COEX_H2C69_WL_LEAKAP 0xc +#define PARA1_H2C69_DIS_5MS 0x1 +#define PARA1_H2C69_EN_5MS 0x0 + +#define COEX_H2C69_TDMA_SLOT 0xb +#define PARA1_H2C69_TDMA_4SLOT 0xc1 +#define PARA1_H2C69_TDMA_2SLOT 0x1 + +#define TDMA_4SLOT BIT(8) + +#define COEX_RSSI_STEP 4 +#define COEX_RSSI_HIGH(rssi) \ + ({ typeof(rssi) __rssi__ = rssi; \ + (__rssi__ == COEX_RSSI_STATE_HIGH || \ + __rssi__ == COEX_RSSI_STATE_STAY_HIGH ? true : false); }) + +#define COEX_RSSI_MEDIUM(rssi) \ + ({ typeof(rssi) __rssi__ = rssi; \ + (__rssi__ == COEX_RSSI_STATE_MEDIUM || \ + __rssi__ == COEX_RSSI_STATE_STAY_MEDIUM ? true : false); }) + +#define COEX_RSSI_LOW(rssi) \ + ({ typeof(rssi) __rssi__ = rssi; \ + (__rssi__ == COEX_RSSI_STATE_LOW || \ + __rssi__ == COEX_RSSI_STATE_STAY_LOW ? true : false); }) + +#define GET_COEX_RESP_BT_SCAN_TYPE(payload) \ + le64_get_bits(*((__le64 *)(payload)), GENMASK(31, 24)) + +enum coex_mp_info_op { + BT_MP_INFO_OP_PATCH_VER = 0x00, + BT_MP_INFO_OP_READ_REG = 0x11, + BT_MP_INFO_OP_SUPP_FEAT = 0x2a, + BT_MP_INFO_OP_SUPP_VER = 0x2b, + BT_MP_INFO_OP_SCAN_TYPE = 0x2d, + BT_MP_INFO_OP_LNA_CONSTRAINT = 0x32, +}; + +enum coex_set_ant_phase { + COEX_SET_ANT_INIT, + COEX_SET_ANT_WONLY, + COEX_SET_ANT_WOFF, + COEX_SET_ANT_2G, + COEX_SET_ANT_5G, + COEX_SET_ANT_POWERON, + COEX_SET_ANT_2G_WLBT, + COEX_SET_ANT_2G_FREERUN, + + COEX_SET_ANT_MAX +}; + +enum coex_runreason { + COEX_RSN_2GSCANSTART = 0, + COEX_RSN_5GSCANSTART = 1, + COEX_RSN_SCANFINISH = 2, + COEX_RSN_2GSWITCHBAND = 3, + COEX_RSN_5GSWITCHBAND = 4, + COEX_RSN_2GCONSTART = 5, + COEX_RSN_5GCONSTART = 6, + COEX_RSN_2GCONFINISH = 7, + COEX_RSN_5GCONFINISH = 8, + COEX_RSN_2GMEDIA = 9, + COEX_RSN_5GMEDIA = 10, + COEX_RSN_MEDIADISCON = 11, + COEX_RSN_BTINFO = 12, + COEX_RSN_LPS = 13, + COEX_RSN_WLSTATUS = 14, + + COEX_RSN_MAX +}; + +enum coex_lte_coex_table_type { + COEX_CTT_WL_VS_LTE, + COEX_CTT_BT_VS_LTE, +}; + +enum coex_gnt_setup_state { + COEX_GNT_SET_HW_PTA = 0x0, + COEX_GNT_SET_SW_LOW = 0x1, + COEX_GNT_SET_SW_HIGH = 0x3, +}; + +enum coex_ext_ant_switch_pos_type { + COEX_SWITCH_TO_BT, + COEX_SWITCH_TO_WLG, + COEX_SWITCH_TO_WLA, + COEX_SWITCH_TO_NOCARE, + COEX_SWITCH_TO_WLG_BT, + + COEX_SWITCH_TO_MAX +}; + +enum coex_ext_ant_switch_ctrl_type { + COEX_SWITCH_CTRL_BY_BBSW, + COEX_SWITCH_CTRL_BY_PTA, + COEX_SWITCH_CTRL_BY_ANTDIV, + COEX_SWITCH_CTRL_BY_MAC, + COEX_SWITCH_CTRL_BY_BT, + COEX_SWITCH_CTRL_BY_FW, + + COEX_SWITCH_CTRL_MAX +}; + +enum coex_algorithm { + COEX_ALGO_NOPROFILE = 0, + COEX_ALGO_HFP = 1, + COEX_ALGO_HID = 2, + COEX_ALGO_A2DP = 3, + COEX_ALGO_PAN = 4, + COEX_ALGO_A2DP_HID = 5, + COEX_ALGO_A2DP_PAN = 6, + COEX_ALGO_PAN_HID = 7, + COEX_ALGO_A2DP_PAN_HID = 8, + + COEX_ALGO_MAX +}; + +enum coex_wl_link_mode { + COEX_WLINK_2G1PORT = 0x0, + COEX_WLINK_5G = 0x3, + COEX_WLINK_MAX +}; + +enum coex_wl2bt_scoreboard { + COEX_SCBD_ACTIVE = BIT(0), + COEX_SCBD_ONOFF = BIT(1), + COEX_SCBD_SCAN = BIT(2), + COEX_SCBD_UNDERTEST = BIT(3), + COEX_SCBD_RXGAIN = BIT(4), + COEX_SCBD_BT_RFK = BIT(5), + COEX_SCBD_WLBUSY = BIT(6), + COEX_SCBD_EXTFEM = BIT(8), + COEX_SCBD_TDMA = BIT(9), + COEX_SCBD_FIX2M = BIT(10), + COEX_SCBD_ALL = GENMASK(15, 0), +}; + +enum coex_power_save_type { + COEX_PS_WIFI_NATIVE = 0, + COEX_PS_LPS_ON = 1, + COEX_PS_LPS_OFF = 2, +}; + +enum coex_rssi_state { + COEX_RSSI_STATE_HIGH, + COEX_RSSI_STATE_MEDIUM, + COEX_RSSI_STATE_LOW, + COEX_RSSI_STATE_STAY_HIGH, + COEX_RSSI_STATE_STAY_MEDIUM, + COEX_RSSI_STATE_STAY_LOW, +}; + +enum coex_notify_type_ips { + COEX_IPS_LEAVE = 0x0, + COEX_IPS_ENTER = 0x1, +}; + +enum coex_notify_type_lps { + COEX_LPS_DISABLE = 0x0, + COEX_LPS_ENABLE = 0x1, +}; + +enum coex_notify_type_scan { + COEX_SCAN_FINISH, + COEX_SCAN_START, + COEX_SCAN_START_2G, + COEX_SCAN_START_5G, +}; + +enum coex_notify_type_switchband { + COEX_NOT_SWITCH, + COEX_SWITCH_TO_24G, + COEX_SWITCH_TO_5G, + COEX_SWITCH_TO_24G_NOFORSCAN, +}; + +enum coex_notify_type_associate { + COEX_ASSOCIATE_FINISH, + COEX_ASSOCIATE_START, + COEX_ASSOCIATE_5G_FINISH, + COEX_ASSOCIATE_5G_START, +}; + +enum coex_notify_type_media_status { + COEX_MEDIA_DISCONNECT, + COEX_MEDIA_CONNECT, + COEX_MEDIA_CONNECT_5G, +}; + +enum coex_bt_status { + COEX_BTSTATUS_NCON_IDLE = 0, + COEX_BTSTATUS_CON_IDLE = 1, + COEX_BTSTATUS_INQ_PAGE = 2, + COEX_BTSTATUS_ACL_BUSY = 3, + COEX_BTSTATUS_SCO_BUSY = 4, + COEX_BTSTATUS_ACL_SCO_BUSY = 5, + + COEX_BTSTATUS_MAX +}; + +enum coex_wl_tput_dir { + COEX_WL_TPUT_TX = 0x0, + COEX_WL_TPUT_RX = 0x1, + COEX_WL_TPUT_MAX +}; + +enum coex_wl_priority_mask { + COEX_WLPRI_RX_RSP = 2, + COEX_WLPRI_TX_RSP = 3, + COEX_WLPRI_TX_BEACON = 4, + COEX_WLPRI_TX_OFDM = 11, + COEX_WLPRI_TX_CCK = 12, + COEX_WLPRI_TX_BEACONQ = 27, + COEX_WLPRI_RX_CCK = 28, + COEX_WLPRI_RX_OFDM = 29, + COEX_WLPRI_MAX +}; + +enum coex_commom_chip_setup { + COEX_CSETUP_INIT_HW = 0x0, + COEX_CSETUP_ANT_SWITCH = 0x1, + COEX_CSETUP_GNT_FIX = 0x2, + COEX_CSETUP_GNT_DEBUG = 0x3, + COEX_CSETUP_RFE_TYPE = 0x4, + COEX_CSETUP_COEXINFO_HW = 0x5, + COEX_CSETUP_WL_TX_POWER = 0x6, + COEX_CSETUP_WL_RX_GAIN = 0x7, + COEX_CSETUP_WLAN_ACT_IPS = 0x8, + COEX_CSETUP_MAX +}; + +enum coex_indirect_reg_type { + COEX_INDIRECT_1700 = 0x0, + COEX_INDIRECT_7C0 = 0x1, + COEX_INDIRECT_MAX +}; + +enum coex_pstdma_type { + COEX_PSTDMA_FORCE_LPSOFF = 0x0, + COEX_PSTDMA_FORCE_LPSON = 0x1, + COEX_PSTDMA_MAX +}; + +enum coex_btrssi_type { + COEX_BTRSSI_RATIO = 0x0, + COEX_BTRSSI_DBM = 0x1, + COEX_BTRSSI_MAX +}; + +struct coex_table_para { + u32 bt; + u32 wl; +}; + +struct coex_tdma_para { + u8 para[5]; +}; + +struct coex_5g_afh_map { + u32 wl_5g_ch; + u8 bt_skip_ch; + u8 bt_skip_span; +}; + +struct coex_rf_para { + u8 wl_pwr_dec_lvl; + u8 bt_pwr_dec_lvl; + bool wl_low_gain_en; + u8 bt_lna_lvl; +}; + +static inline void rtw_coex_set_init(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_init(rtwdev); +} + +static inline +void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->ops->coex_set_ant_switch) + return; + + chip->ops->coex_set_ant_switch(rtwdev, ctrl_type, pos_type); +} + +static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_gnt_fix(rtwdev); +} + +static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_gnt_debug(rtwdev); +} + +static inline void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_rfe_type(rtwdev); +} + +static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr); +} + +static inline +void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain); +} + +void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb); +void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, + u32 mask, u32 val); +void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set); + +void rtw_coex_bt_relink_work(struct work_struct *work); +void rtw_coex_bt_reenable_work(struct work_struct *work); +void rtw_coex_defreeze_work(struct work_struct *work); + +void rtw_coex_power_on_setting(struct rtw_dev *rtwdev); +void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only); +void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type); +void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type); +void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type); +void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 action); +void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 status); +void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 len); +void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length); +void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type); +void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 3b06f7150c41..b082e2cc95f5 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -3,6 +3,7 @@ */ #include "main.h" +#include "coex.h" #include "fw.h" #include "tx.h" #include "reg.h" @@ -39,6 +40,12 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) mutex_lock(&rtwdev->mutex); switch (c2h->id) { + case C2H_BT_INFO: + rtw_coex_bt_info_notify(rtwdev, c2h->payload, len); + break; + case C2H_WLAN_INFO: + rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len); + break; case C2H_HALMAC: rtw_fw_c2h_cmd_handle_ext(rtwdev, skb); break; @@ -63,6 +70,9 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, c2h->id, c2h->seq, len); switch (c2h->id) { + case C2H_BT_MP_INFO: + rtw_coex_info_response(rtwdev, skb); + break; default: /* pass offset for further operation */ *((u32 *)skb->cb) = pkt_offset; @@ -206,6 +216,102 @@ void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para) rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); } +void rtw_fw_query_bt_info(struct rtw_dev *rtwdev) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_INFO); + + SET_QUERY_BT_INFO(h2c_pkt, true); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_CH_INFO); + + SET_WL_CH_INFO_LINK(h2c_pkt, link); + SET_WL_CH_INFO_CHNL(h2c_pkt, ch); + SET_WL_CH_INFO_BW(h2c_pkt, bw); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev, + struct rtw_coex_info_req *req) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_MP_INFO); + + SET_BT_MP_INFO_SEQ(h2c_pkt, req->seq); + SET_BT_MP_INFO_OP_CODE(h2c_pkt, req->op_code); + SET_BT_MP_INFO_PARA1(h2c_pkt, req->para1); + SET_BT_MP_INFO_PARA2(h2c_pkt, req->para2); + SET_BT_MP_INFO_PARA3(h2c_pkt, req->para3); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u8 index = 0 - bt_pwr_dec_lvl; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_FORCE_BT_TX_POWER); + + SET_BT_TX_POWER_INDEX(h2c_pkt, index); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_IGNORE_WLAN_ACTION); + + SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, enable); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev, + u8 para1, u8 para2, u8 para3, u8 para4, u8 para5) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_COEX_TDMA_TYPE); + + SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, para1); + SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, para2); + SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, para3); + SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, para4); + SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, para5); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BT_WIFI_CONTROL); + + SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, op_code); + + SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, *data); + SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, *(data + 1)); + SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, *(data + 2)); + SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, *(data + 3)); + SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, *(data + 4)); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) { u8 h2c_pkt[H2C_PKT_SIZE] = {0}; diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 67f6cf770ced..e95d85bd097f 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -35,7 +35,9 @@ enum rtw_c2h_cmd_id { C2H_BT_INFO = 0x09, + C2H_BT_MP_INFO = 0x0b, C2H_HW_FEATURE_REPORT = 0x19, + C2H_WLAN_INFO = 0x27, C2H_HW_FEATURE_DUMP = 0xfd, C2H_HALMAC = 0xff, }; @@ -71,6 +73,14 @@ enum rtw_fw_rf_type { FW_RF_MAX_TYPE = 0xF, }; +struct rtw_coex_info_req { + u8 seq; + u8 op_code; + u8 para1; + u8 para2; + u8 para3; +}; + struct rtw_iqk_para { u8 clear; u8 segment_iqk; @@ -139,6 +149,14 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define H2C_CMD_RA_INFO 0x40 #define H2C_CMD_RSSI_MONITOR 0x42 +#define H2C_CMD_COEX_TDMA_TYPE 0x60 +#define H2C_CMD_QUERY_BT_INFO 0x61 +#define H2C_CMD_FORCE_BT_TX_POWER 0x62 +#define H2C_CMD_IGNORE_WLAN_ACTION 0x63 +#define H2C_CMD_WL_CH_INFO 0x66 +#define H2C_CMD_QUERY_BT_MP_INFO 0x67 +#define H2C_CMD_BT_WIFI_CONTROL 0x69 + #define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) @@ -191,6 +209,50 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) #define SET_RA_INFO_RA_MASK3(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 24)) +#define SET_QUERY_BT_INFO(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_WL_CH_INFO_LINK(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_WL_CH_INFO_CHNL(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_WL_CH_INFO_BW(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_BT_MP_INFO_SEQ(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12)) +#define SET_BT_MP_INFO_OP_CODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_BT_MP_INFO_PARA1(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_BT_MP_INFO_PARA2(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) +#define SET_BT_MP_INFO_PARA3(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_BT_TX_POWER_INDEX(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) +#define SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) +#define SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) { @@ -208,6 +270,15 @@ void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev); void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para); void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev); +void rtw_fw_query_bt_info(struct rtw_dev *rtwdev); +void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw); +void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev, + struct rtw_coex_info_req *req); +void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl); +void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev, + u8 para1, u8 para2, u8 para3, u8 para4, u8 para5); +void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data); void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index abe6a148673b..fedea28c7a97 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -7,6 +7,7 @@ #include "tx.h" #include "fw.h" #include "mac.h" +#include "coex.h" #include "ps.h" #include "reg.h" #include "debug.h" @@ -253,6 +254,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, enum rtw_net_type net_type; if (conf->assoc) { + rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH); net_type = RTW_NET_MGD_LINKED; chip->ops->do_iqk(rtwdev); @@ -262,6 +264,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); rtw_fw_download_rsvd_page(rtwdev, vif); rtw_send_rsvd_page_h2c(rtwdev); + rtw_coex_media_status_notify(rtwdev, conf->assoc); } else { net_type = RTW_NET_NO_LINK; rtwvif->aid = 0; @@ -469,6 +472,8 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, config |= PORT_SET_MAC_ADDR; rtw_vif_port_config(rtwdev, rtwvif, config); + rtw_coex_scan_notify(rtwdev, COEX_SCAN_START); + rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE); rtw_flag_set(rtwdev, RTW_FLAG_SCANNING); @@ -491,6 +496,19 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, config |= PORT_SET_MAC_ADDR; rtw_vif_port_config(rtwdev, rtwvif, config); + rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH); + + mutex_unlock(&rtwdev->mutex); +} + +static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 duration) +{ + struct rtw_dev *rtwdev = hw->priv; + + mutex_lock(&rtwdev->mutex); + rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START); mutex_unlock(&rtwdev->mutex); } @@ -509,5 +527,6 @@ const struct ieee80211_ops rtw_ops = { .ampdu_action = rtw_ops_ampdu_action, .sw_scan_start = rtw_ops_sw_scan_start, .sw_scan_complete = rtw_ops_sw_scan_complete, + .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, }; EXPORT_SYMBOL(rtw_ops); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 5a2c06267d07..e5a6bc094808 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -8,6 +8,7 @@ #include "ps.h" #include "sec.h" #include "mac.h" +#include "coex.h" #include "phy.h" #include "reg.h" #include "efuse.h" @@ -149,6 +150,7 @@ static void rtw_watch_dog_work(struct work_struct *work) struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, watch_dog_work.work); struct rtw_watch_dog_iter_data data = {}; + bool busy_traffic = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC); if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) return; @@ -156,6 +158,14 @@ static void rtw_watch_dog_work(struct work_struct *work) ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, RTW_WATCH_DOG_DELAY_TIME); + if (rtwdev->stats.tx_cnt > 100 || rtwdev->stats.rx_cnt > 100) + rtw_flag_set(rtwdev, RTW_FLAG_BUSY_TRAFFIC); + else + rtw_flag_clear(rtwdev, RTW_FLAG_BUSY_TRAFFIC); + + if (busy_traffic != rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC)) + rtw_coex_wl_status_change_notify(rtwdev); + /* reset tx/rx statictics */ rtwdev->stats.tx_unicast = 0; rtwdev->stats.rx_unicast = 0; @@ -298,6 +308,15 @@ void rtw_set_channel(struct rtw_dev *rtwdev) chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx); + if (hal->current_band_type == RTW_BAND_5G) { + rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G); + } else { + if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING)) + rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G); + else + rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G_NOFORSCAN); + } + rtw_phy_set_tx_power_level(rtwdev, center_chan); } @@ -641,6 +660,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fw_state *fw = &rtwdev->fw; + bool wifi_only; int ret; ret = rtw_hci_setup(rtwdev); @@ -684,6 +704,10 @@ static int rtw_power_on(struct rtw_dev *rtwdev) goto err_off; } + wifi_only = !rtwdev->efuse.btcoex; + rtw_coex_power_on_setting(rtwdev); + rtw_coex_init_hw_config(rtwdev, wifi_only); + return 0; err_off: @@ -722,10 +746,15 @@ static void rtw_power_off(struct rtw_dev *rtwdev) void rtw_core_stop(struct rtw_dev *rtwdev) { + struct rtw_coex *coex = &rtwdev->coex; + rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING); rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING); cancel_delayed_work_sync(&rtwdev->watch_dog_work); + cancel_delayed_work_sync(&coex->bt_relink_work); + cancel_delayed_work_sync(&coex->bt_reenable_work); + cancel_delayed_work_sync(&coex->defreeze_work); rtw_power_off(rtwdev); } @@ -876,7 +905,6 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) struct rtw_chip_info *chip = rtwdev->chip; struct rtw_hal *hal = &rtwdev->hal; struct rtw_efuse *efuse = &rtwdev->efuse; - u32 wl_bt_pwr_ctrl; int ret = 0; switch (rtw_hci_type(rtwdev)) { @@ -888,9 +916,6 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) return -EINVAL; } - wl_bt_pwr_ctrl = rtw_read32(rtwdev, REG_WL_BT_PWR_CTRL); - if (wl_bt_pwr_ctrl & BIT_BT_FUNC_EN) - rtwdev->efuse.btcoex = true; hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1); hal->fab_version = BIT_GET_VENDOR_ID(hal->chip_version) >> 2; hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version); @@ -1044,11 +1069,14 @@ static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) efuse->lna_type_5g = 0; if (efuse->channel_plan == 0xff) efuse->channel_plan = 0x7f; + if (efuse->rf_board_option == 0xff) + efuse->rf_board_option = 0; if (efuse->bt_setting & BIT(0)) efuse->share_ant = true; if (efuse->regd == 0xff) efuse->regd = 0; + efuse->btcoex = (efuse->rf_board_option & 0xe0) == 0x20; efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; @@ -1111,6 +1139,7 @@ EXPORT_SYMBOL(rtw_chip_info_setup); int rtw_core_init(struct rtw_dev *rtwdev) { + struct rtw_coex *coex = &rtwdev->coex; int ret; INIT_LIST_HEAD(&rtwdev->rsvd_page_list); @@ -1120,8 +1149,12 @@ int rtw_core_init(struct rtw_dev *rtwdev) INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work); + INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work); + INIT_DELAYED_WORK(&coex->bt_reenable_work, rtw_coex_bt_reenable_work); + INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work); INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); skb_queue_head_init(&rtwdev->c2h_queue); + skb_queue_head_init(&rtwdev->coex.queue); skb_queue_head_init(&rtwdev->tx_report.queue); spin_lock_init(&rtwdev->dm_lock); @@ -1130,8 +1163,11 @@ int rtw_core_init(struct rtw_dev *rtwdev) spin_lock_init(&rtwdev->tx_report.q_lock); mutex_init(&rtwdev->mutex); + mutex_init(&rtwdev->coex.mutex); mutex_init(&rtwdev->hal.tx_power_mutex); + init_waitqueue_head(&rtwdev->coex.wait); + rtwdev->sec.total_cam_num = 32; rtwdev->hal.current_channel = 1; set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); @@ -1174,6 +1210,7 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) } mutex_destroy(&rtwdev->mutex); + mutex_destroy(&rtwdev->coex.mutex); mutex_destroy(&rtwdev->hal.tx_power_mutex); } EXPORT_SYMBOL(rtw_core_deinit); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 8fa05751836b..9208b9ce5513 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -310,6 +310,7 @@ enum rtw_flags { RTW_FLAG_INACTIVE_PS, RTW_FLAG_LEISURE_PS, RTW_FLAG_DIG_DISABLE, + RTW_FLAG_BUSY_TRAFFIC, NUM_OF_RTW_FLAGS, }; @@ -640,6 +641,16 @@ struct rtw_chip_ops { void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable); void (*false_alarm_statistics)(struct rtw_dev *rtwdev); void (*do_iqk)(struct rtw_dev *rtwdev); + + /* for coex */ + void (*coex_set_init)(struct rtw_dev *rtwdev); + void (*coex_set_ant_switch)(struct rtw_dev *rtwdev, + u8 ctrl_type, u8 pos_type); + void (*coex_set_gnt_fix)(struct rtw_dev *rtwdev); + void (*coex_set_gnt_debug)(struct rtw_dev *rtwdev); + void (*coex_set_rfe_type)(struct rtw_dev *rtwdev); + void (*coex_set_wl_tx_power)(struct rtw_dev *rtwdev, u8 wl_pwr); + void (*coex_set_wl_rx_gain)(struct rtw_dev *rtwdev, bool low_gain); }; #define RTW_PWR_POLLING_CNT 20000 @@ -852,6 +863,216 @@ struct rtw_chip_info { const struct rtw_rfe_def *rfe_defs; u32 rfe_defs_size; + + /* coex paras */ + u32 coex_para_ver; + u8 bt_desired_ver; + bool scbd_support; + bool new_scbd10_def; /* true: fix 2M(8822c) */ + u8 pstdma_type; /* 0: LPSoff, 1:LPSon */ + u8 bt_rssi_type; + u8 ant_isolation; + u8 rssi_tolerance; + u8 table_sant_num; + u8 table_nsant_num; + u8 tdma_sant_num; + u8 tdma_nsant_num; + u8 bt_afh_span_bw20; + u8 bt_afh_span_bw40; + u8 afh_5g_num; + u8 wl_rf_para_num; + const u8 *bt_rssi_step; + const u8 *wl_rssi_step; + const struct coex_table_para *table_nsant; + const struct coex_table_para *table_sant; + const struct coex_tdma_para *tdma_sant; + const struct coex_tdma_para *tdma_nsant; + const struct coex_rf_para *wl_rf_para_tx; + const struct coex_rf_para *wl_rf_para_rx; + const struct coex_5g_afh_map *afh_5g; +}; + +enum rtw_coex_bt_state_cnt { + COEX_CNT_BT_RETRY, + COEX_CNT_BT_REINIT, + COEX_CNT_BT_REENABLE, + COEX_CNT_BT_POPEVENT, + COEX_CNT_BT_SETUPLINK, + COEX_CNT_BT_IGNWLANACT, + COEX_CNT_BT_INQ, + COEX_CNT_BT_PAGE, + COEX_CNT_BT_ROLESWITCH, + COEX_CNT_BT_AFHUPDATE, + COEX_CNT_BT_INFOUPDATE, + COEX_CNT_BT_IQK, + COEX_CNT_BT_IQKFAIL, + + COEX_CNT_BT_MAX +}; + +enum rtw_coex_wl_state_cnt { + COEX_CNT_WL_CONNPKT, + COEX_CNT_WL_COEXRUN, + COEX_CNT_WL_NOISY0, + COEX_CNT_WL_NOISY1, + COEX_CNT_WL_NOISY2, + COEX_CNT_WL_5MS_NOEXTEND, + COEX_CNT_WL_FW_NOTIFY, + + COEX_CNT_WL_MAX +}; + +struct rtw_coex_rfe { + bool ant_switch_exist; + bool ant_switch_diversity; + bool ant_switch_with_bt; + u8 rfe_module_type; + u8 ant_switch_polarity; + + /* true if WLG at BTG, else at WLAG */ + bool wlg_at_btg; +}; + +struct rtw_coex_dm { + bool cur_ps_tdma_on; + bool cur_wl_rx_low_gain_en; + + u8 reason; + u8 bt_rssi_state[4]; + u8 wl_rssi_state[4]; + u8 wl_ch_info[3]; + u8 cur_ps_tdma; + u8 cur_table; + u8 ps_tdma_para[5]; + u8 cur_bt_pwr_lvl; + u8 cur_bt_lna_lvl; + u8 cur_wl_pwr_lvl; + u8 bt_status; + u32 cur_ant_pos_type; + u32 cur_switch_status; + u32 setting_tdma; +}; + +#define COEX_BTINFO_SRC_WL_FW 0x0 +#define COEX_BTINFO_SRC_BT_RSP 0x1 +#define COEX_BTINFO_SRC_BT_ACT 0x2 +#define COEX_BTINFO_SRC_BT_IQK 0x3 +#define COEX_BTINFO_SRC_BT_SCBD 0x4 +#define COEX_BTINFO_SRC_MAX 0x5 + +#define COEX_INFO_FTP BIT(7) +#define COEX_INFO_A2DP BIT(6) +#define COEX_INFO_HID BIT(5) +#define COEX_INFO_SCO_BUSY BIT(4) +#define COEX_INFO_ACL_BUSY BIT(3) +#define COEX_INFO_INQ_PAGE BIT(2) +#define COEX_INFO_SCO_ESCO BIT(1) +#define COEX_INFO_CONNECTION BIT(0) +#define COEX_BTINFO_LENGTH_MAX 10 + +struct rtw_coex_stat { + bool bt_disabled; + bool bt_disabled_pre; + bool bt_link_exist; + bool bt_whck_test; + bool bt_inq_page; + bool bt_inq; + bool bt_page; + bool bt_ble_voice; + bool bt_ble_exist; + bool bt_hfp_exist; + bool bt_a2dp_exist; + bool bt_hid_exist; + bool bt_pan_exist; /* PAN or OPP */ + bool bt_opp_exist; /* OPP only */ + bool bt_acl_busy; + bool bt_fix_2M; + bool bt_setup_link; + bool bt_multi_link; + bool bt_a2dp_sink; + bool bt_a2dp_active; + bool bt_reenable; + bool bt_ble_scan_en; + bool bt_init_scan; + bool bt_slave; + bool bt_418_hid_exist; + bool bt_mailbox_reply; + + bool wl_under_lps; + bool wl_under_ips; + bool wl_hi_pri_task1; + bool wl_hi_pri_task2; + bool wl_force_lps_ctrl; + bool wl_gl_busy; + bool wl_linkscan_proc; + bool wl_ps_state_fail; + bool wl_tx_limit_en; + bool wl_ampdu_limit_en; + bool wl_connected; + bool wl_slot_extend; + bool wl_cck_lock; + bool wl_cck_lock_pre; + bool wl_cck_lock_ever; + + u32 bt_supported_version; + u32 bt_supported_feature; + s8 bt_rssi; + u8 kt_ver; + u8 gnt_workaround_state; + u8 tdma_timer_base; + u8 bt_profile_num; + u8 bt_info_c2h[COEX_BTINFO_SRC_MAX][COEX_BTINFO_LENGTH_MAX]; + u8 bt_info_lb2; + u8 bt_info_lb3; + u8 bt_info_hb0; + u8 bt_info_hb1; + u8 bt_info_hb2; + u8 bt_info_hb3; + u8 bt_ble_scan_type; + u8 bt_hid_pair_num; + u8 bt_hid_slot; + u8 bt_a2dp_bitpool; + u8 bt_iqk_state; + + u8 wl_noisy_level; + u8 wl_fw_dbg_info[10]; + u8 wl_fw_dbg_info_pre[10]; + u8 wl_coex_mode; + u8 ampdu_max_time; + u8 wl_tput_dir; + + u16 score_board; + u16 retry_limit; + + /* counters to record bt states */ + u32 cnt_bt[COEX_CNT_BT_MAX]; + + /* counters to record wifi states */ + u32 cnt_wl[COEX_CNT_WL_MAX]; + + u32 darfrc; + u32 darfrch; +}; + +struct rtw_coex { + /* protects coex info request section */ + struct mutex mutex; + struct sk_buff_head queue; + wait_queue_head_t wait; + + bool under_5g; + bool stop_dm; + bool freeze; + bool freerun; + bool wl_rf_off; + + struct rtw_coex_stat stat; + struct rtw_coex_dm dm; + struct rtw_coex_rfe rfe; + + struct delayed_work bt_relink_work; + struct delayed_work bt_reenable_work; + struct delayed_work defreeze_work; }; #define DACK_MSBK_BACKUP_NUM 0xf @@ -861,6 +1082,16 @@ struct rtw_dm_info { u32 cck_fa_cnt; u32 ofdm_fa_cnt; u32 total_fa_cnt; + + u32 cck_ok_cnt; + u32 cck_err_cnt; + u32 ofdm_ok_cnt; + u32 ofdm_err_cnt; + u32 ht_ok_cnt; + u32 ht_err_cnt; + u32 vht_ok_cnt; + u32 vht_err_cnt; + u8 min_rssi; u8 pre_min_rssi; u16 fa_history[4]; @@ -888,6 +1119,7 @@ struct rtw_efuse { u8 addr[ETH_ALEN]; u8 channel_plan; u8 country_code[2]; + u8 rf_board_option; u8 rfe_option; u8 thermal_meter; u8 crystal_cap; @@ -1047,6 +1279,7 @@ struct rtw_dev { struct rtw_regulatory regd; struct rtw_dm_info dm_info; + struct rtw_coex coex; /* ensures exclusive access from mac80211 callbacks */ struct mutex mutex; diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 607bfa4317d9..9ecd14feb76b 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -6,6 +6,7 @@ #include "fw.h" #include "ps.h" #include "mac.h" +#include "coex.h" #include "debug.h" static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) @@ -26,6 +27,8 @@ int rtw_enter_ips(struct rtw_dev *rtwdev) { rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS); + rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER); + rtw_core_stop(rtwdev); return 0; @@ -53,6 +56,8 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev); + rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); + return 0; } @@ -67,6 +72,8 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev) rtw_fw_set_pwr_mode(rtwdev); rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS); + + rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); } static void rtw_enter_lps_core(struct rtw_dev *rtwdev) @@ -78,6 +85,8 @@ static void rtw_enter_lps_core(struct rtw_dev *rtwdev) conf->rlbm = 1; conf->smart_ps = 2; + rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE); + rtw_fw_set_pwr_mode(rtwdev); rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS); } diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index e2628f05812c..0bd0717baa8b 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -37,17 +37,28 @@ #define REG_GPIO_MUXCFG 0x0040 #define BIT_FSPI_EN BIT(19) +#define BIT_BT_AOD_GPIO3 BIT(9) +#define BIT_BT_PTA_EN BIT(5) #define BIT_WLRFE_4_5_EN BIT(2) #define REG_LED_CFG 0x004C #define BIT_LNAON_SEL_EN BIT(26) #define BIT_PAPE_SEL_EN BIT(25) +#define BIT_DPDT_WL_SEL BIT(24) +#define BIT_DPDT_SEL_EN BIT(23) #define REG_PAD_CTRL1 0x0064 #define BIT_PAPE_WLBT_SEL BIT(29) #define BIT_LNAON_WLBT_SEL BIT(28) +#define BIT_BTGP_JTAG_EN BIT(24) +#define BIT_BTGP_SPI_EN BIT(20) +#define BIT_LED1DIS BIT(15) +#define BIT_SW_DPDT_SEL_DATA BIT(0) #define REG_WL_BT_PWR_CTRL 0x0068 #define BIT_BT_FUNC_EN BIT(18) #define BIT_BT_DIG_CLK_EN BIT(8) +#define REG_SYS_SDIO_CTRL 0x0070 +#define BIT_DBG_GNT_WL_BT BIT(27) +#define BIT_LTE_MUX_CTRL_PATH BIT(26) #define REG_HCI_OPT_CTRL 0x0074 #define REG_MCUFW_CTRL 0x0080 @@ -70,6 +81,8 @@ #define FW_READY_MASK 0xffff #define REG_WLRF1 0x00EC +#define REG_WIFI_BT_INFO 0x00AA +#define BIT_BT_INT_EN BIT(15) #define REG_SYS_CFG1 0x00F0 #define BIT_RTL_ID BIT(23) #define BIT_RF_TYPE_ID BIT(27) @@ -187,6 +200,7 @@ #define REG_LIFETIME_EN 0x0426 #define BIT_BA_PARSER_EN BIT(5) #define REG_SPEC_SIFS 0x0428 +#define REG_RETRY_LIMIT 0x042a #define REG_DARFRC 0x0430 #define REG_DARFRCH 0x0434 #define REG_RARFRCH 0x043C @@ -199,18 +213,25 @@ #define REG_AMPDU_MAX_TIME_V1 0x0455 #define REG_BCNQ1_BDNY_V1 0x0456 #define REG_TX_HANG_CTRL 0x045E +#define BIT_EN_GNT_BT_AWAKE BIT(3) #define BIT_EN_EOF_V1 BIT(2) #define REG_DATA_SC 0x0483 #define REG_ARFR4 0x049C +#define BIT_WL_RFK BIT(0) #define REG_ARFRH4 0x04A0 #define REG_ARFR5 0x04A4 #define REG_ARFRH5 0x04A8 #define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC #define BIT_PRE_TX_CMD BIT(6) +#define REG_QUEUE_CTRL 0x04C6 +#define BIT_PTA_WL_TX_EN BIT(4) +#define BIT_PTA_EDCCA_EN BIT(5) #define REG_PROT_MODE_CTRL 0x04C8 #define REG_BAR_MODE_CTRL 0x04CC #define REG_PRECNT_CTRL 0x04E5 +#define BIT_BTCCA_CTRL (BIT(0) | BIT(1)) #define BIT_EN_PRECNT BIT(11) +#define REG_DUMMY_PAGE4_V1 0x04FC #define REG_EDCA_VO_PARAM 0x0500 #define REG_EDCA_VI_PARAM 0x0504 @@ -297,11 +318,34 @@ #define REG_RXFLTMAP0 0x06A0 #define REG_RXFLTMAP1 0x06A2 #define REG_RXFLTMAP2 0x06A4 +#define REG_BT_COEX_TABLE0 0x06C0 +#define REG_BT_COEX_TABLE1 0x06C4 +#define REG_BT_COEX_BRK_TABLE 0x06C8 +#define REG_BT_COEX_TABLE_H 0x06CC +#define REG_BT_COEX_TABLE_H1 0x06CD +#define REG_BT_COEX_TABLE_H2 0x06CE +#define REG_BT_COEX_TABLE_H3 0x06CF #define REG_BBPSF_CTRL 0x06DC +#define REG_BT_COEX_V2 0x0763 +#define BIT_GNT_BT_POLARITY BIT(4) +#define BIT_LTE_COEX_EN BIT(7) +#define REG_BT_STAT_CTRL 0x0778 +#define REG_BT_TDMA_TIME 0x0790 #define REG_WMAC_OPTION_FUNCTION 0x07D0 #define REG_WMAC_OPTION_FUNCTION_1 0x07D4 +#define REG_RX_GAIN_EN 0x081c + +#define REG_RFE_CTRL_E 0x0974 + +#define REG_RFE_CTRL8 0x0cb4 +#define BIT_MASK_RFE_SEL89 GENMASK(7, 0) +#define REG_RFE_INV8 0x0cbd +#define BIT_MASK_RFE_INV89 GENMASK(1, 0) +#define REG_RFE_INV16 0x0cbe +#define BIT_RFE_BUF_EN BIT(3) + #define REG_ANAPAR_XTAL_0 0x1040 #define REG_CPU_DMEM_CON 0x1080 #define BIT_WL_PLATFORM_RST BIT(16) @@ -407,15 +451,33 @@ #define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 #define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 +#define REG_IGN_GNT_BT1 0x1860 + +#define REG_RFESEL_CTRL 0x1990 + +#define REG_NOMASK_TXBT 0x1ca7 +#define REG_ANAPAR 0x1c30 +#define BIT_ANAPAR_BTPS BIT(22) +#define REG_RSTB_SEL 0x1c38 + +#define REG_IGN_GNTBT4 0x4160 + +#define RF_MODOPT 0x01 #define RF_DTXLOK 0x08 #define RF_CFGCH 0x18 +#define RF_RCK 0x1d #define RF_LUTWA 0x33 #define RF_LUTWD1 0x3e #define RF_LUTWD0 0x3f #define RF_XTALX2 0xb8 #define RF_MALSEL 0xbe +#define RF_RCKD 0xde #define RF_LUTDBG 0xdf #define RF_LUTWE2 0xee #define RF_LUTWE 0xef +#define LTE_COEX_CTRL 0x38 +#define LTE_WL_TRX_CTRL 0xa0 +#define LTE_BT_TRX_CTRL 0xa4 + #endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index d61d534396c7..568033afb024 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -3,6 +3,7 @@ */ #include "main.h" +#include "coex.h" #include "fw.h" #include "tx.h" #include "rx.h" @@ -31,6 +32,7 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) map = (struct rtw8822b_efuse *)log_map; efuse->rfe_option = map->rfe_option; + efuse->rf_board_option = map->rf_board_option; efuse->crystal_cap = map->xtal_k; efuse->pa_type_2g = map->pa_type; efuse->pa_type_5g = map->pa_type; @@ -104,24 +106,6 @@ static void rtw8822b_phy_set_param(struct rtw_dev *rtwdev) rtw_phy_init(rtwdev); rtw8822b_phy_rfe_init(rtwdev); - - /* wifi path controller */ - rtw_write32_mask(rtwdev, 0x70, 0x4000000, 1); - /* BB control */ - rtw_write32_mask(rtwdev, 0x4c, 0x01800000, 0x2); - /* antenna mux switch */ - rtw_write8(rtwdev, 0x974, 0xff); - rtw_write32_mask(rtwdev, 0x1990, 0x300, 0); - rtw_write32_mask(rtwdev, 0xcbc, 0x80000, 0x0); - /* SW control */ - rtw_write8(rtwdev, 0xcb4, 0x77); - /* switch to WL side controller and gnt_wl gnt_bt debug signal */ - rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e); - /* gnt_wl = 1, gnt_bt = 0 */ - rtw_write32(rtwdev, 0x1704, 0x7700); - rtw_write32(rtwdev, 0x1700, 0xc00f0038); - /* switch for WL 2G */ - rtw_write8(rtwdev, 0xcbd, 0x2); } #define WLAN_SLOT_TIME 0x09 @@ -960,6 +944,7 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev) u32 cck_enable; u32 cck_fa_cnt; u32 ofdm_fa_cnt; + u32 crc32_cnt; cck_enable = rtw_read32(rtwdev, 0x808) & BIT(28); cck_fa_cnt = rtw_read16(rtwdev, 0xa5c); @@ -970,6 +955,19 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev) dm_info->total_fa_cnt = ofdm_fa_cnt; dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0; + crc32_cnt = rtw_read32(rtwdev, 0xf04); + dm_info->cck_ok_cnt = crc32_cnt & 0xffff; + dm_info->cck_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0xf14); + dm_info->ofdm_ok_cnt = crc32_cnt & 0xffff; + dm_info->ofdm_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0xf10); + dm_info->ht_ok_cnt = crc32_cnt & 0xffff; + dm_info->ht_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0xf0c); + dm_info->vht_ok_cnt = crc32_cnt & 0xffff; + dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + rtw_write32_set(rtwdev, 0x9a4, BIT(17)); rtw_write32_clr(rtwdev, 0x9a4, BIT(17)); rtw_write32_clr(rtwdev, 0xa2c, BIT(15)); @@ -1003,6 +1001,254 @@ static void rtw8822b_do_iqk(struct rtw_dev *rtwdev) counter, reload, ++do_iqk_cnt, iqk_fail_mask); } +static void rtw8822b_coex_cfg_init(struct rtw_dev *rtwdev) +{ + /* enable TBTT nterrupt */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + + /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ + rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); + /* wl tx signal to PTA not case EDCCA */ + rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN); + /* GNT_BT=1 while select both */ + rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); +} + +static void rtw8822b_coex_cfg_ant_switch(struct rtw_dev *rtwdev, + u8 ctrl_type, u8 pos_type) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + bool polarity_inverse; + u8 regval = 0; + + if (((ctrl_type << 8) + pos_type) == coex_dm->cur_switch_status) + return; + + coex_dm->cur_switch_status = (ctrl_type << 8) + pos_type; + + if (coex_rfe->ant_switch_diversity && + ctrl_type == COEX_SWITCH_CTRL_BY_BBSW) + ctrl_type = COEX_SWITCH_CTRL_BY_ANTDIV; + + polarity_inverse = (coex_rfe->ant_switch_polarity == 1); + + switch (ctrl_type) { + default: + case COEX_SWITCH_CTRL_BY_BBSW: + /* 0x4c[23] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0); + /* 0x4c[24] = 1 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1); + /* BB SW, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */ + rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x77); + + if (pos_type == COEX_SWITCH_TO_WLG_BT) { + if (coex_rfe->rfe_module_type != 0x4 && + coex_rfe->rfe_module_type != 0x2) + regval = 0x3; + else + regval = (!polarity_inverse ? 0x2 : 0x1); + } else if (pos_type == COEX_SWITCH_TO_WLG) { + regval = (!polarity_inverse ? 0x2 : 0x1); + } else { + regval = (!polarity_inverse ? 0x1 : 0x2); + } + + rtw_write8_mask(rtwdev, REG_RFE_INV8, BIT_MASK_RFE_INV89, regval); + break; + case COEX_SWITCH_CTRL_BY_PTA: + /* 0x4c[23] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0); + /* 0x4c[24] = 1 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1); + /* PTA, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */ + rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x66); + + regval = (!polarity_inverse ? 0x2 : 0x1); + rtw_write8_mask(rtwdev, REG_RFE_INV8, BIT_MASK_RFE_INV89, regval); + break; + case COEX_SWITCH_CTRL_BY_ANTDIV: + /* 0x4c[23] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0); + /* 0x4c[24] = 1 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1); + rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89, 0x88); + break; + case COEX_SWITCH_CTRL_BY_MAC: + /* 0x4c[23] = 1 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x1); + + regval = (!polarity_inverse ? 0x0 : 0x1); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1, BIT_SW_DPDT_SEL_DATA, regval); + break; + case COEX_SWITCH_CTRL_BY_FW: + /* 0x4c[23] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0); + /* 0x4c[24] = 1 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x1); + break; + case COEX_SWITCH_CTRL_BY_BT: + /* 0x4c[23] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 2, BIT_DPDT_SEL_EN >> 16, 0x0); + /* 0x4c[24] = 0 */ + rtw_write8_mask(rtwdev, REG_LED_CFG + 3, BIT_DPDT_WL_SEL >> 24, 0x0); + break; + } +} + +static void rtw8822b_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) +{ +} + +static void rtw8822b_coex_cfg_gnt_debug(struct rtw_dev *rtwdev) +{ + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT_BTGP_SPI_EN >> 16, 0); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT_BTGP_JTAG_EN >> 24, 0); + rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT_FSPI_EN >> 16, 0); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 1, BIT_LED1DIS >> 8, 0); + rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT_DBG_GNT_WL_BT >> 24, 0); +} + +static void rtw8822b_coex_cfg_rfe_type(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + struct rtw_efuse *efuse = &rtwdev->efuse; + bool is_ext_fem = false; + + coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option; + coex_rfe->ant_switch_polarity = 0; + coex_rfe->ant_switch_diversity = false; + if (coex_rfe->rfe_module_type == 0x12 || + coex_rfe->rfe_module_type == 0x15 || + coex_rfe->rfe_module_type == 0x16) + coex_rfe->ant_switch_exist = false; + else + coex_rfe->ant_switch_exist = true; + + if (coex_rfe->rfe_module_type == 2 || + coex_rfe->rfe_module_type == 4) { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_EXTFEM, true); + is_ext_fem = true; + } else { + rtw_coex_write_scbd(rtwdev, COEX_SCBD_EXTFEM, false); + } + + coex_rfe->wlg_at_btg = false; + + if (efuse->share_ant && + coex_rfe->ant_switch_exist && !is_ext_fem) + coex_rfe->ant_switch_with_bt = true; + else + coex_rfe->ant_switch_with_bt = false; + + /* Ext switch buffer mux */ + rtw_write8(rtwdev, REG_RFE_CTRL_E, 0xff); + rtw_write8_mask(rtwdev, REG_RFESEL_CTRL + 1, 0x3, 0x0); + rtw_write8_mask(rtwdev, REG_RFE_INV16, BIT_RFE_BUF_EN, 0x0); + + /* Disable LTE Coex Function in WiFi side */ + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0); + + /* BTC_CTT_WL_VS_LTE */ + rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff); + + /* BTC_CTT_BT_VS_LTE */ + rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff); +} + +static void rtw8822b_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + static const u16 reg_addr[] = {0xc58, 0xe58}; + static const u8 wl_tx_power[] = {0xd8, 0xd4, 0xd0, 0xcc, 0xc8}; + u8 i, pwr; + + if (wl_pwr == coex_dm->cur_wl_pwr_lvl) + return; + + coex_dm->cur_wl_pwr_lvl = wl_pwr; + + if (coex_dm->cur_wl_pwr_lvl >= ARRAY_SIZE(wl_tx_power)) + coex_dm->cur_wl_pwr_lvl = ARRAY_SIZE(wl_tx_power) - 1; + + pwr = wl_tx_power[coex_dm->cur_wl_pwr_lvl]; + + for (i = 0; i < ARRAY_SIZE(reg_addr); i++) + rtw_write8_mask(rtwdev, reg_addr[i], 0xff, pwr); +} + +static void rtw8822b_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + /* WL Rx Low gain on */ + static const u32 wl_rx_low_gain_on[] = { + 0xff000003, 0xbd120003, 0xbe100003, 0xbf080003, 0xbf060003, + 0xbf050003, 0xbc140003, 0xbb160003, 0xba180003, 0xb91a0003, + 0xb81c0003, 0xb71e0003, 0xb4200003, 0xb5220003, 0xb4240003, + 0xb3260003, 0xb2280003, 0xb12a0003, 0xb02c0003, 0xaf2e0003, + 0xae300003, 0xad320003, 0xac340003, 0xab360003, 0x8d380003, + 0x8c3a0003, 0x8b3c0003, 0x8a3e0003, 0x6e400003, 0x6d420003, + 0x6c440003, 0x6b460003, 0x6a480003, 0x694a0003, 0x684c0003, + 0x674e0003, 0x66500003, 0x65520003, 0x64540003, 0x64560003, + 0x007e0403 + }; + + /* WL Rx Low gain off */ + static const u32 wl_rx_low_gain_off[] = { + 0xff000003, 0xf4120003, 0xf5100003, 0xf60e0003, 0xf70c0003, + 0xf80a0003, 0xf3140003, 0xf2160003, 0xf1180003, 0xf01a0003, + 0xef1c0003, 0xee1e0003, 0xed200003, 0xec220003, 0xeb240003, + 0xea260003, 0xe9280003, 0xe82a0003, 0xe72c0003, 0xe62e0003, + 0xe5300003, 0xc8320003, 0xc7340003, 0xc6360003, 0xc5380003, + 0xc43a0003, 0xc33c0003, 0xc23e0003, 0xc1400003, 0xc0420003, + 0xa5440003, 0xa4460003, 0xa3480003, 0xa24a0003, 0xa14c0003, + 0x834e0003, 0x82500003, 0x81520003, 0x80540003, 0x65560003, + 0x007e0403 + }; + u8 i; + + if (low_gain == coex_dm->cur_wl_rx_low_gain_en) + return; + + coex_dm->cur_wl_rx_low_gain_en = low_gain; + + if (coex_dm->cur_wl_rx_low_gain_en) { + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++) + rtw_write32(rtwdev, REG_RX_GAIN_EN, wl_rx_low_gain_on[i]); + + /* set Rx filter corner RCK offset */ + rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, 0x2, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, 0x3f, 0x3f); + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x1); + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x3f); + } else { + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++) + rtw_write32(rtwdev, 0x81c, wl_rx_low_gain_off[i]); + + /* set Rx filter corner RCK offset */ + rtw_write_rf(rtwdev, RF_PATH_A, RF_RCK, 0x3f, 0x4); + rtw_write_rf(rtwdev, RF_PATH_A, RF_RCKD, 0x2, 0x0); + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCK, 0x3f, 0x4); + rtw_write_rf(rtwdev, RF_PATH_B, RF_RCKD, 0x2, 0x0); + } +} + static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, @@ -1549,8 +1795,160 @@ static struct rtw_chip_ops rtw8822b_ops = { .cfg_ldo25 = rtw8822b_cfg_ldo25, .false_alarm_statistics = rtw8822b_false_alarm_statistics, .do_iqk = rtw8822b_do_iqk, + + .coex_set_init = rtw8822b_coex_cfg_init, + .coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch, + .coex_set_gnt_fix = rtw8822b_coex_cfg_gnt_fix, + .coex_set_gnt_debug = rtw8822b_coex_cfg_gnt_debug, + .coex_set_rfe_type = rtw8822b_coex_cfg_rfe_type, + .coex_set_wl_tx_power = rtw8822b_coex_cfg_wl_tx_power, + .coex_set_wl_rx_gain = rtw8822b_coex_cfg_wl_rx_gain, +}; + +/* Shared-Antenna Coex Table */ +static const struct coex_table_para table_sant_8822b[] = { + {0xffffffff, 0xffffffff}, /* case-0 */ + {0x55555555, 0x55555555}, + {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ + {0x6a5a6a5a, 0xaaaaaaaa}, + {0x6a5a56aa, 0x6a5a56aa}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-10 */ + {0x66555555, 0xfafafafa}, + {0x66555555, 0x6a5a5aaa}, + {0x66555555, 0x5aaa5aaa}, + {0x66555555, 0xaaaa5aaa}, + {0x66555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x6afa5afa}, + {0xaaffffaa, 0xfafafafa}, + {0xaa5555aa, 0x5a5a5a5a}, + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x6a5a5a5a}, + {0xffffffff, 0x55555555}, + {0xffffffff, 0x6a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, + {0x55555555, 0x6a5a6a5a}, + {0x66556655, 0x66556655} +}; + +/* Non-Shared-Antenna Coex Table */ +static const struct coex_table_para table_nsant_8822b[] = { + {0xffffffff, 0xffffffff}, /* case-100 */ + {0x55555555, 0x55555555}, + {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-105 */ + {0x5afa5afa, 0x5afa5afa}, + {0x55555555, 0xfafafafa}, + {0x66555555, 0xfafafafa}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-110 */ + {0x66555555, 0xaaaaaaaa}, + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, + {0xaaffffaa, 0xfafafafa}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, + {0xffffffff, 0x5afa5afa}, + {0xffffffff, 0xaaaaaaaa}, /* case-120 */ + {0x55ff55ff, 0x5afa5afa}, + {0x55ff55ff, 0xaaaaaaaa}, + {0x55ff55ff, 0x55ff55ff} }; +/* Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_sant_8822b[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */ + { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */ + { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ + { {0x51, 0x45, 0x03, 0x10, 0x10} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */ + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, + { {0x65, 0x10, 0x03, 0x11, 0x11} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} } +}; + +/* Non-Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_nsant_8822b[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */ + { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */ + { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */ + { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */ +}; + +/* rssi in percentage % (dbm = % - 100) */ +static const u8 wl_rssi_step_8822b[] = {60, 50, 44, 30}; +static const u8 bt_rssi_step_8822b[] = {30, 30, 30, 30}; +static const struct coex_5g_afh_map afh_5g_8822b[] = { {0, 0, 0} }; + +/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */ +static const struct coex_rf_para rf_para_tx_8822b[] = { + {0, 0, false, 7}, /* for normal */ + {0, 16, false, 7}, /* for WL-CPT */ + {4, 0, true, 1}, + {3, 6, true, 1}, + {2, 9, true, 1}, + {1, 13, true, 1} +}; + +static const struct coex_rf_para rf_para_rx_8822b[] = { + {0, 0, false, 7}, /* for normal */ + {0, 16, false, 7}, /* for WL-CPT */ + {4, 0, true, 1}, + {3, 6, true, 1}, + {2, 9, true, 1}, + {1, 13, true, 1} +}; + +static_assert(ARRAY_SIZE(rf_para_tx_8822b) == ARRAY_SIZE(rf_para_rx_8822b)); + struct rtw_chip_info rtw8822b_hw_spec = { .ops = &rtw8822b_ops, .id = RTW_CHIP_TYPE_8822B, @@ -1588,6 +1986,32 @@ struct rtw_chip_info rtw8822b_hw_spec = { .rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl}, .rfe_defs = rtw8822b_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs), + + .coex_para_ver = 0x19062706, + .bt_desired_ver = 0x6, + .scbd_support = true, + .new_scbd10_def = false, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_RATIO, + .ant_isolation = 15, + .rssi_tolerance = 2, + .wl_rssi_step = wl_rssi_step_8822b, + .bt_rssi_step = bt_rssi_step_8822b, + .table_sant_num = ARRAY_SIZE(table_sant_8822b), + .table_sant = table_sant_8822b, + .table_nsant_num = ARRAY_SIZE(table_nsant_8822b), + .table_nsant = table_nsant_8822b, + .tdma_sant_num = ARRAY_SIZE(tdma_sant_8822b), + .tdma_sant = tdma_sant_8822b, + .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8822b), + .tdma_nsant = tdma_nsant_8822b, + .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8822b), + .wl_rf_para_tx = rf_para_tx_8822b, + .wl_rf_para_rx = rf_para_rx_8822b, + .bt_afh_span_bw20 = 0x24, + .bt_afh_span_bw40 = 0x36, + .afh_5g_num = ARRAY_SIZE(afh_5g_8822b), + .afh_5g = afh_5g_8822b, }; EXPORT_SYMBOL(rtw8822b_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index f6214ff20337..207f64cc3e55 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3,6 +3,7 @@ */ #include "main.h" +#include "coex.h" #include "fw.h" #include "tx.h" #include "rx.h" @@ -31,6 +32,7 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) map = (struct rtw8822c_efuse *)log_map; efuse->rfe_option = map->rfe_option; + efuse->rf_board_option = map->rf_board_option; efuse->crystal_cap = map->xtal_k; efuse->channel_plan = map->channel_plan; efuse->country_code[0] = map->country_code[0]; @@ -1041,12 +1043,6 @@ static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev) dm_info->cck_gi_l_bnd = ((cck_gi_l_bnd_msb << 4) | (cck_gi_l_bnd_lsb)); rtw8822c_rf_init(rtwdev); - /* wifi path controller */ - rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e); - rtw_write32_mask(rtwdev, 0x1704, 0xffffffff, 0x7700); - rtw_write32_mask(rtwdev, 0x1700, 0xffffffff, 0xc00f0038); - rtw_write32_mask(rtwdev, 0x6c0, 0xffffffff, 0xaaaaaaaa); - rtw_write32_mask(rtwdev, 0x6c4, 0xffffffff, 0xaaaaaaaa); } #define WLAN_TXQ_RPT_EN 0x1F @@ -1817,6 +1813,7 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev) struct rtw_dm_info *dm_info = &rtwdev->dm_info; u32 cck_enable; u32 cck_fa_cnt; + u32 crc32_cnt; u32 ofdm_fa_cnt; u32 ofdm_fa_cnt1, ofdm_fa_cnt2, ofdm_fa_cnt3, ofdm_fa_cnt4, ofdm_fa_cnt5; u16 parity_fail, rate_illegal, crc8_fail, mcs_fail, sb_search_fail, @@ -1848,6 +1845,19 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev) dm_info->total_fa_cnt = ofdm_fa_cnt; dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0; + crc32_cnt = rtw_read32(rtwdev, 0x2c04); + dm_info->cck_ok_cnt = crc32_cnt & 0xffff; + dm_info->cck_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0x2c14); + dm_info->ofdm_ok_cnt = crc32_cnt & 0xffff; + dm_info->ofdm_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0x2c10); + dm_info->ht_ok_cnt = crc32_cnt & 0xffff; + dm_info->ht_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + crc32_cnt = rtw_read32(rtwdev, 0x2c0c); + dm_info->vht_ok_cnt = crc32_cnt & 0xffff; + dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16; + rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 0); rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2); rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0); @@ -1864,6 +1874,161 @@ static void rtw8822c_do_iqk(struct rtw_dev *rtwdev) { } +/* for coex */ +static void rtw8822c_coex_cfg_init(struct rtw_dev *rtwdev) +{ + /* enable TBTT nterrupt */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + + /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ + rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); + /* wl tx signal to PTA not case EDCCA */ + rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN); + /* GNT_BT=1 while select both */ + rtw_write8_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY); + /* BT_CCA = ~GNT_WL_BB, (not or GNT_BT_BB, LTE_Rx */ + rtw_write8_clr(rtwdev, REG_DUMMY_PAGE4_V1, BIT_BTCCA_CTRL); + + /* to avoid RF parameter error */ + rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, 0x40000); +} + +static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + u32 rf_0x1; + + if (coex_stat->gnt_workaround_state == coex_stat->wl_coex_mode) + return; + + coex_stat->gnt_workaround_state = coex_stat->wl_coex_mode; + + if ((coex_stat->kt_ver == 0 && coex->under_5g) || coex->freerun) + rf_0x1 = 0x40021; + else + rf_0x1 = 0x40000; + + /* BT at S1 for Shared-Ant */ + if (efuse->share_ant) + rf_0x1 |= BIT(13); + + rtw_write_rf(rtwdev, RF_PATH_B, 0x1, 0xfffff, rf_0x1); + + /* WL-S0 2G RF TRX cannot be masked by GNT_BT + * enable "WLS0 BB chage RF mode if GNT_BT = 1" for shared-antenna type + * disable:0x1860[3] = 1, enable:0x1860[3] = 0 + * + * enable "DAC off if GNT_WL = 0" for non-shared-antenna + * disable 0x1c30[22] = 0, + * enable: 0x1c30[22] = 1, 0x1c38[12] = 0, 0x1c38[28] = 1 + * + * disable WL-S1 BB chage RF mode if GNT_BT + * since RF TRx mask can do it + */ + rtw_write8_mask(rtwdev, 0x1c32, BIT(6), 1); + rtw_write8_mask(rtwdev, 0x1c39, BIT(4), 0); + rtw_write8_mask(rtwdev, 0x1c3b, BIT(4), 1); + rtw_write8_mask(rtwdev, 0x4160, BIT(3), 1); + + /* disable WL-S0 BB chage RF mode if wifi is at 5G, + * or antenna path is separated + */ + if (coex_stat->wl_coex_mode == COEX_WLINK_5G || + coex->under_5g || !efuse->share_ant) { + if (coex_stat->kt_ver >= 3) { + rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0); + rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 1); + } else { + rtw_write8_mask(rtwdev, 0x1860, BIT(3), 1); + } + } else { + /* shared-antenna */ + rtw_write8_mask(rtwdev, 0x1860, BIT(3), 0); + if (coex_stat->kt_ver >= 3) + rtw_write8_mask(rtwdev, 0x1ca7, BIT(3), 0); + } +} + +static void rtw8822c_coex_cfg_gnt_debug(struct rtw_dev *rtwdev) +{ + rtw_write8_mask(rtwdev, 0x66, BIT(4), 0); + rtw_write8_mask(rtwdev, 0x67, BIT(0), 0); + rtw_write8_mask(rtwdev, 0x42, BIT(3), 0); + rtw_write8_mask(rtwdev, 0x65, BIT(7), 0); + rtw_write8_mask(rtwdev, 0x73, BIT(3), 0); +} + +static void rtw8822c_coex_cfg_rfe_type(struct rtw_dev *rtwdev) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + struct rtw_efuse *efuse = &rtwdev->efuse; + + coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option; + coex_rfe->ant_switch_polarity = 0; + coex_rfe->ant_switch_exist = false; + coex_rfe->ant_switch_with_bt = false; + coex_rfe->ant_switch_diversity = false; + + if (efuse->share_ant) + coex_rfe->wlg_at_btg = true; + else + coex_rfe->wlg_at_btg = false; + + /* disable LTE coex in wifi side */ + rtw_coex_write_indirect_reg(rtwdev, 0x38, BIT_LTE_COEX_EN, 0x0); + rtw_coex_write_indirect_reg(rtwdev, 0xa0, MASKLWORD, 0xffff); + rtw_coex_write_indirect_reg(rtwdev, 0xa4, MASKLWORD, 0xffff); +} + +static void rtw8822c_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + + if (wl_pwr == coex_dm->cur_wl_pwr_lvl) + return; + + coex_dm->cur_wl_pwr_lvl = wl_pwr; +} + +static void rtw8822c_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + + if (low_gain == coex_dm->cur_wl_rx_low_gain_en) + return; + + coex_dm->cur_wl_rx_low_gain_en = low_gain; + + if (coex_dm->cur_wl_rx_low_gain_en) { + /* set Rx filter corner RCK offset */ + rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x22); + rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x36); + rtw_write_rf(rtwdev, RF_PATH_B, 0xde, 0xfffff, 0x22); + rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x36); + } else { + /* set Rx filter corner RCK offset */ + rtw_write_rf(rtwdev, RF_PATH_A, 0xde, 0xfffff, 0x20); + rtw_write_rf(rtwdev, RF_PATH_A, 0x1d, 0xfffff, 0x0); + rtw_write_rf(rtwdev, RF_PATH_B, 0x1d, 0xfffff, 0x0); + } +} + static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, @@ -2232,8 +2397,160 @@ static struct rtw_chip_ops rtw8822c_ops = { .cfg_ldo25 = rtw8822c_cfg_ldo25, .false_alarm_statistics = rtw8822c_false_alarm_statistics, .do_iqk = rtw8822c_do_iqk, + + .coex_set_init = rtw8822c_coex_cfg_init, + .coex_set_ant_switch = NULL, + .coex_set_gnt_fix = rtw8822c_coex_cfg_gnt_fix, + .coex_set_gnt_debug = rtw8822c_coex_cfg_gnt_debug, + .coex_set_rfe_type = rtw8822c_coex_cfg_rfe_type, + .coex_set_wl_tx_power = rtw8822c_coex_cfg_wl_tx_power, + .coex_set_wl_rx_gain = rtw8822c_coex_cfg_wl_rx_gain, +}; + +/* Shared-Antenna Coex Table */ +static const struct coex_table_para table_sant_8822c[] = { + {0xffffffff, 0xffffffff}, /* case-0 */ + {0x55555555, 0x55555555}, + {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ + {0x6a5a6a5a, 0xaaaaaaaa}, + {0x6a5a56aa, 0x6a5a56aa}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-10 */ + {0x66555555, 0xfafafafa}, + {0x66555555, 0x6a5a5aaa}, + {0x66555555, 0x5aaa5aaa}, + {0x66555555, 0xaaaa5aaa}, + {0x66555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x6afa5afa}, + {0xaaffffaa, 0xfafafafa}, + {0xaa5555aa, 0x5a5a5a5a}, + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x6a5a5a5a}, + {0xffffffff, 0x55555555}, + {0xffffffff, 0x6a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, + {0x55555555, 0x6a5a6a5a}, + {0x66556655, 0x66556655} +}; + +/* Non-Shared-Antenna Coex Table */ +static const struct coex_table_para table_nsant_8822c[] = { + {0xffffffff, 0xffffffff}, /* case-100 */ + {0x55555555, 0x55555555}, + {0x66555555, 0x66555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-105 */ + {0x5afa5afa, 0x5afa5afa}, + {0x55555555, 0xfafafafa}, + {0x66555555, 0xfafafafa}, + {0x66555555, 0x5a5a5a5a}, + {0x66555555, 0x6a5a5a5a}, /* case-110 */ + {0x66555555, 0xaaaaaaaa}, + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, + {0xaaffffaa, 0xfafafafa}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, + {0xffffffff, 0x5afa5afa}, + {0xffffffff, 0xaaaaaaaa},/* case-120 */ + {0x55ff55ff, 0x5afa5afa}, + {0x55ff55ff, 0xaaaaaaaa}, + {0x55ff55ff, 0x55ff55ff} +}; + +/* Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_sant_8822c[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */ + { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */ + { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */ + { {0x51, 0x45, 0x03, 0x10, 0x10} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */ + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, + { {0x65, 0x10, 0x03, 0x11, 0x11} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} } }; +/* Non-Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_nsant_8822c[] = { + { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-100 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */ + { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */ + { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */ + { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} } /* case-120 */ +}; + +/* rssi in percentage % (dbm = % - 100) */ +static const u8 wl_rssi_step_8822c[] = {60, 50, 44, 30}; +static const u8 bt_rssi_step_8822c[] = {8, 15, 20, 25}; +static const struct coex_5g_afh_map afh_5g_8822c[] = { {0, 0, 0} }; + +/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */ +static const struct coex_rf_para rf_para_tx_8822c[] = { + {0, 0, false, 7}, /* for normal */ + {0, 16, false, 7}, /* for WL-CPT */ + {8, 17, true, 4}, + {7, 18, true, 4}, + {6, 19, true, 4}, + {5, 20, true, 4} +}; + +static const struct coex_rf_para rf_para_rx_8822c[] = { + {0, 0, false, 7}, /* for normal */ + {0, 16, false, 7}, /* for WL-CPT */ + {3, 24, true, 5}, + {2, 26, true, 5}, + {1, 27, true, 5}, + {0, 28, true, 5} +}; + +static_assert(ARRAY_SIZE(rf_para_tx_8822c) == ARRAY_SIZE(rf_para_rx_8822c)); + struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, @@ -2272,6 +2589,32 @@ struct rtw_chip_info rtw8822c_hw_spec = { .rf_tbl = {&rtw8822c_rf_a_tbl, &rtw8822c_rf_b_tbl}, .rfe_defs = rtw8822c_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs), + + .coex_para_ver = 0x19062706, + .bt_desired_ver = 0x6, + .scbd_support = true, + .new_scbd10_def = true, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_DBM, + .ant_isolation = 15, + .rssi_tolerance = 2, + .wl_rssi_step = wl_rssi_step_8822c, + .bt_rssi_step = bt_rssi_step_8822c, + .table_sant_num = ARRAY_SIZE(table_sant_8822c), + .table_sant = table_sant_8822c, + .table_nsant_num = ARRAY_SIZE(table_nsant_8822c), + .table_nsant = table_nsant_8822c, + .tdma_sant_num = ARRAY_SIZE(tdma_sant_8822c), + .tdma_sant = tdma_sant_8822c, + .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8822c), + .tdma_nsant = tdma_nsant_8822c, + .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8822c), + .wl_rf_para_tx = rf_para_tx_8822c, + .wl_rf_para_rx = rf_para_rx_8822c, + .bt_afh_span_bw20 = 0x24, + .bt_afh_span_bw40 = 0x36, + .afh_5g_num = ARRAY_SIZE(afh_5g_8822c), + .afh_5g = afh_5g_8822c, }; EXPORT_SYMBOL(rtw8822c_hw_spec); -- GitLab From 49a52d05a3c7252357ab6b1e49c17ed0c02cf80f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 1 Aug 2019 20:20:59 -0500 Subject: [PATCH 2077/7155] rtlwifi: rtl8192ce: Remove unused GET_XXX and SET_XXX As the first step in converting from macros that get/set information in the RX and TX descriptors, unused macros are being removed. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192ce/trx.h | 330 +----------------- 1 file changed, 4 insertions(+), 326 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index fb1d4444a52f..37e40f44c347 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -52,31 +52,9 @@ SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) #define SET_TX_DESC_LINIP(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) #define SET_TX_DESC_OWN(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) #define GET_TX_DESC_OWN(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 31, 1) @@ -84,136 +62,33 @@ SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) #define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) -#define SET_TX_DESC_BK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 24, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) + #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) + #define SET_TX_DESC_SEQ(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) #define SET_TX_DESC_PKT_ID(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) -#define GET_TX_DESC_PKT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) - #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) #define SET_TX_DESC_QOS(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ @@ -222,18 +97,8 @@ SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ @@ -245,158 +110,29 @@ #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) - #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) + #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) -#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) -#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) -#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) -#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) -#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) -#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) -#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) #define GET_RX_DESC_PKT_LEN(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 0, 14) @@ -406,22 +142,12 @@ SHIFT_AND_MASK_LE(__pdesc, 15, 1) #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 23, 1) #define GET_RX_DESC_SHIFT(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 24, 2) #define GET_RX_DESC_PHYST(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 26, 1) #define GET_RX_DESC_SWDEC(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) #define GET_RX_DESC_OWN(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc, 31, 1) @@ -432,44 +158,10 @@ #define SET_RX_DESC_OWN(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) -#define GET_RX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_RX_DESC_TID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) -#define GET_RX_DESC_HWRSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) #define GET_RX_DESC_PAGGR(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) #define GET_RX_DESC_FAGGR(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) -#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) -#define GET_RX_DESC_NEXT_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) -#define GET_RX_DESC_RSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) #define GET_RX_DESC_RXMCS(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) @@ -479,29 +171,15 @@ SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) #define GET_RX_DESC_BW(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) -#define GET_RX_DESC_HWPC_ERR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) -#define GET_RX_DESC_HWPC_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) -#define GET_RX_DESC_IV0(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) - -#define GET_RX_DESC_IV1(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) + #define GET_RX_DESC_TSFL(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) #define GET_RX_DESC_BUFF_ADDR(__pdesc) \ SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) -- GitLab From a246b92914339e539b5fd27b347601fc9f0e8460 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 1 Aug 2019 20:21:00 -0500 Subject: [PATCH 2078/7155] rtlwifi: rtl8192ce: Replace local bit manipulation macros This driver uses a set of local macros to manipulate the RX and TX descriptors, which are all little-endian quantities. These macros are replaced by the bitfield macros le32p_replace_bits() and le32_get_bits(). In several places, the macros operated on an entire 32-bit word. In these cases, a direct read or replacement is used. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192ce/trx.h | 146 ++++++++---------- 1 file changed, 62 insertions(+), 84 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index 37e40f44c347..f4dbeeda062f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -14,172 +14,150 @@ #define USB_HWDESC_HEADER_LEN 32 #define CRCLENGTH 4 -/* Define a macro that takes a le32 word, converts it to host ordering, - * right shifts by a specified count, creates a mask of the specified - * bit count, and extracts that number of bits. - */ - -#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__mask)) - -/* Define a macro that clears a bit field in an le32 word and - * sets the specified value into that bit field. The resulting - * value remains in le32 ordering; however, it is properly converted - * to host ordering for the clear and set operations before conversion - * back to le32. - */ - -#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \ - (*(__le32 *)(__pdesc) = \ - (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \ - (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \ - (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); - /* macros to read/write various fields in RX or TX descriptors */ #define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)) #define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)) #define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)) #define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)) #define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)) #define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)) #define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)) #define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) #define GET_TX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(31)) #define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(4, 0)) #define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(5)) #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(7)) #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)) #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)) #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)) #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)) #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)) #define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)) #define SET_TX_DESC_PKT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(31, 28)) #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)) #define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)) #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(7)) #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)) #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)) #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)) #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)) #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)) #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)) #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)) #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)) #define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)) #define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)) #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)) #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)) #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)) #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)) #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)) #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) + le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)) #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)) #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) + *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val) #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 32))) #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) + *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val) #define GET_RX_DESC_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 14) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)) #define GET_RX_DESC_CRC32(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 14, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(14)) #define GET_RX_DESC_ICV(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 15, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(15)) #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 4) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)) #define GET_RX_DESC_SHIFT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 2) + le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)) #define GET_RX_DESC_PHYST(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(26)) #define GET_RX_DESC_SWDEC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(27)) #define GET_RX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) + le32_get_bits(*((__le32 *)__pdesc), BIT(31)) #define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)) #define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)) #define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) #define GET_RX_DESC_PAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)) #define GET_RX_DESC_FAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) + le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)) #define GET_RX_DESC_RXMCS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) + le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)) #define GET_RX_DESC_RXHT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)) #define GET_RX_DESC_SPLCP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)) #define GET_RX_DESC_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) + le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)) #define GET_RX_DESC_TSFL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 20))) #define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) + le32_to_cpu(*((__le32 *)(__pdesc + 24))) #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) + *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val) #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) -- GitLab From 98fd8db59a007c05f30f911180f745b243d56746 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 1 Aug 2019 20:21:01 -0500 Subject: [PATCH 2079/7155] rtlwifi: rtl8192ce: Convert macros that set descriptor As a first step in the conversion, the macros that set the RX and TX descriptors are converted to static inline routines, and the names are changed from upper to lower case. To minimize the changes in a given step, the input descriptor information is left as as a byte array (u8 *), even though it should be a little-endian word array (__le32 *). That will be changed in the next patch. Several places where checkpatch.pl complains about a space after a cast are fixed. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192ce/trx.c | 192 ++++---- .../wireless/realtek/rtlwifi/rtl8192ce/trx.h | 451 ++++++++++++------ 2 files changed, 405 insertions(+), 238 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 18a0ab59631a..7bff0825b264 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -251,8 +251,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, */ if (i == 0) pstats->signalquality = - (u8) (evm & 0xff); - pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); + (u8)(evm & 0xff); + pstats->rx_mimo_sig_qual[i] = (u8)(evm & 0xff); } } } @@ -262,10 +262,10 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, */ if (is_cck_rate) pstats->signalstrength = - (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); + (u8)(_rtl92ce_signal_scale_mapping(hw, pwdb_all)); else if (rf_rx_num != 0) pstats->signalstrength = - (u8) (_rtl92ce_signal_scale_mapping + (u8)(_rtl92ce_signal_scale_mapping (hw, total_rssi /= rf_rx_num)); } @@ -322,24 +322,24 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rx_fwinfo_92c *p_drvinfo; struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; struct ieee80211_hdr *hdr; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); + u32 phystatus = get_rx_desc_physt(p_desc); - stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); - stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + stats->length = (u16)get_rx_desc_pkt_len(p_desc); + stats->rx_drvinfo_size = (u8)get_rx_desc_drv_info_size(p_desc) * RX_DRV_INFO_SIZE_UNIT; - stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); - stats->icv = (u16) GET_RX_DESC_ICV(pdesc); - stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->rx_bufshift = (u8)(get_rx_desc_shift(p_desc) & 0x03); + stats->icv = (u16)get_rx_desc_icv(p_desc); + stats->crc = (u16)get_rx_desc_crc32(p_desc); stats->hwerror = (stats->crc | stats->icv); - stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); - stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); - stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); - stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) - && (GET_RX_DESC_FAGGR(pdesc) == 1)); - stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); - stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + stats->decrypted = !get_rx_desc_swdec(p_desc); + stats->rate = (u8)get_rx_desc_rxmcs(p_desc); + stats->shortpreamble = (u16)get_rx_desc_splcp(p_desc); + stats->isampdu = (bool)(get_rx_desc_paggr(p_desc) == 1); + stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(p_desc) == 1) && + (get_rx_desc_faggr(p_desc) == 1)); + stats->timestamp_low = get_rx_desc_tsfl(p_desc); + stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(p_desc); + stats->is_ht = (bool)get_rx_desc_rxht(p_desc); stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); @@ -454,57 +454,57 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, lastseg = true; } if (firstseg) { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); + set_tx_desc_tx_rate(pdesc, tcb_desc->hw_rate); if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + set_tx_desc_data_shortgi(pdesc, 1); if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_BREAK(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + set_tx_desc_agg_break(pdesc, 1); + set_tx_desc_max_agg_num(pdesc, 0x14); } - SET_TX_DESC_SEQ(pdesc, seq_number); + set_tx_desc_seq(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && + set_tx_desc_rts_enable(pdesc, ((tcb_desc->rts_enable && !tcb_desc-> cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, + set_tx_desc_hw_rts_enable(pdesc, ((tcb_desc->rts_enable || tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + set_tx_desc_cts2self(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + set_tx_desc_rts_stbc(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, + set_tx_desc_rts_rate(pdesc, tcb_desc->rts_rate); + set_tx_desc_rts_bw(pdesc, 0); + set_tx_desc_rts_sc(pdesc, tcb_desc->rts_sc); + set_tx_desc_rts_short(pdesc, ((tcb_desc->rts_rate <= DESC_RATE54M) ? (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (bw_40) { if (tcb_desc->packet_bw) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + set_tx_desc_data_bw(pdesc, 1); + set_tx_desc_tx_sub_carrier(pdesc, 3); } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, + set_tx_desc_data_bw(pdesc, 0); + set_tx_desc_tx_sub_carrier(pdesc, mac->cur_40_prime_sc); } } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + set_tx_desc_data_bw(pdesc, 0); + set_tx_desc_tx_sub_carrier(pdesc, 0); } - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + set_tx_desc_linip(pdesc, 0); + set_tx_desc_pkt_size(pdesc, (u16)skb->len); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + set_tx_desc_ampdu_density(pdesc, ampdu_density); } if (info->control.hw_key) { @@ -515,65 +515,65 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + set_tx_desc_sec_type(pdesc, 0x1); break; case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + set_tx_desc_sec_type(pdesc, 0x3); break; default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + set_tx_desc_sec_type(pdesc, 0x0); break; } } - SET_TX_DESC_PKT_ID(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + set_tx_desc_pkt_id(pdesc, 0); + set_tx_desc_queue_sel(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); + set_tx_desc_data_rate_fb_limit(pdesc, 0x1F); + set_tx_desc_rts_rate_fb_limit(pdesc, 0xF); + set_tx_desc_disable_fb(pdesc, 0); + set_tx_desc_use_rate(pdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "Enable RDG function\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); + set_tx_desc_rdg_enable(pdesc, 1); + set_tx_desc_htc(pdesc, 1); } } } rcu_read_unlock(); - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + set_tx_desc_first_seg(pdesc, (firstseg ? 1 : 0)); + set_tx_desc_last_seg(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + set_tx_desc_tx_buffer_size(pdesc, (u16)skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + set_tx_desc_tx_buffer_address(pdesc, mapping); if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); + set_tx_desc_rate_id(pdesc, tcb_desc->ratr_index); + set_tx_desc_macid(pdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); + set_tx_desc_rate_id(pdesc, 0xC + tcb_desc->ratr_index); + set_tx_desc_macid(pdesc, tcb_desc->ratr_index); } if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); + set_tx_desc_hwseq_en(pdesc, 1); + set_tx_desc_pkt_id(pdesc, 8); if (!defaultadapter) - SET_TX_DESC_QOS(pdesc, 1); + set_tx_desc_qos(pdesc, 1); } - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + set_tx_desc_more_frag(pdesc, (lastseg ? 0 : 1)); if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); + set_tx_desc_bmc(pdesc, 1); } RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); @@ -602,40 +602,40 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + set_tx_desc_tx_rate(pdesc, DESC_RATE1M); - SET_TX_DESC_SEQ(pdesc, 0); + set_tx_desc_seq(pdesc, 0); - SET_TX_DESC_LINIP(pdesc, 0); + set_tx_desc_linip(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + set_tx_desc_queue_sel(pdesc, fw_queue); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); + set_tx_desc_first_seg(pdesc, 1); + set_tx_desc_last_seg(pdesc, 1); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); + set_tx_desc_tx_buffer_size(pdesc, (u16)(skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + set_tx_desc_tx_buffer_address(pdesc, mapping); - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); + set_tx_desc_rate_id(pdesc, 7); + set_tx_desc_macid(pdesc, 0); - SET_TX_DESC_OWN(pdesc, 1); + set_tx_desc_own(pdesc, 1); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); + set_tx_desc_pkt_size(pdesc, (u16)(skb->len)); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); + set_tx_desc_first_seg(pdesc, 1); + set_tx_desc_last_seg(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, 0x20); + set_tx_desc_offset(pdesc, 0x20); - SET_TX_DESC_USE_RATE(pdesc, 1); + set_tx_desc_use_rate(pdesc, 1); if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); + set_tx_desc_hwseq_en(pdesc, 1); + set_tx_desc_pkt_id(pdesc, 8); } RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, @@ -649,10 +649,10 @@ void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, switch (desc_name) { case HW_DESC_OWN: wmb(); - SET_TX_DESC_OWN(pdesc, 1); + set_tx_desc_own(pdesc, 1); break; case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + set_tx_desc_next_desc_address(pdesc, *(u32 *)val); break; default: WARN_ONCE(true, "rtl8192ce: ERR txdesc :%d not processed\n", @@ -663,16 +663,16 @@ void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, switch (desc_name) { case HW_DESC_RXOWN: wmb(); - SET_RX_DESC_OWN(pdesc, 1); + set_rx_desc_own(pdesc, 1); break; case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); + set_rx_desc_buff_addr(pdesc, *(u32 *)val); break; case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); + set_rx_desc_pkt_len(pdesc, *(u32 *)val); break; case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); + set_rx_desc_eor(pdesc, 1); break; default: WARN_ONCE(true, "rtl8192ce: ERR rxdesc :%d not processed\n", @@ -690,10 +690,10 @@ u64 rtl92ce_get_desc(struct ieee80211_hw *hw, u8 *p_desc, if (istx) { switch (desc_name) { case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(p_desc); + ret = get_tx_desc_own(p_desc); break; case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); + ret = get_tx_desc_tx_buffer_address(p_desc); break; default: WARN_ONCE(true, "rtl8192ce: ERR txdesc :%d not processed\n", @@ -703,13 +703,13 @@ u64 rtl92ce_get_desc(struct ieee80211_hw *hw, u8 *p_desc, } else { switch (desc_name) { case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(p_desc); + ret = get_rx_desc_own(p_desc); break; case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(p_desc); + ret = get_rx_desc_pkt_len(p_desc); break; case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(p_desc); + ret = get_rx_desc_buff_addr(p_desc); break; default: WARN_ONCE(true, "rtl8192ce: ERR rxdesc :%d not processed\n", diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index f4dbeeda062f..5addfa20b2b7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -16,148 +16,315 @@ /* macros to read/write various fields in RX or TX descriptors */ -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) - -#define GET_TX_DESC_OWN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(31)) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(4, 0)) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(5)) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(7)) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)) - -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)) - -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)) -#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(31, 28)) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(7)) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)) - -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 32))) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)) -#define GET_RX_DESC_CRC32(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(14)) -#define GET_RX_DESC_ICV(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(15)) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)) -#define GET_RX_DESC_SHIFT(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)) -#define GET_RX_DESC_PHYST(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(26)) -#define GET_RX_DESC_SWDEC(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(27)) -#define GET_RX_DESC_OWN(__pdesc) \ - le32_get_bits(*((__le32 *)__pdesc), BIT(31)) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)) - -#define GET_RX_DESC_PAGGR(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)) -#define GET_RX_DESC_FAGGR(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)) -#define GET_RX_DESC_RXHT(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)) -#define GET_RX_DESC_SPLCP(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)) -#define GET_RX_DESC_BW(__pdesc) \ - le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)) - -#define GET_RX_DESC_TSFL(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 20))) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - le32_to_cpu(*((__le32 *)(__pdesc + 24))) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val) +static inline void set_tx_desc_pkt_size(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)); +} + +static inline void set_tx_desc_offset(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)); +} + +static inline void set_tx_desc_bmc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)); +} + +static inline void set_tx_desc_htc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)); +} + +static inline void set_tx_desc_last_seg(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)); +} + +static inline void set_tx_desc_first_seg(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)); +} + +static inline void set_tx_desc_linip(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)); +} + +static inline void set_tx_desc_own(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); +} + +static inline int get_tx_desc_own(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); +} + +static inline void set_tx_desc_macid(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(4, 0)); +} + +static inline void set_tx_desc_agg_break(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(5)); +} + +static inline void set_tx_desc_rdg_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(7)); +} + +static inline void set_tx_desc_queue_sel(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)); +} + +static inline void set_tx_desc_rate_id(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)); +} + +static inline void set_tx_desc_sec_type(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)); +} + +static inline void set_tx_desc_more_frag(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)); +} + +static inline void set_tx_desc_ampdu_density(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)); +} + +static inline void set_tx_desc_seq(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)); +} + +static inline void set_tx_desc_pkt_id(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(31, 28)); +} + +static inline void set_tx_desc_rts_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)); +} + +static inline void set_tx_desc_qos(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)); +} + +static inline void set_tx_desc_hwseq_en(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(7)); +} + +static inline void set_tx_desc_use_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)); +} + +static inline void set_tx_desc_disable_fb(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)); +} + +static inline void set_tx_desc_cts2self(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)); +} + +static inline void set_tx_desc_rts_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)); +} + +static inline void set_tx_desc_hw_rts_enable(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)); +} + +static inline void set_tx_desc_tx_sub_carrier(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)); +} + +static inline void set_tx_desc_data_bw(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)); +} + +static inline void set_tx_desc_rts_short(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)); +} + +static inline void set_tx_desc_rts_bw(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)); +} + +static inline void set_tx_desc_rts_sc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)); +} + +static inline void set_tx_desc_rts_stbc(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)); +} + +static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)); +} + +static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)); +} + +static inline void set_tx_desc_data_rate_fb_limit(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)); +} + +static inline void set_tx_desc_rts_rate_fb_limit(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)); +} + +static inline void set_tx_desc_max_agg_num(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)); +} + +static inline void set_tx_desc_tx_buffer_size(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)); +} + +static inline void set_tx_desc_tx_buffer_address(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val); +} + +static inline int get_tx_desc_tx_buffer_address(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 32))); +} + +static inline void set_tx_desc_next_desc_address(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val); +} + +static inline int get_rx_desc_pkt_len(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)); +} + +static inline int get_rx_desc_crc32(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(14)); +} + +static inline int get_rx_desc_icv(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(15)); +} + +static inline int get_rx_desc_drv_info_size(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)); +} + +static inline int get_rx_desc_shift(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)); +} + +static inline int get_rx_desc_physt(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(26)); +} + +static inline int get_rx_desc_swdec(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(27)); +} + +static inline int get_rx_desc_own(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); +} + +static inline void set_rx_desc_pkt_len(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)); +} + +static inline void set_rx_desc_eor(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)); +} + +static inline void set_rx_desc_own(u8 *__pdesc, u32 __val) +{ + le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); +} + +static inline int get_rx_desc_paggr(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)); +} + +static inline int get_rx_desc_faggr(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)); +} + +static inline int get_rx_desc_rxmcs(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)); +} + +static inline int get_rx_desc_rxht(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)); +} + +static inline int get_rx_desc_splcp(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)); +} + +static inline int get_rx_desc_bw(u8 *__pdesc) +{ + return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)); +} + +static inline int get_rx_desc_tsfl(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 20))); +} + +static inline int get_rx_desc_buff_addr(u8 *__pdesc) +{ + return le32_to_cpu(*((__le32 *)(__pdesc + 24))); +} + +static inline void set_rx_desc_buff_addr(u8 *__pdesc, u32 __val) +{ + *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val); +} #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) -- GitLab From c85a6376673805a68633e5d7d7d1fccf4b207685 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 1 Aug 2019 20:21:02 -0500 Subject: [PATCH 2080/7155] rtlwifi: rtl8192ce: Convert inline routines to little-endian words In this step, the read/write routines for the descriptors are converted to use __le32 quantities, thus a lot of casts can be removed. Callback routines still use the 8-bit arrays, but these are changed within the specified routine. The macro that cleared a descriptor has now been converted into an inline routine. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192ce/trx.c | 23 +- .../wireless/realtek/rtlwifi/rtl8192ce/trx.h | 254 +++++++++--------- 2 files changed, 142 insertions(+), 135 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 7bff0825b264..123dbf0903a1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -317,11 +317,12 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb) + u8 *p_desc8, struct sk_buff *skb) { struct rx_fwinfo_92c *p_drvinfo; - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc8; struct ieee80211_hdr *hdr; + __le32 *p_desc = (__le32 *)p_desc8; u32 phystatus = get_rx_desc_physt(p_desc); stats->length = (u16)get_rx_desc_pkt_len(p_desc); @@ -400,7 +401,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, } void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, + struct ieee80211_hdr *hdr, u8 *pdesc8, u8 *pbd_desc_tx, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, struct sk_buff *skb, @@ -411,7 +412,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - u8 *pdesc = pdesc_tx; + __le32 *pdesc = (__le32 *)pdesc8; u16 seq_number; __le16 fc = hdr->frame_control; u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); @@ -447,7 +448,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); + clear_pci_tx_desc_content(pdesc, sizeof(struct tx_desc_92c)); if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { firstseg = true; @@ -580,12 +581,13 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, } void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, + u8 *pdesc8, bool firstseg, bool lastseg, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 fw_queue = QSLT_BEACON; + __le32 *pdesc = (__le32 *)pdesc8; dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, @@ -599,7 +601,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, "DMA mapping error\n"); return; } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); if (firstseg) set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); @@ -642,9 +644,11 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); } -void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, +void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc8, bool istx, u8 desc_name, u8 *val) { + __le32 *pdesc = (__le32 *)pdesc8; + if (istx) { switch (desc_name) { case HW_DESC_OWN: @@ -682,10 +686,11 @@ void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, } } -u64 rtl92ce_get_desc(struct ieee80211_hw *hw, u8 *p_desc, +u64 rtl92ce_get_desc(struct ieee80211_hw *hw, u8 *p_desc8, bool istx, u8 desc_name) { u32 ret = 0; + __le32 *p_desc = (__le32 *)p_desc8; if (istx) { switch (desc_name) { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index 5addfa20b2b7..709dcac9d84b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -16,318 +16,320 @@ /* macros to read/write various fields in RX or TX descriptors */ -static inline void set_tx_desc_pkt_size(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_pkt_size(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(15, 0)); + le32p_replace_bits(__pdesc, __val, GENMASK(15, 0)); } -static inline void set_tx_desc_offset(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_offset(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(23, 16)); + le32p_replace_bits(__pdesc, __val, GENMASK(23, 16)); } -static inline void set_tx_desc_bmc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_bmc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(24)); + le32p_replace_bits(__pdesc, __val, BIT(24)); } -static inline void set_tx_desc_htc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_htc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(25)); + le32p_replace_bits(__pdesc, __val, BIT(25)); } -static inline void set_tx_desc_last_seg(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_last_seg(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(26)); + le32p_replace_bits(__pdesc, __val, BIT(26)); } -static inline void set_tx_desc_first_seg(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_first_seg(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(27)); + le32p_replace_bits(__pdesc, __val, BIT(27)); } -static inline void set_tx_desc_linip(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_linip(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(28)); + le32p_replace_bits(__pdesc, __val, BIT(28)); } -static inline void set_tx_desc_own(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_own(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); + le32p_replace_bits(__pdesc, __val, BIT(31)); } -static inline int get_tx_desc_own(u8 *__pdesc) +static inline int get_tx_desc_own(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); + return le32_get_bits(*(__pdesc), BIT(31)); } -static inline void set_tx_desc_macid(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_macid(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(4, 0)); + le32p_replace_bits((__pdesc + 1), __val, GENMASK(4, 0)); } -static inline void set_tx_desc_agg_break(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_agg_break(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(5)); + le32p_replace_bits((__pdesc + 1), __val, BIT(5)); } -static inline void set_tx_desc_rdg_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rdg_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, BIT(7)); + le32p_replace_bits((__pdesc + 1), __val, BIT(7)); } -static inline void set_tx_desc_queue_sel(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_queue_sel(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(12, 8)); + le32p_replace_bits((__pdesc + 1), __val, GENMASK(12, 8)); } -static inline void set_tx_desc_rate_id(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rate_id(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(19, 16)); + le32p_replace_bits((__pdesc + 1), __val, GENMASK(19, 16)); } -static inline void set_tx_desc_sec_type(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_sec_type(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 4), __val, GENMASK(23, 22)); + le32p_replace_bits((__pdesc + 1), __val, GENMASK(23, 22)); } -static inline void set_tx_desc_more_frag(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_more_frag(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, BIT(17)); + le32p_replace_bits((__pdesc + 2), __val, BIT(17)); } -static inline void set_tx_desc_ampdu_density(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_ampdu_density(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 8), __val, GENMASK(22, 20)); + le32p_replace_bits((__pdesc + 2), __val, GENMASK(22, 20)); } -static inline void set_tx_desc_seq(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_seq(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(27, 16)); + le32p_replace_bits((__pdesc + 3), __val, GENMASK(27, 16)); } -static inline void set_tx_desc_pkt_id(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_pkt_id(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 12), __val, GENMASK(31, 28)); + le32p_replace_bits((__pdesc + 3), __val, GENMASK(31, 28)); } -static inline void set_tx_desc_rts_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(4, 0)); + le32p_replace_bits((__pdesc + 4), __val, GENMASK(4, 0)); } -static inline void set_tx_desc_qos(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_qos(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(6)); + le32p_replace_bits((__pdesc + 4), __val, BIT(6)); } -static inline void set_tx_desc_hwseq_en(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_hwseq_en(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(7)); + le32p_replace_bits((__pdesc + 4), __val, BIT(7)); } -static inline void set_tx_desc_use_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_use_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(8)); + le32p_replace_bits((__pdesc + 4), __val, BIT(8)); } -static inline void set_tx_desc_disable_fb(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_disable_fb(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(10)); + le32p_replace_bits((__pdesc + 4), __val, BIT(10)); } -static inline void set_tx_desc_cts2self(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_cts2self(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(11)); + le32p_replace_bits((__pdesc + 4), __val, BIT(11)); } -static inline void set_tx_desc_rts_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(12)); + le32p_replace_bits((__pdesc + 4), __val, BIT(12)); } -static inline void set_tx_desc_hw_rts_enable(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_hw_rts_enable(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(13)); + le32p_replace_bits((__pdesc + 4), __val, BIT(13)); } -static inline void set_tx_desc_tx_sub_carrier(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_sub_carrier(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(21, 20)); + le32p_replace_bits((__pdesc + 4), __val, GENMASK(21, 20)); } -static inline void set_tx_desc_data_bw(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_bw(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(25)); + le32p_replace_bits((__pdesc + 4), __val, BIT(25)); } -static inline void set_tx_desc_rts_short(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_short(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(26)); + le32p_replace_bits((__pdesc + 4), __val, BIT(26)); } -static inline void set_tx_desc_rts_bw(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_bw(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, BIT(27)); + le32p_replace_bits((__pdesc + 4), __val, BIT(27)); } -static inline void set_tx_desc_rts_sc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_sc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(29, 28)); + le32p_replace_bits((__pdesc + 4), __val, GENMASK(29, 28)); } -static inline void set_tx_desc_rts_stbc(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_stbc(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 16), __val, GENMASK(31, 30)); + le32p_replace_bits((__pdesc + 4), __val, GENMASK(31, 30)); } -static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_rate(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0)); + le32p_replace_bits((__pdesc + 5), __val, GENMASK(5, 0)); } -static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_shortgi(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6)); + le32p_replace_bits((__pdesc + 5), __val, BIT(6)); } -static inline void set_tx_desc_data_rate_fb_limit(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_data_rate_fb_limit(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(12, 8)); + le32p_replace_bits((__pdesc + 5), __val, GENMASK(12, 8)); } -static inline void set_tx_desc_rts_rate_fb_limit(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_rts_rate_fb_limit(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(16, 13)); + le32p_replace_bits((__pdesc + 5), __val, GENMASK(16, 13)); } -static inline void set_tx_desc_max_agg_num(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_max_agg_num(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 24), __val, GENMASK(15, 11)); + le32p_replace_bits((__pdesc + 6), __val, GENMASK(15, 11)); } -static inline void set_tx_desc_tx_buffer_size(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_buffer_size(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)(__pdesc + 28), __val, GENMASK(15, 0)); + le32p_replace_bits((__pdesc + 7), __val, GENMASK(15, 0)); } -static inline void set_tx_desc_tx_buffer_address(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_tx_buffer_address(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 32) = cpu_to_le32(__val); + *(__pdesc + 8) = cpu_to_le32(__val); } -static inline int get_tx_desc_tx_buffer_address(u8 *__pdesc) +static inline int get_tx_desc_tx_buffer_address(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 32))); + return le32_to_cpu(*((__pdesc + 8))); } -static inline void set_tx_desc_next_desc_address(u8 *__pdesc, u32 __val) +static inline void set_tx_desc_next_desc_address(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 40) = cpu_to_le32(__val); + *(__pdesc + 10) = cpu_to_le32(__val); } -static inline int get_rx_desc_pkt_len(u8 *__pdesc) +static inline int get_rx_desc_pkt_len(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(13, 0)); + return le32_get_bits(*(__pdesc), GENMASK(13, 0)); } -static inline int get_rx_desc_crc32(u8 *__pdesc) +static inline int get_rx_desc_crc32(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(14)); + return le32_get_bits(*(__pdesc), BIT(14)); } -static inline int get_rx_desc_icv(u8 *__pdesc) +static inline int get_rx_desc_icv(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(15)); + return le32_get_bits(*(__pdesc), BIT(15)); } -static inline int get_rx_desc_drv_info_size(u8 *__pdesc) +static inline int get_rx_desc_drv_info_size(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(19, 16)); + return le32_get_bits(*(__pdesc), GENMASK(19, 16)); } -static inline int get_rx_desc_shift(u8 *__pdesc) +static inline int get_rx_desc_shift(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), GENMASK(25, 24)); + return le32_get_bits(*(__pdesc), GENMASK(25, 24)); } -static inline int get_rx_desc_physt(u8 *__pdesc) +static inline int get_rx_desc_physt(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(26)); + return le32_get_bits(*(__pdesc), BIT(26)); } -static inline int get_rx_desc_swdec(u8 *__pdesc) +static inline int get_rx_desc_swdec(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(27)); + return le32_get_bits(*(__pdesc), BIT(27)); } -static inline int get_rx_desc_own(u8 *__pdesc) +static inline int get_rx_desc_own(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)__pdesc), BIT(31)); + return le32_get_bits(*(__pdesc), BIT(31)); } -static inline void set_rx_desc_pkt_len(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_pkt_len(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, GENMASK(13, 0)); + le32p_replace_bits(__pdesc, __val, GENMASK(13, 0)); } -static inline void set_rx_desc_eor(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_eor(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(30)); + le32p_replace_bits(__pdesc, __val, BIT(30)); } -static inline void set_rx_desc_own(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_own(__le32 *__pdesc, u32 __val) { - le32p_replace_bits((__le32 *)__pdesc, __val, BIT(31)); + le32p_replace_bits(__pdesc, __val, BIT(31)); } -static inline int get_rx_desc_paggr(u8 *__pdesc) +static inline int get_rx_desc_paggr(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(14)); + return le32_get_bits(*((__pdesc + 1)), BIT(14)); } -static inline int get_rx_desc_faggr(u8 *__pdesc) +static inline int get_rx_desc_faggr(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 4)), BIT(15)); + return le32_get_bits(*((__pdesc + 1)), BIT(15)); } -static inline int get_rx_desc_rxmcs(u8 *__pdesc) +static inline int get_rx_desc_rxmcs(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), GENMASK(5, 0)); + return le32_get_bits(*((__pdesc + 3)), GENMASK(5, 0)); } -static inline int get_rx_desc_rxht(u8 *__pdesc) +static inline int get_rx_desc_rxht(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(6)); + return le32_get_bits(*((__pdesc + 3)), BIT(6)); } -static inline int get_rx_desc_splcp(u8 *__pdesc) +static inline int get_rx_desc_splcp(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(8)); + return le32_get_bits(*((__pdesc + 3)), BIT(8)); } -static inline int get_rx_desc_bw(u8 *__pdesc) +static inline int get_rx_desc_bw(__le32 *__pdesc) { - return le32_get_bits(*((__le32 *)(__pdesc + 12)), BIT(9)); + return le32_get_bits(*((__pdesc + 3)), BIT(9)); } -static inline int get_rx_desc_tsfl(u8 *__pdesc) +static inline int get_rx_desc_tsfl(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 20))); + return le32_to_cpu(*((__pdesc + 5))); } -static inline int get_rx_desc_buff_addr(u8 *__pdesc) +static inline int get_rx_desc_buff_addr(__le32 *__pdesc) { - return le32_to_cpu(*((__le32 *)(__pdesc + 24))); + return le32_to_cpu(*((__pdesc + 6))); } -static inline void set_rx_desc_buff_addr(u8 *__pdesc, u32 __val) +static inline void set_rx_desc_buff_addr(__le32 *__pdesc, u32 __val) { - *(__le32 *)(__pdesc + 24) = cpu_to_le32(__val); + *(__pdesc + 6) = cpu_to_le32(__val); } -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ - memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) +static inline void clear_pci_tx_desc_content(__le32 *__pdesc, int _size) +{ + memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)); +} struct rx_fwinfo_92c { u8 gain_trsw[4]; -- GitLab From 654026df2635863fd695b2ca833e5c62454bd5ee Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 5 Aug 2019 10:15:04 -0700 Subject: [PATCH 2081/7155] Revert "mwifiex: fix system hang problem after resume" This reverts commit 437322ea2a36d112e20aa7282c869bf924b3a836. This above-mentioned "fix" does not actually do anything to prevent a race condition. It simply papers over it so that the issue doesn't appear. If this is a real problem, it should be explained better than the above commit does, and an alternative, non-racy solution should be found. For further reason to revert this: there's no reason we can't try resetting the card when it's *actually* stuck in host-sleep mode. So instead, this is unnecessarily creating scenarios where we can't recover Wifi (and in fact, I'm fielding reports of Chromebooks that can't recover after the aforementioned commit). Note that this was proposed in 2017 and Ack'ed then, but due to my marking as RFC, it never went anywhere: https://patchwork.kernel.org/patch/9657277/ [RFC] Revert "mwifiex: fix system hang problem after resume" Cc: Amitkumar Karwar Signed-off-by: Brian Norris Reviewed-by: Dmitry Torokhov Acked-by: Amitkumar Karwar Tested-by: Matthias Kaehlcke Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 6c0e52eb8794..1aa93e7e9835 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -59,7 +59,7 @@ static void wakeup_timer_fn(struct timer_list *t) adapter->hw_status = MWIFIEX_HW_STATUS_RESET; mwifiex_cancel_all_pending_cmd(adapter); - if (adapter->if_ops.card_reset && !adapter->hs_activated) + if (adapter->if_ops.card_reset) adapter->if_ops.card_reset(adapter); } -- GitLab From 6004cf298a4180199dc40bc40466126df8a5a88c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Aug 2019 13:58:40 +0200 Subject: [PATCH 2082/7155] b43legacy: Remove pointless cond_resched() wrapper cond_resched() can be used unconditionally. If CONFIG_PREEMPT is set, it becomes a NOP scheduler wise. Also the B43_BUG_ON() in that wrapper is a homebrewn variant of __might_sleep() which is part of cond_resched() already. Remove the cruft and invoke cond_resched() directly. Signed-off-by: Thomas Gleixner Reviewed-by: Larry Finger Tested-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/b43legacy/phy.c | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/broadcom/b43legacy/phy.c b/drivers/net/wireless/broadcom/b43legacy/phy.c index add7a0ff75b8..a659259bc51a 100644 --- a/drivers/net/wireless/broadcom/b43legacy/phy.c +++ b/drivers/net/wireless/broadcom/b43legacy/phy.c @@ -69,17 +69,6 @@ static const s8 b43legacy_tssi2dbm_g_table[] = { static void b43legacy_phy_initg(struct b43legacy_wldev *dev); - -static inline -void b43legacy_voluntary_preempt(void) -{ - B43legacy_BUG_ON(!(!in_atomic() && !in_irq() && - !in_interrupt() && !irqs_disabled())); -#ifndef CONFIG_PREEMPT - cond_resched(); -#endif /* CONFIG_PREEMPT */ -} - /* Lock the PHY registers against concurrent access from the microcode. * This lock is nonrecursive. */ void b43legacy_phy_lock(struct b43legacy_wldev *dev) @@ -1124,7 +1113,7 @@ static u16 b43legacy_phy_lo_b_r15_loop(struct b43legacy_wldev *dev) ret += b43legacy_phy_read(dev, 0x002C); } local_irq_restore(flags); - b43legacy_voluntary_preempt(); + cond_resched(); return ret; } @@ -1253,7 +1242,7 @@ u16 b43legacy_phy_lo_g_deviation_subval(struct b43legacy_wldev *dev, } ret = b43legacy_phy_read(dev, 0x002D); local_irq_restore(flags); - b43legacy_voluntary_preempt(); + cond_resched(); return ret; } @@ -1591,7 +1580,7 @@ void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev) b43legacy_radio_write16(dev, 0x43, i); b43legacy_radio_write16(dev, 0x52, phy->txctl2); udelay(10); - b43legacy_voluntary_preempt(); + cond_resched(); b43legacy_phy_set_baseband_attenuation(dev, j * 2); @@ -1642,7 +1631,7 @@ void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev) phy->txctl2 | (3/*txctl1*/ << 4)); udelay(10); - b43legacy_voluntary_preempt(); + cond_resched(); b43legacy_phy_set_baseband_attenuation(dev, j * 2); @@ -1665,7 +1654,7 @@ void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev) b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA2); udelay(2); b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA3); - b43legacy_voluntary_preempt(); + cond_resched(); } else b43legacy_phy_write(dev, 0x0015, r27 | 0xEFA0); b43legacy_phy_lo_adjust(dev, is_initializing); -- GitLab From e7ef681a8ab8568100eedac1d50fe5973178147b Mon Sep 17 00:00:00 2001 From: Luis Oliveira Date: Tue, 23 Jul 2019 17:17:27 +0200 Subject: [PATCH 2083/7155] dt-bindings: Document the DesignWare IP reset bindings This adds documentation of device tree bindings for the DesignWare IP reset controller. Signed-off-by: Gustavo Pimentel Signed-off-by: Luis Oliveira Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../bindings/reset/snps,dw-reset.txt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/snps,dw-reset.txt diff --git a/Documentation/devicetree/bindings/reset/snps,dw-reset.txt b/Documentation/devicetree/bindings/reset/snps,dw-reset.txt new file mode 100644 index 000000000000..f94f911dd98d --- /dev/null +++ b/Documentation/devicetree/bindings/reset/snps,dw-reset.txt @@ -0,0 +1,30 @@ +Synopsys DesignWare Reset controller +======================================= + +Please also refer to reset.txt in this directory for common reset +controller binding usage. + +Required properties: + +- compatible: should be one of the following. + "snps,dw-high-reset" - for active high configuration + "snps,dw-low-reset" - for active low configuration + +- reg: physical base address of the controller and length of memory mapped + region. + +- #reset-cells: must be 1. + +example: + + dw_rst_1: reset-controller@0000 { + compatible = "snps,dw-high-reset"; + reg = <0x0000 0x4>; + #reset-cells = <1>; + }; + + dw_rst_2: reset-controller@1000 {i + compatible = "snps,dw-low-reset"; + reg = <0x1000 0x8>; + #reset-cells = <1>; + }; -- GitLab From ea651ffd4f7febd4a0b3fdb98e39a6980e978a2c Mon Sep 17 00:00:00 2001 From: Gustavo Pimentel Date: Tue, 23 Jul 2019 17:17:28 +0200 Subject: [PATCH 2084/7155] reset: Add DesignWare IP support to simple reset The reset-simple driver can be now used on DesignWare IPs by default by selecting the following compatible strings: - snps,dw-high-reset for active high resets inputs - snps,dw-low-reset for active low resets inputs Signed-off-by: Gustavo Pimentel Signed-off-by: Luis Oliveira Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 2 +- drivers/reset/reset-simple.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 21efb7d39d62..6d5d76db55b0 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -118,7 +118,7 @@ config RESET_QCOM_PDC config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST - default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN + default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN || ARC help This enables a simple reset controller driver for reset lines that that can be asserted and deasserted by toggling bits in a contiguous, diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index 1154f7b1f4dd..067e7e7b34f1 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -127,6 +127,9 @@ static const struct of_device_id reset_simple_dt_ids[] = { { .compatible = "aspeed,ast2500-lpc-reset" }, { .compatible = "bitmain,bm1880-reset", .data = &reset_simple_active_low }, + { .compatible = "snps,dw-high-reset" }, + { .compatible = "snps,dw-low-reset", + .data = &reset_simple_active_low }, { /* sentinel */ }, }; -- GitLab From 98d87f70f4ab84b9e50e16b7848937ae07518cd4 Mon Sep 17 00:00:00 2001 From: Hans Holmberg Date: Wed, 31 Jul 2019 11:41:33 +0200 Subject: [PATCH 2085/7155] lightnvm: remove nvm_submit_io_sync_fn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the redundant sync handling interface and wait for a completion in the lightnvm core instead. Reviewed-by: Javier González Reviewed-by: Christoph Hellwig Signed-off-by: Hans Holmberg Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 35 +++++++++++++++++++++++++++++------ drivers/nvme/host/lightnvm.c | 29 ----------------------------- include/linux/lightnvm.h | 2 -- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index a600934fdd9c..01d098fb96ac 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -752,12 +752,36 @@ int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) } EXPORT_SYMBOL(nvm_submit_io); +static void nvm_sync_end_io(struct nvm_rq *rqd) +{ + struct completion *waiting = rqd->private; + + complete(waiting); +} + +static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd) +{ + DECLARE_COMPLETION_ONSTACK(wait); + int ret = 0; + + rqd->end_io = nvm_sync_end_io; + rqd->private = &wait; + + ret = dev->ops->submit_io(dev, rqd); + if (ret) + return ret; + + wait_for_completion_io(&wait); + + return 0; +} + int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) { struct nvm_dev *dev = tgt_dev->parent; int ret; - if (!dev->ops->submit_io_sync) + if (!dev->ops->submit_io) return -ENODEV; nvm_rq_tgt_to_dev(tgt_dev, rqd); @@ -765,9 +789,7 @@ int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) rqd->dev = tgt_dev; rqd->flags = nvm_set_flags(&tgt_dev->geo, rqd); - /* In case of error, fail with right address format */ - ret = dev->ops->submit_io_sync(dev, rqd); - nvm_rq_dev_to_tgt(tgt_dev, rqd); + ret = nvm_submit_io_wait(dev, rqd); return ret; } @@ -788,12 +810,13 @@ EXPORT_SYMBOL(nvm_end_io); static int nvm_submit_io_sync_raw(struct nvm_dev *dev, struct nvm_rq *rqd) { - if (!dev->ops->submit_io_sync) + if (!dev->ops->submit_io) return -ENODEV; + rqd->dev = NULL; rqd->flags = nvm_set_flags(&dev->geo, rqd); - return dev->ops->submit_io_sync(dev, rqd); + return nvm_submit_io_wait(dev, rqd); } static int nvm_bb_chunk_sense(struct nvm_dev *dev, struct ppa_addr ppa) diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index ba009d4c9dfa..d6f121452d5d 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -690,34 +690,6 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) return 0; } -static int nvme_nvm_submit_io_sync(struct nvm_dev *dev, struct nvm_rq *rqd) -{ - struct request_queue *q = dev->q; - struct request *rq; - struct nvme_nvm_command cmd; - int ret = 0; - - memset(&cmd, 0, sizeof(struct nvme_nvm_command)); - - rq = nvme_nvm_alloc_request(q, rqd, &cmd); - if (IS_ERR(rq)) - return PTR_ERR(rq); - - /* I/Os can fail and the error is signaled through rqd. Callers must - * handle the error accordingly. - */ - blk_execute_rq(q, NULL, rq, 0); - if (nvme_req(rq)->flags & NVME_REQ_CANCELLED) - ret = -EINTR; - - rqd->ppa_status = le64_to_cpu(nvme_req(rq)->result.u64); - rqd->error = nvme_req(rq)->status; - - blk_mq_free_request(rq); - - return ret; -} - static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name, int size) { @@ -754,7 +726,6 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = { .get_chk_meta = nvme_nvm_get_chk_meta, .submit_io = nvme_nvm_submit_io, - .submit_io_sync = nvme_nvm_submit_io_sync, .create_dma_pool = nvme_nvm_create_dma_pool, .destroy_dma_pool = nvme_nvm_destroy_dma_pool, diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 4d0d5655c7b2..8891647b24b1 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -89,7 +89,6 @@ typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int); typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, sector_t, int, struct nvm_chk_meta *); typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); -typedef int (nvm_submit_io_sync_fn)(struct nvm_dev *, struct nvm_rq *); typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *, int); typedef void (nvm_destroy_dma_pool_fn)(void *); typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t, @@ -104,7 +103,6 @@ struct nvm_dev_ops { nvm_get_chk_meta_fn *get_chk_meta; nvm_submit_io_fn *submit_io; - nvm_submit_io_sync_fn *submit_io_sync; nvm_create_dma_pool_fn *create_dma_pool; nvm_destroy_dma_pool_fn *destroy_dma_pool; -- GitLab From 48e5da725581c1f7444e45cccbafc33e11430b48 Mon Sep 17 00:00:00 2001 From: Hans Holmberg Date: Wed, 31 Jul 2019 11:41:34 +0200 Subject: [PATCH 2086/7155] lightnvm: move metadata mapping to lower level driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that blk_rq_map_kern can map both kmem and vmem, move internal metadata mapping down to the lower level driver. Reviewed-by: Javier González Reviewed-by: Christoph Hellwig Signed-off-by: Hans Holmberg Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 16 +++-- drivers/lightnvm/pblk-core.c | 113 ++++--------------------------- drivers/lightnvm/pblk-read.c | 22 +----- drivers/lightnvm/pblk-recovery.c | 39 ++--------- drivers/lightnvm/pblk-write.c | 20 +----- drivers/lightnvm/pblk.h | 8 +-- drivers/nvme/host/lightnvm.c | 20 +++++- include/linux/lightnvm.h | 6 +- 8 files changed, 54 insertions(+), 190 deletions(-) diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 01d098fb96ac..3cd03582a2ed 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -731,7 +731,7 @@ static int nvm_set_flags(struct nvm_geo *geo, struct nvm_rq *rqd) return flags; } -int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) +int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd, void *buf) { struct nvm_dev *dev = tgt_dev->parent; int ret; @@ -745,7 +745,7 @@ int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) rqd->flags = nvm_set_flags(&tgt_dev->geo, rqd); /* In case of error, fail with right address format */ - ret = dev->ops->submit_io(dev, rqd); + ret = dev->ops->submit_io(dev, rqd, buf); if (ret) nvm_rq_dev_to_tgt(tgt_dev, rqd); return ret; @@ -759,7 +759,8 @@ static void nvm_sync_end_io(struct nvm_rq *rqd) complete(waiting); } -static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd) +static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd, + void *buf) { DECLARE_COMPLETION_ONSTACK(wait); int ret = 0; @@ -767,7 +768,7 @@ static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd) rqd->end_io = nvm_sync_end_io; rqd->private = &wait; - ret = dev->ops->submit_io(dev, rqd); + ret = dev->ops->submit_io(dev, rqd, buf); if (ret) return ret; @@ -776,7 +777,8 @@ static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd) return 0; } -int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) +int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd, + void *buf) { struct nvm_dev *dev = tgt_dev->parent; int ret; @@ -789,7 +791,7 @@ int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) rqd->dev = tgt_dev; rqd->flags = nvm_set_flags(&tgt_dev->geo, rqd); - ret = nvm_submit_io_wait(dev, rqd); + ret = nvm_submit_io_wait(dev, rqd, buf); return ret; } @@ -816,7 +818,7 @@ static int nvm_submit_io_sync_raw(struct nvm_dev *dev, struct nvm_rq *rqd) rqd->dev = NULL; rqd->flags = nvm_set_flags(&dev->geo, rqd); - return nvm_submit_io_wait(dev, rqd); + return nvm_submit_io_wait(dev, rqd, NULL); } static int nvm_bb_chunk_sense(struct nvm_dev *dev, struct ppa_addr ppa) diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index f546e6f28b8a..a58d3c84a3f2 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c @@ -507,7 +507,7 @@ void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write) pblk->sec_per_write = sec_per_write; } -int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd) +int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd, void *buf) { struct nvm_tgt_dev *dev = pblk->dev; @@ -518,7 +518,7 @@ int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd) return NVM_IO_ERR; #endif - return nvm_submit_io(dev, rqd); + return nvm_submit_io(dev, rqd, buf); } void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd) @@ -541,7 +541,7 @@ void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd) } } -int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) +int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd, void *buf) { struct nvm_tgt_dev *dev = pblk->dev; int ret; @@ -553,7 +553,7 @@ int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) return NVM_IO_ERR; #endif - ret = nvm_submit_io_sync(dev, rqd); + ret = nvm_submit_io_sync(dev, rqd, buf); if (trace_pblk_chunk_state_enabled() && !ret && rqd->opcode == NVM_OP_PWRITE) @@ -562,65 +562,19 @@ int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) return ret; } -int pblk_submit_io_sync_sem(struct pblk *pblk, struct nvm_rq *rqd) +static int pblk_submit_io_sync_sem(struct pblk *pblk, struct nvm_rq *rqd, + void *buf) { struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd); int ret; pblk_down_chunk(pblk, ppa_list[0]); - ret = pblk_submit_io_sync(pblk, rqd); + ret = pblk_submit_io_sync(pblk, rqd, buf); pblk_up_chunk(pblk, ppa_list[0]); return ret; } -static void pblk_bio_map_addr_endio(struct bio *bio) -{ - bio_put(bio); -} - -struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data, - unsigned int nr_secs, unsigned int len, - int alloc_type, gfp_t gfp_mask) -{ - struct nvm_tgt_dev *dev = pblk->dev; - void *kaddr = data; - struct page *page; - struct bio *bio; - int i, ret; - - if (alloc_type == PBLK_KMALLOC_META) - return bio_map_kern(dev->q, kaddr, len, gfp_mask); - - bio = bio_kmalloc(gfp_mask, nr_secs); - if (!bio) - return ERR_PTR(-ENOMEM); - - for (i = 0; i < nr_secs; i++) { - page = vmalloc_to_page(kaddr); - if (!page) { - pblk_err(pblk, "could not map vmalloc bio\n"); - bio_put(bio); - bio = ERR_PTR(-ENOMEM); - goto out; - } - - ret = bio_add_pc_page(dev->q, bio, page, PAGE_SIZE, 0); - if (ret != PAGE_SIZE) { - pblk_err(pblk, "could not add page to bio\n"); - bio_put(bio); - bio = ERR_PTR(-ENOMEM); - goto out; - } - - kaddr += PAGE_SIZE; - } - - bio->bi_end_io = pblk_bio_map_addr_endio; -out: - return bio; -} - int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail, unsigned long secs_to_flush, bool skip_meta) { @@ -722,9 +676,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line) int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line) { - struct nvm_tgt_dev *dev = pblk->dev; struct pblk_line_meta *lm = &pblk->lm; - struct bio *bio; struct ppa_addr *ppa_list; struct nvm_rq rqd; u64 paddr = pblk_line_smeta_start(pblk, line); @@ -736,16 +688,6 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line) if (ret) return ret; - bio = bio_map_kern(dev->q, line->smeta, lm->smeta_len, GFP_KERNEL); - if (IS_ERR(bio)) { - ret = PTR_ERR(bio); - goto clear_rqd; - } - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_READ, 0); - - rqd.bio = bio; rqd.opcode = NVM_OP_PREAD; rqd.nr_ppas = lm->smeta_sec; rqd.is_seq = 1; @@ -754,10 +696,9 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line) for (i = 0; i < lm->smeta_sec; i++, paddr++) ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id); - ret = pblk_submit_io_sync(pblk, &rqd); + ret = pblk_submit_io_sync(pblk, &rqd, line->smeta); if (ret) { pblk_err(pblk, "smeta I/O submission failed: %d\n", ret); - bio_put(bio); goto clear_rqd; } @@ -776,9 +717,7 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line) static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line, u64 paddr) { - struct nvm_tgt_dev *dev = pblk->dev; struct pblk_line_meta *lm = &pblk->lm; - struct bio *bio; struct ppa_addr *ppa_list; struct nvm_rq rqd; __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf); @@ -791,16 +730,6 @@ static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line, if (ret) return ret; - bio = bio_map_kern(dev->q, line->smeta, lm->smeta_len, GFP_KERNEL); - if (IS_ERR(bio)) { - ret = PTR_ERR(bio); - goto clear_rqd; - } - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_WRITE, 0); - - rqd.bio = bio; rqd.opcode = NVM_OP_PWRITE; rqd.nr_ppas = lm->smeta_sec; rqd.is_seq = 1; @@ -814,10 +743,9 @@ static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line, meta->lba = lba_list[paddr] = addr_empty; } - ret = pblk_submit_io_sync_sem(pblk, &rqd); + ret = pblk_submit_io_sync_sem(pblk, &rqd, line->smeta); if (ret) { pblk_err(pblk, "smeta I/O submission failed: %d\n", ret); - bio_put(bio); goto clear_rqd; } @@ -838,10 +766,8 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line, { struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; - struct pblk_line_mgmt *l_mg = &pblk->l_mg; struct pblk_line_meta *lm = &pblk->lm; void *ppa_list_buf, *meta_list; - struct bio *bio; struct ppa_addr *ppa_list; struct nvm_rq rqd; u64 paddr = line->emeta_ssec; @@ -867,17 +793,6 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line, rq_ppas = pblk_calc_secs(pblk, left_ppas, 0, false); rq_len = rq_ppas * geo->csecs; - bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len, - l_mg->emeta_alloc_type, GFP_KERNEL); - if (IS_ERR(bio)) { - ret = PTR_ERR(bio); - goto free_rqd_dma; - } - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_READ, 0); - - rqd.bio = bio; rqd.meta_list = meta_list; rqd.ppa_list = ppa_list_buf; rqd.dma_meta_list = dma_meta_list; @@ -896,7 +811,6 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line, while (test_bit(pos, line->blk_bitmap)) { paddr += min; if (pblk_boundary_paddr_checks(pblk, paddr)) { - bio_put(bio); ret = -EINTR; goto free_rqd_dma; } @@ -906,7 +820,6 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line, } if (pblk_boundary_paddr_checks(pblk, paddr + min)) { - bio_put(bio); ret = -EINTR; goto free_rqd_dma; } @@ -915,10 +828,9 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line, ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line_id); } - ret = pblk_submit_io_sync(pblk, &rqd); + ret = pblk_submit_io_sync(pblk, &rqd, emeta_buf); if (ret) { pblk_err(pblk, "emeta I/O submission failed: %d\n", ret); - bio_put(bio); goto free_rqd_dma; } @@ -963,7 +875,7 @@ static int pblk_blk_erase_sync(struct pblk *pblk, struct ppa_addr ppa) /* The write thread schedules erases so that it minimizes disturbances * with writes. Thus, there is no need to take the LUN semaphore. */ - ret = pblk_submit_io_sync(pblk, &rqd); + ret = pblk_submit_io_sync(pblk, &rqd, NULL); rqd.private = pblk; __pblk_end_io_erase(pblk, &rqd); @@ -1792,7 +1704,7 @@ int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa) /* The write thread schedules erases so that it minimizes disturbances * with writes. Thus, there is no need to take the LUN semaphore. */ - err = pblk_submit_io(pblk, rqd); + err = pblk_submit_io(pblk, rqd, NULL); if (err) { struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; @@ -1923,7 +1835,6 @@ void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line) static void pblk_save_lba_list(struct pblk *pblk, struct pblk_line *line) { struct pblk_line_meta *lm = &pblk->lm; - struct pblk_line_mgmt *l_mg = &pblk->l_mg; unsigned int lba_list_size = lm->emeta_len[2]; struct pblk_w_err_gc *w_err_gc = line->w_err_gc; struct pblk_emeta *emeta = line->emeta; diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c index d98ea392fe33..d572d4559e4e 100644 --- a/drivers/lightnvm/pblk-read.c +++ b/drivers/lightnvm/pblk-read.c @@ -342,7 +342,7 @@ void pblk_submit_read(struct pblk *pblk, struct bio *bio) bio_put(int_bio); int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set); goto split_retry; - } else if (pblk_submit_io(pblk, rqd)) { + } else if (pblk_submit_io(pblk, rqd, NULL)) { /* Submitting IO to drive failed, let's report an error */ rqd->error = -ENODEV; pblk_end_io_read(rqd); @@ -419,7 +419,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) { struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; - struct bio *bio; struct nvm_rq rqd; int data_len; int ret = NVM_IO_OK; @@ -447,25 +446,12 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) goto out; data_len = (gc_rq->secs_to_gc) * geo->csecs; - bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len, - PBLK_VMALLOC_META, GFP_KERNEL); - if (IS_ERR(bio)) { - pblk_err(pblk, "could not allocate GC bio (%lu)\n", - PTR_ERR(bio)); - ret = PTR_ERR(bio); - goto err_free_dma; - } - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_READ, 0); - rqd.opcode = NVM_OP_PREAD; rqd.nr_ppas = gc_rq->secs_to_gc; - rqd.bio = bio; - if (pblk_submit_io_sync(pblk, &rqd)) { + if (pblk_submit_io_sync(pblk, &rqd, gc_rq->data)) { ret = -EIO; - goto err_free_bio; + goto err_free_dma; } pblk_read_check_rand(pblk, &rqd, gc_rq->lba_list, gc_rq->nr_secs); @@ -489,8 +475,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) pblk_free_rqd_meta(pblk, &rqd); return ret; -err_free_bio: - bio_put(bio); err_free_dma: pblk_free_rqd_meta(pblk, &rqd); return ret; diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c index e6dda04de144..d5e210c3c5b7 100644 --- a/drivers/lightnvm/pblk-recovery.c +++ b/drivers/lightnvm/pblk-recovery.c @@ -178,12 +178,11 @@ static int pblk_recov_pad_line(struct pblk *pblk, struct pblk_line *line, void *meta_list; struct pblk_pad_rq *pad_rq; struct nvm_rq *rqd; - struct bio *bio; struct ppa_addr *ppa_list; void *data; __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf); u64 w_ptr = line->cur_sec; - int left_line_ppas, rq_ppas, rq_len; + int left_line_ppas, rq_ppas; int i, j; int ret = 0; @@ -212,28 +211,15 @@ static int pblk_recov_pad_line(struct pblk *pblk, struct pblk_line *line, goto fail_complete; } - rq_len = rq_ppas * geo->csecs; - - bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len, - PBLK_VMALLOC_META, GFP_KERNEL); - if (IS_ERR(bio)) { - ret = PTR_ERR(bio); - goto fail_complete; - } - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_WRITE, 0); - rqd = pblk_alloc_rqd(pblk, PBLK_WRITE_INT); ret = pblk_alloc_rqd_meta(pblk, rqd); if (ret) { pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT); - bio_put(bio); goto fail_complete; } - rqd->bio = bio; + rqd->bio = NULL; rqd->opcode = NVM_OP_PWRITE; rqd->is_seq = 1; rqd->nr_ppas = rq_ppas; @@ -275,13 +261,12 @@ static int pblk_recov_pad_line(struct pblk *pblk, struct pblk_line *line, kref_get(&pad_rq->ref); pblk_down_chunk(pblk, ppa_list[0]); - ret = pblk_submit_io(pblk, rqd); + ret = pblk_submit_io(pblk, rqd, data); if (ret) { pblk_err(pblk, "I/O submission failed: %d\n", ret); pblk_up_chunk(pblk, ppa_list[0]); kref_put(&pad_rq->ref, pblk_recov_complete); pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT); - bio_put(bio); goto fail_complete; } @@ -375,7 +360,6 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, struct ppa_addr *ppa_list; void *meta_list; struct nvm_rq *rqd; - struct bio *bio; void *data; dma_addr_t dma_ppa_list, dma_meta_list; __le64 *lba_list; @@ -407,15 +391,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, rq_len = rq_ppas * geo->csecs; retry_rq: - bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL); - if (IS_ERR(bio)) - return PTR_ERR(bio); - - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_READ, 0); - bio_get(bio); - - rqd->bio = bio; + rqd->bio = NULL; rqd->opcode = NVM_OP_PREAD; rqd->meta_list = meta_list; rqd->nr_ppas = rq_ppas; @@ -445,10 +421,9 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, addr_to_gen_ppa(pblk, paddr + j, line->id); } - ret = pblk_submit_io_sync(pblk, rqd); + ret = pblk_submit_io_sync(pblk, rqd, data); if (ret) { pblk_err(pblk, "I/O submission failed: %d\n", ret); - bio_put(bio); return ret; } @@ -460,24 +435,20 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, if (padded) { pblk_log_read_err(pblk, rqd); - bio_put(bio); return -EINTR; } pad_distance = pblk_pad_distance(pblk, line); ret = pblk_recov_pad_line(pblk, line, pad_distance); if (ret) { - bio_put(bio); return ret; } padded = true; - bio_put(bio); goto retry_rq; } pblk_get_packed_meta(pblk, rqd); - bio_put(bio); for (i = 0; i < rqd->nr_ppas; i++) { struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i); diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c index 4e63f9b5954c..b9a2aeba95ab 100644 --- a/drivers/lightnvm/pblk-write.c +++ b/drivers/lightnvm/pblk-write.c @@ -373,7 +373,6 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) struct pblk_emeta *emeta = meta_line->emeta; struct ppa_addr *ppa_list; struct pblk_g_ctx *m_ctx; - struct bio *bio; struct nvm_rq *rqd; void *data; u64 paddr; @@ -391,20 +390,9 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) rq_len = rq_ppas * geo->csecs; data = ((void *)emeta->buf) + emeta->mem; - bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len, - l_mg->emeta_alloc_type, GFP_KERNEL); - if (IS_ERR(bio)) { - pblk_err(pblk, "failed to map emeta io"); - ret = PTR_ERR(bio); - goto fail_free_rqd; - } - bio->bi_iter.bi_sector = 0; /* internal bio */ - bio_set_op_attrs(bio, REQ_OP_WRITE, 0); - rqd->bio = bio; - ret = pblk_alloc_w_rq(pblk, rqd, rq_ppas, pblk_end_io_write_meta); if (ret) - goto fail_free_bio; + goto fail_free_rqd; ppa_list = nvm_rq_to_ppa_list(rqd); for (i = 0; i < rqd->nr_ppas; ) { @@ -423,7 +411,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) pblk_down_chunk(pblk, ppa_list[0]); - ret = pblk_submit_io(pblk, rqd); + ret = pblk_submit_io(pblk, rqd, data); if (ret) { pblk_err(pblk, "emeta I/O submission failed: %d\n", ret); goto fail_rollback; @@ -437,8 +425,6 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) pblk_dealloc_page(pblk, meta_line, rq_ppas); list_add(&meta_line->list, &meta_line->list); spin_unlock(&l_mg->close_lock); -fail_free_bio: - bio_put(bio); fail_free_rqd: pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT); return ret; @@ -523,7 +509,7 @@ static int pblk_submit_io_set(struct pblk *pblk, struct nvm_rq *rqd) meta_line = pblk_should_submit_meta_io(pblk, rqd); /* Submit data write for current data line */ - err = pblk_submit_io(pblk, rqd); + err = pblk_submit_io(pblk, rqd, NULL); if (err) { pblk_err(pblk, "data I/O submission failed: %d\n", err); return NVM_IO_ERR; diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h index a67855387f53..d515d3409a74 100644 --- a/drivers/lightnvm/pblk.h +++ b/drivers/lightnvm/pblk.h @@ -783,14 +783,10 @@ struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk, struct ppa_addr ppa); void pblk_log_write_err(struct pblk *pblk, struct nvm_rq *rqd); void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd); -int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd); -int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd); -int pblk_submit_io_sync_sem(struct pblk *pblk, struct nvm_rq *rqd); +int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd, void *buf); +int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd, void *buf); int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line); void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd); -struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data, - unsigned int nr_secs, unsigned int len, - int alloc_type, gfp_t gfp_mask); struct pblk_line *pblk_line_get(struct pblk *pblk); struct pblk_line *pblk_line_get_first_data(struct pblk *pblk); struct pblk_line *pblk_line_replace_data(struct pblk *pblk); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index d6f121452d5d..ec46693f6b64 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -667,11 +667,14 @@ static struct request *nvme_nvm_alloc_request(struct request_queue *q, return rq; } -static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) +static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd, + void *buf) { + struct nvm_geo *geo = &dev->geo; struct request_queue *q = dev->q; struct nvme_nvm_command *cmd; struct request *rq; + int ret; cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL); if (!cmd) @@ -679,8 +682,15 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) rq = nvme_nvm_alloc_request(q, rqd, cmd); if (IS_ERR(rq)) { - kfree(cmd); - return PTR_ERR(rq); + ret = PTR_ERR(rq); + goto err_free_cmd; + } + + if (buf) { + ret = blk_rq_map_kern(q, rq, buf, geo->csecs * rqd->nr_ppas, + GFP_KERNEL); + if (ret) + goto err_free_cmd; } rq->end_io_data = rqd; @@ -688,6 +698,10 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_io); return 0; + +err_free_cmd: + kfree(cmd); + return ret; } static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name, diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 8891647b24b1..ee8ec2e68055 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -88,7 +88,7 @@ typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *); typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int); typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, sector_t, int, struct nvm_chk_meta *); -typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); +typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *, void *); typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *, int); typedef void (nvm_destroy_dma_pool_fn)(void *); typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t, @@ -680,8 +680,8 @@ extern int nvm_get_chunk_meta(struct nvm_tgt_dev *, struct ppa_addr, int, struct nvm_chk_meta *); extern int nvm_set_chunk_meta(struct nvm_tgt_dev *, struct ppa_addr *, int, int); -extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *); -extern int nvm_submit_io_sync(struct nvm_tgt_dev *, struct nvm_rq *); +extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *, void *); +extern int nvm_submit_io_sync(struct nvm_tgt_dev *, struct nvm_rq *, void *); extern void nvm_end_io(struct nvm_rq *); #else /* CONFIG_NVM */ -- GitLab From ff8f352070b204ab1721f41339547d897f8120fd Mon Sep 17 00:00:00 2001 From: Hans Holmberg Date: Wed, 31 Jul 2019 11:41:35 +0200 Subject: [PATCH 2087/7155] lightnvm: pblk: use kvmalloc for metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason now not to use kvmalloc, so replace the internal metadata allocation scheme. Reviewed-by: Javier González Reviewed-by: Christoph Hellwig Signed-off-by: Hans Holmberg Signed-off-by: Jens Axboe --- drivers/lightnvm/pblk-core.c | 3 +-- drivers/lightnvm/pblk-gc.c | 19 ++++++++---------- drivers/lightnvm/pblk-init.c | 38 ++++++++++-------------------------- drivers/lightnvm/pblk.h | 23 ---------------------- 4 files changed, 19 insertions(+), 64 deletions(-) diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index a58d3c84a3f2..b413bafe93fd 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c @@ -1839,8 +1839,7 @@ static void pblk_save_lba_list(struct pblk *pblk, struct pblk_line *line) struct pblk_w_err_gc *w_err_gc = line->w_err_gc; struct pblk_emeta *emeta = line->emeta; - w_err_gc->lba_list = pblk_malloc(lba_list_size, - l_mg->emeta_alloc_type, GFP_KERNEL); + w_err_gc->lba_list = kvmalloc(lba_list_size, GFP_KERNEL); memcpy(w_err_gc->lba_list, emeta_to_lbas(pblk, emeta->buf), lba_list_size); } diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c index 63ee205b41c4..2581eebcfc41 100644 --- a/drivers/lightnvm/pblk-gc.c +++ b/drivers/lightnvm/pblk-gc.c @@ -132,14 +132,12 @@ static __le64 *get_lba_list_from_emeta(struct pblk *pblk, struct pblk_line *line) { struct line_emeta *emeta_buf; - struct pblk_line_mgmt *l_mg = &pblk->l_mg; struct pblk_line_meta *lm = &pblk->lm; unsigned int lba_list_size = lm->emeta_len[2]; __le64 *lba_list; int ret; - emeta_buf = pblk_malloc(lm->emeta_len[0], - l_mg->emeta_alloc_type, GFP_KERNEL); + emeta_buf = kvmalloc(lm->emeta_len[0], GFP_KERNEL); if (!emeta_buf) return NULL; @@ -147,7 +145,7 @@ static __le64 *get_lba_list_from_emeta(struct pblk *pblk, if (ret) { pblk_err(pblk, "line %d read emeta failed (%d)\n", line->id, ret); - pblk_mfree(emeta_buf, l_mg->emeta_alloc_type); + kvfree(emeta_buf); return NULL; } @@ -161,16 +159,16 @@ static __le64 *get_lba_list_from_emeta(struct pblk *pblk, if (ret) { pblk_err(pblk, "inconsistent emeta (line %d)\n", line->id); - pblk_mfree(emeta_buf, l_mg->emeta_alloc_type); + kvfree(emeta_buf); return NULL; } - lba_list = pblk_malloc(lba_list_size, - l_mg->emeta_alloc_type, GFP_KERNEL); + lba_list = kvmalloc(lba_list_size, GFP_KERNEL); + if (lba_list) memcpy(lba_list, emeta_to_lbas(pblk, emeta_buf), lba_list_size); - pblk_mfree(emeta_buf, l_mg->emeta_alloc_type); + kvfree(emeta_buf); return lba_list; } @@ -181,7 +179,6 @@ static void pblk_gc_line_prepare_ws(struct work_struct *work) ws); struct pblk *pblk = line_ws->pblk; struct pblk_line *line = line_ws->line; - struct pblk_line_mgmt *l_mg = &pblk->l_mg; struct pblk_line_meta *lm = &pblk->lm; struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; @@ -272,7 +269,7 @@ static void pblk_gc_line_prepare_ws(struct work_struct *work) goto next_rq; out: - pblk_mfree(lba_list, l_mg->emeta_alloc_type); + kvfree(lba_list); kfree(line_ws); kfree(invalid_bitmap); @@ -286,7 +283,7 @@ static void pblk_gc_line_prepare_ws(struct work_struct *work) fail_free_gc_rq: kfree(gc_rq); fail_free_lba_list: - pblk_mfree(lba_list, l_mg->emeta_alloc_type); + kvfree(lba_list); fail_free_invalid_bitmap: kfree(invalid_bitmap); fail_free_ws: diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index b351c7f002de..9a967a2e83dd 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c @@ -543,7 +543,7 @@ static void pblk_line_mg_free(struct pblk *pblk) for (i = 0; i < PBLK_DATA_LINES; i++) { kfree(l_mg->sline_meta[i]); - pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type); + kvfree(l_mg->eline_meta[i]->buf); kfree(l_mg->eline_meta[i]); } @@ -560,7 +560,7 @@ static void pblk_line_meta_free(struct pblk_line_mgmt *l_mg, kfree(line->erase_bitmap); kfree(line->chks); - pblk_mfree(w_err_gc->lba_list, l_mg->emeta_alloc_type); + kvfree(w_err_gc->lba_list); kfree(w_err_gc); } @@ -890,29 +890,14 @@ static int pblk_line_mg_init(struct pblk *pblk) if (!emeta) goto fail_free_emeta; - if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) { - l_mg->emeta_alloc_type = PBLK_VMALLOC_META; - - emeta->buf = vmalloc(lm->emeta_len[0]); - if (!emeta->buf) { - kfree(emeta); - goto fail_free_emeta; - } - - emeta->nr_entries = lm->emeta_sec[0]; - l_mg->eline_meta[i] = emeta; - } else { - l_mg->emeta_alloc_type = PBLK_KMALLOC_META; - - emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL); - if (!emeta->buf) { - kfree(emeta); - goto fail_free_emeta; - } - - emeta->nr_entries = lm->emeta_sec[0]; - l_mg->eline_meta[i] = emeta; + emeta->buf = kvmalloc(lm->emeta_len[0], GFP_KERNEL); + if (!emeta->buf) { + kfree(emeta); + goto fail_free_emeta; } + + emeta->nr_entries = lm->emeta_sec[0]; + l_mg->eline_meta[i] = emeta; } for (i = 0; i < l_mg->nr_lines; i++) @@ -926,10 +911,7 @@ static int pblk_line_mg_init(struct pblk *pblk) fail_free_emeta: while (--i >= 0) { - if (l_mg->emeta_alloc_type == PBLK_VMALLOC_META) - vfree(l_mg->eline_meta[i]->buf); - else - kfree(l_mg->eline_meta[i]->buf); + kvfree(l_mg->eline_meta[i]->buf); kfree(l_mg->eline_meta[i]); } diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h index d515d3409a74..86ffa875bfe1 100644 --- a/drivers/lightnvm/pblk.h +++ b/drivers/lightnvm/pblk.h @@ -481,11 +481,6 @@ struct pblk_line { #define PBLK_DATA_LINES 4 -enum { - PBLK_KMALLOC_META = 1, - PBLK_VMALLOC_META = 2, -}; - enum { PBLK_EMETA_TYPE_HEADER = 1, /* struct line_emeta first sector */ PBLK_EMETA_TYPE_LLBA = 2, /* lba list - type: __le64 */ @@ -521,9 +516,6 @@ struct pblk_line_mgmt { __le32 *vsc_list; /* Valid sector counts for all lines */ - /* Metadata allocation type: VMALLOC | KMALLOC */ - int emeta_alloc_type; - /* Pre-allocated metadata for data lines */ struct pblk_smeta *sline_meta[PBLK_DATA_LINES]; struct pblk_emeta *eline_meta[PBLK_DATA_LINES]; @@ -934,21 +926,6 @@ void pblk_rl_werr_line_out(struct pblk_rl *rl); int pblk_sysfs_init(struct gendisk *tdisk); void pblk_sysfs_exit(struct gendisk *tdisk); -static inline void *pblk_malloc(size_t size, int type, gfp_t flags) -{ - if (type == PBLK_KMALLOC_META) - return kmalloc(size, flags); - return vmalloc(size); -} - -static inline void pblk_mfree(void *ptr, int type) -{ - if (type == PBLK_KMALLOC_META) - kfree(ptr); - else - vfree(ptr); -} - static inline struct nvm_rq *nvm_rq_from_c_ctx(void *c_ctx) { return c_ctx - sizeof(struct nvm_rq); -- GitLab From 00ec4f3039a9e36cbccd1aea82d06c77c440a51c Mon Sep 17 00:00:00 2001 From: Hans Holmberg Date: Wed, 31 Jul 2019 11:41:36 +0200 Subject: [PATCH 2088/7155] block: stop exporting bio_map_kern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that there no module users left of bio_map_kern, stop exporting the symbol. Reviewed-by: Javier González Reviewed-by: Christoph Hellwig Signed-off-by: Hans Holmberg Signed-off-by: Jens Axboe --- block/bio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/bio.c b/block/bio.c index 0fff4eb9eb1e..24a496f5d2e2 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1521,7 +1521,6 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len, bio->bi_end_io = bio_map_kern_endio; return bio; } -EXPORT_SYMBOL(bio_map_kern); static void bio_copy_kern_endio(struct bio *bio) { -- GitLab From a78d0dbec712999ecd2f800eea0f62dc93867a78 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Fri, 2 Aug 2019 15:54:01 -0700 Subject: [PATCH 2089/7155] selftests/bpf: add loop test 4 Add a test that returns a 'random' number between [0, 2^20) If state pruning is not working correctly for loop body the number of processed insns will be 2^20 * num_of_insns_in_loop_body and the program will be rejected. Signed-off-by: Alexei Starovoitov Acked-by: Andrii Nakryiko Acked-by: Yonghong Song --- .../selftests/bpf/prog_tests/bpf_verif_scale.c | 1 + tools/testing/selftests/bpf/progs/loop4.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/loop4.c diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index b4be96162ff4..e9e72d8d7aae 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -71,6 +71,7 @@ void test_bpf_verif_scale(void) { "loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, + { "loop4.o", BPF_PROG_TYPE_SCHED_CLS }, /* partial unroll. 19k insn in a loop. * Total program size 20.8k insn. diff --git a/tools/testing/selftests/bpf/progs/loop4.c b/tools/testing/selftests/bpf/progs/loop4.c new file mode 100644 index 000000000000..650859022771 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/loop4.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +SEC("socket") +int combinations(volatile struct __sk_buff* skb) +{ + int ret = 0, i; + +#pragma nounroll + for (i = 0; i < 20; i++) + if (skb->len) + ret |= 1 << i; + return ret; +} -- GitLab From 8c30396074c131765b19eb3cb7ff764a4f2f2913 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Fri, 2 Aug 2019 16:23:40 -0700 Subject: [PATCH 2090/7155] selftests/bpf: add loop test 5 Add a test with multiple exit conditions. It's not an infinite loop only when the verifier can properly track all math on variable 'i' through all possible ways of executing this loop. barrier()s are needed to disable llvm optimization that combines multiple branches into fewer branches. Signed-off-by: Alexei Starovoitov Acked-by: Yonghong Song --- .../bpf/prog_tests/bpf_verif_scale.c | 1 + tools/testing/selftests/bpf/progs/loop5.c | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/loop5.c diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index e9e72d8d7aae..0caf8eafa9eb 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -72,6 +72,7 @@ void test_bpf_verif_scale(void) { "loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT }, { "loop4.o", BPF_PROG_TYPE_SCHED_CLS }, + { "loop5.o", BPF_PROG_TYPE_SCHED_CLS }, /* partial unroll. 19k insn in a loop. * Total program size 20.8k insn. diff --git a/tools/testing/selftests/bpf/progs/loop5.c b/tools/testing/selftests/bpf/progs/loop5.c new file mode 100644 index 000000000000..28d1d668f07c --- /dev/null +++ b/tools/testing/selftests/bpf/progs/loop5.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook +#include +#include "bpf_helpers.h" +#define barrier() __asm__ __volatile__("": : :"memory") + +char _license[] SEC("license") = "GPL"; + +SEC("socket") +int while_true(volatile struct __sk_buff* skb) +{ + int i = 0; + + while (1) { + if (skb->len) + i += 3; + else + i += 7; + if (i == 9) + break; + barrier(); + if (i == 10) + break; + barrier(); + if (i == 13) + break; + barrier(); + if (i == 14) + break; + } + return i; +} -- GitLab From 2b835e24b5c6f9c633ff51973581ee7ca7b3e8ec Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 23 Jul 2019 19:58:38 +0200 Subject: [PATCH 2091/7155] arm64: untag user pointers in access_ok and __uaccess_mask_ptr This patch is a part of a series that extends kernel ABI to allow to pass tagged user pointers (with the top byte set to something else other than 0x00) as syscall arguments. copy_from_user (and a few other similar functions) are used to copy data from user memory into the kernel memory or vice versa. Since a user can provided a tagged pointer to one of the syscalls that use copy_from_user, we need to correctly handle such pointers. Do this by untagging user pointers in access_ok and in __uaccess_mask_ptr, before performing access validity checks. Note, that this patch only temporarily untags the pointers to perform the checks, but then passes them as is into the kernel internals. Reviewed-by: Vincenzo Frascino Reviewed-by: Kees Cook Reviewed-by: Catalin Marinas Signed-off-by: Andrey Konovalov [will: Add __force to casting in untagged_addr() to kill sparse warning] Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 2 +- arch/arm64/include/asm/uaccess.h | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index fb04f10a78ab..46c4c08a80a9 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -201,7 +201,7 @@ extern u64 vabits_user; * pass on to access_ok(), for instance. */ #define untagged_addr(addr) \ - ((__typeof__(addr))sign_extend64((u64)(addr), 55)) + ((__typeof__(addr))sign_extend64((__force u64)(addr), 55)) #ifdef CONFIG_KASAN_SW_TAGS #define __tag_shifted(tag) ((u64)(tag) << 56) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 5a1c32260c1f..a138e3b4f717 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -62,6 +62,8 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si { unsigned long ret, limit = current_thread_info()->addr_limit; + addr = untagged_addr(addr); + __chk_user_ptr(addr); asm volatile( // A + B <= C + 1 for all A,B,C, in four easy steps: @@ -215,7 +217,8 @@ static inline void uaccess_enable_not_uao(void) /* * Sanitise a uaccess pointer such that it becomes NULL if above the - * current addr_limit. + * current addr_limit. In case the pointer is tagged (has the top byte set), + * untag the pointer before checking. */ #define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr) static inline void __user *__uaccess_mask_ptr(const void __user *ptr) @@ -223,10 +226,11 @@ static inline void __user *__uaccess_mask_ptr(const void __user *ptr) void __user *safe_ptr; asm volatile( - " bics xzr, %1, %2\n" + " bics xzr, %3, %2\n" " csel %0, %1, xzr, eq\n" : "=&r" (safe_ptr) - : "r" (ptr), "r" (current_thread_info()->addr_limit) + : "r" (ptr), "r" (current_thread_info()->addr_limit), + "r" (untagged_addr(ptr)) : "cc"); csdb(); -- GitLab From 63f0c60379650d82250f22e4cf4137ef3dc4f43d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 23 Jul 2019 19:58:39 +0200 Subject: [PATCH 2092/7155] arm64: Introduce prctl() options to control the tagged user addresses ABI It is not desirable to relax the ABI to allow tagged user addresses into the kernel indiscriminately. This patch introduces a prctl() interface for enabling or disabling the tagged ABI with a global sysctl control for preventing applications from enabling the relaxed ABI (meant for testing user-space prctl() return error checking without reconfiguring the kernel). The ABI properties are inherited by threads of the same application and fork()'ed children but cleared on execve(). A Kconfig option allows the overall disabling of the relaxed ABI. The PR_SET_TAGGED_ADDR_CTRL will be expanded in the future to handle MTE-specific settings like imprecise vs precise exceptions. Reviewed-by: Kees Cook Signed-off-by: Catalin Marinas Signed-off-by: Andrey Konovalov Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 9 ++++ arch/arm64/include/asm/processor.h | 8 +++ arch/arm64/include/asm/thread_info.h | 1 + arch/arm64/include/asm/uaccess.h | 4 +- arch/arm64/kernel/process.c | 73 ++++++++++++++++++++++++++++ include/uapi/linux/prctl.h | 5 ++ kernel/sys.c | 12 +++++ 7 files changed, 111 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3adcec05b1f6..5d254178b9ca 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1110,6 +1110,15 @@ config ARM64_SW_TTBR0_PAN zeroed area and reserved ASID. The user access routines restore the valid TTBR0_EL1 temporarily. +config ARM64_TAGGED_ADDR_ABI + bool "Enable the tagged user addresses syscall ABI" + default y + help + When this option is enabled, user applications can opt in to a + relaxed ABI via prctl() allowing tagged addresses to be passed + to system calls as pointer arguments. For details, see + Documentation/arm64/tagged-address-abi.txt. + menuconfig COMPAT bool "Kernel support for 32-bit EL0" depends on ARM64_4K_PAGES || EXPERT diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 844e2964b0f5..28eed40ffc12 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -306,6 +306,14 @@ extern void __init minsigstksz_setup(void); /* PR_PAC_RESET_KEYS prctl */ #define PAC_RESET_KEYS(tsk, arg) ptrauth_prctl_reset_keys(tsk, arg) +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI +/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */ +long set_tagged_addr_ctrl(unsigned long arg); +long get_tagged_addr_ctrl(void); +#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(arg) +#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl() +#endif + /* * For CONFIG_GCC_PLUGIN_STACKLEAK * diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 180b34ec5965..012238d8e58d 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -90,6 +90,7 @@ void arch_release_task_struct(struct task_struct *tsk); #define TIF_SVE 23 /* Scalable Vector Extension in use */ #define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */ #define TIF_SSBD 25 /* Wants SSB mitigation */ +#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index a138e3b4f717..097d6bfac0b7 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -62,7 +62,9 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si { unsigned long ret, limit = current_thread_info()->addr_limit; - addr = untagged_addr(addr); + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) && + test_thread_flag(TIF_TAGGED_ADDR)) + addr = untagged_addr(addr); __chk_user_ptr(addr); asm volatile( diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index f674f28df663..76b7c55026aa 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -307,11 +309,18 @@ static void tls_thread_flush(void) } } +static void flush_tagged_addr_state(void) +{ + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI)) + clear_thread_flag(TIF_TAGGED_ADDR); +} + void flush_thread(void) { fpsimd_flush_thread(); tls_thread_flush(); flush_ptrace_hw_breakpoint(current); + flush_tagged_addr_state(); } void release_thread(struct task_struct *dead_task) @@ -565,3 +574,67 @@ void arch_setup_new_exec(void) ptrauth_thread_init_user(current); } + +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI +/* + * Control the relaxed ABI allowing tagged user addresses into the kernel. + */ +static unsigned int tagged_addr_prctl_allowed = 1; + +long set_tagged_addr_ctrl(unsigned long arg) +{ + if (!tagged_addr_prctl_allowed) + return -EINVAL; + if (is_compat_task()) + return -EINVAL; + if (arg & ~PR_TAGGED_ADDR_ENABLE) + return -EINVAL; + + update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE); + + return 0; +} + +long get_tagged_addr_ctrl(void) +{ + if (!tagged_addr_prctl_allowed) + return -EINVAL; + if (is_compat_task()) + return -EINVAL; + + if (test_thread_flag(TIF_TAGGED_ADDR)) + return PR_TAGGED_ADDR_ENABLE; + + return 0; +} + +/* + * Global sysctl to disable the tagged user addresses support. This control + * only prevents the tagged address ABI enabling via prctl() and does not + * disable it for tasks that already opted in to the relaxed ABI. + */ +static int zero; +static int one = 1; + +static struct ctl_table tagged_addr_sysctl_table[] = { + { + .procname = "tagged_addr", + .mode = 0644, + .data = &tagged_addr_prctl_allowed, + .maxlen = sizeof(int), + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { } +}; + +static int __init tagged_addr_init(void) +{ + if (!register_sysctl("abi", tagged_addr_sysctl_table)) + return -EINVAL; + return 0; +} + +core_initcall(tagged_addr_init); +#endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 094bb03b9cc2..2e927b3e9d6c 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -229,4 +229,9 @@ struct prctl_mm_map { # define PR_PAC_APDBKEY (1UL << 3) # define PR_PAC_APGAKEY (1UL << 4) +/* Tagged user address controls for arm64 */ +#define PR_SET_TAGGED_ADDR_CTRL 55 +#define PR_GET_TAGGED_ADDR_CTRL 56 +# define PR_TAGGED_ADDR_ENABLE (1UL << 0) + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 2969304c29fe..c6c4d5358bd3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -124,6 +124,12 @@ #ifndef PAC_RESET_KEYS # define PAC_RESET_KEYS(a, b) (-EINVAL) #endif +#ifndef SET_TAGGED_ADDR_CTRL +# define SET_TAGGED_ADDR_CTRL(a) (-EINVAL) +#endif +#ifndef GET_TAGGED_ADDR_CTRL +# define GET_TAGGED_ADDR_CTRL() (-EINVAL) +#endif /* * this is where the system-wide overflow UID and GID are defined, for @@ -2492,6 +2498,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, return -EINVAL; error = PAC_RESET_KEYS(me, arg2); break; + case PR_SET_TAGGED_ADDR_CTRL: + error = SET_TAGGED_ADDR_CTRL(arg2); + break; + case PR_GET_TAGGED_ADDR_CTRL: + error = GET_TAGGED_ADDR_CTRL(); + break; default: error = -EINVAL; break; -- GitLab From 9ce1263033cd2ad393e2ff0df4a1c4ab4992c9df Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 23 Jul 2019 19:58:52 +0200 Subject: [PATCH 2093/7155] selftests, arm64: add a selftest for passing tagged pointers to kernel This patch is a part of a series that extends kernel ABI to allow to pass tagged user pointers (with the top byte set to something else other than 0x00) as syscall arguments. This patch adds a simple test, that calls the uname syscall with a tagged user pointer as an argument. Without the kernel accepting tagged user pointers the test fails with EFAULT. Reviewed-by: Catalin Marinas Acked-by: Kees Cook Signed-off-by: Andrey Konovalov Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/.gitignore | 1 + tools/testing/selftests/arm64/Makefile | 11 +++++++ .../testing/selftests/arm64/run_tags_test.sh | 12 ++++++++ tools/testing/selftests/arm64/tags_test.c | 29 +++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 tools/testing/selftests/arm64/.gitignore create mode 100644 tools/testing/selftests/arm64/Makefile create mode 100755 tools/testing/selftests/arm64/run_tags_test.sh create mode 100644 tools/testing/selftests/arm64/tags_test.c diff --git a/tools/testing/selftests/arm64/.gitignore b/tools/testing/selftests/arm64/.gitignore new file mode 100644 index 000000000000..e8fae8d61ed6 --- /dev/null +++ b/tools/testing/selftests/arm64/.gitignore @@ -0,0 +1 @@ +tags_test diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile new file mode 100644 index 000000000000..a61b2e743e99 --- /dev/null +++ b/tools/testing/selftests/arm64/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 + +# ARCH can be overridden by the user for cross compiling +ARCH ?= $(shell uname -m 2>/dev/null || echo not) + +ifneq (,$(filter $(ARCH),aarch64 arm64)) +TEST_GEN_PROGS := tags_test +TEST_PROGS := run_tags_test.sh +endif + +include ../lib.mk diff --git a/tools/testing/selftests/arm64/run_tags_test.sh b/tools/testing/selftests/arm64/run_tags_test.sh new file mode 100755 index 000000000000..745f11379930 --- /dev/null +++ b/tools/testing/selftests/arm64/run_tags_test.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +echo "--------------------" +echo "running tags test" +echo "--------------------" +./tags_test +if [ $? -ne 0 ]; then + echo "[FAIL]" +else + echo "[PASS]" +fi diff --git a/tools/testing/selftests/arm64/tags_test.c b/tools/testing/selftests/arm64/tags_test.c new file mode 100644 index 000000000000..22a1b266e373 --- /dev/null +++ b/tools/testing/selftests/arm64/tags_test.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include + +#define SHIFT_TAG(tag) ((uint64_t)(tag) << 56) +#define SET_TAG(ptr, tag) (((uint64_t)(ptr) & ~SHIFT_TAG(0xff)) | \ + SHIFT_TAG(tag)) + +int main(void) +{ + static int tbi_enabled = 0; + struct utsname *ptr, *tagged_ptr; + int err; + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) + tbi_enabled = 1; + ptr = (struct utsname *)malloc(sizeof(*ptr)); + if (tbi_enabled) + tagged_ptr = (struct utsname *)SET_TAG(ptr, 0x42); + err = uname(tagged_ptr); + free(ptr); + + return err; +} -- GitLab From c5e5c48c16422521d363c33cfb0dcf58f88c119b Mon Sep 17 00:00:00 2001 From: chenzefeng Date: Tue, 6 Aug 2019 15:46:33 +0800 Subject: [PATCH 2094/7155] ia64:unwind: fix double free for mod->arch.init_unw_table The function free_module in file kernel/module.c as follow: void free_module(struct module *mod) { ...... module_arch_cleanup(mod); ...... module_arch_freeing_init(mod); ...... } Both module_arch_cleanup and module_arch_freeing_init function would free the mod->arch.init_unw_table, which cause double free. Here, set mod->arch.init_unw_table = NULL after remove the unwind table to avoid double free. Signed-off-by: chenzefeng Signed-off-by: Tony Luck --- arch/ia64/kernel/module.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 326448f9df16..1a42ba885188 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -914,10 +914,14 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo void module_arch_cleanup (struct module *mod) { - if (mod->arch.init_unw_table) + if (mod->arch.init_unw_table) { unw_remove_unwind_table(mod->arch.init_unw_table); - if (mod->arch.core_unw_table) + mod->arch.init_unw_table = NULL; + } + if (mod->arch.core_unw_table) { unw_remove_unwind_table(mod->arch.core_unw_table); + mod->arch.core_unw_table = NULL; + } } void *dereference_module_function_descriptor(struct module *mod, void *ptr) -- GitLab From 95e760cbf62755bd3d8999bee1e6579f0ff1425e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 5 Aug 2019 09:29:50 -0700 Subject: [PATCH 2095/7155] kernel-doc: ignore __printf attribute Ignore __printf() function attributes just as other __attribute__ strings are ignored. Fixes this kernel-doc warning message: include/kunit/kunit-stream.h:58: warning: Function parameter or member '2' not described in '__printf' Reported-by: kbuild test robot Signed-off-by: Randy Dunlap Cc: Brendan Higgins Tested-by: Brendan Higgins Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 6b03012750da..32e793ca5e95 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1580,6 +1580,7 @@ sub dump_function($$) { $prototype =~ s/__must_check +//; $prototype =~ s/__weak +//; $prototype =~ s/__sched +//; + $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//; my $define = $prototype =~ s/^#\s*define\s+//; #ak added $prototype =~ s/__attribute__\s*\(\( (?: -- GitLab From ac862503639ff824e0e1f32fbca220ed75261138 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 5 Aug 2019 11:49:51 +0100 Subject: [PATCH 2096/7155] Input: docs: fix spelling mistake "potocol" -> "protocol" There is a minor spelling mistake in the documentation, fix it. Signed-off-by: Colin Ian King Signed-off-by: Jonathan Corbet --- Documentation/input/multi-touch-protocol.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/input/multi-touch-protocol.rst b/Documentation/input/multi-touch-protocol.rst index 6be70342e709..307fe22d9668 100644 --- a/Documentation/input/multi-touch-protocol.rst +++ b/Documentation/input/multi-touch-protocol.rst @@ -23,7 +23,7 @@ devices capable of tracking identifiable contacts (type B), the protocol describes how to send updates for individual contacts via event slots. .. note:: - MT potocol type A is obsolete, all kernel drivers have been + MT protocol type A is obsolete, all kernel drivers have been converted to use type B. Protocol Usage -- GitLab From a4a03bdccfd02eda6613a892fb418f15adeb2b21 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 1 Aug 2019 11:17:50 +0800 Subject: [PATCH 2097/7155] mailmap: add entry for Gao Xiang Add entry to connect all Gao Xiang's email addresses. Signed-off-by: Chao Yu Acked-by: Gao Xiang Signed-off-by: Jonathan Corbet --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 477debe3d960..c4a780a4dff4 100644 --- a/.mailmap +++ b/.mailmap @@ -79,6 +79,8 @@ Frank Rowand Frank Rowand Frank Rowand Frank Zago +Gao Xiang +Gao Xiang Greg Kroah-Hartman Greg Kroah-Hartman Greg Kroah-Hartman -- GitLab From 758f2512546f70fdb70bd1d752d975a09ad9741b Mon Sep 17 00:00:00 2001 From: Todor Tomov Date: Thu, 1 Aug 2019 20:26:03 +0300 Subject: [PATCH 2098/7155] mailmap: Add an entry for my email address My @linaro.org email address doesn't exist anymore so add a mailmap entry to map it to my @gmail.com address. Signed-off-by: Todor Tomov Signed-off-by: Jonathan Corbet --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index c4a780a4dff4..0e6b0b016c49 100644 --- a/.mailmap +++ b/.mailmap @@ -225,6 +225,7 @@ Sumit Semwal Tejun Heo Thomas Graf Thomas Pedersen +Todor Tomov Tony Luck TripleX Chung TripleX Chung -- GitLab From aa48e31b874774bef42fd2b433474202cbe8ac79 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 2 Aug 2019 09:21:35 +0800 Subject: [PATCH 2099/7155] mailmap: add entry for Jaegeuk Kim Add entry to connect all Jaegeuk's email addresses. Acked-by: Jaegeuk Kim Signed-off-by: Chao Yu Signed-off-by: Jonathan Corbet --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index 0e6b0b016c49..ea703abcb397 100644 --- a/.mailmap +++ b/.mailmap @@ -91,6 +91,9 @@ Henrik Kretzschmar Henrik Rydberg Herbert Xu Jacob Shin +Jaegeuk Kim +Jaegeuk Kim +Jaegeuk Kim James Bottomley James Bottomley James E Wilson -- GitLab From e63f3085709e92bd876e2977a07099d56bbda1c2 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 28 Jul 2019 00:22:30 +0200 Subject: [PATCH 2100/7155] pidfd: add pidfd_wait tests Add tests for pidfd_wait() and CLONE_WAIT_PID: - test that waitid(P_PIDFD) fails on /proc/ - test that waitid(P_PIDFD) fails on /dev/null - test that waitid(P_PIDFD) can wait on a pidfd - test that waitid(P_PIDFD) can wait on a pidfd and return siginfo_t - test that waitid(P_PIDFD) works with WEXITED - test that waitid(P_PIDFD) works with WSTOPPED - test that waitid(P_PIDFD) works with WUNTRACED - test that waitid(P_PIDFD) works with WCONTINUED - test that waitid(P_PIDFD) works with WNOWAIT - test that waitid(P_PIDFD)works with WNOHANG Signed-off-by: Christian Brauner Reviewed-by: Kees Cook Cc: Arnd Bergmann Cc: "Eric W. Biederman" Cc: Joel Fernandes (Google) Cc: Thomas Gleixner Cc: David Howells Cc: Jann Horn Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Oleg Nesterov Cc: Aleksa Sarai Cc: Linus Torvalds Cc: Al Viro Link: https://lore.kernel.org/r/20190727222229.6516-3-christian@brauner.io --- tools/testing/selftests/pidfd/.gitignore | 1 + tools/testing/selftests/pidfd/Makefile | 2 +- tools/testing/selftests/pidfd/pidfd.h | 25 ++ tools/testing/selftests/pidfd/pidfd_test.c | 14 -- tools/testing/selftests/pidfd/pidfd_wait.c | 271 +++++++++++++++++++++ 5 files changed, 298 insertions(+), 15 deletions(-) create mode 100644 tools/testing/selftests/pidfd/pidfd_wait.c diff --git a/tools/testing/selftests/pidfd/.gitignore b/tools/testing/selftests/pidfd/.gitignore index 16d84d117bc0..730ef9dc08cc 100644 --- a/tools/testing/selftests/pidfd/.gitignore +++ b/tools/testing/selftests/pidfd/.gitignore @@ -1,2 +1,3 @@ pidfd_open_test pidfd_test +pidfd_wait diff --git a/tools/testing/selftests/pidfd/Makefile b/tools/testing/selftests/pidfd/Makefile index 720b2d884b3c..7c97e890f353 100644 --- a/tools/testing/selftests/pidfd/Makefile +++ b/tools/testing/selftests/pidfd/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS += -g -I../../../../usr/include/ -lpthread -TEST_GEN_PROGS := pidfd_test pidfd_open_test +TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_wait include ../lib.mk diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h index 8452e910463f..7d7d0ca05e0b 100644 --- a/tools/testing/selftests/pidfd/pidfd.h +++ b/tools/testing/selftests/pidfd/pidfd.h @@ -16,6 +16,26 @@ #include "../kselftest.h" +#ifndef P_PIDFD +#define P_PIDFD 3 +#endif + +#ifndef CLONE_PIDFD +#define CLONE_PIDFD 0x00001000 +#endif + +#ifndef __NR_pidfd_open +#define __NR_pidfd_open -1 +#endif + +#ifndef __NR_pidfd_send_signal +#define __NR_pidfd_send_signal -1 +#endif + +#ifndef __NR_clone3 +#define __NR_clone3 -1 +#endif + /* * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c * That means, when it wraps around any pid < 300 will be skipped. @@ -53,5 +73,10 @@ int wait_for_pid(pid_t pid) return WEXITSTATUS(status); } +static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, + unsigned int flags) +{ + return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); +} #endif /* __PIDFD_H */ diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c index 7eaa8a3de262..42e3eb494d72 100644 --- a/tools/testing/selftests/pidfd/pidfd_test.c +++ b/tools/testing/selftests/pidfd/pidfd_test.c @@ -21,20 +21,12 @@ #include "pidfd.h" #include "../kselftest.h" -#ifndef __NR_pidfd_send_signal -#define __NR_pidfd_send_signal -1 -#endif - #define str(s) _str(s) #define _str(s) #s #define CHILD_THREAD_MIN_WAIT 3 /* seconds */ #define MAX_EVENTS 5 -#ifndef CLONE_PIDFD -#define CLONE_PIDFD 0x00001000 -#endif - static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *)) { size_t stack_size = 1024; @@ -47,12 +39,6 @@ static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *)) #endif } -static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, - unsigned int flags) -{ - return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); -} - static int signal_received; static void set_signal_received_on_sigusr1(int sig) diff --git a/tools/testing/selftests/pidfd/pidfd_wait.c b/tools/testing/selftests/pidfd/pidfd_wait.c new file mode 100644 index 000000000000..7079f8eef792 --- /dev/null +++ b/tools/testing/selftests/pidfd/pidfd_wait.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pidfd.h" +#include "../kselftest.h" + +#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) + +static pid_t sys_clone3(struct clone_args *args) +{ + return syscall(__NR_clone3, args, sizeof(struct clone_args)); +} + +static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options, + struct rusage *ru) +{ + return syscall(__NR_waitid, which, pid, info, options, ru); +} + +static int test_pidfd_wait_simple(void) +{ + const char *test_name = "pidfd wait simple"; + int pidfd = -1, status = 0; + pid_t parent_tid = -1; + struct clone_args args = { + .parent_tid = ptr_to_u64(&parent_tid), + .pidfd = ptr_to_u64(&pidfd), + .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, + .exit_signal = SIGCHLD, + }; + int ret; + pid_t pid; + siginfo_t info = { + .si_signo = 0, + }; + + pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC); + if (pidfd < 0) + ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n", + test_name, strerror(errno)); + + pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL); + if (pid == 0) + ksft_exit_fail_msg( + "%s test: succeeded to wait on invalid pidfd %s\n", + test_name, strerror(errno)); + close(pidfd); + pidfd = -1; + + pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC); + if (pidfd == 0) + ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n", + test_name, strerror(errno)); + + pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL); + if (pid == 0) + ksft_exit_fail_msg( + "%s test: succeeded to wait on invalid pidfd %s\n", + test_name, strerror(errno)); + close(pidfd); + pidfd = -1; + + pid = sys_clone3(&args); + if (pid < 0) + ksft_exit_fail_msg("%s test: failed to create new process %s\n", + test_name, strerror(errno)); + + if (pid == 0) + exit(EXIT_SUCCESS); + + pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL); + if (pid < 0) + ksft_exit_fail_msg( + "%s test: failed to wait on process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status)) + ksft_exit_fail_msg( + "%s test: unexpected status received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + close(pidfd); + + if (info.si_signo != SIGCHLD) + ksft_exit_fail_msg( + "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_signo, parent_tid, pidfd, + strerror(errno)); + + if (info.si_code != CLD_EXITED) + ksft_exit_fail_msg( + "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_code, parent_tid, pidfd, + strerror(errno)); + + if (info.si_pid != parent_tid) + ksft_exit_fail_msg( + "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_pid, parent_tid, pidfd, + strerror(errno)); + + ksft_test_result_pass("%s test: Passed\n", test_name); + return 0; +} + +static int test_pidfd_wait_states(void) +{ + const char *test_name = "pidfd wait states"; + int pidfd = -1, status = 0; + pid_t parent_tid = -1; + struct clone_args args = { + .parent_tid = ptr_to_u64(&parent_tid), + .pidfd = ptr_to_u64(&pidfd), + .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, + .exit_signal = SIGCHLD, + }; + int ret; + pid_t pid; + siginfo_t info = { + .si_signo = 0, + }; + + pid = sys_clone3(&args); + if (pid < 0) + ksft_exit_fail_msg("%s test: failed to create new process %s\n", + test_name, strerror(errno)); + + if (pid == 0) { + kill(getpid(), SIGSTOP); + kill(getpid(), SIGSTOP); + exit(EXIT_SUCCESS); + } + + ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to wait on WSTOPPED process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + if (info.si_signo != SIGCHLD) + ksft_exit_fail_msg( + "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_signo, parent_tid, pidfd, + strerror(errno)); + + if (info.si_code != CLD_STOPPED) + ksft_exit_fail_msg( + "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_code, parent_tid, pidfd, + strerror(errno)); + + if (info.si_pid != parent_tid) + ksft_exit_fail_msg( + "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_pid, parent_tid, pidfd, + strerror(errno)); + + ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to send signal to process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to wait WCONTINUED on process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + if (info.si_signo != SIGCHLD) + ksft_exit_fail_msg( + "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_signo, parent_tid, pidfd, + strerror(errno)); + + if (info.si_code != CLD_CONTINUED) + ksft_exit_fail_msg( + "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_code, parent_tid, pidfd, + strerror(errno)); + + if (info.si_pid != parent_tid) + ksft_exit_fail_msg( + "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_pid, parent_tid, pidfd, + strerror(errno)); + + ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to wait on WUNTRACED process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + if (info.si_signo != SIGCHLD) + ksft_exit_fail_msg( + "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_signo, parent_tid, pidfd, + strerror(errno)); + + if (info.si_code != CLD_STOPPED) + ksft_exit_fail_msg( + "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_code, parent_tid, pidfd, + strerror(errno)); + + if (info.si_pid != parent_tid) + ksft_exit_fail_msg( + "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_pid, parent_tid, pidfd, + strerror(errno)); + + ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to send SIGKILL to process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL); + if (ret < 0) + ksft_exit_fail_msg( + "%s test: failed to wait on WEXITED process with pid %d and pidfd %d: %s\n", + test_name, parent_tid, pidfd, strerror(errno)); + + if (info.si_signo != SIGCHLD) + ksft_exit_fail_msg( + "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_signo, parent_tid, pidfd, + strerror(errno)); + + if (info.si_code != CLD_KILLED) + ksft_exit_fail_msg( + "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_code, parent_tid, pidfd, + strerror(errno)); + + if (info.si_pid != parent_tid) + ksft_exit_fail_msg( + "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n", + test_name, info.si_pid, parent_tid, pidfd, + strerror(errno)); + + close(pidfd); + + ksft_test_result_pass("%s test: Passed\n", test_name); + return 0; +} + +int main(int argc, char **argv) +{ + ksft_print_header(); + ksft_set_plan(2); + + test_pidfd_wait_simple(); + test_pidfd_wait_states(); + + return ksft_exit_pass(); +} -- GitLab From 2ec2f99abd2c75b507410c5def731fe1b483271b Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Fri, 26 Jul 2019 09:22:25 -0700 Subject: [PATCH 2101/7155] tests: move common definitions and functions into pidfd.h Move definitions and functions used across different pidfd tests into pidfd.h header. Signed-off-by: Suren Baghdasaryan Reviewed-by: Christian Brauner Link: https://lore.kernel.org/r/20190726162226.252750-1-surenb@google.com Signed-off-by: Christian Brauner --- tools/testing/selftests/pidfd/pidfd.h | 5 +++++ tools/testing/selftests/pidfd/pidfd_open_test.c | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h index 7d7d0ca05e0b..c6bc68329f4b 100644 --- a/tools/testing/selftests/pidfd/pidfd.h +++ b/tools/testing/selftests/pidfd/pidfd.h @@ -73,6 +73,11 @@ int wait_for_pid(pid_t pid) return WEXITSTATUS(status); } +static inline int sys_pidfd_open(pid_t pid, unsigned int flags) +{ + return syscall(__NR_pidfd_open, pid, flags); +} + static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) { diff --git a/tools/testing/selftests/pidfd/pidfd_open_test.c b/tools/testing/selftests/pidfd/pidfd_open_test.c index 0377133dd6dc..b9fe75fc3e51 100644 --- a/tools/testing/selftests/pidfd/pidfd_open_test.c +++ b/tools/testing/selftests/pidfd/pidfd_open_test.c @@ -22,11 +22,6 @@ #include "pidfd.h" #include "../kselftest.h" -static inline int sys_pidfd_open(pid_t pid, unsigned int flags) -{ - return syscall(__NR_pidfd_open, pid, flags); -} - static int safe_int(const char *numstr, int *converted) { char *err = NULL; -- GitLab From aed5a8df3dbbd804409d40f821e0768891cfd5ab Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Fri, 26 Jul 2019 09:22:26 -0700 Subject: [PATCH 2102/7155] tests: add pidfd poll tests This adds testing for polling on pidfd of a process being killed. Test runs 10000 iterations by default to stress test pidfd polling functionality. It accepts an optional command-line parameter to override the number or iterations to run. Specifically, it tests for: - pidfd_open on a child process succeeds - pidfd_send_signal on a child process succeeds - polling on pidfd succeeds and returns exactly one event - returned event is POLLIN - event is received within 3 secs of the process being killed 10000 iterations was chosen because of the race condition being tested which is not consistently reproducible but usually is revealed after less than 2000 iterations. Reveals race fixed by commit b191d6491be6 ("pidfd: fix a poll race when setting exit_state") Signed-off-by: Suren Baghdasaryan Link: https://lore.kernel.org/r/20190726162226.252750-2-surenb@google.com Signed-off-by: Christian Brauner --- tools/testing/selftests/pidfd/.gitignore | 1 + tools/testing/selftests/pidfd/Makefile | 2 +- .../testing/selftests/pidfd/pidfd_poll_test.c | 117 ++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/pidfd/pidfd_poll_test.c diff --git a/tools/testing/selftests/pidfd/.gitignore b/tools/testing/selftests/pidfd/.gitignore index 730ef9dc08cc..8d069490e17b 100644 --- a/tools/testing/selftests/pidfd/.gitignore +++ b/tools/testing/selftests/pidfd/.gitignore @@ -1,3 +1,4 @@ pidfd_open_test +pidfd_poll_test pidfd_test pidfd_wait diff --git a/tools/testing/selftests/pidfd/Makefile b/tools/testing/selftests/pidfd/Makefile index 7c97e890f353..464c9b76148f 100644 --- a/tools/testing/selftests/pidfd/Makefile +++ b/tools/testing/selftests/pidfd/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS += -g -I../../../../usr/include/ -lpthread -TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_wait +TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_poll_test pidfd_wait include ../lib.mk diff --git a/tools/testing/selftests/pidfd/pidfd_poll_test.c b/tools/testing/selftests/pidfd/pidfd_poll_test.c new file mode 100644 index 000000000000..4b115444dfe9 --- /dev/null +++ b/tools/testing/selftests/pidfd/pidfd_poll_test.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pidfd.h" +#include "../kselftest.h" + +static bool timeout; + +static void handle_alarm(int sig) +{ + timeout = true; +} + +int main(int argc, char **argv) +{ + struct pollfd fds; + int iter, nevents; + int nr_iterations = 10000; + + fds.events = POLLIN; + + if (argc > 2) + ksft_exit_fail_msg("Unexpected command line argument\n"); + + if (argc == 2) { + nr_iterations = atoi(argv[1]); + if (nr_iterations <= 0) + ksft_exit_fail_msg("invalid input parameter %s\n", + argv[1]); + } + + ksft_print_msg("running pidfd poll test for %d iterations\n", + nr_iterations); + + for (iter = 0; iter < nr_iterations; iter++) { + int pidfd; + int child_pid = fork(); + + if (child_pid < 0) { + if (errno == EAGAIN) { + iter--; + continue; + } + ksft_exit_fail_msg( + "%s - failed to fork a child process\n", + strerror(errno)); + } + + if (child_pid == 0) { + /* Child process just sleeps for a min and exits */ + sleep(60); + exit(EXIT_SUCCESS); + } + + /* Parent kills the child and waits for its death */ + pidfd = sys_pidfd_open(child_pid, 0); + if (pidfd < 0) + ksft_exit_fail_msg("%s - pidfd_open failed\n", + strerror(errno)); + + /* Setup 3 sec alarm - plenty of time */ + if (signal(SIGALRM, handle_alarm) == SIG_ERR) + ksft_exit_fail_msg("%s - signal failed\n", + strerror(errno)); + alarm(3); + + /* Send SIGKILL to the child */ + if (sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0)) + ksft_exit_fail_msg("%s - pidfd_send_signal failed\n", + strerror(errno)); + + /* Wait for the death notification */ + fds.fd = pidfd; + nevents = poll(&fds, 1, -1); + + /* Check for error conditions */ + if (nevents < 0) + ksft_exit_fail_msg("%s - poll failed\n", + strerror(errno)); + + if (nevents != 1) + ksft_exit_fail_msg("unexpected poll result: %d\n", + nevents); + + if (!(fds.revents & POLLIN)) + ksft_exit_fail_msg( + "unexpected event type received: 0x%x\n", + fds.revents); + + if (timeout) + ksft_exit_fail_msg( + "death notification wait timeout\n"); + + close(pidfd); + /* Wait for child to prevent zombies */ + if (waitpid(child_pid, NULL, 0) < 0) + ksft_exit_fail_msg("%s - waitpid failed\n", + strerror(errno)); + + } + + ksft_test_result_pass("pidfd poll test: pass\n"); + return ksft_exit_pass(); +} -- GitLab From ffc60b55d9ccd9950a77686d14da69eb6e437394 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 6 Aug 2019 15:06:07 +0200 Subject: [PATCH 2103/7155] net: dsa: ksz: Remove dead code and fix warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove ksz_port_cleanup(), which is unused. Add missing include "ksz_common.h", which fixes the following warning when built with make ... W=1 drivers/net/dsa/microchip/ksz_common.c:23:6: warning: no previous prototype for ‘...’ [-Wmissing-prototypes] Note that the order of the headers cannot be swapped, as that would trigger missing forward declaration errors, which would indicate the way forward is to merge the two headers into one. Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz_common.c | 11 +---------- drivers/net/dsa/microchip/ksz_common.h | 1 - 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index ce20cc90f9ef..a1e6e560fde8 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -19,16 +19,7 @@ #include #include "ksz_priv.h" - -void ksz_port_cleanup(struct ksz_device *dev, int port) -{ - /* Common code for port cleanup. */ - mutex_lock(&dev->dev_mutex); - dev->on_ports &= ~(1 << port); - dev->live_ports &= ~(1 << port); - mutex_unlock(&dev->dev_mutex); -} -EXPORT_SYMBOL_GPL(ksz_port_cleanup); +#include "ksz_common.h" void ksz_update_port_member(struct ksz_device *dev, int port) { diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 84fed4a2578b..9f9ff0fb3b53 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -9,7 +9,6 @@ #include -void ksz_port_cleanup(struct ksz_device *dev, int port); void ksz_update_port_member(struct ksz_device *dev, int port); void ksz_init_mib_timer(struct ksz_device *dev); -- GitLab From 6a7abc610250b28675e98e0bf2fb5634d810c8d5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 6 Aug 2019 15:06:08 +0200 Subject: [PATCH 2104/7155] net: dsa: ksz: Merge ksz_priv.h into ksz_common.h Merge the two headers into one, no functional change. Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz8795.c | 1 - drivers/net/dsa/microchip/ksz8795_spi.c | 1 - drivers/net/dsa/microchip/ksz9477.c | 1 - drivers/net/dsa/microchip/ksz9477_spi.c | 1 - drivers/net/dsa/microchip/ksz_common.c | 1 - drivers/net/dsa/microchip/ksz_common.h | 144 ++++++++++++++++++++++ drivers/net/dsa/microchip/ksz_priv.h | 156 ------------------------ 7 files changed, 144 insertions(+), 161 deletions(-) delete mode 100644 drivers/net/dsa/microchip/ksz_priv.h diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index ae80b3c6dea2..a23d3ffdf0c4 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -18,7 +18,6 @@ #include #include -#include "ksz_priv.h" #include "ksz_common.h" #include "ksz8795_reg.h" diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index 50aa0d24effb..d0f8153e86b7 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -14,7 +14,6 @@ #include #include -#include "ksz_priv.h" #include "ksz_common.h" #define SPI_ADDR_SHIFT 12 diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index a8c97f7a79b7..187be42de5f1 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -14,7 +14,6 @@ #include #include -#include "ksz_priv.h" #include "ksz9477_reg.h" #include "ksz_common.h" diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index 5a9e27b337a8..a226b389e12d 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -13,7 +13,6 @@ #include #include -#include "ksz_priv.h" #include "ksz_common.h" #define SPI_ADDR_SHIFT 24 diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a1e6e560fde8..b45c7b972cec 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -18,7 +18,6 @@ #include #include -#include "ksz_priv.h" #include "ksz_common.h" void ksz_update_port_member(struct ksz_device *dev, int port) diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 9f9ff0fb3b53..c44a8d23d973 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -7,7 +7,151 @@ #ifndef __KSZ_COMMON_H #define __KSZ_COMMON_H +#include +#include +#include +#include #include +#include + +struct vlan_table { + u32 table[3]; +}; + +struct ksz_port_mib { + struct mutex cnt_mutex; /* structure access */ + u8 cnt_ptr; + u64 *counters; +}; + +struct ksz_port { + u16 member; + u16 vid_member; + int stp_state; + struct phy_device phydev; + + u32 on:1; /* port is not disabled by hardware */ + u32 phy:1; /* port has a PHY */ + u32 fiber:1; /* port is fiber */ + u32 sgmii:1; /* port is SGMII */ + u32 force:1; + u32 read:1; /* read MIB counters in background */ + u32 freeze:1; /* MIB counter freeze is enabled */ + + struct ksz_port_mib mib; +}; + +struct ksz_device { + struct dsa_switch *ds; + struct ksz_platform_data *pdata; + const char *name; + + struct mutex dev_mutex; /* device access */ + struct mutex stats_mutex; /* status access */ + struct mutex alu_mutex; /* ALU access */ + struct mutex vlan_mutex; /* vlan access */ + const struct ksz_dev_ops *dev_ops; + + struct device *dev; + struct regmap *regmap[3]; + + void *priv; + + struct gpio_desc *reset_gpio; /* Optional reset GPIO */ + + /* chip specific data */ + u32 chip_id; + int num_vlans; + int num_alus; + int num_statics; + int cpu_port; /* port connected to CPU */ + int cpu_ports; /* port bitmap can be cpu port */ + int phy_port_cnt; + int port_cnt; + int reg_mib_cnt; + int mib_cnt; + int mib_port_cnt; + int last_port; /* ports after that not used */ + phy_interface_t interface; + u32 regs_size; + bool phy_errata_9477; + bool synclko_125; + + struct vlan_table *vlan_cache; + + struct ksz_port *ports; + struct timer_list mib_read_timer; + struct work_struct mib_read; + unsigned long mib_read_interval; + u16 br_member; + u16 member; + u16 live_ports; + u16 on_ports; /* ports enabled by DSA */ + u16 rx_ports; + u16 tx_ports; + u16 mirror_rx; + u16 mirror_tx; + u32 features; /* chip specific features */ + u32 overrides; /* chip functions set by user */ + u16 host_mask; + u16 port_mask; +}; + +struct alu_struct { + /* entry 1 */ + u8 is_static:1; + u8 is_src_filter:1; + u8 is_dst_filter:1; + u8 prio_age:3; + u32 _reserv_0_1:23; + u8 mstp:3; + /* entry 2 */ + u8 is_override:1; + u8 is_use_fid:1; + u32 _reserv_1_1:23; + u8 port_forward:7; + /* entry 3 & 4*/ + u32 _reserv_2_1:9; + u8 fid:7; + u8 mac[ETH_ALEN]; +}; + +struct ksz_dev_ops { + u32 (*get_port_addr)(int port, int offset); + void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); + void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); + void (*phy_setup)(struct ksz_device *dev, int port, + struct phy_device *phy); + void (*port_cleanup)(struct ksz_device *dev, int port); + void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); + void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); + void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); + int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr, + u8 *fid, u8 *src_port, u8 *timestamp, + u16 *entries); + int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr, + struct alu_struct *alu); + void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr, + struct alu_struct *alu); + void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr, + u64 *cnt); + void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt); + void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); + void (*port_init_cnt)(struct ksz_device *dev, int port); + int (*shutdown)(struct ksz_device *dev); + int (*detect)(struct ksz_device *dev); + int (*init)(struct ksz_device *dev); + void (*exit)(struct ksz_device *dev); +}; + +struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); +int ksz_switch_register(struct ksz_device *dev, + const struct ksz_dev_ops *ops); +void ksz_switch_remove(struct ksz_device *dev); + +int ksz8795_switch_register(struct ksz_device *dev); +int ksz9477_switch_register(struct ksz_device *dev); void ksz_update_port_member(struct ksz_device *dev, int port); void ksz_init_mib_timer(struct ksz_device *dev); diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h deleted file mode 100644 index 44c16aaf775c..000000000000 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ /dev/null @@ -1,156 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Microchip KSZ series switch common definitions - * - * Copyright (C) 2017-2019 Microchip Technology Inc. - */ - -#ifndef __KSZ_PRIV_H -#define __KSZ_PRIV_H - -#include -#include -#include -#include -#include - -struct vlan_table { - u32 table[3]; -}; - -struct ksz_port_mib { - struct mutex cnt_mutex; /* structure access */ - u8 cnt_ptr; - u64 *counters; -}; - -struct ksz_port { - u16 member; - u16 vid_member; - int stp_state; - struct phy_device phydev; - - u32 on:1; /* port is not disabled by hardware */ - u32 phy:1; /* port has a PHY */ - u32 fiber:1; /* port is fiber */ - u32 sgmii:1; /* port is SGMII */ - u32 force:1; - u32 read:1; /* read MIB counters in background */ - u32 freeze:1; /* MIB counter freeze is enabled */ - - struct ksz_port_mib mib; -}; - -struct ksz_device { - struct dsa_switch *ds; - struct ksz_platform_data *pdata; - const char *name; - - struct mutex dev_mutex; /* device access */ - struct mutex stats_mutex; /* status access */ - struct mutex alu_mutex; /* ALU access */ - struct mutex vlan_mutex; /* vlan access */ - const struct ksz_dev_ops *dev_ops; - - struct device *dev; - struct regmap *regmap[3]; - - void *priv; - - struct gpio_desc *reset_gpio; /* Optional reset GPIO */ - - /* chip specific data */ - u32 chip_id; - int num_vlans; - int num_alus; - int num_statics; - int cpu_port; /* port connected to CPU */ - int cpu_ports; /* port bitmap can be cpu port */ - int phy_port_cnt; - int port_cnt; - int reg_mib_cnt; - int mib_cnt; - int mib_port_cnt; - int last_port; /* ports after that not used */ - phy_interface_t interface; - u32 regs_size; - bool phy_errata_9477; - bool synclko_125; - - struct vlan_table *vlan_cache; - - struct ksz_port *ports; - struct timer_list mib_read_timer; - struct work_struct mib_read; - unsigned long mib_read_interval; - u16 br_member; - u16 member; - u16 live_ports; - u16 on_ports; /* ports enabled by DSA */ - u16 rx_ports; - u16 tx_ports; - u16 mirror_rx; - u16 mirror_tx; - u32 features; /* chip specific features */ - u32 overrides; /* chip functions set by user */ - u16 host_mask; - u16 port_mask; -}; - -struct alu_struct { - /* entry 1 */ - u8 is_static:1; - u8 is_src_filter:1; - u8 is_dst_filter:1; - u8 prio_age:3; - u32 _reserv_0_1:23; - u8 mstp:3; - /* entry 2 */ - u8 is_override:1; - u8 is_use_fid:1; - u32 _reserv_1_1:23; - u8 port_forward:7; - /* entry 3 & 4*/ - u32 _reserv_2_1:9; - u8 fid:7; - u8 mac[ETH_ALEN]; -}; - -struct ksz_dev_ops { - u32 (*get_port_addr)(int port, int offset); - void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); - void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); - void (*phy_setup)(struct ksz_device *dev, int port, - struct phy_device *phy); - void (*port_cleanup)(struct ksz_device *dev, int port); - void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); - void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); - void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); - int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr, - u8 *fid, u8 *src_port, u8 *timestamp, - u16 *entries); - int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr, - struct alu_struct *alu); - void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr, - struct alu_struct *alu); - void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr, - u64 *cnt); - void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, - u64 *dropped, u64 *cnt); - void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); - void (*port_init_cnt)(struct ksz_device *dev, int port); - int (*shutdown)(struct ksz_device *dev); - int (*detect)(struct ksz_device *dev); - int (*init)(struct ksz_device *dev); - void (*exit)(struct ksz_device *dev); -}; - -struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); -int ksz_switch_register(struct ksz_device *dev, - const struct ksz_dev_ops *ops); -void ksz_switch_remove(struct ksz_device *dev); - -int ksz8795_switch_register(struct ksz_device *dev); -int ksz9477_switch_register(struct ksz_device *dev); - -#endif -- GitLab From 267df70fe81b0b89502ca23ca7aeb9409ec45bdf Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 6 Aug 2019 15:06:09 +0200 Subject: [PATCH 2105/7155] net: dsa: ksz: Drop NET_DSA_TAG_KSZ9477 This Kconfig option is unused, drop it. Signed-off-by: Marek Vasut Cc: Andrew Lunn Cc: David S. Miller Cc: Florian Fainelli Cc: Tristram Ha Cc: Vivien Didelot Cc: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/Kconfig | 1 - net/dsa/Kconfig | 7 ------- 2 files changed, 8 deletions(-) diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig index 5e4f74286ea3..e1c23d1e91e6 100644 --- a/drivers/net/dsa/microchip/Kconfig +++ b/drivers/net/dsa/microchip/Kconfig @@ -5,7 +5,6 @@ config NET_DSA_MICROCHIP_KSZ_COMMON menuconfig NET_DSA_MICROCHIP_KSZ9477 tristate "Microchip KSZ9477 series switch support" depends on NET_DSA - select NET_DSA_TAG_KSZ9477 select NET_DSA_MICROCHIP_KSZ_COMMON help This driver adds support for Microchip KSZ9477 switch chips. diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 6e942dda1bcd..2f69d4b53d46 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -84,13 +84,6 @@ config NET_DSA_TAG_KSZ Say Y if you want to enable support for tagging frames for the Microchip 9893 family of switches. -config NET_DSA_TAG_KSZ9477 - tristate "Tag driver for Microchip 9477 family of switches" - select NET_DSA_TAG_KSZ_COMMON - help - Say Y if you want to enable support for tagging frames for the - Microchip 9477 family of switches. - config NET_DSA_TAG_QCA tristate "Tag driver for Qualcomm Atheros QCA8K switches" help -- GitLab From 2230a7ef5198632bdbf844fcf0abdd7958a6ac7d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:51 +0300 Subject: [PATCH 2106/7155] drop_monitor: Use correct error code The error code 'ENOTSUPP' is reserved for use with NFS. Use 'EOPNOTSUPP' instead. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 4ea4347f5062..dcb4d2aeb2a8 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -298,7 +298,7 @@ static int set_all_monitor_traces(int state) static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { - return -ENOTSUPP; + return -EOPNOTSUPP; } static int net_dm_cmd_trace(struct sk_buff *skb, @@ -311,7 +311,7 @@ static int net_dm_cmd_trace(struct sk_buff *skb, return set_all_monitor_traces(TRACE_OFF); } - return -ENOTSUPP; + return -EOPNOTSUPP; } static int dropmon_net_event(struct notifier_block *ev_block, -- GitLab From dbf896b70d4a4bdbd10aec060af42d7c70e6a88d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:52 +0300 Subject: [PATCH 2107/7155] drop_monitor: Rename and document scope of mutex The 'trace_state_mutex' does not only protect the global 'trace_state' variable, but also the global 'hw_stats_list'. Subsequent patches are going add more operations from user space to drop_monitor and these all need to be mutually exclusive. Rename 'trace_state_mutex' to the more fitting 'net_dm_mutex' name and document its scope. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index dcb4d2aeb2a8..000ec8b66d1e 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -43,7 +43,13 @@ * netlink alerts */ static int trace_state = TRACE_OFF; -static DEFINE_MUTEX(trace_state_mutex); + +/* net_dm_mutex + * + * An overall lock guarding every operation coming from userspace. + * It also guards the global 'hw_stats_list' list. + */ +static DEFINE_MUTEX(net_dm_mutex); struct per_cpu_dm_data { spinlock_t lock; @@ -241,7 +247,7 @@ static int set_all_monitor_traces(int state) struct dm_hw_stat_delta *new_stat = NULL; struct dm_hw_stat_delta *temp; - mutex_lock(&trace_state_mutex); + mutex_lock(&net_dm_mutex); if (state == trace_state) { rc = -EAGAIN; @@ -289,7 +295,7 @@ static int set_all_monitor_traces(int state) rc = -EINPROGRESS; out_unlock: - mutex_unlock(&trace_state_mutex); + mutex_unlock(&net_dm_mutex); return rc; } @@ -330,12 +336,12 @@ static int dropmon_net_event(struct notifier_block *ev_block, new_stat->dev = dev; new_stat->last_rx = jiffies; - mutex_lock(&trace_state_mutex); + mutex_lock(&net_dm_mutex); list_add_rcu(&new_stat->list, &hw_stats_list); - mutex_unlock(&trace_state_mutex); + mutex_unlock(&net_dm_mutex); break; case NETDEV_UNREGISTER: - mutex_lock(&trace_state_mutex); + mutex_lock(&net_dm_mutex); list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) { if (new_stat->dev == dev) { new_stat->dev = NULL; @@ -346,7 +352,7 @@ static int dropmon_net_event(struct notifier_block *ev_block, } } } - mutex_unlock(&trace_state_mutex); + mutex_unlock(&net_dm_mutex); break; } out: -- GitLab From 01921d53f870653f04ebf8d3c375029ee3ca4a31 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:53 +0300 Subject: [PATCH 2108/7155] drop_monitor: Document scope of spinlock While 'per_cpu_dm_data' is a per-CPU variable, its 'skb' and 'send_timer' fields can be accessed concurrently by the CPU sending the netlink notification to user space from the workqueue and the CPU tracing kfree_skb(). This spinlock is meant to protect against that. Document its scope and suppress the checkpatch message "spinlock_t definition without comment". Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 000ec8b66d1e..35d31b007da4 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -52,7 +52,7 @@ static int trace_state = TRACE_OFF; static DEFINE_MUTEX(net_dm_mutex); struct per_cpu_dm_data { - spinlock_t lock; + spinlock_t lock; /* Protects 'skb' and 'send_timer' */ struct sk_buff *skb; struct work_struct dm_alert_work; struct timer_list send_timer; -- GitLab From ff3818ca39c9f9ce07c4d50db594b9673dfa422c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:54 +0300 Subject: [PATCH 2109/7155] drop_monitor: Avoid multiple blank lines Remove multiple blank lines which are visually annoying and useless. This suppresses the "Please don't use multiple blank lines" checkpatch messages. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 35d31b007da4..9080e62245b9 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -300,7 +300,6 @@ static int set_all_monitor_traces(int state) return rc; } - static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { @@ -427,7 +426,6 @@ static int __init init_net_drop_monitor(void) reset_per_cpu_data(data); } - goto out; out_unreg: -- GitLab From 965100966efe85e636178166fbf006e9b74f78d4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:55 +0300 Subject: [PATCH 2110/7155] drop_monitor: Add extack support Add various extack messages to make drop_monitor more user friendly. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 9080e62245b9..1d463c0d4bc5 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -241,7 +241,7 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi, rcu_read_unlock(); } -static int set_all_monitor_traces(int state) +static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) { int rc = 0; struct dm_hw_stat_delta *new_stat = NULL; @@ -250,6 +250,7 @@ static int set_all_monitor_traces(int state) mutex_lock(&net_dm_mutex); if (state == trace_state) { + NL_SET_ERR_MSG_MOD(extack, "Trace state already set to requested state"); rc = -EAGAIN; goto out_unlock; } @@ -257,6 +258,7 @@ static int set_all_monitor_traces(int state) switch (state) { case TRACE_ON: if (!try_module_get(THIS_MODULE)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to take reference on module"); rc = -ENODEV; break; } @@ -303,6 +305,8 @@ static int set_all_monitor_traces(int state) static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { + NL_SET_ERR_MSG_MOD(info->extack, "Command not supported"); + return -EOPNOTSUPP; } @@ -311,9 +315,9 @@ static int net_dm_cmd_trace(struct sk_buff *skb, { switch (info->genlhdr->cmd) { case NET_DM_CMD_START: - return set_all_monitor_traces(TRACE_ON); + return set_all_monitor_traces(TRACE_ON, info->extack); case NET_DM_CMD_STOP: - return set_all_monitor_traces(TRACE_OFF); + return set_all_monitor_traces(TRACE_OFF, info->extack); } return -EOPNOTSUPP; -- GitLab From b19d955055480ac4e03f5afec0ca80f0de7b7013 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 6 Aug 2019 16:19:56 +0300 Subject: [PATCH 2111/7155] drop_monitor: Use pre_doit / post_doit hooks Each operation from user space should be protected by the global drop monitor mutex. Use the pre_doit / post_doit hooks to take / release the lock instead of doing it explicitly in each function. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 1d463c0d4bc5..4deb86f990f1 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -247,12 +247,9 @@ static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) struct dm_hw_stat_delta *new_stat = NULL; struct dm_hw_stat_delta *temp; - mutex_lock(&net_dm_mutex); - if (state == trace_state) { NL_SET_ERR_MSG_MOD(extack, "Trace state already set to requested state"); - rc = -EAGAIN; - goto out_unlock; + return -EAGAIN; } switch (state) { @@ -296,9 +293,6 @@ static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) else rc = -EINPROGRESS; -out_unlock: - mutex_unlock(&net_dm_mutex); - return rc; } @@ -380,10 +374,26 @@ static const struct genl_ops dropmon_ops[] = { }, }; +static int net_dm_nl_pre_doit(const struct genl_ops *ops, + struct sk_buff *skb, struct genl_info *info) +{ + mutex_lock(&net_dm_mutex); + + return 0; +} + +static void net_dm_nl_post_doit(const struct genl_ops *ops, + struct sk_buff *skb, struct genl_info *info) +{ + mutex_unlock(&net_dm_mutex); +} + static struct genl_family net_drop_monitor_family __ro_after_init = { .hdrsize = 0, .name = "NET_DM", .version = 2, + .pre_doit = net_dm_nl_pre_doit, + .post_doit = net_dm_nl_post_doit, .module = THIS_MODULE, .ops = dropmon_ops, .n_ops = ARRAY_SIZE(dropmon_ops), -- GitLab From 694a296024d4cd5e637fa679c4c7e4c63a7c24f3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 2 Aug 2019 16:13:16 +0100 Subject: [PATCH 2112/7155] net/mlx5: remove self-assignment on esw->dev There is a self assignment of esw->dev to itself, clean this up by removing it. Also make dev a const pointer. Addresses-Coverity: ("Self assignment") Fixes: 6cedde451399 ("net/mlx5: E-Switch, Verify support QoS element type") Signed-off-by: Colin Ian King Reviewed-by: Parav Pandit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d4465dd18c11..81e03e493a01 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1413,7 +1413,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw, static bool element_type_supported(struct mlx5_eswitch *esw, int type) { - struct mlx5_core_dev *dev = esw->dev = esw->dev; + const struct mlx5_core_dev *dev = esw->dev; switch (type) { case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR: -- GitLab From 48e2331197b82c425e12ab728bb5332e49c78f63 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 2 Aug 2019 15:34:55 -0400 Subject: [PATCH 2113/7155] net: dsa: dump CPU port regs through master Merge the CPU port registers dump into the master interface registers dump through ethtool, by nesting the ethtool_drvinfo and ethtool_regs structures of the CPU port into the dump. drvinfo->regdump_len will contain the full data length, while regs->len will contain only the master interface registers dump length. This allows for example to dump the CPU port registers on a ZII Dev C board like this: # ethtool -d eth1 0x004: 0x00000000 0x008: 0x0a8000aa 0x010: 0x01000000 0x014: 0x00000000 0x024: 0xf0000102 0x040: 0x6d82c800 0x044: 0x00000020 0x064: 0x40000000 0x084: RCR (Receive Control Register) 0x47c00104 MAX_FL (Maximum frame length) 1984 FCE (Flow control enable) 0 BC_REJ (Broadcast frame reject) 0 PROM (Promiscuous mode) 0 DRT (Disable receive on transmit) 0 LOOP (Internal loopback) 0 0x0c4: TCR (Transmit Control Register) 0x00000004 RFC_PAUSE (Receive frame control pause) 0 TFC_PAUSE (Transmit frame control pause) 0 FDEN (Full duplex enable) 1 HBC (Heartbeat control) 0 GTS (Graceful transmit stop) 0 0x0e4: 0x76735d6d 0x0e8: 0x7e9e8808 0x0ec: 0x00010000 . . . 88E6352 Switch Port Registers ------------------------------ 00: Port Status 0x4d04 Pause Enabled 0 My Pause 1 802.3 PHY Detected 0 Link Status Up Duplex Full Speed 100 or 200 Mbps EEE Enabled 0 Transmitter Paused 0 Flow Control 0 Config Mode 0x4 01: Physical Control 0x003d RGMII Receive Timing Control Default RGMII Transmit Timing Control Default 200 BASE Mode 100 Flow Control's Forced value 0 Force Flow Control 0 Link's Forced value Up Force Link 1 Duplex's Forced value Full Force Duplex 1 Force Speed 100 or 200 Mbps . . . Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- net/dsa/master.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/net/dsa/master.c b/net/dsa/master.c index 4b52f8bac5e1..a8e52c9967f4 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -8,6 +8,70 @@ #include "dsa_priv.h" +static int dsa_master_get_regs_len(struct net_device *dev) +{ + struct dsa_port *cpu_dp = dev->dsa_ptr; + const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; + struct dsa_switch *ds = cpu_dp->ds; + int port = cpu_dp->index; + int ret = 0; + int len; + + if (ops->get_regs_len) { + len = ops->get_regs_len(dev); + if (len < 0) + return len; + ret += len; + } + + ret += sizeof(struct ethtool_drvinfo); + ret += sizeof(struct ethtool_regs); + + if (ds->ops->get_regs_len) { + len = ds->ops->get_regs_len(ds, port); + if (len < 0) + return len; + ret += len; + } + + return ret; +} + +static void dsa_master_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *data) +{ + struct dsa_port *cpu_dp = dev->dsa_ptr; + const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; + struct dsa_switch *ds = cpu_dp->ds; + struct ethtool_drvinfo *cpu_info; + struct ethtool_regs *cpu_regs; + int port = cpu_dp->index; + int len; + + if (ops->get_regs_len && ops->get_regs) { + len = ops->get_regs_len(dev); + if (len < 0) + return; + regs->len = len; + ops->get_regs(dev, regs, data); + data += regs->len; + } + + cpu_info = (struct ethtool_drvinfo *)data; + strlcpy(cpu_info->driver, "dsa", sizeof(cpu_info->driver)); + data += sizeof(*cpu_info); + cpu_regs = (struct ethtool_regs *)data; + data += sizeof(*cpu_regs); + + if (ds->ops->get_regs_len && ds->ops->get_regs) { + len = ds->ops->get_regs_len(ds, port); + if (len < 0) + return; + cpu_regs->len = len; + ds->ops->get_regs(ds, port, cpu_regs, data); + } +} + static void dsa_master_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, uint64_t *data) @@ -147,6 +211,8 @@ static int dsa_master_ethtool_setup(struct net_device *dev) if (cpu_dp->orig_ethtool_ops) memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops)); + ops->get_regs_len = dsa_master_get_regs_len; + ops->get_regs = dsa_master_get_regs; ops->get_sset_count = dsa_master_get_sset_count; ops->get_ethtool_stats = dsa_master_get_ethtool_stats; ops->get_strings = dsa_master_get_strings; -- GitLab From b8fb640643fcdb3bca84137c4cec0c649b25e056 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 2 Aug 2019 23:01:56 -0700 Subject: [PATCH 2114/7155] net: mdio-octeon: Fix Kconfig warnings and build errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 171a9bae68c7 ("staging/octeon: Allow test build on !MIPS"), the following combination of configs cause a few Kconfig warnings and build errors (distilled from arm allyesconfig and Randy's randconfig builds): CONFIG_NETDEVICES=y CONFIG_STAGING=y CONFIG_COMPILE_TEST=y and CONFIG_OCTEON_ETHERNET as either a module or built-in. WARNING: unmet direct dependencies detected for MDIO_OCTEON Depends on [n]: NETDEVICES [=y] && MDIO_DEVICE [=y] && MDIO_BUS [=y] && 64BIT [=n] && HAS_IOMEM [=y] && OF_MDIO [=n] Selected by [y]: - OCTEON_ETHERNET [=y] && STAGING [=y] && (CAVIUM_OCTEON_SOC || COMPILE_TEST [=y]) && NETDEVICES [=y] In file included from ../drivers/net/phy/mdio-octeon.c:14: ../drivers/net/phy/mdio-cavium.h:111:36: error: implicit declaration of function ‘writeq’; did you mean ‘writel’? [-Werror=implicit-function-declaration] 111 | #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr) | ^~~~~~ CONFIG_64BIT is not strictly necessary if the proper readq/writeq definitions are included from io-64-nonatomic-lo-hi.h. CONFIG_OF_MDIO is not needed when CONFIG_COMPILE_TEST is enabled because of commit f9dc9ac51610 ("of/mdio: Add dummy functions in of_mdio.h."). Fixes: 171a9bae68c7 ("staging/octeon: Allow test build on !MIPS") Reported-by: kbuild test robot Reported-by: Mark Brown Reported-by: Randy Dunlap Signed-off-by: Nathan Chancellor Acked-by: Randy Dunlap # build-tested Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 4 ++-- drivers/net/phy/mdio-cavium.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 206d8650ee7f..48ca213c0ada 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -172,8 +172,8 @@ config MDIO_MSCC_MIIM config MDIO_OCTEON tristate "Octeon and some ThunderX SOCs MDIO buses" - depends on 64BIT - depends on HAS_IOMEM && OF_MDIO + depends on (64BIT && OF_MDIO) || COMPILE_TEST + depends on HAS_IOMEM select MDIO_CAVIUM help This module provides a driver for the Octeon and ThunderX MDIO diff --git a/drivers/net/phy/mdio-cavium.h b/drivers/net/phy/mdio-cavium.h index ed5f9bb5448d..b7f89ad27465 100644 --- a/drivers/net/phy/mdio-cavium.h +++ b/drivers/net/phy/mdio-cavium.h @@ -108,6 +108,8 @@ static inline u64 oct_mdio_readq(u64 addr) return cvmx_read_csr(addr); } #else +#include + #define oct_mdio_writeq(val, addr) writeq(val, (void *)addr) #define oct_mdio_readq(addr) readq((void *)addr) #endif -- GitLab From ae697f3bf784898a9be1d68ff7fc38819ca5040f Mon Sep 17 00:00:00 2001 From: Dave Taht Date: Sat, 3 Aug 2019 16:37:28 -0700 Subject: [PATCH 2115/7155] Increase fq_codel count in the bulk dropper In the field fq_codel is often used with a smaller memory or packet limit than the default, and when the bulk dropper is hit, the drop pattern bifircates into one that more slowly increases the codel drop rate and hits the bulk dropper more than it should. The scan through the 1024 queues happens more often than it needs to. This patch increases the codel count in the bulk dropper, but does not change the drop rate there, relying on the next codel round to deliver the next packet at the original drop rate (after that burst of loss), then escalate to a higher signaling rate. Signed-off-by: Dave Taht Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index d59fbcc745d1..d67b2c40e6e6 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -173,6 +173,8 @@ static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets, __qdisc_drop(skb, to_free); } while (++i < max_packets && len < threshold); + /* Tell codel to increase its signal strength also */ + flow->cvars.count += i; flow->dropped += i; q->backlogs[idx] -= len; q->memory_usage -= mem; -- GitLab From 77ddaff218fc505f6930a2bf3e4eec2ff74255f5 Mon Sep 17 00:00:00 2001 From: Dave Taht Date: Sat, 3 Aug 2019 16:37:29 -0700 Subject: [PATCH 2116/7155] fq_codel: Kill useless per-flow dropped statistic It is almost impossible to get anything other than a 0 out of flow->dropped statistic with a tc class dump, as it resets to 0 on every round. It also conflates ecn marks with drops. It would have been useful had it kept a cumulative drop count, but it doesn't. This patch doesn't change the API, it just stops tracking a stat and state that is impossible to measure and nobody uses. Signed-off-by: Dave Taht Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index d67b2c40e6e6..9edd0f495001 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -45,7 +45,6 @@ struct fq_codel_flow { struct sk_buff *tail; struct list_head flowchain; int deficit; - u32 dropped; /* number of drops (or ECN marks) on this flow */ struct codel_vars cvars; }; /* please try to keep this structure <= 64 bytes */ @@ -175,7 +174,6 @@ static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets, /* Tell codel to increase its signal strength also */ flow->cvars.count += i; - flow->dropped += i; q->backlogs[idx] -= len; q->memory_usage -= mem; sch->qstats.drops += i; @@ -213,7 +211,6 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch, list_add_tail(&flow->flowchain, &q->new_flows); q->new_flow_count++; flow->deficit = q->quantum; - flow->dropped = 0; } get_codel_cb(skb)->mem_usage = skb->truesize; q->memory_usage += get_codel_cb(skb)->mem_usage; @@ -312,9 +309,6 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) &flow->cvars, &q->cstats, qdisc_pkt_len, codel_get_enqueue_time, drop_func, dequeue_func); - flow->dropped += q->cstats.drop_count - prev_drop_count; - flow->dropped += q->cstats.ecn_mark - prev_ecn_mark; - if (!skb) { /* force a pass through old_flows to prevent starvation */ if ((head == &q->new_flows) && !list_empty(&q->old_flows)) @@ -660,7 +654,7 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl, sch_tree_unlock(sch); } qs.backlog = q->backlogs[idx]; - qs.drops = flow->dropped; + qs.drops = 0; } if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0) return -1; -- GitLab From a14cc4d24a645dd13abe66f50e1439136337fa1a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 4 Aug 2019 09:42:57 +0200 Subject: [PATCH 2117/7155] r8169: remove access to legacy register MultiIntr This code piece was inherited from RTL8139 code, the register at address 0x5c however has a different meaning on RTL8169 and is unused. So we can remove this. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 109779e449cd..1817d0ab8df6 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -271,7 +271,6 @@ enum rtl_registers { Config3 = 0x54, Config4 = 0x55, Config5 = 0x56, - MultiIntr = 0x5c, PHYAR = 0x60, PHYstatus = 0x6c, RxMaxSize = 0xda, @@ -5241,10 +5240,7 @@ static void rtl_hw_start(struct rtl8169_private *tp) RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); rtl_init_rxcfg(tp); rtl_set_tx_config_registers(tp); - rtl_set_rx_mode(tp->dev); - /* no early-rx interrupts */ - RTL_W16(tp, MultiIntr, RTL_R16(tp, MultiIntr) & 0xf000); rtl_irq_enable(tp); } -- GitLab From ef712ede3541dd364131d2fe29603cb362bd5aaa Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 4 Aug 2019 09:47:51 +0200 Subject: [PATCH 2118/7155] r8169: add helper r8168_mac_ocp_modify Add a helper for MAC OCP read-modify-write operations. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 65 +++++++---------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 1817d0ab8df6..4d02095e3ca3 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -850,6 +850,14 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) return RTL_R32(tp, OCPDR); } +static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask, + u16 set) +{ + u16 data = r8168_mac_ocp_read(tp, reg); + + r8168_mac_ocp_write(tp, reg, (data & ~mask) | set); +} + #define OCP_STD_PHY_BASE 0xa400 static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) @@ -4809,8 +4817,6 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp) static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) { - int rg_saw_cnt; - u32 data; static const struct ephy_info e_info_8168h_1[] = { { 0x1e, 0x0800, 0x0001 }, { 0x1d, 0x0000, 0x0800 }, @@ -4819,6 +4825,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) { 0x04, 0xffff, 0x154a }, { 0x01, 0xffff, 0x068b } }; + int rg_saw_cnt; /* disable aspm and clock request before access ephy */ rtl_hw_aspm_clkreq_enable(tp, false); @@ -4863,31 +4870,13 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) sw_cnt_1ms_ini = 16000000/rg_saw_cnt; sw_cnt_1ms_ini &= 0x0fff; - data = r8168_mac_ocp_read(tp, 0xd412); - data &= ~0x0fff; - data |= sw_cnt_1ms_ini; - r8168_mac_ocp_write(tp, 0xd412, data); + r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini); } - data = r8168_mac_ocp_read(tp, 0xe056); - data &= ~0xf0; - data |= 0x70; - r8168_mac_ocp_write(tp, 0xe056, data); - - data = r8168_mac_ocp_read(tp, 0xe052); - data &= ~0x6000; - data |= 0x8008; - r8168_mac_ocp_write(tp, 0xe052, data); - - data = r8168_mac_ocp_read(tp, 0xe0d6); - data &= ~0x01ff; - data |= 0x017f; - r8168_mac_ocp_write(tp, 0xe0d6, data); - - data = r8168_mac_ocp_read(tp, 0xd420); - data &= ~0x0fff; - data |= 0x047f; - r8168_mac_ocp_write(tp, 0xd420, data); + r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070); + r8168_mac_ocp_modify(tp, 0xe052, 0x6000, 0x8008); + r8168_mac_ocp_modify(tp, 0xe0d6, 0x01ff, 0x017f); + r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f); r8168_mac_ocp_write(tp, 0xe63e, 0x0001); r8168_mac_ocp_write(tp, 0xe63e, 0x0000); @@ -4969,7 +4958,6 @@ static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp) static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp) { - u32 data; static const struct ephy_info e_info_8168ep_3[] = { { 0x00, 0xffff, 0x10a3 }, { 0x19, 0xffff, 0x7c00 }, @@ -4986,18 +4974,9 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp) RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN); RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN); - data = r8168_mac_ocp_read(tp, 0xd3e2); - data &= 0xf000; - data |= 0x0271; - r8168_mac_ocp_write(tp, 0xd3e2, data); - - data = r8168_mac_ocp_read(tp, 0xd3e4); - data &= 0xff00; - r8168_mac_ocp_write(tp, 0xd3e4, data); - - data = r8168_mac_ocp_read(tp, 0xe860); - data |= 0x0080; - r8168_mac_ocp_write(tp, 0xe860, data); + r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271); + r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000); + r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080); rtl_hw_aspm_clkreq_enable(tp, true); } @@ -6657,8 +6636,6 @@ static int r8169_mdio_register(struct rtl8169_private *tp) static void rtl_hw_init_8168g(struct rtl8169_private *tp) { - u32 data; - tp->ocp_base = OCP_STD_PHY_BASE; RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN); @@ -6673,16 +6650,12 @@ static void rtl_hw_init_8168g(struct rtl8169_private *tp) msleep(1); RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB); - data = r8168_mac_ocp_read(tp, 0xe8de); - data &= ~(1 << 14); - r8168_mac_ocp_write(tp, 0xe8de, data); + r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0); if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) return; - data = r8168_mac_ocp_read(tp, 0xe8de); - data |= (1 << 15); - r8168_mac_ocp_write(tp, 0xe8de, data); + r8168_mac_ocp_modify(tp, 0xe8de, 0, BIT(15)); rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42); } -- GitLab From a7a92cf81589ca2e9bef5443e8a99d0855b3722f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 4 Aug 2019 09:52:33 +0200 Subject: [PATCH 2119/7155] r8169: sync PCIe PHY init with vendor driver 8.047.01 Synchronize PCIe PHY initialization with vendor driver version 8.047.01. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 60 ++++++++++++++--------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 4d02095e3ca3..a10ff9e1efec 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4415,7 +4415,7 @@ static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168c_2[] = { { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } + { 0x03, 0x0400, 0x0020 } }; rtl_set_def_aspm_entry_latency(tp); @@ -4462,7 +4462,8 @@ static void rtl_hw_start_8168d_4(struct rtl8169_private *tp) static const struct ephy_info e_info_8168d_4[] = { { 0x0b, 0x0000, 0x0048 }, { 0x19, 0x0020, 0x0050 }, - { 0x0c, 0x0100, 0x0020 } + { 0x0c, 0x0100, 0x0020 }, + { 0x10, 0x0004, 0x0000 }, }; rtl_set_def_aspm_entry_latency(tp); @@ -4512,7 +4513,9 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168e_2[] = { { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, }; rtl_set_def_aspm_entry_latency(tp); @@ -4574,7 +4577,9 @@ static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) { 0x06, 0x00c0, 0x0020 }, { 0x08, 0x0001, 0x0002 }, { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, }; rtl_hw_start_8168f(tp); @@ -4589,8 +4594,9 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp) static const struct ephy_info e_info_8168f_1[] = { { 0x06, 0x00c0, 0x0020 }, { 0x0f, 0xffff, 0x5200 }, - { 0x1e, 0x0000, 0x4000 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, }; rtl_hw_start_8168f(tp); @@ -4629,8 +4635,8 @@ static void rtl_hw_start_8168g(struct rtl8169_private *tp) static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168g_1[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x37d0, 0x0820 }, + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x3ff0, 0x0820 }, { 0x1e, 0x0000, 0x0001 }, { 0x19, 0x8000, 0x0000 } }; @@ -4646,10 +4652,15 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168g_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x19, 0xffff, 0xfc00 }, - { 0x1e, 0xffff, 0x20eb } + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x3ff0, 0x0820 }, + { 0x19, 0xffff, 0x7c00 }, + { 0x1e, 0xffff, 0x20eb }, + { 0x0d, 0xffff, 0x1666 }, + { 0x00, 0xffff, 0x10a3 }, + { 0x06, 0xffff, 0xf050 }, + { 0x04, 0x0000, 0x0010 }, + { 0x1d, 0x4000, 0x0000 }, }; rtl_hw_start_8168g(tp); @@ -4663,11 +4674,16 @@ static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) static void rtl_hw_start_8411_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8411_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x0f, 0xffff, 0x5200 }, - { 0x19, 0x0020, 0x0000 }, - { 0x1e, 0x0000, 0x2000 } + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x37d0, 0x0820 }, + { 0x1e, 0x0000, 0x0001 }, + { 0x19, 0x8021, 0x0000 }, + { 0x1e, 0x0000, 0x2000 }, + { 0x0d, 0x0100, 0x0200 }, + { 0x00, 0x0000, 0x0080 }, + { 0x06, 0x0000, 0x0010 }, + { 0x04, 0x0000, 0x0010 }, + { 0x1d, 0x0000, 0x4000 }, }; rtl_hw_start_8168g(tp); @@ -4822,7 +4838,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) { 0x1d, 0x0000, 0x0800 }, { 0x05, 0xffff, 0x2089 }, { 0x06, 0xffff, 0x5881 }, - { 0x04, 0xffff, 0x154a }, + { 0x04, 0xffff, 0x854a }, { 0x01, 0xffff, 0x068b } }; int rg_saw_cnt; @@ -4959,10 +4975,10 @@ static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp) static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168ep_3[] = { - { 0x00, 0xffff, 0x10a3 }, - { 0x19, 0xffff, 0x7c00 }, - { 0x1e, 0xffff, 0x20eb }, - { 0x0d, 0xffff, 0x1666 } + { 0x00, 0x0000, 0x0080 }, + { 0x0d, 0x0100, 0x0200 }, + { 0x19, 0x8021, 0x0000 }, + { 0x1e, 0x0000, 0x2000 }, }; /* disable aspm and clock request before access ephy */ -- GitLab From 77feb4eed7560215a724df6e7d4f1beaf98ba49d Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:03 +0100 Subject: [PATCH 2120/7155] net: tc_act: add skbedit_ptype helper functions The tc_act header file contains an inline function that checks if an action is changing the skb mark of a packet and a further function to extract the mark. Add similar functions to check for and get skbedit actions that modify the packet type of the skb. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/tc_act/tc_skbedit.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h index 4c04e2985508..b22a1f641f02 100644 --- a/include/net/tc_act/tc_skbedit.h +++ b/include/net/tc_act/tc_skbedit.h @@ -54,4 +54,31 @@ static inline u32 tcf_skbedit_mark(const struct tc_action *a) return mark; } +/* Return true iff action is ptype */ +static inline bool is_tcf_skbedit_ptype(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT + u32 flags; + + if (a->ops && a->ops->id == TCA_ID_SKBEDIT) { + rcu_read_lock(); + flags = rcu_dereference(to_skbedit(a)->params)->flags; + rcu_read_unlock(); + return flags == SKBEDIT_F_PTYPE; + } +#endif + return false; +} + +static inline u32 tcf_skbedit_ptype(const struct tc_action *a) +{ + u16 ptype; + + rcu_read_lock(); + ptype = rcu_dereference(to_skbedit(a)->params)->ptype; + rcu_read_unlock(); + + return ptype; +} + #endif /* __NET_TC_SKBEDIT_H */ -- GitLab From fb1b775a247ee8d846152841f780eba6cb71bcfc Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:04 +0100 Subject: [PATCH 2121/7155] net: sched: add skbedit of ptype action to hardware IR TC rules can impliment skbedit actions. Currently actions that modify the skb mark are passed to offloading drivers via the hardware intermediate representation in the flow_offload API. Extend this to include skbedit actions that modify the packet type of the skb. Such actions may be used to set the ptype to HOST when redirecting a packet to ingress. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/flow_offload.h | 2 ++ net/sched/cls_api.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 00b9aab5fdc1..04c29f5bb60a 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -126,6 +126,7 @@ enum flow_action_id { FLOW_ACTION_ADD, FLOW_ACTION_CSUM, FLOW_ACTION_MARK, + FLOW_ACTION_PTYPE, FLOW_ACTION_WAKE, FLOW_ACTION_QUEUE, FLOW_ACTION_SAMPLE, @@ -168,6 +169,7 @@ struct flow_action_entry { const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */ u32 csum_flags; /* FLOW_ACTION_CSUM */ u32 mark; /* FLOW_ACTION_MARK */ + u16 ptype; /* FLOW_ACTION_PTYPE */ struct { /* FLOW_ACTION_QUEUE */ u32 ctx; u32 index; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 3565d9aa09aa..ae73d3705571 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3294,6 +3294,9 @@ int tc_setup_flow_action(struct flow_action *flow_action, default: goto err_out; } + } else if (is_tcf_skbedit_ptype(act)) { + entry->id = FLOW_ACTION_PTYPE; + entry->ptype = tcf_skbedit_ptype(act); } else { goto err_out; } -- GitLab From d7609c96c6da0831e196d970a20dc960bcc4a4d6 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:05 +0100 Subject: [PATCH 2122/7155] net: tc_act: add helpers to detect ingress mirred actions TC mirred actions can send to egress or ingress on a given netdev. Helpers exist to detect actions that are mirred to egress. Extend the header file to include helpers to detect ingress mirred actions. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/tc_act/tc_mirred.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h index c757585a05b0..1cace4c69e44 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h @@ -32,6 +32,24 @@ static inline bool is_tcf_mirred_egress_mirror(const struct tc_action *a) return false; } +static inline bool is_tcf_mirred_ingress_redirect(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT + if (a->ops && a->ops->id == TCA_ID_MIRRED) + return to_mirred(a)->tcfm_eaction == TCA_INGRESS_REDIR; +#endif + return false; +} + +static inline bool is_tcf_mirred_ingress_mirror(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT + if (a->ops && a->ops->id == TCA_ID_MIRRED) + return to_mirred(a)->tcfm_eaction == TCA_INGRESS_MIRROR; +#endif + return false; +} + static inline struct net_device *tcf_mirred_dev(const struct tc_action *a) { return rtnl_dereference(to_mirred(a)->tcfm_dev); -- GitLab From 48e584ac583b08a923d4d872596cc7b049e99f12 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:06 +0100 Subject: [PATCH 2123/7155] net: sched: add ingress mirred action to hardware IR TC mirred actions (redirect and mirred) can send to egress or ingress of a device. Currently only egress is used for hw offload rules. Modify the intermediate representation for hw offload to include mirred actions that go to ingress. This gives drivers access to such rules and can decide whether or not to offload them. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/flow_offload.h | 2 ++ net/sched/cls_api.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 04c29f5bb60a..d3b12bc8a114 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -117,6 +117,8 @@ enum flow_action_id { FLOW_ACTION_GOTO, FLOW_ACTION_REDIRECT, FLOW_ACTION_MIRRED, + FLOW_ACTION_REDIRECT_INGRESS, + FLOW_ACTION_MIRRED_INGRESS, FLOW_ACTION_VLAN_PUSH, FLOW_ACTION_VLAN_POP, FLOW_ACTION_VLAN_MANGLE, diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index ae73d3705571..9d85d3295c7c 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3205,6 +3205,12 @@ int tc_setup_flow_action(struct flow_action *flow_action, } else if (is_tcf_mirred_egress_mirror(act)) { entry->id = FLOW_ACTION_MIRRED; entry->dev = tcf_mirred_dev(act); + } else if (is_tcf_mirred_ingress_redirect(act)) { + entry->id = FLOW_ACTION_REDIRECT_INGRESS; + entry->dev = tcf_mirred_dev(act); + } else if (is_tcf_mirred_ingress_mirror(act)) { + entry->id = FLOW_ACTION_MIRRED_INGRESS; + entry->dev = tcf_mirred_dev(act); } else if (is_tcf_vlan(act)) { switch (tcf_vlan_action(act)) { case TCA_VLAN_ACT_PUSH: -- GitLab From 4b10c53d81fd1350a5510f3038f52b5db9c953e0 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:07 +0100 Subject: [PATCH 2124/7155] nfp: flower: push vlan after tunnel in merge NFP allows the merging of 2 flows together into a single offloaded flow. In the kernel datapath the packet must match 1 flow, impliment its actions, recirculate, match the 2nd flow and also impliment its actions. Merging creates a single flow with all actions from the 2 original flows. Firmware impliments a tunnel header push as the packet is about to egress the card. Therefore, if the first merge rule candiate pushes a tunnel, then the second rule can only have an egress action for a valid merge to occur (or else the action ordering will be incorrect). This prevents the pushing of a tunnel header followed by the pushing of a vlan header. In order to support this behaviour, firmware allows VLAN information to be encoded in the tunnel push action. If this is non zero then the fw will push a VLAN after the tunnel header push meaning that 2 such flows with these actions can be merged (with action order being maintained). Support tunnel in VLAN pushes by encoding VLAN information in the tunnel push action of any merge flow requiring this. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/cmsg.h | 3 +- .../ethernet/netronome/nfp/flower/offload.c | 60 +++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 332439400d85..caf3029144bd 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -220,7 +220,8 @@ struct nfp_fl_set_ipv4_tun { __be16 tun_flags; u8 ttl; u8 tos; - __be32 extra; + __be16 outer_vlan_tpid; + __be16 outer_vlan_tci; u8 tun_len; u8 res2; __be16 tun_proto; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index e209f150c5f2..607426c02ed3 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -732,28 +732,62 @@ nfp_flower_copy_pre_actions(char *act_dst, char *act_src, int len, return act_off; } -static int nfp_fl_verify_post_tun_acts(char *acts, int len) +static int +nfp_fl_verify_post_tun_acts(char *acts, int len, struct nfp_fl_push_vlan **vlan) { struct nfp_fl_act_head *a; unsigned int act_off = 0; while (act_off < len) { a = (struct nfp_fl_act_head *)&acts[act_off]; - if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) + + if (a->jump_id == NFP_FL_ACTION_OPCODE_PUSH_VLAN && !act_off) + *vlan = (struct nfp_fl_push_vlan *)a; + else if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) return -EOPNOTSUPP; act_off += a->len_lw << NFP_FL_LW_SIZ; } + /* Ensure any VLAN push also has an egress action. */ + if (*vlan && act_off <= sizeof(struct nfp_fl_push_vlan)) + return -EOPNOTSUPP; + return 0; } +static int +nfp_fl_push_vlan_after_tun(char *acts, int len, struct nfp_fl_push_vlan *vlan) +{ + struct nfp_fl_set_ipv4_tun *tun; + struct nfp_fl_act_head *a; + unsigned int act_off = 0; + + while (act_off < len) { + a = (struct nfp_fl_act_head *)&acts[act_off]; + + if (a->jump_id == NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL) { + tun = (struct nfp_fl_set_ipv4_tun *)a; + tun->outer_vlan_tpid = vlan->vlan_tpid; + tun->outer_vlan_tci = vlan->vlan_tci; + + return 0; + } + + act_off += a->len_lw << NFP_FL_LW_SIZ; + } + + /* Return error if no tunnel action is found. */ + return -EOPNOTSUPP; +} + static int nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1, struct nfp_fl_payload *sub_flow2, struct nfp_fl_payload *merge_flow) { unsigned int sub1_act_len, sub2_act_len, pre_off1, pre_off2; + struct nfp_fl_push_vlan *post_tun_push_vlan = NULL; bool tunnel_act = false; char *merge_act; int err; @@ -790,18 +824,36 @@ nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1, sub2_act_len -= pre_off2; /* FW does a tunnel push when egressing, therefore, if sub_flow 1 pushes - * a tunnel, sub_flow 2 can only have output actions for a valid merge. + * a tunnel, there are restrictions on what sub_flow 2 actions lead to a + * valid merge. */ if (tunnel_act) { char *post_tun_acts = &sub_flow2->action_data[pre_off2]; - err = nfp_fl_verify_post_tun_acts(post_tun_acts, sub2_act_len); + err = nfp_fl_verify_post_tun_acts(post_tun_acts, sub2_act_len, + &post_tun_push_vlan); if (err) return err; + + if (post_tun_push_vlan) { + pre_off2 += sizeof(*post_tun_push_vlan); + sub2_act_len -= sizeof(*post_tun_push_vlan); + } } /* Copy remaining actions from sub_flows 1 and 2. */ memcpy(merge_act, sub_flow1->action_data + pre_off1, sub1_act_len); + + if (post_tun_push_vlan) { + /* Update tunnel action in merge to include VLAN push. */ + err = nfp_fl_push_vlan_after_tun(merge_act, sub1_act_len, + post_tun_push_vlan); + if (err) + return err; + + merge_flow->meta.act_len -= sizeof(*post_tun_push_vlan); + } + merge_act += sub1_act_len; memcpy(merge_act, sub_flow2->action_data + pre_off2, sub2_act_len); -- GitLab From f5c977eed725a000dd4efa6d56e86d88085d0b1b Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:08 +0100 Subject: [PATCH 2125/7155] nfp: flower: detect potential pre-tunnel rules Pre-tunnel rules are used when the tunnel end-point is on an 'internal port'. These rules are used to direct the tunnelled packets (based on outer header fields) to the internal port where they can be detunnelled. The rule must send the packet to ingress the internal port at the TC layer. Currently FW does not support an action to send to ingress so cannot offload such rules. However, in preparation for populating the pre-tunnel table to represent such rules, check for rules that send to the ingress of an internal port and mark them as such. Further validation of such rules is left to subsequent patches. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/flower/action.c | 40 +++++++++++++++---- .../net/ethernet/netronome/nfp/flower/main.h | 4 ++ .../ethernet/netronome/nfp/flower/offload.c | 25 ++++++++++++ 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index ff2f419ae352..1b019fdfcd97 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -173,7 +173,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, struct nfp_fl_payload *nfp_flow, bool last, struct net_device *in_dev, enum nfp_flower_tun_type tun_type, int *tun_out_cnt, - struct netlink_ext_ack *extack) + bool pkt_host, struct netlink_ext_ack *extack) { size_t act_size = sizeof(struct nfp_fl_output); struct nfp_flower_priv *priv = app->priv; @@ -218,6 +218,20 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, return gid; } output->port = cpu_to_be32(NFP_FL_LAG_OUT | gid); + } else if (nfp_flower_internal_port_can_offload(app, out_dev)) { + if (!(priv->flower_ext_feats & NFP_FL_FEATS_PRE_TUN_RULES)) { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pre-tunnel rules not supported in loaded firmware"); + return -EOPNOTSUPP; + } + + if (nfp_flow->pre_tun_rule.dev || !pkt_host) { + NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pre-tunnel rules require single egress dev and ptype HOST action"); + return -EOPNOTSUPP; + } + + nfp_flow->pre_tun_rule.dev = out_dev; + + return 0; } else { /* Set action output parameters. */ output->flags = cpu_to_be16(tmp_flags); @@ -885,7 +899,7 @@ nfp_flower_output_action(struct nfp_app *app, struct nfp_fl_payload *nfp_fl, int *a_len, struct net_device *netdev, bool last, enum nfp_flower_tun_type *tun_type, int *tun_out_cnt, - int *out_cnt, u32 *csum_updated, + int *out_cnt, u32 *csum_updated, bool pkt_host, struct netlink_ext_ack *extack) { struct nfp_flower_priv *priv = app->priv; @@ -907,7 +921,7 @@ nfp_flower_output_action(struct nfp_app *app, output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len]; err = nfp_fl_output(app, output, act, nfp_fl, last, netdev, *tun_type, - tun_out_cnt, extack); + tun_out_cnt, pkt_host, extack); if (err) return err; @@ -939,7 +953,7 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, struct net_device *netdev, enum nfp_flower_tun_type *tun_type, int *tun_out_cnt, int *out_cnt, u32 *csum_updated, - struct nfp_flower_pedit_acts *set_act, + struct nfp_flower_pedit_acts *set_act, bool *pkt_host, struct netlink_ext_ack *extack, int act_idx) { struct nfp_fl_set_ipv4_tun *set_tun; @@ -955,17 +969,21 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, case FLOW_ACTION_DROP: nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_DROP); break; + case FLOW_ACTION_REDIRECT_INGRESS: case FLOW_ACTION_REDIRECT: err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev, true, tun_type, tun_out_cnt, - out_cnt, csum_updated, extack); + out_cnt, csum_updated, *pkt_host, + extack); if (err) return err; break; + case FLOW_ACTION_MIRRED_INGRESS: case FLOW_ACTION_MIRRED: err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev, false, tun_type, tun_out_cnt, - out_cnt, csum_updated, extack); + out_cnt, csum_updated, *pkt_host, + extack); if (err) return err; break; @@ -1095,6 +1113,13 @@ nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, nfp_fl_set_mpls(set_m, act); *a_len += sizeof(struct nfp_fl_set_mpls); break; + case FLOW_ACTION_PTYPE: + /* TC ptype skbedit sets PACKET_HOST for ingress redirect. */ + if (act->ptype != PACKET_HOST) + return -EOPNOTSUPP; + + *pkt_host = true; + break; default: /* Currently we do not handle any other actions. */ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list"); @@ -1150,6 +1175,7 @@ int nfp_flower_compile_action(struct nfp_app *app, struct nfp_flower_pedit_acts set_act; enum nfp_flower_tun_type tun_type; struct flow_action_entry *act; + bool pkt_host = false; u32 csum_updated = 0; memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ); @@ -1166,7 +1192,7 @@ int nfp_flower_compile_action(struct nfp_app *app, err = nfp_flower_loop_action(app, act, flow, nfp_flow, &act_len, netdev, &tun_type, &tun_out_cnt, &out_cnt, &csum_updated, - &set_act, extack, i); + &set_act, &pkt_host, extack, i); if (err) return err; act_cnt++; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index af9441d5787f..6e9de4e52423 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -42,6 +42,7 @@ struct nfp_app; #define NFP_FL_FEATS_VLAN_PCP BIT(3) #define NFP_FL_FEATS_VF_RLIM BIT(4) #define NFP_FL_FEATS_FLOW_MOD BIT(5) +#define NFP_FL_FEATS_PRE_TUN_RULES BIT(6) #define NFP_FL_FEATS_FLOW_MERGE BIT(30) #define NFP_FL_FEATS_LAG BIT(31) @@ -280,6 +281,9 @@ struct nfp_fl_payload { char *action_data; struct list_head linked_flows; bool in_hw; + struct { + struct net_device *dev; + } pre_tun_rule; }; struct nfp_fl_payload_link { diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 607426c02ed3..fba802a02a03 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -489,6 +489,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer) flow_pay->meta.flags = 0; INIT_LIST_HEAD(&flow_pay->linked_flows); flow_pay->in_hw = false; + flow_pay->pre_tun_rule.dev = NULL; return flow_pay; @@ -996,6 +997,24 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, return err; } +/** + * nfp_flower_validate_pre_tun_rule() + * @app: Pointer to the APP handle + * @flow: Pointer to NFP flow representation of rule + * @extack: Netlink extended ACK report + * + * Verifies the flow as a pre-tunnel rule. + * + * Return: negative value on error, 0 if verified. + */ +static int +nfp_flower_validate_pre_tun_rule(struct nfp_app *app, + struct nfp_fl_payload *flow, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} + /** * nfp_flower_add_offload() - Adds a new flow to hardware. * @app: Pointer to the APP handle @@ -1046,6 +1065,12 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, if (err) goto err_destroy_flow; + if (flow_pay->pre_tun_rule.dev) { + err = nfp_flower_validate_pre_tun_rule(app, flow_pay, extack); + if (err) + goto err_destroy_flow; + } + err = nfp_compile_flow_metadata(app, flow, flow_pay, netdev, extack); if (err) goto err_destroy_flow; -- GitLab From 120ffd84a9ec2430faba83db274a6946374f4631 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:09 +0100 Subject: [PATCH 2126/7155] nfp: flower: verify pre-tunnel rules Pre-tunnel rules must direct packets to an internal port based on L2 information. Rules that egress to an internal port are already indicated by a non-NULL device in its nfp_fl_payload struct. Verfiy the rest of the match fields indicate that the rule is a pre-tunnel rule. This requires a full match on the destination MAC address, an option VLAN field, and no specific matches on other lower layer fields (with the exception of L4 proto and flags). If a rule is identified as a pre-tunnel rule then mark it for offload to the pre-tunnel table. Similarly, remove it from the pre-tunnel table on rule deletion. The actual offloading of these commands is left to a following patch. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/main.h | 5 + .../ethernet/netronome/nfp/flower/offload.c | 103 +++++++++++++++++- .../netronome/nfp/flower/tunnel_conf.c | 12 ++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 6e9de4e52423..c3aa4154fe8d 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -283,6 +283,7 @@ struct nfp_fl_payload { bool in_hw; struct { struct net_device *dev; + __be16 vlan_tci; } pre_tun_rule; }; @@ -419,4 +420,8 @@ void nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev); u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app, struct net_device *netdev); +int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app, + struct nfp_fl_payload *flow); +int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app, + struct nfp_fl_payload *flow); #endif diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index fba802a02a03..ff8a9f1a38f8 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -61,6 +61,11 @@ NFP_FLOWER_LAYER_IPV4 | \ NFP_FLOWER_LAYER_IPV6) +#define NFP_FLOWER_PRE_TUN_RULE_FIELDS \ + (NFP_FLOWER_LAYER_PORT | \ + NFP_FLOWER_LAYER_MAC | \ + NFP_FLOWER_LAYER_IPV4) + struct nfp_flower_merge_check { union { struct { @@ -1012,7 +1017,89 @@ nfp_flower_validate_pre_tun_rule(struct nfp_app *app, struct nfp_fl_payload *flow, struct netlink_ext_ack *extack) { - return -EOPNOTSUPP; + struct nfp_flower_meta_tci *meta_tci; + struct nfp_flower_mac_mpls *mac; + struct nfp_fl_act_head *act; + u8 *mask = flow->mask_data; + bool vlan = false; + int act_offset; + u8 key_layer; + + meta_tci = (struct nfp_flower_meta_tci *)flow->unmasked_data; + if (meta_tci->tci & cpu_to_be16(NFP_FLOWER_MASK_VLAN_PRESENT)) { + u16 vlan_tci = be16_to_cpu(meta_tci->tci); + + vlan_tci &= ~NFP_FLOWER_MASK_VLAN_PRESENT; + flow->pre_tun_rule.vlan_tci = cpu_to_be16(vlan_tci); + vlan = true; + } else { + flow->pre_tun_rule.vlan_tci = cpu_to_be16(0xffff); + } + + key_layer = meta_tci->nfp_flow_key_layer; + if (key_layer & ~NFP_FLOWER_PRE_TUN_RULE_FIELDS) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: too many match fields"); + return -EOPNOTSUPP; + } + + if (!(key_layer & NFP_FLOWER_LAYER_MAC)) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: MAC fields match required"); + return -EOPNOTSUPP; + } + + /* Skip fields known to exist. */ + mask += sizeof(struct nfp_flower_meta_tci); + mask += sizeof(struct nfp_flower_in_port); + + /* Ensure destination MAC address is fully matched. */ + mac = (struct nfp_flower_mac_mpls *)mask; + if (!is_broadcast_ether_addr(&mac->mac_dst[0])) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: dest MAC field must not be masked"); + return -EOPNOTSUPP; + } + + if (key_layer & NFP_FLOWER_LAYER_IPV4) { + int ip_flags = offsetof(struct nfp_flower_ipv4, ip_ext.flags); + int ip_proto = offsetof(struct nfp_flower_ipv4, ip_ext.proto); + int i; + + mask += sizeof(struct nfp_flower_mac_mpls); + + /* Ensure proto and flags are the only IP layer fields. */ + for (i = 0; i < sizeof(struct nfp_flower_ipv4); i++) + if (mask[i] && i != ip_flags && i != ip_proto) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: only flags and proto can be matched in ip header"); + return -EOPNOTSUPP; + } + } + + /* Action must be a single egress or pop_vlan and egress. */ + act_offset = 0; + act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; + if (vlan) { + if (act->jump_id != NFP_FL_ACTION_OPCODE_POP_VLAN) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: match on VLAN must have VLAN pop as first action"); + return -EOPNOTSUPP; + } + + act_offset += act->len_lw << NFP_FL_LW_SIZ; + act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; + } + + if (act->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: non egress action detected where egress was expected"); + return -EOPNOTSUPP; + } + + act_offset += act->len_lw << NFP_FL_LW_SIZ; + + /* Ensure there are no more actions after egress. */ + if (act_offset != flow->meta.act_len) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: egress is not the last action"); + return -EOPNOTSUPP; + } + + return 0; } /** @@ -1083,8 +1170,11 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, goto err_release_metadata; } - err = nfp_flower_xmit_flow(app, flow_pay, - NFP_FLOWER_CMSG_TYPE_FLOW_ADD); + if (flow_pay->pre_tun_rule.dev) + err = nfp_flower_xmit_pre_tun_flow(app, flow_pay); + else + err = nfp_flower_xmit_flow(app, flow_pay, + NFP_FLOWER_CMSG_TYPE_FLOW_ADD); if (err) goto err_remove_rhash; @@ -1226,8 +1316,11 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev, goto err_free_merge_flow; } - err = nfp_flower_xmit_flow(app, nfp_flow, - NFP_FLOWER_CMSG_TYPE_FLOW_DEL); + if (nfp_flow->pre_tun_rule.dev) + err = nfp_flower_xmit_pre_tun_del_flow(app, nfp_flow); + else + err = nfp_flower_xmit_flow(app, nfp_flow, + NFP_FLOWER_CMSG_TYPE_FLOW_DEL); /* Fall through on error. */ err_free_merge_flow: diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index a7a80f4b722a..ef5948112581 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -832,6 +832,18 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, return NOTIFY_OK; } +int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app, + struct nfp_fl_payload *flow) +{ + return -EOPNOTSUPP; +} + +int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app, + struct nfp_fl_payload *flow) +{ + return -EOPNOTSUPP; +} + int nfp_tunnel_config_start(struct nfp_app *app) { struct nfp_flower_priv *priv = app->priv; -- GitLab From f12725d98cbe862c7680c63fd1f8b381af965f7b Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:10 +0100 Subject: [PATCH 2127/7155] nfp: flower: offload pre-tunnel rules Pre-tunnel rules are TC flower and OvS rules that forward a packet to the tunnel end point where it can then pass through the network stack and be decapsulated. These are required if the tunnel end point is, say, an OvS internal port. Currently, firmware determines that a packet is in a tunnel and decaps it if it has a known destination IP and MAC address. However, this bypasses the flower pre-tunnel rule and so does not update the stats. Further to this it ignores VLANs that may exist outside of the tunnel header. Offload pre-tunnel rules to the NFP. This embeds the pre-tunnel rule into the tunnel decap process based on (firmware) mac index and VLAN. This means that decap can be carried out correctly with VLANs and that stats can be updated for all kernel rules correctly. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/cmsg.h | 1 + .../net/ethernet/netronome/nfp/flower/main.c | 1 + .../net/ethernet/netronome/nfp/flower/main.h | 3 + .../netronome/nfp/flower/tunnel_conf.c | 79 ++++++++++++++++++- 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index caf3029144bd..7eb2ec8969c3 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -484,6 +484,7 @@ enum nfp_flower_cmsg_type_port { NFP_FLOWER_CMSG_TYPE_QOS_MOD = 18, NFP_FLOWER_CMSG_TYPE_QOS_DEL = 19, NFP_FLOWER_CMSG_TYPE_QOS_STATS = 20, + NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE = 21, NFP_FLOWER_CMSG_TYPE_MAX = 32, }; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index eb846133943b..7a20447cca19 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -781,6 +781,7 @@ static int nfp_flower_init(struct nfp_app *app) INIT_LIST_HEAD(&app_priv->indr_block_cb_priv); INIT_LIST_HEAD(&app_priv->non_repr_priv); + app_priv->pre_tun_rule_cnt = 0; return 0; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index c3aa4154fe8d..5d302d79c004 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -163,6 +163,7 @@ struct nfp_fl_internal_ports { * @qos_stats_work: Workqueue for qos stats processing * @qos_rate_limiters: Current active qos rate limiters * @qos_stats_lock: Lock on qos stats updates + * @pre_tun_rule_cnt: Number of pre-tunnel rules offloaded */ struct nfp_flower_priv { struct nfp_app *app; @@ -194,6 +195,7 @@ struct nfp_flower_priv { struct delayed_work qos_stats_work; unsigned int qos_rate_limiters; spinlock_t qos_stats_lock; /* Protect the qos stats */ + int pre_tun_rule_cnt; }; /** @@ -284,6 +286,7 @@ struct nfp_fl_payload { struct { struct net_device *dev; __be16 vlan_tci; + __be16 port_idx; } pre_tun_rule; }; diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index ef5948112581..b9dbfb7f6c1f 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -15,6 +15,23 @@ #define NFP_FL_MAX_ROUTES 32 +#define NFP_TUN_PRE_TUN_RULE_LIMIT 32 +#define NFP_TUN_PRE_TUN_RULE_DEL 0x1 + +/** + * struct nfp_tun_pre_run_rule - rule matched before decap + * @flags: options for the rule offset + * @port_idx: index of destination MAC address for the rule + * @vlan_tci: VLAN info associated with MAC + * @host_ctx_id: stats context of rule to update + */ +struct nfp_tun_pre_tun_rule { + __be32 flags; + __be16 port_idx; + __be16 vlan_tci; + __be32 host_ctx_id; +}; + /** * struct nfp_tun_active_tuns - periodic message of active tunnels * @seq: sequence number of the message @@ -835,13 +852,71 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app, struct nfp_fl_payload *flow) { - return -EOPNOTSUPP; + struct nfp_flower_priv *app_priv = app->priv; + struct nfp_tun_offloaded_mac *mac_entry; + struct nfp_tun_pre_tun_rule payload; + struct net_device *internal_dev; + int err; + + if (app_priv->pre_tun_rule_cnt == NFP_TUN_PRE_TUN_RULE_LIMIT) + return -ENOSPC; + + memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); + + internal_dev = flow->pre_tun_rule.dev; + payload.vlan_tci = flow->pre_tun_rule.vlan_tci; + payload.host_ctx_id = flow->meta.host_ctx_id; + + /* Lookup MAC index for the pre-tunnel rule egress device. + * Note that because the device is always an internal port, it will + * have a constant global index so does not need to be tracked. + */ + mac_entry = nfp_tunnel_lookup_offloaded_macs(app, + internal_dev->dev_addr); + if (!mac_entry) + return -ENOENT; + + payload.port_idx = cpu_to_be16(mac_entry->index); + + /* Copy mac id and vlan to flow - dev may not exist at delete time. */ + flow->pre_tun_rule.vlan_tci = payload.vlan_tci; + flow->pre_tun_rule.port_idx = payload.port_idx; + + err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, + sizeof(struct nfp_tun_pre_tun_rule), + (unsigned char *)&payload, GFP_KERNEL); + if (err) + return err; + + app_priv->pre_tun_rule_cnt++; + + return 0; } int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app, struct nfp_fl_payload *flow) { - return -EOPNOTSUPP; + struct nfp_flower_priv *app_priv = app->priv; + struct nfp_tun_pre_tun_rule payload; + u32 tmp_flags = 0; + int err; + + memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); + + tmp_flags |= NFP_TUN_PRE_TUN_RULE_DEL; + payload.flags = cpu_to_be32(tmp_flags); + payload.vlan_tci = flow->pre_tun_rule.vlan_tci; + payload.port_idx = flow->pre_tun_rule.port_idx; + + err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, + sizeof(struct nfp_tun_pre_tun_rule), + (unsigned char *)&payload, GFP_KERNEL); + if (err) + return err; + + app_priv->pre_tun_rule_cnt--; + + return 0; } int nfp_tunnel_config_start(struct nfp_app *app) -- GitLab From 09aa811bb7def147e230f53ed3c19ff1a54a1575 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:09:11 +0100 Subject: [PATCH 2128/7155] nfp: flower: remove offloaded MACs when reprs are applied to OvS bridges MAC addresses along with an identifying index are offloaded to firmware to allow tunnel decapsulation. If a tunnel packet arrives with a matching destination MAC address and a verified index, it can continue on the decapsulation process. This replicates the MAC verifications carried out in the kernel network stack. When a netdev is added to a bridge (e.g. OvS) then packets arriving on that dev are directed through the bridge datapath instead of passing through the network stack. Therefore, tunnelled packets matching the MAC of that dev will not be decapped here. Replicate this behaviour on firmware by removing offloaded MAC addresses when a MAC representer is added to an OvS bridge. This can prevent any false positive tunnel decaps. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/main.h | 7 ++++ .../netronome/nfp/flower/tunnel_conf.c | 42 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 5d302d79c004..31d94592a7c0 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -221,6 +221,7 @@ struct nfp_fl_qos { * @block_shared: Flag indicating if offload applies to shared blocks * @mac_list: List entry of reprs that share the same offloaded MAC * @qos_table: Stored info on filters implementing qos + * @on_bridge: Indicates if the repr is attached to a bridge */ struct nfp_flower_repr_priv { struct nfp_repr *nfp_repr; @@ -230,6 +231,7 @@ struct nfp_flower_repr_priv { bool block_shared; struct list_head mac_list; struct nfp_fl_qos qos_table; + bool on_bridge; }; /** @@ -341,6 +343,11 @@ static inline bool nfp_flower_is_merge_flow(struct nfp_fl_payload *flow_pay) return flow_pay->tc_flower_cookie == (unsigned long)flow_pay; } +static inline bool nfp_flower_is_supported_bridge(struct net_device *netdev) +{ + return netif_is_ovs_master(netdev); +} + int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, unsigned int host_ctx_split); void nfp_flower_metadata_cleanup(struct nfp_app *app); diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index b9dbfb7f6c1f..a61e7f266644 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -730,6 +730,9 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, return 0; repr_priv = repr->app_priv; + if (repr_priv->on_bridge) + return 0; + mac_offloaded = &repr_priv->mac_offloaded; off_mac = &repr_priv->offloaded_mac_addr[0]; port = nfp_repr_get_port_id(netdev); @@ -845,6 +848,45 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, if (err) nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n", netdev_name(netdev)); + } else if (event == NETDEV_CHANGEUPPER) { + /* If a repr is attached to a bridge then tunnel packets + * entering the physical port are directed through the bridge + * datapath and cannot be directly detunneled. Therefore, + * associated offloaded MACs and indexes should not be used + * by fw for detunneling. + */ + struct netdev_notifier_changeupper_info *info = ptr; + struct net_device *upper = info->upper_dev; + struct nfp_flower_repr_priv *repr_priv; + struct nfp_repr *repr; + + if (!nfp_netdev_is_nfp_repr(netdev) || + !nfp_flower_is_supported_bridge(upper)) + return NOTIFY_OK; + + repr = netdev_priv(netdev); + if (repr->app != app) + return NOTIFY_OK; + + repr_priv = repr->app_priv; + + if (info->linking) { + if (nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_DEL)) + nfp_flower_cmsg_warn(app, "Failed to delete offloaded MAC on %s.\n", + netdev_name(netdev)); + repr_priv->on_bridge = true; + } else { + repr_priv->on_bridge = false; + + if (!(netdev->flags & IFF_UP)) + return NOTIFY_OK; + + if (nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_ADD)) + nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", + netdev_name(netdev)); + } } return NOTIFY_OK; } -- GitLab From 2e0bc7f3cb5553812f5808ede2cea746aabfbd03 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Sun, 4 Aug 2019 16:10:49 +0100 Subject: [PATCH 2129/7155] nfp: flower: encode mac indexes with pre-tunnel rule check When a tunnel packet arrives on the NFP card, its destination MAC is looked up and MAC index returned for it. This index can help verify the tunnel by, for example, ensuring that the packet arrived on the expected port. If the packet is destined for a known MAC that is not connected to a given physical port then the mac index can have a global value (e.g. when a series of bonded ports shared the same MAC). If the packet is to be detunneled at a bridge device or internal port like an Open vSwitch VLAN port, then it should first match a 'pre-tunnel' rule to direct it to that internal port. Use the MAC index to indicate if a packet should match a pre-tunnel rule before decap is allowed. Do this by tracking the number of internal ports associated with a MAC address and, if the number if >0, set a bit in the mac_index to forward the packet to the pre-tunnel table before continuing with decap. Signed-off-by: John Hurley Reviewed-by: Simon Horman Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../netronome/nfp/flower/tunnel_conf.c | 71 ++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index a61e7f266644..def8c198b016 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -17,6 +17,7 @@ #define NFP_TUN_PRE_TUN_RULE_LIMIT 32 #define NFP_TUN_PRE_TUN_RULE_DEL 0x1 +#define NFP_TUN_PRE_TUN_IDX_BIT 0x8 /** * struct nfp_tun_pre_run_rule - rule matched before decap @@ -141,11 +142,12 @@ enum nfp_flower_mac_offload_cmd { /** * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC - * @ht_node: Hashtable entry - * @addr: Offloaded MAC address - * @index: Offloaded index for given MAC address - * @ref_count: Number of devs using this MAC address - * @repr_list: List of reprs sharing this MAC address + * @ht_node: Hashtable entry + * @addr: Offloaded MAC address + * @index: Offloaded index for given MAC address + * @ref_count: Number of devs using this MAC address + * @repr_list: List of reprs sharing this MAC address + * @bridge_count: Number of bridge/internal devs with MAC */ struct nfp_tun_offloaded_mac { struct rhash_head ht_node; @@ -153,6 +155,7 @@ struct nfp_tun_offloaded_mac { u16 index; int ref_count; struct list_head repr_list; + int bridge_count; }; static const struct rhashtable_params offloaded_macs_params = { @@ -573,6 +576,8 @@ nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac *entry, list_del(&repr_priv->mac_list); list_add_tail(&repr_priv->mac_list, &entry->repr_list); + } else if (nfp_flower_is_supported_bridge(netdev)) { + entry->bridge_count++; } entry->ref_count++; @@ -589,20 +594,35 @@ nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { - nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod); - return 0; + if (entry->bridge_count || + !nfp_flower_is_supported_bridge(netdev)) { + nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, + netdev, mod); + return 0; + } + + /* MAC is global but matches need to go to pre_tun table. */ + nfp_mac_idx = entry->index | NFP_TUN_PRE_TUN_IDX_BIT; } - /* Assign a global index if non-repr or MAC address is now shared. */ - if (entry || !port) { - ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0, - NFP_MAX_MAC_INDEX, GFP_KERNEL); - if (ida_idx < 0) - return ida_idx; + if (!nfp_mac_idx) { + /* Assign a global index if non-repr or MAC is now shared. */ + if (entry || !port) { + ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0, + NFP_MAX_MAC_INDEX, GFP_KERNEL); + if (ida_idx < 0) + return ida_idx; - nfp_mac_idx = nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); - } else { - nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port); + nfp_mac_idx = + nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); + + if (nfp_flower_is_supported_bridge(netdev)) + nfp_mac_idx |= NFP_TUN_PRE_TUN_IDX_BIT; + + } else { + nfp_mac_idx = + nfp_tunnel_get_mac_idx_from_phy_port_id(port); + } } if (!entry) { @@ -671,6 +691,25 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, list_del(&repr_priv->mac_list); } + if (nfp_flower_is_supported_bridge(netdev)) { + entry->bridge_count--; + + if (!entry->bridge_count && entry->ref_count) { + u16 nfp_mac_idx; + + nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; + if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, + false)) { + nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n", + netdev_name(netdev)); + return 0; + } + + entry->index = nfp_mac_idx; + return 0; + } + } + /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { u16 nfp_mac_idx; -- GitLab From aa733660dbd8d9192b8c528ae0f4b84f3fef74e4 Mon Sep 17 00:00:00 2001 From: Yifeng Sun Date: Sun, 4 Aug 2019 19:56:11 -0700 Subject: [PATCH 2130/7155] openvswitch: Print error when ovs_execute_actions() fails Currently in function ovs_dp_process_packet(), return values of ovs_execute_actions() are silently discarded. This patch prints out an debug message when error happens so as to provide helpful hints for debugging. Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 892287d06c17..12d985029eb1 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -222,6 +222,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) struct dp_stats_percpu *stats; u64 *stats_counter; u32 n_mask_hit; + int error; stats = this_cpu_ptr(dp->stats_percpu); @@ -229,7 +230,6 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) flow = ovs_flow_tbl_lookup_stats(&dp->table, key, &n_mask_hit); if (unlikely(!flow)) { struct dp_upcall_info upcall; - int error; memset(&upcall, 0, sizeof(upcall)); upcall.cmd = OVS_PACKET_CMD_MISS; @@ -246,7 +246,10 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) ovs_flow_stats_update(flow, key->tp.flags, skb); sf_acts = rcu_dereference(flow->sf_acts); - ovs_execute_actions(dp, skb, sf_acts, key); + error = ovs_execute_actions(dp, skb, sf_acts, key); + if (unlikely(error)) + net_dbg_ratelimited("ovs: action execution error on datapath %s: %d\n", + ovs_dp_name(dp), error); stats_counter = &stats->n_hit; -- GitLab From 946152b3c5d6bab128db8eee226ec2665429b79c Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Tue, 6 Aug 2019 10:45:27 -0700 Subject: [PATCH 2131/7155] selftests/bpf: test_progs: switch to open_memstream Use open_memstream to override stdout during test execution. The copy of the original stdout is held in env.stdout and used to print subtest info and dump failed log. test_{v,}printf are now simple wrappers around stdout and will be removed in the next patch. v5: * fix -v crash by always setting env.std{in,err} (Alexei Starovoitov) * drop force_log check from stdio_hijack (Andrii Nakryiko) v4: * one field per line for stdout/stderr (Andrii Nakryiko) v3: * don't do strlen over log_buf, log_cnt has it already (Andrii Nakryiko) v2: * add ifdef __GLIBC__ around open_memstream (maybe pointless since we already depend on glibc for argp_parse) * hijack stderr as well (Andrii Nakryiko) * don't hijack for every test, do it once (Andrii Nakryiko) * log_cap -> log_size (Andrii Nakryiko) * do fseeko in a proper place (Andrii Nakryiko) * check open_memstream returned value (Andrii Nakryiko) Cc: Andrii Nakryiko Acked-by: Andrii Nakryiko Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_progs.c | 115 ++++++++++++----------- tools/testing/selftests/bpf/test_progs.h | 3 +- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index db00196c8315..6ea289ba307b 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -40,14 +40,20 @@ static bool should_run(struct test_selector *sel, int num, const char *name) static void dump_test_log(const struct prog_test_def *test, bool failed) { + if (stdout == env.stdout) + return; + + fflush(stdout); /* exports env.log_buf & env.log_cnt */ + if (env.verbose || test->force_log || failed) { if (env.log_cnt) { - fprintf(stdout, "%s", env.log_buf); + fprintf(env.stdout, "%s", env.log_buf); if (env.log_buf[env.log_cnt - 1] != '\n') - fprintf(stdout, "\n"); + fprintf(env.stdout, "\n"); } } - env.log_cnt = 0; + + fseeko(stdout, 0, SEEK_SET); /* rewind */ } void test__end_subtest() @@ -62,7 +68,7 @@ void test__end_subtest() dump_test_log(test, sub_error_cnt); - printf("#%d/%d %s:%s\n", + fprintf(env.stdout, "#%d/%d %s:%s\n", test->test_num, test->subtest_num, test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); } @@ -79,7 +85,8 @@ bool test__start_subtest(const char *name) test->subtest_num++; if (!name || !name[0]) { - fprintf(stderr, "Subtest #%d didn't provide sub-test name!\n", + fprintf(env.stderr, + "Subtest #%d didn't provide sub-test name!\n", test->subtest_num); return false; } @@ -100,53 +107,7 @@ void test__force_log() { void test__vprintf(const char *fmt, va_list args) { - size_t rem_sz; - int ret = 0; - - if (env.verbose || (env.test && env.test->force_log)) { - vfprintf(stderr, fmt, args); - return; - } - -try_again: - rem_sz = env.log_cap - env.log_cnt; - if (rem_sz) { - va_list ap; - - va_copy(ap, args); - /* we reserved extra byte for \0 at the end */ - ret = vsnprintf(env.log_buf + env.log_cnt, rem_sz + 1, fmt, ap); - va_end(ap); - - if (ret < 0) { - env.log_buf[env.log_cnt] = '\0'; - fprintf(stderr, "failed to log w/ fmt '%s'\n", fmt); - return; - } - } - - if (!rem_sz || ret > rem_sz) { - size_t new_sz = env.log_cap * 3 / 2; - char *new_buf; - - if (new_sz < 4096) - new_sz = 4096; - if (new_sz < ret + env.log_cnt) - new_sz = ret + env.log_cnt; - - /* +1 for guaranteed space for terminating \0 */ - new_buf = realloc(env.log_buf, new_sz + 1); - if (!new_buf) { - fprintf(stderr, "failed to realloc log buffer: %d\n", - errno); - return; - } - env.log_buf = new_buf; - env.log_cap = new_sz; - goto try_again; - } - - env.log_cnt += ret; + vprintf(fmt, args); } void test__printf(const char *fmt, ...) @@ -477,6 +438,48 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) return 0; } +static void stdio_hijack(void) +{ +#ifdef __GLIBC__ + env.stdout = stdout; + env.stderr = stderr; + + if (env.verbose) { + /* nothing to do, output to stdout by default */ + return; + } + + /* stdout and stderr -> buffer */ + fflush(stdout); + + stdout = open_memstream(&env.log_buf, &env.log_cnt); + if (!stdout) { + stdout = env.stdout; + perror("open_memstream"); + return; + } + + stderr = stdout; +#endif +} + +static void stdio_restore(void) +{ +#ifdef __GLIBC__ + if (stdout == env.stdout) + return; + + fclose(stdout); + free(env.log_buf); + + env.log_buf = NULL; + env.log_cnt = 0; + + stdout = env.stdout; + stderr = env.stderr; +#endif +} + int main(int argc, char **argv) { static const struct argp argp = { @@ -496,6 +499,7 @@ int main(int argc, char **argv) env.jit_enabled = is_jit_enabled(); + stdio_hijack(); for (i = 0; i < prog_test_cnt; i++) { struct prog_test_def *test = &prog_test_defs[i]; int old_pass_cnt = pass_cnt; @@ -523,13 +527,14 @@ int main(int argc, char **argv) dump_test_log(test, test->error_cnt); - printf("#%d %s:%s\n", test->test_num, test->test_name, - test->error_cnt ? "FAIL" : "OK"); + fprintf(env.stdout, "#%d %s:%s\n", + test->test_num, test->test_name, + test->error_cnt ? "FAIL" : "OK"); } + stdio_restore(); printf("Summary: %d/%d PASSED, %d FAILED\n", env.succ_cnt, env.sub_succ_cnt, env.fail_cnt); - free(env.log_buf); free(env.test_selector.num_set); free(env.subtest_selector.num_set); diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index afd14962456f..541f9eab5eed 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -56,9 +56,10 @@ struct test_env { bool jit_enabled; struct prog_test_def *test; + FILE *stdout; + FILE *stderr; char *log_buf; size_t log_cnt; - size_t log_cap; int succ_cnt; /* successful tests */ int sub_succ_cnt; /* successful sub-tests */ -- GitLab From 66bd2ec1e0d9781133eb1a14eddb68facc69d54b Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Tue, 6 Aug 2019 10:45:28 -0700 Subject: [PATCH 2132/7155] selftests/bpf: test_progs: test__printf -> printf Now that test__printf is a simple wraper around printf, let's drop it (and test__vprintf as well). Cc: Andrii Nakryiko Acked-by: Andrii Nakryiko Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/bpf_verif_scale.c | 4 ++-- .../testing/selftests/bpf/prog_tests/l4lb_all.c | 2 +- .../testing/selftests/bpf/prog_tests/map_lock.c | 10 +++++----- .../selftests/bpf/prog_tests/send_signal.c | 4 ++-- .../testing/selftests/bpf/prog_tests/spinlock.c | 2 +- .../bpf/prog_tests/stacktrace_build_id.c | 4 ++-- .../bpf/prog_tests/stacktrace_build_id_nmi.c | 4 ++-- .../selftests/bpf/prog_tests/xdp_noinline.c | 4 ++-- tools/testing/selftests/bpf/test_progs.c | 16 +--------------- tools/testing/selftests/bpf/test_progs.h | 10 ++++------ 10 files changed, 22 insertions(+), 38 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c index 0caf8eafa9eb..1a1eae356f81 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c @@ -5,13 +5,13 @@ static int libbpf_debug_print(enum libbpf_print_level level, const char *format, va_list args) { if (level != LIBBPF_DEBUG) { - test__vprintf(format, args); + vprintf(format, args); return 0; } if (!strstr(format, "verifier log")) return 0; - test__vprintf("%s", args); + vprintf("%s", args); return 0; } diff --git a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c index 5ce572c03a5f..20ddca830e68 100644 --- a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c +++ b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c @@ -74,7 +74,7 @@ static void test_l4lb(const char *file) } if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) { error_cnt++; - test__printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts); + printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts); } out: bpf_object__close(obj); diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c index 2e78217ed3fd..ee99368c595c 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_lock.c +++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c @@ -9,12 +9,12 @@ static void *parallel_map_access(void *arg) for (i = 0; i < 10000; i++) { err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK); if (err) { - test__printf("lookup failed\n"); + printf("lookup failed\n"); error_cnt++; goto out; } if (vars[0] != 0) { - test__printf("lookup #%d var[0]=%d\n", i, vars[0]); + printf("lookup #%d var[0]=%d\n", i, vars[0]); error_cnt++; goto out; } @@ -22,8 +22,8 @@ static void *parallel_map_access(void *arg) for (j = 2; j < 17; j++) { if (vars[j] == rnd) continue; - test__printf("lookup #%d var[1]=%d var[%d]=%d\n", - i, rnd, j, vars[j]); + printf("lookup #%d var[1]=%d var[%d]=%d\n", + i, rnd, j, vars[j]); error_cnt++; goto out; } @@ -43,7 +43,7 @@ void test_map_lock(void) err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); if (err) { - test__printf("test_map_lock:bpf_prog_load errno %d\n", errno); + printf("test_map_lock:bpf_prog_load errno %d\n", errno); goto close_prog; } map_fd[0] = bpf_find_map(__func__, obj, "hash_map"); diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c index 461b423d0584..1575f0a1f586 100644 --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c @@ -202,8 +202,8 @@ static int test_send_signal_nmi(void) -1 /* cpu */, -1 /* group_fd */, 0 /* flags */); if (pmu_fd == -1) { if (errno == ENOENT) { - test__printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", - __func__); + printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", + __func__); return 0; } /* Let the test fail with a more informative message */ diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c index deb2db5b85b0..114ebe6a438e 100644 --- a/tools/testing/selftests/bpf/prog_tests/spinlock.c +++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c @@ -12,7 +12,7 @@ void test_spinlock(void) err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); if (err) { - test__printf("test_spin_lock:bpf_prog_load errno %d\n", errno); + printf("test_spin_lock:bpf_prog_load errno %d\n", errno); goto close_prog; } for (i = 0; i < 4; i++) diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c index 356d2c017a9c..ac44fda84833 100644 --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c @@ -109,8 +109,8 @@ void test_stacktrace_build_id(void) if (build_id_matches < 1 && retry--) { bpf_link__destroy(link); bpf_object__close(obj); - test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", - __func__); + printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", + __func__); goto retry; } diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c index f44f2c159714..9557b7dfb782 100644 --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c @@ -140,8 +140,8 @@ void test_stacktrace_build_id_nmi(void) if (build_id_matches < 1 && retry--) { bpf_link__destroy(link); bpf_object__close(obj); - test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", - __func__); + printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", + __func__); goto retry; } diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c index b5404494b8aa..15f7c272edb0 100644 --- a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c +++ b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c @@ -75,8 +75,8 @@ void test_xdp_noinline(void) } if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) { error_cnt++; - test__printf("test_xdp_noinline:FAIL:stats %lld %lld\n", - bytes, pkts); + printf("test_xdp_noinline:FAIL:stats %lld %lld\n", + bytes, pkts); } out: bpf_object__close(obj); diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 6ea289ba307b..6c11c796ea1f 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -105,20 +105,6 @@ void test__force_log() { env.test->force_log = true; } -void test__vprintf(const char *fmt, va_list args) -{ - vprintf(fmt, args); -} - -void test__printf(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - test__vprintf(fmt, args); - va_end(args); -} - struct ipv4_packet pkt_v4 = { .eth.h_proto = __bpf_constant_htons(ETH_P_IP), .iph.ihl = 5, @@ -310,7 +296,7 @@ static int libbpf_print_fn(enum libbpf_print_level level, { if (!env.very_verbose && level == LIBBPF_DEBUG) return 0; - test__vprintf(format, args); + vprintf(format, args); return 0; } diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 541f9eab5eed..37d427f5a1e5 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -70,8 +70,6 @@ extern int error_cnt; extern int pass_cnt; extern struct test_env env; -extern void test__printf(const char *fmt, ...); -extern void test__vprintf(const char *fmt, va_list args); extern void test__force_log(); extern bool test__start_subtest(const char *name); @@ -97,12 +95,12 @@ extern struct ipv6_packet pkt_v6; int __ret = !!(condition); \ if (__ret) { \ error_cnt++; \ - test__printf("%s:FAIL:%s ", __func__, tag); \ - test__printf(format); \ + printf("%s:FAIL:%s ", __func__, tag); \ + printf(format); \ } else { \ pass_cnt++; \ - test__printf("%s:PASS:%s %d nsec\n", \ - __func__, tag, duration); \ + printf("%s:PASS:%s %d nsec\n", \ + __func__, tag, duration); \ } \ __ret; \ }) -- GitLab From 16e910d4467ccdf1cae5035e71035e5f7197e77d Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Tue, 6 Aug 2019 10:45:29 -0700 Subject: [PATCH 2133/7155] selftests/bpf: test_progs: drop extra trailing tab Small (un)related cleanup. Cc: Andrii Nakryiko Acked-by: Andrii Nakryiko Signed-off-by: Stanislav Fomichev Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/test_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 6c11c796ea1f..12895d03d58b 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -278,7 +278,7 @@ enum ARG_KEYS { ARG_VERIFIER_STATS = 's', ARG_VERBOSE = 'v', }; - + static const struct argp_option opts[] = { { "num", ARG_TEST_NUM, "NUM", 0, "Run test number NUM only " }, -- GitLab From 7bea41c4a25675a32bc3a63cfbd98099fdfb2695 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 6 Aug 2019 19:23:56 -0700 Subject: [PATCH 2134/7155] soc: qcom: socinfo: Annotate switch cases with fall through Introduce fall through annotations in the switch statements of socinfo_debugfs_init() to silence compiler warnings. Acked-by: Vaishali Thakkar Fixes: 9c84c1e78634 ("soc: qcom: socinfo: Expose custom attributes") Reported-by: Stephen Rothwell Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 855353bed19e..a39ea5061dc5 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -323,6 +323,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_x32("raw_device_number", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_num); + /* Fall through */ case SOCINFO_VERSION(0, 11): case SOCINFO_VERSION(0, 10): case SOCINFO_VERSION(0, 9): @@ -330,10 +331,12 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.foundry_id); + /* Fall through */ case SOCINFO_VERSION(0, 8): case SOCINFO_VERSION(0, 7): DEBUGFS_ADD(info, pmic_model); DEBUGFS_ADD(info, pmic_die_rev); + /* Fall through */ case SOCINFO_VERSION(0, 6): qcom_socinfo->info.hw_plat_subtype = __le32_to_cpu(info->hw_plat_subtype); @@ -341,6 +344,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("hardware_platform_subtype", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat_subtype); + /* Fall through */ case SOCINFO_VERSION(0, 5): qcom_socinfo->info.accessory_chip = __le32_to_cpu(info->accessory_chip); @@ -348,23 +352,27 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("accessory_chip", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.accessory_chip); + /* Fall through */ case SOCINFO_VERSION(0, 4): qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); debugfs_create_u32("platform_version", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.plat_ver); + /* Fall through */ case SOCINFO_VERSION(0, 3): qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); debugfs_create_u32("hardware_platform", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat); + /* Fall through */ case SOCINFO_VERSION(0, 2): qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_ver); + /* Fall through */ case SOCINFO_VERSION(0, 1): DEBUGFS_ADD(info, build_id); break; -- GitLab From 8faa1cf6ed82f33009f63986c3776cc48af1b7b2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 24 Jun 2019 16:47:17 +0300 Subject: [PATCH 2135/7155] EDAC/altera: Use the proper type for the IRQ status bits Smatch complains about the cast of a u32 pointer to unsigned long: drivers/edac/altera_edac.c:1878 altr_edac_a10_irq_handler() warn: passing casted pointer '&irq_status' to 'find_first_bit()' This code wouldn't work on a 64 bit big endian system because it would read past the end of &irq_status. [ bp: massage. ] Fixes: 13ab8448d2c9 ("EDAC, altera: Add ECC Manager IRQ controller support") Signed-off-by: Dan Carpenter Signed-off-by: Borislav Petkov Reviewed-by: Thor Thayer Cc: James Morse Cc: kernel-janitors@vger.kernel.org Cc: linux-edac Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190624134717.GA1754@mwanda --- drivers/edac/altera_edac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 09a80b53acea..fbda4b876afd 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -1886,6 +1886,7 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc) struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); int irq = irq_desc_get_irq(desc); + unsigned long bits; dberr = (irq == edac->db_irq) ? 1 : 0; sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST : @@ -1895,7 +1896,8 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc) regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status); - for_each_set_bit(bit, (unsigned long *)&irq_status, 32) { + bits = irq_status; + for_each_set_bit(bit, &bits, 32) { irq = irq_linear_revmap(edac->domain, dberr * 32 + bit); if (irq) generic_handle_irq(irq); -- GitLab From 683df830e6bd12e9eb7da1fbdfccc6ac444508ae Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 6 Aug 2019 11:50:29 +0200 Subject: [PATCH 2136/7155] cpufreq: mediatek-cpufreq: Add compatible for MT8516 Add the compatible for MT8516 in order to take advantage of the MediaTek CPUFreq driver for Mediatek's MT8516 SoC. Signed-off-by: Fabien Parent Signed-off-by: Viresh Kumar --- drivers/cpufreq/mediatek-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index f14f3a85f2f7..10bc06f5dd45 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -535,6 +535,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { { .compatible = "mediatek,mt817x", }, { .compatible = "mediatek,mt8173", }, { .compatible = "mediatek,mt8176", }, + { .compatible = "mediatek,mt8516", }, { } }; -- GitLab From b71b283e3d6df40cef03b5ce882b2385971f58a3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:51 +0200 Subject: [PATCH 2137/7155] USB: add support for dev_groups to struct usb_driver Now that the driver core supports dev_groups for individual drivers, expose that pointer to struct usb_driver to make it easier for USB drivers to also use it. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190806144502.17792-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 1 + include/linux/usb.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ebcadaad89d1..687fc5df4c17 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -954,6 +954,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, new_driver->drvwrap.driver.remove = usb_unbind_interface; new_driver->drvwrap.driver.owner = owner; new_driver->drvwrap.driver.mod_name = mod_name; + new_driver->drvwrap.driver.dev_groups = new_driver->dev_groups; spin_lock_init(&new_driver->dynids.lock); INIT_LIST_HEAD(&new_driver->dynids.list); diff --git a/include/linux/usb.h b/include/linux/usb.h index 83d35d993e8c..af4eb6419ae8 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1151,6 +1151,8 @@ struct usbdrv_wrap { * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. + * @dev_groups: Attributes attached to the device that will be created once it + * is bound to the driver. * @dynids: used internally to hold the list of dynamically added device * ids for this driver. * @drvwrap: Driver-model core structure wrapper. @@ -1198,6 +1200,7 @@ struct usb_driver { int (*post_reset)(struct usb_interface *intf); const struct usb_device_id *id_table; + const struct attribute_group **dev_groups; struct usb_dynids dynids; struct usbdrv_wrap drvwrap; -- GitLab From 7d9c1d2f7aca2651b3821947bf928ee131df102a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:52 +0200 Subject: [PATCH 2138/7155] USB: add support for dev_groups to struct usb_device_driver Now that the driver core supports dev_groups for individual drivers, expose that pointer to struct usb_device_driver to make it easier for USB drivers to also use it. Yes, users of usb_device_driver are much rare, but there are instances already that use custom sysfs files, so adding this support will make things easier for those drivers. usbip is one example, hubs might be another one. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190806144502.17792-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 1 + include/linux/usb.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 687fc5df4c17..2b27d232d7a7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -892,6 +892,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, new_udriver->drvwrap.driver.probe = usb_probe_device; new_udriver->drvwrap.driver.remove = usb_unbind_device; new_udriver->drvwrap.driver.owner = owner; + new_udriver->drvwrap.driver.dev_groups = new_udriver->dev_groups; retval = driver_register(&new_udriver->drvwrap.driver); diff --git a/include/linux/usb.h b/include/linux/usb.h index af4eb6419ae8..57f667cad3ec 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1224,6 +1224,8 @@ struct usb_driver { * module is being unloaded. * @suspend: Called when the device is going to be suspended by the system. * @resume: Called when the device is being resumed by the system. + * @dev_groups: Attributes attached to the device that will be created once it + * is bound to the driver. * @drvwrap: Driver-model core structure wrapper. * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend * for devices bound to this driver. @@ -1238,6 +1240,7 @@ struct usb_device_driver { int (*suspend) (struct usb_device *udev, pm_message_t message); int (*resume) (struct usb_device *udev, pm_message_t message); + const struct attribute_group **dev_groups; struct usbdrv_wrap drvwrap; unsigned int supports_autosuspend:1; }; -- GitLab From 40b0bcd3e0e258cff3382717fb287f8be161a398 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Wed, 7 Aug 2019 10:12:54 +0800 Subject: [PATCH 2139/7155] gpio: mpc8xxx: Add new platforms GPIO DT node description Update the NXP GPIO node dt-binding file for QorIQ and Layerscape platforms, and add one more example with ls1028a GPIO node. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190807021254.49092-1-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-mpc8xxx.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index 69d46162d0f5..baf95d93f85d 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -4,7 +4,7 @@ Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, - ls1021a, ls1043a, ls2080a. + ls1021a, ls1043a, ls2080a, ls1028a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -37,3 +37,17 @@ gpio0: gpio@2300000 { interrupt-controller; #interrupt-cells = <2>; }; + + +Example of gpio-controller node for a ls1028a SoC: + +gpio1: gpio@2300000 { + compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + little-endian; +}; -- GitLab From 45880f7b7b19e043ce0aaa4cb7d05369425c82fa Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Tue, 6 Aug 2019 18:00:13 +0800 Subject: [PATCH 2140/7155] error-injection: Consolidate override function definition The function override_function_with_return() is defined separately for each architecture and every architecture's definition is almost same with each other. E.g. x86 and powerpc both define function in its own asm/error-injection.h header and override_function_with_return() has the same definition, the only difference is that x86 defines an extra function just_return_func() but it is specific for x86 and is only used by x86's override_function_with_return(), so don't need to export this function. This patch consolidates override_function_with_return() definition into asm-generic/error-injection.h header, thus all architectures can use the common definition. As result, the architecture specific headers are removed; the include/linux/error-injection.h header also changes to include asm-generic/error-injection.h header rather than architecture header, furthermore, it includes linux/compiler.h for successful compilation. Reviewed-by: Masami Hiramatsu Signed-off-by: Leo Yan Signed-off-by: Will Deacon --- arch/powerpc/include/asm/error-injection.h | 13 ------------- arch/x86/include/asm/error-injection.h | 13 ------------- include/asm-generic/error-injection.h | 6 ++++++ include/linux/error-injection.h | 6 +++--- 4 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 arch/powerpc/include/asm/error-injection.h delete mode 100644 arch/x86/include/asm/error-injection.h diff --git a/arch/powerpc/include/asm/error-injection.h b/arch/powerpc/include/asm/error-injection.h deleted file mode 100644 index 62fd24739852..000000000000 --- a/arch/powerpc/include/asm/error-injection.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ - -#ifndef _ASM_ERROR_INJECTION_H -#define _ASM_ERROR_INJECTION_H - -#include -#include -#include -#include - -void override_function_with_return(struct pt_regs *regs); - -#endif /* _ASM_ERROR_INJECTION_H */ diff --git a/arch/x86/include/asm/error-injection.h b/arch/x86/include/asm/error-injection.h deleted file mode 100644 index 47b7a1296245..000000000000 --- a/arch/x86/include/asm/error-injection.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_ERROR_INJECTION_H -#define _ASM_ERROR_INJECTION_H - -#include -#include -#include -#include - -asmlinkage void just_return_func(void); -void override_function_with_return(struct pt_regs *regs); - -#endif /* _ASM_ERROR_INJECTION_H */ diff --git a/include/asm-generic/error-injection.h b/include/asm-generic/error-injection.h index 95a159a4137f..80ca61058dd2 100644 --- a/include/asm-generic/error-injection.h +++ b/include/asm-generic/error-injection.h @@ -16,6 +16,8 @@ struct error_injection_entry { int etype; }; +struct pt_regs; + #ifdef CONFIG_FUNCTION_ERROR_INJECTION /* * Whitelist ganerating macro. Specify functions which can be @@ -28,8 +30,12 @@ static struct error_injection_entry __used \ .addr = (unsigned long)fname, \ .etype = EI_ETYPE_##_etype, \ }; + +void override_function_with_return(struct pt_regs *regs); #else #define ALLOW_ERROR_INJECTION(fname, _etype) + +static inline void override_function_with_return(struct pt_regs *regs) { } #endif #endif diff --git a/include/linux/error-injection.h b/include/linux/error-injection.h index 280c61ecbf20..635a95caf29f 100644 --- a/include/linux/error-injection.h +++ b/include/linux/error-injection.h @@ -2,16 +2,16 @@ #ifndef _LINUX_ERROR_INJECTION_H #define _LINUX_ERROR_INJECTION_H -#ifdef CONFIG_FUNCTION_ERROR_INJECTION +#include +#include -#include +#ifdef CONFIG_FUNCTION_ERROR_INJECTION extern bool within_error_injection_list(unsigned long addr); extern int get_injectable_error_type(unsigned long addr); #else /* !CONFIG_FUNCTION_ERROR_INJECTION */ -#include static inline bool within_error_injection_list(unsigned long addr) { return false; -- GitLab From 42d038c4fb00f1ec1a4c4616784da4561385b628 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Tue, 6 Aug 2019 18:00:14 +0800 Subject: [PATCH 2141/7155] arm64: Add support for function error injection Inspired by the commit 7cd01b08d35f ("powerpc: Add support for function error injection"), this patch supports function error injection for Arm64. This patch mainly support two functions: one is regs_set_return_value() which is used to overwrite the return value; the another function is override_function_with_return() which is to override the probed function returning and jump to its caller. Reviewed-by: Masami Hiramatsu Signed-off-by: Leo Yan Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/ptrace.h | 5 +++++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/error-inject.c | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+) create mode 100644 arch/arm64/lib/error-inject.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3adcec05b1f6..b15803afb2a0 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -148,6 +148,7 @@ config ARM64 select HAVE_FAST_GUP select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_TRACER select HAVE_GCC_PLUGINS select HAVE_HW_BREAKPOINT if PERF_EVENTS diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index 1dcf63a9ac1f..fbebb411ae20 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -301,6 +301,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) return regs->regs[0]; } +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) +{ + regs->regs[0] = rc; +} + /** * regs_get_kernel_argument() - get Nth function argument in kernel * @regs: pt_regs of that context diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 33c2a4abda04..f182ccb0438e 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -33,3 +33,5 @@ UBSAN_SANITIZE_atomic_ll_sc.o := n lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o obj-$(CONFIG_CRC32) += crc32.o + +obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o diff --git a/arch/arm64/lib/error-inject.c b/arch/arm64/lib/error-inject.c new file mode 100644 index 000000000000..ed15021da3ed --- /dev/null +++ b/arch/arm64/lib/error-inject.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void override_function_with_return(struct pt_regs *regs) +{ + /* + * 'regs' represents the state on entry of a predefined function in + * the kernel/module and which is captured on a kprobe. + * + * When kprobe returns back from exception it will override the end + * of probed function and directly return to the predefined + * function's caller. + */ + instruction_pointer_set(regs, procedure_link_pointer(regs)); +} +NOKPROBE_SYMBOL(override_function_with_return); -- GitLab From 06e8f5c842f2dbb232897ba967ea7b422745c271 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 6 Aug 2019 12:45:38 +0900 Subject: [PATCH 2142/7155] ASoC: rsnd: don't call clk_get_rate() under atomic context ADG is using clk_get_rate() under atomic context, thus, we might have scheduling issue. To avoid this issue, we need to get/keep clk rate under non atomic context. We need to handle ADG as special device at Renesas Sound driver. From SW point of view, we want to impletent it as rsnd_mod_ops :: prepare, but it makes code just complicate. To avoid complicated code/patch, this patch adds new clk_rate[] array, and keep clk IN rate when rsnd_adg_clk_enable() was called. Reported-by: Leon Kong Signed-off-by: Kuninori Morimoto Tested-by: Leon Kong Link: https://lore.kernel.org/r/87v9vb0xkp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index fce4e050a9b7..b9aacf3d3b29 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,7 @@ struct rsnd_adg { struct clk *clkout[CLKOUTMAX]; struct clk_onecell_data onecell; struct rsnd_mod mod; + int clk_rate[CLKMAX]; u32 flags; u32 ckr; u32 rbga; @@ -114,9 +115,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, unsigned int val, en; unsigned int min, diff; unsigned int sel_rate[] = { - clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ - clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ - clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->clk_rate[CLKA], /* 0000: CLKA */ + adg->clk_rate[CLKB], /* 0001: CLKB */ + adg->clk_rate[CLKC], /* 0010: CLKC */ adg->rbga_rate_for_441khz, /* 0011: RBGA */ adg->rbgb_rate_for_48khz, /* 0100: RBGB */ }; @@ -302,7 +303,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. */ for_each_rsnd_clk(clk, adg, i) { - if (rate == clk_get_rate(clk)) + if (rate == adg->clk_rate[i]) return sel_table[i]; } @@ -369,10 +370,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) for_each_rsnd_clk(clk, adg, i) { ret = 0; - if (enable) + if (enable) { ret = clk_prepare_enable(clk); - else + + /* + * We shouldn't use clk_get_rate() under + * atomic context. Let's keep it when + * rsnd_adg_clk_enable() was called + */ + adg->clk_rate[i] = clk_get_rate(adg->clk[i]); + } else { clk_disable_unprepare(clk); + } if (ret < 0) dev_warn(dev, "can't use clk %d\n", i); -- GitLab From cc352735d49c9c25fd711795bee35d3d001ddffa Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 6 Aug 2019 15:19:58 -0700 Subject: [PATCH 2143/7155] ASoC: SOF: Intel: hda: Initialize HDA controller after i915 init On some platforms, sound card registration fails when a HDMI monitor is not connected. This is caused by a recent commit that switched the order in which the HDA controller and the i915 are initialized. Initializing the i915 before initializing the HDA controller fixes the problem. Fixes: be1b577d01787c ("ASoC: SOF: Intel: hda: fix the hda init chip" Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20190806221958.19180-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 136f98bf5d7e..82f61c4e74bd 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -321,10 +321,23 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->ppcap) dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* init i915 and HDMI codecs */ + ret = hda_codec_i915_init(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n"); + return ret; + } +#endif + + /* Init HDA controller after i915 init */ ret = hda_dsp_ctrl_init_chip(sdev, true); if (ret < 0) { dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + hda_codec_i915_exit(sdev); +#endif return ret; } @@ -332,13 +345,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - /* init i915 and HDMI codecs */ - ret = hda_codec_i915_init(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: no HDMI audio devices found\n"); - return ret; - } - /* codec detection */ if (!bus->codec_mask) { dev_info(bus->dev, "no hda codecs found!\n"); -- GitLab From 3403b808a0eb6d25883b72a6c4d2a4a452f8a233 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 6 Aug 2019 17:14:35 +0800 Subject: [PATCH 2144/7155] ASoC: rt1011: Add R0 temperature and TDM1 ADC2DAT Swap control - The user level application could set the R0 temperature after booting system. The degree Celsius of R0 temperature store in the non-volatile space when doing R0 calibration. - TDM1 ADC2DAT Swap controls use to control TDM slot2/3 data Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190806091435.14329-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 9 ++++++++- sound/soc/codecs/rt1011.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 0a6ff13d76e1..b25b4c1127ca 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1029,6 +1029,8 @@ static const char * const rt1011_tdm_adc_swap_select[] = { static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6, rt1011_tdm_adc_swap_select); +static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum, RT1011_TDM1_SET_3, 4, + rt1011_tdm_adc_swap_select); static void rt1011_reset(struct regmap *regmap) { @@ -1333,7 +1335,8 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = { /* TDM1 Data Out Selection */ SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum), SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum), - SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum), + SOC_ENUM("TDM1 ADC1DAT Swap Select", rt1011_tdm_adc1_1_enum), + SOC_ENUM("TDM1 ADC2DAT Swap Select", rt1011_tdm_adc2_1_enum), /* Data Out Mode */ SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum), @@ -1355,6 +1358,10 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = { SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0, rt1011_r0_cali_get, rt1011_r0_cali_put), RT1011_R0_LOAD("R0 Load Mode"), + + /* R0 temperature */ + SOC_SINGLE("R0 Temperature", RT1011_STP_INITIAL_RESISTANCE_TEMP, + 2, 255, 0), }; static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, diff --git a/sound/soc/codecs/rt1011.h b/sound/soc/codecs/rt1011.h index 98a38800c4df..5d431d7f1d16 100644 --- a/sound/soc/codecs/rt1011.h +++ b/sound/soc/codecs/rt1011.h @@ -227,6 +227,7 @@ #define RT1011_STP_CALIB_RS_TEMP 0x152a #define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538 #define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539 +#define RT1011_STP_INITIAL_RESISTANCE_TEMP 0x153c #define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e #define RT1011_SPK_RESISTANCE_1 0x1544 #define RT1011_SPK_RESISTANCE_2 0x1546 -- GitLab From 0922c7a51c775b71a297598623debe9cb6ce3a08 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 6 Aug 2019 17:14:59 +0800 Subject: [PATCH 2145/7155] ASoC: rt1011: Add a flag for the R0 calibration test The factory test needs to know whether the calibration completed. This flag helps to confirm the calibration completed or not. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20190806091459.14382-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 14 +++++++++++++- sound/soc/codecs/rt1011.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index b25b4c1127ca..638abcaf52b3 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1225,7 +1225,10 @@ static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol, static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = 0; + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rt1011->cali_done; return 0; } @@ -1239,6 +1242,7 @@ static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol, if (!component->card->instantiated) return 0; + rt1011->cali_done = 0; if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF && ucontrol->value.integer.value[0]) rt1011_calibrate(rt1011, 1); @@ -2135,6 +2139,7 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag) r0_factor = ((format / r0[0] * 100) / 128) - (r0_integer * 100); rt1011->r0_reg = r0[0]; + rt1011->cali_done = 1; dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n", r0_integer, r0_factor, r0[0]); } @@ -2185,6 +2190,13 @@ static void rt1011_calibration_work(struct work_struct *work) rt1011_calibrate(rt1011, 1); + /* + * This flag should reset after booting. + * The factory test will do calibration again and use this flag to check + * whether the calibration completed + */ + rt1011->cali_done = 0; + /* initial */ rt1011_reg_init(component); } diff --git a/sound/soc/codecs/rt1011.h b/sound/soc/codecs/rt1011.h index 5d431d7f1d16..2d65983f3d0f 100644 --- a/sound/soc/codecs/rt1011.h +++ b/sound/soc/codecs/rt1011.h @@ -666,7 +666,7 @@ struct rt1011_priv { int pll_out; int bq_drc_set; - unsigned int r0_reg; + unsigned int r0_reg, cali_done; int recv_spk_mode; }; -- GitLab From bb67dd1878de5766c24fe7a4002d1a12c14da518 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 6 Aug 2019 12:06:03 -0500 Subject: [PATCH 2146/7155] ASoC: SOF: Intel: hda: fix MSI handling The addition of a kernel module parameter to optionally disable MSI had the side effect of permanently disabling it. The return value of pci_alloc_irq_vectors() is the number of allocated vectors or a negative number on error, so testing with the ! operator is not quite right. It was one optimization too far. Restore previous behavior to use MSI by default, unless the user selects not to do so or the allocation of irq_vectors fails. Fixes: 672ff5e3596ee ('ASoC: SOF: Intel: hda: add a parameter to disable MSI') Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190806170603.10815-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 79cce20666b6..53813de7844e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -537,7 +537,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * if it fails, use legacy interrupt mode * TODO: support msi multiple vectors */ - if (hda_use_msi && !pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI)) { + if (hda_use_msi && pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) > 0) { dev_info(sdev->dev, "use msi interrupt mode\n"); hdev->irq = pci_irq_vector(pci, 0); /* ipc irq number is the same of hda irq */ -- GitLab From 371be51a925a619f1fb149b8d7707e353d9c9f86 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 6 Aug 2019 18:12:14 +0300 Subject: [PATCH 2147/7155] ASoC: dt-bindings: Introduce compatible strings for 7ULP and 8MQ For i.MX7ULP and i.MX8MQ register map is changed. Add two new compatbile strings to differentiate this. Signed-off-by: Daniel Baluta Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20190806151214.6783-6-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-sai.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index 2e726b983845..e61c0dc1fc0b 100644 --- a/Documentation/devicetree/bindings/sound/fsl-sai.txt +++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt @@ -8,7 +8,8 @@ codec/DSP interfaces. Required properties: - compatible : Compatible list, contains "fsl,vf610-sai", - "fsl,imx6sx-sai" or "fsl,imx6ul-sai" + "fsl,imx6sx-sai", "fsl,imx6ul-sai", + "fsl,imx7ulp-sai" or "fsl,imx8mq-sai". - reg : Offset and length of the register set for the device. -- GitLab From 79629d0f7ce5b38515c1716911a0181f01b91102 Mon Sep 17 00:00:00 2001 From: Rayagonda Kokatanur Date: Tue, 6 Aug 2019 15:37:50 +0530 Subject: [PATCH 2148/7155] spi: bcm-qspi: Fix BSPI QUAD and DUAL mode support when using flex mode Fix data transfer width settings based on DT field 'spi-rx-bus-width' to configure BSPI in single, dual or quad mode by using data width and not the command width. Fixes: 5f195ee7d830c ("spi: bcm-qspi: Implement the spi_mem interface") Signed-off-by: Rayagonda Kokatanur Link: https://lore.kernel.org/r/1565086070-28451-1-git-send-email-rayagonda.kokatanur@broadcom.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 584bcb018a62..285a6f463013 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -354,7 +354,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, { int bpc = 0, bpp = 0; u8 command = op->cmd.opcode; - int width = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE; + int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE; int addrlen = op->addr.nbytes; int flex_mode = 1; @@ -992,7 +992,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem, if (mspi_read) return bcm_qspi_mspi_exec_mem_op(spi, op); - ret = bcm_qspi_bspi_set_mode(qspi, op, -1); + ret = bcm_qspi_bspi_set_mode(qspi, op, 0); if (!ret) ret = bcm_qspi_bspi_exec_mem_op(spi, op); -- GitLab From eeee0d093afc2e352e15b23bca38f69aad3d689b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2149/7155] irqchip/gic-v3: Register the distributor's PA instead of its VA in fwnode Do not expose the distributor's VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 96d927f0f91a..be961c261093 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1845,7 +1845,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end) if (err) goto out_redist_unmap; - domain_handle = irq_domain_alloc_fwnode(acpi_data.dist_base); + domain_handle = irq_domain_alloc_fwnode(&dist->base_address); if (!domain_handle) { err = -ENOMEM; goto out_redist_unmap; -- GitLab From 6444b40eeda4f78f57b255dd7ecb8d3e5936eea2 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 5 Aug 2019 14:21:34 -0700 Subject: [PATCH 2150/7155] x86/apic: Annotate global config variables as "read-only after init" Mark the APIC's global config variables that are constant after boot as __ro_after_init to help document that the majority of the APIC config is not changed at runtime, and to harden the kernel a smidge. Signed-off-by: Sean Christopherson Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190805212134.12001-1-sean.j.christopherson@intel.com --- arch/x86/kernel/apic/apic.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 831274e3c09f..3a31875bd0a3 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -65,10 +65,10 @@ unsigned int num_processors; unsigned disabled_cpus; /* Processor that is doing the boot up */ -unsigned int boot_cpu_physical_apicid = -1U; +unsigned int boot_cpu_physical_apicid __ro_after_init = -1U; EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid); -u8 boot_cpu_apic_version; +u8 boot_cpu_apic_version __ro_after_init; /* * The highest APIC ID seen during enumeration. @@ -85,13 +85,13 @@ physid_mask_t phys_cpu_present_map; * disable_cpu_apicid=, mostly used for the kdump 2nd kernel to * avoid undefined behaviour caused by sending INIT from AP to BSP. */ -static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID; +static unsigned int disabled_cpu_apicid __ro_after_init = BAD_APICID; /* * This variable controls which CPUs receive external NMIs. By default, * external NMIs are delivered only to the BSP. */ -static int apic_extnmi = APIC_EXTNMI_BSP; +static int apic_extnmi __ro_after_init = APIC_EXTNMI_BSP; /* * Map cpu index to physical APIC ID @@ -114,7 +114,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_acpiid); DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID); /* Local APIC was disabled by the BIOS and enabled by the kernel */ -static int enabled_via_apicbase; +static int enabled_via_apicbase __ro_after_init; /* * Handle interrupt mode configuration register (IMCR). @@ -172,23 +172,23 @@ static __init int setup_apicpmtimer(char *s) __setup("apicpmtimer", setup_apicpmtimer); #endif -unsigned long mp_lapic_addr; -int disable_apic; +unsigned long mp_lapic_addr __ro_after_init; +int disable_apic __ro_after_init; /* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer __initdata; /* Local APIC timer works in C2 */ -int local_apic_timer_c2_ok; +int local_apic_timer_c2_ok __ro_after_init; EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); /* * Debug level, exported for io_apic.c */ -int apic_verbosity; +int apic_verbosity __ro_after_init; -int pic_mode; +int pic_mode __ro_after_init; /* Have we found an MP table */ -int smp_found_config; +int smp_found_config __ro_after_init; static struct resource lapic_resource = { .name = "Local APIC", @@ -199,7 +199,7 @@ unsigned int lapic_timer_period = 0; static void apic_pm_activate(void); -static unsigned long apic_phys; +static unsigned long apic_phys __ro_after_init; /* * Get the LAPIC version @@ -1278,7 +1278,7 @@ void __init sync_Arb_IDs(void) APIC_INT_LEVELTRIG | APIC_DM_INIT); } -enum apic_intr_mode_id apic_intr_mode; +enum apic_intr_mode_id apic_intr_mode __ro_after_init; static int __init apic_intr_mode_select(void) { -- GitLab From 5778cc77111f09fd2033c66cdf1654f542771ed0 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2151/7155] irqchip/gic-v3-its: Register the ITS' PA instead of its VA in fwnode Do not expose the ITS' VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3-its.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 1b5c3672aea2..8eeb0e284896 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3921,7 +3921,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header, res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1; res.flags = IORESOURCE_MEM; - dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address); + dom_handle = irq_domain_alloc_fwnode(&res.start); if (!dom_handle) { pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n", &res.start); -- GitLab From 188a8471ef03718709bd785d3976f6cd72bb551d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2152/7155] irqchip/gic: Register the distributor's PA instead of its VA in fwnode Do not expose the distributor's VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index e45f45e68720..b6b857377763 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1627,7 +1627,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header, /* * Initialize GIC instance zero (no multi-GIC support). */ - domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base); + domain_handle = irq_domain_alloc_fwnode(&dist->base_address); if (!domain_handle) { pr_err("Unable to allocate domain handle\n"); gic_teardown(gic); -- GitLab From 7d5b7695c22f6e22d9a16df17f477832eef8e2b7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2153/7155] irqchip/gic-v2m: Register the frame's PA instead of its VA in fwnode Do not expose the frame's VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 7338f90b2f9e..e88e75c22b6a 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header, spi_start, nr_spis); } - fwnode = irq_domain_alloc_fwnode((void *)m->base_address); + fwnode = irq_domain_alloc_fwnode(&res.start); if (!fwnode) { pr_err("Unable to allocate GICv2m domain token\n"); return -EINVAL; -- GitLab From 9adc54d4e8c56ed5851bb51314ffcbaebdfbf17e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2154/7155] irqchip/ixp4xx: Register the base PA instead of its VA in fwnode Do not expose the base VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-ixp4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c index 6751c35b7e1d..37e0749215c7 100644 --- a/drivers/irqchip/irq-ixp4xx.c +++ b/drivers/irqchip/irq-ixp4xx.c @@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase, pr_crit("IXP4XX: could not ioremap interrupt controller\n"); return; } - fwnode = irq_domain_alloc_fwnode(base); + fwnode = irq_domain_alloc_fwnode(&irqbase); if (!fwnode) { pr_crit("IXP4XX: no domain handle\n"); return; -- GitLab From daa19fe5b082779962988a5ba9e38509004db3de Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 2155/7155] gpio/ixp4xx: Register the base PA instead of its VA in fwnode Do not expose the base VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Reviewed-by: Linus Walleij Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/gpio/gpio-ixp4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 670c2a85a35b..cc72c9aca5a1 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -400,7 +400,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) g->fwnode = of_node_to_fwnode(np); } else { parent = ixp4xx_get_irq_domain(); - g->fwnode = irq_domain_alloc_fwnode(g->base); + g->fwnode = irq_domain_alloc_fwnode(&res->start); if (!g->fwnode) { dev_err(dev, "no domain base\n"); return -ENODEV; -- GitLab From 920d947af9cd528338bbfe989449489a9962142f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 7 Aug 2019 10:52:13 +0200 Subject: [PATCH 2156/7155] spi: sh-msiof: Use devm_platform_ioremap_resource() helper Use the devm_platform_ioremap_resource() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190807085213.24666-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index f73f811c9ba7..8f134735291f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1297,7 +1297,6 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p) static int sh_msiof_spi_probe(struct platform_device *pdev) { - struct resource *r; struct spi_controller *ctlr; const struct sh_msiof_chipdata *chipdata; struct sh_msiof_spi_info *info; @@ -1350,8 +1349,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) goto err1; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - p->mapbase = devm_ioremap_resource(&pdev->dev, r); + p->mapbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->mapbase)) { ret = PTR_ERR(p->mapbase); goto err1; -- GitLab From 467a3bb974320a23c0c000559cc54b64e06e9787 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Aug 2019 15:23:33 +0100 Subject: [PATCH 2157/7155] PCI: hv: Allocate a named fwnode instead of an address-based one To allocate its fwnode that is then used to allocate an irqdomain, the driver uses irq_domain_alloc_fwnode(), passing it a VA as an identifier. This is a rather bad idea, as this address ends up published in debugfs (and we want to move away from VAs there anyway). Instead, let's allocate a named fwnode by using the device GUID as an identifier. It is allegedly unique, and can be traced back to the original device. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/pci/controller/pci-hyperv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 40b625458afa..97056f3dd317 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev, const struct hv_vmbus_device_id *dev_id) { struct hv_pcibus_device *hbus; + char *name; int ret; /* @@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev, goto free_config; } - hbus->sysdata.fwnode = irq_domain_alloc_fwnode(hbus); + name = kasprintf(GFP_KERNEL, "%pUL", &hdev->dev_instance); + if (!name) { + ret = -ENOMEM; + goto unmap; + } + + hbus->sysdata.fwnode = irq_domain_alloc_named_fwnode(name); + kfree(name); if (!hbus->sysdata.fwnode) { ret = -ENOMEM; goto unmap; -- GitLab From b977fcf477c176e5f41775f0ea139f935b0f25b7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 15:13:19 +0100 Subject: [PATCH 2158/7155] irqdomain/debugfs: Use PAs to generate fwnode names Booting a large arm64 server (HiSi D05) leads to the following shouting at boot time: [ 20.722132] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.730851] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.739560] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.748267] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.756975] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.765683] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! [ 20.774391] debugfs: File 'irqchip@(____ptrval____)-3' in directory 'domains' already present! and many more... Evidently, we expect something a bit more informative than ____ptrval____, and certainly we want all of our domains, not just the first one. For that, turn the %p used to generate the fwnode name into something that won't be repainted (%pa). Given that we've now fixed all users to pass a pointer to a PA, it will actually do the right thing. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- include/linux/irqdomain.h | 6 +++--- kernel/irq/irqdomain.c | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 07ec8b390161..583e7abd07f9 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -220,7 +220,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) #ifdef CONFIG_IRQ_DOMAIN struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, - const char *name, void *data); + const char *name, phys_addr_t *pa); enum { IRQCHIP_FWNODE_REAL, @@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id) NULL); } -static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data) +static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa) { - return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data); + return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, pa); } void irq_domain_free_fwnode(struct fwnode_handle *fwnode); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3078d0e48bba..e7bbab149750 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -31,7 +31,7 @@ struct irqchip_fwid { struct fwnode_handle fwnode; unsigned int type; char *name; - void *data; + phys_addr_t *pa; }; #ifdef CONFIG_GENERIC_IRQ_DEBUGFS @@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops); * domain struct. */ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, - const char *name, void *data) + const char *name, + phys_addr_t *pa) { struct irqchip_fwid *fwid; char *n; @@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, n = kasprintf(GFP_KERNEL, "%s-%d", name, id); break; default: - n = kasprintf(GFP_KERNEL, "irqchip@%p", data); + n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa); break; } @@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, fwid->type = type; fwid->name = n; - fwid->data = data; + fwid->pa = pa; fwid->fwnode.ops = &irqchip_fwnode_ops; return &fwid->fwnode; } -- GitLab From ad64bfbd09d7b7997a1b1510983350836bcd6ed9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:13 +0900 Subject: [PATCH 2159/7155] ASoC: soc-core: set component->debugfs_root NULL To be more safety code, let's set NULL to component->debugfs_root when it was cleanuped. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87muglahq0.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0f75dac4bb26..2f37c4e0974b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -171,7 +171,10 @@ static void soc_init_component_debugfs(struct snd_soc_component *component) static void soc_cleanup_component_debugfs(struct snd_soc_component *component) { + if (!component->debugfs_root) + return; debugfs_remove_recursive(component->debugfs_root); + component->debugfs_root = NULL; } static int dai_list_show(struct seq_file *m, void *v) -- GitLab From 6634e3d6ea8cd92fce10d1d2da0c8e42ab84da32 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:31 +0900 Subject: [PATCH 2160/7155] ASoC: soc-core: add comment for for_each_xxx soc-core has many for_each_xxx, but it is a little bit difficult to know which list is relead to which for_each_xxx. This patch adds missing comment for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfw5ahpj.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2f37c4e0974b..5e6a48a0f79e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -380,6 +380,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) static void soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd) { + /* see for_each_card_rtds */ list_add_tail(&rtd->list, &card->rtd_list); rtd->num = card->num_rtd; card->num_rtd++; @@ -1149,6 +1150,7 @@ int snd_soc_add_dai_link(struct snd_soc_card *card, if (dai_link->dobj.type && card->add_dai_link) card->add_dai_link(card, dai_link); + /* see for_each_card_links */ list_add_tail(&dai_link->list, &card->dai_link_list); return 0; -- GitLab From 5b99a0aad08a3428cc3262ecee29a71c88c981c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:36 +0900 Subject: [PATCH 2161/7155] ASoC: soc-core: check return value of snd_soc_add_dai_link() snd_soc_add_dai_link() might return error, we need to check it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k1bpahpd.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5e6a48a0f79e..7345679d4903 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1964,8 +1964,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } /* add predefined DAI links to the list */ - for_each_card_prelinks(card, i, dai_link) - snd_soc_add_dai_link(card, dai_link); + for_each_card_prelinks(card, i, dai_link) { + ret = snd_soc_add_dai_link(card, dai_link); + if (ret < 0) + goto probe_end; + } /* card bind complete so register a sound card */ ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, -- GitLab From 42849064500b24892e2abfe8679507dfffd585f1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:41 +0900 Subject: [PATCH 2162/7155] ASoC: soc-core: don't use for_each_card_links_safe() at snd_soc_find_dai_link() It doesn't removes list during loop at snd_soc_find_dai_link(). We don't need to use _safe loop. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87imr9ahp9.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7345679d4903..e176b972e4e6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -817,11 +817,11 @@ struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card, int id, const char *name, const char *stream_name) { - struct snd_soc_dai_link *link, *_link; + struct snd_soc_dai_link *link; lockdep_assert_held(&client_mutex); - for_each_card_links_safe(card, link, _link) { + for_each_card_links(card, link) { if (link->id != id) continue; -- GitLab From 32d2c172fe88705058310635a732259c0a98e89b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:47 +0900 Subject: [PATCH 2163/7155] ASoC: soc-core: reuse rtdcom at snd_soc_rtdcom_add() snd_soc_rtdcom_add() is using both "rtdcom" and "new_rtdcom" as variable name, but these are not used at same time. Let's reuse rtdcom. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h86tahp2.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e176b972e4e6..d12054ab8741 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -274,7 +274,6 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component) { struct snd_soc_rtdcom_list *rtdcom; - struct snd_soc_rtdcom_list *new_rtdcom; for_each_rtdcom(rtd, rtdcom) { /* already connected */ @@ -282,14 +281,14 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, return 0; } - new_rtdcom = kmalloc(sizeof(*new_rtdcom), GFP_KERNEL); - if (!new_rtdcom) + rtdcom = kmalloc(sizeof(*rtdcom), GFP_KERNEL); + if (!rtdcom) return -ENOMEM; - new_rtdcom->component = component; - INIT_LIST_HEAD(&new_rtdcom->list); + rtdcom->component = component; + INIT_LIST_HEAD(&rtdcom->list); - list_add_tail(&new_rtdcom->list, &rtd->component_list); + list_add_tail(&rtdcom->list, &rtd->component_list); return 0; } -- GitLab From b8ba3b572c70c8559ef76c1e0ca02e7b05126e8c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:53 +0900 Subject: [PATCH 2164/7155] ASoC: soc-core: tidyup for snd_soc_dapm_new_controls() snd_soc_dapm_new_controls() registers controls by using for(... i < num; ...). It means if widget was NULL, num should be zero. Thus, we don't need to check about widget pointer. This patch also cares missing return value. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ftmdahow.wl-kuninori.morimoto.gx@renesas.com Reviewed-by: Ranjani Sridharan Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d12054ab8741..bb1e9e2c4ff4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1264,16 +1264,14 @@ static int soc_probe_component(struct snd_soc_card *card, soc_init_component_debugfs(component); - if (component->driver->dapm_widgets) { - ret = snd_soc_dapm_new_controls(dapm, + ret = snd_soc_dapm_new_controls(dapm, component->driver->dapm_widgets, component->driver->num_dapm_widgets); - if (ret != 0) { - dev_err(component->dev, - "Failed to create new controls %d\n", ret); - goto err_probe; - } + if (ret != 0) { + dev_err(component->dev, + "Failed to create new controls %d\n", ret); + goto err_probe; } for_each_component_dais(component, dai) { @@ -1990,13 +1988,15 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); #endif - if (card->dapm_widgets) - snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, - card->num_dapm_widgets); + ret = snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, + card->num_dapm_widgets); + if (ret < 0) + goto probe_end; - if (card->of_dapm_widgets) - snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets, - card->num_of_dapm_widgets); + ret = snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets, + card->num_of_dapm_widgets); + if (ret < 0) + goto probe_end; /* initialise the sound card only once */ if (card->probe) { -- GitLab From abf31feea26c0f412a191c83f408311a0de7435c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 23 Jul 2019 16:43:40 +0200 Subject: [PATCH 2165/7155] ASoC: Intel: Update request-reply IPC model struct ipc_message contains fields: header, tx_data and tx_size which represent TX i.e. request while RX is represented by rx_data and rx_size with reply's header equivalent missing. Reply header may contain some vital information including, but not limited to, received payload size. Some IPCs have entire payload found within RX header instead. Content and value of said header is context dependent and may vary between firmware versions and target platform. Current model does not allow such IPCs to function at all. Rather than appending yet another parameter to an already long list of such for sst_ipc_tx_message_XXXs, declare message container in form of struct sst_ipc_message and add them to parent's ipc_message declaration. Align haswell, baytrail and skylake with updated request-reply model and modify their reply processing functions to save RX header within message container. Despite the range of changes, status quo is achieved. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190723144341.21339-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/baytrail/sst-baytrail-ipc.c | 65 ++++---- sound/soc/intel/common/sst-ipc.c | 69 ++++---- sound/soc/intel/common/sst-ipc.h | 27 ++-- sound/soc/intel/haswell/sst-haswell-ipc.c | 164 +++++++++++--------- sound/soc/intel/skylake/cnl-sst.c | 6 +- sound/soc/intel/skylake/skl-sst-ipc.c | 110 ++++++++----- 6 files changed, 239 insertions(+), 202 deletions(-) diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 8bd1eddcc091..74274bd38f7a 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -211,7 +211,7 @@ static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) { struct sst_byt_stream *stream; - u64 header = msg->header; + u64 header = msg->tx.header; u8 stream_id = sst_byt_header_str_id(header); u8 stream_msg = sst_byt_header_msg_id(header); @@ -240,9 +240,10 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header) if (msg == NULL) return 1; + msg->rx.header = header; if (header & IPC_HEADER_LARGE(true)) { - msg->rx_size = sst_byt_header_data(header); - sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size); + msg->rx.size = sst_byt_header_data(header); + sst_dsp_inbox_read(byt->dsp, msg->rx.data, msg->rx.size); } /* update any stream states */ @@ -407,17 +408,18 @@ int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) { - struct sst_byt_alloc_params *str_req = &stream->request; - struct sst_byt_alloc_response *reply = &stream->reply; - u64 header; + struct sst_ipc_message request, reply = {0}; int ret; - header = sst_byt_header(IPC_IA_ALLOC_STREAM, - sizeof(*str_req) + sizeof(u32), + request.header = sst_byt_header(IPC_IA_ALLOC_STREAM, + sizeof(stream->request) + sizeof(u32), true, stream->str_id); - ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req, - sizeof(*str_req), - reply, sizeof(*reply)); + request.data = &stream->request; + request.size = sizeof(stream->request); + reply.data = &stream->reply; + reply.size = sizeof(stream->reply); + + ret = sst_ipc_tx_message_wait(&byt->ipc, request, &reply); if (ret < 0) { dev_err(byt->dev, "ipc: error stream commit failed\n"); return ret; @@ -430,7 +432,7 @@ int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) { - u64 header; + struct sst_ipc_message request = {0}; int ret = 0; struct sst_dsp *sst = byt->dsp; unsigned long flags; @@ -438,8 +440,9 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) if (!stream->commited) goto out; - header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); - ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0); + request.header = sst_byt_header(IPC_IA_FREE_STREAM, + 0, false, stream->str_id); + ret = sst_ipc_tx_message_wait(&byt->ipc, request, NULL); if (ret < 0) { dev_err(byt->dev, "ipc: free stream %d failed\n", stream->str_id); @@ -459,15 +462,13 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) static int sst_byt_stream_operations(struct sst_byt *byt, int type, int stream_id, int wait) { - u64 header; + struct sst_ipc_message request = {0}; - header = sst_byt_header(type, 0, false, stream_id); + request.header = sst_byt_header(type, 0, false, stream_id); if (wait) - return sst_ipc_tx_message_wait(&byt->ipc, header, NULL, - 0, NULL, 0); + return sst_ipc_tx_message_wait(&byt->ipc, request, NULL); else - return sst_ipc_tx_message_nowait(&byt->ipc, header, - NULL, 0); + return sst_ipc_tx_message_nowait(&byt->ipc, request); } /* stream ALSA trigger operations */ @@ -475,19 +476,17 @@ int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream, u32 start_offset) { struct sst_byt_start_stream_params start_stream; - void *tx_msg; - size_t size; - u64 header; + struct sst_ipc_message request; int ret; start_stream.byte_offset = start_offset; - header = sst_byt_header(IPC_IA_START_STREAM, + request.header = sst_byt_header(IPC_IA_START_STREAM, sizeof(start_stream) + sizeof(u32), true, stream->str_id); - tx_msg = &start_stream; - size = sizeof(start_stream); + request.data = &start_stream; + request.size = sizeof(start_stream); - ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size); + ret = sst_ipc_tx_message_nowait(&byt->ipc, request); if (ret < 0) dev_err(byt->dev, "ipc: error failed to start stream %d\n", stream->str_id); @@ -623,10 +622,10 @@ EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) { - if (msg->header & IPC_HEADER_LARGE(true)) - sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + if (msg->tx.header & IPC_HEADER_LARGE(true)) + sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); - sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header); + sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->tx.header); } static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text) @@ -648,9 +647,9 @@ static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { /* msg content = lower 32-bit of the header + data */ - *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1); - memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size); - msg->tx_size += sizeof(u32); + *(u32 *)msg->tx.data = (u32)(msg->tx.header & (u32)-1); + memcpy(msg->tx.data + sizeof(u32), tx_data, tx_size); + msg->tx.size += sizeof(u32); } static u64 byt_reply_msg_match(u64 header, u64 *mask) diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index ef5b66af1cd2..1186a03a88d6 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -43,7 +43,7 @@ static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc) } static int tx_wait_done(struct sst_generic_ipc *ipc, - struct ipc_message *msg, void *rx_data) + struct ipc_message *msg, struct sst_ipc_message *reply) { unsigned long flags; int ret; @@ -62,8 +62,11 @@ static int tx_wait_done(struct sst_generic_ipc *ipc, } else { /* copy the data returned from DSP */ - if (rx_data) - memcpy(rx_data, msg->rx_data, msg->rx_size); + if (reply) { + reply->header = msg->rx.header; + if (reply->data) + memcpy(reply->data, msg->rx.data, msg->rx.size); + } ret = msg->errno; } @@ -72,9 +75,9 @@ static int tx_wait_done(struct sst_generic_ipc *ipc, return ret; } -static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes, void *rx_data, - size_t rx_bytes, int wait) +static int ipc_tx_message(struct sst_generic_ipc *ipc, + struct sst_ipc_message request, + struct sst_ipc_message *reply, int wait) { struct ipc_message *msg; unsigned long flags; @@ -87,23 +90,24 @@ static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header, return -EBUSY; } - msg->header = header; - msg->tx_size = tx_bytes; - msg->rx_size = rx_bytes; + msg->tx.header = request.header; + msg->tx.size = request.size; + msg->rx.header = 0; + msg->rx.size = reply ? reply->size : 0; msg->wait = wait; msg->errno = 0; msg->pending = false; msg->complete = false; - if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL)) - ipc->ops.tx_data_copy(msg, tx_data, tx_bytes); + if ((request.size) && (ipc->ops.tx_data_copy != NULL)) + ipc->ops.tx_data_copy(msg, request.data, request.size); list_add_tail(&msg->list, &ipc->tx_list); schedule_work(&ipc->kwork); spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); if (wait) - return tx_wait_done(ipc, msg, rx_data); + return tx_wait_done(ipc, msg, reply); else return 0; } @@ -118,13 +122,13 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) return -ENOMEM; for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { - ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); - if (ipc->msg[i].tx_data == NULL) + ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); + if (ipc->msg[i].tx.data == NULL) goto free_mem; - ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); - if (ipc->msg[i].rx_data == NULL) { - kfree(ipc->msg[i].tx_data); + ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); + if (ipc->msg[i].rx.data == NULL) { + kfree(ipc->msg[i].tx.data); goto free_mem; } @@ -136,8 +140,8 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) free_mem: while (i > 0) { - kfree(ipc->msg[i-1].tx_data); - kfree(ipc->msg[i-1].rx_data); + kfree(ipc->msg[i-1].tx.data); + kfree(ipc->msg[i-1].rx.data); --i; } kfree(ipc->msg); @@ -173,8 +177,8 @@ static void ipc_tx_msgs(struct work_struct *work) spin_unlock_irq(&ipc->dsp->spinlock); } -int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) +int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, + struct sst_ipc_message request, struct sst_ipc_message *reply) { int ret; @@ -187,8 +191,7 @@ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, if (ipc->ops.check_dsp_lp_on(ipc->dsp, true)) return -EIO; - ret = ipc_tx_message(ipc, header, tx_data, tx_bytes, - rx_data, rx_bytes, 1); + ret = ipc_tx_message(ipc, request, reply, 1); if (ipc->ops.check_dsp_lp_on) if (ipc->ops.check_dsp_lp_on(ipc->dsp, false)) @@ -198,19 +201,17 @@ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, } EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait); -int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes) +int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, + struct sst_ipc_message request) { - return ipc_tx_message(ipc, header, tx_data, tx_bytes, - NULL, 0, 0); + return ipc_tx_message(ipc, request, NULL, 0); } EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait); -int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) +int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, + struct sst_ipc_message request, struct sst_ipc_message *reply) { - return ipc_tx_message(ipc, header, tx_data, tx_bytes, - rx_data, rx_bytes, 1); + return ipc_tx_message(ipc, request, reply, 1); } EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm); @@ -230,7 +231,7 @@ struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, } list_for_each_entry(msg, &ipc->rx_list, list) { - if ((msg->header & mask) == header) + if ((msg->tx.header & mask) == header) return msg; } @@ -304,8 +305,8 @@ void sst_ipc_fini(struct sst_generic_ipc *ipc) if (ipc->msg) { for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { - kfree(ipc->msg[i].tx_data); - kfree(ipc->msg[i].rx_data); + kfree(ipc->msg[i].tx.data); + kfree(ipc->msg[i].rx.data); } kfree(ipc->msg); } diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index ef38600e88f7..08c4831b2664 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -17,15 +17,16 @@ #define IPC_MAX_MAILBOX_BYTES 256 -struct ipc_message { - struct list_head list; +struct sst_ipc_message { u64 header; + void *data; + size_t size; +}; - /* direction wrt host CPU */ - char *tx_data; - size_t tx_size; - char *rx_data; - size_t rx_size; +struct ipc_message { + struct list_head list; + struct sst_ipc_message tx; + struct sst_ipc_message rx; wait_queue_head_t waitq; bool pending; @@ -66,14 +67,14 @@ struct sst_generic_ipc { struct sst_plat_ipc_ops ops; }; -int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes); +int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, + struct sst_ipc_message request, struct sst_ipc_message *reply); -int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes); +int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, + struct sst_ipc_message request); -int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header, - void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes); +int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, + struct sst_ipc_message request, struct sst_ipc_message *reply); struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, u64 header); diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index a83b92d6bea8..5c73b11375e3 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -511,7 +511,7 @@ static void hsw_notification_work(struct work_struct *work) static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) { struct sst_hsw_stream *stream; - u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); + u32 header = msg->tx.header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); u32 stream_id = msg_get_stream_id(header); u32 stream_msg = msg_get_stream_type(header); @@ -552,6 +552,7 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) return -EIO; } + msg->rx.header = header; /* first process the header */ switch (reply) { case IPC_GLB_REPLY_PENDING: @@ -562,13 +563,13 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) case IPC_GLB_REPLY_SUCCESS: if (msg->pending) { trace_ipc_pending_reply("completed", header); - sst_dsp_inbox_read(hsw->dsp, msg->rx_data, - msg->rx_size); + sst_dsp_inbox_read(hsw->dsp, msg->rx.data, + msg->rx.size); hsw->ipc.pending = false; } else { /* copy data from the DSP */ - sst_dsp_outbox_read(hsw->dsp, msg->rx_data, - msg->rx_size); + sst_dsp_outbox_read(hsw->dsp, msg->rx.data, + msg->rx.size); } break; /* these will be rare - but useful for debug */ @@ -810,11 +811,13 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) int sst_hsw_fw_get_version(struct sst_hsw *hsw, struct sst_hsw_ipc_fw_version *version) { + struct sst_ipc_message request = {0}, reply = {0}; int ret; - ret = sst_ipc_tx_message_wait(&hsw->ipc, - IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), - NULL, 0, version, sizeof(*version)); + request.header = IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION); + reply.data = version; + reply.size = sizeof(*version); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); if (ret < 0) dev_err(hsw->dev, "error: get version failed\n"); @@ -840,7 +843,7 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) { struct sst_hsw_ipc_volume_req *req; - u32 header; + struct sst_ipc_message request; int ret; trace_ipc_request("set stream volume", stream->reply.stream_hw_id); @@ -848,11 +851,11 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL) return -EINVAL; - header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); - header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); - header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); - header |= (stage_id << IPC_STG_ID_SHIFT); + request.header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); + request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + request.header |= (stage_id << IPC_STG_ID_SHIFT); req = &stream->vol_req; req->target_volume = volume; @@ -877,8 +880,9 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, req->channel = channel; } - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, req, - sizeof(*req), NULL, 0); + request.data = req; + request.size = sizeof(*req); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) { dev_err(hsw->dev, "error: set stream volume failed\n"); return ret; @@ -905,7 +909,7 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, u32 volume) { struct sst_hsw_ipc_volume_req req; - u32 header; + struct sst_ipc_message request; int ret; trace_ipc_request("set mixer volume", volume); @@ -933,18 +937,19 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, req.channel = channel; } - header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); - header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); - header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); - header |= (stage_id << IPC_STG_ID_SHIFT); + request.header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); + request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + request.header |= (stage_id << IPC_STG_ID_SHIFT); req.curve_duration = hsw->curve_duration; req.curve_type = hsw->curve_type; req.target_volume = volume; - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &req, - sizeof(req), NULL, 0); + request.data = &req; + request.size = sizeof(req); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) { dev_err(hsw->dev, "error: set mixer volume failed\n"); return ret; @@ -983,7 +988,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) { - u32 header; + struct sst_ipc_message request; int ret = 0; struct sst_dsp *sst = hsw->dsp; unsigned long flags; @@ -1000,10 +1005,11 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) trace_ipc_request("stream free", stream->host_id); stream->free_req.stream_id = stream->reply.stream_hw_id; - header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); + request.header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); + request.data = &stream->free_req; + request.size = sizeof(stream->free_req); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &stream->free_req, - sizeof(stream->free_req), NULL, 0); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) { dev_err(hsw->dev, "error: free stream %d failed\n", stream->free_req.stream_id); @@ -1175,9 +1181,7 @@ int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) { - struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request; - struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply; - u32 header; + struct sst_ipc_message request, reply = {0}; int ret; if (!stream) { @@ -1192,10 +1196,13 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) trace_ipc_request("stream alloc", stream->host_id); - header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); + request.header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); + request.data = &stream->request; + request.size = sizeof(stream->request); + reply.data = &stream->reply; + reply.size = sizeof(stream->reply); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, str_req, - sizeof(*str_req), reply, sizeof(*reply)); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); if (ret < 0) { dev_err(hsw->dev, "error: stream commit failed\n"); return ret; @@ -1235,23 +1242,22 @@ void sst_hsw_stream_set_silence_start(struct sst_hsw *hsw, ABI to be opaque to client PCM drivers to cope with any future ABI changes */ int sst_hsw_mixer_get_info(struct sst_hsw *hsw) { - struct sst_hsw_ipc_stream_info_reply *reply; - u32 header; + struct sst_ipc_message request = {0}, reply = {0}; int ret; - reply = &hsw->mixer_info; - header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); + request.header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); + reply.data = &hsw->mixer_info; + reply.size = sizeof(hsw->mixer_info); trace_ipc_request("get global mixer info", 0); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, - reply, sizeof(*reply)); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); if (ret < 0) { dev_err(hsw->dev, "error: get stream info failed\n"); return ret; } - trace_hsw_mixer_info_reply(reply); + trace_hsw_mixer_info_reply(&hsw->mixer_info); return 0; } @@ -1260,16 +1266,15 @@ int sst_hsw_mixer_get_info(struct sst_hsw *hsw) static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, int stream_id, int wait) { - u32 header; + struct sst_ipc_message request = {0}; - header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type); - header |= (stream_id << IPC_STR_ID_SHIFT); + request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE); + request.header |= IPC_STR_TYPE(type) | (stream_id << IPC_STR_ID_SHIFT); if (wait) - return sst_ipc_tx_message_wait(&hsw->ipc, header, - NULL, 0, NULL, 0); + return sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); else - return sst_ipc_tx_message_nowait(&hsw->ipc, header, NULL, 0); + return sst_ipc_tx_message_nowait(&hsw->ipc, request); } /* Stream ALSA trigger operations */ @@ -1377,8 +1382,8 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, enum sst_hsw_device_mode mode, u32 clock_divider) { + struct sst_ipc_message request; struct sst_hsw_ipc_device_config_req config; - u32 header; int ret; trace_ipc_request("set device config", dev); @@ -1394,10 +1399,11 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, trace_hsw_device_config_req(&config); - header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); + request.header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); + request.data = &config; + request.size = sizeof(config); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &config, - sizeof(config), NULL, 0); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) dev_err(hsw->dev, "error: set device formats failed\n"); @@ -1409,16 +1415,20 @@ EXPORT_SYMBOL_GPL(sst_hsw_device_set_config); int sst_hsw_dx_set_state(struct sst_hsw *hsw, enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) { - u32 header, state_; + struct sst_ipc_message request, reply = {0}; + u32 state_; int ret, item; - header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); state_ = state; + request.header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); + request.data = &state_; + request.size = sizeof(state_); + reply.data = dx; + reply.size = sizeof(*dx); trace_ipc_request("PM enter Dx state", state); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &state_, - sizeof(state_), dx, sizeof(*dx)); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); if (ret < 0) { dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); return ret; @@ -1878,7 +1888,7 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, u32 module_id, u32 instance_id) { int ret; - u32 header = 0; + struct sst_ipc_message request; struct sst_hsw_ipc_module_config config; struct sst_module *module; struct sst_module_runtime *runtime; @@ -1907,10 +1917,10 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, return -ENXIO; } - header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | + request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) | IPC_MODULE_ID(module_id); - dev_dbg(dev, "module enable header: %x\n", header); + dev_dbg(dev, "module enable header: %x\n", (u32)request.header); config.map.module_entries_count = 1; config.map.module_entries[0].module_id = module->id; @@ -1932,8 +1942,9 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, config.scratch_mem.size, config.scratch_mem.offset, config.map.module_entries[0].entry_point); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, - &config, sizeof(config), NULL, 0); + request.data = &config; + request.size = sizeof(config); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) dev_err(dev, "ipc: module enable failed - %d\n", ret); else @@ -1946,7 +1957,7 @@ int sst_hsw_module_disable(struct sst_hsw *hsw, u32 module_id, u32 instance_id) { int ret; - u32 header; + struct sst_ipc_message request = {0}; struct sst_module *module; struct device *dev = hsw->dev; struct sst_dsp *dsp = hsw->dsp; @@ -1967,11 +1978,11 @@ int sst_hsw_module_disable(struct sst_hsw *hsw, return -ENXIO; } - header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | + request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) | IPC_MODULE_ID(module_id); - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) dev_err(dev, "module disable failed - %d\n", ret); else @@ -1985,15 +1996,16 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, u32 param_size, char *param) { int ret; - u32 header = 0; - u32 payload_size = 0, transfer_parameter_size = 0; + struct sst_ipc_message request = {0}; + u32 payload_size = 0; struct sst_hsw_transfer_parameter *parameter; struct device *dev = hsw->dev; - header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | + request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) | IPC_MODULE_ID(module_id); - dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", header); + dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", + (u32)request.header); payload_size = param_size + sizeof(struct sst_hsw_transfer_parameter) - @@ -2003,14 +2015,14 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) { /* short parameter, mailbox can contain data */ - dev_dbg(dev, "transfer parameter size : %d\n", - transfer_parameter_size); + dev_dbg(dev, "transfer parameter size : %lu\n", + request.size); - transfer_parameter_size = ALIGN(payload_size, 4); - dev_dbg(dev, "transfer parameter aligned size : %d\n", - transfer_parameter_size); + request.size = ALIGN(payload_size, 4); + dev_dbg(dev, "transfer parameter aligned size : %lu\n", + request.size); - parameter = kzalloc(transfer_parameter_size, GFP_KERNEL); + parameter = kzalloc(request.size, GFP_KERNEL); if (parameter == NULL) return -ENOMEM; @@ -2022,9 +2034,9 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, parameter->parameter_id = parameter_id; parameter->data_size = param_size; + request.data = parameter; - ret = sst_ipc_tx_message_wait(&hsw->ipc, header, - parameter, transfer_parameter_size , NULL, 0); + ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); if (ret < 0) dev_err(dev, "ipc: module set parameter failed - %d\n", ret); @@ -2041,8 +2053,8 @@ static struct sst_dsp_device hsw_dev = { static void hsw_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) { /* send the message */ - sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); - sst_dsp_ipc_msg_tx(ipc->dsp, msg->header); + sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); + sst_dsp_ipc_msg_tx(ipc->dsp, msg->tx.header); } static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text) @@ -2063,7 +2075,7 @@ static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text) static void hsw_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { - memcpy(msg->tx_data, tx_data, tx_size); + memcpy(msg->tx.data, tx_data, tx_size); } static u64 hsw_reply_msg_match(u64 header, u64 *mask) diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 2d748a335bcf..4f64f097e9ae 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -366,10 +366,10 @@ static struct sst_dsp_device cnl_dev = { static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) { - struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); - if (msg->tx_size) - sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + if (msg->tx.size) + sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, header->extension); sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index ee1493acc9a8..a2b69a02aab2 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -281,7 +281,7 @@ void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { if (tx_size) - memcpy(msg->tx_data, tx_data, tx_size); + memcpy(msg->tx.data, tx_data, tx_size); } static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) @@ -295,10 +295,10 @@ static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) /* Lock to be held by caller */ static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) { - struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); - if (msg->tx_size) - sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + if (msg->tx.size) + sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, header->extension); sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, @@ -447,11 +447,12 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, return; } + msg->rx.header = *ipc_header; /* first process the header */ if (reply == IPC_GLB_REPLY_SUCCESS) { dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); /* copy the rx data from the mailbox */ - sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); + sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: case IPC_GLB_LOAD_LIBRARY: @@ -635,7 +636,7 @@ int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -646,9 +647,10 @@ int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); header.extension = IPC_PPL_LP_MODE(lp_mode); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); return ret; @@ -661,16 +663,17 @@ EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); header.primary |= IPC_INSTANCE_ID(instance_id); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); return ret; @@ -684,7 +687,7 @@ int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, u8 instance_id, enum skl_ipc_pipeline_state state) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -692,9 +695,10 @@ int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); header.primary |= IPC_INSTANCE_ID(instance_id); header.primary |= IPC_PPL_STATE(state); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); return ret; @@ -707,7 +711,7 @@ int skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -716,8 +720,10 @@ skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) header.primary |= IPC_INSTANCE_ID(instance_id); header.extension = IPC_DMA_ID(dma_id); + request.header = *(u64 *)(&header); + dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); return ret; @@ -730,16 +736,17 @@ EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); header.primary |= IPC_INSTANCE_ID(instance_id); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); return ret; @@ -753,7 +760,7 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request; int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); @@ -762,10 +769,13 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, header.primary |= IPC_MOD_INSTANCE_ID(instance_id); header.primary |= IPC_MOD_ID(module_id); + request.header = *(u64 *)(&header); + request.data = dx; + request.size = sizeof(*dx); + dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, header.primary, header.extension); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, - dx, sizeof(*dx), NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); return ret; @@ -779,7 +789,7 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc, struct skl_ipc_init_instance_msg *msg, void *param_data) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request; int ret; u32 *buffer = (u32 *)param_data; /* param_block_size must be in dwords */ @@ -799,10 +809,13 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc, header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); header.extension |= IPC_DOMAIN(msg->domain); + request.header = *(u64 *)(&header); + request.data = param_data; + request.size = msg->param_data_size; + dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, header.primary, header.extension); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, - msg->param_data_size, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: init instance failed\n"); @@ -817,7 +830,7 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, struct skl_ipc_bind_unbind_msg *msg) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; int ret; @@ -831,10 +844,11 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); header.extension |= IPC_DST_QUEUE(msg->dst_queue); header.extension |= IPC_SRC_QUEUE(msg->src_queue); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, header.extension); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: bind/unbind failed\n"); return ret; @@ -854,7 +868,7 @@ int skl_ipc_load_modules(struct sst_generic_ipc *ipc, u8 module_cnt, void *data) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -862,8 +876,11 @@ int skl_ipc_load_modules(struct sst_generic_ipc *ipc, header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); - ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data, - (sizeof(u16) * module_cnt)); + request.header = *(u64 *)(&header); + request.data = data; + request.size = sizeof(u16) * module_cnt; + + ret = sst_ipc_tx_message_nowait(ipc, request); if (ret < 0) dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); @@ -875,7 +892,7 @@ int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, void *data) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request; int ret; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -883,8 +900,11 @@ int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, - (sizeof(u16) * module_cnt), NULL, 0); + request.header = *(u64 *)(&header); + request.data = data; + request.size = sizeof(u16) * module_cnt; + + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); @@ -896,7 +916,7 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request; int ret = 0; size_t sz_remaining, tx_size, data_offset; @@ -923,9 +943,11 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, header.primary, header.extension); dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", (unsigned)data_offset, (unsigned)tx_size); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, - ((char *)param) + data_offset, - tx_size, NULL, 0); + + request.header = *(u64 *)(&header); + request.data = ((char *)param) + data_offset; + request.size = tx_size; + ret = sst_ipc_tx_message_wait(ipc, request, NULL); if (ret < 0) { dev_err(ipc->dev, "ipc: set large config fail, err: %d\n", ret); @@ -950,7 +972,7 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}, reply = {0}; int ret = 0; size_t sz_remaining, rx_size, data_offset; @@ -974,9 +996,10 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, if (rx_size == sz_remaining) header.extension |= IPC_FINAL_BLOCK(1); - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, - ((char *)param) + data_offset, - msg->param_data_size); + request.header = *(u64 *)(&header); + reply.data = ((char *)param) + data_offset; + reply.size = msg->param_data_size; + ret = sst_ipc_tx_message_wait(ipc, request, &reply); if (ret < 0) { dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); @@ -1001,7 +1024,7 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, u8 dma_id, u8 table_id, bool wait) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret = 0; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); @@ -1009,12 +1032,12 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); header.primary |= IPC_MOD_INSTANCE_ID(table_id); header.primary |= IPC_MOD_ID(dma_id); + request.header = *(u64 *)(&header); if (wait) - ret = sst_ipc_tx_message_wait(ipc, *ipc_header, - NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_wait(ipc, request, NULL); else - ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0); + ret = sst_ipc_tx_message_nowait(ipc, request); if (ret < 0) dev_err(ipc->dev, "ipc: load lib failed\n"); @@ -1026,7 +1049,7 @@ EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) { struct skl_ipc_header header = {0}; - u64 *ipc_header = (u64 *)(&header); + struct sst_ipc_message request = {0}; int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); @@ -1037,6 +1060,7 @@ int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) header.extension = IPC_D0IX_WAKE(msg->wake); header.extension |= IPC_D0IX_STREAMING(msg->streaming); + request.header = *(u64 *)(&header); dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, header.primary, header.extension); @@ -1044,7 +1068,7 @@ int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) /* * Use the nopm IPC here as we dont want it checking for D0iX */ - ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0); + ret = sst_ipc_tx_message_nopm(ipc, request, NULL); if (ret < 0) dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); -- GitLab From 5f0ac20ed6db1d6da2eea8b862cf3d54fdfb5830 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 6 Aug 2019 18:12:10 +0300 Subject: [PATCH 2166/7155] ASoC: fsl_sai: Add registers definition for multiple datalines SAI IP supports up to 8 data lines. The configuration of supported number of data lines is decided at SoC integration time. This patch adds definitions for all related data TX/RX registers: * TDR0..7, Transmit data register * TFR0..7, Transmit FIFO register * RDR0..7, Receive data register * RFR0..7, Receive FIFO register Signed-off-by: Daniel Baluta Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20190806151214.6783-2-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 76 +++++++++++++++++++++++++++++++++++------ sound/soc/fsl/fsl_sai.h | 36 ++++++++++++++++--- 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 8f4d9fa95599..e4221f2a5ee3 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -685,7 +685,14 @@ static struct reg_default fsl_sai_reg_defaults[] = { {FSL_SAI_TCR3, 0}, {FSL_SAI_TCR4, 0}, {FSL_SAI_TCR5, 0}, - {FSL_SAI_TDR, 0}, + {FSL_SAI_TDR0, 0}, + {FSL_SAI_TDR1, 0}, + {FSL_SAI_TDR2, 0}, + {FSL_SAI_TDR3, 0}, + {FSL_SAI_TDR4, 0}, + {FSL_SAI_TDR5, 0}, + {FSL_SAI_TDR6, 0}, + {FSL_SAI_TDR7, 0}, {FSL_SAI_TMR, 0}, {FSL_SAI_RCR1, 0}, {FSL_SAI_RCR2, 0}, @@ -704,7 +711,14 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) case FSL_SAI_TCR3: case FSL_SAI_TCR4: case FSL_SAI_TCR5: - case FSL_SAI_TFR: + case FSL_SAI_TFR0: + case FSL_SAI_TFR1: + case FSL_SAI_TFR2: + case FSL_SAI_TFR3: + case FSL_SAI_TFR4: + case FSL_SAI_TFR5: + case FSL_SAI_TFR6: + case FSL_SAI_TFR7: case FSL_SAI_TMR: case FSL_SAI_RCSR: case FSL_SAI_RCR1: @@ -712,8 +726,22 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) case FSL_SAI_RCR3: case FSL_SAI_RCR4: case FSL_SAI_RCR5: - case FSL_SAI_RDR: - case FSL_SAI_RFR: + case FSL_SAI_RDR0: + case FSL_SAI_RDR1: + case FSL_SAI_RDR2: + case FSL_SAI_RDR3: + case FSL_SAI_RDR4: + case FSL_SAI_RDR5: + case FSL_SAI_RDR6: + case FSL_SAI_RDR7: + case FSL_SAI_RFR0: + case FSL_SAI_RFR1: + case FSL_SAI_RFR2: + case FSL_SAI_RFR3: + case FSL_SAI_RFR4: + case FSL_SAI_RFR5: + case FSL_SAI_RFR6: + case FSL_SAI_RFR7: case FSL_SAI_RMR: return true; default: @@ -726,9 +754,30 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) switch (reg) { case FSL_SAI_TCSR: case FSL_SAI_RCSR: - case FSL_SAI_TFR: - case FSL_SAI_RFR: - case FSL_SAI_RDR: + case FSL_SAI_TFR0: + case FSL_SAI_TFR1: + case FSL_SAI_TFR2: + case FSL_SAI_TFR3: + case FSL_SAI_TFR4: + case FSL_SAI_TFR5: + case FSL_SAI_TFR6: + case FSL_SAI_TFR7: + case FSL_SAI_RFR0: + case FSL_SAI_RFR1: + case FSL_SAI_RFR2: + case FSL_SAI_RFR3: + case FSL_SAI_RFR4: + case FSL_SAI_RFR5: + case FSL_SAI_RFR6: + case FSL_SAI_RFR7: + case FSL_SAI_RDR0: + case FSL_SAI_RDR1: + case FSL_SAI_RDR2: + case FSL_SAI_RDR3: + case FSL_SAI_RDR4: + case FSL_SAI_RDR5: + case FSL_SAI_RDR6: + case FSL_SAI_RDR7: return true; default: return false; @@ -744,7 +793,14 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) case FSL_SAI_TCR3: case FSL_SAI_TCR4: case FSL_SAI_TCR5: - case FSL_SAI_TDR: + case FSL_SAI_TDR0: + case FSL_SAI_TDR1: + case FSL_SAI_TDR2: + case FSL_SAI_TDR3: + case FSL_SAI_TDR4: + case FSL_SAI_TDR5: + case FSL_SAI_TDR6: + case FSL_SAI_TDR7: case FSL_SAI_TMR: case FSL_SAI_RCSR: case FSL_SAI_RCR1: @@ -883,8 +939,8 @@ static int fsl_sai_probe(struct platform_device *pdev) MCLK_DIR(index)); } - sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; - sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; + sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0; + sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0; sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 7c1ef671da28..4bb478041d67 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -20,8 +20,22 @@ #define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ #define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ #define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ -#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ -#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ +#define FSL_SAI_TDR0 0x20 /* SAI Transmit Data 0 */ +#define FSL_SAI_TDR1 0x24 /* SAI Transmit Data 1 */ +#define FSL_SAI_TDR2 0x28 /* SAI Transmit Data 2 */ +#define FSL_SAI_TDR3 0x2C /* SAI Transmit Data 3 */ +#define FSL_SAI_TDR4 0x30 /* SAI Transmit Data 4 */ +#define FSL_SAI_TDR5 0x34 /* SAI Transmit Data 5 */ +#define FSL_SAI_TDR6 0x38 /* SAI Transmit Data 6 */ +#define FSL_SAI_TDR7 0x3C /* SAI Transmit Data 7 */ +#define FSL_SAI_TFR0 0x40 /* SAI Transmit FIFO 0 */ +#define FSL_SAI_TFR1 0x44 /* SAI Transmit FIFO 1 */ +#define FSL_SAI_TFR2 0x48 /* SAI Transmit FIFO 2 */ +#define FSL_SAI_TFR3 0x4C /* SAI Transmit FIFO 3 */ +#define FSL_SAI_TFR4 0x50 /* SAI Transmit FIFO 4 */ +#define FSL_SAI_TFR5 0x54 /* SAI Transmit FIFO 5 */ +#define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO 6 */ +#define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO 7 */ #define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ #define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ #define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ @@ -29,8 +43,22 @@ #define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ #define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ #define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ -#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ -#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ +#define FSL_SAI_RDR0 0xa0 /* SAI Receive Data 0 */ +#define FSL_SAI_RDR1 0xa4 /* SAI Receive Data 1 */ +#define FSL_SAI_RDR2 0xa8 /* SAI Receive Data 2 */ +#define FSL_SAI_RDR3 0xac /* SAI Receive Data 3 */ +#define FSL_SAI_RDR4 0xb0 /* SAI Receive Data 4 */ +#define FSL_SAI_RDR5 0xb4 /* SAI Receive Data 5 */ +#define FSL_SAI_RDR6 0xb8 /* SAI Receive Data 6 */ +#define FSL_SAI_RDR7 0xbc /* SAI Receive Data 7 */ +#define FSL_SAI_RFR0 0xc0 /* SAI Receive FIFO 0 */ +#define FSL_SAI_RFR1 0xc4 /* SAI Receive FIFO 1 */ +#define FSL_SAI_RFR2 0xc8 /* SAI Receive FIFO 2 */ +#define FSL_SAI_RFR3 0xcc /* SAI Receive FIFO 3 */ +#define FSL_SAI_RFR4 0xd0 /* SAI Receive FIFO 4 */ +#define FSL_SAI_RFR5 0xd4 /* SAI Receive FIFO 5 */ +#define FSL_SAI_RFR6 0xd8 /* SAI Receive FIFO 6 */ +#define FSL_SAI_RFR7 0xdc /* SAI Receive FIFO 7 */ #define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ #define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR) -- GitLab From b84f50b0fcb497a62068926fca793d2d213c7dbd Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 6 Aug 2019 18:12:11 +0300 Subject: [PATCH 2167/7155] ASoC: fsl_sai: Update Tx/Rx channel enable mask Tx channel enable (TCE) / Rx channel enable (RCE) bits enable corresponding data channel for Tx/Rx operation. Because SAI supports up the 8 channels TCE/RCE occupy up the 8 bits inside TCR3/RCR3 registers we need to extend the mask to reflect this. Signed-off-by: Daniel Baluta Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20190806151214.6783-3-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 6 ++++-- sound/soc/fsl/fsl_sai.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index e4221f2a5ee3..f2698c94c9fe 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -599,7 +599,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int ret; - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, + regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), + FSL_SAI_CR3_TRCE_MASK, FSL_SAI_CR3_TRCE); ret = snd_pcm_hw_constraint_list(substream->runtime, 0, @@ -614,7 +615,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0); + regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), + FSL_SAI_CR3_TRCE_MASK, 0); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 4bb478041d67..20c5b9b1e8bc 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -110,6 +110,7 @@ /* SAI Transmit and Receive Configuration 3 Register */ #define FSL_SAI_CR3_TRCE BIT(16) +#define FSL_SAI_CR3_TRCE_MASK GENMASK(23, 16) #define FSL_SAI_CR3_WDFL(x) (x) #define FSL_SAI_CR3_WDFL_MASK 0x1f -- GitLab From 4f7a0728b5305e2d865f543fbcffd617e03c7674 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 6 Aug 2019 18:12:12 +0300 Subject: [PATCH 2168/7155] ASoC: fsl_sai: Add support for SAI new version New IP version introduces Version ID and Parameter registers and optionally added Timestamp feature. VERID and PARAM registers are placed at the top of registers address space and some registers are shifted according to the following table: Tx/Rx data registers and Tx/Rx FIFO registers keep their addresses, all other registers are shifted by 8. SAI Memory map is described in chapter 13.10.4.1.1 I2S Memory map of the Reference Manual [1]. In order to make as less changes as possible we attach an offset to each register offset to each changed register definition. The offset is read from each board private data. [1]https://cache.nxp.com/secured/assets/documents/en/reference-manual/IMX8MDQLQRM.pdf?__gda__=1563728701_38bea7f0f726472cc675cb141b91bec7&fileExt=.pdf Signed-off-by: Mihai Serban [initial coding in the NXP internal tree] Signed-off-by: Shengjiu Wang [bugfixing and cleanups] Signed-off-by: Daniel Baluta [adapted to linux-next] Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20190806151214.6783-4-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 228 ++++++++++++++++++++++++---------------- sound/soc/fsl/fsl_sai.h | 41 ++++---- 2 files changed, 156 insertions(+), 113 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index f2698c94c9fe..0c5452927c04 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -40,6 +40,7 @@ static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = { static irqreturn_t fsl_sai_isr(int irq, void *devid) { struct fsl_sai *sai = (struct fsl_sai *)devid; + unsigned int ofs = sai->soc_data->reg_offset; struct device *dev = &sai->pdev->dev; u32 flags, xcsr, mask; bool irq_none = true; @@ -52,7 +53,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT; /* Tx IRQ */ - regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr); + regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr); flags = xcsr & mask; if (flags) @@ -82,11 +83,11 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) xcsr &= ~FSL_SAI_CSR_xF_MASK; if (flags) - regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr); irq_rx: /* Rx IRQ */ - regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr); + regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr); flags = xcsr & mask; if (flags) @@ -116,7 +117,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) xcsr &= ~FSL_SAI_CSR_xF_MASK; if (flags) - regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr); out: if (irq_none) @@ -140,6 +141,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int fsl_dir) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; bool tx = fsl_dir == FSL_FMT_TRANSMITTER; u32 val_cr2 = 0; @@ -160,7 +162,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), FSL_SAI_CR2_MSEL_MASK, val_cr2); return 0; @@ -193,6 +195,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, unsigned int fmt, int fsl_dir) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; bool tx = fsl_dir == FSL_FMT_TRANSMITTER; u32 val_cr2 = 0, val_cr4 = 0; @@ -287,9 +290,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2); - regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4); @@ -316,6 +319,7 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); + unsigned int ofs = sai->soc_data->reg_offset; unsigned long clk_rate; u32 savediv = 0, ratio, savesub = freq; u32 id; @@ -378,17 +382,17 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) */ if ((sai->synchronous[TX] && !sai->synchronous[RX]) || (!tx && !sai->synchronous[RX])) { - regmap_update_bits(sai->regmap, FSL_SAI_RCR2, + regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_MSEL_MASK, FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); - regmap_update_bits(sai->regmap, FSL_SAI_RCR2, + regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_DIV_MASK, savediv - 1); } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) || (tx && !sai->synchronous[TX])) { - regmap_update_bits(sai->regmap, FSL_SAI_TCR2, + regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_MSEL_MASK, FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); - regmap_update_bits(sai->regmap, FSL_SAI_TCR2, + regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_DIV_MASK, savediv - 1); } @@ -403,6 +407,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; unsigned int channels = params_channels(params); u32 word_width = params_width(params); @@ -455,19 +460,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, if (!sai->is_slave_mode) { if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) { - regmap_update_bits(sai->regmap, FSL_SAI_TCR4, + regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs), FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, val_cr4); - regmap_update_bits(sai->regmap, FSL_SAI_TCR5, + regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs), FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | FSL_SAI_CR5_FBT_MASK, val_cr5); regmap_write(sai->regmap, FSL_SAI_TMR, ~0UL - ((1 << channels) - 1)); } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) { - regmap_update_bits(sai->regmap, FSL_SAI_RCR4, + regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs), FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, val_cr4); - regmap_update_bits(sai->regmap, FSL_SAI_RCR5, + regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs), FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | FSL_SAI_CR5_FBT_MASK, val_cr5); regmap_write(sai->regmap, FSL_SAI_RMR, @@ -475,10 +480,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, } } - regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, val_cr4); - regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs), FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | FSL_SAI_CR5_FBT_MASK, val_cr5); regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1)); @@ -506,6 +511,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; u32 xcsr, count = 100; @@ -514,9 +521,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx. * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx. */ - regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, - sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0); - regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, + regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC, + sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0); + regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC, sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0); /* @@ -527,43 +534,44 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR, + regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); - regmap_update_bits(sai->regmap, FSL_SAI_TCSR, + regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); - regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_FRDE, 0); - regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_xIE_MASK, 0); /* Check if the opposite FRDE is also disabled */ - regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr); + regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr); if (!(xcsr & FSL_SAI_CSR_FRDE)) { /* Disable both directions and reset their FIFOs */ - regmap_update_bits(sai->regmap, FSL_SAI_TCSR, + regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_TERE, 0); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR, + regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_TERE, 0); /* TERE will remain set till the end of current frame */ do { udelay(10); - regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr); + regmap_read(sai->regmap, + FSL_SAI_xCSR(tx, ofs), &xcsr); } while (--count && xcsr & FSL_SAI_CSR_TERE); - regmap_update_bits(sai->regmap, FSL_SAI_TCSR, + regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR, + regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); /* @@ -575,13 +583,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, */ if (!sai->is_slave_mode) { /* Software Reset for both Tx and Rx */ - regmap_write(sai->regmap, - FSL_SAI_TCSR, FSL_SAI_CSR_SR); - regmap_write(sai->regmap, - FSL_SAI_RCSR, FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), + FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), + FSL_SAI_CSR_SR); /* Clear SR bit to finish the reset */ - regmap_write(sai->regmap, FSL_SAI_TCSR, 0); - regmap_write(sai->regmap, FSL_SAI_RCSR, 0); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); } } break; @@ -596,10 +604,11 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int ret; - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), FSL_SAI_CR3_TRCE_MASK, FSL_SAI_CR3_TRCE); @@ -613,9 +622,10 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int ofs = sai->soc_data->reg_offset; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), + regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), FSL_SAI_CR3_TRCE_MASK, 0); } @@ -633,18 +643,20 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); + unsigned int ofs = sai->soc_data->reg_offset; /* Software Reset for both Tx and Rx */ - regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); - regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); /* Clear SR bit to finish the reset */ - regmap_write(sai->regmap, FSL_SAI_TCSR, 0); - regmap_write(sai->regmap, FSL_SAI_RCSR, 0); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); - regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, + regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), + FSL_SAI_CR1_RFW_MASK, sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); - regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, - FSL_SAI_MAXBURST_RX - 1); + regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs), + FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -681,12 +693,12 @@ static const struct snd_soc_component_driver fsl_component = { .name = "fsl-sai", }; -static struct reg_default fsl_sai_reg_defaults[] = { - {FSL_SAI_TCR1, 0}, - {FSL_SAI_TCR2, 0}, - {FSL_SAI_TCR3, 0}, - {FSL_SAI_TCR4, 0}, - {FSL_SAI_TCR5, 0}, +static struct reg_default fsl_sai_reg_defaults_ofs0[] = { + {FSL_SAI_TCR1(0), 0}, + {FSL_SAI_TCR2(0), 0}, + {FSL_SAI_TCR3(0), 0}, + {FSL_SAI_TCR4(0), 0}, + {FSL_SAI_TCR5(0), 0}, {FSL_SAI_TDR0, 0}, {FSL_SAI_TDR1, 0}, {FSL_SAI_TDR2, 0}, @@ -695,24 +707,50 @@ static struct reg_default fsl_sai_reg_defaults[] = { {FSL_SAI_TDR5, 0}, {FSL_SAI_TDR6, 0}, {FSL_SAI_TDR7, 0}, - {FSL_SAI_TMR, 0}, - {FSL_SAI_RCR1, 0}, - {FSL_SAI_RCR2, 0}, - {FSL_SAI_RCR3, 0}, - {FSL_SAI_RCR4, 0}, - {FSL_SAI_RCR5, 0}, - {FSL_SAI_RMR, 0}, + {FSL_SAI_TMR, 0}, + {FSL_SAI_RCR1(0), 0}, + {FSL_SAI_RCR2(0), 0}, + {FSL_SAI_RCR3(0), 0}, + {FSL_SAI_RCR4(0), 0}, + {FSL_SAI_RCR5(0), 0}, + {FSL_SAI_RMR, 0}, +}; + +static struct reg_default fsl_sai_reg_defaults_ofs8[] = { + {FSL_SAI_TCR1(8), 0}, + {FSL_SAI_TCR2(8), 0}, + {FSL_SAI_TCR3(8), 0}, + {FSL_SAI_TCR4(8), 0}, + {FSL_SAI_TCR5(8), 0}, + {FSL_SAI_TDR0, 0}, + {FSL_SAI_TDR1, 0}, + {FSL_SAI_TDR2, 0}, + {FSL_SAI_TDR3, 0}, + {FSL_SAI_TDR4, 0}, + {FSL_SAI_TDR5, 0}, + {FSL_SAI_TDR6, 0}, + {FSL_SAI_TDR7, 0}, + {FSL_SAI_TMR, 0}, + {FSL_SAI_RCR1(8), 0}, + {FSL_SAI_RCR2(8), 0}, + {FSL_SAI_RCR3(8), 0}, + {FSL_SAI_RCR4(8), 0}, + {FSL_SAI_RCR5(8), 0}, + {FSL_SAI_RMR, 0}, }; static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) { + struct fsl_sai *sai = dev_get_drvdata(dev); + unsigned int ofs = sai->soc_data->reg_offset; + + if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs)) + return true; + + if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs)) + return true; + switch (reg) { - case FSL_SAI_TCSR: - case FSL_SAI_TCR1: - case FSL_SAI_TCR2: - case FSL_SAI_TCR3: - case FSL_SAI_TCR4: - case FSL_SAI_TCR5: case FSL_SAI_TFR0: case FSL_SAI_TFR1: case FSL_SAI_TFR2: @@ -722,12 +760,6 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) case FSL_SAI_TFR6: case FSL_SAI_TFR7: case FSL_SAI_TMR: - case FSL_SAI_RCSR: - case FSL_SAI_RCR1: - case FSL_SAI_RCR2: - case FSL_SAI_RCR3: - case FSL_SAI_RCR4: - case FSL_SAI_RCR5: case FSL_SAI_RDR0: case FSL_SAI_RDR1: case FSL_SAI_RDR2: @@ -753,9 +785,13 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) { + struct fsl_sai *sai = dev_get_drvdata(dev); + unsigned int ofs = sai->soc_data->reg_offset; + + if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs)) + return true; + switch (reg) { - case FSL_SAI_TCSR: - case FSL_SAI_RCSR: case FSL_SAI_TFR0: case FSL_SAI_TFR1: case FSL_SAI_TFR2: @@ -788,13 +824,16 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) { + struct fsl_sai *sai = dev_get_drvdata(dev); + unsigned int ofs = sai->soc_data->reg_offset; + + if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs)) + return true; + + if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs)) + return true; + switch (reg) { - case FSL_SAI_TCSR: - case FSL_SAI_TCR1: - case FSL_SAI_TCR2: - case FSL_SAI_TCR3: - case FSL_SAI_TCR4: - case FSL_SAI_TCR5: case FSL_SAI_TDR0: case FSL_SAI_TDR1: case FSL_SAI_TDR2: @@ -804,12 +843,6 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) case FSL_SAI_TDR6: case FSL_SAI_TDR7: case FSL_SAI_TMR: - case FSL_SAI_RCSR: - case FSL_SAI_RCR1: - case FSL_SAI_RCR2: - case FSL_SAI_RCR3: - case FSL_SAI_RCR4: - case FSL_SAI_RCR5: case FSL_SAI_RMR: return true; default: @@ -817,15 +850,15 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_sai_regmap_config = { +static struct regmap_config fsl_sai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, .fast_io = true, .max_register = FSL_SAI_RMR, - .reg_defaults = fsl_sai_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults), + .reg_defaults = fsl_sai_reg_defaults_ofs0, + .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0), .readable_reg = fsl_sai_readable_reg, .volatile_reg = fsl_sai_volatile_reg, .writeable_reg = fsl_sai_writeable_reg, @@ -857,6 +890,12 @@ static int fsl_sai_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); + if (sai->soc_data->reg_offset == 8) { + fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8; + fsl_sai_regmap_config.num_reg_defaults = + ARRAY_SIZE(fsl_sai_reg_defaults_ofs8); + } + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, &fsl_sai_regmap_config); @@ -971,11 +1010,13 @@ static int fsl_sai_remove(struct platform_device *pdev) static const struct fsl_sai_soc_data fsl_sai_vf610_data = { .use_imx_pcm = false, .fifo_depth = 32, + .reg_offset = 0, }; static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { .use_imx_pcm = true, .fifo_depth = 32, + .reg_offset = 0, }; static const struct of_device_id fsl_sai_ids[] = { @@ -1008,6 +1049,7 @@ static int fsl_sai_runtime_suspend(struct device *dev) static int fsl_sai_runtime_resume(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); + unsigned int ofs = sai->soc_data->reg_offset; int ret; ret = clk_prepare_enable(sai->bus_clk); @@ -1029,11 +1071,11 @@ static int fsl_sai_runtime_resume(struct device *dev) } regcache_cache_only(sai->regmap, false); - regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); - regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); usleep_range(1000, 2000); - regmap_write(sai->regmap, FSL_SAI_TCSR, 0); - regmap_write(sai->regmap, FSL_SAI_RCSR, 0); + regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); + regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); ret = regcache_sync(sai->regmap); if (ret) diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 20c5b9b1e8bc..b89b0ca26053 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -14,12 +14,12 @@ SNDRV_PCM_FMTBIT_S32_LE) /* SAI Register Map Register */ -#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ -#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ -#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ -#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ -#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ -#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ +#define FSL_SAI_TCSR(ofs) (0x00 + ofs) /* SAI Transmit Control */ +#define FSL_SAI_TCR1(ofs) (0x04 + ofs) /* SAI Transmit Configuration 1 */ +#define FSL_SAI_TCR2(ofs) (0x08 + ofs) /* SAI Transmit Configuration 2 */ +#define FSL_SAI_TCR3(ofs) (0x0c + ofs) /* SAI Transmit Configuration 3 */ +#define FSL_SAI_TCR4(ofs) (0x10 + ofs) /* SAI Transmit Configuration 4 */ +#define FSL_SAI_TCR5(ofs) (0x14 + ofs) /* SAI Transmit Configuration 5 */ #define FSL_SAI_TDR0 0x20 /* SAI Transmit Data 0 */ #define FSL_SAI_TDR1 0x24 /* SAI Transmit Data 1 */ #define FSL_SAI_TDR2 0x28 /* SAI Transmit Data 2 */ @@ -37,12 +37,12 @@ #define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO 6 */ #define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO 7 */ #define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ -#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ -#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ -#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ -#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ -#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ -#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ +#define FSL_SAI_RCSR(ofs) (0x80 + ofs) /* SAI Receive Control */ +#define FSL_SAI_RCR1(ofs) (0x84 + ofs)/* SAI Receive Configuration 1 */ +#define FSL_SAI_RCR2(ofs) (0x88 + ofs) /* SAI Receive Configuration 2 */ +#define FSL_SAI_RCR3(ofs) (0x8c + ofs) /* SAI Receive Configuration 3 */ +#define FSL_SAI_RCR4(ofs) (0x90 + ofs) /* SAI Receive Configuration 4 */ +#define FSL_SAI_RCR5(ofs) (0x94 + ofs) /* SAI Receive Configuration 5 */ #define FSL_SAI_RDR0 0xa0 /* SAI Receive Data 0 */ #define FSL_SAI_RDR1 0xa4 /* SAI Receive Data 1 */ #define FSL_SAI_RDR2 0xa8 /* SAI Receive Data 2 */ @@ -61,14 +61,14 @@ #define FSL_SAI_RFR7 0xdc /* SAI Receive FIFO 7 */ #define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ -#define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR) -#define FSL_SAI_xCR1(tx) (tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1) -#define FSL_SAI_xCR2(tx) (tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2) -#define FSL_SAI_xCR3(tx) (tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3) -#define FSL_SAI_xCR4(tx) (tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4) -#define FSL_SAI_xCR5(tx) (tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5) -#define FSL_SAI_xDR(tx) (tx ? FSL_SAI_TDR : FSL_SAI_RDR) -#define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR) +#define FSL_SAI_xCSR(tx, ofs) (tx ? FSL_SAI_TCSR(ofs) : FSL_SAI_RCSR(ofs)) +#define FSL_SAI_xCR1(tx, ofs) (tx ? FSL_SAI_TCR1(ofs) : FSL_SAI_RCR1(ofs)) +#define FSL_SAI_xCR2(tx, ofs) (tx ? FSL_SAI_TCR2(ofs) : FSL_SAI_RCR2(ofs)) +#define FSL_SAI_xCR3(tx, ofs) (tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs)) +#define FSL_SAI_xCR4(tx, ofs) (tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs)) +#define FSL_SAI_xCR5(tx, ofs) (tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs)) +#define FSL_SAI_xDR(tx, ofs) (tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs)) +#define FSL_SAI_xFR(tx, ofs) (tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs)) #define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR) /* SAI Transmit/Receive Control Register */ @@ -158,6 +158,7 @@ struct fsl_sai_soc_data { bool use_imx_pcm; unsigned int fifo_depth; + unsigned int reg_offset; }; struct fsl_sai { -- GitLab From a860fac420971c5a90d4f78959b44ead793aee4f Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 6 Aug 2019 18:12:13 +0300 Subject: [PATCH 2169/7155] ASoC: fsl_sai: Add support for imx7ulp/imx8mq SAI module on imx7ulp/imx8m features 2 new registers (VERID and PARAM) at the beginning of register address space. On imx7ulp FIFOs can held up to 16 x 32 bit samples. On imx8mq FIFOs can held up to 128 x 32 bit samples. Signed-off-by: Daniel Baluta Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20190806151214.6783-5-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 0c5452927c04..4a346fcb5630 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1019,10 +1019,24 @@ static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { .reg_offset = 0, }; +static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = { + .use_imx_pcm = true, + .fifo_depth = 16, + .reg_offset = 8, +}; + +static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = { + .use_imx_pcm = true, + .fifo_depth = 128, + .reg_offset = 8, +}; + static const struct of_device_id fsl_sai_ids[] = { { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data }, { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data }, { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data }, + { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data }, + { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); -- GitLab From 71c67a31f09fa8fdd1495dffd96a5f0d4cef2ede Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 7 Aug 2019 12:48:33 +0100 Subject: [PATCH 2170/7155] init/Kconfig: Fix infinite Kconfig recursion on PPC Commit 5cf896fb6be3 ("arm64: Add support for relocating the kernel with RELR relocations") introduced CONFIG_TOOLS_SUPPORT_RELR, which checks for RELR support in the toolchain as part of the kernel configuration. During this procedure, "$(NM)" is invoked to see if it supports the new relocation format, however PowerPC conditionally overrides this variable in the architecture Makefile in order to pass '--synthetic' when targetting PPC64. This conditional override causes Kconfig to recurse forever, since CONFIG_TOOLS_SUPPORT_RELR cannot be determined without $(NM) being defined, but that in turn depends on CONFIG_PPC64: $ make ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- scripts/kconfig/conf --syncconfig Kconfig scripts/kconfig/conf --syncconfig Kconfig scripts/kconfig/conf --syncconfig Kconfig [...] In this particular case, it looks like PowerPC may be able to pass '--synthetic' unconditionally to nm or even drop it altogether. While that is being resolved, let's just bodge the RELR check by picking up $(NM) directly from the environment in whatever state it happens to be in. Cc: Peter Collingbourne Reported-by: Stephen Rothwell Suggested-by: Masahiro Yamada Signed-off-by: Will Deacon --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index d96127ebc44e..8b4596edda4e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -31,7 +31,7 @@ config CC_HAS_ASM_GOTO def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC)) config TOOLS_SUPPORT_RELR - def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh) + def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh) config CC_HAS_WARN_MAYBE_UNINITIALIZED def_bool $(cc-option,-Wmaybe-uninitialized) -- GitLab From b99286b088ea843b935dcfb29f187697359fe5cd Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Mon, 5 Aug 2019 23:05:03 -0400 Subject: [PATCH 2171/7155] arm64/prefetch: fix a -Wtype-limits warning The commit d5370f754875 ("arm64: prefetch: add alternative pattern for CPUs without a prefetcher") introduced MIDR_IS_CPU_MODEL_RANGE() to be used in has_no_hw_prefetch() with rv_min=0 which generates a compilation warning from GCC, In file included from ./arch/arm64/include/asm/cache.h:8, from ./include/linux/cache.h:6, from ./include/linux/printk.h:9, from ./include/linux/kernel.h:15, from ./include/linux/cpumask.h:10, from arch/arm64/kernel/cpufeature.c:11: arch/arm64/kernel/cpufeature.c: In function 'has_no_hw_prefetch': ./arch/arm64/include/asm/cputype.h:59:26: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] _model == (model) && rv >= (rv_min) && rv <= (rv_max); \ ^~ arch/arm64/kernel/cpufeature.c:889:9: note: in expansion of macro 'MIDR_IS_CPU_MODEL_RANGE' return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, ^~~~~~~~~~~~~~~~~~~~~~~ Fix it by converting MIDR_IS_CPU_MODEL_RANGE to a static inline function. Signed-off-by: Qian Cai Signed-off-by: Will Deacon --- arch/arm64/include/asm/cputype.h | 21 +++++++++++---------- arch/arm64/kernel/cpufeature.c | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index e7d46631cc42..b1454d117cd2 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -51,14 +51,6 @@ #define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \ MIDR_ARCHITECTURE_MASK) -#define MIDR_IS_CPU_MODEL_RANGE(midr, model, rv_min, rv_max) \ -({ \ - u32 _model = (midr) & MIDR_CPU_MODEL_MASK; \ - u32 rv = (midr) & (MIDR_REVISION_MASK | MIDR_VARIANT_MASK); \ - \ - _model == (model) && rv >= (rv_min) && rv <= (rv_max); \ - }) - #define ARM_CPU_IMP_ARM 0x41 #define ARM_CPU_IMP_APM 0x50 #define ARM_CPU_IMP_CAVIUM 0x43 @@ -159,10 +151,19 @@ struct midr_range { #define MIDR_REV(m, v, r) MIDR_RANGE(m, v, r, v, r) #define MIDR_ALL_VERSIONS(m) MIDR_RANGE(m, 0, 0, 0xf, 0xf) +static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min, + u32 rv_max) +{ + u32 _model = midr & MIDR_CPU_MODEL_MASK; + u32 rv = midr & (MIDR_REVISION_MASK | MIDR_VARIANT_MASK); + + return _model == model && rv >= rv_min && rv <= rv_max; +} + static inline bool is_midr_in_range(u32 midr, struct midr_range const *range) { - return MIDR_IS_CPU_MODEL_RANGE(midr, range->model, - range->rv_min, range->rv_max); + return midr_is_cpu_model_range(midr, range->model, + range->rv_min, range->rv_max); } static inline bool diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index d19d14ba9ae4..95201e5ff5e1 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -886,7 +886,7 @@ static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int _ u32 midr = read_cpuid_id(); /* Cavium ThunderX pass 1.x and 2.x */ - return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, + return midr_is_cpu_model_range(midr, MIDR_THUNDERX, MIDR_CPU_VAR_REV(0, 0), MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK)); } -- GitLab From 2951d5efaf8b67cc4851373de92a91a60899611c Mon Sep 17 00:00:00 2001 From: Miles Chen Date: Wed, 7 Aug 2019 08:33:36 +0800 Subject: [PATCH 2172/7155] arm64: mm: print hexadecimal EC value in mem_abort_decode() This change prints the hexadecimal EC value in mem_abort_decode(), which makes it easier to lookup the corresponding EC in the ARM Architecture Reference Manual. The commit 1f9b8936f36f ("arm64: Decode information from ESR upon mem faults") prints useful information when memory abort occurs. It would be easier to lookup "0x25" instead of "DABT" in the document. Then we can check the corresponding ISS. For example: Current info Document EC Exception class "CP15 MCR/MRC" 0x3 "MCR or MRC access to CP15a..." "ASIMD" 0x7 "Access to SIMD or floating-point..." "DABT (current EL)" 0x25 "Data Abort taken without..." ... Before: Unable to handle kernel paging request at virtual address 000000000000c000 Mem abort info: ESR = 0x96000046 Exception class = DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000046 CM = 0, WnR = 1 After: Unable to handle kernel paging request at virtual address 000000000000c000 Mem abort info: ESR = 0x96000046 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000046 CM = 0, WnR = 1 Cc: Anshuman Khandual Cc: James Morse Acked-by: Mark Rutland Signed-off-by: Miles Chen Signed-off-by: Will Deacon --- arch/arm64/mm/fault.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index cfd65b63f36f..ad4980a27edb 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -86,8 +86,8 @@ static void mem_abort_decode(unsigned int esr) pr_alert("Mem abort info:\n"); pr_alert(" ESR = 0x%08x\n", esr); - pr_alert(" Exception class = %s, IL = %u bits\n", - esr_get_class_string(esr), + pr_alert(" EC = 0x%02lx: %s, IL = %u bits\n", + ESR_ELx_EC(esr), esr_get_class_string(esr), (esr & ESR_ELx_IL) ? 32 : 16); pr_alert(" SET = %lu, FnV = %lu\n", (esr & ESR_ELx_SET_MASK) >> ESR_ELx_SET_SHIFT, -- GitLab From 08f103b9a9502974109fab47ea35ca8542c4e57a Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Wed, 7 Aug 2019 11:34:45 +0100 Subject: [PATCH 2173/7155] arm64/ptrace: Fix typoes in sve_set() comment The ptrace trace SVE flags are prefixed with SVE_PT_*. Update the comment accordingly. Reviewed-by: Dave Martin Signed-off-by: Julien Grall Signed-off-by: Will Deacon --- arch/arm64/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 3cf3b135027e..21176d02e21a 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -870,7 +870,7 @@ static int sve_set(struct task_struct *target, goto out; /* - * Apart from PT_SVE_REGS_MASK, all PT_SVE_* flags are consumed by + * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by * sve_set_vector_length(), which will also validate them for us: */ ret = sve_set_vector_length(target, header.vl, -- GitLab From 0ad0bdd8ba6489d05044aa5ca6c6f7491be7743c Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 6 Aug 2019 12:26:53 -0700 Subject: [PATCH 2174/7155] of/platform: Fix fn definitons for of_link_is_valid() and of_link_property() of_link_is_valid() can be static since it's not used anywhere else. of_link_property() return type should have been int instead of bool. Reported-by: Stephen Rothwell Signed-off-by: Saravana Kannan Acked-by: Rob Herring Link: https://lore.kernel.org/r/20190806192654.138605-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 21838226d68a..f68de5c4aeff 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -506,7 +506,7 @@ int of_platform_default_populate(struct device_node *root, } EXPORT_SYMBOL_GPL(of_platform_default_populate); -bool of_link_is_valid(struct device_node *con, struct device_node *sup) +static bool of_link_is_valid(struct device_node *con, struct device_node *sup) { of_node_get(sup); /* @@ -625,7 +625,7 @@ static const struct supplier_bindings bindings[] = { { }, }; -static bool of_link_property(struct device *dev, struct device_node *con_np, +static int of_link_property(struct device *dev, struct device_node *con_np, const char *prop) { struct device_node *phandle; -- GitLab From 5adf5781019dd21233d6d13ab0d78bf03a13d4f1 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 6 Aug 2019 19:05:58 -0700 Subject: [PATCH 2175/7155] of/platform: Fix device_links_supplier_sync_state_resume() warning In platforms/devices which have CONFIG_OF turned on but don't have a populated DT, the calls to device_links_supplier_sync_state_pause() and device_links_supplier_sync_state_resume() can get mismatched. This will cause a warning during boot. Fix the warning by making sure the calls are matched even in that case. Reported-by: Qian Cai Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20190807020559.74458-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index f68de5c4aeff..a3cd69772264 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -723,7 +723,8 @@ arch_initcall_sync(of_platform_default_populate_init); static int __init of_platform_sync_state_init(void) { - device_links_supplier_sync_state_resume(); + if (of_have_populated_dt()) + device_links_supplier_sync_state_resume(); return 0; } late_initcall_sync(of_platform_sync_state_init); -- GitLab From f19b4fe783e753cfc0322969a8bc80c43c979316 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 27 Jul 2019 16:16:56 +0200 Subject: [PATCH 2176/7155] ARM: dts: exynos: Use space after '=' in exynos4412-itop-scp-core Replace tab with space after assignment operator. Signed-off-by: Krzysztof Kozlowski --- .../arm/boot/dts/exynos4412-itop-scp-core.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi index 462a5409b1de..dfceb155b3a7 100644 --- a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi +++ b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi @@ -377,7 +377,7 @@ buck1_reg: BUCK1 { regulator-name = "vdd_mif"; regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -386,7 +386,7 @@ buck2_reg: BUCK2 { regulator-name = "vdd_arm"; regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1456250>; + regulator-max-microvolt = <1456250>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -395,7 +395,7 @@ buck3_reg: BUCK3 { regulator-name = "vdd_int"; regulator-min-microvolt = <875000>; - regulator-max-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -404,7 +404,7 @@ buck4_reg: BUCK4 { regulator-name = "vdd_g3d"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -413,7 +413,7 @@ buck5_reg: BUCK5 { regulator-name = "vdd_m12"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -422,7 +422,7 @@ buck6_reg: BUCK6 { regulator-name = "vdd12_5m"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; op_mode = <1>; /* Normal Mode */ @@ -431,7 +431,7 @@ buck7_reg: BUCK7 { regulator-name = "pvdd_buck7"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; regulator-boot-on; regulator-always-on; op_mode = <1>; /* Normal Mode */ @@ -440,7 +440,7 @@ buck8_reg: BUCK8 { regulator-name = "pvdd_buck8"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; op_mode = <1>; /* Normal Mode */ @@ -449,7 +449,7 @@ buck9_reg: BUCK9 { regulator-name = "vddf28_emmc"; regulator-min-microvolt = <750000>; - regulator-max-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; op_mode = <1>; /* Normal Mode */ }; }; -- GitLab From 4675719d0f47d18bc13db62bd21cffd4e4ec8001 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Tue, 2 Jul 2019 22:35:48 +0800 Subject: [PATCH 2177/7155] raid1: use an int as the return value of raise_barrier() Using a sector_t as the return value is misleading, because raise_barrier() only return 0 or -EINTR. Also add comments for the return values of raise_barrier(). Signed-off-by: Hou Tao Signed-off-by: Song Liu --- drivers/md/raid1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 34e26834ad28..108c75006cef 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -872,8 +872,11 @@ static void flush_pending_writes(struct r1conf *conf) * backgroup IO calls must call raise_barrier. Once that returns * there is no normal IO happeing. It must arrange to call * lower_barrier when the particular background IO completes. + * + * If resync/recovery is interrupted, returns -EINTR; + * Otherwise, returns 0. */ -static sector_t raise_barrier(struct r1conf *conf, sector_t sector_nr) +static int raise_barrier(struct r1conf *conf, sector_t sector_nr) { int idx = sector_to_idx(sector_nr); -- GitLab From 143f6e733b73051cd22dcb80951c6c929da413ce Mon Sep 17 00:00:00 2001 From: Xiao Ni Date: Mon, 8 Jul 2019 10:14:32 +0800 Subject: [PATCH 2178/7155] md/raid6: Set R5_ReadError when there is read failure on parity disk 7471fb77ce4d ("md/raid6: Fix anomily when recovering a single device in RAID6.") avoids rereading P when it can be computed from other members. However, this misses the chance to re-write the right data to P. This patch sets R5_ReadError if the re-read fails. Also, when re-read is skipped, we also missed the chance to reset rdev->read_errors to 0. It can fail the disk when there are many read errors on P member disk (other disks don't have read error) V2: upper layer read request don't read parity/Q data. So there is no need to consider such situation. This is Reported-by: kbuild test robot Fixes: 7471fb77ce4d ("md/raid6: Fix anomily when recovering a single device in RAID6.") Cc: #4.4+ Signed-off-by: Xiao Ni Signed-off-by: Song Liu --- drivers/md/raid5.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 3de4e13bde98..59cafafd5a5d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2558,7 +2558,9 @@ static void raid5_end_read_request(struct bio * bi) && !test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) retry = 1; if (retry) - if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) { + if (sh->qd_idx >= 0 && sh->pd_idx == i) + set_bit(R5_ReadError, &sh->dev[i].flags); + else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) { set_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); } else -- GitLab From eeba6809d8d58908b5ed1b5ceb5fcb09a98a7cad Mon Sep 17 00:00:00 2001 From: Yufen Yu Date: Fri, 19 Jul 2019 13:48:46 +0800 Subject: [PATCH 2179/7155] md/raid1: end bio when the device faulty When write bio return error, it would be added to conf->retry_list and wait for raid1d thread to retry write and acknowledge badblocks. In narrow_write_error(), the error bio will be split in the unit of badblock shift (such as one sector) and raid1d thread issues them one by one. Until all of the splited bio has finished, raid1d thread can go on processing other things, which is time consuming. But, there is a scene for error handling that is not necessary. When the device has been set faulty, flush_bio_list() may end bios in pending_bio_list with error status. Since these bios has not been issued to the device actually, error handlding to retry write and acknowledge badblocks make no sense. Even without that scene, when the device is faulty, badblocks info can not be written out to the device. Thus, we also no need to handle the error IO. Signed-off-by: Yufen Yu Signed-off-by: Song Liu --- drivers/md/raid1.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 108c75006cef..7ffbd8112400 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -447,19 +447,21 @@ static void raid1_end_write_request(struct bio *bio) /* We never try FailFast to WriteMostly devices */ !test_bit(WriteMostly, &rdev->flags)) { md_error(r1_bio->mddev, rdev); - if (!test_bit(Faulty, &rdev->flags)) - /* This is the only remaining device, - * We need to retry the write without - * FailFast - */ - set_bit(R1BIO_WriteError, &r1_bio->state); - else { - /* Finished with this branch */ - r1_bio->bios[mirror] = NULL; - to_put = bio; - } - } else + } + + /* + * When the device is faulty, it is not necessary to + * handle write error. + * For failfast, this is the only remaining device, + * We need to retry the write without FailFast. + */ + if (!test_bit(Faulty, &rdev->flags)) set_bit(R1BIO_WriteError, &r1_bio->state); + else { + /* Finished with this branch */ + r1_bio->bios[mirror] = NULL; + to_put = bio; + } } else { /* * Set R1BIO_Uptodate in our master bio, so that we -- GitLab From 7cee6d4e6035603d42acd56d591e624921aa1b14 Mon Sep 17 00:00:00 2001 From: Yufen Yu Date: Fri, 19 Jul 2019 13:48:47 +0800 Subject: [PATCH 2180/7155] md/raid10: end bio when the device faulty Just like raid1, we do not queue write error bio to retry write and acknowlege badblocks, when the device is faulty. Signed-off-by: Yufen Yu Signed-off-by: Song Liu --- drivers/md/raid10.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8a1354a08a1a..a982e040b609 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -465,19 +465,21 @@ static void raid10_end_write_request(struct bio *bio) if (test_bit(FailFast, &rdev->flags) && (bio->bi_opf & MD_FAILFAST)) { md_error(rdev->mddev, rdev); - if (!test_bit(Faulty, &rdev->flags)) - /* This is the only remaining device, - * We need to retry the write without - * FailFast - */ - set_bit(R10BIO_WriteError, &r10_bio->state); - else { - r10_bio->devs[slot].bio = NULL; - to_put = bio; - dec_rdev = 1; - } - } else + } + + /* + * When the device is faulty, it is not necessary to + * handle write error. + * For failfast, this is the only remaining device, + * We need to retry the write without FailFast. + */ + if (!test_bit(Faulty, &rdev->flags)) set_bit(R10BIO_WriteError, &r10_bio->state); + else { + r10_bio->devs[slot].bio = NULL; + to_put = bio; + dec_rdev = 1; + } } } else { /* -- GitLab From cf89160793c439dca00e2563d0b7f153c274027b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 23:41:55 +0300 Subject: [PATCH 2181/7155] md: Convert to use int_pow() Instead of linear approach to calculate power of 10, use generic int_pow() which does it better. Signed-off-by: Andy Shevchenko Signed-off-by: Song Liu --- drivers/md/md.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 24638ccedce4..3f1252440ad0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3664,11 +3664,7 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) return -EINVAL; if (decimals < 0) decimals = 0; - while (decimals < scale) { - result *= 10; - decimals ++; - } - *res = result; + *res = result * int_pow(10, scale - decimals); return 0; } -- GitLab From 9a567843f7ce0037bfd4d5fdc58a09d0a527b28b Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Wed, 24 Jul 2019 11:09:19 +0200 Subject: [PATCH 2182/7155] md: allow last device to be forcibly removed from RAID1/RAID10. When the 'last' device in a RAID1 or RAID10 reports an error, we do not mark it as failed. This would serve little purpose as there is no risk of losing data beyond that which is obviously lost (as there is with RAID5), and there could be other sectors on the device which are readable, and only readable from this device. This in general this maximises access to data. However the current implementation also stops an admin from removing the last device by direct action. This is rarely useful, but in many case is not harmful and can make automation easier by removing special cases. Also, if an attempt to write metadata fails the device must be marked as faulty, else an infinite loop will result, attempting to update the metadata on all non-faulty devices. So add 'fail_last_dev' member to 'struct mddev', then we can bypasses the 'last disk' checks for RAID1 and RAID10, and control the behavior per array by change sysfs node. Signed-off-by: NeilBrown [add sysfs node for fail_last_dev by Guoqing] Signed-off-by: Guoqing Jiang Signed-off-by: Song Liu --- drivers/md/md.c | 29 +++++++++++++++++++++++++++++ drivers/md/md.h | 1 + drivers/md/raid1.c | 6 +++--- drivers/md/raid10.c | 6 +++--- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 3f1252440ad0..67b90d547f8b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5178,6 +5178,34 @@ static struct md_sysfs_entry md_consistency_policy = __ATTR(consistency_policy, S_IRUGO | S_IWUSR, consistency_policy_show, consistency_policy_store); +static ssize_t fail_last_dev_show(struct mddev *mddev, char *page) +{ + return sprintf(page, "%d\n", mddev->fail_last_dev); +} + +/* + * Setting fail_last_dev to true to allow last device to be forcibly removed + * from RAID1/RAID10. + */ +static ssize_t +fail_last_dev_store(struct mddev *mddev, const char *buf, size_t len) +{ + int ret; + bool value; + + ret = kstrtobool(buf, &value); + if (ret) + return ret; + + if (value != mddev->fail_last_dev) + mddev->fail_last_dev = value; + + return len; +} +static struct md_sysfs_entry md_fail_last_dev = +__ATTR(fail_last_dev, S_IRUGO | S_IWUSR, fail_last_dev_show, + fail_last_dev_store); + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_layout.attr, @@ -5194,6 +5222,7 @@ static struct attribute *md_default_attrs[] = { &md_array_size.attr, &max_corr_read_errors.attr, &md_consistency_policy.attr, + &md_fail_last_dev.attr, NULL, }; diff --git a/drivers/md/md.h b/drivers/md/md.h index 10f98200e2f8..b742659150a2 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -487,6 +487,7 @@ struct mddev { unsigned int good_device_nr; /* good device num within cluster raid */ bool has_superblocks:1; + bool fail_last_dev:1; }; enum recovery_flags { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7ffbd8112400..cd80f281b95d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1617,12 +1617,12 @@ static void raid1_error(struct mddev *mddev, struct md_rdev *rdev) /* * If it is not operational, then we have already marked it as dead - * else if it is the last working disks, ignore the error, let the - * next level up know. + * else if it is the last working disks with "fail_last_dev == false", + * ignore the error, let the next level up know. * else mark the drive as failed */ spin_lock_irqsave(&conf->device_lock, flags); - if (test_bit(In_sync, &rdev->flags) + if (test_bit(In_sync, &rdev->flags) && !mddev->fail_last_dev && (conf->raid_disks - mddev->degraded) == 1) { /* * Don't fail the drive, act as though we were just a diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a982e040b609..299c7b1c9718 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1640,12 +1640,12 @@ static void raid10_error(struct mddev *mddev, struct md_rdev *rdev) /* * If it is not operational, then we have already marked it as dead - * else if it is the last working disks, ignore the error, let the - * next level up know. + * else if it is the last working disks with "fail_last_dev == false", + * ignore the error, let the next level up know. * else mark the drive as failed */ spin_lock_irqsave(&conf->device_lock, flags); - if (test_bit(In_sync, &rdev->flags) + if (test_bit(In_sync, &rdev->flags) && !mddev->fail_last_dev && !enough(conf, rdev->raid_disk)) { /* * Don't fail the drive, just return an IO error. -- GitLab From 062f5b2ae12a153644c765e7ba3b0f825427be1d Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Wed, 24 Jul 2019 11:09:20 +0200 Subject: [PATCH 2183/7155] md: don't set In_sync if array is frozen When a disk is added to array, the following path is called in mdadm. Manage_subdevs -> sysfs_freeze_array -> Manage_add -> sysfs_set_str(&info, NULL, "sync_action","idle") Then from kernel side, Manage_add invokes the path (add_new_disk -> validate_super = super_1_validate) to set In_sync flag. Since In_sync means "device is in_sync with rest of array", and the new added disk need to resync thread to help the synchronization of data. And md_reap_sync_thread would call spare_active to set In_sync for the new added disk finally. So don't set In_sync if array is in frozen. Signed-off-by: Guoqing Jiang Signed-off-by: Song Liu --- drivers/md/md.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 67b90d547f8b..1cdaa6ff9bd7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1826,8 +1826,15 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) if (!(le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_BITMAP)) rdev->saved_raid_disk = -1; - } else - set_bit(In_sync, &rdev->flags); + } else { + /* + * If the array is FROZEN, then the device can't + * be in_sync with rest of array. + */ + if (!test_bit(MD_RECOVERY_FROZEN, + &mddev->recovery)) + set_bit(In_sync, &rdev->flags); + } rdev->raid_disk = role; break; } -- GitLab From 0d8ed0e9bf9643f27f4816dca61081784dedb38d Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Wed, 24 Jul 2019 11:09:21 +0200 Subject: [PATCH 2184/7155] md: don't call spare_active in md_reap_sync_thread if all member devices can't work When add one disk to array, the md_reap_sync_thread is responsible to activate the spare and set In_sync flag for the new member in spare_active(). But if raid1 has one member disk A, and disk B is added to the array. Then we offline A before all the datas are synchronized from A to B, obviously B doesn't have the latest data as A, but B is still marked with In_sync flag. So let's not call spare_active under the condition, otherwise B is still showed with 'U' state which is not correct. Signed-off-by: Guoqing Jiang Signed-off-by: Song Liu --- drivers/md/md.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 1cdaa6ff9bd7..daa885ee4d60 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9075,7 +9075,8 @@ void md_reap_sync_thread(struct mddev *mddev) /* resync has finished, collect result */ md_unregister_thread(&mddev->sync_thread); if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { + !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && + mddev->degraded != mddev->raid_disks) { /* success...*/ /* activate any spares */ if (mddev->pers->spare_active(mddev)) { -- GitLab From 449808a254fd567d3dbeb11595a0af238c687c82 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Sat, 27 Jul 2019 14:02:58 +0800 Subject: [PATCH 2185/7155] raid1: factor out a common routine to handle the completion of sync write It's just code clean-up. Signed-off-by: Hou Tao Signed-off-by: Song Liu --- drivers/md/raid1.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index cd80f281b95d..6ea4f2679b78 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1906,6 +1906,22 @@ static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio) } while (sectors_to_go > 0); } +static void put_sync_write_buf(struct r1bio *r1_bio, int uptodate) +{ + if (atomic_dec_and_test(&r1_bio->remaining)) { + struct mddev *mddev = r1_bio->mddev; + int s = r1_bio->sectors; + + if (test_bit(R1BIO_MadeGood, &r1_bio->state) || + test_bit(R1BIO_WriteError, &r1_bio->state)) + reschedule_retry(r1_bio); + else { + put_buf(r1_bio); + md_done_sync(mddev, s, uptodate); + } + } +} + static void end_sync_write(struct bio *bio) { int uptodate = !bio->bi_status; @@ -1932,16 +1948,7 @@ static void end_sync_write(struct bio *bio) ) set_bit(R1BIO_MadeGood, &r1_bio->state); - if (atomic_dec_and_test(&r1_bio->remaining)) { - int s = r1_bio->sectors; - if (test_bit(R1BIO_MadeGood, &r1_bio->state) || - test_bit(R1BIO_WriteError, &r1_bio->state)) - reschedule_retry(r1_bio); - else { - put_buf(r1_bio); - md_done_sync(mddev, s, uptodate); - } - } + put_sync_write_buf(r1_bio, uptodate); } static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector, @@ -2224,17 +2231,7 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) generic_make_request(wbio); } - if (atomic_dec_and_test(&r1_bio->remaining)) { - /* if we're here, all write(s) have completed, so clean up */ - int s = r1_bio->sectors; - if (test_bit(R1BIO_MadeGood, &r1_bio->state) || - test_bit(R1BIO_WriteError, &r1_bio->state)) - reschedule_retry(r1_bio); - else { - put_buf(r1_bio); - md_done_sync(mddev, s, 1); - } - } + put_sync_write_buf(r1_bio, 1); } /* -- GitLab From 1e1c735a6ba0698a107b99979aad72f48392a441 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 2 Aug 2019 12:18:21 +0200 Subject: [PATCH 2186/7155] ARM: dts: exynos: Add port map to Exynos5250 AHCI node Exynos AHCI (SATA) controller has only one port for SATA device. According to AHCI driver bindings (ata/ahci-platform.txt), if the bootloader doesn't program the PORTS_IMPL register to proper value, the available port map has to be provided by 'ports-implemented' device tree property. This fixes SATA operation on Exynos5250-based boards since Linux v4.5. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5250.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index d5e0392b409e..30f6f5c6bbcb 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -346,6 +346,7 @@ clock-names = "sata", "sclk_sata"; phys = <&sata_phy>; phy-names = "sata-phy"; + ports-implemented = <0x1>; status = "disabled"; }; -- GitLab From 91a49470c29cc0abea8e8481a2f2744a59f49caf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 2 Aug 2019 12:18:22 +0200 Subject: [PATCH 2187/7155] ARM: exynos_defconfig: Enable AHCI-platform SATA driver Exynos5250-based Arndale board has one eSATA port, so enable AHCI-platform driver, which handles it. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/exynos_defconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 2e6a863d25aa..08db1c83eb2d 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -92,9 +92,12 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y +CONFIG_ATA=y +# CONFIG_SATA_PMP is not set +CONFIG_SATA_AHCI_PLATFORM=y +# CONFIG_ATA_SFF is not set CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m -- GitLab From 94f3e14e00fd43024b1c4d8e0c1e442db9b4d964 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 6 Aug 2019 09:59:50 +0800 Subject: [PATCH 2188/7155] mlx5: Use refcount_t for refcount Reference counters are preferred to use refcount_t instead of atomic_t. This is because the implementation of refcount_t can prevent overflows and detect possible use-after-free. So convert atomic_t ref counters to refcount_t. Signed-off-by: Chuhong Yuan Acked-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/srq_cmd.c | 6 +++--- drivers/net/ethernet/mellanox/mlx5/core/qp.c | 6 +++--- include/linux/mlx5/driver.h | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/srq_cmd.c b/drivers/infiniband/hw/mlx5/srq_cmd.c index b0d0687c7a68..8fc3630a9d4c 100644 --- a/drivers/infiniband/hw/mlx5/srq_cmd.c +++ b/drivers/infiniband/hw/mlx5/srq_cmd.c @@ -86,7 +86,7 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn) xa_lock(&table->array); srq = xa_load(&table->array, srqn); if (srq) - atomic_inc(&srq->common.refcount); + refcount_inc(&srq->common.refcount); xa_unlock(&table->array); return srq; @@ -592,7 +592,7 @@ int mlx5_cmd_create_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq, if (err) return err; - atomic_set(&srq->common.refcount, 1); + refcount_set(&srq->common.refcount, 1); init_completion(&srq->common.free); err = xa_err(xa_store_irq(&table->array, srq->srqn, srq, GFP_KERNEL)); @@ -675,7 +675,7 @@ static int srq_event_notifier(struct notifier_block *nb, xa_lock(&table->array); srq = xa_load(&table->array, srqn); if (srq) - atomic_inc(&srq->common.refcount); + refcount_inc(&srq->common.refcount); xa_unlock(&table->array); if (!srq) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index b8ba74de9555..7b44d1e49604 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -53,7 +53,7 @@ mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn) common = radix_tree_lookup(&table->tree, rsn); if (common) - atomic_inc(&common->refcount); + refcount_inc(&common->refcount); spin_unlock_irqrestore(&table->lock, flags); @@ -62,7 +62,7 @@ mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn) void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common) { - if (atomic_dec_and_test(&common->refcount)) + if (refcount_dec_and_test(&common->refcount)) complete(&common->free); } @@ -209,7 +209,7 @@ static int create_resource_common(struct mlx5_core_dev *dev, if (err) return err; - atomic_set(&qp->common.refcount, 1); + refcount_set(&qp->common.refcount, 1); init_completion(&qp->common.free); qp->pid = current->pid; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 267b2bc0ca4a..0acd28f2e62c 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -398,7 +399,7 @@ enum mlx5_res_type { struct mlx5_core_rsc_common { enum mlx5_res_type res; - atomic_t refcount; + refcount_t refcount; struct completion free; }; -- GitLab From 653a23ca7e1e1ae907654e91d028bc6dfc7fce0c Mon Sep 17 00:00:00 2001 From: Marc Koderer Date: Tue, 6 Aug 2019 15:24:12 +0200 Subject: [PATCH 2189/7155] Use kvmalloc in cgroups-v1 Instead of using its own logic for k-/vmalloc rely on kvmalloc which is actually doing quite the same. Signed-off-by: Marc Koderer Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup-v1.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index 88006be40ea3..7f83f4121d8d 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -193,25 +193,6 @@ struct cgroup_pidlist { struct delayed_work destroy_dwork; }; -/* - * The following two functions "fix" the issue where there are more pids - * than kmalloc will give memory for; in such cases, we use vmalloc/vfree. - * TODO: replace with a kernel-wide solution to this problem - */ -#define PIDLIST_TOO_LARGE(c) ((c) * sizeof(pid_t) > (PAGE_SIZE * 2)) -static void *pidlist_allocate(int count) -{ - if (PIDLIST_TOO_LARGE(count)) - return vmalloc(array_size(count, sizeof(pid_t))); - else - return kmalloc_array(count, sizeof(pid_t), GFP_KERNEL); -} - -static void pidlist_free(void *p) -{ - kvfree(p); -} - /* * Used to destroy all pidlists lingering waiting for destroy timer. None * should be left afterwards. @@ -244,7 +225,7 @@ static void cgroup_pidlist_destroy_work_fn(struct work_struct *work) */ if (!delayed_work_pending(dwork)) { list_del(&l->links); - pidlist_free(l->list); + kvfree(l->list); put_pid_ns(l->key.ns); tofree = l; } @@ -365,7 +346,7 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, * show up until sometime later on. */ length = cgroup_task_count(cgrp); - array = pidlist_allocate(length); + array = kvmalloc_array(length, sizeof(pid_t), GFP_KERNEL); if (!array) return -ENOMEM; /* now, populate the array */ @@ -390,12 +371,12 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, l = cgroup_pidlist_find_create(cgrp, type); if (!l) { - pidlist_free(array); + kvfree(array); return -ENOMEM; } /* store array, freeing old if necessary */ - pidlist_free(l->list); + kvfree(l->list); l->list = array; l->length = length; *lp = l; -- GitLab From 29e97f56f2ee0dd5dbd0f7a0a698f2cdcaf54c79 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:39 +0200 Subject: [PATCH 2190/7155] ARM: davinci: enable the clocksource driver for DT mode Switch all davinci boards supporting device tree to using the new clocksource driver: remove the previous OF_TIMER_DECLARE() from mach-davinci and select davinci-timer for ARCH_DAVINCI. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/Kconfig | 1 + arch/arm/mach-davinci/time.c | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 33b00579beff..92ff58be1a43 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -583,6 +583,7 @@ config ARCH_DAVINCI select ARCH_HAS_HOLES_MEMORYMODEL select COMMON_CLK select CPU_ARM926T + select DAVINCI_TIMER select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 5a6de5368ab0..740410a3bb6a 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -398,17 +398,3 @@ void __init davinci_timer_init(struct clk *timer_clk) for (i=0; i< ARRAY_SIZE(timers); i++) timer32_config(&timers[i]); } - -static int __init of_davinci_timer_init(struct device_node *np) -{ - struct clk *clk; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - davinci_timer_init(clk); - - return 0; -} -TIMER_OF_DECLARE(davinci_timer, "ti,da830-timer", of_davinci_timer_init); -- GitLab From d470df3bc5e1a9cd38995b55c918d9ecdda141e1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:40 +0200 Subject: [PATCH 2191/7155] ARM: davinci: WARN_ON() if clk_get() fails Currently the timer code checks if the clock pointer passed to it is good (!IS_ERR(clk)). The new clocksource driver expects the clock to be functional and doesn't perform any checks so emit a warning if clk_get() fails. Apply this to all davinci platforms. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da830.c | 4 ++++ arch/arm/mach-davinci/da850.c | 4 ++++ arch/arm/mach-davinci/dm355.c | 4 ++++ arch/arm/mach-davinci/dm365.c | 4 ++++ arch/arm/mach-davinci/dm644x.c | 4 ++++ arch/arm/mach-davinci/dm646x.c | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index e6b8ffd934a1..220e99438ae0 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -751,6 +751,10 @@ void __init da830_init_time(void) da830_pll_init(NULL, pll, NULL); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 77bc64d6e39b..dcf3536c46bc 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -681,6 +681,10 @@ void __init da850_init_time(void) da850_pll0_init(NULL, pll0, cfgchip); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index c6073326be2e..a38a3648345b 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -743,6 +743,10 @@ void __init dm355_init_time(void) dm355_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 2f9ae6431bf5..8062412be70f 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -784,6 +784,10 @@ void __init dm365_init_time(void) dm365_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 1b9e9a6192ef..7a6b5a48cae5 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -679,6 +679,10 @@ void __init dm644x_init_time(void) dm644x_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 62ca952fe161..97fe533726e9 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -663,6 +663,10 @@ void __init dm646x_init_time(unsigned long ref_clk_rate, dm646x_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } davinci_timer_init(clk); } -- GitLab From 76c7473f753dabee2e6ad03f72181b45083a0c7c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:41 +0200 Subject: [PATCH 2192/7155] ARM: davinci: da850: switch to using the clocksource driver We now have a proper clocksource driver for davinci. Switch the da850 platform to using it. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da850.c | 46 ++++++++++------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index dcf3536c46bc..73b7cc53f966 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -35,7 +35,8 @@ #include #include #include -#include + +#include #include "irqs.h" #include "mux.h" @@ -333,38 +334,16 @@ static struct davinci_id da850_ids[] = { }, }; -static struct davinci_timer_instance da850_timer_instance[4] = { - { - .base = DA8XX_TIMER64P0_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0), - }, - { - .base = DA8XX_TIMER64P1_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1), - }, - { - .base = DA850_TIMER64P2_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_2), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_2), - }, - { - .base = DA850_TIMER64P3_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_3), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_3), - }, -}; - /* - * T0_BOT: Timer 0, bottom : Used for clock_event - * T0_TOP: Timer 0, top : Used for clocksource - * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer + * Bottom half of timer 0 is used for clock_event, top half for + * clocksource. */ -static struct davinci_timer_info da850_timer_info = { - .timers = da850_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg da850_timer_cfg = { + .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0)), + }, }; #ifdef CONFIG_CPU_FREQ @@ -635,7 +614,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = { .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da850_pins, .pinmux_pins_num = ARRAY_SIZE(da850_pins), - .timer_info = &da850_timer_info, .emac_pdata = &da8xx_emac_pdata, .sram_dma = DA8XX_SHARED_RAM_BASE, .sram_len = SZ_128K, @@ -672,6 +650,7 @@ void __init da850_init_time(void) void __iomem *pll0; struct regmap *cfgchip; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ); @@ -686,7 +665,8 @@ void __init da850_init_time(void) return; } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &da850_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource da850_pll1_resources[] = { -- GitLab From a248f524ea85f4960ff12267fd70184a8cebd13d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:42 +0200 Subject: [PATCH 2193/7155] ARM: davinci: da830: switch to using the clocksource driver We now have a proper clocksource driver for davinci. Switch the da830 platform to using it. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da830.c | 41 ++++++++++++----------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 220e99438ae0..018ab4b549f1 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -21,7 +21,8 @@ #include #include #include -#include + +#include #include "irqs.h" #include "mux.h" @@ -676,32 +677,17 @@ int __init da830_register_gpio(void) return da8xx_register_gpio(&da830_gpio_platform_data); } -static struct davinci_timer_instance da830_timer_instance[2] = { - { - .base = DA8XX_TIMER64P0_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0), - .cmp_off = DA830_CMP12_0, - .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0), - }, - { - .base = DA8XX_TIMER64P1_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1), - .cmp_off = DA830_CMP12_0, - .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_1), - }, -}; - /* - * T0_BOT: Timer 0, bottom : Used for clock_event & clocksource - * T0_TOP: Timer 0, top : Used by DSP - * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer + * Bottom half of timer0 is used both for clock even and clocksource. + * Top half is used by DSP. */ -static struct davinci_timer_info da830_timer_info = { - .timers = da830_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_BOT, +static const struct davinci_timer_cfg da830_timer_cfg = { + .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)), + }, + .cmp_off = DA830_CMP12_0, }; static const struct davinci_soc_info davinci_soc_info_da830 = { @@ -713,7 +699,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = { .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da830_pins, .pinmux_pins_num = ARRAY_SIZE(da830_pins), - .timer_info = &da830_timer_info, .emac_pdata = &da8xx_emac_pdata, }; @@ -743,6 +728,7 @@ void __init da830_init_time(void) { void __iomem *pll; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA830_REF_FREQ); @@ -756,7 +742,8 @@ void __init da830_init_time(void) return; } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &da830_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource da830_psc0_resources[] = { -- GitLab From 66ae81dccc02a3e0793ae01fd1a20590e561d733 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:43 +0200 Subject: [PATCH 2194/7155] ARM: davinci: move timer definitions to davinci.h Boards from the dm* family rely on register offset definitions from arch/arm/mach-davinci/include/mach/time.h. We'll be removing this file soon, so move the required defines to davinci.h where the rest of such constants live. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/davinci.h | 3 +++ arch/arm/mach-davinci/include/mach/time.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 56c1835c42e5..208d7a4d3597 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -60,6 +60,9 @@ void davinci_map_sysmod(void); #define DAVINCI_GPIO_BASE 0x01C67000 int davinci_gpio_register(struct resource *res, int size, void *pdata); +#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) +#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) + /* DM355 base addresses */ #define DM355_ASYNC_EMIF_CONTROL_BASE 0x01e10000 #define DM355_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h index 1c971d8d8ba8..ba913736990f 100644 --- a/arch/arm/mach-davinci/include/mach/time.h +++ b/arch/arm/mach-davinci/include/mach/time.h @@ -11,9 +11,7 @@ #ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H #define __ARCH_ARM_MACH_DAVINCI_TIME_H -#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) #define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) -#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) enum { T0_BOT, -- GitLab From c0512c2ca380cdfb109e44f65ecdf45c8693d533 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:17:44 +0200 Subject: [PATCH 2195/7155] ARM: davinci: dm355: switch to using the clocksource driver We now have a proper clocksource driver for davinci. Switch the dm355 platform to using it. Signed-off-by: Bartosz Golaszewski Reviewed-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/dm355.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index a38a3648345b..5de72d2fa8f0 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -30,7 +30,8 @@ #include #include #include -#include + +#include #include "asp.h" #include "davinci.h" @@ -620,15 +621,15 @@ static struct davinci_id dm355_ids[] = { }; /* - * T0_BOT: Timer 0, bottom: clockevent source for hrtimers - * T0_TOP: Timer 0, top : clocksource for generic timekeeping - * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) - * T1_TOP: Timer 1, top : + * Bottom half of timer0 is used for clockevent, top half is used for + * clocksource. */ -static struct davinci_timer_info dm355_timer_info = { - .timers = davinci_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg dm355_timer_cfg = { + .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)), + }, }; static struct plat_serial8250_port dm355_serial0_platform_data[] = { @@ -706,7 +707,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = { .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm355_pins, .pinmux_pins_num = ARRAY_SIZE(dm355_pins), - .timer_info = &dm355_timer_info, .sram_dma = 0x00010000, .sram_len = SZ_32K, }; @@ -733,6 +733,7 @@ void __init dm355_init_time(void) { void __iomem *pll1, *psc; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ); @@ -748,7 +749,8 @@ void __init dm355_init_time(void) return; } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &dm355_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource dm355_pll2_resources[] = { -- GitLab From 6b2265975239ab655069d796b822835a593e1cc7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 24 Jul 2019 23:41:29 -0300 Subject: [PATCH 2196/7155] media: staging: tegra-vde: Fix build error If IOMMU_SUPPORT is not set, and COMPILE_TEST is y, IOMMU_IOVA may be set to m. So building will fails: drivers/staging/media/tegra-vde/iommu.o: In function `tegra_vde_iommu_map': iommu.c:(.text+0x41): undefined reference to `alloc_iova' iommu.c:(.text+0x56): undefined reference to `__free_iova' Select IOMMU_IOVA while COMPILE_TEST is set to fix this. Reported-by: Hulk Robot Suggested-by: Dmitry Osipenko Fixes: b301f8de1925 ("media: staging: media: tegra-vde: Add IOMMU support") Signed-off-by: YueHaibing Acked-by: Dmitry Osipenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tegra-vde/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-vde/Kconfig b/drivers/staging/media/tegra-vde/Kconfig index 2e7f644ae591..ba49ea50b8c0 100644 --- a/drivers/staging/media/tegra-vde/Kconfig +++ b/drivers/staging/media/tegra-vde/Kconfig @@ -3,7 +3,7 @@ config TEGRA_VDE tristate "NVIDIA Tegra Video Decoder Engine driver" depends on ARCH_TEGRA || COMPILE_TEST select DMA_SHARED_BUFFER - select IOMMU_IOVA if IOMMU_SUPPORT + select IOMMU_IOVA if (IOMMU_SUPPORT || COMPILE_TEST) select SRAM help Say Y here to enable support for the NVIDIA Tegra video decoder -- GitLab From b40dc2bf3581748aa772ad2690bd6092b1fca8da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Jul 2019 10:00:20 -0300 Subject: [PATCH 2197/7155] media: vicodec: add support for 4 new RGB32 pixelformats Add support for V4L2_PIX_FMT_BGRA/X32 and V4L2_PIX_FMT_RGBA/X32 formats. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vicodec/codec-v4l2-fwht.c | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index 01e7f09efc4e..3c93d9232c3c 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -29,11 +29,15 @@ static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = { { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV}, { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_ABGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV}, { V4L2_PIX_FMT_ARGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_ABGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_BGRX32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_BGRA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_RGBX32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_RGBA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV}, { V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB}, }; @@ -193,6 +197,28 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf, rf->luma++; rf->alpha = rf->cr + 1; break; + case V4L2_PIX_FMT_BGRX32: + rf->cb = rf->luma + 1; + rf->cr = rf->cb + 2; + rf->luma += 2; + break; + case V4L2_PIX_FMT_BGRA32: + rf->alpha = rf->luma; + rf->cb = rf->luma + 1; + rf->cr = rf->cb + 2; + rf->luma += 2; + break; + case V4L2_PIX_FMT_RGBX32: + rf->cr = rf->luma; + rf->cb = rf->cr + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_RGBA32: + rf->alpha = rf->luma + 3; + rf->cr = rf->luma; + rf->cb = rf->cr + 2; + rf->luma++; + break; default: return -EINVAL; } -- GitLab From 00ab9c1a620dc29f3651d5b61ad12aa327d4dd12 Mon Sep 17 00:00:00 2001 From: Rui Wang Date: Wed, 31 Jul 2019 01:29:39 -0300 Subject: [PATCH 2198/7155] media: mtk-vcodec: Handle H264 error bitstreams Error h264 bitstreams which picture info are out range of decoder hardware specification, and no nal start code at the beginning of the buffer, stop decoding and exit. Signed-off-by: Rui Wang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mtk-vcodec/vdec/vdec_h264_if.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c index c5f8f1fca44c..49aa85a9bb5a 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c @@ -29,6 +29,9 @@ #define H264_MAX_FB_NUM 17 #define HDR_PARSING_BUF_SZ 1024 +#define DEC_ERR_RET(ret) ((ret) >> 16) +#define H264_ERR_NOT_VALID 3 + /** * struct h264_fb - h264 decode frame buffer information * @vdec_fb_va : virtual address of struct vdec_fb @@ -357,8 +360,11 @@ static int vdec_h264_decode(void *h_vdec, struct mtk_vcodec_mem *bs, buf = (unsigned char *)bs->va; buf_sz = bs->size; nal_start_idx = find_start_code(buf, buf_sz); - if (nal_start_idx < 0) + if (nal_start_idx < 0) { + mtk_vcodec_err(inst, "invalid nal start code"); + err = -EIO; goto err_free_fb_out; + } nal_start = buf[nal_start_idx]; nal_type = NAL_TYPE(buf[nal_start_idx]); @@ -382,8 +388,14 @@ static int vdec_h264_decode(void *h_vdec, struct mtk_vcodec_mem *bs, data[0] = buf_sz; data[1] = nal_start; err = vpu_dec_start(vpu, data, 2); - if (err) + if (err) { + if (err > 0 && (DEC_ERR_RET(err) == H264_ERR_NOT_VALID)) { + mtk_vcodec_err(inst, "- error bitstream - err = %d -", + err); + err = -EIO; + } goto err_free_fb_out; + } *res_chg = inst->vsi->dec.resolution_changed; if (*res_chg) { -- GitLab From 8fb294ca20886a723007c543a65fcdf286ec667f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 1 Aug 2019 14:56:11 -0300 Subject: [PATCH 2199/7155] media: imx7.rst: Fix the references to the CSI multiplexer In imx7s.dtsi the node name for the CSI multiplexer is "csi-mux", not "csi_mux", so fix all the references in the document. This fixes the following error when the instructions are followed: Unable to parse link: Invalid argument (22) While at it, provide the "media-ctl -p" output from 5.2 kernel version, so that users can see a more updated output. Fixes: fa88fbdafb4a ("media: imx7.rst: add documentation for i.MX7 media driver") Signed-off-by: Fabio Estevam Reviewed-by: Rui Miguel Silva Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/v4l-drivers/imx7.rst | 127 +++++++++++------------ 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/Documentation/media/v4l-drivers/imx7.rst b/Documentation/media/v4l-drivers/imx7.rst index fe411f65c01c..1e442c97da47 100644 --- a/Documentation/media/v4l-drivers/imx7.rst +++ b/Documentation/media/v4l-drivers/imx7.rst @@ -41,7 +41,7 @@ data from MIPI CSI-2 camera sensor. It has one source pad, corresponding to the virtual channel 0. This module is compliant to previous version of Samsung D-phy, and supports two D-PHY Rx Data lanes. -csi_mux +csi-mux ------- This is the video multiplexer. It has two sink pads to select from either camera @@ -56,7 +56,7 @@ can interface directly with Parallel and MIPI CSI-2 buses. It has 256 x 64 FIFO to store received image pixel data and embedded DMA controllers to transfer data from the FIFO through AHB bus. -This entity has one sink pad that receives from the csi_mux entity and a single +This entity has one sink pad that receives from the csi-mux entity and a single source pad that routes video frames directly to memory buffers. This pad is routed to a capture device node. @@ -81,14 +81,14 @@ an output of 800x600, and BGGR 10 bit bayer format: # Setup links media-ctl -l "'ov2680 1-0036':0 -> 'imx7-mipi-csis.0':0[1]" - media-ctl -l "'imx7-mipi-csis.0':1 -> 'csi_mux':1[1]" - media-ctl -l "'csi_mux':2 -> 'csi':0[1]" + media-ctl -l "'imx7-mipi-csis.0':1 -> 'csi-mux':1[1]" + media-ctl -l "'csi-mux':2 -> 'csi':0[1]" media-ctl -l "'csi':1 -> 'csi capture':0[1]" # Configure pads for pipeline media-ctl -V "'ov2680 1-0036':0 [fmt:SBGGR10_1X10/800x600 field:none]" - media-ctl -V "'csi_mux':1 [fmt:SBGGR10_1X10/800x600 field:none]" - media-ctl -V "'csi_mux':2 [fmt:SBGGR10_1X10/800x600 field:none]" + media-ctl -V "'csi-mux':1 [fmt:SBGGR10_1X10/800x600 field:none]" + media-ctl -V "'csi-mux':2 [fmt:SBGGR10_1X10/800x600 field:none]" media-ctl -V "'imx7-mipi-csis.0':0 [fmt:SBGGR10_1X10/800x600 field:none]" media-ctl -V "'csi':0 [fmt:SBGGR10_1X10/800x600 field:none]" @@ -97,64 +97,63 @@ the resolutions supported by the sensor. .. code-block:: none - root@imx7s-warp:~# media-ctl -p - Media controller API version 4.17.0 - - Media device information - ------------------------ - driver imx-media - model imx-media - serial - bus info - hw revision 0x0 - driver version 4.17.0 - - Device topology - - entity 1: csi (2 pads, 2 links) - type V4L2 subdev subtype Unknown flags 0 - device node name /dev/v4l-subdev0 - pad0: Sink - [fmt:SBGGR10_1X10/800x600 field:none] - <- "csi_mux":2 [ENABLED] - pad1: Source - [fmt:SBGGR10_1X10/800x600 field:none] - -> "csi capture":0 [ENABLED] - - - entity 4: csi capture (1 pad, 1 link) - type Node subtype V4L flags 0 - device node name /dev/video0 - pad0: Sink - <- "csi":1 [ENABLED] - - - entity 10: csi_mux (3 pads, 2 links) - type V4L2 subdev subtype Unknown flags 0 - device node name /dev/v4l-subdev1 - pad0: Sink - [fmt:unknown/0x0] - pad1: Sink - [fmt:unknown/800x600 field:none] - <- "imx7-mipi-csis.0":1 [ENABLED] - pad2: Source - [fmt:unknown/800x600 field:none] - -> "csi":0 [ENABLED] - - - entity 14: imx7-mipi-csis.0 (2 pads, 2 links) - type V4L2 subdev subtype Unknown flags 0 - device node name /dev/v4l-subdev2 - pad0: Sink - [fmt:SBGGR10_1X10/800x600 field:none] - <- "ov2680 1-0036":0 [ENABLED] - pad1: Source - [fmt:SBGGR10_1X10/800x600 field:none] - -> "csi_mux":1 [ENABLED] - - - entity 17: ov2680 1-0036 (1 pad, 1 link) - type V4L2 subdev subtype Sensor flags 0 - device node name /dev/v4l-subdev3 - pad0: Source - [fmt:SBGGR10_1X10/800x600 field:none] - -> "imx7-mipi-csis.0":0 [ENABLED] - + # media-ctl -p + Media controller API version 5.2.0 + + Media device information + ------------------------ + driver imx7-csi + model imx-media + serial + bus info + hw revision 0x0 + driver version 5.2.0 + + Device topology + - entity 1: csi (2 pads, 2 links) + type V4L2 subdev subtype Unknown flags 0 + device node name /dev/v4l-subdev0 + pad0: Sink + [fmt:SBGGR10_1X10/800x600 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range] + <- "csi-mux":2 [ENABLED] + pad1: Source + [fmt:SBGGR10_1X10/800x600 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range] + -> "csi capture":0 [ENABLED] + + - entity 4: csi capture (1 pad, 1 link) + type Node subtype V4L flags 0 + device node name /dev/video0 + pad0: Sink + <- "csi":1 [ENABLED] + + - entity 10: csi-mux (3 pads, 2 links) + type V4L2 subdev subtype Unknown flags 0 + device node name /dev/v4l-subdev1 + pad0: Sink + [fmt:Y8_1X8/1x1 field:none] + pad1: Sink + [fmt:SBGGR10_1X10/800x600 field:none] + <- "imx7-mipi-csis.0":1 [ENABLED] + pad2: Source + [fmt:SBGGR10_1X10/800x600 field:none] + -> "csi":0 [ENABLED] + + - entity 14: imx7-mipi-csis.0 (2 pads, 2 links) + type V4L2 subdev subtype Unknown flags 0 + device node name /dev/v4l-subdev2 + pad0: Sink + [fmt:SBGGR10_1X10/800x600 field:none] + <- "ov2680 1-0036":0 [ENABLED] + pad1: Source + [fmt:SBGGR10_1X10/800x600 field:none] + -> "csi-mux":1 [ENABLED] + + - entity 17: ov2680 1-0036 (1 pad, 1 link) + type V4L2 subdev subtype Sensor flags 0 + device node name /dev/v4l-subdev3 + pad0: Source + [fmt:SBGGR10_1X10/800x600@1/30 field:none colorspace:srgb] + -> "imx7-mipi-csis.0":0 [ENABLED] References ---------- -- GitLab From 6898dd580a045341f844862ceb775144156ec1af Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 6 Aug 2019 19:01:36 -0300 Subject: [PATCH 2200/7155] media: media/platform: fsl-viu.c: fix build for MICROBLAZE arch/microblaze/ defines out_be32() and in_be32(), so don't do that again in the driver source. Fixes these build warnings: ../drivers/media/platform/fsl-viu.c:36: warning: "out_be32" redefined ../arch/microblaze/include/asm/io.h:50: note: this is the location of the previous definition ../drivers/media/platform/fsl-viu.c:37: warning: "in_be32" redefined ../arch/microblaze/include/asm/io.h:53: note: this is the location of the previous definition Fixes: 29d750686331 ("media: fsl-viu: allow building it with COMPILE_TEST") Signed-off-by: Randy Dunlap Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/fsl-viu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index bf5392f0d61c..bb64152acf94 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -32,7 +32,7 @@ #define VIU_VERSION "0.5.1" /* Allow building this driver with COMPILE_TEST */ -#ifndef CONFIG_PPC +#if !defined(CONFIG_PPC) && !defined(CONFIG_MICROBLAZE) #define out_be32(v, a) iowrite32be(a, (void __iomem *)v) #define in_be32(a) ioread32be((void __iomem *)a) #endif -- GitLab From 25a3d6bac6b9ff7d62033185780daa1b4f7bee2f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 7 Aug 2019 05:43:32 -0300 Subject: [PATCH 2201/7155] media: adv7511/cobalt: rename driver name to adv7511-v4l2 Commit b2ce5617dad2 ("media: i2c: fix warning same module names") renamed the adv7511 module in the media tree to adv7511-v4l2. This patch does the same rename for the driver name and device id to keep the naming consistent. Since the cobalt driver loads this module, it had to be renamed there as well. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511-v4l2.c | 4 ++-- drivers/media/pci/cobalt/cobalt-driver.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c index 2ad6bdf1a9fc..45cc5a4c2de5 100644 --- a/drivers/media/i2c/adv7511-v4l2.c +++ b/drivers/media/i2c/adv7511-v4l2.c @@ -1980,14 +1980,14 @@ static int adv7511_remove(struct i2c_client *client) /* ----------------------------------------------------------------------- */ static const struct i2c_device_id adv7511_id[] = { - { "adv7511", 0 }, + { "adv7511-v4l2", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, adv7511_id); static struct i2c_driver adv7511_driver = { .driver = { - .name = "adv7511", + .name = "adv7511-v4l2", }, .probe = adv7511_probe, .remove = adv7511_remove, diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index b92833f3d464..0695078ef812 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -584,7 +584,7 @@ static int cobalt_subdevs_hsma_init(struct cobalt *cobalt) .cec_clk = 12000000, }; static struct i2c_board_info adv7511_info = { - .type = "adv7511", + .type = "adv7511-v4l2", .addr = 0x39, /* 0x39 or 0x3d */ .platform_data = &adv7511_pdata, }; -- GitLab From 97299a3035328d7ae2f4fccaf6e549974df6e118 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 15:15:25 -0300 Subject: [PATCH 2202/7155] media: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 1 - drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7 ++----- drivers/media/platform/exynos4-is/mipi-csis.c | 4 +--- drivers/media/platform/imx-pxp.c | 4 +--- drivers/media/platform/omap3isp/isp.c | 1 - drivers/media/platform/renesas-ceu.c | 4 +--- drivers/media/platform/rockchip/rga/rga.c | 1 - drivers/media/platform/s3c-camif/camif-core.c | 4 +--- drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 8 ++------ drivers/media/platform/sti/hva/hva-hw.c | 8 ++------ drivers/media/platform/stm32/stm32-dcmi.c | 5 +---- drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 7 ++----- drivers/media/rc/img-ir/img-ir-core.c | 4 +--- drivers/media/rc/ir-hix5hd2.c | 4 +--- drivers/media/rc/meson-ir.c | 4 +--- drivers/media/rc/mtk-cir.c | 4 +--- drivers/media/rc/sunxi-cir.c | 1 - 17 files changed, 17 insertions(+), 54 deletions(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 3b1d60ca859b..2b42ba1f5949 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2540,7 +2540,6 @@ static int vpfe_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); ret = -ENODEV; goto probe_out_cleanup; } diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c index 266df14da2d5..78381651238d 100644 --- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c +++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c @@ -160,11 +160,8 @@ static int atmel_isc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - dev_err(dev, "failed to get irq: %d\n", ret); - return ret; - } + if (irq < 0) + return irq; ret = devm_request_irq(dev, irq, isc_interrupt, 0, ATMEL_ISC_NAME, isc); diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 3e9ac6066cf6..b9f1cc42b0ab 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -803,10 +803,8 @@ static int s5pcsis_probe(struct platform_device *pdev) return PTR_ERR(state->regs); state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { - dev_err(dev, "Failed to get irq\n"); + if (state->irq < 0) return state->irq; - } for (i = 0; i < CSIS_NUM_SUPPLIES; i++) state->supplies[i].supply = csis_supply_name[i]; diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c index 8e7ef23b9a7e..38d942322302 100644 --- a/drivers/media/platform/imx-pxp.c +++ b/drivers/media/platform/imx-pxp.c @@ -1661,10 +1661,8 @@ static int pxp_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get irq resource: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler, IRQF_ONESHOT, dev_name(&pdev->dev), dev); diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 3b9c82b63433..36fb3bef7dbe 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2387,7 +2387,6 @@ static int isp_probe(struct platform_device *pdev) /* Interrupt */ ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(isp->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iommu; } diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c index 57d0c0f9fa4b..197b3991330d 100644 --- a/drivers/media/platform/renesas-ceu.c +++ b/drivers/media/platform/renesas-ceu.c @@ -1659,10 +1659,8 @@ static int ceu_probe(struct platform_device *pdev) } ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Failed to get irq: %d\n", ret); + if (ret < 0) goto error_free_ceudev; - } irq = ret; ret = devm_request_irq(dev, irq, ceu_irq, diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index 5283d4533fa0..e9ff12b6b5bb 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -831,7 +831,6 @@ static int rga_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(rga->dev, "failed to get irq\n"); ret = irq; goto err_put_clk; } diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index f0acd6edcbba..c6fbcd7036d6 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -380,10 +380,8 @@ static int camif_request_irqs(struct platform_device *pdev, init_waitqueue_head(&vp->irq_queue); irq = platform_get_irq(pdev, i); - if (irq <= 0) { - dev_err(&pdev->dev, "failed to get IRQ %d\n", i); + if (irq <= 0) return -ENXIO; - } ret = devm_request_irq(&pdev->dev, irq, s3c_camif_irq_handler, 0, dev_name(&pdev->dev), vp); diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index 3c05b3dc49ec..5baada4f65e5 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -693,16 +693,12 @@ static int c8sectpfe_probe(struct platform_device *pdev) fei->sram_size = resource_size(res); fei->idle_irq = platform_get_irq_byname(pdev, "c8sectpfe-idle-irq"); - if (fei->idle_irq < 0) { - dev_err(dev, "Can't get c8sectpfe-idle-irq\n"); + if (fei->idle_irq < 0) return fei->idle_irq; - } fei->error_irq = platform_get_irq_byname(pdev, "c8sectpfe-error-irq"); - if (fei->error_irq < 0) { - dev_err(dev, "Can't get c8sectpfe-error-irq\n"); + if (fei->error_irq < 0) return fei->error_irq; - } platform_set_drvdata(pdev, fei); diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c index 7917fd2c4bd4..401aaafa1710 100644 --- a/drivers/media/platform/sti/hva/hva-hw.c +++ b/drivers/media/platform/sti/hva/hva-hw.c @@ -341,10 +341,8 @@ int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva) /* get status interruption resource */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "%s failed to get status IRQ\n", HVA_PREFIX); + if (ret < 0) goto err_clk; - } hva->irq_its = ret; ret = devm_request_threaded_irq(dev, hva->irq_its, hva_hw_its_interrupt, @@ -360,10 +358,8 @@ int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva) /* get error interruption resource */ ret = platform_get_irq(pdev, 1); - if (ret < 0) { - dev_err(dev, "%s failed to get error IRQ\n", HVA_PREFIX); + if (ret < 0) goto err_clk; - } hva->irq_err = ret; ret = devm_request_threaded_irq(dev, hva->irq_err, hva_hw_err_interrupt, diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index d855e9c09c08..672a53195b56 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -1699,11 +1699,8 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->bus.data_shift = ep.bus.parallel.data_shift; irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - if (irq != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get irq\n"); + if (irq <= 0) return irq ? irq : -ENXIO; - } dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!dcmi->res) { diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c index 6e0e894154f4..055eb0b8e396 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c @@ -866,11 +866,8 @@ static int sun6i_csi_resource_request(struct sun6i_csi_dev *sdev, } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "No csi IRQ specified\n"); - ret = -ENXIO; - return ret; - } + if (irq < 0) + return -ENXIO; ret = devm_request_irq(&pdev->dev, irq, sun6i_csi_isr, 0, MODULE_NAME, sdev); diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 7e457f26a595..094aa6a06315 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -81,10 +81,8 @@ static int img_ir_probe(struct platform_device *pdev) /* Get resources from platform device */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "cannot find IRQ resource\n"); + if (irq < 0) return irq; - } /* Private driver data */ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c index 85561f6555a2..32ccefeff57d 100644 --- a/drivers/media/rc/ir-hix5hd2.c +++ b/drivers/media/rc/ir-hix5hd2.c @@ -232,10 +232,8 @@ static int hix5hd2_ir_probe(struct platform_device *pdev) return PTR_ERR(priv->base); priv->irq = platform_get_irq(pdev, 0); - if (priv->irq < 0) { - dev_err(dev, "irq can not get\n"); + if (priv->irq < 0) return priv->irq; - } rdev = rc_allocate_device(RC_DRIVER_IR_RAW); if (!rdev) diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c index 72a7bbbf6b1f..51c6dd3406a0 100644 --- a/drivers/media/rc/meson-ir.c +++ b/drivers/media/rc/meson-ir.c @@ -117,10 +117,8 @@ static int meson_ir_probe(struct platform_device *pdev) return PTR_ERR(ir->reg); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq resource\n"); + if (irq < 0) return irq; - } ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); if (!ir->rc) { diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c index 99a3f1e773c6..a0c94ab322c7 100644 --- a/drivers/media/rc/mtk-cir.c +++ b/drivers/media/rc/mtk-cir.c @@ -358,10 +358,8 @@ static int mtk_ir_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ir); ir->irq = platform_get_irq(pdev, 0); - if (ir->irq < 0) { - dev_err(dev, "no irq resource\n"); + if (ir->irq < 0) return -ENODEV; - } if (clk_prepare_enable(ir->clk)) { dev_err(dev, "try to enable ir_clk failed\n"); diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index f91154c2f45c..e222b4c98be4 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -256,7 +256,6 @@ static int sunxi_ir_probe(struct platform_device *pdev) /* IRQ */ ir->irq = platform_get_irq(pdev, 0); if (ir->irq < 0) { - dev_err(dev, "no irq resource\n"); ret = ir->irq; goto exit_free_dev; } -- GitLab From ef20a9b27c66278ac2f85006db8ea11d5f61a781 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:48 -0700 Subject: [PATCH 2203/7155] libbpf: add helpers for working with BTF types Add lots of frequently used helpers that simplify working with BTF types. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/btf.h | 178 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 88a52ae56fc6..2604dc099855 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -5,6 +5,7 @@ #define __LIBBPF_BTF_H #include +#include #include #ifdef __cplusplus @@ -120,6 +121,183 @@ LIBBPF_API void btf_dump__free(struct btf_dump *d); LIBBPF_API int btf_dump__dump_type(struct btf_dump *d, __u32 id); +/* + * A set of helpers for easier BTF types handling + */ +static inline __u16 btf_kind(const struct btf_type *t) +{ + return BTF_INFO_KIND(t->info); +} + +static inline __u16 btf_vlen(const struct btf_type *t) +{ + return BTF_INFO_VLEN(t->info); +} + +static inline bool btf_kflag(const struct btf_type *t) +{ + return BTF_INFO_KFLAG(t->info); +} + +static inline bool btf_is_int(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_INT; +} + +static inline bool btf_is_ptr(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_PTR; +} + +static inline bool btf_is_array(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_ARRAY; +} + +static inline bool btf_is_struct(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_STRUCT; +} + +static inline bool btf_is_union(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_UNION; +} + +static inline bool btf_is_composite(const struct btf_type *t) +{ + __u16 kind = btf_kind(t); + + return kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION; +} + +static inline bool btf_is_enum(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_ENUM; +} + +static inline bool btf_is_fwd(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_FWD; +} + +static inline bool btf_is_typedef(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_TYPEDEF; +} + +static inline bool btf_is_volatile(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_VOLATILE; +} + +static inline bool btf_is_const(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_CONST; +} + +static inline bool btf_is_restrict(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_RESTRICT; +} + +static inline bool btf_is_mod(const struct btf_type *t) +{ + __u16 kind = btf_kind(t); + + return kind == BTF_KIND_VOLATILE || + kind == BTF_KIND_CONST || + kind == BTF_KIND_RESTRICT; +} + +static inline bool btf_is_func(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_FUNC; +} + +static inline bool btf_is_func_proto(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_FUNC_PROTO; +} + +static inline bool btf_is_var(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_VAR; +} + +static inline bool btf_is_datasec(const struct btf_type *t) +{ + return btf_kind(t) == BTF_KIND_DATASEC; +} + +static inline __u8 btf_int_encoding(const struct btf_type *t) +{ + return BTF_INT_ENCODING(*(__u32 *)(t + 1)); +} + +static inline __u8 btf_int_offset(const struct btf_type *t) +{ + return BTF_INT_OFFSET(*(__u32 *)(t + 1)); +} + +static inline __u8 btf_int_bits(const struct btf_type *t) +{ + return BTF_INT_BITS(*(__u32 *)(t + 1)); +} + +static inline struct btf_array *btf_array(const struct btf_type *t) +{ + return (struct btf_array *)(t + 1); +} + +static inline struct btf_enum *btf_enum(const struct btf_type *t) +{ + return (struct btf_enum *)(t + 1); +} + +static inline struct btf_member *btf_members(const struct btf_type *t) +{ + return (struct btf_member *)(t + 1); +} + +/* Get bit offset of a member with specified index. */ +static inline __u32 btf_member_bit_offset(const struct btf_type *t, + __u32 member_idx) +{ + const struct btf_member *m = btf_members(t) + member_idx; + bool kflag = btf_kflag(t); + + return kflag ? BTF_MEMBER_BIT_OFFSET(m->offset) : m->offset; +} +/* + * Get bitfield size of a member, assuming t is BTF_KIND_STRUCT or + * BTF_KIND_UNION. If member is not a bitfield, zero is returned. + */ +static inline __u32 btf_member_bitfield_size(const struct btf_type *t, + __u32 member_idx) +{ + const struct btf_member *m = btf_members(t) + member_idx; + bool kflag = btf_kflag(t); + + return kflag ? BTF_MEMBER_BITFIELD_SIZE(m->offset) : 0; +} + +static inline struct btf_param *btf_params(const struct btf_type *t) +{ + return (struct btf_param *)(t + 1); +} + +static inline struct btf_var *btf_var(const struct btf_type *t) +{ + return (struct btf_var *)(t + 1); +} + +static inline struct btf_var_secinfo * +btf_var_secinfos(const struct btf_type *t) +{ + return (struct btf_var_secinfo *)(t + 1); +} + #ifdef __cplusplus } /* extern "C" */ #endif -- GitLab From b03bc6853c0e0c97da842434e8056f1b9d9a1f4a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:49 -0700 Subject: [PATCH 2204/7155] libbpf: convert libbpf code to use new btf helpers Simplify code by relying on newly added BTF helper functions. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/btf.c | 181 ++++++++++++++++++--------------------- tools/lib/bpf/btf_dump.c | 138 ++++++++++------------------- tools/lib/bpf/libbpf.c | 60 +++++++------ 3 files changed, 158 insertions(+), 221 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 467224feb43b..1cd4e5d67158 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -19,13 +19,6 @@ #define BTF_MAX_NR_TYPES 0x7fffffff #define BTF_MAX_STR_OFFSET 0x7fffffff -#define IS_MODIFIER(k) (((k) == BTF_KIND_TYPEDEF) || \ - ((k) == BTF_KIND_VOLATILE) || \ - ((k) == BTF_KIND_CONST) || \ - ((k) == BTF_KIND_RESTRICT)) - -#define IS_VAR(k) ((k) == BTF_KIND_VAR) - static struct btf_type btf_void; struct btf { @@ -192,9 +185,9 @@ static int btf_parse_str_sec(struct btf *btf) static int btf_type_size(struct btf_type *t) { int base_size = sizeof(struct btf_type); - __u16 vlen = BTF_INFO_VLEN(t->info); + __u16 vlen = btf_vlen(t); - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_FWD: case BTF_KIND_CONST: case BTF_KIND_VOLATILE: @@ -219,7 +212,7 @@ static int btf_type_size(struct btf_type *t) case BTF_KIND_DATASEC: return base_size + vlen * sizeof(struct btf_var_secinfo); default: - pr_debug("Unsupported BTF_KIND:%u\n", BTF_INFO_KIND(t->info)); + pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t)); return -EINVAL; } } @@ -263,7 +256,7 @@ const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id) static bool btf_type_is_void(const struct btf_type *t) { - return t == &btf_void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD; + return t == &btf_void || btf_is_fwd(t); } static bool btf_type_is_void_or_null(const struct btf_type *t) @@ -284,7 +277,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id) t = btf__type_by_id(btf, type_id); for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); i++) { - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_INT: case BTF_KIND_STRUCT: case BTF_KIND_UNION: @@ -303,7 +296,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id) type_id = t->type; break; case BTF_KIND_ARRAY: - array = (const struct btf_array *)(t + 1); + array = btf_array(t); if (nelems && array->nelems > UINT32_MAX / nelems) return -E2BIG; nelems *= array->nelems; @@ -334,8 +327,7 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id) t = btf__type_by_id(btf, type_id); while (depth < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t) && - (IS_MODIFIER(BTF_INFO_KIND(t->info)) || - IS_VAR(BTF_INFO_KIND(t->info)))) { + (btf_is_mod(t) || btf_is_typedef(t) || btf_is_var(t))) { type_id = t->type; t = btf__type_by_id(btf, type_id); depth++; @@ -554,11 +546,11 @@ static int compare_vsi_off(const void *_a, const void *_b) static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf, struct btf_type *t) { - __u32 size = 0, off = 0, i, vars = BTF_INFO_VLEN(t->info); + __u32 size = 0, off = 0, i, vars = btf_vlen(t); const char *name = btf__name_by_offset(btf, t->name_off); const struct btf_type *t_var; struct btf_var_secinfo *vsi; - struct btf_var *var; + const struct btf_var *var; int ret; if (!name) { @@ -574,12 +566,11 @@ static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf, t->size = size; - for (i = 0, vsi = (struct btf_var_secinfo *)(t + 1); - i < vars; i++, vsi++) { + for (i = 0, vsi = btf_var_secinfos(t); i < vars; i++, vsi++) { t_var = btf__type_by_id(btf, vsi->type); - var = (struct btf_var *)(t_var + 1); + var = btf_var(t_var); - if (BTF_INFO_KIND(t_var->info) != BTF_KIND_VAR) { + if (!btf_is_var(t_var)) { pr_debug("Non-VAR type seen in section %s\n", name); return -EINVAL; } @@ -595,7 +586,8 @@ static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf, ret = bpf_object__variable_offset(obj, name, &off); if (ret) { - pr_debug("No offset found in symbol table for VAR %s\n", name); + pr_debug("No offset found in symbol table for VAR %s\n", + name); return -ENOENT; } @@ -619,7 +611,7 @@ int btf__finalize_data(struct bpf_object *obj, struct btf *btf) * is section size and global variable offset. We use * the info from the ELF itself for this purpose. */ - if (BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC) { + if (btf_is_datasec(t)) { err = btf_fixup_datasec(obj, btf, t); if (err) break; @@ -774,14 +766,13 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, return -EINVAL; } - if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT || - BTF_INFO_VLEN(container_type->info) < 2) { + if (!btf_is_struct(container_type) || btf_vlen(container_type) < 2) { pr_warning("map:%s container_name:%s is an invalid container struct\n", map_name, container_name); return -EINVAL; } - key = (struct btf_member *)(container_type + 1); + key = btf_members(container_type); value = key + 1; key_size = btf__resolve_size(btf, key->type); @@ -1440,10 +1431,9 @@ static struct btf_dedup *btf_dedup_new(struct btf *btf, struct btf_ext *btf_ext, d->map[0] = 0; for (i = 1; i <= btf->nr_types; i++) { struct btf_type *t = d->btf->types[i]; - __u16 kind = BTF_INFO_KIND(t->info); /* VAR and DATASEC are never deduped and are self-canonical */ - if (kind == BTF_KIND_VAR || kind == BTF_KIND_DATASEC) + if (btf_is_var(t) || btf_is_datasec(t)) d->map[i] = i; else d->map[i] = BTF_UNPROCESSED_ID; @@ -1484,11 +1474,11 @@ static int btf_for_each_str_off(struct btf_dedup *d, str_off_fn_t fn, void *ctx) if (r) return r; - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_STRUCT: case BTF_KIND_UNION: { - struct btf_member *m = (struct btf_member *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_member *m = btf_members(t); + __u16 vlen = btf_vlen(t); for (j = 0; j < vlen; j++) { r = fn(&m->name_off, ctx); @@ -1499,8 +1489,8 @@ static int btf_for_each_str_off(struct btf_dedup *d, str_off_fn_t fn, void *ctx) break; } case BTF_KIND_ENUM: { - struct btf_enum *m = (struct btf_enum *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_enum *m = btf_enum(t); + __u16 vlen = btf_vlen(t); for (j = 0; j < vlen; j++) { r = fn(&m->name_off, ctx); @@ -1511,8 +1501,8 @@ static int btf_for_each_str_off(struct btf_dedup *d, str_off_fn_t fn, void *ctx) break; } case BTF_KIND_FUNC_PROTO: { - struct btf_param *m = (struct btf_param *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_param *m = btf_params(t); + __u16 vlen = btf_vlen(t); for (j = 0; j < vlen; j++) { r = fn(&m->name_off, ctx); @@ -1801,16 +1791,16 @@ static long btf_hash_enum(struct btf_type *t) /* Check structural equality of two ENUMs. */ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2) { - struct btf_enum *m1, *m2; + const struct btf_enum *m1, *m2; __u16 vlen; int i; if (!btf_equal_common(t1, t2)) return false; - vlen = BTF_INFO_VLEN(t1->info); - m1 = (struct btf_enum *)(t1 + 1); - m2 = (struct btf_enum *)(t2 + 1); + vlen = btf_vlen(t1); + m1 = btf_enum(t1); + m2 = btf_enum(t2); for (i = 0; i < vlen; i++) { if (m1->name_off != m2->name_off || m1->val != m2->val) return false; @@ -1822,8 +1812,7 @@ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2) static inline bool btf_is_enum_fwd(struct btf_type *t) { - return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM && - BTF_INFO_VLEN(t->info) == 0; + return btf_is_enum(t) && btf_vlen(t) == 0; } static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2) @@ -1843,8 +1832,8 @@ static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2) */ static long btf_hash_struct(struct btf_type *t) { - struct btf_member *member = (struct btf_member *)(t + 1); - __u32 vlen = BTF_INFO_VLEN(t->info); + const struct btf_member *member = btf_members(t); + __u32 vlen = btf_vlen(t); long h = btf_hash_common(t); int i; @@ -1864,16 +1853,16 @@ static long btf_hash_struct(struct btf_type *t) */ static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2) { - struct btf_member *m1, *m2; + const struct btf_member *m1, *m2; __u16 vlen; int i; if (!btf_equal_common(t1, t2)) return false; - vlen = BTF_INFO_VLEN(t1->info); - m1 = (struct btf_member *)(t1 + 1); - m2 = (struct btf_member *)(t2 + 1); + vlen = btf_vlen(t1); + m1 = btf_members(t1); + m2 = btf_members(t2); for (i = 0; i < vlen; i++) { if (m1->name_off != m2->name_off || m1->offset != m2->offset) return false; @@ -1890,7 +1879,7 @@ static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2) */ static long btf_hash_array(struct btf_type *t) { - struct btf_array *info = (struct btf_array *)(t + 1); + const struct btf_array *info = btf_array(t); long h = btf_hash_common(t); h = hash_combine(h, info->type); @@ -1908,13 +1897,13 @@ static long btf_hash_array(struct btf_type *t) */ static bool btf_equal_array(struct btf_type *t1, struct btf_type *t2) { - struct btf_array *info1, *info2; + const struct btf_array *info1, *info2; if (!btf_equal_common(t1, t2)) return false; - info1 = (struct btf_array *)(t1 + 1); - info2 = (struct btf_array *)(t2 + 1); + info1 = btf_array(t1); + info2 = btf_array(t2); return info1->type == info2->type && info1->index_type == info2->index_type && info1->nelems == info2->nelems; @@ -1927,14 +1916,10 @@ static bool btf_equal_array(struct btf_type *t1, struct btf_type *t2) */ static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2) { - struct btf_array *info1, *info2; - if (!btf_equal_common(t1, t2)) return false; - info1 = (struct btf_array *)(t1 + 1); - info2 = (struct btf_array *)(t2 + 1); - return info1->nelems == info2->nelems; + return btf_array(t1)->nelems == btf_array(t2)->nelems; } /* @@ -1944,8 +1929,8 @@ static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2) */ static long btf_hash_fnproto(struct btf_type *t) { - struct btf_param *member = (struct btf_param *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + const struct btf_param *member = btf_params(t); + __u16 vlen = btf_vlen(t); long h = btf_hash_common(t); int i; @@ -1966,16 +1951,16 @@ static long btf_hash_fnproto(struct btf_type *t) */ static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2) { - struct btf_param *m1, *m2; + const struct btf_param *m1, *m2; __u16 vlen; int i; if (!btf_equal_common(t1, t2)) return false; - vlen = BTF_INFO_VLEN(t1->info); - m1 = (struct btf_param *)(t1 + 1); - m2 = (struct btf_param *)(t2 + 1); + vlen = btf_vlen(t1); + m1 = btf_params(t1); + m2 = btf_params(t2); for (i = 0; i < vlen; i++) { if (m1->name_off != m2->name_off || m1->type != m2->type) return false; @@ -1992,7 +1977,7 @@ static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2) */ static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2) { - struct btf_param *m1, *m2; + const struct btf_param *m1, *m2; __u16 vlen; int i; @@ -2000,9 +1985,9 @@ static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2) if (t1->name_off != t2->name_off || t1->info != t2->info) return false; - vlen = BTF_INFO_VLEN(t1->info); - m1 = (struct btf_param *)(t1 + 1); - m2 = (struct btf_param *)(t2 + 1); + vlen = btf_vlen(t1); + m1 = btf_params(t1); + m2 = btf_params(t2); for (i = 0; i < vlen; i++) { if (m1->name_off != m2->name_off) return false; @@ -2028,7 +2013,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id) __u32 cand_id; long h; - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_CONST: case BTF_KIND_VOLATILE: case BTF_KIND_RESTRICT: @@ -2141,13 +2126,13 @@ static uint32_t resolve_fwd_id(struct btf_dedup *d, uint32_t type_id) { __u32 orig_type_id = type_id; - if (BTF_INFO_KIND(d->btf->types[type_id]->info) != BTF_KIND_FWD) + if (!btf_is_fwd(d->btf->types[type_id])) return type_id; while (is_type_mapped(d, type_id) && d->map[type_id] != type_id) type_id = d->map[type_id]; - if (BTF_INFO_KIND(d->btf->types[type_id]->info) != BTF_KIND_FWD) + if (!btf_is_fwd(d->btf->types[type_id])) return type_id; return orig_type_id; @@ -2156,7 +2141,7 @@ static uint32_t resolve_fwd_id(struct btf_dedup *d, uint32_t type_id) static inline __u16 btf_fwd_kind(struct btf_type *t) { - return BTF_INFO_KFLAG(t->info) ? BTF_KIND_UNION : BTF_KIND_STRUCT; + return btf_kflag(t) ? BTF_KIND_UNION : BTF_KIND_STRUCT; } /* @@ -2277,8 +2262,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, cand_type = d->btf->types[cand_id]; canon_type = d->btf->types[canon_id]; - cand_kind = BTF_INFO_KIND(cand_type->info); - canon_kind = BTF_INFO_KIND(canon_type->info); + cand_kind = btf_kind(cand_type); + canon_kind = btf_kind(canon_type); if (cand_type->name_off != canon_type->name_off) return 0; @@ -2327,12 +2312,12 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, return btf_dedup_is_equiv(d, cand_type->type, canon_type->type); case BTF_KIND_ARRAY: { - struct btf_array *cand_arr, *canon_arr; + const struct btf_array *cand_arr, *canon_arr; if (!btf_compat_array(cand_type, canon_type)) return 0; - cand_arr = (struct btf_array *)(cand_type + 1); - canon_arr = (struct btf_array *)(canon_type + 1); + cand_arr = btf_array(cand_type); + canon_arr = btf_array(canon_type); eq = btf_dedup_is_equiv(d, cand_arr->index_type, canon_arr->index_type); if (eq <= 0) @@ -2342,14 +2327,14 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, case BTF_KIND_STRUCT: case BTF_KIND_UNION: { - struct btf_member *cand_m, *canon_m; + const struct btf_member *cand_m, *canon_m; __u16 vlen; if (!btf_shallow_equal_struct(cand_type, canon_type)) return 0; - vlen = BTF_INFO_VLEN(cand_type->info); - cand_m = (struct btf_member *)(cand_type + 1); - canon_m = (struct btf_member *)(canon_type + 1); + vlen = btf_vlen(cand_type); + cand_m = btf_members(cand_type); + canon_m = btf_members(canon_type); for (i = 0; i < vlen; i++) { eq = btf_dedup_is_equiv(d, cand_m->type, canon_m->type); if (eq <= 0) @@ -2362,7 +2347,7 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, } case BTF_KIND_FUNC_PROTO: { - struct btf_param *cand_p, *canon_p; + const struct btf_param *cand_p, *canon_p; __u16 vlen; if (!btf_compat_fnproto(cand_type, canon_type)) @@ -2370,9 +2355,9 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, eq = btf_dedup_is_equiv(d, cand_type->type, canon_type->type); if (eq <= 0) return eq; - vlen = BTF_INFO_VLEN(cand_type->info); - cand_p = (struct btf_param *)(cand_type + 1); - canon_p = (struct btf_param *)(canon_type + 1); + vlen = btf_vlen(cand_type); + cand_p = btf_params(cand_type); + canon_p = btf_params(canon_type); for (i = 0; i < vlen; i++) { eq = btf_dedup_is_equiv(d, cand_p->type, canon_p->type); if (eq <= 0) @@ -2427,8 +2412,8 @@ static void btf_dedup_merge_hypot_map(struct btf_dedup *d) targ_type_id = d->hypot_map[cand_type_id]; t_id = resolve_type_id(d, targ_type_id); c_id = resolve_type_id(d, cand_type_id); - t_kind = BTF_INFO_KIND(d->btf->types[t_id]->info); - c_kind = BTF_INFO_KIND(d->btf->types[c_id]->info); + t_kind = btf_kind(d->btf->types[t_id]); + c_kind = btf_kind(d->btf->types[c_id]); /* * Resolve FWD into STRUCT/UNION. * It's ok to resolve FWD into STRUCT/UNION that's not yet @@ -2497,7 +2482,7 @@ static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id) return 0; t = d->btf->types[type_id]; - kind = BTF_INFO_KIND(t->info); + kind = btf_kind(t); if (kind != BTF_KIND_STRUCT && kind != BTF_KIND_UNION) return 0; @@ -2592,7 +2577,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id) t = d->btf->types[type_id]; d->map[type_id] = BTF_IN_PROGRESS_ID; - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_CONST: case BTF_KIND_VOLATILE: case BTF_KIND_RESTRICT: @@ -2616,7 +2601,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id) break; case BTF_KIND_ARRAY: { - struct btf_array *info = (struct btf_array *)(t + 1); + struct btf_array *info = btf_array(t); ref_type_id = btf_dedup_ref_type(d, info->type); if (ref_type_id < 0) @@ -2650,8 +2635,8 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id) return ref_type_id; t->type = ref_type_id; - vlen = BTF_INFO_VLEN(t->info); - param = (struct btf_param *)(t + 1); + vlen = btf_vlen(t); + param = btf_params(t); for (i = 0; i < vlen; i++) { ref_type_id = btf_dedup_ref_type(d, param->type); if (ref_type_id < 0) @@ -2791,7 +2776,7 @@ static int btf_dedup_remap_type(struct btf_dedup *d, __u32 type_id) struct btf_type *t = d->btf->types[type_id]; int i, r; - switch (BTF_INFO_KIND(t->info)) { + switch (btf_kind(t)) { case BTF_KIND_INT: case BTF_KIND_ENUM: break; @@ -2811,7 +2796,7 @@ static int btf_dedup_remap_type(struct btf_dedup *d, __u32 type_id) break; case BTF_KIND_ARRAY: { - struct btf_array *arr_info = (struct btf_array *)(t + 1); + struct btf_array *arr_info = btf_array(t); r = btf_dedup_remap_type_id(d, arr_info->type); if (r < 0) @@ -2826,8 +2811,8 @@ static int btf_dedup_remap_type(struct btf_dedup *d, __u32 type_id) case BTF_KIND_STRUCT: case BTF_KIND_UNION: { - struct btf_member *member = (struct btf_member *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_member *member = btf_members(t); + __u16 vlen = btf_vlen(t); for (i = 0; i < vlen; i++) { r = btf_dedup_remap_type_id(d, member->type); @@ -2840,8 +2825,8 @@ static int btf_dedup_remap_type(struct btf_dedup *d, __u32 type_id) } case BTF_KIND_FUNC_PROTO: { - struct btf_param *param = (struct btf_param *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_param *param = btf_params(t); + __u16 vlen = btf_vlen(t); r = btf_dedup_remap_type_id(d, t->type); if (r < 0) @@ -2859,8 +2844,8 @@ static int btf_dedup_remap_type(struct btf_dedup *d, __u32 type_id) } case BTF_KIND_DATASEC: { - struct btf_var_secinfo *var = (struct btf_var_secinfo *)(t + 1); - __u16 vlen = BTF_INFO_VLEN(t->info); + struct btf_var_secinfo *var = btf_var_secinfos(t); + __u16 vlen = btf_vlen(t); for (i = 0; i < vlen; i++) { r = btf_dedup_remap_type_id(d, var->type); diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index 7065bb5b2752..715967762312 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -100,21 +100,6 @@ static bool str_equal_fn(const void *a, const void *b, void *ctx) return strcmp(a, b) == 0; } -static __u16 btf_kind_of(const struct btf_type *t) -{ - return BTF_INFO_KIND(t->info); -} - -static __u16 btf_vlen_of(const struct btf_type *t) -{ - return BTF_INFO_VLEN(t->info); -} - -static bool btf_kflag_of(const struct btf_type *t) -{ - return BTF_INFO_KFLAG(t->info); -} - static const char *btf_name_of(const struct btf_dump *d, __u32 name_off) { return btf__name_by_offset(d->btf, name_off); @@ -349,7 +334,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) */ struct btf_dump_type_aux_state *tstate = &d->type_states[id]; const struct btf_type *t; - __u16 kind, vlen; + __u16 vlen; int err, i; /* return true, letting typedefs know that it's ok to be emitted */ @@ -357,18 +342,16 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) return 1; t = btf__type_by_id(d->btf, id); - kind = btf_kind_of(t); if (tstate->order_state == ORDERING) { /* type loop, but resolvable through fwd declaration */ - if ((kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION) && - through_ptr && t->name_off != 0) + if (btf_is_composite(t) && through_ptr && t->name_off != 0) return 0; pr_warning("unsatisfiable type cycle, id:[%u]\n", id); return -ELOOP; } - switch (kind) { + switch (btf_kind(t)) { case BTF_KIND_INT: tstate->order_state = ORDERED; return 0; @@ -378,14 +361,12 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) tstate->order_state = ORDERED; return err; - case BTF_KIND_ARRAY: { - const struct btf_array *a = (void *)(t + 1); + case BTF_KIND_ARRAY: + return btf_dump_order_type(d, btf_array(t)->type, through_ptr); - return btf_dump_order_type(d, a->type, through_ptr); - } case BTF_KIND_STRUCT: case BTF_KIND_UNION: { - const struct btf_member *m = (void *)(t + 1); + const struct btf_member *m = btf_members(t); /* * struct/union is part of strong link, only if it's embedded * (so no ptr in a path) or it's anonymous (so has to be @@ -396,7 +377,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) tstate->order_state = ORDERING; - vlen = btf_vlen_of(t); + vlen = btf_vlen(t); for (i = 0; i < vlen; i++, m++) { err = btf_dump_order_type(d, m->type, false); if (err < 0) @@ -447,7 +428,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) return btf_dump_order_type(d, t->type, through_ptr); case BTF_KIND_FUNC_PROTO: { - const struct btf_param *p = (void *)(t + 1); + const struct btf_param *p = btf_params(t); bool is_strong; err = btf_dump_order_type(d, t->type, through_ptr); @@ -455,7 +436,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) return err; is_strong = err > 0; - vlen = btf_vlen_of(t); + vlen = btf_vlen(t); for (i = 0; i < vlen; i++, p++) { err = btf_dump_order_type(d, p->type, through_ptr); if (err < 0) @@ -553,7 +534,7 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) return; t = btf__type_by_id(d->btf, id); - kind = btf_kind_of(t); + kind = btf_kind(t); if (top_level_def && t->name_off == 0) { pr_warning("unexpected nameless definition, id:[%u]\n", id); @@ -618,12 +599,9 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) case BTF_KIND_RESTRICT: btf_dump_emit_type(d, t->type, cont_id); break; - case BTF_KIND_ARRAY: { - const struct btf_array *a = (void *)(t + 1); - - btf_dump_emit_type(d, a->type, cont_id); + case BTF_KIND_ARRAY: + btf_dump_emit_type(d, btf_array(t)->type, cont_id); break; - } case BTF_KIND_FWD: btf_dump_emit_fwd_def(d, id, t); btf_dump_printf(d, ";\n\n"); @@ -656,8 +634,8 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) * applicable */ if (top_level_def || t->name_off == 0) { - const struct btf_member *m = (void *)(t + 1); - __u16 vlen = btf_vlen_of(t); + const struct btf_member *m = btf_members(t); + __u16 vlen = btf_vlen(t); int i, new_cont_id; new_cont_id = t->name_off == 0 ? cont_id : id; @@ -678,8 +656,8 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) } break; case BTF_KIND_FUNC_PROTO: { - const struct btf_param *p = (void *)(t + 1); - __u16 vlen = btf_vlen_of(t); + const struct btf_param *p = btf_params(t); + __u16 vlen = btf_vlen(t); int i; btf_dump_emit_type(d, t->type, cont_id); @@ -696,7 +674,7 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) static int btf_align_of(const struct btf *btf, __u32 id) { const struct btf_type *t = btf__type_by_id(btf, id); - __u16 kind = btf_kind_of(t); + __u16 kind = btf_kind(t); switch (kind) { case BTF_KIND_INT: @@ -709,15 +687,12 @@ static int btf_align_of(const struct btf *btf, __u32 id) case BTF_KIND_CONST: case BTF_KIND_RESTRICT: return btf_align_of(btf, t->type); - case BTF_KIND_ARRAY: { - const struct btf_array *a = (void *)(t + 1); - - return btf_align_of(btf, a->type); - } + case BTF_KIND_ARRAY: + return btf_align_of(btf, btf_array(t)->type); case BTF_KIND_STRUCT: case BTF_KIND_UNION: { - const struct btf_member *m = (void *)(t + 1); - __u16 vlen = btf_vlen_of(t); + const struct btf_member *m = btf_members(t); + __u16 vlen = btf_vlen(t); int i, align = 1; for (i = 0; i < vlen; i++, m++) @@ -726,7 +701,7 @@ static int btf_align_of(const struct btf *btf, __u32 id) return align; } default: - pr_warning("unsupported BTF_KIND:%u\n", btf_kind_of(t)); + pr_warning("unsupported BTF_KIND:%u\n", btf_kind(t)); return 1; } } @@ -737,20 +712,18 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id, const struct btf_member *m; int align, i, bit_sz; __u16 vlen; - bool kflag; align = btf_align_of(btf, id); /* size of a non-packed struct has to be a multiple of its alignment*/ if (t->size % align) return true; - m = (void *)(t + 1); - kflag = btf_kflag_of(t); - vlen = btf_vlen_of(t); + m = btf_members(t); + vlen = btf_vlen(t); /* all non-bitfield fields have to be naturally aligned */ for (i = 0; i < vlen; i++, m++) { align = btf_align_of(btf, m->type); - bit_sz = kflag ? BTF_MEMBER_BITFIELD_SIZE(m->offset) : 0; + bit_sz = btf_member_bitfield_size(t, i); if (bit_sz == 0 && m->offset % (8 * align) != 0) return true; } @@ -807,7 +780,7 @@ static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id, const struct btf_type *t) { btf_dump_printf(d, "%s %s", - btf_kind_of(t) == BTF_KIND_STRUCT ? "struct" : "union", + btf_is_struct(t) ? "struct" : "union", btf_dump_type_name(d, id)); } @@ -816,12 +789,11 @@ static void btf_dump_emit_struct_def(struct btf_dump *d, const struct btf_type *t, int lvl) { - const struct btf_member *m = (void *)(t + 1); - bool kflag = btf_kflag_of(t), is_struct; + const struct btf_member *m = btf_members(t); + bool is_struct = btf_is_struct(t); int align, i, packed, off = 0; - __u16 vlen = btf_vlen_of(t); + __u16 vlen = btf_vlen(t); - is_struct = btf_kind_of(t) == BTF_KIND_STRUCT; packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0; align = packed ? 1 : btf_align_of(d->btf, id); @@ -835,8 +807,8 @@ static void btf_dump_emit_struct_def(struct btf_dump *d, int m_off, m_sz; fname = btf_name_of(d, m->name_off); - m_sz = kflag ? BTF_MEMBER_BITFIELD_SIZE(m->offset) : 0; - m_off = kflag ? BTF_MEMBER_BIT_OFFSET(m->offset) : m->offset; + m_sz = btf_member_bitfield_size(t, i); + m_off = btf_member_bit_offset(t, i); align = packed ? 1 : btf_align_of(d->btf, m->type); btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1); @@ -870,8 +842,8 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id, const struct btf_type *t, int lvl) { - const struct btf_enum *v = (void *)(t+1); - __u16 vlen = btf_vlen_of(t); + const struct btf_enum *v = btf_enum(t); + __u16 vlen = btf_vlen(t); const char *name; size_t dup_cnt; int i; @@ -905,7 +877,7 @@ static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id, { const char *name = btf_dump_type_name(d, id); - if (btf_kflag_of(t)) + if (btf_kflag(t)) btf_dump_printf(d, "union %s", name); else btf_dump_printf(d, "struct %s", name); @@ -987,7 +959,6 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id, struct id_stack decl_stack; const struct btf_type *t; int err, stack_start; - __u16 kind; stack_start = d->decl_stack_cnt; for (;;) { @@ -1008,8 +979,7 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id, break; t = btf__type_by_id(d->btf, id); - kind = btf_kind_of(t); - switch (kind) { + switch (btf_kind(t)) { case BTF_KIND_PTR: case BTF_KIND_VOLATILE: case BTF_KIND_CONST: @@ -1017,12 +987,9 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id, case BTF_KIND_FUNC_PROTO: id = t->type; break; - case BTF_KIND_ARRAY: { - const struct btf_array *a = (void *)(t + 1); - - id = a->type; + case BTF_KIND_ARRAY: + id = btf_array(t)->type; break; - } case BTF_KIND_INT: case BTF_KIND_ENUM: case BTF_KIND_FWD: @@ -1032,7 +999,7 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id, goto done; default: pr_warning("unexpected type in decl chain, kind:%u, id:[%u]\n", - kind, id); + btf_kind(t), id); goto done; } } @@ -1070,7 +1037,7 @@ static void btf_dump_emit_mods(struct btf_dump *d, struct id_stack *decl_stack) id = decl_stack->ids[decl_stack->cnt - 1]; t = btf__type_by_id(d->btf, id); - switch (btf_kind_of(t)) { + switch (btf_kind(t)) { case BTF_KIND_VOLATILE: btf_dump_printf(d, "volatile "); break; @@ -1087,20 +1054,6 @@ static void btf_dump_emit_mods(struct btf_dump *d, struct id_stack *decl_stack) } } -static bool btf_is_mod_kind(const struct btf *btf, __u32 id) -{ - const struct btf_type *t = btf__type_by_id(btf, id); - - switch (btf_kind_of(t)) { - case BTF_KIND_VOLATILE: - case BTF_KIND_CONST: - case BTF_KIND_RESTRICT: - return true; - default: - return false; - } -} - static void btf_dump_emit_name(const struct btf_dump *d, const char *name, bool last_was_ptr) { @@ -1139,7 +1092,7 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, } t = btf__type_by_id(d->btf, id); - kind = btf_kind_of(t); + kind = btf_kind(t); switch (kind) { case BTF_KIND_INT: @@ -1185,7 +1138,7 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, btf_dump_printf(d, " restrict"); break; case BTF_KIND_ARRAY: { - const struct btf_array *a = (void *)(t + 1); + const struct btf_array *a = btf_array(t); const struct btf_type *next_t; __u32 next_id; bool multidim; @@ -1201,7 +1154,8 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, */ while (decls->cnt) { next_id = decls->ids[decls->cnt - 1]; - if (btf_is_mod_kind(d->btf, next_id)) + next_t = btf__type_by_id(d->btf, next_id); + if (btf_is_mod(next_t)) decls->cnt--; else break; @@ -1214,7 +1168,7 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, } next_t = btf__type_by_id(d->btf, next_id); - multidim = btf_kind_of(next_t) == BTF_KIND_ARRAY; + multidim = btf_is_array(next_t); /* we need space if we have named non-pointer */ if (fname[0] && !last_was_ptr) btf_dump_printf(d, " "); @@ -1228,8 +1182,8 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, return; } case BTF_KIND_FUNC_PROTO: { - const struct btf_param *p = (void *)(t + 1); - __u16 vlen = btf_vlen_of(t); + const struct btf_param *p = btf_params(t); + __u16 vlen = btf_vlen(t); int i; btf_dump_emit_mods(d, decls); diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index ead915aec349..8fc62b6b1cd6 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -1049,9 +1049,9 @@ static bool get_map_field_int(const char *map_name, const struct btf *btf, const struct btf_array *arr_info; const struct btf_type *arr_t; - if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) { + if (!btf_is_ptr(t)) { pr_warning("map '%s': attr '%s': expected PTR, got %u.\n", - map_name, name, BTF_INFO_KIND(t->info)); + map_name, name, btf_kind(t)); return false; } @@ -1061,12 +1061,12 @@ static bool get_map_field_int(const char *map_name, const struct btf *btf, map_name, name, t->type); return false; } - if (BTF_INFO_KIND(arr_t->info) != BTF_KIND_ARRAY) { + if (!btf_is_array(arr_t)) { pr_warning("map '%s': attr '%s': expected ARRAY, got %u.\n", - map_name, name, BTF_INFO_KIND(arr_t->info)); + map_name, name, btf_kind(arr_t)); return false; } - arr_info = (const void *)(arr_t + 1); + arr_info = btf_array(arr_t); *res = arr_info->nelems; return true; } @@ -1084,11 +1084,11 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, struct bpf_map *map; int vlen, i; - vi = (const struct btf_var_secinfo *)(const void *)(sec + 1) + var_idx; + vi = btf_var_secinfos(sec) + var_idx; var = btf__type_by_id(obj->btf, vi->type); - var_extra = (const void *)(var + 1); + var_extra = btf_var(var); map_name = btf__name_by_offset(obj->btf, var->name_off); - vlen = BTF_INFO_VLEN(var->info); + vlen = btf_vlen(var); if (map_name == NULL || map_name[0] == '\0') { pr_warning("map #%d: empty name.\n", var_idx); @@ -1098,9 +1098,9 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, pr_warning("map '%s' BTF data is corrupted.\n", map_name); return -EINVAL; } - if (BTF_INFO_KIND(var->info) != BTF_KIND_VAR) { + if (!btf_is_var(var)) { pr_warning("map '%s': unexpected var kind %u.\n", - map_name, BTF_INFO_KIND(var->info)); + map_name, btf_kind(var)); return -EINVAL; } if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED && @@ -1111,9 +1111,9 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, } def = skip_mods_and_typedefs(obj->btf, var->type); - if (BTF_INFO_KIND(def->info) != BTF_KIND_STRUCT) { + if (!btf_is_struct(def)) { pr_warning("map '%s': unexpected def kind %u.\n", - map_name, BTF_INFO_KIND(var->info)); + map_name, btf_kind(var)); return -EINVAL; } if (def->size > vi->size) { @@ -1136,8 +1136,8 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, pr_debug("map '%s': at sec_idx %d, offset %zu.\n", map_name, map->sec_idx, map->sec_offset); - vlen = BTF_INFO_VLEN(def->info); - m = (const void *)(def + 1); + vlen = btf_vlen(def); + m = btf_members(def); for (i = 0; i < vlen; i++, m++) { const char *name = btf__name_by_offset(obj->btf, m->name_off); @@ -1187,9 +1187,9 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, map_name, m->type); return -EINVAL; } - if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) { + if (!btf_is_ptr(t)) { pr_warning("map '%s': key spec is not PTR: %u.\n", - map_name, BTF_INFO_KIND(t->info)); + map_name, btf_kind(t)); return -EINVAL; } sz = btf__resolve_size(obj->btf, t->type); @@ -1230,9 +1230,9 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, map_name, m->type); return -EINVAL; } - if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) { + if (!btf_is_ptr(t)) { pr_warning("map '%s': value spec is not PTR: %u.\n", - map_name, BTF_INFO_KIND(t->info)); + map_name, btf_kind(t)); return -EINVAL; } sz = btf__resolve_size(obj->btf, t->type); @@ -1293,7 +1293,7 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict) nr_types = btf__get_nr_types(obj->btf); for (i = 1; i <= nr_types; i++) { t = btf__type_by_id(obj->btf, i); - if (BTF_INFO_KIND(t->info) != BTF_KIND_DATASEC) + if (!btf_is_datasec(t)) continue; name = btf__name_by_offset(obj->btf, t->name_off); if (strcmp(name, MAPS_ELF_SEC) == 0) { @@ -1307,7 +1307,7 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict) return -ENOENT; } - vlen = BTF_INFO_VLEN(sec->info); + vlen = btf_vlen(sec); for (i = 0; i < vlen; i++) { err = bpf_object__init_user_btf_map(obj, sec, i, obj->efile.btf_maps_shndx, @@ -1368,24 +1368,22 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj) struct btf *btf = obj->btf; struct btf_type *t; int i, j, vlen; - __u16 kind; if (!obj->btf || (has_func && has_datasec)) return; for (i = 1; i <= btf__get_nr_types(btf); i++) { t = (struct btf_type *)btf__type_by_id(btf, i); - kind = BTF_INFO_KIND(t->info); - if (!has_datasec && kind == BTF_KIND_VAR) { + if (!has_datasec && btf_is_var(t)) { /* replace VAR with INT */ t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0); t->size = sizeof(int); - *(int *)(t+1) = BTF_INT_ENC(0, 0, 32); - } else if (!has_datasec && kind == BTF_KIND_DATASEC) { + *(int *)(t + 1) = BTF_INT_ENC(0, 0, 32); + } else if (!has_datasec && btf_is_datasec(t)) { /* replace DATASEC with STRUCT */ - struct btf_var_secinfo *v = (void *)(t + 1); - struct btf_member *m = (void *)(t + 1); + const struct btf_var_secinfo *v = btf_var_secinfos(t); + struct btf_member *m = btf_members(t); struct btf_type *vt; char *name; @@ -1396,7 +1394,7 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj) name++; } - vlen = BTF_INFO_VLEN(t->info); + vlen = btf_vlen(t); t->info = BTF_INFO_ENC(BTF_KIND_STRUCT, 0, vlen); for (j = 0; j < vlen; j++, v++, m++) { /* order of field assignments is important */ @@ -1406,12 +1404,12 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj) vt = (void *)btf__type_by_id(btf, v->type); m->name_off = vt->name_off; } - } else if (!has_func && kind == BTF_KIND_FUNC_PROTO) { + } else if (!has_func && btf_is_func_proto(t)) { /* replace FUNC_PROTO with ENUM */ - vlen = BTF_INFO_VLEN(t->info); + vlen = btf_vlen(t); t->info = BTF_INFO_ENC(BTF_KIND_ENUM, 0, vlen); t->size = sizeof(__u32); /* kernel enforced */ - } else if (!has_func && kind == BTF_KIND_FUNC) { + } else if (!has_func && btf_is_func(t)) { /* replace FUNC with TYPEDEF */ t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0); } -- GitLab From 4cedc0dad9b5bf55c4180c833be35e27e5d6cdbb Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:50 -0700 Subject: [PATCH 2205/7155] libbpf: add .BTF.ext offset relocation section loading Add support for BPF CO-RE offset relocations. Add section/record iteration macros for .BTF.ext. These macro are useful for iterating over each .BTF.ext record, either for dumping out contents or later for BPF CO-RE relocation handling. To enable other parts of libbpf to work with .BTF.ext contents, moved a bunch of type definitions into libbpf_internal.h. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/btf.c | 69 ++++++++------------- tools/lib/bpf/btf.h | 4 ++ tools/lib/bpf/libbpf_internal.h | 105 ++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 42 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 1cd4e5d67158..aacb7608f02d 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -35,47 +35,6 @@ struct btf { int fd; }; -struct btf_ext_info { - /* - * info points to the individual info section (e.g. func_info and - * line_info) from the .BTF.ext. It does not include the __u32 rec_size. - */ - void *info; - __u32 rec_size; - __u32 len; -}; - -struct btf_ext { - union { - struct btf_ext_header *hdr; - void *data; - }; - struct btf_ext_info func_info; - struct btf_ext_info line_info; - __u32 data_size; -}; - -struct btf_ext_info_sec { - __u32 sec_name_off; - __u32 num_info; - /* Followed by num_info * record_size number of bytes */ - __u8 data[0]; -}; - -/* The minimum bpf_func_info checked by the loader */ -struct bpf_func_info_min { - __u32 insn_off; - __u32 type_id; -}; - -/* The minimum bpf_line_info checked by the loader */ -struct bpf_line_info_min { - __u32 insn_off; - __u32 file_name_off; - __u32 line_off; - __u32 line_col; -}; - static inline __u64 ptr_to_u64(const void *ptr) { return (__u64) (unsigned long) ptr; @@ -822,6 +781,9 @@ static int btf_ext_setup_info(struct btf_ext *btf_ext, /* The start of the info sec (including the __u32 record_size). */ void *info; + if (ext_sec->len == 0) + return 0; + if (ext_sec->off & 0x03) { pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n", ext_sec->desc); @@ -925,11 +887,24 @@ static int btf_ext_setup_line_info(struct btf_ext *btf_ext) return btf_ext_setup_info(btf_ext, ¶m); } +static int btf_ext_setup_offset_reloc(struct btf_ext *btf_ext) +{ + struct btf_ext_sec_setup_param param = { + .off = btf_ext->hdr->offset_reloc_off, + .len = btf_ext->hdr->offset_reloc_len, + .min_rec_size = sizeof(struct bpf_offset_reloc), + .ext_info = &btf_ext->offset_reloc_info, + .desc = "offset_reloc", + }; + + return btf_ext_setup_info(btf_ext, ¶m); +} + static int btf_ext_parse_hdr(__u8 *data, __u32 data_size) { const struct btf_ext_header *hdr = (struct btf_ext_header *)data; - if (data_size < offsetof(struct btf_ext_header, func_info_off) || + if (data_size < offsetofend(struct btf_ext_header, hdr_len) || data_size < hdr->hdr_len) { pr_debug("BTF.ext header not found"); return -EINVAL; @@ -987,6 +962,9 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) } memcpy(btf_ext->data, data, size); + if (btf_ext->hdr->hdr_len < + offsetofend(struct btf_ext_header, line_info_len)) + goto done; err = btf_ext_setup_func_info(btf_ext); if (err) goto done; @@ -995,6 +973,13 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) if (err) goto done; + if (btf_ext->hdr->hdr_len < + offsetofend(struct btf_ext_header, offset_reloc_len)) + goto done; + err = btf_ext_setup_offset_reloc(btf_ext); + if (err) + goto done; + done: if (err) { btf_ext__free(btf_ext); diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 2604dc099855..9cb44b4fbf60 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -58,6 +58,10 @@ struct btf_ext_header { __u32 func_info_len; __u32 line_info_off; __u32 line_info_len; + + /* optional part of .BTF.ext header */ + __u32 offset_reloc_off; + __u32 offset_reloc_len; }; LIBBPF_API void btf__free(struct btf *btf); diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 2ac29bd36226..2e83a34f8c79 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -29,6 +29,10 @@ #ifndef max # define max(x, y) ((x) < (y) ? (y) : (x)) #endif +#ifndef offsetofend +# define offsetofend(TYPE, FIELD) \ + (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) +#endif extern void libbpf_print(enum libbpf_print_level level, const char *format, ...) @@ -46,4 +50,105 @@ do { \ int libbpf__load_raw_btf(const char *raw_types, size_t types_len, const char *str_sec, size_t str_len); +struct btf_ext_info { + /* + * info points to the individual info section (e.g. func_info and + * line_info) from the .BTF.ext. It does not include the __u32 rec_size. + */ + void *info; + __u32 rec_size; + __u32 len; +}; + +#define for_each_btf_ext_sec(seg, sec) \ + for (sec = (seg)->info; \ + (void *)sec < (seg)->info + (seg)->len; \ + sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \ + (seg)->rec_size * sec->num_info) + +#define for_each_btf_ext_rec(seg, sec, i, rec) \ + for (i = 0, rec = (void *)&(sec)->data; \ + i < (sec)->num_info; \ + i++, rec = (void *)rec + (seg)->rec_size) + +struct btf_ext { + union { + struct btf_ext_header *hdr; + void *data; + }; + struct btf_ext_info func_info; + struct btf_ext_info line_info; + struct btf_ext_info offset_reloc_info; + __u32 data_size; +}; + +struct btf_ext_info_sec { + __u32 sec_name_off; + __u32 num_info; + /* Followed by num_info * record_size number of bytes */ + __u8 data[0]; +}; + +/* The minimum bpf_func_info checked by the loader */ +struct bpf_func_info_min { + __u32 insn_off; + __u32 type_id; +}; + +/* The minimum bpf_line_info checked by the loader */ +struct bpf_line_info_min { + __u32 insn_off; + __u32 file_name_off; + __u32 line_off; + __u32 line_col; +}; + +/* The minimum bpf_offset_reloc checked by the loader + * + * Offset relocation captures the following data: + * - insn_off - instruction offset (in bytes) within a BPF program that needs + * its insn->imm field to be relocated with actual offset; + * - type_id - BTF type ID of the "root" (containing) entity of a relocatable + * offset; + * - access_str_off - offset into corresponding .BTF string section. String + * itself encodes an accessed field using a sequence of field and array + * indicies, separated by colon (:). It's conceptually very close to LLVM's + * getelementptr ([0]) instruction's arguments for identifying offset to + * a field. + * + * Example to provide a better feel. + * + * struct sample { + * int a; + * struct { + * int b[10]; + * }; + * }; + * + * struct sample *s = ...; + * int x = &s->a; // encoded as "0:0" (a is field #0) + * int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1, + * // b is field #0 inside anon struct, accessing elem #5) + * int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array) + * + * type_id for all relocs in this example will capture BTF type id of + * `struct sample`. + * + * Such relocation is emitted when using __builtin_preserve_access_index() + * Clang built-in, passing expression that captures field address, e.g.: + * + * bpf_probe_read(&dst, sizeof(dst), + * __builtin_preserve_access_index(&src->a.b.c)); + * + * In this case Clang will emit offset relocation recording necessary data to + * be able to find offset of embedded `a.b.c` field within `src` struct. + * + * [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction + */ +struct bpf_offset_reloc { + __u32 insn_off; + __u32 type_id; + __u32 access_str_off; +}; + #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ -- GitLab From ddc7c3042614e273044f698d2beab25cc3842d45 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:51 -0700 Subject: [PATCH 2206/7155] libbpf: implement BPF CO-RE offset relocation algorithm This patch implements the core logic for BPF CO-RE offsets relocations. Every instruction that needs to be relocated has corresponding bpf_offset_reloc as part of BTF.ext. Relocations are performed by trying to match recorded "local" relocation spec against potentially many compatible "target" types, creating corresponding spec. Details of the algorithm are noted in corresponding comments in the code. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf.c | 881 ++++++++++++++++++++++++++++++++++++++++- tools/lib/bpf/libbpf.h | 1 + 2 files changed, 864 insertions(+), 18 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8fc62b6b1cd6..3abf2dd1b3b5 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include "btf.h" #include "str_error.h" #include "libbpf_internal.h" +#include "hashmap.h" #ifndef EM_BPF #define EM_BPF 247 @@ -1015,23 +1017,21 @@ static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict) return 0; } -static const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, - __u32 id) +static const struct btf_type * +skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id) { const struct btf_type *t = btf__type_by_id(btf, id); - while (true) { - switch (BTF_INFO_KIND(t->info)) { - case BTF_KIND_VOLATILE: - case BTF_KIND_CONST: - case BTF_KIND_RESTRICT: - case BTF_KIND_TYPEDEF: - t = btf__type_by_id(btf, t->type); - break; - default: - return t; - } + if (res_id) + *res_id = id; + + while (btf_is_mod(t) || btf_is_typedef(t)) { + if (res_id) + *res_id = t->type; + t = btf__type_by_id(btf, t->type); } + + return t; } /* @@ -1044,7 +1044,7 @@ static const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, static bool get_map_field_int(const char *map_name, const struct btf *btf, const struct btf_type *def, const struct btf_member *m, __u32 *res) { - const struct btf_type *t = skip_mods_and_typedefs(btf, m->type); + const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL); const char *name = btf__name_by_offset(btf, m->name_off); const struct btf_array *arr_info; const struct btf_type *arr_t; @@ -1110,7 +1110,7 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, return -EOPNOTSUPP; } - def = skip_mods_and_typedefs(obj->btf, var->type); + def = skip_mods_and_typedefs(obj->btf, var->type, NULL); if (!btf_is_struct(def)) { pr_warning("map '%s': unexpected def kind %u.\n", map_name, btf_kind(var)); @@ -2290,6 +2290,844 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj, return 0; } +#define BPF_CORE_SPEC_MAX_LEN 64 + +/* represents BPF CO-RE field or array element accessor */ +struct bpf_core_accessor { + __u32 type_id; /* struct/union type or array element type */ + __u32 idx; /* field index or array index */ + const char *name; /* field name or NULL for array accessor */ +}; + +struct bpf_core_spec { + const struct btf *btf; + /* high-level spec: named fields and array indices only */ + struct bpf_core_accessor spec[BPF_CORE_SPEC_MAX_LEN]; + /* high-level spec length */ + int len; + /* raw, low-level spec: 1-to-1 with accessor spec string */ + int raw_spec[BPF_CORE_SPEC_MAX_LEN]; + /* raw spec length */ + int raw_len; + /* field byte offset represented by spec */ + __u32 offset; +}; + +static bool str_is_empty(const char *s) +{ + return !s || !s[0]; +} + +/* + * Turn bpf_offset_reloc into a low- and high-level spec representation, + * validating correctness along the way, as well as calculating resulting + * field offset (in bytes), specified by accessor string. Low-level spec + * captures every single level of nestedness, including traversing anonymous + * struct/union members. High-level one only captures semantically meaningful + * "turning points": named fields and array indicies. + * E.g., for this case: + * + * struct sample { + * int __unimportant; + * struct { + * int __1; + * int __2; + * int a[7]; + * }; + * }; + * + * struct sample *s = ...; + * + * int x = &s->a[3]; // access string = '0:1:2:3' + * + * Low-level spec has 1:1 mapping with each element of access string (it's + * just a parsed access string representation): [0, 1, 2, 3]. + * + * High-level spec will capture only 3 points: + * - intial zero-index access by pointer (&s->... is the same as &s[0]...); + * - field 'a' access (corresponds to '2' in low-level spec); + * - array element #3 access (corresponds to '3' in low-level spec). + * + */ +static int bpf_core_spec_parse(const struct btf *btf, + __u32 type_id, + const char *spec_str, + struct bpf_core_spec *spec) +{ + int access_idx, parsed_len, i; + const struct btf_type *t; + const char *name; + __u32 id; + __s64 sz; + + if (str_is_empty(spec_str) || *spec_str == ':') + return -EINVAL; + + memset(spec, 0, sizeof(*spec)); + spec->btf = btf; + + /* parse spec_str="0:1:2:3:4" into array raw_spec=[0, 1, 2, 3, 4] */ + while (*spec_str) { + if (*spec_str == ':') + ++spec_str; + if (sscanf(spec_str, "%d%n", &access_idx, &parsed_len) != 1) + return -EINVAL; + if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN) + return -E2BIG; + spec_str += parsed_len; + spec->raw_spec[spec->raw_len++] = access_idx; + } + + if (spec->raw_len == 0) + return -EINVAL; + + /* first spec value is always reloc type array index */ + t = skip_mods_and_typedefs(btf, type_id, &id); + if (!t) + return -EINVAL; + + access_idx = spec->raw_spec[0]; + spec->spec[0].type_id = id; + spec->spec[0].idx = access_idx; + spec->len++; + + sz = btf__resolve_size(btf, id); + if (sz < 0) + return sz; + spec->offset = access_idx * sz; + + for (i = 1; i < spec->raw_len; i++) { + t = skip_mods_and_typedefs(btf, id, &id); + if (!t) + return -EINVAL; + + access_idx = spec->raw_spec[i]; + + if (btf_is_composite(t)) { + const struct btf_member *m; + __u32 offset; + + if (access_idx >= btf_vlen(t)) + return -EINVAL; + if (btf_member_bitfield_size(t, access_idx)) + return -EINVAL; + + offset = btf_member_bit_offset(t, access_idx); + if (offset % 8) + return -EINVAL; + spec->offset += offset / 8; + + m = btf_members(t) + access_idx; + if (m->name_off) { + name = btf__name_by_offset(btf, m->name_off); + if (str_is_empty(name)) + return -EINVAL; + + spec->spec[spec->len].type_id = id; + spec->spec[spec->len].idx = access_idx; + spec->spec[spec->len].name = name; + spec->len++; + } + + id = m->type; + } else if (btf_is_array(t)) { + const struct btf_array *a = btf_array(t); + + t = skip_mods_and_typedefs(btf, a->type, &id); + if (!t || access_idx >= a->nelems) + return -EINVAL; + + spec->spec[spec->len].type_id = id; + spec->spec[spec->len].idx = access_idx; + spec->len++; + + sz = btf__resolve_size(btf, id); + if (sz < 0) + return sz; + spec->offset += access_idx * sz; + } else { + pr_warning("relo for [%u] %s (at idx %d) captures type [%d] of unexpected kind %d\n", + type_id, spec_str, i, id, btf_kind(t)); + return -EINVAL; + } + } + + return 0; +} + +static bool bpf_core_is_flavor_sep(const char *s) +{ + /* check X___Y name pattern, where X and Y are not underscores */ + return s[0] != '_' && /* X */ + s[1] == '_' && s[2] == '_' && s[3] == '_' && /* ___ */ + s[4] != '_'; /* Y */ +} + +/* Given 'some_struct_name___with_flavor' return the length of a name prefix + * before last triple underscore. Struct name part after last triple + * underscore is ignored by BPF CO-RE relocation during relocation matching. + */ +static size_t bpf_core_essential_name_len(const char *name) +{ + size_t n = strlen(name); + int i; + + for (i = n - 5; i >= 0; i--) { + if (bpf_core_is_flavor_sep(name + i)) + return i + 1; + } + return n; +} + +/* dynamically sized list of type IDs */ +struct ids_vec { + __u32 *data; + int len; +}; + +static void bpf_core_free_cands(struct ids_vec *cand_ids) +{ + free(cand_ids->data); + free(cand_ids); +} + +static struct ids_vec *bpf_core_find_cands(const struct btf *local_btf, + __u32 local_type_id, + const struct btf *targ_btf) +{ + size_t local_essent_len, targ_essent_len; + const char *local_name, *targ_name; + const struct btf_type *t; + struct ids_vec *cand_ids; + __u32 *new_ids; + int i, err, n; + + t = btf__type_by_id(local_btf, local_type_id); + if (!t) + return ERR_PTR(-EINVAL); + + local_name = btf__name_by_offset(local_btf, t->name_off); + if (str_is_empty(local_name)) + return ERR_PTR(-EINVAL); + local_essent_len = bpf_core_essential_name_len(local_name); + + cand_ids = calloc(1, sizeof(*cand_ids)); + if (!cand_ids) + return ERR_PTR(-ENOMEM); + + n = btf__get_nr_types(targ_btf); + for (i = 1; i <= n; i++) { + t = btf__type_by_id(targ_btf, i); + targ_name = btf__name_by_offset(targ_btf, t->name_off); + if (str_is_empty(targ_name)) + continue; + + targ_essent_len = bpf_core_essential_name_len(targ_name); + if (targ_essent_len != local_essent_len) + continue; + + if (strncmp(local_name, targ_name, local_essent_len) == 0) { + pr_debug("[%d] %s: found candidate [%d] %s\n", + local_type_id, local_name, i, targ_name); + new_ids = realloc(cand_ids->data, cand_ids->len + 1); + if (!new_ids) { + err = -ENOMEM; + goto err_out; + } + cand_ids->data = new_ids; + cand_ids->data[cand_ids->len++] = i; + } + } + return cand_ids; +err_out: + bpf_core_free_cands(cand_ids); + return ERR_PTR(err); +} + +/* Check two types for compatibility, skipping const/volatile/restrict and + * typedefs, to ensure we are relocating offset to the compatible entities: + * - any two STRUCTs/UNIONs are compatible and can be mixed; + * - any two FWDs are compatible; + * - any two PTRs are always compatible; + * - for ENUMs, check sizes, names are ignored; + * - for INT, size and bitness should match, signedness is ignored; + * - for ARRAY, dimensionality is ignored, element types are checked for + * compatibility recursively; + * - everything else shouldn't be ever a target of relocation. + * These rules are not set in stone and probably will be adjusted as we get + * more experience with using BPF CO-RE relocations. + */ +static int bpf_core_fields_are_compat(const struct btf *local_btf, + __u32 local_id, + const struct btf *targ_btf, + __u32 targ_id) +{ + const struct btf_type *local_type, *targ_type; + +recur: + local_type = skip_mods_and_typedefs(local_btf, local_id, &local_id); + targ_type = skip_mods_and_typedefs(targ_btf, targ_id, &targ_id); + if (!local_type || !targ_type) + return -EINVAL; + + if (btf_is_composite(local_type) && btf_is_composite(targ_type)) + return 1; + if (btf_kind(local_type) != btf_kind(targ_type)) + return 0; + + switch (btf_kind(local_type)) { + case BTF_KIND_FWD: + case BTF_KIND_PTR: + return 1; + case BTF_KIND_ENUM: + return local_type->size == targ_type->size; + case BTF_KIND_INT: + return btf_int_offset(local_type) == 0 && + btf_int_offset(targ_type) == 0 && + local_type->size == targ_type->size && + btf_int_bits(local_type) == btf_int_bits(targ_type); + case BTF_KIND_ARRAY: + local_id = btf_array(local_type)->type; + targ_id = btf_array(targ_type)->type; + goto recur; + default: + pr_warning("unexpected kind %d relocated, local [%d], target [%d]\n", + btf_kind(local_type), local_id, targ_id); + return 0; + } +} + +/* + * Given single high-level named field accessor in local type, find + * corresponding high-level accessor for a target type. Along the way, + * maintain low-level spec for target as well. Also keep updating target + * offset. + * + * Searching is performed through recursive exhaustive enumeration of all + * fields of a struct/union. If there are any anonymous (embedded) + * structs/unions, they are recursively searched as well. If field with + * desired name is found, check compatibility between local and target types, + * before returning result. + * + * 1 is returned, if field is found. + * 0 is returned if no compatible field is found. + * <0 is returned on error. + */ +static int bpf_core_match_member(const struct btf *local_btf, + const struct bpf_core_accessor *local_acc, + const struct btf *targ_btf, + __u32 targ_id, + struct bpf_core_spec *spec, + __u32 *next_targ_id) +{ + const struct btf_type *local_type, *targ_type; + const struct btf_member *local_member, *m; + const char *local_name, *targ_name; + __u32 local_id; + int i, n, found; + + targ_type = skip_mods_and_typedefs(targ_btf, targ_id, &targ_id); + if (!targ_type) + return -EINVAL; + if (!btf_is_composite(targ_type)) + return 0; + + local_id = local_acc->type_id; + local_type = btf__type_by_id(local_btf, local_id); + local_member = btf_members(local_type) + local_acc->idx; + local_name = btf__name_by_offset(local_btf, local_member->name_off); + + n = btf_vlen(targ_type); + m = btf_members(targ_type); + for (i = 0; i < n; i++, m++) { + __u32 offset; + + /* bitfield relocations not supported */ + if (btf_member_bitfield_size(targ_type, i)) + continue; + offset = btf_member_bit_offset(targ_type, i); + if (offset % 8) + continue; + + /* too deep struct/union/array nesting */ + if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN) + return -E2BIG; + + /* speculate this member will be the good one */ + spec->offset += offset / 8; + spec->raw_spec[spec->raw_len++] = i; + + targ_name = btf__name_by_offset(targ_btf, m->name_off); + if (str_is_empty(targ_name)) { + /* embedded struct/union, we need to go deeper */ + found = bpf_core_match_member(local_btf, local_acc, + targ_btf, m->type, + spec, next_targ_id); + if (found) /* either found or error */ + return found; + } else if (strcmp(local_name, targ_name) == 0) { + /* matching named field */ + struct bpf_core_accessor *targ_acc; + + targ_acc = &spec->spec[spec->len++]; + targ_acc->type_id = targ_id; + targ_acc->idx = i; + targ_acc->name = targ_name; + + *next_targ_id = m->type; + found = bpf_core_fields_are_compat(local_btf, + local_member->type, + targ_btf, m->type); + if (!found) + spec->len--; /* pop accessor */ + return found; + } + /* member turned out not to be what we looked for */ + spec->offset -= offset / 8; + spec->raw_len--; + } + + return 0; +} + +/* + * Try to match local spec to a target type and, if successful, produce full + * target spec (high-level, low-level + offset). + */ +static int bpf_core_spec_match(struct bpf_core_spec *local_spec, + const struct btf *targ_btf, __u32 targ_id, + struct bpf_core_spec *targ_spec) +{ + const struct btf_type *targ_type; + const struct bpf_core_accessor *local_acc; + struct bpf_core_accessor *targ_acc; + int i, sz, matched; + + memset(targ_spec, 0, sizeof(*targ_spec)); + targ_spec->btf = targ_btf; + + local_acc = &local_spec->spec[0]; + targ_acc = &targ_spec->spec[0]; + + for (i = 0; i < local_spec->len; i++, local_acc++, targ_acc++) { + targ_type = skip_mods_and_typedefs(targ_spec->btf, targ_id, + &targ_id); + if (!targ_type) + return -EINVAL; + + if (local_acc->name) { + matched = bpf_core_match_member(local_spec->btf, + local_acc, + targ_btf, targ_id, + targ_spec, &targ_id); + if (matched <= 0) + return matched; + } else { + /* for i=0, targ_id is already treated as array element + * type (because it's the original struct), for others + * we should find array element type first + */ + if (i > 0) { + const struct btf_array *a; + + if (!btf_is_array(targ_type)) + return 0; + + a = btf_array(targ_type); + if (local_acc->idx >= a->nelems) + return 0; + if (!skip_mods_and_typedefs(targ_btf, a->type, + &targ_id)) + return -EINVAL; + } + + /* too deep struct/union/array nesting */ + if (targ_spec->raw_len == BPF_CORE_SPEC_MAX_LEN) + return -E2BIG; + + targ_acc->type_id = targ_id; + targ_acc->idx = local_acc->idx; + targ_acc->name = NULL; + targ_spec->len++; + targ_spec->raw_spec[targ_spec->raw_len] = targ_acc->idx; + targ_spec->raw_len++; + + sz = btf__resolve_size(targ_btf, targ_id); + if (sz < 0) + return sz; + targ_spec->offset += local_acc->idx * sz; + } + } + + return 1; +} + +/* + * Patch relocatable BPF instruction. + * Expected insn->imm value is provided for validation, as well as the new + * relocated value. + * + * Currently three kinds of BPF instructions are supported: + * 1. rX = (assignment with immediate operand); + * 2. rX += (arithmetic operations with immediate operand); + * 3. *(rX) = (indirect memory assignment with immediate operand). + * + * If actual insn->imm value is wrong, bail out. + */ +static int bpf_core_reloc_insn(struct bpf_program *prog, int insn_off, + __u32 orig_off, __u32 new_off) +{ + struct bpf_insn *insn; + int insn_idx; + __u8 class; + + if (insn_off % sizeof(struct bpf_insn)) + return -EINVAL; + insn_idx = insn_off / sizeof(struct bpf_insn); + + insn = &prog->insns[insn_idx]; + class = BPF_CLASS(insn->code); + + if (class == BPF_ALU || class == BPF_ALU64) { + if (BPF_SRC(insn->code) != BPF_K) + return -EINVAL; + if (insn->imm != orig_off) + return -EINVAL; + insn->imm = new_off; + pr_debug("prog '%s': patched insn #%d (ALU/ALU64) imm %d -> %d\n", + bpf_program__title(prog, false), + insn_idx, orig_off, new_off); + } else { + pr_warning("prog '%s': trying to relocate unrecognized insn #%d, code:%x, src:%x, dst:%x, off:%x, imm:%x\n", + bpf_program__title(prog, false), + insn_idx, insn->code, insn->src_reg, insn->dst_reg, + insn->off, insn->imm); + return -EINVAL; + } + return 0; +} + +/* + * Probe few well-known locations for vmlinux kernel image and try to load BTF + * data out of it to use for target BTF. + */ +static struct btf *bpf_core_find_kernel_btf(void) +{ + const char *locations[] = { + "/lib/modules/%1$s/vmlinux-%1$s", + "/usr/lib/modules/%1$s/kernel/vmlinux", + }; + char path[PATH_MAX + 1]; + struct utsname buf; + struct btf *btf; + int i; + + uname(&buf); + + for (i = 0; i < ARRAY_SIZE(locations); i++) { + snprintf(path, PATH_MAX, locations[i], buf.release); + + if (access(path, R_OK)) + continue; + + btf = btf__parse_elf(path, NULL); + pr_debug("kernel BTF load from '%s': %ld\n", + path, PTR_ERR(btf)); + if (IS_ERR(btf)) + continue; + + return btf; + } + + pr_warning("failed to find valid kernel BTF\n"); + return ERR_PTR(-ESRCH); +} + +/* Output spec definition in the format: + * [] () + => @, + * where is a C-syntax view of recorded field access, e.g.: x.a[3].b + */ +static void bpf_core_dump_spec(int level, const struct bpf_core_spec *spec) +{ + const struct btf_type *t; + const char *s; + __u32 type_id; + int i; + + type_id = spec->spec[0].type_id; + t = btf__type_by_id(spec->btf, type_id); + s = btf__name_by_offset(spec->btf, t->name_off); + libbpf_print(level, "[%u] %s + ", type_id, s); + + for (i = 0; i < spec->raw_len; i++) + libbpf_print(level, "%d%s", spec->raw_spec[i], + i == spec->raw_len - 1 ? " => " : ":"); + + libbpf_print(level, "%u @ &x", spec->offset); + + for (i = 0; i < spec->len; i++) { + if (spec->spec[i].name) + libbpf_print(level, ".%s", spec->spec[i].name); + else + libbpf_print(level, "[%u]", spec->spec[i].idx); + } + +} + +static size_t bpf_core_hash_fn(const void *key, void *ctx) +{ + return (size_t)key; +} + +static bool bpf_core_equal_fn(const void *k1, const void *k2, void *ctx) +{ + return k1 == k2; +} + +static void *u32_as_hash_key(__u32 x) +{ + return (void *)(uintptr_t)x; +} + +/* + * CO-RE relocate single instruction. + * + * The outline and important points of the algorithm: + * 1. For given local type, find corresponding candidate target types. + * Candidate type is a type with the same "essential" name, ignoring + * everything after last triple underscore (___). E.g., `sample`, + * `sample___flavor_one`, `sample___flavor_another_one`, are all candidates + * for each other. Names with triple underscore are referred to as + * "flavors" and are useful, among other things, to allow to + * specify/support incompatible variations of the same kernel struct, which + * might differ between different kernel versions and/or build + * configurations. + * + * N.B. Struct "flavors" could be generated by bpftool's BTF-to-C + * converter, when deduplicated BTF of a kernel still contains more than + * one different types with the same name. In that case, ___2, ___3, etc + * are appended starting from second name conflict. But start flavors are + * also useful to be defined "locally", in BPF program, to extract same + * data from incompatible changes between different kernel + * versions/configurations. For instance, to handle field renames between + * kernel versions, one can use two flavors of the struct name with the + * same common name and use conditional relocations to extract that field, + * depending on target kernel version. + * 2. For each candidate type, try to match local specification to this + * candidate target type. Matching involves finding corresponding + * high-level spec accessors, meaning that all named fields should match, + * as well as all array accesses should be within the actual bounds. Also, + * types should be compatible (see bpf_core_fields_are_compat for details). + * 3. It is supported and expected that there might be multiple flavors + * matching the spec. As long as all the specs resolve to the same set of + * offsets across all candidates, there is not error. If there is any + * ambiguity, CO-RE relocation will fail. This is necessary to accomodate + * imprefection of BTF deduplication, which can cause slight duplication of + * the same BTF type, if some directly or indirectly referenced (by + * pointer) type gets resolved to different actual types in different + * object files. If such situation occurs, deduplicated BTF will end up + * with two (or more) structurally identical types, which differ only in + * types they refer to through pointer. This should be OK in most cases and + * is not an error. + * 4. Candidate types search is performed by linearly scanning through all + * types in target BTF. It is anticipated that this is overall more + * efficient memory-wise and not significantly worse (if not better) + * CPU-wise compared to prebuilding a map from all local type names to + * a list of candidate type names. It's also sped up by caching resolved + * list of matching candidates per each local "root" type ID, that has at + * least one bpf_offset_reloc associated with it. This list is shared + * between multiple relocations for the same type ID and is updated as some + * of the candidates are pruned due to structural incompatibility. + */ +static int bpf_core_reloc_offset(struct bpf_program *prog, + const struct bpf_offset_reloc *relo, + int relo_idx, + const struct btf *local_btf, + const struct btf *targ_btf, + struct hashmap *cand_cache) +{ + const char *prog_name = bpf_program__title(prog, false); + struct bpf_core_spec local_spec, cand_spec, targ_spec; + const void *type_key = u32_as_hash_key(relo->type_id); + const struct btf_type *local_type, *cand_type; + const char *local_name, *cand_name; + struct ids_vec *cand_ids; + __u32 local_id, cand_id; + const char *spec_str; + int i, j, err; + + local_id = relo->type_id; + local_type = btf__type_by_id(local_btf, local_id); + if (!local_type) + return -EINVAL; + + local_name = btf__name_by_offset(local_btf, local_type->name_off); + if (str_is_empty(local_name)) + return -EINVAL; + + spec_str = btf__name_by_offset(local_btf, relo->access_str_off); + if (str_is_empty(spec_str)) + return -EINVAL; + + err = bpf_core_spec_parse(local_btf, local_id, spec_str, &local_spec); + if (err) { + pr_warning("prog '%s': relo #%d: parsing [%d] %s + %s failed: %d\n", + prog_name, relo_idx, local_id, local_name, spec_str, + err); + return -EINVAL; + } + + pr_debug("prog '%s': relo #%d: spec is ", prog_name, relo_idx); + bpf_core_dump_spec(LIBBPF_DEBUG, &local_spec); + libbpf_print(LIBBPF_DEBUG, "\n"); + + if (!hashmap__find(cand_cache, type_key, (void **)&cand_ids)) { + cand_ids = bpf_core_find_cands(local_btf, local_id, targ_btf); + if (IS_ERR(cand_ids)) { + pr_warning("prog '%s': relo #%d: target candidate search failed for [%d] %s: %ld", + prog_name, relo_idx, local_id, local_name, + PTR_ERR(cand_ids)); + return PTR_ERR(cand_ids); + } + err = hashmap__set(cand_cache, type_key, cand_ids, NULL, NULL); + if (err) { + bpf_core_free_cands(cand_ids); + return err; + } + } + + for (i = 0, j = 0; i < cand_ids->len; i++) { + cand_id = cand_ids->data[i]; + cand_type = btf__type_by_id(targ_btf, cand_id); + cand_name = btf__name_by_offset(targ_btf, cand_type->name_off); + + err = bpf_core_spec_match(&local_spec, targ_btf, + cand_id, &cand_spec); + pr_debug("prog '%s': relo #%d: matching candidate #%d %s against spec ", + prog_name, relo_idx, i, cand_name); + bpf_core_dump_spec(LIBBPF_DEBUG, &cand_spec); + libbpf_print(LIBBPF_DEBUG, ": %d\n", err); + if (err < 0) { + pr_warning("prog '%s': relo #%d: matching error: %d\n", + prog_name, relo_idx, err); + return err; + } + if (err == 0) + continue; + + if (j == 0) { + targ_spec = cand_spec; + } else if (cand_spec.offset != targ_spec.offset) { + /* if there are many candidates, they should all + * resolve to the same offset + */ + pr_warning("prog '%s': relo #%d: offset ambiguity: %u != %u\n", + prog_name, relo_idx, cand_spec.offset, + targ_spec.offset); + return -EINVAL; + } + + cand_ids->data[j++] = cand_spec.spec[0].type_id; + } + + cand_ids->len = j; + if (cand_ids->len == 0) { + pr_warning("prog '%s': relo #%d: no matching targets found for [%d] %s + %s\n", + prog_name, relo_idx, local_id, local_name, spec_str); + return -ESRCH; + } + + err = bpf_core_reloc_insn(prog, relo->insn_off, + local_spec.offset, targ_spec.offset); + if (err) { + pr_warning("prog '%s': relo #%d: failed to patch insn at offset %d: %d\n", + prog_name, relo_idx, relo->insn_off, err); + return -EINVAL; + } + + return 0; +} + +static int +bpf_core_reloc_offsets(struct bpf_object *obj, const char *targ_btf_path) +{ + const struct btf_ext_info_sec *sec; + const struct bpf_offset_reloc *rec; + const struct btf_ext_info *seg; + struct hashmap_entry *entry; + struct hashmap *cand_cache = NULL; + struct bpf_program *prog; + struct btf *targ_btf; + const char *sec_name; + int i, err = 0; + + if (targ_btf_path) + targ_btf = btf__parse_elf(targ_btf_path, NULL); + else + targ_btf = bpf_core_find_kernel_btf(); + if (IS_ERR(targ_btf)) { + pr_warning("failed to get target BTF: %ld\n", + PTR_ERR(targ_btf)); + return PTR_ERR(targ_btf); + } + + cand_cache = hashmap__new(bpf_core_hash_fn, bpf_core_equal_fn, NULL); + if (IS_ERR(cand_cache)) { + err = PTR_ERR(cand_cache); + goto out; + } + + seg = &obj->btf_ext->offset_reloc_info; + for_each_btf_ext_sec(seg, sec) { + sec_name = btf__name_by_offset(obj->btf, sec->sec_name_off); + if (str_is_empty(sec_name)) { + err = -EINVAL; + goto out; + } + prog = bpf_object__find_program_by_title(obj, sec_name); + if (!prog) { + pr_warning("failed to find program '%s' for CO-RE offset relocation\n", + sec_name); + err = -EINVAL; + goto out; + } + + pr_debug("prog '%s': performing %d CO-RE offset relocs\n", + sec_name, sec->num_info); + + for_each_btf_ext_rec(seg, sec, i, rec) { + err = bpf_core_reloc_offset(prog, rec, i, obj->btf, + targ_btf, cand_cache); + if (err) { + pr_warning("prog '%s': relo #%d: failed to relocate: %d\n", + sec_name, i, err); + goto out; + } + } + } + +out: + btf__free(targ_btf); + if (!IS_ERR_OR_NULL(cand_cache)) { + hashmap__for_each_entry(cand_cache, entry, i) { + bpf_core_free_cands(entry->value); + } + hashmap__free(cand_cache); + } + return err; +} + +static int +bpf_object__relocate_core(struct bpf_object *obj, const char *targ_btf_path) +{ + int err = 0; + + if (obj->btf_ext->offset_reloc_info.len) + err = bpf_core_reloc_offsets(obj, targ_btf_path); + + return err; +} + static int bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, struct reloc_desc *relo) @@ -2397,14 +3235,21 @@ bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) return 0; } - static int -bpf_object__relocate(struct bpf_object *obj) +bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path) { struct bpf_program *prog; size_t i; int err; + if (obj->btf_ext) { + err = bpf_object__relocate_core(obj, targ_btf_path); + if (err) { + pr_warning("failed to perform CO-RE relocations: %d\n", + err); + return err; + } + } for (i = 0; i < obj->nr_programs; i++) { prog = &obj->programs[i]; @@ -2805,7 +3650,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr) obj->loaded = true; CHECK_ERR(bpf_object__create_maps(obj), err, out); - CHECK_ERR(bpf_object__relocate(obj), err, out); + CHECK_ERR(bpf_object__relocate(obj, attr->target_btf_path), err, out); CHECK_ERR(bpf_object__load_progs(obj, attr->log_level), err, out); return 0; diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 8a9d462a6f6d..e8f70977d137 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -92,6 +92,7 @@ LIBBPF_API void bpf_object__close(struct bpf_object *object); struct bpf_object_load_attr { struct bpf_object *obj; int log_level; + const char *target_btf_path; }; /* Load/unload object into/from kernel */ -- GitLab From 2dc26d5a4f2e97364542030a4a51e4a50c14bae3 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:52 -0700 Subject: [PATCH 2207/7155] selftests/bpf: add BPF_CORE_READ relocatable read macro Add BPF_CORE_READ macro used in tests to do bpf_core_read(), which automatically captures offset relocation. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/bpf_helpers.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 120aa86c58d3..8b503ea142f0 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -504,4 +504,24 @@ struct pt_regs; (void *)(PT_REGS_FP(ctx) + sizeof(ip))); }) #endif +/* + * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset + * relocation for source address using __builtin_preserve_access_index() + * built-in, provided by Clang. + * + * __builtin_preserve_access_index() takes as an argument an expression of + * taking an address of a field within struct/union. It makes compiler emit + * a relocation, which records BTF type ID describing root struct/union and an + * accessor string which describes exact embedded field that was used to take + * an address. See detailed description of this relocation format and + * semantics in comments to struct bpf_offset_reloc in libbpf_internal.h. + * + * This relocation allows libbpf to adjust BPF instruction to use correct + * actual field offset, based on target kernel BTF type that matches original + * (local) BTF, used to record relocation. + */ +#define BPF_CORE_READ(dst, src) \ + bpf_probe_read((dst), sizeof(*(src)), \ + __builtin_preserve_access_index(src)) + #endif -- GitLab From df36e621418b0de4d4afec5f8002d45ee636bb5c Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:53 -0700 Subject: [PATCH 2208/7155] selftests/bpf: add CO-RE relocs testing setup Add CO-RE relocation test runner. Add one simple test validating that libbpf's logic for searching for kernel image and loading BTF out of it works. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 129 ++++++++++++++++++ .../bpf/progs/test_core_reloc_kernel.c | 36 +++++ 2 files changed, 165 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/core_reloc.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c new file mode 100644 index 000000000000..4323a459c8a2 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +struct core_reloc_test_case { + const char *case_name; + const char *bpf_obj_file; + const char *btf_src_file; + const char *input; + int input_len; + const char *output; + int output_len; + bool fails; +}; + +static struct core_reloc_test_case test_cases[] = { + /* validate we can find kernel image and use its BTF for relocs */ + { + .case_name = "kernel", + .bpf_obj_file = "test_core_reloc_kernel.o", + .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */ + .input = "", + .input_len = 0, + .output = "\1", /* true */ + .output_len = 1, + }, +}; + +struct data { + char in[256]; + char out[256]; +}; + +void test_core_reloc(void) +{ + const char *probe_name = "raw_tracepoint/sys_enter"; + struct bpf_object_load_attr load_attr = {}; + struct core_reloc_test_case *test_case; + int err, duration = 0, i, equal; + struct bpf_link *link = NULL; + struct bpf_map *data_map; + struct bpf_program *prog; + struct bpf_object *obj; + const int zero = 0; + struct data data; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + test_case = &test_cases[i]; + + if (!test__start_subtest(test_case->case_name)) + continue; + + obj = bpf_object__open(test_case->bpf_obj_file); + if (CHECK(IS_ERR_OR_NULL(obj), "obj_open", + "failed to open '%s': %ld\n", + test_case->bpf_obj_file, PTR_ERR(obj))) + continue; + + prog = bpf_object__find_program_by_title(obj, probe_name); + if (CHECK(!prog, "find_probe", + "prog '%s' not found\n", probe_name)) + goto cleanup; + bpf_program__set_type(prog, BPF_PROG_TYPE_RAW_TRACEPOINT); + + load_attr.obj = obj; + load_attr.log_level = 0; + load_attr.target_btf_path = test_case->btf_src_file; + err = bpf_object__load_xattr(&load_attr); + if (test_case->fails) { + CHECK(!err, "obj_load_fail", + "should fail to load prog '%s'\n", probe_name); + goto cleanup; + } else { + if (CHECK(err, "obj_load", + "failed to load prog '%s': %d\n", + probe_name, err)) + goto cleanup; + } + + link = bpf_program__attach_raw_tracepoint(prog, "sys_enter"); + if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", + PTR_ERR(link))) + goto cleanup; + + data_map = bpf_object__find_map_by_name(obj, "test_cor.bss"); + if (CHECK(!data_map, "find_data_map", "data map not found\n")) + goto cleanup; + + memset(&data, 0, sizeof(data)); + memcpy(data.in, test_case->input, test_case->input_len); + + err = bpf_map_update_elem(bpf_map__fd(data_map), + &zero, &data, 0); + if (CHECK(err, "update_data_map", + "failed to update .data map: %d\n", err)) + goto cleanup; + + /* trigger test run */ + usleep(1); + + err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, &data); + if (CHECK(err, "get_result", + "failed to get output data: %d\n", err)) + goto cleanup; + + equal = memcmp(data.out, test_case->output, + test_case->output_len) == 0; + if (CHECK(!equal, "check_result", + "input/output data don't match\n")) { + int j; + + for (j = 0; j < test_case->input_len; j++) { + printf("input byte #%d: 0x%02hhx\n", + j, test_case->input[j]); + } + for (j = 0; j < test_case->output_len; j++) { + printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n", + j, test_case->output[j], data.out[j]); + } + goto cleanup; + } + +cleanup: + if (!IS_ERR_OR_NULL(link)) { + bpf_link__destroy(link); + link = NULL; + } + bpf_object__close(obj); + } +} diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c new file mode 100644 index 000000000000..37e02aa3f0c8 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct task_struct { + int pid; + int tgid; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_kernel(void *ctx) +{ + struct task_struct *task = (void *)bpf_get_current_task(); + uint64_t pid_tgid = bpf_get_current_pid_tgid(); + int pid, tgid; + + if (BPF_CORE_READ(&pid, &task->pid) || + BPF_CORE_READ(&tgid, &task->tgid)) + return 1; + + /* validate pid + tgid matches */ + data.out[0] = (((uint64_t)pid << 32) | tgid) == pid_tgid; + + return 0; +} + -- GitLab From 002d3afce65518dc5dfc398a37c2be2a6bf559c4 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:54 -0700 Subject: [PATCH 2209/7155] selftests/bpf: add CO-RE relocs struct flavors tests Add tests verifying that BPF program can use various struct/union "flavors" to extract data from the same target struct/union. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 34 ++++++++++ .../bpf/progs/btf__core_reloc_flavors.c | 3 + .../btf__core_reloc_flavors__err_wrong_name.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 15 +++++ .../bpf/progs/test_core_reloc_flavors.c | 62 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_flavors.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_flavors__err_wrong_name.c create mode 100644 tools/testing/selftests/bpf/progs/core_reloc_types.h create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 4323a459c8a2..59fd9cb207ab 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -1,5 +1,32 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include "progs/core_reloc_types.h" + +#define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name) + +#define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ + .a = 42, \ + .b = 0xc001, \ + .c = 0xbeef, \ +} + +#define FLAVORS_CASE_COMMON(name) \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_flavors.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o" \ + +#define FLAVORS_CASE(name) { \ + FLAVORS_CASE_COMMON(name), \ + .input = FLAVORS_DATA(core_reloc_##name), \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = FLAVORS_DATA(core_reloc_flavors), \ + .output_len = sizeof(struct core_reloc_flavors), \ +} + +#define FLAVORS_ERR_CASE(name) { \ + FLAVORS_CASE_COMMON(name), \ + .fails = true, \ +} struct core_reloc_test_case { const char *case_name; @@ -23,6 +50,13 @@ static struct core_reloc_test_case test_cases[] = { .output = "\1", /* true */ .output_len = 1, }, + + /* validate BPF program can use multiple flavors to match against + * single target BTF type + */ + FLAVORS_CASE(flavors), + + FLAVORS_ERR_CASE(flavors__err_wrong_name), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors.c new file mode 100644 index 000000000000..b74455b91227 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_flavors x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors__err_wrong_name.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors__err_wrong_name.c new file mode 100644 index 000000000000..7b6035f86ee6 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_flavors__err_wrong_name.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_flavors__err_wrong_name x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h new file mode 100644 index 000000000000..33b0c6a61912 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -0,0 +1,15 @@ +/* + * FLAVORS + */ +struct core_reloc_flavors { + int a; + int b; + int c; +}; + +/* this is not a flavor, as it doesn't have triple underscore */ +struct core_reloc_flavors__err_wrong_name { + int a; + int b; + int c; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c new file mode 100644 index 000000000000..9fda73e87972 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_flavors { + int a; + int b; + int c; +}; + +/* local flavor with reversed layout */ +struct core_reloc_flavors___reversed { + int c; + int b; + int a; +}; + +/* local flavor with nested/overlapping layout */ +struct core_reloc_flavors___weird { + struct { + int b; + }; + /* a and c overlap in local flavor, but this should still work + * correctly with target original flavor + */ + union { + int a; + int c; + }; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_flavors(void *ctx) +{ + struct core_reloc_flavors *in_orig = (void *)&data.in; + struct core_reloc_flavors___reversed *in_rev = (void *)&data.in; + struct core_reloc_flavors___weird *in_weird = (void *)&data.in; + struct core_reloc_flavors *out = (void *)&data.out; + + /* read a using weird layout */ + if (BPF_CORE_READ(&out->a, &in_weird->a)) + return 1; + /* read b using reversed layout */ + if (BPF_CORE_READ(&out->b, &in_rev->b)) + return 1; + /* read c using original layout */ + if (BPF_CORE_READ(&out->c, &in_orig->c)) + return 1; + + return 0; +} + -- GitLab From ec6438a988a43dcb03f0a04f3f51a48aba54764a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:55 -0700 Subject: [PATCH 2210/7155] selftests/bpf: add CO-RE relocs nesting tests Add a bunch of test validating correct handling of nested structs/unions. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 39 +++ .../bpf/progs/btf__core_reloc_nesting.c | 3 + .../btf__core_reloc_nesting___anon_embed.c | 3 + ...f__core_reloc_nesting___dup_compat_types.c | 5 + ...core_reloc_nesting___err_array_container.c | 3 + ...tf__core_reloc_nesting___err_array_field.c | 3 + ...e_reloc_nesting___err_dup_incompat_types.c | 4 + ...re_reloc_nesting___err_missing_container.c | 3 + ...__core_reloc_nesting___err_missing_field.c | 3 + ..._reloc_nesting___err_nonstruct_container.c | 3 + ...e_reloc_nesting___err_partial_match_dups.c | 4 + .../btf__core_reloc_nesting___err_too_deep.c | 3 + .../btf__core_reloc_nesting___extra_nesting.c | 3 + ..._core_reloc_nesting___struct_union_mixup.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 293 ++++++++++++++++++ .../bpf/progs/test_core_reloc_nesting.c | 46 +++ 16 files changed, 421 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___anon_embed.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___dup_compat_types.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_container.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_field.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_dup_incompat_types.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_container.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_field.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_nonstruct_container.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_partial_match_dups.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_too_deep.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___extra_nesting.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___struct_union_mixup.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 59fd9cb207ab..3e9344e41556 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -28,6 +28,29 @@ .fails = true, \ } +#define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ + .a = { .a = { .a = 42 } }, \ + .b = { .b = { .b = 0xc001 } }, \ +} + +#define NESTING_CASE_COMMON(name) \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_nesting.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o" + +#define NESTING_CASE(name) { \ + NESTING_CASE_COMMON(name), \ + .input = NESTING_DATA(core_reloc_##name), \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = NESTING_DATA(core_reloc_nesting), \ + .output_len = sizeof(struct core_reloc_nesting) \ +} + +#define NESTING_ERR_CASE(name) { \ + NESTING_CASE_COMMON(name), \ + .fails = true, \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -57,6 +80,22 @@ static struct core_reloc_test_case test_cases[] = { FLAVORS_CASE(flavors), FLAVORS_ERR_CASE(flavors__err_wrong_name), + + /* various struct/enum nesting and resolution scenarios */ + NESTING_CASE(nesting), + NESTING_CASE(nesting___anon_embed), + NESTING_CASE(nesting___struct_union_mixup), + NESTING_CASE(nesting___extra_nesting), + NESTING_CASE(nesting___dup_compat_types), + + NESTING_ERR_CASE(nesting___err_missing_field), + NESTING_ERR_CASE(nesting___err_array_field), + NESTING_ERR_CASE(nesting___err_missing_container), + NESTING_ERR_CASE(nesting___err_nonstruct_container), + NESTING_ERR_CASE(nesting___err_array_container), + NESTING_ERR_CASE(nesting___err_dup_incompat_types), + NESTING_ERR_CASE(nesting___err_partial_match_dups), + NESTING_ERR_CASE(nesting___err_too_deep), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting.c new file mode 100644 index 000000000000..4480fcc0f183 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___anon_embed.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___anon_embed.c new file mode 100644 index 000000000000..13e108f76ece --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___anon_embed.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___anon_embed x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___dup_compat_types.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___dup_compat_types.c new file mode 100644 index 000000000000..76b54fda5fbb --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___dup_compat_types.c @@ -0,0 +1,5 @@ +#include "core_reloc_types.h" + +void f1(struct core_reloc_nesting___dup_compat_types x) {} +void f2(struct core_reloc_nesting___dup_compat_types__2 x) {} +void f3(struct core_reloc_nesting___dup_compat_types__3 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_container.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_container.c new file mode 100644 index 000000000000..975fb95db810 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_container.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_array_container x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_field.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_field.c new file mode 100644 index 000000000000..ad66c67e7980 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_array_field.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_array_field x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_dup_incompat_types.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_dup_incompat_types.c new file mode 100644 index 000000000000..35c5f8da6812 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_dup_incompat_types.c @@ -0,0 +1,4 @@ +#include "core_reloc_types.h" + +void f1(struct core_reloc_nesting___err_dup_incompat_types__1 x) {} +void f2(struct core_reloc_nesting___err_dup_incompat_types__2 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_container.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_container.c new file mode 100644 index 000000000000..142e332041db --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_container.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_missing_container x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_field.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_field.c new file mode 100644 index 000000000000..efcae167fab9 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_missing_field.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_missing_field x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_nonstruct_container.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_nonstruct_container.c new file mode 100644 index 000000000000..97aaaedd8ada --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_nonstruct_container.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_nonstruct_container x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_partial_match_dups.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_partial_match_dups.c new file mode 100644 index 000000000000..ffde35086e90 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_partial_match_dups.c @@ -0,0 +1,4 @@ +#include "core_reloc_types.h" + +void f1(struct core_reloc_nesting___err_partial_match_dups__a x) {} +void f2(struct core_reloc_nesting___err_partial_match_dups__b x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_too_deep.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_too_deep.c new file mode 100644 index 000000000000..39a2fadd8e95 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___err_too_deep.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___err_too_deep x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___extra_nesting.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___extra_nesting.c new file mode 100644 index 000000000000..a09d9dfb20df --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___extra_nesting.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___extra_nesting x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___struct_union_mixup.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___struct_union_mixup.c new file mode 100644 index 000000000000..3d8a1a74012f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_nesting___struct_union_mixup.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_nesting___struct_union_mixup x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 33b0c6a61912..340ee2bcd463 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -13,3 +13,296 @@ struct core_reloc_flavors__err_wrong_name { int b; int c; }; + +/* + * NESTING + */ +/* original set up, used to record relocations in BPF program */ +struct core_reloc_nesting_substruct { + int a; +}; + +union core_reloc_nesting_subunion { + int b; +}; + +struct core_reloc_nesting { + union { + struct core_reloc_nesting_substruct a; + } a; + struct { + union core_reloc_nesting_subunion b; + } b; +}; + +/* inlined anonymous struct/union instead of named structs in original */ +struct core_reloc_nesting___anon_embed { + int __just_for_padding; + union { + struct { + int a; + } a; + } a; + struct { + union { + int b; + } b; + } b; +}; + +/* different mix of nested structs/unions than in original */ +struct core_reloc_nesting___struct_union_mixup { + int __a; + struct { + int __a; + union { + char __a; + int a; + } a; + } a; + int __b; + union { + int __b; + union { + char __b; + int b; + } b; + } b; +}; + +/* extra anon structs/unions, but still valid a.a.a and b.b.b accessors */ +struct core_reloc_nesting___extra_nesting { + int __padding; + struct { + struct { + struct { + struct { + union { + int a; + } a; + }; + }; + } a; + int __some_more; + struct { + union { + union { + union { + struct { + int b; + }; + } b; + }; + } b; + }; + }; +}; + +/* three flavors of same struct with different structure but same layout for + * a.a.a and b.b.b, thus successfully resolved and relocatable */ +struct core_reloc_nesting___dup_compat_types { + char __just_for_padding; + /* 3 more bytes of padding */ + struct { + struct { + int a; /* offset 4 */ + } a; + } a; + long long __more_padding; + struct { + struct { + int b; /* offset 16 */ + } b; + } b; +}; + +struct core_reloc_nesting___dup_compat_types__2 { + int __aligned_padding; + struct { + int __trickier_noop[0]; + struct { + char __some_more_noops[0]; + int a; /* offset 4 */ + } a; + } a; + int __more_padding; + struct { + struct { + struct { + int __critical_padding; + int b; /* offset 16 */ + } b; + int __does_not_matter; + }; + } b; + int __more_irrelevant_stuff; +}; + +struct core_reloc_nesting___dup_compat_types__3 { + char __correct_padding[4]; + struct { + struct { + int a; /* offset 4 */ + } a; + } a; + /* 8 byte padding due to next struct's alignment */ + struct { + struct { + int b; + } b; + } b __attribute__((aligned(16))); +}; + +/* b.b.b field is missing */ +struct core_reloc_nesting___err_missing_field { + struct { + struct { + int a; + } a; + } a; + struct { + struct { + int x; + } b; + } b; +}; + +/* b.b.b field is an array of integers instead of plain int */ +struct core_reloc_nesting___err_array_field { + struct { + struct { + int a; + } a; + } a; + struct { + struct { + int b[1]; + } b; + } b; +}; + +/* middle b container is missing */ +struct core_reloc_nesting___err_missing_container { + struct { + struct { + int a; + } a; + } a; + struct { + int x; + } b; +}; + +/* middle b container is referenced through pointer instead of being embedded */ +struct core_reloc_nesting___err_nonstruct_container { + struct { + struct { + int a; + } a; + } a; + struct { + struct { + int b; + } *b; + } b; +}; + +/* middle b container is an array of structs instead of plain struct */ +struct core_reloc_nesting___err_array_container { + struct { + struct { + int a; + } a; + } a; + struct { + struct { + int b; + } b[1]; + } b; +}; + +/* two flavors of same struct with incompatible layout for b.b.b */ +struct core_reloc_nesting___err_dup_incompat_types__1 { + struct { + struct { + int a; /* offset 0 */ + } a; + } a; + struct { + struct { + int b; /* offset 4 */ + } b; + } b; +}; + +struct core_reloc_nesting___err_dup_incompat_types__2 { + struct { + struct { + int a; /* offset 0 */ + } a; + } a; + int __extra_padding; + struct { + struct { + int b; /* offset 8 (!) */ + } b; + } b; +}; + +/* two flavors of same struct having one of a.a.a and b.b.b, but not both */ +struct core_reloc_nesting___err_partial_match_dups__a { + struct { + struct { + int a; + } a; + } a; +}; + +struct core_reloc_nesting___err_partial_match_dups__b { + struct { + struct { + int b; + } b; + } b; +}; + +struct core_reloc_nesting___err_too_deep { + struct { + struct { + int a; + } a; + } a; + /* 65 levels of nestedness for b.b.b */ + struct { + struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + struct { struct { struct { struct { struct { + /* this one is one too much */ + struct { + int b; + }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + }; }; }; }; }; + } b; + } b; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c b/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c new file mode 100644 index 000000000000..3ca30cec2b39 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_nesting_substruct { + int a; +}; + +union core_reloc_nesting_subunion { + int b; +}; + +/* int a.a.a and b.b.b accesses */ +struct core_reloc_nesting { + union { + struct core_reloc_nesting_substruct a; + } a; + struct { + union core_reloc_nesting_subunion b; + } b; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_nesting(void *ctx) +{ + struct core_reloc_nesting *in = (void *)&data.in; + struct core_reloc_nesting *out = (void *)&data.out; + + if (BPF_CORE_READ(&out->a.a.a, &in->a.a.a)) + return 1; + if (BPF_CORE_READ(&out->b.b.b, &in->b.b.b)) + return 1; + + return 0; +} + -- GitLab From 20a9ad2e71368da8e831317f0a545e4bfb31cce1 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:56 -0700 Subject: [PATCH 2211/7155] selftests/bpf: add CO-RE relocs array tests Add tests for various array handling/relocation scenarios. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 41 ++++++++++ .../bpf/progs/btf__core_reloc_arrays.c | 3 + .../btf__core_reloc_arrays___diff_arr_dim.c | 3 + ...btf__core_reloc_arrays___diff_arr_val_sz.c | 3 + .../btf__core_reloc_arrays___err_non_array.c | 3 + ...btf__core_reloc_arrays___err_too_shallow.c | 3 + .../btf__core_reloc_arrays___err_too_small.c | 3 + ..._core_reloc_arrays___err_wrong_val_type1.c | 3 + ..._core_reloc_arrays___err_wrong_val_type2.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 81 +++++++++++++++++++ .../bpf/progs/test_core_reloc_arrays.c | 55 +++++++++++++ 11 files changed, 201 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_dim.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_val_sz.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_non_array.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_shallow.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_small.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type1.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type2.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 3e9344e41556..3b40160c0837 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -51,6 +51,36 @@ .fails = true, \ } +#define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ + .a = { [2] = 1 }, \ + .b = { [1] = { [2] = { [3] = 2 } } }, \ + .c = { [1] = { .c = 3 } }, \ + .d = { [0] = { [0] = { .d = 4 } } }, \ +} + +#define ARRAYS_CASE_COMMON(name) \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_arrays.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o" + +#define ARRAYS_CASE(name) { \ + ARRAYS_CASE_COMMON(name), \ + .input = ARRAYS_DATA(core_reloc_##name), \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) { \ + .a2 = 1, \ + .b123 = 2, \ + .c1c = 3, \ + .d00d = 4, \ + }, \ + .output_len = sizeof(struct core_reloc_arrays_output) \ +} + +#define ARRAYS_ERR_CASE(name) { \ + ARRAYS_CASE_COMMON(name), \ + .fails = true, \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -96,6 +126,17 @@ static struct core_reloc_test_case test_cases[] = { NESTING_ERR_CASE(nesting___err_dup_incompat_types), NESTING_ERR_CASE(nesting___err_partial_match_dups), NESTING_ERR_CASE(nesting___err_too_deep), + + /* various array access relocation scenarios */ + ARRAYS_CASE(arrays), + ARRAYS_CASE(arrays___diff_arr_dim), + ARRAYS_CASE(arrays___diff_arr_val_sz), + + ARRAYS_ERR_CASE(arrays___err_too_small), + ARRAYS_ERR_CASE(arrays___err_too_shallow), + ARRAYS_ERR_CASE(arrays___err_non_array), + ARRAYS_ERR_CASE(arrays___err_wrong_val_type1), + ARRAYS_ERR_CASE(arrays___err_wrong_val_type2), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays.c new file mode 100644 index 000000000000..018ed7fbba3a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_dim.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_dim.c new file mode 100644 index 000000000000..13d662c57014 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_dim.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___diff_arr_dim x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_val_sz.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_val_sz.c new file mode 100644 index 000000000000..a351f418c85d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___diff_arr_val_sz.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___diff_arr_val_sz x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_non_array.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_non_array.c new file mode 100644 index 000000000000..a8735009becc --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_non_array.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___err_non_array x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_shallow.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_shallow.c new file mode 100644 index 000000000000..2a67c28b1e75 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_shallow.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___err_too_shallow x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_small.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_small.c new file mode 100644 index 000000000000..1142c08c925f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_too_small.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___err_too_small x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type1.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type1.c new file mode 100644 index 000000000000..795a5b729176 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type1.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___err_wrong_val_type1 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type2.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type2.c new file mode 100644 index 000000000000..3af74b837c4d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_arrays___err_wrong_val_type2.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_arrays___err_wrong_val_type2 x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 340ee2bcd463..45de7986ea2e 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -306,3 +306,84 @@ struct core_reloc_nesting___err_too_deep { } b; } b; }; + +/* + * ARRAYS + */ +struct core_reloc_arrays_output { + int a2; + char b123; + int c1c; + int d00d; +}; + +struct core_reloc_arrays_substruct { + int c; + int d; +}; + +struct core_reloc_arrays { + int a[5]; + char b[2][3][4]; + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +/* bigger array dimensions */ +struct core_reloc_arrays___diff_arr_dim { + int a[7]; + char b[3][4][5]; + struct core_reloc_arrays_substruct c[4]; + struct core_reloc_arrays_substruct d[2][3]; +}; + +/* different size of array's value (struct) */ +struct core_reloc_arrays___diff_arr_val_sz { + int a[5]; + char b[2][3][4]; + struct { + int __padding1; + int c; + int __padding2; + } c[3]; + struct { + int __padding1; + int d; + int __padding2; + } d[1][2]; +}; + +struct core_reloc_arrays___err_too_small { + int a[2]; /* this one is too small */ + char b[2][3][4]; + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +struct core_reloc_arrays___err_too_shallow { + int a[5]; + char b[2][3]; /* this one lacks one dimension */ + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +struct core_reloc_arrays___err_non_array { + int a; /* not an array */ + char b[2][3][4]; + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +struct core_reloc_arrays___err_wrong_val_type1 { + char a[5]; /* char instead of int */ + char b[2][3][4]; + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +struct core_reloc_arrays___err_wrong_val_type2 { + int a[5]; + char b[2][3][4]; + int c[3]; /* value is not a struct */ + struct core_reloc_arrays_substruct d[1][2]; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c new file mode 100644 index 000000000000..bf67f0fdf743 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_arrays_output { + int a2; + char b123; + int c1c; + int d00d; +}; + +struct core_reloc_arrays_substruct { + int c; + int d; +}; + +struct core_reloc_arrays { + int a[5]; + char b[2][3][4]; + struct core_reloc_arrays_substruct c[3]; + struct core_reloc_arrays_substruct d[1][2]; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_arrays(void *ctx) +{ + struct core_reloc_arrays *in = (void *)&data.in; + struct core_reloc_arrays_output *out = (void *)&data.out; + + /* in->a[2] */ + if (BPF_CORE_READ(&out->a2, &in->a[2])) + return 1; + /* in->b[1][2][3] */ + if (BPF_CORE_READ(&out->b123, &in->b[1][2][3])) + return 1; + /* in->c[1].c */ + if (BPF_CORE_READ(&out->c1c, &in->c[1].c)) + return 1; + /* in->d[0][0].d */ + if (BPF_CORE_READ(&out->d00d, &in->d[0][0].d)) + return 1; + + return 0; +} + -- GitLab From d9db3550300f4390e457c79189e2601c107f9fe6 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:57 -0700 Subject: [PATCH 2212/7155] selftests/bpf: add CO-RE relocs enum/ptr/func_proto tests Test CO-RE relocation handling of ints, enums, pointers, func protos, etc. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 36 ++++++++++ .../bpf/progs/btf__core_reloc_primitives.c | 3 + ...f__core_reloc_primitives___diff_enum_def.c | 3 + ..._core_reloc_primitives___diff_func_proto.c | 3 + ...f__core_reloc_primitives___diff_ptr_type.c | 3 + ...tf__core_reloc_primitives___err_non_enum.c | 3 + ...btf__core_reloc_primitives___err_non_int.c | 3 + ...btf__core_reloc_primitives___err_non_ptr.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 67 +++++++++++++++++++ .../bpf/progs/test_core_reloc_primitives.c | 43 ++++++++++++ 10 files changed, 167 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_enum_def.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_func_proto.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_ptr_type.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_enum.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_int.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_ptr.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 3b40160c0837..37b36df93ded 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -81,6 +81,32 @@ .fails = true, \ } +#define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ + .a = 1, \ + .b = 2, \ + .c = 3, \ + .d = (void *)4, \ + .f = (void *)5, \ +} + +#define PRIMITIVES_CASE_COMMON(name) \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_primitives.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o" + +#define PRIMITIVES_CASE(name) { \ + PRIMITIVES_CASE_COMMON(name), \ + .input = PRIMITIVES_DATA(core_reloc_##name), \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = PRIMITIVES_DATA(core_reloc_primitives), \ + .output_len = sizeof(struct core_reloc_primitives), \ +} + +#define PRIMITIVES_ERR_CASE(name) { \ + PRIMITIVES_CASE_COMMON(name), \ + .fails = true, \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -137,6 +163,16 @@ static struct core_reloc_test_case test_cases[] = { ARRAYS_ERR_CASE(arrays___err_non_array), ARRAYS_ERR_CASE(arrays___err_wrong_val_type1), ARRAYS_ERR_CASE(arrays___err_wrong_val_type2), + + /* enum/ptr/int handling scenarios */ + PRIMITIVES_CASE(primitives), + PRIMITIVES_CASE(primitives___diff_enum_def), + PRIMITIVES_CASE(primitives___diff_func_proto), + PRIMITIVES_CASE(primitives___diff_ptr_type), + + PRIMITIVES_ERR_CASE(primitives___err_non_enum), + PRIMITIVES_ERR_CASE(primitives___err_non_int), + PRIMITIVES_ERR_CASE(primitives___err_non_ptr), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives.c new file mode 100644 index 000000000000..96b90e39242a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_enum_def.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_enum_def.c new file mode 100644 index 000000000000..6e87233a3ed0 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_enum_def.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___diff_enum_def x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_func_proto.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_func_proto.c new file mode 100644 index 000000000000..d9f48e80b9d9 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_func_proto.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___diff_func_proto x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_ptr_type.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_ptr_type.c new file mode 100644 index 000000000000..c718f75f8f3b --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___diff_ptr_type.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___diff_ptr_type x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_enum.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_enum.c new file mode 100644 index 000000000000..b8a120830891 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_enum.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___err_non_enum x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_int.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_int.c new file mode 100644 index 000000000000..ad8b3c9aa76f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_int.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___err_non_int x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_ptr.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_ptr.c new file mode 100644 index 000000000000..e20bc1d42d0a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_primitives___err_non_ptr.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_primitives___err_non_ptr x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 45de7986ea2e..7526a5f5755b 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -387,3 +387,70 @@ struct core_reloc_arrays___err_wrong_val_type2 { int c[3]; /* value is not a struct */ struct core_reloc_arrays_substruct d[1][2]; }; + +/* + * PRIMITIVES + */ +enum core_reloc_primitives_enum { + A = 0, + B = 1, +}; + +struct core_reloc_primitives { + char a; + int b; + enum core_reloc_primitives_enum c; + void *d; + int (*f)(const char *); +}; + +struct core_reloc_primitives___diff_enum_def { + char a; + int b; + void *d; + int (*f)(const char *); + enum { + X = 100, + Y = 200, + } c; /* inline enum def with differing set of values */ +}; + +struct core_reloc_primitives___diff_func_proto { + void (*f)(int); /* incompatible function prototype */ + void *d; + enum core_reloc_primitives_enum c; + int b; + char a; +}; + +struct core_reloc_primitives___diff_ptr_type { + const char * const d; /* different pointee type + modifiers */ + char a; + int b; + enum core_reloc_primitives_enum c; + int (*f)(const char *); +}; + +struct core_reloc_primitives___err_non_enum { + char a[1]; + int b; + int c; /* int instead of enum */ + void *d; + int (*f)(const char *); +}; + +struct core_reloc_primitives___err_non_int { + char a[1]; + int *b; /* ptr instead of int */ + enum core_reloc_primitives_enum c; + void *d; + int (*f)(const char *); +}; + +struct core_reloc_primitives___err_non_ptr { + char a[1]; + int b; + enum core_reloc_primitives_enum c; + int d; /* int instead of ptr */ + int (*f)(const char *); +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c b/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c new file mode 100644 index 000000000000..add52f23ab35 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +enum core_reloc_primitives_enum { + A = 0, + B = 1, +}; + +struct core_reloc_primitives { + char a; + int b; + enum core_reloc_primitives_enum c; + void *d; + int (*f)(const char *); +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_primitives(void *ctx) +{ + struct core_reloc_primitives *in = (void *)&data.in; + struct core_reloc_primitives *out = (void *)&data.out; + + if (BPF_CORE_READ(&out->a, &in->a) || + BPF_CORE_READ(&out->b, &in->b) || + BPF_CORE_READ(&out->c, &in->c) || + BPF_CORE_READ(&out->d, &in->d) || + BPF_CORE_READ(&out->f, &in->f)) + return 1; + + return 0; +} + -- GitLab From 9654e2ae908eb0d51b0b79c7c50df0754ed38edd Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:58 -0700 Subject: [PATCH 2213/7155] selftests/bpf: add CO-RE relocs modifiers/typedef tests Add tests validating correct handling of various combinations of typedefs and const/volatile/restrict modifiers. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 27 +++++++ .../bpf/progs/btf__core_reloc_mods.c | 3 + .../progs/btf__core_reloc_mods___mod_swap.c | 3 + .../progs/btf__core_reloc_mods___typedefs.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 72 +++++++++++++++++++ .../bpf/progs/test_core_reloc_mods.c | 62 ++++++++++++++++ 6 files changed, 170 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_mods.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_mods___mod_swap.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_mods___typedefs.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_mods.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 37b36df93ded..9dadf462a951 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -107,6 +107,28 @@ .fails = true, \ } +#define MODS_CASE(name) { \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_mods.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o", \ + .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) { \ + .a = 1, \ + .b = 2, \ + .c = (void *)3, \ + .d = (void *)4, \ + .e = { [2] = 5 }, \ + .f = { [1] = 6 }, \ + .g = { .x = 7 }, \ + .h = { .y = 8 }, \ + }, \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) { \ + .a = 1, .b = 2, .c = 3, .d = 4, \ + .e = 5, .f = 6, .g = 7, .h = 8, \ + }, \ + .output_len = sizeof(struct core_reloc_mods_output), \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -173,6 +195,11 @@ static struct core_reloc_test_case test_cases[] = { PRIMITIVES_ERR_CASE(primitives___err_non_enum), PRIMITIVES_ERR_CASE(primitives___err_non_int), PRIMITIVES_ERR_CASE(primitives___err_non_ptr), + + /* const/volatile/restrict and typedefs scenarios */ + MODS_CASE(mods), + MODS_CASE(mods___mod_swap), + MODS_CASE(mods___typedefs), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_mods.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods.c new file mode 100644 index 000000000000..124197a2e813 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_mods x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___mod_swap.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___mod_swap.c new file mode 100644 index 000000000000..f8a6592ca75f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___mod_swap.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_mods___mod_swap x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___typedefs.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___typedefs.c new file mode 100644 index 000000000000..5c0d73687247 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_mods___typedefs.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_mods___typedefs x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 7526a5f5755b..3401e8342e57 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -454,3 +454,75 @@ struct core_reloc_primitives___err_non_ptr { int d; /* int instead of ptr */ int (*f)(const char *); }; + +/* + * MODS + */ +struct core_reloc_mods_output { + int a, b, c, d, e, f, g, h; +}; + +typedef const int int_t; +typedef const char *char_ptr_t; +typedef const int arr_t[7]; + +struct core_reloc_mods_substruct { + int x; + int y; +}; + +typedef struct { + int x; + int y; +} core_reloc_mods_substruct_t; + +struct core_reloc_mods { + int a; + int_t b; + char *c; + char_ptr_t d; + int e[3]; + arr_t f; + struct core_reloc_mods_substruct g; + core_reloc_mods_substruct_t h; +}; + +/* a/b, c/d, e/f, and g/h pairs are swapped */ +struct core_reloc_mods___mod_swap { + int b; + int_t a; + char *d; + char_ptr_t c; + int f[3]; + arr_t e; + struct { + int y; + int x; + } h; + core_reloc_mods_substruct_t g; +}; + +typedef int int1_t; +typedef int1_t int2_t; +typedef int2_t int3_t; + +typedef int arr1_t[5]; +typedef arr1_t arr2_t; +typedef arr2_t arr3_t; +typedef arr3_t arr4_t; + +typedef const char * const volatile restrict fancy_char_ptr_t; + +typedef core_reloc_mods_substruct_t core_reloc_mods_substruct_tt; + +/* we need more typedefs */ +struct core_reloc_mods___typedefs { + core_reloc_mods_substruct_tt g; + core_reloc_mods_substruct_tt h; + arr4_t f; + arr4_t e; + fancy_char_ptr_t d; + fancy_char_ptr_t c; + int3_t b; + int3_t a; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c b/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c new file mode 100644 index 000000000000..f98b942c062b --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_mods_output { + int a, b, c, d, e, f, g, h; +}; + +typedef const int int_t; +typedef const char *char_ptr_t; +typedef const int arr_t[7]; + +struct core_reloc_mods_substruct { + int x; + int y; +}; + +typedef struct { + int x; + int y; +} core_reloc_mods_substruct_t; + +struct core_reloc_mods { + int a; + int_t b; + char *c; + char_ptr_t d; + int e[3]; + arr_t f; + struct core_reloc_mods_substruct g; + core_reloc_mods_substruct_t h; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_mods(void *ctx) +{ + struct core_reloc_mods *in = (void *)&data.in; + struct core_reloc_mods_output *out = (void *)&data.out; + + if (BPF_CORE_READ(&out->a, &in->a) || + BPF_CORE_READ(&out->b, &in->b) || + BPF_CORE_READ(&out->c, &in->c) || + BPF_CORE_READ(&out->d, &in->d) || + BPF_CORE_READ(&out->e, &in->e[2]) || + BPF_CORE_READ(&out->f, &in->f[1]) || + BPF_CORE_READ(&out->g, &in->g.x) || + BPF_CORE_READ(&out->h, &in->h.y)) + return 1; + + return 0; +} + -- GitLab From d698f9dbdbed036ef28a96cd34a1b5d7fe58750e Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:39:59 -0700 Subject: [PATCH 2214/7155] selftests/bpf: add CO-RE relocs ptr-as-array tests Add test validating correct relocation handling for cases where pointer to something is used as an array. E.g.: int *ptr = ...; int x = ptr[42]; Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 20 +++++++++++++ .../bpf/progs/btf__core_reloc_ptr_as_arr.c | 3 ++ .../btf__core_reloc_ptr_as_arr___diff_sz.c | 3 ++ .../selftests/bpf/progs/core_reloc_types.h | 13 ++++++++ .../bpf/progs/test_core_reloc_ptr_as_arr.c | 30 +++++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr___diff_sz.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 9dadf462a951..2cfe0bdc53f8 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -129,6 +129,22 @@ .output_len = sizeof(struct core_reloc_mods_output), \ } +#define PTR_AS_ARR_CASE(name) { \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_ptr_as_arr.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o", \ + .input = (const char *)&(struct core_reloc_##name []){ \ + { .a = 1 }, \ + { .a = 2 }, \ + { .a = 3 }, \ + }, \ + .input_len = 3 * sizeof(struct core_reloc_##name), \ + .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) { \ + .a = 3, \ + }, \ + .output_len = sizeof(struct core_reloc_ptr_as_arr), \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -200,6 +216,10 @@ static struct core_reloc_test_case test_cases[] = { MODS_CASE(mods), MODS_CASE(mods___mod_swap), MODS_CASE(mods___typedefs), + + /* handling "ptr is an array" semantics */ + PTR_AS_ARR_CASE(ptr_as_arr), + PTR_AS_ARR_CASE(ptr_as_arr___diff_sz), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr.c new file mode 100644 index 000000000000..8da52432ba17 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ptr_as_arr x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr___diff_sz.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr___diff_sz.c new file mode 100644 index 000000000000..003acfc9a3e7 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ptr_as_arr___diff_sz.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ptr_as_arr___diff_sz x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 3401e8342e57..c17c9279deae 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -526,3 +526,16 @@ struct core_reloc_mods___typedefs { int3_t b; int3_t a; }; + +/* + * PTR_AS_ARR + */ +struct core_reloc_ptr_as_arr { + int a; +}; + +struct core_reloc_ptr_as_arr___diff_sz { + int :32; /* padding */ + char __some_more_padding; + int a; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c new file mode 100644 index 000000000000..526b7ddc7ea1 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_ptr_as_arr { + int a; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_ptr_as_arr(void *ctx) +{ + struct core_reloc_ptr_as_arr *in = (void *)&data.in; + struct core_reloc_ptr_as_arr *out = (void *)&data.out; + + if (BPF_CORE_READ(&out->a, &in[2].a)) + return 1; + + return 0; +} + -- GitLab From c1f5e7dd19e71cd3607572bb957def618a33519a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:40:00 -0700 Subject: [PATCH 2215/7155] selftests/bpf: add CO-RE relocs ints tests Add various tests validating handling compatible/incompatible integer types. Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 40 +++++++ .../bpf/progs/btf__core_reloc_ints.c | 3 + .../bpf/progs/btf__core_reloc_ints___bool.c | 3 + .../btf__core_reloc_ints___err_bitfield.c | 3 + .../btf__core_reloc_ints___err_wrong_sz_16.c | 3 + .../btf__core_reloc_ints___err_wrong_sz_32.c | 3 + .../btf__core_reloc_ints___err_wrong_sz_64.c | 3 + .../btf__core_reloc_ints___err_wrong_sz_8.c | 3 + .../btf__core_reloc_ints___reverse_sign.c | 3 + .../selftests/bpf/progs/core_reloc_types.h | 101 ++++++++++++++++++ .../bpf/progs/test_core_reloc_ints.c | 44 ++++++++ 11 files changed, 209 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___bool.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_bitfield.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_16.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_32.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_64.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_8.c create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_ints___reverse_sign.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_ints.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 2cfe0bdc53f8..251ef8c518f0 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -145,6 +145,35 @@ .output_len = sizeof(struct core_reloc_ptr_as_arr), \ } +#define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ + .u8_field = 1, \ + .s8_field = 2, \ + .u16_field = 3, \ + .s16_field = 4, \ + .u32_field = 5, \ + .s32_field = 6, \ + .u64_field = 7, \ + .s64_field = 8, \ +} + +#define INTS_CASE_COMMON(name) \ + .case_name = #name, \ + .bpf_obj_file = "test_core_reloc_ints.o", \ + .btf_src_file = "btf__core_reloc_" #name ".o" + +#define INTS_CASE(name) { \ + INTS_CASE_COMMON(name), \ + .input = INTS_DATA(core_reloc_##name), \ + .input_len = sizeof(struct core_reloc_##name), \ + .output = INTS_DATA(core_reloc_ints), \ + .output_len = sizeof(struct core_reloc_ints), \ +} + +#define INTS_ERR_CASE(name) { \ + INTS_CASE_COMMON(name), \ + .fails = true, \ +} + struct core_reloc_test_case { const char *case_name; const char *bpf_obj_file; @@ -220,6 +249,17 @@ static struct core_reloc_test_case test_cases[] = { /* handling "ptr is an array" semantics */ PTR_AS_ARR_CASE(ptr_as_arr), PTR_AS_ARR_CASE(ptr_as_arr___diff_sz), + + /* int signedness/sizing/bitfield handling */ + INTS_CASE(ints), + INTS_CASE(ints___bool), + INTS_CASE(ints___reverse_sign), + + INTS_ERR_CASE(ints___err_bitfield), + INTS_ERR_CASE(ints___err_wrong_sz_8), + INTS_ERR_CASE(ints___err_wrong_sz_16), + INTS_ERR_CASE(ints___err_wrong_sz_32), + INTS_ERR_CASE(ints___err_wrong_sz_64), }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints.c new file mode 100644 index 000000000000..7d0f041042c5 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___bool.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___bool.c new file mode 100644 index 000000000000..f9359450186e --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___bool.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___bool x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_bitfield.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_bitfield.c new file mode 100644 index 000000000000..50369e8320a0 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_bitfield.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___err_bitfield x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_16.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_16.c new file mode 100644 index 000000000000..823bac13d641 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_16.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___err_wrong_sz_16 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_32.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_32.c new file mode 100644 index 000000000000..b44f3be18535 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_32.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___err_wrong_sz_32 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_64.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_64.c new file mode 100644 index 000000000000..9a3dd2099c0f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_64.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___err_wrong_sz_64 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_8.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_8.c new file mode 100644 index 000000000000..9f11ef5f6e88 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___err_wrong_sz_8.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___err_wrong_sz_8 x) {} diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___reverse_sign.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___reverse_sign.c new file mode 100644 index 000000000000..aafb1c5819d7 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_ints___reverse_sign.c @@ -0,0 +1,3 @@ +#include "core_reloc_types.h" + +void f(struct core_reloc_ints___reverse_sign x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index c17c9279deae..5f3ebd4f6dc3 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -1,3 +1,6 @@ +#include +#include + /* * FLAVORS */ @@ -539,3 +542,101 @@ struct core_reloc_ptr_as_arr___diff_sz { char __some_more_padding; int a; }; + +/* + * INTS + */ +struct core_reloc_ints { + uint8_t u8_field; + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field; + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +/* signed/unsigned types swap */ +struct core_reloc_ints___reverse_sign { + int8_t u8_field; + uint8_t s8_field; + int16_t u16_field; + uint16_t s16_field; + int32_t u32_field; + uint32_t s32_field; + int64_t u64_field; + uint64_t s64_field; +}; + +struct core_reloc_ints___bool { + bool u8_field; /* bool instead of uint8 */ + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field; + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +struct core_reloc_ints___err_bitfield { + uint8_t u8_field; + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field: 32; /* bitfields are not supported */ + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +struct core_reloc_ints___err_wrong_sz_8 { + uint16_t u8_field; /* not 8-bit anymore */ + int16_t s8_field; /* not 8-bit anymore */ + + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field; + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +struct core_reloc_ints___err_wrong_sz_16 { + uint8_t u8_field; + int8_t s8_field; + + uint32_t u16_field; /* not 16-bit anymore */ + int32_t s16_field; /* not 16-bit anymore */ + + uint32_t u32_field; + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +struct core_reloc_ints___err_wrong_sz_32 { + uint8_t u8_field; + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + + uint64_t u32_field; /* not 32-bit anymore */ + int64_t s32_field; /* not 32-bit anymore */ + + uint64_t u64_field; + int64_t s64_field; +}; + +struct core_reloc_ints___err_wrong_sz_64 { + uint8_t u8_field; + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field; + int32_t s32_field; + + uint32_t u64_field; /* not 64-bit anymore */ + int32_t s64_field; /* not 64-bit anymore */ +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c new file mode 100644 index 000000000000..d99233c8008a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_ints { + uint8_t u8_field; + int8_t s8_field; + uint16_t u16_field; + int16_t s16_field; + uint32_t u32_field; + int32_t s32_field; + uint64_t u64_field; + int64_t s64_field; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_ints(void *ctx) +{ + struct core_reloc_ints *in = (void *)&data.in; + struct core_reloc_ints *out = (void *)&data.out; + + if (BPF_CORE_READ(&out->u8_field, &in->u8_field) || + BPF_CORE_READ(&out->s8_field, &in->s8_field) || + BPF_CORE_READ(&out->u16_field, &in->u16_field) || + BPF_CORE_READ(&out->s16_field, &in->s16_field) || + BPF_CORE_READ(&out->u32_field, &in->u32_field) || + BPF_CORE_READ(&out->s32_field, &in->s32_field) || + BPF_CORE_READ(&out->u64_field, &in->u64_field) || + BPF_CORE_READ(&out->s64_field, &in->s64_field)) + return 1; + + return 0; +} + -- GitLab From 29e1c66872450adba0ad552ff6019932168676f3 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 7 Aug 2019 14:40:01 -0700 Subject: [PATCH 2216/7155] selftests/bpf: add CO-RE relocs misc tests Add tests validating few edge-cases of capturing offset relocations. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/core_reloc.c | 19 +++++++ .../bpf/progs/btf__core_reloc_misc.c | 5 ++ .../selftests/bpf/progs/core_reloc_types.h | 25 ++++++++ .../bpf/progs/test_core_reloc_misc.c | 57 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_misc.c create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_misc.c diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 251ef8c518f0..f3863f976a48 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -260,6 +260,25 @@ static struct core_reloc_test_case test_cases[] = { INTS_ERR_CASE(ints___err_wrong_sz_16), INTS_ERR_CASE(ints___err_wrong_sz_32), INTS_ERR_CASE(ints___err_wrong_sz_64), + + /* validate edge cases of capturing relocations */ + { + .case_name = "misc", + .bpf_obj_file = "test_core_reloc_misc.o", + .btf_src_file = "btf__core_reloc_misc.o", + .input = (const char *)&(struct core_reloc_misc_extensible[]){ + { .a = 1 }, + { .a = 2 }, /* not read */ + { .a = 3 }, + }, + .input_len = 4 * sizeof(int), + .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) { + .a = 1, + .b = 1, + .c = 0, /* BUG in clang, should be 3 */ + }, + .output_len = sizeof(struct core_reloc_misc_output), + }, }; struct data { diff --git a/tools/testing/selftests/bpf/progs/btf__core_reloc_misc.c b/tools/testing/selftests/bpf/progs/btf__core_reloc_misc.c new file mode 100644 index 000000000000..ed9ad8b5b4f8 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/btf__core_reloc_misc.c @@ -0,0 +1,5 @@ +#include "core_reloc_types.h" + +void f1(struct core_reloc_misc___a x) {} +void f2(struct core_reloc_misc___b x) {} +void f3(struct core_reloc_misc_extensible x) {} diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 5f3ebd4f6dc3..10a252b6da55 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -640,3 +640,28 @@ struct core_reloc_ints___err_wrong_sz_64 { uint32_t u64_field; /* not 64-bit anymore */ int32_t s64_field; /* not 64-bit anymore */ }; + +/* + * MISC + */ +struct core_reloc_misc_output { + int a, b, c; +}; + +struct core_reloc_misc___a { + int a1; + int a2; +}; + +struct core_reloc_misc___b { + int b1; + int b2; +}; + +/* this one extends core_reloc_misc_extensible struct from BPF prog */ +struct core_reloc_misc_extensible { + int a; + int b; + int c; + int d; +}; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c b/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c new file mode 100644 index 000000000000..c59984bd3e23 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_misc_output { + int a, b, c; +}; + +struct core_reloc_misc___a { + int a1; + int a2; +}; + +struct core_reloc_misc___b { + int b1; + int b2; +}; + +/* fixed two first members, can be extended with new fields */ +struct core_reloc_misc_extensible { + int a; + int b; +}; + +SEC("raw_tracepoint/sys_enter") +int test_core_misc(void *ctx) +{ + struct core_reloc_misc___a *in_a = (void *)&data.in; + struct core_reloc_misc___b *in_b = (void *)&data.in; + struct core_reloc_misc_extensible *in_ext = (void *)&data.in; + struct core_reloc_misc_output *out = (void *)&data.out; + + /* record two different relocations with the same accessor string */ + if (BPF_CORE_READ(&out->a, &in_a->a1) || /* accessor: 0:0 */ + BPF_CORE_READ(&out->b, &in_b->b1)) /* accessor: 0:0 */ + return 1; + + /* Validate relocations capture array-only accesses for structs with + * fixed header, but with potentially extendable tail. This will read + * first 4 bytes of 2nd element of in_ext array of potentially + * variably sized struct core_reloc_misc_extensible. */ + if (BPF_CORE_READ(&out->c, &in_ext[2])) /* accessor: 2 */ + return 1; + + return 0; +} + -- GitLab From b707659213d3c70f2c704ec950df6263b4bffe84 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Wed, 7 Aug 2019 17:38:56 -0700 Subject: [PATCH 2217/7155] tools/bpf: fix core_reloc.c compilation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my local machine, I have the following compilation errors: ===== In file included from prog_tests/core_reloc.c:3:0: ./progs/core_reloc_types.h:517:46: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘fancy_char_ptr_t’ typedef const char * const volatile restrict fancy_char_ptr_t; ^ ./progs/core_reloc_types.h:527:2: error: unknown type name ‘fancy_char_ptr_t’ fancy_char_ptr_t d; ^ ===== I am using gcc 4.8.5. Later compilers may change their behavior not emitting the error. Nevertheless, let us fix the issue. "restrict" can be tested without typedef. Fixes: 9654e2ae908e ("selftests/bpf: add CO-RE relocs modifiers/typedef tests") Cc: Andrii Nakryiko Signed-off-by: Yonghong Song Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/core_reloc_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index 10a252b6da55..f686a8138d90 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -514,7 +514,7 @@ typedef arr1_t arr2_t; typedef arr2_t arr3_t; typedef arr3_t arr4_t; -typedef const char * const volatile restrict fancy_char_ptr_t; +typedef const char * const volatile fancy_char_ptr_t; typedef core_reloc_mods_substruct_t core_reloc_mods_substruct_tt; -- GitLab From b7a2758f20251e1d7f884d96e46ea165810431c3 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 5 Aug 2019 14:49:59 +1000 Subject: [PATCH 2218/7155] hwrng: n2-drv - fix typo Fixes: 3e75241be808 ("hwrng: drivers - Use device-managed registration API") Signed-off-by: Stephen Rothwell Signed-off-by: Herbert Xu --- drivers/char/hw_random/n2-drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 2d256b3470db..73e408146420 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -768,7 +768,7 @@ static int n2rng_probe(struct platform_device *op) np->hwrng.data_read = n2rng_data_read; np->hwrng.priv = (unsigned long) np; - err = devm_hwrng_register(&pdev->dev, &np->hwrng); + err = devm_hwrng_register(&op->dev, &np->hwrng); if (err) goto out_hvapi_unregister; -- GitLab From 71ed79b0e4be0db254640c3beb9a1a0316eb5f61 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 12:15:09 +0200 Subject: [PATCH 2219/7155] USB: Move wusbcore and UWB to staging as it is obsolete The UWB and wusbcore code is long obsolete, so let us just move the code out of the real part of the kernel and into the drivers/staging/ location with plans to remove it entirely in a few releases. Link: https://lore.kernel.org/r/20190806101509.GA11280@kroah.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 15 +++------- drivers/Kconfig | 2 -- drivers/Makefile | 1 - drivers/staging/Kconfig | 3 ++ drivers/staging/Makefile | 2 ++ drivers/{ => staging}/uwb/Kconfig | 0 drivers/{ => staging}/uwb/Makefile | 0 drivers/staging/uwb/TODO | 8 ++++++ drivers/{ => staging}/uwb/address.c | 0 drivers/{ => staging}/uwb/allocator.c | 2 +- drivers/{ => staging}/uwb/beacon.c | 0 drivers/{ => staging}/uwb/driver.c | 0 drivers/{ => staging}/uwb/drp-avail.c | 0 drivers/{ => staging}/uwb/drp-ie.c | 2 +- drivers/{ => staging}/uwb/drp.c | 0 drivers/{ => staging}/uwb/est.c | 0 drivers/{ => staging}/uwb/hwa-rc.c | 6 ++-- drivers/{ => staging}/uwb/i1480/Makefile | 0 drivers/{ => staging}/uwb/i1480/dfu/Makefile | 0 drivers/{ => staging}/uwb/i1480/dfu/dfu.c | 2 +- .../{ => staging}/uwb/i1480/dfu/i1480-dfu.h | 2 +- drivers/{ => staging}/uwb/i1480/dfu/mac.c | 2 +- drivers/{ => staging}/uwb/i1480/dfu/phy.c | 2 +- drivers/{ => staging}/uwb/i1480/dfu/usb.c | 6 ++-- drivers/{ => staging}/uwb/i1480/i1480-est.c | 2 +- drivers/{ => staging}/uwb/ie-rcv.c | 0 drivers/{ => staging}/uwb/ie.c | 0 .../staging/uwb/include}/debug-cmd.h | 0 .../staging/uwb/include}/spec.h | 0 .../uwb => drivers/staging/uwb/include}/umc.h | 0 .../staging/uwb/include}/whci.h | 0 drivers/{ => staging}/uwb/lc-dev.c | 0 drivers/{ => staging}/uwb/lc-rc.c | 0 drivers/{ => staging}/uwb/neh.c | 0 drivers/{ => staging}/uwb/pal.c | 2 +- drivers/{ => staging}/uwb/radio.c | 2 +- drivers/{ => staging}/uwb/reset.c | 0 drivers/{ => staging}/uwb/rsv.c | 2 +- drivers/{ => staging}/uwb/scan.c | 0 drivers/{ => staging}/uwb/umc-bus.c | 2 +- drivers/{ => staging}/uwb/umc-dev.c | 2 +- drivers/{ => staging}/uwb/umc-drv.c | 2 +- drivers/{ => staging}/uwb/uwb-debug.c | 3 +- drivers/{ => staging}/uwb/uwb-internal.h | 2 +- {include/linux => drivers/staging/uwb}/uwb.h | 2 +- drivers/{ => staging}/uwb/uwbd.c | 0 drivers/{ => staging}/uwb/whc-rc.c | 6 ++-- drivers/{ => staging}/uwb/whci.c | 4 +-- .../staging/wusbcore/Documentation}/wusb-cbaf | 0 .../Documentation}/wusb-design-overview.rst | 0 drivers/{usb => staging}/wusbcore/Kconfig | 1 + drivers/{usb => staging}/wusbcore/Makefile | 2 ++ drivers/staging/wusbcore/TODO | 8 ++++++ drivers/{usb => staging}/wusbcore/cbaf.c | 6 ++-- drivers/{usb => staging}/wusbcore/crypto.c | 4 +-- drivers/{usb => staging}/wusbcore/dev-sysfs.c | 0 .../{usb => staging}/wusbcore/devconnect.c | 0 drivers/staging/wusbcore/host/Kconfig | 28 +++++++++++++++++++ drivers/staging/wusbcore/host/Makefile | 3 ++ .../{usb => staging/wusbcore}/host/hwa-hc.c | 4 +-- .../wusbcore}/host/whci/Makefile | 0 .../{usb => staging/wusbcore}/host/whci/asl.c | 4 +-- .../wusbcore}/host/whci/debug.c | 2 +- .../{usb => staging/wusbcore}/host/whci/hcd.c | 4 +-- .../{usb => staging/wusbcore}/host/whci/hw.c | 4 +-- .../wusbcore}/host/whci/init.c | 4 +-- .../{usb => staging/wusbcore}/host/whci/int.c | 4 +-- .../{usb => staging/wusbcore}/host/whci/pzl.c | 4 +-- .../wusbcore}/host/whci/qset.c | 4 +-- .../wusbcore}/host/whci/whcd.h | 4 +-- .../wusbcore}/host/whci/whci-hc.h | 0 .../wusbcore}/host/whci/wusb.c | 4 +-- .../staging/wusbcore/include}/association.h | 0 .../staging/wusbcore/include}/wusb-wa.h | 0 .../staging/wusbcore/include}/wusb.h | 2 +- drivers/{usb => staging}/wusbcore/mmc.c | 2 +- drivers/{usb => staging}/wusbcore/pal.c | 0 .../{usb => staging}/wusbcore/reservation.c | 2 +- drivers/{usb => staging}/wusbcore/rh.c | 0 drivers/{usb => staging}/wusbcore/security.c | 0 drivers/{usb => staging}/wusbcore/wa-hc.c | 0 drivers/{usb => staging}/wusbcore/wa-hc.h | 6 ++-- drivers/{usb => staging}/wusbcore/wa-nep.c | 0 drivers/{usb => staging}/wusbcore/wa-rpipe.c | 0 drivers/{usb => staging}/wusbcore/wa-xfer.c | 0 drivers/{usb => staging}/wusbcore/wusbhc.c | 0 drivers/{usb => staging}/wusbcore/wusbhc.h | 4 +-- drivers/usb/Kconfig | 2 -- drivers/usb/Makefile | 2 -- drivers/usb/host/Kconfig | 26 ----------------- drivers/usb/host/Makefile | 3 -- 91 files changed, 120 insertions(+), 109 deletions(-) rename drivers/{ => staging}/uwb/Kconfig (100%) rename drivers/{ => staging}/uwb/Makefile (100%) create mode 100644 drivers/staging/uwb/TODO rename drivers/{ => staging}/uwb/address.c (100%) rename drivers/{ => staging}/uwb/allocator.c (99%) rename drivers/{ => staging}/uwb/beacon.c (100%) rename drivers/{ => staging}/uwb/driver.c (100%) rename drivers/{ => staging}/uwb/drp-avail.c (100%) rename drivers/{ => staging}/uwb/drp-ie.c (99%) rename drivers/{ => staging}/uwb/drp.c (100%) rename drivers/{ => staging}/uwb/est.c (100%) rename drivers/{ => staging}/uwb/hwa-rc.c (99%) rename drivers/{ => staging}/uwb/i1480/Makefile (100%) rename drivers/{ => staging}/uwb/i1480/dfu/Makefile (100%) rename drivers/{ => staging}/uwb/i1480/dfu/dfu.c (99%) rename drivers/{ => staging}/uwb/i1480/dfu/i1480-dfu.h (99%) rename drivers/{ => staging}/uwb/i1480/dfu/mac.c (99%) rename drivers/{ => staging}/uwb/i1480/dfu/phy.c (99%) rename drivers/{ => staging}/uwb/i1480/dfu/usb.c (99%) rename drivers/{ => staging}/uwb/i1480/i1480-est.c (99%) rename drivers/{ => staging}/uwb/ie-rcv.c (100%) rename drivers/{ => staging}/uwb/ie.c (100%) rename {include/linux/uwb => drivers/staging/uwb/include}/debug-cmd.h (100%) rename {include/linux/uwb => drivers/staging/uwb/include}/spec.h (100%) rename {include/linux/uwb => drivers/staging/uwb/include}/umc.h (100%) rename {include/linux/uwb => drivers/staging/uwb/include}/whci.h (100%) rename drivers/{ => staging}/uwb/lc-dev.c (100%) rename drivers/{ => staging}/uwb/lc-rc.c (100%) rename drivers/{ => staging}/uwb/neh.c (100%) rename drivers/{ => staging}/uwb/pal.c (99%) rename drivers/{ => staging}/uwb/radio.c (99%) rename drivers/{ => staging}/uwb/reset.c (100%) rename drivers/{ => staging}/uwb/rsv.c (99%) rename drivers/{ => staging}/uwb/scan.c (100%) rename drivers/{ => staging}/uwb/umc-bus.c (99%) rename drivers/{ => staging}/uwb/umc-dev.c (98%) rename drivers/{ => staging}/uwb/umc-drv.c (96%) rename drivers/{ => staging}/uwb/uwb-debug.c (99%) rename drivers/{ => staging}/uwb/uwb-internal.h (99%) rename {include/linux => drivers/staging/uwb}/uwb.h (99%) rename drivers/{ => staging}/uwb/uwbd.c (100%) rename drivers/{ => staging}/uwb/whc-rc.c (99%) rename drivers/{ => staging}/uwb/whci.c (99%) rename {Documentation/usb => drivers/staging/wusbcore/Documentation}/wusb-cbaf (100%) rename {Documentation/usb => drivers/staging/wusbcore/Documentation}/wusb-design-overview.rst (100%) rename drivers/{usb => staging}/wusbcore/Kconfig (95%) rename drivers/{usb => staging}/wusbcore/Makefile (96%) create mode 100644 drivers/staging/wusbcore/TODO rename drivers/{usb => staging}/wusbcore/cbaf.c (99%) rename drivers/{usb => staging}/wusbcore/crypto.c (99%) rename drivers/{usb => staging}/wusbcore/dev-sysfs.c (100%) rename drivers/{usb => staging}/wusbcore/devconnect.c (100%) create mode 100644 drivers/staging/wusbcore/host/Kconfig create mode 100644 drivers/staging/wusbcore/host/Makefile rename drivers/{usb => staging/wusbcore}/host/hwa-hc.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/Makefile (100%) rename drivers/{usb => staging/wusbcore}/host/whci/asl.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/debug.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/hcd.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/hw.c (97%) rename drivers/{usb => staging/wusbcore}/host/whci/init.c (98%) rename drivers/{usb => staging/wusbcore}/host/whci/int.c (96%) rename drivers/{usb => staging/wusbcore}/host/whci/pzl.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/qset.c (99%) rename drivers/{usb => staging/wusbcore}/host/whci/whcd.h (98%) rename drivers/{usb => staging/wusbcore}/host/whci/whci-hc.h (100%) rename drivers/{usb => staging/wusbcore}/host/whci/wusb.c (98%) rename {include/linux/usb => drivers/staging/wusbcore/include}/association.h (100%) rename {include/linux/usb => drivers/staging/wusbcore/include}/wusb-wa.h (100%) rename {include/linux/usb => drivers/staging/wusbcore/include}/wusb.h (99%) rename drivers/{usb => staging}/wusbcore/mmc.c (99%) rename drivers/{usb => staging}/wusbcore/pal.c (100%) rename drivers/{usb => staging}/wusbcore/reservation.c (99%) rename drivers/{usb => staging}/wusbcore/rh.c (100%) rename drivers/{usb => staging}/wusbcore/security.c (100%) rename drivers/{usb => staging}/wusbcore/wa-hc.c (100%) rename drivers/{usb => staging}/wusbcore/wa-hc.h (99%) rename drivers/{usb => staging}/wusbcore/wa-nep.c (100%) rename drivers/{usb => staging}/wusbcore/wa-rpipe.c (100%) rename drivers/{usb => staging}/wusbcore/wa-xfer.c (100%) rename drivers/{usb => staging}/wusbcore/wusbhc.c (100%) rename drivers/{usb => staging}/wusbcore/wusbhc.h (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 6426db5198f0..f4463fb48249 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3800,14 +3800,9 @@ F: scripts/sign-file.c F: scripts/extract-cert.c CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: -L: linux-usb@vger.kernel.org +L: devel@driverdev.osuosl.org S: Orphan -F: Documentation/usb/wusb-design-overview.rst -F: Documentation/usb/wusb-cbaf -F: drivers/usb/host/hwa-hc.c -F: drivers/usb/host/whci/ -F: drivers/usb/wusbcore/ -F: include/linux/usb/wusb* +F: drivers/staging/wbusbcore/ CFAG12864B LCD DRIVER M: Miguel Ojeda Sandonis @@ -16447,11 +16442,9 @@ F: drivers/usb/common/ulpi.c F: include/linux/ulpi/ ULTRA-WIDEBAND (UWB) SUBSYSTEM: -L: linux-usb@vger.kernel.org +L: devel@driverdev.osuosl.org S: Orphan -F: drivers/uwb/ -F: include/linux/uwb.h -F: include/linux/uwb/ +F: drivers/staging/uwb/ UNICODE SUBSYSTEM: M: Gabriel Krisman Bertazi diff --git a/drivers/Kconfig b/drivers/Kconfig index 61cf4ea2c229..e8852c09184b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -108,8 +108,6 @@ source "drivers/hid/Kconfig" source "drivers/usb/Kconfig" -source "drivers/uwb/Kconfig" - source "drivers/mmc/Kconfig" source "drivers/memstick/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 6d37564e783c..cf046e9bd88c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -100,7 +100,6 @@ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ -obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_PHY) += usb/ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_USB_SUPPORT) += usb/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7c96a01eef6c..cf419d9c942d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -120,4 +120,7 @@ source "drivers/staging/kpc2000/Kconfig" source "drivers/staging/isdn/Kconfig" +source "drivers/staging/wusbcore/Kconfig" +source "drivers/staging/uwb/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fcaac9693b83..38179bc842a8 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -50,3 +50,5 @@ obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ +obj-$(CONFIG_UWB) += uwb/ +obj-$(CONFIG_USB_WUSB) += wusbcore/ diff --git a/drivers/uwb/Kconfig b/drivers/staging/uwb/Kconfig similarity index 100% rename from drivers/uwb/Kconfig rename to drivers/staging/uwb/Kconfig diff --git a/drivers/uwb/Makefile b/drivers/staging/uwb/Makefile similarity index 100% rename from drivers/uwb/Makefile rename to drivers/staging/uwb/Makefile diff --git a/drivers/staging/uwb/TODO b/drivers/staging/uwb/TODO new file mode 100644 index 000000000000..abae57000534 --- /dev/null +++ b/drivers/staging/uwb/TODO @@ -0,0 +1,8 @@ +TODO: Remove in late 2019 unless there are users + +There seems to not be any real wireless USB devices anywhere in the wild +anymore. It turned out to be a failed technology :( + +This will be removed from the tree if no one objects. + +Greg Kroah-Hartman diff --git a/drivers/uwb/address.c b/drivers/staging/uwb/address.c similarity index 100% rename from drivers/uwb/address.c rename to drivers/staging/uwb/address.c diff --git a/drivers/uwb/allocator.c b/drivers/staging/uwb/allocator.c similarity index 99% rename from drivers/uwb/allocator.c rename to drivers/staging/uwb/allocator.c index 2e1590124d5f..1f429fba20b7 100644 --- a/drivers/uwb/allocator.c +++ b/drivers/staging/uwb/allocator.c @@ -6,7 +6,7 @@ */ #include #include -#include +#include "uwb.h" #include "uwb-internal.h" diff --git a/drivers/uwb/beacon.c b/drivers/staging/uwb/beacon.c similarity index 100% rename from drivers/uwb/beacon.c rename to drivers/staging/uwb/beacon.c diff --git a/drivers/uwb/driver.c b/drivers/staging/uwb/driver.c similarity index 100% rename from drivers/uwb/driver.c rename to drivers/staging/uwb/driver.c diff --git a/drivers/uwb/drp-avail.c b/drivers/staging/uwb/drp-avail.c similarity index 100% rename from drivers/uwb/drp-avail.c rename to drivers/staging/uwb/drp-avail.c diff --git a/drivers/uwb/drp-ie.c b/drivers/staging/uwb/drp-ie.c similarity index 99% rename from drivers/uwb/drp-ie.c rename to drivers/staging/uwb/drp-ie.c index 4b545b41161c..b2a862cf76de 100644 --- a/drivers/uwb/drp-ie.c +++ b/drivers/staging/uwb/drp-ie.c @@ -8,8 +8,8 @@ #include #include #include -#include +#include "uwb.h" #include "uwb-internal.h" diff --git a/drivers/uwb/drp.c b/drivers/staging/uwb/drp.c similarity index 100% rename from drivers/uwb/drp.c rename to drivers/staging/uwb/drp.c diff --git a/drivers/uwb/est.c b/drivers/staging/uwb/est.c similarity index 100% rename from drivers/uwb/est.c rename to drivers/staging/uwb/est.c diff --git a/drivers/uwb/hwa-rc.c b/drivers/staging/uwb/hwa-rc.c similarity index 99% rename from drivers/uwb/hwa-rc.c rename to drivers/staging/uwb/hwa-rc.c index cd03b7f827c1..b6effad749d7 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/staging/uwb/hwa-rc.c @@ -38,9 +38,9 @@ #include #include #include -#include -#include -#include +#include "../wusbcore/include/wusb.h" +#include "../wusbcore/include/wusb-wa.h" +#include "uwb.h" #include "uwb-internal.h" diff --git a/drivers/uwb/i1480/Makefile b/drivers/staging/uwb/i1480/Makefile similarity index 100% rename from drivers/uwb/i1480/Makefile rename to drivers/staging/uwb/i1480/Makefile diff --git a/drivers/uwb/i1480/dfu/Makefile b/drivers/staging/uwb/i1480/dfu/Makefile similarity index 100% rename from drivers/uwb/i1480/dfu/Makefile rename to drivers/staging/uwb/i1480/dfu/Makefile diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/staging/uwb/i1480/dfu/dfu.c similarity index 99% rename from drivers/uwb/i1480/dfu/dfu.c rename to drivers/staging/uwb/i1480/dfu/dfu.c index ec1af858ead9..9d51ce8faad1 100644 --- a/drivers/uwb/i1480/dfu/dfu.c +++ b/drivers/staging/uwb/i1480/dfu/dfu.c @@ -17,9 +17,9 @@ #include #include #include -#include #include #include +#include "../../uwb.h" /* * i1480_rceb_check - Check RCEB for expected field values diff --git a/drivers/uwb/i1480/dfu/i1480-dfu.h b/drivers/staging/uwb/i1480/dfu/i1480-dfu.h similarity index 99% rename from drivers/uwb/i1480/dfu/i1480-dfu.h rename to drivers/staging/uwb/i1480/dfu/i1480-dfu.h index 9dd567d174b3..b21d058ecc23 100644 --- a/drivers/uwb/i1480/dfu/i1480-dfu.h +++ b/drivers/staging/uwb/i1480/dfu/i1480-dfu.h @@ -50,9 +50,9 @@ #ifndef __i1480_DFU_H__ #define __i1480_DFU_H__ -#include #include #include +#include "../../include/spec.h" #define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) diff --git a/drivers/uwb/i1480/dfu/mac.c b/drivers/staging/uwb/i1480/dfu/mac.c similarity index 99% rename from drivers/uwb/i1480/dfu/mac.c rename to drivers/staging/uwb/i1480/dfu/mac.c index ddc224f01a7f..6e4d6c9cecf5 100644 --- a/drivers/uwb/i1480/dfu/mac.c +++ b/drivers/staging/uwb/i1480/dfu/mac.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "../../uwb.h" #include "i1480-dfu.h" /* diff --git a/drivers/uwb/i1480/dfu/phy.c b/drivers/staging/uwb/i1480/dfu/phy.c similarity index 99% rename from drivers/uwb/i1480/dfu/phy.c rename to drivers/staging/uwb/i1480/dfu/phy.c index 50da4527c113..13512c7dda0b 100644 --- a/drivers/uwb/i1480/dfu/phy.c +++ b/drivers/staging/uwb/i1480/dfu/phy.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "../../../wusbcore/include/wusb.h" #include "i1480-dfu.h" diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/staging/uwb/i1480/dfu/usb.c similarity index 99% rename from drivers/uwb/i1480/dfu/usb.c rename to drivers/staging/uwb/i1480/dfu/usb.c index 6129a8f4b5f2..d41086bdd783 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/staging/uwb/i1480/dfu/usb.c @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include "../../uwb.h" +#include "../../../wusbcore/include/wusb.h" +#include "../../../wusbcore/include/wusb-wa.h" #include "i1480-dfu.h" struct i1480_usb { diff --git a/drivers/uwb/i1480/i1480-est.c b/drivers/staging/uwb/i1480/i1480-est.c similarity index 99% rename from drivers/uwb/i1480/i1480-est.c rename to drivers/staging/uwb/i1480/i1480-est.c index 1346c409d10e..106e0a44b138 100644 --- a/drivers/uwb/i1480/i1480-est.c +++ b/drivers/staging/uwb/i1480/i1480-est.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include "../uwb.h" #include "dfu/i1480-dfu.h" diff --git a/drivers/uwb/ie-rcv.c b/drivers/staging/uwb/ie-rcv.c similarity index 100% rename from drivers/uwb/ie-rcv.c rename to drivers/staging/uwb/ie-rcv.c diff --git a/drivers/uwb/ie.c b/drivers/staging/uwb/ie.c similarity index 100% rename from drivers/uwb/ie.c rename to drivers/staging/uwb/ie.c diff --git a/include/linux/uwb/debug-cmd.h b/drivers/staging/uwb/include/debug-cmd.h similarity index 100% rename from include/linux/uwb/debug-cmd.h rename to drivers/staging/uwb/include/debug-cmd.h diff --git a/include/linux/uwb/spec.h b/drivers/staging/uwb/include/spec.h similarity index 100% rename from include/linux/uwb/spec.h rename to drivers/staging/uwb/include/spec.h diff --git a/include/linux/uwb/umc.h b/drivers/staging/uwb/include/umc.h similarity index 100% rename from include/linux/uwb/umc.h rename to drivers/staging/uwb/include/umc.h diff --git a/include/linux/uwb/whci.h b/drivers/staging/uwb/include/whci.h similarity index 100% rename from include/linux/uwb/whci.h rename to drivers/staging/uwb/include/whci.h diff --git a/drivers/uwb/lc-dev.c b/drivers/staging/uwb/lc-dev.c similarity index 100% rename from drivers/uwb/lc-dev.c rename to drivers/staging/uwb/lc-dev.c diff --git a/drivers/uwb/lc-rc.c b/drivers/staging/uwb/lc-rc.c similarity index 100% rename from drivers/uwb/lc-rc.c rename to drivers/staging/uwb/lc-rc.c diff --git a/drivers/uwb/neh.c b/drivers/staging/uwb/neh.c similarity index 100% rename from drivers/uwb/neh.c rename to drivers/staging/uwb/neh.c diff --git a/drivers/uwb/pal.c b/drivers/staging/uwb/pal.c similarity index 99% rename from drivers/uwb/pal.c rename to drivers/staging/uwb/pal.c index 765fd426dbd1..a541e646a603 100644 --- a/drivers/uwb/pal.c +++ b/drivers/staging/uwb/pal.c @@ -6,9 +6,9 @@ */ #include #include -#include #include +#include "uwb.h" #include "uwb-internal.h" /** diff --git a/drivers/uwb/radio.c b/drivers/staging/uwb/radio.c similarity index 99% rename from drivers/uwb/radio.c rename to drivers/staging/uwb/radio.c index 240dd755927e..6afb75ce1b5f 100644 --- a/drivers/uwb/radio.c +++ b/drivers/staging/uwb/radio.c @@ -5,9 +5,9 @@ * Copyright (C) 2008 Cambridge Silicon Radio Ltd. */ #include -#include #include +#include "uwb.h" #include "uwb-internal.h" diff --git a/drivers/uwb/reset.c b/drivers/staging/uwb/reset.c similarity index 100% rename from drivers/uwb/reset.c rename to drivers/staging/uwb/reset.c diff --git a/drivers/uwb/rsv.c b/drivers/staging/uwb/rsv.c similarity index 99% rename from drivers/uwb/rsv.c rename to drivers/staging/uwb/rsv.c index ec924deb0a32..f45a04ff7275 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/staging/uwb/rsv.c @@ -5,11 +5,11 @@ * Copyright (C) 2008 Cambridge Silicon Radio Ltd. */ #include -#include #include #include #include +#include "uwb.h" #include "uwb-internal.h" static void uwb_rsv_timer(struct timer_list *t); diff --git a/drivers/uwb/scan.c b/drivers/staging/uwb/scan.c similarity index 100% rename from drivers/uwb/scan.c rename to drivers/staging/uwb/scan.c diff --git a/drivers/uwb/umc-bus.c b/drivers/staging/uwb/umc-bus.c similarity index 99% rename from drivers/uwb/umc-bus.c rename to drivers/staging/uwb/umc-bus.c index 0fdc38078eee..8b931f66a720 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/staging/uwb/umc-bus.c @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include "include/umc.h" static int umc_bus_pre_reset_helper(struct device *dev, void *data) { diff --git a/drivers/uwb/umc-dev.c b/drivers/staging/uwb/umc-dev.c similarity index 98% rename from drivers/uwb/umc-dev.c rename to drivers/staging/uwb/umc-dev.c index c845ca414bb2..0c71caae00be 100644 --- a/drivers/uwb/umc-dev.c +++ b/drivers/staging/uwb/umc-dev.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include "include/umc.h" static void umc_device_release(struct device *dev) { diff --git a/drivers/uwb/umc-drv.c b/drivers/staging/uwb/umc-drv.c similarity index 96% rename from drivers/uwb/umc-drv.c rename to drivers/staging/uwb/umc-drv.c index b141d520efbf..ed3bd220e8c2 100644 --- a/drivers/uwb/umc-drv.c +++ b/drivers/staging/uwb/umc-drv.c @@ -6,7 +6,7 @@ */ #include #include -#include +#include "include/umc.h" int __umc_driver_register(struct umc_driver *umc_drv, struct module *module, const char *mod_name) diff --git a/drivers/uwb/uwb-debug.c b/drivers/staging/uwb/uwb-debug.c similarity index 99% rename from drivers/uwb/uwb-debug.c rename to drivers/staging/uwb/uwb-debug.c index 5457b6d42387..dd14df219ef8 100644 --- a/drivers/uwb/uwb-debug.c +++ b/drivers/staging/uwb/uwb-debug.c @@ -19,8 +19,7 @@ #include #include -#include - +#include "include/debug-cmd.h" #include "uwb-internal.h" /* diff --git a/drivers/uwb/uwb-internal.h b/drivers/staging/uwb/uwb-internal.h similarity index 99% rename from drivers/uwb/uwb-internal.h rename to drivers/staging/uwb/uwb-internal.h index 00de0a5333d2..4c2fdac7f610 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/staging/uwb/uwb-internal.h @@ -17,8 +17,8 @@ #include #include -#include #include +#include "uwb.h" struct uwb_beca_e; diff --git a/include/linux/uwb.h b/drivers/staging/uwb/uwb.h similarity index 99% rename from include/linux/uwb.h rename to drivers/staging/uwb/uwb.h index 6918a61e1ac1..6a59706ba3a0 100644 --- a/include/linux/uwb.h +++ b/drivers/staging/uwb/uwb.h @@ -18,8 +18,8 @@ #include #include #include -#include #include +#include "include/spec.h" struct uwb_dev; struct uwb_beca_e; diff --git a/drivers/uwb/uwbd.c b/drivers/staging/uwb/uwbd.c similarity index 100% rename from drivers/uwb/uwbd.c rename to drivers/staging/uwb/uwbd.c diff --git a/drivers/uwb/whc-rc.c b/drivers/staging/uwb/whc-rc.c similarity index 99% rename from drivers/uwb/whc-rc.c rename to drivers/staging/uwb/whc-rc.c index 22397f70dee2..34020ed351ab 100644 --- a/drivers/uwb/whc-rc.c +++ b/drivers/staging/uwb/whc-rc.c @@ -33,9 +33,9 @@ #include #include #include -#include -#include -#include +#include "uwb.h" +#include "include/whci.h" +#include "include/umc.h" #include "uwb-internal.h" diff --git a/drivers/uwb/whci.c b/drivers/staging/uwb/whci.c similarity index 99% rename from drivers/uwb/whci.c rename to drivers/staging/uwb/whci.c index be8a8b8e857b..a8832f64d708 100644 --- a/drivers/uwb/whci.c +++ b/drivers/staging/uwb/whci.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include "include/whci.h" +#include "include/umc.h" struct whci_card { struct pci_dev *pci; diff --git a/Documentation/usb/wusb-cbaf b/drivers/staging/wusbcore/Documentation/wusb-cbaf similarity index 100% rename from Documentation/usb/wusb-cbaf rename to drivers/staging/wusbcore/Documentation/wusb-cbaf diff --git a/Documentation/usb/wusb-design-overview.rst b/drivers/staging/wusbcore/Documentation/wusb-design-overview.rst similarity index 100% rename from Documentation/usb/wusb-design-overview.rst rename to drivers/staging/wusbcore/Documentation/wusb-design-overview.rst diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/staging/wusbcore/Kconfig similarity index 95% rename from drivers/usb/wusbcore/Kconfig rename to drivers/staging/wusbcore/Kconfig index abc0f361021f..056c60b4d57f 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/staging/wusbcore/Kconfig @@ -36,3 +36,4 @@ config USB_WUSB_CBAF_DEBUG to the system log. Select this if you are having a problem with CBA support and want to see more of what is going on. +source "drivers/staging/wusbcore/host/Kconfig" diff --git a/drivers/usb/wusbcore/Makefile b/drivers/staging/wusbcore/Makefile similarity index 96% rename from drivers/usb/wusbcore/Makefile rename to drivers/staging/wusbcore/Makefile index d604ccdd916f..b47b874268ac 100644 --- a/drivers/usb/wusbcore/Makefile +++ b/drivers/staging/wusbcore/Makefile @@ -24,3 +24,5 @@ wusb-wa-y := \ wa-nep.o \ wa-rpipe.o \ wa-xfer.o + +obj-y += host/ diff --git a/drivers/staging/wusbcore/TODO b/drivers/staging/wusbcore/TODO new file mode 100644 index 000000000000..abae57000534 --- /dev/null +++ b/drivers/staging/wusbcore/TODO @@ -0,0 +1,8 @@ +TODO: Remove in late 2019 unless there are users + +There seems to not be any real wireless USB devices anywhere in the wild +anymore. It turned out to be a failed technology :( + +This will be removed from the tree if no one objects. + +Greg Kroah-Hartman diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/staging/wusbcore/cbaf.c similarity index 99% rename from drivers/usb/wusbcore/cbaf.c rename to drivers/staging/wusbcore/cbaf.c index af77064c7456..57062eaf7558 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/staging/wusbcore/cbaf.c @@ -80,9 +80,9 @@ #include #include #include -#include -#include -#include +#include "../uwb/uwb.h" +#include "include/wusb.h" +#include "include/association.h" #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */ diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/staging/wusbcore/crypto.c similarity index 99% rename from drivers/usb/wusbcore/crypto.c rename to drivers/staging/wusbcore/crypto.c index 9ee66483ee54..d7d55ed19a98 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/staging/wusbcore/crypto.c @@ -38,10 +38,10 @@ #include #include #include -#include #include -#include #include +#include "../uwb/uwb.h" +#include "include/wusb.h" static int debug_crypto_verify; diff --git a/drivers/usb/wusbcore/dev-sysfs.c b/drivers/staging/wusbcore/dev-sysfs.c similarity index 100% rename from drivers/usb/wusbcore/dev-sysfs.c rename to drivers/staging/wusbcore/dev-sysfs.c diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/staging/wusbcore/devconnect.c similarity index 100% rename from drivers/usb/wusbcore/devconnect.c rename to drivers/staging/wusbcore/devconnect.c diff --git a/drivers/staging/wusbcore/host/Kconfig b/drivers/staging/wusbcore/host/Kconfig new file mode 100644 index 000000000000..9a73f9360a08 --- /dev/null +++ b/drivers/staging/wusbcore/host/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 + +config USB_WHCI_HCD + tristate "Wireless USB Host Controller Interface (WHCI) driver" + depends on USB_PCI && USB && UWB + select USB_WUSB + select UWB_WHCI + help + A driver for PCI-based Wireless USB Host Controllers that are + compliant with the WHCI specification. + + To compile this driver a module, choose M here: the module + will be called "whci-hcd". + +config USB_HWA_HCD + tristate "Host Wire Adapter (HWA) driver" + depends on USB && UWB + select USB_WUSB + select UWB_HWA + help + This driver enables you to connect Wireless USB devices to + your system using a Host Wire Adaptor USB dongle. This is an + UWB Radio Controller and WUSB Host Controller connected to + your machine via USB (specified in WUSB1.0). + + To compile this driver a module, choose M here: the module + will be called "hwa-hc". + diff --git a/drivers/staging/wusbcore/host/Makefile b/drivers/staging/wusbcore/host/Makefile new file mode 100644 index 000000000000..d65ee8a73e21 --- /dev/null +++ b/drivers/staging/wusbcore/host/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_USB_WHCI_HCD) += whci/ +obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o diff --git a/drivers/usb/host/hwa-hc.c b/drivers/staging/wusbcore/host/hwa-hc.c similarity index 99% rename from drivers/usb/host/hwa-hc.c rename to drivers/staging/wusbcore/host/hwa-hc.c index 6968b9f2b76b..8d959e91fe27 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/staging/wusbcore/host/hwa-hc.c @@ -45,8 +45,8 @@ #include #include #include -#include "../wusbcore/wa-hc.h" -#include "../wusbcore/wusbhc.h" +#include "../wa-hc.h" +#include "../wusbhc.h" struct hwahc { struct wusbhc wusbhc; /* has to be 1st */ diff --git a/drivers/usb/host/whci/Makefile b/drivers/staging/wusbcore/host/whci/Makefile similarity index 100% rename from drivers/usb/host/whci/Makefile rename to drivers/staging/wusbcore/host/whci/Makefile diff --git a/drivers/usb/host/whci/asl.c b/drivers/staging/wusbcore/host/whci/asl.c similarity index 99% rename from drivers/usb/host/whci/asl.c rename to drivers/staging/wusbcore/host/whci/asl.c index 276fb34c8efd..a2b9a50cfb80 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/staging/wusbcore/host/whci/asl.c @@ -7,10 +7,10 @@ #include #include #include -#include #include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/debug.c b/drivers/staging/wusbcore/host/whci/debug.c similarity index 99% rename from drivers/usb/host/whci/debug.c rename to drivers/staging/wusbcore/host/whci/debug.c index 8ddfe3f1f693..443da6719147 100644 --- a/drivers/usb/host/whci/debug.c +++ b/drivers/staging/wusbcore/host/whci/debug.c @@ -10,7 +10,7 @@ #include #include -#include "../../wusbcore/wusbhc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/hcd.c b/drivers/staging/wusbcore/host/whci/hcd.c similarity index 99% rename from drivers/usb/host/whci/hcd.c rename to drivers/staging/wusbcore/host/whci/hcd.c index 8af9dcfea127..bee1ff2d35be 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/staging/wusbcore/host/whci/hcd.c @@ -7,9 +7,9 @@ #include #include #include -#include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/hw.c b/drivers/staging/wusbcore/host/whci/hw.c similarity index 97% rename from drivers/usb/host/whci/hw.c rename to drivers/staging/wusbcore/host/whci/hw.c index 22b3b7f7419d..e4e8914abf42 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/staging/wusbcore/host/whci/hw.c @@ -6,9 +6,9 @@ */ #include #include -#include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/init.c b/drivers/staging/wusbcore/host/whci/init.c similarity index 98% rename from drivers/usb/host/whci/init.c rename to drivers/staging/wusbcore/host/whci/init.c index 82416973f773..55fd458a8f30 100644 --- a/drivers/usb/host/whci/init.c +++ b/drivers/staging/wusbcore/host/whci/init.c @@ -7,9 +7,9 @@ #include #include #include -#include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/int.c b/drivers/staging/wusbcore/host/whci/int.c similarity index 96% rename from drivers/usb/host/whci/int.c rename to drivers/staging/wusbcore/host/whci/int.c index 7e4ad1b8f3e3..bdbe35e9366f 100644 --- a/drivers/usb/host/whci/int.c +++ b/drivers/staging/wusbcore/host/whci/int.c @@ -5,9 +5,9 @@ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. */ #include -#include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/pzl.c b/drivers/staging/wusbcore/host/whci/pzl.c similarity index 99% rename from drivers/usb/host/whci/pzl.c rename to drivers/staging/wusbcore/host/whci/pzl.c index ef52aeb02fde..6dfc075f5798 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/staging/wusbcore/host/whci/pzl.c @@ -7,10 +7,10 @@ #include #include #include -#include #include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/qset.c b/drivers/staging/wusbcore/host/whci/qset.c similarity index 99% rename from drivers/usb/host/whci/qset.c rename to drivers/staging/wusbcore/host/whci/qset.c index 925166a207aa..66459b77dc77 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/staging/wusbcore/host/whci/qset.c @@ -7,10 +7,10 @@ #include #include #include -#include #include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/drivers/usb/host/whci/whcd.h b/drivers/staging/wusbcore/host/whci/whcd.h similarity index 98% rename from drivers/usb/host/whci/whcd.h rename to drivers/staging/wusbcore/host/whci/whcd.h index 139476997e7c..a442a2589e83 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/staging/wusbcore/host/whci/whcd.h @@ -7,10 +7,10 @@ #ifndef __WHCD_H #define __WHCD_H -#include -#include #include +#include "../../../uwb/include/whci.h" +#include "../../../uwb/include/umc.h" #include "whci-hc.h" /* Generic command timeout. */ diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/staging/wusbcore/host/whci/whci-hc.h similarity index 100% rename from drivers/usb/host/whci/whci-hc.h rename to drivers/staging/wusbcore/host/whci/whci-hc.h diff --git a/drivers/usb/host/whci/wusb.c b/drivers/staging/wusbcore/host/whci/wusb.c similarity index 98% rename from drivers/usb/host/whci/wusb.c rename to drivers/staging/wusbcore/host/whci/wusb.c index 8a4d805ff63a..6d0068ab35e4 100644 --- a/drivers/usb/host/whci/wusb.c +++ b/drivers/staging/wusbcore/host/whci/wusb.c @@ -5,9 +5,9 @@ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. */ #include -#include -#include "../../wusbcore/wusbhc.h" +#include "../../../uwb/include/umc.h" +#include "../../wusbhc.h" #include "whcd.h" diff --git a/include/linux/usb/association.h b/drivers/staging/wusbcore/include/association.h similarity index 100% rename from include/linux/usb/association.h rename to drivers/staging/wusbcore/include/association.h diff --git a/include/linux/usb/wusb-wa.h b/drivers/staging/wusbcore/include/wusb-wa.h similarity index 100% rename from include/linux/usb/wusb-wa.h rename to drivers/staging/wusbcore/include/wusb-wa.h diff --git a/include/linux/usb/wusb.h b/drivers/staging/wusbcore/include/wusb.h similarity index 99% rename from include/linux/usb/wusb.h rename to drivers/staging/wusbcore/include/wusb.h index 65adee629106..09771d1da7bc 100644 --- a/include/linux/usb/wusb.h +++ b/drivers/staging/wusbcore/include/wusb.h @@ -33,9 +33,9 @@ #include #include -#include #include #include +#include "../../uwb/include/spec.h" /** * WUSB Information Element header diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/staging/wusbcore/mmc.c similarity index 99% rename from drivers/usb/wusbcore/mmc.c rename to drivers/staging/wusbcore/mmc.c index acce0d551eb2..881e1f20d718 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/staging/wusbcore/mmc.c @@ -22,9 +22,9 @@ * FIXME: * - add timers that autoremove intervalled IEs? */ -#include #include #include +#include "include/wusb.h" #include "wusbhc.h" /* Initialize the MMCIEs handling mechanism */ diff --git a/drivers/usb/wusbcore/pal.c b/drivers/staging/wusbcore/pal.c similarity index 100% rename from drivers/usb/wusbcore/pal.c rename to drivers/staging/wusbcore/pal.c diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/staging/wusbcore/reservation.c similarity index 99% rename from drivers/usb/wusbcore/reservation.c rename to drivers/staging/wusbcore/reservation.c index 6dcfc6825f55..b921faac698b 100644 --- a/drivers/usb/wusbcore/reservation.c +++ b/drivers/staging/wusbcore/reservation.c @@ -5,8 +5,8 @@ * Copyright (C) 2007 Cambridge Silicon Radio Ltd. */ #include -#include +#include "../uwb/uwb.h" #include "wusbhc.h" /* diff --git a/drivers/usb/wusbcore/rh.c b/drivers/staging/wusbcore/rh.c similarity index 100% rename from drivers/usb/wusbcore/rh.c rename to drivers/staging/wusbcore/rh.c diff --git a/drivers/usb/wusbcore/security.c b/drivers/staging/wusbcore/security.c similarity index 100% rename from drivers/usb/wusbcore/security.c rename to drivers/staging/wusbcore/security.c diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/staging/wusbcore/wa-hc.c similarity index 100% rename from drivers/usb/wusbcore/wa-hc.c rename to drivers/staging/wusbcore/wa-hc.c diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/staging/wusbcore/wa-hc.h similarity index 99% rename from drivers/usb/wusbcore/wa-hc.h rename to drivers/staging/wusbcore/wa-hc.h index ec90fff21deb..5a38465724c2 100644 --- a/drivers/usb/wusbcore/wa-hc.h +++ b/drivers/staging/wusbcore/wa-hc.h @@ -70,9 +70,9 @@ #include #include #include -#include -#include -#include +#include "../uwb/uwb.h" +#include "include/wusb.h" +#include "include/wusb-wa.h" struct wusbhc; struct wahc; diff --git a/drivers/usb/wusbcore/wa-nep.c b/drivers/staging/wusbcore/wa-nep.c similarity index 100% rename from drivers/usb/wusbcore/wa-nep.c rename to drivers/staging/wusbcore/wa-nep.c diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/staging/wusbcore/wa-rpipe.c similarity index 100% rename from drivers/usb/wusbcore/wa-rpipe.c rename to drivers/staging/wusbcore/wa-rpipe.c diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/staging/wusbcore/wa-xfer.c similarity index 100% rename from drivers/usb/wusbcore/wa-xfer.c rename to drivers/staging/wusbcore/wa-xfer.c diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/staging/wusbcore/wusbhc.c similarity index 100% rename from drivers/usb/wusbcore/wusbhc.c rename to drivers/staging/wusbcore/wusbhc.c diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/staging/wusbcore/wusbhc.h similarity index 99% rename from drivers/usb/wusbcore/wusbhc.h rename to drivers/staging/wusbcore/wusbhc.h index 7681d796ca5b..716244a2ec44 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/staging/wusbcore/wusbhc.h @@ -45,8 +45,8 @@ #include #include #include -#include -#include +#include "../uwb/uwb.h" +#include "include/wusb.h" /* * Time from a WUSB channel stop request to the last transmitted MMC. diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6e59d370ef81..9987c399819f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -98,8 +98,6 @@ source "drivers/usb/core/Kconfig" source "drivers/usb/mon/Kconfig" -source "drivers/usb/wusbcore/Kconfig" - source "drivers/usb/host/Kconfig" source "drivers/usb/renesas_usbhs/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index ecc2de1ffaae..db064dd59e08 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -35,8 +35,6 @@ obj-$(CONFIG_USB_MAX3421_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ -obj-$(CONFIG_USB_WUSB) += wusbcore/ - obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_WDM) += class/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 40b5de597112..d040408f5baa 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -717,32 +717,6 @@ config USB_RENESAS_USBHS_HCD To compile this driver as a module, choose M here: the module will be called renesas-usbhs. -config USB_WHCI_HCD - tristate "Wireless USB Host Controller Interface (WHCI) driver" - depends on USB_PCI && USB && UWB - select USB_WUSB - select UWB_WHCI - help - A driver for PCI-based Wireless USB Host Controllers that are - compliant with the WHCI specification. - - To compile this driver a module, choose M here: the module - will be called "whci-hcd". - -config USB_HWA_HCD - tristate "Host Wire Adapter (HWA) driver" - depends on USB && UWB - select USB_WUSB - select UWB_HWA - help - This driver enables you to connect Wireless USB devices to - your system using a Host Wire Adaptor USB dongle. This is an - UWB Radio Controller and WUSB Host Controller connected to - your machine via USB (specified in WUSB1.0). - - To compile this driver a module, choose M here: the module - will be called "hwa-hc". - config USB_IMX21_HCD tristate "i.MX21 HCD support" depends on ARM && ARCH_MXC diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 84514f71ae44..59b39e6b350b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -35,8 +35,6 @@ ifneq ($(CONFIG_DEBUG_FS),) xhci-hcd-y += xhci-debugfs.o endif -obj-$(CONFIG_USB_WHCI_HCD) += whci/ - obj-$(CONFIG_USB_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o @@ -82,7 +80,6 @@ obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o -obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_USB2) += fsl-mph-dr-of.o obj-$(CONFIG_USB_EHCI_FSL) += fsl-mph-dr-of.o -- GitLab From d3b5e319a19e6c6b612528c57c4ad55cb10273a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:32 +0200 Subject: [PATCH 2220/7155] USB: musb: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Acked-by: Bin Liu Link: https://lore.kernel.org/r/20190805193636.25560-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2bc55e0ceace..bd63450af76a 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1829,16 +1829,13 @@ static ssize_t srp_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_WO(srp); -static struct attribute *musb_attributes[] = { +static struct attribute *musb_attrs[] = { &dev_attr_mode.attr, &dev_attr_vbus.attr, &dev_attr_srp.attr, NULL }; - -static const struct attribute_group musb_attr_group = { - .attrs = musb_attributes, -}; +ATTRIBUTE_GROUPS(musb); #define MUSB_QUIRK_B_INVALID_VBUS_91 (MUSB_DEVCTL_BDEVICE | \ (2 << MUSB_DEVCTL_VBUS_SHIFT) | \ @@ -2038,10 +2035,6 @@ static void musb_free(struct musb *musb) * cleanup after everything's been de-activated. */ -#ifdef CONFIG_SYSFS - sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); -#endif - if (musb->nIrq >= 0) { if (musb->irq_wake) disable_irq_wake(musb->nIrq); @@ -2390,22 +2383,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_init_debugfs(musb); - status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); - if (status) - goto fail5; - musb->is_initialized = 1; pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); return 0; -fail5: - musb_exit_debugfs(musb); - - musb_gadget_cleanup(musb); - musb_host_cleanup(musb); - fail3: cancel_delayed_work_sync(&musb->irq_work); cancel_delayed_work_sync(&musb->finish_resume_work); @@ -2798,6 +2781,7 @@ static struct platform_driver musb_driver = { .name = (char *)musb_driver_name, .bus = &platform_bus_type, .pm = MUSB_DEV_PM_OPS, + .dev_groups = musb_groups, }, .probe = musb_probe, .remove = musb_remove, -- GitLab From 2e18b14e164213e608cb609430c17a6fe2ba894c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:36 +0200 Subject: [PATCH 2221/7155] USB: typec: ucsi_ccg: convert i2c driver to use dev_groups The driver core now supports the option to automatically create and remove any needed sysfs attribute files for a driver when the device is bound/removed from it. Convert the uscsi_ccg code to use that instead of trying to create sysfs files "by hand". Cc: Ajay Gupta Cc: Wolfram Sang Cc: Wei Yongjun Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20190805193636.25560-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi_ccg.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index f7a79a23ebed..e283a42e4f06 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -1104,14 +1104,11 @@ static ssize_t do_flash_store(struct device *dev, static DEVICE_ATTR_WO(do_flash); -static struct attribute *ucsi_ccg_sysfs_attrs[] = { +static struct attribute *ucsi_ccg_attrs[] = { &dev_attr_do_flash.attr, NULL, }; - -static struct attribute_group ucsi_ccg_attr_group = { - .attrs = ucsi_ccg_sysfs_attrs, -}; +ATTRIBUTE_GROUPS(ucsi_ccg); static int ucsi_ccg_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -1189,10 +1186,6 @@ static int ucsi_ccg_probe(struct i2c_client *client, i2c_set_clientdata(client, uc); - status = sysfs_create_group(&uc->dev->kobj, &ucsi_ccg_attr_group); - if (status) - dev_err(uc->dev, "cannot create sysfs group: %d\n", status); - pm_runtime_set_active(uc->dev); pm_runtime_enable(uc->dev); pm_runtime_idle(uc->dev); @@ -1209,7 +1202,6 @@ static int ucsi_ccg_remove(struct i2c_client *client) ucsi_unregister_ppm(uc->ucsi); pm_runtime_disable(uc->dev); free_irq(uc->irq, uc); - sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group); return 0; } @@ -1270,6 +1262,7 @@ static struct i2c_driver ucsi_ccg_driver = { .driver = { .name = "ucsi_ccg", .pm = &ucsi_ccg_pm, + .dev_groups = ucsi_ccg_groups, }, .probe = ucsi_ccg_probe, .remove = ucsi_ccg_remove, -- GitLab From e57d143091f1c0b1a98140a4d2e63e113afb62c0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 8 Aug 2019 08:47:14 +0200 Subject: [PATCH 2222/7155] mutex: Fix up mutex_waiter usage The patch moving bits into mutex.c was a little too much; by also moving struct mutex_waiter a few less common CONFIGs would no longer build. Fixes: 5f35d5a66b3e ("locking/mutex: Make __mutex_owner static to mutex.c") Signed-off-by: Peter Zijlstra (Intel) --- include/linux/mutex.h | 13 +++++++++++++ kernel/locking/mutex.c | 13 ------------- kernel/locking/mutex.h | 2 -- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/linux/mutex.h b/include/linux/mutex.h index eb8c62aba263..aca8f36dfac9 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -65,6 +65,19 @@ struct mutex { #endif }; +/* + * This is the control structure for tasks blocked on mutex, + * which resides on the blocked task's kernel stack: + */ +struct mutex_waiter { + struct list_head list; + struct task_struct *task; + struct ww_acquire_ctx *ww_ctx; +#ifdef CONFIG_DEBUG_MUTEXES + void *magic; +#endif +}; + #ifdef CONFIG_DEBUG_MUTEXES #define __DEBUG_MUTEX_INITIALIZER(lockname) \ diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index b4bcb0236d7a..468a9b8422e3 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -36,19 +36,6 @@ # include "mutex.h" #endif -/* - * This is the control structure for tasks blocked on mutex, - * which resides on the blocked task's kernel stack: - */ -struct mutex_waiter { - struct list_head list; - struct task_struct *task; - struct ww_acquire_ctx *ww_ctx; -#ifdef CONFIG_DEBUG_MUTEXES - void *magic; -#endif -}; - void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) { diff --git a/kernel/locking/mutex.h b/kernel/locking/mutex.h index 7cde5c6d414e..1c2287d3fa71 100644 --- a/kernel/locking/mutex.h +++ b/kernel/locking/mutex.h @@ -19,8 +19,6 @@ #define debug_mutex_unlock(lock) do { } while (0) #define debug_mutex_init(lock, name, key) do { } while (0) -struct mutex_waiter; - static inline void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) { -- GitLab From 130d9c331bc59a8733b47c58ef197a2b1fa3ed43 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Aug 2019 12:42:06 +0200 Subject: [PATCH 2223/7155] rcu/tree: Fix SCHED_FIFO params A rather embarrasing mistake had us call sched_setscheduler() before initializing the parameters passed to it. Fixes: 1a763fd7c633 ("rcu/tree: Call setschedule() gp ktread to SCHED_FIFO outside of atomic region") Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Paul E. McKenney Cc: Juri Lelli --- kernel/rcu/tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index eb764c24bc4d..5efdce756fdf 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3234,13 +3234,13 @@ static int __init rcu_spawn_gp_kthread(void) t = kthread_create(rcu_gp_kthread, NULL, "%s", rcu_state.name); if (WARN_ONCE(IS_ERR(t), "%s: Could not start grace-period kthread, OOM is now expected behavior\n", __func__)) return 0; - if (kthread_prio) + if (kthread_prio) { + sp.sched_priority = kthread_prio; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + } rnp = rcu_get_root(); raw_spin_lock_irqsave_rcu_node(rnp, flags); rcu_state.gp_kthread = t; - if (kthread_prio) - sp.sched_priority = kthread_prio; raw_spin_unlock_irqrestore_rcu_node(rnp, flags); wake_up_process(t); rcu_spawn_nocb_kthreads(); -- GitLab From 139d025cda1da5484e7287b35c019fe1dcf9b650 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 29 Jul 2019 16:05:15 +0200 Subject: [PATCH 2224/7155] sched: Clean up active_mm reference counting The current active_mm reference counting is confusing and sub-optimal. Rewrite the code to explicitly consider the 4 separate cases: user -> user When switching between two user tasks, all we need to consider is switch_mm(). user -> kernel When switching from a user task to a kernel task (which doesn't have an associated mm) we retain the last mm in our active_mm. Increment a reference count on active_mm. kernel -> kernel When switching between kernel threads, all we need to do is pass along the active_mm reference. kernel -> user When switching between a kernel and user task, we must switch from the last active_mm to the next mm, hoping of course that these are the same. Decrement a reference on the active_mm. The code keeps a different order, because as you'll note, both 'to user' cases require switch_mm(). And where the old code would increment/decrement for the 'kernel -> kernel' case, the new code observes this is a neutral operation and avoids touching the reference count. Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Rik van Riel Reviewed-by: Mathieu Desnoyers Cc: luto@kernel.org --- kernel/sched/core.c | 49 +++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 46f3ca9e392a..b4a44bc84749 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3214,12 +3214,8 @@ static __always_inline struct rq * context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next, struct rq_flags *rf) { - struct mm_struct *mm, *oldmm; - prepare_task_switch(rq, prev, next); - mm = next->mm; - oldmm = prev->active_mm; /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into @@ -3228,22 +3224,37 @@ context_switch(struct rq *rq, struct task_struct *prev, arch_start_context_switch(prev); /* - * If mm is non-NULL, we pass through switch_mm(). If mm is - * NULL, we will pass through mmdrop() in finish_task_switch(). - * Both of these contain the full memory barrier required by - * membarrier after storing to rq->curr, before returning to - * user-space. + * kernel -> kernel lazy + transfer active + * user -> kernel lazy + mmgrab() active + * + * kernel -> user switch + mmdrop() active + * user -> user switch */ - if (!mm) { - next->active_mm = oldmm; - mmgrab(oldmm); - enter_lazy_tlb(oldmm, next); - } else - switch_mm_irqs_off(oldmm, mm, next); - - if (!prev->mm) { - prev->active_mm = NULL; - rq->prev_mm = oldmm; + if (!next->mm) { // to kernel + enter_lazy_tlb(prev->active_mm, next); + + next->active_mm = prev->active_mm; + if (prev->mm) // from user + mmgrab(prev->active_mm); + else + prev->active_mm = NULL; + } else { // to user + /* + * sys_membarrier() requires an smp_mb() between setting + * rq->curr and returning to userspace. + * + * The below provides this either through switch_mm(), or in + * case 'prev->active_mm == next->mm' through + * finish_task_switch()'s mmdrop(). + */ + + switch_mm_irqs_off(prev->active_mm, next->mm, next); + + if (!prev->mm) { // from kernel + /* will mmdrop() in finish_task_switch(). */ + rq->prev_mm = prev->active_mm; + prev->active_mm = NULL; + } } rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP); -- GitLab From de53fd7aedb100f03e5d2231cfce0e4993282425 Mon Sep 17 00:00:00 2001 From: Dave Chiluk Date: Tue, 23 Jul 2019 11:44:26 -0500 Subject: [PATCH 2225/7155] sched/fair: Fix low cpu usage with high throttling by removing expiration of cpu-local slices It has been observed, that highly-threaded, non-cpu-bound applications running under cpu.cfs_quota_us constraints can hit a high percentage of periods throttled while simultaneously not consuming the allocated amount of quota. This use case is typical of user-interactive non-cpu bound applications, such as those running in kubernetes or mesos when run on multiple cpu cores. This has been root caused to cpu-local run queue being allocated per cpu bandwidth slices, and then not fully using that slice within the period. At which point the slice and quota expires. This expiration of unused slice results in applications not being able to utilize the quota for which they are allocated. The non-expiration of per-cpu slices was recently fixed by 'commit 512ac999d275 ("sched/fair: Fix bandwidth timer clock drift condition")'. Prior to that it appears that this had been broken since at least 'commit 51f2176d74ac ("sched/fair: Fix unlocked reads of some cfs_b->quota/period")' which was introduced in v3.16-rc1 in 2014. That added the following conditional which resulted in slices never being expired. if (cfs_rq->runtime_expires != cfs_b->runtime_expires) { /* extend local deadline, drift is bounded above by 2 ticks */ cfs_rq->runtime_expires += TICK_NSEC; Because this was broken for nearly 5 years, and has recently been fixed and is now being noticed by many users running kubernetes (https://github.com/kubernetes/kubernetes/issues/67577) it is my opinion that the mechanisms around expiring runtime should be removed altogether. This allows quota already allocated to per-cpu run-queues to live longer than the period boundary. This allows threads on runqueues that do not use much CPU to continue to use their remaining slice over a longer period of time than cpu.cfs_period_us. However, this helps prevent the above condition of hitting throttling while also not fully utilizing your cpu quota. This theoretically allows a machine to use slightly more than its allotted quota in some periods. This overflow would be bounded by the remaining quota left on each per-cpu runqueueu. This is typically no more than min_cfs_rq_runtime=1ms per cpu. For CPU bound tasks this will change nothing, as they should theoretically fully utilize all of their quota in each period. For user-interactive tasks as described above this provides a much better user/application experience as their cpu utilization will more closely match the amount they requested when they hit throttling. This means that cpu limits no longer strictly apply per period for non-cpu bound applications, but that they are still accurate over longer timeframes. This greatly improves performance of high-thread-count, non-cpu bound applications with low cfs_quota_us allocation on high-core-count machines. In the case of an artificial testcase (10ms/100ms of quota on 80 CPU machine), this commit resulted in almost 30x performance improvement, while still maintaining correct cpu quota restrictions. That testcase is available at https://github.com/indeedeng/fibtest. Fixes: 512ac999d275 ("sched/fair: Fix bandwidth timer clock drift condition") Signed-off-by: Dave Chiluk Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Phil Auld Reviewed-by: Ben Segall Cc: Ingo Molnar Cc: John Hammond Cc: Jonathan Corbet Cc: Kyle Anderson Cc: Gabriel Munos Cc: Peter Oskolkov Cc: Cong Wang Cc: Brendan Gregg Link: https://lkml.kernel.org/r/1563900266-19734-2-git-send-email-chiluk+linux@indeed.com --- Documentation/scheduler/sched-bwc.rst | 74 ++++++++++++++++++++++----- kernel/sched/fair.c | 72 +++----------------------- kernel/sched/sched.h | 4 -- 3 files changed, 67 insertions(+), 83 deletions(-) diff --git a/Documentation/scheduler/sched-bwc.rst b/Documentation/scheduler/sched-bwc.rst index 3a9064219656..9801d6b284b1 100644 --- a/Documentation/scheduler/sched-bwc.rst +++ b/Documentation/scheduler/sched-bwc.rst @@ -9,15 +9,16 @@ CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the specification of the maximum CPU bandwidth available to a group or hierarchy. The bandwidth allowed for a group is specified using a quota and period. Within -each given "period" (microseconds), a group is allowed to consume only up to -"quota" microseconds of CPU time. When the CPU bandwidth consumption of a -group exceeds this limit (for that period), the tasks belonging to its -hierarchy will be throttled and are not allowed to run again until the next -period. - -A group's unused runtime is globally tracked, being refreshed with quota units -above at each period boundary. As threads consume this bandwidth it is -transferred to cpu-local "silos" on a demand basis. The amount transferred +each given "period" (microseconds), a task group is allocated up to "quota" +microseconds of CPU time. That quota is assigned to per-cpu run queues in +slices as threads in the cgroup become runnable. Once all quota has been +assigned any additional requests for quota will result in those threads being +throttled. Throttled threads will not be able to run again until the next +period when the quota is replenished. + +A group's unassigned quota is globally tracked, being refreshed back to +cfs_quota units at each period boundary. As threads consume this bandwidth it +is transferred to cpu-local "silos" on a demand basis. The amount transferred within each of these updates is tunable and described as the "slice". Management @@ -35,12 +36,12 @@ The default values are:: A value of -1 for cpu.cfs_quota_us indicates that the group does not have any bandwidth restriction in place, such a group is described as an unconstrained -bandwidth group. This represents the traditional work-conserving behavior for +bandwidth group. This represents the traditional work-conserving behavior for CFS. Writing any (valid) positive value(s) will enact the specified bandwidth limit. -The minimum quota allowed for the quota or period is 1ms. There is also an -upper bound on the period length of 1s. Additional restrictions exist when +The minimum quota allowed for the quota or period is 1ms. There is also an +upper bound on the period length of 1s. Additional restrictions exist when bandwidth limits are used in a hierarchical fashion, these are explained in more detail below. @@ -53,8 +54,8 @@ unthrottled if it is in a constrained state. System wide settings -------------------- For efficiency run-time is transferred between the global pool and CPU local -"silos" in a batch fashion. This greatly reduces global accounting pressure -on large systems. The amount transferred each time such an update is required +"silos" in a batch fashion. This greatly reduces global accounting pressure +on large systems. The amount transferred each time such an update is required is described as the "slice". This is tunable via procfs:: @@ -97,6 +98,51 @@ There are two ways in which a group may become throttled: In case b) above, even though the child may have runtime remaining it will not be allowed to until the parent's runtime is refreshed. +CFS Bandwidth Quota Caveats +--------------------------- +Once a slice is assigned to a cpu it does not expire. However all but 1ms of +the slice may be returned to the global pool if all threads on that cpu become +unrunnable. This is configured at compile time by the min_cfs_rq_runtime +variable. This is a performance tweak that helps prevent added contention on +the global lock. + +The fact that cpu-local slices do not expire results in some interesting corner +cases that should be understood. + +For cgroup cpu constrained applications that are cpu limited this is a +relatively moot point because they will naturally consume the entirety of their +quota as well as the entirety of each cpu-local slice in each period. As a +result it is expected that nr_periods roughly equal nr_throttled, and that +cpuacct.usage will increase roughly equal to cfs_quota_us in each period. + +For highly-threaded, non-cpu bound applications this non-expiration nuance +allows applications to briefly burst past their quota limits by the amount of +unused slice on each cpu that the task group is running on (typically at most +1ms per cpu or as defined by min_cfs_rq_runtime). This slight burst only +applies if quota had been assigned to a cpu and then not fully used or returned +in previous periods. This burst amount will not be transferred between cores. +As a result, this mechanism still strictly limits the task group to quota +average usage, albeit over a longer time window than a single period. This +also limits the burst ability to no more than 1ms per cpu. This provides +better more predictable user experience for highly threaded applications with +small quota limits on high core count machines. It also eliminates the +propensity to throttle these applications while simultanously using less than +quota amounts of cpu. Another way to say this, is that by allowing the unused +portion of a slice to remain valid across periods we have decreased the +possibility of wastefully expiring quota on cpu-local silos that don't need a +full slice's amount of cpu time. + +The interaction between cpu-bound and non-cpu-bound-interactive applications +should also be considered, especially when single core usage hits 100%. If you +gave each of these applications half of a cpu-core and they both got scheduled +on the same CPU it is theoretically possible that the non-cpu bound application +will use up to 1ms additional quota in some periods, thereby preventing the +cpu-bound application from fully using its quota by that same amount. In these +instances it will be up to the CFS algorithm (see sched-design-CFS.rst) to +decide which application is chosen to run, as they will both be runnable and +have remaining quota. This runtime discrepancy will be made up in the following +periods when the interactive application idles. + Examples -------- 1. Limit a group to 1 CPU worth of runtime:: diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index fb75c0bea80f..7d8043fc8317 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4371,8 +4371,6 @@ void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b) now = sched_clock_cpu(smp_processor_id()); cfs_b->runtime = cfs_b->quota; - cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period); - cfs_b->expires_seq++; } static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg) @@ -4394,8 +4392,7 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq) { struct task_group *tg = cfs_rq->tg; struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(tg); - u64 amount = 0, min_amount, expires; - int expires_seq; + u64 amount = 0, min_amount; /* note: this is a positive sum as runtime_remaining <= 0 */ min_amount = sched_cfs_bandwidth_slice() - cfs_rq->runtime_remaining; @@ -4412,61 +4409,17 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq) cfs_b->idle = 0; } } - expires_seq = cfs_b->expires_seq; - expires = cfs_b->runtime_expires; raw_spin_unlock(&cfs_b->lock); cfs_rq->runtime_remaining += amount; - /* - * we may have advanced our local expiration to account for allowed - * spread between our sched_clock and the one on which runtime was - * issued. - */ - if (cfs_rq->expires_seq != expires_seq) { - cfs_rq->expires_seq = expires_seq; - cfs_rq->runtime_expires = expires; - } return cfs_rq->runtime_remaining > 0; } -/* - * Note: This depends on the synchronization provided by sched_clock and the - * fact that rq->clock snapshots this value. - */ -static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq) -{ - struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg); - - /* if the deadline is ahead of our clock, nothing to do */ - if (likely((s64)(rq_clock(rq_of(cfs_rq)) - cfs_rq->runtime_expires) < 0)) - return; - - if (cfs_rq->runtime_remaining < 0) - return; - - /* - * If the local deadline has passed we have to consider the - * possibility that our sched_clock is 'fast' and the global deadline - * has not truly expired. - * - * Fortunately we can check determine whether this the case by checking - * whether the global deadline(cfs_b->expires_seq) has advanced. - */ - if (cfs_rq->expires_seq == cfs_b->expires_seq) { - /* extend local deadline, drift is bounded above by 2 ticks */ - cfs_rq->runtime_expires += TICK_NSEC; - } else { - /* global deadline is ahead, expiration has passed */ - cfs_rq->runtime_remaining = 0; - } -} - static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec) { /* dock delta_exec before expiring quota (as it could span periods) */ cfs_rq->runtime_remaining -= delta_exec; - expire_cfs_rq_runtime(cfs_rq); if (likely(cfs_rq->runtime_remaining > 0)) return; @@ -4661,8 +4614,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) resched_curr(rq); } -static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, - u64 remaining, u64 expires) +static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, u64 remaining) { struct cfs_rq *cfs_rq; u64 runtime; @@ -4684,7 +4636,6 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, remaining -= runtime; cfs_rq->runtime_remaining += runtime; - cfs_rq->runtime_expires = expires; /* we check whether we're throttled above */ if (cfs_rq->runtime_remaining > 0) @@ -4709,7 +4660,7 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, */ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, unsigned long flags) { - u64 runtime, runtime_expires; + u64 runtime; int throttled; /* no need to continue the timer with no bandwidth constraint */ @@ -4737,8 +4688,6 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u /* account preceding periods in which throttling occurred */ cfs_b->nr_throttled += overrun; - runtime_expires = cfs_b->runtime_expires; - /* * This check is repeated as we are holding onto the new bandwidth while * we unthrottle. This can potentially race with an unthrottled group @@ -4751,8 +4700,7 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u cfs_b->distribute_running = 1; raw_spin_unlock_irqrestore(&cfs_b->lock, flags); /* we can't nest cfs_b->lock while distributing bandwidth */ - runtime = distribute_cfs_runtime(cfs_b, runtime, - runtime_expires); + runtime = distribute_cfs_runtime(cfs_b, runtime); raw_spin_lock_irqsave(&cfs_b->lock, flags); cfs_b->distribute_running = 0; @@ -4834,8 +4782,7 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq) return; raw_spin_lock(&cfs_b->lock); - if (cfs_b->quota != RUNTIME_INF && - cfs_rq->runtime_expires == cfs_b->runtime_expires) { + if (cfs_b->quota != RUNTIME_INF) { cfs_b->runtime += slack_runtime; /* we are under rq->lock, defer unthrottling using a timer */ @@ -4868,7 +4815,6 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) { u64 runtime = 0, slice = sched_cfs_bandwidth_slice(); unsigned long flags; - u64 expires; /* confirm we're still not at a refresh boundary */ raw_spin_lock_irqsave(&cfs_b->lock, flags); @@ -4886,7 +4832,6 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) if (cfs_b->quota != RUNTIME_INF && cfs_b->runtime > slice) runtime = cfs_b->runtime; - expires = cfs_b->runtime_expires; if (runtime) cfs_b->distribute_running = 1; @@ -4895,11 +4840,10 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) if (!runtime) return; - runtime = distribute_cfs_runtime(cfs_b, runtime, expires); + runtime = distribute_cfs_runtime(cfs_b, runtime); raw_spin_lock_irqsave(&cfs_b->lock, flags); - if (expires == cfs_b->runtime_expires) - lsub_positive(&cfs_b->runtime, runtime); + lsub_positive(&cfs_b->runtime, runtime); cfs_b->distribute_running = 0; raw_spin_unlock_irqrestore(&cfs_b->lock, flags); } @@ -5056,8 +5000,6 @@ void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b) cfs_b->period_active = 1; overrun = hrtimer_forward_now(&cfs_b->period_timer, cfs_b->period); - cfs_b->runtime_expires += (overrun + 1) * ktime_to_ns(cfs_b->period); - cfs_b->expires_seq++; hrtimer_start_expires(&cfs_b->period_timer, HRTIMER_MODE_ABS_PINNED); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 7583faddba33..ea48aa5daeee 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -335,8 +335,6 @@ struct cfs_bandwidth { u64 quota; u64 runtime; s64 hierarchical_quota; - u64 runtime_expires; - int expires_seq; u8 idle; u8 period_active; @@ -557,8 +555,6 @@ struct cfs_rq { #ifdef CONFIG_CFS_BANDWIDTH int runtime_enabled; - int expires_seq; - u64 runtime_expires; s64 runtime_remaining; u64 throttled_clock; -- GitLab From 99d84bf8c65a7a0dbc9e166ca0a58ed949ac4f37 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:37 +0000 Subject: [PATCH 2226/7155] stop_machine: Fix stop_cpus_in_progress ordering Make sure the entire for loop has stop_cpus_in_progress set. Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/0fd8fd4b99b9b9aa88d8b2dff897f7fd0d88f72c.1559129225.git.vpillai@digitalocean.com --- kernel/stop_machine.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index b4f83f7bdf86..c7031a22aa7b 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -383,6 +383,7 @@ static bool queue_stop_cpus_work(const struct cpumask *cpumask, */ preempt_disable(); stop_cpus_in_progress = true; + barrier(); for_each_cpu(cpu, cpumask) { work = &per_cpu(cpu_stopper.stop_work, cpu); work->fn = fn; @@ -391,6 +392,7 @@ static bool queue_stop_cpus_work(const struct cpumask *cpumask, if (cpu_stop_queue_work(cpu, work)) queued = true; } + barrier(); stop_cpus_in_progress = false; preempt_enable(); -- GitLab From 5feeb7837a448f659e0aaa19fb446b1d9a4b323a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:38 +0000 Subject: [PATCH 2227/7155] sched: Fix kerneldoc comment for ia64_set_curr_task Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/fde3a65ea3091ec6b84dac3c19639f85f452c5d1.1559129225.git.vpillai@digitalocean.com --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b4a44bc84749..9a821ff68502 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6772,7 +6772,7 @@ struct task_struct *curr_task(int cpu) #ifdef CONFIG_IA64 /** - * set_curr_task - set the current task for a given CPU. + * ia64_set_curr_task - set the current task for a given CPU. * @cpu: the processor in question. * @p: the task pointer to set. * -- GitLab From f95d4eaee6d0207bff2dc93371133d31227d4cfb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:40 +0000 Subject: [PATCH 2228/7155] sched/{rt,deadline}: Fix set_next_task vs pick_next_task Because pick_next_task() implies set_curr_task() and some of the details haven't mattered too much, some of what _should_ be in set_curr_task() ended up in pick_next_task, correct this. This prepares the way for a pick_next_task() variant that does not affect the current state; allowing remote picking. Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/38c61d5240553e043c27c5e00b9dd0d184dd6081.1559129225.git.vpillai@digitalocean.com --- kernel/sched/deadline.c | 22 +++++++++++----------- kernel/sched/rt.c | 26 +++++++++++++------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 039dde2b1dac..2dc2784b196c 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1727,12 +1727,20 @@ static void start_hrtick_dl(struct rq *rq, struct task_struct *p) } #endif -static inline void set_next_task(struct rq *rq, struct task_struct *p) +static void set_next_task_dl(struct rq *rq, struct task_struct *p) { p->se.exec_start = rq_clock_task(rq); /* You can't push away the running task */ dequeue_pushable_dl_task(rq, p); + + if (hrtick_enabled(rq)) + start_hrtick_dl(rq, p); + + if (rq->curr->sched_class != &dl_sched_class) + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0); + + deadline_queue_push_tasks(rq); } static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq, @@ -1791,15 +1799,7 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) p = dl_task_of(dl_se); - set_next_task(rq, p); - - if (hrtick_enabled(rq)) - start_hrtick_dl(rq, p); - - deadline_queue_push_tasks(rq); - - if (rq->curr->sched_class != &dl_sched_class) - update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0); + set_next_task_dl(rq, p); return p; } @@ -1846,7 +1846,7 @@ static void task_fork_dl(struct task_struct *p) static void set_curr_task_dl(struct rq *rq) { - set_next_task(rq, rq->curr); + set_next_task_dl(rq, rq->curr); } #ifdef CONFIG_SMP diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index a532558a5176..40bb71004325 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1498,12 +1498,22 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag #endif } -static inline void set_next_task(struct rq *rq, struct task_struct *p) +static inline void set_next_task_rt(struct rq *rq, struct task_struct *p) { p->se.exec_start = rq_clock_task(rq); /* The running task is never eligible for pushing */ dequeue_pushable_task(rq, p); + + /* + * If prev task was rt, put_prev_task() has already updated the + * utilization. We only care of the case where we start to schedule a + * rt task + */ + if (rq->curr->sched_class != &rt_sched_class) + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0); + + rt_queue_push_tasks(rq); } static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq, @@ -1577,17 +1587,7 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) p = _pick_next_task_rt(rq); - set_next_task(rq, p); - - rt_queue_push_tasks(rq); - - /* - * If prev task was rt, put_prev_task() has already updated the - * utilization. We only care of the case where we start to schedule a - * rt task - */ - if (rq->curr->sched_class != &rt_sched_class) - update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0); + set_next_task_rt(rq, p); return p; } @@ -2356,7 +2356,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) static void set_curr_task_rt(struct rq *rq) { - set_next_task(rq, rq->curr); + set_next_task_rt(rq, rq->curr); } static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task) -- GitLab From 10e7071b2f491b0fb981717ea0a585c441906ede Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 6 Aug 2019 15:13:17 +0200 Subject: [PATCH 2229/7155] sched: Rework CPU hotplug task selection The CPU hotplug task selection is the only place where we used put_prev_task() on a task that is not current. While looking at that, it occured to me that we can simplify all that by by using a custom pick loop. Since we don't need to put current, we can do away with the fake task too. Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan --- kernel/sched/core.c | 32 ++++++++++++++------------------ kernel/sched/sched.h | 1 + 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9a821ff68502..364b6d7da2be 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6082,21 +6082,22 @@ static void calc_load_migrate(struct rq *rq) atomic_long_add(delta, &calc_load_tasks); } -static void put_prev_task_fake(struct rq *rq, struct task_struct *prev) +static struct task_struct *__pick_migrate_task(struct rq *rq) { -} + const struct sched_class *class; + struct task_struct *next; -static const struct sched_class fake_sched_class = { - .put_prev_task = put_prev_task_fake, -}; + for_each_class(class) { + next = class->pick_next_task(rq, NULL, NULL); + if (next) { + next->sched_class->put_prev_task(rq, next); + return next; + } + } -static struct task_struct fake_task = { - /* - * Avoid pull_{rt,dl}_task() - */ - .prio = MAX_PRIO + 1, - .sched_class = &fake_sched_class, -}; + /* The idle class should always have a runnable task */ + BUG(); +} /* * Migrate all tasks from the rq, sleeping tasks will be migrated by @@ -6139,12 +6140,7 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf) if (rq->nr_running == 1) break; - /* - * pick_next_task() assumes pinned rq->lock: - */ - next = pick_next_task(rq, &fake_task, rf); - BUG_ON(!next); - put_prev_task(rq, next); + next = __pick_migrate_task(rq); /* * Rules for changing task_struct::cpus_mask are holding diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index ea48aa5daeee..b3449d0dd7f0 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1751,6 +1751,7 @@ struct sched_class { static inline void put_prev_task(struct rq *rq, struct task_struct *prev) { + WARN_ON_ONCE(rq->curr != prev); prev->sched_class->put_prev_task(rq, prev); } -- GitLab From 03b7fad167efca3b7abbbb39733933f9df56e79c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:41 +0000 Subject: [PATCH 2230/7155] sched: Add task_struct pointer to sched_class::set_curr_task In preparation of further separating pick_next_task() and set_curr_task() we have to pass the actual task into it, while there, rename the thing to better pair with put_prev_task(). Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/a96d1bcdd716db4a4c5da2fece647a1456c0ed78.1559129225.git.vpillai@digitalocean.com --- kernel/sched/core.c | 12 ++++++------ kernel/sched/deadline.c | 7 +------ kernel/sched/fair.c | 17 ++++++++++++++--- kernel/sched/idle.c | 27 +++++++++++++++------------ kernel/sched/rt.c | 7 +------ kernel/sched/sched.h | 7 ++++--- kernel/sched/stop_task.c | 17 +++++++---------- 7 files changed, 48 insertions(+), 46 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 364b6d7da2be..0c4220789092 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1494,7 +1494,7 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) if (queued) enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK); if (running) - set_curr_task(rq, p); + set_next_task(rq, p); } /* @@ -4325,7 +4325,7 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) if (queued) enqueue_task(rq, p, queue_flag); if (running) - set_curr_task(rq, p); + set_next_task(rq, p); check_class_changed(rq, p, prev_class, oldprio); out_unlock: @@ -4392,7 +4392,7 @@ void set_user_nice(struct task_struct *p, long nice) resched_curr(rq); } if (running) - set_curr_task(rq, p); + set_next_task(rq, p); out_unlock: task_rq_unlock(rq, p, &rf); } @@ -4840,7 +4840,7 @@ static int __sched_setscheduler(struct task_struct *p, enqueue_task(rq, p, queue_flags); } if (running) - set_curr_task(rq, p); + set_next_task(rq, p); check_class_changed(rq, p, prev_class, oldprio); @@ -6042,7 +6042,7 @@ void sched_setnuma(struct task_struct *p, int nid) if (queued) enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK); if (running) - set_curr_task(rq, p); + set_next_task(rq, p); task_rq_unlock(rq, p, &rf); } #endif /* CONFIG_NUMA_BALANCING */ @@ -6919,7 +6919,7 @@ void sched_move_task(struct task_struct *tsk) if (queued) enqueue_task(rq, tsk, queue_flags); if (running) - set_curr_task(rq, tsk); + set_next_task(rq, tsk); task_rq_unlock(rq, tsk, &rf); } diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 2dc2784b196c..6eae79350303 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1844,11 +1844,6 @@ static void task_fork_dl(struct task_struct *p) */ } -static void set_curr_task_dl(struct rq *rq) -{ - set_next_task_dl(rq, rq->curr); -} - #ifdef CONFIG_SMP /* Only try algorithms three times */ @@ -2466,6 +2461,7 @@ const struct sched_class dl_sched_class = { .pick_next_task = pick_next_task_dl, .put_prev_task = put_prev_task_dl, + .set_next_task = set_next_task_dl, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_dl, @@ -2476,7 +2472,6 @@ const struct sched_class dl_sched_class = { .task_woken = task_woken_dl, #endif - .set_curr_task = set_curr_task_dl, .task_tick = task_tick_dl, .task_fork = task_fork_dl, diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7d8043fc8317..8ce1b8893947 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -10150,9 +10150,19 @@ static void switched_to_fair(struct rq *rq, struct task_struct *p) * This routine is mostly called to set cfs_rq->curr field when a task * migrates between groups/classes. */ -static void set_curr_task_fair(struct rq *rq) +static void set_next_task_fair(struct rq *rq, struct task_struct *p) { - struct sched_entity *se = &rq->curr->se; + struct sched_entity *se = &p->se; + +#ifdef CONFIG_SMP + if (task_on_rq_queued(p)) { + /* + * Move the next running task to the front of the list, so our + * cfs_tasks list becomes MRU one. + */ + list_move(&se->group_node, &rq->cfs_tasks); + } +#endif for_each_sched_entity(se) { struct cfs_rq *cfs_rq = cfs_rq_of(se); @@ -10423,7 +10433,9 @@ const struct sched_class fair_sched_class = { .check_preempt_curr = check_preempt_wakeup, .pick_next_task = pick_next_task_fair, + .put_prev_task = put_prev_task_fair, + .set_next_task = set_next_task_fair, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_fair, @@ -10436,7 +10448,6 @@ const struct sched_class fair_sched_class = { .set_cpus_allowed = set_cpus_allowed_common, #endif - .set_curr_task = set_curr_task_fair, .task_tick = task_tick_fair, .task_fork = task_fork_fair, diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 80940939b733..54194d41035c 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -374,14 +374,25 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl resched_curr(rq); } +static void put_prev_task_idle(struct rq *rq, struct task_struct *prev) +{ +} + +static void set_next_task_idle(struct rq *rq, struct task_struct *next) +{ + update_idle_core(rq); + schedstat_inc(rq->sched_goidle); +} + static struct task_struct * pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { + struct task_struct *next = rq->idle; + put_prev_task(rq, prev); - update_idle_core(rq); - schedstat_inc(rq->sched_goidle); + set_next_task_idle(rq, next); - return rq->idle; + return next; } /* @@ -397,10 +408,6 @@ dequeue_task_idle(struct rq *rq, struct task_struct *p, int flags) raw_spin_lock_irq(&rq->lock); } -static void put_prev_task_idle(struct rq *rq, struct task_struct *prev) -{ -} - /* * scheduler tick hitting a task of our scheduling class. * @@ -413,10 +420,6 @@ static void task_tick_idle(struct rq *rq, struct task_struct *curr, int queued) { } -static void set_curr_task_idle(struct rq *rq) -{ -} - static void switched_to_idle(struct rq *rq, struct task_struct *p) { BUG(); @@ -451,13 +454,13 @@ const struct sched_class idle_sched_class = { .pick_next_task = pick_next_task_idle, .put_prev_task = put_prev_task_idle, + .set_next_task = set_next_task_idle, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_idle, .set_cpus_allowed = set_cpus_allowed_common, #endif - .set_curr_task = set_curr_task_idle, .task_tick = task_tick_idle, .get_rr_interval = get_rr_interval_idle, diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 40bb71004325..f71bcbe1a00c 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -2354,11 +2354,6 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) } } -static void set_curr_task_rt(struct rq *rq) -{ - set_next_task_rt(rq, rq->curr); -} - static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task) { /* @@ -2380,6 +2375,7 @@ const struct sched_class rt_sched_class = { .pick_next_task = pick_next_task_rt, .put_prev_task = put_prev_task_rt, + .set_next_task = set_next_task_rt, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_rt, @@ -2391,7 +2387,6 @@ const struct sched_class rt_sched_class = { .switched_from = switched_from_rt, #endif - .set_curr_task = set_curr_task_rt, .task_tick = task_tick_rt, .get_rr_interval = get_rr_interval_rt, diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index b3449d0dd7f0..f3c50445bf22 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1707,6 +1707,7 @@ struct sched_class { struct task_struct *prev, struct rq_flags *rf); void (*put_prev_task)(struct rq *rq, struct task_struct *p); + void (*set_next_task)(struct rq *rq, struct task_struct *p); #ifdef CONFIG_SMP int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags); @@ -1721,7 +1722,6 @@ struct sched_class { void (*rq_offline)(struct rq *rq); #endif - void (*set_curr_task)(struct rq *rq); void (*task_tick)(struct rq *rq, struct task_struct *p, int queued); void (*task_fork)(struct task_struct *p); void (*task_dead)(struct task_struct *p); @@ -1755,9 +1755,10 @@ static inline void put_prev_task(struct rq *rq, struct task_struct *prev) prev->sched_class->put_prev_task(rq, prev); } -static inline void set_curr_task(struct rq *rq, struct task_struct *curr) +static inline void set_next_task(struct rq *rq, struct task_struct *next) { - curr->sched_class->set_curr_task(rq); + WARN_ON_ONCE(rq->curr != next); + next->sched_class->set_next_task(rq, next); } #ifdef CONFIG_SMP diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index c183b790ca54..47a3d2a18a9a 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -23,6 +23,11 @@ check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags) /* we're never preempted */ } +static void set_next_task_stop(struct rq *rq, struct task_struct *stop) +{ + stop->se.exec_start = rq_clock_task(rq); +} + static struct task_struct * pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { @@ -32,8 +37,7 @@ pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf return NULL; put_prev_task(rq, prev); - - stop->se.exec_start = rq_clock_task(rq); + set_next_task_stop(rq, stop); return stop; } @@ -86,13 +90,6 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) { } -static void set_curr_task_stop(struct rq *rq) -{ - struct task_struct *stop = rq->stop; - - stop->se.exec_start = rq_clock_task(rq); -} - static void switched_to_stop(struct rq *rq, struct task_struct *p) { BUG(); /* its impossible to change to this class */ @@ -128,13 +125,13 @@ const struct sched_class stop_sched_class = { .pick_next_task = pick_next_task_stop, .put_prev_task = put_prev_task_stop, + .set_next_task = set_next_task_stop, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_stop, .set_cpus_allowed = set_cpus_allowed_common, #endif - .set_curr_task = set_curr_task_stop, .task_tick = task_tick_stop, .get_rr_interval = get_rr_interval_stop, -- GitLab From 5ba553eff0c3a7c099b1e29a740277a82c0c3314 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:42 +0000 Subject: [PATCH 2231/7155] sched/fair: Expose newidle_balance() For pick_next_task_fair() it is the newidle balance that requires dropping the rq->lock; provided we do put_prev_task() early, we can also detect the condition for doing newidle early. Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/9e3eb1859b946f03d7e500453a885725b68957ba.1559129225.git.vpillai@digitalocean.com --- kernel/sched/fair.c | 18 ++++++++---------- kernel/sched/sched.h | 4 ++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 8ce1b8893947..e7c27eda9f24 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3690,8 +3690,6 @@ static inline unsigned long cfs_rq_load_avg(struct cfs_rq *cfs_rq) return cfs_rq->avg.load_avg; } -static int idle_balance(struct rq *this_rq, struct rq_flags *rf); - static inline unsigned long task_util(struct task_struct *p) { return READ_ONCE(p->se.avg.util_avg); @@ -6878,11 +6876,10 @@ done: __maybe_unused; return p; idle: - update_misfit_status(NULL, rq); - new_tasks = idle_balance(rq, rf); + new_tasks = newidle_balance(rq, rf); /* - * Because idle_balance() releases (and re-acquires) rq->lock, it is + * Because newidle_balance() releases (and re-acquires) rq->lock, it is * possible for any higher priority task to appear. In that case we * must re-start the pick_next_entity() loop. */ @@ -9045,10 +9042,10 @@ static int load_balance(int this_cpu, struct rq *this_rq, ld_moved = 0; /* - * idle_balance() disregards balance intervals, so we could repeatedly - * reach this code, which would lead to balance_interval skyrocketting - * in a short amount of time. Skip the balance_interval increase logic - * to avoid that. + * newidle_balance() disregards balance intervals, so we could + * repeatedly reach this code, which would lead to balance_interval + * skyrocketting in a short amount of time. Skip the balance_interval + * increase logic to avoid that. */ if (env.idle == CPU_NEWLY_IDLE) goto out; @@ -9758,7 +9755,7 @@ static inline void nohz_newidle_balance(struct rq *this_rq) { } * idle_balance is called by schedule() if this_cpu is about to become * idle. Attempts to pull tasks from other CPUs. */ -static int idle_balance(struct rq *this_rq, struct rq_flags *rf) +int newidle_balance(struct rq *this_rq, struct rq_flags *rf) { unsigned long next_balance = jiffies + HZ; int this_cpu = this_rq->cpu; @@ -9766,6 +9763,7 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf) int pulled_task = 0; u64 curr_cost = 0; + update_misfit_status(NULL, this_rq); /* * We must set idle_stamp _before_ calling idle_balance(), such that we * measure the duration of idle_balance() as idle time. diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index f3c50445bf22..304d98e712bf 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1445,10 +1445,14 @@ static inline void unregister_sched_domain_sysctl(void) } #endif +extern int newidle_balance(struct rq *this_rq, struct rq_flags *rf); + #else static inline void sched_ttwu_pending(void) { } +static inline int newidle_balance(struct rq *this_rq, struct rq_flags *rf) { return 0; } + #endif /* CONFIG_SMP */ #include "stats.h" -- GitLab From 5f2a45fc9e89e022233085e6f0f352eb6ff770bb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:43 +0000 Subject: [PATCH 2232/7155] sched: Allow put_prev_task() to drop rq->lock Currently the pick_next_task() loop is convoluted and ugly because of how it can drop the rq->lock and needs to restart the picking. For the RT/Deadline classes, it is put_prev_task() where we do balancing, and we could do this before the picking loop. Make this possible. Signed-off-by: Peter Zijlstra (Intel) Cc: Valentin Schneider Cc: Aaron Lu Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/e4519f6850477ab7f3d257062796e6425ee4ba7c.1559129225.git.vpillai@digitalocean.com --- kernel/sched/core.c | 2 +- kernel/sched/deadline.c | 14 +++++++++++++- kernel/sched/fair.c | 2 +- kernel/sched/idle.c | 2 +- kernel/sched/rt.c | 14 +++++++++++++- kernel/sched/sched.h | 4 ++-- kernel/sched/stop_task.c | 2 +- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0c4220789092..7bbe78a31ba5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6090,7 +6090,7 @@ static struct task_struct *__pick_migrate_task(struct rq *rq) for_each_class(class) { next = class->pick_next_task(rq, NULL, NULL); if (next) { - next->sched_class->put_prev_task(rq, next); + next->sched_class->put_prev_task(rq, next, NULL); return next; } } diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 6eae79350303..2872e15a87cd 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1804,13 +1804,25 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) return p; } -static void put_prev_task_dl(struct rq *rq, struct task_struct *p) +static void put_prev_task_dl(struct rq *rq, struct task_struct *p, struct rq_flags *rf) { update_curr_dl(rq); update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 1); if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1) enqueue_pushable_dl_task(rq, p); + + if (rf && !on_dl_rq(&p->dl) && need_pull_dl_task(rq, p)) { + /* + * This is OK, because current is on_cpu, which avoids it being + * picked for load-balance and preemption/IRQs are still + * disabled avoiding further scheduler activity on it and we've + * not yet started the picking loop. + */ + rq_unpin_lock(rq, rf); + pull_dl_task(rq); + rq_repin_lock(rq, rf); + } } /* diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index e7c27eda9f24..4418c1998e69 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6901,7 +6901,7 @@ done: __maybe_unused; /* * Account for a descheduled task: */ -static void put_prev_task_fair(struct rq *rq, struct task_struct *prev) +static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { struct sched_entity *se = &prev->se; struct cfs_rq *cfs_rq; diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 54194d41035c..8d59de2e4a6e 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -374,7 +374,7 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl resched_curr(rq); } -static void put_prev_task_idle(struct rq *rq, struct task_struct *prev) +static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index f71bcbe1a00c..dbdabd76f192 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1592,7 +1592,7 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) return p; } -static void put_prev_task_rt(struct rq *rq, struct task_struct *p) +static void put_prev_task_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf) { update_curr_rt(rq); @@ -1604,6 +1604,18 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p) */ if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1) enqueue_pushable_task(rq, p); + + if (rf && !on_rt_rq(&p->rt) && need_pull_rt_task(rq, p)) { + /* + * This is OK, because current is on_cpu, which avoids it being + * picked for load-balance and preemption/IRQs are still + * disabled avoiding further scheduler activity on it and we've + * not yet started the picking loop. + */ + rq_unpin_lock(rq, rf); + pull_rt_task(rq); + rq_repin_lock(rq, rf); + } } #ifdef CONFIG_SMP diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 304d98e712bf..e085cffb8004 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1710,7 +1710,7 @@ struct sched_class { struct task_struct * (*pick_next_task)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf); - void (*put_prev_task)(struct rq *rq, struct task_struct *p); + void (*put_prev_task)(struct rq *rq, struct task_struct *p, struct rq_flags *rf); void (*set_next_task)(struct rq *rq, struct task_struct *p); #ifdef CONFIG_SMP @@ -1756,7 +1756,7 @@ struct sched_class { static inline void put_prev_task(struct rq *rq, struct task_struct *prev) { WARN_ON_ONCE(rq->curr != prev); - prev->sched_class->put_prev_task(rq, prev); + prev->sched_class->put_prev_task(rq, prev, NULL); } static inline void set_next_task(struct rq *rq, struct task_struct *next) diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 47a3d2a18a9a..8f414018d5e0 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -59,7 +59,7 @@ static void yield_task_stop(struct rq *rq) BUG(); /* the stop task should never yield, its pointless. */ } -static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) +static void put_prev_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { struct task_struct *curr = rq->curr; u64 delta_exec; -- GitLab From 67692435c411e5c53a1c588ecca2037aebd81f2e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 May 2019 20:36:44 +0000 Subject: [PATCH 2233/7155] sched: Rework pick_next_task() slow-path Avoid the RETRY_TASK case in the pick_next_task() slow path. By doing the put_prev_task() early, we get the rt/deadline pull done, and by testing rq->nr_running we know if we need newidle_balance(). This then gives a stable state to pick a task from. Since the fast-path is fair only; it means the other classes will always have pick_next_task(.prev=NULL, .rf=NULL) and we can simplify. Signed-off-by: Peter Zijlstra (Intel) Cc: Aaron Lu Cc: Valentin Schneider Cc: mingo@kernel.org Cc: Phil Auld Cc: Julien Desfossez Cc: Nishanth Aravamudan Link: https://lkml.kernel.org/r/aa34d24b36547139248f32a30138791ac6c02bd6.1559129225.git.vpillai@digitalocean.com --- kernel/sched/core.c | 19 ++++++++++++------- kernel/sched/deadline.c | 30 ++---------------------------- kernel/sched/fair.c | 9 ++++++--- kernel/sched/idle.c | 4 +++- kernel/sched/rt.c | 29 +---------------------------- kernel/sched/sched.h | 13 ++++++++----- kernel/sched/stop_task.c | 3 ++- 7 files changed, 34 insertions(+), 73 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 7bbe78a31ba5..a6661852907b 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3791,7 +3791,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) p = fair_sched_class.pick_next_task(rq, prev, rf); if (unlikely(p == RETRY_TASK)) - goto again; + goto restart; /* Assumes fair_sched_class->next == idle_sched_class */ if (unlikely(!p)) @@ -3800,14 +3800,19 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) return p; } -again: +restart: + /* + * Ensure that we put DL/RT tasks before the pick loop, such that they + * can PULL higher prio tasks when we lower the RQ 'priority'. + */ + prev->sched_class->put_prev_task(rq, prev, rf); + if (!rq->nr_running) + newidle_balance(rq, rf); + for_each_class(class) { - p = class->pick_next_task(rq, prev, rf); - if (p) { - if (unlikely(p == RETRY_TASK)) - goto again; + p = class->pick_next_task(rq, NULL, NULL); + if (p) return p; - } } /* The idle class should always have a runnable task: */ diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 2872e15a87cd..0b9cbfb2b1d4 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1761,39 +1761,13 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) struct task_struct *p; struct dl_rq *dl_rq; - dl_rq = &rq->dl; - - if (need_pull_dl_task(rq, prev)) { - /* - * This is OK, because current is on_cpu, which avoids it being - * picked for load-balance and preemption/IRQs are still - * disabled avoiding further scheduler activity on it and we're - * being very careful to re-start the picking loop. - */ - rq_unpin_lock(rq, rf); - pull_dl_task(rq); - rq_repin_lock(rq, rf); - /* - * pull_dl_task() can drop (and re-acquire) rq->lock; this - * means a stop task can slip in, in which case we need to - * re-start task selection. - */ - if (rq->stop && task_on_rq_queued(rq->stop)) - return RETRY_TASK; - } + WARN_ON_ONCE(prev || rf); - /* - * When prev is DL, we may throttle it in put_prev_task(). - * So, we update time before we check for dl_nr_running. - */ - if (prev->sched_class == &dl_sched_class) - update_curr_dl(rq); + dl_rq = &rq->dl; if (unlikely(!dl_rq->dl_nr_running)) return NULL; - put_prev_task(rq, prev); - dl_se = pick_next_dl_entity(rq, dl_rq); BUG_ON(!dl_se); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 4418c1998e69..19c58599e967 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6770,7 +6770,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf goto idle; #ifdef CONFIG_FAIR_GROUP_SCHED - if (prev->sched_class != &fair_sched_class) + if (!prev || prev->sched_class != &fair_sched_class) goto simple; /* @@ -6847,8 +6847,8 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf goto done; simple: #endif - - put_prev_task(rq, prev); + if (prev) + put_prev_task(rq, prev); do { se = pick_next_entity(cfs_rq, NULL); @@ -6876,6 +6876,9 @@ done: __maybe_unused; return p; idle: + if (!rf) + return NULL; + new_tasks = newidle_balance(rq, rf); /* diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 8d59de2e4a6e..7c54550dda6a 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -389,7 +389,9 @@ pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf { struct task_struct *next = rq->idle; - put_prev_task(rq, prev); + if (prev) + put_prev_task(rq, prev); + set_next_task_idle(rq, next); return next; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index dbdabd76f192..858c4cc6f99b 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1553,38 +1553,11 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) struct task_struct *p; struct rt_rq *rt_rq = &rq->rt; - if (need_pull_rt_task(rq, prev)) { - /* - * This is OK, because current is on_cpu, which avoids it being - * picked for load-balance and preemption/IRQs are still - * disabled avoiding further scheduler activity on it and we're - * being very careful to re-start the picking loop. - */ - rq_unpin_lock(rq, rf); - pull_rt_task(rq); - rq_repin_lock(rq, rf); - /* - * pull_rt_task() can drop (and re-acquire) rq->lock; this - * means a dl or stop task can slip in, in which case we need - * to re-start task selection. - */ - if (unlikely((rq->stop && task_on_rq_queued(rq->stop)) || - rq->dl.dl_nr_running)) - return RETRY_TASK; - } - - /* - * We may dequeue prev's rt_rq in put_prev_task(). - * So, we update time before rt_queued check. - */ - if (prev->sched_class == &rt_sched_class) - update_curr_rt(rq); + WARN_ON_ONCE(prev || rf); if (!rt_rq->rt_queued) return NULL; - put_prev_task(rq, prev); - p = _pick_next_task_rt(rq); set_next_task_rt(rq, p); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index e085cffb8004..7111e3a1eeb4 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1700,12 +1700,15 @@ struct sched_class { void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags); /* - * It is the responsibility of the pick_next_task() method that will - * return the next task to call put_prev_task() on the @prev task or - * something equivalent. + * Both @prev and @rf are optional and may be NULL, in which case the + * caller must already have invoked put_prev_task(rq, prev, rf). * - * May return RETRY_TASK when it finds a higher prio class has runnable - * tasks. + * Otherwise it is the responsibility of the pick_next_task() to call + * put_prev_task() on the @prev task or something equivalent, IFF it + * returns a next task. + * + * In that case (@rf != NULL) it may return RETRY_TASK when it finds a + * higher prio class has runnable tasks. */ struct task_struct * (*pick_next_task)(struct rq *rq, struct task_struct *prev, diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 8f414018d5e0..7e1cee4e65b2 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -33,10 +33,11 @@ pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf { struct task_struct *stop = rq->stop; + WARN_ON_ONCE(prev || rf); + if (!stop || !task_on_rq_queued(stop)) return NULL; - put_prev_task(rq, prev); set_next_task_stop(rq, stop); return stop; -- GitLab From 5c3ceef9ad7b340b0acee6c26d0c9e6429decb2c Mon Sep 17 00:00:00 2001 From: Qais Yousef Date: Fri, 2 Aug 2019 11:46:28 +0100 Subject: [PATCH 2234/7155] cpufreq: schedutil: fix equation in comment scale_irq_capacity() call in schedutil_cpu_util() does util *= (max - irq) util /= max But the comment says util *= (1 - irq) util /= max Fix the comment to match what the scaling function does. Signed-off-by: Qais Yousef Signed-off-by: Peter Zijlstra (Intel) Acked-by: Viresh Kumar Acked-by: Vincent Guittot Cc: Ingo Molnar Cc: "Rafael J . Wysocki" Link: https://lkml.kernel.org/r/20190802104628.8410-1-qais.yousef@arm.com --- kernel/sched/cpufreq_schedutil.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 636ca6f88c8e..e127d89d5974 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -259,9 +259,9 @@ unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs, * irq metric. Because IRQ/steal time is hidden from the task clock we * need to scale the task numbers: * - * 1 - irq - * U' = irq + ------- * U - * max + * max - irq + * U' = irq + --------- * U + * max */ util = scale_irq_capacity(util, irq, max); util += irq; -- GitLab From e55f31a599478fb06a5a5d95e019e963322535cb Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 25 Jun 2019 15:36:45 +0200 Subject: [PATCH 2235/7155] efi: x86: move efi_is_table_address() into arch/x86 The function efi_is_table_address() and the associated array of table pointers is specific to x86. Since we will be adding some more x86 specific tables, let's move this code out of the generic code first. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 5 +++++ arch/x86/mm/ioremap.c | 1 + arch/x86/platform/efi/efi.c | 33 +++++++++++++++++++++++++++++++++ drivers/firmware/efi/efi.c | 33 --------------------------------- include/linux/efi.h | 7 ------- 5 files changed, 39 insertions(+), 40 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 606a4b6a9812..43a82e59c59d 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -242,6 +242,7 @@ static inline bool efi_is_64bit(void) __efi_early()->runtime_services), __VA_ARGS__) extern bool efi_reboot_required(void); +extern bool efi_is_table_address(unsigned long phys_addr); #else static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} @@ -249,6 +250,10 @@ static inline bool efi_reboot_required(void) { return false; } +static inline bool efi_is_table_address(unsigned long phys_addr) +{ + return false; +} #endif /* CONFIG_EFI */ #endif /* _ASM_X86_EFI_H */ diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 63e99f15d7cf..a39dcdb5ae34 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index a7189a3b4d70..8d9be97a5607 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -64,6 +64,25 @@ static efi_config_table_type_t arch_tables[] __initdata = { {NULL_GUID, NULL, NULL}, }; +static const unsigned long * const efi_tables[] = { + &efi.mps, + &efi.acpi, + &efi.acpi20, + &efi.smbios, + &efi.smbios3, + &efi.sal_systab, + &efi.boot_info, + &efi.hcdp, + &efi.uga, + &efi.uv_systab, + &efi.fw_vendor, + &efi.runtime, + &efi.config_table, + &efi.esrt, + &efi.properties_table, + &efi.mem_attr_table, +}; + u64 efi_setup; /* efi setup_data physical address */ static int add_efi_memmap __initdata; @@ -1049,3 +1068,17 @@ static int __init arch_parse_efi_cmdline(char *str) return 0; } early_param("efi", arch_parse_efi_cmdline); + +bool efi_is_table_address(unsigned long phys_addr) +{ + unsigned int i; + + if (phys_addr == EFI_INVALID_TABLE_ADDR) + return false; + + for (i = 0; i < ARRAY_SIZE(efi_tables); i++) + if (*(efi_tables[i]) == phys_addr) + return true; + + return false; +} diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index ad3b1f4866b3..cbdbdbc8f9eb 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -57,25 +57,6 @@ struct efi __read_mostly efi = { }; EXPORT_SYMBOL(efi); -static unsigned long *efi_tables[] = { - &efi.mps, - &efi.acpi, - &efi.acpi20, - &efi.smbios, - &efi.smbios3, - &efi.sal_systab, - &efi.boot_info, - &efi.hcdp, - &efi.uga, - &efi.uv_systab, - &efi.fw_vendor, - &efi.runtime, - &efi.config_table, - &efi.esrt, - &efi.properties_table, - &efi.mem_attr_table, -}; - struct mm_struct efi_mm = { .mm_rb = RB_ROOT, .mm_users = ATOMIC_INIT(2), @@ -964,20 +945,6 @@ int efi_status_to_err(efi_status_t status) return err; } -bool efi_is_table_address(unsigned long phys_addr) -{ - unsigned int i; - - if (phys_addr == EFI_INVALID_TABLE_ADDR) - return false; - - for (i = 0; i < ARRAY_SIZE(efi_tables); i++) - if (*(efi_tables[i]) == phys_addr) - return true; - - return false; -} - static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; diff --git a/include/linux/efi.h b/include/linux/efi.h index f87fabea4a85..60a6242765d8 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1211,8 +1211,6 @@ static inline bool efi_enabled(int feature) return test_bit(feature, &efi.flags) != 0; } extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); - -extern bool efi_is_table_address(unsigned long phys_addr); #else static inline bool efi_enabled(int feature) { @@ -1226,11 +1224,6 @@ efi_capsule_pending(int *reset_type) { return false; } - -static inline bool efi_is_table_address(unsigned long phys_addr) -{ - return false; -} #endif extern int efi_status_to_err(efi_status_t status); -- GitLab From ec7e1605d79d1d469b25e396f2056e42386f512f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 25 Jun 2019 15:48:35 +0200 Subject: [PATCH 2236/7155] efi/x86: move UV_SYSTAB handling into arch/x86 The SGI UV UEFI machines are tightly coupled to the x86 architecture so there is no need to keep any awareness of its existence in the generic EFI layer, especially since we already have the infrastructure to handle arch-specific configuration tables, and were even already using it to some extent. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/uv/uv.h | 4 +++- arch/x86/platform/efi/efi.c | 6 ++++-- arch/x86/platform/uv/bios_uv.c | 10 ++++++---- drivers/firmware/efi/efi.c | 1 - include/linux/efi.h | 1 - 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index e60c45fd3679..6bc6d89d8e2a 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -12,10 +12,12 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include +extern unsigned long uv_systab_phys; + extern enum uv_system_type get_uv_system_type(void); static inline bool is_early_uv_system(void) { - return !((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab); + return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); extern int is_uv_hubless(void); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 8d9be97a5607..9866a3584765 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -59,7 +59,7 @@ static efi_system_table_t efi_systab __initdata; static efi_config_table_type_t arch_tables[] __initdata = { #ifdef CONFIG_X86_UV - {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab}, + {UV_SYSTEM_TABLE_GUID, "UVsystab", &uv_systab_phys}, #endif {NULL_GUID, NULL, NULL}, }; @@ -74,7 +74,9 @@ static const unsigned long * const efi_tables[] = { &efi.boot_info, &efi.hcdp, &efi.uga, - &efi.uv_systab, +#ifdef CONFIG_X86_UV + &uv_systab_phys, +#endif &efi.fw_vendor, &efi.runtime, &efi.config_table, diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c index 7c69652ffeea..c2ee31953372 100644 --- a/arch/x86/platform/uv/bios_uv.c +++ b/arch/x86/platform/uv/bios_uv.c @@ -14,6 +14,8 @@ #include #include +unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; + struct uv_systab *uv_systab; static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, @@ -185,13 +187,13 @@ EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); void uv_bios_init(void) { uv_systab = NULL; - if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || - !efi.uv_systab || efi_runtime_disabled()) { + if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || + !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); return; } - uv_systab = ioremap(efi.uv_systab, sizeof(struct uv_systab)); + uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); @@ -203,7 +205,7 @@ void uv_bios_init(void) int size = uv_systab->size; iounmap(uv_systab); - uv_systab = ioremap(efi.uv_systab, size); + uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); return; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index cbdbdbc8f9eb..4dfd873373bd 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -43,7 +43,6 @@ struct efi __read_mostly efi = { .boot_info = EFI_INVALID_TABLE_ADDR, .hcdp = EFI_INVALID_TABLE_ADDR, .uga = EFI_INVALID_TABLE_ADDR, - .uv_systab = EFI_INVALID_TABLE_ADDR, .fw_vendor = EFI_INVALID_TABLE_ADDR, .runtime = EFI_INVALID_TABLE_ADDR, .config_table = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h index 60a6242765d8..171bb1005a10 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -988,7 +988,6 @@ extern struct efi { unsigned long boot_info; /* boot info table */ unsigned long hcdp; /* HCDP table */ unsigned long uga; /* UGA table */ - unsigned long uv_systab; /* UV system table */ unsigned long fw_vendor; /* fw_vendor */ unsigned long runtime; /* runtime table */ unsigned long config_table; /* config tables */ -- GitLab From 5828efb95bc43ad6a59f05458d3aed9649dd5a63 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 25 Jun 2019 16:28:53 +0200 Subject: [PATCH 2237/7155] efi: ia64: move SAL systab handling out of generic EFI code The SAL systab is an Itanium specific EFI configuration table, so move its handling into arch/ia64 where it belongs. Signed-off-by: Ard Biesheuvel --- arch/ia64/include/asm/sal.h | 1 + arch/ia64/include/asm/sn/sn_sal.h | 2 +- arch/ia64/kernel/efi.c | 3 +++ arch/ia64/kernel/setup.c | 2 +- arch/x86/platform/efi/efi.c | 1 - drivers/firmware/efi/efi.c | 2 -- include/linux/efi.h | 1 - 7 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/ia64/include/asm/sal.h b/arch/ia64/include/asm/sal.h index 588f33156da6..08f5b6aaed73 100644 --- a/arch/ia64/include/asm/sal.h +++ b/arch/ia64/include/asm/sal.h @@ -43,6 +43,7 @@ #include #include +extern unsigned long sal_systab_phys; extern spinlock_t sal_lock; /* SAL spec _requires_ eight args for each call. */ diff --git a/arch/ia64/include/asm/sn/sn_sal.h b/arch/ia64/include/asm/sn/sn_sal.h index 1f5ff470a5a1..5142c444652d 100644 --- a/arch/ia64/include/asm/sn/sn_sal.h +++ b/arch/ia64/include/asm/sn/sn_sal.h @@ -167,7 +167,7 @@ static inline u32 sn_sal_rev(void) { - struct ia64_sal_systab *systab = __va(efi.sal_systab); + struct ia64_sal_systab *systab = __va(sal_systab_phys); return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor); } diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 3795d18276c4..0a34dcc435c6 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -47,8 +47,11 @@ static __initdata unsigned long palo_phys; +unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR; + static __initdata efi_config_table_type_t arch_tables[] = { {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys}, + {SAL_SYSTEM_TABLE_GUID, "SALsystab", &sal_systab_phys}, {NULL_GUID, NULL, 0}, }; diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c9cfa760cd57..0e1b4eb149b4 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -572,7 +572,7 @@ setup_arch (char **cmdline_p) find_memory(); /* process SAL system table: */ - ia64_sal_init(__va(efi.sal_systab)); + ia64_sal_init(__va(sal_systab_phys)); #ifdef CONFIG_ITANIUM ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 9866a3584765..6697c109c449 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -70,7 +70,6 @@ static const unsigned long * const efi_tables[] = { &efi.acpi20, &efi.smbios, &efi.smbios3, - &efi.sal_systab, &efi.boot_info, &efi.hcdp, &efi.uga, diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4dfd873373bd..801925c5bcfb 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -39,7 +39,6 @@ struct efi __read_mostly efi = { .acpi20 = EFI_INVALID_TABLE_ADDR, .smbios = EFI_INVALID_TABLE_ADDR, .smbios3 = EFI_INVALID_TABLE_ADDR, - .sal_systab = EFI_INVALID_TABLE_ADDR, .boot_info = EFI_INVALID_TABLE_ADDR, .hcdp = EFI_INVALID_TABLE_ADDR, .uga = EFI_INVALID_TABLE_ADDR, @@ -456,7 +455,6 @@ static __initdata efi_config_table_type_t common_tables[] = { {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, {HCDP_TABLE_GUID, "HCDP", &efi.hcdp}, {MPS_TABLE_GUID, "MPS", &efi.mps}, - {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab}, {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, diff --git a/include/linux/efi.h b/include/linux/efi.h index 171bb1005a10..f88318b85fb0 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -984,7 +984,6 @@ extern struct efi { unsigned long acpi20; /* ACPI table (ACPI 2.0) */ unsigned long smbios; /* SMBIOS table (32 bit entry point) */ unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ - unsigned long sal_systab; /* SAL system table */ unsigned long boot_info; /* boot info table */ unsigned long hcdp; /* HCDP table */ unsigned long uga; /* UGA table */ -- GitLab From 1c5fecb61255aa12a16c4c06335ab68979865914 Mon Sep 17 00:00:00 2001 From: Narendra K Date: Wed, 10 Jul 2019 18:59:15 +0000 Subject: [PATCH 2238/7155] efi: Export Runtime Configuration Interface table to sysfs System firmware advertises the address of the 'Runtime Configuration Interface table version 2 (RCI2)' via an EFI Configuration Table entry. This code retrieves the RCI2 table from the address and exports it to sysfs as a binary attribute 'rci2' under /sys/firmware/efi/tables directory. The approach adopted is similar to the attribute 'DMI' under /sys/firmware/dmi/tables. RCI2 table contains BIOS HII in XML format and is used to populate BIOS setup page in Dell EMC OpenManage Server Administrator tool. The BIOS setup page contains BIOS tokens which can be configured. Signed-off-by: Narendra K Reviewed-by: Mario Limonciello Signed-off-by: Ard Biesheuvel --- Documentation/ABI/testing/sysfs-firmware-efi | 8 + arch/x86/platform/efi/efi.c | 3 + drivers/firmware/efi/Kconfig | 13 ++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efi.c | 3 + drivers/firmware/efi/rci2-table.c | 147 +++++++++++++++++++ include/linux/efi.h | 5 + 7 files changed, 180 insertions(+) create mode 100644 drivers/firmware/efi/rci2-table.c diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi index e794eac32a90..5e4d0b27cdfe 100644 --- a/Documentation/ABI/testing/sysfs-firmware-efi +++ b/Documentation/ABI/testing/sysfs-firmware-efi @@ -28,3 +28,11 @@ Description: Displays the physical addresses of all EFI Configuration versions are always printed first, i.e. ACPI20 comes before ACPI. Users: dmidecode + +What: /sys/firmware/efi/tables/rci2 +Date: July 2019 +Contact: Narendra K , linux-bugs@dell.com +Description: Displays the content of the Runtime Configuration Interface + Table version 2 on Dell EMC PowerEdge systems in binary format +Users: It is used by Dell EMC OpenManage Server Administrator tool to + populate BIOS setup page. diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6697c109c449..c202e1b07e29 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -82,6 +82,9 @@ static const unsigned long * const efi_tables[] = { &efi.esrt, &efi.properties_table, &efi.mem_attr_table, +#ifdef CONFIG_EFI_RCI2_TABLE + &rci2_table_phys, +#endif }; u64 efi_setup; /* efi setup_data physical address */ diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index d4ea929e8b34..178ee8106828 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -180,6 +180,19 @@ config RESET_ATTACK_MITIGATION have been evicted, since otherwise it will trigger even on clean reboots. +config EFI_RCI2_TABLE + bool "EFI Runtime Configuration Interface Table Version 2 Support" + help + Displays the content of the Runtime Configuration Interface + Table version 2 on Dell EMC PowerEdge systems as a binary + attribute 'rci2' under /sys/firmware/efi/tables directory. + + RCI2 table contains BIOS HII in XML format and is used to populate + BIOS setup page in Dell EMC OpenManage Server Administrator tool. + The BIOS setup page contains BIOS tokens which can be configured. + + Say Y here for Dell EMC PowerEdge systems. + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index d2d0d2030620..4ac2de4dfa72 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o obj-$(CONFIG_EFI_TEST) += test/ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o +obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 801925c5bcfb..8f1ab04f6743 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -465,6 +465,9 @@ static __initdata efi_config_table_type_t common_tables[] = { {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log}, {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log}, {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve}, +#ifdef CONFIG_EFI_RCI2_TABLE + {DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys}, +#endif {NULL_GUID, NULL, NULL}, }; diff --git a/drivers/firmware/efi/rci2-table.c b/drivers/firmware/efi/rci2-table.c new file mode 100644 index 000000000000..3e290f96620a --- /dev/null +++ b/drivers/firmware/efi/rci2-table.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Export Runtime Configuration Interface Table Version 2 (RCI2) + * to sysfs + * + * Copyright (C) 2019 Dell Inc + * by Narendra K + * + * System firmware advertises the address of the RCI2 Table via + * an EFI Configuration Table entry. This code retrieves the RCI2 + * table from the address and exports it to sysfs as a binary + * attribute 'rci2' under /sys/firmware/efi/tables directory. + */ + +#include +#include +#include +#include +#include +#include + +#define RCI_SIGNATURE "_RC_" + +struct rci2_table_global_hdr { + u16 type; + u16 resvd0; + u16 hdr_len; + u8 rci2_sig[4]; + u16 resvd1; + u32 resvd2; + u32 resvd3; + u8 major_rev; + u8 minor_rev; + u16 num_of_structs; + u32 rci2_len; + u16 rci2_chksum; +} __packed; + +static u8 *rci2_base; +static u32 rci2_table_len; +unsigned long rci2_table_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; + +static ssize_t raw_table_read(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t pos, size_t count) +{ + memcpy(buf, attr->private + pos, count); + return count; +} + +static BIN_ATTR(rci2, S_IRUSR, raw_table_read, NULL, 0); + +static u16 checksum(void) +{ + u8 len_is_odd = rci2_table_len % 2; + u32 chksum_len = rci2_table_len; + u16 *base = (u16 *)rci2_base; + u8 buf[2] = {0}; + u32 offset = 0; + u16 chksum = 0; + + if (len_is_odd) + chksum_len -= 1; + + while (offset < chksum_len) { + chksum += *base; + offset += 2; + base++; + } + + if (len_is_odd) { + buf[0] = *(u8 *)base; + chksum += *(u16 *)(buf); + } + + return chksum; +} + +int __init efi_rci2_sysfs_init(void) +{ + struct kobject *tables_kobj; + int ret = -ENOMEM; + + rci2_base = memremap(rci2_table_phys, + sizeof(struct rci2_table_global_hdr), + MEMREMAP_WB); + if (!rci2_base) { + pr_debug("RCI2 table init failed - could not map RCI2 table\n"); + goto err; + } + + if (strncmp(rci2_base + + offsetof(struct rci2_table_global_hdr, rci2_sig), + RCI_SIGNATURE, 4)) { + pr_debug("RCI2 table init failed - incorrect signature\n"); + ret = -ENODEV; + goto err_unmap; + } + + rci2_table_len = *(u32 *)(rci2_base + + offsetof(struct rci2_table_global_hdr, + rci2_len)); + + memunmap(rci2_base); + + if (!rci2_table_len) { + pr_debug("RCI2 table init failed - incorrect table length\n"); + goto err; + } + + rci2_base = memremap(rci2_table_phys, rci2_table_len, MEMREMAP_WB); + if (!rci2_base) { + pr_debug("RCI2 table - could not map RCI2 table\n"); + goto err; + } + + if (checksum() != 0) { + pr_debug("RCI2 table - incorrect checksum\n"); + ret = -ENODEV; + goto err_unmap; + } + + tables_kobj = kobject_create_and_add("tables", efi_kobj); + if (!tables_kobj) { + pr_debug("RCI2 table - tables_kobj creation failed\n"); + goto err_unmap; + } + + bin_attr_rci2.size = rci2_table_len; + bin_attr_rci2.private = rci2_base; + ret = sysfs_create_bin_file(tables_kobj, &bin_attr_rci2); + if (ret != 0) { + pr_debug("RCI2 table - rci2 sysfs bin file creation failed\n"); + kobject_del(tables_kobj); + kobject_put(tables_kobj); + goto err_unmap; + } + + return 0; + + err_unmap: + memunmap(rci2_base); + err: + pr_debug("RCI2 table - sysfs initialization failed\n"); + return ret; +} +late_initcall(efi_rci2_sysfs_init); diff --git a/include/linux/efi.h b/include/linux/efi.h index f88318b85fb0..bd3837022307 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -692,6 +692,9 @@ void efi_native_runtime_setup(void); #define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) +/* OEM GUIDs */ +#define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) + typedef struct { efi_guid_t guid; u64 table; @@ -1713,6 +1716,8 @@ struct efi_tcg2_final_events_table { }; extern int efi_tpm_final_log_size; +extern unsigned long rci2_table_phys; + /* * efi_runtime_service() function identifiers. * "NONE" is used by efi_recover_from_page_fault() to check if the page -- GitLab From f32d0c636371788684ea14c3d05c98a7818e4d04 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 3 Jul 2019 10:41:06 +0200 Subject: [PATCH 2239/7155] dt-bindings: Rename file of DT bindings for Renesas memory controllers For consistency with the naming of (most) other documentation files for DT bindings for Renesas IP blocks rename the Renesas R-Mobile and SH-Mobile memory controllers documentation file from renesas-memory-controllers.txt to renesas,dbsc.txt. Signed-off-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../{renesas-memory-controllers.txt => renesas,dbsc.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/memory-controllers/{renesas-memory-controllers.txt => renesas,dbsc.txt} (100%) diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt similarity index 100% rename from Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt rename to Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt -- GitLab From 72a83ded7f4c30cfcdcf4e6500ff4da03970d9a4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 29 Jul 2019 09:47:57 +0200 Subject: [PATCH 2240/7155] dt-bindings: rcar-imr: Rename bindings documentation file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renesas media binding documentation files use a naming schema of 'renesas,.txt'. Rename the IMR file to match this pattern. Signed-off-by: Simon Horman Reviewed-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/media/{rcar_imr.txt => renesas,imr.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/media/{rcar_imr.txt => renesas,imr.txt} (100%) diff --git a/Documentation/devicetree/bindings/media/rcar_imr.txt b/Documentation/devicetree/bindings/media/renesas,imr.txt similarity index 100% rename from Documentation/devicetree/bindings/media/rcar_imr.txt rename to Documentation/devicetree/bindings/media/renesas,imr.txt -- GitLab From ddc8cd7d92b333e787f34a5ee3f40ba2f1a31087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 8 Aug 2019 03:03:30 +0200 Subject: [PATCH 2241/7155] dt-bindings: rcar-{csi2,vin}: Rename bindings documentation files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renesas media binding documentation files use a naming schema of 'renesas,.txt'. Rename the VIN and CSI-2 files to match this pattern. Signed-off-by: Niklas Söderlund Reviewed-by: Ulrich Hecht Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../media/{renesas,rcar-csi2.txt => renesas,csi2.txt} | 0 .../bindings/media/{rcar_vin.txt => renesas,vin.txt} | 0 MAINTAINERS | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename Documentation/devicetree/bindings/media/{renesas,rcar-csi2.txt => renesas,csi2.txt} (100%) rename Documentation/devicetree/bindings/media/{rcar_vin.txt => renesas,vin.txt} (100%) diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,csi2.txt similarity index 100% rename from Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt rename to Documentation/devicetree/bindings/media/renesas,csi2.txt diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt similarity index 100% rename from Documentation/devicetree/bindings/media/rcar_vin.txt rename to Documentation/devicetree/bindings/media/renesas,vin.txt diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..d99511331788 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10017,8 +10017,8 @@ L: linux-media@vger.kernel.org L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Supported -F: Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt -F: Documentation/devicetree/bindings/media/rcar_vin.txt +F: Documentation/devicetree/bindings/media/renesas,csi2.txt +F: Documentation/devicetree/bindings/media/renesas,vin.txt F: drivers/media/platform/rcar-vin/ MEDIA DRIVERS FOR RENESAS - VSP1 -- GitLab From 2e2c2fdc53437beffd2cf26aaf6187e602d565bc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:05:15 +0200 Subject: [PATCH 2242/7155] ACPI: PM: s2idle: Rearrange lps0_device_attach() To allow a subsequent change to be simpler, rearrange the code in lps0_device_attach() to reduce the indentation level and (while at it) make it avoid calling lpi_device_get_constraints() when lps0_device_handle is not going to be set. Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/sleep.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 9cb0532f7471..3d706938980a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -916,28 +916,30 @@ static int lps0_device_attach(struct acpi_device *adev, guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid); /* Check if the _DSM is present and as expected. */ out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL); - if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { - char bitmask = *(char *)out_obj->buffer.pointer; - - lps0_dsm_func_mask = bitmask; - lps0_device_handle = adev->handle; - /* - * Use suspend-to-idle by default if the default - * suspend mode was not set from the command line. - */ - if (mem_sleep_default > PM_SUSPEND_MEM) - mem_sleep_current = PM_SUSPEND_TO_IDLE; - - acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", - bitmask); - } else { + if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) { acpi_handle_debug(adev->handle, "_DSM function 0 evaluation failed\n"); + return 0; } + + lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer; + ACPI_FREE(out_obj); + acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", + lps0_dsm_func_mask); + + lps0_device_handle = adev->handle; + lpi_device_get_constraints(); + /* + * Use suspend-to-idle by default if the default suspend mode was not + * set from the command line. + */ + if (mem_sleep_default > PM_SUSPEND_MEM) + mem_sleep_current = PM_SUSPEND_TO_IDLE; + return 0; } -- GitLab From 068b47d0984b8756ae71702a1a87aa226cb72fe8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:05:25 +0200 Subject: [PATCH 2243/7155] ACPI: PM: s2idle: Add acpi.sleep_no_lps0 module parameter Add a module parameter to prevent the ACPI LPS0 _DSM functions from being invoked (if need be) and rework the suspend-to-idle blacklist entries in acpisleep_dmi_table[] to make them simply prevent suspend-to-idle from being used by default on the systems in question (which really is the original purpose of those entries). Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/sleep.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3d706938980a..4a94600fea39 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -89,6 +89,10 @@ bool acpi_sleep_state_supported(u8 sleep_state) } #ifdef CONFIG_ACPI_SLEEP +static bool sleep_no_lps0 __read_mostly; +module_param(sleep_no_lps0, bool, 0644); +MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface"); + static u32 acpi_target_sleep_state = ACPI_STATE_S0; u32 acpi_target_system_state(void) @@ -158,11 +162,11 @@ static int __init init_nvs_nosave(const struct dmi_system_id *d) return 0; } -static bool acpi_sleep_no_lps0; +static bool acpi_sleep_default_s3; -static int __init init_no_lps0(const struct dmi_system_id *d) +static int __init init_default_s3(const struct dmi_system_id *d) { - acpi_sleep_no_lps0 = true; + acpi_sleep_default_s3 = true; return 0; } @@ -363,7 +367,7 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { * S0 Idle firmware interface. */ { - .callback = init_no_lps0, + .callback = init_default_s3, .ident = "Dell XPS13 9360", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), @@ -376,7 +380,7 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { * https://bugzilla.kernel.org/show_bug.cgi?id=199057). */ { - .callback = init_no_lps0, + .callback = init_default_s3, .ident = "ThinkPad X1 Tablet(2016)", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -524,8 +528,9 @@ static void acpi_pm_end(void) acpi_sleep_tts_switch(acpi_target_sleep_state); } #else /* !CONFIG_ACPI_SLEEP */ +#define sleep_no_lps0 (1) #define acpi_target_sleep_state ACPI_STATE_S0 -#define acpi_sleep_no_lps0 (false) +#define acpi_sleep_default_s3 (1) static inline void acpi_sleep_dmi_check(void) {} #endif /* CONFIG_ACPI_SLEEP */ @@ -904,12 +909,6 @@ static int lps0_device_attach(struct acpi_device *adev, if (lps0_device_handle) return 0; - if (acpi_sleep_no_lps0) { - acpi_handle_info(adev->handle, - "Low Power S0 Idle interface disabled\n"); - return 0; - } - if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) return 0; @@ -937,7 +936,7 @@ static int lps0_device_attach(struct acpi_device *adev, * Use suspend-to-idle by default if the default suspend mode was not * set from the command line. */ - if (mem_sleep_default > PM_SUSPEND_MEM) + if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) mem_sleep_current = PM_SUSPEND_TO_IDLE; return 0; @@ -957,7 +956,7 @@ static int acpi_s2idle_begin(void) static int acpi_s2idle_prepare(void) { - if (lps0_device_handle) { + if (lps0_device_handle && !sleep_no_lps0) { acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); } @@ -977,7 +976,7 @@ static int acpi_s2idle_prepare(void) static void acpi_s2idle_wake(void) { - if (lps0_device_handle && pm_debug_messages_on) + if (lps0_device_handle && !sleep_no_lps0 && pm_debug_messages_on) lpi_check_constraints(); /* @@ -1025,7 +1024,7 @@ static void acpi_s2idle_restore(void) if (acpi_sci_irq_valid()) disable_irq_wake(acpi_sci_irq); - if (lps0_device_handle) { + if (lps0_device_handle && !sleep_no_lps0) { acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); } -- GitLab From fcd0a04267ac7c5d5f9a27d2af824270f2091760 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:05:33 +0200 Subject: [PATCH 2244/7155] ACPI: PM: s2idle: Switch EC over to polling during "noirq" suspend Since the ACPI SCI is set up for system wakeup before the "noirq" suspend of devices, it is better to make suspend-to-idle follow suspend-to-RAM (S3) and switch over the EC to polling during "noirq" suspend (and back to interrupt-based flow during "noirq" resume). The frequency of spurious wakeup interrupts from the EC may be reduced this way. Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/ec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b996ca5f253f..5a38409114d8 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1958,8 +1958,7 @@ static int acpi_ec_suspend_noirq(struct device *dev) ec->reference_count >= 1) acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); - if (acpi_sleep_no_ec_events()) - acpi_ec_enter_noirq(ec); + acpi_ec_enter_noirq(ec); return 0; } @@ -1968,8 +1967,7 @@ static int acpi_ec_resume_noirq(struct device *dev) { struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); - if (acpi_sleep_no_ec_events()) - acpi_ec_leave_noirq(ec); + acpi_ec_leave_noirq(ec); if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) && ec->reference_count >= 1) -- GitLab From 6e86633a791fdf631617ef3a9af3263141d34bc9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:05:42 +0200 Subject: [PATCH 2245/7155] ACPI: PM: s2idle: Eliminate acpi_sleep_no_ec_events() Change acpi_ec_suspend() to use pm_suspend_no_platform() instead of acpi_sleep_no_ec_events(), which allows the latter to be eliminated along with the s2idle_in_progress variable which is only used by it. Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/ec.c | 2 +- drivers/acpi/internal.h | 2 -- drivers/acpi/sleep.c | 9 --------- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 5a38409114d8..be29b9919e2d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1941,7 +1941,7 @@ static int acpi_ec_suspend(struct device *dev) struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); - if (acpi_sleep_no_ec_events() && ec_freeze_events) + if (!pm_suspend_no_platform() && ec_freeze_events) acpi_ec_disable_event(ec); return 0; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index bcc080511197..8c9cd3733f07 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -210,11 +210,9 @@ void acpi_ec_flush_work(void); -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT extern bool acpi_s2idle_wakeup(void); -extern bool acpi_sleep_no_ec_events(void); extern int acpi_sleep_init(void); #else static inline bool acpi_s2idle_wakeup(void) { return false; } -static inline bool acpi_sleep_no_ec_events(void) { return true; } static inline int acpi_sleep_init(void) { return -ENXIO; } #endif diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4a94600fea39..864bb18d3a5d 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -696,7 +696,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { .recover = acpi_pm_finish, }; -static bool s2idle_in_progress; static bool s2idle_wakeup; /* @@ -950,7 +949,6 @@ static struct acpi_scan_handler lps0_handler = { static int acpi_s2idle_begin(void) { acpi_scan_lock_acquire(); - s2idle_in_progress = true; return 0; } @@ -1032,7 +1030,6 @@ static void acpi_s2idle_restore(void) static void acpi_s2idle_end(void) { - s2idle_in_progress = false; acpi_scan_lock_release(); } @@ -1060,7 +1057,6 @@ static void acpi_sleep_suspend_setup(void) } #else /* !CONFIG_SUSPEND */ -#define s2idle_in_progress (false) #define s2idle_wakeup (false) #define lps0_device_handle (NULL) static inline void acpi_sleep_suspend_setup(void) {} @@ -1071,11 +1067,6 @@ bool acpi_s2idle_wakeup(void) return s2idle_wakeup; } -bool acpi_sleep_no_ec_events(void) -{ - return !s2idle_in_progress; -} - #ifdef CONFIG_PM_SLEEP static u32 saved_bm_rld; -- GitLab From d7589404932be148fabe696b56b7c391bad6bdb1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:05:52 +0200 Subject: [PATCH 2246/7155] ACPI: EC: PM: Consolidate some code depending on PM_SLEEP Move some routines, including acpi_ec_dispatch_gpe(), that are only used if CONFIG_PM_SLEEP is set to the #ifdef block containing the EC suspend and resume callbacks, to make the "full EC PM picture" easier to follow. While at it, move the header of acpi_ec_dispatch_gpe() in the header file to a CONFIG_PM_SLEEP #ifdef block. Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/ec.c | 54 ++++++++++++++++++++--------------------- drivers/acpi/internal.h | 2 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index be29b9919e2d..8d7247b4441f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1049,33 +1049,6 @@ void acpi_ec_unblock_transactions(void) acpi_ec_start(first_ec, true); } -#ifdef CONFIG_PM_SLEEP -void acpi_ec_mark_gpe_for_wake(void) -{ - if (first_ec && !ec_no_wakeup) - acpi_mark_gpe_for_wake(NULL, first_ec->gpe); -} -EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake); - -void acpi_ec_set_gpe_wake_mask(u8 action) -{ - if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) - acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); -} -EXPORT_SYMBOL_GPL(acpi_ec_set_gpe_wake_mask); -#endif - -bool acpi_ec_dispatch_gpe(void) -{ - u32 ret; - - if (!first_ec) - return false; - - ret = acpi_dispatch_gpe(NULL, first_ec->gpe); - return ret == ACPI_INTERRUPT_HANDLED; -} - /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ @@ -1984,7 +1957,32 @@ static int acpi_ec_resume(struct device *dev) acpi_ec_enable_event(ec); return 0; } -#endif + +void acpi_ec_mark_gpe_for_wake(void) +{ + if (first_ec && !ec_no_wakeup) + acpi_mark_gpe_for_wake(NULL, first_ec->gpe); +} +EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake); + +void acpi_ec_set_gpe_wake_mask(u8 action) +{ + if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) + acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); +} +EXPORT_SYMBOL_GPL(acpi_ec_set_gpe_wake_mask); + +bool acpi_ec_dispatch_gpe(void) +{ + u32 ret; + + if (!first_ec) + return false; + + ret = acpi_dispatch_gpe(NULL, first_ec->gpe); + return ret == ACPI_INTERRUPT_HANDLED; +} +#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops acpi_ec_pm = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8c9cd3733f07..afe6636f9ad3 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -194,7 +194,6 @@ void acpi_ec_ecdt_probe(void); void acpi_ec_dsdt_probe(void); void acpi_ec_block_transactions(void); void acpi_ec_unblock_transactions(void); -bool acpi_ec_dispatch_gpe(void); int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, void *data); @@ -202,6 +201,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); #ifdef CONFIG_PM_SLEEP void acpi_ec_flush_work(void); +bool acpi_ec_dispatch_gpe(void); #endif -- GitLab From 29113f2f0a7d8d5332bfdfdfca995c06d0896e83 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 31 Jul 2019 11:06:00 +0200 Subject: [PATCH 2247/7155] ACPI: EC: PM: Make acpi_ec_dispatch_gpe() print debug message Add a pm_pr_dbg() debug statement to acpi_ec_dispatch_gpe() to print a message when the EC GPE has been dispatched (because its status was set). Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/ec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 8d7247b4441f..58597ec813eb 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1980,7 +1980,11 @@ bool acpi_ec_dispatch_gpe(void) return false; ret = acpi_dispatch_gpe(NULL, first_ec->gpe); - return ret == ACPI_INTERRUPT_HANDLED; + if (ret == ACPI_INTERRUPT_HANDLED) { + pm_pr_dbg("EC GPE dispatched\n"); + return true; + } + return false; } #endif /* CONFIG_PM_SLEEP */ -- GitLab From ac9eafbe930abb589e9289842a99cc575cadb854 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 1 Aug 2019 19:31:10 +0200 Subject: [PATCH 2248/7155] ACPI: PM: s2idle: Execute LPS0 _DSM functions with suspended devices According to Section 3.5 of the "Intel Low Power S0 Idle" document [1], Function 5 of the LPS0 _DSM is expected to be invoked when the system configuration matches the criteria for entering the target low-power state of the platform. In particular, this means that all devices should be suspended and in low-power states already when that function is invoked. This is not the case currently, however, because Function 5 of the LPS0 _DSM is invoked by it before the "noirq" phase of device suspend, which means that some devices may not have been put into low-power states yet at that point. That is a consequence of the previous design of the suspend-to-idle flow that allowed the "noirq" phase of device suspend and the "noirq" phase of device resume to be carried out for multiple times while "suspended" (if any spurious wakeup events were detected) and the point of the LPS0 _DSM Function 5 invocation was chosen so as to call it (and LPS0 _DSM Function 6 analogously) once per suspend-resume cycle (regardless of how many times the "noirq" phases of device suspend and resume were carried out while "suspended"). Now that the suspend-to-idle flow has been redesigned to carry out the "noirq" phases of device suspend and resume once in each cycle, the code can be reordered to follow the specification that it is based on more closely. For this purpose, add ->prepare_late and ->restore_early platform callbacks for suspend-to-idle, to be executed, respectively, after the "noirq" phase of suspending devices and before the "noirq" phase of resuming them and make ACPI use them for the invocation of LPS0 _DSM functions as appropriate. While at it, move the LPS0 entry requirements check to be made before invoking Functions 3 and 5 of the LPS0 _DSM (also once per cycle) as follows from the specification [1]. Link: https://uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf # [1] Signed-off-by: Rafael J. Wysocki Tested-by: Kai-Heng Feng --- drivers/acpi/sleep.c | 36 ++++++++++++++++++++++++------------ include/linux/suspend.h | 2 ++ kernel/power/suspend.c | 12 +++++++++--- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 864bb18d3a5d..8f7e95f97e1f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -954,11 +954,6 @@ static int acpi_s2idle_begin(void) static int acpi_s2idle_prepare(void) { - if (lps0_device_handle && !sleep_no_lps0) { - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); - } - if (acpi_sci_irq_valid()) enable_irq_wake(acpi_sci_irq); @@ -972,11 +967,22 @@ static int acpi_s2idle_prepare(void) return 0; } -static void acpi_s2idle_wake(void) +static int acpi_s2idle_prepare_late(void) { - if (lps0_device_handle && !sleep_no_lps0 && pm_debug_messages_on) + if (!lps0_device_handle || sleep_no_lps0) + return 0; + + if (pm_debug_messages_on) lpi_check_constraints(); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); + + return 0; +} + +static void acpi_s2idle_wake(void) +{ /* * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has * not triggered while suspended, so bail out. @@ -1011,6 +1017,15 @@ static void acpi_s2idle_wake(void) rearm_wake_irq(acpi_sci_irq); } +static void acpi_s2idle_restore_early(void) +{ + if (!lps0_device_handle || sleep_no_lps0) + return; + + acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); +} + static void acpi_s2idle_restore(void) { s2idle_wakeup = false; @@ -1021,11 +1036,6 @@ static void acpi_s2idle_restore(void) if (acpi_sci_irq_valid()) disable_irq_wake(acpi_sci_irq); - - if (lps0_device_handle && !sleep_no_lps0) { - acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); - } } static void acpi_s2idle_end(void) @@ -1036,7 +1046,9 @@ static void acpi_s2idle_end(void) static const struct platform_s2idle_ops acpi_s2idle_ops = { .begin = acpi_s2idle_begin, .prepare = acpi_s2idle_prepare, + .prepare_late = acpi_s2idle_prepare_late, .wake = acpi_s2idle_wake, + .restore_early = acpi_s2idle_restore_early, .restore = acpi_s2idle_restore, .end = acpi_s2idle_end, }; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f0c4a8445140..6fc8843f1c9e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -190,7 +190,9 @@ struct platform_suspend_ops { struct platform_s2idle_ops { int (*begin)(void); int (*prepare)(void); + int (*prepare_late)(void); void (*wake)(void); + void (*restore_early)(void); void (*restore)(void); void (*end)(void); }; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2b6057853b33..ed9ddef12b13 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -253,13 +253,19 @@ static int platform_suspend_prepare_late(suspend_state_t state) static int platform_suspend_prepare_noirq(suspend_state_t state) { - return state != PM_SUSPEND_TO_IDLE && suspend_ops->prepare_late ? - suspend_ops->prepare_late() : 0; + if (state == PM_SUSPEND_TO_IDLE) { + if (s2idle_ops && s2idle_ops->prepare_late) + return s2idle_ops->prepare_late(); + } + return suspend_ops->prepare_late ? suspend_ops->prepare_late() : 0; } static void platform_resume_noirq(suspend_state_t state) { - if (state != PM_SUSPEND_TO_IDLE && suspend_ops->wake) + if (state == PM_SUSPEND_TO_IDLE) { + if (s2idle_ops && s2idle_ops->restore_early) + s2idle_ops->restore_early(); + } else if (suspend_ops->wake) suspend_ops->wake(); } -- GitLab From ee8193ee96c7802b5ba766243c4c950059a43323 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 2 Aug 2019 12:26:02 +0200 Subject: [PATCH 2249/7155] ACPI: PM: Print debug messages on device power state changes Add an acpi_handle_debug() statement to acpi_device_set_power() to allow ACPI device power state changes to be tracked. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index f616b16c1f0b..4cb93d4f2ab6 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -166,6 +166,10 @@ int acpi_device_set_power(struct acpi_device *device, int state) || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) return -EINVAL; + acpi_handle_debug(device->handle, "Power state change: %s -> %s\n", + acpi_power_state_string(device->power.state), + acpi_power_state_string(state)); + /* Make sure this is a valid target state */ /* There is a special case for D0 addressed below. */ -- GitLab From b6fd948832496f01750d6c87dfdcef713043da4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Aug 2019 11:25:09 +0200 Subject: [PATCH 2250/7155] MAINTAINERS: mark wusbcore and UWB as obsolete Joe rightly points out that we should be using the "Obsolete" status for these two subsystems. Also I got the path name wrong for the wusbcore tree. Reported-by: Joe Perches Fixes: 71ed79b0e4be ("USB: Move wusbcore and UWB to staging as it is obsolete") Link: https://lore.kernel.org/r/20190808092509.GA20173@kroah.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f4463fb48249..6f2d988fe7b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3801,8 +3801,8 @@ F: scripts/extract-cert.c CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: L: devel@driverdev.osuosl.org -S: Orphan -F: drivers/staging/wbusbcore/ +S: Obsolete +F: drivers/staging/wusbcore/ CFAG12864B LCD DRIVER M: Miguel Ojeda Sandonis @@ -16443,7 +16443,7 @@ F: include/linux/ulpi/ ULTRA-WIDEBAND (UWB) SUBSYSTEM: L: devel@driverdev.osuosl.org -S: Orphan +S: Obsolete F: drivers/staging/uwb/ UNICODE SUBSYSTEM: -- GitLab From 9603a7ab60989f586786f082a8b1e3bf6fbcc749 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 15 Jul 2019 11:17:16 +0800 Subject: [PATCH 2251/7155] dmaengine: imx-sdma: Remove call to memset after dma_alloc_coherent In commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*"), dma_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Link: https://lore.kernel.org/r/20190715031716.6328-1-huangfq.daxian@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a01f4b5d793c..9ba74ab7e912 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1886,10 +1886,6 @@ static int sdma_init(struct sdma_engine *sdma) sdma->context_phys = ccb_phys + MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control); - /* Zero-out the CCB structures array just allocated */ - memset(sdma->channel_control, 0, - MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control)); - /* disable all channels */ for (i = 0; i < sdma->drvdata->num_events; i++) writel_relaxed(0, sdma->regs + chnenbl_ofs(sdma, i)); -- GitLab From 719e25dba4430a7f2b1e77fa962f0527ebc9371d Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Mon, 15 Jul 2019 11:17:23 +0800 Subject: [PATCH 2252/7155] dmaengine: qcom_hidma: Remove call to memset after dmam_alloc_coherent In commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*"), dma_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Acked-by: Sinan Kaya Link: https://lore.kernel.org/r/20190715031723.6375-1-huangfq.daxian@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_ll.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c index 5bf8b145c427..bb4471e84e48 100644 --- a/drivers/dma/qcom/hidma_ll.c +++ b/drivers/dma/qcom/hidma_ll.c @@ -749,7 +749,6 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres, if (!lldev->tre_ring) return NULL; - memset(lldev->tre_ring, 0, (HIDMA_TRE_SIZE + 1) * nr_tres); lldev->tre_ring_size = HIDMA_TRE_SIZE * nr_tres; lldev->nr_tres = nr_tres; @@ -769,7 +768,6 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres, if (!lldev->evre_ring) return NULL; - memset(lldev->evre_ring, 0, (HIDMA_EVRE_SIZE + 1) * nr_tres); lldev->evre_ring_size = HIDMA_EVRE_SIZE * nr_tres; /* the EVRE ring has to be EVRE_SIZE aligned */ -- GitLab From 232a7f18cf8ecbd92a8cc6ca7feee4f6aab668fe Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Wed, 24 Jul 2019 15:20:34 +0800 Subject: [PATCH 2253/7155] dmaengine: fsl-edma: add i.mx7ulp edma2 version support Add edma2 for i.mx7ulp by version v3, since v2 has already been used by mcf-edma. The big changes based on v1 are belows: 1. only one dmamux. 2. another clock dma_clk except dmamux clk. 3. 16 independent interrupts instead of only one interrupt for all channels. Signed-off-by: Robin Gong Link: https://lore.kernel.org/r/1563952834-7731-1-git-send-email-yibin.gong@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-common.c | 18 +++++++++- drivers/dma/fsl-edma-common.h | 4 +++ drivers/dma/fsl-edma.c | 65 +++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c index 44d92c34dec3..6d6d8a4e8e38 100644 --- a/drivers/dma/fsl-edma-common.c +++ b/drivers/dma/fsl-edma-common.c @@ -90,6 +90,19 @@ static void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *addr, iowrite8(val8, addr + off); } +void mux_configure32(struct fsl_edma_chan *fsl_chan, void __iomem *addr, + u32 off, u32 slot, bool enable) +{ + u32 val; + + if (enable) + val = EDMAMUX_CHCFG_ENBL << 24 | slot; + else + val = EDMAMUX_CHCFG_DIS; + + iowrite32(val, addr + off * 4); +} + void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan, unsigned int slot, bool enable) { @@ -103,7 +116,10 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan, muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux]; slot = EDMAMUX_CHCFG_SOURCE(slot); - mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable); + if (fsl_chan->edma->drvdata->version == v3) + mux_configure32(fsl_chan, muxaddr, ch_off, slot, enable); + else + mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable); } EXPORT_SYMBOL_GPL(fsl_edma_chan_mux); diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h index 4e175560292c..5eaa2902ed39 100644 --- a/drivers/dma/fsl-edma-common.h +++ b/drivers/dma/fsl-edma-common.h @@ -125,6 +125,7 @@ struct fsl_edma_chan { dma_addr_t dma_dev_addr; u32 dma_dev_size; enum dma_data_direction dma_dir; + char chan_name[16]; }; struct fsl_edma_desc { @@ -139,11 +140,13 @@ struct fsl_edma_desc { enum edma_version { v1, /* 32ch, Vybrid, mpc57x, etc */ v2, /* 64ch Coldfire */ + v3, /* 32ch, i.mx7ulp */ }; struct fsl_edma_drvdata { enum edma_version version; u32 dmamuxs; + bool has_dmaclk; int (*setup_irq)(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma); }; @@ -153,6 +156,7 @@ struct fsl_edma_engine { void __iomem *membase; void __iomem *muxbase[DMAMUX_NR]; struct clk *muxclk[DMAMUX_NR]; + struct clk *dmaclk; struct mutex fsl_edma_mutex; const struct fsl_edma_drvdata *drvdata; u32 n_chans; diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c index 71650fa01f18..dfce75c2991b 100644 --- a/drivers/dma/fsl-edma.c +++ b/drivers/dma/fsl-edma.c @@ -158,6 +158,49 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma return 0; } +static int +fsl_edma2_irq_init(struct platform_device *pdev, + struct fsl_edma_engine *fsl_edma) +{ + int i, ret, irq; + int count; + + count = platform_irq_count(pdev); + dev_dbg(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count); + if (count <= 2) { + dev_err(&pdev->dev, "Interrupts in DTS not correct.\n"); + return -EINVAL; + } + /* + * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp. + * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17... + * For now, just simply request irq without IRQF_SHARED flag, since 16 + * channels are enough on i.mx7ulp whose M4 domain own some peripherals. + */ + for (i = 0; i < count; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) + return -ENXIO; + + sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i); + + /* The last IRQ is for eDMA err */ + if (i == count - 1) + ret = devm_request_irq(&pdev->dev, irq, + fsl_edma_err_handler, + 0, "eDMA2-ERR", fsl_edma); + else + ret = devm_request_irq(&pdev->dev, irq, + fsl_edma_tx_handler, 0, + fsl_edma->chans[i].chan_name, + fsl_edma); + if (ret) + return ret; + } + + return 0; +} + static void fsl_edma_irq_exit( struct platform_device *pdev, struct fsl_edma_engine *fsl_edma) { @@ -183,8 +226,16 @@ static struct fsl_edma_drvdata vf610_data = { .setup_irq = fsl_edma_irq_init, }; +static struct fsl_edma_drvdata imx7ulp_data = { + .version = v3, + .dmamuxs = 1, + .has_dmaclk = true, + .setup_irq = fsl_edma2_irq_init, +}; + static const struct of_device_id fsl_edma_dt_ids[] = { { .compatible = "fsl,vf610-edma", .data = &vf610_data}, + { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids); @@ -232,6 +283,20 @@ static int fsl_edma_probe(struct platform_device *pdev) fsl_edma_setup_regs(fsl_edma); regs = &fsl_edma->regs; + if (drvdata->has_dmaclk) { + fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma"); + if (IS_ERR(fsl_edma->dmaclk)) { + dev_err(&pdev->dev, "Missing DMA block clock.\n"); + return PTR_ERR(fsl_edma->dmaclk); + } + + ret = clk_prepare_enable(fsl_edma->dmaclk); + if (ret) { + dev_err(&pdev->dev, "DMA clk block failed.\n"); + return ret; + } + } + for (i = 0; i < fsl_edma->drvdata->dmamuxs; i++) { char clkname[32]; -- GitLab From 057b05d5ac4745e7999656223bc6426c0129ba86 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Wed, 24 Jul 2019 13:46:09 +0530 Subject: [PATCH 2254/7155] dmaengine: qcom: hidma_mgmt: Add of_node_put() before goto Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a goto from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put under the label that the gotos point to. In order to avoid decrementing an already-decremented refcount, copy the original contents of the label (including the return statement) to just above the label, so that the code under the label is executed only when a goto exit from the loop occurs. Additionally, remove an unnecessary get/put pair from the loop, as the loop itself already keeps track of refcount. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Acked-by: Sinan Kaya Link: https://lore.kernel.org/r/20190724081609.9724-1-nishkadg.linux@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/qcom/hidma_mgmt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 7cb81a50f3f3..806ca02c52d7 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -387,7 +387,6 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) ret = PTR_ERR(new_pdev); goto out; } - of_node_get(child); new_pdev->dev.of_node = child; of_dma_configure(&new_pdev->dev, child, true); /* @@ -395,9 +394,14 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) * platforms with or without MSI support. */ of_msi_configure(&new_pdev->dev, child); - of_node_put(child); } + + kfree(res); + + return ret; + out: + of_node_put(child); kfree(res); return ret; -- GitLab From 587e6c10a7ce89a5924fdbeff2ec524fbd6a124b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:16:25 +0100 Subject: [PATCH 2255/7155] iommu/arm-smmu-v3: Reduce contention during command-queue insertion The SMMU command queue is a bottleneck in large systems, thanks to the spin_lock which serialises accesses from all CPUs to the single queue supported by the hardware. Attempt to improve this situation by moving to a new algorithm for inserting commands into the queue, which is lock-free on the fast-path. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 677 ++++++++++++++++++++++++++++-------- 1 file changed, 533 insertions(+), 144 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 9ebb8b39a3b1..202b4b6fc70a 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -183,7 +183,7 @@ #define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1)) #define Q_WRP(llq, p) ((p) & (1 << (llq)->max_n_shift)) -#define Q_OVERFLOW_FLAG (1 << 31) +#define Q_OVERFLOW_FLAG (1U << 31) #define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) #define Q_ENT(q, p) ((q)->base + \ Q_IDX(&((q)->llq), p) * \ @@ -307,6 +307,8 @@ #define CMDQ_ERR_CERROR_ABT_IDX 2 #define CMDQ_ERR_CERROR_ATC_INV_IDX 3 +#define CMDQ_PROD_OWNED_FLAG Q_OVERFLOW_FLAG + #define CMDQ_0_OP GENMASK_ULL(7, 0) #define CMDQ_0_SSV (1UL << 11) @@ -369,9 +371,8 @@ #define PRIQ_1_ADDR_MASK GENMASK_ULL(63, 12) /* High-level queue structures */ -#define ARM_SMMU_POLL_TIMEOUT_US 100 -#define ARM_SMMU_CMDQ_SYNC_TIMEOUT_US 1000000 /* 1s! */ -#define ARM_SMMU_CMDQ_SYNC_SPIN_COUNT 10 +#define ARM_SMMU_POLL_TIMEOUT_US 1000000 /* 1s! */ +#define ARM_SMMU_POLL_SPIN_COUNT 10 #define MSI_IOVA_BASE 0x8000000 #define MSI_IOVA_LENGTH 0x100000 @@ -473,15 +474,24 @@ struct arm_smmu_cmdq_ent { #define CMDQ_OP_CMD_SYNC 0x46 struct { - u32 msidata; u64 msiaddr; } sync; }; }; struct arm_smmu_ll_queue { - u32 prod; - u32 cons; + union { + u64 val; + struct { + u32 prod; + u32 cons; + }; + struct { + atomic_t prod; + atomic_t cons; + } atomic; + u8 __pad[SMP_CACHE_BYTES]; + } ____cacheline_aligned_in_smp; u32 max_n_shift; }; @@ -499,9 +509,18 @@ struct arm_smmu_queue { u32 __iomem *cons_reg; }; +struct arm_smmu_queue_poll { + ktime_t timeout; + unsigned int delay; + unsigned int spin_cnt; + bool wfe; +}; + struct arm_smmu_cmdq { struct arm_smmu_queue q; - spinlock_t lock; + atomic_long_t *valid_map; + atomic_t owner_prod; + atomic_t lock; }; struct arm_smmu_evtq { @@ -581,8 +600,6 @@ struct arm_smmu_device { int gerr_irq; int combined_irq; - u32 sync_nr; - u8 prev_cmd_opcode; unsigned long ias; /* IPA */ unsigned long oas; /* PA */ @@ -601,12 +618,6 @@ struct arm_smmu_device { struct arm_smmu_strtab_cfg strtab_cfg; - /* Hi16xx adds an extra 32 bits of goodness to its MSI payload */ - union { - u32 sync_count; - u64 padding; - }; - /* IOMMU core code handle */ struct iommu_device iommu; }; @@ -690,6 +701,21 @@ static void parse_driver_options(struct arm_smmu_device *smmu) } /* Low-level queue manipulation functions */ +static bool queue_has_space(struct arm_smmu_ll_queue *q, u32 n) +{ + u32 space, prod, cons; + + prod = Q_IDX(q, q->prod); + cons = Q_IDX(q, q->cons); + + if (Q_WRP(q, q->prod) == Q_WRP(q, q->cons)) + space = (1 << q->max_n_shift) - (prod - cons); + else + space = cons - prod; + + return space >= n; +} + static bool queue_full(struct arm_smmu_ll_queue *q) { return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && @@ -702,9 +728,12 @@ static bool queue_empty(struct arm_smmu_ll_queue *q) Q_WRP(q, q->prod) == Q_WRP(q, q->cons); } -static void queue_sync_cons_in(struct arm_smmu_queue *q) +static bool queue_consumed(struct arm_smmu_ll_queue *q, u32 prod) { - q->llq.cons = readl_relaxed(q->cons_reg); + return ((Q_WRP(q, q->cons) == Q_WRP(q, prod)) && + (Q_IDX(q, q->cons) > Q_IDX(q, prod))) || + ((Q_WRP(q, q->cons) != Q_WRP(q, prod)) && + (Q_IDX(q, q->cons) <= Q_IDX(q, prod))); } static void queue_sync_cons_out(struct arm_smmu_queue *q) @@ -735,46 +764,34 @@ static int queue_sync_prod_in(struct arm_smmu_queue *q) return ret; } -static void queue_sync_prod_out(struct arm_smmu_queue *q) +static u32 queue_inc_prod_n(struct arm_smmu_ll_queue *q, int n) { - writel(q->llq.prod, q->prod_reg); + u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + n; + return Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); } -static void queue_inc_prod(struct arm_smmu_ll_queue *q) +static void queue_poll_init(struct arm_smmu_device *smmu, + struct arm_smmu_queue_poll *qp) { - u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + 1; - q->prod = Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); + qp->delay = 1; + qp->spin_cnt = 0; + qp->wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV); + qp->timeout = ktime_add_us(ktime_get(), ARM_SMMU_POLL_TIMEOUT_US); } -/* - * Wait for the SMMU to consume items. If sync is true, wait until the queue - * is empty. Otherwise, wait until there is at least one free slot. - */ -static int queue_poll_cons(struct arm_smmu_queue *q, bool sync, bool wfe) +static int queue_poll(struct arm_smmu_queue_poll *qp) { - ktime_t timeout; - unsigned int delay = 1, spin_cnt = 0; - - /* Wait longer if it's a CMD_SYNC */ - timeout = ktime_add_us(ktime_get(), sync ? - ARM_SMMU_CMDQ_SYNC_TIMEOUT_US : - ARM_SMMU_POLL_TIMEOUT_US); - - while (queue_sync_cons_in(q), - (sync ? !queue_empty(&q->llq) : queue_full(&q->llq))) { - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; + if (ktime_compare(ktime_get(), qp->timeout) > 0) + return -ETIMEDOUT; - if (wfe) { - wfe(); - } else if (++spin_cnt < ARM_SMMU_CMDQ_SYNC_SPIN_COUNT) { - cpu_relax(); - continue; - } else { - udelay(delay); - delay *= 2; - spin_cnt = 0; - } + if (qp->wfe) { + wfe(); + } else if (++qp->spin_cnt < ARM_SMMU_POLL_SPIN_COUNT) { + cpu_relax(); + } else { + udelay(qp->delay); + qp->delay *= 2; + qp->spin_cnt = 0; } return 0; @@ -788,17 +805,6 @@ static void queue_write(__le64 *dst, u64 *src, size_t n_dwords) *dst++ = cpu_to_le64(*src++); } -static int queue_insert_raw(struct arm_smmu_queue *q, u64 *ent) -{ - if (queue_full(&q->llq)) - return -ENOSPC; - - queue_write(Q_ENT(q, q->llq.prod), ent, q->ent_dwords); - queue_inc_prod(&q->llq); - queue_sync_prod_out(q); - return 0; -} - static void queue_read(__le64 *dst, u64 *src, size_t n_dwords) { int i; @@ -881,20 +887,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp); break; case CMDQ_OP_CMD_SYNC: - if (ent->sync.msiaddr) + if (ent->sync.msiaddr) { cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_IRQ); - else + cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK; + } else { cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV); + } cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH); cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB); - /* - * Commands are written little-endian, but we want the SMMU to - * receive MSIData, and thus write it back to memory, in CPU - * byte order, so big-endian needs an extra byteswap here. - */ - cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIDATA, - cpu_to_le32(ent->sync.msidata)); - cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK; break; default: return -ENOENT; @@ -903,6 +903,27 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) return 0; } +static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu, + u32 prod) +{ + struct arm_smmu_queue *q = &smmu->cmdq.q; + struct arm_smmu_cmdq_ent ent = { + .opcode = CMDQ_OP_CMD_SYNC, + }; + + /* + * Beware that Hi16xx adds an extra 32 bits of goodness to its MSI + * payload, so the write will zero the entire command on that platform. + */ + if (smmu->features & ARM_SMMU_FEAT_MSI && + smmu->features & ARM_SMMU_FEAT_COHERENCY) { + ent.sync.msiaddr = q->base_dma + Q_IDX(&q->llq, prod) * + q->ent_dwords * 8; + } + + arm_smmu_cmdq_build_cmd(cmd, &ent); +} + static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) { static const char *cerror_str[] = { @@ -961,109 +982,440 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) queue_write(Q_ENT(q, cons), cmd, q->ent_dwords); } -static void arm_smmu_cmdq_insert_cmd(struct arm_smmu_device *smmu, u64 *cmd) +/* + * Command queue locking. + * This is a form of bastardised rwlock with the following major changes: + * + * - The only LOCK routines are exclusive_trylock() and shared_lock(). + * Neither have barrier semantics, and instead provide only a control + * dependency. + * + * - The UNLOCK routines are supplemented with shared_tryunlock(), which + * fails if the caller appears to be the last lock holder (yes, this is + * racy). All successful UNLOCK routines have RELEASE semantics. + */ +static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq) { - struct arm_smmu_queue *q = &smmu->cmdq.q; - bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV); + int val; - smmu->prev_cmd_opcode = FIELD_GET(CMDQ_0_OP, cmd[0]); + /* + * We can try to avoid the cmpxchg() loop by simply incrementing the + * lock counter. When held in exclusive state, the lock counter is set + * to INT_MIN so these increments won't hurt as the value will remain + * negative. + */ + if (atomic_fetch_inc_relaxed(&cmdq->lock) >= 0) + return; + + do { + val = atomic_cond_read_relaxed(&cmdq->lock, VAL >= 0); + } while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) != val); +} + +static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq) +{ + (void)atomic_dec_return_release(&cmdq->lock); +} + +static bool arm_smmu_cmdq_shared_tryunlock(struct arm_smmu_cmdq *cmdq) +{ + if (atomic_read(&cmdq->lock) == 1) + return false; + + arm_smmu_cmdq_shared_unlock(cmdq); + return true; +} + +#define arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags) \ +({ \ + bool __ret; \ + local_irq_save(flags); \ + __ret = !atomic_cmpxchg_relaxed(&cmdq->lock, 0, INT_MIN); \ + if (!__ret) \ + local_irq_restore(flags); \ + __ret; \ +}) + +#define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags) \ +({ \ + atomic_set_release(&cmdq->lock, 0); \ + local_irq_restore(flags); \ +}) + + +/* + * Command queue insertion. + * This is made fiddly by our attempts to achieve some sort of scalability + * since there is one queue shared amongst all of the CPUs in the system. If + * you like mixed-size concurrency, dependency ordering and relaxed atomics, + * then you'll *love* this monstrosity. + * + * The basic idea is to split the queue up into ranges of commands that are + * owned by a given CPU; the owner may not have written all of the commands + * itself, but is responsible for advancing the hardware prod pointer when + * the time comes. The algorithm is roughly: + * + * 1. Allocate some space in the queue. At this point we also discover + * whether the head of the queue is currently owned by another CPU, + * or whether we are the owner. + * + * 2. Write our commands into our allocated slots in the queue. + * + * 3. Mark our slots as valid in arm_smmu_cmdq.valid_map. + * + * 4. If we are an owner: + * a. Wait for the previous owner to finish. + * b. Mark the queue head as unowned, which tells us the range + * that we are responsible for publishing. + * c. Wait for all commands in our owned range to become valid. + * d. Advance the hardware prod pointer. + * e. Tell the next owner we've finished. + * + * 5. If we are inserting a CMD_SYNC (we may or may not have been an + * owner), then we need to stick around until it has completed: + * a. If we have MSIs, the SMMU can write back into the CMD_SYNC + * to clear the first 4 bytes. + * b. Otherwise, we spin waiting for the hardware cons pointer to + * advance past our command. + * + * The devil is in the details, particularly the use of locking for handling + * SYNC completion and freeing up space in the queue before we think that it is + * full. + */ +static void __arm_smmu_cmdq_poll_set_valid_map(struct arm_smmu_cmdq *cmdq, + u32 sprod, u32 eprod, bool set) +{ + u32 swidx, sbidx, ewidx, ebidx; + struct arm_smmu_ll_queue llq = { + .max_n_shift = cmdq->q.llq.max_n_shift, + .prod = sprod, + }; - while (queue_insert_raw(q, cmd) == -ENOSPC) { - if (queue_poll_cons(q, false, wfe)) - dev_err_ratelimited(smmu->dev, "CMDQ timeout\n"); + ewidx = BIT_WORD(Q_IDX(&llq, eprod)); + ebidx = Q_IDX(&llq, eprod) % BITS_PER_LONG; + + while (llq.prod != eprod) { + unsigned long mask; + atomic_long_t *ptr; + u32 limit = BITS_PER_LONG; + + swidx = BIT_WORD(Q_IDX(&llq, llq.prod)); + sbidx = Q_IDX(&llq, llq.prod) % BITS_PER_LONG; + + ptr = &cmdq->valid_map[swidx]; + + if ((swidx == ewidx) && (sbidx < ebidx)) + limit = ebidx; + + mask = GENMASK(limit - 1, sbidx); + + /* + * The valid bit is the inverse of the wrap bit. This means + * that a zero-initialised queue is invalid and, after marking + * all entries as valid, they become invalid again when we + * wrap. + */ + if (set) { + atomic_long_xor(mask, ptr); + } else { /* Poll */ + unsigned long valid; + + valid = (ULONG_MAX + !!Q_WRP(&llq, llq.prod)) & mask; + atomic_long_cond_read_relaxed(ptr, (VAL & mask) == valid); + } + + llq.prod = queue_inc_prod_n(&llq, limit - sbidx); } } -static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu, - struct arm_smmu_cmdq_ent *ent) +/* Mark all entries in the range [sprod, eprod) as valid */ +static void arm_smmu_cmdq_set_valid_map(struct arm_smmu_cmdq *cmdq, + u32 sprod, u32 eprod) +{ + __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, true); +} + +/* Wait for all entries in the range [sprod, eprod) to become valid */ +static void arm_smmu_cmdq_poll_valid_map(struct arm_smmu_cmdq *cmdq, + u32 sprod, u32 eprod) +{ + __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, false); +} + +/* Wait for the command queue to become non-full */ +static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu, + struct arm_smmu_ll_queue *llq) { - u64 cmd[CMDQ_ENT_DWORDS]; unsigned long flags; + struct arm_smmu_queue_poll qp; + struct arm_smmu_cmdq *cmdq = &smmu->cmdq; + int ret = 0; - if (arm_smmu_cmdq_build_cmd(cmd, ent)) { - dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n", - ent->opcode); - return; + /* + * Try to update our copy of cons by grabbing exclusive cmdq access. If + * that fails, spin until somebody else updates it for us. + */ + if (arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags)) { + WRITE_ONCE(cmdq->q.llq.cons, readl_relaxed(cmdq->q.cons_reg)); + arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags); + llq->val = READ_ONCE(cmdq->q.llq.val); + return 0; } - spin_lock_irqsave(&smmu->cmdq.lock, flags); - arm_smmu_cmdq_insert_cmd(smmu, cmd); - spin_unlock_irqrestore(&smmu->cmdq.lock, flags); + queue_poll_init(smmu, &qp); + do { + llq->val = READ_ONCE(smmu->cmdq.q.llq.val); + if (!queue_full(llq)) + break; + + ret = queue_poll(&qp); + } while (!ret); + + return ret; } /* - * The difference between val and sync_idx is bounded by the maximum size of - * a queue at 2^20 entries, so 32 bits is plenty for wrap-safe arithmetic. + * Wait until the SMMU signals a CMD_SYNC completion MSI. + * Must be called with the cmdq lock held in some capacity. */ -static int __arm_smmu_sync_poll_msi(struct arm_smmu_device *smmu, u32 sync_idx) +static int __arm_smmu_cmdq_poll_until_msi(struct arm_smmu_device *smmu, + struct arm_smmu_ll_queue *llq) { - ktime_t timeout; - u32 val; + int ret = 0; + struct arm_smmu_queue_poll qp; + struct arm_smmu_cmdq *cmdq = &smmu->cmdq; + u32 *cmd = (u32 *)(Q_ENT(&cmdq->q, llq->prod)); - timeout = ktime_add_us(ktime_get(), ARM_SMMU_CMDQ_SYNC_TIMEOUT_US); - val = smp_cond_load_acquire(&smmu->sync_count, - (int)(VAL - sync_idx) >= 0 || - !ktime_before(ktime_get(), timeout)); + queue_poll_init(smmu, &qp); - return (int)(val - sync_idx) < 0 ? -ETIMEDOUT : 0; + /* + * The MSI won't generate an event, since it's being written back + * into the command queue. + */ + qp.wfe = false; + smp_cond_load_relaxed(cmd, !VAL || (ret = queue_poll(&qp))); + llq->cons = ret ? llq->prod : queue_inc_prod_n(llq, 1); + return ret; } -static int __arm_smmu_cmdq_issue_sync_msi(struct arm_smmu_device *smmu) +/* + * Wait until the SMMU cons index passes llq->prod. + * Must be called with the cmdq lock held in some capacity. + */ +static int __arm_smmu_cmdq_poll_until_consumed(struct arm_smmu_device *smmu, + struct arm_smmu_ll_queue *llq) { - u64 cmd[CMDQ_ENT_DWORDS]; - unsigned long flags; - struct arm_smmu_cmdq_ent ent = { - .opcode = CMDQ_OP_CMD_SYNC, - .sync = { - .msiaddr = virt_to_phys(&smmu->sync_count), - }, - }; + struct arm_smmu_queue_poll qp; + struct arm_smmu_cmdq *cmdq = &smmu->cmdq; + u32 prod = llq->prod; + int ret = 0; - spin_lock_irqsave(&smmu->cmdq.lock, flags); + queue_poll_init(smmu, &qp); + llq->val = READ_ONCE(smmu->cmdq.q.llq.val); + do { + if (queue_consumed(llq, prod)) + break; - /* Piggy-back on the previous command if it's a SYNC */ - if (smmu->prev_cmd_opcode == CMDQ_OP_CMD_SYNC) { - ent.sync.msidata = smmu->sync_nr; - } else { - ent.sync.msidata = ++smmu->sync_nr; - arm_smmu_cmdq_build_cmd(cmd, &ent); - arm_smmu_cmdq_insert_cmd(smmu, cmd); - } + ret = queue_poll(&qp); - spin_unlock_irqrestore(&smmu->cmdq.lock, flags); + /* + * This needs to be a readl() so that our subsequent call + * to arm_smmu_cmdq_shared_tryunlock() can fail accurately. + * + * Specifically, we need to ensure that we observe all + * shared_lock()s by other CMD_SYNCs that share our owner, + * so that a failing call to tryunlock() means that we're + * the last one out and therefore we can safely advance + * cmdq->q.llq.cons. Roughly speaking: + * + * CPU 0 CPU1 CPU2 (us) + * + * if (sync) + * shared_lock(); + * + * dma_wmb(); + * set_valid_map(); + * + * if (owner) { + * poll_valid_map(); + * + * writel(prod_reg); + * + * readl(cons_reg); + * tryunlock(); + * + * Requires us to see CPU 0's shared_lock() acquisition. + */ + llq->cons = readl(cmdq->q.cons_reg); + } while (!ret); - return __arm_smmu_sync_poll_msi(smmu, ent.sync.msidata); + return ret; } -static int __arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) +static int arm_smmu_cmdq_poll_until_sync(struct arm_smmu_device *smmu, + struct arm_smmu_ll_queue *llq) { - u64 cmd[CMDQ_ENT_DWORDS]; + if (smmu->features & ARM_SMMU_FEAT_MSI && + smmu->features & ARM_SMMU_FEAT_COHERENCY) + return __arm_smmu_cmdq_poll_until_msi(smmu, llq); + + return __arm_smmu_cmdq_poll_until_consumed(smmu, llq); +} + +static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds, + u32 prod, int n) +{ + int i; + struct arm_smmu_ll_queue llq = { + .max_n_shift = cmdq->q.llq.max_n_shift, + .prod = prod, + }; + + for (i = 0; i < n; ++i) { + u64 *cmd = &cmds[i * CMDQ_ENT_DWORDS]; + + prod = queue_inc_prod_n(&llq, i); + queue_write(Q_ENT(&cmdq->q, prod), cmd, CMDQ_ENT_DWORDS); + } +} + +static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu, + u64 *cmds, int n, bool sync) +{ + u64 cmd_sync[CMDQ_ENT_DWORDS]; + u32 prod; unsigned long flags; - bool wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV); - struct arm_smmu_cmdq_ent ent = { .opcode = CMDQ_OP_CMD_SYNC }; - int ret; + bool owner; + struct arm_smmu_cmdq *cmdq = &smmu->cmdq; + struct arm_smmu_ll_queue llq = { + .max_n_shift = cmdq->q.llq.max_n_shift, + }, head = llq; + int ret = 0; - arm_smmu_cmdq_build_cmd(cmd, &ent); + /* 1. Allocate some space in the queue */ + local_irq_save(flags); + llq.val = READ_ONCE(cmdq->q.llq.val); + do { + u64 old; + + while (!queue_has_space(&llq, n + sync)) { + local_irq_restore(flags); + if (arm_smmu_cmdq_poll_until_not_full(smmu, &llq)) + dev_err_ratelimited(smmu->dev, "CMDQ timeout\n"); + local_irq_save(flags); + } + + head.cons = llq.cons; + head.prod = queue_inc_prod_n(&llq, n + sync) | + CMDQ_PROD_OWNED_FLAG; + + old = cmpxchg_relaxed(&cmdq->q.llq.val, llq.val, head.val); + if (old == llq.val) + break; + + llq.val = old; + } while (1); + owner = !(llq.prod & CMDQ_PROD_OWNED_FLAG); + head.prod &= ~CMDQ_PROD_OWNED_FLAG; + llq.prod &= ~CMDQ_PROD_OWNED_FLAG; + + /* + * 2. Write our commands into the queue + * Dependency ordering from the cmpxchg() loop above. + */ + arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n); + if (sync) { + prod = queue_inc_prod_n(&llq, n); + arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod); + queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS); + + /* + * In order to determine completion of our CMD_SYNC, we must + * ensure that the queue can't wrap twice without us noticing. + * We achieve that by taking the cmdq lock as shared before + * marking our slot as valid. + */ + arm_smmu_cmdq_shared_lock(cmdq); + } - spin_lock_irqsave(&smmu->cmdq.lock, flags); - arm_smmu_cmdq_insert_cmd(smmu, cmd); - ret = queue_poll_cons(&smmu->cmdq.q, true, wfe); - spin_unlock_irqrestore(&smmu->cmdq.lock, flags); + /* 3. Mark our slots as valid, ensuring commands are visible first */ + dma_wmb(); + arm_smmu_cmdq_set_valid_map(cmdq, llq.prod, head.prod); + /* 4. If we are the owner, take control of the SMMU hardware */ + if (owner) { + /* a. Wait for previous owner to finish */ + atomic_cond_read_relaxed(&cmdq->owner_prod, VAL == llq.prod); + + /* b. Stop gathering work by clearing the owned flag */ + prod = atomic_fetch_andnot_relaxed(CMDQ_PROD_OWNED_FLAG, + &cmdq->q.llq.atomic.prod); + prod &= ~CMDQ_PROD_OWNED_FLAG; + + /* + * c. Wait for any gathered work to be written to the queue. + * Note that we read our own entries so that we have the control + * dependency required by (d). + */ + arm_smmu_cmdq_poll_valid_map(cmdq, llq.prod, prod); + + /* + * d. Advance the hardware prod pointer + * Control dependency ordering from the entries becoming valid. + */ + writel_relaxed(prod, cmdq->q.prod_reg); + + /* + * e. Tell the next owner we're done + * Make sure we've updated the hardware first, so that we don't + * race to update prod and potentially move it backwards. + */ + atomic_set_release(&cmdq->owner_prod, prod); + } + + /* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */ + if (sync) { + llq.prod = queue_inc_prod_n(&llq, n); + ret = arm_smmu_cmdq_poll_until_sync(smmu, &llq); + if (ret) { + dev_err_ratelimited(smmu->dev, + "CMD_SYNC timeout at 0x%08x [hwprod 0x%08x, hwcons 0x%08x]\n", + llq.prod, + readl_relaxed(cmdq->q.prod_reg), + readl_relaxed(cmdq->q.cons_reg)); + } + + /* + * Try to unlock the cmq lock. This will fail if we're the last + * reader, in which case we can safely update cmdq->q.llq.cons + */ + if (!arm_smmu_cmdq_shared_tryunlock(cmdq)) { + WRITE_ONCE(cmdq->q.llq.cons, llq.cons); + arm_smmu_cmdq_shared_unlock(cmdq); + } + } + + local_irq_restore(flags); return ret; } -static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) +static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu, + struct arm_smmu_cmdq_ent *ent) { - int ret; - bool msi = (smmu->features & ARM_SMMU_FEAT_MSI) && - (smmu->features & ARM_SMMU_FEAT_COHERENCY); + u64 cmd[CMDQ_ENT_DWORDS]; - ret = msi ? __arm_smmu_cmdq_issue_sync_msi(smmu) - : __arm_smmu_cmdq_issue_sync(smmu); - if (ret) - dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n"); - return ret; + if (arm_smmu_cmdq_build_cmd(cmd, ent)) { + dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n", + ent->opcode); + return -EINVAL; + } + + return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false); +} + +static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) +{ + return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true); } /* Context descriptor manipulation functions */ @@ -1580,9 +1932,9 @@ static void arm_smmu_tlb_inv_context(void *cookie) /* * NOTE: when io-pgtable is in non-strict mode, we may get here with * PTEs previously cleared by unmaps on the current CPU not yet visible - * to the SMMU. We are relying on the DSB implicit in - * queue_sync_prod_out() to guarantee those are observed before the - * TLBI. Do be careful, 007. + * to the SMMU. We are relying on the dma_wmb() implicit during cmd + * insertion to guarantee those are observed before the TLBI. Do be + * careful, 007. */ arm_smmu_cmdq_issue_cmd(smmu, &cmd); arm_smmu_cmdq_issue_sync(smmu); @@ -2359,18 +2711,49 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, return 0; } +static void arm_smmu_cmdq_free_bitmap(void *data) +{ + unsigned long *bitmap = data; + bitmap_free(bitmap); +} + +static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu) +{ + int ret = 0; + struct arm_smmu_cmdq *cmdq = &smmu->cmdq; + unsigned int nents = 1 << cmdq->q.llq.max_n_shift; + atomic_long_t *bitmap; + + atomic_set(&cmdq->owner_prod, 0); + atomic_set(&cmdq->lock, 0); + + bitmap = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL); + if (!bitmap) { + dev_err(smmu->dev, "failed to allocate cmdq bitmap\n"); + ret = -ENOMEM; + } else { + cmdq->valid_map = bitmap; + devm_add_action(smmu->dev, arm_smmu_cmdq_free_bitmap, bitmap); + } + + return ret; +} + static int arm_smmu_init_queues(struct arm_smmu_device *smmu) { int ret; /* cmdq */ - spin_lock_init(&smmu->cmdq.lock); ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD, ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS, "cmdq"); if (ret) return ret; + ret = arm_smmu_cmdq_init(smmu); + if (ret) + return ret; + /* evtq */ ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, ARM_SMMU_EVTQ_PROD, ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS, @@ -2951,9 +3334,15 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) /* Queue sizes, capped to ensure natural alignment */ smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, FIELD_GET(IDR1_CMDQS, reg)); - if (!smmu->cmdq.q.llq.max_n_shift) { - /* Odd alignment restrictions on the base, so ignore for now */ - dev_err(smmu->dev, "unit-length command queue not supported\n"); + if (smmu->cmdq.q.llq.max_n_shift < ilog2(BITS_PER_LONG)) { + /* + * The cmdq valid_map relies on the total number of entries + * being a multiple of BITS_PER_LONG. There's also no way + * we can handle the weird alignment restrictions on the + * base pointer for a unit-length queue. + */ + dev_err(smmu->dev, "command queue size < %d entries not supported\n", + BITS_PER_LONG); return -ENXIO; } -- GitLab From 2af2e72b18b499fa36d3f7379fd010ff25d2a984 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jul 2019 17:16:33 +0100 Subject: [PATCH 2256/7155] iommu/arm-smmu-v3: Defer TLB invalidation until ->iotlb_sync() Update the iommu_iotlb_gather structure passed to ->tlb_add_page() and use this information to defer all TLB invalidation until ->iotlb_sync(). This drastically reduces contention on the command queue, since we can insert our commands in batches rather than one-by-one. Tested-by: Ganapatrao Kulkarni Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 71 ++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 202b4b6fc70a..b36a99971401 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -309,6 +309,13 @@ #define CMDQ_PROD_OWNED_FLAG Q_OVERFLOW_FLAG +/* + * This is used to size the command queue and therefore must be at least + * BITS_PER_LONG so that the valid_map works correctly (it relies on the + * total number of queue entries being a multiple of BITS_PER_LONG). + */ +#define CMDQ_BATCH_ENTRIES BITS_PER_LONG + #define CMDQ_0_OP GENMASK_ULL(7, 0) #define CMDQ_0_SSV (1UL << 11) @@ -1940,15 +1947,17 @@ static void arm_smmu_tlb_inv_context(void *cookie) arm_smmu_cmdq_issue_sync(smmu); } -static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, - size_t granule, bool leaf, void *cookie) +static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size, + size_t granule, bool leaf, + struct arm_smmu_domain *smmu_domain) { - struct arm_smmu_domain *smmu_domain = cookie; + u64 cmds[CMDQ_BATCH_ENTRIES * CMDQ_ENT_DWORDS]; struct arm_smmu_device *smmu = smmu_domain->smmu; + unsigned long end = iova + size; + int i = 0; struct arm_smmu_cmdq_ent cmd = { .tlbi = { .leaf = leaf, - .addr = iova, }, }; @@ -1960,37 +1969,41 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid; } - do { - arm_smmu_cmdq_issue_cmd(smmu, &cmd); - cmd.tlbi.addr += granule; - } while (size -= granule); + while (iova < end) { + if (i == CMDQ_BATCH_ENTRIES) { + arm_smmu_cmdq_issue_cmdlist(smmu, cmds, i, false); + i = 0; + } + + cmd.tlbi.addr = iova; + arm_smmu_cmdq_build_cmd(&cmds[i * CMDQ_ENT_DWORDS], &cmd); + iova += granule; + i++; + } + + arm_smmu_cmdq_issue_cmdlist(smmu, cmds, i, true); } static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, unsigned long iova, size_t granule, void *cookie) { - arm_smmu_tlb_inv_range_nosync(iova, granule, granule, true, cookie); + struct arm_smmu_domain *smmu_domain = cookie; + struct iommu_domain *domain = &smmu_domain->domain; + + iommu_iotlb_gather_add_page(domain, gather, iova, granule); } static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, size_t granule, void *cookie) { - struct arm_smmu_domain *smmu_domain = cookie; - struct arm_smmu_device *smmu = smmu_domain->smmu; - - arm_smmu_tlb_inv_range_nosync(iova, size, granule, false, cookie); - arm_smmu_cmdq_issue_sync(smmu); + arm_smmu_tlb_inv_range(iova, size, granule, false, cookie); } static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, size_t granule, void *cookie) { - struct arm_smmu_domain *smmu_domain = cookie; - struct arm_smmu_device *smmu = smmu_domain->smmu; - - arm_smmu_tlb_inv_range_nosync(iova, size, granule, true, cookie); - arm_smmu_cmdq_issue_sync(smmu); + arm_smmu_tlb_inv_range(iova, size, granule, true, cookie); } static const struct iommu_flush_ops arm_smmu_flush_ops = { @@ -2404,10 +2417,10 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) static void arm_smmu_iotlb_sync(struct iommu_domain *domain, struct iommu_iotlb_gather *gather) { - struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu; + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); - if (smmu) - arm_smmu_cmdq_issue_sync(smmu); + arm_smmu_tlb_inv_range(gather->start, gather->end - gather->start, + gather->pgsize, true, smmu_domain); } static phys_addr_t @@ -3334,15 +3347,15 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) /* Queue sizes, capped to ensure natural alignment */ smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, FIELD_GET(IDR1_CMDQS, reg)); - if (smmu->cmdq.q.llq.max_n_shift < ilog2(BITS_PER_LONG)) { + if (smmu->cmdq.q.llq.max_n_shift <= ilog2(CMDQ_BATCH_ENTRIES)) { /* - * The cmdq valid_map relies on the total number of entries - * being a multiple of BITS_PER_LONG. There's also no way - * we can handle the weird alignment restrictions on the - * base pointer for a unit-length queue. + * We don't support splitting up batches, so one batch of + * commands plus an extra sync needs to fit inside the command + * queue. There's also no way we can handle the weird alignment + * restrictions on the base pointer for a unit-length queue. */ - dev_err(smmu->dev, "command queue size < %d entries not supported\n", - BITS_PER_LONG); + dev_err(smmu->dev, "command queue size <= %d entries not supported\n", + CMDQ_BATCH_ENTRIES); return -ENXIO; } -- GitLab From d1b622f68daf6c9f1abed360428e5a8f22063f99 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 26 Jul 2019 18:59:47 +0800 Subject: [PATCH 2257/7155] dmaengine: pl330: use the same attributes when freeing pl330->mcode_cpu In function dmac_alloc_resources(), pl330->mcode_cpu is allocated using dma_alloc_attrs() but freed with dma_free_coherent(). Use the correct dma_free_attrs() function to free pl330->mcode_cpu. Signed-off-by: Fuqian Huang Link: https://lore.kernel.org/r/20190726105947.25342-1-huangfq.daxian@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/pl330.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 1163af2ba4a3..6cce9ef61b29 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1922,9 +1922,10 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330) if (ret) { dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n", __func__, __LINE__); - dma_free_coherent(pl330->ddma.dev, + dma_free_attrs(pl330->ddma.dev, chans * pl330->mcbufsz, - pl330->mcode_cpu, pl330->mcode_bus); + pl330->mcode_cpu, pl330->mcode_bus, + DMA_ATTR_PRIVILEGED); return ret; } @@ -2003,9 +2004,9 @@ static void pl330_del(struct pl330_dmac *pl330) /* Free DMAC resources */ dmac_free_threads(pl330); - dma_free_coherent(pl330->ddma.dev, + dma_free_attrs(pl330->ddma.dev, pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu, - pl330->mcode_bus); + pl330->mcode_bus, DMA_ATTR_PRIVILEGED); } /* forward declaration */ -- GitLab From ba1cab79cfc629f7238a26e040545ca394cd695f Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 31 Jul 2019 10:36:59 -0700 Subject: [PATCH 2258/7155] dmaengine: fsl-edma: implement .device_synchronize callback Implement .device_synchronize callback in order to be able to use dmaengine_terminate_sync() and other primitives relying on said callback. Signed-off-by: Andrey Smirnov Cc: Stefan Agner Cc: Chris Healy Cc: Vinod Koul Cc: linux-imx@nxp.com Cc: dmaengine@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/20190731173659.14778-1-andrew.smirnov@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c index dfce75c2991b..b626c06ac2e0 100644 --- a/drivers/dma/fsl-edma.c +++ b/drivers/dma/fsl-edma.c @@ -20,6 +20,13 @@ #include "fsl-edma-common.h" +static void fsl_edma_synchronize(struct dma_chan *chan) +{ + struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); + + vchan_synchronize(&fsl_chan->vchan); +} + static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id) { struct fsl_edma_engine *fsl_edma = dev_id; @@ -363,6 +370,7 @@ static int fsl_edma_probe(struct platform_device *pdev) fsl_edma->dma_dev.device_pause = fsl_edma_pause; fsl_edma->dma_dev.device_resume = fsl_edma_resume; fsl_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all; + fsl_edma->dma_dev.device_synchronize = fsl_edma_synchronize; fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending; fsl_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS; -- GitLab From ba6f7da99aaf00042b4ed2d8850ed7534492009e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 7 Aug 2019 21:18:47 +0800 Subject: [PATCH 2259/7155] lightnvm: remove set but not used variables 'data_len' and 'rq_len' drivers/lightnvm/pblk-read.c: In function pblk_submit_read_gc: drivers/lightnvm/pblk-read.c:423:6: warning: variable data_len set but not used [-Wunused-but-set-variable] drivers/lightnvm/pblk-recovery.c: In function pblk_recov_scan_oob: drivers/lightnvm/pblk-recovery.c:368:15: warning: variable rq_len set but not used [-Wunused-but-set-variable] They are not used since commit 48e5da725581 ("lightnvm: move metadata mapping to lower level driver") Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Jens Axboe --- drivers/lightnvm/pblk-read.c | 2 -- drivers/lightnvm/pblk-recovery.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c index d572d4559e4e..0cdc48f9cfbf 100644 --- a/drivers/lightnvm/pblk-read.c +++ b/drivers/lightnvm/pblk-read.c @@ -420,7 +420,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; struct nvm_rq rqd; - int data_len; int ret = NVM_IO_OK; memset(&rqd, 0, sizeof(struct nvm_rq)); @@ -445,7 +444,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) if (!(gc_rq->secs_to_gc)) goto out; - data_len = (gc_rq->secs_to_gc) * geo->csecs; rqd.opcode = NVM_OP_PREAD; rqd.nr_ppas = gc_rq->secs_to_gc; diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c index d5e210c3c5b7..299ef47a17b2 100644 --- a/drivers/lightnvm/pblk-recovery.c +++ b/drivers/lightnvm/pblk-recovery.c @@ -365,7 +365,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, __le64 *lba_list; u64 paddr = pblk_line_smeta_start(pblk, line) + lm->smeta_sec; bool padded = false; - int rq_ppas, rq_len; + int rq_ppas; int i, j; int ret; u64 left_ppas = pblk_sec_in_open_line(pblk, line) - lm->smeta_sec; @@ -388,7 +388,6 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line, rq_ppas = pblk_calc_secs(pblk, left_ppas, 0, false); if (!rq_ppas) rq_ppas = pblk->min_write_pgs; - rq_len = rq_ppas * geo->csecs; retry_rq: rqd->bio = NULL; -- GitLab From 79e178f4383a3a645f76bc2dd44c477b361c6a98 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Wed, 24 Jul 2019 11:54:23 +0800 Subject: [PATCH 2260/7155] lib: scatterlist: Fix to support no mapped sg In function sg_split, the second sg_calculate_split will return -EINVAL when in_mapped_nents is 0. Indeed there is no need to do second sg_calculate_split and sg_split_mapped when in_mapped_nents is 0, as in_mapped_nents indicates no mapped entry in original sgl. Signed-off-by: Zhou Wang Acked-by: Robert Jarzmik Signed-off-by: Jens Axboe --- lib/sg_split.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/sg_split.c b/lib/sg_split.c index 9982c63d1063..60a0babebf2e 100644 --- a/lib/sg_split.c +++ b/lib/sg_split.c @@ -176,11 +176,13 @@ int sg_split(struct scatterlist *in, const int in_mapped_nents, * The order of these 3 calls is important and should be kept. */ sg_split_phys(splitters, nb_splits); - ret = sg_calculate_split(in, in_mapped_nents, nb_splits, skip, - split_sizes, splitters, true); - if (ret < 0) - goto err; - sg_split_mapped(splitters, nb_splits); + if (in_mapped_nents) { + ret = sg_calculate_split(in, in_mapped_nents, nb_splits, skip, + split_sizes, splitters, true); + if (ret < 0) + goto err; + sg_split_mapped(splitters, nb_splits); + } for (i = 0; i < nb_splits; i++) { out[i] = splitters[i].out_sg; -- GitLab From 619a1f195f93276dc8c6e33fe057e007adc9c288 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Aug 2019 20:02:31 +0200 Subject: [PATCH 2261/7155] ALSA: hda: Remove page allocation redirection The HD-audio core allocates and releases pages via driver's specific dma_alloc_pages and dma_free_pages ops defined in bus->io_ops. This was because some platforms require the uncached pages and the handling of page flags had to be done locally in the driver code. Since the recent change in ALSA core memory allocator, we can simply pass SNDRV_DMA_TYPE_DEV_UC for the uncached pages, and the only difference became about this type to be passed to the core allocator. That is, it's good time for cleaning up the mess. This patch changes the allocation code in HD-audio core to call the core allocator directly so that we get rid of dma_alloc_pages and dma_free_pages io_ops. If a driver needs the uncached pages, it has to set bus->dma_type right after the bus initialization. This is merely a code refactoring and shouldn't bring any behavior changes. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 6 +----- sound/hda/ext/hdac_ext_bus.c | 13 ------------- sound/hda/hdac_bus.c | 1 + sound/hda/hdac_controller.c | 18 +++++++++--------- sound/hda/hdac_stream.c | 8 ++++---- sound/pci/hda/hda_intel.c | 24 ++++-------------------- sound/pci/hda/hda_tegra.c | 16 ---------------- sound/soc/intel/skylake/skl-messages.c | 15 ++------------- sound/soc/sof/intel/hda-bus.c | 14 -------------- 9 files changed, 21 insertions(+), 94 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 612a17e375d0..20549def0a27 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -264,11 +264,6 @@ struct hdac_io_ops { u16 (*reg_readw)(u16 __iomem *addr); void (*reg_writeb)(u8 value, u8 __iomem *addr); u8 (*reg_readb)(u8 __iomem *addr); - /* Allocation ops */ - int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size, - struct snd_dma_buffer *buf); - void (*dma_free_pages)(struct hdac_bus *bus, - struct snd_dma_buffer *buf); }; #define HDA_UNSOL_QUEUE_SIZE 64 @@ -344,6 +339,7 @@ struct hdac_bus { /* CORB/RIRB and position buffers */ struct snd_dma_buffer rb; struct snd_dma_buffer posbuf; + int dma_type; /* SNDRV_DMA_TYPE_XXX for CORB/RIRB */ /* hdac_stream linked list */ struct list_head stream_list; diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 4f9f1d2a2ec5..7825b74068f4 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -47,17 +47,6 @@ static u8 hdac_ext_readb(u8 __iomem *addr) return readb(addr); } -static int hdac_ext_dma_alloc_pages(struct hdac_bus *bus, int type, - size_t size, struct snd_dma_buffer *buf) -{ - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void hdac_ext_dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - static const struct hdac_io_ops hdac_ext_default_io = { .reg_writel = hdac_ext_writel, .reg_readl = hdac_ext_readl, @@ -65,8 +54,6 @@ static const struct hdac_io_ops hdac_ext_default_io = { .reg_readw = hdac_ext_readw, .reg_writeb = hdac_ext_writeb, .reg_readb = hdac_ext_readb, - .dma_alloc_pages = hdac_ext_dma_alloc_pages, - .dma_free_pages = hdac_ext_dma_free_pages, }; /** diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 14e57ffd5bc1..00ea12e67dc8 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -34,6 +34,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, else bus->ops = &default_ops; bus->io_ops = io_ops; + bus->dma_type = SNDRV_DMA_TYPE_DEV; INIT_LIST_HEAD(&bus->stream_list); INIT_LIST_HEAD(&bus->codec_list); INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 3b0110545070..7e7be8e4dcf9 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -575,12 +575,13 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) { struct hdac_stream *s; int num_streams = 0; + int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV; int err; list_for_each_entry(s, &bus->stream_list, list) { /* allocate memory for the BDL for each stream */ - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, - BDL_SIZE, &s->bdl); + err = snd_dma_alloc_pages(dma_type, bus->dev, + BDL_SIZE, &s->bdl); num_streams++; if (err < 0) return -ENOMEM; @@ -589,16 +590,15 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) if (WARN_ON(!num_streams)) return -EINVAL; /* allocate memory for the position buffer */ - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, - num_streams * 8, &bus->posbuf); + err = snd_dma_alloc_pages(dma_type, bus->dev, + num_streams * 8, &bus->posbuf); if (err < 0) return -ENOMEM; list_for_each_entry(s, &bus->stream_list, list) s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); /* single page (at least 4096 bytes) must suffice for both ringbuffes */ - return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, - PAGE_SIZE, &bus->rb); + return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb); } EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); @@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) list_for_each_entry(s, &bus->stream_list, list) { if (s->bdl.area) - bus->io_ops->dma_free_pages(bus, &s->bdl); + snd_dma_free_pages(&s->bdl); } if (bus->rb.area) - bus->io_ops->dma_free_pages(bus, &bus->rb); + snd_dma_free_pages(&bus->rb); if (bus->posbuf.area) - bus->io_ops->dma_free_pages(bus, &bus->posbuf); + snd_dma_free_pages(&bus->posbuf); } EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 55d53b89ac21..fc68d4ce0a37 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -680,8 +680,8 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, azx_dev->locked = true; spin_unlock_irq(&bus->reg_lock); - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, - byte_size, bufp); + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, + byte_size, bufp); if (err < 0) goto err_alloc; @@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, return azx_dev->stream_tag; error: - bus->io_ops->dma_free_pages(bus, bufp); + snd_dma_free_pages(bufp); err_alloc: spin_lock_irq(&bus->reg_lock); azx_dev->locked = false; @@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, azx_dev->period_bytes = 0; azx_dev->format_val = 0; - bus->io_ops->dma_free_pages(bus, dmab); + snd_dma_free_pages(dmab); dmab->area = NULL; spin_lock_irq(&bus->reg_lock); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cb8b0945547c..3bb4c26f2799 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1694,6 +1694,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, return err; } + /* use the non-cached pages in non-snoop mode */ + if (!azx_snoop(chip)) + azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC; + /* Workaround for a communication error on CFL (bko#199007) and CNL */ if (IS_CFL(pci) || IS_CNL(pci)) azx_bus(chip)->polling_mode = 1; @@ -1979,24 +1983,6 @@ static int disable_msi_reset_irq(struct azx *chip) return 0; } -/* DMA page allocation helpers. */ -static int dma_alloc_pages(struct hdac_bus *bus, - int type, - size_t size, - struct snd_dma_buffer *buf) -{ - struct azx *chip = bus_to_azx(bus); - - if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV) - type = SNDRV_DMA_TYPE_DEV_UC; - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - static void pcm_mmap_prepare(struct snd_pcm_substream *substream, struct vm_area_struct *area) { @@ -2015,8 +2001,6 @@ static const struct hdac_io_ops pci_hda_io_ops = { .reg_readw = pci_azx_readw, .reg_writeb = pci_azx_writeb, .reg_readb = pci_azx_readb, - .dma_alloc_pages = dma_alloc_pages, - .dma_free_pages = dma_free_pages, }; static const struct hda_controller_ops pci_hda_ops = { diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 7dbe9f39fc79..ba414cc639f1 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -75,20 +75,6 @@ MODULE_PARM_DESC(power_save, #define power_save 0 #endif -/* - * DMA page allocation ops. - */ -static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size, - struct snd_dma_buffer *buf) -{ - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - /* * Register access ops. Tegra HDA register access is DWORD only. */ @@ -153,8 +139,6 @@ static const struct hdac_io_ops hda_tegra_io_ops = { .reg_readw = hda_tegra_readw, .reg_writeb = hda_tegra_writeb, .reg_readb = hda_tegra_readb, - .dma_alloc_pages = dma_alloc_pages, - .dma_free_pages = dma_free_pages, }; static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index febc070839e0..c6f9e05c929e 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -25,23 +25,12 @@ static int skl_alloc_dma_buf(struct device *dev, struct snd_dma_buffer *dmab, size_t size) { - struct hdac_bus *bus = dev_get_drvdata(dev); - - if (!bus) - return -ENODEV; - - return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab); + return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, dmab); } static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) { - struct hdac_bus *bus = dev_get_drvdata(dev); - - if (!bus) - return -ENODEV; - - bus->io_ops->dma_free_pages(bus, dmab); - + snd_dma_free_pages(dmab); return 0; } diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index a7e6d8227df6..0bc93fa06b5b 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -51,18 +51,6 @@ static u8 sof_hda_readb(u8 __iomem *addr) return readb(addr); } -static int sof_hda_dma_alloc_pages(struct hdac_bus *bus, int type, - size_t size, struct snd_dma_buffer *buf) -{ - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void sof_hda_dma_free_pages(struct hdac_bus *bus, - struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - static const struct hdac_io_ops io_ops = { .reg_writel = sof_hda_writel, .reg_readl = sof_hda_readl, @@ -70,8 +58,6 @@ static const struct hdac_io_ops io_ops = { .reg_readw = sof_hda_readw, .reg_writeb = sof_hda_writeb, .reg_readb = sof_hda_readb, - .dma_alloc_pages = sof_hda_dma_alloc_pages, - .dma_free_pages = sof_hda_dma_free_pages, }; /* -- GitLab From 19abfefd4c7604993d1c31e098a3f48bdafe334d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Aug 2019 20:32:08 +0200 Subject: [PATCH 2262/7155] ALSA: hda: Direct MMIO accesses HD-audio drivers access to the mmio registers indirectly via the corresponding bus->io_ops callbacks. This is because some platform (notably Tegra SoC) requires the word-aligned access. But it's rather a rare case, and other platforms suffer from the penalties by indirect calls unnecessarily. This patch is an attempt to optimize and cleanup for this situation. Now the special aligned access is used only when a new kconfig CONFIG_SND_HDA_ALIGNED_MMIO is set. And the HD-audio core itself provides the aligned MMIO access helpers instead of the driver side. If Kconfig isn't set (as default), the standard helpers like readl() or writel() are used directly. A couple of places in ASoC Intel drivers have the access via io_ops reg_writel(), and they are replaced with the direct writel() calls. And now with this patch, the whole bus->io_ops becomes empty, so it's dropped completely. The bus initialization functions are changed accordingly as well to drop the whole bus->io_ops. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 63 +++++++++++++++---------------- include/sound/hdaudio_ext.h | 1 - sound/hda/Kconfig | 3 ++ sound/hda/ext/hdac_ext_bus.c | 47 +---------------------- sound/hda/hdac_bus.c | 35 +++++++++++++++-- sound/pci/hda/Kconfig | 1 + sound/pci/hda/hda_controller.c | 6 +-- sound/pci/hda/hda_controller.h | 3 +- sound/pci/hda/hda_intel.c | 47 +---------------------- sound/pci/hda/hda_tegra.c | 68 +--------------------------------- sound/soc/intel/skylake/skl.c | 7 ++-- sound/soc/sof/intel/hda-bus.c | 40 -------------------- sound/soc/sof/intel/hda-dsp.c | 2 +- 13 files changed, 75 insertions(+), 248 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 20549def0a27..4af4af55e854 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -253,19 +253,6 @@ struct hdac_ext_bus_ops { int (*hdev_detach)(struct hdac_device *hdev); }; -/* - * Lowlevel I/O operators - */ -struct hdac_io_ops { - /* mapped register accesses */ - void (*reg_writel)(u32 value, u32 __iomem *addr); - u32 (*reg_readl)(u32 __iomem *addr); - void (*reg_writew)(u16 value, u16 __iomem *addr); - u16 (*reg_readw)(u16 __iomem *addr); - void (*reg_writeb)(u8 value, u8 __iomem *addr); - u8 (*reg_readb)(u8 __iomem *addr); -}; - #define HDA_UNSOL_QUEUE_SIZE 64 #define HDA_MAX_CODECS 8 /* limit by controller side */ @@ -299,7 +286,6 @@ struct hdac_rb { struct hdac_bus { struct device *dev; const struct hdac_bus_ops *ops; - const struct hdac_io_ops *io_ops; const struct hdac_ext_bus_ops *ext_ops; /* h/w resources */ @@ -380,8 +366,7 @@ struct hdac_bus { }; int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops); + const struct hdac_bus_ops *ops); void snd_hdac_bus_exit(struct hdac_bus *bus); int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res); @@ -425,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); +#ifdef CONFIG_SND_HDA_ALIGNED_MMIO +unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask); +void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, + unsigned int mask); +#define snd_hdac_reg_writeb(v, addr) snd_hdac_aligned_write(v, addr, 0xff) +#define snd_hdac_reg_writew(v, addr) snd_hdac_aligned_write(v, addr, 0xffff) +#define snd_hdac_reg_readb(addr) snd_hdac_aligned_read(addr, 0xff) +#define snd_hdac_reg_readw(addr) snd_hdac_aligned_read(addr, 0xffff) +#else /* CONFIG_SND_HDA_ALIGNED_MMIO */ +#define snd_hdac_reg_writeb(val, addr) writeb(val, addr) +#define snd_hdac_reg_writew(val, addr) writew(val, addr) +#define snd_hdac_reg_readb(addr) readb(addr) +#define snd_hdac_reg_readw(addr) readw(addr) +#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ +#define snd_hdac_reg_writel(val, addr) writel(val, addr) +#define snd_hdac_reg_readl(addr) readl(addr) + /* * macros for easy use */ #define _snd_hdac_chip_writeb(chip, reg, value) \ - ((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + (reg))) + snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg)) #define _snd_hdac_chip_readb(chip, reg) \ - ((chip)->io_ops->reg_readb((chip)->remap_addr + (reg))) + snd_hdac_reg_readb((chip)->remap_addr + (reg)) #define _snd_hdac_chip_writew(chip, reg, value) \ - ((chip)->io_ops->reg_writew(value, (chip)->remap_addr + (reg))) + snd_hdac_reg_writew(value, (chip)->remap_addr + (reg)) #define _snd_hdac_chip_readw(chip, reg) \ - ((chip)->io_ops->reg_readw((chip)->remap_addr + (reg))) + snd_hdac_reg_readw((chip)->remap_addr + (reg)) #define _snd_hdac_chip_writel(chip, reg, value) \ - ((chip)->io_ops->reg_writel(value, (chip)->remap_addr + (reg))) + snd_hdac_reg_writel(value, (chip)->remap_addr + (reg)) #define _snd_hdac_chip_readl(chip, reg) \ - ((chip)->io_ops->reg_readl((chip)->remap_addr + (reg))) + snd_hdac_reg_readl((chip)->remap_addr + (reg)) /* read/write a register, pass without AZX_REG_ prefix */ #define snd_hdac_chip_writel(chip, reg, value) \ @@ -544,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, /* * macros for easy use */ -#define _snd_hdac_stream_write(type, dev, reg, value) \ - ((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg))) -#define _snd_hdac_stream_read(type, dev, reg) \ - ((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg))) - /* read/write a register, pass without AZX_REG_ prefix */ #define snd_hdac_stream_writel(dev, reg, value) \ - _snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) + snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_writew(dev, reg, value) \ - _snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) + snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_writeb(dev, reg, value) \ - _snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) + snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_readl(dev, reg) \ - _snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) + snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_readw(dev, reg) \ - _snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) + snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_readb(dev, reg) \ - _snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) + snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg) /* update a register, pass without AZX_REG_ prefix */ #define snd_hdac_stream_updatel(dev, reg, mask, val) \ diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index f34aced69ca8..ef88b20c7b0a 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -6,7 +6,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops, const struct hdac_ext_bus_ops *ext_ops); void snd_hdac_ext_bus_exit(struct hdac_bus *bus); diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index f6feced15f17..1d475cf3f754 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -6,6 +6,9 @@ config SND_HDA_CORE config SND_HDA_DSP_LOADER bool +config SND_HDA_ALIGNED_MMIO + bool + config SND_HDA_COMPONENT bool diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 7825b74068f4..242306d820ec 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -17,67 +17,22 @@ MODULE_DESCRIPTION("HDA extended core"); MODULE_LICENSE("GPL v2"); -static void hdac_ext_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 hdac_ext_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void hdac_ext_writew(u16 value, u16 __iomem *addr) -{ - writew(value, addr); -} - -static u16 hdac_ext_readw(u16 __iomem *addr) -{ - return readw(addr); -} - -static void hdac_ext_writeb(u8 value, u8 __iomem *addr) -{ - writeb(value, addr); -} - -static u8 hdac_ext_readb(u8 __iomem *addr) -{ - return readb(addr); -} - -static const struct hdac_io_ops hdac_ext_default_io = { - .reg_writel = hdac_ext_writel, - .reg_readl = hdac_ext_readl, - .reg_writew = hdac_ext_writew, - .reg_readw = hdac_ext_readw, - .reg_writeb = hdac_ext_writeb, - .reg_readb = hdac_ext_readb, -}; - /** * snd_hdac_ext_bus_init - initialize a HD-audio extended bus * @ebus: the pointer to extended bus object * @dev: device pointer * @ops: bus verb operators - * @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use * default ops * * Returns 0 if successful, or a negative error code. */ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops, const struct hdac_ext_bus_ops *ext_ops) { int ret; - /* check if io ops are provided, if not load the defaults */ - if (io_ops == NULL) - io_ops = &hdac_ext_default_io; - - ret = snd_hdac_bus_init(bus, dev, ops, io_ops); + ret = snd_hdac_bus_init(bus, dev, ops); if (ret < 0) return ret; diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 00ea12e67dc8..dc2523ef7d98 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -19,13 +19,11 @@ static const struct hdac_bus_ops default_ops = { * snd_hdac_bus_init - initialize a HD-audio bas bus * @bus: the pointer to bus object * @ops: bus verb operators - * @io_ops: lowlevel I/O operators * * Returns 0 if successful, or a negative error code. */ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops) + const struct hdac_bus_ops *ops) { memset(bus, 0, sizeof(*bus)); bus->dev = dev; @@ -33,7 +31,6 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, bus->ops = ops; else bus->ops = &default_ops; - bus->io_ops = io_ops; bus->dma_type = SNDRV_DMA_TYPE_DEV; INIT_LIST_HEAD(&bus->stream_list); INIT_LIST_HEAD(&bus->codec_list); @@ -218,3 +215,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, flush_work(&bus->unsol_work); } EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); + +#ifdef CONFIG_SND_HDA_ALIGNED_MMIO +/* Helpers for aligned read/write of mmio space, for Tegra */ +unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask) +{ + void __iomem *aligned_addr = + (void __iomem *)((unsigned long)(addr) & ~0x3); + unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; + unsigned int v; + + v = readl(aligned_addr); + return (v >> shift) & mask; +} +EXPORT_SYMBOL_GPL(snd_hdac_aligned_read); + +void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, + unsigned int mask) +{ + void __iomem *aligned_addr = + (void __iomem *)((unsigned long)(addr) & ~0x3); + unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; + unsigned int v; + + v = readl(aligned_addr); + v &= ~(mask << shift); + v |= val << shift; + writel(v, aligned_addr); +} +EXPORT_SYMBOL_GPL(snd_hdac_aligned_write); +#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 35d934309cb2..82198ea8f7f8 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -26,6 +26,7 @@ config SND_HDA_TEGRA tristate "NVIDIA Tegra HD Audio" depends on ARCH_TEGRA select SND_HDA + select SND_HDA_ALIGNED_MMIO help Say Y here to support the HDA controller present in NVIDIA Tegra SoCs diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index c8d1b4316245..ee5504e2441f 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1202,14 +1202,12 @@ void snd_hda_bus_reset(struct hda_bus *bus) } /* HD-audio bus initialization */ -int azx_bus_init(struct azx *chip, const char *model, - const struct hdac_io_ops *io_ops) +int azx_bus_init(struct azx *chip, const char *model) { struct hda_bus *bus = &chip->bus; int err; - err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, - io_ops); + err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops); if (err < 0) return err; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index baa15374fbcb..146a71e0d594 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip); irqreturn_t azx_interrupt(int irq, void *dev_id); /* Codec interface */ -int azx_bus_init(struct azx *chip, const char *model, - const struct hdac_io_ops *io_ops); +int azx_bus_init(struct azx *chip, const char *model); int azx_probe_codecs(struct azx *chip, unsigned int max_slots); int azx_codec_configure(struct azx *chip); int azx_init_streams(struct azx *chip); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3bb4c26f2799..963a92943a6d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1627,7 +1627,6 @@ static int default_bdl_pos_adj(struct azx *chip) /* * constructor */ -static const struct hdac_io_ops pci_hda_io_ops; static const struct hda_controller_ops pci_hda_ops; static int azx_create(struct snd_card *card, struct pci_dev *pci, @@ -1687,7 +1686,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, else chip->bdl_pos_adj = bdl_pos_adj[dev]; - err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); + err = azx_bus_init(chip, model[dev]); if (err < 0) { kfree(hda); pci_disable_device(pci); @@ -1932,41 +1931,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) } #endif -/* - * HDA controller ops. - */ - -/* PCI register access. */ -static void pci_azx_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 pci_azx_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void pci_azx_writew(u16 value, u16 __iomem *addr) -{ - writew(value, addr); -} - -static u16 pci_azx_readw(u16 __iomem *addr) -{ - return readw(addr); -} - -static void pci_azx_writeb(u8 value, u8 __iomem *addr) -{ - writeb(value, addr); -} - -static u8 pci_azx_readb(u8 __iomem *addr) -{ - return readb(addr); -} - static int disable_msi_reset_irq(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); @@ -1994,15 +1958,6 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, #endif } -static const struct hdac_io_ops pci_hda_io_ops = { - .reg_writel = pci_azx_writel, - .reg_readl = pci_azx_readl, - .reg_writew = pci_azx_writew, - .reg_readw = pci_azx_readw, - .reg_writeb = pci_azx_writeb, - .reg_readb = pci_azx_readb, -}; - static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .pcm_mmap_prepare = pcm_mmap_prepare, diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index ba414cc639f1..8350954b7986 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -75,72 +75,6 @@ MODULE_PARM_DESC(power_save, #define power_save 0 #endif -/* - * Register access ops. Tegra HDA register access is DWORD only. - */ -static void hda_tegra_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 hda_tegra_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void hda_tegra_writew(u16 value, u16 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - v &= ~(0xffff << shift); - v |= value << shift; - writel(v, dword_addr); -} - -static u16 hda_tegra_readw(u16 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - return (v >> shift) & 0xffff; -} - -static void hda_tegra_writeb(u8 value, u8 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - v &= ~(0xff << shift); - v |= value << shift; - writel(v, dword_addr); -} - -static u8 hda_tegra_readb(u8 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - return (v >> shift) & 0xff; -} - -static const struct hdac_io_ops hda_tegra_io_ops = { - .reg_writel = hda_tegra_writel, - .reg_readl = hda_tegra_readl, - .reg_writew = hda_tegra_writew, - .reg_readw = hda_tegra_readw, - .reg_writeb = hda_tegra_writeb, - .reg_readb = hda_tegra_readb, -}; - static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ static void hda_tegra_init(struct hda_tegra *hda) @@ -459,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card, INIT_WORK(&hda->probe_work, hda_tegra_probe_work); - err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); + err = azx_bus_init(chip, NULL); if (err < 0) return err; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 3362e71b4563..c6d8076dc2fd 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -132,7 +132,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) /* Reset stream-to-link mapping */ list_for_each_entry(hlink, &bus->hlink_list, list) - bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); + writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); skl_enable_miscbdcge(bus->dev, true); @@ -854,7 +854,6 @@ static void skl_probe_work(struct work_struct *work) * constructor */ static int skl_create(struct pci_dev *pci, - const struct hdac_io_ops *io_ops, struct skl **rskl) { struct hdac_ext_bus_ops *ext_ops = NULL; @@ -884,7 +883,7 @@ static int skl_create(struct pci_dev *pci, #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) ext_ops = snd_soc_hdac_hda_get_ops(); #endif - snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops); + snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, ext_ops); bus->use_posbuf = 1; skl->pci = pci; INIT_WORK(&skl->probe_work, skl_probe_work); @@ -1013,7 +1012,7 @@ static int skl_probe(struct pci_dev *pci, } /* we use ext core ops, so provide NULL for ops here */ - err = skl_create(pci, NULL, &skl); + err = skl_create(pci, &skl); if (err < 0) return err; diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 0bc93fa06b5b..438121c70f99 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -21,45 +21,6 @@ static const struct hdac_bus_ops bus_ops = { #endif -static void sof_hda_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 sof_hda_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void sof_hda_writew(u16 value, u16 __iomem *addr) -{ - writew(value, addr); -} - -static u16 sof_hda_readw(u16 __iomem *addr) -{ - return readw(addr); -} - -static void sof_hda_writeb(u8 value, u8 __iomem *addr) -{ - writeb(value, addr); -} - -static u8 sof_hda_readb(u8 __iomem *addr) -{ - return readb(addr); -} - -static const struct hdac_io_ops io_ops = { - .reg_writel = sof_hda_writel, - .reg_readl = sof_hda_readl, - .reg_writew = sof_hda_writew, - .reg_readw = sof_hda_readw, - .reg_writeb = sof_hda_writeb, - .reg_readb = sof_hda_readb, -}; - /* * This can be used for both with/without hda link support. */ @@ -69,7 +30,6 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, memset(bus, 0, sizeof(*bus)); bus->dev = dev; - bus->io_ops = &io_ops; INIT_LIST_HEAD(&bus->stream_list); bus->irq = -1; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 91de4785b6a3..8d4ce5b4febd 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -356,7 +356,7 @@ static int hda_resume(struct snd_sof_dev *sdev) /* Reset stream-to-link mapping */ list_for_each_entry(hlink, &bus->hlink_list, list) - bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); + writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); hda_dsp_ctrl_misc_clock_gating(sdev, true); #else -- GitLab From d4ff1b3917a529bdc75592af6b1504ad6c4029f7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Aug 2019 20:50:50 +0200 Subject: [PATCH 2263/7155] ASoC: SOF: Intel: Initialize hdaudio bus properly The SOF HD-audio bus has its house-made initialization code. It's supposedly for making the code independent from HD-audio bus drivers. However, this is error-prone, and above all, the SOF driver has already dependency on HD-audio bus driver when CONFIG_SND_SOF_HDA is set. That is, if this Kconfig is set, there is no reason to avoid the call to the proper bus init function. Also, the ext_ops that is set at bus initialization can be better handled inside sof_hda_bus_init(). We don't need to refer this outside the bus initialization. So this patch addresses these issues: - sof_hda_bus_init() calls nothing but snd_hdac_ext_bus_init() when CONFIG_SND_SOF_HDA is set. Otherwise some fields are initialized locally like before for avoiding the dependency. - ext_ops is referred inside sof_hda_bus_init(). The ext_ops argument of snd_hda_bus_init() is dropped. Acked-by: Mark Brown Reviewed-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-bus.c | 31 +++++++++---------------------- sound/soc/sof/intel/hda.c | 6 +----- sound/soc/sof/intel/hda.h | 3 +-- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 438121c70f99..0caec3a070d3 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -12,28 +12,26 @@ #include "../sof-priv.h" #include "hda.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - -static const struct hdac_bus_ops bus_ops = { - .command = snd_hdac_bus_send_cmd, - .get_response = snd_hdac_bus_get_response, -}; - +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +#define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() +#else +#define sof_hda_ext_ops NULL #endif /* * This can be used for both with/without hda link support. */ -void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_ext_bus_ops *ext_ops) +void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev) { +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops); +#else /* CONFIG_SND_SOC_SOF_HDA */ memset(bus, 0, sizeof(*bus)); bus->dev = dev; INIT_LIST_HEAD(&bus->stream_list); bus->irq = -1; - bus->ext_ops = ext_ops; /* * There is only one HDA bus atm. keep the index as 0. @@ -42,16 +40,5 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, bus->idx = 0; spin_lock_init(&bus->reg_lock); - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - INIT_LIST_HEAD(&bus->codec_list); - INIT_LIST_HEAD(&bus->hlink_list); - - mutex_init(&bus->cmd_mutex); - mutex_init(&bus->lock); - bus->ops = &bus_ops; - INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); - bus->cmd_dma_state = true; -#endif - +#endif /* CONFIG_SND_SOC_SOF_HDA */ } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7f665392618f..7ca27000c34d 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -236,7 +236,6 @@ static int hda_init(struct snd_sof_dev *sdev) { struct hda_bus *hbus; struct hdac_bus *bus; - struct hdac_ext_bus_ops *ext_ops = NULL; struct pci_dev *pci = to_pci_dev(sdev->dev); int ret; @@ -244,10 +243,7 @@ static int hda_init(struct snd_sof_dev *sdev) bus = sof_to_bus(sdev); /* HDA bus init */ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - ext_ops = snd_soc_hdac_hda_get_ops(); -#endif - sof_hda_bus_init(bus, &pci->dev, ext_ops); + sof_hda_bus_init(bus, &pci->dev); /* Workaround for a communication error on CFL (bko#199007) and CNL */ if (IS_CFL(pci) || IS_CNL(pci)) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index d9c17146200b..75b096050fa2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -549,8 +549,7 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); /* * HDA bus operations. */ -void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, - const struct hdac_ext_bus_ops *ext_ops); +void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* -- GitLab From 0a54b809a3a2c31e1055b45b03708eb730222be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valdis=20Kl=C4=93tnieks?= Date: Wed, 7 Aug 2019 18:59:29 -0400 Subject: [PATCH 2264/7155] RAS: Fix prototype warnings When building with C=2 and/or W=1, legitimate warnings are issued about missing prototypes: CHECK drivers/ras/debugfs.c drivers/ras/debugfs.c:4:15: warning: symbol 'ras_debugfs_dir' was not declared. Should it be static? drivers/ras/debugfs.c:8:5: warning: symbol 'ras_userspace_consumers' was not declared. Should it be static? drivers/ras/debugfs.c:38:12: warning: symbol 'ras_add_daemon_trace' was not declared. Should it be static? drivers/ras/debugfs.c:54:13: warning: symbol 'ras_debugfs_init' was not declared. Should it be static? CC drivers/ras/debugfs.o drivers/ras/debugfs.c:8:5: warning: no previous prototype for 'ras_userspace_consumers' [-Wmissing-prototypes] 8 | int ras_userspace_consumers(void) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/ras/debugfs.c:38:12: warning: no previous prototype for 'ras_add_daemon_trace' [-Wmissing-prototypes] 38 | int __init ras_add_daemon_trace(void) | ^~~~~~~~~~~~~~~~~~~~ drivers/ras/debugfs.c:54:13: warning: no previous prototype for 'ras_debugfs_init' [-Wmissing-prototypes] 54 | void __init ras_debugfs_init(void) | ^~~~~~~~~~~~~~~~ Provide the proper includes. [ bp: Take care of the same warnings for cec.c too. ] Signed-off-by: Valdis Kletnieks Signed-off-by: Borislav Petkov Cc: Tony Luck Cc: linux-edac@vger.kernel.org Cc: x86@kernel.org Link: http://lkml.kernel.org/r/7168.1565218769@turing-police --- drivers/ras/cec.c | 1 + drivers/ras/debugfs.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c index 5d545806d930..c09cf55e2d20 100644 --- a/drivers/ras/cec.c +++ b/drivers/ras/cec.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c index 9c1b717efad8..0d4f985afbf3 100644 --- a/drivers/ras/debugfs.c +++ b/drivers/ras/debugfs.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include +#include "debugfs.h" struct dentry *ras_debugfs_dir; -- GitLab From b6ff24f7b5101101ff897dfdde3f37924e676bc2 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Thu, 8 Aug 2019 16:32:27 +0200 Subject: [PATCH 2265/7155] RAS: Build debugfs.o only when enabled in Kconfig In addition, the 0day bot reported this build error: >> drivers/ras/debugfs.c:10:5: error: redefinition of 'ras_userspace_consumers' int ras_userspace_consumers(void) ^~~~~~~~~~~~~~~~~~~~~~~ In file included from drivers/ras/debugfs.c:3:0: include/linux/ras.h:14:19: note: previous definition of 'ras_userspace_consumers' was here static inline int ras_userspace_consumers(void) { return 0; } ^~~~~~~~~~~~~~~~~~~~~~~ for a riscv-specific .config where CONFIG_DEBUG_FS is not set. Fix all that by making debugfs.o depend on that define. [ bp: Rewrite commit message. ] Reported-by: kbuild test robot Signed-off-by: Valdis Kletnieks Signed-off-by: Borislav Petkov Cc: Tony Luck Cc: linux-edac@vger.kernel.org Cc: x86@kernel.org Link: http://lkml.kernel.org/r/7053.1565218556@turing-police --- drivers/ras/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile index ef6777e14d3d..6f0404f50107 100644 --- a/drivers/ras/Makefile +++ b/drivers/ras/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_RAS) += ras.o debugfs.o +obj-$(CONFIG_RAS) += ras.o +obj-$(CONFIG_DEBUG_FS) += debugfs.o obj-$(CONFIG_RAS_CEC) += cec.o -- GitLab From 82413e562ea6eadfb6de946dcc6f74af31d64e7f Mon Sep 17 00:00:00 2001 From: Shravan Kumar Ramani Date: Tue, 25 Jun 2019 15:13:59 -0400 Subject: [PATCH 2266/7155] EDAC, mellanox: Add ECC support for BlueField DDR4 Add ECC support for Mellanox BlueField SoC DDR controller. This requires SMC to the running Arm Trusted Firmware to report what is the current memory configuration. Reviewed-by: James Morse Signed-off-by: Shravan Kumar Ramani Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 5 + drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/bluefield_edac.c | 356 ++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+) create mode 100644 drivers/edac/bluefield_edac.c diff --git a/MAINTAINERS b/MAINTAINERS index 7c22905b5aba..97912d8333a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5757,6 +5757,11 @@ S: Supported F: drivers/edac/aspeed_edac.c F: Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt +EDAC-BLUEFIELD +M: Shravan Kumar Ramani +S: Supported +F: drivers/edac/bluefield_edac.c + EDAC-CALXEDA M: Robert Richter L: linux-edac@vger.kernel.org diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 200c04ce5b0e..2a2603bfb918 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -510,4 +510,11 @@ config EDAC_ASPEED First, ECC must be configured in the bootloader. Then, this driver will expose error counters via the EDAC kernel framework. +config EDAC_BLUEFIELD + tristate "Mellanox BlueField Memory ECC" + depends on ARM64 && ((MELLANOX_PLATFORM && ACPI) || COMPILE_TEST) + help + Support for error detection and correction on the + Mellanox BlueField SoCs. + endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 165ca65e1a3a..d265ff9311f0 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -85,3 +85,4 @@ obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o +obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c new file mode 100644 index 000000000000..e4736eb37bfb --- /dev/null +++ b/drivers/edac/bluefield_edac.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bluefield-specific EDAC driver. + * + * Copyright (c) 2019 Mellanox Technologies. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "edac_module.h" + +#define DRIVER_NAME "bluefield-edac" + +/* + * Mellanox BlueField EMI (External Memory Interface) register definitions. + */ + +#define MLXBF_ECC_CNT 0x340 +#define MLXBF_ECC_CNT__SERR_CNT GENMASK(15, 0) +#define MLXBF_ECC_CNT__DERR_CNT GENMASK(31, 16) + +#define MLXBF_ECC_ERR 0x348 +#define MLXBF_ECC_ERR__SECC BIT(0) +#define MLXBF_ECC_ERR__DECC BIT(16) + +#define MLXBF_ECC_LATCH_SEL 0x354 +#define MLXBF_ECC_LATCH_SEL__START BIT(24) + +#define MLXBF_ERR_ADDR_0 0x358 + +#define MLXBF_ERR_ADDR_1 0x37c + +#define MLXBF_SYNDROM 0x35c +#define MLXBF_SYNDROM__DERR BIT(0) +#define MLXBF_SYNDROM__SERR BIT(1) +#define MLXBF_SYNDROM__SYN GENMASK(25, 16) + +#define MLXBF_ADD_INFO 0x364 +#define MLXBF_ADD_INFO__ERR_PRANK GENMASK(9, 8) + +#define MLXBF_EDAC_MAX_DIMM_PER_MC 2 +#define MLXBF_EDAC_ERROR_GRAIN 8 + +/* + * Request MLNX_SIP_GET_DIMM_INFO + * + * Retrieve information about DIMM on a certain slot. + * + * Call register usage: + * a0: MLNX_SIP_GET_DIMM_INFO + * a1: (Memory controller index) << 16 | (Dimm index in memory controller) + * a2-7: not used. + * + * Return status: + * a0: MLXBF_DIMM_INFO defined below describing the DIMM. + * a1-3: not used. + */ +#define MLNX_SIP_GET_DIMM_INFO 0x82000008 + +/* Format for the SMC response about the memory information */ +#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0) +#define MLXBF_DIMM_INFO__IS_RDIMM BIT(16) +#define MLXBF_DIMM_INFO__IS_LRDIMM BIT(17) +#define MLXBF_DIMM_INFO__IS_NVDIMM BIT(18) +#define MLXBF_DIMM_INFO__RANKS GENMASK_ULL(23, 21) +#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24) + +struct bluefield_edac_priv { + int dimm_ranks[MLXBF_EDAC_MAX_DIMM_PER_MC]; + void __iomem *emi_base; + int dimm_per_mc; +}; + +static u64 smc_call1(u64 smc_op, u64 smc_arg) +{ + struct arm_smccc_res res; + + arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res); + + return res.a0; +} + +/* + * Gather the ECC information from the External Memory Interface registers + * and report it to the edac handler. + */ +static void bluefield_gather_report_ecc(struct mem_ctl_info *mci, + int error_cnt, + int is_single_ecc) +{ + struct bluefield_edac_priv *priv = mci->pvt_info; + u32 dram_additional_info, err_prank, edea0, edea1; + u32 ecc_latch_select, dram_syndrom, serr, derr, syndrom; + enum hw_event_mc_err_type ecc_type; + u64 ecc_dimm_addr; + int ecc_dimm; + + ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED : + HW_EVENT_ERR_UNCORRECTED; + + /* + * Tell the External Memory Interface to populate the relevant + * registers with information about the last ECC error occurrence. + */ + ecc_latch_select = MLXBF_ECC_LATCH_SEL__START; + writel(ecc_latch_select, priv->emi_base + MLXBF_ECC_LATCH_SEL); + + /* + * Verify that the ECC reported info in the registers is of the + * same type as the one asked to report. If not, just report the + * error without the detailed information. + */ + dram_syndrom = readl(priv->emi_base + MLXBF_SYNDROM); + serr = FIELD_GET(MLXBF_SYNDROM__SERR, dram_syndrom); + derr = FIELD_GET(MLXBF_SYNDROM__DERR, dram_syndrom); + syndrom = FIELD_GET(MLXBF_SYNDROM__SYN, dram_syndrom); + + if ((is_single_ecc && !serr) || (!is_single_ecc && !derr)) { + edac_mc_handle_error(ecc_type, mci, error_cnt, 0, 0, 0, + 0, 0, -1, mci->ctl_name, ""); + return; + } + + dram_additional_info = readl(priv->emi_base + MLXBF_ADD_INFO); + err_prank = FIELD_GET(MLXBF_ADD_INFO__ERR_PRANK, dram_additional_info); + + ecc_dimm = (err_prank >= 2 && priv->dimm_ranks[0] <= 2) ? 1 : 0; + + edea0 = readl(priv->emi_base + MLXBF_ERR_ADDR_0); + edea1 = readl(priv->emi_base + MLXBF_ERR_ADDR_1); + + ecc_dimm_addr = ((u64)edea1 << 32) | edea0; + + edac_mc_handle_error(ecc_type, mci, error_cnt, + PFN_DOWN(ecc_dimm_addr), + offset_in_page(ecc_dimm_addr), + syndrom, ecc_dimm, 0, 0, mci->ctl_name, ""); +} + +static void bluefield_edac_check(struct mem_ctl_info *mci) +{ + struct bluefield_edac_priv *priv = mci->pvt_info; + u32 ecc_count, single_error_count, double_error_count, ecc_error = 0; + + /* + * The memory controller might not be initialized by the firmware + * when there isn't memory, which may lead to bad register readings. + */ + if (mci->edac_cap == EDAC_FLAG_NONE) + return; + + ecc_count = readl(priv->emi_base + MLXBF_ECC_CNT); + single_error_count = FIELD_GET(MLXBF_ECC_CNT__SERR_CNT, ecc_count); + double_error_count = FIELD_GET(MLXBF_ECC_CNT__DERR_CNT, ecc_count); + + if (single_error_count) { + ecc_error |= MLXBF_ECC_ERR__SECC; + + bluefield_gather_report_ecc(mci, single_error_count, 1); + } + + if (double_error_count) { + ecc_error |= MLXBF_ECC_ERR__DECC; + + bluefield_gather_report_ecc(mci, double_error_count, 0); + } + + /* Write to clear reported errors. */ + if (ecc_count) + writel(ecc_error, priv->emi_base + MLXBF_ECC_ERR); +} + +/* Initialize the DIMMs information for the given memory controller. */ +static void bluefield_edac_init_dimms(struct mem_ctl_info *mci) +{ + struct bluefield_edac_priv *priv = mci->pvt_info; + int mem_ctrl_idx = mci->mc_idx; + struct dimm_info *dimm; + u64 smc_info, smc_arg; + int is_empty = 1, i; + + for (i = 0; i < priv->dimm_per_mc; i++) { + dimm = mci->dimms[i]; + + smc_arg = mem_ctrl_idx << 16 | i; + smc_info = smc_call1(MLNX_SIP_GET_DIMM_INFO, smc_arg); + + if (!FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info)) { + dimm->mtype = MEM_EMPTY; + continue; + } + + is_empty = 0; + + dimm->edac_mode = EDAC_SECDED; + + if (FIELD_GET(MLXBF_DIMM_INFO__IS_NVDIMM, smc_info)) + dimm->mtype = MEM_NVDIMM; + else if (FIELD_GET(MLXBF_DIMM_INFO__IS_LRDIMM, smc_info)) + dimm->mtype = MEM_LRDDR4; + else if (FIELD_GET(MLXBF_DIMM_INFO__IS_RDIMM, smc_info)) + dimm->mtype = MEM_RDDR4; + else + dimm->mtype = MEM_DDR4; + + dimm->nr_pages = + FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info) * + (SZ_1G / PAGE_SIZE); + dimm->grain = MLXBF_EDAC_ERROR_GRAIN; + + /* Mem controller for BlueField only supports x4, x8 and x16 */ + switch (FIELD_GET(MLXBF_DIMM_INFO__PACKAGE_X, smc_info)) { + case 4: + dimm->dtype = DEV_X4; + break; + case 8: + dimm->dtype = DEV_X8; + break; + case 16: + dimm->dtype = DEV_X16; + break; + default: + dimm->dtype = DEV_UNKNOWN; + } + + priv->dimm_ranks[i] = + FIELD_GET(MLXBF_DIMM_INFO__RANKS, smc_info); + } + + if (is_empty) + mci->edac_cap = EDAC_FLAG_NONE; + else + mci->edac_cap = EDAC_FLAG_SECDED; +} + +static int bluefield_edac_mc_probe(struct platform_device *pdev) +{ + struct bluefield_edac_priv *priv; + struct device *dev = &pdev->dev; + struct edac_mc_layer layers[1]; + struct mem_ctl_info *mci; + struct resource *emi_res; + unsigned int mc_idx, dimm_count; + int rc, ret; + + /* Read the MSS (Memory SubSystem) index from ACPI table. */ + if (device_property_read_u32(dev, "mss_number", &mc_idx)) { + dev_warn(dev, "bf_edac: MSS number unknown\n"); + return -EINVAL; + } + + /* Read the DIMMs per MC from ACPI table. */ + if (device_property_read_u32(dev, "dimm_per_mc", &dimm_count)) { + dev_warn(dev, "bf_edac: DIMMs per MC unknown\n"); + return -EINVAL; + } + + if (dimm_count > MLXBF_EDAC_MAX_DIMM_PER_MC) { + dev_warn(dev, "bf_edac: DIMMs per MC not valid\n"); + return -EINVAL; + } + + emi_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!emi_res) + return -EINVAL; + + layers[0].type = EDAC_MC_LAYER_SLOT; + layers[0].size = dimm_count; + layers[0].is_virt_csrow = true; + + mci = edac_mc_alloc(mc_idx, ARRAY_SIZE(layers), layers, sizeof(*priv)); + if (!mci) + return -ENOMEM; + + priv = mci->pvt_info; + + priv->dimm_per_mc = dimm_count; + priv->emi_base = devm_ioremap_resource(dev, emi_res); + if (IS_ERR(priv->emi_base)) { + dev_err(dev, "failed to map EMI IO resource\n"); + ret = PTR_ERR(priv->emi_base); + goto err; + } + + mci->pdev = dev; + mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_RDDR4 | + MEM_FLAG_LRDDR4 | MEM_FLAG_NVDIMM; + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + + mci->mod_name = DRIVER_NAME; + mci->ctl_name = "BlueField_Memory_Controller"; + mci->dev_name = dev_name(dev); + mci->edac_check = bluefield_edac_check; + + /* Initialize mci with the actual populated DIMM information. */ + bluefield_edac_init_dimms(mci); + + platform_set_drvdata(pdev, mci); + + /* Register with EDAC core */ + rc = edac_mc_add_mc(mci); + if (rc) { + dev_err(dev, "failed to register with EDAC core\n"); + ret = rc; + goto err; + } + + /* Only POLL mode supported so far. */ + edac_op_state = EDAC_OPSTATE_POLL; + + return 0; + +err: + edac_mc_free(mci); + + return ret; + +} + +static int bluefield_edac_mc_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + + return 0; +} + +static const struct acpi_device_id bluefield_mc_acpi_ids[] = { + {"MLNXBF08", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, bluefield_mc_acpi_ids); + +static struct platform_driver bluefield_edac_mc_driver = { + .driver = { + .name = DRIVER_NAME, + .acpi_match_table = bluefield_mc_acpi_ids, + }, + .probe = bluefield_edac_mc_probe, + .remove = bluefield_edac_mc_remove, +}; + +module_platform_driver(bluefield_edac_mc_driver); + +MODULE_DESCRIPTION("Mellanox BlueField memory edac driver"); +MODULE_AUTHOR("Mellanox Technologies"); +MODULE_LICENSE("GPL v2"); -- GitLab From b0d525a007b9c954bd2f777174a378eb76cb89e2 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 6 Aug 2019 10:33:49 +0000 Subject: [PATCH 2267/7155] staging: wilc1000: use helper API to pack data for firmware As discussed in [1] use put_unaligned_le16() & put_unaligned_le32() helper to pack the data before sending to firmware. [1]. https://lore.kernel.org/linux-wireless/86bc79ccd379497d56bade79ec8f717603110ef7.camel@sipsolutions.net/ Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20190806103325.14063-1-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan_cfg.c | 74 ++++++------------------ 1 file changed, 18 insertions(+), 56 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index f4144f93e4a9..3f53807cee0f 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -52,57 +52,35 @@ static const struct wilc_cfg_str g_cfg_str[] = { static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8) { - u8 *buf; - if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 1; - buf[3] = 0; - buf[4] = val8; + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(1, &frame[offset + 2]); + frame[offset + 4] = val8; return 5; } static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16) { - u8 *buf; - if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 2; - buf[3] = 0; - buf[4] = (u8)val16; - buf[5] = (u8)(val16 >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(2, &frame[offset + 2]); + put_unaligned_le16(val16, &frame[offset + 4]); return 6; } static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) { - u8 *buf; - if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 4; - buf[3] = 0; - buf[4] = (u8)val32; - buf[5] = (u8)(val32 >> 8); - buf[6] = (u8)(val32 >> 16); - buf[7] = (u8)(val32 >> 24); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(4, &frame[offset + 2]); + put_unaligned_le32(val32, &frame[offset + 4]); return 8; } @@ -110,46 +88,35 @@ static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, u32 size) { - u8 *buf; - if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); - + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if (str && size != 0) - memcpy(&buf[4], str, size); + memcpy(&frame[offset + 4], str, size); return (size + 4); } static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) { - u8 *buf; u32 i; u8 checksum = 0; if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if ((b) && size != 0) { - memcpy(&buf[4], b, size); + memcpy(&frame[offset + 4], b, size); for (i = 0; i < size; i++) - checksum += buf[i + 4]; + checksum += frame[offset + i + 4]; } - buf[size + 4] = checksum; + frame[offset + size + 4] = checksum; return (size + 5); } @@ -307,15 +274,10 @@ int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size) int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) { - u8 *buf; - if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); + put_unaligned_le16(id, &frame[offset]); return 2; } -- GitLab From 4f4139e0213516e74cc22fc9787671f325c2b66b Mon Sep 17 00:00:00 2001 From: Merwin Trever Ferrao Date: Tue, 6 Aug 2019 17:58:49 +0530 Subject: [PATCH 2268/7155] Staging: rtl8188eu: core: rtw_security: tidy up crc32_init() This code generates checkpatch warning: WARNING: else is not generally useful after a break or return Moving the declaration to the top of the function we can pull the code back one tab and it makes it more readable. Signed-off-by: Merwin Trever Ferrao Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190806122849.GA25628@IoT-COE Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_security.c | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 2f90f60f1681..435c0fbec54a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -87,29 +87,28 @@ static u8 crc32_reverseBit(u8 data) static void crc32_init(void) { - if (bcrc32initialized == 1) { + int i, j; + u32 c; + u8 *p = (u8 *)&c, *p1; + u8 k; + + if (bcrc32initialized == 1) return; - } else { - int i, j; - u32 c; - u8 *p = (u8 *)&c, *p1; - u8 k; - - c = 0x12340000; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); - p1 = (u8 *)&crc32_table[i]; - - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - bcrc32initialized = 1; + + c = 0x12340000; + + for (i = 0; i < 256; ++i) { + k = crc32_reverseBit((u8)i); + for (c = ((u32)k) << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); + p1 = (u8 *)&crc32_table[i]; + + p1[0] = crc32_reverseBit(p[3]); + p1[1] = crc32_reverseBit(p[2]); + p1[2] = crc32_reverseBit(p[1]); + p1[3] = crc32_reverseBit(p[0]); } + bcrc32initialized = 1; } static __le32 getcrc32(u8 *buf, int len) -- GitLab From 5222a8fe6bd0135bd87a629d8d182f951b4ffeae Mon Sep 17 00:00:00 2001 From: Giridhar Prasath R Date: Wed, 7 Aug 2019 07:33:31 +0530 Subject: [PATCH 2269/7155] staging: isdn: hysdn_procconf_init() remove parantheses from return value ERROR: return is not a function, parentheses are not required FILE: git/kernels/staging/drivers/staging/isdn/hysdn/hysdn_procconf.c:385 + return (0); Signed-off-by: Giridhar Prasath R Link: https://lore.kernel.org/r/20190807020331.19729-1-cristianoprasath@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/isdn/hysdn/hysdn_procconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/isdn/hysdn/hysdn_procconf.c b/drivers/staging/isdn/hysdn/hysdn_procconf.c index 73079213ec94..48afd9f5316e 100644 --- a/drivers/staging/isdn/hysdn/hysdn_procconf.c +++ b/drivers/staging/isdn/hysdn/hysdn_procconf.c @@ -382,7 +382,7 @@ hysdn_procconf_init(void) } printk(KERN_NOTICE "HYSDN: procfs initialised\n"); - return (0); + return 0; } /* hysdn_procconf_init */ /*************************************************************************************/ -- GitLab From a9ca0c5951ff1cb782cd78dd3eb57afb35f2f841 Mon Sep 17 00:00:00 2001 From: Jose Carlos Cazarin Filho Date: Tue, 6 Aug 2019 20:45:39 -0300 Subject: [PATCH 2270/7155] staging: rtl8723bs: fix brace position in enum declaration Fix two checkpath errors of type: "open brace '{' following enum go on the same line" Signed-off-by: Jose Carlos Cazarin Filho Link: https://lore.kernel.org/r/20190806234539.7513-1-joseespiriki@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/include/rtw_mlme.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index d3c07d1c36e9..2223e1f139f2 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -81,15 +81,13 @@ enum dot11AuthAlgrthmNum { }; /* Scan type including active and passive scan. */ -typedef enum _RT_SCAN_TYPE -{ +typedef enum _RT_SCAN_TYPE { SCAN_PASSIVE, SCAN_ACTIVE, SCAN_MIX, }RT_SCAN_TYPE, *PRT_SCAN_TYPE; -enum _BAND -{ +enum _BAND { GHZ24_50 = 0, GHZ_50, GHZ_24, -- GitLab From fc898688aa37c08b872a2228d1f0397d01111652 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:03 +0530 Subject: [PATCH 2271/7155] staging: rtl8712: amsdu_to_msdu(): Change return type Change return type of amsdu_to_msdu from int to void as it always returns _SUCCESS. Remove return statement as well. As this return value was never anything other than _SUCCESS, remove the if-branch that depends on the return value not being _SUCCESS. Remove local variable that was only used in the now-removed if-branch Modify call site to call the function amsdu_to_msdu without expecting a return value. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index eb9a4a5ed740..42372e7e76ac 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -318,7 +318,7 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, return prtnframe; } -static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) +static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) { int a_len, padding_len; u16 eth_type, nSubframe_Length; @@ -416,7 +416,6 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) exit: prframe->u.hdr.len = 0; r8712_free_recvframe(prframe, pfree_recv_queue); - return _SUCCESS; } void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf) @@ -506,7 +505,6 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, union recv_frame *prframe; struct rx_pkt_attrib *pattrib; int bPktInBuf = false; - struct recv_priv *precvpriv = &padapter->recvpriv; struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; @@ -543,10 +541,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, prframe); } } else if (pattrib->amsdu == 1) { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - r8712_free_recvframe(prframe, - &precvpriv->free_recv_queue); + amsdu_to_msdu(padapter, prframe); } /* Update local variables. */ bPktInBuf = false; -- GitLab From 4dbadfaf6a77e3d9ffe7069a8f1a13ae0df00d56 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:04 +0530 Subject: [PATCH 2272/7155] staging: rtl8712: recv_indicatepkt_reorder(): Change return values Change return values of recv_indicatepkt_reorder from _SUCCESS/_FAIL to 0/-ENOMEM and -EINVAL. Within recv_indicatepkt_reorder, modify comparison to true and use the respective value directly. Modify call site of recv_indicatepkt_reorder to check for the new return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 42372e7e76ac..3950b2424b64 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -569,9 +569,9 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, if (!padapter->driver_stopped && !padapter->surprise_removed) { r8712_recv_indicatepkt(padapter, prframe); - return _SUCCESS; + return 0; } else { - return _FAIL; + return -EINVAL; } } } @@ -593,8 +593,7 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, * 2. All packets with SeqNum larger than or equal to * WinStart => Buffer it. */ - if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == - true) { + if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) { mod_timer(&preorder_ctrl->reordering_ctrl_timer, jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); @@ -602,10 +601,10 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); del_timer(&preorder_ctrl->reordering_ctrl_timer); } - return _SUCCESS; + return 0; _err_exit: spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - return _FAIL; + return -ENOMEM; } void r8712_reordering_ctrl_timeout_handler(void *pcontext) @@ -631,7 +630,7 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, struct ht_priv *phtpriv = &pmlmepriv->htpriv; if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { + if (recv_indicatepkt_reorder(padapter, prframe)) { /* including perform A-MPDU Rx Ordering Buffer Control*/ if (!padapter->driver_stopped && !padapter->surprise_removed) -- GitLab From 1bdcb3666a83e533feb35a5a86e4e8e01b44dc18 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:05 +0530 Subject: [PATCH 2273/7155] staging: rtl8712: r8712_wlanhdr_to_ethhdr(): Change return values Change return values of r8712_wlanhdr_to_ethhdr from _SUCCESS/_FAIL to 0/-ENOMEM. Modify the function containing a call site of r8712_wlanhdr_to_ethhdr so that it compares the return value to 0/-ENOMEM instead of _SUCCESS/_FAIL. Change the return type of r8712_wlanhdr_to_ethhdr from sint to int to match its prototype in corresponding .h file. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 4 ++-- drivers/staging/rtl8712/rtl871x_recv.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 3950b2424b64..0c5712898653 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -638,8 +638,8 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, } } else { /*B/G mode*/ retval = r8712_wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) - return retval; + if (retval) + return _FAIL; if (!padapter->driver_stopped && !padapter->surprise_removed) { /* indicate this recv_frame */ r8712_recv_indicatepkt(padapter, prframe); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 79c7a329e9f6..4fae3af36af5 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -585,7 +585,7 @@ sint r8712_validate_recv_frame(struct _adapter *adapter, return retval; } -sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) +int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) { /*remove the wlanhdr and add the eth_hdr*/ sint rmv_len; @@ -628,14 +628,14 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24); if (!ptr) - return _FAIL; + return -ENOMEM; memcpy(ptr, get_rxmem(precvframe), 24); ptr += 24; } else { ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); if (!ptr) - return _FAIL; + return -ENOMEM; } memcpy(ptr, pattrib->dst, ETH_ALEN); @@ -645,7 +645,7 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) memcpy(ptr + 12, &be_tmp, 2); } - return _SUCCESS; + return 0; } s32 r8712_recv_entry(union recv_frame *precvframe) -- GitLab From af556d30d3387f8b01495b1645d237121b6624d6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:06 +0530 Subject: [PATCH 2274/7155] staging: rtl8712: r8712_recv_entry(): Change return type Change return type of r8712_recv_entry from s32 to void as its return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 792f9cfbacd9..d8c1fa74f544 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -21,7 +21,7 @@ void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void _r8712_free_recv_priv(struct recv_priv *precvpriv); -s32 r8712_recv_entry(union recv_frame *precv_frame); +void r8712_recv_entry(union recv_frame *precv_frame); void r8712_recv_indicatepkt(struct _adapter *adapter, union recv_frame *precv_frame); void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 4fae3af36af5..e5092b6da4bd 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -648,7 +648,7 @@ int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) return 0; } -s32 r8712_recv_entry(union recv_frame *precvframe) +void r8712_recv_entry(union recv_frame *precvframe) { struct _adapter *padapter; struct recv_priv *precvpriv; @@ -666,9 +666,8 @@ s32 r8712_recv_entry(union recv_frame *precvframe) precvpriv->rx_pkts++; precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail - precvframe->u.hdr.rx_data); - return ret; + return; _recv_entry_drop: precvpriv->rx_drop++; padapter->mppriv.rx_pktloss = precvpriv->rx_drop; - return ret; } -- GitLab From 9dca5e687fb05e1b968e5151fd868ed4722863f6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:07 +0530 Subject: [PATCH 2275/7155] staging: rtl8712: recvbuf2recvframe(): Change return type Change return type of recvbuf2recvframe from int to void as its return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 0c5712898653..42cb2c95b40c 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -980,7 +980,7 @@ int recv_func(struct _adapter *padapter, void *pcontext) return retval; } -static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) +static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) { u8 *pbuf, shift_sz = 0; u8 frag, mf; @@ -1007,7 +1007,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) /* In this case, it means the MAX_RECVBUF_SZ is too small to * get the data from 8712u. */ - return _FAIL; + return; } do { prxstat = (struct recv_stat *)pbuf; @@ -1020,13 +1020,13 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; drvinfo_sz <<= 3; if (pkt_len <= 0) - goto _exit_recvbuf2recvframe; + return; /* Qos data, wireless lan header length is 26 */ if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) shift_sz = 2; precvframe = r8712_alloc_recvframe(pfree_recv_queue); if (!precvframe) - goto _exit_recvbuf2recvframe; + return; INIT_LIST_HEAD(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ precvframe->u.hdr.len = 0; @@ -1057,7 +1057,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) } else { precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); if (!precvframe->u.hdr.pkt) - return _FAIL; + return; precvframe->u.hdr.rx_head = pbuf; precvframe->u.hdr.rx_data = pbuf; precvframe->u.hdr.rx_tail = pbuf; @@ -1077,8 +1077,6 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) precvframe = NULL; pkt_copy = NULL; } while ((transfer_len > 0) && pkt_cnt > 0); -_exit_recvbuf2recvframe: - return _SUCCESS; } static void recv_tasklet(void *priv) -- GitLab From 30d83c801d068abbfbb8f6f47e0c1f2a4a36e4b9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:08 +0530 Subject: [PATCH 2276/7155] staging: rtl8712: init_default_value(): Change return type Change return type of init_default_value from u8 to void as it always returns _SUCCESS. Remove now-unnecessary return statement. Modify call site to simply call the function. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b4059ea17e5c..c98acf4f6fff 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -258,7 +258,7 @@ void r8712_stop_drv_timers(struct _adapter *padapter) del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer); } -static u8 init_default_value(struct _adapter *padapter) +static void init_default_value(struct _adapter *padapter) { struct registry_priv *pregistrypriv = &padapter->registrypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -292,7 +292,6 @@ static u8 init_default_value(struct _adapter *padapter) r8712_init_registrypriv_dev_network(padapter); r8712_update_registrypriv_dev_network(padapter); /*misc.*/ - return _SUCCESS; } u8 r8712_init_drv_sw(struct _adapter *padapter) @@ -316,8 +315,7 @@ u8 r8712_init_drv_sw(struct _adapter *padapter) r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); mp871xinit(padapter); - if (init_default_value(padapter) != _SUCCESS) - return _FAIL; + init_default_value(padapter); r8712_InitSwLeds(padapter); return _SUCCESS; } -- GitLab From 690407fdc9dd8103a78c251c59513646f1bed50d Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:09 +0530 Subject: [PATCH 2277/7155] staging: rtl8712: init_drv_sw(): Change return values Change return values of init_drv_sw from _SUCCESS and _FAIL to 0 and -ENOMEM. Change return type from u8 to int to allow this. Add a return variable to streamline return of error codes of called functions. Modify call site to check for non-zero return value instead of _FAIL. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 26 ++++++++++++++++---------- drivers/staging/rtl8712/usb_intf.c | 2 +- drivers/staging/rtl8712/usb_osintf.h | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index c98acf4f6fff..be3e5bdea495 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -294,30 +294,36 @@ static void init_default_value(struct _adapter *padapter) /*misc.*/ } -u8 r8712_init_drv_sw(struct _adapter *padapter) +int r8712_init_drv_sw(struct _adapter *padapter) { - if (r8712_init_cmd_priv(&padapter->cmdpriv)) - return _FAIL; + int ret; + + ret = r8712_init_cmd_priv(&padapter->cmdpriv); + if (ret) + return ret; padapter->cmdpriv.padapter = padapter; - if (r8712_init_evt_priv(&padapter->evtpriv)) - return _FAIL; - if (r8712_init_mlme_priv(padapter)) - return _FAIL; + ret = r8712_init_evt_priv(&padapter->evtpriv); + if (ret) + return ret; + ret = r8712_init_mlme_priv(padapter); + if (ret) + return ret; _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); _r8712_init_recv_priv(&padapter->recvpriv, padapter); memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); timer_setup(&padapter->securitypriv.tkip_timer, r8712_use_tkipkey_handler, 0); - if (_r8712_init_sta_priv(&padapter->stapriv)) - return _FAIL; + ret = _r8712_init_sta_priv(&padapter->stapriv); + if (ret) + return ret; padapter->stapriv.padapter = padapter; r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); mp871xinit(padapter); init_default_value(padapter); r8712_InitSwLeds(padapter); - return _SUCCESS; + return ret; } u8 r8712_free_drv_sw(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index d0daae0b8299..ba1288297ee4 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -389,7 +389,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } /* step 4. */ status = r8712_init_drv_sw(padapter); - if (status == _FAIL) + if (status) goto error; /* step 5. read efuse/eeprom data and get mac_addr */ { diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h index ddfa405d0c9b..b649adedfe7c 100644 --- a/drivers/staging/rtl8712/usb_osintf.h +++ b/drivers/staging/rtl8712/usb_osintf.h @@ -28,7 +28,7 @@ void rtl871x_intf_stop(struct _adapter *padapter); void r871x_dev_unload(struct _adapter *padapter); void r8712_stop_drv_threads(struct _adapter *padapter); void r8712_stop_drv_timers(struct _adapter *padapter); -u8 r8712_init_drv_sw(struct _adapter *padapter); +int r8712_init_drv_sw(struct _adapter *padapter); u8 r8712_free_drv_sw(struct _adapter *padapter); struct net_device *r8712_init_netdev(void); -- GitLab From 02433a24fe71ba31b8392c2bf98ff9e8a2bce3b6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:10 +0530 Subject: [PATCH 2278/7155] staging: rtl8712: r8712_free_drv_sw(): Change return type Change return type of r8712_free_drv_sw from u8 to void and remove its return statement as it always returns the same value (_SUCCESS) and even this value is never stored, checked or otherwise used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 3 +-- drivers/staging/rtl8712/usb_osintf.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index be3e5bdea495..0c3ae8495afb 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -326,7 +326,7 @@ int r8712_init_drv_sw(struct _adapter *padapter) return ret; } -u8 r8712_free_drv_sw(struct _adapter *padapter) +void r8712_free_drv_sw(struct _adapter *padapter) { struct net_device *pnetdev = padapter->pnetdev; @@ -341,7 +341,6 @@ u8 r8712_free_drv_sw(struct _adapter *padapter) mp871xdeinit(padapter); if (pnetdev) free_netdev(pnetdev); - return _SUCCESS; } static void enable_video_mode(struct _adapter *padapter, int cbw40_value) diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h index b649adedfe7c..2e512b4a564c 100644 --- a/drivers/staging/rtl8712/usb_osintf.h +++ b/drivers/staging/rtl8712/usb_osintf.h @@ -29,7 +29,7 @@ void r871x_dev_unload(struct _adapter *padapter); void r8712_stop_drv_threads(struct _adapter *padapter); void r8712_stop_drv_timers(struct _adapter *padapter); int r8712_init_drv_sw(struct _adapter *padapter); -u8 r8712_free_drv_sw(struct _adapter *padapter); +void r8712_free_drv_sw(struct _adapter *padapter); struct net_device *r8712_init_netdev(void); #endif -- GitLab From 1c8a4f7c84dcb187c076a87e716912053f6ad6ba Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:11 +0530 Subject: [PATCH 2279/7155] staging: rtl8712: Remove while loop and check_cmd_fifo() Remove while loop as it only runs while the function check_cmd_fifo returns _FAIL, whereas check_cmd_fifo always returns _SUCCESS (and hence this loop will never run). Remove now unused function check_cmd_fifo. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_cmd.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index f99fd7cfa445..ff3cb09c57a6 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -263,11 +263,6 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */ } -static u8 check_cmd_fifo(struct _adapter *padapter, uint sz) -{ - return _SUCCESS; -} - u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd) { int pollingcnts = 50; @@ -359,13 +354,6 @@ int r8712_cmd_thread(void *context) (pcmdpriv->cmd_seq << 24)); pcmdbuf += 2; /* 8 bytes alignment */ memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); - while (check_cmd_fifo(padapter, wr_sz) == _FAIL) { - if (padapter->driver_stopped || - padapter->surprise_removed) - break; - msleep(100); - continue; - } if (blnPending) wr_sz += 8; /* Append 8 bytes */ r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, -- GitLab From 3f411e8c99e3354adc10350d0e2ee14914fd1961 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:12 +0530 Subject: [PATCH 2280/7155] staging: rtl8712: r8712_xmit_classifier(): Change return values and type Change return values of r8712_xmit_classifier from _SUCCESS and _FAIL to 0 and -EINVAL respectively. Modify call site to check for non-zero return values instead of _FAIL. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190808064012.12661-10-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 2 +- drivers/staging/rtl8712/rtl871x_xmit.c | 8 ++++---- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index dac79e6dcdcb..3334b03c2548 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -750,7 +750,7 @@ int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - if (r8712_xmit_classifier(padapter, pxmitframe) == _FAIL) { + if (r8712_xmit_classifier(padapter, pxmitframe)) { pxmitframe->pkt = NULL; return _FAIL; } diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 0a26d71e5340..f625fd5b9eb3 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -894,8 +894,8 @@ static inline struct tx_servq *get_sta_pending(struct _adapter *padapter, * Will enqueue pxmitframe to the proper queue, and indicate it * to xx_pending list..... */ -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe) +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe) { unsigned long irqL0; struct __queue *pstapending; @@ -920,7 +920,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, } } if (psta == NULL) - return _FAIL; + return -EINVAL; ptxservq = get_sta_pending(padapter, &pstapending, psta, pattrib->priority); spin_lock_irqsave(&pstapending->lock, irqL0); @@ -929,7 +929,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); ptxservq->qcnt++; spin_unlock_irqrestore(&pstapending->lock, irqL0); - return _SUCCESS; + return 0; } static void alloc_hwxmits(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index c5c55967164b..d4bc059e6a42 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -258,8 +258,8 @@ void r8712_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue); -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe); +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe); sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe); sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -- GitLab From 3881a72f8d0657ca998b217d0a183974ea800401 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 15:20:20 +0200 Subject: [PATCH 2281/7155] leds: pca953x: Include the right header This LED chip provides a GPIO driver, so include rather than the legacy header . Signed-off-by: Linus Walleij Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-pca9532.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 290871072d65..c7c7199e8ebd 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include -- GitLab From 804cbf4bb063204ca6c2471baa694548aab02ce3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 7 Aug 2019 09:50:30 -0500 Subject: [PATCH 2282/7155] ASoC: hdac_hda: fix page fault issue by removing race There is a race between hda codec device removing and the jack-detecting work, which will lead to a page fault issue as the latter work is accessing codec device which could be already removed. Here add the cancellation of jack-detecting work before codecs are actually removed to avoid the race and fix the issue. Bug: https://github.com/thesofproject/linux/issues/1067 Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807145030.26117-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hda.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 7d4940256914..91242b6f8ea7 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -495,6 +495,10 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) static int hdac_hda_dev_remove(struct hdac_device *hdev) { + struct hdac_hda_priv *hda_pvt; + + hda_pvt = dev_get_drvdata(&hdev->dev); + cancel_delayed_work_sync(&hda_pvt->codec.jackpoll_work); return 0; } -- GitLab From d566aae1c80d9be2276057b3236c68bdcc5b3254 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 8 Aug 2019 15:03:42 +0530 Subject: [PATCH 2283/7155] regulator: dt-bindings: Add PM8150x compatibles Add PM8150, PM8150L and PM8009 compatibles for these PMICs found in some Qualcomm platforms. Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190808093343.5600-1-vkoul@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/qcom,rpmh-regulator.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt index 14d2eee96b3d..1a9cab50503a 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt @@ -25,6 +25,9 @@ Supported regulator node names: PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 PMI8998: bob PM8005: smps1 - smps4 + PM8150: smps1 - smps10, ldo1 - ldo18 + PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb + PM8009: smps1 - smps2, ld01 - ldo7 ======================== First Level Nodes - PMIC @@ -35,7 +38,10 @@ First Level Nodes - PMIC Value type: Definition: Must be one of: "qcom,pm8998-rpmh-regulators", "qcom,pmi8998-rpmh-regulators" or - "qcom,pm8005-rpmh-regulators". + "qcom,pm8005-rpmh-regulators" or + "qcom,pm8150-rpmh-regulators" or + "qcom,pm8150l-rpmh-regulators" or + "qcom,pm8009-rpmh-regulators". - qcom,pmic-id Usage: required -- GitLab From 06369bcc15a1620930a17fb35e26477504cd2255 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 8 Aug 2019 15:03:43 +0530 Subject: [PATCH 2284/7155] regulator: qcom-rpmh: Add support for SM8150 Add support from RPMH regulators found in SM8150 platform Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190808093343.5600-2-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 147 ++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index b2c2d01d1637..693ffec62f3e 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -637,6 +637,72 @@ static const struct rpmh_vreg_hw_data pmic4_lvs = { /* LVS hardware does not support voltage or mode configuration. */ }; +static const struct rpmh_vreg_hw_data pmic5_pldo = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), + .n_voltages = 256, + .hpm_min_load_uA = 10000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_pldo_lv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000), + .n_voltages = 63, + .hpm_min_load_uA = 10000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_nldo = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000), + .n_voltages = 124, + .hpm_min_load_uA = 30000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), + .n_voltages = 216, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + .n_voltages = 264, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600), + .n_voltages = 5, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_bob = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_bypass_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), + .n_voltages = 135, + .pmic_mode_map = pmic_mode_map_pmic4_bob, + .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, +}; + #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ { \ .name = _name, \ @@ -705,6 +771,75 @@ static const struct rpmh_vreg_init_data pm8005_vreg_data[] = { {}, }; +static const struct rpmh_vreg_init_data pm8150_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps510, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps510, "vdd-s9"), + RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo18", "ldo%s18", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + {}, +}; + +static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8-l11"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"), + {}, +}; + +static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), + {}, +}; + static int rpmh_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -755,6 +890,18 @@ static const struct of_device_id rpmh_regulator_match_table[] = { .compatible = "qcom,pm8005-rpmh-regulators", .data = pm8005_vreg_data, }, + { + .compatible = "qcom,pm8150-rpmh-regulators", + .data = pm8150_vreg_data, + }, + { + .compatible = "qcom,pm8150l-rpmh-regulators", + .data = pm8150l_vreg_data, + }, + { + .compatible = "qcom,pm8009-rpmh-regulators", + .data = pm8009_vreg_data, + }, {} }; MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table); -- GitLab From 5375f1efd70b5adbbbaded22889d50c07f6f89a4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 7 Aug 2019 21:38:22 +0800 Subject: [PATCH 2285/7155] regulator: act8865: Fix build error without CONFIG_POWER_SUPPLY Building without CONFIG_POWER_SUPPLY will fail: drivers/regulator/act8865-regulator.o: In function `act8865_pmic_probe': act8865-regulator.c:(.text+0x357): undefined reference to `devm_power_supply_register' drivers/regulator/act8865-regulator.o: In function `act8600_charger_get_property': act8865-regulator.c:(.text+0x3f1): undefined reference to `power_supply_get_drvdata' Add POWER_SUPPLY dependency to Kconfig. Reported-by: Hulk Robot Fixes: 2d09a79bf637 ("regulator: act8865: Add support for act8600 charger") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190807133822.67124-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b57093d7c01f..37e64884b9ee 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -83,6 +83,7 @@ config REGULATOR_88PM8607 config REGULATOR_ACT8865 tristate "Active-semi act8865 voltage regulator" depends on I2C + depends on POWER_SUPPLY select REGMAP_I2C help This driver controls a active-semi act8865 voltage output -- GitLab From 43004f31ebf2705905460a6d9a77da4182170c38 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 17:03:21 +0200 Subject: [PATCH 2286/7155] spi: Rename of_spi_register_master() function Rename this function to of_spi_get_gpio_numbers() as this is what the function does, it does not register a master, it is called in the path of registering a master so the name is logical in a convoluted way, but it is better to follow Rusty Russell's ABI level no 7: "The obvious use is (probably) the correct one" Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808150321.23319-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8e83c9567353..aef55acb5ccd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2235,7 +2235,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, EXPORT_SYMBOL_GPL(__spi_alloc_controller); #ifdef CONFIG_OF -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { int nb, i, *cs; struct device_node *np = ctlr->dev.of_node; @@ -2268,7 +2268,7 @@ static int of_spi_register_master(struct spi_controller *ctlr) return 0; } #else -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { return 0; } @@ -2455,7 +2455,7 @@ int spi_register_controller(struct spi_controller *ctlr) ctlr->mode_bits |= SPI_CS_HIGH; } else { /* Legacy code path for GPIOs from DT */ - status = of_spi_register_master(ctlr); + status = of_spi_get_gpio_numbers(ctlr); if (status) return status; } -- GitLab From e6d7020c2946bef2efab7c70339eee6a6b3cb6a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:30:58 +0900 Subject: [PATCH 2287/7155] ASoC: soc-core: tidyup for snd_soc_add_component_controls() snd_soc_add_component_controls() registers controls by using for(... i < num; ...). If controls was NULL, num should be zero. Thus, we don't need to check about controls pointer. This patch also cares missing return value. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ef1xahor.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bb1e9e2c4ff4..e481f9999bfb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1304,10 +1304,12 @@ static int soc_probe_component(struct snd_soc_card *card, } } - if (component->driver->controls) - snd_soc_add_component_controls(component, - component->driver->controls, - component->driver->num_controls); + ret = snd_soc_add_component_controls(component, + component->driver->controls, + component->driver->num_controls); + if (ret < 0) + goto err_probe; + if (component->driver->dapm_routes) snd_soc_dapm_add_routes(dapm, component->driver->dapm_routes, -- GitLab From daa480bde6b3a9b728965e52efffc329ccee3f77 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:03 +0900 Subject: [PATCH 2288/7155] ASoC: soc-core: tidyup for snd_soc_dapm_add_routes() snd_soc_dapm_add_routes() registers routes by using for(... i < num; ...). If routes was NULL, num should be zero. Thus, we don't need to check about route pointer. This patch also cares missing return value. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87d0hhahon.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e481f9999bfb..de95b68ce9ee 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1310,10 +1310,11 @@ static int soc_probe_component(struct snd_soc_card *card, if (ret < 0) goto err_probe; - if (component->driver->dapm_routes) - snd_soc_dapm_add_routes(dapm, - component->driver->dapm_routes, - component->driver->num_dapm_routes); + ret = snd_soc_dapm_add_routes(dapm, + component->driver->dapm_routes, + component->driver->num_dapm_routes); + if (ret < 0) + goto err_probe; list_add(&dapm->list, &card->dapm_list); /* see for_each_card_components */ @@ -2061,13 +2062,15 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) snd_soc_add_card_controls(card, card->controls, card->num_controls); - if (card->dapm_routes) - snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, - card->num_dapm_routes); + ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, + card->num_dapm_routes); + if (ret < 0) + goto probe_end; - if (card->of_dapm_routes) - snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, - card->num_of_dapm_routes); + ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, + card->num_of_dapm_routes); + if (ret < 0) + goto probe_end; /* try to set some sane longname if DMI is available */ snd_soc_set_dmi_name(card, NULL); -- GitLab From 9b98c7c2a0599084c7ed629b5f88f474d2578307 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:08 +0900 Subject: [PATCH 2289/7155] ASoC: soc-core: tidyup for snd_soc_add_card_controls() snd_soc_add_card_controls() registers controls by using for(... i < num; ...). If controls was NULL, num should be zero. Thus, we don't need to check about controls pointer. This patch also cares missing return value. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blx1ahoi.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index de95b68ce9ee..4b9ae867613c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2058,9 +2058,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) snd_soc_dapm_link_dai_widgets(card); snd_soc_dapm_connect_dai_link_widgets(card); - if (card->controls) - snd_soc_add_card_controls(card, card->controls, - card->num_controls); + ret = snd_soc_add_card_controls(card, card->controls, + card->num_controls); + if (ret < 0) + goto probe_end; ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes); -- GitLab From d8ca7a0a8583fc491b625450580c4092879af3dd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:14 +0900 Subject: [PATCH 2290/7155] ASoC: soc-core: call snd_soc_dapm_debugfs_init() at soc_init_card_debugfs() We have 2 soc_init_card_debugfs() implementations for with/without DEBUG_FS. But, snd_soc_instantiate_card() calls snd_soc_dapm_debugfs_init() under ifdef DEBUG_FS after soc_init_card_debugfs(). This is very strange. We can call snd_soc_dapm_debugfs_init() under soc_init_card_debugfs(). #ifdef CONFIG_DEBUG_FS => static void soc_init_card_debugfs(...) { ... } ... #else => static inline void soc_init_card_debugfs(...) { ... } #endif static int snd_soc_instantiate_card(struct snd_soc_card *card) { ... => soc_init_card_debugfs(card); * #ifdef CONFIG_DEBUG_FS * snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); * #endif } Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a7clahob.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4b9ae867613c..cf3d967d731e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -216,6 +216,8 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root, &card->pop_time); + + snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); } static void soc_cleanup_card_debugfs(struct snd_soc_card *card) @@ -1982,10 +1984,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) soc_init_card_debugfs(card); -#ifdef CONFIG_DEBUG_FS - snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); -#endif - #ifdef CONFIG_PM_SLEEP /* deferred resume work */ INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); -- GitLab From b245d273cbcd64eeaa93305f99c4ea8a6baf9c89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:19 +0900 Subject: [PATCH 2291/7155] ASoC: soc-core: remove unneeded list_empty() check for snd_soc_try_rebind_card() list_for_each_entry_safe() will do nothing if it was empty list. This patch removes unneeded list_empty() check for list_for_each_entry_safe(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878ss5aho6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cf3d967d731e..6b0042835233 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2808,12 +2808,9 @@ static void snd_soc_try_rebind_card(void) { struct snd_soc_card *card, *c; - if (!list_empty(&unbind_card_list)) { - list_for_each_entry_safe(card, c, &unbind_card_list, list) { - if (!snd_soc_bind_card(card)) - list_del(&card->list); - } - } + list_for_each_entry_safe(card, c, &unbind_card_list, list) + if (!snd_soc_bind_card(card)) + list_del(&card->list); } int snd_soc_add_component(struct device *dev, -- GitLab From b3da42519c3e6ad977af844d61c31d0e5f874f1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:24 +0900 Subject: [PATCH 2292/7155] ASoC: soc-core: tidyup for card->deferred_resume_work card->deferred_resume_work is used if CONFIG_PM_SLEEP was defined. but 1) It is defined even though CONFIG_PM_SLEEP was not defined 2) random ifdef code is difficult to read. This patch tidyup these issues. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877e7paho1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 5 +++-- sound/soc/soc-core.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 6ac6481b4882..85ad971e9432 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1058,8 +1058,6 @@ struct snd_soc_card { int num_of_dapm_routes; bool fully_routed; - struct work_struct deferred_resume_work; - /* lists of probed devices belonging to this card */ struct list_head component_dev_list; struct list_head list; @@ -1079,6 +1077,9 @@ struct snd_soc_card { #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_card_root; +#endif +#ifdef CONFIG_PM_SLEEP + struct work_struct deferred_resume_work; #endif u32 pop_time; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6b0042835233..25b26caea4e0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -701,9 +701,18 @@ int snd_soc_resume(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(snd_soc_resume); + +static void soc_resume_init(struct snd_soc_card *card) +{ + /* deferred resume work */ + INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); +} #else #define snd_soc_suspend NULL #define snd_soc_resume NULL +static inline void soc_resume_init(struct snd_soc_card *card) +{ +} #endif static const struct snd_soc_dai_ops null_dai_ops = { @@ -1984,10 +1993,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) soc_init_card_debugfs(card); -#ifdef CONFIG_PM_SLEEP - /* deferred resume work */ - INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); -#endif + soc_resume_init(card); ret = snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, card->num_dapm_widgets); -- GitLab From ee5b3f11416d1ba69e919b2fe86aae0b46f9a83e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:31 +0900 Subject: [PATCH 2293/7155] ASoC: soc-core: define soc_dpcm_debugfs_add() for non CONFIG_DEBUG_FS soc_dpcm_debugfs_add() is implemented at soc-pcm.c under CONFIG_DEBUG_FS. Thus, soc-core.c which is only user of it need to use CONFIG_DEBUG_FS, too. This patch defines soc_dpcm_debugfs_add() for non CONFIG_DEBUG_FS case. Then, we can remove #ifdef CONFIG_DEBUG_FS from soc-core.c Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875zn9ahnv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 9 ++++++++- sound/soc/soc-core.c | 2 -- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 4be3a2b7c106..e55aeb00ce2d 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -142,9 +142,16 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, /* internal use only */ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); -void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); int soc_dpcm_runtime_update(struct snd_soc_card *); +#ifdef CONFIG_DEBUG_FS +void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); +#else +static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) +{ +} +#endif + int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_); int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 25b26caea4e0..2a75fba31aa4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1487,11 +1487,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, if (ret) return ret; -#ifdef CONFIG_DEBUG_FS /* add DPCM sysfs entries */ if (dai_link->dynamic) soc_dpcm_debugfs_add(rtd); -#endif num = rtd->num; -- GitLab From 596becd3f82a7b7e091b0f5c380bc9a0e6758126 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 7 Aug 2019 10:31:36 +0900 Subject: [PATCH 2294/7155] ASoC: soc-core: dai_link check under soc_dpcm_debugfs_add() soc_dpcm_debugfs_add(rtd) is checking rtd->dai_link pointer, but, rtd->dai_link->dynamic have been already checked before calling it. static int soc_probe_link_dais(...) { dai_link = rtd->dai_link; ... => if (dai_link->dynamic) => soc_dpcm_debugfs_add(rtd); ... } void soc_dpcm_debugfs_add(rtd) { => if (!rtd->dai_link) return; ... } These pointer checks are strange/pointless. This patch checks dai_link->dynamic under soc_dpcm_debugfs_add(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874l2tahnq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 +-- sound/soc/soc-pcm.c | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2a75fba31aa4..1fbd525763d5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1488,8 +1488,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, return ret; /* add DPCM sysfs entries */ - if (dai_link->dynamic) - soc_dpcm_debugfs_add(rtd); + soc_dpcm_debugfs_add(rtd); num = rtd->num; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 77c986fe08d0..da657c8179cc 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -3200,6 +3200,9 @@ void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) if (!rtd->dai_link) return; + if (!rtd->dai_link->dynamic) + return; + if (!rtd->card->debugfs_card_root) return; -- GitLab From 0e36f36b04e7677c6b74349c9d4baea1ed5668f2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 7 Aug 2019 21:51:31 -0500 Subject: [PATCH 2295/7155] ASoC: soc-core: fix module_put() warning in soc_cleanup_component The recent changes introduce warnings in the SOF load/unload module tests. The code does not seem balanced with a confusion between _close() and _remove() macros. Using _remove() fixes the issue and removes the warning. Suggested-by: Ranjani Sridharan Fixes: 4a81e8f30d0b4 ('ASoC: soc-component: add snd_soc_component_get/put()') Signed-off-by: Pierre-Louis Bossart Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20190808025131.32482-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1fbd525763d5..bf45e60eb34f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -935,7 +935,7 @@ static void soc_cleanup_component(struct snd_soc_component *component) snd_soc_dapm_free(snd_soc_component_get_dapm(component)); soc_cleanup_component_debugfs(component); component->card = NULL; - snd_soc_component_module_put_when_close(component); + snd_soc_component_module_put_when_remove(component); } static void soc_remove_component(struct snd_soc_component *component) -- GitLab From 8e082d8f42fabf9a4a0708d8012f4995765478fc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 8 Aug 2019 11:25:52 +0800 Subject: [PATCH 2296/7155] ASoC: tscs454: remove unused variable 'PLL_48K_RATE' The global variable 'PLL_48K_RATE' is never used so just remove it. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190808032552.45360-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/tscs454.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 93d84e5ae2d5..c3587af9985c 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -22,7 +22,6 @@ #include "tscs454.h" -static const unsigned int PLL_48K_RATE = (48000 * 256); static const unsigned int PLL_44_1K_RATE = (44100 * 256); #define COEFF_SIZE 3 -- GitLab From 0e4cc44f5066b22938f384cd57db99d66311de90 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 8 Aug 2019 14:27:34 -0500 Subject: [PATCH 2297/7155] ASoC: intel: skl_hda_dsp_common: create HDMI jack kctl This patch call snd_jack_add_new_kctl() to create the HDMI jack kctls. Userspace needs these kctls to detect the hdmi monitor hotplug. In /usr/share/alsa/ucm, the config file needs to assign a jack kctl to "JackControl" to let PA get the jack hotplug status. Signed-off-by: Libin Yang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190808192734.18286-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_common.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 55fd82e05e2c..58409b6e476e 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c @@ -147,6 +147,11 @@ int skl_hda_hdmi_jack_init(struct snd_soc_card *card) if (err) return err; + err = snd_jack_add_new_kctl(pcm->hdmi_jack.jack, + jack_name, SND_JACK_AVOUT); + if (err) + dev_warn(component->dev, "failed creating Jack kctl\n"); + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, &pcm->hdmi_jack); if (err < 0) -- GitLab From 63e45324c284d240562a5b435afc4b23ae7d923c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 8 Aug 2019 20:15:48 +0200 Subject: [PATCH 2298/7155] ASoC: Intel: Skylake: Limit large_config_get to single frame Reply for the very first LARGE_CONFIG_GET request contains total size of payload to be retrieved by host. From then on, each subsequent reply carries buffer offset instead. As looping is not covered by any real-life example, remove it and cleanup the function for followup overhaul. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190808181549.12521-2-cezary.rojewski@intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-ipc.c | 37 +++++---------------------- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index a2b69a02aab2..196c80dadb1f 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -973,8 +973,7 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, { struct skl_ipc_header header = {0}; struct sst_ipc_message request = {0}, reply = {0}; - int ret = 0; - size_t sz_remaining, rx_size, data_offset; + int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); @@ -987,34 +986,12 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, header.extension |= IPC_FINAL_BLOCK(1); header.extension |= IPC_INITIAL_BLOCK(1); - sz_remaining = msg->param_data_size; - data_offset = 0; - - while (sz_remaining != 0) { - rx_size = sz_remaining > SKL_ADSP_W1_SZ - ? SKL_ADSP_W1_SZ : sz_remaining; - if (rx_size == sz_remaining) - header.extension |= IPC_FINAL_BLOCK(1); - - request.header = *(u64 *)(&header); - reply.data = ((char *)param) + data_offset; - reply.size = msg->param_data_size; - ret = sst_ipc_tx_message_wait(ipc, request, &reply); - if (ret < 0) { - dev_err(ipc->dev, - "ipc: get large config fail, err: %d\n", ret); - return ret; - } - sz_remaining -= rx_size; - data_offset = msg->param_data_size - sz_remaining; - - /* clear the fields */ - header.extension &= IPC_INITIAL_BLOCK_CLEAR; - header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; - /* fill the fields */ - header.extension |= IPC_INITIAL_BLOCK(1); - header.extension |= IPC_DATA_OFFSET_SZ(data_offset); - } + request.header = *(u64 *)(&header); + reply.data = param; + reply.size = msg->param_data_size; + ret = sst_ipc_tx_message_wait(ipc, request, &reply); + if (ret < 0) + dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); return ret; } -- GitLab From 36004c42c761a6d95b867a4fbb9a955034e53351 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 8 Aug 2019 20:15:49 +0200 Subject: [PATCH 2299/7155] ASoC: Intel: Skylake: large_config_get overhaul LARGE_CONFIG_GET is mainly used to retrieve requested module parameters but it may also carry TX payload with them. Update its implementation to account for both TX and RX data. First reply.header carries total payload size within data_off_sizefield. Make use of reply.header to realloc returned buffer with correct size. Failure of IPC request is permissive - error-payload may be returned, an informative data why GET for given param failed - and thus function should not collapse before entire processing is finished. Caller is responsible for checking returned payload and bytes parameters. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20190808181549.12521-3-cezary.rojewski@intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 3 ++- sound/soc/intel/skylake/skl-sst-ipc.c | 25 ++++++++++++++++++++----- sound/soc/intel/skylake/skl-sst-ipc.h | 3 ++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index e8cc710f092b..84f0e6f58eb5 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -1379,11 +1379,12 @@ int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg) { struct skl_ipc_large_config_msg msg; + size_t bytes = size; msg.module_id = mcfg->id.module_id; msg.instance_id = mcfg->id.pvt_id; msg.param_data_size = size; msg.large_param_id = param_id; - return skl_ipc_get_large_config(&skl->ipc, &msg, params); + return skl_ipc_get_large_config(&skl->ipc, &msg, ¶ms, &bytes); } diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 196c80dadb1f..667cdddc289f 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -969,12 +969,18 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, u32 *param) + struct skl_ipc_large_config_msg *msg, + u32 **payload, size_t *bytes) { struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}, reply = {0}; + struct sst_ipc_message request, reply = {0}; + unsigned int *buf; int ret; + reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL); + if (!reply.data) + return -ENOMEM; + header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET); @@ -986,13 +992,22 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, header.extension |= IPC_FINAL_BLOCK(1); header.extension |= IPC_INITIAL_BLOCK(1); - request.header = *(u64 *)(&header); - reply.data = param; - reply.size = msg->param_data_size; + request.header = *(u64 *)&header; + request.data = *payload; + request.size = *bytes; + reply.size = SKL_ADSP_W1_SZ; + ret = sst_ipc_tx_message_wait(ipc, request, &reply); if (ret < 0) dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); + reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK; + buf = krealloc(reply.data, reply.size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + *payload = buf; + *bytes = reply.size; + return ret; } EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 93af08cf41d2..08ac31778325 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -139,7 +139,8 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param); int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, u32 *param); + struct skl_ipc_large_config_msg *msg, + u32 **payload, size_t *bytes); int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, u8 dma_id, u8 table_id, bool wait); -- GitLab From f6326fa4855b0f8173af822fcc139afdbf4d4b71 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 8 Aug 2019 23:15:54 +0100 Subject: [PATCH 2300/7155] ASoC: sof: Fix warning when IPC flood test is not enabled dentry is only used when the flood test is done so move the declaration of the variable inside the ifdef for the flood test. Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 40940b2fe9d5..54cd431faab7 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -221,7 +221,6 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, { struct snd_sof_dfsentry *dfse = file->private_data; struct snd_sof_dev *sdev = dfse->sdev; - struct dentry *dentry; loff_t pos = *ppos; size_t size_ret; int skip = 0; @@ -229,6 +228,8 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, u8 *buf; #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) + struct dentry *dentry; + dentry = file->f_path.dentry; if ((!strcmp(dentry->d_name.name, "ipc_flood_count") || !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) && -- GitLab From 31168a6d129aebc02f92d4b7cc9946c0b6364c2b Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Sat, 3 Aug 2019 00:47:59 +0800 Subject: [PATCH 2301/7155] dpaa_eth: Use refcount_t for refcount refcount_t is better for reference counters since its implementation can prevent overflows. So convert atomic_t ref counters to refcount_t. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 6 +++--- drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 9c4d1afa34e5..b4b82b9c5cd6 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -485,7 +485,7 @@ static struct dpaa_bp *dpaa_bpid2pool(int bpid) static bool dpaa_bpid2pool_use(int bpid) { if (dpaa_bpid2pool(bpid)) { - atomic_inc(&dpaa_bp_array[bpid]->refs); + refcount_inc(&dpaa_bp_array[bpid]->refs); return true; } @@ -496,7 +496,7 @@ static bool dpaa_bpid2pool_use(int bpid) static void dpaa_bpid2pool_map(int bpid, struct dpaa_bp *dpaa_bp) { dpaa_bp_array[bpid] = dpaa_bp; - atomic_set(&dpaa_bp->refs, 1); + refcount_set(&dpaa_bp->refs, 1); } static int dpaa_bp_alloc_pool(struct dpaa_bp *dpaa_bp) @@ -584,7 +584,7 @@ static void dpaa_bp_free(struct dpaa_bp *dpaa_bp) if (!bp) return; - if (!atomic_dec_and_test(&bp->refs)) + if (!refcount_dec_and_test(&bp->refs)) return; if (bp->free_buf_cb) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index af320f83c742..f7e59e8db075 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -32,6 +32,7 @@ #define __DPAA_H #include +#include #include #include @@ -99,7 +100,7 @@ struct dpaa_bp { int (*seed_cb)(struct dpaa_bp *); /* bpool can be emptied before freeing by this cb */ void (*free_buf_cb)(const struct dpaa_bp *, struct bm_buffer *); - atomic_t refs; + refcount_t refs; }; struct dpaa_rx_errors { -- GitLab From 4b4de39850474350bfc2f3df33ee1c23d0475c59 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Sat, 3 Aug 2019 00:48:21 +0800 Subject: [PATCH 2302/7155] mkiss: Use refcount_t for refcount refcount_t is better for reference counters since its implementation can prevent overflows. So convert atomic_t ref counters to refcount_t. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/hamradio/mkiss.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 442018ccd65e..c5bfa19ddb93 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -70,7 +71,7 @@ struct mkiss { #define CRC_MODE_FLEX_TEST 3 #define CRC_MODE_SMACK_TEST 4 - atomic_t refcnt; + refcount_t refcnt; struct completion dead; }; @@ -668,7 +669,7 @@ static struct mkiss *mkiss_get(struct tty_struct *tty) read_lock(&disc_data_lock); ax = tty->disc_data; if (ax) - atomic_inc(&ax->refcnt); + refcount_inc(&ax->refcnt); read_unlock(&disc_data_lock); return ax; @@ -676,7 +677,7 @@ static struct mkiss *mkiss_get(struct tty_struct *tty) static void mkiss_put(struct mkiss *ax) { - if (atomic_dec_and_test(&ax->refcnt)) + if (refcount_dec_and_test(&ax->refcnt)) complete(&ax->dead); } @@ -704,7 +705,7 @@ static int mkiss_open(struct tty_struct *tty) ax->dev = dev; spin_lock_init(&ax->buflock); - atomic_set(&ax->refcnt, 1); + refcount_set(&ax->refcnt, 1); init_completion(&ax->dead); ax->tty = tty; @@ -784,7 +785,7 @@ static void mkiss_close(struct tty_struct *tty) * We have now ensured that nobody can start using ap from now on, but * we have to wait for all existing users to finish. */ - if (!atomic_dec_and_test(&ax->refcnt)) + if (!refcount_dec_and_test(&ax->refcnt)) wait_for_completion(&ax->dead); /* * Halt the transmit queue so that a new transmit cannot scribble -- GitLab From 9d2f11238398793be11830a6f41908652b661395 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 5 Aug 2019 23:34:41 +0300 Subject: [PATCH 2303/7155] net: delete "register" keyword Delete long obsoleted "register" keyword. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/ethernet/apple/bmac.c | 4 ++-- drivers/net/slip/slhc.c | 30 +++++++++++++++--------------- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++-- net/netfilter/ipvs/ip_vs_lblcr.c | 4 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index c40daad515d5..a58185b1d8bf 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -815,8 +815,8 @@ static int reverse6[64] = { static unsigned int crc416(unsigned int curval, unsigned short nxtval) { - register unsigned int counter, cur = curval, next = nxtval; - register int high_crc_set, low_data_set; + unsigned int counter, cur = curval, next = nxtval; + int high_crc_set, low_data_set; /* Swap bytes */ next = ((next & 0x00FF) << 8) | (next >> 8); diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index ea90db3c7705..58a69f830d29 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -91,8 +91,8 @@ static unsigned short pull16(unsigned char **cpp); struct slcompress * slhc_init(int rslots, int tslots) { - register short i; - register struct cstate *ts; + short i; + struct cstate *ts; struct slcompress *comp; if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255) @@ -206,7 +206,7 @@ pull16(unsigned char **cpp) static long decode(unsigned char **cpp) { - register int x; + int x; x = *(*cpp)++; if(x == 0){ @@ -227,14 +227,14 @@ int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, unsigned char *ocp, unsigned char **cpp, int compress_cid) { - register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]); - register struct cstate *lcs = ocs; - register struct cstate *cs = lcs->next; - register unsigned long deltaS, deltaA; - register short changes = 0; + struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]); + struct cstate *lcs = ocs; + struct cstate *cs = lcs->next; + unsigned long deltaS, deltaA; + short changes = 0; int hlen; unsigned char new_seq[16]; - register unsigned char *cp = new_seq; + unsigned char *cp = new_seq; struct iphdr *ip; struct tcphdr *th, *oth; __sum16 csum; @@ -486,11 +486,11 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, int slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) { - register int changes; + int changes; long x; - register struct tcphdr *thp; - register struct iphdr *ip; - register struct cstate *cs; + struct tcphdr *thp; + struct iphdr *ip; + struct cstate *cs; int len, hdrlen; unsigned char *cp = icp; @@ -543,7 +543,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) switch(changes & SPECIALS_MASK){ case SPECIAL_I: /* Echoed terminal traffic */ { - register short i; + short i; i = ntohs(ip->tot_len) - hdrlen; thp->ack_seq = htonl( ntohl(thp->ack_seq) + i); thp->seq = htonl( ntohl(thp->seq) + i); @@ -637,7 +637,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) { - register struct cstate *cs; + struct cstate *cs; unsigned ihl; unsigned char index; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 060565e7d227..145c8c992927 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -262,7 +262,7 @@ static inline unsigned int ip_vs_svc_hashkey(struct netns_ipvs *ipvs, int af, unsigned int proto, const union nf_inet_addr *addr, __be16 port) { - register unsigned int porth = ntohs(port); + unsigned int porth = ntohs(port); __be32 addr_fold = addr->ip; __u32 ahash; @@ -493,7 +493,7 @@ static inline unsigned int ip_vs_rs_hashkey(int af, const union nf_inet_addr *addr, __be16 port) { - register unsigned int porth = ntohs(port); + unsigned int porth = ntohs(port); __be32 addr_fold = addr->ip; #ifdef CONFIG_IP_VS_IPV6 diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index c8b5a504476c..77c323c36a88 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -160,7 +160,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) /* get weighted least-connection node in the destination set */ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) { - register struct ip_vs_dest_set_elem *e; + struct ip_vs_dest_set_elem *e; struct ip_vs_dest *dest, *least; int loh, doh; @@ -209,7 +209,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) /* get weighted most-connection node in the destination set */ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) { - register struct ip_vs_dest_set_elem *e; + struct ip_vs_dest_set_elem *e; struct ip_vs_dest *dest, *most; int moh, doh; -- GitLab From e858ef1cd4bc1bdfcd18114a8195236e336cee42 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 5 Aug 2019 15:41:37 -0700 Subject: [PATCH 2304/7155] selftests: Add l2tp tests Add IPv4 and IPv6 l2tp tests. Current set is over IP and with IPsec. v2 - add l2tp.sh to TEST_PROGS in Makefile Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/l2tp.sh | 382 +++++++++++++++++++++++++++ 2 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/net/l2tp.sh diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 70f2d6656170..0bd6b23c97ef 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -10,7 +10,7 @@ TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_any.sh TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh -TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh +TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh l2tp.sh TEST_PROGS_EXTENDED := in_netns.sh TEST_GEN_FILES = socket nettest TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any diff --git a/tools/testing/selftests/net/l2tp.sh b/tools/testing/selftests/net/l2tp.sh new file mode 100644 index 000000000000..5782433886fc --- /dev/null +++ b/tools/testing/selftests/net/l2tp.sh @@ -0,0 +1,382 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# L2TPv3 tunnel between 2 hosts +# +# host-1 | router | host-2 +# | | +# lo l2tp | | l2tp lo +# 172.16.101.1 172.16.1.1 | | 172.16.1.2 172.16.101.2 +# fc00:101::1 fc00:1::1 | | fc00:1::2 fc00:101::2 +# | | +# eth0 | | eth0 +# 10.1.1.1 | | 10.1.2.1 +# 2001:db8:1::1 | | 2001:db8:2::1 + +VERBOSE=0 +PAUSE_ON_FAIL=no + +which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping) + +################################################################################ +# +log_test() +{ + local rc=$1 + local expected=$2 + local msg="$3" + + if [ ${rc} -eq ${expected} ]; then + printf "TEST: %-60s [ OK ]\n" "${msg}" + nsuccess=$((nsuccess+1)) + else + ret=1 + nfail=$((nfail+1)) + printf "TEST: %-60s [FAIL]\n" "${msg}" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then + echo + echo "hit enter to continue, 'q' to quit" + read a + [ "$a" = "q" ] && exit 1 + fi + fi +} + +run_cmd() +{ + local ns + local cmd + local out + local rc + + ns="$1" + shift + cmd="$*" + + if [ "$VERBOSE" = "1" ]; then + printf " COMMAND: $cmd\n" + fi + + out=$(eval ip netns exec ${ns} ${cmd} 2>&1) + rc=$? + if [ "$VERBOSE" = "1" -a -n "$out" ]; then + echo " $out" + fi + + [ "$VERBOSE" = "1" ] && echo + + return $rc +} + +################################################################################ +# create namespaces and interconnects + +create_ns() +{ + local ns=$1 + local addr=$2 + local addr6=$3 + + [ -z "${addr}" ] && addr="-" + [ -z "${addr6}" ] && addr6="-" + + ip netns add ${ns} + + ip -netns ${ns} link set lo up + if [ "${addr}" != "-" ]; then + ip -netns ${ns} addr add dev lo ${addr} + fi + if [ "${addr6}" != "-" ]; then + ip -netns ${ns} -6 addr add dev lo ${addr6} + fi + + ip -netns ${ns} ro add unreachable default metric 8192 + ip -netns ${ns} -6 ro add unreachable default metric 8192 + + ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1 + ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0 +} + +# create veth pair to connect namespaces and apply addresses. +connect_ns() +{ + local ns1=$1 + local ns1_dev=$2 + local ns1_addr=$3 + local ns1_addr6=$4 + local ns2=$5 + local ns2_dev=$6 + local ns2_addr=$7 + local ns2_addr6=$8 + + ip -netns ${ns1} li add ${ns1_dev} type veth peer name tmp + ip -netns ${ns1} li set ${ns1_dev} up + ip -netns ${ns1} li set tmp netns ${ns2} name ${ns2_dev} + ip -netns ${ns2} li set ${ns2_dev} up + + if [ "${ns1_addr}" != "-" ]; then + ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr} + ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr} + fi + + if [ "${ns1_addr6}" != "-" ]; then + ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr6} + ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr6} + fi +} + +################################################################################ +# test setup + +cleanup() +{ + local ns + + for ns in host-1 host-2 router + do + ip netns del ${ns} 2>/dev/null + done +} + +setup_l2tp_ipv4() +{ + # + # configure l2tpv3 tunnel on host-1 + # + ip -netns host-1 l2tp add tunnel tunnel_id 1041 peer_tunnel_id 1042 \ + encap ip local 10.1.1.1 remote 10.1.2.1 + ip -netns host-1 l2tp add session name l2tp4 tunnel_id 1041 \ + session_id 1041 peer_session_id 1042 + ip -netns host-1 link set dev l2tp4 up + ip -netns host-1 addr add dev l2tp4 172.16.1.1 peer 172.16.1.2 + + # + # configure l2tpv3 tunnel on host-2 + # + ip -netns host-2 l2tp add tunnel tunnel_id 1042 peer_tunnel_id 1041 \ + encap ip local 10.1.2.1 remote 10.1.1.1 + ip -netns host-2 l2tp add session name l2tp4 tunnel_id 1042 \ + session_id 1042 peer_session_id 1041 + ip -netns host-2 link set dev l2tp4 up + ip -netns host-2 addr add dev l2tp4 172.16.1.2 peer 172.16.1.1 + + # + # add routes to loopback addresses + # + ip -netns host-1 ro add 172.16.101.2/32 via 172.16.1.2 + ip -netns host-2 ro add 172.16.101.1/32 via 172.16.1.1 +} + +setup_l2tp_ipv6() +{ + # + # configure l2tpv3 tunnel on host-1 + # + ip -netns host-1 l2tp add tunnel tunnel_id 1061 peer_tunnel_id 1062 \ + encap ip local 2001:db8:1::1 remote 2001:db8:2::1 + ip -netns host-1 l2tp add session name l2tp6 tunnel_id 1061 \ + session_id 1061 peer_session_id 1062 + ip -netns host-1 link set dev l2tp6 up + ip -netns host-1 addr add dev l2tp6 fc00:1::1 peer fc00:1::2 + + # + # configure l2tpv3 tunnel on host-2 + # + ip -netns host-2 l2tp add tunnel tunnel_id 1062 peer_tunnel_id 1061 \ + encap ip local 2001:db8:2::1 remote 2001:db8:1::1 + ip -netns host-2 l2tp add session name l2tp6 tunnel_id 1062 \ + session_id 1062 peer_session_id 1061 + ip -netns host-2 link set dev l2tp6 up + ip -netns host-2 addr add dev l2tp6 fc00:1::2 peer fc00:1::1 + + # + # add routes to loopback addresses + # + ip -netns host-1 -6 ro add fc00:101::2/128 via fc00:1::2 + ip -netns host-2 -6 ro add fc00:101::1/128 via fc00:1::1 +} + +setup() +{ + # start clean + cleanup + + set -e + create_ns host-1 172.16.101.1/32 fc00:101::1/128 + create_ns host-2 172.16.101.2/32 fc00:101::2/128 + create_ns router + + connect_ns host-1 eth0 10.1.1.1/24 2001:db8:1::1/64 \ + router eth1 10.1.1.2/24 2001:db8:1::2/64 + + connect_ns host-2 eth0 10.1.2.1/24 2001:db8:2::1/64 \ + router eth2 10.1.2.2/24 2001:db8:2::2/64 + + ip -netns host-1 ro add 10.1.2.0/24 via 10.1.1.2 + ip -netns host-1 -6 ro add 2001:db8:2::/64 via 2001:db8:1::2 + + ip -netns host-2 ro add 10.1.1.0/24 via 10.1.2.2 + ip -netns host-2 -6 ro add 2001:db8:1::/64 via 2001:db8:2::2 + + setup_l2tp_ipv4 + setup_l2tp_ipv6 + set +e +} + +setup_ipsec() +{ + # + # IPv4 + # + run_cmd host-1 ip xfrm policy add \ + src 10.1.1.1 dst 10.1.2.1 dir out \ + tmpl proto esp mode transport + + run_cmd host-1 ip xfrm policy add \ + src 10.1.2.1 dst 10.1.1.1 dir in \ + tmpl proto esp mode transport + + run_cmd host-2 ip xfrm policy add \ + src 10.1.1.1 dst 10.1.2.1 dir in \ + tmpl proto esp mode transport + + run_cmd host-2 ip xfrm policy add \ + src 10.1.2.1 dst 10.1.1.1 dir out \ + tmpl proto esp mode transport + + ip -netns host-1 xfrm state add \ + src 10.1.1.1 dst 10.1.2.1 \ + spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-1 xfrm state add \ + src 10.1.2.1 dst 10.1.1.1 \ + spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-2 xfrm state add \ + src 10.1.1.1 dst 10.1.2.1 \ + spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-2 xfrm state add \ + src 10.1.2.1 dst 10.1.1.1 \ + spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + # + # IPV6 + # + run_cmd host-1 ip -6 xfrm policy add \ + src 2001:db8:1::1 dst 2001:db8:2::1 dir out \ + tmpl proto esp mode transport + + run_cmd host-1 ip -6 xfrm policy add \ + src 2001:db8:2::1 dst 2001:db8:1::1 dir in \ + tmpl proto esp mode transport + + run_cmd host-2 ip -6 xfrm policy add \ + src 2001:db8:1::1 dst 2001:db8:2::1 dir in \ + tmpl proto esp mode transport + + run_cmd host-2 ip -6 xfrm policy add \ + src 2001:db8:2::1 dst 2001:db8:1::1 dir out \ + tmpl proto esp mode transport + + ip -netns host-1 -6 xfrm state add \ + src 2001:db8:1::1 dst 2001:db8:2::1 \ + spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-1 -6 xfrm state add \ + src 2001:db8:2::1 dst 2001:db8:1::1 \ + spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-2 -6 xfrm state add \ + src 2001:db8:1::1 dst 2001:db8:2::1 \ + spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport + + ip -netns host-2 -6 xfrm state add \ + src 2001:db8:2::1 dst 2001:db8:1::1 \ + spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \ + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport +} + +teardown_ipsec() +{ + run_cmd host-1 ip xfrm state flush + run_cmd host-1 ip xfrm policy flush + run_cmd host-2 ip xfrm state flush + run_cmd host-2 ip xfrm policy flush +} + +################################################################################ +# generate traffic through tunnel for various cases + +run_ping() +{ + local desc="$1" + + run_cmd host-1 ping -c1 -w1 172.16.1.2 + log_test $? 0 "IPv4 basic L2TP tunnel ${desc}" + + run_cmd host-1 ping -c1 -w1 -I 172.16.101.1 172.16.101.2 + log_test $? 0 "IPv4 route through L2TP tunnel ${desc}" + + run_cmd host-1 ${ping6} -c1 -w1 fc00:1::2 + log_test $? 0 "IPv6 basic L2TP tunnel ${desc}" + + run_cmd host-1 ${ping6} -c1 -w1 -I fc00:101::1 fc00:101::2 + log_test $? 0 "IPv6 route through L2TP tunnel ${desc}" +} + +run_tests() +{ + local desc + + setup + run_ping + + setup_ipsec + run_ping "- with IPsec" + run_cmd host-1 ping -c1 -w1 172.16.1.2 + log_test $? 0 "IPv4 basic L2TP tunnel ${desc}" + + run_cmd host-1 ping -c1 -w1 -I 172.16.101.1 172.16.101.2 + log_test $? 0 "IPv4 route through L2TP tunnel ${desc}" + + run_cmd host-1 ${ping6} -c1 -w1 fc00:1::2 + log_test $? 0 "IPv6 basic L2TP tunnel - with IPsec" + + run_cmd host-1 ${ping6} -c1 -w1 -I fc00:101::1 fc00:101::2 + log_test $? 0 "IPv6 route through L2TP tunnel - with IPsec" + + teardown_ipsec + run_ping "- after IPsec teardown" +} + +################################################################################ +# main + +declare -i nfail=0 +declare -i nsuccess=0 + +while getopts :pv o +do + case $o in + p) PAUSE_ON_FAIL=yes;; + v) VERBOSE=$(($VERBOSE + 1));; + *) exit 1;; + esac +done + +run_tests +cleanup + +printf "\nTests passed: %3d\n" ${nsuccess} +printf "Tests failed: %3d\n" ${nfail} -- GitLab From 4a8937b83892cb69524291cae6cdabad4a8be033 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 6 Aug 2019 10:58:46 +0800 Subject: [PATCH 2305/7155] cxgb4: smt: Add lock for atomic_dec_and_test The atomic_dec_and_test() is not safe because it is outside of locks. Move the locks of t4_smte_free() to its caller, cxgb4_smt_release() to protect the atomic decrement. Fixes: 3bdb376e6944 ("cxgb4: introduce SMT ops to prepare for SMAC rewrite support") Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/smt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/smt.c b/drivers/net/ethernet/chelsio/cxgb4/smt.c index eaf1fb74689c..d6e84c8b5554 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/smt.c +++ b/drivers/net/ethernet/chelsio/cxgb4/smt.c @@ -97,11 +97,9 @@ static struct smt_entry *find_or_alloc_smte(struct smt_data *s, u8 *smac) static void t4_smte_free(struct smt_entry *e) { - spin_lock_bh(&e->lock); if (atomic_read(&e->refcnt) == 0) { /* hasn't been recycled */ e->state = SMT_STATE_UNUSED; } - spin_unlock_bh(&e->lock); } /** @@ -111,8 +109,10 @@ static void t4_smte_free(struct smt_entry *e) */ void cxgb4_smt_release(struct smt_entry *e) { + spin_lock_bh(&e->lock); if (atomic_dec_and_test(&e->refcnt)) t4_smte_free(e); + spin_unlock_bh(&e->lock); } EXPORT_SYMBOL(cxgb4_smt_release); -- GitLab From ad2dcba008a4a24a39ba39300a460bec2f73fd04 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 6 Aug 2019 10:58:54 +0800 Subject: [PATCH 2306/7155] cxgb4: smt: Use normal int for refcount All refcount operations are protected by spinlocks now. Then the atomic counter can be replaced by a normal int. This patch depends on PATCH 1/2. Signed-off-by: Chuhong Yuan Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/smt.c | 14 +++++++------- drivers/net/ethernet/chelsio/cxgb4/smt.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/smt.c b/drivers/net/ethernet/chelsio/cxgb4/smt.c index d6e84c8b5554..01c65d13fc0e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/smt.c +++ b/drivers/net/ethernet/chelsio/cxgb4/smt.c @@ -57,7 +57,7 @@ struct smt_data *t4_init_smt(void) s->smtab[i].state = SMT_STATE_UNUSED; memset(&s->smtab[i].src_mac, 0, ETH_ALEN); spin_lock_init(&s->smtab[i].lock); - atomic_set(&s->smtab[i].refcnt, 0); + s->smtab[i].refcnt = 0; } return s; } @@ -68,7 +68,7 @@ static struct smt_entry *find_or_alloc_smte(struct smt_data *s, u8 *smac) struct smt_entry *e, *end; for (e = &s->smtab[0], end = &s->smtab[s->smt_size]; e != end; ++e) { - if (atomic_read(&e->refcnt) == 0) { + if (e->refcnt == 0) { if (!first_free) first_free = e; } else { @@ -97,7 +97,7 @@ static struct smt_entry *find_or_alloc_smte(struct smt_data *s, u8 *smac) static void t4_smte_free(struct smt_entry *e) { - if (atomic_read(&e->refcnt) == 0) { /* hasn't been recycled */ + if (e->refcnt == 0) { /* hasn't been recycled */ e->state = SMT_STATE_UNUSED; } } @@ -110,7 +110,7 @@ static void t4_smte_free(struct smt_entry *e) void cxgb4_smt_release(struct smt_entry *e) { spin_lock_bh(&e->lock); - if (atomic_dec_and_test(&e->refcnt)) + if ((--e->refcnt) == 0) t4_smte_free(e); spin_unlock_bh(&e->lock); } @@ -215,14 +215,14 @@ static struct smt_entry *t4_smt_alloc_switching(struct adapter *adap, u16 pfvf, e = find_or_alloc_smte(s, smac); if (e) { spin_lock(&e->lock); - if (!atomic_read(&e->refcnt)) { - atomic_set(&e->refcnt, 1); + if (!e->refcnt) { + e->refcnt = 1; e->state = SMT_STATE_SWITCHING; e->pfvf = pfvf; memcpy(e->src_mac, smac, ETH_ALEN); write_smt_entry(adap, e); } else { - atomic_inc(&e->refcnt); + ++e->refcnt; } spin_unlock(&e->lock); } diff --git a/drivers/net/ethernet/chelsio/cxgb4/smt.h b/drivers/net/ethernet/chelsio/cxgb4/smt.h index d6c2cc271398..1268d6e93a47 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/smt.h +++ b/drivers/net/ethernet/chelsio/cxgb4/smt.h @@ -59,7 +59,7 @@ struct smt_entry { u16 idx; u16 pfvf; u8 src_mac[ETH_ALEN]; - atomic_t refcnt; + int refcnt; spinlock_t lock; /* protect smt entry add,removal */ }; -- GitLab From 5e6d9fc76190aa70db9cbfb18a6f44f4ee83b7f5 Mon Sep 17 00:00:00 2001 From: Rahul Verma Date: Mon, 5 Aug 2019 23:59:50 -0700 Subject: [PATCH 2307/7155] qed: Add new ethtool supported port types based on media. Supported ports in ethtool are displayed based on media type. For media type fibre and twinaxial, port type is "FIBRE". Media type Base-T is "TP" and media KR is "Backplane". V1->V2: Corrected the subject. Signed-off-by: Rahul Verma Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 6 +++++- drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 3 ++- include/linux/qed/qed_if.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 829dd60ab937..e5ac8bd4fd14 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1688,6 +1688,7 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn, switch (media_type) { case MEDIA_DA_TWINAX: + *if_capability |= QED_LM_FIBRE_BIT; if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) *if_capability |= QED_LM_20000baseKR2_Full_BIT; /* For DAC media multiple speed capabilities are supported*/ @@ -1707,6 +1708,7 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn, *if_capability |= QED_LM_100000baseCR4_Full_BIT; break; case MEDIA_BASE_T: + *if_capability |= QED_LM_TP_BIT; if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) { if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) { @@ -1718,6 +1720,7 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn, } } if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) { + *if_capability |= QED_LM_FIBRE_BIT; if (tcvr_type == ETH_TRANSCEIVER_TYPE_1000BASET) *if_capability |= QED_LM_1000baseT_Full_BIT; if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_BASET) @@ -1728,6 +1731,7 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn, case MEDIA_SFPP_10G_FIBER: case MEDIA_XFP_FIBER: case MEDIA_MODULE_FIBER: + *if_capability |= QED_LM_FIBRE_BIT; if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) { if ((tcvr_type == ETH_TRANSCEIVER_TYPE_1G_LX) || @@ -1770,6 +1774,7 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn, break; case MEDIA_KR: + *if_capability |= QED_LM_Backplane_BIT; if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G) *if_capability |= QED_LM_20000baseKR2_Full_BIT; if (capability & @@ -1821,7 +1826,6 @@ static void qed_fill_link(struct qed_hwfn *hwfn, if_link->link_up = true; /* TODO - at the moment assume supported and advertised speed equal */ - if_link->supported_caps = QED_LM_FIBRE_BIT; if (link_caps.default_speed_autoneg) if_link->supported_caps |= QED_LM_Autoneg_BIT; if (params.pause.autoneg || diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index e85f9fef930c..abcee474909a 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -424,12 +424,13 @@ struct qede_link_mode_mapping { }; static const struct qede_link_mode_mapping qed_lm_map[] = { + {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, {QED_LM_10000baseT_Full_BIT, ETHTOOL_LINK_MODE_10000baseT_Full_BIT}, - {QED_LM_2500baseX_Full_BIT, ETHTOOL_LINK_MODE_2500baseX_Full_BIT}, + {QED_LM_TP_BIT, ETHTOOL_LINK_MODE_TP_BIT}, {QED_LM_Backplane_BIT, ETHTOOL_LINK_MODE_Backplane_BIT}, {QED_LM_1000baseKX_Full_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT}, {QED_LM_10000baseKX4_Full_BIT, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT}, diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index eef02e64b422..23021366a4e5 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -689,7 +689,7 @@ enum qed_link_mode_bits { QED_LM_40000baseLR4_Full_BIT = BIT(9), QED_LM_50000baseKR2_Full_BIT = BIT(10), QED_LM_100000baseKR4_Full_BIT = BIT(11), - QED_LM_2500baseX_Full_BIT = BIT(12), + QED_LM_TP_BIT = BIT(12), QED_LM_Backplane_BIT = BIT(13), QED_LM_1000baseKX_Full_BIT = BIT(14), QED_LM_10000baseKX4_Full_BIT = BIT(15), -- GitLab From 5e040d4b1a440b832c7b4cf8116eebcdff91909c Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Tue, 6 Aug 2019 14:53:20 +0100 Subject: [PATCH 2308/7155] sfc: don't score irq moderation points for GRO We already scored points when handling the RX event, no-one else does this, and looking at the history it appears this was originally meant to only score on merges, not on GRO_NORMAL. Moreover, it gets in the way of changing GRO to not immediately pass GRO_NORMAL skbs to the stack. Performance testing with four TCP streams received on a single CPU (where throughput was line rate of 9.4Gbps in all tests) showed a 13.7% reduction in RX CPU usage (n=6, p=0.03). Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/rx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index d5db045535d3..85ec07f5a674 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -412,7 +412,6 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, unsigned int n_frags, u8 *eh) { struct napi_struct *napi = &channel->napi_str; - gro_result_t gro_result; struct efx_nic *efx = channel->efx; struct sk_buff *skb; @@ -449,9 +448,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, skb_record_rx_queue(skb, channel->rx_queue.core_index); - gro_result = napi_gro_frags(napi); - if (gro_result != GRO_DROP) - channel->irq_mod_score += 2; + napi_gro_frags(napi); } /* Allocate and construct an SKB around page fragments */ -- GitLab From 67270136949e1d55e1a614b0a2e053b7762384ef Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Tue, 6 Aug 2019 14:53:31 +0100 Subject: [PATCH 2309/7155] sfc: falcon: don't score irq moderation points for GRO Same rationale as for sfc, except that this wasn't performance-tested. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/falcon/rx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c index fd850d3d8ec0..05ea3523890a 100644 --- a/drivers/net/ethernet/sfc/falcon/rx.c +++ b/drivers/net/ethernet/sfc/falcon/rx.c @@ -424,7 +424,6 @@ ef4_rx_packet_gro(struct ef4_channel *channel, struct ef4_rx_buffer *rx_buf, unsigned int n_frags, u8 *eh) { struct napi_struct *napi = &channel->napi_str; - gro_result_t gro_result; struct ef4_nic *efx = channel->efx; struct sk_buff *skb; @@ -460,9 +459,7 @@ ef4_rx_packet_gro(struct ef4_channel *channel, struct ef4_rx_buffer *rx_buf, skb_record_rx_queue(skb, channel->rx_queue.core_index); - gro_result = napi_gro_frags(napi); - if (gro_result != GRO_DROP) - channel->irq_mod_score += 2; + napi_gro_frags(napi); } /* Allocate and construct an SKB around page fragments */ -- GitLab From 323ebb61e32b478e2432c5a3cbf9e2ca678a9609 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Tue, 6 Aug 2019 14:53:55 +0100 Subject: [PATCH 2310/7155] net: use listified RX for handling GRO_NORMAL skbs When GRO decides not to coalesce a packet, in napi_frags_finish(), instead of passing it to the stack immediately, place it on a list in the napi struct. Then, at flush time (napi_complete_done(), napi_poll(), or napi_busy_loop()), call netif_receive_skb_list_internal() on the list. We'd like to do that in napi_gro_flush(), but it's not called if !napi->gro_bitmask, so we have to do it in the callers instead. (There are a handful of drivers that call napi_gro_flush() themselves, but it's not clear why, or whether this will affect them.) Because a full 64 packets is an inefficiently large batch, also consume the list whenever it exceeds gro_normal_batch, a new net/core sysctl that defaults to 8. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 +++ net/core/dev.c | 44 +++++++++++++++++++++++++++++++++++--- net/core/sysctl_net_core.c | 8 +++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 88292953aa6f..55ac223553f8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -332,6 +332,8 @@ struct napi_struct { struct net_device *dev; struct gro_list gro_hash[GRO_HASH_BUCKETS]; struct sk_buff *skb; + struct list_head rx_list; /* Pending GRO_NORMAL skbs */ + int rx_count; /* length of rx_list */ struct hrtimer timer; struct list_head dev_list; struct hlist_node napi_hash_node; @@ -4239,6 +4241,7 @@ extern int dev_weight_rx_bias; extern int dev_weight_tx_bias; extern int dev_rx_weight; extern int dev_tx_weight; +extern int gro_normal_batch; bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev); struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, diff --git a/net/core/dev.c b/net/core/dev.c index af071b0ce88e..49589ed2018d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3963,6 +3963,8 @@ int dev_weight_rx_bias __read_mostly = 1; /* bias for backlog weight */ int dev_weight_tx_bias __read_mostly = 1; /* bias for output_queue quota */ int dev_rx_weight __read_mostly = 64; int dev_tx_weight __read_mostly = 64; +/* Maximum number of GRO_NORMAL skbs to batch up for list-RX */ +int gro_normal_batch __read_mostly = 8; /* Called with irq disabled */ static inline void ____napi_schedule(struct softnet_data *sd, @@ -5747,6 +5749,26 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi) } EXPORT_SYMBOL(napi_get_frags); +/* Pass the currently batched GRO_NORMAL SKBs up to the stack. */ +static void gro_normal_list(struct napi_struct *napi) +{ + if (!napi->rx_count) + return; + netif_receive_skb_list_internal(&napi->rx_list); + INIT_LIST_HEAD(&napi->rx_list); + napi->rx_count = 0; +} + +/* Queue one GRO_NORMAL SKB up for list processing. If batch size exceeded, + * pass the whole batch up to the stack. + */ +static void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb) +{ + list_add_tail(&skb->list, &napi->rx_list); + if (++napi->rx_count >= gro_normal_batch) + gro_normal_list(napi); +} + static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, gro_result_t ret) @@ -5756,8 +5778,8 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, case GRO_HELD: __skb_push(skb, ETH_HLEN); skb->protocol = eth_type_trans(skb, skb->dev); - if (ret == GRO_NORMAL && netif_receive_skb_internal(skb)) - ret = GRO_DROP; + if (ret == GRO_NORMAL) + gro_normal_one(napi, skb); break; case GRO_DROP: @@ -6034,6 +6056,8 @@ bool napi_complete_done(struct napi_struct *n, int work_done) NAPIF_STATE_IN_BUSY_POLL))) return false; + gro_normal_list(n); + if (n->gro_bitmask) { unsigned long timeout = 0; @@ -6119,10 +6143,19 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock) * Ideally, a new ndo_busy_poll_stop() could avoid another round. */ rc = napi->poll(napi, BUSY_POLL_BUDGET); + /* We can't gro_normal_list() here, because napi->poll() might have + * rearmed the napi (napi_complete_done()) in which case it could + * already be running on another CPU. + */ trace_napi_poll(napi, rc, BUSY_POLL_BUDGET); netpoll_poll_unlock(have_poll_lock); - if (rc == BUSY_POLL_BUDGET) + if (rc == BUSY_POLL_BUDGET) { + /* As the whole budget was spent, we still own the napi so can + * safely handle the rx_list. + */ + gro_normal_list(napi); __napi_schedule(napi); + } local_bh_enable(); } @@ -6167,6 +6200,7 @@ void napi_busy_loop(unsigned int napi_id, } work = napi_poll(napi, BUSY_POLL_BUDGET); trace_napi_poll(napi, work, BUSY_POLL_BUDGET); + gro_normal_list(napi); count: if (work > 0) __NET_ADD_STATS(dev_net(napi->dev), @@ -6272,6 +6306,8 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, napi->timer.function = napi_watchdog; init_gro_hash(napi); napi->skb = NULL; + INIT_LIST_HEAD(&napi->rx_list); + napi->rx_count = 0; napi->poll = poll; if (weight > NAPI_POLL_WEIGHT) netdev_err_once(dev, "%s() called with weight %d\n", __func__, @@ -6368,6 +6404,8 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll) goto out_unlock; } + gro_normal_list(n); + if (n->gro_bitmask) { /* flush too old packets * If HZ < 1000, flush all packets. diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 8da5b3a54dac..eb29e5adc84d 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -567,6 +567,14 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_do_static_key, }, + { + .procname = "gro_normal_batch", + .data = &gro_normal_batch, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ONE, + }, { } }; -- GitLab From 242453c227d14751fed0a8809a58f1bf3c7d837a Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:49 +0800 Subject: [PATCH 2311/7155] cls_api: modify the tc_indr_block_ing_cmd parameters. This patch make tc_indr_block_ing_cmd can't access struct tc_indr_block_dev and tc_indr_block_cb. Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- net/sched/cls_api.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 9d85d3295c7c..1dd210d353b7 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -677,26 +677,28 @@ static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb) static int tcf_block_setup(struct tcf_block *block, struct flow_block_offload *bo); -static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev, - struct tc_indr_block_cb *indr_block_cb, +static void tc_indr_block_ing_cmd(struct net_device *dev, + struct tcf_block *block, + tc_indr_block_bind_cb_t *cb, + void *cb_priv, enum flow_block_command command) { struct flow_block_offload bo = { .command = command, .binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS, - .net = dev_net(indr_dev->dev), - .block_shared = tcf_block_non_null_shared(indr_dev->block), + .net = dev_net(dev), + .block_shared = tcf_block_non_null_shared(block), }; INIT_LIST_HEAD(&bo.cb_list); - if (!indr_dev->block) + if (!block) return; - bo.block = &indr_dev->block->flow_block; + bo.block = &block->flow_block; - indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, - &bo); - tcf_block_setup(indr_dev->block, &bo); + cb(dev, cb_priv, TC_SETUP_BLOCK, &bo); + + tcf_block_setup(block, &bo); } int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, @@ -715,7 +717,8 @@ int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, if (err) goto err_dev_put; - tc_indr_block_ing_cmd(indr_dev, indr_block_cb, FLOW_BLOCK_BIND); + tc_indr_block_ing_cmd(dev, indr_dev->block, cb, cb_priv, + FLOW_BLOCK_BIND); return 0; err_dev_put: @@ -752,7 +755,8 @@ void __tc_indr_block_cb_unregister(struct net_device *dev, return; /* Send unbind message if required to free any block cbs. */ - tc_indr_block_ing_cmd(indr_dev, indr_block_cb, FLOW_BLOCK_UNBIND); + tc_indr_block_ing_cmd(dev, indr_dev->block, cb, indr_block_cb->cb_priv, + FLOW_BLOCK_UNBIND); tc_indr_block_cb_del(indr_block_cb); tc_indr_block_dev_put(indr_dev); } -- GitLab From f8436988574e50fe69f6f193ee76c3185b17a5c7 Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:50 +0800 Subject: [PATCH 2312/7155] cls_api: remove the tcf_block cache Remove the tcf_block in the tc_indr_block_dev for muti-subsystem support. Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- net/sched/cls_api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 1dd210d353b7..12eaa6c90e79 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -574,7 +574,6 @@ struct tc_indr_block_dev { struct net_device *dev; unsigned int refcnt; struct list_head cb_list; - struct tcf_block *block; }; struct tc_indr_block_cb { @@ -611,7 +610,6 @@ static struct tc_indr_block_dev *tc_indr_block_dev_get(struct net_device *dev) INIT_LIST_HEAD(&indr_dev->cb_list); indr_dev->dev = dev; - indr_dev->block = tc_dev_ingress_block(dev); if (rhashtable_insert_fast(&indr_setup_block_ht, &indr_dev->ht_node, tc_indr_setup_block_ht_params)) { kfree(indr_dev); @@ -706,6 +704,7 @@ int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, { struct tc_indr_block_cb *indr_block_cb; struct tc_indr_block_dev *indr_dev; + struct tcf_block *block; int err; indr_dev = tc_indr_block_dev_get(dev); @@ -717,8 +716,9 @@ int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, if (err) goto err_dev_put; - tc_indr_block_ing_cmd(dev, indr_dev->block, cb, cb_priv, - FLOW_BLOCK_BIND); + block = tc_dev_ingress_block(dev); + tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb, + indr_block_cb->cb_priv, FLOW_BLOCK_BIND); return 0; err_dev_put: @@ -745,6 +745,7 @@ void __tc_indr_block_cb_unregister(struct net_device *dev, { struct tc_indr_block_cb *indr_block_cb; struct tc_indr_block_dev *indr_dev; + struct tcf_block *block; indr_dev = tc_indr_block_dev_lookup(dev); if (!indr_dev) @@ -755,8 +756,9 @@ void __tc_indr_block_cb_unregister(struct net_device *dev, return; /* Send unbind message if required to free any block cbs. */ - tc_indr_block_ing_cmd(dev, indr_dev->block, cb, indr_block_cb->cb_priv, - FLOW_BLOCK_UNBIND); + block = tc_dev_ingress_block(dev); + tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb, + indr_block_cb->cb_priv, FLOW_BLOCK_UNBIND); tc_indr_block_cb_del(indr_block_cb); tc_indr_block_dev_put(indr_dev); } @@ -792,8 +794,6 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, if (!indr_dev) return; - indr_dev->block = command == FLOW_BLOCK_BIND ? block : NULL; - list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, &bo); -- GitLab From e4da91021153b78b9f2972212610bc71263925f4 Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:51 +0800 Subject: [PATCH 2313/7155] cls_api: add flow_indr_block_call function This patch make indr_block_call don't access struct tc_indr_block_cb and tc_indr_block_dev directly Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- net/sched/cls_api.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 12eaa6c90e79..7c34fc6851c3 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -773,13 +773,27 @@ void tc_indr_block_cb_unregister(struct net_device *dev, } EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister); +static void flow_indr_block_call(struct net_device *dev, + struct flow_block_offload *bo, + enum flow_block_command command) +{ + struct tc_indr_block_cb *indr_block_cb; + struct tc_indr_block_dev *indr_dev; + + indr_dev = tc_indr_block_dev_lookup(dev); + if (!indr_dev) + return; + + list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) + indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, + bo); +} + static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, struct tcf_block_ext_info *ei, enum flow_block_command command, struct netlink_ext_ack *extack) { - struct tc_indr_block_cb *indr_block_cb; - struct tc_indr_block_dev *indr_dev; struct flow_block_offload bo = { .command = command, .binder_type = ei->binder_type, @@ -790,14 +804,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, }; INIT_LIST_HEAD(&bo.cb_list); - indr_dev = tc_indr_block_dev_lookup(dev); - if (!indr_dev) - return; - - list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) - indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, - &bo); - + flow_indr_block_call(dev, &bo, command); tcf_block_setup(block, &bo); } -- GitLab From 4e481908c51bf02457aecdedc2d80e1be22e0146 Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:52 +0800 Subject: [PATCH 2314/7155] flow_offload: move tc indirect block to flow offload move tc indirect block to flow_offload and rename it to flow indirect block.The nf_tables can use the indr block architecture. Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 10 +- .../ethernet/netronome/nfp/flower/offload.c | 11 +- include/net/flow_offload.h | 29 +++ include/net/pkt_cls.h | 35 --- include/net/sch_generic.h | 3 - net/core/flow_offload.c | 215 ++++++++++++++++ net/sched/cls_api.c | 240 ++---------------- 7 files changed, 280 insertions(+), 263 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index fbb9de633578..b7f113e996e5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -781,9 +781,9 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv, { int err; - err = __tc_indr_block_cb_register(netdev, rpriv, - mlx5e_rep_indr_setup_tc_cb, - rpriv); + err = __flow_indr_block_cb_register(netdev, rpriv, + mlx5e_rep_indr_setup_tc_cb, + rpriv); if (err) { struct mlx5e_priv *priv = netdev_priv(rpriv->netdev); @@ -796,8 +796,8 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv, static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv, struct net_device *netdev) { - __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb, - rpriv); + __flow_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb, + rpriv); } static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb, diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index ff8a9f1a38f8..3a4f4f042ae7 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -1649,16 +1649,17 @@ int nfp_flower_reg_indir_block_handler(struct nfp_app *app, return NOTIFY_OK; if (event == NETDEV_REGISTER) { - err = __tc_indr_block_cb_register(netdev, app, - nfp_flower_indr_setup_tc_cb, - app); + err = __flow_indr_block_cb_register(netdev, app, + nfp_flower_indr_setup_tc_cb, + app); if (err) nfp_flower_cmsg_warn(app, "Indirect block reg failed - %s\n", netdev->name); } else if (event == NETDEV_UNREGISTER) { - __tc_indr_block_cb_unregister(netdev, - nfp_flower_indr_setup_tc_cb, app); + __flow_indr_block_cb_unregister(netdev, + nfp_flower_indr_setup_tc_cb, + app); } return NOTIFY_OK; diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index d3b12bc8a114..46b8777ad05d 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -4,6 +4,7 @@ #include #include #include +#include struct flow_match { struct flow_dissector *dissector; @@ -370,4 +371,32 @@ static inline void flow_block_init(struct flow_block *flow_block) INIT_LIST_HEAD(&flow_block->cb_list); } +typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv, + enum tc_setup_type type, void *type_data); + +typedef void flow_indr_block_ing_cmd_t(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command command); + +int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, + flow_indr_block_bind_cb_t *cb, + void *cb_ident); + +void __flow_indr_block_cb_unregister(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_ident); + +int flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, + flow_indr_block_bind_cb_t *cb, void *cb_ident); + +void flow_indr_block_cb_unregister(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_ident); + +void flow_indr_block_call(struct net_device *dev, + flow_indr_block_ing_cmd_t *cb, + struct flow_block_offload *bo, + enum flow_block_command command); + #endif /* _NET_FLOW_OFFLOAD_H */ diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index e429809ca90d..0790a4ed909c 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -70,15 +70,6 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block) return block->q; } -int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident); -int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident); -void __tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident); -void tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident); - int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res, bool compat_mode); @@ -137,32 +128,6 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb, { } -static inline -int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - return 0; -} - -static inline -int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - return 0; -} - -static inline -void __tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ -} - -static inline -void tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ -} - static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res, bool compat_mode) { diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 6b6b01234dd9..d9f359af0b93 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -23,9 +23,6 @@ struct tcf_walker; struct module; struct bpf_flow_keys; -typedef int tc_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv, - enum tc_setup_type type, void *type_data); - struct qdisc_rate_table { struct tc_ratespec rate; u32 data[256]; diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c index d63b970784dc..4cc18e462d50 100644 --- a/net/core/flow_offload.c +++ b/net/core/flow_offload.c @@ -2,6 +2,7 @@ #include #include #include +#include struct flow_rule *flow_rule_alloc(unsigned int num_actions) { @@ -280,3 +281,217 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f, } } EXPORT_SYMBOL(flow_block_cb_setup_simple); + +static struct rhashtable indr_setup_block_ht; + +struct flow_indr_block_cb { + struct list_head list; + void *cb_priv; + flow_indr_block_bind_cb_t *cb; + void *cb_ident; +}; + +struct flow_indr_block_dev { + struct rhash_head ht_node; + struct net_device *dev; + unsigned int refcnt; + flow_indr_block_ing_cmd_t *block_ing_cmd_cb; + struct list_head cb_list; +}; + +static const struct rhashtable_params flow_indr_setup_block_ht_params = { + .key_offset = offsetof(struct flow_indr_block_dev, dev), + .head_offset = offsetof(struct flow_indr_block_dev, ht_node), + .key_len = sizeof(struct net_device *), +}; + +static struct flow_indr_block_dev * +flow_indr_block_dev_lookup(struct net_device *dev) +{ + return rhashtable_lookup_fast(&indr_setup_block_ht, &dev, + flow_indr_setup_block_ht_params); +} + +static struct flow_indr_block_dev * +flow_indr_block_dev_get(struct net_device *dev) +{ + struct flow_indr_block_dev *indr_dev; + + indr_dev = flow_indr_block_dev_lookup(dev); + if (indr_dev) + goto inc_ref; + + indr_dev = kzalloc(sizeof(*indr_dev), GFP_KERNEL); + if (!indr_dev) + return NULL; + + INIT_LIST_HEAD(&indr_dev->cb_list); + indr_dev->dev = dev; + if (rhashtable_insert_fast(&indr_setup_block_ht, &indr_dev->ht_node, + flow_indr_setup_block_ht_params)) { + kfree(indr_dev); + return NULL; + } + +inc_ref: + indr_dev->refcnt++; + return indr_dev; +} + +static void flow_indr_block_dev_put(struct flow_indr_block_dev *indr_dev) +{ + if (--indr_dev->refcnt) + return; + + rhashtable_remove_fast(&indr_setup_block_ht, &indr_dev->ht_node, + flow_indr_setup_block_ht_params); + kfree(indr_dev); +} + +static struct flow_indr_block_cb * +flow_indr_block_cb_lookup(struct flow_indr_block_dev *indr_dev, + flow_indr_block_bind_cb_t *cb, void *cb_ident) +{ + struct flow_indr_block_cb *indr_block_cb; + + list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) + if (indr_block_cb->cb == cb && + indr_block_cb->cb_ident == cb_ident) + return indr_block_cb; + return NULL; +} + +static struct flow_indr_block_cb * +flow_indr_block_cb_add(struct flow_indr_block_dev *indr_dev, void *cb_priv, + flow_indr_block_bind_cb_t *cb, void *cb_ident) +{ + struct flow_indr_block_cb *indr_block_cb; + + indr_block_cb = flow_indr_block_cb_lookup(indr_dev, cb, cb_ident); + if (indr_block_cb) + return ERR_PTR(-EEXIST); + + indr_block_cb = kzalloc(sizeof(*indr_block_cb), GFP_KERNEL); + if (!indr_block_cb) + return ERR_PTR(-ENOMEM); + + indr_block_cb->cb_priv = cb_priv; + indr_block_cb->cb = cb; + indr_block_cb->cb_ident = cb_ident; + list_add(&indr_block_cb->list, &indr_dev->cb_list); + + return indr_block_cb; +} + +static void flow_indr_block_cb_del(struct flow_indr_block_cb *indr_block_cb) +{ + list_del(&indr_block_cb->list); + kfree(indr_block_cb); +} + +int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, + flow_indr_block_bind_cb_t *cb, + void *cb_ident) +{ + struct flow_indr_block_cb *indr_block_cb; + struct flow_indr_block_dev *indr_dev; + int err; + + indr_dev = flow_indr_block_dev_get(dev); + if (!indr_dev) + return -ENOMEM; + + indr_block_cb = flow_indr_block_cb_add(indr_dev, cb_priv, cb, cb_ident); + err = PTR_ERR_OR_ZERO(indr_block_cb); + if (err) + goto err_dev_put; + + if (indr_dev->block_ing_cmd_cb) + indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb, + indr_block_cb->cb_priv, + FLOW_BLOCK_BIND); + + return 0; + +err_dev_put: + flow_indr_block_dev_put(indr_dev); + return err; +} +EXPORT_SYMBOL_GPL(__flow_indr_block_cb_register); + +int flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, + flow_indr_block_bind_cb_t *cb, + void *cb_ident) +{ + int err; + + rtnl_lock(); + err = __flow_indr_block_cb_register(dev, cb_priv, cb, cb_ident); + rtnl_unlock(); + + return err; +} +EXPORT_SYMBOL_GPL(flow_indr_block_cb_register); + +void __flow_indr_block_cb_unregister(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_ident) +{ + struct flow_indr_block_cb *indr_block_cb; + struct flow_indr_block_dev *indr_dev; + + indr_dev = flow_indr_block_dev_lookup(dev); + if (!indr_dev) + return; + + indr_block_cb = flow_indr_block_cb_lookup(indr_dev, cb, cb_ident); + if (!indr_block_cb) + return; + + if (indr_dev->block_ing_cmd_cb) + indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb, + indr_block_cb->cb_priv, + FLOW_BLOCK_UNBIND); + + flow_indr_block_cb_del(indr_block_cb); + flow_indr_block_dev_put(indr_dev); +} +EXPORT_SYMBOL_GPL(__flow_indr_block_cb_unregister); + +void flow_indr_block_cb_unregister(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_ident) +{ + rtnl_lock(); + __flow_indr_block_cb_unregister(dev, cb, cb_ident); + rtnl_unlock(); +} +EXPORT_SYMBOL_GPL(flow_indr_block_cb_unregister); + +void flow_indr_block_call(struct net_device *dev, + flow_indr_block_ing_cmd_t cb, + struct flow_block_offload *bo, + enum flow_block_command command) +{ + struct flow_indr_block_cb *indr_block_cb; + struct flow_indr_block_dev *indr_dev; + + indr_dev = flow_indr_block_dev_lookup(dev); + if (!indr_dev) + return; + + indr_dev->block_ing_cmd_cb = command == FLOW_BLOCK_BIND + ? cb : NULL; + + list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) + indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, + bo); +} +EXPORT_SYMBOL_GPL(flow_indr_block_call); + +static int __init init_flow_indr_rhashtable(void) +{ + return rhashtable_init(&indr_setup_block_ht, + &flow_indr_setup_block_ht_params); +} +subsys_initcall(init_flow_indr_rhashtable); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 7c34fc6851c3..0b0dde26783d 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -37,6 +37,7 @@ #include #include #include +#include extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1]; @@ -545,139 +546,12 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held) } } -static struct tcf_block *tc_dev_ingress_block(struct net_device *dev) -{ - const struct Qdisc_class_ops *cops; - struct Qdisc *qdisc; - - if (!dev_ingress_queue(dev)) - return NULL; - - qdisc = dev_ingress_queue(dev)->qdisc_sleeping; - if (!qdisc) - return NULL; - - cops = qdisc->ops->cl_ops; - if (!cops) - return NULL; - - if (!cops->tcf_block) - return NULL; - - return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL); -} - -static struct rhashtable indr_setup_block_ht; - -struct tc_indr_block_dev { - struct rhash_head ht_node; - struct net_device *dev; - unsigned int refcnt; - struct list_head cb_list; -}; - -struct tc_indr_block_cb { - struct list_head list; - void *cb_priv; - tc_indr_block_bind_cb_t *cb; - void *cb_ident; -}; - -static const struct rhashtable_params tc_indr_setup_block_ht_params = { - .key_offset = offsetof(struct tc_indr_block_dev, dev), - .head_offset = offsetof(struct tc_indr_block_dev, ht_node), - .key_len = sizeof(struct net_device *), -}; - -static struct tc_indr_block_dev * -tc_indr_block_dev_lookup(struct net_device *dev) -{ - return rhashtable_lookup_fast(&indr_setup_block_ht, &dev, - tc_indr_setup_block_ht_params); -} - -static struct tc_indr_block_dev *tc_indr_block_dev_get(struct net_device *dev) -{ - struct tc_indr_block_dev *indr_dev; - - indr_dev = tc_indr_block_dev_lookup(dev); - if (indr_dev) - goto inc_ref; - - indr_dev = kzalloc(sizeof(*indr_dev), GFP_KERNEL); - if (!indr_dev) - return NULL; - - INIT_LIST_HEAD(&indr_dev->cb_list); - indr_dev->dev = dev; - if (rhashtable_insert_fast(&indr_setup_block_ht, &indr_dev->ht_node, - tc_indr_setup_block_ht_params)) { - kfree(indr_dev); - return NULL; - } - -inc_ref: - indr_dev->refcnt++; - return indr_dev; -} - -static void tc_indr_block_dev_put(struct tc_indr_block_dev *indr_dev) -{ - if (--indr_dev->refcnt) - return; - - rhashtable_remove_fast(&indr_setup_block_ht, &indr_dev->ht_node, - tc_indr_setup_block_ht_params); - kfree(indr_dev); -} - -static struct tc_indr_block_cb * -tc_indr_block_cb_lookup(struct tc_indr_block_dev *indr_dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - struct tc_indr_block_cb *indr_block_cb; - - list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) - if (indr_block_cb->cb == cb && - indr_block_cb->cb_ident == cb_ident) - return indr_block_cb; - return NULL; -} - -static struct tc_indr_block_cb * -tc_indr_block_cb_add(struct tc_indr_block_dev *indr_dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - struct tc_indr_block_cb *indr_block_cb; - - indr_block_cb = tc_indr_block_cb_lookup(indr_dev, cb, cb_ident); - if (indr_block_cb) - return ERR_PTR(-EEXIST); - - indr_block_cb = kzalloc(sizeof(*indr_block_cb), GFP_KERNEL); - if (!indr_block_cb) - return ERR_PTR(-ENOMEM); - - indr_block_cb->cb_priv = cb_priv; - indr_block_cb->cb = cb; - indr_block_cb->cb_ident = cb_ident; - list_add(&indr_block_cb->list, &indr_dev->cb_list); - - return indr_block_cb; -} - -static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb) -{ - list_del(&indr_block_cb->list); - kfree(indr_block_cb); -} - static int tcf_block_setup(struct tcf_block *block, struct flow_block_offload *bo); static void tc_indr_block_ing_cmd(struct net_device *dev, struct tcf_block *block, - tc_indr_block_bind_cb_t *cb, + flow_indr_block_bind_cb_t *cb, void *cb_priv, enum flow_block_command command) { @@ -699,97 +573,40 @@ static void tc_indr_block_ing_cmd(struct net_device *dev, tcf_block_setup(block, &bo); } -int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - struct tc_indr_block_cb *indr_block_cb; - struct tc_indr_block_dev *indr_dev; - struct tcf_block *block; - int err; - - indr_dev = tc_indr_block_dev_get(dev); - if (!indr_dev) - return -ENOMEM; - - indr_block_cb = tc_indr_block_cb_add(indr_dev, cb_priv, cb, cb_ident); - err = PTR_ERR_OR_ZERO(indr_block_cb); - if (err) - goto err_dev_put; - - block = tc_dev_ingress_block(dev); - tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb, - indr_block_cb->cb_priv, FLOW_BLOCK_BIND); - return 0; - -err_dev_put: - tc_indr_block_dev_put(indr_dev); - return err; -} -EXPORT_SYMBOL_GPL(__tc_indr_block_cb_register); - -int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv, - tc_indr_block_bind_cb_t *cb, void *cb_ident) +static struct tcf_block *tc_dev_ingress_block(struct net_device *dev) { - int err; - - rtnl_lock(); - err = __tc_indr_block_cb_register(dev, cb_priv, cb, cb_ident); - rtnl_unlock(); - - return err; -} -EXPORT_SYMBOL_GPL(tc_indr_block_cb_register); + const struct Qdisc_class_ops *cops; + struct Qdisc *qdisc; -void __tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - struct tc_indr_block_cb *indr_block_cb; - struct tc_indr_block_dev *indr_dev; - struct tcf_block *block; + if (!dev_ingress_queue(dev)) + return NULL; - indr_dev = tc_indr_block_dev_lookup(dev); - if (!indr_dev) - return; + qdisc = dev_ingress_queue(dev)->qdisc_sleeping; + if (!qdisc) + return NULL; - indr_block_cb = tc_indr_block_cb_lookup(indr_dev, cb, cb_ident); - if (!indr_block_cb) - return; + cops = qdisc->ops->cl_ops; + if (!cops) + return NULL; - /* Send unbind message if required to free any block cbs. */ - block = tc_dev_ingress_block(dev); - tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb, - indr_block_cb->cb_priv, FLOW_BLOCK_UNBIND); - tc_indr_block_cb_del(indr_block_cb); - tc_indr_block_dev_put(indr_dev); -} -EXPORT_SYMBOL_GPL(__tc_indr_block_cb_unregister); + if (!cops->tcf_block) + return NULL; -void tc_indr_block_cb_unregister(struct net_device *dev, - tc_indr_block_bind_cb_t *cb, void *cb_ident) -{ - rtnl_lock(); - __tc_indr_block_cb_unregister(dev, cb, cb_ident); - rtnl_unlock(); + return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL); } -EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister); -static void flow_indr_block_call(struct net_device *dev, - struct flow_block_offload *bo, - enum flow_block_command command) +static void tc_indr_block_get_and_ing_cmd(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command command) { - struct tc_indr_block_cb *indr_block_cb; - struct tc_indr_block_dev *indr_dev; - - indr_dev = tc_indr_block_dev_lookup(dev); - if (!indr_dev) - return; + struct tcf_block *block = tc_dev_ingress_block(dev); - list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) - indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, - bo); + tc_indr_block_ing_cmd(dev, block, cb, cb_priv, command); } -static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, +static void tc_indr_block_call(struct tcf_block *block, + struct net_device *dev, struct tcf_block_ext_info *ei, enum flow_block_command command, struct netlink_ext_ack *extack) @@ -804,7 +621,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, }; INIT_LIST_HEAD(&bo.cb_list); - flow_indr_block_call(dev, &bo, command); + flow_indr_block_call(dev, tc_indr_block_get_and_ing_cmd, &bo, command); tcf_block_setup(block, &bo); } @@ -3378,11 +3195,6 @@ static int __init tc_filter_init(void) if (err) goto err_register_pernet_subsys; - err = rhashtable_init(&indr_setup_block_ht, - &tc_indr_setup_block_ht_params); - if (err) - goto err_rhash_setup_block_ht; - rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL, RTNL_FLAG_DOIT_UNLOCKED); rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_del_tfilter, NULL, @@ -3396,8 +3208,6 @@ static int __init tc_filter_init(void) return 0; -err_rhash_setup_block_ht: - unregister_pernet_subsys(&tcf_net_ops); err_register_pernet_subsys: destroy_workqueue(tc_filter_wq); return err; -- GitLab From 1150ab0f1b333ca310431dac65d8fa403b8471da Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:53 +0800 Subject: [PATCH 2315/7155] flow_offload: support get multi-subsystem block It provide a callback list to find the blocks of tc and nft subsystems Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/flow_offload.h | 10 +++++++- net/core/flow_offload.c | 51 ++++++++++++++++++++++++++++---------- net/sched/cls_api.c | 9 ++++++- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 46b8777ad05d..e8069b6c474c 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -379,6 +379,15 @@ typedef void flow_indr_block_ing_cmd_t(struct net_device *dev, void *cb_priv, enum flow_block_command command); +struct flow_indr_block_ing_entry { + flow_indr_block_ing_cmd_t *cb; + struct list_head list; +}; + +void flow_indr_add_block_ing_cb(struct flow_indr_block_ing_entry *entry); + +void flow_indr_del_block_ing_cb(struct flow_indr_block_ing_entry *entry); + int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, flow_indr_block_bind_cb_t *cb, void *cb_ident); @@ -395,7 +404,6 @@ void flow_indr_block_cb_unregister(struct net_device *dev, void *cb_ident); void flow_indr_block_call(struct net_device *dev, - flow_indr_block_ing_cmd_t *cb, struct flow_block_offload *bo, enum flow_block_command command); diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c index 4cc18e462d50..64c3d4d72b9c 100644 --- a/net/core/flow_offload.c +++ b/net/core/flow_offload.c @@ -3,6 +3,7 @@ #include #include #include +#include struct flow_rule *flow_rule_alloc(unsigned int num_actions) { @@ -282,6 +283,8 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f, } EXPORT_SYMBOL(flow_block_cb_setup_simple); +static LIST_HEAD(block_ing_cb_list); + static struct rhashtable indr_setup_block_ht; struct flow_indr_block_cb { @@ -295,7 +298,6 @@ struct flow_indr_block_dev { struct rhash_head ht_node; struct net_device *dev; unsigned int refcnt; - flow_indr_block_ing_cmd_t *block_ing_cmd_cb; struct list_head cb_list; }; @@ -389,6 +391,20 @@ static void flow_indr_block_cb_del(struct flow_indr_block_cb *indr_block_cb) kfree(indr_block_cb); } +static void flow_block_ing_cmd(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command command) +{ + struct flow_indr_block_ing_entry *entry; + + rcu_read_lock(); + list_for_each_entry_rcu(entry, &block_ing_cb_list, list) { + entry->cb(dev, cb, cb_priv, command); + } + rcu_read_unlock(); +} + int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, flow_indr_block_bind_cb_t *cb, void *cb_ident) @@ -406,10 +422,8 @@ int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, if (err) goto err_dev_put; - if (indr_dev->block_ing_cmd_cb) - indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb, - indr_block_cb->cb_priv, - FLOW_BLOCK_BIND); + flow_block_ing_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv, + FLOW_BLOCK_BIND); return 0; @@ -448,10 +462,8 @@ void __flow_indr_block_cb_unregister(struct net_device *dev, if (!indr_block_cb) return; - if (indr_dev->block_ing_cmd_cb) - indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb, - indr_block_cb->cb_priv, - FLOW_BLOCK_UNBIND); + flow_block_ing_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv, + FLOW_BLOCK_UNBIND); flow_indr_block_cb_del(indr_block_cb); flow_indr_block_dev_put(indr_dev); @@ -469,7 +481,6 @@ void flow_indr_block_cb_unregister(struct net_device *dev, EXPORT_SYMBOL_GPL(flow_indr_block_cb_unregister); void flow_indr_block_call(struct net_device *dev, - flow_indr_block_ing_cmd_t cb, struct flow_block_offload *bo, enum flow_block_command command) { @@ -480,15 +491,29 @@ void flow_indr_block_call(struct net_device *dev, if (!indr_dev) return; - indr_dev->block_ing_cmd_cb = command == FLOW_BLOCK_BIND - ? cb : NULL; - list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list) indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, bo); } EXPORT_SYMBOL_GPL(flow_indr_block_call); +static DEFINE_MUTEX(flow_indr_block_ing_cb_lock); +void flow_indr_add_block_ing_cb(struct flow_indr_block_ing_entry *entry) +{ + mutex_lock(&flow_indr_block_ing_cb_lock); + list_add_tail_rcu(&entry->list, &block_ing_cb_list); + mutex_unlock(&flow_indr_block_ing_cb_lock); +} +EXPORT_SYMBOL_GPL(flow_indr_add_block_ing_cb); + +void flow_indr_del_block_ing_cb(struct flow_indr_block_ing_entry *entry) +{ + mutex_lock(&flow_indr_block_ing_cb_lock); + list_del_rcu(&entry->list); + mutex_unlock(&flow_indr_block_ing_cb_lock); +} +EXPORT_SYMBOL_GPL(flow_indr_del_block_ing_cb); + static int __init init_flow_indr_rhashtable(void) { return rhashtable_init(&indr_setup_block_ht, diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 0b0dde26783d..e0d8b456e9f5 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -621,7 +621,7 @@ static void tc_indr_block_call(struct tcf_block *block, }; INIT_LIST_HEAD(&bo.cb_list); - flow_indr_block_call(dev, tc_indr_block_get_and_ing_cmd, &bo, command); + flow_indr_block_call(dev, &bo, command); tcf_block_setup(block, &bo); } @@ -3183,6 +3183,11 @@ static struct pernet_operations tcf_net_ops = { .size = sizeof(struct tcf_net), }; +static struct flow_indr_block_ing_entry block_ing_entry = { + .cb = tc_indr_block_get_and_ing_cmd, + .list = LIST_HEAD_INIT(block_ing_entry.list), +}; + static int __init tc_filter_init(void) { int err; @@ -3195,6 +3200,8 @@ static int __init tc_filter_init(void) if (err) goto err_register_pernet_subsys; + flow_indr_add_block_ing_cb(&block_ing_entry); + rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL, RTNL_FLAG_DOIT_UNLOCKED); rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_del_tfilter, NULL, -- GitLab From 9a32669fecfb484a1f78fe48d0e42a5efccb0675 Mon Sep 17 00:00:00 2001 From: wenxu Date: Wed, 7 Aug 2019 09:13:54 +0800 Subject: [PATCH 2316/7155] netfilter: nf_tables_offload: support indr block call nftable support indr-block call. It makes nftable an offload vlan and tunnel device. nft add table netdev firewall nft add chain netdev firewall aclout { type filter hook ingress offload device mlx_pf0vf0 priority - 300 \; } nft add rule netdev firewall aclout ip daddr 10.0.0.1 fwd to vlan0 nft add chain netdev firewall aclin { type filter hook ingress device vlan0 priority - 300 \; } nft add rule netdev firewall aclin ip daddr 10.0.0.7 fwd to mlx_pf0vf0 Signed-off-by: wenxu Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/net/netfilter/nf_tables_offload.h | 4 + net/netfilter/nf_tables_api.c | 7 + net/netfilter/nf_tables_offload.c | 148 ++++++++++++++++++---- 3 files changed, 135 insertions(+), 24 deletions(-) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 3196663a10e3..bffd51a90343 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -63,6 +63,10 @@ struct nft_rule; struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule); void nft_flow_rule_destroy(struct nft_flow_rule *flow); int nft_flow_rule_offload_commit(struct net *net); +void nft_indr_block_get_and_ing_cmd(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command command); #define NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \ (__reg)->base_offset = \ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 605a7cfe7ca7..fe3b7b0c6c66 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7593,6 +7593,11 @@ static struct pernet_operations nf_tables_net_ops = { .exit = nf_tables_exit_net, }; +static struct flow_indr_block_ing_entry block_ing_entry = { + .cb = nft_indr_block_get_and_ing_cmd, + .list = LIST_HEAD_INIT(block_ing_entry.list), +}; + static int __init nf_tables_module_init(void) { int err; @@ -7624,6 +7629,7 @@ static int __init nf_tables_module_init(void) goto err5; nft_chain_route_init(); + flow_indr_add_block_ing_cb(&block_ing_entry); return err; err5: rhltable_destroy(&nft_objname_ht); @@ -7640,6 +7646,7 @@ static int __init nf_tables_module_init(void) static void __exit nf_tables_module_exit(void) { + flow_indr_del_block_ing_cb(&block_ing_entry); nfnetlink_subsys_unregister(&nf_tables_subsys); unregister_netdevice_notifier(&nf_tables_flowtable_notifier); nft_chain_filter_fini(); diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 64f5fd5f240e..d3c4c9c88bc8 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -171,24 +171,110 @@ static int nft_flow_offload_unbind(struct flow_block_offload *bo, return 0; } +static int nft_block_setup(struct nft_base_chain *basechain, + struct flow_block_offload *bo, + enum flow_block_command cmd) +{ + int err; + + switch (cmd) { + case FLOW_BLOCK_BIND: + err = nft_flow_offload_bind(bo, basechain); + break; + case FLOW_BLOCK_UNBIND: + err = nft_flow_offload_unbind(bo, basechain); + break; + default: + WARN_ON_ONCE(1); + err = -EOPNOTSUPP; + } + + return err; +} + +static int nft_block_offload_cmd(struct nft_base_chain *chain, + struct net_device *dev, + enum flow_block_command cmd) +{ + struct netlink_ext_ack extack = {}; + struct flow_block_offload bo = {}; + int err; + + bo.net = dev_net(dev); + bo.block = &chain->flow_block; + bo.command = cmd; + bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; + bo.extack = &extack; + INIT_LIST_HEAD(&bo.cb_list); + + err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo); + if (err < 0) + return err; + + return nft_block_setup(chain, &bo, cmd); +} + +static void nft_indr_block_ing_cmd(struct net_device *dev, + struct nft_base_chain *chain, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command cmd) +{ + struct netlink_ext_ack extack = {}; + struct flow_block_offload bo = {}; + + if (!chain) + return; + + bo.net = dev_net(dev); + bo.block = &chain->flow_block; + bo.command = cmd; + bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; + bo.extack = &extack; + INIT_LIST_HEAD(&bo.cb_list); + + cb(dev, cb_priv, TC_SETUP_BLOCK, &bo); + + nft_block_setup(chain, &bo, cmd); +} + +static int nft_indr_block_offload_cmd(struct nft_base_chain *chain, + struct net_device *dev, + enum flow_block_command cmd) +{ + struct flow_block_offload bo = {}; + struct netlink_ext_ack extack = {}; + + bo.net = dev_net(dev); + bo.block = &chain->flow_block; + bo.command = cmd; + bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; + bo.extack = &extack; + INIT_LIST_HEAD(&bo.cb_list); + + flow_indr_block_call(dev, &bo, cmd); + + if (list_empty(&bo.cb_list)) + return -EOPNOTSUPP; + + return nft_block_setup(chain, &bo, cmd); +} + #define FLOW_SETUP_BLOCK TC_SETUP_BLOCK static int nft_flow_offload_chain(struct nft_trans *trans, enum flow_block_command cmd) { struct nft_chain *chain = trans->ctx.chain; - struct netlink_ext_ack extack = {}; - struct flow_block_offload bo = {}; struct nft_base_chain *basechain; struct net_device *dev; - int err; if (!nft_is_base_chain(chain)) return -EOPNOTSUPP; basechain = nft_base_chain(chain); dev = basechain->ops.dev; - if (!dev || !dev->netdev_ops->ndo_setup_tc) + if (!dev) return -EOPNOTSUPP; /* Only default policy to accept is supported for now. */ @@ -197,26 +283,10 @@ static int nft_flow_offload_chain(struct nft_trans *trans, nft_trans_chain_policy(trans) != NF_ACCEPT) return -EOPNOTSUPP; - bo.command = cmd; - bo.block = &basechain->flow_block; - bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; - bo.extack = &extack; - INIT_LIST_HEAD(&bo.cb_list); - - err = dev->netdev_ops->ndo_setup_tc(dev, FLOW_SETUP_BLOCK, &bo); - if (err < 0) - return err; - - switch (cmd) { - case FLOW_BLOCK_BIND: - err = nft_flow_offload_bind(&bo, basechain); - break; - case FLOW_BLOCK_UNBIND: - err = nft_flow_offload_unbind(&bo, basechain); - break; - } - - return err; + if (dev->netdev_ops->ndo_setup_tc) + return nft_block_offload_cmd(basechain, dev, cmd); + else + return nft_indr_block_offload_cmd(basechain, dev, cmd); } int nft_flow_rule_offload_commit(struct net *net) @@ -266,3 +336,33 @@ int nft_flow_rule_offload_commit(struct net *net) return err; } + +void nft_indr_block_get_and_ing_cmd(struct net_device *dev, + flow_indr_block_bind_cb_t *cb, + void *cb_priv, + enum flow_block_command command) +{ + struct net *net = dev_net(dev); + const struct nft_table *table; + const struct nft_chain *chain; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { + if (table->family != NFPROTO_NETDEV) + continue; + + list_for_each_entry_rcu(chain, &table->chains, list) { + if (nft_is_base_chain(chain)) { + struct nft_base_chain *basechain; + + basechain = nft_base_chain(chain); + if (!strncmp(basechain->dev_name, dev->name, + IFNAMSIZ)) { + nft_indr_block_ing_cmd(dev, basechain, + cb, cb_priv, + command); + return; + } + } + } + } +} -- GitLab From fdbe4eeeb1aac219b14f10c0ed31ae5d1123e9b8 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Wed, 7 Aug 2019 01:48:28 +0100 Subject: [PATCH 2317/7155] loop: Add LOOP_SET_DIRECT_IO to compat ioctl Enabling Direct I/O with loop devices helps reducing memory usage by avoiding double caching. 32 bit applications running on 64 bits systems are currently not able to request direct I/O because is missing from the lo_compat_ioctl. This patch fixes the compatibility issue mentioned above by exporting LOOP_SET_DIRECT_IO as additional lo_compat_ioctl() entry. The input argument for this ioctl is a single long converted to a 1-bit boolean, so compatibility is preserved. Cc: Jens Axboe Signed-off-by: Alessio Balsini Signed-off-by: Jens Axboe --- drivers/block/loop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 3036883fc9f8..a7461f482467 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1755,6 +1755,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, case LOOP_SET_FD: case LOOP_CHANGE_FD: case LOOP_SET_BLOCK_SIZE: + case LOOP_SET_DIRECT_IO: err = lo_ioctl(bdev, mode, cmd, arg); break; default: -- GitLab From f0e6f41669d9e07f45b472e4de33d7c233a847bd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 8 Aug 2019 22:11:28 -0600 Subject: [PATCH 2318/7155] lightnvm: remove unused 'geo' variable A previous commit correctly removed set-but-not-read variables, but this left two new variables now unused. Kill them. Fixes: ba6f7da99aaf ("lightnvm: remove set but not used variables 'data_len' and 'rq_len'") Reported-by: Stephen Rothwell Signed-off-by: Jens Axboe --- drivers/lightnvm/pblk-read.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c index 0cdc48f9cfbf..8efd14e683dc 100644 --- a/drivers/lightnvm/pblk-read.c +++ b/drivers/lightnvm/pblk-read.c @@ -417,8 +417,6 @@ static int read_rq_gc(struct pblk *pblk, struct nvm_rq *rqd, int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) { - struct nvm_tgt_dev *dev = pblk->dev; - struct nvm_geo *geo = &dev->geo; struct nvm_rq rqd; int ret = NVM_IO_OK; -- GitLab From 7a4be6c113c1f721818d1e3722a9015fe393295c Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 29 Jul 2019 13:40:18 +0300 Subject: [PATCH 2319/7155] crypto: ccree - use the full crypt length value In case of AEAD decryption verifcation error we were using the wrong value to zero out the plaintext buffer leaving the end of the buffer with the false plaintext. Signed-off-by: Gilad Ben-Yossef Fixes: ff27e85a85bb ("crypto: ccree - add AEAD support") CC: stable@vger.kernel.org # v4.17+ Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index ce302adc76c7..339fabfe3de6 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -236,7 +236,7 @@ static void cc_aead_complete(struct device *dev, void *cc_req, int err) /* In case of payload authentication failure, MUST NOT * revealed the decrypted message --> zero its memory. */ - cc_zero_sgl(areq->dst, areq_ctx->cryptlen); + cc_zero_sgl(areq->dst, areq->cryptlen); err = -EBADMSG; } /*ENCRYPT*/ -- GitLab From e88b27c8eaa8f3126791778803dd2fdd81828f5c Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 29 Jul 2019 13:40:19 +0300 Subject: [PATCH 2320/7155] crypto: ccree - use std api sg_zero_buffer Replace internal cc_zero_sgl() with kernel API of the same function sg_zero_buffer(). Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 3 ++- drivers/crypto/ccree/cc_buffer_mgr.c | 21 --------------------- drivers/crypto/ccree/cc_buffer_mgr.h | 2 -- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index 339fabfe3de6..a9779a212b18 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -236,7 +236,8 @@ static void cc_aead_complete(struct device *dev, void *cc_req, int err) /* In case of payload authentication failure, MUST NOT * revealed the decrypted message --> zero its memory. */ - cc_zero_sgl(areq->dst, areq->cryptlen); + sg_zero_buffer(areq->dst, sg_nents(areq->dst), + areq->cryptlen, 0); err = -EBADMSG; } /*ENCRYPT*/ diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c index c81ad33f9115..a72586eccd81 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.c +++ b/drivers/crypto/ccree/cc_buffer_mgr.c @@ -99,27 +99,6 @@ static unsigned int cc_get_sgl_nents(struct device *dev, return nents; } -/** - * cc_zero_sgl() - Zero scatter scatter list data. - * - * @sgl: - */ -void cc_zero_sgl(struct scatterlist *sgl, u32 data_len) -{ - struct scatterlist *current_sg = sgl; - int sg_index = 0; - - while (sg_index <= data_len) { - if (!current_sg) { - /* reached the end of the sgl --> just return back */ - return; - } - memset(sg_virt(current_sg), 0, current_sg->length); - sg_index += current_sg->length; - current_sg = sg_next(current_sg); - } -} - /** * cc_copy_sg_portion() - Copy scatter list data, * from to_skip to end, to dest and vice versa diff --git a/drivers/crypto/ccree/cc_buffer_mgr.h b/drivers/crypto/ccree/cc_buffer_mgr.h index a726016bdbc1..af434872c6ff 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.h +++ b/drivers/crypto/ccree/cc_buffer_mgr.h @@ -66,6 +66,4 @@ void cc_unmap_hash_request(struct device *dev, void *ctx, void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg, u32 to_skip, u32 end, enum cc_sg_cpy_direct direct); -void cc_zero_sgl(struct scatterlist *sgl, u32 data_len); - #endif /*__BUFFER_MGR_H__*/ -- GitLab From f6ebfd7826a8b69ad6691695a97409bd35d146a9 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Mon, 29 Jul 2019 12:56:08 +0000 Subject: [PATCH 2321/7155] crypto: ccp - Log an error message when ccp-crypto fails to load If there are no CCP devices on the system, ccp-crypto will not load. Write a message to the system log clarifying the reason for the failure of the modprobe operation Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c index 818096490829..8ee4cb45a3f3 100644 --- a/drivers/crypto/ccp/ccp-crypto-main.c +++ b/drivers/crypto/ccp/ccp-crypto-main.c @@ -405,8 +405,10 @@ static int ccp_crypto_init(void) int ret; ret = ccp_present(); - if (ret) + if (ret) { + pr_err("Cannot load: there are no available CCPs\n"); return ret; + } spin_lock_init(&req_queue_lock); INIT_LIST_HEAD(&req_queue.cmds); -- GitLab From 15b2455ab4e6434a53c639bd2a168cd2a3e1eb47 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Jul 2019 17:38:19 -0500 Subject: [PATCH 2322/7155] crypto: ux500/crypt - Mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: arm): drivers/crypto/ux500/cryp/cryp.c: In function ‘cryp_save_device_context’: drivers/crypto/ux500/cryp/cryp.c:316:16: warning: this statement may fall through [-Wimplicit-fallthrough=] ctx->key_4_r = readl_relaxed(&src_reg->key_4_r); drivers/crypto/ux500/cryp/cryp.c:318:2: note: here case CRYP_KEY_SIZE_192: ^~~~ drivers/crypto/ux500/cryp/cryp.c:320:16: warning: this statement may fall through [-Wimplicit-fallthrough=] ctx->key_3_r = readl_relaxed(&src_reg->key_3_r); drivers/crypto/ux500/cryp/cryp.c:322:2: note: here case CRYP_KEY_SIZE_128: ^~~~ drivers/crypto/ux500/cryp/cryp.c:324:16: warning: this statement may fall through [-Wimplicit-fallthrough=] ctx->key_2_r = readl_relaxed(&src_reg->key_2_r); drivers/crypto/ux500/cryp/cryp.c:326:2: note: here default: ^~~~~~~ In file included from ./include/linux/io.h:13:0, from drivers/crypto/ux500/cryp/cryp_p.h:14, from drivers/crypto/ux500/cryp/cryp.c:15: drivers/crypto/ux500/cryp/cryp.c: In function ‘cryp_restore_device_context’: ./arch/arm/include/asm/io.h:92:22: warning: this statement may fall through [-Wimplicit-fallthrough=] #define __raw_writel __raw_writel ^ ./arch/arm/include/asm/io.h:299:29: note: in expansion of macro ‘__raw_writel’ #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) ^~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:363:3: note: in expansion of macro ‘writel_relaxed’ writel_relaxed(ctx->key_4_r, ®->key_4_r); ^~~~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:365:2: note: here case CRYP_KEY_SIZE_192: ^~~~ In file included from ./include/linux/io.h:13:0, from drivers/crypto/ux500/cryp/cryp_p.h:14, from drivers/crypto/ux500/cryp/cryp.c:15: ./arch/arm/include/asm/io.h:92:22: warning: this statement may fall through [-Wimplicit-fallthrough=] #define __raw_writel __raw_writel ^ ./arch/arm/include/asm/io.h:299:29: note: in expansion of macro ‘__raw_writel’ #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) ^~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:367:3: note: in expansion of macro ‘writel_relaxed’ writel_relaxed(ctx->key_3_r, ®->key_3_r); ^~~~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:369:2: note: here case CRYP_KEY_SIZE_128: ^~~~ In file included from ./include/linux/io.h:13:0, from drivers/crypto/ux500/cryp/cryp_p.h:14, from drivers/crypto/ux500/cryp/cryp.c:15: ./arch/arm/include/asm/io.h:92:22: warning: this statement may fall through [-Wimplicit-fallthrough=] #define __raw_writel __raw_writel ^ ./arch/arm/include/asm/io.h:299:29: note: in expansion of macro ‘__raw_writel’ #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) ^~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:371:3: note: in expansion of macro ‘writel_relaxed’ writel_relaxed(ctx->key_2_r, ®->key_2_r); ^~~~~~~~~~~~~~ drivers/crypto/ux500/cryp/cryp.c:373:2: note: here default: ^~~~~~~ Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Herbert Xu --- drivers/crypto/ux500/cryp/cryp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c index ece83a363e11..f22f6fa612b3 100644 --- a/drivers/crypto/ux500/cryp/cryp.c +++ b/drivers/crypto/ux500/cryp/cryp.c @@ -314,14 +314,17 @@ void cryp_save_device_context(struct cryp_device_data *device_data, case CRYP_KEY_SIZE_256: ctx->key_4_l = readl_relaxed(&src_reg->key_4_l); ctx->key_4_r = readl_relaxed(&src_reg->key_4_r); + /* Fall through */ case CRYP_KEY_SIZE_192: ctx->key_3_l = readl_relaxed(&src_reg->key_3_l); ctx->key_3_r = readl_relaxed(&src_reg->key_3_r); + /* Fall through */ case CRYP_KEY_SIZE_128: ctx->key_2_l = readl_relaxed(&src_reg->key_2_l); ctx->key_2_r = readl_relaxed(&src_reg->key_2_r); + /* Fall through */ default: ctx->key_1_l = readl_relaxed(&src_reg->key_1_l); @@ -361,14 +364,17 @@ void cryp_restore_device_context(struct cryp_device_data *device_data, case CRYP_KEY_SIZE_256: writel_relaxed(ctx->key_4_l, ®->key_4_l); writel_relaxed(ctx->key_4_r, ®->key_4_r); + /* Fall through */ case CRYP_KEY_SIZE_192: writel_relaxed(ctx->key_3_l, ®->key_3_l); writel_relaxed(ctx->key_3_r, ®->key_3_r); + /* Fall through */ case CRYP_KEY_SIZE_128: writel_relaxed(ctx->key_2_l, ®->key_2_l); writel_relaxed(ctx->key_2_r, ®->key_2_r); + /* Fall through */ default: writel_relaxed(ctx->key_1_l, ®->key_1_l); -- GitLab From 48f89d2a2920166c35b1c0b69917dbb0390ebec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Tue, 30 Jul 2019 08:48:33 +0300 Subject: [PATCH 2323/7155] crypto: caam - fix concurrency issue in givencrypt descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IV transfer from ofifo to class2 (set up at [29][30]) is not guaranteed to be scheduled before the data transfer from ofifo to external memory (set up at [38]: [29] 10FA0004 ld: ind-nfifo (len=4) imm [30] 81F00010 class2 type=msg len=16> [31] 14820004 ld: ccb2-datasz len=4 offs=0 imm [32] 00000010 data:0x00000010 [33] 8210010D operation: cls1-op aes cbc init-final enc [34] A8080B04 math: (seqin + math0)->vseqout len=4 [35] 28000010 seqfifold: skip len=16 [36] A8080A04 math: (seqin + math0)->vseqin len=4 [37] 2F1E0000 seqfifold: both msg1->2-last2-last1 len=vseqinsz [38] 69300000 seqfifostr: msg len=vseqoutsz [39] 5C20000C seqstr: ccb2 ctx len=12 offs=0 If ofifo -> external memory transfer happens first, DECO will hang (issuing a Watchdog Timeout error, if WDOG is enabled) waiting for data availability in ofifo for the ofifo -> c2 ififo transfer. Make sure IV transfer happens first by waiting for all CAAM internal transfers to end before starting payload transfer. New descriptor with jump command inserted at [37]: [..] [36] A8080A04 math: (seqin + math0)->vseqin len=4 [37] A1000401 jump: jsl1 all-match[!nfifopend] offset=[01] local->[38] [38] 2F1E0000 seqfifold: both msg1->2-last2-last1 len=vseqinsz [39] 69300000 seqfifostr: msg len=vseqoutsz [40] 5C20000C seqstr: ccb2 ctx len=12 offs=0 [Note: the issue is present in the descriptor from the very beginning (cf. Fixes tag). However I've marked it v4.19+ since it's the oldest maintained kernel that the patch applies clean against.] Cc: # v4.19+ Fixes: 1acebad3d8db8 ("crypto: caam - faster aead implementation") Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_desc.c | 9 +++++++++ drivers/crypto/caam/caamalg_desc.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamalg_desc.c b/drivers/crypto/caam/caamalg_desc.c index 72531837571e..28ecef7a481c 100644 --- a/drivers/crypto/caam/caamalg_desc.c +++ b/drivers/crypto/caam/caamalg_desc.c @@ -503,6 +503,7 @@ void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata, const bool is_qi, int era) { u32 geniv, moveiv; + u32 *wait_cmd; /* Note: Context registers are saved. */ init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era); @@ -598,6 +599,14 @@ void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata, /* Will read cryptlen */ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + + /* + * Wait for IV transfer (ofifo -> class2) to finish before starting + * ciphertext transfer (ofifo -> external memory). + */ + wait_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | JUMP_COND_NIFP); + set_jump_tgt_here(desc, wait_cmd); + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF | FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH); append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); diff --git a/drivers/crypto/caam/caamalg_desc.h b/drivers/crypto/caam/caamalg_desc.h index da4a4ee60c80..706007624d82 100644 --- a/drivers/crypto/caam/caamalg_desc.h +++ b/drivers/crypto/caam/caamalg_desc.h @@ -12,7 +12,7 @@ #define DESC_AEAD_BASE (4 * CAAM_CMD_SZ) #define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 11 * CAAM_CMD_SZ) #define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 15 * CAAM_CMD_SZ) -#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ) +#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 8 * CAAM_CMD_SZ) #define DESC_QI_AEAD_ENC_LEN (DESC_AEAD_ENC_LEN + 3 * CAAM_CMD_SZ) #define DESC_QI_AEAD_DEC_LEN (DESC_AEAD_DEC_LEN + 3 * CAAM_CMD_SZ) #define DESC_QI_AEAD_GIVENC_LEN (DESC_AEAD_GIVENC_LEN + 3 * CAAM_CMD_SZ) -- GitLab From f26882a3475eb7b2c35fd3b1e291924161b1327d Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Tue, 30 Jul 2019 15:27:11 +0200 Subject: [PATCH 2324/7155] crypto: inside-secure - Use defines instead of some constants (cosmetic) This patch replaces some hard constants regarding key, IV and nonce sizes with appropriate defines from the crypto header files. Signed-off-by: Pascal van Leeuwen Acked-by: Antoine Tenart Signed-off-by: Herbert Xu --- .../crypto/inside-secure/safexcel_cipher.c | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 477e0ec35f45..718d64f6e3ee 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -226,19 +227,21 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, goto badkey; if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { - /* 20 is minimum AES key: 16 bytes + 4 bytes nonce */ - if (keys.enckeylen < 20) + /* Minimum keysize is minimum AES key size + nonce size */ + if (keys.enckeylen < (AES_MIN_KEY_SIZE + + CTR_RFC3686_NONCE_SIZE)) goto badkey; /* last 4 bytes of key are the nonce! */ - ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen - 4); + ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen - + CTR_RFC3686_NONCE_SIZE); /* exclude the nonce here */ - keys.enckeylen -= 4; + keys.enckeylen -= CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; } /* Encryption key */ switch (ctx->alg) { case SAFEXCEL_3DES: - if (keys.enckeylen != 24) + if (keys.enckeylen != DES3_EDE_KEY_SIZE) goto badkey; flags = crypto_aead_get_flags(ctfm); err = __des3_verify_key(&flags, keys.enckey); @@ -1119,9 +1122,9 @@ static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm, unsigned int keylen; /* last 4 bytes of key are the nonce! */ - ctx->nonce = *(u32 *)(key + len - 4); + ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE); /* exclude the nonce here */ - keylen = len - 4; + keylen = len - CTR_RFC3686_NONCE_SIZE; ret = aes_expandkey(&aes, key, keylen); if (ret) { crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); @@ -1152,10 +1155,10 @@ struct safexcel_alg_template safexcel_alg_ctr_aes = { .setkey = safexcel_skcipher_aesctr_setkey, .encrypt = safexcel_ctr_aes_encrypt, .decrypt = safexcel_ctr_aes_decrypt, - /* Add 4 to include the 4 byte nonce! */ - .min_keysize = AES_MIN_KEY_SIZE + 4, - .max_keysize = AES_MAX_KEY_SIZE + 4, - .ivsize = 8, + /* Add nonce size */ + .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + .ivsize = CTR_RFC3686_IV_SIZE, .base = { .cra_name = "rfc3686(ctr(aes))", .cra_driver_name = "safexcel-ctr-aes", @@ -1657,7 +1660,7 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_aes = { .setkey = safexcel_aead_setkey, .encrypt = safexcel_aead_encrypt_aes, .decrypt = safexcel_aead_decrypt_aes, - .ivsize = 8, + .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, .base = { .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", @@ -1690,7 +1693,7 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_ctr_aes = { .setkey = safexcel_aead_setkey, .encrypt = safexcel_aead_encrypt_aes, .decrypt = safexcel_aead_decrypt_aes, - .ivsize = 8, + .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, .base = { .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", @@ -1723,7 +1726,7 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_ctr_aes = { .setkey = safexcel_aead_setkey, .encrypt = safexcel_aead_encrypt_aes, .decrypt = safexcel_aead_decrypt_aes, - .ivsize = 8, + .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, .base = { .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", @@ -1756,7 +1759,7 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes = { .setkey = safexcel_aead_setkey, .encrypt = safexcel_aead_encrypt_aes, .decrypt = safexcel_aead_decrypt_aes, - .ivsize = 8, + .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, .base = { .cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))", @@ -1789,7 +1792,7 @@ struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_ctr_aes = { .setkey = safexcel_aead_setkey, .encrypt = safexcel_aead_encrypt_aes, .decrypt = safexcel_aead_decrypt_aes, - .ivsize = 8, + .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, .base = { .cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))", -- GitLab From 514838e920d06f5c2ba56e9656107dfcbbb90219 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:05 -0700 Subject: [PATCH 2325/7155] crypto: drivers - Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Greg Kroah-Hartman Cc: Herbert Xu Cc: "David S. Miller" Cc: Signed-off-by: Stephen Boyd Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 1 - drivers/crypto/atmel-sha.c | 1 - drivers/crypto/atmel-tdes.c | 1 - drivers/crypto/ccree/cc_driver.c | 4 +--- drivers/crypto/img-hash.c | 1 - drivers/crypto/mediatek/mtk-platform.c | 4 +--- drivers/crypto/mxs-dcp.c | 8 ++------ drivers/crypto/omap-aes.c | 1 - drivers/crypto/omap-des.c | 1 - drivers/crypto/omap-sham.c | 1 - drivers/crypto/sahara.c | 4 +--- drivers/crypto/stm32/stm32-cryp.c | 4 +--- drivers/crypto/stm32/stm32-hash.c | 4 +--- 13 files changed, 7 insertions(+), 28 deletions(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 2b7af44c7b85..026f193556f9 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -2673,7 +2673,6 @@ static int atmel_aes_probe(struct platform_device *pdev) /* Get the IRQ */ aes_dd->irq = platform_get_irq(pdev, 0); if (aes_dd->irq < 0) { - dev_err(dev, "no IRQ resource info\n"); err = aes_dd->irq; goto res_err; } diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index ab0cfe748931..84cb8748a795 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -2779,7 +2779,6 @@ static int atmel_sha_probe(struct platform_device *pdev) /* Get the IRQ */ sha_dd->irq = platform_get_irq(pdev, 0); if (sha_dd->irq < 0) { - dev_err(dev, "no IRQ resource info\n"); err = sha_dd->irq; goto res_err; } diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index fa76620281e8..6256883a89ed 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -1281,7 +1281,6 @@ static int atmel_tdes_probe(struct platform_device *pdev) /* Get the IRQ */ tdes_dd->irq = platform_get_irq(pdev, 0); if (tdes_dd->irq < 0) { - dev_err(dev, "no IRQ resource info\n"); err = tdes_dd->irq; goto res_err; } diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 196e3d140355..8b8eee513c27 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -338,10 +338,8 @@ static int init_cc_resources(struct platform_device *plat_dev) /* Then IRQ */ new_drvdata->irq = platform_get_irq(plat_dev, 0); - if (new_drvdata->irq < 0) { - dev_err(dev, "Failed getting IRQ resource\n"); + if (new_drvdata->irq < 0) return new_drvdata->irq; - } init_completion(&new_drvdata->hw_queue_avail); diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index d27c812c3d8d..6754eaafdc85 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -980,7 +980,6 @@ static int img_hash_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "no IRQ resource info\n"); err = irq; goto res_err; } diff --git a/drivers/crypto/mediatek/mtk-platform.c b/drivers/crypto/mediatek/mtk-platform.c index 125318a88cd4..4f43318ca14b 100644 --- a/drivers/crypto/mediatek/mtk-platform.c +++ b/drivers/crypto/mediatek/mtk-platform.c @@ -495,10 +495,8 @@ static int mtk_crypto_probe(struct platform_device *pdev) for (i = 0; i < MTK_IRQ_NUM; i++) { cryp->irq[i] = platform_get_irq(pdev, i); - if (cryp->irq[i] < 0) { - dev_err(cryp->dev, "no IRQ:%d resource info\n", i); + if (cryp->irq[i] < 0) return cryp->irq[i]; - } } cryp->clk_cryp = devm_clk_get(&pdev->dev, "cryp"); diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index f1fa637cb029..bf8d2197bc11 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -994,16 +994,12 @@ static int mxs_dcp_probe(struct platform_device *pdev) } dcp_vmi_irq = platform_get_irq(pdev, 0); - if (dcp_vmi_irq < 0) { - dev_err(dev, "Failed to get IRQ: (%d)!\n", dcp_vmi_irq); + if (dcp_vmi_irq < 0) return dcp_vmi_irq; - } dcp_irq = platform_get_irq(pdev, 1); - if (dcp_irq < 0) { - dev_err(dev, "Failed to get IRQ: (%d)!\n", dcp_irq); + if (dcp_irq < 0) return dcp_irq; - } sdcp = devm_kzalloc(dev, sizeof(*sdcp), GFP_KERNEL); if (!sdcp) diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 45a4647f7030..2f53fbb74100 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -1180,7 +1180,6 @@ static int omap_aes_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "can't get IRQ resource\n"); err = irq; goto err_irq; } diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 1ee69a979677..484a693122af 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -1049,7 +1049,6 @@ static int omap_des_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "can't get IRQ resource: %d\n", irq); err = irq; goto err_irq; } diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index e8e2907bd9f4..ac80bc6af093 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -1989,7 +1989,6 @@ static int omap_sham_get_res_pdev(struct omap_sham_dev *dd, /* Get the IRQ */ dd->irq = platform_get_irq(pdev, 0); if (dd->irq < 0) { - dev_err(dev, "no IRQ resource info\n"); err = dd->irq; goto err; } diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index b0b8e3d48aef..8ac8ec6decd5 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1403,10 +1403,8 @@ static int sahara_probe(struct platform_device *pdev) /* Get the IRQ */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (irq < 0) return irq; - } err = devm_request_irq(&pdev->dev, irq, sahara_irq_handler, 0, dev_name(&pdev->dev), dev); diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index 98ae02826e8f..72f86063b046 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -1975,10 +1975,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) return PTR_ERR(cryp->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "Cannot get IRQ resource\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq, stm32_cryp_irq_thread, IRQF_ONESHOT, diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index 2b70d8796f25..cfc8e0e37bee 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -1450,10 +1450,8 @@ static int stm32_hash_probe(struct platform_device *pdev) return ret; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "Cannot get IRQ resource\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, stm32_hash_irq_handler, stm32_hash_irq_thread, IRQF_ONESHOT, -- GitLab From 114e2ccd9eff5859760cfa3bcbb707c3eda63fc3 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 31 Jul 2019 00:03:25 +0000 Subject: [PATCH 2326/7155] crypto: ccp - Clean up and exit correctly on allocation failure Return and fail driver initialization if a DMA pool or coherent memory can't be allocated. Be sure to clean up allocated memory. Fixes: 4b394a232df7 ("crypto: ccp - Let a v5 CCP provide the same function as v3") Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev-v5.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index f146b51a23a5..9ee72cf46a0f 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -803,6 +803,7 @@ static int ccp5_init(struct ccp_device *ccp) if (!dma_pool) { dev_err(dev, "unable to allocate dma pool\n"); ret = -ENOMEM; + goto e_pool; } cmd_q = &ccp->cmd_q[ccp->cmd_q_count]; @@ -816,9 +817,9 @@ static int ccp5_init(struct ccp_device *ccp) /* Page alignment satisfies our needs for N <= 128 */ BUILD_BUG_ON(COMMANDS_PER_QUEUE > 128); cmd_q->qsize = Q_SIZE(Q_DESC_SIZE); - cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize, - &cmd_q->qbase_dma, - GFP_KERNEL); + cmd_q->qbase = dmam_alloc_coherent(dev, cmd_q->qsize, + &cmd_q->qbase_dma, + GFP_KERNEL); if (!cmd_q->qbase) { dev_err(dev, "unable to allocate command queue\n"); ret = -ENOMEM; @@ -994,7 +995,6 @@ static int ccp5_init(struct ccp_device *ccp) static void ccp5_destroy(struct ccp_device *ccp) { - struct device *dev = ccp->dev; struct ccp_cmd_queue *cmd_q; struct ccp_cmd *cmd; unsigned int i; @@ -1037,12 +1037,6 @@ static void ccp5_destroy(struct ccp_device *ccp) sp_free_ccp_irq(ccp->sp, ccp); - for (i = 0; i < ccp->cmd_q_count; i++) { - cmd_q = &ccp->cmd_q[i]; - dma_free_coherent(dev, cmd_q->qsize, cmd_q->qbase, - cmd_q->qbase_dma); - } - /* Flush the cmd and backlog queue */ while (!list_empty(&ccp->cmd)) { /* Invoke the callback directly with an error code */ -- GitLab From 1bfaac7c53f5cfe9c44d2093263fa50630a81b63 Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen Date: Wed, 31 Jul 2019 08:10:54 +0200 Subject: [PATCH 2327/7155] crypto: inside-secure - Remove redundant DES ECB & CBC keysize check This patch removes a DES key size check that is redundant as it is already performed by the crypto API itself due to min_keysize = max_keysize. Signed-off-by: Pascal van Leeuwen Acked-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_cipher.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 718d64f6e3ee..5682fe8b606e 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -1197,11 +1197,6 @@ static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key, u32 tmp[DES_EXPKEY_WORDS]; int ret; - if (len != DES_KEY_SIZE) { - crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - ret = des_ekey(tmp, key); if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; -- GitLab From 6c9081a3915dc0782a8f1424343b794f2cf53d9c Mon Sep 17 00:00:00 2001 From: John Rutherford Date: Wed, 7 Aug 2019 12:52:29 +1000 Subject: [PATCH 2328/7155] tipc: add loopback device tracking Since node internal messages are passed directly to the socket, it is not possible to observe those messages via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is enabled if network taps are active for the loopback device. pcap filtering restrictions require the messages to be presented to the receiving side of the loopback device. v3 - Function dev_nit_active used to check for network taps. - Procedure netif_rx_ni used to send cloned messages to loopback device. Signed-off-by: John Rutherford Acked-by: Jon Maloy Acked-by: Ying Xue Signed-off-by: David S. Miller --- net/tipc/bcast.c | 4 ++- net/tipc/bearer.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 10 ++++++++ net/tipc/core.c | 5 ++++ net/tipc/core.h | 3 +++ net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 7 files changed, 88 insertions(+), 1 deletion(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 1336f3cdad38..34f3e5641438 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -406,8 +406,10 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a809c0ec8d15..0214aa1c4427 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -389,6 +389,11 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, dev_put(dev); return -EINVAL; } + if (dev == net->loopback_dev) { + dev_put(dev); + pr_info("Enabling <%s> not permitted\n", b->name); + return -EINVAL; + } /* Autoconfigure own node identity if needed */ if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { @@ -674,6 +679,65 @@ void tipc_bearer_stop(struct net *net) } } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(pkts, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + + skb_reset_network_header(skb); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->protocol = eth_type_trans(skb, dev); + netif_rx_ni(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + /* Caller should hold rtnl_lock to protect the bearer */ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer, int nlflags) diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569594a5..ea0f3c49cbed 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -232,6 +232,16 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); + +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(dev_nit_active(net->loopback_dev))) + tipc_clone_to_loopback(net, pkts); +} /* check if device MTU is too low for tipc headers */ static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) diff --git a/net/tipc/core.c b/net/tipc/core.c index c8370722f0bb..23cb379a93d6 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -82,6 +82,10 @@ static int __net_init tipc_init_net(struct net *net) if (err) goto out_bclink; + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; + return 0; out_bclink: @@ -94,6 +98,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b6a066..60d829581068 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -125,6 +125,9 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; }; static inline struct tipc_net *tipc_net(struct net *net) diff --git a/net/tipc/node.c b/net/tipc/node.c index 7ca019001f7c..1bdcf0fc1a4d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1443,6 +1443,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index ca8ac96d22a9..3a12fc18239b 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include #include @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- GitLab From 65526f638efc6435b9658d45a3ddd07e6fdbbb7d Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:05:54 +0300 Subject: [PATCH 2329/7155] crypto: gcm - helper functions for assoclen/authsize check Added inline helper functions to check authsize and assoclen for gcm, rfc4106 and rfc4543. These are used in the generic implementation of gcm, rfc4106 and rfc4543. Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- crypto/gcm.c | 41 ++++++++++++--------------------- include/crypto/gcm.h | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/crypto/gcm.c b/crypto/gcm.c index f254e2d4c206..2f3b50f8f3e0 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -152,20 +152,7 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, static int crypto_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) { - switch (authsize) { - case 4: - case 8: - case 12: - case 13: - case 14: - case 15: - case 16: - break; - default: - return -EINVAL; - } - - return 0; + return crypto_gcm_check_authsize(authsize); } static void crypto_gcm_init_common(struct aead_request *req) @@ -762,15 +749,11 @@ static int crypto_rfc4106_setauthsize(struct crypto_aead *parent, unsigned int authsize) { struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent); + int err; - switch (authsize) { - case 8: - case 12: - case 16: - break; - default: - return -EINVAL; - } + err = crypto_rfc4106_check_authsize(authsize); + if (err) + return err; return crypto_aead_setauthsize(ctx->child, authsize); } @@ -818,8 +801,11 @@ static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req) static int crypto_rfc4106_encrypt(struct aead_request *req) { - if (req->assoclen != 16 && req->assoclen != 20) - return -EINVAL; + int err; + + err = crypto_ipsec_check_assoclen(req->assoclen); + if (err) + return err; req = crypto_rfc4106_crypt(req); @@ -828,8 +814,11 @@ static int crypto_rfc4106_encrypt(struct aead_request *req) static int crypto_rfc4106_decrypt(struct aead_request *req) { - if (req->assoclen != 16 && req->assoclen != 20) - return -EINVAL; + int err; + + err = crypto_ipsec_check_assoclen(req->assoclen); + if (err) + return err; req = crypto_rfc4106_crypt(req); diff --git a/include/crypto/gcm.h b/include/crypto/gcm.h index c50e057ea17e..9d7eff04f224 100644 --- a/include/crypto/gcm.h +++ b/include/crypto/gcm.h @@ -1,8 +1,63 @@ #ifndef _CRYPTO_GCM_H #define _CRYPTO_GCM_H +#include + #define GCM_AES_IV_SIZE 12 #define GCM_RFC4106_IV_SIZE 8 #define GCM_RFC4543_IV_SIZE 8 +/* + * validate authentication tag for GCM + */ +static inline int crypto_gcm_check_authsize(unsigned int authsize) +{ + switch (authsize) { + case 4: + case 8: + case 12: + case 13: + case 14: + case 15: + case 16: + break; + default: + return -EINVAL; + } + + return 0; +} + +/* + * validate authentication tag for RFC4106 + */ +static inline int crypto_rfc4106_check_authsize(unsigned int authsize) +{ + switch (authsize) { + case 8: + case 12: + case 16: + break; + default: + return -EINVAL; + } + + return 0; +} + +/* + * validate assoclen for RFC4106/RFC4543 + */ +static inline int crypto_ipsec_check_assoclen(unsigned int assoclen) +{ + switch (assoclen) { + case 16: + case 20: + break; + default: + return -EINVAL; + } + + return 0; +} #endif -- GitLab From bc67d04e75260942fb534fb91673103dcad7ca96 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:05:55 +0300 Subject: [PATCH 2330/7155] crypto: aes - helper function to validate key length for AES algorithms Add inline helper function to check key length for AES algorithms. The key can be 128, 192 or 256 bits size. This function is used in the generic aes implementation. Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- include/crypto/aes.h | 17 +++++++++++++++++ lib/crypto/aes.c | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 8e0f4cf948e5..2090729701ab 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -31,6 +31,23 @@ struct crypto_aes_ctx { extern const u32 crypto_ft_tab[4][256] ____cacheline_aligned; extern const u32 crypto_it_tab[4][256] ____cacheline_aligned; +/* + * validate key length for AES algorithms + */ +static inline int aes_check_keylen(unsigned int keylen) +{ + switch (keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + break; + default: + return -EINVAL; + } + + return 0; +} + int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len); diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index 4e100af38c51..827fe89922ff 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -187,11 +187,11 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, { u32 kwords = key_len / sizeof(u32); u32 rc, i, j; + int err; - if (key_len != AES_KEYSIZE_128 && - key_len != AES_KEYSIZE_192 && - key_len != AES_KEYSIZE_256) - return -EINVAL; + err = aes_check_keylen(key_len); + if (err) + return err; ctx->key_length = key_len; -- GitLab From 51fab3d73054ca5b06b26e20edac0486b052c6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 31 Jul 2019 16:08:02 +0300 Subject: [PATCH 2331/7155] crypto: caam/qi - fix error handling in ERN handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ERN handler calls the caam/qi frontend "done" callback with a status of -EIO. This is incorrect, since the callback expects a status value meaningful for the crypto engine - hence the cryptic messages like the one below: platform caam_qi: 15: unknown error source Fix this by providing the callback with: -the status returned by the crypto engine (fd[status]) in case it contains an error, OR -a QI "No error" code otherwise; this will trigger the message: platform caam_qi: 50000000: Queue Manager Interface: No error which is fine, since QMan driver provides details about the cause of failure Cc: # v5.1+ Fixes: 67c2315def06 ("crypto: caam - add Queue Interface (QI) backend support") Signed-off-by: Horia Geantă Reviewed-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/caam/error.c | 1 + drivers/crypto/caam/qi.c | 5 ++++- drivers/crypto/caam/regs.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c index 4f0d45865aa2..95da6ae43482 100644 --- a/drivers/crypto/caam/error.c +++ b/drivers/crypto/caam/error.c @@ -118,6 +118,7 @@ static const struct { u8 value; const char *error_text; } qi_error_list[] = { + { 0x00, "No error" }, { 0x1F, "Job terminated by FQ or ICID flush" }, { 0x20, "FD format error"}, { 0x21, "FD command format error"}, diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c index 0fe618e3804a..19a378bdf331 100644 --- a/drivers/crypto/caam/qi.c +++ b/drivers/crypto/caam/qi.c @@ -163,7 +163,10 @@ static void caam_fq_ern_cb(struct qman_portal *qm, struct qman_fq *fq, dma_unmap_single(drv_req->drv_ctx->qidev, qm_fd_addr(fd), sizeof(drv_req->fd_sgt), DMA_BIDIRECTIONAL); - drv_req->cbk(drv_req, -EIO); + if (fd->status) + drv_req->cbk(drv_req, be32_to_cpu(fd->status)); + else + drv_req->cbk(drv_req, JRSTA_SSRC_QI); } static struct qman_fq *create_caam_req_fq(struct device *qidev, diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 8591914d5c51..7c7ea8af6a48 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -641,6 +641,7 @@ struct caam_job_ring { #define JRSTA_SSRC_CCB_ERROR 0x20000000 #define JRSTA_SSRC_JUMP_HALT_USER 0x30000000 #define JRSTA_SSRC_DECO 0x40000000 +#define JRSTA_SSRC_QI 0x50000000 #define JRSTA_SSRC_JRERROR 0x60000000 #define JRSTA_SSRC_JUMP_HALT_CC 0x70000000 -- GitLab From 1984aaeec372fbfb597883074253d290cbd543d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 31 Jul 2019 16:08:03 +0300 Subject: [PATCH 2332/7155] crypto: caam - fix return code in completion callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify drive to provide a valid errno (and not the HW error ID) to the user, via completion callbacks. A "valid errno" is currently not explicitly mentioned in the docs, however the error code is expected to match the one returned by the generic SW implementation. Note: in most error cases caam/qi and caam/qi2 returned -EIO; align all caam drivers to return -EINVAL. While here, ratelimit prints triggered by fuzz testing, such that console is not flooded. Signed-off-by: Horia Geantă Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 26 ++++++------- drivers/crypto/caam/caamalg_qi.c | 21 +++-------- drivers/crypto/caam/caamalg_qi2.c | 62 +++++++++---------------------- drivers/crypto/caam/caamhash.c | 20 ++++++---- drivers/crypto/caam/caampkc.c | 20 ++++++---- drivers/crypto/caam/error.c | 60 +++++++++++++++++++----------- drivers/crypto/caam/error.h | 2 +- drivers/crypto/caam/key_gen.c | 5 ++- drivers/crypto/caam/qi.c | 5 ++- 9 files changed, 104 insertions(+), 117 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 43f18253e5b6..06b4f2d47be4 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -930,19 +930,20 @@ static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err, { struct aead_request *req = context; struct aead_edesc *edesc; + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct aead_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); aead_unmap(jrdev, edesc, req); kfree(edesc); - aead_request_complete(req, err); + aead_request_complete(req, ecode); } static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err, @@ -950,25 +951,20 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err, { struct aead_request *req = context; struct aead_edesc *edesc; + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct aead_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); aead_unmap(jrdev, edesc, req); - /* - * verify hw auth check passed else return -EBADMSG - */ - if ((err & JRSTA_CCBERR_ERRID_MASK) == JRSTA_CCBERR_ERRID_ICVCHK) - err = -EBADMSG; - kfree(edesc); - aead_request_complete(req, err); + aead_request_complete(req, ecode); } static void skcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, @@ -978,13 +974,14 @@ static void skcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, struct skcipher_edesc *edesc; struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); int ivsize = crypto_skcipher_ivsize(skcipher); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct skcipher_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); skcipher_unmap(jrdev, edesc, req); @@ -1008,7 +1005,7 @@ static void skcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, kfree(edesc); - skcipher_request_complete(req, err); + skcipher_request_complete(req, ecode); } static void skcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, @@ -1018,12 +1015,13 @@ static void skcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, struct skcipher_edesc *edesc; struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); int ivsize = crypto_skcipher_ivsize(skcipher); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct skcipher_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); skcipher_unmap(jrdev, edesc, req); @@ -1047,7 +1045,7 @@ static void skcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, kfree(edesc); - skcipher_request_complete(req, err); + skcipher_request_complete(req, ecode); } /* diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 32f0f8a72067..ab263b1bf7f1 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -884,20 +884,8 @@ static void aead_done(struct caam_drv_req *drv_req, u32 status) qidev = caam_ctx->qidev; - if (unlikely(status)) { - u32 ssrc = status & JRSTA_SSRC_MASK; - u8 err_id = status & JRSTA_CCBERR_ERRID_MASK; - - caam_jr_strstatus(qidev, status); - /* - * verify hw auth check passed else return -EBADMSG - */ - if (ssrc == JRSTA_SSRC_CCB_ERROR && - err_id == JRSTA_CCBERR_ERRID_ICVCHK) - ecode = -EBADMSG; - else - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_jr_strstatus(qidev, status); edesc = container_of(drv_req, typeof(*edesc), drv_req); aead_unmap(qidev, edesc, aead_req); @@ -1190,13 +1178,14 @@ static void skcipher_done(struct caam_drv_req *drv_req, u32 status) struct caam_ctx *caam_ctx = crypto_skcipher_ctx(skcipher); struct device *qidev = caam_ctx->qidev; int ivsize = crypto_skcipher_ivsize(skcipher); + int ecode = 0; dev_dbg(qidev, "%s %d: status 0x%x\n", __func__, __LINE__, status); edesc = container_of(drv_req, typeof(*edesc), drv_req); if (status) - caam_jr_strstatus(qidev, status); + ecode = caam_jr_strstatus(qidev, status); print_hex_dump_debug("dstiv @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->iv, @@ -1215,7 +1204,7 @@ static void skcipher_done(struct caam_drv_req *drv_req, u32 status) memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, ivsize); qi_cache_free(edesc); - skcipher_request_complete(req, status); + skcipher_request_complete(req, ecode); } static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req, diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index a78a36dfa7b9..008528b563ea 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -1228,10 +1228,8 @@ static void aead_encrypt_done(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); aead_unmap(ctx->dev, edesc, req); qi_cache_free(edesc); @@ -1251,17 +1249,8 @@ static void aead_decrypt_done(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - /* - * verify hw auth check passed else return -EBADMSG - */ - if ((status & JRSTA_CCBERR_ERRID_MASK) == - JRSTA_CCBERR_ERRID_ICVCHK) - ecode = -EBADMSG; - else - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); aead_unmap(ctx->dev, edesc, req); qi_cache_free(edesc); @@ -1353,10 +1342,8 @@ static void skcipher_encrypt_done(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); print_hex_dump_debug("dstiv @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->iv, @@ -1391,10 +1378,8 @@ static void skcipher_decrypt_done(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); print_hex_dump_debug("dstiv @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->iv, @@ -3095,10 +3080,7 @@ static void split_key_sh_done(void *cbk_ctx, u32 err) dev_dbg(res->dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); - if (err) - caam_qi2_strstatus(res->dev, err); - - res->err = err; + res->err = err ? caam_qi2_strstatus(res->dev, err) : 0; complete(&res->completion); } @@ -3283,10 +3265,8 @@ static void ahash_done(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); ahash_unmap_ctx(ctx->dev, edesc, req, DMA_FROM_DEVICE); memcpy(req->result, state->caam_ctx, digestsize); @@ -3311,10 +3291,8 @@ static void ahash_done_bi(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); ahash_unmap_ctx(ctx->dev, edesc, req, DMA_BIDIRECTIONAL); switch_buf(state); @@ -3344,10 +3322,8 @@ static void ahash_done_ctx_src(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); ahash_unmap_ctx(ctx->dev, edesc, req, DMA_BIDIRECTIONAL); memcpy(req->result, state->caam_ctx, digestsize); @@ -3372,10 +3348,8 @@ static void ahash_done_ctx_dst(void *cbk_ctx, u32 status) dev_dbg(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); - if (unlikely(status)) { - caam_qi2_strstatus(ctx->dev, status); - ecode = -EIO; - } + if (unlikely(status)) + ecode = caam_qi2_strstatus(ctx->dev, status); ahash_unmap_ctx(ctx->dev, edesc, req, DMA_FROM_DEVICE); switch_buf(state); @@ -4701,7 +4675,7 @@ static void dpaa2_caam_process_fd(struct dpaa2_caam_priv *priv, fd_err = dpaa2_fd_get_ctrl(fd) & FD_CTRL_ERR_MASK; if (unlikely(fd_err)) - dev_err(priv->dev, "FD error: %08x\n", fd_err); + dev_err_ratelimited(priv->dev, "FD error: %08x\n", fd_err); /* * FD[ADDR] is guaranteed to be valid, irrespective of errors reported diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index e4ac5d591ad6..73abefa262ab 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -584,12 +584,13 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err, int digestsize = crypto_ahash_digestsize(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct ahash_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); memcpy(req->result, state->caam_ctx, digestsize); @@ -599,7 +600,7 @@ static void ahash_done(struct device *jrdev, u32 *desc, u32 err, DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, ctx->ctx_len, 1); - req->base.complete(&req->base, err); + req->base.complete(&req->base, ecode); } static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err, @@ -611,12 +612,13 @@ static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err, struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); int digestsize = crypto_ahash_digestsize(ahash); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct ahash_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL); switch_buf(state); @@ -630,7 +632,7 @@ static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err, DUMP_PREFIX_ADDRESS, 16, 4, req->result, digestsize, 1); - req->base.complete(&req->base, err); + req->base.complete(&req->base, ecode); } static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err, @@ -642,12 +644,13 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err, int digestsize = crypto_ahash_digestsize(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct ahash_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL); memcpy(req->result, state->caam_ctx, digestsize); @@ -657,7 +660,7 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err, DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, ctx->ctx_len, 1); - req->base.complete(&req->base, err); + req->base.complete(&req->base, ecode); } static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err, @@ -669,12 +672,13 @@ static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err, struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); int digestsize = crypto_ahash_digestsize(ahash); + int ecode = 0; dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); edesc = container_of(desc, struct ahash_edesc, hw_desc[0]); if (err) - caam_jr_strstatus(jrdev, err); + ecode = caam_jr_strstatus(jrdev, err); ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE); switch_buf(state); @@ -688,7 +692,7 @@ static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err, DUMP_PREFIX_ADDRESS, 16, 4, req->result, digestsize, 1); - req->base.complete(&req->base, err); + req->base.complete(&req->base, ecode); } /* diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 2340f9441a80..e05d975da582 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -107,9 +107,10 @@ static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context) { struct akcipher_request *req = context; struct rsa_edesc *edesc; + int ecode = 0; if (err) - caam_jr_strstatus(dev, err); + ecode = caam_jr_strstatus(dev, err); edesc = container_of(desc, struct rsa_edesc, hw_desc[0]); @@ -117,7 +118,7 @@ static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context) rsa_io_unmap(dev, edesc, req); kfree(edesc); - akcipher_request_complete(req, err); + akcipher_request_complete(req, ecode); } static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err, @@ -125,9 +126,10 @@ static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err, { struct akcipher_request *req = context; struct rsa_edesc *edesc; + int ecode = 0; if (err) - caam_jr_strstatus(dev, err); + ecode = caam_jr_strstatus(dev, err); edesc = container_of(desc, struct rsa_edesc, hw_desc[0]); @@ -135,7 +137,7 @@ static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err, rsa_io_unmap(dev, edesc, req); kfree(edesc); - akcipher_request_complete(req, err); + akcipher_request_complete(req, ecode); } static void rsa_priv_f2_done(struct device *dev, u32 *desc, u32 err, @@ -143,9 +145,10 @@ static void rsa_priv_f2_done(struct device *dev, u32 *desc, u32 err, { struct akcipher_request *req = context; struct rsa_edesc *edesc; + int ecode = 0; if (err) - caam_jr_strstatus(dev, err); + ecode = caam_jr_strstatus(dev, err); edesc = container_of(desc, struct rsa_edesc, hw_desc[0]); @@ -153,7 +156,7 @@ static void rsa_priv_f2_done(struct device *dev, u32 *desc, u32 err, rsa_io_unmap(dev, edesc, req); kfree(edesc); - akcipher_request_complete(req, err); + akcipher_request_complete(req, ecode); } static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err, @@ -161,9 +164,10 @@ static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err, { struct akcipher_request *req = context; struct rsa_edesc *edesc; + int ecode = 0; if (err) - caam_jr_strstatus(dev, err); + ecode = caam_jr_strstatus(dev, err); edesc = container_of(desc, struct rsa_edesc, hw_desc[0]); @@ -171,7 +175,7 @@ static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err, rsa_io_unmap(dev, edesc, req); kfree(edesc); - akcipher_request_complete(req, err); + akcipher_request_complete(req, ecode); } /** diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c index 95da6ae43482..b7fbf1be37a4 100644 --- a/drivers/crypto/caam/error.c +++ b/drivers/crypto/caam/error.c @@ -211,8 +211,8 @@ static const char * const rng_err_id_list[] = { "Secure key generation", }; -static void report_ccb_status(struct device *jrdev, const u32 status, - const char *error) +static int report_ccb_status(struct device *jrdev, const u32 status, + const char *error) { u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >> JRSTA_CCBERR_CHAID_SHIFT; @@ -248,22 +248,27 @@ static void report_ccb_status(struct device *jrdev, const u32 status, * CCB ICV check failures are part of normal operation life; * we leave the upper layers to do what they want with them. */ - if (err_id != JRSTA_CCBERR_ERRID_ICVCHK) - dev_err(jrdev, "%08x: %s: %s %d: %s%s: %s%s\n", - status, error, idx_str, idx, - cha_str, cha_err_code, - err_str, err_err_code); + if (err_id == JRSTA_CCBERR_ERRID_ICVCHK) + return -EBADMSG; + + dev_err_ratelimited(jrdev, "%08x: %s: %s %d: %s%s: %s%s\n", status, + error, idx_str, idx, cha_str, cha_err_code, + err_str, err_err_code); + + return -EINVAL; } -static void report_jump_status(struct device *jrdev, const u32 status, - const char *error) +static int report_jump_status(struct device *jrdev, const u32 status, + const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); + + return -EINVAL; } -static void report_deco_status(struct device *jrdev, const u32 status, - const char *error) +static int report_deco_status(struct device *jrdev, const u32 status, + const char *error) { u8 err_id = status & JRSTA_DECOERR_ERROR_MASK; u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >> @@ -289,10 +294,12 @@ static void report_deco_status(struct device *jrdev, const u32 status, dev_err(jrdev, "%08x: %s: %s %d: %s%s\n", status, error, idx_str, idx, err_str, err_err_code); + + return -EINVAL; } -static void report_qi_status(struct device *qidev, const u32 status, - const char *error) +static int report_qi_status(struct device *qidev, const u32 status, + const char *error) { u8 err_id = status & JRSTA_QIERR_ERROR_MASK; const char *err_str = "unidentified error value 0x"; @@ -310,27 +317,33 @@ static void report_qi_status(struct device *qidev, const u32 status, dev_err(qidev, "%08x: %s: %s%s\n", status, error, err_str, err_err_code); + + return -EINVAL; } -static void report_jr_status(struct device *jrdev, const u32 status, - const char *error) +static int report_jr_status(struct device *jrdev, const u32 status, + const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); + + return -EINVAL; } -static void report_cond_code_status(struct device *jrdev, const u32 status, - const char *error) +static int report_cond_code_status(struct device *jrdev, const u32 status, + const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); + + return -EINVAL; } -void caam_strstatus(struct device *jrdev, u32 status, bool qi_v2) +int caam_strstatus(struct device *jrdev, u32 status, bool qi_v2) { static const struct stat_src { - void (*report_ssed)(struct device *jrdev, const u32 status, - const char *error); + int (*report_ssed)(struct device *jrdev, const u32 status, + const char *error); const char *error; } status_src[16] = { { NULL, "No error" }, @@ -358,11 +371,14 @@ void caam_strstatus(struct device *jrdev, u32 status, bool qi_v2) * Otherwise print the error source name. */ if (status_src[ssrc].report_ssed) - status_src[ssrc].report_ssed(jrdev, status, error); - else if (error) + return status_src[ssrc].report_ssed(jrdev, status, error); + + if (error) dev_err(jrdev, "%d: %s\n", ssrc, error); else dev_err(jrdev, "%d: unknown error source\n", ssrc); + + return -EINVAL; } EXPORT_SYMBOL(caam_strstatus); diff --git a/drivers/crypto/caam/error.h b/drivers/crypto/caam/error.h index d9726e66edbf..16809fa8fec7 100644 --- a/drivers/crypto/caam/error.h +++ b/drivers/crypto/caam/error.h @@ -12,7 +12,7 @@ #define CAAM_ERROR_STR_MAX 302 -void caam_strstatus(struct device *dev, u32 status, bool qi_v2); +int caam_strstatus(struct device *dev, u32 status, bool qi_v2); #define caam_jr_strstatus(jrdev, status) caam_strstatus(jrdev, status, false) #define caam_qi2_strstatus(qidev, status) caam_strstatus(qidev, status, true) diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 48dd3536060d..c6f8375ae215 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -15,13 +15,14 @@ void split_key_done(struct device *dev, u32 *desc, u32 err, void *context) { struct split_key_result *res = context; + int ecode = 0; dev_dbg(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); if (err) - caam_jr_strstatus(dev, err); + ecode = caam_jr_strstatus(dev, err); - res->err = err; + res->err = ecode; complete(&res->completion); } diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c index 19a378bdf331..378f627e1d64 100644 --- a/drivers/crypto/caam/qi.c +++ b/drivers/crypto/caam/qi.c @@ -577,8 +577,9 @@ static enum qman_cb_dqrr_result caam_rsp_fq_dqrr_cb(struct qman_portal *p, if (ssrc != JRSTA_SSRC_CCB_ERROR || err_id != JRSTA_CCBERR_ERRID_ICVCHK) - dev_err(qidev, "Error: %#x in CAAM response FD\n", - status); + dev_err_ratelimited(qidev, + "Error: %#x in CAAM response FD\n", + status); } if (unlikely(qm_fd_get_format(fd) != qm_fd_compound)) { -- GitLab From 1ccb39eb5a9822543273c35f5114a9dc101e7315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 31 Jul 2019 16:08:04 +0300 Subject: [PATCH 2333/7155] crypto: caam - update IV only when crypto operation succeeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skcipher encryption might fail and in some cases, like (invalid) input length smaller then block size, updating the IV would lead to a useless IV copy in case hardware issued an error. Signed-off-by: Horia Geantă Signed-off-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 5 ++--- drivers/crypto/caam/caamalg_qi.c | 4 +++- drivers/crypto/caam/caamalg_qi2.c | 8 ++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 06b4f2d47be4..28d55a05b0f3 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -990,10 +990,9 @@ static void skcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, * ciphertext block (CBC mode) or last counter (CTR mode). * This is used e.g. by the CTS mode. */ - if (ivsize) { + if (ivsize && !ecode) { memcpy(req->iv, (u8 *)edesc->sec4_sg + edesc->sec4_sg_bytes, ivsize); - print_hex_dump_debug("dstiv @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->iv, edesc->src_nents > 1 ? 100 : ivsize, 1); @@ -1030,7 +1029,7 @@ static void skcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, * ciphertext block (CBC mode) or last counter (CTR mode). * This is used e.g. by the CTS mode. */ - if (ivsize) { + if (ivsize && !ecode) { memcpy(req->iv, (u8 *)edesc->sec4_sg + edesc->sec4_sg_bytes, ivsize); diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index ab263b1bf7f1..66531d6fbd0b 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -1201,7 +1201,9 @@ static void skcipher_done(struct caam_drv_req *drv_req, u32 status) * ciphertext block (CBC mode) or last counter (CTR mode). * This is used e.g. by the CTS mode. */ - memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, ivsize); + if (!ecode) + memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, + ivsize); qi_cache_free(edesc); skcipher_request_complete(req, ecode); diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 008528b563ea..fcd8a488efc5 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -1359,7 +1359,9 @@ static void skcipher_encrypt_done(void *cbk_ctx, u32 status) * ciphertext block (CBC mode) or last counter (CTR mode). * This is used e.g. by the CTS mode. */ - memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, ivsize); + if (!ecode) + memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, + ivsize); qi_cache_free(edesc); skcipher_request_complete(req, ecode); @@ -1395,7 +1397,9 @@ static void skcipher_decrypt_done(void *cbk_ctx, u32 status) * ciphertext block (CBC mode) or last counter (CTR mode). * This is used e.g. by the CTS mode. */ - memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, ivsize); + if (!ecode) + memcpy(req->iv, (u8 *)&edesc->sgt[0] + edesc->qm_sg_bytes, + ivsize); qi_cache_free(edesc); skcipher_request_complete(req, ecode); -- GitLab From 836d8f43c5e529935bb3140edc710c23ffd1d54a Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:05 +0300 Subject: [PATCH 2334/7155] crypto: caam - check key length Check key length to solve the extra tests that expect -EINVAL to be returned when the key size is not valid. Validated AES keylen for skcipher, ahash and aead. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/Kconfig | 2 + drivers/crypto/caam/caamalg.c | 125 ++++++++++++++++++------ drivers/crypto/caam/caamalg_qi.c | 130 +++++++++++++++++++------ drivers/crypto/caam/caamalg_qi2.c | 155 ++++++++++++++++++++++-------- drivers/crypto/caam/caamhash.c | 12 +++ 5 files changed, 324 insertions(+), 100 deletions(-) diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 3720ddabb507..e4fdf545ac90 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -111,6 +111,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI select CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER + select CRYPTO_DES help Selecting this will use CAAM Queue Interface (QI) for sending & receiving crypto jobs to/from CAAM. This gives better performance @@ -161,6 +162,7 @@ config CRYPTO_DEV_FSL_DPAA2_CAAM select CRYPTO_AUTHENC select CRYPTO_AEAD select CRYPTO_HASH + select CRYPTO_DES help CAAM driver for QorIQ Data Path Acceleration Architecture 2. It handles DPSECI DPAA2 objects that sit on the Management Complex diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 28d55a05b0f3..ce50ae1dc825 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -667,6 +667,13 @@ static int gcm_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; + int err; + + err = aes_check_keylen(keylen); + if (err) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } print_hex_dump_debug("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -683,9 +690,13 @@ static int rfc4106_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; + int err; - if (keylen < 4) - return -EINVAL; + err = aes_check_keylen(keylen - 4); + if (err) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } print_hex_dump_debug("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -707,9 +718,13 @@ static int rfc4543_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; + int err; - if (keylen < 4) - return -EINVAL; + err = aes_check_keylen(keylen - 4); + if (err) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } print_hex_dump_debug("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -727,7 +742,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, } static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, - unsigned int keylen) + unsigned int keylen, const u32 ctx1_iv_off) { struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); struct caam_skcipher_alg *alg = @@ -736,30 +751,10 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, struct device *jrdev = ctx->jrdev; unsigned int ivsize = crypto_skcipher_ivsize(skcipher); u32 *desc; - u32 ctx1_iv_off = 0; - const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == - OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; print_hex_dump_debug("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); - /* - * AES-CTR needs to load IV in CONTEXT1 reg - * at an offset of 128bits (16bytes) - * CONTEXT1[255:128] = IV - */ - if (ctr_mode) - ctx1_iv_off = 16; - - /* - * RFC3686 specific: - * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} - * | *key = {KEY, NONCE} - */ - if (is_rfc3686) { - ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; - keylen -= CTR_RFC3686_NONCE_SIZE; - } ctx->cdata.keylen = keylen; ctx->cdata.key_virt = key; @@ -782,6 +777,74 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, return 0; } +static int aes_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + int err; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, 0); +} + +static int rfc3686_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * RFC3686 specific: + * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} + * | *key = {KEY, NONCE} + */ + ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; + keylen -= CTR_RFC3686_NONCE_SIZE; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + +static int ctr_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * AES-CTR needs to load IV in CONTEXT1 reg + * at an offset of 128bits (16bytes) + * CONTEXT1[255:128] = IV + */ + ctx1_iv_off = 16; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + +static int arc4_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + return skcipher_setkey(skcipher, key, keylen, 0); +} + static int des_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { @@ -800,7 +863,7 @@ static int des_skcipher_setkey(struct crypto_skcipher *skcipher, return -EINVAL; } - return skcipher_setkey(skcipher, key, keylen); + return skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, @@ -1880,7 +1943,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-aes-caam", .cra_blocksize = AES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = aes_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1928,7 +1991,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ctr-aes-caam", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = ctr_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1946,7 +2009,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "rfc3686-ctr-aes-caam", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = rfc3686_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE + @@ -2000,7 +2063,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ecb-aes-caam", .cra_blocksize = AES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = aes_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -2030,7 +2093,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ecb-arc4-caam", .cra_blocksize = ARC4_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = arc4_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = ARC4_MIN_KEY_SIZE, diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 66531d6fbd0b..b8854f268e5a 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -385,6 +385,12 @@ static int gcm_setkey(struct crypto_aead *aead, struct device *jrdev = ctx->jrdev; int ret; + ret = aes_check_keylen(keylen); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } + print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -480,8 +486,11 @@ static int rfc4106_setkey(struct crypto_aead *aead, struct device *jrdev = ctx->jrdev; int ret; - if (keylen < 4) - return -EINVAL; + ret = aes_check_keylen(keylen - 4); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -582,8 +591,11 @@ static int rfc4543_setkey(struct crypto_aead *aead, struct device *jrdev = ctx->jrdev; int ret; - if (keylen < 4) - return -EINVAL; + ret = aes_check_keylen(keylen - 4); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -624,7 +636,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, } static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, - unsigned int keylen) + unsigned int keylen, const u32 ctx1_iv_off) { struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); struct caam_skcipher_alg *alg = @@ -632,33 +644,12 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, skcipher); struct device *jrdev = ctx->jrdev; unsigned int ivsize = crypto_skcipher_ivsize(skcipher); - u32 ctx1_iv_off = 0; - const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == - OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; int ret = 0; print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); - /* - * AES-CTR needs to load IV in CONTEXT1 reg - * at an offset of 128bits (16bytes) - * CONTEXT1[255:128] = IV - */ - if (ctr_mode) - ctx1_iv_off = 16; - - /* - * RFC3686 specific: - * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} - * | *key = {KEY, NONCE} - */ - if (is_rfc3686) { - ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; - keylen -= CTR_RFC3686_NONCE_SIZE; - } - ctx->cdata.keylen = keylen; ctx->cdata.key_virt = key; ctx->cdata.key_inline = true; @@ -694,11 +685,88 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, return -EINVAL; } +static int aes_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + int err; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, 0); +} + +static int rfc3686_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * RFC3686 specific: + * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} + * | *key = {KEY, NONCE} + */ + ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; + keylen -= CTR_RFC3686_NONCE_SIZE; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + +static int ctr_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * AES-CTR needs to load IV in CONTEXT1 reg + * at an offset of 128bits (16bytes) + * CONTEXT1[255:128] = IV + */ + ctx1_iv_off = 16; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + static int des3_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { return unlikely(des3_verify_key(skcipher, key)) ?: - skcipher_setkey(skcipher, key, keylen); + skcipher_setkey(skcipher, key, keylen, 0); +} + +static int des_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 tmp[DES_EXPKEY_WORDS]; + + if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) & + CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_WEAK_KEY); + return -EINVAL; + } + + return skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, @@ -1405,7 +1473,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-aes-caam-qi", .cra_blocksize = AES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = aes_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1437,7 +1505,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-des-caam-qi", .cra_blocksize = DES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = des_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES_KEY_SIZE, @@ -1453,7 +1521,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ctr-aes-caam-qi", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = ctr_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1471,7 +1539,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "rfc3686-ctr-aes-caam-qi", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = rfc3686_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE + diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index fcd8a488efc5..337150bdf3d1 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -732,7 +732,13 @@ static int gcm_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *dev = ctx->dev; + int ret; + ret = aes_check_keylen(keylen); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -818,9 +824,13 @@ static int rfc4106_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *dev = ctx->dev; + int ret; - if (keylen < 4) - return -EINVAL; + ret = aes_check_keylen(keylen - 4); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -912,9 +922,13 @@ static int rfc4543_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *dev = ctx->dev; + int ret; - if (keylen < 4) - return -EINVAL; + ret = aes_check_keylen(keylen - 4); + if (ret) { + crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); + return ret; + } print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); @@ -932,7 +946,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, } static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, - unsigned int keylen) + unsigned int keylen, const u32 ctx1_iv_off) { struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); struct caam_skcipher_alg *alg = @@ -942,34 +956,11 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, struct caam_flc *flc; unsigned int ivsize = crypto_skcipher_ivsize(skcipher); u32 *desc; - u32 ctx1_iv_off = 0; - const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == - OP_ALG_AAI_CTR_MOD128) && - ((ctx->cdata.algtype & OP_ALG_ALGSEL_MASK) != - OP_ALG_ALGSEL_CHACHA20); const bool is_rfc3686 = alg->caam.rfc3686; print_hex_dump_debug("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); - /* - * AES-CTR needs to load IV in CONTEXT1 reg - * at an offset of 128bits (16bytes) - * CONTEXT1[255:128] = IV - */ - if (ctr_mode) - ctx1_iv_off = 16; - - /* - * RFC3686 specific: - * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} - * | *key = {KEY, NONCE} - */ - if (is_rfc3686) { - ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; - keylen -= CTR_RFC3686_NONCE_SIZE; - } - ctx->cdata.keylen = keylen; ctx->cdata.key_virt = key; ctx->cdata.key_inline = true; @@ -997,11 +988,99 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, return 0; } -static int des3_skcipher_setkey(struct crypto_skcipher *skcipher, - const u8 *key, unsigned int keylen) +static int aes_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) { - return unlikely(des3_verify_key(skcipher, key)) ?: - skcipher_setkey(skcipher, key, keylen); + int err; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, 0); +} + +static int rfc3686_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * RFC3686 specific: + * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} + * | *key = {KEY, NONCE} + */ + ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; + keylen -= CTR_RFC3686_NONCE_SIZE; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + +static int ctr_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 ctx1_iv_off; + int err; + + /* + * AES-CTR needs to load IV in CONTEXT1 reg + * at an offset of 128bits (16bytes) + * CONTEXT1[255:128] = IV + */ + ctx1_iv_off = 16; + + err = aes_check_keylen(keylen); + if (err) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } + + return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off); +} + +static int chacha20_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + if (keylen != CHACHA_KEY_SIZE) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + return skcipher_setkey(skcipher, key, keylen, 0); +} + +static int des_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + u32 tmp[DES3_EDE_EXPKEY_WORDS]; + struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); + + if (keylen == DES3_EDE_KEY_SIZE && + __des3_ede_setkey(tmp, &tfm->crt_flags, key, DES3_EDE_KEY_SIZE)) { + return -EINVAL; + } + + if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) & + CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { + crypto_skcipher_set_flags(skcipher, + CRYPTO_TFM_RES_WEAK_KEY); + return -EINVAL; + } + + return skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, @@ -1535,7 +1614,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-aes-caam-qi2", .cra_blocksize = AES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = aes_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1551,7 +1630,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-3des-caam-qi2", .cra_blocksize = DES3_EDE_BLOCK_SIZE, }, - .setkey = des3_skcipher_setkey, + .setkey = des_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, @@ -1567,7 +1646,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-des-caam-qi2", .cra_blocksize = DES_BLOCK_SIZE, }, - .setkey = skcipher_setkey, + .setkey = des_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES_KEY_SIZE, @@ -1583,7 +1662,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ctr-aes-caam-qi2", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = ctr_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE, @@ -1601,7 +1680,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "rfc3686-ctr-aes-caam-qi2", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = rfc3686_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = AES_MIN_KEY_SIZE + @@ -1640,7 +1719,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "chacha20-caam-qi2", .cra_blocksize = 1, }, - .setkey = skcipher_setkey, + .setkey = chacha20_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = CHACHA_KEY_SIZE, diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 73abefa262ab..d6ef3c0d9b94 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -501,6 +501,11 @@ static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key, struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct device *jrdev = ctx->jrdev; + if (keylen != AES_KEYSIZE_128) { + crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + memcpy(ctx->key, key, keylen); dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE); ctx->adata.keylen = keylen; @@ -515,6 +520,13 @@ static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key, unsigned int keylen) { struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + int err; + + err = aes_check_keylen(keylen); + if (err) { + crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return err; + } /* key is immediate data for all cmac shared descriptors */ ctx->adata.key_virt = key; -- GitLab From 68a51394f37ae8c6eb51209efc406355a9861874 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:06 +0300 Subject: [PATCH 2335/7155] crypto: caam - check authsize Check authsize to solve the extra tests that expect -EINVAL to be returned when the authentication tag size is not valid. Validated authsize for GCM, RFC4106 and RFC4543. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 13 +++++++++++++ drivers/crypto/caam/caamalg_qi.c | 13 +++++++++++++ drivers/crypto/caam/caamalg_qi2.c | 13 +++++++++++++ 3 files changed, 39 insertions(+) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index ce50ae1dc825..591906988a22 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -376,6 +376,11 @@ static int gcm_set_sh_desc(struct crypto_aead *aead) static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_gcm_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; gcm_set_sh_desc(authenc); @@ -439,6 +444,11 @@ static int rfc4106_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_rfc4106_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; rfc4106_set_sh_desc(authenc); @@ -503,6 +513,9 @@ static int rfc4543_setauthsize(struct crypto_aead *authenc, { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + if (authsize != 16) + return -EINVAL; + ctx->authsize = authsize; rfc4543_set_sh_desc(authenc); diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index b8854f268e5a..6c69f54d1f79 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -371,6 +371,11 @@ static int gcm_set_sh_desc(struct crypto_aead *aead) static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_gcm_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; gcm_set_sh_desc(authenc); @@ -472,6 +477,11 @@ static int rfc4106_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_rfc4106_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; rfc4106_set_sh_desc(authenc); @@ -578,6 +588,9 @@ static int rfc4543_setauthsize(struct crypto_aead *authenc, { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + if (authsize != 16) + return -EINVAL; + ctx->authsize = authsize; rfc4543_set_sh_desc(authenc); diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 337150bdf3d1..141d6231e4b9 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -720,6 +720,11 @@ static int gcm_set_sh_desc(struct crypto_aead *aead) static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_gcm_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; gcm_set_sh_desc(authenc); @@ -812,6 +817,11 @@ static int rfc4106_setauthsize(struct crypto_aead *authenc, unsigned int authsize) { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + int err; + + err = crypto_rfc4106_check_authsize(authsize); + if (err) + return err; ctx->authsize = authsize; rfc4106_set_sh_desc(authenc); @@ -911,6 +921,9 @@ static int rfc4543_setauthsize(struct crypto_aead *authenc, { struct caam_ctx *ctx = crypto_aead_ctx(authenc); + if (authsize != 16) + return -EINVAL; + ctx->authsize = authsize; rfc4543_set_sh_desc(authenc); -- GitLab From fcd23ed57c4cccda17b0be736cdfbd7970b842c8 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:07 +0300 Subject: [PATCH 2336/7155] crypto: caam - check assoclen Check assoclen to solve the extra tests that expect -EINVAL to be returned when the associated data size is not valid. Validated assoclen for RFC4106 and RFC4543 which expects an assoclen of 16 or 20. Based on seqiv, IPsec ESP and RFC4543/RFC4106 the assoclen is sizeof IP Header (spi, seq_no, extended seq_no) and IV len. This can be 16 or 20 bytes. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 10 ++-------- drivers/crypto/caam/caamalg_qi.c | 12 ++++-------- drivers/crypto/caam/caamalg_qi2.c | 10 ++-------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 591906988a22..f832491a6bd9 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -1598,10 +1598,7 @@ static int chachapoly_decrypt(struct aead_request *req) static int ipsec_gcm_encrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return gcm_encrypt(req); + return crypto_ipsec_check_assoclen(req->assoclen) ? : gcm_encrypt(req); } static int aead_encrypt(struct aead_request *req) @@ -1675,10 +1672,7 @@ static int gcm_decrypt(struct aead_request *req) static int ipsec_gcm_decrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return gcm_decrypt(req); + return crypto_ipsec_check_assoclen(req->assoclen) ? : gcm_decrypt(req); } static int aead_decrypt(struct aead_request *req) diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 6c69f54d1f79..215802017d53 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -1237,18 +1237,14 @@ static int aead_decrypt(struct aead_request *req) static int ipsec_gcm_encrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return aead_crypt(req, true); + return crypto_ipsec_check_assoclen(req->assoclen) ? : aead_crypt(req, + true); } static int ipsec_gcm_decrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return aead_crypt(req, false); + return crypto_ipsec_check_assoclen(req->assoclen) ? : aead_crypt(req, + false); } static void skcipher_done(struct caam_drv_req *drv_req, u32 status) diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 141d6231e4b9..7350142050cc 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -1407,18 +1407,12 @@ static int aead_decrypt(struct aead_request *req) static int ipsec_gcm_encrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return aead_encrypt(req); + return crypto_ipsec_check_assoclen(req->assoclen) ? : aead_encrypt(req); } static int ipsec_gcm_decrypt(struct aead_request *req) { - if (req->assoclen < 8) - return -EINVAL; - - return aead_decrypt(req); + return crypto_ipsec_check_assoclen(req->assoclen) ? : aead_decrypt(req); } static void skcipher_encrypt_done(void *cbk_ctx, u32 status) -- GitLab From 31bb2f0da1b5099732337d9ecef792ab67970ddf Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:08 +0300 Subject: [PATCH 2337/7155] crypto: caam - check zero-length input Check zero-length input, for skcipher algorithm, to solve the extra tests. This is a valid operation, therefore the API will return no error. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 6 ++++++ drivers/crypto/caam/caamalg_qi.c | 3 +++ drivers/crypto/caam/caamalg_qi2.c | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index f832491a6bd9..21e30ded365a 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -1884,6 +1884,9 @@ static int skcipher_encrypt(struct skcipher_request *req) u32 *desc; int ret = 0; + if (!req->cryptlen) + return 0; + /* allocate extended descriptor */ edesc = skcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ); if (IS_ERR(edesc)) @@ -1918,6 +1921,9 @@ static int skcipher_decrypt(struct skcipher_request *req) u32 *desc; int ret = 0; + if (!req->cryptlen) + return 0; + /* allocate extended descriptor */ edesc = skcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ); if (IS_ERR(edesc)) diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 215802017d53..e63b2f719695 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -1445,6 +1445,9 @@ static inline int skcipher_crypt(struct skcipher_request *req, bool encrypt) struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); int ret; + if (!req->cryptlen) + return 0; + if (unlikely(caam_congested)) return -EAGAIN; diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 7350142050cc..63a86b6b8b96 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -1499,6 +1499,9 @@ static int skcipher_encrypt(struct skcipher_request *req) struct caam_request *caam_req = skcipher_request_ctx(req); int ret; + if (!req->cryptlen) + return 0; + /* allocate extended descriptor */ edesc = skcipher_edesc_alloc(req); if (IS_ERR(edesc)) @@ -1527,6 +1530,8 @@ static int skcipher_decrypt(struct skcipher_request *req) struct caam_request *caam_req = skcipher_request_ctx(req); int ret; + if (!req->cryptlen) + return 0; /* allocate extended descriptor */ edesc = skcipher_edesc_alloc(req); if (IS_ERR(edesc)) -- GitLab From d28a43edf3caff971b58d75c83ad00487152e448 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:09 +0300 Subject: [PATCH 2338/7155] crypto: caam - update rfc4106 sh desc to support zero length input Update share descriptor for rfc4106 to skip instructions in case cryptlen is zero. If no instructions are jumped the DECO hangs and a timeout error is thrown. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_desc.c | 47 ++++++++++++++++++++---------- drivers/crypto/caam/caamalg_desc.h | 2 +- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/caam/caamalg_desc.c b/drivers/crypto/caam/caamalg_desc.c index 28ecef7a481c..aa9ccca67045 100644 --- a/drivers/crypto/caam/caamalg_desc.c +++ b/drivers/crypto/caam/caamalg_desc.c @@ -852,13 +852,16 @@ EXPORT_SYMBOL(cnstr_shdsc_gcm_decap); * @ivsize: initialization vector size * @icvsize: integrity check value (ICV) size (truncated or full) * @is_qi: true when called from caam/qi + * + * Input sequence: AAD | PTXT + * Output sequence: AAD | CTXT | ICV + * AAD length (assoclen), which includes the IV length, is available in Math3. */ void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata, unsigned int ivsize, unsigned int icvsize, const bool is_qi) { - u32 *key_jump_cmd; - + u32 *key_jump_cmd, *zero_cryptlen_jump_cmd, *skip_instructions; init_sh_desc(desc, HDR_SHARE_SERIAL); /* Skip key loading if it is loaded due to sharing */ @@ -901,24 +904,26 @@ void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata, append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, ivsize); append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); - /* Read assoc data */ - append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | - FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1); + /* Skip AAD */ + append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); - /* Skip IV */ - append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_SKIP); + /* Read cryptlen and set this value into VARSEQOUTLEN */ + append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG3, CAAM_CMD_SZ); - /* Will read cryptlen bytes */ - append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + /* If cryptlen is ZERO jump to AAD command */ + zero_cryptlen_jump_cmd = append_jump(desc, JUMP_TEST_ALL | + JUMP_COND_MATH_Z); - /* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */ - append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG); + /* Read AAD data */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | + FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1); - /* Skip assoc data */ - append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); + /* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */ + append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA); - /* cryptlen = seqoutlen - assoclen */ - append_math_sub(desc, VARSEQOUTLEN, VARSEQINLEN, REG0, CAAM_CMD_SZ); + /* Skip IV */ + append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_SKIP); + append_math_add(desc, VARSEQINLEN, VARSEQOUTLEN, REG0, CAAM_CMD_SZ); /* Write encrypted data */ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF); @@ -927,6 +932,18 @@ void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata, append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); + /* Jump instructions to avoid double reading of AAD */ + skip_instructions = append_jump(desc, JUMP_TEST_ALL); + + /* There is no input data, cryptlen = 0 */ + set_jump_tgt_here(desc, zero_cryptlen_jump_cmd); + + /* Read AAD */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | + FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1); + + set_jump_tgt_here(desc, skip_instructions); + /* Write ICV */ append_seq_store(desc, icvsize, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT); diff --git a/drivers/crypto/caam/caamalg_desc.h b/drivers/crypto/caam/caamalg_desc.h index 706007624d82..f2893393ba5e 100644 --- a/drivers/crypto/caam/caamalg_desc.h +++ b/drivers/crypto/caam/caamalg_desc.h @@ -31,7 +31,7 @@ #define DESC_QI_GCM_DEC_LEN (DESC_GCM_DEC_LEN + 3 * CAAM_CMD_SZ) #define DESC_RFC4106_BASE (3 * CAAM_CMD_SZ) -#define DESC_RFC4106_ENC_LEN (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ) +#define DESC_RFC4106_ENC_LEN (DESC_RFC4106_BASE + 16 * CAAM_CMD_SZ) #define DESC_RFC4106_DEC_LEN (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ) #define DESC_QI_RFC4106_ENC_LEN (DESC_RFC4106_ENC_LEN + 5 * CAAM_CMD_SZ) #define DESC_QI_RFC4106_DEC_LEN (DESC_RFC4106_DEC_LEN + 5 * CAAM_CMD_SZ) -- GitLab From a2fb864c042b00debc7696d4459d8058ec7c8013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 31 Jul 2019 16:08:10 +0300 Subject: [PATCH 2339/7155] crypto: caam - keep both virtual and dma key addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update alginfo struct to keep both virtual and dma key addresses, so that descriptors have them at hand. One example where this is needed is in the xcbc(aes) shared descriptors, which are updated in current patch. Another example is the upcoming fix for DKP. Signed-off-by: Horia Geantă Reviewed-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamhash.c | 37 +++++++++++++---------------- drivers/crypto/caam/caamhash_desc.c | 5 ++-- drivers/crypto/caam/caamhash_desc.h | 2 +- drivers/crypto/caam/desc_constr.h | 10 ++++---- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index d6ef3c0d9b94..d19373e6ed4a 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -95,7 +95,6 @@ struct caam_hash_ctx { dma_addr_t sh_desc_update_first_dma; dma_addr_t sh_desc_fin_dma; dma_addr_t sh_desc_digest_dma; - dma_addr_t key_dma; enum dma_data_direction dir; struct device *jrdev; int ctx_len; @@ -282,13 +281,10 @@ static int axcbc_set_sh_desc(struct crypto_ahash *ahash) struct device *jrdev = ctx->jrdev; u32 *desc; - /* key is loaded from memory for UPDATE and FINALIZE states */ - ctx->adata.key_dma = ctx->key_dma; - /* shared descriptor for ahash_update */ desc = ctx->sh_desc_update; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE, - ctx->ctx_len, ctx->ctx_len, 0); + ctx->ctx_len, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ", @@ -298,7 +294,7 @@ static int axcbc_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for ahash_{final,finup} */ desc = ctx->sh_desc_fin; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, - digestsize, ctx->ctx_len, 0); + digestsize, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ", @@ -311,7 +307,7 @@ static int axcbc_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for first invocation of ahash_update */ desc = ctx->sh_desc_update_first; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, - ctx->ctx_len, ctx->key_dma); + ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__) @@ -321,7 +317,7 @@ static int axcbc_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for ahash_digest */ desc = ctx->sh_desc_digest; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, - digestsize, ctx->ctx_len, 0); + digestsize, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ", @@ -340,7 +336,7 @@ static int acmac_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for ahash_update */ desc = ctx->sh_desc_update; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE, - ctx->ctx_len, ctx->ctx_len, 0); + ctx->ctx_len, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ", @@ -350,7 +346,7 @@ static int acmac_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for ahash_{final,finup} */ desc = ctx->sh_desc_fin; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, - digestsize, ctx->ctx_len, 0); + digestsize, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ", @@ -360,7 +356,7 @@ static int acmac_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for first invocation of ahash_update */ desc = ctx->sh_desc_update_first; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, - ctx->ctx_len, 0); + ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__) @@ -370,7 +366,7 @@ static int acmac_set_sh_desc(struct crypto_ahash *ahash) /* shared descriptor for ahash_digest */ desc = ctx->sh_desc_digest; cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, - digestsize, ctx->ctx_len, 0); + digestsize, ctx->ctx_len); dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, desc_bytes(desc), ctx->dir); print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ", @@ -507,7 +503,8 @@ static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key, } memcpy(ctx->key, key, keylen); - dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE); + dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen, + DMA_TO_DEVICE); ctx->adata.keylen = keylen; print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ", @@ -1831,11 +1828,11 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type; ctx->ctx_len = 48; - ctx->key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key, - ARRAY_SIZE(ctx->key), - DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC); - if (dma_mapping_error(ctx->jrdev, ctx->key_dma)) { + ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key, + ARRAY_SIZE(ctx->key), + DMA_BIDIRECTIONAL, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) { dev_err(ctx->jrdev, "unable to map key\n"); caam_jr_free(ctx->jrdev); return -ENOMEM; @@ -1859,7 +1856,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) dev_err(ctx->jrdev, "unable to map shared descriptors\n"); if (is_xcbc_aes(caam_hash->alg_type)) - dma_unmap_single_attrs(ctx->jrdev, ctx->key_dma, + dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, ARRAY_SIZE(ctx->key), DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); @@ -1895,7 +1892,7 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm) offsetof(struct caam_hash_ctx, key), ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); if (is_xcbc_aes(ctx->adata.algtype)) - dma_unmap_single_attrs(ctx->jrdev, ctx->key_dma, + dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, ARRAY_SIZE(ctx->key), DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); caam_jr_free(ctx->jrdev); diff --git a/drivers/crypto/caam/caamhash_desc.c b/drivers/crypto/caam/caamhash_desc.c index 71d018343ee4..78383d77da99 100644 --- a/drivers/crypto/caam/caamhash_desc.c +++ b/drivers/crypto/caam/caamhash_desc.c @@ -83,10 +83,9 @@ EXPORT_SYMBOL(cnstr_shdsc_ahash); * @state: algorithm state OP_ALG_AS_{INIT, FINALIZE, INITFINALIZE, UPDATE} * @digestsize: algorithm's digest size * @ctx_len: size of Context Register - * @key_dma: I/O Virtual Address of the key */ void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state, - int digestsize, int ctx_len, dma_addr_t key_dma) + int digestsize, int ctx_len) { u32 *skip_key_load; @@ -136,7 +135,7 @@ void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state, LDST_SRCDST_BYTE_CONTEXT); if (is_xcbc_aes(adata->algtype) && state == OP_ALG_AS_INIT) /* Save K1 */ - append_fifo_store(desc, key_dma, adata->keylen, + append_fifo_store(desc, adata->key_dma, adata->keylen, LDST_CLASS_1_CCB | FIFOST_TYPE_KEY_KEK); } EXPORT_SYMBOL(cnstr_shdsc_sk_hash); diff --git a/drivers/crypto/caam/caamhash_desc.h b/drivers/crypto/caam/caamhash_desc.h index 6947ee1f200c..4f369b8cb6ae 100644 --- a/drivers/crypto/caam/caamhash_desc.h +++ b/drivers/crypto/caam/caamhash_desc.h @@ -25,5 +25,5 @@ void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state, int digestsize, int ctx_len, bool import_ctx, int era); void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state, - int digestsize, int ctx_len, dma_addr_t key_dma); + int digestsize, int ctx_len); #endif /* _CAAMHASH_DESC_H_ */ diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h index 5988a26a2441..815417411a18 100644 --- a/drivers/crypto/caam/desc_constr.h +++ b/drivers/crypto/caam/desc_constr.h @@ -457,8 +457,8 @@ do { \ * functions where it is used. * @keylen: length of the provided algorithm key, in bytes * @keylen_pad: padded length of the provided algorithm key, in bytes - * @key: address where algorithm key resides; virtual address if key_inline - * is true, dma (bus) address if key_inline is false. + * @key_dma: dma (bus) address where algorithm key resides + * @key_virt: virtual address where algorithm key resides * @key_inline: true - key can be inlined in the descriptor; false - key is * referenced by the descriptor */ @@ -466,10 +466,8 @@ struct alginfo { u32 algtype; unsigned int keylen; unsigned int keylen_pad; - union { - dma_addr_t key_dma; - const void *key_virt; - }; + dma_addr_t key_dma; + const void *key_virt; bool key_inline; }; -- GitLab From e9b4913a5f944b23d6109c44b6f3fc6e092e30ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 31 Jul 2019 16:08:11 +0300 Subject: [PATCH 2340/7155] crypto: caam - fix MDHA key derivation for certain user key lengths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fuzz testing uncovered an issue when |user key| > |derived key|. Derived key generation has to be fixed in two cases: 1. Era >= 6 (DKP is available) DKP cannot be used with immediate input key if |user key| > |derived key|, since the resulting descriptor (after DKP execution) would be invalid - having a few bytes from user key left in descriptor buffer as incorrect opcodes. Fix DKP usage both in standalone hmac and in authenc algorithms. For authenc the logic is simplified, by always storing both virtual and dma key addresses. 2. Era < 6 The same case (|user key| > |derived key|) fails when DKP is not available. Make sure gen_split_key() dma maps max(|user key|, |derived key|), since this is an in-place (bidirectional) operation. Signed-off-by: Horia Geantă Reviewed-by: Iuliana Prodan Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 42 ++++++------------- drivers/crypto/caam/caamalg_qi.c | 42 ++++++------------- drivers/crypto/caam/caamalg_qi2.c | 67 ++++++++++++++++++++++--------- drivers/crypto/caam/caamhash.c | 53 +++++++++++++++++------- drivers/crypto/caam/desc_constr.h | 24 ++++++++--- drivers/crypto/caam/key_gen.c | 9 +++-- 6 files changed, 132 insertions(+), 105 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 21e30ded365a..947ba8ef487a 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -205,6 +205,18 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ctx->cdata.keylen - CTR_RFC3686_NONCE_SIZE); } + /* + * In case |user key| > |derived key|, using DKP + * would result in invalid opcodes (last bytes of user key) in + * the resulting descriptor. Use DKP instead => both + * virtual and dma key addresses are needed. + */ + ctx->adata.key_virt = ctx->key; + ctx->adata.key_dma = ctx->key_dma; + + ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; + ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; + data_len[0] = ctx->adata.keylen_pad; data_len[1] = ctx->cdata.keylen; @@ -221,16 +233,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -253,16 +255,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -287,16 +279,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index e63b2f719695..59b59f5e9550 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -105,6 +105,18 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ctx->cdata.keylen - CTR_RFC3686_NONCE_SIZE); } + /* + * In case |user key| > |derived key|, using DKP would result + * in invalid opcodes (last bytes of user key) in the resulting + * descriptor. Use DKP instead => both virtual and dma key + * addresses are needed. + */ + ctx->adata.key_virt = ctx->key; + ctx->adata.key_dma = ctx->key_dma; + + ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; + ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; + data_len[0] = ctx->adata.keylen_pad; data_len[1] = ctx->cdata.keylen; @@ -118,16 +130,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -143,16 +145,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -171,16 +163,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 63a86b6b8b96..bd01bcd799e8 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -199,6 +199,18 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ctx->cdata.keylen - CTR_RFC3686_NONCE_SIZE); } + /* + * In case |user key| > |derived key|, using DKP would result + * in invalid opcodes (last bytes of user key) in the resulting + * descriptor. Use DKP instead => both virtual and dma key + * addresses are needed. + */ + ctx->adata.key_virt = ctx->key; + ctx->adata.key_dma = ctx->key_dma; + + ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; + ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; + data_len[0] = ctx->adata.keylen_pad; data_len[1] = ctx->cdata.keylen; @@ -210,16 +222,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -248,16 +250,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead) ARRAY_SIZE(data_len)) < 0) return -EINVAL; - if (inl_mask & 1) - ctx->adata.key_virt = ctx->key; - else - ctx->adata.key_dma = ctx->key_dma; - - if (inl_mask & 2) - ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; - else - ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; - ctx->adata.key_inline = !!(inl_mask & 1); ctx->cdata.key_inline = !!(inl_mask & 2); @@ -2999,6 +2991,7 @@ enum hash_optype { /** * caam_hash_ctx - ahash per-session context * @flc: Flow Contexts array + * @key: authentication key * @flc_dma: I/O virtual addresses of the Flow Contexts * @dev: dpseci device * @ctx_len: size of Context Register @@ -3006,6 +2999,7 @@ enum hash_optype { */ struct caam_hash_ctx { struct caam_flc flc[HASH_NUM_OP]; + u8 key[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; dma_addr_t flc_dma[HASH_NUM_OP]; struct device *dev; int ctx_len; @@ -3306,6 +3300,19 @@ static int ahash_setkey(struct crypto_ahash *ahash, const u8 *key, ctx->adata.key_virt = key; ctx->adata.key_inline = true; + /* + * In case |user key| > |derived key|, using DKP would result + * in invalid opcodes (last bytes of user key) in the resulting + * descriptor. Use DKP instead => both virtual and dma key + * addresses are needed. + */ + if (keylen > ctx->adata.keylen_pad) { + memcpy(ctx->key, key, keylen); + dma_sync_single_for_device(ctx->dev, ctx->adata.key_dma, + ctx->adata.keylen_pad, + DMA_TO_DEVICE); + } + ret = ahash_set_sh_desc(ahash); kfree(hashed_key); return ret; @@ -4536,11 +4543,27 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) ctx->dev = caam_hash->dev; + if (alg->setkey) { + ctx->adata.key_dma = dma_map_single_attrs(ctx->dev, ctx->key, + ARRAY_SIZE(ctx->key), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->dev, ctx->adata.key_dma)) { + dev_err(ctx->dev, "unable to map key\n"); + return -ENOMEM; + } + } + dma_addr = dma_map_single_attrs(ctx->dev, ctx->flc, sizeof(ctx->flc), DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); if (dma_mapping_error(ctx->dev, dma_addr)) { dev_err(ctx->dev, "unable to map shared descriptors\n"); + if (ctx->adata.key_dma) + dma_unmap_single_attrs(ctx->dev, ctx->adata.key_dma, + ARRAY_SIZE(ctx->key), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); return -ENOMEM; } @@ -4566,6 +4589,10 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm) dma_unmap_single_attrs(ctx->dev, ctx->flc_dma[0], sizeof(ctx->flc), DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); + if (ctx->adata.key_dma) + dma_unmap_single_attrs(ctx->dev, ctx->adata.key_dma, + ARRAY_SIZE(ctx->key), DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); } static struct caam_hash_alg *caam_hash_alloc(struct device *dev, diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index d19373e6ed4a..ed1931f97df1 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -96,6 +96,7 @@ struct caam_hash_ctx { dma_addr_t sh_desc_fin_dma; dma_addr_t sh_desc_digest_dma; enum dma_data_direction dir; + enum dma_data_direction key_dir; struct device *jrdev; int ctx_len; struct alginfo adata; @@ -476,6 +477,18 @@ static int ahash_setkey(struct crypto_ahash *ahash, goto bad_free_key; memcpy(ctx->key, key, keylen); + + /* + * In case |user key| > |derived key|, using DKP + * would result in invalid opcodes (last bytes of user key) in + * the resulting descriptor. Use DKP instead => both + * virtual and dma key addresses are needed. + */ + if (keylen > ctx->adata.keylen_pad) + dma_sync_single_for_device(ctx->jrdev, + ctx->adata.key_dma, + ctx->adata.keylen_pad, + DMA_TO_DEVICE); } else { ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key, keylen, CAAM_MAX_HASH_KEY_SIZE); @@ -1825,40 +1838,50 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) if (is_xcbc_aes(caam_hash->alg_type)) { ctx->dir = DMA_TO_DEVICE; + ctx->key_dir = DMA_BIDIRECTIONAL; ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type; ctx->ctx_len = 48; - - ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key, - ARRAY_SIZE(ctx->key), - DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC); - if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) { - dev_err(ctx->jrdev, "unable to map key\n"); - caam_jr_free(ctx->jrdev); - return -ENOMEM; - } } else if (is_cmac_aes(caam_hash->alg_type)) { ctx->dir = DMA_TO_DEVICE; + ctx->key_dir = DMA_NONE; ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type; ctx->ctx_len = 32; } else { - ctx->dir = priv->era >= 6 ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; + if (priv->era >= 6) { + ctx->dir = DMA_BIDIRECTIONAL; + ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE; + } else { + ctx->dir = DMA_TO_DEVICE; + ctx->key_dir = DMA_NONE; + } ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; ctx->ctx_len = runninglen[(ctx->adata.algtype & OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT]; } + if (ctx->key_dir != DMA_NONE) { + ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key, + ARRAY_SIZE(ctx->key), + ctx->key_dir, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) { + dev_err(ctx->jrdev, "unable to map key\n"); + caam_jr_free(ctx->jrdev); + return -ENOMEM; + } + } + dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update, offsetof(struct caam_hash_ctx, key), ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); if (dma_mapping_error(ctx->jrdev, dma_addr)) { dev_err(ctx->jrdev, "unable to map shared descriptors\n"); - if (is_xcbc_aes(caam_hash->alg_type)) + if (ctx->key_dir != DMA_NONE) dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, ARRAY_SIZE(ctx->key), - DMA_BIDIRECTIONAL, + ctx->key_dir, DMA_ATTR_SKIP_CPU_SYNC); caam_jr_free(ctx->jrdev); @@ -1891,9 +1914,9 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm) dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma, offsetof(struct caam_hash_ctx, key), ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); - if (is_xcbc_aes(ctx->adata.algtype)) + if (ctx->key_dir != DMA_NONE) dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, - ARRAY_SIZE(ctx->key), DMA_BIDIRECTIONAL, + ARRAY_SIZE(ctx->key), ctx->key_dir, DMA_ATTR_SKIP_CPU_SYNC); caam_jr_free(ctx->jrdev); } diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h index 815417411a18..536f360bf131 100644 --- a/drivers/crypto/caam/desc_constr.h +++ b/drivers/crypto/caam/desc_constr.h @@ -533,14 +533,26 @@ static inline void append_proto_dkp(u32 * const desc, struct alginfo *adata) if (adata->key_inline) { int words; - append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | - OP_PCL_DKP_SRC_IMM | OP_PCL_DKP_DST_IMM | - adata->keylen); - append_data(desc, adata->key_virt, adata->keylen); + if (adata->keylen > adata->keylen_pad) { + append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | + OP_PCL_DKP_SRC_PTR | + OP_PCL_DKP_DST_IMM | adata->keylen); + append_ptr(desc, adata->key_dma); + + words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - + CAAM_PTR_SZ) / CAAM_CMD_SZ; + } else { + append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | + OP_PCL_DKP_SRC_IMM | + OP_PCL_DKP_DST_IMM | adata->keylen); + append_data(desc, adata->key_virt, adata->keylen); + + words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - + ALIGN(adata->keylen, CAAM_CMD_SZ)) / + CAAM_CMD_SZ; + } /* Reserve space in descriptor buffer for the derived key */ - words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - - ALIGN(adata->keylen, CAAM_CMD_SZ)) / CAAM_CMD_SZ; if (words) (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words); } else { diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index c6f8375ae215..5a851ddc48fb 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -48,18 +48,20 @@ int gen_split_key(struct device *jrdev, u8 *key_out, u32 *desc; struct split_key_result result; dma_addr_t dma_addr; + unsigned int local_max; int ret = -ENOMEM; adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK); adata->keylen_pad = split_key_pad_len(adata->algtype & OP_ALG_ALGSEL_MASK); + local_max = max(keylen, adata->keylen_pad); dev_dbg(jrdev, "split keylen %d split keylen padded %d\n", adata->keylen, adata->keylen_pad); print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); - if (adata->keylen_pad > max_keylen) + if (local_max > max_keylen) return -EINVAL; desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); @@ -70,8 +72,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, memcpy(key_out, key_in, keylen); - dma_addr = dma_map_single(jrdev, key_out, adata->keylen_pad, - DMA_BIDIRECTIONAL); + dma_addr = dma_map_single(jrdev, key_out, local_max, DMA_BIDIRECTIONAL); if (dma_mapping_error(jrdev, dma_addr)) { dev_err(jrdev, "unable to map key memory\n"); goto out_free; @@ -117,7 +118,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, adata->keylen_pad, 1); } - dma_unmap_single(jrdev, dma_addr, adata->keylen_pad, DMA_BIDIRECTIONAL); + dma_unmap_single(jrdev, dma_addr, local_max, DMA_BIDIRECTIONAL); out_free: kfree(desc); return ret; -- GitLab From c59a1d41672a89b5cac49db1a472ff889e35a2d2 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:12 +0300 Subject: [PATCH 2341/7155] crypto: caam - free resources in case caam_rng registration failed Check the return value of the hardware registration for caam_rng and free resources in case of failure. Fixes: e24f7c9e87d4 ("crypto: caam - hwrng support") Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamrng.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 561bcb535184..54c32d53760c 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -333,7 +333,10 @@ int caam_rng_init(struct device *ctrldev) goto free_rng_ctx; dev_info(dev, "registering rng-caam\n"); - return hwrng_register(&caam_rng); + + err = hwrng_register(&caam_rng); + if (!err) + return err; free_rng_ctx: kfree(rng_ctx); -- GitLab From 4e3a61c55b8c5db9bfaaf1fc1f448f8f874f66eb Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:13 +0300 Subject: [PATCH 2342/7155] crypto: caam - execute module exit point only if necessary Commit 1b46c90c8e00 ("crypto: caam - convert top level drivers to libraries") changed entry and exit points behavior for caamalg, caamalg_qi, caamalg_qi2, caamhash, caampkc, caamrng. For example, previously caam_pkc_init() and caam_pkc_exit() were module entry/exit points. This means that if an error would happen in caam_pkc_init(), then caam_pkc_exit() wouldn't have been called. After the mentioned commit, caam_pkc_init() and caam_pkc_exit() are manually called - from jr.c. caam_pkc_exit() is called unconditionally, even if caam_pkc_init() failed. Added a global variable to keep the status of the algorithm registration and free of resources. The exit point of caampkc/caamrng module is executed only if the registration was successful. Therefore we avoid double free of resources in case the algorithm registration failed. Fixes: 1b46c90c8e00 ("crypto: caam - convert top level drivers to libraries") Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caampkc.c | 11 +++++++++++ drivers/crypto/caam/caamrng.c | 14 +++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index e05d975da582..e00a4701b950 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -29,6 +29,12 @@ /* buffer filled with zeros, used for padding */ static u8 *zero_buffer; +/* + * variable used to avoid double free of resources in case + * algorithm registration was unsuccessful + */ +static bool init_done; + static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc, struct akcipher_request *req) { @@ -1076,6 +1082,7 @@ int caam_pkc_init(struct device *ctrldev) struct caam_drv_private *priv = dev_get_drvdata(ctrldev); u32 pk_inst; int err; + init_done = false; /* Determine public key hardware accelerator presence. */ if (priv->era < 10) @@ -1100,6 +1107,7 @@ int caam_pkc_init(struct device *ctrldev) dev_warn(ctrldev, "%s alg registration failed\n", caam_rsa.base.cra_driver_name); } else { + init_done = true; dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n"); } @@ -1108,6 +1116,9 @@ int caam_pkc_init(struct device *ctrldev) void caam_pkc_exit(void) { + if (!init_done) + return; + kfree(zero_buffer); crypto_unregister_akcipher(&caam_rsa); } diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 54c32d53760c..7fbda1b08360 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -80,6 +80,12 @@ struct caam_rng_ctx { static struct caam_rng_ctx *rng_ctx; +/* + * Variable used to avoid double free of resources in case + * algorithm registration was unsuccessful + */ +static bool init_done; + static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd) { if (bd->addr) @@ -296,6 +302,9 @@ static struct hwrng caam_rng = { void caam_rng_exit(void) { + if (!init_done) + return; + caam_jr_free(rng_ctx->jrdev); hwrng_unregister(&caam_rng); kfree(rng_ctx); @@ -307,6 +316,7 @@ int caam_rng_init(struct device *ctrldev) u32 rng_inst; struct caam_drv_private *priv = dev_get_drvdata(ctrldev); int err; + init_done = false; /* Check for an instantiated RNG before registration */ if (priv->era < 10) @@ -335,8 +345,10 @@ int caam_rng_init(struct device *ctrldev) dev_info(dev, "registering rng-caam\n"); err = hwrng_register(&caam_rng); - if (!err) + if (!err) { + init_done = true; return err; + } free_rng_ctx: kfree(rng_ctx); -- GitLab From 58068cfc810c3b5cc8c25b0fab73c02625aeadf1 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:14 +0300 Subject: [PATCH 2343/7155] crypto: caam - unregister algorithm only if the registration succeeded To know if a registration succeeded added a new struct, caam_akcipher_alg, that keeps, also, the registration status. This status is updated in caam_pkc_init and verified in caam_pkc_exit to unregister an algorithm. Fixes: 1b46c90c8e00 ("crypto: caam - convert top level drivers to libraries") Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caampkc.c | 49 +++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index e00a4701b950..5b12b232ee5e 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -35,6 +35,11 @@ static u8 *zero_buffer; */ static bool init_done; +struct caam_akcipher_alg { + struct akcipher_alg akcipher; + bool registered; +}; + static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc, struct akcipher_request *req) { @@ -1058,22 +1063,24 @@ static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm) caam_jr_free(ctx->dev); } -static struct akcipher_alg caam_rsa = { - .encrypt = caam_rsa_enc, - .decrypt = caam_rsa_dec, - .set_pub_key = caam_rsa_set_pub_key, - .set_priv_key = caam_rsa_set_priv_key, - .max_size = caam_rsa_max_size, - .init = caam_rsa_init_tfm, - .exit = caam_rsa_exit_tfm, - .reqsize = sizeof(struct caam_rsa_req_ctx), - .base = { - .cra_name = "rsa", - .cra_driver_name = "rsa-caam", - .cra_priority = 3000, - .cra_module = THIS_MODULE, - .cra_ctxsize = sizeof(struct caam_rsa_ctx), - }, +static struct caam_akcipher_alg caam_rsa = { + .akcipher = { + .encrypt = caam_rsa_enc, + .decrypt = caam_rsa_dec, + .set_pub_key = caam_rsa_set_pub_key, + .set_priv_key = caam_rsa_set_priv_key, + .max_size = caam_rsa_max_size, + .init = caam_rsa_init_tfm, + .exit = caam_rsa_exit_tfm, + .reqsize = sizeof(struct caam_rsa_req_ctx), + .base = { + .cra_name = "rsa", + .cra_driver_name = "rsa-caam", + .cra_priority = 3000, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct caam_rsa_ctx), + }, + } }; /* Public Key Cryptography module initialization handler */ @@ -1101,13 +1108,15 @@ int caam_pkc_init(struct device *ctrldev) if (!zero_buffer) return -ENOMEM; - err = crypto_register_akcipher(&caam_rsa); + err = crypto_register_akcipher(&caam_rsa.akcipher); + if (err) { kfree(zero_buffer); dev_warn(ctrldev, "%s alg registration failed\n", - caam_rsa.base.cra_driver_name); + caam_rsa.akcipher.base.cra_driver_name); } else { init_done = true; + caam_rsa.registered = true; dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n"); } @@ -1119,6 +1128,8 @@ void caam_pkc_exit(void) if (!init_done) return; + if (caam_rsa.registered) + crypto_unregister_akcipher(&caam_rsa.akcipher); + kfree(zero_buffer); - crypto_unregister_akcipher(&caam_rsa); } -- GitLab From 0435d47e2627b76b6dfb59e2e95ffed7232bd0ed Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 31 Jul 2019 16:08:15 +0300 Subject: [PATCH 2344/7155] crypto: caam - change return value in case CAAM has no MDHA To be consistent with other CAAM modules, caamhash should return 0 instead of -ENODEV in case CAAM has no MDHA. Based on commit 1b46c90c8e00 ("crypto: caam - convert top level drivers to libraries") the value returned by entry point is never checked and the exit point is always executed. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamhash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index ed1931f97df1..8a07edb45dad 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -2007,7 +2007,7 @@ int caam_algapi_hash_init(struct device *ctrldev) * is not present. */ if (!md_inst) - return -ENODEV; + return 0; /* Limit digest size based on LP256 */ if (md_vid == CHA_VER_VID_MD_LP256) -- GitLab From d13dfae3cedd60072d448b7e382c86143a29cedc Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Aug 2019 13:13:51 +0200 Subject: [PATCH 2345/7155] crypto: engine - Reduce default RT priority The crypto engine initializes its kworker thread to FIFO-99 (when requesting RT priority), reduce this to FIFO-50. FIFO-99 is the very highest priority available to SCHED_FIFO and it not a suitable default; it would indicate the crypto work is the most important work on the machine. Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Herbert Xu --- crypto/crypto_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c index d7502ec37f20..055d17977280 100644 --- a/crypto/crypto_engine.c +++ b/crypto/crypto_engine.c @@ -425,7 +425,7 @@ EXPORT_SYMBOL_GPL(crypto_engine_stop); */ struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt) { - struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 }; struct crypto_engine *engine; if (!dev) -- GitLab From 263c9959c9376ec0217d6adc61222a53469eed3c Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:50 +0800 Subject: [PATCH 2346/7155] crypto: hisilicon - add queue management driver for HiSilicon QM module QM is a general IP used by HiSilicon accelerators. It provides a general PCIe interface for the CPU and the accelerator to share a group of queues. A QM integrated in an accelerator provides queue management service. Queues can be assigned to PF and VFs, and queues can be controlled by unified mailboxes and doorbells. Specific task request are descripted by specific description buffer, which will be controlled and pass to related accelerator IP by QM. This patch adds a QM driver used by the accelerator driver to access the QM hardware. Signed-off-by: Zhou Wang Signed-off-by: Kenneth Lee Signed-off-by: Shiju Jose Signed-off-by: Hao Fang Reviewed-by: Jonathan Cameron Reviewed-by: John Garry Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/Kconfig | 7 + drivers/crypto/hisilicon/Makefile | 1 + drivers/crypto/hisilicon/qm.c | 1550 +++++++++++++++++++++++++++++ drivers/crypto/hisilicon/qm.h | 182 ++++ 4 files changed, 1740 insertions(+) create mode 100644 drivers/crypto/hisilicon/qm.c create mode 100644 drivers/crypto/hisilicon/qm.h diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index 8ca9c503bcb0..b79be8dc78e7 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -12,3 +12,10 @@ config CRYPTO_DEV_HISI_SEC To compile this as a module, choose M here: the module will be called hisi_sec. + +config CRYPTO_DEV_HISI_QM + tristate + depends on ARM64 && PCI && PCI_MSI + help + HiSilicon accelerator engines use a common queue management + interface. Specific engine driver may use this module. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index 463f46ace182..05e9052e0f52 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/ +obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += qm.o diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c new file mode 100644 index 000000000000..c095d4747812 --- /dev/null +++ b/drivers/crypto/hisilicon/qm.c @@ -0,0 +1,1550 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ +#include +#include +#include +#include +#include +#include +#include +#include "qm.h" + +/* eq/aeq irq enable */ +#define QM_VF_AEQ_INT_SOURCE 0x0 +#define QM_VF_AEQ_INT_MASK 0x4 +#define QM_VF_EQ_INT_SOURCE 0x8 +#define QM_VF_EQ_INT_MASK 0xc +#define QM_IRQ_NUM_V1 1 +#define QM_IRQ_NUM_PF_V2 4 + +#define QM_EQ_EVENT_IRQ_VECTOR 0 +#define QM_AEQ_EVENT_IRQ_VECTOR 1 +#define QM_ABNORMAL_EVENT_IRQ_VECTOR 3 + +/* mailbox */ +#define QM_MB_CMD_SQC 0x0 +#define QM_MB_CMD_CQC 0x1 +#define QM_MB_CMD_EQC 0x2 +#define QM_MB_CMD_AEQC 0x3 +#define QM_MB_CMD_SQC_BT 0x4 +#define QM_MB_CMD_CQC_BT 0x5 +#define QM_MB_CMD_SQC_VFT_V2 0x6 + +#define QM_MB_CMD_SEND_BASE 0x300 +#define QM_MB_EVENT_SHIFT 8 +#define QM_MB_BUSY_SHIFT 13 +#define QM_MB_OP_SHIFT 14 +#define QM_MB_CMD_DATA_ADDR_L 0x304 +#define QM_MB_CMD_DATA_ADDR_H 0x308 + +/* sqc shift */ +#define QM_SQ_HOP_NUM_SHIFT 0 +#define QM_SQ_PAGE_SIZE_SHIFT 4 +#define QM_SQ_BUF_SIZE_SHIFT 8 +#define QM_SQ_SQE_SIZE_SHIFT 12 +#define QM_SQ_PRIORITY_SHIFT 0 +#define QM_SQ_ORDERS_SHIFT 4 +#define QM_SQ_TYPE_SHIFT 8 + +#define QM_SQ_TYPE_MASK GENMASK(3, 0) + +/* cqc shift */ +#define QM_CQ_HOP_NUM_SHIFT 0 +#define QM_CQ_PAGE_SIZE_SHIFT 4 +#define QM_CQ_BUF_SIZE_SHIFT 8 +#define QM_CQ_CQE_SIZE_SHIFT 12 +#define QM_CQ_PHASE_SHIFT 0 +#define QM_CQ_FLAG_SHIFT 1 + +#define QM_CQE_PHASE(cqe) ((cqe)->w7 & 0x1) +#define QM_QC_CQE_SIZE 4 + +/* eqc shift */ +#define QM_EQE_AEQE_SIZE (2UL << 12) +#define QM_EQC_PHASE_SHIFT 16 + +#define QM_EQE_PHASE(eqe) (((eqe)->dw0 >> 16) & 0x1) +#define QM_EQE_CQN_MASK GENMASK(15, 0) + +#define QM_AEQE_PHASE(aeqe) (((aeqe)->dw0 >> 16) & 0x1) +#define QM_AEQE_TYPE_SHIFT 17 + +#define QM_DOORBELL_CMD_SQ 0 +#define QM_DOORBELL_CMD_CQ 1 +#define QM_DOORBELL_CMD_EQ 2 +#define QM_DOORBELL_CMD_AEQ 3 + +#define QM_DOORBELL_BASE_V1 0x340 +#define QM_DB_CMD_SHIFT_V1 16 +#define QM_DB_INDEX_SHIFT_V1 32 +#define QM_DB_PRIORITY_SHIFT_V1 48 +#define QM_DOORBELL_SQ_CQ_BASE_V2 0x1000 +#define QM_DOORBELL_EQ_AEQ_BASE_V2 0x2000 +#define QM_DB_CMD_SHIFT_V2 12 +#define QM_DB_RAND_SHIFT_V2 16 +#define QM_DB_INDEX_SHIFT_V2 32 +#define QM_DB_PRIORITY_SHIFT_V2 48 + +#define QM_MEM_START_INIT 0x100040 +#define QM_MEM_INIT_DONE 0x100044 +#define QM_VFT_CFG_RDY 0x10006c +#define QM_VFT_CFG_OP_WR 0x100058 +#define QM_VFT_CFG_TYPE 0x10005c +#define QM_SQC_VFT 0x0 +#define QM_CQC_VFT 0x1 +#define QM_VFT_CFG 0x100060 +#define QM_VFT_CFG_OP_ENABLE 0x100054 + +#define QM_VFT_CFG_DATA_L 0x100064 +#define QM_VFT_CFG_DATA_H 0x100068 +#define QM_SQC_VFT_BUF_SIZE (7ULL << 8) +#define QM_SQC_VFT_SQC_SIZE (5ULL << 12) +#define QM_SQC_VFT_INDEX_NUMBER (1ULL << 16) +#define QM_SQC_VFT_START_SQN_SHIFT 28 +#define QM_SQC_VFT_VALID (1ULL << 44) +#define QM_SQC_VFT_SQN_SHIFT 45 +#define QM_CQC_VFT_BUF_SIZE (7ULL << 8) +#define QM_CQC_VFT_SQC_SIZE (5ULL << 12) +#define QM_CQC_VFT_INDEX_NUMBER (1ULL << 16) +#define QM_CQC_VFT_VALID (1ULL << 28) + +#define QM_SQC_VFT_BASE_SHIFT_V2 28 +#define QM_SQC_VFT_BASE_MASK_V2 GENMASK(5, 0) +#define QM_SQC_VFT_NUM_SHIFT_V2 45 +#define QM_SQC_VFT_NUM_MASK_v2 GENMASK(9, 0) + + +#define QM_ABNORMAL_INT_SOURCE 0x100000 +#define QM_ABNORMAL_INT_MASK 0x100004 +#define QM_ABNORMAL_INT_MASK_VALUE 0x1fff +#define QM_ABNORMAL_INT_STATUS 0x100008 +#define QM_ABNORMAL_INF00 0x100010 +#define QM_FIFO_OVERFLOW_TYPE 0xc0 +#define QM_FIFO_OVERFLOW_TYPE_SHIFT 6 +#define QM_FIFO_OVERFLOW_VF 0x3f +#define QM_ABNORMAL_INF01 0x100014 +#define QM_DB_TIMEOUT_TYPE 0xc0 +#define QM_DB_TIMEOUT_TYPE_SHIFT 6 +#define QM_DB_TIMEOUT_VF 0x3f +#define QM_RAS_CE_ENABLE 0x1000ec +#define QM_RAS_FE_ENABLE 0x1000f0 +#define QM_RAS_NFE_ENABLE 0x1000f4 +#define QM_RAS_CE_THRESHOLD 0x1000f8 +#define QM_RAS_CE_TIMES_PER_IRQ 1 +#define QM_RAS_MSI_INT_SEL 0x1040f4 + +#define QM_CACHE_WB_START 0x204 +#define QM_CACHE_WB_DONE 0x208 + +#define PCI_BAR_2 2 +#define QM_SQE_DATA_ALIGN_MASK GENMASK(6, 0) +#define QMC_ALIGN(sz) ALIGN(sz, 32) + + +#define QM_MK_CQC_DW3_V1(hop_num, pg_sz, buf_sz, cqe_sz) \ + (((hop_num) << QM_CQ_HOP_NUM_SHIFT) | \ + ((pg_sz) << QM_CQ_PAGE_SIZE_SHIFT) | \ + ((buf_sz) << QM_CQ_BUF_SIZE_SHIFT) | \ + ((cqe_sz) << QM_CQ_CQE_SIZE_SHIFT)) + +#define QM_MK_CQC_DW3_V2(cqe_sz) \ + ((QM_Q_DEPTH - 1) | ((cqe_sz) << QM_CQ_CQE_SIZE_SHIFT)) + +#define QM_MK_SQC_W13(priority, orders, alg_type) \ + (((priority) << QM_SQ_PRIORITY_SHIFT) | \ + ((orders) << QM_SQ_ORDERS_SHIFT) | \ + (((alg_type) & QM_SQ_TYPE_MASK) << QM_SQ_TYPE_SHIFT)) + +#define QM_MK_SQC_DW3_V1(hop_num, pg_sz, buf_sz, sqe_sz) \ + (((hop_num) << QM_SQ_HOP_NUM_SHIFT) | \ + ((pg_sz) << QM_SQ_PAGE_SIZE_SHIFT) | \ + ((buf_sz) << QM_SQ_BUF_SIZE_SHIFT) | \ + ((u32)ilog2(sqe_sz) << QM_SQ_SQE_SIZE_SHIFT)) + +#define QM_MK_SQC_DW3_V2(sqe_sz) \ + ((QM_Q_DEPTH - 1) | ((u32)ilog2(sqe_sz) << QM_SQ_SQE_SIZE_SHIFT)) + +#define INIT_QC_COMMON(qc, base, pasid) do { \ + (qc)->head = 0; \ + (qc)->tail = 0; \ + (qc)->base_l = lower_32_bits(base); \ + (qc)->base_h = upper_32_bits(base); \ + (qc)->dw3 = 0; \ + (qc)->w8 = 0; \ + (qc)->rsvd0 = 0; \ + (qc)->pasid = pasid; \ + (qc)->w11 = 0; \ + (qc)->rsvd1 = 0; \ +} while (0) + +enum vft_type { + SQC_VFT = 0, + CQC_VFT, +}; + +struct qm_cqe { + __le32 rsvd0; + __le16 cmd_id; + __le16 rsvd1; + __le16 sq_head; + __le16 sq_num; + __le16 rsvd2; + __le16 w7; +}; + +struct qm_eqe { + __le32 dw0; +}; + +struct qm_aeqe { + __le32 dw0; +}; + +struct qm_sqc { + __le16 head; + __le16 tail; + __le32 base_l; + __le32 base_h; + __le32 dw3; + __le16 w8; + __le16 rsvd0; + __le16 pasid; + __le16 w11; + __le16 cq_num; + __le16 w13; + __le32 rsvd1; +}; + +struct qm_cqc { + __le16 head; + __le16 tail; + __le32 base_l; + __le32 base_h; + __le32 dw3; + __le16 w8; + __le16 rsvd0; + __le16 pasid; + __le16 w11; + __le32 dw6; + __le32 rsvd1; +}; + +struct qm_eqc { + __le16 head; + __le16 tail; + __le32 base_l; + __le32 base_h; + __le32 dw3; + __le32 rsvd[2]; + __le32 dw6; +}; + +struct qm_aeqc { + __le16 head; + __le16 tail; + __le32 base_l; + __le32 base_h; + __le32 dw3; + __le32 rsvd[2]; + __le32 dw6; +}; + +struct qm_mailbox { + __le16 w0; + __le16 queue_num; + __le32 base_l; + __le32 base_h; + __le32 rsvd; +}; + +struct qm_doorbell { + __le16 queue_num; + __le16 cmd; + __le16 index; + __le16 priority; +}; + +struct hisi_qm_hw_ops { + void (*qm_db)(struct hisi_qm *qm, u16 qn, + u8 cmd, u16 index, u8 priority); + u32 (*get_irq_num)(struct hisi_qm *qm); + void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, + u32 msi); + pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm); +}; + +struct hisi_qm_hw_error { + u32 int_msk; + const char *msg; +}; + +static const struct hisi_qm_hw_error qm_hw_error[] = { + { .int_msk = BIT(0), .msg = "qm_axi_rresp" }, + { .int_msk = BIT(1), .msg = "qm_axi_bresp" }, + { .int_msk = BIT(2), .msg = "qm_ecc_mbit" }, + { .int_msk = BIT(3), .msg = "qm_ecc_1bit" }, + { .int_msk = BIT(4), .msg = "qm_acc_get_task_timeout" }, + { .int_msk = BIT(5), .msg = "qm_acc_do_task_timeout" }, + { .int_msk = BIT(6), .msg = "qm_acc_wb_not_ready_timeout" }, + { .int_msk = BIT(7), .msg = "qm_sq_cq_vf_invalid" }, + { .int_msk = BIT(8), .msg = "qm_cq_vf_invalid" }, + { .int_msk = BIT(9), .msg = "qm_sq_vf_invalid" }, + { .int_msk = BIT(10), .msg = "qm_db_timeout" }, + { .int_msk = BIT(11), .msg = "qm_of_fifo_of" }, + { .int_msk = BIT(12), .msg = "qm_db_random_invalid" }, + { /* sentinel */ } +}; + +static const char * const qm_db_timeout[] = { + "sq", "cq", "eq", "aeq", +}; + +static const char * const qm_fifo_overflow[] = { + "cq", "eq", "aeq", +}; + +/* return 0 mailbox ready, -ETIMEDOUT hardware timeout */ +static int qm_wait_mb_ready(struct hisi_qm *qm) +{ + u32 val; + + return readl_relaxed_poll_timeout(qm->io_base + QM_MB_CMD_SEND_BASE, + val, !((val >> QM_MB_BUSY_SHIFT) & + 0x1), 10, 1000); +} + +/* 128 bit should be written to hardware at one time to trigger a mailbox */ +static void qm_mb_write(struct hisi_qm *qm, const void *src) +{ + void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE; + unsigned long tmp0 = 0, tmp1 = 0; + + asm volatile("ldp %0, %1, %3\n" + "stp %0, %1, %2\n" + "dsb sy\n" + : "=&r" (tmp0), + "=&r" (tmp1), + "+Q" (*((char *)fun_base)) + : "Q" (*((char *)src)) + : "memory"); +} + +static int qm_mb(struct hisi_qm *qm, u8 cmd, dma_addr_t dma_addr, u16 queue, + bool op) +{ + struct qm_mailbox mailbox; + int ret = 0; + + dev_dbg(&qm->pdev->dev, "QM mailbox request to q%u: %u-%llx\n", queue, + cmd, dma_addr); + + mailbox.w0 = cmd | + (op ? 0x1 << QM_MB_OP_SHIFT : 0) | + (0x1 << QM_MB_BUSY_SHIFT); + mailbox.queue_num = queue; + mailbox.base_l = lower_32_bits(dma_addr); + mailbox.base_h = upper_32_bits(dma_addr); + mailbox.rsvd = 0; + + mutex_lock(&qm->mailbox_lock); + + if (unlikely(qm_wait_mb_ready(qm))) { + ret = -EBUSY; + dev_err(&qm->pdev->dev, "QM mailbox is busy to start!\n"); + goto busy_unlock; + } + + qm_mb_write(qm, &mailbox); + + if (unlikely(qm_wait_mb_ready(qm))) { + ret = -EBUSY; + dev_err(&qm->pdev->dev, "QM mailbox operation timeout!\n"); + goto busy_unlock; + } + +busy_unlock: + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +static void qm_db_v1(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority) +{ + u64 doorbell; + + doorbell = qn | ((u64)cmd << QM_DB_CMD_SHIFT_V1) | + ((u64)index << QM_DB_INDEX_SHIFT_V1) | + ((u64)priority << QM_DB_PRIORITY_SHIFT_V1); + + writeq(doorbell, qm->io_base + QM_DOORBELL_BASE_V1); +} + +static void qm_db_v2(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority) +{ + u64 doorbell; + u64 dbase; + u16 randata = 0; + + if (cmd == QM_DOORBELL_CMD_SQ || cmd == QM_DOORBELL_CMD_CQ) + dbase = QM_DOORBELL_SQ_CQ_BASE_V2; + else + dbase = QM_DOORBELL_EQ_AEQ_BASE_V2; + + doorbell = qn | ((u64)cmd << QM_DB_CMD_SHIFT_V2) | + ((u64)randata << QM_DB_RAND_SHIFT_V2) | + ((u64)index << QM_DB_INDEX_SHIFT_V2) | + ((u64)priority << QM_DB_PRIORITY_SHIFT_V2); + + writeq(doorbell, qm->io_base + dbase); +} + +static void qm_db(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority) +{ + dev_dbg(&qm->pdev->dev, "QM doorbell request: qn=%u, cmd=%u, index=%u\n", + qn, cmd, index); + + qm->ops->qm_db(qm, qn, cmd, index, priority); +} + +static int qm_dev_mem_reset(struct hisi_qm *qm) +{ + u32 val; + + writel(0x1, qm->io_base + QM_MEM_START_INIT); + return readl_relaxed_poll_timeout(qm->io_base + QM_MEM_INIT_DONE, val, + val & BIT(0), 10, 1000); +} + +static u32 qm_get_irq_num_v1(struct hisi_qm *qm) +{ + return QM_IRQ_NUM_V1; +} + +static u32 qm_get_irq_num_v2(struct hisi_qm *qm) +{ + return QM_IRQ_NUM_PF_V2; +} + +static struct hisi_qp *qm_to_hisi_qp(struct hisi_qm *qm, struct qm_eqe *eqe) +{ + u16 cqn = eqe->dw0 & QM_EQE_CQN_MASK; + + return qm->qp_array[cqn]; +} + +static void qm_cq_head_update(struct hisi_qp *qp) +{ + if (qp->qp_status.cq_head == QM_Q_DEPTH - 1) { + qp->qp_status.cqc_phase = !qp->qp_status.cqc_phase; + qp->qp_status.cq_head = 0; + } else { + qp->qp_status.cq_head++; + } +} + +static void qm_poll_qp(struct hisi_qp *qp, struct hisi_qm *qm) +{ + struct qm_cqe *cqe = qp->cqe + qp->qp_status.cq_head; + + if (qp->req_cb) { + while (QM_CQE_PHASE(cqe) == qp->qp_status.cqc_phase) { + dma_rmb(); + qp->req_cb(qp, qp->sqe + qm->sqe_size * cqe->sq_head); + qm_cq_head_update(qp); + cqe = qp->cqe + qp->qp_status.cq_head; + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, + qp->qp_status.cq_head, 0); + atomic_dec(&qp->qp_status.used); + } + + /* set c_flag */ + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, + qp->qp_status.cq_head, 1); + } +} + +static void qm_qp_work_func(struct work_struct *work) +{ + struct hisi_qp *qp; + + qp = container_of(work, struct hisi_qp, work); + qm_poll_qp(qp, qp->qm); +} + +static irqreturn_t qm_irq_handler(int irq, void *data) +{ + struct hisi_qm *qm = data; + struct qm_eqe *eqe = qm->eqe + qm->status.eq_head; + struct hisi_qp *qp; + int eqe_num = 0; + + while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { + eqe_num++; + qp = qm_to_hisi_qp(qm, eqe); + if (qp) + queue_work(qp->wq, &qp->work); + + if (qm->status.eq_head == QM_Q_DEPTH - 1) { + qm->status.eqc_phase = !qm->status.eqc_phase; + eqe = qm->eqe; + qm->status.eq_head = 0; + } else { + eqe++; + qm->status.eq_head++; + } + + if (eqe_num == QM_Q_DEPTH / 2 - 1) { + eqe_num = 0; + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + } + } + + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + + return IRQ_HANDLED; +} + +static irqreturn_t qm_irq(int irq, void *data) +{ + struct hisi_qm *qm = data; + + if (readl(qm->io_base + QM_VF_EQ_INT_SOURCE)) + return qm_irq_handler(irq, data); + + dev_err(&qm->pdev->dev, "invalid int source\n"); + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + + return IRQ_NONE; +} + +static irqreturn_t qm_aeq_irq(int irq, void *data) +{ + struct hisi_qm *qm = data; + struct qm_aeqe *aeqe = qm->aeqe + qm->status.aeq_head; + u32 type; + + if (!readl(qm->io_base + QM_VF_AEQ_INT_SOURCE)) + return IRQ_NONE; + + while (QM_AEQE_PHASE(aeqe) == qm->status.aeqc_phase) { + type = aeqe->dw0 >> QM_AEQE_TYPE_SHIFT; + if (type < ARRAY_SIZE(qm_fifo_overflow)) + dev_err(&qm->pdev->dev, "%s overflow\n", + qm_fifo_overflow[type]); + else + dev_err(&qm->pdev->dev, "unknown error type %d\n", + type); + + if (qm->status.aeq_head == QM_Q_DEPTH - 1) { + qm->status.aeqc_phase = !qm->status.aeqc_phase; + aeqe = qm->aeqe; + qm->status.aeq_head = 0; + } else { + aeqe++; + qm->status.aeq_head++; + } + + qm_db(qm, 0, QM_DOORBELL_CMD_AEQ, qm->status.aeq_head, 0); + } + + return IRQ_HANDLED; +} + +static irqreturn_t qm_abnormal_irq(int irq, void *data) +{ + const struct hisi_qm_hw_error *err = qm_hw_error; + struct hisi_qm *qm = data; + struct device *dev = &qm->pdev->dev; + u32 error_status, tmp; + + /* read err sts */ + tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS); + error_status = qm->msi_mask & tmp; + + while (err->msg) { + if (err->int_msk & error_status) + dev_err(dev, "%s [error status=0x%x] found\n", + err->msg, err->int_msk); + + err++; + } + + /* clear err sts */ + writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE); + + return IRQ_HANDLED; +} + +static int qm_irq_register(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + int ret; + + ret = request_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), + qm_irq, IRQF_SHARED, qm->dev_name, qm); + if (ret) + return ret; + + if (qm->ver == QM_HW_V2) { + ret = request_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), + qm_aeq_irq, IRQF_SHARED, qm->dev_name, qm); + if (ret) + goto err_aeq_irq; + + ret = request_irq(pci_irq_vector(pdev, + QM_ABNORMAL_EVENT_IRQ_VECTOR), + qm_abnormal_irq, IRQF_SHARED, + qm->dev_name, qm); + if (ret) + goto err_abonormal_irq; + } + + return 0; + +err_abonormal_irq: + free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm); +err_aeq_irq: + free_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), qm); + return ret; +} + +static void qm_irq_unregister(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + + free_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), qm); + + if (qm->ver == QM_HW_V2) { + free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm); + free_irq(pci_irq_vector(pdev, + QM_ABNORMAL_EVENT_IRQ_VECTOR), qm); + } +} + +static void qm_init_qp_status(struct hisi_qp *qp) +{ + struct hisi_qp_status *qp_status = &qp->qp_status; + + qp_status->sq_tail = 0; + qp_status->cq_head = 0; + qp_status->cqc_phase = 1; + qp_status->flags = 0; +} + +static void qm_vft_data_cfg(struct hisi_qm *qm, enum vft_type type, u32 base, + u32 number) +{ + u64 tmp = 0; + + if (number > 0) { + switch (type) { + case SQC_VFT: + switch (qm->ver) { + case QM_HW_V1: + tmp = QM_SQC_VFT_BUF_SIZE | + QM_SQC_VFT_SQC_SIZE | + QM_SQC_VFT_INDEX_NUMBER | + QM_SQC_VFT_VALID | + (u64)base << QM_SQC_VFT_START_SQN_SHIFT; + break; + case QM_HW_V2: + tmp = (u64)base << QM_SQC_VFT_START_SQN_SHIFT | + QM_SQC_VFT_VALID | + (u64)(number - 1) << QM_SQC_VFT_SQN_SHIFT; + break; + case QM_HW_UNKNOWN: + break; + } + break; + case CQC_VFT: + switch (qm->ver) { + case QM_HW_V1: + tmp = QM_CQC_VFT_BUF_SIZE | + QM_CQC_VFT_SQC_SIZE | + QM_CQC_VFT_INDEX_NUMBER | + QM_CQC_VFT_VALID; + break; + case QM_HW_V2: + tmp = QM_CQC_VFT_VALID; + break; + case QM_HW_UNKNOWN: + break; + } + break; + } + } + + writel(lower_32_bits(tmp), qm->io_base + QM_VFT_CFG_DATA_L); + writel(upper_32_bits(tmp), qm->io_base + QM_VFT_CFG_DATA_H); +} + +static int qm_set_vft_common(struct hisi_qm *qm, enum vft_type type, + u32 fun_num, u32 base, u32 number) +{ + unsigned int val; + int ret; + + ret = readl_relaxed_poll_timeout(qm->io_base + QM_VFT_CFG_RDY, val, + val & BIT(0), 10, 1000); + if (ret) + return ret; + + writel(0x0, qm->io_base + QM_VFT_CFG_OP_WR); + writel(type, qm->io_base + QM_VFT_CFG_TYPE); + writel(fun_num, qm->io_base + QM_VFT_CFG); + + qm_vft_data_cfg(qm, type, base, number); + + writel(0x0, qm->io_base + QM_VFT_CFG_RDY); + writel(0x1, qm->io_base + QM_VFT_CFG_OP_ENABLE); + + return readl_relaxed_poll_timeout(qm->io_base + QM_VFT_CFG_RDY, val, + val & BIT(0), 10, 1000); +} + +/* The config should be conducted after qm_dev_mem_reset() */ +static int qm_set_sqc_cqc_vft(struct hisi_qm *qm, u32 fun_num, u32 base, + u32 number) +{ + int ret, i; + + for (i = SQC_VFT; i <= CQC_VFT; i++) { + ret = qm_set_vft_common(qm, i, fun_num, base, number); + if (ret) + return ret; + } + + return 0; +} + +static void qm_hw_error_init_v1(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, + u32 msi) +{ + dev_info(&qm->pdev->dev, + "QM v%d does not support hw error handle\n", qm->ver); + + writel(QM_ABNORMAL_INT_MASK_VALUE, qm->io_base + QM_ABNORMAL_INT_MASK); +} + +static void qm_hw_error_init_v2(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, + u32 msi) +{ + u32 irq_enable = ce | nfe | fe | msi; + u32 irq_unmask = ~irq_enable; + + qm->error_mask = ce | nfe | fe; + qm->msi_mask = msi; + + /* configure error type */ + writel(ce, qm->io_base + QM_RAS_CE_ENABLE); + writel(QM_RAS_CE_TIMES_PER_IRQ, qm->io_base + QM_RAS_CE_THRESHOLD); + writel(nfe, qm->io_base + QM_RAS_NFE_ENABLE); + writel(fe, qm->io_base + QM_RAS_FE_ENABLE); + + /* use RAS irq default, so only set QM_RAS_MSI_INT_SEL for MSI */ + writel(msi, qm->io_base + QM_RAS_MSI_INT_SEL); + + irq_unmask &= readl(qm->io_base + QM_ABNORMAL_INT_MASK); + writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK); +} + +static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status) +{ + const struct hisi_qm_hw_error *err = qm_hw_error; + struct device *dev = &qm->pdev->dev; + u32 reg_val, type, vf_num; + + while (err->msg) { + if (err->int_msk & error_status) { + dev_err(dev, "%s [error status=0x%x] found\n", + err->msg, err->int_msk); + + if (error_status & QM_DB_TIMEOUT) { + reg_val = readl(qm->io_base + + QM_ABNORMAL_INF01); + type = (reg_val & QM_DB_TIMEOUT_TYPE) >> + QM_DB_TIMEOUT_TYPE_SHIFT; + vf_num = reg_val & QM_DB_TIMEOUT_VF; + dev_err(dev, "qm %s doorbell timeout in function %u\n", + qm_db_timeout[type], vf_num); + } + + if (error_status & QM_OF_FIFO_OF) { + reg_val = readl(qm->io_base + + QM_ABNORMAL_INF00); + type = (reg_val & QM_FIFO_OVERFLOW_TYPE) >> + QM_FIFO_OVERFLOW_TYPE_SHIFT; + vf_num = reg_val & QM_FIFO_OVERFLOW_VF; + + if (type < ARRAY_SIZE(qm_fifo_overflow)) + dev_err(dev, "qm %s fifo overflow in function %u\n", + qm_fifo_overflow[type], + vf_num); + else + dev_err(dev, "unknown error type\n"); + } + } + err++; + } +} + +static pci_ers_result_t qm_hw_error_handle_v2(struct hisi_qm *qm) +{ + u32 error_status, tmp; + + /* read err sts */ + tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS); + error_status = qm->error_mask & tmp; + + if (error_status) { + qm_log_hw_error(qm, error_status); + + /* clear err sts */ + writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE); + + return PCI_ERS_RESULT_NEED_RESET; + } + + return PCI_ERS_RESULT_RECOVERED; +} + +static const struct hisi_qm_hw_ops qm_hw_ops_v1 = { + .qm_db = qm_db_v1, + .get_irq_num = qm_get_irq_num_v1, + .hw_error_init = qm_hw_error_init_v1, +}; + +static const struct hisi_qm_hw_ops qm_hw_ops_v2 = { + .qm_db = qm_db_v2, + .get_irq_num = qm_get_irq_num_v2, + .hw_error_init = qm_hw_error_init_v2, + .hw_error_handle = qm_hw_error_handle_v2, +}; + +static void *qm_get_avail_sqe(struct hisi_qp *qp) +{ + struct hisi_qp_status *qp_status = &qp->qp_status; + u16 sq_tail = qp_status->sq_tail; + + if (unlikely(atomic_read(&qp->qp_status.used) == QM_Q_DEPTH)) + return NULL; + + return qp->sqe + sq_tail * qp->qm->sqe_size; +} + +/** + * hisi_qm_create_qp() - Create a queue pair from qm. + * @qm: The qm we create a qp from. + * @alg_type: Accelerator specific algorithm type in sqc. + * + * return created qp, -EBUSY if all qps in qm allocated, -ENOMEM if allocating + * qp memory fails. + */ +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type) +{ + struct device *dev = &qm->pdev->dev; + struct hisi_qp *qp; + int qp_id, ret; + + qp = kzalloc(sizeof(*qp), GFP_KERNEL); + if (!qp) + return ERR_PTR(-ENOMEM); + + write_lock(&qm->qps_lock); + + qp_id = find_first_zero_bit(qm->qp_bitmap, qm->qp_num); + if (qp_id >= qm->qp_num) { + write_unlock(&qm->qps_lock); + dev_info(&qm->pdev->dev, "QM all queues are busy!\n"); + ret = -EBUSY; + goto err_free_qp; + } + set_bit(qp_id, qm->qp_bitmap); + qm->qp_array[qp_id] = qp; + + write_unlock(&qm->qps_lock); + + qp->qm = qm; + + if (qm->use_dma_api) { + qp->qdma.size = qm->sqe_size * QM_Q_DEPTH + + sizeof(struct qm_cqe) * QM_Q_DEPTH; + qp->qdma.va = dma_alloc_coherent(dev, qp->qdma.size, + &qp->qdma.dma, GFP_KERNEL); + if (!qp->qdma.va) { + ret = -ENOMEM; + goto err_clear_bit; + } + + dev_dbg(dev, "allocate qp dma buf(va=%pK, dma=%pad, size=%lx)\n", + qp->qdma.va, &qp->qdma.dma, qp->qdma.size); + } + + qp->qp_id = qp_id; + qp->alg_type = alg_type; + INIT_WORK(&qp->work, qm_qp_work_func); + qp->wq = alloc_workqueue("hisi_qm", WQ_UNBOUND | WQ_HIGHPRI | + WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 0); + if (!qp->wq) { + ret = -EFAULT; + goto err_free_qp_mem; + } + + return qp; + +err_free_qp_mem: + if (qm->use_dma_api) + dma_free_coherent(dev, qp->qdma.size, qp->qdma.va, + qp->qdma.dma); +err_clear_bit: + write_lock(&qm->qps_lock); + qm->qp_array[qp_id] = NULL; + clear_bit(qp_id, qm->qp_bitmap); + write_unlock(&qm->qps_lock); +err_free_qp: + kfree(qp); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(hisi_qm_create_qp); + +/** + * hisi_qm_release_qp() - Release a qp back to its qm. + * @qp: The qp we want to release. + * + * This function releases the resource of a qp. + */ +void hisi_qm_release_qp(struct hisi_qp *qp) +{ + struct hisi_qm *qm = qp->qm; + struct qm_dma *qdma = &qp->qdma; + struct device *dev = &qm->pdev->dev; + + if (qm->use_dma_api && qdma->va) + dma_free_coherent(dev, qdma->size, qdma->va, qdma->dma); + + write_lock(&qm->qps_lock); + qm->qp_array[qp->qp_id] = NULL; + clear_bit(qp->qp_id, qm->qp_bitmap); + write_unlock(&qm->qps_lock); + + kfree(qp); +} +EXPORT_SYMBOL_GPL(hisi_qm_release_qp); + +static int qm_qp_ctx_cfg(struct hisi_qp *qp, int qp_id, int pasid) +{ + struct hisi_qm *qm = qp->qm; + struct device *dev = &qm->pdev->dev; + enum qm_hw_ver ver = qm->ver; + struct qm_sqc *sqc; + struct qm_cqc *cqc; + dma_addr_t sqc_dma; + dma_addr_t cqc_dma; + int ret; + + qm_init_qp_status(qp); + + sqc = kzalloc(sizeof(struct qm_sqc), GFP_KERNEL); + if (!sqc) + return -ENOMEM; + sqc_dma = dma_map_single(dev, sqc, sizeof(struct qm_sqc), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, sqc_dma)) { + kfree(sqc); + return -ENOMEM; + } + + INIT_QC_COMMON(sqc, qp->sqe_dma, pasid); + if (ver == QM_HW_V1) { + sqc->dw3 = QM_MK_SQC_DW3_V1(0, 0, 0, qm->sqe_size); + sqc->w8 = QM_Q_DEPTH - 1; + } else if (ver == QM_HW_V2) { + sqc->dw3 = QM_MK_SQC_DW3_V2(qm->sqe_size); + sqc->w8 = 0; /* rand_qc */ + } + sqc->cq_num = qp_id; + sqc->w13 = QM_MK_SQC_W13(0, 1, qp->alg_type); + + ret = qm_mb(qm, QM_MB_CMD_SQC, sqc_dma, qp_id, 0); + dma_unmap_single(dev, sqc_dma, sizeof(struct qm_sqc), DMA_TO_DEVICE); + kfree(sqc); + if (ret) + return ret; + + cqc = kzalloc(sizeof(struct qm_cqc), GFP_KERNEL); + if (!cqc) + return -ENOMEM; + cqc_dma = dma_map_single(dev, cqc, sizeof(struct qm_cqc), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, cqc_dma)) { + kfree(cqc); + return -ENOMEM; + } + + INIT_QC_COMMON(cqc, qp->cqe_dma, pasid); + if (ver == QM_HW_V1) { + cqc->dw3 = QM_MK_CQC_DW3_V1(0, 0, 0, 4); + cqc->w8 = QM_Q_DEPTH - 1; + } else if (ver == QM_HW_V2) { + cqc->dw3 = QM_MK_CQC_DW3_V2(4); + cqc->w8 = 0; + } + cqc->dw6 = 1 << QM_CQ_PHASE_SHIFT | 1 << QM_CQ_FLAG_SHIFT; + + ret = qm_mb(qm, QM_MB_CMD_CQC, cqc_dma, qp_id, 0); + dma_unmap_single(dev, cqc_dma, sizeof(struct qm_cqc), DMA_TO_DEVICE); + kfree(cqc); + + return ret; +} + +/** + * hisi_qm_start_qp() - Start a qp into running. + * @qp: The qp we want to start to run. + * @arg: Accelerator specific argument. + * + * After this function, qp can receive request from user. Return qp_id if + * successful, Return -EBUSY if failed. + */ +int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg) +{ + struct hisi_qm *qm = qp->qm; + struct device *dev = &qm->pdev->dev; + enum qm_hw_ver ver = qm->ver; + int qp_id = qp->qp_id; + int pasid = arg; + size_t off = 0; + int ret; + +#define QP_INIT_BUF(qp, type, size) do { \ + (qp)->type = ((qp)->qdma.va + (off)); \ + (qp)->type##_dma = (qp)->qdma.dma + (off); \ + off += (size); \ +} while (0) + + if (!qp->qdma.dma) { + dev_err(dev, "cannot get qm dma buffer\n"); + return -EINVAL; + } + + /* sq need 128 bytes alignment */ + if (qp->qdma.dma & QM_SQE_DATA_ALIGN_MASK) { + dev_err(dev, "qm sq is not aligned to 128 byte\n"); + return -EINVAL; + } + + QP_INIT_BUF(qp, sqe, qm->sqe_size * QM_Q_DEPTH); + QP_INIT_BUF(qp, cqe, sizeof(struct qm_cqe) * QM_Q_DEPTH); + + dev_dbg(dev, "init qp buffer(v%d):\n" + " sqe (%pK, %lx)\n" + " cqe (%pK, %lx)\n", + ver, qp->sqe, (unsigned long)qp->sqe_dma, + qp->cqe, (unsigned long)qp->cqe_dma); + + ret = qm_qp_ctx_cfg(qp, qp_id, pasid); + if (ret) + return ret; + + dev_dbg(dev, "queue %d started\n", qp_id); + + return qp_id; +} +EXPORT_SYMBOL_GPL(hisi_qm_start_qp); + +/** + * hisi_qm_stop_qp() - Stop a qp in qm. + * @qp: The qp we want to stop. + * + * This function is reverse of hisi_qm_start_qp. Return 0 if successful. + */ +int hisi_qm_stop_qp(struct hisi_qp *qp) +{ + struct device *dev = &qp->qm->pdev->dev; + int i = 0; + + /* it is stopped */ + if (test_bit(QP_STOP, &qp->qp_status.flags)) + return 0; + + while (atomic_read(&qp->qp_status.used)) { + i++; + msleep(20); + if (i == 10) { + dev_err(dev, "Cannot drain out data for stopping, Force to stop!\n"); + return 0; + } + } + + set_bit(QP_STOP, &qp->qp_status.flags); + + dev_dbg(dev, "stop queue %u!", qp->qp_id); + + return 0; +} +EXPORT_SYMBOL_GPL(hisi_qm_stop_qp); + +/** + * hisi_qp_send() - Queue up a task in the hardware queue. + * @qp: The qp in which to put the message. + * @msg: The message. + * + * This function will return -EBUSY if qp is currently full, and -EAGAIN + * if qp related qm is resetting. + */ +int hisi_qp_send(struct hisi_qp *qp, const void *msg) +{ + struct hisi_qp_status *qp_status = &qp->qp_status; + u16 sq_tail = qp_status->sq_tail; + u16 sq_tail_next = (sq_tail + 1) % QM_Q_DEPTH; + void *sqe = qm_get_avail_sqe(qp); + + if (unlikely(test_bit(QP_STOP, &qp->qp_status.flags))) { + dev_info(&qp->qm->pdev->dev, "QP is stopped or resetting\n"); + return -EAGAIN; + } + + if (!sqe) + return -EBUSY; + + memcpy(sqe, msg, qp->qm->sqe_size); + + qm_db(qp->qm, qp->qp_id, QM_DOORBELL_CMD_SQ, sq_tail_next, 0); + atomic_inc(&qp->qp_status.used); + qp_status->sq_tail = sq_tail_next; + + return 0; +} +EXPORT_SYMBOL_GPL(hisi_qp_send); + +static void hisi_qm_cache_wb(struct hisi_qm *qm) +{ + unsigned int val; + + if (qm->ver == QM_HW_V2) { + writel(0x1, qm->io_base + QM_CACHE_WB_START); + if (readl_relaxed_poll_timeout(qm->io_base + QM_CACHE_WB_DONE, + val, val & BIT(0), 10, 1000)) + dev_err(&qm->pdev->dev, "QM writeback sqc cache fail!\n"); + } +} + +/** + * hisi_qm_init() - Initialize configures about qm. + * @qm: The qm needing init. + * + * This function init qm, then we can call hisi_qm_start to put qm into work. + */ +int hisi_qm_init(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + struct device *dev = &pdev->dev; + unsigned int num_vec; + int ret; + + switch (qm->ver) { + case QM_HW_V1: + qm->ops = &qm_hw_ops_v1; + break; + case QM_HW_V2: + qm->ops = &qm_hw_ops_v2; + break; + default: + return -EINVAL; + } + + ret = pci_enable_device_mem(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to enable device mem!\n"); + return ret; + } + + ret = pci_request_mem_regions(pdev, qm->dev_name); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request mem regions!\n"); + goto err_disable_pcidev; + } + + qm->io_base = ioremap(pci_resource_start(pdev, PCI_BAR_2), + pci_resource_len(qm->pdev, PCI_BAR_2)); + if (!qm->io_base) { + ret = -EIO; + goto err_release_mem_regions; + } + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (ret < 0) + goto err_iounmap; + pci_set_master(pdev); + + if (!qm->ops->get_irq_num) { + ret = -EOPNOTSUPP; + goto err_iounmap; + } + num_vec = qm->ops->get_irq_num(qm); + ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSI); + if (ret < 0) { + dev_err(dev, "Failed to enable MSI vectors!\n"); + goto err_iounmap; + } + + ret = qm_irq_register(qm); + if (ret) + goto err_free_irq_vectors; + + mutex_init(&qm->mailbox_lock); + rwlock_init(&qm->qps_lock); + + return 0; + +err_free_irq_vectors: + pci_free_irq_vectors(pdev); +err_iounmap: + iounmap(qm->io_base); +err_release_mem_regions: + pci_release_mem_regions(pdev); +err_disable_pcidev: + pci_disable_device(pdev); + + return ret; +} +EXPORT_SYMBOL_GPL(hisi_qm_init); + +/** + * hisi_qm_uninit() - Uninitialize qm. + * @qm: The qm needed uninit. + * + * This function uninits qm related device resources. + */ +void hisi_qm_uninit(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + struct device *dev = &pdev->dev; + + if (qm->use_dma_api && qm->qdma.va) { + hisi_qm_cache_wb(qm); + dma_free_coherent(dev, qm->qdma.size, + qm->qdma.va, qm->qdma.dma); + memset(&qm->qdma, 0, sizeof(qm->qdma)); + } + + qm_irq_unregister(qm); + pci_free_irq_vectors(pdev); + iounmap(qm->io_base); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} +EXPORT_SYMBOL_GPL(hisi_qm_uninit); + +/** + * hisi_qm_set_vft() - Set "virtual function table" for a qm. + * @fun_num: Number of operated function. + * @qm: The qm in which to set vft, alway in a PF. + * @base: The base number of queue in vft. + * @number: The number of queues in vft. 0 means invalid vft. + * + * This function is alway called in PF driver, it is used to assign queues + * among PF and VFs. + * + * Assign queues A~B to PF: hisi_qm_set_vft(qm, 0, A, B - A + 1) + * Assign queues A~B to VF: hisi_qm_set_vft(qm, 2, A, B - A + 1) + * (VF function number 0x2) + */ +int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base, + u32 number) +{ + u32 max_q_num = qm->ctrl_qp_num; + + if (base >= max_q_num || number > max_q_num || + (base + number) > max_q_num) + return -EINVAL; + + return qm_set_sqc_cqc_vft(qm, fun_num, base, number); +} +EXPORT_SYMBOL_GPL(hisi_qm_set_vft); + +static void qm_init_eq_aeq_status(struct hisi_qm *qm) +{ + struct hisi_qm_status *status = &qm->status; + + status->eq_head = 0; + status->aeq_head = 0; + status->eqc_phase = 1; + status->aeqc_phase = 1; +} + +static int qm_eq_ctx_cfg(struct hisi_qm *qm) +{ + struct device *dev = &qm->pdev->dev; + struct qm_eqc *eqc; + struct qm_aeqc *aeqc; + dma_addr_t eqc_dma; + dma_addr_t aeqc_dma; + int ret; + + qm_init_eq_aeq_status(qm); + + eqc = kzalloc(sizeof(struct qm_eqc), GFP_KERNEL); + if (!eqc) + return -ENOMEM; + eqc_dma = dma_map_single(dev, eqc, sizeof(struct qm_eqc), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, eqc_dma)) { + kfree(eqc); + return -ENOMEM; + } + + eqc->base_l = lower_32_bits(qm->eqe_dma); + eqc->base_h = upper_32_bits(qm->eqe_dma); + if (qm->ver == QM_HW_V1) + eqc->dw3 = QM_EQE_AEQE_SIZE; + eqc->dw6 = (QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT); + ret = qm_mb(qm, QM_MB_CMD_EQC, eqc_dma, 0, 0); + dma_unmap_single(dev, eqc_dma, sizeof(struct qm_eqc), DMA_TO_DEVICE); + kfree(eqc); + if (ret) + return ret; + + aeqc = kzalloc(sizeof(struct qm_aeqc), GFP_KERNEL); + if (!aeqc) + return -ENOMEM; + aeqc_dma = dma_map_single(dev, aeqc, sizeof(struct qm_aeqc), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, aeqc_dma)) { + kfree(aeqc); + return -ENOMEM; + } + + aeqc->base_l = lower_32_bits(qm->aeqe_dma); + aeqc->base_h = upper_32_bits(qm->aeqe_dma); + aeqc->dw6 = (QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT); + + ret = qm_mb(qm, QM_MB_CMD_AEQC, aeqc_dma, 0, 0); + dma_unmap_single(dev, aeqc_dma, sizeof(struct qm_aeqc), DMA_TO_DEVICE); + kfree(aeqc); + + return ret; +} + +static int __hisi_qm_start(struct hisi_qm *qm) +{ + struct pci_dev *pdev = qm->pdev; + struct device *dev = &pdev->dev; + size_t off = 0; + int ret; + +#define QM_INIT_BUF(qm, type, num) do { \ + (qm)->type = ((qm)->qdma.va + (off)); \ + (qm)->type##_dma = (qm)->qdma.dma + (off); \ + off += QMC_ALIGN(sizeof(struct qm_##type) * (num)); \ +} while (0) + + WARN_ON(!qm->qdma.dma); + + if (qm->qp_num == 0) + return -EINVAL; + + ret = qm_dev_mem_reset(qm); + if (ret) + return ret; + + ret = hisi_qm_set_vft(qm, 0, qm->qp_base, qm->qp_num); + if (ret) + return ret; + + QM_INIT_BUF(qm, eqe, QM_Q_DEPTH); + QM_INIT_BUF(qm, aeqe, QM_Q_DEPTH); + QM_INIT_BUF(qm, sqc, qm->qp_num); + QM_INIT_BUF(qm, cqc, qm->qp_num); + + dev_dbg(dev, "init qm buffer:\n" + " eqe (%pK, %lx)\n" + " aeqe (%pK, %lx)\n" + " sqc (%pK, %lx)\n" + " cqc (%pK, %lx)\n", + qm->eqe, (unsigned long)qm->eqe_dma, + qm->aeqe, (unsigned long)qm->aeqe_dma, + qm->sqc, (unsigned long)qm->sqc_dma, + qm->cqc, (unsigned long)qm->cqc_dma); + + ret = qm_eq_ctx_cfg(qm); + if (ret) + return ret; + + ret = qm_mb(qm, QM_MB_CMD_SQC_BT, qm->sqc_dma, 0, 0); + if (ret) + return ret; + + ret = qm_mb(qm, QM_MB_CMD_CQC_BT, qm->cqc_dma, 0, 0); + if (ret) + return ret; + + writel(0x0, qm->io_base + QM_VF_EQ_INT_MASK); + writel(0x0, qm->io_base + QM_VF_AEQ_INT_MASK); + + return 0; +} + +/** + * hisi_qm_start() - start qm + * @qm: The qm to be started. + * + * This function starts a qm, then we can allocate qp from this qm. + */ +int hisi_qm_start(struct hisi_qm *qm) +{ + struct device *dev = &qm->pdev->dev; + + dev_dbg(dev, "qm start with %d queue pairs\n", qm->qp_num); + + if (!qm->qp_num) { + dev_err(dev, "qp_num should not be 0\n"); + return -EINVAL; + } + + if (!qm->qp_bitmap) { + qm->qp_bitmap = devm_kcalloc(dev, BITS_TO_LONGS(qm->qp_num), + sizeof(long), GFP_KERNEL); + qm->qp_array = devm_kcalloc(dev, qm->qp_num, + sizeof(struct hisi_qp *), + GFP_KERNEL); + if (!qm->qp_bitmap || !qm->qp_array) + return -ENOMEM; + } + + if (!qm->use_dma_api) { + dev_dbg(&qm->pdev->dev, "qm delay start\n"); + return 0; + } else if (!qm->qdma.va) { + qm->qdma.size = QMC_ALIGN(sizeof(struct qm_eqe) * QM_Q_DEPTH) + + QMC_ALIGN(sizeof(struct qm_aeqe) * QM_Q_DEPTH) + + QMC_ALIGN(sizeof(struct qm_sqc) * qm->qp_num) + + QMC_ALIGN(sizeof(struct qm_cqc) * qm->qp_num); + qm->qdma.va = dma_alloc_coherent(dev, qm->qdma.size, + &qm->qdma.dma, GFP_KERNEL); + dev_dbg(dev, "allocate qm dma buf(va=%pK, dma=%pad, size=%lx)\n", + qm->qdma.va, &qm->qdma.dma, qm->qdma.size); + if (!qm->qdma.va) + return -ENOMEM; + } + + return __hisi_qm_start(qm); +} +EXPORT_SYMBOL_GPL(hisi_qm_start); + +/** + * hisi_qm_stop() - Stop a qm. + * @qm: The qm which will be stopped. + * + * This function stops qm and its qps, then qm can not accept request. + * Related resources are not released at this state, we can use hisi_qm_start + * to let qm start again. + */ +int hisi_qm_stop(struct hisi_qm *qm) +{ + struct device *dev; + struct hisi_qp *qp; + int ret = 0, i; + + if (!qm || !qm->pdev) { + WARN_ON(1); + return -EINVAL; + } + + dev = &qm->pdev->dev; + + /* Mask eq and aeq irq */ + writel(0x1, qm->io_base + QM_VF_EQ_INT_MASK); + writel(0x1, qm->io_base + QM_VF_AEQ_INT_MASK); + + /* Stop all qps belong to this qm */ + for (i = 0; i < qm->qp_num; i++) { + qp = qm->qp_array[i]; + if (qp) { + ret = hisi_qm_stop_qp(qp); + if (ret < 0) { + dev_err(dev, "Failed to stop qp%d!\n", i); + return -EBUSY; + } + } + } + + ret = hisi_qm_set_vft(qm, 0, 0, 0); + if (ret < 0) + dev_err(dev, "Failed to set vft!\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(hisi_qm_stop); + +/** + * hisi_qm_hw_error_init() - Configure qm hardware error report method. + * @qm: The qm which we want to configure. + * @ce: Bit mask of correctable error configure. + * @nfe: Bit mask of non-fatal error configure. + * @fe: Bit mask of fatal error configure. + * @msi: Bit mask of error reported by message signal interrupt. + * + * Hardware errors of qm can be reported either by RAS interrupts which will + * be handled by UEFI and then PCIe AER or by device MSI. User can configure + * each error to use either of above two methods. For RAS interrupts, we can + * configure an error as one of correctable error, non-fatal error or + * fatal error. + * + * Bits indicating errors can be configured to ce, nfe, fe and msi to enable + * related report methods. Error report will be masked if related error bit + * does not configure. + */ +void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, + u32 msi) +{ + if (!qm->ops->hw_error_init) { + dev_err(&qm->pdev->dev, "QM version %d doesn't support hw error handling!\n", + qm->ver); + return; + } + + qm->ops->hw_error_init(qm, ce, nfe, fe, msi); +} +EXPORT_SYMBOL_GPL(hisi_qm_hw_error_init); + +/** + * hisi_qm_hw_error_handle() - Handle qm non-fatal hardware errors. + * @qm: The qm which has non-fatal hardware errors. + * + * Accelerators use this function to handle qm non-fatal hardware errors. + */ +int hisi_qm_hw_error_handle(struct hisi_qm *qm) +{ + if (!qm->ops->hw_error_handle) { + dev_err(&qm->pdev->dev, "QM version %d doesn't support hw error report!\n", + qm->ver); + return PCI_ERS_RESULT_NONE; + } + + return qm->ops->hw_error_handle(qm); +} +EXPORT_SYMBOL_GPL(hisi_qm_hw_error_handle); + +/** + * hisi_qm_get_hw_version() - Get hardware version of a qm. + * @pdev: The device which hardware version we want to get. + * + * This function gets the hardware version of a qm. Return QM_HW_UNKNOWN + * if the hardware version is not supported. + */ +enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev) +{ + switch (pdev->revision) { + case QM_HW_V1: + case QM_HW_V2: + return pdev->revision; + default: + return QM_HW_UNKNOWN; + } +} +EXPORT_SYMBOL_GPL(hisi_qm_get_hw_version); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Zhou Wang "); +MODULE_DESCRIPTION("HiSilicon Accelerator queue manager driver"); diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h new file mode 100644 index 000000000000..a5849db163cb --- /dev/null +++ b/drivers/crypto/hisilicon/qm.h @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019 HiSilicon Limited. */ +#ifndef HISI_ACC_QM_H +#define HISI_ACC_QM_H + +#include +#include +#include +#include + +/* qm user domain */ +#define QM_ARUSER_M_CFG_1 0x100088 +#define AXUSER_SNOOP_ENABLE BIT(30) +#define AXUSER_CMD_TYPE GENMASK(14, 12) +#define AXUSER_CMD_SMMU_NORMAL 1 +#define AXUSER_NS BIT(6) +#define AXUSER_NO BIT(5) +#define AXUSER_FP BIT(4) +#define AXUSER_SSV BIT(0) +#define AXUSER_BASE (AXUSER_SNOOP_ENABLE | \ + FIELD_PREP(AXUSER_CMD_TYPE, \ + AXUSER_CMD_SMMU_NORMAL) | \ + AXUSER_NS | AXUSER_NO | AXUSER_FP) +#define QM_ARUSER_M_CFG_ENABLE 0x100090 +#define ARUSER_M_CFG_ENABLE 0xfffffffe +#define QM_AWUSER_M_CFG_1 0x100098 +#define QM_AWUSER_M_CFG_ENABLE 0x1000a0 +#define AWUSER_M_CFG_ENABLE 0xfffffffe +#define QM_WUSER_M_CFG_ENABLE 0x1000a8 +#define WUSER_M_CFG_ENABLE 0xffffffff + +/* qm cache */ +#define QM_CACHE_CTL 0x100050 +#define SQC_CACHE_ENABLE BIT(0) +#define CQC_CACHE_ENABLE BIT(1) +#define SQC_CACHE_WB_ENABLE BIT(4) +#define SQC_CACHE_WB_THRD GENMASK(10, 5) +#define CQC_CACHE_WB_ENABLE BIT(11) +#define CQC_CACHE_WB_THRD GENMASK(17, 12) +#define QM_AXI_M_CFG 0x1000ac +#define AXI_M_CFG 0xffff +#define QM_AXI_M_CFG_ENABLE 0x1000b0 +#define AXI_M_CFG_ENABLE 0xffffffff +#define QM_PEH_AXUSER_CFG 0x1000cc +#define QM_PEH_AXUSER_CFG_ENABLE 0x1000d0 +#define PEH_AXUSER_CFG 0x401001 +#define PEH_AXUSER_CFG_ENABLE 0xffffffff + + +#define QM_AXI_RRESP BIT(0) +#define QM_AXI_BRESP BIT(1) +#define QM_ECC_MBIT BIT(2) +#define QM_ECC_1BIT BIT(3) +#define QM_ACC_GET_TASK_TIMEOUT BIT(4) +#define QM_ACC_DO_TASK_TIMEOUT BIT(5) +#define QM_ACC_WB_NOT_READY_TIMEOUT BIT(6) +#define QM_SQ_CQ_VF_INVALID BIT(7) +#define QM_CQ_VF_INVALID BIT(8) +#define QM_SQ_VF_INVALID BIT(9) +#define QM_DB_TIMEOUT BIT(10) +#define QM_OF_FIFO_OF BIT(11) +#define QM_DB_RANDOM_INVALID BIT(12) + +#define QM_BASE_NFE (QM_AXI_RRESP | QM_AXI_BRESP | QM_ECC_MBIT | \ + QM_ACC_GET_TASK_TIMEOUT | QM_DB_TIMEOUT | \ + QM_OF_FIFO_OF) +#define QM_BASE_CE QM_ECC_1BIT + +#define QM_Q_DEPTH 1024 + +enum qp_state { + QP_STOP, +}; + +enum qm_hw_ver { + QM_HW_UNKNOWN = -1, + QM_HW_V1 = 0x20, + QM_HW_V2 = 0x21, +}; + +enum qm_fun_type { + QM_HW_PF, +}; + +struct qm_dma { + void *va; + dma_addr_t dma; + size_t size; +}; + +struct hisi_qm_status { + u32 eq_head; + bool eqc_phase; + u32 aeq_head; + bool aeqc_phase; + unsigned long flags; +}; + +struct hisi_qm { + enum qm_hw_ver ver; + const char *dev_name; + struct pci_dev *pdev; + void __iomem *io_base; + u32 sqe_size; + u32 qp_base; + u32 qp_num; + u32 ctrl_qp_num; + + struct qm_dma qdma; + struct qm_sqc *sqc; + struct qm_cqc *cqc; + struct qm_eqe *eqe; + struct qm_aeqe *aeqe; + dma_addr_t sqc_dma; + dma_addr_t cqc_dma; + dma_addr_t eqe_dma; + dma_addr_t aeqe_dma; + + struct hisi_qm_status status; + + rwlock_t qps_lock; + unsigned long *qp_bitmap; + struct hisi_qp **qp_array; + + struct mutex mailbox_lock; + + const struct hisi_qm_hw_ops *ops; + + u32 error_mask; + u32 msi_mask; + + bool use_dma_api; +}; + +struct hisi_qp_status { + atomic_t used; + u16 sq_tail; + u16 cq_head; + bool cqc_phase; + unsigned long flags; +}; + +struct hisi_qp_ops { + int (*fill_sqe)(void *sqe, void *q_parm, void *d_parm); +}; + +struct hisi_qp { + u32 qp_id; + u8 alg_type; + u8 req_type; + + struct qm_dma qdma; + void *sqe; + struct qm_cqe *cqe; + dma_addr_t sqe_dma; + dma_addr_t cqe_dma; + + struct hisi_qp_status qp_status; + struct hisi_qp_ops *hw_ops; + void *qp_ctx; + void (*req_cb)(struct hisi_qp *qp, void *data); + struct work_struct work; + struct workqueue_struct *wq; + + struct hisi_qm *qm; +}; + +int hisi_qm_init(struct hisi_qm *qm); +void hisi_qm_uninit(struct hisi_qm *qm); +int hisi_qm_start(struct hisi_qm *qm); +int hisi_qm_stop(struct hisi_qm *qm); +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type); +int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg); +int hisi_qm_stop_qp(struct hisi_qp *qp); +void hisi_qm_release_qp(struct hisi_qp *qp); +int hisi_qp_send(struct hisi_qp *qp, const void *msg); +int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base, u32 number); +void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, + u32 msi); +int hisi_qm_hw_error_handle(struct hisi_qm *qm); +enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev); +#endif -- GitLab From dfed0098ab91f647b5720ab6f1e03b5b55139408 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:51 +0800 Subject: [PATCH 2347/7155] crypto: hisilicon - add hardware SGL support HiSilicon accelerators in Hip08 use same hardware scatterlist for data format. We support it in this module. Specific accelerator drivers can use hisi_acc_create_sgl_pool to allocate hardware SGLs ahead. Then use hisi_acc_sg_buf_map_to_hw_sgl to get one hardware SGL and pass related information to hardware SGL. The DMA address of mapped hardware SGL can be passed to SGL src/dst field in QM SQE. Signed-off-by: Zhou Wang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/Kconfig | 8 ++ drivers/crypto/hisilicon/Makefile | 1 + drivers/crypto/hisilicon/sgl.c | 214 ++++++++++++++++++++++++++++++ drivers/crypto/hisilicon/sgl.h | 24 ++++ 4 files changed, 247 insertions(+) create mode 100644 drivers/crypto/hisilicon/sgl.c create mode 100644 drivers/crypto/hisilicon/sgl.h diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index b79be8dc78e7..457d9bcb0d4e 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -19,3 +19,11 @@ config CRYPTO_DEV_HISI_QM help HiSilicon accelerator engines use a common queue management interface. Specific engine driver may use this module. + +config CRYPTO_HISI_SGL + tristate + depends on ARM64 + help + HiSilicon accelerator engines use a common hardware scatterlist + interface for data format. Specific engine driver may use this + module. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index 05e9052e0f52..96cb9134194e 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += qm.o +obj-$(CONFIG_CRYPTO_HISI_SGL) += sgl.o diff --git a/drivers/crypto/hisilicon/sgl.c b/drivers/crypto/hisilicon/sgl.c new file mode 100644 index 000000000000..8ef7679a365e --- /dev/null +++ b/drivers/crypto/hisilicon/sgl.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ +#include +#include +#include "./sgl.h" + +#define HISI_ACC_SGL_SGE_NR_MIN 1 +#define HISI_ACC_SGL_SGE_NR_MAX 255 +#define HISI_ACC_SGL_SGE_NR_DEF 10 +#define HISI_ACC_SGL_NR_MAX 256 +#define HISI_ACC_SGL_ALIGN_SIZE 64 + +static int acc_sgl_sge_set(const char *val, const struct kernel_param *kp) +{ + int ret; + u32 n; + + if (!val) + return -EINVAL; + + ret = kstrtou32(val, 10, &n); + if (ret != 0 || n > HISI_ACC_SGL_SGE_NR_MAX || n == 0) + return -EINVAL; + + return param_set_int(val, kp); +} + +static const struct kernel_param_ops acc_sgl_sge_ops = { + .set = acc_sgl_sge_set, + .get = param_get_int, +}; + +static u32 acc_sgl_sge_nr = HISI_ACC_SGL_SGE_NR_DEF; +module_param_cb(acc_sgl_sge_nr, &acc_sgl_sge_ops, &acc_sgl_sge_nr, 0444); +MODULE_PARM_DESC(acc_sgl_sge_nr, "Number of sge in sgl(1-255)"); + +struct acc_hw_sge { + dma_addr_t buf; + void *page_ctrl; + __le32 len; + __le32 pad; + __le32 pad0; + __le32 pad1; +}; + +/* use default sgl head size 64B */ +struct hisi_acc_hw_sgl { + dma_addr_t next_dma; + __le16 entry_sum_in_chain; + __le16 entry_sum_in_sgl; + __le16 entry_length_in_sgl; + __le16 pad0; + __le64 pad1[5]; + struct hisi_acc_hw_sgl *next; + struct acc_hw_sge sge_entries[]; +} __aligned(1); + +/** + * hisi_acc_create_sgl_pool() - Create a hw sgl pool. + * @dev: The device which hw sgl pool belongs to. + * @pool: Pointer of pool. + * @count: Count of hisi_acc_hw_sgl in pool. + * + * This function creates a hw sgl pool, after this user can get hw sgl memory + * from it. + */ +int hisi_acc_create_sgl_pool(struct device *dev, + struct hisi_acc_sgl_pool *pool, u32 count) +{ + u32 sgl_size; + u32 size; + + if (!dev || !pool || !count) + return -EINVAL; + + sgl_size = sizeof(struct acc_hw_sge) * acc_sgl_sge_nr + + sizeof(struct hisi_acc_hw_sgl); + size = sgl_size * count; + + pool->sgl = dma_alloc_coherent(dev, size, &pool->sgl_dma, GFP_KERNEL); + if (!pool->sgl) + return -ENOMEM; + + pool->size = size; + pool->count = count; + pool->sgl_size = sgl_size; + + return 0; +} +EXPORT_SYMBOL_GPL(hisi_acc_create_sgl_pool); + +/** + * hisi_acc_free_sgl_pool() - Free a hw sgl pool. + * @dev: The device which hw sgl pool belongs to. + * @pool: Pointer of pool. + * + * This function frees memory of a hw sgl pool. + */ +void hisi_acc_free_sgl_pool(struct device *dev, struct hisi_acc_sgl_pool *pool) +{ + dma_free_coherent(dev, pool->size, pool->sgl, pool->sgl_dma); + memset(pool, 0, sizeof(struct hisi_acc_sgl_pool)); +} +EXPORT_SYMBOL_GPL(hisi_acc_free_sgl_pool); + +struct hisi_acc_hw_sgl *acc_get_sgl(struct hisi_acc_sgl_pool *pool, u32 index, + dma_addr_t *hw_sgl_dma) +{ + if (!pool || !hw_sgl_dma || index >= pool->count || !pool->sgl) + return ERR_PTR(-EINVAL); + + *hw_sgl_dma = pool->sgl_dma + pool->sgl_size * index; + return (void *)pool->sgl + pool->sgl_size * index; +} + +void acc_put_sgl(struct hisi_acc_sgl_pool *pool, u32 index) {} + +static void sg_map_to_hw_sg(struct scatterlist *sgl, + struct acc_hw_sge *hw_sge) +{ + hw_sge->buf = sgl->dma_address; + hw_sge->len = sgl->dma_length; +} + +static void inc_hw_sgl_sge(struct hisi_acc_hw_sgl *hw_sgl) +{ + hw_sgl->entry_sum_in_sgl++; +} + +static void update_hw_sgl_sum_sge(struct hisi_acc_hw_sgl *hw_sgl, u16 sum) +{ + hw_sgl->entry_sum_in_chain = sum; +} + +/** + * hisi_acc_sg_buf_map_to_hw_sgl - Map a scatterlist to a hw sgl. + * @dev: The device which hw sgl belongs to. + * @sgl: Scatterlist which will be mapped to hw sgl. + * @pool: Pool which hw sgl memory will be allocated in. + * @index: Index of hisi_acc_hw_sgl in pool. + * @hw_sgl_dma: The dma address of allocated hw sgl. + * + * This function builds hw sgl according input sgl, user can use hw_sgl_dma + * as src/dst in its BD. Only support single hw sgl currently. + */ +struct hisi_acc_hw_sgl * +hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev, + struct scatterlist *sgl, + struct hisi_acc_sgl_pool *pool, + u32 index, dma_addr_t *hw_sgl_dma) +{ + struct hisi_acc_hw_sgl *curr_hw_sgl; + dma_addr_t curr_sgl_dma; + struct acc_hw_sge *curr_hw_sge; + struct scatterlist *sg; + int sg_n = sg_nents(sgl); + int i, ret; + + if (!dev || !sgl || !pool || !hw_sgl_dma || sg_n > acc_sgl_sge_nr) + return ERR_PTR(-EINVAL); + + ret = dma_map_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL); + if (!ret) + return ERR_PTR(-EINVAL); + + curr_hw_sgl = acc_get_sgl(pool, index, &curr_sgl_dma); + if (!curr_hw_sgl) { + ret = -ENOMEM; + goto err_unmap_sg; + } + curr_hw_sgl->entry_length_in_sgl = acc_sgl_sge_nr; + curr_hw_sge = curr_hw_sgl->sge_entries; + + for_each_sg(sgl, sg, sg_n, i) { + sg_map_to_hw_sg(sg, curr_hw_sge); + inc_hw_sgl_sge(curr_hw_sgl); + curr_hw_sge++; + } + + update_hw_sgl_sum_sge(curr_hw_sgl, acc_sgl_sge_nr); + *hw_sgl_dma = curr_sgl_dma; + + return curr_hw_sgl; + +err_unmap_sg: + dma_unmap_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(hisi_acc_sg_buf_map_to_hw_sgl); + +/** + * hisi_acc_sg_buf_unmap() - Unmap allocated hw sgl. + * @dev: The device which hw sgl belongs to. + * @sgl: Related scatterlist. + * @hw_sgl: Virtual address of hw sgl. + * @hw_sgl_dma: DMA address of hw sgl. + * @pool: Pool which hw sgl is allocated in. + * + * This function unmaps allocated hw sgl. + */ +void hisi_acc_sg_buf_unmap(struct device *dev, struct scatterlist *sgl, + struct hisi_acc_hw_sgl *hw_sgl) +{ + dma_unmap_sg(dev, sgl, sg_nents(sgl), DMA_BIDIRECTIONAL); + + hw_sgl->entry_sum_in_chain = 0; + hw_sgl->entry_sum_in_sgl = 0; + hw_sgl->entry_length_in_sgl = 0; +} +EXPORT_SYMBOL_GPL(hisi_acc_sg_buf_unmap); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Zhou Wang "); +MODULE_DESCRIPTION("HiSilicon Accelerator SGL support"); diff --git a/drivers/crypto/hisilicon/sgl.h b/drivers/crypto/hisilicon/sgl.h new file mode 100644 index 000000000000..3ac8871c7acf --- /dev/null +++ b/drivers/crypto/hisilicon/sgl.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019 HiSilicon Limited. */ +#ifndef HISI_ACC_SGL_H +#define HISI_ACC_SGL_H + +struct hisi_acc_sgl_pool { + struct hisi_acc_hw_sgl *sgl; + dma_addr_t sgl_dma; + size_t size; + u32 count; + size_t sgl_size; +}; + +struct hisi_acc_hw_sgl * +hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev, + struct scatterlist *sgl, + struct hisi_acc_sgl_pool *pool, + u32 index, dma_addr_t *hw_sgl_dma); +void hisi_acc_sg_buf_unmap(struct device *dev, struct scatterlist *sgl, + struct hisi_acc_hw_sgl *hw_sgl); +int hisi_acc_create_sgl_pool(struct device *dev, struct hisi_acc_sgl_pool *pool, + u32 count); +void hisi_acc_free_sgl_pool(struct device *dev, struct hisi_acc_sgl_pool *pool); +#endif -- GitLab From 62c455ca853e3e352e465d66a6cc39f1f88caa60 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:52 +0800 Subject: [PATCH 2348/7155] crypto: hisilicon - add HiSilicon ZIP accelerator support The HiSilicon ZIP accelerator implements the zlib and gzip algorithm. It uses Hisilicon QM as the interface to the CPU. This patch provides PCIe driver to the accelerator and registers it to crypto acomp interface. It also uses sgl as data input/output interface. Signed-off-by: Zhou Wang Signed-off-by: Shiju Jose Signed-off-by: Kenneth Lee Signed-off-by: Hao Fang Reviewed-by: Jonathan Cameron Reviewed-by: John Garry Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/Kconfig | 8 + drivers/crypto/hisilicon/Makefile | 1 + drivers/crypto/hisilicon/zip/Makefile | 2 + drivers/crypto/hisilicon/zip/zip.h | 71 +++ drivers/crypto/hisilicon/zip/zip_crypto.c | 651 ++++++++++++++++++++++ drivers/crypto/hisilicon/zip/zip_main.c | 504 +++++++++++++++++ 6 files changed, 1237 insertions(+) create mode 100644 drivers/crypto/hisilicon/zip/Makefile create mode 100644 drivers/crypto/hisilicon/zip/zip.h create mode 100644 drivers/crypto/hisilicon/zip/zip_crypto.c create mode 100644 drivers/crypto/hisilicon/zip/zip_main.c diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index 457d9bcb0d4e..19293172b408 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -27,3 +27,11 @@ config CRYPTO_HISI_SGL HiSilicon accelerator engines use a common hardware scatterlist interface for data format. Specific engine driver may use this module. + +config CRYPTO_DEV_HISI_ZIP + tristate "Support for HiSilicon ZIP accelerator" + select CRYPTO_DEV_HISI_QM + select CRYPTO_HISI_SGL + select SG_SPLIT + help + Support for HiSilicon ZIP Driver diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index 96cb9134194e..45a279741126 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += qm.o obj-$(CONFIG_CRYPTO_HISI_SGL) += sgl.o +obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/ diff --git a/drivers/crypto/hisilicon/zip/Makefile b/drivers/crypto/hisilicon/zip/Makefile new file mode 100644 index 000000000000..a936f099ee22 --- /dev/null +++ b/drivers/crypto/hisilicon/zip/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += hisi_zip.o +hisi_zip-objs = zip_main.o zip_crypto.o diff --git a/drivers/crypto/hisilicon/zip/zip.h b/drivers/crypto/hisilicon/zip/zip.h new file mode 100644 index 000000000000..ffb00d987d02 --- /dev/null +++ b/drivers/crypto/hisilicon/zip/zip.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019 HiSilicon Limited. */ +#ifndef HISI_ZIP_H +#define HISI_ZIP_H + +#undef pr_fmt +#define pr_fmt(fmt) "hisi_zip: " fmt + +#include +#include "../qm.h" +#include "../sgl.h" + +/* hisi_zip_sqe dw3 */ +#define HZIP_BD_STATUS_M GENMASK(7, 0) +/* hisi_zip_sqe dw9 */ +#define HZIP_REQ_TYPE_M GENMASK(7, 0) +#define HZIP_ALG_TYPE_ZLIB 0x02 +#define HZIP_ALG_TYPE_GZIP 0x03 +#define HZIP_BUF_TYPE_M GENMASK(11, 8) +#define HZIP_PBUFFER 0x0 +#define HZIP_SGL 0x1 + +enum hisi_zip_error_type { + /* negative compression */ + HZIP_NC_ERR = 0x0d, +}; + +struct hisi_zip_ctrl; + +struct hisi_zip { + struct hisi_qm qm; + struct list_head list; + struct hisi_zip_ctrl *ctrl; +}; + +struct hisi_zip_sqe { + u32 consumed; + u32 produced; + u32 comp_data_length; + u32 dw3; + u32 input_data_length; + u32 lba_l; + u32 lba_h; + u32 dw7; + u32 dw8; + u32 dw9; + u32 dw10; + u32 priv_info; + u32 dw12; + u32 tag; + u32 dest_avail_out; + u32 rsvd0; + u32 comp_head_addr_l; + u32 comp_head_addr_h; + u32 source_addr_l; + u32 source_addr_h; + u32 dest_addr_l; + u32 dest_addr_h; + u32 stream_ctx_addr_l; + u32 stream_ctx_addr_h; + u32 cipher_key1_addr_l; + u32 cipher_key1_addr_h; + u32 cipher_key2_addr_l; + u32 cipher_key2_addr_h; + u32 rsvd1[4]; +}; + +struct hisi_zip *find_zip_device(int node); +int hisi_zip_register_to_crypto(void); +void hisi_zip_unregister_from_crypto(void); +#endif diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c new file mode 100644 index 000000000000..303351325a58 --- /dev/null +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c @@ -0,0 +1,651 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ +#include +#include +#include +#include +#include "zip.h" + +#define HZIP_ZLIB_HEAD_SIZE 2 +#define HZIP_GZIP_HEAD_SIZE 10 + +#define GZIP_HEAD_FHCRC_BIT BIT(1) +#define GZIP_HEAD_FEXTRA_BIT BIT(2) +#define GZIP_HEAD_FNAME_BIT BIT(3) +#define GZIP_HEAD_FCOMMENT_BIT BIT(4) + +#define GZIP_HEAD_FLG_SHIFT 3 +#define GZIP_HEAD_FEXTRA_SHIFT 10 +#define GZIP_HEAD_FEXTRA_XLEN 2 +#define GZIP_HEAD_FHCRC_SIZE 2 + +#define HZIP_CTX_Q_NUM 2 +#define HZIP_GZIP_HEAD_BUF 256 +#define HZIP_ALG_PRIORITY 300 + +static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c}; +static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {0x1f, 0x8b, 0x08, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x03}; +enum hisi_zip_alg_type { + HZIP_ALG_TYPE_COMP = 0, + HZIP_ALG_TYPE_DECOMP = 1, +}; + +#define COMP_NAME_TO_TYPE(alg_name) \ + (!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB : \ + !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0) \ + +#define TO_HEAD_SIZE(req_type) \ + (((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) : \ + ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0) \ + +#define TO_HEAD(req_type) \ + (((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head : \ + ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : 0) \ + +struct hisi_zip_req { + struct acomp_req *req; + struct scatterlist *src; + struct scatterlist *dst; + size_t slen; + size_t dlen; + struct hisi_acc_hw_sgl *hw_src; + struct hisi_acc_hw_sgl *hw_dst; + dma_addr_t dma_src; + dma_addr_t dma_dst; + int req_id; +}; + +struct hisi_zip_req_q { + struct hisi_zip_req *q; + unsigned long *req_bitmap; + rwlock_t req_lock; + u16 size; +}; + +struct hisi_zip_qp_ctx { + struct hisi_qp *qp; + struct hisi_zip_sqe zip_sqe; + struct hisi_zip_req_q req_q; + struct hisi_acc_sgl_pool sgl_pool; + struct hisi_zip *zip_dev; + struct hisi_zip_ctx *ctx; +}; + +struct hisi_zip_ctx { +#define QPC_COMP 0 +#define QPC_DECOMP 1 + struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM]; +}; + +static void hisi_zip_config_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type) +{ + u32 val; + + val = (sqe->dw9) & ~HZIP_BUF_TYPE_M; + val |= FIELD_PREP(HZIP_BUF_TYPE_M, buf_type); + sqe->dw9 = val; +} + +static void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag) +{ + sqe->tag = tag; +} + +static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type, + dma_addr_t s_addr, dma_addr_t d_addr, u32 slen, + u32 dlen) +{ + memset(sqe, 0, sizeof(struct hisi_zip_sqe)); + + sqe->input_data_length = slen; + sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type); + sqe->dest_avail_out = dlen; + sqe->source_addr_l = lower_32_bits(s_addr); + sqe->source_addr_h = upper_32_bits(s_addr); + sqe->dest_addr_l = lower_32_bits(d_addr); + sqe->dest_addr_h = upper_32_bits(d_addr); +} + +static int hisi_zip_create_qp(struct hisi_qm *qm, struct hisi_zip_qp_ctx *ctx, + int alg_type, int req_type) +{ + struct hisi_qp *qp; + int ret; + + qp = hisi_qm_create_qp(qm, alg_type); + if (IS_ERR(qp)) + return PTR_ERR(qp); + + qp->req_type = req_type; + qp->qp_ctx = ctx; + ctx->qp = qp; + + ret = hisi_qm_start_qp(qp, 0); + if (ret < 0) + goto err_release_qp; + + return 0; + +err_release_qp: + hisi_qm_release_qp(qp); + return ret; +} + +static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *ctx) +{ + hisi_qm_stop_qp(ctx->qp); + hisi_qm_release_qp(ctx->qp); +} + +static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type) +{ + struct hisi_zip *hisi_zip; + struct hisi_qm *qm; + int ret, i, j; + + /* find the proper zip device */ + hisi_zip = find_zip_device(cpu_to_node(smp_processor_id())); + if (!hisi_zip) { + pr_err("Failed to find a proper ZIP device!\n"); + return -ENODEV; + } + qm = &hisi_zip->qm; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) { + /* alg_type = 0 for compress, 1 for decompress in hw sqe */ + ret = hisi_zip_create_qp(qm, &hisi_zip_ctx->qp_ctx[i], i, + req_type); + if (ret) + goto err; + + hisi_zip_ctx->qp_ctx[i].zip_dev = hisi_zip; + } + + return 0; +err: + for (j = i - 1; j >= 0; j--) + hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[j]); + + return ret; +} + +static void hisi_zip_ctx_exit(struct hisi_zip_ctx *hisi_zip_ctx) +{ + int i; + + for (i = 1; i >= 0; i--) + hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[i]); +} + +static u16 get_extra_field_size(const u8 *start) +{ + return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN; +} + +static u32 get_name_field_size(const u8 *start) +{ + return strlen(start) + 1; +} + +static u32 get_comment_field_size(const u8 *start) +{ + return strlen(start) + 1; +} + +static u32 __get_gzip_head_size(const u8 *src) +{ + u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT); + u32 size = GZIP_HEAD_FEXTRA_SHIFT; + + if (head_flg & GZIP_HEAD_FEXTRA_BIT) + size += get_extra_field_size(src + size); + if (head_flg & GZIP_HEAD_FNAME_BIT) + size += get_name_field_size(src + size); + if (head_flg & GZIP_HEAD_FCOMMENT_BIT) + size += get_comment_field_size(src + size); + if (head_flg & GZIP_HEAD_FHCRC_BIT) + size += GZIP_HEAD_FHCRC_SIZE; + + return size; +} + +static int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx) +{ + struct hisi_zip_req_q *req_q; + int i, ret; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) { + req_q = &ctx->qp_ctx[i].req_q; + req_q->size = QM_Q_DEPTH; + + req_q->req_bitmap = kcalloc(BITS_TO_LONGS(req_q->size), + sizeof(long), GFP_KERNEL); + if (!req_q->req_bitmap) { + ret = -ENOMEM; + if (i == 1) + goto err_free_loop0; + } + rwlock_init(&req_q->req_lock); + + req_q->q = kcalloc(req_q->size, sizeof(struct hisi_zip_req), + GFP_KERNEL); + if (!req_q->q) { + ret = -ENOMEM; + if (i == 0) + goto err_free_bitmap; + else + goto err_free_loop1; + } + } + + return 0; + +err_free_loop1: + kfree(ctx->qp_ctx[QPC_DECOMP].req_q.req_bitmap); +err_free_loop0: + kfree(ctx->qp_ctx[QPC_COMP].req_q.q); +err_free_bitmap: + kfree(ctx->qp_ctx[QPC_COMP].req_q.req_bitmap); + return ret; +} + +static void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx) +{ + int i; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) { + kfree(ctx->qp_ctx[i].req_q.q); + kfree(ctx->qp_ctx[i].req_q.req_bitmap); + } +} + +static int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx) +{ + struct hisi_zip_qp_ctx *tmp; + int i, ret; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) { + tmp = &ctx->qp_ctx[i]; + ret = hisi_acc_create_sgl_pool(&tmp->qp->qm->pdev->dev, + &tmp->sgl_pool, + QM_Q_DEPTH << 1); + if (ret < 0) { + if (i == 1) + goto err_free_sgl_pool0; + return -ENOMEM; + } + } + + return 0; + +err_free_sgl_pool0: + hisi_acc_free_sgl_pool(&ctx->qp_ctx[QPC_COMP].qp->qm->pdev->dev, + &ctx->qp_ctx[QPC_COMP].sgl_pool); + return -ENOMEM; +} + +static void hisi_zip_release_sgl_pool(struct hisi_zip_ctx *ctx) +{ + int i; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) + hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev, + &ctx->qp_ctx[i].sgl_pool); +} + +static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx, + struct hisi_zip_req *req) +{ + struct hisi_zip_req_q *req_q = &qp_ctx->req_q; + + if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP) + kfree(req->dst); + else + kfree(req->src); + + write_lock(&req_q->req_lock); + clear_bit(req->req_id, req_q->req_bitmap); + memset(req, 0, sizeof(struct hisi_zip_req)); + write_unlock(&req_q->req_lock); +} + +static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) +{ + struct hisi_zip_sqe *sqe = data; + struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx; + struct hisi_zip_req_q *req_q = &qp_ctx->req_q; + struct hisi_zip_req *req = req_q->q + sqe->tag; + struct acomp_req *acomp_req = req->req; + struct device *dev = &qp->qm->pdev->dev; + u32 status, dlen, head_size; + int err = 0; + + status = sqe->dw3 & HZIP_BD_STATUS_M; + + if (status != 0 && status != HZIP_NC_ERR) { + dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n", + (qp->alg_type == 0) ? "" : "de", qp->qp_id, status, + sqe->produced); + err = -EIO; + } + dlen = sqe->produced; + + hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); + hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); + + head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0; + acomp_req->dlen = dlen + head_size; + + if (acomp_req->base.complete) + acomp_request_complete(acomp_req, err); + + hisi_zip_remove_req(qp_ctx, req); +} + +static void hisi_zip_set_acomp_cb(struct hisi_zip_ctx *ctx, + void (*fn)(struct hisi_qp *, void *)) +{ + int i; + + for (i = 0; i < HZIP_CTX_Q_NUM; i++) + ctx->qp_ctx[i].qp->req_cb = fn; +} + +static int hisi_zip_acomp_init(struct crypto_acomp *tfm) +{ + const char *alg_name = crypto_tfm_alg_name(&tfm->base); + struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base); + int ret; + + ret = hisi_zip_ctx_init(ctx, COMP_NAME_TO_TYPE(alg_name)); + if (ret) + return ret; + + ret = hisi_zip_create_req_q(ctx); + if (ret) + goto err_ctx_exit; + + ret = hisi_zip_create_sgl_pool(ctx); + if (ret) + goto err_release_req_q; + + hisi_zip_set_acomp_cb(ctx, hisi_zip_acomp_cb); + + return 0; + +err_release_req_q: + hisi_zip_release_req_q(ctx); +err_ctx_exit: + hisi_zip_ctx_exit(ctx); + return ret; +} + +static void hisi_zip_acomp_exit(struct crypto_acomp *tfm) +{ + struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base); + + hisi_zip_set_acomp_cb(ctx, NULL); + hisi_zip_release_sgl_pool(ctx); + hisi_zip_release_req_q(ctx); + hisi_zip_ctx_exit(ctx); +} + +static int add_comp_head(struct scatterlist *dst, u8 req_type) +{ + int head_size = TO_HEAD_SIZE(req_type); + const u8 *head = TO_HEAD(req_type); + int ret; + + ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size); + if (ret != head_size) + return -ENOMEM; + + return head_size; +} + +static size_t get_gzip_head_size(struct scatterlist *sgl) +{ + char buf[HZIP_GZIP_HEAD_BUF]; + + sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf)); + + return __get_gzip_head_size(buf); +} + +static size_t get_comp_head_size(struct scatterlist *src, u8 req_type) +{ + switch (req_type) { + case HZIP_ALG_TYPE_ZLIB: + return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB); + case HZIP_ALG_TYPE_GZIP: + return get_gzip_head_size(src); + default: + pr_err("request type does not support!\n"); + return -EINVAL; + } +} + +static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes, + size_t remains, struct scatterlist **out) +{ +#define SPLIT_NUM 2 + size_t split_sizes[SPLIT_NUM]; + int out_mapped_nents[SPLIT_NUM]; + + split_sizes[0] = bytes; + split_sizes[1] = remains; + + return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out, + out_mapped_nents, GFP_KERNEL); +} + +static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, + struct hisi_zip_qp_ctx *qp_ctx, + size_t head_size, bool is_comp) +{ + struct hisi_zip_req_q *req_q = &qp_ctx->req_q; + struct hisi_zip_req *q = req_q->q; + struct hisi_zip_req *req_cache; + struct scatterlist *out[2]; + struct scatterlist *sgl; + size_t len; + int ret, req_id; + + /* + * remove/add zlib/gzip head, as hardware operations do not include + * comp head. so split req->src to get sgl without heads in acomp, or + * add comp head to req->dst ahead of that hardware output compressed + * data in sgl splited from req->dst without comp head. + */ + if (is_comp) { + sgl = req->dst; + len = req->dlen - head_size; + } else { + sgl = req->src; + len = req->slen - head_size; + } + + ret = get_sg_skip_bytes(sgl, head_size, len, out); + if (ret) + return ERR_PTR(ret); + + /* sgl for comp head is useless, so free it now */ + kfree(out[0]); + + write_lock(&req_q->req_lock); + + req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size); + if (req_id >= req_q->size) { + write_unlock(&req_q->req_lock); + dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n"); + kfree(out[1]); + return ERR_PTR(-EBUSY); + } + set_bit(req_id, req_q->req_bitmap); + + req_cache = q + req_id; + req_cache->req_id = req_id; + req_cache->req = req; + if (is_comp) { + req_cache->src = req->src; + req_cache->dst = out[1]; + req_cache->slen = req->slen; + req_cache->dlen = req->dlen - head_size; + } else { + req_cache->src = out[1]; + req_cache->dst = req->dst; + req_cache->slen = req->slen - head_size; + req_cache->dlen = req->dlen; + } + + write_unlock(&req_q->req_lock); + + return req_cache; +} + +static int hisi_zip_do_work(struct hisi_zip_req *req, + struct hisi_zip_qp_ctx *qp_ctx) +{ + struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe; + struct hisi_qp *qp = qp_ctx->qp; + struct device *dev = &qp->qm->pdev->dev; + struct hisi_acc_sgl_pool *pool = &qp_ctx->sgl_pool; + dma_addr_t input; + dma_addr_t output; + int ret; + + if (!req->src || !req->slen || !req->dst || !req->dlen) + return -EINVAL; + + req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool, + req->req_id << 1, &input); + if (IS_ERR(req->hw_src)) + return PTR_ERR(req->hw_src); + req->dma_src = input; + + req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool, + (req->req_id << 1) + 1, + &output); + if (IS_ERR(req->hw_dst)) { + ret = PTR_ERR(req->hw_dst); + goto err_unmap_input; + } + req->dma_dst = output; + + hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen, + req->dlen); + hisi_zip_config_buf_type(zip_sqe, HZIP_SGL); + hisi_zip_config_tag(zip_sqe, req->req_id); + + /* send command to start a task */ + ret = hisi_qp_send(qp, zip_sqe); + if (ret < 0) + goto err_unmap_output; + + return -EINPROGRESS; + +err_unmap_output: + hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); +err_unmap_input: + hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); + return ret; +} + +static int hisi_zip_acompress(struct acomp_req *acomp_req) +{ + struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm); + struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[QPC_COMP]; + struct hisi_zip_req *req; + size_t head_size; + int ret; + + /* let's output compression head now */ + head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type); + if (head_size < 0) + return -ENOMEM; + + req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = hisi_zip_do_work(req, qp_ctx); + if (ret != -EINPROGRESS) + hisi_zip_remove_req(qp_ctx, req); + + return ret; +} + +static int hisi_zip_adecompress(struct acomp_req *acomp_req) +{ + struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm); + struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[QPC_DECOMP]; + struct hisi_zip_req *req; + size_t head_size; + int ret; + + head_size = get_comp_head_size(acomp_req->src, qp_ctx->qp->req_type); + + req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = hisi_zip_do_work(req, qp_ctx); + if (ret != -EINPROGRESS) + hisi_zip_remove_req(qp_ctx, req); + + return ret; +} + +static struct acomp_alg hisi_zip_acomp_zlib = { + .init = hisi_zip_acomp_init, + .exit = hisi_zip_acomp_exit, + .compress = hisi_zip_acompress, + .decompress = hisi_zip_adecompress, + .base = { + .cra_name = "zlib-deflate", + .cra_driver_name = "hisi-zlib-acomp", + .cra_module = THIS_MODULE, + .cra_priority = HZIP_ALG_PRIORITY, + .cra_ctxsize = sizeof(struct hisi_zip_ctx), + } +}; + +static struct acomp_alg hisi_zip_acomp_gzip = { + .init = hisi_zip_acomp_init, + .exit = hisi_zip_acomp_exit, + .compress = hisi_zip_acompress, + .decompress = hisi_zip_adecompress, + .base = { + .cra_name = "gzip", + .cra_driver_name = "hisi-gzip-acomp", + .cra_module = THIS_MODULE, + .cra_priority = HZIP_ALG_PRIORITY, + .cra_ctxsize = sizeof(struct hisi_zip_ctx), + } +}; + +int hisi_zip_register_to_crypto(void) +{ + int ret = 0; + + ret = crypto_register_acomp(&hisi_zip_acomp_zlib); + if (ret) { + pr_err("Zlib acomp algorithm registration failed\n"); + return ret; + } + + ret = crypto_register_acomp(&hisi_zip_acomp_gzip); + if (ret) { + pr_err("Gzip acomp algorithm registration failed\n"); + crypto_unregister_acomp(&hisi_zip_acomp_zlib); + } + + return ret; +} + +void hisi_zip_unregister_from_crypto(void) +{ + crypto_unregister_acomp(&hisi_zip_acomp_gzip); + crypto_unregister_acomp(&hisi_zip_acomp_zlib); +} diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c new file mode 100644 index 000000000000..ee4e20e0230e --- /dev/null +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zip.h" + +#define PCI_DEVICE_ID_ZIP_PF 0xa250 + +#define HZIP_VF_NUM 63 +#define HZIP_QUEUE_NUM_V1 4096 +#define HZIP_QUEUE_NUM_V2 1024 + +#define HZIP_CLOCK_GATE_CTRL 0x301004 +#define COMP0_ENABLE BIT(0) +#define COMP1_ENABLE BIT(1) +#define DECOMP0_ENABLE BIT(2) +#define DECOMP1_ENABLE BIT(3) +#define DECOMP2_ENABLE BIT(4) +#define DECOMP3_ENABLE BIT(5) +#define DECOMP4_ENABLE BIT(6) +#define DECOMP5_ENABLE BIT(7) +#define ALL_COMP_DECOMP_EN (COMP0_ENABLE | COMP1_ENABLE | \ + DECOMP0_ENABLE | DECOMP1_ENABLE | \ + DECOMP2_ENABLE | DECOMP3_ENABLE | \ + DECOMP4_ENABLE | DECOMP5_ENABLE) +#define DECOMP_CHECK_ENABLE BIT(16) + +#define HZIP_PORT_ARCA_CHE_0 0x301040 +#define HZIP_PORT_ARCA_CHE_1 0x301044 +#define HZIP_PORT_AWCA_CHE_0 0x301060 +#define HZIP_PORT_AWCA_CHE_1 0x301064 +#define CACHE_ALL_EN 0xffffffff + +#define HZIP_BD_RUSER_32_63 0x301110 +#define HZIP_SGL_RUSER_32_63 0x30111c +#define HZIP_DATA_RUSER_32_63 0x301128 +#define HZIP_DATA_WUSER_32_63 0x301134 +#define HZIP_BD_WUSER_32_63 0x301140 + + + +#define HZIP_CORE_INT_SOURCE 0x3010A0 +#define HZIP_CORE_INT_MASK 0x3010A4 +#define HZIP_CORE_INT_STATUS 0x3010AC +#define HZIP_CORE_INT_STATUS_M_ECC BIT(1) +#define HZIP_CORE_SRAM_ECC_ERR_INFO 0x301148 +#define SRAM_ECC_ERR_NUM_SHIFT 16 +#define SRAM_ECC_ERR_ADDR_SHIFT 24 +#define HZIP_CORE_INT_DISABLE 0x000007FF +#define HZIP_SQE_SIZE 128 +#define HZIP_PF_DEF_Q_NUM 64 +#define HZIP_PF_DEF_Q_BASE 0 + + +#define HZIP_NUMA_DISTANCE 100 + +static const char hisi_zip_name[] = "hisi_zip"; +LIST_HEAD(hisi_zip_list); +DEFINE_MUTEX(hisi_zip_list_lock); + +#ifdef CONFIG_NUMA +static struct hisi_zip *find_zip_device_numa(int node) +{ + struct hisi_zip *zip = NULL; + struct hisi_zip *hisi_zip; + int min_distance = HZIP_NUMA_DISTANCE; + struct device *dev; + + list_for_each_entry(hisi_zip, &hisi_zip_list, list) { + dev = &hisi_zip->qm.pdev->dev; + if (node_distance(dev->numa_node, node) < min_distance) { + zip = hisi_zip; + min_distance = node_distance(dev->numa_node, node); + } + } + + return zip; +} +#endif + +struct hisi_zip *find_zip_device(int node) +{ + struct hisi_zip *zip = NULL; + + mutex_lock(&hisi_zip_list_lock); +#ifdef CONFIG_NUMA + zip = find_zip_device_numa(node); +#else + zip = list_first_entry(&hisi_zip_list, struct hisi_zip, list); +#endif + mutex_unlock(&hisi_zip_list_lock); + + return zip; +} + +struct hisi_zip_hw_error { + u32 int_msk; + const char *msg; +}; + +static const struct hisi_zip_hw_error zip_hw_error[] = { + { .int_msk = BIT(0), .msg = "zip_ecc_1bitt_err" }, + { .int_msk = BIT(1), .msg = "zip_ecc_2bit_err" }, + { .int_msk = BIT(2), .msg = "zip_axi_rresp_err" }, + { .int_msk = BIT(3), .msg = "zip_axi_bresp_err" }, + { .int_msk = BIT(4), .msg = "zip_src_addr_parse_err" }, + { .int_msk = BIT(5), .msg = "zip_dst_addr_parse_err" }, + { .int_msk = BIT(6), .msg = "zip_pre_in_addr_err" }, + { .int_msk = BIT(7), .msg = "zip_pre_in_data_err" }, + { .int_msk = BIT(8), .msg = "zip_com_inf_err" }, + { .int_msk = BIT(9), .msg = "zip_enc_inf_err" }, + { .int_msk = BIT(10), .msg = "zip_pre_out_err" }, + { /* sentinel */ } +}; + +/* + * One ZIP controller has one PF and multiple VFs, some global configurations + * which PF has need this structure. + * + * Just relevant for PF. + */ +struct hisi_zip_ctrl { + struct hisi_zip *hisi_zip; +}; + +static int pf_q_num_set(const char *val, const struct kernel_param *kp) +{ + struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, + PCI_DEVICE_ID_ZIP_PF, NULL); + u32 n, q_num; + u8 rev_id; + int ret; + + if (!val) + return -EINVAL; + + if (!pdev) { + q_num = min_t(u32, HZIP_QUEUE_NUM_V1, HZIP_QUEUE_NUM_V2); + pr_info("No device found currently, suppose queue number is %d\n", + q_num); + } else { + rev_id = pdev->revision; + switch (rev_id) { + case QM_HW_V1: + q_num = HZIP_QUEUE_NUM_V1; + break; + case QM_HW_V2: + q_num = HZIP_QUEUE_NUM_V2; + break; + default: + return -EINVAL; + } + } + + ret = kstrtou32(val, 10, &n); + if (ret != 0 || n > q_num || n == 0) + return -EINVAL; + + return param_set_int(val, kp); +} + +static const struct kernel_param_ops pf_q_num_ops = { + .set = pf_q_num_set, + .get = param_get_int, +}; + +static u32 pf_q_num = HZIP_PF_DEF_Q_NUM; +module_param_cb(pf_q_num, &pf_q_num_ops, &pf_q_num, 0444); +MODULE_PARM_DESC(pf_q_num, "Number of queues in PF(v1 1-4096, v2 1-1024)"); + +static int uacce_mode; +module_param(uacce_mode, int, 0); + +static const struct pci_device_id hisi_zip_dev_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_ZIP_PF) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, hisi_zip_dev_ids); + +static inline void hisi_zip_add_to_list(struct hisi_zip *hisi_zip) +{ + mutex_lock(&hisi_zip_list_lock); + list_add_tail(&hisi_zip->list, &hisi_zip_list); + mutex_unlock(&hisi_zip_list_lock); +} + +static inline void hisi_zip_remove_from_list(struct hisi_zip *hisi_zip) +{ + mutex_lock(&hisi_zip_list_lock); + list_del(&hisi_zip->list); + mutex_unlock(&hisi_zip_list_lock); +} + +static void hisi_zip_set_user_domain_and_cache(struct hisi_zip *hisi_zip) +{ + void __iomem *base = hisi_zip->qm.io_base; + + /* qm user domain */ + writel(AXUSER_BASE, base + QM_ARUSER_M_CFG_1); + writel(ARUSER_M_CFG_ENABLE, base + QM_ARUSER_M_CFG_ENABLE); + writel(AXUSER_BASE, base + QM_AWUSER_M_CFG_1); + writel(AWUSER_M_CFG_ENABLE, base + QM_AWUSER_M_CFG_ENABLE); + writel(WUSER_M_CFG_ENABLE, base + QM_WUSER_M_CFG_ENABLE); + + /* qm cache */ + writel(AXI_M_CFG, base + QM_AXI_M_CFG); + writel(AXI_M_CFG_ENABLE, base + QM_AXI_M_CFG_ENABLE); + /* disable FLR triggered by BME(bus master enable) */ + writel(PEH_AXUSER_CFG, base + QM_PEH_AXUSER_CFG); + writel(PEH_AXUSER_CFG_ENABLE, base + QM_PEH_AXUSER_CFG_ENABLE); + + /* cache */ + writel(CACHE_ALL_EN, base + HZIP_PORT_ARCA_CHE_0); + writel(CACHE_ALL_EN, base + HZIP_PORT_ARCA_CHE_1); + writel(CACHE_ALL_EN, base + HZIP_PORT_AWCA_CHE_0); + writel(CACHE_ALL_EN, base + HZIP_PORT_AWCA_CHE_1); + + /* user domain configurations */ + writel(AXUSER_BASE, base + HZIP_BD_RUSER_32_63); + writel(AXUSER_BASE, base + HZIP_SGL_RUSER_32_63); + writel(AXUSER_BASE, base + HZIP_BD_WUSER_32_63); + writel(AXUSER_BASE, base + HZIP_DATA_RUSER_32_63); + writel(AXUSER_BASE, base + HZIP_DATA_WUSER_32_63); + + /* let's open all compression/decompression cores */ + writel(DECOMP_CHECK_ENABLE | ALL_COMP_DECOMP_EN, + base + HZIP_CLOCK_GATE_CTRL); + + /* enable sqc writeback */ + writel(SQC_CACHE_ENABLE | CQC_CACHE_ENABLE | SQC_CACHE_WB_ENABLE | + CQC_CACHE_WB_ENABLE | FIELD_PREP(SQC_CACHE_WB_THRD, 1) | + FIELD_PREP(CQC_CACHE_WB_THRD, 1), base + QM_CACHE_CTL); +} + +static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state) +{ + struct hisi_qm *qm = &hisi_zip->qm; + + if (qm->ver == QM_HW_V1) { + writel(HZIP_CORE_INT_DISABLE, qm->io_base + HZIP_CORE_INT_MASK); + dev_info(&qm->pdev->dev, "ZIP v%d does not support hw error handle\n", + qm->ver); + return; + } + + if (state) { + /* clear ZIP hw error source if having */ + writel(HZIP_CORE_INT_DISABLE, hisi_zip->qm.io_base + + HZIP_CORE_INT_SOURCE); + /* enable ZIP hw error interrupts */ + writel(0, hisi_zip->qm.io_base + HZIP_CORE_INT_MASK); + } else { + /* disable ZIP hw error interrupts */ + writel(HZIP_CORE_INT_DISABLE, + hisi_zip->qm.io_base + HZIP_CORE_INT_MASK); + } +} + +static void hisi_zip_hw_error_init(struct hisi_zip *hisi_zip) +{ + hisi_qm_hw_error_init(&hisi_zip->qm, QM_BASE_CE, + QM_BASE_NFE | QM_ACC_WB_NOT_READY_TIMEOUT, 0, + QM_DB_RANDOM_INVALID); + hisi_zip_hw_error_set_state(hisi_zip, true); +} + +static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) +{ + struct hisi_qm *qm = &hisi_zip->qm; + struct hisi_zip_ctrl *ctrl; + + ctrl = devm_kzalloc(&qm->pdev->dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + hisi_zip->ctrl = ctrl; + ctrl->hisi_zip = hisi_zip; + + switch (qm->ver) { + case QM_HW_V1: + qm->ctrl_qp_num = HZIP_QUEUE_NUM_V1; + break; + + case QM_HW_V2: + qm->ctrl_qp_num = HZIP_QUEUE_NUM_V2; + break; + + default: + return -EINVAL; + } + + hisi_zip_set_user_domain_and_cache(hisi_zip); + hisi_zip_hw_error_init(hisi_zip); + + return 0; +} + +static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct hisi_zip *hisi_zip; + enum qm_hw_ver rev_id; + struct hisi_qm *qm; + int ret; + + rev_id = hisi_qm_get_hw_version(pdev); + if (rev_id == QM_HW_UNKNOWN) + return -EINVAL; + + hisi_zip = devm_kzalloc(&pdev->dev, sizeof(*hisi_zip), GFP_KERNEL); + if (!hisi_zip) + return -ENOMEM; + pci_set_drvdata(pdev, hisi_zip); + + qm = &hisi_zip->qm; + qm->pdev = pdev; + qm->ver = rev_id; + + qm->sqe_size = HZIP_SQE_SIZE; + qm->dev_name = hisi_zip_name; + switch (uacce_mode) { + case 0: + qm->use_dma_api = true; + break; + case 1: + qm->use_dma_api = false; + break; + case 2: + qm->use_dma_api = true; + break; + default: + return -EINVAL; + } + + ret = hisi_qm_init(qm); + if (ret) { + dev_err(&pdev->dev, "Failed to init qm!\n"); + return ret; + } + + ret = hisi_zip_pf_probe_init(hisi_zip); + if (ret) + goto err_qm_uninit; + + qm->qp_base = HZIP_PF_DEF_Q_BASE; + qm->qp_num = pf_q_num; + + ret = hisi_qm_start(qm); + if (ret) + goto err_qm_uninit; + + hisi_zip_add_to_list(hisi_zip); + + return 0; + +err_qm_uninit: + hisi_qm_uninit(qm); + return ret; +} + +static void hisi_zip_remove(struct pci_dev *pdev) +{ + struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); + struct hisi_qm *qm = &hisi_zip->qm; + + hisi_qm_stop(qm); + hisi_zip_hw_error_set_state(hisi_zip, false); + hisi_qm_uninit(qm); + hisi_zip_remove_from_list(hisi_zip); +} + +static void hisi_zip_log_hw_error(struct hisi_zip *hisi_zip, u32 err_sts) +{ + const struct hisi_zip_hw_error *err = zip_hw_error; + struct device *dev = &hisi_zip->qm.pdev->dev; + u32 err_val; + + while (err->msg) { + if (err->int_msk & err_sts) { + dev_warn(dev, "%s [error status=0x%x] found\n", + err->msg, err->int_msk); + + if (HZIP_CORE_INT_STATUS_M_ECC & err->int_msk) { + err_val = readl(hisi_zip->qm.io_base + + HZIP_CORE_SRAM_ECC_ERR_INFO); + dev_warn(dev, "hisi-zip multi ecc sram num=0x%x\n", + ((err_val >> SRAM_ECC_ERR_NUM_SHIFT) & + 0xFF)); + dev_warn(dev, "hisi-zip multi ecc sram addr=0x%x\n", + (err_val >> SRAM_ECC_ERR_ADDR_SHIFT)); + } + } + err++; + } +} + +static pci_ers_result_t hisi_zip_hw_error_handle(struct hisi_zip *hisi_zip) +{ + u32 err_sts; + + /* read err sts */ + err_sts = readl(hisi_zip->qm.io_base + HZIP_CORE_INT_STATUS); + + if (err_sts) { + hisi_zip_log_hw_error(hisi_zip, err_sts); + /* clear error interrupts */ + writel(err_sts, hisi_zip->qm.io_base + HZIP_CORE_INT_SOURCE); + + return PCI_ERS_RESULT_NEED_RESET; + } + + return PCI_ERS_RESULT_RECOVERED; +} + +static pci_ers_result_t hisi_zip_process_hw_error(struct pci_dev *pdev) +{ + struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + pci_ers_result_t qm_ret, zip_ret; + + if (!hisi_zip) { + dev_err(dev, + "Can't recover ZIP-error occurred during device init\n"); + return PCI_ERS_RESULT_NONE; + } + + qm_ret = hisi_qm_hw_error_handle(&hisi_zip->qm); + + zip_ret = hisi_zip_hw_error_handle(hisi_zip); + + return (qm_ret == PCI_ERS_RESULT_NEED_RESET || + zip_ret == PCI_ERS_RESULT_NEED_RESET) ? + PCI_ERS_RESULT_NEED_RESET : PCI_ERS_RESULT_RECOVERED; +} + +static pci_ers_result_t hisi_zip_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + if (pdev->is_virtfn) + return PCI_ERS_RESULT_NONE; + + dev_info(&pdev->dev, "PCI error detected, state(=%d)!!\n", state); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + return hisi_zip_process_hw_error(pdev); +} + +static const struct pci_error_handlers hisi_zip_err_handler = { + .error_detected = hisi_zip_error_detected, +}; + +static struct pci_driver hisi_zip_pci_driver = { + .name = "hisi_zip", + .id_table = hisi_zip_dev_ids, + .probe = hisi_zip_probe, + .remove = hisi_zip_remove, + .err_handler = &hisi_zip_err_handler, +}; + +static int __init hisi_zip_init(void) +{ + int ret; + + ret = pci_register_driver(&hisi_zip_pci_driver); + if (ret < 0) { + pr_err("Failed to register pci driver.\n"); + return ret; + } + + if (uacce_mode == 0 || uacce_mode == 2) { + ret = hisi_zip_register_to_crypto(); + if (ret < 0) { + pr_err("Failed to register driver to crypto.\n"); + goto err_crypto; + } + } + + return 0; + +err_crypto: + pci_unregister_driver(&hisi_zip_pci_driver); + return ret; +} + +static void __exit hisi_zip_exit(void) +{ + if (uacce_mode == 0 || uacce_mode == 2) + hisi_zip_unregister_from_crypto(); + pci_unregister_driver(&hisi_zip_pci_driver); +} + +module_init(hisi_zip_init); +module_exit(hisi_zip_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Zhou Wang "); +MODULE_DESCRIPTION("Driver for HiSilicon ZIP accelerator"); -- GitLab From 79e09f30eeba857b09832209bfc66bd689c58328 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:53 +0800 Subject: [PATCH 2349/7155] crypto: hisilicon - add SRIOV support for ZIP HiSilicon ZIP engine supports PCI SRIOV. This patch enable this feature. User can enable VFs and pass through them to VM, same ZIP driver can work in VM to provide ZLIB and GZIP algorithm by crypto acomp interface. Signed-off-by: Zhou Wang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 97 ++++++++++++--- drivers/crypto/hisilicon/qm.h | 4 + drivers/crypto/hisilicon/zip/zip_main.c | 150 ++++++++++++++++++++++-- 3 files changed, 226 insertions(+), 25 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index c095d4747812..4f6bbdd4a25b 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -16,6 +16,7 @@ #define QM_VF_EQ_INT_MASK 0xc #define QM_IRQ_NUM_V1 1 #define QM_IRQ_NUM_PF_V2 4 +#define QM_IRQ_NUM_VF_V2 2 #define QM_EQ_EVENT_IRQ_VECTOR 0 #define QM_AEQ_EVENT_IRQ_VECTOR 1 @@ -265,6 +266,7 @@ struct qm_doorbell { }; struct hisi_qm_hw_ops { + int (*get_vft)(struct hisi_qm *qm, u32 *base, u32 *number); void (*qm_db)(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority); u32 (*get_irq_num)(struct hisi_qm *qm); @@ -422,7 +424,10 @@ static u32 qm_get_irq_num_v1(struct hisi_qm *qm) static u32 qm_get_irq_num_v2(struct hisi_qm *qm) { - return QM_IRQ_NUM_PF_V2; + if (qm->fun_type == QM_HW_PF) + return QM_IRQ_NUM_PF_V2; + else + return QM_IRQ_NUM_VF_V2; } static struct hisi_qp *qm_to_hisi_qp(struct hisi_qm *qm, struct qm_eqe *eqe) @@ -591,12 +596,14 @@ static int qm_irq_register(struct hisi_qm *qm) if (ret) goto err_aeq_irq; - ret = request_irq(pci_irq_vector(pdev, - QM_ABNORMAL_EVENT_IRQ_VECTOR), - qm_abnormal_irq, IRQF_SHARED, - qm->dev_name, qm); - if (ret) - goto err_abonormal_irq; + if (qm->fun_type == QM_HW_PF) { + ret = request_irq(pci_irq_vector(pdev, + QM_ABNORMAL_EVENT_IRQ_VECTOR), + qm_abnormal_irq, IRQF_SHARED, + qm->dev_name, qm); + if (ret) + goto err_abonormal_irq; + } } return 0; @@ -616,8 +623,10 @@ static void qm_irq_unregister(struct hisi_qm *qm) if (qm->ver == QM_HW_V2) { free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm); - free_irq(pci_irq_vector(pdev, - QM_ABNORMAL_EVENT_IRQ_VECTOR), qm); + + if (qm->fun_type == QM_HW_PF) + free_irq(pci_irq_vector(pdev, + QM_ABNORMAL_EVENT_IRQ_VECTOR), qm); } } @@ -717,6 +726,24 @@ static int qm_set_sqc_cqc_vft(struct hisi_qm *qm, u32 fun_num, u32 base, return 0; } +static int qm_get_vft_v2(struct hisi_qm *qm, u32 *base, u32 *number) +{ + u64 sqc_vft; + int ret; + + ret = qm_mb(qm, QM_MB_CMD_SQC_VFT_V2, 0, 0, 1); + if (ret) + return ret; + + sqc_vft = readl(qm->io_base + QM_MB_CMD_DATA_ADDR_L) | + ((u64)readl(qm->io_base + QM_MB_CMD_DATA_ADDR_H) << 32); + *base = QM_SQC_VFT_BASE_MASK_V2 & (sqc_vft >> QM_SQC_VFT_BASE_SHIFT_V2); + *number = (QM_SQC_VFT_NUM_MASK_v2 & + (sqc_vft >> QM_SQC_VFT_NUM_SHIFT_V2)) + 1; + + return 0; +} + static void qm_hw_error_init_v1(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, u32 msi) { @@ -815,6 +842,7 @@ static const struct hisi_qm_hw_ops qm_hw_ops_v1 = { }; static const struct hisi_qm_hw_ops qm_hw_ops_v2 = { + .get_vft = qm_get_vft_v2, .qm_db = qm_db_v2, .get_irq_num = qm_get_irq_num_v2, .hw_error_init = qm_hw_error_init_v2, @@ -1195,6 +1223,9 @@ int hisi_qm_init(struct hisi_qm *qm) mutex_init(&qm->mailbox_lock); rwlock_init(&qm->qps_lock); + dev_dbg(dev, "init qm %s with %s\n", pdev->is_physfn ? "pf" : "vf", + qm->use_dma_api ? "dma api" : "iommu api"); + return 0; err_free_irq_vectors: @@ -1236,6 +1267,32 @@ void hisi_qm_uninit(struct hisi_qm *qm) } EXPORT_SYMBOL_GPL(hisi_qm_uninit); +/** + * hisi_qm_get_vft() - Get vft from a qm. + * @qm: The qm we want to get its vft. + * @base: The base number of queue in vft. + * @number: The number of queues in vft. + * + * We can allocate multiple queues to a qm by configuring virtual function + * table. We get related configures by this function. Normally, we call this + * function in VF driver to get the queue information. + * + * qm hw v1 does not support this interface. + */ +int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number) +{ + if (!base || !number) + return -EINVAL; + + if (!qm->ops->get_vft) { + dev_err(&qm->pdev->dev, "Don't support vft read!\n"); + return -EINVAL; + } + + return qm->ops->get_vft(qm, base, number); +} +EXPORT_SYMBOL_GPL(hisi_qm_get_vft); + /** * hisi_qm_set_vft() - Set "virtual function table" for a qm. * @fun_num: Number of operated function. @@ -1344,13 +1401,15 @@ static int __hisi_qm_start(struct hisi_qm *qm) if (qm->qp_num == 0) return -EINVAL; - ret = qm_dev_mem_reset(qm); - if (ret) - return ret; + if (qm->fun_type == QM_HW_PF) { + ret = qm_dev_mem_reset(qm); + if (ret) + return ret; - ret = hisi_qm_set_vft(qm, 0, qm->qp_base, qm->qp_num); - if (ret) - return ret; + ret = hisi_qm_set_vft(qm, 0, qm->qp_base, qm->qp_num); + if (ret) + return ret; + } QM_INIT_BUF(qm, eqe, QM_Q_DEPTH); QM_INIT_BUF(qm, aeqe, QM_Q_DEPTH); @@ -1469,9 +1528,11 @@ int hisi_qm_stop(struct hisi_qm *qm) } } - ret = hisi_qm_set_vft(qm, 0, 0, 0); - if (ret < 0) - dev_err(dev, "Failed to set vft!\n"); + if (qm->fun_type == QM_HW_PF) { + ret = hisi_qm_set_vft(qm, 0, 0, 0); + if (ret < 0) + dev_err(dev, "Failed to set vft!\n"); + } return ret; } diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h index a5849db163cb..8b3cb69dffca 100644 --- a/drivers/crypto/hisilicon/qm.h +++ b/drivers/crypto/hisilicon/qm.h @@ -80,6 +80,7 @@ enum qm_hw_ver { enum qm_fun_type { QM_HW_PF, + QM_HW_VF, }; struct qm_dma { @@ -98,6 +99,7 @@ struct hisi_qm_status { struct hisi_qm { enum qm_hw_ver ver; + enum qm_fun_type fun_type; const char *dev_name; struct pci_dev *pdev; void __iomem *io_base; @@ -174,7 +176,9 @@ int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg); int hisi_qm_stop_qp(struct hisi_qp *qp); void hisi_qm_release_qp(struct hisi_qp *qp); int hisi_qp_send(struct hisi_qp *qp, const void *msg); +int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number); int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base, u32 number); +int hisi_qm_debug_init(struct hisi_qm *qm); void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, u32 msi); int hisi_qm_hw_error_handle(struct hisi_qm *qm); diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index ee4e20e0230e..b3e4f1ab9240 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -12,6 +12,7 @@ #include "zip.h" #define PCI_DEVICE_ID_ZIP_PF 0xa250 +#define PCI_DEVICE_ID_ZIP_VF 0xa251 #define HZIP_VF_NUM 63 #define HZIP_QUEUE_NUM_V1 4096 @@ -127,6 +128,7 @@ static const struct hisi_zip_hw_error zip_hw_error[] = { * Just relevant for PF. */ struct hisi_zip_ctrl { + u32 num_vfs; struct hisi_zip *hisi_zip; }; @@ -180,6 +182,7 @@ module_param(uacce_mode, int, 0); static const struct pci_device_id hisi_zip_dev_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_ZIP_PF) }, + { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_ZIP_VF) }, { 0, } }; MODULE_DEVICE_TABLE(pci, hisi_zip_dev_ids); @@ -324,6 +327,8 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) qm->sqe_size = HZIP_SQE_SIZE; qm->dev_name = hisi_zip_name; + qm->fun_type = (pdev->device == PCI_DEVICE_ID_ZIP_PF) ? QM_HW_PF : + QM_HW_VF; switch (uacce_mode) { case 0: qm->use_dma_api = true; @@ -344,12 +349,28 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } - ret = hisi_zip_pf_probe_init(hisi_zip); - if (ret) - goto err_qm_uninit; - - qm->qp_base = HZIP_PF_DEF_Q_BASE; - qm->qp_num = pf_q_num; + if (qm->fun_type == QM_HW_PF) { + ret = hisi_zip_pf_probe_init(hisi_zip); + if (ret) + return ret; + + qm->qp_base = HZIP_PF_DEF_Q_BASE; + qm->qp_num = pf_q_num; + } else if (qm->fun_type == QM_HW_VF) { + /* + * have no way to get qm configure in VM in v1 hardware, + * so currently force PF to uses HZIP_PF_DEF_Q_NUM, and force + * to trigger only one VF in v1 hardware. + * + * v2 hardware has no such problem. + */ + if (qm->ver == QM_HW_V1) { + qm->qp_base = HZIP_PF_DEF_Q_NUM; + qm->qp_num = HZIP_QUEUE_NUM_V1 - HZIP_PF_DEF_Q_NUM; + } else if (qm->ver == QM_HW_V2) + /* v2 starts to support get vft by mailbox */ + hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num); + } ret = hisi_qm_start(qm); if (ret) @@ -364,13 +385,127 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } +/* Currently we only support equal assignment */ +static int hisi_zip_vf_q_assign(struct hisi_zip *hisi_zip, int num_vfs) +{ + struct hisi_qm *qm = &hisi_zip->qm; + u32 qp_num = qm->qp_num; + u32 q_base = qp_num; + u32 q_num, remain_q_num, i; + int ret; + + if (!num_vfs) + return -EINVAL; + + remain_q_num = qm->ctrl_qp_num - qp_num; + if (remain_q_num < num_vfs) + return -EINVAL; + + q_num = remain_q_num / num_vfs; + for (i = 1; i <= num_vfs; i++) { + if (i == num_vfs) + q_num += remain_q_num % num_vfs; + ret = hisi_qm_set_vft(qm, i, q_base, q_num); + if (ret) + return ret; + q_base += q_num; + } + + return 0; +} + +static int hisi_zip_clear_vft_config(struct hisi_zip *hisi_zip) +{ + struct hisi_zip_ctrl *ctrl = hisi_zip->ctrl; + struct hisi_qm *qm = &hisi_zip->qm; + u32 i, num_vfs = ctrl->num_vfs; + int ret; + + for (i = 1; i <= num_vfs; i++) { + ret = hisi_qm_set_vft(qm, i, 0, 0); + if (ret) + return ret; + } + + ctrl->num_vfs = 0; + + return 0; +} + +static int hisi_zip_sriov_enable(struct pci_dev *pdev, int max_vfs) +{ +#ifdef CONFIG_PCI_IOV + struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); + int pre_existing_vfs, num_vfs, ret; + + pre_existing_vfs = pci_num_vf(pdev); + + if (pre_existing_vfs) { + dev_err(&pdev->dev, + "Can't enable VF. Please disable pre-enabled VFs!\n"); + return 0; + } + + num_vfs = min_t(int, max_vfs, HZIP_VF_NUM); + + ret = hisi_zip_vf_q_assign(hisi_zip, num_vfs); + if (ret) { + dev_err(&pdev->dev, "Can't assign queues for VF!\n"); + return ret; + } + + hisi_zip->ctrl->num_vfs = num_vfs; + + ret = pci_enable_sriov(pdev, num_vfs); + if (ret) { + dev_err(&pdev->dev, "Can't enable VF!\n"); + hisi_zip_clear_vft_config(hisi_zip); + return ret; + } + + return num_vfs; +#else + return 0; +#endif +} + +static int hisi_zip_sriov_disable(struct pci_dev *pdev) +{ + struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); + + if (pci_vfs_assigned(pdev)) { + dev_err(&pdev->dev, + "Can't disable VFs while VFs are assigned!\n"); + return -EPERM; + } + + /* remove in hisi_zip_pci_driver will be called to free VF resources */ + pci_disable_sriov(pdev); + + return hisi_zip_clear_vft_config(hisi_zip); +} + +static int hisi_zip_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + if (num_vfs == 0) + return hisi_zip_sriov_disable(pdev); + else + return hisi_zip_sriov_enable(pdev, num_vfs); +} + static void hisi_zip_remove(struct pci_dev *pdev) { struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); struct hisi_qm *qm = &hisi_zip->qm; + if (qm->fun_type == QM_HW_PF && hisi_zip->ctrl->num_vfs != 0) + hisi_zip_sriov_disable(pdev); + hisi_qm_stop(qm); - hisi_zip_hw_error_set_state(hisi_zip, false); + + if (qm->fun_type == QM_HW_PF) + hisi_zip_hw_error_set_state(hisi_zip, false); + hisi_qm_uninit(qm); hisi_zip_remove_from_list(hisi_zip); } @@ -461,6 +596,7 @@ static struct pci_driver hisi_zip_pci_driver = { .id_table = hisi_zip_dev_ids, .probe = hisi_zip_probe, .remove = hisi_zip_remove, + .sriov_configure = hisi_zip_sriov_configure, .err_handler = &hisi_zip_err_handler, }; -- GitLab From 8201fdf49ff0950fa7a0c55a4aeb1ba3d747d404 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:54 +0800 Subject: [PATCH 2350/7155] Documentation: Add debugfs doc for hisi_zip Add debugfs descriptions for HiSilicon ZIP and QM driver. Signed-off-by: Zhou Wang Reviewed-by: Jonathan Cameron Signed-off-by: Herbert Xu --- Documentation/ABI/testing/debugfs-hisi-zip | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/ABI/testing/debugfs-hisi-zip diff --git a/Documentation/ABI/testing/debugfs-hisi-zip b/Documentation/ABI/testing/debugfs-hisi-zip new file mode 100644 index 000000000000..a7c63e6c4bc3 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-hisi-zip @@ -0,0 +1,50 @@ +What: /sys/kernel/debug/hisi_zip//comp_core[01]/regs +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: Dump of compression cores related debug registers. + Only available for PF. + +What: /sys/kernel/debug/hisi_zip//decomp_core[0-5]/regs +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: Dump of decompression cores related debug registers. + Only available for PF. + +What: /sys/kernel/debug/hisi_zip//clear_enable +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: Compression/decompression core debug registers read clear + control. 1 means enable register read clear, otherwise 0. + Writing to this file has no functional effect, only enable or + disable counters clear after reading of these registers. + Only available for PF. + +What: /sys/kernel/debug/hisi_zip//current_qm +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: One ZIP controller has one PF and multiple VFs, each function + has a QM. Select the QM which below qm refers to. + Only available for PF. + +What: /sys/kernel/debug/hisi_zip//qm/qm_regs +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: Dump of QM related debug registers. + Available for PF and VF in host. VF in guest currently only + has one debug register. + +What: /sys/kernel/debug/hisi_zip//qm/current_q +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: One QM may contain multiple queues. Select specific queue to + show its debug registers in above qm_regs. + Only available for PF. + +What: /sys/kernel/debug/hisi_zip//qm/clear_enable +Date: Nov 2018 +Contact: linux-crypto@vger.kernel.org +Description: QM debug registers(qm_regs) read clear control. 1 means enable + register read clear, otherwise 0. + Writing to this file has no functional effect, only enable or + disable counters clear after reading of these registers. + Only available for PF. -- GitLab From 72c7a68d2ea34803e9c4ef948261ec6744fc72fc Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:55 +0800 Subject: [PATCH 2351/7155] crypto: hisilicon - add debugfs for ZIP and QM HiSilicon ZIP engine driver uses debugfs to provide debug information, the usage can be found in /Documentation/ABI/testing/debugfs-hisi-zip. Signed-off-by: Zhou Wang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 301 +++++++++++++++++++ drivers/crypto/hisilicon/qm.h | 29 ++ drivers/crypto/hisilicon/zip/zip_main.c | 375 +++++++++++++++++++++++- 3 files changed, 704 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 4f6bbdd4a25b..363f71b77aed 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -2,10 +2,12 @@ /* Copyright (c) 2019 HiSilicon Limited. */ #include #include +#include #include #include #include #include +#include #include #include "qm.h" @@ -114,6 +116,7 @@ #define QM_SQC_VFT_NUM_SHIFT_V2 45 #define QM_SQC_VFT_NUM_MASK_v2 GENMASK(9, 0) +#define QM_DFX_CNT_CLR_CE 0x100118 #define QM_ABNORMAL_INT_SOURCE 0x100000 #define QM_ABNORMAL_INT_MASK 0x100004 @@ -141,6 +144,7 @@ #define QM_SQE_DATA_ALIGN_MASK GENMASK(6, 0) #define QMC_ALIGN(sz) ALIGN(sz, 32) +#define QM_DBG_TMP_BUF_LEN 22 #define QM_MK_CQC_DW3_V1(hop_num, pg_sz, buf_sz, cqe_sz) \ (((hop_num) << QM_CQ_HOP_NUM_SHIFT) | \ @@ -270,11 +274,17 @@ struct hisi_qm_hw_ops { void (*qm_db)(struct hisi_qm *qm, u16 qn, u8 cmd, u16 index, u8 priority); u32 (*get_irq_num)(struct hisi_qm *qm); + int (*debug_init)(struct hisi_qm *qm); void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, u32 msi); pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm); }; +static const char * const qm_debug_file_name[] = { + [CURRENT_Q] = "current_q", + [CLEAR_ENABLE] = "clear_enable", +}; + struct hisi_qm_hw_error { u32 int_msk; const char *msg; @@ -744,6 +754,229 @@ static int qm_get_vft_v2(struct hisi_qm *qm, u32 *base, u32 *number) return 0; } +static struct hisi_qm *file_to_qm(struct debugfs_file *file) +{ + struct qm_debug *debug = file->debug; + + return container_of(debug, struct hisi_qm, debug); +} + +static u32 current_q_read(struct debugfs_file *file) +{ + struct hisi_qm *qm = file_to_qm(file); + + return readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) >> QM_DFX_QN_SHIFT; +} + +static int current_q_write(struct debugfs_file *file, u32 val) +{ + struct hisi_qm *qm = file_to_qm(file); + u32 tmp; + + if (val >= qm->debug.curr_qm_qp_num) + return -EINVAL; + + tmp = val << QM_DFX_QN_SHIFT | + (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_FUN_MASK); + writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN); + + tmp = val << QM_DFX_QN_SHIFT | + (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_FUN_MASK); + writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN); + + return 0; +} + +static u32 clear_enable_read(struct debugfs_file *file) +{ + struct hisi_qm *qm = file_to_qm(file); + + return readl(qm->io_base + QM_DFX_CNT_CLR_CE); +} + +/* rd_clr_ctrl 1 enable read clear, otherwise 0 disable it */ +static int clear_enable_write(struct debugfs_file *file, u32 rd_clr_ctrl) +{ + struct hisi_qm *qm = file_to_qm(file); + + if (rd_clr_ctrl > 1) + return -EINVAL; + + writel(rd_clr_ctrl, qm->io_base + QM_DFX_CNT_CLR_CE); + + return 0; +} + +static ssize_t qm_debug_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct debugfs_file *file = filp->private_data; + enum qm_debug_file index = file->index; + char tbuf[QM_DBG_TMP_BUF_LEN]; + u32 val; + int ret; + + mutex_lock(&file->lock); + switch (index) { + case CURRENT_Q: + val = current_q_read(file); + break; + case CLEAR_ENABLE: + val = clear_enable_read(file); + break; + default: + mutex_unlock(&file->lock); + return -EINVAL; + } + mutex_unlock(&file->lock); + ret = sprintf(tbuf, "%u\n", val); + return simple_read_from_buffer(buf, count, pos, tbuf, ret); +} + +static ssize_t qm_debug_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct debugfs_file *file = filp->private_data; + enum qm_debug_file index = file->index; + unsigned long val; + char tbuf[QM_DBG_TMP_BUF_LEN]; + int len, ret; + + if (*pos != 0) + return 0; + + if (count >= QM_DBG_TMP_BUF_LEN) + return -ENOSPC; + + len = simple_write_to_buffer(tbuf, QM_DBG_TMP_BUF_LEN - 1, pos, buf, + count); + if (len < 0) + return len; + + tbuf[len] = '\0'; + if (kstrtoul(tbuf, 0, &val)) + return -EFAULT; + + mutex_lock(&file->lock); + switch (index) { + case CURRENT_Q: + ret = current_q_write(file, val); + if (ret) + goto err_input; + break; + case CLEAR_ENABLE: + ret = clear_enable_write(file, val); + if (ret) + goto err_input; + break; + default: + ret = -EINVAL; + goto err_input; + } + mutex_unlock(&file->lock); + + return count; + +err_input: + mutex_unlock(&file->lock); + return ret; +} + +static const struct file_operations qm_debug_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = qm_debug_read, + .write = qm_debug_write, +}; + +struct qm_dfx_registers { + char *reg_name; + u64 reg_offset; +}; + +#define CNT_CYC_REGS_NUM 10 +static struct qm_dfx_registers qm_dfx_regs[] = { + /* XXX_CNT are reading clear register */ + {"QM_ECC_1BIT_CNT ", 0x104000ull}, + {"QM_ECC_MBIT_CNT ", 0x104008ull}, + {"QM_DFX_MB_CNT ", 0x104018ull}, + {"QM_DFX_DB_CNT ", 0x104028ull}, + {"QM_DFX_SQE_CNT ", 0x104038ull}, + {"QM_DFX_CQE_CNT ", 0x104048ull}, + {"QM_DFX_SEND_SQE_TO_ACC_CNT ", 0x104050ull}, + {"QM_DFX_WB_SQE_FROM_ACC_CNT ", 0x104058ull}, + {"QM_DFX_ACC_FINISH_CNT ", 0x104060ull}, + {"QM_DFX_CQE_ERR_CNT ", 0x1040b4ull}, + {"QM_DFX_FUNS_ACTIVE_ST ", 0x200ull}, + {"QM_ECC_1BIT_INF ", 0x104004ull}, + {"QM_ECC_MBIT_INF ", 0x10400cull}, + {"QM_DFX_ACC_RDY_VLD0 ", 0x1040a0ull}, + {"QM_DFX_ACC_RDY_VLD1 ", 0x1040a4ull}, + {"QM_DFX_AXI_RDY_VLD ", 0x1040a8ull}, + {"QM_DFX_FF_ST0 ", 0x1040c8ull}, + {"QM_DFX_FF_ST1 ", 0x1040ccull}, + {"QM_DFX_FF_ST2 ", 0x1040d0ull}, + {"QM_DFX_FF_ST3 ", 0x1040d4ull}, + {"QM_DFX_FF_ST4 ", 0x1040d8ull}, + {"QM_DFX_FF_ST5 ", 0x1040dcull}, + {"QM_DFX_FF_ST6 ", 0x1040e0ull}, + {"QM_IN_IDLE_ST ", 0x1040e4ull}, + { NULL, 0} +}; + +static struct qm_dfx_registers qm_vf_dfx_regs[] = { + {"QM_DFX_FUNS_ACTIVE_ST ", 0x200ull}, + { NULL, 0} +}; + +static int qm_regs_show(struct seq_file *s, void *unused) +{ + struct hisi_qm *qm = s->private; + struct qm_dfx_registers *regs; + u32 val; + + if (qm->fun_type == QM_HW_PF) + regs = qm_dfx_regs; + else + regs = qm_vf_dfx_regs; + + while (regs->reg_name) { + val = readl(qm->io_base + regs->reg_offset); + seq_printf(s, "%s= 0x%08x\n", regs->reg_name, val); + regs++; + } + + return 0; +} + +static int qm_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, qm_regs_show, inode->i_private); +} + +static const struct file_operations qm_regs_fops = { + .owner = THIS_MODULE, + .open = qm_regs_open, + .read = seq_read, +}; + +static int qm_create_debugfs_file(struct hisi_qm *qm, enum qm_debug_file index) +{ + struct dentry *qm_d = qm->debug.qm_d, *tmp; + struct debugfs_file *file = qm->debug.files + index; + + tmp = debugfs_create_file(qm_debug_file_name[index], 0600, qm_d, file, + &qm_debug_fops); + if (IS_ERR(tmp)) + return -ENOENT; + + file->index = index; + mutex_init(&file->lock); + file->debug = &qm->debug; + + return 0; +} + static void qm_hw_error_init_v1(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, u32 msi) { @@ -1538,6 +1771,74 @@ int hisi_qm_stop(struct hisi_qm *qm) } EXPORT_SYMBOL_GPL(hisi_qm_stop); +/** + * hisi_qm_debug_init() - Initialize qm related debugfs files. + * @qm: The qm for which we want to add debugfs files. + * + * Create qm related debugfs files. + */ +int hisi_qm_debug_init(struct hisi_qm *qm) +{ + struct dentry *qm_d, *qm_regs; + int i, ret; + + qm_d = debugfs_create_dir("qm", qm->debug.debug_root); + if (IS_ERR(qm_d)) + return -ENOENT; + qm->debug.qm_d = qm_d; + + /* only show this in PF */ + if (qm->fun_type == QM_HW_PF) + for (i = CURRENT_Q; i < DEBUG_FILE_NUM; i++) + if (qm_create_debugfs_file(qm, i)) { + ret = -ENOENT; + goto failed_to_create; + } + + qm_regs = debugfs_create_file("qm_regs", 0444, qm->debug.qm_d, qm, + &qm_regs_fops); + if (IS_ERR(qm_regs)) { + ret = -ENOENT; + goto failed_to_create; + } + + return 0; + +failed_to_create: + debugfs_remove_recursive(qm_d); + return ret; +} +EXPORT_SYMBOL_GPL(hisi_qm_debug_init); + +/** + * hisi_qm_debug_regs_clear() - clear qm debug related registers. + * @qm: The qm for which we want to clear its debug registers. + */ +void hisi_qm_debug_regs_clear(struct hisi_qm *qm) +{ + struct qm_dfx_registers *regs; + int i; + + /* clear current_q */ + writel(0x0, qm->io_base + QM_DFX_SQE_CNT_VF_SQN); + writel(0x0, qm->io_base + QM_DFX_CQE_CNT_VF_CQN); + + /* + * these registers are reading and clearing, so clear them after + * reading them. + */ + writel(0x1, qm->io_base + QM_DFX_CNT_CLR_CE); + + regs = qm_dfx_regs; + for (i = 0; i < CNT_CYC_REGS_NUM; i++) { + readl(qm->io_base + regs->reg_offset); + regs++; + } + + writel(0x0, qm->io_base + QM_DFX_CNT_CLR_CE); +} +EXPORT_SYMBOL_GPL(hisi_qm_debug_regs_clear); + /** * hisi_qm_hw_error_init() - Configure qm hardware error report method. * @qm: The qm which we want to configure. diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h index 8b3cb69dffca..70e672ae86bf 100644 --- a/drivers/crypto/hisilicon/qm.h +++ b/drivers/crypto/hisilicon/qm.h @@ -46,6 +46,13 @@ #define PEH_AXUSER_CFG 0x401001 #define PEH_AXUSER_CFG_ENABLE 0xffffffff +#define QM_DFX_MB_CNT_VF 0x104010 +#define QM_DFX_DB_CNT_VF 0x104020 +#define QM_DFX_SQE_CNT_VF_SQN 0x104030 +#define QM_DFX_CQE_CNT_VF_CQN 0x104040 +#define QM_DFX_QN_SHIFT 16 +#define CURRENT_FUN_MASK GENMASK(5, 0) +#define CURRENT_Q_MASK GENMASK(31, 16) #define QM_AXI_RRESP BIT(0) #define QM_AXI_BRESP BIT(1) @@ -83,6 +90,25 @@ enum qm_fun_type { QM_HW_VF, }; +enum qm_debug_file { + CURRENT_Q, + CLEAR_ENABLE, + DEBUG_FILE_NUM, +}; + +struct debugfs_file { + enum qm_debug_file index; + struct mutex lock; + struct qm_debug *debug; +}; + +struct qm_debug { + u32 curr_qm_qp_num; + struct dentry *debug_root; + struct dentry *qm_d; + struct debugfs_file files[DEBUG_FILE_NUM]; +}; + struct qm_dma { void *va; dma_addr_t dma; @@ -128,6 +154,8 @@ struct hisi_qm { const struct hisi_qm_hw_ops *ops; + struct qm_debug debug; + u32 error_mask; u32 msi_mask; @@ -183,4 +211,5 @@ void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, u32 msi); int hisi_qm_hw_error_handle(struct hisi_qm *qm); enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev); +void hisi_qm_debug_regs_clear(struct hisi_qm *qm); #endif diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index b3e4f1ab9240..6e0ca75585d4 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -3,11 +3,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include "zip.h" @@ -32,6 +34,7 @@ DECOMP2_ENABLE | DECOMP3_ENABLE | \ DECOMP4_ENABLE | DECOMP5_ENABLE) #define DECOMP_CHECK_ENABLE BIT(16) +#define HZIP_FSM_MAX_CNT 0x301008 #define HZIP_PORT_ARCA_CHE_0 0x301040 #define HZIP_PORT_ARCA_CHE_1 0x301044 @@ -45,7 +48,16 @@ #define HZIP_DATA_WUSER_32_63 0x301134 #define HZIP_BD_WUSER_32_63 0x301140 +#define HZIP_QM_IDEL_STATUS 0x3040e4 +#define HZIP_CORE_DEBUG_COMP_0 0x302000 +#define HZIP_CORE_DEBUG_COMP_1 0x303000 +#define HZIP_CORE_DEBUG_DECOMP_0 0x304000 +#define HZIP_CORE_DEBUG_DECOMP_1 0x305000 +#define HZIP_CORE_DEBUG_DECOMP_2 0x306000 +#define HZIP_CORE_DEBUG_DECOMP_3 0x307000 +#define HZIP_CORE_DEBUG_DECOMP_4 0x308000 +#define HZIP_CORE_DEBUG_DECOMP_5 0x309000 #define HZIP_CORE_INT_SOURCE 0x3010A0 #define HZIP_CORE_INT_MASK 0x3010A4 @@ -55,14 +67,23 @@ #define SRAM_ECC_ERR_NUM_SHIFT 16 #define SRAM_ECC_ERR_ADDR_SHIFT 24 #define HZIP_CORE_INT_DISABLE 0x000007FF +#define HZIP_COMP_CORE_NUM 2 +#define HZIP_DECOMP_CORE_NUM 6 +#define HZIP_CORE_NUM (HZIP_COMP_CORE_NUM + \ + HZIP_DECOMP_CORE_NUM) #define HZIP_SQE_SIZE 128 +#define HZIP_SQ_SIZE (HZIP_SQE_SIZE * QM_Q_DEPTH) #define HZIP_PF_DEF_Q_NUM 64 #define HZIP_PF_DEF_Q_BASE 0 +#define HZIP_SOFT_CTRL_CNT_CLR_CE 0x301000 +#define SOFT_CTRL_CNT_CLR_CE_BIT BIT(0) #define HZIP_NUMA_DISTANCE 100 +#define HZIP_BUF_SIZE 22 static const char hisi_zip_name[] = "hisi_zip"; +static struct dentry *hzip_debugfs_root; LIST_HEAD(hisi_zip_list); DEFINE_MUTEX(hisi_zip_list_lock); @@ -121,6 +142,23 @@ static const struct hisi_zip_hw_error zip_hw_error[] = { { /* sentinel */ } }; +enum ctrl_debug_file_index { + HZIP_CURRENT_QM, + HZIP_CLEAR_ENABLE, + HZIP_DEBUG_FILE_NUM, +}; + +static const char * const ctrl_debug_file_name[] = { + [HZIP_CURRENT_QM] = "current_qm", + [HZIP_CLEAR_ENABLE] = "clear_enable", +}; + +struct ctrl_debug_file { + enum ctrl_debug_file_index index; + spinlock_t lock; + struct hisi_zip_ctrl *ctrl; +}; + /* * One ZIP controller has one PF and multiple VFs, some global configurations * which PF has need this structure. @@ -130,6 +168,55 @@ static const struct hisi_zip_hw_error zip_hw_error[] = { struct hisi_zip_ctrl { u32 num_vfs; struct hisi_zip *hisi_zip; + struct dentry *debug_root; + struct ctrl_debug_file files[HZIP_DEBUG_FILE_NUM]; +}; + +enum { + HZIP_COMP_CORE0, + HZIP_COMP_CORE1, + HZIP_DECOMP_CORE0, + HZIP_DECOMP_CORE1, + HZIP_DECOMP_CORE2, + HZIP_DECOMP_CORE3, + HZIP_DECOMP_CORE4, + HZIP_DECOMP_CORE5, +}; + +static const u64 core_offsets[] = { + [HZIP_COMP_CORE0] = 0x302000, + [HZIP_COMP_CORE1] = 0x303000, + [HZIP_DECOMP_CORE0] = 0x304000, + [HZIP_DECOMP_CORE1] = 0x305000, + [HZIP_DECOMP_CORE2] = 0x306000, + [HZIP_DECOMP_CORE3] = 0x307000, + [HZIP_DECOMP_CORE4] = 0x308000, + [HZIP_DECOMP_CORE5] = 0x309000, +}; + +static struct debugfs_reg32 hzip_dfx_regs[] = { + {"HZIP_GET_BD_NUM ", 0x00ull}, + {"HZIP_GET_RIGHT_BD ", 0x04ull}, + {"HZIP_GET_ERROR_BD ", 0x08ull}, + {"HZIP_DONE_BD_NUM ", 0x0cull}, + {"HZIP_WORK_CYCLE ", 0x10ull}, + {"HZIP_IDLE_CYCLE ", 0x18ull}, + {"HZIP_MAX_DELAY ", 0x20ull}, + {"HZIP_MIN_DELAY ", 0x24ull}, + {"HZIP_AVG_DELAY ", 0x28ull}, + {"HZIP_MEM_VISIBLE_DATA ", 0x30ull}, + {"HZIP_MEM_VISIBLE_ADDR ", 0x34ull}, + {"HZIP_COMSUMED_BYTE ", 0x38ull}, + {"HZIP_PRODUCED_BYTE ", 0x40ull}, + {"HZIP_COMP_INF ", 0x70ull}, + {"HZIP_PRE_OUT ", 0x78ull}, + {"HZIP_BD_RD ", 0x7cull}, + {"HZIP_BD_WR ", 0x80ull}, + {"HZIP_GET_BD_AXI_ERR_NUM ", 0x84ull}, + {"HZIP_GET_BD_PARSE_ERR_NUM ", 0x88ull}, + {"HZIP_ADD_BD_AXI_ERR_NUM ", 0x8cull}, + {"HZIP_DECOMP_STF_RELOAD_CURR_ST ", 0x94ull}, + {"HZIP_DECOMP_LZ77_CURR_ST ", 0x9cull}, }; static int pf_q_num_set(const char *val, const struct kernel_param *kp) @@ -266,6 +353,265 @@ static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state) } } +static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file) +{ + struct hisi_zip *hisi_zip = file->ctrl->hisi_zip; + + return &hisi_zip->qm; +} + +static u32 current_qm_read(struct ctrl_debug_file *file) +{ + struct hisi_qm *qm = file_to_qm(file); + + return readl(qm->io_base + QM_DFX_MB_CNT_VF); +} + +static int current_qm_write(struct ctrl_debug_file *file, u32 val) +{ + struct hisi_qm *qm = file_to_qm(file); + struct hisi_zip_ctrl *ctrl = file->ctrl; + u32 vfq_num; + u32 tmp; + + if (val > ctrl->num_vfs) + return -EINVAL; + + /* Calculate curr_qm_qp_num and store */ + if (val == 0) { + qm->debug.curr_qm_qp_num = qm->qp_num; + } else { + vfq_num = (qm->ctrl_qp_num - qm->qp_num) / ctrl->num_vfs; + if (val == ctrl->num_vfs) + qm->debug.curr_qm_qp_num = qm->ctrl_qp_num - + qm->qp_num - (ctrl->num_vfs - 1) * vfq_num; + else + qm->debug.curr_qm_qp_num = vfq_num; + } + + writel(val, qm->io_base + QM_DFX_MB_CNT_VF); + writel(val, qm->io_base + QM_DFX_DB_CNT_VF); + + tmp = val | + (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_Q_MASK); + writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN); + + tmp = val | + (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_Q_MASK); + writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN); + + return 0; +} + +static u32 clear_enable_read(struct ctrl_debug_file *file) +{ + struct hisi_qm *qm = file_to_qm(file); + + return readl(qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE) & + SOFT_CTRL_CNT_CLR_CE_BIT; +} + +static int clear_enable_write(struct ctrl_debug_file *file, u32 val) +{ + struct hisi_qm *qm = file_to_qm(file); + u32 tmp; + + if (val != 1 && val != 0) + return -EINVAL; + + tmp = (readl(qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE) & + ~SOFT_CTRL_CNT_CLR_CE_BIT) | val; + writel(tmp, qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE); + + return 0; +} + +static ssize_t ctrl_debug_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct ctrl_debug_file *file = filp->private_data; + char tbuf[HZIP_BUF_SIZE]; + u32 val; + int ret; + + spin_lock_irq(&file->lock); + switch (file->index) { + case HZIP_CURRENT_QM: + val = current_qm_read(file); + break; + case HZIP_CLEAR_ENABLE: + val = clear_enable_read(file); + break; + default: + spin_unlock_irq(&file->lock); + return -EINVAL; + } + spin_unlock_irq(&file->lock); + ret = sprintf(tbuf, "%u\n", val); + return simple_read_from_buffer(buf, count, pos, tbuf, ret); +} + +static ssize_t ctrl_debug_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct ctrl_debug_file *file = filp->private_data; + char tbuf[HZIP_BUF_SIZE]; + unsigned long val; + int len, ret; + + if (*pos != 0) + return 0; + + if (count >= HZIP_BUF_SIZE) + return -ENOSPC; + + len = simple_write_to_buffer(tbuf, HZIP_BUF_SIZE - 1, pos, buf, count); + if (len < 0) + return len; + + tbuf[len] = '\0'; + if (kstrtoul(tbuf, 0, &val)) + return -EFAULT; + + spin_lock_irq(&file->lock); + switch (file->index) { + case HZIP_CURRENT_QM: + ret = current_qm_write(file, val); + if (ret) + goto err_input; + break; + case HZIP_CLEAR_ENABLE: + ret = clear_enable_write(file, val); + if (ret) + goto err_input; + break; + default: + ret = -EINVAL; + goto err_input; + } + spin_unlock_irq(&file->lock); + + return count; + +err_input: + spin_unlock_irq(&file->lock); + return ret; +} + +static const struct file_operations ctrl_debug_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = ctrl_debug_read, + .write = ctrl_debug_write, +}; + +static int hisi_zip_core_debug_init(struct hisi_zip_ctrl *ctrl) +{ + struct hisi_zip *hisi_zip = ctrl->hisi_zip; + struct hisi_qm *qm = &hisi_zip->qm; + struct device *dev = &qm->pdev->dev; + struct debugfs_regset32 *regset; + struct dentry *tmp_d, *tmp; + char buf[HZIP_BUF_SIZE]; + int i; + + for (i = 0; i < HZIP_CORE_NUM; i++) { + if (i < HZIP_COMP_CORE_NUM) + sprintf(buf, "comp_core%d", i); + else + sprintf(buf, "decomp_core%d", i - HZIP_COMP_CORE_NUM); + + tmp_d = debugfs_create_dir(buf, ctrl->debug_root); + if (!tmp_d) + return -ENOENT; + + regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); + if (!regset) + return -ENOENT; + + regset->regs = hzip_dfx_regs; + regset->nregs = ARRAY_SIZE(hzip_dfx_regs); + regset->base = qm->io_base + core_offsets[i]; + + tmp = debugfs_create_regset32("regs", 0444, tmp_d, regset); + if (!tmp) + return -ENOENT; + } + + return 0; +} + +static int hisi_zip_ctrl_debug_init(struct hisi_zip_ctrl *ctrl) +{ + struct dentry *tmp; + int i; + + for (i = HZIP_CURRENT_QM; i < HZIP_DEBUG_FILE_NUM; i++) { + spin_lock_init(&ctrl->files[i].lock); + ctrl->files[i].ctrl = ctrl; + ctrl->files[i].index = i; + + tmp = debugfs_create_file(ctrl_debug_file_name[i], 0600, + ctrl->debug_root, ctrl->files + i, + &ctrl_debug_fops); + if (!tmp) + return -ENOENT; + } + + return hisi_zip_core_debug_init(ctrl); +} + +static int hisi_zip_debugfs_init(struct hisi_zip *hisi_zip) +{ + struct hisi_qm *qm = &hisi_zip->qm; + struct device *dev = &qm->pdev->dev; + struct dentry *dev_d; + int ret; + + dev_d = debugfs_create_dir(dev_name(dev), hzip_debugfs_root); + if (!dev_d) + return -ENOENT; + + qm->debug.debug_root = dev_d; + ret = hisi_qm_debug_init(qm); + if (ret) + goto failed_to_create; + + if (qm->fun_type == QM_HW_PF) { + hisi_zip->ctrl->debug_root = dev_d; + ret = hisi_zip_ctrl_debug_init(hisi_zip->ctrl); + if (ret) + goto failed_to_create; + } + + return 0; + +failed_to_create: + debugfs_remove_recursive(hzip_debugfs_root); + return ret; +} + +static void hisi_zip_debug_regs_clear(struct hisi_zip *hisi_zip) +{ + struct hisi_qm *qm = &hisi_zip->qm; + + writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF); + writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF); + writel(0x0, qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE); + + hisi_qm_debug_regs_clear(qm); +} + +static void hisi_zip_debugfs_exit(struct hisi_zip *hisi_zip) +{ + struct hisi_qm *qm = &hisi_zip->qm; + + debugfs_remove_recursive(qm->debug.debug_root); + + if (qm->fun_type == QM_HW_PF) + hisi_zip_debug_regs_clear(hisi_zip); +} + static void hisi_zip_hw_error_init(struct hisi_zip *hisi_zip) { hisi_qm_hw_error_init(&hisi_zip->qm, QM_BASE_CE, @@ -301,6 +647,7 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) hisi_zip_set_user_domain_and_cache(hisi_zip); hisi_zip_hw_error_init(hisi_zip); + hisi_zip_debug_regs_clear(hisi_zip); return 0; } @@ -376,6 +723,10 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_qm_uninit; + ret = hisi_zip_debugfs_init(hisi_zip); + if (ret) + dev_err(&pdev->dev, "Failed to init debugfs (%d)!\n", ret); + hisi_zip_add_to_list(hisi_zip); return 0; @@ -501,6 +852,7 @@ static void hisi_zip_remove(struct pci_dev *pdev) if (qm->fun_type == QM_HW_PF && hisi_zip->ctrl->num_vfs != 0) hisi_zip_sriov_disable(pdev); + hisi_zip_debugfs_exit(hisi_zip); hisi_qm_stop(qm); if (qm->fun_type == QM_HW_PF) @@ -600,14 +952,31 @@ static struct pci_driver hisi_zip_pci_driver = { .err_handler = &hisi_zip_err_handler, }; +static void hisi_zip_register_debugfs(void) +{ + if (!debugfs_initialized()) + return; + + hzip_debugfs_root = debugfs_create_dir("hisi_zip", NULL); + if (IS_ERR_OR_NULL(hzip_debugfs_root)) + hzip_debugfs_root = NULL; +} + +static void hisi_zip_unregister_debugfs(void) +{ + debugfs_remove_recursive(hzip_debugfs_root); +} + static int __init hisi_zip_init(void) { int ret; + hisi_zip_register_debugfs(); + ret = pci_register_driver(&hisi_zip_pci_driver); if (ret < 0) { pr_err("Failed to register pci driver.\n"); - return ret; + goto err_pci; } if (uacce_mode == 0 || uacce_mode == 2) { @@ -622,6 +991,9 @@ static int __init hisi_zip_init(void) err_crypto: pci_unregister_driver(&hisi_zip_pci_driver); +err_pci: + hisi_zip_unregister_debugfs(); + return ret; } @@ -630,6 +1002,7 @@ static void __exit hisi_zip_exit(void) if (uacce_mode == 0 || uacce_mode == 2) hisi_zip_unregister_from_crypto(); pci_unregister_driver(&hisi_zip_pci_driver); + hisi_zip_unregister_debugfs(); } module_init(hisi_zip_init); -- GitLab From ad3f0a93b639c342abbe8982cc34a3370169c464 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 2 Aug 2019 15:57:56 +0800 Subject: [PATCH 2352/7155] MAINTAINERS: add maintainer for HiSilicon QM and ZIP controller driver Add Zhou Wang as a maintainer for HiSilicon QM and ZIP controller driver. Signed-off-by: Zhou Wang Reviewed-by: John Garry Signed-off-by: Herbert Xu --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..667aac441f75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7307,6 +7307,17 @@ S: Supported F: drivers/scsi/hisi_sas/ F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +HISILICON QM AND ZIP Controller DRIVER +M: Zhou Wang +L: linux-crypto@vger.kernel.org +S: Maintained +F: drivers/crypto/hisilicon/qm.c +F: drivers/crypto/hisilicon/qm.h +F: drivers/crypto/hisilicon/sgl.c +F: drivers/crypto/hisilicon/sgl.h +F: drivers/crypto/hisilicon/zip/ +F: Documentation/ABI/testing/debugfs-hisi-zip + HMM - Heterogeneous Memory Management M: Jérôme Glisse L: linux-mm@kvack.org -- GitLab From 74bf81d0968c2262926dc2a690e671ebb768f2ec Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Fri, 2 Aug 2019 11:47:33 +0300 Subject: [PATCH 2353/7155] crypto: gcm - restrict assoclen for rfc4543 Based on seqiv, IPsec ESP and rfc4543/rfc4106 the assoclen can be 16 or 20 bytes. From esp4/esp6, assoclen is sizeof IP Header. This includes spi, seq_no and extended seq_no, that is 8 or 12 bytes. In seqiv, to asscolen is added the IV size (8 bytes). Therefore, the assoclen, for rfc4543, should be restricted to 16 or 20 bytes, as for rfc4106. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta Signed-off-by: Herbert Xu --- crypto/gcm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/gcm.c b/crypto/gcm.c index 2f3b50f8f3e0..73884208f075 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -1034,12 +1034,14 @@ static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc) static int crypto_rfc4543_encrypt(struct aead_request *req) { - return crypto_rfc4543_crypt(req, true); + return crypto_ipsec_check_assoclen(req->assoclen) ?: + crypto_rfc4543_crypt(req, true); } static int crypto_rfc4543_decrypt(struct aead_request *req) { - return crypto_rfc4543_crypt(req, false); + return crypto_ipsec_check_assoclen(req->assoclen) ?: + crypto_rfc4543_crypt(req, false); } static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm) -- GitLab From 0866ba23b7efcc6837d6b4231bf91b79647b81ea Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:27:58 +0800 Subject: [PATCH 2354/7155] crypto: artpec6 - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/axis/artpec6_crypto.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index 80fa04ef215f..4b20606983a4 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c @@ -2854,7 +2854,6 @@ static int artpec6_crypto_probe(struct platform_device *pdev) struct artpec6_crypto *ac; struct device *dev = &pdev->dev; void __iomem *base; - struct resource *res; int irq; int err; @@ -2867,8 +2866,7 @@ static int artpec6_crypto_probe(struct platform_device *pdev) variant = (enum artpec6_crypto_variant)match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 17729e56f9b8f9f0a057ea16571cdea0457900f0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:27:59 +0800 Subject: [PATCH 2355/7155] crypto: ccp - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sp-platform.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c index 1b45236e3716..831aac1393a2 100644 --- a/drivers/crypto/ccp/sp-platform.c +++ b/drivers/crypto/ccp/sp-platform.c @@ -125,7 +125,6 @@ static int sp_platform_probe(struct platform_device *pdev) struct sp_platform *sp_platform; struct device *dev = &pdev->dev; enum dev_dma_attr attr; - struct resource *ior; int ret; ret = -ENOMEM; @@ -146,8 +145,7 @@ static int sp_platform_probe(struct platform_device *pdev) goto e_err; } - ior = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sp->io_map = devm_ioremap_resource(dev, ior); + sp->io_map = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sp->io_map)) { ret = PTR_ERR(sp->io_map); goto e_err; -- GitLab From 6d1c0186f392e77b9e873490bed4d27b2fe580d7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:00 +0800 Subject: [PATCH 2356/7155] crypto: exynos - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/crypto/exynos-rng.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c index 2cfabb99cb6e..cbd8ca6e52ee 100644 --- a/drivers/crypto/exynos-rng.c +++ b/drivers/crypto/exynos-rng.c @@ -268,7 +268,6 @@ static struct rng_alg exynos_rng_alg = { static int exynos_rng_probe(struct platform_device *pdev) { struct exynos_rng_dev *rng; - struct resource *res; int ret; if (exynos_rng_dev) @@ -289,8 +288,7 @@ static int exynos_rng_probe(struct platform_device *pdev) return PTR_ERR(rng->clk); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rng->mem = devm_ioremap_resource(&pdev->dev, res); + rng->mem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rng->mem)) return PTR_ERR(rng->mem); -- GitLab From f78c7123ff4cfb90572633d79d85e20f29f87112 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:01 +0800 Subject: [PATCH 2357/7155] crypto: img-hash - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/img-hash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index 6754eaafdc85..fe4cc8babe1c 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -958,9 +958,7 @@ static int img_hash_probe(struct platform_device *pdev) crypto_init_queue(&hdev->queue, IMG_HASH_QUEUE_LENGTH); /* Register bank */ - hash_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - hdev->io_base = devm_ioremap_resource(dev, hash_res); + hdev->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hdev->io_base)) { err = PTR_ERR(hdev->io_base); dev_err(dev, "can't ioremap, returned %d\n", err); -- GitLab From f8dab5575b76ea01b300e4b3a145955763ed61a9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:02 +0800 Subject: [PATCH 2358/7155] crypto: inside-secure - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index d1f60fd7e91a..822744dc9c21 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -999,7 +999,6 @@ static void safexcel_init_register_offsets(struct safexcel_crypto_priv *priv) static int safexcel_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct safexcel_crypto_priv *priv; int i, ret; @@ -1015,8 +1014,7 @@ static int safexcel_probe(struct platform_device *pdev) safexcel_init_register_offsets(priv); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { dev_err(dev, "failed to get resource\n"); return PTR_ERR(priv->base); -- GitLab From b26120fdb9326052cc0bffe6a52c19a7145d3851 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:03 +0800 Subject: [PATCH 2359/7155] crypto: mediatek - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/mediatek/mtk-platform.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/mediatek/mtk-platform.c b/drivers/crypto/mediatek/mtk-platform.c index 4f43318ca14b..7e3ad085b5bd 100644 --- a/drivers/crypto/mediatek/mtk-platform.c +++ b/drivers/crypto/mediatek/mtk-platform.c @@ -481,7 +481,6 @@ static int mtk_desc_ring_alloc(struct mtk_cryp *cryp) static int mtk_crypto_probe(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct mtk_cryp *cryp; int i, err; @@ -489,7 +488,7 @@ static int mtk_crypto_probe(struct platform_device *pdev) if (!cryp) return -ENOMEM; - cryp->base = devm_ioremap_resource(&pdev->dev, res); + cryp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cryp->base)) return PTR_ERR(cryp->base); -- GitLab From 9a8e0a513b2b07aad90182cce102032437795778 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:04 +0800 Subject: [PATCH 2360/7155] crypto: picoxcell - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Jamie Iles Signed-off-by: Herbert Xu --- drivers/crypto/picoxcell_crypto.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c index b985cb85c9bc..9a939b4fd32f 100644 --- a/drivers/crypto/picoxcell_crypto.c +++ b/drivers/crypto/picoxcell_crypto.c @@ -1624,7 +1624,7 @@ MODULE_DEVICE_TABLE(of, spacc_of_id_table); static int spacc_probe(struct platform_device *pdev) { int i, err, ret; - struct resource *mem, *irq; + struct resource *irq; struct device_node *np = pdev->dev.of_node; struct spacc_engine *engine = devm_kzalloc(&pdev->dev, sizeof(*engine), GFP_KERNEL); @@ -1653,8 +1653,7 @@ static int spacc_probe(struct platform_device *pdev) engine->name = dev_name(&pdev->dev); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - engine->regs = devm_ioremap_resource(&pdev->dev, mem); + engine->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(engine->regs)) return PTR_ERR(engine->regs); -- GitLab From cf68528f9aaae3e5022bf9a4c71769ad48636c89 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:05 +0800 Subject: [PATCH 2361/7155] crypto: sunxi-ss - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/sunxi-ss/sun4i-ss-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c index 2e8704271f45..9aa6fe081a27 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c @@ -225,7 +225,6 @@ static struct sun4i_ss_alg_template ss_algs[] = { static int sun4i_ss_probe(struct platform_device *pdev) { - struct resource *res; u32 v; int err, i; unsigned long cr; @@ -240,8 +239,7 @@ static int sun4i_ss_probe(struct platform_device *pdev) if (!ss) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ss->base = devm_ioremap_resource(&pdev->dev, res); + ss->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ss->base)) { dev_err(&pdev->dev, "Cannot request MMIO\n"); return PTR_ERR(ss->base); -- GitLab From 721744730ab06079df8197a700dc8929dadfcebc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:06 +0800 Subject: [PATCH 2362/7155] crypto: rockchip - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Heiko Stuebner Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index 8d7e2545e65a..e5714ef24bf2 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -311,7 +311,6 @@ MODULE_DEVICE_TABLE(of, crypto_of_id_table); static int rk_crypto_probe(struct platform_device *pdev) { - struct resource *res; struct device *dev = &pdev->dev; struct rk_crypto_info *crypto_info; int err = 0; @@ -339,8 +338,7 @@ static int rk_crypto_probe(struct platform_device *pdev) spin_lock_init(&crypto_info->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - crypto_info->reg = devm_ioremap_resource(&pdev->dev, res); + crypto_info->reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(crypto_info->reg)) { err = PTR_ERR(crypto_info->reg); goto err_crypto; -- GitLab From 473b4d995963b158f1713274c7992aed9240eb45 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:07 +0800 Subject: [PATCH 2363/7155] crypto: stm32 - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/stm32/stm32-crc32.c | 4 +--- drivers/crypto/stm32/stm32-cryp.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c index 440c9f1bd006..9e11c3480353 100644 --- a/drivers/crypto/stm32/stm32-crc32.c +++ b/drivers/crypto/stm32/stm32-crc32.c @@ -255,7 +255,6 @@ static int stm32_crc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct stm32_crc *crc; - struct resource *res; int ret; crc = devm_kzalloc(dev, sizeof(*crc), GFP_KERNEL); @@ -264,8 +263,7 @@ static int stm32_crc_probe(struct platform_device *pdev) crc->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - crc->regs = devm_ioremap_resource(dev, res); + crc->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(crc->regs)) { dev_err(dev, "Cannot map CRC IO\n"); return PTR_ERR(crc->regs); diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index 72f86063b046..5cf6679da580 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -1955,7 +1955,6 @@ static int stm32_cryp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct stm32_cryp *cryp; - struct resource *res; struct reset_control *rst; int irq, ret; @@ -1969,8 +1968,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) cryp->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - cryp->regs = devm_ioremap_resource(dev, res); + cryp->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cryp->regs)) return PTR_ERR(cryp->regs); -- GitLab From a54d83d42890e986018d0957fdd683df536505aa Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:08 +0800 Subject: [PATCH 2364/7155] crypto: qce - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/qce/core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index ef1d74e8ddb2..08d4ce3bfddf 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -167,7 +167,6 @@ static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct qce_device *qce; - struct resource *res; int ret; qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL); @@ -177,8 +176,7 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->dev = dev; platform_set_drvdata(pdev, qce); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - qce->base = devm_ioremap_resource(&pdev->dev, res); + qce->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); -- GitLab From 2229c74079285c8f99754450e56d4d9814558e57 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:28:09 +0800 Subject: [PATCH 2365/7155] crypto: qcom-rng - use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Herbert Xu --- drivers/crypto/qcom-rng.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index e54249ccc009..4730f84b646d 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -153,7 +153,6 @@ static struct rng_alg qcom_rng_alg = { static int qcom_rng_probe(struct platform_device *pdev) { - struct resource *res; struct qcom_rng *rng; int ret; @@ -164,8 +163,7 @@ static int qcom_rng_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rng); mutex_init(&rng->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rng->base = devm_ioremap_resource(&pdev->dev, res); + rng->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rng->base)) return PTR_ERR(rng->base); -- GitLab From f6b0b78a5c6c198b31967bfc2c7d17150980a0f6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 2 Aug 2019 18:20:11 -0500 Subject: [PATCH 2366/7155] crypto: ccp - Include DMA declarations explicitly ccp-dev.h uses dma_direction, which is defined in linux/dma-direction.h. Include that explicitly instead of relying on it being included via linux/pci.h, since ccp-dev.h requires nothing else from linux/pci.h. Similarly, ccp-dmaengine.c uses dma_get_mask(), which is defined in linux/dma-mapping.h, so include that explicitly since it requires nothing else from linux/pci.h. A future patch will remove the includes of linux/pci.h where it is not needed. Signed-off-by: Bjorn Helgaas Acked-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.h | 1 + drivers/crypto/ccp/ccp-dmaengine.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index dd13468111cd..2fe5713fd40e 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c index 9d077c42bcbe..a54f9367a580 100644 --- a/drivers/crypto/ccp/ccp-dmaengine.c +++ b/drivers/crypto/ccp/ccp-dmaengine.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include -- GitLab From 3a646b6ed49cc64f0dc0a1bba24e62f7b557e7d7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 2 Aug 2019 18:20:12 -0500 Subject: [PATCH 2367/7155] crypto: ccp - Remove unnecessary linux/pci.h include Remove unused includes of linux/pci.h. Signed-off-by: Bjorn Helgaas Acked-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto.h | 1 - drivers/crypto/ccp/ccp-dev-v3.c | 1 - drivers/crypto/ccp/ccp-dev-v5.c | 1 - drivers/crypto/ccp/ccp-dev.h | 1 - drivers/crypto/ccp/ccp-ops.c | 1 - drivers/crypto/ccp/psp-dev.h | 1 - drivers/crypto/ccp/sp-dev.h | 1 - 7 files changed, 7 deletions(-) diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 599f7f2820a0..9015b5da6ba3 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 4005d438dff9..0186b3df4c87 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index 9ee72cf46a0f..57eb53b8ac21 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 2fe5713fd40e..3f68262d9ab4 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -12,7 +12,6 @@ #define __CCP_DEV_H__ #include -#include #include #include #include diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index 42d167574131..591584a95028 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h index c5e06c92d40e..82a084f02990 100644 --- a/drivers/crypto/ccp/psp-dev.h +++ b/drivers/crypto/ccp/psp-dev.h @@ -11,7 +11,6 @@ #define __PSP_DEV_H__ #include -#include #include #include #include diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h index 8abe9ea7e76f..53c12562d31e 100644 --- a/drivers/crypto/ccp/sp-dev.h +++ b/drivers/crypto/ccp/sp-dev.h @@ -13,7 +13,6 @@ #define __SP_DEV_H__ #include -#include #include #include #include -- GitLab From ec9c7d19336ee98ecba8de80128aa405c45feebb Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Thu, 8 Aug 2019 12:05:35 -0400 Subject: [PATCH 2368/7155] padata: initialize pd->cpu with effective cpumask Exercising CPU hotplug on a 5.2 kernel with recent padata fixes from cryptodev-2.6.git in an 8-CPU kvm guest... # modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3 # echo 0 > /sys/devices/system/cpu/cpu1/online # echo c > /sys/kernel/pcrypt/pencrypt/parallel_cpumask # modprobe tcrypt mode=215 ...caused the following crash: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI CPU: 2 PID: 134 Comm: kworker/2:2 Not tainted 5.2.0-padata-base+ #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0- Workqueue: pencrypt padata_parallel_worker RIP: 0010:padata_reorder+0xcb/0x180 ... Call Trace: padata_do_serial+0x57/0x60 pcrypt_aead_enc+0x3a/0x50 [pcrypt] padata_parallel_worker+0x9b/0xe0 process_one_work+0x1b5/0x3f0 worker_thread+0x4a/0x3c0 ... In padata_alloc_pd, pd->cpu is set using the user-supplied cpumask instead of the effective cpumask, and in this case cpumask_first picked an offline CPU. The offline CPU's reorder->list.next is NULL in padata_reorder because the list wasn't initialized in padata_init_pqueues, which only operates on CPUs in the effective mask. Fix by using the effective mask in padata_alloc_pd. Fixes: 6fc4dbcf0276 ("padata: Replace delayed timer with immediate workqueue in padata_reorder") Signed-off-by: Daniel Jordan Cc: Herbert Xu Cc: Steffen Klassert Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Herbert Xu --- kernel/padata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/padata.c b/kernel/padata.c index 7372fb45eeeb..b60cc3dcee58 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -426,7 +426,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, atomic_set(&pd->refcnt, 0); pd->pinst = pinst; spin_lock_init(&pd->lock); - pd->cpu = cpumask_first(pcpumask); + pd->cpu = cpumask_first(pd->cpumask.pcpu); INIT_WORK(&pd->reorder_work, invoke_padata_reorder); return pd; -- GitLab From b6cdf09f51c20a25b7952773b61116452de66189 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:09 +0200 Subject: [PATCH 2369/7155] net: stmmac: xgmac: Implement MMC counters Implement the MMC counters feature in XGMAC core. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 1 + .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 1 + drivers/net/ethernet/stmicro/stmmac/hwif.c | 4 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + drivers/net/ethernet/stmicro/stmmac/mmc.h | 9 + .../net/ethernet/stmicro/stmmac/mmc_core.c | 192 ++++++++++++++++++ .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 + 7 files changed, 212 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 3174b701aa90..86a42bc39d21 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -84,6 +84,7 @@ #define XGMAC_HWFEAT_AVSEL BIT(11) #define XGMAC_HWFEAT_RAVSEL BIT(10) #define XGMAC_HWFEAT_ARPOFFSEL BIT(9) +#define XGMAC_HWFEAT_MMCSEL BIT(8) #define XGMAC_HWFEAT_MGKSEL BIT(7) #define XGMAC_HWFEAT_RWKSEL BIT(6) #define XGMAC_HWFEAT_GMIISEL BIT(1) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index a4f236e3593e..0f1c772e892a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -356,6 +356,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12; dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11; dma_cap->av &= (hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10; + dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8; dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7; dma_cap->pmt_remote_wake_up = (hw_cap & XGMAC_HWFEAT_RWKSEL) >> 6; dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 6c61b753b55e..3af2e5015245 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -201,7 +201,7 @@ static const struct stmmac_hwif_entry { .min_id = DWXGMAC_CORE_2_10, .regs = { .ptp_off = PTP_XGMAC_OFFSET, - .mmc_off = 0, + .mmc_off = MMC_XGMAC_OFFSET, }, .desc = &dwxgmac210_desc_ops, .dma = &dwxgmac210_dma_ops, @@ -209,7 +209,7 @@ static const struct stmmac_hwif_entry { .hwtimestamp = &stmmac_ptp, .mode = NULL, .tc = &dwmac510_tc_ops, - .mmc = NULL, + .mmc = &dwxgmac_mmc_ops, .setup = dwxgmac2_setup, .quirks = NULL, }, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 278c0dbec9d9..00539a09d1db 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -503,6 +503,7 @@ extern const struct stmmac_ops dwxgmac210_ops; extern const struct stmmac_dma_ops dwxgmac210_dma_ops; extern const struct stmmac_desc_ops dwxgmac210_desc_ops; extern const struct stmmac_mmc_ops dwmac_mmc_ops; +extern const struct stmmac_mmc_ops dwxgmac_mmc_ops; #define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */ diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h index 3587ceb9faf5..a0c05925883e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -24,6 +24,7 @@ #define MMC_GMAC4_OFFSET 0x700 #define MMC_GMAC3_X_OFFSET 0x100 +#define MMC_XGMAC_OFFSET 0x800 struct stmmac_counters { unsigned int mmc_tx_octetcount_gb; @@ -116,6 +117,14 @@ struct stmmac_counters { unsigned int mmc_rx_tcp_err_octets; unsigned int mmc_rx_icmp_gd_octets; unsigned int mmc_rx_icmp_err_octets; + + /* FPE */ + unsigned int mmc_tx_fpe_fragment_cntr; + unsigned int mmc_tx_hold_req_cntr; + unsigned int mmc_rx_packet_assembly_err_cntr; + unsigned int mmc_rx_packet_smd_err_cntr; + unsigned int mmc_rx_packet_assembly_ok_cntr; + unsigned int mmc_rx_fpe_fragment_cntr; }; #endif /* __MMC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index a471db6d7b11..a223584f5f9a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -119,6 +119,64 @@ #define MMC_RX_ICMP_GD_OCTETS 0x180 #define MMC_RX_ICMP_ERR_OCTETS 0x184 +/* XGMAC MMC Registers */ +#define MMC_XGMAC_TX_OCTET_GB 0x14 +#define MMC_XGMAC_TX_PKT_GB 0x1c +#define MMC_XGMAC_TX_BROAD_PKT_G 0x24 +#define MMC_XGMAC_TX_MULTI_PKT_G 0x2c +#define MMC_XGMAC_TX_64OCT_GB 0x34 +#define MMC_XGMAC_TX_65OCT_GB 0x3c +#define MMC_XGMAC_TX_128OCT_GB 0x44 +#define MMC_XGMAC_TX_256OCT_GB 0x4c +#define MMC_XGMAC_TX_512OCT_GB 0x54 +#define MMC_XGMAC_TX_1024OCT_GB 0x5c +#define MMC_XGMAC_TX_UNI_PKT_GB 0x64 +#define MMC_XGMAC_TX_MULTI_PKT_GB 0x6c +#define MMC_XGMAC_TX_BROAD_PKT_GB 0x74 +#define MMC_XGMAC_TX_UNDER 0x7c +#define MMC_XGMAC_TX_OCTET_G 0x84 +#define MMC_XGMAC_TX_PKT_G 0x8c +#define MMC_XGMAC_TX_PAUSE 0x94 +#define MMC_XGMAC_TX_VLAN_PKT_G 0x9c +#define MMC_XGMAC_TX_LPI_USEC 0xa4 +#define MMC_XGMAC_TX_LPI_TRAN 0xa8 + +#define MMC_XGMAC_RX_PKT_GB 0x100 +#define MMC_XGMAC_RX_OCTET_GB 0x108 +#define MMC_XGMAC_RX_OCTET_G 0x110 +#define MMC_XGMAC_RX_BROAD_PKT_G 0x118 +#define MMC_XGMAC_RX_MULTI_PKT_G 0x120 +#define MMC_XGMAC_RX_CRC_ERR 0x128 +#define MMC_XGMAC_RX_RUNT_ERR 0x130 +#define MMC_XGMAC_RX_JABBER_ERR 0x134 +#define MMC_XGMAC_RX_UNDER 0x138 +#define MMC_XGMAC_RX_OVER 0x13c +#define MMC_XGMAC_RX_64OCT_GB 0x140 +#define MMC_XGMAC_RX_65OCT_GB 0x148 +#define MMC_XGMAC_RX_128OCT_GB 0x150 +#define MMC_XGMAC_RX_256OCT_GB 0x158 +#define MMC_XGMAC_RX_512OCT_GB 0x160 +#define MMC_XGMAC_RX_1024OCT_GB 0x168 +#define MMC_XGMAC_RX_UNI_PKT_G 0x170 +#define MMC_XGMAC_RX_LENGTH_ERR 0x178 +#define MMC_XGMAC_RX_RANGE 0x180 +#define MMC_XGMAC_RX_PAUSE 0x188 +#define MMC_XGMAC_RX_FIFOOVER_PKT 0x190 +#define MMC_XGMAC_RX_VLAN_PKT_GB 0x198 +#define MMC_XGMAC_RX_WATCHDOG_ERR 0x1a0 +#define MMC_XGMAC_RX_LPI_USEC 0x1a4 +#define MMC_XGMAC_RX_LPI_TRAN 0x1a8 +#define MMC_XGMAC_RX_DISCARD_PKT_GB 0x1ac +#define MMC_XGMAC_RX_DISCARD_OCT_GB 0x1b4 +#define MMC_XGMAC_RX_ALIGN_ERR_PKT 0x1bc + +#define MMC_XGMAC_TX_FPE_FRAG 0x208 +#define MMC_XGMAC_TX_HOLD_REQ 0x20c +#define MMC_XGMAC_RX_PKT_ASSEMBLY_ERR 0x228 +#define MMC_XGMAC_RX_PKT_SMD_ERR 0x22c +#define MMC_XGMAC_RX_PKT_ASSEMBLY_OK 0x230 +#define MMC_XGMAC_RX_FPE_FRAG 0x234 + static void dwmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode) { u32 value = readl(mmcaddr + MMC_CNTRL); @@ -263,3 +321,137 @@ const struct stmmac_mmc_ops dwmac_mmc_ops = { .intr_all_mask = dwmac_mmc_intr_all_mask, .read = dwmac_mmc_read, }; + +static void dwxgmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode) +{ + u32 value = readl(mmcaddr + MMC_CNTRL); + + value |= (mode & 0x3F); + + writel(value, mmcaddr + MMC_CNTRL); +} + +static void dwxgmac_mmc_intr_all_mask(void __iomem *mmcaddr) +{ + writel(MMC_DEFAULT_MASK, mmcaddr + MMC_RX_INTR_MASK); + writel(MMC_DEFAULT_MASK, mmcaddr + MMC_TX_INTR_MASK); +} + +static void dwxgmac_read_mmc_reg(void __iomem *addr, u32 reg, u32 *dest) +{ + u64 tmp = 0; + + tmp += readl(addr + reg); + tmp += ((u64 )readl(addr + reg + 0x4)) << 32; + if (tmp > GENMASK(31, 0)) + *dest = ~0x0; + else + *dest = *dest + tmp; +} + +/* This reads the MAC core counters (if actaully supported). + * by default the MMC core is programmed to reset each + * counter after a read. So all the field of the mmc struct + * have to be incremented. + */ +static void dwxgmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) +{ + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_OCTET_GB, + &mmc->mmc_tx_octetcount_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_PKT_GB, + &mmc->mmc_tx_framecount_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_BROAD_PKT_G, + &mmc->mmc_tx_broadcastframe_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_MULTI_PKT_G, + &mmc->mmc_tx_multicastframe_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_64OCT_GB, + &mmc->mmc_tx_64_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_65OCT_GB, + &mmc->mmc_tx_65_to_127_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_128OCT_GB, + &mmc->mmc_tx_128_to_255_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_256OCT_GB, + &mmc->mmc_tx_256_to_511_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_512OCT_GB, + &mmc->mmc_tx_512_to_1023_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_1024OCT_GB, + &mmc->mmc_tx_1024_to_max_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_UNI_PKT_GB, + &mmc->mmc_tx_unicast_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_MULTI_PKT_GB, + &mmc->mmc_tx_multicast_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_BROAD_PKT_GB, + &mmc->mmc_tx_broadcast_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_UNDER, + &mmc->mmc_tx_underflow_error); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_OCTET_G, + &mmc->mmc_tx_octetcount_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_PKT_G, + &mmc->mmc_tx_framecount_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_PAUSE, + &mmc->mmc_tx_pause_frame); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_TX_VLAN_PKT_G, + &mmc->mmc_tx_vlan_frame_g); + + /* MMC RX counter registers */ + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_PKT_GB, + &mmc->mmc_rx_framecount_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_OCTET_GB, + &mmc->mmc_rx_octetcount_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_OCTET_G, + &mmc->mmc_rx_octetcount_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_BROAD_PKT_G, + &mmc->mmc_rx_broadcastframe_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_MULTI_PKT_G, + &mmc->mmc_rx_multicastframe_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_CRC_ERR, + &mmc->mmc_rx_crc_error); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_CRC_ERR, + &mmc->mmc_rx_crc_error); + mmc->mmc_rx_run_error += readl(mmcaddr + MMC_XGMAC_RX_RUNT_ERR); + mmc->mmc_rx_jabber_error += readl(mmcaddr + MMC_XGMAC_RX_JABBER_ERR); + mmc->mmc_rx_undersize_g += readl(mmcaddr + MMC_XGMAC_RX_UNDER); + mmc->mmc_rx_oversize_g += readl(mmcaddr + MMC_XGMAC_RX_OVER); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_64OCT_GB, + &mmc->mmc_rx_64_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_65OCT_GB, + &mmc->mmc_rx_65_to_127_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_128OCT_GB, + &mmc->mmc_rx_128_to_255_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_256OCT_GB, + &mmc->mmc_rx_256_to_511_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_512OCT_GB, + &mmc->mmc_rx_512_to_1023_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_1024OCT_GB, + &mmc->mmc_rx_1024_to_max_octets_gb); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_UNI_PKT_G, + &mmc->mmc_rx_unicast_g); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_LENGTH_ERR, + &mmc->mmc_rx_length_error); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_RANGE, + &mmc->mmc_rx_autofrangetype); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_PAUSE, + &mmc->mmc_rx_pause_frames); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_FIFOOVER_PKT, + &mmc->mmc_rx_fifo_overflow); + dwxgmac_read_mmc_reg(mmcaddr, MMC_XGMAC_RX_VLAN_PKT_GB, + &mmc->mmc_rx_vlan_frames_gb); + mmc->mmc_rx_watchdog_error += readl(mmcaddr + MMC_XGMAC_RX_WATCHDOG_ERR); + + mmc->mmc_tx_fpe_fragment_cntr += readl(mmcaddr + MMC_XGMAC_TX_FPE_FRAG); + mmc->mmc_tx_hold_req_cntr += readl(mmcaddr + MMC_XGMAC_TX_HOLD_REQ); + mmc->mmc_rx_packet_assembly_err_cntr += + readl(mmcaddr + MMC_XGMAC_RX_PKT_ASSEMBLY_ERR); + mmc->mmc_rx_packet_smd_err_cntr += + readl(mmcaddr + MMC_XGMAC_RX_PKT_SMD_ERR); + mmc->mmc_rx_packet_assembly_ok_cntr += + readl(mmcaddr + MMC_XGMAC_RX_PKT_ASSEMBLY_OK); + mmc->mmc_rx_fpe_fragment_cntr += + readl(mmcaddr + MMC_XGMAC_RX_FPE_FRAG); +} + +const struct stmmac_mmc_ops dwxgmac_mmc_ops = { + .ctrl = dwxgmac_mmc_ctrl, + .intr_all_mask = dwxgmac_mmc_intr_all_mask, + .read = dwxgmac_mmc_read, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 6efb66820d4c..d294590cba27 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -243,6 +243,12 @@ static const struct stmmac_stats stmmac_mmc[] = { STMMAC_MMC_STAT(mmc_rx_tcp_err_octets), STMMAC_MMC_STAT(mmc_rx_icmp_gd_octets), STMMAC_MMC_STAT(mmc_rx_icmp_err_octets), + STMMAC_MMC_STAT(mmc_tx_fpe_fragment_cntr), + STMMAC_MMC_STAT(mmc_tx_hold_req_cntr), + STMMAC_MMC_STAT(mmc_rx_packet_assembly_err_cntr), + STMMAC_MMC_STAT(mmc_rx_packet_smd_err_cntr), + STMMAC_MMC_STAT(mmc_rx_packet_assembly_ok_cntr), + STMMAC_MMC_STAT(mmc_rx_fpe_fragment_cntr), }; #define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_mmc) -- GitLab From 5656ac5542df5842d9e581546aab19cd83222b32 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:10 +0200 Subject: [PATCH 2370/7155] net: stmmac: xgmac: Implement set_mtl_tx_queue_weight() Implement the TX Queue Weight callback. In order for this to be active we also need to set ETS algorithm when configuring Queue. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 85c68b7ee8c6..ce6503dfc86d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -144,7 +144,9 @@ static void dwxgmac2_prog_mtl_tx_algorithms(struct mac_device_info *hw, u32 tx_alg) { void __iomem *ioaddr = hw->pcsr; + bool ets = true; u32 value; + int i; value = readl(ioaddr + XGMAC_MTL_OPMODE); value &= ~XGMAC_ETSALG; @@ -160,10 +162,28 @@ static void dwxgmac2_prog_mtl_tx_algorithms(struct mac_device_info *hw, value |= XGMAC_DWRR; break; default: + ets = false; break; } writel(value, ioaddr + XGMAC_MTL_OPMODE); + + /* Set ETS if desired */ + for (i = 0; i < MTL_MAX_TX_QUEUES; i++) { + value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i)); + value &= ~XGMAC_TSA; + if (ets) + value |= XGMAC_ETS; + writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i)); + } +} + +static void dwxgmac2_set_mtl_tx_queue_weight(struct mac_device_info *hw, + u32 weight, u32 queue) +{ + void __iomem *ioaddr = hw->pcsr; + + writel(weight, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(queue)); } static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue, @@ -412,7 +432,7 @@ const struct stmmac_ops dwxgmac210_ops = { .rx_queue_routing = NULL, .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms, .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms, - .set_mtl_tx_queue_weight = NULL, + .set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight, .map_mtl_to_dma = dwxgmac2_map_mtl_to_dma, .config_cbs = dwxgmac2_config_cbs, .dump_regs = NULL, -- GitLab From 7035aad875ba83331ab243173d2775f59880164f Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:11 +0200 Subject: [PATCH 2371/7155] net: stmmac: xgmac: Implement tx_queue_prio() Implement the TX Queue Priority callback in XGMAC core. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 4 ++++ .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 86a42bc39d21..b77091161765 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -127,6 +127,10 @@ #define XGMAC_MTL_RXQ_DMA_MAP1 0x00001034 #define XGMAC_QxMDMACH(x) GENMASK((x) * 8 + 3, (x) * 8) #define XGMAC_QxMDMACH_SHIFT(x) ((x) * 8) +#define XGMAC_TC_PRTY_MAP0 0x00001040 +#define XGMAC_TC_PRTY_MAP1 0x00001044 +#define XGMAC_PSTC(x) GENMASK((x) * 8 + 7, (x) * 8) +#define XGMAC_PSTC_SHIFT(x) ((x) * 8) #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) #define XGMAC_TQS GENMASK(25, 16) #define XGMAC_TQS_SHIFT 16 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index ce6503dfc86d..bfbd5ae11540 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -118,6 +118,23 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio, writel(value, ioaddr + reg); } +static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio, + u32 queue) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value, reg; + + reg = (queue < 4) ? XGMAC_TC_PRTY_MAP0 : XGMAC_TC_PRTY_MAP1; + if (queue >= 4) + queue -= 4; + + value = readl(ioaddr + reg); + value &= ~XGMAC_PSTC(queue); + value |= (prio << XGMAC_PSTC_SHIFT(queue)) & XGMAC_PSTC(queue); + + writel(value, ioaddr + reg); +} + static void dwxgmac2_prog_mtl_rx_algorithms(struct mac_device_info *hw, u32 rx_alg) { @@ -428,7 +445,7 @@ const struct stmmac_ops dwxgmac210_ops = { .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxgmac2_rx_queue_enable, .rx_queue_prio = dwxgmac2_rx_queue_prio, - .tx_queue_prio = NULL, + .tx_queue_prio = dwxgmac2_tx_queue_prio, .rx_queue_routing = NULL, .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms, .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms, -- GitLab From 76067459c686c4fc6352613e5a6a54e4ffef2861 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:12 +0200 Subject: [PATCH 2372/7155] net: stmmac: Implement RSS and enable it in XGMAC core Implement the RSS functionality and add the corresponding callbacks in XGMAC core. Changes from v1: - Do not use magic constants (Jakub) - Use ethtool_rxfh_indir_default() (Jakub) Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 5 ++ .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 22 +++++- .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 52 +++++++++++++ .../ethernet/stmicro/stmmac/dwxgmac2_descs.c | 29 +++++++ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 1 + drivers/net/ethernet/stmicro/stmmac/hwif.h | 11 +++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 9 +++ .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 75 +++++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 41 +++++++++- include/linux/stmmac.h | 1 + 10 files changed, 242 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index ed872eed1cab..45a997fe571c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -354,6 +354,7 @@ struct dma_features { unsigned int frpbs; unsigned int frpes; unsigned int addr64; + unsigned int rssen; }; /* GMAC TX FIFO is 8K, Rx FIFO is 16K */ @@ -381,6 +382,10 @@ struct dma_features { #define JUMBO_LEN 9000 +/* Receive Side Scaling */ +#define STMMAC_RSS_HASH_KEY_SIZE 40 +#define STMMAC_RSS_MAX_TABLE_SIZE 256 + extern const struct stmmac_desc_ops enh_desc_ops; extern const struct stmmac_desc_ops ndesc_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index b77091161765..ed3a85f73a72 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -89,6 +89,7 @@ #define XGMAC_HWFEAT_RWKSEL BIT(6) #define XGMAC_HWFEAT_GMIISEL BIT(1) #define XGMAC_HW_FEATURE1 0x00000120 +#define XGMAC_HWFEAT_RSSEN BIT(20) #define XGMAC_HWFEAT_TSOEN BIT(18) #define XGMAC_HWFEAT_ADDR64 GENMASK(15, 14) #define XGMAC_HWFEAT_TXFIFOSIZE GENMASK(10, 6) @@ -109,6 +110,17 @@ #define XGMAC_DCS_SHIFT 16 #define XGMAC_ADDRx_LOW(x) (0x00000304 + (x) * 0x8) #define XGMAC_ARP_ADDR 0x00000c10 +#define XGMAC_RSS_CTRL 0x00000c80 +#define XGMAC_UDP4TE BIT(3) +#define XGMAC_TCP4TE BIT(2) +#define XGMAC_IP2TE BIT(1) +#define XGMAC_RSSE BIT(0) +#define XGMAC_RSS_ADDR 0x00000c88 +#define XGMAC_RSSIA_SHIFT 8 +#define XGMAC_ADDRT BIT(2) +#define XGMAC_CT BIT(1) +#define XGMAC_OB BIT(0) +#define XGMAC_RSS_DATA 0x00000c8c #define XGMAC_TIMESTAMP_STATUS 0x00000d20 #define XGMAC_TXTSC BIT(15) #define XGMAC_TXTIMESTAMP_NSEC 0x00000d30 @@ -125,8 +137,9 @@ #define XGMAC_MTL_INT_STATUS 0x00001020 #define XGMAC_MTL_RXQ_DMA_MAP0 0x00001030 #define XGMAC_MTL_RXQ_DMA_MAP1 0x00001034 -#define XGMAC_QxMDMACH(x) GENMASK((x) * 8 + 3, (x) * 8) +#define XGMAC_QxMDMACH(x) GENMASK((x) * 8 + 7, (x) * 8) #define XGMAC_QxMDMACH_SHIFT(x) ((x) * 8) +#define XGMAC_QDDMACH BIT(7) #define XGMAC_TC_PRTY_MAP0 0x00001040 #define XGMAC_TC_PRTY_MAP1 0x00001044 #define XGMAC_PSTC(x) GENMASK((x) * 8 + 7, (x) * 8) @@ -261,6 +274,13 @@ #define XGMAC_RDES3_IOC BIT(30) #define XGMAC_RDES3_LD BIT(28) #define XGMAC_RDES3_CDA BIT(27) +#define XGMAC_RDES3_RSV BIT(26) +#define XGMAC_RDES3_L34T GENMASK(23, 20) +#define XGMAC_RDES3_L34T_SHIFT 20 +#define XGMAC_L34T_IP4TCP 0x1 +#define XGMAC_L34T_IP4UDP 0x2 +#define XGMAC_L34T_IP6TCP 0x9 +#define XGMAC_L34T_IP6UDP 0xA #define XGMAC_RDES3_ES BIT(15) #define XGMAC_RDES3_PL GENMASK(13, 0) #define XGMAC_RDES3_TSD BIT(6) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index bfbd5ae11540..04eec85acc59 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -6,6 +6,7 @@ #include #include +#include #include "stmmac.h" #include "dwxgmac2.h" @@ -439,6 +440,56 @@ static void dwxgmac2_set_mac_loopback(void __iomem *ioaddr, bool enable) writel(value, ioaddr + XGMAC_RX_CONFIG); } +static int dwxgmac2_rss_write_reg(void __iomem *ioaddr, bool is_key, int idx, + u32 val) +{ + u32 ctrl = 0; + + writel(val, ioaddr + XGMAC_RSS_DATA); + ctrl |= idx << XGMAC_RSSIA_SHIFT; + ctrl |= is_key ? XGMAC_ADDRT : 0x0; + ctrl |= XGMAC_OB; + writel(ctrl, ioaddr + XGMAC_RSS_ADDR); + + return readl_poll_timeout(ioaddr + XGMAC_RSS_ADDR, ctrl, + !(ctrl & XGMAC_OB), 100, 10000); +} + +static int dwxgmac2_rss_configure(struct mac_device_info *hw, + struct stmmac_rss *cfg, u32 num_rxq) +{ + void __iomem *ioaddr = hw->pcsr; + u32 *key = (u32 *)cfg->key; + int i, ret; + u32 value; + + value = readl(ioaddr + XGMAC_RSS_CTRL); + if (!cfg->enable) { + value &= ~XGMAC_RSSE; + writel(value, ioaddr + XGMAC_RSS_CTRL); + return 0; + } + + for (i = 0; i < (sizeof(cfg->key) / sizeof(u32)); i++) { + ret = dwxgmac2_rss_write_reg(ioaddr, true, i, *key++); + if (ret) + return ret; + } + + for (i = 0; i < ARRAY_SIZE(cfg->table); i++) { + ret = dwxgmac2_rss_write_reg(ioaddr, false, i, cfg->table[i]); + if (ret) + return ret; + } + + for (i = 0; i < num_rxq; i++) + dwxgmac2_map_mtl_to_dma(hw, i, XGMAC_QDDMACH); + + value |= XGMAC_UDP4TE | XGMAC_TCP4TE | XGMAC_IP2TE | XGMAC_RSSE; + writel(value, ioaddr + XGMAC_RSS_CTRL); + return 0; +} + const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, .set_mac = dwxgmac2_set_mac, @@ -469,6 +520,7 @@ const struct stmmac_ops dwxgmac210_ops = { .debug = NULL, .set_filter = dwxgmac2_set_filter, .set_mac_loopback = dwxgmac2_set_mac_loopback, + .rss_configure = dwxgmac2_rss_configure, }; int dwxgmac2_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index c4c45402b8f8..8c5dd6a36157 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -254,6 +254,34 @@ static void dwxgmac2_clear(struct dma_desc *p) p->des3 = 0; } +static int dwxgmac2_get_rx_hash(struct dma_desc *p, u32 *hash, + enum pkt_hash_types *type) +{ + unsigned int rdes3 = le32_to_cpu(p->des3); + u32 ptype; + + if (rdes3 & XGMAC_RDES3_RSV) { + ptype = (rdes3 & XGMAC_RDES3_L34T) >> XGMAC_RDES3_L34T_SHIFT; + + switch (ptype) { + case XGMAC_L34T_IP4TCP: + case XGMAC_L34T_IP4UDP: + case XGMAC_L34T_IP6TCP: + case XGMAC_L34T_IP6UDP: + *type = PKT_HASH_TYPE_L4; + break; + default: + *type = PKT_HASH_TYPE_L3; + break; + } + + *hash = le32_to_cpu(p->des1); + return 0; + } + + return -EINVAL; +} + const struct stmmac_desc_ops dwxgmac210_desc_ops = { .tx_status = dwxgmac2_get_tx_status, .rx_status = dwxgmac2_get_rx_status, @@ -277,4 +305,5 @@ const struct stmmac_desc_ops dwxgmac210_desc_ops = { .get_addr = dwxgmac2_get_addr, .set_addr = dwxgmac2_set_addr, .clear = dwxgmac2_clear, + .get_rx_hash = dwxgmac2_get_rx_hash, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 0f1c772e892a..45a6634ee397 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -363,6 +363,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature 1 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); + dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20; dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18; dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 00539a09d1db..bfe7efee9481 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -86,6 +86,9 @@ struct stmmac_desc_ops { void (*set_addr)(struct dma_desc *p, dma_addr_t addr); /* clear descriptor */ void (*clear)(struct dma_desc *p); + /* RSS */ + int (*get_rx_hash)(struct dma_desc *p, u32 *hash, + enum pkt_hash_types *type); }; #define stmmac_init_rx_desc(__priv, __args...) \ @@ -136,6 +139,8 @@ struct stmmac_desc_ops { stmmac_do_void_callback(__priv, desc, set_addr, __args) #define stmmac_clear_desc(__priv, __args...) \ stmmac_do_void_callback(__priv, desc, clear, __args) +#define stmmac_get_rx_hash(__priv, __args...) \ + stmmac_do_callback(__priv, desc, get_rx_hash, __args) struct stmmac_dma_cfg; struct dma_features; @@ -249,6 +254,7 @@ struct rgmii_adv; struct stmmac_safety_stats; struct stmmac_tc_entry; struct stmmac_pps_cfg; +struct stmmac_rss; /* Helpers to program the MAC core */ struct stmmac_ops { @@ -327,6 +333,9 @@ struct stmmac_ops { u32 sub_second_inc, u32 systime_flags); /* Loopback for selftests */ void (*set_mac_loopback)(void __iomem *ioaddr, bool enable); + /* RSS */ + int (*rss_configure)(struct mac_device_info *hw, + struct stmmac_rss *cfg, u32 num_rxq); }; #define stmmac_core_init(__priv, __args...) \ @@ -397,6 +406,8 @@ struct stmmac_ops { stmmac_do_callback(__priv, mac, flex_pps_config, __args) #define stmmac_set_mac_loopback(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, set_mac_loopback, __args) +#define stmmac_rss_configure(__priv, __args...) \ + stmmac_do_callback(__priv, mac, rss_configure, __args) /* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 5cd966c154f3..d2f6f56ae29c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -113,6 +113,12 @@ struct stmmac_pps_cfg { struct timespec64 period; }; +struct stmmac_rss { + int enable; + u8 key[STMMAC_RSS_HASH_KEY_SIZE]; + u32 table[STMMAC_RSS_MAX_TABLE_SIZE]; +}; + struct stmmac_priv { /* Frequently used values are kept adjacent for cache effect */ u32 tx_coal_frames; @@ -203,6 +209,9 @@ struct stmmac_priv { /* Pulse Per Second output */ struct stmmac_pps_cfg pps[STMMAC_PPS_MAX]; + + /* Receive Side Scaling */ + struct stmmac_rss rss; }; enum stmmac_state { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index d294590cba27..2423160ab582 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -764,6 +764,76 @@ static int stmmac_set_coalesce(struct net_device *dev, return 0; } +static int stmmac_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *rxnfc, u32 *rule_locs) +{ + struct stmmac_priv *priv = netdev_priv(dev); + + switch (rxnfc->cmd) { + case ETHTOOL_GRXRINGS: + rxnfc->data = priv->plat->rx_queues_to_use; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 stmmac_get_rxfh_key_size(struct net_device *dev) +{ + struct stmmac_priv *priv = netdev_priv(dev); + + return sizeof(priv->rss.key); +} + +static u32 stmmac_get_rxfh_indir_size(struct net_device *dev) +{ + struct stmmac_priv *priv = netdev_priv(dev); + + return ARRAY_SIZE(priv->rss.table); +} + +static int stmmac_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct stmmac_priv *priv = netdev_priv(dev); + int i; + + if (indir) { + for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++) + indir[i] = priv->rss.table[i]; + } + + if (key) + memcpy(key, priv->rss.key, sizeof(priv->rss.key)); + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + return 0; +} + +static int stmmac_set_rxfh(struct net_device *dev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct stmmac_priv *priv = netdev_priv(dev); + int i; + + if ((hfunc != ETH_RSS_HASH_NO_CHANGE) && (hfunc != ETH_RSS_HASH_TOP)) + return -EOPNOTSUPP; + + if (indir) { + for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++) + priv->rss.table[i] = indir[i]; + } + + if (key) + memcpy(priv->rss.key, key, sizeof(priv->rss.key)); + + return stmmac_rss_configure(priv, priv->hw, &priv->rss, + priv->plat->rx_queues_to_use); +} + static int stmmac_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { @@ -855,6 +925,11 @@ static const struct ethtool_ops stmmac_ethtool_ops = { .get_eee = stmmac_ethtool_op_get_eee, .set_eee = stmmac_ethtool_op_set_eee, .get_sset_count = stmmac_get_sset_count, + .get_rxnfc = stmmac_get_rxnfc, + .get_rxfh_key_size = stmmac_get_rxfh_key_size, + .get_rxfh_indir_size = stmmac_get_rxfh_indir_size, + .get_rxfh = stmmac_get_rxfh, + .set_rxfh = stmmac_set_rxfh, .get_ts_info = stmmac_get_ts_info, .get_coalesce = stmmac_get_coalesce, .set_coalesce = stmmac_set_coalesce, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fd54c7c87485..404a0548f213 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2417,6 +2417,22 @@ static void stmmac_mac_config_rx_queues_routing(struct stmmac_priv *priv) } } +static void stmmac_mac_config_rss(struct stmmac_priv *priv) +{ + if (!priv->dma_cap.rssen || !priv->plat->rss_en) { + priv->rss.enable = false; + return; + } + + if (priv->dev->features & NETIF_F_RXHASH) + priv->rss.enable = true; + else + priv->rss.enable = false; + + stmmac_rss_configure(priv, priv->hw, &priv->rss, + priv->plat->rx_queues_to_use); +} + /** * stmmac_mtl_configuration - Configure MTL * @priv: driver private structure @@ -2461,6 +2477,10 @@ static void stmmac_mtl_configuration(struct stmmac_priv *priv) /* Set RX routing */ if (rx_queues_count > 1) stmmac_mac_config_rx_queues_routing(priv); + + /* Receive Side Scaling */ + if (rx_queues_count > 1) + stmmac_mac_config_rss(priv); } static void stmmac_safety_feat_configuration(struct stmmac_priv *priv) @@ -3385,9 +3405,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) priv->dev->stats.rx_errors++; buf->page = NULL; } else { + enum pkt_hash_types hash_type; struct sk_buff *skb; - int frame_len; unsigned int des; + int frame_len; + u32 hash; stmmac_get_desc_addr(priv, p, &des); frame_len = stmmac_get_rx_frame_len(priv, p, coe); @@ -3452,6 +3474,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) else skb->ip_summed = CHECKSUM_UNNECESSARY; + if (!stmmac_get_rx_hash(priv, p, &hash, &hash_type)) + skb_set_hash(skb, hash, hash_type); + + skb_record_rx_queue(skb, queue); napi_gro_receive(&ch->rx_napi, skb); /* Data payload copied into SKB, page ready for recycle */ @@ -4175,8 +4201,8 @@ int stmmac_dvr_probe(struct device *device, { struct net_device *ndev = NULL; struct stmmac_priv *priv; - u32 queue, maxq; - int ret = 0; + u32 queue, rxq, maxq; + int i, ret = 0; ndev = devm_alloc_etherdev_mqs(device, sizeof(struct stmmac_priv), MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES); @@ -4284,6 +4310,15 @@ int stmmac_dvr_probe(struct device *device, #endif priv->msg_enable = netif_msg_init(debug, default_msg_level); + /* Initialize RSS */ + rxq = priv->plat->rx_queues_to_use; + netdev_rss_key_fill(priv->rss.key, sizeof(priv->rss.key)); + for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++) + priv->rss.table[i] = ethtool_rxfh_indir_default(i, rxq); + + if (priv->dma_cap.rssen && priv->plat->rss_en) + ndev->features |= NETIF_F_RXHASH; + /* MTU range: 46 - hw-specific max */ ndev->min_mtu = ETH_ZLEN - ETH_HLEN; if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 7b3e354bcd3c..5cc6b6faf359 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -173,6 +173,7 @@ struct plat_stmmacenet_data { int has_gmac4; bool has_sun8i; bool tso_en; + int rss_en; int mac_port_sel_speed; bool en_tx_lpi_clockgating; int has_xgmac; -- GitLab From 1fbdad00055c59adb853935606468cf218c28dad Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:13 +0200 Subject: [PATCH 2373/7155] net: stmmac: selftests: Add RSS test Add a test for RSS in the stmmac selftests. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../stmicro/stmmac/stmmac_selftests.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index a97b1ea76438..83b775a8cedc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -700,6 +700,21 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv) return ret; } +static int stmmac_test_rss(struct stmmac_priv *priv) +{ + struct stmmac_packet_attrs attr = { }; + + if (!priv->dma_cap.rssen || !priv->rss.enable) + return -EOPNOTSUPP; + + attr.dst = priv->dev->dev_addr; + attr.exp_hash = true; + attr.sport = 0x321; + attr.dport = 0x123; + + return __stmmac_test_loopback(priv, &attr); +} + #define STMMAC_LOOPBACK_NONE 0 #define STMMAC_LOOPBACK_MAC 1 #define STMMAC_LOOPBACK_PHY 2 @@ -745,6 +760,10 @@ static const struct stmmac_test { .name = "Flow Control ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_flowctrl, + }, { + .name = "RSS ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_rss, }, }; -- GitLab From 3cd1cfcba26e2ebbadcd84ba118e785b8963e11b Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:14 +0200 Subject: [PATCH 2374/7155] net: stmmac: Implement VLAN Hash Filtering in XGMAC Implement the VLAN Hash Filtering feature in XGMAC core. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 10 +++ .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 41 ++++++++++ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 1 + drivers/net/ethernet/stmicro/stmmac/hwif.h | 5 ++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 79 +++++++++++++++++++ 7 files changed, 139 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 45a997fe571c..e1e6f67041ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -355,6 +355,7 @@ struct dma_features { unsigned int frpes; unsigned int addr64; unsigned int rssen; + unsigned int vlhash; }; /* GMAC TX FIFO is 8K, Rx FIFO is 16K */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index ed3a85f73a72..bae0b01000cc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -44,6 +44,7 @@ #define XGMAC_CORE_INIT_RX 0 #define XGMAC_PACKET_FILTER 0x00000008 #define XGMAC_FILTER_RA BIT(31) +#define XGMAC_FILTER_VTFE BIT(16) #define XGMAC_FILTER_HPF BIT(10) #define XGMAC_FILTER_PCF BIT(7) #define XGMAC_FILTER_PM BIT(4) @@ -51,6 +52,14 @@ #define XGMAC_FILTER_PR BIT(0) #define XGMAC_HASH_TABLE(x) (0x00000010 + (x) * 4) #define XGMAC_MAX_HASH_TABLE 8 +#define XGMAC_VLAN_TAG 0x00000050 +#define XGMAC_VLAN_EDVLP BIT(26) +#define XGMAC_VLAN_VTHM BIT(25) +#define XGMAC_VLAN_DOVLTC BIT(20) +#define XGMAC_VLAN_ESVL BIT(18) +#define XGMAC_VLAN_ETV BIT(16) +#define XGMAC_VLAN_VID GENMASK(15, 0) +#define XGMAC_VLAN_HASH_TABLE 0x00000058 #define XGMAC_RXQ_CTRL0 0x000000a0 #define XGMAC_RXQEN(x) GENMASK((x) * 2 + 1, (x) * 2) #define XGMAC_RXQEN_SHIFT(x) ((x) * 2) @@ -87,6 +96,7 @@ #define XGMAC_HWFEAT_MMCSEL BIT(8) #define XGMAC_HWFEAT_MGKSEL BIT(7) #define XGMAC_HWFEAT_RWKSEL BIT(6) +#define XGMAC_HWFEAT_VLHASH BIT(4) #define XGMAC_HWFEAT_GMIISEL BIT(1) #define XGMAC_HW_FEATURE1 0x00000120 #define XGMAC_HWFEAT_RSSEN BIT(20) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 04eec85acc59..e2dbebeb59e9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -490,6 +490,46 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw, return 0; } +static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, + bool is_double) +{ + void __iomem *ioaddr = hw->pcsr; + + writel(hash, ioaddr + XGMAC_VLAN_HASH_TABLE); + + if (hash) { + u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); + + value |= XGMAC_FILTER_VTFE; + + writel(value, ioaddr + XGMAC_PACKET_FILTER); + + value |= XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV; + if (is_double) { + value |= XGMAC_VLAN_EDVLP; + value |= XGMAC_VLAN_ESVL; + value |= XGMAC_VLAN_DOVLTC; + } + + writel(value, ioaddr + XGMAC_VLAN_TAG); + } else { + u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); + + value &= ~XGMAC_FILTER_VTFE; + + writel(value, ioaddr + XGMAC_PACKET_FILTER); + + value = readl(ioaddr + XGMAC_VLAN_TAG); + + value &= ~(XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV); + value &= ~(XGMAC_VLAN_EDVLP | XGMAC_VLAN_ESVL); + value &= ~XGMAC_VLAN_DOVLTC; + value &= ~XGMAC_VLAN_VID; + + writel(value, ioaddr + XGMAC_VLAN_TAG); + } +} + const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, .set_mac = dwxgmac2_set_mac, @@ -521,6 +561,7 @@ const struct stmmac_ops dwxgmac210_ops = { .set_filter = dwxgmac2_set_filter, .set_mac_loopback = dwxgmac2_set_mac_loopback, .rss_configure = dwxgmac2_rss_configure, + .update_vlan_hash = dwxgmac2_update_vlan_hash, }; int dwxgmac2_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 45a6634ee397..b50e275e76c2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -359,6 +359,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8; dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7; dma_cap->pmt_remote_wake_up = (hw_cap & XGMAC_HWFEAT_RWKSEL) >> 6; + dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; /* MAC HW feature 1 */ diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index bfe7efee9481..52fc2344b066 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -336,6 +336,9 @@ struct stmmac_ops { /* RSS */ int (*rss_configure)(struct mac_device_info *hw, struct stmmac_rss *cfg, u32 num_rxq); + /* VLAN */ + void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, + bool is_double); }; #define stmmac_core_init(__priv, __args...) \ @@ -408,6 +411,8 @@ struct stmmac_ops { stmmac_do_void_callback(__priv, mac, set_mac_loopback, __args) #define stmmac_rss_configure(__priv, __args...) \ stmmac_do_callback(__priv, mac, rss_configure, __args) +#define stmmac_update_vlan_hash(__priv, __args...) \ + stmmac_do_void_callback(__priv, mac, update_vlan_hash, __args) /* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index d2f6f56ae29c..4179559b11ad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -13,6 +13,7 @@ #define DRV_MODULE_VERSION "Jan_2016" #include +#include #include #include #include @@ -191,6 +192,7 @@ struct stmmac_priv { spinlock_t ptp_lock; void __iomem *mmcaddr; void __iomem *ptpaddr; + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 404a0548f213..2274bb58eefa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4037,6 +4037,79 @@ static void stmmac_exit_fs(struct net_device *dev) } #endif /* CONFIG_DEBUG_FS */ +static u32 stmmac_vid_crc32_le(__le16 vid_le) +{ + unsigned char *data = (unsigned char *)&vid_le; + unsigned char data_byte = 0; + u32 crc = ~0x0; + u32 temp = 0; + int i, bits; + + bits = get_bitmask_order(VLAN_VID_MASK); + for (i = 0; i < bits; i++) { + if ((i % 8) == 0) + data_byte = data[i / 8]; + + temp = ((crc & 1) ^ data_byte) & 1; + crc >>= 1; + data_byte >>= 1; + + if (temp) + crc ^= 0xedb88320; + } + + return crc; +} + +static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) +{ + u32 crc, hash = 0; + u16 vid; + + for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) { + __le16 vid_le = cpu_to_le16(vid); + crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28; + hash |= (1 << crc); + } + + return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double); +} + +static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid) +{ + struct stmmac_priv *priv = netdev_priv(ndev); + bool is_double = false; + int ret; + + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + if (be16_to_cpu(proto) == ETH_P_8021AD) + is_double = true; + + set_bit(vid, priv->active_vlans); + ret = stmmac_vlan_update(priv, is_double); + if (ret) { + clear_bit(vid, priv->active_vlans); + return ret; + } + + return ret; +} + +static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid) +{ + struct stmmac_priv *priv = netdev_priv(ndev); + bool is_double = false; + + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + if (be16_to_cpu(proto) == ETH_P_8021AD) + is_double = true; + + clear_bit(vid, priv->active_vlans); + return stmmac_vlan_update(priv, is_double); +} + static const struct net_device_ops stmmac_netdev_ops = { .ndo_open = stmmac_open, .ndo_start_xmit = stmmac_xmit, @@ -4053,6 +4126,8 @@ static const struct net_device_ops stmmac_netdev_ops = { .ndo_poll_controller = stmmac_poll_controller, #endif .ndo_set_mac_address = stmmac_set_mac_address, + .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, }; static void stmmac_reset_subtask(struct stmmac_priv *priv) @@ -4307,6 +4382,10 @@ int stmmac_dvr_probe(struct device *device, #ifdef STMMAC_VLAN_TAG_USED /* Both mac100 and gmac support receive VLAN tag detection */ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; + if (priv->dma_cap.vlhash) { + ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER; + } #endif priv->msg_enable = netif_msg_init(debug, default_msg_level); -- GitLab From 74043f6b22c3201c63ae6ef37c4d3a96b0850e91 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:15 +0200 Subject: [PATCH 2375/7155] net: stmmac: selftests: Add test for VLAN and Double VLAN Filtering Add a selftest for VLAN and Double VLAN Filtering in stmmac. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../stmicro/stmmac/stmmac_selftests.c | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 83b775a8cedc..6b08bb15af15 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -715,6 +715,203 @@ static int stmmac_test_rss(struct stmmac_priv *priv) return __stmmac_test_loopback(priv, &attr); } +static int stmmac_test_vlan_validate(struct sk_buff *skb, + struct net_device *ndev, + struct packet_type *pt, + struct net_device *orig_ndev) +{ + struct stmmac_test_priv *tpriv = pt->af_packet_priv; + struct stmmachdr *shdr; + struct ethhdr *ehdr; + struct udphdr *uhdr; + struct iphdr *ihdr; + + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + goto out; + + if (skb_linearize(skb)) + goto out; + if (skb_headlen(skb) < (STMMAC_TEST_PKT_SIZE - ETH_HLEN)) + goto out; + + ehdr = (struct ethhdr *)skb_mac_header(skb); + if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst)) + goto out; + + ihdr = ip_hdr(skb); + if (tpriv->double_vlan) + ihdr = (struct iphdr *)(skb_network_header(skb) + 4); + if (ihdr->protocol != IPPROTO_UDP) + goto out; + + uhdr = (struct udphdr *)((u8 *)ihdr + 4 * ihdr->ihl); + if (uhdr->dest != htons(tpriv->packet->dport)) + goto out; + + shdr = (struct stmmachdr *)((u8 *)uhdr + sizeof(*uhdr)); + if (shdr->magic != cpu_to_be64(STMMAC_TEST_PKT_MAGIC)) + goto out; + + tpriv->ok = true; + complete(&tpriv->comp); + +out: + kfree_skb(skb); + return 0; +} + +static int stmmac_test_vlanfilt(struct stmmac_priv *priv) +{ + struct stmmac_packet_attrs attr = { }; + struct stmmac_test_priv *tpriv; + struct sk_buff *skb = NULL; + int ret = 0, i; + + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + + tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); + if (!tpriv) + return -ENOMEM; + + tpriv->ok = false; + init_completion(&tpriv->comp); + + tpriv->pt.type = htons(ETH_P_IP); + tpriv->pt.func = stmmac_test_vlan_validate; + tpriv->pt.dev = priv->dev; + tpriv->pt.af_packet_priv = tpriv; + tpriv->packet = &attr; + + /* + * As we use HASH filtering, false positives may appear. This is a + * specially chosen ID so that adjacent IDs (+4) have different + * HASH values. + */ + tpriv->vlan_id = 0x123; + dev_add_pack(&tpriv->pt); + + ret = vlan_vid_add(priv->dev, htons(ETH_P_8021Q), tpriv->vlan_id); + if (ret) + goto cleanup; + + for (i = 0; i < 4; i++) { + attr.vlan = 1; + attr.vlan_id_out = tpriv->vlan_id + i; + attr.dst = priv->dev->dev_addr; + attr.sport = 9; + attr.dport = 9; + + skb = stmmac_test_get_udp_skb(priv, &attr); + if (!skb) { + ret = -ENOMEM; + goto vlan_del; + } + + skb_set_queue_mapping(skb, 0); + ret = dev_queue_xmit(skb); + if (ret) + goto vlan_del; + + wait_for_completion_timeout(&tpriv->comp, STMMAC_LB_TIMEOUT); + ret = !tpriv->ok; + if (ret && !i) { + goto vlan_del; + } else if (!ret && i) { + ret = -1; + goto vlan_del; + } else { + ret = 0; + } + + tpriv->ok = false; + } + +vlan_del: + vlan_vid_del(priv->dev, htons(ETH_P_8021Q), tpriv->vlan_id); +cleanup: + dev_remove_pack(&tpriv->pt); + kfree(tpriv); + return ret; +} + +static int stmmac_test_dvlanfilt(struct stmmac_priv *priv) +{ + struct stmmac_packet_attrs attr = { }; + struct stmmac_test_priv *tpriv; + struct sk_buff *skb = NULL; + int ret = 0, i; + + if (!priv->dma_cap.vlhash) + return -EOPNOTSUPP; + + tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); + if (!tpriv) + return -ENOMEM; + + tpriv->ok = false; + tpriv->double_vlan = true; + init_completion(&tpriv->comp); + + tpriv->pt.type = htons(ETH_P_8021Q); + tpriv->pt.func = stmmac_test_vlan_validate; + tpriv->pt.dev = priv->dev; + tpriv->pt.af_packet_priv = tpriv; + tpriv->packet = &attr; + + /* + * As we use HASH filtering, false positives may appear. This is a + * specially chosen ID so that adjacent IDs (+4) have different + * HASH values. + */ + tpriv->vlan_id = 0x123; + dev_add_pack(&tpriv->pt); + + ret = vlan_vid_add(priv->dev, htons(ETH_P_8021AD), tpriv->vlan_id); + if (ret) + goto cleanup; + + for (i = 0; i < 4; i++) { + attr.vlan = 2; + attr.vlan_id_out = tpriv->vlan_id + i; + attr.dst = priv->dev->dev_addr; + attr.sport = 9; + attr.dport = 9; + + skb = stmmac_test_get_udp_skb(priv, &attr); + if (!skb) { + ret = -ENOMEM; + goto vlan_del; + } + + skb_set_queue_mapping(skb, 0); + ret = dev_queue_xmit(skb); + if (ret) + goto vlan_del; + + wait_for_completion_timeout(&tpriv->comp, STMMAC_LB_TIMEOUT); + ret = !tpriv->ok; + if (ret && !i) { + goto vlan_del; + } else if (!ret && i) { + ret = -1; + goto vlan_del; + } else { + ret = 0; + } + + tpriv->ok = false; + } + +vlan_del: + vlan_vid_del(priv->dev, htons(ETH_P_8021AD), tpriv->vlan_id); +cleanup: + dev_remove_pack(&tpriv->pt); + kfree(tpriv); + return ret; +} + #define STMMAC_LOOPBACK_NONE 0 #define STMMAC_LOOPBACK_MAC 1 #define STMMAC_LOOPBACK_PHY 2 @@ -764,6 +961,14 @@ static const struct stmmac_test { .name = "RSS ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_rss, + }, { + .name = "VLAN Filtering ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_vlanfilt, + }, { + .name = "Double VLAN Filtering", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_dvlanfilt, }, }; -- GitLab From 56e58d6c8a5640eb708e85866e9d243d0357ee54 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:16 +0200 Subject: [PATCH 2376/7155] net: stmmac: Implement Safety Features in XGMAC core XGMAC also supports Safety Features. This patch implements the configuration and handling of this feature in XGMAC core. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 26 ++ .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 281 ++++++++++++++++++ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 4 + 3 files changed, 311 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index bae0b01000cc..34a53f2141dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -110,6 +110,12 @@ #define XGMAC_HWFEAT_RXCHCNT GENMASK(15, 12) #define XGMAC_HWFEAT_TXQCNT GENMASK(9, 6) #define XGMAC_HWFEAT_RXQCNT GENMASK(3, 0) +#define XGMAC_HW_FEATURE3 0x00000128 +#define XGMAC_HWFEAT_ASP GENMASK(15, 14) +#define XGMAC_MAC_DPP_FSM_INT_STATUS 0x00000150 +#define XGMAC_MAC_FSM_CONTROL 0x00000158 +#define XGMAC_PRTYEN BIT(1) +#define XGMAC_TMOUTEN BIT(0) #define XGMAC_MDIO_ADDR 0x00000200 #define XGMAC_MDIO_DATA 0x00000204 #define XGMAC_MDIO_C22P 0x00000220 @@ -154,6 +160,16 @@ #define XGMAC_TC_PRTY_MAP1 0x00001044 #define XGMAC_PSTC(x) GENMASK((x) * 8 + 7, (x) * 8) #define XGMAC_PSTC_SHIFT(x) ((x) * 8) +#define XGMAC_MTL_ECC_CONTROL 0x000010c0 +#define XGMAC_MTL_SAFETY_INT_STATUS 0x000010c4 +#define XGMAC_MEUIS BIT(1) +#define XGMAC_MECIS BIT(0) +#define XGMAC_MTL_ECC_INT_ENABLE 0x000010c8 +#define XGMAC_RPCEIE BIT(12) +#define XGMAC_ECEIE BIT(8) +#define XGMAC_RXCEIE BIT(4) +#define XGMAC_TXCEIE BIT(0) +#define XGMAC_MTL_ECC_INT_STATUS 0x000010cc #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) #define XGMAC_TQS GENMASK(25, 16) #define XGMAC_TQS_SHIFT 16 @@ -218,6 +234,16 @@ #define XGMAC_TDPS GENMASK(29, 0) #define XGMAC_RX_EDMA_CTRL 0x00003044 #define XGMAC_RDPS GENMASK(29, 0) +#define XGMAC_DMA_SAFETY_INT_STATUS 0x00003064 +#define XGMAC_MCSIS BIT(31) +#define XGMAC_MSUIS BIT(29) +#define XGMAC_MSCIS BIT(28) +#define XGMAC_DEUIS BIT(1) +#define XGMAC_DECIS BIT(0) +#define XGMAC_DMA_ECC_INT_ENABLE 0x00003068 +#define XGMAC_DCEIE BIT(1) +#define XGMAC_TCEIE BIT(0) +#define XGMAC_DMA_ECC_INT_STATUS 0x0000306c #define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x))) #define XGMAC_PBLx8 BIT(16) #define XGMAC_DMA_CH_TX_CONTROL(x) (0x00003104 + (0x80 * (x))) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index e2dbebeb59e9..19dfb72cab11 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -530,6 +530,284 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, } } +struct dwxgmac3_error_desc { + bool valid; + const char *desc; + const char *detailed_desc; +}; + +#define STAT_OFF(field) offsetof(struct stmmac_safety_stats, field) + +static void dwxgmac3_log_error(struct net_device *ndev, u32 value, bool corr, + const char *module_name, + const struct dwxgmac3_error_desc *desc, + unsigned long field_offset, + struct stmmac_safety_stats *stats) +{ + unsigned long loc, mask; + u8 *bptr = (u8 *)stats; + unsigned long *ptr; + + ptr = (unsigned long *)(bptr + field_offset); + + mask = value; + for_each_set_bit(loc, &mask, 32) { + netdev_err(ndev, "Found %s error in %s: '%s: %s'\n", corr ? + "correctable" : "uncorrectable", module_name, + desc[loc].desc, desc[loc].detailed_desc); + + /* Update counters */ + ptr[loc]++; + } +} + +static const struct dwxgmac3_error_desc dwxgmac3_mac_errors[32]= { + { true, "ATPES", "Application Transmit Interface Parity Check Error" }, + { true, "DPES", "Descriptor Cache Data Path Parity Check Error" }, + { true, "TPES", "TSO Data Path Parity Check Error" }, + { true, "TSOPES", "TSO Header Data Path Parity Check Error" }, + { true, "MTPES", "MTL Data Path Parity Check Error" }, + { true, "MTSPES", "MTL TX Status Data Path Parity Check Error" }, + { true, "MTBUPES", "MAC TBU Data Path Parity Check Error" }, + { true, "MTFCPES", "MAC TFC Data Path Parity Check Error" }, + { true, "ARPES", "Application Receive Interface Data Path Parity Check Error" }, + { true, "MRWCPES", "MTL RWC Data Path Parity Check Error" }, + { true, "MRRCPES", "MTL RCC Data Path Parity Check Error" }, + { true, "CWPES", "CSR Write Data Path Parity Check Error" }, + { true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" }, + { true, "TTES", "TX FSM Timeout Error" }, + { true, "RTES", "RX FSM Timeout Error" }, + { true, "CTES", "CSR FSM Timeout Error" }, + { true, "ATES", "APP FSM Timeout Error" }, + { true, "PTES", "PTP FSM Timeout Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 18 */ + { false, "UNKNOWN", "Unknown Error" }, /* 19 */ + { false, "UNKNOWN", "Unknown Error" }, /* 20 */ + { true, "MSTTES", "Master Read/Write Timeout Error" }, + { true, "SLVTES", "Slave Read/Write Timeout Error" }, + { true, "ATITES", "Application Timeout on ATI Interface Error" }, + { true, "ARITES", "Application Timeout on ARI Interface Error" }, + { true, "FSMPES", "FSM State Parity Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 26 */ + { false, "UNKNOWN", "Unknown Error" }, /* 27 */ + { false, "UNKNOWN", "Unknown Error" }, /* 28 */ + { false, "UNKNOWN", "Unknown Error" }, /* 29 */ + { false, "UNKNOWN", "Unknown Error" }, /* 30 */ + { true, "CPI", "Control Register Parity Check Error" }, +}; + +static void dwxgmac3_handle_mac_err(struct net_device *ndev, + void __iomem *ioaddr, bool correctable, + struct stmmac_safety_stats *stats) +{ + u32 value; + + value = readl(ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS); + writel(value, ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS); + + dwxgmac3_log_error(ndev, value, correctable, "MAC", + dwxgmac3_mac_errors, STAT_OFF(mac_errors), stats); +} + +static const struct dwxgmac3_error_desc dwxgmac3_mtl_errors[32]= { + { true, "TXCES", "MTL TX Memory Error" }, + { true, "TXAMS", "MTL TX Memory Address Mismatch Error" }, + { true, "TXUES", "MTL TX Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 3 */ + { true, "RXCES", "MTL RX Memory Error" }, + { true, "RXAMS", "MTL RX Memory Address Mismatch Error" }, + { true, "RXUES", "MTL RX Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 7 */ + { true, "ECES", "MTL EST Memory Error" }, + { true, "EAMS", "MTL EST Memory Address Mismatch Error" }, + { true, "EUES", "MTL EST Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 11 */ + { true, "RPCES", "MTL RX Parser Memory Error" }, + { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" }, + { true, "RPUES", "MTL RX Parser Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 15 */ + { false, "UNKNOWN", "Unknown Error" }, /* 16 */ + { false, "UNKNOWN", "Unknown Error" }, /* 17 */ + { false, "UNKNOWN", "Unknown Error" }, /* 18 */ + { false, "UNKNOWN", "Unknown Error" }, /* 19 */ + { false, "UNKNOWN", "Unknown Error" }, /* 20 */ + { false, "UNKNOWN", "Unknown Error" }, /* 21 */ + { false, "UNKNOWN", "Unknown Error" }, /* 22 */ + { false, "UNKNOWN", "Unknown Error" }, /* 23 */ + { false, "UNKNOWN", "Unknown Error" }, /* 24 */ + { false, "UNKNOWN", "Unknown Error" }, /* 25 */ + { false, "UNKNOWN", "Unknown Error" }, /* 26 */ + { false, "UNKNOWN", "Unknown Error" }, /* 27 */ + { false, "UNKNOWN", "Unknown Error" }, /* 28 */ + { false, "UNKNOWN", "Unknown Error" }, /* 29 */ + { false, "UNKNOWN", "Unknown Error" }, /* 30 */ + { false, "UNKNOWN", "Unknown Error" }, /* 31 */ +}; + +static void dwxgmac3_handle_mtl_err(struct net_device *ndev, + void __iomem *ioaddr, bool correctable, + struct stmmac_safety_stats *stats) +{ + u32 value; + + value = readl(ioaddr + XGMAC_MTL_ECC_INT_STATUS); + writel(value, ioaddr + XGMAC_MTL_ECC_INT_STATUS); + + dwxgmac3_log_error(ndev, value, correctable, "MTL", + dwxgmac3_mtl_errors, STAT_OFF(mtl_errors), stats); +} + +static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= { + { true, "TCES", "DMA TSO Memory Error" }, + { true, "TAMS", "DMA TSO Memory Address Mismatch Error" }, + { true, "TUES", "DMA TSO Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 3 */ + { true, "DCES", "DMA DCACHE Memory Error" }, + { true, "DAMS", "DMA DCACHE Address Mismatch Error" }, + { true, "DUES", "DMA DCACHE Memory Error" }, + { false, "UNKNOWN", "Unknown Error" }, /* 7 */ + { false, "UNKNOWN", "Unknown Error" }, /* 8 */ + { false, "UNKNOWN", "Unknown Error" }, /* 9 */ + { false, "UNKNOWN", "Unknown Error" }, /* 10 */ + { false, "UNKNOWN", "Unknown Error" }, /* 11 */ + { false, "UNKNOWN", "Unknown Error" }, /* 12 */ + { false, "UNKNOWN", "Unknown Error" }, /* 13 */ + { false, "UNKNOWN", "Unknown Error" }, /* 14 */ + { false, "UNKNOWN", "Unknown Error" }, /* 15 */ + { false, "UNKNOWN", "Unknown Error" }, /* 16 */ + { false, "UNKNOWN", "Unknown Error" }, /* 17 */ + { false, "UNKNOWN", "Unknown Error" }, /* 18 */ + { false, "UNKNOWN", "Unknown Error" }, /* 19 */ + { false, "UNKNOWN", "Unknown Error" }, /* 20 */ + { false, "UNKNOWN", "Unknown Error" }, /* 21 */ + { false, "UNKNOWN", "Unknown Error" }, /* 22 */ + { false, "UNKNOWN", "Unknown Error" }, /* 23 */ + { false, "UNKNOWN", "Unknown Error" }, /* 24 */ + { false, "UNKNOWN", "Unknown Error" }, /* 25 */ + { false, "UNKNOWN", "Unknown Error" }, /* 26 */ + { false, "UNKNOWN", "Unknown Error" }, /* 27 */ + { false, "UNKNOWN", "Unknown Error" }, /* 28 */ + { false, "UNKNOWN", "Unknown Error" }, /* 29 */ + { false, "UNKNOWN", "Unknown Error" }, /* 30 */ + { false, "UNKNOWN", "Unknown Error" }, /* 31 */ +}; + +static void dwxgmac3_handle_dma_err(struct net_device *ndev, + void __iomem *ioaddr, bool correctable, + struct stmmac_safety_stats *stats) +{ + u32 value; + + value = readl(ioaddr + XGMAC_DMA_ECC_INT_STATUS); + writel(value, ioaddr + XGMAC_DMA_ECC_INT_STATUS); + + dwxgmac3_log_error(ndev, value, correctable, "DMA", + dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats); +} + +static int dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp) +{ + u32 value; + + if (!asp) + return -EINVAL; + + /* 1. Enable Safety Features */ + writel(0x0, ioaddr + XGMAC_MTL_ECC_CONTROL); + + /* 2. Enable MTL Safety Interrupts */ + value = readl(ioaddr + XGMAC_MTL_ECC_INT_ENABLE); + value |= XGMAC_RPCEIE; /* RX Parser Memory Correctable Error */ + value |= XGMAC_ECEIE; /* EST Memory Correctable Error */ + value |= XGMAC_RXCEIE; /* RX Memory Correctable Error */ + value |= XGMAC_TXCEIE; /* TX Memory Correctable Error */ + writel(value, ioaddr + XGMAC_MTL_ECC_INT_ENABLE); + + /* 3. Enable DMA Safety Interrupts */ + value = readl(ioaddr + XGMAC_DMA_ECC_INT_ENABLE); + value |= XGMAC_DCEIE; /* Descriptor Cache Memory Correctable Error */ + value |= XGMAC_TCEIE; /* TSO Memory Correctable Error */ + writel(value, ioaddr + XGMAC_DMA_ECC_INT_ENABLE); + + /* Only ECC Protection for External Memory feature is selected */ + if (asp <= 0x1) + return 0; + + /* 4. Enable Parity and Timeout for FSM */ + value = readl(ioaddr + XGMAC_MAC_FSM_CONTROL); + value |= XGMAC_PRTYEN; /* FSM Parity Feature */ + value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */ + writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL); + + return 0; +} + +static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev, + void __iomem *ioaddr, + unsigned int asp, + struct stmmac_safety_stats *stats) +{ + bool err, corr; + u32 mtl, dma; + int ret = 0; + + if (!asp) + return -EINVAL; + + mtl = readl(ioaddr + XGMAC_MTL_SAFETY_INT_STATUS); + dma = readl(ioaddr + XGMAC_DMA_SAFETY_INT_STATUS); + + err = (mtl & XGMAC_MCSIS) || (dma & XGMAC_MCSIS); + corr = false; + if (err) { + dwxgmac3_handle_mac_err(ndev, ioaddr, corr, stats); + ret |= !corr; + } + + err = (mtl & (XGMAC_MEUIS | XGMAC_MECIS)) || + (dma & (XGMAC_MSUIS | XGMAC_MSCIS)); + corr = (mtl & XGMAC_MECIS) || (dma & XGMAC_MSCIS); + if (err) { + dwxgmac3_handle_mtl_err(ndev, ioaddr, corr, stats); + ret |= !corr; + } + + err = dma & (XGMAC_DEUIS | XGMAC_DECIS); + corr = dma & XGMAC_DECIS; + if (err) { + dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats); + ret |= !corr; + } + + return ret; +} + +static const struct dwxgmac3_error { + const struct dwxgmac3_error_desc *desc; +} dwxgmac3_all_errors[] = { + { dwxgmac3_mac_errors }, + { dwxgmac3_mtl_errors }, + { dwxgmac3_dma_errors }, +}; + +static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats, + int index, unsigned long *count, + const char **desc) +{ + int module = index / 32, offset = index % 32; + unsigned long *ptr = (unsigned long *)stats; + + if (module >= ARRAY_SIZE(dwxgmac3_all_errors)) + return -EINVAL; + if (!dwxgmac3_all_errors[module].desc[offset].valid) + return -EINVAL; + if (count) + *count = *(ptr + index); + if (desc) + *desc = dwxgmac3_all_errors[module].desc[offset].desc; + return 0; +} + const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, .set_mac = dwxgmac2_set_mac, @@ -559,6 +837,9 @@ const struct stmmac_ops dwxgmac210_ops = { .pcs_get_adv_lp = NULL, .debug = NULL, .set_filter = dwxgmac2_set_filter, + .safety_feat_config = dwxgmac3_safety_feat_config, + .safety_feat_irq_status = dwxgmac3_safety_feat_irq_status, + .safety_feat_dump = dwxgmac3_safety_feat_dump, .set_mac_loopback = dwxgmac2_set_mac_loopback, .rss_configure = dwxgmac2_rss_configure, .update_vlan_hash = dwxgmac2_update_vlan_hash, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index b50e275e76c2..e4a1c877f2e1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -399,6 +399,10 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, ((hw_cap & XGMAC_HWFEAT_TXQCNT) >> 6) + 1; dma_cap->number_rx_queues = ((hw_cap & XGMAC_HWFEAT_RXQCNT) >> 0) + 1; + + /* MAC HW feature 3 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3); + dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14; } static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan) -- GitLab From d6e1c12cf9bc18759b3f02b08286a6f53248cb55 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:17 +0200 Subject: [PATCH 2377/7155] net: stmmac: Add Flexible RX Parser support in XGMAC XGMAC cores also support the Flexible RX Parser feature. Add the support for it in the XGMAC core. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 13 ++ .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 190 ++++++++++++++++++ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 3 + 3 files changed, 206 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 34a53f2141dc..429c94e40c73 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -112,6 +112,9 @@ #define XGMAC_HWFEAT_RXQCNT GENMASK(3, 0) #define XGMAC_HW_FEATURE3 0x00000128 #define XGMAC_HWFEAT_ASP GENMASK(15, 14) +#define XGMAC_HWFEAT_FRPES GENMASK(12, 11) +#define XGMAC_HWFEAT_FRPPB GENMASK(10, 9) +#define XGMAC_HWFEAT_FRPSEL BIT(3) #define XGMAC_MAC_DPP_FSM_INT_STATUS 0x00000150 #define XGMAC_MAC_FSM_CONTROL 0x00000158 #define XGMAC_PRTYEN BIT(1) @@ -145,6 +148,7 @@ /* MTL Registers */ #define XGMAC_MTL_OPMODE 0x00001000 +#define XGMAC_FRPE BIT(15) #define XGMAC_ETSALG GENMASK(6, 5) #define XGMAC_WRR (0x0 << 5) #define XGMAC_WFQ (0x1 << 5) @@ -160,6 +164,15 @@ #define XGMAC_TC_PRTY_MAP1 0x00001044 #define XGMAC_PSTC(x) GENMASK((x) * 8 + 7, (x) * 8) #define XGMAC_PSTC_SHIFT(x) ((x) * 8) +#define XGMAC_MTL_RXP_CONTROL_STATUS 0x000010a0 +#define XGMAC_RXPI BIT(31) +#define XGMAC_NPE GENMASK(23, 16) +#define XGMAC_NVE GENMASK(7, 0) +#define XGMAC_MTL_RXP_IACC_CTRL_ST 0x000010b0 +#define XGMAC_STARTBUSY BIT(31) +#define XGMAC_WRRDN BIT(16) +#define XGMAC_ADDR GENMASK(9, 0) +#define XGMAC_MTL_RXP_IACC_DATA 0x000010b4 #define XGMAC_MTL_ECC_CONTROL 0x000010c0 #define XGMAC_MTL_SAFETY_INT_STATUS 0x000010c4 #define XGMAC_MEUIS BIT(1) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 19dfb72cab11..767f3fe5efaa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -808,6 +808,195 @@ static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats, return 0; } +static int dwxgmac3_rxp_disable(void __iomem *ioaddr) +{ + u32 val = readl(ioaddr + XGMAC_MTL_OPMODE); + + val &= ~XGMAC_FRPE; + writel(val, ioaddr + XGMAC_MTL_OPMODE); + + return 0; +} + +static void dwxgmac3_rxp_enable(void __iomem *ioaddr) +{ + u32 val; + + val = readl(ioaddr + XGMAC_MTL_OPMODE); + val |= XGMAC_FRPE; + writel(val, ioaddr + XGMAC_MTL_OPMODE); +} + +static int dwxgmac3_rxp_update_single_entry(void __iomem *ioaddr, + struct stmmac_tc_entry *entry, + int pos) +{ + int ret, i; + + for (i = 0; i < (sizeof(entry->val) / sizeof(u32)); i++) { + int real_pos = pos * (sizeof(entry->val) / sizeof(u32)) + i; + u32 val; + + /* Wait for ready */ + ret = readl_poll_timeout(ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST, + val, !(val & XGMAC_STARTBUSY), 1, 10000); + if (ret) + return ret; + + /* Write data */ + val = *((u32 *)&entry->val + i); + writel(val, ioaddr + XGMAC_MTL_RXP_IACC_DATA); + + /* Write pos */ + val = real_pos & XGMAC_ADDR; + writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST); + + /* Write OP */ + val |= XGMAC_WRRDN; + writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST); + + /* Start Write */ + val |= XGMAC_STARTBUSY; + writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST); + + /* Wait for done */ + ret = readl_poll_timeout(ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST, + val, !(val & XGMAC_STARTBUSY), 1, 10000); + if (ret) + return ret; + } + + return 0; +} + +static struct stmmac_tc_entry * +dwxgmac3_rxp_get_next_entry(struct stmmac_tc_entry *entries, + unsigned int count, u32 curr_prio) +{ + struct stmmac_tc_entry *entry; + u32 min_prio = ~0x0; + int i, min_prio_idx; + bool found = false; + + for (i = count - 1; i >= 0; i--) { + entry = &entries[i]; + + /* Do not update unused entries */ + if (!entry->in_use) + continue; + /* Do not update already updated entries (i.e. fragments) */ + if (entry->in_hw) + continue; + /* Let last entry be updated last */ + if (entry->is_last) + continue; + /* Do not return fragments */ + if (entry->is_frag) + continue; + /* Check if we already checked this prio */ + if (entry->prio < curr_prio) + continue; + /* Check if this is the minimum prio */ + if (entry->prio < min_prio) { + min_prio = entry->prio; + min_prio_idx = i; + found = true; + } + } + + if (found) + return &entries[min_prio_idx]; + return NULL; +} + +static int dwxgmac3_rxp_config(void __iomem *ioaddr, + struct stmmac_tc_entry *entries, + unsigned int count) +{ + struct stmmac_tc_entry *entry, *frag; + int i, ret, nve = 0; + u32 curr_prio = 0; + u32 old_val, val; + + /* Force disable RX */ + old_val = readl(ioaddr + XGMAC_RX_CONFIG); + val = old_val & ~XGMAC_CONFIG_RE; + writel(val, ioaddr + XGMAC_RX_CONFIG); + + /* Disable RX Parser */ + ret = dwxgmac3_rxp_disable(ioaddr); + if (ret) + goto re_enable; + + /* Set all entries as NOT in HW */ + for (i = 0; i < count; i++) { + entry = &entries[i]; + entry->in_hw = false; + } + + /* Update entries by reverse order */ + while (1) { + entry = dwxgmac3_rxp_get_next_entry(entries, count, curr_prio); + if (!entry) + break; + + curr_prio = entry->prio; + frag = entry->frag_ptr; + + /* Set special fragment requirements */ + if (frag) { + entry->val.af = 0; + entry->val.rf = 0; + entry->val.nc = 1; + entry->val.ok_index = nve + 2; + } + + ret = dwxgmac3_rxp_update_single_entry(ioaddr, entry, nve); + if (ret) + goto re_enable; + + entry->table_pos = nve++; + entry->in_hw = true; + + if (frag && !frag->in_hw) { + ret = dwxgmac3_rxp_update_single_entry(ioaddr, frag, nve); + if (ret) + goto re_enable; + frag->table_pos = nve++; + frag->in_hw = true; + } + } + + if (!nve) + goto re_enable; + + /* Update all pass entry */ + for (i = 0; i < count; i++) { + entry = &entries[i]; + if (!entry->is_last) + continue; + + ret = dwxgmac3_rxp_update_single_entry(ioaddr, entry, nve); + if (ret) + goto re_enable; + + entry->table_pos = nve++; + } + + /* Assume n. of parsable entries == n. of valid entries */ + val = (nve << 16) & XGMAC_NPE; + val |= nve & XGMAC_NVE; + writel(val, ioaddr + XGMAC_MTL_RXP_CONTROL_STATUS); + + /* Enable RX Parser */ + dwxgmac3_rxp_enable(ioaddr); + +re_enable: + /* Re-enable RX */ + writel(old_val, ioaddr + XGMAC_RX_CONFIG); + return ret; +} + const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, .set_mac = dwxgmac2_set_mac, @@ -843,6 +1032,7 @@ const struct stmmac_ops dwxgmac210_ops = { .set_mac_loopback = dwxgmac2_set_mac_loopback, .rss_configure = dwxgmac2_rss_configure, .update_vlan_hash = dwxgmac2_update_vlan_hash, + .rxp_config = dwxgmac3_rxp_config, }; int dwxgmac2_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index e4a1c877f2e1..18cbf4ab4ad2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -403,6 +403,9 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature 3 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3); dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14; + dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11; + dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9; + dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3; } static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan) -- GitLab From ccfc639a94f25eb8639e8ffbecad2f6b60d22eb1 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 7 Aug 2019 10:03:18 +0200 Subject: [PATCH 2378/7155] net: stmmac: selftests: Add a selftest for Flexible RX Parser Add a selftest for the Flexible RX Parser feature. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../stmicro/stmmac/stmmac_selftests.c | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 6b08bb15af15..abab84f2ef8b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "stmmac.h" struct stmmachdr { @@ -229,7 +231,7 @@ static int stmmac_test_loopback_validate(struct sk_buff *skb, goto out; } if (tpriv->packet->src) { - if (!ether_addr_equal(ehdr->h_source, orig_ndev->dev_addr)) + if (!ether_addr_equal(ehdr->h_source, tpriv->packet->src)) goto out; } @@ -912,6 +914,96 @@ static int stmmac_test_dvlanfilt(struct stmmac_priv *priv) return ret; } +#ifdef CONFIG_NET_CLS_ACT +static int stmmac_test_rxp(struct stmmac_priv *priv) +{ + unsigned char addr[ETH_ALEN] = {0xde, 0xad, 0xbe, 0xef, 0x00, 0x00}; + struct tc_cls_u32_offload cls_u32 = { }; + struct stmmac_packet_attrs attr = { }; + struct tc_action **actions, *act; + struct tc_u32_sel *sel; + struct tcf_exts *exts; + int ret, i, nk = 1; + + if (!tc_can_offload(priv->dev)) + return -EOPNOTSUPP; + if (!priv->dma_cap.frpsel) + return -EOPNOTSUPP; + + sel = kzalloc(sizeof(*sel) + nk * sizeof(struct tc_u32_key), GFP_KERNEL); + if (!sel) + return -ENOMEM; + + exts = kzalloc(sizeof(*exts), GFP_KERNEL); + if (!exts) { + ret = -ENOMEM; + goto cleanup_sel; + } + + actions = kzalloc(nk * sizeof(*actions), GFP_KERNEL); + if (!actions) { + ret = -ENOMEM; + goto cleanup_exts; + } + + act = kzalloc(nk * sizeof(*act), GFP_KERNEL); + if (!act) { + ret = -ENOMEM; + goto cleanup_actions; + } + + cls_u32.command = TC_CLSU32_NEW_KNODE; + cls_u32.common.chain_index = 0; + cls_u32.common.protocol = htons(ETH_P_ALL); + cls_u32.knode.exts = exts; + cls_u32.knode.sel = sel; + cls_u32.knode.handle = 0x123; + + exts->nr_actions = nk; + exts->actions = actions; + for (i = 0; i < nk; i++) { + struct tcf_gact *gact = to_gact(&act[i]); + + actions[i] = &act[i]; + gact->tcf_action = TC_ACT_SHOT; + } + + sel->nkeys = nk; + sel->offshift = 0; + sel->keys[0].off = 6; + sel->keys[0].val = htonl(0xdeadbeef); + sel->keys[0].mask = ~0x0; + + ret = stmmac_tc_setup_cls_u32(priv, priv, &cls_u32); + if (ret) + goto cleanup_act; + + attr.dst = priv->dev->dev_addr; + attr.src = addr; + + ret = __stmmac_test_loopback(priv, &attr); + ret = !ret; /* Shall NOT receive packet */ + + cls_u32.command = TC_CLSU32_DELETE_KNODE; + stmmac_tc_setup_cls_u32(priv, priv, &cls_u32); + +cleanup_act: + kfree(act); +cleanup_actions: + kfree(actions); +cleanup_exts: + kfree(exts); +cleanup_sel: + kfree(sel); + return ret; +} +#else +static int stmmac_test_rxp(struct stmmac_priv *priv) +{ + return -EOPNOTSUPP; +} +#endif + #define STMMAC_LOOPBACK_NONE 0 #define STMMAC_LOOPBACK_MAC 1 #define STMMAC_LOOPBACK_PHY 2 @@ -969,6 +1061,10 @@ static const struct stmmac_test { .name = "Double VLAN Filtering", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_dvlanfilt, + }, { + .name = "Flexible RX Parser ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_rxp, }, }; -- GitLab From da382875c616856b234790206fc80d51f66b3bc7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 7 Aug 2019 13:42:31 +0300 Subject: [PATCH 2379/7155] mlxsw: spectrum: Extend to support Spectrum-3 ASIC Extend existing driver for Spectrum and Spectrum-2 ASICs to support Spectrum-3 ASIC as well. Signed-off-by: Jiri Pirko Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 6 +- drivers/net/ethernet/mellanox/mlxsw/pci.h | 1 + .../net/ethernet/mellanox/mlxsw/spectrum.c | 55 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 06c80343d9ed..f458fd1ce9f8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -71,7 +71,7 @@ config MLXSW_SWITCHX2 module will be called mlxsw_switchx2. config MLXSW_SPECTRUM - tristate "Mellanox Technologies Spectrum support" + tristate "Mellanox Technologies Spectrum family support" depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q depends on PSAMPLE || PSAMPLE=n depends on BRIDGE || BRIDGE=n @@ -87,8 +87,8 @@ config MLXSW_SPECTRUM select NET_PTP_CLASSIFY if PTP_1588_CLOCK default m ---help--- - This driver supports Mellanox Technologies Spectrum Ethernet - Switch ASICs. + This driver supports Mellanox Technologies + Spectrum/Spectrum-2/Spectrum-3 Ethernet Switch ASICs. To compile this driver as a module, choose M here: the module will be called mlxsw_spectrum. diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index 946339e13eb9..5b1323645a5d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -9,6 +9,7 @@ #define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 #define PCI_DEVICE_ID_MELLANOX_SPECTRUM2 0xcf6c +#define PCI_DEVICE_ID_MELLANOX_SPECTRUM3 0xcf70 #define PCI_DEVICE_ID_MELLANOX_SWITCHIB 0xcb20 #define PCI_DEVICE_ID_MELLANOX_SWITCHIB2 0xcf08 diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5a8e94c0a95a..389861ece418 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -65,6 +65,7 @@ static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { static const char mlxsw_sp1_driver_name[] = "mlxsw_spectrum"; static const char mlxsw_sp2_driver_name[] = "mlxsw_spectrum2"; +static const char mlxsw_sp3_driver_name[] = "mlxsw_spectrum3"; static const char mlxsw_sp_driver_version[] = "1.0"; static const unsigned char mlxsw_sp1_mac_mask[ETH_ALEN] = { @@ -5290,6 +5291,35 @@ static struct mlxsw_driver mlxsw_sp2_driver = { .res_query_enabled = true, }; +static struct mlxsw_driver mlxsw_sp3_driver = { + .kind = mlxsw_sp3_driver_name, + .priv_size = sizeof(struct mlxsw_sp), + .init = mlxsw_sp2_init, + .fini = mlxsw_sp_fini, + .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, + .port_split = mlxsw_sp_port_split, + .port_unsplit = mlxsw_sp_port_unsplit, + .sb_pool_get = mlxsw_sp_sb_pool_get, + .sb_pool_set = mlxsw_sp_sb_pool_set, + .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, + .sb_port_pool_set = mlxsw_sp_sb_port_pool_set, + .sb_tc_pool_bind_get = mlxsw_sp_sb_tc_pool_bind_get, + .sb_tc_pool_bind_set = mlxsw_sp_sb_tc_pool_bind_set, + .sb_occ_snapshot = mlxsw_sp_sb_occ_snapshot, + .sb_occ_max_clear = mlxsw_sp_sb_occ_max_clear, + .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, + .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, + .flash_update = mlxsw_sp_flash_update, + .txhdr_construct = mlxsw_sp_txhdr_construct, + .resources_register = mlxsw_sp2_resources_register, + .params_register = mlxsw_sp2_params_register, + .params_unregister = mlxsw_sp2_params_unregister, + .ptp_transmitted = mlxsw_sp_ptp_transmitted, + .txhdr_len = MLXSW_TXHDR_LEN, + .profile = &mlxsw_sp2_config_profile, + .res_query_enabled = true, +}; + bool mlxsw_sp_port_dev_check(const struct net_device *dev) { return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; @@ -6324,6 +6354,16 @@ static struct pci_driver mlxsw_sp2_pci_driver = { .id_table = mlxsw_sp2_pci_id_table, }; +static const struct pci_device_id mlxsw_sp3_pci_id_table[] = { + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM3), 0}, + {0, }, +}; + +static struct pci_driver mlxsw_sp3_pci_driver = { + .name = mlxsw_sp3_driver_name, + .id_table = mlxsw_sp3_pci_id_table, +}; + static int __init mlxsw_sp_module_init(void) { int err; @@ -6339,6 +6379,10 @@ static int __init mlxsw_sp_module_init(void) if (err) goto err_sp2_core_driver_register; + err = mlxsw_core_driver_register(&mlxsw_sp3_driver); + if (err) + goto err_sp3_core_driver_register; + err = mlxsw_pci_driver_register(&mlxsw_sp1_pci_driver); if (err) goto err_sp1_pci_driver_register; @@ -6347,11 +6391,19 @@ static int __init mlxsw_sp_module_init(void) if (err) goto err_sp2_pci_driver_register; + err = mlxsw_pci_driver_register(&mlxsw_sp3_pci_driver); + if (err) + goto err_sp3_pci_driver_register; + return 0; +err_sp3_pci_driver_register: + mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver); err_sp2_pci_driver_register: mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver); err_sp1_pci_driver_register: + mlxsw_core_driver_unregister(&mlxsw_sp3_driver); +err_sp3_core_driver_register: mlxsw_core_driver_unregister(&mlxsw_sp2_driver); err_sp2_core_driver_register: mlxsw_core_driver_unregister(&mlxsw_sp1_driver); @@ -6363,8 +6415,10 @@ static int __init mlxsw_sp_module_init(void) static void __exit mlxsw_sp_module_exit(void) { + mlxsw_pci_driver_unregister(&mlxsw_sp3_pci_driver); mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver); mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver); + mlxsw_core_driver_unregister(&mlxsw_sp3_driver); mlxsw_core_driver_unregister(&mlxsw_sp2_driver); mlxsw_core_driver_unregister(&mlxsw_sp1_driver); unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); @@ -6379,4 +6433,5 @@ MODULE_AUTHOR("Jiri Pirko "); MODULE_DESCRIPTION("Mellanox Spectrum driver"); MODULE_DEVICE_TABLE(pci, mlxsw_sp1_pci_id_table); MODULE_DEVICE_TABLE(pci, mlxsw_sp2_pci_id_table); +MODULE_DEVICE_TABLE(pci, mlxsw_sp3_pci_id_table); MODULE_FIRMWARE(MLXSW_SP1_FW_FILENAME); -- GitLab From dccce749ac66aa01593273d86cf3c55542ce6fc0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 5 Aug 2019 14:14:26 -0500 Subject: [PATCH 2380/7155] USB: gadget: udc: s3c2410_udc: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: tct_hammer_defconfig arm): drivers/usb/gadget/udc/s3c2410_udc.c:314:7: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/usb/gadget/udc/s3c2410_udc.c:418:7: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Gustavo A. R. Silva Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/s3c2410_udc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index af3e63316ace..f82208fbc249 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -312,6 +312,7 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, switch (idx) { default: idx = 0; + /* fall through */ case 0: fifo_reg = S3C2410_UDC_EP0_FIFO_REG; break; @@ -416,6 +417,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, switch (idx) { default: idx = 0; + /* fall through */ case 0: fifo_reg = S3C2410_UDC_EP0_FIFO_REG; break; -- GitLab From 27125cf8b5aee9f62dd108051203ccbd2e426b51 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 5 Aug 2019 13:48:42 -0500 Subject: [PATCH 2381/7155] usb: gadget: atmel_usba_udc: Mark expected switch fall-through Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: at91_dt_defconfig arm): drivers/usb/gadget/udc/atmel_usba_udc.c:329:13: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Gustavo A. R. Silva Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 503d275bc4c4..86ffc8307864 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -327,6 +327,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) switch (fifo_mode) { default: fifo_mode = 0; + /* fall through */ case 0: udc->fifo_cfg = NULL; n = 0; -- GitLab From 37bea42fec575203c1b49d64322f717c29e82b90 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 5 Aug 2019 17:01:21 +0100 Subject: [PATCH 2382/7155] usb: dwc2: gadget: Fix kill_all_requests race When a gadget is disabled, kill_all_requests() can be called simultaneously from both a user process via dwc2_hsotg_pullup() and from the interrupt handler if the hardware detects disconnection. Since we drop the lock in dwc2_hsotg_complete_request() in order to call the completion handler, this means that the list is modified concurrently and leads to an infinite loop in kill_all_requests(). Replace the foreach loop with a while-not-empty loop in order to remove the danger of this concurrent modification. Note: I observed this with threadirqs, I'm not sure if it can be triggered without threaded interrupts. Signed-off-by: John Keeping Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index bff48a8a1984..6be10e496e10 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3224,14 +3224,15 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, struct dwc2_hsotg_ep *ep, int result) { - struct dwc2_hsotg_req *req, *treq; unsigned int size; ep->req = NULL; - list_for_each_entry_safe(req, treq, &ep->queue, queue) - dwc2_hsotg_complete_request(hsotg, ep, req, - result); + while (!list_empty(&ep->queue)) { + struct dwc2_hsotg_req *req = get_ep_head(ep); + + dwc2_hsotg_complete_request(hsotg, ep, req, result); + } if (!hsotg->dedicated_fifos) return; -- GitLab From c6e4999cd930b8bd11dd8d4767e871b47f502845 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:04:08 +0800 Subject: [PATCH 2383/7155] usb: dwc3: meson-g12a: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Acked-by: Neil Armstrong Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-meson-g12a.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index bca7e92a10e9..d73ccd9e1366 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -386,7 +386,6 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; void __iomem *base; - struct resource *res; enum phy_mode otg_id; int ret, i, irq; @@ -394,8 +393,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 58dd0bad25543f95ffb5627d183eb4d01f38e633 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:06:16 +0800 Subject: [PATCH 2384/7155] usb: dwc3: omap: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ed8b86517675..84c459c15222 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -446,7 +446,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct dwc3_omap *omap; - struct resource *res; struct device *dev = &pdev->dev; struct regulator *vbus_reg = NULL; @@ -474,8 +473,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) return irq; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 5b76f6a0b0f868d8f4fae4e79a92e433a250a2eb Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 2 Aug 2019 21:01:04 +0800 Subject: [PATCH 2385/7155] usb: dwc3: keystone: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-keystone.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index cbee5fb9b9fb..d3c0233fed2f 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -81,7 +81,6 @@ static int kdwc3_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *node = pdev->dev.of_node; struct dwc3_keystone *kdwc; - struct resource *res; int error, irq; kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL); @@ -92,8 +91,7 @@ static int kdwc3_probe(struct platform_device *pdev) kdwc->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - kdwc->usbss = devm_ioremap_resource(dev, res); + kdwc->usbss = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kdwc->usbss)) return PTR_ERR(kdwc->usbss); -- GitLab From 18425e5eb029eadbf82407d4fc224ced52fde986 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:16:39 +0300 Subject: [PATCH 2386/7155] usb: dwc2: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Acked-by: Minas Harutyunyan Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/params.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 55f841a54015..31e090ac9f1e 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -404,10 +404,7 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) device_property_read_u32(hsotg->dev, "g-np-tx-fifo-size", &p->g_np_tx_fifo_size); - num = device_property_read_u32_array(hsotg->dev, - "g-tx-fifo-size", - NULL, 0); - + num = device_property_count_u32(hsotg->dev, "g-tx-fifo-size"); if (num > 0) { num = min(num, 15); memset(p->g_tx_fifo_size, 0, -- GitLab From 8484aa0cb36d8fd751db77e46763719c78a03b22 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 24 Jul 2019 21:18:49 +0800 Subject: [PATCH 2387/7155] usb: gadget: pch_udc: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index cded51f36fc1..265dab2bbfac 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -3046,8 +3046,7 @@ static void pch_udc_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int pch_udc_suspend(struct device *d) { - struct pci_dev *pdev = to_pci_dev(d); - struct pch_udc_dev *dev = pci_get_drvdata(pdev); + struct pch_udc_dev *dev = dev_get_drvdata(d); pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL); -- GitLab From a6e5e6794a538534e797f422e6f31888ff5b6b64 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 23 Jul 2019 22:17:04 +0300 Subject: [PATCH 2388/7155] usb: dwc3: Switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c9bb93a2c81e..98bce85c29d0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -813,8 +813,7 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) * result = 1, means INCRx burst mode supported. * result > 1, means undefined length burst mode supported. */ - ntype = device_property_read_u32_array(dev, - "snps,incr-burst-type-adjustment", NULL, 0); + ntype = device_property_count_u32(dev, "snps,incr-burst-type-adjustment"); if (ntype <= 0) return; -- GitLab From b2a3974253d32374af556541141d7fdad8fe2ce0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 21 Jul 2019 16:36:49 +0900 Subject: [PATCH 2389/7155] usb: dwc3: omap: squash include/linux/platform_data/dwc3-omap.h This enum is only used in drivers/usb/dwc3/dwc3-omap3.c Signed-off-by: Masahiro Yamada Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 7 +++- include/linux/platform_data/dwc3-omap.h | 43 ------------------------- 2 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 include/linux/platform_data/dwc3-omap.h diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 84c459c15222..c2940dbfb683 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -106,6 +105,12 @@ #define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) #define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) +enum dwc3_omap_utmi_mode { + DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, + DWC3_OMAP_UTMI_MODE_HW, + DWC3_OMAP_UTMI_MODE_SW, +}; + struct dwc3_omap { struct device *dev; diff --git a/include/linux/platform_data/dwc3-omap.h b/include/linux/platform_data/dwc3-omap.h deleted file mode 100644 index 1d36ca874cc8..000000000000 --- a/include/linux/platform_data/dwc3-omap.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * dwc3-omap.h - OMAP Specific Glue layer, header. - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * All rights reserved. - * - * Author: Felipe Balbi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -enum dwc3_omap_utmi_mode { - DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, - DWC3_OMAP_UTMI_MODE_HW, - DWC3_OMAP_UTMI_MODE_SW, -}; -- GitLab From 4749e0e61241cc121de572520a39dab365b9ea1d Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Thu, 8 Aug 2019 16:39:42 -0700 Subject: [PATCH 2390/7155] usb: dwc3: Update soft-reset wait polling rate Starting from DWC_usb31 version 1.90a and later, the DCTL.CSFRST bit will not be cleared until after all the internal clocks are synchronized during soft-reset. This may take a little more than 50ms. Set the polling rate at 20ms instead. Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 23 ++++++++++++++++++----- drivers/usb/dwc3/core.h | 2 ++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 98bce85c29d0..252c397860ef 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -252,12 +252,25 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) reg |= DWC3_DCTL_CSFTRST; dwc3_writel(dwc->regs, DWC3_DCTL, reg); + /* + * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit + * is cleared only after all the clocks are synchronized. This can + * take a little more than 50ms. Set the polling rate at 20ms + * for 10 times instead. + */ + if (dwc3_is_usb31(dwc) && dwc->revision >= DWC3_USB31_REVISION_190A) + retries = 10; + do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) goto done; - udelay(1); + if (dwc3_is_usb31(dwc) && + dwc->revision >= DWC3_USB31_REVISION_190A) + msleep(20); + else + udelay(1); } while (--retries); phy_exit(dwc->usb3_generic_phy); @@ -267,11 +280,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) done: /* - * For DWC_usb31 controller, once DWC3_DCTL_CSFTRST bit is cleared, - * we must wait at least 50ms before accessing the PHY domain - * (synchronization delay). DWC_usb31 programming guide section 1.3.2. + * For DWC_usb31 controller 1.80a and prior, once DCTL.CSFRST bit + * is cleared, we must wait at least 50ms before accessing the PHY + * domain (synchronization delay). */ - if (dwc3_is_usb31(dwc)) + if (dwc3_is_usb31(dwc) && dwc->revision <= DWC3_USB31_REVISION_180A) msleep(50); return 0; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 3dd783b889cb..1c8b349379af 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1137,6 +1137,8 @@ struct dwc3 { #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_160A (0x3136302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) +#define DWC3_USB31_REVISION_180A (0x3138302a | DWC3_REVISION_IS_DWC31) +#define DWC3_USB31_REVISION_190A (0x3139302a | DWC3_REVISION_IS_DWC31) u32 version_type; -- GitLab From 018e5b458723d04cbeadbc3f0e06eba85798f427 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 7 Aug 2019 21:10:55 +0800 Subject: [PATCH 2391/7155] fq_codel: remove set but not used variables 'prev_ecn_mark' and 'prev_drop_count' Fixes gcc '-Wunused-but-set-variable' warning: net/sched/sch_fq_codel.c: In function fq_codel_dequeue: net/sched/sch_fq_codel.c:288:23: warning: variable prev_ecn_mark set but not used [-Wunused-but-set-variable] net/sched/sch_fq_codel.c:288:6: warning: variable prev_drop_count set but not used [-Wunused-but-set-variable] They are not used since commit 77ddaff218fc ("fq_codel: Kill useless per-flow dropped statistic") Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 9edd0f495001..c261c0a18868 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -285,7 +285,6 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) struct sk_buff *skb; struct fq_codel_flow *flow; struct list_head *head; - u32 prev_drop_count, prev_ecn_mark; begin: head = &q->new_flows; @@ -302,9 +301,6 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) goto begin; } - prev_drop_count = q->cstats.drop_count; - prev_ecn_mark = q->cstats.ecn_mark; - skb = codel_dequeue(sch, &sch->qstats.backlog, &q->cparams, &flow->cvars, &q->cstats, qdisc_pkt_len, codel_get_enqueue_time, drop_func, dequeue_func); -- GitLab From 32879f000120fead7cbd4a9aacbda95c84c6b287 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 7 Aug 2019 21:38:22 +0200 Subject: [PATCH 2392/7155] r8169: allocate rx buffers using alloc_pages_node We allocate 16kb per rx buffer, so we can avoid some overhead by using alloc_pages_node directly instead of bothering kmalloc_node. Due to this change buffers are page-aligned now, therefore the alignment check can be removed. Signed-off-by: Heiner Kallweit Acked-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 45 ++++++++++------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index fa6eae2e7ed8..b2a275d8504c 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -642,7 +642,7 @@ struct rtl8169_private { struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ + struct page *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ u16 cp_cmd; u16 irq_mask; @@ -5261,12 +5261,13 @@ static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) } static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) + struct page **data_buff, + struct RxDesc *desc) { - dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), - R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); + dma_unmap_page(tp_to_dev(tp), le64_to_cpu(desc->addr), + R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); - kfree(*data_buff); + __free_pages(*data_buff, get_order(R8169_RX_BUF_SIZE)); *data_buff = NULL; rtl8169_make_unusable_by_asic(desc); } @@ -5281,38 +5282,30 @@ static inline void rtl8169_mark_to_asic(struct RxDesc *desc) desc->opts1 = cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE); } -static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) +static struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp, + struct RxDesc *desc) { - void *data; - dma_addr_t mapping; struct device *d = tp_to_dev(tp); int node = dev_to_node(d); + dma_addr_t mapping; + struct page *data; - data = kmalloc_node(R8169_RX_BUF_SIZE, GFP_KERNEL, node); + data = alloc_pages_node(node, GFP_KERNEL, get_order(R8169_RX_BUF_SIZE)); if (!data) return NULL; - /* Memory should be properly aligned, but better check. */ - if (!IS_ALIGNED((unsigned long)data, 8)) { - netdev_err_once(tp->dev, "RX buffer not 8-byte-aligned\n"); - goto err_out; - } - - mapping = dma_map_single(d, data, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); + mapping = dma_map_page(d, data, 0, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(d, mapping))) { if (net_ratelimit()) netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; + __free_pages(data, get_order(R8169_RX_BUF_SIZE)); + return NULL; } desc->addr = cpu_to_le64(mapping); rtl8169_mark_to_asic(desc); - return data; -err_out: - kfree(data); - return NULL; + return data; } static void rtl8169_rx_clear(struct rtl8169_private *tp) @@ -5337,7 +5330,7 @@ static int rtl8169_rx_fill(struct rtl8169_private *tp) unsigned int i; for (i = 0; i < NUM_RX_DESC; i++) { - void *data; + struct page *data; data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); if (!data) { @@ -5892,6 +5885,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) { unsigned int entry = cur_rx % NUM_RX_DESC; + const void *rx_buf = page_address(tp->Rx_databuff[entry]); struct RxDesc *desc = tp->RxDescArray + entry; u32 status; @@ -5946,9 +5940,8 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget goto release_descriptor; } - prefetch(tp->Rx_databuff[entry]); - skb_copy_to_linear_data(skb, tp->Rx_databuff[entry], - pkt_size); + prefetch(rx_buf); + skb_copy_to_linear_data(skb, rx_buf, pkt_size); skb->tail += pkt_size; skb->len = pkt_size; -- GitLab From fcc32a21655e26d30c746b4828b33a5fd4ccfb11 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Thu, 8 Aug 2019 07:57:53 +0300 Subject: [PATCH 2393/7155] liquidio: Use pcie_flr() instead of reimplementing it octeon_mbox_process_cmd() directly writes the PCI_EXP_DEVCTL_BCR_FLR bit, which bypasses timing requirements imposed by the PCIe spec. This patch fixes the function to use the pcie_flr() interface instead. Signed-off-by: Denis Efremov Reviewed-by: Andrew Murray Reviewed-by: Bjorn Helgaas Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c index 021d99cd1665..614d07be7181 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c @@ -260,9 +260,7 @@ static int octeon_mbox_process_cmd(struct octeon_mbox *mbox, dev_info(&oct->pci_dev->dev, "got a request for FLR from VF that owns DPI ring %u\n", mbox->q_no); - pcie_capability_set_word( - oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no], - PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); + pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]); break; case OCTEON_PF_CHANGED_VF_MACADDR: -- GitLab From fe4010667741df8c8d6bef1780ec34ebf43cf007 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 9 Aug 2019 12:54:58 +1000 Subject: [PATCH 2394/7155] ALSA: hda: readl/writel need linux/io.h Fixes: 19abfefd4c76 ("ALSA: hda: Direct MMIO accesses") Signed-off-by: Stephen Rothwell Signed-off-by: Takashi Iwai --- sound/hda/hdac_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index dc2523ef7d98..cd25e2b3f7f2 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include -- GitLab From 938a76ed64860b361d73a6d80f78865ffdc7e0ea Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 5 Aug 2019 13:48:42 -0500 Subject: [PATCH 2395/7155] usb: gadget: atmel_usba_udc: Mark expected switch fall-through Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: at91_dt_defconfig arm): drivers/usb/gadget/udc/atmel_usba_udc.c:329:13: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20190805184842.GA8627@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/atmel_usba_udc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 503d275bc4c4..86ffc8307864 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -327,6 +327,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) switch (fifo_mode) { default: fifo_mode = 0; + /* fall through */ case 0: udc->fifo_cfg = NULL; n = 0; -- GitLab From f0104b0c0fd34f176b305e339e614023b6e27610 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 5 Aug 2019 14:14:26 -0500 Subject: [PATCH 2396/7155] USB: gadget: udc: s3c2410_udc: Mark expected switch fall-throughs Mark switch cases where we are expecting to fall through. This patch fixes the following warning (Building: tct_hammer_defconfig arm): drivers/usb/gadget/udc/s3c2410_udc.c:314:7: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/usb/gadget/udc/s3c2410_udc.c:418:7: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20190805191426.GA12414@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/s3c2410_udc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index af3e63316ace..f82208fbc249 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -312,6 +312,7 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, switch (idx) { default: idx = 0; + /* fall through */ case 0: fifo_reg = S3C2410_UDC_EP0_FIFO_REG; break; @@ -416,6 +417,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, switch (idx) { default: idx = 0; + /* fall through */ case 0: fifo_reg = S3C2410_UDC_EP0_FIFO_REG; break; -- GitLab From 891c1da6ceff10a500e56790e7272e4ac521dc26 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 09:32:34 +0200 Subject: [PATCH 2397/7155] USB: phy: twl6030: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Cc: Felipe Balbi Link: https://lore.kernel.org/r/20190806073235.25140-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-twl6030-usb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index dade34d70419..bfebf1f2e991 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -196,6 +196,12 @@ static ssize_t vbus_show(struct device *dev, } static DEVICE_ATTR_RO(vbus); +static struct attribute *twl6030_attrs[] = { + &dev_attr_vbus.attr, + NULL, +}; +ATTRIBUTE_GROUPS(twl6030); + static irqreturn_t twl6030_usb_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; @@ -361,8 +367,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, twl); - if (device_create_file(&pdev->dev, &dev_attr_vbus)) - dev_warn(&pdev->dev, "could not create sysfs file\n"); INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work); @@ -373,7 +377,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq1, status); - device_remove_file(twl->dev, &dev_attr_vbus); return status; } @@ -384,7 +387,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq2, status); free_irq(twl->irq1, twl); - device_remove_file(twl->dev, &dev_attr_vbus); return status; } @@ -408,7 +410,6 @@ static int twl6030_usb_remove(struct platform_device *pdev) free_irq(twl->irq1, twl); free_irq(twl->irq2, twl); regulator_put(twl->usb3v3); - device_remove_file(twl->dev, &dev_attr_vbus); cancel_work_sync(&twl->set_vbus_work); return 0; @@ -426,6 +427,7 @@ static struct platform_driver twl6030_usb_driver = { .driver = { .name = "twl6030_usb", .of_match_table = of_match_ptr(twl6030_usb_id_table), + .dev_groups = twl6030_groups, }, }; -- GitLab From f4d09e9f53ae2e45a9abb85227fc5f3731184da5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:34 +0200 Subject: [PATCH 2398/7155] USB: phy: tahvo: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Cc: Felipe Balbi Link: https://lore.kernel.org/r/20190805193636.25560-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-tahvo.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index 0981abc3d1ad..baebb1f5a973 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -312,15 +312,12 @@ static ssize_t otg_mode_store(struct device *device, } static DEVICE_ATTR_RW(otg_mode); -static struct attribute *tahvo_attributes[] = { +static struct attribute *tahvo_attrs[] = { &dev_attr_vbus.attr, &dev_attr_otg_mode.attr, NULL }; - -static const struct attribute_group tahvo_attr_group = { - .attrs = tahvo_attributes, -}; +ATTRIBUTE_GROUPS(tahvo); static int tahvo_usb_probe(struct platform_device *pdev) { @@ -406,17 +403,8 @@ static int tahvo_usb_probe(struct platform_device *pdev) goto err_remove_phy; } - /* Attributes */ - ret = sysfs_create_group(&pdev->dev.kobj, &tahvo_attr_group); - if (ret) { - dev_err(&pdev->dev, "cannot create sysfs group: %d\n", ret); - goto err_free_irq; - } - return 0; -err_free_irq: - free_irq(tu->irq, tu); err_remove_phy: usb_remove_phy(&tu->phy); err_disable_clk: @@ -430,7 +418,6 @@ static int tahvo_usb_remove(struct platform_device *pdev) { struct tahvo_usb *tu = platform_get_drvdata(pdev); - sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group); free_irq(tu->irq, tu); usb_remove_phy(&tu->phy); if (!IS_ERR(tu->ick)) @@ -444,6 +431,7 @@ static struct platform_driver tahvo_usb_driver = { .remove = tahvo_usb_remove, .driver = { .name = "tahvo-usb", + .dev_groups = tahvo_groups, }, }; module_platform_driver(tahvo_usb_driver); -- GitLab From 3e2cb866b2b1497a2246c8d222cd672694ac9f15 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:33 +0200 Subject: [PATCH 2399/7155] USB: phy: mv-usb: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Cc: Felipe Balbi Link: https://lore.kernel.org/r/20190805193636.25560-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-mv-usb.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index cf7ecdc9a9d4..06b47f1028b3 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -641,12 +641,15 @@ static const struct attribute_group inputs_attr_group = { .attrs = inputs_attrs, }; +static const struct attribute_group *mv_otg_groups[] = { + &inputs_attr_group, + NULL, +}; + static int mv_otg_remove(struct platform_device *pdev) { struct mv_otg *mvotg = platform_get_drvdata(pdev); - sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); - if (mvotg->qwork) { flush_workqueue(mvotg->qwork); destroy_workqueue(mvotg->qwork); @@ -809,13 +812,6 @@ static int mv_otg_probe(struct platform_device *pdev) goto err_disable_clk; } - retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group); - if (retval < 0) { - dev_dbg(&pdev->dev, - "Can't register sysfs attr group: %d\n", retval); - goto err_remove_phy; - } - spin_lock_init(&mvotg->wq_lock); if (spin_trylock(&mvotg->wq_lock)) { mv_otg_run_state_machine(mvotg, 2 * HZ); @@ -828,8 +824,6 @@ static int mv_otg_probe(struct platform_device *pdev) return 0; -err_remove_phy: - usb_remove_phy(&mvotg->phy); err_disable_clk: mv_otg_disable_internal(mvotg); err_destroy_workqueue: @@ -883,6 +877,7 @@ static struct platform_driver mv_otg_driver = { .remove = mv_otg_remove, .driver = { .name = driver_name, + .dev_groups = mv_otg_groups, }, #ifdef CONFIG_PM .suspend = mv_otg_suspend, -- GitLab From 524f3ac1542c294a9337e4b82c6a22a9e7362290 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Aug 2019 21:36:31 +0200 Subject: [PATCH 2400/7155] USB: chipidea: convert platform driver to use dev_groups Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" any sysfs files. Cc: Peter Chen Link: https://lore.kernel.org/r/20190805193636.25560-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/core.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 36c964cd40a3..215c655295b8 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -903,10 +903,7 @@ static struct attribute *ci_attrs[] = { &dev_attr_role.attr, NULL, }; - -static const struct attribute_group ci_attr_group = { - .attrs = ci_attrs, -}; +ATTRIBUTE_GROUPS(ci); static int ci_hdrc_probe(struct platform_device *pdev) { @@ -1105,14 +1102,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); dbg_create_files(ci); - ret = sysfs_create_group(&dev->kobj, &ci_attr_group); - if (ret) - goto remove_debug; - return 0; -remove_debug: - dbg_remove_files(ci); stop: if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) ci_hdrc_otg_destroy(ci); @@ -1139,7 +1130,6 @@ static int ci_hdrc_remove(struct platform_device *pdev) } dbg_remove_files(ci); - sysfs_remove_group(&ci->dev->kobj, &ci_attr_group); ci_role_destroy(ci); ci_hdrc_enter_lpm(ci, true); ci_usb_phy_exit(ci); @@ -1318,6 +1308,7 @@ static struct platform_driver ci_hdrc_driver = { .driver = { .name = "ci_hdrc", .pm = &ci_pm_ops, + .dev_groups = ci_groups, }, }; -- GitLab From 899ad6d68ec8751d07f537346fbdead53cd43bca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:59 +0200 Subject: [PATCH 2401/7155] USB: lvstest: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Link: https://lore.kernel.org/r/20190806144502.17792-10-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/lvstest.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c index e5c03c6d16e9..407fe7570f3b 100644 --- a/drivers/usb/misc/lvstest.c +++ b/drivers/usb/misc/lvstest.c @@ -310,7 +310,7 @@ static ssize_t enable_compliance_store(struct device *dev, } static DEVICE_ATTR_WO(enable_compliance); -static struct attribute *lvs_attributes[] = { +static struct attribute *lvs_attrs[] = { &dev_attr_get_dev_desc.attr, &dev_attr_u1_timeout.attr, &dev_attr_u2_timeout.attr, @@ -321,10 +321,7 @@ static struct attribute *lvs_attributes[] = { &dev_attr_enable_compliance.attr, NULL }; - -static const struct attribute_group lvs_attr_group = { - .attrs = lvs_attributes, -}; +ATTRIBUTE_GROUPS(lvs); static void lvs_rh_work(struct work_struct *work) { @@ -439,12 +436,6 @@ static int lvs_rh_probe(struct usb_interface *intf, INIT_WORK(&lvs->rh_work, lvs_rh_work); - ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group); - if (ret < 0) { - dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret); - goto free_urb; - } - pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp, @@ -453,13 +444,11 @@ static int lvs_rh_probe(struct usb_interface *intf, ret = usb_submit_urb(lvs->urb, GFP_KERNEL); if (ret < 0) { dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret); - goto sysfs_remove; + goto free_urb; } return ret; -sysfs_remove: - sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); free_urb: usb_free_urb(lvs->urb); return ret; @@ -469,7 +458,6 @@ static void lvs_rh_disconnect(struct usb_interface *intf) { struct lvs_rh *lvs = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); usb_poison_urb(lvs->urb); /* used in scheduled work */ flush_work(&lvs->rh_work); usb_free_urb(lvs->urb); @@ -479,6 +467,7 @@ static struct usb_driver lvs_driver = { .name = "lvs", .probe = lvs_rh_probe, .disconnect = lvs_rh_disconnect, + .dev_groups = lvs_groups, }; module_usb_driver(lvs_driver); -- GitLab From 761ef1e4bc20e7b47e17be3022a2eae87de30560 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:57 +0200 Subject: [PATCH 2402/7155] USB: cypress_cy7c63: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Link: https://lore.kernel.org/r/20190806144502.17792-8-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/cypress_cy7c63.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 9d780b77314b..14faec51d7a5 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -183,6 +183,7 @@ static ssize_t port0_show(struct device *dev, { return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0); } +static DEVICE_ATTR_RW(port0); /* attribute callback handler (read) */ static ssize_t port1_show(struct device *dev, @@ -190,11 +191,14 @@ static ssize_t port1_show(struct device *dev, { return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); } - -static DEVICE_ATTR_RW(port0); - static DEVICE_ATTR_RW(port1); +static struct attribute *cypress_attrs[] = { + &dev_attr_port0.attr, + &dev_attr_port1.attr, + NULL, +}; +ATTRIBUTE_GROUPS(cypress); static int cypress_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -212,26 +216,11 @@ static int cypress_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); - /* create device attribute files */ - retval = device_create_file(&interface->dev, &dev_attr_port0); - if (retval) - goto error; - retval = device_create_file(&interface->dev, &dev_attr_port1); - if (retval) - goto error; - /* let the user know that the device is now attached */ dev_info(&interface->dev, "Cypress CY7C63xxx device now attached\n"); return 0; -error: - device_remove_file(&interface->dev, &dev_attr_port0); - device_remove_file(&interface->dev, &dev_attr_port1); - usb_set_intfdata(interface, NULL); - usb_put_dev(dev->udev); - kfree(dev); - error_mem: return retval; } @@ -242,9 +231,6 @@ static void cypress_disconnect(struct usb_interface *interface) dev = usb_get_intfdata(interface); - /* remove device attribute files */ - device_remove_file(&interface->dev, &dev_attr_port0); - device_remove_file(&interface->dev, &dev_attr_port1); /* the intfdata can be set to NULL only after the * device files have been removed */ usb_set_intfdata(interface, NULL); @@ -262,6 +248,7 @@ static struct usb_driver cypress_driver = { .probe = cypress_probe, .disconnect = cypress_disconnect, .id_table = cypress_table, + .dev_groups = cypress_groups, }; module_usb_driver(cypress_driver); -- GitLab From c847a36521b08dbdaa4a23cb0795c0ee01241f8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:58 +0200 Subject: [PATCH 2403/7155] USB: cytherm: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Link: https://lore.kernel.org/r/20190806144502.17792-9-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/cytherm.c | 64 +++++++++++--------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 8b15ab5e1450..3e3802aaefa3 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -36,20 +36,6 @@ struct usb_cytherm { }; -/* local function prototypes */ -static int cytherm_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void cytherm_disconnect(struct usb_interface *interface); - - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver cytherm_driver = { - .name = "cytherm", - .probe = cytherm_probe, - .disconnect = cytherm_disconnect, - .id_table = id_table, -}; - /* Vendor requests */ /* They all operate on one byte at a time */ #define PING 0x00 @@ -304,6 +290,15 @@ static ssize_t port1_store(struct device *dev, struct device_attribute *attr, co } static DEVICE_ATTR_RW(port1); +static struct attribute *cytherm_attrs[] = { + &dev_attr_brightness.attr, + &dev_attr_temp.attr, + &dev_attr_button.attr, + &dev_attr_port0.attr, + &dev_attr_port1.attr, + NULL, +}; +ATTRIBUTE_GROUPS(cytherm); static int cytherm_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -322,34 +317,10 @@ static int cytherm_probe(struct usb_interface *interface, dev->brightness = 0xFF; - retval = device_create_file(&interface->dev, &dev_attr_brightness); - if (retval) - goto error; - retval = device_create_file(&interface->dev, &dev_attr_temp); - if (retval) - goto error; - retval = device_create_file(&interface->dev, &dev_attr_button); - if (retval) - goto error; - retval = device_create_file(&interface->dev, &dev_attr_port0); - if (retval) - goto error; - retval = device_create_file(&interface->dev, &dev_attr_port1); - if (retval) - goto error; - dev_info (&interface->dev, "Cypress thermometer device now attached\n"); return 0; -error: - device_remove_file(&interface->dev, &dev_attr_brightness); - device_remove_file(&interface->dev, &dev_attr_temp); - device_remove_file(&interface->dev, &dev_attr_button); - device_remove_file(&interface->dev, &dev_attr_port0); - device_remove_file(&interface->dev, &dev_attr_port1); - usb_set_intfdata (interface, NULL); - usb_put_dev(dev->udev); - kfree(dev); + error_mem: return retval; } @@ -360,12 +331,6 @@ static void cytherm_disconnect(struct usb_interface *interface) dev = usb_get_intfdata (interface); - device_remove_file(&interface->dev, &dev_attr_brightness); - device_remove_file(&interface->dev, &dev_attr_temp); - device_remove_file(&interface->dev, &dev_attr_button); - device_remove_file(&interface->dev, &dev_attr_port0); - device_remove_file(&interface->dev, &dev_attr_port1); - /* first remove the files, then NULL the pointer */ usb_set_intfdata (interface, NULL); @@ -376,6 +341,15 @@ static void cytherm_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "Cypress thermometer now disconnected\n"); } +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver cytherm_driver = { + .name = "cytherm", + .probe = cytherm_probe, + .disconnect = cytherm_disconnect, + .id_table = id_table, + .dev_groups = cytherm_groups, +}; + module_usb_driver(cytherm_driver); MODULE_AUTHOR(DRIVER_AUTHOR); -- GitLab From 04a0625e3b374a418139547431eadb0d8676bcba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:56 +0200 Subject: [PATCH 2404/7155] USB: usbtmc: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Cc: Guido Kiener Cc: Steve Bayless Link: https://lore.kernel.org/r/20190806144502.17792-7-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 4942122b2346..7ff831f2fd21 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1836,17 +1836,14 @@ capability_attribute(device_capabilities); capability_attribute(usb488_interface_capabilities); capability_attribute(usb488_device_capabilities); -static struct attribute *capability_attrs[] = { +static struct attribute *usbtmc_attrs[] = { &dev_attr_interface_capabilities.attr, &dev_attr_device_capabilities.attr, &dev_attr_usb488_interface_capabilities.attr, &dev_attr_usb488_device_capabilities.attr, NULL, }; - -static const struct attribute_group capability_attr_grp = { - .attrs = capability_attrs, -}; +ATTRIBUTE_GROUPS(usbtmc); static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data) { @@ -2383,9 +2380,6 @@ static int usbtmc_probe(struct usb_interface *intf, retcode = get_capabilities(data); if (retcode) dev_err(&intf->dev, "can't read capabilities\n"); - else - retcode = sysfs_create_group(&intf->dev.kobj, - &capability_attr_grp); if (data->iin_ep_present) { /* allocate int urb */ @@ -2432,7 +2426,6 @@ static int usbtmc_probe(struct usb_interface *intf, return 0; error_register: - sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); usbtmc_free_int(data); err_put: kref_put(&data->kref, usbtmc_delete); @@ -2445,7 +2438,6 @@ static void usbtmc_disconnect(struct usb_interface *intf) struct list_head *elem; usb_deregister_dev(intf, &usbtmc_class); - sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); mutex_lock(&data->io_mutex); data->zombie = 1; wake_up_interruptible_all(&data->waitq); @@ -2551,6 +2543,7 @@ static struct usb_driver usbtmc_driver = { .resume = usbtmc_resume, .pre_reset = usbtmc_pre_reset, .post_reset = usbtmc_post_reset, + .dev_groups = usbtmc_groups, }; module_usb_driver(usbtmc_driver); -- GitLab From 02c4d45d838957971ec5b7ee359380a0ccfdb963 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:55 +0200 Subject: [PATCH 2405/7155] USB: usblp: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Cc: Pete Zaitcev Link: https://lore.kernel.org/r/20190806144502.17792-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 407a7a6198a2..7fea4999d352 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1082,6 +1082,12 @@ static ssize_t ieee1284_id_show(struct device *dev, struct device_attribute *att static DEVICE_ATTR_RO(ieee1284_id); +static struct attribute *usblp_attrs[] = { + &dev_attr_ieee1284_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(usblp); + static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1156,9 +1162,6 @@ static int usblp_probe(struct usb_interface *intf, /* Retrieve and store the device ID string. */ usblp_cache_device_id_string(usblp); - retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id); - if (retval) - goto abort_intfdata; #ifdef DEBUG usblp_check_status(usblp, 0); @@ -1189,7 +1192,6 @@ static int usblp_probe(struct usb_interface *intf, abort_intfdata: usb_set_intfdata(intf, NULL); - device_remove_file(&intf->dev, &dev_attr_ieee1284_id); abort: kfree(usblp->readbuf); kfree(usblp->statusbuf); @@ -1360,8 +1362,6 @@ static void usblp_disconnect(struct usb_interface *intf) BUG(); } - device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - mutex_lock(&usblp_mutex); mutex_lock(&usblp->mut); usblp->present = 0; @@ -1421,6 +1421,7 @@ static struct usb_driver usblp_driver = { .suspend = usblp_suspend, .resume = usblp_resume, .id_table = usblp_ids, + .dev_groups = usblp_groups, .supports_autosuspend = 1, }; -- GitLab From ec935791ec52ae5098de8fcbf5ac484745b5bd79 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:54 +0200 Subject: [PATCH 2406/7155] USB: ueagle-atm: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Cc: Matthieu CASTET Cc: Stanislaw Gruszka Link: https://lore.kernel.org/r/20190806144502.17792-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 8faa51b1a520..8b0ea8c70d73 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2458,7 +2458,7 @@ static int claim_interface(struct usb_device *usb_dev, return ret; } -static struct attribute *attrs[] = { +static struct attribute *uea_attrs[] = { &dev_attr_stat_status.attr, &dev_attr_stat_mflags.attr, &dev_attr_stat_human_status.attr, @@ -2479,9 +2479,7 @@ static struct attribute *attrs[] = { &dev_attr_stat_firmid.attr, NULL, }; -static const struct attribute_group attr_grp = { - .attrs = attrs, -}; +ATTRIBUTE_GROUPS(uea); static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, const struct usb_device_id *id) @@ -2550,18 +2548,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, } } - ret = sysfs_create_group(&intf->dev.kobj, &attr_grp); - if (ret < 0) - goto error; - ret = uea_boot(sc); if (ret < 0) - goto error_rm_grp; + goto error; return 0; -error_rm_grp: - sysfs_remove_group(&intf->dev.kobj, &attr_grp); error: kfree(sc); return ret; @@ -2571,7 +2563,6 @@ static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) { struct uea_softc *sc = usbatm->driver_data; - sysfs_remove_group(&intf->dev.kobj, &attr_grp); uea_stop(sc); kfree(sc); } @@ -2721,6 +2712,7 @@ static struct usb_driver uea_driver = { .id_table = uea_ids, .probe = uea_probe, .disconnect = uea_disconnect, + .dev_groups = uea_groups, }; MODULE_DEVICE_TABLE(usb, uea_ids); -- GitLab From e605c30977bb5f48af6d14149a252b1619851f33 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:44:53 +0200 Subject: [PATCH 2407/7155] USB: atm: cxacru: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Link: https://lore.kernel.org/r/20190806144502.17792-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 58 +++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index e57a2be8754a..5d41f85a7445 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -539,6 +539,37 @@ CXACRU_SET_##_action( adsl_config); CXACRU_ALL_FILES(INIT); +static struct attribute *cxacru_attrs[] = { + &dev_attr_adsl_config.attr, + &dev_attr_adsl_state.attr, + &dev_attr_adsl_controller_version.attr, + &dev_attr_adsl_headend_environment.attr, + &dev_attr_adsl_headend.attr, + &dev_attr_modulation.attr, + &dev_attr_line_startable.attr, + &dev_attr_downstream_hec_errors.attr, + &dev_attr_upstream_hec_errors.attr, + &dev_attr_downstream_fec_errors.attr, + &dev_attr_upstream_fec_errors.attr, + &dev_attr_downstream_crc_errors.attr, + &dev_attr_upstream_crc_errors.attr, + &dev_attr_startup_attempts.attr, + &dev_attr_downstream_bits_per_frame.attr, + &dev_attr_upstream_bits_per_frame.attr, + &dev_attr_transmitter_power.attr, + &dev_attr_downstream_attenuation.attr, + &dev_attr_upstream_attenuation.attr, + &dev_attr_downstream_snr_margin.attr, + &dev_attr_upstream_snr_margin.attr, + &dev_attr_mac_address.attr, + &dev_attr_line_status.attr, + &dev_attr_link_status.attr, + &dev_attr_upstream_rate.attr, + &dev_attr_downstream_rate.attr, + NULL, +}; +ATTRIBUTE_GROUPS(cxacru); + /* the following three functions are stolen from drivers/usb/core/message.c */ static void cxacru_blocking_completion(struct urb *urb) { @@ -736,17 +767,6 @@ static int cxacru_card_status(struct cxacru_data *instance) return 0; } -static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance, - struct atm_dev *atm_dev) -{ - struct usb_interface *intf = usbatm_instance->usb_intf; - - #define CXACRU_DEVICE_REMOVE_FILE(_name) \ - device_remove_file(&intf->dev, &dev_attr_##_name); - CXACRU_ALL_FILES(REMOVE); - #undef CXACRU_DEVICE_REMOVE_FILE -} - static int cxacru_atm_start(struct usbatm_data *usbatm_instance, struct atm_dev *atm_dev) { @@ -765,13 +785,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, return ret; } - #define CXACRU_DEVICE_CREATE_FILE(_name) \ - ret = device_create_file(&intf->dev, &dev_attr_##_name); \ - if (unlikely(ret)) \ - goto fail_sysfs; - CXACRU_ALL_FILES(CREATE); - #undef CXACRU_DEVICE_CREATE_FILE - /* start ADSL */ mutex_lock(&instance->adsl_state_serialize); ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); @@ -804,11 +817,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, if (start_polling) cxacru_poll_status(&instance->poll_work.work); return 0; - -fail_sysfs: - usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret); - cxacru_remove_device_files(usbatm_instance, atm_dev); - return ret; } static void cxacru_poll_status(struct work_struct *work) @@ -1332,7 +1340,6 @@ static struct usbatm_driver cxacru_driver = { .heavy_init = cxacru_heavy_init, .unbind = cxacru_unbind, .atm_start = cxacru_atm_start, - .atm_stop = cxacru_remove_device_files, .bulk_in = CXACRU_EP_DATA, .bulk_out = CXACRU_EP_DATA, .rx_padding = 3, @@ -1364,7 +1371,8 @@ static struct usb_driver cxacru_usb_driver = { .name = cxacru_driver_name, .probe = cxacru_usb_probe, .disconnect = usbatm_usb_disconnect, - .id_table = cxacru_usb_ids + .id_table = cxacru_usb_ids, + .dev_groups = cxacru_groups, }; module_usb_driver(cxacru_usb_driver); -- GitLab From c5501d23e38df1f1e7afd373a5d924a18936930c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:45:02 +0200 Subject: [PATCH 2408/7155] USB: usbip: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Cc: Valentina Manea Cc: Shuah Khan Link: https://lore.kernel.org/r/20190806144502.17792-13-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_dev.c | 50 ++++++------------------------------ 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 7931e6cecc70..2305d425e6c9 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -106,38 +106,13 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a } static DEVICE_ATTR_WO(usbip_sockfd); -static int stub_add_files(struct device *dev) -{ - int err = 0; - - err = device_create_file(dev, &dev_attr_usbip_status); - if (err) - goto err_status; - - err = device_create_file(dev, &dev_attr_usbip_sockfd); - if (err) - goto err_sockfd; - - err = device_create_file(dev, &dev_attr_usbip_debug); - if (err) - goto err_debug; - - return 0; - -err_debug: - device_remove_file(dev, &dev_attr_usbip_sockfd); -err_sockfd: - device_remove_file(dev, &dev_attr_usbip_status); -err_status: - return err; -} - -static void stub_remove_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_usbip_status); - device_remove_file(dev, &dev_attr_usbip_sockfd); - device_remove_file(dev, &dev_attr_usbip_debug); -} +static struct attribute *usbip_attrs[] = { + &dev_attr_usbip_status.attr, + &dev_attr_usbip_sockfd.attr, + &dev_attr_usbip_debug.attr, + NULL, +}; +ATTRIBUTE_GROUPS(usbip); static void stub_shutdown_connection(struct usbip_device *ud) { @@ -379,17 +354,8 @@ static int stub_probe(struct usb_device *udev) goto err_port; } - rc = stub_add_files(&udev->dev); - if (rc) { - dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); - goto err_files; - } - return 0; -err_files: - usb_hub_release_port(udev->parent, udev->portnum, - (struct usb_dev_state *) udev); err_port: dev_set_drvdata(&udev->dev, NULL); usb_put_dev(udev); @@ -457,7 +423,6 @@ static void stub_disconnect(struct usb_device *udev) /* * NOTE: rx/tx threads are invoked for each usb_device. */ - stub_remove_files(&udev->dev); /* release port */ rc = usb_hub_release_port(udev->parent, udev->portnum, @@ -526,4 +491,5 @@ struct usb_device_driver stub_driver = { .resume = stub_resume, #endif .supports_autosuspend = 0, + .dev_groups = usbip_groups, }; -- GitLab From f9bbcbef0c50b766cf5931ab7d8f3c97a784257e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:45:00 +0200 Subject: [PATCH 2409/7155] USB: trancevibrator: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Cc: Ding Xiang Link: https://lore.kernel.org/r/20190806144502.17792-11-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/trancevibrator.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index ac357ce2d1a6..a3dfc77578ea 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -71,9 +71,14 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr, } return count; } - static DEVICE_ATTR_RW(speed); +static struct attribute *tv_attrs[] = { + &dev_attr_speed.attr, + NULL, +}; +ATTRIBUTE_GROUPS(tv); + static int tv_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -89,15 +94,9 @@ static int tv_probe(struct usb_interface *interface, dev->udev = usb_get_dev(udev); usb_set_intfdata(interface, dev); - retval = device_create_file(&interface->dev, &dev_attr_speed); - if (retval) - goto error_create_file; return 0; -error_create_file: - usb_put_dev(udev); - usb_set_intfdata(interface, NULL); error: kfree(dev); return retval; @@ -108,7 +107,6 @@ static void tv_disconnect(struct usb_interface *interface) struct trancevibrator *dev; dev = usb_get_intfdata (interface); - device_remove_file(&interface->dev, &dev_attr_speed); usb_set_intfdata(interface, NULL); usb_put_dev(dev->udev); kfree(dev); @@ -120,6 +118,7 @@ static struct usb_driver tv_driver = { .probe = tv_probe, .disconnect = tv_disconnect, .id_table = id_table, + .dev_groups = tv_groups, }; module_usb_driver(tv_driver); -- GitLab From a21350feb9ae4d03062eda1fe344ec2a93d6bccc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Aug 2019 16:45:01 +0200 Subject: [PATCH 2410/7155] USB: usbsevseg: convert to use dev_groups USB drivers now support the ability for the driver core to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting the driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it. Link: https://lore.kernel.org/r/20190806144502.17792-12-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbsevseg.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 1923d5b6d9c9..551074f5b7ad 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -316,7 +316,7 @@ MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered); MYDEV_ATTR_SIMPLE_UNSIGNED(mode_msb, update_display_mode); MYDEV_ATTR_SIMPLE_UNSIGNED(mode_lsb, update_display_mode); -static struct attribute *dev_attrs[] = { +static struct attribute *sevseg_attrs[] = { &dev_attr_powered.attr, &dev_attr_text.attr, &dev_attr_textmode.attr, @@ -325,10 +325,7 @@ static struct attribute *dev_attrs[] = { &dev_attr_mode_lsb.attr, NULL }; - -static const struct attribute_group dev_attr_grp = { - .attrs = dev_attrs, -}; +ATTRIBUTE_GROUPS(sevseg); static int sevseg_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -354,17 +351,9 @@ static int sevseg_probe(struct usb_interface *interface, mydev->mode_msb = 0x06; /* 6 characters */ mydev->mode_lsb = 0x3f; /* scanmode for 6 chars */ - rc = sysfs_create_group(&interface->dev.kobj, &dev_attr_grp); - if (rc) - goto error; - dev_info(&interface->dev, "USB 7 Segment device now attached\n"); return 0; -error: - usb_set_intfdata(interface, NULL); - usb_put_dev(mydev->udev); - kfree(mydev); error_mem: return rc; } @@ -374,7 +363,6 @@ static void sevseg_disconnect(struct usb_interface *interface) struct usb_sevsegdev *mydev; mydev = usb_get_intfdata(interface); - sysfs_remove_group(&interface->dev.kobj, &dev_attr_grp); usb_set_intfdata(interface, NULL); usb_put_dev(mydev->udev); kfree(mydev); @@ -423,6 +411,7 @@ static struct usb_driver sevseg_driver = { .resume = sevseg_resume, .reset_resume = sevseg_reset_resume, .id_table = id_table, + .dev_groups = sevseg_groups, .supports_autosuspend = 1, }; -- GitLab From 7794f486ed0b1fa8022dd0a27b9babf86a46d1cf Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 7 Aug 2019 10:29:50 -0400 Subject: [PATCH 2411/7155] usbfs: Add ioctls for runtime power management It has been requested that usbfs should implement runtime power management, instead of forcing the device to remain at full power as long as the device file is open. This patch introduces that new feature. It does so by adding three new usbfs ioctls: USBDEVFS_FORBID_SUSPEND: Prevents the device from going into runtime suspend (and causes a resume if the device is already suspended). USBDEVFS_ALLOW_SUSPEND: Allows the device to go into runtime suspend. Some time may elapse before the device actually is suspended, depending on things like the autosuspend delay. USBDEVFS_WAIT_FOR_RESUME: Blocks until the call is interrupted by a signal or at least one runtime resume has occurred since the most recent ALLOW_SUSPEND ioctl call (which may mean immediately, even if the device is currently suspended). In the latter case, the device is prevented from suspending again just as if FORBID_SUSPEND was called before the ioctl returns. For backward compatibility, when the device file is first opened runtime suspends are forbidden. The userspace program can then allow suspends whenever it wants, and either resume the device directly (by forbidding suspends again) or wait for a resume from some other source (such as a remote wakeup). URBs submitted to a suspended device will fail or will complete with an appropriate error code. This combination of ioctls is sufficient for user programs to have nearly the same degree of control over a device's runtime power behavior as kernel drivers do. Still lacking is documentation for the new ioctls. I intend to add it later, after the existing documentation for the usbfs userspace API is straightened out into a reasonable form. Suggested-by: Mayuresh Kulkarni Signed-off-by: Alan Stern Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908071013220.1514-100000@iolanthe.rowland.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 96 +++++++++++++++++++++++++++++-- drivers/usb/core/generic.c | 5 ++ drivers/usb/core/usb.h | 3 + include/uapi/linux/usbdevice_fs.h | 3 + 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index b265ab5405f9..cdd34dcb2395 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -48,6 +48,9 @@ #define USB_DEVICE_MAX (USB_MAXBUS * 128) #define USB_SG_SIZE 16384 /* split-size for large txs */ +/* Mutual exclusion for ps->list in resume vs. release and remove */ +static DEFINE_MUTEX(usbfs_mutex); + struct usb_dev_state { struct list_head list; /* state list */ struct usb_device *dev; @@ -57,14 +60,17 @@ struct usb_dev_state { struct list_head async_completed; struct list_head memory_list; wait_queue_head_t wait; /* wake up if a request completed */ + wait_queue_head_t wait_for_resume; /* wake up upon runtime resume */ unsigned int discsignr; struct pid *disc_pid; const struct cred *cred; sigval_t disccontext; unsigned long ifclaimed; u32 disabled_bulk_eps; - bool privileges_dropped; unsigned long interface_allowed_mask; + int not_yet_resumed; + bool suspend_allowed; + bool privileges_dropped; }; struct usb_memory { @@ -694,9 +700,7 @@ static void driver_disconnect(struct usb_interface *intf) destroy_async_on_interface(ps, ifnum); } -/* The following routines are merely placeholders. There is no way - * to inform a user task about suspend or resumes. - */ +/* We don't care about suspend/resume of claimed interfaces */ static int driver_suspend(struct usb_interface *intf, pm_message_t msg) { return 0; @@ -707,12 +711,32 @@ static int driver_resume(struct usb_interface *intf) return 0; } +/* The following routines apply to the entire device, not interfaces */ +void usbfs_notify_suspend(struct usb_device *udev) +{ + /* We don't need to handle this */ +} + +void usbfs_notify_resume(struct usb_device *udev) +{ + struct usb_dev_state *ps; + + /* Protect against simultaneous remove or release */ + mutex_lock(&usbfs_mutex); + list_for_each_entry(ps, &udev->filelist, list) { + WRITE_ONCE(ps->not_yet_resumed, 0); + wake_up_all(&ps->wait_for_resume); + } + mutex_unlock(&usbfs_mutex); +} + struct usb_driver usbfs_driver = { .name = "usbfs", .probe = driver_probe, .disconnect = driver_disconnect, .suspend = driver_suspend, .resume = driver_resume, + .supports_autosuspend = 1, }; static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) @@ -997,9 +1021,12 @@ static int usbdev_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&ps->async_completed); INIT_LIST_HEAD(&ps->memory_list); init_waitqueue_head(&ps->wait); + init_waitqueue_head(&ps->wait_for_resume); ps->disc_pid = get_pid(task_pid(current)); ps->cred = get_current_cred(); smp_wmb(); + + /* Can't race with resume; the device is already active */ list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; usb_unlock_device(dev); @@ -1025,7 +1052,10 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_lock_device(dev); usb_hub_release_all_ports(dev, ps); + /* Protect against simultaneous resume */ + mutex_lock(&usbfs_mutex); list_del_init(&ps->list); + mutex_unlock(&usbfs_mutex); for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); ifnum++) { @@ -1033,7 +1063,8 @@ static int usbdev_release(struct inode *inode, struct file *file) releaseintf(ps, ifnum); } destroy_all_async(ps); - usb_autosuspend_device(dev); + if (!ps->suspend_allowed) + usb_autosuspend_device(dev); usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); @@ -2384,6 +2415,47 @@ static int proc_drop_privileges(struct usb_dev_state *ps, void __user *arg) return 0; } +static int proc_forbid_suspend(struct usb_dev_state *ps) +{ + int ret = 0; + + if (ps->suspend_allowed) { + ret = usb_autoresume_device(ps->dev); + if (ret == 0) + ps->suspend_allowed = false; + else if (ret != -ENODEV) + ret = -EIO; + } + return ret; +} + +static int proc_allow_suspend(struct usb_dev_state *ps) +{ + if (!connected(ps)) + return -ENODEV; + + WRITE_ONCE(ps->not_yet_resumed, 1); + if (!ps->suspend_allowed) { + usb_autosuspend_device(ps->dev); + ps->suspend_allowed = true; + } + return 0; +} + +static int proc_wait_for_resume(struct usb_dev_state *ps) +{ + int ret; + + usb_unlock_device(ps->dev); + ret = wait_event_interruptible(ps->wait_for_resume, + READ_ONCE(ps->not_yet_resumed) == 0); + usb_lock_device(ps->dev); + + if (ret != 0) + return -EINTR; + return proc_forbid_suspend(ps); +} + /* * NOTE: All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from @@ -2578,6 +2650,15 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, case USBDEVFS_GET_SPEED: ret = ps->dev->speed; break; + case USBDEVFS_FORBID_SUSPEND: + ret = proc_forbid_suspend(ps); + break; + case USBDEVFS_ALLOW_SUSPEND: + ret = proc_allow_suspend(ps); + break; + case USBDEVFS_WAIT_FOR_RESUME: + ret = proc_wait_for_resume(ps); + break; } /* Handle variable-length commands */ @@ -2651,15 +2732,20 @@ static void usbdev_remove(struct usb_device *udev) { struct usb_dev_state *ps; + /* Protect against simultaneous resume */ + mutex_lock(&usbfs_mutex); while (!list_empty(&udev->filelist)) { ps = list_entry(udev->filelist.next, struct usb_dev_state, list); destroy_all_async(ps); wake_up_all(&ps->wait); + WRITE_ONCE(ps->not_yet_resumed, 0); + wake_up_all(&ps->wait_for_resume); list_del_init(&ps->list); if (ps->discsignr) kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext, ps->disc_pid, ps->cred); } + mutex_unlock(&usbfs_mutex); } static int usbdev_notify(struct notifier_block *self, diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 1ac9c1e5f773..38f8b3e31762 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -257,6 +257,8 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) else rc = usb_port_suspend(udev, msg); + if (rc == 0) + usbfs_notify_suspend(udev); return rc; } @@ -273,6 +275,9 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg) rc = hcd_bus_resume(udev, msg); else rc = usb_port_resume(udev, msg); + + if (rc == 0) + usbfs_notify_resume(udev); return rc; } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index bd8d01f85a13..2932d1ec5def 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -95,6 +95,9 @@ extern int usb_runtime_idle(struct device *dev); extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev); extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev); +extern void usbfs_notify_suspend(struct usb_device *udev); +extern void usbfs_notify_resume(struct usb_device *udev); + #else static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg) diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index 78efe870c2b7..d24bbb6d3ca1 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -223,5 +223,8 @@ struct usbdevfs_streams { * extending size of the data returned. */ #define USBDEVFS_CONNINFO_EX(len) _IOC(_IOC_READ, 'U', 32, len) +#define USBDEVFS_FORBID_SUSPEND _IO('U', 33) +#define USBDEVFS_ALLOW_SUSPEND _IO('U', 34) +#define USBDEVFS_WAIT_FOR_RESUME _IO('U', 35) #endif /* _UAPI_LINUX_USBDEVICE_FS_H */ -- GitLab From 31eb845718398f9bc9f6fbe1aca675f4e6284392 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 8 Aug 2019 11:39:17 +0200 Subject: [PATCH 2412/7155] intel-hid: intel-vbtn: Avoid leaking wakeup_mode set Both intel-hid and intel-vbtn set a wakeup_mode flag causing them to behave in a special way during system suspend and while suspended in their "prepare" PM callbacks and clear it in their "resume" PM callbacks. That may cause the wakeup_mode flag to remain set after a system suspend failure (if some other driver's "suspend" callback returns an error before the "suspend" callback of either intel-hid or intel-vbtn is invoked). After commit 10a08fd65ec1 ("ACPI: PM: Set up EC GPE for system wakeup from drivers that need it") that also affects the "wakeup mask" bit of the EC GPE, which may not be cleared after a failing system suspend. Fix this issue by adding "complete" PM callbacks to intel-hid and intel-vbtn to clear the wakeup_mode flag and the "wakeup mask" bit of the EC GPE if they have not been cleared earlier. Fixes: 10a08fd65ec1 ("ACPI: PM: Set up EC GPE for system wakeup from drivers that need it") Signed-off-by: Rafael J. Wysocki Acked-by: Andy Shevchenko --- drivers/platform/x86/intel-hid.c | 17 ++++++++++++----- drivers/platform/x86/intel-vbtn.c | 12 +++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index e51c72b92cbd..6feda887df9d 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -262,6 +262,16 @@ static int intel_hid_pm_prepare(struct device *device) return 0; } +static void intel_hid_pm_complete(struct device *device) +{ + struct intel_hid_priv *priv = dev_get_drvdata(device); + + if (priv->wakeup_mode) { + acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); + priv->wakeup_mode = false; + } +} + static int intel_hid_pl_suspend_handler(struct device *device) { if (pm_suspend_via_firmware()) { @@ -273,12 +283,8 @@ static int intel_hid_pl_suspend_handler(struct device *device) static int intel_hid_pl_resume_handler(struct device *device) { - if (device_may_wakeup(device)) { - struct intel_hid_priv *priv = dev_get_drvdata(device); + intel_hid_pm_complete(device); - acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); - priv->wakeup_mode = false; - } if (pm_resume_via_firmware()) { intel_hid_set_enable(device, true); intel_button_array_enable(device, true); @@ -288,6 +294,7 @@ static int intel_hid_pl_resume_handler(struct device *device) static const struct dev_pm_ops intel_hid_pl_pm_ops = { .prepare = intel_hid_pm_prepare, + .complete = intel_hid_pm_complete, .freeze = intel_hid_pl_suspend_handler, .thaw = intel_hid_pl_resume_handler, .restore = intel_hid_pl_resume_handler, diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index ab84e1bbdedd..b28e5519337e 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -210,19 +210,25 @@ static int intel_vbtn_pm_prepare(struct device *dev) return 0; } -static int intel_vbtn_pm_resume(struct device *dev) +static void intel_vbtn_pm_complete(struct device *dev) { - if (device_may_wakeup(dev)) { - struct intel_vbtn_priv *priv = dev_get_drvdata(dev); + struct intel_vbtn_priv *priv = dev_get_drvdata(dev); + if (priv->wakeup_mode) { acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); priv->wakeup_mode = false; } +} + +static int intel_vbtn_pm_resume(struct device *dev) +{ + intel_vbtn_pm_complete(dev); return 0; } static const struct dev_pm_ops intel_vbtn_pm_ops = { .prepare = intel_vbtn_pm_prepare, + .complete = intel_vbtn_pm_complete, .resume = intel_vbtn_pm_resume, .restore = intel_vbtn_pm_resume, .thaw = intel_vbtn_pm_resume, -- GitLab From d19bdb876bece27187d4ffbc272672e1239cd313 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 8 Aug 2019 11:39:23 +0200 Subject: [PATCH 2413/7155] intel-hid: Disable button array during suspend-to-idle Notice that intel_button_array_enable() never disables the power button which is the only one needed to wake up the system from suspend-to-idle, so it can be safely called during suspend-to-idle as well as during "regular" system suspend, and rearrange the code in the driver's "suspend" and "resume" callbacks accordingly. While at it, use pm_suspend_no_platform() to check if the current suspend-resume cycle is suspend-to-idle, as that is the only case when the device should be enabled while suspended. Signed-off-by: Rafael J. Wysocki Acked-by: Andy Shevchenko --- drivers/platform/x86/intel-hid.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 6feda887df9d..18ac237114ff 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -274,10 +274,11 @@ static void intel_hid_pm_complete(struct device *device) static int intel_hid_pl_suspend_handler(struct device *device) { - if (pm_suspend_via_firmware()) { + intel_button_array_enable(device, false); + + if (!pm_suspend_no_platform()) intel_hid_set_enable(device, false); - intel_button_array_enable(device, false); - } + return 0; } @@ -285,10 +286,10 @@ static int intel_hid_pl_resume_handler(struct device *device) { intel_hid_pm_complete(device); - if (pm_resume_via_firmware()) { + if (!pm_suspend_no_platform()) intel_hid_set_enable(device, true); - intel_button_array_enable(device, true); - } + + intel_button_array_enable(device, true); return 0; } -- GitLab From 2c2b005f549544c13ef4cfb0e4842949066889bc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 7 Aug 2019 13:10:37 +0200 Subject: [PATCH 2414/7155] ACPI / processor: don't print errors for processorIDs == 0xff Some platforms define their processors in this manner: Device (SCK0) { Name (_HID, "ACPI0004" /* Module Device */) // _HID: Hardware ID Name (_UID, "CPUSCK0") // _UID: Unique ID Processor (CP00, 0x00, 0x00000410, 0x06){} Processor (CP01, 0x02, 0x00000410, 0x06){} Processor (CP02, 0x04, 0x00000410, 0x06){} Processor (CP03, 0x06, 0x00000410, 0x06){} Processor (CP04, 0x01, 0x00000410, 0x06){} Processor (CP05, 0x03, 0x00000410, 0x06){} Processor (CP06, 0x05, 0x00000410, 0x06){} Processor (CP07, 0x07, 0x00000410, 0x06){} Processor (CP08, 0xFF, 0x00000410, 0x06){} Processor (CP09, 0xFF, 0x00000410, 0x06){} Processor (CP0A, 0xFF, 0x00000410, 0x06){} Processor (CP0B, 0xFF, 0x00000410, 0x06){} ... The processors marked as 0xff are invalid, there are only 8 of them in this case. So do not print an error on ids == 0xff, just print an info message. Actually, we could return ENODEV even on the first CPU with ID 0xff, but ACPI spec does not forbid the 0xff value to be a processor ID. Given 0xff could be a correct one, we would break working systems if we returned ENODEV. Signed-off-by: Jiri Slaby Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 24f065114d42..2c4dda0787e8 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -279,9 +279,13 @@ static int acpi_processor_get_info(struct acpi_device *device) } if (acpi_duplicate_processor_id(pr->acpi_id)) { - dev_err(&device->dev, - "Failed to get unique processor _UID (0x%x)\n", - pr->acpi_id); + if (pr->acpi_id == 0xff) + dev_info_once(&device->dev, + "Entry not well-defined, consider updating BIOS\n"); + else + dev_err(&device->dev, + "Failed to get unique processor _UID (0x%x)\n", + pr->acpi_id); return -ENODEV; } -- GitLab From cc911c2251f07470f8e085ec8ff670e6bdd56add Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 17:01:13 +0800 Subject: [PATCH 2415/7155] ALSA: ac97: remove unused variable 'snd_ac97_controls_master_mono' sound/pci/ac97/ac97_codec.c:599:38: warning: snd_ac97_controls_master_mono defined but not used [-Wunused-const-variable=] It is never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 96b4601aae73..66f6c3bf08e3 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -596,11 +596,6 @@ static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, return err; } -static const struct snd_kcontrol_new snd_ac97_controls_master_mono[2] = { -AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), -AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1) -}; - static const struct snd_kcontrol_new snd_ac97_controls_tone[2] = { AC97_SINGLE("Tone Control - Bass", AC97_MASTER_TONE, 8, 15, 1), AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1) -- GitLab From 3567894b6914813299300019e028874927210880 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 10:40:16 +0200 Subject: [PATCH 2416/7155] clk: core: introduce clk_hw_set_parent() Introduce the clk_hw_set_parent() provider call to change parent of a clock by using the clk_hw pointers. This eases the clock reparenting from clock rate notifiers and implementing DVFS with simpler code avoiding the boilerplates functions as __clk_lookup(clk_hw_get_name()) then clk_set_parent(). Signed-off-by: Neil Armstrong Acked-by: Martin Blumenstingl Acked-by: Stephen Boyd Signed-off-by: Jerome Brunet --- drivers/clk/clk.c | 6 ++++++ include/linux/clk-provider.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c0990703ce54..c11b1781d24a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2487,6 +2487,12 @@ static int clk_core_set_parent_nolock(struct clk_core *core, return ret; } +int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *parent) +{ + return clk_core_set_parent_nolock(hw->core, parent->core); +} +EXPORT_SYMBOL_GPL(clk_hw_set_parent); + /** * clk_set_parent - switch the parent of a mux clk * @clk: the mux clk whose input we are switching diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 2ae7604783dd..dce5521a9bf6 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -817,6 +817,7 @@ unsigned int clk_hw_get_num_parents(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index); +int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent); unsigned int __clk_get_enable_count(struct clk *clk); unsigned long clk_hw_get_rate(const struct clk_hw *hw); unsigned long __clk_get_flags(struct clk *clk); -- GitLab From 26d34431add04a98a60b8935c25765914fa773f7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 10:40:17 +0200 Subject: [PATCH 2417/7155] clk: meson: add g12a cpu dynamic divider driver Add a clock driver for the cpu dynamic divider, this divider needs to have a flag set before setting the divider value then removed while writing the new value to the register. This drivers implements this behavior and will be used essentially on the Amlogic G12A and G12B SoCs for cpu clock trees. Signed-off-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 5 ++ drivers/clk/meson/Makefile | 1 + drivers/clk/meson/clk-cpu-dyndiv.c | 73 ++++++++++++++++++++++++++++++ drivers/clk/meson/clk-cpu-dyndiv.h | 20 ++++++++ 4 files changed, 99 insertions(+) create mode 100644 drivers/clk/meson/clk-cpu-dyndiv.c create mode 100644 drivers/clk/meson/clk-cpu-dyndiv.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 500be0b0d473..dabeb435d067 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -36,6 +36,10 @@ config COMMON_CLK_MESON_EE_CLKC tristate select COMMON_CLK_MESON_REGMAP +config COMMON_CLK_MESON_CPU_DYNDIV + tristate + select COMMON_CLK_MESON_REGMAP + config COMMON_CLK_MESON8B bool depends on ARCH_MESON @@ -98,6 +102,7 @@ config COMMON_CLK_G12A select COMMON_CLK_MESON_PLL select COMMON_CLK_MESON_AO_CLKC select COMMON_CLK_MESON_EE_CLKC + select COMMON_CLK_MESON_CPU_DYNDIV select MFD_SYSCON help Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index f09d83dc3d60..3939f218587a 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,6 +2,7 @@ # Amlogic clock drivers obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o +obj-$(CONFIG_COMMON_CLK_MESON_CPU_DYNDIV) += clk-cpu-dyndiv.o obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o diff --git a/drivers/clk/meson/clk-cpu-dyndiv.c b/drivers/clk/meson/clk-cpu-dyndiv.c new file mode 100644 index 000000000000..36976927fe82 --- /dev/null +++ b/drivers/clk/meson/clk-cpu-dyndiv.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS. + * Author: Neil Armstrong + */ + +#include +#include + +#include "clk-regmap.h" +#include "clk-cpu-dyndiv.h" + +static inline struct meson_clk_cpu_dyndiv_data * +meson_clk_cpu_dyndiv_data(struct clk_regmap *clk) +{ + return (struct meson_clk_cpu_dyndiv_data *)clk->data; +} + +static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk); + + return divider_recalc_rate(hw, prate, + meson_parm_read(clk->map, &data->div), + NULL, 0, data->div.width); +} + +static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk); + + return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0); +} + +static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk); + unsigned int val; + int ret; + + ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0); + if (ret < 0) + return ret; + + val = (unsigned int)ret << data->div.shift; + + /* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */ + meson_parm_write(clk->map, &data->dyn, 1); + + /* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */ + return regmap_update_bits(clk->map, data->div.reg_off, + SETPMASK(data->div.width, data->div.shift) | + SETPMASK(data->dyn.width, data->dyn.shift), + val); +}; + +const struct clk_ops meson_clk_cpu_dyndiv_ops = { + .recalc_rate = meson_clk_cpu_dyndiv_recalc_rate, + .round_rate = meson_clk_cpu_dyndiv_round_rate, + .set_rate = meson_clk_cpu_dyndiv_set_rate, +}; +EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops); + +MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/meson/clk-cpu-dyndiv.h b/drivers/clk/meson/clk-cpu-dyndiv.h new file mode 100644 index 000000000000..f4908404792e --- /dev/null +++ b/drivers/clk/meson/clk-cpu-dyndiv.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 BayLibre, SAS. + * Author: Neil Armstrong + */ + +#ifndef __MESON_CLK_CPU_DYNDIV_H +#define __MESON_CLK_CPU_DYNDIV_H + +#include +#include "parm.h" + +struct meson_clk_cpu_dyndiv_data { + struct parm div; + struct parm dyn; +}; + +extern const struct clk_ops meson_clk_cpu_dyndiv_ops; + +#endif /* __MESON_CLK_CPU_DYNDIV_H */ -- GitLab From ffae8475b90c045ca508675794c08a0c8c12d202 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 10:40:18 +0200 Subject: [PATCH 2418/7155] clk: meson: g12a: add notifiers to handle cpu clock change In order to implement clock switching for the CLKID_CPU_CLK and CLKID_CPUB_CLK, notifiers are added on specific points of the clock tree : cpu_clk / cpub_clk | \- cpu_clk_dyn | | \- cpu_clk_premux0 | | |- cpu_clk_postmux0 | | | |- cpu_clk_dyn0_div | | | \- xtal/fclk_div2/fclk_div3 | | \- xtal/fclk_div2/fclk_div3 | \- cpu_clk_premux1 | |- cpu_clk_postmux1 | | |- cpu_clk_dyn1_div | | \- xtal/fclk_div2/fclk_div3 | \- xtal/fclk_div2/fclk_div3 \ sys_pll / sys1_pll This for each cluster, a single one for G12A, two for G12B. Each cpu_clk_premux1 tree is marked as read-only and CLK_SET_RATE_NO_REPARENT, to be used as "parking" clock in a safe clock frequency. A notifier is added on each cpu_clk_premux0 to detech when CCF want to change the frequency of the cpu_clk_dyn tree. In this notifier, the cpu_clk_premux1 tree is configured to use the xtal clock and then the cpu_clk_dyn is switch to cpu_clk_premux1 while CCF updates the cpu_clk_premux0 tree. A notifier is added on each sys_pll/sys1_pll to detect when CCF wants to change the PLL clock source of the cpu_clk. In this notifier, the cpu_clk is switched to cpu_clk_dyn while CCF updates the sys_pll/sys1_pll frequency. A third small notifier is added on each cpu_clk / cpub_clk and cpu_clk_dyn, add a small delay at PRE_RATE_CHANGE/POST_RATE_CHANGE to let the other notofiers change propagate before changing the cpu_clk_premux0 and sys_pll clock trees. This notifier set permits switching the cpu_clk / cpub_clk without any glitches and using a safe parking clock while switching between sub-GHz clocks using the cpu_clk_dyn tree. This setup has been tested and validated on the Amlogic G12A and G12B SoCs running the arm64 cpuburn at [1] and cycling between all the possible cpufreq translations of each cluster and checking the final frequency using the clock-measurer, script at [2]. [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a.c | 535 +++++++++++++++++++++++++++++++++++---- 1 file changed, 481 insertions(+), 54 deletions(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index a8f706de811b..c3f0ffc3280d 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -14,10 +14,12 @@ #include #include #include +#include #include "clk-mpll.h" #include "clk-pll.h" #include "clk-regmap.h" +#include "clk-cpu-dyndiv.h" #include "vid-pll-div.h" #include "meson-eeclk.h" #include "g12a.h" @@ -88,16 +90,9 @@ static struct clk_regmap g12a_fixed_pll = { }, }; -/* - * Internal sys pll emulation configuration parameters - */ -static const struct reg_sequence g12a_sys_init_regs[] = { - { .reg = HHI_SYS_PLL_CNTL1, .def = 0x00000000 }, - { .reg = HHI_SYS_PLL_CNTL2, .def = 0x00000000 }, - { .reg = HHI_SYS_PLL_CNTL3, .def = 0x48681c00 }, - { .reg = HHI_SYS_PLL_CNTL4, .def = 0x88770290 }, - { .reg = HHI_SYS_PLL_CNTL5, .def = 0x39272000 }, - { .reg = HHI_SYS_PLL_CNTL6, .def = 0x56540000 }, +static const struct pll_mult_range g12a_sys_pll_mult_range = { + .min = 128, + .max = 250, }; static struct clk_regmap g12a_sys_pll_dco = { @@ -127,16 +122,17 @@ static struct clk_regmap g12a_sys_pll_dco = { .shift = 29, .width = 1, }, - .init_regs = g12a_sys_init_regs, - .init_count = ARRAY_SIZE(g12a_sys_init_regs), + .range = &g12a_sys_pll_mult_range, }, .hw.init = &(struct clk_init_data){ .name = "sys_pll_dco", - .ops = &meson_clk_pll_ro_ops, + .ops = &meson_clk_pll_ops, .parent_data = &(const struct clk_parent_data) { .fw_name = "xtal", }, .num_parents = 1, + /* This clock feeds the CPU, avoid disabling it */ + .flags = CLK_IS_CRITICAL, }, }; @@ -149,11 +145,12 @@ static struct clk_regmap g12a_sys_pll = { }, .hw.init = &(struct clk_init_data){ .name = "sys_pll", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_sys_pll_dco.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -184,14 +181,17 @@ static struct clk_regmap g12b_sys1_pll_dco = { .shift = 29, .width = 1, }, + .range = &g12a_sys_pll_mult_range, }, .hw.init = &(struct clk_init_data){ .name = "sys1_pll_dco", - .ops = &meson_clk_pll_ro_ops, + .ops = &meson_clk_pll_ops, .parent_data = &(const struct clk_parent_data) { .fw_name = "xtal", }, .num_parents = 1, + /* This clock feeds the CPU, avoid disabling it */ + .flags = CLK_IS_CRITICAL, }, }; @@ -204,11 +204,12 @@ static struct clk_regmap g12b_sys1_pll = { }, .hw.init = &(struct clk_init_data){ .name = "sys1_pll", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_sys1_pll_dco.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -345,13 +346,15 @@ static struct clk_regmap g12a_cpu_clk_premux0 = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_data = (const struct clk_parent_data []) { { .fw_name = "xtal", }, { .hw = &g12a_fclk_div2.hw }, { .hw = &g12a_fclk_div3.hw }, }, .num_parents = 3, + /* This sub-tree is used a parking clock */ + .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -364,30 +367,40 @@ static struct clk_regmap g12a_cpu_clk_premux1 = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn1_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_data = (const struct clk_parent_data []) { { .fw_name = "xtal", }, { .hw = &g12a_fclk_div2.hw }, { .hw = &g12a_fclk_div3.hw }, }, .num_parents = 3, + /* This sub-tree is used a parking clock */ + .flags = CLK_SET_RATE_NO_REPARENT }, }; /* Datasheet names this field as "mux0_divn_tcnt" */ static struct clk_regmap g12a_cpu_clk_mux0_div = { - .data = &(struct clk_regmap_div_data){ - .offset = HHI_SYS_CPU_CLK_CNTL0, - .shift = 4, - .width = 6, + .data = &(struct meson_clk_cpu_dyndiv_data){ + .div = { + .reg_off = HHI_SYS_CPU_CLK_CNTL0, + .shift = 4, + .width = 6, + }, + .dyn = { + .reg_off = HHI_SYS_CPU_CLK_CNTL0, + .shift = 26, + .width = 1, + }, }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0_div", - .ops = &clk_regmap_divider_ro_ops, + .ops = &meson_clk_cpu_dyndiv_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_premux0.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -400,12 +413,13 @@ static struct clk_regmap g12a_cpu_clk_postmux0 = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn0", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_premux0.hw, &g12a_cpu_clk_mux0_div.hw, }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -435,12 +449,14 @@ static struct clk_regmap g12a_cpu_clk_postmux1 = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn1", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_premux1.hw, &g12a_cpu_clk_mux1_div.hw, }, .num_parents = 2, + /* This sub-tree is used a parking clock */ + .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -453,12 +469,13 @@ static struct clk_regmap g12a_cpu_clk_dyn = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk_dyn", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_postmux0.hw, &g12a_cpu_clk_postmux1.hw, }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -471,12 +488,13 @@ static struct clk_regmap g12a_cpu_clk = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_dyn.hw, &g12a_sys_pll.hw, }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -489,12 +507,13 @@ static struct clk_regmap g12b_cpu_clk = { }, .hw.init = &(struct clk_init_data){ .name = "cpu_clk", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk_dyn.hw, &g12b_sys1_pll.hw }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -507,7 +526,7 @@ static struct clk_regmap g12b_cpub_clk_premux0 = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_data = (const struct clk_parent_data []) { { .fw_name = "xtal", }, { .hw = &g12a_fclk_div2.hw }, @@ -519,18 +538,26 @@ static struct clk_regmap g12b_cpub_clk_premux0 = { /* Datasheet names this field as "mux0_divn_tcnt" */ static struct clk_regmap g12b_cpub_clk_mux0_div = { - .data = &(struct clk_regmap_div_data){ - .offset = HHI_SYS_CPUB_CLK_CNTL, - .shift = 4, - .width = 6, + .data = &(struct meson_clk_cpu_dyndiv_data){ + .div = { + .reg_off = HHI_SYS_CPUB_CLK_CNTL, + .shift = 4, + .width = 6, + }, + .dyn = { + .reg_off = HHI_SYS_CPUB_CLK_CNTL, + .shift = 26, + .width = 1, + }, }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0_div", - .ops = &clk_regmap_divider_ro_ops, + .ops = &meson_clk_cpu_dyndiv_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_cpub_clk_premux0.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -543,12 +570,13 @@ static struct clk_regmap g12b_cpub_clk_postmux0 = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn0", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_cpub_clk_premux0.hw, &g12b_cpub_clk_mux0_div.hw }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -561,13 +589,15 @@ static struct clk_regmap g12b_cpub_clk_premux1 = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn1_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_data = (const struct clk_parent_data []) { { .fw_name = "xtal", }, { .hw = &g12a_fclk_div2.hw }, { .hw = &g12a_fclk_div3.hw }, }, .num_parents = 3, + /* This sub-tree is used a parking clock */ + .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -597,12 +627,14 @@ static struct clk_regmap g12b_cpub_clk_postmux1 = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn1", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_cpub_clk_premux1.hw, &g12b_cpub_clk_mux1_div.hw }, .num_parents = 2, + /* This sub-tree is used a parking clock */ + .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -615,12 +647,13 @@ static struct clk_regmap g12b_cpub_clk_dyn = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk_dyn", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_cpub_clk_postmux0.hw, &g12b_cpub_clk_postmux1.hw }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -633,15 +666,227 @@ static struct clk_regmap g12b_cpub_clk = { }, .hw.init = &(struct clk_init_data){ .name = "cpub_clk", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = (const struct clk_hw *[]) { &g12b_cpub_clk_dyn.hw, &g12a_sys_pll.hw }, .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, }, }; +static int g12a_cpu_clk_mux_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + if (event == POST_RATE_CHANGE || event == PRE_RATE_CHANGE) { + /* Wait for clock propagation before/after changing the mux */ + udelay(100); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + +static struct notifier_block g12a_cpu_clk_mux_nb = { + .notifier_call = g12a_cpu_clk_mux_notifier_cb, +}; + +struct g12a_cpu_clk_postmux_nb_data { + struct notifier_block nb; + struct clk_hw *xtal; + struct clk_hw *cpu_clk_dyn; + struct clk_hw *cpu_clk_postmux0; + struct clk_hw *cpu_clk_postmux1; + struct clk_hw *cpu_clk_premux1; +}; + +static int g12a_cpu_clk_postmux_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct g12a_cpu_clk_postmux_nb_data *nb_data = + container_of(nb, struct g12a_cpu_clk_postmux_nb_data, nb); + + switch (event) { + case PRE_RATE_CHANGE: + /* + * This notifier means cpu_clk_postmux0 clock will be changed + * to feed cpu_clk, this is the current path : + * cpu_clk + * \- cpu_clk_dyn + * \- cpu_clk_postmux0 + * \- cpu_clk_muxX_div + * \- cpu_clk_premux0 + * \- fclk_div3 or fclk_div2 + * OR + * \- cpu_clk_premux0 + * \- fclk_div3 or fclk_div2 + */ + + /* Setup cpu_clk_premux1 to xtal */ + clk_hw_set_parent(nb_data->cpu_clk_premux1, + nb_data->xtal); + + /* Setup cpu_clk_postmux1 to bypass divider */ + clk_hw_set_parent(nb_data->cpu_clk_postmux1, + nb_data->cpu_clk_premux1); + + /* Switch to parking clk on cpu_clk_postmux1 */ + clk_hw_set_parent(nb_data->cpu_clk_dyn, + nb_data->cpu_clk_postmux1); + + /* + * Now, cpu_clk is 24MHz in the current path : + * cpu_clk + * \- cpu_clk_dyn + * \- cpu_clk_postmux1 + * \- cpu_clk_premux1 + * \- xtal + */ + + udelay(100); + + return NOTIFY_OK; + + case POST_RATE_CHANGE: + /* + * The cpu_clk_postmux0 has ben updated, now switch back + * cpu_clk_dyn to cpu_clk_postmux0 and take the changes + * in account. + */ + + /* Configure cpu_clk_dyn back to cpu_clk_postmux0 */ + clk_hw_set_parent(nb_data->cpu_clk_dyn, + nb_data->cpu_clk_postmux0); + + /* + * new path : + * cpu_clk + * \- cpu_clk_dyn + * \- cpu_clk_postmux0 + * \- cpu_clk_muxX_div + * \- cpu_clk_premux0 + * \- fclk_div3 or fclk_div2 + * OR + * \- cpu_clk_premux0 + * \- fclk_div3 or fclk_div2 + */ + + udelay(100); + + return NOTIFY_OK; + + default: + return NOTIFY_DONE; + } +} + +static struct g12a_cpu_clk_postmux_nb_data g12a_cpu_clk_postmux0_nb_data = { + .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw, + .cpu_clk_postmux0 = &g12a_cpu_clk_postmux0.hw, + .cpu_clk_postmux1 = &g12a_cpu_clk_postmux1.hw, + .cpu_clk_premux1 = &g12a_cpu_clk_premux1.hw, + .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb, +}; + +static struct g12a_cpu_clk_postmux_nb_data g12b_cpub_clk_postmux0_nb_data = { + .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw, + .cpu_clk_postmux0 = &g12b_cpub_clk_postmux0.hw, + .cpu_clk_postmux1 = &g12b_cpub_clk_postmux1.hw, + .cpu_clk_premux1 = &g12b_cpub_clk_premux1.hw, + .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb, +}; + +struct g12a_sys_pll_nb_data { + struct notifier_block nb; + struct clk_hw *sys_pll; + struct clk_hw *cpu_clk; + struct clk_hw *cpu_clk_dyn; +}; + +static int g12a_sys_pll_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct g12a_sys_pll_nb_data *nb_data = + container_of(nb, struct g12a_sys_pll_nb_data, nb); + + switch (event) { + case PRE_RATE_CHANGE: + /* + * This notifier means sys_pll clock will be changed + * to feed cpu_clk, this the current path : + * cpu_clk + * \- sys_pll + * \- sys_pll_dco + */ + + /* Configure cpu_clk to use cpu_clk_dyn */ + clk_hw_set_parent(nb_data->cpu_clk, + nb_data->cpu_clk_dyn); + + /* + * Now, cpu_clk uses the dyn path + * cpu_clk + * \- cpu_clk_dyn + * \- cpu_clk_dynX + * \- cpu_clk_dynX_sel + * \- cpu_clk_dynX_div + * \- xtal/fclk_div2/fclk_div3 + * \- xtal/fclk_div2/fclk_div3 + */ + + udelay(100); + + return NOTIFY_OK; + + case POST_RATE_CHANGE: + /* + * The sys_pll has ben updated, now switch back cpu_clk to + * sys_pll + */ + + /* Configure cpu_clk to use sys_pll */ + clk_hw_set_parent(nb_data->cpu_clk, + nb_data->sys_pll); + + udelay(100); + + /* new path : + * cpu_clk + * \- sys_pll + * \- sys_pll_dco + */ + + return NOTIFY_OK; + + default: + return NOTIFY_DONE; + } +} + +static struct g12a_sys_pll_nb_data g12a_sys_pll_nb_data = { + .sys_pll = &g12a_sys_pll.hw, + .cpu_clk = &g12a_cpu_clk.hw, + .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw, + .nb.notifier_call = g12a_sys_pll_notifier_cb, +}; + +/* G12B first CPU cluster uses sys1_pll */ +static struct g12a_sys_pll_nb_data g12b_cpu_clk_sys1_pll_nb_data = { + .sys_pll = &g12b_sys1_pll.hw, + .cpu_clk = &g12b_cpu_clk.hw, + .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw, + .nb.notifier_call = g12a_sys_pll_notifier_cb, +}; + +/* G12B second CPU cluster uses sys_pll */ +static struct g12a_sys_pll_nb_data g12b_cpub_clk_sys_pll_nb_data = { + .sys_pll = &g12a_sys_pll.hw, + .cpu_clk = &g12b_cpub_clk.hw, + .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw, + .nb.notifier_call = g12a_sys_pll_notifier_cb, +}; + static struct clk_regmap g12a_cpu_clk_div16_en = { .data = &(struct clk_regmap_gate_data){ .offset = HHI_SYS_CPU_CLK_CNTL1, @@ -4097,28 +4342,210 @@ static const struct reg_sequence g12a_init_regs[] = { { .reg = HHI_MPLL_CNTL0, .def = 0x00000543 }, }; -static const struct meson_eeclkc_data g12a_clkc_data = { - .regmap_clks = g12a_clk_regmaps, - .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps), - .hw_onecell_data = &g12a_hw_onecell_data, - .init_regs = g12a_init_regs, - .init_count = ARRAY_SIZE(g12a_init_regs), -}; - -static const struct meson_eeclkc_data g12b_clkc_data = { - .regmap_clks = g12a_clk_regmaps, - .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps), - .hw_onecell_data = &g12b_hw_onecell_data +static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, + struct clk_hw **hws) +{ + const char *notifier_clk_name; + struct clk *notifier_clk; + struct clk_hw *xtal; + int ret; + + xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0); + + /* Setup clock notifier for cpu_clk_postmux0 */ + g12a_cpu_clk_postmux0_nb_data.xtal = xtal; + notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, + &g12a_cpu_clk_postmux0_nb_data.nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n"); + return ret; + } + + /* Setup clock notifier for cpu_clk_dyn mux */ + notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n"); + return ret; + } + + return 0; +} + +static int meson_g12b_dvfs_setup(struct platform_device *pdev) +{ + struct clk_hw **hws = g12b_hw_onecell_data.hws; + const char *notifier_clk_name; + struct clk *notifier_clk; + struct clk_hw *xtal; + int ret; + + ret = meson_g12a_dvfs_setup_common(pdev, hws); + if (ret) + return ret; + + xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0); + + /* Setup clock notifier for cpu_clk mux */ + notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + return ret; + } + + /* Setup clock notifier for sys1_pll */ + notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, + &g12b_cpu_clk_sys1_pll_nb_data.nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n"); + return ret; + } + + /* Add notifiers for the second CPU cluster */ + + /* Setup clock notifier for cpub_clk_postmux0 */ + g12b_cpub_clk_postmux0_nb_data.xtal = xtal; + notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, + &g12b_cpub_clk_postmux0_nb_data.nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n"); + return ret; + } + + /* Setup clock notifier for cpub_clk_dyn mux */ + notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n"); + return ret; + } + + /* Setup clock notifier for cpub_clk mux */ + notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n"); + return ret; + } + + /* Setup clock notifier for sys_pll */ + notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, + &g12b_cpub_clk_sys_pll_nb_data.nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + return ret; + } + + return 0; +} + +static int meson_g12a_dvfs_setup(struct platform_device *pdev) +{ + struct clk_hw **hws = g12a_hw_onecell_data.hws; + const char *notifier_clk_name; + struct clk *notifier_clk; + int ret; + + ret = meson_g12a_dvfs_setup_common(pdev, hws); + if (ret) + return ret; + + /* Setup clock notifier for cpu_clk mux */ + notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + return ret; + } + + /* Setup clock notifier for sys_pll */ + notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); + notifier_clk = __clk_lookup(notifier_clk_name); + ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb); + if (ret) { + dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + return ret; + } + + return 0; +} + +struct meson_g12a_data { + const struct meson_eeclkc_data eeclkc_data; + int (*dvfs_setup)(struct platform_device *pdev); +}; + +static int meson_g12a_probe(struct platform_device *pdev) +{ + const struct meson_eeclkc_data *eeclkc_data; + const struct meson_g12a_data *g12a_data; + int ret; + + eeclkc_data = of_device_get_match_data(&pdev->dev); + if (!eeclkc_data) + return -EINVAL; + + ret = meson_eeclkc_probe(pdev); + if (ret) + return ret; + + g12a_data = container_of(eeclkc_data, struct meson_g12a_data, + eeclkc_data); + + if (g12a_data->dvfs_setup) + return g12a_data->dvfs_setup(pdev); + + return 0; +} + +static const struct meson_g12a_data g12a_clkc_data = { + .eeclkc_data = { + .regmap_clks = g12a_clk_regmaps, + .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps), + .hw_onecell_data = &g12a_hw_onecell_data, + .init_regs = g12a_init_regs, + .init_count = ARRAY_SIZE(g12a_init_regs), + }, + .dvfs_setup = meson_g12a_dvfs_setup, +}; + +static const struct meson_g12a_data g12b_clkc_data = { + .eeclkc_data = { + .regmap_clks = g12a_clk_regmaps, + .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps), + .hw_onecell_data = &g12b_hw_onecell_data, + }, + .dvfs_setup = meson_g12b_dvfs_setup, }; static const struct of_device_id clkc_match_table[] = { - { .compatible = "amlogic,g12a-clkc", .data = &g12a_clkc_data }, - { .compatible = "amlogic,g12b-clkc", .data = &g12b_clkc_data }, + { + .compatible = "amlogic,g12a-clkc", + .data = &g12a_clkc_data.eeclkc_data + }, + { + .compatible = "amlogic,g12b-clkc", + .data = &g12b_clkc_data.eeclkc_data + }, {} }; static struct platform_driver g12a_driver = { - .probe = meson_eeclkc_probe, + .probe = meson_g12a_probe, .driver = { .name = "g12a-clkc", .of_match_table = clkc_match_table, -- GitLab From 85ab9d954698961960240622de4fad85c7d8a61e Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 10:40:19 +0200 Subject: [PATCH 2419/7155] clk: meson: g12a: expose CPUB clock ID for G12B Expose the CPUB clock id to add DVFS to the second CPU cluster of the Amlogic G12B SoC. Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a.h | 1 - include/dt-bindings/clock/g12a-clkc.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h index c8aed31fbe17..559a34cfdfeb 100644 --- a/drivers/clk/meson/g12a.h +++ b/drivers/clk/meson/g12a.h @@ -216,7 +216,6 @@ #define CLKID_CPUB_CLK_DYN1_DIV 221 #define CLKID_CPUB_CLK_DYN1 222 #define CLKID_CPUB_CLK_DYN 223 -#define CLKID_CPUB_CLK 224 #define CLKID_CPUB_CLK_DIV16_EN 225 #define CLKID_CPUB_CLK_DIV16 226 #define CLKID_CPUB_CLK_DIV2 227 diff --git a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h index b6b127e45634..8ccc29ac7a72 100644 --- a/include/dt-bindings/clock/g12a-clkc.h +++ b/include/dt-bindings/clock/g12a-clkc.h @@ -137,5 +137,6 @@ #define CLKID_VDEC_HEVC 207 #define CLKID_VDEC_HEVCF 210 #define CLKID_TS 212 +#define CLKID_CPUB_CLK 224 #endif /* __G12A_CLKC_H */ -- GitLab From 9cb1c5ddd2c432834dd4f40c0170d6b639e8e5c3 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:13 +0100 Subject: [PATCH 2420/7155] arm64: mm: Remove bit-masking optimisations for PAGE_OFFSET and VMEMMAP_START Currently there are assumptions about the alignment of VMEMMAP_START and PAGE_OFFSET that won't be valid after this series is applied. These assumptions are in the form of bitwise operators being used instead of addition and subtraction when calculating addresses. This patch replaces these bitwise operators with addition/subtraction. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index fb04f10a78ab..98fda92a2612 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -299,21 +299,20 @@ static inline void *phys_to_virt(phys_addr_t x) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #else -#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) -#define __page_to_voff(kaddr) (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) +#define __virt_to_pgoff(kaddr) (((u64)(kaddr) - PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) +#define __page_to_voff(kaddr) (((u64)(kaddr) - VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) #define page_to_virt(page) ({ \ unsigned long __addr = \ - ((__page_to_voff(page)) | PAGE_OFFSET); \ + ((__page_to_voff(page)) + PAGE_OFFSET); \ const void *__addr_tag = \ __tag_set((void *)__addr, page_kasan_tag(page)); \ ((void *)__addr_tag); \ }) -#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START)) +#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) + VMEMMAP_START)) -#define _virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \ - + PHYS_OFFSET) >> PAGE_SHIFT) +#define _virt_addr_valid(kaddr) pfn_valid(__virt_to_phys((u64)(kaddr)) >> PAGE_SHIFT) #endif #endif -- GitLab From 14c127c957c1c6070647c171e72f06e0db275ebf Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:14 +0100 Subject: [PATCH 2421/7155] arm64: mm: Flip kernel VA space In order to allow for a KASAN shadow that changes size at boot time, one must fix the KASAN_SHADOW_END for both 48 & 52-bit VAs and "grow" the start address. Also, it is highly desirable to maintain the same function addresses in the kernel .text between VA sizes. Both of these requirements necessitate us to flip the kernel address space halves s.t. the direct linear map occupies the lower addresses. This patch puts the direct linear map in the lower addresses of the kernel VA range and everything else in the higher ranges. We need to adjust: *) KASAN shadow region placement logic, *) KASAN_SHADOW_OFFSET computation logic, *) virt_to_phys, phys_to_virt checks, *) page table dumper. These are all small changes, that need to take place atomically, so they are bundled into this commit. As part of the re-arrangement, a guard region of 2MB (to preserve alignment for fixed map) is added after the vmemmap. Otherwise the vmemmap could intersect with IS_ERR pointers. Reviewed-by: Catalin Marinas Signed-off-by: Steve Capper Signed-off-by: Will Deacon --- arch/arm64/Makefile | 2 +- arch/arm64/include/asm/memory.h | 8 ++++---- arch/arm64/include/asm/pgtable.h | 2 +- arch/arm64/kernel/hibernate.c | 2 +- arch/arm64/mm/dump.c | 5 +++-- arch/arm64/mm/init.c | 9 +-------- arch/arm64/mm/kasan_init.c | 6 +++--- arch/arm64/mm/mmu.c | 4 ++-- 8 files changed, 16 insertions(+), 22 deletions(-) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 61de992bbea3..61f7926fdeca 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -130,7 +130,7 @@ KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) # - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT)) # in 32-bit arithmetic KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \ - (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \ + (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 1 - 32))) \ + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \ - (1 << (64 - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) )) ) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 98fda92a2612..380594b1a0ba 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -38,9 +38,9 @@ */ #define VA_BITS (CONFIG_ARM64_VA_BITS) #define VA_START (UL(0xffffffffffffffff) - \ - (UL(1) << VA_BITS) + 1) -#define PAGE_OFFSET (UL(0xffffffffffffffff) - \ (UL(1) << (VA_BITS - 1)) + 1) +#define PAGE_OFFSET (UL(0xffffffffffffffff) - \ + (UL(1) << VA_BITS) + 1) #define KIMAGE_VADDR (MODULES_END) #define BPF_JIT_REGION_START (VA_START + KASAN_SHADOW_SIZE) #define BPF_JIT_REGION_SIZE (SZ_128M) @@ -48,7 +48,7 @@ #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) #define MODULES_VADDR (BPF_JIT_REGION_END) #define MODULES_VSIZE (SZ_128M) -#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE) +#define VMEMMAP_START (-VMEMMAP_SIZE - SZ_2M) #define PCI_IO_END (VMEMMAP_START - SZ_2M) #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) #define FIXADDR_TOP (PCI_IO_START - SZ_2M) @@ -231,7 +231,7 @@ static inline const void *__tag_set(const void *addr, u8 tag) * space. Testing the top bit for the start of the region is a * sufficient check. */ -#define __is_lm_address(addr) (!!((addr) & BIT(VA_BITS - 1))) +#define __is_lm_address(addr) (!((addr) & BIT(VA_BITS - 1))) #define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) #define __kimg_to_phys(addr) ((addr) - kimage_voffset) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 5fdcfe237338..046b811309bb 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -21,7 +21,7 @@ * and fixed mappings */ #define VMALLOC_START (MODULES_END) -#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) +#define VMALLOC_END (- PUD_SIZE - VMEMMAP_SIZE - SZ_64K) #define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 9341fcc6e809..e130db05d932 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -496,7 +496,7 @@ int swsusp_arch_resume(void) rc = -ENOMEM; goto out; } - rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0); + rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, VA_START); if (rc) goto out; diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index 82b3a7fdb4a6..beec87488e97 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -26,6 +26,8 @@ #include static const struct addr_marker address_markers[] = { + { PAGE_OFFSET, "Linear Mapping start" }, + { VA_START, "Linear Mapping end" }, #ifdef CONFIG_KASAN { KASAN_SHADOW_START, "Kasan shadow start" }, { KASAN_SHADOW_END, "Kasan shadow end" }, @@ -42,7 +44,6 @@ static const struct addr_marker address_markers[] = { { VMEMMAP_START, "vmemmap start" }, { VMEMMAP_START + VMEMMAP_SIZE, "vmemmap end" }, #endif - { PAGE_OFFSET, "Linear mapping" }, { -1, NULL }, }; @@ -376,7 +377,7 @@ static void ptdump_initialize(void) static struct ptdump_info kernel_ptdump_info = { .mm = &init_mm, .markers = address_markers, - .base_addr = VA_START, + .base_addr = PAGE_OFFSET, }; void ptdump_check_wx(void) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f3c795278def..62927ed02229 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -301,7 +301,7 @@ static void __init fdt_enforce_memory_region(void) void __init arm64_memblock_init(void) { - const s64 linear_region_size = -(s64)PAGE_OFFSET; + const s64 linear_region_size = BIT(VA_BITS - 1); /* Handle linux,usable-memory-range property */ fdt_enforce_memory_region(); @@ -309,13 +309,6 @@ void __init arm64_memblock_init(void) /* Remove memory above our supported physical address size */ memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); - /* - * Ensure that the linear region takes up exactly half of the kernel - * virtual address space. This way, we can distinguish a linear address - * from a kernel/module/vmalloc address by testing a single bit. - */ - BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1)); - /* * Select a suitable value for the base of physical memory. */ diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index 6cf97b904ebb..05edfe9b02e4 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -225,10 +225,10 @@ void __init kasan_init(void) kasan_map_populate(kimg_shadow_start, kimg_shadow_end, early_pfn_to_nid(virt_to_pfn(lm_alias(_text)))); - kasan_populate_early_shadow((void *)KASAN_SHADOW_START, - (void *)mod_shadow_start); + kasan_populate_early_shadow(kasan_mem_to_shadow((void *) VA_START), + (void *)mod_shadow_start); kasan_populate_early_shadow((void *)kimg_shadow_end, - kasan_mem_to_shadow((void *)PAGE_OFFSET)); + (void *)KASAN_SHADOW_END); if (kimg_shadow_start > mod_shadow_end) kasan_populate_early_shadow((void *)mod_shadow_end, diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 750a69dde39b..1d4247f9a496 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -398,7 +398,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift) static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot) { - if (virt < VMALLOC_START) { + if ((virt >= VA_START) && (virt < VMALLOC_START)) { pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", &phys, virt); return; @@ -425,7 +425,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, static void update_mapping_prot(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot) { - if (virt < VMALLOC_START) { + if ((virt >= VA_START) && (virt < VMALLOC_START)) { pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", &phys, virt); return; -- GitLab From 6bd1d0be0e97936d15cdacc71f5c232fbf71293e Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:15 +0100 Subject: [PATCH 2422/7155] arm64: kasan: Switch to using KASAN_SHADOW_OFFSET KASAN_SHADOW_OFFSET is a constant that is supplied to gcc as a command line argument and affects the codegen of the inline address sanetiser. Essentially, for an example memory access: *ptr1 = val; The compiler will insert logic similar to the below: shadowValue = *(ptr1 >> KASAN_SHADOW_SCALE_SHIFT + KASAN_SHADOW_OFFSET) if (somethingWrong(shadowValue)) flagAnError(); This code sequence is inserted into many places, thus KASAN_SHADOW_OFFSET is essentially baked into many places in the kernel text. If we want to run a single kernel binary with multiple address spaces, then we need to do this with KASAN_SHADOW_OFFSET fixed. Thankfully, due to the way the KASAN_SHADOW_OFFSET is used to provide shadow addresses we know that the end of the shadow region is constant w.r.t. VA space size: KASAN_SHADOW_END = ~0 >> KASAN_SHADOW_SCALE_SHIFT + KASAN_SHADOW_OFFSET This means that if we increase the size of the VA space, the start of the KASAN region expands into lower addresses whilst the end of the KASAN region is fixed. Currently the arm64 code computes KASAN_SHADOW_OFFSET at build time via build scripts with the VA size used as a parameter. (There are build time checks in the C code too to ensure that expected values are being derived). It is sufficient, and indeed is a simplification, to remove the build scripts (and build time checks) entirely and instead provide KASAN_SHADOW_OFFSET values. This patch removes the logic to compute the KASAN_SHADOW_OFFSET in the arm64 Makefile, and instead we adopt the approach used by x86 to supply offset values in kConfig. To help debug/develop future VA space changes, the Makefile logic has been preserved in a script file in the arm64 Documentation folder. Reviewed-by: Catalin Marinas Signed-off-by: Steve Capper Signed-off-by: Will Deacon --- Documentation/arm64/kasan-offsets.sh | 27 +++++++++++++++++++++++++++ arch/arm64/Kconfig | 15 +++++++++++++++ arch/arm64/Makefile | 8 -------- arch/arm64/include/asm/kasan.h | 11 ++++------- arch/arm64/include/asm/memory.h | 8 +++++--- 5 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 Documentation/arm64/kasan-offsets.sh diff --git a/Documentation/arm64/kasan-offsets.sh b/Documentation/arm64/kasan-offsets.sh new file mode 100644 index 000000000000..2b7a021db363 --- /dev/null +++ b/Documentation/arm64/kasan-offsets.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Print out the KASAN_SHADOW_OFFSETS required to place the KASAN SHADOW +# start address at the mid-point of the kernel VA space + +print_kasan_offset () { + printf "%02d\t" $1 + printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \ + + (1 << ($1 - 32 - $2)) \ + - (1 << (64 - 32 - $2)) )) +} + +echo KASAN_SHADOW_SCALE_SHIFT = 3 +printf "VABITS\tKASAN_SHADOW_OFFSET\n" +print_kasan_offset 48 3 +print_kasan_offset 47 3 +print_kasan_offset 42 3 +print_kasan_offset 39 3 +print_kasan_offset 36 3 +echo +echo KASAN_SHADOW_SCALE_SHIFT = 4 +printf "VABITS\tKASAN_SHADOW_OFFSET\n" +print_kasan_offset 48 4 +print_kasan_offset 47 4 +print_kasan_offset 42 4 +print_kasan_offset 39 4 +print_kasan_offset 36 4 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3adcec05b1f6..f7f23e47c28f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -297,6 +297,21 @@ config ARCH_SUPPORTS_UPROBES config ARCH_PROC_KCORE_TEXT def_bool y +config KASAN_SHADOW_OFFSET + hex + depends on KASAN + default 0xdfffa00000000000 if (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) && !KASAN_SW_TAGS + default 0xdfffd00000000000 if ARM64_VA_BITS_47 && !KASAN_SW_TAGS + default 0xdffffe8000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS + default 0xdfffffd000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS + default 0xdffffffa00000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS + default 0xefff900000000000 if (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) && KASAN_SW_TAGS + default 0xefffc80000000000 if ARM64_VA_BITS_47 && KASAN_SW_TAGS + default 0xeffffe4000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS + default 0xefffffc800000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS + default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS + default 0xffffffffffffffff + source "arch/arm64/Kconfig.platforms" menu "Kernel Features" diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 61f7926fdeca..a8d2a241ac58 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -126,14 +126,6 @@ KBUILD_CFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) -# KASAN_SHADOW_OFFSET = VA_START + (1 << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT)) -# - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT)) -# in 32-bit arithmetic -KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \ - (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 1 - 32))) \ - + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \ - - (1 << (64 - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) )) ) - export TEXT_OFFSET GZFLAGS core-y += arch/arm64/kernel/ arch/arm64/mm/ diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h index b52aacd2c526..10d2add842da 100644 --- a/arch/arm64/include/asm/kasan.h +++ b/arch/arm64/include/asm/kasan.h @@ -18,11 +18,8 @@ * KASAN_SHADOW_START: beginning of the kernel virtual addresses. * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/N of kernel virtual addresses, * where N = (1 << KASAN_SHADOW_SCALE_SHIFT). - */ -#define KASAN_SHADOW_START (VA_START) -#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE) - -/* + * + * KASAN_SHADOW_OFFSET: * This value is used to map an address to the corresponding shadow * address by the following formula: * shadow_addr = (address >> KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET @@ -33,8 +30,8 @@ * KASAN_SHADOW_OFFSET = KASAN_SHADOW_END - * (1ULL << (64 - KASAN_SHADOW_SCALE_SHIFT)) */ -#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << \ - (64 - KASAN_SHADOW_SCALE_SHIFT))) +#define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (1UL << ((va) - KASAN_SHADOW_SCALE_SHIFT))) +#define KASAN_SHADOW_START _KASAN_SHADOW_START(VA_BITS) void kasan_init(void); void kasan_copy_shadow(pgd_t *pgdir); diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 380594b1a0ba..968659c90f5c 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -42,7 +42,7 @@ #define PAGE_OFFSET (UL(0xffffffffffffffff) - \ (UL(1) << VA_BITS) + 1) #define KIMAGE_VADDR (MODULES_END) -#define BPF_JIT_REGION_START (VA_START + KASAN_SHADOW_SIZE) +#define BPF_JIT_REGION_START (KASAN_SHADOW_END) #define BPF_JIT_REGION_SIZE (SZ_128M) #define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE) #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) @@ -68,11 +68,13 @@ * significantly, so double the (minimum) stack size when they are in use. */ #ifdef CONFIG_KASAN -#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT)) +#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL) +#define KASAN_SHADOW_END ((UL(1) << (64 - KASAN_SHADOW_SCALE_SHIFT)) \ + + KASAN_SHADOW_OFFSET) #define KASAN_THREAD_SHIFT 1 #else -#define KASAN_SHADOW_SIZE (0) #define KASAN_THREAD_SHIFT 0 +#define KASAN_SHADOW_END (VA_START) #endif #define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT) -- GitLab From 99426e5e8c9f11b9de65e7c1200868e8a9ceaa47 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:16 +0100 Subject: [PATCH 2423/7155] arm64: dump: De-constify VA_START and KASAN_SHADOW_START The kernel page table dumper assumes that the placement of VA regions is constant and determined at compile time. As we are about to introduce variable VA logic, we need to be able to determine certain regions at boot time. Specifically the VA_START and KASAN_SHADOW_START will depend on whether or not the system is booted with 52-bit kernel VAs. This patch adds logic to the kernel page table dumper s.t. these regions can be computed at boot time. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/mm/dump.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index beec87488e97..6ec75305828e 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -25,11 +25,20 @@ #include #include -static const struct addr_marker address_markers[] = { + +enum address_markers_idx { + PAGE_OFFSET_NR = 0, + VA_START_NR, +#ifdef CONFIG_KASAN + KASAN_START_NR, +#endif +}; + +static struct addr_marker address_markers[] = { { PAGE_OFFSET, "Linear Mapping start" }, - { VA_START, "Linear Mapping end" }, + { 0 /* VA_START */, "Linear Mapping end" }, #ifdef CONFIG_KASAN - { KASAN_SHADOW_START, "Kasan shadow start" }, + { 0 /* KASAN_SHADOW_START */, "Kasan shadow start" }, { KASAN_SHADOW_END, "Kasan shadow end" }, #endif { MODULES_VADDR, "Modules start" }, @@ -402,6 +411,10 @@ void ptdump_check_wx(void) static int ptdump_init(void) { + address_markers[VA_START_NR].start_address = VA_START; +#ifdef CONFIG_KASAN + address_markers[KASAN_START_NR].start_address = KASAN_SHADOW_START; +#endif ptdump_initialize(); ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables"); return 0; -- GitLab From 90ec95cda91a021d82351c976896a63aa364ebf1 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:17 +0100 Subject: [PATCH 2424/7155] arm64: mm: Introduce VA_BITS_MIN In order to support 52-bit kernel addresses detectable at boot time, the kernel needs to know the most conservative VA_BITS possible should it need to fall back to this quantity due to lack of hardware support. A new compile time constant VA_BITS_MIN is introduced in this patch and it is employed in the KASAN end address, KASLR, and EFI stub. For Arm, if 52-bit VA support is unavailable the fallback is to 48-bits. In other words: VA_BITS_MIN = min (48, VA_BITS) Reviewed-by: Catalin Marinas Signed-off-by: Steve Capper Signed-off-by: Will Deacon --- arch/arm64/include/asm/efi.h | 4 ++-- arch/arm64/include/asm/memory.h | 9 ++++++++- arch/arm64/include/asm/processor.h | 2 +- arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/kaslr.c | 6 +++--- arch/arm64/mm/kasan_init.c | 3 ++- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 76a144702586..b54d3a86c444 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -79,7 +79,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) /* * On arm64, we have to ensure that the initrd ends up in the linear region, - * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is + * which is a 1 GB aligned region of size '1UL << (VA_BITS_MIN - 1)' that is * guaranteed to cover the kernel Image. * * Since the EFI stub is part of the kernel Image, we can relax the @@ -90,7 +90,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, unsigned long image_addr) { - return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1)); + return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1)); } #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 968659c90f5c..79e75e45d560 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -52,6 +52,13 @@ #define PCI_IO_END (VMEMMAP_START - SZ_2M) #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) #define FIXADDR_TOP (PCI_IO_START - SZ_2M) +#if VA_BITS > 48 +#define VA_BITS_MIN (48) +#else +#define VA_BITS_MIN (VA_BITS) +#endif +#define _VA_START(va) (UL(0xffffffffffffffff) - \ + (UL(1) << ((va) - 1)) + 1) #define KERNEL_START _text #define KERNEL_END _end @@ -74,7 +81,7 @@ #define KASAN_THREAD_SHIFT 1 #else #define KASAN_THREAD_SHIFT 0 -#define KASAN_SHADOW_END (VA_START) +#define KASAN_SHADOW_END (_VA_START(VA_BITS_MIN)) #endif #define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 844e2964b0f5..0e1f2770192a 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -42,7 +42,7 @@ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. */ -#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS) +#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS_MIN) #define TASK_SIZE_64 (UL(1) << vabits_user) #ifdef CONFIG_COMPAT diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 2cdacd1c141b..ac58c69993ec 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -314,7 +314,7 @@ __create_page_tables: mov x5, #52 cbnz x6, 1f #endif - mov x5, #VA_BITS + mov x5, #VA_BITS_MIN 1: adr_l x6, vabits_user str x5, [x6] diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index 708051655ad9..5a59f7567f9c 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -116,15 +116,15 @@ u64 __init kaslr_early_init(u64 dt_phys) /* * OK, so we are proceeding with KASLR enabled. Calculate a suitable * kernel image offset from the seed. Let's place the kernel in the - * middle half of the VMALLOC area (VA_BITS - 2), and stay clear of + * middle half of the VMALLOC area (VA_BITS_MIN - 2), and stay clear of * the lower and upper quarters to avoid colliding with other * allocations. * Even if we could randomize at page granularity for 16k and 64k pages, * let's always round to 2 MB so we don't interfere with the ability to * map using contiguous PTEs */ - mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1); - offset = BIT(VA_BITS - 3) + (seed & mask); + mask = ((1UL << (VA_BITS_MIN - 2)) - 1) & ~(SZ_2M - 1); + offset = BIT(VA_BITS_MIN - 3) + (seed & mask); /* use the top 16 bits to randomize the linear region */ memstart_offset_seed = seed >> 48; diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index 05edfe9b02e4..725222271474 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -156,7 +156,8 @@ asmlinkage void __init kasan_early_init(void) { BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); - BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS), PGDIR_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS_MIN), PGDIR_SIZE)); BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE, true); -- GitLab From 5383cc6efed13784ddb3cff2cc183b6b8c50c8db Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:18 +0100 Subject: [PATCH 2425/7155] arm64: mm: Introduce vabits_actual In order to support 52-bit kernel addresses detectable at boot time, one needs to know the actual VA_BITS detected. A new variable vabits_actual is introduced in this commit and employed for the KVM hypervisor layout, KASAN, fault handling and phys-to/from-virt translation where there would normally be compile time constants. In order to maintain performance in phys_to_virt, another variable physvirt_offset is introduced. Reviewed-by: Catalin Marinas Signed-off-by: Steve Capper Signed-off-by: Will Deacon --- arch/arm64/include/asm/kasan.h | 2 +- arch/arm64/include/asm/memory.h | 11 ++++++----- arch/arm64/include/asm/mmu_context.h | 2 +- arch/arm64/kernel/head.S | 5 +++++ arch/arm64/kvm/va_layout.c | 14 +++++++------- arch/arm64/mm/fault.c | 4 ++-- arch/arm64/mm/init.c | 7 ++++++- arch/arm64/mm/mmu.c | 3 +++ 8 files changed, 31 insertions(+), 17 deletions(-) diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h index 10d2add842da..b0dc4abc3589 100644 --- a/arch/arm64/include/asm/kasan.h +++ b/arch/arm64/include/asm/kasan.h @@ -31,7 +31,7 @@ * (1ULL << (64 - KASAN_SHADOW_SCALE_SHIFT)) */ #define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (1UL << ((va) - KASAN_SHADOW_SCALE_SHIFT))) -#define KASAN_SHADOW_START _KASAN_SHADOW_START(VA_BITS) +#define KASAN_SHADOW_START _KASAN_SHADOW_START(vabits_actual) void kasan_init(void); void kasan_copy_shadow(pgd_t *pgdir); diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 79e75e45d560..364635b8370a 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -37,8 +37,6 @@ * VA_START - the first kernel virtual address. */ #define VA_BITS (CONFIG_ARM64_VA_BITS) -#define VA_START (UL(0xffffffffffffffff) - \ - (UL(1) << (VA_BITS - 1)) + 1) #define PAGE_OFFSET (UL(0xffffffffffffffff) - \ (UL(1) << VA_BITS) + 1) #define KIMAGE_VADDR (MODULES_END) @@ -166,10 +164,13 @@ #endif #ifndef __ASSEMBLY__ +extern u64 vabits_actual; +#define VA_START (_VA_START(vabits_actual)) #include #include +extern s64 physvirt_offset; extern s64 memstart_addr; /* PHYS_OFFSET - the physical address of the start of memory. */ #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) @@ -240,9 +241,9 @@ static inline const void *__tag_set(const void *addr, u8 tag) * space. Testing the top bit for the start of the region is a * sufficient check. */ -#define __is_lm_address(addr) (!((addr) & BIT(VA_BITS - 1))) +#define __is_lm_address(addr) (!((addr) & BIT(vabits_actual - 1))) -#define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) +#define __lm_to_phys(addr) (((addr) + physvirt_offset)) #define __kimg_to_phys(addr) ((addr) - kimage_voffset) #define __virt_to_phys_nodebug(x) ({ \ @@ -261,7 +262,7 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x); #define __phys_addr_symbol(x) __pa_symbol_nodebug(x) #endif -#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) +#define __phys_to_virt(x) ((unsigned long)((x) - physvirt_offset)) #define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset)) /* diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 7ed0adb187a8..670003a55d28 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -95,7 +95,7 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) isb(); } -#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS)) +#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual)) #define cpu_set_idmap_tcr_t0sz() __cpu_set_tcr_t0sz(idmap_t0sz) /* diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index ac58c69993ec..6dc7349868d9 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -321,6 +321,11 @@ __create_page_tables: dmb sy dc ivac, x6 // Invalidate potentially stale cache line + adr_l x6, vabits_actual + str x5, [x6] + dmb sy + dc ivac, x6 // Invalidate potentially stale cache line + /* * VA_BITS may be too small to allow for an ID mapping to be created * that covers system RAM if that is located sufficiently high in the diff --git a/arch/arm64/kvm/va_layout.c b/arch/arm64/kvm/va_layout.c index acd8084f1f2c..2cf7d4b606c3 100644 --- a/arch/arm64/kvm/va_layout.c +++ b/arch/arm64/kvm/va_layout.c @@ -29,25 +29,25 @@ static void compute_layout(void) int kva_msb; /* Where is my RAM region? */ - hyp_va_msb = idmap_addr & BIT(VA_BITS - 1); - hyp_va_msb ^= BIT(VA_BITS - 1); + hyp_va_msb = idmap_addr & BIT(vabits_actual - 1); + hyp_va_msb ^= BIT(vabits_actual - 1); kva_msb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^ (u64)(high_memory - 1)); - if (kva_msb == (VA_BITS - 1)) { + if (kva_msb == (vabits_actual - 1)) { /* * No space in the address, let's compute the mask so - * that it covers (VA_BITS - 1) bits, and the region + * that it covers (vabits_actual - 1) bits, and the region * bit. The tag stays set to zero. */ - va_mask = BIT(VA_BITS - 1) - 1; + va_mask = BIT(vabits_actual - 1) - 1; va_mask |= hyp_va_msb; } else { /* * We do have some free bits to insert a random tag. * Hyp VAs are now created from kernel linear map VAs - * using the following formula (with V == VA_BITS): + * using the following formula (with V == vabits_actual): * * 63 ... V | V-1 | V-2 .. tag_lsb | tag_lsb - 1 .. 0 * --------------------------------------------------------- @@ -55,7 +55,7 @@ static void compute_layout(void) */ tag_lsb = kva_msb; va_mask = GENMASK_ULL(tag_lsb - 1, 0); - tag_val = get_random_long() & GENMASK_ULL(VA_BITS - 2, tag_lsb); + tag_val = get_random_long() & GENMASK_ULL(vabits_actual - 2, tag_lsb); tag_val |= hyp_va_msb; tag_val >>= tag_lsb; } diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index cfd65b63f36f..6b195871769a 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -138,9 +138,9 @@ static void show_pte(unsigned long addr) return; } - pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp=%016lx\n", + pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n", mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, - mm == &init_mm ? VA_BITS : (int)vabits_user, + mm == &init_mm ? vabits_actual : (int)vabits_user, (unsigned long)virt_to_phys(mm->pgd)); pgdp = pgd_offset(mm, addr); pgd = READ_ONCE(*pgdp); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 62927ed02229..e752f46d430e 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -50,6 +50,9 @@ s64 memstart_addr __ro_after_init = -1; EXPORT_SYMBOL(memstart_addr); +s64 physvirt_offset __ro_after_init; +EXPORT_SYMBOL(physvirt_offset); + phys_addr_t arm64_dma_phys_limit __ro_after_init; #ifdef CONFIG_KEXEC_CORE @@ -301,7 +304,7 @@ static void __init fdt_enforce_memory_region(void) void __init arm64_memblock_init(void) { - const s64 linear_region_size = BIT(VA_BITS - 1); + const s64 linear_region_size = BIT(vabits_actual - 1); /* Handle linux,usable-memory-range property */ fdt_enforce_memory_region(); @@ -315,6 +318,8 @@ void __init arm64_memblock_init(void) memstart_addr = round_down(memblock_start_of_DRAM(), ARM64_MEMSTART_ALIGN); + physvirt_offset = PHYS_OFFSET - PAGE_OFFSET; + /* * Remove the memory that we will not be able to cover with the * linear mapping. Take care not to clip the kernel which may be diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 1d4247f9a496..07b30e6d17f8 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -43,6 +43,9 @@ u64 idmap_ptrs_per_pgd = PTRS_PER_PGD; u64 vabits_user __ro_after_init; EXPORT_SYMBOL(vabits_user); +u64 __section(".mmuoff.data.write") vabits_actual; +EXPORT_SYMBOL(vabits_actual); + u64 kimage_voffset __ro_after_init; EXPORT_SYMBOL(kimage_voffset); -- GitLab From c812026c54cfaec23fa1d78cdbfd0e56e787470a Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:19 +0100 Subject: [PATCH 2426/7155] arm64: mm: Logic to make offset_ttbr1 conditional When running with a 52-bit userspace VA and a 48-bit kernel VA we offset ttbr1_el1 to allow the kernel pagetables with a 52-bit PTRS_PER_PGD to be used for both userspace and kernel. Moving on to a 52-bit kernel VA we no longer require this offset to ttbr1_el1 should we be running on a system with HW support for 52-bit VAs. This patch introduces conditional logic to offset_ttbr1 to query SYS_ID_AA64MMFR2_EL1 whenever 52-bit VAs are selected. If there is HW support for 52-bit VAs then the ttbr1 offset is skipped. We choose to read a system register rather than vabits_actual because offset_ttbr1 can be called in places where the kernel data is not actually mapped. Calls to offset_ttbr1 appear to be made from rarely called code paths so this extra logic is not expected to adversely affect performance. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/include/asm/assembler.h | 12 ++++++++++-- arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/hibernate-asm.S | 8 ++++---- arch/arm64/mm/proc.S | 6 +++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index e3a15c751b13..ede368bafa2c 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -538,9 +538,17 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU * In future this may be nop'ed out when dealing with 52-bit kernel VAs. * ttbr: Value of ttbr to set, modified. */ - .macro offset_ttbr1, ttbr + .macro offset_ttbr1, ttbr, tmp #ifdef CONFIG_ARM64_USER_VA_BITS_52 orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET +#endif + +#ifdef CONFIG_ARM64_VA_BITS_52 + mrs_s \tmp, SYS_ID_AA64MMFR2_EL1 + and \tmp, \tmp, #(0xf << ID_AA64MMFR2_LVA_SHIFT) + cbnz \tmp, .Lskipoffs_\@ + orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET +.Lskipoffs_\@ : #endif .endm @@ -550,7 +558,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU * to be nop'ed out when dealing with 52-bit kernel VAs. */ .macro restore_ttbr1, ttbr -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#if defined(CONFIG_ARM64_USER_VA_BITS_52) || defined(CONFIG_ARM64_VA_BITS_52) bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET #endif .endm diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 6dc7349868d9..a96dc4386c7c 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -777,7 +777,7 @@ ENTRY(__enable_mmu) phys_to_ttbr x1, x1 phys_to_ttbr x2, x2 msr ttbr0_el1, x2 // load TTBR0 - offset_ttbr1 x1 + offset_ttbr1 x1, x3 msr ttbr1_el1, x1 // load TTBR1 isb msr sctlr_el1, x0 diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S index 2f4a2ce7264b..38bcd4d4e43b 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -22,14 +22,14 @@ * Even switching to our copied tables will cause a changed output address at * each stage of the walk. */ -.macro break_before_make_ttbr_switch zero_page, page_table, tmp +.macro break_before_make_ttbr_switch zero_page, page_table, tmp, tmp2 phys_to_ttbr \tmp, \zero_page msr ttbr1_el1, \tmp isb tlbi vmalle1 dsb nsh phys_to_ttbr \tmp, \page_table - offset_ttbr1 \tmp + offset_ttbr1 \tmp, \tmp2 msr ttbr1_el1, \tmp isb .endm @@ -70,7 +70,7 @@ ENTRY(swsusp_arch_suspend_exit) * We execute from ttbr0, change ttbr1 to our copied linear map tables * with a break-before-make via the zero page */ - break_before_make_ttbr_switch x5, x0, x6 + break_before_make_ttbr_switch x5, x0, x6, x8 mov x21, x1 mov x30, x2 @@ -101,7 +101,7 @@ ENTRY(swsusp_arch_suspend_exit) dsb ish /* wait for PoU cleaning to finish */ /* switch to the restored kernels page tables */ - break_before_make_ttbr_switch x25, x21, x6 + break_before_make_ttbr_switch x25, x21, x6, x8 ic ialluis dsb ish diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 7dbf2be470f6..8d289ff7584d 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -168,7 +168,7 @@ ENDPROC(cpu_do_switch_mm) .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 adrp \tmp1, empty_zero_page phys_to_ttbr \tmp2, \tmp1 - offset_ttbr1 \tmp2 + offset_ttbr1 \tmp2, \tmp1 msr ttbr1_el1, \tmp2 isb tlbi vmalle1 @@ -187,7 +187,7 @@ ENTRY(idmap_cpu_replace_ttbr1) __idmap_cpu_set_reserved_ttbr1 x1, x3 - offset_ttbr1 x0 + offset_ttbr1 x0, x3 msr ttbr1_el1, x0 isb @@ -362,7 +362,7 @@ __idmap_kpti_secondary: cbnz w18, 1b /* All done, act like nothing happened */ - offset_ttbr1 swapper_ttb + offset_ttbr1 swapper_ttb, x18 msr ttbr1_el1, swapper_ttb isb ret -- GitLab From c8b6d2ccf9b10ce872cdea037f9685804440bb7e Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:20 +0100 Subject: [PATCH 2427/7155] arm64: mm: Separate out vmemmap vmemmap is a preprocessor definition that depends on a variable, memstart_addr. In a later patch we will need to expand the size of the VMEMMAP region and optionally modify vmemmap depending upon whether or not hardware support is available for 52-bit virtual addresses. This patch changes vmemmap to be a variable. As the old definition depended on a variable load, this should not affect performance noticeably. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/include/asm/pgtable.h | 4 ++-- arch/arm64/mm/init.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 046b811309bb..4a695b9ee0f0 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -23,8 +23,6 @@ #define VMALLOC_START (MODULES_END) #define VMALLOC_END (- PUD_SIZE - VMEMMAP_SIZE - SZ_64K) -#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) - #define FIRST_USER_ADDRESS 0UL #ifndef __ASSEMBLY__ @@ -35,6 +33,8 @@ #include #include +extern struct page *vmemmap; + extern void __pte_error(const char *file, int line, unsigned long val); extern void __pmd_error(const char *file, int line, unsigned long val); extern void __pud_error(const char *file, int line, unsigned long val); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index e752f46d430e..2940221e5519 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -53,6 +53,9 @@ EXPORT_SYMBOL(memstart_addr); s64 physvirt_offset __ro_after_init; EXPORT_SYMBOL(physvirt_offset); +struct page *vmemmap __ro_after_init; +EXPORT_SYMBOL(vmemmap); + phys_addr_t arm64_dma_phys_limit __ro_after_init; #ifdef CONFIG_KEXEC_CORE @@ -320,6 +323,8 @@ void __init arm64_memblock_init(void) physvirt_offset = PHYS_OFFSET - PAGE_OFFSET; + vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)); + /* * Remove the memory that we will not be able to cover with the * linear mapping. Take care not to clip the kernel which may be -- GitLab From ce3aaed87344c83c77135f80e7b76e1da9c92ee6 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:21 +0100 Subject: [PATCH 2428/7155] arm64: mm: Modify calculation of VMEMMAP_SIZE In a later patch we will need to have a slightly larger VMEMMAP region to accommodate boot time selection between 48/52-bit kernel VAs. This patch modifies the formula for computing VMEMMAP_SIZE to depend explicitly on the PAGE_OFFSET and start of kernel addressable memory. (This allows for a slightly larger direct linear map in future). Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 364635b8370a..0204c2006c92 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -26,8 +26,15 @@ /* * VMEMMAP_SIZE - allows the whole linear region to be covered by * a struct page array + * + * If we are configured with a 52-bit kernel VA then our VMEMMAP_SIZE + * neads to cover the memory region from the beginning of the 52-bit + * PAGE_OFFSET all the way to VA_START for 48-bit. This allows us to + * keep a constant PAGE_OFFSET and "fallback" to using the higher end + * of the VMEMMAP where 52-bit support is not available in hardware. */ -#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)) +#define VMEMMAP_SIZE ((_VA_START(VA_BITS_MIN) - PAGE_OFFSET) \ + >> (PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT)) /* * PAGE_OFFSET - the virtual address of the start of the linear map (top -- GitLab From b6d00d47e81a49f6cf462518c10408f37a3e6785 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:22 +0100 Subject: [PATCH 2429/7155] arm64: mm: Introduce 52-bit Kernel VAs Most of the machinery is now in place to enable 52-bit kernel VAs that are detectable at boot time. This patch adds a Kconfig option for 52-bit user and kernel addresses and plumbs in the requisite CONFIG_ macros as well as sets TCR.T1SZ, physvirt_offset and vmemmap at early boot. To simplify things this patch also removes the 52-bit user/48-bit kernel kconfig option. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 20 +++++++++++--------- arch/arm64/include/asm/assembler.h | 13 ++++++++----- arch/arm64/include/asm/memory.h | 7 ++++--- arch/arm64/include/asm/mmu_context.h | 2 +- arch/arm64/include/asm/pgtable-hwdef.h | 2 +- arch/arm64/kernel/head.S | 4 ++-- arch/arm64/mm/init.c | 10 ++++++++++ arch/arm64/mm/proc.S | 3 ++- 8 files changed, 39 insertions(+), 22 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index f7f23e47c28f..f5f7cb75a698 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -286,7 +286,7 @@ config PGTABLE_LEVELS int default 2 if ARM64_16K_PAGES && ARM64_VA_BITS_36 default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42 - default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) + default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39 default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47 default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48 @@ -300,12 +300,12 @@ config ARCH_PROC_KCORE_TEXT config KASAN_SHADOW_OFFSET hex depends on KASAN - default 0xdfffa00000000000 if (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) && !KASAN_SW_TAGS + default 0xdfffa00000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && !KASAN_SW_TAGS default 0xdfffd00000000000 if ARM64_VA_BITS_47 && !KASAN_SW_TAGS default 0xdffffe8000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS default 0xdfffffd000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS default 0xdffffffa00000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS - default 0xefff900000000000 if (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) && KASAN_SW_TAGS + default 0xefff900000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && KASAN_SW_TAGS default 0xefffc80000000000 if ARM64_VA_BITS_47 && KASAN_SW_TAGS default 0xeffffe4000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS default 0xefffffc800000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS @@ -759,13 +759,14 @@ config ARM64_VA_BITS_47 config ARM64_VA_BITS_48 bool "48-bit" -config ARM64_USER_VA_BITS_52 - bool "52-bit (user)" +config ARM64_VA_BITS_52 + bool "52-bit" depends on ARM64_64K_PAGES && (ARM64_PAN || !ARM64_SW_TTBR0_PAN) help Enable 52-bit virtual addressing for userspace when explicitly - requested via a hint to mmap(). The kernel will continue to - use 48-bit virtual addresses for its own mappings. + requested via a hint to mmap(). The kernel will also use 52-bit + virtual addresses for its own mappings (provided HW support for + this feature is available, otherwise it reverts to 48-bit). NOTE: Enabling 52-bit virtual addressing in conjunction with ARMv8.3 Pointer Authentication will result in the PAC being @@ -778,7 +779,7 @@ endchoice config ARM64_FORCE_52BIT bool "Force 52-bit virtual addresses for userspace" - depends on ARM64_USER_VA_BITS_52 && EXPERT + depends on ARM64_VA_BITS_52 && EXPERT help For systems with 52-bit userspace VAs enabled, the kernel will attempt to maintain compatibility with older software by providing 48-bit VAs @@ -795,7 +796,8 @@ config ARM64_VA_BITS default 39 if ARM64_VA_BITS_39 default 42 if ARM64_VA_BITS_42 default 47 if ARM64_VA_BITS_47 - default 48 if ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52 + default 48 if ARM64_VA_BITS_48 + default 52 if ARM64_VA_BITS_52 choice prompt "Physical address space size" diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index ede368bafa2c..c066fc4976cd 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -349,6 +349,13 @@ alternative_endif bfi \valreg, \t0sz, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH .endm +/* + * tcr_set_t1sz - update TCR.T1SZ + */ + .macro tcr_set_t1sz, valreg, t1sz + bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH + .endm + /* * tcr_compute_pa_size - set TCR.(I)PS to the highest supported * ID_AA64MMFR0_EL1.PARange value @@ -539,10 +546,6 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU * ttbr: Value of ttbr to set, modified. */ .macro offset_ttbr1, ttbr, tmp -#ifdef CONFIG_ARM64_USER_VA_BITS_52 - orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET -#endif - #ifdef CONFIG_ARM64_VA_BITS_52 mrs_s \tmp, SYS_ID_AA64MMFR2_EL1 and \tmp, \tmp, #(0xf << ID_AA64MMFR2_LVA_SHIFT) @@ -558,7 +561,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU * to be nop'ed out when dealing with 52-bit kernel VAs. */ .macro restore_ttbr1, ttbr -#if defined(CONFIG_ARM64_USER_VA_BITS_52) || defined(CONFIG_ARM64_VA_BITS_52) +#ifdef CONFIG_ARM64_VA_BITS_52 bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET #endif .endm diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 0204c2006c92..d911d0573460 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -44,8 +44,9 @@ * VA_START - the first kernel virtual address. */ #define VA_BITS (CONFIG_ARM64_VA_BITS) -#define PAGE_OFFSET (UL(0xffffffffffffffff) - \ - (UL(1) << VA_BITS) + 1) +#define _PAGE_OFFSET(va) (UL(0xffffffffffffffff) - \ + (UL(1) << (va)) + 1) +#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS)) #define KIMAGE_VADDR (MODULES_END) #define BPF_JIT_REGION_START (KASAN_SHADOW_END) #define BPF_JIT_REGION_SIZE (SZ_128M) @@ -68,7 +69,7 @@ #define KERNEL_START _text #define KERNEL_END _end -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#ifdef CONFIG_ARM64_VA_BITS_52 #define MAX_USER_VA_BITS 52 #else #define MAX_USER_VA_BITS VA_BITS diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 670003a55d28..3827ff4040a3 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -63,7 +63,7 @@ extern u64 idmap_ptrs_per_pgd; static inline bool __cpu_uses_extended_idmap(void) { - if (IS_ENABLED(CONFIG_ARM64_USER_VA_BITS_52)) + if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52)) return false; return unlikely(idmap_t0sz != TCR_T0SZ(VA_BITS)); diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index db92950bb1a0..3df60f97da1f 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -304,7 +304,7 @@ #define TTBR_BADDR_MASK_52 (((UL(1) << 46) - 1) << 2) #endif -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#ifdef CONFIG_ARM64_VA_BITS_52 /* Must be at least 64-byte aligned to prevent corruption of the TTBR */ #define TTBR1_BADDR_4852_OFFSET (((UL(1) << (52 - PGDIR_SHIFT)) - \ (UL(1) << (48 - PGDIR_SHIFT))) * 8) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index a96dc4386c7c..c8446f8c81f5 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -308,7 +308,7 @@ __create_page_tables: adrp x0, idmap_pg_dir adrp x3, __idmap_text_start // __pa(__idmap_text_start) -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#ifdef CONFIG_ARM64_VA_BITS_52 mrs_s x6, SYS_ID_AA64MMFR2_EL1 and x6, x6, #(0xf << ID_AA64MMFR2_LVA_SHIFT) mov x5, #52 @@ -794,7 +794,7 @@ ENTRY(__enable_mmu) ENDPROC(__enable_mmu) ENTRY(__cpu_secondary_check52bitva) -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#ifdef CONFIG_ARM64_VA_BITS_52 ldr_l x0, vabits_user cmp x0, #52 b.ne 2f diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 2940221e5519..531c497c5758 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -325,6 +325,16 @@ void __init arm64_memblock_init(void) vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)); + /* + * If we are running with a 52-bit kernel VA config on a system that + * does not support it, we have to offset our vmemmap and physvirt_offset + * s.t. we avoid the 52-bit portion of the direct linear map + */ + if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) { + vmemmap += (_PAGE_OFFSET(48) - _PAGE_OFFSET(52)) >> PAGE_SHIFT; + physvirt_offset = PHYS_OFFSET - _PAGE_OFFSET(48); + } + /* * Remove the memory that we will not be able to cover with the * linear mapping. Take care not to clip the kernel which may be diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 8d289ff7584d..8b021c5c0884 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -438,10 +438,11 @@ ENTRY(__cpu_setup) TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS tcr_clear_errata_bits x10, x9, x5 -#ifdef CONFIG_ARM64_USER_VA_BITS_52 +#ifdef CONFIG_ARM64_VA_BITS_52 ldr_l x9, vabits_user sub x9, xzr, x9 add x9, x9, #64 + tcr_set_t1sz x10, x9 #else ldr_l x9, idmap_t0sz #endif -- GitLab From 2c624fe68715e76eba1a7089f91e122310dc663c Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:23 +0100 Subject: [PATCH 2430/7155] arm64: mm: Remove vabits_user Previous patches have enabled 52-bit kernel + user VAs and there is no longer any scenario where user VA != kernel VA size. This patch removes the, now redundant, vabits_user variable and replaces usage with vabits_actual where appropriate. Reviewed-by: Catalin Marinas Signed-off-by: Steve Capper Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 3 --- arch/arm64/include/asm/pointer_auth.h | 2 +- arch/arm64/include/asm/processor.h | 2 +- arch/arm64/kernel/head.S | 7 +------ arch/arm64/mm/fault.c | 3 +-- arch/arm64/mm/mmu.c | 2 -- arch/arm64/mm/proc.S | 2 +- 7 files changed, 5 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index d911d0573460..ecc945ba8607 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -194,9 +194,6 @@ static inline unsigned long kaslr_offset(void) return kimage_vaddr - KIMAGE_VADDR; } -/* the actual size of a user virtual address */ -extern u64 vabits_user; - /* * Allow all memory at the discovery stage. We will clip it later. */ diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h index d328540cb85e..7a24bad1a58b 100644 --- a/arch/arm64/include/asm/pointer_auth.h +++ b/arch/arm64/include/asm/pointer_auth.h @@ -69,7 +69,7 @@ extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg); * The EL0 pointer bits used by a pointer authentication code. * This is dependent on TBI0 being enabled, or bits 63:56 would also apply. */ -#define ptrauth_user_pac_mask() GENMASK(54, vabits_user) +#define ptrauth_user_pac_mask() GENMASK(54, vabits_actual) /* Only valid for EL0 TTBR0 instruction pointers */ static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 0e1f2770192a..e4c93945e477 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -43,7 +43,7 @@ */ #define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS_MIN) -#define TASK_SIZE_64 (UL(1) << vabits_user) +#define TASK_SIZE_64 (UL(1) << vabits_actual) #ifdef CONFIG_COMPAT #if defined(CONFIG_ARM64_64K_PAGES) && defined(CONFIG_KUSER_HELPERS) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index c8446f8c81f5..949b001a73bb 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -316,11 +316,6 @@ __create_page_tables: #endif mov x5, #VA_BITS_MIN 1: - adr_l x6, vabits_user - str x5, [x6] - dmb sy - dc ivac, x6 // Invalidate potentially stale cache line - adr_l x6, vabits_actual str x5, [x6] dmb sy @@ -795,7 +790,7 @@ ENDPROC(__enable_mmu) ENTRY(__cpu_secondary_check52bitva) #ifdef CONFIG_ARM64_VA_BITS_52 - ldr_l x0, vabits_user + ldr_l x0, vabits_actual cmp x0, #52 b.ne 2f diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 6b195871769a..75eff57bd9ef 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -140,8 +140,7 @@ static void show_pte(unsigned long addr) pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n", mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, - mm == &init_mm ? vabits_actual : (int)vabits_user, - (unsigned long)virt_to_phys(mm->pgd)); + vabits_actual, (unsigned long)virt_to_phys(mm->pgd)); pgdp = pgd_offset(mm, addr); pgd = READ_ONCE(*pgdp); pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd)); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 07b30e6d17f8..0c8f7e55f859 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -40,8 +40,6 @@ u64 idmap_t0sz = TCR_T0SZ(VA_BITS); u64 idmap_ptrs_per_pgd = PTRS_PER_PGD; -u64 vabits_user __ro_after_init; -EXPORT_SYMBOL(vabits_user); u64 __section(".mmuoff.data.write") vabits_actual; EXPORT_SYMBOL(vabits_actual); diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 8b021c5c0884..391f9cabfe60 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -439,7 +439,7 @@ ENTRY(__cpu_setup) tcr_clear_errata_bits x10, x9, x5 #ifdef CONFIG_ARM64_VA_BITS_52 - ldr_l x9, vabits_user + ldr_l x9, vabits_actual sub x9, xzr, x9 add x9, x9, #64 tcr_set_t1sz x10, x9 -- GitLab From d2c68de192cfb90f607a80c6b10c41ebd8a3de6a Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Wed, 7 Aug 2019 16:55:24 +0100 Subject: [PATCH 2431/7155] docs: arm64: Add layout and 52-bit info to memory document As the kernel no longer prints out the memory layout on boot, this patch adds this information back to the memory document. Also, as the 52-bit support introduces some subtle changes to the arm64 memory, the rationale behind these changes are also added to the memory document. Signed-off-by: Steve Capper Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon --- Documentation/arm64/memory.rst | 123 +++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 28 deletions(-) diff --git a/Documentation/arm64/memory.rst b/Documentation/arm64/memory.rst index 464b880fc4b7..b040909e45f8 100644 --- a/Documentation/arm64/memory.rst +++ b/Documentation/arm64/memory.rst @@ -14,6 +14,10 @@ with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit 64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB) virtual address, are used but the memory layout is the same. +ARMv8.2 adds optional support for Large Virtual Address space. This is +only available when running with a 64KB page size and expands the +number of descriptors in the first level of translation. + User addresses have bits 63:48 set to 0 while the kernel addresses have the same bits set to 1. TTBRx selection is given by bit 63 of the virtual address. The swapper_pg_dir contains only kernel (global) @@ -22,40 +26,43 @@ The swapper_pg_dir address is written to TTBR1 and never written to TTBR0. -AArch64 Linux memory layout with 4KB pages + 3 levels:: - - Start End Size Use - ----------------------------------------------------------------------- - 0000000000000000 0000007fffffffff 512GB user - ffffff8000000000 ffffffffffffffff 512GB kernel - - -AArch64 Linux memory layout with 4KB pages + 4 levels:: +AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit):: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000ffffffffffff 256TB user - ffff000000000000 ffffffffffffffff 256TB kernel - - -AArch64 Linux memory layout with 64KB pages + 2 levels:: + ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map + ffff800000000000 ffff9fffffffffff 32TB kasan shadow region + ffffa00000000000 ffffa00007ffffff 128MB bpf jit region + ffffa00008000000 ffffa0000fffffff 128MB modules + ffffa00010000000 fffffdffbffeffff ~93TB vmalloc + fffffdffbfff0000 fffffdfffe5f8fff ~998MB [guard region] + fffffdfffe5f9000 fffffdfffe9fffff 4124KB fixed mappings + fffffdfffea00000 fffffdfffebfffff 2MB [guard region] + fffffdfffec00000 fffffdffffbfffff 16MB PCI I/O space + fffffdffffc00000 fffffdffffdfffff 2MB [guard region] + fffffdffffe00000 ffffffffffdfffff 2TB vmemmap + ffffffffffe00000 ffffffffffffffff 2MB [guard region] + + +AArch64 Linux memory layout with 64KB pages + 3 levels (52-bit with HW support):: Start End Size Use ----------------------------------------------------------------------- - 0000000000000000 000003ffffffffff 4TB user - fffffc0000000000 ffffffffffffffff 4TB kernel - - -AArch64 Linux memory layout with 64KB pages + 3 levels:: - - Start End Size Use - ----------------------------------------------------------------------- - 0000000000000000 0000ffffffffffff 256TB user - ffff000000000000 ffffffffffffffff 256TB kernel - - -For details of the virtual kernel memory layout please see the kernel -booting log. + 0000000000000000 000fffffffffffff 4PB user + fff0000000000000 fff7ffffffffffff 2PB kernel logical memory map + fff8000000000000 fffd9fffffffffff 1440TB [gap] + fffda00000000000 ffff9fffffffffff 512TB kasan shadow region + ffffa00000000000 ffffa00007ffffff 128MB bpf jit region + ffffa00008000000 ffffa0000fffffff 128MB modules + ffffa00010000000 fffff81ffffeffff ~88TB vmalloc + fffff81fffff0000 fffffc1ffe58ffff ~3TB [guard region] + fffffc1ffe590000 fffffc1ffe9fffff 4544KB fixed mappings + fffffc1ffea00000 fffffc1ffebfffff 2MB [guard region] + fffffc1ffec00000 fffffc1fffbfffff 16MB PCI I/O space + fffffc1fffc00000 fffffc1fffdfffff 2MB [guard region] + fffffc1fffe00000 ffffffffffdfffff 3968GB vmemmap + ffffffffffe00000 ffffffffffffffff 2MB [guard region] Translation table lookup with 4KB pages:: @@ -83,7 +90,8 @@ Translation table lookup with 64KB pages:: | | | | [15:0] in-page offset | | | +----------> [28:16] L3 index | | +--------------------------> [41:29] L2 index - | +-------------------------------> [47:42] L1 index + | +-------------------------------> [47:42] L1 index (48-bit) + | [51:42] L1 index (52-bit) +-------------------------------------------------> [63] TTBR0/1 @@ -96,3 +104,62 @@ ARM64_HARDEN_EL2_VECTORS is selected for particular CPUs. When using KVM with the Virtualization Host Extensions, no additional mappings are created, since the host kernel runs directly in EL2. + +52-bit VA support in the kernel +------------------------------- +If the ARMv8.2-LVA optional feature is present, and we are running +with a 64KB page size; then it is possible to use 52-bits of address +space for both userspace and kernel addresses. However, any kernel +binary that supports 52-bit must also be able to fall back to 48-bit +at early boot time if the hardware feature is not present. + +This fallback mechanism necessitates the kernel .text to be in the +higher addresses such that they are invariant to 48/52-bit VAs. Due +to the kasan shadow being a fraction of the entire kernel VA space, +the end of the kasan shadow must also be in the higher half of the +kernel VA space for both 48/52-bit. (Switching from 48-bit to 52-bit, +the end of the kasan shadow is invariant and dependent on ~0UL, +whilst the start address will "grow" towards the lower addresses). + +In order to optimise phys_to_virt and virt_to_phys, the PAGE_OFFSET +is kept constant at 0xFFF0000000000000 (corresponding to 52-bit), +this obviates the need for an extra variable read. The physvirt +offset and vmemmap offsets are computed at early boot to enable +this logic. + +As a single binary will need to support both 48-bit and 52-bit VA +spaces, the VMEMMAP must be sized large enough for 52-bit VAs and +also must be sized large enought to accommodate a fixed PAGE_OFFSET. + +Most code in the kernel should not need to consider the VA_BITS, for +code that does need to know the VA size the variables are +defined as follows: + +VA_BITS constant the *maximum* VA space size + +VA_BITS_MIN constant the *minimum* VA space size + +vabits_actual variable the *actual* VA space size + + +Maximum and minimum sizes can be useful to ensure that buffers are +sized large enough or that addresses are positioned close enough for +the "worst" case. + +52-bit userspace VAs +-------------------- +To maintain compatibility with software that relies on the ARMv8.0 +VA space maximum size of 48-bits, the kernel will, by default, +return virtual addresses to userspace from a 48-bit range. + +Software can "opt-in" to receiving VAs from a 52-bit space by +specifying an mmap hint parameter that is larger than 48-bit. +For example: + maybe_high_address = mmap(~0UL, size, prot, flags,...); + +It is also possible to build a debug kernel that returns addresses +from a 52-bit space by enabling the following kernel config options: + CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y + +Note that this option is only intended for debugging applications +and should not be used in production. -- GitLab From 3cd703f483d1d8cfcd7fd6f304ab6fc74e29cf15 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 19 Jul 2019 11:30:37 +0200 Subject: [PATCH 2432/7155] usb: dwc3: remove generic PHYs forwarding for XHCI device Commit 08f871a3aca2 ("usb: dwc3: host: convey the PHYs to xhci") added forwarding of the generic PHYs from DWC3 core to the instantiated XHCI-plat device. However XHCI(-plat) driver never gained support for generic PHYs, thus the lookup added by that commit is never used. In meantime the commit d64ff406e51e ("usb: dwc3: use bus->sysdev for DMA configuration") incorrectly changed the device used for creating lookup, making the lookup useless and generic PHYs inaccessible from XHCI device. However since commit 178a0bce05cb ("usb: core: hcd: integrate the PHY wrapper into the HCD core") USB HCD already handles generic PHYs acquired from the HCD's 'sysdev', which in this case is DWC3 core device. This means that creating any custom lookup entries for XHCI driver is no longer needed and can be simply removed. Signed-off-by: Marek Szyprowski Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/host.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index f55947294f7c..8deea8c91e03 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -85,7 +85,7 @@ int dwc3_host_init(struct dwc3 *dwc) DWC3_XHCI_RESOURCES_NUM); if (ret) { dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); - goto err1; + goto err; } memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); @@ -112,37 +112,23 @@ int dwc3_host_init(struct dwc3 *dwc) ret = platform_device_add_properties(xhci, props); if (ret) { dev_err(dwc->dev, "failed to add properties to xHCI\n"); - goto err1; + goto err; } } - phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy", - dev_name(dwc->dev)); - phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy", - dev_name(dwc->dev)); - ret = platform_device_add(xhci); if (ret) { dev_err(dwc->dev, "failed to register xHCI device\n"); - goto err2; + goto err; } return 0; -err2: - phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", - dev_name(dwc->dev)); - phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", - dev_name(dwc->dev)); -err1: +err: platform_device_put(xhci); return ret; } void dwc3_host_exit(struct dwc3 *dwc) { - phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", - dev_name(dwc->dev)); - phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", - dev_name(dwc->dev)); platform_device_unregister(dwc->xhci); } -- GitLab From 03bf32bbb607e07bf9ac6ea126088d1dc88ea948 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 12 Jul 2019 00:26:33 -0700 Subject: [PATCH 2433/7155] usb: dwc3: Use devres to get clocks Use devres to get clocks and drop explicit clock freeing. No functional change intended. Signed-off-by: Andrey Smirnov Cc: Felipe Balbi Cc: Chris Healy Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 252c397860ef..7ae2eee72f90 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1448,7 +1448,7 @@ static int dwc3_probe(struct platform_device *pdev) if (dev->of_node) { dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); - ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); + ret = devm_clk_bulk_get(dev, dwc->num_clks, dwc->clks); if (ret == -EPROBE_DEFER) return ret; /* @@ -1461,7 +1461,7 @@ static int dwc3_probe(struct platform_device *pdev) ret = reset_control_deassert(dwc->reset); if (ret) - goto put_clks; + return ret; ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); if (ret) @@ -1548,8 +1548,6 @@ static int dwc3_probe(struct platform_device *pdev) clk_bulk_unprepare(dwc->num_clks, dwc->clks); assert_reset: reset_control_assert(dwc->reset); -put_clks: - clk_bulk_put(dwc->num_clks, dwc->clks); return ret; } @@ -1572,7 +1570,6 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_free_event_buffers(dwc); dwc3_free_scratch_buffers(dwc); - clk_bulk_put(dwc->num_clks, dwc->clks); return 0; } -- GitLab From 240b65dc1e89dd83d0c4946f58e49e7ee669b25d Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 12 Jul 2019 00:26:34 -0700 Subject: [PATCH 2434/7155] usb: dwc3: Use clk_bulk_prepare_enable() Use clk_bulk_prepare_enable() and clk_bulk_disable_unprepare() to simplify code a bit. No functional change intended. Signed-off-by: Andrey Smirnov Cc: Felipe Balbi Cc: Chris Healy Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7ae2eee72f90..30ebf3c65a63 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -699,8 +699,7 @@ static void dwc3_core_exit(struct dwc3 *dwc) usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); - clk_bulk_disable(dwc->num_clks, dwc->clks); - clk_bulk_unprepare(dwc->num_clks, dwc->clks); + clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); reset_control_assert(dwc->reset); } @@ -1463,14 +1462,10 @@ static int dwc3_probe(struct platform_device *pdev) if (ret) return ret; - ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); + ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); if (ret) goto assert_reset; - ret = clk_bulk_enable(dwc->num_clks, dwc->clks); - if (ret) - goto unprepare_clks; - if (!dwc3_core_is_valid(dwc)) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; @@ -1543,9 +1538,7 @@ static int dwc3_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); disable_clks: - clk_bulk_disable(dwc->num_clks, dwc->clks); -unprepare_clks: - clk_bulk_unprepare(dwc->num_clks, dwc->clks); + clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); assert_reset: reset_control_assert(dwc->reset); @@ -1583,14 +1576,10 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) if (ret) return ret; - ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); + ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); if (ret) goto assert_reset; - ret = clk_bulk_enable(dwc->num_clks, dwc->clks); - if (ret) - goto unprepare_clks; - ret = dwc3_core_init(dwc); if (ret) goto disable_clks; @@ -1598,9 +1587,7 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) return 0; disable_clks: - clk_bulk_disable(dwc->num_clks, dwc->clks); -unprepare_clks: - clk_bulk_unprepare(dwc->num_clks, dwc->clks); + clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); assert_reset: reset_control_assert(dwc->reset); -- GitLab From a62bd63893027bfa32fccbba0e0ac067824c362c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 19:01:00 +0800 Subject: [PATCH 2435/7155] ASoC: SOF: Intel: Add missing include file hdac_hda.h Building with SND_SOC_SOF_HDA_AUDIO_CODEC fails: sound/soc/sof/intel/hda-bus.c: In function sof_hda_bus_init: sound/soc/sof/intel/hda-bus.c:16:25: error: implicit declaration of function snd_soc_hdac_hda_get_ops; did you mean snd_soc_jack_add_gpiods? [-Werror=implicit-function-declaration] #define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() Reported-by: Hulk Robot Suggested-by: Takashi Iwai Fixes: d4ff1b3917a5 ('ASoC: SOF: Intel: Initialize hdaudio bus properly") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190809110100.71236-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-bus.c | 1 + sound/soc/sof/intel/hda.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 0caec3a070d3..1d2babdda9dd 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -13,6 +13,7 @@ #include "hda.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +#include "../../codecs/hdac_hda.h" #define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() #else #define sof_hda_ext_ops NULL diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d04844d6b104..28eb780494aa 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -23,9 +23,6 @@ #include #include "../ops.h" #include "hda.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -#include "../../codecs/hdac_hda.h" -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #include -- GitLab From bc8d9f737fc01cce913f1cc215b7e66f01697e52 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 16:02:34 +0800 Subject: [PATCH 2436/7155] ASoC: mt6351: remove unused variable 'mt_lineout_control' sound/soc/codecs/mt6351.c:1070:38: warning: mt_lineout_control defined but not used [-Wunused-const-variable=] It is never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190809080234.23332-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6351.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/codecs/mt6351.c b/sound/soc/codecs/mt6351.c index 4b3ce01c5a93..5c0536eb1044 100644 --- a/sound/soc/codecs/mt6351.c +++ b/sound/soc/codecs/mt6351.c @@ -1066,11 +1066,6 @@ static int mt_mic_bias_2_event(struct snd_soc_dapm_widget *w, return 0; } -/* DAPM Kcontrols */ -static const struct snd_kcontrol_new mt_lineout_control = - SOC_DAPM_SINGLE("Switch", MT6351_AUDDEC_ANA_CON3, - RG_AUDLOLPWRUP_VAUDP32_BIT, 1, 0); - /* DAPM Widgets */ static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = { /* Digital Clock */ -- GitLab From 0fd70e22a0ffebd13028bf2c7da6b747070475bf Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 16:24:40 +0800 Subject: [PATCH 2437/7155] ASoC: ml26124: remove unused variable 'ngth' In file included from ./include/sound/tlv.h:10:0, from sound/soc/codecs/ml26124.c:19: sound/soc/codecs/ml26124.c:59:35: warning: ngth defined but not used [-Wunused-const-variable=] static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); ^ ./include/uapi/sound/tlv.h:64:15: note: in definition of macro SNDRV_CTL_TLVD_DECLARE_DB_SCALE unsigned int name[] = { \ ^~~~ sound/soc/codecs/ml26124.c:59:14: note: in expansion of macro DECLARE_TLV_DB_SCALE static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); ^~~~~~~~~~~~~~~~~~~~ It is never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190809082440.67412-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/ml26124.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 3abd27893ce6..55823bc95d06 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -56,7 +56,6 @@ static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0); static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0); static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0); static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); static const char * const ml26124_companding[] = {"16bit PCM", "u-law", "A-law"}; -- GitLab From 0b76f512c206dd7c3f7761b24826887af80204c6 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:01:58 -0500 Subject: [PATCH 2438/7155] ASoC: SOF: Remove call to snd_sof_dsp_mailbox_init This is reserved for some historical reason, we didn't enable memory windows for byt/bdw at the beginning, to make it compatible, we get those mailbox offsets from fw_ready struct firstly, and then update them if they existed in the following memory windows, to make sure the mailbox still can be used if no memory windows are created. With this change all platforms have the same implementation for xxx_fw_ready function so that we can refactor it in a common file. Suggested-by: Keyon Jie Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 5 ----- sound/soc/sof/intel/byt.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 4bb9636da990..94be024a99eb 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -455,11 +455,6 @@ static int bdw_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, sizeof(*fw_ready)); - snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset, - fw_ready->dspbox_size, - fw_ready->hostbox_offset, - fw_ready->hostbox_size); - /* make sure ABI version is compatible */ ret = snd_sof_ipc_valid(sdev); if (ret < 0) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 000d576f6a8d..cb8f02ee09f2 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -237,11 +237,6 @@ static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, sizeof(*fw_ready)); - snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset, - fw_ready->dspbox_size, - fw_ready->hostbox_offset, - fw_ready->hostbox_size); - /* make sure ABI version is compatible */ ret = snd_sof_ipc_valid(sdev); if (ret < 0) -- GitLab From ddf14b640b05839cfe44d686d5a5cc7c55076094 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:02:02 -0500 Subject: [PATCH 2439/7155] ASoC: SOF: Intel: bdw: Use generic function for fw ready / mem windows creation bdw_get_windows / bdw_fw_ready is identical with the generic implementation introduced in a previous patch. So remove bdw_get_windows / bdw_fw_ready and use the generic sof_get_windows version. Do not forget to implement get_mailbox_offset/get_window_offset so that we export the correct mailbox/memory window offset to the outside world. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 156 ++++---------------------------------- 1 file changed, 13 insertions(+), 143 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 94be024a99eb..e282179263e8 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -327,148 +327,6 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) return IRQ_HANDLED; } -/* - * IPC Firmware ready. - */ -static void bdw_get_windows(struct snd_sof_dev *sdev) -{ - struct sof_ipc_window_elem *elem; - u32 outbox_offset = 0; - u32 stream_offset = 0; - u32 inbox_offset = 0; - u32 outbox_size = 0; - u32 stream_size = 0; - u32 inbox_size = 0; - int i; - - if (!sdev->info_window) { - dev_err(sdev->dev, "error: have no window info\n"); - return; - } - - for (i = 0; i < sdev->info_window->num_windows; i++) { - elem = &sdev->info_window->window[i]; - - switch (elem->type) { - case SOF_IPC_REGION_UPBOX: - inbox_offset = elem->offset + MBOX_OFFSET; - inbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - inbox_offset, - elem->size, "inbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DOWNBOX: - outbox_offset = elem->offset + MBOX_OFFSET; - outbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - outbox_offset, - elem->size, "outbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_TRACE: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "etrace", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DEBUG: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "debug", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_STREAM: - stream_offset = elem->offset + MBOX_OFFSET; - stream_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - stream_offset, - elem->size, "stream", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_REGS: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "regs", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_EXCEPTION: - sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BDW_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "exception", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - default: - dev_err(sdev->dev, "error: get illegal window info\n"); - return; - } - } - - if (outbox_size == 0 || inbox_size == 0) { - dev_err(sdev->dev, "error: get illegal mailbox window\n"); - return; - } - - snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, - outbox_offset, outbox_size); - sdev->stream_box.offset = stream_offset; - sdev->stream_box.size = stream_size; - - dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", - inbox_offset, inbox_size); - dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", - outbox_offset, outbox_size); - dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", - stream_offset, stream_size); -} - -/* check for ABI compatibility and create memory windows on first boot */ -static int bdw_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) -{ - struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; - u32 offset; - int ret; - - /* mailbox must be on 4k boundary */ - offset = MBOX_OFFSET; - - dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset %d\n", - msg_id, offset); - - /* no need to re-check version/ABI for subsequent boots */ - if (!sdev->first_boot) - return 0; - - /* copy data from the DSP FW ready offset */ - sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, - sizeof(*fw_ready)); - - /* make sure ABI version is compatible */ - ret = snd_sof_ipc_valid(sdev); - if (ret < 0) - return ret; - - /* now check for extended data */ - snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET + - sizeof(struct sof_ipc_fw_ready)); - - bdw_get_windows(sdev); - - return 0; -} - /* * IPC Mailbox IO */ @@ -522,6 +380,16 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) msg->reply_error = ret; } +static int bdw_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + return MBOX_OFFSET; +} + +static int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id) +{ + return MBOX_OFFSET; +} + static void bdw_host_done(struct snd_sof_dev *sdev) { /* clear BUSY bit and set DONE bit - accept new messages */ @@ -672,7 +540,9 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { /* ipc */ .send_msg = bdw_send_msg, - .fw_ready = bdw_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = bdw_get_mailbox_offset, + .get_window_offset = bdw_get_window_offset, .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, -- GitLab From 6eebd3907527764618ee250e1106b9e809c46143 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:02:03 -0500 Subject: [PATCH 2440/7155] ASoC: SOF: Intel: hda: Use generic function for fw ready / mem windows creation We can use generic sof_fw_ready function and reduce code duplication. Careful here that we need to provide the implementation for get_mailbox_offset and get_window_offset. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 4 +- sound/soc/sof/intel/cnl.c | 4 +- sound/soc/sof/intel/hda-ipc.c | 150 +--------------------------------- sound/soc/sof/intel/hda.h | 4 +- 4 files changed, 13 insertions(+), 149 deletions(-) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index fd2e26d79796..8dc7a5558da4 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -46,7 +46,9 @@ const struct snd_sof_dsp_ops sof_apl_ops = { /* ipc */ .send_msg = hda_dsp_ipc_send_msg, - .fw_ready = hda_dsp_ipc_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset, + .get_window_offset = hda_dsp_ipc_get_window_offset, .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index ffd8d4394537..6d7d9c93252c 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -204,7 +204,9 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { /* ipc */ .send_msg = cnl_ipc_send_msg, - .fw_ready = hda_dsp_ipc_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset, + .get_window_offset = hda_dsp_ipc_get_window_offset, .ipc_msg_data = hda_ipc_msg_data, .ipc_pcm_params = hda_ipc_pcm_params, diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 2ecba91f5219..6aae6f18b3dc 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -266,156 +266,14 @@ irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context) return ret; } -/* IPC Firmware ready */ - -static void ipc_get_windows(struct snd_sof_dev *sdev) +int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { - struct sof_ipc_window_elem *elem; - u32 outbox_offset = 0; - u32 stream_offset = 0; - u32 inbox_offset = 0; - u32 outbox_size = 0; - u32 stream_size = 0; - u32 inbox_size = 0; - int i; - - if (!sdev->info_window) { - dev_err(sdev->dev, "error: have no window info\n"); - return; - } - - for (i = 0; i < sdev->info_window->num_windows; i++) { - elem = &sdev->info_window->window[i]; - - switch (elem->type) { - case SOF_IPC_REGION_UPBOX: - inbox_offset = - elem->offset + SRAM_WINDOW_OFFSET(elem->id); - inbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - inbox_offset, - elem->size, "inbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DOWNBOX: - outbox_offset = - elem->offset + SRAM_WINDOW_OFFSET(elem->id); - outbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - outbox_offset, - elem->size, "outbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_TRACE: - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - elem->offset + - SRAM_WINDOW_OFFSET - (elem->id), - elem->size, "etrace", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DEBUG: - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - elem->offset + - SRAM_WINDOW_OFFSET - (elem->id), - elem->size, "debug", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_STREAM: - stream_offset = - elem->offset + SRAM_WINDOW_OFFSET(elem->id); - stream_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - elem->offset + - SRAM_WINDOW_OFFSET - (elem->id), - elem->size, "stream", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_REGS: - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - elem->offset + - SRAM_WINDOW_OFFSET - (elem->id), - elem->size, "regs", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_EXCEPTION: - sdev->dsp_oops_offset = elem->offset + - SRAM_WINDOW_OFFSET(elem->id); - snd_sof_debugfs_io_item(sdev, - sdev->bar[HDA_DSP_BAR] + - elem->offset + - SRAM_WINDOW_OFFSET - (elem->id), - elem->size, "exception", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - default: - dev_err(sdev->dev, "error: get illegal window info\n"); - return; - } - } - - if (outbox_size == 0 || inbox_size == 0) { - dev_err(sdev->dev, "error: get illegal mailbox window\n"); - return; - } - - snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, - outbox_offset, outbox_size); - sdev->stream_box.offset = stream_offset; - sdev->stream_box.size = stream_size; - - dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", - inbox_offset, inbox_size); - dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", - outbox_offset, outbox_size); - dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", - stream_offset, stream_size); + return HDA_DSP_MBOX_UPLINK_OFFSET; } -/* check for ABI compatibility and create memory windows on first boot */ -int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) +int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) { - struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; - u32 offset; - int ret; - - /* mailbox must be on 4k boundary */ - offset = HDA_DSP_MBOX_UPLINK_OFFSET; - - dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", - msg_id, offset); - - /* no need to re-check version/ABI for subsequent boots */ - if (!sdev->first_boot) - return 0; - - /* copy data from the DSP FW ready offset */ - sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, - sizeof(*fw_ready)); - - /* make sure ABI version is compatible */ - ret = snd_sof_ipc_valid(sdev); - if (ret < 0) - return ret; - - /* now check for extended data */ - snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, - HDA_DSP_MBOX_UPLINK_OFFSET + - sizeof(struct sof_ipc_fw_ready)); - - ipc_get_windows(sdev); - - return 0; + return SRAM_WINDOW_OFFSET(id); } void hda_ipc_msg_data(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 65904c3511df..6db3dcbab3bd 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -519,7 +519,9 @@ int hda_ipc_pcm_params(struct snd_sof_dev *sdev, int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg); void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); -int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); +int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev); +int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); + irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); -- GitLab From bb9c93f58cb66049cb5a5570cc476d9a8a97f491 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:01:59 -0500 Subject: [PATCH 2441/7155] ASoC: SOF: Introduce snd_sof_dsp_get_mailbox_offset This will allow us to export mailbox offset in order to read the fw_ready message from. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 9 +++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 793c1aea0c53..c820606f19a1 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -119,6 +119,15 @@ static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type) return sdev->mmio_bar; } +static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev)->get_mailbox_offset) + return sof_ops(sdev)->get_mailbox_offset(sdev); + + dev_err(sdev->dev, "error: %s not defined\n", __func__); + return -ENOTSUPP; +} + /* power management */ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1cec3f23f9cd..3aefb8ec3ef9 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -198,6 +198,8 @@ struct snd_sof_dsp_ops { /* misc */ int (*get_bar_index)(struct snd_sof_dev *sdev, u32 type); /* optional */ + int (*get_mailbox_offset)(struct snd_sof_dev *sdev);/* mandatory for common loader code */ + /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; -- GitLab From e17422cda9d60339d71e117d3fdfd444e83669a4 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:02:00 -0500 Subject: [PATCH 2442/7155] ASoC: SOF: Introduce snd_sof_dsp_get_window_offset This will allow us to export the offset for a memory window. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 9 +++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index c820606f19a1..824d36fe59fd 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -128,6 +128,15 @@ static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev) return -ENOTSUPP; } +static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev, + u32 id) +{ + if (sof_ops(sdev)->get_window_offset) + return sof_ops(sdev)->get_window_offset(sdev, id); + + dev_err(sdev->dev, "error: %s not defined\n", __func__); + return -ENOTSUPP; +} /* power management */ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 3aefb8ec3ef9..de11f28bae3a 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -199,6 +199,8 @@ struct snd_sof_dsp_ops { int (*get_bar_index)(struct snd_sof_dev *sdev, u32 type); /* optional */ int (*get_mailbox_offset)(struct snd_sof_dev *sdev);/* mandatory for common loader code */ + int (*get_window_offset)(struct snd_sof_dev *sdev, + u32 id);/* mandatory for common loader code */ /* DAI ops */ struct snd_soc_dai_driver *drv; -- GitLab From 83ee7ab1627b7597bbb9acc26b37e9f96fff40c9 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 7 Aug 2019 10:02:01 -0500 Subject: [PATCH 2443/7155] ASoC: SOF: Intel: byt: Refactor fw ready / mem windows creation There is a lot of duplicate code when processing IPC firmware ready notification and creating memory windows. First step in reducing the code duplication is to introduce generic functions: * sof_get_windows * sof_fw_ready that will replace, in the first step, the specific implementation related to baytrail related platforms: * byt_get_windows * byt_fw_ready So we are basically moving code from intel/byt.c to loader.c keeping in mind that mbox_offset is a per platform constant so we need to use newly introduced snd_sof_dsp_get_mailbox_offset / snd_sof_dsp_get_window_offset in order to get the correct mbox offset / window offset value. Also, bar is a per platform constant so we use snd_sof_dsp_get_bar_index instead of the hardcoded BYT_DSP_BAR. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190807150203.26359-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 164 +++++-------------------------------- sound/soc/sof/loader.c | 168 ++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-priv.h | 2 + 3 files changed, 189 insertions(+), 145 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index cb8f02ee09f2..5e7a6aaa627a 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -109,148 +109,6 @@ static void byt_host_done(struct snd_sof_dev *sdev); static void byt_dsp_done(struct snd_sof_dev *sdev); static void byt_get_reply(struct snd_sof_dev *sdev); -/* - * IPC Firmware ready. - */ -static void byt_get_windows(struct snd_sof_dev *sdev) -{ - struct sof_ipc_window_elem *elem; - u32 outbox_offset = 0; - u32 stream_offset = 0; - u32 inbox_offset = 0; - u32 outbox_size = 0; - u32 stream_size = 0; - u32 inbox_size = 0; - int i; - - if (!sdev->info_window) { - dev_err(sdev->dev, "error: have no window info\n"); - return; - } - - for (i = 0; i < sdev->info_window->num_windows; i++) { - elem = &sdev->info_window->window[i]; - - switch (elem->type) { - case SOF_IPC_REGION_UPBOX: - inbox_offset = elem->offset + MBOX_OFFSET; - inbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - inbox_offset, - elem->size, "inbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DOWNBOX: - outbox_offset = elem->offset + MBOX_OFFSET; - outbox_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - outbox_offset, - elem->size, "outbox", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_TRACE: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "etrace", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_DEBUG: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "debug", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_STREAM: - stream_offset = elem->offset + MBOX_OFFSET; - stream_size = elem->size; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - stream_offset, - elem->size, "stream", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_REGS: - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "regs", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - case SOF_IPC_REGION_EXCEPTION: - sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET; - snd_sof_debugfs_io_item(sdev, - sdev->bar[BYT_DSP_BAR] + - elem->offset + - MBOX_OFFSET, - elem->size, "exception", - SOF_DEBUGFS_ACCESS_D0_ONLY); - break; - default: - dev_err(sdev->dev, "error: get illegal window info\n"); - return; - } - } - - if (outbox_size == 0 || inbox_size == 0) { - dev_err(sdev->dev, "error: get illegal mailbox window\n"); - return; - } - - snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, - outbox_offset, outbox_size); - sdev->stream_box.offset = stream_offset; - sdev->stream_box.size = stream_size; - - dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", - inbox_offset, inbox_size); - dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", - outbox_offset, outbox_size); - dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", - stream_offset, stream_size); -} - -/* check for ABI compatibility and create memory windows on first boot */ -static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) -{ - struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; - u32 offset; - int ret; - - /* mailbox must be on 4k boundary */ - offset = MBOX_OFFSET; - - dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", - msg_id, offset); - - /* no need to re-check version/ABI for subsequent boots */ - if (!sdev->first_boot) - return 0; - - /* copy data from the DSP FW ready offset */ - sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, - sizeof(*fw_ready)); - - /* make sure ABI version is compatible */ - ret = snd_sof_ipc_valid(sdev); - if (ret < 0) - return ret; - - /* now check for extended data */ - snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET + - sizeof(struct sof_ipc_fw_ready)); - - byt_get_windows(sdev); - - return 0; -} - /* * Debug */ @@ -418,6 +276,16 @@ static void byt_get_reply(struct snd_sof_dev *sdev) msg->reply_error = ret; } +static int byt_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + return MBOX_OFFSET; +} + +static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id) +{ + return MBOX_OFFSET; +} + static void byt_host_done(struct snd_sof_dev *sdev) { /* clear BUSY bit and set DONE bit - accept new messages */ @@ -612,7 +480,9 @@ const struct snd_sof_dsp_ops sof_tng_ops = { /* ipc */ .send_msg = byt_send_msg, - .fw_ready = byt_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = byt_get_mailbox_offset, + .get_window_offset = byt_get_window_offset, .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, @@ -771,7 +641,9 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /* ipc */ .send_msg = byt_send_msg, - .fw_ready = byt_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = byt_get_mailbox_offset, + .get_window_offset = byt_get_window_offset, .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, @@ -828,7 +700,9 @@ const struct snd_sof_dsp_ops sof_cht_ops = { /* ipc */ .send_msg = byt_send_msg, - .fw_ready = byt_fw_ready, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = byt_get_mailbox_offset, + .get_window_offset = byt_get_window_offset, .ipc_msg_data = intel_ipc_msg_data, .ipc_pcm_params = intel_ipc_pcm_params, diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 93cb8fd0844f..d7f32745fefe 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -87,6 +87,174 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +/* + * IPC Firmware ready. + */ +static void sof_get_windows(struct snd_sof_dev *sdev) +{ + struct sof_ipc_window_elem *elem; + u32 outbox_offset = 0; + u32 stream_offset = 0; + u32 inbox_offset = 0; + u32 outbox_size = 0; + u32 stream_size = 0; + u32 inbox_size = 0; + int window_offset; + int bar; + int i; + + if (!sdev->info_window) { + dev_err(sdev->dev, "error: have no window info\n"); + return; + } + + bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); + if (bar < 0) { + dev_err(sdev->dev, "error: have no bar mapping\n"); + return; + } + + for (i = 0; i < sdev->info_window->num_windows; i++) { + elem = &sdev->info_window->window[i]; + + window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id); + if (window_offset < 0) { + dev_warn(sdev->dev, "warn: no offset for window %d\n", + elem->id); + continue; + } + + switch (elem->type) { + case SOF_IPC_REGION_UPBOX: + inbox_offset = window_offset + elem->offset; + inbox_size = elem->size; + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + inbox_offset, + elem->size, "inbox", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_DOWNBOX: + outbox_offset = window_offset + elem->offset; + outbox_size = elem->size; + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + outbox_offset, + elem->size, "outbox", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_TRACE: + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + window_offset + + elem->offset, + elem->size, "etrace", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_DEBUG: + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + window_offset + + elem->offset, + elem->size, "debug", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_STREAM: + stream_offset = window_offset + elem->offset; + stream_size = elem->size; + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + stream_offset, + elem->size, "stream", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_REGS: + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + window_offset + + elem->offset, + elem->size, "regs", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + case SOF_IPC_REGION_EXCEPTION: + sdev->dsp_oops_offset = window_offset + elem->offset; + snd_sof_debugfs_io_item(sdev, + sdev->bar[bar] + + window_offset + + elem->offset, + elem->size, "exception", + SOF_DEBUGFS_ACCESS_D0_ONLY); + break; + default: + dev_err(sdev->dev, "error: get illegal window info\n"); + return; + } + } + + if (outbox_size == 0 || inbox_size == 0) { + dev_err(sdev->dev, "error: get illegal mailbox window\n"); + return; + } + + snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, + outbox_offset, outbox_size); + sdev->stream_box.offset = stream_offset; + sdev->stream_box.size = stream_size; + + dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", + inbox_offset, inbox_size); + dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", + outbox_offset, outbox_size); + dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", + stream_offset, stream_size); +} + +/* check for ABI compatibility and create memory windows on first boot */ +int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) +{ + struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; + int offset; + int bar; + int ret; + + /* mailbox must be on 4k boundary */ + offset = snd_sof_dsp_get_mailbox_offset(sdev); + if (offset < 0) { + dev_err(sdev->dev, "error: have no mailbox offset\n"); + return offset; + } + + bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); + if (bar < 0) { + dev_err(sdev->dev, "error: have no bar mapping\n"); + return -EINVAL; + } + + dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", + msg_id, offset); + + /* no need to re-check version/ABI for subsequent boots */ + if (!sdev->first_boot) + return 0; + + /* copy data from the DSP FW ready offset */ + sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready)); + + /* make sure ABI version is compatible */ + ret = snd_sof_ipc_valid(sdev); + if (ret < 0) + return ret; + + /* now check for extended data */ + snd_sof_fw_parse_ext_data(sdev, bar, offset + + sizeof(struct sof_ipc_fw_ready)); + + sof_get_windows(sdev); + + return 0; +} +EXPORT_SYMBOL(sof_fw_ready); + /* generic module parser for mmaped DSPs */ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, struct snd_sof_mod_hdr *module) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index de11f28bae3a..730f3259dd02 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -642,6 +642,8 @@ void sof_block_write(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *src, void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest, size_t size); +int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); + void intel_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, void *p, size_t sz); -- GitLab From c6e20fa49818381dfa7288fad4c33b84408aab54 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:13 +0530 Subject: [PATCH 2444/7155] regulator: dt-bindings: Sort the compatibles and nodes It helps to keep sorted order for compatibles and nodes, so sort them Suggested-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-1-vkoul@kernel.org Signed-off-by: Mark Brown --- .../regulator/qcom,rpmh-regulator.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt index 1a9cab50503a..bab9f71140b8 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt @@ -22,12 +22,12 @@ RPMh resource. The names used for regulator nodes must match those supported by a given PMIC. Supported regulator node names: - PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 - PMI8998: bob PM8005: smps1 - smps4 + PM8009: smps1 - smps2, ldo1 - ldo7 PM8150: smps1 - smps10, ldo1 - ldo18 PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb - PM8009: smps1 - smps2, ld01 - ldo7 + PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 + PMI8998: bob ======================== First Level Nodes - PMIC @@ -36,12 +36,13 @@ First Level Nodes - PMIC - compatible Usage: required Value type: - Definition: Must be one of: "qcom,pm8998-rpmh-regulators", - "qcom,pmi8998-rpmh-regulators" or - "qcom,pm8005-rpmh-regulators" or - "qcom,pm8150-rpmh-regulators" or - "qcom,pm8150l-rpmh-regulators" or - "qcom,pm8009-rpmh-regulators". + Definition: Must be one of below: + "qcom,pm8005-rpmh-regulators" + "qcom,pm8009-rpmh-regulators" + "qcom,pm8150-rpmh-regulators" + "qcom,pm8150l-rpmh-regulators" + "qcom,pm8998-rpmh-regulators" + "qcom,pmi8998-rpmh-regulators" - qcom,pmic-id Usage: required -- GitLab From 7172fb7f3abea4787ca01dda7297241c4b0f0af5 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:14 +0530 Subject: [PATCH 2445/7155] regulator: qcom-rpmh: Sort the compatibles It helps to keep sorted order for compatibles, so sort them Suggested-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-2-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 693ffec62f3e..0ef2716da3bd 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -878,18 +878,14 @@ static int rpmh_regulator_probe(struct platform_device *pdev) } static const struct of_device_id rpmh_regulator_match_table[] = { - { - .compatible = "qcom,pm8998-rpmh-regulators", - .data = pm8998_vreg_data, - }, - { - .compatible = "qcom,pmi8998-rpmh-regulators", - .data = pmi8998_vreg_data, - }, { .compatible = "qcom,pm8005-rpmh-regulators", .data = pm8005_vreg_data, }, + { + .compatible = "qcom,pm8009-rpmh-regulators", + .data = pm8009_vreg_data, + }, { .compatible = "qcom,pm8150-rpmh-regulators", .data = pm8150_vreg_data, @@ -899,8 +895,12 @@ static const struct of_device_id rpmh_regulator_match_table[] = { .data = pm8150l_vreg_data, }, { - .compatible = "qcom,pm8009-rpmh-regulators", - .data = pm8009_vreg_data, + .compatible = "qcom,pm8998-rpmh-regulators", + .data = pm8998_vreg_data, + }, + { + .compatible = "qcom,pmi8998-rpmh-regulators", + .data = pmi8998_vreg_data, }, {} }; -- GitLab From 553c452d6093d66e7617ed6c68cc93547d07075f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:15 +0530 Subject: [PATCH 2446/7155] regulator: qcom-rpmh: Fix pmic5_bob voltage count pmic5_bob voltages count is 136 [0,135] so update it Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-3-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 0ef2716da3bd..391ed844a251 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -698,7 +698,7 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_bypass_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), - .n_voltages = 135, + .n_voltages = 136, .pmic_mode_map = pmic_mode_map_pmic4_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; -- GitLab From 610f29e5cc0e8d5864dd049b0b3576d9437ae7b4 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:16 +0530 Subject: [PATCH 2447/7155] regulator: qcom-rpmh: Update PMIC modes for PMIC5 Add the PMIC5 modes and use them pmic5 ldo and smps Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-4-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 52 +++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 391ed844a251..db6c085da65e 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -50,6 +50,20 @@ enum rpmh_regulator_type { #define PMIC4_BOB_MODE_AUTO 2 #define PMIC4_BOB_MODE_PWM 3 +#define PMIC5_LDO_MODE_RETENTION 3 +#define PMIC5_LDO_MODE_LPM 4 +#define PMIC5_LDO_MODE_HPM 7 + +#define PMIC5_SMPS_MODE_RETENTION 3 +#define PMIC5_SMPS_MODE_PFM 4 +#define PMIC5_SMPS_MODE_AUTO 6 +#define PMIC5_SMPS_MODE_PWM 7 + +#define PMIC5_BOB_MODE_PASS 2 +#define PMIC5_BOB_MODE_PFM 4 +#define PMIC5_BOB_MODE_AUTO 6 +#define PMIC5_BOB_MODE_PWM 7 + /** * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations * @regulator_type: RPMh accelerator type used to manage this @@ -488,6 +502,14 @@ static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = -EINVAL, }; +static const int pmic_mode_map_pmic5_ldo[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = PMIC5_LDO_MODE_RETENTION, + [REGULATOR_MODE_IDLE] = PMIC5_LDO_MODE_LPM, + [REGULATOR_MODE_NORMAL] = PMIC5_LDO_MODE_HPM, + [REGULATOR_MODE_FAST] = -EINVAL, +}; + static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode) { unsigned int mode; @@ -518,6 +540,14 @@ static const int pmic_mode_map_pmic4_smps[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = PMIC4_SMPS_MODE_PWM, }; +static const int pmic_mode_map_pmic5_smps[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = PMIC5_SMPS_MODE_RETENTION, + [REGULATOR_MODE_IDLE] = PMIC5_SMPS_MODE_PFM, + [REGULATOR_MODE_NORMAL] = PMIC5_SMPS_MODE_AUTO, + [REGULATOR_MODE_FAST] = PMIC5_SMPS_MODE_PWM, +}; + static unsigned int rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode) { @@ -552,6 +582,14 @@ static const int pmic_mode_map_pmic4_bob[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = PMIC4_BOB_MODE_PWM, }; +static const int pmic_mode_map_pmic5_bob[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = -EINVAL, + [REGULATOR_MODE_IDLE] = PMIC5_BOB_MODE_PFM, + [REGULATOR_MODE_NORMAL] = PMIC5_BOB_MODE_AUTO, + [REGULATOR_MODE_FAST] = PMIC5_BOB_MODE_PWM, +}; + static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode) { unsigned int mode; @@ -643,7 +681,7 @@ static const struct rpmh_vreg_hw_data pmic5_pldo = { .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), .n_voltages = 256, .hpm_min_load_uA = 10000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -653,7 +691,7 @@ static const struct rpmh_vreg_hw_data pmic5_pldo_lv = { .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000), .n_voltages = 63, .hpm_min_load_uA = 10000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -663,7 +701,7 @@ static const struct rpmh_vreg_hw_data pmic5_nldo = { .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000), .n_voltages = 124, .hpm_min_load_uA = 30000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -672,7 +710,7 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), .n_voltages = 216, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -681,7 +719,7 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), .n_voltages = 264, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -690,7 +728,7 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600), .n_voltages = 5, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -699,7 +737,7 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { .ops = &rpmh_regulator_vrm_bypass_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), .n_voltages = 136, - .pmic_mode_map = pmic_mode_map_pmic4_bob, + .pmic_mode_map = pmic_mode_map_pmic5_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; -- GitLab From 40073a9d53eac3f3ebf569aa9afd61301eff9190 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 19:01:00 +0800 Subject: [PATCH 2448/7155] ASoC: SOF: Intel: Add missing include file hdac_hda.h Building with SND_SOC_SOF_HDA_AUDIO_CODEC fails: sound/soc/sof/intel/hda-bus.c: In function sof_hda_bus_init: sound/soc/sof/intel/hda-bus.c:16:25: error: implicit declaration of function snd_soc_hdac_hda_get_ops; did you mean snd_soc_jack_add_gpiods? [-Werror=implicit-function-declaration] #define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() Reported-by: Hulk Robot Suggested-by: Takashi Iwai Fixes: d4ff1b3917a5 ("ASoC: SOF: Intel: Initialize hdaudio bus properly") Signed-off-by: YueHaibing Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-bus.c | 1 + sound/soc/sof/intel/hda.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 0caec3a070d3..1d2babdda9dd 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -13,6 +13,7 @@ #include "hda.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +#include "../../codecs/hdac_hda.h" #define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() #else #define sof_hda_ext_ops NULL diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7ca27000c34d..dd6c8ad62b3e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -23,9 +23,6 @@ #include #include "../ops.h" #include "hda.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -#include "../../codecs/hdac_hda.h" -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #include -- GitLab From 894efaf5236d3abf0512d8a71ae927ea9f99b509 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 18:21:50 +0800 Subject: [PATCH 2449/7155] staging: wusbcore: Fix build error without CONFIG_USB USB_WUSB should depends on CONFIG_USB, otherwise building fails drivers/staging/wusbcore/wusbhc.o: In function `wusbhc_giveback_urb': wusbhc.c:(.text+0xa28): undefined reference to `usb_hcd_giveback_urb' Reported-by: Hulk Robot Fixes: 71ed79b0e4be ("USB: Move wusbcore and UWB to staging as it is obsolete") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190809102150.66896-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wusbcore/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wusbcore/Kconfig b/drivers/staging/wusbcore/Kconfig index 056c60b4d57f..a559d023b508 100644 --- a/drivers/staging/wusbcore/Kconfig +++ b/drivers/staging/wusbcore/Kconfig @@ -4,7 +4,7 @@ # config USB_WUSB tristate "Enable Wireless USB extensions" - depends on UWB + depends on UWB && USB select CRYPTO select CRYPTO_AES select CRYPTO_CCM -- GitLab From 1f573cce48a2ebb35953034062ef01056b7d6a58 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Fri, 9 Aug 2019 11:20:33 +0100 Subject: [PATCH 2450/7155] device.h: Fix warnings for mismatched parameter names in comments Fix the warnings for parameter named as "driver" instead of the actual "drv" in the comments as reported by the kbuild robot. Reported-by: kbuild test robot Cc: Greg Kroah-Hartman Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20190809102033.28463-1-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index 23efaff5f10c..e32038f4ef56 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -479,7 +479,7 @@ struct device *driver_find_device(struct device_driver *drv, /** * driver_find_device_by_name - device iterator for locating a particular device * of a specific name. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @name: name of the device to match */ static inline struct device *driver_find_device_by_name(struct device_driver *drv, @@ -491,7 +491,7 @@ static inline struct device *driver_find_device_by_name(struct device_driver *dr /** * driver_find_device_by_of_node- device iterator for locating a particular device * by of_node pointer. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @np: of_node pointer to match. */ static inline struct device * @@ -504,7 +504,7 @@ driver_find_device_by_of_node(struct device_driver *drv, /** * driver_find_device_by_fwnode- device iterator for locating a particular device * by fwnode pointer. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @fwnode: fwnode pointer to match. */ static inline struct device * @@ -536,7 +536,7 @@ static inline struct device *driver_find_next_device(struct device_driver *drv, /** * driver_find_device_by_acpi_dev : device iterator for locating a particular * device matching the ACPI_COMPANION device. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @adev: ACPI_COMPANION device to match. */ static inline struct device * -- GitLab From 52f6f9d74f31078964ca1574f7bb612da7877ac8 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Tue, 26 Mar 2019 23:03:48 +0100 Subject: [PATCH 2451/7155] floppy: fix usercopy direction As sparse points out, these two copy_from_user() should actually be copy_to_user(). Fixes: 229b53c9bf4e ("take floppy compat ioctls to sodding floppy.c") Cc: stable@vger.kernel.org Acked-by: Alexander Popov Reviewed-by: Mukesh Ojha Signed-off-by: Jann Horn Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0469aceaa230..485865fd0412 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3780,7 +3780,7 @@ static int compat_getdrvprm(int drive, v.native_format = UDP->native_format; mutex_unlock(&floppy_mutex); - if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) + if (copy_to_user(arg, &v, sizeof(struct compat_floppy_drive_params))) return -EFAULT; return 0; } @@ -3816,7 +3816,7 @@ static int compat_getdrvstat(int drive, bool poll, v.bufblocks = UDRS->bufblocks; mutex_unlock(&floppy_mutex); - if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) + if (copy_to_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) return -EFAULT; return 0; Eintr: -- GitLab From d2d73d2fef421ca0d447946cc430fdf5c4c5b06a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Aug 2019 15:27:32 +0100 Subject: [PATCH 2452/7155] arm64: mm: Simplify definition of virt_addr_valid() _virt_addr_valid() is defined as the same value in two places and rolls its own version of virt_to_pfn() in both cases. Consolidate these definitions by inlining a simplified version directly into virt_addr_valid(). Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index ecc945ba8607..2c3c4b145e95 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -312,7 +312,6 @@ static inline void *phys_to_virt(phys_addr_t x) #if !defined(CONFIG_SPARSEMEM_VMEMMAP) || defined(CONFIG_DEBUG_VIRTUAL) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #else #define __virt_to_pgoff(kaddr) (((u64)(kaddr) - PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) #define __page_to_voff(kaddr) (((u64)(kaddr) - VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) @@ -326,15 +325,14 @@ static inline void *phys_to_virt(phys_addr_t x) }) #define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) + VMEMMAP_START)) - -#define _virt_addr_valid(kaddr) pfn_valid(__virt_to_phys((u64)(kaddr)) >> PAGE_SHIFT) #endif #endif #define _virt_addr_is_linear(kaddr) \ (__tag_reset((u64)(kaddr)) >= PAGE_OFFSET) + #define virt_addr_valid(kaddr) \ - (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr)) + (_virt_addr_is_linear(kaddr) && pfn_valid(virt_to_pfn(kaddr))) /* * Given that the GIC architecture permits ITS implementations that can only be -- GitLab From 9c1cac424c93d2b3122014e07a54b003ddedc168 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Aug 2019 15:39:37 +0100 Subject: [PATCH 2453/7155] arm64: mm: Really fix sparse warning in untagged_addr() untagged_addr() can be called with a '__user' pointer parameter and must therefore use '__force' casts both when passing this parameter through to sign_extend64() as a 'u64', but also when casting the 's64' return value back to the '__user' pointer type. Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 46c4c08a80a9..76e0b232a473 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -201,7 +201,7 @@ extern u64 vabits_user; * pass on to access_ok(), for instance. */ #define untagged_addr(addr) \ - ((__typeof__(addr))sign_extend64((__force u64)(addr), 55)) + ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55)) #ifdef CONFIG_KASAN_SW_TAGS #define __tag_shifted(tag) ((u64)(tag) << 56) -- GitLab From f43ec25aa5480515a39a405084ca8cb5e2c408aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Aug 2019 16:13:16 +0200 Subject: [PATCH 2454/7155] ALSA: hda - Inform too slow responses For the sake of debugging, show each response that took too long time and its corresponding last verb. Since such an error happens in series once when started, use the ratelimited variant for suppressing the flood. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_controller.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 156930d0c9d3..ec0608d44263 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -789,6 +789,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, unsigned long timeout; unsigned long loopcounter; int do_poll = 0; + bool warned = false; again: timeout = jiffies + msecs_to_jiffies(1000); @@ -808,9 +809,17 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, spin_unlock_irq(&bus->reg_lock); if (time_after(jiffies, timeout)) break; - if (hbus->needs_damn_long_delay || loopcounter > 3000) +#define LOOP_COUNT_MAX 3000 + if (hbus->needs_damn_long_delay || + loopcounter > LOOP_COUNT_MAX) { + if (loopcounter > LOOP_COUNT_MAX && !warned) { + dev_dbg_ratelimited(chip->card->dev, + "too slow response, last cmd=%#08x\n", + bus->last_cmd[addr]); + warned = true; + } msleep(2); /* temporary workaround */ - else { + } else { udelay(10); cond_resched(); } -- GitLab From a2ef03fe617a8365fb7794531b11ba587509a9b9 Mon Sep 17 00:00:00 2001 From: Tomas Espeleta Date: Fri, 9 Aug 2019 16:37:54 +0200 Subject: [PATCH 2455/7155] ALSA: hda - Add a quirk model for fixing Huawei Matebook X right speaker [ This is rather a revival of the patch Tomas sent in months ago, but applying only with the quirk model option -- tiwai ] Hard coded coefficients to make Huawuei Matebook X right speaker work. The Matebook X has a ALC298, please refer to bug 197801 on how these numbers were reverse engineered from the Windows driver The reversed engineered sequence represents a repeating pattern of verbs, and the only values that are changing periodically are written on indexes 0x23 and 0x25: 0x500, 0x23 0x400, VALUE1 0x500, 0x25 0x400, VALUE2 * skipped reading sequences (0x500 - 0xc00 sequences are ignored) * static values from reverse engineering are used NOTE: since a significant risk is still considered, this is provided as an experimental fix that isn't applied as default for now. For enabling the fix, you'll have to choose huawei-mbx-stereo via model option of snd-hda-intel module. If we get feedback from users that this works stably, we may apply it per default. [ Some coding style fixes and replacement with AC_VERB_* by tiwai ] BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=197801 Signed-off-by: Tomas Espeleta Signed-off-by: Takashi Iwai --- Documentation/sound/hd-audio/models.rst | 3 + sound/pci/hda/patch_realtek.c | 74 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index 7d7c191102a7..11298f0ce44d 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst @@ -260,6 +260,9 @@ alc295-hp-x360 HP Spectre X360 fixups alc-sense-combo Headset button support for Chrome platform +huawei-mbx-stereo + Enable initialization verbs for Huawei MBX stereo speakers; + might be risky, try this at your own risk ALC66x/67x/892 ============== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index de224cbea7a0..cb7baa65b298 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3762,6 +3762,72 @@ static void alc269_x101_hp_automute_hook(struct hda_codec *codec, vref); } +/* + * Magic sequence to make Huawei Matebook X right speaker working (bko#197801) + */ +struct hda_alc298_mbxinit { + unsigned char value_0x23; + unsigned char value_0x25; +}; + +static void alc298_huawei_mbx_stereo_seq(struct hda_codec *codec, + const struct hda_alc298_mbxinit *initval, + bool first) +{ + snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x0); + alc_write_coef_idx(codec, 0x26, 0xb000); + + if (first) + snd_hda_codec_write(codec, 0x21, 0, AC_VERB_GET_PIN_SENSE, 0x0); + + snd_hda_codec_write(codec, 0x6, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x80); + alc_write_coef_idx(codec, 0x26, 0xf000); + alc_write_coef_idx(codec, 0x23, initval->value_0x23); + + if (initval->value_0x23 != 0x1e) + alc_write_coef_idx(codec, 0x25, initval->value_0x25); + + snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x26); + snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb010); +} + +static void alc298_fixup_huawei_mbx_stereo(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + /* Initialization magic */ + static const struct hda_alc298_mbxinit dac_init[] = { + {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00}, + {0x10, 0x00}, {0x1a, 0x40}, {0x1b, 0x82}, {0x1c, 0x00}, + {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00}, + {0x20, 0xc2}, {0x21, 0xc8}, {0x22, 0x26}, {0x23, 0x24}, + {0x27, 0xff}, {0x28, 0xff}, {0x29, 0xff}, {0x2a, 0x8f}, + {0x2b, 0x02}, {0x2c, 0x48}, {0x2d, 0x34}, {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, + {0x34, 0x00}, {0x35, 0x01}, {0x36, 0x93}, {0x37, 0x0c}, + {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0xf8}, {0x38, 0x80}, + {} + }; + const struct hda_alc298_mbxinit *seq; + + if (action != HDA_FIXUP_ACT_INIT) + return; + + /* Start */ + snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x00); + snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x80); + alc_write_coef_idx(codec, 0x26, 0xf000); + alc_write_coef_idx(codec, 0x22, 0x31); + alc_write_coef_idx(codec, 0x23, 0x0b); + alc_write_coef_idx(codec, 0x25, 0x00); + snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x26); + snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb010); + + for (seq = dac_init; seq->value_0x23; seq++) + alc298_huawei_mbx_stereo_seq(codec, seq, seq == dac_init); +} + static void alc269_fixup_x101_headset_mic(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -5787,6 +5853,7 @@ enum { ALC255_FIXUP_DUMMY_LINEOUT_VERB, ALC255_FIXUP_DELL_HEADSET_MIC, ALC256_FIXUP_HUAWEI_MACH_WX9_PINS, + ALC298_FIXUP_HUAWEI_MBX_STEREO, ALC295_FIXUP_HP_X360, ALC221_FIXUP_HP_HEADSET_MIC, ALC285_FIXUP_LENOVO_HEADPHONE_NOISE, @@ -6095,6 +6162,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC255_FIXUP_MIC_MUTE_LED }, + [ALC298_FIXUP_HUAWEI_MBX_STEREO] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc298_fixup_huawei_mbx_stereo, + .chained = true, + .chain_id = ALC255_FIXUP_MIC_MUTE_LED + }, [ALC269_FIXUP_ASUS_X101_FUNC] = { .type = HDA_FIXUP_FUNC, .v.func = alc269_fixup_x101_headset_mic, @@ -7272,6 +7345,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-headset-jack"}, {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-chrome-book"}, {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"}, + {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"}, {} }; #define ALC225_STANDARD_PINS \ -- GitLab From b9c6ff94e43a0ee053e0c1d983fba1ac4953b762 Mon Sep 17 00:00:00 2001 From: "Suthikulpanit, Suravee" Date: Tue, 23 Jul 2019 19:00:37 +0000 Subject: [PATCH 2456/7155] iommu/amd: Re-factor guest virtual APIC (de-)activation code Re-factore the logic for activate/deactivate guest virtual APIC mode (GAM) into helper functions, and export them for other drivers (e.g. SVM). to support run-time activate/deactivate of SVM AVIC. Cc: Joerg Roedel Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 85 +++++++++++++++++++++++---------- drivers/iommu/amd_iommu_types.h | 9 ++++ include/linux/amd-iommu.h | 12 +++++ 3 files changed, 82 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index b607a92791d3..008da21a2592 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4313,13 +4313,62 @@ static const struct irq_domain_ops amd_ir_domain_ops = { .deactivate = irq_remapping_deactivate, }; +int amd_iommu_activate_guest_mode(void *data) +{ + struct amd_ir_data *ir_data = (struct amd_ir_data *)data; + struct irte_ga *entry = (struct irte_ga *) ir_data->entry; + + if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || + !entry || entry->lo.fields_vapic.guest_mode) + return 0; + + entry->lo.val = 0; + entry->hi.val = 0; + + entry->lo.fields_vapic.guest_mode = 1; + entry->lo.fields_vapic.ga_log_intr = 1; + entry->hi.fields.ga_root_ptr = ir_data->ga_root_ptr; + entry->hi.fields.vector = ir_data->ga_vector; + entry->lo.fields_vapic.ga_tag = ir_data->ga_tag; + + return modify_irte_ga(ir_data->irq_2_irte.devid, + ir_data->irq_2_irte.index, entry, NULL); +} +EXPORT_SYMBOL(amd_iommu_activate_guest_mode); + +int amd_iommu_deactivate_guest_mode(void *data) +{ + struct amd_ir_data *ir_data = (struct amd_ir_data *)data; + struct irte_ga *entry = (struct irte_ga *) ir_data->entry; + struct irq_cfg *cfg = ir_data->cfg; + + if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || + !entry || !entry->lo.fields_vapic.guest_mode) + return 0; + + entry->lo.val = 0; + entry->hi.val = 0; + + entry->lo.fields_remap.dm = apic->irq_dest_mode; + entry->lo.fields_remap.int_type = apic->irq_delivery_mode; + entry->hi.fields.vector = cfg->vector; + entry->lo.fields_remap.destination = + APICID_TO_IRTE_DEST_LO(cfg->dest_apicid); + entry->hi.fields.destination = + APICID_TO_IRTE_DEST_HI(cfg->dest_apicid); + + return modify_irte_ga(ir_data->irq_2_irte.devid, + ir_data->irq_2_irte.index, entry, NULL); +} +EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode); + static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) { + int ret; struct amd_iommu *iommu; struct amd_iommu_pi_data *pi_data = vcpu_info; struct vcpu_data *vcpu_pi_info = pi_data->vcpu_data; struct amd_ir_data *ir_data = data->chip_data; - struct irte_ga *irte = (struct irte_ga *) ir_data->entry; struct irq_2_irte *irte_info = &ir_data->irq_2_irte; struct iommu_dev_data *dev_data = search_dev_data(irte_info->devid); @@ -4330,6 +4379,7 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) if (!dev_data || !dev_data->use_vapic) return 0; + ir_data->cfg = irqd_cfg(data); pi_data->ir_data = ir_data; /* Note: @@ -4348,37 +4398,24 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) pi_data->prev_ga_tag = ir_data->cached_ga_tag; if (pi_data->is_guest_mode) { - /* Setting */ - irte->hi.fields.ga_root_ptr = (pi_data->base >> 12); - irte->hi.fields.vector = vcpu_pi_info->vector; - irte->lo.fields_vapic.ga_log_intr = 1; - irte->lo.fields_vapic.guest_mode = 1; - irte->lo.fields_vapic.ga_tag = pi_data->ga_tag; - - ir_data->cached_ga_tag = pi_data->ga_tag; + ir_data->ga_root_ptr = (pi_data->base >> 12); + ir_data->ga_vector = vcpu_pi_info->vector; + ir_data->ga_tag = pi_data->ga_tag; + ret = amd_iommu_activate_guest_mode(ir_data); + if (!ret) + ir_data->cached_ga_tag = pi_data->ga_tag; } else { - /* Un-Setting */ - struct irq_cfg *cfg = irqd_cfg(data); - - irte->hi.val = 0; - irte->lo.val = 0; - irte->hi.fields.vector = cfg->vector; - irte->lo.fields_remap.guest_mode = 0; - irte->lo.fields_remap.destination = - APICID_TO_IRTE_DEST_LO(cfg->dest_apicid); - irte->hi.fields.destination = - APICID_TO_IRTE_DEST_HI(cfg->dest_apicid); - irte->lo.fields_remap.int_type = apic->irq_delivery_mode; - irte->lo.fields_remap.dm = apic->irq_dest_mode; + ret = amd_iommu_deactivate_guest_mode(ir_data); /* * This communicates the ga_tag back to the caller * so that it can do all the necessary clean up. */ - ir_data->cached_ga_tag = 0; + if (!ret) + ir_data->cached_ga_tag = 0; } - return modify_irte_ga(irte_info->devid, irte_info->index, irte, ir_data); + return ret; } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 64edd5a9694c..9ac229e92b07 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -873,6 +873,15 @@ struct amd_ir_data { struct msi_msg msi_entry; void *entry; /* Pointer to union irte or struct irte_ga */ void *ref; /* Pointer to the actual irte */ + + /** + * Store information for activate/de-activate + * Guest virtual APIC mode during runtime. + */ + struct irq_cfg *cfg; + int ga_vector; + int ga_root_ptr; + int ga_tag; }; struct amd_irte_ops { diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 4a4d00646040..21e950e4ab62 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h @@ -184,6 +184,9 @@ extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)); extern int amd_iommu_update_ga(int cpu, bool is_run, void *data); +extern int amd_iommu_activate_guest_mode(void *data); +extern int amd_iommu_deactivate_guest_mode(void *data); + #else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ static inline int @@ -198,6 +201,15 @@ amd_iommu_update_ga(int cpu, bool is_run, void *data) return 0; } +static inline int amd_iommu_activate_guest_mode(void *data) +{ + return 0; +} + +static inline int amd_iommu_deactivate_guest_mode(void *data) +{ + return 0; +} #endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ #endif /* _ASM_X86_AMD_IOMMU_H */ -- GitLab From 086f9efae7e96ac2c829d33ca3d513caa3bbb225 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:22 -0700 Subject: [PATCH 2457/7155] iommu: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Joerg Roedel Cc: iommu@lists.linux-foundation.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Signed-off-by: Joerg Roedel --- drivers/iommu/exynos-iommu.c | 4 +--- drivers/iommu/msm_iommu.c | 1 - drivers/iommu/qcom_iommu.c | 4 +--- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index b0c1e5f9daae..1934c16a5abc 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -583,10 +583,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) return PTR_ERR(data->sfrbase); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "Unable to find IRQ resource\n"); + if (irq <= 0) return irq; - } ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, dev_name(dev), data); diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index b25e2eb9e038..3df9266abe65 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -750,7 +750,6 @@ static int msm_iommu_probe(struct platform_device *pdev) iommu->irq = platform_get_irq(pdev, 0); if (iommu->irq < 0) { - dev_err(iommu->dev, "could not get iommu irq\n"); ret = -ENODEV; goto fail; } diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 34d0b9783b3e..fb45486c6d14 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -696,10 +696,8 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev) return PTR_ERR(ctx->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get irq\n"); + if (irq < 0) return -ENODEV; - } /* clear IRQs before registering fault handler, just in case the * boot-loader left us a surprise: -- GitLab From 3846a3b9511c5166082a93536d919a9c42abcd91 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:45 +0300 Subject: [PATCH 2458/7155] iommu/omap: fix boot issue on remoteprocs with AMMU/Unicache Support has been added to the OMAP IOMMU driver to fix a boot hang issue on OMAP remoteprocs with AMMU/Unicache, caused by an improper AMMU/Unicache state upon initial deassertion of the processor reset. The issue is described in detail in the next three paragraphs. All the Cortex M3/M4 IPU processor subsystems in OMAP SoCs have a AMMU/Unicache IP that dictates the memory attributes for addresses seen by the processor cores. The AMMU/Unicache is configured/enabled by the SCACHE_CONFIG.BYPASS bit - a value of 1 enables the cache and mandates all addresses accessed by M3/M4 be defined in the AMMU. This bit is not programmable from the host processor. The M3/M4 boot sequence starts out with the AMMU/Unicache in disabled state, and SYS/BIOS programs the AMMU regions and enables the Unicache during one of its initial boot steps. This SCACHE_CONFIG.BYPASS bit is however enabled by default whenever a RET reset is applied to the IP, irrespective of whether it was previously enabled or not. The AMMU registers lose their context whenever this reset is applied. The reset is effective as long as the MMU portion of the subsystem is enabled and clocked. This behavior is common to all the IPU and DSP subsystems that have an AMMU/Unicache. The IPU boot sequence involves enabling and programming the MMU, and loading the processor and releasing the reset(s) for the processor. The PM setup code currently sets the target state for most of the power domains to RET. The L2 MMU can be enabled, programmed and accessed properly just fine with the domain in hardware supervised mode, while the power domain goes through a RET->ON->RET transition during the programming sequence. However, the ON->RET transition asserts a RET reset, and the SCACHE_CONFIG.BYPASS bit gets auto-set. An AMMU fault is thrown immediately when the M3/M4 core's reset is released since the first instruction address itself will not be defined in any valid AMMU regions. The ON->RET transition happens automatically on the power domain after enabling the iommu due to the hardware supervised mode. This patch adds and invokes the .set_pwrdm_constraint pdata ops, if present, during the OMAP IOMMU enable and disable functions to resolve the above boot hang issue. The ops will allow to invoke a mach-omap2 layer API pwrdm_set_next_pwrst() in a multi-arch kernel environment. The ops also returns the current power domain state while enforcing the constraint so that the driver can store it and use it to set back the power domain state while releasing the constraint. The pdata ops implementation restricts the target power domain to ON during enable, and back to the original power domain state during disable, and thereby eliminating the conditions for the boot issue. The implementation is effective only when the original power domain state is either RET or OFF, and is a no-op when it is ON or INACTIVE. The .set_pwrdm_constraint ops need to be plugged in pdata-quirks for the affected remote processors to be able to boot properly. Note that the current issue is seen only on kernels with the affected power domains programmed to enter RET. For eg., IPU1 on DRA7xx is in a separate domain and is susceptible to this bug, while the IPU2 subsystem is within CORE power domain, and CORE RET is not supported on this SoC. IPUs on OMAP4 and OMAP5 are also susceptible since they are in CORE power domain, and CORE RET is a valid power target on these SoCs. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- arch/arm/mach-omap2/Makefile | 2 ++ arch/arm/mach-omap2/omap-iommu.c | 43 ++++++++++++++++++++++++ drivers/iommu/omap-iommu.c | 17 ++++++++++ drivers/iommu/omap-iommu.h | 2 ++ include/linux/platform_data/iommu-omap.h | 2 ++ 5 files changed, 66 insertions(+) create mode 100644 arch/arm/mach-omap2/omap-iommu.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 600650551621..d4f11c5070ae 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -229,3 +229,5 @@ include/generated/ti-pm-asm-offsets.h: arch/arm/mach-omap2/pm-asm-offsets.s FORC $(obj)/sleep33xx.o $(obj)/sleep43xx.o: include/generated/ti-pm-asm-offsets.h targets += pm-asm-offsets.s + +obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c new file mode 100644 index 000000000000..f1a6ece8108e --- /dev/null +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * OMAP IOMMU quirks for various TI SoCs + * + * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/ + * Suman Anna + */ + +#include +#include + +#include "omap_hwmod.h" +#include "omap_device.h" +#include "powerdomain.h" + +int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request, + u8 *pwrst) +{ + struct powerdomain *pwrdm; + struct omap_device *od; + u8 next_pwrst; + + od = to_omap_device(pdev); + if (!od) + return -ENODEV; + + if (od->hwmods_cnt != 1) + return -EINVAL; + + pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]); + if (!pwrdm) + return -EINVAL; + + if (request) + *pwrst = pwrdm_read_next_pwrst(pwrdm); + + if (*pwrst > PWRDM_POWER_RET) + return 0; + + next_pwrst = request ? PWRDM_POWER_ON : *pwrst; + + return pwrdm_set_next_pwrst(pwrdm, next_pwrst); +} diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index dfb961d8c21b..84b99d5841ae 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -190,6 +190,14 @@ static int iommu_enable(struct omap_iommu *obj) struct platform_device *pdev = to_platform_device(obj->dev); struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); + if (pdata && pdata->set_pwrdm_constraint) { + err = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst); + if (err) { + dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n", + err); + } + } + if (pdata && pdata->deassert_reset) { err = pdata->deassert_reset(pdev, pdata->reset_name); if (err) { @@ -209,6 +217,7 @@ static void iommu_disable(struct omap_iommu *obj) { struct platform_device *pdev = to_platform_device(obj->dev); struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); + int ret; omap2_iommu_disable(obj); @@ -216,6 +225,14 @@ static void iommu_disable(struct omap_iommu *obj) if (pdata && pdata->assert_reset) pdata->assert_reset(pdev, pdata->reset_name); + + if (pdata && pdata->set_pwrdm_constraint) { + ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst); + if (ret) { + dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n", + ret); + } + } } /* diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 09968a02d291..aac1ca65ef9d 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h @@ -78,6 +78,8 @@ struct omap_iommu { struct iommu_device iommu; struct iommu_group *group; + + u8 pwrst; }; /** diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index 44d913a7580c..1ed60265a20e 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h @@ -13,4 +13,6 @@ struct iommu_platform_data { const char *reset_name; int (*assert_reset)(struct platform_device *pdev, const char *name); int (*deassert_reset)(struct platform_device *pdev, const char *name); + int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request, + u8 *pwrst); }; -- GitLab From 74c116df66d25a9fb48d44ce545a505edc5fbbba Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:46 +0300 Subject: [PATCH 2459/7155] iommu/omap: add pdata ops for omap_device_enable/idle Add two new platform data ops to allow the OMAP iommu driver to be able to invoke the omap_device_enable and omap_device_idle from within the driver. These are being added to streamline the sequence between managing the hard reset lines and the clocks during the suspend path, as the default device pm_domain callback sequences in omap_device layer are not conducive for the OMAP IOMMU driver. This could have been done by expanding the existing pdata ops for reset management (like in the OMAP remoteproc driver), but this was chosen to avoid adding additional code in the separate file in the mach-omap2 layer. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- include/linux/platform_data/iommu-omap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index 1ed60265a20e..8474a0208b34 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h @@ -13,6 +13,8 @@ struct iommu_platform_data { const char *reset_name; int (*assert_reset)(struct platform_device *pdev, const char *name); int (*deassert_reset)(struct platform_device *pdev, const char *name); + int (*device_enable)(struct platform_device *pdev); + int (*device_idle)(struct platform_device *pdev); int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request, u8 *pwrst); }; -- GitLab From db8918f61d51b87aaf7554ab7647ccdb7dbd739f Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:47 +0300 Subject: [PATCH 2460/7155] iommu/omap: streamline enable/disable through runtime pm callbacks The OMAP IOMMU devices are typically present within the respective client processor subsystem and have their own dedicated hard-reset line. Enabling an IOMMU requires the reset line to be deasserted and the clocks to be enabled before programming the necessary IOMMU registers. The IOMMU disable sequence follow the reverse order of enabling. The OMAP IOMMU driver programs the reset lines through pdata ops to invoke the omap_device_assert/deassert_hardreset API. The clocks are managed through the pm_runtime framework, and the callbacks associated with the device's pm_domain, implemented in the omap_device layer. Streamline the enable and disable sequences in the OMAP IOMMU driver by implementing all the above operations within the runtime pm callbacks. All the OMAP devices have device pm_domain callbacks plugged in the omap_device layer for automatic runtime management of the clocks. Invoking the reset management functions within the runtime pm callbacks in OMAP IOMMU driver therefore requires that the default device's pm domain callbacks in the omap_device layer be reset, as the ordering sequence for managing the reset lines and clocks from the pm_domain callbacks don't gel well with the implementation in the IOMMU driver callbacks. The omap_device_enable/omap_device_idle functions are invoked through the newly added pdata ops. Consolidating all the device management sequences within the runtime pm callbacks allows the driver to easily support both system suspend/resume and runtime suspend/resume using common code. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 139 ++++++++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 40 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 84b99d5841ae..fbceae3c2ee7 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -186,53 +186,18 @@ static void omap2_iommu_disable(struct omap_iommu *obj) static int iommu_enable(struct omap_iommu *obj) { - int err; - struct platform_device *pdev = to_platform_device(obj->dev); - struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); - - if (pdata && pdata->set_pwrdm_constraint) { - err = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst); - if (err) { - dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n", - err); - } - } - - if (pdata && pdata->deassert_reset) { - err = pdata->deassert_reset(pdev, pdata->reset_name); - if (err) { - dev_err(obj->dev, "deassert_reset failed: %d\n", err); - return err; - } - } - - pm_runtime_get_sync(obj->dev); + int ret; - err = omap2_iommu_enable(obj); + ret = pm_runtime_get_sync(obj->dev); + if (ret < 0) + pm_runtime_put_noidle(obj->dev); - return err; + return ret < 0 ? ret : 0; } static void iommu_disable(struct omap_iommu *obj) { - struct platform_device *pdev = to_platform_device(obj->dev); - struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev); - int ret; - - omap2_iommu_disable(obj); - pm_runtime_put_sync(obj->dev); - - if (pdata && pdata->assert_reset) - pdata->assert_reset(pdev, pdata->reset_name); - - if (pdata && pdata->set_pwrdm_constraint) { - ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst); - if (ret) { - dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n", - ret); - } - } } /* @@ -927,6 +892,85 @@ static void omap_iommu_detach(struct omap_iommu *obj) dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); } +/** + * omap_iommu_runtime_suspend - disable an iommu device + * @dev: iommu device + * + * This function performs all that is necessary to disable an + * IOMMU device, either during final detachment from a client + * device, or during system/runtime suspend of the device. This + * includes programming all the appropriate IOMMU registers, and + * managing the associated omap_hwmod's state and the device's + * reset line. + **/ +static int omap_iommu_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iommu_platform_data *pdata = dev_get_platdata(dev); + struct omap_iommu *obj = to_iommu(dev); + int ret; + + omap2_iommu_disable(obj); + + if (pdata && pdata->device_idle) + pdata->device_idle(pdev); + + if (pdata && pdata->assert_reset) + pdata->assert_reset(pdev, pdata->reset_name); + + if (pdata && pdata->set_pwrdm_constraint) { + ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst); + if (ret) { + dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n", + ret); + } + } + + return 0; +} + +/** + * omap_iommu_runtime_resume - enable an iommu device + * @dev: iommu device + * + * This function performs all that is necessary to enable an + * IOMMU device, either during initial attachment to a client + * device, or during system/runtime resume of the device. This + * includes programming all the appropriate IOMMU registers, and + * managing the associated omap_hwmod's state and the device's + * reset line. + **/ +static int omap_iommu_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iommu_platform_data *pdata = dev_get_platdata(dev); + struct omap_iommu *obj = to_iommu(dev); + int ret = 0; + + if (pdata && pdata->set_pwrdm_constraint) { + ret = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst); + if (ret) { + dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n", + ret); + } + } + + if (pdata && pdata->deassert_reset) { + ret = pdata->deassert_reset(pdev, pdata->reset_name); + if (ret) { + dev_err(dev, "deassert_reset failed: %d\n", ret); + return ret; + } + } + + if (pdata && pdata->device_enable) + pdata->device_enable(pdev); + + ret = omap2_iommu_enable(obj); + + return ret; +} + static bool omap_iommu_can_register(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1001,6 +1045,15 @@ static int omap_iommu_probe(struct platform_device *pdev) if (!obj) return -ENOMEM; + /* + * self-manage the ordering dependencies between omap_device_enable/idle + * and omap_device_assert/deassert_hardreset API + */ + if (pdev->dev.pm_domain) { + dev_dbg(&pdev->dev, "device pm_domain is being reset\n"); + pdev->dev.pm_domain = NULL; + } + obj->name = dev_name(&pdev->dev); obj->nr_tlb_entries = 32; err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries); @@ -1089,6 +1142,11 @@ static int omap_iommu_remove(struct platform_device *pdev) return 0; } +static const struct dev_pm_ops omap_iommu_pm_ops = { + SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend, + omap_iommu_runtime_resume, NULL) +}; + static const struct of_device_id omap_iommu_of_match[] = { { .compatible = "ti,omap2-iommu" }, { .compatible = "ti,omap4-iommu" }, @@ -1102,6 +1160,7 @@ static struct platform_driver omap_iommu_driver = { .remove = omap_iommu_remove, .driver = { .name = "omap-iommu", + .pm = &omap_iommu_pm_ops, .of_match_table = of_match_ptr(omap_iommu_of_match), }, }; -- GitLab From c3b44a063d3b4d9b5afabaf5ab2e3fc11518dc84 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:48 +0300 Subject: [PATCH 2461/7155] iommu/omap: add logic to save/restore locked TLBs The MMUs provide a mechanism to lock TLB entries to avoid eviction and fetching of frequently used page table entries. These TLBs lose context when the MMUs are turned OFF. Add the logic to save and restore these locked TLBS during suspend and resume respectively. There are no locked TLBs during initial power ON, and they need not be saved during final shutdown. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 61 ++++++++++++++++++++++++++++++++++++-- drivers/iommu/omap-iommu.h | 3 ++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index fbceae3c2ee7..7640f2bd7c81 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -883,15 +883,55 @@ static void omap_iommu_detach(struct omap_iommu *obj) dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE, DMA_TO_DEVICE); - iommu_disable(obj); obj->pd_dma = 0; obj->iopgd = NULL; + iommu_disable(obj); spin_unlock(&obj->iommu_lock); dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); } +static void omap_iommu_save_tlb_entries(struct omap_iommu *obj) +{ + struct iotlb_lock lock; + struct cr_regs cr; + struct cr_regs *tmp; + int i; + + /* check if there are any locked tlbs to save */ + iotlb_lock_get(obj, &lock); + obj->num_cr_ctx = lock.base; + if (!obj->num_cr_ctx) + return; + + tmp = obj->cr_ctx; + for_each_iotlb_cr(obj, obj->num_cr_ctx, i, cr) + * tmp++ = cr; +} + +static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj) +{ + struct iotlb_lock l; + struct cr_regs *tmp; + int i; + + /* no locked tlbs to restore */ + if (!obj->num_cr_ctx) + return; + + l.base = 0; + tmp = obj->cr_ctx; + for (i = 0; i < obj->num_cr_ctx; i++, tmp++) { + l.vict = i; + iotlb_lock_set(obj, &l); + iotlb_load_cr(obj, tmp); + } + l.base = obj->num_cr_ctx; + l.vict = i; + iotlb_lock_set(obj, &l); +} + /** * omap_iommu_runtime_suspend - disable an iommu device * @dev: iommu device @@ -901,7 +941,8 @@ static void omap_iommu_detach(struct omap_iommu *obj) * device, or during system/runtime suspend of the device. This * includes programming all the appropriate IOMMU registers, and * managing the associated omap_hwmod's state and the device's - * reset line. + * reset line. This function also saves the context of any + * locked TLBs if suspending. **/ static int omap_iommu_runtime_suspend(struct device *dev) { @@ -910,6 +951,10 @@ static int omap_iommu_runtime_suspend(struct device *dev) struct omap_iommu *obj = to_iommu(dev); int ret; + /* save the TLBs only during suspend, and not for power down */ + if (obj->domain && obj->iopgd) + omap_iommu_save_tlb_entries(obj); + omap2_iommu_disable(obj); if (pdata && pdata->device_idle) @@ -938,7 +983,8 @@ static int omap_iommu_runtime_suspend(struct device *dev) * device, or during system/runtime resume of the device. This * includes programming all the appropriate IOMMU registers, and * managing the associated omap_hwmod's state and the device's - * reset line. + * reset line. The function also restores any locked TLBs if + * resuming after a suspend. **/ static int omap_iommu_runtime_resume(struct device *dev) { @@ -966,6 +1012,10 @@ static int omap_iommu_runtime_resume(struct device *dev) if (pdata && pdata->device_enable) pdata->device_enable(pdev); + /* restore the TLBs only during resume, and not for power up */ + if (obj->domain) + omap_iommu_restore_tlb_entries(obj); + ret = omap2_iommu_enable(obj); return ret; @@ -1066,6 +1116,11 @@ static int omap_iommu_probe(struct platform_device *pdev) obj->dev = &pdev->dev; obj->ctx = (void *)obj + sizeof(*obj); + obj->cr_ctx = devm_kzalloc(&pdev->dev, + sizeof(*obj->cr_ctx) * obj->nr_tlb_entries, + GFP_KERNEL); + if (!obj->cr_ctx) + return -ENOMEM; spin_lock_init(&obj->iommu_lock); spin_lock_init(&obj->page_table_lock); diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index aac1ca65ef9d..1d15aa857634 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h @@ -73,6 +73,9 @@ struct omap_iommu { void *ctx; /* iommu context: registres saved area */ + struct cr_regs *cr_ctx; + u32 num_cr_ctx; + int has_bus_err_back; u32 id; -- GitLab From c4206c4e190bd272e4e86389613f2cded4609ba1 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:49 +0300 Subject: [PATCH 2462/7155] iommu/omap: Add system suspend/resume support The MMU registers for the remote processors lose their context in Open Switch Retention (OSWR) or device OFF modes. Hence, the context of the IOMMU needs to be saved before it is put into any of these lower power state (OSWR/OFF) and restored before it is powered up to ON again. The IOMMUs need to be active as long as the client devices that are present behind the IOMMU are active. This patch adds the dev_pm_ops callbacks to provide the system suspend/resume functionality through the appropriate runtime PM callbacks. The PM runtime_resume and runtime_suspend callbacks are already used to enable, configure and disable the IOMMUs during the attaching and detaching of the client devices to the IOMMUs, and the new PM callbacks reuse the same code by invoking the pm_runtime_force_suspend() and pm_runtime_force_resume() API. The functionality in dev_pm_ops .prepare() checks if the IOMMU device was already runtime suspended, and skips invoking the suspend/resume PM callbacks. The suspend/resume PM callbacks are plugged in through the 'late' pm ops to ensure that the IOMMU devices will be suspended only after its master devices (remoteproc devices) are suspended and restored before them. NOTE: There are two other existing API, omap_iommu_save_ctx() and omap_iommu_restore_ctx(). These are left as is to support suspend/resume of devices on legacy OMAP3 SoC. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 7640f2bd7c81..ef62ac9057bb 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -65,6 +65,9 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom) /** * omap_iommu_save_ctx - Save registers for pm off-mode support * @dev: client device + * + * This should be treated as an deprecated API. It is preserved only + * to maintain existing functionality for OMAP3 ISP driver. **/ void omap_iommu_save_ctx(struct device *dev) { @@ -92,6 +95,9 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); /** * omap_iommu_restore_ctx - Restore registers for pm off-mode support * @dev: client device + * + * This should be treated as an deprecated API. It is preserved only + * to maintain existing functionality for OMAP3 ISP driver. **/ void omap_iommu_restore_ctx(struct device *dev) { @@ -1021,6 +1027,23 @@ static int omap_iommu_runtime_resume(struct device *dev) return ret; } +/** + * omap_iommu_suspend_prepare - prepare() dev_pm_ops implementation + * @dev: iommu device + * + * This function performs the necessary checks to determine if the IOMMU + * device needs suspending or not. The function checks if the runtime_pm + * status of the device is suspended, and returns 1 in that case. This + * results in the PM core to skip invoking any of the Sleep PM callbacks + * (suspend, suspend_late, resume, resume_early etc). + */ +static int omap_iommu_prepare(struct device *dev) +{ + if (pm_runtime_status_suspended(dev)) + return 1; + return 0; +} + static bool omap_iommu_can_register(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1198,6 +1221,9 @@ static int omap_iommu_remove(struct platform_device *pdev) } static const struct dev_pm_ops omap_iommu_pm_ops = { + .prepare = omap_iommu_prepare, + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend, omap_iommu_runtime_resume, NULL) }; -- GitLab From d9c4d8a6cc0f852adf3829fbe40e2e3f6213b0c6 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 7 Aug 2019 11:26:50 +0300 Subject: [PATCH 2463/7155] iommu/omap: introduce new API for runtime suspend/resume control This patch adds the support for the OMAP IOMMUs to be suspended during the auto suspend/resume of the OMAP remoteproc devices. The remote processors are auto suspended after a certain time of idle or inactivity period. This is done by introducing two new API, omap_iommu_domain_deactivate() and omap_iommu_domain_activate() to allow the client users/master devices of the IOMMU devices to deactivate & activate the IOMMU devices from their runtime suspend/resume operations. There is no API exposed by the IOMMU layer at present, and so these new API are added directly in the OMAP IOMMU driver to minimize framework changes. The API simply decrements and increments the runtime usage count of the IOMMU devices and let the context be saved/restored using the existing runtime pm callbacks. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 58 ++++++++++++++++++++++++++++++++++++++ include/linux/omap-iommu.h | 8 ++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index ef62ac9057bb..ecf14001beed 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -938,6 +938,64 @@ static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj) iotlb_lock_set(obj, &l); } +/** + * omap_iommu_domain_deactivate - deactivate attached iommu devices + * @domain: iommu domain attached to the target iommu device + * + * This API allows the client devices of IOMMU devices to suspend + * the IOMMUs they control at runtime, after they are idled and + * suspended all activity. System Suspend will leverage the PM + * driver late callbacks. + **/ +int omap_iommu_domain_deactivate(struct iommu_domain *domain) +{ + struct omap_iommu_domain *omap_domain = to_omap_domain(domain); + struct omap_iommu_device *iommu; + struct omap_iommu *oiommu; + int i; + + if (!omap_domain->dev) + return 0; + + iommu = omap_domain->iommus; + iommu += (omap_domain->num_iommus - 1); + for (i = 0; i < omap_domain->num_iommus; i++, iommu--) { + oiommu = iommu->iommu_dev; + pm_runtime_put_sync(oiommu->dev); + } + + return 0; +} +EXPORT_SYMBOL_GPL(omap_iommu_domain_deactivate); + +/** + * omap_iommu_domain_activate - activate attached iommu devices + * @domain: iommu domain attached to the target iommu device + * + * This API allows the client devices of IOMMU devices to resume the + * IOMMUs they control at runtime, before they can resume operations. + * System Resume will leverage the PM driver late callbacks. + **/ +int omap_iommu_domain_activate(struct iommu_domain *domain) +{ + struct omap_iommu_domain *omap_domain = to_omap_domain(domain); + struct omap_iommu_device *iommu; + struct omap_iommu *oiommu; + int i; + + if (!omap_domain->dev) + return 0; + + iommu = omap_domain->iommus; + for (i = 0; i < omap_domain->num_iommus; i++, iommu++) { + oiommu = iommu->iommu_dev; + pm_runtime_get_sync(oiommu->dev); + } + + return 0; +} +EXPORT_SYMBOL_GPL(omap_iommu_domain_activate); + /** * omap_iommu_runtime_suspend - disable an iommu device * @dev: iommu device diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h index 153bf25b4df3..36b645726813 100644 --- a/include/linux/omap-iommu.h +++ b/include/linux/omap-iommu.h @@ -10,12 +10,20 @@ #ifndef _OMAP_IOMMU_H_ #define _OMAP_IOMMU_H_ +struct iommu_domain; + #ifdef CONFIG_OMAP_IOMMU extern void omap_iommu_save_ctx(struct device *dev); extern void omap_iommu_restore_ctx(struct device *dev); + +int omap_iommu_domain_deactivate(struct iommu_domain *domain); +int omap_iommu_domain_activate(struct iommu_domain *domain); #else static inline void omap_iommu_save_ctx(struct device *dev) {} static inline void omap_iommu_restore_ctx(struct device *dev) {} + +static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain) {} +static inline int omap_iommu_domain_activate(struct iommu_domain *domain) {} #endif #endif -- GitLab From 604629bcb5057d778839652f8f38d23734f2fe1d Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 7 Aug 2019 11:26:51 +0300 Subject: [PATCH 2464/7155] iommu/omap: add support for late attachment of iommu devices Current implementation of OMAP IOMMU enforces strict ordering of device probe, initiated by iommu and followed by remoteproc later. This doesn't work too well with the new setup done with ti-sysc changes which may have the devices probed at pretty much any order. To overcome this limitation, if iommu has not been probed yet when a consumer tries to attach to it, add the device to orphan device list which will be parsed during iommu probe to see if any orphan devices should be attached. Signed-off-by: Tero Kristo Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 56 ++++++++++++++++++++++++++++++++++++-- drivers/iommu/omap-iommu.h | 4 ++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index ecf14001beed..3c7ba517dbc3 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -35,6 +35,15 @@ static const struct iommu_ops omap_iommu_ops; +struct orphan_dev { + struct device *dev; + struct list_head node; +}; + +static LIST_HEAD(orphan_dev_list); + +static DEFINE_SPINLOCK(orphan_lock); + #define to_iommu(dev) ((struct omap_iommu *)dev_get_drvdata(dev)) /* bitmap of the page sizes currently supported */ @@ -53,6 +62,8 @@ static const struct iommu_ops omap_iommu_ops; static struct platform_driver omap_iommu_driver; static struct kmem_cache *iopte_cachep; +static int _omap_iommu_add_device(struct device *dev); + /** * to_omap_domain - Get struct omap_iommu_domain from generic iommu_domain * @dom: generic iommu domain handle @@ -1166,6 +1177,7 @@ static int omap_iommu_probe(struct platform_device *pdev) struct omap_iommu *obj; struct resource *res; struct device_node *of = pdev->dev.of_node; + struct orphan_dev *orphan_dev, *tmp; if (!of) { pr_err("%s: only DT-based devices are supported\n", __func__); @@ -1249,6 +1261,14 @@ static int omap_iommu_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s registered\n", obj->name); + list_for_each_entry_safe(orphan_dev, tmp, &orphan_dev_list, node) { + err = _omap_iommu_add_device(orphan_dev->dev); + if (!err) { + list_del(&orphan_dev->node); + kfree(orphan_dev); + } + } + return 0; out_sysfs: @@ -1638,7 +1658,7 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain, return ret; } -static int omap_iommu_add_device(struct device *dev) +static int _omap_iommu_add_device(struct device *dev) { struct omap_iommu_arch_data *arch_data, *tmp; struct omap_iommu *oiommu; @@ -1647,6 +1667,8 @@ static int omap_iommu_add_device(struct device *dev) struct platform_device *pdev; int num_iommus, i; int ret; + struct orphan_dev *orphan_dev; + unsigned long flags; /* * Allocate the archdata iommu structure for DT-based devices. @@ -1678,10 +1700,26 @@ static int omap_iommu_add_device(struct device *dev) } pdev = of_find_device_by_node(np); - if (WARN_ON(!pdev)) { + if (!pdev) { of_node_put(np); kfree(arch_data); - return -EINVAL; + spin_lock_irqsave(&orphan_lock, flags); + list_for_each_entry(orphan_dev, &orphan_dev_list, + node) { + if (orphan_dev->dev == dev) + break; + } + spin_unlock_irqrestore(&orphan_lock, flags); + + if (orphan_dev && orphan_dev->dev == dev) + return -EPROBE_DEFER; + + orphan_dev = kzalloc(sizeof(*orphan_dev), GFP_KERNEL); + orphan_dev->dev = dev; + spin_lock_irqsave(&orphan_lock, flags); + list_add(&orphan_dev->node, &orphan_dev_list); + spin_unlock_irqrestore(&orphan_lock, flags); + return -EPROBE_DEFER; } oiommu = platform_get_drvdata(pdev); @@ -1692,6 +1730,7 @@ static int omap_iommu_add_device(struct device *dev) } tmp->iommu_dev = oiommu; + tmp->dev = &pdev->dev; of_node_put(np); } @@ -1726,6 +1765,17 @@ static int omap_iommu_add_device(struct device *dev) return 0; } +static int omap_iommu_add_device(struct device *dev) +{ + int ret; + + ret = _omap_iommu_add_device(dev); + if (ret == -EPROBE_DEFER) + return 0; + + return ret; +} + static void omap_iommu_remove_device(struct device *dev) { struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 1d15aa857634..18ee713ede78 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h @@ -87,7 +87,8 @@ struct omap_iommu { /** * struct omap_iommu_arch_data - omap iommu private data - * @iommu_dev: handle of the iommu device + * @iommu_dev: handle of the OMAP iommu device + * @dev: handle of the iommu device * * This is an omap iommu private data object, which binds an iommu user * to its iommu device. This object should be placed at the iommu user's @@ -96,6 +97,7 @@ struct omap_iommu { */ struct omap_iommu_arch_data { struct omap_iommu *iommu_dev; + struct device *dev; }; struct cr_regs { -- GitLab From 1432ebbd60033f48ae24302524f9dca592103804 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 7 Aug 2019 11:26:52 +0300 Subject: [PATCH 2465/7155] iommu/omap: remove pm_runtime_irq_safe flag for OMAP IOMMUs This is not needed for anything, and prevents proper PM transitions for parent devices which is bad in case of ti-sysc; this effectively kills PM completely. Thus, remove the flag. Signed-off-by: Tero Kristo Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 3c7ba517dbc3..99a9ff3e7f71 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1254,7 +1254,6 @@ static int omap_iommu_probe(struct platform_device *pdev) goto out_sysfs; } - pm_runtime_irq_safe(obj->dev); pm_runtime_enable(obj->dev); omap_iommu_debugfs_add(obj); -- GitLab From d9973cec9d578b381235bb872a2d378c69c54915 Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Thu, 8 Aug 2019 12:38:03 +0300 Subject: [PATCH 2466/7155] xdp: xdp_umem: fix umem pages mapping for 32bits systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use kmap instead of page_address as it's not always in low memory. Acked-by: Björn Töpel Signed-off-by: Ivan Khoronzhuk Signed-off-by: Daniel Borkmann --- net/xdp/xdp_umem.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 83de74ca729a..a0607969f8c0 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "xdp_umem.h" #include "xsk_queue.h" @@ -164,6 +165,14 @@ void xdp_umem_clear_dev(struct xdp_umem *umem) umem->zc = false; } +static void xdp_umem_unmap_pages(struct xdp_umem *umem) +{ + unsigned int i; + + for (i = 0; i < umem->npgs; i++) + kunmap(umem->pgs[i]); +} + static void xdp_umem_unpin_pages(struct xdp_umem *umem) { unsigned int i; @@ -207,6 +216,7 @@ static void xdp_umem_release(struct xdp_umem *umem) xsk_reuseq_destroy(umem); + xdp_umem_unmap_pages(umem); xdp_umem_unpin_pages(umem); kfree(umem->pages); @@ -369,7 +379,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) } for (i = 0; i < umem->npgs; i++) - umem->pages[i].addr = page_address(umem->pgs[i]); + umem->pages[i].addr = kmap(umem->pgs[i]); return 0; -- GitLab From 3783d43752eab247ed296ac8d5022484ed969151 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 8 Aug 2019 18:17:37 +0200 Subject: [PATCH 2467/7155] samples/bpf: xdp_fwd rename devmap name to be xdp_tx_ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The devmap name 'tx_port' came from a copy-paste from xdp_redirect_map which only have a single TX port. Change name to xdp_tx_ports to make it more descriptive. Signed-off-by: Jesper Dangaard Brouer Reviewed-by: David Ahern Acked-by: Yonghong Song Reviewed-by: Toke Høiland-Jørgensen Signed-off-by: Daniel Borkmann --- samples/bpf/xdp_fwd_kern.c | 5 +++-- samples/bpf/xdp_fwd_user.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/samples/bpf/xdp_fwd_kern.c b/samples/bpf/xdp_fwd_kern.c index a7e94e7ff87d..e6ffc4ea06f4 100644 --- a/samples/bpf/xdp_fwd_kern.c +++ b/samples/bpf/xdp_fwd_kern.c @@ -23,7 +23,8 @@ #define IPV6_FLOWINFO_MASK cpu_to_be32(0x0FFFFFFF) -struct bpf_map_def SEC("maps") tx_port = { +/* For TX-traffic redirect requires net_device ifindex to be in this devmap */ +struct bpf_map_def SEC("maps") xdp_tx_ports = { .type = BPF_MAP_TYPE_DEVMAP, .key_size = sizeof(int), .value_size = sizeof(int), @@ -117,7 +118,7 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN); memcpy(eth->h_source, fib_params.smac, ETH_ALEN); - return bpf_redirect_map(&tx_port, fib_params.ifindex, 0); + return bpf_redirect_map(&xdp_tx_ports, fib_params.ifindex, 0); } return XDP_PASS; diff --git a/samples/bpf/xdp_fwd_user.c b/samples/bpf/xdp_fwd_user.c index 5b46ee12c696..ba012d9f93dd 100644 --- a/samples/bpf/xdp_fwd_user.c +++ b/samples/bpf/xdp_fwd_user.c @@ -113,7 +113,7 @@ int main(int argc, char **argv) return 1; } map_fd = bpf_map__fd(bpf_object__find_map_by_name(obj, - "tx_port")); + "xdp_tx_ports")); if (map_fd < 0) { printf("map not found: %s\n", strerror(map_fd)); return 1; -- GitLab From a32a32cb26eb6291125e4eb49b569874ca9a53b5 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 8 Aug 2019 18:17:42 +0200 Subject: [PATCH 2468/7155] samples/bpf: make xdp_fwd more practically usable via devmap lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This address the TODO in samples/bpf/xdp_fwd_kern.c, which points out that the chosen egress index should be checked for existence in the devmap. This can now be done via taking advantage of Toke's work in commit 0cdbb4b09a06 ("devmap: Allow map lookups from eBPF"). This change makes xdp_fwd more practically usable, as this allows for a mixed environment, where IP-forwarding fallback to network stack, if the egress device isn't configured to use XDP. Signed-off-by: Jesper Dangaard Brouer Reviewed-by: David Ahern Reviewed-by: Toke Høiland-Jørgensen Acked-by: Yonghong Song Signed-off-by: Daniel Borkmann --- samples/bpf/xdp_fwd_kern.c | 17 +++++++++++------ samples/bpf/xdp_fwd_user.c | 33 ++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/samples/bpf/xdp_fwd_kern.c b/samples/bpf/xdp_fwd_kern.c index e6ffc4ea06f4..a43d6953c054 100644 --- a/samples/bpf/xdp_fwd_kern.c +++ b/samples/bpf/xdp_fwd_kern.c @@ -104,13 +104,18 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags); - /* verify egress index has xdp support - * TO-DO bpf_map_lookup_elem(&tx_port, &key) fails with - * cannot pass map_type 14 into func bpf_map_lookup_elem#1: - * NOTE: without verification that egress index supports XDP - * forwarding packets are dropped. - */ if (rc == 0) { + /* Verify egress index has been configured as TX-port. + * (Note: User can still have inserted an egress ifindex that + * doesn't support XDP xmit, which will result in packet drops). + * + * Note: lookup in devmap supported since 0cdbb4b09a0. + * If not supported will fail with: + * cannot pass map_type 14 into func bpf_map_lookup_elem#1: + */ + if (!bpf_map_lookup_elem(&xdp_tx_ports, &fib_params.ifindex)) + return XDP_PASS; + if (h_proto == htons(ETH_P_IP)) ip_decrease_ttl(iph); else if (h_proto == htons(ETH_P_IPV6)) diff --git a/samples/bpf/xdp_fwd_user.c b/samples/bpf/xdp_fwd_user.c index ba012d9f93dd..97ff1dad7669 100644 --- a/samples/bpf/xdp_fwd_user.c +++ b/samples/bpf/xdp_fwd_user.c @@ -27,14 +27,20 @@ #include "libbpf.h" #include - -static int do_attach(int idx, int fd, const char *name) +static int do_attach(int idx, int prog_fd, int map_fd, const char *name) { int err; - err = bpf_set_link_xdp_fd(idx, fd, 0); - if (err < 0) + err = bpf_set_link_xdp_fd(idx, prog_fd, 0); + if (err < 0) { printf("ERROR: failed to attach program to %s\n", name); + return err; + } + + /* Adding ifindex as a possible egress TX port */ + err = bpf_map_update_elem(map_fd, &idx, &idx, 0); + if (err) + printf("ERROR: failed using device %s as TX-port\n", name); return err; } @@ -47,6 +53,9 @@ static int do_detach(int idx, const char *name) if (err < 0) printf("ERROR: failed to detach program from %s\n", name); + /* TODO: Remember to cleanup map, when adding use of shared map + * bpf_map_delete_elem((map_fd, &idx); + */ return err; } @@ -67,10 +76,10 @@ int main(int argc, char **argv) }; const char *prog_name = "xdp_fwd"; struct bpf_program *prog; + int prog_fd, map_fd = -1; char filename[PATH_MAX]; struct bpf_object *obj; int opt, i, idx, err; - int prog_fd, map_fd; int attach = 1; int ret = 0; @@ -103,8 +112,14 @@ int main(int argc, char **argv) return 1; } - if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) + err = bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd); + if (err) { + printf("Does kernel support devmap lookup?\n"); + /* If not, the error message will be: + * "cannot pass map_type 14 into func bpf_map_lookup_elem#1" + */ return 1; + } prog = bpf_object__find_program_by_title(obj, prog_name); prog_fd = bpf_program__fd(prog); @@ -119,10 +134,6 @@ int main(int argc, char **argv) return 1; } } - if (attach) { - for (i = 1; i < 64; ++i) - bpf_map_update_elem(map_fd, &i, &i, 0); - } for (i = optind; i < argc; ++i) { idx = if_nametoindex(argv[i]); @@ -138,7 +149,7 @@ int main(int argc, char **argv) if (err) ret = err; } else { - err = do_attach(idx, prog_fd, argv[i]); + err = do_attach(idx, prog_fd, map_fd, argv[i]); if (err) ret = err; } -- GitLab From abcce733adb71013997fcb84142a5454ef133616 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 8 Aug 2019 18:17:47 +0200 Subject: [PATCH 2469/7155] samples/bpf: xdp_fwd explain bpf_fib_lookup return codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make it clear that this XDP program depend on the network stack to do the ARP resolution. This is connected with the BPF_FIB_LKUP_RET_NO_NEIGH return code from bpf_fib_lookup(). Another common mistake (seen via XDP-tutorial) is that users don't realize that sysctl net.ipv{4,6}.conf.all.forwarding setting is honored by bpf_fib_lookup. Reported-by: Anton Protopopov Signed-off-by: Jesper Dangaard Brouer Reviewed-by: David Ahern Acked-by: Yonghong Song Reviewed-by: Toke Høiland-Jørgensen Signed-off-by: Daniel Borkmann --- samples/bpf/xdp_fwd_kern.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/samples/bpf/xdp_fwd_kern.c b/samples/bpf/xdp_fwd_kern.c index a43d6953c054..701a30f258b1 100644 --- a/samples/bpf/xdp_fwd_kern.c +++ b/samples/bpf/xdp_fwd_kern.c @@ -103,8 +103,23 @@ static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags) fib_params.ifindex = ctx->ingress_ifindex; rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags); - - if (rc == 0) { + /* + * Some rc (return codes) from bpf_fib_lookup() are important, + * to understand how this XDP-prog interacts with network stack. + * + * BPF_FIB_LKUP_RET_NO_NEIGH: + * Even if route lookup was a success, then the MAC-addresses are also + * needed. This is obtained from arp/neighbour table, but if table is + * (still) empty then BPF_FIB_LKUP_RET_NO_NEIGH is returned. To avoid + * doing ARP lookup directly from XDP, then send packet to normal + * network stack via XDP_PASS and expect it will do ARP resolution. + * + * BPF_FIB_LKUP_RET_FWD_DISABLED: + * The bpf_fib_lookup respect sysctl net.ipv{4,6}.conf.all.forwarding + * setting, and will return BPF_FIB_LKUP_RET_FWD_DISABLED if not + * enabled this on ingress device. + */ + if (rc == BPF_FIB_LKUP_RET_SUCCESS) { /* Verify egress index has been configured as TX-port. * (Note: User can still have inserted an egress ifindex that * doesn't support XDP xmit, which will result in packet drops). -- GitLab From 63e3ee61549595719145d23fdacd1d8744051108 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:07 +0100 Subject: [PATCH 2470/7155] ARM: cpuidle: Remove useless header include The generic ARM CPUidle driver includes by mistake. Remove the topology header include. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Reviewed-by: Ulf Hansson Reviewed-by: Sudeep Holla Cc: Ulf Hansson Cc: Sudeep Holla Cc: Daniel Lezcano Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- drivers/cpuidle/cpuidle-arm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c index 5bcd82c35dcf..dc33b3d2954f 100644 --- a/drivers/cpuidle/cpuidle-arm.c +++ b/drivers/cpuidle/cpuidle-arm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include -- GitLab From 6460d7ba488419dd5bc2cbfd989d5d7930ac1f9f Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:08 +0100 Subject: [PATCH 2471/7155] ARM: cpuidle: Remove overzealous error logging CPUidle back-end operations are not implemented in some platforms but this should not be considered an error serious enough to be logged. Check the arm_cpuidle_init() return value to detect whether the failure must be reported or not in the kernel log and do not log it if the platform does not support CPUidle operations. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Reviewed-by: Ulf Hansson Reviewed-by: Sudeep Holla Cc: Ulf Hansson Cc: Sudeep Holla Cc: Daniel Lezcano Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- drivers/cpuidle/cpuidle-arm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c index dc33b3d2954f..9e5156d39627 100644 --- a/drivers/cpuidle/cpuidle-arm.c +++ b/drivers/cpuidle/cpuidle-arm.c @@ -105,11 +105,17 @@ static int __init arm_idle_init_cpu(int cpu) ret = arm_cpuidle_init(cpu); /* - * Allow the initialization to continue for other CPUs, if the reported - * failure is a HW misconfiguration/breakage (-ENXIO). + * Allow the initialization to continue for other CPUs, if the + * reported failure is a HW misconfiguration/breakage (-ENXIO). + * + * Some platforms do not support idle operations + * (arm_cpuidle_init() returning -EOPNOTSUPP), we should + * not flag this case as an error, it is a valid + * configuration. */ if (ret) { - pr_err("CPU %d failed to init idle CPU ops\n", cpu); + if (ret != -EOPNOTSUPP) + pr_err("CPU %d failed to init idle CPU ops\n", cpu); ret = ret == -ENXIO ? 0 : ret; goto out_kfree_drv; } -- GitLab From e76d8b7027d9451cfdcb8cd605148ff5e0a1bf5d Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:09 +0100 Subject: [PATCH 2472/7155] drivers: firmware: psci: Decouple checker from generic ARM CPUidle The PSCI checker currently relies on the generic ARM CPUidle infrastructure to enter an idle state, which in turn creates a dependency that is not really needed. The PSCI checker code to test PSCI CPU suspend is built on top of the CPUidle framework and can easily reuse the struct cpuidle_state.enter() function (previously initialized by an idle driver, with a PSCI back-end) to trigger an entry into an idle state, decoupling the PSCI checker from the generic ARM CPUidle infrastructure and simplyfing the code in the process. Convert the PSCI checker suspend entry function to use the struct cpuidle_state.enter() function callback. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Reviewed-by: Ulf Hansson Reviewed-by: Sudeep Holla Cc: Sudeep Holla Cc: Mark Rutland Signed-off-by: Will Deacon --- drivers/firmware/psci/psci_checker.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c index f3659443f8c2..6a445397771c 100644 --- a/drivers/firmware/psci/psci_checker.c +++ b/drivers/firmware/psci/psci_checker.c @@ -228,8 +228,11 @@ static int hotplug_tests(void) static void dummy_callback(struct timer_list *unused) {} -static int suspend_cpu(int index, bool broadcast) +static int suspend_cpu(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { + struct cpuidle_state *state = &drv->states[index]; + bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP; int ret; arch_cpu_idle_enter(); @@ -254,11 +257,7 @@ static int suspend_cpu(int index, bool broadcast) } } - /* - * Replicate the common ARM cpuidle enter function - * (arm_enter_idle_state). - */ - ret = CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, index); + ret = state->enter(dev, drv, index); if (broadcast) tick_broadcast_exit(); @@ -301,9 +300,8 @@ static int suspend_test_thread(void *arg) * doesn't use PSCI). */ for (index = 1; index < drv->state_count; ++index) { - struct cpuidle_state *state = &drv->states[index]; - bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP; int ret; + struct cpuidle_state *state = &drv->states[index]; /* * Set the timer to wake this CPU up in some time (which @@ -318,7 +316,7 @@ static int suspend_test_thread(void *arg) /* IRQs must be disabled during suspend operations. */ local_irq_disable(); - ret = suspend_cpu(index, broadcast); + ret = suspend_cpu(dev, drv, index); /* * We have woken up. Re-enable IRQs to handle any -- GitLab From 81d549e0c810773bf003a25f59fa5509857bf9b2 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:10 +0100 Subject: [PATCH 2473/7155] ARM: psci: cpuidle: Introduce PSCI CPUidle driver PSCI firmware is the standard power management control for all ARM64 based platforms and it is also deployed on some ARM 32 bit platforms to date. Idle state entry in PSCI is currently achieved by calling arm_cpuidle_init() and arm_cpuidle_suspend() in a generic idle driver, which in turn relies on ARM/ARM64 CPUidle back-end to relay the call into PSCI firmware if PSCI is the boot method. Given that PSCI is the standard idle entry method on ARM64 systems (which means that no other CPUidle driver are expected on ARM64 platforms - so PSCI is already a generic idle driver), in order to simplify idle entry and code maintenance, it makes sense to have a PSCI specific idle driver so that idle code that it is currently living in drivers/firmware directory can be hoisted out of it and moved where it belongs, into a full-fledged PSCI driver, leaving PSCI code in drivers/firmware as a pure firmware interface, as it should be. Implement a PSCI CPUidle driver. By default it is a silent Kconfig entry which is left unselected, since it selection would clash with the generic ARM CPUidle driver that provides a PSCI based idle driver through the arm/arm64 arches back-ends CPU operations. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Reviewed-by: Ulf Hansson Reviewed-by: Sudeep Holla Cc: Ulf Hansson Cc: Sudeep Holla Cc: Daniel Lezcano Cc: Mark Rutland Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- MAINTAINERS | 8 ++ drivers/cpuidle/Kconfig.arm | 10 +++ drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-psci.c | 151 +++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 drivers/cpuidle/cpuidle-psci.c diff --git a/MAINTAINERS b/MAINTAINERS index a2c343ee3b2c..b6c2d21103fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4290,6 +4290,14 @@ S: Supported F: drivers/cpuidle/cpuidle-exynos.c F: arch/arm/mach-exynos/pm.c +CPUIDLE DRIVER - ARM PSCI +M: Lorenzo Pieralisi +M: Sudeep Holla +L: linux-pm@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Supported +F: drivers/cpuidle/cpuidle-psci.c + CPU IDLE TIME MANAGEMENT FRAMEWORK M: "Rafael J. Wysocki" M: Daniel Lezcano diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 48cb3d4bb7d1..eb014aa5ce6b 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -13,6 +13,16 @@ config ARM_CPUIDLE initialized by calling the CPU operations init idle hook provided by architecture code. +config ARM_PSCI_CPUIDLE + bool + depends on ARM_PSCI_FW + select DT_IDLE_STATES + select CPU_IDLE_MULTIPLE_DRIVERS + help + Select this to enable PSCI firmware based CPUidle driver for ARM. + It provides an idle driver that is capable of detecting and + managing idle states through the PSCI firmware interface. + config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 9d7176cee3d3..40d016339b29 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o +obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o ############################################################################### # MIPS drivers diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c new file mode 100644 index 000000000000..ab1dea918ea3 --- /dev/null +++ b/drivers/cpuidle/cpuidle-psci.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PSCI CPU idle driver. + * + * Copyright (C) 2019 ARM Ltd. + * Author: Lorenzo Pieralisi + */ + +#define pr_fmt(fmt) "CPUidle PSCI: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dt_idle_states.h" + +static int psci_enter_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) +{ + return CPU_PM_CPU_IDLE_ENTER(psci_cpu_suspend_enter, idx); +} + +static struct cpuidle_driver psci_idle_driver __initdata = { + .name = "psci_idle", + .owner = THIS_MODULE, + /* + * PSCI idle states relies on architectural WFI to + * be represented as state index 0. + */ + .states[0] = { + .enter = psci_enter_idle_state, + .exit_latency = 1, + .target_residency = 1, + .power_usage = UINT_MAX, + .name = "WFI", + .desc = "ARM WFI", + } +}; + +static const struct of_device_id psci_idle_state_match[] __initconst = { + { .compatible = "arm,idle-state", + .data = psci_enter_idle_state }, + { }, +}; + +static int __init psci_idle_init_cpu(int cpu) +{ + struct cpuidle_driver *drv; + struct device_node *cpu_node; + const char *enable_method; + int ret = 0; + + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + return -ENODEV; + + /* + * Check whether the enable-method for the cpu is PSCI, fail + * if it is not. + */ + enable_method = of_get_property(cpu_node, "enable-method", NULL); + if (!enable_method || (strcmp(enable_method, "psci"))) + ret = -ENODEV; + + of_node_put(cpu_node); + if (ret) + return ret; + + drv = kmemdup(&psci_idle_driver, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + drv->cpumask = (struct cpumask *)cpumask_of(cpu); + + /* + * Initialize idle states data, starting at index 1, since + * by default idle state 0 is the quiescent state reached + * by the cpu by executing the wfi instruction. + * + * If no DT idle states are detected (ret == 0) let the driver + * initialization fail accordingly since there is no reason to + * initialize the idle driver if only wfi is supported, the + * default archictectural back-end already executes wfi + * on idle entry. + */ + ret = dt_init_idle_driver(drv, psci_idle_state_match, 1); + if (ret <= 0) { + ret = ret ? : -ENODEV; + goto out_kfree_drv; + } + + /* + * Initialize PSCI idle states. + */ + ret = psci_cpu_init_idle(cpu); + if (ret) { + pr_err("CPU %d failed to PSCI idle\n", cpu); + goto out_kfree_drv; + } + + ret = cpuidle_register(drv, NULL); + if (ret) + goto out_kfree_drv; + + return 0; + +out_kfree_drv: + kfree(drv); + return ret; +} + +/* + * psci_idle_init - Initializes PSCI cpuidle driver + * + * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails + * to register cpuidle driver then rollback to cancel all CPUs + * registration. + */ +static int __init psci_idle_init(void) +{ + int cpu, ret; + struct cpuidle_driver *drv; + struct cpuidle_device *dev; + + for_each_possible_cpu(cpu) { + ret = psci_idle_init_cpu(cpu); + if (ret) + goto out_fail; + } + + return 0; + +out_fail: + while (--cpu >= 0) { + dev = per_cpu(cpuidle_devices, cpu); + drv = cpuidle_get_cpu_driver(dev); + cpuidle_unregister(drv); + kfree(drv); + } + + return ret; +} +device_initcall(psci_idle_init); -- GitLab From 788961462f3471617749edf10d0fcafad410d2bb Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:11 +0100 Subject: [PATCH 2474/7155] ARM: psci: cpuidle: Enable PSCI CPUidle driver Allow selection of the PSCI CPUidle in the kernel by updating the respective Kconfig entry. Remove PSCI callbacks from ARM/ARM64 generic CPU ops to prevent the PSCI idle driver from clashing with the generic ARM CPUidle driver initialization, that relies on CPU ops to initialize and enter idle states. Signed-off-by: Lorenzo Pieralisi Reviewed-by: Ulf Hansson Cc: Will Deacon Cc: Ulf Hansson Cc: Sudeep Holla Cc: Daniel Lezcano Cc: Catalin Marinas Cc: Mark Rutland Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- arch/arm64/kernel/cpuidle.c | 7 ++++--- arch/arm64/kernel/psci.c | 4 ---- drivers/cpuidle/Kconfig.arm | 2 +- drivers/firmware/psci/psci.c | 10 ---------- 4 files changed, 5 insertions(+), 18 deletions(-) diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index d1048173fd8a..619e0ebb8399 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -48,15 +49,15 @@ int arm_cpuidle_suspend(int index) int acpi_processor_ffh_lpi_probe(unsigned int cpu) { - return arm_cpuidle_init(cpu); + return psci_cpu_init_idle(cpu); } int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) { if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags)) - return CPU_PM_CPU_IDLE_ENTER_RETENTION(arm_cpuidle_suspend, + return CPU_PM_CPU_IDLE_ENTER_RETENTION(psci_cpu_suspend_enter, lpi->index); else - return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, lpi->index); + return CPU_PM_CPU_IDLE_ENTER(psci_cpu_suspend_enter, lpi->index); } #endif diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 85ee7d07889e..a543ab7e007c 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -105,10 +105,6 @@ static int cpu_psci_cpu_kill(unsigned int cpu) const struct cpu_operations cpu_psci_ops = { .name = "psci", -#ifdef CONFIG_CPU_IDLE - .cpu_init_idle = psci_cpu_init_idle, - .cpu_suspend = psci_cpu_suspend_enter, -#endif .cpu_init = cpu_psci_cpu_init, .cpu_prepare = cpu_psci_cpu_prepare, .cpu_boot = cpu_psci_cpu_boot, diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index eb014aa5ce6b..d8530475493c 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -14,7 +14,7 @@ config ARM_CPUIDLE provided by architecture code. config ARM_PSCI_CPUIDLE - bool + bool "PSCI CPU idle Driver" depends on ARM_PSCI_FW select DT_IDLE_STATES select CPU_IDLE_MULTIPLE_DRIVERS diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index f82ccd39a913..b343f8a34c6a 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -436,16 +436,6 @@ int psci_cpu_suspend_enter(unsigned long index) return ret; } - -/* ARM specific CPU idle operations */ -#ifdef CONFIG_ARM -static const struct cpuidle_ops psci_cpuidle_ops __initconst = { - .suspend = psci_cpu_suspend_enter, - .init = psci_dt_cpu_init_idle, -}; - -CPUIDLE_METHOD_OF_DECLARE(psci, "psci", &psci_cpuidle_ops); -#endif #endif static int psci_system_suspend(unsigned long unused) -- GitLab From 9ffeb6d08c3a4bbd7b1e33711b241f511e2ded79 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 9 Aug 2019 12:03:12 +0100 Subject: [PATCH 2475/7155] PSCI: cpuidle: Refactor CPU suspend power_state parameter handling Current PSCI code handles idle state entry through the psci_cpu_suspend_enter() API, that takes an idle state index as a parameter and convert the index into a previously initialized power_state parameter before calling the PSCI.CPU_SUSPEND() with it. This is unwieldly, since it forces the PSCI firmware layer to keep track of power_state parameter for every idle state so that the index->power_state conversion can be made in the PSCI firmware layer instead of the CPUidle driver implementations. Move the power_state handling out of drivers/firmware/psci into the respective ACPI/DT PSCI CPUidle backends and convert the psci_cpu_suspend_enter() API to get the power_state parameter as input, which makes it closer to its firmware interface PSCI.CPU_SUSPEND() API. A notable side effect is that the PSCI ACPI/DT CPUidle backends now can directly handle (and if needed update) power_state parameters before handing them over to the PSCI firmware interface to trigger PSCI.CPU_SUSPEND() calls. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Reviewed-by: Ulf Hansson Reviewed-by: Sudeep Holla Cc: Will Deacon Cc: Ulf Hansson Cc: Sudeep Holla Cc: Daniel Lezcano Cc: Catalin Marinas Cc: Mark Rutland Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- arch/arm64/kernel/cpuidle.c | 49 +++++++++- drivers/cpuidle/cpuidle-psci.c | 87 +++++++++++++++++- drivers/firmware/psci/psci.c | 157 ++------------------------------- include/linux/cpuidle.h | 17 +++- include/linux/psci.h | 4 +- 5 files changed, 154 insertions(+), 160 deletions(-) diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 619e0ebb8399..e4d6af2fdec7 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -47,17 +47,58 @@ int arm_cpuidle_suspend(int index) #define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags)) +static int psci_acpi_cpu_init_idle(unsigned int cpu) +{ + int i, count; + struct acpi_lpi_state *lpi; + struct acpi_processor *pr = per_cpu(processors, cpu); + + /* + * If the PSCI cpu_suspend function hook has not been initialized + * idle states must not be enabled, so bail out + */ + if (!psci_ops.cpu_suspend) + return -EOPNOTSUPP; + + if (unlikely(!pr || !pr->flags.has_lpi)) + return -EINVAL; + + count = pr->power.count - 1; + if (count <= 0) + return -ENODEV; + + for (i = 0; i < count; i++) { + u32 state; + + lpi = &pr->power.lpi_states[i + 1]; + /* + * Only bits[31:0] represent a PSCI power_state while + * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification + */ + state = lpi->address; + if (!psci_power_state_is_valid(state)) { + pr_warn("Invalid PSCI power state %#x\n", state); + return -EINVAL; + } + } + + return 0; +} + int acpi_processor_ffh_lpi_probe(unsigned int cpu) { - return psci_cpu_init_idle(cpu); + return psci_acpi_cpu_init_idle(cpu); } int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) { + u32 state = lpi->address; + if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags)) - return CPU_PM_CPU_IDLE_ENTER_RETENTION(psci_cpu_suspend_enter, - lpi->index); + return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(psci_cpu_suspend_enter, + lpi->index, state); else - return CPU_PM_CPU_IDLE_ENTER(psci_cpu_suspend_enter, lpi->index); + return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, + lpi->index, state); } #endif diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c index ab1dea918ea3..f3c1a2396f98 100644 --- a/drivers/cpuidle/cpuidle-psci.c +++ b/drivers/cpuidle/cpuidle-psci.c @@ -22,10 +22,15 @@ #include "dt_idle_states.h" +static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); + static int psci_enter_idle_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int idx) { - return CPU_PM_CPU_IDLE_ENTER(psci_cpu_suspend_enter, idx); + u32 *state = __this_cpu_read(psci_power_state); + + return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, + idx, state[idx - 1]); } static struct cpuidle_driver psci_idle_driver __initdata = { @@ -51,6 +56,86 @@ static const struct of_device_id psci_idle_state_match[] __initconst = { { }, }; +static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state) +{ + int err = of_property_read_u32(np, "arm,psci-suspend-param", state); + + if (err) { + pr_warn("%pOF missing arm,psci-suspend-param property\n", np); + return err; + } + + if (!psci_power_state_is_valid(*state)) { + pr_warn("Invalid PSCI power state %#x\n", *state); + return -EINVAL; + } + + return 0; +} + +static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) +{ + int i, ret = 0, count = 0; + u32 *psci_states; + struct device_node *state_node; + + /* Count idle states */ + while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", + count))) { + count++; + of_node_put(state_node); + } + + if (!count) + return -ENODEV; + + psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); + if (!psci_states) + return -ENOMEM; + + for (i = 0; i < count; i++) { + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + ret = psci_dt_parse_state_node(state_node, &psci_states[i]); + of_node_put(state_node); + + if (ret) + goto free_mem; + + pr_debug("psci-power-state %#x index %d\n", psci_states[i], i); + } + + /* Idle states parsed correctly, initialize per-cpu pointer */ + per_cpu(psci_power_state, cpu) = psci_states; + return 0; + +free_mem: + kfree(psci_states); + return ret; +} + +static __init int psci_cpu_init_idle(unsigned int cpu) +{ + struct device_node *cpu_node; + int ret; + + /* + * If the PSCI cpu_suspend function hook has not been initialized + * idle states must not be enabled, so bail out + */ + if (!psci_ops.cpu_suspend) + return -EOPNOTSUPP; + + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + return -ENODEV; + + ret = psci_dt_cpu_init_idle(cpu_node, cpu); + + of_node_put(cpu_node); + + return ret; +} + static int __init psci_idle_init_cpu(int cpu) { struct cpuidle_driver *drv; diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index b343f8a34c6a..84f4ff351c62 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -103,7 +103,7 @@ static inline bool psci_power_state_loses_context(u32 state) return state & mask; } -static inline bool psci_power_state_is_valid(u32 state) +bool psci_power_state_is_valid(u32 state) { const u32 valid_mask = psci_has_ext_power_state() ? PSCI_1_0_EXT_POWER_STATE_MASK : @@ -277,162 +277,21 @@ static int __init psci_features(u32 psci_func_id) } #ifdef CONFIG_CPU_IDLE -static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); - -static int psci_dt_parse_state_node(struct device_node *np, u32 *state) -{ - int err = of_property_read_u32(np, "arm,psci-suspend-param", state); - - if (err) { - pr_warn("%pOF missing arm,psci-suspend-param property\n", np); - return err; - } - - if (!psci_power_state_is_valid(*state)) { - pr_warn("Invalid PSCI power state %#x\n", *state); - return -EINVAL; - } - - return 0; -} - -static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) -{ - int i, ret = 0, count = 0; - u32 *psci_states; - struct device_node *state_node; - - /* Count idle states */ - while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", - count))) { - count++; - of_node_put(state_node); - } - - if (!count) - return -ENODEV; - - psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); - if (!psci_states) - return -ENOMEM; - - for (i = 0; i < count; i++) { - state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); - ret = psci_dt_parse_state_node(state_node, &psci_states[i]); - of_node_put(state_node); - - if (ret) - goto free_mem; - - pr_debug("psci-power-state %#x index %d\n", psci_states[i], i); - } - - /* Idle states parsed correctly, initialize per-cpu pointer */ - per_cpu(psci_power_state, cpu) = psci_states; - return 0; - -free_mem: - kfree(psci_states); - return ret; -} - -#ifdef CONFIG_ACPI -#include - -static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu) -{ - int i, count; - u32 *psci_states; - struct acpi_lpi_state *lpi; - struct acpi_processor *pr = per_cpu(processors, cpu); - - if (unlikely(!pr || !pr->flags.has_lpi)) - return -EINVAL; - - count = pr->power.count - 1; - if (count <= 0) - return -ENODEV; - - psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); - if (!psci_states) - return -ENOMEM; - - for (i = 0; i < count; i++) { - u32 state; - - lpi = &pr->power.lpi_states[i + 1]; - /* - * Only bits[31:0] represent a PSCI power_state while - * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification - */ - state = lpi->address; - if (!psci_power_state_is_valid(state)) { - pr_warn("Invalid PSCI power state %#x\n", state); - kfree(psci_states); - return -EINVAL; - } - psci_states[i] = state; - } - /* Idle states parsed correctly, initialize per-cpu pointer */ - per_cpu(psci_power_state, cpu) = psci_states; - return 0; -} -#else -static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu) -{ - return -EINVAL; -} -#endif - -int psci_cpu_init_idle(unsigned int cpu) -{ - struct device_node *cpu_node; - int ret; - - /* - * If the PSCI cpu_suspend function hook has not been initialized - * idle states must not be enabled, so bail out - */ - if (!psci_ops.cpu_suspend) - return -EOPNOTSUPP; - - if (!acpi_disabled) - return psci_acpi_cpu_init_idle(cpu); - - cpu_node = of_get_cpu_node(cpu, NULL); - if (!cpu_node) - return -ENODEV; - - ret = psci_dt_cpu_init_idle(cpu_node, cpu); - - of_node_put(cpu_node); - - return ret; -} - -static int psci_suspend_finisher(unsigned long index) +static int psci_suspend_finisher(unsigned long state) { - u32 *state = __this_cpu_read(psci_power_state); + u32 power_state = state; - return psci_ops.cpu_suspend(state[index - 1], - __pa_symbol(cpu_resume)); + return psci_ops.cpu_suspend(power_state, __pa_symbol(cpu_resume)); } -int psci_cpu_suspend_enter(unsigned long index) +int psci_cpu_suspend_enter(u32 state) { int ret; - u32 *state = __this_cpu_read(psci_power_state); - /* - * idle state index 0 corresponds to wfi, should never be called - * from the cpu_suspend operations - */ - if (WARN_ON_ONCE(!index)) - return -EINVAL; - if (!psci_power_state_loses_context(state[index - 1])) - ret = psci_ops.cpu_suspend(state[index - 1], 0); + if (!psci_power_state_loses_context(state)) + ret = psci_ops.cpu_suspend(state, 0); else - ret = cpu_suspend(index, psci_suspend_finisher); + ret = cpu_suspend(state, psci_suspend_finisher); return ret; } diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index bb9a0db89f1a..12ae4b87494e 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -256,7 +256,10 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) {return 0;} #endif -#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, is_retention) \ +#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \ + idx, \ + state, \ + is_retention) \ ({ \ int __ret = 0; \ \ @@ -268,7 +271,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) if (!is_retention) \ __ret = cpu_pm_enter(); \ if (!__ret) { \ - __ret = low_level_idle_enter(idx); \ + __ret = low_level_idle_enter(state); \ if (!is_retention) \ cpu_pm_exit(); \ } \ @@ -277,9 +280,15 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) }) #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ - __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 0) + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0) #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ - __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1) + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1) + +#define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \ + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0) + +#define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \ + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1) #endif /* _LINUX_CPUIDLE_H */ diff --git a/include/linux/psci.h b/include/linux/psci.h index a8a15613c157..e2bacc6fd2f2 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -15,8 +15,8 @@ bool psci_tos_resident_on(int cpu); -int psci_cpu_init_idle(unsigned int cpu); -int psci_cpu_suspend_enter(unsigned long index); +int psci_cpu_suspend_enter(u32 state); +bool psci_power_state_is_valid(u32 state); enum psci_conduit { PSCI_CONDUIT_NONE, -- GitLab From 332ccf00bf85adbf48015084be0e60f5cc57a055 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Aug 2019 17:15:31 +0200 Subject: [PATCH 2476/7155] ASoC: hdac_hdmi: Offload dapm update at jack detection hdac_hdmi_present_sense() calls the audio component to get ELD update, then it reports the jack status change and updates DAPM graph accordingly. This works when it's called from the normal code paths. However, it may lead to a dead lock when it's called from the audio component notifier. Namely, the DAPM update involves with the runtime PM, and it eventually calls again the audio component get_power() ops. Since i915 driver already takes a mutex around the audio component ops calls, we'll eventually get the mutex doubly. As a workaround, in this patch, only the jack state is updated in the code path from hdac_hdmi_eld_notify_cb(), and the DAPM update is deferred to a work so that it's processed in another context. Reported-by: Imre Deak Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20190809151531.24359-1-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 57 ++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 47eee18b66a3..11ec031ad749 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -88,8 +88,10 @@ struct hdac_hdmi_port { hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; struct hdac_hdmi_eld eld; const char *jack_pin; + bool is_connect; struct snd_soc_dapm_context *dapm; const char *output_pin; + struct work_struct dapm_work; }; struct hdac_hdmi_pcm { @@ -163,11 +165,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, { struct hdac_device *hdev = port->pin->hdev; - if (is_connect) - snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); - else - snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); - + port->is_connect = is_connect; if (is_connect) { /* * Report Jack connect event when a device is connected @@ -193,10 +191,32 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, if (pcm->jack_event > 0) pcm->jack_event--; } +} +static void hdac_hdmi_port_dapm_update(struct hdac_hdmi_port *port) +{ + if (port->is_connect) + snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); + else + snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); snd_soc_dapm_sync(port->dapm); } +static void hdac_hdmi_jack_dapm_work(struct work_struct *work) +{ + struct hdac_hdmi_port *port; + + port = container_of(work, struct hdac_hdmi_port, dapm_work); + hdac_hdmi_port_dapm_update(port); +} + +static void hdac_hdmi_jack_report_sync(struct hdac_hdmi_pcm *pcm, + struct hdac_hdmi_port *port, bool is_connect) +{ + hdac_hdmi_jack_report(pcm, port, is_connect); + hdac_hdmi_port_dapm_update(port); +} + /* MST supported verbs */ /* * Get the no devices that can be connected to a port on the Pin widget. @@ -873,7 +893,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, list_for_each_entry_safe(p, p_next, &pcm->port_list, head) { if (p == port && p->id == port->id && p->pin == port->pin) { - hdac_hdmi_jack_report(pcm, port, false); + hdac_hdmi_jack_report_sync(pcm, port, false); list_del(&p->head); } } @@ -887,7 +907,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, if (!strcmp(cvt_name, pcm->cvt->name)) { list_add_tail(&port->head, &pcm->port_list); if (port->eld.monitor_present && port->eld.eld_valid) { - hdac_hdmi_jack_report(pcm, port, true); + hdac_hdmi_jack_report_sync(pcm, port, true); mutex_unlock(&hdmi->pin_mutex); return ret; } @@ -1250,16 +1270,20 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, * report jack here. It will be done in usermode mux * control select. */ - if (pcm) + if (pcm) { hdac_hdmi_jack_report(pcm, port, false); + schedule_work(&port->dapm_work); + } mutex_unlock(&hdmi->pin_mutex); return; } if (port->eld.monitor_present && port->eld.eld_valid) { - if (pcm) + if (pcm) { hdac_hdmi_jack_report(pcm, port, true); + schedule_work(&port->dapm_work); + } print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, port->eld.eld_buffer, port->eld.eld_size, false); @@ -1288,6 +1312,7 @@ static int hdac_hdmi_add_ports(struct hdac_device *hdev, for (i = 0; i < max_ports; i++) { ports[i].id = i; ports[i].pin = pin; + INIT_WORK(&ports[i].dapm_work, hdac_hdmi_jack_dapm_work); } pin->ports = ports; pin->num_ports = max_ports; @@ -2052,8 +2077,20 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) return ret; } +static void clear_dapm_works(struct hdac_device *hdev) +{ + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); + struct hdac_hdmi_pin *pin; + int i; + + list_for_each_entry(pin, &hdmi->pin_list, head) + for (i = 0; i < pin->num_ports; i++) + cancel_work_sync(&pin->ports[i].dapm_work); +} + static int hdac_hdmi_dev_remove(struct hdac_device *hdev) { + clear_dapm_works(hdev); snd_hdac_display_power(hdev->bus, hdev->addr, false); return 0; @@ -2072,6 +2109,8 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) if (!bus) return 0; + clear_dapm_works(hdev); + /* * Power down afg. * codec_read is preferred over codec_write to set the power state. -- GitLab From 906c4d5c939b4d8ebe7be357121271df7b8c9582 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:40 +0200 Subject: [PATCH 2477/7155] dt-bindings: regulator: twl6030: Add retain-on-reset property During reset the VMMC regulator doesn't reach 0V and only drops to 1.8V, furthermore the pulse width is under 200us whereas the SD specification expect 1ms. For this 2 reasons being able to no reset at all the VMMC during warm reset and keep the current voltage is a good workaround. The TWL6030 allows this but needs to be aware of it and this configuration should also be shared with the bootloader. This is the purpose of this new property: ti,retain-on-reset Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-2-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/twl-regulator.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 74a91c4f8530..549f80436deb 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -71,3 +71,10 @@ Example: regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3000000>; }; + +For twl6030 regulators/LDOs: + + - ti,retain-on-reset: Does not turn off the supplies during warm + reset. Could be needed for VMMC, as TWL6030 + reset sequence for this signal does not comply + with the SD specification. -- GitLab From 621d3ce830649d56ef1c9611e370d05ceaffd7fc Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:41 +0200 Subject: [PATCH 2478/7155] regulator: twl6030: use variable for device node Instead of refering the full pdev->dev.of_node use a local variable. Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-3-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- drivers/regulator/twl6030-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index 5fe208b381eb..d73c81542ceb 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -665,14 +665,14 @@ static int twlreg_probe(struct platform_device *pdev) struct regulation_constraints *c; struct regulator_dev *rdev; struct regulator_config config = { }; + struct device_node *np = pdev->dev.of_node; template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; id = template->desc.id; - initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, - &template->desc); + initdata = of_get_regulator_init_data(&pdev->dev, np, &template->desc); if (!initdata) return -EINVAL; @@ -713,7 +713,7 @@ static int twlreg_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = info; - config.of_node = pdev->dev.of_node; + config.of_node = np; rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); if (IS_ERR(rdev)) { -- GitLab From d9df0187b6edd5871255cee29128c63f134e599c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:42 +0200 Subject: [PATCH 2479/7155] regulator: twl6030: workaround the VMMC reset behavior During reset the VMMC regulator doesn't reach 0V and only drops to 1.8V, furthermore the pulse width is under 200us whereas the SD specification expect 1ms. The WR_S bit allows the TWL6030 to no reset at all the VMMC during warm reset and keep the current voltage. Thanks to this workaround the SD card doesn't reach a undefined reset stage. Actually this behavior is available for all the LDO regulator, so the driver will also allow to use it with any of these regulator. Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-4-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- drivers/regulator/twl6030-regulator.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index d73c81542ceb..b8100c3cedad 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -57,6 +57,9 @@ struct twlreg_info { #define VREG_BC_PROC 3 #define VREG_BC_CLK_RST 4 +/* TWL6030 LDO register values for VREG_VOLTAGE */ +#define TWL6030_VREG_VOLTAGE_WR_S BIT(7) + /* TWL6030 LDO register values for CFG_STATE */ #define TWL6030_CFG_STATE_OFF 0x00 #define TWL6030_CFG_STATE_ON 0x01 @@ -68,9 +71,10 @@ struct twlreg_info { #define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ TWL6030_CFG_STATE_APP_SHIFT) -/* Flags for SMPS Voltage reading */ +/* Flags for SMPS Voltage reading and LDO reading*/ #define SMPS_OFFSET_EN BIT(0) #define SMPS_EXTENDED_EN BIT(1) +#define TWL_6030_WARM_RESET BIT(3) /* twl6032 SMPS EPROM values */ #define TWL6030_SMPS_OFFSET 0xB0 @@ -250,6 +254,9 @@ twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); + if (info->flags & TWL_6030_WARM_RESET) + selector |= TWL6030_VREG_VOLTAGE_WR_S; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, selector); } @@ -259,6 +266,9 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); + if (info->flags & TWL_6030_WARM_RESET) + vsel &= ~TWL6030_VREG_VOLTAGE_WR_S; + return vsel; } @@ -710,6 +720,9 @@ static int twlreg_probe(struct platform_device *pdev) break; } + if (of_get_property(np, "ti,retain-on-reset", NULL)) + info->flags |= TWL_6030_WARM_RESET; + config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = info; -- GitLab From 3dc29b8b2062075602c7aff1514a120b4ed0187f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:52:33 +0900 Subject: [PATCH 2480/7155] ASoC: soc-core: support snd_soc_dai_link_component for aux_dev To find aux_dev, ASoC is using .name, codec_name, codec_of_node. Here, .name is used to fallback in case of no codec. But, we already have this kind of component finding method by snd_soc_dai_link_component and soc_find_component(). We shouldn't have duplicated implementation to do same things. This patch adds snd_soc_dai_link_component support to finding aux_dev. Now, no driver is using only .name. All drivers are using codec_name and/or codec_of_node. This means no driver is finding component from .name so far. (Actually almost all drivers are using .name as just "device name", not for finding component...) This patch 1) add snd_soc_dai_link_component support for aux_dev. legacy style will be removed if all drivers are switched to new style. 2) try to find component via snd_soc_dai_link_component. Then, it doesn't try to find via .name, because no driver is using it so far. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y3046wcf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 7 +++++++ sound/soc/soc-core.c | 36 ++++++++++-------------------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 85ad971e9432..fd6ecea48fc0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -941,6 +941,7 @@ struct snd_soc_dai_link { #define COMP_CPU(_dai) { .dai_name = _dai, } #define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, } #define COMP_PLATFORM(_name) { .name = _name } +#define COMP_AUX(_name) { .name = _name } #define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } extern struct snd_soc_dai_link_component null_dailink_component[0]; @@ -971,6 +972,12 @@ struct snd_soc_aux_dev { const char *codec_name; struct device_node *codec_of_node; + /* + * name, codec_name, codec_of_node will be replaced + * into dlc. don't use both in the same time + */ + struct snd_soc_dai_link_component dlc; + /* codec/machine specific init - e.g. add machine controls */ int (*init)(struct snd_soc_component *component); }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bf45e60eb34f..56b99e340dda 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1537,38 +1537,22 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *component; - struct snd_soc_dai_link_component dlc; - if (aux_dev->codec_of_node || aux_dev->codec_name) { - /* codecs, usually analog devices */ - dlc.name = aux_dev->codec_name; - dlc.of_node = aux_dev->codec_of_node; - component = soc_find_component(&dlc); - if (!component) { - if (dlc.of_node) - dlc.name = of_node_full_name(dlc.of_node); - goto err_defer; - } - } else if (aux_dev->name) { - /* generic components */ - dlc.name = aux_dev->name; - dlc.of_node = NULL; - component = soc_find_component(&dlc); - if (!component) - goto err_defer; - } else { - dev_err(card->dev, "ASoC: Invalid auxiliary device\n"); - return -EINVAL; - } + /* remove me */ + if (aux_dev->codec_name) + aux_dev->dlc.name = aux_dev->codec_name; + if (aux_dev->codec_of_node) + aux_dev->dlc.of_node = aux_dev->codec_of_node; + + /* codecs, usually analog devices */ + component = soc_find_component(&aux_dev->dlc); + if (!component) + return -EPROBE_DEFER; component->init = aux_dev->init; list_add(&component->card_aux_list, &card->aux_comp_list); return 0; - -err_defer: - dev_err(card->dev, "ASoC: %s not registered\n", dlc.name); - return -EPROBE_DEFER; } static int soc_probe_aux_devices(struct snd_soc_card *card) -- GitLab From 14fdfc058d812f683d9aa51083d1a920aa6a1eb9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:52:47 +0900 Subject: [PATCH 2481/7155] ASoC: simple-card: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wofo6wc1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index ef849151ba56..0eac3bcb9736 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -424,7 +424,7 @@ static int simple_parse_aux_devs(struct device_node *node, aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); if (!aux_node) return -EINVAL; - card->aux_dev[i].codec_of_node = aux_node; + card->aux_dev[i].dlc.of_node = aux_node; } card->num_aux_devs = n; -- GitLab From aa1afd92f374a895ab74cb96dacd25a3485a08c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:53:33 +0900 Subject: [PATCH 2482/7155] ASoC: intel: cht_bsw_max98090_ti: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9v86war.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 33eb72545be6..1db9a95e6a79 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -324,9 +324,8 @@ static const struct snd_soc_ops cht_be_ssp2_ops = { }; static struct snd_soc_aux_dev cht_max98090_headset_dev = { - .name = "Headset Chip", + .dlc = COMP_AUX("i2c-104C227E:00"), .init = cht_max98090_headset_init, - .codec_name = "i2c-104C227E:00", }; SND_SOC_DAILINK_DEF(dummy, -- GitLab From 5c9e38cb57ce07d780dc05d34ae140271c2da159 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:53:45 +0900 Subject: [PATCH 2483/7155] ASoC: mediatek: mt8183-da7219-max98357: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tvas6waf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 59076e21cb47..2a6097174614 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -370,7 +370,7 @@ static int mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { - .name = "Headset Chip", + .dlc = COMP_EMPTY(), .init = mt8183_da7219_max98357_headset_init, }; @@ -436,10 +436,10 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) dai_link->platforms->of_node = platform_node; } - mt8183_da7219_max98357_headset_dev.codec_of_node = + mt8183_da7219_max98357_headset_dev.dlc.of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,headset-codec", 0); - if (!mt8183_da7219_max98357_headset_dev.codec_of_node) { + if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) { dev_err(&pdev->dev, "Property 'mediatek,headset-codec' missing/invalid\n"); return -EINVAL; -- GitLab From a73b522d4b570ee41754990e81f6f4e849af1af9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:53:59 +0900 Subject: [PATCH 2484/7155] ASoC: meson: axg-card: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r25w6wa1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 14a8321744da..6283e5025548 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -124,7 +124,7 @@ static void axg_card_clean_references(struct axg_card *priv) if (card->aux_dev) { for (i = 0; i < card->num_aux_devs; i++) - of_node_put(card->aux_dev[i].codec_of_node); + of_node_put(card->aux_dev[i].dlc.of_node); } kfree(card->dai_link); @@ -158,9 +158,9 @@ static int axg_card_add_aux_devices(struct snd_soc_card *card) card->num_aux_devs = num; for (i = 0; i < card->num_aux_devs; i++, aux++) { - aux->codec_of_node = + aux->dlc.of_node = of_parse_phandle(node, "audio-aux-devs", i); - if (!aux->codec_of_node) + if (!aux->dlc.of_node) return -EINVAL; } -- GitLab From 70a6b7bfba9bfd781b8c137f059487017dd385d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:05 +0900 Subject: [PATCH 2485/7155] ASoC: rockchip: rockchip_max98090: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pnlg6w9v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 1af1147c3da3..7b0c21fa6dca 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -160,7 +160,7 @@ static struct snd_soc_dai_link rk_dailink = { static int rk_98090_headset_init(struct snd_soc_component *component); static struct snd_soc_aux_dev rk_98090_headset_dev = { - .name = "Headset Chip", + .dlc = COMP_EMPTY(), .init = rk_98090_headset_init, }; @@ -226,9 +226,9 @@ static int snd_rk_mc_probe(struct platform_device *pdev) rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; - rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, + rk_98090_headset_dev.dlc.of_node = of_parse_phandle(np, "rockchip,headset-codec", 0); - if (!rk_98090_headset_dev.codec_of_node) { + if (!rk_98090_headset_dev.dlc.of_node) { dev_err(&pdev->dev, "Property 'rockchip,headset-codec' missing/invalid\n"); return -EINVAL; -- GitLab From d20bb789d7283bcbacd3b12c60668c473bc1dac0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:10 +0900 Subject: [PATCH 2486/7155] ASoC: samsung: neo1973_wm8753: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/87o9106w9p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 396776ffd670..38f536bafa09 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -297,8 +297,7 @@ static struct snd_soc_dai_link neo1973_dai[] = { static struct snd_soc_aux_dev neo1973_aux_devs[] = { { - .name = "dfbmcs320", - .codec_name = "dfbmcs320.0", + .dlc = COMP_AUX("dfbmcs320.0"), }, }; -- GitLab From 2d946aaa80c79452c700381b4c1f06f11dfd2bdd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:15 +0900 Subject: [PATCH 2487/7155] ASoC: samsung: speyside: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/87mugk6w9l.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 51e4c976c8be..9e58cbed942a 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -240,8 +240,7 @@ static int speyside_wm9081_init(struct snd_soc_component *component) static struct snd_soc_aux_dev speyside_aux_dev[] = { { - .name = "wm9081", - .codec_name = "wm9081.1-006c", + .dlc = COMP_AUX("wm9081.1-006c"), .init = speyside_wm9081_init, }, }; -- GitLab From 124749194ad2e08fbea9c34fa5e2728310bf4486 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:20 +0900 Subject: [PATCH 2488/7155] ASoC: samsung: tm2_wm5110: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/87lfw46w9g.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index c091033d17ad..bb9910d4cbe2 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -307,7 +307,6 @@ static struct snd_soc_aux_dev tm2_speaker_amp_dev; static int tm2_late_probe(struct snd_soc_card *card) { struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); - struct snd_soc_dai_link_component dlc = { 0 }; unsigned int ch_map[] = { 0, 1 }; struct snd_soc_dai *amp_pdm_dai; struct snd_soc_pcm_runtime *rtd; @@ -334,8 +333,7 @@ static int tm2_late_probe(struct snd_soc_card *card) return ret; } - dlc.of_node = tm2_speaker_amp_dev.codec_of_node; - amp_pdm_dai = snd_soc_find_dai(&dlc); + amp_pdm_dai = snd_soc_find_dai(&tm2_speaker_amp_dev.dlc); if (!amp_pdm_dai) return -ENODEV; @@ -532,9 +530,9 @@ static int tm2_probe(struct platform_device *pdev) return ret; } - card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, + card->aux_dev[0].dlc.of_node = of_parse_phandle(dev->of_node, "audio-amplifier", 0); - if (!card->aux_dev[0].codec_of_node) { + if (!card->aux_dev[0].dlc.of_node) { dev_err(dev, "audio-amplifier property invalid or missing\n"); return -EINVAL; } @@ -623,7 +621,7 @@ static int tm2_probe(struct platform_device *pdev) of_node_put(cpu_dai_node[i]); } - of_node_put(card->aux_dev[0].codec_of_node); + of_node_put(card->aux_dev[0].dlc.of_node); return ret; } -- GitLab From 3d0d2d64b7eb4f2a451fa184829b749851c14f55 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:25 +0900 Subject: [PATCH 2489/7155] ASoC: sunxi: sun4i-codec: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k1bo6w9b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 619073e7d972..ee448d5e07a6 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1424,7 +1424,7 @@ static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = { }; static struct snd_soc_aux_dev aux_dev = { - .name = "Codec Analog Controls", + .dlc = COMP_EMPTY(), }; static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) @@ -1436,10 +1436,10 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) if (!card) return ERR_PTR(-ENOMEM); - aux_dev.codec_of_node = of_parse_phandle(dev->of_node, + aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, "allwinner,codec-analog-controls", 0); - if (!aux_dev.codec_of_node) { + if (!aux_dev.dlc.of_node) { dev_err(dev, "Can't find analog controls for codec.\n"); return ERR_PTR(-EINVAL); }; @@ -1474,10 +1474,10 @@ static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev) if (!card) return ERR_PTR(-ENOMEM); - aux_dev.codec_of_node = of_parse_phandle(dev->of_node, + aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, "allwinner,codec-analog-controls", 0); - if (!aux_dev.codec_of_node) { + if (!aux_dev.dlc.of_node) { dev_err(dev, "Can't find analog controls for codec.\n"); return ERR_PTR(-EINVAL); }; @@ -1512,10 +1512,10 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev) if (!card) return ERR_PTR(-ENOMEM); - aux_dev.codec_of_node = of_parse_phandle(dev->of_node, + aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, "allwinner,codec-analog-controls", 0); - if (!aux_dev.codec_of_node) { + if (!aux_dev.dlc.of_node) { dev_err(dev, "Can't find analog controls for codec.\n"); return ERR_PTR(-EINVAL); }; -- GitLab From 77b21d2822fdbfad19170516256c4c7f236054a9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:30 +0900 Subject: [PATCH 2490/7155] ASoC: ti: rx51: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87imr86w96.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/rx51.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index ccd0e8a07dd1..588f680a9c24 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -319,12 +319,10 @@ static struct snd_soc_dai_link rx51_dai[] = { static struct snd_soc_aux_dev rx51_aux_dev[] = { { - .name = "TLV320AIC34b", - .codec_name = "tlv320aic3x-codec.2-0019", + .dlc = COMP_AUX("tlv320aic3x-codec.2-0019"), }, { - .name = "TPA61320A2", - .codec_name = "tpa6130a2.2-0060", + .dlc = COMP_AUX("tpa6130a2.2-0060"), }, }; @@ -397,8 +395,8 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n"); return -EINVAL; } - rx51_aux_dev[0].codec_name = NULL; - rx51_aux_dev[0].codec_of_node = dai_node; + rx51_aux_dev[0].dlc.name = NULL; + rx51_aux_dev[0].dlc.of_node = dai_node; rx51_codec_conf[0].dev_name = NULL; rx51_codec_conf[0].of_node = dai_node; @@ -407,8 +405,8 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; } - rx51_aux_dev[1].codec_name = NULL; - rx51_aux_dev[1].codec_of_node = dai_node; + rx51_aux_dev[1].dlc.name = NULL; + rx51_aux_dev[1].dlc.of_node = dai_node; rx51_codec_conf[1].dev_name = NULL; rx51_codec_conf[1].of_node = dai_node; } -- GitLab From a48b561d873d1d9fda55782d275eff94ec647863 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:39 +0900 Subject: [PATCH 2491/7155] ASoC: soc-core: remove legacy style of aux_dev Now all drivers are using snd_soc_dai_link_component for aux_dev. Let's remove legacy style Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h86s6w8x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 9 --------- sound/soc/soc-core.c | 6 ------ 2 files changed, 15 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index fd6ecea48fc0..2fc56e5963f3 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -963,19 +963,10 @@ struct snd_soc_codec_conf { }; struct snd_soc_aux_dev { - const char *name; /* Codec name */ - /* * specify multi-codec either by device name, or by * DT/OF node, but not both. */ - const char *codec_name; - struct device_node *codec_of_node; - - /* - * name, codec_name, codec_of_node will be replaced - * into dlc. don't use both in the same time - */ struct snd_soc_dai_link_component dlc; /* codec/machine specific init - e.g. add machine controls */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 56b99e340dda..4af382d52675 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1538,12 +1538,6 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *component; - /* remove me */ - if (aux_dev->codec_name) - aux_dev->dlc.name = aux_dev->codec_name; - if (aux_dev->codec_of_node) - aux_dev->dlc.of_node = aux_dev->codec_of_node; - /* codecs, usually analog devices */ component = soc_find_component(&aux_dev->dlc); if (!component) -- GitLab From dbf0649f4340c8bb7d36b8d6255dba03ed6981e7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 8 Aug 2019 22:32:15 +0800 Subject: [PATCH 2492/7155] ASoC: max98926: remove two unused variables sound/soc/codecs/max98926.c:28:26: warning: max98926_dai_txt defined but not used [-Wunused-const-variable=] sound/soc/codecs/max98926.c:23:27: warning: max98926_boost_current_txt defined but not used [-Wunused-const-variable=] They are never used, so can be removd. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190808143215.65904-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98926.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 818c0301fb29..c4dfa8ab1d49 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -20,15 +20,6 @@ static const char * const max98926_boost_voltage_txt[] = { "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" }; -static const char * const max98926_boost_current_txt[] = { - "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0", - "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4" -}; - -static const char *const max98926_dai_txt[] = { - "Left", "Right", "LeftRight", "LeftRightDiv2", -}; - static const char *const max98926_pdm_ch_text[] = { "Current", "Voltage", }; -- GitLab From c86102a333f77dcd0f7ef20ba836c6f13f1a077a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 8 Aug 2019 22:35:07 +0800 Subject: [PATCH 2493/7155] ASoC: max9850: remove unused variable 'max9850_reg' sound/soc/codecs/max9850.c:31:33: warning: max9850_reg defined but not used [-Wunused-const-variable=] It is not used since commit 068416620c0d ("ASoC: max9850: Convert to direct regmap API usage") Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190808143507.66788-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/max9850.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index f50ee8f5fe93..6f43748f9239 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -27,19 +27,6 @@ struct max9850_priv { unsigned int sysclk; }; -/* max9850 register cache */ -static const struct reg_default max9850_reg[] = { - { 2, 0x0c }, - { 3, 0x00 }, - { 4, 0x00 }, - { 5, 0x00 }, - { 6, 0x00 }, - { 7, 0x00 }, - { 8, 0x00 }, - { 9, 0x00 }, - { 10, 0x00 }, -}; - /* these registers are not used at the moment but provided for the sake of * completeness */ static bool max9850_volatile_register(struct device *dev, unsigned int reg) -- GitLab From b812cd5864548bd9718879896fdd2822d3cb3d76 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:53:52 +0900 Subject: [PATCH 2494/7155] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: use snd_soc_dai_link_component for aux_dev We can use snd_soc_dai_link_component to specify aux_dev. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sgqc6wa8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 4c816c86844b..53f54078f78c 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -343,7 +343,7 @@ static int mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *cpnt); static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { - .name = "Headset Chip", + .dlc = COMP_EMPTY(), .init = mt8183_mt6358_ts3a227_max98357_headset_init, }; @@ -399,10 +399,10 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) dai_link->platforms->of_node = platform_node; } - mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node = + mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,headset-codec", 0); - if (mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { + if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) { card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; card->num_aux_devs = 1; } -- GitLab From c2b71c71037bea7765aa6ff37824520d19108769 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Aug 2019 14:54:44 +0900 Subject: [PATCH 2495/7155] ASoC: soc-core: add for_each_xxx macro for aux_dev To be more readable code, this patch adds new for_each_xxx() macro for aux_dev. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ftmc6w8s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ++++++++++ sound/soc/meson/axg-card.c | 7 ++++--- sound/soc/soc-core.c | 15 ++++++++------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 2fc56e5963f3..b1fe5ebea257 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1087,6 +1087,10 @@ struct snd_soc_card { for ((i) = 0; \ ((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \ (i)++) +#define for_each_card_pre_auxs(card, i, aux) \ + for ((i) = 0; \ + ((i) < (card)->num_aux_devs) && ((aux) = &(card)->aux_dev[i]); \ + (i)++) #define for_each_card_links(card, link) \ list_for_each_entry(link, &(card)->dai_link_list, list) @@ -1098,6 +1102,12 @@ struct snd_soc_card { #define for_each_card_rtds_safe(card, rtd, _rtd) \ list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list) +#define for_each_card_auxs(card, component) \ + list_for_each_entry(component, &card->aux_comp_list, card_aux_list) +#define for_each_card_auxs_safe(card, component, _comp) \ + list_for_each_entry_safe(component, _comp, \ + &card->aux_comp_list, card_aux_list) + #define for_each_card_components(card, component) \ list_for_each_entry(component, &(card)->component_dev_list, card_list) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 6283e5025548..1f698adde506 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -111,6 +111,7 @@ static void axg_card_clean_references(struct axg_card *priv) struct snd_soc_card *card = &priv->card; struct snd_soc_dai_link *link; struct snd_soc_dai_link_component *codec; + struct snd_soc_aux_dev *aux; int i, j; if (card->dai_link) { @@ -123,8 +124,8 @@ static void axg_card_clean_references(struct axg_card *priv) } if (card->aux_dev) { - for (i = 0; i < card->num_aux_devs; i++) - of_node_put(card->aux_dev[i].dlc.of_node); + for_each_card_pre_auxs(card, i, aux) + of_node_put(aux->dlc.of_node); } kfree(card->dai_link); @@ -157,7 +158,7 @@ static int axg_card_add_aux_devices(struct snd_soc_card *card) card->aux_dev = aux; card->num_aux_devs = num; - for (i = 0; i < card->num_aux_devs; i++, aux++) { + for_each_card_pre_auxs(card, i, aux) { aux->dlc.of_node = of_parse_phandle(node, "audio-aux-devs", i); if (!aux->dlc.of_node) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4af382d52675..e9f44505cc3e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1533,9 +1533,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, return ret; } -static int soc_bind_aux_dev(struct snd_soc_card *card, int num) +static int soc_bind_aux_dev(struct snd_soc_card *card, + struct snd_soc_aux_dev *aux_dev) { - struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *component; /* codecs, usually analog devices */ @@ -1544,6 +1544,7 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) return -EPROBE_DEFER; component->init = aux_dev->init; + /* see for_each_card_auxs */ list_add(&component->card_aux_list, &card->aux_comp_list); return 0; @@ -1556,7 +1557,7 @@ static int soc_probe_aux_devices(struct snd_soc_card *card) int ret; for_each_comp_order(order) { - list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) { + for_each_card_auxs(card, comp) { if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { @@ -1578,8 +1579,7 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) int order; for_each_comp_order(order) { - list_for_each_entry_safe(comp, _comp, - &card->aux_comp_list, card_aux_list) { + for_each_card_auxs_safe(card, comp, _comp) { if (comp->driver->remove_order == order) { soc_remove_component(comp); @@ -1913,6 +1913,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link *dai_link; + struct snd_soc_aux_dev *aux; int ret, i, order; mutex_lock(&client_mutex); @@ -1943,8 +1944,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } /* bind aux_devs too */ - for (i = 0; i < card->num_aux_devs; i++) { - ret = soc_bind_aux_dev(card, i); + for_each_card_pre_auxs(card, i, aux) { + ret = soc_bind_aux_dev(card, aux); if (ret != 0) goto probe_end; } -- GitLab From 29a3388bfcce7a6d087051376ea02bf8326a957b Mon Sep 17 00:00:00 2001 From: Stephen Douthit Date: Fri, 9 Aug 2019 14:18:02 +0000 Subject: [PATCH 2496/7155] EDAC, pnd2: Fix ioremap() size in dnv_rd_reg() Depending on how BIOS has marked the reserved region containing the 32KB MCHBAR you can get warnings like: resource sanity check: requesting [mem 0xfed10000-0xfed1ffff], which spans more than reserved [mem 0xfed10000-0xfed17fff] caller dnv_rd_reg+0xc8/0x240 [pnd2_edac] mapping multiple BARs Not all of the mmio regions used in dnv_rd_reg() are the same size. The MCHBAR window is 32KB and the sideband ports are 64KB. Pass the correct size to ioremap() depending on which resource we're reading from. Signed-off-by: Stephen Douthit Signed-off-by: Tony Luck --- drivers/edac/pnd2_edac.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index ca25f8fe57ef..1ad538baaa4a 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -260,11 +260,14 @@ static u64 get_sideband_reg_base_addr(void) } } +#define DNV_MCHBAR_SIZE 0x8000 +#define DNV_SB_PORT_SIZE 0x10000 static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *name) { struct pci_dev *pdev; char *base; u64 addr; + unsigned long size; if (op == 4) { pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x1980, NULL); @@ -279,15 +282,17 @@ static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *na addr = get_mem_ctrl_hub_base_addr(); if (!addr) return -ENODEV; + size = DNV_MCHBAR_SIZE; } else { /* MMIO via sideband register base address */ addr = get_sideband_reg_base_addr(); if (!addr) return -ENODEV; addr += (port << 16); + size = DNV_SB_PORT_SIZE; } - base = ioremap((resource_size_t)addr, 0x10000); + base = ioremap((resource_size_t)addr, size); if (!base) return -ENODEV; -- GitLab From 6240973e5661a83df24e35a9a9c2013496931e2b Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Mon, 29 Jul 2019 08:36:05 -0400 Subject: [PATCH 2497/7155] tools/memory-model: Use cumul-fence instead of fence in ->prop example To reduce ambiguity in the more exotic ->prop ordering example, this commit uses the term cumul-fence instead of the term fence for the two fences, so that the implict ->rfe on loads/stores to Y are covered by the description. Link: https://lore.kernel.org/lkml/20190729121745.GA140682@google.com Suggested-by: Alan Stern Signed-off-by: Joel Fernandes (Google) Acked-by: Alan Stern Signed-off-by: Paul E. McKenney --- tools/memory-model/Documentation/explanation.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt index 68caa9a976d0..634dc6db26c4 100644 --- a/tools/memory-model/Documentation/explanation.txt +++ b/tools/memory-model/Documentation/explanation.txt @@ -1302,7 +1302,7 @@ followed by an arbitrary number of cumul-fence links, ending with an rfe link. You can concoct more exotic examples, containing more than one fence, although this quickly leads to diminishing returns in terms of complexity. For instance, here's an example containing a coe link -followed by two fences and an rfe link, utilizing the fact that +followed by two cumul-fences and an rfe link, utilizing the fact that release fences are A-cumulative: int x, y, z; @@ -1334,10 +1334,10 @@ If x = 2, r0 = 1, and r2 = 1 after this code runs then there is a prop link from P0's store to its load. This is because P0's store gets overwritten by P1's store since x = 2 at the end (a coe link), the smp_wmb() ensures that P1's store to x propagates to P2 before the -store to y does (the first fence), the store to y propagates to P2 +store to y does (the first cumul-fence), the store to y propagates to P2 before P2's load and store execute, P2's smp_store_release() guarantees that the stores to x and y both propagate to P0 before the -store to z does (the second fence), and P0's load executes after the +store to z does (the second cumul-fence), and P0's load executes after the store to z has propagated to P0 (an rfe link). In summary, the fact that the hb relation links memory access events -- GitLab From 6738ff85c3ee8073d5b030cb26241d0009d4ce29 Mon Sep 17 00:00:00 2001 From: Andrea Parri Date: Sat, 29 Jun 2019 23:10:44 +0200 Subject: [PATCH 2498/7155] tools/memory-model: Update the informal documentation The formal memory consistency model has added support for plain accesses (and data races). While updating the informal documentation to describe this addition to the model is highly desirable and important future work, update the informal documentation to at least acknowledge such addition. Signed-off-by: Andrea Parri Cc: Will Deacon Cc: Peter Zijlstra Cc: Boqun Feng Cc: Nicholas Piggin Cc: David Howells Cc: Jade Alglave Cc: Luc Maranget Cc: "Paul E. McKenney" Cc: Akira Yokosawa Cc: Daniel Lustig Signed-off-by: Paul E. McKenney Acked-by: Alan Stern --- .../Documentation/explanation.txt | 47 +++++++++---------- tools/memory-model/README | 18 +++---- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt index 634dc6db26c4..488f11f6c588 100644 --- a/tools/memory-model/Documentation/explanation.txt +++ b/tools/memory-model/Documentation/explanation.txt @@ -42,7 +42,8 @@ linux-kernel.bell and linux-kernel.cat files that make up the formal version of the model; they are extremely terse and their meanings are far from clear. -This document describes the ideas underlying the LKMM. It is meant +This document describes the ideas underlying the LKMM, but excluding +the modeling of bare C (or plain) shared memory accesses. It is meant for people who want to understand how the model was designed. It does not go into the details of the code in the .bell and .cat files; rather, it explains in English what the code expresses symbolically. @@ -354,31 +355,25 @@ be extremely complex. Optimizing compilers have great freedom in the way they translate source code to object code. They are allowed to apply transformations that add memory accesses, eliminate accesses, combine them, split them -into pieces, or move them around. Faced with all these possibilities, -the LKMM basically gives up. It insists that the code it analyzes -must contain no ordinary accesses to shared memory; all accesses must -be performed using READ_ONCE(), WRITE_ONCE(), or one of the other -atomic or synchronization primitives. These primitives prevent a -large number of compiler optimizations. In particular, it is -guaranteed that the compiler will not remove such accesses from the -generated code (unless it can prove the accesses will never be -executed), it will not change the order in which they occur in the -code (within limits imposed by the C standard), and it will not -introduce extraneous accesses. - -This explains why the MP and SB examples above used READ_ONCE() and -WRITE_ONCE() rather than ordinary memory accesses. Thanks to this -usage, we can be certain that in the MP example, P0's write event to -buf really is po-before its write event to flag, and similarly for the -other shared memory accesses in the examples. - -Private variables are not subject to this restriction. Since they are -not shared between CPUs, they can be accessed normally without -READ_ONCE() or WRITE_ONCE(), and there will be no ill effects. In -fact, they need not even be stored in normal memory at all -- in -principle a private variable could be stored in a CPU register (hence -the convention that these variables have names starting with the -letter 'r'). +into pieces, or move them around. The use of READ_ONCE(), WRITE_ONCE(), +or one of the other atomic or synchronization primitives prevents a +large number of compiler optimizations. In particular, it is guaranteed +that the compiler will not remove such accesses from the generated code +(unless it can prove the accesses will never be executed), it will not +change the order in which they occur in the code (within limits imposed +by the C standard), and it will not introduce extraneous accesses. + +The MP and SB examples above used READ_ONCE() and WRITE_ONCE() rather +than ordinary memory accesses. Thanks to this usage, we can be certain +that in the MP example, the compiler won't reorder P0's write event to +buf and P0's write event to flag, and similarly for the other shared +memory accesses in the examples. + +Since private variables are not shared between CPUs, they can be +accessed normally without READ_ONCE() or WRITE_ONCE(). In fact, they +need not even be stored in normal memory at all -- in principle a +private variable could be stored in a CPU register (hence the convention +that these variables have names starting with the letter 'r'). A WARNING diff --git a/tools/memory-model/README b/tools/memory-model/README index 2b87f3971548..fc07b52f2028 100644 --- a/tools/memory-model/README +++ b/tools/memory-model/README @@ -167,15 +167,15 @@ scripts Various scripts, see scripts/README. LIMITATIONS =========== -The Linux-kernel memory model has the following limitations: - -1. Compiler optimizations are not modeled. Of course, the use - of READ_ONCE() and WRITE_ONCE() limits the compiler's ability - to optimize, but there is Linux-kernel code that uses bare C - memory accesses. Handling this code is on the to-do list. - For more information, see Documentation/explanation.txt (in - particular, the "THE PROGRAM ORDER RELATION: po AND po-loc" - and "A WARNING" sections). +The Linux-kernel memory model (LKMM) has the following limitations: + +1. Compiler optimizations are not accurately modeled. Of course, + the use of READ_ONCE() and WRITE_ONCE() limits the compiler's + ability to optimize, but under some circumstances it is possible + for the compiler to undermine the memory model. For more + information, see Documentation/explanation.txt (in particular, + the "THE PROGRAM ORDER RELATION: po AND po-loc" and "A WARNING" + sections). Note that this limitation in turn limits LKMM's ability to accurately model address, control, and data dependencies. -- GitLab From 73499ad21d595638213f2a5f8b9b58259fa0cae2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 9 Aug 2019 18:09:13 +0200 Subject: [PATCH 2499/7155] iommu/omap: Fix compilation warnings A recent patch introduced a new compiler warning because two functions with non-void return type have no return statement in omap-iommu.h for CONFIG_OMAP_IOMMU=n. Fix this by adding return statements to these functions. Fixes: d9c4d8a6cc0f8 ('iommu/omap: introduce new API for runtime suspend/resume control') Signed-off-by: Joerg Roedel --- include/linux/omap-iommu.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h index 36b645726813..2c32ca09df02 100644 --- a/include/linux/omap-iommu.h +++ b/include/linux/omap-iommu.h @@ -22,8 +22,15 @@ int omap_iommu_domain_activate(struct iommu_domain *domain); static inline void omap_iommu_save_ctx(struct device *dev) {} static inline void omap_iommu_restore_ctx(struct device *dev) {} -static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain) {} -static inline int omap_iommu_domain_activate(struct iommu_domain *domain) {} +static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain) +{ + return -ENODEV; +} + +static inline int omap_iommu_domain_activate(struct iommu_domain *domain) +{ + return -ENODEV; +} #endif #endif -- GitLab From 28875945ba98d1b47a8a706812b6494d165bb0a0 Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Tue, 16 Jul 2019 18:12:22 -0400 Subject: [PATCH 2500/7155] rcu: Add support for consolidated-RCU reader checking This commit adds RCU-reader checks to list_for_each_entry_rcu() and hlist_for_each_entry_rcu(). These checks are optional, and are indicated by a lockdep expression passed to a new optional argument to these two macros. If this optional lockdep expression is omitted, these two macros act as before, checking for an RCU read-side critical section. Signed-off-by: Joel Fernandes (Google) [ paulmck: Update to eliminate return within macro and update comment. ] Signed-off-by: Paul E. McKenney --- include/linux/rculist.h | 32 +++++++++++--- include/linux/rcupdate.h | 7 +++ kernel/rcu/Kconfig.debug | 11 +++++ kernel/rcu/update.c | 96 ++++++++++++++++++++++++++-------------- 4 files changed, 108 insertions(+), 38 deletions(-) diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 932296144131..4158b7212936 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -40,6 +40,24 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list) */ #define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next))) +/* + * Check during list traversal that we are within an RCU reader + */ + +#define check_arg_count_one(dummy) + +#ifdef CONFIG_PROVE_RCU_LIST +#define __list_check_rcu(dummy, cond, extra...) \ + ({ \ + check_arg_count_one(extra); \ + RCU_LOCKDEP_WARN(!cond && !rcu_read_lock_any_held(), \ + "RCU-list traversed in non-reader section!"); \ + }) +#else +#define __list_check_rcu(dummy, cond, extra...) \ + ({ check_arg_count_one(extra); }) +#endif + /* * Insert a new entry between two known consecutive entries. * @@ -343,14 +361,16 @@ static inline void list_splice_tail_init_rcu(struct list_head *list, * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_head within the struct. + * @cond: optional lockdep expression if called from non-RCU protection. * * This list-traversal primitive may safely run concurrently with * the _rcu list-mutation primitives such as list_add_rcu() * as long as the traversal is guarded by rcu_read_lock(). */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ +#define list_for_each_entry_rcu(pos, head, member, cond...) \ + for (__list_check_rcu(dummy, ## cond, 0), \ + pos = list_entry_rcu((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) /** @@ -616,13 +636,15 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n, * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the hlist_node within the struct. + * @cond: optional lockdep expression if called from non-RCU protection. * * This list-traversal primitive may safely run concurrently with * the _rcu list-mutation primitives such as hlist_add_head_rcu() * as long as the traversal is guarded by rcu_read_lock(). */ -#define hlist_for_each_entry_rcu(pos, head, member) \ - for (pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\ +#define hlist_for_each_entry_rcu(pos, head, member, cond...) \ + for (__list_check_rcu(dummy, ## cond, 0), \ + pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\ typeof(*(pos)), member); \ pos; \ pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\ diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index bfcafbc1e301..80d6056f5855 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -221,6 +221,7 @@ int debug_lockdep_rcu_enabled(void); int rcu_read_lock_held(void); int rcu_read_lock_bh_held(void); int rcu_read_lock_sched_held(void); +int rcu_read_lock_any_held(void); #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ @@ -241,6 +242,12 @@ static inline int rcu_read_lock_sched_held(void) { return !preemptible(); } + +static inline int rcu_read_lock_any_held(void) +{ + return !preemptible(); +} + #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ #ifdef CONFIG_PROVE_RCU diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug index 5ec3ea4028e2..4aa02eee8f6c 100644 --- a/kernel/rcu/Kconfig.debug +++ b/kernel/rcu/Kconfig.debug @@ -8,6 +8,17 @@ menu "RCU Debugging" config PROVE_RCU def_bool PROVE_LOCKING +config PROVE_RCU_LIST + bool "RCU list lockdep debugging" + depends on PROVE_RCU && RCU_EXPERT + default n + help + Enable RCU lockdep checking for list usages. By default it is + turned off since there are several list RCU users that still + need to be converted to pass a lockdep expression. To prevent + false-positive splats, we keep it default disabled but once all + users are converted, we can remove this config option. + config TORTURE_TEST tristate default n diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 9dd5aeef6e70..38cbd616b381 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -61,9 +61,15 @@ module_param(rcu_normal_after_boot, int, 0); #ifdef CONFIG_DEBUG_LOCK_ALLOC /** - * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? + * rcu_read_lock_held_common() - might we be in RCU-sched read-side critical section? + * @ret: Best guess answer if lockdep cannot be relied on * - * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an + * Returns true if lockdep must be ignored, in which case *ret contains + * the best guess described below. Otherwise returns false, in which + * case *ret tells the caller nothing and the caller should instead + * consult lockdep. + * + * If CONFIG_DEBUG_LOCK_ALLOC is selected, set *ret to nonzero iff in an * RCU-sched read-side critical section. In absence of * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side * critical section unless it can prove otherwise. Note that disabling @@ -75,30 +81,44 @@ module_param(rcu_normal_after_boot, int, 0); * Check debug_lockdep_rcu_enabled() to prevent false positives during boot * and while lockdep is disabled. * - * Note that if the CPU is in the idle loop from an RCU point of - * view (ie: that we are in the section between rcu_idle_enter() and - * rcu_idle_exit()) then rcu_read_lock_held() returns false even if the CPU - * did an rcu_read_lock(). The reason for this is that RCU ignores CPUs - * that are in such a section, considering these as in extended quiescent - * state, so such a CPU is effectively never in an RCU read-side critical - * section regardless of what RCU primitives it invokes. This state of - * affairs is required --- we need to keep an RCU-free window in idle - * where the CPU may possibly enter into low power mode. This way we can - * notice an extended quiescent state to other CPUs that started a grace - * period. Otherwise we would delay any grace period as long as we run in - * the idle task. + * Note that if the CPU is in the idle loop from an RCU point of view (ie: + * that we are in the section between rcu_idle_enter() and rcu_idle_exit()) + * then rcu_read_lock_held() sets *ret to false even if the CPU did an + * rcu_read_lock(). The reason for this is that RCU ignores CPUs that are + * in such a section, considering these as in extended quiescent state, + * so such a CPU is effectively never in an RCU read-side critical section + * regardless of what RCU primitives it invokes. This state of affairs is + * required --- we need to keep an RCU-free window in idle where the CPU may + * possibly enter into low power mode. This way we can notice an extended + * quiescent state to other CPUs that started a grace period. Otherwise + * we would delay any grace period as long as we run in the idle task. * - * Similarly, we avoid claiming an SRCU read lock held if the current + * Similarly, we avoid claiming an RCU read lock held if the current * CPU is offline. */ +static bool rcu_read_lock_held_common(bool *ret) +{ + if (!debug_lockdep_rcu_enabled()) { + *ret = 1; + return true; + } + if (!rcu_is_watching()) { + *ret = 0; + return true; + } + if (!rcu_lockdep_current_cpu_online()) { + *ret = 0; + return true; + } + return false; +} + int rcu_read_lock_sched_held(void) { - if (!debug_lockdep_rcu_enabled()) - return 1; - if (!rcu_is_watching()) - return 0; - if (!rcu_lockdep_current_cpu_online()) - return 0; + bool ret; + + if (rcu_read_lock_held_common(&ret)) + return ret; return lock_is_held(&rcu_sched_lock_map) || !preemptible(); } EXPORT_SYMBOL(rcu_read_lock_sched_held); @@ -257,12 +277,10 @@ NOKPROBE_SYMBOL(debug_lockdep_rcu_enabled); */ int rcu_read_lock_held(void) { - if (!debug_lockdep_rcu_enabled()) - return 1; - if (!rcu_is_watching()) - return 0; - if (!rcu_lockdep_current_cpu_online()) - return 0; + bool ret; + + if (rcu_read_lock_held_common(&ret)) + return ret; return lock_is_held(&rcu_lock_map); } EXPORT_SYMBOL_GPL(rcu_read_lock_held); @@ -284,16 +302,28 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_held); */ int rcu_read_lock_bh_held(void) { - if (!debug_lockdep_rcu_enabled()) - return 1; - if (!rcu_is_watching()) - return 0; - if (!rcu_lockdep_current_cpu_online()) - return 0; + bool ret; + + if (rcu_read_lock_held_common(&ret)) + return ret; return in_softirq() || irqs_disabled(); } EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held); +int rcu_read_lock_any_held(void) +{ + bool ret; + + if (rcu_read_lock_held_common(&ret)) + return ret; + if (lock_is_held(&rcu_lock_map) || + lock_is_held(&rcu_bh_lock_map) || + lock_is_held(&rcu_sched_lock_map)) + return 1; + return !preemptible(); +} +EXPORT_SYMBOL_GPL(rcu_read_lock_any_held); + #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ /** -- GitLab From fbab8d6735e2643365040bd9e1057addc0d9b4cf Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Tue, 16 Jul 2019 18:12:23 -0400 Subject: [PATCH 2501/7155] rcu/sync: Remove custom check for RCU readers The rcu/sync code currently does a special check for being in an RCU read-side critical section. With RCU consolidating flavors and the generic helper added earlier in this series, this check is no longer need. This commit switches to the generic helper, saving a couple of lines of code. Cc: Oleg Nesterov Acked-by: Oleg Nesterov Signed-off-by: Joel Fernandes (Google) Signed-off-by: Paul E. McKenney --- include/linux/rcu_sync.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h index 9b83865d24f9..0027d4c8087c 100644 --- a/include/linux/rcu_sync.h +++ b/include/linux/rcu_sync.h @@ -31,9 +31,7 @@ struct rcu_sync { */ static inline bool rcu_sync_is_idle(struct rcu_sync *rsp) { - RCU_LOCKDEP_WARN(!rcu_read_lock_held() && - !rcu_read_lock_bh_held() && - !rcu_read_lock_sched_held(), + RCU_LOCKDEP_WARN(!rcu_read_lock_any_held(), "suspicious rcu_sync_is_idle() usage"); return !READ_ONCE(rsp->gp_state); /* GP_IDLE */ } -- GitLab From 7fd69b0ba48a2b2d8e5b4f0945b28d3839a7705a Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Tue, 16 Jul 2019 18:12:24 -0400 Subject: [PATCH 2502/7155] ipv4: Add lockdep condition to fix for_each_entry() This commit applies the consolidated list_for_each_entry_rcu() support for lockdep conditions. Acked-by: David S. Miller Signed-off-by: Joel Fernandes (Google) Signed-off-by: Paul E. McKenney --- net/ipv4/fib_frontend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e8bc939b56dd..dde77f72e03e 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -124,7 +124,8 @@ struct fib_table *fib_get_table(struct net *net, u32 id) h = id & (FIB_TABLE_HASHSZ - 1); head = &net->ipv4.fib_table_hash[h]; - hlist_for_each_entry_rcu(tb, head, tb_hlist) { + hlist_for_each_entry_rcu(tb, head, tb_hlist, + lockdep_rtnl_is_held()) { if (tb->tb_id == id) return tb; } -- GitLab From 1a9914884db5138682032cf69f2d55739f236c80 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 9 Aug 2019 05:04:47 -0700 Subject: [PATCH 2503/7155] tcp: batch calls to sk_flush_backlog() Starting from commit d41a69f1d390 ("tcp: make tcp_sendmsg() aware of socket backlog") loopback flows got hurt, because for each skb sent, the socket receives an immediate ACK and sk_flush_backlog() causes extra work. Intent was to not let the backlog grow too much, but we went a bit too far. We can check the backlog every 16 skbs (about 1MB chunks) to increase TCP over loopback performance by about 15 % Note that the call to sk_flush_backlog() handles a single ACK, thanks to coalescing done on backlog, but cleans the 16 skbs found in rtx rb-tree. Reported-by: Soheil Hassas Yeganeh Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a0a66321c0ee..f8fa1686f7f3 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1162,7 +1162,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) struct sockcm_cookie sockc; int flags, err, copied = 0; int mss_now = 0, size_goal, copied_syn = 0; - bool process_backlog = false; + int process_backlog = 0; bool zc = false; long timeo; @@ -1254,9 +1254,10 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; - if (process_backlog && sk_flush_backlog(sk)) { - process_backlog = false; - goto restart; + if (unlikely(process_backlog >= 16)) { + process_backlog = 0; + if (sk_flush_backlog(sk)) + goto restart; } first_skb = tcp_rtx_and_write_queues_empty(sk); skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation, @@ -1264,7 +1265,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) if (!skb) goto wait_for_memory; - process_backlog = true; + process_backlog++; skb->ip_summed = CHECKSUM_PARTIAL; skb_entail(sk, skb); -- GitLab From 1499218c80c99ae73c937c370142c8f6048002d5 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:17 +0200 Subject: [PATCH 2504/7155] arm64: dts: move common G12A & G12B modes to meson-g12-common.dtsi To simplify the representation of differences betweem the G12A and G12B SoCs, move the common nodes into a meson-g12-common.dtsi file and express the CPU nodes and differences in meson-g12a.dtsi and meson-g12b.dtsi. This separation will help for DVFS and future Amlogic SM1 Family support. The sd_emmc_a quirk is added in the g12a/g12b since since it's already known the sd_emmc_a controller is fixed in the next SM1 SoC family. Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- .../boot/dts/amlogic/meson-g12-common.dtsi | 2409 +++++++++++++++++ arch/arm64/boot/dts/amlogic/meson-g12a.dtsi | 2406 +--------------- arch/arm64/boot/dts/amlogic/meson-g12b.dtsi | 30 +- 3 files changed, 2440 insertions(+), 2405 deletions(-) create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi new file mode 100644 index 000000000000..06e186ca41e3 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -0,0 +1,2409 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Amlogic, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + tdmif_a: audio-controller-0 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_A"; + clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>, + <&clkc_audio AUD_CLKID_MST_A_SCLK>, + <&clkc_audio AUD_CLKID_MST_A_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; + + tdmif_b: audio-controller-1 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_B"; + clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>, + <&clkc_audio AUD_CLKID_MST_B_SCLK>, + <&clkc_audio AUD_CLKID_MST_B_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; + + tdmif_c: audio-controller-2 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_C"; + clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>, + <&clkc_audio AUD_CLKID_MST_C_SCLK>, + <&clkc_audio AUD_CLKID_MST_C_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; + + efuse: efuse { + compatible = "amlogic,meson-gxbb-efuse"; + clocks = <&clkc CLKID_EFUSE>; + #address-cells = <1>; + #size-cells = <1>; + read-only; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 3 MiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@5000000 { + reg = <0x0 0x05000000 0x0 0x300000>; + no-map; + }; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + linux,cma-default; + }; + }; + + sm: secure-monitor { + compatible = "amlogic,meson-gxbb-sm"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic,meson-axg-dwmac", + "snps,dwmac-3.70a", + "snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = ; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_MPLL2>; + clock-names = "stmmaceth", "clkin0", "clkin1"; + status = "disabled"; + + mdio0: mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + }; + }; + + apb: bus@ff600000 { + compatible = "simple-bus"; + reg = <0x0 0xff600000 0x0 0x200000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff600000 0x0 0x200000>; + + hdmi_tx: hdmi-tx@0 { + compatible = "amlogic,meson-g12a-dw-hdmi"; + reg = <0x0 0x0 0x0 0x10000>; + interrupts = ; + resets = <&reset RESET_HDMITX_CAPB3>, + <&reset RESET_HDMITX_PHY>, + <&reset RESET_HDMITX>; + reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy"; + clocks = <&clkc CLKID_HDMI>, + <&clkc CLKID_HTX_PCLK>, + <&clkc CLKID_VPU_INTR>; + clock-names = "isfr", "iahb", "venci"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <0>; + status = "disabled"; + + /* VPU VENC Input */ + hdmi_tx_venc_port: port@0 { + reg = <0>; + + hdmi_tx_in: endpoint { + remote-endpoint = <&hdmi_tx_out>; + }; + }; + + /* TMDS Output */ + hdmi_tx_tmds_port: port@1 { + reg = <1>; + }; + }; + + apb_efuse: bus@30000 { + compatible = "simple-bus"; + reg = <0x0 0x30000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x30000 0x0 0x2000>; + + hwrng: rng@218 { + compatible = "amlogic,meson-rng"; + reg = <0x0 0x218 0x0 0x4>; + }; + }; + + periphs: bus@34400 { + compatible = "simple-bus"; + reg = <0x0 0x34400 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>; + + periphs_pinctrl: pinctrl@40 { + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: bank@40 { + reg = <0x0 0x40 0x0 0x4c>, + <0x0 0xe8 0x0 0x18>, + <0x0 0x120 0x0 0x18>, + <0x0 0x2c0 0x0 0x40>, + <0x0 0x340 0x0 0x1c>; + reg-names = "gpio", + "pull", + "pull-enable", + "mux", + "ds"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&periphs_pinctrl 0 0 86>; + }; + + cec_ao_a_h_pins: cec_ao_a_h { + mux { + groups = "cec_ao_a_h"; + function = "cec_ao_a_h"; + bias-disable; + }; + }; + + cec_ao_b_h_pins: cec_ao_b_h { + mux { + groups = "cec_ao_b_h"; + function = "cec_ao_b_h"; + bias-disable; + }; + }; + + emmc_pins: emmc { + mux-0 { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "emmc_cmd"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + + mux-1 { + groups = "emmc_clk"; + function = "emmc"; + bias-disable; + drive-strength-microamp = <4000>; + }; + }; + + emmc_ds_pins: emmc-ds { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + emmc_clk_gate_pins: emmc_clk_gate { + mux { + groups = "BOOT_8"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + hdmitx_ddc_pins: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength-microamp = <4000>; + }; + }; + + hdmitx_hpd_pins: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + + i2c0_sda_c_pins: i2c0-sda-c { + mux { + groups = "i2c0_sda_c"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + + }; + }; + + i2c0_sck_c_pins: i2c0-sck-c { + mux { + groups = "i2c0_sck_c"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c0_sda_z0_pins: i2c0-sda-z0 { + mux { + groups = "i2c0_sda_z0"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c0_sck_z1_pins: i2c0-sck-z1 { + mux { + groups = "i2c0_sck_z1"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c0_sda_z7_pins: i2c0-sda-z7 { + mux { + groups = "i2c0_sda_z7"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c0_sda_z8_pins: i2c0-sda-z8 { + mux { + groups = "i2c0_sda_z8"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sda_x_pins: i2c1-sda-x { + mux { + groups = "i2c1_sda_x"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sck_x_pins: i2c1-sck-x { + mux { + groups = "i2c1_sck_x"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sda_h2_pins: i2c1-sda-h2 { + mux { + groups = "i2c1_sda_h2"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sck_h3_pins: i2c1-sck-h3 { + mux { + groups = "i2c1_sck_h3"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sda_h6_pins: i2c1-sda-h6 { + mux { + groups = "i2c1_sda_h6"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_sck_h7_pins: i2c1-sck-h7 { + mux { + groups = "i2c1_sck_h7"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c2_sda_x_pins: i2c2-sda-x { + mux { + groups = "i2c2_sda_x"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c2_sck_x_pins: i2c2-sck-x { + mux { + groups = "i2c2_sck_x"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c2_sda_z_pins: i2c2-sda-z { + mux { + groups = "i2c2_sda_z"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c2_sck_z_pins: i2c2-sck-z { + mux { + groups = "i2c2_sck_z"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_sda_h_pins: i2c3-sda-h { + mux { + groups = "i2c3_sda_h"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_sck_h_pins: i2c3-sck-h { + mux { + groups = "i2c3_sck_h"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_sda_a_pins: i2c3-sda-a { + mux { + groups = "i2c3_sda_a"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_sck_a_pins: i2c3-sck-a { + mux { + groups = "i2c3_sck_a"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + mclk0_a_pins: mclk0-a { + mux { + groups = "mclk0_a"; + function = "mclk0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + mclk1_a_pins: mclk1-a { + mux { + groups = "mclk1_a"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + mclk1_x_pins: mclk1-x { + mux { + groups = "mclk1_x"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + mclk1_z_pins: mclk1-z { + mux { + groups = "mclk1_z"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + pdm_din0_a_pins: pdm-din0-a { + mux { + groups = "pdm_din0_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din0_c_pins: pdm-din0-c { + mux { + groups = "pdm_din0_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din0_x_pins: pdm-din0-x { + mux { + groups = "pdm_din0_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din0_z_pins: pdm-din0-z { + mux { + groups = "pdm_din0_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din1_a_pins: pdm-din1-a { + mux { + groups = "pdm_din1_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din1_c_pins: pdm-din1-c { + mux { + groups = "pdm_din1_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din1_x_pins: pdm-din1-x { + mux { + groups = "pdm_din1_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din1_z_pins: pdm-din1-z { + mux { + groups = "pdm_din1_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din2_a_pins: pdm-din2-a { + mux { + groups = "pdm_din2_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din2_c_pins: pdm-din2-c { + mux { + groups = "pdm_din2_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din2_x_pins: pdm-din2-x { + mux { + groups = "pdm_din2_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din2_z_pins: pdm-din2-z { + mux { + groups = "pdm_din2_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din3_a_pins: pdm-din3-a { + mux { + groups = "pdm_din3_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din3_c_pins: pdm-din3-c { + mux { + groups = "pdm_din3_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din3_x_pins: pdm-din3-x { + mux { + groups = "pdm_din3_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_din3_z_pins: pdm-din3-z { + mux { + groups = "pdm_din3_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm_dclk_a_pins: pdm-dclk-a { + mux { + groups = "pdm_dclk_a"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <500>; + }; + }; + + pdm_dclk_c_pins: pdm-dclk-c { + mux { + groups = "pdm_dclk_c"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <500>; + }; + }; + + pdm_dclk_x_pins: pdm-dclk-x { + mux { + groups = "pdm_dclk_x"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <500>; + }; + }; + + pdm_dclk_z_pins: pdm-dclk-z { + mux { + groups = "pdm_dclk_z"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <500>; + }; + }; + + pwm_a_pins: pwm-a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + bias-disable; + }; + }; + + pwm_b_x7_pins: pwm-b-x7 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + bias-disable; + }; + }; + + pwm_b_x19_pins: pwm-b-x19 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + bias-disable; + }; + }; + + pwm_c_c_pins: pwm-c-c { + mux { + groups = "pwm_c_c"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm_c_x5_pins: pwm-c-x5 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm_c_x8_pins: pwm-c-x8 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm_d_x3_pins: pwm-d-x3 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + bias-disable; + }; + }; + + pwm_d_x6_pins: pwm-d-x6 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + bias-disable; + }; + }; + + pwm_e_pins: pwm-e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + bias-disable; + }; + }; + + pwm_f_x_pins: pwm-f-x { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + bias-disable; + }; + }; + + pwm_f_h_pins: pwm-f-h { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + bias-disable; + }; + }; + + sdcard_c_pins: sdcard_c { + mux-0 { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + + mux-1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-disable; + drive-strength-microamp = <4000>; + }; + }; + + sdcard_clk_gate_c_pins: sdcard_clk_gate_c { + mux { + groups = "GPIOC_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + sdcard_z_pins: sdcard_z { + mux-0 { + groups = "sdcard_d0_z", + "sdcard_d1_z", + "sdcard_d2_z", + "sdcard_d3_z", + "sdcard_cmd_z"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + + mux-1 { + groups = "sdcard_clk_z"; + function = "sdcard"; + bias-disable; + drive-strength-microamp = <4000>; + }; + }; + + sdcard_clk_gate_z_pins: sdcard_clk_gate_z { + mux { + groups = "GPIOZ_6"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + sdio_pins: sdio { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + bias-disable; + drive-strength-microamp = <4000>; + }; + }; + + sdio_clk_gate_pins: sdio_clk_gate { + mux { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + spdif_in_a10_pins: spdif-in-a10 { + mux { + groups = "spdif_in_a10"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif_in_a12_pins: spdif-in-a12 { + mux { + groups = "spdif_in_a12"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif_in_h_pins: spdif-in-h { + mux { + groups = "spdif_in_h"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif_out_h_pins: spdif-out-h { + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + drive-strength-microamp = <500>; + bias-disable; + }; + }; + + spdif_out_a11_pins: spdif-out-a11 { + mux { + groups = "spdif_out_a11"; + function = "spdif_out"; + drive-strength-microamp = <500>; + bias-disable; + }; + }; + + spdif_out_a13_pins: spdif-out-a13 { + mux { + groups = "spdif_out_a13"; + function = "spdif_out"; + drive-strength-microamp = <500>; + bias-disable; + }; + }; + + tdm_a_din0_pins: tdm-a-din0 { + mux { + groups = "tdm_a_din0"; + function = "tdm_a"; + bias-disable; + }; + }; + + + tdm_a_din1_pins: tdm-a-din1 { + mux { + groups = "tdm_a_din1"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm_a_dout0_pins: tdm-a-dout0 { + mux { + groups = "tdm_a_dout0"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_a_dout1_pins: tdm-a-dout1 { + mux { + groups = "tdm_a_dout1"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_a_fs_pins: tdm-a-fs { + mux { + groups = "tdm_a_fs"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_a_sclk_pins: tdm-a-sclk { + mux { + groups = "tdm_a_sclk"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_a_slv_fs_pins: tdm-a-slv-fs { + mux { + groups = "tdm_a_slv_fs"; + function = "tdm_a"; + bias-disable; + }; + }; + + + tdm_a_slv_sclk_pins: tdm-a-slv-sclk { + mux { + groups = "tdm_a_slv_sclk"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm_b_din0_pins: tdm-b-din0 { + mux { + groups = "tdm_b_din0"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_din1_pins: tdm-b-din1 { + mux { + groups = "tdm_b_din1"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_din2_pins: tdm-b-din2 { + mux { + groups = "tdm_b_din2"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_din3_a_pins: tdm-b-din3-a { + mux { + groups = "tdm_b_din3_a"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_din3_h_pins: tdm-b-din3-h { + mux { + groups = "tdm_b_din3_h"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_dout0_pins: tdm-b-dout0 { + mux { + groups = "tdm_b_dout0"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_dout1_pins: tdm-b-dout1 { + mux { + groups = "tdm_b_dout1"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_dout2_pins: tdm-b-dout2 { + mux { + groups = "tdm_b_dout2"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_dout3_a_pins: tdm-b-dout3-a { + mux { + groups = "tdm_b_dout3_a"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_dout3_h_pins: tdm-b-dout3-h { + mux { + groups = "tdm_b_dout3_h"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_fs_pins: tdm-b-fs { + mux { + groups = "tdm_b_fs"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_sclk_pins: tdm-b-sclk { + mux { + groups = "tdm_b_sclk"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_b_slv_fs_pins: tdm-b-slv-fs { + mux { + groups = "tdm_b_slv_fs"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_b_slv_sclk_pins: tdm-b-slv-sclk { + mux { + groups = "tdm_b_slv_sclk"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm_c_din0_a_pins: tdm-c-din0-a { + mux { + groups = "tdm_c_din0_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din0_z_pins: tdm-c-din0-z { + mux { + groups = "tdm_c_din0_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din1_a_pins: tdm-c-din1-a { + mux { + groups = "tdm_c_din1_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din1_z_pins: tdm-c-din1-z { + mux { + groups = "tdm_c_din1_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din2_a_pins: tdm-c-din2-a { + mux { + groups = "tdm_c_din2_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + eth_leds_pins: eth-leds { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + bias-disable; + }; + }; + + eth_pins: eth { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_txen", + "eth_txd0", + "eth_txd1"; + function = "eth"; + drive-strength-microamp = <4000>; + bias-disable; + }; + }; + + eth_rgmii_pins: eth-rgmii { + mux { + groups = "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength-microamp = <4000>; + bias-disable; + }; + }; + + tdm_c_din2_z_pins: tdm-c-din2-z { + mux { + groups = "tdm_c_din2_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din3_a_pins: tdm-c-din3-a { + mux { + groups = "tdm_c_din3_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_din3_z_pins: tdm-c-din3-z { + mux { + groups = "tdm_c_din3_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_dout0_a_pins: tdm-c-dout0-a { + mux { + groups = "tdm_c_dout0_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout0_z_pins: tdm-c-dout0-z { + mux { + groups = "tdm_c_dout0_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout1_a_pins: tdm-c-dout1-a { + mux { + groups = "tdm_c_dout1_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout1_z_pins: tdm-c-dout1-z { + mux { + groups = "tdm_c_dout1_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout2_a_pins: tdm-c-dout2-a { + mux { + groups = "tdm_c_dout2_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout2_z_pins: tdm-c-dout2-z { + mux { + groups = "tdm_c_dout2_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout3_a_pins: tdm-c-dout3-a { + mux { + groups = "tdm_c_dout3_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_dout3_z_pins: tdm-c-dout3-z { + mux { + groups = "tdm_c_dout3_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_fs_a_pins: tdm-c-fs-a { + mux { + groups = "tdm_c_fs_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_fs_z_pins: tdm-c-fs-z { + mux { + groups = "tdm_c_fs_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_sclk_a_pins: tdm-c-sclk-a { + mux { + groups = "tdm_c_sclk_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_sclk_z_pins: tdm-c-sclk-z { + mux { + groups = "tdm_c_sclk_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_c_slv_fs_a_pins: tdm-c-slv-fs-a { + mux { + groups = "tdm_c_slv_fs_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_slv_fs_z_pins: tdm-c-slv-fs-z { + mux { + groups = "tdm_c_slv_fs_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_slv_sclk_a_pins: tdm-c-slv-sclk-a { + mux { + groups = "tdm_c_slv_sclk_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm_c_slv_sclk_z_pins: tdm-c-slv-sclk-z { + mux { + groups = "tdm_c_slv_sclk_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + uart_a_pins: uart-a { + mux { + groups = "uart_a_tx", + "uart_a_rx"; + function = "uart_a"; + bias-disable; + }; + }; + + uart_a_cts_rts_pins: uart-a-cts-rts { + mux { + groups = "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + bias-disable; + }; + }; + + uart_b_pins: uart-b { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + bias-disable; + }; + }; + + uart_c_pins: uart-c { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + bias-disable; + }; + }; + + uart_c_cts_rts_pins: uart-c-cts-rts { + mux { + groups = "uart_c_cts", + "uart_c_rts"; + function = "uart_c"; + bias-disable; + }; + }; + }; + }; + + usb2_phy0: phy@36000 { + compatible = "amlogic,g12a-usb2-phy"; + reg = <0x0 0x36000 0x0 0x2000>; + clocks = <&xtal>; + clock-names = "xtal"; + resets = <&reset RESET_USB_PHY20>; + reset-names = "phy"; + #phy-cells = <0>; + }; + + dmc: bus@38000 { + compatible = "simple-bus"; + reg = <0x0 0x38000 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>; + + canvas: video-lut@48 { + compatible = "amlogic,canvas"; + reg = <0x0 0x48 0x0 0x14>; + }; + }; + + usb2_phy1: phy@3a000 { + compatible = "amlogic,g12a-usb2-phy"; + reg = <0x0 0x3a000 0x0 0x2000>; + clocks = <&xtal>; + clock-names = "xtal"; + resets = <&reset RESET_USB_PHY21>; + reset-names = "phy"; + #phy-cells = <0>; + }; + + hiu: bus@3c000 { + compatible = "simple-bus"; + reg = <0x0 0x3c000 0x0 0x1400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x3c000 0x0 0x1400>; + + hhi: system-controller@0 { + compatible = "amlogic,meson-gx-hhi-sysctrl", + "simple-mfd", "syscon"; + reg = <0 0 0 0x400>; + + clkc: clock-controller { + compatible = "amlogic,g12a-clkc"; + #clock-cells = <1>; + clocks = <&xtal>; + clock-names = "xtal"; + }; + }; + }; + + pdm: audio-controller@40000 { + compatible = "amlogic,g12a-pdm", + "amlogic,axg-pdm"; + reg = <0x0 0x40000 0x0 0x34>; + #sound-dai-cells = <0>; + sound-name-prefix = "PDM"; + clocks = <&clkc_audio AUD_CLKID_PDM>, + <&clkc_audio AUD_CLKID_PDM_DCLK>, + <&clkc_audio AUD_CLKID_PDM_SYSCLK>; + clock-names = "pclk", "dclk", "sysclk"; + status = "disabled"; + }; + + audio: bus@42000 { + compatible = "simple-bus"; + reg = <0x0 0x42000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x42000 0x0 0x2000>; + + clkc_audio: clock-controller@0 { + status = "disabled"; + compatible = "amlogic,g12a-audio-clkc"; + reg = <0x0 0x0 0x0 0xb4>; + #clock-cells = <1>; + + clocks = <&clkc CLKID_AUDIO>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL3>, + <&clkc CLKID_HIFI_PLL>, + <&clkc CLKID_FCLK_DIV3>, + <&clkc CLKID_FCLK_DIV4>, + <&clkc CLKID_GP0_PLL>; + clock-names = "pclk", + "mst_in0", + "mst_in1", + "mst_in2", + "mst_in3", + "mst_in4", + "mst_in5", + "mst_in6", + "mst_in7"; + + resets = <&reset RESET_AUDIO>; + }; + + toddr_a: audio-controller@100 { + compatible = "amlogic,g12a-toddr", + "amlogic,axg-toddr"; + reg = <0x0 0x100 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_A"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_TODDR_A>; + resets = <&arb AXG_ARB_TODDR_A>; + status = "disabled"; + }; + + toddr_b: audio-controller@140 { + compatible = "amlogic,g12a-toddr", + "amlogic,axg-toddr"; + reg = <0x0 0x140 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_B"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_TODDR_B>; + resets = <&arb AXG_ARB_TODDR_B>; + status = "disabled"; + }; + + toddr_c: audio-controller@180 { + compatible = "amlogic,g12a-toddr", + "amlogic,axg-toddr"; + reg = <0x0 0x180 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_C"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_TODDR_C>; + resets = <&arb AXG_ARB_TODDR_C>; + status = "disabled"; + }; + + frddr_a: audio-controller@1c0 { + compatible = "amlogic,g12a-frddr", + "amlogic,axg-frddr"; + reg = <0x0 0x1c0 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_A"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; + resets = <&arb AXG_ARB_FRDDR_A>; + status = "disabled"; + }; + + frddr_b: audio-controller@200 { + compatible = "amlogic,g12a-frddr", + "amlogic,axg-frddr"; + reg = <0x0 0x200 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_B"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_FRDDR_B>; + resets = <&arb AXG_ARB_FRDDR_B>; + status = "disabled"; + }; + + frddr_c: audio-controller@240 { + compatible = "amlogic,g12a-frddr", + "amlogic,axg-frddr"; + reg = <0x0 0x240 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_C"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_FRDDR_C>; + resets = <&arb AXG_ARB_FRDDR_C>; + status = "disabled"; + }; + + arb: reset-controller@280 { + status = "disabled"; + compatible = "amlogic,meson-axg-audio-arb"; + reg = <0x0 0x280 0x0 0x4>; + #reset-cells = <1>; + clocks = <&clkc_audio AUD_CLKID_DDR_ARB>; + }; + + tdmin_a: audio-controller@300 { + compatible = "amlogic,g12a-tdmin", + "amlogic,axg-tdmin"; + reg = <0x0 0x300 0x0 0x40>; + sound-name-prefix = "TDMIN_A"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_A>, + <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_b: audio-controller@340 { + compatible = "amlogic,g12a-tdmin", + "amlogic,axg-tdmin"; + reg = <0x0 0x340 0x0 0x40>; + sound-name-prefix = "TDMIN_B"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_B>, + <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_c: audio-controller@380 { + compatible = "amlogic,g12a-tdmin", + "amlogic,axg-tdmin"; + reg = <0x0 0x380 0x0 0x40>; + sound-name-prefix = "TDMIN_C"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_C>, + <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_lb: audio-controller@3c0 { + compatible = "amlogic,g12a-tdmin", + "amlogic,axg-tdmin"; + reg = <0x0 0x3c0 0x0 0x40>; + sound-name-prefix = "TDMIN_LB"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>, + <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + spdifin: audio-controller@400 { + compatible = "amlogic,g12a-spdifin", + "amlogic,axg-spdifin"; + reg = <0x0 0x400 0x0 0x30>; + #sound-dai-cells = <0>; + sound-name-prefix = "SPDIFIN"; + interrupts = ; + clocks = <&clkc_audio AUD_CLKID_SPDIFIN>, + <&clkc_audio AUD_CLKID_SPDIFIN_CLK>; + clock-names = "pclk", "refclk"; + status = "disabled"; + }; + + spdifout: audio-controller@480 { + compatible = "amlogic,g12a-spdifout", + "amlogic,axg-spdifout"; + reg = <0x0 0x480 0x0 0x50>; + #sound-dai-cells = <0>; + sound-name-prefix = "SPDIFOUT"; + clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>, + <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>; + clock-names = "pclk", "mclk"; + status = "disabled"; + }; + + tdmout_a: audio-controller@500 { + compatible = "amlogic,g12a-tdmout"; + reg = <0x0 0x500 0x0 0x40>; + sound-name-prefix = "TDMOUT_A"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmout_b: audio-controller@540 { + compatible = "amlogic,g12a-tdmout"; + reg = <0x0 0x540 0x0 0x40>; + sound-name-prefix = "TDMOUT_B"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>, + <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmout_c: audio-controller@580 { + compatible = "amlogic,g12a-tdmout"; + reg = <0x0 0x580 0x0 0x40>; + sound-name-prefix = "TDMOUT_C"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>, + <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + spdifout_b: audio-controller@680 { + compatible = "amlogic,g12a-spdifout", + "amlogic,axg-spdifout"; + reg = <0x0 0x680 0x0 0x50>; + #sound-dai-cells = <0>; + sound-name-prefix = "SPDIFOUT_B"; + clocks = <&clkc_audio AUD_CLKID_SPDIFOUT_B>, + <&clkc_audio AUD_CLKID_SPDIFOUT_B_CLK>; + clock-names = "pclk", "mclk"; + status = "disabled"; + }; + + tohdmitx: audio-controller@744 { + compatible = "amlogic,g12a-tohdmitx"; + reg = <0x0 0x744 0x0 0x4>; + #sound-dai-cells = <1>; + sound-name-prefix = "TOHDMITX"; + status = "disabled"; + }; + }; + + usb3_pcie_phy: phy@46000 { + compatible = "amlogic,g12a-usb3-pcie-phy"; + reg = <0x0 0x46000 0x0 0x2000>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "ref_clk"; + resets = <&reset RESET_PCIE_PHY>; + reset-names = "phy"; + assigned-clocks = <&clkc CLKID_PCIE_PLL>; + assigned-clock-rates = <100000000>; + #phy-cells = <1>; + }; + + eth_phy: mdio-multiplexer@4c000 { + compatible = "amlogic,g12a-mdio-mux"; + reg = <0x0 0x4c000 0x0 0xa4>; + clocks = <&clkc CLKID_ETH_PHY>, + <&xtal>, + <&clkc CLKID_MPLL_50M>; + clock-names = "pclk", "clkin0", "clkin1"; + mdio-parent-bus = <&mdio0>; + #address-cells = <1>; + #size-cells = <0>; + + ext_mdio: mdio@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + int_mdio: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + internal_ephy: ethernet_phy@8 { + compatible = "ethernet-phy-id0180.3301", + "ethernet-phy-ieee802.3-c22"; + interrupts = ; + reg = <8>; + max-speed = <100>; + }; + }; + }; + }; + + aobus: bus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0x100000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>; + + rti: sys-ctrl@0 { + compatible = "amlogic,meson-gx-ao-sysctrl", + "simple-mfd", "syscon"; + reg = <0x0 0x0 0x0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x0 0x0 0x100>; + + clkc_AO: clock-controller { + compatible = "amlogic,meson-g12a-aoclkc"; + #clock-cells = <1>; + #reset-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_CLK81>; + clock-names = "xtal", "mpeg-clk"; + }; + + pwrc_vpu: power-controller-vpu { + compatible = "amlogic,meson-g12a-pwrc-vpu"; + #power-domain-cells = <0>; + amlogic,hhi-sysctrl = <&hhi>; + resets = <&reset RESET_VIU>, + <&reset RESET_VENC>, + <&reset RESET_VCBUS>, + <&reset RESET_BT656>, + <&reset RESET_RDMA>, + <&reset RESET_VENCI>, + <&reset RESET_VENCP>, + <&reset RESET_VDAC>, + <&reset RESET_VDI6>, + <&reset RESET_VENCL>, + <&reset RESET_VID_LOCK>; + clocks = <&clkc CLKID_VPU>, + <&clkc CLKID_VAPB>; + clock-names = "vpu", "vapb"; + /* + * VPU clocking is provided by two identical clock paths + * VPU_0 and VPU_1 muxed to a single clock by a glitch + * free mux to safely change frequency while running. + * Same for VAPB but with a final gate after the glitch free mux. + */ + assigned-clocks = <&clkc CLKID_VPU_0_SEL>, + <&clkc CLKID_VPU_0>, + <&clkc CLKID_VPU>, /* Glitch free mux */ + <&clkc CLKID_VAPB_0_SEL>, + <&clkc CLKID_VAPB_0>, + <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */ + assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>, + <0>, /* Do Nothing */ + <&clkc CLKID_VPU_0>, + <&clkc CLKID_FCLK_DIV4>, + <0>, /* Do Nothing */ + <&clkc CLKID_VAPB_0>; + assigned-clock-rates = <0>, /* Do Nothing */ + <666666666>, + <0>, /* Do Nothing */ + <0>, /* Do Nothing */ + <250000000>, + <0>; /* Do Nothing */ + }; + + ao_pinctrl: pinctrl@14 { + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: bank@14 { + reg = <0x0 0x14 0x0 0x8>, + <0x0 0x1c 0x0 0x8>, + <0x0 0x24 0x0 0x14>; + reg-names = "mux", + "ds", + "gpio"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&ao_pinctrl 0 0 15>; + }; + + i2c_ao_sck_pins: i2c_ao_sck_pins { + mux { + groups = "i2c_ao_sck"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c_ao_sda_pins: i2c_ao_sda { + mux { + groups = "i2c_ao_sda"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c_ao_sck_e_pins: i2c_ao_sck_e { + mux { + groups = "i2c_ao_sck_e"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c_ao_sda_e_pins: i2c_ao_sda_e { + mux { + groups = "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + mclk0_ao_pins: mclk0-ao { + mux { + groups = "mclk0_ao"; + function = "mclk0_ao"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_din0_pins: tdm-ao-b-din0 { + mux { + groups = "tdm_ao_b_din0"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + spdif_ao_out_pins: spdif-ao-out { + mux { + groups = "spdif_ao_out"; + function = "spdif_ao_out"; + drive-strength-microamp = <500>; + bias-disable; + }; + }; + + tdm_ao_b_din1_pins: tdm-ao-b-din1 { + mux { + groups = "tdm_ao_b_din1"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm_ao_b_din2_pins: tdm-ao-b-din2 { + mux { + groups = "tdm_ao_b_din2"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm_ao_b_dout0_pins: tdm-ao-b-dout0 { + mux { + groups = "tdm_ao_b_dout0"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_dout1_pins: tdm-ao-b-dout1 { + mux { + groups = "tdm_ao_b_dout1"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_dout2_pins: tdm-ao-b-dout2 { + mux { + groups = "tdm_ao_b_dout2"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_fs_pins: tdm-ao-b-fs { + mux { + groups = "tdm_ao_b_fs"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_sclk_pins: tdm-ao-b-sclk { + mux { + groups = "tdm_ao_b_sclk"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs { + mux { + groups = "tdm_ao_b_slv_fs"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk { + mux { + groups = "tdm_ao_b_slv_sclk"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + uart_ao_a_pins: uart-a-ao { + mux { + groups = "uart_ao_a_tx", + "uart_ao_a_rx"; + function = "uart_ao_a"; + bias-disable; + }; + }; + + uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts { + mux { + groups = "uart_ao_a_cts", + "uart_ao_a_rts"; + function = "uart_ao_a"; + bias-disable; + }; + }; + + pwm_ao_a_pins: pwm-ao-a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + bias-disable; + }; + }; + + pwm_ao_b_pins: pwm-ao-b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + bias-disable; + }; + }; + + pwm_ao_c_4_pins: pwm-ao-c-4 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + bias-disable; + }; + }; + + pwm_ao_c_6_pins: pwm-ao-c-6 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + bias-disable; + }; + }; + + pwm_ao_d_5_pins: pwm-ao-d-5 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + bias-disable; + }; + }; + + pwm_ao_d_10_pins: pwm-ao-d-10 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + bias-disable; + }; + }; + + pwm_ao_d_e_pins: pwm-ao-d-e { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + remote_input_ao_pins: remote-input-ao { + mux { + groups = "remote_ao_input"; + function = "remote_ao_input"; + bias-disable; + }; + }; + }; + }; + + cec_AO: cec@100 { + compatible = "amlogic,meson-gx-ao-cec"; + reg = <0x0 0x00100 0x0 0x14>; + interrupts = ; + clocks = <&clkc_AO CLKID_AO_CEC>; + clock-names = "core"; + status = "disabled"; + }; + + sec_AO: ao-secure@140 { + compatible = "amlogic,meson-gx-ao-secure", "syscon"; + reg = <0x0 0x140 0x0 0x140>; + amlogic,has-chip-id; + }; + + cecb_AO: cec@280 { + compatible = "amlogic,meson-g12a-ao-cec"; + reg = <0x0 0x00280 0x0 0x1c>; + interrupts = ; + clocks = <&clkc_AO CLKID_AO_CTS_OSCIN>; + clock-names = "oscin"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,meson-g12a-ao-pwm-cd"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + uart_AO: serial@3000 { + compatible = "amlogic,meson-gx-uart", + "amlogic,meson-ao-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = ; + clocks = <&xtal>, <&clkc_AO CLKID_AO_UART>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic,meson-gx-uart", + "amlogic,meson-ao-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = ; + clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,meson-g12a-ao-pwm-ab"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + ir: ir@8000 { + compatible = "amlogic,meson-gxbb-ir"; + reg = <0x0 0x8000 0x0 0x20>; + interrupts = ; + status = "disabled"; + }; + + saradc: adc@9000 { + compatible = "amlogic,meson-g12a-saradc", + "amlogic,meson-saradc"; + reg = <0x0 0x9000 0x0 0x48>; + #io-channel-cells = <1>; + interrupts = ; + clocks = <&xtal>, + <&clkc_AO CLKID_AO_SAR_ADC>, + <&clkc_AO CLKID_AO_SAR_ADC_CLK>, + <&clkc_AO CLKID_AO_SAR_ADC_SEL>; + clock-names = "clkin", "core", "adc_clk", "adc_sel"; + status = "disabled"; + }; + }; + + vpu: vpu@ff900000 { + compatible = "amlogic,meson-g12a-vpu"; + reg = <0x0 0xff900000 0x0 0x100000>, + <0x0 0xff63c000 0x0 0x1000>; + reg-names = "vpu", "hhi"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + amlogic,canvas = <&canvas>; + power-domains = <&pwrc_vpu>; + + /* CVBS VDAC output port */ + cvbs_vdac_port: port@0 { + reg = <0>; + }; + + /* HDMI-TX output port */ + hdmi_tx_port: port@1 { + reg = <1>; + + hdmi_tx_out: endpoint { + remote-endpoint = <&hdmi_tx_in>; + }; + }; + }; + + gic: interrupt-controller@ffc01000 { + compatible = "arm,gic-400"; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x2000>, + <0x0 0xffc04000 0 0x2000>, + <0x0 0xffc06000 0 0x2000>; + interrupt-controller; + interrupts = ; + #interrupt-cells = <3>; + #address-cells = <0>; + }; + + cbus: bus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x100000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x100000>; + + reset: reset-controller@1004 { + compatible = "amlogic,meson-g12a-reset", + "amlogic,meson-axg-reset"; + reg = <0x0 0x1004 0x0 0x9c>; + #reset-cells = <1>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-g12a-gpio-intc", + "amlogic,meson-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + }; + + clk_msr: clock-measure@18000 { + compatible = "amlogic,meson-g12a-clk-measure"; + reg = <0x0 0x18000 0x0 0x10>; + }; + + uart_C: serial@22000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x0 0x22000 0x0 0x18>; + interrupts = ; + clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + + uart_B: serial@23000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x0 0x23000 0x0 0x18>; + interrupts = ; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + + uart_A: serial@24000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x0 0x24000 0x0 0x18>; + interrupts = ; + clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + }; + + sd_emmc_a: sd@ffe03000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe03000 0x0 0x800>; + interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_CLK0>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_A>; + }; + + sd_emmc_b: sd@ffe05000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_CLK0>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; + }; + + sd_emmc_c: mmc@ffe07000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_CLK0>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; + }; + + usb: usb@ffe09000 { + status = "disabled"; + compatible = "amlogic,meson-g12a-usb-ctrl"; + reg = <0x0 0xffe09000 0x0 0xa0>; + interrupts = ; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&clkc CLKID_USB>; + resets = <&reset RESET_USB>; + + dr_mode = "otg"; + + phys = <&usb2_phy0>, <&usb2_phy1>, + <&usb3_pcie_phy PHY_TYPE_USB3>; + phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0"; + + dwc2: usb@ff400000 { + compatible = "amlogic,meson-g12a-usb", "snps,dwc2"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = ; + clocks = <&clkc CLKID_USB1_DDR_BRIDGE>; + clock-names = "ddr"; + phys = <&usb2_phy1>; + phy-names = "usb2-phy"; + dr_mode = "peripheral"; + g-rx-fifo-size = <192>; + g-np-tx-fifo-size = <128>; + g-tx-fifo-size = <128 128 16 16 16>; + }; + + dwc3: usb@ff500000 { + compatible = "snps,dwc3"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = ; + dr_mode = "host"; + snps,dis_u2_susphy_quirk; + snps,quirk-frame-length-adjustment; + }; + }; + + mali: gpu@ffe40000 { + compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost"; + reg = <0x0 0xffe40000 0x0 0x40000>; + interrupt-parent = <&gic>; + interrupts = , + , + ; + interrupt-names = "gpu", "mmu", "job"; + clocks = <&clkc CLKID_MALI>; + resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>; + + /* + * Mali clocking is provided by two identical clock paths + * MALI_0 and MALI_1 muxed to a single clock by a glitch + * free mux to safely change frequency while running. + */ + assigned-clocks = <&clkc CLKID_MALI_0_SEL>, + <&clkc CLKID_MALI_0>, + <&clkc CLKID_MALI>; /* Glitch free mux */ + assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>, + <0>, /* Do Nothing */ + <&clkc CLKID_MALI_0>; + assigned-clock-rates = <0>, /* Do Nothing */ + <800000000>, + <0>; /* Do Nothing */ + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi index 1785552d450c..ac15967bb7fa 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -3,56 +3,11 @@ * Copyright (c) 2018 Amlogic, Inc. All rights reserved. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "meson-g12-common.dtsi" / { compatible = "amlogic,g12a"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - tdmif_a: audio-controller-0 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_A"; - clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>, - <&clkc_audio AUD_CLKID_MST_A_SCLK>, - <&clkc_audio AUD_CLKID_MST_A_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - - tdmif_b: audio-controller-1 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_B"; - clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>, - <&clkc_audio AUD_CLKID_MST_B_SCLK>, - <&clkc_audio AUD_CLKID_MST_B_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - - tdmif_c: audio-controller-2 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_C"; - clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>, - <&clkc_audio AUD_CLKID_MST_C_SCLK>, - <&clkc_audio AUD_CLKID_MST_C_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - cpus { #address-cells = <0x2>; #size-cells = <0x0>; @@ -93,2361 +48,8 @@ compatible = "cache"; }; }; +}; - efuse: efuse { - compatible = "amlogic,meson-gxbb-efuse"; - clocks = <&clkc CLKID_EFUSE>; - #address-cells = <1>; - #size-cells = <1>; - read-only; - }; - - psci { - compatible = "arm,psci-1.0"; - method = "smc"; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* 3 MiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@5000000 { - reg = <0x0 0x05000000 0x0 0x300000>; - no-map; - }; - - linux,cma { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x10000000>; - alignment = <0x0 0x400000>; - linux,cma-default; - }; - }; - - sm: secure-monitor { - compatible = "amlogic,meson-gxbb-sm"; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - ethmac: ethernet@ff3f0000 { - compatible = "amlogic,meson-axg-dwmac", - "snps,dwmac-3.70a", - "snps,dwmac"; - reg = <0x0 0xff3f0000 0x0 0x10000 - 0x0 0xff634540 0x0 0x8>; - interrupts = ; - interrupt-names = "macirq"; - clocks = <&clkc CLKID_ETH>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_MPLL2>; - clock-names = "stmmaceth", "clkin0", "clkin1"; - status = "disabled"; - - mdio0: mdio { - #address-cells = <1>; - #size-cells = <0>; - compatible = "snps,dwmac-mdio"; - }; - }; - - apb: bus@ff600000 { - compatible = "simple-bus"; - reg = <0x0 0xff600000 0x0 0x200000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xff600000 0x0 0x200000>; - - hdmi_tx: hdmi-tx@0 { - compatible = "amlogic,meson-g12a-dw-hdmi"; - reg = <0x0 0x0 0x0 0x10000>; - interrupts = ; - resets = <&reset RESET_HDMITX_CAPB3>, - <&reset RESET_HDMITX_PHY>, - <&reset RESET_HDMITX>; - reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy"; - clocks = <&clkc CLKID_HDMI>, - <&clkc CLKID_HTX_PCLK>, - <&clkc CLKID_VPU_INTR>; - clock-names = "isfr", "iahb", "venci"; - #address-cells = <1>; - #size-cells = <0>; - #sound-dai-cells = <0>; - status = "disabled"; - - /* VPU VENC Input */ - hdmi_tx_venc_port: port@0 { - reg = <0>; - - hdmi_tx_in: endpoint { - remote-endpoint = <&hdmi_tx_out>; - }; - }; - - /* TMDS Output */ - hdmi_tx_tmds_port: port@1 { - reg = <1>; - }; - }; - - apb_efuse: bus@30000 { - compatible = "simple-bus"; - reg = <0x0 0x30000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x30000 0x0 0x2000>; - - hwrng: rng@218 { - compatible = "amlogic,meson-rng"; - reg = <0x0 0x218 0x0 0x4>; - }; - }; - - periphs: bus@34400 { - compatible = "simple-bus"; - reg = <0x0 0x34400 0x0 0x400>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>; - - periphs_pinctrl: pinctrl@40 { - compatible = "amlogic,meson-g12a-periphs-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio: bank@40 { - reg = <0x0 0x40 0x0 0x4c>, - <0x0 0xe8 0x0 0x18>, - <0x0 0x120 0x0 0x18>, - <0x0 0x2c0 0x0 0x40>, - <0x0 0x340 0x0 0x1c>; - reg-names = "gpio", - "pull", - "pull-enable", - "mux", - "ds"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&periphs_pinctrl 0 0 86>; - }; - - cec_ao_a_h_pins: cec_ao_a_h { - mux { - groups = "cec_ao_a_h"; - function = "cec_ao_a_h"; - bias-disable; - }; - }; - - cec_ao_b_h_pins: cec_ao_b_h { - mux { - groups = "cec_ao_b_h"; - function = "cec_ao_b_h"; - bias-disable; - }; - }; - - emmc_pins: emmc { - mux-0 { - groups = "emmc_nand_d0", - "emmc_nand_d1", - "emmc_nand_d2", - "emmc_nand_d3", - "emmc_nand_d4", - "emmc_nand_d5", - "emmc_nand_d6", - "emmc_nand_d7", - "emmc_cmd"; - function = "emmc"; - bias-pull-up; - drive-strength-microamp = <4000>; - }; - - mux-1 { - groups = "emmc_clk"; - function = "emmc"; - bias-disable; - drive-strength-microamp = <4000>; - }; - }; - - emmc_ds_pins: emmc-ds { - mux { - groups = "emmc_nand_ds"; - function = "emmc"; - bias-pull-down; - drive-strength-microamp = <4000>; - }; - }; - - emmc_clk_gate_pins: emmc_clk_gate { - mux { - groups = "BOOT_8"; - function = "gpio_periphs"; - bias-pull-down; - drive-strength-microamp = <4000>; - }; - }; - - hdmitx_ddc_pins: hdmitx_ddc { - mux { - groups = "hdmitx_sda", - "hdmitx_sck"; - function = "hdmitx"; - bias-disable; - drive-strength-microamp = <4000>; - }; - }; - - hdmitx_hpd_pins: hdmitx_hpd { - mux { - groups = "hdmitx_hpd_in"; - function = "hdmitx"; - bias-disable; - }; - }; - - - i2c0_sda_c_pins: i2c0-sda-c { - mux { - groups = "i2c0_sda_c"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - - }; - }; - - i2c0_sck_c_pins: i2c0-sck-c { - mux { - groups = "i2c0_sck_c"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c0_sda_z0_pins: i2c0-sda-z0 { - mux { - groups = "i2c0_sda_z0"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c0_sck_z1_pins: i2c0-sck-z1 { - mux { - groups = "i2c0_sck_z1"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c0_sda_z7_pins: i2c0-sda-z7 { - mux { - groups = "i2c0_sda_z7"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c0_sda_z8_pins: i2c0-sda-z8 { - mux { - groups = "i2c0_sda_z8"; - function = "i2c0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sda_x_pins: i2c1-sda-x { - mux { - groups = "i2c1_sda_x"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sck_x_pins: i2c1-sck-x { - mux { - groups = "i2c1_sck_x"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sda_h2_pins: i2c1-sda-h2 { - mux { - groups = "i2c1_sda_h2"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sck_h3_pins: i2c1-sck-h3 { - mux { - groups = "i2c1_sck_h3"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sda_h6_pins: i2c1-sda-h6 { - mux { - groups = "i2c1_sda_h6"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c1_sck_h7_pins: i2c1-sck-h7 { - mux { - groups = "i2c1_sck_h7"; - function = "i2c1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c2_sda_x_pins: i2c2-sda-x { - mux { - groups = "i2c2_sda_x"; - function = "i2c2"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c2_sck_x_pins: i2c2-sck-x { - mux { - groups = "i2c2_sck_x"; - function = "i2c2"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c2_sda_z_pins: i2c2-sda-z { - mux { - groups = "i2c2_sda_z"; - function = "i2c2"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c2_sck_z_pins: i2c2-sck-z { - mux { - groups = "i2c2_sck_z"; - function = "i2c2"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c3_sda_h_pins: i2c3-sda-h { - mux { - groups = "i2c3_sda_h"; - function = "i2c3"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c3_sck_h_pins: i2c3-sck-h { - mux { - groups = "i2c3_sck_h"; - function = "i2c3"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c3_sda_a_pins: i2c3-sda-a { - mux { - groups = "i2c3_sda_a"; - function = "i2c3"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c3_sck_a_pins: i2c3-sck-a { - mux { - groups = "i2c3_sck_a"; - function = "i2c3"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - mclk0_a_pins: mclk0-a { - mux { - groups = "mclk0_a"; - function = "mclk0"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - mclk1_a_pins: mclk1-a { - mux { - groups = "mclk1_a"; - function = "mclk1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - mclk1_x_pins: mclk1-x { - mux { - groups = "mclk1_x"; - function = "mclk1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - mclk1_z_pins: mclk1-z { - mux { - groups = "mclk1_z"; - function = "mclk1"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - pdm_din0_a_pins: pdm-din0-a { - mux { - groups = "pdm_din0_a"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din0_c_pins: pdm-din0-c { - mux { - groups = "pdm_din0_c"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din0_x_pins: pdm-din0-x { - mux { - groups = "pdm_din0_x"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din0_z_pins: pdm-din0-z { - mux { - groups = "pdm_din0_z"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din1_a_pins: pdm-din1-a { - mux { - groups = "pdm_din1_a"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din1_c_pins: pdm-din1-c { - mux { - groups = "pdm_din1_c"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din1_x_pins: pdm-din1-x { - mux { - groups = "pdm_din1_x"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din1_z_pins: pdm-din1-z { - mux { - groups = "pdm_din1_z"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din2_a_pins: pdm-din2-a { - mux { - groups = "pdm_din2_a"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din2_c_pins: pdm-din2-c { - mux { - groups = "pdm_din2_c"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din2_x_pins: pdm-din2-x { - mux { - groups = "pdm_din2_x"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din2_z_pins: pdm-din2-z { - mux { - groups = "pdm_din2_z"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din3_a_pins: pdm-din3-a { - mux { - groups = "pdm_din3_a"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din3_c_pins: pdm-din3-c { - mux { - groups = "pdm_din3_c"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din3_x_pins: pdm-din3-x { - mux { - groups = "pdm_din3_x"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_din3_z_pins: pdm-din3-z { - mux { - groups = "pdm_din3_z"; - function = "pdm"; - bias-disable; - }; - }; - - pdm_dclk_a_pins: pdm-dclk-a { - mux { - groups = "pdm_dclk_a"; - function = "pdm"; - bias-disable; - drive-strength-microamp = <500>; - }; - }; - - pdm_dclk_c_pins: pdm-dclk-c { - mux { - groups = "pdm_dclk_c"; - function = "pdm"; - bias-disable; - drive-strength-microamp = <500>; - }; - }; - - pdm_dclk_x_pins: pdm-dclk-x { - mux { - groups = "pdm_dclk_x"; - function = "pdm"; - bias-disable; - drive-strength-microamp = <500>; - }; - }; - - pdm_dclk_z_pins: pdm-dclk-z { - mux { - groups = "pdm_dclk_z"; - function = "pdm"; - bias-disable; - drive-strength-microamp = <500>; - }; - }; - - pwm_a_pins: pwm-a { - mux { - groups = "pwm_a"; - function = "pwm_a"; - bias-disable; - }; - }; - - pwm_b_x7_pins: pwm-b-x7 { - mux { - groups = "pwm_b_x7"; - function = "pwm_b"; - bias-disable; - }; - }; - - pwm_b_x19_pins: pwm-b-x19 { - mux { - groups = "pwm_b_x19"; - function = "pwm_b"; - bias-disable; - }; - }; - - pwm_c_c_pins: pwm-c-c { - mux { - groups = "pwm_c_c"; - function = "pwm_c"; - bias-disable; - }; - }; - - pwm_c_x5_pins: pwm-c-x5 { - mux { - groups = "pwm_c_x5"; - function = "pwm_c"; - bias-disable; - }; - }; - - pwm_c_x8_pins: pwm-c-x8 { - mux { - groups = "pwm_c_x8"; - function = "pwm_c"; - bias-disable; - }; - }; - - pwm_d_x3_pins: pwm-d-x3 { - mux { - groups = "pwm_d_x3"; - function = "pwm_d"; - bias-disable; - }; - }; - - pwm_d_x6_pins: pwm-d-x6 { - mux { - groups = "pwm_d_x6"; - function = "pwm_d"; - bias-disable; - }; - }; - - pwm_e_pins: pwm-e { - mux { - groups = "pwm_e"; - function = "pwm_e"; - bias-disable; - }; - }; - - pwm_f_x_pins: pwm-f-x { - mux { - groups = "pwm_f_x"; - function = "pwm_f"; - bias-disable; - }; - }; - - pwm_f_h_pins: pwm-f-h { - mux { - groups = "pwm_f_h"; - function = "pwm_f"; - bias-disable; - }; - }; - - sdcard_c_pins: sdcard_c { - mux-0 { - groups = "sdcard_d0_c", - "sdcard_d1_c", - "sdcard_d2_c", - "sdcard_d3_c", - "sdcard_cmd_c"; - function = "sdcard"; - bias-pull-up; - drive-strength-microamp = <4000>; - }; - - mux-1 { - groups = "sdcard_clk_c"; - function = "sdcard"; - bias-disable; - drive-strength-microamp = <4000>; - }; - }; - - sdcard_clk_gate_c_pins: sdcard_clk_gate_c { - mux { - groups = "GPIOC_4"; - function = "gpio_periphs"; - bias-pull-down; - drive-strength-microamp = <4000>; - }; - }; - - sdcard_z_pins: sdcard_z { - mux-0 { - groups = "sdcard_d0_z", - "sdcard_d1_z", - "sdcard_d2_z", - "sdcard_d3_z", - "sdcard_cmd_z"; - function = "sdcard"; - bias-pull-up; - drive-strength-microamp = <4000>; - }; - - mux-1 { - groups = "sdcard_clk_z"; - function = "sdcard"; - bias-disable; - drive-strength-microamp = <4000>; - }; - }; - - sdcard_clk_gate_z_pins: sdcard_clk_gate_z { - mux { - groups = "GPIOZ_6"; - function = "gpio_periphs"; - bias-pull-down; - drive-strength-microamp = <4000>; - }; - }; - - sdio_pins: sdio { - mux { - groups = "sdio_d0", - "sdio_d1", - "sdio_d2", - "sdio_d3", - "sdio_clk", - "sdio_cmd"; - function = "sdio"; - bias-disable; - drive-strength-microamp = <4000>; - }; - }; - - sdio_clk_gate_pins: sdio_clk_gate { - mux { - groups = "GPIOX_4"; - function = "gpio_periphs"; - bias-pull-down; - drive-strength-microamp = <4000>; - }; - }; - - spdif_in_a10_pins: spdif-in-a10 { - mux { - groups = "spdif_in_a10"; - function = "spdif_in"; - bias-disable; - }; - }; - - spdif_in_a12_pins: spdif-in-a12 { - mux { - groups = "spdif_in_a12"; - function = "spdif_in"; - bias-disable; - }; - }; - - spdif_in_h_pins: spdif-in-h { - mux { - groups = "spdif_in_h"; - function = "spdif_in"; - bias-disable; - }; - }; - - spdif_out_h_pins: spdif-out-h { - mux { - groups = "spdif_out_h"; - function = "spdif_out"; - drive-strength-microamp = <500>; - bias-disable; - }; - }; - - spdif_out_a11_pins: spdif-out-a11 { - mux { - groups = "spdif_out_a11"; - function = "spdif_out"; - drive-strength-microamp = <500>; - bias-disable; - }; - }; - - spdif_out_a13_pins: spdif-out-a13 { - mux { - groups = "spdif_out_a13"; - function = "spdif_out"; - drive-strength-microamp = <500>; - bias-disable; - }; - }; - - tdm_a_din0_pins: tdm-a-din0 { - mux { - groups = "tdm_a_din0"; - function = "tdm_a"; - bias-disable; - }; - }; - - - tdm_a_din1_pins: tdm-a-din1 { - mux { - groups = "tdm_a_din1"; - function = "tdm_a"; - bias-disable; - }; - }; - - tdm_a_dout0_pins: tdm-a-dout0 { - mux { - groups = "tdm_a_dout0"; - function = "tdm_a"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_a_dout1_pins: tdm-a-dout1 { - mux { - groups = "tdm_a_dout1"; - function = "tdm_a"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_a_fs_pins: tdm-a-fs { - mux { - groups = "tdm_a_fs"; - function = "tdm_a"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_a_sclk_pins: tdm-a-sclk { - mux { - groups = "tdm_a_sclk"; - function = "tdm_a"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_a_slv_fs_pins: tdm-a-slv-fs { - mux { - groups = "tdm_a_slv_fs"; - function = "tdm_a"; - bias-disable; - }; - }; - - - tdm_a_slv_sclk_pins: tdm-a-slv-sclk { - mux { - groups = "tdm_a_slv_sclk"; - function = "tdm_a"; - bias-disable; - }; - }; - - tdm_b_din0_pins: tdm-b-din0 { - mux { - groups = "tdm_b_din0"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_din1_pins: tdm-b-din1 { - mux { - groups = "tdm_b_din1"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_din2_pins: tdm-b-din2 { - mux { - groups = "tdm_b_din2"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_din3_a_pins: tdm-b-din3-a { - mux { - groups = "tdm_b_din3_a"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_din3_h_pins: tdm-b-din3-h { - mux { - groups = "tdm_b_din3_h"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_dout0_pins: tdm-b-dout0 { - mux { - groups = "tdm_b_dout0"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_dout1_pins: tdm-b-dout1 { - mux { - groups = "tdm_b_dout1"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_dout2_pins: tdm-b-dout2 { - mux { - groups = "tdm_b_dout2"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_dout3_a_pins: tdm-b-dout3-a { - mux { - groups = "tdm_b_dout3_a"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_dout3_h_pins: tdm-b-dout3-h { - mux { - groups = "tdm_b_dout3_h"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_fs_pins: tdm-b-fs { - mux { - groups = "tdm_b_fs"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_sclk_pins: tdm-b-sclk { - mux { - groups = "tdm_b_sclk"; - function = "tdm_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_b_slv_fs_pins: tdm-b-slv-fs { - mux { - groups = "tdm_b_slv_fs"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_b_slv_sclk_pins: tdm-b-slv-sclk { - mux { - groups = "tdm_b_slv_sclk"; - function = "tdm_b"; - bias-disable; - }; - }; - - tdm_c_din0_a_pins: tdm-c-din0-a { - mux { - groups = "tdm_c_din0_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din0_z_pins: tdm-c-din0-z { - mux { - groups = "tdm_c_din0_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din1_a_pins: tdm-c-din1-a { - mux { - groups = "tdm_c_din1_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din1_z_pins: tdm-c-din1-z { - mux { - groups = "tdm_c_din1_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din2_a_pins: tdm-c-din2-a { - mux { - groups = "tdm_c_din2_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - eth_leds_pins: eth-leds { - mux { - groups = "eth_link_led", - "eth_act_led"; - function = "eth"; - bias-disable; - }; - }; - - eth_pins: eth { - mux { - groups = "eth_mdio", - "eth_mdc", - "eth_rgmii_rx_clk", - "eth_rx_dv", - "eth_rxd0", - "eth_rxd1", - "eth_txen", - "eth_txd0", - "eth_txd1"; - function = "eth"; - drive-strength-microamp = <4000>; - bias-disable; - }; - }; - - eth_rgmii_pins: eth-rgmii { - mux { - groups = "eth_rxd2_rgmii", - "eth_rxd3_rgmii", - "eth_rgmii_tx_clk", - "eth_txd2_rgmii", - "eth_txd3_rgmii"; - function = "eth"; - drive-strength-microamp = <4000>; - bias-disable; - }; - }; - - tdm_c_din2_z_pins: tdm-c-din2-z { - mux { - groups = "tdm_c_din2_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din3_a_pins: tdm-c-din3-a { - mux { - groups = "tdm_c_din3_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_din3_z_pins: tdm-c-din3-z { - mux { - groups = "tdm_c_din3_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_dout0_a_pins: tdm-c-dout0-a { - mux { - groups = "tdm_c_dout0_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout0_z_pins: tdm-c-dout0-z { - mux { - groups = "tdm_c_dout0_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout1_a_pins: tdm-c-dout1-a { - mux { - groups = "tdm_c_dout1_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout1_z_pins: tdm-c-dout1-z { - mux { - groups = "tdm_c_dout1_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout2_a_pins: tdm-c-dout2-a { - mux { - groups = "tdm_c_dout2_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout2_z_pins: tdm-c-dout2-z { - mux { - groups = "tdm_c_dout2_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout3_a_pins: tdm-c-dout3-a { - mux { - groups = "tdm_c_dout3_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_dout3_z_pins: tdm-c-dout3-z { - mux { - groups = "tdm_c_dout3_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_fs_a_pins: tdm-c-fs-a { - mux { - groups = "tdm_c_fs_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_fs_z_pins: tdm-c-fs-z { - mux { - groups = "tdm_c_fs_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_sclk_a_pins: tdm-c-sclk-a { - mux { - groups = "tdm_c_sclk_a"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_sclk_z_pins: tdm-c-sclk-z { - mux { - groups = "tdm_c_sclk_z"; - function = "tdm_c"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_c_slv_fs_a_pins: tdm-c-slv-fs-a { - mux { - groups = "tdm_c_slv_fs_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_slv_fs_z_pins: tdm-c-slv-fs-z { - mux { - groups = "tdm_c_slv_fs_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_slv_sclk_a_pins: tdm-c-slv-sclk-a { - mux { - groups = "tdm_c_slv_sclk_a"; - function = "tdm_c"; - bias-disable; - }; - }; - - tdm_c_slv_sclk_z_pins: tdm-c-slv-sclk-z { - mux { - groups = "tdm_c_slv_sclk_z"; - function = "tdm_c"; - bias-disable; - }; - }; - - uart_a_pins: uart-a { - mux { - groups = "uart_a_tx", - "uart_a_rx"; - function = "uart_a"; - bias-disable; - }; - }; - - uart_a_cts_rts_pins: uart-a-cts-rts { - mux { - groups = "uart_a_cts", - "uart_a_rts"; - function = "uart_a"; - bias-disable; - }; - }; - - uart_b_pins: uart-b { - mux { - groups = "uart_b_tx", - "uart_b_rx"; - function = "uart_b"; - bias-disable; - }; - }; - - uart_c_pins: uart-c { - mux { - groups = "uart_c_tx", - "uart_c_rx"; - function = "uart_c"; - bias-disable; - }; - }; - - uart_c_cts_rts_pins: uart-c-cts-rts { - mux { - groups = "uart_c_cts", - "uart_c_rts"; - function = "uart_c"; - bias-disable; - }; - }; - }; - }; - - usb2_phy0: phy@36000 { - compatible = "amlogic,g12a-usb2-phy"; - reg = <0x0 0x36000 0x0 0x2000>; - clocks = <&xtal>; - clock-names = "xtal"; - resets = <&reset RESET_USB_PHY20>; - reset-names = "phy"; - #phy-cells = <0>; - }; - - dmc: bus@38000 { - compatible = "simple-bus"; - reg = <0x0 0x38000 0x0 0x400>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>; - - canvas: video-lut@48 { - compatible = "amlogic,canvas"; - reg = <0x0 0x48 0x0 0x14>; - }; - }; - - usb2_phy1: phy@3a000 { - compatible = "amlogic,g12a-usb2-phy"; - reg = <0x0 0x3a000 0x0 0x2000>; - clocks = <&xtal>; - clock-names = "xtal"; - resets = <&reset RESET_USB_PHY21>; - reset-names = "phy"; - #phy-cells = <0>; - }; - - hiu: bus@3c000 { - compatible = "simple-bus"; - reg = <0x0 0x3c000 0x0 0x1400>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x3c000 0x0 0x1400>; - - hhi: system-controller@0 { - compatible = "amlogic,meson-gx-hhi-sysctrl", - "simple-mfd", "syscon"; - reg = <0 0 0 0x400>; - - clkc: clock-controller { - compatible = "amlogic,g12a-clkc"; - #clock-cells = <1>; - clocks = <&xtal>; - clock-names = "xtal"; - }; - }; - }; - - pdm: audio-controller@40000 { - compatible = "amlogic,g12a-pdm", - "amlogic,axg-pdm"; - reg = <0x0 0x40000 0x0 0x34>; - #sound-dai-cells = <0>; - sound-name-prefix = "PDM"; - clocks = <&clkc_audio AUD_CLKID_PDM>, - <&clkc_audio AUD_CLKID_PDM_DCLK>, - <&clkc_audio AUD_CLKID_PDM_SYSCLK>; - clock-names = "pclk", "dclk", "sysclk"; - status = "disabled"; - }; - - audio: bus@42000 { - compatible = "simple-bus"; - reg = <0x0 0x42000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x42000 0x0 0x2000>; - - clkc_audio: clock-controller@0 { - status = "disabled"; - compatible = "amlogic,g12a-audio-clkc"; - reg = <0x0 0x0 0x0 0xb4>; - #clock-cells = <1>; - - clocks = <&clkc CLKID_AUDIO>, - <&clkc CLKID_MPLL0>, - <&clkc CLKID_MPLL1>, - <&clkc CLKID_MPLL2>, - <&clkc CLKID_MPLL3>, - <&clkc CLKID_HIFI_PLL>, - <&clkc CLKID_FCLK_DIV3>, - <&clkc CLKID_FCLK_DIV4>, - <&clkc CLKID_GP0_PLL>; - clock-names = "pclk", - "mst_in0", - "mst_in1", - "mst_in2", - "mst_in3", - "mst_in4", - "mst_in5", - "mst_in6", - "mst_in7"; - - resets = <&reset RESET_AUDIO>; - }; - - toddr_a: audio-controller@100 { - compatible = "amlogic,g12a-toddr", - "amlogic,axg-toddr"; - reg = <0x0 0x100 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "TODDR_A"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_TODDR_A>; - resets = <&arb AXG_ARB_TODDR_A>; - status = "disabled"; - }; - - toddr_b: audio-controller@140 { - compatible = "amlogic,g12a-toddr", - "amlogic,axg-toddr"; - reg = <0x0 0x140 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "TODDR_B"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_TODDR_B>; - resets = <&arb AXG_ARB_TODDR_B>; - status = "disabled"; - }; - - toddr_c: audio-controller@180 { - compatible = "amlogic,g12a-toddr", - "amlogic,axg-toddr"; - reg = <0x0 0x180 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "TODDR_C"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_TODDR_C>; - resets = <&arb AXG_ARB_TODDR_C>; - status = "disabled"; - }; - - frddr_a: audio-controller@1c0 { - compatible = "amlogic,g12a-frddr", - "amlogic,axg-frddr"; - reg = <0x0 0x1c0 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "FRDDR_A"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; - resets = <&arb AXG_ARB_FRDDR_A>; - status = "disabled"; - }; - - frddr_b: audio-controller@200 { - compatible = "amlogic,g12a-frddr", - "amlogic,axg-frddr"; - reg = <0x0 0x200 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "FRDDR_B"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_FRDDR_B>; - resets = <&arb AXG_ARB_FRDDR_B>; - status = "disabled"; - }; - - frddr_c: audio-controller@240 { - compatible = "amlogic,g12a-frddr", - "amlogic,axg-frddr"; - reg = <0x0 0x240 0x0 0x1c>; - #sound-dai-cells = <0>; - sound-name-prefix = "FRDDR_C"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_FRDDR_C>; - resets = <&arb AXG_ARB_FRDDR_C>; - status = "disabled"; - }; - - arb: reset-controller@280 { - status = "disabled"; - compatible = "amlogic,meson-axg-audio-arb"; - reg = <0x0 0x280 0x0 0x4>; - #reset-cells = <1>; - clocks = <&clkc_audio AUD_CLKID_DDR_ARB>; - }; - - tdmin_a: audio-controller@300 { - compatible = "amlogic,g12a-tdmin", - "amlogic,axg-tdmin"; - reg = <0x0 0x300 0x0 0x40>; - sound-name-prefix = "TDMIN_A"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_A>, - <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_b: audio-controller@340 { - compatible = "amlogic,g12a-tdmin", - "amlogic,axg-tdmin"; - reg = <0x0 0x340 0x0 0x40>; - sound-name-prefix = "TDMIN_B"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_B>, - <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_c: audio-controller@380 { - compatible = "amlogic,g12a-tdmin", - "amlogic,axg-tdmin"; - reg = <0x0 0x380 0x0 0x40>; - sound-name-prefix = "TDMIN_C"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_C>, - <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_lb: audio-controller@3c0 { - compatible = "amlogic,g12a-tdmin", - "amlogic,axg-tdmin"; - reg = <0x0 0x3c0 0x0 0x40>; - sound-name-prefix = "TDMIN_LB"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>, - <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - spdifin: audio-controller@400 { - compatible = "amlogic,g12a-spdifin", - "amlogic,axg-spdifin"; - reg = <0x0 0x400 0x0 0x30>; - #sound-dai-cells = <0>; - sound-name-prefix = "SPDIFIN"; - interrupts = ; - clocks = <&clkc_audio AUD_CLKID_SPDIFIN>, - <&clkc_audio AUD_CLKID_SPDIFIN_CLK>; - clock-names = "pclk", "refclk"; - status = "disabled"; - }; - - spdifout: audio-controller@480 { - compatible = "amlogic,g12a-spdifout", - "amlogic,axg-spdifout"; - reg = <0x0 0x480 0x0 0x50>; - #sound-dai-cells = <0>; - sound-name-prefix = "SPDIFOUT"; - clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>, - <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>; - clock-names = "pclk", "mclk"; - status = "disabled"; - }; - - tdmout_a: audio-controller@500 { - compatible = "amlogic,g12a-tdmout"; - reg = <0x0 0x500 0x0 0x40>; - sound-name-prefix = "TDMOUT_A"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, - <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmout_b: audio-controller@540 { - compatible = "amlogic,g12a-tdmout"; - reg = <0x0 0x540 0x0 0x40>; - sound-name-prefix = "TDMOUT_B"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>, - <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmout_c: audio-controller@580 { - compatible = "amlogic,g12a-tdmout"; - reg = <0x0 0x580 0x0 0x40>; - sound-name-prefix = "TDMOUT_C"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>, - <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - spdifout_b: audio-controller@680 { - compatible = "amlogic,g12a-spdifout", - "amlogic,axg-spdifout"; - reg = <0x0 0x680 0x0 0x50>; - #sound-dai-cells = <0>; - sound-name-prefix = "SPDIFOUT_B"; - clocks = <&clkc_audio AUD_CLKID_SPDIFOUT_B>, - <&clkc_audio AUD_CLKID_SPDIFOUT_B_CLK>; - clock-names = "pclk", "mclk"; - status = "disabled"; - }; - - tohdmitx: audio-controller@744 { - compatible = "amlogic,g12a-tohdmitx"; - reg = <0x0 0x744 0x0 0x4>; - #sound-dai-cells = <1>; - sound-name-prefix = "TOHDMITX"; - status = "disabled"; - }; - }; - - usb3_pcie_phy: phy@46000 { - compatible = "amlogic,g12a-usb3-pcie-phy"; - reg = <0x0 0x46000 0x0 0x2000>; - clocks = <&clkc CLKID_PCIE_PLL>; - clock-names = "ref_clk"; - resets = <&reset RESET_PCIE_PHY>; - reset-names = "phy"; - assigned-clocks = <&clkc CLKID_PCIE_PLL>; - assigned-clock-rates = <100000000>; - #phy-cells = <1>; - }; - - eth_phy: mdio-multiplexer@4c000 { - compatible = "amlogic,g12a-mdio-mux"; - reg = <0x0 0x4c000 0x0 0xa4>; - clocks = <&clkc CLKID_ETH_PHY>, - <&xtal>, - <&clkc CLKID_MPLL_50M>; - clock-names = "pclk", "clkin0", "clkin1"; - mdio-parent-bus = <&mdio0>; - #address-cells = <1>; - #size-cells = <0>; - - ext_mdio: mdio@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - }; - - int_mdio: mdio@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - - internal_ephy: ethernet_phy@8 { - compatible = "ethernet-phy-id0180.3301", - "ethernet-phy-ieee802.3-c22"; - interrupts = ; - reg = <8>; - max-speed = <100>; - }; - }; - }; - }; - - aobus: bus@ff800000 { - compatible = "simple-bus"; - reg = <0x0 0xff800000 0x0 0x100000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>; - - rti: sys-ctrl@0 { - compatible = "amlogic,meson-gx-ao-sysctrl", - "simple-mfd", "syscon"; - reg = <0x0 0x0 0x0 0x100>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x0 0x0 0x100>; - - clkc_AO: clock-controller { - compatible = "amlogic,meson-g12a-aoclkc"; - #clock-cells = <1>; - #reset-cells = <1>; - clocks = <&xtal>, <&clkc CLKID_CLK81>; - clock-names = "xtal", "mpeg-clk"; - }; - - pwrc_vpu: power-controller-vpu { - compatible = "amlogic,meson-g12a-pwrc-vpu"; - #power-domain-cells = <0>; - amlogic,hhi-sysctrl = <&hhi>; - resets = <&reset RESET_VIU>, - <&reset RESET_VENC>, - <&reset RESET_VCBUS>, - <&reset RESET_BT656>, - <&reset RESET_RDMA>, - <&reset RESET_VENCI>, - <&reset RESET_VENCP>, - <&reset RESET_VDAC>, - <&reset RESET_VDI6>, - <&reset RESET_VENCL>, - <&reset RESET_VID_LOCK>; - clocks = <&clkc CLKID_VPU>, - <&clkc CLKID_VAPB>; - clock-names = "vpu", "vapb"; - /* - * VPU clocking is provided by two identical clock paths - * VPU_0 and VPU_1 muxed to a single clock by a glitch - * free mux to safely change frequency while running. - * Same for VAPB but with a final gate after the glitch free mux. - */ - assigned-clocks = <&clkc CLKID_VPU_0_SEL>, - <&clkc CLKID_VPU_0>, - <&clkc CLKID_VPU>, /* Glitch free mux */ - <&clkc CLKID_VAPB_0_SEL>, - <&clkc CLKID_VAPB_0>, - <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */ - assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>, - <0>, /* Do Nothing */ - <&clkc CLKID_VPU_0>, - <&clkc CLKID_FCLK_DIV4>, - <0>, /* Do Nothing */ - <&clkc CLKID_VAPB_0>; - assigned-clock-rates = <0>, /* Do Nothing */ - <666666666>, - <0>, /* Do Nothing */ - <0>, /* Do Nothing */ - <250000000>, - <0>; /* Do Nothing */ - }; - - ao_pinctrl: pinctrl@14 { - compatible = "amlogic,meson-g12a-aobus-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio_ao: bank@14 { - reg = <0x0 0x14 0x0 0x8>, - <0x0 0x1c 0x0 0x8>, - <0x0 0x24 0x0 0x14>; - reg-names = "mux", - "ds", - "gpio"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&ao_pinctrl 0 0 15>; - }; - - i2c_ao_sck_pins: i2c_ao_sck_pins { - mux { - groups = "i2c_ao_sck"; - function = "i2c_ao"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c_ao_sda_pins: i2c_ao_sda { - mux { - groups = "i2c_ao_sda"; - function = "i2c_ao"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c_ao_sck_e_pins: i2c_ao_sck_e { - mux { - groups = "i2c_ao_sck_e"; - function = "i2c_ao"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - i2c_ao_sda_e_pins: i2c_ao_sda_e { - mux { - groups = "i2c_ao_sda_e"; - function = "i2c_ao"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - mclk0_ao_pins: mclk0-ao { - mux { - groups = "mclk0_ao"; - function = "mclk0_ao"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_din0_pins: tdm-ao-b-din0 { - mux { - groups = "tdm_ao_b_din0"; - function = "tdm_ao_b"; - bias-disable; - }; - }; - - spdif_ao_out_pins: spdif-ao-out { - mux { - groups = "spdif_ao_out"; - function = "spdif_ao_out"; - drive-strength-microamp = <500>; - bias-disable; - }; - }; - - tdm_ao_b_din1_pins: tdm-ao-b-din1 { - mux { - groups = "tdm_ao_b_din1"; - function = "tdm_ao_b"; - bias-disable; - }; - }; - - tdm_ao_b_din2_pins: tdm-ao-b-din2 { - mux { - groups = "tdm_ao_b_din2"; - function = "tdm_ao_b"; - bias-disable; - }; - }; - - tdm_ao_b_dout0_pins: tdm-ao-b-dout0 { - mux { - groups = "tdm_ao_b_dout0"; - function = "tdm_ao_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_dout1_pins: tdm-ao-b-dout1 { - mux { - groups = "tdm_ao_b_dout1"; - function = "tdm_ao_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_dout2_pins: tdm-ao-b-dout2 { - mux { - groups = "tdm_ao_b_dout2"; - function = "tdm_ao_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_fs_pins: tdm-ao-b-fs { - mux { - groups = "tdm_ao_b_fs"; - function = "tdm_ao_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_sclk_pins: tdm-ao-b-sclk { - mux { - groups = "tdm_ao_b_sclk"; - function = "tdm_ao_b"; - bias-disable; - drive-strength-microamp = <3000>; - }; - }; - - tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs { - mux { - groups = "tdm_ao_b_slv_fs"; - function = "tdm_ao_b"; - bias-disable; - }; - }; - - tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk { - mux { - groups = "tdm_ao_b_slv_sclk"; - function = "tdm_ao_b"; - bias-disable; - }; - }; - - uart_ao_a_pins: uart-a-ao { - mux { - groups = "uart_ao_a_tx", - "uart_ao_a_rx"; - function = "uart_ao_a"; - bias-disable; - }; - }; - - uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts { - mux { - groups = "uart_ao_a_cts", - "uart_ao_a_rts"; - function = "uart_ao_a"; - bias-disable; - }; - }; - - pwm_ao_a_pins: pwm-ao-a { - mux { - groups = "pwm_ao_a"; - function = "pwm_ao_a"; - bias-disable; - }; - }; - - pwm_ao_b_pins: pwm-ao-b { - mux { - groups = "pwm_ao_b"; - function = "pwm_ao_b"; - bias-disable; - }; - }; - - pwm_ao_c_4_pins: pwm-ao-c-4 { - mux { - groups = "pwm_ao_c_4"; - function = "pwm_ao_c"; - bias-disable; - }; - }; - - pwm_ao_c_6_pins: pwm-ao-c-6 { - mux { - groups = "pwm_ao_c_6"; - function = "pwm_ao_c"; - bias-disable; - }; - }; - - pwm_ao_d_5_pins: pwm-ao-d-5 { - mux { - groups = "pwm_ao_d_5"; - function = "pwm_ao_d"; - bias-disable; - }; - }; - - pwm_ao_d_10_pins: pwm-ao-d-10 { - mux { - groups = "pwm_ao_d_10"; - function = "pwm_ao_d"; - bias-disable; - }; - }; - - pwm_ao_d_e_pins: pwm-ao-d-e { - mux { - groups = "pwm_ao_d_e"; - function = "pwm_ao_d"; - }; - }; - - remote_input_ao_pins: remote-input-ao { - mux { - groups = "remote_ao_input"; - function = "remote_ao_input"; - bias-disable; - }; - }; - }; - }; - - cec_AO: cec@100 { - compatible = "amlogic,meson-gx-ao-cec"; - reg = <0x0 0x00100 0x0 0x14>; - interrupts = ; - clocks = <&clkc_AO CLKID_AO_CEC>; - clock-names = "core"; - status = "disabled"; - }; - - sec_AO: ao-secure@140 { - compatible = "amlogic,meson-gx-ao-secure", "syscon"; - reg = <0x0 0x140 0x0 0x140>; - amlogic,has-chip-id; - }; - - cecb_AO: cec@280 { - compatible = "amlogic,meson-g12a-ao-cec"; - reg = <0x0 0x00280 0x0 0x1c>; - interrupts = ; - clocks = <&clkc_AO CLKID_AO_CTS_OSCIN>; - clock-names = "oscin"; - status = "disabled"; - }; - - pwm_AO_cd: pwm@2000 { - compatible = "amlogic,meson-g12a-ao-pwm-cd"; - reg = <0x0 0x2000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - uart_AO: serial@3000 { - compatible = "amlogic,meson-gx-uart", - "amlogic,meson-ao-uart"; - reg = <0x0 0x3000 0x0 0x18>; - interrupts = ; - clocks = <&xtal>, <&clkc_AO CLKID_AO_UART>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - status = "disabled"; - }; - - uart_AO_B: serial@4000 { - compatible = "amlogic,meson-gx-uart", - "amlogic,meson-ao-uart"; - reg = <0x0 0x4000 0x0 0x18>; - interrupts = ; - clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - status = "disabled"; - }; - - i2c_AO: i2c@5000 { - compatible = "amlogic,meson-axg-i2c"; - status = "disabled"; - reg = <0x0 0x05000 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_AO_ab: pwm@7000 { - compatible = "amlogic,meson-g12a-ao-pwm-ab"; - reg = <0x0 0x7000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - ir: ir@8000 { - compatible = "amlogic,meson-gxbb-ir"; - reg = <0x0 0x8000 0x0 0x20>; - interrupts = ; - status = "disabled"; - }; - - saradc: adc@9000 { - compatible = "amlogic,meson-g12a-saradc", - "amlogic,meson-saradc"; - reg = <0x0 0x9000 0x0 0x48>; - #io-channel-cells = <1>; - interrupts = ; - clocks = <&xtal>, - <&clkc_AO CLKID_AO_SAR_ADC>, - <&clkc_AO CLKID_AO_SAR_ADC_CLK>, - <&clkc_AO CLKID_AO_SAR_ADC_SEL>; - clock-names = "clkin", "core", "adc_clk", "adc_sel"; - status = "disabled"; - }; - }; - - vpu: vpu@ff900000 { - compatible = "amlogic,meson-g12a-vpu"; - reg = <0x0 0xff900000 0x0 0x100000>, - <0x0 0xff63c000 0x0 0x1000>; - reg-names = "vpu", "hhi"; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - amlogic,canvas = <&canvas>; - power-domains = <&pwrc_vpu>; - - /* CVBS VDAC output port */ - cvbs_vdac_port: port@0 { - reg = <0>; - }; - - /* HDMI-TX output port */ - hdmi_tx_port: port@1 { - reg = <1>; - - hdmi_tx_out: endpoint { - remote-endpoint = <&hdmi_tx_in>; - }; - }; - }; - - gic: interrupt-controller@ffc01000 { - compatible = "arm,gic-400"; - reg = <0x0 0xffc01000 0 0x1000>, - <0x0 0xffc02000 0 0x2000>, - <0x0 0xffc04000 0 0x2000>, - <0x0 0xffc06000 0 0x2000>; - interrupt-controller; - interrupts = ; - #interrupt-cells = <3>; - #address-cells = <0>; - }; - - cbus: bus@ffd00000 { - compatible = "simple-bus"; - reg = <0x0 0xffd00000 0x0 0x100000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x100000>; - - reset: reset-controller@1004 { - compatible = "amlogic,meson-g12a-reset", - "amlogic,meson-axg-reset"; - reg = <0x0 0x1004 0x0 0x9c>; - #reset-cells = <1>; - }; - - gpio_intc: interrupt-controller@f080 { - compatible = "amlogic,meson-g12a-gpio-intc", - "amlogic,meson-gpio-intc"; - reg = <0x0 0xf080 0x0 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>; - }; - - pwm_ef: pwm@19000 { - compatible = "amlogic,meson-g12a-ee-pwm"; - reg = <0x0 0x19000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - pwm_cd: pwm@1a000 { - compatible = "amlogic,meson-g12a-ee-pwm"; - reg = <0x0 0x1a000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - pwm_ab: pwm@1b000 { - compatible = "amlogic,meson-g12a-ee-pwm"; - reg = <0x0 0x1b000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - i2c3: i2c@1c000 { - compatible = "amlogic,meson-axg-i2c"; - status = "disabled"; - reg = <0x0 0x1c000 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - i2c2: i2c@1d000 { - compatible = "amlogic,meson-axg-i2c"; - status = "disabled"; - reg = <0x0 0x1d000 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - i2c1: i2c@1e000 { - compatible = "amlogic,meson-axg-i2c"; - status = "disabled"; - reg = <0x0 0x1e000 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - i2c0: i2c@1f000 { - compatible = "amlogic,meson-axg-i2c"; - status = "disabled"; - reg = <0x0 0x1f000 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - clk_msr: clock-measure@18000 { - compatible = "amlogic,meson-g12a-clk-measure"; - reg = <0x0 0x18000 0x0 0x10>; - }; - - uart_C: serial@22000 { - compatible = "amlogic,meson-gx-uart"; - reg = <0x0 0x22000 0x0 0x18>; - interrupts = ; - clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - status = "disabled"; - }; - - uart_B: serial@23000 { - compatible = "amlogic,meson-gx-uart"; - reg = <0x0 0x23000 0x0 0x18>; - interrupts = ; - clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - status = "disabled"; - }; - - uart_A: serial@24000 { - compatible = "amlogic,meson-gx-uart"; - reg = <0x0 0x24000 0x0 0x18>; - interrupts = ; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - status = "disabled"; - }; - }; - - sd_emmc_a: sd@ffe03000 { - compatible = "amlogic,meson-axg-mmc"; - reg = <0x0 0xffe03000 0x0 0x800>; - interrupts = ; - status = "disabled"; - clocks = <&clkc CLKID_SD_EMMC_A>, - <&clkc CLKID_SD_EMMC_A_CLK0>, - <&clkc CLKID_FCLK_DIV2>; - clock-names = "core", "clkin0", "clkin1"; - resets = <&reset RESET_SD_EMMC_A>; - amlogic,dram-access-quirk; - }; - - sd_emmc_b: sd@ffe05000 { - compatible = "amlogic,meson-axg-mmc"; - reg = <0x0 0xffe05000 0x0 0x800>; - interrupts = ; - status = "disabled"; - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_CLK0>, - <&clkc CLKID_FCLK_DIV2>; - clock-names = "core", "clkin0", "clkin1"; - resets = <&reset RESET_SD_EMMC_B>; - }; - - sd_emmc_c: mmc@ffe07000 { - compatible = "amlogic,meson-axg-mmc"; - reg = <0x0 0xffe07000 0x0 0x800>; - interrupts = ; - status = "disabled"; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_CLK0>, - <&clkc CLKID_FCLK_DIV2>; - clock-names = "core", "clkin0", "clkin1"; - resets = <&reset RESET_SD_EMMC_C>; - }; - - usb: usb@ffe09000 { - status = "disabled"; - compatible = "amlogic,meson-g12a-usb-ctrl"; - reg = <0x0 0xffe09000 0x0 0xa0>; - interrupts = ; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - clocks = <&clkc CLKID_USB>; - resets = <&reset RESET_USB>; - - dr_mode = "otg"; - - phys = <&usb2_phy0>, <&usb2_phy1>, - <&usb3_pcie_phy PHY_TYPE_USB3>; - phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0"; - - dwc2: usb@ff400000 { - compatible = "amlogic,meson-g12a-usb", "snps,dwc2"; - reg = <0x0 0xff400000 0x0 0x40000>; - interrupts = ; - clocks = <&clkc CLKID_USB1_DDR_BRIDGE>; - clock-names = "ddr"; - phys = <&usb2_phy1>; - phy-names = "usb2-phy"; - dr_mode = "peripheral"; - g-rx-fifo-size = <192>; - g-np-tx-fifo-size = <128>; - g-tx-fifo-size = <128 128 16 16 16>; - }; - - dwc3: usb@ff500000 { - compatible = "snps,dwc3"; - reg = <0x0 0xff500000 0x0 0x100000>; - interrupts = ; - dr_mode = "host"; - snps,dis_u2_susphy_quirk; - snps,quirk-frame-length-adjustment; - }; - }; - - mali: gpu@ffe40000 { - compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost"; - reg = <0x0 0xffe40000 0x0 0x40000>; - interrupt-parent = <&gic>; - interrupts = , - , - ; - interrupt-names = "gpu", "mmu", "job"; - clocks = <&clkc CLKID_MALI>; - resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>; - - /* - * Mali clocking is provided by two identical clock paths - * MALI_0 and MALI_1 muxed to a single clock by a glitch - * free mux to safely change frequency while running. - */ - assigned-clocks = <&clkc CLKID_MALI_0_SEL>, - <&clkc CLKID_MALI_0>, - <&clkc CLKID_MALI>; /* Glitch free mux */ - assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>, - <0>, /* Do Nothing */ - <&clkc CLKID_MALI_0>; - assigned-clock-rates = <0>, /* Do Nothing */ - <800000000>, - <0>; /* Do Nothing */ - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - +&sd_emmc_a { + amlogic,dram-access-quirk; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi index 9e88e513b22d..d5edbc1a1991 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi @@ -4,12 +4,15 @@ * Author: Neil Armstrong */ -#include "meson-g12a.dtsi" +#include "meson-g12-common.dtsi" / { compatible = "amlogic,g12b"; cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + cpu-map { cluster0 { core0 { @@ -40,8 +43,21 @@ }; }; - /delete-node/ cpu@2; - /delete-node/ cpu@3; + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x1>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; cpu100: cpu@100 { device_type = "cpu"; @@ -74,9 +90,17 @@ enable-method = "psci"; next-level-cache = <&l2>; }; + + l2: l2-cache0 { + compatible = "cache"; + }; }; }; &clkc { compatible = "amlogic,g12b-clkc"; }; + +&sd_emmc_a { + amlogic,dram-access-quirk; +}; -- GitLab From cca30c891247fc35655bc24836f46094771d3d47 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:18 +0200 Subject: [PATCH 2505/7155] arm64: dts: meson-g12-common: add pwm_a on GPIOE_2 pinmux Add the ao_pinctrl subnode for the pwm_a function on GPIOE_2. Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi index 06e186ca41e3..38d70ce1cfc7 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -1970,6 +1970,14 @@ }; }; + pwm_a_e_pins: pwm-a-e { + mux { + groups = "pwm_a_e"; + function = "pwm_a_e"; + bias-disable; + }; + }; + pwm_ao_a_pins: pwm-ao-a { mux { groups = "pwm_ao_a"; -- GitLab From b190056fa9eecc016b6a6e41f89a04da14b78bf7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:19 +0200 Subject: [PATCH 2506/7155] arm64: dts: meson-g12a: add cpus OPP table Add the OPP table taken from the vendor u200 and u211 DTS. The Amlogic G12A SoC seems to available in 3 types : - low-speed: up to 1,8GHz - mid-speed: up to 1,908GHz - high-speed: up to 2.1GHz And the S905X2 opp voltages are slightly higher than the S905D2 OPP voltages for the low-speed table. This adds the conservative OPP table with the S905X2 higher voltages and the maximum low-speed OPP frequency. The values were tested to be stable on an Amlogic U200 Reference Board, SeiRobotics SEI510 and X96 Max Set-Top-Boxes running the arm64 cpuburn at [1] and cycling between all the possible cpufreq translations and checking the final frequency using the clock-measurer, script at [2]. [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-g12a.dtsi | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi index ac15967bb7fa..733a9d46fc4b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -48,6 +48,66 @@ compatible = "cache"; }; }; + + cpu_opp_table: opp-table { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + + opp-667000000 { + opp-hz = /bits/ 64 <666666666>; + opp-microvolt = <731000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; }; &sd_emmc_a { -- GitLab From e9bc0765cc1274b7221360f462a3a993b41cac92 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:20 +0200 Subject: [PATCH 2507/7155] arm64: dts: meson-g12a: enable DVFS on G12A boards Enable DVFS for the U200, SEI520 and X96-Max Amlogic G12A based board by setting the clock, OPP and supply for each CPU cores. The CPU cluster power supply can achieve 0.73V to 1.01V using a PWM output clocked at 800KHz with an inverse duty-cycle. DVFS has been tested by running the arm64 cpuburn at [1] and cycling between all the possible cpufreq translations and checking the final frequency using the clock-measurer, script at [2]. [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- .../boot/dts/amlogic/meson-g12a-sei510.dts | 55 +++++++++++++++++++ .../boot/dts/amlogic/meson-g12a-u200.dts | 54 ++++++++++++++++++ .../boot/dts/amlogic/meson-g12a-x96-max.dts | 52 ++++++++++++++++++ 3 files changed, 161 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts index 12aa7eaeaf68..c9fa23a56562 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts @@ -129,6 +129,25 @@ enable-active-high; }; + vddcpu: regulator-vddcpu { + /* + * SY8120B1ABC DC/DC Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + + vin-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + vddio_ao1v8: regulator-vddio_ao1v8 { compatible = "regulator-fixed"; regulator-name = "VDDIO_AO1V8"; @@ -297,6 +316,34 @@ status = "okay"; }; +&cpu0 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu1 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu2 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu3 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + &cvbs_vdac_port { cvbs_vdac_out: endpoint { remote-endpoint = <&cvbs_connector_in>; @@ -345,6 +392,14 @@ pinctrl-names = "default"; }; +&pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin1"; + status = "okay"; +}; + &pwm_ef { status = "okay"; pinctrl-0 = <&pwm_e_pins>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts index 8551fbd4a488..2a324f0136e3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts @@ -129,6 +129,24 @@ regulator-always-on; }; + vddcpu: regulator-vddcpu { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + + vin-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; }; &cec_AO { @@ -145,6 +163,34 @@ hdmi-phandle = <&hdmi_tx>; }; +&cpu0 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu1 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu2 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu3 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + &cvbs_vdac_port { cvbs_vdac_out: endpoint { remote-endpoint = <&cvbs_connector_in>; @@ -197,6 +243,14 @@ pinctrl-names = "default"; }; +&pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin1"; + status = "okay"; +}; + /* SD card */ &sd_emmc_b { status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts index fe4013cca876..c1e58a69d434 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts @@ -132,6 +132,22 @@ regulator-always-on; }; + vddcpu: regulator-vddcpu { + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + + vin-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + sound { compatible = "amlogic,axg-sound-card"; model = "G12A-X96-MAX"; @@ -242,6 +258,34 @@ status = "okay"; }; +&cpu0 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu1 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu2 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu3 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + &cvbs_vdac_port { cvbs_vdac_out: endpoint { remote-endpoint = <&cvbs_connector_in>; @@ -279,6 +323,14 @@ pinctrl-names = "default"; }; +&pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin1"; + status = "okay"; +}; + &ext_mdio { external_phy: ethernet-phy@0 { /* Realtek RTL8211F (0x001cc916) */ -- GitLab From 53fbee339a9524787f698f10bd676c26643198d5 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:21 +0200 Subject: [PATCH 2508/7155] arm64: dts: meson-g12b: add cpus OPP tables Add the OPP table taken from the HardKernel Odroid-N2 DTS. The Amlogic G12B SoC seems to available in 2 types : - low-speed: Cortex-A73 Cluster up to 1,704GHz - high-speed: Cortex-A73 Cluster up to 2.208GHz The Cortex-A73 Cluster can be clocked up to 1,896GHz for both types. The Vendor Amlogic A311D OPP table are slighly different, with lower voltages than the HardKernel S922X tables but seems to be high-speed type. This adds the conservative OPP table with the S922X higher voltages and the maximum low-speed OPP frequency. The values were tested to be stable on an HardKernel Odroid-N2 board running the arm64 cpuburn at [1] and cycling between all the possible cpufreq translations for both clusters and checking the final frequency using the clock-measurer, script at [2]. [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-g12b.dtsi | 115 ++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi index d5edbc1a1991..98ae8a7c8b41 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi @@ -95,6 +95,121 @@ compatible = "cache"; }; }; + + cpu_opp_table_0: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + + opp-666666666 { + opp-hz = /bits/ 64 <666666666>; + opp-microvolt = <731000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + + opp-1896000000 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + }; + + cpub_opp_table_1: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + + opp-666666666 { + opp-hz = /bits/ 64 <666666666>; + opp-microvolt = <751000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <751000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; }; &clkc { -- GitLab From ef68984eab6bbe30a2a921c9440213cf5dded75b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 18 Jul 2019 11:03:01 +0200 Subject: [PATCH 2509/7155] arm64: dts: meson: add ethernet fifo sizes If unspecified in DT, the fifo sizes are not automatically detected by the dwmac1000 dma driver and the reported fifo sizes default to 0. Because of this, flow control will be turned off on the device. Add the fifo sizes provided by the datasheets in the SoC in DT so flow control may be enabled if necessary. Signed-off-by: Jerome Brunet Reviewed-by: Martin Blumenstingl Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 2 ++ arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 2 ++ arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 2 ++ 3 files changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi index 6219337033a0..12bf959c17a7 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi @@ -182,6 +182,8 @@ <&clkc CLKID_FCLK_DIV2>, <&clkc CLKID_MPLL2>; clock-names = "stmmaceth", "clkin0", "clkin1"; + rx-fifo-depth = <4096>; + tx-fifo-depth = <2048>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi index 38d70ce1cfc7..27bb242dc95d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -106,6 +106,8 @@ <&clkc CLKID_FCLK_DIV2>, <&clkc CLKID_MPLL2>; clock-names = "stmmaceth", "clkin0", "clkin1"; + rx-fifo-depth = <4096>; + tx-fifo-depth = <2048>; status = "disabled"; mdio0: mdio { diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi index 74d03fc706be..e62aad5bf867 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -493,6 +493,8 @@ 0x0 0xc8834540 0x0 0x4>; interrupts = ; interrupt-names = "macirq"; + rx-fifo-depth = <4096>; + tx-fifo-depth = <2048>; status = "disabled"; }; -- GitLab From 0b34189b0875040c80bfb99f71554411fadfb89f Mon Sep 17 00:00:00 2001 From: Maxime Jourdan Date: Fri, 26 Jul 2019 14:46:37 +0200 Subject: [PATCH 2510/7155] dt-bindings: media: amlogic,vdec: add default compatible The first version of the bindings is missing a generic compatible that is used by the base node (GX), and then extended by the SoC device trees (GXBB, GXL, GXM) Also change the example to use "video-codec" instead of "video-decoder", as the former is the one used in almost all cases when it comes to video decode/encode accelerators. Signed-off-by: Maxime Jourdan Reviewed-by: Neil Armstrong Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/media/amlogic,vdec.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/amlogic,vdec.txt b/Documentation/devicetree/bindings/media/amlogic,vdec.txt index aabdd01bcf32..9b6aace86ca7 100644 --- a/Documentation/devicetree/bindings/media/amlogic,vdec.txt +++ b/Documentation/devicetree/bindings/media/amlogic,vdec.txt @@ -26,6 +26,7 @@ Required properties: - GXBB (S905) : "amlogic,gxbb-vdec" - GXL (S905X, S905D) : "amlogic,gxl-vdec" - GXM (S912) : "amlogic,gxm-vdec" + followed by the common "amlogic,gx-vdec" - reg: base address and size of he following memory-mapped regions : - dos - esparser @@ -47,8 +48,8 @@ Required properties: Example: -vdec: video-decoder@c8820000 { - compatible = "amlogic,gxbb-vdec"; +vdec: video-codec@c8820000 { + compatible = "amlogic,gxbb-vdec", "amlogic,gx-vdec"; reg = <0x0 0xc8820000 0x0 0x10000>, <0x0 0xc110a580 0x0 0xe4>; reg-names = "dos", "esparser"; -- GitLab From 1f11d61182aeb97473490ce5d781d5f083ba33a1 Mon Sep 17 00:00:00 2001 From: Maxime Jourdan Date: Fri, 26 Jul 2019 14:46:38 +0200 Subject: [PATCH 2511/7155] arm64: dts: meson-gx: add video decoder entry Add the base video decoder node compatible with the meson vdec driver, for GX* chips. Signed-off-by: Maxime Jourdan Reviewed-by: Neil Armstrong Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi index e62aad5bf867..ca4b834c65d8 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -437,6 +437,20 @@ }; }; + vdec: video-codec@c8820000 { + compatible = "amlogic,gx-vdec"; + reg = <0x0 0xc8820000 0x0 0x10000>, + <0x0 0xc110a580 0x0 0xe4>; + reg-names = "dos", "esparser"; + + interrupts = , + ; + interrupt-names = "vdec", "esparser"; + + amlogic,ao-sysctrl = <&sysctrl_AO>; + amlogic,canvas = <&canvas>; + }; + periphs: periphs@c8834000 { compatible = "simple-bus"; reg = <0x0 0xc8834000 0x0 0x2000>; -- GitLab From 4be247f79ff4e21ba2ae8f94e8a8b4d6956e6be6 Mon Sep 17 00:00:00 2001 From: Maxime Jourdan Date: Fri, 26 Jul 2019 14:46:39 +0200 Subject: [PATCH 2512/7155] arm64: dts: meson: add video decoder entries This enables the video decoder for GXBB, GXL and GXM chips Signed-off-by: Maxime Jourdan Reviewed-by: Neil Armstrong Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 11 +++++++++++ arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 11 +++++++++++ arch/arm64/boot/dts/amlogic/meson-gxm.dtsi | 4 ++++ 3 files changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi index f734faaf7b78..0cb40326b0d3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -845,3 +845,14 @@ compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu"; power-domains = <&pwrc_vpu>; }; + +&vdec { + compatible = "amlogic,gxbb-vdec", "amlogic,gx-vdec"; + clocks = <&clkc CLKID_DOS_PARSER>, + <&clkc CLKID_DOS>, + <&clkc CLKID_VDEC_1>, + <&clkc CLKID_VDEC_HEVC>; + clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc"; + resets = <&reset RESET_PARSER>; + reset-names = "esparser"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi index c959456bacc6..a09c53aaa0e8 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi @@ -848,3 +848,14 @@ compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu"; power-domains = <&pwrc_vpu>; }; + +&vdec { + compatible = "amlogic,gxl-vdec", "amlogic,gx-vdec"; + clocks = <&clkc CLKID_DOS_PARSER>, + <&clkc CLKID_DOS>, + <&clkc CLKID_VDEC_1>, + <&clkc CLKID_VDEC_HEVC>; + clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc"; + resets = <&reset RESET_PARSER>; + reset-names = "esparser"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi index 7a85a82bf65d..a0e677d5a8f7 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi @@ -144,3 +144,7 @@ &dwc3 { phys = <&usb3_phy>, <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>; }; + +&vdec { + compatible = "amlogic,gxm-vdec", "amlogic,gx-vdec"; +}; -- GitLab From a742eda915e36732628e1a546e2deaeceb735c68 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 14:39:56 +0200 Subject: [PATCH 2513/7155] dt-bindings: arm: amlogic: add bindings for G12B based S922X SoC Add a specific compatible for the Amlogic G12B family based S922X SoC to differentiate with the A311D SoC from the same family. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index 325c6fd3566d..3c3bc806cd23 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -139,6 +139,7 @@ properties: items: - enum: - hardkernel,odroid-n2 + - const: amlogic,s922x - const: amlogic,g12b ... -- GitLab From a0250352e32b961397241b41771c8e629b5bbc61 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 31 Jul 2019 14:39:57 +0200 Subject: [PATCH 2514/7155] dt-bindings: arm: amlogic: add bindings for the Amlogic G12B based A311D SoC Add a specific compatible for the Amlogic G12B bases A311D SoC used in the Khadas VIM3. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index 3c3bc806cd23..efa032d12402 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -135,6 +135,11 @@ properties: - amlogic,u200 - const: amlogic,g12a + - description: Boards with the Amlogic Meson G12B A311D SoC + items: + - const: amlogic,a311d + - const: amlogic,g12b + - description: Boards with the Amlogic Meson G12B S922X SoC items: - enum: -- GitLab From 8f920256e9b661c85a01e7334eada2c7c8970493 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Wed, 31 Jul 2019 14:39:58 +0200 Subject: [PATCH 2515/7155] dt-bindings: arm: amlogic: add support for the Khadas VIM3 The Khadas VIM3 uses the Amlogic S922X or A311S SoC, both based on the Amlogic G12B SoC family, on a board with the same form factor as the VIM/VIM2 models. It ships in two variants; basic and pro which differ in RAM and eMMC size: - 2GB (basic) or 4GB (pro) LPDDR4 RAM - 16GB (basic) or 32GB (pro) eMMC 5.1 storage - 16MB SPI flash - 10/100/1000 Base-T Ethernet - AP6398S Wireless (802.11 a/b/g/n/ac, BT5.0) - HDMI 2.1 video - 1x USB 2.0 + 1x USB 3.0 ports - 1x USB-C (power) with USB 2.0 OTG - 3x LED's (1x red, 1x blue, 1x white) - 3x buttons (power, function, reset) - IR receiver - M2 socket with PCIe, USB, ADC & I2C - 40pin GPIO Header - 1x micro SD card slot Signed-off-by: Christian Hewitt Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index efa032d12402..04a2b0ef34c6 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -137,6 +137,8 @@ properties: - description: Boards with the Amlogic Meson G12B A311D SoC items: + - enum: + - khadas,vim3 - const: amlogic,a311d - const: amlogic,g12b @@ -144,6 +146,7 @@ properties: items: - enum: - hardkernel,odroid-n2 + - khadas,vim3 - const: amlogic,s922x - const: amlogic,g12b -- GitLab From b96d4e92709b5c4a0ab1494be76415a466c9c0c3 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Wed, 31 Jul 2019 14:39:59 +0200 Subject: [PATCH 2516/7155] arm64: dts: meson-g12b: support a311d and s922x cpu operating points Meson g12b ships with a low-speed (S922X) and high-speed (A311D) variant so remove cpu_opp_table nodes in meson-g12b.dtsi and create two new dtsi that can be included in device-specific dts files. Opp points were taken from the vendor BSP kernel. Also make meson-g12b-odroid-n2.dts include the new meson-g12b-s922x.dtsi. Signed-off-by: Christian Hewitt Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- .../boot/dts/amlogic/meson-g12b-a311d.dtsi | 149 ++++++++++++++++++ .../boot/dts/amlogic/meson-g12b-odroid-n2.dts | 2 +- .../boot/dts/amlogic/meson-g12b-s922x.dtsi | 124 +++++++++++++++ arch/arm64/boot/dts/amlogic/meson-g12b.dtsi | 115 -------------- 4 files changed, 274 insertions(+), 116 deletions(-) create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi new file mode 100644 index 000000000000..d61f43052a34 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include "meson-g12b.dtsi" + +/ { + cpu_opp_table_0: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + + opp-667000000 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <761000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <781000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <811000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <861000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <901000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <951000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; + }; + }; + + cpub_opp_table_1: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + + opp-667000000 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <751000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <771000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <771000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <781000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <791000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + + opp-1908000000 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + + opp-2016000000 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + + opp-2108000000 { + opp-hz = /bits/ 64 <2108000000>; + opp-microvolt = <951000>; + }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts index 4e916e1f71f7..237adae0ffae 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include "meson-g12b.dtsi" +#include "meson-g12b-s922x.dtsi" #include #include #include diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi new file mode 100644 index 000000000000..046cc332d07f --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include "meson-g12b.dtsi" + +/ { + cpu_opp_table_0: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + + opp-667000000 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + + opp-1896000000 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + }; + + cpub_opp_table_1: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + + opp-667000000 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + + opp-1398000000 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + + opp-1704000000 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi index 98ae8a7c8b41..d5edbc1a1991 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi @@ -95,121 +95,6 @@ compatible = "cache"; }; }; - - cpu_opp_table_0: opp-table-0 { - compatible = "operating-points-v2"; - opp-shared; - - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - - opp-666666666 { - opp-hz = /bits/ 64 <666666666>; - opp-microvolt = <731000>; - }; - - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - - opp-1398000000 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - - opp-1512000000 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - - opp-1608000000 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - - opp-1704000000 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - - opp-1896000000 { - opp-hz = /bits/ 64 <1896000000>; - opp-microvolt = <981000>; - }; - }; - - cpub_opp_table_1: opp-table-1 { - compatible = "operating-points-v2"; - opp-shared; - - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; - }; - - opp-666666666 { - opp-hz = /bits/ 64 <666666666>; - opp-microvolt = <751000>; - }; - - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <751000>; - }; - - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; - }; - - opp-1398000000 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; - }; - - opp-1512000000 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; - }; - - opp-1608000000 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; - }; - - opp-1704000000 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; - }; - }; }; &clkc { -- GitLab From a55022706068c461f13552fbbb4e0f8cf056933f Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 8 Aug 2019 09:44:48 -0700 Subject: [PATCH 2517/7155] arm64: dts: amlogic: g12 CPU timers stop in suspend The Arm per-CPU architected timers stop ticking in suspend, when the SCP powers down the CPUs. Flag that in the DT. Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi index 27bb242dc95d..cd3d23d2c6a2 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -2407,6 +2407,7 @@ (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, ; + arm,no-tick-in-suspend; }; xtal: xtal-clk { -- GitLab From 3a5e523479c49b082b8ac291a1a9fbd035c06df5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 9 Aug 2019 15:27:15 +0200 Subject: [PATCH 2518/7155] devlink: remove pointless data_len arg from region snapshot create The size of the snapshot has to be the same as the size of the region, therefore no need to pass it again during snapshot creation. Remove the arg and use region->size instead. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/crdump.c | 7 ++----- include/net/devlink.h | 2 +- net/core/devlink.c | 9 +++------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/crdump.c b/drivers/net/ethernet/mellanox/mlx4/crdump.c index 88316c743820..eaf08f7ad128 100644 --- a/drivers/net/ethernet/mellanox/mlx4/crdump.c +++ b/drivers/net/ethernet/mellanox/mlx4/crdump.c @@ -99,8 +99,7 @@ static void mlx4_crdump_collect_crspace(struct mlx4_dev *dev, readl(cr_space + offset); err = devlink_region_snapshot_create(crdump->region_crspace, - cr_res_size, crspace_data, - id, &kvfree); + crspace_data, id, &kvfree); if (err) { kvfree(crspace_data); mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n", @@ -139,9 +138,7 @@ static void mlx4_crdump_collect_fw_health(struct mlx4_dev *dev, readl(health_buf_start + offset); err = devlink_region_snapshot_create(crdump->region_fw_health, - HEALTH_BUFFER_SIZE, - health_data, - id, &kvfree); + health_data, id, &kvfree); if (err) { kvfree(health_data); mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n", diff --git a/include/net/devlink.h b/include/net/devlink.h index bc36f942a7d5..451268f64880 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -702,7 +702,7 @@ struct devlink_region *devlink_region_create(struct devlink *devlink, u64 region_size); void devlink_region_destroy(struct devlink_region *region); u32 devlink_region_shapshot_id_get(struct devlink *devlink); -int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, +int devlink_region_snapshot_create(struct devlink_region *region, u8 *data, u32 snapshot_id, devlink_snapshot_data_dest_t *data_destructor); int devlink_info_serial_number_put(struct devlink_info_req *req, diff --git a/net/core/devlink.c b/net/core/devlink.c index 4f40aeace902..e8f0b891f000 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -342,7 +342,6 @@ struct devlink_snapshot { struct list_head list; struct devlink_region *region; devlink_snapshot_data_dest_t *data_destructor; - u64 data_len; u8 *data; u32 id; }; @@ -3748,8 +3747,8 @@ static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, if (!snapshot) return -EINVAL; - if (end_offset > snapshot->data_len || dump) - end_offset = snapshot->data_len; + if (end_offset > region->size || dump) + end_offset = region->size; while (curr_offset < end_offset) { u32 data_size; @@ -6784,12 +6783,11 @@ EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); * The @snapshot_id should be obtained using the getter function. * * @region: devlink region of the snapshot - * @data_len: size of snapshot data * @data: snapshot data * @snapshot_id: snapshot id to be created * @data_destructor: pointer to destructor function to free data */ -int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, +int devlink_region_snapshot_create(struct devlink_region *region, u8 *data, u32 snapshot_id, devlink_snapshot_data_dest_t *data_destructor) { @@ -6819,7 +6817,6 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, snapshot->id = snapshot_id; snapshot->region = region; snapshot->data = data; - snapshot->data_len = data_len; snapshot->data_destructor = data_destructor; list_add_tail(&snapshot->list, ®ion->snapshot_list); -- GitLab From c04b79b6cfd714144f6a2cf359603d82ee631e62 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 7 Aug 2019 19:52:29 -0400 Subject: [PATCH 2519/7155] tcp: add new tcp_mtu_probe_floor sysctl The current implementation of TCP MTU probing can considerably underestimate the MTU on lossy connections allowing the MSS to get down to 48. We have found that in almost all of these cases on our networks these paths can handle much larger MTUs meaning the connections are being artificially limited. Even though TCP MTU probing can raise the MSS back up we have seen this not to be the case causing connections to be "stuck" with an MSS of 48 when heavy loss is present. Prior to pushing out this change we could not keep TCP MTU probing enabled b/c of the above reasons. Now with a reasonble floor set we've had it enabled for the past 6 months. The new sysctl will still default to TCP_MIN_SND_MSS (48), but gives administrators the ability to control the floor of MSS probing. Signed-off-by: Josh Hunt Signed-off-by: Eric Dumazet Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/net/netns/ipv4.h | 1 + net/ipv4/sysctl_net_ipv4.c | 9 +++++++++ net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_timer.c | 2 +- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index df33674799b5..49e95f438ed7 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -256,6 +256,12 @@ tcp_base_mss - INTEGER Path MTU discovery (MTU probing). If MTU probing is enabled, this is the initial MSS used by the connection. +tcp_mtu_probe_floor - INTEGER + If MTU probing is enabled this caps the minimum MSS used for search_low + for the connection. + + Default : 48 + tcp_min_snd_mss - INTEGER TCP SYN and SYNACK messages usually advertise an ADVMSS option, as described in RFC 1122 and RFC 6691. diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index bc24a8ec1ce5..c0c0791b1912 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -116,6 +116,7 @@ struct netns_ipv4 { int sysctl_tcp_l3mdev_accept; #endif int sysctl_tcp_mtu_probing; + int sysctl_tcp_mtu_probe_floor; int sysctl_tcp_base_mss; int sysctl_tcp_min_snd_mss; int sysctl_tcp_probe_threshold; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 0b980e841927..59ded25acd04 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -819,6 +819,15 @@ static struct ctl_table ipv4_net_table[] = { .extra1 = &tcp_min_snd_mss_min, .extra2 = &tcp_min_snd_mss_max, }, + { + .procname = "tcp_mtu_probe_floor", + .data = &init_net.ipv4.sysctl_tcp_mtu_probe_floor, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &tcp_min_snd_mss_min, + .extra2 = &tcp_min_snd_mss_max, + }, { .procname = "tcp_probe_threshold", .data = &init_net.ipv4.sysctl_tcp_probe_threshold, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d57641cb3477..e0a372676329 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2637,6 +2637,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS; net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; + net->ipv4.sysctl_tcp_mtu_probe_floor = TCP_MIN_SND_MSS; net->ipv4.sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME; net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c801cd37cc2a..dbd9d2d0ee63 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -154,7 +154,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) } else { mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; mss = min(net->ipv4.sysctl_tcp_base_mss, mss); - mss = max(mss, 68 - tcp_sk(sk)->tcp_header_len); + mss = max(mss, net->ipv4.sysctl_tcp_mtu_probe_floor); mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss); icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); } -- GitLab From 1555e6fdf062e2ae2514c67f46d475c7ebcce10e Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 7 Aug 2019 19:52:30 -0400 Subject: [PATCH 2520/7155] tcp: Update TCP_BASE_MSS comment TCP_BASE_MSS is used as the default initial MSS value when MTU probing is enabled. Update the comment to reflect this. Suggested-by: Neal Cardwell Signed-off-by: Josh Hunt Signed-off-by: Eric Dumazet Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 81e8ade1e6e4..9e9fbfaf052b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -64,7 +64,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); /* Minimal accepted MSS. It is (60+60+8) - (20+20). */ #define TCP_MIN_MSS 88U -/* The least MTU to use for probing */ +/* The initial MTU to use for probing */ #define TCP_BASE_MSS 1024 /* probing interval, default to 10 minutes as per RFC4821 */ -- GitLab From a7eb6a4f2560d5ae64bfac98d79d11378ca2de6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Hoffst=C3=A4tte?= Date: Fri, 9 Aug 2019 00:02:40 +0200 Subject: [PATCH 2521/7155] r8169: fix performance issue on RTL8168evl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disabling TSO but leaving SG active results is a significant performance drop. Therefore disable also SG on RTL8168evl. This restores the original performance. Fixes: 93681cd7d94f ("r8169: enable HW csum and TSO") Signed-off-by: Holger Hoffstätte Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index b2a275d8504c..912bd41eaa1b 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -6898,9 +6898,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* RTL8168e-vl has a HW issue with TSO */ if (tp->mac_version == RTL_GIGA_MAC_VER_34) { - dev->vlan_features &= ~NETIF_F_ALL_TSO; - dev->hw_features &= ~NETIF_F_ALL_TSO; - dev->features &= ~NETIF_F_ALL_TSO; + dev->vlan_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); + dev->hw_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); + dev->features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); } dev->hw_features |= NETIF_F_RXALL; -- GitLab From ca497fb6aa9fbd3b0a87fd0a71e9e1df2600ac30 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 9 Aug 2019 09:49:23 +0800 Subject: [PATCH 2522/7155] taprio: remove unused variable 'entry_list_policy' net/sched/sch_taprio.c:680:32: warning: entry_list_policy defined but not used [-Wunused-const-variable=] One of the points of commit a3d43c0d56f1 ("taprio: Add support adding an admin schedule") is that it removes support (it now returns "not supported") for schedules using the TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY attribute (which were never used), the parsing of those types of schedules was the only user of this policy. So removing this policy should be fine. Reported-by: Hulk Robot Suggested-by: Vinicius Costa Gomes Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- net/sched/sch_taprio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index c39db507ba3f..046fd2c102b4 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -677,10 +677,6 @@ static const struct nla_policy entry_policy[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { [TCA_TAPRIO_SCHED_ENTRY_INTERVAL] = { .type = NLA_U32 }, }; -static const struct nla_policy entry_list_policy[TCA_TAPRIO_SCHED_MAX + 1] = { - [TCA_TAPRIO_SCHED_ENTRY] = { .type = NLA_NESTED }, -}; - static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { [TCA_TAPRIO_ATTR_PRIOMAP] = { .len = sizeof(struct tc_mqprio_qopt) -- GitLab From 9e6717af61dfe6de304562602364a19d70c886d4 Mon Sep 17 00:00:00 2001 From: Zhongzhu Liu Date: Fri, 9 Aug 2019 10:31:07 +0800 Subject: [PATCH 2523/7155] net: hns3: fix GFP flag error in hclge_mac_update_stats() When CONFIG_DEBUG_ATOMIC_SLEEP on, calling kzalloc with GFP_KERNEL in hclge_mac_update_stats() will get below warning: [ 52.514677] BUG: sleeping function called from invalid context at mm/slab.h:501 [ 52.522051] in_atomic(): 0, irqs_disabled(): 0, pid: 1015, name: ifconfig [ 52.528827] 2 locks held by ifconfig/1015: [ 52.532921] #0: (____ptrval____) (&p->lock){....}, at: seq_read+0x54/0x748 [ 52.539878] #1: (____ptrval____) (rcu_read_lock){....}, at: dev_seq_start+0x0/0x140 [ 52.547610] CPU: 16 PID: 1015 Comm: ifconfig Not tainted 5.3.0-rc3-00697-g20b80be #98 [ 52.555408] Hardware name: Huawei TaiShan 2280 V2/BC82AMDC, BIOS 2280-V2 CS V3.B050.01 08/08/2019 [ 52.564242] Call trace: [ 52.566687] dump_backtrace+0x0/0x1f8 [ 52.570338] show_stack+0x14/0x20 [ 52.573646] dump_stack+0xb4/0xec [ 52.576950] ___might_sleep+0x178/0x198 [ 52.580773] __might_sleep+0x74/0xe0 [ 52.584338] __kmalloc+0x244/0x2d8 [ 52.587744] hclge_mac_update_stats+0xc8/0x1f8 [hclge] [ 52.592870] hclge_update_stats+0xe0/0x170 [hclge] [ 52.597651] hns3_nic_get_stats64+0xa0/0x458 [hns3] [ 52.602514] dev_get_stats+0x58/0x138 [ 52.606165] dev_seq_printf_stats+0x8c/0x280 [ 52.610420] dev_seq_show+0x14/0x40 [ 52.613898] seq_read+0x574/0x748 [ 52.617205] proc_reg_read+0xb4/0x108 [ 52.620857] __vfs_read+0x54/0xa8 [ 52.624162] vfs_read+0xa0/0x190 [ 52.627380] ksys_read+0xc8/0x178 [ 52.630685] __arm64_sys_read+0x40/0x50 [ 52.634509] el0_svc_common.constprop.0+0x120/0x1e0 [ 52.639369] el0_svc_handler+0x50/0x90 [ 52.643106] el0_svc+0x8/0xc So this patch uses GFP_ATOMIC instead of GFP_KERNEL to fix it. Fixes: d174ea75c96a ("net: hns3: add statistics for PFC frames and MAC control frames") Signed-off-by: Zhongzhu Liu Reviewed-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b7399f5ba2c3..c0feae3a9f86 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -364,9 +364,13 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) u16 i, k, n; int ret; - desc = kcalloc(desc_num, sizeof(struct hclge_desc), GFP_KERNEL); + /* This may be called inside atomic sections, + * so GFP_ATOMIC is more suitalbe here + */ + desc = kcalloc(desc_num, sizeof(struct hclge_desc), GFP_ATOMIC); if (!desc) return -ENOMEM; + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC_ALL, true); ret = hclge_cmd_send(&hdev->hw, desc, desc_num); if (ret) { -- GitLab From 130509213baeb3cada40c19dd87341a6787f8b23 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 9 Aug 2019 10:31:08 +0800 Subject: [PATCH 2524/7155] net: hns3: fix interrupt clearing error for VF Currently, VF driver has two kinds of interrupts, reset & CMDQ RX. For revision 0x21, according to the UM, each interrupt should be cleared by write 0 to the corresponding bit, but the implementation writes 0 to the whole register in fact, it will clear other interrupt at the same time, then the VF will loss the interrupt. But for revision 0x20, this interrupt clear register is a read & write register, for compatible, we just keep the old implementation for 0x20. This patch fixes it, also, adds a new register for reading the interrupt status according to hardware user manual. Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") Fixes: b90fcc5bd904 ("net: hns3: add reset handling for VF when doing Core/Global/IMP reset") Signed-off-by: Huazhong Tan Reviewed-by: Yunsheng Lin Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 28 +++++++++++++------ .../hisilicon/hns3/hns3vf/hclgevf_main.h | 2 ++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index ce82b2b0f8f5..d8b828180aa8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1889,21 +1889,20 @@ static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr) static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, u32 *clearval) { - u32 val, cmdq_src_reg, rst_ing_reg; + u32 val, cmdq_stat_reg, rst_ing_reg; /* fetch the events from their corresponding regs */ - cmdq_src_reg = hclgevf_read_dev(&hdev->hw, - HCLGEVF_VECTOR0_CMDQ_SRC_REG); + cmdq_stat_reg = hclgevf_read_dev(&hdev->hw, + HCLGEVF_VECTOR0_CMDQ_STAT_REG); - if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_src_reg) { + if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) { rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING); dev_info(&hdev->pdev->dev, "receive reset interrupt 0x%x!\n", rst_ing_reg); set_bit(HNAE3_VF_RESET, &hdev->reset_pending); set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state); - cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RST_INT_B); - *clearval = cmdq_src_reg; + *clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B); hdev->rst_stats.vf_rst_cnt++; /* set up VF hardware reset status, its PF will clear * this status when PF has initialized done. @@ -1915,9 +1914,20 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, } /* check for vector0 mailbox(=CMDQ RX) event source */ - if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) { - cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B); - *clearval = cmdq_src_reg; + if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_stat_reg) { + /* for revision 0x21, clearing interrupt is writing bit 0 + * to the clear register, writing bit 1 means to keep the + * old value. + * for revision 0x20, the clear register is a read & write + * register, so we should just write 0 to the bit we are + * handling, and keep other bits as cmdq_stat_reg. + */ + if (hdev->pdev->revision >= 0x21) + *clearval = ~(1U << HCLGEVF_VECTOR0_RX_CMDQ_INT_B); + else + *clearval = cmdq_stat_reg & + ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B); + return HCLGEVF_VECTOR0_EVENT_MBX; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index f0736b060884..4ccf107079eb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -87,6 +87,8 @@ /* Vector0 interrupt CMDQ event source register(RW) */ #define HCLGEVF_VECTOR0_CMDQ_SRC_REG 0x27100 +/* Vector0 interrupt CMDQ event status register(RO) */ +#define HCLGEVF_VECTOR0_CMDQ_STAT_REG 0x27104 /* CMDQ register bits for RX event(=MBX event) */ #define HCLGEVF_VECTOR0_RX_CMDQ_INT_B 1 /* RST register bits for RESET event */ -- GitLab From eb977d996e9316c66e4d9908fd12d682e4db14e9 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Fri, 9 Aug 2019 10:31:09 +0800 Subject: [PATCH 2525/7155] net: hns3: clean up for vlan handling in hns3_fill_desc_vtags This patch refactors the hns3_fill_desc_vtags function by avoiding passing too many parameters, reducing indent level and some other clean up. This patch also adds the hns3_fill_skb_desc function to fill the first desc of a skb. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 167 ++++++++++-------- 1 file changed, 89 insertions(+), 78 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index ed05fb9f04ed..fd6a3d589f40 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -45,6 +45,9 @@ MODULE_PARM_DESC(debug, " Network interface message level setting"); #define DEFAULT_MSG_LEVEL (NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) +#define HNS3_INNER_VLAN_TAG 1 +#define HNS3_OUTER_VLAN_TAG 2 + /* hns3_pci_tbl - PCI Device ID Table * * Last entry must be all 0s @@ -961,16 +964,16 @@ static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end) hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1U); } -static int hns3_fill_desc_vtags(struct sk_buff *skb, - struct hns3_enet_ring *tx_ring, - u32 *inner_vlan_flag, - u32 *out_vlan_flag, - u16 *inner_vtag, - u16 *out_vtag) +static int hns3_handle_vtags(struct hns3_enet_ring *tx_ring, + struct sk_buff *skb) { -#define HNS3_TX_VLAN_PRIO_SHIFT 13 - struct hnae3_handle *handle = tx_ring->tqp->handle; + struct vlan_ethhdr *vhdr; + int rc; + + if (!(skb->protocol == htons(ETH_P_8021Q) || + skb_vlan_tag_present(skb))) + return 0; /* Since HW limitation, if port based insert VLAN enabled, only one VLAN * header is allowed in skb, otherwise it will cause RAS error. @@ -981,8 +984,7 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb, return -EINVAL; if (skb->protocol == htons(ETH_P_8021Q) && - !(tx_ring->tqp->handle->kinfo.netdev->features & - NETIF_F_HW_VLAN_CTAG_TX)) { + !(handle->kinfo.netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) { /* When HW VLAN acceleration is turned off, and the stack * sets the protocol to 802.1q, the driver just need to * set the protocol to the encapsulated ethertype. @@ -992,45 +994,92 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb, } if (skb_vlan_tag_present(skb)) { - u16 vlan_tag; - - vlan_tag = skb_vlan_tag_get(skb); - vlan_tag |= (skb->priority & 0x7) << HNS3_TX_VLAN_PRIO_SHIFT; - /* Based on hw strategy, use out_vtag in two layer tag case, * and use inner_vtag in one tag case. */ - if (skb->protocol == htons(ETH_P_8021Q)) { - if (handle->port_base_vlan_state == - HNAE3_PORT_BASE_VLAN_DISABLE){ - hns3_set_field(*out_vlan_flag, - HNS3_TXD_OVLAN_B, 1); - *out_vtag = vlan_tag; - } else { - hns3_set_field(*inner_vlan_flag, - HNS3_TXD_VLAN_B, 1); - *inner_vtag = vlan_tag; - } - } else { - hns3_set_field(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1); - *inner_vtag = vlan_tag; - } - } else if (skb->protocol == htons(ETH_P_8021Q)) { - struct vlan_ethhdr *vhdr; - int rc; + if (skb->protocol == htons(ETH_P_8021Q) && + handle->port_base_vlan_state == + HNAE3_PORT_BASE_VLAN_DISABLE) + rc = HNS3_OUTER_VLAN_TAG; + else + rc = HNS3_INNER_VLAN_TAG; - rc = skb_cow_head(skb, 0); - if (unlikely(rc < 0)) - return rc; - vhdr = (struct vlan_ethhdr *)skb->data; - vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority & 0x7) - << HNS3_TX_VLAN_PRIO_SHIFT); + skb->protocol = vlan_get_protocol(skb); + return rc; } + rc = skb_cow_head(skb, 0); + if (unlikely(rc < 0)) + return rc; + + vhdr = (struct vlan_ethhdr *)skb->data; + vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority << VLAN_PRIO_SHIFT) + & VLAN_PRIO_MASK); + skb->protocol = vlan_get_protocol(skb); return 0; } +static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, + struct sk_buff *skb, struct hns3_desc *desc) +{ + u32 ol_type_vlan_len_msec = 0; + u32 type_cs_vlan_tso = 0; + u32 paylen = skb->len; + u16 inner_vtag = 0; + u16 out_vtag = 0; + u16 mss = 0; + int ret; + + ret = hns3_handle_vtags(ring, skb); + if (unlikely(ret < 0)) { + return ret; + } else if (ret == HNS3_INNER_VLAN_TAG) { + inner_vtag = skb_vlan_tag_get(skb); + inner_vtag |= (skb->priority << VLAN_PRIO_SHIFT) & + VLAN_PRIO_MASK; + hns3_set_field(type_cs_vlan_tso, HNS3_TXD_VLAN_B, 1); + } else if (ret == HNS3_OUTER_VLAN_TAG) { + out_vtag = skb_vlan_tag_get(skb); + out_vtag |= (skb->priority << VLAN_PRIO_SHIFT) & + VLAN_PRIO_MASK; + hns3_set_field(ol_type_vlan_len_msec, HNS3_TXD_OVLAN_B, + 1); + } + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + u8 ol4_proto, il4_proto; + + skb_reset_mac_len(skb); + + ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto); + if (unlikely(ret)) + return ret; + + ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto, + &type_cs_vlan_tso, + &ol_type_vlan_len_msec); + if (unlikely(ret)) + return ret; + + ret = hns3_set_tso(skb, &paylen, &mss, + &type_cs_vlan_tso); + if (unlikely(ret)) + return ret; + } + + /* Set txbd */ + desc->tx.ol_type_vlan_len_msec = + cpu_to_le32(ol_type_vlan_len_msec); + desc->tx.type_cs_vlan_tso_len = cpu_to_le32(type_cs_vlan_tso); + desc->tx.paylen = cpu_to_le32(paylen); + desc->tx.mss = cpu_to_le16(mss); + desc->tx.vlan_tag = cpu_to_le16(inner_vtag); + desc->tx.outer_vlan_tag = cpu_to_le16(out_vtag); + + return 0; +} + static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, unsigned int size, int frag_end, enum hns_desc_type type) @@ -1045,50 +1094,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, if (type == DESC_TYPE_SKB) { struct sk_buff *skb = (struct sk_buff *)priv; - u32 ol_type_vlan_len_msec = 0; - u32 type_cs_vlan_tso = 0; - u32 paylen = skb->len; - u16 inner_vtag = 0; - u16 out_vtag = 0; - u16 mss = 0; int ret; - ret = hns3_fill_desc_vtags(skb, ring, &type_cs_vlan_tso, - &ol_type_vlan_len_msec, - &inner_vtag, &out_vtag); + ret = hns3_fill_skb_desc(ring, skb, desc); if (unlikely(ret)) return ret; - if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 ol4_proto, il4_proto; - - skb_reset_mac_len(skb); - - ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto); - if (unlikely(ret)) - return ret; - - ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto, - &type_cs_vlan_tso, - &ol_type_vlan_len_msec); - if (unlikely(ret)) - return ret; - - ret = hns3_set_tso(skb, &paylen, &mss, - &type_cs_vlan_tso); - if (unlikely(ret)) - return ret; - } - - /* Set txbd */ - desc->tx.ol_type_vlan_len_msec = - cpu_to_le32(ol_type_vlan_len_msec); - desc->tx.type_cs_vlan_tso_len = cpu_to_le32(type_cs_vlan_tso); - desc->tx.paylen = cpu_to_le32(paylen); - desc->tx.mss = cpu_to_le16(mss); - desc->tx.vlan_tag = cpu_to_le16(inner_vtag); - desc->tx.outer_vlan_tag = cpu_to_le16(out_vtag); - dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); } else { frag = (skb_frag_t *)priv; -- GitLab From 7ac243f99d61f4580a72f62e638ed4e04aa52aa1 Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Fri, 9 Aug 2019 10:31:10 +0800 Subject: [PATCH 2526/7155] net: hns3: add input length check for debugfs write function If the input length reaches the maximum value of size_t, the reverse is triggered when 1 is added. In addition, there is no need to have such a large length. Therefore, the input length should be checked and the value should be less than or equal to 1024. Signed-off-by: Yufeng Mo Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index a4b937286f55..7996dcc21cf6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -8,6 +8,7 @@ #include "hns3_enet.h" #define HNS3_DBG_READ_LEN 256 +#define HNS3_DBG_WRITE_LEN 1024 static struct dentry *hns3_dbgfs_root; @@ -322,6 +323,9 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) return 0; + if (count > HNS3_DBG_WRITE_LEN) + return -ENOSPC; + cmd_buf = kzalloc(count + 1, GFP_KERNEL); if (!cmd_buf) return count; -- GitLab From aacbe27e82f01f6e0e3c2ab859d51d0823604ec8 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Fri, 9 Aug 2019 10:31:11 +0800 Subject: [PATCH 2527/7155] net: hns3: modify how pause options is displayed Currently, the pause options of HNS3 shown like this: "RX/TX" is always the same with "RX negotiated/TX negotiated". Because of the driver covered the value of "RX/TX" with the value of "RX negotiated/TX negotiated" after adjust link. This patch records the pause configurations of the user, and never covered them in adjust link. Signed-off-by: Yonglong Liu Reviewed-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c0feae3a9f86..381f19527d9d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8207,28 +8207,15 @@ static int hclge_cfg_pauseparam(struct hclge_dev *hdev, u32 rx_en, u32 tx_en) { int ret; - if (rx_en && tx_en) - hdev->fc_mode_last_time = HCLGE_FC_FULL; - else if (rx_en && !tx_en) - hdev->fc_mode_last_time = HCLGE_FC_RX_PAUSE; - else if (!rx_en && tx_en) - hdev->fc_mode_last_time = HCLGE_FC_TX_PAUSE; - else - hdev->fc_mode_last_time = HCLGE_FC_NONE; - if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) return 0; ret = hclge_mac_pause_en_cfg(hdev, tx_en, rx_en); - if (ret) { - dev_err(&hdev->pdev->dev, "configure pauseparam error, ret = %d.\n", - ret); - return ret; - } - - hdev->tm_info.fc_mode = hdev->fc_mode_last_time; + if (ret) + dev_err(&hdev->pdev->dev, + "configure pauseparam error, ret = %d.\n", ret); - return 0; + return ret; } int hclge_cfg_flowctrl(struct hclge_dev *hdev) @@ -8293,6 +8280,21 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg, } } +static void hclge_record_user_pauseparam(struct hclge_dev *hdev, + u32 rx_en, u32 tx_en) +{ + if (rx_en && tx_en) + hdev->fc_mode_last_time = HCLGE_FC_FULL; + else if (rx_en && !tx_en) + hdev->fc_mode_last_time = HCLGE_FC_RX_PAUSE; + else if (!rx_en && tx_en) + hdev->fc_mode_last_time = HCLGE_FC_TX_PAUSE; + else + hdev->fc_mode_last_time = HCLGE_FC_NONE; + + hdev->tm_info.fc_mode = hdev->fc_mode_last_time; +} + static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg, u32 rx_en, u32 tx_en) { @@ -8318,6 +8320,8 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg, hclge_set_flowctrl_adv(hdev, rx_en, tx_en); + hclge_record_user_pauseparam(hdev, rx_en, tx_en); + if (!auto_neg) return hclge_cfg_pauseparam(hdev, rx_en, tx_en); -- GitLab From ddb54554fa517be1639f10c6f2828429a871368b Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Fri, 9 Aug 2019 10:31:12 +0800 Subject: [PATCH 2528/7155] net: hns3: add DFX registers information for ethtool -d Now we can use ethtool -d command to dump some registers. However, these registers information is not enough to find out where the problem is. This patch adds DFX registers information after original registers when use ethtool -d commmand to dump registers. Also, using macro replaces some related magic number. Signed-off-by: Guangbin Huang Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 12 +- .../hisilicon/hns3/hns3pf/hclge_main.c | 342 +++++++++++++++--- .../hisilicon/hns3/hns3pf/hclge_main.h | 2 + 3 files changed, 301 insertions(+), 55 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index f16bfc67412a..933dec53ed8e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -14,16 +14,8 @@ static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset) struct hclge_desc desc[4]; int ret; - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_DFX_BD_NUM, true); - desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); - hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_DFX_BD_NUM, true); - desc[1].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); - hclge_cmd_setup_basic_desc(&desc[2], HCLGE_OPC_DFX_BD_NUM, true); - desc[2].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); - hclge_cmd_setup_basic_desc(&desc[3], HCLGE_OPC_DFX_BD_NUM, true); - - ret = hclge_cmd_send(&hdev->hw, desc, 4); - if (ret != HCLGE_CMD_EXEC_SUCCESS) { + ret = hclge_query_bd_num_cmd_send(hdev, desc); + if (ret) { dev_err(&hdev->pdev->dev, "get dfx bdnum fail, status is %d.\n", ret); return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 381f19527d9d..7d7ab9e66383 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -36,6 +36,20 @@ #define HCLGE_RESET_MAX_FAIL_CNT 5 +/* Get DFX BD number offset */ +#define HCLGE_DFX_BIOS_BD_OFFSET 1 +#define HCLGE_DFX_SSU_0_BD_OFFSET 2 +#define HCLGE_DFX_SSU_1_BD_OFFSET 3 +#define HCLGE_DFX_IGU_BD_OFFSET 4 +#define HCLGE_DFX_RPU_0_BD_OFFSET 5 +#define HCLGE_DFX_RPU_1_BD_OFFSET 6 +#define HCLGE_DFX_NCSI_BD_OFFSET 7 +#define HCLGE_DFX_RTC_BD_OFFSET 8 +#define HCLGE_DFX_PPP_BD_OFFSET 9 +#define HCLGE_DFX_RCB_BD_OFFSET 10 +#define HCLGE_DFX_TQP_BD_OFFSET 11 +#define HCLGE_DFX_SSU_2_BD_OFFSET 12 + static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); static int hclge_init_vlan_config(struct hclge_dev *hdev); static void hclge_sync_vlan_filter(struct hclge_dev *hdev); @@ -317,6 +331,36 @@ static const u8 hclge_hash_key[] = { 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA }; +static const u32 hclge_dfx_bd_offset_list[] = { + HCLGE_DFX_BIOS_BD_OFFSET, + HCLGE_DFX_SSU_0_BD_OFFSET, + HCLGE_DFX_SSU_1_BD_OFFSET, + HCLGE_DFX_IGU_BD_OFFSET, + HCLGE_DFX_RPU_0_BD_OFFSET, + HCLGE_DFX_RPU_1_BD_OFFSET, + HCLGE_DFX_NCSI_BD_OFFSET, + HCLGE_DFX_RTC_BD_OFFSET, + HCLGE_DFX_PPP_BD_OFFSET, + HCLGE_DFX_RCB_BD_OFFSET, + HCLGE_DFX_TQP_BD_OFFSET, + HCLGE_DFX_SSU_2_BD_OFFSET +}; + +static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { + HCLGE_OPC_DFX_BIOS_COMMON_REG, + HCLGE_OPC_DFX_SSU_REG_0, + HCLGE_OPC_DFX_SSU_REG_1, + HCLGE_OPC_DFX_IGU_EGU_REG, + HCLGE_OPC_DFX_RPU_REG_0, + HCLGE_OPC_DFX_RPU_REG_1, + HCLGE_OPC_DFX_NCSI_REG, + HCLGE_OPC_DFX_RTC_REG, + HCLGE_OPC_DFX_PPP_REG, + HCLGE_OPC_DFX_RCB_REG, + HCLGE_OPC_DFX_TQP_REG, + HCLGE_OPC_DFX_SSU_REG_2 +}; + static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) { #define HCLGE_MAC_CMD_NUM 21 @@ -9332,106 +9376,314 @@ static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, } #define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFFFFFFFF +#define SEPARATOR_VALUE 0xFDFCFBFA #define REG_NUM_PER_LINE 4 #define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) +#define REG_SEPARATOR_LINE 1 +#define REG_NUM_REMAIN_MASK 3 +#define BD_LIST_MAX_NUM 30 -static int hclge_get_regs_len(struct hnae3_handle *handle) +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) { - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - u32 regs_num_32_bit, regs_num_64_bit; + /*prepare 4 commands to query DFX BD number*/ + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_DFX_BD_NUM, true); + desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_DFX_BD_NUM, true); + desc[1].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[2], HCLGE_OPC_DFX_BD_NUM, true); + desc[2].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[3], HCLGE_OPC_DFX_BD_NUM, true); + + return hclge_cmd_send(&hdev->hw, desc, 4); +} + +static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev, + int *bd_num_list, + u32 type_num) +{ +#define HCLGE_DFX_REG_BD_NUM 4 + + u32 entries_per_desc, desc_index, index, offset, i; + struct hclge_desc desc[HCLGE_DFX_REG_BD_NUM]; int ret; - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + ret = hclge_query_bd_num_cmd_send(hdev, desc); if (ret) { dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return -EOPNOTSUPP; + "Get dfx bd num fail, status is %d.\n", ret); + return ret; } - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1; + entries_per_desc = ARRAY_SIZE(desc[0].data); + for (i = 0; i < type_num; i++) { + offset = hclge_dfx_bd_offset_list[i]; + index = offset % entries_per_desc; + desc_index = offset / entries_per_desc; + bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]); + } - return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE + - regs_num_32_bit * sizeof(u32) + regs_num_64_bit * sizeof(u64); + return ret; } -static void hclge_get_regs(struct hnae3_handle *handle, u32 *version, - void *data) +static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc_src, int bd_num, + enum hclge_opcode_type cmd) { - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - u32 regs_num_32_bit, regs_num_64_bit; - int i, j, reg_um, separator_num; + struct hclge_desc *desc = desc_src; + int i, ret; + + hclge_cmd_setup_basic_desc(desc, cmd, true); + for (i = 0; i < bd_num - 1; i++) { + desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + desc++; + hclge_cmd_setup_basic_desc(desc, cmd, true); + } + + desc = desc_src; + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(&hdev->pdev->dev, + "Query dfx reg cmd(0x%x) send fail, status is %d.\n", + cmd, ret); + + return ret; +} + +static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, + void *data) +{ + int entries_per_desc, reg_num, separator_num, desc_index, index, i; + struct hclge_desc *desc = desc_src; u32 *reg = data; + + entries_per_desc = ARRAY_SIZE(desc->data); + reg_num = entries_per_desc * bd_num; + separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) { + index = i % entries_per_desc; + desc_index = i / entries_per_desc; + *reg++ = le32_to_cpu(desc[desc_index].data[index]); + } + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + return reg_num + separator_num; +} + +static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int data_len_per_desc, data_len, bd_num, i; + int bd_num_list[BD_LIST_MAX_NUM]; int ret; - *version = hdev->fw_version; + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); + return ret; + } - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + data_len_per_desc = FIELD_SIZEOF(struct hclge_desc, data); + *len = 0; + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; + data_len = data_len_per_desc * bd_num; + *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; + } + + return ret; +} + +static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int bd_num, bd_num_max, buf_len, i; + int bd_num_list[BD_LIST_MAX_NUM]; + struct hclge_desc *desc_src; + u32 *reg = data; + int ret; + + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); if (ret) { dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return; + "Get dfx reg bd num fail, status is %d.\n", ret); + return ret; + } + + bd_num_max = bd_num_list[0]; + for (i = 1; i < dfx_reg_type_num; i++) + bd_num_max = max_t(int, bd_num_max, bd_num_list[i]); + + buf_len = sizeof(*desc_src) * bd_num_max; + desc_src = kzalloc(buf_len, GFP_KERNEL); + if (!desc_src) { + dev_err(&hdev->pdev->dev, "%s kzalloc failed\n", __func__); + return -ENOMEM; } + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; + ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num, + hclge_dfx_reg_opcode_list[i]); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg fail, status is %d.\n", ret); + break; + } + + reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); + } + + kfree(desc_src); + return ret; +} + +static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, + struct hnae3_knic_private_info *kinfo) +{ +#define HCLGE_RING_REG_OFFSET 0x200 +#define HCLGE_RING_INT_REG_OFFSET 0x4 + + int i, j, reg_num, separator_num; + int data_num_sum; + u32 *reg = data; + /* fetching per-PF registers valus from PF PCIe register space */ - reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) + reg_num = ARRAY_SIZE(cmdq_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); for (i = 0; i < separator_num; i++) *reg++ = SEPARATOR_VALUE; + data_num_sum = reg_num + separator_num; - reg_um = sizeof(common_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) + reg_num = ARRAY_SIZE(common_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); for (i = 0; i < separator_num; i++) *reg++ = SEPARATOR_VALUE; + data_num_sum += reg_num + separator_num; - reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + reg_num = ARRAY_SIZE(ring_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); for (j = 0; j < kinfo->num_tqps; j++) { - for (i = 0; i < reg_um; i++) + for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, ring_reg_addr_list[i] + - 0x200 * j); + HCLGE_RING_REG_OFFSET * j); for (i = 0; i < separator_num; i++) *reg++ = SEPARATOR_VALUE; } + data_num_sum += (reg_num + separator_num) * kinfo->num_tqps; - reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); for (j = 0; j < hdev->num_msi_used - 1; j++) { - for (i = 0; i < reg_um; i++) + for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, tqp_intr_reg_addr_list[i] + - 4 * j); + HCLGE_RING_INT_REG_OFFSET * j); for (i = 0; i < separator_num; i++) *reg++ = SEPARATOR_VALUE; } + data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1); + + return data_num_sum; +} + +static int hclge_get_regs_len(struct hnae3_handle *handle) +{ + int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; + int regs_lines_32_bit, regs_lines_64_bit; + int ret; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return ret; + } + + ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg len failed, ret = %d.\n", ret); + return ret; + } + + cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + + return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + + tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit + + regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len; +} + +static void hclge_get_regs(struct hnae3_handle *handle, u32 *version, + void *data) +{ + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + u32 regs_num_32_bit, regs_num_64_bit; + int i, reg_num, separator_num, ret; + u32 *reg = data; + + *version = hdev->fw_version; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return; + } + + reg += hclge_fetch_pf_reg(hdev, reg, kinfo); - /* fetching PF common registers values from firmware */ ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); if (ret) { dev_err(&hdev->pdev->dev, "Get 32 bit register failed, ret = %d.\n", ret); return; } + reg_num = regs_num_32_bit; + reg += reg_num; + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; - reg += regs_num_32_bit; ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); - if (ret) + if (ret) { dev_err(&hdev->pdev->dev, "Get 64 bit register failed, ret = %d.\n", ret); + return; + } + reg_num = regs_num_64_bit * 2; + reg += reg_num; + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + ret = hclge_get_dfx_reg(hdev, reg); + if (ret) + dev_err(&hdev->pdev->dev, + "Get dfx register failed, ret = %d.\n", ret); } static int hclge_set_led_status(struct hclge_dev *hdev, u8 locate_led_status) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index c9b9867fc226..f6d9b57830fb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1029,4 +1029,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, u16 state, u16 vlan_tag, u16 qos, u16 vlan_proto); void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time); +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc); #endif -- GitLab From b20d7fe51e0de28982e115b8ec0647066d73d206 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Fri, 9 Aug 2019 10:31:13 +0800 Subject: [PATCH 2529/7155] net: hns3: add some statitics info to tx process This patch adds tx_vlan_err, tx_l4_proto_err, tx_l2l3l4_err and tx_tso_err counter to tx process, in order to better debug the desc filling error. This patch also adds a missing u64_stats_update_* around ring->stats.sw_err_cnt and adds hns3_rl_err to limit the error printing in the IO patch. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 58 ++++++++++++++----- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 4 ++ .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 ++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index fd6a3d589f40..b2a668d6dad7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -28,6 +28,12 @@ #define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) #define hns3_tx_bd_count(S) DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE) +#define hns3_rl_err(fmt, ...) \ + do { \ + if (net_ratelimit()) \ + netdev_err(fmt, ##__VA_ARGS__); \ + } while (0) + static void hns3_clear_all_ring(struct hnae3_handle *h, bool force); static void hns3_remove_hw_addr(struct net_device *netdev); @@ -1033,6 +1039,9 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, ret = hns3_handle_vtags(ring, skb); if (unlikely(ret < 0)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_vlan_err++; + u64_stats_update_end(&ring->syncp); return ret; } else if (ret == HNS3_INNER_VLAN_TAG) { inner_vtag = skb_vlan_tag_get(skb); @@ -1053,19 +1062,31 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, skb_reset_mac_len(skb); ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto); - if (unlikely(ret)) + if (unlikely(ret)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_l4_proto_err++; + u64_stats_update_end(&ring->syncp); return ret; + } ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto, &type_cs_vlan_tso, &ol_type_vlan_len_msec); - if (unlikely(ret)) + if (unlikely(ret)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_l2l3l4_err++; + u64_stats_update_end(&ring->syncp); return ret; + } ret = hns3_set_tso(skb, &paylen, &mss, &type_cs_vlan_tso); - if (unlikely(ret)) + if (unlikely(ret)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_tso_err++; + u64_stats_update_end(&ring->syncp); return ret; + } } /* Set txbd */ @@ -1107,7 +1128,9 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, } if (unlikely(dma_mapping_error(dev, dma))) { + u64_stats_update_begin(&ring->syncp); ring->stats.sw_err_cnt++; + u64_stats_update_end(&ring->syncp); return -ENOMEM; } @@ -1330,9 +1353,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) u64_stats_update_end(&ring->syncp); } - if (net_ratelimit()) - netdev_err(netdev, "xmit error: %d!\n", buf_num); - + hns3_rl_err(netdev, "xmit error: %d!\n", buf_num); goto out_err_tx_ok; } @@ -1498,7 +1519,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_bytes += ring->stats.tx_bytes; tx_pkts += ring->stats.tx_pkts; tx_drop += ring->stats.sw_err_cnt; + tx_drop += ring->stats.tx_vlan_err; + tx_drop += ring->stats.tx_l4_proto_err; + tx_drop += ring->stats.tx_l2l3l4_err; + tx_drop += ring->stats.tx_tso_err; tx_errors += ring->stats.sw_err_cnt; + tx_errors += ring->stats.tx_vlan_err; + tx_errors += ring->stats.tx_l4_proto_err; + tx_errors += ring->stats.tx_l2l3l4_err; + tx_errors += ring->stats.tx_tso_err; } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); /* fetch the rx stats */ @@ -2382,8 +2411,9 @@ static void hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring, ring->stats.sw_err_cnt++; u64_stats_update_end(&ring->syncp); - netdev_err(ring->tqp->handle->kinfo.netdev, - "hnae reserve buffer map failed.\n"); + hns3_rl_err(ring->tqp_vector->napi.dev, + "alloc rx buffer failed: %d\n", + ret); break; } hns3_replace_buffer(ring, ring->next_to_use, &res_cbs); @@ -2468,9 +2498,9 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info) th->check = ~tcp_v6_check(skb->len - depth, &iph->saddr, &iph->daddr, 0); } else { - netdev_err(skb->dev, - "Error: FW GRO supports only IPv4/IPv6, not 0x%04x, depth: %d\n", - be16_to_cpu(type), depth); + hns3_rl_err(skb->dev, + "Error: FW GRO supports only IPv4/IPv6, not 0x%04x, depth: %d\n", + be16_to_cpu(type), depth); return -EFAULT; } @@ -2612,7 +2642,7 @@ static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length, ring->skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE); skb = ring->skb; if (unlikely(!skb)) { - netdev_err(netdev, "alloc rx skb fail\n"); + hns3_rl_err(netdev, "alloc rx skb fail\n"); u64_stats_update_begin(&ring->syncp); ring->stats.sw_err_cnt++; @@ -2687,8 +2717,8 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc, new_skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE); if (unlikely(!new_skb)) { - netdev_err(ring->tqp->handle->kinfo.netdev, - "alloc rx skb frag fail\n"); + hns3_rl_err(ring->tqp_vector->napi.dev, + "alloc rx fraglist skb fail\n"); return -ENXIO; } ring->frag_num = 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 0a970f5fed10..a76712c3f65c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -377,6 +377,10 @@ struct ring_stats { u64 restart_queue; u64 tx_busy; u64 tx_copy; + u64 tx_vlan_err; + u64 tx_l4_proto_err; + u64 tx_l2l3l4_err; + u64 tx_tso_err; }; struct { u64 rx_pkts; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 02f46c73ac3b..185ff32262e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -30,6 +30,10 @@ static const struct hns3_stats hns3_txq_stats[] = { HNS3_TQP_STAT("wake", restart_queue), HNS3_TQP_STAT("busy", tx_busy), HNS3_TQP_STAT("copy", tx_copy), + HNS3_TQP_STAT("vlan_err", tx_vlan_err), + HNS3_TQP_STAT("l4_proto_err", tx_l4_proto_err), + HNS3_TQP_STAT("l2l3l4_err", tx_l2l3l4_err), + HNS3_TQP_STAT("tso_err", tx_tso_err), }; #define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats) -- GitLab From 42611b70f8be12c46906c869f5d819ac70dfd1c7 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Fri, 9 Aug 2019 10:31:14 +0800 Subject: [PATCH 2530/7155] net: hns3: add check for max TX BD num for tso and non-tso case Hardware supports up to 8 TX BD for non-TSO skb and 63 TX BD for TSO skb. Currently hns3 driver does not check the max BD num that required by a skb before filling desc, which may cause the hardware to issue a RAS error throug PCIe AER. This patch adds the max BD num check before filling desc, if the bd num is not within the hardware limit, it will record the error by ring->stats.sw_err_cnt counter and free the skb. This patch also cleans up the hns3_nic_bd_num function by changing the return type and removing an unnecessary check. Signed-off-by: Yunsheng Lin Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 38 ++++++++----------- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 3 +- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b2a668d6dad7..df08f9ec0601 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1186,28 +1186,20 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, return 0; } -static int hns3_nic_bd_num(struct sk_buff *skb) +static unsigned int hns3_nic_bd_num(struct sk_buff *skb) { - int size = skb_headlen(skb); - int i, bd_num; + unsigned int bd_num; + int i; /* if the total len is within the max bd limit */ if (likely(skb->len <= HNS3_MAX_BD_SIZE)) return skb_shinfo(skb)->nr_frags + 1; - bd_num = hns3_tx_bd_count(size); + bd_num = hns3_tx_bd_count(skb_headlen(skb)); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - int frag_bd_num; - - size = skb_frag_size(frag); - frag_bd_num = hns3_tx_bd_count(size); - - if (unlikely(frag_bd_num > HNS3_MAX_BD_PER_FRAG)) - return -ENOMEM; - - bd_num += frag_bd_num; + bd_num += hns3_tx_bd_count(skb_frag_size(frag)); } return bd_num; @@ -1228,7 +1220,7 @@ static unsigned int hns3_gso_hdr_len(struct sk_buff *skb) */ static bool hns3_skb_need_linearized(struct sk_buff *skb) { - int bd_limit = HNS3_MAX_BD_PER_FRAG - 1; + int bd_limit = HNS3_MAX_BD_NUM_NORMAL - 1; unsigned int tot_len = 0; int i; @@ -1258,21 +1250,16 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, struct sk_buff **out_skb) { struct sk_buff *skb = *out_skb; - int bd_num; + unsigned int bd_num; bd_num = hns3_nic_bd_num(skb); - if (bd_num < 0) - return bd_num; - - if (unlikely(bd_num > HNS3_MAX_BD_PER_FRAG)) { + if (unlikely(bd_num > HNS3_MAX_BD_NUM_NORMAL)) { struct sk_buff *new_skb; - if (skb_is_gso(skb) && !hns3_skb_need_linearized(skb)) + if (skb_is_gso(skb) && bd_num <= HNS3_MAX_BD_NUM_TSO && + !hns3_skb_need_linearized(skb)) goto out; - bd_num = hns3_tx_bd_count(skb->len); - if (unlikely(ring_space(ring) < bd_num)) - return -EBUSY; /* manual split the send packet */ new_skb = skb_copy(skb, GFP_ATOMIC); if (!new_skb) @@ -1280,6 +1267,11 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, dev_kfree_skb_any(skb); *out_skb = new_skb; + bd_num = hns3_nic_bd_num(new_skb); + if ((skb_is_gso(new_skb) && bd_num > HNS3_MAX_BD_NUM_TSO) || + (!skb_is_gso(new_skb) && bd_num > HNS3_MAX_BD_NUM_NORMAL)) + return -ENOMEM; + u64_stats_update_begin(&ring->syncp); ring->stats.tx_copy++; u64_stats_update_end(&ring->syncp); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index a76712c3f65c..5b0ee1fe40f1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -195,7 +195,8 @@ enum hns3_nic_state { #define HNS3_VECTOR_INITED 1 #define HNS3_MAX_BD_SIZE 65535 -#define HNS3_MAX_BD_PER_FRAG 8 +#define HNS3_MAX_BD_NUM_NORMAL 8 +#define HNS3_MAX_BD_NUM_TSO 63 #define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS #define HNS3_VECTOR_GL0_OFFSET 0x100 -- GitLab From dec8466001f740868f01a3cb75b21174197be85e Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Fri, 9 Aug 2019 10:31:15 +0800 Subject: [PATCH 2531/7155] net: hns3: add function display NCL_CONFIG info This adds a new function hclge_ncl_config_data_print() to print the data of NCL_CONFIG, to make the code more readable. Also, using macro replaces some magic number. Signed-off-by: Yufeng Mo Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 933dec53ed8e..f0295d12a1b6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -995,6 +995,33 @@ void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev) kfree(desc_src); } +#define HCLGE_CMD_NCL_CONFIG_BD_NUM 5 + +static void hclge_ncl_config_data_print(struct hclge_dev *hdev, + struct hclge_desc *desc, int *offset, + int *length) +{ +#define HCLGE_CMD_DATA_NUM 6 + + int i; + int j; + + for (i = 0; i < HCLGE_CMD_NCL_CONFIG_BD_NUM; i++) { + for (j = 0; j < HCLGE_CMD_DATA_NUM; j++) { + if (i == 0 && j == 0) + continue; + + dev_info(&hdev->pdev->dev, "0x%04x | 0x%08x\n", + *offset, + le32_to_cpu(desc[i].data[j])); + *offset += sizeof(u32); + *length -= sizeof(u32); + if (*length <= 0) + return; + } + } +} + /* hclge_dbg_dump_ncl_config: print specified range of NCL_CONFIG file * @hdev: pointer to struct hclge_dev * @cmd_buf: string that contains offset and length @@ -1004,17 +1031,13 @@ static void hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, { #define HCLGE_MAX_NCL_CONFIG_OFFSET 4096 #define HCLGE_MAX_NCL_CONFIG_LENGTH (20 + 24 * 4) -#define HCLGE_CMD_DATA_NUM 6 - struct hclge_desc desc[5]; - u32 byte_offset; - int bd_num = 5; + struct hclge_desc desc[HCLGE_CMD_NCL_CONFIG_BD_NUM]; + int bd_num = HCLGE_CMD_NCL_CONFIG_BD_NUM; int offset; int length; int data0; int ret; - int i; - int j; ret = sscanf(cmd_buf, "%x %x", &offset, &length); if (ret != 2 || offset >= HCLGE_MAX_NCL_CONFIG_OFFSET || @@ -1040,22 +1063,7 @@ static void hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, if (ret) return; - byte_offset = offset; - for (i = 0; i < bd_num; i++) { - for (j = 0; j < HCLGE_CMD_DATA_NUM; j++) { - if (i == 0 && j == 0) - continue; - - dev_info(&hdev->pdev->dev, "0x%04x | 0x%08x\n", - byte_offset, - le32_to_cpu(desc[i].data[j])); - byte_offset += sizeof(u32); - length -= sizeof(u32); - if (length <= 0) - return; - } - } - offset += HCLGE_MAX_NCL_CONFIG_LENGTH; + hclge_ncl_config_data_print(hdev, desc, &offset, &length); } } -- GitLab From 615466ce415a8a94d3c2cbd5ac35aa29bd189ebe Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Fri, 9 Aug 2019 10:31:16 +0800 Subject: [PATCH 2532/7155] net: hns3: refine MAC pause statistics querying function This patch refines the interface for querying MAC pause statistics, and adds structure hns3_mac_stats to keep the count of TX & RX. Signed-off-by: Yufeng Mo Reviewed-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 11 +++++++++-- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 11 ++++------- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 12 +++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index a4624db3b5d5..43740ee9d8d8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -91,6 +91,11 @@ struct hnae3_queue { u16 rx_desc_num;/* total number of rx desc */ }; +struct hns3_mac_stats { + u64 tx_pause_cnt; + u64 rx_pause_cnt; +}; + /*hnae3 loop mode*/ enum hnae3_loop { HNAE3_LOOP_APP, @@ -298,6 +303,8 @@ struct hnae3_ae_dev { * Remove multicast address from mac table * update_stats() * Update Old network device statistics + * get_mac_stats() + * get mac pause statistics including tx_cnt and rx_cnt * get_ethtool_stats() * Get ethtool network device statistics * get_strings() @@ -426,8 +433,8 @@ struct hnae3_ae_ops { void (*update_stats)(struct hnae3_handle *handle, struct net_device_stats *net_stats); void (*get_stats)(struct hnae3_handle *handle, u64 *data); - void (*get_mac_pause_stats)(struct hnae3_handle *handle, u64 *tx_cnt, - u64 *rx_cnt); + void (*get_mac_stats)(struct hnae3_handle *handle, + struct hns3_mac_stats *mac_stats); void (*get_strings)(struct hnae3_handle *handle, u32 stringset, u8 *data); int (*get_sset_count)(struct hnae3_handle *handle, int stringset); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index df08f9ec0601..1750f80341e7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1726,15 +1726,12 @@ static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev) /* When mac received many pause frames continuous, it's unable to send * packets, which may cause tx timeout */ - if (h->ae_algo->ops->update_stats && - h->ae_algo->ops->get_mac_pause_stats) { - u64 tx_pause_cnt, rx_pause_cnt; + if (h->ae_algo->ops->get_mac_stats) { + struct hns3_mac_stats mac_stats; - h->ae_algo->ops->update_stats(h, &ndev->stats); - h->ae_algo->ops->get_mac_pause_stats(h, &tx_pause_cnt, - &rx_pause_cnt); + h->ae_algo->ops->get_mac_stats(h, &mac_stats); netdev_info(ndev, "tx_pause_cnt: %llu, rx_pause_cnt: %llu\n", - tx_pause_cnt, rx_pause_cnt); + mac_stats.tx_pause_cnt, mac_stats.rx_pause_cnt); } hw_head = readl_relaxed(tx_ring->tqp->io_base + diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 7d7ab9e66383..13152753c75d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -750,14 +750,16 @@ static void hclge_get_stats(struct hnae3_handle *handle, u64 *data) p = hclge_tqps_get_stats(handle, p); } -static void hclge_get_mac_pause_stat(struct hnae3_handle *handle, u64 *tx_cnt, - u64 *rx_cnt) +static void hclge_get_mac_stat(struct hnae3_handle *handle, + struct hns3_mac_stats *mac_stats) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - *tx_cnt = hdev->hw_stats.mac_stats.mac_tx_mac_pause_num; - *rx_cnt = hdev->hw_stats.mac_stats.mac_rx_mac_pause_num; + hclge_update_stats(handle, NULL); + + mac_stats->tx_pause_cnt = hdev->hw_stats.mac_stats.mac_tx_mac_pause_num; + mac_stats->rx_pause_cnt = hdev->hw_stats.mac_stats.mac_rx_mac_pause_num; } static int hclge_parse_func_status(struct hclge_dev *hdev, @@ -9798,7 +9800,7 @@ static const struct hnae3_ae_ops hclge_ops = { .set_mtu = hclge_set_mtu, .reset_queue = hclge_reset_tqp, .get_stats = hclge_get_stats, - .get_mac_pause_stats = hclge_get_mac_pause_stat, + .get_mac_stats = hclge_get_mac_stat, .update_stats = hclge_update_stats, .get_strings = hclge_get_strings, .get_sset_count = hclge_get_sset_count, -- GitLab From 427a7bff66c8a9f8cf68384e24093fc4bf7763a1 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 9 Aug 2019 10:31:17 +0800 Subject: [PATCH 2533/7155] net: hns3: add handshake with VF for PF reset Before PF asserting function reset, it should make sure that all its VFs have been ready, otherwise, it will cause some hardware errors. So this patch adds function hclge_func_reset_sync_vf() to synchronize VF before asserting PF function reset. For new firmware which supports command HCLGE_OPC_QUERY_VF_RST_RDY, we will try to query VFs' ready status within 30 seconds. And keep the old implementation for compatible with firmware which does not support this command. Signed-off-by: Huazhong Tan Reviewed-by: Yunsheng Lin Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 7 +++ .../hisilicon/hns3/hns3pf/hclge_main.c | 56 ++++++++++++++++--- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index dade20a37d40..29979be9e33a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -87,6 +87,7 @@ enum hclge_opcode_type { HCLGE_OPC_QUERY_VF_RSRC = 0x0024, HCLGE_OPC_GET_CFG_PARAM = 0x0025, HCLGE_OPC_PF_RST_DONE = 0x0026, + HCLGE_OPC_QUERY_VF_RST_RDY = 0x0027, HCLGE_OPC_STATS_64_BIT = 0x0030, HCLGE_OPC_STATS_32_BIT = 0x0031, @@ -588,6 +589,12 @@ struct hclge_config_mac_mode_cmd { u8 rsv[20]; }; +struct hclge_pf_rst_sync_cmd { +#define HCLGE_PF_RST_ALL_VF_RDY_B 0 + u8 all_vf_ready; + u8 rsv[23]; +}; + #define HCLGE_CFG_SPEED_S 0 #define HCLGE_CFG_SPEED_M GENMASK(5, 0) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 13152753c75d..d207dac1fd5e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -35,6 +35,9 @@ #define BUF_RESERVE_PERCENT 90 #define HCLGE_RESET_MAX_FAIL_CNT 5 +#define HCLGE_RESET_SYNC_TIME 100 +#define HCLGE_PF_RESET_SYNC_TIME 20 +#define HCLGE_PF_RESET_SYNC_CNT 1500 /* Get DFX BD number offset */ #define HCLGE_DFX_BIOS_BD_OFFSET 1 @@ -3184,6 +3187,39 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) return 0; } +int hclge_func_reset_sync_vf(struct hclge_dev *hdev) +{ + struct hclge_pf_rst_sync_cmd *req; + struct hclge_desc desc; + int cnt = 0; + int ret; + + req = (struct hclge_pf_rst_sync_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_VF_RST_RDY, true); + + do { + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + /* for compatible with old firmware, wait + * 100 ms for VF to stop IO + */ + if (ret == -EOPNOTSUPP) { + msleep(HCLGE_RESET_SYNC_TIME); + return 0; + } else if (ret) { + dev_err(&hdev->pdev->dev, "sync with VF fail %d!\n", + ret); + return ret; + } else if (req->all_vf_ready) { + return 0; + } + msleep(HCLGE_PF_RESET_SYNC_TIME); + hclge_cmd_reuse_desc(&desc, true); + } while (cnt++ < HCLGE_PF_RESET_SYNC_CNT); + + dev_err(&hdev->pdev->dev, "sync with VF timeout!\n"); + return -ETIME; +} + int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id) { struct hclge_desc desc; @@ -3350,17 +3386,18 @@ static void hclge_reset_handshake(struct hclge_dev *hdev, bool enable) static int hclge_reset_prepare_wait(struct hclge_dev *hdev) { -#define HCLGE_RESET_SYNC_TIME 100 - u32 reg_val; int ret = 0; switch (hdev->reset_type) { case HNAE3_FUNC_RESET: - /* There is no mechanism for PF to know if VF has stopped IO - * for now, just wait 100 ms for VF to stop IO + /* to confirm whether all running VF is ready + * before request PF reset */ - msleep(HCLGE_RESET_SYNC_TIME); + ret = hclge_func_reset_sync_vf(hdev); + if (ret) + return ret; + ret = hclge_func_reset_cmd(hdev, 0); if (ret) { dev_err(&hdev->pdev->dev, @@ -3377,10 +3414,13 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) hdev->rst_stats.pf_rst_cnt++; break; case HNAE3_FLR_RESET: - /* There is no mechanism for PF to know if VF has stopped IO - * for now, just wait 100 ms for VF to stop IO + /* to confirm whether all running VF is ready + * before request PF reset */ - msleep(HCLGE_RESET_SYNC_TIME); + ret = hclge_func_reset_sync_vf(hdev); + if (ret) + return ret; + set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state); set_bit(HNAE3_FLR_DOWN, &hdev->flr_state); hdev->rst_stats.flr_rst_cnt++; -- GitLab From eddd98600b382d80cd71e44150eec5de4a0830a4 Mon Sep 17 00:00:00 2001 From: Guojia Liao Date: Fri, 9 Aug 2019 10:31:18 +0800 Subject: [PATCH 2534/7155] net: hns3: refine some macro definitions Macro arguments should be enclosed in parentheses, in case of expression argument, but parentheses of pure number in macro definition should be removed for simplicity. Signed-off-by: Guojia Liao Signed-off-by: Guangbin Huang Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 43740ee9d8d8..6c9fd58c436f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -58,10 +58,10 @@ BIT(HNAE3_DEV_SUPPORT_ROCE_B)) #define hnae3_dev_roce_supported(hdev) \ - hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B) + hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B) #define hnae3_dev_dcb_supported(hdev) \ - hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_DCB_B) + hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_DCB_B) #define hnae3_dev_fd_supported(hdev) \ hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 4ccf107079eb..bdde3afc286b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -125,7 +125,7 @@ #define HCLGEVF_S_IP_BIT BIT(3) #define HCLGEVF_V_TAG_BIT BIT(4) -#define HCLGEVF_STATS_TIMER_INTERVAL (36) +#define HCLGEVF_STATS_TIMER_INTERVAL 36U enum hclgevf_evt_cause { HCLGEVF_VECTOR0_EVENT_RST, -- GitLab From e2fb6f7c0df1cb9d5f89c1b6a9d3caf434c040bb Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Tue, 6 Aug 2019 09:55:20 +0200 Subject: [PATCH 2535/7155] dt-bindings: arm: amlogic: fix x96-max/sei510 section in amlogic.yaml Move amediatech,x96-max and seirobotics,sei510 to the S905D2 section and update the S905D2 description to S905D2/X2/Y2. Signed-off-by: Christian Hewitt Signed-off-by: Neil Armstrong Acked-by: Rob Herring Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index 04a2b0ef34c6..96f66911e3c6 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -91,13 +91,11 @@ properties: - description: Boards with the Amlogic Meson GXL S905X SoC items: - enum: - - amediatech,x96-max - amlogic,p212 - hwacom,amazetv - khadas,vim - libretech,cc - nexbox,a95x - - seirobotics,sei510 - const: amlogic,s905x - const: amlogic,meson-gxl @@ -129,10 +127,12 @@ properties: - const: amlogic,a113d - const: amlogic,meson-axg - - description: Boards with the Amlogic Meson G12A S905D2 SoC + - description: Boards with the Amlogic Meson G12A S905D2/X2/Y2 SoC items: - enum: + - amediatech,x96-max - amlogic,u200 + - seirobotics,sei510 - const: amlogic,g12a - description: Boards with the Amlogic Meson G12B A311D SoC -- GitLab From e4f9abbd38e468c73710ad3678005ad05f79c818 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 8 Jun 2018 19:26:50 +0300 Subject: [PATCH 2536/7155] net/mlx5e: Extend hairpin entry with reference counter List of flows attached to hairpin entry is used as implicit reference counter (hairpin entry is deallocated when list becomes free) and as a mechanism to obtain hairpin entry that flow is attached to (through list head). This is not safe when concurrent modification of list of flows attached to hairpin entry is possible. Proper atomic reference counter is required to support concurrent access. As a preparation for extending hairpin with reference counting, extract code that deletes hairpin entry into standalone function. In order to remove this dependency on external locking, extend hairpin entry with reference counter to manage its lifetime and extend flow structure with direct pointer to hairpin entry that flow is attached to. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 4d97cc47835f..64ce762ec1e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -119,6 +119,7 @@ struct mlx5e_tc_flow { struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; struct mlx5e_tc_flow *peer_flow; struct list_head mod_hdr; /* flows sharing the same mod hdr ID */ + struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ @@ -167,6 +168,7 @@ struct mlx5e_hairpin_entry { u16 peer_vhca_id; u8 prio; struct mlx5e_hairpin *hp; + refcount_t refcnt; }; struct mod_hdr_key { @@ -635,13 +637,31 @@ static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv, hash_for_each_possible(priv->fs.tc.hairpin_tbl, hpe, hairpin_hlist, hash_key) { - if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) + if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) { + refcount_inc(&hpe->refcnt); return hpe; + } } return NULL; } +static void mlx5e_hairpin_put(struct mlx5e_priv *priv, + struct mlx5e_hairpin_entry *hpe) +{ + /* no more hairpin flows for us, release the hairpin pair */ + if (!refcount_dec_and_test(&hpe->refcnt)) + return; + + netdev_dbg(priv->netdev, "del hairpin: peer %s\n", + dev_name(hpe->hp->pair->peer_mdev->device)); + + WARN_ON(!list_empty(&hpe->flows)); + mlx5e_hairpin_destroy(hpe->hp); + hash_del(&hpe->hairpin_hlist); + kfree(hpe); +} + #define UNKNOWN_MATCH_PRIO 8 static int mlx5e_hairpin_get_prio(struct mlx5e_priv *priv, @@ -718,6 +738,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, INIT_LIST_HEAD(&hpe->flows); hpe->peer_vhca_id = peer_id; hpe->prio = match_prio; + refcount_set(&hpe->refcnt, 1); params.log_data_size = 15; params.log_data_size = min_t(u8, params.log_data_size, @@ -760,6 +781,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, } else { flow->nic_attr->hairpin_tirn = hpe->hp->tirn; } + flow->hpe = hpe; list_add(&flow->hairpin, &hpe->flows); return 0; @@ -772,27 +794,13 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { - struct list_head *next = flow->hairpin.next; - /* flow wasn't fully initialized */ - if (list_empty(&flow->hairpin)) + if (!flow->hpe) return; list_del(&flow->hairpin); - - /* no more hairpin flows for us, release the hairpin pair */ - if (list_empty(next)) { - struct mlx5e_hairpin_entry *hpe; - - hpe = list_entry(next, struct mlx5e_hairpin_entry, flows); - - netdev_dbg(priv->netdev, "del hairpin: peer %s\n", - dev_name(hpe->hp->pair->peer_mdev->device)); - - mlx5e_hairpin_destroy(hpe->hp); - hash_del(&hpe->hairpin_hlist); - kfree(hpe); - } + mlx5e_hairpin_put(priv, flow->hpe); + flow->hpe = NULL; } static int -- GitLab From 73edca736e581a685c98d3928b4cc029932d2d5a Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 7 Jun 2018 23:01:40 +0300 Subject: [PATCH 2537/7155] net/mlx5e: Protect hairpin entry flows list with spinlock To remove dependency on rtnl lock, extend hairpin entry with spinlock and use it to protect list of flows attached to hairpin entry from concurrent modifications. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 64ce762ec1e6..0abfa9b3ec54 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -162,6 +162,8 @@ struct mlx5e_hairpin_entry { /* a node of a hash table which keeps all the hairpin entries */ struct hlist_node hairpin_hlist; + /* protects flows list */ + spinlock_t flows_lock; /* flows sharing the same hairpin */ struct list_head flows; @@ -735,6 +737,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, if (!hpe) return -ENOMEM; + spin_lock_init(&hpe->flows_lock); INIT_LIST_HEAD(&hpe->flows); hpe->peer_vhca_id = peer_id; hpe->prio = match_prio; @@ -782,7 +785,9 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, flow->nic_attr->hairpin_tirn = hpe->hp->tirn; } flow->hpe = hpe; + spin_lock(&hpe->flows_lock); list_add(&flow->hairpin, &hpe->flows); + spin_unlock(&hpe->flows_lock); return 0; @@ -798,7 +803,10 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv, if (!flow->hpe) return; + spin_lock(&flow->hpe->flows_lock); list_del(&flow->hairpin); + spin_unlock(&flow->hpe->flows_lock); + mlx5e_hairpin_put(priv, flow->hpe); flow->hpe = NULL; } -- GitLab From b32accda8afd36d7de1581375467fd3642d3c73e Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 31 Jul 2019 18:19:06 +0300 Subject: [PATCH 2538/7155] net/mlx5e: Protect hairpin hash table with mutex To remove dependency on rtnl lock, protect hairpin hash table from concurrent modifications with new "hairpin_tbl_lock" mutex. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/fs.h | 1 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 21 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h index 4518ce19112e..100506a3dd58 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h @@ -17,6 +17,7 @@ struct mlx5e_tc_table { struct rhashtable ht; DECLARE_HASHTABLE(mod_hdr_tbl, 8); + struct mutex hairpin_tbl_lock; /* protects hairpin_tbl */ DECLARE_HASHTABLE(hairpin_tbl, 8); struct notifier_block netdevice_nb; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 0abfa9b3ec54..a7acb7fcbf5a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -652,15 +652,16 @@ static void mlx5e_hairpin_put(struct mlx5e_priv *priv, struct mlx5e_hairpin_entry *hpe) { /* no more hairpin flows for us, release the hairpin pair */ - if (!refcount_dec_and_test(&hpe->refcnt)) + if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &priv->fs.tc.hairpin_tbl_lock)) return; + hash_del(&hpe->hairpin_hlist); + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); netdev_dbg(priv->netdev, "del hairpin: peer %s\n", dev_name(hpe->hp->pair->peer_mdev->device)); WARN_ON(!list_empty(&hpe->flows)); mlx5e_hairpin_destroy(hpe->hp); - hash_del(&hpe->hairpin_hlist); kfree(hpe); } @@ -729,13 +730,17 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, extack); if (err) return err; + + mutex_lock(&priv->fs.tc.hairpin_tbl_lock); hpe = mlx5e_hairpin_get(priv, peer_id, match_prio); if (hpe) goto attach_flow; hpe = kzalloc(sizeof(*hpe), GFP_KERNEL); - if (!hpe) - return -ENOMEM; + if (!hpe) { + err = -ENOMEM; + goto create_hairpin_err; + } spin_lock_init(&hpe->flows_lock); INIT_LIST_HEAD(&hpe->flows); @@ -784,6 +789,8 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, } else { flow->nic_attr->hairpin_tirn = hpe->hp->tirn; } + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); + flow->hpe = hpe; spin_lock(&hpe->flows_lock); list_add(&flow->hairpin, &hpe->flows); @@ -792,6 +799,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, return 0; create_hairpin_err: + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); kfree(hpe); return err; } @@ -3768,10 +3776,12 @@ static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id); + mutex_lock(&priv->fs.tc.hairpin_tbl_lock); hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) { if (hpe->peer_vhca_id == peer_vhca_id) hpe->hp->pair->peer_gone = true; } + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); } static int mlx5e_tc_netdev_event(struct notifier_block *this, @@ -3808,6 +3818,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) mutex_init(&tc->t_lock); hash_init(tc->mod_hdr_tbl); + mutex_init(&tc->hairpin_tbl_lock); hash_init(tc->hairpin_tbl); err = rhashtable_init(&tc->ht, &tc_ht_params); @@ -3839,6 +3850,8 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) if (tc->netdevice_nb.notifier_call) unregister_netdevice_notifier(&tc->netdevice_nb); + mutex_destroy(&tc->hairpin_tbl_lock); + rhashtable_destroy(&tc->ht); if (!IS_ERR_OR_NULL(tc->t)) { -- GitLab From db76ca2424fe28923aaec5e2187e886b025a914c Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 1 Aug 2019 16:54:54 +0300 Subject: [PATCH 2539/7155] net/mlx5e: Allow concurrent creation of hairpin entries Hairpin entries creation is fully synchronized by hairpin_tbl_lock. In order to allow concurrent initialization of mlx5e_hairpin structure instances and provisioning of hairpin entries to hardware, extend mlx5e_hairpin_entry with 'res_ready' completion. Move call to mlx5e_hairpin_create() out of hairpin_tbl_lock critical section. Modify code that attaches new flows to existing hpe to wait for 'res_ready' completion before using the hpe. Insert hpe to hairpin table before provisioning it to hardware and modify all users of hairpin table to verify that hpe was fully initialized by checking hpe->hp pointer (and to wait for 'res_ready' completion, if necessary). Modify dead peer update event handling function to save hpe's to temporary list with their reference counter incremented. Wait for completion of hpe's in temporary list and update their 'peer_gone' flag outside of hairpin_tbl_lock critical section. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a7acb7fcbf5a..b6a91e3054c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -166,11 +167,16 @@ struct mlx5e_hairpin_entry { spinlock_t flows_lock; /* flows sharing the same hairpin */ struct list_head flows; + /* hpe's that were not fully initialized when dead peer update event + * function traversed them. + */ + struct list_head dead_peer_wait_list; u16 peer_vhca_id; u8 prio; struct mlx5e_hairpin *hp; refcount_t refcnt; + struct completion res_ready; }; struct mod_hdr_key { @@ -657,11 +663,14 @@ static void mlx5e_hairpin_put(struct mlx5e_priv *priv, hash_del(&hpe->hairpin_hlist); mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); - netdev_dbg(priv->netdev, "del hairpin: peer %s\n", - dev_name(hpe->hp->pair->peer_mdev->device)); + if (!IS_ERR_OR_NULL(hpe->hp)) { + netdev_dbg(priv->netdev, "del hairpin: peer %s\n", + dev_name(hpe->hp->pair->peer_mdev->device)); + + mlx5e_hairpin_destroy(hpe->hp); + } WARN_ON(!list_empty(&hpe->flows)); - mlx5e_hairpin_destroy(hpe->hp); kfree(hpe); } @@ -733,20 +742,34 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, mutex_lock(&priv->fs.tc.hairpin_tbl_lock); hpe = mlx5e_hairpin_get(priv, peer_id, match_prio); - if (hpe) + if (hpe) { + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); + wait_for_completion(&hpe->res_ready); + + if (IS_ERR(hpe->hp)) { + err = -EREMOTEIO; + goto out_err; + } goto attach_flow; + } hpe = kzalloc(sizeof(*hpe), GFP_KERNEL); if (!hpe) { - err = -ENOMEM; - goto create_hairpin_err; + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); + return -ENOMEM; } spin_lock_init(&hpe->flows_lock); INIT_LIST_HEAD(&hpe->flows); + INIT_LIST_HEAD(&hpe->dead_peer_wait_list); hpe->peer_vhca_id = peer_id; hpe->prio = match_prio; refcount_set(&hpe->refcnt, 1); + init_completion(&hpe->res_ready); + + hash_add(priv->fs.tc.hairpin_tbl, &hpe->hairpin_hlist, + hash_hairpin_info(peer_id, match_prio)); + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); params.log_data_size = 15; params.log_data_size = min_t(u8, params.log_data_size, @@ -768,9 +791,11 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, params.num_channels = link_speed64; hp = mlx5e_hairpin_create(priv, ¶ms, peer_ifindex); + hpe->hp = hp; + complete_all(&hpe->res_ready); if (IS_ERR(hp)) { err = PTR_ERR(hp); - goto create_hairpin_err; + goto out_err; } netdev_dbg(priv->netdev, "add hairpin: tirn %x rqn %x peer %s sqn %x prio %d (log) data %d packets %d\n", @@ -778,10 +803,6 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, dev_name(hp->pair->peer_mdev->device), hp->pair->sqn[0], match_prio, params.log_data_size, params.log_num_packets); - hpe->hp = hp; - hash_add(priv->fs.tc.hairpin_tbl, &hpe->hairpin_hlist, - hash_hairpin_info(peer_id, match_prio)); - attach_flow: if (hpe->hp->num_channels > 1) { flow_flag_set(flow, HAIRPIN_RSS); @@ -789,7 +810,6 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, } else { flow->nic_attr->hairpin_tirn = hpe->hp->tirn; } - mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); flow->hpe = hpe; spin_lock(&hpe->flows_lock); @@ -798,9 +818,8 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv, return 0; -create_hairpin_err: - mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); - kfree(hpe); +out_err: + mlx5e_hairpin_put(priv, hpe); return err; } @@ -3767,7 +3786,8 @@ static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) { struct mlx5_core_dev *peer_mdev = peer_priv->mdev; - struct mlx5e_hairpin_entry *hpe; + struct mlx5e_hairpin_entry *hpe, *tmp; + LIST_HEAD(init_wait_list); u16 peer_vhca_id; int bkt; @@ -3777,11 +3797,18 @@ static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id); mutex_lock(&priv->fs.tc.hairpin_tbl_lock); - hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) { - if (hpe->peer_vhca_id == peer_vhca_id) + hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) + if (refcount_inc_not_zero(&hpe->refcnt)) + list_add(&hpe->dead_peer_wait_list, &init_wait_list); + mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); + + list_for_each_entry_safe(hpe, tmp, &init_wait_list, dead_peer_wait_list) { + wait_for_completion(&hpe->res_ready); + if (!IS_ERR_OR_NULL(hpe->hp) && hpe->peer_vhca_id == peer_vhca_id) hpe->hp->pair->peer_gone = true; + + mlx5e_hairpin_put(priv, hpe); } - mutex_unlock(&priv->fs.tc.hairpin_tbl_lock); } static int mlx5e_tc_netdev_event(struct notifier_block *this, -- GitLab From dd58edc328cec1a0d837f3f2f41e9955ec623e3e Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 1 Jun 2018 21:47:43 +0300 Subject: [PATCH 2540/7155] net/mlx5e: Extend mod header entry with reference counter List of flows attached to mod header entry is used as implicit reference counter (mod header entry is deallocated when list becomes free) and as a mechanism to obtain mod header entry that flow is attached to (through list head). This is not safe when concurrent modification of list of flows attached to mod header entry is possible. Proper atomic reference counter is required to support concurrent access. As a preparation for extending mod header with reference counting, extract code that lookups and deletes mod header entry into standalone put/get helpers. In order to remove this dependency on external locking, extend mod header entry with reference counter to manage its lifetime and extend flow structure with direct pointer to mod header entry that flow is attached to. To remove code duplication between legacy and switchdev mode implementations that both support mod_hdr functionality, store mod_hdr table in dedicated structure used by both fdb and kernel namespaces. New table structure is extended with table lock by one of the following patches in this series. Implement helper function to get correct mod_hdr table depending on flow namespace. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/fs.h | 2 +- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 94 +++++++++++-------- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- .../net/ethernet/mellanox/mlx5/core/eswitch.h | 2 +- include/linux/mlx5/fs.h | 4 + 5 files changed, 61 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h index 100506a3dd58..ca2161b42c7f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h @@ -16,7 +16,7 @@ struct mlx5e_tc_table { struct rhashtable ht; - DECLARE_HASHTABLE(mod_hdr_tbl, 8); + struct mod_hdr_tbl mod_hdr; struct mutex hairpin_tbl_lock; /* protects hairpin_tbl */ DECLARE_HASHTABLE(hairpin_tbl, 8); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index b6a91e3054c0..fe1b04aa910a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -119,6 +119,7 @@ struct mlx5e_tc_flow { */ struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; struct mlx5e_tc_flow *peer_flow; + struct mlx5e_mod_hdr_entry *mh; /* attached mod header instance */ struct list_head mod_hdr; /* flows sharing the same mod hdr ID */ struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ struct list_head hairpin; /* flows sharing the same hairpin */ @@ -194,6 +195,8 @@ struct mlx5e_mod_hdr_entry { struct mod_hdr_key key; u32 mod_hdr_id; + + refcount_t refcnt; }; #define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto) @@ -284,14 +287,51 @@ static inline int cmp_mod_hdr_info(struct mod_hdr_key *a, return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ); } +static struct mod_hdr_tbl * +get_mod_hdr_table(struct mlx5e_priv *priv, int namespace) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + + return namespace == MLX5_FLOW_NAMESPACE_FDB ? &esw->offloads.mod_hdr : + &priv->fs.tc.mod_hdr; +} + +static struct mlx5e_mod_hdr_entry * +mlx5e_mod_hdr_get(struct mod_hdr_tbl *tbl, struct mod_hdr_key *key, u32 hash_key) +{ + struct mlx5e_mod_hdr_entry *mh, *found = NULL; + + hash_for_each_possible(tbl->hlist, mh, mod_hdr_hlist, hash_key) { + if (!cmp_mod_hdr_info(&mh->key, key)) { + refcount_inc(&mh->refcnt); + found = mh; + break; + } + } + + return found; +} + +static void mlx5e_mod_hdr_put(struct mlx5e_priv *priv, + struct mlx5e_mod_hdr_entry *mh) +{ + if (!refcount_dec_and_test(&mh->refcnt)) + return; + + WARN_ON(!list_empty(&mh->flows)); + mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id); + hash_del(&mh->mod_hdr_hlist); + kfree(mh); +} + static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, struct mlx5e_tc_flow_parse_attr *parse_attr) { - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + bool is_eswitch_flow = mlx5e_is_eswitch_flow(flow); int num_actions, actions_size, namespace, err; - bool found = false, is_eswitch_flow; struct mlx5e_mod_hdr_entry *mh; + struct mod_hdr_tbl *tbl; struct mod_hdr_key key; u32 hash_key; @@ -303,28 +343,12 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, hash_key = hash_mod_hdr_info(&key); - is_eswitch_flow = mlx5e_is_eswitch_flow(flow); - if (is_eswitch_flow) { - namespace = MLX5_FLOW_NAMESPACE_FDB; - hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh, - mod_hdr_hlist, hash_key) { - if (!cmp_mod_hdr_info(&mh->key, &key)) { - found = true; - break; - } - } - } else { - namespace = MLX5_FLOW_NAMESPACE_KERNEL; - hash_for_each_possible(priv->fs.tc.mod_hdr_tbl, mh, - mod_hdr_hlist, hash_key) { - if (!cmp_mod_hdr_info(&mh->key, &key)) { - found = true; - break; - } - } - } + namespace = is_eswitch_flow ? + MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL; + tbl = get_mod_hdr_table(priv, namespace); - if (found) + mh = mlx5e_mod_hdr_get(tbl, &key, hash_key); + if (mh) goto attach_flow; mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL); @@ -335,6 +359,7 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, memcpy(mh->key.actions, key.actions, actions_size); mh->key.num_actions = num_actions; INIT_LIST_HEAD(&mh->flows); + refcount_set(&mh->refcnt, 1); err = mlx5_modify_header_alloc(priv->mdev, namespace, mh->key.num_actions, @@ -343,12 +368,10 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, if (err) goto out_err; - if (is_eswitch_flow) - hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key); - else - hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key); + hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key); attach_flow: + flow->mh = mh; list_add(&flow->mod_hdr, &mh->flows); if (is_eswitch_flow) flow->esw_attr->mod_hdr_id = mh->mod_hdr_id; @@ -365,23 +388,14 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { - struct list_head *next = flow->mod_hdr.next; - /* flow wasn't fully initialized */ - if (list_empty(&flow->mod_hdr)) + if (!flow->mh) return; list_del(&flow->mod_hdr); - if (list_empty(next)) { - struct mlx5e_mod_hdr_entry *mh; - - mh = list_entry(next, struct mlx5e_mod_hdr_entry, flows); - - mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id); - hash_del(&mh->mod_hdr_hlist); - kfree(mh); - } + mlx5e_mod_hdr_put(priv, flow->mh); + flow->mh = NULL; } static @@ -3844,7 +3858,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) int err; mutex_init(&tc->t_lock); - hash_init(tc->mod_hdr_tbl); + hash_init(tc->mod_hdr.hlist); mutex_init(&tc->hairpin_tbl_lock); hash_init(tc->hairpin_tbl); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 5fbebee7254d..5ce3c81e3083 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -2000,7 +2000,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) goto abort; hash_init(esw->offloads.encap_tbl); - hash_init(esw->offloads.mod_hdr_tbl); + hash_init(esw->offloads.mod_hdr.hlist); atomic64_set(&esw->offloads.num_flows, 0); mutex_init(&esw->state_lock); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 804912e38dee..fd63ba4ed0da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -182,7 +182,7 @@ struct mlx5_esw_offload { struct list_head peer_flows; struct mutex peer_mutex; DECLARE_HASHTABLE(encap_tbl, 8); - DECLARE_HASHTABLE(mod_hdr_tbl, 8); + struct mod_hdr_tbl mod_hdr; DECLARE_HASHTABLE(termtbl_tbl, 8); struct mutex termtbl_mutex; /* protects termtbl hash */ const struct mlx5_eswitch_rep_ops *rep_ops[NUM_REP_TYPES]; diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index f049af3f3cd8..96650a33aa91 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -126,6 +126,10 @@ struct mlx5_flow_destination { }; }; +struct mod_hdr_tbl { + DECLARE_HASHTABLE(hlist, 8); +}; + struct mlx5_flow_namespace * mlx5_get_fdb_sub_ns(struct mlx5_core_dev *dev, int n); struct mlx5_flow_namespace * -- GitLab From 83a52f0d525587de65b2bc979a12b4dfad9ea82a Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 8 Jun 2018 22:10:09 +0300 Subject: [PATCH 2541/7155] net/mlx5e: Protect mod header entry flows list with spinlock To remove dependency on rtnl lock, extend mod header entry with spinlock and use it to protect list of flows attached to mod header entry from concurrent modifications. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index fe1b04aa910a..09d5cc700297 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -189,6 +189,8 @@ struct mlx5e_mod_hdr_entry { /* a node of a hash table which keeps all the mod_hdr entries */ struct hlist_node mod_hdr_hlist; + /* protects flows list */ + spinlock_t flows_lock; /* flows sharing the same mod_hdr entry */ struct list_head flows; @@ -358,6 +360,7 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, mh->key.actions = (void *)mh + sizeof(*mh); memcpy(mh->key.actions, key.actions, actions_size); mh->key.num_actions = num_actions; + spin_lock_init(&mh->flows_lock); INIT_LIST_HEAD(&mh->flows); refcount_set(&mh->refcnt, 1); @@ -372,7 +375,9 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, attach_flow: flow->mh = mh; + spin_lock(&mh->flows_lock); list_add(&flow->mod_hdr, &mh->flows); + spin_unlock(&mh->flows_lock); if (is_eswitch_flow) flow->esw_attr->mod_hdr_id = mh->mod_hdr_id; else @@ -392,7 +397,9 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv, if (!flow->mh) return; + spin_lock(&flow->mh->flows_lock); list_del(&flow->mod_hdr); + spin_unlock(&flow->mh->flows_lock); mlx5e_mod_hdr_put(priv, flow->mh); flow->mh = NULL; -- GitLab From d2faae25c3050a87c8ff965a7939e999e3154b62 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 9 Aug 2019 13:20:48 +0300 Subject: [PATCH 2542/7155] net/mlx5e: Protect mod_hdr hash table with mutex To remove dependency on rtnl lock, protect mod_hdr hash table from concurrent modifications with new mutex. Implement helper function to get flow namespace to prevent code duplication. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 35 +++++++++++++------ .../net/ethernet/mellanox/mlx5/core/eswitch.c | 2 ++ include/linux/mlx5/fs.h | 1 + 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 09d5cc700297..0600b7878600 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -315,22 +315,31 @@ mlx5e_mod_hdr_get(struct mod_hdr_tbl *tbl, struct mod_hdr_key *key, u32 hash_key } static void mlx5e_mod_hdr_put(struct mlx5e_priv *priv, - struct mlx5e_mod_hdr_entry *mh) + struct mlx5e_mod_hdr_entry *mh, + int namespace) { - if (!refcount_dec_and_test(&mh->refcnt)) + struct mod_hdr_tbl *tbl = get_mod_hdr_table(priv, namespace); + + if (!refcount_dec_and_mutex_lock(&mh->refcnt, &tbl->lock)) return; + hash_del(&mh->mod_hdr_hlist); + mutex_unlock(&tbl->lock); WARN_ON(!list_empty(&mh->flows)); mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id); - hash_del(&mh->mod_hdr_hlist); + kfree(mh); } +static int get_flow_name_space(struct mlx5e_tc_flow *flow) +{ + return mlx5e_is_eswitch_flow(flow) ? + MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL; +} static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, struct mlx5e_tc_flow_parse_attr *parse_attr) { - bool is_eswitch_flow = mlx5e_is_eswitch_flow(flow); int num_actions, actions_size, namespace, err; struct mlx5e_mod_hdr_entry *mh; struct mod_hdr_tbl *tbl; @@ -345,17 +354,19 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, hash_key = hash_mod_hdr_info(&key); - namespace = is_eswitch_flow ? - MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL; + namespace = get_flow_name_space(flow); tbl = get_mod_hdr_table(priv, namespace); + mutex_lock(&tbl->lock); mh = mlx5e_mod_hdr_get(tbl, &key, hash_key); if (mh) goto attach_flow; mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL); - if (!mh) - return -ENOMEM; + if (!mh) { + err = -ENOMEM; + goto out_err; + } mh->key.actions = (void *)mh + sizeof(*mh); memcpy(mh->key.actions, key.actions, actions_size); @@ -374,11 +385,12 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key); attach_flow: + mutex_unlock(&tbl->lock); flow->mh = mh; spin_lock(&mh->flows_lock); list_add(&flow->mod_hdr, &mh->flows); spin_unlock(&mh->flows_lock); - if (is_eswitch_flow) + if (mlx5e_is_eswitch_flow(flow)) flow->esw_attr->mod_hdr_id = mh->mod_hdr_id; else flow->nic_attr->mod_hdr_id = mh->mod_hdr_id; @@ -386,6 +398,7 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, return 0; out_err: + mutex_unlock(&tbl->lock); kfree(mh); return err; } @@ -401,7 +414,7 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv, list_del(&flow->mod_hdr); spin_unlock(&flow->mh->flows_lock); - mlx5e_mod_hdr_put(priv, flow->mh); + mlx5e_mod_hdr_put(priv, flow->mh, get_flow_name_space(flow)); flow->mh = NULL; } @@ -3865,6 +3878,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv) int err; mutex_init(&tc->t_lock); + mutex_init(&tc->mod_hdr.lock); hash_init(tc->mod_hdr.hlist); mutex_init(&tc->hairpin_tbl_lock); hash_init(tc->hairpin_tbl); @@ -3898,6 +3912,7 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) if (tc->netdevice_nb.notifier_call) unregister_netdevice_notifier(&tc->netdevice_nb); + mutex_destroy(&tc->mod_hdr.lock); mutex_destroy(&tc->hairpin_tbl_lock); rhashtable_destroy(&tc->ht); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 5ce3c81e3083..2d734ecae719 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -2000,6 +2000,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) goto abort; hash_init(esw->offloads.encap_tbl); + mutex_init(&esw->offloads.mod_hdr.lock); hash_init(esw->offloads.mod_hdr.hlist); atomic64_set(&esw->offloads.num_flows, 0); mutex_init(&esw->state_lock); @@ -2037,6 +2038,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) esw->dev->priv.eswitch = NULL; destroy_workqueue(esw->work_queue); esw_offloads_cleanup_reps(esw); + mutex_destroy(&esw->offloads.mod_hdr.lock); kfree(esw->vports); kfree(esw); } diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index 96650a33aa91..1cb1045ce313 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -127,6 +127,7 @@ struct mlx5_flow_destination { }; struct mod_hdr_tbl { + struct mutex lock; /* protects hlist */ DECLARE_HASHTABLE(hlist, 8); }; -- GitLab From a734d007173119fe8e7bde1689ee4123c529e238 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 8 Aug 2019 16:53:15 +0300 Subject: [PATCH 2543/7155] net/mlx5e: Allow concurrent creation of mod_hdr entries Mod_hdr entries creation is fully synchronized by mod_hdr_tbl->lock. In order to allow concurrent allocation of hardware resources used to offload header rewrite, extend mlx5e_mod_hdr_entry with 'res_ready' completion. Move call to mlx5_modify_header_alloc() out of mod_hdr_tbl->lock critical section. Modify code that attaches new flows to existing mh to wait for 'res_ready' completion before using the entry. Insert mh to mod_hdr table before provisioning it to hardware and modify all users of mod_hdr table to verify that mh was fully initialized by checking completion result for negative value (and to wait for 'res_ready' completion, if necessary). Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 0600b7878600..fcaf9ab9e373 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -199,6 +199,8 @@ struct mlx5e_mod_hdr_entry { u32 mod_hdr_id; refcount_t refcnt; + struct completion res_ready; + int compl_result; }; #define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto) @@ -326,7 +328,8 @@ static void mlx5e_mod_hdr_put(struct mlx5e_priv *priv, mutex_unlock(&tbl->lock); WARN_ON(!list_empty(&mh->flows)); - mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id); + if (mh->compl_result > 0) + mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id); kfree(mh); } @@ -359,13 +362,21 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, mutex_lock(&tbl->lock); mh = mlx5e_mod_hdr_get(tbl, &key, hash_key); - if (mh) + if (mh) { + mutex_unlock(&tbl->lock); + wait_for_completion(&mh->res_ready); + + if (mh->compl_result < 0) { + err = -EREMOTEIO; + goto attach_header_err; + } goto attach_flow; + } mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL); if (!mh) { - err = -ENOMEM; - goto out_err; + mutex_unlock(&tbl->lock); + return -ENOMEM; } mh->key.actions = (void *)mh + sizeof(*mh); @@ -374,18 +385,23 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, spin_lock_init(&mh->flows_lock); INIT_LIST_HEAD(&mh->flows); refcount_set(&mh->refcnt, 1); + init_completion(&mh->res_ready); + + hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key); + mutex_unlock(&tbl->lock); err = mlx5_modify_header_alloc(priv->mdev, namespace, mh->key.num_actions, mh->key.actions, &mh->mod_hdr_id); - if (err) - goto out_err; - - hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key); + if (err) { + mh->compl_result = err; + goto alloc_header_err; + } + mh->compl_result = 1; + complete_all(&mh->res_ready); attach_flow: - mutex_unlock(&tbl->lock); flow->mh = mh; spin_lock(&mh->flows_lock); list_add(&flow->mod_hdr, &mh->flows); @@ -397,9 +413,10 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv, return 0; -out_err: - mutex_unlock(&tbl->lock); - kfree(mh); +alloc_header_err: + complete_all(&mh->res_ready); +attach_header_err: + mlx5e_mod_hdr_put(priv, mh, namespace); return err; } -- GitLab From 948993f2beebbdc1c9d926cfdad9827cf6bb67c0 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Sun, 3 Jun 2018 20:31:47 +0300 Subject: [PATCH 2544/7155] net/mlx5e: Extend encap entry with reference counter List of flows attached to encap entry is used as implicit reference counter (encap entry is deallocated when list becomes free) and as a mechanism to obtain encap entry that flow is attached to (through list head). This is not safe when concurrent modification of list of flows attached to encap entry is possible. Proper atomic reference counter is required to support concurrent access. As a preparation for extending encap with reference counting, extract code that lookups and deletes encap entry into standalone put/get helpers. In order to remove this dependency on external locking, extend encap entry with reference counter to manage its lifetime and extend flow structure with direct pointer to encap entry that flow is attached to. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 5 ++ .../net/ethernet/mellanox/mlx5/core/en_rep.h | 1 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 84 ++++++++++++------- .../net/ethernet/mellanox/mlx5/core/en_tc.h | 2 + 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index b7f113e996e5..cd957ff4e207 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -613,12 +613,17 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) neigh_connected = (nud_state & NUD_VALID) && !dead; list_for_each_entry(e, &nhe->encap_list, encap_list) { + if (!mlx5e_encap_take(e)) + continue; + encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); priv = netdev_priv(e->out_dev); if (encap_connected != neigh_connected || !ether_addr_equal(e->h_dest, ha)) mlx5e_rep_update_flows(priv, e, neigh_connected, ha); + + mlx5e_encap_put(priv, e); } mlx5e_rep_neigh_entry_release(nhe); rtnl_unlock(); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 43eeebe9c8d2..2e970d0729be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -164,6 +164,7 @@ struct mlx5e_encap_entry { u8 flags; char *encap_header; int encap_size; + refcount_t refcnt; }; struct mlx5e_rep_sq { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index fcaf9ab9e373..4e378200a9d2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -103,6 +103,7 @@ enum { * container_of(helper item, containing struct type, helper field[index]) */ struct encap_flow_item { + struct mlx5e_encap_entry *e; /* attached encap instance */ struct list_head list; int index; }; @@ -1433,8 +1434,11 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) list_for_each_entry(e, &nhe->encap_list, encap_list) { struct encap_flow_item *efi, *tmp; - if (!(e->flags & MLX5_ENCAP_ENTRY_VALID)) + + if (!(e->flags & MLX5_ENCAP_ENTRY_VALID) || + !mlx5e_encap_take(e)) continue; + list_for_each_entry_safe(efi, tmp, &e->flows, list) { flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); @@ -1453,6 +1457,8 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) mlx5e_flow_put(netdev_priv(e->out_dev), flow); } + + mlx5e_encap_put(netdev_priv(e->out_dev), e); if (neigh_used) break; } @@ -1472,29 +1478,33 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) } } +void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) +{ + if (!refcount_dec_and_test(&e->refcnt)) + return; + + WARN_ON(!list_empty(&e->flows)); + mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); + + if (e->flags & MLX5_ENCAP_ENTRY_VALID) + mlx5_packet_reformat_dealloc(priv->mdev, e->encap_id); + + hash_del_rcu(&e->encap_hlist); + kfree(e->encap_header); + kfree(e); +} + static void mlx5e_detach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, int out_index) { - struct list_head *next = flow->encaps[out_index].list.next; - /* flow wasn't fully initialized */ - if (list_empty(&flow->encaps[out_index].list)) + if (!flow->encaps[out_index].e) return; list_del(&flow->encaps[out_index].list); - if (list_empty(next)) { - struct mlx5e_encap_entry *e; - - e = list_entry(next, struct mlx5e_encap_entry, flows); - mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); - if (e->flags & MLX5_ENCAP_ENTRY_VALID) - mlx5_packet_reformat_dealloc(priv->mdev, e->encap_id); - - hash_del_rcu(&e->encap_hlist); - kfree(e->encap_header); - kfree(e); - } + mlx5e_encap_put(priv, flow->encaps[out_index].e); + flow->encaps[out_index].e = NULL; } static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) @@ -2817,6 +2827,31 @@ static bool is_merged_eswitch_dev(struct mlx5e_priv *priv, +bool mlx5e_encap_take(struct mlx5e_encap_entry *e) +{ + return refcount_inc_not_zero(&e->refcnt); +} + +static struct mlx5e_encap_entry * +mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key, + uintptr_t hash_key) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + struct mlx5e_encap_entry *e; + struct encap_key e_key; + + hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, + encap_hlist, hash_key) { + e_key.ip_tun_key = &e->tun_info->key; + e_key.tc_tunnel = e->tunnel; + if (!cmp_encap_info(&e_key, key) && + mlx5e_encap_take(e)) + return e; + } + + return NULL; +} + static int mlx5e_attach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, struct net_device *mirred_dev, @@ -2829,11 +2864,10 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, struct mlx5_esw_flow_attr *attr = flow->esw_attr; struct mlx5e_tc_flow_parse_attr *parse_attr; const struct ip_tunnel_info *tun_info; - struct encap_key key, e_key; + struct encap_key key; struct mlx5e_encap_entry *e; unsigned short family; uintptr_t hash_key; - bool found = false; int err = 0; parse_attr = attr->parse_attr; @@ -2848,24 +2882,17 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, hash_key = hash_encap_info(&key); - hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, - encap_hlist, hash_key) { - e_key.ip_tun_key = &e->tun_info->key; - e_key.tc_tunnel = e->tunnel; - if (!cmp_encap_info(&e_key, &key)) { - found = true; - break; - } - } + e = mlx5e_encap_get(priv, &key, hash_key); /* must verify if encap is valid or not */ - if (found) + if (e) goto attach_flow; e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) return -ENOMEM; + refcount_set(&e->refcnt, 1); e->tun_info = tun_info; err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack); if (err) @@ -2884,6 +2911,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); attach_flow: + flow->encaps[out_index].e = e; list_add(&flow->encaps[out_index].list, &e->flows); flow->encaps[out_index].index = out_index; *encap_dev = e->out_dev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index 20f045e96c92..ea2072e2fe84 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -75,6 +75,8 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); +bool mlx5e_encap_take(struct mlx5e_encap_entry *e); +void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); struct mlx5e_neigh_hash_entry; void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe); -- GitLab From 61086f391044fd587af9d70a9b8f6f800dd474ba Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 2 Aug 2019 22:21:56 +0300 Subject: [PATCH 2545/7155] net/mlx5e: Protect encap hash table with mutex To remove dependency on rtnl lock, protect encap hash table from concurrent modifications with new "encap_tbl_lock" mutex. Use the mutex to protect internal encap entry state from concurrent modification. This is necessary because a flow can be attached to multiple encap entries simultaneously, which significantly complicates using finer grained per-entry lock. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 43 ++++++++++++++----- .../net/ethernet/mellanox/mlx5/core/eswitch.c | 2 + .../net/ethernet/mellanox/mlx5/core/eswitch.h | 1 + 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 4e378200a9d2..c13db9bc1f9b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1478,33 +1478,51 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) } } -void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) +static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { - if (!refcount_dec_and_test(&e->refcnt)) - return; - WARN_ON(!list_empty(&e->flows)); mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); if (e->flags & MLX5_ENCAP_ENTRY_VALID) mlx5_packet_reformat_dealloc(priv->mdev, e->encap_id); - hash_del_rcu(&e->encap_hlist); kfree(e->encap_header); kfree(e); } +void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + + if (!refcount_dec_and_mutex_lock(&e->refcnt, &esw->offloads.encap_tbl_lock)) + return; + hash_del_rcu(&e->encap_hlist); + mutex_unlock(&esw->offloads.encap_tbl_lock); + + mlx5e_encap_dealloc(priv, e); +} + static void mlx5e_detach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, int out_index) { + struct mlx5e_encap_entry *e = flow->encaps[out_index].e; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + /* flow wasn't fully initialized */ - if (!flow->encaps[out_index].e) + if (!e) return; + mutex_lock(&esw->offloads.encap_tbl_lock); list_del(&flow->encaps[out_index].list); - - mlx5e_encap_put(priv, flow->encaps[out_index].e); flow->encaps[out_index].e = NULL; + if (!refcount_dec_and_test(&e->refcnt)) { + mutex_unlock(&esw->offloads.encap_tbl_lock); + return; + } + hash_del_rcu(&e->encap_hlist); + mutex_unlock(&esw->offloads.encap_tbl_lock); + + mlx5e_encap_dealloc(priv, e); } static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) @@ -2882,6 +2900,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, hash_key = hash_encap_info(&key); + mutex_lock(&esw->offloads.encap_tbl_lock); e = mlx5e_encap_get(priv, &key, hash_key); /* must verify if encap is valid or not */ @@ -2889,8 +2908,10 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, goto attach_flow; e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) - return -ENOMEM; + if (!e) { + err = -ENOMEM; + goto out_err; + } refcount_set(&e->refcnt, 1); e->tun_info = tun_info; @@ -2922,10 +2943,12 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, } else { *encap_valid = false; } + mutex_unlock(&esw->offloads.encap_tbl_lock); return err; out_err: + mutex_unlock(&esw->offloads.encap_tbl_lock); kfree(e); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 2d734ecae719..f0692407f617 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1999,6 +1999,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) if (err) goto abort; + mutex_init(&esw->offloads.encap_tbl_lock); hash_init(esw->offloads.encap_tbl); mutex_init(&esw->offloads.mod_hdr.lock); hash_init(esw->offloads.mod_hdr.hlist); @@ -2039,6 +2040,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) destroy_workqueue(esw->work_queue); esw_offloads_cleanup_reps(esw); mutex_destroy(&esw->offloads.mod_hdr.lock); + mutex_destroy(&esw->offloads.encap_tbl_lock); kfree(esw->vports); kfree(esw); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index fd63ba4ed0da..86db0e9776da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -181,6 +181,7 @@ struct mlx5_esw_offload { struct mlx5_eswitch_rep *vport_reps; struct list_head peer_flows; struct mutex peer_mutex; + struct mutex encap_tbl_lock; /* protects encap_tbl */ DECLARE_HASHTABLE(encap_tbl, 8); struct mod_hdr_tbl mod_hdr; DECLARE_HASHTABLE(termtbl_tbl, 8); -- GitLab From d589e785baf5e48ee80a4fbfed96661a4c7c8c8d Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Thu, 8 Aug 2019 17:01:33 +0300 Subject: [PATCH 2546/7155] net/mlx5e: Allow concurrent creation of encap entries Encap entries creation is fully synchronized by encap_tbl_lock. In order to allow concurrent allocation of hardware resources used to offload encapsulation, extend mlx5e_encap_entry with 'res_ready' completion. Move call to mlx5e_tc_tun_create_header_ipv{4|6}() out of encap_tbl_lock critical section. Modify code that attaches new flows to existing encap to wait for 'res_ready' completion before using the entry. Insert encap entry to table before provisioning it to hardware and modify all users of the encap table to verify that encap was fully initialized by checking completion result for non-zero value (and to wait for 'res_ready' completion, if necessary). Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 ++ .../net/ethernet/mellanox/mlx5/core/en_tc.c | 33 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 2e970d0729be..8ac96727cad8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -165,6 +165,8 @@ struct mlx5e_encap_entry { char *encap_header; int encap_size; refcount_t refcnt; + struct completion res_ready; + int compl_result; }; struct mlx5e_rep_sq { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c13db9bc1f9b..5be3da621499 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2904,8 +2904,18 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, e = mlx5e_encap_get(priv, &key, hash_key); /* must verify if encap is valid or not */ - if (e) + if (e) { + mutex_unlock(&esw->offloads.encap_tbl_lock); + wait_for_completion(&e->res_ready); + + /* Protect against concurrent neigh update. */ + mutex_lock(&esw->offloads.encap_tbl_lock); + if (e->compl_result) { + err = -EREMOTEIO; + goto out_err; + } goto attach_flow; + } e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) { @@ -2914,22 +2924,32 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, } refcount_set(&e->refcnt, 1); + init_completion(&e->res_ready); + e->tun_info = tun_info; err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack); - if (err) + if (err) { + kfree(e); + e = NULL; goto out_err; + } INIT_LIST_HEAD(&e->flows); + hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); + mutex_unlock(&esw->offloads.encap_tbl_lock); if (family == AF_INET) err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e); else if (family == AF_INET6) err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e); - if (err) + /* Protect against concurrent neigh update. */ + mutex_lock(&esw->offloads.encap_tbl_lock); + complete_all(&e->res_ready); + if (err) { + e->compl_result = err; goto out_err; - - hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); + } attach_flow: flow->encaps[out_index].e = e; @@ -2949,7 +2969,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, out_err: mutex_unlock(&esw->offloads.encap_tbl_lock); - kfree(e); + if (e) + mlx5e_encap_put(priv, e); return err; } -- GitLab From ef2e4094e076858343ea1202046443f642a245cd Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Fri, 26 Jul 2019 08:26:52 -0500 Subject: [PATCH 2547/7155] net/mlx5: E-switch, Removed unused hwid Currently mlx5_eswitch_rep stores same hw ID for all representors. However it is never used from this structure. It is always used from mlx5_vport. Hence, remove unused field. Signed-off-by: Parav Pandit Reviewed-by: Vu Pham Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 6 +----- include/linux/mlx5/eswitch.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 8fe5dddf18d0..42cc5001255b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -1393,10 +1393,9 @@ void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw) int esw_offloads_init_reps(struct mlx5_eswitch *esw) { int total_vports = esw->total_vports; - struct mlx5_core_dev *dev = esw->dev; struct mlx5_eswitch_rep *rep; - u8 hw_id[ETH_ALEN], rep_type; int vport_index; + u8 rep_type; esw->offloads.vport_reps = kcalloc(total_vports, sizeof(struct mlx5_eswitch_rep), @@ -1404,12 +1403,9 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) if (!esw->offloads.vport_reps) return -ENOMEM; - mlx5_query_mac_address(dev, hw_id); - mlx5_esw_for_all_reps(esw, vport_index, rep) { rep->vport = mlx5_eswitch_index_to_vport_num(esw, vport_index); rep->vport_index = vport_index; - ether_addr_copy(rep->hw_id, hw_id); for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) atomic_set(&rep->rep_data[rep_type].state, diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index 46b5ba029802..38a70d16d8d5 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -44,7 +44,6 @@ struct mlx5_eswitch_rep_data { struct mlx5_eswitch_rep { struct mlx5_eswitch_rep_data rep_data[NUM_REP_TYPES]; u16 vport; - u8 hw_id[ETH_ALEN]; u16 vlan; /* Only IB rep is using vport_index */ u16 vport_index; -- GitLab From 724ee17912c9a8e5362751a22fd955166ed0550a Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Fri, 26 Jul 2019 13:42:04 -0500 Subject: [PATCH 2548/7155] net/mlx5e: Simplify querying port representor parent id System image GUID doesn't depend on eswitch switchdev mode. Hence, remove the check which simplifies the code. Signed-off-by: Parav Pandit Reviewed-by: Vu Pham Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index cd957ff4e207..33ae66dc72e2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -389,24 +389,17 @@ static const struct ethtool_ops mlx5e_uplink_rep_ethtool_ops = { .set_pauseparam = mlx5e_uplink_rep_set_pauseparam, }; -static int mlx5e_rep_get_port_parent_id(struct net_device *dev, - struct netdev_phys_item_id *ppid) +static void mlx5e_rep_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { - struct mlx5_eswitch *esw; struct mlx5e_priv *priv; u64 parent_id; priv = netdev_priv(dev); - esw = priv->mdev->priv.eswitch; - - if (esw->mode == MLX5_ESWITCH_NONE) - return -EOPNOTSUPP; parent_id = mlx5_query_nic_system_image_guid(priv->mdev); ppid->id_len = sizeof(parent_id); memcpy(ppid->id, &parent_id, sizeof(parent_id)); - - return 0; } static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, @@ -1759,14 +1752,11 @@ static int register_devlink_port(struct mlx5_core_dev *dev, struct devlink *devlink = priv_to_devlink(dev); struct mlx5_eswitch_rep *rep = rpriv->rep; struct netdev_phys_item_id ppid = {}; - int ret; if (!is_devlink_port_supported(dev, rpriv)) return 0; - ret = mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid); - if (ret) - return ret; + mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid); if (rep->vport == MLX5_VPORT_UPLINK) devlink_port_attrs_set(&rpriv->dl_port, -- GitLab From c938451f6b9ccbf25eceb27fe1d1c24fd98af923 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Sat, 20 Jul 2019 22:20:58 -0500 Subject: [PATCH 2549/7155] net/mlx5e: Use vhca_id in generating representor port_index It is desired to use unique port indices when multiple pci devices' devlink instance have the same switch-id. Make use of vhca-id to generate such unique devlink port indices. Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 33ae66dc72e2..7ce5cb6e527e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1746,34 +1746,46 @@ is_devlink_port_supported(const struct mlx5_core_dev *dev, mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport); } +static unsigned int +vport_to_devlink_port_index(const struct mlx5_core_dev *dev, u16 vport_num) +{ + return (MLX5_CAP_GEN(dev, vhca_id) << 16) | vport_num; +} + static int register_devlink_port(struct mlx5_core_dev *dev, struct mlx5e_rep_priv *rpriv) { struct devlink *devlink = priv_to_devlink(dev); struct mlx5_eswitch_rep *rep = rpriv->rep; struct netdev_phys_item_id ppid = {}; + unsigned int dl_port_index = 0; if (!is_devlink_port_supported(dev, rpriv)) return 0; mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid); - if (rep->vport == MLX5_VPORT_UPLINK) + if (rep->vport == MLX5_VPORT_UPLINK) { devlink_port_attrs_set(&rpriv->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, PCI_FUNC(dev->pdev->devfn), false, 0, &ppid.id[0], ppid.id_len); - else if (rep->vport == MLX5_VPORT_PF) + dl_port_index = vport_to_devlink_port_index(dev, rep->vport); + } else if (rep->vport == MLX5_VPORT_PF) { devlink_port_attrs_pci_pf_set(&rpriv->dl_port, &ppid.id[0], ppid.id_len, dev->pdev->devfn); - else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport)) + dl_port_index = rep->vport; + } else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, + rpriv->rep->vport)) { devlink_port_attrs_pci_vf_set(&rpriv->dl_port, &ppid.id[0], ppid.id_len, dev->pdev->devfn, rep->vport - 1); + dl_port_index = vport_to_devlink_port_index(dev, rep->vport); + } - return devlink_port_register(devlink, &rpriv->dl_port, rep->vport); + return devlink_port_register(devlink, &rpriv->dl_port, dl_port_index); } static void unregister_devlink_port(struct mlx5_core_dev *dev, -- GitLab From b51c225e6c4e987e131b8b1332f66969382bf328 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Sat, 3 Aug 2019 00:48:28 +0800 Subject: [PATCH 2550/7155] net/mlx5e: Use refcount_t for refcount refcount_t is better for reference counters since its implementation can prevent overflows. So convert atomic_t ref counters to refcount_t. Signed-off-by: Chuhong Yuan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c index b9d4f4e19ff9..148b55c3db7a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include "mlx5_core.h" @@ -48,7 +49,7 @@ struct mlx5_vxlan { struct mlx5_vxlan_port { struct hlist_node hlist; - atomic_t refcount; + refcount_t refcount; u16 udp_port; }; @@ -113,7 +114,7 @@ int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port) vxlanp = mlx5_vxlan_lookup_port(vxlan, port); if (vxlanp) { - atomic_inc(&vxlanp->refcount); + refcount_inc(&vxlanp->refcount); return 0; } @@ -137,7 +138,7 @@ int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port) } vxlanp->udp_port = port; - atomic_set(&vxlanp->refcount, 1); + refcount_set(&vxlanp->refcount, 1); spin_lock_bh(&vxlan->lock); hash_add(vxlan->htable, &vxlanp->hlist, port); @@ -170,7 +171,7 @@ int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port) goto out_unlock; } - if (atomic_dec_and_test(&vxlanp->refcount)) { + if (refcount_dec_and_test(&vxlanp->refcount)) { hash_del(&vxlanp->hlist); remove = true; } -- GitLab From f887427b2cecfb57165f0207b33aed89dd29ab61 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 9 Aug 2019 16:13:38 -0700 Subject: [PATCH 2551/7155] selftests: Fix detection of nettest command in fcnal-test Most of the tests run by fcnal-test.sh relies on the nettest command. Rather than trying to cover all of the individual tests, check for the binary only at the beginning. Also removes the need for log_error which is undefined. Fixes: 6f9d5cacfe07 ("selftests: Setup for functional tests for fib and socket lookups") Signed-off-by: David Ahern Signed-off-by: David S. Miller --- tools/testing/selftests/net/fcnal-test.sh | 38 ++++------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index bd6b564382ec..9fd3a0b97f0d 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -998,13 +998,6 @@ ipv4_tcp_vrf() ipv4_tcp() { log_section "IPv4/TCP" - - which nettest >/dev/null - if [ $? -ne 0 ]; then - log_error "nettest not found; skipping tests" - return - fi - log_subsection "No VRF" setup @@ -1375,12 +1368,6 @@ ipv4_udp_vrf() ipv4_udp() { - which nettest >/dev/null - if [ $? -ne 0 ]; then - log_error "nettest not found; skipping tests" - return - fi - log_section "IPv4/UDP" log_subsection "No VRF" @@ -2314,13 +2301,6 @@ ipv6_tcp_vrf() ipv6_tcp() { log_section "IPv6/TCP" - - which nettest >/dev/null - if [ $? -ne 0 ]; then - log_error "nettest not found; skipping tests" - return - fi - log_subsection "No VRF" setup @@ -3156,12 +3136,6 @@ netfilter_icmp() ipv4_netfilter() { - which nettest >/dev/null - if [ $? -ne 0 ]; then - log_error "nettest not found; skipping tests" - return - fi - log_section "IPv4 Netfilter" log_subsection "TCP reset" @@ -3219,12 +3193,6 @@ netfilter_icmp6() ipv6_netfilter() { - which nettest >/dev/null - if [ $? -ne 0 ]; then - log_error "nettest not found; skipping tests" - return - fi - log_section "IPv6 Netfilter" log_subsection "TCP reset" @@ -3422,6 +3390,12 @@ elif [ "$TESTS" = "ipv6" ]; then TESTS="$TESTS_IPV6" fi +which nettest >/dev/null +if [ $? -ne 0 ]; then + echo "'nettest' command not found; skipping tests" + exit 0 +fi + declare -i nfail=0 declare -i nsuccess=0 -- GitLab From 62ad42ec9c4933f8973e5a28d9abdb63f8f901a0 Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 9 Aug 2019 18:46:40 -0400 Subject: [PATCH 2552/7155] tc-testing: added tdc tests for matchall filter Signed-off-by: Roman Mashak Signed-off-by: David S. Miller --- .../tc-testing/tc-tests/filters/matchall.json | 391 ++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 tools/testing/selftests/tc-testing/tc-tests/filters/matchall.json diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/matchall.json b/tools/testing/selftests/tc-testing/tc-tests/filters/matchall.json new file mode 100644 index 000000000000..5f24c0598624 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/matchall.json @@ -0,0 +1,391 @@ +[ + { + "id": "f62b", + "name": "Add ingress matchall filter for protocol ipv4 and action PASS", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ip matchall action ok", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 prio 1 protocol ip matchall", + "matchPattern": "^filter parent ffff: protocol ip pref 1 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "7f09", + "name": "Add egress matchall filter for protocol ipv4 and action PASS", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0x1 prio 1 protocol ip matchall action ok", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 1 prio 1 protocol ip matchall", + "matchPattern": "^filter parent 1: protocol ip pref 1 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "0596", + "name": "Add ingress matchall filter for protocol ipv6 and action DROP", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall action drop", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 prio 1 protocol ipv6 matchall", + "matchPattern": "^filter parent ffff: protocol ipv6 pref 1 matchall.*handle 0x1.*gact action drop.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "41df", + "name": "Add egress matchall filter for protocol ipv6 and action DROP", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0x1 prio 1 protocol ipv6 matchall action drop", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 1 prio 1 protocol ipv6 matchall", + "matchPattern": "^filter parent 1: protocol ipv6 pref 1 matchall.*handle 0x1.*gact action drop.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "e1da", + "name": "Add ingress matchall filter for protocol ipv4 and action PASS with priority at 16-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 65535 protocol ipv4 matchall action pass", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 prio 65535 protocol ipv4 matchall", + "matchPattern": "^filter parent ffff: protocol ip pref 65535 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "3de5", + "name": "Add egress matchall filter for protocol ipv4 and action PASS with priority at 16-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0x1 prio 65535 protocol ipv4 matchall action pass", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 1 prio 65535 protocol ipv4 matchall", + "matchPattern": "^filter parent 1: protocol ip pref 65535 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "72d7", + "name": "Add ingress matchall filter for protocol ipv4 and action PASS with priority exceeding 16-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 655355 protocol ipv4 matchall action pass", + "expExitCode": "255", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 prio 655355 protocol ipv4 matchall", + "matchPattern": "^filter parent ffff: protocol ip pref 655355 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "41d3", + "name": "Add egress matchall filter for protocol ipv4 and action PASS with priority exceeding 16-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0x1 prio 655355 protocol ipv4 matchall action pass", + "expExitCode": "255", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 1 prio 655355 protocol ipv4 matchall", + "matchPattern": "^filter parent 1: protocol ip pref 655355 matchall.*handle 0x1.*gact action pass.*ref 1 bind 1", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "f755", + "name": "Add ingress matchall filter for all protocols and action CONTINUE with handle at 32-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0xffffffff prio 1 protocol all matchall action continue", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 0xffffffff prio 1 protocol all matchall", + "matchPattern": "^filter parent ffff: protocol all pref 1 matchall.*handle 0xffffffff.*gact action continue.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "2c33", + "name": "Add egress matchall filter for all protocols and action CONTINUE with handle at 32-bit maximum", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0xffffffff prio 1 protocol all matchall action continue", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 0xffffffff prio 1 protocol all matchall", + "matchPattern": "^filter parent 1: protocol all pref 1 matchall.*handle 0xffffffff.*gact action continue.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "0e4a", + "name": "Add ingress matchall filter for all protocols and action RECLASSIFY with skip_hw flag", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol all matchall skip_hw action reclassify", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 0x1 prio 1 protocol all matchall", + "matchPattern": "^filter parent ffff: protocol all pref 1 matchall.*handle 0x1.*skip_hw.*not_in_hw.*gact action reclassify.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "7f60", + "name": "Add egress matchall filter for all protocols and action RECLASSIFY with skip_hw flag", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 root handle 1: prio" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent 1: handle 0x1 prio 1 protocol all matchall skip_hw action reclassify", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent 1: handle 0x1 prio 1 protocol all matchall", + "matchPattern": "^filter parent 1: protocol all pref 1 matchall.*handle 0x1.*skip_hw.*not_in_hw.*gact action reclassify.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 root handle 1: prio", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "8bd2", + "name": "Add ingress matchall filter for protocol ipv6 and action PASS with classid", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall classid 1:1 action pass", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall", + "matchPattern": "^filter parent ffff: protocol ipv6 pref 1 matchall.*handle 0x1.*flowid 1:1.*gact action pass.*ref 1 bind 1", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "2a4a", + "name": "Add ingress matchall filter for protocol ipv6 and action PASS with invalid classid", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall classid 6789defg action pass", + "expExitCode": "1", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall", + "matchPattern": "^filter protocol ipv6 pref 1 matchall.*handle 0x1.*flowid 6789defg.*gact action pass.*ref 1 bind 1", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "eaf8", + "name": "Delete single ingress matchall filter", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall classid 1:2 action pass" + ], + "cmdUnderTest": "$TC filter del dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv6 matchall", + "matchPattern": "^filter protocol ipv6 pref 1 matchall.*handle 0x1.*flowid 1:2.*gact action pass.*ref 1 bind 1", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "76ad", + "name": "Delete all ingress matchall filters", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol all matchall classid 1:2 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x2 prio 2 protocol all matchall classid 1:3 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x3 prio 3 protocol all matchall classid 1:4 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x4 prio 4 protocol all matchall classid 1:5 action pass" + ], + "cmdUnderTest": "$TC filter del dev $DEV1 parent ffff:", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", + "matchPattern": "^filter protocol all pref.*matchall.*handle.*flowid.*gact action pass", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "1eb9", + "name": "Delete single ingress matchall filter out of multiple", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol all matchall classid 1:2 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x2 prio 2 protocol all matchall classid 1:3 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x3 prio 3 protocol all matchall classid 1:4 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x4 prio 4 protocol all matchall classid 1:5 action pass" + ], + "cmdUnderTest": "$TC filter del dev $DEV1 parent ffff: protocol all handle 0x2 prio 2 matchall", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", + "matchPattern": "^filter protocol all pref 2 matchall.*handle 0x2 flowid 1:2.*gact action pass", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + }, + { + "id": "6d63", + "name": "Delete ingress matchall filter by chain ID", + "category": [ + "filter", + "matchall" + ], + "setup": [ + "$IP link add dev $DEV1 type dummy || /bin/true", + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol all chain 1 matchall classid 1:1 action pass", + "$TC filter add dev $DEV1 parent ffff: handle 0x1 prio 1 protocol ipv4 chain 2 matchall classid 1:3 action continue" + ], + "cmdUnderTest": "$TC filter del dev $DEV1 parent ffff: chain 2", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", + "matchPattern": "^filter protocol all pref 1 matchall chain 1 handle 0x1 flowid 1:1.*gact action pass", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress", + "$IP link del dev $DEV1 type dummy" + ] + } +] -- GitLab From a190d94830c30e41bd5fbdf803a636263208fa2e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 22:27:43 +0200 Subject: [PATCH 2553/7155] usb: remove ehci-w90x900 driver The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190809202749.742267-16-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 6 -- drivers/usb/host/Makefile | 1 - drivers/usb/host/ehci-w90x900.c | 130 -------------------------------- 3 files changed, 137 deletions(-) delete mode 100644 drivers/usb/host/ehci-w90x900.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d040408f5baa..f39f24f107f4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -287,12 +287,6 @@ config USB_EHCI_MV Dova, Armada 370 and Armada XP. See "Support for Marvell EBU on-chip EHCI USB controller" for those. -config USB_W90X900_EHCI - tristate "W90X900(W90P910) EHCI support" - depends on ARCH_W90X900 - ---help--- - Enables support for the W90X900 USB controller - config USB_CNS3XXX_EHCI bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" depends on ARCH_CNS3XXX diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 59b39e6b350b..b191361257cc 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,7 +49,6 @@ obj-$(CONFIG_USB_EHCI_HCD_STI) += ehci-st.o obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o -obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c deleted file mode 100644 index 6d77ace1697b..000000000000 --- a/drivers/usb/host/ehci-w90x900.c +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/driver/usb/host/ehci-w90x900.c - * - * Copyright (c) 2008 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ehci.h" - -/* enable phy0 and phy1 for w90p910 */ -#define ENPHY (0x01<<8) -#define PHY0_CTR (0xA4) -#define PHY1_CTR (0xA8) - -#define DRIVER_DESC "EHCI w90x900 driver" - -static const char hcd_name[] = "ehci-w90x900 "; - -static struct hc_driver __read_mostly ehci_w90x900_hc_driver; - -static int ehci_w90x900_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - struct resource *res; - int retval = 0, irq; - unsigned long val; - - hcd = usb_create_hcd(&ehci_w90x900_hc_driver, - &pdev->dev, "w90x900 EHCI"); - if (!hcd) { - retval = -ENOMEM; - goto err1; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hcd->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hcd->regs)) { - retval = PTR_ERR(hcd->regs); - goto err2; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* enable PHY 0,1,the regs only apply to w90p910 - * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of - * w90p910 IC relative to ehci->regs. - */ - val = __raw_readl(ehci->regs+PHY0_CTR); - val |= ENPHY; - __raw_writel(val, ehci->regs+PHY0_CTR); - - val = __raw_readl(ehci->regs+PHY1_CTR); - val |= ENPHY; - __raw_writel(val, ehci->regs+PHY1_CTR); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - retval = irq; - goto err2; - } - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval != 0) - goto err2; - - device_wakeup_enable(hcd->self.controller); - return retval; -err2: - usb_put_hcd(hcd); -err1: - return retval; -} - -static int ehci_w90x900_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - - return 0; -} - -static struct platform_driver ehci_hcd_w90x900_driver = { - .probe = ehci_w90x900_probe, - .remove = ehci_w90x900_remove, - .driver = { - .name = "w90x900-ehci", - }, -}; - -static int __init ehci_w90X900_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_info("%s: " DRIVER_DESC "\n", hcd_name); - - ehci_init_driver(&ehci_w90x900_hc_driver, NULL); - return platform_driver_register(&ehci_hcd_w90x900_driver); -} -module_init(ehci_w90X900_init); - -static void __exit ehci_w90X900_cleanup(void) -{ - platform_driver_unregister(&ehci_hcd_w90x900_driver); -} -module_exit(ehci_w90X900_cleanup); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Wan ZongShun "); -MODULE_ALIAS("platform:w90p910-ehci"); -MODULE_LICENSE("GPL v2"); -- GitLab From b772d7aeae093a120c737c0183df532262229efe Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 22:27:31 +0200 Subject: [PATCH 2554/7155] gpio: remove ks8695 driver The platform is getting removed, so there are no remaining users of this driver. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190809202749.742267-4-arnd@arndb.de Signed-off-by: Linus Walleij --- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-ks8695.c | 284 ------------------------------------- 2 files changed, 285 deletions(-) delete mode 100644 drivers/gpio/gpio-ks8695.c diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a4e91175c708..65d74084c9b2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -67,7 +67,6 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o -obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c deleted file mode 100644 index a0f87c124894..000000000000 --- a/drivers/gpio/gpio-ks8695.c +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * arch/arm/mach-ks8695/gpio.c - * - * Copyright (C) 2006 Andrew Victor - * Updated to GPIOLIB, Copyright 2008 Simtec Electronics - * Daniel Silverstone - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -/* - * Configure a GPIO line for either GPIO function, or its internal - * function (Interrupt, Timer, etc). - */ -static void ks8695_gpio_mode(unsigned int pin, short gpio) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned long x, flags; - - if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ - return; - - local_irq_save(flags); - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - if (gpio) /* GPIO: set bit to 0 */ - x &= ~enable[pin]; - else /* Internal function: set bit to 1 */ - x |= enable[pin]; - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); - - local_irq_restore(flags); -} - - -static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; - -/* - * Configure GPIO pin as external interrupt source. - */ -int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - /* Set IRQ triggering type */ - irq_set_irq_type(gpio_irq[pin], type); - - /* enable interrupt mode */ - ks8695_gpio_mode(pin, 0); - - return 0; -} -EXPORT_SYMBOL(ks8695_gpio_interrupt); - - - -/* .... Generic GPIO interface .............................................. */ - -/* - * Configure the GPIO line as an input. - */ -static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Configure the GPIO line as an output, with default state. - */ -static int ks8695_gpio_direction_output(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - /* set pin as output */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x |= IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Set the state of an output GPIO line. - */ -static void ks8695_gpio_set_value(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return; - - local_irq_save(flags); - - /* set output line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - local_irq_restore(flags); -} - - -/* - * Read the state of a GPIO line. - */ -static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - return (x & IOPD(pin)) != 0; -} - - -/* - * Map GPIO line to IRQ number. - */ -static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) -{ - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - return gpio_irq[pin]; -} - -/* GPIOLIB interface */ - -static struct gpio_chip ks8695_gpio_chip = { - .label = "KS8695", - .direction_input = ks8695_gpio_direction_input, - .direction_output = ks8695_gpio_direction_output, - .get = ks8695_gpio_get_value, - .set = ks8695_gpio_set_value, - .to_irq = ks8695_gpio_to_irq, - .base = 0, - .ngpio = 16, - .can_sleep = false, -}; - -/* Register the GPIOs */ -void ks8695_register_gpios(void) -{ - if (gpiochip_add_data(&ks8695_gpio_chip, NULL)) - printk(KERN_ERR "Unable to register core GPIOs\n"); -} - -/* .... Debug interface ..................................................... */ - -#ifdef CONFIG_DEBUG_FS - -static int ks8695_gpio_show(struct seq_file *s, void *unused) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; - unsigned long mode, ctrl, data; - int i; - - mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - - seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); - - for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { - seq_printf(s, "%i:\t", i); - - seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); - - if (i <= KS8695_GPIO_3) { - if (ctrl & enable[i]) { - seq_printf(s, "EXT%i ", i); - - switch ((ctrl & intmask[i]) >> (4 * i)) { - case IOPC_TM_LOW: - seq_printf(s, "(Low)"); break; - case IOPC_TM_HIGH: - seq_printf(s, "(High)"); break; - case IOPC_TM_RISING: - seq_printf(s, "(Rising)"); break; - case IOPC_TM_FALLING: - seq_printf(s, "(Falling)"); break; - case IOPC_TM_EDGE: - seq_printf(s, "(Edges)"); break; - } - } else - seq_printf(s, "GPIO\t"); - } else if (i <= KS8695_GPIO_5) { - if (ctrl & enable[i]) - seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); - else - seq_printf(s, "GPIO\t"); - } else { - seq_printf(s, "GPIO\t"); - } - - seq_printf(s, "\t"); - - seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); - } - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ks8695_gpio); - -static int __init ks8695_gpio_debugfs_init(void) -{ - /* /sys/kernel/debug/ks8695_gpio */ - debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, - &ks8695_gpio_fops); - return 0; -} -postcore_initcall(ks8695_gpio_debugfs_init); - -#endif -- GitLab From 92b8608691bf129b1137be46a3a0058bcacc97a9 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 9 Aug 2019 14:37:10 -0700 Subject: [PATCH 2555/7155] dt-bindings: usb: renesas_gen3: Rename bindings documentation file to reflect IP block For consistency with the naming of (most) other documentation files for DT bindings for Renesas IP blocks rename the Renesas USB3.0 peripheral documentation file from renesas,usb3.txt to renesas,usb3-peri.txt This refines a recent rename from renesas_usb3.txt to renesas,usb3.txt. The motivation is to more accurately reflect the IP block documented in this file. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Reviewed-by: Niklas Sderlund Link: https://lore.kernel.org/r/20190809213710.31783-1-horms+renesas@verge.net.au Signed-off-by: Greg Kroah-Hartman --- .../bindings/usb/{renesas,usb3.txt => renesas,usb3-peri.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/usb/{renesas,usb3.txt => renesas,usb3-peri.txt} (100%) diff --git a/Documentation/devicetree/bindings/usb/renesas,usb3.txt b/Documentation/devicetree/bindings/usb/renesas,usb3-peri.txt similarity index 100% rename from Documentation/devicetree/bindings/usb/renesas,usb3.txt rename to Documentation/devicetree/bindings/usb/renesas,usb3-peri.txt -- GitLab From 11f26633cccb7243217370837cbb066a73f678a5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 10 Aug 2019 13:18:06 +0200 Subject: [PATCH 2556/7155] PM: suspend: Fix platform_suspend_prepare_noirq() After commit ac9eafbe930a ("ACPI: PM: s2idle: Execute LPS0 _DSM functions with suspended devices"), a NULL pointer may be dereferenced if suspend-to-idle is attempted on a platform without "traditional" suspend support due to invalid fall-through in platform_suspend_prepare_noirq(). Fix that and while at it add missing braces in platform_resume_noirq(). Fixes: ac9eafbe930a ("ACPI: PM: s2idle: Execute LPS0 _DSM functions with suspended devices") Reported-by: Marek Szyprowski Signed-off-by: Rafael J. Wysocki --- kernel/power/suspend.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index ed9ddef12b13..f3b7239f1892 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -253,10 +253,10 @@ static int platform_suspend_prepare_late(suspend_state_t state) static int platform_suspend_prepare_noirq(suspend_state_t state) { - if (state == PM_SUSPEND_TO_IDLE) { - if (s2idle_ops && s2idle_ops->prepare_late) - return s2idle_ops->prepare_late(); - } + if (state == PM_SUSPEND_TO_IDLE) + return s2idle_ops && s2idle_ops->prepare_late ? + s2idle_ops->prepare_late() : 0; + return suspend_ops->prepare_late ? suspend_ops->prepare_late() : 0; } @@ -265,8 +265,9 @@ static void platform_resume_noirq(suspend_state_t state) if (state == PM_SUSPEND_TO_IDLE) { if (s2idle_ops && s2idle_ops->restore_early) s2idle_ops->restore_early(); - } else if (suspend_ops->wake) + } else if (suspend_ops->wake) { suspend_ops->wake(); + } } static void platform_resume_early(suspend_state_t state) -- GitLab From 6a1490367c44f94614e39e8b98ff7114ff8a6449 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:01 +0530 Subject: [PATCH 2557/7155] cpufreq: Add policy create/remove notifiers back This effectively reverts some changes made by commit f9f41e3ef99 ("cpufreq: Remove policy create/remove notifiers"). We have a new use case for policy create/remove notifiers (for allocating/freeing QoS requests per policy), so add them back. Signed-off-by: Viresh Kumar [ rjw: Subject & changelog ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 15 ++++++++++++++- include/linux/cpufreq.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8dda62367816..c13dcb59b30c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1266,7 +1266,17 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) DEV_PM_QOS_MAX_FREQUENCY); dev_pm_qos_remove_notifier(dev, &policy->nb_min, DEV_PM_QOS_MIN_FREQUENCY); - dev_pm_qos_remove_request(policy->max_freq_req); + + if (policy->max_freq_req) { + /* + * CPUFREQ_CREATE_POLICY notification is sent only after + * successfully adding max_freq_req request. + */ + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_REMOVE_POLICY, policy); + dev_pm_qos_remove_request(policy->max_freq_req); + } + dev_pm_qos_remove_request(policy->min_freq_req); kfree(policy->min_freq_req); @@ -1391,6 +1401,9 @@ static int cpufreq_online(unsigned int cpu) ret); goto out_destroy_policy; } + + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_CREATE_POLICY, policy); } if (cpufreq_driver->get && has_target()) { diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 536a049d7ecc..afc10384a681 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -458,6 +458,8 @@ static inline void cpufreq_resume(void) {} /* Policy Notifiers */ #define CPUFREQ_ADJUST (0) #define CPUFREQ_NOTIFY (1) +#define CPUFREQ_CREATE_POLICY (2) +#define CPUFREQ_REMOVE_POLICY (3) #ifdef CONFIG_CPU_FREQ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); -- GitLab From 5130802ddbb10a73cf17d1117e2044c8d5ba7d65 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:02 +0530 Subject: [PATCH 2558/7155] thermal: cpu_cooling: Switch to QoS requests for freq limits The cpufreq core now takes the min/max frequency constraints via QoS requests and the CPUFREQ_ADJUST notifier shall get removed later on. Switch over to using the QoS request for maximum frequency constraint for cpu_cooling driver. Signed-off-by: Viresh Kumar [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- drivers/thermal/cpu_cooling.c | 110 ++++++++-------------------------- 1 file changed, 26 insertions(+), 84 deletions(-) diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 4c5db59a619b..391f39776c6a 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -66,8 +67,6 @@ struct time_in_idle { * @last_load: load measured by the latest call to cpufreq_get_requested_power() * @cpufreq_state: integer value representing the current state of cpufreq * cooling devices. - * @clipped_freq: integer value representing the absolute value of the clipped - * frequency. * @max_level: maximum cooling level. One less than total number of valid * cpufreq frequencies. * @freq_table: Freq table in descending order of frequencies @@ -84,12 +83,12 @@ struct cpufreq_cooling_device { int id; u32 last_load; unsigned int cpufreq_state; - unsigned int clipped_freq; unsigned int max_level; struct freq_table *freq_table; /* In descending order */ struct cpufreq_policy *policy; struct list_head node; struct time_in_idle *idle_time; + struct dev_pm_qos_request qos_req; }; static DEFINE_IDA(cpufreq_ida); @@ -118,59 +117,6 @@ static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev, return level - 1; } -/** - * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. - * @nb: struct notifier_block * with callback info. - * @event: value showing cpufreq event for which this function invoked. - * @data: callback-specific data - * - * Callback to hijack the notification on cpufreq policy transition. - * Every time there is a change in policy, we will intercept and - * update the cpufreq policy with thermal constraints. - * - * Return: 0 (success) - */ -static int cpufreq_thermal_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_policy *policy = data; - unsigned long clipped_freq; - struct cpufreq_cooling_device *cpufreq_cdev; - - if (event != CPUFREQ_ADJUST) - return NOTIFY_DONE; - - mutex_lock(&cooling_list_lock); - list_for_each_entry(cpufreq_cdev, &cpufreq_cdev_list, node) { - /* - * A new copy of the policy is sent to the notifier and can't - * compare that directly. - */ - if (policy->cpu != cpufreq_cdev->policy->cpu) - continue; - - /* - * policy->max is the maximum allowed frequency defined by user - * and clipped_freq is the maximum that thermal constraints - * allow. - * - * If clipped_freq is lower than policy->max, then we need to - * readjust policy->max. - * - * But, if clipped_freq is greater than policy->max, we don't - * need to do anything. - */ - clipped_freq = cpufreq_cdev->clipped_freq; - - if (policy->max > clipped_freq) - cpufreq_verify_within_limits(policy, 0, clipped_freq); - break; - } - mutex_unlock(&cooling_list_lock); - - return NOTIFY_OK; -} - /** * update_freq_table() - Update the freq table with power numbers * @cpufreq_cdev: the cpufreq cooling device in which to update the table @@ -374,7 +320,6 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; - unsigned int clip_freq; /* Request state should be less than max_level */ if (WARN_ON(state > cpufreq_cdev->max_level)) @@ -384,13 +329,10 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, if (cpufreq_cdev->cpufreq_state == state) return 0; - clip_freq = cpufreq_cdev->freq_table[state].frequency; cpufreq_cdev->cpufreq_state = state; - cpufreq_cdev->clipped_freq = clip_freq; - - cpufreq_update_policy(cpufreq_cdev->policy->cpu); - return 0; + return dev_pm_qos_update_request(&cpufreq_cdev->qos_req, + cpufreq_cdev->freq_table[state].frequency); } /** @@ -554,11 +496,6 @@ static struct thermal_cooling_device_ops cpufreq_power_cooling_ops = { .power2state = cpufreq_power2state, }; -/* Notifier for cpufreq policy change */ -static struct notifier_block thermal_cpufreq_notifier_block = { - .notifier_call = cpufreq_thermal_notifier, -}; - static unsigned int find_next_max(struct cpufreq_frequency_table *table, unsigned int prev_max) { @@ -596,9 +533,16 @@ __cpufreq_cooling_register(struct device_node *np, struct cpufreq_cooling_device *cpufreq_cdev; char dev_name[THERMAL_NAME_LENGTH]; unsigned int freq, i, num_cpus; + struct device *dev; int ret; struct thermal_cooling_device_ops *cooling_ops; - bool first; + + dev = get_cpu_device(policy->cpu); + if (unlikely(!dev)) { + pr_warn("No cpu device for cpu %d\n", policy->cpu); + return ERR_PTR(-ENODEV); + } + if (IS_ERR_OR_NULL(policy)) { pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); @@ -671,25 +615,29 @@ __cpufreq_cooling_register(struct device_node *np, cooling_ops = &cpufreq_cooling_ops; } + ret = dev_pm_qos_add_request(dev, &cpufreq_cdev->qos_req, + DEV_PM_QOS_MAX_FREQUENCY, + cpufreq_cdev->freq_table[0].frequency); + if (ret < 0) { + pr_err("%s: Failed to add freq constraint (%d)\n", __func__, + ret); + cdev = ERR_PTR(ret); + goto remove_ida; + } + cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev, cooling_ops); if (IS_ERR(cdev)) - goto remove_ida; - - cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency; + goto remove_qos_req; mutex_lock(&cooling_list_lock); - /* Register the notifier for first cpufreq cooling device */ - first = list_empty(&cpufreq_cdev_list); list_add(&cpufreq_cdev->node, &cpufreq_cdev_list); mutex_unlock(&cooling_list_lock); - if (first) - cpufreq_register_notifier(&thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); - return cdev; +remove_qos_req: + dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); remove_ida: ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); free_table: @@ -777,7 +725,6 @@ EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) { struct cpufreq_cooling_device *cpufreq_cdev; - bool last; if (!cdev) return; @@ -786,15 +733,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) mutex_lock(&cooling_list_lock); list_del(&cpufreq_cdev->node); - /* Unregister the notifier for the last cpufreq cooling device */ - last = list_empty(&cpufreq_cdev_list); mutex_unlock(&cooling_list_lock); - if (last) - cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); - thermal_cooling_device_unregister(cdev); + dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); kfree(cpufreq_cdev->idle_time); kfree(cpufreq_cdev->freq_table); -- GitLab From b7e7fffd3e8c81aa0654ed4c9f7a142b4c4dab1a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2019 12:11:08 +0200 Subject: [PATCH 2559/7155] cpuidle: teo: Get rid of redundant check in teo_update() Notice that setting measured_us to UINT_MAX in teo_update() earlier doesn't change the behavior of the following code, so do that and eliminate a redundant check used for setting measured_us to UINT_MAX. This change is not expected to alter functionality. Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/teo.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c index 4d7a60c5b24a..b5a0e498f798 100644 --- a/drivers/cpuidle/governors/teo.c +++ b/drivers/cpuidle/governors/teo.c @@ -123,10 +123,11 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) { /* - * One of the safety nets has triggered or this was a timer - * wakeup (or equivalent). + * One of the safety nets has triggered or the wakeup was close + * enough to the closest timer event expected at the idle state + * selection time to be discarded. */ - measured_us = sleep_length_us; + measured_us = UINT_MAX; } else { unsigned int lat; @@ -188,15 +189,6 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) cpu_data->states[idx_timer].hits = hits; } - /* - * If the total time span between idle state selection and the "reflect" - * callback is greater than or equal to the sleep length determined at - * the idle state selection time, the wakeup is likely to be due to a - * timer event. - */ - if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) - measured_us = UINT_MAX; - /* * Save idle duration values corresponding to non-timer wakeups for * pattern detection. -- GitLab From a62052ba2aecb9269a32efeb3e22f96b83a13304 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:16 +0200 Subject: [PATCH 2560/7155] wimax: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. This cleans up a lot of unneeded code and logic around the debugfs wimax files, making all of this much simpler and easier to understand. Cc: Inaky Perez-Gonzalez Cc: linux-wimax@intel.com Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/debugfs.c | 150 +++++------------------------ drivers/net/wimax/i2400m/driver.c | 7 +- drivers/net/wimax/i2400m/i2400m.h | 7 +- drivers/net/wimax/i2400m/usb.c | 64 +++--------- include/linux/wimax/debug.h | 20 +--- net/wimax/debugfs.c | 42 ++------ net/wimax/stack.c | 11 +-- net/wimax/wimax-internal.h | 7 +- 8 files changed, 51 insertions(+), 257 deletions(-) diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c index 6544ac9df047..73f5892ce6c1 100644 --- a/drivers/net/wimax/i2400m/debugfs.c +++ b/drivers/net/wimax/i2400m/debugfs.c @@ -30,15 +30,6 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped, debugfs_netdev_queue_stopped_get, NULL, "%llu\n"); - -static -struct dentry *debugfs_create_netdev_queue_stopped( - const char *name, struct dentry *parent, struct i2400m *i2400m) -{ - return debugfs_create_file(name, 0400, parent, i2400m, - &fops_netdev_queue_stopped); -} - /* * We don't allow partial reads of this file, as then the reader would * get weirdly confused data as it is updated. @@ -167,15 +158,6 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend, NULL, debugfs_i2400m_suspend_set, "%llu\n"); -static -struct dentry *debugfs_create_i2400m_suspend( - const char *name, struct dentry *parent, struct i2400m *i2400m) -{ - return debugfs_create_file(name, 0200, parent, i2400m, - &fops_i2400m_suspend); -} - - /* * Reset the device * @@ -205,73 +187,25 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset, NULL, debugfs_i2400m_reset_set, "%llu\n"); -static -struct dentry *debugfs_create_i2400m_reset( - const char *name, struct dentry *parent, struct i2400m *i2400m) +void i2400m_debugfs_add(struct i2400m *i2400m) { - return debugfs_create_file(name, 0200, parent, i2400m, - &fops_i2400m_reset); -} - - -#define __debugfs_register(prefix, name, parent) \ -do { \ - result = d_level_register_debugfs(prefix, name, parent); \ - if (result < 0) \ - goto error; \ -} while (0) - - -int i2400m_debugfs_add(struct i2400m *i2400m) -{ - int result; - struct device *dev = i2400m_dev(i2400m); struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry; - struct dentry *fd; dentry = debugfs_create_dir("i2400m", dentry); - result = PTR_ERR(dentry); - if (IS_ERR(dentry)) { - if (result == -ENODEV) - result = 0; /* No debugfs support */ - goto error; - } i2400m->debugfs_dentry = dentry; - __debugfs_register("dl_", control, dentry); - __debugfs_register("dl_", driver, dentry); - __debugfs_register("dl_", debugfs, dentry); - __debugfs_register("dl_", fw, dentry); - __debugfs_register("dl_", netdev, dentry); - __debugfs_register("dl_", rfkill, dentry); - __debugfs_register("dl_", rx, dentry); - __debugfs_register("dl_", tx, dentry); - - fd = debugfs_create_size_t("tx_in", 0400, dentry, - &i2400m->tx_in); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "tx_in: %d\n", result); - goto error; - } - fd = debugfs_create_size_t("tx_out", 0400, dentry, - &i2400m->tx_out); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "tx_out: %d\n", result); - goto error; - } + d_level_register_debugfs("dl_", control, dentry); + d_level_register_debugfs("dl_", driver, dentry); + d_level_register_debugfs("dl_", debugfs, dentry); + d_level_register_debugfs("dl_", fw, dentry); + d_level_register_debugfs("dl_", netdev, dentry); + d_level_register_debugfs("dl_", rfkill, dentry); + d_level_register_debugfs("dl_", rx, dentry); + d_level_register_debugfs("dl_", tx, dentry); - fd = debugfs_create_u32("state", 0600, dentry, - &i2400m->state); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "state: %d\n", result); - goto error; - } + debugfs_create_size_t("tx_in", 0400, dentry, &i2400m->tx_in); + debugfs_create_size_t("tx_out", 0400, dentry, &i2400m->tx_out); + debugfs_create_u32("state", 0600, dentry, &i2400m->state); /* * Trace received messages from user space @@ -295,60 +229,22 @@ int i2400m_debugfs_add(struct i2400m *i2400m) * It is not really very atomic, but it is also not too * critical. */ - fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry, - &i2400m->trace_msg_from_user); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "trace_msg_from_user: %d\n", result); - goto error; - } + debugfs_create_u8("trace_msg_from_user", 0600, dentry, + &i2400m->trace_msg_from_user); - fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped", - dentry, i2400m); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "netdev_queue_stopped: %d\n", result); - goto error; - } + debugfs_create_file("netdev_queue_stopped", 0400, dentry, i2400m, + &fops_netdev_queue_stopped); - fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m, - &i2400m_rx_stats_fops); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "rx_stats: %d\n", result); - goto error; - } + debugfs_create_file("rx_stats", 0600, dentry, i2400m, + &i2400m_rx_stats_fops); - fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m, - &i2400m_tx_stats_fops); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "tx_stats: %d\n", result); - goto error; - } + debugfs_create_file("tx_stats", 0600, dentry, i2400m, + &i2400m_tx_stats_fops); - fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry suspend: %d\n", - result); - goto error; - } + debugfs_create_file("suspend", 0200, dentry, i2400m, + &fops_i2400m_suspend); - fd = debugfs_create_i2400m_reset("reset", dentry, i2400m); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry reset: %d\n", result); - goto error; - } - - result = 0; -error: - return result; + debugfs_create_file("reset", 0200, dentry, i2400m, &fops_i2400m_reset); } void i2400m_debugfs_rm(struct i2400m *i2400m) diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 0a29222a1bf9..f66c0f8f6f4a 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -905,11 +905,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) goto error_sysfs_setup; } - result = i2400m_debugfs_add(i2400m); - if (result < 0) { - dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); - goto error_debugfs_setup; - } + i2400m_debugfs_add(i2400m); result = i2400m_dev_start(i2400m, bm_flags); if (result < 0) @@ -919,7 +915,6 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) error_dev_start: i2400m_debugfs_rm(i2400m); -error_debugfs_setup: sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, &i2400m_dev_attr_group); error_sysfs_setup: diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 5a34e72bab9a..a3733a6d14f5 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -812,13 +812,10 @@ enum i2400m_pt; int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); #ifdef CONFIG_DEBUG_FS -int i2400m_debugfs_add(struct i2400m *); +void i2400m_debugfs_add(struct i2400m *); void i2400m_debugfs_rm(struct i2400m *); #else -static inline int i2400m_debugfs_add(struct i2400m *i2400m) -{ - return 0; -} +static inline void i2400m_debugfs_add(struct i2400m *i2400m) {} static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} #endif diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 2075e7b1fff6..6953f904232f 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -366,61 +366,25 @@ struct d_level D_LEVEL[] = { }; size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); - -#define __debugfs_register(prefix, name, parent) \ -do { \ - result = d_level_register_debugfs(prefix, name, parent); \ - if (result < 0) \ - goto error; \ -} while (0) - - static -int i2400mu_debugfs_add(struct i2400mu *i2400mu) +void i2400mu_debugfs_add(struct i2400mu *i2400mu) { - int result; - struct device *dev = &i2400mu->usb_iface->dev; struct dentry *dentry = i2400mu->i2400m.wimax_dev.debugfs_dentry; - struct dentry *fd; dentry = debugfs_create_dir("i2400m-usb", dentry); - result = PTR_ERR(dentry); - if (IS_ERR(dentry)) { - if (result == -ENODEV) - result = 0; /* No debugfs support */ - goto error; - } i2400mu->debugfs_dentry = dentry; - __debugfs_register("dl_", usb, dentry); - __debugfs_register("dl_", fw, dentry); - __debugfs_register("dl_", notif, dentry); - __debugfs_register("dl_", rx, dentry); - __debugfs_register("dl_", tx, dentry); - /* Don't touch these if you don't know what you are doing */ - fd = debugfs_create_u8("rx_size_auto_shrink", 0600, dentry, - &i2400mu->rx_size_auto_shrink); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "rx_size_auto_shrink: %d\n", result); - goto error; - } + d_level_register_debugfs("dl_", usb, dentry); + d_level_register_debugfs("dl_", fw, dentry); + d_level_register_debugfs("dl_", notif, dentry); + d_level_register_debugfs("dl_", rx, dentry); + d_level_register_debugfs("dl_", tx, dentry); - fd = debugfs_create_size_t("rx_size", 0600, dentry, - &i2400mu->rx_size); - result = PTR_ERR(fd); - if (IS_ERR(fd) && result != -ENODEV) { - dev_err(dev, "Can't create debugfs entry " - "rx_size: %d\n", result); - goto error; - } - - return 0; + /* Don't touch these if you don't know what you are doing */ + debugfs_create_u8("rx_size_auto_shrink", 0600, dentry, + &i2400mu->rx_size_auto_shrink); -error: - debugfs_remove_recursive(i2400mu->debugfs_dentry); - return result; + debugfs_create_size_t("rx_size", 0600, dentry, &i2400mu->rx_size); } @@ -534,15 +498,9 @@ int i2400mu_probe(struct usb_interface *iface, dev_err(dev, "cannot setup device: %d\n", result); goto error_setup; } - result = i2400mu_debugfs_add(i2400mu); - if (result < 0) { - dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result); - goto error_debugfs_add; - } + i2400mu_debugfs_add(i2400mu); return 0; -error_debugfs_add: - i2400m_release(i2400m); error_setup: usb_set_intfdata(iface, NULL); usb_put_dev(i2400mu->usb_dev); diff --git a/include/linux/wimax/debug.h b/include/linux/wimax/debug.h index 7cb63e4ec0ae..4dd2c1cea6a9 100644 --- a/include/linux/wimax/debug.h +++ b/include/linux/wimax/debug.h @@ -98,9 +98,7 @@ * To manipulate from user space the levels, create a debugfs dentry * and then register each submodule with: * - * result = d_level_register_debugfs("PREFIX_", submodule_X, parent); - * if (result < 0) - * goto error; + * d_level_register_debugfs("PREFIX_", submodule_X, parent); * * Where PREFIX_ is a name of your chosing. This will create debugfs * file with a single numeric value that can be use to tweak it. To @@ -408,25 +406,13 @@ do { \ * @submodule: name of submodule (not a string, just the name) * @dentry: debugfs parent dentry * - * Returns: 0 if ok, < 0 errno on error. - * * For removing, just use debugfs_remove_recursive() on the parent. */ #define d_level_register_debugfs(prefix, name, parent) \ ({ \ - int rc; \ - struct dentry *fd; \ - struct dentry *verify_parent_type = parent; \ - fd = debugfs_create_u8( \ - prefix #name, 0600, verify_parent_type, \ + debugfs_create_u8( \ + prefix #name, 0600, parent, \ &(D_LEVEL[__D_SUBMODULE_ ## name].level)); \ - rc = PTR_ERR(fd); \ - if (IS_ERR(fd) && rc != -ENODEV) \ - printk(KERN_ERR "%s: Can't create debugfs entry %s: " \ - "%d\n", __func__, prefix #name, rc); \ - else \ - rc = 0; \ - rc; \ }) diff --git a/net/wimax/debugfs.c b/net/wimax/debugfs.c index 1af56df30276..3c54bb6b925a 100644 --- a/net/wimax/debugfs.c +++ b/net/wimax/debugfs.c @@ -13,49 +13,23 @@ #define D_SUBMODULE debugfs #include "debug-levels.h" - -#define __debugfs_register(prefix, name, parent) \ -do { \ - result = d_level_register_debugfs(prefix, name, parent); \ - if (result < 0) \ - goto error; \ -} while (0) - - -int wimax_debugfs_add(struct wimax_dev *wimax_dev) +void wimax_debugfs_add(struct wimax_dev *wimax_dev) { - int result; struct net_device *net_dev = wimax_dev->net_dev; - struct device *dev = net_dev->dev.parent; struct dentry *dentry; char buf[128]; snprintf(buf, sizeof(buf), "wimax:%s", net_dev->name); dentry = debugfs_create_dir(buf, NULL); - result = PTR_ERR(dentry); - if (IS_ERR(dentry)) { - if (result == -ENODEV) - result = 0; /* No debugfs support */ - else - dev_err(dev, "Can't create debugfs dentry: %d\n", - result); - goto out; - } wimax_dev->debugfs_dentry = dentry; - __debugfs_register("wimax_dl_", debugfs, dentry); - __debugfs_register("wimax_dl_", id_table, dentry); - __debugfs_register("wimax_dl_", op_msg, dentry); - __debugfs_register("wimax_dl_", op_reset, dentry); - __debugfs_register("wimax_dl_", op_rfkill, dentry); - __debugfs_register("wimax_dl_", op_state_get, dentry); - __debugfs_register("wimax_dl_", stack, dentry); - result = 0; -out: - return result; -error: - debugfs_remove_recursive(wimax_dev->debugfs_dentry); - return result; + d_level_register_debugfs("wimax_dl_", debugfs, dentry); + d_level_register_debugfs("wimax_dl_", id_table, dentry); + d_level_register_debugfs("wimax_dl_", op_msg, dentry); + d_level_register_debugfs("wimax_dl_", op_reset, dentry); + d_level_register_debugfs("wimax_dl_", op_rfkill, dentry); + d_level_register_debugfs("wimax_dl_", op_state_get, dentry); + d_level_register_debugfs("wimax_dl_", stack, dentry); } void wimax_debugfs_rm(struct wimax_dev *wimax_dev) diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 1ba99d65feca..4b9b1c5e8f3a 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -481,12 +481,7 @@ int wimax_dev_add(struct wimax_dev *wimax_dev, struct net_device *net_dev) /* Set up user-space interaction */ mutex_lock(&wimax_dev->mutex); wimax_id_table_add(wimax_dev); - result = wimax_debugfs_add(wimax_dev); - if (result < 0) { - dev_err(dev, "cannot initialize debugfs: %d\n", - result); - goto error_debugfs_add; - } + wimax_debugfs_add(wimax_dev); __wimax_state_set(wimax_dev, WIMAX_ST_DOWN); mutex_unlock(&wimax_dev->mutex); @@ -498,10 +493,6 @@ int wimax_dev_add(struct wimax_dev *wimax_dev, struct net_device *net_dev) d_fnend(3, dev, "(wimax_dev %p net_dev %p) = 0\n", wimax_dev, net_dev); return 0; -error_debugfs_add: - wimax_id_table_rm(wimax_dev); - mutex_unlock(&wimax_dev->mutex); - wimax_rfkill_rm(wimax_dev); error_rfkill_add: d_fnend(3, dev, "(wimax_dev %p net_dev %p) = %d\n", wimax_dev, net_dev, result); diff --git a/net/wimax/wimax-internal.h b/net/wimax/wimax-internal.h index e819a09337ee..40751207296c 100644 --- a/net/wimax/wimax-internal.h +++ b/net/wimax/wimax-internal.h @@ -57,13 +57,10 @@ void __wimax_state_set(struct wimax_dev *wimax_dev, enum wimax_st state) void __wimax_state_change(struct wimax_dev *, enum wimax_st); #ifdef CONFIG_DEBUG_FS -int wimax_debugfs_add(struct wimax_dev *); +void wimax_debugfs_add(struct wimax_dev *); void wimax_debugfs_rm(struct wimax_dev *); #else -static inline int wimax_debugfs_add(struct wimax_dev *wimax_dev) -{ - return 0; -} +static inline void wimax_debugfs_add(struct wimax_dev *wimax_dev) {} static inline void wimax_debugfs_rm(struct wimax_dev *wimax_dev) {} #endif -- GitLab From fedcc6da10f33098d76b45adefa1b4e92a261748 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:17 +0200 Subject: [PATCH 2561/7155] bonding: no need to print a message if debugfs_create_dir() fails The debugfs core now will print a message if this function fails, so don't duplicate that logic. Also, no need to change the code logic if the call fails either, as no debugfs calls should interrupt normal kernel code for any reason. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/bonding/bond_debugfs.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 1360f1ffe070..f3f86ef68ae0 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -55,11 +55,6 @@ void bond_debug_register(struct bonding *bond) bond->debug_dir = debugfs_create_dir(bond->dev->name, bonding_debug_root); - if (!bond->debug_dir) { - netdev_warn(bond->dev, "failed to register to debugfs\n"); - return; - } - debugfs_create_file("rlb_hash_table", 0400, bond->debug_dir, bond, &bond_debug_rlb_hash_fops); } -- GitLab From 9f818c8a7388ad1a5c60ace50be6f658c058a5f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:18 +0200 Subject: [PATCH 2562/7155] mlx5: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. This cleans up a lot of unneeded code and logic around the debugfs files, making all of this much simpler and easier to understand as we don't need to keep the dentries saved anymore. Cc: Saeed Mahameed Cc: Leon Romanovsky Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 51 ++------- .../net/ethernet/mellanox/mlx5/core/debugfs.c | 102 ++---------------- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 11 +- .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 2 +- .../net/ethernet/mellanox/mlx5/core/main.c | 7 +- .../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +- include/linux/mlx5/driver.h | 12 +-- 7 files changed, 24 insertions(+), 163 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 8cdd7e66f8df..973f90888b1f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1368,49 +1368,19 @@ static void clean_debug_files(struct mlx5_core_dev *dev) debugfs_remove_recursive(dbg->dbg_root); } -static int create_debugfs_files(struct mlx5_core_dev *dev) +static void create_debugfs_files(struct mlx5_core_dev *dev) { struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; - int err = -ENOMEM; - - if (!mlx5_debugfs_root) - return 0; dbg->dbg_root = debugfs_create_dir("cmd", dev->priv.dbg_root); - if (!dbg->dbg_root) - return err; - - dbg->dbg_in = debugfs_create_file("in", 0400, dbg->dbg_root, - dev, &dfops); - if (!dbg->dbg_in) - goto err_dbg; - dbg->dbg_out = debugfs_create_file("out", 0200, dbg->dbg_root, - dev, &dfops); - if (!dbg->dbg_out) - goto err_dbg; - - dbg->dbg_outlen = debugfs_create_file("out_len", 0600, dbg->dbg_root, - dev, &olfops); - if (!dbg->dbg_outlen) - goto err_dbg; - - dbg->dbg_status = debugfs_create_u8("status", 0600, dbg->dbg_root, - &dbg->status); - if (!dbg->dbg_status) - goto err_dbg; - - dbg->dbg_run = debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops); - if (!dbg->dbg_run) - goto err_dbg; + debugfs_create_file("in", 0400, dbg->dbg_root, dev, &dfops); + debugfs_create_file("out", 0200, dbg->dbg_root, dev, &dfops); + debugfs_create_file("out_len", 0600, dbg->dbg_root, dev, &olfops); + debugfs_create_u8("status", 0600, dbg->dbg_root, &dbg->status); + debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops); mlx5_cmdif_debugfs_init(dev); - - return 0; - -err_dbg: - clean_debug_files(dev); - return err; } static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) @@ -2007,17 +1977,10 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) goto err_cache; } - err = create_debugfs_files(dev); - if (err) { - err = -ENOMEM; - goto err_wq; - } + create_debugfs_files(dev); return 0; -err_wq: - destroy_workqueue(cmd->wq); - err_cache: destroy_msg_cache(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index a11e22d0b0cc..04854e5fbcd7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -92,8 +92,6 @@ EXPORT_SYMBOL(mlx5_debugfs_root); void mlx5_register_debugfs(void) { mlx5_debugfs_root = debugfs_create_dir("mlx5", NULL); - if (IS_ERR_OR_NULL(mlx5_debugfs_root)) - mlx5_debugfs_root = NULL; } void mlx5_unregister_debugfs(void) @@ -101,45 +99,25 @@ void mlx5_unregister_debugfs(void) debugfs_remove(mlx5_debugfs_root); } -int mlx5_qp_debugfs_init(struct mlx5_core_dev *dev) +void mlx5_qp_debugfs_init(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return 0; - atomic_set(&dev->num_qps, 0); dev->priv.qp_debugfs = debugfs_create_dir("QPs", dev->priv.dbg_root); - if (!dev->priv.qp_debugfs) - return -ENOMEM; - - return 0; } void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return; - debugfs_remove_recursive(dev->priv.qp_debugfs); } -int mlx5_eq_debugfs_init(struct mlx5_core_dev *dev) +void mlx5_eq_debugfs_init(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return 0; - dev->priv.eq_debugfs = debugfs_create_dir("EQs", dev->priv.dbg_root); - if (!dev->priv.eq_debugfs) - return -ENOMEM; - - return 0; } void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return; - debugfs_remove_recursive(dev->priv.eq_debugfs); } @@ -183,85 +161,41 @@ static const struct file_operations stats_fops = { .write = average_write, }; -int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) +void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) { struct mlx5_cmd_stats *stats; struct dentry **cmd; const char *namep; - int err; int i; - if (!mlx5_debugfs_root) - return 0; - cmd = &dev->priv.cmdif_debugfs; *cmd = debugfs_create_dir("commands", dev->priv.dbg_root); - if (!*cmd) - return -ENOMEM; for (i = 0; i < ARRAY_SIZE(dev->cmd.stats); i++) { stats = &dev->cmd.stats[i]; namep = mlx5_command_str(i); if (strcmp(namep, "unknown command opcode")) { stats->root = debugfs_create_dir(namep, *cmd); - if (!stats->root) { - mlx5_core_warn(dev, "failed adding command %d\n", - i); - err = -ENOMEM; - goto out; - } - - stats->avg = debugfs_create_file("average", 0400, - stats->root, stats, - &stats_fops); - if (!stats->avg) { - mlx5_core_warn(dev, "failed creating debugfs file\n"); - err = -ENOMEM; - goto out; - } - - stats->count = debugfs_create_u64("n", 0400, - stats->root, - &stats->n); - if (!stats->count) { - mlx5_core_warn(dev, "failed creating debugfs file\n"); - err = -ENOMEM; - goto out; - } + + debugfs_create_file("average", 0400, stats->root, stats, + &stats_fops); + debugfs_create_u64("n", 0400, stats->root, &stats->n); } } - - return 0; -out: - debugfs_remove_recursive(dev->priv.cmdif_debugfs); - return err; } void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return; - debugfs_remove_recursive(dev->priv.cmdif_debugfs); } -int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev) +void mlx5_cq_debugfs_init(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return 0; - dev->priv.cq_debugfs = debugfs_create_dir("CQs", dev->priv.dbg_root); - if (!dev->priv.cq_debugfs) - return -ENOMEM; - - return 0; } void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev) { - if (!mlx5_debugfs_root) - return; - debugfs_remove_recursive(dev->priv.cq_debugfs); } @@ -484,7 +418,6 @@ static int add_res_tree(struct mlx5_core_dev *dev, enum dbg_rsc_type type, { struct mlx5_rsc_debug *d; char resn[32]; - int err; int i; d = kzalloc(struct_size(d, fields, nfile), GFP_KERNEL); @@ -496,30 +429,15 @@ static int add_res_tree(struct mlx5_core_dev *dev, enum dbg_rsc_type type, d->type = type; sprintf(resn, "0x%x", rsn); d->root = debugfs_create_dir(resn, root); - if (!d->root) { - err = -ENOMEM; - goto out_free; - } for (i = 0; i < nfile; i++) { d->fields[i].i = i; - d->fields[i].dent = debugfs_create_file(field[i], 0400, - d->root, &d->fields[i], - &fops); - if (!d->fields[i].dent) { - err = -ENOMEM; - goto out_rem; - } + debugfs_create_file(field[i], 0400, d->root, &d->fields[i], + &fops); } *dbg = d; return 0; -out_rem: - debugfs_remove_recursive(d->root); - -out_free: - kfree(d); - return err; } static void rem_res_tree(struct mlx5_rsc_debug *d) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 2df9aaa421c6..09d4c64b6e73 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -411,7 +411,7 @@ void mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq) int mlx5_eq_table_init(struct mlx5_core_dev *dev) { struct mlx5_eq_table *eq_table; - int i, err; + int i; eq_table = kvzalloc(sizeof(*eq_table), GFP_KERNEL); if (!eq_table) @@ -419,9 +419,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) dev->priv.eq_table = eq_table; - err = mlx5_eq_debugfs_init(dev); - if (err) - goto kvfree_eq_table; + mlx5_eq_debugfs_init(dev); mutex_init(&eq_table->lock); for (i = 0; i < MLX5_EVENT_TYPE_MAX; i++) @@ -429,11 +427,6 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) eq_table->irq_table = dev->priv.irq_table; return 0; - -kvfree_eq_table: - kvfree(eq_table); - dev->priv.eq_table = NULL; - return err; } void mlx5_eq_table_cleanup(struct mlx5_core_dev *dev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h index 3dfab91ae5f2..4be4d2d36218 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h @@ -87,7 +87,7 @@ void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev); int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq); void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq); -int mlx5_eq_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_eq_debugfs_init(struct mlx5_core_dev *dev); void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev); /* This function should only be called after mlx5_cmd_force_teardown_hca */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index fa0e991f1983..0b70b1d6338d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -826,11 +826,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) goto err_eq_cleanup; } - err = mlx5_cq_debugfs_init(dev); - if (err) { - mlx5_core_err(dev, "failed to initialize cq debugfs\n"); - goto err_events_cleanup; - } + mlx5_cq_debugfs_init(dev); mlx5_init_qp_table(dev); @@ -891,7 +887,6 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) mlx5_cleanup_mkey_table(dev); mlx5_cleanup_qp_table(dev); mlx5_cq_debugfs_cleanup(dev); -err_events_cleanup: mlx5_events_cleanup(dev); err_eq_cleanup: mlx5_eq_table_cleanup(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 471bbc48bc1f..87b75b2207c4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -146,7 +146,7 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev, void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev); void mlx5_cmd_flush(struct mlx5_core_dev *dev); -int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_cq_debugfs_init(struct mlx5_core_dev *dev); void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group, diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index d8f348ef9c33..df23f17eed64 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -189,7 +189,6 @@ enum mlx5_coredev_type { }; struct mlx5_field_desc { - struct dentry *dent; int i; }; @@ -242,11 +241,6 @@ struct mlx5_cmd_msg { struct mlx5_cmd_debug { struct dentry *dbg_root; - struct dentry *dbg_in; - struct dentry *dbg_out; - struct dentry *dbg_outlen; - struct dentry *dbg_status; - struct dentry *dbg_run; void *in_msg; void *out_msg; u8 status; @@ -271,8 +265,6 @@ struct mlx5_cmd_stats { u64 sum; u64 n; struct dentry *root; - struct dentry *avg; - struct dentry *count; /* protect command average calculations */ spinlock_t lock; }; @@ -972,7 +964,7 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); -int mlx5_qp_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_qp_debugfs_init(struct mlx5_core_dev *dev); void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, int size_in, void *data_out, int size_out, @@ -984,7 +976,7 @@ int mlx5_db_alloc_node(struct mlx5_core_dev *dev, struct mlx5_db *db, void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); const char *mlx5_command_str(int command); -int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn, int npsvs, u32 *sig_index); -- GitLab From 9e3926df8779a69f8541c9983c6d19b097671abd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:19 +0200 Subject: [PATCH 2563/7155] xgbe: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. This cleans up a lot of unneeded code and logic around the debugfs files, making all of this much simpler and easier to understand. Cc: Tom Lendacky Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 107 ++++++------------- 1 file changed, 31 insertions(+), 76 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c index b91143947ed2..b0a6c96b6ef4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c @@ -438,7 +438,6 @@ static const struct file_operations xi2c_reg_value_fops = { void xgbe_debugfs_init(struct xgbe_prv_data *pdata) { - struct dentry *pfile; char *buf; /* Set defaults */ @@ -451,88 +450,48 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) return; pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); - if (!pdata->xgbe_debugfs) { - netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); - kfree(buf); - return; - } - pfile = debugfs_create_file("xgmac_register", 0600, - pdata->xgbe_debugfs, pdata, - &xgmac_reg_addr_fops); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_create_file failed\n"); + debugfs_create_file("xgmac_register", 0600, pdata->xgbe_debugfs, pdata, + &xgmac_reg_addr_fops); - pfile = debugfs_create_file("xgmac_register_value", 0600, - pdata->xgbe_debugfs, pdata, - &xgmac_reg_value_fops); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_create_file failed\n"); + debugfs_create_file("xgmac_register_value", 0600, pdata->xgbe_debugfs, + pdata, &xgmac_reg_value_fops); - pfile = debugfs_create_file("xpcs_mmd", 0600, - pdata->xgbe_debugfs, pdata, - &xpcs_mmd_fops); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_create_file failed\n"); + debugfs_create_file("xpcs_mmd", 0600, pdata->xgbe_debugfs, pdata, + &xpcs_mmd_fops); - pfile = debugfs_create_file("xpcs_register", 0600, - pdata->xgbe_debugfs, pdata, - &xpcs_reg_addr_fops); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_create_file failed\n"); + debugfs_create_file("xpcs_register", 0600, pdata->xgbe_debugfs, pdata, + &xpcs_reg_addr_fops); - pfile = debugfs_create_file("xpcs_register_value", 0600, - pdata->xgbe_debugfs, pdata, - &xpcs_reg_value_fops); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_create_file failed\n"); + debugfs_create_file("xpcs_register_value", 0600, pdata->xgbe_debugfs, + pdata, &xpcs_reg_value_fops); if (pdata->xprop_regs) { - pfile = debugfs_create_file("xprop_register", 0600, - pdata->xgbe_debugfs, pdata, - &xprop_reg_addr_fops); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_file failed\n"); - - pfile = debugfs_create_file("xprop_register_value", 0600, - pdata->xgbe_debugfs, pdata, - &xprop_reg_value_fops); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_file failed\n"); + debugfs_create_file("xprop_register", 0600, pdata->xgbe_debugfs, + pdata, &xprop_reg_addr_fops); + + debugfs_create_file("xprop_register_value", 0600, + pdata->xgbe_debugfs, pdata, + &xprop_reg_value_fops); } if (pdata->xi2c_regs) { - pfile = debugfs_create_file("xi2c_register", 0600, - pdata->xgbe_debugfs, pdata, - &xi2c_reg_addr_fops); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_file failed\n"); - - pfile = debugfs_create_file("xi2c_register_value", 0600, - pdata->xgbe_debugfs, pdata, - &xi2c_reg_value_fops); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_file failed\n"); + debugfs_create_file("xi2c_register", 0600, pdata->xgbe_debugfs, + pdata, &xi2c_reg_addr_fops); + + debugfs_create_file("xi2c_register_value", 0600, + pdata->xgbe_debugfs, pdata, + &xi2c_reg_value_fops); } if (pdata->vdata->an_cdr_workaround) { - pfile = debugfs_create_bool("an_cdr_workaround", 0600, - pdata->xgbe_debugfs, - &pdata->debugfs_an_cdr_workaround); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_bool failed\n"); - - pfile = debugfs_create_bool("an_cdr_track_early", 0600, - pdata->xgbe_debugfs, - &pdata->debugfs_an_cdr_track_early); - if (!pfile) - netdev_err(pdata->netdev, - "debugfs_create_bool failed\n"); + debugfs_create_bool("an_cdr_workaround", 0600, + pdata->xgbe_debugfs, + &pdata->debugfs_an_cdr_workaround); + + debugfs_create_bool("an_cdr_track_early", 0600, + pdata->xgbe_debugfs, + &pdata->debugfs_an_cdr_track_early); } kfree(buf); @@ -546,7 +505,6 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) { - struct dentry *pfile; char *buf; if (!pdata->xgbe_debugfs) @@ -559,11 +517,8 @@ void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf)) goto out; - pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent, - pdata->xgbe_debugfs, - pdata->xgbe_debugfs->d_parent, buf); - if (!pfile) - netdev_err(pdata->netdev, "debugfs_rename failed\n"); + debugfs_rename(pdata->xgbe_debugfs->d_parent, pdata->xgbe_debugfs, + pdata->xgbe_debugfs->d_parent, buf); out: kfree(buf); -- GitLab From 3a131e85043cf538d5e70c0f23f9d69a4dd642b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:20 +0200 Subject: [PATCH 2564/7155] bnxt: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. This cleans up a lot of unneeded code and logic around the debugfs files, making all of this much simpler and easier to understand. Cc: Michael Chan Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 - .../net/ethernet/broadcom/bnxt/bnxt_debugfs.c | 39 ++++++------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index e3262089b751..1b1610d5b573 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1724,7 +1724,6 @@ struct bnxt { u8 switch_id[8]; struct bnxt_tc_info *tc_info; struct dentry *debugfs_pdev; - struct dentry *debugfs_dim; struct device *hwmon_dev; }; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_debugfs.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_debugfs.c index 61393f351a77..156c2404854f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_debugfs.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_debugfs.c @@ -61,45 +61,30 @@ static const struct file_operations debugfs_dim_fops = { .read = debugfs_dim_read, }; -static struct dentry *debugfs_dim_ring_init(struct dim *dim, int ring_idx, - struct dentry *dd) +static void debugfs_dim_ring_init(struct dim *dim, int ring_idx, + struct dentry *dd) { static char qname[16]; snprintf(qname, 10, "%d", ring_idx); - return debugfs_create_file(qname, 0600, dd, - dim, &debugfs_dim_fops); + debugfs_create_file(qname, 0600, dd, dim, &debugfs_dim_fops); } void bnxt_debug_dev_init(struct bnxt *bp) { const char *pname = pci_name(bp->pdev); - struct dentry *pdevf; + struct dentry *dir; int i; bp->debugfs_pdev = debugfs_create_dir(pname, bnxt_debug_mnt); - if (bp->debugfs_pdev) { - pdevf = debugfs_create_dir("dim", bp->debugfs_pdev); - if (!pdevf) { - pr_err("failed to create debugfs entry %s/dim\n", - pname); - return; - } - bp->debugfs_dim = pdevf; - /* create files for each rx ring */ - for (i = 0; i < bp->cp_nr_rings; i++) { - struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring; + dir = debugfs_create_dir("dim", bp->debugfs_pdev); - if (cpr && bp->bnapi[i]->rx_ring) { - pdevf = debugfs_dim_ring_init(&cpr->dim, i, - bp->debugfs_dim); - if (!pdevf) - pr_err("failed to create debugfs entry %s/dim/%d\n", - pname, i); - } - } - } else { - pr_err("failed to create debugfs entry %s\n", pname); + /* create files for each rx ring */ + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring; + + if (cpr && bp->bnapi[i]->rx_ring) + debugfs_dim_ring_init(&cpr->dim, i, dir); } } @@ -114,8 +99,6 @@ void bnxt_debug_dev_exit(struct bnxt *bp) void bnxt_debug_init(void) { bnxt_debug_mnt = debugfs_create_dir("bnxt_en", NULL); - if (!bnxt_debug_mnt) - pr_err("failed to init bnxt_en debugfs\n"); } void bnxt_debug_exit(void) -- GitLab From 9dac1e8eeaa2fafa0ce2931a3abf5644c5ab61eb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:21 +0200 Subject: [PATCH 2565/7155] cxgb4: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. If a debugfs call fails, it will properly warn in the syslog, there's no need for all individual drivers to also print a message, so that is one more reason to not care about checking the return values. Cc: Vishal Kulkarni Cc: "David S. Miller" Cc: Casey Leedom Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 5 ++--- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 --- .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 21 +++++++------------ 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 02959035ed3f..dd99c55d9a88 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -3529,7 +3529,6 @@ int t4_setup_debugfs(struct adapter *adap) { int i; u32 size = 0; - struct dentry *de; static struct t4_debugfs_entry t4_debugfs_files[] = { { "cim_la", &cim_la_fops, 0400, 0 }, @@ -3640,8 +3639,8 @@ int t4_setup_debugfs(struct adapter *adap) } } - de = debugfs_create_file_size("flash", 0400, adap->debugfs_root, adap, - &flash_debugfs_fops, adap->params.sf_size); + debugfs_create_file_size("flash", 0400, adap->debugfs_root, adap, + &flash_debugfs_fops, adap->params.sf_size); debugfs_create_bool("use_backdoor", 0600, adap->debugfs_root, &adap->use_bd); debugfs_create_bool("trace_rss", 0600, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 4311ad9c84b2..71854a19cebe 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -6269,10 +6269,7 @@ static int __init cxgb4_init_module(void) { int ret; - /* Debugfs support is optional, just warn if this fails */ cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!cxgb4_debugfs_root) - pr_warn("could not create debugfs entry, continuing\n"); ret = pci_register_driver(&cxgb4_driver); if (ret < 0) diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 6d4cf3d0b2f0..f6fc0875d5b0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2478,11 +2478,10 @@ static int setup_debugfs(struct adapter *adapter) * Debugfs support is best effort. */ for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) - (void)debugfs_create_file(debugfs_files[i].name, - debugfs_files[i].mode, - adapter->debugfs_root, - (void *)adapter, - debugfs_files[i].fops); + debugfs_create_file(debugfs_files[i].name, + debugfs_files[i].mode, + adapter->debugfs_root, (void *)adapter, + debugfs_files[i].fops); return 0; } @@ -3257,11 +3256,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, adapter->debugfs_root = debugfs_create_dir(pci_name(pdev), cxgb4vf_debugfs_root); - if (IS_ERR_OR_NULL(adapter->debugfs_root)) - dev_warn(&pdev->dev, "could not create debugfs" - " directory"); - else - setup_debugfs(adapter); + setup_debugfs(adapter); } /* @@ -3486,13 +3481,11 @@ static int __init cxgb4vf_module_init(void) return -EINVAL; } - /* Debugfs support is optional, just warn if this fails */ + /* Debugfs support is optional, debugfs will warn if this fails */ cxgb4vf_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR_OR_NULL(cxgb4vf_debugfs_root)) - pr_warn("could not create debugfs entry, continuing\n"); ret = pci_register_driver(&cxgb4vf_driver); - if (ret < 0 && !IS_ERR_OR_NULL(cxgb4vf_debugfs_root)) + if (ret < 0) debugfs_remove(cxgb4vf_debugfs_root); return ret; } -- GitLab From 11ab11e69d63f4f7af92e9466f19255eff877945 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:22 +0200 Subject: [PATCH 2566/7155] hns3: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Yisen Zhuang Cc: Salil Mehta Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3_debugfs.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 7996dcc21cf6..7070d25ddb5b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -376,20 +376,11 @@ static const struct file_operations hns3_dbg_cmd_fops = { void hns3_dbg_init(struct hnae3_handle *handle) { const char *name = pci_name(handle->pdev); - struct dentry *pfile; handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root); - if (!handle->hnae3_dbgfs) - return; - pfile = debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, - &hns3_dbg_cmd_fops); - if (!pfile) { - debugfs_remove_recursive(handle->hnae3_dbgfs); - handle->hnae3_dbgfs = NULL; - dev_warn(&handle->pdev->dev, "create file for %s fail\n", - name); - } + debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, + &hns3_dbg_cmd_fops); } void hns3_dbg_uninit(struct hnae3_handle *handle) @@ -401,10 +392,6 @@ void hns3_dbg_uninit(struct hnae3_handle *handle) void hns3_dbg_register_debugfs(const char *debugfs_dir_name) { hns3_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); - if (!hns3_dbgfs_root) { - pr_warn("Register debugfs for %s fail\n", debugfs_dir_name); - return; - } } void hns3_dbg_unregister_debugfs(void) -- GitLab From 16e9b481e988b1f7e6df2243bb510e1c9b581272 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:23 +0200 Subject: [PATCH 2567/7155] nfp: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: "David S. Miller" Cc: Alexei Starovoitov Cc: Daniel Borkmann Cc: Jesper Dangaard Brouer Cc: John Fastabend Cc: Edwin Peer Cc: Yangtao Li Cc: Simon Horman Cc: oss-drivers@netronome.com Cc: netdev@vger.kernel.org Acked-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_debugfs.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index ab7f2498e1c4..553c708694e8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -159,19 +159,13 @@ void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir) else strcpy(name, "ctrl-vnic"); nn->debugfs_dir = debugfs_create_dir(name, ddir); - if (IS_ERR_OR_NULL(nn->debugfs_dir)) - return; /* Create queue debugging sub-tree */ queues = debugfs_create_dir("queue", nn->debugfs_dir); - if (IS_ERR_OR_NULL(queues)) - return; rx = debugfs_create_dir("rx", queues); tx = debugfs_create_dir("tx", queues); xdp = debugfs_create_dir("xdp", queues); - if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx) || IS_ERR_OR_NULL(xdp)) - return; for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) { sprintf(name, "%d", i); @@ -190,16 +184,7 @@ void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir) struct dentry *nfp_net_debugfs_device_add(struct pci_dev *pdev) { - struct dentry *dev_dir; - - if (IS_ERR_OR_NULL(nfp_dir)) - return NULL; - - dev_dir = debugfs_create_dir(pci_name(pdev), nfp_dir); - if (IS_ERR_OR_NULL(dev_dir)) - return NULL; - - return dev_dir; + return debugfs_create_dir(pci_name(pdev), nfp_dir); } void nfp_net_debugfs_dir_clean(struct dentry **dir) -- GitLab From 8d72ab119f42f25abb393093472ae0ca275088b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:24 +0200 Subject: [PATCH 2568/7155] stmmac: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Because we don't care about the individual files, we can remove the stored dentry for the files, as they are not needed to be kept track of at all. Cc: Giuseppe Cavallaro Cc: Alexandre Torgue Cc: Jose Abreu Cc: "David S. Miller" Cc: Maxime Coquelin Cc: netdev@vger.kernel.org Cc: linux-stm32@st-md-mailman.stormreply.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 52 +++---------------- 2 files changed, 8 insertions(+), 46 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 4179559b11ad..80276587048a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -196,8 +196,6 @@ struct stmmac_priv { #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; - struct dentry *dbgfs_rings_status; - struct dentry *dbgfs_dma_cap; #endif unsigned long state; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2274bb58eefa..06a63df1c2c5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -105,7 +105,7 @@ MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode"); static irqreturn_t stmmac_interrupt(int irq, void *dev_id); #ifdef CONFIG_DEBUG_FS -static int stmmac_init_fs(struct net_device *dev); +static void stmmac_init_fs(struct net_device *dev); static void stmmac_exit_fs(struct net_device *dev); #endif @@ -3988,45 +3988,20 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(stmmac_dma_cap); -static int stmmac_init_fs(struct net_device *dev) +static void stmmac_init_fs(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); /* Create per netdev entries */ priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); - if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { - netdev_err(priv->dev, "ERROR failed to create debugfs directory\n"); - - return -ENOMEM; - } - /* Entry to report DMA RX/TX rings */ - priv->dbgfs_rings_status = - debugfs_create_file("descriptors_status", 0444, - priv->dbgfs_dir, dev, - &stmmac_rings_status_fops); - - if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { - netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n"); - debugfs_remove_recursive(priv->dbgfs_dir); - - return -ENOMEM; - } + debugfs_create_file("descriptors_status", 0444, priv->dbgfs_dir, dev, + &stmmac_rings_status_fops); /* Entry to report the DMA HW features */ - priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", 0444, - priv->dbgfs_dir, - dev, &stmmac_dma_cap_fops); - - if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { - netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n"); - debugfs_remove_recursive(priv->dbgfs_dir); - - return -ENOMEM; - } - - return 0; + debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev, + &stmmac_dma_cap_fops); } static void stmmac_exit_fs(struct net_device *dev) @@ -4482,10 +4457,7 @@ int stmmac_dvr_probe(struct device *device, } #ifdef CONFIG_DEBUG_FS - ret = stmmac_init_fs(ndev); - if (ret < 0) - netdev_warn(priv->dev, "%s: failed debugFS registration\n", - __func__); + stmmac_init_fs(ndev); #endif return ret; @@ -4731,16 +4703,8 @@ static int __init stmmac_init(void) { #ifdef CONFIG_DEBUG_FS /* Create debugfs main directory if it doesn't exist yet */ - if (!stmmac_fs_dir) { + if (!stmmac_fs_dir) stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); - - if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { - pr_err("ERROR %s, debugfs create directory failed\n", - STMMAC_RESOURCE_NAME); - - return -ENOMEM; - } - } #endif return 0; -- GitLab From 92aff5b4678745660259035a5467bc8870003900 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:25 +0200 Subject: [PATCH 2569/7155] dpaa2: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Because we don't care about the individual files, we can remove the stored dentry for the files, as they are not needed to be kept track of at all. Cc: Ioana Radulescu Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../freescale/dpaa2/dpaa2-eth-debugfs.c | 54 +++---------------- .../freescale/dpaa2/dpaa2-eth-debugfs.h | 3 -- 2 files changed, 7 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c index a027f4a9d0cc..a9afe46b837f 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c @@ -164,70 +164,30 @@ static const struct file_operations dpaa2_dbg_ch_ops = { void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) { - if (!dpaa2_dbg_root) - return; + struct dentry *dir; /* Create a directory for the interface */ - priv->dbg.dir = debugfs_create_dir(priv->net_dev->name, - dpaa2_dbg_root); - if (!priv->dbg.dir) { - netdev_err(priv->net_dev, "debugfs_create_dir() failed\n"); - return; - } + dir = debugfs_create_dir(priv->net_dev->name, dpaa2_dbg_root); + priv->dbg.dir = dir; /* per-cpu stats file */ - priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", 0444, - priv->dbg.dir, priv, - &dpaa2_dbg_cpu_ops); - if (!priv->dbg.cpu_stats) { - netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); - goto err_cpu_stats; - } + debugfs_create_file("cpu_stats", 0444, dir, priv, &dpaa2_dbg_cpu_ops); /* per-fq stats file */ - priv->dbg.fq_stats = debugfs_create_file("fq_stats", 0444, - priv->dbg.dir, priv, - &dpaa2_dbg_fq_ops); - if (!priv->dbg.fq_stats) { - netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); - goto err_fq_stats; - } + debugfs_create_file("fq_stats", 0444, dir, priv, &dpaa2_dbg_fq_ops); /* per-fq stats file */ - priv->dbg.ch_stats = debugfs_create_file("ch_stats", 0444, - priv->dbg.dir, priv, - &dpaa2_dbg_ch_ops); - if (!priv->dbg.fq_stats) { - netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); - goto err_ch_stats; - } - - return; - -err_ch_stats: - debugfs_remove(priv->dbg.fq_stats); -err_fq_stats: - debugfs_remove(priv->dbg.cpu_stats); -err_cpu_stats: - debugfs_remove(priv->dbg.dir); + debugfs_create_file("ch_stats", 0444, dir, priv, &dpaa2_dbg_ch_ops); } void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) { - debugfs_remove(priv->dbg.fq_stats); - debugfs_remove(priv->dbg.ch_stats); - debugfs_remove(priv->dbg.cpu_stats); - debugfs_remove(priv->dbg.dir); + debugfs_remove_recursive(priv->dbg.dir); } void dpaa2_eth_dbg_init(void) { dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL); - if (!dpaa2_dbg_root) { - pr_err("DPAA2-ETH: debugfs create failed\n"); - return; - } - pr_debug("DPAA2-ETH: debugfs created\n"); } diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h index 4f63de997a26..15598b28f03b 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h @@ -11,9 +11,6 @@ struct dpaa2_eth_priv; struct dpaa2_debugfs { struct dentry *dir; - struct dentry *fq_stats; - struct dentry *ch_stats; - struct dentry *cpu_stats; }; #ifdef CONFIG_DEBUG_FS -- GitLab From 687236b07a672ad10a0432270c7b19217580a0b1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:26 +0200 Subject: [PATCH 2570/7155] qca: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: "David S. Miller" Cc: Stefan Wahren Cc: Michael Heimpold Cc: Yangtao Li Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/qca_debug.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c index bcb890b18a94..702aa217a27a 100644 --- a/drivers/net/ethernet/qualcomm/qca_debug.c +++ b/drivers/net/ethernet/qualcomm/qca_debug.c @@ -131,17 +131,10 @@ DEFINE_SHOW_ATTRIBUTE(qcaspi_info); void qcaspi_init_device_debugfs(struct qcaspi *qca) { - struct dentry *device_root; + qca->device_root = debugfs_create_dir(dev_name(&qca->net_dev->dev), + NULL); - device_root = debugfs_create_dir(dev_name(&qca->net_dev->dev), NULL); - qca->device_root = device_root; - - if (IS_ERR(device_root) || !device_root) { - pr_warn("failed to create debugfs directory for %s\n", - dev_name(&qca->net_dev->dev)); - return; - } - debugfs_create_file("info", S_IFREG | 0444, device_root, qca, + debugfs_create_file("info", S_IFREG | 0444, qca->device_root, qca, &qcaspi_info_fops); } -- GitLab From 2f62f8e6c379c32cc1d629043b67feb06cda7661 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:27 +0200 Subject: [PATCH 2571/7155] skge: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Mirko Lindner Cc: Stephen Hemminger Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/skge.c | 39 +++++++---------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 06dffee81e02..0a2ec387a482 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3731,7 +3731,6 @@ static int skge_device_event(struct notifier_block *unused, { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct skge_port *skge; - struct dentry *d; if (dev->netdev_ops->ndo_open != &skge_up || !skge_debug) goto done; @@ -3739,33 +3738,20 @@ static int skge_device_event(struct notifier_block *unused, skge = netdev_priv(dev); switch (event) { case NETDEV_CHANGENAME: - if (skge->debugfs) { - d = debugfs_rename(skge_debug, skge->debugfs, - skge_debug, dev->name); - if (d) - skge->debugfs = d; - else { - netdev_info(dev, "rename failed\n"); - debugfs_remove(skge->debugfs); - } - } + if (skge->debugfs) + skge->debugfs = debugfs_rename(skge_debug, + skge->debugfs, + skge_debug, dev->name); break; case NETDEV_GOING_DOWN: - if (skge->debugfs) { - debugfs_remove(skge->debugfs); - skge->debugfs = NULL; - } + debugfs_remove(skge->debugfs); + skge->debugfs = NULL; break; case NETDEV_UP: - d = debugfs_create_file(dev->name, 0444, - skge_debug, dev, - &skge_debug_fops); - if (!d || IS_ERR(d)) - netdev_info(dev, "debugfs create failed\n"); - else - skge->debugfs = d; + skge->debugfs = debugfs_create_file(dev->name, 0444, skge_debug, + dev, &skge_debug_fops); break; } @@ -3780,15 +3766,8 @@ static struct notifier_block skge_notifier = { static __init void skge_debug_init(void) { - struct dentry *ent; - - ent = debugfs_create_dir("skge", NULL); - if (!ent || IS_ERR(ent)) { - pr_info("debugfs create directory failed\n"); - return; - } + skge_debug = debugfs_create_dir("skge", NULL); - skge_debug = ent; register_netdevice_notifier(&skge_notifier); } -- GitLab From e6882aa623f6fe0d80fa82ebf3ee78c353bffbe1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:28 +0200 Subject: [PATCH 2572/7155] mvpp2: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: "David S. Miller" Cc: Maxime Chevallier Cc: Nick Desaulniers Cc: Nathan Huckleberry Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../ethernet/marvell/mvpp2/mvpp2_debugfs.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c index 274fb07362cb..4a3baa7e0142 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c @@ -452,8 +452,6 @@ static int mvpp2_dbgfs_flow_port_init(struct dentry *parent, struct dentry *port_dir; port_dir = debugfs_create_dir(port->dev->name, parent); - if (IS_ERR(port_dir)) - return PTR_ERR(port_dir); port_entry = &port->priv->dbgfs_entries->port_flow_entries[port->id]; @@ -480,8 +478,6 @@ static int mvpp2_dbgfs_flow_entry_init(struct dentry *parent, sprintf(flow_entry_name, "%02d", flow); flow_entry_dir = debugfs_create_dir(flow_entry_name, parent); - if (!flow_entry_dir) - return -ENOMEM; entry = &priv->dbgfs_entries->flow_entries[flow]; @@ -514,8 +510,6 @@ static int mvpp2_dbgfs_flow_init(struct dentry *parent, struct mvpp2 *priv) int i, ret; flow_dir = debugfs_create_dir("flows", parent); - if (!flow_dir) - return -ENOMEM; for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) { ret = mvpp2_dbgfs_flow_entry_init(flow_dir, priv, i); @@ -539,8 +533,6 @@ static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent, sprintf(prs_entry_name, "%03d", tid); prs_entry_dir = debugfs_create_dir(prs_entry_name, parent); - if (!prs_entry_dir) - return -ENOMEM; entry = &priv->dbgfs_entries->prs_entries[tid]; @@ -578,8 +570,6 @@ static int mvpp2_dbgfs_prs_init(struct dentry *parent, struct mvpp2 *priv) int i, ret; prs_dir = debugfs_create_dir("parser", parent); - if (!prs_dir) - return -ENOMEM; for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) { ret = mvpp2_dbgfs_prs_entry_init(prs_dir, priv, i); @@ -688,8 +678,6 @@ static int mvpp2_dbgfs_port_init(struct dentry *parent, struct dentry *port_dir; port_dir = debugfs_create_dir(port->dev->name, parent); - if (IS_ERR(port_dir)) - return PTR_ERR(port_dir); debugfs_create_file("parser_entries", 0444, port_dir, port, &mvpp2_dbgfs_port_parser_fops); @@ -716,15 +704,10 @@ void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name) int ret, i; mvpp2_root = debugfs_lookup(MVPP2_DRIVER_NAME, NULL); - if (!mvpp2_root) { + if (!mvpp2_root) mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL); - if (IS_ERR(mvpp2_root)) - return; - } mvpp2_dir = debugfs_create_dir(name, mvpp2_root); - if (IS_ERR(mvpp2_dir)) - return; priv->dbgfs_dir = mvpp2_dir; priv->dbgfs_entries = kzalloc(sizeof(*priv->dbgfs_entries), GFP_KERNEL); -- GitLab From ecc557075166e751305e7448d9436d35dbce2e54 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:29 +0200 Subject: [PATCH 2573/7155] fm10k: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Jeff Kirsher Cc: "David S. Miller" Cc: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c index dca104121c05..1d27b2fb23af 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c @@ -160,8 +160,6 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx); q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc); - if (!q_vector->dbg_q_vector) - return; /* Generate a file for each rx ring in the q_vector */ for (i = 0; i < q_vector->tx.count; i++) { -- GitLab From 43c4eb0381198bdef655461d745c38bfaf3e4b06 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:30 +0200 Subject: [PATCH 2574/7155] i40e: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Jeff Kirsher Cc: "David S. Miller" Cc: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../net/ethernet/intel/i40e/i40e_debugfs.c | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 55d20acfcf70..41232898d8ae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1732,29 +1732,15 @@ static const struct file_operations i40e_dbg_netdev_ops_fops = { **/ void i40e_dbg_pf_init(struct i40e_pf *pf) { - struct dentry *pfile; const char *name = pci_name(pf->pdev); - const struct device *dev = &pf->pdev->dev; pf->i40e_dbg_pf = debugfs_create_dir(name, i40e_dbg_root); - if (!pf->i40e_dbg_pf) - return; - - pfile = debugfs_create_file("command", 0600, pf->i40e_dbg_pf, pf, - &i40e_dbg_command_fops); - if (!pfile) - goto create_failed; - pfile = debugfs_create_file("netdev_ops", 0600, pf->i40e_dbg_pf, pf, - &i40e_dbg_netdev_ops_fops); - if (!pfile) - goto create_failed; + debugfs_create_file("command", 0600, pf->i40e_dbg_pf, pf, + &i40e_dbg_command_fops); - return; - -create_failed: - dev_info(dev, "debugfs dir/file for %s failed\n", name); - debugfs_remove_recursive(pf->i40e_dbg_pf); + debugfs_create_file("netdev_ops", 0600, pf->i40e_dbg_pf, pf, + &i40e_dbg_netdev_ops_fops); } /** -- GitLab From 35dc61ebfc10849121ce059af7343bf470d1fc1b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:31 +0200 Subject: [PATCH 2575/7155] ixgbe: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Jeff Kirsher Cc: "David S. Miller" Cc: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- .../net/ethernet/intel/ixgbe/ixgbe_debugfs.c | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c index 50dfb02fa34c..171cdc552961 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c @@ -190,22 +190,12 @@ static const struct file_operations ixgbe_dbg_netdev_ops_fops = { void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter) { const char *name = pci_name(adapter->pdev); - struct dentry *pfile; + adapter->ixgbe_dbg_adapter = debugfs_create_dir(name, ixgbe_dbg_root); - if (adapter->ixgbe_dbg_adapter) { - pfile = debugfs_create_file("reg_ops", 0600, - adapter->ixgbe_dbg_adapter, adapter, - &ixgbe_dbg_reg_ops_fops); - if (!pfile) - e_dev_err("debugfs reg_ops for %s failed\n", name); - pfile = debugfs_create_file("netdev_ops", 0600, - adapter->ixgbe_dbg_adapter, adapter, - &ixgbe_dbg_netdev_ops_fops); - if (!pfile) - e_dev_err("debugfs netdev_ops for %s failed\n", name); - } else { - e_dev_err("debugfs entry for %s failed\n", name); - } + debugfs_create_file("reg_ops", 0600, adapter->ixgbe_dbg_adapter, + adapter, &ixgbe_dbg_reg_ops_fops); + debugfs_create_file("netdev_ops", 0600, adapter->ixgbe_dbg_adapter, + adapter, &ixgbe_dbg_netdev_ops_fops); } /** @@ -224,8 +214,6 @@ void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter) void ixgbe_dbg_init(void) { ixgbe_dbg_root = debugfs_create_dir(ixgbe_driver_name, NULL); - if (ixgbe_dbg_root == NULL) - pr_err("init of debugfs failed\n"); } /** -- GitLab From 7e174a49bb80f32c20a963b12aa514394666cc3c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:17:32 +0200 Subject: [PATCH 2576/7155] ieee802154: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Alexander Aring Cc: "David S. Miller" Cc: Harry Morris Cc: linux-wpan@vger.kernel.org Cc: netdev@vger.kernel.org Acked-by: Stefan Schmidt Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ieee802154/adf7242.c | 13 +++---------- drivers/net/ieee802154/at86rf230.c | 20 +++++--------------- drivers/net/ieee802154/ca8210.c | 9 +-------- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index c9392d70e639..5a37514e4234 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1158,23 +1158,16 @@ static int adf7242_stats_show(struct seq_file *file, void *offset) return 0; } -static int adf7242_debugfs_init(struct adf7242_local *lp) +static void adf7242_debugfs_init(struct adf7242_local *lp) { char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "adf7242-"; - struct dentry *stats; strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN); lp->debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL); - if (IS_ERR_OR_NULL(lp->debugfs_root)) - return PTR_ERR_OR_ZERO(lp->debugfs_root); - stats = debugfs_create_devm_seqfile(&lp->spi->dev, "status", - lp->debugfs_root, - adf7242_stats_show); - return PTR_ERR_OR_ZERO(stats); - - return 0; + debugfs_create_devm_seqfile(&lp->spi->dev, "status", lp->debugfs_root, + adf7242_stats_show); } static const s32 adf7242_powers[] = { diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 595cf7e2a651..7d67f41387f5 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1626,24 +1626,16 @@ static int at86rf230_stats_show(struct seq_file *file, void *offset) } DEFINE_SHOW_ATTRIBUTE(at86rf230_stats); -static int at86rf230_debugfs_init(struct at86rf230_local *lp) +static void at86rf230_debugfs_init(struct at86rf230_local *lp) { char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-"; - struct dentry *stats; strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN); at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL); - if (!at86rf230_debugfs_root) - return -ENOMEM; - - stats = debugfs_create_file("trac_stats", 0444, - at86rf230_debugfs_root, lp, - &at86rf230_stats_fops); - if (!stats) - return -ENOMEM; - return 0; + debugfs_create_file("trac_stats", 0444, at86rf230_debugfs_root, lp, + &at86rf230_stats_fops); } static void at86rf230_debugfs_remove(void) @@ -1651,7 +1643,7 @@ static void at86rf230_debugfs_remove(void) debugfs_remove_recursive(at86rf230_debugfs_root); } #else -static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; } +static void at86rf230_debugfs_init(struct at86rf230_local *lp) { } static void at86rf230_debugfs_remove(void) { } #endif @@ -1751,9 +1743,7 @@ static int at86rf230_probe(struct spi_device *spi) /* going into sleep by default */ at86rf230_sleep(lp); - rc = at86rf230_debugfs_init(lp); - if (rc) - goto free_dev; + at86rf230_debugfs_init(lp); rc = ieee802154_register_hw(lp->hw); if (rc) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index b188fce3f641..11402dc347db 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -3019,14 +3019,7 @@ static int ca8210_test_interface_init(struct ca8210_priv *priv) priv, &test_int_fops ); - if (IS_ERR(test->ca8210_dfs_spi_int)) { - dev_err( - &priv->spi->dev, - "Error %ld when creating debugfs node\n", - PTR_ERR(test->ca8210_dfs_spi_int) - ); - return PTR_ERR(test->ca8210_dfs_spi_int); - } + debugfs_create_symlink("ca8210", NULL, node_name); init_waitqueue_head(&test->readq); return kfifo_alloc( -- GitLab From e031d5f558f1535968df1ecae8d734b84c17f78d Mon Sep 17 00:00:00 2001 From: Denis Ciocca Date: Mon, 5 Aug 2019 11:57:11 -0700 Subject: [PATCH 2577/7155] iio:st_sensors: remove buffer allocation at each buffer enable This patch is removing the buffer allocation at each buffer enable. We just allocate enough memory in the main structure during probe to cover maximum size needed (that anyway is pretty small) [16bytes]. Signed-off-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_buffer.c | 12 +----------- drivers/iio/gyro/st_gyro_buffer.c | 12 +----------- drivers/iio/magnetometer/st_magn_buffer.c | 12 +----------- drivers/iio/pressure/st_pressure_buffer.c | 12 +----------- include/linux/iio/common/st_sensors.h | 14 +++++++++----- 5 files changed, 13 insertions(+), 49 deletions(-) diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c index 59dcef02ec19..9f2b40474b8e 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -31,17 +31,11 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state) static int st_accel_buffer_postenable(struct iio_dev *indio_dev) { - struct st_sensor_data *adata = iio_priv(indio_dev); int err; - adata->buffer_data = kmalloc(indio_dev->scan_bytes, - GFP_DMA | GFP_KERNEL); - if (!adata->buffer_data) - return -ENOMEM; - err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_accel_free_buffer; + return err; err = st_sensors_set_axis_enable(indio_dev, (u8)indio_dev->active_scan_mask[0]); @@ -58,14 +52,11 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); st_accel_buffer_predisable: iio_triggered_buffer_predisable(indio_dev); -st_accel_free_buffer: - kfree(adata->buffer_data); return err; } static int st_accel_buffer_predisable(struct iio_dev *indio_dev) { - struct st_sensor_data *adata = iio_priv(indio_dev); int err, err2; err = st_sensors_set_enable(indio_dev, false); @@ -79,7 +70,6 @@ static int st_accel_buffer_predisable(struct iio_dev *indio_dev) if (!err) err = err2; - kfree(adata->buffer_data); return err; } diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c index c6ddfecc1fc3..7465ad62391c 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -31,17 +31,11 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state) static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) { - struct st_sensor_data *gdata = iio_priv(indio_dev); int err; - gdata->buffer_data = kmalloc(indio_dev->scan_bytes, - GFP_DMA | GFP_KERNEL); - if (!gdata->buffer_data) - return -ENOMEM; - err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_gyro_free_buffer; + return err; err = st_sensors_set_axis_enable(indio_dev, (u8)indio_dev->active_scan_mask[0]); @@ -58,15 +52,12 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); st_gyro_buffer_predisable: iio_triggered_buffer_predisable(indio_dev); -st_gyro_free_buffer: - kfree(gdata->buffer_data); return err; } static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) { int err, err2; - struct st_sensor_data *gdata = iio_priv(indio_dev); err = st_sensors_set_enable(indio_dev, false); if (err < 0) @@ -79,7 +70,6 @@ static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) if (!err) err = err2; - kfree(gdata->buffer_data); return err; } diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index 658d627dad8e..bb425c167a96 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -31,17 +31,11 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state) static int st_magn_buffer_postenable(struct iio_dev *indio_dev) { - struct st_sensor_data *mdata = iio_priv(indio_dev); int err; - mdata->buffer_data = kmalloc(indio_dev->scan_bytes, - GFP_DMA | GFP_KERNEL); - if (!mdata->buffer_data) - return -ENOMEM; - err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_magn_free_buffer; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -51,14 +45,11 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev) st_magn_buffer_predisable: iio_triggered_buffer_predisable(indio_dev); -st_magn_free_buffer: - kfree(mdata->buffer_data); return err; } static int st_magn_buffer_predisable(struct iio_dev *indio_dev) { - struct st_sensor_data *mdata = iio_priv(indio_dev); int err, err2; err = st_sensors_set_enable(indio_dev, false); @@ -67,7 +58,6 @@ static int st_magn_buffer_predisable(struct iio_dev *indio_dev) if (!err) err = err2; - kfree(mdata->buffer_data); return err; } diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c index 77cb2d862f19..418dbf9e6e1e 100644 --- a/drivers/iio/pressure/st_pressure_buffer.c +++ b/drivers/iio/pressure/st_pressure_buffer.c @@ -31,17 +31,11 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state) static int st_press_buffer_postenable(struct iio_dev *indio_dev) { - struct st_sensor_data *press_data = iio_priv(indio_dev); int err; - press_data->buffer_data = kmalloc(indio_dev->scan_bytes, - GFP_DMA | GFP_KERNEL); - if (!press_data->buffer_data) - return -ENOMEM; - err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_press_free_buffer; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -51,14 +45,11 @@ static int st_press_buffer_postenable(struct iio_dev *indio_dev) st_press_buffer_predisable: iio_triggered_buffer_predisable(indio_dev); -st_press_free_buffer: - kfree(press_data->buffer_data); return err; } static int st_press_buffer_predisable(struct iio_dev *indio_dev) { - struct st_sensor_data *press_data = iio_priv(indio_dev); int err, err2; err = st_sensors_set_enable(indio_dev, false); @@ -67,7 +58,6 @@ static int st_press_buffer_predisable(struct iio_dev *indio_dev) if (!err) err = err2; - kfree(press_data->buffer_data); return err; } diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 4d0889bf1c6c..686be532f4cb 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -20,8 +20,12 @@ #include -#define ST_SENSORS_TX_MAX_LENGTH 2 -#define ST_SENSORS_RX_MAX_LENGTH 6 +/* + * Buffer size max case: 2bytes per channel, 3 channels in total + + * 8bytes timestamp channel (s64) + */ +#define ST_SENSORS_MAX_BUFFER_SIZE (ALIGN(2 * 3, sizeof(s64)) + \ + sizeof(s64)) #define ST_SENSORS_ODR_LIST_MAX 10 #define ST_SENSORS_FULLSCALE_AVL_MAX 10 @@ -215,7 +219,6 @@ struct st_sensor_settings { * @vdd_io: Pointer to sensor's Vdd-IO power supply * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). - * @buffer_data: Data used by buffer part. * @odr: Output data rate of the sensor [Hz]. * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). @@ -224,6 +227,7 @@ struct st_sensor_settings { * @edge_irq: the IRQ triggers on edges and need special handling. * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. + * @buffer_data: Data used by buffer part. */ struct st_sensor_data { struct device *dev; @@ -237,8 +241,6 @@ struct st_sensor_data { bool enabled; - char *buffer_data; - unsigned int odr; unsigned int num_data_channels; @@ -249,6 +251,8 @@ struct st_sensor_data { bool edge_irq; bool hw_irq_trigger; s64 hw_timestamp; + + char buffer_data[ST_SENSORS_MAX_BUFFER_SIZE] ____cacheline_aligned; }; #ifdef CONFIG_IIO_BUFFER -- GitLab From 91227632fc7a047965dcc41da89a40dc982caae8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 23 Jul 2019 16:07:25 +0530 Subject: [PATCH 2578/7155] i3c: master: Add of_node_put() before return Each iteration of for_each_available_childe_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Add an of_node_put before the return. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Boris Brezillon --- drivers/i3c/master.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index c58729081899..87d0f349dd37 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2048,8 +2048,10 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master) for_each_available_child_of_node(i3cbus_np, node) { ret = of_i3c_master_add_dev(master, node); - if (ret) + if (ret) { + of_node_put(node); return ret; + } } /* -- GitLab From fd3f8f3118c66c492c5fe05568569d26db258fbd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Jul 2019 23:51:45 +0300 Subject: [PATCH 2579/7155] i3c: master: cdns: Use for_each_set_bit() This simplifies and standardizes slot manipulation code by using for_each_set_bit() library function. Signed-off-by: Andy Shevchenko Signed-off-by: Boris Brezillon --- drivers/i3c/master/i3c-master-cdns.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index 237f24adddc6..c8adf1eb7e1e 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -903,7 +903,8 @@ static void cdns_i3c_master_upd_i3c_addr(struct i3c_dev_desc *dev) static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master, u8 dyn_addr) { - u32 activedevs, rr; + unsigned long activedevs; + u32 rr; int i; if (!dyn_addr) { @@ -913,13 +914,10 @@ static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master, return ffs(master->free_rr_slots) - 1; } - activedevs = readl(master->regs + DEVS_CTRL) & - DEVS_CTRL_DEVS_ACTIVE_MASK; - - for (i = 1; i <= master->maxdevs; i++) { - if (!(BIT(i) & activedevs)) - continue; + activedevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; + activedevs &= ~BIT(0); + for_each_set_bit(i, &activedevs, master->maxdevs + 1) { rr = readl(master->regs + DEV_ID_RR0(i)); if (!(rr & DEV_ID_RR0_IS_I3C) || DEV_ID_RR0_GET_DEV_ADDR(rr) != dyn_addr) @@ -1126,18 +1124,16 @@ static void cdns_i3c_master_upd_i3c_scl_lim(struct cdns_i3c_master *master) static int cdns_i3c_master_do_daa(struct i3c_master_controller *m) { struct cdns_i3c_master *master = to_cdns_i3c_master(m); - u32 olddevs, newdevs; + unsigned long olddevs, newdevs; int ret, slot; u8 addrs[MAX_DEVS] = { }; u8 last_addr = 0; olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; + olddevs |= BIT(0); /* Prepare RR slots before launching DAA. */ - for (slot = 1; slot <= master->maxdevs; slot++) { - if (olddevs & BIT(slot)) - continue; - + for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) { ret = i3c_master_get_free_addr(m, last_addr + 1); if (ret < 0) return -ENOSPC; @@ -1161,10 +1157,8 @@ static int cdns_i3c_master_do_daa(struct i3c_master_controller *m) * Clear all retaining registers filled during DAA. We already * have the addressed assigned to them in the addrs array. */ - for (slot = 1; slot <= master->maxdevs; slot++) { - if (newdevs & BIT(slot)) - i3c_master_add_i3c_dev_locked(m, addrs[slot]); - } + for_each_set_bit(slot, &newdevs, master->maxdevs + 1) + i3c_master_add_i3c_dev_locked(m, addrs[slot]); /* * Clear slots that ended up not being used. Can be caused by I3C -- GitLab From 6822dc9daa26102161e58a96b2ca938d14696006 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sat, 10 Aug 2019 22:45:11 -0700 Subject: [PATCH 2580/7155] iio: hi8435: Use gpiod_set_value_cansleep() Use gpiod_set_value_cansleep() instead of gpiod_set_value() to support the case when reset pin is connected to a GPIO expander. See ZII VF610 SCU4 AIB for one such example. Signed-off-by: Andrey Smirnov Cc: linux-kernel@vger.kernel.org Cc: linux-iio@vger.kernel.org Cc: Jonathan Cameron Cc: Chris Healy Signed-off-by: Jonathan Cameron --- drivers/iio/adc/hi8435.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 35951c47004e..c15f0e154e4d 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -477,7 +477,7 @@ static int hi8435_probe(struct spi_device *spi) hi8435_writeb(priv, HI8435_CTRL_REG, 0); } else { udelay(5); - gpiod_set_value(reset_gpio, 1); + gpiod_set_value_cansleep(reset_gpio, 1); } spi_set_drvdata(spi, idev); -- GitLab From b1ac3a4b9aa2f68d498824f1235788e67b51b486 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gaj Date: Sat, 22 Jun 2019 21:54:59 +0100 Subject: [PATCH 2581/7155] i3c: add addr and lvr to i2c_dev_desc structure I need to store address and lvr value for I2C devices without static definition in DT. This allows secondary master to transmit DEFSLVS command properly. Main changes between v4 and v5: - Change in defslvs to use addr and lvr from i2c_dev_desc structure - Change in CDNS and DW drivers to use addr and lvr from i2c_dev_desc structure Signed-off-by: Przemyslaw Gaj Signed-off-by: Boris Brezillon --- drivers/i3c/master.c | 10 ++++++---- drivers/i3c/master/dw-i3c-master.c | 4 ++-- drivers/i3c/master/i3c-master-cdns.c | 4 ++-- include/linux/i3c/master.h | 5 +++++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 87d0f349dd37..a38fdf325d30 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -600,6 +600,8 @@ i3c_master_alloc_i2c_dev(struct i3c_master_controller *master, dev->common.master = master; dev->boardinfo = boardinfo; + dev->addr = boardinfo->base.addr; + dev->lvr = boardinfo->lvr; return dev; } @@ -918,8 +920,8 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master) desc = defslvs->slaves; i3c_bus_for_each_i2cdev(bus, i2cdev) { - desc->lvr = i2cdev->boardinfo->lvr; - desc->static_addr = i2cdev->boardinfo->base.addr << 1; + desc->lvr = i2cdev->lvr; + desc->static_addr = i2cdev->addr << 1; desc++; } @@ -1586,8 +1588,8 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master) common.node) { i3c_master_detach_i2c_dev(i2cdev); i3c_bus_set_addr_slot_status(&master->bus, - i2cdev->boardinfo->base.addr, - I3C_ADDR_SLOT_FREE); + i2cdev->addr, + I3C_ADDR_SLOT_FREE); i3c_master_free_i2c_dev(i2cdev); } } diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 09912d75c6d5..b0ff0e12d84c 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -1033,12 +1033,12 @@ static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) return -ENOMEM; data->index = pos; - master->addrs[pos] = dev->boardinfo->base.addr; + master->addrs[pos] = dev->addr; master->free_pos &= ~BIT(pos); i2c_dev_set_master_data(dev, data); writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV | - DEV_ADDR_TABLE_STATIC_ADDR(dev->boardinfo->base.addr), + DEV_ADDR_TABLE_STATIC_ADDR(dev->addr), master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index c8adf1eb7e1e..10db0bf0655a 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -1003,9 +1003,9 @@ static int cdns_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) master->free_rr_slots &= ~BIT(slot); i2c_dev_set_master_data(dev, data); - writel(prepare_rr0_dev_address(dev->boardinfo->base.addr), + writel(prepare_rr0_dev_address(dev->addr), master->regs + DEV_ID_RR0(data->id)); - writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id)); + writel(dev->lvr, master->regs + DEV_ID_RR2(data->id)); writel(readl(master->regs + DEVS_CTRL) | DEVS_CTRL_DEV_ACTIVE(data->id), master->regs + DEVS_CTRL); diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 1f08fa8d69d2..9cb39d901cd5 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -71,6 +71,9 @@ struct i2c_dev_boardinfo { * @common: common part of the I2C device descriptor * @boardinfo: pointer to the boardinfo attached to this I2C device * @dev: I2C device object registered to the I2C framework + * @addr: I2C device address + * @lvr: LVR (Legacy Virtual Register) needed by the I3C core to know about + * the I2C device limitations * * Each I2C device connected on the bus will have an i2c_dev_desc. * This object is created by the core and later attached to the controller @@ -84,6 +87,8 @@ struct i2c_dev_desc { struct i3c_i2c_dev_desc common; const struct i2c_dev_boardinfo *boardinfo; struct i2c_client *dev; + u16 addr; + u8 lvr; }; /** -- GitLab From ef19ee60f9cf713518c1d5e15946466d51e9f00b Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sat, 10 Aug 2019 22:45:45 -0700 Subject: [PATCH 2582/7155] iio: hi8435: Drop hi8435_remove() by using devres for remaining elements Convert the remainder of hi8435_probe() to use devres and get rid of hi8435_remove(). Signed-off-by: Andrey Smirnov Cc: linux-kernel@vger.kernel.org Cc: linux-iio@vger.kernel.org Cc: Chris Healy Signed-off-by: Jonathan Cameron --- drivers/iio/adc/hi8435.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index c15f0e154e4d..8da45bf36d36 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -456,6 +456,11 @@ static irqreturn_t hi8435_trigger_handler(int irq, void *private) return IRQ_HANDLED; } +static void hi8435_triggered_event_cleanup(void *data) +{ + iio_triggered_event_cleanup(data); +} + static int hi8435_probe(struct spi_device *spi) { struct iio_dev *idev; @@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_device_register(idev); - if (ret < 0) { - dev_err(&spi->dev, "unable to register device\n"); - goto unregister_triggered_event; - } - - return 0; - -unregister_triggered_event: - iio_triggered_event_cleanup(idev); - return ret; -} - -static int hi8435_remove(struct spi_device *spi) -{ - struct iio_dev *idev = spi_get_drvdata(spi); - - iio_device_unregister(idev); - iio_triggered_event_cleanup(idev); + ret = devm_add_action_or_reset(&spi->dev, + hi8435_triggered_event_cleanup, + idev); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&spi->dev, idev); } static const struct of_device_id hi8435_dt_ids[] = { @@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = { .of_match_table = of_match_ptr(hi8435_dt_ids), }, .probe = hi8435_probe, - .remove = hi8435_remove, .id_table = hi8435_id, }; module_spi_driver(hi8435_driver); -- GitLab From 7c747838a55818fd0cdbe48afd98fba726aa898d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:46 +0300 Subject: [PATCH 2583/7155] drop_monitor: Split tracing enable / disable to different functions Subsequent patches will need to enable / disable tracing based on the configured alerting mode. Reduce the nesting level and prepare for the introduction of this functionality by splitting the tracing enable / disable operations into two different functions. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 79 ++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 4deb86f990f1..8b9b0b899ebc 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -241,11 +241,58 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi, rcu_read_unlock(); } +static int net_dm_trace_on_set(struct netlink_ext_ack *extack) +{ + int rc; + + if (!try_module_get(THIS_MODULE)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to take reference on module"); + return -ENODEV; + } + + rc = register_trace_kfree_skb(trace_kfree_skb_hit, NULL); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to kfree_skb() tracepoint"); + goto err_module_put; + } + + rc = register_trace_napi_poll(trace_napi_poll_hit, NULL); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to napi_poll() tracepoint"); + goto err_unregister_trace; + } + + return 0; + +err_unregister_trace: + unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); +err_module_put: + module_put(THIS_MODULE); + return rc; +} + +static void net_dm_trace_off_set(void) +{ + struct dm_hw_stat_delta *new_stat, *temp; + + unregister_trace_napi_poll(trace_napi_poll_hit, NULL); + unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); + + tracepoint_synchronize_unregister(); + + list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { + if (new_stat->dev == NULL) { + list_del_rcu(&new_stat->list); + kfree_rcu(new_stat, rcu); + } + } + + module_put(THIS_MODULE); +} + static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) { int rc = 0; - struct dm_hw_stat_delta *new_stat = NULL; - struct dm_hw_stat_delta *temp; if (state == trace_state) { NL_SET_ERR_MSG_MOD(extack, "Trace state already set to requested state"); @@ -254,34 +301,10 @@ static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) switch (state) { case TRACE_ON: - if (!try_module_get(THIS_MODULE)) { - NL_SET_ERR_MSG_MOD(extack, "Failed to take reference on module"); - rc = -ENODEV; - break; - } - - rc |= register_trace_kfree_skb(trace_kfree_skb_hit, NULL); - rc |= register_trace_napi_poll(trace_napi_poll_hit, NULL); + rc = net_dm_trace_on_set(extack); break; - case TRACE_OFF: - rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); - rc |= unregister_trace_napi_poll(trace_napi_poll_hit, NULL); - - tracepoint_synchronize_unregister(); - - /* - * Clean the device list - */ - list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { - if (new_stat->dev == NULL) { - list_del_rcu(&new_stat->list); - kfree_rcu(new_stat, rcu); - } - } - - module_put(THIS_MODULE); - + net_dm_trace_off_set(); break; default: rc = 1; -- GitLab From 70c69274f354ecb905cd46449111e73b17dedaad Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:47 +0300 Subject: [PATCH 2584/7155] drop_monitor: Initialize timer and work item upon tracing enable The timer and work item are currently initialized once during module init, but subsequent patches will need to associate different functions with the work item, based on the configured alert mode. Allow subsequent patches to make that change by initializing and de-initializing these objects during tracing enable and disable. This also guarantees that once the request to disable tracing returns, no more netlink notifications will be generated. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 8b9b0b899ebc..b266dc1660ed 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -243,13 +243,20 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi, static int net_dm_trace_on_set(struct netlink_ext_ack *extack) { - int rc; + int cpu, rc; if (!try_module_get(THIS_MODULE)) { NL_SET_ERR_MSG_MOD(extack, "Failed to take reference on module"); return -ENODEV; } + for_each_possible_cpu(cpu) { + struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); + + INIT_WORK(&data->dm_alert_work, send_dm_alert); + timer_setup(&data->send_timer, sched_send_work, 0); + } + rc = register_trace_kfree_skb(trace_kfree_skb_hit, NULL); if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to kfree_skb() tracepoint"); @@ -274,12 +281,23 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) static void net_dm_trace_off_set(void) { struct dm_hw_stat_delta *new_stat, *temp; + int cpu; unregister_trace_napi_poll(trace_napi_poll_hit, NULL); unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); tracepoint_synchronize_unregister(); + /* Make sure we do not send notifications to user space after request + * to stop tracing returns. + */ + for_each_possible_cpu(cpu) { + struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); + + del_timer_sync(&data->send_timer); + cancel_work_sync(&data->dm_alert_work); + } + list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { if (new_stat->dev == NULL) { list_del_rcu(&new_stat->list); @@ -481,14 +499,10 @@ static void exit_net_drop_monitor(void) /* * Because of the module_get/put we do in the trace state change path * we are guarnateed not to have any current users when we get here - * all we need to do is make sure that we don't have any running timers - * or pending schedule calls */ for_each_possible_cpu(cpu) { data = &per_cpu(dm_cpu_data, cpu); - del_timer_sync(&data->send_timer); - cancel_work_sync(&data->dm_alert_work); /* * At this point, we should have exclusive access * to this struct and can free the skb inside it -- GitLab From 44075f563793880d17d1a2f3a17e06835b157d07 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:48 +0300 Subject: [PATCH 2585/7155] drop_monitor: Reset per-CPU data before starting to trace The function reset_per_cpu_data() allocates and prepares a new skb for the summary netlink alert message ('NET_DM_CMD_ALERT'). The new skb is stored in the per-CPU 'data' variable and the old is returned. The function is invoked during module initialization and from the workqueue, before an alert is sent. This means that it is possible to receive an alert with stale data, if we stopped tracing when the hysteresis timer ('data->send_timer') was pending. Instead of invoking the function during module initialization, invoke it just before we start tracing and ensure we get a fresh skb. This also allows us to remove the calls to initialize the timer and the work item from the module initialization path, since both could have been triggered by the error paths of reset_per_cpu_data(). Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b266dc1660ed..1cf4988de591 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -252,9 +252,16 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) for_each_possible_cpu(cpu) { struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); + struct sk_buff *skb; INIT_WORK(&data->dm_alert_work, send_dm_alert); timer_setup(&data->send_timer, sched_send_work, 0); + /* Allocate a new per-CPU skb for the summary alert message and + * free the old one which might contain stale data from + * previous tracing. + */ + skb = reset_per_cpu_data(data); + consume_skb(skb); } rc = register_trace_kfree_skb(trace_kfree_skb_hit, NULL); @@ -475,10 +482,7 @@ static int __init init_net_drop_monitor(void) for_each_possible_cpu(cpu) { data = &per_cpu(dm_cpu_data, cpu); - INIT_WORK(&data->dm_alert_work, send_dm_alert); - timer_setup(&data->send_timer, sched_send_work, 0); spin_lock_init(&data->lock); - reset_per_cpu_data(data); } goto out; -- GitLab From c5ab9b1c41f6d89d84fe147e51fe623f90bd026c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:49 +0300 Subject: [PATCH 2586/7155] drop_monitor: Require CAP_NET_ADMIN for drop monitor configuration Currently, the configure command does not do anything but return an error. Subsequent patches will enable the command to change various configuration options such as alert mode and packet truncation. Similar to other netlink-based configuration channels, make sure only users with the CAP_NET_ADMIN capability set can execute this command. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 1cf4988de591..cd2f3069f34e 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -409,6 +409,7 @@ static const struct genl_ops dropmon_ops[] = { .cmd = NET_DM_CMD_CONFIG, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = net_dm_cmd_config, + .flags = GENL_ADMIN_PERM, }, { .cmd = NET_DM_CMD_START, -- GitLab From 28315f7999870bb56da236f6b4ffce63efcc7897 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:50 +0300 Subject: [PATCH 2587/7155] drop_monitor: Add alert mode operations The next patch is going to add another alert mode in which the dropped packet is notified to user space, instead of only a summary of recent drops. Abstract the differences between the modes by adding alert mode operations. The operations are selected based on the currently configured mode and associated with the probes and the work item just before tracing starts. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 9 ++++++++ net/core/drop_monitor.c | 38 +++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 5edbd0a675fd..0fecdedeb6ca 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -62,4 +62,13 @@ enum { * Our group identifiers */ #define NET_DM_GRP_ALERT 1 + +/** + * enum net_dm_alert_mode - Alert mode. + * @NET_DM_ALERT_MODE_SUMMARY: A summary of recent drops is sent to user space. + */ +enum net_dm_alert_mode { + NET_DM_ALERT_MODE_SUMMARY, +}; + #endif diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index cd2f3069f34e..9cd2f662cb9e 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -75,6 +75,16 @@ static int dm_delay = 1; static unsigned long dm_hw_check_delta = 2*HZ; static LIST_HEAD(hw_stats_list); +static enum net_dm_alert_mode net_dm_alert_mode = NET_DM_ALERT_MODE_SUMMARY; + +struct net_dm_alert_ops { + void (*kfree_skb_probe)(void *ignore, struct sk_buff *skb, + void *location); + void (*napi_poll_probe)(void *ignore, struct napi_struct *napi, + int work, int budget); + void (*work_item_func)(struct work_struct *work); +}; + static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; @@ -241,10 +251,23 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi, rcu_read_unlock(); } +static const struct net_dm_alert_ops net_dm_alert_summary_ops = { + .kfree_skb_probe = trace_kfree_skb_hit, + .napi_poll_probe = trace_napi_poll_hit, + .work_item_func = send_dm_alert, +}; + +static const struct net_dm_alert_ops *net_dm_alert_ops_arr[] = { + [NET_DM_ALERT_MODE_SUMMARY] = &net_dm_alert_summary_ops, +}; + static int net_dm_trace_on_set(struct netlink_ext_ack *extack) { + const struct net_dm_alert_ops *ops; int cpu, rc; + ops = net_dm_alert_ops_arr[net_dm_alert_mode]; + if (!try_module_get(THIS_MODULE)) { NL_SET_ERR_MSG_MOD(extack, "Failed to take reference on module"); return -ENODEV; @@ -254,7 +277,7 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); struct sk_buff *skb; - INIT_WORK(&data->dm_alert_work, send_dm_alert); + INIT_WORK(&data->dm_alert_work, ops->work_item_func); timer_setup(&data->send_timer, sched_send_work, 0); /* Allocate a new per-CPU skb for the summary alert message and * free the old one which might contain stale data from @@ -264,13 +287,13 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) consume_skb(skb); } - rc = register_trace_kfree_skb(trace_kfree_skb_hit, NULL); + rc = register_trace_kfree_skb(ops->kfree_skb_probe, NULL); if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to kfree_skb() tracepoint"); goto err_module_put; } - rc = register_trace_napi_poll(trace_napi_poll_hit, NULL); + rc = register_trace_napi_poll(ops->napi_poll_probe, NULL); if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to napi_poll() tracepoint"); goto err_unregister_trace; @@ -279,7 +302,7 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) return 0; err_unregister_trace: - unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); + unregister_trace_kfree_skb(ops->kfree_skb_probe, NULL); err_module_put: module_put(THIS_MODULE); return rc; @@ -288,10 +311,13 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) static void net_dm_trace_off_set(void) { struct dm_hw_stat_delta *new_stat, *temp; + const struct net_dm_alert_ops *ops; int cpu; - unregister_trace_napi_poll(trace_napi_poll_hit, NULL); - unregister_trace_kfree_skb(trace_kfree_skb_hit, NULL); + ops = net_dm_alert_ops_arr[net_dm_alert_mode]; + + unregister_trace_napi_poll(ops->napi_poll_probe, NULL); + unregister_trace_kfree_skb(ops->kfree_skb_probe, NULL); tracepoint_synchronize_unregister(); -- GitLab From ca30707dee2bc8bc81cfd8b4277fe90f7ca6df1f Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:51 +0300 Subject: [PATCH 2588/7155] drop_monitor: Add packet alert mode So far drop monitor supported only one alert mode in which a summary of locations in which packets were recently dropped was sent to user space. This alert mode is sufficient in order to understand that packets were dropped, but lacks information to perform a more detailed analysis. Add a new alert mode in which the dropped packet itself is passed to user space along with metadata: The drop location (as program counter and resolved symbol), ingress netdevice and drop timestamp. More metadata can be added in the future. To avoid performing expensive operations in the context in which kfree_skb() is invoked (can be hard IRQ), the dropped skb is cloned and queued on per-CPU skb drop list. Then, in process context the netlink message is allocated, prepared and finally sent to user space. The per-CPU skb drop list is limited to 1000 skbs to prevent exhausting the system's memory. Subsequent patches will make this limit configurable and also add a counter that indicates how many skbs were tail dropped. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 27 +++ net/core/drop_monitor.c | 280 ++++++++++++++++++++++++++++++- 2 files changed, 305 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 0fecdedeb6ca..cfaaf75371b8 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -53,6 +53,7 @@ enum { NET_DM_CMD_CONFIG, NET_DM_CMD_START, NET_DM_CMD_STOP, + NET_DM_CMD_PACKET_ALERT, _NET_DM_CMD_MAX, }; @@ -63,12 +64,38 @@ enum { */ #define NET_DM_GRP_ALERT 1 +enum net_dm_attr { + NET_DM_ATTR_UNSPEC, + + NET_DM_ATTR_ALERT_MODE, /* u8 */ + NET_DM_ATTR_PC, /* u64 */ + NET_DM_ATTR_SYMBOL, /* string */ + NET_DM_ATTR_IN_PORT, /* nested */ + NET_DM_ATTR_TIMESTAMP, /* struct timespec */ + NET_DM_ATTR_PROTO, /* u16 */ + NET_DM_ATTR_PAYLOAD, /* binary */ + NET_DM_ATTR_PAD, + + __NET_DM_ATTR_MAX, + NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1 +}; + /** * enum net_dm_alert_mode - Alert mode. * @NET_DM_ALERT_MODE_SUMMARY: A summary of recent drops is sent to user space. + * @NET_DM_ALERT_MODE_PACKET: Each dropped packet is sent to user space along + * with metadata. */ enum net_dm_alert_mode { NET_DM_ALERT_MODE_SUMMARY, + NET_DM_ALERT_MODE_PACKET, +}; + +enum { + NET_DM_ATTR_PORT_NETDEV_IFINDEX, /* u32 */ + + __NET_DM_ATTR_PORT_MAX, + NET_DM_ATTR_PORT_MAX = __NET_DM_ATTR_PORT_MAX - 1 }; #endif diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 9cd2f662cb9e..ba765832413b 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -54,6 +54,7 @@ static DEFINE_MUTEX(net_dm_mutex); struct per_cpu_dm_data { spinlock_t lock; /* Protects 'skb' and 'send_timer' */ struct sk_buff *skb; + struct sk_buff_head drop_queue; struct work_struct dm_alert_work; struct timer_list send_timer; }; @@ -85,6 +86,14 @@ struct net_dm_alert_ops { void (*work_item_func)(struct work_struct *work); }; +struct net_dm_skb_cb { + void *pc; +}; + +#define NET_DM_SKB_CB(__skb) ((struct net_dm_skb_cb *)&((__skb)->cb[0])) + +#define NET_DM_QUEUE_LEN 1000 + static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; @@ -257,8 +266,214 @@ static const struct net_dm_alert_ops net_dm_alert_summary_ops = { .work_item_func = send_dm_alert, }; +static void net_dm_packet_trace_kfree_skb_hit(void *ignore, + struct sk_buff *skb, + void *location) +{ + ktime_t tstamp = ktime_get_real(); + struct per_cpu_dm_data *data; + struct sk_buff *nskb; + unsigned long flags; + + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) + return; + + NET_DM_SKB_CB(nskb)->pc = location; + /* Override the timestamp because we care about the time when the + * packet was dropped. + */ + nskb->tstamp = tstamp; + + data = this_cpu_ptr(&dm_cpu_data); + + spin_lock_irqsave(&data->drop_queue.lock, flags); + if (skb_queue_len(&data->drop_queue) < NET_DM_QUEUE_LEN) + __skb_queue_tail(&data->drop_queue, nskb); + else + goto unlock_free; + spin_unlock_irqrestore(&data->drop_queue.lock, flags); + + schedule_work(&data->dm_alert_work); + + return; + +unlock_free: + spin_unlock_irqrestore(&data->drop_queue.lock, flags); + consume_skb(nskb); +} + +static void net_dm_packet_trace_napi_poll_hit(void *ignore, + struct napi_struct *napi, + int work, int budget) +{ +} + +static size_t net_dm_in_port_size(void) +{ + /* NET_DM_ATTR_IN_PORT nest */ + return nla_total_size(0) + + /* NET_DM_ATTR_PORT_NETDEV_IFINDEX */ + nla_total_size(sizeof(u32)); +} + +#define NET_DM_MAX_SYMBOL_LEN 40 + +static size_t net_dm_packet_report_size(size_t payload_len) +{ + size_t size; + + size = nlmsg_msg_size(GENL_HDRLEN + net_drop_monitor_family.hdrsize); + + return NLMSG_ALIGN(size) + + /* NET_DM_ATTR_PC */ + nla_total_size(sizeof(u64)) + + /* NET_DM_ATTR_SYMBOL */ + nla_total_size(NET_DM_MAX_SYMBOL_LEN + 1) + + /* NET_DM_ATTR_IN_PORT */ + net_dm_in_port_size() + + /* NET_DM_ATTR_TIMESTAMP */ + nla_total_size(sizeof(struct timespec)) + + /* NET_DM_ATTR_PROTO */ + nla_total_size(sizeof(u16)) + + /* NET_DM_ATTR_PAYLOAD */ + nla_total_size(payload_len); +} + +static int net_dm_packet_report_in_port_put(struct sk_buff *msg, int ifindex) +{ + struct nlattr *attr; + + attr = nla_nest_start(msg, NET_DM_ATTR_IN_PORT); + if (!attr) + return -EMSGSIZE; + + if (ifindex && + nla_put_u32(msg, NET_DM_ATTR_PORT_NETDEV_IFINDEX, ifindex)) + goto nla_put_failure; + + nla_nest_end(msg, attr); + + return 0; + +nla_put_failure: + nla_nest_cancel(msg, attr); + return -EMSGSIZE; +} + +static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb, + size_t payload_len) +{ + u64 pc = (u64)(uintptr_t) NET_DM_SKB_CB(skb)->pc; + char buf[NET_DM_MAX_SYMBOL_LEN]; + struct nlattr *attr; + struct timespec ts; + void *hdr; + int rc; + + hdr = genlmsg_put(msg, 0, 0, &net_drop_monitor_family, 0, + NET_DM_CMD_PACKET_ALERT); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u64_64bit(msg, NET_DM_ATTR_PC, pc, NET_DM_ATTR_PAD)) + goto nla_put_failure; + + snprintf(buf, sizeof(buf), "%pS", NET_DM_SKB_CB(skb)->pc); + if (nla_put_string(msg, NET_DM_ATTR_SYMBOL, buf)) + goto nla_put_failure; + + rc = net_dm_packet_report_in_port_put(msg, skb->skb_iif); + if (rc) + goto nla_put_failure; + + if (ktime_to_timespec_cond(skb->tstamp, &ts) && + nla_put(msg, NET_DM_ATTR_TIMESTAMP, sizeof(ts), &ts)) + goto nla_put_failure; + + if (!payload_len) + goto out; + + if (nla_put_u16(msg, NET_DM_ATTR_PROTO, be16_to_cpu(skb->protocol))) + goto nla_put_failure; + + attr = skb_put(msg, nla_total_size(payload_len)); + attr->nla_type = NET_DM_ATTR_PAYLOAD; + attr->nla_len = nla_attr_size(payload_len); + if (skb_copy_bits(skb, 0, nla_data(attr), payload_len)) + goto nla_put_failure; + +out: + genlmsg_end(msg, hdr); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +#define NET_DM_MAX_PACKET_SIZE (0xffff - NLA_HDRLEN - NLA_ALIGNTO) + +static void net_dm_packet_report(struct sk_buff *skb) +{ + struct sk_buff *msg; + size_t payload_len; + int rc; + + /* Make sure we start copying the packet from the MAC header */ + if (skb->data > skb_mac_header(skb)) + skb_push(skb, skb->data - skb_mac_header(skb)); + else + skb_pull(skb, skb_mac_header(skb) - skb->data); + + /* Ensure packet fits inside a single netlink attribute */ + payload_len = min_t(size_t, skb->len, NET_DM_MAX_PACKET_SIZE); + + msg = nlmsg_new(net_dm_packet_report_size(payload_len), GFP_KERNEL); + if (!msg) + goto out; + + rc = net_dm_packet_report_fill(msg, skb, payload_len); + if (rc) { + nlmsg_free(msg); + goto out; + } + + genlmsg_multicast(&net_drop_monitor_family, msg, 0, 0, GFP_KERNEL); + +out: + consume_skb(skb); +} + +static void net_dm_packet_work(struct work_struct *work) +{ + struct per_cpu_dm_data *data; + struct sk_buff_head list; + struct sk_buff *skb; + unsigned long flags; + + data = container_of(work, struct per_cpu_dm_data, dm_alert_work); + + __skb_queue_head_init(&list); + + spin_lock_irqsave(&data->drop_queue.lock, flags); + skb_queue_splice_tail_init(&data->drop_queue, &list); + spin_unlock_irqrestore(&data->drop_queue.lock, flags); + + while ((skb = __skb_dequeue(&list))) + net_dm_packet_report(skb); +} + +static const struct net_dm_alert_ops net_dm_alert_packet_ops = { + .kfree_skb_probe = net_dm_packet_trace_kfree_skb_hit, + .napi_poll_probe = net_dm_packet_trace_napi_poll_hit, + .work_item_func = net_dm_packet_work, +}; + static const struct net_dm_alert_ops *net_dm_alert_ops_arr[] = { [NET_DM_ALERT_MODE_SUMMARY] = &net_dm_alert_summary_ops, + [NET_DM_ALERT_MODE_PACKET] = &net_dm_alert_packet_ops, }; static int net_dm_trace_on_set(struct netlink_ext_ack *extack) @@ -326,9 +541,12 @@ static void net_dm_trace_off_set(void) */ for_each_possible_cpu(cpu) { struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); + struct sk_buff *skb; del_timer_sync(&data->send_timer); cancel_work_sync(&data->dm_alert_work); + while ((skb = __skb_dequeue(&data->drop_queue))) + consume_skb(skb); } list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { @@ -370,12 +588,61 @@ static int set_all_monitor_traces(int state, struct netlink_ext_ack *extack) return rc; } +static int net_dm_alert_mode_get_from_info(struct genl_info *info, + enum net_dm_alert_mode *p_alert_mode) +{ + u8 val; + + val = nla_get_u8(info->attrs[NET_DM_ATTR_ALERT_MODE]); + + switch (val) { + case NET_DM_ALERT_MODE_SUMMARY: /* fall-through */ + case NET_DM_ALERT_MODE_PACKET: + *p_alert_mode = val; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int net_dm_alert_mode_set(struct genl_info *info) +{ + struct netlink_ext_ack *extack = info->extack; + enum net_dm_alert_mode alert_mode; + int rc; + + if (!info->attrs[NET_DM_ATTR_ALERT_MODE]) + return 0; + + rc = net_dm_alert_mode_get_from_info(info, &alert_mode); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Invalid alert mode"); + return -EINVAL; + } + + net_dm_alert_mode = alert_mode; + + return 0; +} + static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { - NL_SET_ERR_MSG_MOD(info->extack, "Command not supported"); + struct netlink_ext_ack *extack = info->extack; + int rc; - return -EOPNOTSUPP; + if (trace_state == TRACE_ON) { + NL_SET_ERR_MSG_MOD(extack, "Cannot configure drop monitor while tracing is on"); + return -EBUSY; + } + + rc = net_dm_alert_mode_set(info); + if (rc) + return rc; + + return 0; } static int net_dm_cmd_trace(struct sk_buff *skb, @@ -430,6 +697,11 @@ static int dropmon_net_event(struct notifier_block *ev_block, return NOTIFY_DONE; } +static const struct nla_policy net_dm_nl_policy[NET_DM_ATTR_MAX + 1] = { + [NET_DM_ATTR_UNSPEC] = { .strict_start_type = NET_DM_ATTR_UNSPEC + 1 }, + [NET_DM_ATTR_ALERT_MODE] = { .type = NLA_U8 }, +}; + static const struct genl_ops dropmon_ops[] = { { .cmd = NET_DM_CMD_CONFIG, @@ -467,6 +739,8 @@ static struct genl_family net_drop_monitor_family __ro_after_init = { .hdrsize = 0, .name = "NET_DM", .version = 2, + .maxattr = NET_DM_ATTR_MAX, + .policy = net_dm_nl_policy, .pre_doit = net_dm_nl_pre_doit, .post_doit = net_dm_nl_post_doit, .module = THIS_MODULE, @@ -510,6 +784,7 @@ static int __init init_net_drop_monitor(void) for_each_possible_cpu(cpu) { data = &per_cpu(dm_cpu_data, cpu); spin_lock_init(&data->lock); + skb_queue_head_init(&data->drop_queue); } goto out; @@ -539,6 +814,7 @@ static void exit_net_drop_monitor(void) * to this struct and can free the skb inside it */ kfree_skb(data->skb); + WARN_ON(!skb_queue_empty(&data->drop_queue)); } BUG_ON(genl_unregister_family(&net_drop_monitor_family)); -- GitLab From 57986617a736aec2980c1c78a9dd8dcdf477ee6e Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:52 +0300 Subject: [PATCH 2589/7155] drop_monitor: Allow truncation of dropped packets When sending dropped packets to user space it is not always necessary to copy the entire packet as usually only the headers are of interest. Allow user to specify the truncation length and add the original length of the packet as additional metadata to the netlink message. By default no truncation is performed. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 2 ++ net/core/drop_monitor.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index cfaaf75371b8..5cd7eb1f66ba 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -75,6 +75,8 @@ enum net_dm_attr { NET_DM_ATTR_PROTO, /* u16 */ NET_DM_ATTR_PAYLOAD, /* binary */ NET_DM_ATTR_PAD, + NET_DM_ATTR_TRUNC_LEN, /* u32 */ + NET_DM_ATTR_ORIG_LEN, /* u32 */ __NET_DM_ATTR_MAX, NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1 diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index ba765832413b..9f884adaa85f 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -77,6 +77,7 @@ static unsigned long dm_hw_check_delta = 2*HZ; static LIST_HEAD(hw_stats_list); static enum net_dm_alert_mode net_dm_alert_mode = NET_DM_ALERT_MODE_SUMMARY; +static u32 net_dm_trunc_len; struct net_dm_alert_ops { void (*kfree_skb_probe)(void *ignore, struct sk_buff *skb, @@ -334,6 +335,8 @@ static size_t net_dm_packet_report_size(size_t payload_len) net_dm_in_port_size() + /* NET_DM_ATTR_TIMESTAMP */ nla_total_size(sizeof(struct timespec)) + + /* NET_DM_ATTR_ORIG_LEN */ + nla_total_size(sizeof(u32)) + /* NET_DM_ATTR_PROTO */ nla_total_size(sizeof(u16)) + /* NET_DM_ATTR_PAYLOAD */ @@ -391,6 +394,9 @@ static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb, nla_put(msg, NET_DM_ATTR_TIMESTAMP, sizeof(ts), &ts)) goto nla_put_failure; + if (nla_put_u32(msg, NET_DM_ATTR_ORIG_LEN, skb->len)) + goto nla_put_failure; + if (!payload_len) goto out; @@ -429,6 +435,8 @@ static void net_dm_packet_report(struct sk_buff *skb) /* Ensure packet fits inside a single netlink attribute */ payload_len = min_t(size_t, skb->len, NET_DM_MAX_PACKET_SIZE); + if (net_dm_trunc_len) + payload_len = min_t(size_t, net_dm_trunc_len, payload_len); msg = nlmsg_new(net_dm_packet_report_size(payload_len), GFP_KERNEL); if (!msg) @@ -627,6 +635,14 @@ static int net_dm_alert_mode_set(struct genl_info *info) return 0; } +static void net_dm_trunc_len_set(struct genl_info *info) +{ + if (!info->attrs[NET_DM_ATTR_TRUNC_LEN]) + return; + + net_dm_trunc_len = nla_get_u32(info->attrs[NET_DM_ATTR_TRUNC_LEN]); +} + static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { @@ -642,6 +658,8 @@ static int net_dm_cmd_config(struct sk_buff *skb, if (rc) return rc; + net_dm_trunc_len_set(info); + return 0; } @@ -700,6 +718,7 @@ static int dropmon_net_event(struct notifier_block *ev_block, static const struct nla_policy net_dm_nl_policy[NET_DM_ATTR_MAX + 1] = { [NET_DM_ATTR_UNSPEC] = { .strict_start_type = NET_DM_ATTR_UNSPEC + 1 }, [NET_DM_ATTR_ALERT_MODE] = { .type = NLA_U8 }, + [NET_DM_ATTR_TRUNC_LEN] = { .type = NLA_U32 }, }; static const struct genl_ops dropmon_ops[] = { -- GitLab From 444be061d012f1a8ebf95292a648a4e0e2afa83f Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:53 +0300 Subject: [PATCH 2590/7155] drop_monitor: Add a command to query current configuration Users should be able to query the current configuration of drop monitor before they start using it. Add a command to query the existing configuration which currently consists of alert mode and packet truncation length. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 2 ++ net/core/drop_monitor.c | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 5cd7eb1f66ba..3b765a8428b5 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -54,6 +54,8 @@ enum { NET_DM_CMD_START, NET_DM_CMD_STOP, NET_DM_CMD_PACKET_ALERT, + NET_DM_CMD_CONFIG_GET, + NET_DM_CMD_CONFIG_NEW, _NET_DM_CMD_MAX, }; diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 9f884adaa85f..135638474ab8 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -676,6 +676,50 @@ static int net_dm_cmd_trace(struct sk_buff *skb, return -EOPNOTSUPP; } +static int net_dm_config_fill(struct sk_buff *msg, struct genl_info *info) +{ + void *hdr; + + hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, + &net_drop_monitor_family, 0, NET_DM_CMD_CONFIG_NEW); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u8(msg, NET_DM_ATTR_ALERT_MODE, net_dm_alert_mode)) + goto nla_put_failure; + + if (nla_put_u32(msg, NET_DM_ATTR_TRUNC_LEN, net_dm_trunc_len)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int net_dm_cmd_config_get(struct sk_buff *skb, struct genl_info *info) +{ + struct sk_buff *msg; + int rc; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + rc = net_dm_config_fill(msg, info); + if (rc) + goto free_msg; + + return genlmsg_reply(msg, info); + +free_msg: + nlmsg_free(msg); + return rc; +} + static int dropmon_net_event(struct notifier_block *ev_block, unsigned long event, void *ptr) { @@ -738,6 +782,10 @@ static const struct genl_ops dropmon_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = net_dm_cmd_trace, }, + { + .cmd = NET_DM_CMD_CONFIG_GET, + .doit = net_dm_cmd_config_get, + }, }; static int net_dm_nl_pre_doit(const struct genl_ops *ops, -- GitLab From 30328d46af593dcf24582f2a431d84ea0cf4bdef Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:54 +0300 Subject: [PATCH 2591/7155] drop_monitor: Make drop queue length configurable In packet alert mode, each CPU holds a list of dropped skbs that need to be processed in process context and sent to user space. To avoid exhausting the system's memory the maximum length of this queue is currently set to 1000. Allow users to tune the length of this queue according to their needs. The configured length is reported to user space when drop monitor configuration is queried. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 1 + net/core/drop_monitor.c | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 3b765a8428b5..1d0bdb1ba954 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -79,6 +79,7 @@ enum net_dm_attr { NET_DM_ATTR_PAD, NET_DM_ATTR_TRUNC_LEN, /* u32 */ NET_DM_ATTR_ORIG_LEN, /* u32 */ + NET_DM_ATTR_QUEUE_LEN, /* u32 */ __NET_DM_ATTR_MAX, NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1 diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 135638474ab8..eb3c34d69ea9 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -78,6 +78,7 @@ static LIST_HEAD(hw_stats_list); static enum net_dm_alert_mode net_dm_alert_mode = NET_DM_ALERT_MODE_SUMMARY; static u32 net_dm_trunc_len; +static u32 net_dm_queue_len = 1000; struct net_dm_alert_ops { void (*kfree_skb_probe)(void *ignore, struct sk_buff *skb, @@ -93,8 +94,6 @@ struct net_dm_skb_cb { #define NET_DM_SKB_CB(__skb) ((struct net_dm_skb_cb *)&((__skb)->cb[0])) -#define NET_DM_QUEUE_LEN 1000 - static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; @@ -289,7 +288,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, data = this_cpu_ptr(&dm_cpu_data); spin_lock_irqsave(&data->drop_queue.lock, flags); - if (skb_queue_len(&data->drop_queue) < NET_DM_QUEUE_LEN) + if (skb_queue_len(&data->drop_queue) < net_dm_queue_len) __skb_queue_tail(&data->drop_queue, nskb); else goto unlock_free; @@ -643,6 +642,14 @@ static void net_dm_trunc_len_set(struct genl_info *info) net_dm_trunc_len = nla_get_u32(info->attrs[NET_DM_ATTR_TRUNC_LEN]); } +static void net_dm_queue_len_set(struct genl_info *info) +{ + if (!info->attrs[NET_DM_ATTR_QUEUE_LEN]) + return; + + net_dm_queue_len = nla_get_u32(info->attrs[NET_DM_ATTR_QUEUE_LEN]); +} + static int net_dm_cmd_config(struct sk_buff *skb, struct genl_info *info) { @@ -660,6 +667,8 @@ static int net_dm_cmd_config(struct sk_buff *skb, net_dm_trunc_len_set(info); + net_dm_queue_len_set(info); + return 0; } @@ -691,6 +700,9 @@ static int net_dm_config_fill(struct sk_buff *msg, struct genl_info *info) if (nla_put_u32(msg, NET_DM_ATTR_TRUNC_LEN, net_dm_trunc_len)) goto nla_put_failure; + if (nla_put_u32(msg, NET_DM_ATTR_QUEUE_LEN, net_dm_queue_len)) + goto nla_put_failure; + genlmsg_end(msg, hdr); return 0; @@ -763,6 +775,7 @@ static const struct nla_policy net_dm_nl_policy[NET_DM_ATTR_MAX + 1] = { [NET_DM_ATTR_UNSPEC] = { .strict_start_type = NET_DM_ATTR_UNSPEC + 1 }, [NET_DM_ATTR_ALERT_MODE] = { .type = NLA_U8 }, [NET_DM_ATTR_TRUNC_LEN] = { .type = NLA_U32 }, + [NET_DM_ATTR_QUEUE_LEN] = { .type = NLA_U32 }, }; static const struct genl_ops dropmon_ops[] = { -- GitLab From e9feb58020f952f7d9de785ede9a7d54ab1eda5c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 11 Aug 2019 10:35:55 +0300 Subject: [PATCH 2592/7155] drop_monitor: Expose tail drop counter Previous patch made the length of the per-CPU skb drop list configurable. Expose a counter that shows how many packets could not be enqueued to this list. This allows users determine the desired queue length. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 10 +++ net/core/drop_monitor.c | 101 +++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 1d0bdb1ba954..405b31cbf723 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -56,6 +56,8 @@ enum { NET_DM_CMD_PACKET_ALERT, NET_DM_CMD_CONFIG_GET, NET_DM_CMD_CONFIG_NEW, + NET_DM_CMD_STATS_GET, + NET_DM_CMD_STATS_NEW, _NET_DM_CMD_MAX, }; @@ -80,6 +82,7 @@ enum net_dm_attr { NET_DM_ATTR_TRUNC_LEN, /* u32 */ NET_DM_ATTR_ORIG_LEN, /* u32 */ NET_DM_ATTR_QUEUE_LEN, /* u32 */ + NET_DM_ATTR_STATS, /* nested */ __NET_DM_ATTR_MAX, NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1 @@ -103,4 +106,11 @@ enum { NET_DM_ATTR_PORT_MAX = __NET_DM_ATTR_PORT_MAX - 1 }; +enum { + NET_DM_ATTR_STATS_DROPPED, /* u64 */ + + __NET_DM_ATTR_STATS_MAX, + NET_DM_ATTR_STATS_MAX = __NET_DM_ATTR_STATS_MAX - 1 +}; + #endif diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index eb3c34d69ea9..39e094907391 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -51,12 +51,18 @@ static int trace_state = TRACE_OFF; */ static DEFINE_MUTEX(net_dm_mutex); +struct net_dm_stats { + u64 dropped; + struct u64_stats_sync syncp; +}; + struct per_cpu_dm_data { spinlock_t lock; /* Protects 'skb' and 'send_timer' */ struct sk_buff *skb; struct sk_buff_head drop_queue; struct work_struct dm_alert_work; struct timer_list send_timer; + struct net_dm_stats stats; }; struct dm_hw_stat_delta { @@ -300,6 +306,9 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, unlock_free: spin_unlock_irqrestore(&data->drop_queue.lock, flags); + u64_stats_update_begin(&data->stats.syncp); + data->stats.dropped++; + u64_stats_update_end(&data->stats.syncp); consume_skb(nskb); } @@ -732,6 +741,93 @@ static int net_dm_cmd_config_get(struct sk_buff *skb, struct genl_info *info) return rc; } +static void net_dm_stats_read(struct net_dm_stats *stats) +{ + int cpu; + + memset(stats, 0, sizeof(*stats)); + for_each_possible_cpu(cpu) { + struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); + struct net_dm_stats *cpu_stats = &data->stats; + unsigned int start; + u64 dropped; + + do { + start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); + dropped = cpu_stats->dropped; + } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); + + stats->dropped += dropped; + } +} + +static int net_dm_stats_put(struct sk_buff *msg) +{ + struct net_dm_stats stats; + struct nlattr *attr; + + net_dm_stats_read(&stats); + + attr = nla_nest_start(msg, NET_DM_ATTR_STATS); + if (!attr) + return -EMSGSIZE; + + if (nla_put_u64_64bit(msg, NET_DM_ATTR_STATS_DROPPED, + stats.dropped, NET_DM_ATTR_PAD)) + goto nla_put_failure; + + nla_nest_end(msg, attr); + + return 0; + +nla_put_failure: + nla_nest_cancel(msg, attr); + return -EMSGSIZE; +} + +static int net_dm_stats_fill(struct sk_buff *msg, struct genl_info *info) +{ + void *hdr; + int rc; + + hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, + &net_drop_monitor_family, 0, NET_DM_CMD_STATS_NEW); + if (!hdr) + return -EMSGSIZE; + + rc = net_dm_stats_put(msg); + if (rc) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int net_dm_cmd_stats_get(struct sk_buff *skb, struct genl_info *info) +{ + struct sk_buff *msg; + int rc; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + rc = net_dm_stats_fill(msg, info); + if (rc) + goto free_msg; + + return genlmsg_reply(msg, info); + +free_msg: + nlmsg_free(msg); + return rc; +} + static int dropmon_net_event(struct notifier_block *ev_block, unsigned long event, void *ptr) { @@ -799,6 +895,10 @@ static const struct genl_ops dropmon_ops[] = { .cmd = NET_DM_CMD_CONFIG_GET, .doit = net_dm_cmd_config_get, }, + { + .cmd = NET_DM_CMD_STATS_GET, + .doit = net_dm_cmd_stats_get, + }, }; static int net_dm_nl_pre_doit(const struct genl_ops *ops, @@ -865,6 +965,7 @@ static int __init init_net_drop_monitor(void) data = &per_cpu(dm_cpu_data, cpu); spin_lock_init(&data->lock); skb_queue_head_init(&data->drop_queue); + u64_stats_init(&data->stats.syncp); } goto out; -- GitLab From 150e8f8a1bae1dea75f4217f483ac95ca48c979a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 9 Aug 2019 13:05:12 +0200 Subject: [PATCH 2593/7155] netdevsim: register couple of devlink params Register couple of devlink params, one generic, one driver-specific. Make the values available over debugfs. Example: $ echo "111" > /sys/bus/netdevsim/new_device $ devlink dev param netdevsim/netdevsim111: name max_macs type generic values: cmode driverinit value 32 name test1 type driver-specific values: cmode driverinit value true $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs 32 $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1 Y $ devlink dev param set netdevsim/netdevsim111 name max_macs cmode driverinit value 16 $ devlink dev param set netdevsim/netdevsim111 name test1 cmode driverinit value false $ devlink dev reload netdevsim/netdevsim111 $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs 16 $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 72 ++++++++++++++++++++++++++++++- drivers/net/netdevsim/netdevsim.h | 2 + 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index c5c417a3c0ce..08ca59fc189b 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -40,6 +40,10 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) return PTR_ERR_OR_ZERO(nsim_dev->ports_ddir) ?: -EINVAL; debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir, &nsim_dev->fw_update_status); + debugfs_create_u32("max_macs", 0600, nsim_dev->ddir, + &nsim_dev->max_macs); + debugfs_create_bool("test1", 0600, nsim_dev->ddir, + &nsim_dev->test1); return 0; } @@ -196,6 +200,54 @@ static int nsim_dev_resources_register(struct devlink *devlink) return err; } +enum nsim_devlink_param_id { + NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, + NSIM_DEVLINK_PARAM_ID_TEST1, +}; + +static const struct devlink_param nsim_devlink_params[] = { + DEVLINK_PARAM_GENERIC(MAX_MACS, + BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, NULL), + DEVLINK_PARAM_DRIVER(NSIM_DEVLINK_PARAM_ID_TEST1, + "test1", DEVLINK_PARAM_TYPE_BOOL, + BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, NULL), +}; + +static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev, + struct devlink *devlink) +{ + union devlink_param_value value; + + value.vu32 = nsim_dev->max_macs; + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_MAX_MACS, + value); + value.vbool = nsim_dev->test1; + devlink_param_driverinit_value_set(devlink, + NSIM_DEVLINK_PARAM_ID_TEST1, + value); +} + +static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + union devlink_param_value saved_value; + int err; + + err = devlink_param_driverinit_value_get(devlink, + DEVLINK_PARAM_GENERIC_ID_MAX_MACS, + &saved_value); + if (!err) + nsim_dev->max_macs = saved_value.vu32; + err = devlink_param_driverinit_value_get(devlink, + NSIM_DEVLINK_PARAM_ID_TEST1, + &saved_value); + if (!err) + nsim_dev->test1 = saved_value.vbool; +} + static int nsim_dev_reload(struct devlink *devlink, struct netlink_ext_ack *extack) { @@ -218,6 +270,7 @@ static int nsim_dev_reload(struct devlink *devlink, return err; } } + nsim_devlink_param_load_driverinit_values(devlink); return 0; } @@ -267,6 +320,9 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .flash_update = nsim_dev_flash_update, }; +#define NSIM_DEV_MAX_MACS_DEFAULT 32 +#define NSIM_DEV_TEST1_DEFAULT true + static struct nsim_dev * nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) { @@ -284,6 +340,8 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) INIT_LIST_HEAD(&nsim_dev->port_list); mutex_init(&nsim_dev->port_list_lock); nsim_dev->fw_update_status = true; + nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT; + nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT; nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { @@ -299,18 +357,28 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) if (err) goto err_resources_unregister; - err = nsim_dev_debugfs_init(nsim_dev); + err = devlink_params_register(devlink, nsim_devlink_params, + ARRAY_SIZE(nsim_devlink_params)); if (err) goto err_dl_unregister; + nsim_devlink_set_params_init_values(nsim_dev, devlink); + + err = nsim_dev_debugfs_init(nsim_dev); + if (err) + goto err_params_unregister; err = nsim_bpf_dev_init(nsim_dev); if (err) goto err_debugfs_exit; + devlink_params_publish(devlink); return nsim_dev; err_debugfs_exit: nsim_dev_debugfs_exit(nsim_dev); +err_params_unregister: + devlink_params_unregister(devlink, nsim_devlink_params, + ARRAY_SIZE(nsim_devlink_params)); err_dl_unregister: devlink_unregister(devlink); err_resources_unregister: @@ -328,6 +396,8 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev) nsim_bpf_dev_exit(nsim_dev); nsim_dev_debugfs_exit(nsim_dev); + devlink_params_unregister(devlink, nsim_devlink_params, + ARRAY_SIZE(nsim_devlink_params)); devlink_unregister(devlink); devlink_resources_unregister(devlink, NULL); nsim_fib_destroy(nsim_dev->fib_data); diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 79c05af2a7c0..95751a817508 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -158,6 +158,8 @@ struct nsim_dev { struct list_head port_list; struct mutex port_list_lock; /* protects port list */ bool fw_update_status; + u32 max_macs; + bool test1; }; int nsim_dev_init(void); -- GitLab From 3eef8689325e6358a0c51d2ef8c6a689b2f22d48 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 9 Aug 2019 20:43:04 +0200 Subject: [PATCH 2594/7155] net: phy: simplify genphy_config_advert by using the linkmode_adv_to_xxx_t functions Using linkmode_adv_to_mii_adv_t and linkmode_adv_to_mii_ctrl1000_t allows to simplify the code. In addition avoiding the conversion to the legacy u32 advertisement format allows to remove the warning. Signed-off-by: Heiner Kallweit Suggested-by: Andrew Lunn Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7ddd91df99e3..a70a98dc9879 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1564,24 +1564,20 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable); */ static int genphy_config_advert(struct phy_device *phydev) { - u32 advertise; - int bmsr, adv; - int err, changed = 0; + int err, bmsr, changed = 0; + u32 adv; /* Only allow advertising what this PHY supports */ linkmode_and(phydev->advertising, phydev->advertising, phydev->supported); - if (!ethtool_convert_link_mode_to_legacy_u32(&advertise, - phydev->advertising)) - phydev_warn(phydev, "PHY advertising (%*pb) more modes than genphy supports, some modes not advertised.\n", - __ETHTOOL_LINK_MODE_MASK_NBITS, - phydev->advertising); + + adv = linkmode_adv_to_mii_adv_t(phydev->advertising); /* Setup standard advertisement */ err = phy_modify_changed(phydev, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, - ethtool_adv_to_mii_adv_t(advertise)); + adv); if (err < 0) return err; if (err > 0) @@ -1598,13 +1594,7 @@ static int genphy_config_advert(struct phy_device *phydev) if (!(bmsr & BMSR_ESTATEN)) return changed; - /* Configure gigabit if it's supported */ - adv = 0; - if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->supported) || - linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->supported)) - adv = ethtool_adv_to_mii_ctrl1000_t(advertise); + adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); err = phy_modify_changed(phydev, MII_CTRL1000, ADVERTISE_1000FULL | ADVERTISE_1000HALF, -- GitLab From f4069cd7fa6583e7094001c6fce6f426d17a4c76 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 9 Aug 2019 20:43:50 +0200 Subject: [PATCH 2595/7155] net: phy: prepare phylib to deal with PHY's extending Clause 22 The integrated PHY in 2.5Gbps chip RTL8125 is the first (known to me) PHY that uses standard Clause 22 for all modes up to 1Gbps and adds 2.5Gbps control using vendor-specific registers. To use phylib for the standard part little extensions are needed: - Move most of genphy_config_aneg to a new function __genphy_config_aneg that takes a parameter whether restarting auto-negotiation is needed (depending on whether content of vendor-specific advertisement register changed). - Don't clear phydev->lp_advertising in genphy_read_status so that we can set non-C22 mode flags before. Basically both changes mimic the behavior of the equivalent Clause 45 functions. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 27 ++++++++++++--------------- include/linux/phy.h | 8 +++++++- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index a70a98dc9879..b039632de73a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1671,18 +1671,20 @@ int genphy_restart_aneg(struct phy_device *phydev) EXPORT_SYMBOL(genphy_restart_aneg); /** - * genphy_config_aneg - restart auto-negotiation or write BMCR + * __genphy_config_aneg - restart auto-negotiation or write BMCR * @phydev: target phy_device struct + * @changed: whether autoneg is requested * * Description: If auto-negotiation is enabled, we configure the * advertising, and then restart auto-negotiation. If it is not * enabled, then we write the BMCR. */ -int genphy_config_aneg(struct phy_device *phydev) +int __genphy_config_aneg(struct phy_device *phydev, bool changed) { - int err, changed; + int err; - changed = genphy_config_eee_advert(phydev); + if (genphy_config_eee_advert(phydev)) + changed = true; if (AUTONEG_ENABLE != phydev->autoneg) return genphy_setup_forced(phydev); @@ -1690,10 +1692,10 @@ int genphy_config_aneg(struct phy_device *phydev) err = genphy_config_advert(phydev); if (err < 0) /* error */ return err; + else if (err) + changed = true; - changed |= err; - - if (changed == 0) { + if (!changed) { /* Advertisement hasn't changed, but maybe aneg was never on to * begin with? Or maybe phy was isolated? */ @@ -1703,18 +1705,15 @@ int genphy_config_aneg(struct phy_device *phydev) return ctl; if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) - changed = 1; /* do restart aneg */ + changed = true; /* do restart aneg */ } /* Only restart aneg if we are advertising something different * than we were before. */ - if (changed > 0) - return genphy_restart_aneg(phydev); - - return 0; + return changed ? genphy_restart_aneg(phydev) : 0; } -EXPORT_SYMBOL(genphy_config_aneg); +EXPORT_SYMBOL(__genphy_config_aneg); /** * genphy_aneg_done - return auto-negotiation status @@ -1801,8 +1800,6 @@ int genphy_read_status(struct phy_device *phydev) phydev->pause = 0; phydev->asym_pause = 0; - linkmode_zero(phydev->lp_advertising); - if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { if (phydev->is_gigabit_capable) { lpagb = phy_read(phydev, MII_STAT1000); diff --git a/include/linux/phy.h b/include/linux/phy.h index 462b90b73f93..7117825ee57a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1069,7 +1069,7 @@ int genphy_read_abilities(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev); int genphy_config_eee_advert(struct phy_device *phydev); -int genphy_config_aneg(struct phy_device *phydev); +int __genphy_config_aneg(struct phy_device *phydev, bool changed); int genphy_aneg_done(struct phy_device *phydev); int genphy_update_link(struct phy_device *phydev); int genphy_read_status(struct phy_device *phydev); @@ -1077,6 +1077,12 @@ int genphy_suspend(struct phy_device *phydev); int genphy_resume(struct phy_device *phydev); int genphy_loopback(struct phy_device *phydev, bool enable); int genphy_soft_reset(struct phy_device *phydev); + +static inline int genphy_config_aneg(struct phy_device *phydev) +{ + return __genphy_config_aneg(phydev, false); +} + static inline int genphy_no_soft_reset(struct phy_device *phydev) { return 0; -- GitLab From bf22b343ca800aac076ccf986e762b28545aa6bb Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 9 Aug 2019 20:44:22 +0200 Subject: [PATCH 2596/7155] net: phy: add phy_modify_paged_changed Add helper function phy_modify_paged_changed, behavios is the same as for phy_modify_changed. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 29 ++++++++++++++++++++++++----- include/linux/phy.h | 2 ++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 16667fbac8bf..9ae3abb2daca 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -783,24 +783,43 @@ int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val) EXPORT_SYMBOL(phy_write_paged); /** - * phy_modify_paged() - Convenience function for modifying a paged register + * phy_modify_paged_changed() - Function for modifying a paged register * @phydev: a pointer to a &struct phy_device * @page: the page for the phy * @regnum: register number * @mask: bit mask of bits to clear * @set: bit mask of bits to set * - * Same rules as for phy_read() and phy_write(). + * Returns negative errno, 0 if there was no change, and 1 in case of change */ -int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, - u16 mask, u16 set) +int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, + u16 mask, u16 set) { int ret = 0, oldpage; oldpage = phy_select_page(phydev, page); if (oldpage >= 0) - ret = __phy_modify(phydev, regnum, mask, set); + ret = __phy_modify_changed(phydev, regnum, mask, set); return phy_restore_page(phydev, oldpage, ret); } +EXPORT_SYMBOL(phy_modify_paged_changed); + +/** + * phy_modify_paged() - Convenience function for modifying a paged register + * @phydev: a pointer to a &struct phy_device + * @page: the page for the phy + * @regnum: register number + * @mask: bit mask of bits to clear + * @set: bit mask of bits to set + * + * Same rules as for phy_read() and phy_write(). + */ +int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, + u16 mask, u16 set) +{ + int ret = phy_modify_paged_changed(phydev, page, regnum, mask, set); + + return ret < 0 ? ret : 0; +} EXPORT_SYMBOL(phy_modify_paged); diff --git a/include/linux/phy.h b/include/linux/phy.h index 7117825ee57a..781f4810ceba 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -984,6 +984,8 @@ int phy_select_page(struct phy_device *phydev, int page); int phy_restore_page(struct phy_device *phydev, int oldpage, int ret); int phy_read_paged(struct phy_device *phydev, int page, u32 regnum); int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val); +int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, + u16 mask, u16 set); int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set); -- GitLab From 087f5b8758ae9f1b1968bc469bb3f5fae53e639b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 9 Aug 2019 20:45:14 +0200 Subject: [PATCH 2597/7155] net: phy: realtek: add support for the 2.5Gbps PHY in RTL8125 This adds support for the integrated 2.5Gbps PHY in Realtek RTL8125. Advertisement of 2.5Gbps mode is done via a vendor-specific register. Same applies to reading NBase-T link partner advertisement. Unfortunately this 2.5Gbps PHY shares the PHY ID with the integrated 1Gbps PHY's in other Realtek network chips and so far no method is known to differentiate them. As a workaround use a dedicated fake PHY ID that is set by the network driver by intercepting the MDIO PHY ID read. v2: - Create dedicated PHY driver and use a fake PHY ID that is injected by the network driver. Suggested by Andrew Lunn. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/realtek.c | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index a669945eb829..5b466e80d956 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -39,6 +39,11 @@ #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) +#define RTL_ADV_2500FULL BIT(7) +#define RTL_LPADV_10000FULL BIT(11) +#define RTL_LPADV_5000FULL BIT(6) +#define RTL_LPADV_2500FULL BIT(5) + MODULE_DESCRIPTION("Realtek PHY driver"); MODULE_AUTHOR("Johnson Leung"); MODULE_LICENSE("GPL"); @@ -256,6 +261,53 @@ static int rtl8366rb_config_init(struct phy_device *phydev) return ret; } +static int rtl8125_get_features(struct phy_device *phydev) +{ + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported); + + return genphy_read_abilities(phydev); +} + +static int rtl8125_config_aneg(struct phy_device *phydev) +{ + int ret = 0; + + if (phydev->autoneg == AUTONEG_ENABLE) { + u16 adv2500 = 0; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->advertising)) + adv2500 = RTL_ADV_2500FULL; + + ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, + RTL_ADV_2500FULL, adv2500); + if (ret < 0) + return ret; + } + + return __genphy_config_aneg(phydev, ret); +} + +static int rtl8125_read_status(struct phy_device *phydev) +{ + if (phydev->autoneg == AUTONEG_ENABLE) { + int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); + + if (lpadv < 0) + return lpadv; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); + } + + return genphy_read_status(phydev); +} + static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), @@ -332,6 +384,16 @@ static struct phy_driver realtek_drvs[] = { .resume = genphy_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + }, { + PHY_ID_MATCH_EXACT(0x001cca50), + .name = "RTL8125 2.5Gbps internal", + .get_features = rtl8125_get_features, + .config_aneg = rtl8125_config_aneg, + .read_status = rtl8125_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { PHY_ID_MATCH_EXACT(0x001cc961), .name = "RTL8366RB Gigabit Ethernet", -- GitLab From eb2e7f092271091f774a20c0c3b8df3c8c52e060 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 9 Aug 2019 22:59:07 +0200 Subject: [PATCH 2598/7155] r8169: inline rtl8169_free_rx_databuff rtl8169_free_rx_databuff is used in only one place, so let's inline it. We can improve the loop because rtl8169_init_ring zero's RX_databuff before calling rtl8169_rx_fill, and rtl8169_rx_fill fills Rx_databuff starting from index 0. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 24 +++++++---------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 912bd41eaa1b..a4233ace21ca 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5260,18 +5260,6 @@ static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); } -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - struct page **data_buff, - struct RxDesc *desc) -{ - dma_unmap_page(tp_to_dev(tp), le64_to_cpu(desc->addr), - R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); - - __free_pages(*data_buff, get_order(R8169_RX_BUF_SIZE)); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - static inline void rtl8169_mark_to_asic(struct RxDesc *desc) { u32 eor = le32_to_cpu(desc->opts1) & RingEnd; @@ -5312,11 +5300,13 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) { unsigned int i; - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } + for (i = 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) { + dma_unmap_page(tp_to_dev(tp), + le64_to_cpu(tp->RxDescArray[i].addr), + R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); + __free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE)); + tp->Rx_databuff[i] = NULL; + rtl8169_make_unusable_by_asic(tp->RxDescArray + i); } } -- GitLab From 929938536fc0b1628fec8aff62a756e1c4f506d2 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:53 -0400 Subject: [PATCH 2599/7155] net: dsa: mv88e6xxx: wait for 88E6185 PPU disabled The PPU state of 88E6185 can be either "Disabled at Reset" or "Disabled after Initialization". Because we intentionally clear the PPU Enabled bit before checking its state, it is safe to wait for the MV88E6185_G1_STS_PPU_STATE_DISABLED state explicitly instead of waiting for any state different than MV88E6185_G1_STS_PPU_STATE_POLLING. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 1323ef30a5e9..bbd31c9f8b48 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -46,7 +46,7 @@ static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip) /* Check the value of the PPUState bits 15:14 */ state &= MV88E6185_G1_STS_PPU_STATE_MASK; - if (state != MV88E6185_G1_STS_PPU_STATE_POLLING) + if (state == MV88E6185_G1_STS_PPU_STATE_DISABLED) return 0; usleep_range(1000, 2000); -- GitLab From 683f2244c5a3fb61c0e01999d43b4775775ef4e3 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:54 -0400 Subject: [PATCH 2600/7155] net: dsa: mv88e6xxx: introduce wait mask routine The current mv88e6xxx_wait routine is used to wait for a given mask to be cleared to zero. However in some cases, the driver may have to wait for a given mask to be of a certain non-zero value. Thus provide a generic wait mask routine that will be used to implement the current mv88e6xxx_wait function, and use it to wait for 88E6185 PPU states. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 42 +++++++++++++++----------- drivers/net/dsa/mv88e6xxx/chip.h | 2 ++ drivers/net/dsa/mv88e6xxx/global1.c | 47 ++++++++--------------------- drivers/net/dsa/mv88e6xxx/global1.h | 2 ++ 4 files changed, 41 insertions(+), 52 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d3804ffd3d2a..bd61d0d3a245 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -80,6 +80,29 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) return 0; } +int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, + u16 mask, u16 val) +{ + u16 data; + int err; + int i; + + /* There's no bus specific operation to wait for a mask */ + for (i = 0; i < 16; i++) { + err = mv88e6xxx_read(chip, addr, reg, &data); + if (err) + return err; + + if ((data & mask) == val) + return 0; + + usleep_range(1000, 2000); + } + + dev_err(chip->dev, "Timeout while waiting for switch\n"); + return -ETIMEDOUT; +} + struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip) { struct mv88e6xxx_mdio_bus *mdio_bus; @@ -365,24 +388,7 @@ static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip) int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask) { - int i; - - for (i = 0; i < 16; i++) { - u16 val; - int err; - - err = mv88e6xxx_read(chip, addr, reg, &val); - if (err) - return err; - - if (!(val & mask)) - return 0; - - usleep_range(1000, 2000); - } - - dev_err(chip->dev, "Timeout while waiting for switch\n"); - return -ETIMEDOUT; + return mv88e6xxx_wait_mask(chip, addr, reg, mask, 0x0000); } /* Indirect write to single pointer-data register with an Update bit */ diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 8c6d3c906197..95b44532a282 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -588,6 +588,8 @@ static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int po int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); +int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, + u16 mask, u16 val); int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update); int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index bbd31c9f8b48..482f9f8465af 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -32,48 +32,27 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); } +int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg, + u16 mask, u16 val) +{ + return mv88e6xxx_wait_mask(chip, chip->info->global1_addr, reg, + mask, val); +} + /* Offset 0x00: Switch Global Status Register */ static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip) { - u16 state; - int i, err; - - for (i = 0; i < 16; i++) { - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state); - if (err) - return err; - - /* Check the value of the PPUState bits 15:14 */ - state &= MV88E6185_G1_STS_PPU_STATE_MASK; - if (state == MV88E6185_G1_STS_PPU_STATE_DISABLED) - return 0; - - usleep_range(1000, 2000); - } - - return -ETIMEDOUT; + return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS, + MV88E6185_G1_STS_PPU_STATE_MASK, + MV88E6185_G1_STS_PPU_STATE_DISABLED); } static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) { - u16 state; - int i, err; - - for (i = 0; i < 16; ++i) { - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state); - if (err) - return err; - - /* Check the value of the PPUState bits 15:14 */ - state &= MV88E6185_G1_STS_PPU_STATE_MASK; - if (state == MV88E6185_G1_STS_PPU_STATE_POLLING) - return 0; - - usleep_range(1000, 2000); - } - - return -ETIMEDOUT; + return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS, + MV88E6185_G1_STS_PPU_STATE_MASK, + MV88E6185_G1_STS_PPU_STATE_POLLING); } static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index d444266f7d78..48869d7984f4 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -250,6 +250,8 @@ int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val); int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); +int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg, + u16 mask, u16 val); int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); -- GitLab From 19fb7f69da2a1d46bb11cce467b3a9c0b2244202 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:55 -0400 Subject: [PATCH 2601/7155] net: dsa: mv88e6xxx: introduce wait bit routine Many portions of the driver need to wait until a given bit is set or cleared. Some busses even have a specific implementation for this operation. In preparation for such variant, implement a generic Wait Bit routine that can be used by the driver core functions. This allows us to get rid of the custom implementations we may find in the driver. Note that for the EEPROM bits, BUSY and RUNNING bits are independent, thus it is more efficient to wait independently for each bit instead of waiting for their mask. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 14 ++++++- drivers/net/dsa/mv88e6xxx/chip.h | 2 + drivers/net/dsa/mv88e6xxx/global1.c | 49 +++++++------------------ drivers/net/dsa/mv88e6xxx/global1.h | 2 + drivers/net/dsa/mv88e6xxx/global1_atu.c | 7 +++- drivers/net/dsa/mv88e6xxx/global1_vtu.c | 6 ++- drivers/net/dsa/mv88e6xxx/global2.c | 35 +++++++++++++----- drivers/net/dsa/mv88e6xxx/global2.h | 8 ++++ 8 files changed, 73 insertions(+), 50 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bd61d0d3a245..b7e0513c675a 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -10,6 +10,7 @@ * Vivien Didelot */ +#include #include #include #include @@ -103,6 +104,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, return -ETIMEDOUT; } +int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg, + int bit, int val) +{ + return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit), + val ? BIT(bit) : 0x0000); +} + struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip) { struct mv88e6xxx_mdio_bus *mdio_bus; @@ -2360,8 +2368,10 @@ static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port, static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT, - PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY); + int bit = __bf_shf(PORT_RESERVED_1A_BUSY); + + return mv88e6xxx_wait_bit(chip, PORT_RESERVED_1A_CTRL_PORT, + PORT_RESERVED_1A, bit, 0); } diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 95b44532a282..9cdb6bfead25 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -592,6 +592,8 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask, u16 val); int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update); +int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg, + int bit, int val); int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, int speed, int duplex, int pause, diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 482f9f8465af..5ace6490695b 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -32,6 +32,13 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); } +int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int + bit, int val) +{ + return mv88e6xxx_wait_bit(chip, chip->info->global1_addr, reg, + bit, val); +} + int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg, u16 mask, u16 val) { @@ -57,49 +64,20 @@ static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) { - u16 state; - int i, err; - - for (i = 0; i < 16; ++i) { - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state); - if (err) - return err; + int bit = __bf_shf(MV88E6352_G1_STS_PPU_STATE); - /* Check the value of the PPUState (or InitState) bit 15 */ - if (state & MV88E6352_G1_STS_PPU_STATE) - return 0; - - usleep_range(1000, 2000); - } - - return -ETIMEDOUT; + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); } static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) { - const unsigned long timeout = jiffies + 1 * HZ; - u16 val; - int err; + int bit = __bf_shf(MV88E6XXX_G1_STS_INIT_READY); /* Wait up to 1 second for the switch to be ready. The InitReady bit 11 * is set to a one when all units inside the device (ATU, VTU, etc.) * have finished their initialization and are ready to accept frames. */ - while (time_before(jiffies, timeout)) { - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); - if (err) - return err; - - if (val & MV88E6XXX_G1_STS_INIT_READY) - break; - - usleep_range(1000, 2000); - } - - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - - return 0; + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); } /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 @@ -455,8 +433,9 @@ int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index) static int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP, - MV88E6XXX_G1_STATS_OP_BUSY); + int bit = __bf_shf(MV88E6XXX_G1_STATS_OP_BUSY); + + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STATS_OP, bit, 0); } int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 48869d7984f4..ffa11749fecb 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -250,6 +250,8 @@ int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val); int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); +int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int + bit, int val); int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg, u16 mask, u16 val); diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c index 1cf388e9bd94..18b86515b6bc 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_atu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c @@ -5,6 +5,8 @@ * Copyright (c) 2008 Marvell Semiconductor * Copyright (c) 2017 Savoir-faire Linux, Inc. */ + +#include #include #include @@ -75,8 +77,9 @@ int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_ATU_OP, - MV88E6XXX_G1_ATU_OP_BUSY); + int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY); + + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0); } static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op) diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c index 6cac997360e8..33056a609e96 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c @@ -7,6 +7,7 @@ * Copyright (c) 2017 Savoir-faire Linux, Inc. */ +#include #include #include @@ -67,8 +68,9 @@ static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP, - MV88E6XXX_G1_VTU_OP_BUSY); + int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY); + + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0); } static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op) diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 2305b94b3051..b5acf45f30cb 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -36,6 +36,13 @@ int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) return mv88e6xxx_wait(chip, chip->info->global2_addr, reg, mask); } +int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int + bit, int val) +{ + return mv88e6xxx_wait_bit(chip, chip->info->global2_addr, reg, + bit, val); +} + /* Offset 0x00: Interrupt Source Register */ static int mv88e6xxx_g2_int_source(struct mv88e6xxx_chip *chip, u16 *src) @@ -178,8 +185,9 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_IRL_CMD, - MV88E6XXX_G2_IRL_CMD_BUSY); + int bit = __bf_shf(MV88E6XXX_G2_IRL_CMD_BUSY); + + return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_IRL_CMD, bit, 0); } static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port, @@ -214,8 +222,9 @@ int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port) static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR, - MV88E6XXX_G2_PVT_ADDR_BUSY); + int bit = __bf_shf(MV88E6XXX_G2_PVT_ADDR_BUSY); + + return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_PVT_ADDR, bit, 0); } static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev, @@ -308,9 +317,16 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD, - MV88E6XXX_G2_EEPROM_CMD_BUSY | - MV88E6XXX_G2_EEPROM_CMD_RUNNING); + int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); + int err; + + err = mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0); + if (err) + return err; + + bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_RUNNING); + + return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0); } static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd) @@ -572,8 +588,9 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD, - MV88E6XXX_G2_SMI_PHY_CMD_BUSY); + int bit = __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_BUSY); + + return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_SMI_PHY_CMD, bit, 0); } static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd) diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index a664fc25f132..f5574e463a92 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -297,6 +297,8 @@ int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val); int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update); int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); +int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, + int bit, int val); int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port); @@ -386,6 +388,12 @@ static inline int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 ma return -EOPNOTSUPP; } +static inline int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, + int reg, int bit, int val) +{ + return -EOPNOTSUPP; +} + static inline int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port) { -- GitLab From 28ae1e9662b2b29a004adbb11ab0bd033bae296a Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:56 -0400 Subject: [PATCH 2602/7155] net: dsa: mv88e6xxx: wait for AVB Busy bit The AVB is not an indirect table using an Update bit, but a unit using a Busy bit. This means that we must ensure that this bit is cleared before setting it and wait until it gets cleared again after writing an operation. Reflect that. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global2_avb.c | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/global2_avb.c b/drivers/net/dsa/mv88e6xxx/global2_avb.c index 116b8cf5a6e3..657783e043ff 100644 --- a/drivers/net/dsa/mv88e6xxx/global2_avb.c +++ b/drivers/net/dsa/mv88e6xxx/global2_avb.c @@ -11,6 +11,8 @@ * Brandon Streiff */ +#include + #include "global2.h" /* Offset 0x16: AVB Command Register @@ -27,17 +29,33 @@ /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words. * The hardware supports snapshotting up to four contiguous registers. */ +static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip) +{ + int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY); + + return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0); +} + static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop, u16 *data, int len) { int err; int i; + err = mv88e6xxx_g2_avb_wait(chip); + if (err) + return err; + /* Hardware can only snapshot four words. */ if (len > 4) return -E2BIG; - err = mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, readop); + err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD, + MV88E6352_G2_AVB_CMD_BUSY | readop); + if (err) + return err; + + err = mv88e6xxx_g2_avb_wait(chip); if (err) return err; @@ -57,11 +75,18 @@ static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop, { int err; + err = mv88e6xxx_g2_avb_wait(chip); + if (err) + return err; + err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data); if (err) return err; - return mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, writeop); + err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD, + MV88E6352_G2_AVB_CMD_BUSY | writeop); + + return mv88e6xxx_g2_avb_wait(chip); } static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip, -- GitLab From 2ad4da776bdbad92e876aefe2f7bae3e691bbda4 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:57 -0400 Subject: [PATCH 2603/7155] net: dsa: mv88e6xxx: remove wait and update routines Now that we have proper Wait Bit and Wait Mask routines, remove the unused mv88e6xxx_wait routine and its Global 1 and Global 2 variants. The indirect tables such as the Device Mapping Table or Priority Override Table make use of an Update bit to distinguish reading (0) from writing (1) operations. After a write operation occurs, the bit self clears right away so there's no need to wait on it. Thus keep things simple and remove the mv88e6xxx_update helper as well. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 22 ----------- drivers/net/dsa/mv88e6xxx/chip.h | 3 -- drivers/net/dsa/mv88e6xxx/global1.c | 5 --- drivers/net/dsa/mv88e6xxx/global1.h | 1 - drivers/net/dsa/mv88e6xxx/global2.c | 43 ++++++++++----------- drivers/net/dsa/mv88e6xxx/global2.h | 12 ------ drivers/net/dsa/mv88e6xxx/global2_scratch.c | 3 +- 7 files changed, 22 insertions(+), 67 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b7e0513c675a..818a83eb2dcb 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -394,28 +394,6 @@ static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip) mv88e6xxx_reg_unlock(chip); } -int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask) -{ - return mv88e6xxx_wait_mask(chip, addr, reg, mask, 0x0000); -} - -/* Indirect write to single pointer-data register with an Update bit */ -int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update) -{ - u16 val; - int err; - - /* Wait until the previous operation is completed */ - err = mv88e6xxx_wait(chip, addr, reg, BIT(15)); - if (err) - return err; - - /* Set the Update bit to trigger a write operation */ - val = BIT(15) | update; - - return mv88e6xxx_write(chip, addr, reg, val); -} - int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, int speed, int duplex, int pause, phy_interface_t mode) diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 9cdb6bfead25..a406be2f5652 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -590,11 +590,8 @@ int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask, u16 val); -int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, - u16 update); int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg, int bit, int val); -int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, int speed, int duplex, int pause, phy_interface_t mode); diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 5ace6490695b..25ec4c0ac589 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -27,11 +27,6 @@ int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val) return mv88e6xxx_write(chip, addr, reg, val); } -int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) -{ - return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); -} - int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int bit, int val) { diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index ffa11749fecb..78b9ae22d18c 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -249,7 +249,6 @@ int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val); -int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int bit, int val); int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg, diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index b5acf45f30cb..bdbb72fc20ed 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -26,16 +26,6 @@ int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val) return mv88e6xxx_write(chip, chip->info->global2_addr, reg, val); } -int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update) -{ - return mv88e6xxx_update(chip, chip->info->global2_addr, reg, update); -} - -int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) -{ - return mv88e6xxx_wait(chip, chip->info->global2_addr, reg, mask); -} - int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int bit, int val) { @@ -130,7 +120,8 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, * but bit 4 is reserved on older chips, so it is safe to use. */ - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_DEVICE_MAPPING, + MV88E6XXX_G2_DEVICE_MAPPING_UPDATE | val); } /* Offset 0x07: Trunk Mask Table register */ @@ -143,7 +134,8 @@ static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, if (hash) val |= MV88E6XXX_G2_TRUNK_MASK_HASH; - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MASK, + MV88E6XXX_G2_TRUNK_MASK_UPDATE | val); } /* Offset 0x08: Trunk Mapping Table register */ @@ -154,7 +146,8 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; u16 val = (id << 11) | (map & port_mask); - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MAPPING, + MV88E6XXX_G2_TRUNK_MAPPING_UPDATE | val); } int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) @@ -270,7 +263,8 @@ static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip, { u16 val = (pointer << 8) | data; - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MAC, + MV88E6XXX_G2_SWITCH_MAC_UPDATE | val); } int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) @@ -293,7 +287,8 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer, { u16 val = (pointer << 8) | (data & 0x7); - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE, + MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val); } int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) @@ -857,12 +852,13 @@ const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = { static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, - MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE | - MV88E6390_G2_WDOG_CTL_CUT_THROUGH | - MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER | - MV88E6390_G2_WDOG_CTL_EGRESS | - MV88E6390_G2_WDOG_CTL_FORCE_IRQ); + return mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_UPDATE | + MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE | + MV88E6390_G2_WDOG_CTL_CUT_THROUGH | + MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER | + MV88E6390_G2_WDOG_CTL_EGRESS | + MV88E6390_G2_WDOG_CTL_FORCE_IRQ); } static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq) @@ -895,8 +891,9 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq) static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip) { - mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, - MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE); + mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_UPDATE | + MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE); } const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = { diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index f5574e463a92..42da4bca73e8 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -295,8 +295,6 @@ static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip) int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val); -int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update); -int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int bit, int val); @@ -378,16 +376,6 @@ static inline int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 v return -EOPNOTSUPP; } -static inline int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) -{ - return -EOPNOTSUPP; -} - static inline int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int bit, int val) { diff --git a/drivers/net/dsa/mv88e6xxx/global2_scratch.c b/drivers/net/dsa/mv88e6xxx/global2_scratch.c index baddecadd8be..33b7b9570d29 100644 --- a/drivers/net/dsa/mv88e6xxx/global2_scratch.c +++ b/drivers/net/dsa/mv88e6xxx/global2_scratch.c @@ -37,7 +37,8 @@ static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg, { u16 value = (reg << 8) | data; - return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, value); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, + MV88E6XXX_G2_SCRATCH_MISC_UPDATE | value); } /** -- GitLab From 1c6463b6fc36f2261df1a68ee13a5ebd980914b1 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:58 -0400 Subject: [PATCH 2604/7155] net: dsa: mv88e6xxx: fix SMI bit checking The current mv88e6xxx_smi_direct_wait function is only used to check the 16th bit of the (16-bit) SMI Command register. But the bit shift operation is not enough if we eventually use this function to check other bits, thus replace it with a mask. Fixes: e7ba0fad9c53 ("net: dsa: mv88e6xxx: refine SMI support") Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/smi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c index 5fc78a063843..18e87a5a20a3 100644 --- a/drivers/net/dsa/mv88e6xxx/smi.c +++ b/drivers/net/dsa/mv88e6xxx/smi.c @@ -64,7 +64,7 @@ static int mv88e6xxx_smi_direct_wait(struct mv88e6xxx_chip *chip, if (err) return err; - if (!!(data >> bit) == !!val) + if (!!(data & BIT(bit)) == !!val) return 0; } -- GitLab From eede236112b7ea4d9a7c2f2af2ac6648699b88f3 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 9 Aug 2019 18:47:59 -0400 Subject: [PATCH 2605/7155] net: dsa: mv88e6xxx: add delay in direct SMI wait The mv88e6xxx_smi_direct_wait routine is used to wait on indirect registers access. It is of no exception and must delay between read attempts, like other wait routines. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/smi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c index 18e87a5a20a3..282fe08db050 100644 --- a/drivers/net/dsa/mv88e6xxx/smi.c +++ b/drivers/net/dsa/mv88e6xxx/smi.c @@ -66,6 +66,8 @@ static int mv88e6xxx_smi_direct_wait(struct mv88e6xxx_chip *chip, if (!!(data & BIT(bit)) == !!val) return 0; + + usleep_range(1000, 2000); } return -ETIMEDOUT; -- GitLab From 6f20a697e487dea9e054daa18651fef04d97fe3d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:31:08 +0200 Subject: [PATCH 2606/7155] xen-netback: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Wei Liu Cc: Paul Durrant Cc: xen-devel@lists.xenproject.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 3 -- drivers/net/xen-netback/xenbus.c | 46 ++++++++----------------------- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 3ef07b63613e..4679fcf1a1c4 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1653,9 +1653,6 @@ static int __init netback_init(void) #ifdef CONFIG_DEBUG_FS xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - pr_warn("Init of debugfs returned %ld!\n", - PTR_ERR(xen_netback_dbg_root)); #endif /* CONFIG_DEBUG_FS */ return 0; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 41034264bd34..f533b7372d59 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -170,50 +170,26 @@ DEFINE_SHOW_ATTRIBUTE(xenvif_ctrl); static void xenvif_debugfs_addif(struct xenvif *vif) { - struct dentry *pfile; int i; - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - return; - vif->xenvif_dbg_root = debugfs_create_dir(vif->dev->name, xen_netback_dbg_root); - if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root)) { - for (i = 0; i < vif->num_queues; ++i) { - char filename[sizeof("io_ring_q") + 4]; - - snprintf(filename, sizeof(filename), "io_ring_q%d", i); - pfile = debugfs_create_file(filename, - 0600, - vif->xenvif_dbg_root, - &vif->queues[i], - &xenvif_dbg_io_ring_ops_fops); - if (IS_ERR_OR_NULL(pfile)) - pr_warn("Creation of io_ring file returned %ld!\n", - PTR_ERR(pfile)); - } + for (i = 0; i < vif->num_queues; ++i) { + char filename[sizeof("io_ring_q") + 4]; - if (vif->ctrl_irq) { - pfile = debugfs_create_file("ctrl", - 0400, - vif->xenvif_dbg_root, - vif, - &xenvif_ctrl_fops); - if (IS_ERR_OR_NULL(pfile)) - pr_warn("Creation of ctrl file returned %ld!\n", - PTR_ERR(pfile)); - } - } else - netdev_warn(vif->dev, - "Creation of vif debugfs dir returned %ld!\n", - PTR_ERR(vif->xenvif_dbg_root)); + snprintf(filename, sizeof(filename), "io_ring_q%d", i); + debugfs_create_file(filename, 0600, vif->xenvif_dbg_root, + &vif->queues[i], + &xenvif_dbg_io_ring_ops_fops); + } + + if (vif->ctrl_irq) + debugfs_create_file("ctrl", 0400, vif->xenvif_dbg_root, vif, + &xenvif_ctrl_fops); } static void xenvif_debugfs_delif(struct xenvif *vif) { - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - return; - debugfs_remove_recursive(vif->xenvif_dbg_root); vif->xenvif_dbg_root = NULL; } -- GitLab From 53f6f391786e01bf2050c03d8a36d9defdcc2831 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Aug 2019 12:42:43 +0200 Subject: [PATCH 2607/7155] caif: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Richard Fontana Cc: Steve Winslow Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/caif/caif_serial.c | 26 ++++++++++---------------- drivers/net/caif/caif_virtio.c | 6 +----- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index ed3c437063dc..40b079162804 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -94,26 +94,20 @@ static inline void update_tty_status(struct ser_device *ser) } static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) { - ser->debugfs_tty_dir = - debugfs_create_dir(tty->name, debugfsdir); - if (!IS_ERR(ser->debugfs_tty_dir)) { - debugfs_create_blob("last_tx_msg", 0400, - ser->debugfs_tty_dir, - &ser->tx_blob); + ser->debugfs_tty_dir = debugfs_create_dir(tty->name, debugfsdir); - debugfs_create_blob("last_rx_msg", 0400, - ser->debugfs_tty_dir, - &ser->rx_blob); + debugfs_create_blob("last_tx_msg", 0400, ser->debugfs_tty_dir, + &ser->tx_blob); - debugfs_create_x32("ser_state", 0400, - ser->debugfs_tty_dir, - (u32 *)&ser->state); + debugfs_create_blob("last_rx_msg", 0400, ser->debugfs_tty_dir, + &ser->rx_blob); - debugfs_create_x8("tty_status", 0400, - ser->debugfs_tty_dir, - &ser->tty_status); + debugfs_create_x32("ser_state", 0400, ser->debugfs_tty_dir, + (u32 *)&ser->state); + + debugfs_create_x8("tty_status", 0400, ser->debugfs_tty_dir, + &ser->tty_status); - } ser->tx_blob.data = ser->tx_data; ser->tx_blob.size = 0; ser->rx_blob.data = ser->rx_data; diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index 27e93a438dd9..eb426822ad06 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c @@ -623,11 +623,7 @@ static void cfv_netdev_setup(struct net_device *netdev) /* Create debugfs counters for the device */ static inline void debugfs_init(struct cfv_info *cfv) { - cfv->debugfs = - debugfs_create_dir(netdev_name(cfv->ndev), NULL); - - if (IS_ERR(cfv->debugfs)) - return; + cfv->debugfs = debugfs_create_dir(netdev_name(cfv->ndev), NULL); debugfs_create_u32("rx-napi-complete", 0400, cfv->debugfs, &cfv->stats.rx_napi_complete); -- GitLab From 9fbbeb4eff076859891c022c151ad20eda83d983 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:30 +1000 Subject: [PATCH 2608/7155] usb: gadget: aspeed: Don't set port enable change bit on reset This bit should be only set when the port enable goes down, for example, on errors. Not when it gets set after a port reset. Some USB stacks seem to be sensitive to this and fails enumeration. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/hub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c index 7c040f56100e..0755115fd90d 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c @@ -449,8 +449,15 @@ static void ast_vhub_change_port_stat(struct ast_vhub *vhub, USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_L1; - p->change |= chg; + /* + * We only set USB_PORT_STAT_C_ENABLE if we are disabling + * the port as per USB spec, otherwise MacOS gets upset + */ + if (p->status & USB_PORT_STAT_ENABLE) + chg &= ~USB_PORT_STAT_C_ENABLE; + + p->change = chg; ast_vhub_update_hub_ep1(vhub, port); } } -- GitLab From d042c35eb86a8ef13c4b5180fd6953a51d9e1efc Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:31 +1000 Subject: [PATCH 2609/7155] usb: gadget: aspeed: Cleanup EP0 state on port reset Otherwise, we can have a stale state after a disconnect and reconnect causing errors on the first SETUP packet to the device. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 3 +++ drivers/usb/gadget/udc/aspeed-vhub/ep0.c | 9 +++++++++ drivers/usb/gadget/udc/aspeed-vhub/vhub.h | 1 + 3 files changed, 13 insertions(+) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 6b1b16b17d7d..678bbdbd0971 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -55,6 +55,9 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d) if (d->enabled) return; + /* Cleanup EP0 state */ + ast_vhub_reset_ep0(d); + /* Enable device and its EP0 interrupts */ reg = VHUB_DEV_EN_ENABLE_PORT | VHUB_DEV_EN_EP0_IN_ACK_IRQEN | diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c index e2927fb083cf..5e4714d7febb 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c @@ -459,6 +459,15 @@ static const struct usb_ep_ops ast_vhub_ep0_ops = { .free_request = ast_vhub_free_request, }; +void ast_vhub_reset_ep0(struct ast_vhub_dev *dev) +{ + struct ast_vhub_ep *ep = &dev->ep0; + + ast_vhub_nuke(ep, -EIO); + ep->ep0.state = ep0_state_token; +} + + void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, struct ast_vhub_dev *dev) { diff --git a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h index 4ed03d33a5a9..2e7ef387f4f0 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h +++ b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h @@ -507,6 +507,7 @@ void ast_vhub_init_hw(struct ast_vhub *vhub); /* ep0.c */ void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack); void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep); +void ast_vhub_reset_ep0(struct ast_vhub_dev *dev); void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, struct ast_vhub_dev *dev); int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len); -- GitLab From 7e420cef9047dc945b019dc235ec91c792c30f2d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:32 +1000 Subject: [PATCH 2610/7155] usb: gadget: aspeed: Fix EP0 stall handling When stalling EP0, we need to wait for an ACK interrupt, otherwise we may get out of sync on the next setup packet data phase. Also we need to ignore the direction when processing that interrupt as the HW reports a potential mismatch. Implement this by adding a stall state to EP0. This fixes some reported issues with mass storage and some hosts. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/ep0.c | 48 +++++++++++++++-------- drivers/usb/gadget/udc/aspeed-vhub/vhub.h | 1 + 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c index 5e4714d7febb..b64dca7933b0 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c @@ -105,18 +105,20 @@ void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep) (crq.bRequestType & USB_DIR_IN) ? "in" : "out", ep->ep0.state); - /* Check our state, cancel pending requests if needed */ - if (ep->ep0.state != ep0_state_token) { + /* + * Check our state, cancel pending requests if needed + * + * Note: Under some circumstances, we can get a new setup + * packet while waiting for the stall ack, just accept it. + * + * In any case, a SETUP packet in wrong state should have + * reset the HW state machine, so let's just log, nuke + * requests, move on. + */ + if (ep->ep0.state != ep0_state_token && + ep->ep0.state != ep0_state_stall) { EPDBG(ep, "wrong state\n"); ast_vhub_nuke(ep, -EIO); - - /* - * Accept the packet regardless, this seems to happen - * when stalling a SETUP packet that has an OUT data - * phase. - */ - ast_vhub_nuke(ep, 0); - goto stall; } /* Calculate next state for EP0 */ @@ -165,7 +167,7 @@ void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep) stall: EPDBG(ep, "stalling\n"); writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); - ep->ep0.state = ep0_state_status; + ep->ep0.state = ep0_state_stall; ep->ep0.dir_in = false; return; @@ -299,8 +301,8 @@ void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack) if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) || (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) || (ep->ep0.dir_in != in_ack)) { + /* In that case, ignore interrupt */ dev_warn(dev, "irq state mismatch"); - stall = true; break; } /* @@ -335,12 +337,22 @@ void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack) dev_warn(dev, "status direction mismatch\n"); stall = true; } + break; + case ep0_state_stall: + /* + * There shouldn't be any request left, but nuke just in case + * otherwise the stale request will block subsequent ones + */ + ast_vhub_nuke(ep, -EIO); + break; } - /* Reset to token state */ - ep->ep0.state = ep0_state_token; - if (stall) + /* Reset to token state or stall */ + if (stall) { writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); + ep->ep0.state = ep0_state_stall; + } else + ep->ep0.state = ep0_state_token; } static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, @@ -390,8 +402,12 @@ static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, spin_lock_irqsave(&vhub->lock, flags); /* EP0 can only support a single request at a time */ - if (!list_empty(&ep->queue) || ep->ep0.state == ep0_state_token) { + if (!list_empty(&ep->queue) || + ep->ep0.state == ep0_state_token || + ep->ep0.state == ep0_state_stall) { dev_warn(dev, "EP0: Request in wrong state\n"); + EPVDBG(ep, "EP0: list_empty=%d state=%d\n", + list_empty(&ep->queue), ep->ep0.state); spin_unlock_irqrestore(&vhub->lock, flags); return -EBUSY; } diff --git a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h index 2e7ef387f4f0..00f922604a1c 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h +++ b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h @@ -257,6 +257,7 @@ enum ep0_state { ep0_state_token, ep0_state_data, ep0_state_status, + ep0_state_stall, }; /* -- GitLab From ef9d34686bae33de38b0198a4c6c1a50daab31d7 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:33 +1000 Subject: [PATCH 2611/7155] usb: gadget: aspeed: Don't reject requests on suspended devices A disconnect may just suspend the hub in absence of a physical disconnect detection. If we start rejecting requests, the mass storage function gets into a spin trying to requeue the same request for ever and hangs. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 13 +++++++++---- drivers/usb/gadget/udc/aspeed-vhub/ep0.c | 2 +- drivers/usb/gadget/udc/aspeed-vhub/epn.c | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 678bbdbd0971..71e2416858fd 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -204,14 +204,19 @@ int ast_vhub_std_dev_request(struct ast_vhub_ep *ep, u16 wValue, wIndex; /* No driver, we shouldn't be enabled ... */ - if (!d->driver || !d->enabled || d->suspended) { + if (!d->driver || !d->enabled) { EPDBG(ep, - "Device is wrong state driver=%p enabled=%d" - " suspended=%d\n", - d->driver, d->enabled, d->suspended); + "Device is wrong state driver=%p enabled=%d\n", + d->driver, d->enabled); return std_req_stall; } + /* + * Note: we used to reject/stall requests while suspended, + * we don't do that anymore as we seem to have cases of + * mass storage getting very upset. + */ + /* First packet, grab speed */ if (d->gadget.speed == USB_SPEED_UNKNOWN) { d->gadget.speed = ep->vhub->speed; diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c index b64dca7933b0..022b777b85f8 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c @@ -379,7 +379,7 @@ static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, return -EINVAL; /* Disabled device */ - if (ep->dev && (!ep->dev->enabled || ep->dev->suspended)) + if (ep->dev && !ep->dev->enabled) return -ESHUTDOWN; /* Data, no buffer and not internal ? */ diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 35941dc125f9..7475c74aa5c5 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -352,7 +352,7 @@ static int ast_vhub_epn_queue(struct usb_ep* u_ep, struct usb_request *u_req, /* Endpoint enabled ? */ if (!ep->epn.enabled || !u_ep->desc || !ep->dev || !ep->d_idx || - !ep->dev->enabled || ep->dev->suspended) { + !ep->dev->enabled) { EPDBG(ep, "Enqueuing request on wrong or disabled EP\n"); return -ESHUTDOWN; } -- GitLab From 155940a16d688b5376f7c955a5f53259c6fe5689 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:34 +1000 Subject: [PATCH 2612/7155] usb: gadget: aspeed: Check suspend/resume callback existence .. before calling them Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 71e2416858fd..5f7e3b6de531 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -458,7 +458,7 @@ static const struct usb_gadget_ops ast_vhub_udc_ops = { void ast_vhub_dev_suspend(struct ast_vhub_dev *d) { d->suspended = true; - if (d->driver) { + if (d->driver && d->driver->suspend) { spin_unlock(&d->vhub->lock); d->driver->suspend(&d->gadget); spin_lock(&d->vhub->lock); @@ -468,7 +468,7 @@ void ast_vhub_dev_suspend(struct ast_vhub_dev *d) void ast_vhub_dev_resume(struct ast_vhub_dev *d) { d->suspended = false; - if (d->driver) { + if (d->driver && d->driver->resume) { spin_unlock(&d->vhub->lock); d->driver->resume(&d->gadget); spin_lock(&d->vhub->lock); -- GitLab From 5f0625aaba5e4c0db75e942ff3c76516465a77d9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:35 +1000 Subject: [PATCH 2613/7155] usb: gadget: aspeed: Rework the reset logic We had some dodgy code using the speed setting to decide whether a port reset would reset the device or just enable it. Instead, if the device is disabled and has a gadget attached, a reset will enable it. If it's already enabled, a reset will reset it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 58 +++++++++++------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 5f7e3b6de531..79d3cb6bd2e7 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -50,7 +50,7 @@ void ast_vhub_dev_irq(struct ast_vhub_dev *d) static void ast_vhub_dev_enable(struct ast_vhub_dev *d) { - u32 reg, hmsk; + u32 reg, hmsk, i; if (d->enabled) return; @@ -76,6 +76,20 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d) /* Set EP0 DMA buffer address */ writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA); + /* Clear stall on all EPs */ + for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { + struct ast_vhub_ep *ep = d->epns[i]; + + if (ep && (ep->epn.stalled || ep->epn.wedged)) { + ep->epn.stalled = false; + ep->epn.wedged = false; + ast_vhub_update_epn_stall(ep); + } + } + + /* Additional cleanups */ + d->wakeup_en = false; + d->suspended = false; d->enabled = true; } @@ -477,46 +491,28 @@ void ast_vhub_dev_resume(struct ast_vhub_dev *d) void ast_vhub_dev_reset(struct ast_vhub_dev *d) { - /* - * If speed is not set, we enable the port. If it is, - * send reset to the gadget and reset "speed". - * - * Speed is an indication that we have got the first - * setup packet to the device. - */ - if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) { - DDBG(d, "Reset at unknown speed of disabled device, enabling...\n"); - ast_vhub_dev_enable(d); - d->suspended = false; + /* No driver, just disable the device and return */ + if (!d->driver) { + ast_vhub_dev_disable(d); + return; } - if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) { - unsigned int i; - DDBG(d, "Reset at known speed of bound device, resetting...\n"); + /* If the port isn't enabled, just enable it */ + if (!d->enabled) { + DDBG(d, "Reset of disabled device, enabling...\n"); + ast_vhub_dev_enable(d); + } else { + DDBG(d, "Reset of enabled device, resetting...\n"); spin_unlock(&d->vhub->lock); - d->driver->reset(&d->gadget); + usb_gadget_udc_reset(&d->gadget, d->driver); spin_lock(&d->vhub->lock); /* - * Disable/re-enable HW, this will clear the address + * Disable and maybe re-enable HW, this will clear the address * and speed setting. */ ast_vhub_dev_disable(d); ast_vhub_dev_enable(d); - - /* Clear stall on all EPs */ - for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { - struct ast_vhub_ep *ep = d->epns[i]; - - if (ep && ep->epn.stalled) { - ep->epn.stalled = false; - ast_vhub_update_epn_stall(ep); - } - } - - /* Additional cleanups */ - d->wakeup_en = false; - d->suspended = false; } } -- GitLab From 8016759894089ef79415852d253eb54217b44539 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:36 +1000 Subject: [PATCH 2614/7155] usb: gadget: aspeed: Remove unused "suspended" flag The state bit in the hub is sufficient Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 4 ---- drivers/usb/gadget/udc/aspeed-vhub/vhub.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 79d3cb6bd2e7..4008e7a51188 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -89,7 +89,6 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d) /* Additional cleanups */ d->wakeup_en = false; - d->suspended = false; d->enabled = true; } @@ -110,7 +109,6 @@ static void ast_vhub_dev_disable(struct ast_vhub_dev *d) writel(0, d->regs + AST_VHUB_DEV_EN_CTRL); d->gadget.speed = USB_SPEED_UNKNOWN; d->enabled = false; - d->suspended = false; } static int ast_vhub_dev_feature(struct ast_vhub_dev *d, @@ -471,7 +469,6 @@ static const struct usb_gadget_ops ast_vhub_udc_ops = { void ast_vhub_dev_suspend(struct ast_vhub_dev *d) { - d->suspended = true; if (d->driver && d->driver->suspend) { spin_unlock(&d->vhub->lock); d->driver->suspend(&d->gadget); @@ -481,7 +478,6 @@ void ast_vhub_dev_suspend(struct ast_vhub_dev *d) void ast_vhub_dev_resume(struct ast_vhub_dev *d) { - d->suspended = false; if (d->driver && d->driver->resume) { spin_unlock(&d->vhub->lock); d->driver->resume(&d->gadget); diff --git a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h index 00f922604a1c..761919e220d3 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h +++ b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h @@ -354,7 +354,6 @@ struct ast_vhub_dev { struct usb_gadget_driver *driver; bool registered : 1; bool wakeup_en : 1; - bool suspended : 1; bool enabled : 1; /* Endpoint structures */ -- GitLab From cca1754c1d004370b86f41ad346130589fd41152 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:37 +1000 Subject: [PATCH 2615/7155] usb: gadget: aspeed: Improve debugging when nuking When nuking requests, it's useful to display how many were actually nuked. It has proven handy when debugging issues where EP0 went in a wrong state. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index db3628be38c0..9e698de4b1e8 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -65,14 +65,16 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, void ast_vhub_nuke(struct ast_vhub_ep *ep, int status) { struct ast_vhub_req *req; - - EPDBG(ep, "Nuking\n"); + int count = 0; /* Beware, lock will be dropped & req-acquired by done() */ while (!list_empty(&ep->queue)) { req = list_first_entry(&ep->queue, struct ast_vhub_req, queue); ast_vhub_done(ep, req, status); + count++; } + if (count) + EPDBG(ep, "Nuked %d request(s)\n", count); } struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep, -- GitLab From 22a5d3ce0d032d843e36d431e78e6a7dd0efa193 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:38 +1000 Subject: [PATCH 2616/7155] usb: Add definitions for the USB2.0 hub TT requests Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- include/linux/usb/hcd.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index bab27ccc8ff5..367f9b39ac56 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -591,6 +591,10 @@ extern void usb_ep0_reinit(struct usb_device *); #define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS) #define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE) #define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE) +#define ClearTTBuffer HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_CLEAR_TT_BUFFER) +#define ResetTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_RESET_TT) +#define GetTTState HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, HUB_GET_TT_STATE) +#define StopTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_STOP_TT) /*-------------------------------------------------------------------------*/ -- GitLab From aa31332f67ac5418d0ca448153cf49ad09dba360 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 26 Jul 2019 15:05:39 +1000 Subject: [PATCH 2617/7155] usb: gadget: aspeed: Implement dummy hub TT requests We just accept them instead of stalling and return zeros on GetTTState. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/hub.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c index 0755115fd90d..19b3517e04c0 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c @@ -730,6 +730,12 @@ enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep, case ClearPortFeature: EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue); return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue); + case ClearTTBuffer: + case ResetTT: + case StopTT: + return std_req_complete; + case GetTTState: + return ast_vhub_simple_reply(ep, 0, 0, 0, 0); default: EPDBG(ep, "Unknown class request\n"); } -- GitLab From 9b1e6ce34a1ab6d205effa7da38ea520f04d4e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Sun, 11 Aug 2019 22:31:44 +0200 Subject: [PATCH 2618/7155] arm64: defconfig: Enable Sun4i SPDIF module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner A64 and H6 use the Sun4i SPDIF driver. Enable this to allow a proper support. Signed-off-by: Clément Péron Signed-off-by: Chen-Yu Tsai --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c03618c17b04..2aa82650e8e5 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -559,6 +559,7 @@ CONFIG_SND_SOC_ROCKCHIP_RT5645=m CONFIG_SND_SOC_RK3399_GRU_SOUND=m CONFIG_SND_SOC_SAMSUNG=y CONFIG_SND_SOC_RCAR=m +CONFIG_SND_SUN4I_SPDIF=m CONFIG_SND_SOC_AK4613=m CONFIG_SND_SOC_ES7134=m CONFIG_SND_SOC_ES7241=m -- GitLab From f2ee73147a3f23cc4b032a76b5677b4b8441ba74 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 16:40:31 +0200 Subject: [PATCH 2619/7155] gpio: lpc32xx: allow building on non-lpc32xx targets The driver uses hardwire MMIO addresses instead of the data that is passed in device tree. Change it over to only hardcode the register offset values and allow compile-testing. Acked-by: Sylvain Lemieux Tested-by: Sylvain Lemieux Signed-off-by: Arnd Bergmann Signed-off-by: Bartosz Golaszewski --- arch/arm/configs/lpc32xx_defconfig | 1 + drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-lpc32xx.c | 118 +++++++++++++++++------------ 4 files changed, 77 insertions(+), 51 deletions(-) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 0cdc6c7974b3..3772d5a8975a 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -93,6 +93,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_PNX=y +CONFIG_GPIO_LPC32XX=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bb13c266c329..8b40a578963c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -311,6 +311,13 @@ config GPIO_LPC18XX Select this option to enable GPIO driver for NXP LPC18XX/43XX devices. +config GPIO_LPC32XX + tristate "NXP LPC32XX GPIO support" + depends on OF_GPIO && (ARCH_LPC32XX || COMPILE_TEST) + help + Select this option to enable GPIO driver for + NXP LPC32XX devices. + config GPIO_LYNXPOINT tristate "Intel Lynxpoint GPIO support" depends on ACPI && X86 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a4e91175c708..87d659ae95eb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -74,7 +74,7 @@ obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o -obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o +obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 24885b3db3d5..4e626c4235c2 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -16,36 +16,33 @@ #include #include -#include -#include - -#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) -#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) -#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) -#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) -#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) -#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) -#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) -#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) -#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) -#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) -#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) -#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) -#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) -#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) -#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) -#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) -#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) -#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) -#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) -#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) -#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) -#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) -#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) -#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) -#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) -#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) -#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) +#define LPC32XX_GPIO_P3_INP_STATE (0x000) +#define LPC32XX_GPIO_P3_OUTP_SET (0x004) +#define LPC32XX_GPIO_P3_OUTP_CLR (0x008) +#define LPC32XX_GPIO_P3_OUTP_STATE (0x00C) +#define LPC32XX_GPIO_P2_DIR_SET (0x010) +#define LPC32XX_GPIO_P2_DIR_CLR (0x014) +#define LPC32XX_GPIO_P2_DIR_STATE (0x018) +#define LPC32XX_GPIO_P2_INP_STATE (0x01C) +#define LPC32XX_GPIO_P2_OUTP_SET (0x020) +#define LPC32XX_GPIO_P2_OUTP_CLR (0x024) +#define LPC32XX_GPIO_P2_MUX_SET (0x028) +#define LPC32XX_GPIO_P2_MUX_CLR (0x02C) +#define LPC32XX_GPIO_P2_MUX_STATE (0x030) +#define LPC32XX_GPIO_P0_INP_STATE (0x040) +#define LPC32XX_GPIO_P0_OUTP_SET (0x044) +#define LPC32XX_GPIO_P0_OUTP_CLR (0x048) +#define LPC32XX_GPIO_P0_OUTP_STATE (0x04C) +#define LPC32XX_GPIO_P0_DIR_SET (0x050) +#define LPC32XX_GPIO_P0_DIR_CLR (0x054) +#define LPC32XX_GPIO_P0_DIR_STATE (0x058) +#define LPC32XX_GPIO_P1_INP_STATE (0x060) +#define LPC32XX_GPIO_P1_OUTP_SET (0x064) +#define LPC32XX_GPIO_P1_OUTP_CLR (0x068) +#define LPC32XX_GPIO_P1_OUTP_STATE (0x06C) +#define LPC32XX_GPIO_P1_DIR_SET (0x070) +#define LPC32XX_GPIO_P1_DIR_CLR (0x074) +#define LPC32XX_GPIO_P1_DIR_STATE (0x078) #define GPIO012_PIN_TO_BIT(x) (1 << (x)) #define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) @@ -72,12 +69,12 @@ #define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) struct gpio_regs { - void __iomem *inp_state; - void __iomem *outp_state; - void __iomem *outp_set; - void __iomem *outp_clr; - void __iomem *dir_set; - void __iomem *dir_clr; + unsigned long inp_state; + unsigned long outp_state; + unsigned long outp_set; + unsigned long outp_clr; + unsigned long dir_set; + unsigned long dir_clr; }; /* @@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = { struct lpc32xx_gpio_chip { struct gpio_chip chip; struct gpio_regs *gpio_grp; + void __iomem *reg_base; }; +static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset) +{ + return __raw_readl(group->reg_base + offset); +} + +static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset) +{ + __raw_writel(val, group->reg_base + offset); +} + static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, unsigned pin, int input) { if (input) - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->dir_clr); else - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->dir_set); } @@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, u32 u = GPIO3_PIN_TO_BIT(pin); if (input) - __raw_writel(u, group->gpio_grp->dir_clr); + gpreg_write(group, u, group->gpio_grp->dir_clr); else - __raw_writel(u, group->gpio_grp->dir_set); + gpreg_write(group, u, group->gpio_grp->dir_set); } static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, unsigned pin, int high) { if (high) - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->outp_set); else - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); } @@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, u32 u = GPIO3_PIN_TO_BIT(pin); if (high) - __raw_writel(u, group->gpio_grp->outp_set); + gpreg_write(group, u, group->gpio_grp->outp_set); else - __raw_writel(u, group->gpio_grp->outp_clr); + gpreg_write(group, u, group->gpio_grp->outp_clr); } static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, unsigned pin, int high) { if (high) - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); else - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); } static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), + return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin); } static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - int state = __raw_readl(group->gpio_grp->inp_state); + int state = gpreg_read(group, group->gpio_grp->inp_state); /* * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped @@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); + return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin); } static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin); + return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin); } /* @@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc, static int lpc32xx_gpio_probe(struct platform_device *pdev) { int i; + void __iomem *reg_base; + + reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) { if (pdev->dev.of_node) { lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate; lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3; lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node; + lpc32xx_gpiochip[i].reg_base = reg_base; } devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, &lpc32xx_gpiochip[i]); @@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = { }; module_platform_driver(lpc32xx_gpio_driver); + +MODULE_AUTHOR("Kevin Wells "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC"); -- GitLab From 7afe9a4e56658bd659660ea10671831664469e5f Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Sun, 11 Aug 2019 13:33:06 -0500 Subject: [PATCH 2620/7155] i3c: master: fix a memory leak bug In i3c_master_getmwl_locked(), the buffer used for the dest payload data is allocated using kzalloc() in i3c_ccc_cmd_dest_init(). Later on, the length of the dest payload data is checked against 'sizeof(*mwl)'. If they are not equal, -EIO is returned to indicate the error. However, the allocated buffer is not deallocated on this path, leading to a memory leak. To fix the above issue, free the buffer before returning the error. Signed-off-by: Wenwen Wang Signed-off-by: Boris Brezillon --- drivers/i3c/master.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index a38fdf325d30..8ff527263f46 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -1041,8 +1041,10 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master, if (ret) goto out; - if (dest.payload.len != sizeof(*mwl)) - return -EIO; + if (dest.payload.len != sizeof(*mwl)) { + ret = -EIO; + goto out; + } info->max_write_len = be16_to_cpu(mwl->len); -- GitLab From 06188d713885d2a469067637240605b657a4b5a7 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 5 Aug 2019 08:27:04 -0600 Subject: [PATCH 2621/7155] HMAT: Register memory-side cache after parsing Instead of registering the HMAT cache attributes in line with parsing the table, save the attributes in the memory target and register them after parsing completes. This will make it easier to register the attributes later when hot add is supported. Tested-by: Brice Goglin Signed-off-by: Keith Busch Signed-off-by: Rafael J. Wysocki --- drivers/acpi/hmat/hmat.c | 70 +++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c index 96b7d39a97c6..bf23c9a27958 100644 --- a/drivers/acpi/hmat/hmat.c +++ b/drivers/acpi/hmat/hmat.c @@ -36,11 +36,17 @@ enum locality_types { static struct memory_locality *localities_types[4]; +struct target_cache { + struct list_head node; + struct node_cache_attrs cache_attrs; +}; + struct memory_target { struct list_head node; unsigned int memory_pxm; unsigned int processor_pxm; struct node_hmem_attrs hmem_attrs; + struct list_head caches; }; struct memory_initiator { @@ -110,6 +116,7 @@ static __init void alloc_memory_target(unsigned int mem_pxm) target->memory_pxm = mem_pxm; target->processor_pxm = PXM_INVAL; list_add_tail(&target->node, &targets); + INIT_LIST_HEAD(&target->caches); } static __init const char *hmat_data_type(u8 type) @@ -314,7 +321,8 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, const unsigned long end) { struct acpi_hmat_cache *cache = (void *)header; - struct node_cache_attrs cache_attrs; + struct memory_target *target; + struct target_cache *tcache; u32 attrs; if (cache->header.length < sizeof(*cache)) { @@ -328,37 +336,47 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, cache->memory_PD, cache->cache_size, attrs, cache->number_of_SMBIOShandles); - cache_attrs.size = cache->cache_size; - cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4; - cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16; + target = find_mem_target(cache->memory_PD); + if (!target) + return 0; + + tcache = kzalloc(sizeof(*tcache), GFP_KERNEL); + if (!tcache) { + pr_notice_once("Failed to allocate HMAT cache info\n"); + return 0; + } + + tcache->cache_attrs.size = cache->cache_size; + tcache->cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4; + tcache->cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16; switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) { case ACPI_HMAT_CA_DIRECT_MAPPED: - cache_attrs.indexing = NODE_CACHE_DIRECT_MAP; + tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP; break; case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING: - cache_attrs.indexing = NODE_CACHE_INDEXED; + tcache->cache_attrs.indexing = NODE_CACHE_INDEXED; break; case ACPI_HMAT_CA_NONE: default: - cache_attrs.indexing = NODE_CACHE_OTHER; + tcache->cache_attrs.indexing = NODE_CACHE_OTHER; break; } switch ((attrs & ACPI_HMAT_WRITE_POLICY) >> 12) { case ACPI_HMAT_CP_WB: - cache_attrs.write_policy = NODE_CACHE_WRITE_BACK; + tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_BACK; break; case ACPI_HMAT_CP_WT: - cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH; + tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH; break; case ACPI_HMAT_CP_NONE: default: - cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER; + tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER; break; } + list_add_tail(&tcache->node, &target->caches); - node_add_cache(pxm_to_node(cache->memory_PD), &cache_attrs); return 0; } @@ -577,20 +595,37 @@ static __init void hmat_register_target_initiators(struct memory_target *target) } } +static __init void hmat_register_target_cache(struct memory_target *target) +{ + unsigned mem_nid = pxm_to_node(target->memory_pxm); + struct target_cache *tcache; + + list_for_each_entry(tcache, &target->caches, node) + node_add_cache(mem_nid, &tcache->cache_attrs); +} + static __init void hmat_register_target_perf(struct memory_target *target) { unsigned mem_nid = pxm_to_node(target->memory_pxm); node_set_perf_attrs(mem_nid, &target->hmem_attrs, 0); } +static __init void hmat_register_target(struct memory_target *target) +{ + if (!node_online(pxm_to_node(target->memory_pxm))) + return; + + hmat_register_target_initiators(target); + hmat_register_target_cache(target); + hmat_register_target_perf(target); +} + static __init void hmat_register_targets(void) { struct memory_target *target; - list_for_each_entry(target, &targets, node) { - hmat_register_target_initiators(target); - hmat_register_target_perf(target); - } + list_for_each_entry(target, &targets, node) + hmat_register_target(target); } static __init void hmat_free_structures(void) @@ -598,8 +633,13 @@ static __init void hmat_free_structures(void) struct memory_target *target, *tnext; struct memory_locality *loc, *lnext; struct memory_initiator *initiator, *inext; + struct target_cache *tcache, *cnext; list_for_each_entry_safe(target, tnext, &targets, node) { + list_for_each_entry_safe(tcache, cnext, &target->caches, node) { + list_del(&tcache->node); + kfree(tcache); + } list_del(&target->node); kfree(target); } -- GitLab From b630f62bc57cb2f6364cb1199983361d2a664abd Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 5 Aug 2019 08:27:05 -0600 Subject: [PATCH 2622/7155] HMAT: Register attributes for memory hot add Some of the memory nodes described in HMAT may not be online at the time the HMAT subsystem parses their nodes' attributes. Should the node be set to online later, as can happen when using PMEM as RAM after boot, the nodes will be missing their initiator links and performance attributes. Regsiter a memory notifier callback and register the memory attributes the first time its node is brought online if it wasn't registered. Signed-off-by: Keith Busch Signed-off-by: Rafael J. Wysocki --- drivers/acpi/hmat/hmat.c | 75 ++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c index bf23c9a27958..f86fe7130736 100644 --- a/drivers/acpi/hmat/hmat.c +++ b/drivers/acpi/hmat/hmat.c @@ -14,14 +14,18 @@ #include #include #include +#include +#include #include #include -static __initdata u8 hmat_revision; +static u8 hmat_revision; -static __initdata LIST_HEAD(targets); -static __initdata LIST_HEAD(initiators); -static __initdata LIST_HEAD(localities); +static LIST_HEAD(targets); +static LIST_HEAD(initiators); +static LIST_HEAD(localities); + +static DEFINE_MUTEX(target_lock); /* * The defined enum order is used to prioritize attributes to break ties when @@ -47,6 +51,8 @@ struct memory_target { unsigned int processor_pxm; struct node_hmem_attrs hmem_attrs; struct list_head caches; + struct node_cache_attrs cache_attrs; + bool registered; }; struct memory_initiator { @@ -59,7 +65,7 @@ struct memory_locality { struct acpi_hmat_locality *hmat_loc; }; -static __init struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm) +static struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm) { struct memory_initiator *initiator; @@ -69,7 +75,7 @@ static __init struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm) return NULL; } -static __init struct memory_target *find_mem_target(unsigned int mem_pxm) +static struct memory_target *find_mem_target(unsigned int mem_pxm) { struct memory_target *target; @@ -155,7 +161,7 @@ static __init const char *hmat_data_type_suffix(u8 type) } } -static __init u32 hmat_normalize(u16 entry, u64 base, u8 type) +static u32 hmat_normalize(u16 entry, u64 base, u8 type) { u32 value; @@ -190,7 +196,7 @@ static __init u32 hmat_normalize(u16 entry, u64 base, u8 type) return value; } -static __init void hmat_update_target_access(struct memory_target *target, +static void hmat_update_target_access(struct memory_target *target, u8 type, u32 value) { switch (type) { @@ -453,7 +459,7 @@ static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header, return 0; } -static __init u32 hmat_initiator_perf(struct memory_target *target, +static u32 hmat_initiator_perf(struct memory_target *target, struct memory_initiator *initiator, struct acpi_hmat_locality *hmat_loc) { @@ -491,7 +497,7 @@ static __init u32 hmat_initiator_perf(struct memory_target *target, hmat_loc->data_type); } -static __init bool hmat_update_best(u8 type, u32 value, u32 *best) +static bool hmat_update_best(u8 type, u32 value, u32 *best) { bool updated = false; @@ -535,7 +541,7 @@ static int initiator_cmp(void *priv, struct list_head *a, struct list_head *b) return ia->processor_pxm - ib->processor_pxm; } -static __init void hmat_register_target_initiators(struct memory_target *target) +static void hmat_register_target_initiators(struct memory_target *target) { static DECLARE_BITMAP(p_nodes, MAX_NUMNODES); struct memory_initiator *initiator; @@ -595,7 +601,7 @@ static __init void hmat_register_target_initiators(struct memory_target *target) } } -static __init void hmat_register_target_cache(struct memory_target *target) +static void hmat_register_target_cache(struct memory_target *target) { unsigned mem_nid = pxm_to_node(target->memory_pxm); struct target_cache *tcache; @@ -604,23 +610,28 @@ static __init void hmat_register_target_cache(struct memory_target *target) node_add_cache(mem_nid, &tcache->cache_attrs); } -static __init void hmat_register_target_perf(struct memory_target *target) +static void hmat_register_target_perf(struct memory_target *target) { unsigned mem_nid = pxm_to_node(target->memory_pxm); node_set_perf_attrs(mem_nid, &target->hmem_attrs, 0); } -static __init void hmat_register_target(struct memory_target *target) +static void hmat_register_target(struct memory_target *target) { if (!node_online(pxm_to_node(target->memory_pxm))) return; - hmat_register_target_initiators(target); - hmat_register_target_cache(target); - hmat_register_target_perf(target); + mutex_lock(&target_lock); + if (!target->registered) { + hmat_register_target_initiators(target); + hmat_register_target_cache(target); + hmat_register_target_perf(target); + target->registered = true; + } + mutex_unlock(&target_lock); } -static __init void hmat_register_targets(void) +static void hmat_register_targets(void) { struct memory_target *target; @@ -628,6 +639,30 @@ static __init void hmat_register_targets(void) hmat_register_target(target); } +static int hmat_callback(struct notifier_block *self, + unsigned long action, void *arg) +{ + struct memory_target *target; + struct memory_notify *mnb = arg; + int pxm, nid = mnb->status_change_nid; + + if (nid == NUMA_NO_NODE || action != MEM_ONLINE) + return NOTIFY_OK; + + pxm = node_to_pxm(nid); + target = find_mem_target(pxm); + if (!target) + return NOTIFY_OK; + + hmat_register_target(target); + return NOTIFY_OK; +} + +static struct notifier_block hmat_callback_nb = { + .notifier_call = hmat_callback, + .priority = 2, +}; + static __init void hmat_free_structures(void) { struct memory_target *target, *tnext; @@ -698,6 +733,10 @@ static __init int hmat_init(void) } } hmat_register_targets(); + + /* Keep the table and structures if the notifier may use them */ + if (!register_hotmemory_notifier(&hmat_callback_nb)) + return 0; out_put: hmat_free_structures(); acpi_put_table(tbl); -- GitLab From 5c7ed4385424b1c2ce0c27c41448e080e44ebb09 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 5 Aug 2019 08:27:06 -0600 Subject: [PATCH 2623/7155] HMAT: Skip publishing target info for nodes with no online memory There are multiple scenarios where the HMAT may contain information about proximity domains that are not currently online. Rather than fail to report any HMAT data just elide those offline domains. If and when those domains are later onlined they can be added to the HMEM reporting at that point. This was found while testing EFI_MEMORY_SP support which reserves "specific purpose" memory from the general allocation pool. If that reservation results in an empty numa-node then the node is not marked online leading a spurious: "acpi/hmat: Ignoring HMAT: Invalid table" ...result for HMAT parsing. Reviewed-by: Dave Hansen Signed-off-by: Dan Williams Signed-off-by: Keith Busch Signed-off-by: Rafael J. Wysocki --- drivers/acpi/hmat/hmat.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c index f86fe7130736..8f9a28a870b0 100644 --- a/drivers/acpi/hmat/hmat.c +++ b/drivers/acpi/hmat/hmat.c @@ -108,9 +108,6 @@ static __init void alloc_memory_target(unsigned int mem_pxm) { struct memory_target *target; - if (pxm_to_node(mem_pxm) == NUMA_NO_NODE) - return; - target = find_mem_target(mem_pxm); if (target) return; @@ -618,7 +615,16 @@ static void hmat_register_target_perf(struct memory_target *target) static void hmat_register_target(struct memory_target *target) { - if (!node_online(pxm_to_node(target->memory_pxm))) + int nid = pxm_to_node(target->memory_pxm); + + /* + * Skip offline nodes. This can happen when memory + * marked EFI_MEMORY_SP, "specific purpose", is applied + * to all the memory in a promixity domain leading to + * the node being marked offline / unplugged, or if + * memory-only "hotplug" node is offline. + */ + if (nid == NUMA_NO_NODE || !node_online(nid)) return; mutex_lock(&target_lock); -- GitLab From b194a77fcc4001dc40aecdd15d249648e8a436d1 Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Fri, 26 Jul 2019 09:43:37 +0800 Subject: [PATCH 2624/7155] efi: cper: print AER info of PCIe fatal error AER info of PCIe fatal error is not printed in the current driver. Because APEI driver will panic directly for fatal error, and can't run to the place of printing AER info. An example log is as following: {763}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 11 {763}[Hardware Error]: event severity: fatal {763}[Hardware Error]: Error 0, type: fatal {763}[Hardware Error]: section_type: PCIe error {763}[Hardware Error]: port_type: 0, PCIe end point {763}[Hardware Error]: version: 4.0 {763}[Hardware Error]: command: 0x0000, status: 0x0010 {763}[Hardware Error]: device_id: 0000:82:00.0 {763}[Hardware Error]: slot: 0 {763}[Hardware Error]: secondary_bus: 0x00 {763}[Hardware Error]: vendor_id: 0x8086, device_id: 0x10fb {763}[Hardware Error]: class_code: 000002 Kernel panic - not syncing: Fatal hardware error! This issue was imported by the patch, '37448adfc7ce ("aerdrv: Move cper_print_aer() call out of interrupt context")'. To fix this issue, this patch adds print of AER info in cper_print_pcie() for fatal error. Here is the example log after this patch applied: {24}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 10 {24}[Hardware Error]: event severity: fatal {24}[Hardware Error]: Error 0, type: fatal {24}[Hardware Error]: section_type: PCIe error {24}[Hardware Error]: port_type: 0, PCIe end point {24}[Hardware Error]: version: 4.0 {24}[Hardware Error]: command: 0x0546, status: 0x4010 {24}[Hardware Error]: device_id: 0000:01:00.0 {24}[Hardware Error]: slot: 0 {24}[Hardware Error]: secondary_bus: 0x00 {24}[Hardware Error]: vendor_id: 0x15b3, device_id: 0x1019 {24}[Hardware Error]: class_code: 000002 {24}[Hardware Error]: aer_uncor_status: 0x00040000, aer_uncor_mask: 0x00000000 {24}[Hardware Error]: aer_uncor_severity: 0x00062010 {24}[Hardware Error]: TLP Header: 000000c0 01010000 00000001 00000000 Kernel panic - not syncing: Fatal hardware error! Fixes: 37448adfc7ce ("aerdrv: Move cper_print_aer() call out of interrupt context") Signed-off-by: Xiaofei Tan Reviewed-by: James Morse [ardb: put parens around terms of && operator] Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/cper.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 8fa977c7861f..addf0749dd8b 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -390,6 +390,21 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, printk( "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", pfx, pcie->bridge.secondary_status, pcie->bridge.control); + + /* Fatal errors call __ghes_panic() before AER handler prints this */ + if ((pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) && + (gdata->error_severity & CPER_SEV_FATAL)) { + struct aer_capability_regs *aer; + + aer = (struct aer_capability_regs *)pcie->aer_info; + printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n", + pfx, aer->uncor_status, aer->uncor_mask); + printk("%saer_uncor_severity: 0x%08x\n", + pfx, aer->uncor_severity); + printk("%sTLP Header: %08x %08x %08x %08x\n", pfx, + aer->header_log.dw0, aer->header_log.dw1, + aer->header_log.dw2, aer->header_log.dw3); + } } static void cper_print_tstamp(const char *pfx, -- GitLab From a664a834579ae8a6166ac9e5a3232976cab2c24d Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 9 Aug 2019 01:39:11 +0100 Subject: [PATCH 2625/7155] tools: bpftool: fix reading from /proc/config.gz /proc/config has never existed as far as I can see, but /proc/config.gz is present on Arch Linux. Add support for decompressing config.gz using zlib which is a mandatory dependency of libelf anyway. Replace existing stdio functions with gzFile operations since the latter transparently handles uncompressed and gzip-compressed files. Cc: Quentin Monnet Signed-off-by: Peter Wu Reviewed-by: Quentin Monnet Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/Makefile | 2 +- tools/bpf/bpftool/feature.c | 105 ++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile index a7afea4dec47..078bd0dcfba5 100644 --- a/tools/bpf/bpftool/Makefile +++ b/tools/bpf/bpftool/Makefile @@ -52,7 +52,7 @@ ifneq ($(EXTRA_LDFLAGS),) LDFLAGS += $(EXTRA_LDFLAGS) endif -LIBS = -lelf $(LIBBPF) +LIBS = -lelf -lz $(LIBBPF) INSTALL ?= install RM ?= rm -f diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c index d672d9086fff..03bdc5b3ac49 100644 --- a/tools/bpf/bpftool/feature.c +++ b/tools/bpf/bpftool/feature.c @@ -14,6 +14,7 @@ #include #include +#include #include "main.h" @@ -284,34 +285,32 @@ static void probe_jit_limit(void) } } -static char *get_kernel_config_option(FILE *fd, const char *option) +static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n, + char **value) { - size_t line_n = 0, optlen = strlen(option); - char *res, *strval, *line = NULL; - ssize_t n; + char *sep; - rewind(fd); - while ((n = getline(&line, &line_n, fd)) > 0) { - if (strncmp(line, option, optlen)) + while (gzgets(file, buf, n)) { + if (strncmp(buf, "CONFIG_", 7)) continue; - /* Check we have at least '=', value, and '\n' */ - if (strlen(line) < optlen + 3) - continue; - if (*(line + optlen) != '=') + + sep = strchr(buf, '='); + if (!sep) continue; /* Trim ending '\n' */ - line[strlen(line) - 1] = '\0'; + buf[strlen(buf) - 1] = '\0'; + + /* Split on '=' and ensure that a value is present. */ + *sep = '\0'; + if (!sep[1]) + continue; - /* Copy and return config option value */ - strval = line + optlen + 1; - res = strdup(strval); - free(line); - return res; + *value = sep + 1; + return true; } - free(line); - return NULL; + return false; } static void probe_kernel_image_config(void) @@ -386,59 +385,61 @@ static void probe_kernel_image_config(void) /* test_bpf module for BPF tests */ "CONFIG_TEST_BPF", }; - char *value, *buf = NULL; + char *values[ARRAY_SIZE(options)] = { }; struct utsname utsn; char path[PATH_MAX]; - size_t i, n; - ssize_t ret; - FILE *fd; + gzFile file = NULL; + char buf[4096]; + char *value; + size_t i; - if (uname(&utsn)) - goto no_config; + if (!uname(&utsn)) { + snprintf(path, sizeof(path), "/boot/config-%s", utsn.release); - snprintf(path, sizeof(path), "/boot/config-%s", utsn.release); + /* gzopen also accepts uncompressed files. */ + file = gzopen(path, "r"); + } - fd = fopen(path, "r"); - if (!fd && errno == ENOENT) { - /* Some distributions put the config file at /proc/config, give - * it a try. - * Sometimes it is also at /proc/config.gz but we do not try - * this one for now, it would require linking against libz. + if (!file) { + /* Some distributions build with CONFIG_IKCONFIG=y and put the + * config file at /proc/config.gz. */ - fd = fopen("/proc/config", "r"); + file = gzopen("/proc/config.gz", "r"); } - if (!fd) { + if (!file) { p_info("skipping kernel config, can't open file: %s", strerror(errno)); - goto no_config; + goto end_parse; } /* Sanity checks */ - ret = getline(&buf, &n, fd); - ret = getline(&buf, &n, fd); - if (!buf || !ret) { + if (!gzgets(file, buf, sizeof(buf)) || + !gzgets(file, buf, sizeof(buf))) { p_info("skipping kernel config, can't read from file: %s", strerror(errno)); - free(buf); - goto no_config; + goto end_parse; } if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) { p_info("skipping kernel config, can't find correct file"); - free(buf); - goto no_config; + goto end_parse; } - free(buf); - for (i = 0; i < ARRAY_SIZE(options); i++) { - value = get_kernel_config_option(fd, options[i]); - print_kernel_option(options[i], value); - free(value); + while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) { + for (i = 0; i < ARRAY_SIZE(options); i++) { + if (values[i] || strcmp(buf, options[i])) + continue; + + values[i] = strdup(value); + } } - fclose(fd); - return; -no_config: - for (i = 0; i < ARRAY_SIZE(options); i++) - print_kernel_option(options[i], NULL); +end_parse: + if (file) + gzclose(file); + + for (i = 0; i < ARRAY_SIZE(options); i++) { + print_kernel_option(options[i], values[i]); + free(values[i]); + } } static bool probe_bpf_syscall(const char *define_prefix) -- GitLab From 4752544a447b52b9949eb648a3b7719357853f91 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 23 Jul 2019 14:00:09 +0100 Subject: [PATCH 2626/7155] firmware: arm_scmi: Use the correct style for SPDX License Identifier Fix to correct the SPDX License Identifier style in header file related to firmware frivers for ARM SCMI message protocol. For C header files Documentation/process/license-rules.rst mandates C-like comments(opposed to C source files where C++ style should be used). While at it, change GPL-2.0 to GPL-2.0-only similar to the ones in psci.h and scpi_protocol.h Signed-off-by: Sudeep Holla --- include/linux/scmi_protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 9ff2e9357e9a..aa1e791779b4 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * SCMI Message Protocol driver header * -- GitLab From 9eefa43a1a03960c7458e1463132f893702741be Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:33 +0100 Subject: [PATCH 2627/7155] firmware: arm_scmi: Align few names in sensors protocol with SCMI specification Looks like more code developed during the draft versions of the specification slipped through and they don't match the final released version. This seem to have happened only with sensor protocol. Renaming few command and function names here to match exactly with the released version of SCMI specification for ease of maintenance. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/sensors.c | 28 +++++++++++++++------------- include/linux/scmi_protocol.h | 12 ++++++------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 0e94ab56f679..17dbabd8a94a 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -9,8 +9,8 @@ enum scmi_sensor_protocol_cmd { SENSOR_DESCRIPTION_GET = 0x3, - SENSOR_CONFIG_SET = 0x4, - SENSOR_TRIP_POINT_SET = 0x5, + SENSOR_TRIP_POINT_NOTIFY = 0x4, + SENSOR_TRIP_POINT_CONFIG = 0x5, SENSOR_READING_GET = 0x6, }; @@ -42,9 +42,10 @@ struct scmi_msg_resp_sensor_description { } desc[0]; }; -struct scmi_msg_set_sensor_config { +struct scmi_msg_sensor_trip_point_notify { __le32 id; __le32 event_control; +#define SENSOR_TP_NOTIFY_ALL BIT(0) }; struct scmi_msg_set_sensor_trip_point { @@ -160,15 +161,15 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, return ret; } -static int -scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id) +static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle, + u32 sensor_id, bool enable) { int ret; - u32 evt_cntl = BIT(0); + u32 evt_cntl = enable ? SENSOR_TP_NOTIFY_ALL : 0; struct scmi_xfer *t; - struct scmi_msg_set_sensor_config *cfg; + struct scmi_msg_sensor_trip_point_notify *cfg; - ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET, + ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY, SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -183,15 +184,16 @@ scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id) return ret; } -static int scmi_sensor_trip_point_set(const struct scmi_handle *handle, - u32 sensor_id, u8 trip_id, u64 trip_value) +static int +scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id, + u8 trip_id, u64 trip_value) { int ret; u32 evt_cntl = SENSOR_TP_BOTH; struct scmi_xfer *t; struct scmi_msg_set_sensor_trip_point *trip; - ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET, + ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG, SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t); if (ret) return ret; @@ -255,8 +257,8 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle) static struct scmi_sensor_ops sensor_ops = { .count_get = scmi_sensor_count_get, .info_get = scmi_sensor_info_get, - .configuration_set = scmi_sensor_configuration_set, - .trip_point_set = scmi_sensor_trip_point_set, + .trip_point_notify = scmi_sensor_trip_point_notify, + .trip_point_config = scmi_sensor_trip_point_config, .reading_get = scmi_sensor_reading_get, }; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index aa1e791779b4..1383d47e6435 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -167,9 +167,9 @@ enum scmi_sensor_class { * * @count_get: get the count of sensors provided by SCMI * @info_get: get the information of the specified sensor - * @configuration_set: control notifications on cross-over events for + * @trip_point_notify: control notifications on cross-over events for * the trip-points - * @trip_point_set: selects and configures a trip-point of interest + * @trip_point_config: selects and configures a trip-point of interest * @reading_get: gets the current value of the sensor */ struct scmi_sensor_ops { @@ -177,10 +177,10 @@ struct scmi_sensor_ops { const struct scmi_sensor_info *(*info_get) (const struct scmi_handle *handle, u32 sensor_id); - int (*configuration_set)(const struct scmi_handle *handle, - u32 sensor_id); - int (*trip_point_set)(const struct scmi_handle *handle, u32 sensor_id, - u8 trip_id, u64 trip_value); + int (*trip_point_notify)(const struct scmi_handle *handle, + u32 sensor_id, bool enable); + int (*trip_point_config)(const struct scmi_handle *handle, + u32 sensor_id, u8 trip_id, u64 trip_value); int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id, bool async, u64 *value); }; -- GitLab From 37bbffcb19a7c98ed0a8c0b2dd2e11bfc05d5964 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:35 +0100 Subject: [PATCH 2628/7155] firmware: arm_scmi: Remove extra check for invalid length message responses scmi_xfer_get_init ensures both transmit and receive buffer lengths are within the maximum limits. If receive buffer length is not supplied by the caller, it's set to the maximum limit value. Receive buffer length is never modified after that. So there's no need for the extra check when receive transmit completion for a command essage. Further, if the response header length is greater than the prescribed receive buffer length, the response buffer is truncated to the latter. Reported-by: Jim Quinlan Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index b5bc4c7a8fab..6ef652940099 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -230,12 +230,6 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) xfer = &minfo->xfer_block[xfer_id]; scmi_dump_header_dbg(dev, &xfer->hdr); - /* Is the message of valid length? */ - if (xfer->rx.len > info->desc->max_msg_size) { - dev_err(dev, "unable to handle %zu xfer(max %d)\n", - xfer->rx.len, info->desc->max_msg_size); - return; - } scmi_fetch_response(xfer, mem); complete(&xfer->done); -- GitLab From c29a628976b39ecf2f9ced376ceeef8e9f6ccde0 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:38 +0100 Subject: [PATCH 2629/7155] firmware: arm_scmi: Fix few trivial typos in comments While adding new comments found couple of typos that are better fixed. s/informfation/information/ s/statues/status/ Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 6ef652940099..cac255c418b2 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -86,7 +86,7 @@ struct scmi_desc { }; /** - * struct scmi_chan_info - Structure representing a SCMI channel informfation + * struct scmi_chan_info - Structure representing a SCMI channel information * * @cl: Mailbox Client * @chan: Transmit/Receive mailbox channel @@ -190,7 +190,7 @@ static void scmi_fetch_response(struct scmi_xfer *xfer, struct scmi_shared_mem __iomem *mem) { xfer->hdr.status = ioread32(mem->msg_payload); - /* Skip the length of header and statues in payload area i.e 8 bytes*/ + /* Skip the length of header and status in payload area i.e 8 bytes */ xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8); /* Take a copy to the rx buffer.. */ -- GitLab From 5b65af8f60f580188c0be55b25cd45908024b985 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:40 +0100 Subject: [PATCH 2630/7155] firmware: arm_scmi: Use the term 'message' instead of 'command' In preparation to adding support for other two types of messages that SCMI specification mentions, let's replace the term 'command' with the correct term 'message'. As per the specification the messages are of 3 types: commands(synchronous or asynchronous), delayed responses and notifications. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 10 +++++----- drivers/firmware/arm_scmi/driver.c | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 44fd4f9404a9..a9eee62c7142 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -48,11 +48,11 @@ struct scmi_msg_resp_prot_version { /** * struct scmi_msg_hdr - Message(Tx/Rx) header * - * @id: The identifier of the command being sent - * @protocol_id: The identifier of the protocol used to send @id command - * @seq: The token to identify the message. when a message/command returns, - * the platform returns the whole message header unmodified including - * the token + * @id: The identifier of the message being sent + * @protocol_id: The identifier of the protocol used to send @id message + * @seq: The token to identify the message. When a message returns, the + * platform returns the whole message header unmodified including the + * token * @status: Status of the transfer once it's complete * @poll_completion: Indicate if the transfer needs to be polled for * completion or interrupt mode is used diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index cac255c418b2..69bf85fea967 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -182,7 +182,7 @@ static inline int scmi_to_linux_errno(int errno) static inline void scmi_dump_header_dbg(struct device *dev, struct scmi_msg_hdr *hdr) { - dev_dbg(dev, "Command ID: %x Sequence ID: %x Protocol: %x\n", + dev_dbg(dev, "Message ID: %x Sequence ID: %x Protocol: %x\n", hdr->id, hdr->seq, hdr->protocol_id); } @@ -241,7 +241,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) * @hdr: pointer to header containing all the information on message id, * protocol id and sequence id. * - * Return: 32-bit packed command header to be sent to the platform. + * Return: 32-bit packed message header to be sent to the platform. */ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr) { @@ -280,7 +280,7 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m) * * @handle: Pointer to SCMI entity handle * - * Helper function which is used by various command functions that are + * Helper function which is used by various message functions that are * exposed to clients of this driver for allocating a message traffic event. * * This function can sleep depending on pending requests already in the system -- GitLab From 9dc34d635c67e57051853855c43249408641a5ab Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 15:48:36 +0100 Subject: [PATCH 2631/7155] firmware: arm_scmi: Check if platform has released shmem before using Sometimes platfom may take too long to respond to the command and OS might timeout before platform transfer the ownership of the shared memory region to the OS with the response. Since the mailbox channel associated with the channel is freed and new commands are dispatch on the same channel, OS needs to wait until it gets back the ownership. If not, either OS may end up overwriting the platform response for the last command(which is fine as OS timed out that command) or platform might overwrite the payload for the next command with the response for the old. The latter is problematic as platform may end up interpretting the response as the payload. In order to avoid such race, let's wait until the OS gets back the ownership before we prepare the shared memory with the payload for the next command. Reported-by: Jim Quinlan Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 69bf85fea967..ccbe34da801a 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -265,6 +265,14 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m) struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); struct scmi_shared_mem __iomem *mem = cinfo->payload; + /* + * Ideally channel must be free by now unless OS timeout last + * request and platform continued to process the same, wait + * until it releases the shared memory, otherwise we may endup + * overwriting its response with new message payload or vice-versa + */ + spin_until_cond(ioread32(&mem->channel_status) & + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); /* Mark channel busy + clear error */ iowrite32(0x0, &mem->channel_status); iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED, -- GitLab From 2747a967c85d1745c497599c632f1319a58aed5f Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:42 +0100 Subject: [PATCH 2632/7155] firmware: arm_scmi: Reorder some functions to avoid forward declarations Re-shuffling few functions to keep definitions and their usages close. This is also needed to avoid too many unnecessary forward declarations while adding new features(delayed response and notifications). Keeping this separate to avoid mixing up of these trivial change that doesn't affect functionality into the ones that does. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 180 ++++++++++++++--------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index ccbe34da801a..8bd350b1e108 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -197,44 +197,6 @@ static void scmi_fetch_response(struct scmi_xfer *xfer, memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len); } -/** - * scmi_rx_callback() - mailbox client callback for receive messages - * - * @cl: client pointer - * @m: mailbox message - * - * Processes one received message to appropriate transfer information and - * signals completion of the transfer. - * - * NOTE: This function will be invoked in IRQ context, hence should be - * as optimal as possible. - */ -static void scmi_rx_callback(struct mbox_client *cl, void *m) -{ - u16 xfer_id; - struct scmi_xfer *xfer; - struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); - struct device *dev = cinfo->dev; - struct scmi_info *info = handle_to_scmi_info(cinfo->handle); - struct scmi_xfers_info *minfo = &info->minfo; - struct scmi_shared_mem __iomem *mem = cinfo->payload; - - xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header)); - - /* Are we even expecting this? */ - if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { - dev_err(dev, "message for %d is not expected!\n", xfer_id); - return; - } - - xfer = &minfo->xfer_block[xfer_id]; - - scmi_dump_header_dbg(dev, &xfer->hdr); - - scmi_fetch_response(xfer, mem); - complete(&xfer->done); -} - /** * pack_scmi_header() - packs and returns 32-bit header * @@ -349,6 +311,44 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) spin_unlock_irqrestore(&minfo->xfer_lock, flags); } +/** + * scmi_rx_callback() - mailbox client callback for receive messages + * + * @cl: client pointer + * @m: mailbox message + * + * Processes one received message to appropriate transfer information and + * signals completion of the transfer. + * + * NOTE: This function will be invoked in IRQ context, hence should be + * as optimal as possible. + */ +static void scmi_rx_callback(struct mbox_client *cl, void *m) +{ + u16 xfer_id; + struct scmi_xfer *xfer; + struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); + struct device *dev = cinfo->dev; + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); + struct scmi_xfers_info *minfo = &info->minfo; + struct scmi_shared_mem __iomem *mem = cinfo->payload; + + xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header)); + + /* Are we even expecting this? */ + if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { + dev_err(dev, "message for %d is not expected!\n", xfer_id); + return; + } + + xfer = &minfo->xfer_block[xfer_id]; + + scmi_dump_header_dbg(dev, &xfer->hdr); + + scmi_fetch_response(xfer, mem); + complete(&xfer->done); +} + static bool scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) { @@ -599,20 +599,6 @@ int scmi_handle_put(const struct scmi_handle *handle) return 0; } -static const struct scmi_desc scmi_generic_desc = { - .max_rx_timeout_ms = 30, /* We may increase this if required */ - .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ - .max_msg_size = 128, -}; - -/* Each compatible listed below must have descriptor associated with it */ -static const struct of_device_id scmi_of_match[] = { - { .compatible = "arm,scmi", .data = &scmi_generic_desc }, - { /* Sentinel */ }, -}; - -MODULE_DEVICE_TABLE(of, scmi_of_match); - static int scmi_xfer_info_init(struct scmi_info *sinfo) { int i; @@ -659,44 +645,6 @@ static int scmi_mailbox_check(struct device_node *np) return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL); } -static int scmi_mbox_free_channel(int id, void *p, void *data) -{ - struct scmi_chan_info *cinfo = p; - struct idr *idr = data; - - if (!IS_ERR_OR_NULL(cinfo->chan)) { - mbox_free_channel(cinfo->chan); - cinfo->chan = NULL; - } - - idr_remove(idr, id); - - return 0; -} - -static int scmi_remove(struct platform_device *pdev) -{ - int ret = 0; - struct scmi_info *info = platform_get_drvdata(pdev); - struct idr *idr = &info->tx_idr; - - mutex_lock(&scmi_list_mutex); - if (info->users) - ret = -EBUSY; - else - list_del(&info->node); - mutex_unlock(&scmi_list_mutex); - - if (ret) - return ret; - - /* Safe to free channels since no more users */ - ret = idr_for_each(idr, scmi_mbox_free_channel, idr); - idr_destroy(&info->tx_idr); - - return ret; -} - static inline int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id) { @@ -856,6 +804,58 @@ static int scmi_probe(struct platform_device *pdev) return 0; } +static int scmi_mbox_free_channel(int id, void *p, void *data) +{ + struct scmi_chan_info *cinfo = p; + struct idr *idr = data; + + if (!IS_ERR_OR_NULL(cinfo->chan)) { + mbox_free_channel(cinfo->chan); + cinfo->chan = NULL; + } + + idr_remove(idr, id); + + return 0; +} + +static int scmi_remove(struct platform_device *pdev) +{ + int ret = 0; + struct scmi_info *info = platform_get_drvdata(pdev); + struct idr *idr = &info->tx_idr; + + mutex_lock(&scmi_list_mutex); + if (info->users) + ret = -EBUSY; + else + list_del(&info->node); + mutex_unlock(&scmi_list_mutex); + + if (ret) + return ret; + + /* Safe to free channels since no more users */ + ret = idr_for_each(idr, scmi_mbox_free_channel, idr); + idr_destroy(&info->tx_idr); + + return ret; +} + +static const struct scmi_desc scmi_generic_desc = { + .max_rx_timeout_ms = 30, /* We may increase this if required */ + .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ + .max_msg_size = 128, +}; + +/* Each compatible listed below must have descriptor associated with it */ +static const struct of_device_id scmi_of_match[] = { + { .compatible = "arm,scmi", .data = &scmi_generic_desc }, + { /* Sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, scmi_of_match); + static struct platform_driver scmi_driver = { .driver = { .name = "arm-scmi", -- GitLab From 3748daf7fb6b5459c7a62d4976b9698b82ee9b48 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:44 +0100 Subject: [PATCH 2633/7155] firmware: arm_scmi: Segregate tx channel handling and prepare to add rx The transmit(Tx) channels are specified as the first entry and the receive(Rx) channels are the second entry as per the device tree bindings. Since we currently just support Tx, index 0 is hardcoded at all required callsites. In order to prepare for adding Rx support, let's remove those hardcoded index and add boolean parameter to identify Tx/Rx channels when setting them up. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 41 +++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 8bd350b1e108..08787aed5519 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -112,7 +112,7 @@ struct scmi_chan_info { * @version: SCMI revision information containing protocol version, * implementation version and (sub-)vendor identification. * @minfo: Message info - * @tx_idr: IDR object to map protocol id to channel info pointer + * @tx_idr: IDR object to map protocol id to Tx channel info pointer * @protocols_imp: List of protocols implemented, currently maximum of * MAX_PROTOCOLS_IMP elements allocated by the base protocol * @node: List head @@ -640,22 +640,27 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) return 0; } -static int scmi_mailbox_check(struct device_node *np) +static int scmi_mailbox_check(struct device_node *np, int idx) { - return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL); + return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", + idx, NULL); } -static inline int -scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id) +static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, + int prot_id, bool tx) { - int ret; + int ret, idx; struct resource res; resource_size_t size; struct device_node *shmem, *np = dev->of_node; struct scmi_chan_info *cinfo; struct mbox_client *cl; + const char *desc = tx ? "Tx" : "Rx"; + + /* Transmit channel is first entry i.e. index 0 */ + idx = tx ? 0 : 1; - if (scmi_mailbox_check(np)) { + if (scmi_mailbox_check(np, idx)) { cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE); goto idr_alloc; } @@ -669,31 +674,31 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id) cl = &cinfo->cl; cl->dev = dev; cl->rx_callback = scmi_rx_callback; - cl->tx_prepare = scmi_tx_prepare; + cl->tx_prepare = tx ? scmi_tx_prepare : NULL; cl->tx_block = false; - cl->knows_txdone = true; + cl->knows_txdone = tx; - shmem = of_parse_phandle(np, "shmem", 0); + shmem = of_parse_phandle(np, "shmem", idx); ret = of_address_to_resource(shmem, 0, &res); of_node_put(shmem); if (ret) { - dev_err(dev, "failed to get SCMI Tx payload mem resource\n"); + dev_err(dev, "failed to get SCMI %s payload memory\n", desc); return ret; } size = resource_size(&res); cinfo->payload = devm_ioremap(info->dev, res.start, size); if (!cinfo->payload) { - dev_err(dev, "failed to ioremap SCMI Tx payload\n"); + dev_err(dev, "failed to ioremap SCMI %s payload\n", desc); return -EADDRNOTAVAIL; } - /* Transmit channel is first entry i.e. index 0 */ - cinfo->chan = mbox_request_channel(cl, 0); + cinfo->chan = mbox_request_channel(cl, idx); if (IS_ERR(cinfo->chan)) { ret = PTR_ERR(cinfo->chan); if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to request SCMI Tx mailbox\n"); + dev_err(dev, "failed to request SCMI %s mailbox\n", + desc); return ret; } @@ -721,7 +726,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, return; } - if (scmi_mbox_chan_setup(info, &sdev->dev, prot_id)) { + if (scmi_mbox_chan_setup(info, &sdev->dev, prot_id, true)) { dev_err(&sdev->dev, "failed to setup transport\n"); scmi_device_destroy(sdev); return; @@ -741,7 +746,7 @@ static int scmi_probe(struct platform_device *pdev) struct device_node *child, *np = dev->of_node; /* Only mailbox method supported, check for the presence of one */ - if (scmi_mailbox_check(np)) { + if (scmi_mailbox_check(np, 0)) { dev_err(dev, "no mailbox found in %pOF\n", np); return -EINVAL; } @@ -769,7 +774,7 @@ static int scmi_probe(struct platform_device *pdev) handle->dev = info->dev; handle->version = &info->version; - ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE); + ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE, true); if (ret) return ret; -- GitLab From 46cc7c286ce33f729055f28c114d84e6340c08dd Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:46 +0100 Subject: [PATCH 2634/7155] firmware: arm_scmi: Add receive channel support for notifications With scmi_mbox_chan_setup enabled to identify and setup both Tx and Rx, let's consolidate setting up of both the channels under the function scmi_mbox_txrx_setup. Since some platforms may opt not to support notifications or delayed response, they may not need support for Rx. Hence Rx is optional and failure of setting one up is not considered fatal. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 08787aed5519..2d5aaff5e3ec 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -113,6 +113,7 @@ struct scmi_chan_info { * implementation version and (sub-)vendor identification. * @minfo: Message info * @tx_idr: IDR object to map protocol id to Tx channel info pointer + * @rx_idr: IDR object to map protocol id to Rx channel info pointer * @protocols_imp: List of protocols implemented, currently maximum of * MAX_PROTOCOLS_IMP elements allocated by the base protocol * @node: List head @@ -125,6 +126,7 @@ struct scmi_info { struct scmi_handle handle; struct scmi_xfers_info minfo; struct idr tx_idr; + struct idr rx_idr; u8 *protocols_imp; struct list_head node; int users; @@ -655,13 +657,17 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, struct device_node *shmem, *np = dev->of_node; struct scmi_chan_info *cinfo; struct mbox_client *cl; + struct idr *idr; const char *desc = tx ? "Tx" : "Rx"; /* Transmit channel is first entry i.e. index 0 */ idx = tx ? 0 : 1; + idr = tx ? &info->tx_idr : &info->rx_idr; if (scmi_mailbox_check(np, idx)) { - cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE); + cinfo = idr_find(idr, SCMI_PROTOCOL_BASE); + if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ + return -EINVAL; goto idr_alloc; } @@ -703,7 +709,7 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, } idr_alloc: - ret = idr_alloc(&info->tx_idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); + ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); if (ret != prot_id) { dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret); return ret; @@ -713,6 +719,17 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, return 0; } +static inline int +scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) +{ + int ret = scmi_mbox_chan_setup(info, dev, prot_id, true); + + if (!ret) /* Rx is optional, hence no error check */ + scmi_mbox_chan_setup(info, dev, prot_id, false); + + return ret; +} + static inline void scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, int prot_id) @@ -726,7 +743,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, return; } - if (scmi_mbox_chan_setup(info, &sdev->dev, prot_id, true)) { + if (scmi_mbox_txrx_setup(info, &sdev->dev, prot_id)) { dev_err(&sdev->dev, "failed to setup transport\n"); scmi_device_destroy(sdev); return; @@ -769,12 +786,13 @@ static int scmi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); idr_init(&info->tx_idr); + idr_init(&info->rx_idr); handle = &info->handle; handle->dev = info->dev; handle->version = &info->version; - ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE, true); + ret = scmi_mbox_txrx_setup(info, dev, SCMI_PROTOCOL_BASE); if (ret) return ret; @@ -844,6 +862,10 @@ static int scmi_remove(struct platform_device *pdev) ret = idr_for_each(idr, scmi_mbox_free_channel, idr); idr_destroy(&info->tx_idr); + idr = &info->rx_idr; + ret = idr_for_each(idr, scmi_mbox_free_channel, idr); + idr_destroy(&info->rx_idr); + return ret; } -- GitLab From 38c927fbebb3d69c561ae77600f64bb1c308d0c2 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:48 +0100 Subject: [PATCH 2635/7155] firmware: arm_scmi: Separate out tx buffer handling and prepare to add rx Currently we pre-allocate transmit buffers only and use the first free slot in that pre-allocated buffer for transmitting any new message that are generally originated from OS to the platform firmware. Notifications or the delayed responses on the other hand are originated from the platform firmware and consumes by the OS. It's better to have separate and dedicated pre-allocated buffers to handle the notifications. We can still use the transmit buffers for the delayed responses. In addition, let's prepare existing scmi_xfer_{get,put} for acquiring and releasing a slot to identify the right(tx/rx) buffers. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 40 ++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 2d5aaff5e3ec..989e59f3d141 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -111,7 +111,7 @@ struct scmi_chan_info { * @handle: Instance of SCMI handle to send to clients * @version: SCMI revision information containing protocol version, * implementation version and (sub-)vendor identification. - * @minfo: Message info + * @tx_minfo: Universal Transmit Message management info * @tx_idr: IDR object to map protocol id to Tx channel info pointer * @rx_idr: IDR object to map protocol id to Rx channel info pointer * @protocols_imp: List of protocols implemented, currently maximum of @@ -124,7 +124,7 @@ struct scmi_info { const struct scmi_desc *desc; struct scmi_revision_info version; struct scmi_handle handle; - struct scmi_xfers_info minfo; + struct scmi_xfers_info tx_minfo; struct idr tx_idr; struct idr rx_idr; u8 *protocols_imp; @@ -251,6 +251,7 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m) * scmi_xfer_get() - Allocate one message * * @handle: Pointer to SCMI entity handle + * @minfo: Pointer to Tx/Rx Message management info based on channel type * * Helper function which is used by various message functions that are * exposed to clients of this driver for allocating a message traffic event. @@ -261,13 +262,13 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m) * * Return: 0 if all went fine, else corresponding error. */ -static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle) +static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle, + struct scmi_xfers_info *minfo) { u16 xfer_id; struct scmi_xfer *xfer; unsigned long flags, bit_pos; struct scmi_info *info = handle_to_scmi_info(handle); - struct scmi_xfers_info *minfo = &info->minfo; /* Keep the locked section as small as possible */ spin_lock_irqsave(&minfo->xfer_lock, flags); @@ -290,18 +291,17 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle) } /** - * scmi_xfer_put() - Release a message + * __scmi_xfer_put() - Release a message * - * @handle: Pointer to SCMI entity handle + * @minfo: Pointer to Tx/Rx Message management info based on channel type * @xfer: message that was reserved by scmi_xfer_get * * This holds a spinlock to maintain integrity of internal data structures. */ -void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) +static void +__scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) { unsigned long flags; - struct scmi_info *info = handle_to_scmi_info(handle); - struct scmi_xfers_info *minfo = &info->minfo; /* * Keep the locked section as small as possible @@ -332,7 +332,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); struct device *dev = cinfo->dev; struct scmi_info *info = handle_to_scmi_info(cinfo->handle); - struct scmi_xfers_info *minfo = &info->minfo; + struct scmi_xfers_info *minfo = &info->tx_minfo; struct scmi_shared_mem __iomem *mem = cinfo->payload; xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header)); @@ -351,6 +351,19 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) complete(&xfer->done); } +/** + * scmi_xfer_put() - Release a transmit message + * + * @handle: Pointer to SCMI entity handle + * @xfer: message that was reserved by scmi_xfer_get + */ +void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + + __scmi_xfer_put(&info->tx_minfo, xfer); +} + static bool scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) { @@ -440,7 +453,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) } /** - * scmi_xfer_get_init() - Allocate and initialise one message + * scmi_xfer_get_init() - Allocate and initialise one message for transmit * * @handle: Pointer to SCMI entity handle * @msg_id: Message identifier @@ -461,6 +474,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id, int ret; struct scmi_xfer *xfer; struct scmi_info *info = handle_to_scmi_info(handle); + struct scmi_xfers_info *minfo = &info->tx_minfo; struct device *dev = info->dev; /* Ensure we have sane transfer sizes */ @@ -468,7 +482,7 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id, tx_size > info->desc->max_msg_size) return -ERANGE; - xfer = scmi_xfer_get(handle); + xfer = scmi_xfer_get(handle, minfo); if (IS_ERR(xfer)) { ret = PTR_ERR(xfer); dev_err(dev, "failed to get free message slot(%d)\n", ret); @@ -607,7 +621,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) struct scmi_xfer *xfer; struct device *dev = sinfo->dev; const struct scmi_desc *desc = sinfo->desc; - struct scmi_xfers_info *info = &sinfo->minfo; + struct scmi_xfers_info *info = &sinfo->tx_minfo; /* Pre-allocated messages, no more than what hdr.seq can support */ if (WARN_ON(desc->max_msg >= MSG_TOKEN_MAX)) { -- GitLab From 22d1f76109f74b716a5f4d46bade61f544f40f81 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:52 +0100 Subject: [PATCH 2636/7155] firmware: arm_scmi: Add mechanism to unpack message headers In order to identify the message type when a response arrives, we need a mechanism to unpack the message header similar to packing. Let's add one. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 989e59f3d141..835a1d9e2b9a 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -30,8 +30,14 @@ #include "common.h" #define MSG_ID_MASK GENMASK(7, 0) +#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) #define MSG_TYPE_MASK GENMASK(9, 8) +#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr)) +#define MSG_TYPE_COMMAND 0 +#define MSG_TYPE_DELAYED_RESP 2 +#define MSG_TYPE_NOTIFICATION 3 #define MSG_PROTOCOL_ID_MASK GENMASK(17, 10) +#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr)) #define MSG_TOKEN_ID_MASK GENMASK(27, 18) #define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr)) #define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1) @@ -214,6 +220,18 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr) FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id); } +/** + * unpack_scmi_header() - unpacks and records message and protocol id + * + * @msg_hdr: 32-bit packed message header sent from the platform + * @hdr: pointer to header to fetch message and protocol id. + */ +static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) +{ + hdr->id = MSG_XTRACT_ID(msg_hdr); + hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr); +} + /** * scmi_tx_prepare() - mailbox client callback to prepare for the transfer * -- GitLab From 58ecdf03dbb9ce8f130bc1ac63fcd8f4d72f9c06 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:54 +0100 Subject: [PATCH 2637/7155] firmware: arm_scmi: Add support for asynchronous commands and delayed response Messages that are sent to platform, also known as commands and can be: 1. Synchronous commands that block the channel until the requested work has been completed. The platform responds to these commands over the same channel and hence can't be used to send another command until the previous command has completed. 2. Asynchronous commands on the other hand, the platform schedules the requested work to complete later in time and returns almost immediately freeing the channel for new commands. The response indicates the success or failure in the ability to schedule the requested work. When the work has completed, the platform sends an additional delayed response message. Using the same transmit buffer used for sending the asynchronous command even for the delayed response corresponding to it simplifies handling of the delayed response. It's the caller of asynchronous command that is responsible for allocating the completion flag that scmi driver can complete to indicate the arrival of delayed response. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 6 ++++- drivers/firmware/arm_scmi/driver.c | 43 ++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index a9eee62c7142..43884e4ceac5 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -84,17 +84,21 @@ struct scmi_msg { * @rx: Receive message, the buffer should be pre-allocated to store * message. If request-ACK protocol is used, we can reuse the same * buffer for the rx path as we use for the tx path. - * @done: completion event + * @done: command message transmit completion event + * @async: pointer to delayed response message received event completion */ struct scmi_xfer { struct scmi_msg_hdr hdr; struct scmi_msg tx; struct scmi_msg rx; struct completion done; + struct completion *async_done; }; void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer); int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer); +int scmi_do_xfer_with_response(const struct scmi_handle *h, + struct scmi_xfer *xfer); int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id, size_t tx_size, size_t rx_size, struct scmi_xfer **p); int scmi_handle_put(const struct scmi_handle *handle); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 835a1d9e2b9a..3eb0382491ce 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -345,6 +345,8 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) */ static void scmi_rx_callback(struct mbox_client *cl, void *m) { + u8 msg_type; + u32 msg_hdr; u16 xfer_id; struct scmi_xfer *xfer; struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); @@ -353,7 +355,12 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) struct scmi_xfers_info *minfo = &info->tx_minfo; struct scmi_shared_mem __iomem *mem = cinfo->payload; - xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header)); + msg_hdr = ioread32(&mem->msg_header); + msg_type = MSG_XTRACT_TYPE(msg_hdr); + xfer_id = MSG_XTRACT_TOKEN(msg_hdr); + + if (msg_type == MSG_TYPE_NOTIFICATION) + return; /* Notifications not yet supported */ /* Are we even expecting this? */ if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { @@ -366,7 +373,11 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) scmi_dump_header_dbg(dev, &xfer->hdr); scmi_fetch_response(xfer, mem); - complete(&xfer->done); + + if (msg_type == MSG_TYPE_DELAYED_RESP) + complete(xfer->async_done); + else + complete(&xfer->done); } /** @@ -470,6 +481,34 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) return ret; } +#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) + +/** + * scmi_do_xfer_with_response() - Do one transfer and wait until the delayed + * response is received + * + * @handle: Pointer to SCMI entity handle + * @xfer: Transfer to initiate and wait for response + * + * Return: -ETIMEDOUT in case of no delayed response, if transmit error, + * return corresponding error, else if all goes well, return 0. + */ +int scmi_do_xfer_with_response(const struct scmi_handle *handle, + struct scmi_xfer *xfer) +{ + int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); + DECLARE_COMPLETION_ONSTACK(async_response); + + xfer->async_done = &async_response; + + ret = scmi_do_xfer(handle, xfer); + if (!ret && !wait_for_completion_timeout(xfer->async_done, timeout)) + ret = -ETIMEDOUT; + + xfer->async_done = NULL; + return ret; +} + /** * scmi_xfer_get_init() - Allocate and initialise one message for transmit * -- GitLab From 6a55331c87d86a7406d8126ae75bdd07244a91b1 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:40:57 +0100 Subject: [PATCH 2638/7155] firmware: arm_scmi: Drop async flag in sensor_ops->reading_get SENSOR_DESCRIPTION_GET provides attributes to indicate if the sensor supports asynchronous read. Ideally we should be able to read that flag and use asynchronous reads for any sensors with that attribute set. In order to add that support, let's drop the async flag passed to sensor_ops->reading_get and dynamically switch between sync and async flags based on the attributes as provided by the firmware. Cc: linux-hwmon@vger.kernel.org Acked-by: Guenter Roeck Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/sensors.c | 4 ++-- drivers/hwmon/scmi-hwmon.c | 2 +- include/linux/scmi_protocol.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 17dbabd8a94a..1b5757c77a35 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -211,7 +211,7 @@ scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id, } static int scmi_sensor_reading_get(const struct scmi_handle *handle, - u32 sensor_id, bool async, u64 *value) + u32 sensor_id, u64 *value) { int ret; struct scmi_xfer *t; @@ -225,7 +225,7 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, sensor = t->tx.buf; sensor->id = cpu_to_le32(sensor_id); - sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0); + sensor->flags = cpu_to_le32(0); ret = scmi_do_xfer(handle, t); if (!ret) { diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index 0c93fc5ca762..8a7732c0bef3 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -72,7 +72,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, const struct scmi_handle *h = scmi_sensors->handle; sensor = *(scmi_sensors->info[type] + channel); - ret = h->sensor_ops->reading_get(h, sensor->id, false, &value); + ret = h->sensor_ops->reading_get(h, sensor->id, &value); if (ret) return ret; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 1383d47e6435..2ace5af210ad 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -182,7 +182,7 @@ struct scmi_sensor_ops { int (*trip_point_config)(const struct scmi_handle *handle, u32 sensor_id, u8 trip_id, u64 trip_value); int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id, - bool async, u64 *value); + u64 *value); }; /** -- GitLab From d09aac0eb17c6ce2b66095e1e324f60ec9dd8988 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:01 +0100 Subject: [PATCH 2639/7155] firmware: arm_scmi: Add asynchronous sensor read if it supports SENSOR_DESCRIPTION_GET provides attributes to indicate if the sensor supports asynchronous read. We can read that flag and use asynchronous reads for any sensors with that attribute set. Let's use the new scmi_do_xfer_with_response to support asynchronous sensor reads. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/sensors.c | 30 +++++++++++++++++++++-------- include/linux/scmi_protocol.h | 2 ++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 1b5757c77a35..7570308a16a0 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -136,9 +136,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, } for (cnt = 0; cnt < num_returned; cnt++) { - u32 attrh; + u32 attrh, attrl; struct scmi_sensor_info *s; + attrl = le32_to_cpu(buf->desc[cnt].attributes_low); attrh = le32_to_cpu(buf->desc[cnt].attributes_high); s = &si->sensors[desc_index + cnt]; s->id = le32_to_cpu(buf->desc[cnt].id); @@ -147,6 +148,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, /* Sign extend to a full s8 */ if (s->scale & SENSOR_SCALE_SIGN) s->scale |= SENSOR_SCALE_EXTEND; + s->async = SUPPORTS_ASYNC_READ(attrl); + s->num_trip_points = NUM_TRIP_POINTS(attrl); strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); } @@ -214,8 +217,11 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, u32 sensor_id, u64 *value) { int ret; + __le32 *pval; struct scmi_xfer *t; struct scmi_msg_sensor_reading_get *sensor; + struct sensors_info *si = handle->sensor_priv; + struct scmi_sensor_info *s = si->sensors + sensor_id; ret = scmi_xfer_get_init(handle, SENSOR_READING_GET, SCMI_PROTOCOL_SENSOR, sizeof(*sensor), @@ -223,16 +229,24 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, if (ret) return ret; + pval = t->rx.buf; sensor = t->tx.buf; sensor->id = cpu_to_le32(sensor_id); - sensor->flags = cpu_to_le32(0); - - ret = scmi_do_xfer(handle, t); - if (!ret) { - __le32 *pval = t->rx.buf; - *value = le32_to_cpu(*pval); - *value |= (u64)le32_to_cpu(*(pval + 1)) << 32; + if (s->async) { + sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC); + ret = scmi_do_xfer_with_response(handle, t); + if (!ret) { + *value = le32_to_cpu(*(pval + 1)); + *value |= (u64)le32_to_cpu(*(pval + 2)) << 32; + } + } else { + sensor->flags = cpu_to_le32(0); + ret = scmi_do_xfer(handle, t); + if (!ret) { + *value = le32_to_cpu(*pval); + *value |= (u64)le32_to_cpu(*(pval + 1)) << 32; + } } scmi_xfer_put(handle, t); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 2ace5af210ad..ae7381413f1f 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -145,6 +145,8 @@ struct scmi_sensor_info { u32 id; u8 type; s8 scale; + u8 num_trip_points; + bool async; char name[SCMI_MAX_STR_SIZE]; }; -- GitLab From d0aba11614552d43a61c3acdf36876b00060286e Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:42:22 +0100 Subject: [PATCH 2640/7155] firmware: arm_scmi: Drop config flag in clk_ops->rate_set CLOCK_PROTOCOL_ATTRIBUTES provides attributes to indicate the maximum number of pending asynchronous clock rate changes supported by the platform. If it's non-zero, then we should be able to use asynchronous clock rate set for any clocks until the maximum limit is reached. In order to add that support, let's drop the config flag passed to clk_ops->rate_set and handle the asynchronous requests dynamically. Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Stephen Boyd Signed-off-by: Sudeep Holla --- drivers/clk/clk-scmi.c | 2 +- drivers/firmware/arm_scmi/clock.c | 4 ++-- include/linux/scmi_protocol.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index a2287c770d5c..886f7c5df51a 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -69,7 +69,7 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate, { struct scmi_clk *clk = to_scmi_clk(hw); - return clk->handle->clk_ops->rate_set(clk->handle, clk->id, 0, rate); + return clk->handle->clk_ops->rate_set(clk->handle, clk->id, rate); } static int scmi_clk_enable(struct clk_hw *hw) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 0a194af92438..dd215bd11a58 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -218,7 +218,7 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value) } static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, - u32 config, u64 rate) + u64 rate) { int ret; struct scmi_xfer *t; @@ -230,7 +230,7 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, return ret; cfg = t->tx.buf; - cfg->flags = cpu_to_le32(config); + cfg->flags = cpu_to_le32(0); cfg->id = cpu_to_le32(clk_id); cfg->value_low = cpu_to_le32(rate & 0xffffffff); cfg->value_high = cpu_to_le32(rate >> 32); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index ae7381413f1f..f0f2b53a1dac 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -71,7 +71,7 @@ struct scmi_clk_ops { int (*rate_get)(const struct scmi_handle *handle, u32 clk_id, u64 *rate); int (*rate_set)(const struct scmi_handle *handle, u32 clk_id, - u32 config, u64 rate); + u64 rate); int (*enable)(const struct scmi_handle *handle, u32 clk_id); int (*disable)(const struct scmi_handle *handle, u32 clk_id); }; -- GitLab From 2bc06ffa0635e99cd4d88d6f6fe5bb4e4b9e50f1 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 14:42:16 +0100 Subject: [PATCH 2641/7155] firmware: arm_scmi: Use asynchronous CLOCK_RATE_SET when possible CLOCK_PROTOCOL_ATTRIBUTES provides attributes to indicate the maximum number of pending asynchronous clock rate changes supported by the platform. If it's non-zero, then we should be able to use asynchronous clock rate set for any clocks until the maximum limit is reached. Tracking the current count of pending asynchronous clock set rate requests, we can decide if the incoming/new request for clock set rate can be handled asynchronously or not until the maximum limit is reached. Cc: linux-clk@vger.kernel.org Reviewed-by: Stephen Boyd Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index dd215bd11a58..4a32ae1822a3 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -56,7 +56,7 @@ struct scmi_msg_resp_clock_describe_rates { struct scmi_clock_set_rate { __le32 flags; #define CLOCK_SET_ASYNC BIT(0) -#define CLOCK_SET_DELAYED BIT(1) +#define CLOCK_SET_IGNORE_RESP BIT(1) #define CLOCK_SET_ROUND_UP BIT(2) #define CLOCK_SET_ROUND_AUTO BIT(3) __le32 id; @@ -67,6 +67,7 @@ struct scmi_clock_set_rate { struct clock_info { int num_clocks; int max_async_req; + atomic_t cur_async_req; struct scmi_clock_info *clk; }; @@ -221,21 +222,33 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, u64 rate) { int ret; + u32 flags = 0; struct scmi_xfer *t; struct scmi_clock_set_rate *cfg; + struct clock_info *ci = handle->clk_priv; ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, sizeof(*cfg), 0, &t); if (ret) return ret; + if (ci->max_async_req && + atomic_inc_return(&ci->cur_async_req) < ci->max_async_req) + flags |= CLOCK_SET_ASYNC; + cfg = t->tx.buf; - cfg->flags = cpu_to_le32(0); + cfg->flags = cpu_to_le32(flags); cfg->id = cpu_to_le32(clk_id); cfg->value_low = cpu_to_le32(rate & 0xffffffff); cfg->value_high = cpu_to_le32(rate >> 32); - ret = scmi_do_xfer(handle, t); + if (flags & CLOCK_SET_ASYNC) + ret = scmi_do_xfer_with_response(handle, t); + else + ret = scmi_do_xfer(handle, t); + + if (ci->max_async_req) + atomic_dec(&ci->cur_async_req); scmi_xfer_put(handle, t); return ret; -- GitLab From aa90ac45bc88e6a8efb199e45dab5d5a6b01c3d2 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Aug 2019 13:46:27 +0100 Subject: [PATCH 2642/7155] firmware: arm_scmi: Use {get,put}_unaligned_le{32,64} accessors Instead of type-casting the {tx,rx}.buf all over the place while accessing them to read/write __le{32,64} from/to the firmware, let's use the existing {get,put}_unaligned_le{32,64} accessors to hide all the type cast ugliness. Suggested-by: Philipp Zabel Reviewed-by: Philipp Zabel Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/base.c | 2 +- drivers/firmware/arm_scmi/clock.c | 12 ++++-------- drivers/firmware/arm_scmi/common.h | 2 ++ drivers/firmware/arm_scmi/perf.c | 8 ++++---- drivers/firmware/arm_scmi/power.c | 6 +++--- drivers/firmware/arm_scmi/sensors.c | 17 ++++++----------- 6 files changed, 20 insertions(+), 27 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index 204390297f4b..f804e8af6521 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -204,7 +204,7 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle, if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(id); + put_unaligned_le32(id, t->tx.buf); ret = scmi_do_xfer(handle, t); if (!ret) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 4a32ae1822a3..32526a793f3a 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -107,7 +107,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle, if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(clk_id); + put_unaligned_le32(clk_id, t->tx.buf); attr = t->rx.buf; ret = scmi_do_xfer(handle, t); @@ -204,15 +204,11 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value) if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(clk_id); + put_unaligned_le32(clk_id, t->tx.buf); ret = scmi_do_xfer(handle, t); - if (!ret) { - __le32 *pval = t->rx.buf; - - *value = le32_to_cpu(*pval); - *value |= (u64)le32_to_cpu(*(pval + 1)) << 32; - } + if (!ret) + *value = get_unaligned_le64(t->rx.buf); scmi_xfer_put(handle, t); return ret; diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 43884e4ceac5..5237c2ff79fe 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -15,6 +15,8 @@ #include #include +#include + #define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0) #define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16) #define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x))) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 3c8ae7cc35de..95b87cd44f94 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -151,7 +151,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain, if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(domain); + put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; ret = scmi_do_xfer(handle, t); @@ -284,7 +284,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(domain); + put_unaligned_le32(domain, t->tx.buf); ret = scmi_do_xfer(handle, t); if (!ret) { @@ -333,11 +333,11 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, return ret; t->hdr.poll_completion = poll; - *(__le32 *)t->tx.buf = cpu_to_le32(domain); + put_unaligned_le32(domain, t->tx.buf); ret = scmi_do_xfer(handle, t); if (!ret) - *level = le32_to_cpu(*(__le32 *)t->rx.buf); + *level = get_unaligned_le32(t->rx.buf); scmi_xfer_put(handle, t); return ret; diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 62f3401a1f01..5abef7079c0a 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -96,7 +96,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(domain); + put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; ret = scmi_do_xfer(handle, t); @@ -147,11 +147,11 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state) if (ret) return ret; - *(__le32 *)t->tx.buf = cpu_to_le32(domain); + put_unaligned_le32(domain, t->tx.buf); ret = scmi_do_xfer(handle, t); if (!ret) - *state = le32_to_cpu(*(__le32 *)t->rx.buf); + *state = get_unaligned_le32(t->rx.buf); scmi_xfer_put(handle, t); return ret; diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 7570308a16a0..a400ea805fc2 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -120,7 +120,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, do { /* Set the number of sensors to be skipped/already read */ - *(__le32 *)t->tx.buf = cpu_to_le32(desc_index); + put_unaligned_le32(desc_index, t->tx.buf); ret = scmi_do_xfer(handle, t); if (ret) @@ -217,7 +217,6 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, u32 sensor_id, u64 *value) { int ret; - __le32 *pval; struct scmi_xfer *t; struct scmi_msg_sensor_reading_get *sensor; struct sensors_info *si = handle->sensor_priv; @@ -229,24 +228,20 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, if (ret) return ret; - pval = t->rx.buf; sensor = t->tx.buf; sensor->id = cpu_to_le32(sensor_id); if (s->async) { sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC); ret = scmi_do_xfer_with_response(handle, t); - if (!ret) { - *value = le32_to_cpu(*(pval + 1)); - *value |= (u64)le32_to_cpu(*(pval + 2)) << 32; - } + if (!ret) + *value = get_unaligned_le64((void *) + ((__le32 *)t->rx.buf + 1)); } else { sensor->flags = cpu_to_le32(0); ret = scmi_do_xfer(handle, t); - if (!ret) { - *value = le32_to_cpu(*pval); - *value |= (u64)le32_to_cpu(*(pval + 1)) << 32; - } + if (!ret) + *value = get_unaligned_le64(t->rx.buf); } scmi_xfer_put(handle, t); -- GitLab From ac8aaf348cf54a07aff8e709329ef82ecfa230cc Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:12 +0100 Subject: [PATCH 2643/7155] firmware: arm_scmi: Add discovery of SCMI v2.0 performance fastchannels SCMI v2.0 adds support for "FastChannel", a lightweight unidirectional channel that is dedicated to a single SCMI message type for controlling a specific platform resource. They do not use a message header as they are specialized for a single message. Only PERFORMANCE_LIMITS_{SET,GET} and PERFORMANCE_LEVEL_{SET,GET} commands are supported over fastchannels. As they are optional, they need to be discovered by PERFORMANCE_DESCRIBE_FASTCHANNEL command. Further {LIMIT,LEVEL}_SET commands can have optional doorbell support. Add support for discovery of these fastchannels. Cc: Ionela Voinescu Cc: Chris Redpath Cc: Quentin Perret Reviewed-by: Peng Fan Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/perf.c | 153 ++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 95b87cd44f94..b0951b175578 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -5,7 +5,9 @@ * Copyright (C) 2018 ARM Ltd. */ +#include #include +#include #include #include #include @@ -21,6 +23,7 @@ enum scmi_performance_protocol_cmd { PERF_LEVEL_GET = 0x8, PERF_NOTIFY_LIMITS = 0x9, PERF_NOTIFY_LEVEL = 0xa, + PERF_DESCRIBE_FASTCHANNEL = 0xb, }; struct scmi_opp { @@ -44,6 +47,7 @@ struct scmi_msg_resp_perf_domain_attributes { #define SUPPORTS_SET_PERF_LVL(x) ((x) & BIT(30)) #define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29)) #define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28)) +#define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27)) __le32 rate_limit_us; __le32 sustained_freq_khz; __le32 sustained_perf_level; @@ -87,17 +91,56 @@ struct scmi_msg_resp_perf_describe_levels { } opp[0]; }; +struct scmi_perf_get_fc_info { + __le32 domain; + __le32 message_id; +}; + +struct scmi_msg_resp_perf_desc_fc { + __le32 attr; +#define SUPPORTS_DOORBELL(x) ((x) & BIT(0)) +#define DOORBELL_REG_WIDTH(x) FIELD_GET(GENMASK(2, 1), (x)) + __le32 rate_limit; + __le32 chan_addr_low; + __le32 chan_addr_high; + __le32 chan_size; + __le32 db_addr_low; + __le32 db_addr_high; + __le32 db_set_lmask; + __le32 db_set_hmask; + __le32 db_preserve_lmask; + __le32 db_preserve_hmask; +}; + +struct scmi_fc_db_info { + int width; + u64 set; + u64 mask; + void __iomem *addr; +}; + +struct scmi_fc_info { + void __iomem *level_set_addr; + void __iomem *limit_set_addr; + void __iomem *level_get_addr; + void __iomem *limit_get_addr; + struct scmi_fc_db_info *level_set_db; + struct scmi_fc_db_info *limit_set_db; +}; + struct perf_dom_info { bool set_limits; bool set_perf; bool perf_limit_notify; bool perf_level_notify; + bool perf_fastchannels; u32 opp_count; u32 sustained_freq_khz; u32 sustained_perf_level; u32 mult_factor; char name[SCMI_MAX_STR_SIZE]; struct scmi_opp opp[MAX_OPPS]; + struct scmi_fc_info *fc_info; }; struct scmi_perf_info { @@ -162,6 +205,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain, dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags); dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags); + dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags); dom_info->sustained_freq_khz = le32_to_cpu(attr->sustained_freq_khz); dom_info->sustained_perf_level = @@ -250,7 +294,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, } static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, - u32 max_perf, u32 min_perf) + u32 max_perf, u32 min_perf) { int ret; struct scmi_xfer *t; @@ -273,7 +317,7 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, } static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, - u32 *max_perf, u32 *min_perf) + u32 *max_perf, u32 *min_perf) { int ret; struct scmi_xfer *t; @@ -299,7 +343,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, } static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, - u32 level, bool poll) + u32 level, bool poll) { int ret; struct scmi_xfer *t; @@ -322,7 +366,7 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, } static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, - u32 *level, bool poll) + u32 *level, bool poll) { int ret; struct scmi_xfer *t; @@ -343,6 +387,104 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, return ret; } +static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) +{ + if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4) + return true; + if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8) + return true; + return false; +} + +static void +scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain, + u32 message_id, void __iomem **p_addr, + struct scmi_fc_db_info **p_db) +{ + int ret; + u32 flags; + u64 phys_addr; + u8 size; + void __iomem *addr; + struct scmi_xfer *t; + struct scmi_fc_db_info *db; + struct scmi_perf_get_fc_info *info; + struct scmi_msg_resp_perf_desc_fc *resp; + + if (!p_addr) + return; + + ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_FASTCHANNEL, + SCMI_PROTOCOL_PERF, + sizeof(*info), sizeof(*resp), &t); + if (ret) + return; + + info = t->tx.buf; + info->domain = cpu_to_le32(domain); + info->message_id = cpu_to_le32(message_id); + + ret = scmi_do_xfer(handle, t); + if (ret) + goto err_xfer; + + resp = t->rx.buf; + flags = le32_to_cpu(resp->attr); + size = le32_to_cpu(resp->chan_size); + if (!scmi_perf_fc_size_is_valid(message_id, size)) + goto err_xfer; + + phys_addr = le32_to_cpu(resp->chan_addr_low); + phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32; + addr = devm_ioremap(handle->dev, phys_addr, size); + if (!addr) + goto err_xfer; + *p_addr = addr; + + if (p_db && SUPPORTS_DOORBELL(flags)) { + db = devm_kzalloc(handle->dev, sizeof(*db), GFP_KERNEL); + if (!db) + goto err_xfer; + + size = 1 << DOORBELL_REG_WIDTH(flags); + phys_addr = le32_to_cpu(resp->db_addr_low); + phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32; + addr = devm_ioremap(handle->dev, phys_addr, size); + if (!addr) + goto err_xfer; + + db->addr = addr; + db->width = size; + db->set = le32_to_cpu(resp->db_set_lmask); + db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32; + db->mask = le32_to_cpu(resp->db_preserve_lmask); + db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32; + *p_db = db; + } +err_xfer: + scmi_xfer_put(handle, t); +} + +static void scmi_perf_domain_init_fc(const struct scmi_handle *handle, + u32 domain, struct scmi_fc_info **p_fc) +{ + struct scmi_fc_info *fc; + + fc = devm_kzalloc(handle->dev, sizeof(*fc), GFP_KERNEL); + if (!fc) + return; + + scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_SET, + &fc->level_set_addr, &fc->level_set_db); + scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_GET, + &fc->level_get_addr, NULL); + scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_SET, + &fc->limit_set_addr, &fc->limit_set_db); + scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_GET, + &fc->limit_get_addr, NULL); + *p_fc = fc; +} + /* Device specific ops */ static int scmi_dev_domain_id(struct device *dev) { @@ -494,6 +636,9 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) scmi_perf_domain_attributes_get(handle, domain, dom); scmi_perf_describe_levels_get(handle, domain, dom); + + if (dom->perf_fastchannels) + scmi_perf_domain_init_fc(handle, domain, &dom->fc_info); } handle->perf_ops = &perf_ops; -- GitLab From 823839571d76d465c6e454495864b085d699adb5 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:17 +0100 Subject: [PATCH 2644/7155] firmware: arm_scmi: Make use SCMI v2.0 fastchannel for performance protocol SCMI v2.0 adds support for "FastChannel" which do not use a message header as they are specialized for a single message. Only PERFORMANCE_LIMITS_{SET,GET} and PERFORMANCE_LEVEL_{SET,GET} commands are supported over fastchannels. As they are optional, they need to be discovered by PERFORMANCE_DESCRIBE_FASTCHANNEL command. Further {LIMIT,LEVEL}_SET commands can have optional doorbell support. Add support for making use of these fastchannels. Cc: Ionela Voinescu Cc: Chris Redpath Cc: Quentin Perret Reviewed-by: Peng Fan Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/perf.c | 103 +++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index b0951b175578..4a8012e3cb8c 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -293,7 +294,41 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, return ret; } -static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, +#define SCMI_PERF_FC_RING_DB(w) \ +do { \ + u##w val = 0; \ + \ + if (db->mask) \ + val = ioread##w(db->addr) & db->mask; \ + iowrite##w((u##w)db->set | val, db->addr); \ +} while (0) + +static void scmi_perf_fc_ring_db(struct scmi_fc_db_info *db) +{ + if (!db || !db->addr) + return; + + if (db->width == 1) + SCMI_PERF_FC_RING_DB(8); + else if (db->width == 2) + SCMI_PERF_FC_RING_DB(16); + else if (db->width == 4) + SCMI_PERF_FC_RING_DB(32); + else /* db->width == 8 */ +#ifdef CONFIG_64BIT + SCMI_PERF_FC_RING_DB(64); +#else + { + u64 val = 0; + + if (db->mask) + val = ioread64_hi_lo(db->addr) & db->mask; + iowrite64_hi_lo(db->set, db->addr); + } +#endif +} + +static int scmi_perf_mb_limits_set(const struct scmi_handle *handle, u32 domain, u32 max_perf, u32 min_perf) { int ret; @@ -316,7 +351,23 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, return ret; } -static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, +static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, + u32 max_perf, u32 min_perf) +{ + struct scmi_perf_info *pi = handle->perf_priv; + struct perf_dom_info *dom = pi->dom_info + domain; + + if (dom->fc_info && dom->fc_info->limit_set_addr) { + iowrite32(max_perf, dom->fc_info->limit_set_addr); + iowrite32(min_perf, dom->fc_info->limit_set_addr + 4); + scmi_perf_fc_ring_db(dom->fc_info->limit_set_db); + return 0; + } + + return scmi_perf_mb_limits_set(handle, domain, max_perf, min_perf); +} + +static int scmi_perf_mb_limits_get(const struct scmi_handle *handle, u32 domain, u32 *max_perf, u32 *min_perf) { int ret; @@ -342,7 +393,22 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, return ret; } -static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, +static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, + u32 *max_perf, u32 *min_perf) +{ + struct scmi_perf_info *pi = handle->perf_priv; + struct perf_dom_info *dom = pi->dom_info + domain; + + if (dom->fc_info && dom->fc_info->limit_get_addr) { + *max_perf = ioread32(dom->fc_info->limit_get_addr); + *min_perf = ioread32(dom->fc_info->limit_get_addr + 4); + return 0; + } + + return scmi_perf_mb_limits_get(handle, domain, max_perf, min_perf); +} + +static int scmi_perf_mb_level_set(const struct scmi_handle *handle, u32 domain, u32 level, bool poll) { int ret; @@ -365,7 +431,22 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, return ret; } -static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, +static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, + u32 level, bool poll) +{ + struct scmi_perf_info *pi = handle->perf_priv; + struct perf_dom_info *dom = pi->dom_info + domain; + + if (dom->fc_info && dom->fc_info->level_set_addr) { + iowrite32(level, dom->fc_info->level_set_addr); + scmi_perf_fc_ring_db(dom->fc_info->level_set_db); + return 0; + } + + return scmi_perf_mb_level_set(handle, domain, level, poll); +} + +static int scmi_perf_mb_level_get(const struct scmi_handle *handle, u32 domain, u32 *level, bool poll) { int ret; @@ -387,6 +468,20 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, return ret; } +static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, + u32 *level, bool poll) +{ + struct scmi_perf_info *pi = handle->perf_priv; + struct perf_dom_info *dom = pi->dom_info + domain; + + if (dom->fc_info && dom->fc_info->level_get_addr) { + *level = ioread32(dom->fc_info->level_get_addr); + return 0; + } + + return scmi_perf_mb_level_get(handle, domain, level, poll); +} + static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) { if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4) -- GitLab From ae39913ce4095682d1a6e5734a5558062a59d29f Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:04 +0100 Subject: [PATCH 2645/7155] dt-bindings: arm: Extend SCMI to support new reset protocol SCMIv2.0 adds a new Reset Management Protocol to manage various reset states a given device or domain can enter. Extend the existing SCMI bindings to add reset protocol support by re-using the reset bindings for both reset providers and consumers. Cc: Philipp Zabel Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Signed-off-by: Sudeep Holla --- .../devicetree/bindings/arm/arm,scmi.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt index 317a2fc3667a..083dbf96ee00 100644 --- a/Documentation/devicetree/bindings/arm/arm,scmi.txt +++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt @@ -73,6 +73,16 @@ Required properties: as used by the firmware. Refer to platform details for your implementation for the IDs to use. +Reset signal bindings for the reset domains based on SCMI Message Protocol +------------------------------------------------------------ + +This binding for the SCMI reset domain providers uses the generic reset +signal binding[5]. + +Required properties: + - #reset-cells : Should be 1. Contains the reset domain ID value used + by SCMI commands. + SRAM and Shared Memory for SCMI ------------------------------- @@ -93,6 +103,7 @@ Required sub-node properties: [2] Documentation/devicetree/bindings/power/power_domain.txt [3] Documentation/devicetree/bindings/thermal/thermal.txt [4] Documentation/devicetree/bindings/sram/sram.txt +[5] Documentation/devicetree/bindings/reset/reset.txt Example: @@ -152,6 +163,11 @@ firmware { reg = <0x15>; #thermal-sensor-cells = <1>; }; + + scmi_reset: protocol@16 { + reg = <0x16>; + #reset-cells = <1>; + }; }; }; @@ -166,6 +182,7 @@ hdlcd@7ff60000 { reg = <0 0x7ff60000 0 0x1000>; clocks = <&scmi_clk 4>; power-domains = <&scmi_devpd 1>; + resets = <&scmi_reset 10>; }; thermal-zones { -- GitLab From 95a15d80aa0de938299acfcbc6aa6f2b16f5d7e5 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:06 +0100 Subject: [PATCH 2646/7155] firmware: arm_scmi: Add RESET protocol in SCMI v2.0 SCMIv2.0 adds a new Reset Management Protocol to manage various reset states a given device or domain can enter. Device(s) that can be collectively reset through a common reset signal constitute a reset domain for the firmware. A reset domain can be reset autonomously or explicitly through assertion and de-assertion of the signal. When autonomous reset is chosen, the firmware is responsible for taking the necessary steps to reset the domain and to subsequently bring it out of reset. When explicit reset is chosen, the caller has to specifically assert and then de-assert the reset signal by issuing two separate RESET commands. Add the basic SCMI reset infrastructure that can be used by Linux reset controller driver. Reviewed-by: Peng Fan Reviewed-by: Philipp Zabel Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/Makefile | 2 +- drivers/firmware/arm_scmi/reset.c | 231 +++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 26 ++++ 3 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/reset.c diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index c47d28d556b6..5f298f00a82e 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -2,5 +2,5 @@ obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-bus-y = bus.o scmi-driver-y = driver.o -scmi-protocols-y = base.o clock.o perf.o power.o sensors.o +scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c new file mode 100644 index 000000000000..64cc81915581 --- /dev/null +++ b/drivers/firmware/arm_scmi/reset.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Reset Protocol + * + * Copyright (C) 2019 ARM Ltd. + */ + +#include "common.h" + +enum scmi_reset_protocol_cmd { + RESET_DOMAIN_ATTRIBUTES = 0x3, + RESET = 0x4, + RESET_NOTIFY = 0x5, +}; + +enum scmi_reset_protocol_notify { + RESET_ISSUED = 0x0, +}; + +#define NUM_RESET_DOMAIN_MASK 0xffff +#define RESET_NOTIFY_ENABLE BIT(0) + +struct scmi_msg_resp_reset_domain_attributes { + __le32 attributes; +#define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31)) +#define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30)) + __le32 latency; + u8 name[SCMI_MAX_STR_SIZE]; +}; + +struct scmi_msg_reset_domain_reset { + __le32 domain_id; + __le32 flags; +#define AUTONOMOUS_RESET BIT(0) +#define EXPLICIT_RESET_ASSERT BIT(1) +#define ASYNCHRONOUS_RESET BIT(2) + __le32 reset_state; +#define ARCH_RESET_TYPE BIT(31) +#define COLD_RESET_STATE BIT(0) +#define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE) +}; + +struct reset_dom_info { + bool async_reset; + bool reset_notify; + u32 latency_us; + char name[SCMI_MAX_STR_SIZE]; +}; + +struct scmi_reset_info { + int num_domains; + struct reset_dom_info *dom_info; +}; + +static int scmi_reset_attributes_get(const struct scmi_handle *handle, + struct scmi_reset_info *pi) +{ + int ret; + struct scmi_xfer *t; + u32 attr; + + ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t); + if (ret) + return ret; + + ret = scmi_do_xfer(handle, t); + if (!ret) { + attr = get_unaligned_le32(t->rx.buf); + pi->num_domains = attr & NUM_RESET_DOMAIN_MASK; + } + + scmi_xfer_put(handle, t); + return ret; +} + +static int +scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, + struct reset_dom_info *dom_info) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_resp_reset_domain_attributes *attr; + + ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES, + SCMI_PROTOCOL_RESET, sizeof(domain), + sizeof(*attr), &t); + if (ret) + return ret; + + put_unaligned_le32(domain, t->tx.buf); + attr = t->rx.buf; + + ret = scmi_do_xfer(handle, t); + if (!ret) { + u32 attributes = le32_to_cpu(attr->attributes); + + dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes); + dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes); + dom_info->latency_us = le32_to_cpu(attr->latency); + if (dom_info->latency_us == U32_MAX) + dom_info->latency_us = 0; + strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); + } + + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_reset_num_domains_get(const struct scmi_handle *handle) +{ + struct scmi_reset_info *pi = handle->reset_priv; + + return pi->num_domains; +} + +static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) +{ + struct scmi_reset_info *pi = handle->reset_priv; + struct reset_dom_info *dom = pi->dom_info + domain; + + return dom->name; +} + +static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain) +{ + struct scmi_reset_info *pi = handle->reset_priv; + struct reset_dom_info *dom = pi->dom_info + domain; + + return dom->latency_us; +} + +static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, + u32 flags, u32 state) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_reset_domain_reset *dom; + struct scmi_reset_info *pi = handle->reset_priv; + struct reset_dom_info *rdom = pi->dom_info + domain; + + if (rdom->async_reset) + flags |= ASYNCHRONOUS_RESET; + + ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET, + sizeof(*dom), 0, &t); + if (ret) + return ret; + + dom = t->tx.buf; + dom->domain_id = cpu_to_le32(domain); + dom->flags = cpu_to_le32(flags); + dom->domain_id = cpu_to_le32(state); + + if (rdom->async_reset) + ret = scmi_do_xfer_with_response(handle, t); + else + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain) +{ + return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET, + ARCH_COLD_RESET); +} + +static int +scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain) +{ + return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT, + ARCH_COLD_RESET); +} + +static int +scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain) +{ + return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET); +} + +static struct scmi_reset_ops reset_ops = { + .num_domains_get = scmi_reset_num_domains_get, + .name_get = scmi_reset_name_get, + .latency_get = scmi_reset_latency_get, + .reset = scmi_reset_domain_reset, + .assert = scmi_reset_domain_assert, + .deassert = scmi_reset_domain_deassert, +}; + +static int scmi_reset_protocol_init(struct scmi_handle *handle) +{ + int domain; + u32 version; + struct scmi_reset_info *pinfo; + + scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version); + + dev_dbg(handle->dev, "Reset Version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); + if (!pinfo) + return -ENOMEM; + + scmi_reset_attributes_get(handle, pinfo); + + pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains, + sizeof(*pinfo->dom_info), GFP_KERNEL); + if (!pinfo->dom_info) + return -ENOMEM; + + for (domain = 0; domain < pinfo->num_domains; domain++) { + struct reset_dom_info *dom = pinfo->dom_info + domain; + + scmi_reset_domain_attributes_get(handle, domain, dom); + } + + handle->reset_ops = &reset_ops; + handle->reset_priv = pinfo; + + return 0; +} + +static int __init scmi_reset_init(void) +{ + return scmi_protocol_register(SCMI_PROTOCOL_RESET, + &scmi_reset_protocol_init); +} +subsys_initcall(scmi_reset_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index f0f2b53a1dac..881fea47c83d 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -187,6 +187,26 @@ struct scmi_sensor_ops { u64 *value); }; +/** + * struct scmi_reset_ops - represents the various operations provided + * by SCMI Reset Protocol + * + * @num_domains_get: get the count of reset domains provided by SCMI + * @name_get: gets the name of a reset domain + * @latency_get: gets the reset latency for the specified reset domain + * @reset: resets the specified reset domain + * @assert: explicitly assert reset signal of the specified reset domain + * @deassert: explicitly deassert reset signal of the specified reset domain + */ +struct scmi_reset_ops { + int (*num_domains_get)(const struct scmi_handle *handle); + char *(*name_get)(const struct scmi_handle *handle, u32 domain); + int (*latency_get)(const struct scmi_handle *handle, u32 domain); + int (*reset)(const struct scmi_handle *handle, u32 domain); + int (*assert)(const struct scmi_handle *handle, u32 domain); + int (*deassert)(const struct scmi_handle *handle, u32 domain); +}; + /** * struct scmi_handle - Handle returned to ARM SCMI clients for usage. * @@ -196,6 +216,7 @@ struct scmi_sensor_ops { * @perf_ops: pointer to set of performance protocol operations * @clk_ops: pointer to set of clock protocol operations * @sensor_ops: pointer to set of sensor protocol operations + * @reset_ops: pointer to set of reset protocol operations * @perf_priv: pointer to private data structure specific to performance * protocol(for internal use only) * @clk_priv: pointer to private data structure specific to clock @@ -204,6 +225,8 @@ struct scmi_sensor_ops { * protocol(for internal use only) * @sensor_priv: pointer to private data structure specific to sensors * protocol(for internal use only) + * @reset_priv: pointer to private data structure specific to reset + * protocol(for internal use only) */ struct scmi_handle { struct device *dev; @@ -212,11 +235,13 @@ struct scmi_handle { struct scmi_clk_ops *clk_ops; struct scmi_power_ops *power_ops; struct scmi_sensor_ops *sensor_ops; + struct scmi_reset_ops *reset_ops; /* for protocol internal use */ void *perf_priv; void *clk_priv; void *power_priv; void *sensor_priv; + void *reset_priv; }; enum scmi_std_protocol { @@ -226,6 +251,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_PERF = 0x13, SCMI_PROTOCOL_CLOCK = 0x14, SCMI_PROTOCOL_SENSOR = 0x15, + SCMI_PROTOCOL_RESET = 0x16, }; struct scmi_device { -- GitLab From c8ae9c2da1cc5d18b6d51d10160508a3dc3436bf Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Jul 2019 09:41:08 +0100 Subject: [PATCH 2647/7155] reset: Add support for resets provided by SCMI On some ARM based systems, a separate Cortex-M based System Control Processor(SCP) provides the overall power, clock, reset and system control. System Control and Management Interface(SCMI) Message Protocol is defined for the communication between the Application Cores(AP) and the SCP. Adds support for the resets provided using SCMI protocol for performing reset management of various devices present on the SoC. Various reset functionalities are achieved by the means of different ARM SCMI device operations provided by the ARM SCMI framework. Reviewed-by: Philipp Zabel Signed-off-by: Sudeep Holla --- MAINTAINERS | 1 + drivers/reset/Kconfig | 11 ++++ drivers/reset/Makefile | 1 + drivers/reset/reset-scmi.c | 124 +++++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 drivers/reset/reset-scmi.c diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..59df8f88b56d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15545,6 +15545,7 @@ F: drivers/clk/clk-sc[mp]i.c F: drivers/cpufreq/sc[mp]i-cpufreq.c F: drivers/firmware/arm_scpi.c F: drivers/firmware/arm_scmi/ +F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h SYSTEM RESET/SHUTDOWN DRIVERS diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 21efb7d39d62..4178ac11ba85 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -116,6 +116,17 @@ config RESET_QCOM_PDC to control reset signals provided by PDC for Modem, Compute, Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS. +config RESET_SCMI + tristate "Reset driver controlled via ARM SCMI interface" + depends on ARM_SCMI_PROTOCOL || COMPILE_TEST + default ARM_SCMI_PROTOCOL + help + This driver provides support for reset signal/domains that are + controlled by firmware that implements the SCMI interface. + + This driver uses SCMI Message Protocol to interact with the + firmware controlling all the reset signals. + config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 61456b8f659c..cf60ce526064 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o +obj-$(CONFIG_RESET_SCMI) += reset-scmi.o obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c new file mode 100644 index 000000000000..c6d3c8427f14 --- /dev/null +++ b/drivers/reset/reset-scmi.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM System Control and Management Interface (ARM SCMI) reset driver + * + * Copyright (C) 2019 ARM Ltd. + */ + +#include +#include +#include +#include +#include + +/** + * struct scmi_reset_data - reset controller information structure + * @rcdev: reset controller entity + * @handle: ARM SCMI handle used for communication with system controller + */ +struct scmi_reset_data { + struct reset_controller_dev rcdev; + const struct scmi_handle *handle; +}; + +#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev) +#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle) + +/** + * scmi_reset_assert() - assert device reset + * @rcdev: reset controller entity + * @id: ID of the reset to be asserted + * + * This function implements the reset driver op to assert a device's reset + * using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_handle *handle = to_scmi_handle(rcdev); + + return handle->reset_ops->assert(handle, id); +} + +/** + * scmi_reset_deassert() - deassert device reset + * @rcdev: reset controller entity + * @id: ID of the reset to be deasserted + * + * This function implements the reset driver op to deassert a device's reset + * using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_handle *handle = to_scmi_handle(rcdev); + + return handle->reset_ops->deassert(handle, id); +} + +/** + * scmi_reset_reset() - reset the device + * @rcdev: reset controller entity + * @id: ID of the reset signal to be reset(assert + deassert) + * + * This function implements the reset driver op to trigger a device's + * reset signal using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_handle *handle = to_scmi_handle(rcdev); + + return handle->reset_ops->reset(handle, id); +} + +static const struct reset_control_ops scmi_reset_ops = { + .assert = scmi_reset_assert, + .deassert = scmi_reset_deassert, + .reset = scmi_reset_reset, +}; + +static int scmi_reset_probe(struct scmi_device *sdev) +{ + struct scmi_reset_data *data; + struct device *dev = &sdev->dev; + struct device_node *np = dev->of_node; + const struct scmi_handle *handle = sdev->handle; + + if (!handle || !handle->reset_ops) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->rcdev.ops = &scmi_reset_ops; + data->rcdev.owner = THIS_MODULE; + data->rcdev.of_node = np; + data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle); + + return devm_reset_controller_register(dev, &data->rcdev); +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_RESET }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_reset_driver = { + .name = "scmi-reset", + .probe = scmi_reset_probe, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_reset_driver); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("ARM SCMI reset controller driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From bbd1b70639f785a970d998f35155c713f975e3ac Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Thu, 8 Aug 2019 15:40:06 -0500 Subject: [PATCH 2648/7155] ACPI/PPTT: Add support for ACPI 6.3 thread flag ACPI 6.3 adds a flag to the CPU node to indicate whether the given PE is a thread. Add a function to return that information for a given linux logical CPU. Signed-off-by: Jeremy Linton Reviewed-by: Sudeep Holla Reviewed-by: Robert Richter Acked-by: Rafael J. Wysocki Signed-off-by: Will Deacon --- drivers/acpi/pptt.c | 53 +++++++++++++++++++++++++++++++++++++++++++- include/linux/acpi.h | 5 +++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 1e7ac0bd0d3a..f31544d3656e 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -540,6 +540,44 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag) return retval; } +/** + * check_acpi_cpu_flag() - Determine if CPU node has a flag set + * @cpu: Kernel logical CPU number + * @rev: The minimum PPTT revision defining the flag + * @flag: The flag itself + * + * Check the node representing a CPU for a given flag. + * + * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or + * the table revision isn't new enough. + * 1, any passed flag set + * 0, flag unset + */ +static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag) +{ + struct acpi_table_header *table; + acpi_status status; + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); + struct acpi_pptt_processor *cpu_node = NULL; + int ret = -ENOENT; + + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); + if (ACPI_FAILURE(status)) { + acpi_pptt_warn_missing(); + return ret; + } + + if (table->revision >= rev) + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); + + if (cpu_node) + ret = (cpu_node->flags & flag) != 0; + + acpi_put_table(table); + + return ret; +} + /** * acpi_find_last_cache_level() - Determines the number of cache levels for a PE * @cpu: Kernel logical CPU number @@ -604,6 +642,20 @@ int cache_setup_acpi(unsigned int cpu) return status; } +/** + * acpi_pptt_cpu_is_thread() - Determine if CPU is a thread + * @cpu: Kernel logical CPU number + * + * Return: 1, a thread + * 0, not a thread + * -ENOENT ,if the PPTT doesn't exist, the CPU cannot be found or + * the table revision isn't new enough. + */ +int acpi_pptt_cpu_is_thread(unsigned int cpu) +{ + return check_acpi_cpu_flag(cpu, 2, ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD); +} + /** * find_acpi_cpu_topology() - Determine a unique topology value for a given CPU * @cpu: Kernel logical CPU number @@ -664,7 +716,6 @@ int find_acpi_cpu_cache_topology(unsigned int cpu, int level) return ret; } - /** * find_acpi_cpu_topology_package() - Determine a unique CPU package value * @cpu: Kernel logical CPU number diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9426b9aaed86..9d0e20a2ac83 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1302,11 +1302,16 @@ static inline int lpit_read_residency_count_address(u64 *address) #endif #ifdef CONFIG_ACPI_PPTT +int acpi_pptt_cpu_is_thread(unsigned int cpu); int find_acpi_cpu_topology(unsigned int cpu, int level); int find_acpi_cpu_topology_package(unsigned int cpu); int find_acpi_cpu_topology_hetero_id(unsigned int cpu); int find_acpi_cpu_cache_topology(unsigned int cpu, int level); #else +static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) +{ + return -EINVAL; +} static inline int find_acpi_cpu_topology(unsigned int cpu, int level) { return -EINVAL; -- GitLab From d3b682c49e2223f86553c9c10f7fbba073d28703 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Jun 2019 10:21:42 +0800 Subject: [PATCH 2649/7155] dt-bindings: arm: imx: Add the soc binding for i.MX8MN This patch adds the soc & board binding for i.MX8MN. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 6847c925fa49..362bf827cad1 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -215,6 +215,12 @@ properties: - fsl,imx8mm-evk # i.MX8MM EVK Board - const: fsl,imx8mm + - description: i.MX8MN based Boards + items: + - enum: + - fsl,imx8mn-ddr4-evk # i.MX8MN DDR4 EVK Board + - const: fsl,imx8mn + - description: i.MX8MQ based Boards items: - enum: -- GitLab From 73feb4d0f8f14c5102bd46ce2255ff55d3d52db7 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 2 Jul 2019 15:45:45 +0800 Subject: [PATCH 2650/7155] soc: imx-scu: Add SoC UID(unique identifier) support Add i.MX SCU SoC's UID(unique identifier) support, user can read it from sysfs: root@imx8qxpmek:~# cat /sys/devices/soc0/soc_uid 7B64280B57AC1898 Signed-off-by: Anson Huang Reviewed-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/soc/imx/soc-imx-scu.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/soc/imx/soc-imx-scu.c b/drivers/soc/imx/soc-imx-scu.c index 676f612f6488..50831ebf126a 100644 --- a/drivers/soc/imx/soc-imx-scu.c +++ b/drivers/soc/imx/soc-imx-scu.c @@ -27,6 +27,40 @@ struct imx_sc_msg_misc_get_soc_id { } data; } __packed; +struct imx_sc_msg_misc_get_soc_uid { + struct imx_sc_rpc_msg hdr; + u32 uid_low; + u32 uid_high; +} __packed; + +static ssize_t soc_uid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct imx_sc_msg_misc_get_soc_uid msg; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + u64 soc_uid; + int ret; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = IMX_SC_RPC_SVC_MISC; + hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID; + hdr->size = 1; + + ret = imx_scu_call_rpc(soc_ipc_handle, &msg, false); + if (ret) { + pr_err("%s: get soc uid failed, ret %d\n", __func__, ret); + return ret; + } + + soc_uid = msg.uid_high; + soc_uid <<= 32; + soc_uid |= msg.uid_low; + + return sprintf(buf, "%016llX\n", soc_uid); +} + +static DEVICE_ATTR_RO(soc_uid); + static int imx_scu_soc_id(void) { struct imx_sc_msg_misc_get_soc_id msg; @@ -102,6 +136,11 @@ static int imx_scu_soc_probe(struct platform_device *pdev) goto free_revision; } + ret = device_create_file(soc_device_to_device(soc_dev), + &dev_attr_soc_uid); + if (ret) + goto free_revision; + return 0; free_revision: -- GitLab From a46d14eca7b75fffe35603aa8b81df654353d80f Mon Sep 17 00:00:00 2001 From: Phil Auld Date: Thu, 1 Aug 2019 09:37:49 -0400 Subject: [PATCH 2651/7155] sched/fair: Use rq_lock/unlock in online_fair_sched_group Enabling WARN_DOUBLE_CLOCK in /sys/kernel/debug/sched_features causes warning to fire in update_rq_clock. This seems to be caused by onlining a new fair sched group not using the rq lock wrappers. [] rq->clock_update_flags & RQCF_UPDATED [] WARNING: CPU: 5 PID: 54385 at kernel/sched/core.c:210 update_rq_clock+0xec/0x150 [] Call Trace: [] online_fair_sched_group+0x53/0x100 [] cpu_cgroup_css_online+0x16/0x20 [] online_css+0x1c/0x60 [] cgroup_apply_control_enable+0x231/0x3b0 [] cgroup_mkdir+0x41b/0x530 [] kernfs_iop_mkdir+0x61/0xa0 [] vfs_mkdir+0x108/0x1a0 [] do_mkdirat+0x77/0xe0 [] do_syscall_64+0x55/0x1d0 [] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Using the wrappers in online_fair_sched_group instead of the raw locking removes this warning. [ tglx: Use rq_*lock_irq() ] Signed-off-by: Phil Auld Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Thomas Gleixner Cc: Ingo Molnar Cc: Vincent Guittot Cc: Ingo Molnar Link: https://lkml.kernel.org/r/20190801133749.11033-1-pauld@redhat.com --- kernel/sched/fair.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 19c58599e967..1054d2cf6aaa 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -10281,18 +10281,18 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) void online_fair_sched_group(struct task_group *tg) { struct sched_entity *se; + struct rq_flags rf; struct rq *rq; int i; for_each_possible_cpu(i) { rq = cpu_rq(i); se = tg->se[i]; - - raw_spin_lock_irq(&rq->lock); + rq_lock_irq(rq, &rf); update_rq_clock(rq); attach_entity_cfs_rq(se); sync_throttle(tg, i); - raw_spin_unlock_irq(&rq->lock); + rq_unlock_irq(rq, &rf); } } -- GitLab From 2e1da13fba4cb529c2c8c1d9f657690d1e853d7d Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Wed, 7 Aug 2019 15:02:58 +0200 Subject: [PATCH 2652/7155] x86/kconfig: Remove X86_DIRECT_GBPAGES dependency on !DEBUG_PAGEALLOC These days CONFIG_DEBUG_PAGEALLOC just compiles in the code that has to be enabled on boot time, or with an extra config option, and only then are the large page based direct mappings disabled. Therefore remove the config dependency, allowing 1GB direct mappings with debug_pagealloc compiled in but not enabled. Signed-off-by: Vlastimil Babka Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190807130258.22185-1-vbabka@suse.cz --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 222855cc0158..58eae28c3dd6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1503,7 +1503,7 @@ config X86_5LEVEL config X86_DIRECT_GBPAGES def_bool y - depends on X86_64 && !DEBUG_PAGEALLOC + depends on X86_64 ---help--- Certain kernel features effectively disable kernel linear 1 GB mappings (even if the CPU otherwise -- GitLab From 8afd1a99d713ccc7cf1bd509b205c3bb60cf0b90 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 9 Aug 2019 18:22:34 -0500 Subject: [PATCH 2653/7155] ASoC: Intel: sof-rt5682: add dmic dapm widget to support dmic PCM We need add DAPM MIC endpoint widget "SoC DMIC" and route, to enable DMIC PCM DAPM support. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809232236.21182-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 64db00353e18..7285474f7d65 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -309,6 +309,7 @@ static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SPK("Spk", NULL), + SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route sof_map[] = { @@ -319,6 +320,9 @@ static const struct snd_soc_dapm_route sof_map[] = { /* other jacks */ { "IN1P", NULL, "Headset Mic" }, + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, + }; static const struct snd_soc_dapm_route speaker_map[] = { -- GitLab From 8b209cdb696f49f7f5d6c1922bed435e54631ddd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 22:27:36 +0200 Subject: [PATCH 2654/7155] ASoC: remove w90x900/nuc900 platform drivers The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Acked-by: Mark Brown Link: https://lore.kernel.org/r/20190809202749.742267-9-arnd@arndb.de Signed-off-by: Mark Brown --- sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/nuc900/Kconfig | 29 --- sound/soc/nuc900/Makefile | 12 - sound/soc/nuc900/nuc900-ac97.c | 391 -------------------------------- sound/soc/nuc900/nuc900-audio.c | 73 ------ sound/soc/nuc900/nuc900-audio.h | 108 --------- sound/soc/nuc900/nuc900-pcm.c | 321 -------------------------- 8 files changed, 936 deletions(-) delete mode 100644 sound/soc/nuc900/Kconfig delete mode 100644 sound/soc/nuc900/Makefile delete mode 100644 sound/soc/nuc900/nuc900-ac97.c delete mode 100644 sound/soc/nuc900/nuc900-audio.c delete mode 100644 sound/soc/nuc900/nuc900-audio.h delete mode 100644 sound/soc/nuc900/nuc900-pcm.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index dc86e4073001..bdc305cece6e 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -51,7 +51,6 @@ source "sound/soc/dwc/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/hisilicon/Kconfig" source "sound/soc/jz4740/Kconfig" -source "sound/soc/nuc900/Kconfig" source "sound/soc/kirkwood/Kconfig" source "sound/soc/img/Kconfig" source "sound/soc/intel/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 250a0dea9294..861a21b79484 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -39,7 +39,6 @@ obj-$(CONFIG_SND_SOC) += intel/ obj-$(CONFIG_SND_SOC) += mediatek/ obj-$(CONFIG_SND_SOC) += meson/ obj-$(CONFIG_SND_SOC) += mxs/ -obj-$(CONFIG_SND_SOC) += nuc900/ obj-$(CONFIG_SND_SOC) += kirkwood/ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += qcom/ diff --git a/sound/soc/nuc900/Kconfig b/sound/soc/nuc900/Kconfig deleted file mode 100644 index e1b22fbcb159..000000000000 --- a/sound/soc/nuc900/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -## -## NUC900 series AC97 API -## -config SND_SOC_NUC900 - tristate "SoC Audio for NUC900 series" - depends on ARCH_W90X900 - select SND_SOC_NUC900_AC97 - help - This option enables support for AC97 mode on the NUC900 SoC. - -config SND_SOC_NUC900_AC97 - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - - -## -## Boards -## -config SND_SOC_NUC900EVB - tristate "NUC900 AC97 support for demo board" - depends on SND_SOC_NUC900 - select SND_SOC_NUC900_AC97 - select SND_SOC_AC97_CODEC - help - Select this option to enable audio (AC97) on the - NUC900 demoboard. diff --git a/sound/soc/nuc900/Makefile b/sound/soc/nuc900/Makefile deleted file mode 100644 index c7ba2b9549d2..000000000000 --- a/sound/soc/nuc900/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# NUC900 series audio -snd-soc-nuc900-pcm-objs := nuc900-pcm.o -snd-soc-nuc900-ac97-objs := nuc900-ac97.o - -obj-$(CONFIG_SND_SOC_NUC900) += snd-soc-nuc900-pcm.o -obj-$(CONFIG_SND_SOC_NUC900_AC97) += snd-soc-nuc900-ac97.o - -# Boards -snd-soc-nuc900-audio-objs := nuc900-audio.o - -obj-$(CONFIG_SND_SOC_NUC900EVB) += snd-soc-nuc900-audio.o diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c deleted file mode 100644 index 5f2e5c069377..000000000000 --- a/sound/soc/nuc900/nuc900-ac97.c +++ /dev/null @@ -1,391 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2009-2010 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nuc900-audio.h" - -static DEFINE_MUTEX(ac97_mutex); -struct nuc900_audio *nuc900_ac97_data; -EXPORT_SYMBOL_GPL(nuc900_ac97_data); - -static int nuc900_checkready(void) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - - if (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS0) & CODEC_READY)) - return -EPERM; - - return 0; -} - -/* AC97 controller reads codec register */ -static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long timeout = 0x10000, val; - - mutex_lock(&ac97_mutex); - - val = nuc900_checkready(); - if (val) { - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - goto out; - } - - /* set the R_WB bit and write register index */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, R_WB | reg); - - /* set the valid frame bit and valid slots */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - val |= (VALID_FRAME | SLOT1_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); - - udelay(100); - - /* polling the AC_R_FINISH */ - while (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_R_FINISH) - && --timeout) - mdelay(1); - - if (!timeout) { - dev_err(nuc900_audio->dev, "AC97 read register time out !\n"); - val = -EPERM; - goto out; - } - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0) ; - val &= ~SLOT1_VALID; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); - - if (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS1) >> 2 != reg) { - dev_err(nuc900_audio->dev, - "R_INDEX of REG_ACTL_ACIS1 not match!\n"); - } - - udelay(100); - val = (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS2) & 0xFFFF); - -out: - mutex_unlock(&ac97_mutex); - return val; -} - -/* AC97 controller writes to codec register */ -static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long tmp, timeout = 0x10000; - - mutex_lock(&ac97_mutex); - - tmp = nuc900_checkready(); - if (tmp) - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - - /* clear the R_WB bit and write register index */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, reg); - - /* write register value */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS2, val); - - /* set the valid frame bit and valid slots */ - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp |= SLOT1_VALID | SLOT2_VALID | VALID_FRAME; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - udelay(100); - - /* polling the AC_W_FINISH */ - while ((AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_W_FINISH) - && --timeout) - mdelay(1); - - if (!timeout) - dev_err(nuc900_audio->dev, "AC97 write register time out !\n"); - - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp &= ~(SLOT1_VALID | SLOT2_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - mutex_unlock(&ac97_mutex); - -} - -static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* warm reset AC 97 */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val |= AC_W_RES; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - udelay(100); - - val = nuc900_checkready(); - if (val) - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - - mutex_unlock(&ac97_mutex); -} - -static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* reset Audio Controller */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val |= ACTL_RESET_BIT; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val &= (~ACTL_RESET_BIT); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - /* reset AC-link interface */ - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val |= AC_RESET; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val &= ~AC_RESET; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - /* cold reset AC 97 */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val |= AC_C_RES; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val &= (~AC_C_RES); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - udelay(100); - - mutex_unlock(&ac97_mutex); - -} - -/* AC97 controller operations */ -static struct snd_ac97_bus_ops nuc900_ac97_ops = { - .read = nuc900_ac97_read, - .write = nuc900_ac97_write, - .reset = nuc900_ac97_cold_reset, - .warm_reset = nuc900_ac97_warm_reset, -}; - -static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - int ret; - unsigned long val, tmp; - - ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp |= (SLOT3_VALID | SLOT4_VALID | VALID_FRAME); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); - tmp |= (P_DMA_END_IRQ | P_DMA_MIDDLE_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, tmp); - val |= AC_PLAY; - } else { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); - tmp |= (R_DMA_END_IRQ | R_DMA_MIDDLE_IRQ); - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, tmp); - val |= AC_RECORD; - } - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp &= ~(SLOT3_VALID | SLOT4_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, RESET_PRSR); - val &= ~AC_PLAY; - } else { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, RESET_PRSR); - val &= ~AC_RECORD; - } - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int nuc900_ac97_probe(struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* enable unit clock */ - clk_enable(nuc900_audio->clk); - - /* enable audio controller and AC-link interface */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val |= (IIS_AC_PIN_SEL | ACLINK_EN); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); - - mutex_unlock(&ac97_mutex); - - return 0; -} - -static int nuc900_ac97_remove(struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - - clk_disable(nuc900_audio->clk); - return 0; -} - -static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = { - .trigger = nuc900_ac97_trigger, -}; - -static struct snd_soc_dai_driver nuc900_ac97_dai = { - .probe = nuc900_ac97_probe, - .remove = nuc900_ac97_remove, - .bus_control = true, - .playback = { - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 1, - .channels_max = 2, - }, - .capture = { - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &nuc900_ac97_dai_ops, -}; - -static const struct snd_soc_component_driver nuc900_ac97_component = { - .name = "nuc900-ac97", -}; - -static int nuc900_ac97_drvprobe(struct platform_device *pdev) -{ - struct nuc900_audio *nuc900_audio; - int ret; - - if (nuc900_ac97_data) - return -EBUSY; - - nuc900_audio = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_audio), - GFP_KERNEL); - if (!nuc900_audio) - return -ENOMEM; - - spin_lock_init(&nuc900_audio->lock); - - nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, - nuc900_audio->res); - if (IS_ERR(nuc900_audio->mmio)) - return PTR_ERR(nuc900_audio->mmio); - - nuc900_audio->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(nuc900_audio->clk)) { - ret = PTR_ERR(nuc900_audio->clk); - goto out; - } - - ret = platform_get_irq(pdev, 0); - if (ret < 0) - goto out; - nuc900_audio->irq_num = ret; - - nuc900_ac97_data = nuc900_audio; - - ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); - if (ret) - goto out; - - ret = devm_snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, - &nuc900_ac97_dai, 1); - if (ret) - goto out; - - /* enbale ac97 multifunction pin */ - mfp_set_groupg(nuc900_audio->dev, NULL); - - return 0; - -out: - snd_soc_set_ac97_ops(NULL); - return ret; -} - -static int nuc900_ac97_drvremove(struct platform_device *pdev) -{ - nuc900_ac97_data = NULL; - snd_soc_set_ac97_ops(NULL); - - return 0; -} - -static struct platform_driver nuc900_ac97_driver = { - .driver = { - .name = "nuc900-ac97", - }, - .probe = nuc900_ac97_drvprobe, - .remove = nuc900_ac97_drvremove, -}; - -module_platform_driver(nuc900_ac97_driver); - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("NUC900 AC97 SoC driver!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-ac97"); diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c deleted file mode 100644 index 19146690d514..000000000000 --- a/sound/soc/nuc900/nuc900-audio.c +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "nuc900-audio.h" - -SND_SOC_DAILINK_DEFS(ac97, - DAILINK_COMP_ARRAY(COMP_CPU("nuc900-ac97")), - DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("nuc900-pcm-audio"))); - -static struct snd_soc_dai_link nuc900evb_ac97_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - SND_SOC_DAILINK_REG(ac97), -}; - -static struct snd_soc_card nuc900evb_audio_machine = { - .name = "NUC900EVB_AC97", - .owner = THIS_MODULE, - .dai_link = &nuc900evb_ac97_dai, - .num_links = 1, -}; - -static struct platform_device *nuc900evb_asoc_dev; - -static int __init nuc900evb_audio_init(void) -{ - int ret; - - ret = -ENOMEM; - nuc900evb_asoc_dev = platform_device_alloc("soc-audio", -1); - if (!nuc900evb_asoc_dev) - goto out; - - /* nuc900 board audio device */ - platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); - - ret = platform_device_add(nuc900evb_asoc_dev); - - if (ret) { - platform_device_put(nuc900evb_asoc_dev); - nuc900evb_asoc_dev = NULL; - } - -out: - return ret; -} - -static void __exit nuc900evb_audio_exit(void) -{ - platform_device_unregister(nuc900evb_asoc_dev); -} - -module_init(nuc900evb_audio_init); -module_exit(nuc900evb_audio_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("NUC900 Series ASoC audio support"); -MODULE_AUTHOR("Wan ZongShun"); diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h deleted file mode 100644 index 90ffa7bbce01..000000000000 --- a/sound/soc/nuc900/nuc900-audio.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#ifndef _NUC900_AUDIO_H -#define _NUC900_AUDIO_H - -#include - -/* Audio Control Registers */ -#define ACTL_CON 0x00 -#define ACTL_RESET 0x04 -#define ACTL_RDSTB 0x08 -#define ACTL_RDST_LENGTH 0x0C -#define ACTL_RDSTC 0x10 -#define ACTL_RSR 0x14 -#define ACTL_PDSTB 0x18 -#define ACTL_PDST_LENGTH 0x1C -#define ACTL_PDSTC 0x20 -#define ACTL_PSR 0x24 -#define ACTL_IISCON 0x28 -#define ACTL_ACCON 0x2C -#define ACTL_ACOS0 0x30 -#define ACTL_ACOS1 0x34 -#define ACTL_ACOS2 0x38 -#define ACTL_ACIS0 0x3C -#define ACTL_ACIS1 0x40 -#define ACTL_ACIS2 0x44 -#define ACTL_COUNTER 0x48 - -/* bit definition of REG_ACTL_CON register */ -#define R_DMA_IRQ 0x1000 -#define T_DMA_IRQ 0x0800 -#define IIS_AC_PIN_SEL 0x0100 -#define FIFO_TH 0x0080 -#define ADC_EN 0x0010 -#define M80_EN 0x0008 -#define ACLINK_EN 0x0004 -#define IIS_EN 0x0002 - -/* bit definition of REG_ACTL_RESET register */ -#define W5691_PLAY 0x20000 -#define ACTL_RESET_BIT 0x10000 -#define RECORD_RIGHT_CHNNEL 0x08000 -#define RECORD_LEFT_CHNNEL 0x04000 -#define PLAY_RIGHT_CHNNEL 0x02000 -#define PLAY_LEFT_CHNNEL 0x01000 -#define DAC_PLAY 0x00800 -#define ADC_RECORD 0x00400 -#define M80_PLAY 0x00200 -#define AC_RECORD 0x00100 -#define AC_PLAY 0x00080 -#define IIS_RECORD 0x00040 -#define IIS_PLAY 0x00020 -#define DAC_RESET 0x00010 -#define ADC_RESET 0x00008 -#define M80_RESET 0x00004 -#define AC_RESET 0x00002 -#define IIS_RESET 0x00001 - -/* bit definition of REG_ACTL_ACCON register */ -#define AC_BCLK_PU_EN 0x20 -#define AC_R_FINISH 0x10 -#define AC_W_FINISH 0x08 -#define AC_W_RES 0x04 -#define AC_C_RES 0x02 - -/* bit definition of ACTL_RSR register */ -#define R_FIFO_EMPTY 0x04 -#define R_DMA_END_IRQ 0x02 -#define R_DMA_MIDDLE_IRQ 0x01 - -/* bit definition of ACTL_PSR register */ -#define P_FIFO_EMPTY 0x04 -#define P_DMA_END_IRQ 0x02 -#define P_DMA_MIDDLE_IRQ 0x01 - -/* bit definition of ACTL_ACOS0 register */ -#define SLOT1_VALID 0x01 -#define SLOT2_VALID 0x02 -#define SLOT3_VALID 0x04 -#define SLOT4_VALID 0x08 -#define VALID_FRAME 0x10 - -/* bit definition of ACTL_ACOS1 register */ -#define R_WB 0x80 - -#define CODEC_READY 0x10 -#define RESET_PRSR 0x00 -#define AUDIO_WRITE(addr, val) __raw_writel(val, addr) -#define AUDIO_READ(addr) __raw_readl(addr) - -struct nuc900_audio { - void __iomem *mmio; - spinlock_t lock; - unsigned long irq_num; - struct resource *res; - struct clk *clk; - struct device *dev; - -}; - -extern struct nuc900_audio *nuc900_ac97_data; - -#endif /*end _NUC900_AUDIO_H */ diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c deleted file mode 100644 index 4442a26e9502..000000000000 --- a/sound/soc/nuc900/nuc900-pcm.c +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "nuc900-audio.h" - -static const struct snd_pcm_hardware nuc900_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .buffer_bytes_max = 4*1024, - .period_bytes_min = 1*1024, - .period_bytes_max = 4*1024, - .periods_min = 1, - .periods_max = 1024, -}; - -static int nuc900_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); -} - -static void nuc900_update_dma_register(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - void __iomem *mmio_addr, *mmio_len; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mmio_addr = nuc900_audio->mmio + ACTL_PDSTB; - mmio_len = nuc900_audio->mmio + ACTL_PDST_LENGTH; - } else { - mmio_addr = nuc900_audio->mmio + ACTL_RDSTB; - mmio_len = nuc900_audio->mmio + ACTL_RDST_LENGTH; - } - - AUDIO_WRITE(mmio_addr, runtime->dma_addr); - AUDIO_WRITE(mmio_len, runtime->dma_bytes); -} - -static void nuc900_dma_start(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long val; - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val |= (T_DMA_IRQ | R_DMA_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); -} - -static void nuc900_dma_stop(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long val; - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val &= ~(T_DMA_IRQ | R_DMA_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); -} - -static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct nuc900_audio *nuc900_audio = substream->runtime->private_data; - unsigned long val; - - spin_lock(&nuc900_audio->lock); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - - if (val & R_DMA_IRQ) { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); - - if (val & R_DMA_MIDDLE_IRQ) { - val |= R_DMA_MIDDLE_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); - } - - if (val & R_DMA_END_IRQ) { - val |= R_DMA_END_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); - } - } else if (val & T_DMA_IRQ) { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); - - if (val & P_DMA_MIDDLE_IRQ) { - val |= P_DMA_MIDDLE_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); - } - - if (val & P_DMA_END_IRQ) { - val |= P_DMA_END_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); - } - } else { - dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n"); - spin_unlock(&nuc900_audio->lock); - return IRQ_HANDLED; - } - - spin_unlock(&nuc900_audio->lock); - - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static int nuc900_dma_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int nuc900_dma_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long flags, val; - int ret = 0; - - spin_lock_irqsave(&nuc900_audio->lock, flags); - - nuc900_update_dma_register(substream); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - - switch (runtime->channels) { - case 1: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); - val |= PLAY_RIGHT_CHNNEL; - } else { - val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); - val |= RECORD_RIGHT_CHNNEL; - } - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - break; - case 2: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); - else - val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&nuc900_audio->lock, flags); - return ret; -} - -static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd) -{ - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - nuc900_dma_start(substream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - nuc900_dma_stop(substream); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int nuc900_dma_getposition(struct snd_pcm_substream *substream, - dma_addr_t *src, dma_addr_t *dst) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - - if (src != NULL) - *src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC); - - if (dst != NULL) - *dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC); - - return 0; -} - -static snd_pcm_uframes_t nuc900_dma_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - dma_addr_t src, dst; - unsigned long res; - - nuc900_dma_getposition(substream, &src, &dst); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - res = dst - runtime->dma_addr; - else - res = src - runtime->dma_addr; - - return bytes_to_frames(substream->runtime, res); -} - -static int nuc900_dma_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio; - - snd_soc_set_runtime_hwparams(substream, &nuc900_pcm_hardware); - - nuc900_audio = nuc900_ac97_data; - - if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, - 0, "nuc900-dma", substream)) - return -EBUSY; - - runtime->private_data = nuc900_audio; - - return 0; -} - -static int nuc900_dma_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - - free_irq(nuc900_audio->irq_num, substream); - - return 0; -} - -static int nuc900_dma_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, - runtime->dma_addr, runtime->dma_bytes); -} - -static const struct snd_pcm_ops nuc900_dma_ops = { - .open = nuc900_dma_open, - .close = nuc900_dma_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = nuc900_dma_hw_params, - .hw_free = nuc900_dma_hw_free, - .prepare = nuc900_dma_prepare, - .trigger = nuc900_dma_trigger, - .pointer = nuc900_dma_pointer, - .mmap = nuc900_dma_mmap, -}; - -static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; - - ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 4 * 1024, (4 * 1024) - 1); - - return 0; -} - -static const struct snd_soc_component_driver nuc900_soc_component = { - .ops = &nuc900_dma_ops, - .pcm_new = nuc900_dma_new, -}; - -static int nuc900_soc_platform_probe(struct platform_device *pdev) -{ - return devm_snd_soc_register_component(&pdev->dev, &nuc900_soc_component, - NULL, 0); -} - -static struct platform_driver nuc900_pcm_driver = { - .driver = { - .name = "nuc900-pcm-audio", - }, - - .probe = nuc900_soc_platform_probe, -}; - -module_platform_driver(nuc900_pcm_driver); - -MODULE_AUTHOR("Wan ZongShun, "); -MODULE_DESCRIPTION("nuc900 Audio DMA module"); -MODULE_LICENSE("GPL"); -- GitLab From ae032156ec4142b7a1d644eba652806785de1777 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Fri, 9 Aug 2019 14:59:51 -0700 Subject: [PATCH 2655/7155] ASoC: rt5677: Revert remove superfluous set Commit 4dc057a786dc23 ("ASoC: rt5677: remove superfluous set") was an attempted code cleanup but was incorrectly tested before sent and actually breaks the interrupt since it never resets the value on each loop now. The breakage is most testable when hotwording code is added and also uses the interrupt. Signed-off-by: Curtis Malainey Link: https://lore.kernel.org/r/20190809215952.155660-1-cujomalainey@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index deaed5132dc9..c779dc3474f9 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5098,6 +5098,7 @@ static irqreturn_t rt5677_irq(int unused, void *data) goto exit; } + irq_fired = false; for (i = 0; i < RT5677_IRQ_NUM; i++) { if (reg_irq & rt5677_irq_descs[i].status_mask) { irq_fired = true; -- GitLab From 9c2806c4941641a6c75736f8c4303c89d2013cc4 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 9 Aug 2019 18:27:46 +0800 Subject: [PATCH 2656/7155] ASoC: fsl_esai: Add compatible string for imx6ull Add compatible string for imx6ull, from imx6ull platform, the issue of channel swap after xrun is fixed in hardware. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/1565346467-5769-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 5832144beb9f..a78e4ab478df 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1049,6 +1049,7 @@ static int fsl_esai_remove(struct platform_device *pdev) static const struct of_device_id fsl_esai_dt_ids[] = { { .compatible = "fsl,imx35-esai", }, { .compatible = "fsl,vf610-esai", }, + { .compatible = "fsl,imx6ull-esai", }, {} }; MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); -- GitLab From 9ea08f2a6d27b6a26d33dae5c58e4099672d6bb3 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 9 Aug 2019 18:27:47 +0800 Subject: [PATCH 2657/7155] ASoC: fsl_esai: Add new compatible string for imx6ull Add new compatible string "fsl,imx6ull-esai" in the binding document. Signed-off-by: Shengjiu Wang Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/1565346467-5769-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,esai.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index 5b9914367610..0e6e2166f76c 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -7,8 +7,11 @@ other DSPs. It has up to six transmitters and four receivers. Required properties: - - compatible : Compatible list, must contain "fsl,imx35-esai" or - "fsl,vf610-esai" + - compatible : Compatible list, should contain one of the following + compatibles: + "fsl,imx35-esai", + "fsl,vf610-esai", + "fsl,imx6ull-esai", - reg : Offset and length of the register set for the device. -- GitLab From cac974a51ebb955f3be260a9633836e1413c8672 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Fri, 9 Aug 2019 18:17:14 -0500 Subject: [PATCH 2658/7155] ASoC: SOF: topology: use set_get_data in process load Currently when loading sof process components there's a check if binary control data is associated with it. If found the data is extracted to be part of component loading and initialization. If binary data exceeds the ipc max size, loading fails with error as large message support is only implemented in set_get_data method. So make the process loading use set_get_data to enable large parameters in component initialization. Also refactor the process component loading function as it digs out 3 times almost identical information of related controls. This is redundant, looks ugly and makes it difficult to understand the mechanism. So make a function out of fetching the control data and use it in process loading. Signed-off-by: Ranjani Sridharan Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809231714.20874-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 201 +++++++++++++++++++++++++-------------- 1 file changed, 127 insertions(+), 74 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 12b7d900b9c2..9cffea142395 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -42,6 +42,13 @@ /* size of tplg abi in byte */ #define SOF_TPLG_ABI_SIZE 3 +struct sof_widget_data { + int ctrl_type; + int ipc_cmd; + struct sof_abi_hdr *pdata; + struct snd_sof_control *control; +}; + /* send pcm params ipc */ static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) { @@ -1742,51 +1749,32 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index, return ret; } -static int sof_process_load(struct snd_soc_component *scomp, int index, - struct snd_sof_widget *swidget, - struct snd_soc_tplg_dapm_widget *tw, - struct sof_ipc_comp_reply *r, - int type) +static size_t sof_get_control_data(struct snd_sof_dev *sdev, + struct snd_soc_dapm_widget *widget, + struct sof_widget_data *wdata) { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct snd_soc_tplg_private *private = &tw->priv; - struct snd_soc_dapm_widget *widget = swidget->widget; const struct snd_kcontrol_new *kc; - struct soc_bytes_ext *sbe; struct soc_mixer_control *sm; + struct soc_bytes_ext *sbe; struct soc_enum *se; - struct snd_sof_control *scontrol = NULL; - struct sof_abi_hdr *pdata = NULL; - struct sof_ipc_comp_process *process; - size_t ipc_size, ipc_data_size = 0; - int ret, i, offset = 0; - - if (type == SOF_COMP_NONE) { - dev_err(sdev->dev, "error: invalid process comp type %d\n", - type); - return -EINVAL; - } + size_t size = 0; + int i; - /* - * get possible component controls - get size of all pdata, - * then memcpy with headers - */ for (i = 0; i < widget->num_kcontrols; i++) { - kc = &widget->kcontrol_news[i]; switch (widget->dobj.widget.kcontrol_type) { case SND_SOC_TPLG_TYPE_MIXER: sm = (struct soc_mixer_control *)kc->private_value; - scontrol = sm->dobj.private; + wdata[i].control = sm->dobj.private; break; case SND_SOC_TPLG_TYPE_BYTES: sbe = (struct soc_bytes_ext *)kc->private_value; - scontrol = sbe->dobj.private; + wdata[i].control = sbe->dobj.private; break; case SND_SOC_TPLG_TYPE_ENUM: se = (struct soc_enum *)kc->private_value; - scontrol = se->dobj.private; + wdata[i].control = se->dobj.private; break; default: dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", @@ -1795,31 +1783,98 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - if (!scontrol) { + if (!wdata[i].control) { dev_err(sdev->dev, "error: no scontrol for widget %s\n", widget->name); return -EINVAL; } - /* don't include if no private data */ - pdata = scontrol->control_data->data; - if (!pdata) - continue; + wdata[i].pdata = wdata[i].control->control_data->data; + if (!wdata[i].pdata) + return -EINVAL; /* make sure data is valid - data can be updated at runtime */ - if (pdata->magic != SOF_ABI_MAGIC) - continue; + if (wdata[i].pdata->magic != SOF_ABI_MAGIC) + return -EINVAL; + + size += wdata[i].pdata->size; + + /* get data type */ + switch (wdata[i].control->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_ENUM: + case SOF_CTRL_CMD_SWITCH: + wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE; + wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; + break; + case SOF_CTRL_CMD_BINARY: + wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA; + wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET; + break; + default: + break; + } + } + + return size; +} + +static int sof_process_load(struct snd_soc_component *scomp, int index, + struct snd_sof_widget *swidget, + struct snd_soc_tplg_dapm_widget *tw, + struct sof_ipc_comp_reply *r, + int type) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_dapm_widget *widget = swidget->widget; + struct snd_soc_tplg_private *private = &tw->priv; + struct sof_ipc_comp_process *process = NULL; + struct sof_widget_data *wdata = NULL; + size_t ipc_data_size = 0; + size_t ipc_size; + int offset = 0; + int ret = 0; + int i; + + if (type == SOF_COMP_NONE) { + dev_err(sdev->dev, "error: invalid process comp type %d\n", + type); + return -EINVAL; + } + + /* allocate struct for widget control data sizes and types */ + if (widget->num_kcontrols) { + wdata = kcalloc(widget->num_kcontrols, + sizeof(*wdata), + GFP_KERNEL); + + if (!wdata) + return -ENOMEM; - ipc_data_size += pdata->size; + /* get possible component controls and get size of all pdata */ + ipc_data_size = sof_get_control_data(sdev, widget, wdata); + + if (ipc_data_size <= 0) { + ret = ipc_data_size; + goto out; + } } ipc_size = sizeof(struct sof_ipc_comp_process) + le32_to_cpu(private->size) + ipc_data_size; + /* we are exceeding max ipc size, config needs to be sent separately */ + if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { + ipc_size -= ipc_data_size; + ipc_data_size = 0; + } + process = kzalloc(ipc_size, GFP_KERNEL); - if (!process) - return -ENOMEM; + if (!process) { + ret = -ENOMEM; + goto out; + } /* configure iir IPC message */ process->comp.hdr.size = ipc_size; @@ -1845,40 +1900,13 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, * get possible component controls - get size of all pdata, * then memcpy with headers */ - for (i = 0; i < widget->num_kcontrols; i++) { - kc = &widget->kcontrol_news[i]; - - switch (widget->dobj.widget.kcontrol_type) { - case SND_SOC_TPLG_TYPE_MIXER: - sm = (struct soc_mixer_control *)kc->private_value; - scontrol = sm->dobj.private; - break; - case SND_SOC_TPLG_TYPE_BYTES: - sbe = (struct soc_bytes_ext *)kc->private_value; - scontrol = sbe->dobj.private; - break; - case SND_SOC_TPLG_TYPE_ENUM: - se = (struct soc_enum *)kc->private_value; - scontrol = se->dobj.private; - break; - default: - dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", - widget->dobj.widget.kcontrol_type, - widget->name); - return -EINVAL; + if (ipc_data_size) { + for (i = 0; i < widget->num_kcontrols; i++) { + memcpy(&process->data + offset, + wdata[i].pdata->data, + wdata[i].pdata->size); + offset += wdata[i].pdata->size; } - - /* don't include if no private data */ - pdata = scontrol->control_data->data; - if (!pdata) - continue; - - /* make sure data is valid - data can be updated at runtime */ - if (pdata->magic != SOF_ABI_MAGIC) - continue; - - memcpy(&process->data + offset, pdata->data, pdata->size); - offset += pdata->size; } process->size = ipc_data_size; @@ -1886,10 +1914,35 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, ret = sof_ipc_tx_message(sdev->ipc, process->comp.hdr.cmd, process, ipc_size, r, sizeof(*r)); - if (ret >= 0) - return ret; + + if (ret < 0) { + dev_err(sdev->dev, "error: create process failed\n"); + goto err; + } + + /* we sent the data in single message so return */ + if (ipc_data_size) + goto out; + + /* send control data with large message supported method */ + for (i = 0; i < widget->num_kcontrols; i++) { + wdata[i].control->readback_offset = 0; + ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, wdata[i].control, + wdata[i].ipc_cmd, + wdata[i].ctrl_type, + wdata[i].control->cmd, + true); + if (ret != 0) { + dev_err(sdev->dev, "error: send control failed\n"); + break; + } + } + err: - kfree(process); + if (ret < 0) + kfree(process); +out: + kfree(wdata); return ret; } -- GitLab From 872f3ac583cb00c14a4dc86b1511cf98618dd671 Mon Sep 17 00:00:00 2001 From: Szymon Mielczarek Date: Fri, 9 Aug 2019 10:40:34 +0200 Subject: [PATCH 2659/7155] ASoC: dapm: Invalidate only paths reachable for a given stream By resetting the cached number of endpoints for all card's widgets we may overwrite previously cached values for other streams. The situation may happen especially when running streams simultaneously. Signed-off-by: Szymon Mielczarek Link: https://lore.kernel.org/r/20190809084034.26220-1-szymonx.mielczarek@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 50 ++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d09bdca63c62..10819b3e0b98 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1128,6 +1128,34 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list, return 0; } +/* + * Recursively reset the cached number of inputs or outputs for the specified + * widget and all widgets that can be reached via incoming or outcoming paths + * from the widget. + */ +static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget, + enum snd_soc_dapm_direction dir) +{ + enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir); + struct snd_soc_dapm_path *path; + + widget->endpoints[dir] = -1; + + snd_soc_dapm_widget_for_each_path(widget, rdir, path) { + if (path->weak || path->is_supply) + continue; + + if (path->walking) + return; + + if (path->connect) { + path->walking = 1; + invalidate_paths_ep(path->node[dir], dir); + path->walking = 0; + } + } +} + /* * Common implementation for is_connected_output_ep() and * is_connected_input_ep(). The function is inlined since the combined size of @@ -1257,21 +1285,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - /* - * For is_connected_{output,input}_ep fully discover the graph we need - * to reset the cached number of inputs and outputs. - */ - list_for_each_entry(w, &card->widgets, list) { - w->endpoints[SND_SOC_DAPM_DIR_IN] = -1; - w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1; - } - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - paths = is_connected_output_ep(dai->playback_widget, &widgets, + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + w = dai->playback_widget; + invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT); + paths = is_connected_output_ep(w, &widgets, custom_stop_condition); - else - paths = is_connected_input_ep(dai->capture_widget, &widgets, + } else { + w = dai->capture_widget; + invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN); + paths = is_connected_input_ep(w, &widgets, custom_stop_condition); + } /* Drop starting point */ list_del(widgets.next); -- GitLab From 1a3fb5d3f420d5f022768fcff091e5a9862f5877 Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Fri, 9 Aug 2019 18:22:33 -0500 Subject: [PATCH 2660/7155] ASoC: Intel: boards: Match Product Family instead of product The generic machine driver of sof_rt5682 supports more platforms of same product family. hence match the product family instead of product name. Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809232236.21182-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index daeaa396d928..c1181bc0119e 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -91,8 +91,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { { .callback = sof_rt5682_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Google"), - DMI_MATCH(DMI_PRODUCT_NAME, "Hatch"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_RT5682_MCLK_24MHZ | -- GitLab From 0181d2853126db0717de6bd5b3287f1c87faf7c3 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 9 Aug 2019 18:22:35 -0500 Subject: [PATCH 2661/7155] ASoC: Intel: skl-hda-dsp-generic: add dependency to dmic driver The hda generic machine actually has dependency on the dmic driver, select SND_SOC_DMIC at the machine selected to fix it. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809232236.21182-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 50bf149818b5..4a529cea0190 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -387,6 +387,7 @@ if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "SKL/KBL/BXT/APL with HDA Codecs" select SND_SOC_HDAC_HDMI + select SND_SOC_DMIC # SND_SOC_HDAC_HDA is already selected help This adds support for ASoC machine driver for Intel platforms -- GitLab From 79631210fc413546d0ed73632ff904ded5192cc9 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 9 Aug 2019 18:22:36 -0500 Subject: [PATCH 2662/7155] ASoC: Intel: skl-hda-dsp-generic: add dmic dapm widget and route Adding DAPM MIC endpoint widget "SoC DMIC" and route, to enable DMIC DAPM support with hda generic machine. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190809232236.21182-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 9ed68eb4f058..1778acdc367c 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -23,6 +23,7 @@ static const struct snd_soc_dapm_widget skl_hda_widgets[] = { SND_SOC_DAPM_MIC("Alt Analog In", NULL), SND_SOC_DAPM_SPK("Digital Out", NULL), SND_SOC_DAPM_MIC("Digital In", NULL), + SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route skl_hda_map[] = { @@ -41,6 +42,9 @@ static const struct snd_soc_dapm_route skl_hda_map[] = { { "Codec Input Pin2", NULL, "Digital In" }, { "Codec Input Pin3", NULL, "Alt Analog In" }, + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, + /* CODEC BE connections */ { "Analog Codec Playback", NULL, "Analog CPU Playback" }, { "Analog CPU Playback", NULL, "codec0_out" }, -- GitLab From fba5b1e9ab527bd46bc529370d52a7b2b552dce1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 12 Aug 2019 10:24:09 +0100 Subject: [PATCH 2663/7155] regmap-irq: Correct error paths in regmap_irq_thread for pm_runtime Some error paths in regmap_irq_thread put the pm_runtime others do not, there is no reason to leave the pm_runtime enabled in some cases so update those paths to also put the pm_runtime. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190812092409.21593-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index c9dc70ceca5f..3d64c9331a82 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -370,7 +370,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) if (ret < 0) { dev_err(map->dev, "IRQ thread failed to resume: %d\n", ret); - pm_runtime_put(map->dev); goto exit; } } @@ -425,8 +424,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) dev_err(map->dev, "Failed to read IRQ status %d\n", ret); - if (chip->runtime_pm) - pm_runtime_put(map->dev); goto exit; } } @@ -478,8 +475,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) dev_err(map->dev, "Failed to read IRQ status: %d\n", ret); - if (chip->runtime_pm) - pm_runtime_put(map->dev); goto exit; } } @@ -513,10 +508,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } +exit: if (chip->runtime_pm) pm_runtime_put(map->dev); -exit: if (chip->handle_post_irq) chip->handle_post_irq(chip->irq_drv_data); -- GitLab From 52718908c3f44b939a9934ef624e68457b21704f Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 12 Aug 2019 13:13:44 +0300 Subject: [PATCH 2664/7155] spi: dw-pci: Add support for Intel Elkhart Lake PSE SPI Add support for Intel(R) Programmable Services Engine (Intel(R) PSE) SPI controller in Intel Elkhart Lake when interface is assigned to the host processor. Signed-off-by: Jarkko Nikula Link: https://lore.kernel.org/r/20190812101344.3975-1-jarkko.nikula@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 9651679ee7f7..e9ba63814548 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -19,6 +19,7 @@ struct spi_pci_desc { int (*setup)(struct dw_spi *); u16 num_cs; u16 bus_num; + u32 max_freq; }; static struct spi_pci_desc spi_pci_mid_desc_1 = { @@ -33,6 +34,12 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = { .bus_num = 1, }; +static struct spi_pci_desc spi_pci_ehl_desc = { + .num_cs = 1, + .bus_num = -1, + .max_freq = 100000000, +}; + static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dw_spi *dws; @@ -65,6 +72,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (desc) { dws->num_cs = desc->num_cs; dws->bus_num = desc->bus_num; + dws->max_freq = desc->max_freq; if (desc->setup) { ret = desc->setup(dws); @@ -125,6 +133,11 @@ static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc_1}, /* Intel MID platform SPI controller 2 */ { PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&spi_pci_mid_desc_2}, + /* Intel Elkhart Lake PSE SPI controllers */ + { PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc}, {}, }; -- GitLab From abe51c351827e0086dad079dfe02918fecdf4830 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 12 Aug 2019 12:52:25 +0300 Subject: [PATCH 2665/7155] ASoC: pcm3168a: Retain the independence of DAC and ADC side of the codec The DAC and ADC path of the codec is independent, have dedicated LRCK (FS) and BCK for DAC/ADC. They can be configured to use different format, TDM slots and slot_width if needed. Move these parameters under dedicated io_params structure and manage them independently based on the dai. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190812095226.18870-2-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 125 ++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 71 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index e84a1509fe65..75fa8e9ee894 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -44,18 +44,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { "VCCDA2" }; +#define PCM3168A_DAI_DAC 0 +#define PCM3168A_DAI_ADC 1 + +/* ADC/DAC side parameters */ +struct pcm3168a_io_params { + bool master_mode; + unsigned int fmt; + int tdm_slots; + u32 tdm_mask; + int slot_width; +}; + struct pcm3168a_priv { struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; struct regmap *regmap; struct clk *scki; - bool adc_master_mode; - bool dac_master_mode; unsigned long sysclk; - unsigned int adc_fmt; - unsigned int dac_fmt; - int tdm_slots; - u32 tdm_mask[2]; - int slot_width; + + struct pcm3168a_io_params io_params[2]; }; static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; @@ -308,8 +315,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, return 0; } -static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int format, bool dac) +static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); @@ -356,43 +362,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, return -EINVAL; } - if (dac) { + if (dai->id == PCM3168A_DAI_DAC) { reg = PCM3168A_DAC_PWR_MST_FMT; mask = PCM3168A_DAC_FMT_MASK; shift = PCM3168A_DAC_FMT_SHIFT; - pcm3168a->dac_master_mode = master_mode; - pcm3168a->dac_fmt = fmt; } else { reg = PCM3168A_ADC_MST_FMT; mask = PCM3168A_ADC_FMTAD_MASK; shift = PCM3168A_ADC_FMTAD_SHIFT; - pcm3168a->adc_master_mode = master_mode; - pcm3168a->adc_fmt = fmt; } + pcm3168a->io_params[dai->id].master_mode = master_mode; + pcm3168a->io_params[dai->id].fmt = fmt; + regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); return 0; } -static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai, - unsigned int format) -{ - return pcm3168a_set_dai_fmt(dai, format, true); -} - -static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, - unsigned int format) -{ - return pcm3168a_set_dai_fmt(dai, format, false); -} - static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); + struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; if (tx_mask >= (1<= (1<dev, @@ -408,22 +402,25 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return -EINVAL; } - if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { + if (io_params->tdm_slots && io_params->tdm_slots != slots) { dev_err(component->dev, "Not matching slots %d vs %d\n", - pcm3168a->tdm_slots, slots); + io_params->tdm_slots, slots); return -EINVAL; } - if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { + if (io_params->slot_width && io_params->slot_width != slot_width) { dev_err(component->dev, "Not matching slot_width %d vs %d\n", - pcm3168a->slot_width, slot_width); + io_params->slot_width, slot_width); return -EINVAL; } - pcm3168a->tdm_slots = slots; - pcm3168a->slot_width = slot_width; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; + io_params->tdm_slots = slots; + io_params->slot_width = slot_width; + /* Ignore the not relevant mask for the DAI/direction */ + if (dai->id == PCM3168A_DAI_DAC) + io_params->tdm_mask = tx_mask; + else + io_params->tdm_mask = rx_mask; return 0; } @@ -434,7 +431,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); - bool tx, master_mode; + struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; + bool master_mode; u32 val, mask, shift, reg; unsigned int rate, fmt, ratio, max_ratio; unsigned int tdm_slots; @@ -444,23 +442,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, ratio = pcm3168a->sysclk / rate; - tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - if (tx) { + if (dai->id == PCM3168A_DAI_DAC) { max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; reg = PCM3168A_DAC_PWR_MST_FMT; mask = PCM3168A_DAC_MSDA_MASK; shift = PCM3168A_DAC_MSDA_SHIFT; - master_mode = pcm3168a->dac_master_mode; - fmt = pcm3168a->dac_fmt; } else { max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; reg = PCM3168A_ADC_MST_FMT; mask = PCM3168A_ADC_MSAD_MASK; shift = PCM3168A_ADC_MSAD_SHIFT; - master_mode = pcm3168a->adc_master_mode; - fmt = pcm3168a->adc_fmt; } + master_mode = io_params->master_mode; + fmt = io_params->fmt; + for (i = 0; i < max_ratio; i++) { if (pcm3168a_scki_ratios[i] == ratio) break; @@ -471,8 +467,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if (pcm3168a->slot_width) - slot_width = pcm3168a->slot_width; + if (io_params->slot_width) + slot_width = io_params->slot_width; else slot_width = params_width(params); @@ -497,8 +493,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if (pcm3168a->tdm_slots) - tdm_slots = pcm3168a->tdm_slots; + if (io_params->tdm_slots) + tdm_slots = io_params->tdm_slots; else tdm_slots = params_channels(params); @@ -534,7 +530,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(pcm3168a->regmap, reg, mask, val); - if (tx) { + if (dai->id == PCM3168A_DAI_DAC) { mask = PCM3168A_DAC_FMT_MASK; shift = PCM3168A_DAC_FMT_SHIFT; } else { @@ -552,20 +548,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); - bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int fmt; unsigned int sample_min; unsigned int channel_max; unsigned int channel_maxs[] = { - 6, /* rx */ - 8 /* tx */ + 8, /* DAC */ + 6 /* ADC */ }; - if (tx) - fmt = pcm3168a->dac_fmt; - else - fmt = pcm3168a->adc_fmt; - /* * Available Data Bits * @@ -578,7 +567,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, * I2S * LEFT_J */ - switch (fmt) { + switch (pcm3168a->io_params[dai->id].fmt) { case PCM3168A_FMT_RIGHT_J: sample_min = 16; channel_max = 2; @@ -588,7 +577,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, case PCM3168A_FMT_DSP_A: case PCM3168A_FMT_DSP_B: sample_min = 24; - channel_max = channel_maxs[tx]; + channel_max = channel_maxs[dai->id]; break; default: sample_min = 24; @@ -600,8 +589,8 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, sample_min, 32); /* Allow all channels in multi DIN/DOUT mode */ - if (pcm3168a->tdm_slots == 2) - channel_max = channel_maxs[tx]; + if (pcm3168a->io_params[dai->id].tdm_slots == 2) + channel_max = channel_maxs[dai->id]; snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_CHANNELS, @@ -609,26 +598,19 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, return 0; } -static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { +static const struct snd_soc_dai_ops pcm3168a_dai_ops = { .startup = pcm3168a_startup, - .set_fmt = pcm3168a_set_dai_fmt_dac, + .set_fmt = pcm3168a_set_dai_fmt, .set_sysclk = pcm3168a_set_dai_sysclk, .hw_params = pcm3168a_hw_params, .digital_mute = pcm3168a_digital_mute, .set_tdm_slot = pcm3168a_set_tdm_slot, }; -static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { - .startup = pcm3168a_startup, - .set_fmt = pcm3168a_set_dai_fmt_adc, - .set_sysclk = pcm3168a_set_dai_sysclk, - .hw_params = pcm3168a_hw_params, - .set_tdm_slot = pcm3168a_set_tdm_slot, -}; - static struct snd_soc_dai_driver pcm3168a_dais[] = { { .name = "pcm3168a-dac", + .id = PCM3168A_DAI_DAC, .playback = { .stream_name = "Playback", .channels_min = 1, @@ -636,10 +618,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = PCM3168A_FORMATS }, - .ops = &pcm3168a_dac_dai_ops + .ops = &pcm3168a_dai_ops }, { .name = "pcm3168a-adc", + .id = PCM3168A_DAI_ADC, .capture = { .stream_name = "Capture", .channels_min = 1, @@ -647,7 +630,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { .rates = SNDRV_PCM_RATE_8000_96000, .formats = PCM3168A_FORMATS }, - .ops = &pcm3168a_adc_dai_ops + .ops = &pcm3168a_dai_ops }, }; -- GitLab From 6fa4e0cae684d268d309d1b1f929d52e3df5649c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 12 Aug 2019 12:52:26 +0300 Subject: [PATCH 2666/7155] ASoC: pcm3168a: Allow reconfiguration of tdm_slots and slot_width When using right_j format and the codec is slave it can support 16bit format, but only if slot_width == 16, in the same DAI mode the 24 bit audio can work with 24 or 32 slot_width. Because of this, the codec and CPU needs to be reconfigured when the sample format changes. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190812095226.18870-3-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 75fa8e9ee894..50ed86d45c26 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -402,18 +402,6 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return -EINVAL; } - if (io_params->tdm_slots && io_params->tdm_slots != slots) { - dev_err(component->dev, "Not matching slots %d vs %d\n", - io_params->tdm_slots, slots); - return -EINVAL; - } - - if (io_params->slot_width && io_params->slot_width != slot_width) { - dev_err(component->dev, "Not matching slot_width %d vs %d\n", - io_params->slot_width, slot_width); - return -EINVAL; - } - io_params->tdm_slots = slots; io_params->slot_width = slot_width; /* Ignore the not relevant mask for the DAI/direction */ -- GitLab From ffbf23d50353915dc2622a3b7b4ddc678165f92d Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 1 Aug 2019 12:56:36 +0300 Subject: [PATCH 2667/7155] firmware: imx: Add DSP IPC protocol interface Some of i.MX8 processors (e.g i.MX8QM, i.MX8QXP) contain the Tensilica HiFi4 DSP for advanced pre- and post-audio processing. The communication between Host CPU and DSP firmware is taking place using a shared memory area for message passing and a dedicated Messaging Unit for notifications. DSP IPC protocol offers a doorbell interface using imx-mailbox API. We use 4 MU channels (2 x TXDB, 2 x RXDB) to implement a request-reply protocol. Connection 0 (txdb0, rxdb0): - Host writes messasge to shared memory [SHMEM] - Host sends a request [MU] - DSP handles request [SHMEM] - DSP sends reply [MU] Connection 1 (txdb1, rxdb1): - DSP writes a message to shared memory [SHMEM] - DSP sends a request [MU] - Host handles request [SHMEM] - Host sends reply [MU] The protocol interface will be used by a Host client to communicate with the DSP. First client will be the i.MX8 part from Sound Open Firmware infrastructure. The protocol offers the following interface: On Tx: - imx_dsp_ring_doorbell, will be called to notify the DSP that it needs to handle a request. On Rx: - clients need to provide two callbacks: .handle_reply .handle_request - the callbacks will be used by the protocol on notification arrival from DSP. Signed-off-by: Daniel Baluta Reviewed-by: Oleksij Rempel Signed-off-by: Shawn Guo --- drivers/firmware/imx/Kconfig | 11 +++ drivers/firmware/imx/Makefile | 1 + drivers/firmware/imx/imx-dsp.c | 155 +++++++++++++++++++++++++++++++ include/linux/firmware/imx/dsp.h | 67 +++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 drivers/firmware/imx/imx-dsp.c create mode 100644 include/linux/firmware/imx/dsp.h diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig index 42b566f8903f..0dbee32da4c6 100644 --- a/drivers/firmware/imx/Kconfig +++ b/drivers/firmware/imx/Kconfig @@ -1,4 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only +config IMX_DSP + bool "IMX DSP Protocol driver" + depends on IMX_MBOX + help + This enables DSP IPC protocol between host AP (Linux) + and the firmware running on DSP. + DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP). + + It acts like a doorbell. Client might use shared memory to + exchange information with DSP side. + config IMX_SCU bool "IMX SCU Protocol driver" depends on IMX_MBOX diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile index 802c4ad8e8f9..08bc9ddfbdfb 100644 --- a/drivers/firmware/imx/Makefile +++ b/drivers/firmware/imx/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_IMX_DSP) += imx-dsp.o obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c new file mode 100644 index 000000000000..a43d2db5cbdb --- /dev/null +++ b/drivers/firmware/imx/imx-dsp.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + * Author: Daniel Baluta + * + * Implementation of the DSP IPC interface (host side) + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP) + * + * @dsp: DSP IPC handle + * @chan_idx: index of the channel where to trigger the interrupt + * + * Returns non-negative value for success, negative value for error + */ +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx) +{ + int ret; + struct imx_dsp_chan *dsp_chan; + + if (idx >= DSP_MU_CHAN_NUM) + return -EINVAL; + + dsp_chan = &ipc->chans[idx]; + ret = mbox_send_message(dsp_chan->ch, NULL); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(imx_dsp_ring_doorbell); + +/* + * imx_dsp_handle_rx - rx callback used by imx mailbox + * + * @c: mbox client + * @msg: message received + * + * Users of DSP IPC will need to privde handle_reply and handle_request + * callbacks. + */ +static void imx_dsp_handle_rx(struct mbox_client *c, void *msg) +{ + struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl); + + if (chan->idx == 0) { + chan->ipc->ops->handle_reply(chan->ipc); + } else { + chan->ipc->ops->handle_request(chan->ipc); + imx_dsp_ring_doorbell(chan->ipc, 1); + } +} + +static int imx_dsp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx_dsp_ipc *dsp_ipc; + struct imx_dsp_chan *dsp_chan; + struct mbox_client *cl; + char *chan_name; + int ret; + int i, j; + + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); + + dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL); + if (!dsp_ipc) + return -ENOMEM; + + for (i = 0; i < DSP_MU_CHAN_NUM; i++) { + if (i < 2) + chan_name = kasprintf(GFP_KERNEL, "txdb%d", i); + else + chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2); + + if (!chan_name) + return -ENOMEM; + + dsp_chan = &dsp_ipc->chans[i]; + cl = &dsp_chan->cl; + cl->dev = dev; + cl->tx_block = false; + cl->knows_txdone = true; + cl->rx_callback = imx_dsp_handle_rx; + + dsp_chan->ipc = dsp_ipc; + dsp_chan->idx = i % 2; + dsp_chan->ch = mbox_request_channel_byname(cl, chan_name); + if (IS_ERR(dsp_chan->ch)) { + ret = PTR_ERR(dsp_chan->ch); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to request mbox chan %s ret %d\n", + chan_name, ret); + goto out; + } + + dev_dbg(dev, "request mbox chan %s\n", chan_name); + /* chan_name is not used anymore by framework */ + kfree(chan_name); + } + + dsp_ipc->dev = dev; + + dev_set_drvdata(dev, dsp_ipc); + + dev_info(dev, "NXP i.MX DSP IPC initialized\n"); + + return devm_of_platform_populate(dev); +out: + kfree(chan_name); + for (j = 0; j < i; j++) { + dsp_chan = &dsp_ipc->chans[j]; + mbox_free_channel(dsp_chan->ch); + } + + return ret; +} + +static int imx_dsp_remove(struct platform_device *pdev) +{ + struct imx_dsp_chan *dsp_chan; + struct imx_dsp_ipc *dsp_ipc; + int i; + + dsp_ipc = dev_get_drvdata(&pdev->dev); + + for (i = 0; i < DSP_MU_CHAN_NUM; i++) { + dsp_chan = &dsp_ipc->chans[i]; + mbox_free_channel(dsp_chan->ch); + } + + return 0; +} + +static struct platform_driver imx_dsp_driver = { + .driver = { + .name = "imx-dsp", + }, + .probe = imx_dsp_probe, + .remove = imx_dsp_remove, +}; +builtin_platform_driver(imx_dsp_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("IMX DSP IPC protocol driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h new file mode 100644 index 000000000000..7562099c9e46 --- /dev/null +++ b/include/linux/firmware/imx/dsp.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + * + * Header file for the DSP IPC implementation + */ + +#ifndef _IMX_DSP_IPC_H +#define _IMX_DSP_IPC_H + +#include +#include +#include + +#define DSP_MU_CHAN_NUM 4 + +struct imx_dsp_chan { + struct imx_dsp_ipc *ipc; + struct mbox_client cl; + struct mbox_chan *ch; + char *name; + int idx; +}; + +struct imx_dsp_ops { + void (*handle_reply)(struct imx_dsp_ipc *ipc); + void (*handle_request)(struct imx_dsp_ipc *ipc); +}; + +struct imx_dsp_ipc { + /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */ + struct imx_dsp_chan chans[DSP_MU_CHAN_NUM]; + struct device *dev; + struct imx_dsp_ops *ops; + void *private_data; +}; + +static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data) +{ + if (!ipc) + return; + + ipc->private_data = data; +} + +static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc) +{ + if (!ipc) + return NULL; + + return ipc->private_data; +} + +#if IS_ENABLED(CONFIG_IMX_DSP) + +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx); + +#else + +static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, + unsigned int chan_idx) +{ + return -ENOTSUPP; +} + +#endif +#endif /* _IMX_DSP_IPC_H */ -- GitLab From aae15b1453a22dde4a3623d01cfeaf5e39ac424f Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:21 +0200 Subject: [PATCH 2668/7155] ARM: dts: imx27 phyCARD-S: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts index 5e5e282ed30e..0cd75dadf292 100644 --- a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts +++ b/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts @@ -15,10 +15,10 @@ display: display { model = "Primeview-PD050VL1"; - native-mode = <&timing0>; bits-per-pixel = <16>; /* non-standard but required */ fsl,pcr = <0xf0c88080>; /* non-standard but required */ display-timings { + native-mode = <&timing0>; timing0: 640x480 { hactive = <640>; vactive = <480>; -- GitLab From 28992ae05cc64363623cb75ee3de95425690ede0 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:22 +0200 Subject: [PATCH 2669/7155] ARM: dts: imx25: mbimxsd25: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts index ad2f7e879831..80a7f96de4c6 100644 --- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts +++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts @@ -14,8 +14,8 @@ bits-per-pixel = <16>; fsl,pcr = <0xfa208b80>; bus-width = <18>; - native-mode = <&dvi_svga_timings>; display-timings { + native-mode = <&dvi_svga_timings>; dvi_svga_timings: 800x600 { clock-frequency = <40000000>; hactive = <800>; -- GitLab From 6fbeef213c4189231b950ddaeeb3d3ce867d573b Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:23 +0200 Subject: [PATCH 2670/7155] ARM: dts: eukrea-mbimxsd27: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts index 84fc8df4be7c..9c3ec82ec7e5 100644 --- a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts +++ b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts @@ -11,11 +11,11 @@ display0: CMO-QVGA { model = "CMO-QVGA"; - native-mode = <&timing0>; bits-per-pixel = <16>; fsl,pcr = <0xfad08b80>; display-timings { + native-mode = <&timing0>; timing0: 320x240 { clock-frequency = <6500000>; hactive = <320>; -- GitLab From 38910680d5cb632013f056629e15706e26b1109a Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:24 +0200 Subject: [PATCH 2671/7155] ARM: dts: mbimxsd25: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts index dbecd6d2cfc4..7d4301b22b90 100644 --- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts +++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts @@ -14,8 +14,8 @@ bits-per-pixel = <16>; fsl,pcr = <0xcad08b80>; bus-width = <18>; - native-mode = <&qvga_timings>; display-timings { + native-mode = <&qvga_timings>; qvga_timings: 320x240 { clock-frequency = <6500000>; hactive = <320>; -- GitLab From 558ea43a7d8347dedd6d585d1da4c38de0852018 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:25 +0200 Subject: [PATCH 2672/7155] ARM: dts: imx27-phytec-phycore-rdk: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts index 5606f417e9e8..bf883e45576a 100644 --- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts +++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts @@ -14,11 +14,11 @@ display0: LQ035Q7 { model = "Sharp-LQ035Q7"; - native-mode = <&timing0>; bits-per-pixel = <16>; fsl,pcr = <0xf00080c0>; display-timings { + native-mode = <&timing0>; timing0: 240x320 { clock-frequency = <5500000>; hactive = <240>; -- GitLab From 001d4793734716b416bbb97ee3184f4d677b01c0 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:26 +0200 Subject: [PATCH 2673/7155] ARM: dts: edb7211: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/ep7211-edb7211.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/ep7211-edb7211.dts b/arch/arm/boot/dts/ep7211-edb7211.dts index a0c270f63fee..da076479c8e2 100644 --- a/arch/arm/boot/dts/ep7211-edb7211.dts +++ b/arch/arm/boot/dts/ep7211-edb7211.dts @@ -25,11 +25,11 @@ display: display { model = "320x240x4"; - native-mode = <&timing0>; bits-per-pixel = <4>; ac-prescale = <17>; display-timings { + native-mode = <&timing0>; timing0: 320x240 { hactive = <320>; hback-porch = <0>; -- GitLab From 7244c49dd36d3787a8867cce3b39e8db3403f7ef Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:27 +0200 Subject: [PATCH 2674/7155] ARM: dts: apf27dev: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-apf27dev.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts index 087c6e237af0..6f1e8ce9e76e 100644 --- a/arch/arm/boot/dts/imx27-apf27dev.dts +++ b/arch/arm/boot/dts/imx27-apf27dev.dts @@ -12,10 +12,10 @@ display: display { model = "Chimei-LW700AT9003"; - native-mode = <&timing0>; bits-per-pixel = <16>; /* non-standard but required */ fsl,pcr = <0xfae80083>; /* non-standard but required */ display-timings { + native-mode = <&timing0>; timing0: 800x480 { clock-frequency = <33000033>; hactive = <800>; -- GitLab From f32f77814925e8325cbca836328b2f467bc24996 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 1 Aug 2019 17:46:28 +0200 Subject: [PATCH 2675/7155] ARM: dts: imx25: mbimxsd25: native-mode is part of display-timings Move the native-mode property inside the display-timings node. According to Documentation/devicetree/bindings/display/panel/display-timing.txt. native-mode is a property of the display-timings node. If it's located outside of display-timings, the native-mode setting is ignored and the first display timing is used (which is a problem only if someone adds another display timing). Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts index d60d8f464ca9..24027a1fb46d 100644 --- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts +++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts @@ -14,8 +14,8 @@ bits-per-pixel = <16>; fsl,pcr = <0xfa208b80>; bus-width = <18>; - native-mode = <&dvi_vga_timings>; display-timings { + native-mode = <&dvi_vga_timings>; dvi_vga_timings: 640x480 { clock-frequency = <31250000>; hactive = <640>; -- GitLab From 73d9c8d4c0017e21e1ff519474ceb1450484dc9a Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 23 Jul 2019 22:10:42 +0800 Subject: [PATCH 2676/7155] blk-mq: Fix memory leak in blk_mq_init_allocated_queue error handling If blk_mq_init_allocated_queue->elevator_init_mq fails, need to release the previously requested resources. Fixes: d34849913819 ("blk-mq-sched: allow setting of default IO scheduler") Signed-off-by: zhengbin Signed-off-by: Jens Axboe --- block/blk-mq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 6968de9d7402..509f69fdfcf2 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2846,6 +2846,8 @@ static unsigned int nr_hw_queues(struct blk_mq_tag_set *set) struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, struct request_queue *q) { + int ret = -ENOMEM; + /* mark the queue as mq asap */ q->mq_ops = set->ops; @@ -2907,17 +2909,18 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, blk_mq_map_swqueue(q); if (!(set->flags & BLK_MQ_F_NO_SCHED)) { - int ret; - ret = elevator_init_mq(q); if (ret) - return ERR_PTR(ret); + goto err_tag_set; } return q; +err_tag_set: + blk_mq_del_queue_tag_set(q); err_hctxs: kfree(q->queue_hw_ctx); + q->nr_hw_queues = 0; err_sys_init: blk_mq_sysfs_deinit(q); err_poll: -- GitLab From 0d1b57c1f04cad448eec54dc8de6da3777d3a28d Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Fri, 9 Aug 2019 18:25:18 +0000 Subject: [PATCH 2677/7155] staging: wilc1000: Don't reset WILC CPU disgracefully Send abort request to WILC from wilc_wlan_stop instead of resetting the CPU. The abort request was being sent from wilc_wlan_cleanup after the CPU was reset which wasn't the correct order. The abort request handler in the chip will take care of resetting the CPU. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190809182510.22443-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 4 +- drivers/staging/wilc1000/wilc_wlan.c | 75 +++++++------------------- drivers/staging/wilc1000/wilc_wlan.h | 5 +- 3 files changed, 24 insertions(+), 60 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 57510400f243..cd11c35adcfe 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -475,7 +475,7 @@ static void wilc_wlan_deinitialize(struct net_device *dev) wlan_deinitialize_threads(dev); deinit_irq(dev); - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); wilc_wlan_cleanup(dev); wlan_deinit_locks(dev); @@ -573,7 +573,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) return 0; fail_fw_start: - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); fail_irq_enable: if (!wl->dev_irq_num && diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d4ca6467485c..3d902b499a34 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -968,60 +968,42 @@ int wilc_wlan_start(struct wilc *wilc) return (ret < 0) ? ret : 0; } -int wilc_wlan_stop(struct wilc *wilc) +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) { u32 reg = 0; int ret; - u8 timeout = 10; acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return ret; } - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, + (reg | WILC_ABORT_REQ_BIT)); if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return ret; } - do { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - - if ((reg & BIT(10))) { - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, - WILC_GLB_RESET_0, - reg); - timeout--; - } else { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, - ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - break; - } - - } while (timeout); - reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) | - BIT(29) | BIT(30) | BIT(31)); - - wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); - reg = (u32)~BIT(10); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); + if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret; + } + reg = BIT(0); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg); + if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret; + } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); @@ -1032,8 +1014,6 @@ void wilc_wlan_cleanup(struct net_device *dev) { struct txq_entry_t *tqe; struct rxq_entry_t *rqe; - u32 reg = 0; - int ret; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -1058,23 +1038,6 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->rx_buffer = NULL; kfree(wilc->tx_buffer); wilc->tx_buffer = NULL; - - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, - (reg | ABORT_INT)); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 802f11807659..f566d040bb72 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -98,6 +98,7 @@ #define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE #define WILC_VMM_TBL_RX_SHADOW_SIZE 256 +#define WILC_FW_HOST_COMM 0x13c0 #define WILC_GP_REG_0 0x149c #define WILC_GP_REG_1 0x14a0 @@ -129,7 +130,7 @@ #define WILC_PLL_TO_SDIO 4 #define WILC_PLL_TO_SPI 2 -#define ABORT_INT BIT(31) +#define WILC_ABORT_REQ_BIT BIT(31) #define WILC_RX_BUFF_SIZE (96 * 1024) #define WILC_TX_BUFF_SIZE (64 * 1024) @@ -280,7 +281,7 @@ struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *wilc); -int wilc_wlan_stop(struct wilc *wilc); +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*tx_complete_fn)(void *, int)); -- GitLab From 133716f4ece320691f0052b296df44ed88307da4 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Fri, 9 Aug 2019 18:25:19 +0000 Subject: [PATCH 2678/7155] staging: wilc1000: return kernel error codes from wilc_wlan_stop return -EIO for bus failures, 0 otherwise. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190809182510.22443-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 3d902b499a34..2bbb359d2119 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -979,7 +979,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, @@ -987,14 +987,14 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); if (!ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } reg = BIT(0); @@ -1002,12 +1002,12 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return 0; } void wilc_wlan_cleanup(struct net_device *dev) -- GitLab From ed5d2eaf5f5d59aac17343acebe27b1929e5dcac Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:43 +0530 Subject: [PATCH 2679/7155] staging: rtl8712: _r8712_init_xmit_priv(): Change return values and type Change the return values in _r8712_init_xmit_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 14 +++++++------- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index f625fd5b9eb3..b9dc8953c6b3 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -49,8 +49,8 @@ void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) INIT_LIST_HEAD(&psta_xmitpriv->apsd); } -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter) +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter) { sint i; struct xmit_buf *pxmitbuf; @@ -79,7 +79,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4, GFP_ATOMIC); if (!pxmitpriv->pallocated_frame_buf) { pxmitpriv->pxmit_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3); @@ -119,7 +119,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, if (!pxmitpriv->pallocated_xmitbuf) { kfree(pxmitpriv->pallocated_frame_buf); pxmitpriv->pallocated_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3); @@ -129,12 +129,12 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC); if (!pxmitbuf->pallocated_buf) - return _FAIL; + return -ENOMEM; pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ - ((addr_t) (pxmitbuf->pallocated_buf) & (XMITBUF_ALIGN_SZ - 1)); if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) - return _FAIL; + return -ENOMEM; list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue)); pxmitbuf++; @@ -146,7 +146,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, tasklet_init(&pxmitpriv->xmit_tasklet, (void(*)(unsigned long))r8712_xmit_bh, (unsigned long)padapter); - return _SUCCESS; + return 0; } void _free_xmit_priv(struct xmit_priv *pxmitpriv) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index d4bc059e6a42..6ddf5b6bb633 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -268,8 +268,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib); int r8712_txframes_sta_ac_pending(struct _adapter *padapter, struct pkt_attrib *pattrib); -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter); +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter); void _free_xmit_priv(struct xmit_priv *pxmitpriv); void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); -- GitLab From b013c5b8ddacdf966392b6197289721a6e4d4ac9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:44 +0530 Subject: [PATCH 2680/7155] staging: rtl8712: r8712_update_attrib(): Change return values and type Change return values of r8712_update_attrib from _SUCCESS and _FAIL to 0 and -ENOMEM or -EINVAL respectively. Modify call site to check for the new failure conditions. Also modify the return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 16 ++++++++-------- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- drivers/staging/rtl8712/xmit_linux.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index b9dc8953c6b3..40246cdd0911 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -173,8 +173,8 @@ void _free_xmit_priv(struct xmit_priv *pxmitpriv) free_hwxmits(padapter); } -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib) +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib) { struct pkt_file pktfile; struct sta_info *psta = NULL; @@ -224,7 +224,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { /*firstly, filter packet not belongs to mp*/ if (pattrib->ether_type != 0x8712) - return _FAIL; + return -EINVAL; /* for mp storing the txcmd per packet, * according to the info of txcmd to update pattrib */ @@ -271,7 +271,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else { psta = r8712_get_stainfo(pstapriv, pattrib->ra); if (psta == NULL) /* drop the pkt */ - return _FAIL; + return -ENOMEM; if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) pattrib->mac_id = 5; else @@ -283,7 +283,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->psta = psta; } else { /* if we cannot get psta => drrp the pkt */ - return _FAIL; + return -ENOMEM; } pattrib->ack_policy = 0; @@ -301,7 +301,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->encrypt = 0; if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) - return _FAIL; + return -EINVAL; } else { GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); } @@ -315,7 +315,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->iv_len = 8; pattrib->icv_len = 4; if (padapter->securitypriv.busetkipkey == _FAIL) - return _FAIL; + return -EINVAL; break; case _AES_: pattrib->iv_len = 8; @@ -339,7 +339,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; - return _SUCCESS; + return 0; } static sint xmitframe_addmic(struct _adapter *padapter, diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 6ddf5b6bb633..291763c310ba 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -264,8 +264,8 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe); sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv); -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib); +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib); int r8712_txframes_sta_ac_pending(struct _adapter *padapter, struct pkt_attrib *pattrib); int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 01d713d027b0..1f67d86c606f 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -160,7 +160,7 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *netdev) if (!xmitframe) goto _xmit_entry_drop; - if ((!r8712_update_attrib(adapter, pkt, &xmitframe->attrib))) + if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib)) goto _xmit_entry_drop; adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX); -- GitLab From 0d478943e3c5b3f07e48cfa6e9a0d6a0e546dab2 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:46 +0530 Subject: [PATCH 2681/7155] staging: rtl8712: make_wlanhdr(): Change return values and type Change return values of make_wlanhdr from _SUCCESS/_FAIL to 0/-EINVAL. Modify call site to check for non-zero return values instead of _FAIL. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 40246cdd0911..2e63cceff0da 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -469,8 +469,8 @@ static sint xmitframe_swencrypt(struct _adapter *padapter, return _SUCCESS; } -static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) +static int make_wlanhdr(struct _adapter *padapter, u8 *hdr, + struct pkt_attrib *pattrib) { u16 *qc; @@ -509,7 +509,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); } else { - return _FAIL; + return -EINVAL; } if (pattrib->encrypt) @@ -547,7 +547,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, } } } - return _SUCCESS; + return 0; } static sint r8712_put_snap(u8 *data, u16 h_proto) @@ -605,7 +605,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, pbuf_start = pxmitframe->buf_addr; ptxdesc = pbuf_start; mem_start = pbuf_start + TXDESC_OFFSET; - if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) + if (make_wlanhdr(padapter, mem_start, pattrib)) return _FAIL; _r8712_open_pktfile(pkt, &pktfile); _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen); -- GitLab From 670b673fa0d0f0abd1f95e5dd26dabdcff5a7be1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:47 +0530 Subject: [PATCH 2682/7155] staging: rtl8712: r8712_free_xmitbuf(): Change return type Change return type of r8712_free_xmitbuf from int to void (and remove its return values) as its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 5 ++--- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 2e63cceff0da..178f8b96943b 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -753,19 +753,18 @@ struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv) return pxmitbuf; } -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { unsigned long irqL; struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; if (pxmitbuf == NULL) - return _FAIL; + return; spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); list_del_init(&pxmitbuf->list); list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue); pxmitpriv->free_xmitbuf_cnt++; spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - return _SUCCESS; } /* diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 291763c310ba..d4658c1c4bd4 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -249,8 +249,8 @@ struct xmit_priv { uint free_xmitbuf_cnt; }; -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, + struct xmit_buf *pxmitbuf); struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv); void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len); struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv); -- GitLab From 9958e0e53ba49521323b5ffeafcf996683f6172f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:48 +0530 Subject: [PATCH 2683/7155] staging: rtl8712: r8712_xmit_direct(): Change return type Change return type of r8712_xmit_direct from int to void as its return value is never used. Remove return statement accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 3 +-- drivers/staging/rtl8712/rtl871x_xmit.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 3334b03c2548..d6e8e3fc6527 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -737,7 +737,7 @@ static void dump_xframe(struct _adapter *padapter, } } -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) { int res; @@ -745,7 +745,6 @@ int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) pxmitframe->pkt = NULL; if (res == _SUCCESS) dump_xframe(padapter, pxmitframe); - return res; } int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index d4658c1c4bd4..b14da38bf652 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -276,7 +276,7 @@ void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe); int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe); -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); void r8712_xmit_bh(void *priv); void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe, -- GitLab From e7df51e00828c81fe22225da92223eb6a233e91e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:49 +0530 Subject: [PATCH 2684/7155] staging: rtl8712: r8712_construct_txaggr_cmd_desc(): Change return type Change return type of r8712_construct_txaggr_cmd_desc from u8 to void (and remove its return statement) as it always returns _SUCCESS and its return value is never stored, checked or otherwise used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index d6e8e3fc6527..87278438bc48 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -246,7 +246,7 @@ void r8712_do_queue_select(struct _adapter *padapter, } #ifdef CONFIG_R8712_TX_AGGR -u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) { struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; @@ -260,8 +260,6 @@ u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) /* dw1 */ ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); - - return _SUCCESS; } u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) -- GitLab From 70deda9dfa6678bcd88020f8fb6614f13ccfb451 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:50 +0530 Subject: [PATCH 2685/7155] staging: rtl8712: r8712_construct_txaggr_cmd_hdr(): Change return type Change return type of r8712_construct_txaggr_cmd_hdr from u8 to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 87278438bc48..04e70048f0dd 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -262,7 +262,7 @@ void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); } -u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) { struct xmit_frame *pxmitframe = (struct xmit_frame *) pxmitbuf->priv_data; @@ -276,8 +276,6 @@ u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | (pcmdpriv->cmd_seq << 24)); pcmdpriv->cmd_seq++; - - return _SUCCESS; } u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, -- GitLab From 1aee09b8fa5b872d5fde8f23a26bd775aff908f7 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Sun, 11 Aug 2019 15:51:20 -0700 Subject: [PATCH 2686/7155] staging: rtl8192u: fix spacing errors Used checkpatch's --fix-inplace option for types SPACING, OPEN_BRACE, ELSE_AFTER_BRACE. Manually edited the resulting changes to correct for mistaken fixes and complete fixes that were only partially applied. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190811225120.7308-1-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211_rx.c | 455 ++++++++---------- 1 file changed, 200 insertions(+), 255 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 0a3e478fccd6..7ef1e89de269 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -124,7 +124,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, 2 /* alignment */ + 8 /* WEP */ + ETH_ALEN /* WDS */ + - (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); + (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */); if (!skb) return NULL; @@ -145,7 +145,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, } else { /* received a fragment of a frame for which the head fragment * should have already been received */ - entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, + entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, hdr->addr1); if (entry) { entry->last_frag = frag; @@ -169,7 +169,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addrqos *hdr_4addrqos; u8 tid; - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); @@ -216,7 +216,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; rx_stats->len = skb->len; - ieee80211_rx_mgt(ieee,(struct rtl_80211_hdr_4addr *)skb->data,rx_stats); + ieee80211_rx_mgt(ieee, (struct rtl_80211_hdr_4addr *)skb->data, rx_stats); /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */ if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */ { @@ -281,11 +281,11 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +static unsigned char rfc1042_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +static unsigned char bridge_tunnel_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; /* No encapsulation header if EtherType < 0x600 (=length) */ /* Called by ieee80211_rx_frame_decrypt */ @@ -300,7 +300,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, if (skb->len < 24) return 0; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; fc = le16_to_cpu(hdr->frame_ctl); /* check that the frame is unicast frame to us */ @@ -341,10 +341,10 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); if (ieee->tkip_countermeasures && @@ -388,11 +388,11 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s return 0; if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); atomic_inc(&crypt->refcnt); @@ -410,7 +410,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s /* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5*HZ) +#define IEEE_PACKET_RETRY_TIME (5 * HZ) static int is_duplicate_packet(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addr *header) { @@ -426,12 +426,12 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, //TO2DS and QoS - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); tid++; - } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS + } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); @@ -507,7 +507,7 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *pReorderEntry) { struct list_head *pList = &pTS->rx_pending_pkt_list; - while(pList->next != &pTS->rx_pending_pkt_list) + while (pList->next != &pTS->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) pList = pList->next; @@ -524,17 +524,17 @@ static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *p return true; } -void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray,u8 index) +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray, u8 index) { - u8 i = 0 , j=0; + u8 i = 0, j = 0; u16 ethertype; // if(index > 1) // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__func__,index); - for(j = 0; jnr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { struct sk_buff *sub_skb = prxb->subframes[i]; /* convert hdr + possible LLC headers into Ethernet header */ @@ -585,7 +585,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, u16 WinEnd = (pTS->rx_indicate_seq + WinSize - 1) % 4096; u8 index = 0; bool bMatchWinStart = false, bPktInBuf = false; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n",__func__,SeqNum,pTS->rx_indicate_seq,WinSize); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n", __func__, SeqNum, pTS->rx_indicate_seq, WinSize); prxbIndicateArray = kmalloc_array(REORDER_WIN_SIZE, sizeof(struct ieee80211_rxb *), @@ -599,12 +599,12 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, /* Drop out the packet which SeqNum is smaller than WinStart */ if (SN_LESS(SeqNum, pTS->rx_indicate_seq)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n", + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); pHTInfo->RxReorderDropCounter++; { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -620,16 +620,16 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - if(SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { + if (SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; bMatchWinStart = true; - } else if(SN_LESS(WinEnd, SeqNum)) { - if(SeqNum >= (WinSize - 1)) { - pTS->rx_indicate_seq = SeqNum + 1 -WinSize; + } else if (SN_LESS(WinEnd, SeqNum)) { + if (SeqNum >= (WinSize - 1)) { + pTS->rx_indicate_seq = SeqNum + 1 - WinSize; } else { pTS->rx_indicate_seq = 4095 - (WinSize - (SeqNum + 1)) + 1; } - IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } /* @@ -641,7 +641,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. All packets with SeqNum smaller than WinStart => Indicate * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */ - if(bMatchWinStart) { + if (bMatchWinStart) { /* Current packet is going to be indicated.*/ IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\ pTS->rx_indicate_seq, SeqNum); @@ -651,7 +651,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } else { /* Current packet is going to be inserted into pending list.*/ //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to ordered list\n",__func__); - if(!list_empty(&ieee->RxReorder_Unused_List)) { + if (!list_empty(&ieee->RxReorder_Unused_List)) { pReorderEntry = list_entry(ieee->RxReorder_Unused_List.next, struct rx_reorder_entry, List); list_del_init(&pReorderEntry->List); @@ -660,13 +660,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, pReorderEntry->prxb = prxb; // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); - if(!AddReorderEntry(pTS, pReorderEntry)) { + if (!AddReorderEntry(pTS, pReorderEntry)) { IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", __func__, pTS->rx_indicate_seq, SeqNum); - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -674,10 +674,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } } else { IEEE80211_DEBUG(IEEE80211_DL_REORDER, - "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } - } - else { + } else { /* * Packets are dropped if there is not enough reorder entries. * This part shall be modified!! We can just indicate all the @@ -686,7 +685,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -696,8 +695,8 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Check if there is any packet need indicate.*/ - while(!list_empty(&pTS->rx_pending_pkt_list)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__func__); + while (!list_empty(&pTS->rx_pending_pkt_list)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): start RREORDER indicate\n", __func__); pReorderEntry = list_entry(pTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List); if (SN_LESS(pReorderEntry->SeqNum, pTS->rx_indicate_seq) || SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) @@ -711,15 +710,15 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, list_del_init(&pReorderEntry->List); - if(SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) + if (SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); prxbIndicateArray[index] = pReorderEntry->prxb; // printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); index++; - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); } else { bPktInBuf = true; break; @@ -727,13 +726,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/ - if (index>0) { + if (index > 0) { // Cancel previous pending timer. // del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_timeout_indicate_seq = 0xffff; // Indicate packets - if(index>REORDER_WIN_SIZE){ + if (index > REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"); kfree(prxbIndicateArray); return; @@ -743,9 +742,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, if (bPktInBuf && pTS->rx_timeout_indicate_seq == 0xffff) { // Set new pending timer. - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __func__); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): SET rx timeout timer\n", __func__); pTS->rx_timeout_indicate_seq = pTS->rx_indicate_seq; - if(timer_pending(&pTS->rx_pkt_pending_timer)) + if (timer_pending(&pTS->rx_pkt_pending_timer)) del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_pkt_pending_timer.expires = jiffies + msecs_to_jiffies(pHTInfo->RxReorderPendingTime); @@ -762,12 +761,12 @@ static u8 parse_subframe(struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 LLCOffset= sizeof(struct rtl_80211_hdr_3addr); + u16 LLCOffset = sizeof(struct rtl_80211_hdr_3addr); u16 ChkLength; bool bIsAggregateFrame = false; u16 nSubframe_Length; u8 nPadding_Length = 0; - u16 SeqNum=0; + u16 SeqNum = 0; struct sk_buff *sub_skb; /* just for debug purpose */ @@ -793,7 +792,7 @@ static u8 parse_subframe(struct sk_buff *skb, skb_pull(skb, LLCOffset); - if(!bIsAggregateFrame) { + if (!bIsAggregateFrame) { rxb->nr_subframes = 1; #ifdef JOHN_NOCPY rxb->subframes[0] = skb; @@ -801,26 +800,26 @@ static u8 parse_subframe(struct sk_buff *skb, rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC); #endif - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len); return 1; } else { rxb->nr_subframes = 0; - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); - while(skb->len > ETHERNET_HEADER_SIZE) { + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); + while (skb->len > ETHERNET_HEADER_SIZE) { /* Offset 12 denote 2 mac address */ nSubframe_Length = *((u16 *)(skb->data + 12)); //==m==>change the length order - nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); + nSubframe_Length = (nSubframe_Length >> 8) + (nSubframe_Length << 8); - if (skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) { + if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ __func__, rxb->nr_subframes); - printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__func__, nSubframe_Length); - printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length); - printk("The Packet SeqNum is %d\n",SeqNum); + printk("%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); + printk("nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); + printk("The Packet SeqNum is %d\n", SeqNum); return 0; } @@ -925,7 +924,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, if (HTCCheck(ieee, skb->data)) { - if(net_ratelimit()) + if (net_ratelimit()) printk("find HTCControl\n"); hdrlen += 4; rx_stats->bContainHTC = true; @@ -972,7 +971,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) - (void) hostap_handle_sta_crypto(local, hdr, &crypt, + (void)hostap_handle_sta_crypto(local, hdr, &crypt, &sta); #endif @@ -998,18 +997,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; // if QoS enabled, should check the sequence for each of the AC - if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { + if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active || !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { if (is_duplicate_packet(ieee, hdr)) goto rx_dropped; - } - else - { + } else { struct rx_ts_record *pRxTS = NULL; //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__func__, tid); - if(GetTs( + if (GetTs( ieee, - (struct ts_common_info **) &pRxTS, + (struct ts_common_info **)&pRxTS, hdr->addr2, Frame_QoSTID((u8 *)(skb->data)), RX_DIR, @@ -1017,20 +1014,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, { // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc)); - if ((fc & (1<<11)) && + if ((fc & (1 << 11)) && (frag == pRxTS->rx_last_frag_num) && (WLAN_GET_SEQ_SEQ(sc) == pRxTS->rx_last_seq_num)) { goto rx_dropped; - } - else - { + } else { pRxTS->rx_last_frag_num = frag; pRxTS->rx_last_seq_num = WLAN_GET_SEQ_SEQ(sc); } - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n", __func__); goto rx_dropped; } } @@ -1133,7 +1126,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; /* skb: hdr + (possibly fragmented) plaintext payload */ // PR: FIXME: hostap has additional conditions in the "if" below: @@ -1185,7 +1178,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* this was the last fragment and the frame will be * delivered, so remove skb from fragment cache */ skb = frag_skb; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; ieee80211_frag_cache_invalidate(ieee, hdr); } @@ -1202,7 +1195,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->LinkDetectInfo.NumRecvDataInPeriod++; ieee->LinkDetectInfo.NumRxOkInPeriod++; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { if (/*ieee->ieee802_1x &&*/ ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { @@ -1254,8 +1247,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); - GetTs(ieee,(struct ts_common_info **) &pTS,hdr->addr2,TID,RX_DIR,true); - if (TID !=0 && TID !=3) + GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); + if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } @@ -1270,7 +1263,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* qos data packets & reserved bit is 1 */ if (parse_subframe(skb, rx_stats, rxb, src, dst) == 0) { /* only to free rxb, and not submit the packets to upper layer */ - for(i =0; i < rxb->nr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { dev_kfree_skb(rxb->subframes[i]); } kfree(rxb); @@ -1281,7 +1274,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, //added by amy for reorder if (!ieee->pHTInfo->bCurRxReorderEnable || !pTS) { //added by amy for reorder - for(i = 0; inr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { struct sk_buff *sub_skb = rxb->subframes[i]; if (sub_skb) { @@ -1324,10 +1317,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, kfree(rxb); rxb = NULL; - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n", __func__); RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); } #ifndef JOHN_NOCPY @@ -1407,10 +1398,9 @@ static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info /* * Parse a QoS information element */ -static int ieee80211_read_qos_info_element(struct - ieee80211_qos_information_element - *element_info, struct ieee80211_info_element - *info_element) +static int ieee80211_read_qos_info_element( + struct ieee80211_qos_information_element *element_info, + struct ieee80211_info_element *info_element) { int ret = 0; u16 size = sizeof(struct ieee80211_qos_information_element) - 2; @@ -1438,11 +1428,9 @@ static int ieee80211_read_qos_info_element(struct /* * Write QoS parameters from the ac parameters. */ -static int ieee80211_qos_convert_ac_to_parameters(struct - ieee80211_qos_parameter_info - *param_elm, struct - ieee80211_qos_parameters - *qos_param) +static int ieee80211_qos_convert_ac_to_parameters( + struct ieee80211_qos_parameter_info *param_elm, + struct ieee80211_qos_parameters *qos_param) { int i; struct ieee80211_qos_ac_parameter *ac_params; @@ -1455,12 +1443,12 @@ static int ieee80211_qos_convert_ac_to_parameters(struct aci = (ac_params->aci_aifsn & 0x60) >> 5; - if(aci >= QOS_QUEUE_NUM) + if (aci >= QOS_QUEUE_NUM) continue; qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ - qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; + qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci]; qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F); @@ -1563,7 +1551,7 @@ static inline void ieee80211_extract_country_ie( { if (IS_DOT11D_ENABLE(ieee)) { - if (info_element->len!= 0) + if (info_element->len != 0) { memcpy(network->CountryIeBuf, info_element->data, info_element->len); network->CountryIeLen = info_element->len; @@ -1579,7 +1567,7 @@ static inline void ieee80211_extract_country_ie( // some AP (e.g. Cisco 1242) don't include country IE in their // probe response frame. // - if (IS_EQUAL_CIE_SRC(ieee, addr2) ) + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { UPDATE_CIE_WATCHDOG(ieee); } @@ -1595,9 +1583,9 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, { u8 i; short offset; - u16 tmp_htcap_len=0; - u16 tmp_htinfo_len=0; - u16 ht_realtek_agg_len=0; + u16 tmp_htcap_len = 0; + u16 tmp_htinfo_len = 0; + u16 ht_realtek_agg_len = 0; u8 ht_realtek_agg_buf[MAX_IE_LEN]; // u16 broadcom_len = 0; #ifdef CONFIG_IEEE80211_DEBUG @@ -1628,7 +1616,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } network->ssid_len = min(info_element->len, - (u8) IW_ESSID_MAX_SIZE); + (u8)IW_ESSID_MAX_SIZE); memcpy(network->ssid, info_element->data, network->ssid_len); if (network->ssid_len < IW_ESSID_MAX_SIZE) memset(network->ssid + network->ssid_len, 0, @@ -1707,14 +1695,14 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, break; case MFIE_TYPE_TIM: - if(info_element->len < 4) + if (info_element->len < 4) break; network->tim.tim_count = info_element->data[0]; network->tim.tim_period = info_element->data[1]; network->dtim_period = info_element->data[1]; - if(ieee->state != IEEE80211_LINKED) + if (ieee->state != IEEE80211_LINKED) break; network->last_dtim_sta_time[0] = stats->mac_time[0]; @@ -1722,22 +1710,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, network->dtim_data = IEEE80211_DTIM_VALID; - if(info_element->data[0] != 0) + if (info_element->data[0] != 0) break; - if(info_element->data[2] & 1) + if (info_element->data[2] & 1) network->dtim_data |= IEEE80211_DTIM_MBCAST; - offset = (info_element->data[2] >> 1)*2; + offset = (info_element->data[2] >> 1) * 2; - if(ieee->assoc_id < 8*offset || - ieee->assoc_id > 8*(offset + info_element->len -3)) + if (ieee->assoc_id < 8 * offset || + ieee->assoc_id > 8 * (offset + info_element->len - 3)) break; offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ; - if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) + if (info_element->data[3 + offset] & (1 << (ieee->assoc_id % 8))) network->dtim_data |= IEEE80211_DTIM_UCAST; //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); @@ -1790,42 +1778,42 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, #endif //for HTcap and HTinfo parameters - if(tmp_htcap_len == 0){ - if(info_element->len >= 4 && + if (tmp_htcap_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x033){ - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); } } - if(tmp_htcap_len != 0) + if (tmp_htcap_len != 0) network->bssht.bdSupportHT = true; else network->bssht.bdSupportHT = false; } - if(tmp_htinfo_len == 0){ - if(info_element->len >= 4 && + if (tmp_htinfo_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x034){ - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len != 0){ + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - if(tmp_htinfo_len){ - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + if (tmp_htinfo_len) { + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } } @@ -1833,22 +1821,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } } - if(ieee->aggregation){ - if(network->bssht.bdSupportHT){ - if(info_element->len >= 4 && + if (ieee->aggregation) { + if (network->bssht.bdSupportHT) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0xe0 && info_element->data[2] == 0x4c && info_element->data[3] == 0x02){ - ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN); - memcpy(ht_realtek_agg_buf,info_element->data,info_element->len); + ht_realtek_agg_len = min(info_element->len, (u8)MAX_IE_LEN); + memcpy(ht_realtek_agg_buf, info_element->data, info_element->len); } - if(ht_realtek_agg_len >= 5){ + if (ht_realtek_agg_len >= 5) { network->bssht.bdRT2RTAggregation = true; - if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) + if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) network->bssht.bdRT2RTLongSlotTime = true; } } @@ -1874,17 +1862,16 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } } - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x0c && info_element->data[2] == 0x43) { network->ralink_cap_exist = true; - } - else + } else network->ralink_cap_exist = false; //added by amy for atheros AP - if((info_element->len >= 3 && + if ((info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x03 && info_element->data[2] == 0x7f) || @@ -1893,20 +1880,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[1] == 0x13 && info_element->data[2] == 0x74)) { - printk("========>%s(): athros AP is exist\n",__func__); + printk("========>%s(): athros AP is exist\n", __func__); network->atheros_cap_exist = true; - } - else + } else network->atheros_cap_exist = false; - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96) { network->cisco_cap_exist = true; - } - else + } else network->cisco_cap_exist = false; //added by amy for LEAP of cisco if (info_element->len > 4 && @@ -1915,33 +1900,28 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { - if(info_element->len == 6) + if (info_element->len == 6) { memcpy(network->CcxRmState, &info_element[4], 2); - if(network->CcxRmState[0] != 0) + if (network->CcxRmState[0] != 0) { network->bCcxRmEnable = true; - } - else + } else network->bCcxRmEnable = false; // // CCXv4 Table 59-1 MBSSID Masks. // network->MBssidMask = network->CcxRmState[1] & 0x07; - if(network->MBssidMask != 0) + if (network->MBssidMask != 0) { network->bMBssidValid = true; network->MBssidMask = 0xff << (network->MBssidMask); ether_addr_copy(network->MBssid, network->bssid); network->MBssid[5] &= network->MBssidMask; - } - else - { + } else { network->bMBssidValid = false; } - } - else - { + } else { network->bCcxRmEnable = false; } } @@ -1951,13 +1931,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x03) { - if(info_element->len == 5) - { + if (info_element->len == 5) { network->bWithCcxVerNum = true; network->BssCcxVerNumber = info_element->data[4]; - } - else - { + } else { network->bWithCcxVerNum = false; network->BssCcxVerNumber = 0; } @@ -1977,19 +1954,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_CAP: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n", info_element->len); - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT() // windows driver will update WMM parameters each beacon received once connected // Linux driver is a bit different. network->bssht.bdSupportHT = true; - } - else + } else network->bssht.bdSupportHT = false; break; @@ -1997,37 +1973,33 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_INFO: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n", info_element->len); - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len){ + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len) { network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE; - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } break; case MFIE_TYPE_AIRONET: IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); - if(info_element->len >IE_CISCO_FLAG_POSITION) + if (info_element->len > IE_CISCO_FLAG_POSITION) { network->bWithAironetIE = true; // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): // "A Cisco access point advertises support for CKIP in beacon and probe response packets, // by adding an Aironet element and setting one or both of the CKIP negotiation bits." - if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) ) + if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || + (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) { network->bCkipSupported = true; - } - else - { + } else { network->bCkipSupported = false; } - } - else - { + } else { network->bWithAironetIE = false; network->bCkipSupported = false; } @@ -2057,13 +2029,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, data[info_element->len]; } - if(!network->atheros_cap_exist && !network->broadcom_cap_exist && - !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) - { + if (!network->atheros_cap_exist && !network->broadcom_cap_exist && + !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) { network->unknown_cap_exist = true; - } - else - { + } else { network->unknown_cap_exist = false; } return 0; @@ -2076,44 +2045,25 @@ static inline u8 ieee80211_SignalStrengthTranslate( u8 RetSS; // Step 1. Scale mapping. - if(CurrSS >= 71 && CurrSS <= 100) - { + if (CurrSS >= 71 && CurrSS <= 100) { RetSS = 90 + ((CurrSS - 70) / 3); - } - else if(CurrSS >= 41 && CurrSS <= 70) - { + } else if (CurrSS >= 41 && CurrSS <= 70) { RetSS = 78 + ((CurrSS - 40) / 3); - } - else if(CurrSS >= 31 && CurrSS <= 40) - { + } else if (CurrSS >= 31 && CurrSS <= 40) { RetSS = 66 + (CurrSS - 30); - } - else if(CurrSS >= 21 && CurrSS <= 30) - { + } else if (CurrSS >= 21 && CurrSS <= 30) { RetSS = 54 + (CurrSS - 20); - } - else if(CurrSS >= 5 && CurrSS <= 20) - { + } else if (CurrSS >= 5 && CurrSS <= 20) { RetSS = 42 + (((CurrSS - 5) * 2) / 3); - } - else if(CurrSS == 4) - { + } else if (CurrSS == 4) { RetSS = 36; - } - else if(CurrSS == 3) - { + } else if (CurrSS == 3) { RetSS = 27; - } - else if(CurrSS == 2) - { + } else if (CurrSS == 2) { RetSS = 18; - } - else if(CurrSS == 1) - { + } else if (CurrSS == 1) { RetSS = 9; - } - else - { + } else { RetSS = CurrSS; } //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); @@ -2193,7 +2143,7 @@ static inline int ieee80211_network_init( network->rsn_ie_len = 0; if (ieee80211_parse_info_param - (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats)) + (ieee, beacon->info_element, stats->len - sizeof(*beacon), network, stats)) return 1; network->mode = 0; @@ -2215,10 +2165,10 @@ static inline int ieee80211_network_init( return 1; } - if(network->bssht.bdSupportHT){ - if(network->mode == IEEE_A) + if (network->bssht.bdSupportHT) { + if (network->mode == IEEE_A) network->mode = IEEE_N_5G; - else if(network->mode & (IEEE_G | IEEE_B)) + else if (network->mode & (IEEE_G | IEEE_B)) network->mode = IEEE_N_24G; } if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) @@ -2226,7 +2176,7 @@ static inline int ieee80211_network_init( stats->signal = 30 + (stats->SignalStrength * 70) / 100; //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal); - stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25; + stats->noise = ieee80211_translate_todbm((u8)(100 - stats->signal)) - 25; memcpy(&network->stats, stats, sizeof(network->stats)); @@ -2290,10 +2240,10 @@ static inline void update_network(struct ieee80211_network *dst, dst->bssht.bdSupportHT = src->bssht.bdSupportHT; dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation; - dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen; - memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen); - dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen; - memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen); + dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen; + memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf, src->bssht.bdHTCapLen); + dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen; + memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf, src->bssht.bdHTInfoLen); dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer; dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime; dst->broadcom_cap_exist = src->broadcom_cap_exist; @@ -2312,7 +2262,7 @@ static inline void update_network(struct ieee80211_network *dst, qos_active = dst->qos_data.active; //old_param = dst->qos_data.old_param_count; old_param = dst->qos_data.param_count; - if(dst->flags & NETWORK_HAS_QOS_MASK) + if (dst->flags & NETWORK_HAS_QOS_MASK) memcpy(&dst->qos_data, &src->qos_data, sizeof(struct ieee80211_qos_data)); else { @@ -2322,7 +2272,7 @@ static inline void update_network(struct ieee80211_network *dst, if (dst->qos_data.supported == 1) { dst->QoS_Enable = 1; - if(dst->ssid_len) + if (dst->ssid_len) IEEE80211_DEBUG_QOS ("QoS the network %s is QoS supported\n", dst->ssid); @@ -2335,9 +2285,9 @@ static inline void update_network(struct ieee80211_network *dst, /* dst->last_associate is not overwritten */ dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. - if (src->wmm_param[0].aci_aifsn|| \ - src->wmm_param[1].aci_aifsn|| \ - src->wmm_param[2].aci_aifsn|| \ + if (src->wmm_param[0].aci_aifsn || \ + src->wmm_param[1].aci_aifsn || \ + src->wmm_param[2].aci_aifsn || \ src->wmm_param[3].aci_aifsn) { memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); } @@ -2434,8 +2384,7 @@ static inline void ieee80211_process_probe_response( if (fc == IEEE80211_STYPE_PROBE_RESP) { // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + if (IS_COUNTRY_IE_VALID(ieee)) { if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; @@ -2451,14 +2400,11 @@ static inline void ieee80211_process_probe_response( goto out; } } - } - else - { + } else { // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + if (IS_COUNTRY_IE_VALID(ieee)) { if (!is_legal_channel(ieee, network->channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network->channel); + printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } } @@ -2468,7 +2414,7 @@ static inline void ieee80211_process_probe_response( // Filter over channel ch12~14 if (network->channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network->channel); + printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } } @@ -2491,18 +2437,17 @@ static inline void ieee80211_process_probe_response( update_network(&ieee->current_network, network); if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) && ieee->current_network.berp_info_valid){ - if(ieee->current_network.erp_value& ERP_UseProtection) + if (ieee->current_network.erp_value & ERP_UseProtection) ieee->current_network.buseprotection = true; else ieee->current_network.buseprotection = false; } - if(is_beacon(beacon->header.frame_ctl)) + if (is_beacon(beacon->header.frame_ctl)) { - if(ieee->state == IEEE80211_LINKED) + if (ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; - } - else //hidden AP - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); + } else //hidden AP + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & ieee->current_network.flags); } list_for_each_entry(target, &ieee->network_list, list) { @@ -2543,8 +2488,8 @@ static inline void ieee80211_process_probe_response( #endif memcpy(target, network, sizeof(*target)); list_add_tail(&target->list, &ieee->network_list); - if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) - ieee80211_softmac_new_net(ieee,network); + if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) + ieee80211_softmac_new_net(ieee, network); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", escape_essid(target->ssid, @@ -2559,26 +2504,26 @@ static inline void ieee80211_process_probe_response( */ renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); //YJ,add,080819,for hidden ap - if(is_beacon(beacon->header.frame_ctl) == 0) - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & target->flags); + if (is_beacon(beacon->header.frame_ctl) == 0) + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & target->flags); //if(strncmp(network->ssid, "linksys-c",9) == 0) // printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags); - if(((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + if (((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ && (((network->ssid_len > 0) && (strncmp(target->ssid, network->ssid, network->ssid_len)))\ - ||((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) + || ((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) renew = 1; //YJ,add,080819,for hidden ap,end update_network(target, network); - if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) - ieee80211_softmac_new_net(ieee,network); + if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) + ieee80211_softmac_new_net(ieee, network); } spin_unlock_irqrestore(&ieee->lock, flags); if (is_beacon(beacon->header.frame_ctl) && is_same_network(&ieee->current_network, network, ieee) && \ (ieee->state == IEEE80211_LINKED)) { if (ieee->handle_beacon) - ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); + ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network); } out: -- GitLab From 7da20788d3ff59506aebd946d8a424f01f2c1c66 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Aug 2019 18:01:47 +0200 Subject: [PATCH 2687/7155] ALSA: hda: Set fifo_size for both playback and capture streams Currently we set hdac_stream.fifo_size field only for the playback stream by some odd reason I forgot, while this field isn't referred in any places. Actually this fifo_size field would have been required in the position report correction for VIA chipset, but due to the lack of the fifo_size set for capture streams, snd-hda-intel driver fetches the register by itself. This patch straightens and simplifies the code by setting the fifo_size field for both playback and capture streams, and use it in the HD-audio controller driver. Signed-off-by: Takashi Iwai --- sound/hda/hdac_stream.c | 6 +----- sound/pci/hda/hda_intel.c | 8 +------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index fc68d4ce0a37..d8fe7ff0cd58 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -229,11 +229,7 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev) /* set the interrupt enable bits in the descriptor control register */ snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); - if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) - azx_dev->fifo_size = - snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; - else - azx_dev->fifo_size = 0; + azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; /* when LPIB delay correction gives a small negative value, * we ignore it; currently set the threshold statically to diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3a209e07d5d8..dc8a83cb7393 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -84,8 +84,6 @@ enum { #define INTEL_SCH_HDA_DEVC 0x78 #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) -/* Define IN stream 0 FIFO size offset in VIA controller */ -#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 /* Define VIA HD Audio Device ID*/ #define VIA_HDAC_DEVICE_ID 0x3288 @@ -811,11 +809,7 @@ static unsigned int azx_via_get_position(struct azx *chip, mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf); mod_dma_pos %= azx_dev->core.period_bytes; - /* azx_dev->fifo_size can't get FIFO size of in stream. - * Get from base address + offset. - */ - fifo_size = readw(azx_bus(chip)->remap_addr + - VIA_IN_STREAM0_FIFO_SIZE_OFFSET); + fifo_size = azx_stream(azx_dev)->fifo_size - 1; if (azx_dev->insufficient) { /* Link position never gather than FIFO size */ -- GitLab From 0bf63e2c2913391dbf7e49ed8df2c89c180e58d9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Jul 2019 03:17:59 -0300 Subject: [PATCH 2688/7155] media: mach-omap2/devices.c: set dma mask The dma_mask and coherent_dma_mask values were never set. This prevented the media omap_vout driver from loading successfully. Tested on a Pandaboard and Beagle XM board. Signed-off-by: Hans Verkuil Acked-by: Tony Lindgren Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-omap2/devices.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index cc0d08dad141..5a2e198e7db1 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -43,11 +44,17 @@ static struct resource omap_vout_resource[2] = { }; #endif +static u64 omap_vout_dma_mask = DMA_BIT_MASK(32); + static struct platform_device omap_vout_device = { .name = "omap_vout", .num_resources = ARRAY_SIZE(omap_vout_resource), .resource = &omap_vout_resource[0], .id = -1, + .dev = { + .dma_mask = &omap_vout_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; int __init omap_init_vout(void) -- GitLab From 782d7a217eb63353dbfd81fb88b24e600bc6bd9c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 08:55:21 +0200 Subject: [PATCH 2689/7155] ia64: annotate a switch fallthrough in ia64_do_signal Also reindent the switch statement to use the normal kernel style while at it. Signed-off-by: Christoph Hellwig Link: https://lkml.kernel.org/r/20190812065524.19959-2-hch@lst.de Signed-off-by: Tony Luck --- arch/ia64/kernel/signal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index e5044aed9452..d07ed65c9c6e 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -363,19 +363,19 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) if (unlikely(restart)) { switch (errno) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: + case ERESTART_RESTARTBLOCK: + case ERESTARTNOHAND: scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; - - case ERESTARTSYS: + case ERESTARTSYS: if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) { scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; } - case ERESTARTNOINTR: + /*FALLTHRU*/ + case ERESTARTNOINTR: ia64_decrement_ip(&scr->pt); restart = 0; /* don't restart twice if handle_signal() fails... */ } -- GitLab From 94707d90b7d6ea5552078e2c3b78b7f1e29ee528 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 08:55:22 +0200 Subject: [PATCH 2690/7155] ia64: annotate switch fallthroughs in ia64_handle_unaligned Replace the "no break" comments with something that the compiler recognizes. Signed-off-by: Christoph Hellwig Link: https://lkml.kernel.org/r/20190812065524.19959-3-hch@lst.de Signed-off-by: Tony Luck --- arch/ia64/kernel/unaligned.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index eb7d5df59fa3..2d4e65ba5c3e 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1431,7 +1431,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /* no break */ + /*FALLTHRU*/ case LDS_IMM_OP: case LDSA_IMM_OP: case LDFS_OP: @@ -1459,7 +1459,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /* no break */ + /*FALLTHRU*/ case LD_IMM_OP: case LDA_IMM_OP: case LDBIAS_IMM_OP: @@ -1475,7 +1475,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /* no break */ + /*FALLTHRU*/ case ST_IMM_OP: case STREL_IMM_OP: ret = emulate_store_int(ifa, u.insn, regs); -- GitLab From d0d82d24cdfd289d755c87448dbc27c2dd0559ec Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 08:55:23 +0200 Subject: [PATCH 2691/7155] ia64/kprobes: remove the unused ia64_get_bsp_cfm function Signed-off-by: Christoph Hellwig Link: https://lkml.kernel.org/r/20190812065524.19959-4-hch@lst.de Signed-off-by: Tony Luck --- arch/ia64/kernel/kprobes.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 5de801a2c0f0..b8356edbde65 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -979,32 +979,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, return ret; } -struct param_bsp_cfm { - unsigned long ip; - unsigned long *bsp; - unsigned long cfm; -}; - -static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg) -{ - unsigned long ip; - struct param_bsp_cfm *lp = arg; - - do { - unw_get_ip(info, &ip); - if (ip == 0) - break; - if (ip == lp->ip) { - unw_get_bsp(info, (unsigned long*)&lp->bsp); - unw_get_cfm(info, (unsigned long*)&lp->cfm); - return; - } - } while (unw_unwind(info) >= 0); - lp->bsp = NULL; - lp->cfm = 0; - return; -} - unsigned long arch_deref_entry_point(void *entry) { return ((struct fnptr *)entry)->ip; -- GitLab From 4189ff23489e6688ef4c7f5109df0cebbad425b1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 08:55:24 +0200 Subject: [PATCH 2692/7155] kernel: only define task_struct_whitelist conditionally If CONFIG_ARCH_TASK_STRUCT_ALLOCATOR is set task_struct_whitelist is never called, and thus generates a compiler warning. Signed-off-by: Christoph Hellwig Link: https://lkml.kernel.org/r/20190812065524.19959-5-hch@lst.de Signed-off-by: Tony Luck --- kernel/fork.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/fork.c b/kernel/fork.c index 2852d0e76ea3..f79e3da0caaf 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -768,6 +768,7 @@ static void set_max_threads(unsigned int max_threads_suggested) int arch_task_struct_size __read_mostly; #endif +#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR static void task_struct_whitelist(unsigned long *offset, unsigned long *size) { /* Fetch thread_struct whitelist for the architecture. */ @@ -782,6 +783,7 @@ static void task_struct_whitelist(unsigned long *offset, unsigned long *size) else *offset += offsetof(struct task_struct, thread); } +#endif /* CONFIG_ARCH_TASK_STRUCT_ALLOCATOR */ void __init fork_init(void) { -- GitLab From 98dc19902a0b2e5348e43d6a2c39a0a7d0fc639e Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Thu, 8 Aug 2019 15:40:07 -0500 Subject: [PATCH 2693/7155] arm64: topology: Use PPTT to determine if PE is a thread ACPI 6.3 adds a thread flag to represent if a CPU/PE is actually a thread. Given that the MPIDR_MT bit may not represent this information consistently on homogeneous machines we should prefer the PPTT flag if its available. Signed-off-by: Jeremy Linton Reviewed-by: Sudeep Holla Reviewed-by: Robert Richter [will: made acpi_cpu_is_threaded() return 'bool'] Signed-off-by: Will Deacon --- arch/arm64/kernel/topology.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 0825c4a856e3..6106c49f84bc 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -340,17 +340,28 @@ void remove_cpu_topology(unsigned int cpu) } #ifdef CONFIG_ACPI +static bool __init acpi_cpu_is_threaded(int cpu) +{ + int is_threaded = acpi_pptt_cpu_is_thread(cpu); + + /* + * if the PPTT doesn't have thread information, assume a homogeneous + * machine and return the current CPU's thread state. + */ + if (is_threaded < 0) + is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; + + return !!is_threaded; +} + /* * Propagate the topology information of the processor_topology_node tree to the * cpu_topology array. */ static int __init parse_acpi_topology(void) { - bool is_threaded; int cpu, topology_id; - is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; - for_each_possible_cpu(cpu) { int i, cache_id; @@ -358,7 +369,7 @@ static int __init parse_acpi_topology(void) if (topology_id < 0) return topology_id; - if (is_threaded) { + if (acpi_cpu_is_threaded(cpu)) { cpu_topology[cpu].thread_id = topology_id; topology_id = find_acpi_cpu_topology(cpu, 1); cpu_topology[cpu].core_id = topology_id; -- GitLab From 791aa2150b296059b017cf458075c2f90a652b2b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 9 Aug 2019 15:09:56 +0200 Subject: [PATCH 2694/7155] ARM: dts: exynos: Move MSC power domain to the right (sorted) place DT nodes should be sorted by 'reg' property, so move MSC power domain node in exynos5420.dtsi to the end of power domains to keep them sorted. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5420.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 55d4dbf6f83a..2b55be150bc0 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -294,13 +294,6 @@ label = "MFC"; }; - msc_pd: power-domain@10044120 { - compatible = "samsung,exynos4210-pd"; - reg = <0x10044120 0x20>; - #power-domain-cells = <0>; - label = "MSC"; - }; - disp_pd: power-domain@100440c0 { compatible = "samsung,exynos4210-pd"; reg = <0x100440C0 0x20>; @@ -315,6 +308,13 @@ label = "MAU"; }; + msc_pd: power-domain@10044120 { + compatible = "samsung,exynos4210-pd"; + reg = <0x10044120 0x20>; + #power-domain-cells = <0>; + label = "MSC"; + }; + pinctrl_0: pinctrl@13400000 { compatible = "samsung,exynos5420-pinctrl"; reg = <0x13400000 0x1000>; -- GitLab From 8686764fc0711f409b8fcaaa76e7c5a816e9160b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 9 Aug 2019 15:09:57 +0200 Subject: [PATCH 2695/7155] ARM: dts: exynos: Add G3D power domain to Exynos542x Add a power domain for G3D/Mali device present in Exynos542x/5800 SoCs. Node for the Mali device will be added by a separate patch. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5420.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 2b55be150bc0..7d51e0f4ab79 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -294,6 +294,13 @@ label = "MFC"; }; + g3d_pd: power-domain@10044080 { + compatible = "samsung,exynos4210-pd"; + reg = <0x10044080 0x20>; + #power-domain-cells = <0>; + label = "G3D"; + }; + disp_pd: power-domain@100440c0 { compatible = "samsung,exynos4210-pd"; reg = <0x100440C0 0x20>; -- GitLab From bfb77169306d5d560a8b62eebaf6d69d02e8d152 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 9 Aug 2019 15:09:58 +0200 Subject: [PATCH 2696/7155] ARM: dts: exynos: Add CAM power domain to Exynos5422/5800 CAM power domain contains CAMIF, 3AA and FIMC LITE devices. It is present only in Exynos 5422/5800 SoCs. Currently there are no drivers nor the device nodes for those devices, but instantiating its power domain allows to turn it off and save some energy. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5800.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi index 57d3b319fd65..de639eecc5c9 100644 --- a/arch/arm/boot/dts/exynos5800.dtsi +++ b/arch/arm/boot/dts/exynos5800.dtsi @@ -131,3 +131,12 @@ &mfc { compatible = "samsung,mfc-v8"; }; + +&soc { + cam_pd: power-domain@10045100 { + compatible = "samsung,exynos4210-pd"; + reg = <0x10045100 0x20>; + #power-domain-cells = <0>; + label = "CAM"; + }; +}; -- GitLab From 82992fc70f98dee091faa926eb5cecadda5c84f4 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 12 Aug 2019 19:11:06 +0200 Subject: [PATCH 2697/7155] parisc: Add ALTERNATIVE_CODE() and ALT_COND_RUN_ON_QEMU The macro ALTERNATIVE_CODE() allows assembly code to patch in a series of new assembler statements given at a specific start address. The ALT_COND_RUN_ON_QEMU condition is true if the kernel is started in a qemu emulation. Signed-off-by: Helge Deller --- arch/parisc/include/asm/alternative.h | 11 ++++++++++- arch/parisc/kernel/alternative.c | 23 +++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h index 793d8baa3a10..0ec54f43d6d2 100644 --- a/arch/parisc/include/asm/alternative.h +++ b/arch/parisc/include/asm/alternative.h @@ -8,6 +8,7 @@ #define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */ #define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */ #define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */ +#define ALT_COND_RUN_ON_QEMU 0x20 /* if running on QEMU */ #define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */ #define INSN_NOP 0x08000240 /* nop */ @@ -21,7 +22,7 @@ struct alt_instr { s32 orig_offset; /* offset to original instructions */ - u32 len; /* end of original instructions */ + s32 len; /* end of original instructions */ u32 cond; /* see ALT_COND_XXX */ u32 replacement; /* replacement instruction or code */ }; @@ -40,12 +41,20 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, #else +/* to replace one single instructions by a new instruction */ #define ALTERNATIVE(from, to, cond, replacement)\ .section .altinstructions, "aw" ! \ .word (from - .), (to - from)/4 ! \ .word cond, replacement ! \ .previous +/* to replace multiple instructions by new code */ +#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\ + .section .altinstructions, "aw" ! \ + .word (from - .), -num_instructions ! \ + .word cond, (new_instr_ptr - .) ! \ + .previous + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PARISC_ALTERNATIVE_H */ diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c index ca1f5ca0540a..3c66d5c4d90d 100644 --- a/arch/parisc/kernel/alternative.c +++ b/arch/parisc/kernel/alternative.c @@ -28,7 +28,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, for (entry = start; entry < end; entry++, index++) { - u32 *from, len, cond, replacement; + u32 *from, cond, replacement; + s32 len; from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); len = entry->len; @@ -49,6 +50,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, continue; if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0)) continue; + if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu) + continue; /* * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit @@ -74,11 +77,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start, if (replacement == INSN_NOP && len > 1) replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ - pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", - index, cond, len, from, replacement); - - /* Replace instruction */ - *from = replacement; + pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n", + index, cond, len, replacement, from, from); + + if (len < 0) { + /* Replace multiple instruction by new code */ + u32 *source; + len = -len; + source = (u32 *)((ulong)&entry->replacement + entry->replacement); + memcpy(from, source, 4 * len); + } else { + /* Replace by one instruction */ + *from = replacement; + } applied++; } -- GitLab From a5ff2130a4d98d22377e5fdab87d713f4b17f4f2 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 12 Aug 2019 19:13:20 +0200 Subject: [PATCH 2698/7155] parisc: speed up flush_tlb_all_local with qemu When started in qemu, we know that qemu will drop all local TLB entries on any pxtlbe instruction. So, if we detect qemu, replace the whole flush_tlb_all_local function by one pdtlbe instruction. Signed-off-by: Helge Deller --- arch/parisc/kernel/pacache.S | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index df46b0e5a915..fa092ed1e837 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -174,6 +174,15 @@ fdtdone: 2: bv %r0(%r2) nop + + /* + * When running in qemu, drop whole flush_tlb_all_local function and + * replace by one pdtlbe instruction, for which QEMU will drop all + * local TLB entries. + */ +3: pdtlbe %r0(%sr1,%r0) + bv,n %r0(%r2) + ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b) ENDPROC_CFI(flush_tlb_all_local) .import cache_info,data -- GitLab From 8069e69a9792402b52eff61e5bb874fa94798fc9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 11 Aug 2019 10:05:39 +0200 Subject: [PATCH 2699/7155] gpio: intel-mid: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-intel-mid.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 4e803baf980e..4d835f9089df 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -329,6 +329,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, u32 gpio_base; u32 irq_base; int retval; + struct gpio_irq_chip *girq; struct intel_mid_gpio_ddata *ddata = (struct intel_mid_gpio_ddata *)id->driver_data; @@ -369,6 +370,22 @@ static int intel_gpio_probe(struct pci_dev *pdev, spin_lock_init(&priv->lock); + girq = &priv->chip.irq; + girq->chip = &intel_mid_irqchip; + girq->parent_handler = intel_mid_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = pdev->irq; + girq->first = irq_base; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + + intel_mid_irq_init_hw(priv); + pci_set_drvdata(pdev, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { @@ -376,24 +393,6 @@ static int intel_gpio_probe(struct pci_dev *pdev, return retval; } - retval = gpiochip_irqchip_add(&priv->chip, - &intel_mid_irqchip, - irq_base, - handle_simple_irq, - IRQ_TYPE_NONE); - if (retval) { - dev_err(&pdev->dev, - "could not connect irqchip to gpiochip\n"); - return retval; - } - - intel_mid_irq_init_hw(priv); - - gpiochip_set_chained_irqchip(&priv->chip, - &intel_mid_irqchip, - pdev->irq, - intel_mid_irq_handler); - pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); -- GitLab From 7b1e889436a156c2c88953fbc5602a64a75889bd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Aug 2019 10:13:51 +0200 Subject: [PATCH 2700/7155] gpio: lynxpoint: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-lynxpoint.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 31b4a091ab60..6bb9741ad036 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -358,25 +358,30 @@ static int lp_gpio_probe(struct platform_device *pdev) gc->can_sleep = false; gc->parent = dev; - ret = devm_gpiochip_add_data(dev, gc, lg); - if (ret) { - dev_err(dev, "failed adding lp-gpio chip\n"); - return ret; - } - /* set up interrupts */ if (irq_rc && irq_rc->start) { + struct gpio_irq_chip *girq; + + girq = &gc->irq; + girq->chip = &lp_irqchip; + girq->parent_handler = lp_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = (unsigned)irq_rc->start; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + lp_gpio_irq_init_hw(lg); - ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add irqchip\n"); - return ret; - } + } - gpiochip_set_chained_irqchip(gc, &lp_irqchip, - (unsigned)irq_rc->start, - lp_gpio_irq_handler); + ret = devm_gpiochip_add_data(dev, gc, lg); + if (ret) { + dev_err(dev, "failed adding lp-gpio chip\n"); + return ret; } pm_runtime_enable(dev); -- GitLab From 8f86a5b4ad679e4836733b47414226074eee4e4d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Aug 2019 10:23:31 +0200 Subject: [PATCH 2701/7155] gpio: merrifield: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 3302125e5265..4f27ddfe1e2f 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -397,6 +397,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id { const struct mrfld_gpio_pinrange *range; const char *pinctrl_dev_name; + struct gpio_irq_chip *girq; struct mrfld_gpio *priv; u32 gpio_base, irq_base; void __iomem *base; @@ -444,6 +445,21 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id raw_spin_lock_init(&priv->lock); + girq = &priv->chip.irq; + girq->chip = &mrfld_irqchip; + girq->parent_handler = mrfld_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = pdev->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + mrfld_irq_init_hw(priv); + pci_set_drvdata(pdev, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { @@ -465,18 +481,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id } } - retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, - handle_bad_irq, IRQ_TYPE_NONE); - if (retval) { - dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); - return retval; - } - - mrfld_irq_init_hw(priv); - - gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq, - mrfld_irq_handler); - return 0; } -- GitLab From 68b953aeb50d9206de27d6c216e301f01dfac34d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 12 Aug 2019 11:06:23 -0500 Subject: [PATCH 2702/7155] ASoC: SOF: Intel: hda: fixup HDaudio topology name with DMIC number The SOF project maintains 6 topologies for HDaudio (iDisp or HDaudio+iDisp, no DMIC, 2 DMICs, 4 DMICs). The user is currently required to manually rename the topology file used in /lib/firmware/intel/sof-tplg. We can do better to avoid such renames and use logic to select the relevant file. The NHLT information can be used to figure out which topology file should be used. Alternatively, when NHLT is not present in ACPI tables or is possibly incorrect, a module parameter can provide that information, e.g. on Up^2 board with the test DMIC kit. Tested on Up^2 board and Acer Swift-SF314-55 Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190812160623.20821-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 1 + sound/soc/sof/intel/hda.c | 75 +++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index dd14ce92fe10..545071afbe18 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -254,6 +254,7 @@ config SND_SOC_SOF_HDA tristate select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC + select SND_INTEL_NHLT help This option is not user-selectable but automagically handled by 'select' statements at a higher level diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 28eb780494aa..c97c004afa43 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include "../ops.h" @@ -49,6 +50,12 @@ module_param_named(use_msi, hda_use_msi, bool, 0444); MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static int hda_dmic_num = -1; +module_param_named(dmic_num, hda_dmic_num, int, 0444); +MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); +#endif + static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"}, {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"}, @@ -283,8 +290,26 @@ static int hda_init(struct snd_sof_dev *sdev) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static int check_nhlt_dmic(struct snd_sof_dev *sdev) +{ + struct nhlt_acpi_table *nhlt; + int dmic_num; + + nhlt = intel_nhlt_init(sdev->dev); + if (nhlt) { + dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt); + intel_nhlt_free(nhlt); + if (dmic_num == 2 || dmic_num == 4) + return dmic_num; + } + + return 0; +} + static const char *fixup_tplg_name(struct snd_sof_dev *sdev, - const char *sof_tplg_filename) + const char *sof_tplg_filename, + const char *idisp_str, + const char *dmic_str) { const char *tplg_filename = NULL; char *filename; @@ -298,7 +323,8 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, split_ext = strsep(&filename, "."); if (split_ext) { tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, - "%s-idisp.tplg", split_ext); + "%s%s%s.tplg", + split_ext, idisp_str, dmic_str); if (!tplg_filename) return NULL; } @@ -317,6 +343,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev) struct snd_sof_pdata *pdata = sdev->pdata; struct snd_soc_acpi_mach *mach; const char *tplg_filename; + const char *idisp_str; + const char *dmic_str; + int dmic_num; int codec_num = 0; int i; #endif @@ -381,17 +410,39 @@ static int hda_init_caps(struct snd_sof_dev *sdev) dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); - /* fixup topology file for HDMI only platforms */ - if (codec_num == 1) { - /* use local variable for readability */ - tplg_filename = pdata->tplg_filename; - tplg_filename = fixup_tplg_name(sdev, tplg_filename); - if (!tplg_filename) { - hda_codec_i915_exit(sdev); - return ret; - } - pdata->tplg_filename = tplg_filename; + if (codec_num == 1) + idisp_str = "-idisp"; + else + idisp_str = ""; + + /* first check NHLT for DMICs */ + dmic_num = check_nhlt_dmic(sdev); + + /* allow for module parameter override */ + if (hda_dmic_num != -1) + dmic_num = hda_dmic_num; + + switch (dmic_num) { + case 2: + dmic_str = "-2ch"; + break; + case 4: + dmic_str = "-4ch"; + break; + default: + dmic_num = 0; + dmic_str = ""; + break; + } + + tplg_filename = pdata->tplg_filename; + tplg_filename = fixup_tplg_name(sdev, tplg_filename, + idisp_str, dmic_str); + if (!tplg_filename) { + hda_codec_i915_exit(sdev); + return ret; } + pdata->tplg_filename = tplg_filename; } } -- GitLab From e78a7614f3876ac649b3df608789cb6ef74d0480 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Jun 2019 07:46:43 -0700 Subject: [PATCH 2703/7155] idle: Prevent late-arriving interrupts from disrupting offline Scheduling-clock interrupts can arrive late in the CPU-offline process, after idle entry and the subsequent call to cpuhp_report_idle_dead(). Once execution passes the call to rcu_report_dead(), RCU is ignoring the CPU, which results in lockdep complaints when the interrupt handler uses RCU: ------------------------------------------------------------------------ ============================= WARNING: suspicious RCU usage 5.2.0-rc1+ #681 Not tainted ----------------------------- kernel/sched/fair.c:9542 suspicious rcu_dereference_check() usage! other info that might help us debug this: RCU used illegally from offline CPU! rcu_scheduler_active = 2, debug_locks = 1 no locks held by swapper/5/0. stack backtrace: CPU: 5 PID: 0 Comm: swapper/5 Not tainted 5.2.0-rc1+ #681 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0x5e/0x8b trigger_load_balance+0xa8/0x390 ? tick_sched_do_timer+0x60/0x60 update_process_times+0x3b/0x50 tick_sched_handle+0x2f/0x40 tick_sched_timer+0x32/0x70 __hrtimer_run_queues+0xd3/0x3b0 hrtimer_interrupt+0x11d/0x270 ? sched_clock_local+0xc/0x74 smp_apic_timer_interrupt+0x79/0x200 apic_timer_interrupt+0xf/0x20 RIP: 0010:delay_tsc+0x22/0x50 Code: ff 0f 1f 80 00 00 00 00 65 44 8b 05 18 a7 11 48 0f ae e8 0f 31 48 89 d6 48 c1 e6 20 48 09 c6 eb 0e f3 90 65 8b 05 fe a6 11 48 <41> 39 c0 75 18 0f ae e8 0f 31 48 c1 e2 20 48 09 c2 48 89 d0 48 29 RSP: 0000:ffff8f92c0157ed0 EFLAGS: 00000212 ORIG_RAX: ffffffffffffff13 RAX: 0000000000000005 RBX: ffff8c861f356400 RCX: ffff8f92c0157e64 RDX: 000000321214c8cc RSI: 00000032120daa7f RDI: 0000000000260f15 RBP: 0000000000000005 R08: 0000000000000005 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000000 R13: 0000000000000000 R14: ffff8c861ee18000 R15: ffff8c861ee18000 cpuhp_report_idle_dead+0x31/0x60 do_idle+0x1d5/0x200 ? _raw_spin_unlock_irqrestore+0x2d/0x40 cpu_startup_entry+0x14/0x20 start_secondary+0x151/0x170 secondary_startup_64+0xa4/0xb0 ------------------------------------------------------------------------ This happens rarely, but can be forced by happen more often by placing delays in cpuhp_report_idle_dead() following the call to rcu_report_dead(). With this in place, the following rcutorture scenario reproduces the problem within a few minutes: tools/testing/selftests/rcutorture/bin/kvm.sh --cpus 8 --duration 5 --kconfig "CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y" --configs "TREE04" This commit uses the crude but effective expedient of moving the disabling of interrupts within the idle loop to precede the cpu_is_offline() check. It also invokes tick_nohz_idle_stop_tick() instead of tick_nohz_idle_stop_tick_protected() to shut off the scheduling-clock interrupt. Signed-off-by: Peter Zijlstra Cc: Frederic Weisbecker Cc: Thomas Gleixner Cc: Ingo Molnar [ paulmck: Revert tick_nohz_idle_stop_tick_protected() removal, new callers. ] Signed-off-by: Paul E. McKenney --- kernel/sched/idle.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 80940939b733..e4bc4aa739b8 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -241,13 +241,14 @@ static void do_idle(void) check_pgt_cache(); rmb(); + local_irq_disable(); + if (cpu_is_offline(cpu)) { - tick_nohz_idle_stop_tick_protected(); + tick_nohz_idle_stop_tick(); cpuhp_report_idle_dead(); arch_cpu_idle_dead(); } - local_irq_disable(); arch_cpu_idle_enter(); /* -- GitLab From b823cafa7501f946a37dce5aa1e576a0b2f31ed9 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 5 Jul 2019 08:05:10 -0700 Subject: [PATCH 2704/7155] rcu: Remove redundant "if" condition from rcu_gp_is_expedited() Because rcu_expedited_nesting is initialized to 1 and not decremented until just before init is spawned, rcu_expedited_nesting is guaranteed to be non-zero whenever rcu_scheduler_active == RCU_SCHEDULER_INIT. This commit therefore removes this redundant "if" equality test. Signed-off-by: Paul E. McKenney Reviewed-by: Joel Fernandes (Google) --- kernel/rcu/update.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 249517058b13..64e9cc8609e7 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -136,8 +136,7 @@ static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1); */ bool rcu_gp_is_expedited(void) { - return rcu_expedited || atomic_read(&rcu_expedited_nesting) || - rcu_scheduler_active == RCU_SCHEDULER_INIT; + return rcu_expedited || atomic_read(&rcu_expedited_nesting); } EXPORT_SYMBOL_GPL(rcu_gp_is_expedited); -- GitLab From 1d5087ab964d84e5a0cfe5059cf5e929127d573f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 May 2015 14:50:06 -0700 Subject: [PATCH 2705/7155] arm: Use common outgoing-CPU-notification code This commit removes the open-coded CPU-offline notification with new common code. In particular, this change avoids calling scheduler code using RCU from an offline CPU that RCU is ignoring. This is a minimal change. A more intrusive change might invoke the cpu_check_up_prepare() and cpu_set_state_online() functions at CPU-online time, which would allow onlining throw an error if the CPU did not go offline properly. Signed-off-by: Paul E. McKenney Cc: linux-arm-kernel@lists.infradead.org Cc: Russell King Cc: Mark Rutland Cc: Dietmar Eggemann --- arch/arm/kernel/smp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index aab8ba40ce38..4b0bab2607e4 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -264,15 +264,13 @@ int __cpu_disable(void) return 0; } -static DECLARE_COMPLETION(cpu_died); - /* * called on the thread which is asking for a CPU to be shutdown - * waits until shutdown has completed, or it is timed out. */ void __cpu_die(unsigned int cpu) { - if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { + if (!cpu_wait_death(cpu, 5)) { pr_err("CPU%u: cpu didn't die\n", cpu); return; } @@ -319,7 +317,7 @@ void arch_cpu_idle_dead(void) * this returns, power and/or clocks can be removed at any point * from this CPU and its cache by platform_cpu_kill(). */ - complete(&cpu_died); + (void)cpu_report_death(); /* * Ensure that the cache lines associated with that completion are -- GitLab From 511b44f7598ce602f9efce687ca9eec013967d9b Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Mon, 29 Jul 2019 13:25:57 +0530 Subject: [PATCH 2706/7155] rcu: Fix spelling mistake "greate"->"great" This commit fixes a spelling mistake in file tree_exp.h. Signed-off-by: Mukesh Ojha Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_exp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h index 513b403b683b..d632cd019597 100644 --- a/kernel/rcu/tree_exp.h +++ b/kernel/rcu/tree_exp.h @@ -781,7 +781,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp) * other hand, if the CPU is not in an RCU read-side critical section, * the IPI handler reports the quiescent state immediately. * - * Although this is a greate improvement over previous expedited + * Although this is a great improvement over previous expedited * implementations, it is still unfriendly to real-time workloads, so is * thus not recommended for any sort of common-case code. In fact, if * you are using synchronize_rcu_expedited() in a loop, please restructure -- GitLab From ba31ebfa7b749906e0befcc1e0c0db5e7463d55e Mon Sep 17 00:00:00 2001 From: Andrea Parri Date: Mon, 5 Aug 2019 14:15:17 +0200 Subject: [PATCH 2707/7155] MAINTAINERS: Update e-mail address for Andrea Parri My @amarulasolutions.com address stopped working this July, so update to my @gmail.com address where you'll still be able to reach me. Signed-off-by: Andrea Parri Cc: Alan Stern Cc: Will Deacon Cc: Peter Zijlstra Cc: Boqun Feng Cc: Nicholas Piggin Cc: David Howells Cc: Jade Alglave Cc: Luc Maranget Cc: "Paul E. McKenney" Cc: Akira Yokosawa Cc: Daniel Lustig Signed-off-by: Paul E. McKenney --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6426db5198f0..527317026492 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9326,7 +9326,7 @@ F: drivers/misc/lkdtm/* LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM) M: Alan Stern -M: Andrea Parri +M: Andrea Parri M: Will Deacon M: Peter Zijlstra M: Boqun Feng -- GitLab From 57fc032ad643ffd018d66bd4c1bd3a91de4841e8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Jul 2019 10:58:41 -0300 Subject: [PATCH 2708/7155] perf session: Avoid infinite loop when seeing invalid header.size Vince reported that when fuzzing the userland perf tool with a bogus perf.data file he got into a infinite loop in 'perf report'. Changing the return of fetch_mmaped_event() to ERR_PTR(-EINVAL) for that case gets us out of that infinite loop. Reported-by: Vince Weaver Tested-by: Vince Weaver Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: https://lkml.kernel.org/r/20190726211415.GE24867@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 11e6093c941b..b9fe71d11bf6 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -1955,7 +1956,9 @@ fetch_mmaped_event(struct perf_session *session, /* We're not fetching the event so swap back again */ if (session->header.needs_swap) perf_event_header__bswap(&event->header); - return NULL; + pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx: fuzzed perf.data?\n", + __func__, head, event->header.size, mmap_size); + return ERR_PTR(-EINVAL); } return event; @@ -1973,6 +1976,9 @@ static int __perf_session__process_decomp_events(struct perf_session *session) while (decomp->head < decomp->size && !session_done()) { union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data); + if (IS_ERR(event)) + return PTR_ERR(event); + if (!event) break; @@ -2072,6 +2078,9 @@ reader__process_events(struct reader *rd, struct perf_session *session, more: event = fetch_mmaped_event(session, head, mmap_size, buf); + if (IS_ERR(event)) + return PTR_ERR(event); + if (!event) { if (mmaps[map_idx]) { munmap(mmaps[map_idx], mmap_size); -- GitLab From 61a461fcbd62d42c29a1ea6a9cc3838ad9f49401 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Jul 2019 11:20:55 -0300 Subject: [PATCH 2709/7155] perf config: Honour $PERF_CONFIG env var to specify alternate .perfconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We had this comment in Documentation/perf_counter/config.c, i.e. since when we got this from the git sources, but never really did that getenv("PERF_CONFIG"), do it now as I need to disable whatever ~/.perfconfig root has so that tests parsing tool output are done for the expected default output or that we specify an alternate config file that when read will make the tools produce expected output. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Cc: Taeung Song Fixes: 078006012401 ("perf_counter tools: add in basic glue from Git") Link: https://lkml.kernel.org/n/tip-jo209zac9rut0dz1rqvbdlgm@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/perf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 97e2628ea5dd..d4e4d53e8b44 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -441,6 +441,9 @@ int main(int argc, const char **argv) srandom(time(NULL)); + /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ + config_exclusive_filename = getenv("PERF_CONFIG"); + err = perf_config(perf_default_config, NULL); if (err) return err; -- GitLab From 5de9e5fda05b580c036e1fec6e2d8bf78eb2ac9d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Jul 2019 11:30:37 -0300 Subject: [PATCH 2710/7155] perf config: Document the PERF_CONFIG environment variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was a provision for setting this variable, but not the getenv("PERF_CONFIG") call to set it, as this was fixed in the previous cset, document that it can be used to ask for using an alternative .perfconfig file or to disable reading whatever file exists in the system or home directory, i.e. using: export PERF_CONFIG=/dev/null Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Cc: Taeung Song Link: https://lkml.kernel.org/n/tip-0u4o967hsk7j0o50zp9ctn89@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index e4aa268d2e38..c599623a1f3d 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -40,6 +40,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration. The file '$(sysconfdir)/perfconfig' can be used to store a system-wide default configuration. +One an disable reading config files by setting the PERF_CONFIG environment +variable to /dev/null, or provide an alternate config file by setting that +variable. + When reading or writing, the values are read from the system and user configuration files by default, and options '--system' and '--user' can be used to tell the command to read from or write to only that location. -- GitLab From 4fe94ce1c6ba678b5f12b94bb9996eea4fc99e85 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Jul 2019 11:37:44 -0300 Subject: [PATCH 2711/7155] perf test vfs_getname: Disable ~/.perfconfig to get default output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To get the expected output we have to ignore whatever changes the user has in its ~/.perfconfig file, so set PERF_CONFIG to /dev/null to achieve that. Before: # egrep 'trace|show_' ~/.perfconfig [trace] show_zeros = yes show_duration = no show_timestamp = no show_arg_names = no show_prefix = yes # echo $PERF_CONFIG # perf test "trace + vfs_getname" 70: Check open filename arg using perf trace + vfs_getname: FAILED! # export PERF_CONFIG=/dev/null # perf test "trace + vfs_getname" 70: Check open filename arg using perf trace + vfs_getname: Ok # After: # egrep 'trace|show_' ~/.perfconfig [trace] show_zeros = yes show_duration = no show_timestamp = no show_arg_names = no show_prefix = yes # echo $PERF_CONFIG # perf test "trace + vfs_getname" 70: Check open filename arg using perf trace + vfs_getname: Ok # Cc: Adrian Hunter Cc: Jiri Olsa Cc: Luis Cláudio Gonçalves Cc: Namhyung Kim Cc: Taeung Song Link: https://lkml.kernel.org/n/tip-3up27pexg5i3exuzqrvt4m8u@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/trace+probe_vfs_getname.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh index 45d269b0157e..11cc2af13f2b 100755 --- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh +++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh @@ -32,6 +32,10 @@ if [ $err -ne 0 ] ; then exit $err fi +# Do not use whatever ~/.perfconfig file, it may change the output +# via trace.{show_timestamp,show_prefix,etc} +export PERF_CONFIG=/dev/null + trace_open_vfs_getname err=$? rm -f ${file} -- GitLab From 2b75863b0845764529e01014a5c90664d8044cbe Mon Sep 17 00:00:00 2001 From: Luke Mujica Date: Fri, 19 Jul 2019 13:22:53 -0700 Subject: [PATCH 2712/7155] perf tools: Fix paths in include statements These paths point to the wrong location but still work because they get picked up by a -I flag that happens to direct to the correct file. Fix paths to lead to the actual file location without help from include flags. Signed-off-by: Luke Mujica Cc: Alexander Shishkin Cc: Ian Rogers Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20190719202253.220261-1-lukemujica@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/kvm-stat.c | 4 ++-- tools/perf/arch/x86/util/tsc.c | 6 +++--- tools/perf/ui/helpline.c | 4 ++-- tools/perf/ui/util.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c index 54a3f2373c35..81b531a707bf 100644 --- a/tools/perf/arch/x86/util/kvm-stat.c +++ b/tools/perf/arch/x86/util/kvm-stat.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include -#include "../../util/kvm-stat.h" -#include "../../util/evsel.h" +#include "../../../util/kvm-stat.h" +#include "../../../util/evsel.h" #include #include #include diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index 950539f9a4f7..b1eb963b4a6e 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c @@ -5,10 +5,10 @@ #include #include -#include "../../perf.h" +#include "../../../perf.h" #include -#include "../../util/debug.h" -#include "../../util/tsc.h" +#include "../../../util/debug.h" +#include "../../../util/tsc.h" int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, struct perf_tsc_conversion *tc) diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c index b3c421429ed4..54bcd08df87e 100644 --- a/tools/perf/ui/helpline.c +++ b/tools/perf/ui/helpline.c @@ -3,10 +3,10 @@ #include #include -#include "../debug.h" +#include "../util/debug.h" #include "helpline.h" #include "ui.h" -#include "../util.h" +#include "../util/util.h" char ui_helpline__current[512]; diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c index 63bf06e80ab9..9ed76e88a3e4 100644 --- a/tools/perf/ui/util.c +++ b/tools/perf/ui/util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "util.h" -#include "../debug.h" +#include "../util/debug.h" /* -- GitLab From b115df076d337a727017538d11d7d46f5bcbff15 Mon Sep 17 00:00:00 2001 From: Haiyan Song Date: Wed, 12 Jun 2019 16:15:42 +0800 Subject: [PATCH 2713/7155] perf vendor events intel: Add Icelake V1.00 event file Add a Intel event file for perf. Signed-off-by: Haiyan Song Reviewed-by: Kan Liang Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: Peter Zijlstra Link: https://lkml.kernel.org/r/8859095e-5b02-d6b7-fbdc-3f42b714bae0@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/icelake/cache.json | 552 +++++++++++ .../arch/x86/icelake/floating-point.json | 102 ++ .../pmu-events/arch/x86/icelake/frontend.json | 424 +++++++++ .../pmu-events/arch/x86/icelake/memory.json | 410 ++++++++ .../pmu-events/arch/x86/icelake/other.json | 121 +++ .../pmu-events/arch/x86/icelake/pipeline.json | 892 ++++++++++++++++++ .../arch/x86/icelake/virtual-memory.json | 236 +++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 + 8 files changed, 2739 insertions(+) create mode 100644 tools/perf/pmu-events/arch/x86/icelake/cache.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/floating-point.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/frontend.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/memory.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/other.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/pipeline.json create mode 100644 tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json diff --git a/tools/perf/pmu-events/arch/x86/icelake/cache.json b/tools/perf/pmu-events/arch/x86/icelake/cache.json new file mode 100644 index 000000000000..3529fc338c17 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/cache.json @@ -0,0 +1,552 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0x21", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Demand Data Read miss L2, no rejects" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0x22", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.RFO_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "RFO requests that miss L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts L2 cache misses when fetching instructions.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0x24", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.CODE_RD_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "L2 cache misses when fetching instructions" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts demand requests that miss L2 cache.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0x27", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.ALL_DEMAND_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Demand requests that miss L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Software prefetch requests that miss the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0x28", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.SWPF_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "SW prefetch requests that miss L2 cache." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of demand Data Read requests initiated by load instructions that hit L2 cache.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xc1", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Demand Data Read requests that hit L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xc2", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.RFO_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "RFO requests that hit L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xc4", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.CODE_RD_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "L2 cache hits when fetching instructions, code reads." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Software prefetch requests that hit the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xc8", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.SWPF_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "SW prefetch requests that hit L2 cache." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xe1", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD", + "SampleAfterValue": "200003", + "BriefDescription": "Demand Data Read requests" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xe2", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.ALL_RFO", + "SampleAfterValue": "200003", + "BriefDescription": "RFO requests to L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the total number of L2 code requests.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xe4", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.ALL_CODE_RD", + "SampleAfterValue": "200003", + "BriefDescription": "L2 code requests" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts demand requests to L2 cache.", + "EventCode": "0x24", + "Counter": "0,1,2,3", + "UMask": "0xe7", + "PEBScounters": "0,1,2,3", + "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES", + "SampleAfterValue": "200003", + "BriefDescription": "Demand requests to L2 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of L1D misses that are outstanding in each cycle, that is each cycle the number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch. Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.", + "EventCode": "0x48", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "L1D_PEND_MISS.PENDING", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of L1D misses that are outstanding" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts duration of L1D miss outstanding in cycles.", + "EventCode": "0x48", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "L1D_PEND_MISS.PENDING_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles with L1D load Misses outstanding.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "EventCode": "0x48", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "L1D_PEND_MISS.FB_FULL", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailablability." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "EventCode": "0x48", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "L1D_PEND_MISS.FB_FULL_PERIODS", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability.", + "CounterMask": "1", + "EdgeDetect": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of cycles a demand request has waited due to L1D due to lack of L2 resources. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "EventCode": "0x48", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "L1D_PEND_MISS.L2_STALL", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of cycles a demand request has waited due to L1D due to lack of L2 resources." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.", + "EventCode": "0x51", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "L1D.REPLACEMENT", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts the number of cache lines replaced in L1 data cache." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.", + "EventCode": "0x60", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.", + "EventCode": "0x60", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", + "SampleAfterValue": "2000003", + "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.", + "EventCode": "0x60", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.", + "EventCode": "0xB0", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD", + "SampleAfterValue": "100003", + "BriefDescription": "Demand Data Read requests sent to uncore" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.", + "EventCode": "0xB0", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS.DEMAND_RFO", + "SampleAfterValue": "100003", + "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.", + "EventCode": "0xB0", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD", + "SampleAfterValue": "100003", + "BriefDescription": "Demand and prefetch data reads" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..", + "EventCode": "0xB0", + "Counter": "0,1,2,3", + "UMask": "0x80", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS", + "SampleAfterValue": "100003", + "BriefDescription": "Any memory transaction that reached the SQ." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions that true miss the STLB.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x11", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS", + "SampleAfterValue": "100003", + "BriefDescription": "Retired load instructions that miss the STLB.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired store instructions that true miss the STLB.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x12", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES", + "SampleAfterValue": "100003", + "BriefDescription": "Retired store instructions that miss the STLB.", + "Data_LA": "1", + "L1_Hit_Indication": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with locked access.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x21", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.LOCK_LOADS", + "SampleAfterValue": "100007", + "BriefDescription": "Retired load instructions with locked access.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x41", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.SPLIT_LOADS", + "SampleAfterValue": "100003", + "BriefDescription": "Retired load instructions that split across a cacheline boundary.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x42", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.SPLIT_STORES", + "SampleAfterValue": "100003", + "BriefDescription": "Retired store instructions that split across a cacheline boundary.", + "Data_LA": "1", + "L1_Hit_Indication": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all retired load instructions. This event accounts for SW prefetch instructions for loads.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x81", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.ALL_LOADS", + "SampleAfterValue": "2000003", + "BriefDescription": "All retired load instructions.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all retired store instructions. This event account for SW prefetch instructions and PREFETCHW instruction for stores.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x82", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_INST_RETIRED.ALL_STORES", + "SampleAfterValue": "2000003", + "BriefDescription": "All retired store instructions.", + "Data_LA": "1", + "L1_Hit_Indication": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L1_HIT", + "SampleAfterValue": "2000003", + "BriefDescription": "Retired load instructions with L1 cache hits as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with L2 cache hits as data sources.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L2_HIT", + "SampleAfterValue": "100003", + "BriefDescription": "Retired load instructions with L2 cache hits as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L3_HIT", + "SampleAfterValue": "50021", + "BriefDescription": "Retired load instructions with L3 cache hits as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L1_MISS", + "SampleAfterValue": "100003", + "BriefDescription": "Retired load instructions missed L1 cache as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions missed L2 cache as data sources.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L2_MISS", + "SampleAfterValue": "50021", + "BriefDescription": "Retired load instructions missed L2 cache as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.L3_MISS", + "SampleAfterValue": "100007", + "BriefDescription": "Retired load instructions missed L3 cache as data sources", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.", + "EventCode": "0xd1", + "Counter": "0,1,2,3", + "UMask": "0x40", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_RETIRED.FB_HIT", + "SampleAfterValue": "100007", + "BriefDescription": "Number of completed demand load requests that missed the L1, but hit the FB(fill buffer), because a preceding miss to the same cacheline initiated the line to be brought into L1, but data is not yet ready in L1.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.", + "EventCode": "0xd2", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS", + "SampleAfterValue": "20011", + "BriefDescription": "Retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache.", + "EventCode": "0xd2", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT", + "SampleAfterValue": "20011", + "BriefDescription": "Retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions whose data sources were HitM responses from shared L3.", + "EventCode": "0xd2", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM", + "SampleAfterValue": "20011", + "BriefDescription": "Retired load instructions whose data sources were HitM responses from shared L3", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired load instructions whose data sources were hits in L3 without snoops required.", + "EventCode": "0xd2", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE", + "SampleAfterValue": "100003", + "BriefDescription": "Retired load instructions whose data sources were hits in L3 without snoops required", + "Data_LA": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.", + "EventCode": "0xF1", + "Counter": "0,1,2,3", + "UMask": "0x1f", + "PEBScounters": "0,1,2,3", + "EventName": "L2_LINES_IN.ALL", + "SampleAfterValue": "100003", + "BriefDescription": "L2 cache lines filling L2" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the cycles for which the thread is active and the superQ cannot take any more entries.", + "EventCode": "0xF4", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "SQ_MISC.SQ_FULL", + "SampleAfterValue": "100003", + "BriefDescription": "Cycles the thread is active and superQ cannot take any more entries." + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/floating-point.json b/tools/perf/pmu-events/arch/x86/icelake/floating-point.json new file mode 100644 index 000000000000..594c5551f610 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/floating-point.json @@ -0,0 +1,102 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all microcode Floating Point assists.", + "EventCode": "0xC1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "ASSISTS.FP", + "SampleAfterValue": "100003", + "BriefDescription": "Counts all microcode FP assists.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x8", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x10", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 RANGE FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element." + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/frontend.json b/tools/perf/pmu-events/arch/x86/icelake/frontend.json new file mode 100644 index 000000000000..9c3cfbfcec0f --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/frontend.json @@ -0,0 +1,424 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MITE_UOPS", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MITE_CYCLES_OK", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles MITE is delivering optimal number of Uops", + "CounterMask": "5" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MITE_CYCLES_ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles MITE is delivering any Uop", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.DSB_UOPS", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.DSB_CYCLES_OK", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles DSB is delivering optimal number of Uops", + "CounterMask": "5" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.DSB_CYCLES_ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x30", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MS_SWITCHES", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of switches from DSB or MITE to the MS", + "CounterMask": "1", + "EdgeDetect": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x30", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MS_UOPS", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops delivered to IDQ while MS is busy" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.", + "EventCode": "0x79", + "Counter": "0,1,2,3", + "UMask": "0x30", + "PEBScounters": "0,1,2,3", + "EventName": "IDQ.MS_CYCLES_ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when uops are being delivered to IDQ while MS is busy", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.", + "EventCode": "0x80", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE_16B.IFDATA_STALL", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.", + "EventCode": "0x83", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE_64B.IFTAG_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.", + "EventCode": "0x83", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE_64B.IFTAG_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles where a code fetch is stalled due to L1 instruction cache tag miss.", + "EventCode": "0x83", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE_64B.IFTAG_STALL", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "EventCode": "0x9C", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "EventCode": "0x9c", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled", + "CounterMask": "5" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "EventCode": "0x9C", + "Invert": "1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Decode Stream Buffer (DSB) is a Uop-cache that holds translations of previously fetched instructions that were decoded by the legacy x86 decode pipeline (MITE). This event counts fetch penalty cycles when a transition occurs from DSB to MITE.", + "EventCode": "0xAB", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "DSB-to-MITE switch true penalty cycles." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.", + "EventCode": "0xC6", + "MSRValue": "0x11", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.DSB_MISS", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired Instructions who experienced DSB miss.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Instructions who experienced Instruction L1 Cache true miss.", + "EventCode": "0xC6", + "MSRValue": "0x12", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.L1I_MISS", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Instructions who experienced Instruction L2 Cache true miss.", + "EventCode": "0xC6", + "MSRValue": "0x13", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.L2_MISS", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.", + "EventCode": "0xC6", + "MSRValue": "0x14", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.ITLB_MISS", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired Instructions who experienced iTLB true miss.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.", + "EventCode": "0xC6", + "MSRValue": "0x15", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.STLB_MISS", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x500206", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_2", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x500406", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_4", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.", + "EventCode": "0xC6", + "MSRValue": "0x500806", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_8", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.", + "EventCode": "0xC6", + "MSRValue": "0x501006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_16", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.", + "EventCode": "0xC6", + "MSRValue": "0x502006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_32", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x504006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_64", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x508006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_128", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x510006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_256", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xC6", + "MSRValue": "0x520006", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_512", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.", + "EventCode": "0xC6", + "MSRValue": "0x100206", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1", + "MSRIndex": "0x3F7", + "SampleAfterValue": "100007", + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.", + "TakenAlone": "1" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/memory.json b/tools/perf/pmu-events/arch/x86/icelake/memory.json new file mode 100644 index 000000000000..f158366b9dd6 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/memory.json @@ -0,0 +1,410 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a TSX line had a cache conflict.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_CONFLICT", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Speculatively counts the number Transactional Synchronization Extensions (TSX) Aborts due to a data capacity limitation for transactional writes.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_CAPACITY_WRITE", + "SampleAfterValue": "2000003", + "BriefDescription": "Speculatively counts the number TSX Aborts due to a data capacity limitation for transactional writes." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a TSX Abort was triggered due to a non-release/commit store to lock.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK", + "SampleAfterValue": "100003", + "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a TSX Abort was triggered due to release/commit but data and address mismatch.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times we could not allocate Lock Buffer.", + "EventCode": "0x54", + "Counter": "0,1,2,3", + "UMask": "0x40", + "PEBScounters": "0,1,2,3", + "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Unfriendly TSX abort triggered by a vzeroupper instruction.", + "EventCode": "0x5d", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "TX_EXEC.MISC2", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed inside a transactional region" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Unfriendly TSX abort triggered by a nest count that is too deep.", + "EventCode": "0x5d", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "TX_EXEC.MISC3", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an instruction execution caused the transactional nest count supported to be exceeded" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.", + "CounterMask": "2" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0x6", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.", + "CounterMask": "6" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Demand Data Read requests who miss L3 cache.", + "EventCode": "0xB0", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", + "SampleAfterValue": "100003", + "BriefDescription": "Demand Data Read requests who miss L3 cache" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of Machine Clears detected dye to memory ordering. Memory Ordering Machine Clears may apply when a memory read may not conform to the memory ordering rules of the x86 architecture", + "EventCode": "0xc3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING", + "SampleAfterValue": "100003", + "BriefDescription": "Number of machine clears due to memory ordering conflicts." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times we entered an HLE region. Does not count nested transactions.", + "EventCode": "0xC8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.START", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution started." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times HLE commit succeeded.", + "EventCode": "0xC8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.COMMIT", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution successfully committed", + "Data_LA": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times HLE abort was triggered.", + "EventCode": "0xc8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.ABORTED", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one)." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).", + "EventCode": "0xC8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x8", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.ABORTED_MEM", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts)." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).", + "EventCode": "0xC8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.)." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an HLE execution aborted due to unfriendly events (such as interrupts).", + "EventCode": "0xC8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "HLE_RETIRED.ABORTED_EVENTS", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts)." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times we entered an RTM region. Does not count nested transactions.", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.START", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution started." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times RTM commit succeeded.", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.COMMIT", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution successfully committed" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times RTM abort was triggered.", + "EventCode": "0xc9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.ABORTED", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution aborted.", + "Data_LA": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x8", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.ABORTED_MEM", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an RTM execution aborted due to HLE-unfriendly instructions.", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an RTM execution aborted due to incompatible memory type.", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.ABORTED_MEMTYPE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).", + "EventCode": "0xC9", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RTM_RETIRED.ABORTED_EVENTS", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4", + "MSRIndex": "0x3F6", + "SampleAfterValue": "100003", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x8", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8", + "MSRIndex": "0x3F6", + "SampleAfterValue": "50021", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x10", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16", + "MSRIndex": "0x3F6", + "SampleAfterValue": "20011", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x20", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32", + "MSRIndex": "0x3F6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x40", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64", + "MSRIndex": "0x3F6", + "SampleAfterValue": "2003", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x80", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128", + "MSRIndex": "0x3F6", + "SampleAfterValue": "1009", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x100", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256", + "MSRIndex": "0x3F6", + "SampleAfterValue": "503", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.", + "TakenAlone": "1" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.", + "EventCode": "0xcd", + "MSRValue": "0x200", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512", + "MSRIndex": "0x3F6", + "SampleAfterValue": "101", + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.", + "TakenAlone": "1" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/other.json b/tools/perf/pmu-events/arch/x86/icelake/other.json new file mode 100644 index 000000000000..f8dfdb847224 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/other.json @@ -0,0 +1,121 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core. Software can use this event as the denominator for the top-level metrics of the Top-down Microarchitecture Analysis method. This event is counted on a designated fixed counter (Fixed Counter 3) and is an architectural event.", + "Counter": "35", + "UMask": "0x4", + "PEBScounters": "35", + "EventName": "TOPDOWN.SLOTS", + "SampleAfterValue": "10000003", + "BriefDescription": "Counts the number of available slots for an unhalted logical processor." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.", + "EventCode": "0x28", + "Counter": "0,1,2,3", + "UMask": "0x7", + "PEBScounters": "0,1,2,3", + "EventName": "CORE_POWER.LVL0_TURBO_LICENSE", + "SampleAfterValue": "200003", + "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.", + "EventCode": "0x28", + "Counter": "0,1,2,3", + "UMask": "0x18", + "PEBScounters": "0,1,2,3", + "EventName": "CORE_POWER.LVL1_TURBO_LICENSE", + "SampleAfterValue": "200003", + "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server microarchtecture). This includes high current AVX 512-bit instructions.", + "EventCode": "0x28", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "CORE_POWER.LVL2_TURBO_LICENSE", + "SampleAfterValue": "200003", + "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of PREFETCHNTA instructions executed.", + "EventCode": "0x32", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "SW_PREFETCH_ACCESS.NTA", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of PREFETCHNTA instructions executed." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of PREFETCHT0 instructions executed.", + "EventCode": "0x32", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "SW_PREFETCH_ACCESS.T0", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of PREFETCHT0 instructions executed." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of PREFETCHT1 or PREFETCHT2 instructions executed.", + "EventCode": "0x32", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "SW_PREFETCH_ACCESS.T1_T2", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of PREFETCHW instructions executed.", + "EventCode": "0x32", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "SW_PREFETCH_ACCESS.PREFETCHW", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of PREFETCHW instructions executed." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core.", + "EventCode": "0xa4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "TOPDOWN.SLOTS_P", + "SampleAfterValue": "10000003", + "BriefDescription": "Counts the number of available slots for an unhalted logical processor." + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "TOPDOWN.BACKEND_BOUND_SLOTS", + "SampleAfterValue": "10000003", + "BriefDescription": "Issue slots where no uops were being issued due to lack of back end resources." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of occurrences where a microcode assist is invoked by hardware Examples include AD (page Access Dirty), FP and AVX related assists.", + "EventCode": "0xc1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x7", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "ASSISTS.ANY", + "SampleAfterValue": "100003", + "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware." + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/pipeline.json b/tools/perf/pmu-events/arch/x86/icelake/pipeline.json new file mode 100644 index 000000000000..6d8311e634aa --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/pipeline.json @@ -0,0 +1,892 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "Counter": "32", + "UMask": "0x1", + "PEBScounters": "32", + "EventName": "INST_RETIRED.ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of instructions retired. Fixed Counter - architectural event" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "3", + "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled. Use on Fixed Counter 0.", + "Counter": "32", + "UMask": "0x1", + "PEBScounters": "32", + "EventName": "INST_RETIRED.PREC_DIST", + "SampleAfterValue": "2000003", + "BriefDescription": "Precise instruction retired event with a reduced effect of PEBS shadow in IP distribution" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.", + "Counter": "33", + "UMask": "0x2", + "PEBScounters": "33", + "EventName": "CPU_CLK_UNHALTED.THREAD", + "SampleAfterValue": "2000003", + "BriefDescription": "Core cycles when the thread is not in halt state" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.", + "Counter": "34", + "UMask": "0x3", + "PEBScounters": "34", + "EventName": "CPU_CLK_UNHALTED.REF_TSC", + "SampleAfterValue": "2000003", + "BriefDescription": "Reference cycles when the core is not in halt state." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when: a. preceding store conflicts with the load (incomplete overlap),b. store forwarding is impossible due to u-arch limitations, c. preceding lock RMW operations are not forwarded, d. store has the no-forward bit set (uncacheable/page-split/masked stores), e. all-blocking stores are used (mostly, fences and port I/O), and others. The most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events. See the table of not supported store forwards in the Optimization Guide.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "SampleAfterValue": "100003", + "BriefDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.NO_SR", + "SampleAfterValue": "100003", + "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times a load got blocked due to false dependencies in MOB due to partial compare on address.", + "EventCode": "0x07", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS", + "SampleAfterValue": "100003", + "BriefDescription": "False dependencies in MOB due to partial compare on address." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts core cycles when the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.", + "EventCode": "0x0D", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "INT_MISC.RECOVERY_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.", + "EventCode": "0x0D", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x3", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "INT_MISC.ALL_RECOVERY_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.", + "EventCode": "0x0d", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).", + "EventCode": "0x0E", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_ISSUED.ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops that RAT issues to RS" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.", + "EventCode": "0x0E", + "Invert": "1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_ISSUED.STALL_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when RAT does not issue Uops to RS for the thread", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.", + "EventCode": "0x14", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x9", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "ARITH.DIVIDER_ACTIVE", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.", + "EventCode": "0x3C", + "Counter": "0,1,2,3,4,5,6,7", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CPU_CLK_UNHALTED.THREAD_P", + "SampleAfterValue": "2000003", + "BriefDescription": "Thread cycles when thread is not in halt state" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts core crystal clock cycles when the thread is unhalted.", + "EventCode": "0x3C", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CPU_CLK_UNHALTED.REF_XCLK", + "SampleAfterValue": "25003", + "BriefDescription": "Core crystal clock cycles when the thread is unhalted." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Core crystal clock cycles when current thread is unhalted and the other thread is halted.", + "EventCode": "0x3C", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE", + "SampleAfterValue": "25003", + "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.", + "EventCode": "0x4c", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LOAD_HIT_PREFETCH.SWPF", + "SampleAfterValue": "100003", + "BriefDescription": "Counts the number of demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for this logical processor. This is usually caused when the front-end pipeline runs into stravation periods (e.g. branch mispredictions or i-cache misses)", + "EventCode": "0x5E", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RS_EVENTS.EMPTY_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to closely sample on front-end latency issues (see the FRONTEND_RETIRED event of designated precise events)", + "EventCode": "0x5E", + "Invert": "1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RS_EVENTS.EMPTY_END", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty.", + "CounterMask": "1", + "EdgeDetect": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.", + "EventCode": "0x87", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "ILD_STALL.LCP", + "SampleAfterValue": "2000003", + "BriefDescription": "Stalls caused by changing prefix length of the instruction." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_0", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 0" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_1", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 2 and 3.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_2_3", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 2 and 3" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 5 and 9.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x10", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_4_9", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 4 and 9" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_5", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 5" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_6", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 6" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 7 and 8.", + "EventCode": "0xa1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_DISPATCHED.PORT_7_8", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on port 7 and 8" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xa2", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RESOURCE_STALLS.SCOREBOARD", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts cycles where the pipeline is stalled due to serializing operations." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.", + "EventCode": "0xA2", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x8", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "RESOURCE_STALLS.SB", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync)." + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL", + "SampleAfterValue": "2000003", + "BriefDescription": "Total execution stalls.", + "CounterMask": "4" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0x5", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.", + "CounterMask": "5" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.", + "CounterMask": "8" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3", + "UMask": "0xc", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS", + "SampleAfterValue": "2000003", + "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.", + "CounterMask": "12" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x10", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles while memory subsystem has an outstanding load.", + "CounterMask": "16" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xA3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x14", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY", + "SampleAfterValue": "2000003", + "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.", + "CounterMask": "20" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.", + "EventCode": "0xa6", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "EXE_ACTIVITY.1_PORTS_UTIL", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.", + "EventCode": "0xa6", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "EXE_ACTIVITY.2_PORTS_UTIL", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles where the Store Buffer was full and no loads caused an execution stall.", + "EventCode": "0xA6", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "EXE_ACTIVITY.BOUND_ON_STORES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where the Store Buffer was full and no loads caused an execution stall.", + "CounterMask": "2" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.", + "EventCode": "0xa6", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops delivered to the back-end by the LSD(Loop Stream Detector).", + "EventCode": "0xA8", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LSD.UOPS", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of Uops delivered by the LSD." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).", + "EventCode": "0xA8", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LSD.CYCLES_ACTIVE", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the cycles when optimal number of uops is delivered by the LSD (Loop-stream detector).", + "EventCode": "0xa8", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LSD.CYCLES_OK", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles optimal number of Uops delivered by the LSD, but did not come from the decoder.", + "CounterMask": "5" + }, + { + "CollectPEBSRecord": "2", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.THREAD", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts the number of uops to be executed per-thread each cycle." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.", + "EventCode": "0xB1", + "Invert": "1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.STALL_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Cycles where at least 1 uop was executed per-thread.", + "EventCode": "0xb1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CYCLES_GE_1", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where at least 1 uop was executed per-thread", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Cycles where at least 2 uops were executed per-thread.", + "EventCode": "0xb1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CYCLES_GE_2", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where at least 2 uops were executed per-thread", + "CounterMask": "2" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Cycles where at least 3 uops were executed per-thread.", + "EventCode": "0xb1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CYCLES_GE_3", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where at least 3 uops were executed per-thread", + "CounterMask": "3" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Cycles where at least 4 uops were executed per-thread.", + "EventCode": "0xb1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CYCLES_GE_4", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles where at least 4 uops were executed per-thread", + "CounterMask": "4" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of uops executed from any thread.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CORE", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of uops executed on the core." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least 1 micro-op is executed from any thread on physical core.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least 2 micro-ops are executed from any thread on physical core.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.", + "CounterMask": "2" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least 3 micro-ops are executed from any thread on physical core.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.", + "CounterMask": "3" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least 4 micro-ops are executed from any thread on physical core.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.", + "CounterMask": "4" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of x87 uops executed.", + "EventCode": "0xB1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x10", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_EXECUTED.X87", + "SampleAfterValue": "2000003", + "BriefDescription": "Counts the number of x87 uops dispatched." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "EventCode": "0xC0", + "Counter": "0,1,2,3,4,5,6,7", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "INST_RETIRED.ANY_P", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of instructions retired. General Counter - architectural event" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of cycles using always true condition (uops_ret &lt; 16) applied to non PEBS uops retired event.", + "EventCode": "0xC2", + "Invert": "1", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_RETIRED.TOTAL_CYCLES", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles with less than 10 actually retired uops.", + "CounterMask": "10" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the retirement slots used each cycle.", + "EventCode": "0xc2", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "UOPS_RETIRED.SLOTS", + "SampleAfterValue": "2000003", + "BriefDescription": "Retirement slots used." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of machine clears (nukes) of any type.", + "EventCode": "0xC3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MACHINE_CLEARS.COUNT", + "SampleAfterValue": "100003", + "BriefDescription": "Number of machine clears (nukes) of any type.", + "CounterMask": "1", + "EdgeDetect": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.", + "EventCode": "0xC3", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x4", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MACHINE_CLEARS.SMC", + "SampleAfterValue": "100003", + "BriefDescription": "Self-modifying code (SMC) detected." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.ALL_BRANCHES", + "SampleAfterValue": "400009", + "BriefDescription": "All branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts taken conditional branch instructions retired.", + "EventCode": "0xc4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.COND_TAKEN", + "SampleAfterValue": "400009", + "BriefDescription": "Taken conditional branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts both direct and indirect near call instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.NEAR_CALL", + "SampleAfterValue": "100007", + "BriefDescription": "Direct and indirect near call instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts return instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x8", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.NEAR_RETURN", + "SampleAfterValue": "100007", + "BriefDescription": "Return instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts not taken branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x10", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.COND_NTAKEN", + "SampleAfterValue": "400009", + "BriefDescription": "Not taken branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts conditional branch instructions retired.", + "EventCode": "0xc4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x11", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.COND", + "SampleAfterValue": "400009", + "BriefDescription": "Conditional branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts taken branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "SampleAfterValue": "400009", + "BriefDescription": "Taken branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts far branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.FAR_BRANCH", + "SampleAfterValue": "100007", + "BriefDescription": "Far branch instructions retired." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).", + "EventCode": "0xc4", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_INST_RETIRED.INDIRECT", + "SampleAfterValue": "100003", + "BriefDescription": "All indirect branch instructions retired (excluding RETs. TSX aborts are considered indirect branch)." + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.", + "EventCode": "0xC5", + "Counter": "0,1,2,3,4,5,6,7", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", + "SampleAfterValue": "400009", + "BriefDescription": "All mispredicted branch instructions retired.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts taken conditional mispredicted branch instructions retired.", + "EventCode": "0xc5", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x1", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_MISP_RETIRED.COND_TAKEN", + "SampleAfterValue": "400009", + "BriefDescription": "number of branch instructions retired that were mispredicted and taken. Non PEBS", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted conditional branch instructions retired.", + "EventCode": "0xc5", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x11", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_MISP_RETIRED.COND", + "SampleAfterValue": "400009", + "BriefDescription": "Mispredicted conditional branch instructions retired.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts number of near branch instructions retired that were mispredicted and taken.", + "EventCode": "0xC5", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "SampleAfterValue": "400009", + "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.", + "Data_LA": "1" + }, + { + "PEBS": "1", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts all miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).", + "EventCode": "0xC5", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x80", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "BR_MISP_RETIRED.INDIRECT", + "SampleAfterValue": "100003", + "BriefDescription": "All miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).", + "Data_LA": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.", + "EventCode": "0xcc", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x20", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "MISC_RETIRED.LBR_INSERTS", + "SampleAfterValue": "2000003", + "BriefDescription": "Increments whenever there is an update to the LBR array." + }, + { + "PublicDescription": "Counts number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted).", + "EventCode": "0xcc", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x40", + "EventName": "MISC_RETIRED.PAUSE_INST", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of retired PAUSE instructions." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.", + "EventCode": "0xE6", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "BACLEARS.ANY", + "SampleAfterValue": "100003", + "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "This event distributes cycle counts between active hyperthreads, i.e., those in C0. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If all other hyperthreads are inactive (or disabled or do not exist), all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.", + "EventCode": "0xec", + "Counter": "0,1,2,3,4,5,6,7", + "UMask": "0x2", + "PEBScounters": "0,1,2,3,4,5,6,7", + "EventName": "CPU_CLK_UNHALTED.DISTRIBUTED", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycle counts are evenly distributed between active threads in the Core." + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json new file mode 100644 index 000000000000..7180a900c175 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/icelake/virtual-memory.json @@ -0,0 +1,236 @@ +[ + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walks completed due to a demand data load to a 4K page." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walks completed due to a demand data load to a 2M/4M page." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts demand data loads that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0xe", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED", + "SampleAfterValue": "100003", + "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of page walks outstanding for a demand load in the PMH (Page Miss Handler) each cycle.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_PENDING", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of page walks outstanding for a demand load in the PMH each cycle." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a demand load.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE", + "SampleAfterValue": "100003", + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a demand load.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.STLB_HIT", + "SampleAfterValue": "2000003", + "BriefDescription": "Loads that miss the DTLB and hit the STLB." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K", + "SampleAfterValue": "100003", + "BriefDescription": "Page walks completed due to a demand data store to a 4K page." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", + "SampleAfterValue": "100003", + "BriefDescription": "Page walks completed due to a demand data store to a 2M/4M page." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts demand data stores that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0xe", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED", + "SampleAfterValue": "100003", + "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of page walks outstanding for a store in the PMH (Page Miss Handler) each cycle.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_PENDING", + "SampleAfterValue": "2000003", + "BriefDescription": "Number of page walks outstanding for a store in the PMH each cycle." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE", + "SampleAfterValue": "100003", + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.STLB_HIT", + "SampleAfterValue": "100003", + "BriefDescription": "Stores that miss the DTLB and hit the STLB." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts completed page walks (4K page size) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED_4K", + "SampleAfterValue": "100003", + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts code misses in all ITLB (Instruction TLB) levels that caused a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M", + "SampleAfterValue": "100003", + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts completed page walks (2M and 4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0xe", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED", + "SampleAfterValue": "100003", + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of page walks outstanding for an outstanding code (instruction fetch) request in the PMH (Page Miss Handler) each cycle.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_PENDING", + "SampleAfterValue": "100003", + "BriefDescription": "Number of page walks outstanding for an outstanding code request in the PMH each cycle." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a code (instruction fetch) request.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_ACTIVE", + "SampleAfterValue": "100003", + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request.", + "CounterMask": "1" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts instruction fetch requests that miss the ITLB (Instruction TLB) and hit the STLB (Second-level TLB).", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.STLB_HIT", + "SampleAfterValue": "100003", + "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).", + "EventCode": "0xAE", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB.ITLB_FLUSH", + "SampleAfterValue": "100007", + "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages." + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.", + "EventCode": "0xBD", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "TLB_FLUSH.DTLB_THREAD", + "SampleAfterValue": "100007", + "BriefDescription": "DTLB flush attempts of the thread-specific entries" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).", + "EventCode": "0xBD", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "TLB_FLUSH.STLB_ANY", + "SampleAfterValue": "100007", + "BriefDescription": "STLB flush attempts" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index d6984a3017e0..b90e5fec2f32 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -33,4 +33,6 @@ GenuineIntel-6-25,v2,westmereep-sp,core GenuineIntel-6-2F,v2,westmereex,core GenuineIntel-6-55-[01234],v1,skylakex,core GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core +GenuineIntel-6-7D,v1,icelake,core +GenuineIntel-6-7E,v1,icelake,core AuthenticAMD-23-[[:xdigit:]]+,v1,amdfam17h,core -- GitLab From 1205a2719e52b6b52e0f9c0011554419da0377a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 6 Aug 2019 11:20:42 -0300 Subject: [PATCH 2714/7155] perf top: Set display thread COMM to help with debugging When we want to attach just to the thread that updates the display it helps having its COMM stand out, so change it from the default "perf" to "perf-top-UI". Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-5w0hmlk3zfvysxvpsh763k9w@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 1a4615a5f6c9..94e34853a238 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -601,6 +601,8 @@ static void *display_thread_tui(void *arg) */ unshare(CLONE_FS); + prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0); + perf_top__sort_new_samples(top); /* @@ -651,6 +653,8 @@ static void *display_thread(void *arg) */ unshare(CLONE_FS); + prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0); + display_setup_sig(); pthread__unblock_sigwinch(); repeat: -- GitLab From 7d1a5efa20dbfea97cb93b99c67ce5cd5c4a4dbc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 7 Aug 2019 10:45:30 -0300 Subject: [PATCH 2715/7155] perf hists: Do not link a pair if already linked When we have multiple events in a group we link hist_entries in the non-leader evsel hists to the one in the leader that points to the same sorting criteria, in hists__match(). For 'perf report' we do this just once and then print the results, but for 'perf top' we need to look if this was already done in the previous refresh of the screen, so check for that and don't try to link again. This is part of having 'perf top' using the hists browser for showing multiple events in multiple columns. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-iwvb37rgb7upswhruwpcdnhw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 4297f56b1e05..d923a5bb7b48 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2453,7 +2453,7 @@ void hists__match(struct hists *leader, struct hists *other) pos = rb_entry(nd, struct hist_entry, rb_node_in); pair = hists__find_entry(other, pos); - if (pair) + if (pair && list_empty(&pair->pairs.node)) hist_entry__add_pair(pair, pos); } } -- GitLab From 3e70008a6021fffd2cd1614734603ea970773060 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Fri, 9 Aug 2019 18:47:52 +0800 Subject: [PATCH 2716/7155] perf trace: Fix segmentation fault when access syscall info on arm64 'perf trace' reports the segmentation fault as below on Arm64: # perf trace -e string -e augmented_raw_syscalls.c LLVM: dumping tools/perf/examples/bpf/augmented_raw_syscalls.o perf: Segmentation fault Obtained 12 stack frames. perf(sighandler_dump_stack+0x47) [0xaaaaac96ac87] linux-vdso.so.1(+0x5b7) [0xffffadbeb5b7] /lib/aarch64-linux-gnu/libc.so.6(strlen+0x10) [0xfffface7d5d0] /lib/aarch64-linux-gnu/libc.so.6(_IO_vfprintf+0x1ac7) [0xfffface49f97] /lib/aarch64-linux-gnu/libc.so.6(__vsnprintf_chk+0xc7) [0xffffacedfbe7] perf(scnprintf+0x97) [0xaaaaac9ca3ff] perf(+0x997bb) [0xaaaaac8e37bb] perf(cmd_trace+0x28e7) [0xaaaaac8ec09f] perf(+0xd4a13) [0xaaaaac91ea13] perf(main+0x62f) [0xaaaaac8a147f] /lib/aarch64-linux-gnu/libc.so.6(__libc_start_main+0xe3) [0xfffface22d23] perf(+0x57723) [0xaaaaac8a1723] Segmentation fault This issue is introduced by commit 30a910d7d3e0 ("perf trace: Preallocate the syscall table"), it allocates trace->syscalls.table[] array and the element count is 'trace->sctbl->syscalls.nr_entries'; but on Arm64, the system call number is not continuously used; e.g. the syscall maximum id is 436 but the real entries is only 281. So the table is allocated with 'nr_entries' as the element count, but it accesses the table with the syscall id, which might be out of the bound of the array and cause the segmentation fault. This patch allocates trace->syscalls.table[] with the element count is 'trace->sctbl->syscalls.max_id + 1', this allows any id to access the table without out of the bound. Signed-off-by: Leo Yan Cc: Alexander Shishkin Cc: Daniel Borkmann Cc: Jiri Olsa Cc: Martin KaFai Lau Cc: Namhyung Kim Cc: Song Liu Cc: Yonghong Song Fixes: 30a910d7d3e0 ("perf trace: Preallocate the syscall table") Link: http://lkml.kernel.org/r/20190809104752.27338-1-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 75eb3811e942..d553d06a9aeb 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1492,7 +1492,7 @@ static int trace__read_syscall_info(struct trace *trace, int id) const char *name = syscalltbl__name(trace->sctbl, id); if (trace->syscalls.table == NULL) { - trace->syscalls.table = calloc(trace->sctbl->syscalls.nr_entries, sizeof(*sc)); + trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc)); if (trace->syscalls.table == NULL) return -ENOMEM; } -- GitLab From 5f8b4d5d237a3e2e35509da4e63769ae5c82c085 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 9 Aug 2019 17:56:06 -0300 Subject: [PATCH 2717/7155] perf hist: Remove dummy entries when finding real ones. When he have an event group we have multiple struct hist instances, one per evsel, and in each of these hists we may have hist_entries that point to the same thing being observed, say a symbol, i.e. if we're looking at instructions and cycles, then we'll have one hist_entry in the "instructions" evsel and another in the "cycles" evsel. We need to link those to then show one column for each. When we're looking at some other pair of events, say instructions and cache misses, we may have just the "instructions" hist entry and not one for "cache misses", as instructions not necessarily generate cache misses, as the logic expects one hist_entry per evsel, we end up adding "dummy" hist_entries. This is enough for 'perf report', that does this matching operation (hists__match()) just once after processing all events, but for 'perf top', we do this at each refresh, so we may finally find events matching and then we need to trow away the dummies and link with the real events. So if we find a match, traverse the link of matches and trow away dummies for that hists. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-dwvtjqqifsbsczeb35q6mqkk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index d923a5bb7b48..8efbf58dc3d0 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2436,7 +2436,7 @@ void hists__match(struct hists *leader, struct hists *other) { struct rb_root_cached *root; struct rb_node *nd; - struct hist_entry *pos, *pair; + struct hist_entry *pos, *pair, *pos_pair, *tmp_pair; if (symbol_conf.report_hierarchy) { /* hierarchy report always collapses entries */ @@ -2453,8 +2453,24 @@ void hists__match(struct hists *leader, struct hists *other) pos = rb_entry(nd, struct hist_entry, rb_node_in); pair = hists__find_entry(other, pos); - if (pair && list_empty(&pair->pairs.node)) + if (pair && list_empty(&pair->pairs.node)) { + list_for_each_entry_safe(pos_pair, tmp_pair, &pos->pairs.head, pairs.node) { + if (pos_pair->hists == other) { + /* + * XXX maybe decayed entries can appear + * here? but then we would have use + * after free, as decayed entries are + * freed see hists__delete_entry + */ + BUG_ON(!pos_pair->dummy); + list_del_init(&pos_pair->pairs.node); + hist_entry__delete(pos_pair); + break; + } + } + hist_entry__add_pair(pair, pos); + } } } -- GitLab From 40d81772dac45643cecc7add0e95356072265754 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 9 Aug 2019 16:44:34 -0300 Subject: [PATCH 2718/7155] perf top: Collapse and resort all evsels in a group And link them, i.e. find the hist entries in the non-leader events and link them to the ones in the leader. This should be the same thing already done for the 'perf report' case, but now we do it periodically. With this in place we get percentages in from the second overhead column on, not just on the first (the leader). Try it using: perf top --stdio -e '{cycles,instructions}' You should see something like: PerfTop: 20776 irqs/sec kernel:68.7% exact: 0.0% lost: 0/0 drop: 0/0 [cycles], (all, 8 CPUs) --------------------------------------------------------------------------------------------------- 4.44% 0.44% [kernel] [k] do_syscall_64 2.27% 0.17% [kernel] [k] entry_SYSCALL_64 1.73% 0.27% [kernel] [k] syscall_return_via_sysret 1.60% 0.91% [kernel] [k] _raw_spin_lock_irqsave 1.45% 3.53% libglib-2.0.so.0.6000.4 [.] g_string_insert_unichar 1.39% 0.21% [kernel] [k] copy_user_enhanced_fast_string 1.26% 1.15% [kernel] [k] psi_task_change 1.16% 0.14% libpixman-1.so.0.38.0 [.] 0x000000000006f403 1.00% 0.32% [kernel] [k] __sched_text_start 0.97% 2.11% [kernel] [k] n_tty_write 0.96% 0.04% [kernel] [k] queued_spin_lock_slowpath 0.93% 0.88% [kernel] [k] menu_select 0.87% 0.14% [kernel] [k] try_to_wake_up 0.77% 0.10% libpixman-1.so.0.38.0 [.] 0x000000000006f40b 0.73% 0.09% libpixman-1.so.0.38.0 [.] 0x000000000006f413 0.69% 0.48% libc-2.29.so [.] __memmove_avx_unaligned_erms 0.68% 0.29% [kernel] [k] _raw_spin_lock_irq 0.61% 0.04% libpixman-1.so.0.38.0 [.] 0x000000000006f423 0.60% 0.37% [kernel] [k] native_sched_clock 0.57% 0.23% [kernel] [k] do_idle 0.57% 0.23% [kernel] [k] __fget 0.56% 0.30% [kernel] [k] __switch_to_asm 0.56% 0.00% libc-2.29.so [.] __memset_avx2_erms 0.52% 0.32% [kernel] [k] _raw_spin_lock 0.49% 0.24% [kernel] [k] n_tty_poll 0.49% 0.54% libglib-2.0.so.0.6000.4 [.] g_mutex_lock 0.48% 0.62% [kernel] [k] _raw_spin_unlock_irqrestore 0.47% 0.27% [kernel] [k] __switch_to 0.47% 0.25% [kernel] [k] pick_next_task_fair 0.45% 0.17% [kernel] [k] filldir64 0.40% 0.16% [kernel] [k] update_rq_clock 0.39% 0.19% [kernel] [k] enqueue_task_fair # Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-uw8cjeifxvjpkjp6x2iil0ar@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 94e34853a238..78e7efc597a6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -264,6 +264,30 @@ static void perf_top__show_details(struct perf_top *top) pthread_mutex_unlock(¬es->lock); } +static void evlist__resort_hists(struct evlist *evlist) +{ + struct evsel *pos; + + evlist__for_each_entry(evlist, pos) { + struct hists *hists = evsel__hists(pos); + + hists__collapse_resort(hists, NULL); + + /* Non-group events are considered as leader */ + if (symbol_conf.event_group && + !perf_evsel__is_group_leader(pos)) { + struct hists *leader_hists = evsel__hists(pos->leader); + + hists__match(leader_hists, hists); + hists__link(leader_hists, hists); + } + } + + evlist__for_each_entry(evlist, pos) { + perf_evsel__output_resort(pos, NULL); + } +} + static void perf_top__print_sym_table(struct perf_top *top) { char bf[160]; @@ -304,8 +328,7 @@ static void perf_top__print_sym_table(struct perf_top *top) } } - hists__collapse_resort(hists, NULL); - perf_evsel__output_resort(evsel, NULL); + evlist__resort_hists(top->evlist); hists__output_recalc_col_len(hists, top->print_entries - printed); putchar('\n'); @@ -570,8 +593,7 @@ static void perf_top__sort_new_samples(void *arg) } } - hists__collapse_resort(hists, NULL); - perf_evsel__output_resort(evsel, NULL); + evlist__resort_hists(t->evlist); if (t->lost || t->drop) pr_warning("Too slow to read ring buffer (change period (-c/-F) or limit CPUs (-C)\n"); -- GitLab From 74d5f3d06f707eb5f7e1908ad88954bde02000ce Mon Sep 17 00:00:00 2001 From: Igor Lubashev Date: Wed, 7 Aug 2019 10:44:14 -0400 Subject: [PATCH 2719/7155] tools build: Add capability-related feature detection Add utilities to help checking capabilities of the running procss. Make perf link with libcap, if it is available. If no libcap-dev[el], assume no capabilities. Committer testing: $ make O=/tmp/build/perf -C tools/perf install-bin make: Entering directory '/home/acme/git/perf/tools/perf' BUILD: Doing 'make -j8' parallel build Auto-detecting system features: ... libbfd: [ on ] ... libcap: [ OFF ] ... libelf: [ on ] Makefile.config:833: No libcap found, disables capability support, please install libcap-devel/libcap-dev $ grep libcap /tmp/build/perf/FEATURE-DUMP feature-libcap=0 $ cat /tmp/build/perf/feature/test-libcap.make.output test-libcap.c:2:10: fatal error: sys/capability.h: No such file or directory 2 | #include | ^~~~~~~~~~~~~~~~~~ compilation terminated. $ Now install libcap-devel and try again: $ make O=/tmp/build/perf -C tools/perf install-bin make: Entering directory '/home/acme/git/perf/tools/perf' BUILD: Doing 'make -j8' parallel build Warning: Kernel ABI header at 'tools/include/linux/bits.h' differs from latest version at 'include/linux/bits.h' diff -u tools/include/linux/bits.h include/linux/bits.h Warning: Kernel ABI header at 'tools/arch/x86/include/asm/cpufeatures.h' differs from latest version at 'arch/x86/include/asm/cpufeatures.h' diff -u tools/arch/x86/include/asm/cpufeatures.h arch/x86/include/asm/cpufeatures.h Auto-detecting system features: ... libbfd: [ on ] ... libcap: [ on ] ... libelf: [ on ] > CC /tmp/build/perf/jvmti/libjvmti.o > $ grep libcap /tmp/build/perf/FEATURE-DUMP feature-libcap=1 $ cat /tmp/build/perf/feature/test-libcap.make.output $ ldd /tmp/build/perf/feature/test-libcap.make.bin ldd: /tmp/build/perf/feature/test-libcap.make.bin: No such file or directory $ ldd /tmp/build/perf/feature/test-libcap.bin linux-vdso.so.1 (0x00007ffc35bfe000) libcap.so.2 => /lib64/libcap.so.2 (0x00007ff9c62ff000) libc.so.6 => /lib64/libc.so.6 (0x00007ff9c6139000) /lib64/ld-linux-x86-64.so.2 (0x00007ff9c6326000) $ Signed-off-by: Igor Lubashev Acked-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Alexey Budankov Cc: James Morris Cc: Mathieu Poirier Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Suzuki Poulouse [ split from a larger patch ] Link: http://lkml.kernel.org/r/8a1e76cf5c7c9796d0d4d240fbaa85305298aafa.1565188228.git.ilubashe@akamai.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 2 ++ tools/build/feature/Makefile | 4 ++++ tools/build/feature/test-libcap.c | 20 ++++++++++++++++++++ tools/perf/Makefile.config | 11 +++++++++++ tools/perf/Makefile.perf | 2 ++ 5 files changed, 39 insertions(+) create mode 100644 tools/build/feature/test-libcap.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 86b793dffbc4..8a19753cc26a 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -42,6 +42,7 @@ FEATURE_TESTS_BASIC := \ gtk2-infobar \ libaudit \ libbfd \ + libcap \ libelf \ libelf-getphdrnum \ libelf-gelf_getnote \ @@ -110,6 +111,7 @@ FEATURE_DISPLAY ?= \ gtk2 \ libaudit \ libbfd \ + libcap \ libelf \ libnuma \ numa_num_possible_cpus \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 0658b8cd0e53..8499385365c0 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -20,6 +20,7 @@ FILES= \ test-libbfd-liberty.bin \ test-libbfd-liberty-z.bin \ test-cplus-demangle.bin \ + test-libcap.bin \ test-libelf.bin \ test-libelf-getphdrnum.bin \ test-libelf-gelf_getnote.bin \ @@ -105,6 +106,9 @@ $(OUTPUT)test-fortify-source.bin: $(OUTPUT)test-bionic.bin: $(BUILD) +$(OUTPUT)test-libcap.bin: + $(BUILD) -lcap + $(OUTPUT)test-libelf.bin: $(BUILD) -lelf diff --git a/tools/build/feature/test-libcap.c b/tools/build/feature/test-libcap.c new file mode 100644 index 000000000000..d2a2e152195f --- /dev/null +++ b/tools/build/feature/test-libcap.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +int main(void) +{ + cap_flag_value_t val; + cap_t caps = cap_get_proc(); + + if (!caps) + return 1; + + if (cap_get_flag(caps, CAP_SYS_ADMIN, CAP_EFFECTIVE, &val) != 0) + return 1; + + if (cap_free(caps) != 0) + return 1; + + return 0; +} diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index e4988f49ea79..9a06787fedc6 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -824,6 +824,17 @@ ifndef NO_LIBZSTD endif endif +ifndef NO_LIBCAP + ifeq ($(feature-libcap), 1) + CFLAGS += -DHAVE_LIBCAP_SUPPORT + EXTLIBS += -lcap + $(call detected,CONFIG_LIBCAP) + else + msg := $(warning No libcap found, disables capability support, please install libcap-devel/libcap-dev); + NO_LIBCAP := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORT diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 67512a12276b..f9807d8c005b 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -88,6 +88,8 @@ include ../scripts/utilities.mak # # Define NO_LIBBPF if you do not want BPF support # +# Define NO_LIBCAP if you do not want process capabilities considered by perf +# # Define NO_SDT if you do not want to define SDT event in perf tools, # note that it doesn't disable SDT scanning support. # -- GitLab From c6d29c66e582f9a3ae27d08a488aa89232545a39 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Mon, 12 Aug 2019 09:48:57 +0200 Subject: [PATCH 2720/7155] arm64: dts: meson-g12b-khadas-vim3: add initial device-tree The Khadas VIM3 uses the Amlogic S922X or A311S SoC, both based on the Amlogic G12B SoC family, on a board with the same form factor as the VIM/VIM2 models. It ships in two variants; basic and pro which differ in RAM and eMMC size: - 2GB (basic) or 4GB (pro) LPDDR4 RAM - 16GB (basic) or 32GB (pro) eMMC 5.1 storage - 16MB SPI flash - 10/100/1000 Base-T Ethernet - AP6398S Wireless (802.11 a/b/g/n/ac, BT5.0) - HDMI 2.1 video - 1x USB 2.0 + 1x USB 3.0 ports - 1x USB-C (power) with USB 2.0 OTG - 3x LED's (1x red, 1x blue, 1x white) - 3x buttons (power, function, reset) - IR receiver - M2 socket with PCIe, USB, ADC & I2C - 40pin GPIO Header - 1x micro SD card slot A common meson-g12b-khadas-vim3.dtsi is added to support both S922X and A311D SoCs supported by two variants of the board. Signed-off-by: Christian Hewitt Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/Makefile | 2 + .../amlogic/meson-g12b-a311d-khadas-vim3.dts | 15 + .../dts/amlogic/meson-g12b-khadas-vim3.dtsi | 544 ++++++++++++++++++ .../amlogic/meson-g12b-s922x-khadas-vim3.dts | 15 + 4 files changed, 576 insertions(+) create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index 07b861fe5fa5..ae5e8d0c08da 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -3,6 +3,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb dtb-$(CONFIG_ARCH_MESON) += meson-g12a-sei510.dtb dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts new file mode 100644 index 000000000000..73128ed24361 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (c) 2019 Christian Hewitt + */ + +/dts-v1/; + +#include "meson-g12b-a311d.dtsi" +#include "meson-g12b-khadas-vim3.dtsi" + +/ { + compatible = "khadas,vim3", "amlogic,a311d", "amlogic,g12b"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi new file mode 100644 index 000000000000..9c3ca2edc725 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (c) 2019 Christian Hewitt + */ + +#include +#include +#include + +/ { + model = "Khadas VIM3"; + + aliases { + serial0 = &uart_AO; + ethernet0 = ðmac; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1710000>; + + button-function { + label = "Function"; + linux,code = ; + press-threshold-microvolt = <10000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + white { + label = "vim3:white:sys"; + gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + + red { + label = "vim3:red"; + gpios = <&gpio_expander 5 GPIO_ACTIVE_LOW>; + }; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + power-button { + label = "power"; + linux,code = ; + gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_LOW>; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; + + dc_in: regulator-dc_in { + compatible = "regulator-fixed"; + regulator-name = "DC_IN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + vcc_5v: regulator-vcc_5v { + compatible = "regulator-fixed"; + regulator-name = "VCC_5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_in>; + + gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; + enable-active-high; + }; + + vcc_1v8: regulator-vcc_1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-always-on; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vsys_3v3>; + regulator-always-on; + /* FIXME: actually controlled by VDDCPU_B_EN */ + }; + + vddcpu_a: regulator-vddcpu-a { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU_A"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + + vin-supply = <&dc_in>; + + pwms = <&pwm_ab 0 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + + vddcpu_b: regulator-vddcpu-b { + /* + * Silergy SY8030DEC Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU_B"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + + vin-supply = <&vsys_3v3>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + + vddao_1v8: regulator-vddao_1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_AO1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vsys_3v3>; + regulator-always-on; + }; + + emmc_1v8: regulator-emmc_1v8 { + compatible = "regulator-fixed"; + regulator-name = "EMMC_AO1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-always-on; + }; + + vsys_3v3: regulator-vsys_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VSYS_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&dc_in>; + regulator-always-on; + }; + + usb_pwr: regulator-usb_pwr { + compatible = "regulator-fixed"; + regulator-name = "USB_PWR"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_5v>; + + gpio = <&gpio GPIOA_6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi_tx_tmds_out>; + }; + }; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sound { + compatible = "amlogic,axg-sound-card"; + model = "G12A-KHADAS-VIM3"; + audio-aux-devs = <&tdmout_b>; + audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", + "TDMOUT_B IN 1", "FRDDR_B OUT 1", + "TDMOUT_B IN 2", "FRDDR_C OUT 1", + "TDM_B Playback", "TDMOUT_B OUT"; + + assigned-clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clock-parents = <0>, <0>, <0>; + assigned-clock-rates = <294912000>, + <270950400>, + <393216000>; + status = "okay"; + + dai-link-0 { + sound-dai = <&frddr_a>; + }; + + dai-link-1 { + sound-dai = <&frddr_b>; + }; + + dai-link-2 { + sound-dai = <&frddr_c>; + }; + + /* 8ch hdmi interface */ + dai-link-3 { + sound-dai = <&tdmif_b>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; + dai-tdm-slot-tx-mask-1 = <1 1>; + dai-tdm-slot-tx-mask-2 = <1 1>; + dai-tdm-slot-tx-mask-3 = <1 1>; + mclk-fs = <256>; + + codec { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; + }; + }; + + /* hdmi glue */ + dai-link-4 { + sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; + + codec { + sound-dai = <&hdmi_tx>; + }; + }; + }; +}; + +&arb { + status = "okay"; +}; + +&cec_AO { + pinctrl-0 = <&cec_ao_a_h_pins>; + pinctrl-names = "default"; + status = "disabled"; + hdmi-phandle = <&hdmi_tx>; +}; + +&cecb_AO { + pinctrl-0 = <&cec_ao_b_h_pins>; + pinctrl-names = "default"; + status = "okay"; + hdmi-phandle = <&hdmi_tx>; +}; + +&clkc_audio { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vddcpu_b>; + operating-points-v2 = <&cpu_opp_table_0>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu1 { + cpu-supply = <&vddcpu_b>; + operating-points-v2 = <&cpu_opp_table_0>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu100 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu101 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu102 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu103 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&ext_mdio { + external_phy: ethernet-phy@0 { + /* Realtek RTL8211F (0x001cc916) */ + reg = <0>; + max-speed = <1000>; + + interrupt-parent = <&gpio_intc>; + /* MAC_INTR on GPIOZ_14 */ + interrupts = <26 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +ðmac { + pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; + pinctrl-names = "default"; + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&external_phy>; + amlogic,tx-delay-ns = <2>; +}; + +&frddr_a { + status = "okay"; +}; + +&frddr_b { + status = "okay"; +}; + +&frddr_c { + status = "okay"; +}; + +&hdmi_tx { + status = "okay"; + pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; + pinctrl-names = "default"; + hdmi-supply = <&vcc_5v>; +}; + +&hdmi_tx_tmds_port { + hdmi_tx_tmds_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; +}; + +&i2c_AO { + status = "okay"; + pinctrl-0 = <&i2c_ao_sck_pins>, <&i2c_ao_sda_pins>; + pinctrl-names = "default"; + + gpio_expander: gpio-controller@20 { + compatible = "ti,tca6408"; + reg = <0x20>; + vcc-supply = <&vcc_3v3>; + gpio-controller; + #gpio-cells = <2>; + }; + + rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + }; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; + linux,rc-map-name = "rc-khadas"; +}; + +&pwm_ab { + pinctrl-0 = <&pwm_a_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin0"; + status = "okay"; +}; + +&pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin1"; + status = "okay"; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; +}; + +&saradc { + status = "okay"; + vref-supply = <&vddao_1v8>; +}; + +/* SDIO */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins>; + pinctrl-1 = <&sdio_clk_gate_pins>; + pinctrl-names = "default", "clk-gate"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr50; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vsys_3v3>; + vqmmc-supply = <&vddao_1v8>; + + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_c_pins>; + pinctrl-1 = <&sdcard_clk_gate_c_pins>; + pinctrl-names = "default", "clk-gate"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <50000000>; + disable-wp; + + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vsys_3v3>; + vqmmc-supply = <&vsys_3v3>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>; + pinctrl-1 = <&emmc_clk_gate_pins>; + pinctrl-names = "default", "clk-gate"; + + bus-width = <8>; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + max-frequency = <200000000>; + disable-wp; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&emmc_1v8>; +}; + +&tdmif_b { + status = "okay"; +}; + +&tdmout_b { + status = "okay"; +}; + +&tohdmitx { + status = "okay"; +}; + +&uart_A { + status = "okay"; + pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; + pinctrl-names = "default"; + uart-has-rtscts; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + max-speed = <2000000>; + clocks = <&wifi32k>; + clock-names = "lpo"; + }; +}; + +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +&usb2_phy0 { + phy-supply = <&dc_in>; +}; + +&usb2_phy1 { + phy-supply = <&usb_pwr>; +}; + +&usb3_pcie_phy { + phy-supply = <&usb_pwr>; +}; + +&usb { + status = "okay"; + dr_mode = "peripheral"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts new file mode 100644 index 000000000000..6bcf972b8bfa --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (c) 2019 Christian Hewitt + */ + +/dts-v1/; + +#include "meson-g12b-s922x.dtsi" +#include "meson-g12b-khadas-vim3.dtsi" + +/ { + compatible = "khadas,vim3", "amlogic,s922x", "amlogic,g12b"; +}; -- GitLab From d14734a04a8aea793a5534de39a21ad59b324a11 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 Jul 2019 15:26:22 +0200 Subject: [PATCH 2721/7155] arm64: dts: meson-g12b-odroid-n2: enable DVFS Enable DVFS for the Odroid-N2 by setting the clock, OPP and supply for each cores of each CPU clusters. The first cluster uses the "VDDCPU_B" power supply, and the second cluster uses the "VDDCPU_A" power supply. Each power supply can achieve 0.73V to 1.01V using 2 distinct PWM outputs clocked at 800KHz with an inverse duty-cycle. DVFS has been tested by running the arm64 cpuburn at [1] and cycling between all the possible cpufreq translations of each cluster and checking the final frequency using the clock-measurer, script at [2]. [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Kevin Hilman --- .../boot/dts/amlogic/meson-g12b-odroid-n2.dts | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts index 237adae0ffae..6cfc2c69bb4f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts @@ -115,6 +115,44 @@ /* FIXME: actually controlled by VDDCPU_B_EN */ }; + vddcpu_a: regulator-vddcpu-a { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU_A"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + + vin-supply = <&main_12v>; + + pwms = <&pwm_ab 0 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + + vddcpu_b: regulator-vddcpu-b { + /* + * Silergy SY8120B1ABC Regulator. + */ + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU_B"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + + vin-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + hub_5v: regulator-hub_5v { compatible = "regulator-fixed"; regulator-name = "HUB_5V"; @@ -246,6 +284,48 @@ status = "okay"; }; +&cpu0 { + cpu-supply = <&vddcpu_b>; + operating-points-v2 = <&cpu_opp_table_0>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu1 { + cpu-supply = <&vddcpu_b>; + operating-points-v2 = <&cpu_opp_table_0>; + clocks = <&clkc CLKID_CPU_CLK>; + clock-latency = <50000>; +}; + +&cpu100 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu101 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu102 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + +&cpu103 { + cpu-supply = <&vddcpu_a>; + operating-points-v2 = <&cpub_opp_table_1>; + clocks = <&clkc CLKID_CPUB_CLK>; + clock-latency = <50000>; +}; + &ext_mdio { external_phy: ethernet-phy@0 { /* Realtek RTL8211F (0x001cc916) */ @@ -317,6 +397,22 @@ pinctrl-names = "default"; }; +&pwm_ab { + pinctrl-0 = <&pwm_a_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin0"; + status = "okay"; +}; + +&pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; + clocks = <&xtal>; + clock-names = "clkin1"; + status = "okay"; +}; + /* SD card */ &sd_emmc_b { status = "okay"; -- GitLab From 6b14dd7267126931e9a95c68a442e8f2dabdc3c4 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Mon, 12 Aug 2019 19:50:04 +0200 Subject: [PATCH 2722/7155] ARM: dts: meson8b: odroidc1: use the MAC address stored in the eFuse Odroid-C1 uses the MAC address stored in eFuse at offset 0x1b4 (which is defined as a "standard" offset for all Meson8 and Meson8b boards, but testing shows that MXQ doesn't have the eFuse values programmed and EC-100 stores it's MAC address in eMMC). Add the nvmem cell which points to the MAC address and asssign it to the Ethernet controller as "mac-address". As result of this the MAC address which is stored in the eFuse is now assigned to the Ethernet controller and consistent across reboots. Signed-off-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- arch/arm/boot/dts/meson8b-odroidc1.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts index 90f66dc45115..a24eccc354b9 100644 --- a/arch/arm/boot/dts/meson8b-odroidc1.dts +++ b/arch/arm/boot/dts/meson8b-odroidc1.dts @@ -190,6 +190,12 @@ cpu-supply = <&vcck>; }; +&efuse { + ethernet_mac_address: mac@1b4 { + reg = <0x1b4 0x6>; + }; +}; + ðmac { status = "okay"; @@ -200,6 +206,9 @@ phy-handle = <ð_phy>; amlogic,tx-delay-ns = <4>; + nvmem-cells = <ðernet_mac_address>; + nvmem-cell-names = "mac-address"; + mdio { compatible = "snps,dwmac-mdio"; #address-cells = <1>; -- GitLab From e7774049ff255c8ba72bcee9c7ab307a95e8d7bc Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 14 Jul 2019 17:55:00 +0200 Subject: [PATCH 2723/7155] ARM: dts: bcm283x: Define MMC interfaces at board level Starting with RPi 4 this is the first board, which doesn't use sdhost as default SD interface. So the MMC interfaces should be defined finally at board level. Since all boards using sdhci already does this, we can drop the pinctrl part from bcm2835-rpi.dtsi. Signed-off-by: Stefan Wahren Acked-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-a.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-b.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi-zero.dts | 7 +++++++ arch/arm/boot/dts/bcm2835-rpi.dtsi | 13 ------------- arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 7 +++++++ arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 7 +++++++ 11 files changed, 70 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index db8a6017f220..cb3f08da5a4a 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -107,6 +107,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index 067d1f07a2d3..2d167d9e0bb4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -102,6 +102,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index 1e40d672b055..83a3a60e976e 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -109,6 +109,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index 28e7513ce617..b6b4feabb5b9 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -102,6 +102,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index 31ff602e2cd3..b5782faabedf 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -97,6 +97,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts index 4764a25585ab..41afea4f1da2 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts @@ -81,6 +81,13 @@ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts index ba0167df6c5f..5ecc4032beb6 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts @@ -116,6 +116,13 @@ }; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio32 &uart0_ctsrts_gpio30>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero.dts b/arch/arm/boot/dts/bcm2835-rpi-zero.dts index 3b35a8a4a55f..84c70354faf2 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts @@ -98,6 +98,13 @@ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 715d50c64529..40bac52ecc39 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -68,19 +68,6 @@ status = "okay"; }; -&sdhci { - pinctrl-names = "default"; - pinctrl-0 = <&emmc_gpio48>; - bus-width = <4>; -}; - -&sdhost { - pinctrl-names = "default"; - pinctrl-0 = <&sdhost_gpio48>; - status = "okay"; - bus-width = <4>; -}; - &usb { power-domains = <&power RPI_POWER_DOMAIN_USB>; }; diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts index 7b4e651bafdd..f97ec9519104 100644 --- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts @@ -113,6 +113,13 @@ status = "okay"; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts index 6c8233a36d86..433e306a4b0f 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts @@ -80,6 +80,13 @@ hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>; }; +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_gpio14>; -- GitLab From 328e3e369bcee3375a8f48d9ae68daf173fc8453 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 16 Jul 2019 20:13:13 +0200 Subject: [PATCH 2724/7155] ARM: dts: bcm283x: Define memory at board level Now with the varity of several RPi boards, the memory should be defined at board level. This step gives us the chance to fix the memory size of the RPi 1 B+, Zero (incl. W) and Compute Module 1. Signed-off-by: Stefan Wahren Acked-by: Eric Anholt --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-a.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-b.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi-zero.dts | 5 +++++ arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 ----- arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 1 + arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts | 1 + arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 1 + arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 1 + arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi | 1 + 14 files changed, 45 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index cb3f08da5a4a..5b42e9a61c14 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -8,6 +8,11 @@ compatible = "raspberrypi,model-a-plus", "brcm,bcm2835"; model = "Raspberry Pi Model A+"; + memory@0 { + device_type = "memory"; + reg = <0 0x10000000>; + }; + leds { act { gpios = <&gpio 47 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index 2d167d9e0bb4..b71621487c16 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -8,6 +8,11 @@ compatible = "raspberrypi,model-a", "brcm,bcm2835"; model = "Raspberry Pi Model A"; + memory@0 { + device_type = "memory"; + reg = <0 0x10000000>; + }; + leds { act { gpios = <&gpio 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index 83a3a60e976e..3318082d3513 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -9,6 +9,11 @@ compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; model = "Raspberry Pi Model B+"; + memory@0 { + device_type = "memory"; + reg = <0 0x20000000>; + }; + leds { act { gpios = <&gpio 47 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index b6b4feabb5b9..97d7eb5e0e93 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -9,6 +9,11 @@ compatible = "raspberrypi,model-b-rev2", "brcm,bcm2835"; model = "Raspberry Pi Model B rev2"; + memory@0 { + device_type = "memory"; + reg = <0 0x10000000>; + }; + leds { act { gpios = <&gpio 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index b5782faabedf..37e02a1c9e4a 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -9,6 +9,11 @@ compatible = "raspberrypi,model-b", "brcm,bcm2835"; model = "Raspberry Pi Model B"; + memory@0 { + device_type = "memory"; + reg = <0 0x10000000>; + }; + leds { act { gpios = <&gpio 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi index ef22c2da783a..58059c2ce129 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi @@ -10,6 +10,11 @@ }; }; + memory@0 { + device_type = "memory"; + reg = <0 0x20000000>; + }; + reg_3v3: fixed-regulator { compatible = "regulator-fixed"; regulator-name = "3V3"; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts index 5ecc4032beb6..f38f388e44b4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts @@ -12,6 +12,11 @@ compatible = "raspberrypi,model-zero-w", "brcm,bcm2835"; model = "Raspberry Pi Zero W"; + memory@0 { + device_type = "memory"; + reg = <0 0x20000000>; + }; + chosen { /* 8250 auxiliary UART instead of pl011 */ stdout-path = "serial1:115200n8"; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero.dts b/arch/arm/boot/dts/bcm2835-rpi-zero.dts index 84c70354faf2..5fd06869dfcf 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts @@ -12,6 +12,11 @@ compatible = "raspberrypi,model-zero", "brcm,bcm2835"; model = "Raspberry Pi Zero"; + memory@0 { + device_type = "memory"; + reg = <0 0x20000000>; + }; + leds { act { gpios = <&gpio 47 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 40bac52ecc39..f5125b745986 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -1,11 +1,6 @@ #include / { - memory@0 { - device_type = "memory"; - reg = <0 0x10000000>; - }; - leds { compatible = "gpio-leds"; diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts index f97ec9519104..6a89999f1976 100644 --- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts @@ -10,6 +10,7 @@ model = "Raspberry Pi 2 Model B"; memory@0 { + device_type = "memory"; reg = <0 0x40000000>; }; diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts index 7f4437a8eedb..0e29aaae3038 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts @@ -14,6 +14,7 @@ }; memory@0 { + device_type = "memory"; reg = <0 0x20000000>; }; diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts index c6fa34c24100..a1487ae3db8d 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts @@ -15,6 +15,7 @@ }; memory@0 { + device_type = "memory"; reg = <0 0x40000000>; }; diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts index ce71f578c51a..a36bfdb5950a 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts @@ -15,6 +15,7 @@ }; memory@0 { + device_type = "memory"; reg = <0 0x40000000>; }; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi index 81399b2c5af9..7c3cb7ece6cb 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi @@ -5,6 +5,7 @@ / { memory@0 { + device_type = "memory"; reg = <0 0x40000000>; }; -- GitLab From abab1cd6c617762adade199c33034d6d744bd28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 28 Jul 2019 23:04:02 +0200 Subject: [PATCH 2725/7155] dt-bindings: add vendor prefix "acme" for "Acme Systems srl" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prefix for Acme Systems srl https://www.acmesystems.it Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190728210403.2730-2-uwe@kleine-koenig.org Acked-by: Rob Herring Reviewed-by: Ludovic Desroches Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6992bbbbffab..85965e3446bf 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -27,6 +27,8 @@ patternProperties: description: Abilis Systems "^abracon,.*": description: Abracon Corporation + "^acme,.*": + description: Acme Systems srl "^actions,.*": description: Actions Semiconductor Co., Ltd. "^active-semi,.*": -- GitLab From 11fec009d97e5bd2329ef7d52d71e9f6763f1048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Mon, 12 Aug 2019 18:07:04 +0200 Subject: [PATCH 2726/7155] Documentation: sphinx: Add missing comma to list of strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Python, like in C, when a comma is omitted in a list of strings, the two strings around the missing comma are concatenated. Cc: stable@vger.kernel.org # v5.2 only Signed-off-by: Jonathan Neuschäfer Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/sphinx/automarkup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sphinx/automarkup.py b/Documentation/sphinx/automarkup.py index 77e89c1956d7..a8798369e8f7 100644 --- a/Documentation/sphinx/automarkup.py +++ b/Documentation/sphinx/automarkup.py @@ -25,7 +25,7 @@ RE_function = re.compile(r'([\w_][\w\d_]+\(\))') # to the creation of incorrect and confusing cross references. So # just don't even try with these names. # -Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap' +Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap', 'select', 'poll', 'fork', 'execve', 'clone', 'ioctl'] # -- GitLab From 82bf829b692d6bc9c44cd43ddd75a9b04f1bfa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Mon, 12 Aug 2019 18:07:05 +0200 Subject: [PATCH 2727/7155] Documentation: sphinx: Don't parse socket() as identifier reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the introduction of Documentation/sphinx/automarkup.py, socket() is parsed as a reference to the in-kernel definition of socket. Sphinx then decides that struct socket is a good match, which is usually not intended, when the syscall is meant instead. This was observed in Documentation/networking/af_xdp.rst. Prevent socket() from being misinterpreted by adding it to the Skipfuncs list in automarkup.py. Signed-off-by: Jonathan Neuschäfer Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/sphinx/automarkup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/sphinx/automarkup.py b/Documentation/sphinx/automarkup.py index a8798369e8f7..5b6119ff69f4 100644 --- a/Documentation/sphinx/automarkup.py +++ b/Documentation/sphinx/automarkup.py @@ -26,7 +26,8 @@ RE_function = re.compile(r'([\w_][\w\d_]+\(\))') # just don't even try with these names. # Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap', - 'select', 'poll', 'fork', 'execve', 'clone', 'ioctl'] + 'select', 'poll', 'fork', 'execve', 'clone', 'ioctl', + 'socket' ] # # Find all occurrences of function() and try to replace them with -- GitLab From 15e2544ed38a1e39b702277bdcd2bb1275e78925 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2019 19:06:31 +0300 Subject: [PATCH 2728/7155] kernel-doc: Allow anonymous enum In C is a valid construction to have an anonymous enumerator. Though we have now: drivers/pinctrl/intel/pinctrl-intel.c:240: error: Cannot parse enum! Support it in the kernel-doc script. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 32e793ca5e95..81dc91760b23 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1245,7 +1245,7 @@ sub dump_enum($$) { # strip #define macros inside enums $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; - if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) { + if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { $declaration_name = $1; my $members = $2; my %_members; -- GitLab From 3b2cb439a63fd5bed75bf9e023f4a8ec6623b3c0 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Fri, 9 Aug 2019 18:29:07 -0500 Subject: [PATCH 2729/7155] docs: Fix typo on pull requests guide Signed-off-by: Marco Villegas Signed-off-by: Jonathan Corbet --- Documentation/maintainer/pull-requests.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/maintainer/pull-requests.rst b/Documentation/maintainer/pull-requests.rst index 22b271de0304..1a2f99b67d25 100644 --- a/Documentation/maintainer/pull-requests.rst +++ b/Documentation/maintainer/pull-requests.rst @@ -29,7 +29,7 @@ request to. In order to create the pull request you must first tag the branch that you have just created. It is recommended that you choose a meaningful tag name, in a way that you and others can understand, even after some time. A good -practice is to include in the name an indicator of the sybsystem of origin +practice is to include in the name an indicator of the subsystem of origin and the target kernel version. Greg offers the following. A pull request with miscellaneous stuff for -- GitLab From 03d36521f5d22e4bd93246a53fd493f275924593 Mon Sep 17 00:00:00 2001 From: Sheriff Esseson Date: Fri, 9 Aug 2019 14:23:49 +0100 Subject: [PATCH 2730/7155] Documentation: virt: Fix broken reference to virt tree's index Fix broken reference to virt/index.rst. Fixes: 2f5947dfcaec ("Documentation: move Documentation/virtual to Documentation/virt") Signed-off-by: Sheriff Esseson Signed-off-by: Jonathan Corbet --- Documentation/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/index.rst b/Documentation/index.rst index 0a564f3c336e..b5fd87e7dbee 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -119,7 +119,7 @@ needed). spi/index w1/index watchdog/index - virtual/index + virt/index input/index hwmon/index gpu/index -- GitLab From 6a241a11f9257e34f64db5e1769c77af72593c20 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 9 Aug 2019 20:04:47 +0800 Subject: [PATCH 2731/7155] docs/zh_CN: update Chinese howto.rst for latexdocs making Mauro Carvalho Chehab found a reference error in Chinese howto.rst. and further more there more infos of latexdocs/epubdocs format doc making in English howto.rst. So I update this part according to latest howto.rst and settled the correct reference. Signed-off-by: Alex Shi Signed-off-by: Jonathan Corbet --- Documentation/translations/zh_CN/process/howto.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst index c4ff8356b88d..b244a7190eb6 100644 --- a/Documentation/translations/zh_CN/process/howto.rst +++ b/Documentation/translations/zh_CN/process/howto.rst @@ -146,14 +146,18 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 :ref:`Documentation/process/applying-patches.rst ` 关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍 -内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何 -妥善处理加锁的规则。生成的文档会放在 Documentation/output/目录下。在内 -核源码的主目录中使用以下不同命令将会分别生成PDF、Postscript、HTML和手册 -页等不同格式的文档:: +内核还拥有大量从代码自动生成或者从 ReStructuredText(ReST) 标记生成的文档, +比如这个文档,它包含内核内部API的全面介绍以及如何妥善处理加锁的规则。所有 +这些文档都可以通过运行以下命令从内核代码中生成为PDF或HTML文档:: make pdfdocs make htmldocs +ReST格式的文档会生成在 Documentation/output. 目录中。 +它们也可以用下列命令生成 LaTeX 和 ePub 格式文档:: + + make latexdocs + make epubdocs 如何成为内核开发者 ------------------ -- GitLab From 198266af3ab934847c840b2442ed66b255723e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Thu, 8 Aug 2019 18:58:55 +0200 Subject: [PATCH 2732/7155] Documentation/arm/sa1100: Remove some obsolete documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The support for the following boards, among others, was removed in 2004 with commit "[ARM] Remove broken SA1100 machine support.": - ADS Bitsy - Brutus - Freebird - ADS GraphicsClient Plus - ADS GraphicsMaster - Höft & Wessel Webpanel - Compaq Itsy - nanoEngine - Pangolin - PLEB - Yopy Tifon support has been removed in 2.4.3.3. Signed-off-by: Jonathan Neuschäfer Signed-off-by: Jonathan Corbet --- Documentation/arm/sa1100/adsbitsy.rst | 51 ---------- Documentation/arm/sa1100/brutus.rst | 69 ------------- Documentation/arm/sa1100/freebird.rst | 25 ----- Documentation/arm/sa1100/graphicsclient.rst | 102 -------------------- Documentation/arm/sa1100/graphicsmaster.rst | 60 ------------ Documentation/arm/sa1100/huw_webpanel.rst | 21 ---- Documentation/arm/sa1100/index.rst | 12 --- Documentation/arm/sa1100/itsy.rst | 47 --------- Documentation/arm/sa1100/nanoengine.rst | 11 --- Documentation/arm/sa1100/pangolin.rst | 29 ------ Documentation/arm/sa1100/pleb.rst | 13 --- Documentation/arm/sa1100/tifon.rst | 7 -- Documentation/arm/sa1100/yopy.rst | 5 - 13 files changed, 452 deletions(-) delete mode 100644 Documentation/arm/sa1100/adsbitsy.rst delete mode 100644 Documentation/arm/sa1100/brutus.rst delete mode 100644 Documentation/arm/sa1100/freebird.rst delete mode 100644 Documentation/arm/sa1100/graphicsclient.rst delete mode 100644 Documentation/arm/sa1100/graphicsmaster.rst delete mode 100644 Documentation/arm/sa1100/huw_webpanel.rst delete mode 100644 Documentation/arm/sa1100/itsy.rst delete mode 100644 Documentation/arm/sa1100/nanoengine.rst delete mode 100644 Documentation/arm/sa1100/pangolin.rst delete mode 100644 Documentation/arm/sa1100/pleb.rst delete mode 100644 Documentation/arm/sa1100/tifon.rst delete mode 100644 Documentation/arm/sa1100/yopy.rst diff --git a/Documentation/arm/sa1100/adsbitsy.rst b/Documentation/arm/sa1100/adsbitsy.rst deleted file mode 100644 index c179cb26b682..000000000000 --- a/Documentation/arm/sa1100/adsbitsy.rst +++ /dev/null @@ -1,51 +0,0 @@ -=============================== -ADS Bitsy Single Board Computer -=============================== - -(It is different from Bitsy(iPAQ) of Compaq) - -For more details, contact Applied Data Systems or see -http://www.applieddata.net/products.html - -The Linux support for this product has been provided by -Woojung Huh - -Use 'make adsbitsy_config' before any 'make config'. -This will set up defaults for ADS Bitsy support. - -The kernel zImage is linked to be loaded and executed at 0xc0400000. - -Linux can be used with the ADS BootLoader that ships with the -newer rev boards. See their documentation on how to load Linux. - -Supported peripherals -===================== - -- SA1100 LCD frame buffer (8/16bpp...sort of) -- SA1111 USB Master -- SA1100 serial port -- pcmcia, compact flash -- touchscreen(ucb1200) -- console on LCD screen -- serial ports (ttyS[0-2]) - - ttyS0 is default for serial console - -To do -===== - -- everything else! :-) - -Notes -===== - -- The flash on board is divided into 3 partitions. - You should be careful to use flash on board. - Its partition is different from GraphicsClient Plus and GraphicsMaster - -- 16bpp mode requires a different cable than what ships with the board. - Contact ADS or look through the manual to wire your own. Currently, - if you compile with 16bit mode support and switch into a lower bpp - mode, the timing is off so the image is corrupted. This will be - fixed soon. - -Any contribution can be sent to nico@fluxnic.net and will be greatly welcome! diff --git a/Documentation/arm/sa1100/brutus.rst b/Documentation/arm/sa1100/brutus.rst deleted file mode 100644 index e1a23bee6d44..000000000000 --- a/Documentation/arm/sa1100/brutus.rst +++ /dev/null @@ -1,69 +0,0 @@ -====== -Brutus -====== - -Brutus is an evaluation platform for the SA1100 manufactured by Intel. -For more details, see: - -http://developer.intel.com - -To compile for Brutus, you must issue the following commands:: - - make brutus_config - make config - [accept all the defaults] - make zImage - -The resulting kernel will end up in linux/arch/arm/boot/zImage. This file -must be loaded at 0xc0008000 in Brutus's memory and execution started at -0xc0008000 as well with the value of registers r0 = 0 and r1 = 16 upon -entry. - -But prior to execute the kernel, a ramdisk image must also be loaded in -memory. Use memory address 0xd8000000 for this. Note that the file -containing the (compressed) ramdisk image must not exceed 4 MB. - -Typically, you'll need angelboot to load the kernel. -The following angelboot.opt file should be used:: - - base 0xc0008000 - entry 0xc0008000 - r0 0x00000000 - r1 0x00000010 - device /dev/ttyS0 - options "9600 8N1" - baud 115200 - otherfile ramdisk_img.gz - otherbase 0xd8000000 - -Then load the kernel and ramdisk with:: - - angelboot -f angelboot.opt zImage - -The first Brutus serial port (assumed to be linked to /dev/ttyS0 on your -host PC) is used by angel to load the kernel and ramdisk image. The serial -console is provided through the second Brutus serial port. To access it, -you may use minicom configured with /dev/ttyS1, 9600 baud, 8N1, no flow -control. - -Currently supported -=================== - - - RS232 serial ports - - audio output - - LCD screen - - keyboard - -The actual Brutus support may not be complete without extra patches. -If such patches exist, they should be found from -ftp.netwinder.org/users/n/nico. - -A full PCMCIA support is still missing, although it's possible to hack -some drivers in order to drive already inserted cards at boot time with -little modifications. - -Any contribution is welcome. - -Please send patches to nico@fluxnic.net - -Have Fun ! diff --git a/Documentation/arm/sa1100/freebird.rst b/Documentation/arm/sa1100/freebird.rst deleted file mode 100644 index 81043d0c6d64..000000000000 --- a/Documentation/arm/sa1100/freebird.rst +++ /dev/null @@ -1,25 +0,0 @@ -======== -Freebird -======== - -Freebird-1.1 is produced by Legend(C), Inc. -`http://web.archive.org/web/*/http://www.legend.com.cn` -and software/linux maintained by Coventive(C), Inc. -(http://www.coventive.com) - -Based on the Nicolas's strongarm kernel tree. - -Maintainer: - -Chester Kuo - - - - - -Author: - -- Tim wu -- CIH -- Eric Peng -- Jeff Lee -- Allen Cheng -- Tony Liu diff --git a/Documentation/arm/sa1100/graphicsclient.rst b/Documentation/arm/sa1100/graphicsclient.rst deleted file mode 100644 index a73d61c3ce91..000000000000 --- a/Documentation/arm/sa1100/graphicsclient.rst +++ /dev/null @@ -1,102 +0,0 @@ -============================================= -ADS GraphicsClient Plus Single Board Computer -============================================= - -For more details, contact Applied Data Systems or see -http://www.applieddata.net/products.html - -The original Linux support for this product has been provided by -Nicolas Pitre . Continued development work by -Woojung Huh - -It's currently possible to mount a root filesystem via NFS providing a -complete Linux environment. Otherwise a ramdisk image may be used. The -board supports MTD/JFFS, so you could also mount something on there. - -Use 'make graphicsclient_config' before any 'make config'. This will set up -defaults for GraphicsClient Plus support. - -The kernel zImage is linked to be loaded and executed at 0xc0200000. -Also the following registers should have the specified values upon entry:: - - r0 = 0 - r1 = 29 (this is the GraphicsClient architecture number) - -Linux can be used with the ADS BootLoader that ships with the -newer rev boards. See their documentation on how to load Linux. -Angel is not available for the GraphicsClient Plus AFAIK. - -There is a board known as just the GraphicsClient that ADS used to -produce but has end of lifed. This code will not work on the older -board with the ADS bootloader, but should still work with Angel, -as outlined below. In any case, if you're planning on deploying -something en masse, you should probably get the newer board. - -If using Angel on the older boards, here is a typical angel.opt option file -if the kernel is loaded through the Angel Debug Monitor:: - - base 0xc0200000 - entry 0xc0200000 - r0 0x00000000 - r1 0x0000001d - device /dev/ttyS1 - options "38400 8N1" - baud 115200 - #otherfile ramdisk.gz - #otherbase 0xc0800000 - exec minicom - -Then the kernel (and ramdisk if otherfile/otherbase lines above are -uncommented) would be loaded with:: - - angelboot -f angelboot.opt zImage - -Here it is assumed that the board is connected to ttyS1 on your PC -and that minicom is preconfigured with /dev/ttyS1, 38400 baud, 8N1, no flow -control by default. - -If any other bootloader is used, ensure it accomplish the same, especially -for r0/r1 register values before jumping into the kernel. - - -Supported peripherals -===================== - -- SA1100 LCD frame buffer (8/16bpp...sort of) -- on-board SMC 92C96 ethernet NIC -- SA1100 serial port -- flash memory access (MTD/JFFS) -- pcmcia -- touchscreen(ucb1200) -- ps/2 keyboard -- console on LCD screen -- serial ports (ttyS[0-2]) - - ttyS0 is default for serial console -- Smart I/O (ADC, keypad, digital inputs, etc) - See http://www.eurotech-inc.com/linux-sbc.asp for IOCTL documentation - and example user space code. ps/2 keybd is multiplexed through this driver - -To do -===== - -- UCB1200 audio with new ucb_generic layer -- everything else! :-) - -Notes -===== - -- The flash on board is divided into 3 partitions. mtd0 is where - the ADS boot ROM and zImage is stored. It's been marked as - read-only to keep you from blasting over the bootloader. :) mtd1 is - for the ramdisk.gz image. mtd2 is user flash space and can be - utilized for either JFFS or if you're feeling crazy, running ext2 - on top of it. If you're not using the ADS bootloader, you're - welcome to blast over the mtd1 partition also. - -- 16bpp mode requires a different cable than what ships with the board. - Contact ADS or look through the manual to wire your own. Currently, - if you compile with 16bit mode support and switch into a lower bpp - mode, the timing is off so the image is corrupted. This will be - fixed soon. - -Any contribution can be sent to nico@fluxnic.net and will be greatly welcome! diff --git a/Documentation/arm/sa1100/graphicsmaster.rst b/Documentation/arm/sa1100/graphicsmaster.rst deleted file mode 100644 index e39892514f0c..000000000000 --- a/Documentation/arm/sa1100/graphicsmaster.rst +++ /dev/null @@ -1,60 +0,0 @@ -======================================== -ADS GraphicsMaster Single Board Computer -======================================== - -For more details, contact Applied Data Systems or see -http://www.applieddata.net/products.html - -The original Linux support for this product has been provided by -Nicolas Pitre . Continued development work by -Woojung Huh - -Use 'make graphicsmaster_config' before any 'make config'. -This will set up defaults for GraphicsMaster support. - -The kernel zImage is linked to be loaded and executed at 0xc0400000. - -Linux can be used with the ADS BootLoader that ships with the -newer rev boards. See their documentation on how to load Linux. - -Supported peripherals -===================== - -- SA1100 LCD frame buffer (8/16bpp...sort of) -- SA1111 USB Master -- on-board SMC 92C96 ethernet NIC -- SA1100 serial port -- flash memory access (MTD/JFFS) -- pcmcia, compact flash -- touchscreen(ucb1200) -- ps/2 keyboard -- console on LCD screen -- serial ports (ttyS[0-2]) - - ttyS0 is default for serial console -- Smart I/O (ADC, keypad, digital inputs, etc) - See http://www.eurotech-inc.com/linux-sbc.asp for IOCTL documentation - and example user space code. ps/2 keybd is multiplexed through this driver - -To do -===== - -- everything else! :-) - -Notes -===== - -- The flash on board is divided into 3 partitions. mtd0 is where - the zImage is stored. It's been marked as read-only to keep you - from blasting over the bootloader. :) mtd1 is - for the ramdisk.gz image. mtd2 is user flash space and can be - utilized for either JFFS or if you're feeling crazy, running ext2 - on top of it. If you're not using the ADS bootloader, you're - welcome to blast over the mtd1 partition also. - -- 16bpp mode requires a different cable than what ships with the board. - Contact ADS or look through the manual to wire your own. Currently, - if you compile with 16bit mode support and switch into a lower bpp - mode, the timing is off so the image is corrupted. This will be - fixed soon. - -Any contribution can be sent to nico@fluxnic.net and will be greatly welcome! diff --git a/Documentation/arm/sa1100/huw_webpanel.rst b/Documentation/arm/sa1100/huw_webpanel.rst deleted file mode 100644 index 1dc7ccb165f0..000000000000 --- a/Documentation/arm/sa1100/huw_webpanel.rst +++ /dev/null @@ -1,21 +0,0 @@ -======================= -Hoeft & Wessel Webpanel -======================= - -The HUW_WEBPANEL is a product of the german company Hoeft & Wessel AG - -If you want more information, please visit -http://www.hoeft-wessel.de - -To build the kernel:: - - make huw_webpanel_config - make oldconfig - [accept all defaults] - make zImage - -Mostly of the work is done by: -Roman Jordan jor@hoeft-wessel.de -Christoph Schulz schu@hoeft-wessel.de - -2000/12/18/ diff --git a/Documentation/arm/sa1100/index.rst b/Documentation/arm/sa1100/index.rst index 68c2a280a745..c9aed43280ff 100644 --- a/Documentation/arm/sa1100/index.rst +++ b/Documentation/arm/sa1100/index.rst @@ -7,19 +7,7 @@ Intel StrongARM 1100 .. toctree:: :maxdepth: 1 - adsbitsy assabet - brutus cerf - freebird - graphicsclient - graphicsmaster - huw_webpanel - itsy lart - nanoengine - pangolin - pleb serial_uart - tifon - yopy diff --git a/Documentation/arm/sa1100/itsy.rst b/Documentation/arm/sa1100/itsy.rst deleted file mode 100644 index f49896ba3ef1..000000000000 --- a/Documentation/arm/sa1100/itsy.rst +++ /dev/null @@ -1,47 +0,0 @@ -==== -Itsy -==== - -Itsy is a research project done by the Western Research Lab, and Systems -Research Center in Palo Alto, CA. The Itsy project is one of several -research projects at Compaq that are related to pocket computing. - -For more information, see: - - http://www.hpl.hp.com/downloads/crl/itsy/ - -Notes on initial 2.4 Itsy support (8/27/2000) : - -The port was done on an Itsy version 1.5 machine with a daughtercard with -64 Meg of DRAM and 32 Meg of Flash. The initial work includes support for -serial console (to see what you're doing). No other devices have been -enabled. - -To build, do a "make menuconfig" (or xmenuconfig) and select Itsy support. -Disable Flash and LCD support. and then do a make zImage. -Finally, you will need to cd to arch/arm/boot/tools and execute a make there -to build the params-itsy program used to boot the kernel. - -In order to install the port of 2.4 to the itsy, You will need to set the -configuration parameters in the monitor as follows:: - - Arg 1:0x08340000, Arg2: 0xC0000000, Arg3:18 (0x12), Arg4:0 - -Make sure the start-routine address is set to 0x00060000. - -Next, flash the params-itsy program to 0x00060000 ("p 1 0x00060000" in the -flash menu) Flash the kernel in arch/arm/boot/zImage into 0x08340000 -("p 1 0x00340000"). Finally flash an initial ramdisk into 0xC8000000 -("p 2 0x0") We used ramdisk-2-30.gz from the 0.11 version directory on -handhelds.org. - -The serial connection we established was at: - -8-bit data, no parity, 1 stop bit(s), 115200.00 b/s. in the monitor, in the -params-itsy program, and in the kernel itself. This can be changed, but -not easily. The monitor parameters are easily changed, the params program -setup is assembly outl's, and the kernel is a configuration item specific to -the itsy. (i.e. grep for CONFIG_SA1100_ITSY and you'll find where it is.) - - -This should get you a properly booting 2.4 kernel on the itsy. diff --git a/Documentation/arm/sa1100/nanoengine.rst b/Documentation/arm/sa1100/nanoengine.rst deleted file mode 100644 index 47f1a14cf98a..000000000000 --- a/Documentation/arm/sa1100/nanoengine.rst +++ /dev/null @@ -1,11 +0,0 @@ -========== -nanoEngine -========== - -"nanoEngine" is a SA1110 based single board computer from -Bright Star Engineering Inc. See www.brightstareng.com/arm -for more info. -(Ref: Stuart Adams ) - -Also visit Larry Doolittle's "Linux for the nanoEngine" site: -http://www.brightstareng.com/arm/nanoeng.htm diff --git a/Documentation/arm/sa1100/pangolin.rst b/Documentation/arm/sa1100/pangolin.rst deleted file mode 100644 index f0c5c1618553..000000000000 --- a/Documentation/arm/sa1100/pangolin.rst +++ /dev/null @@ -1,29 +0,0 @@ -======== -Pangolin -======== - -Pangolin is a StrongARM 1110-based evaluation platform produced -by Dialogue Technology (http://www.dialogue.com.tw/). -It has EISA slots for ease of configuration with SDRAM/Flash -memory card, USB/Serial/Audio card, Compact Flash card, -PCMCIA/IDE card and TFT-LCD card. - -To compile for Pangolin, you must issue the following commands:: - - make pangolin_config - make oldconfig - make zImage - -Supported peripherals -===================== - -- SA1110 serial port (UART1/UART2/UART3) -- flash memory access -- compact flash driver -- UDA1341 sound driver -- SA1100 LCD controller for 800x600 16bpp TFT-LCD -- MQ-200 driver for 800x600 16bpp TFT-LCD -- Penmount(touch panel) driver -- PCMCIA driver -- SMC91C94 LAN driver -- IDE driver (experimental) diff --git a/Documentation/arm/sa1100/pleb.rst b/Documentation/arm/sa1100/pleb.rst deleted file mode 100644 index d5b732967aa3..000000000000 --- a/Documentation/arm/sa1100/pleb.rst +++ /dev/null @@ -1,13 +0,0 @@ -==== -PLEB -==== - -The PLEB project was started as a student initiative at the School of -Computer Science and Engineering, University of New South Wales to make a -pocket computer capable of running the Linux Kernel. - -PLEB support has yet to be fully integrated. - -For more information, see: - - http://www.cse.unsw.edu.au diff --git a/Documentation/arm/sa1100/tifon.rst b/Documentation/arm/sa1100/tifon.rst deleted file mode 100644 index c26e910b9ea7..000000000000 --- a/Documentation/arm/sa1100/tifon.rst +++ /dev/null @@ -1,7 +0,0 @@ -===== -Tifon -===== - -More info has to come... - -Contact: Peter Danielsson diff --git a/Documentation/arm/sa1100/yopy.rst b/Documentation/arm/sa1100/yopy.rst deleted file mode 100644 index 5b35a5f61a44..000000000000 --- a/Documentation/arm/sa1100/yopy.rst +++ /dev/null @@ -1,5 +0,0 @@ -==== -Yopy -==== - -See http://www.yopydeveloper.org for more. -- GitLab From 13afbbf49a34c21085dd6c7a48340ed5d2309729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Thu, 8 Aug 2019 18:58:56 +0200 Subject: [PATCH 2733/7155] Documentation/arm/sa1100/assabet: Fix 'make assabet_defconfig' command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "make assabet_config" doesn't work. Signed-off-by: Jonathan Neuschäfer Signed-off-by: Jonathan Corbet --- Documentation/arm/sa1100/assabet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/arm/sa1100/assabet.rst b/Documentation/arm/sa1100/assabet.rst index 3e704831c311..a761e128fb08 100644 --- a/Documentation/arm/sa1100/assabet.rst +++ b/Documentation/arm/sa1100/assabet.rst @@ -14,7 +14,7 @@ Building the kernel To build the kernel with current defaults:: - make assabet_config + make assabet_defconfig make oldconfig make zImage -- GitLab From 4514fe8cd96f8147c18c05c7c32271d95d6ab0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Thu, 8 Aug 2019 18:48:09 +0200 Subject: [PATCH 2734/7155] Documentation/arm/samsung-s3c24xx: Remove stray U+FEFF character to fix title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems a UTF-8 byte order mark (the least useful kind of BOM...) snuck into the file and broke Sphinx's detection of the title line. Besides making arm/samsung-s3c24xx/index.html look a little better, this patch also confines the non-index pages in arm/samsung-s3c24xx to their own table of contents. Signed-off-by: Jonathan Neuschäfer Signed-off-by: Jonathan Corbet --- Documentation/arm/samsung-s3c24xx/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/arm/samsung-s3c24xx/index.rst b/Documentation/arm/samsung-s3c24xx/index.rst index 5b8a7f9398d8..ccb951a0bedb 100644 --- a/Documentation/arm/samsung-s3c24xx/index.rst +++ b/Documentation/arm/samsung-s3c24xx/index.rst @@ -1,6 +1,6 @@ .. SPDX-License-Identifier: GPL-2.0 -========================== +========================== Samsung S3C24XX SoC Family ========================== -- GitLab From b0eb93cfd516201ccf0e4d36e226cfe1b16cc1fe Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 8 Aug 2019 11:37:45 -0700 Subject: [PATCH 2735/7155] lkdtm: Add Control Flow Integrity test This adds a simple test for forward CFI (indirect function calls) with function prototype granularity (as implemented by Clang's CFI). Signed-off-by: Kees Cook --- drivers/misc/lkdtm/Makefile | 1 + drivers/misc/lkdtm/cfi.c | 42 +++++++++++++++++++++++++++++++++++++ drivers/misc/lkdtm/core.c | 1 + drivers/misc/lkdtm/lkdtm.h | 3 +++ 4 files changed, 47 insertions(+) create mode 100644 drivers/misc/lkdtm/cfi.c diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile index fb10eafe9bde..c70b3822013f 100644 --- a/drivers/misc/lkdtm/Makefile +++ b/drivers/misc/lkdtm/Makefile @@ -9,6 +9,7 @@ lkdtm-$(CONFIG_LKDTM) += refcount.o lkdtm-$(CONFIG_LKDTM) += rodata_objcopy.o lkdtm-$(CONFIG_LKDTM) += usercopy.o lkdtm-$(CONFIG_LKDTM) += stackleak.o +lkdtm-$(CONFIG_LKDTM) += cfi.o KASAN_SANITIZE_stackleak.o := n KCOV_INSTRUMENT_rodata.o := n diff --git a/drivers/misc/lkdtm/cfi.c b/drivers/misc/lkdtm/cfi.c new file mode 100644 index 000000000000..e73ebdbfa806 --- /dev/null +++ b/drivers/misc/lkdtm/cfi.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This is for all the tests relating directly to Control Flow Integrity. + */ +#include "lkdtm.h" + +static int called_count; + +/* Function taking one argument, without a return value. */ +static noinline void lkdtm_increment_void(int *counter) +{ + (*counter)++; +} + +/* Function taking one argument, returning int. */ +static noinline int lkdtm_increment_int(int *counter) +{ + (*counter)++; + + return *counter; +} +/* + * This tries to call an indirect function with a mismatched prototype. + */ +void lkdtm_CFI_FORWARD_PROTO(void) +{ + /* + * Matches lkdtm_increment_void()'s prototype, but not + * lkdtm_increment_int()'s prototype. + */ + void (*func)(int *); + + pr_info("Calling matched prototype ...\n"); + func = lkdtm_increment_void; + func(&called_count); + + pr_info("Calling mismatched prototype ...\n"); + func = (void *)lkdtm_increment_int; + func(&called_count); + + pr_info("Fail: survived mismatched prototype function call!\n"); +} diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 66ae6b2a6950..42136196681e 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -169,6 +169,7 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(USERCOPY_KERNEL), CRASHTYPE(USERCOPY_KERNEL_DS), CRASHTYPE(STACKLEAK_ERASING), + CRASHTYPE(CFI_FORWARD_PROTO), }; diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index 6a284a87a037..8a25afbdf954 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -95,4 +95,7 @@ void lkdtm_USERCOPY_KERNEL_DS(void); /* lkdtm_stackleak.c */ void lkdtm_STACKLEAK_ERASING(void); +/* cfi.c */ +void lkdtm_CFI_FORWARD_PROTO(void); + #endif -- GitLab From 75798f85f2badb04074cc909dbbb93072f4041ff Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:07:57 -0700 Subject: [PATCH 2736/7155] fscrypt: remove loadable module related code Since commit 643fa9612bf1 ("fscrypt: remove filesystem specific build config option"), fs/crypto/ can no longer be built as a loadable module. Thus it no longer needs a module_exit function, nor a MODULE_LICENSE. So remove them, and change module_init to late_initcall. Reviewed-by: Chandan Rajendra Signed-off-by: Eric Biggers --- fs/crypto/crypto.c | 20 +------------------- fs/crypto/fscrypt_private.h | 2 -- fs/crypto/keyinfo.c | 5 ----- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 45c3d0427fb2..d52c788b723d 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -510,22 +510,4 @@ static int __init fscrypt_init(void) fail: return -ENOMEM; } -module_init(fscrypt_init) - -/** - * fscrypt_exit() - Shutdown the fs encryption system - */ -static void __exit fscrypt_exit(void) -{ - fscrypt_destroy(); - - if (fscrypt_read_workqueue) - destroy_workqueue(fscrypt_read_workqueue); - kmem_cache_destroy(fscrypt_ctx_cachep); - kmem_cache_destroy(fscrypt_info_cachep); - - fscrypt_essiv_cleanup(); -} -module_exit(fscrypt_exit); - -MODULE_LICENSE("GPL"); +late_initcall(fscrypt_init) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 8978eec9d766..224178294371 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -166,6 +166,4 @@ struct fscrypt_mode { bool needs_essiv; }; -extern void __exit fscrypt_essiv_cleanup(void); - #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 207ebed918c1..9bcadc09e2ad 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -437,11 +437,6 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, return err; } -void __exit fscrypt_essiv_cleanup(void) -{ - crypto_free_shash(essiv_hash_tfm); -} - /* * Given the encryption mode and key (normally the derived key, but for * FS_POLICY_FLAG_DIRECT_KEY mode it's the master key), set up the inode's -- GitLab From 1c5100a2aab4143f36ca671c28189a8734d5381a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:07:58 -0700 Subject: [PATCH 2737/7155] fscrypt: clean up base64 encoding/decoding Some minor cleanups for the code that base64 encodes and decodes encrypted filenames and long name digests: - Rename "digest_{encode,decode}()" => "base64_{encode,decode}()" since they are used for filenames too, not just for long name digests. - Replace 'while' loops with more conventional 'for' loops. - Use 'u8' for binary data. Keep 'char' for string data. - Fully constify the lookup table (pointer was not const). - Improve comment. No actual change in behavior. Signed-off-by: Eric Biggers --- fs/crypto/fname.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 00d150ff3033..6f9daba99168 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -127,44 +127,45 @@ static int fname_decrypt(struct inode *inode, return 0; } -static const char *lookup_table = +static const char lookup_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; #define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) /** - * digest_encode() - + * base64_encode() - * - * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. + * Encodes the input string using characters from the set [A-Za-z0-9+,]. * The encoded string is roughly 4/3 times the size of the input string. + * + * Return: length of the encoded string */ -static int digest_encode(const char *src, int len, char *dst) +static int base64_encode(const u8 *src, int len, char *dst) { - int i = 0, bits = 0, ac = 0; + int i, bits = 0, ac = 0; char *cp = dst; - while (i < len) { - ac += (((unsigned char) src[i]) << bits); + for (i = 0; i < len; i++) { + ac += src[i] << bits; bits += 8; do { *cp++ = lookup_table[ac & 0x3f]; ac >>= 6; bits -= 6; } while (bits >= 6); - i++; } if (bits) *cp++ = lookup_table[ac & 0x3f]; return cp - dst; } -static int digest_decode(const char *src, int len, char *dst) +static int base64_decode(const char *src, int len, u8 *dst) { - int i = 0, bits = 0, ac = 0; + int i, bits = 0, ac = 0; const char *p; - char *cp = dst; + u8 *cp = dst; - while (i < len) { + for (i = 0; i < len; i++) { p = strchr(lookup_table, src[i]); if (p == NULL || src[i] == 0) return -2; @@ -175,7 +176,6 @@ static int digest_decode(const char *src, int len, char *dst) ac >>= 8; bits -= 8; } - i++; } if (ac) return -1; @@ -272,7 +272,7 @@ int fscrypt_fname_disk_to_usr(struct inode *inode, return fname_decrypt(inode, iname, oname); if (iname->len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) { - oname->len = digest_encode(iname->name, iname->len, + oname->len = base64_encode(iname->name, iname->len, oname->name); return 0; } @@ -287,7 +287,7 @@ int fscrypt_fname_disk_to_usr(struct inode *inode, FSCRYPT_FNAME_DIGEST(iname->name, iname->len), FSCRYPT_FNAME_DIGEST_SIZE); oname->name[0] = '_'; - oname->len = 1 + digest_encode((const char *)&digested_name, + oname->len = 1 + base64_encode((const u8 *)&digested_name, sizeof(digested_name), oname->name + 1); return 0; } @@ -380,8 +380,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, if (fname->crypto_buf.name == NULL) return -ENOMEM; - ret = digest_decode(iname->name + digested, iname->len - digested, - fname->crypto_buf.name); + ret = base64_decode(iname->name + digested, iname->len - digested, + fname->crypto_buf.name); if (ret < 0) { ret = -ENOENT; goto errout; -- GitLab From 886da8b39cf27995836062bb7fe5fd5cb764540a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:07:58 -0700 Subject: [PATCH 2738/7155] fscrypt: make fscrypt_msg() take inode instead of super_block Most of the warning and error messages in fs/crypto/ are for situations related to a specific inode, not merely to a super_block. So to make things easier, make fscrypt_msg() take an inode rather than a super_block, and make it print the inode number. Note: This is the same approach I'm taking for fsverity_msg(). Signed-off-by: Eric Biggers --- fs/crypto/crypto.c | 13 ++++++------- fs/crypto/fname.c | 8 ++------ fs/crypto/fscrypt_private.h | 10 +++++----- fs/crypto/hooks.c | 6 +++--- fs/crypto/keyinfo.c | 26 ++++++++++++-------------- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index d52c788b723d..3e4624cfe4b5 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -188,10 +188,8 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); skcipher_request_free(req); if (res) { - fscrypt_err(inode->i_sb, - "%scryption failed for inode %lu, block %llu: %d", - (rw == FS_DECRYPT ? "de" : "en"), - inode->i_ino, lblk_num, res); + fscrypt_err(inode, "%scryption failed for block %llu: %d", + (rw == FS_DECRYPT ? "De" : "En"), lblk_num, res); return res; } return 0; @@ -453,7 +451,7 @@ int fscrypt_initialize(unsigned int cop_flags) return res; } -void fscrypt_msg(struct super_block *sb, const char *level, +void fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...) { static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, @@ -467,8 +465,9 @@ void fscrypt_msg(struct super_block *sb, const char *level, va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - if (sb) - printk("%sfscrypt (%s): %pV\n", level, sb->s_id, &vaf); + if (inode) + printk("%sfscrypt (%s, inode %lu): %pV\n", + level, inode->i_sb->s_id, inode->i_ino, &vaf); else printk("%sfscrypt: %pV\n", level, &vaf); va_end(args); diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 6f9daba99168..5cab3bb2d1fc 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -71,9 +71,7 @@ int fname_encrypt(struct inode *inode, const struct qstr *iname, res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); skcipher_request_free(req); if (res < 0) { - fscrypt_err(inode->i_sb, - "Filename encryption failed for inode %lu: %d", - inode->i_ino, res); + fscrypt_err(inode, "Filename encryption failed: %d", res); return res; } @@ -117,9 +115,7 @@ static int fname_decrypt(struct inode *inode, res = crypto_wait_req(crypto_skcipher_decrypt(req), &wait); skcipher_request_free(req); if (res < 0) { - fscrypt_err(inode->i_sb, - "Filename decryption failed for inode %lu: %d", - inode->i_ino, res); + fscrypt_err(inode, "Filename decryption failed: %d", res); return res; } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 224178294371..4d715708c6e1 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -125,12 +125,12 @@ extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags); extern const struct dentry_operations fscrypt_d_ops; extern void __printf(3, 4) __cold -fscrypt_msg(struct super_block *sb, const char *level, const char *fmt, ...); +fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...); -#define fscrypt_warn(sb, fmt, ...) \ - fscrypt_msg(sb, KERN_WARNING, fmt, ##__VA_ARGS__) -#define fscrypt_err(sb, fmt, ...) \ - fscrypt_msg(sb, KERN_ERR, fmt, ##__VA_ARGS__) +#define fscrypt_warn(inode, fmt, ...) \ + fscrypt_msg((inode), KERN_WARNING, fmt, ##__VA_ARGS__) +#define fscrypt_err(inode, fmt, ...) \ + fscrypt_msg((inode), KERN_ERR, fmt, ##__VA_ARGS__) #define FSCRYPT_MAX_IV_SIZE 32 diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index c1d6715d88e9..bb3b7fcfdd48 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -39,9 +39,9 @@ int fscrypt_file_open(struct inode *inode, struct file *filp) dir = dget_parent(file_dentry(filp)); if (IS_ENCRYPTED(d_inode(dir)) && !fscrypt_has_permitted_context(d_inode(dir), inode)) { - fscrypt_warn(inode->i_sb, - "inconsistent encryption contexts: %lu/%lu", - d_inode(dir)->i_ino, inode->i_ino); + fscrypt_warn(inode, + "Inconsistent encryption context (parent directory: %lu)", + d_inode(dir)->i_ino); err = -EPERM; } dput(dir); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 9bcadc09e2ad..d0eb901a6d1a 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -166,10 +166,9 @@ static struct fscrypt_mode * select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) { if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { - fscrypt_warn(inode->i_sb, - "inode %lu uses unsupported encryption modes (contents mode %d, filenames mode %d)", - inode->i_ino, ci->ci_data_mode, - ci->ci_filename_mode); + fscrypt_warn(inode, + "Unsupported encryption modes (contents mode %d, filenames mode %d)", + ci->ci_data_mode, ci->ci_filename_mode); return ERR_PTR(-EINVAL); } @@ -206,14 +205,14 @@ static int find_and_derive_key(const struct inode *inode, if (ctx->flags & FS_POLICY_FLAG_DIRECT_KEY) { if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { - fscrypt_warn(inode->i_sb, - "direct key mode not allowed with %s", + fscrypt_warn(inode, + "Direct key mode not allowed with %s", mode->friendly_name); err = -EINVAL; } else if (ctx->contents_encryption_mode != ctx->filenames_encryption_mode) { - fscrypt_warn(inode->i_sb, - "direct key mode not allowed with different contents and filenames modes"); + fscrypt_warn(inode, + "Direct key mode not allowed with different contents and filenames modes"); err = -EINVAL; } else { memcpy(derived_key, payload->raw, mode->keysize); @@ -238,9 +237,8 @@ allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); if (IS_ERR(tfm)) { - fscrypt_warn(inode->i_sb, - "error allocating '%s' transform for inode %lu: %ld", - mode->cipher_str, inode->i_ino, PTR_ERR(tfm)); + fscrypt_warn(inode, "Error allocating '%s' transform: %ld", + mode->cipher_str, PTR_ERR(tfm)); return tfm; } if (unlikely(!mode->logged_impl_name)) { @@ -471,9 +469,9 @@ static int setup_crypto_transform(struct fscrypt_info *ci, err = init_essiv_generator(ci, raw_key, mode->keysize); if (err) { - fscrypt_warn(inode->i_sb, - "error initializing ESSIV generator for inode %lu: %d", - inode->i_ino, err); + fscrypt_warn(inode, + "Error initializing ESSIV generator: %d", + err); return err; } } -- GitLab From 63f668f0def1b58ed1e480661c4043d2b11abc6c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:07:59 -0700 Subject: [PATCH 2739/7155] fscrypt: improve warning messages for unsupported encryption contexts When fs/crypto/ encounters an inode with an invalid encryption context, currently it prints a warning if the pair of encryption modes are unrecognized, but it's silent if there are other problems such as unsupported context size, format, or flags. To help people debug such situations, add more warning messages. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index d0eb901a6d1a..e5ab18d98f32 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -510,8 +510,12 @@ int fscrypt_get_encryption_info(struct inode *inode) res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); if (res < 0) { if (!fscrypt_dummy_context_enabled(inode) || - IS_ENCRYPTED(inode)) + IS_ENCRYPTED(inode)) { + fscrypt_warn(inode, + "Error %d getting encryption context", + res); return res; + } /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; @@ -519,14 +523,22 @@ int fscrypt_get_encryption_info(struct inode *inode) ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE); } else if (res != sizeof(ctx)) { + fscrypt_warn(inode, + "Unknown encryption context size (%d bytes)", res); return -EINVAL; } - if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) + if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) { + fscrypt_warn(inode, "Unknown encryption context version (%d)", + ctx.format); return -EINVAL; + } - if (ctx.flags & ~FS_POLICY_FLAGS_VALID) + if (ctx.flags & ~FS_POLICY_FLAGS_VALID) { + fscrypt_warn(inode, "Unknown encryption context flags (0x%02x)", + ctx.flags); return -EINVAL; + } crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); if (!crypt_info) -- GitLab From a4d14e915bcb86e13b45231cd4fe2ce19bd9ba86 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:07:59 -0700 Subject: [PATCH 2740/7155] fscrypt: improve warnings for missing crypto API support Users of fscrypt with non-default algorithms will encounter an error like the following if they fail to include the needed algorithms into the crypto API when configuring the kernel (as per the documentation): Error allocating 'adiantum(xchacha12,aes)' transform: -2 This requires that the user figure out what the "-2" error means. Make it more friendly by printing a warning like the following instead: Missing crypto API support for Adiantum (API name: "adiantum(xchacha12,aes)") Also upgrade the log level for *other* errors to KERN_ERR. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index e5ab18d98f32..b75678587c3a 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -237,8 +237,13 @@ allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); if (IS_ERR(tfm)) { - fscrypt_warn(inode, "Error allocating '%s' transform: %ld", - mode->cipher_str, PTR_ERR(tfm)); + if (PTR_ERR(tfm) == -ENOENT) + fscrypt_warn(inode, + "Missing crypto API support for %s (API name: \"%s\")", + mode->friendly_name, mode->cipher_str); + else + fscrypt_err(inode, "Error allocating '%s' transform: %ld", + mode->cipher_str, PTR_ERR(tfm)); return tfm; } if (unlikely(!mode->logged_impl_name)) { @@ -384,9 +389,13 @@ static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) tfm = crypto_alloc_shash("sha256", 0, 0); if (IS_ERR(tfm)) { - fscrypt_warn(NULL, - "error allocating SHA-256 transform: %ld", - PTR_ERR(tfm)); + if (PTR_ERR(tfm) == -ENOENT) + fscrypt_warn(NULL, + "Missing crypto API support for SHA-256"); + else + fscrypt_err(NULL, + "Error allocating SHA-256 transform: %ld", + PTR_ERR(tfm)); return PTR_ERR(tfm); } prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); -- GitLab From 29a98c1caf7b37b12a79eee7f839bf2924593c1c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 Jul 2019 11:08:00 -0700 Subject: [PATCH 2741/7155] fscrypt: use ENOPKG when crypto API support missing Return ENOPKG rather than ENOENT when trying to open a file that's encrypted using algorithms not available in the kernel's crypto API. This avoids an ambiguity, since ENOENT is also returned when the file doesn't exist. Note: this is the same approach I'm taking for fs-verity. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index b75678587c3a..212994300233 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -237,13 +237,14 @@ allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); if (IS_ERR(tfm)) { - if (PTR_ERR(tfm) == -ENOENT) + if (PTR_ERR(tfm) == -ENOENT) { fscrypt_warn(inode, "Missing crypto API support for %s (API name: \"%s\")", mode->friendly_name, mode->cipher_str); - else - fscrypt_err(inode, "Error allocating '%s' transform: %ld", - mode->cipher_str, PTR_ERR(tfm)); + return ERR_PTR(-ENOPKG); + } + fscrypt_err(inode, "Error allocating '%s' transform: %ld", + mode->cipher_str, PTR_ERR(tfm)); return tfm; } if (unlikely(!mode->logged_impl_name)) { @@ -389,13 +390,14 @@ static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) tfm = crypto_alloc_shash("sha256", 0, 0); if (IS_ERR(tfm)) { - if (PTR_ERR(tfm) == -ENOENT) + if (PTR_ERR(tfm) == -ENOENT) { fscrypt_warn(NULL, "Missing crypto API support for SHA-256"); - else - fscrypt_err(NULL, - "Error allocating SHA-256 transform: %ld", - PTR_ERR(tfm)); + return -ENOPKG; + } + fscrypt_err(NULL, + "Error allocating SHA-256 transform: %ld", + PTR_ERR(tfm)); return PTR_ERR(tfm); } prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); -- GitLab From 7af0ab0d3aab951518b0d520f95e9f6b1995ec69 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:43 -0700 Subject: [PATCH 2742/7155] fs, fscrypt: move uapi definitions to new header More fscrypt definitions are being added, and we shouldn't use a disproportionate amount of space in for fscrypt stuff. So move the fscrypt definitions to a new header . For source compatibility with existing userspace programs, still includes the new header. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- MAINTAINERS | 1 + include/linux/fscrypt.h | 1 + include/uapi/linux/fs.h | 54 ++----------------------------- include/uapi/linux/fscrypt.h | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 51 deletions(-) create mode 100644 include/uapi/linux/fscrypt.h diff --git a/MAINTAINERS b/MAINTAINERS index a2c343ee3b2c..714ffdaaa920 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6603,6 +6603,7 @@ T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git S: Supported F: fs/crypto/ F: include/linux/fscrypt*.h +F: include/uapi/linux/fscrypt.h F: Documentation/filesystems/fscrypt.rst FSI SUBSYSTEM diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index bd8f207a2fb6..81c0c754f8b2 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -16,6 +16,7 @@ #include #include #include +#include #define FS_CRYPTO_BLOCK_SIZE 16 diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 59c71fa8c553..41bd84d25a98 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -13,6 +13,9 @@ #include #include #include +#ifndef __KERNEL__ +#include +#endif /* Use of MS_* flags within the kernel is restricted to core mount(2) code. */ #if !defined(__KERNEL__) @@ -212,57 +215,6 @@ struct fsxattr { #define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) #define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX]) -/* - * File system encryption support - */ -/* Policy provided via an ioctl on the topmost directory */ -#define FS_KEY_DESCRIPTOR_SIZE 8 - -#define FS_POLICY_FLAGS_PAD_4 0x00 -#define FS_POLICY_FLAGS_PAD_8 0x01 -#define FS_POLICY_FLAGS_PAD_16 0x02 -#define FS_POLICY_FLAGS_PAD_32 0x03 -#define FS_POLICY_FLAGS_PAD_MASK 0x03 -#define FS_POLICY_FLAG_DIRECT_KEY 0x04 /* use master key directly */ -#define FS_POLICY_FLAGS_VALID 0x07 - -/* Encryption algorithms */ -#define FS_ENCRYPTION_MODE_INVALID 0 -#define FS_ENCRYPTION_MODE_AES_256_XTS 1 -#define FS_ENCRYPTION_MODE_AES_256_GCM 2 -#define FS_ENCRYPTION_MODE_AES_256_CBC 3 -#define FS_ENCRYPTION_MODE_AES_256_CTS 4 -#define FS_ENCRYPTION_MODE_AES_128_CBC 5 -#define FS_ENCRYPTION_MODE_AES_128_CTS 6 -#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */ -#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */ -#define FS_ENCRYPTION_MODE_ADIANTUM 9 - -struct fscrypt_policy { - __u8 version; - __u8 contents_encryption_mode; - __u8 filenames_encryption_mode; - __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; -}; - -#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) -#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) -#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) - -/* Parameters for passing an encryption key into the kernel keyring */ -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 - -/* Structure that userspace passes to the kernel keyring */ -#define FS_MAX_KEY_SIZE 64 - -struct fscrypt_key { - __u32 mode; - __u8 raw[FS_MAX_KEY_SIZE]; - __u32 size; -}; - /* * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS) * diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h new file mode 100644 index 000000000000..26f6d2c19afd --- /dev/null +++ b/include/uapi/linux/fscrypt.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * fscrypt user API + * + * These ioctls can be used on filesystems that support fscrypt. See the + * "User API" section of Documentation/filesystems/fscrypt.rst. + */ +#ifndef _UAPI_LINUX_FSCRYPT_H +#define _UAPI_LINUX_FSCRYPT_H + +#include + +#define FS_KEY_DESCRIPTOR_SIZE 8 + +/* Encryption policy flags */ +#define FS_POLICY_FLAGS_PAD_4 0x00 +#define FS_POLICY_FLAGS_PAD_8 0x01 +#define FS_POLICY_FLAGS_PAD_16 0x02 +#define FS_POLICY_FLAGS_PAD_32 0x03 +#define FS_POLICY_FLAGS_PAD_MASK 0x03 +#define FS_POLICY_FLAG_DIRECT_KEY 0x04 /* use master key directly */ +#define FS_POLICY_FLAGS_VALID 0x07 + +/* Encryption algorithms */ +#define FS_ENCRYPTION_MODE_INVALID 0 +#define FS_ENCRYPTION_MODE_AES_256_XTS 1 +#define FS_ENCRYPTION_MODE_AES_256_GCM 2 +#define FS_ENCRYPTION_MODE_AES_256_CBC 3 +#define FS_ENCRYPTION_MODE_AES_256_CTS 4 +#define FS_ENCRYPTION_MODE_AES_128_CBC 5 +#define FS_ENCRYPTION_MODE_AES_128_CTS 6 +#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */ +#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */ +#define FS_ENCRYPTION_MODE_ADIANTUM 9 + +struct fscrypt_policy { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; +}; + +#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) +#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) + +/* Parameters for passing an encryption key into the kernel keyring */ +#define FS_KEY_DESC_PREFIX "fscrypt:" +#define FS_KEY_DESC_PREFIX_SIZE 8 + +/* Structure that userspace passes to the kernel keyring */ +#define FS_MAX_KEY_SIZE 64 + +struct fscrypt_key { + __u32 mode; + __u8 raw[FS_MAX_KEY_SIZE]; + __u32 size; +}; + +#endif /* _UAPI_LINUX_FSCRYPT_H */ -- GitLab From 2336d0deb2d4680349de59d6fbdfc338437be191 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:44 -0700 Subject: [PATCH 2743/7155] fscrypt: use FSCRYPT_ prefix for uapi constants Prefix all filesystem encryption UAPI constants except the ioctl numbers with "FSCRYPT_" rather than with "FS_". This namespaces the constants more appropriately and makes it clear that they are related specifically to the filesystem encryption feature, and to the 'fscrypt_*' structures. With some of the old names like "FS_POLICY_FLAGS_VALID", it was not immediately clear that the constant had anything to do with encryption. This is also useful because we'll be adding more encryption-related constants, e.g. for the policy version, and we'd otherwise have to choose whether to use unclear names like FS_POLICY_V1 or inconsistent names like FS_ENCRYPTION_POLICY_V1. For source compatibility with existing userspace programs, keep the old names defined as aliases to the new names. Finally, as long as new names are being defined anyway, I skipped defining new names for the fscrypt mode numbers that aren't actually used: INVALID (0), AES_256_GCM (2), AES_256_CBC (3), SPECK128_256_XTS (7), and SPECK128_256_CTS (8). Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- Documentation/filesystems/fscrypt.rst | 40 ++++++++--------- include/uapi/linux/fscrypt.h | 65 +++++++++++++++++---------- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 82efa41b0e6c..d60b885c4024 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -225,9 +225,10 @@ a little endian number, except that: is encrypted with AES-256 where the AES-256 key is the SHA-256 hash of the file's data encryption key. -- In the "direct key" configuration (FS_POLICY_FLAG_DIRECT_KEY set in - the fscrypt_policy), the file's nonce is also appended to the IV. - Currently this is only allowed with the Adiantum encryption mode. +- In the "direct key" configuration (FSCRYPT_POLICY_FLAG_DIRECT_KEY + set in the fscrypt_policy), the file's nonce is also appended to the + IV. Currently this is only allowed with the Adiantum encryption + mode. Filenames encryption -------------------- @@ -274,14 +275,14 @@ empty directory or verifies that a directory or regular file already has the specified encryption policy. It takes in a pointer to a :c:type:`struct fscrypt_policy`, defined as follows:: - #define FS_KEY_DESCRIPTOR_SIZE 8 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 struct fscrypt_policy { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; This structure must be initialized as follows: @@ -289,19 +290,18 @@ This structure must be initialized as follows: - ``version`` must be 0. - ``contents_encryption_mode`` and ``filenames_encryption_mode`` must - be set to constants from ```` which identify the - encryption modes to use. If unsure, use - FS_ENCRYPTION_MODE_AES_256_XTS (1) for ``contents_encryption_mode`` - and FS_ENCRYPTION_MODE_AES_256_CTS (4) for - ``filenames_encryption_mode``. + be set to constants from ```` which identify the + encryption modes to use. If unsure, use FSCRYPT_MODE_AES_256_XTS + (1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS + (4) for ``filenames_encryption_mode``. -- ``flags`` must contain a value from ```` which +- ``flags`` must contain a value from ```` which identifies the amount of NUL-padding to use when encrypting - filenames. If unsure, use FS_POLICY_FLAGS_PAD_32 (0x3). - In addition, if the chosen encryption modes are both - FS_ENCRYPTION_MODE_ADIANTUM, this can contain - FS_POLICY_FLAG_DIRECT_KEY to specify that the master key should be - used directly, without key derivation. + filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). In + addition, if the chosen encryption modes are both + FSCRYPT_MODE_ADIANTUM, this can contain + FSCRYPT_POLICY_FLAG_DIRECT_KEY to specify that the master key should + be used directly, without key derivation. - ``master_key_descriptor`` specifies how to find the master key in the keyring; see `Adding keys`_. It is up to userspace to choose a @@ -401,11 +401,11 @@ followed by the 16-character lower case hex representation of the ``master_key_descriptor`` that was set in the encryption policy. The key payload must conform to the following structure:: - #define FS_MAX_KEY_SIZE 64 + #define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { u32 mode; - u8 raw[FS_MAX_KEY_SIZE]; + u8 raw[FSCRYPT_MAX_KEY_SIZE]; u32 size; }; @@ -574,7 +574,7 @@ much confusion if an encryption policy were to be added to or removed from anything other than an empty directory.) The struct is defined as follows:: - #define FS_KEY_DESCRIPTOR_SIZE 8 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DERIVATION_NONCE_SIZE 16 struct fscrypt_context { @@ -582,7 +582,7 @@ as follows:: u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; - u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 26f6d2c19afd..674b0452ef57 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -10,35 +10,30 @@ #include -#define FS_KEY_DESCRIPTOR_SIZE 8 +#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 /* Encryption policy flags */ -#define FS_POLICY_FLAGS_PAD_4 0x00 -#define FS_POLICY_FLAGS_PAD_8 0x01 -#define FS_POLICY_FLAGS_PAD_16 0x02 -#define FS_POLICY_FLAGS_PAD_32 0x03 -#define FS_POLICY_FLAGS_PAD_MASK 0x03 -#define FS_POLICY_FLAG_DIRECT_KEY 0x04 /* use master key directly */ -#define FS_POLICY_FLAGS_VALID 0x07 +#define FSCRYPT_POLICY_FLAGS_PAD_4 0x00 +#define FSCRYPT_POLICY_FLAGS_PAD_8 0x01 +#define FSCRYPT_POLICY_FLAGS_PAD_16 0x02 +#define FSCRYPT_POLICY_FLAGS_PAD_32 0x03 +#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 +#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 /* use master key directly */ +#define FSCRYPT_POLICY_FLAGS_VALID 0x07 /* Encryption algorithms */ -#define FS_ENCRYPTION_MODE_INVALID 0 -#define FS_ENCRYPTION_MODE_AES_256_XTS 1 -#define FS_ENCRYPTION_MODE_AES_256_GCM 2 -#define FS_ENCRYPTION_MODE_AES_256_CBC 3 -#define FS_ENCRYPTION_MODE_AES_256_CTS 4 -#define FS_ENCRYPTION_MODE_AES_128_CBC 5 -#define FS_ENCRYPTION_MODE_AES_128_CTS 6 -#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */ -#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */ -#define FS_ENCRYPTION_MODE_ADIANTUM 9 +#define FSCRYPT_MODE_AES_256_XTS 1 +#define FSCRYPT_MODE_AES_256_CTS 4 +#define FSCRYPT_MODE_AES_128_CBC 5 +#define FSCRYPT_MODE_AES_128_CTS 6 +#define FSCRYPT_MODE_ADIANTUM 9 struct fscrypt_policy { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) @@ -46,16 +41,40 @@ struct fscrypt_policy { #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) /* Parameters for passing an encryption key into the kernel keyring */ -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 +#define FSCRYPT_KEY_DESC_PREFIX "fscrypt:" +#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 /* Structure that userspace passes to the kernel keyring */ -#define FS_MAX_KEY_SIZE 64 +#define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { __u32 mode; - __u8 raw[FS_MAX_KEY_SIZE]; + __u8 raw[FSCRYPT_MAX_KEY_SIZE]; __u32 size; }; +/**********************************************************************/ + +/* old names; don't add anything new here! */ +#define FS_KEY_DESCRIPTOR_SIZE FSCRYPT_KEY_DESCRIPTOR_SIZE +#define FS_POLICY_FLAGS_PAD_4 FSCRYPT_POLICY_FLAGS_PAD_4 +#define FS_POLICY_FLAGS_PAD_8 FSCRYPT_POLICY_FLAGS_PAD_8 +#define FS_POLICY_FLAGS_PAD_16 FSCRYPT_POLICY_FLAGS_PAD_16 +#define FS_POLICY_FLAGS_PAD_32 FSCRYPT_POLICY_FLAGS_PAD_32 +#define FS_POLICY_FLAGS_PAD_MASK FSCRYPT_POLICY_FLAGS_PAD_MASK +#define FS_POLICY_FLAG_DIRECT_KEY FSCRYPT_POLICY_FLAG_DIRECT_KEY +#define FS_POLICY_FLAGS_VALID FSCRYPT_POLICY_FLAGS_VALID +#define FS_ENCRYPTION_MODE_INVALID 0 /* never used */ +#define FS_ENCRYPTION_MODE_AES_256_XTS FSCRYPT_MODE_AES_256_XTS +#define FS_ENCRYPTION_MODE_AES_256_GCM 2 /* never used */ +#define FS_ENCRYPTION_MODE_AES_256_CBC 3 /* never used */ +#define FS_ENCRYPTION_MODE_AES_256_CTS FSCRYPT_MODE_AES_256_CTS +#define FS_ENCRYPTION_MODE_AES_128_CBC FSCRYPT_MODE_AES_128_CBC +#define FS_ENCRYPTION_MODE_AES_128_CTS FSCRYPT_MODE_AES_128_CTS +#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* removed */ +#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* removed */ +#define FS_ENCRYPTION_MODE_ADIANTUM FSCRYPT_MODE_ADIANTUM +#define FS_KEY_DESC_PREFIX FSCRYPT_KEY_DESC_PREFIX +#define FS_KEY_DESC_PREFIX_SIZE FSCRYPT_KEY_DESC_PREFIX_SIZE +#define FS_MAX_KEY_SIZE FSCRYPT_MAX_KEY_SIZE #endif /* _UAPI_LINUX_FSCRYPT_H */ -- GitLab From 3b6df59bc4d242ac5847592de55d1ff327cd4549 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:44 -0700 Subject: [PATCH 2744/7155] fscrypt: use FSCRYPT_* definitions, not FS_* Update fs/crypto/ to use the new names for the UAPI constants rather than the old names, then make the old definitions conditional on !__KERNEL__. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/crypto.c | 2 +- fs/crypto/fname.c | 2 +- fs/crypto/fscrypt_private.h | 16 +++++------ fs/crypto/keyinfo.c | 53 ++++++++++++++++++------------------ fs/crypto/policy.c | 14 +++++----- include/uapi/linux/fscrypt.h | 2 ++ 6 files changed, 46 insertions(+), 43 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 3e4624cfe4b5..7502c1f0ede9 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -141,7 +141,7 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, memset(iv, 0, ci->ci_mode->ivsize); iv->lblk_num = cpu_to_le64(lblk_num); - if (ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY) + if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE); if (ci->ci_essiv_tfm != NULL) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 5cab3bb2d1fc..f4977d44d69b 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -182,7 +182,7 @@ bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret) { int padding = 4 << (inode->i_crypt_info->ci_flags & - FS_POLICY_FLAGS_PAD_MASK); + FSCRYPT_POLICY_FLAGS_PAD_MASK); u32 encrypted_len; if (orig_len > max_len) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 4d715708c6e1..fae411b2f78d 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -34,7 +34,7 @@ struct fscrypt_context { u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; - u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; } __packed; @@ -84,7 +84,7 @@ struct fscrypt_info { u8 ci_data_mode; u8 ci_filename_mode; u8 ci_flags; - u8 ci_master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 ci_master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 ci_nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; @@ -98,16 +98,16 @@ typedef enum { static inline bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) { - if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && - filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) + if (contents_mode == FSCRYPT_MODE_AES_128_CBC && + filenames_mode == FSCRYPT_MODE_AES_128_CTS) return true; - if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && - filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + if (contents_mode == FSCRYPT_MODE_AES_256_XTS && + filenames_mode == FSCRYPT_MODE_AES_256_CTS) return true; - if (contents_mode == FS_ENCRYPTION_MODE_ADIANTUM && - filenames_mode == FS_ENCRYPTION_MODE_ADIANTUM) + if (contents_mode == FSCRYPT_MODE_ADIANTUM && + filenames_mode == FSCRYPT_MODE_ADIANTUM) return true; return false; diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 212994300233..22345ddede11 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -20,7 +20,7 @@ static struct crypto_shash *essiv_hash_tfm; -/* Table of keys referenced by FS_POLICY_FLAG_DIRECT_KEY policies */ +/* Table of keys referenced by DIRECT_KEY policies */ static DEFINE_HASHTABLE(fscrypt_master_keys, 6); /* 6 bits = 64 buckets */ static DEFINE_SPINLOCK(fscrypt_master_keys_lock); @@ -77,7 +77,7 @@ static int derive_key_aes(const u8 *master_key, */ static struct key * find_and_lock_process_key(const char *prefix, - const u8 descriptor[FS_KEY_DESCRIPTOR_SIZE], + const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], unsigned int min_keysize, const struct fscrypt_key **payload_ret) { @@ -87,7 +87,7 @@ find_and_lock_process_key(const char *prefix, const struct fscrypt_key *payload; description = kasprintf(GFP_NOFS, "%s%*phN", prefix, - FS_KEY_DESCRIPTOR_SIZE, descriptor); + FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); if (!description) return ERR_PTR(-ENOMEM); @@ -105,7 +105,7 @@ find_and_lock_process_key(const char *prefix, payload = (const struct fscrypt_key *)ukp->data; if (ukp->datalen != sizeof(struct fscrypt_key) || - payload->size < 1 || payload->size > FS_MAX_KEY_SIZE) { + payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { fscrypt_warn(NULL, "key with description '%s' has invalid payload", key->description); @@ -129,32 +129,32 @@ find_and_lock_process_key(const char *prefix, } static struct fscrypt_mode available_modes[] = { - [FS_ENCRYPTION_MODE_AES_256_XTS] = { + [FSCRYPT_MODE_AES_256_XTS] = { .friendly_name = "AES-256-XTS", .cipher_str = "xts(aes)", .keysize = 64, .ivsize = 16, }, - [FS_ENCRYPTION_MODE_AES_256_CTS] = { + [FSCRYPT_MODE_AES_256_CTS] = { .friendly_name = "AES-256-CTS-CBC", .cipher_str = "cts(cbc(aes))", .keysize = 32, .ivsize = 16, }, - [FS_ENCRYPTION_MODE_AES_128_CBC] = { + [FSCRYPT_MODE_AES_128_CBC] = { .friendly_name = "AES-128-CBC", .cipher_str = "cbc(aes)", .keysize = 16, .ivsize = 16, .needs_essiv = true, }, - [FS_ENCRYPTION_MODE_AES_128_CTS] = { + [FSCRYPT_MODE_AES_128_CTS] = { .friendly_name = "AES-128-CTS-CBC", .cipher_str = "cts(cbc(aes))", .keysize = 16, .ivsize = 16, }, - [FS_ENCRYPTION_MODE_ADIANTUM] = { + [FSCRYPT_MODE_ADIANTUM] = { .friendly_name = "Adiantum", .cipher_str = "adiantum(xchacha12,aes)", .keysize = 32, @@ -192,7 +192,7 @@ static int find_and_derive_key(const struct inode *inode, const struct fscrypt_key *payload; int err; - key = find_and_lock_process_key(FS_KEY_DESC_PREFIX, + key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, ctx->master_key_descriptor, mode->keysize, &payload); if (key == ERR_PTR(-ENOKEY) && inode->i_sb->s_cop->key_prefix) { @@ -203,7 +203,7 @@ static int find_and_derive_key(const struct inode *inode, if (IS_ERR(key)) return PTR_ERR(key); - if (ctx->flags & FS_POLICY_FLAG_DIRECT_KEY) { + if (ctx->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { fscrypt_warn(inode, "Direct key mode not allowed with %s", @@ -272,14 +272,14 @@ allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, return ERR_PTR(err); } -/* Master key referenced by FS_POLICY_FLAG_DIRECT_KEY policy */ +/* Master key referenced by DIRECT_KEY policy */ struct fscrypt_master_key { struct hlist_node mk_node; refcount_t mk_refcount; const struct fscrypt_mode *mk_mode; struct crypto_skcipher *mk_ctfm; - u8 mk_descriptor[FS_KEY_DESCRIPTOR_SIZE]; - u8 mk_raw[FS_MAX_KEY_SIZE]; + u8 mk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + u8 mk_raw[FSCRYPT_MAX_KEY_SIZE]; }; static void free_master_key(struct fscrypt_master_key *mk) @@ -320,13 +320,13 @@ find_or_insert_master_key(struct fscrypt_master_key *to_insert, * raw key, and use crypto_memneq() when comparing raw keys. */ - BUILD_BUG_ON(sizeof(hash_key) > FS_KEY_DESCRIPTOR_SIZE); + BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); spin_lock(&fscrypt_master_keys_lock); hash_for_each_possible(fscrypt_master_keys, mk, mk_node, hash_key) { if (memcmp(ci->ci_master_key_descriptor, mk->mk_descriptor, - FS_KEY_DESCRIPTOR_SIZE) != 0) + FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) continue; if (mode != mk->mk_mode) continue; @@ -370,7 +370,7 @@ fscrypt_get_master_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, goto err_free_mk; } memcpy(mk->mk_descriptor, ci->ci_master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(mk->mk_raw, raw_key, mode->keysize); return find_or_insert_master_key(mk, raw_key, mode, ci); @@ -448,8 +448,8 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, /* * Given the encryption mode and key (normally the derived key, but for - * FS_POLICY_FLAG_DIRECT_KEY mode it's the master key), set up the inode's - * symmetric cipher transform object(s). + * DIRECT_KEY mode it's the master key), set up the inode's symmetric cipher + * transform object(s). */ static int setup_crypto_transform(struct fscrypt_info *ci, struct fscrypt_mode *mode, @@ -459,7 +459,7 @@ static int setup_crypto_transform(struct fscrypt_info *ci, struct crypto_skcipher *ctfm; int err; - if (ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY) { + if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { mk = fscrypt_get_master_key(ci, mode, raw_key, inode); if (IS_ERR(mk)) return PTR_ERR(mk); @@ -476,7 +476,7 @@ static int setup_crypto_transform(struct fscrypt_info *ci, if (mode->needs_essiv) { /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ WARN_ON(mode->ivsize != AES_BLOCK_SIZE); - WARN_ON(ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY); + WARN_ON(ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY); err = init_essiv_generator(ci, raw_key, mode->keysize); if (err) { @@ -530,9 +530,10 @@ int fscrypt_get_encryption_info(struct inode *inode) /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; - ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; - memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE); + ctx.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; + ctx.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; + memset(ctx.master_key_descriptor, 0x42, + FSCRYPT_KEY_DESCRIPTOR_SIZE); } else if (res != sizeof(ctx)) { fscrypt_warn(inode, "Unknown encryption context size (%d bytes)", res); @@ -545,7 +546,7 @@ int fscrypt_get_encryption_info(struct inode *inode) return -EINVAL; } - if (ctx.flags & ~FS_POLICY_FLAGS_VALID) { + if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) { fscrypt_warn(inode, "Unknown encryption context flags (0x%02x)", ctx.flags); return -EINVAL; @@ -559,7 +560,7 @@ int fscrypt_get_encryption_info(struct inode *inode) crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(crypt_info->ci_nonce, ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); mode = select_encryption_mode(crypt_info, inode); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 4941fe8471ce..da7ae9c8b4ad 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -22,7 +22,7 @@ static bool is_encryption_context_consistent_with_policy( const struct fscrypt_policy *policy) { return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (ctx->flags == policy->flags) && (ctx->contents_encryption_mode == policy->contents_encryption_mode) && @@ -37,13 +37,13 @@ static int create_encryption_context_from_policy(struct inode *inode, ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, policy->filenames_encryption_mode)) return -EINVAL; - if (policy->flags & ~FS_POLICY_FLAGS_VALID) + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) return -EINVAL; ctx.contents_encryption_mode = policy->contents_encryption_mode; @@ -128,7 +128,7 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) policy.filenames_encryption_mode = ctx.filenames_encryption_mode; policy.flags = ctx.flags; memcpy(policy.master_key_descriptor, ctx.master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); if (copy_to_user(arg, &policy, sizeof(policy))) return -EFAULT; @@ -202,7 +202,7 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) if (parent_ci && child_ci) { return memcmp(parent_ci->ci_master_key_descriptor, child_ci->ci_master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (parent_ci->ci_data_mode == child_ci->ci_data_mode) && (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && @@ -219,7 +219,7 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) return memcmp(parent_ctx.master_key_descriptor, child_ctx.master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (parent_ctx.contents_encryption_mode == child_ctx.contents_encryption_mode) && (parent_ctx.filenames_encryption_mode == @@ -257,7 +257,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, ctx.filenames_encryption_mode = ci->ci_filename_mode; ctx.flags = ci->ci_flags; memcpy(ctx.master_key_descriptor, ci->ci_master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); res = parent->i_sb->s_cop->set_context(child, &ctx, diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 674b0452ef57..29a945d165de 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -55,6 +55,7 @@ struct fscrypt_key { /**********************************************************************/ /* old names; don't add anything new here! */ +#ifndef __KERNEL__ #define FS_KEY_DESCRIPTOR_SIZE FSCRYPT_KEY_DESCRIPTOR_SIZE #define FS_POLICY_FLAGS_PAD_4 FSCRYPT_POLICY_FLAGS_PAD_4 #define FS_POLICY_FLAGS_PAD_8 FSCRYPT_POLICY_FLAGS_PAD_8 @@ -76,5 +77,6 @@ struct fscrypt_key { #define FS_KEY_DESC_PREFIX FSCRYPT_KEY_DESC_PREFIX #define FS_KEY_DESC_PREFIX_SIZE FSCRYPT_KEY_DESC_PREFIX_SIZE #define FS_MAX_KEY_SIZE FSCRYPT_MAX_KEY_SIZE +#endif /* !__KERNEL__ */ #endif /* _UAPI_LINUX_FSCRYPT_H */ -- GitLab From 59dc6a8e1f534cde6f7986f2fd278062e25336c0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:44 -0700 Subject: [PATCH 2745/7155] fscrypt: add ->ci_inode to fscrypt_info Add an inode back-pointer to 'struct fscrypt_info', such that inode->i_crypt_info->ci_inode == inode. This will be useful for: 1. Evicting the inodes when a fscrypt key is removed, since we'll track the inodes using a given key by linking their fscrypt_infos together, rather than the inodes directly. This avoids bloating 'struct inode' with a new list_head. 2. Simplifying the per-file key setup, since the inode pointer won't have to be passed around everywhere just in case something goes wrong and it's needed for fscrypt_warn(). Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 3 +++ fs/crypto/keyinfo.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index fae411b2f78d..d345a7d28df8 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -73,6 +73,9 @@ struct fscrypt_info { */ struct fscrypt_mode *ci_mode; + /* Back-pointer to the inode */ + struct inode *ci_inode; + /* * If non-NULL, then this inode uses a master key directly rather than a * derived key, and ci_ctfm will equal ci_master_key->mk_ctfm. diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 22345ddede11..2d45a86f09db 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -556,6 +556,8 @@ int fscrypt_get_encryption_info(struct inode *inode) if (!crypt_info) return -ENOMEM; + crypt_info->ci_inode = inode; + crypt_info->ci_flags = ctx.flags; crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; -- GitLab From a828daabb2ae917c12f4dc617c04db1185e6221f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:45 -0700 Subject: [PATCH 2746/7155] fscrypt: rename fscrypt_master_key to fscrypt_direct_key In preparation for introducing a filesystem-level keyring which will contain fscrypt master keys, rename the existing 'struct fscrypt_master_key' to 'struct fscrypt_direct_key'. This is the structure in the existing table of master keys that's maintained to deduplicate the crypto transforms for v1 DIRECT_KEY policies. I've chosen to keep this table as-is rather than make it automagically add/remove the keys to/from the filesystem-level keyring, since that would add a lot of extra complexity to the filesystem-level keyring. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 7 +- fs/crypto/keyinfo.c | 130 ++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index d345a7d28df8..80d15a1bf606 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -77,11 +77,10 @@ struct fscrypt_info { struct inode *ci_inode; /* - * If non-NULL, then this inode uses a master key directly rather than a - * derived key, and ci_ctfm will equal ci_master_key->mk_ctfm. - * Otherwise, this inode uses a derived key. + * If non-NULL, then encryption is done using the master key directly + * and ci_ctfm will equal ci_direct_key->dk_ctfm. */ - struct fscrypt_master_key *ci_master_key; + struct fscrypt_direct_key *ci_direct_key; /* fields from the fscrypt_context */ u8 ci_data_mode; diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 2d45a86f09db..c4650071df27 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -21,8 +21,8 @@ static struct crypto_shash *essiv_hash_tfm; /* Table of keys referenced by DIRECT_KEY policies */ -static DEFINE_HASHTABLE(fscrypt_master_keys, 6); /* 6 bits = 64 buckets */ -static DEFINE_SPINLOCK(fscrypt_master_keys_lock); +static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ +static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); /* * Key derivation function. This generates the derived key by encrypting the @@ -273,46 +273,46 @@ allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, } /* Master key referenced by DIRECT_KEY policy */ -struct fscrypt_master_key { - struct hlist_node mk_node; - refcount_t mk_refcount; - const struct fscrypt_mode *mk_mode; - struct crypto_skcipher *mk_ctfm; - u8 mk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; - u8 mk_raw[FSCRYPT_MAX_KEY_SIZE]; +struct fscrypt_direct_key { + struct hlist_node dk_node; + refcount_t dk_refcount; + const struct fscrypt_mode *dk_mode; + struct crypto_skcipher *dk_ctfm; + u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; }; -static void free_master_key(struct fscrypt_master_key *mk) +static void free_direct_key(struct fscrypt_direct_key *dk) { - if (mk) { - crypto_free_skcipher(mk->mk_ctfm); - kzfree(mk); + if (dk) { + crypto_free_skcipher(dk->dk_ctfm); + kzfree(dk); } } -static void put_master_key(struct fscrypt_master_key *mk) +static void put_direct_key(struct fscrypt_direct_key *dk) { - if (!refcount_dec_and_lock(&mk->mk_refcount, &fscrypt_master_keys_lock)) + if (!refcount_dec_and_lock(&dk->dk_refcount, &fscrypt_direct_keys_lock)) return; - hash_del(&mk->mk_node); - spin_unlock(&fscrypt_master_keys_lock); + hash_del(&dk->dk_node); + spin_unlock(&fscrypt_direct_keys_lock); - free_master_key(mk); + free_direct_key(dk); } /* - * Find/insert the given master key into the fscrypt_master_keys table. If - * found, it is returned with elevated refcount, and 'to_insert' is freed if - * non-NULL. If not found, 'to_insert' is inserted and returned if it's - * non-NULL; otherwise NULL is returned. + * Find/insert the given key into the fscrypt_direct_keys table. If found, it + * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If + * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise + * NULL is returned. */ -static struct fscrypt_master_key * -find_or_insert_master_key(struct fscrypt_master_key *to_insert, +static struct fscrypt_direct_key * +find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, const u8 *raw_key, const struct fscrypt_mode *mode, const struct fscrypt_info *ci) { unsigned long hash_key; - struct fscrypt_master_key *mk; + struct fscrypt_direct_key *dk; /* * Careful: to avoid potentially leaking secret key bytes via timing @@ -323,60 +323,60 @@ find_or_insert_master_key(struct fscrypt_master_key *to_insert, BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); - spin_lock(&fscrypt_master_keys_lock); - hash_for_each_possible(fscrypt_master_keys, mk, mk_node, hash_key) { - if (memcmp(ci->ci_master_key_descriptor, mk->mk_descriptor, + spin_lock(&fscrypt_direct_keys_lock); + hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { + if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) continue; - if (mode != mk->mk_mode) + if (mode != dk->dk_mode) continue; - if (crypto_memneq(raw_key, mk->mk_raw, mode->keysize)) + if (crypto_memneq(raw_key, dk->dk_raw, mode->keysize)) continue; /* using existing tfm with same (descriptor, mode, raw_key) */ - refcount_inc(&mk->mk_refcount); - spin_unlock(&fscrypt_master_keys_lock); - free_master_key(to_insert); - return mk; + refcount_inc(&dk->dk_refcount); + spin_unlock(&fscrypt_direct_keys_lock); + free_direct_key(to_insert); + return dk; } if (to_insert) - hash_add(fscrypt_master_keys, &to_insert->mk_node, hash_key); - spin_unlock(&fscrypt_master_keys_lock); + hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key); + spin_unlock(&fscrypt_direct_keys_lock); return to_insert; } /* Prepare to encrypt directly using the master key in the given mode */ -static struct fscrypt_master_key * -fscrypt_get_master_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, +static struct fscrypt_direct_key * +fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, const u8 *raw_key, const struct inode *inode) { - struct fscrypt_master_key *mk; + struct fscrypt_direct_key *dk; int err; /* Is there already a tfm for this key? */ - mk = find_or_insert_master_key(NULL, raw_key, mode, ci); - if (mk) - return mk; + dk = find_or_insert_direct_key(NULL, raw_key, mode, ci); + if (dk) + return dk; /* Nope, allocate one. */ - mk = kzalloc(sizeof(*mk), GFP_NOFS); - if (!mk) + dk = kzalloc(sizeof(*dk), GFP_NOFS); + if (!dk) return ERR_PTR(-ENOMEM); - refcount_set(&mk->mk_refcount, 1); - mk->mk_mode = mode; - mk->mk_ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); - if (IS_ERR(mk->mk_ctfm)) { - err = PTR_ERR(mk->mk_ctfm); - mk->mk_ctfm = NULL; - goto err_free_mk; + refcount_set(&dk->dk_refcount, 1); + dk->dk_mode = mode; + dk->dk_ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); + if (IS_ERR(dk->dk_ctfm)) { + err = PTR_ERR(dk->dk_ctfm); + dk->dk_ctfm = NULL; + goto err_free_dk; } - memcpy(mk->mk_descriptor, ci->ci_master_key_descriptor, + memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(mk->mk_raw, raw_key, mode->keysize); + memcpy(dk->dk_raw, raw_key, mode->keysize); - return find_or_insert_master_key(mk, raw_key, mode, ci); + return find_or_insert_direct_key(dk, raw_key, mode, ci); -err_free_mk: - free_master_key(mk); +err_free_dk: + free_direct_key(dk); return ERR_PTR(err); } @@ -455,22 +455,22 @@ static int setup_crypto_transform(struct fscrypt_info *ci, struct fscrypt_mode *mode, const u8 *raw_key, const struct inode *inode) { - struct fscrypt_master_key *mk; + struct fscrypt_direct_key *dk; struct crypto_skcipher *ctfm; int err; if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { - mk = fscrypt_get_master_key(ci, mode, raw_key, inode); - if (IS_ERR(mk)) - return PTR_ERR(mk); - ctfm = mk->mk_ctfm; + dk = fscrypt_get_direct_key(ci, mode, raw_key, inode); + if (IS_ERR(dk)) + return PTR_ERR(dk); + ctfm = dk->dk_ctfm; } else { - mk = NULL; + dk = NULL; ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); if (IS_ERR(ctfm)) return PTR_ERR(ctfm); } - ci->ci_master_key = mk; + ci->ci_direct_key = dk; ci->ci_ctfm = ctfm; if (mode->needs_essiv) { @@ -494,8 +494,8 @@ static void put_crypt_info(struct fscrypt_info *ci) if (!ci) return; - if (ci->ci_master_key) { - put_master_key(ci->ci_master_key); + if (ci->ci_direct_key) { + put_direct_key(ci->ci_direct_key); } else { crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); -- GitLab From 3ec4f2a62927c72607db633f55b0489e3d5b8e48 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:45 -0700 Subject: [PATCH 2747/7155] fscrypt: refactor key setup code in preparation for v2 policies Do some more refactoring of the key setup code, in preparation for introducing a filesystem-level keyring and v2 encryption policies: - Now that ci_inode exists, don't pass around the inode unnecessarily. - Define a function setup_file_encryption_key() which handles the crypto key setup given an under-construction fscrypt_info. Don't pass the fscrypt_context, since everything is in the fscrypt_info. [This will be extended for v2 policies and the fs-level keyring.] - Define a function fscrypt_set_derived_key() which sets the per-file key, without depending on anything specific to v1 policies. [This will also be used for v2 policies.] - Define a function fscrypt_setup_v1_file_key() which takes the raw master key, thus separating finding the key from using it. [This will also be used if the key is found in the fs-level keyring.] Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 11 +- fs/crypto/keyinfo.c | 247 ++++++++++++++++++++---------------- 2 files changed, 146 insertions(+), 112 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 80d15a1bf606..56bac5c7ef40 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -4,9 +4,8 @@ * * Copyright (C) 2015, Google, Inc. * - * This contains encryption key functions. - * - * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. + * Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar. + * Heavily modified since then. */ #ifndef _FSCRYPT_PRIVATE_H @@ -168,4 +167,10 @@ struct fscrypt_mode { bool needs_essiv; }; +static inline bool +fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) +{ + return mode->ivsize >= offsetofend(union fscrypt_iv, nonce); +} + #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index c4650071df27..c6bf44d64111 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* - * key management facility for FS encryption support. + * Key setup facility for FS encryption support. * * Copyright (C) 2015, Google, Inc. * - * This contains encryption key functions. - * - * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. + * Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar. + * Heavily modified since then. */ #include @@ -25,14 +24,19 @@ static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); /* - * Key derivation function. This generates the derived key by encrypting the - * master key with AES-128-ECB using the inode's nonce as the AES key. + * v1 key derivation function. This generates the derived key by encrypting the + * master key with AES-128-ECB using the nonce as the AES key. This provides a + * unique derived key with sufficient entropy for each inode. However, it's + * nonstandard, non-extensible, doesn't evenly distribute the entropy from the + * master key, and is trivially reversible: an attacker who compromises a + * derived key can "decrypt" it to get back to the master key, then derive any + * other key. For all new code, use HKDF instead. * * The master key must be at least as long as the derived key. If the master * key is longer, then only the first 'derived_keysize' bytes are used. */ static int derive_key_aes(const u8 *master_key, - const struct fscrypt_context *ctx, + const u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE], u8 *derived_key, unsigned int derived_keysize) { int res = 0; @@ -55,7 +59,7 @@ static int derive_key_aes(const u8 *master_key, skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); - res = crypto_skcipher_setkey(tfm, ctx->nonce, sizeof(ctx->nonce)); + res = crypto_skcipher_setkey(tfm, nonce, FS_KEY_DERIVATION_NONCE_SIZE); if (res < 0) goto out; @@ -183,54 +187,10 @@ select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) return ERR_PTR(-EINVAL); } -/* Find the master key, then derive the inode's actual encryption key */ -static int find_and_derive_key(const struct inode *inode, - const struct fscrypt_context *ctx, - u8 *derived_key, const struct fscrypt_mode *mode) -{ - struct key *key; - const struct fscrypt_key *payload; - int err; - - key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, - ctx->master_key_descriptor, - mode->keysize, &payload); - if (key == ERR_PTR(-ENOKEY) && inode->i_sb->s_cop->key_prefix) { - key = find_and_lock_process_key(inode->i_sb->s_cop->key_prefix, - ctx->master_key_descriptor, - mode->keysize, &payload); - } - if (IS_ERR(key)) - return PTR_ERR(key); - - if (ctx->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { - if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { - fscrypt_warn(inode, - "Direct key mode not allowed with %s", - mode->friendly_name); - err = -EINVAL; - } else if (ctx->contents_encryption_mode != - ctx->filenames_encryption_mode) { - fscrypt_warn(inode, - "Direct key mode not allowed with different contents and filenames modes"); - err = -EINVAL; - } else { - memcpy(derived_key, payload->raw, mode->keysize); - err = 0; - } - } else { - err = derive_key_aes(payload->raw, ctx, derived_key, - mode->keysize); - } - up_read(&key->sem); - key_put(key); - return err; -} - -/* Allocate and key a symmetric cipher object for the given encryption mode */ +/* Create a symmetric cipher object for the given encryption mode and key */ static struct crypto_skcipher * -allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, - const struct inode *inode) +fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, + const struct inode *inode) { struct crypto_skcipher *tfm; int err; @@ -308,8 +268,7 @@ static void put_direct_key(struct fscrypt_direct_key *dk) */ static struct fscrypt_direct_key * find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, - const u8 *raw_key, const struct fscrypt_mode *mode, - const struct fscrypt_info *ci) + const u8 *raw_key, const struct fscrypt_info *ci) { unsigned long hash_key; struct fscrypt_direct_key *dk; @@ -328,9 +287,9 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) continue; - if (mode != dk->dk_mode) + if (ci->ci_mode != dk->dk_mode) continue; - if (crypto_memneq(raw_key, dk->dk_raw, mode->keysize)) + if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) continue; /* using existing tfm with same (descriptor, mode, raw_key) */ refcount_inc(&dk->dk_refcount); @@ -346,14 +305,13 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, /* Prepare to encrypt directly using the master key in the given mode */ static struct fscrypt_direct_key * -fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, - const u8 *raw_key, const struct inode *inode) +fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) { struct fscrypt_direct_key *dk; int err; /* Is there already a tfm for this key? */ - dk = find_or_insert_direct_key(NULL, raw_key, mode, ci); + dk = find_or_insert_direct_key(NULL, raw_key, ci); if (dk) return dk; @@ -362,8 +320,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, if (!dk) return ERR_PTR(-ENOMEM); refcount_set(&dk->dk_refcount, 1); - dk->dk_mode = mode; - dk->dk_ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); + dk->dk_mode = ci->ci_mode; + dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, + ci->ci_inode); if (IS_ERR(dk->dk_ctfm)) { err = PTR_ERR(dk->dk_ctfm); dk->dk_ctfm = NULL; @@ -371,9 +330,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, } memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(dk->dk_raw, raw_key, mode->keysize); + memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); - return find_or_insert_direct_key(dk, raw_key, mode, ci); + return find_or_insert_direct_key(dk, raw_key, ci); err_free_dk: free_direct_key(dk); @@ -422,6 +381,9 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, struct crypto_cipher *essiv_tfm; u8 salt[SHA256_DIGEST_SIZE]; + if (WARN_ON(ci->ci_mode->ivsize != AES_BLOCK_SIZE)) + return -EINVAL; + essiv_tfm = crypto_alloc_cipher("aes", 0, 0); if (IS_ERR(essiv_tfm)) return PTR_ERR(essiv_tfm); @@ -446,41 +408,24 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, return err; } -/* - * Given the encryption mode and key (normally the derived key, but for - * DIRECT_KEY mode it's the master key), set up the inode's symmetric cipher - * transform object(s). - */ -static int setup_crypto_transform(struct fscrypt_info *ci, - struct fscrypt_mode *mode, - const u8 *raw_key, const struct inode *inode) +/* Given the per-file key, set up the file's crypto transform object(s) */ +static int fscrypt_set_derived_key(struct fscrypt_info *ci, + const u8 *derived_key) { - struct fscrypt_direct_key *dk; + struct fscrypt_mode *mode = ci->ci_mode; struct crypto_skcipher *ctfm; int err; - if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { - dk = fscrypt_get_direct_key(ci, mode, raw_key, inode); - if (IS_ERR(dk)) - return PTR_ERR(dk); - ctfm = dk->dk_ctfm; - } else { - dk = NULL; - ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); - if (IS_ERR(ctfm)) - return PTR_ERR(ctfm); - } - ci->ci_direct_key = dk; + ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode); + if (IS_ERR(ctfm)) + return PTR_ERR(ctfm); + ci->ci_ctfm = ctfm; if (mode->needs_essiv) { - /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ - WARN_ON(mode->ivsize != AES_BLOCK_SIZE); - WARN_ON(ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY); - - err = init_essiv_generator(ci, raw_key, mode->keysize); + err = init_essiv_generator(ci, derived_key, mode->keysize); if (err) { - fscrypt_warn(inode, + fscrypt_warn(ci->ci_inode, "Error initializing ESSIV generator: %d", err); return err; @@ -489,6 +434,105 @@ static int setup_crypto_transform(struct fscrypt_info *ci, return 0; } +/* v1 policy, DIRECT_KEY: use the master key directly */ +static int setup_v1_file_key_direct(struct fscrypt_info *ci, + const u8 *raw_master_key) +{ + const struct fscrypt_mode *mode = ci->ci_mode; + struct fscrypt_direct_key *dk; + + if (!fscrypt_mode_supports_direct_key(mode)) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with %s", + mode->friendly_name); + return -EINVAL; + } + + if (ci->ci_data_mode != ci->ci_filename_mode) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with different contents and filenames modes"); + return -EINVAL; + } + + /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ + if (WARN_ON(mode->needs_essiv)) + return -EINVAL; + + dk = fscrypt_get_direct_key(ci, raw_master_key); + if (IS_ERR(dk)) + return PTR_ERR(dk); + ci->ci_direct_key = dk; + ci->ci_ctfm = dk->dk_ctfm; + return 0; +} + +/* v1 policy, !DIRECT_KEY: derive the file's encryption key */ +static int setup_v1_file_key_derived(struct fscrypt_info *ci, + const u8 *raw_master_key) +{ + u8 *derived_key; + int err; + + /* + * This cannot be a stack buffer because it will be passed to the + * scatterlist crypto API during derive_key_aes(). + */ + derived_key = kmalloc(ci->ci_mode->keysize, GFP_NOFS); + if (!derived_key) + return -ENOMEM; + + err = derive_key_aes(raw_master_key, ci->ci_nonce, + derived_key, ci->ci_mode->keysize); + if (err) + goto out; + + err = fscrypt_set_derived_key(ci, derived_key); +out: + kzfree(derived_key); + return err; +} + +static int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, + const u8 *raw_master_key) +{ + if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) + return setup_v1_file_key_direct(ci, raw_master_key); + else + return setup_v1_file_key_derived(ci, raw_master_key); +} + +static int fscrypt_setup_v1_file_key_via_subscribed_keyrings( + struct fscrypt_info *ci) +{ + struct key *key; + const struct fscrypt_key *payload; + int err; + + key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, + ci->ci_master_key_descriptor, + ci->ci_mode->keysize, &payload); + if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) { + key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix, + ci->ci_master_key_descriptor, + ci->ci_mode->keysize, &payload); + } + if (IS_ERR(key)) + return PTR_ERR(key); + + err = fscrypt_setup_v1_file_key(ci, payload->raw); + up_read(&key->sem); + key_put(key); + return err; +} + +/* + * Find the master key, then set up the inode's actual encryption key. + */ +static int setup_file_encryption_key(struct fscrypt_info *ci) +{ + return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); +} + static void put_crypt_info(struct fscrypt_info *ci) { if (!ci) @@ -508,7 +552,6 @@ int fscrypt_get_encryption_info(struct inode *inode) struct fscrypt_info *crypt_info; struct fscrypt_context ctx; struct fscrypt_mode *mode; - u8 *raw_key = NULL; int res; if (fscrypt_has_encryption_key(inode)) @@ -573,20 +616,7 @@ int fscrypt_get_encryption_info(struct inode *inode) WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); crypt_info->ci_mode = mode; - /* - * This cannot be a stack buffer because it may be passed to the - * scatterlist crypto API as part of key derivation. - */ - res = -ENOMEM; - raw_key = kmalloc(mode->keysize, GFP_NOFS); - if (!raw_key) - goto out; - - res = find_and_derive_key(inode, &ctx, raw_key, mode); - if (res) - goto out; - - res = setup_crypto_transform(crypt_info, mode, raw_key, inode); + res = setup_file_encryption_key(crypt_info); if (res) goto out; @@ -596,7 +626,6 @@ int fscrypt_get_encryption_info(struct inode *inode) if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); - kzfree(raw_key); return res; } EXPORT_SYMBOL(fscrypt_get_encryption_info); -- GitLab From 0109ce76dd6e9e69559e56ea9f10d1e12ca4a50b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:45 -0700 Subject: [PATCH 2748/7155] fscrypt: move v1 policy key setup to keysetup_v1.c In preparation for introducing v2 encryption policies which will find and derive encryption keys differently from the current v1 encryption policies, move the v1 policy-specific key setup code from keyinfo.c into keysetup_v1.c. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/Makefile | 8 +- fs/crypto/fscrypt_private.h | 17 ++ fs/crypto/keyinfo.c | 328 +--------------------------------- fs/crypto/keysetup_v1.c | 338 ++++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 322 deletions(-) create mode 100644 fs/crypto/keysetup_v1.c diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 4f0df5e682e4..1fba255c34ca 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -1,5 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o -fscrypto-y := crypto.o fname.o hooks.o keyinfo.o policy.o +fscrypto-y := crypto.o \ + fname.o \ + hooks.o \ + keyinfo.o \ + keysetup_v1.o \ + policy.o + fscrypto-$(CONFIG_BLOCK) += bio.o diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 56bac5c7ef40..387b44b255f6 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -173,4 +173,21 @@ fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) return mode->ivsize >= offsetofend(union fscrypt_iv, nonce); } +extern struct crypto_skcipher * +fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, + const struct inode *inode); + +extern int fscrypt_set_derived_key(struct fscrypt_info *ci, + const u8 *derived_key); + +/* keysetup_v1.c */ + +extern void fscrypt_put_direct_key(struct fscrypt_direct_key *dk); + +extern int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, + const u8 *raw_master_key); + +extern int fscrypt_setup_v1_file_key_via_subscribed_keyrings( + struct fscrypt_info *ci); + #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index c6bf44d64111..f4a47448e9ef 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -8,130 +8,15 @@ * Heavily modified since then. */ -#include -#include -#include #include -#include #include #include +#include + #include "fscrypt_private.h" static struct crypto_shash *essiv_hash_tfm; -/* Table of keys referenced by DIRECT_KEY policies */ -static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ -static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); - -/* - * v1 key derivation function. This generates the derived key by encrypting the - * master key with AES-128-ECB using the nonce as the AES key. This provides a - * unique derived key with sufficient entropy for each inode. However, it's - * nonstandard, non-extensible, doesn't evenly distribute the entropy from the - * master key, and is trivially reversible: an attacker who compromises a - * derived key can "decrypt" it to get back to the master key, then derive any - * other key. For all new code, use HKDF instead. - * - * The master key must be at least as long as the derived key. If the master - * key is longer, then only the first 'derived_keysize' bytes are used. - */ -static int derive_key_aes(const u8 *master_key, - const u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE], - u8 *derived_key, unsigned int derived_keysize) -{ - int res = 0; - struct skcipher_request *req = NULL; - DECLARE_CRYPTO_WAIT(wait); - struct scatterlist src_sg, dst_sg; - struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); - - if (IS_ERR(tfm)) { - res = PTR_ERR(tfm); - tfm = NULL; - goto out; - } - crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); - req = skcipher_request_alloc(tfm, GFP_NOFS); - if (!req) { - res = -ENOMEM; - goto out; - } - skcipher_request_set_callback(req, - CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &wait); - res = crypto_skcipher_setkey(tfm, nonce, FS_KEY_DERIVATION_NONCE_SIZE); - if (res < 0) - goto out; - - sg_init_one(&src_sg, master_key, derived_keysize); - sg_init_one(&dst_sg, derived_key, derived_keysize); - skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, - NULL); - res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); -out: - skcipher_request_free(req); - crypto_free_skcipher(tfm); - return res; -} - -/* - * Search the current task's subscribed keyrings for a "logon" key with - * description prefix:descriptor, and if found acquire a read lock on it and - * return a pointer to its validated payload in *payload_ret. - */ -static struct key * -find_and_lock_process_key(const char *prefix, - const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], - unsigned int min_keysize, - const struct fscrypt_key **payload_ret) -{ - char *description; - struct key *key; - const struct user_key_payload *ukp; - const struct fscrypt_key *payload; - - description = kasprintf(GFP_NOFS, "%s%*phN", prefix, - FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); - if (!description) - return ERR_PTR(-ENOMEM); - - key = request_key(&key_type_logon, description, NULL); - kfree(description); - if (IS_ERR(key)) - return key; - - down_read(&key->sem); - ukp = user_key_payload_locked(key); - - if (!ukp) /* was the key revoked before we acquired its semaphore? */ - goto invalid; - - payload = (const struct fscrypt_key *)ukp->data; - - if (ukp->datalen != sizeof(struct fscrypt_key) || - payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { - fscrypt_warn(NULL, - "key with description '%s' has invalid payload", - key->description); - goto invalid; - } - - if (payload->size < min_keysize) { - fscrypt_warn(NULL, - "key with description '%s' is too short (got %u bytes, need %u+ bytes)", - key->description, payload->size, min_keysize); - goto invalid; - } - - *payload_ret = payload; - return key; - -invalid: - up_read(&key->sem); - key_put(key); - return ERR_PTR(-ENOKEY); -} - static struct fscrypt_mode available_modes[] = { [FSCRYPT_MODE_AES_256_XTS] = { .friendly_name = "AES-256-XTS", @@ -188,9 +73,9 @@ select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) } /* Create a symmetric cipher object for the given encryption mode and key */ -static struct crypto_skcipher * -fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, - const struct inode *inode) +struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, + const u8 *raw_key, + const struct inode *inode) { struct crypto_skcipher *tfm; int err; @@ -232,113 +117,6 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, return ERR_PTR(err); } -/* Master key referenced by DIRECT_KEY policy */ -struct fscrypt_direct_key { - struct hlist_node dk_node; - refcount_t dk_refcount; - const struct fscrypt_mode *dk_mode; - struct crypto_skcipher *dk_ctfm; - u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; - u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; -}; - -static void free_direct_key(struct fscrypt_direct_key *dk) -{ - if (dk) { - crypto_free_skcipher(dk->dk_ctfm); - kzfree(dk); - } -} - -static void put_direct_key(struct fscrypt_direct_key *dk) -{ - if (!refcount_dec_and_lock(&dk->dk_refcount, &fscrypt_direct_keys_lock)) - return; - hash_del(&dk->dk_node); - spin_unlock(&fscrypt_direct_keys_lock); - - free_direct_key(dk); -} - -/* - * Find/insert the given key into the fscrypt_direct_keys table. If found, it - * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If - * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise - * NULL is returned. - */ -static struct fscrypt_direct_key * -find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, - const u8 *raw_key, const struct fscrypt_info *ci) -{ - unsigned long hash_key; - struct fscrypt_direct_key *dk; - - /* - * Careful: to avoid potentially leaking secret key bytes via timing - * information, we must key the hash table by descriptor rather than by - * raw key, and use crypto_memneq() when comparing raw keys. - */ - - BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); - - spin_lock(&fscrypt_direct_keys_lock); - hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { - if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) - continue; - if (ci->ci_mode != dk->dk_mode) - continue; - if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) - continue; - /* using existing tfm with same (descriptor, mode, raw_key) */ - refcount_inc(&dk->dk_refcount); - spin_unlock(&fscrypt_direct_keys_lock); - free_direct_key(to_insert); - return dk; - } - if (to_insert) - hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key); - spin_unlock(&fscrypt_direct_keys_lock); - return to_insert; -} - -/* Prepare to encrypt directly using the master key in the given mode */ -static struct fscrypt_direct_key * -fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) -{ - struct fscrypt_direct_key *dk; - int err; - - /* Is there already a tfm for this key? */ - dk = find_or_insert_direct_key(NULL, raw_key, ci); - if (dk) - return dk; - - /* Nope, allocate one. */ - dk = kzalloc(sizeof(*dk), GFP_NOFS); - if (!dk) - return ERR_PTR(-ENOMEM); - refcount_set(&dk->dk_refcount, 1); - dk->dk_mode = ci->ci_mode; - dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, - ci->ci_inode); - if (IS_ERR(dk->dk_ctfm)) { - err = PTR_ERR(dk->dk_ctfm); - dk->dk_ctfm = NULL; - goto err_free_dk; - } - memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); - - return find_or_insert_direct_key(dk, raw_key, ci); - -err_free_dk: - free_direct_key(dk); - return ERR_PTR(err); -} - static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) { struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); @@ -409,8 +187,7 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, } /* Given the per-file key, set up the file's crypto transform object(s) */ -static int fscrypt_set_derived_key(struct fscrypt_info *ci, - const u8 *derived_key) +int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) { struct fscrypt_mode *mode = ci->ci_mode; struct crypto_skcipher *ctfm; @@ -434,97 +211,6 @@ static int fscrypt_set_derived_key(struct fscrypt_info *ci, return 0; } -/* v1 policy, DIRECT_KEY: use the master key directly */ -static int setup_v1_file_key_direct(struct fscrypt_info *ci, - const u8 *raw_master_key) -{ - const struct fscrypt_mode *mode = ci->ci_mode; - struct fscrypt_direct_key *dk; - - if (!fscrypt_mode_supports_direct_key(mode)) { - fscrypt_warn(ci->ci_inode, - "Direct key mode not allowed with %s", - mode->friendly_name); - return -EINVAL; - } - - if (ci->ci_data_mode != ci->ci_filename_mode) { - fscrypt_warn(ci->ci_inode, - "Direct key mode not allowed with different contents and filenames modes"); - return -EINVAL; - } - - /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ - if (WARN_ON(mode->needs_essiv)) - return -EINVAL; - - dk = fscrypt_get_direct_key(ci, raw_master_key); - if (IS_ERR(dk)) - return PTR_ERR(dk); - ci->ci_direct_key = dk; - ci->ci_ctfm = dk->dk_ctfm; - return 0; -} - -/* v1 policy, !DIRECT_KEY: derive the file's encryption key */ -static int setup_v1_file_key_derived(struct fscrypt_info *ci, - const u8 *raw_master_key) -{ - u8 *derived_key; - int err; - - /* - * This cannot be a stack buffer because it will be passed to the - * scatterlist crypto API during derive_key_aes(). - */ - derived_key = kmalloc(ci->ci_mode->keysize, GFP_NOFS); - if (!derived_key) - return -ENOMEM; - - err = derive_key_aes(raw_master_key, ci->ci_nonce, - derived_key, ci->ci_mode->keysize); - if (err) - goto out; - - err = fscrypt_set_derived_key(ci, derived_key); -out: - kzfree(derived_key); - return err; -} - -static int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, - const u8 *raw_master_key) -{ - if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) - return setup_v1_file_key_direct(ci, raw_master_key); - else - return setup_v1_file_key_derived(ci, raw_master_key); -} - -static int fscrypt_setup_v1_file_key_via_subscribed_keyrings( - struct fscrypt_info *ci) -{ - struct key *key; - const struct fscrypt_key *payload; - int err; - - key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, - ci->ci_master_key_descriptor, - ci->ci_mode->keysize, &payload); - if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) { - key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix, - ci->ci_master_key_descriptor, - ci->ci_mode->keysize, &payload); - } - if (IS_ERR(key)) - return PTR_ERR(key); - - err = fscrypt_setup_v1_file_key(ci, payload->raw); - up_read(&key->sem); - key_put(key); - return err; -} - /* * Find the master key, then set up the inode's actual encryption key. */ @@ -539,7 +225,7 @@ static void put_crypt_info(struct fscrypt_info *ci) return; if (ci->ci_direct_key) { - put_direct_key(ci->ci_direct_key); + fscrypt_put_direct_key(ci->ci_direct_key); } else { crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c new file mode 100644 index 000000000000..631690bb6ed5 --- /dev/null +++ b/fs/crypto/keysetup_v1.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Key setup for v1 encryption policies + * + * Copyright 2015, 2019 Google LLC + */ + +/* + * This file implements compatibility functions for the original encryption + * policy version ("v1"), including: + * + * - Deriving per-file keys using the AES-128-ECB based KDF + * (rather than the new method of using HKDF-SHA512) + * + * - Retrieving fscrypt master keys from process-subscribed keyrings + * (rather than the new method of using a filesystem-level keyring) + * + * - Handling policies with the DIRECT_KEY flag set using a master key table + * (rather than the new method of implementing DIRECT_KEY with per-mode keys + * managed alongside the master keys in the filesystem-level keyring) + */ + +#include +#include +#include +#include +#include + +#include "fscrypt_private.h" + +/* Table of keys referenced by DIRECT_KEY policies */ +static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ +static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); + +/* + * v1 key derivation function. This generates the derived key by encrypting the + * master key with AES-128-ECB using the nonce as the AES key. This provides a + * unique derived key with sufficient entropy for each inode. However, it's + * nonstandard, non-extensible, doesn't evenly distribute the entropy from the + * master key, and is trivially reversible: an attacker who compromises a + * derived key can "decrypt" it to get back to the master key, then derive any + * other key. For all new code, use HKDF instead. + * + * The master key must be at least as long as the derived key. If the master + * key is longer, then only the first 'derived_keysize' bytes are used. + */ +static int derive_key_aes(const u8 *master_key, + const u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE], + u8 *derived_key, unsigned int derived_keysize) +{ + int res = 0; + struct skcipher_request *req = NULL; + DECLARE_CRYPTO_WAIT(wait); + struct scatterlist src_sg, dst_sg; + struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); + + if (IS_ERR(tfm)) { + res = PTR_ERR(tfm); + tfm = NULL; + goto out; + } + crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); + req = skcipher_request_alloc(tfm, GFP_NOFS); + if (!req) { + res = -ENOMEM; + goto out; + } + skcipher_request_set_callback(req, + CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + res = crypto_skcipher_setkey(tfm, nonce, FS_KEY_DERIVATION_NONCE_SIZE); + if (res < 0) + goto out; + + sg_init_one(&src_sg, master_key, derived_keysize); + sg_init_one(&dst_sg, derived_key, derived_keysize); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, + NULL); + res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); +out: + skcipher_request_free(req); + crypto_free_skcipher(tfm); + return res; +} + +/* + * Search the current task's subscribed keyrings for a "logon" key with + * description prefix:descriptor, and if found acquire a read lock on it and + * return a pointer to its validated payload in *payload_ret. + */ +static struct key * +find_and_lock_process_key(const char *prefix, + const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], + unsigned int min_keysize, + const struct fscrypt_key **payload_ret) +{ + char *description; + struct key *key; + const struct user_key_payload *ukp; + const struct fscrypt_key *payload; + + description = kasprintf(GFP_NOFS, "%s%*phN", prefix, + FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); + if (!description) + return ERR_PTR(-ENOMEM); + + key = request_key(&key_type_logon, description, NULL); + kfree(description); + if (IS_ERR(key)) + return key; + + down_read(&key->sem); + ukp = user_key_payload_locked(key); + + if (!ukp) /* was the key revoked before we acquired its semaphore? */ + goto invalid; + + payload = (const struct fscrypt_key *)ukp->data; + + if (ukp->datalen != sizeof(struct fscrypt_key) || + payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { + fscrypt_warn(NULL, + "key with description '%s' has invalid payload", + key->description); + goto invalid; + } + + if (payload->size < min_keysize) { + fscrypt_warn(NULL, + "key with description '%s' is too short (got %u bytes, need %u+ bytes)", + key->description, payload->size, min_keysize); + goto invalid; + } + + *payload_ret = payload; + return key; + +invalid: + up_read(&key->sem); + key_put(key); + return ERR_PTR(-ENOKEY); +} + +/* Master key referenced by DIRECT_KEY policy */ +struct fscrypt_direct_key { + struct hlist_node dk_node; + refcount_t dk_refcount; + const struct fscrypt_mode *dk_mode; + struct crypto_skcipher *dk_ctfm; + u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; +}; + +static void free_direct_key(struct fscrypt_direct_key *dk) +{ + if (dk) { + crypto_free_skcipher(dk->dk_ctfm); + kzfree(dk); + } +} + +void fscrypt_put_direct_key(struct fscrypt_direct_key *dk) +{ + if (!refcount_dec_and_lock(&dk->dk_refcount, &fscrypt_direct_keys_lock)) + return; + hash_del(&dk->dk_node); + spin_unlock(&fscrypt_direct_keys_lock); + + free_direct_key(dk); +} + +/* + * Find/insert the given key into the fscrypt_direct_keys table. If found, it + * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If + * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise + * NULL is returned. + */ +static struct fscrypt_direct_key * +find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, + const u8 *raw_key, const struct fscrypt_info *ci) +{ + unsigned long hash_key; + struct fscrypt_direct_key *dk; + + /* + * Careful: to avoid potentially leaking secret key bytes via timing + * information, we must key the hash table by descriptor rather than by + * raw key, and use crypto_memneq() when comparing raw keys. + */ + + BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); + memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); + + spin_lock(&fscrypt_direct_keys_lock); + hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { + if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) + continue; + if (ci->ci_mode != dk->dk_mode) + continue; + if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) + continue; + /* using existing tfm with same (descriptor, mode, raw_key) */ + refcount_inc(&dk->dk_refcount); + spin_unlock(&fscrypt_direct_keys_lock); + free_direct_key(to_insert); + return dk; + } + if (to_insert) + hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key); + spin_unlock(&fscrypt_direct_keys_lock); + return to_insert; +} + +/* Prepare to encrypt directly using the master key in the given mode */ +static struct fscrypt_direct_key * +fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) +{ + struct fscrypt_direct_key *dk; + int err; + + /* Is there already a tfm for this key? */ + dk = find_or_insert_direct_key(NULL, raw_key, ci); + if (dk) + return dk; + + /* Nope, allocate one. */ + dk = kzalloc(sizeof(*dk), GFP_NOFS); + if (!dk) + return ERR_PTR(-ENOMEM); + refcount_set(&dk->dk_refcount, 1); + dk->dk_mode = ci->ci_mode; + dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, + ci->ci_inode); + if (IS_ERR(dk->dk_ctfm)) { + err = PTR_ERR(dk->dk_ctfm); + dk->dk_ctfm = NULL; + goto err_free_dk; + } + memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); + memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); + + return find_or_insert_direct_key(dk, raw_key, ci); + +err_free_dk: + free_direct_key(dk); + return ERR_PTR(err); +} + +/* v1 policy, DIRECT_KEY: use the master key directly */ +static int setup_v1_file_key_direct(struct fscrypt_info *ci, + const u8 *raw_master_key) +{ + const struct fscrypt_mode *mode = ci->ci_mode; + struct fscrypt_direct_key *dk; + + if (!fscrypt_mode_supports_direct_key(mode)) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with %s", + mode->friendly_name); + return -EINVAL; + } + + if (ci->ci_data_mode != ci->ci_filename_mode) { + fscrypt_warn(ci->ci_inode, + "Direct key mode not allowed with different contents and filenames modes"); + return -EINVAL; + } + + /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ + if (WARN_ON(mode->needs_essiv)) + return -EINVAL; + + dk = fscrypt_get_direct_key(ci, raw_master_key); + if (IS_ERR(dk)) + return PTR_ERR(dk); + ci->ci_direct_key = dk; + ci->ci_ctfm = dk->dk_ctfm; + return 0; +} + +/* v1 policy, !DIRECT_KEY: derive the file's encryption key */ +static int setup_v1_file_key_derived(struct fscrypt_info *ci, + const u8 *raw_master_key) +{ + u8 *derived_key; + int err; + + /* + * This cannot be a stack buffer because it will be passed to the + * scatterlist crypto API during derive_key_aes(). + */ + derived_key = kmalloc(ci->ci_mode->keysize, GFP_NOFS); + if (!derived_key) + return -ENOMEM; + + err = derive_key_aes(raw_master_key, ci->ci_nonce, + derived_key, ci->ci_mode->keysize); + if (err) + goto out; + + err = fscrypt_set_derived_key(ci, derived_key); +out: + kzfree(derived_key); + return err; +} + +int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, const u8 *raw_master_key) +{ + if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) + return setup_v1_file_key_direct(ci, raw_master_key); + else + return setup_v1_file_key_derived(ci, raw_master_key); +} + +int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci) +{ + struct key *key; + const struct fscrypt_key *payload; + int err; + + key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, + ci->ci_master_key_descriptor, + ci->ci_mode->keysize, &payload); + if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) { + key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix, + ci->ci_master_key_descriptor, + ci->ci_mode->keysize, &payload); + } + if (IS_ERR(key)) + return PTR_ERR(key); + + err = fscrypt_setup_v1_file_key(ci, payload->raw); + up_read(&key->sem); + key_put(key); + return err; +} -- GitLab From feed825861919ac3fac4b2ab83673dd5225f7f0d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:45 -0700 Subject: [PATCH 2749/7155] fscrypt: rename keyinfo.c to keysetup.c Rename keyinfo.c to keysetup.c since this better describes what the file does (sets up the key), and it matches the new file keysetup_v1.c. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/Makefile | 2 +- fs/crypto/fscrypt_private.h | 2 +- fs/crypto/{keyinfo.c => keysetup.c} | 0 include/linux/fscrypt.h | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename fs/crypto/{keyinfo.c => keysetup.c} (100%) diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 1fba255c34ca..ad14d4c29784 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o fscrypto-y := crypto.o \ fname.o \ hooks.o \ - keyinfo.o \ + keysetup.o \ keysetup_v1.o \ policy.o diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 387b44b255f6..794dcba25ca8 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -156,7 +156,7 @@ extern bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret); -/* keyinfo.c */ +/* keysetup.c */ struct fscrypt_mode { const char *friendly_name; diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keysetup.c similarity index 100% rename from fs/crypto/keyinfo.c rename to fs/crypto/keysetup.c diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 81c0c754f8b2..583802cb2e35 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -138,7 +138,7 @@ extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); -/* keyinfo.c */ +/* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *); extern void fscrypt_free_inode(struct inode *); @@ -367,7 +367,7 @@ static inline int fscrypt_inherit_context(struct inode *parent, return -EOPNOTSUPP; } -/* keyinfo.c */ +/* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { return -EOPNOTSUPP; -- GitLab From 22d94f493bfb408fdd764f7b1d0363af2122fba5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:46 -0700 Subject: [PATCH 2750/7155] fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl Add a new fscrypt ioctl, FS_IOC_ADD_ENCRYPTION_KEY. This ioctl adds an encryption key to the filesystem's fscrypt keyring ->s_master_keys, making any files encrypted with that key appear "unlocked". Why we need this ~~~~~~~~~~~~~~~~ The main problem is that the "locked/unlocked" (ciphertext/plaintext) status of encrypted files is global, but the fscrypt keys are not. fscrypt only looks for keys in the keyring(s) the process accessing the filesystem is subscribed to: the thread keyring, process keyring, and session keyring, where the session keyring may contain the user keyring. Therefore, userspace has to put fscrypt keys in the keyrings for individual users or sessions. But this means that when a process with a different keyring tries to access encrypted files, whether they appear "unlocked" or not is nondeterministic. This is because it depends on whether the files are currently present in the inode cache. Fixing this by consistently providing each process its own view of the filesystem depending on whether it has the key or not isn't feasible due to how the VFS caches work. Furthermore, while sometimes users expect this behavior, it is misguided for two reasons. First, it would be an OS-level access control mechanism largely redundant with existing access control mechanisms such as UNIX file permissions, ACLs, LSMs, etc. Encryption is actually for protecting the data at rest. Second, almost all users of fscrypt actually do need the keys to be global. The largest users of fscrypt, Android and Chromium OS, achieve this by having PID 1 create a "session keyring" that is inherited by every process. This works, but it isn't scalable because it prevents session keyrings from being used for any other purpose. On general-purpose Linux distros, the 'fscrypt' userspace tool [1] can't similarly abuse the session keyring, so to make 'sudo' work on all systems it has to link all the user keyrings into root's user keyring [2]. This is ugly and raises security concerns. Moreover it can't make the keys available to system services, such as sshd trying to access the user's '~/.ssh' directory (see [3], [4]) or NetworkManager trying to read certificates from the user's home directory (see [5]); or to Docker containers (see [6], [7]). By having an API to add a key to the *filesystem* we'll be able to fix the above bugs, remove userspace workarounds, and clearly express the intended semantics: the locked/unlocked status of an encrypted directory is global, and encryption is orthogonal to OS-level access control. Why not use the add_key() syscall ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We use an ioctl for this API rather than the existing add_key() system call because the ioctl gives us the flexibility needed to implement fscrypt-specific semantics that will be introduced in later patches: - Supporting key removal with the semantics such that the secret is removed immediately and any unused inodes using the key are evicted; also, the eviction of any in-use inodes can be retried. - Calculating a key-dependent cryptographic identifier and returning it to userspace. - Allowing keys to be added and removed by non-root users, but only keys for v2 encryption policies; and to prevent denial-of-service attacks, users can only remove keys they themselves have added, and a key is only really removed after all users who added it have removed it. Trying to shoehorn these semantics into the keyrings syscalls would be very difficult, whereas the ioctls make things much easier. However, to reuse code the implementation still uses the keyrings service internally. Thus we get lockless RCU-mode key lookups without having to re-implement it, and the keys automatically show up in /proc/keys for debugging purposes. References: [1] https://github.com/google/fscrypt [2] https://goo.gl/55cCrI#heading=h.vf09isp98isb [3] https://github.com/google/fscrypt/issues/111#issuecomment-444347939 [4] https://github.com/google/fscrypt/issues/116 [5] https://bugs.launchpad.net/ubuntu/+source/fscrypt/+bug/1770715 [6] https://github.com/google/fscrypt/issues/128 [7] https://askubuntu.com/questions/1130306/cannot-run-docker-on-an-encrypted-filesystem Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/Makefile | 1 + fs/crypto/crypto.c | 10 +- fs/crypto/fscrypt_private.h | 62 +++++++- fs/crypto/keyring.c | 286 +++++++++++++++++++++++++++++++++++ fs/crypto/keysetup.c | 35 ++++- fs/super.c | 2 + include/linux/fs.h | 1 + include/linux/fscrypt.h | 14 ++ include/uapi/linux/fscrypt.h | 49 ++++-- 9 files changed, 447 insertions(+), 13 deletions(-) create mode 100644 fs/crypto/keyring.c diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index ad14d4c29784..6b2485b41393 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o fscrypto-y := crypto.o \ fname.o \ hooks.o \ + keyring.o \ keysetup.o \ keysetup_v1.o \ policy.o diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 7502c1f0ede9..65ca077e8d58 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -478,6 +478,8 @@ void fscrypt_msg(const struct inode *inode, const char *level, */ static int __init fscrypt_init(void) { + int err = -ENOMEM; + /* * Use an unbound workqueue to allow bios to be decrypted in parallel * even when they happen to complete on the same CPU. This sacrifices @@ -500,13 +502,19 @@ static int __init fscrypt_init(void) if (!fscrypt_info_cachep) goto fail_free_ctx; + err = fscrypt_init_keyring(); + if (err) + goto fail_free_info; + return 0; +fail_free_info: + kmem_cache_destroy(fscrypt_info_cachep); fail_free_ctx: kmem_cache_destroy(fscrypt_ctx_cachep); fail_free_queue: destroy_workqueue(fscrypt_read_workqueue); fail: - return -ENOMEM; + return err; } late_initcall(fscrypt_init) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 794dcba25ca8..0d9ebfd3bf3a 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -14,9 +14,12 @@ #include #include -/* Encryption parameters */ +#define CONST_STRLEN(str) (sizeof(str) - 1) + #define FS_KEY_DERIVATION_NONCE_SIZE 16 +#define FSCRYPT_MIN_KEY_SIZE 16 + /** * Encryption context for inode * @@ -156,6 +159,63 @@ extern bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret); +/* keyring.c */ + +/* + * fscrypt_master_key_secret - secret key material of an in-use master key + */ +struct fscrypt_master_key_secret { + + /* Size of the raw key in bytes */ + u32 size; + + /* The raw key */ + u8 raw[FSCRYPT_MAX_KEY_SIZE]; + +} __randomize_layout; + +/* + * fscrypt_master_key - an in-use master key + * + * This represents a master encryption key which has been added to the + * filesystem and can be used to "unlock" the encrypted files which were + * encrypted with it. + */ +struct fscrypt_master_key { + + /* The secret key material */ + struct fscrypt_master_key_secret mk_secret; + + /* Arbitrary key descriptor which was assigned by userspace */ + struct fscrypt_key_specifier mk_spec; + +} __randomize_layout; + +static inline const char *master_key_spec_type( + const struct fscrypt_key_specifier *spec) +{ + switch (spec->type) { + case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: + return "descriptor"; + } + return "[unknown]"; +} + +static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) +{ + switch (spec->type) { + case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: + return FSCRYPT_KEY_DESCRIPTOR_SIZE; + } + return 0; +} + +extern struct key * +fscrypt_find_master_key(struct super_block *sb, + const struct fscrypt_key_specifier *mk_spec); + +extern int __init fscrypt_init_keyring(void); + /* keysetup.c */ struct fscrypt_mode { diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c new file mode 100644 index 000000000000..bcd7d2836e1e --- /dev/null +++ b/fs/crypto/keyring.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Filesystem-level keyring for fscrypt + * + * Copyright 2019 Google LLC + */ + +/* + * This file implements management of fscrypt master keys in the + * filesystem-level keyring, including the ioctls: + * + * - FS_IOC_ADD_ENCRYPTION_KEY + * + * See the "User API" section of Documentation/filesystems/fscrypt.rst for more + * information about these ioctls. + */ + +#include +#include + +#include "fscrypt_private.h" + +static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) +{ + memzero_explicit(secret, sizeof(*secret)); +} + +static void move_master_key_secret(struct fscrypt_master_key_secret *dst, + struct fscrypt_master_key_secret *src) +{ + memcpy(dst, src, sizeof(*dst)); + memzero_explicit(src, sizeof(*src)); +} + +static void free_master_key(struct fscrypt_master_key *mk) +{ + wipe_master_key_secret(&mk->mk_secret); + kzfree(mk); +} + +static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec) +{ + if (spec->__reserved) + return false; + return master_key_spec_len(spec) != 0; +} + +static int fscrypt_key_instantiate(struct key *key, + struct key_preparsed_payload *prep) +{ + key->payload.data[0] = (struct fscrypt_master_key *)prep->data; + return 0; +} + +static void fscrypt_key_destroy(struct key *key) +{ + free_master_key(key->payload.data[0]); +} + +static void fscrypt_key_describe(const struct key *key, struct seq_file *m) +{ + seq_puts(m, key->description); +} + +/* + * Type of key in ->s_master_keys. Each key of this type represents a master + * key which has been added to the filesystem. Its payload is a + * 'struct fscrypt_master_key'. The "." prefix in the key type name prevents + * users from adding keys of this type via the keyrings syscalls rather than via + * the intended method of FS_IOC_ADD_ENCRYPTION_KEY. + */ +static struct key_type key_type_fscrypt = { + .name = "._fscrypt", + .instantiate = fscrypt_key_instantiate, + .destroy = fscrypt_key_destroy, + .describe = fscrypt_key_describe, +}; + +/* Search ->s_master_keys */ +static struct key *search_fscrypt_keyring(struct key *keyring, + struct key_type *type, + const char *description) +{ + /* + * We need to mark the keyring reference as "possessed" so that we + * acquire permission to search it, via the KEY_POS_SEARCH permission. + */ + key_ref_t keyref = make_key_ref(keyring, true /* possessed */); + + keyref = keyring_search(keyref, type, description, false); + if (IS_ERR(keyref)) { + if (PTR_ERR(keyref) == -EAGAIN || /* not found */ + PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */ + keyref = ERR_PTR(-ENOKEY); + return ERR_CAST(keyref); + } + return key_ref_to_ptr(keyref); +} + +#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \ + (CONST_STRLEN("fscrypt-") + FIELD_SIZEOF(struct super_block, s_id)) + +#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1) + +static void format_fs_keyring_description( + char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], + const struct super_block *sb) +{ + sprintf(description, "fscrypt-%s", sb->s_id); +} + +static void format_mk_description( + char description[FSCRYPT_MK_DESCRIPTION_SIZE], + const struct fscrypt_key_specifier *mk_spec) +{ + sprintf(description, "%*phN", + master_key_spec_len(mk_spec), (u8 *)&mk_spec->u); +} + +/* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */ +static int allocate_filesystem_keyring(struct super_block *sb) +{ + char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE]; + struct key *keyring; + + if (sb->s_master_keys) + return 0; + + format_fs_keyring_description(description, sb); + keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), KEY_POS_SEARCH | + KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + + /* Pairs with READ_ONCE() in fscrypt_find_master_key() */ + smp_store_release(&sb->s_master_keys, keyring); + return 0; +} + +void fscrypt_sb_free(struct super_block *sb) +{ + key_put(sb->s_master_keys); + sb->s_master_keys = NULL; +} + +/* + * Find the specified master key in ->s_master_keys. + * Returns ERR_PTR(-ENOKEY) if not found. + */ +struct key *fscrypt_find_master_key(struct super_block *sb, + const struct fscrypt_key_specifier *mk_spec) +{ + struct key *keyring; + char description[FSCRYPT_MK_DESCRIPTION_SIZE]; + + /* pairs with smp_store_release() in allocate_filesystem_keyring() */ + keyring = READ_ONCE(sb->s_master_keys); + if (keyring == NULL) + return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */ + + format_mk_description(description, mk_spec); + return search_fscrypt_keyring(keyring, &key_type_fscrypt, description); +} + +/* + * Allocate a new fscrypt_master_key which contains the given secret, set it as + * the payload of a new 'struct key' of type fscrypt, and link the 'struct key' + * into the given keyring. Synchronized by fscrypt_add_key_mutex. + */ +static int add_new_master_key(struct fscrypt_master_key_secret *secret, + const struct fscrypt_key_specifier *mk_spec, + struct key *keyring) +{ + struct fscrypt_master_key *mk; + char description[FSCRYPT_MK_DESCRIPTION_SIZE]; + struct key *key; + int err; + + mk = kzalloc(sizeof(*mk), GFP_KERNEL); + if (!mk) + return -ENOMEM; + + mk->mk_spec = *mk_spec; + + move_master_key_secret(&mk->mk_secret, secret); + + format_mk_description(description, mk_spec); + key = key_alloc(&key_type_fscrypt, description, + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), + KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto out_free_mk; + } + err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL); + key_put(key); + if (err) + goto out_free_mk; + + return 0; + +out_free_mk: + free_master_key(mk); + return err; +} + +static int add_master_key(struct super_block *sb, + struct fscrypt_master_key_secret *secret, + const struct fscrypt_key_specifier *mk_spec) +{ + static DEFINE_MUTEX(fscrypt_add_key_mutex); + struct key *key; + int err; + + mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ + key = fscrypt_find_master_key(sb, mk_spec); + if (IS_ERR(key)) { + err = PTR_ERR(key); + if (err != -ENOKEY) + goto out_unlock; + /* Didn't find the key in ->s_master_keys. Add it. */ + err = allocate_filesystem_keyring(sb); + if (err) + goto out_unlock; + err = add_new_master_key(secret, mk_spec, sb->s_master_keys); + } else { + key_put(key); + err = 0; + } +out_unlock: + mutex_unlock(&fscrypt_add_key_mutex); + return err; +} + +/* + * Add a master encryption key to the filesystem, causing all files which were + * encrypted with it to appear "unlocked" (decrypted) when accessed. + * + * For more details, see the "FS_IOC_ADD_ENCRYPTION_KEY" section of + * Documentation/filesystems/fscrypt.rst. + */ +int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_add_key_arg __user *uarg = _uarg; + struct fscrypt_add_key_arg arg; + struct fscrypt_master_key_secret secret; + int err; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || + arg.raw_size > FSCRYPT_MAX_KEY_SIZE) + return -EINVAL; + + if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) + return -EINVAL; + + memset(&secret, 0, sizeof(secret)); + secret.size = arg.raw_size; + err = -EFAULT; + if (copy_from_user(secret.raw, uarg->raw, secret.size)) + goto out_wipe_secret; + + err = -EACCES; + if (!capable(CAP_SYS_ADMIN)) + goto out_wipe_secret; + + err = add_master_key(sb, &secret, &arg.key_spec); +out_wipe_secret: + wipe_master_key_secret(&secret); + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); + +int __init fscrypt_init_keyring(void) +{ + return register_key_type(&key_type_fscrypt); +} diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index f4a47448e9ef..1c6d18bcdc7b 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -216,7 +216,40 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) */ static int setup_file_encryption_key(struct fscrypt_info *ci) { - return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); + struct key *key; + struct fscrypt_master_key *mk = NULL; + struct fscrypt_key_specifier mk_spec; + int err; + + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; + memcpy(mk_spec.u.descriptor, ci->ci_master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); + + key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); + if (IS_ERR(key)) { + if (key != ERR_PTR(-ENOKEY)) + return PTR_ERR(key); + + return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); + } + + mk = key->payload.data[0]; + + if (mk->mk_secret.size < ci->ci_mode->keysize) { + fscrypt_warn(NULL, + "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", + master_key_spec_type(&mk_spec), + master_key_spec_len(&mk_spec), (u8 *)&mk_spec.u, + mk->mk_secret.size, ci->ci_mode->keysize); + err = -ENOKEY; + goto out_release_key; + } + + err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); + +out_release_key: + key_put(key); + return err; } static void put_crypt_info(struct fscrypt_info *ci) diff --git a/fs/super.c b/fs/super.c index 5960578a4076..e486a442a61f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -290,6 +291,7 @@ static void __put_super(struct super_block *s) WARN_ON(s->s_inode_lru.node); WARN_ON(!list_empty(&s->s_mounts)); security_sb_free(s); + fscrypt_sb_free(s); put_user_ns(s->s_user_ns); kfree(s->s_subtype); call_rcu(&s->rcu, destroy_super_rcu); diff --git a/include/linux/fs.h b/include/linux/fs.h index 997a530ff4e9..5dff77326cec 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1427,6 +1427,7 @@ struct super_block { const struct xattr_handler **s_xattr; #ifdef CONFIG_FS_ENCRYPTION const struct fscrypt_operations *s_cop; + struct key *s_master_keys; /* master crypto keys in use */ #endif struct hlist_bl_head s_roots; /* alternate root dentries for NFS */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 583802cb2e35..46bf66cf76ef 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -138,6 +138,10 @@ extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); +/* keyring.c */ +extern void fscrypt_sb_free(struct super_block *sb); +extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); + /* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *); @@ -367,6 +371,16 @@ static inline int fscrypt_inherit_context(struct inode *parent, return -EOPNOTSUPP; } +/* keyring.c */ +static inline void fscrypt_sb_free(struct super_block *sb) +{ +} + +static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + /* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 29a945d165de..6aeca3cb0a2d 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -36,22 +36,51 @@ struct fscrypt_policy { __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; -#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) -#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) -#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) - -/* Parameters for passing an encryption key into the kernel keyring */ +/* + * Process-subscribed "logon" key description prefix and payload format. + * Deprecated; prefer FS_IOC_ADD_ENCRYPTION_KEY instead. + */ #define FSCRYPT_KEY_DESC_PREFIX "fscrypt:" -#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 - -/* Structure that userspace passes to the kernel keyring */ -#define FSCRYPT_MAX_KEY_SIZE 64 - +#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 +#define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { __u32 mode; __u8 raw[FSCRYPT_MAX_KEY_SIZE]; __u32 size; }; + +/* + * Keys are specified by an arbitrary 8-byte key "descriptor", + * matching fscrypt_policy::master_key_descriptor. + */ +#define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 + +/* + * Specifies a key. This doesn't contain the actual key itself; this is just + * the "name" of the key. + */ +struct fscrypt_key_specifier { + __u32 type; /* one of FSCRYPT_KEY_SPEC_TYPE_* */ + __u32 __reserved; + union { + __u8 __reserved[32]; /* reserve some extra space */ + __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + } u; +}; + +/* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */ +struct fscrypt_add_key_arg { + struct fscrypt_key_specifier key_spec; + __u32 raw_size; + __u32 __reserved[9]; + __u8 raw[]; +}; + +#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) +#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) +#define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) + /**********************************************************************/ /* old names; don't add anything new here! */ -- GitLab From b1c0ec3599f42ad372063b0235a3c33f65eb1e30 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:46 -0700 Subject: [PATCH 2751/7155] fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY ioctl Add a new fscrypt ioctl, FS_IOC_REMOVE_ENCRYPTION_KEY. This ioctl removes an encryption key that was added by FS_IOC_ADD_ENCRYPTION_KEY. It wipes the secret key itself, then "locks" the encrypted files and directories that had been unlocked using that key -- implemented by evicting the relevant dentries and inodes from the VFS caches. The problem this solves is that many fscrypt users want the ability to remove encryption keys, causing the corresponding encrypted directories to appear "locked" (presented in ciphertext form) again. Moreover, users want removing an encryption key to *really* remove it, in the sense that the removed keys cannot be recovered even if kernel memory is compromised, e.g. by the exploit of a kernel security vulnerability or by a physical attack. This is desirable after a user logs out of the system, for example. In many cases users even already assume this to be the case and are surprised to hear when it's not. It is not sufficient to simply unlink the master key from the keyring (or to revoke or invalidate it), since the actual encryption transform objects are still pinned in memory by their inodes. Therefore, to really remove a key we must also evict the relevant inodes. Currently one workaround is to run 'sync && echo 2 > /proc/sys/vm/drop_caches'. But, that evicts all unused inodes in the system rather than just the inodes associated with the key being removed, causing severe performance problems. Moreover, it requires root privileges, so regular users can't "lock" their encrypted files. Another workaround, used in Chromium OS kernels, is to add a new VFS-level ioctl FS_IOC_DROP_CACHE which is a more restricted version of drop_caches that operates on a single super_block. It does: shrink_dcache_sb(sb); invalidate_inodes(sb, false); But it's still a hack. Yet, the major users of filesystem encryption want this feature badly enough that they are actually using these hacks. To properly solve the problem, start maintaining a list of the inodes which have been "unlocked" using each master key. Originally this wasn't possible because the kernel didn't keep track of in-use master keys at all. But, with the ->s_master_keys keyring it is now possible. Then, add an ioctl FS_IOC_REMOVE_ENCRYPTION_KEY. It finds the specified master key in ->s_master_keys, then wipes the secret key itself, which prevents any additional inodes from being unlocked with the key. Then, it syncs the filesystem and evicts the inodes in the key's list. The normal inode eviction code will free and wipe the per-file keys (in ->i_crypt_info). Note that freeing ->i_crypt_info without evicting the inodes was also considered, but would have been racy. Some inodes may still be in use when a master key is removed, and we can't simply revoke random file descriptors, mmap's, etc. Thus, the ioctl simply skips in-use inodes, and returns -EBUSY to indicate that some inodes weren't evicted. The master key *secret* is still removed, but the fscrypt_master_key struct remains to keep track of the remaining inodes. Userspace can then retry the ioctl to evict the remaining inodes. Alternatively, if userspace adds the key again, the refreshed secret will be associated with the existing list of inodes so they remain correctly tracked for future key removals. The ioctl doesn't wipe pagecache pages. Thus, we tolerate that after a kernel compromise some portions of plaintext file contents may still be recoverable from memory. This can be solved by enabling page poisoning system-wide, which security conscious users may choose to do. But it's very difficult to solve otherwise, e.g. note that plaintext file contents may have been read in other places than pagecache pages. Like FS_IOC_ADD_ENCRYPTION_KEY, FS_IOC_REMOVE_ENCRYPTION_KEY is initially restricted to privileged users only. This is sufficient for some use cases, but not all. A later patch will relax this restriction, but it will require introducing key hashes, among other changes. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 53 ++++++- fs/crypto/keyring.c | 260 ++++++++++++++++++++++++++++++++++- fs/crypto/keysetup.c | 103 +++++++++++++- include/linux/fscrypt.h | 12 ++ include/uapi/linux/fscrypt.h | 9 ++ 5 files changed, 432 insertions(+), 5 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 0d9ebfd3bf3a..fc804f4a03fc 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -78,6 +78,19 @@ struct fscrypt_info { /* Back-pointer to the inode */ struct inode *ci_inode; + /* + * The master key with which this inode was unlocked (decrypted). This + * will be NULL if the master key was found in a process-subscribed + * keyring rather than in the filesystem-level keyring. + */ + struct key *ci_master_key; + + /* + * Link in list of inodes that were unlocked with the master key. + * Only used when ->ci_master_key is set. + */ + struct list_head ci_master_key_link; + /* * If non-NULL, then encryption is done using the master key directly * and ci_ctfm will equal ci_direct_key->dk_ctfm. @@ -183,14 +196,52 @@ struct fscrypt_master_key_secret { */ struct fscrypt_master_key { - /* The secret key material */ + /* + * The secret key material. After FS_IOC_REMOVE_ENCRYPTION_KEY is + * executed, this is wiped and no new inodes can be unlocked with this + * key; however, there may still be inodes in ->mk_decrypted_inodes + * which could not be evicted. As long as some inodes still remain, + * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or + * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again. + * + * Locking: protected by key->sem. + */ struct fscrypt_master_key_secret mk_secret; /* Arbitrary key descriptor which was assigned by userspace */ struct fscrypt_key_specifier mk_spec; + /* + * Length of ->mk_decrypted_inodes, plus one if mk_secret is present. + * Once this goes to 0, the master key is removed from ->s_master_keys. + * The 'struct fscrypt_master_key' will continue to live as long as the + * 'struct key' whose payload it is, but we won't let this reference + * count rise again. + */ + refcount_t mk_refcount; + + /* + * List of inodes that were unlocked using this key. This allows the + * inodes to be evicted efficiently if the key is removed. + */ + struct list_head mk_decrypted_inodes; + spinlock_t mk_decrypted_inodes_lock; + } __randomize_layout; +static inline bool +is_master_key_secret_present(const struct fscrypt_master_key_secret *secret) +{ + /* + * The READ_ONCE() is only necessary for fscrypt_drop_inode() and + * fscrypt_key_describe(). These run in atomic context, so they can't + * take key->sem and thus 'secret' can change concurrently which would + * be a data race. But they only need to know whether the secret *was* + * present at the time of check, so READ_ONCE() suffices. + */ + return READ_ONCE(secret->size) != 0; +} + static inline const char *master_key_spec_type( const struct fscrypt_key_specifier *spec) { diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index bcd7d2836e1e..c3423f0edc70 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -10,6 +10,7 @@ * filesystem-level keyring, including the ioctls: * * - FS_IOC_ADD_ENCRYPTION_KEY + * - FS_IOC_REMOVE_ENCRYPTION_KEY * * See the "User API" section of Documentation/filesystems/fscrypt.rst for more * information about these ioctls. @@ -60,6 +61,13 @@ static void fscrypt_key_destroy(struct key *key) static void fscrypt_key_describe(const struct key *key, struct seq_file *m) { seq_puts(m, key->description); + + if (key_is_positive(key)) { + const struct fscrypt_master_key *mk = key->payload.data[0]; + + if (!is_master_key_secret_present(&mk->mk_secret)) + seq_puts(m, ": secret removed"); + } } /* @@ -186,6 +194,10 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret, move_master_key_secret(&mk->mk_secret, secret); + refcount_set(&mk->mk_refcount, 1); /* secret is present */ + INIT_LIST_HEAD(&mk->mk_decrypted_inodes); + spin_lock_init(&mk->mk_decrypted_inodes_lock); + format_mk_description(description, mk_spec); key = key_alloc(&key_type_fscrypt, description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), @@ -207,6 +219,21 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret, return err; } +#define KEY_DEAD 1 + +static int add_existing_master_key(struct fscrypt_master_key *mk, + struct fscrypt_master_key_secret *secret) +{ + if (is_master_key_secret_present(&mk->mk_secret)) + return 0; + + if (!refcount_inc_not_zero(&mk->mk_refcount)) + return KEY_DEAD; + + move_master_key_secret(&mk->mk_secret, secret); + return 0; +} + static int add_master_key(struct super_block *sb, struct fscrypt_master_key_secret *secret, const struct fscrypt_key_specifier *mk_spec) @@ -216,6 +243,7 @@ static int add_master_key(struct super_block *sb, int err; mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ +retry: key = fscrypt_find_master_key(sb, mk_spec); if (IS_ERR(key)) { err = PTR_ERR(key); @@ -227,8 +255,20 @@ static int add_master_key(struct super_block *sb, goto out_unlock; err = add_new_master_key(secret, mk_spec, sb->s_master_keys); } else { + /* + * Found the key in ->s_master_keys. Re-add the secret if + * needed. + */ + down_write(&key->sem); + err = add_existing_master_key(key->payload.data[0], secret); + up_write(&key->sem); + if (err == KEY_DEAD) { + /* Key being removed or needs to be removed */ + key_invalidate(key); + key_put(key); + goto retry; + } key_put(key); - err = 0; } out_unlock: mutex_unlock(&fscrypt_add_key_mutex); @@ -280,6 +320,224 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); +/* + * Try to evict the inode's dentries from the dentry cache. If the inode is a + * directory, then it can have at most one dentry; however, that dentry may be + * pinned by child dentries, so first try to evict the children too. + */ +static void shrink_dcache_inode(struct inode *inode) +{ + struct dentry *dentry; + + if (S_ISDIR(inode->i_mode)) { + dentry = d_find_any_alias(inode); + if (dentry) { + shrink_dcache_parent(dentry); + dput(dentry); + } + } + d_prune_aliases(inode); +} + +static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk) +{ + struct fscrypt_info *ci; + struct inode *inode; + struct inode *toput_inode = NULL; + + spin_lock(&mk->mk_decrypted_inodes_lock); + + list_for_each_entry(ci, &mk->mk_decrypted_inodes, ci_master_key_link) { + inode = ci->ci_inode; + spin_lock(&inode->i_lock); + if (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) { + spin_unlock(&inode->i_lock); + continue; + } + __iget(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&mk->mk_decrypted_inodes_lock); + + shrink_dcache_inode(inode); + iput(toput_inode); + toput_inode = inode; + + spin_lock(&mk->mk_decrypted_inodes_lock); + } + + spin_unlock(&mk->mk_decrypted_inodes_lock); + iput(toput_inode); +} + +static int check_for_busy_inodes(struct super_block *sb, + struct fscrypt_master_key *mk) +{ + struct list_head *pos; + size_t busy_count = 0; + unsigned long ino; + struct dentry *dentry; + char _path[256]; + char *path = NULL; + + spin_lock(&mk->mk_decrypted_inodes_lock); + + list_for_each(pos, &mk->mk_decrypted_inodes) + busy_count++; + + if (busy_count == 0) { + spin_unlock(&mk->mk_decrypted_inodes_lock); + return 0; + } + + { + /* select an example file to show for debugging purposes */ + struct inode *inode = + list_first_entry(&mk->mk_decrypted_inodes, + struct fscrypt_info, + ci_master_key_link)->ci_inode; + ino = inode->i_ino; + dentry = d_find_alias(inode); + } + spin_unlock(&mk->mk_decrypted_inodes_lock); + + if (dentry) { + path = dentry_path(dentry, _path, sizeof(_path)); + dput(dentry); + } + if (IS_ERR_OR_NULL(path)) + path = "(unknown)"; + + fscrypt_warn(NULL, + "%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu (%s)", + sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec), + master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u, + ino, path); + return -EBUSY; +} + +static int try_to_lock_encrypted_files(struct super_block *sb, + struct fscrypt_master_key *mk) +{ + int err1; + int err2; + + /* + * An inode can't be evicted while it is dirty or has dirty pages. + * Thus, we first have to clean the inodes in ->mk_decrypted_inodes. + * + * Just do it the easy way: call sync_filesystem(). It's overkill, but + * it works, and it's more important to minimize the amount of caches we + * drop than the amount of data we sync. Also, unprivileged users can + * already call sync_filesystem() via sys_syncfs() or sys_sync(). + */ + down_read(&sb->s_umount); + err1 = sync_filesystem(sb); + up_read(&sb->s_umount); + /* If a sync error occurs, still try to evict as much as possible. */ + + /* + * Inodes are pinned by their dentries, so we have to evict their + * dentries. shrink_dcache_sb() would suffice, but would be overkill + * and inappropriate for use by unprivileged users. So instead go + * through the inodes' alias lists and try to evict each dentry. + */ + evict_dentries_for_decrypted_inodes(mk); + + /* + * evict_dentries_for_decrypted_inodes() already iput() each inode in + * the list; any inodes for which that dropped the last reference will + * have been evicted due to fscrypt_drop_inode() detecting the key + * removal and telling the VFS to evict the inode. So to finish, we + * just need to check whether any inodes couldn't be evicted. + */ + err2 = check_for_busy_inodes(sb, mk); + + return err1 ?: err2; +} + +/* + * Try to remove an fscrypt master encryption key. + * + * First we wipe the actual master key secret, so that no more inodes can be + * unlocked with it. Then we try to evict all cached inodes that had been + * unlocked with the key. + * + * If all inodes were evicted, then we unlink the fscrypt_master_key from the + * keyring. Otherwise it remains in the keyring in the "incompletely removed" + * state (without the actual secret key) where it tracks the list of remaining + * inodes. Userspace can execute the ioctl again later to retry eviction, or + * alternatively can re-add the secret key again. + * + * For more details, see the "Removing keys" section of + * Documentation/filesystems/fscrypt.rst. + */ +int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_remove_key_arg __user *uarg = _uarg; + struct fscrypt_remove_key_arg arg; + struct key *key; + struct fscrypt_master_key *mk; + u32 status_flags = 0; + int err; + bool dead; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + /* Find the key being removed. */ + key = fscrypt_find_master_key(sb, &arg.key_spec); + if (IS_ERR(key)) + return PTR_ERR(key); + mk = key->payload.data[0]; + + down_write(&key->sem); + + /* Wipe the secret. */ + dead = false; + if (is_master_key_secret_present(&mk->mk_secret)) { + wipe_master_key_secret(&mk->mk_secret); + dead = refcount_dec_and_test(&mk->mk_refcount); + } + up_write(&key->sem); + if (dead) { + /* + * No inodes reference the key, and we wiped the secret, so the + * key object is free to be removed from the keyring. + */ + key_invalidate(key); + err = 0; + } else { + /* Some inodes still reference this key; try to evict them. */ + err = try_to_lock_encrypted_files(sb, mk); + if (err == -EBUSY) { + status_flags |= + FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY; + err = 0; + } + } + /* + * We return 0 if we successfully did something: wiped the secret, or + * tried locking the files again. Users need to check the informational + * status flags if they care whether the key has been fully removed + * including all files locked. + */ + key_put(key); + if (err == 0) + err = put_user(status_flags, &uarg->removal_status_flags); + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); + int __init fscrypt_init_keyring(void) { return register_key_type(&key_type_fscrypt); diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 1c6d18bcdc7b..7b60a47fc73c 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -213,8 +213,16 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) /* * Find the master key, then set up the inode's actual encryption key. + * + * If the master key is found in the filesystem-level keyring, then the + * corresponding 'struct key' is returned in *master_key_ret with + * ->sem read-locked. This is needed to ensure that only one task links the + * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create + * an fscrypt_info for the same inode), and to synchronize the master key being + * removed with a new inode starting to use it. */ -static int setup_file_encryption_key(struct fscrypt_info *ci) +static int setup_file_encryption_key(struct fscrypt_info *ci, + struct key **master_key_ret) { struct key *key; struct fscrypt_master_key *mk = NULL; @@ -234,6 +242,13 @@ static int setup_file_encryption_key(struct fscrypt_info *ci) } mk = key->payload.data[0]; + down_read(&key->sem); + + /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */ + if (!is_master_key_secret_present(&mk->mk_secret)) { + err = -ENOKEY; + goto out_release_key; + } if (mk->mk_secret.size < ci->ci_mode->keysize) { fscrypt_warn(NULL, @@ -246,14 +261,22 @@ static int setup_file_encryption_key(struct fscrypt_info *ci) } err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); + if (err) + goto out_release_key; + + *master_key_ret = key; + return 0; out_release_key: + up_read(&key->sem); key_put(key); return err; } static void put_crypt_info(struct fscrypt_info *ci) { + struct key *key; + if (!ci) return; @@ -263,6 +286,26 @@ static void put_crypt_info(struct fscrypt_info *ci) crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); } + + key = ci->ci_master_key; + if (key) { + struct fscrypt_master_key *mk = key->payload.data[0]; + + /* + * Remove this inode from the list of inodes that were unlocked + * with the master key. + * + * In addition, if we're removing the last inode from a key that + * already had its secret removed, invalidate the key so that it + * gets removed from ->s_master_keys. + */ + spin_lock(&mk->mk_decrypted_inodes_lock); + list_del(&ci->ci_master_key_link); + spin_unlock(&mk->mk_decrypted_inodes_lock); + if (refcount_dec_and_test(&mk->mk_refcount)) + key_invalidate(key); + key_put(key); + } kmem_cache_free(fscrypt_info_cachep, ci); } @@ -271,6 +314,7 @@ int fscrypt_get_encryption_info(struct inode *inode) struct fscrypt_info *crypt_info; struct fscrypt_context ctx; struct fscrypt_mode *mode; + struct key *master_key = NULL; int res; if (fscrypt_has_encryption_key(inode)) @@ -335,13 +379,30 @@ int fscrypt_get_encryption_info(struct inode *inode) WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); crypt_info->ci_mode = mode; - res = setup_file_encryption_key(crypt_info); + res = setup_file_encryption_key(crypt_info, &master_key); if (res) goto out; - if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) + if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) { + if (master_key) { + struct fscrypt_master_key *mk = + master_key->payload.data[0]; + + refcount_inc(&mk->mk_refcount); + crypt_info->ci_master_key = key_get(master_key); + spin_lock(&mk->mk_decrypted_inodes_lock); + list_add(&crypt_info->ci_master_key_link, + &mk->mk_decrypted_inodes); + spin_unlock(&mk->mk_decrypted_inodes_lock); + } crypt_info = NULL; + } + res = 0; out: + if (master_key) { + up_read(&master_key->sem); + key_put(master_key); + } if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); @@ -376,3 +437,39 @@ void fscrypt_free_inode(struct inode *inode) } } EXPORT_SYMBOL(fscrypt_free_inode); + +/** + * fscrypt_drop_inode - check whether the inode's master key has been removed + * + * Filesystems supporting fscrypt must call this from their ->drop_inode() + * method so that encrypted inodes are evicted as soon as they're no longer in + * use and their master key has been removed. + * + * Return: 1 if fscrypt wants the inode to be evicted now, otherwise 0 + */ +int fscrypt_drop_inode(struct inode *inode) +{ + const struct fscrypt_info *ci = READ_ONCE(inode->i_crypt_info); + const struct fscrypt_master_key *mk; + + /* + * If ci is NULL, then the inode doesn't have an encryption key set up + * so it's irrelevant. If ci_master_key is NULL, then the master key + * was provided via the legacy mechanism of the process-subscribed + * keyrings, so we don't know whether it's been removed or not. + */ + if (!ci || !ci->ci_master_key) + return 0; + mk = ci->ci_master_key->payload.data[0]; + + /* + * Note: since we aren't holding key->sem, the result here can + * immediately become outdated. But there's no correctness problem with + * unnecessarily evicting. Nor is there a correctness problem with not + * evicting while iput() is racing with the key being removed, since + * then the thread removing the key will either evict the inode itself + * or will correctly detect that it wasn't evicted due to the race. + */ + return !is_master_key_secret_present(&mk->mk_secret); +} +EXPORT_SYMBOL_GPL(fscrypt_drop_inode); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 46bf66cf76ef..b494c5f9c01f 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -141,11 +141,13 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, /* keyring.c */ extern void fscrypt_sb_free(struct super_block *sb); extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); /* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *); extern void fscrypt_free_inode(struct inode *); +extern int fscrypt_drop_inode(struct inode *inode); /* fname.c */ extern int fscrypt_setup_filename(struct inode *, const struct qstr *, @@ -381,6 +383,11 @@ static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + /* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { @@ -396,6 +403,11 @@ static inline void fscrypt_free_inode(struct inode *inode) { } +static inline int fscrypt_drop_inode(struct inode *inode) +{ + return 0; +} + /* fname.c */ static inline int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 6aeca3cb0a2d..07f37a27a944 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -76,10 +76,19 @@ struct fscrypt_add_key_arg { __u8 raw[]; }; +/* Struct passed to FS_IOC_REMOVE_ENCRYPTION_KEY */ +struct fscrypt_remove_key_arg { + struct fscrypt_key_specifier key_spec; +#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY 0x00000001 + __u32 removal_status_flags; /* output */ + __u32 __reserved[5]; +}; + #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) +#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) /**********************************************************************/ -- GitLab From 5a7e29924dac34f0690b06906aad9d70d3c022a5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:46 -0700 Subject: [PATCH 2752/7155] fscrypt: add FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl Add a new fscrypt ioctl, FS_IOC_GET_ENCRYPTION_KEY_STATUS. Given a key specified by 'struct fscrypt_key_specifier' (the same way a key is specified for the other fscrypt key management ioctls), it returns status information in a 'struct fscrypt_get_key_status_arg'. The main motivation for this is that applications need to be able to check whether an encrypted directory is "unlocked" or not, so that they can add the key if it is not, and avoid adding the key (which may involve prompting the user for a passphrase) if it already is. It's possible to use some workarounds such as checking whether opening a regular file fails with ENOKEY, or checking whether the filenames "look like gibberish" or not. However, no workaround is usable in all cases. Like the other key management ioctls, the keyrings syscalls may seem at first to be a good fit for this. Unfortunately, they are not. Even if we exposed the keyring ID of the ->s_master_keys keyring and gave everyone Search permission on it (note: currently the keyrings permission system would also allow everyone to "invalidate" the keyring too), the fscrypt keys have an additional state that doesn't map cleanly to the keyrings API: the secret can be removed, but we can be still tracking the files that were using the key, and the removal can be re-attempted or the secret added again. After later patches, some applications will also need a way to determine whether a key was added by the current user vs. by some other user. Reserved fields are included in fscrypt_get_key_status_arg for this and other future extensions. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 63 ++++++++++++++++++++++++++++++++++++ include/linux/fscrypt.h | 7 ++++ include/uapi/linux/fscrypt.h | 15 +++++++++ 3 files changed, 85 insertions(+) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index c3423f0edc70..8c94c2fa0c13 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -11,6 +11,7 @@ * * - FS_IOC_ADD_ENCRYPTION_KEY * - FS_IOC_REMOVE_ENCRYPTION_KEY + * - FS_IOC_GET_ENCRYPTION_KEY_STATUS * * See the "User API" section of Documentation/filesystems/fscrypt.rst for more * information about these ioctls. @@ -538,6 +539,68 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); +/* + * Retrieve the status of an fscrypt master encryption key. + * + * We set ->status to indicate whether the key is absent, present, or + * incompletely removed. "Incompletely removed" means that the master key + * secret has been removed, but some files which had been unlocked with it are + * still in use. This field allows applications to easily determine the state + * of an encrypted directory without using a hack such as trying to open a + * regular file in it (which can confuse the "incompletely removed" state with + * absent or present). + * + * For more details, see the "FS_IOC_GET_ENCRYPTION_KEY_STATUS" section of + * Documentation/filesystems/fscrypt.rst. + */ +int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_get_key_status_arg arg; + struct key *key; + struct fscrypt_master_key *mk; + int err; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) + return -EINVAL; + + memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved)); + + key = fscrypt_find_master_key(sb, &arg.key_spec); + if (IS_ERR(key)) { + if (key != ERR_PTR(-ENOKEY)) + return PTR_ERR(key); + arg.status = FSCRYPT_KEY_STATUS_ABSENT; + err = 0; + goto out; + } + mk = key->payload.data[0]; + down_read(&key->sem); + + if (!is_master_key_secret_present(&mk->mk_secret)) { + arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED; + err = 0; + goto out_release_key; + } + + arg.status = FSCRYPT_KEY_STATUS_PRESENT; + err = 0; +out_release_key: + up_read(&key->sem); + key_put(key); +out: + if (!err && copy_to_user(uarg, &arg, sizeof(arg))) + err = -EFAULT; + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_key_status); + int __init fscrypt_init_keyring(void) { return register_key_type(&key_type_fscrypt); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index b494c5f9c01f..6628d09585bd 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -142,6 +142,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, extern void fscrypt_sb_free(struct super_block *sb); extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); /* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); @@ -388,6 +389,12 @@ static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_key_status(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + /* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 07f37a27a944..ed5995b15016 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -84,11 +84,26 @@ struct fscrypt_remove_key_arg { __u32 __reserved[5]; }; +/* Struct passed to FS_IOC_GET_ENCRYPTION_KEY_STATUS */ +struct fscrypt_get_key_status_arg { + /* input */ + struct fscrypt_key_specifier key_spec; + __u32 __reserved[6]; + + /* output */ +#define FSCRYPT_KEY_STATUS_ABSENT 1 +#define FSCRYPT_KEY_STATUS_PRESENT 2 +#define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 + __u32 status; + __u32 __out_reserved[15]; +}; + #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) +#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) /**********************************************************************/ -- GitLab From c1144c9b8ad94d8c11809d75c1f322a853cdfc4a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:47 -0700 Subject: [PATCH 2753/7155] fscrypt: add an HKDF-SHA512 implementation Add an implementation of HKDF (RFC 5869) to fscrypt, for the purpose of deriving additional key material from the fscrypt master keys for v2 encryption policies. HKDF is a key derivation function built on top of HMAC. We choose SHA-512 for the underlying unkeyed hash, and use an "hmac(sha512)" transform allocated from the crypto API. We'll be using this to replace the AES-ECB based KDF currently used to derive the per-file encryption keys. While the AES-ECB based KDF is believed to meet the original security requirements, it is nonstandard and has problems that don't exist in modern KDFs such as HKDF: 1. It's reversible. Given a derived key and nonce, an attacker can easily compute the master key. This is okay if the master key and derived keys are equally hard to compromise, but now we'd like to be more robust against threats such as a derived key being compromised through a timing attack, or a derived key for an in-use file being compromised after the master key has already been removed. 2. It doesn't evenly distribute the entropy from the master key; each 16 input bytes only affects the corresponding 16 output bytes. 3. It isn't easily extensible to deriving other values or keys, such as a public hash for securely identifying the key, or per-mode keys. Per-mode keys will be immediately useful for Adiantum encryption, for which fscrypt currently uses the master key directly, introducing unnecessary usage constraints. Per-mode keys will also be useful for hardware inline encryption, which is currently being worked on. HKDF solves all the above problems. Reviewed-by: Paul Crowley Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/Kconfig | 2 + fs/crypto/Makefile | 1 + fs/crypto/fscrypt_private.h | 15 +++ fs/crypto/hkdf.c | 181 ++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 fs/crypto/hkdf.c diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 5fdf24877c17..ff5a1746cbae 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -7,6 +7,8 @@ config FS_ENCRYPTION select CRYPTO_ECB select CRYPTO_XTS select CRYPTO_CTS + select CRYPTO_SHA512 + select CRYPTO_HMAC select KEYS help Enable encryption of files and directories. This diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 6b2485b41393..232e2bb5a337 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o fscrypto-y := crypto.o \ fname.o \ + hkdf.o \ hooks.o \ keyring.o \ keysetup.o \ diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index fc804f4a03fc..9556e9499dc5 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -172,6 +172,21 @@ extern bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret); +/* hkdf.c */ + +struct fscrypt_hkdf { + struct crypto_shash *hmac_tfm; +}; + +extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, + unsigned int master_key_size); + +extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, + const u8 *info, unsigned int infolen, + u8 *okm, unsigned int okmlen); + +extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); + /* keyring.c */ /* diff --git a/fs/crypto/hkdf.c b/fs/crypto/hkdf.c new file mode 100644 index 000000000000..f21873e1b467 --- /dev/null +++ b/fs/crypto/hkdf.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation + * Function"), aka RFC 5869. See also the original paper (Krawczyk 2010): + * "Cryptographic Extraction and Key Derivation: The HKDF Scheme". + * + * This is used to derive keys from the fscrypt master keys. + * + * Copyright 2019 Google LLC + */ + +#include +#include + +#include "fscrypt_private.h" + +/* + * HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses + * SHA-512 because it is reasonably secure and efficient; and since it produces + * a 64-byte digest, deriving an AES-256-XTS key preserves all 64 bytes of + * entropy from the master key and requires only one iteration of HKDF-Expand. + */ +#define HKDF_HMAC_ALG "hmac(sha512)" +#define HKDF_HASHLEN SHA512_DIGEST_SIZE + +/* + * HKDF consists of two steps: + * + * 1. HKDF-Extract: extract a pseudorandom key of length HKDF_HASHLEN bytes from + * the input keying material and optional salt. + * 2. HKDF-Expand: expand the pseudorandom key into output keying material of + * any length, parameterized by an application-specific info string. + * + * HKDF-Extract can be skipped if the input is already a pseudorandom key of + * length HKDF_HASHLEN bytes. However, cipher modes other than AES-256-XTS take + * shorter keys, and we don't want to force users of those modes to provide + * unnecessarily long master keys. Thus fscrypt still does HKDF-Extract. No + * salt is used, since fscrypt master keys should already be pseudorandom and + * there's no way to persist a random salt per master key from kernel mode. + */ + +/* HKDF-Extract (RFC 5869 section 2.2), unsalted */ +static int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm, + unsigned int ikmlen, u8 prk[HKDF_HASHLEN]) +{ + static const u8 default_salt[HKDF_HASHLEN]; + SHASH_DESC_ON_STACK(desc, hmac_tfm); + int err; + + err = crypto_shash_setkey(hmac_tfm, default_salt, HKDF_HASHLEN); + if (err) + return err; + + desc->tfm = hmac_tfm; + err = crypto_shash_digest(desc, ikm, ikmlen, prk); + shash_desc_zero(desc); + return err; +} + +/* + * Compute HKDF-Extract using the given master key as the input keying material, + * and prepare an HMAC transform object keyed by the resulting pseudorandom key. + * + * Afterwards, the keyed HMAC transform object can be used for HKDF-Expand many + * times without having to recompute HKDF-Extract each time. + */ +int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, + unsigned int master_key_size) +{ + struct crypto_shash *hmac_tfm; + u8 prk[HKDF_HASHLEN]; + int err; + + hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0); + if (IS_ERR(hmac_tfm)) { + fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld", + PTR_ERR(hmac_tfm)); + return PTR_ERR(hmac_tfm); + } + + if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) { + err = -EINVAL; + goto err_free_tfm; + } + + err = hkdf_extract(hmac_tfm, master_key, master_key_size, prk); + if (err) + goto err_free_tfm; + + err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk)); + if (err) + goto err_free_tfm; + + hkdf->hmac_tfm = hmac_tfm; + goto out; + +err_free_tfm: + crypto_free_shash(hmac_tfm); +out: + memzero_explicit(prk, sizeof(prk)); + return err; +} + +/* + * HKDF-Expand (RFC 5869 section 2.3). This expands the pseudorandom key, which + * was already keyed into 'hkdf->hmac_tfm' by fscrypt_init_hkdf(), into 'okmlen' + * bytes of output keying material parameterized by the application-specific + * 'info' of length 'infolen' bytes, prefixed by "fscrypt\0" and the 'context' + * byte. This is thread-safe and may be called by multiple threads in parallel. + * + * ('context' isn't part of the HKDF specification; it's just a prefix fscrypt + * adds to its application-specific info strings to guarantee that it doesn't + * accidentally repeat an info string when using HKDF for different purposes.) + */ +int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, + const u8 *info, unsigned int infolen, + u8 *okm, unsigned int okmlen) +{ + SHASH_DESC_ON_STACK(desc, hkdf->hmac_tfm); + u8 prefix[9]; + unsigned int i; + int err; + const u8 *prev = NULL; + u8 counter = 1; + u8 tmp[HKDF_HASHLEN]; + + if (WARN_ON(okmlen > 255 * HKDF_HASHLEN)) + return -EINVAL; + + desc->tfm = hkdf->hmac_tfm; + + memcpy(prefix, "fscrypt\0", 8); + prefix[8] = context; + + for (i = 0; i < okmlen; i += HKDF_HASHLEN) { + + err = crypto_shash_init(desc); + if (err) + goto out; + + if (prev) { + err = crypto_shash_update(desc, prev, HKDF_HASHLEN); + if (err) + goto out; + } + + err = crypto_shash_update(desc, prefix, sizeof(prefix)); + if (err) + goto out; + + err = crypto_shash_update(desc, info, infolen); + if (err) + goto out; + + BUILD_BUG_ON(sizeof(counter) != 1); + if (okmlen - i < HKDF_HASHLEN) { + err = crypto_shash_finup(desc, &counter, 1, tmp); + if (err) + goto out; + memcpy(&okm[i], tmp, okmlen - i); + memzero_explicit(tmp, sizeof(tmp)); + } else { + err = crypto_shash_finup(desc, &counter, 1, &okm[i]); + if (err) + goto out; + } + counter++; + prev = &okm[i]; + } + err = 0; +out: + if (unlikely(err)) + memzero_explicit(okm, okmlen); /* so caller doesn't need to */ + shash_desc_zero(desc); + return err; +} + +void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf) +{ + crypto_free_shash(hkdf->hmac_tfm); +} -- GitLab From 5dae460c2292dbbdac3a7a982cd566f470d957a2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:47 -0700 Subject: [PATCH 2754/7155] fscrypt: v2 encryption policy support Add a new fscrypt policy version, "v2". It has the following changes from the original policy version, which we call "v1" (*): - Master keys (the user-provided encryption keys) are only ever used as input to HKDF-SHA512. This is more flexible and less error-prone, and it avoids the quirks and limitations of the AES-128-ECB based KDF. Three classes of cryptographically isolated subkeys are defined: - Per-file keys, like used in v1 policies except for the new KDF. - Per-mode keys. These implement the semantics of the DIRECT_KEY flag, which for v1 policies made the master key be used directly. These are also planned to be used for inline encryption when support for it is added. - Key identifiers (see below). - Each master key is identified by a 16-byte master_key_identifier, which is derived from the key itself using HKDF-SHA512. This prevents users from associating the wrong key with an encrypted file or directory. This was easily possible with v1 policies, which identified the key by an arbitrary 8-byte master_key_descriptor. - The key must be provided in the filesystem-level keyring, not in a process-subscribed keyring. The following UAPI additions are made: - The existing ioctl FS_IOC_SET_ENCRYPTION_POLICY can now be passed a fscrypt_policy_v2 to set a v2 encryption policy. It's disambiguated from fscrypt_policy/fscrypt_policy_v1 by the version code prefix. - A new ioctl FS_IOC_GET_ENCRYPTION_POLICY_EX is added. It allows getting the v1 or v2 encryption policy of an encrypted file or directory. The existing FS_IOC_GET_ENCRYPTION_POLICY ioctl could not be used because it did not have a way for userspace to indicate which policy structure is expected. The new ioctl includes a size field, so it is extensible to future fscrypt policy versions. - The ioctls FS_IOC_ADD_ENCRYPTION_KEY, FS_IOC_REMOVE_ENCRYPTION_KEY, and FS_IOC_GET_ENCRYPTION_KEY_STATUS now support managing keys for v2 encryption policies. Such keys are kept logically separate from keys for v1 encryption policies, and are identified by 'identifier' rather than by 'descriptor'. The 'identifier' need not be provided when adding a key, since the kernel will calculate it anyway. This patch temporarily keeps adding/removing v2 policy keys behind the same permission check done for adding/removing v1 policy keys: capable(CAP_SYS_ADMIN). However, the next patch will carefully take advantage of the cryptographically secure master_key_identifier to allow non-root users to add/remove v2 policy keys, thus providing a full replacement for v1 policies. (*) Actually, in the API fscrypt_policy::version is 0 while on-disk fscrypt_context::format is 1. But I believe it makes the most sense to advance both to '2' to have them be in sync, and to consider the numbering to start at 1 except for the API quirk. Reviewed-by: Paul Crowley Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/crypto.c | 2 +- fs/crypto/fname.c | 3 +- fs/crypto/fscrypt_private.h | 187 +++++++++++++--- fs/crypto/keyring.c | 35 ++- fs/crypto/keysetup.c | 202 +++++++++++++---- fs/crypto/keysetup_v1.c | 18 +- fs/crypto/policy.c | 422 ++++++++++++++++++++++++++--------- include/linux/fscrypt.h | 9 +- include/uapi/linux/fscrypt.h | 57 ++++- 9 files changed, 741 insertions(+), 194 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 65ca077e8d58..32a7ad0098cc 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -141,7 +141,7 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, memset(iv, 0, ci->ci_mode->ivsize); iv->lblk_num = cpu_to_le64(lblk_num); - if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) + if (fscrypt_is_direct_key_policy(&ci->ci_policy)) memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE); if (ci->ci_essiv_tfm != NULL) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index f4977d44d69b..3da3707c10e3 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -181,7 +181,8 @@ static int base64_decode(const char *src, int len, u8 *dst) bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret) { - int padding = 4 << (inode->i_crypt_info->ci_flags & + const struct fscrypt_info *ci = inode->i_crypt_info; + int padding = 4 << (fscrypt_policy_flags(&ci->ci_policy) & FSCRYPT_POLICY_FLAGS_PAD_MASK); u32 encrypted_len; diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 9556e9499dc5..c89e37d38e42 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -20,27 +20,127 @@ #define FSCRYPT_MIN_KEY_SIZE 16 -/** - * Encryption context for inode - * - * Protector format: - * 1 byte: Protector format (1 = this version) - * 1 byte: File contents encryption mode - * 1 byte: File names encryption mode - * 1 byte: Flags - * 8 bytes: Master Key descriptor - * 16 bytes: Encryption Key derivation nonce - */ -struct fscrypt_context { - u8 format; +#define FSCRYPT_CONTEXT_V1 1 +#define FSCRYPT_CONTEXT_V2 2 + +struct fscrypt_context_v1 { + u8 version; /* FSCRYPT_CONTEXT_V1 */ u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; -} __packed; +}; -#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1 +struct fscrypt_context_v2 { + u8 version; /* FSCRYPT_CONTEXT_V2 */ + u8 contents_encryption_mode; + u8 filenames_encryption_mode; + u8 flags; + u8 __reserved[4]; + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; +}; + +/** + * fscrypt_context - the encryption context of an inode + * + * This is the on-disk equivalent of an fscrypt_policy, stored alongside each + * encrypted file usually in a hidden extended attribute. It contains the + * fields from the fscrypt_policy, in order to identify the encryption algorithm + * and key with which the file is encrypted. It also contains a nonce that was + * randomly generated by fscrypt itself; this is used as KDF input or as a tweak + * to cause different files to be encrypted differently. + */ +union fscrypt_context { + u8 version; + struct fscrypt_context_v1 v1; + struct fscrypt_context_v2 v2; +}; + +/* + * Return the size expected for the given fscrypt_context based on its version + * number, or 0 if the context version is unrecognized. + */ +static inline int fscrypt_context_size(const union fscrypt_context *ctx) +{ + switch (ctx->version) { + case FSCRYPT_CONTEXT_V1: + BUILD_BUG_ON(sizeof(ctx->v1) != 28); + return sizeof(ctx->v1); + case FSCRYPT_CONTEXT_V2: + BUILD_BUG_ON(sizeof(ctx->v2) != 40); + return sizeof(ctx->v2); + } + return 0; +} + +#undef fscrypt_policy +union fscrypt_policy { + u8 version; + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; +}; + +/* + * Return the size expected for the given fscrypt_policy based on its version + * number, or 0 if the policy version is unrecognized. + */ +static inline int fscrypt_policy_size(const union fscrypt_policy *policy) +{ + switch (policy->version) { + case FSCRYPT_POLICY_V1: + return sizeof(policy->v1); + case FSCRYPT_POLICY_V2: + return sizeof(policy->v2); + } + return 0; +} + +/* Return the contents encryption mode of a valid encryption policy */ +static inline u8 +fscrypt_policy_contents_mode(const union fscrypt_policy *policy) +{ + switch (policy->version) { + case FSCRYPT_POLICY_V1: + return policy->v1.contents_encryption_mode; + case FSCRYPT_POLICY_V2: + return policy->v2.contents_encryption_mode; + } + BUG(); +} + +/* Return the filenames encryption mode of a valid encryption policy */ +static inline u8 +fscrypt_policy_fnames_mode(const union fscrypt_policy *policy) +{ + switch (policy->version) { + case FSCRYPT_POLICY_V1: + return policy->v1.filenames_encryption_mode; + case FSCRYPT_POLICY_V2: + return policy->v2.filenames_encryption_mode; + } + BUG(); +} + +/* Return the flags (FSCRYPT_POLICY_FLAG*) of a valid encryption policy */ +static inline u8 +fscrypt_policy_flags(const union fscrypt_policy *policy) +{ + switch (policy->version) { + case FSCRYPT_POLICY_V1: + return policy->v1.flags; + case FSCRYPT_POLICY_V2: + return policy->v2.flags; + } + BUG(); +} + +static inline bool +fscrypt_is_direct_key_policy(const union fscrypt_policy *policy) +{ + return fscrypt_policy_flags(policy) & FSCRYPT_POLICY_FLAG_DIRECT_KEY; +} /** * For encrypted symlinks, the ciphertext length is stored at the beginning @@ -70,8 +170,8 @@ struct fscrypt_info { struct crypto_cipher *ci_essiv_tfm; /* - * Encryption mode used for this inode. It corresponds to either - * ci_data_mode or ci_filename_mode, depending on the inode type. + * Encryption mode used for this inode. It corresponds to either the + * contents or filenames encryption mode, depending on the inode type. */ struct fscrypt_mode *ci_mode; @@ -97,11 +197,10 @@ struct fscrypt_info { */ struct fscrypt_direct_key *ci_direct_key; - /* fields from the fscrypt_context */ - u8 ci_data_mode; - u8 ci_filename_mode; - u8 ci_flags; - u8 ci_master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + /* The encryption policy used by this inode */ + union fscrypt_policy ci_policy; + + /* This inode's nonce, copied from the fscrypt_context */ u8 ci_nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; @@ -181,6 +280,17 @@ struct fscrypt_hkdf { extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, unsigned int master_key_size); +/* + * The list of contexts in which fscrypt uses HKDF. These values are used as + * the first byte of the HKDF application-specific info string to guarantee that + * info strings are never repeated between contexts. This ensures that all HKDF + * outputs are unique and cryptographically isolated, i.e. knowledge of one + * output doesn't reveal another. + */ +#define HKDF_CONTEXT_KEY_IDENTIFIER 1 +#define HKDF_CONTEXT_PER_FILE_KEY 2 +#define HKDF_CONTEXT_PER_MODE_KEY 3 + extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen, u8 *okm, unsigned int okmlen); @@ -194,10 +304,16 @@ extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); */ struct fscrypt_master_key_secret { - /* Size of the raw key in bytes */ + /* + * For v2 policy keys: HKDF context keyed by this master key. + * For v1 policy keys: not set (hkdf.hmac_tfm == NULL). + */ + struct fscrypt_hkdf hkdf; + + /* Size of the raw key in bytes. Set even if ->raw isn't set. */ u32 size; - /* The raw key */ + /* For v1 policy keys: the raw key. Wiped for v2 policy keys. */ u8 raw[FSCRYPT_MAX_KEY_SIZE]; } __randomize_layout; @@ -223,7 +339,12 @@ struct fscrypt_master_key { */ struct fscrypt_master_key_secret mk_secret; - /* Arbitrary key descriptor which was assigned by userspace */ + /* + * For v1 policy keys: an arbitrary key descriptor which was assigned by + * userspace (->descriptor). + * + * For v2 policy keys: a cryptographic hash of this key (->identifier). + */ struct fscrypt_key_specifier mk_spec; /* @@ -242,6 +363,9 @@ struct fscrypt_master_key { struct list_head mk_decrypted_inodes; spinlock_t mk_decrypted_inodes_lock; + /* Per-mode tfms for DIRECT_KEY policies, allocated on-demand */ + struct crypto_skcipher *mk_mode_keys[__FSCRYPT_MODE_MAX + 1]; + } __randomize_layout; static inline bool @@ -263,6 +387,8 @@ static inline const char *master_key_spec_type( switch (spec->type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: return "descriptor"; + case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: + return "identifier"; } return "[unknown]"; } @@ -272,6 +398,8 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) switch (spec->type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: return FSCRYPT_KEY_DESCRIPTOR_SIZE; + case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: + return FSCRYPT_KEY_IDENTIFIER_SIZE; } return 0; } @@ -315,5 +443,14 @@ extern int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, extern int fscrypt_setup_v1_file_key_via_subscribed_keyrings( struct fscrypt_info *ci); +/* policy.c */ + +extern bool fscrypt_policies_equal(const union fscrypt_policy *policy1, + const union fscrypt_policy *policy2); +extern bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, + const struct inode *inode); +extern int fscrypt_policy_from_context(union fscrypt_policy *policy_u, + const union fscrypt_context *ctx_u, + int ctx_size); #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 8c94c2fa0c13..fca3bdf01e7c 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -17,6 +17,7 @@ * information about these ioctls. */ +#include #include #include @@ -24,6 +25,7 @@ static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) { + fscrypt_destroy_hkdf(&secret->hkdf); memzero_explicit(secret, sizeof(*secret)); } @@ -36,7 +38,13 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst, static void free_master_key(struct fscrypt_master_key *mk) { + size_t i; + wipe_master_key_secret(&mk->mk_secret); + + for (i = 0; i < ARRAY_SIZE(mk->mk_mode_keys); i++) + crypto_free_skcipher(mk->mk_mode_keys[i]); + kzfree(mk); } @@ -109,7 +117,7 @@ static struct key *search_fscrypt_keyring(struct key *keyring, #define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \ (CONST_STRLEN("fscrypt-") + FIELD_SIZEOF(struct super_block, s_id)) -#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1) +#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1) static void format_fs_keyring_description( char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], @@ -314,6 +322,31 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (!capable(CAP_SYS_ADMIN)) goto out_wipe_secret; + if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + err = fscrypt_init_hkdf(&secret.hkdf, secret.raw, secret.size); + if (err) + goto out_wipe_secret; + + /* + * Now that the HKDF context is initialized, the raw key is no + * longer needed. + */ + memzero_explicit(secret.raw, secret.size); + + /* Calculate the key identifier and return it to userspace. */ + err = fscrypt_hkdf_expand(&secret.hkdf, + HKDF_CONTEXT_KEY_IDENTIFIER, + NULL, 0, arg.key_spec.u.identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE); + if (err) + goto out_wipe_secret; + err = -EFAULT; + if (copy_to_user(uarg->key_spec.u.identifier, + arg.key_spec.u.identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE)) + goto out_wipe_secret; + } + err = add_master_key(sb, &secret, &arg.key_spec); out_wipe_secret: wipe_master_key_secret(&secret); diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 7b60a47fc73c..f423d48264db 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -52,20 +52,14 @@ static struct fscrypt_mode available_modes[] = { }; static struct fscrypt_mode * -select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) +select_encryption_mode(const union fscrypt_policy *policy, + const struct inode *inode) { - if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { - fscrypt_warn(inode, - "Unsupported encryption modes (contents mode %d, filenames mode %d)", - ci->ci_data_mode, ci->ci_filename_mode); - return ERR_PTR(-EINVAL); - } - if (S_ISREG(inode->i_mode)) - return &available_modes[ci->ci_data_mode]; + return &available_modes[fscrypt_policy_contents_mode(policy)]; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - return &available_modes[ci->ci_filename_mode]; + return &available_modes[fscrypt_policy_fnames_mode(policy)]; WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", inode->i_ino, (inode->i_mode & S_IFMT)); @@ -211,6 +205,82 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) return 0; } +static int setup_per_mode_key(struct fscrypt_info *ci, + struct fscrypt_master_key *mk) +{ + struct fscrypt_mode *mode = ci->ci_mode; + u8 mode_num = mode - available_modes; + struct crypto_skcipher *tfm, *prev_tfm; + u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; + int err; + + if (WARN_ON(mode_num >= ARRAY_SIZE(mk->mk_mode_keys))) + return -EINVAL; + + /* pairs with cmpxchg() below */ + tfm = READ_ONCE(mk->mk_mode_keys[mode_num]); + if (likely(tfm != NULL)) + goto done; + + BUILD_BUG_ON(sizeof(mode_num) != 1); + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_PER_MODE_KEY, + &mode_num, sizeof(mode_num), + mode_key, mode->keysize); + if (err) + return err; + tfm = fscrypt_allocate_skcipher(mode, mode_key, ci->ci_inode); + memzero_explicit(mode_key, mode->keysize); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + /* pairs with READ_ONCE() above */ + prev_tfm = cmpxchg(&mk->mk_mode_keys[mode_num], NULL, tfm); + if (prev_tfm != NULL) { + crypto_free_skcipher(tfm); + tfm = prev_tfm; + } +done: + ci->ci_ctfm = tfm; + return 0; +} + +static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, + struct fscrypt_master_key *mk) +{ + u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; + int err; + + if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { + /* + * DIRECT_KEY: instead of deriving per-file keys, the per-file + * nonce will be included in all the IVs. But unlike v1 + * policies, for v2 policies in this case we don't encrypt with + * the master key directly but rather derive a per-mode key. + * This ensures that the master key is consistently used only + * for HKDF, avoiding key reuse issues. + */ + if (!fscrypt_mode_supports_direct_key(ci->ci_mode)) { + fscrypt_warn(ci->ci_inode, + "Direct key flag not allowed with %s", + ci->ci_mode->friendly_name); + return -EINVAL; + } + return setup_per_mode_key(ci, mk); + } + + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_PER_FILE_KEY, + ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE, + derived_key, ci->ci_mode->keysize); + if (err) + return err; + + err = fscrypt_set_derived_key(ci, derived_key); + memzero_explicit(derived_key, ci->ci_mode->keysize); + return err; +} + /* * Find the master key, then set up the inode's actual encryption key. * @@ -229,15 +299,36 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, struct fscrypt_key_specifier mk_spec; int err; - mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; - memcpy(mk_spec.u.descriptor, ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); + switch (ci->ci_policy.version) { + case FSCRYPT_POLICY_V1: + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; + memcpy(mk_spec.u.descriptor, + ci->ci_policy.v1.master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); + break; + case FSCRYPT_POLICY_V2: + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; + memcpy(mk_spec.u.identifier, + ci->ci_policy.v2.master_key_identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE); + break; + default: + WARN_ON(1); + return -EINVAL; + } key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); if (IS_ERR(key)) { - if (key != ERR_PTR(-ENOKEY)) + if (key != ERR_PTR(-ENOKEY) || + ci->ci_policy.version != FSCRYPT_POLICY_V1) return PTR_ERR(key); + /* + * As a legacy fallback for v1 policies, search for the key in + * the current task's subscribed keyrings too. Don't move this + * to before the search of ->s_master_keys, since users + * shouldn't be able to override filesystem-level keys. + */ return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); } @@ -250,6 +341,12 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, goto out_release_key; } + /* + * Require that the master key be at least as long as the derived key. + * Otherwise, the derived key cannot possibly contain as much entropy as + * that required by the encryption mode it will be used for. For v1 + * policies it's also required for the KDF to work at all. + */ if (mk->mk_secret.size < ci->ci_mode->keysize) { fscrypt_warn(NULL, "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", @@ -260,7 +357,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, goto out_release_key; } - err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); + switch (ci->ci_policy.version) { + case FSCRYPT_POLICY_V1: + err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); + break; + case FSCRYPT_POLICY_V2: + err = fscrypt_setup_v2_file_key(ci, mk); + break; + default: + WARN_ON(1); + err = -EINVAL; + break; + } if (err) goto out_release_key; @@ -282,7 +390,8 @@ static void put_crypt_info(struct fscrypt_info *ci) if (ci->ci_direct_key) { fscrypt_put_direct_key(ci->ci_direct_key); - } else { + } else if ((ci->ci_ctfm != NULL || ci->ci_essiv_tfm != NULL) && + !fscrypt_is_direct_key_policy(&ci->ci_policy)) { crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); } @@ -312,7 +421,7 @@ static void put_crypt_info(struct fscrypt_info *ci) int fscrypt_get_encryption_info(struct inode *inode) { struct fscrypt_info *crypt_info; - struct fscrypt_context ctx; + union fscrypt_context ctx; struct fscrypt_mode *mode; struct key *master_key = NULL; int res; @@ -335,27 +444,12 @@ int fscrypt_get_encryption_info(struct inode *inode) } /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; - ctx.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; - memset(ctx.master_key_descriptor, 0x42, + ctx.version = FSCRYPT_CONTEXT_V1; + ctx.v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; + ctx.v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; + memset(ctx.v1.master_key_descriptor, 0x42, FSCRYPT_KEY_DESCRIPTOR_SIZE); - } else if (res != sizeof(ctx)) { - fscrypt_warn(inode, - "Unknown encryption context size (%d bytes)", res); - return -EINVAL; - } - - if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) { - fscrypt_warn(inode, "Unknown encryption context version (%d)", - ctx.format); - return -EINVAL; - } - - if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) { - fscrypt_warn(inode, "Unknown encryption context flags (0x%02x)", - ctx.flags); - return -EINVAL; + res = sizeof(ctx.v1); } crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); @@ -364,14 +458,34 @@ int fscrypt_get_encryption_info(struct inode *inode) crypt_info->ci_inode = inode; - crypt_info->ci_flags = ctx.flags; - crypt_info->ci_data_mode = ctx.contents_encryption_mode; - crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; - memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(crypt_info->ci_nonce, ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); + res = fscrypt_policy_from_context(&crypt_info->ci_policy, &ctx, res); + if (res) { + fscrypt_warn(inode, + "Unrecognized or corrupt encryption context"); + goto out; + } + + switch (ctx.version) { + case FSCRYPT_CONTEXT_V1: + memcpy(crypt_info->ci_nonce, ctx.v1.nonce, + FS_KEY_DERIVATION_NONCE_SIZE); + break; + case FSCRYPT_CONTEXT_V2: + memcpy(crypt_info->ci_nonce, ctx.v2.nonce, + FS_KEY_DERIVATION_NONCE_SIZE); + break; + default: + WARN_ON(1); + res = -EINVAL; + goto out; + } + + if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) { + res = -EINVAL; + goto out; + } - mode = select_encryption_mode(crypt_info, inode); + mode = select_encryption_mode(&crypt_info->ci_policy, inode); if (IS_ERR(mode)) { res = PTR_ERR(mode); goto out; diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index 631690bb6ed5..ad1a36c370c3 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -189,12 +189,13 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, */ BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); - memcpy(&hash_key, ci->ci_master_key_descriptor, sizeof(hash_key)); + memcpy(&hash_key, ci->ci_policy.v1.master_key_descriptor, + sizeof(hash_key)); spin_lock(&fscrypt_direct_keys_lock); hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { - if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) + if (memcmp(ci->ci_policy.v1.master_key_descriptor, + dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) continue; if (ci->ci_mode != dk->dk_mode) continue; @@ -237,7 +238,7 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) dk->dk_ctfm = NULL; goto err_free_dk; } - memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, + memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); @@ -262,7 +263,8 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci, return -EINVAL; } - if (ci->ci_data_mode != ci->ci_filename_mode) { + if (ci->ci_policy.v1.contents_encryption_mode != + ci->ci_policy.v1.filenames_encryption_mode) { fscrypt_warn(ci->ci_inode, "Direct key mode not allowed with different contents and filenames modes"); return -EINVAL; @@ -308,7 +310,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci, int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, const u8 *raw_master_key) { - if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) + if (ci->ci_policy.v1.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) return setup_v1_file_key_direct(ci, raw_master_key); else return setup_v1_file_key_derived(ci, raw_master_key); @@ -321,11 +323,11 @@ int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci) int err; key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, - ci->ci_master_key_descriptor, + ci->ci_policy.v1.master_key_descriptor, ci->ci_mode->keysize, &payload); if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) { key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix, - ci->ci_master_key_descriptor, + ci->ci_policy.v1.master_key_descriptor, ci->ci_mode->keysize, &payload); } if (IS_ERR(key)) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index da7ae9c8b4ad..0141d338c1fd 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -5,8 +5,9 @@ * Copyright (C) 2015, Google, Inc. * Copyright (C) 2015, Motorola Mobility. * - * Written by Michael Halcrow, 2015. + * Originally written by Michael Halcrow, 2015. * Modified by Jaegeuk Kim, 2015. + * Modified by Eric Biggers, 2019 for v2 policy support. */ #include @@ -14,70 +15,291 @@ #include #include "fscrypt_private.h" -/* - * check whether an encryption policy is consistent with an encryption context +/** + * fscrypt_policies_equal - check whether two encryption policies are the same + * + * Return: %true if equal, else %false */ -static bool is_encryption_context_consistent_with_policy( - const struct fscrypt_context *ctx, - const struct fscrypt_policy *policy) +bool fscrypt_policies_equal(const union fscrypt_policy *policy1, + const union fscrypt_policy *policy2) { - return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (ctx->flags == policy->flags) && - (ctx->contents_encryption_mode == - policy->contents_encryption_mode) && - (ctx->filenames_encryption_mode == - policy->filenames_encryption_mode); + if (policy1->version != policy2->version) + return false; + + return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); } -static int create_encryption_context_from_policy(struct inode *inode, - const struct fscrypt_policy *policy) +/** + * fscrypt_supported_policy - check whether an encryption policy is supported + * + * Given an encryption policy, check whether all its encryption modes and other + * settings are supported by this kernel. (But we don't currently don't check + * for crypto API support here, so attempting to use an algorithm not configured + * into the crypto API will still fail later.) + * + * Return: %true if supported, else %false + */ +bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, + const struct inode *inode) { - struct fscrypt_context ctx; + switch (policy_u->version) { + case FSCRYPT_POLICY_V1: { + const struct fscrypt_policy_v1 *policy = &policy_u->v1; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) { + fscrypt_warn(inode, + "Unsupported encryption modes (contents %d, filenames %d)", + policy->contents_encryption_mode, + policy->filenames_encryption_mode); + return false; + } + + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { + fscrypt_warn(inode, + "Unsupported encryption flags (0x%02x)", + policy->flags); + return false; + } + + return true; + } + case FSCRYPT_POLICY_V2: { + const struct fscrypt_policy_v2 *policy = &policy_u->v2; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) { + fscrypt_warn(inode, + "Unsupported encryption modes (contents %d, filenames %d)", + policy->contents_encryption_mode, + policy->filenames_encryption_mode); + return false; + } + + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { + fscrypt_warn(inode, + "Unsupported encryption flags (0x%02x)", + policy->flags); + return false; + } + + if (memchr_inv(policy->__reserved, 0, + sizeof(policy->__reserved))) { + fscrypt_warn(inode, + "Reserved bits set in encryption policy"); + return false; + } + + return true; + } + } + return false; +} + +/** + * fscrypt_new_context_from_policy - create a new fscrypt_context from a policy + * + * Create an fscrypt_context for an inode that is being assigned the given + * encryption policy. A new nonce is randomly generated. + * + * Return: the size of the new context in bytes. + */ +static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u, + const union fscrypt_policy *policy_u) +{ + memset(ctx_u, 0, sizeof(*ctx_u)); + + switch (policy_u->version) { + case FSCRYPT_POLICY_V1: { + const struct fscrypt_policy_v1 *policy = &policy_u->v1; + struct fscrypt_context_v1 *ctx = &ctx_u->v1; + + ctx->version = FSCRYPT_CONTEXT_V1; + ctx->contents_encryption_mode = + policy->contents_encryption_mode; + ctx->filenames_encryption_mode = + policy->filenames_encryption_mode; + ctx->flags = policy->flags; + memcpy(ctx->master_key_descriptor, + policy->master_key_descriptor, + sizeof(ctx->master_key_descriptor)); + get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); + return sizeof(*ctx); + } + case FSCRYPT_POLICY_V2: { + const struct fscrypt_policy_v2 *policy = &policy_u->v2; + struct fscrypt_context_v2 *ctx = &ctx_u->v2; + + ctx->version = FSCRYPT_CONTEXT_V2; + ctx->contents_encryption_mode = + policy->contents_encryption_mode; + ctx->filenames_encryption_mode = + policy->filenames_encryption_mode; + ctx->flags = policy->flags; + memcpy(ctx->master_key_identifier, + policy->master_key_identifier, + sizeof(ctx->master_key_identifier)); + get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); + return sizeof(*ctx); + } + } + BUG(); +} - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); +/** + * fscrypt_policy_from_context - convert an fscrypt_context to an fscrypt_policy + * + * Given an fscrypt_context, build the corresponding fscrypt_policy. + * + * Return: 0 on success, or -EINVAL if the fscrypt_context has an unrecognized + * version number or size. + * + * This does *not* validate the settings within the policy itself, e.g. the + * modes, flags, and reserved bits. Use fscrypt_supported_policy() for that. + */ +int fscrypt_policy_from_context(union fscrypt_policy *policy_u, + const union fscrypt_context *ctx_u, + int ctx_size) +{ + memset(policy_u, 0, sizeof(*policy_u)); - if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, - policy->filenames_encryption_mode)) + if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u)) return -EINVAL; - if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) + switch (ctx_u->version) { + case FSCRYPT_CONTEXT_V1: { + const struct fscrypt_context_v1 *ctx = &ctx_u->v1; + struct fscrypt_policy_v1 *policy = &policy_u->v1; + + policy->version = FSCRYPT_POLICY_V1; + policy->contents_encryption_mode = + ctx->contents_encryption_mode; + policy->filenames_encryption_mode = + ctx->filenames_encryption_mode; + policy->flags = ctx->flags; + memcpy(policy->master_key_descriptor, + ctx->master_key_descriptor, + sizeof(policy->master_key_descriptor)); + return 0; + } + case FSCRYPT_CONTEXT_V2: { + const struct fscrypt_context_v2 *ctx = &ctx_u->v2; + struct fscrypt_policy_v2 *policy = &policy_u->v2; + + policy->version = FSCRYPT_POLICY_V2; + policy->contents_encryption_mode = + ctx->contents_encryption_mode; + policy->filenames_encryption_mode = + ctx->filenames_encryption_mode; + policy->flags = ctx->flags; + memcpy(policy->__reserved, ctx->__reserved, + sizeof(policy->__reserved)); + memcpy(policy->master_key_identifier, + ctx->master_key_identifier, + sizeof(policy->master_key_identifier)); + return 0; + } + } + /* unreachable */ + return -EINVAL; +} + +/* Retrieve an inode's encryption policy */ +static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) +{ + const struct fscrypt_info *ci; + union fscrypt_context ctx; + int ret; + + ci = READ_ONCE(inode->i_crypt_info); + if (ci) { + /* key available, use the cached policy */ + *policy = ci->ci_policy; + return 0; + } + + if (!IS_ENCRYPTED(inode)) + return -ENODATA; + + ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + if (ret < 0) + return (ret == -ERANGE) ? -EINVAL : ret; + + return fscrypt_policy_from_context(policy, &ctx, ret); +} + +static int set_encryption_policy(struct inode *inode, + const union fscrypt_policy *policy) +{ + union fscrypt_context ctx; + int ctxsize; + + if (!fscrypt_supported_policy(policy, inode)) return -EINVAL; - ctx.contents_encryption_mode = policy->contents_encryption_mode; - ctx.filenames_encryption_mode = policy->filenames_encryption_mode; - ctx.flags = policy->flags; - BUILD_BUG_ON(sizeof(ctx.nonce) != FS_KEY_DERIVATION_NONCE_SIZE); - get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); + if (policy->version == FSCRYPT_POLICY_V1) { + /* + * The original encryption policy version provided no way of + * verifying that the correct master key was supplied, which was + * insecure in scenarios where multiple users have access to the + * same encrypted files (even just read-only access). The new + * encryption policy version fixes this and also implies use of + * an improved key derivation function and allows non-root users + * to securely remove keys. So as long as compatibility with + * old kernels isn't required, it is recommended to use the new + * policy version for all new encrypted directories. + */ + pr_warn_once("%s (pid %d) is setting deprecated v1 encryption policy; recommend upgrading to v2.\n", + current->comm, current->pid); + } - return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL); + ctxsize = fscrypt_new_context_from_policy(&ctx, policy); + + return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, NULL); } int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) { - struct fscrypt_policy policy; + union fscrypt_policy policy; + union fscrypt_policy existing_policy; struct inode *inode = file_inode(filp); + u8 version; + int size; int ret; - struct fscrypt_context ctx; - if (copy_from_user(&policy, arg, sizeof(policy))) + if (get_user(policy.version, (const u8 __user *)arg)) return -EFAULT; + size = fscrypt_policy_size(&policy); + if (size <= 0) + return -EINVAL; + + /* + * We should just copy the remaining 'size - 1' bytes here, but a + * bizarre bug in gcc 7 and earlier (fixed by gcc r255731) causes gcc to + * think that size can be 0 here (despite the check above!) *and* that + * it's a compile-time constant. Thus it would think copy_from_user() + * is passed compile-time constant ULONG_MAX, causing the compile-time + * buffer overflow check to fail, breaking the build. This only occurred + * when building an i386 kernel with -Os and branch profiling enabled. + * + * Work around it by just copying the first byte again... + */ + version = policy.version; + if (copy_from_user(&policy, arg, size)) + return -EFAULT; + policy.version = version; + if (!inode_owner_or_capable(inode)) return -EACCES; - if (policy.version != 0) - return -EINVAL; - ret = mnt_want_write_file(filp); if (ret) return ret; inode_lock(inode); - ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + ret = fscrypt_get_policy(inode, &existing_policy); if (ret == -ENODATA) { if (!S_ISDIR(inode->i_mode)) ret = -ENOTDIR; @@ -86,14 +308,10 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) else if (!inode->i_sb->s_cop->empty_dir(inode)) ret = -ENOTEMPTY; else - ret = create_encryption_context_from_policy(inode, - &policy); - } else if (ret == sizeof(ctx) && - is_encryption_context_consistent_with_policy(&ctx, - &policy)) { - /* The file already uses the same encryption policy. */ - ret = 0; - } else if (ret >= 0 || ret == -ERANGE) { + ret = set_encryption_policy(inode, &policy); + } else if (ret == -EINVAL || + (ret == 0 && !fscrypt_policies_equal(&policy, + &existing_policy))) { /* The file already uses a different encryption policy. */ ret = -EEXIST; } @@ -105,37 +323,57 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) } EXPORT_SYMBOL(fscrypt_ioctl_set_policy); +/* Original ioctl version; can only get the original policy version */ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) { - struct inode *inode = file_inode(filp); - struct fscrypt_context ctx; - struct fscrypt_policy policy; - int res; + union fscrypt_policy policy; + int err; - if (!IS_ENCRYPTED(inode)) - return -ENODATA; + err = fscrypt_get_policy(file_inode(filp), &policy); + if (err) + return err; - res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); - if (res < 0 && res != -ERANGE) - return res; - if (res != sizeof(ctx)) - return -EINVAL; - if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) + if (policy.version != FSCRYPT_POLICY_V1) return -EINVAL; - policy.version = 0; - policy.contents_encryption_mode = ctx.contents_encryption_mode; - policy.filenames_encryption_mode = ctx.filenames_encryption_mode; - policy.flags = ctx.flags; - memcpy(policy.master_key_descriptor, ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); - - if (copy_to_user(arg, &policy, sizeof(policy))) + if (copy_to_user(arg, &policy, sizeof(policy.v1))) return -EFAULT; return 0; } EXPORT_SYMBOL(fscrypt_ioctl_get_policy); +/* Extended ioctl version; can get policies of any version */ +int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) +{ + struct fscrypt_get_policy_ex_arg arg; + union fscrypt_policy *policy = (union fscrypt_policy *)&arg.policy; + size_t policy_size; + int err; + + /* arg is policy_size, then policy */ + BUILD_BUG_ON(offsetof(typeof(arg), policy_size) != 0); + BUILD_BUG_ON(offsetofend(typeof(arg), policy_size) != + offsetof(typeof(arg), policy)); + BUILD_BUG_ON(sizeof(arg.policy) != sizeof(*policy)); + + err = fscrypt_get_policy(file_inode(filp), policy); + if (err) + return err; + policy_size = fscrypt_policy_size(policy); + + if (copy_from_user(&arg, uarg, sizeof(arg.policy_size))) + return -EFAULT; + + if (policy_size > arg.policy_size) + return -EOVERFLOW; + arg.policy_size = policy_size; + + if (copy_to_user(uarg, &arg, sizeof(arg.policy_size) + policy_size)) + return -EFAULT; + return 0; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); + /** * fscrypt_has_permitted_context() - is a file's encryption policy permitted * within its directory? @@ -157,10 +395,8 @@ EXPORT_SYMBOL(fscrypt_ioctl_get_policy); */ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { - const struct fscrypt_operations *cops = parent->i_sb->s_cop; - const struct fscrypt_info *parent_ci, *child_ci; - struct fscrypt_context parent_ctx, child_ctx; - int res; + union fscrypt_policy parent_policy, child_policy; + int err; /* No restrictions on file types which are never encrypted */ if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && @@ -190,41 +426,22 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) * In any case, if an unexpected error occurs, fall back to "forbidden". */ - res = fscrypt_get_encryption_info(parent); - if (res) + err = fscrypt_get_encryption_info(parent); + if (err) return 0; - res = fscrypt_get_encryption_info(child); - if (res) + err = fscrypt_get_encryption_info(child); + if (err) return 0; - parent_ci = READ_ONCE(parent->i_crypt_info); - child_ci = READ_ONCE(child->i_crypt_info); - - if (parent_ci && child_ci) { - return memcmp(parent_ci->ci_master_key_descriptor, - child_ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (parent_ci->ci_data_mode == child_ci->ci_data_mode) && - (parent_ci->ci_filename_mode == - child_ci->ci_filename_mode) && - (parent_ci->ci_flags == child_ci->ci_flags); - } - res = cops->get_context(parent, &parent_ctx, sizeof(parent_ctx)); - if (res != sizeof(parent_ctx)) + err = fscrypt_get_policy(parent, &parent_policy); + if (err) return 0; - res = cops->get_context(child, &child_ctx, sizeof(child_ctx)); - if (res != sizeof(child_ctx)) + err = fscrypt_get_policy(child, &child_policy); + if (err) return 0; - return memcmp(parent_ctx.master_key_descriptor, - child_ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (parent_ctx.contents_encryption_mode == - child_ctx.contents_encryption_mode) && - (parent_ctx.filenames_encryption_mode == - child_ctx.filenames_encryption_mode) && - (parent_ctx.flags == child_ctx.flags); + return fscrypt_policies_equal(&parent_policy, &child_policy); } EXPORT_SYMBOL(fscrypt_has_permitted_context); @@ -240,7 +457,8 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context); int fscrypt_inherit_context(struct inode *parent, struct inode *child, void *fs_data, bool preload) { - struct fscrypt_context ctx; + union fscrypt_context ctx; + int ctxsize; struct fscrypt_info *ci; int res; @@ -252,16 +470,10 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, if (ci == NULL) return -ENOKEY; - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = ci->ci_data_mode; - ctx.filenames_encryption_mode = ci->ci_filename_mode; - ctx.flags = ci->ci_flags; - memcpy(ctx.master_key_descriptor, ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); - get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); + ctxsize = fscrypt_new_context_from_policy(&ctx, &ci->ci_policy); + BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); - res = parent->i_sb->s_cop->set_context(child, &ctx, - sizeof(ctx), fs_data); + res = parent->i_sb->s_cop->set_context(child, &ctx, ctxsize, fs_data); if (res) return res; return preload ? fscrypt_get_encryption_info(child): 0; diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 6628d09585bd..8b8ff0484042 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -43,7 +43,7 @@ struct fscrypt_name { #define fname_len(p) ((p)->disk_name.len) /* Maximum value for the third parameter of fscrypt_operations.set_context(). */ -#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28 +#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40 #ifdef CONFIG_FS_ENCRYPTION /* @@ -135,6 +135,7 @@ extern void fscrypt_free_bounce_page(struct page *bounce_page); /* policy.c */ extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *); +extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); @@ -361,6 +362,12 @@ static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index ed5995b15016..f961ebf83e98 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -10,15 +10,13 @@ #include -#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 - /* Encryption policy flags */ #define FSCRYPT_POLICY_FLAGS_PAD_4 0x00 #define FSCRYPT_POLICY_FLAGS_PAD_8 0x01 #define FSCRYPT_POLICY_FLAGS_PAD_16 0x02 #define FSCRYPT_POLICY_FLAGS_PAD_32 0x03 #define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 -#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 /* use master key directly */ +#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 #define FSCRYPT_POLICY_FLAGS_VALID 0x07 /* Encryption algorithms */ @@ -27,14 +25,24 @@ #define FSCRYPT_MODE_AES_128_CBC 5 #define FSCRYPT_MODE_AES_128_CTS 6 #define FSCRYPT_MODE_ADIANTUM 9 +#define __FSCRYPT_MODE_MAX 9 -struct fscrypt_policy { +/* + * Legacy policy version; ad-hoc KDF and no key verification. + * For new encrypted directories, use fscrypt_policy_v2 instead. + * + * Careful: the .version field for this is actually 0, not 1. + */ +#define FSCRYPT_POLICY_V1 0 +#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 +struct fscrypt_policy_v1 { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; +#define fscrypt_policy fscrypt_policy_v1 /* * Process-subscribed "logon" key description prefix and payload format. @@ -50,14 +58,45 @@ struct fscrypt_key { }; /* - * Keys are specified by an arbitrary 8-byte key "descriptor", - * matching fscrypt_policy::master_key_descriptor. + * New policy version with HKDF and key verification (recommended). + */ +#define FSCRYPT_POLICY_V2 2 +#define FSCRYPT_KEY_IDENTIFIER_SIZE 16 +struct fscrypt_policy_v2 { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 __reserved[4]; + __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; +}; + +/* Struct passed to FS_IOC_GET_ENCRYPTION_POLICY_EX */ +struct fscrypt_get_policy_ex_arg { + __u64 policy_size; /* input/output */ + union { + __u8 version; + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; + } policy; /* output */ +}; + +/* + * v1 policy keys are specified by an arbitrary 8-byte key "descriptor", + * matching fscrypt_policy_v1::master_key_descriptor. */ #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 /* - * Specifies a key. This doesn't contain the actual key itself; this is just - * the "name" of the key. + * v2 policy keys are specified by a 16-byte key "identifier" which the kernel + * calculates as a cryptographic hash of the key itself, + * matching fscrypt_policy_v2::master_key_identifier. + */ +#define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2 + +/* + * Specifies a key, either for v1 or v2 policies. This doesn't contain the + * actual key itself; this is just the "name" of the key. */ struct fscrypt_key_specifier { __u32 type; /* one of FSCRYPT_KEY_SPEC_TYPE_* */ @@ -65,6 +104,7 @@ struct fscrypt_key_specifier { union { __u8 __reserved[32]; /* reserve some extra space */ __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; } u; }; @@ -101,6 +141,7 @@ struct fscrypt_get_key_status_arg { #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */ #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) -- GitLab From 23c688b54016eed15d39f4387ca9da241e165922 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:47 -0700 Subject: [PATCH 2755/7155] fscrypt: allow unprivileged users to add/remove keys for v2 policies Allow the FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY ioctls to be used by non-root users to add and remove encryption keys from the filesystem-level crypto keyrings, subject to limitations. Motivation: while privileged fscrypt key management is sufficient for some users (e.g. Android and Chromium OS, where a privileged process manages all keys), the old API by design also allows non-root users to set up and use encrypted directories, and we don't want to regress on that. Especially, we don't want to force users to continue using the old API, running into the visibility mismatch between files and keyrings and being unable to "lock" encrypted directories. Intuitively, the ioctls have to be privileged since they manipulate filesystem-level state. However, it's actually safe to make them unprivileged if we very carefully enforce some specific limitations. First, each key must be identified by a cryptographic hash so that a user can't add the wrong key for another user's files. For v2 encryption policies, we use the key_identifier for this. v1 policies don't have this, so managing keys for them remains privileged. Second, each key a user adds is charged to their quota for the keyrings service. Thus, a user can't exhaust memory by adding a huge number of keys. By default each non-root user is allowed up to 200 keys; this can be changed using the existing sysctl 'kernel.keys.maxkeys'. Third, if multiple users add the same key, we keep track of those users of the key (of which there remains a single copy), and won't really remove the key, i.e. "lock" the encrypted files, until all those users have removed it. This prevents denial of service attacks that would be possible under simpler schemes, such allowing the first user who added a key to remove it -- since that could be a malicious user who has compromised the key. Of course, encryption keys should be kept secret, but the idea is that using encryption should never be *less* secure than not using encryption, even if your key was compromised. We tolerate that a user will be unable to really remove a key, i.e. unable to "lock" their encrypted files, if another user has added the same key. But in a sense, this is actually a good thing because it will avoid providing a false notion of security where a key appears to have been removed when actually it's still in memory, available to any attacker who compromises the operating system kernel. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 31 +++- fs/crypto/keyring.c | 320 ++++++++++++++++++++++++++++++++--- fs/crypto/keysetup.c | 18 +- include/uapi/linux/fscrypt.h | 6 +- 4 files changed, 341 insertions(+), 34 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index c89e37d38e42..d0e238234234 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -335,9 +335,16 @@ struct fscrypt_master_key { * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again. * - * Locking: protected by key->sem. + * Locking: protected by key->sem (outer) and mk_secret_sem (inner). + * The reason for two locks is that key->sem also protects modifying + * mk_users, which ranks it above the semaphore for the keyring key + * type, which is in turn above page faults (via keyring_read). But + * sometimes filesystems call fscrypt_get_encryption_info() from within + * a transaction, which ranks it below page faults. So we need a + * separate lock which protects mk_secret but not also mk_users. */ struct fscrypt_master_key_secret mk_secret; + struct rw_semaphore mk_secret_sem; /* * For v1 policy keys: an arbitrary key descriptor which was assigned by @@ -347,6 +354,22 @@ struct fscrypt_master_key { */ struct fscrypt_key_specifier mk_spec; + /* + * Keyring which contains a key of type 'key_type_fscrypt_user' for each + * user who has added this key. Normally each key will be added by just + * one user, but it's possible that multiple users share a key, and in + * that case we need to keep track of those users so that one user can't + * remove the key before the others want it removed too. + * + * This is NULL for v1 policy keys; those can only be added by root. + * + * Locking: in addition to this keyrings own semaphore, this is + * protected by the master key's key->sem, so we can do atomic + * search+insert. It can also be searched without taking any locks, but + * in that case the returned key may have already been removed. + */ + struct key *mk_users; + /* * Length of ->mk_decrypted_inodes, plus one if mk_secret is present. * Once this goes to 0, the master key is removed from ->s_master_keys. @@ -374,9 +397,9 @@ is_master_key_secret_present(const struct fscrypt_master_key_secret *secret) /* * The READ_ONCE() is only necessary for fscrypt_drop_inode() and * fscrypt_key_describe(). These run in atomic context, so they can't - * take key->sem and thus 'secret' can change concurrently which would - * be a data race. But they only need to know whether the secret *was* - * present at the time of check, so READ_ONCE() suffices. + * take ->mk_secret_sem and thus 'secret' can change concurrently which + * would be a data race. But they only need to know whether the secret + * *was* present at the time of check, so READ_ONCE() suffices. */ return READ_ONCE(secret->size) != 0; } diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index fca3bdf01e7c..c654effb83f5 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -45,6 +45,7 @@ static void free_master_key(struct fscrypt_master_key *mk) for (i = 0; i < ARRAY_SIZE(mk->mk_mode_keys); i++) crypto_free_skcipher(mk->mk_mode_keys[i]); + key_put(mk->mk_users); kzfree(mk); } @@ -93,7 +94,39 @@ static struct key_type key_type_fscrypt = { .describe = fscrypt_key_describe, }; -/* Search ->s_master_keys */ +static int fscrypt_user_key_instantiate(struct key *key, + struct key_preparsed_payload *prep) +{ + /* + * We just charge FSCRYPT_MAX_KEY_SIZE bytes to the user's key quota for + * each key, regardless of the exact key size. The amount of memory + * actually used is greater than the size of the raw key anyway. + */ + return key_payload_reserve(key, FSCRYPT_MAX_KEY_SIZE); +} + +static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m) +{ + seq_puts(m, key->description); +} + +/* + * Type of key in ->mk_users. Each key of this type represents a particular + * user who has added a particular master key. + * + * Note that the name of this key type really should be something like + * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen + * mainly for simplicity of presentation in /proc/keys when read by a non-root + * user. And it is expected to be rare that a key is actually added by multiple + * users, since users should keep their encryption keys confidential. + */ +static struct key_type key_type_fscrypt_user = { + .name = ".fscrypt", + .instantiate = fscrypt_user_key_instantiate, + .describe = fscrypt_user_key_describe, +}; + +/* Search ->s_master_keys or ->mk_users */ static struct key *search_fscrypt_keyring(struct key *keyring, struct key_type *type, const char *description) @@ -119,6 +152,13 @@ static struct key *search_fscrypt_keyring(struct key *keyring, #define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1) +#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \ + (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \ + CONST_STRLEN("-users") + 1) + +#define FSCRYPT_MK_USER_DESCRIPTION_SIZE \ + (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1) + static void format_fs_keyring_description( char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], const struct super_block *sb) @@ -134,6 +174,23 @@ static void format_mk_description( master_key_spec_len(mk_spec), (u8 *)&mk_spec->u); } +static void format_mk_users_keyring_description( + char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE], + const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + sprintf(description, "fscrypt-%*phN-users", + FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier); +} + +static void format_mk_user_description( + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE], + const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + + sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE, + mk_identifier, __kuid_val(current_fsuid())); +} + /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */ static int allocate_filesystem_keyring(struct super_block *sb) { @@ -181,6 +238,80 @@ struct key *fscrypt_find_master_key(struct super_block *sb, return search_fscrypt_keyring(keyring, &key_type_fscrypt, description); } +static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE]; + struct key *keyring; + + format_mk_users_keyring_description(description, + mk->mk_spec.u.identifier); + keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), KEY_POS_SEARCH | + KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + + mk->mk_users = keyring; + return 0; +} + +/* + * Find the current user's "key" in the master key's ->mk_users. + * Returns ERR_PTR(-ENOKEY) if not found. + */ +static struct key *find_master_key_user(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; + + format_mk_user_description(description, mk->mk_spec.u.identifier); + return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user, + description); +} + +/* + * Give the current user a "key" in ->mk_users. This charges the user's quota + * and marks the master key as added by the current user, so that it cannot be + * removed by another user with the key. Either the master key's key->sem must + * be held for write, or the master key must be still undergoing initialization. + */ +static int add_master_key_user(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; + struct key *mk_user; + int err; + + format_mk_user_description(description, mk->mk_spec.u.identifier); + mk_user = key_alloc(&key_type_fscrypt_user, description, + current_fsuid(), current_gid(), current_cred(), + KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL); + if (IS_ERR(mk_user)) + return PTR_ERR(mk_user); + + err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL); + key_put(mk_user); + return err; +} + +/* + * Remove the current user's "key" from ->mk_users. + * The master key's key->sem must be held for write. + * + * Returns 0 if removed, -ENOKEY if not found, or another -errno code. + */ +static int remove_master_key_user(struct fscrypt_master_key *mk) +{ + struct key *mk_user; + int err; + + mk_user = find_master_key_user(mk); + if (IS_ERR(mk_user)) + return PTR_ERR(mk_user); + err = key_unlink(mk->mk_users, mk_user); + key_put(mk_user); + return err; +} + /* * Allocate a new fscrypt_master_key which contains the given secret, set it as * the payload of a new 'struct key' of type fscrypt, and link the 'struct key' @@ -202,11 +333,26 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret, mk->mk_spec = *mk_spec; move_master_key_secret(&mk->mk_secret, secret); + init_rwsem(&mk->mk_secret_sem); refcount_set(&mk->mk_refcount, 1); /* secret is present */ INIT_LIST_HEAD(&mk->mk_decrypted_inodes); spin_lock_init(&mk->mk_decrypted_inodes_lock); + if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + err = allocate_master_key_users_keyring(mk); + if (err) + goto out_free_mk; + err = add_master_key_user(mk); + if (err) + goto out_free_mk; + } + + /* + * Note that we don't charge this key to anyone's quota, since when + * ->mk_users is in use those keys are charged instead, and otherwise + * (when ->mk_users isn't in use) only root can add these keys. + */ format_mk_description(description, mk_spec); key = key_alloc(&key_type_fscrypt, description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), @@ -233,13 +379,45 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret, static int add_existing_master_key(struct fscrypt_master_key *mk, struct fscrypt_master_key_secret *secret) { - if (is_master_key_secret_present(&mk->mk_secret)) - return 0; + struct key *mk_user; + bool rekey; + int err; - if (!refcount_inc_not_zero(&mk->mk_refcount)) + /* + * If the current user is already in ->mk_users, then there's nothing to + * do. (Not applicable for v1 policy keys, which have NULL ->mk_users.) + */ + if (mk->mk_users) { + mk_user = find_master_key_user(mk); + if (mk_user != ERR_PTR(-ENOKEY)) { + if (IS_ERR(mk_user)) + return PTR_ERR(mk_user); + key_put(mk_user); + return 0; + } + } + + /* If we'll be re-adding ->mk_secret, try to take the reference. */ + rekey = !is_master_key_secret_present(&mk->mk_secret); + if (rekey && !refcount_inc_not_zero(&mk->mk_refcount)) return KEY_DEAD; - move_master_key_secret(&mk->mk_secret, secret); + /* Add the current user to ->mk_users, if applicable. */ + if (mk->mk_users) { + err = add_master_key_user(mk); + if (err) { + if (rekey && refcount_dec_and_test(&mk->mk_refcount)) + return KEY_DEAD; + return err; + } + } + + /* Re-add the secret if needed. */ + if (rekey) { + down_write(&mk->mk_secret_sem); + move_master_key_secret(&mk->mk_secret, secret); + up_write(&mk->mk_secret_sem); + } return 0; } @@ -266,7 +444,7 @@ static int add_master_key(struct super_block *sb, } else { /* * Found the key in ->s_master_keys. Re-add the secret if - * needed. + * needed, and add the user to ->mk_users if needed. */ down_write(&key->sem); err = add_existing_master_key(key->payload.data[0], secret); @@ -288,6 +466,23 @@ static int add_master_key(struct super_block *sb, * Add a master encryption key to the filesystem, causing all files which were * encrypted with it to appear "unlocked" (decrypted) when accessed. * + * When adding a key for use by v1 encryption policies, this ioctl is + * privileged, and userspace must provide the 'key_descriptor'. + * + * When adding a key for use by v2+ encryption policies, this ioctl is + * unprivileged. This is needed, in general, to allow non-root users to use + * encryption without encountering the visibility problems of process-subscribed + * keyrings and the inability to properly remove keys. This works by having + * each key identified by its cryptographically secure hash --- the + * 'key_identifier'. The cryptographic hash ensures that a malicious user + * cannot add the wrong key for a given identifier. Furthermore, each added key + * is charged to the appropriate user's quota for the keyrings service, which + * prevents a malicious user from adding too many keys. Finally, we forbid a + * user from removing a key while other users have added it too, which prevents + * a user who knows another user's key from causing a denial-of-service by + * removing it at an inopportune time. (We tolerate that a user who knows a key + * can prevent other users from removing it.) + * * For more details, see the "FS_IOC_ADD_ENCRYPTION_KEY" section of * Documentation/filesystems/fscrypt.rst. */ @@ -318,11 +513,18 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (copy_from_user(secret.raw, uarg->raw, secret.size)) goto out_wipe_secret; - err = -EACCES; - if (!capable(CAP_SYS_ADMIN)) - goto out_wipe_secret; - - if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + switch (arg.key_spec.type) { + case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: + /* + * Only root can add keys that are identified by an arbitrary + * descriptor rather than by a cryptographic hash --- since + * otherwise a malicious user could add the wrong key. + */ + err = -EACCES; + if (!capable(CAP_SYS_ADMIN)) + goto out_wipe_secret; + break; + case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: err = fscrypt_init_hkdf(&secret.hkdf, secret.raw, secret.size); if (err) goto out_wipe_secret; @@ -345,6 +547,11 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) arg.key_spec.u.identifier, FSCRYPT_KEY_IDENTIFIER_SIZE)) goto out_wipe_secret; + break; + default: + WARN_ON(1); + err = -EINVAL; + goto out_wipe_secret; } err = add_master_key(sb, &secret, &arg.key_spec); @@ -492,9 +699,12 @@ static int try_to_lock_encrypted_files(struct super_block *sb, /* * Try to remove an fscrypt master encryption key. * - * First we wipe the actual master key secret, so that no more inodes can be - * unlocked with it. Then we try to evict all cached inodes that had been - * unlocked with the key. + * This removes the current user's claim to the key, then removes the key itself + * if no other users have claims. + * + * To "remove the key itself", first we wipe the actual master key secret, so + * that no more inodes can be unlocked with it. Then we try to evict all cached + * inodes that had been unlocked with the key. * * If all inodes were evicted, then we unlink the fscrypt_master_key from the * keyring. Otherwise it remains in the keyring in the "incompletely removed" @@ -525,7 +735,12 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + /* + * Only root can add and remove keys that are identified by an arbitrary + * descriptor rather than by a cryptographic hash. + */ + if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR && + !capable(CAP_SYS_ADMIN)) return -EACCES; /* Find the key being removed. */ @@ -536,11 +751,34 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) down_write(&key->sem); - /* Wipe the secret. */ + /* If relevant, remove current user's claim to the key */ + if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { + err = remove_master_key_user(mk); + if (err) { + up_write(&key->sem); + goto out_put_key; + } + if (mk->mk_users->keys.nr_leaves_on_tree != 0) { + /* + * Other users have still added the key too. We removed + * the current user's claim to the key, but we still + * can't remove the key itself. + */ + status_flags |= + FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS; + err = 0; + up_write(&key->sem); + goto out_put_key; + } + } + + /* No user claims remaining. Go ahead and wipe the secret. */ dead = false; if (is_master_key_secret_present(&mk->mk_secret)) { + down_write(&mk->mk_secret_sem); wipe_master_key_secret(&mk->mk_secret); dead = refcount_dec_and_test(&mk->mk_refcount); + up_write(&mk->mk_secret_sem); } up_write(&key->sem); if (dead) { @@ -560,11 +798,12 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) } } /* - * We return 0 if we successfully did something: wiped the secret, or - * tried locking the files again. Users need to check the informational - * status flags if they care whether the key has been fully removed - * including all files locked. + * We return 0 if we successfully did something: removed a claim to the + * key, wiped the secret, or tried locking the files again. Users need + * to check the informational status flags if they care whether the key + * has been fully removed including all files locked. */ +out_put_key: key_put(key); if (err == 0) err = put_user(status_flags, &uarg->removal_status_flags); @@ -583,6 +822,15 @@ EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); * regular file in it (which can confuse the "incompletely removed" state with * absent or present). * + * In addition, for v2 policy keys we allow applications to determine, via + * ->status_flags and ->user_count, whether the key has been added by the + * current user, by other users, or by both. Most applications should not need + * this, since ordinarily only one user should know a given key. However, if a + * secret key is shared by multiple users, applications may wish to add an + * already-present key to prevent other users from removing it. This ioctl can + * be used to check whether that really is the case before the work is done to + * add the key --- which might e.g. require prompting the user for a passphrase. + * * For more details, see the "FS_IOC_GET_ENCRYPTION_KEY_STATUS" section of * Documentation/filesystems/fscrypt.rst. */ @@ -603,6 +851,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) return -EINVAL; + arg.status_flags = 0; + arg.user_count = 0; memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved)); key = fscrypt_find_master_key(sb, &arg.key_spec); @@ -623,6 +873,20 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) } arg.status = FSCRYPT_KEY_STATUS_PRESENT; + if (mk->mk_users) { + struct key *mk_user; + + arg.user_count = mk->mk_users->keys.nr_leaves_on_tree; + mk_user = find_master_key_user(mk); + if (!IS_ERR(mk_user)) { + arg.status_flags |= + FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF; + key_put(mk_user); + } else if (mk_user != ERR_PTR(-ENOKEY)) { + err = PTR_ERR(mk_user); + goto out_release_key; + } + } err = 0; out_release_key: up_read(&key->sem); @@ -636,5 +900,19 @@ EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_key_status); int __init fscrypt_init_keyring(void) { - return register_key_type(&key_type_fscrypt); + int err; + + err = register_key_type(&key_type_fscrypt); + if (err) + return err; + + err = register_key_type(&key_type_fscrypt_user); + if (err) + goto err_unregister_fscrypt; + + return 0; + +err_unregister_fscrypt: + unregister_key_type(&key_type_fscrypt); + return err; } diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index f423d48264db..d71c2d6dd162 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -286,10 +286,10 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, * * If the master key is found in the filesystem-level keyring, then the * corresponding 'struct key' is returned in *master_key_ret with - * ->sem read-locked. This is needed to ensure that only one task links the - * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create - * an fscrypt_info for the same inode), and to synchronize the master key being - * removed with a new inode starting to use it. + * ->mk_secret_sem read-locked. This is needed to ensure that only one task + * links the fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race + * to create an fscrypt_info for the same inode), and to synchronize the master + * key being removed with a new inode starting to use it. */ static int setup_file_encryption_key(struct fscrypt_info *ci, struct key **master_key_ret) @@ -333,7 +333,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, } mk = key->payload.data[0]; - down_read(&key->sem); + down_read(&mk->mk_secret_sem); /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */ if (!is_master_key_secret_present(&mk->mk_secret)) { @@ -376,7 +376,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, return 0; out_release_key: - up_read(&key->sem); + up_read(&mk->mk_secret_sem); key_put(key); return err; } @@ -514,7 +514,9 @@ int fscrypt_get_encryption_info(struct inode *inode) res = 0; out: if (master_key) { - up_read(&master_key->sem); + struct fscrypt_master_key *mk = master_key->payload.data[0]; + + up_read(&mk->mk_secret_sem); key_put(master_key); } if (res == -ENOKEY) @@ -577,7 +579,7 @@ int fscrypt_drop_inode(struct inode *inode) mk = ci->ci_master_key->payload.data[0]; /* - * Note: since we aren't holding key->sem, the result here can + * Note: since we aren't holding ->mk_secret_sem, the result here can * immediately become outdated. But there's no correctness problem with * unnecessarily evicting. Nor is there a correctness problem with not * evicting while iput() is racing with the key being removed, since diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index f961ebf83e98..b9fb775e3db8 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -120,6 +120,7 @@ struct fscrypt_add_key_arg { struct fscrypt_remove_key_arg { struct fscrypt_key_specifier key_spec; #define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY 0x00000001 +#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS 0x00000002 __u32 removal_status_flags; /* output */ __u32 __reserved[5]; }; @@ -135,7 +136,10 @@ struct fscrypt_get_key_status_arg { #define FSCRYPT_KEY_STATUS_PRESENT 2 #define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 __u32 status; - __u32 __out_reserved[15]; +#define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001 + __u32 status_flags; + __u32 user_count; + __u32 __out_reserved[13]; }; #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) -- GitLab From 78a1b96bcf7a0721c7852bb1475218c3cbef884a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:47 -0700 Subject: [PATCH 2756/7155] fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS ioctl Add a root-only variant of the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl which removes all users' claims of the key, not just the current user's claim. I.e., it always removes the key itself, no matter how many users have added it. This is useful for forcing a directory to be locked, without having to figure out which user ID(s) the key was added under. This is planned to be used by a command like 'sudo fscrypt lock DIR --all-users' in the fscrypt userspace tool (http://github.com/google/fscrypt). Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 29 ++++++++++++++++++++++++----- include/linux/fscrypt.h | 8 ++++++++ include/uapi/linux/fscrypt.h | 1 + 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index c654effb83f5..8c600ead0e2e 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -11,6 +11,7 @@ * * - FS_IOC_ADD_ENCRYPTION_KEY * - FS_IOC_REMOVE_ENCRYPTION_KEY + * - FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS * - FS_IOC_GET_ENCRYPTION_KEY_STATUS * * See the "User API" section of Documentation/filesystems/fscrypt.rst for more @@ -699,8 +700,10 @@ static int try_to_lock_encrypted_files(struct super_block *sb, /* * Try to remove an fscrypt master encryption key. * - * This removes the current user's claim to the key, then removes the key itself - * if no other users have claims. + * FS_IOC_REMOVE_ENCRYPTION_KEY (all_users=false) removes the current user's + * claim to the key, then removes the key itself if no other users have claims. + * FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS (all_users=true) always removes the + * key itself. * * To "remove the key itself", first we wipe the actual master key secret, so * that no more inodes can be unlocked with it. Then we try to evict all cached @@ -715,7 +718,7 @@ static int try_to_lock_encrypted_files(struct super_block *sb, * For more details, see the "Removing keys" section of * Documentation/filesystems/fscrypt.rst. */ -int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) +static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) { struct super_block *sb = file_inode(filp)->i_sb; struct fscrypt_remove_key_arg __user *uarg = _uarg; @@ -751,9 +754,12 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) down_write(&key->sem); - /* If relevant, remove current user's claim to the key */ + /* If relevant, remove current user's (or all users) claim to the key */ if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { - err = remove_master_key_user(mk); + if (all_users) + err = keyring_clear(mk->mk_users); + else + err = remove_master_key_user(mk); if (err) { up_write(&key->sem); goto out_put_key; @@ -809,8 +815,21 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) err = put_user(status_flags, &uarg->removal_status_flags); return err; } + +int fscrypt_ioctl_remove_key(struct file *filp, void __user *uarg) +{ + return do_remove_key(filp, uarg, false); +} EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); +int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *uarg) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return do_remove_key(filp, uarg, true); +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key_all_users); + /* * Retrieve the status of an fscrypt master encryption key. * diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 8b8ff0484042..f622f7460ed8 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -143,6 +143,8 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, extern void fscrypt_sb_free(struct super_block *sb); extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg); extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); /* keysetup.c */ @@ -396,6 +398,12 @@ static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg) { diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index b9fb775e3db8..39ccfe9311c3 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -148,6 +148,7 @@ struct fscrypt_get_key_status_arg { #define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */ #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) +#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) /**********************************************************************/ -- GitLab From 5ab7189a31bad40e4b44020cae6e56c8074721a1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:48 -0700 Subject: [PATCH 2757/7155] fscrypt: require that key be added when setting a v2 encryption policy By looking up the master keys in a filesystem-level keyring rather than in the calling processes' key hierarchy, it becomes possible for a user to set an encryption policy which refers to some key they don't actually know, then encrypt their files using that key. Cryptographically this isn't much of a problem, but the semantics of this would be a bit weird. Thus, enforce that a v2 encryption policy can only be set if the user has previously added the key, or has capable(CAP_FOWNER). We tolerate that this problem will continue to exist for v1 encryption policies, however; there is no way around that. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 3 +++ fs/crypto/keyring.c | 47 +++++++++++++++++++++++++++++++++++++ fs/crypto/policy.c | 14 ++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index d0e238234234..e84efc01512e 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -431,6 +431,9 @@ extern struct key * fscrypt_find_master_key(struct super_block *sb, const struct fscrypt_key_specifier *mk_spec); +extern int fscrypt_verify_key_added(struct super_block *sb, + const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]); + extern int __init fscrypt_init_keyring(void); /* keysetup.c */ diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 8c600ead0e2e..c34fa7c61b43 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -562,6 +562,53 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); +/* + * Verify that the current user has added a master key with the given identifier + * (returns -ENOKEY if not). This is needed to prevent a user from encrypting + * their files using some other user's key which they don't actually know. + * Cryptographically this isn't much of a problem, but the semantics of this + * would be a bit weird, so it's best to just forbid it. + * + * The system administrator (CAP_FOWNER) can override this, which should be + * enough for any use cases where encryption policies are being set using keys + * that were chosen ahead of time but aren't available at the moment. + * + * Note that the key may have already removed by the time this returns, but + * that's okay; we just care whether the key was there at some point. + * + * Return: 0 if the key is added, -ENOKEY if it isn't, or another -errno code + */ +int fscrypt_verify_key_added(struct super_block *sb, + const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + struct fscrypt_key_specifier mk_spec; + struct key *key, *mk_user; + struct fscrypt_master_key *mk; + int err; + + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; + memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE); + + key = fscrypt_find_master_key(sb, &mk_spec); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto out; + } + mk = key->payload.data[0]; + mk_user = find_master_key_user(mk); + if (IS_ERR(mk_user)) { + err = PTR_ERR(mk_user); + } else { + key_put(mk_user); + err = 0; + } + key_put(key); +out: + if (err == -ENOKEY && capable(CAP_FOWNER)) + err = 0; + return err; +} + /* * Try to evict the inode's dentries from the dentry cache. If the inode is a * directory, then it can have at most one dentry; however, that dentry may be diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 0141d338c1fd..4072ba644595 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -233,11 +233,13 @@ static int set_encryption_policy(struct inode *inode, { union fscrypt_context ctx; int ctxsize; + int err; if (!fscrypt_supported_policy(policy, inode)) return -EINVAL; - if (policy->version == FSCRYPT_POLICY_V1) { + switch (policy->version) { + case FSCRYPT_POLICY_V1: /* * The original encryption policy version provided no way of * verifying that the correct master key was supplied, which was @@ -251,6 +253,16 @@ static int set_encryption_policy(struct inode *inode, */ pr_warn_once("%s (pid %d) is setting deprecated v1 encryption policy; recommend upgrading to v2.\n", current->comm, current->pid); + break; + case FSCRYPT_POLICY_V2: + err = fscrypt_verify_key_added(inode->i_sb, + policy->v2.master_key_identifier); + if (err) + return err; + break; + default: + WARN_ON(1); + return -EINVAL; } ctxsize = fscrypt_new_context_from_policy(&ctx, policy); -- GitLab From 29b3692e6dbf82266ec3c2764c236f8708d7fc89 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:48 -0700 Subject: [PATCH 2758/7155] ext4: wire up new fscrypt ioctls Wire up the new ioctls for adding and removing fscrypt keys to/from the filesystem, and the new ioctl for retrieving v2 encryption policies. The key removal ioctls also required making ext4_drop_inode() call fscrypt_drop_inode(). For more details see Documentation/filesystems/fscrypt.rst and the fscrypt patches that added the implementation of these ioctls. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/ext4/ioctl.c | 30 ++++++++++++++++++++++++++++++ fs/ext4/super.c | 3 +++ 2 files changed, 33 insertions(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 442f7ef873fc..fe5a4b13f939 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -1115,6 +1115,31 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case EXT4_IOC_GET_ENCRYPTION_POLICY: return fscrypt_ioctl_get_policy(filp, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg); + + case FS_IOC_ADD_ENCRYPTION_KEY: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_add_key(filp, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_remove_key(filp, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_remove_key_all_users(filp, + (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); + case EXT4_IOC_FSGETXATTR: { struct fsxattr fa; @@ -1231,6 +1256,11 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EXT4_IOC_SET_ENCRYPTION_POLICY: case EXT4_IOC_GET_ENCRYPTION_PWSALT: case EXT4_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case EXT4_IOC_SHUTDOWN: case FS_IOC_GETFSMAP: break; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4079605d437a..757819139b8f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1107,6 +1107,9 @@ static int ext4_drop_inode(struct inode *inode) { int drop = generic_drop_inode(inode); + if (!drop) + drop = fscrypt_drop_inode(inode); + trace_ext4_drop_inode(inode, drop); return drop; } -- GitLab From 8ce589c773180f15d9ef426679a92909e8233dbe Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:48 -0700 Subject: [PATCH 2759/7155] f2fs: wire up new fscrypt ioctls Wire up the new ioctls for adding and removing fscrypt keys to/from the filesystem, and the new ioctl for retrieving v2 encryption policies. The key removal ioctls also required making f2fs_drop_inode() call fscrypt_drop_inode(). For more details see Documentation/filesystems/fscrypt.rst and the fscrypt patches that added the implementation of these ioctls. Acked-by: Jaegeuk Kim Reviewed-by: Chao Yu Signed-off-by: Eric Biggers --- fs/f2fs/file.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/super.c | 2 ++ 2 files changed, 60 insertions(+) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3e58a6f697dd..6a7349f9ac15 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2184,6 +2184,49 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) return err; } +static int f2fs_ioc_get_encryption_policy_ex(struct file *filp, + unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg); +} + +static int f2fs_ioc_add_encryption_key(struct file *filp, unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_add_key(filp, (void __user *)arg); +} + +static int f2fs_ioc_remove_encryption_key(struct file *filp, unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_remove_key(filp, (void __user *)arg); +} + +static int f2fs_ioc_remove_encryption_key_all_users(struct file *filp, + unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_remove_key_all_users(filp, (void __user *)arg); +} + +static int f2fs_ioc_get_encryption_key_status(struct file *filp, + unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); +} + static int f2fs_ioc_gc(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -3092,6 +3135,16 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_get_encryption_policy(filp, arg); case F2FS_IOC_GET_ENCRYPTION_PWSALT: return f2fs_ioc_get_encryption_pwsalt(filp, arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return f2fs_ioc_get_encryption_policy_ex(filp, arg); + case FS_IOC_ADD_ENCRYPTION_KEY: + return f2fs_ioc_add_encryption_key(filp, arg); + case FS_IOC_REMOVE_ENCRYPTION_KEY: + return f2fs_ioc_remove_encryption_key(filp, arg); + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + return f2fs_ioc_remove_encryption_key_all_users(filp, arg); + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + return f2fs_ioc_get_encryption_key_status(filp, arg); case F2FS_IOC_GARBAGE_COLLECT: return f2fs_ioc_gc(filp, arg); case F2FS_IOC_GARBAGE_COLLECT_RANGE: @@ -3219,6 +3272,11 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_ENCRYPTION_POLICY: case F2FS_IOC_GET_ENCRYPTION_PWSALT: case F2FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_WRITE_CHECKPOINT: diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 78a1b873e48a..e15bd29bd453 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -913,6 +913,8 @@ static int f2fs_drop_inode(struct inode *inode) return 0; } ret = generic_drop_inode(inode); + if (!ret) + ret = fscrypt_drop_inode(inode); trace_f2fs_drop_inode(inode, ret); return ret; } -- GitLab From 62de25927a2558324f2f425545cdc90682168ca9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:49 -0700 Subject: [PATCH 2760/7155] ubifs: wire up new fscrypt ioctls Wire up the new ioctls for adding and removing fscrypt keys to/from the filesystem, and the new ioctl for retrieving v2 encryption policies. The key removal ioctls also required making UBIFS use fscrypt_drop_inode(). For more details see Documentation/filesystems/fscrypt.rst and the fscrypt patches that added the implementation of these ioctls. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/ubifs/ioctl.c | 20 ++++++++++++++++++++ fs/ubifs/super.c | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 034ad14710d1..5dc5abca11c7 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -185,6 +185,21 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_GET_ENCRYPTION_POLICY: return fscrypt_ioctl_get_policy(file, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg); + + case FS_IOC_ADD_ENCRYPTION_KEY: + return fscrypt_ioctl_add_key(file, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY: + return fscrypt_ioctl_remove_key(file, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + return fscrypt_ioctl_remove_key_all_users(file, + (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + return fscrypt_ioctl_get_key_status(file, (void __user *)arg); + default: return -ENOTTY; } @@ -202,6 +217,11 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: break; default: return -ENOIOCTLCMD; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 2c0803b0ac3a..3ad6620f14fb 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -318,6 +318,16 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) return err; } +static int ubifs_drop_inode(struct inode *inode) +{ + int drop = generic_drop_inode(inode); + + if (!drop) + drop = fscrypt_drop_inode(inode); + + return drop; +} + static void ubifs_evict_inode(struct inode *inode) { int err; @@ -1990,6 +2000,7 @@ const struct super_operations ubifs_super_operations = { .free_inode = ubifs_free_inode, .put_super = ubifs_put_super, .write_inode = ubifs_write_inode, + .drop_inode = ubifs_drop_inode, .evict_inode = ubifs_evict_inode, .statfs = ubifs_statfs, .dirty_inode = ubifs_dirty_inode, -- GitLab From ba13f2c8d7a08362d519c8f91c846a8987b8df5f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Aug 2019 19:35:49 -0700 Subject: [PATCH 2761/7155] fscrypt: document the new ioctls and policy version Update the fscrypt documentation file to catch up to all the latest changes, including the new ioctls to manage master encryption keys in the filesystem-level keyring and the support for v2 encryption policies. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- Documentation/filesystems/fscrypt.rst | 729 ++++++++++++++++++++++---- 1 file changed, 613 insertions(+), 116 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index d60b885c4024..4289c29d7c5a 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -72,6 +72,9 @@ Online attacks fscrypt (and storage encryption in general) can only provide limited protection, if any at all, against online attacks. In detail: +Side-channel attacks +~~~~~~~~~~~~~~~~~~~~ + fscrypt is only resistant to side-channel attacks, such as timing or electromagnetic attacks, to the extent that the underlying Linux Cryptographic API algorithms are. If a vulnerable algorithm is used, @@ -80,29 +83,90 @@ attacker to mount a side channel attack against the online system. Side channel attacks may also be mounted against applications consuming decrypted data. -After an encryption key has been provided, fscrypt is not designed to -hide the plaintext file contents or filenames from other users on the -same system, regardless of the visibility of the keyring key. -Instead, existing access control mechanisms such as file mode bits, -POSIX ACLs, LSMs, or mount namespaces should be used for this purpose. -Also note that as long as the encryption keys are *anywhere* in -memory, an online attacker can necessarily compromise them by mounting -a physical attack or by exploiting any kernel security vulnerability -which provides an arbitrary memory read primitive. - -While it is ostensibly possible to "evict" keys from the system, -recently accessed encrypted files will remain accessible at least -until the filesystem is unmounted or the VFS caches are dropped, e.g. -using ``echo 2 > /proc/sys/vm/drop_caches``. Even after that, if the -RAM is compromised before being powered off, it will likely still be -possible to recover portions of the plaintext file contents, if not -some of the encryption keys as well. (Since Linux v4.12, all -in-kernel keys related to fscrypt are sanitized before being freed. -However, userspace would need to do its part as well.) - -Currently, fscrypt does not prevent a user from maliciously providing -an incorrect key for another user's existing encrypted files. A -protection against this is planned. +Unauthorized file access +~~~~~~~~~~~~~~~~~~~~~~~~ + +After an encryption key has been added, fscrypt does not hide the +plaintext file contents or filenames from other users on the same +system. Instead, existing access control mechanisms such as file mode +bits, POSIX ACLs, LSMs, or namespaces should be used for this purpose. + +(For the reasoning behind this, understand that while the key is +added, the confidentiality of the data, from the perspective of the +system itself, is *not* protected by the mathematical properties of +encryption but rather only by the correctness of the kernel. +Therefore, any encryption-specific access control checks would merely +be enforced by kernel *code* and therefore would be largely redundant +with the wide variety of access control mechanisms already available.) + +Kernel memory compromise +~~~~~~~~~~~~~~~~~~~~~~~~ + +An attacker who compromises the system enough to read from arbitrary +memory, e.g. by mounting a physical attack or by exploiting a kernel +security vulnerability, can compromise all encryption keys that are +currently in use. + +However, fscrypt allows encryption keys to be removed from the kernel, +which may protect them from later compromise. + +In more detail, the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl (or the +FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS ioctl) can wipe a master +encryption key from kernel memory. If it does so, it will also try to +evict all cached inodes which had been "unlocked" using the key, +thereby wiping their per-file keys and making them once again appear +"locked", i.e. in ciphertext or encrypted form. + +However, these ioctls have some limitations: + +- Per-file keys for in-use files will *not* be removed or wiped. + Therefore, for maximum effect, userspace should close the relevant + encrypted files and directories before removing a master key, as + well as kill any processes whose working directory is in an affected + encrypted directory. + +- The kernel cannot magically wipe copies of the master key(s) that + userspace might have as well. Therefore, userspace must wipe all + copies of the master key(s) it makes as well; normally this should + be done immediately after FS_IOC_ADD_ENCRYPTION_KEY, without waiting + for FS_IOC_REMOVE_ENCRYPTION_KEY. Naturally, the same also applies + to all higher levels in the key hierarchy. Userspace should also + follow other security precautions such as mlock()ing memory + containing keys to prevent it from being swapped out. + +- In general, decrypted contents and filenames in the kernel VFS + caches are freed but not wiped. Therefore, portions thereof may be + recoverable from freed memory, even after the corresponding key(s) + were wiped. To partially solve this, you can set + CONFIG_PAGE_POISONING=y in your kernel config and add page_poison=1 + to your kernel command line. However, this has a performance cost. + +- Secret keys might still exist in CPU registers, in crypto + accelerator hardware (if used by the crypto API to implement any of + the algorithms), or in other places not explicitly considered here. + +Limitations of v1 policies +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +v1 encryption policies have some weaknesses with respect to online +attacks: + +- There is no verification that the provided master key is correct. + Therefore, a malicious user can temporarily associate the wrong key + with another user's encrypted files to which they have read-only + access. Because of filesystem caching, the wrong key will then be + used by the other user's accesses to those files, even if the other + user has the correct key in their own keyring. This violates the + meaning of "read-only access". + +- A compromise of a per-file key also compromises the master key from + which it was derived. + +- Non-root users cannot securely remove encryption keys. + +All the above problems are fixed with v2 encryption policies. For +this reason among others, it is recommended to use v2 encryption +policies on all new encrypted directories. Key hierarchy ============= @@ -123,11 +187,52 @@ appropriate master key. There can be any number of master keys, each of which protects any number of directory trees on any number of filesystems. -Userspace should generate master keys either using a cryptographically -secure random number generator, or by using a KDF (Key Derivation -Function). Note that whenever a KDF is used to "stretch" a -lower-entropy secret such as a passphrase, it is critical that a KDF -designed for this purpose be used, such as scrypt, PBKDF2, or Argon2. +Master keys must be real cryptographic keys, i.e. indistinguishable +from random bytestrings of the same length. This implies that users +**must not** directly use a password as a master key, zero-pad a +shorter key, or repeat a shorter key. Security cannot be guaranteed +if userspace makes any such error, as the cryptographic proofs and +analysis would no longer apply. + +Instead, users should generate master keys either using a +cryptographically secure random number generator, or by using a KDF +(Key Derivation Function). The kernel does not do any key stretching; +therefore, if userspace derives the key from a low-entropy secret such +as a passphrase, it is critical that a KDF designed for this purpose +be used, such as scrypt, PBKDF2, or Argon2. + +Key derivation function +----------------------- + +With one exception, fscrypt never uses the master key(s) for +encryption directly. Instead, they are only used as input to a KDF +(Key Derivation Function) to derive the actual keys. + +The KDF used for a particular master key differs depending on whether +the key is used for v1 encryption policies or for v2 encryption +policies. Users **must not** use the same key for both v1 and v2 +encryption policies. (No real-world attack is currently known on this +specific case of key reuse, but its security cannot be guaranteed +since the cryptographic proofs and analysis would no longer apply.) + +For v1 encryption policies, the KDF only supports deriving per-file +encryption keys. It works by encrypting the master key with +AES-128-ECB, using the file's 16-byte nonce as the AES key. The +resulting ciphertext is used as the derived key. If the ciphertext is +longer than needed, then it is truncated to the needed length. + +For v2 encryption policies, the KDF is HKDF-SHA512. The master key is +passed as the "input keying material", no salt is used, and a distinct +"application-specific information string" is used for each distinct +key to be derived. For example, when a per-file encryption key is +derived, the application-specific information string is the file's +nonce prefixed with "fscrypt\\0" and a context byte. Different +context bytes are used for other types of derived keys. + +HKDF-SHA512 is preferred to the original AES-128-ECB based KDF because +HKDF is more flexible, is nonreversible, and evenly distributes +entropy from the master key. HKDF is also standardized and widely +used by other software, whereas the AES-128-ECB based KDF is ad-hoc. Per-file keys ------------- @@ -138,29 +243,9 @@ files doesn't map to the same ciphertext, or vice versa. In most cases, fscrypt does this by deriving per-file keys. When a new encrypted inode (regular file, directory, or symlink) is created, fscrypt randomly generates a 16-byte nonce and stores it in the -inode's encryption xattr. Then, it uses a KDF (Key Derivation -Function) to derive the file's key from the master key and nonce. - -The Adiantum encryption mode (see `Encryption modes and usage`_) is -special, since it accepts longer IVs and is suitable for both contents -and filenames encryption. For it, a "direct key" option is offered -where the file's nonce is included in the IVs and the master key is -used for encryption directly. This improves performance; however, -users must not use the same master key for any other encryption mode. - -Below, the KDF and design considerations are described in more detail. - -The current KDF works by encrypting the master key with AES-128-ECB, -using the file's nonce as the AES key. The output is used as the -derived key. If the output is longer than needed, then it is -truncated to the needed length. - -Note: this KDF meets the primary security requirement, which is to -produce unique derived keys that preserve the entropy of the master -key, assuming that the master key is already a good pseudorandom key. -However, it is nonstandard and has some problems such as being -reversible, so it is generally considered to be a mistake! It may be -replaced with HKDF or another more standard KDF in the future. +inode's encryption xattr. Then, it uses a KDF (as described in `Key +derivation function`_) to derive the file's key from the master key +and nonce. Key derivation was chosen over key wrapping because wrapped keys would require larger xattrs which would be less likely to fit in-line in the @@ -176,6 +261,37 @@ rejected as it would have prevented ext4 filesystems from being resized, and by itself still wouldn't have been sufficient to prevent the same key from being directly reused for both XTS and CTS-CBC. +DIRECT_KEY and per-mode keys +---------------------------- + +The Adiantum encryption mode (see `Encryption modes and usage`_) is +suitable for both contents and filenames encryption, and it accepts +long IVs --- long enough to hold both an 8-byte logical block number +and a 16-byte per-file nonce. Also, the overhead of each Adiantum key +is greater than that of an AES-256-XTS key. + +Therefore, to improve performance and save memory, for Adiantum a +"direct key" configuration is supported. When the user has enabled +this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy, +per-file keys are not used. Instead, whenever any data (contents or +filenames) is encrypted, the file's 16-byte nonce is included in the +IV. Moreover: + +- For v1 encryption policies, the encryption is done directly with the + master key. Because of this, users **must not** use the same master + key for any other purpose, even for other v1 policies. + +- For v2 encryption policies, the encryption is done with a per-mode + key derived using the KDF. Users may use the same master key for + other v2 encryption policies. + +Key identifiers +--------------- + +For master keys used for v2 encryption policies, a unique 16-byte "key +identifier" is also derived using the KDF. This value is stored in +the clear, since it is needed to reliably identify the key itself. + Encryption modes and usage ========================== @@ -270,24 +386,44 @@ User API Setting an encryption policy ---------------------------- +FS_IOC_SET_ENCRYPTION_POLICY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The FS_IOC_SET_ENCRYPTION_POLICY ioctl sets an encryption policy on an empty directory or verifies that a directory or regular file already has the specified encryption policy. It takes in a pointer to a -:c:type:`struct fscrypt_policy`, defined as follows:: +:c:type:`struct fscrypt_policy_v1` or a :c:type:`struct +fscrypt_policy_v2`, defined as follows:: - #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 - - struct fscrypt_policy { + #define FSCRYPT_POLICY_V1 0 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 + struct fscrypt_policy_v1 { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; + #define fscrypt_policy fscrypt_policy_v1 + + #define FSCRYPT_POLICY_V2 2 + #define FSCRYPT_KEY_IDENTIFIER_SIZE 16 + struct fscrypt_policy_v2 { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 __reserved[4]; + __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + }; This structure must be initialized as follows: -- ``version`` must be 0. +- ``version`` must be FSCRYPT_POLICY_V1 (0) if the struct is + :c:type:`fscrypt_policy_v1` or FSCRYPT_POLICY_V2 (2) if the struct + is :c:type:`fscrypt_policy_v2`. (Note: we refer to the original + policy version as "v1", though its version code is really 0.) For + new encrypted directories, use v2 policies. - ``contents_encryption_mode`` and ``filenames_encryption_mode`` must be set to constants from ```` which identify the @@ -297,21 +433,30 @@ This structure must be initialized as follows: - ``flags`` must contain a value from ```` which identifies the amount of NUL-padding to use when encrypting - filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). In - addition, if the chosen encryption modes are both + filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). + Additionally, if the encryption modes are both FSCRYPT_MODE_ADIANTUM, this can contain - FSCRYPT_POLICY_FLAG_DIRECT_KEY to specify that the master key should - be used directly, without key derivation. + FSCRYPT_POLICY_FLAG_DIRECT_KEY; see `DIRECT_KEY and per-mode keys`_. + +- For v2 encryption policies, ``__reserved`` must be zeroed. -- ``master_key_descriptor`` specifies how to find the master key in - the keyring; see `Adding keys`_. It is up to userspace to choose a - unique ``master_key_descriptor`` for each master key. The e4crypt - and fscrypt tools use the first 8 bytes of +- For v1 encryption policies, ``master_key_descriptor`` specifies how + to find the master key in a keyring; see `Adding keys`_. It is up + to userspace to choose a unique ``master_key_descriptor`` for each + master key. The e4crypt and fscrypt tools use the first 8 bytes of ``SHA-512(SHA-512(master_key))``, but this particular scheme is not required. Also, the master key need not be in the keyring yet when FS_IOC_SET_ENCRYPTION_POLICY is executed. However, it must be added before any files can be created in the encrypted directory. + For v2 encryption policies, ``master_key_descriptor`` has been + replaced with ``master_key_identifier``, which is longer and cannot + be arbitrarily chosen. Instead, the key must first be added using + `FS_IOC_ADD_ENCRYPTION_KEY`_. Then, the ``key_spec.u.identifier`` + the kernel returned in the :c:type:`struct fscrypt_add_key_arg` must + be used as the ``master_key_identifier`` in the :c:type:`struct + fscrypt_policy_v2`. + If the file is not yet encrypted, then FS_IOC_SET_ENCRYPTION_POLICY verifies that the file is an empty directory. If so, the specified encryption policy is assigned to the directory, turning it into an @@ -327,6 +472,15 @@ policy exactly matches the actual one. If they match, then the ioctl returns 0. Otherwise, it fails with EEXIST. This works on both regular files and directories, including nonempty directories. +When a v2 encryption policy is assigned to a directory, it is also +required that either the specified key has been added by the current +user or that the caller has CAP_FOWNER in the initial user namespace. +(This is needed to prevent a user from encrypting their data with +another user's key.) The key must remain added while +FS_IOC_SET_ENCRYPTION_POLICY is executing. However, if the new +encrypted directory does not need to be accessed immediately, then the +key can be removed right away afterwards. + Note that the ext4 filesystem does not allow the root directory to be encrypted, even if it is empty. Users who want to encrypt an entire filesystem with one key should consider using dm-crypt instead. @@ -339,7 +493,11 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: - ``EEXIST``: the file is already encrypted with an encryption policy different from the one specified - ``EINVAL``: an invalid encryption policy was specified (invalid - version, mode(s), or flags) + version, mode(s), or flags; or reserved bits were set) +- ``ENOKEY``: a v2 encryption policy was specified, but the key with + the specified ``master_key_identifier`` has not been added, nor does + the process have the CAP_FOWNER capability in the initial user + namespace - ``ENOTDIR``: the file is unencrypted and is a regular file, not a directory - ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory @@ -358,25 +516,78 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: Getting an encryption policy ---------------------------- -The FS_IOC_GET_ENCRYPTION_POLICY ioctl retrieves the :c:type:`struct -fscrypt_policy`, if any, for a directory or regular file. See above -for the struct definition. No additional permissions are required -beyond the ability to open the file. +Two ioctls are available to get a file's encryption policy: + +- `FS_IOC_GET_ENCRYPTION_POLICY_EX`_ +- `FS_IOC_GET_ENCRYPTION_POLICY`_ + +The extended (_EX) version of the ioctl is more general and is +recommended to use when possible. However, on older kernels only the +original ioctl is available. Applications should try the extended +version, and if it fails with ENOTTY fall back to the original +version. + +FS_IOC_GET_ENCRYPTION_POLICY_EX +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FS_IOC_GET_ENCRYPTION_POLICY_EX ioctl retrieves the encryption +policy, if any, for a directory or regular file. No additional +permissions are required beyond the ability to open the file. It +takes in a pointer to a :c:type:`struct fscrypt_get_policy_ex_arg`, +defined as follows:: + + struct fscrypt_get_policy_ex_arg { + __u64 policy_size; /* input/output */ + union { + __u8 version; + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; + } policy; /* output */ + }; + +The caller must initialize ``policy_size`` to the size available for +the policy struct, i.e. ``sizeof(arg.policy)``. + +On success, the policy struct is returned in ``policy``, and its +actual size is returned in ``policy_size``. ``policy.version`` should +be checked to determine the version of policy returned. Note that the +version code for the "v1" policy is actually 0 (FSCRYPT_POLICY_V1). -FS_IOC_GET_ENCRYPTION_POLICY can fail with the following errors: +FS_IOC_GET_ENCRYPTION_POLICY_EX can fail with the following errors: - ``EINVAL``: the file is encrypted, but it uses an unrecognized - encryption context format + encryption policy version - ``ENODATA``: the file is not encrypted -- ``ENOTTY``: this type of filesystem does not implement encryption +- ``ENOTTY``: this type of filesystem does not implement encryption, + or this kernel is too old to support FS_IOC_GET_ENCRYPTION_POLICY_EX + (try FS_IOC_GET_ENCRYPTION_POLICY instead) - ``EOPNOTSUPP``: the kernel was not configured with encryption support for this filesystem +- ``EOVERFLOW``: the file is encrypted and uses a recognized + encryption policy version, but the policy struct does not fit into + the provided buffer Note: if you only need to know whether a file is encrypted or not, on most filesystems it is also possible to use the FS_IOC_GETFLAGS ioctl and check for FS_ENCRYPT_FL, or to use the statx() system call and check for STATX_ATTR_ENCRYPTED in stx_attributes. +FS_IOC_GET_ENCRYPTION_POLICY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FS_IOC_GET_ENCRYPTION_POLICY ioctl can also retrieve the +encryption policy, if any, for a directory or regular file. However, +unlike `FS_IOC_GET_ENCRYPTION_POLICY_EX`_, +FS_IOC_GET_ENCRYPTION_POLICY only supports the original policy +version. It takes in a pointer directly to a :c:type:`struct +fscrypt_policy_v1` rather than a :c:type:`struct +fscrypt_get_policy_ex_arg`. + +The error codes for FS_IOC_GET_ENCRYPTION_POLICY are the same as those +for FS_IOC_GET_ENCRYPTION_POLICY_EX, except that +FS_IOC_GET_ENCRYPTION_POLICY also returns ``EINVAL`` if the file is +encrypted using a newer encryption policy version. + Getting the per-filesystem salt ------------------------------- @@ -392,8 +603,115 @@ generate and manage any needed salt(s) in userspace. Adding keys ----------- -To provide a master key, userspace must add it to an appropriate -keyring using the add_key() system call (see: +FS_IOC_ADD_ENCRYPTION_KEY +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FS_IOC_ADD_ENCRYPTION_KEY ioctl adds a master encryption key to +the filesystem, making all files on the filesystem which were +encrypted using that key appear "unlocked", i.e. in plaintext form. +It can be executed on any file or directory on the target filesystem, +but using the filesystem's root directory is recommended. It takes in +a pointer to a :c:type:`struct fscrypt_add_key_arg`, defined as +follows:: + + struct fscrypt_add_key_arg { + struct fscrypt_key_specifier key_spec; + __u32 raw_size; + __u32 __reserved[9]; + __u8 raw[]; + }; + + #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 + #define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2 + + struct fscrypt_key_specifier { + __u32 type; /* one of FSCRYPT_KEY_SPEC_TYPE_* */ + __u32 __reserved; + union { + __u8 __reserved[32]; /* reserve some extra space */ + __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + } u; + }; + +:c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized +as follows: + +- If the key is being added for use by v1 encryption policies, then + ``key_spec.type`` must contain FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR, and + ``key_spec.u.descriptor`` must contain the descriptor of the key + being added, corresponding to the value in the + ``master_key_descriptor`` field of :c:type:`struct + fscrypt_policy_v1`. To add this type of key, the calling process + must have the CAP_SYS_ADMIN capability in the initial user + namespace. + + Alternatively, if the key is being added for use by v2 encryption + policies, then ``key_spec.type`` must contain + FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, and ``key_spec.u.identifier`` is + an *output* field which the kernel fills in with a cryptographic + hash of the key. To add this type of key, the calling process does + not need any privileges. However, the number of keys that can be + added is limited by the user's quota for the keyrings service (see + ``Documentation/security/keys/core.rst``). + +- ``raw_size`` must be the size of the ``raw`` key provided, in bytes. + +- ``raw`` is a variable-length field which must contain the actual + key, ``raw_size`` bytes long. + +For v2 policy keys, the kernel keeps track of which user (identified +by effective user ID) added the key, and only allows the key to be +removed by that user --- or by "root", if they use +`FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS`_. + +However, if another user has added the key, it may be desirable to +prevent that other user from unexpectedly removing it. Therefore, +FS_IOC_ADD_ENCRYPTION_KEY may also be used to add a v2 policy key +*again*, even if it's already added by other user(s). In this case, +FS_IOC_ADD_ENCRYPTION_KEY will just install a claim to the key for the +current user, rather than actually add the key again (but the raw key +must still be provided, as a proof of knowledge). + +FS_IOC_ADD_ENCRYPTION_KEY returns 0 if either the key or a claim to +the key was either added or already exists. + +FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors: + +- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the + caller does not have the CAP_SYS_ADMIN capability in the initial + user namespace +- ``EDQUOT``: the key quota for this user would be exceeded by adding + the key +- ``EINVAL``: invalid key size or key specifier type, or reserved bits + were set +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it + +Legacy method +~~~~~~~~~~~~~ + +For v1 encryption policies, a master encryption key can also be +provided by adding it to a process-subscribed keyring, e.g. to a +session keyring, or to a user keyring if the user keyring is linked +into the session keyring. + +This method is deprecated (and not supported for v2 encryption +policies) for several reasons. First, it cannot be used in +combination with FS_IOC_REMOVE_ENCRYPTION_KEY (see `Removing keys`_), +so for removing a key a workaround such as keyctl_unlink() in +combination with ``sync; echo 2 > /proc/sys/vm/drop_caches`` would +have to be used. Second, it doesn't match the fact that the +locked/unlocked status of encrypted files (i.e. whether they appear to +be in plaintext form or in ciphertext form) is global. This mismatch +has caused much confusion as well as real problems when processes +running under different UIDs, such as a ``sudo`` command, need to +access encrypted files. + +Nevertheless, to add a key to one of the process-subscribed keyrings, +the add_key() system call can be used (see: ``Documentation/security/keys/core.rst``). The key type must be "logon"; keys of this type are kept in kernel memory and cannot be read back by userspace. The key description must be "fscrypt:" @@ -401,12 +719,12 @@ followed by the 16-character lower case hex representation of the ``master_key_descriptor`` that was set in the encryption policy. The key payload must conform to the following structure:: - #define FSCRYPT_MAX_KEY_SIZE 64 + #define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { - u32 mode; - u8 raw[FSCRYPT_MAX_KEY_SIZE]; - u32 size; + __u32 mode; + __u8 raw[FSCRYPT_MAX_KEY_SIZE]; + __u32 size; }; ``mode`` is ignored; just set it to 0. The actual key is provided in @@ -418,26 +736,194 @@ with a filesystem-specific prefix such as "ext4:". However, the filesystem-specific prefixes are deprecated and should not be used in new programs. -There are several different types of keyrings in which encryption keys -may be placed, such as a session keyring, a user session keyring, or a -user keyring. Each key must be placed in a keyring that is "attached" -to all processes that might need to access files encrypted with it, in -the sense that request_key() will find the key. Generally, if only -processes belonging to a specific user need to access a given -encrypted directory and no session keyring has been installed, then -that directory's key should be placed in that user's user session -keyring or user keyring. Otherwise, a session keyring should be -installed if needed, and the key should be linked into that session -keyring, or in a keyring linked into that session keyring. - -Note: introducing the complex visibility semantics of keyrings here -was arguably a mistake --- especially given that by design, after any -process successfully opens an encrypted file (thereby setting up the -per-file key), possessing the keyring key is not actually required for -any process to read/write the file until its in-memory inode is -evicted. In the future there probably should be a way to provide keys -directly to the filesystem instead, which would make the intended -semantics clearer. +Removing keys +------------- + +Two ioctls are available for removing a key that was added by +`FS_IOC_ADD_ENCRYPTION_KEY`_: + +- `FS_IOC_REMOVE_ENCRYPTION_KEY`_ +- `FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS`_ + +These two ioctls differ only in cases where v2 policy keys are added +or removed by non-root users. + +These ioctls don't work on keys that were added via the legacy +process-subscribed keyrings mechanism. + +Before using these ioctls, read the `Kernel memory compromise`_ +section for a discussion of the security goals and limitations of +these ioctls. + +FS_IOC_REMOVE_ENCRYPTION_KEY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FS_IOC_REMOVE_ENCRYPTION_KEY ioctl removes a claim to a master +encryption key from the filesystem, and possibly removes the key +itself. It can be executed on any file or directory on the target +filesystem, but using the filesystem's root directory is recommended. +It takes in a pointer to a :c:type:`struct fscrypt_remove_key_arg`, +defined as follows:: + + struct fscrypt_remove_key_arg { + struct fscrypt_key_specifier key_spec; + #define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY 0x00000001 + #define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS 0x00000002 + __u32 removal_status_flags; /* output */ + __u32 __reserved[5]; + }; + +This structure must be zeroed, then initialized as follows: + +- The key to remove is specified by ``key_spec``: + + - To remove a key used by v1 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill + in ``key_spec.u.descriptor``. To remove this type of key, the + calling process must have the CAP_SYS_ADMIN capability in the + initial user namespace. + + - To remove a key used by v2 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill + in ``key_spec.u.identifier``. + +For v2 policy keys, this ioctl is usable by non-root users. However, +to make this possible, it actually just removes the current user's +claim to the key, undoing a single call to FS_IOC_ADD_ENCRYPTION_KEY. +Only after all claims are removed is the key really removed. + +For example, if FS_IOC_ADD_ENCRYPTION_KEY was called with uid 1000, +then the key will be "claimed" by uid 1000, and +FS_IOC_REMOVE_ENCRYPTION_KEY will only succeed as uid 1000. Or, if +both uids 1000 and 2000 added the key, then for each uid +FS_IOC_REMOVE_ENCRYPTION_KEY will only remove their own claim. Only +once *both* are removed is the key really removed. (Think of it like +unlinking a file that may have hard links.) + +If FS_IOC_REMOVE_ENCRYPTION_KEY really removes the key, it will also +try to "lock" all files that had been unlocked with the key. It won't +lock files that are still in-use, so this ioctl is expected to be used +in cooperation with userspace ensuring that none of the files are +still open. However, if necessary, this ioctl can be executed again +later to retry locking any remaining files. + +FS_IOC_REMOVE_ENCRYPTION_KEY returns 0 if either the key was removed +(but may still have files remaining to be locked), the user's claim to +the key was removed, or the key was already removed but had files +remaining to be the locked so the ioctl retried locking them. In any +of these cases, ``removal_status_flags`` is filled in with the +following informational status flags: + +- ``FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY``: set if some file(s) + are still in-use. Not guaranteed to be set in the case where only + the user's claim to the key was removed. +- ``FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS``: set if only the + user's claim to the key was removed, not the key itself + +FS_IOC_REMOVE_ENCRYPTION_KEY can fail with the following errors: + +- ``EACCES``: The FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR key specifier type + was specified, but the caller does not have the CAP_SYS_ADMIN + capability in the initial user namespace +- ``EINVAL``: invalid key specifier type, or reserved bits were set +- ``ENOKEY``: the key object was not found at all, i.e. it was never + added in the first place or was already fully removed including all + files locked; or, the user does not have a claim to the key (but + someone else does). +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it + +FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS is exactly the same as +`FS_IOC_REMOVE_ENCRYPTION_KEY`_, except that for v2 policy keys, the +ALL_USERS version of the ioctl will remove all users' claims to the +key, not just the current user's. I.e., the key itself will always be +removed, no matter how many users have added it. This difference is +only meaningful if non-root users are adding and removing keys. + +Because of this, FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS also requires +"root", namely the CAP_SYS_ADMIN capability in the initial user +namespace. Otherwise it will fail with EACCES. + +Getting key status +------------------ + +FS_IOC_GET_ENCRYPTION_KEY_STATUS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl retrieves the status of a +master encryption key. It can be executed on any file or directory on +the target filesystem, but using the filesystem's root directory is +recommended. It takes in a pointer to a :c:type:`struct +fscrypt_get_key_status_arg`, defined as follows:: + + struct fscrypt_get_key_status_arg { + /* input */ + struct fscrypt_key_specifier key_spec; + __u32 __reserved[6]; + + /* output */ + #define FSCRYPT_KEY_STATUS_ABSENT 1 + #define FSCRYPT_KEY_STATUS_PRESENT 2 + #define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 + __u32 status; + #define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001 + __u32 status_flags; + __u32 user_count; + __u32 __out_reserved[13]; + }; + +The caller must zero all input fields, then fill in ``key_spec``: + + - To get the status of a key for v1 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill + in ``key_spec.u.descriptor``. + + - To get the status of a key for v2 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill + in ``key_spec.u.identifier``. + +On success, 0 is returned and the kernel fills in the output fields: + +- ``status`` indicates whether the key is absent, present, or + incompletely removed. Incompletely removed means that the master + secret has been removed, but some files are still in use; i.e., + `FS_IOC_REMOVE_ENCRYPTION_KEY`_ returned 0 but set the informational + status flag FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY. + +- ``status_flags`` can contain the following flags: + + - ``FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF`` indicates that the key + has added by the current user. This is only set for keys + identified by ``identifier`` rather than by ``descriptor``. + +- ``user_count`` specifies the number of users who have added the key. + This is only set for keys identified by ``identifier`` rather than + by ``descriptor``. + +FS_IOC_GET_ENCRYPTION_KEY_STATUS can fail with the following errors: + +- ``EINVAL``: invalid key specifier type, or reserved bits were set +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it + +Among other use cases, FS_IOC_GET_ENCRYPTION_KEY_STATUS can be useful +for determining whether the key for a given encrypted directory needs +to be added before prompting the user for the passphrase needed to +derive the key. + +FS_IOC_GET_ENCRYPTION_KEY_STATUS can only get the status of keys in +the filesystem-level keyring, i.e. the keyring managed by +`FS_IOC_ADD_ENCRYPTION_KEY`_ and `FS_IOC_REMOVE_ENCRYPTION_KEY`_. It +cannot get the status of a key that has only been added for use by v1 +encryption policies using the legacy mechanism involving +process-subscribed keyrings. Access semantics ================ @@ -500,7 +986,7 @@ Without the key Some filesystem operations may be performed on encrypted regular files, directories, and symlinks even before their encryption key has -been provided: +been added, or after their encryption key has been removed: - File metadata may be read, e.g. using stat(). @@ -565,20 +1051,20 @@ Encryption context ------------------ An encryption policy is represented on-disk by a :c:type:`struct -fscrypt_context`. It is up to individual filesystems to decide where -to store it, but normally it would be stored in a hidden extended -attribute. It should *not* be exposed by the xattr-related system -calls such as getxattr() and setxattr() because of the special -semantics of the encryption xattr. (In particular, there would be -much confusion if an encryption policy were to be added to or removed -from anything other than an empty directory.) The struct is defined -as follows:: +fscrypt_context_v1` or a :c:type:`struct fscrypt_context_v2`. It is +up to individual filesystems to decide where to store it, but normally +it would be stored in a hidden extended attribute. It should *not* be +exposed by the xattr-related system calls such as getxattr() and +setxattr() because of the special semantics of the encryption xattr. +(In particular, there would be much confusion if an encryption policy +were to be added to or removed from anything other than an empty +directory.) These structs are defined as follows:: - #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DERIVATION_NONCE_SIZE 16 - struct fscrypt_context { - u8 format; + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 + struct fscrypt_context_v1 { + u8 version; u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; @@ -586,12 +1072,23 @@ as follows:: u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; -Note that :c:type:`struct fscrypt_context` contains the same -information as :c:type:`struct fscrypt_policy` (see `Setting an -encryption policy`_), except that :c:type:`struct fscrypt_context` -also contains a nonce. The nonce is randomly generated by the kernel -and is used to derive the inode's encryption key as described in -`Per-file keys`_. + #define FSCRYPT_KEY_IDENTIFIER_SIZE 16 + struct fscrypt_context_v2 { + u8 version; + u8 contents_encryption_mode; + u8 filenames_encryption_mode; + u8 flags; + u8 __reserved[4]; + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; + }; + +The context structs contain the same information as the corresponding +policy structs (see `Setting an encryption policy`_), except that the +context structs also contain a nonce. The nonce is randomly generated +by the kernel and is used as KDF input or as a tweak to cause +different files to be encrypted differently; see `Per-file keys`_ and +`DIRECT_KEY and per-mode keys`_. Data path changes ----------------- -- GitLab From 3fda4c617e84c21c8a03b7cc2b3dbfe6c6461592 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:22 -0700 Subject: [PATCH 2762/7155] fs-verity: implement FS_IOC_ENABLE_VERITY ioctl Add a function for filesystems to call to implement the FS_IOC_ENABLE_VERITY ioctl. This ioctl enables fs-verity on a file. See the "FS_IOC_ENABLE_VERITY" section of Documentation/filesystems/fsverity.rst for the documentation. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/Makefile | 3 +- fs/verity/enable.c | 363 +++++++++++++++++++++++++++++++++++++++ include/linux/fsverity.h | 66 +++++++ 3 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 fs/verity/enable.c diff --git a/fs/verity/Makefile b/fs/verity/Makefile index 7fa628cd5eba..04b37475fd28 100644 --- a/fs/verity/Makefile +++ b/fs/verity/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_FS_VERITY) += hash_algs.o \ +obj-$(CONFIG_FS_VERITY) += enable.o \ + hash_algs.o \ init.o \ open.o \ verify.o diff --git a/fs/verity/enable.c b/fs/verity/enable.c new file mode 100644 index 000000000000..df5dab03f0c2 --- /dev/null +++ b/fs/verity/enable.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/enable.c: ioctl to enable verity on a file + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include +#include +#include +#include +#include + +static int build_merkle_tree_level(struct inode *inode, unsigned int level, + u64 num_blocks_to_hash, + const struct merkle_tree_params *params, + u8 *pending_hashes, + struct ahash_request *req) +{ + const struct fsverity_operations *vops = inode->i_sb->s_vop; + unsigned int pending_size = 0; + u64 dst_block_num; + u64 i; + int err; + + if (WARN_ON(params->block_size != PAGE_SIZE)) /* checked earlier too */ + return -EINVAL; + + if (level < params->num_levels) { + dst_block_num = params->level_start[level]; + } else { + if (WARN_ON(num_blocks_to_hash != 1)) + return -EINVAL; + dst_block_num = 0; /* unused */ + } + + for (i = 0; i < num_blocks_to_hash; i++) { + struct page *src_page; + + if ((pgoff_t)i % 10000 == 0 || i + 1 == num_blocks_to_hash) + pr_debug("Hashing block %llu of %llu for level %u\n", + i + 1, num_blocks_to_hash, level); + + if (level == 0) { + /* Leaf: hashing a data block */ + src_page = read_mapping_page(inode->i_mapping, i, NULL); + if (IS_ERR(src_page)) { + err = PTR_ERR(src_page); + fsverity_err(inode, + "Error %d reading data page %llu", + err, i); + return err; + } + } else { + /* Non-leaf: hashing hash block from level below */ + src_page = vops->read_merkle_tree_page(inode, + params->level_start[level - 1] + i); + if (IS_ERR(src_page)) { + err = PTR_ERR(src_page); + fsverity_err(inode, + "Error %d reading Merkle tree page %llu", + err, params->level_start[level - 1] + i); + return err; + } + } + + err = fsverity_hash_page(params, inode, req, src_page, + &pending_hashes[pending_size]); + put_page(src_page); + if (err) + return err; + pending_size += params->digest_size; + + if (level == params->num_levels) /* Root hash? */ + return 0; + + if (pending_size + params->digest_size > params->block_size || + i + 1 == num_blocks_to_hash) { + /* Flush the pending hash block */ + memset(&pending_hashes[pending_size], 0, + params->block_size - pending_size); + err = vops->write_merkle_tree_block(inode, + pending_hashes, + dst_block_num, + params->log_blocksize); + if (err) { + fsverity_err(inode, + "Error %d writing Merkle tree block %llu", + err, dst_block_num); + return err; + } + dst_block_num++; + pending_size = 0; + } + + if (fatal_signal_pending(current)) + return -EINTR; + cond_resched(); + } + return 0; +} + +/* + * Build the Merkle tree for the given inode using the given parameters, and + * return the root hash in @root_hash. + * + * The tree is written to a filesystem-specific location as determined by the + * ->write_merkle_tree_block() method. However, the blocks that comprise the + * tree are the same for all filesystems. + */ +static int build_merkle_tree(struct inode *inode, + const struct merkle_tree_params *params, + u8 *root_hash) +{ + u8 *pending_hashes; + struct ahash_request *req; + u64 blocks; + unsigned int level; + int err = -ENOMEM; + + if (inode->i_size == 0) { + /* Empty file is a special case; root hash is all 0's */ + memset(root_hash, 0, params->digest_size); + return 0; + } + + pending_hashes = kmalloc(params->block_size, GFP_KERNEL); + req = ahash_request_alloc(params->hash_alg->tfm, GFP_KERNEL); + if (!pending_hashes || !req) + goto out; + + /* + * Build each level of the Merkle tree, starting at the leaf level + * (level 0) and ascending to the root node (level 'num_levels - 1'). + * Then at the end (level 'num_levels'), calculate the root hash. + */ + blocks = (inode->i_size + params->block_size - 1) >> + params->log_blocksize; + for (level = 0; level <= params->num_levels; level++) { + err = build_merkle_tree_level(inode, level, blocks, params, + pending_hashes, req); + if (err) + goto out; + blocks = (blocks + params->hashes_per_block - 1) >> + params->log_arity; + } + memcpy(root_hash, pending_hashes, params->digest_size); + err = 0; +out: + kfree(pending_hashes); + ahash_request_free(req); + return err; +} + +static int enable_verity(struct file *filp, + const struct fsverity_enable_arg *arg) +{ + struct inode *inode = file_inode(filp); + const struct fsverity_operations *vops = inode->i_sb->s_vop; + struct merkle_tree_params params = { }; + struct fsverity_descriptor *desc; + size_t desc_size = sizeof(*desc); + struct fsverity_info *vi; + int err; + + /* Start initializing the fsverity_descriptor */ + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + return -ENOMEM; + desc->version = 1; + desc->hash_algorithm = arg->hash_algorithm; + desc->log_blocksize = ilog2(arg->block_size); + + /* Get the salt if the user provided one */ + if (arg->salt_size && + copy_from_user(desc->salt, + (const u8 __user *)(uintptr_t)arg->salt_ptr, + arg->salt_size)) { + err = -EFAULT; + goto out; + } + desc->salt_size = arg->salt_size; + + desc->data_size = cpu_to_le64(inode->i_size); + + /* Prepare the Merkle tree parameters */ + err = fsverity_init_merkle_tree_params(¶ms, inode, + arg->hash_algorithm, + desc->log_blocksize, + desc->salt, desc->salt_size); + if (err) + goto out; + + /* + * Start enabling verity on this file, serialized by the inode lock. + * Fail if verity is already enabled or is already being enabled. + */ + inode_lock(inode); + if (IS_VERITY(inode)) + err = -EEXIST; + else + err = vops->begin_enable_verity(filp); + inode_unlock(inode); + if (err) + goto out; + + /* + * Build the Merkle tree. Don't hold the inode lock during this, since + * on huge files this may take a very long time and we don't want to + * force unrelated syscalls like chown() to block forever. We don't + * need the inode lock here because deny_write_access() already prevents + * the file from being written to or truncated, and we still serialize + * ->begin_enable_verity() and ->end_enable_verity() using the inode + * lock and only allow one process to be here at a time on a given file. + */ + pr_debug("Building Merkle tree...\n"); + BUILD_BUG_ON(sizeof(desc->root_hash) < FS_VERITY_MAX_DIGEST_SIZE); + err = build_merkle_tree(inode, ¶ms, desc->root_hash); + if (err) { + fsverity_err(inode, "Error %d building Merkle tree", err); + goto rollback; + } + pr_debug("Done building Merkle tree. Root hash is %s:%*phN\n", + params.hash_alg->name, params.digest_size, desc->root_hash); + + /* + * Create the fsverity_info. Don't bother trying to save work by + * reusing the merkle_tree_params from above. Instead, just create the + * fsverity_info from the fsverity_descriptor as if it were just loaded + * from disk. This is simpler, and it serves as an extra check that the + * metadata we're writing is valid before actually enabling verity. + */ + vi = fsverity_create_info(inode, desc, desc_size); + if (IS_ERR(vi)) { + err = PTR_ERR(vi); + goto rollback; + } + + /* + * Tell the filesystem to finish enabling verity on the file. + * Serialized with ->begin_enable_verity() by the inode lock. + */ + inode_lock(inode); + err = vops->end_enable_verity(filp, desc, desc_size, params.tree_size); + inode_unlock(inode); + if (err) { + fsverity_err(inode, "%ps() failed with err %d", + vops->end_enable_verity, err); + fsverity_free_info(vi); + } else if (WARN_ON(!IS_VERITY(inode))) { + err = -EINVAL; + fsverity_free_info(vi); + } else { + /* Successfully enabled verity */ + + /* + * Readers can start using ->i_verity_info immediately, so it + * can't be rolled back once set. So don't set it until just + * after the filesystem has successfully enabled verity. + */ + fsverity_set_info(inode, vi); + } +out: + kfree(params.hashstate); + kfree(desc); + return err; + +rollback: + inode_lock(inode); + (void)vops->end_enable_verity(filp, NULL, 0, params.tree_size); + inode_unlock(inode); + goto out; +} + +/** + * fsverity_ioctl_enable() - enable verity on a file + * + * Enable fs-verity on a file. See the "FS_IOC_ENABLE_VERITY" section of + * Documentation/filesystems/fsverity.rst for the documentation. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_ioctl_enable(struct file *filp, const void __user *uarg) +{ + struct inode *inode = file_inode(filp); + struct fsverity_enable_arg arg; + int err; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (arg.version != 1) + return -EINVAL; + + if (arg.__reserved1 || + memchr_inv(arg.__reserved2, 0, sizeof(arg.__reserved2))) + return -EINVAL; + + if (arg.block_size != PAGE_SIZE) + return -EINVAL; + + if (arg.salt_size > FIELD_SIZEOF(struct fsverity_descriptor, salt)) + return -EMSGSIZE; + + if (arg.sig_size) + return -EINVAL; + + /* + * Require a regular file with write access. But the actual fd must + * still be readonly so that we can lock out all writers. This is + * needed to guarantee that no writable fds exist to the file once it + * has verity enabled, and to stabilize the data being hashed. + */ + + err = inode_permission(inode, MAY_WRITE); + if (err) + return err; + + if (IS_APPEND(inode)) + return -EPERM; + + if (S_ISDIR(inode->i_mode)) + return -EISDIR; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + err = mnt_want_write_file(filp); + if (err) /* -EROFS */ + return err; + + err = deny_write_access(filp); + if (err) /* -ETXTBSY */ + goto out_drop_write; + + err = enable_verity(filp, &arg); + if (err) + goto out_allow_write_access; + + /* + * Some pages of the file may have been evicted from pagecache after + * being used in the Merkle tree construction, then read into pagecache + * again by another process reading from the file concurrently. Since + * these pages didn't undergo verification against the file measurement + * which fs-verity now claims to be enforcing, we have to wipe the + * pagecache to ensure that all future reads are verified. + */ + filemap_write_and_wait(inode->i_mapping); + invalidate_inode_pages2(inode->i_mapping); + + /* + * allow_write_access() is needed to pair with deny_write_access(). + * Regardless, the filesystem won't allow writing to verity files. + */ +out_allow_write_access: + allow_write_access(filp); +out_drop_write: + mnt_drop_write_file(filp); + return err; +} +EXPORT_SYMBOL_GPL(fsverity_ioctl_enable); diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 95c257cd7ff0..d1a5dbf450c4 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -17,6 +17,44 @@ /* Verity operations for filesystems */ struct fsverity_operations { + /** + * Begin enabling verity on the given file. + * + * @filp: a readonly file descriptor for the file + * + * The filesystem must do any needed filesystem-specific preparations + * for enabling verity, e.g. evicting inline data. It also must return + * -EBUSY if verity is already being enabled on the given file. + * + * i_rwsem is held for write. + * + * Return: 0 on success, -errno on failure + */ + int (*begin_enable_verity)(struct file *filp); + + /** + * End enabling verity on the given file. + * + * @filp: a readonly file descriptor for the file + * @desc: the verity descriptor to write, or NULL on failure + * @desc_size: size of verity descriptor, or 0 on failure + * @merkle_tree_size: total bytes the Merkle tree took up + * + * If desc == NULL, then enabling verity failed and the filesystem only + * must do any necessary cleanups. Else, it must also store the given + * verity descriptor to a fs-specific location associated with the inode + * and do any fs-specific actions needed to mark the inode as a verity + * inode, e.g. setting a bit in the on-disk inode. The filesystem is + * also responsible for setting the S_VERITY flag in the VFS inode. + * + * i_rwsem is held for write, but it may have been dropped between + * ->begin_enable_verity() and ->end_enable_verity(). + * + * Return: 0 on success, -errno on failure + */ + int (*end_enable_verity)(struct file *filp, const void *desc, + size_t desc_size, u64 merkle_tree_size); + /** * Get the verity descriptor of the given inode. * @@ -50,6 +88,22 @@ struct fsverity_operations { */ struct page *(*read_merkle_tree_page)(struct inode *inode, pgoff_t index); + + /** + * Write a Merkle tree block to the given inode. + * + * @inode: the inode for which the Merkle tree is being built + * @buf: block to write + * @index: 0-based index of the block within the Merkle tree + * @log_blocksize: log base 2 of the Merkle tree block size + * + * This is only called between ->begin_enable_verity() and + * ->end_enable_verity(). + * + * Return: 0 on success, -errno on failure + */ + int (*write_merkle_tree_block)(struct inode *inode, const void *buf, + u64 index, int log_blocksize); }; #ifdef CONFIG_FS_VERITY @@ -60,6 +114,10 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) return READ_ONCE(inode->i_verity_info); } +/* enable.c */ + +extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg); + /* open.c */ extern int fsverity_file_open(struct inode *inode, struct file *filp); @@ -79,6 +137,14 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) return NULL; } +/* enable.c */ + +static inline int fsverity_ioctl_enable(struct file *filp, + const void __user *arg) +{ + return -EOPNOTSUPP; +} + /* open.c */ static inline int fsverity_file_open(struct inode *inode, struct file *filp) -- GitLab From 4dd893d832cf4da5409e1fecea9c4f6452a93f2b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:23 -0700 Subject: [PATCH 2763/7155] fs-verity: implement FS_IOC_MEASURE_VERITY ioctl Add a function for filesystems to call to implement the FS_IOC_MEASURE_VERITY ioctl. This ioctl retrieves the file measurement that fs-verity calculated for the given file and is enforcing for reads; i.e., reads that don't match this hash will fail. This ioctl can be used for authentication or logging of file measurements in userspace. See the "FS_IOC_MEASURE_VERITY" section of Documentation/filesystems/fsverity.rst for the documentation. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/Makefile | 1 + fs/verity/measure.c | 57 ++++++++++++++++++++++++++++++++++++++++ include/linux/fsverity.h | 11 ++++++++ 3 files changed, 69 insertions(+) create mode 100644 fs/verity/measure.c diff --git a/fs/verity/Makefile b/fs/verity/Makefile index 04b37475fd28..6f7675ae0a31 100644 --- a/fs/verity/Makefile +++ b/fs/verity/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_FS_VERITY) += enable.o \ hash_algs.o \ init.o \ + measure.o \ open.o \ verify.o diff --git a/fs/verity/measure.c b/fs/verity/measure.c new file mode 100644 index 000000000000..05049b68c745 --- /dev/null +++ b/fs/verity/measure.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/measure.c: ioctl to get a verity file's measurement + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include + +/** + * fsverity_ioctl_measure() - get a verity file's measurement + * + * Retrieve the file measurement that the kernel is enforcing for reads from a + * verity file. See the "FS_IOC_MEASURE_VERITY" section of + * Documentation/filesystems/fsverity.rst for the documentation. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_ioctl_measure(struct file *filp, void __user *_uarg) +{ + const struct inode *inode = file_inode(filp); + struct fsverity_digest __user *uarg = _uarg; + const struct fsverity_info *vi; + const struct fsverity_hash_alg *hash_alg; + struct fsverity_digest arg; + + vi = fsverity_get_info(inode); + if (!vi) + return -ENODATA; /* not a verity file */ + hash_alg = vi->tree_params.hash_alg; + + /* + * The user specifies the digest_size their buffer has space for; we can + * return the digest if it fits in the available space. We write back + * the actual size, which may be shorter than the user-specified size. + */ + + if (get_user(arg.digest_size, &uarg->digest_size)) + return -EFAULT; + if (arg.digest_size < hash_alg->digest_size) + return -EOVERFLOW; + + memset(&arg, 0, sizeof(arg)); + arg.digest_algorithm = hash_alg - fsverity_hash_algs; + arg.digest_size = hash_alg->digest_size; + + if (copy_to_user(uarg, &arg, sizeof(arg))) + return -EFAULT; + + if (copy_to_user(uarg->digest, vi->measurement, hash_alg->digest_size)) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL_GPL(fsverity_ioctl_measure); diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index d1a5dbf450c4..3b6b8ccebe7d 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -118,6 +118,10 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg); +/* measure.c */ + +extern int fsverity_ioctl_measure(struct file *filp, void __user *arg); + /* open.c */ extern int fsverity_file_open(struct inode *inode, struct file *filp); @@ -145,6 +149,13 @@ static inline int fsverity_ioctl_enable(struct file *filp, return -EOPNOTSUPP; } +/* measure.c */ + +static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + /* open.c */ static inline int fsverity_file_open(struct inode *inode, struct file *filp) -- GitLab From add890c9f9d2d1d79184ded72f23b37b164fc673 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:23 -0700 Subject: [PATCH 2764/7155] fs-verity: add SHA-512 support Add SHA-512 support to fs-verity. This is primarily a demonstration of the trivial changes needed to support a new hash algorithm in fs-verity; most users will still use SHA-256, due to the smaller space required to store the hashes. But some users may prefer SHA-512. Reviewed-by: Theodore Ts'o Reviewed-by: Jaegeuk Kim Signed-off-by: Eric Biggers --- fs/verity/fsverity_private.h | 2 +- fs/verity/hash_algs.c | 5 +++++ include/uapi/linux/fsverity.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index eaa2b3b93bbf..02a547f0667c 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -29,7 +29,7 @@ struct ahash_request; * Largest digest size among all hash algorithms supported by fs-verity. * Currently assumed to be <= size of fsverity_descriptor::root_hash. */ -#define FS_VERITY_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE +#define FS_VERITY_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE /* A hash algorithm supported by fs-verity */ struct fsverity_hash_alg { diff --git a/fs/verity/hash_algs.c b/fs/verity/hash_algs.c index 7df1d67742b8..31e6d7d2389a 100644 --- a/fs/verity/hash_algs.c +++ b/fs/verity/hash_algs.c @@ -17,6 +17,11 @@ struct fsverity_hash_alg fsverity_hash_algs[] = { .digest_size = SHA256_DIGEST_SIZE, .block_size = SHA256_BLOCK_SIZE, }, + [FS_VERITY_HASH_ALG_SHA512] = { + .name = "sha512", + .digest_size = SHA512_DIGEST_SIZE, + .block_size = SHA512_BLOCK_SIZE, + }, }; /** diff --git a/include/uapi/linux/fsverity.h b/include/uapi/linux/fsverity.h index 57d1d7fc0c34..da0daf6c193b 100644 --- a/include/uapi/linux/fsverity.h +++ b/include/uapi/linux/fsverity.h @@ -14,6 +14,7 @@ #include #define FS_VERITY_HASH_ALG_SHA256 1 +#define FS_VERITY_HASH_ALG_SHA512 2 struct fsverity_enable_arg { __u32 version; -- GitLab From 432434c9f8e18cb4cf0fe05bc3eeceada0e10dc6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:23 -0700 Subject: [PATCH 2765/7155] fs-verity: support builtin file signatures To meet some users' needs, add optional support for having fs-verity handle a portion of the authentication policy in the kernel. An ".fs-verity" keyring is created to which X.509 certificates can be added; then a sysctl 'fs.verity.require_signatures' can be set to cause the kernel to enforce that all fs-verity files contain a signature of their file measurement by a key in this keyring. See the "Built-in signature verification" section of Documentation/filesystems/fsverity.rst for the full documentation. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/verity/Kconfig | 17 ++++ fs/verity/Makefile | 2 + fs/verity/enable.c | 20 ++++- fs/verity/fsverity_private.h | 48 ++++++++++- fs/verity/init.c | 6 ++ fs/verity/open.c | 27 ++++-- fs/verity/signature.c | 157 +++++++++++++++++++++++++++++++++++ fs/verity/verify.c | 6 ++ 8 files changed, 269 insertions(+), 14 deletions(-) create mode 100644 fs/verity/signature.c diff --git a/fs/verity/Kconfig b/fs/verity/Kconfig index c2bca0b01ecf..88fb25119899 100644 --- a/fs/verity/Kconfig +++ b/fs/verity/Kconfig @@ -36,3 +36,20 @@ config FS_VERITY_DEBUG Enable debugging messages related to fs-verity by default. Say N unless you are an fs-verity developer. + +config FS_VERITY_BUILTIN_SIGNATURES + bool "FS Verity builtin signature support" + depends on FS_VERITY + select SYSTEM_DATA_VERIFICATION + help + Support verifying signatures of verity files against the X.509 + certificates that have been loaded into the ".fs-verity" + kernel keyring. + + This is meant as a relatively simple mechanism that can be + used to provide an authenticity guarantee for verity files, as + an alternative to IMA appraisal. Userspace programs still + need to check that the verity bit is set in order to get an + authenticity guarantee. + + If unsure, say N. diff --git a/fs/verity/Makefile b/fs/verity/Makefile index 6f7675ae0a31..570e9136334d 100644 --- a/fs/verity/Makefile +++ b/fs/verity/Makefile @@ -6,3 +6,5 @@ obj-$(CONFIG_FS_VERITY) += enable.o \ measure.o \ open.o \ verify.o + +obj-$(CONFIG_FS_VERITY_BUILTIN_SIGNATURES) += signature.o diff --git a/fs/verity/enable.c b/fs/verity/enable.c index df5dab03f0c2..eabc6ac19906 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -161,7 +161,7 @@ static int enable_verity(struct file *filp, const struct fsverity_operations *vops = inode->i_sb->s_vop; struct merkle_tree_params params = { }; struct fsverity_descriptor *desc; - size_t desc_size = sizeof(*desc); + size_t desc_size = sizeof(*desc) + arg->sig_size; struct fsverity_info *vi; int err; @@ -183,6 +183,16 @@ static int enable_verity(struct file *filp, } desc->salt_size = arg->salt_size; + /* Get the signature if the user provided one */ + if (arg->sig_size && + copy_from_user(desc->signature, + (const u8 __user *)(uintptr_t)arg->sig_ptr, + arg->sig_size)) { + err = -EFAULT; + goto out; + } + desc->sig_size = cpu_to_le32(arg->sig_size); + desc->data_size = cpu_to_le64(inode->i_size); /* Prepare the Merkle tree parameters */ @@ -238,6 +248,10 @@ static int enable_verity(struct file *filp, goto rollback; } + if (arg->sig_size) + pr_debug("Storing a %u-byte PKCS#7 signature alongside the file\n", + arg->sig_size); + /* * Tell the filesystem to finish enabling verity on the file. * Serialized with ->begin_enable_verity() by the inode lock. @@ -304,8 +318,8 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg) if (arg.salt_size > FIELD_SIZEOF(struct fsverity_descriptor, salt)) return -EMSGSIZE; - if (arg.sig_size) - return -EINVAL; + if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE) + return -EMSGSIZE; /* * Require a regular file with write access. But the actual fd must diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index 02a547f0667c..e74c79b64d88 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -75,23 +75,41 @@ struct fsverity_info { }; /* - * Merkle tree properties. The file measurement is the hash of this structure. + * Merkle tree properties. The file measurement is the hash of this structure + * excluding the signature and with the sig_size field set to 0. */ struct fsverity_descriptor { __u8 version; /* must be 1 */ __u8 hash_algorithm; /* Merkle tree hash algorithm */ __u8 log_blocksize; /* log2 of size of data and tree blocks */ __u8 salt_size; /* size of salt in bytes; 0 if none */ - __le32 sig_size; /* reserved, must be 0 */ + __le32 sig_size; /* size of signature in bytes; 0 if none */ __le64 data_size; /* size of file the Merkle tree is built over */ __u8 root_hash[64]; /* Merkle tree root hash */ __u8 salt[32]; /* salt prepended to each hashed block */ __u8 __reserved[144]; /* must be 0's */ + __u8 signature[]; /* optional PKCS#7 signature */ }; /* Arbitrary limit to bound the kmalloc() size. Can be changed. */ #define FS_VERITY_MAX_DESCRIPTOR_SIZE 16384 +#define FS_VERITY_MAX_SIGNATURE_SIZE (FS_VERITY_MAX_DESCRIPTOR_SIZE - \ + sizeof(struct fsverity_descriptor)) + +/* + * Format in which verity file measurements are signed. This is the same as + * 'struct fsverity_digest', except here some magic bytes are prepended to + * provide some context about what is being signed in case the same key is used + * for non-fsverity purposes, and here the fields have fixed endianness. + */ +struct fsverity_signed_digest { + char magic[8]; /* must be "FSVerity" */ + __le16 digest_algorithm; + __le16 digest_size; + __u8 digest[]; +}; + /* hash_algs.c */ extern struct fsverity_hash_alg fsverity_hash_algs[]; @@ -127,7 +145,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, const u8 *salt, size_t salt_size); struct fsverity_info *fsverity_create_info(const struct inode *inode, - const void *desc, size_t desc_size); + void *desc, size_t desc_size); void fsverity_set_info(struct inode *inode, struct fsverity_info *vi); @@ -136,8 +154,32 @@ void fsverity_free_info(struct fsverity_info *vi); int __init fsverity_init_info_cache(void); void __init fsverity_exit_info_cache(void); +/* signature.c */ + +#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES +int fsverity_verify_signature(const struct fsverity_info *vi, + const struct fsverity_descriptor *desc, + size_t desc_size); + +int __init fsverity_init_signature(void); +#else /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */ +static inline int +fsverity_verify_signature(const struct fsverity_info *vi, + const struct fsverity_descriptor *desc, + size_t desc_size) +{ + return 0; +} + +static inline int fsverity_init_signature(void) +{ + return 0; +} +#endif /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */ + /* verify.c */ int __init fsverity_init_workqueue(void); +void __init fsverity_exit_workqueue(void); #endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/init.c b/fs/verity/init.c index b593805aafcc..94c104e00861 100644 --- a/fs/verity/init.c +++ b/fs/verity/init.c @@ -45,9 +45,15 @@ static int __init fsverity_init(void) if (err) goto err_exit_info_cache; + err = fsverity_init_signature(); + if (err) + goto err_exit_workqueue; + pr_debug("Initialized fs-verity\n"); return 0; +err_exit_workqueue: + fsverity_exit_workqueue(); err_exit_info_cache: fsverity_exit_info_cache(); return err; diff --git a/fs/verity/open.c b/fs/verity/open.c index 3636a1ed8e2c..63d1004b688c 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -122,22 +122,32 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, return err; } -/* Compute the file measurement by hashing the fsverity_descriptor. */ +/* + * Compute the file measurement by hashing the fsverity_descriptor excluding the + * signature and with the sig_size field set to 0. + */ static int compute_file_measurement(const struct fsverity_hash_alg *hash_alg, - const struct fsverity_descriptor *desc, + struct fsverity_descriptor *desc, u8 *measurement) { - return fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), measurement); + __le32 sig_size = desc->sig_size; + int err; + + desc->sig_size = 0; + err = fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), measurement); + desc->sig_size = sig_size; + + return err; } /* * Validate the given fsverity_descriptor and create a new fsverity_info from - * it. + * it. The signature (if present) is also checked. */ struct fsverity_info *fsverity_create_info(const struct inode *inode, - const void *_desc, size_t desc_size) + void *_desc, size_t desc_size) { - const struct fsverity_descriptor *desc = _desc; + struct fsverity_descriptor *desc = _desc; struct fsverity_info *vi; int err; @@ -153,8 +163,7 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode, return ERR_PTR(-EINVAL); } - if (desc->sig_size || - memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) { + if (memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) { fsverity_err(inode, "Reserved bits set in descriptor"); return ERR_PTR(-EINVAL); } @@ -198,6 +207,8 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode, pr_debug("Computed file measurement: %s:%*phN\n", vi->tree_params.hash_alg->name, vi->tree_params.digest_size, vi->measurement); + + err = fsverity_verify_signature(vi, desc, desc_size); out: if (err) { fsverity_free_info(vi); diff --git a/fs/verity/signature.c b/fs/verity/signature.c new file mode 100644 index 000000000000..c8b255232de5 --- /dev/null +++ b/fs/verity/signature.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/verity/signature.c: verification of builtin signatures + * + * Copyright 2019 Google LLC + */ + +#include "fsverity_private.h" + +#include +#include +#include +#include + +/* + * /proc/sys/fs/verity/require_signatures + * If 1, all verity files must have a valid builtin signature. + */ +static int fsverity_require_signatures; + +/* + * Keyring that contains the trusted X.509 certificates. + * + * Only root (kuid=0) can modify this. Also, root may use + * keyctl_restrict_keyring() to prevent any more additions. + */ +static struct key *fsverity_keyring; + +/** + * fsverity_verify_signature() - check a verity file's signature + * + * If the file's fs-verity descriptor includes a signature of the file + * measurement, verify it against the certificates in the fs-verity keyring. + * + * Return: 0 on success (signature valid or not required); -errno on failure + */ +int fsverity_verify_signature(const struct fsverity_info *vi, + const struct fsverity_descriptor *desc, + size_t desc_size) +{ + const struct inode *inode = vi->inode; + const struct fsverity_hash_alg *hash_alg = vi->tree_params.hash_alg; + const u32 sig_size = le32_to_cpu(desc->sig_size); + struct fsverity_signed_digest *d; + int err; + + if (sig_size == 0) { + if (fsverity_require_signatures) { + fsverity_err(inode, + "require_signatures=1, rejecting unsigned file!"); + return -EPERM; + } + return 0; + } + + if (sig_size > desc_size - sizeof(*desc)) { + fsverity_err(inode, "Signature overflows verity descriptor"); + return -EBADMSG; + } + + d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL); + if (!d) + return -ENOMEM; + memcpy(d->magic, "FSVerity", 8); + d->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs); + d->digest_size = cpu_to_le16(hash_alg->digest_size); + memcpy(d->digest, vi->measurement, hash_alg->digest_size); + + err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size, + desc->signature, sig_size, + fsverity_keyring, + VERIFYING_UNSPECIFIED_SIGNATURE, + NULL, NULL); + kfree(d); + + if (err) { + if (err == -ENOKEY) + fsverity_err(inode, + "File's signing cert isn't in the fs-verity keyring"); + else if (err == -EKEYREJECTED) + fsverity_err(inode, "Incorrect file signature"); + else if (err == -EBADMSG) + fsverity_err(inode, "Malformed file signature"); + else + fsverity_err(inode, "Error %d verifying file signature", + err); + return err; + } + + pr_debug("Valid signature for file measurement %s:%*phN\n", + hash_alg->name, hash_alg->digest_size, vi->measurement); + return 0; +} + +#ifdef CONFIG_SYSCTL +static struct ctl_table_header *fsverity_sysctl_header; + +static const struct ctl_path fsverity_sysctl_path[] = { + { .procname = "fs", }, + { .procname = "verity", }, + { } +}; + +static struct ctl_table fsverity_sysctl_table[] = { + { + .procname = "require_signatures", + .data = &fsverity_require_signatures, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, + { } +}; + +static int __init fsverity_sysctl_init(void) +{ + fsverity_sysctl_header = register_sysctl_paths(fsverity_sysctl_path, + fsverity_sysctl_table); + if (!fsverity_sysctl_header) { + pr_err("sysctl registration failed!\n"); + return -ENOMEM; + } + return 0; +} +#else /* !CONFIG_SYSCTL */ +static inline int __init fsverity_sysctl_init(void) +{ + return 0; +} +#endif /* !CONFIG_SYSCTL */ + +int __init fsverity_init_signature(void) +{ + struct key *ring; + int err; + + ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0), + current_cred(), KEY_POS_SEARCH | + KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | + KEY_USR_SEARCH | KEY_USR_SETATTR, + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + if (IS_ERR(ring)) + return PTR_ERR(ring); + + err = fsverity_sysctl_init(); + if (err) + goto err_put_ring; + + fsverity_keyring = ring; + return 0; + +err_put_ring: + key_put(ring); + return err; +} diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 62ab8f6a8ea1..3e8f2de44667 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -273,3 +273,9 @@ int __init fsverity_init_workqueue(void) return -ENOMEM; return 0; } + +void __init fsverity_exit_workqueue(void) +{ + destroy_workqueue(fsverity_read_workqueue); + fsverity_read_workqueue = NULL; +} -- GitLab From c93d8f88580921c84d2213161ef3c22560511b84 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:24 -0700 Subject: [PATCH 2766/7155] ext4: add basic fs-verity support Add most of fs-verity support to ext4. fs-verity is a filesystem feature that enables transparent integrity protection and authentication of read-only files. It uses a dm-verity like mechanism at the file level: a Merkle tree is used to verify any block in the file in log(filesize) time. It is implemented mainly by helper functions in fs/verity/. See Documentation/filesystems/fsverity.rst for the full documentation. This commit adds all of ext4 fs-verity support except for the actual data verification, including: - Adding a filesystem feature flag and an inode flag for fs-verity. - Implementing the fsverity_operations to support enabling verity on an inode and reading/writing the verity metadata. - Updating ->write_begin(), ->write_end(), and ->writepages() to support writing verity metadata pages. - Calling the fs-verity hooks for ->open(), ->setattr(), and ->ioctl(). ext4 stores the verity metadata (Merkle tree and fsverity_descriptor) past the end of the file, starting at the first 64K boundary beyond i_size. This approach works because (a) verity files are readonly, and (b) pages fully beyond i_size aren't visible to userspace but can be read/written internally by ext4 with only some relatively small changes to ext4. This approach avoids having to depend on the EA_INODE feature and on rearchitecturing ext4's xattr support to support paging multi-gigabyte xattrs into memory, and to support encrypting xattrs. Note that the verity metadata *must* be encrypted when the file is, since it contains hashes of the plaintext data. This patch incorporates work by Theodore Ts'o and Chandan Rajendra. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/ext4/Makefile | 1 + fs/ext4/ext4.h | 21 ++- fs/ext4/file.c | 4 + fs/ext4/inode.c | 53 +++++-- fs/ext4/ioctl.c | 13 ++ fs/ext4/super.c | 9 ++ fs/ext4/sysfs.c | 6 + fs/ext4/verity.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 457 insertions(+), 17 deletions(-) create mode 100644 fs/ext4/verity.c diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index 8fdfcd3c3e04..b17ddc229ac5 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -13,3 +13,4 @@ ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o +ext4-$(CONFIG_FS_VERITY) += verity.o diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index bf660aa7a9e0..736972f46ea6 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -41,6 +41,7 @@ #endif #include +#include #include @@ -395,6 +396,7 @@ struct flex_groups { #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT4_VERITY_FL 0x00100000 /* Verity protected inode */ #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ #define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */ @@ -402,7 +404,7 @@ struct flex_groups { #define EXT4_CASEFOLD_FL 0x40000000 /* Casefolded file */ #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ -#define EXT4_FL_USER_VISIBLE 0x704BDFFF /* User visible flags */ +#define EXT4_FL_USER_VISIBLE 0x705BDFFF /* User visible flags */ #define EXT4_FL_USER_MODIFIABLE 0x604BC0FF /* User modifiable flags */ /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */ @@ -467,6 +469,7 @@ enum { EXT4_INODE_TOPDIR = 17, /* Top of directory hierarchies*/ EXT4_INODE_HUGE_FILE = 18, /* Set to each huge file */ EXT4_INODE_EXTENTS = 19, /* Inode uses extents */ + EXT4_INODE_VERITY = 20, /* Verity protected inode */ EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */ EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */ EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */ @@ -512,6 +515,7 @@ static inline void ext4_check_flag_values(void) CHECK_FLAG_VALUE(TOPDIR); CHECK_FLAG_VALUE(HUGE_FILE); CHECK_FLAG_VALUE(EXTENTS); + CHECK_FLAG_VALUE(VERITY); CHECK_FLAG_VALUE(EA_INODE); CHECK_FLAG_VALUE(EOFBLOCKS); CHECK_FLAG_VALUE(INLINE_DATA); @@ -1560,6 +1564,7 @@ enum { EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ EXT4_STATE_EXT_PRECACHED, /* extents have been precached */ EXT4_STATE_LUSTRE_EA_INODE, /* Lustre-style ea_inode */ + EXT4_STATE_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ }; #define EXT4_INODE_BIT_FNS(name, field, offset) \ @@ -1610,6 +1615,12 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) #define EXT4_SB(sb) (sb) #endif +static inline bool ext4_verity_in_progress(struct inode *inode) +{ + return IS_ENABLED(CONFIG_FS_VERITY) && + ext4_test_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); +} + #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime /* @@ -1662,6 +1673,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 #define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000 #define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000 +#define EXT4_FEATURE_RO_COMPAT_VERITY 0x8000 #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 @@ -1756,6 +1768,7 @@ EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc, BIGALLOC) EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum, METADATA_CSUM) EXT4_FEATURE_RO_COMPAT_FUNCS(readonly, READONLY) EXT4_FEATURE_RO_COMPAT_FUNCS(project, PROJECT) +EXT4_FEATURE_RO_COMPAT_FUNCS(verity, VERITY) EXT4_FEATURE_INCOMPAT_FUNCS(compression, COMPRESSION) EXT4_FEATURE_INCOMPAT_FUNCS(filetype, FILETYPE) @@ -1813,7 +1826,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold, CASEFOLD) EXT4_FEATURE_RO_COMPAT_BIGALLOC |\ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ EXT4_FEATURE_RO_COMPAT_QUOTA |\ - EXT4_FEATURE_RO_COMPAT_PROJECT) + EXT4_FEATURE_RO_COMPAT_PROJECT |\ + EXT4_FEATURE_RO_COMPAT_VERITY) #define EXTN_FEATURE_FUNCS(ver) \ static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \ @@ -3283,6 +3297,9 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io, /* mmp.c */ extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); +/* verity.c */ +extern const struct fsverity_operations ext4_verityops; + /* * Add new method to test whether block and inode bitmaps are properly * initialized. With uninit_bg reading the block from disk is not enough diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 70b0438dbc94..b8a20bb9a145 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -457,6 +457,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp) if (ret) return ret; + ret = fsverity_file_open(inode, filp); + if (ret) + return ret; + /* * Set up the jbd2_inode if we are opening the inode for * writing and the journal is present diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 420fe3deed39..6de3d4ba28f3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1340,6 +1340,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, } if (ret) { + bool extended = (pos + len > inode->i_size) && + !ext4_verity_in_progress(inode); + unlock_page(page); /* * __block_write_begin may have instantiated a few blocks @@ -1349,11 +1352,11 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, * Add inode to orphan list in case we crash before * truncate finishes */ - if (pos + len > inode->i_size && ext4_can_truncate(inode)) + if (extended && ext4_can_truncate(inode)) ext4_orphan_add(handle, inode); ext4_journal_stop(handle); - if (pos + len > inode->i_size) { + if (extended) { ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might @@ -1406,6 +1409,7 @@ static int ext4_write_end(struct file *file, int ret = 0, ret2; int i_size_changed = 0; int inline_data = ext4_has_inline_data(inode); + bool verity = ext4_verity_in_progress(inode); trace_ext4_write_end(inode, pos, len, copied); if (inline_data) { @@ -1423,12 +1427,16 @@ static int ext4_write_end(struct file *file, /* * it's important to update i_size while still holding page lock: * page writeout could otherwise come in and zero beyond i_size. + * + * If FS_IOC_ENABLE_VERITY is running on this inode, then Merkle tree + * blocks are being written past EOF, so skip the i_size update. */ - i_size_changed = ext4_update_inode_size(inode, pos + copied); + if (!verity) + i_size_changed = ext4_update_inode_size(inode, pos + copied); unlock_page(page); put_page(page); - if (old_size < pos) + if (old_size < pos && !verity) pagecache_isize_extended(inode, old_size, pos); /* * Don't mark the inode dirty under page lock. First, it unnecessarily @@ -1439,7 +1447,7 @@ static int ext4_write_end(struct file *file, if (i_size_changed || inline_data) ext4_mark_inode_dirty(handle, inode); - if (pos + len > inode->i_size && ext4_can_truncate(inode)) + if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) /* if we have allocated more blocks and copied * less. We will have blocks allocated outside * inode->i_size. So truncate them @@ -1450,7 +1458,7 @@ static int ext4_write_end(struct file *file, if (!ret) ret = ret2; - if (pos + len > inode->i_size) { + if (pos + len > inode->i_size && !verity) { ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be @@ -1511,6 +1519,7 @@ static int ext4_journalled_write_end(struct file *file, unsigned from, to; int size_changed = 0; int inline_data = ext4_has_inline_data(inode); + bool verity = ext4_verity_in_progress(inode); trace_ext4_journalled_write_end(inode, pos, len, copied); from = pos & (PAGE_SIZE - 1); @@ -1540,13 +1549,14 @@ static int ext4_journalled_write_end(struct file *file, if (!partial) SetPageUptodate(page); } - size_changed = ext4_update_inode_size(inode, pos + copied); + if (!verity) + size_changed = ext4_update_inode_size(inode, pos + copied); ext4_set_inode_state(inode, EXT4_STATE_JDATA); EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; unlock_page(page); put_page(page); - if (old_size < pos) + if (old_size < pos && !verity) pagecache_isize_extended(inode, old_size, pos); if (size_changed || inline_data) { @@ -1555,7 +1565,7 @@ static int ext4_journalled_write_end(struct file *file, ret = ret2; } - if (pos + len > inode->i_size && ext4_can_truncate(inode)) + if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) /* if we have allocated more blocks and copied * less. We will have blocks allocated outside * inode->i_size. So truncate them @@ -1566,7 +1576,7 @@ static int ext4_journalled_write_end(struct file *file, ret2 = ext4_journal_stop(handle); if (!ret) ret = ret2; - if (pos + len > inode->i_size) { + if (pos + len > inode->i_size && !verity) { ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be @@ -2162,7 +2172,8 @@ static int ext4_writepage(struct page *page, trace_ext4_writepage(page); size = i_size_read(inode); - if (page->index == size >> PAGE_SHIFT) + if (page->index == size >> PAGE_SHIFT && + !ext4_verity_in_progress(inode)) len = size & ~PAGE_MASK; else len = PAGE_SIZE; @@ -2246,7 +2257,8 @@ static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) * after page tables are updated. */ size = i_size_read(mpd->inode); - if (page->index == size >> PAGE_SHIFT) + if (page->index == size >> PAGE_SHIFT && + !ext4_verity_in_progress(mpd->inode)) len = size & ~PAGE_MASK; else len = PAGE_SIZE; @@ -2345,6 +2357,9 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd, ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1) >> inode->i_blkbits; + if (ext4_verity_in_progress(inode)) + blocks = EXT_MAX_BLOCKS; + do { BUG_ON(buffer_locked(bh)); @@ -3061,8 +3076,8 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, index = pos >> PAGE_SHIFT; - if (ext4_nonda_switch(inode->i_sb) || - S_ISLNK(inode->i_mode)) { + if (ext4_nonda_switch(inode->i_sb) || S_ISLNK(inode->i_mode) || + ext4_verity_in_progress(inode)) { *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; return ext4_write_begin(file, mapping, pos, len, flags, pagep, fsdata); @@ -4739,6 +4754,8 @@ static bool ext4_should_use_dax(struct inode *inode) return false; if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT)) return false; + if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY)) + return false; return true; } @@ -4763,9 +4780,11 @@ void ext4_set_inode_flags(struct inode *inode) new_fl |= S_ENCRYPTED; if (flags & EXT4_CASEFOLD_FL) new_fl |= S_CASEFOLD; + if (flags & EXT4_VERITY_FL) + new_fl |= S_VERITY; inode_set_flags(inode, new_fl, S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX| - S_ENCRYPTED|S_CASEFOLD); + S_ENCRYPTED|S_CASEFOLD|S_VERITY); } static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, @@ -5555,6 +5574,10 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) if (error) return error; + error = fsverity_prepare_setattr(dentry, attr); + if (error) + return error; + if (is_quota_modification(inode, attr)) { error = dquot_initialize(inode); if (error) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 442f7ef873fc..ce811df71690 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -1171,6 +1171,17 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } case EXT4_IOC_SHUTDOWN: return ext4_shutdown(sb, arg); + + case FS_IOC_ENABLE_VERITY: + if (!ext4_has_feature_verity(sb)) + return -EOPNOTSUPP; + return fsverity_ioctl_enable(filp, (const void __user *)arg); + + case FS_IOC_MEASURE_VERITY: + if (!ext4_has_feature_verity(sb)) + return -EOPNOTSUPP; + return fsverity_ioctl_measure(filp, (void __user *)arg); + default: return -ENOTTY; } @@ -1233,6 +1244,8 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EXT4_IOC_GET_ENCRYPTION_POLICY: case EXT4_IOC_SHUTDOWN: case FS_IOC_GETFSMAP: + case FS_IOC_ENABLE_VERITY: + case FS_IOC_MEASURE_VERITY: break; default: return -ENOIOCTLCMD; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4079605d437a..05a9874687c3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1179,6 +1179,7 @@ void ext4_clear_inode(struct inode *inode) EXT4_I(inode)->jinode = NULL; } fscrypt_put_encryption_info(inode); + fsverity_cleanup_inode(inode); } static struct inode *ext4_nfs_get_inode(struct super_block *sb, @@ -4272,6 +4273,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_FS_ENCRYPTION sb->s_cop = &ext4_cryptops; #endif +#ifdef CONFIG_FS_VERITY + sb->s_vop = &ext4_verityops; +#endif #ifdef CONFIG_QUOTA sb->dq_op = &ext4_quota_operations; if (ext4_has_feature_quota(sb)) @@ -4419,6 +4423,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount_wq; } + if (ext4_has_feature_verity(sb) && blocksize != PAGE_SIZE) { + ext4_msg(sb, KERN_ERR, "Unsupported blocksize for fs-verity"); + goto failed_mount_wq; + } + if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) && !ext4_has_feature_encrypt(sb)) { ext4_set_feature_encrypt(sb); diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c index b3cd7655a6ff..eb1efad0e20a 100644 --- a/fs/ext4/sysfs.c +++ b/fs/ext4/sysfs.c @@ -242,6 +242,9 @@ EXT4_ATTR_FEATURE(encryption); #ifdef CONFIG_UNICODE EXT4_ATTR_FEATURE(casefold); #endif +#ifdef CONFIG_FS_VERITY +EXT4_ATTR_FEATURE(verity); +#endif EXT4_ATTR_FEATURE(metadata_csum_seed); static struct attribute *ext4_feat_attrs[] = { @@ -253,6 +256,9 @@ static struct attribute *ext4_feat_attrs[] = { #endif #ifdef CONFIG_UNICODE ATTR_LIST(casefold), +#endif +#ifdef CONFIG_FS_VERITY + ATTR_LIST(verity), #endif ATTR_LIST(metadata_csum_seed), NULL, diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c new file mode 100644 index 000000000000..d0d8a9795dd6 --- /dev/null +++ b/fs/ext4/verity.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/ext4/verity.c: fs-verity support for ext4 + * + * Copyright 2019 Google LLC + */ + +/* + * Implementation of fsverity_operations for ext4. + * + * ext4 stores the verity metadata (Merkle tree and fsverity_descriptor) past + * the end of the file, starting at the first 64K boundary beyond i_size. This + * approach works because (a) verity files are readonly, and (b) pages fully + * beyond i_size aren't visible to userspace but can be read/written internally + * by ext4 with only some relatively small changes to ext4. This approach + * avoids having to depend on the EA_INODE feature and on rearchitecturing + * ext4's xattr support to support paging multi-gigabyte xattrs into memory, and + * to support encrypting xattrs. Note that the verity metadata *must* be + * encrypted when the file is, since it contains hashes of the plaintext data. + * + * Using a 64K boundary rather than a 4K one keeps things ready for + * architectures with 64K pages, and it doesn't necessarily waste space on-disk + * since there can be a hole between i_size and the start of the Merkle tree. + */ + +#include + +#include "ext4.h" +#include "ext4_extents.h" +#include "ext4_jbd2.h" + +static inline loff_t ext4_verity_metadata_pos(const struct inode *inode) +{ + return round_up(inode->i_size, 65536); +} + +/* + * Read some verity metadata from the inode. __vfs_read() can't be used because + * we need to read beyond i_size. + */ +static int pagecache_read(struct inode *inode, void *buf, size_t count, + loff_t pos) +{ + while (count) { + size_t n = min_t(size_t, count, + PAGE_SIZE - offset_in_page(pos)); + struct page *page; + void *addr; + + page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT, + NULL); + if (IS_ERR(page)) + return PTR_ERR(page); + + addr = kmap_atomic(page); + memcpy(buf, addr + offset_in_page(pos), n); + kunmap_atomic(addr); + + put_page(page); + + buf += n; + pos += n; + count -= n; + } + return 0; +} + +/* + * Write some verity metadata to the inode for FS_IOC_ENABLE_VERITY. + * kernel_write() can't be used because the file descriptor is readonly. + */ +static int pagecache_write(struct inode *inode, const void *buf, size_t count, + loff_t pos) +{ + if (pos + count > inode->i_sb->s_maxbytes) + return -EFBIG; + + while (count) { + size_t n = min_t(size_t, count, + PAGE_SIZE - offset_in_page(pos)); + struct page *page; + void *fsdata; + void *addr; + int res; + + res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0, + &page, &fsdata); + if (res) + return res; + + addr = kmap_atomic(page); + memcpy(addr + offset_in_page(pos), buf, n); + kunmap_atomic(addr); + + res = pagecache_write_end(NULL, inode->i_mapping, pos, n, n, + page, fsdata); + if (res < 0) + return res; + if (res != n) + return -EIO; + + buf += n; + pos += n; + count -= n; + } + return 0; +} + +static int ext4_begin_enable_verity(struct file *filp) +{ + struct inode *inode = file_inode(filp); + const int credits = 2; /* superblock and inode for ext4_orphan_add() */ + handle_t *handle; + int err; + + if (ext4_verity_in_progress(inode)) + return -EBUSY; + + /* + * Since the file was opened readonly, we have to initialize the jbd + * inode and quotas here and not rely on ->open() doing it. This must + * be done before evicting the inline data. + */ + + err = ext4_inode_attach_jinode(inode); + if (err) + return err; + + err = dquot_initialize(inode); + if (err) + return err; + + err = ext4_convert_inline_data(inode); + if (err) + return err; + + if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { + ext4_warning_inode(inode, + "verity is only allowed on extent-based files"); + return -EOPNOTSUPP; + } + + /* + * ext4 uses the last allocated block to find the verity descriptor, so + * we must remove any other blocks past EOF which might confuse things. + */ + err = ext4_truncate(inode); + if (err) + return err; + + handle = ext4_journal_start(inode, EXT4_HT_INODE, credits); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + err = ext4_orphan_add(handle, inode); + if (err == 0) + ext4_set_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); + + ext4_journal_stop(handle); + return err; +} + +/* + * ext4 stores the verity descriptor beginning on the next filesystem block + * boundary after the Merkle tree. Then, the descriptor size is stored in the + * last 4 bytes of the last allocated filesystem block --- which is either the + * block in which the descriptor ends, or the next block after that if there + * weren't at least 4 bytes remaining. + * + * We can't simply store the descriptor in an xattr because it *must* be + * encrypted when ext4 encryption is used, but ext4 encryption doesn't encrypt + * xattrs. Also, if the descriptor includes a large signature blob it may be + * too large to store in an xattr without the EA_INODE feature. + */ +static int ext4_write_verity_descriptor(struct inode *inode, const void *desc, + size_t desc_size, u64 merkle_tree_size) +{ + const u64 desc_pos = round_up(ext4_verity_metadata_pos(inode) + + merkle_tree_size, i_blocksize(inode)); + const u64 desc_end = desc_pos + desc_size; + const __le32 desc_size_disk = cpu_to_le32(desc_size); + const u64 desc_size_pos = round_up(desc_end + sizeof(desc_size_disk), + i_blocksize(inode)) - + sizeof(desc_size_disk); + int err; + + err = pagecache_write(inode, desc, desc_size, desc_pos); + if (err) + return err; + + return pagecache_write(inode, &desc_size_disk, sizeof(desc_size_disk), + desc_size_pos); +} + +static int ext4_end_enable_verity(struct file *filp, const void *desc, + size_t desc_size, u64 merkle_tree_size) +{ + struct inode *inode = file_inode(filp); + const int credits = 2; /* superblock and inode for ext4_orphan_del() */ + handle_t *handle; + int err = 0; + int err2; + + if (desc != NULL) { + /* Succeeded; write the verity descriptor. */ + err = ext4_write_verity_descriptor(inode, desc, desc_size, + merkle_tree_size); + + /* Write all pages before clearing VERITY_IN_PROGRESS. */ + if (!err) + err = filemap_write_and_wait(inode->i_mapping); + } + + /* If we failed, truncate anything we wrote past i_size. */ + if (desc == NULL || err) + ext4_truncate(inode); + + /* + * We must always clean up by clearing EXT4_STATE_VERITY_IN_PROGRESS and + * deleting the inode from the orphan list, even if something failed. + * If everything succeeded, we'll also set the verity bit in the same + * transaction. + */ + + ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); + + handle = ext4_journal_start(inode, EXT4_HT_INODE, credits); + if (IS_ERR(handle)) { + ext4_orphan_del(NULL, inode); + return PTR_ERR(handle); + } + + err2 = ext4_orphan_del(handle, inode); + if (err2) + goto out_stop; + + if (desc != NULL && !err) { + struct ext4_iloc iloc; + + err = ext4_reserve_inode_write(handle, inode, &iloc); + if (err) + goto out_stop; + ext4_set_inode_flag(inode, EXT4_INODE_VERITY); + ext4_set_inode_flags(inode); + err = ext4_mark_iloc_dirty(handle, inode, &iloc); + } +out_stop: + ext4_journal_stop(handle); + return err ?: err2; +} + +static int ext4_get_verity_descriptor_location(struct inode *inode, + size_t *desc_size_ret, + u64 *desc_pos_ret) +{ + struct ext4_ext_path *path; + struct ext4_extent *last_extent; + u32 end_lblk; + u64 desc_size_pos; + __le32 desc_size_disk; + u32 desc_size; + u64 desc_pos; + int err; + + /* + * Descriptor size is in last 4 bytes of last allocated block. + * See ext4_write_verity_descriptor(). + */ + + if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { + EXT4_ERROR_INODE(inode, "verity file doesn't use extents"); + return -EFSCORRUPTED; + } + + path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0); + if (IS_ERR(path)) + return PTR_ERR(path); + + last_extent = path[path->p_depth].p_ext; + if (!last_extent) { + EXT4_ERROR_INODE(inode, "verity file has no extents"); + ext4_ext_drop_refs(path); + kfree(path); + return -EFSCORRUPTED; + } + + end_lblk = le32_to_cpu(last_extent->ee_block) + + ext4_ext_get_actual_len(last_extent); + desc_size_pos = (u64)end_lblk << inode->i_blkbits; + ext4_ext_drop_refs(path); + kfree(path); + + if (desc_size_pos < sizeof(desc_size_disk)) + goto bad; + desc_size_pos -= sizeof(desc_size_disk); + + err = pagecache_read(inode, &desc_size_disk, sizeof(desc_size_disk), + desc_size_pos); + if (err) + return err; + desc_size = le32_to_cpu(desc_size_disk); + + /* + * The descriptor is stored just before the desc_size_disk, but starting + * on a filesystem block boundary. + */ + + if (desc_size > INT_MAX || desc_size > desc_size_pos) + goto bad; + + desc_pos = round_down(desc_size_pos - desc_size, i_blocksize(inode)); + if (desc_pos < ext4_verity_metadata_pos(inode)) + goto bad; + + *desc_size_ret = desc_size; + *desc_pos_ret = desc_pos; + return 0; + +bad: + EXT4_ERROR_INODE(inode, "verity file corrupted; can't find descriptor"); + return -EFSCORRUPTED; +} + +static int ext4_get_verity_descriptor(struct inode *inode, void *buf, + size_t buf_size) +{ + size_t desc_size = 0; + u64 desc_pos = 0; + int err; + + err = ext4_get_verity_descriptor_location(inode, &desc_size, &desc_pos); + if (err) + return err; + + if (buf_size) { + if (desc_size > buf_size) + return -ERANGE; + err = pagecache_read(inode, buf, desc_size, desc_pos); + if (err) + return err; + } + return desc_size; +} + +static struct page *ext4_read_merkle_tree_page(struct inode *inode, + pgoff_t index) +{ + index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT; + + return read_mapping_page(inode->i_mapping, index, NULL); +} + +static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf, + u64 index, int log_blocksize) +{ + loff_t pos = ext4_verity_metadata_pos(inode) + (index << log_blocksize); + + return pagecache_write(inode, buf, 1 << log_blocksize, pos); +} + +const struct fsverity_operations ext4_verityops = { + .begin_enable_verity = ext4_begin_enable_verity, + .end_enable_verity = ext4_end_enable_verity, + .get_verity_descriptor = ext4_get_verity_descriptor, + .read_merkle_tree_page = ext4_read_merkle_tree_page, + .write_merkle_tree_block = ext4_write_merkle_tree_block, +}; -- GitLab From 22cfe4b48ccb5a3dbb92d6dcb88f396e0f400f74 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:24 -0700 Subject: [PATCH 2767/7155] ext4: add fs-verity read support Make ext4_mpage_readpages() verify data as it is read from fs-verity files, using the helper functions from fs/verity/. To support both encryption and verity simultaneously, this required refactoring the decryption workflow into a generic "post-read processing" workflow which can do decryption, verification, or both. The case where the ext4 block size is not equal to the PAGE_SIZE is not supported yet, since in that case ext4_mpage_readpages() sometimes falls back to block_read_full_page(), which does not support fs-verity yet. Co-developed-by: Theodore Ts'o Signed-off-by: Theodore Ts'o Signed-off-by: Eric Biggers --- fs/ext4/ext4.h | 2 + fs/ext4/inode.c | 2 + fs/ext4/readpage.c | 211 +++++++++++++++++++++++++++++++++++++-------- fs/ext4/super.c | 9 +- 4 files changed, 188 insertions(+), 36 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 736972f46ea6..9c7f4036021b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -3191,6 +3191,8 @@ static inline void ext4_set_de_type(struct super_block *sb, extern int ext4_mpage_readpages(struct address_space *mapping, struct list_head *pages, struct page *page, unsigned nr_pages, bool is_readahead); +extern int __init ext4_init_post_read_processing(void); +extern void ext4_exit_post_read_processing(void); /* symlink.c */ extern const struct inode_operations ext4_encrypted_symlink_inode_operations; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6de3d4ba28f3..cf0fce1173a4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3912,6 +3912,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) return 0; #endif + if (fsverity_active(inode)) + return 0; /* * If we are doing data journalling we don't support O_DIRECT diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index c916017db334..a30b203fa461 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -47,13 +47,103 @@ #include "ext4.h" -static inline bool ext4_bio_encrypted(struct bio *bio) +#define NUM_PREALLOC_POST_READ_CTXS 128 + +static struct kmem_cache *bio_post_read_ctx_cache; +static mempool_t *bio_post_read_ctx_pool; + +/* postprocessing steps for read bios */ +enum bio_post_read_step { + STEP_INITIAL = 0, + STEP_DECRYPT, + STEP_VERITY, +}; + +struct bio_post_read_ctx { + struct bio *bio; + struct work_struct work; + unsigned int cur_step; + unsigned int enabled_steps; +}; + +static void __read_end_io(struct bio *bio) { -#ifdef CONFIG_FS_ENCRYPTION - return unlikely(bio->bi_private != NULL); -#else - return false; -#endif + struct page *page; + struct bio_vec *bv; + struct bvec_iter_all iter_all; + + bio_for_each_segment_all(bv, bio, iter_all) { + page = bv->bv_page; + + /* PG_error was set if any post_read step failed */ + if (bio->bi_status || PageError(page)) { + ClearPageUptodate(page); + /* will re-read again later */ + ClearPageError(page); + } else { + SetPageUptodate(page); + } + unlock_page(page); + } + if (bio->bi_private) + mempool_free(bio->bi_private, bio_post_read_ctx_pool); + bio_put(bio); +} + +static void bio_post_read_processing(struct bio_post_read_ctx *ctx); + +static void decrypt_work(struct work_struct *work) +{ + struct bio_post_read_ctx *ctx = + container_of(work, struct bio_post_read_ctx, work); + + fscrypt_decrypt_bio(ctx->bio); + + bio_post_read_processing(ctx); +} + +static void verity_work(struct work_struct *work) +{ + struct bio_post_read_ctx *ctx = + container_of(work, struct bio_post_read_ctx, work); + + fsverity_verify_bio(ctx->bio); + + bio_post_read_processing(ctx); +} + +static void bio_post_read_processing(struct bio_post_read_ctx *ctx) +{ + /* + * We use different work queues for decryption and for verity because + * verity may require reading metadata pages that need decryption, and + * we shouldn't recurse to the same workqueue. + */ + switch (++ctx->cur_step) { + case STEP_DECRYPT: + if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { + INIT_WORK(&ctx->work, decrypt_work); + fscrypt_enqueue_decrypt_work(&ctx->work); + return; + } + ctx->cur_step++; + /* fall-through */ + case STEP_VERITY: + if (ctx->enabled_steps & (1 << STEP_VERITY)) { + INIT_WORK(&ctx->work, verity_work); + fsverity_enqueue_verify_work(&ctx->work); + return; + } + ctx->cur_step++; + /* fall-through */ + default: + __read_end_io(ctx->bio); + } +} + +static bool bio_post_read_required(struct bio *bio) +{ + return bio->bi_private && !bio->bi_status; } /* @@ -70,30 +160,53 @@ static inline bool ext4_bio_encrypted(struct bio *bio) */ static void mpage_end_io(struct bio *bio) { - struct bio_vec *bv; - struct bvec_iter_all iter_all; + if (bio_post_read_required(bio)) { + struct bio_post_read_ctx *ctx = bio->bi_private; - if (ext4_bio_encrypted(bio)) { - if (bio->bi_status) { - fscrypt_release_ctx(bio->bi_private); - } else { - fscrypt_enqueue_decrypt_bio(bio->bi_private, bio); - return; - } + ctx->cur_step = STEP_INITIAL; + bio_post_read_processing(ctx); + return; } - bio_for_each_segment_all(bv, bio, iter_all) { - struct page *page = bv->bv_page; + __read_end_io(bio); +} - if (!bio->bi_status) { - SetPageUptodate(page); - } else { - ClearPageUptodate(page); - SetPageError(page); - } - unlock_page(page); +static inline bool ext4_need_verity(const struct inode *inode, pgoff_t idx) +{ + return fsverity_active(inode) && + idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE); +} + +static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode, + struct bio *bio, + pgoff_t first_idx) +{ + unsigned int post_read_steps = 0; + struct bio_post_read_ctx *ctx = NULL; + + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) + post_read_steps |= 1 << STEP_DECRYPT; + + if (ext4_need_verity(inode, first_idx)) + post_read_steps |= 1 << STEP_VERITY; + + if (post_read_steps) { + ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); + if (!ctx) + return ERR_PTR(-ENOMEM); + ctx->bio = bio; + ctx->enabled_steps = post_read_steps; + bio->bi_private = ctx; } + return ctx; +} - bio_put(bio); +static inline loff_t ext4_readpage_limit(struct inode *inode) +{ + if (IS_ENABLED(CONFIG_FS_VERITY) && + (IS_VERITY(inode) || ext4_verity_in_progress(inode))) + return inode->i_sb->s_maxbytes; + + return i_size_read(inode); } int ext4_mpage_readpages(struct address_space *mapping, @@ -141,7 +254,8 @@ int ext4_mpage_readpages(struct address_space *mapping, block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); last_block = block_in_file + nr_pages * blocks_per_page; - last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits; + last_block_in_file = (ext4_readpage_limit(inode) + + blocksize - 1) >> blkbits; if (last_block > last_block_in_file) last_block = last_block_in_file; page_block = 0; @@ -218,6 +332,9 @@ int ext4_mpage_readpages(struct address_space *mapping, zero_user_segment(page, first_hole << blkbits, PAGE_SIZE); if (first_hole == 0) { + if (ext4_need_verity(inode, page->index) && + !fsverity_verify_page(page)) + goto set_error_page; SetPageUptodate(page); unlock_page(page); goto next_page; @@ -241,18 +358,16 @@ int ext4_mpage_readpages(struct address_space *mapping, bio = NULL; } if (bio == NULL) { - struct fscrypt_ctx *ctx = NULL; + struct bio_post_read_ctx *ctx; - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) { - ctx = fscrypt_get_ctx(GFP_NOFS); - if (IS_ERR(ctx)) - goto set_error_page; - } bio = bio_alloc(GFP_KERNEL, min_t(int, nr_pages, BIO_MAX_PAGES)); - if (!bio) { - if (ctx) - fscrypt_release_ctx(ctx); + if (!bio) + goto set_error_page; + ctx = get_bio_post_read_ctx(inode, bio, page->index); + if (IS_ERR(ctx)) { + bio_put(bio); + bio = NULL; goto set_error_page; } bio_set_dev(bio, bdev); @@ -293,3 +408,29 @@ int ext4_mpage_readpages(struct address_space *mapping, submit_bio(bio); return 0; } + +int __init ext4_init_post_read_processing(void) +{ + bio_post_read_ctx_cache = + kmem_cache_create("ext4_bio_post_read_ctx", + sizeof(struct bio_post_read_ctx), 0, 0, NULL); + if (!bio_post_read_ctx_cache) + goto fail; + bio_post_read_ctx_pool = + mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, + bio_post_read_ctx_cache); + if (!bio_post_read_ctx_pool) + goto fail_free_cache; + return 0; + +fail_free_cache: + kmem_cache_destroy(bio_post_read_ctx_cache); +fail: + return -ENOMEM; +} + +void ext4_exit_post_read_processing(void) +{ + mempool_destroy(bio_post_read_ctx_pool); + kmem_cache_destroy(bio_post_read_ctx_cache); +} diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 05a9874687c3..23e7acd43e4e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -6103,6 +6103,10 @@ static int __init ext4_init_fs(void) return err; err = ext4_init_pending(); + if (err) + goto out7; + + err = ext4_init_post_read_processing(); if (err) goto out6; @@ -6144,8 +6148,10 @@ static int __init ext4_init_fs(void) out4: ext4_exit_pageio(); out5: - ext4_exit_pending(); + ext4_exit_post_read_processing(); out6: + ext4_exit_pending(); +out7: ext4_exit_es(); return err; @@ -6162,6 +6168,7 @@ static void __exit ext4_exit_fs(void) ext4_exit_sysfs(); ext4_exit_system_zone(); ext4_exit_pageio(); + ext4_exit_post_read_processing(); ext4_exit_es(); ext4_exit_pending(); } -- GitLab From 84fb7ca4b3f864782cb1e66e60b04d4ea1d2930b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:24 -0700 Subject: [PATCH 2768/7155] ext4: update on-disk format documentation for fs-verity Document the format of verity files on ext4, and the corresponding inode and superblock flags. Reviewed-by: Theodore Ts'o Signed-off-by: Eric Biggers --- Documentation/filesystems/ext4/inodes.rst | 6 ++- Documentation/filesystems/ext4/overview.rst | 1 + Documentation/filesystems/ext4/super.rst | 2 + Documentation/filesystems/ext4/verity.rst | 41 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/ext4/verity.rst diff --git a/Documentation/filesystems/ext4/inodes.rst b/Documentation/filesystems/ext4/inodes.rst index 6bd35e506b6f..e851e6ca31fa 100644 --- a/Documentation/filesystems/ext4/inodes.rst +++ b/Documentation/filesystems/ext4/inodes.rst @@ -277,6 +277,8 @@ The ``i_flags`` field is a combination of these values: - This is a huge file (EXT4\_HUGE\_FILE\_FL). * - 0x80000 - Inode uses extents (EXT4\_EXTENTS\_FL). + * - 0x100000 + - Verity protected file (EXT4\_VERITY\_FL). * - 0x200000 - Inode stores a large extended attribute value in its data blocks (EXT4\_EA\_INODE\_FL). @@ -299,9 +301,9 @@ The ``i_flags`` field is a combination of these values: - Reserved for ext4 library (EXT4\_RESERVED\_FL). * - - Aggregate flags: - * - 0x4BDFFF + * - 0x705BDFFF - User-visible flags. - * - 0x4B80FF + * - 0x604BC0FF - User-modifiable flags. Note that while EXT4\_JOURNAL\_DATA\_FL and EXT4\_EXTENTS\_FL can be set with setattr, they are not in the kernel's EXT4\_FL\_USER\_MODIFIABLE mask, since it needs to handle the setting of diff --git a/Documentation/filesystems/ext4/overview.rst b/Documentation/filesystems/ext4/overview.rst index cbab18baba12..123ebfde47ee 100644 --- a/Documentation/filesystems/ext4/overview.rst +++ b/Documentation/filesystems/ext4/overview.rst @@ -24,3 +24,4 @@ order. .. include:: bigalloc.rst .. include:: inlinedata.rst .. include:: eainode.rst +.. include:: verity.rst diff --git a/Documentation/filesystems/ext4/super.rst b/Documentation/filesystems/ext4/super.rst index 04ff079a2acf..6eae92054827 100644 --- a/Documentation/filesystems/ext4/super.rst +++ b/Documentation/filesystems/ext4/super.rst @@ -696,6 +696,8 @@ the following: (RO\_COMPAT\_READONLY) * - 0x2000 - Filesystem tracks project quotas. (RO\_COMPAT\_PROJECT) + * - 0x8000 + - Verity inodes may be present on the filesystem. (RO\_COMPAT\_VERITY) .. _super_def_hash: diff --git a/Documentation/filesystems/ext4/verity.rst b/Documentation/filesystems/ext4/verity.rst new file mode 100644 index 000000000000..3e4c0ee0e068 --- /dev/null +++ b/Documentation/filesystems/ext4/verity.rst @@ -0,0 +1,41 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Verity files +------------ + +ext4 supports fs-verity, which is a filesystem feature that provides +Merkle tree based hashing for individual readonly files. Most of +fs-verity is common to all filesystems that support it; see +:ref:`Documentation/filesystems/fsverity.rst ` for the +fs-verity documentation. However, the on-disk layout of the verity +metadata is filesystem-specific. On ext4, the verity metadata is +stored after the end of the file data itself, in the following format: + +- Zero-padding to the next 65536-byte boundary. This padding need not + actually be allocated on-disk, i.e. it may be a hole. + +- The Merkle tree, as documented in + :ref:`Documentation/filesystems/fsverity.rst + `, with the tree levels stored in order from + root to leaf, and the tree blocks within each level stored in their + natural order. + +- Zero-padding to the next filesystem block boundary. + +- The verity descriptor, as documented in + :ref:`Documentation/filesystems/fsverity.rst `, + with optionally appended signature blob. + +- Zero-padding to the next offset that is 4 bytes before a filesystem + block boundary. + +- The size of the verity descriptor in bytes, as a 4-byte little + endian integer. + +Verity inodes have EXT4_VERITY_FL set, and they must use extents, i.e. +EXT4_EXTENTS_FL must be set and EXT4_INLINE_DATA_FL must be clear. +They can have EXT4_ENCRYPT_FL set, in which case the verity metadata +is encrypted as well as the data itself. + +Verity files cannot have blocks allocated past the end of the verity +metadata. -- GitLab From 95ae251fe82838b85c6d37e5a1775006e2a42ae0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jul 2019 09:26:24 -0700 Subject: [PATCH 2769/7155] f2fs: add fs-verity support Add fs-verity support to f2fs. fs-verity is a filesystem feature that enables transparent integrity protection and authentication of read-only files. It uses a dm-verity like mechanism at the file level: a Merkle tree is used to verify any block in the file in log(filesize) time. It is implemented mainly by helper functions in fs/verity/. See Documentation/filesystems/fsverity.rst for the full documentation. The f2fs support for fs-verity consists of: - Adding a filesystem feature flag and an inode flag for fs-verity. - Implementing the fsverity_operations to support enabling verity on an inode and reading/writing the verity metadata. - Updating ->readpages() to verify data as it's read from verity files and to support reading verity metadata pages. - Updating ->write_begin(), ->write_end(), and ->writepages() to support writing verity metadata pages. - Calling the fs-verity hooks for ->open(), ->setattr(), and ->ioctl(). Like ext4, f2fs stores the verity metadata (Merkle tree and fsverity_descriptor) past the end of the file, starting at the first 64K boundary beyond i_size. This approach works because (a) verity files are readonly, and (b) pages fully beyond i_size aren't visible to userspace but can be read/written internally by f2fs with only some relatively small changes to f2fs. Extended attributes cannot be used because (a) f2fs limits the total size of an inode's xattr entries to 4096 bytes, which wouldn't be enough for even a single Merkle tree block, and (b) f2fs encryption doesn't encrypt xattrs, yet the verity metadata *must* be encrypted when the file is because it contains hashes of the plaintext data. Acked-by: Jaegeuk Kim Acked-by: Chao Yu Signed-off-by: Eric Biggers --- fs/f2fs/Makefile | 1 + fs/f2fs/data.c | 75 ++++++++++++-- fs/f2fs/f2fs.h | 20 +++- fs/f2fs/file.c | 43 ++++++++- fs/f2fs/inode.c | 5 +- fs/f2fs/super.c | 3 + fs/f2fs/sysfs.c | 11 +++ fs/f2fs/verity.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/xattr.h | 2 + 9 files changed, 392 insertions(+), 15 deletions(-) create mode 100644 fs/f2fs/verity.c diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile index 776c4b936504..2aaecc63834f 100644 --- a/fs/f2fs/Makefile +++ b/fs/f2fs/Makefile @@ -8,3 +8,4 @@ f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o +f2fs-$(CONFIG_FS_VERITY) += verity.o diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index abbf14e9bd72..54cad80acb7d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -74,6 +74,7 @@ static enum count_type __read_io_type(struct page *page) enum bio_post_read_step { STEP_INITIAL = 0, STEP_DECRYPT, + STEP_VERITY, }; struct bio_post_read_ctx { @@ -120,8 +121,23 @@ static void decrypt_work(struct work_struct *work) bio_post_read_processing(ctx); } +static void verity_work(struct work_struct *work) +{ + struct bio_post_read_ctx *ctx = + container_of(work, struct bio_post_read_ctx, work); + + fsverity_verify_bio(ctx->bio); + + bio_post_read_processing(ctx); +} + static void bio_post_read_processing(struct bio_post_read_ctx *ctx) { + /* + * We use different work queues for decryption and for verity because + * verity may require reading metadata pages that need decryption, and + * we shouldn't recurse to the same workqueue. + */ switch (++ctx->cur_step) { case STEP_DECRYPT: if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { @@ -131,6 +147,14 @@ static void bio_post_read_processing(struct bio_post_read_ctx *ctx) } ctx->cur_step++; /* fall-through */ + case STEP_VERITY: + if (ctx->enabled_steps & (1 << STEP_VERITY)) { + INIT_WORK(&ctx->work, verity_work); + fsverity_enqueue_verify_work(&ctx->work); + return; + } + ctx->cur_step++; + /* fall-through */ default: __read_end_io(ctx->bio); } @@ -608,8 +632,15 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) up_write(&io->io_rwsem); } +static inline bool f2fs_need_verity(const struct inode *inode, pgoff_t idx) +{ + return fsverity_active(inode) && + idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE); +} + static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, - unsigned nr_pages, unsigned op_flag) + unsigned nr_pages, unsigned op_flag, + pgoff_t first_idx) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct bio *bio; @@ -625,6 +656,10 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, if (f2fs_encrypted_file(inode)) post_read_steps |= 1 << STEP_DECRYPT; + + if (f2fs_need_verity(inode, first_idx)) + post_read_steps |= 1 << STEP_VERITY; + if (post_read_steps) { ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); if (!ctx) { @@ -646,7 +681,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct bio *bio; - bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0); + bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0, page->index); if (IS_ERR(bio)) return PTR_ERR(bio); @@ -1569,6 +1604,15 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, return ret; } +static inline loff_t f2fs_readpage_limit(struct inode *inode) +{ + if (IS_ENABLED(CONFIG_FS_VERITY) && + (IS_VERITY(inode) || f2fs_verity_in_progress(inode))) + return inode->i_sb->s_maxbytes; + + return i_size_read(inode); +} + static int f2fs_read_single_page(struct inode *inode, struct page *page, unsigned nr_pages, struct f2fs_map_blocks *map, @@ -1587,7 +1631,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, block_in_file = (sector_t)page_index(page); last_block = block_in_file + nr_pages; - last_block_in_file = (i_size_read(inode) + blocksize - 1) >> + last_block_in_file = (f2fs_readpage_limit(inode) + blocksize - 1) >> blkbits; if (last_block > last_block_in_file) last_block = last_block_in_file; @@ -1632,6 +1676,11 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, } else { zero_out: zero_user_segment(page, 0, PAGE_SIZE); + if (f2fs_need_verity(inode, page->index) && + !fsverity_verify_page(page)) { + ret = -EIO; + goto out; + } if (!PageUptodate(page)) SetPageUptodate(page); unlock_page(page); @@ -1650,7 +1699,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, } if (bio == NULL) { bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, - is_readahead ? REQ_RAHEAD : 0); + is_readahead ? REQ_RAHEAD : 0, page->index); if (IS_ERR(bio)) { ret = PTR_ERR(bio); bio = NULL; @@ -2052,7 +2101,7 @@ static int __write_data_page(struct page *page, bool *submitted, if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto redirty_out; - if (page->index < end_index) + if (page->index < end_index || f2fs_verity_in_progress(inode)) goto write; /* @@ -2427,7 +2476,8 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to) struct inode *inode = mapping->host; loff_t i_size = i_size_read(inode); - if (to > i_size) { + /* In the fs-verity case, f2fs_end_enable_verity() does the truncate */ + if (to > i_size && !f2fs_verity_in_progress(inode)) { down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); down_write(&F2FS_I(inode)->i_mmap_sem); @@ -2458,7 +2508,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, * the block addresses when there is no need to fill the page. */ if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && - !is_inode_flag_set(inode, FI_NO_PREALLOC)) + !is_inode_flag_set(inode, FI_NO_PREALLOC) && + !f2fs_verity_in_progress(inode)) return 0; /* f2fs_lock_op avoids race between write CP and convert_inline_page */ @@ -2597,7 +2648,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, if (len == PAGE_SIZE || PageUptodate(page)) return 0; - if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode)) { + if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && + !f2fs_verity_in_progress(inode)) { zero_user_segment(page, len, PAGE_SIZE); return 0; } @@ -2660,7 +2712,8 @@ static int f2fs_write_end(struct file *file, set_page_dirty(page); - if (pos + copied > i_size_read(inode)) + if (pos + copied > i_size_read(inode) && + !f2fs_verity_in_progress(inode)) f2fs_i_size_write(inode, pos + copied); unlock_out: f2fs_put_page(page, 1); @@ -3104,7 +3157,9 @@ void f2fs_clear_page_cache_dirty_tag(struct page *page) int __init f2fs_init_post_read_processing(void) { - bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0); + bio_post_read_ctx_cache = + kmem_cache_create("f2fs_bio_post_read_ctx", + sizeof(struct bio_post_read_ctx), 0, 0, NULL); if (!bio_post_read_ctx_cache) goto fail; bio_post_read_ctx_pool = diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 17382da7f0bd..7c5f121edac5 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -25,6 +25,7 @@ #include #include +#include #ifdef CONFIG_F2FS_CHECK_FS #define f2fs_bug_on(sbi, condition) BUG_ON(condition) @@ -151,7 +152,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_QUOTA_INO 0x0080 #define F2FS_FEATURE_INODE_CRTIME 0x0100 #define F2FS_FEATURE_LOST_FOUND 0x0200 -#define F2FS_FEATURE_VERITY 0x0400 /* reserved */ +#define F2FS_FEATURE_VERITY 0x0400 #define F2FS_FEATURE_SB_CHKSUM 0x0800 #define __F2FS_HAS_FEATURE(raw_super, mask) \ @@ -630,7 +631,7 @@ enum { #define FADVISE_ENC_NAME_BIT 0x08 #define FADVISE_KEEP_SIZE_BIT 0x10 #define FADVISE_HOT_BIT 0x20 -#define FADVISE_VERITY_BIT 0x40 /* reserved */ +#define FADVISE_VERITY_BIT 0x40 #define FADVISE_MODIFIABLE_BITS (FADVISE_COLD_BIT | FADVISE_HOT_BIT) @@ -650,6 +651,8 @@ enum { #define file_is_hot(inode) is_file(inode, FADVISE_HOT_BIT) #define file_set_hot(inode) set_file(inode, FADVISE_HOT_BIT) #define file_clear_hot(inode) clear_file(inode, FADVISE_HOT_BIT) +#define file_is_verity(inode) is_file(inode, FADVISE_VERITY_BIT) +#define file_set_verity(inode) set_file(inode, FADVISE_VERITY_BIT) #define DEF_DIR_LEVEL 0 @@ -2412,6 +2415,7 @@ enum { FI_PROJ_INHERIT, /* indicate file inherits projectid */ FI_PIN_FILE, /* indicate file should not be gced */ FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */ + FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ }; static inline void __mark_inode_dirty_flag(struct inode *inode, @@ -2451,6 +2455,12 @@ static inline void clear_inode_flag(struct inode *inode, int flag) __mark_inode_dirty_flag(inode, flag, false); } +static inline bool f2fs_verity_in_progress(struct inode *inode) +{ + return IS_ENABLED(CONFIG_FS_VERITY) && + is_inode_flag_set(inode, FI_VERITY_IN_PROGRESS); +} + static inline void set_acl_inode(struct inode *inode, umode_t mode) { F2FS_I(inode)->i_acl_mode = mode; @@ -3521,6 +3531,9 @@ void f2fs_exit_sysfs(void); int f2fs_register_sysfs(struct f2fs_sb_info *sbi); void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi); +/* verity.c */ +extern const struct fsverity_operations f2fs_verityops; + /* * crypto support */ @@ -3543,7 +3556,7 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode) */ static inline bool f2fs_post_read_required(struct inode *inode) { - return f2fs_encrypted_file(inode); + return f2fs_encrypted_file(inode) || fsverity_active(inode); } #define F2FS_FEATURE_FUNCS(name, flagname) \ @@ -3561,6 +3574,7 @@ F2FS_FEATURE_FUNCS(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); +F2FS_FEATURE_FUNCS(verity, VERITY); F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); #ifdef CONFIG_BLK_DEV_ZONED diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f8d46df8fa9e..838bfeecbd86 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -493,6 +493,10 @@ static int f2fs_file_open(struct inode *inode, struct file *filp) { int err = fscrypt_file_open(inode, filp); + if (err) + return err; + + err = fsverity_file_open(inode, filp); if (err) return err; @@ -778,6 +782,10 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) if (err) return err; + err = fsverity_prepare_setattr(dentry, attr); + if (err) + return err; + if (is_quota_modification(inode, attr)) { err = dquot_initialize(inode); if (err) @@ -1712,7 +1720,8 @@ static const struct { FS_PROJINHERIT_FL | \ FS_ENCRYPT_FL | \ FS_INLINE_DATA_FL | \ - FS_NOCOW_FL) + FS_NOCOW_FL | \ + FS_VERITY_FL) #define F2FS_SETTABLE_FS_FL ( \ FS_SYNC_FL | \ @@ -1757,6 +1766,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg) if (IS_ENCRYPTED(inode)) fsflags |= FS_ENCRYPT_FL; + if (IS_VERITY(inode)) + fsflags |= FS_VERITY_FL; if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) fsflags |= FS_INLINE_DATA_FL; if (is_inode_flag_set(inode, FI_PIN_FILE)) @@ -3077,6 +3088,30 @@ static int f2fs_ioc_resize_fs(struct file *filp, unsigned long arg) return ret; } +static int f2fs_ioc_enable_verity(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); + + if (!f2fs_sb_has_verity(F2FS_I_SB(inode))) { + f2fs_warn(F2FS_I_SB(inode), + "Can't enable fs-verity on inode %lu: the verity feature is not enabled on this filesystem.\n", + inode->i_ino); + return -EOPNOTSUPP; + } + + return fsverity_ioctl_enable(filp, (const void __user *)arg); +} + +static int f2fs_ioc_measure_verity(struct file *filp, unsigned long arg) +{ + if (!f2fs_sb_has_verity(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fsverity_ioctl_measure(filp, (void __user *)arg); +} + long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) @@ -3135,6 +3170,10 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_precache_extents(filp, arg); case F2FS_IOC_RESIZE_FS: return f2fs_ioc_resize_fs(filp, arg); + case FS_IOC_ENABLE_VERITY: + return f2fs_ioc_enable_verity(filp, arg); + case FS_IOC_MEASURE_VERITY: + return f2fs_ioc_measure_verity(filp, arg); default: return -ENOTTY; } @@ -3249,6 +3288,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_PIN_FILE: case F2FS_IOC_PRECACHE_EXTENTS: case F2FS_IOC_RESIZE_FS: + case FS_IOC_ENABLE_VERITY: + case FS_IOC_MEASURE_VERITY: break; default: return -ENOIOCTLCMD; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index a33d7a849b2d..06da75d418e0 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -46,9 +46,11 @@ void f2fs_set_inode_flags(struct inode *inode) new_fl |= S_DIRSYNC; if (file_is_encrypt(inode)) new_fl |= S_ENCRYPTED; + if (file_is_verity(inode)) + new_fl |= S_VERITY; inode_set_flags(inode, new_fl, S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| - S_ENCRYPTED); + S_ENCRYPTED|S_VERITY); } static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) @@ -733,6 +735,7 @@ void f2fs_evict_inode(struct inode *inode) } out_clear: fscrypt_put_encryption_info(inode); + fsverity_cleanup_inode(inode); clear_inode(inode); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 6de6cda44031..f085ce15acd1 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3143,6 +3143,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &f2fs_sops; #ifdef CONFIG_FS_ENCRYPTION sb->s_cop = &f2fs_cryptops; +#endif +#ifdef CONFIG_FS_VERITY + sb->s_vop = &f2fs_verityops; #endif sb->s_xattr = f2fs_xattr_handlers; sb->s_export_op = &f2fs_export_ops; diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 3aeacd0aacfd..0cd64f994068 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -131,6 +131,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_lost_found(sbi)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "lost_found"); + if (f2fs_sb_has_verity(sbi)) + len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", + len ? ", " : "", "verity"); if (f2fs_sb_has_sb_chksum(sbi)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "sb_checksum"); @@ -364,6 +367,7 @@ enum feat_id { FEAT_QUOTA_INO, FEAT_INODE_CRTIME, FEAT_LOST_FOUND, + FEAT_VERITY, FEAT_SB_CHECKSUM, }; @@ -381,6 +385,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, case FEAT_QUOTA_INO: case FEAT_INODE_CRTIME: case FEAT_LOST_FOUND: + case FEAT_VERITY: case FEAT_SB_CHECKSUM: return snprintf(buf, PAGE_SIZE, "supported\n"); } @@ -470,6 +475,9 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); +#ifdef CONFIG_FS_VERITY +F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY); +#endif F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); #define ATTR_LIST(name) (&f2fs_attr_##name.attr) @@ -534,6 +542,9 @@ static struct attribute *f2fs_feat_attrs[] = { ATTR_LIST(quota_ino), ATTR_LIST(inode_crtime), ATTR_LIST(lost_found), +#ifdef CONFIG_FS_VERITY + ATTR_LIST(verity), +#endif ATTR_LIST(sb_checksum), NULL, }; diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c new file mode 100644 index 000000000000..a401ef72bc82 --- /dev/null +++ b/fs/f2fs/verity.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/f2fs/verity.c: fs-verity support for f2fs + * + * Copyright 2019 Google LLC + */ + +/* + * Implementation of fsverity_operations for f2fs. + * + * Like ext4, f2fs stores the verity metadata (Merkle tree and + * fsverity_descriptor) past the end of the file, starting at the first 64K + * boundary beyond i_size. This approach works because (a) verity files are + * readonly, and (b) pages fully beyond i_size aren't visible to userspace but + * can be read/written internally by f2fs with only some relatively small + * changes to f2fs. Extended attributes cannot be used because (a) f2fs limits + * the total size of an inode's xattr entries to 4096 bytes, which wouldn't be + * enough for even a single Merkle tree block, and (b) f2fs encryption doesn't + * encrypt xattrs, yet the verity metadata *must* be encrypted when the file is + * because it contains hashes of the plaintext data. + * + * Using a 64K boundary rather than a 4K one keeps things ready for + * architectures with 64K pages, and it doesn't necessarily waste space on-disk + * since there can be a hole between i_size and the start of the Merkle tree. + */ + +#include + +#include "f2fs.h" +#include "xattr.h" + +static inline loff_t f2fs_verity_metadata_pos(const struct inode *inode) +{ + return round_up(inode->i_size, 65536); +} + +/* + * Read some verity metadata from the inode. __vfs_read() can't be used because + * we need to read beyond i_size. + */ +static int pagecache_read(struct inode *inode, void *buf, size_t count, + loff_t pos) +{ + while (count) { + size_t n = min_t(size_t, count, + PAGE_SIZE - offset_in_page(pos)); + struct page *page; + void *addr; + + page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT, + NULL); + if (IS_ERR(page)) + return PTR_ERR(page); + + addr = kmap_atomic(page); + memcpy(buf, addr + offset_in_page(pos), n); + kunmap_atomic(addr); + + put_page(page); + + buf += n; + pos += n; + count -= n; + } + return 0; +} + +/* + * Write some verity metadata to the inode for FS_IOC_ENABLE_VERITY. + * kernel_write() can't be used because the file descriptor is readonly. + */ +static int pagecache_write(struct inode *inode, const void *buf, size_t count, + loff_t pos) +{ + if (pos + count > inode->i_sb->s_maxbytes) + return -EFBIG; + + while (count) { + size_t n = min_t(size_t, count, + PAGE_SIZE - offset_in_page(pos)); + struct page *page; + void *fsdata; + void *addr; + int res; + + res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0, + &page, &fsdata); + if (res) + return res; + + addr = kmap_atomic(page); + memcpy(addr + offset_in_page(pos), buf, n); + kunmap_atomic(addr); + + res = pagecache_write_end(NULL, inode->i_mapping, pos, n, n, + page, fsdata); + if (res < 0) + return res; + if (res != n) + return -EIO; + + buf += n; + pos += n; + count -= n; + } + return 0; +} + +/* + * Format of f2fs verity xattr. This points to the location of the verity + * descriptor within the file data rather than containing it directly because + * the verity descriptor *must* be encrypted when f2fs encryption is used. But, + * f2fs encryption does not encrypt xattrs. + */ +struct fsverity_descriptor_location { + __le32 version; + __le32 size; + __le64 pos; +}; + +static int f2fs_begin_enable_verity(struct file *filp) +{ + struct inode *inode = file_inode(filp); + int err; + + if (f2fs_verity_in_progress(inode)) + return -EBUSY; + + if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) + return -EOPNOTSUPP; + + /* + * Since the file was opened readonly, we have to initialize the quotas + * here and not rely on ->open() doing it. This must be done before + * evicting the inline data. + */ + err = dquot_initialize(inode); + if (err) + return err; + + err = f2fs_convert_inline_inode(inode); + if (err) + return err; + + set_inode_flag(inode, FI_VERITY_IN_PROGRESS); + return 0; +} + +static int f2fs_end_enable_verity(struct file *filp, const void *desc, + size_t desc_size, u64 merkle_tree_size) +{ + struct inode *inode = file_inode(filp); + u64 desc_pos = f2fs_verity_metadata_pos(inode) + merkle_tree_size; + struct fsverity_descriptor_location dloc = { + .version = cpu_to_le32(1), + .size = cpu_to_le32(desc_size), + .pos = cpu_to_le64(desc_pos), + }; + int err = 0; + + if (desc != NULL) { + /* Succeeded; write the verity descriptor. */ + err = pagecache_write(inode, desc, desc_size, desc_pos); + + /* Write all pages before clearing FI_VERITY_IN_PROGRESS. */ + if (!err) + err = filemap_write_and_wait(inode->i_mapping); + } + + /* If we failed, truncate anything we wrote past i_size. */ + if (desc == NULL || err) + f2fs_truncate(inode); + + clear_inode_flag(inode, FI_VERITY_IN_PROGRESS); + + if (desc != NULL && !err) { + err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_VERITY, + F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc), + NULL, XATTR_CREATE); + if (!err) { + file_set_verity(inode); + f2fs_set_inode_flags(inode); + f2fs_mark_inode_dirty_sync(inode, true); + } + } + return err; +} + +static int f2fs_get_verity_descriptor(struct inode *inode, void *buf, + size_t buf_size) +{ + struct fsverity_descriptor_location dloc; + int res; + u32 size; + u64 pos; + + /* Get the descriptor location */ + res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_VERITY, + F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc), NULL); + if (res < 0 && res != -ERANGE) + return res; + if (res != sizeof(dloc) || dloc.version != cpu_to_le32(1)) { + f2fs_warn(F2FS_I_SB(inode), "unknown verity xattr format"); + return -EINVAL; + } + size = le32_to_cpu(dloc.size); + pos = le64_to_cpu(dloc.pos); + + /* Get the descriptor */ + if (pos + size < pos || pos + size > inode->i_sb->s_maxbytes || + pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) { + f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr"); + return -EFSCORRUPTED; + } + if (buf_size) { + if (size > buf_size) + return -ERANGE; + res = pagecache_read(inode, buf, size, pos); + if (res) + return res; + } + return size; +} + +static struct page *f2fs_read_merkle_tree_page(struct inode *inode, + pgoff_t index) +{ + index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT; + + return read_mapping_page(inode->i_mapping, index, NULL); +} + +static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf, + u64 index, int log_blocksize) +{ + loff_t pos = f2fs_verity_metadata_pos(inode) + (index << log_blocksize); + + return pagecache_write(inode, buf, 1 << log_blocksize, pos); +} + +const struct fsverity_operations f2fs_verityops = { + .begin_enable_verity = f2fs_begin_enable_verity, + .end_enable_verity = f2fs_end_enable_verity, + .get_verity_descriptor = f2fs_get_verity_descriptor, + .read_merkle_tree_page = f2fs_read_merkle_tree_page, + .write_merkle_tree_block = f2fs_write_merkle_tree_block, +}; diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index a90920e2f949..de0c600b9cab 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -34,8 +34,10 @@ #define F2FS_XATTR_INDEX_ADVISE 7 /* Should be same as EXT4_XATTR_INDEX_ENCRYPTION */ #define F2FS_XATTR_INDEX_ENCRYPTION 9 +#define F2FS_XATTR_INDEX_VERITY 11 #define F2FS_XATTR_NAME_ENCRYPTION_CONTEXT "c" +#define F2FS_XATTR_NAME_VERITY "v" struct f2fs_xattr_header { __le32 h_magic; /* magic number for identification */ -- GitLab From 069e4a19f44d82c43d6a3866499f3d4da6ab3dec Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 12 Aug 2019 12:11:43 +0200 Subject: [PATCH 2770/7155] dmaengine: ti: unexport filter functions The two filter functions are now marked static, but still exported, which triggers a coming build-time check: WARNING: "omap_dma_filter_fn" [vmlinux] is a static EXPORT_SYMBOL_GPL WARNING: "edma_filter_fn" [vmlinux] is a static EXPORT_SYMBOL Remove the unneeded exports as well, as originally intended. Fixes: 9c71b9eb3cb2 ("dmaengine: omap-dma: make omap_dma_filter_fn private") Fixes: d2bfe7b5d182 ("dmaengine: edma: make edma_filter_fn private") Reported-by: Stephen Rothwell Acked-by: Peter Ujfalusi Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190812101155.997721-1-arnd@arndb.de Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 1 - drivers/dma/ti/omap-dma.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index fe468e2f7e67..f7555d78ff9e 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -2600,7 +2600,6 @@ static bool edma_filter_fn(struct dma_chan *chan, void *param) } return match; } -EXPORT_SYMBOL(edma_filter_fn); static int edma_init(void) { diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index a4a63425dc0b..d27779be5b17 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -1666,7 +1666,6 @@ static bool omap_dma_filter_fn(struct dma_chan *chan, void *param) } return false; } -EXPORT_SYMBOL_GPL(omap_dma_filter_fn); static int omap_dma_init(void) { -- GitLab From 7607a121f4617840fe645c65f090af6403738031 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Aug 2019 19:22:00 -0500 Subject: [PATCH 2771/7155] dmaengine: fsldma: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark switch cases where we are expecting to fall through. Fix the following warning (Building: powerpc-ppa8548_defconfig powerpc): drivers/dma/fsldma.c: In function ‘fsl_dma_chan_probe’: drivers/dma/fsldma.c:1165:26: warning: this statement may fall through [-Wimplicit-fallthrough=] chan->toggle_ext_pause = fsl_chan_toggle_ext_pause; ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/dma/fsldma.c:1166:2: note: here case FSL_DMA_IP_83XX: ^~~~ Reported-by: kbuild test robot Signed-off-by: Gustavo A. R. Silva Acked-by: Li Yang Link: https://lore.kernel.org/r/20190812002159.GA26899@embeddedor Signed-off-by: Vinod Koul --- drivers/dma/fsldma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 23e0a356f167..ad72b3f42ffa 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1163,6 +1163,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev, switch (chan->feature & FSL_DMA_IP_MASK) { case FSL_DMA_IP_85XX: chan->toggle_ext_pause = fsl_chan_toggle_ext_pause; + /* Fall through */ case FSL_DMA_IP_83XX: chan->toggle_ext_start = fsl_chan_toggle_ext_start; chan->set_src_loop_size = fsl_chan_set_src_loop_size; -- GitLab From 647d58a989b3b0b788c721a08394aec825e3438c Mon Sep 17 00:00:00 2001 From: Yishai Hadas Date: Thu, 8 Aug 2019 11:43:55 +0300 Subject: [PATCH 2772/7155] net/mlx5: Use debug message instead of warn As QP may be created by DEVX, it may be valid to not find the rsn in mlx5 core tree, change the level to be debug. Signed-off-by: Yishai Hadas Reviewed-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index 7b44d1e49604..c3aea4cc2fff 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -162,7 +162,7 @@ static int rsc_event_notifier(struct notifier_block *nb, common = mlx5_get_rsc(table, rsn); if (!common) { - mlx5_core_warn(dev, "Async event for bogus resource 0x%x\n", rsn); + mlx5_core_dbg(dev, "Async event for unknown resource 0x%x\n", rsn); return NOTIFY_OK; } -- GitLab From b1635ee6120cbeb3de6ab270432b2a2b839c9c56 Mon Sep 17 00:00:00 2001 From: Yishai Hadas Date: Thu, 8 Aug 2019 11:43:56 +0300 Subject: [PATCH 2773/7155] net/mlx5: Add XRQ legacy commands opcodes Add XRQ legacy commands opcodes, will be used via the DEVX interface. Signed-off-by: Yishai Hadas Reviewed-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 4 ++++ include/linux/mlx5/mlx5_ifc.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 8cdd7e66f8df..53d09620e215 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -446,6 +446,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, case MLX5_CMD_OP_CREATE_UMEM: case MLX5_CMD_OP_DESTROY_UMEM: case MLX5_CMD_OP_ALLOC_MEMIC: + case MLX5_CMD_OP_MODIFY_XRQ: + case MLX5_CMD_OP_RELEASE_XRQ_ERROR: *status = MLX5_DRIVER_STATUS_ABORTED; *synd = MLX5_DRIVER_SYND; return -EIO; @@ -637,6 +639,8 @@ const char *mlx5_command_str(int command) MLX5_COMMAND_STR_CASE(DESTROY_UCTX); MLX5_COMMAND_STR_CASE(CREATE_UMEM); MLX5_COMMAND_STR_CASE(DESTROY_UMEM); + MLX5_COMMAND_STR_CASE(RELEASE_XRQ_ERROR); + MLX5_COMMAND_STR_CASE(MODIFY_XRQ); default: return "unknown command opcode"; } } diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 1f9d4a8e6227..ab6ae723aae6 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -172,6 +172,8 @@ enum { MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY = 0x725, MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY = 0x726, MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS = 0x727, + MLX5_CMD_OP_RELEASE_XRQ_ERROR = 0x729, + MLX5_CMD_OP_MODIFY_XRQ = 0x72a, MLX5_CMD_OP_QUERY_ESW_FUNCTIONS = 0x740, MLX5_CMD_OP_QUERY_VPORT_STATE = 0x750, MLX5_CMD_OP_MODIFY_VPORT_STATE = 0x751, -- GitLab From 7e59b3fea2a2510b52761c20ccc71d3e9f6b7db8 Mon Sep 17 00:00:00 2001 From: yangxingwu Date: Tue, 16 Jul 2019 10:13:01 +0800 Subject: [PATCH 2774/7155] netfilter: remove unnecessary spaces This patch removes extra spaces. Signed-off-by: yangxingwu Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_hash_gen.h | 2 +- net/netfilter/ipset/ip_set_list_set.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 2 +- net/netfilter/ipvs/ip_vs_mh.c | 4 ++-- net/netfilter/ipvs/ip_vs_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_ftp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nfnetlink_log.c | 4 ++-- net/netfilter/nfnetlink_queue.c | 4 ++-- net/netfilter/xt_IDLETIMER.c | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index 0feb77fa9edc..3fced06ab752 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -953,7 +953,7 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, mtype_data_netmask(d, NCIDR_GET(h->nets[j].cidr[0])); #endif key = HKEY(d, h->initval, t->htable_bits); - n = rcu_dereference_bh(hbucket(t, key)); + n = rcu_dereference_bh(hbucket(t, key)); if (!n) continue; for (i = 0; i < n->pos; i++) { diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 6f9ead6319e0..67ac50104e6f 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c @@ -288,7 +288,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, if (n && !(SET_WITH_TIMEOUT(set) && ip_set_timeout_expired(ext_timeout(n, set)))) - n = NULL; + n = NULL; e = kzalloc(set->dsize, GFP_ATOMIC); if (!e) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 46f06f92ab8f..8b80ab794a92 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -617,7 +617,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET && iph->protocol == IPPROTO_UDP) ? IP_VS_CONN_F_ONE_PACKET : 0; - union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; + union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; /* create a new connection entry */ IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__); diff --git a/net/netfilter/ipvs/ip_vs_mh.c b/net/netfilter/ipvs/ip_vs_mh.c index 94d9d349ebb0..da0280cec506 100644 --- a/net/netfilter/ipvs/ip_vs_mh.c +++ b/net/netfilter/ipvs/ip_vs_mh.c @@ -174,8 +174,8 @@ static int ip_vs_mh_populate(struct ip_vs_mh_state *s, return 0; } - table = kcalloc(BITS_TO_LONGS(IP_VS_MH_TAB_SIZE), - sizeof(unsigned long), GFP_KERNEL); + table = kcalloc(BITS_TO_LONGS(IP_VS_MH_TAB_SIZE), + sizeof(unsigned long), GFP_KERNEL); if (!table) return -ENOMEM; diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 000d961b97e4..32b028853a7c 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c @@ -710,7 +710,7 @@ static int __ip_vs_tcp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd sizeof(tcp_timeouts)); if (!pd->timeout_table) return -ENOMEM; - pd->tcp_state_table = tcp_states; + pd->tcp_state_table = tcp_states; return 0; } diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 0ecb3e289ef2..c57d2348c505 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -162,7 +162,7 @@ static int try_rfc959(const char *data, size_t dlen, if (length == 0) return 0; - cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) | + cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]); cmd->u.tcp.port = htons((array[4] << 8) | array[5]); return length; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 85c1f8c213b0..1926fd56df56 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1227,7 +1227,7 @@ static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, - [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, }; #define TCP_NLATTR_SIZE ( \ diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 6dee4f9a944c..d69e1863e536 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -651,7 +651,7 @@ nfulnl_log_packet(struct net *net, /* FIXME: do we want to make the size calculation conditional based on * what is actually present? way more branches and checks, but more * memory efficient... */ - size = nlmsg_total_size(sizeof(struct nfgenmsg)) + size = nlmsg_total_size(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ @@ -668,7 +668,7 @@ nfulnl_log_packet(struct net *net, + nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */ if (in && skb_mac_header_was_set(skb)) { - size += nla_total_size(skb->dev->hard_header_len) + size += nla_total_size(skb->dev->hard_header_len) + nla_total_size(sizeof(u_int16_t)) /* hwtype */ + nla_total_size(sizeof(u_int16_t)); /* hwlen */ } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b6a7ce622c72..feabdfb22920 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -394,7 +394,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, char *secdata = NULL; u32 seclen = 0; - size = nlmsg_total_size(sizeof(struct nfgenmsg)) + size = nlmsg_total_size(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ @@ -453,7 +453,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, } if (queue->flags & NFQA_CFG_F_UID_GID) { - size += (nla_total_size(sizeof(u_int32_t)) /* uid */ + size += (nla_total_size(sizeof(u_int32_t)) /* uid */ + nla_total_size(sizeof(u_int32_t))); /* gid */ } diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index 9cec9eae556a..f56d3ed93e56 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -283,7 +283,7 @@ static int __init idletimer_tg_init(void) idletimer_tg_kobj = &idletimer_tg_device->kobj; - err = xt_register_target(&idletimer_tg); + err = xt_register_target(&idletimer_tg); if (err < 0) { pr_debug("couldn't register xt target\n"); goto out_dev; -- GitLab From bd8699e9e29287b5571b32b68c3dcd05985fa9b1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 30 Jul 2019 13:32:01 +0200 Subject: [PATCH 2775/7155] netfilter: nft_bitwise: add offload support Extract mask from bitwise operation and store it into the corresponding context register so the cmp instruction can set the mask accordingly. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index b310b637b550..1f04ed5c518c 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -13,6 +13,7 @@ #include #include #include +#include struct nft_bitwise { enum nft_registers sreg:8; @@ -126,12 +127,30 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) return -1; } +static struct nft_data zero; + +static int nft_bitwise_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + const struct nft_bitwise *priv = nft_expr_priv(expr); + + if (memcmp(&priv->xor, &zero, sizeof(priv->xor) || + priv->sreg != priv->dreg)) + return -EOPNOTSUPP; + + memcpy(&ctx->regs[priv->dreg].mask, &priv->mask, sizeof(priv->mask)); + + return 0; +} + static const struct nft_expr_ops nft_bitwise_ops = { .type = &nft_bitwise_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)), .eval = nft_bitwise_eval, .init = nft_bitwise_init, .dump = nft_bitwise_dump, + .offload = nft_bitwise_offload, }; struct nft_expr_type nft_bitwise_type __read_mostly = { -- GitLab From 43dd16efc7f235f153804500a4363769bd2276fc Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 1 Aug 2019 14:09:26 +0200 Subject: [PATCH 2776/7155] netfilter: nf_tables: store data in offload context registers Store immediate data into offload context register. This allows follow up instructions to take it from the corresponding source register. This patch is required to support for payload mangling, although other instructions that take data from source register will benefit from this too. Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables_offload.h | 1 + net/netfilter/nft_immediate.c | 24 ++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 3196663a10e3..4977fbe7ed08 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -9,6 +9,7 @@ struct nft_offload_reg { u32 len; u32 base_offset; u32 offset; + struct nft_data data; struct nft_data mask; }; diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index ca2ae4b95a8d..c7f0ef73d939 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c @@ -125,17 +125,13 @@ static int nft_immediate_validate(const struct nft_ctx *ctx, return 0; } -static int nft_immediate_offload(struct nft_offload_ctx *ctx, - struct nft_flow_rule *flow, - const struct nft_expr *expr) +static int nft_immediate_offload_verdict(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_immediate_expr *priv) { - const struct nft_immediate_expr *priv = nft_expr_priv(expr); struct flow_action_entry *entry; const struct nft_data *data; - if (priv->dreg != NFT_REG_VERDICT) - return -EOPNOTSUPP; - entry = &flow->rule->action.entries[ctx->num_actions++]; data = &priv->data; @@ -153,6 +149,20 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx, return 0; } +static int nft_immediate_offload(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr) +{ + const struct nft_immediate_expr *priv = nft_expr_priv(expr); + + if (priv->dreg == NFT_REG_VERDICT) + return nft_immediate_offload_verdict(ctx, flow, priv); + + memcpy(&ctx->regs[priv->dreg].data, &priv->data, sizeof(priv->data)); + + return 0; +} + static const struct nft_expr_ops nft_imm_ops = { .type = &nft_imm_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), -- GitLab From bd96b4c75675e616eefef6d85d163530eef9c5e5 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:16:58 +0100 Subject: [PATCH 2777/7155] netfilter: inline four headers files into another one. linux/netfilter/ipset/ip_set.h included four other header files: include/linux/netfilter/ipset/ip_set_comment.h include/linux/netfilter/ipset/ip_set_counter.h include/linux/netfilter/ipset/ip_set_skbinfo.h include/linux/netfilter/ipset/ip_set_timeout.h Of these the first three were not included anywhere else. The last, ip_set_timeout.h, was included in a couple of other places, but defined inline functions which call other inline functions defined in ip_set.h, so ip_set.h had to be included before it. Inlined all four into ip_set.h, and updated the other files that included ip_set_timeout.h. Signed-off-by: Jeremy Sowden Acked-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/ipset/ip_set.h | 238 +++++++++++++++++- .../linux/netfilter/ipset/ip_set_comment.h | 73 ------ .../linux/netfilter/ipset/ip_set_counter.h | 84 ------- .../linux/netfilter/ipset/ip_set_skbinfo.h | 42 ---- .../linux/netfilter/ipset/ip_set_timeout.h | 77 ------ net/netfilter/ipset/ip_set_hash_gen.h | 2 +- net/netfilter/xt_set.c | 1 - 7 files changed, 235 insertions(+), 282 deletions(-) delete mode 100644 include/linux/netfilter/ipset/ip_set_comment.h delete mode 100644 include/linux/netfilter/ipset/ip_set_counter.h delete mode 100644 include/linux/netfilter/ipset/ip_set_skbinfo.h delete mode 100644 include/linux/netfilter/ipset/ip_set_timeout.h diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 12ad9b1853b4..9bc255a8461b 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -452,10 +452,240 @@ bitmap_bytes(u32 a, u32 b) return 4 * ((((b - a + 8) / 8) + 3) / 4); } -#include -#include -#include -#include +/* How often should the gc be run by default */ +#define IPSET_GC_TIME (3 * 60) + +/* Timeout period depending on the timeout value of the given set */ +#define IPSET_GC_PERIOD(timeout) \ + ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1) + +/* Entry is set with no timeout value */ +#define IPSET_ELEM_PERMANENT 0 + +/* Set is defined with timeout support: timeout value may be 0 */ +#define IPSET_NO_TIMEOUT UINT_MAX + +/* Max timeout value, see msecs_to_jiffies() in jiffies.h */ +#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC + +#define ip_set_adt_opt_timeout(opt, set) \ +((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) + +static inline unsigned int +ip_set_timeout_uget(struct nlattr *tb) +{ + unsigned int timeout = ip_set_get_h32(tb); + + /* Normalize to fit into jiffies */ + if (timeout > IPSET_MAX_TIMEOUT) + timeout = IPSET_MAX_TIMEOUT; + + return timeout; +} + +static inline bool +ip_set_timeout_expired(const unsigned long *t) +{ + return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t); +} + +static inline void +ip_set_timeout_set(unsigned long *timeout, u32 value) +{ + unsigned long t; + + if (!value) { + *timeout = IPSET_ELEM_PERMANENT; + return; + } + + t = msecs_to_jiffies(value * MSEC_PER_SEC) + jiffies; + if (t == IPSET_ELEM_PERMANENT) + /* Bingo! :-) */ + t--; + *timeout = t; +} + +static inline u32 +ip_set_timeout_get(const unsigned long *timeout) +{ + u32 t; + + if (*timeout == IPSET_ELEM_PERMANENT) + return 0; + + t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; + /* Zero value in userspace means no timeout */ + return t == 0 ? 1 : t; +} + +static inline char* +ip_set_comment_uget(struct nlattr *tb) +{ + return nla_data(tb); +} + +/* Called from uadd only, protected by the set spinlock. + * The kadt functions don't use the comment extensions in any way. + */ +static inline void +ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, + const struct ip_set_ext *ext) +{ + struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); + size_t len = ext->comment ? strlen(ext->comment) : 0; + + if (unlikely(c)) { + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; + kfree_rcu(c, rcu); + rcu_assign_pointer(comment->c, NULL); + } + if (!len) + return; + if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) + len = IPSET_MAX_COMMENT_SIZE; + c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); + if (unlikely(!c)) + return; + strlcpy(c->str, ext->comment, len + 1); + set->ext_size += sizeof(*c) + strlen(c->str) + 1; + rcu_assign_pointer(comment->c, c); +} + +/* Used only when dumping a set, protected by rcu_read_lock() */ +static inline int +ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) +{ + struct ip_set_comment_rcu *c = rcu_dereference(comment->c); + + if (!c) + return 0; + return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); +} + +/* Called from uadd/udel, flush or the garbage collectors protected + * by the set spinlock. + * Called when the set is destroyed and when there can't be any user + * of the set data anymore. + */ +static inline void +ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) +{ + struct ip_set_comment_rcu *c; + + c = rcu_dereference_protected(comment->c, 1); + if (unlikely(!c)) + return; + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; + kfree_rcu(c, rcu); + rcu_assign_pointer(comment->c, NULL); +} + +static inline void +ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) +{ + atomic64_add((long long)bytes, &(counter)->bytes); +} + +static inline void +ip_set_add_packets(u64 packets, struct ip_set_counter *counter) +{ + atomic64_add((long long)packets, &(counter)->packets); +} + +static inline u64 +ip_set_get_bytes(const struct ip_set_counter *counter) +{ + return (u64)atomic64_read(&(counter)->bytes); +} + +static inline u64 +ip_set_get_packets(const struct ip_set_counter *counter) +{ + return (u64)atomic64_read(&(counter)->packets); +} + +static inline bool +ip_set_match_counter(u64 counter, u64 match, u8 op) +{ + switch (op) { + case IPSET_COUNTER_NONE: + return true; + case IPSET_COUNTER_EQ: + return counter == match; + case IPSET_COUNTER_NE: + return counter != match; + case IPSET_COUNTER_LT: + return counter < match; + case IPSET_COUNTER_GT: + return counter > match; + } + return false; +} + +static inline void +ip_set_update_counter(struct ip_set_counter *counter, + const struct ip_set_ext *ext, u32 flags) +{ + if (ext->packets != ULLONG_MAX && + !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { + ip_set_add_bytes(ext->bytes, counter); + ip_set_add_packets(ext->packets, counter); + } +} + +static inline bool +ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) +{ + return nla_put_net64(skb, IPSET_ATTR_BYTES, + cpu_to_be64(ip_set_get_bytes(counter)), + IPSET_ATTR_PAD) || + nla_put_net64(skb, IPSET_ATTR_PACKETS, + cpu_to_be64(ip_set_get_packets(counter)), + IPSET_ATTR_PAD); +} + +static inline void +ip_set_init_counter(struct ip_set_counter *counter, + const struct ip_set_ext *ext) +{ + if (ext->bytes != ULLONG_MAX) + atomic64_set(&(counter)->bytes, (long long)(ext->bytes)); + if (ext->packets != ULLONG_MAX) + atomic64_set(&(counter)->packets, (long long)(ext->packets)); +} + +static inline void +ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, + const struct ip_set_ext *ext, + struct ip_set_ext *mext, u32 flags) +{ + mext->skbinfo = *skbinfo; +} + +static inline bool +ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) +{ + /* Send nonzero parameters only */ + return ((skbinfo->skbmark || skbinfo->skbmarkmask) && + nla_put_net64(skb, IPSET_ATTR_SKBMARK, + cpu_to_be64((u64)skbinfo->skbmark << 32 | + skbinfo->skbmarkmask), + IPSET_ATTR_PAD)) || + (skbinfo->skbprio && + nla_put_net32(skb, IPSET_ATTR_SKBPRIO, + cpu_to_be32(skbinfo->skbprio))) || + (skbinfo->skbqueue && + nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, + cpu_to_be16(skbinfo->skbqueue))); +} + +static inline void +ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, + const struct ip_set_ext *ext) +{ + *skbinfo = ext->skbinfo; +} #define IP_SET_INIT_KEXT(skb, opt, set) \ { .bytes = (skb)->len, .packets = 1, \ diff --git a/include/linux/netfilter/ipset/ip_set_comment.h b/include/linux/netfilter/ipset/ip_set_comment.h deleted file mode 100644 index 0b894d81bbf2..000000000000 --- a/include/linux/netfilter/ipset/ip_set_comment.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_COMMENT_H -#define _IP_SET_COMMENT_H - -/* Copyright (C) 2013 Oliver Smith - */ - -#ifdef __KERNEL__ - -static inline char* -ip_set_comment_uget(struct nlattr *tb) -{ - return nla_data(tb); -} - -/* Called from uadd only, protected by the set spinlock. - * The kadt functions don't use the comment extensions in any way. - */ -static inline void -ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, - const struct ip_set_ext *ext) -{ - struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); - size_t len = ext->comment ? strlen(ext->comment) : 0; - - if (unlikely(c)) { - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; - kfree_rcu(c, rcu); - rcu_assign_pointer(comment->c, NULL); - } - if (!len) - return; - if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) - len = IPSET_MAX_COMMENT_SIZE; - c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); - if (unlikely(!c)) - return; - strlcpy(c->str, ext->comment, len + 1); - set->ext_size += sizeof(*c) + strlen(c->str) + 1; - rcu_assign_pointer(comment->c, c); -} - -/* Used only when dumping a set, protected by rcu_read_lock() */ -static inline int -ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) -{ - struct ip_set_comment_rcu *c = rcu_dereference(comment->c); - - if (!c) - return 0; - return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); -} - -/* Called from uadd/udel, flush or the garbage collectors protected - * by the set spinlock. - * Called when the set is destroyed and when there can't be any user - * of the set data anymore. - */ -static inline void -ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) -{ - struct ip_set_comment_rcu *c; - - c = rcu_dereference_protected(comment->c, 1); - if (unlikely(!c)) - return; - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; - kfree_rcu(c, rcu); - rcu_assign_pointer(comment->c, NULL); -} - -#endif -#endif diff --git a/include/linux/netfilter/ipset/ip_set_counter.h b/include/linux/netfilter/ipset/ip_set_counter.h deleted file mode 100644 index 3400958c07be..000000000000 --- a/include/linux/netfilter/ipset/ip_set_counter.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_COUNTER_H -#define _IP_SET_COUNTER_H - -/* Copyright (C) 2015 Jozsef Kadlecsik */ - -#ifdef __KERNEL__ - -static inline void -ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) -{ - atomic64_add((long long)bytes, &(counter)->bytes); -} - -static inline void -ip_set_add_packets(u64 packets, struct ip_set_counter *counter) -{ - atomic64_add((long long)packets, &(counter)->packets); -} - -static inline u64 -ip_set_get_bytes(const struct ip_set_counter *counter) -{ - return (u64)atomic64_read(&(counter)->bytes); -} - -static inline u64 -ip_set_get_packets(const struct ip_set_counter *counter) -{ - return (u64)atomic64_read(&(counter)->packets); -} - -static inline bool -ip_set_match_counter(u64 counter, u64 match, u8 op) -{ - switch (op) { - case IPSET_COUNTER_NONE: - return true; - case IPSET_COUNTER_EQ: - return counter == match; - case IPSET_COUNTER_NE: - return counter != match; - case IPSET_COUNTER_LT: - return counter < match; - case IPSET_COUNTER_GT: - return counter > match; - } - return false; -} - -static inline void -ip_set_update_counter(struct ip_set_counter *counter, - const struct ip_set_ext *ext, u32 flags) -{ - if (ext->packets != ULLONG_MAX && - !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { - ip_set_add_bytes(ext->bytes, counter); - ip_set_add_packets(ext->packets, counter); - } -} - -static inline bool -ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) -{ - return nla_put_net64(skb, IPSET_ATTR_BYTES, - cpu_to_be64(ip_set_get_bytes(counter)), - IPSET_ATTR_PAD) || - nla_put_net64(skb, IPSET_ATTR_PACKETS, - cpu_to_be64(ip_set_get_packets(counter)), - IPSET_ATTR_PAD); -} - -static inline void -ip_set_init_counter(struct ip_set_counter *counter, - const struct ip_set_ext *ext) -{ - if (ext->bytes != ULLONG_MAX) - atomic64_set(&(counter)->bytes, (long long)(ext->bytes)); - if (ext->packets != ULLONG_MAX) - atomic64_set(&(counter)->packets, (long long)(ext->packets)); -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_COUNTER_H */ diff --git a/include/linux/netfilter/ipset/ip_set_skbinfo.h b/include/linux/netfilter/ipset/ip_set_skbinfo.h deleted file mode 100644 index 3a2df02dbd55..000000000000 --- a/include/linux/netfilter/ipset/ip_set_skbinfo.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_SKBINFO_H -#define _IP_SET_SKBINFO_H - -/* Copyright (C) 2015 Jozsef Kadlecsik */ - -#ifdef __KERNEL__ - -static inline void -ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, - const struct ip_set_ext *ext, - struct ip_set_ext *mext, u32 flags) -{ - mext->skbinfo = *skbinfo; -} - -static inline bool -ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) -{ - /* Send nonzero parameters only */ - return ((skbinfo->skbmark || skbinfo->skbmarkmask) && - nla_put_net64(skb, IPSET_ATTR_SKBMARK, - cpu_to_be64((u64)skbinfo->skbmark << 32 | - skbinfo->skbmarkmask), - IPSET_ATTR_PAD)) || - (skbinfo->skbprio && - nla_put_net32(skb, IPSET_ATTR_SKBPRIO, - cpu_to_be32(skbinfo->skbprio))) || - (skbinfo->skbqueue && - nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, - cpu_to_be16(skbinfo->skbqueue))); -} - -static inline void -ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, - const struct ip_set_ext *ext) -{ - *skbinfo = ext->skbinfo; -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_SKBINFO_H */ diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h deleted file mode 100644 index 2be60e379ecf..000000000000 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_TIMEOUT_H -#define _IP_SET_TIMEOUT_H - -/* Copyright (C) 2003-2013 Jozsef Kadlecsik */ - -#ifdef __KERNEL__ - -/* How often should the gc be run by default */ -#define IPSET_GC_TIME (3 * 60) - -/* Timeout period depending on the timeout value of the given set */ -#define IPSET_GC_PERIOD(timeout) \ - ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1) - -/* Entry is set with no timeout value */ -#define IPSET_ELEM_PERMANENT 0 - -/* Set is defined with timeout support: timeout value may be 0 */ -#define IPSET_NO_TIMEOUT UINT_MAX - -/* Max timeout value, see msecs_to_jiffies() in jiffies.h */ -#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC - -#define ip_set_adt_opt_timeout(opt, set) \ -((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) - -static inline unsigned int -ip_set_timeout_uget(struct nlattr *tb) -{ - unsigned int timeout = ip_set_get_h32(tb); - - /* Normalize to fit into jiffies */ - if (timeout > IPSET_MAX_TIMEOUT) - timeout = IPSET_MAX_TIMEOUT; - - return timeout; -} - -static inline bool -ip_set_timeout_expired(const unsigned long *t) -{ - return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t); -} - -static inline void -ip_set_timeout_set(unsigned long *timeout, u32 value) -{ - unsigned long t; - - if (!value) { - *timeout = IPSET_ELEM_PERMANENT; - return; - } - - t = msecs_to_jiffies(value * MSEC_PER_SEC) + jiffies; - if (t == IPSET_ELEM_PERMANENT) - /* Bingo! :-) */ - t--; - *timeout = t; -} - -static inline u32 -ip_set_timeout_get(const unsigned long *timeout) -{ - u32 t; - - if (*timeout == IPSET_ELEM_PERMANENT) - return 0; - - t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; - /* Zero value in userspace means no timeout */ - return t == 0 ? 1 : t; -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_TIMEOUT_H */ diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index 3fced06ab752..d098d87bc331 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define __ipset_dereference_protected(p, c) rcu_dereference_protected(p, c) #define ipset_dereference_protected(p, set) \ diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index ecbfa291fb70..731bc2cafae4 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -14,7 +14,6 @@ #include #include -#include #include MODULE_LICENSE("GPL"); -- GitLab From a1b2f04ea527397fcacacd09e0d690927feef429 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:16:59 +0100 Subject: [PATCH 2778/7155] netfilter: add missing includes to a number of header-files. A number of netfilter header-files used declarations and definitions from other headers without including them. Added include directives to make those declarations and definitions available. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/ipset/ip_set_getport.h | 4 ++++ include/linux/netfilter/nf_conntrack_amanda.h | 4 ++++ include/linux/netfilter/nf_conntrack_ftp.h | 8 +++++--- include/linux/netfilter/nf_conntrack_h323.h | 7 +++++-- include/linux/netfilter/nf_conntrack_h323_asn1.h | 2 ++ include/linux/netfilter/nf_conntrack_irc.h | 4 ++++ include/linux/netfilter/nf_conntrack_pptp.h | 9 +++++---- include/linux/netfilter/nf_conntrack_sip.h | 4 ++-- include/linux/netfilter/nf_conntrack_snmp.h | 3 +++ include/linux/netfilter/nf_conntrack_tftp.h | 5 +++++ include/net/netfilter/br_netfilter.h | 2 ++ include/net/netfilter/ipv4/nf_dup_ipv4.h | 3 +++ include/net/netfilter/ipv6/nf_defrag_ipv6.h | 4 +++- include/net/netfilter/ipv6/nf_dup_ipv6.h | 2 ++ include/net/netfilter/nf_conntrack_bridge.h | 4 ++++ include/net/netfilter/nf_conntrack_count.h | 3 +++ include/net/netfilter/nf_dup_netdev.h | 2 ++ include/net/netfilter/nf_flow_table.h | 1 + include/net/netfilter/nf_nat_helper.h | 4 ++-- include/net/netfilter/nf_nat_redirect.h | 3 +++ include/net/netfilter/nf_queue.h | 2 ++ include/net/netfilter/nf_reject.h | 3 +++ include/net/netfilter/nf_tables_ipv6.h | 1 + include/net/netfilter/nft_fib.h | 2 ++ include/net/netfilter/nft_meta.h | 2 ++ include/net/netfilter/nft_reject.h | 5 +++++ include/uapi/linux/netfilter/xt_policy.h | 1 + 27 files changed, 80 insertions(+), 14 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h index ac6a11d38a19..a906df06948b 100644 --- a/include/linux/netfilter/ipset/ip_set_getport.h +++ b/include/linux/netfilter/ipset/ip_set_getport.h @@ -2,6 +2,10 @@ #ifndef _IP_SET_GETPORT_H #define _IP_SET_GETPORT_H +#include +#include +#include + extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h index 34345e543ba2..6f0ac896fcc9 100644 --- a/include/linux/netfilter/nf_conntrack_amanda.h +++ b/include/linux/netfilter/nf_conntrack_amanda.h @@ -3,6 +3,10 @@ #define _NF_CONNTRACK_AMANDA_H /* AMANDA tracking. */ +#include +#include +#include + extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, enum ip_conntrack_info ctinfo, unsigned int protoff, diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h index 73a296dfd019..0e38302820b9 100644 --- a/include/linux/netfilter/nf_conntrack_ftp.h +++ b/include/linux/netfilter/nf_conntrack_ftp.h @@ -2,8 +2,12 @@ #ifndef _NF_CONNTRACK_FTP_H #define _NF_CONNTRACK_FTP_H +#include +#include +#include +#include #include - +#include #define FTP_PORT 21 @@ -20,8 +24,6 @@ struct nf_ct_ftp_master { u_int16_t flags[IP_CT_DIR_MAX]; }; -struct nf_conntrack_expect; - /* For NAT to hook in when we find a packet which describes what other * connection we should expect. */ extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index f76ed373a2a5..96dfa886f8c0 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -4,7 +4,12 @@ #ifdef __KERNEL__ +#include +#include +#include #include +#include +#include #define RAS_PORT 1719 #define Q931_PORT 1720 @@ -28,8 +33,6 @@ struct nf_ct_h323_master { }; }; -struct nf_conn; - int get_h225_addr(struct nf_conn *ct, unsigned char *data, TransportAddress *taddr, union nf_inet_addr *addr, __be16 *port); diff --git a/include/linux/netfilter/nf_conntrack_h323_asn1.h b/include/linux/netfilter/nf_conntrack_h323_asn1.h index 19df78341fb3..bd6797f823b2 100644 --- a/include/linux/netfilter/nf_conntrack_h323_asn1.h +++ b/include/linux/netfilter/nf_conntrack_h323_asn1.h @@ -37,6 +37,8 @@ /***************************************************************************** * H.323 Types ****************************************************************************/ + +#include #include typedef struct { diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h index 00c2b74206e1..f75e005db969 100644 --- a/include/linux/netfilter/nf_conntrack_irc.h +++ b/include/linux/netfilter/nf_conntrack_irc.h @@ -4,6 +4,10 @@ #ifdef __KERNEL__ +#include +#include +#include + #define IRC_PORT 6667 extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index 833a5b2255ea..3f10e806f0dc 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -3,7 +3,12 @@ #ifndef _NF_CONNTRACK_PPTP_H #define _NF_CONNTRACK_PPTP_H +#include +#include +#include #include +#include +#include extern const char *const pptp_msg_name[]; @@ -297,10 +302,6 @@ union pptp_ctrl_union { struct PptpSetLinkInfo setlink; }; -/* crap needed for nf_conntrack_compat.h */ -struct nf_conn; -struct nf_conntrack_expect; - extern int (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index c7fc38807a33..f6437f7841af 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -3,9 +3,9 @@ #define __NF_CONNTRACK_SIP_H__ #ifdef __KERNEL__ -#include - +#include #include +#include #define SIP_PORT 5060 #define SIP_TIMEOUT 3600 diff --git a/include/linux/netfilter/nf_conntrack_snmp.h b/include/linux/netfilter/nf_conntrack_snmp.h index 818088c47475..87e4f33eb55f 100644 --- a/include/linux/netfilter/nf_conntrack_snmp.h +++ b/include/linux/netfilter/nf_conntrack_snmp.h @@ -2,6 +2,9 @@ #ifndef _NF_CONNTRACK_SNMP_H #define _NF_CONNTRACK_SNMP_H +#include +#include + extern int (*nf_nat_snmp_hook)(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h index 5769e12dd0a2..dc4c1b9beac0 100644 --- a/include/linux/netfilter/nf_conntrack_tftp.h +++ b/include/linux/netfilter/nf_conntrack_tftp.h @@ -4,6 +4,11 @@ #define TFTP_PORT 69 +#include +#include +#include +#include + struct tftphdr { __be16 opcode; }; diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index 302fcd3aade2..ca121ed906df 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -2,6 +2,8 @@ #ifndef _BR_NETFILTER_H_ #define _BR_NETFILTER_H_ +#include + #include "../../../net/bridge/br_private.h" static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) diff --git a/include/net/netfilter/ipv4/nf_dup_ipv4.h b/include/net/netfilter/ipv4/nf_dup_ipv4.h index c962e0be3549..a2bc16cdbcd3 100644 --- a/include/net/netfilter/ipv4/nf_dup_ipv4.h +++ b/include/net/netfilter/ipv4/nf_dup_ipv4.h @@ -2,6 +2,9 @@ #ifndef _NF_DUP_IPV4_H_ #define _NF_DUP_IPV4_H_ +#include +#include + void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in_addr *gw, int oif); diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h index 9d7e28736da9..6d31cd041143 100644 --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h @@ -2,7 +2,9 @@ #ifndef _NF_DEFRAG_IPV6_H #define _NF_DEFRAG_IPV6_H -struct net; +#include +#include + int nf_defrag_ipv6_enable(struct net *); int nf_ct_frag6_init(void); diff --git a/include/net/netfilter/ipv6/nf_dup_ipv6.h b/include/net/netfilter/ipv6/nf_dup_ipv6.h index caf0c2dd8ee7..f6312bb04a13 100644 --- a/include/net/netfilter/ipv6/nf_dup_ipv6.h +++ b/include/net/netfilter/ipv6/nf_dup_ipv6.h @@ -2,6 +2,8 @@ #ifndef _NF_DUP_IPV6_H_ #define _NF_DUP_IPV6_H_ +#include + void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in6_addr *gw, int oif); diff --git a/include/net/netfilter/nf_conntrack_bridge.h b/include/net/netfilter/nf_conntrack_bridge.h index 9a5514d5bc51..8f2e5b2ab523 100644 --- a/include/net/netfilter/nf_conntrack_bridge.h +++ b/include/net/netfilter/nf_conntrack_bridge.h @@ -1,6 +1,10 @@ #ifndef NF_CONNTRACK_BRIDGE_ #define NF_CONNTRACK_BRIDGE_ +#include +#include +#include + struct nf_ct_bridge_info { struct nf_hook_ops *ops; unsigned int ops_size; diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h index f32fc8289473..9645b47fa7e4 100644 --- a/include/net/netfilter/nf_conntrack_count.h +++ b/include/net/netfilter/nf_conntrack_count.h @@ -2,6 +2,9 @@ #define _NF_CONNTRACK_COUNT_H #include +#include +#include +#include struct nf_conncount_data; diff --git a/include/net/netfilter/nf_dup_netdev.h b/include/net/netfilter/nf_dup_netdev.h index 2a6f6dcad3d9..181672672160 100644 --- a/include/net/netfilter/nf_dup_netdev.h +++ b/include/net/netfilter/nf_dup_netdev.h @@ -2,6 +2,8 @@ #ifndef _NF_DUP_NETDEV_H_ #define _NF_DUP_NETDEV_H_ +#include + void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif); void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif); diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index d8c187936bec..7249e331bd0b 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index 97d7033e93a4..efae84646353 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h @@ -3,9 +3,9 @@ #define _NF_NAT_HELPER_H /* NAT protocol helper routines. */ +#include #include - -struct sk_buff; +#include /* These return true or false. */ bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct, diff --git a/include/net/netfilter/nf_nat_redirect.h b/include/net/netfilter/nf_nat_redirect.h index c129aacc8ae8..2418653a66db 100644 --- a/include/net/netfilter/nf_nat_redirect.h +++ b/include/net/netfilter/nf_nat_redirect.h @@ -2,6 +2,9 @@ #ifndef _NF_NAT_REDIRECT_H_ #define _NF_NAT_REDIRECT_H_ +#include +#include + unsigned int nf_nat_redirect_ipv4(struct sk_buff *skb, const struct nf_nat_ipv4_multi_range_compat *mr, diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 3cb6dcf53a4e..359b80b43169 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include /* Each queued (to userspace) skbuff has one of these. */ struct nf_queue_entry { diff --git a/include/net/netfilter/nf_reject.h b/include/net/netfilter/nf_reject.h index 221f877f29d1..9051c3a0c8e7 100644 --- a/include/net/netfilter/nf_reject.h +++ b/include/net/netfilter/nf_reject.h @@ -2,6 +2,9 @@ #ifndef _NF_REJECT_H #define _NF_REJECT_H +#include +#include + static inline bool nf_reject_verify_csum(__u8 proto) { /* Skip protocols that don't use 16-bit one's complement checksum diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h index dabe6fdb553a..d0f1c537b017 100644 --- a/include/net/netfilter/nf_tables_ipv6.h +++ b/include/net/netfilter/nf_tables_ipv6.h @@ -4,6 +4,7 @@ #include #include +#include static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, struct sk_buff *skb) diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h index e4c4d8eaca8c..628b6fa579cd 100644 --- a/include/net/netfilter/nft_fib.h +++ b/include/net/netfilter/nft_fib.h @@ -2,6 +2,8 @@ #ifndef _NFT_FIB_H_ #define _NFT_FIB_H_ +#include + struct nft_fib { enum nft_registers dreg:8; u8 result; diff --git a/include/net/netfilter/nft_meta.h b/include/net/netfilter/nft_meta.h index 5c69e9b09388..07e2fd507963 100644 --- a/include/net/netfilter/nft_meta.h +++ b/include/net/netfilter/nft_meta.h @@ -2,6 +2,8 @@ #ifndef _NFT_META_H_ #define _NFT_META_H_ +#include + struct nft_meta { enum nft_meta_keys key:8; union { diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h index de80c50761f0..56b123a42220 100644 --- a/include/net/netfilter/nft_reject.h +++ b/include/net/netfilter/nft_reject.h @@ -2,6 +2,11 @@ #ifndef _NFT_REJECT_H_ #define _NFT_REJECT_H_ +#include +#include +#include +#include + struct nft_reject { enum nft_reject_types type:8; u8 icmp_code; diff --git a/include/uapi/linux/netfilter/xt_policy.h b/include/uapi/linux/netfilter/xt_policy.h index 323bfa3074c5..4cf2ce2a8a44 100644 --- a/include/uapi/linux/netfilter/xt_policy.h +++ b/include/uapi/linux/netfilter/xt_policy.h @@ -2,6 +2,7 @@ #ifndef _XT_POLICY_H #define _XT_POLICY_H +#include #include #include #include -- GitLab From 9211bfbff80a7604273086fec5685efcdc10be2b Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:00 +0100 Subject: [PATCH 2779/7155] netfilter: add missing IS_ENABLED(CONFIG_BRIDGE_NETFILTER) checks to header-file. br_netfilter.h defines inline functions that use an enum constant and struct member that are only defined if CONFIG_BRIDGE_NETFILTER is enabled. Added preprocessor checks to ensure br_netfilter.h will compile if CONFIG_BRIDGE_NETFILTER is disabled. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/br_netfilter.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index ca121ed906df..33533ea852a1 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -8,12 +8,16 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) { +#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) struct nf_bridge_info *b = skb_ext_add(skb, SKB_EXT_BRIDGE_NF); if (b) memset(b, 0, sizeof(*b)); return b; +#else + return NULL; +#endif } void nf_bridge_update_protocol(struct sk_buff *skb); @@ -38,10 +42,14 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) { +#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) struct net_bridge_port *port; port = br_port_get_rcu(dev); return port ? &port->br->fake_rtable : NULL; +#else + return NULL; +#endif } struct net_device *setup_pre_routing(struct sk_buff *skb, -- GitLab From 47e640af2e492cc28778dd6f894d50313f7fba75 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:01 +0100 Subject: [PATCH 2780/7155] netfilter: add missing IS_ENABLED(CONFIG_NF_TABLES) check to header-file. nf_tables.h defines an API comprising several inline functions and macros that depend on the nft member of struct net. However, this is only defined is CONFIG_NF_TABLES is enabled. Added preprocessor checks to ensure that nf_tables.h will compile if CONFIG_NF_TABLES is disabled. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 9b624566b82d..66edf76301d3 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1207,6 +1207,8 @@ void nft_trace_notify(struct nft_traceinfo *info); #define MODULE_ALIAS_NFT_OBJ(type) \ MODULE_ALIAS("nft-obj-" __stringify(type)) +#if IS_ENABLED(CONFIG_NF_TABLES) + /* * The gencursor defines two generations, the currently active and the * next one. Objects contain a bitmask of 2 bits specifying the generations @@ -1280,6 +1282,8 @@ static inline void nft_set_elem_change_active(const struct net *net, ext->genmask ^= nft_genmask_next(net); } +#endif /* IS_ENABLED(CONFIG_NF_TABLES) */ + /* * We use a free bit in the genmask field to indicate the element * is busy, meaning it is currently being processed either by -- GitLab From 0abc8bf4f2842e409926096f0fa009b468cbd855 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:02 +0100 Subject: [PATCH 2781/7155] netfilter: add missing IS_ENABLED(CONFIG_NF_CONNTRACK) checks to some header-files. struct nf_conn contains a "struct nf_conntrack ct_general" member and struct net contains a "struct netns_ct ct" member which are both only defined in CONFIG_NF_CONNTRACK is enabled. These members are used in a number of inline functions defined in other header-files. Added preprocessor checks to make sure the headers will compile if CONFIG_NF_CONNTRACK is disabled. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack.h | 10 ++++++++++ include/net/netfilter/nf_conntrack_acct.h | 13 +++++++++++++ include/net/netfilter/nf_conntrack_l4proto.h | 2 ++ include/net/netfilter/nf_conntrack_timestamp.h | 6 ++++++ 4 files changed, 31 insertions(+) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index c86657d99630..2cc304efe7f9 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -59,6 +59,7 @@ struct nf_conntrack_net { #include struct nf_conn { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) /* Usage count in here is 1 for hash table, 1 per skb, * plus 1 for any connection(s) we are `master' for * @@ -68,6 +69,7 @@ struct nf_conn { * beware nf_ct_get() is different and don't inc refcnt. */ struct nf_conntrack ct_general; +#endif spinlock_t lock; /* jiffies32 when this ct is considered dead */ @@ -148,6 +150,8 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, int nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack); +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + #define NFCT_INFOMASK 7UL #define NFCT_PTRMASK ~(NFCT_INFOMASK) @@ -167,6 +171,8 @@ static inline void nf_ct_put(struct nf_conn *ct) nf_conntrack_put(&ct->ct_general); } +#endif + /* Protocol module loading */ int nf_ct_l3proto_try_module_get(unsigned short l3proto); void nf_ct_l3proto_module_put(unsigned short l3proto); @@ -318,12 +324,16 @@ void nf_ct_tmpl_free(struct nf_conn *tmpl); u32 nf_ct_get_id(const struct nf_conn *ct); +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + static inline void nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info) { skb->_nfct = (unsigned long)ct | info; } +#endif + #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v)) diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h index 1fee733c18a7..ad9f2172dee1 100644 --- a/include/net/netfilter/nf_conntrack_acct.h +++ b/include/net/netfilter/nf_conntrack_acct.h @@ -29,6 +29,7 @@ struct nf_conn_acct *nf_conn_acct_find(const struct nf_conn *ct) static inline struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp) { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) struct net *net = nf_ct_net(ct); struct nf_conn_acct *acct; @@ -41,22 +42,34 @@ struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp) return acct; +#else + return NULL; +#endif }; /* Check if connection tracking accounting is enabled */ static inline bool nf_ct_acct_enabled(struct net *net) { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) return net->ct.sysctl_acct != 0; +#else + return false; +#endif } /* Enable/disable connection tracking accounting */ static inline void nf_ct_set_acct(struct net *net, bool enable) { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) net->ct.sysctl_acct = enable; +#endif } +#if IS_ENABLED(CONFIG_NF_CONNTRACK) void nf_conntrack_acct_pernet_init(struct net *net); int nf_conntrack_acct_init(void); void nf_conntrack_acct_fini(void); +#endif /* IS_ENABLED(CONFIG_NF_CONNTRACK) */ + #endif /* _NF_CONNTRACK_ACCT_H */ diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index a49edfdf47e8..1990d54bf8f2 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -176,6 +176,7 @@ void nf_ct_l4proto_log_invalid(const struct sk_buff *skb, const char *fmt, ...) { } #endif /* CONFIG_SYSCTL */ +#if IS_ENABLED(CONFIG_NF_CONNTRACK) static inline struct nf_generic_net *nf_generic_pernet(struct net *net) { return &net->ct.nf_ct_proto.generic; @@ -200,6 +201,7 @@ static inline struct nf_icmp_net *nf_icmpv6_pernet(struct net *net) { return &net->ct.nf_ct_proto.icmpv6; } +#endif #ifdef CONFIG_NF_CT_PROTO_DCCP static inline struct nf_dccp_net *nf_dccp_pernet(struct net *net) diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h index 0ed617bf0a3d..2b8aeba649aa 100644 --- a/include/net/netfilter/nf_conntrack_timestamp.h +++ b/include/net/netfilter/nf_conntrack_timestamp.h @@ -40,12 +40,18 @@ struct nf_conn_tstamp *nf_ct_tstamp_ext_add(struct nf_conn *ct, gfp_t gfp) static inline bool nf_ct_tstamp_enabled(struct net *net) { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) return net->ct.sysctl_tstamp != 0; +#else + return false; +#endif } static inline void nf_ct_set_tstamp(struct net *net, bool enable) { +#if IS_ENABLED(CONFIG_NF_CONNTRACK) net->ct.sysctl_tstamp = enable; +#endif } #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP -- GitLab From 78458e3e08cda2aacaec9fde8c295dfc2f88618a Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:03 +0100 Subject: [PATCH 2782/7155] netfilter: add missing IS_ENABLED(CONFIG_NETFILTER) checks to some header-files. linux/netfilter.h defines a number of struct and inline function definitions which are only available is CONFIG_NETFILTER is enabled. These structs and functions are used in declarations and definitions in other header-files. Added preprocessor checks to make sure these headers will compile if CONFIG_NETFILTER is disabled. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 6 ++++++ include/linux/netfilter_arp/arp_tables.h | 2 ++ include/linux/netfilter_bridge/ebtables.h | 2 ++ include/linux/netfilter_ipv4/ip_tables.h | 4 ++++ include/linux/netfilter_ipv6/ip6_tables.h | 2 ++ include/net/netfilter/br_netfilter.h | 2 ++ include/net/netfilter/nf_conntrack_bridge.h | 2 ++ include/net/netfilter/nf_conntrack_core.h | 3 +++ include/net/netfilter/nf_conntrack_l4proto.h | 2 ++ include/net/netfilter/nf_conntrack_tuple.h | 2 ++ include/net/netfilter/nf_flow_table.h | 4 ++++ include/net/netfilter/nf_nat.h | 4 ++++ include/net/netfilter/nf_queue.h | 5 +++++ include/net/netfilter/nf_synproxy.h | 4 ++++ include/net/netfilter/nf_tables.h | 8 ++++++++ 15 files changed, 52 insertions(+) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 1f852ef7b098..ae62bf1c6824 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -35,12 +35,15 @@ struct xt_action_param { union { const void *matchinfo, *targinfo; }; +#if IS_ENABLED(CONFIG_NETFILTER) const struct nf_hook_state *state; +#endif int fragoff; unsigned int thoff; bool hotdrop; }; +#if IS_ENABLED(CONFIG_NETFILTER) static inline struct net *xt_net(const struct xt_action_param *par) { return par->state->net; @@ -75,6 +78,7 @@ static inline u_int8_t xt_family(const struct xt_action_param *par) { return par->state->pf; } +#endif /** * struct xt_mtchk_param - parameters for match extensions' @@ -446,7 +450,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu) return cnt; } +#if IS_ENABLED(CONFIG_NETFILTER) struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *); +#endif #ifdef CONFIG_COMPAT #include diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index e98028f00e47..1b7b35bb9c27 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -49,6 +49,7 @@ struct arpt_error { } extern void *arpt_alloc_initial_table(const struct xt_table *); +#if IS_ENABLED(CONFIG_NETFILTER) int arpt_register_table(struct net *net, const struct xt_table *table, const struct arpt_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); @@ -57,6 +58,7 @@ void arpt_unregister_table(struct net *net, struct xt_table *table, extern unsigned int arpt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); +#endif #ifdef CONFIG_COMPAT #include diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index c6935be7c6ca..b5b2d371f0ef 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -105,6 +105,7 @@ struct ebt_table { #define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \ ~(__alignof__(struct _xt_align)-1)) +#if IS_ENABLED(CONFIG_NETFILTER) extern int ebt_register_table(struct net *net, const struct ebt_table *table, const struct nf_hook_ops *ops, @@ -114,6 +115,7 @@ extern void ebt_unregister_table(struct net *net, struct ebt_table *table, extern unsigned int ebt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct ebt_table *table); +#endif /* True if the hook mask denotes that the rule is in a base chain, * used in the check() functions */ diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d026e63a5aa4..f40a65481df4 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -25,11 +25,13 @@ extern void ipt_init(void) __init; +#if IS_ENABLED(CONFIG_NETFILTER) int ipt_register_table(struct net *net, const struct xt_table *table, const struct ipt_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); void ipt_unregister_table(struct net *net, struct xt_table *table, const struct nf_hook_ops *ops); +#endif /* Standard entry. */ struct ipt_standard { @@ -65,9 +67,11 @@ struct ipt_error { } extern void *ipt_alloc_initial_table(const struct xt_table *); +#if IS_ENABLED(CONFIG_NETFILTER) extern unsigned int ipt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); +#endif #ifdef CONFIG_COMPAT #include diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 99cbfd3add40..53b7309613bf 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -26,6 +26,7 @@ extern void ip6t_init(void) __init; extern void *ip6t_alloc_initial_table(const struct xt_table *); +#if IS_ENABLED(CONFIG_NETFILTER) int ip6t_register_table(struct net *net, const struct xt_table *table, const struct ip6t_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); @@ -34,6 +35,7 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table, extern unsigned int ip6t_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); +#endif /* Check for an extension */ static inline int diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index 33533ea852a1..2a613c84d49f 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -55,6 +55,7 @@ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) struct net_device *setup_pre_routing(struct sk_buff *skb, const struct net *net); +#if IS_ENABLED(CONFIG_NETFILTER) #if IS_ENABLED(CONFIG_IPV6) int br_validate_ipv6(struct net *net, struct sk_buff *skb); unsigned int br_nf_pre_routing_ipv6(void *priv, @@ -73,5 +74,6 @@ br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, struct sk_buff *skb, return NF_ACCEPT; } #endif +#endif #endif /* _BR_NETFILTER_H_ */ diff --git a/include/net/netfilter/nf_conntrack_bridge.h b/include/net/netfilter/nf_conntrack_bridge.h index 8f2e5b2ab523..34c28f248b18 100644 --- a/include/net/netfilter/nf_conntrack_bridge.h +++ b/include/net/netfilter/nf_conntrack_bridge.h @@ -6,7 +6,9 @@ #include struct nf_ct_bridge_info { +#if IS_ENABLED(CONFIG_NETFILTER) struct nf_hook_ops *ops; +#endif unsigned int ops_size; struct module *me; }; diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index de10faf2ce91..71a2d9cb64ea 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -20,7 +20,10 @@ /* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use of connection tracking. */ + +#if IS_ENABLED(CONFIG_NETFILTER) unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state); +#endif int nf_conntrack_init_net(struct net *net); void nf_conntrack_cleanup_net(struct net *net); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 1990d54bf8f2..c200b95d27ae 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -75,6 +75,7 @@ bool nf_conntrack_invert_icmp_tuple(struct nf_conntrack_tuple *tuple, bool nf_conntrack_invert_icmpv6_tuple(struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *orig); +#if IS_ENABLED(CONFIG_NETFILTER) int nf_conntrack_inet_error(struct nf_conn *tmpl, struct sk_buff *skb, unsigned int dataoff, const struct nf_hook_state *state, @@ -131,6 +132,7 @@ int nf_conntrack_gre_packet(struct nf_conn *ct, unsigned int dataoff, enum ip_conntrack_info ctinfo, const struct nf_hook_state *state); +#endif void nf_conntrack_generic_init_net(struct net *net); void nf_conntrack_tcp_init_net(struct net *net); diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index bf0444e111a6..480c87b44a96 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -121,6 +121,7 @@ struct nf_conntrack_tuple_hash { struct nf_conntrack_tuple tuple; }; +#if IS_ENABLED(CONFIG_NETFILTER) static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1, const struct nf_conntrack_tuple *t2) { @@ -183,5 +184,6 @@ nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t, return nf_ct_tuple_src_mask_cmp(t, tuple, mask) && __nf_ct_tuple_dst_equal(t, tuple); } +#endif #endif /* _NF_CONNTRACK_TUPLE_H */ diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index 7249e331bd0b..609df33b1209 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -17,7 +17,9 @@ struct nf_flowtable_type { int family; int (*init)(struct nf_flowtable *ft); void (*free)(struct nf_flowtable *ft); +#if IS_ENABLED(CONFIG_NETFILTER) nf_hookfn *hook; +#endif struct module *owner; }; @@ -115,10 +117,12 @@ struct flow_ports { __be16 source, dest; }; +#if IS_ENABLED(CONFIG_NETFILTER) unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); +#endif #define MODULE_ALIAS_NF_FLOWTABLE(family) \ MODULE_ALIAS("nf-flowtable-" __stringify(family)) diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 423cda2c6542..eec208fb9c23 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -69,10 +69,12 @@ static inline bool nf_nat_oif_changed(unsigned int hooknum, #endif } +#if IS_ENABLED(CONFIG_NETFILTER) int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops, const struct nf_hook_ops *nat_ops, unsigned int ops_count); void nf_nat_unregister_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops, unsigned int ops_count); +#endif unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, struct sk_buff *skb); @@ -92,6 +94,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, unsigned int hdrlen); +#if IS_ENABLED(CONFIG_NETFILTER) int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops); void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops); @@ -104,6 +107,7 @@ void nf_nat_inet_unregister_fn(struct net *net, const struct nf_hook_ops *ops); unsigned int nf_nat_inet_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); +#endif int nf_xfrm_me_harder(struct net *n, struct sk_buff *s, unsigned int family); diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 359b80b43169..80edb46a1bbc 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -15,7 +15,9 @@ struct nf_queue_entry { unsigned int id; unsigned int hook_index; /* index in hook_entries->hook[] */ +#if IS_ENABLED(CONFIG_NETFILTER) struct nf_hook_state state; +#endif u16 size; /* sizeof(entry) + saved route keys */ /* extra space to store route keys */ @@ -121,6 +123,9 @@ nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family, return queue; } +#if IS_ENABLED(CONFIG_NETFILTER) int nf_queue(struct sk_buff *skb, struct nf_hook_state *state, unsigned int index, unsigned int verdict); +#endif + #endif /* _NF_QUEUE_H */ diff --git a/include/net/netfilter/nf_synproxy.h b/include/net/netfilter/nf_synproxy.h index 87d73fb5279d..dc420b47e3aa 100644 --- a/include/net/netfilter/nf_synproxy.h +++ b/include/net/netfilter/nf_synproxy.h @@ -20,8 +20,10 @@ bool synproxy_recv_client_ack(struct net *net, const struct tcphdr *th, struct synproxy_options *opts, u32 recv_seq); +#if IS_ENABLED(CONFIG_NETFILTER) unsigned int ipv4_synproxy_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *nhs); +#endif int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net); void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net); @@ -35,8 +37,10 @@ bool synproxy_recv_client_ack_ipv6(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, struct synproxy_options *opts, u32 recv_seq); +#if IS_ENABLED(CONFIG_NETFILTER) unsigned int ipv6_synproxy_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *nhs); +#endif int nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net); void nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net); #else diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 66edf76301d3..dc301e3d6739 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -25,6 +25,7 @@ struct nft_pktinfo { struct xt_action_param xt; }; +#if IS_ENABLED(CONFIG_NETFILTER) static inline struct net *nft_net(const struct nft_pktinfo *pkt) { return pkt->xt.state->net; @@ -57,6 +58,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, pkt->skb = skb; pkt->xt.state = state; } +#endif static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, struct sk_buff *skb) @@ -927,9 +929,11 @@ struct nft_chain_type { int family; struct module *owner; unsigned int hook_mask; +#if IS_ENABLED(CONFIG_NETFILTER) nf_hookfn *hooks[NF_MAX_HOOKS]; int (*ops_register)(struct net *net, const struct nf_hook_ops *ops); void (*ops_unregister)(struct net *net, const struct nf_hook_ops *ops); +#endif }; int nft_chain_validate_dependency(const struct nft_chain *chain, @@ -955,7 +959,9 @@ struct nft_stats { * @flow_block: flow block (for hardware offload) */ struct nft_base_chain { +#if IS_ENABLED(CONFIG_NETFILTER) struct nf_hook_ops ops; +#endif const struct nft_chain_type *type; u8 policy; u8 flags; @@ -1152,7 +1158,9 @@ struct nft_flowtable { use:30; u64 handle; /* runtime data below here */ +#if IS_ENABLED(CONFIG_NETFILTER) struct nf_hook_ops *ops ____cacheline_aligned; +#endif struct nf_flowtable data; }; -- GitLab From 20a9379d9a03ee0712d225035308973ecc5f6783 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:04 +0100 Subject: [PATCH 2783/7155] netfilter: remove "#ifdef __KERNEL__" guards from some headers. A number of non-UAPI Netfilter header-files contained superfluous "#ifdef __KERNEL__" guards. Removed them. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_conntrack_dccp.h | 3 --- include/linux/netfilter/nf_conntrack_h323.h | 4 ---- include/linux/netfilter/nf_conntrack_irc.h | 3 --- include/linux/netfilter/nf_conntrack_pptp.h | 3 --- include/linux/netfilter/nf_conntrack_proto_gre.h | 2 -- include/linux/netfilter/nf_conntrack_sane.h | 4 ---- include/linux/netfilter/nf_conntrack_sip.h | 2 -- 7 files changed, 21 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_dccp.h b/include/linux/netfilter/nf_conntrack_dccp.h index ace0f952d50f..c509ed76e714 100644 --- a/include/linux/netfilter/nf_conntrack_dccp.h +++ b/include/linux/netfilter/nf_conntrack_dccp.h @@ -25,7 +25,6 @@ enum ct_dccp_roles { }; #define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1) -#ifdef __KERNEL__ #include struct nf_ct_dccp { @@ -36,6 +35,4 @@ struct nf_ct_dccp { u_int64_t handshake_seq; }; -#endif /* __KERNEL__ */ - #endif /* _NF_CONNTRACK_DCCP_H */ diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index 96dfa886f8c0..4561ec0fcea4 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -2,8 +2,6 @@ #ifndef _NF_CONNTRACK_H323_H #define _NF_CONNTRACK_H323_H -#ifdef __KERNEL__ - #include #include #include @@ -97,5 +95,3 @@ extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct, struct nf_conntrack_expect *exp); #endif - -#endif diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h index f75e005db969..d02255f721e1 100644 --- a/include/linux/netfilter/nf_conntrack_irc.h +++ b/include/linux/netfilter/nf_conntrack_irc.h @@ -2,8 +2,6 @@ #ifndef _NF_CONNTRACK_IRC_H #define _NF_CONNTRACK_IRC_H -#ifdef __KERNEL__ - #include #include #include @@ -17,5 +15,4 @@ extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, unsigned int matchlen, struct nf_conntrack_expect *exp); -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_IRC_H */ diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index 3f10e806f0dc..fcc409de31a4 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -50,8 +50,6 @@ struct nf_nat_pptp { __be16 pac_call_id; /* NAT'ed PAC call id */ }; -#ifdef __KERNEL__ - #define PPTP_CONTROL_PORT 1723 #define PPTP_PACKET_CONTROL 1 @@ -324,5 +322,4 @@ extern void (*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_PPTP_H */ diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h index 25f9a770fb84..f33aa6021364 100644 --- a/include/linux/netfilter/nf_conntrack_proto_gre.h +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -10,7 +10,6 @@ struct nf_ct_gre { unsigned int timeout; }; -#ifdef __KERNEL__ #include struct nf_conn; @@ -32,5 +31,4 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct); bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct net *net, struct nf_conntrack_tuple *tuple); -#endif /* __KERNEL__ */ #endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/include/linux/netfilter/nf_conntrack_sane.h b/include/linux/netfilter/nf_conntrack_sane.h index 7d2de44edce3..46c7acd1b4a7 100644 --- a/include/linux/netfilter/nf_conntrack_sane.h +++ b/include/linux/netfilter/nf_conntrack_sane.h @@ -3,8 +3,6 @@ #define _NF_CONNTRACK_SANE_H /* SANE tracking. */ -#ifdef __KERNEL__ - #define SANE_PORT 6566 enum sane_state { @@ -17,6 +15,4 @@ struct nf_ct_sane_master { enum sane_state state; }; -#endif /* __KERNEL__ */ - #endif /* _NF_CONNTRACK_SANE_H */ diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index f6437f7841af..c620521c42bc 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __NF_CONNTRACK_SIP_H__ #define __NF_CONNTRACK_SIP_H__ -#ifdef __KERNEL__ #include #include @@ -196,5 +195,4 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, enum sdp_header_types term, unsigned int *matchoff, unsigned int *matchlen); -#endif /* __KERNEL__ */ #endif /* __NF_CONNTRACK_SIP_H__ */ -- GitLab From 2a475c409fe81a76fb26a6b023509d648237bbe6 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 7 Aug 2019 15:17:05 +0100 Subject: [PATCH 2784/7155] kbuild: remove all netfilter headers from header-test blacklist. All the blacklisted NF headers can now be compiled stand-alone, so removed them from the blacklist. Cc: Masahiro Yamada Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/Kbuild | 74 -------------------------------------------------- 1 file changed, 74 deletions(-) diff --git a/include/Kbuild b/include/Kbuild index c38f0d46b267..af498acb7cd2 100644 --- a/include/Kbuild +++ b/include/Kbuild @@ -386,31 +386,6 @@ header-test- += linux/mvebu-pmsu.h header-test- += linux/mxm-wmi.h header-test- += linux/n_r3964.h header-test- += linux/ndctl.h -header-test- += linux/netfilter/ipset/ip_set.h -header-test- += linux/netfilter/ipset/ip_set_bitmap.h -header-test- += linux/netfilter/ipset/ip_set_comment.h -header-test- += linux/netfilter/ipset/ip_set_counter.h -header-test- += linux/netfilter/ipset/ip_set_getport.h -header-test- += linux/netfilter/ipset/ip_set_hash.h -header-test- += linux/netfilter/ipset/ip_set_list.h -header-test- += linux/netfilter/ipset/ip_set_skbinfo.h -header-test- += linux/netfilter/ipset/ip_set_timeout.h -header-test- += linux/netfilter/nf_conntrack_amanda.h -header-test- += linux/netfilter/nf_conntrack_ftp.h -header-test- += linux/netfilter/nf_conntrack_h323.h -header-test- += linux/netfilter/nf_conntrack_h323_asn1.h -header-test- += linux/netfilter/nf_conntrack_irc.h -header-test- += linux/netfilter/nf_conntrack_pptp.h -header-test- += linux/netfilter/nf_conntrack_proto_gre.h -header-test- += linux/netfilter/nf_conntrack_sip.h -header-test- += linux/netfilter/nf_conntrack_snmp.h -header-test- += linux/netfilter/nf_conntrack_tftp.h -header-test- += linux/netfilter/x_tables.h -header-test- += linux/netfilter_arp/arp_tables.h -header-test- += linux/netfilter_bridge/ebtables.h -header-test- += linux/netfilter_ipv4/ip4_tables.h -header-test- += linux/netfilter_ipv4/ip_tables.h -header-test- += linux/netfilter_ipv6/ip6_tables.h header-test- += linux/nfs.h header-test- += linux/nfs_fs_i.h header-test- += linux/nfs_fs_sb.h @@ -874,43 +849,6 @@ header-test- += net/mpls_iptunnel.h header-test- += net/mrp.h header-test- += net/ncsi.h header-test- += net/netevent.h -header-test- += net/netfilter/br_netfilter.h -header-test- += net/netfilter/ipv4/nf_dup_ipv4.h -header-test- += net/netfilter/ipv6/nf_defrag_ipv6.h -header-test- += net/netfilter/ipv6/nf_dup_ipv6.h -header-test- += net/netfilter/nf_conntrack.h -header-test- += net/netfilter/nf_conntrack_acct.h -header-test- += net/netfilter/nf_conntrack_bridge.h -header-test- += net/netfilter/nf_conntrack_core.h -header-test- += net/netfilter/nf_conntrack_count.h -header-test- += net/netfilter/nf_conntrack_ecache.h -header-test- += net/netfilter/nf_conntrack_expect.h -header-test- += net/netfilter/nf_conntrack_extend.h -header-test- += net/netfilter/nf_conntrack_helper.h -header-test- += net/netfilter/nf_conntrack_l4proto.h -header-test- += net/netfilter/nf_conntrack_labels.h -header-test- += net/netfilter/nf_conntrack_seqadj.h -header-test- += net/netfilter/nf_conntrack_synproxy.h -header-test- += net/netfilter/nf_conntrack_timeout.h -header-test- += net/netfilter/nf_conntrack_timestamp.h -header-test- += net/netfilter/nf_conntrack_tuple.h -header-test- += net/netfilter/nf_dup_netdev.h -header-test- += net/netfilter/nf_flow_table.h -header-test- += net/netfilter/nf_nat.h -header-test- += net/netfilter/nf_nat_helper.h -header-test- += net/netfilter/nf_nat_masquerade.h -header-test- += net/netfilter/nf_nat_redirect.h -header-test- += net/netfilter/nf_queue.h -header-test- += net/netfilter/nf_reject.h -header-test- += net/netfilter/nf_synproxy.h -header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables.h -header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_core.h -header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_ipv4.h -header-test- += net/netfilter/nf_tables_ipv6.h -header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_offload.h -header-test- += net/netfilter/nft_fib.h -header-test- += net/netfilter/nft_meta.h -header-test- += net/netfilter/nft_reject.h header-test- += net/netns/can.h header-test- += net/netns/generic.h header-test- += net/netns/ieee802154_6lowpan.h @@ -1140,18 +1078,6 @@ header-test- += uapi/linux/kvm_para.h header-test- += uapi/linux/lightnvm.h header-test- += uapi/linux/mic_common.h header-test- += uapi/linux/mman.h -header-test- += uapi/linux/netfilter/ipset/ip_set_bitmap.h -header-test- += uapi/linux/netfilter/ipset/ip_set_hash.h -header-test- += uapi/linux/netfilter/ipset/ip_set_list.h -header-test- += uapi/linux/netfilter/nf_synproxy.h -header-test- += uapi/linux/netfilter/xt_policy.h -header-test- += uapi/linux/netfilter/xt_set.h -header-test- += uapi/linux/netfilter_arp/arp_tables.h -header-test- += uapi/linux/netfilter_arp/arpt_mangle.h -header-test- += uapi/linux/netfilter_ipv4/ip_tables.h -header-test- += uapi/linux/netfilter_ipv4/ipt_LOG.h -header-test- += uapi/linux/netfilter_ipv6/ip6_tables.h -header-test- += uapi/linux/netfilter_ipv6/ip6t_LOG.h header-test- += uapi/linux/nilfs2_ondisk.h header-test- += uapi/linux/patchkey.h header-test- += uapi/linux/ptrace.h -- GitLab From 5785cf15fd74ec3b1a076fd39bc67382a8455fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valdis=20Kl=C4=93tnieks?= Date: Thu, 8 Aug 2019 01:28:08 -0400 Subject: [PATCH 2785/7155] netfilter: nf_tables: add missing prototypes. Sparse rightly complains about undeclared symbols. CHECK net/netfilter/nft_set_hash.c net/netfilter/nft_set_hash.c:647:21: warning: symbol 'nft_set_rhash_type' was not declared. Should it be static? net/netfilter/nft_set_hash.c:670:21: warning: symbol 'nft_set_hash_type' was not declared. Should it be static? net/netfilter/nft_set_hash.c:690:21: warning: symbol 'nft_set_hash_fast_type' was not declared. Should it be static? CHECK net/netfilter/nft_set_bitmap.c net/netfilter/nft_set_bitmap.c:296:21: warning: symbol 'nft_set_bitmap_type' was not declared. Should it be static? CHECK net/netfilter/nft_set_rbtree.c net/netfilter/nft_set_rbtree.c:470:21: warning: symbol 'nft_set_rbtree_type' was not declared. Should it be static? Include nf_tables_core.h rather than nf_tables.h to pick up the additional definitions. Signed-off-by: Valdis Kletnieks Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_set_bitmap.c | 2 +- net/netfilter/nft_set_hash.c | 2 +- net/netfilter/nft_set_rbtree.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index b5aeccdddb22..087a056e34d1 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include struct nft_bitmap_elem { struct list_head head; diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 6e8d20c03e3d..c490451fcebf 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include /* We target a hash table size of 4, element hint is 75% of final size */ #define NFT_RHASH_ELEMENT_HINT 3 diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 419d58ef802b..57123259452f 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include struct nft_rbtree { struct rb_root root; -- GitLab From 0a30ba509fdeea740bedb81ce3bee4f74a759654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valdis=20Kl=C4=93tnieks?= Date: Thu, 8 Aug 2019 01:43:22 -0400 Subject: [PATCH 2786/7155] netfilter: nf_nat_proto: make tables static Sparse warns about two tables not being declared. CHECK net/netfilter/nf_nat_proto.c net/netfilter/nf_nat_proto.c:725:26: warning: symbol 'nf_nat_ipv4_ops' was not declared. Should it be static? net/netfilter/nf_nat_proto.c:964:26: warning: symbol 'nf_nat_ipv6_ops' was not declared. Should it be static? And in fact they can indeed be static. Signed-off-by: Valdis Kletnieks Acked-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_nat_proto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c index 7ac733ebd060..0a59c14b5177 100644 --- a/net/netfilter/nf_nat_proto.c +++ b/net/netfilter/nf_nat_proto.c @@ -722,7 +722,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, return ret; } -const struct nf_hook_ops nf_nat_ipv4_ops[] = { +static const struct nf_hook_ops nf_nat_ipv4_ops[] = { /* Before packet filtering, change destination */ { .hook = nf_nat_ipv4_in, @@ -961,7 +961,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, return ret; } -const struct nf_hook_ops nf_nat_ipv6_ops[] = { +static const struct nf_hook_ops nf_nat_ipv6_ops[] = { /* Before packet filtering, change destination */ { .hook = nf_nat_ipv6_in, -- GitLab From 105333435b4f3b21ffc325f32fae17719310db64 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 12 Aug 2019 13:40:04 +0200 Subject: [PATCH 2787/7155] netfilter: connlabels: prefer static lock initialiser seen during boot: BUG: spinlock bad magic on CPU#2, swapper/0/1 lock: nf_connlabels_lock+0x0/0x60, .magic: 00000000, .owner: /-1, .owner_cpu: 0 Call Trace: do_raw_spin_lock+0x14e/0x1b0 nf_connlabels_get+0x15/0x40 ct_init_net+0xc4/0x270 ops_init+0x56/0x1c0 register_pernet_operations+0x1c8/0x350 register_pernet_subsys+0x1f/0x40 tcf_register_action+0x7c/0x1a0 do_one_initcall+0x13d/0x2d9 Problem is that ct action init function can run before connlabels_init(). Lock has not been initialised yet. Fix it by using a static initialiser. Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_labels.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index 74b8113f7aeb..d1c6b2a2e7bd 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c @@ -11,7 +11,7 @@ #include #include -static spinlock_t nf_connlabels_lock; +static __read_mostly DEFINE_SPINLOCK(nf_connlabels_lock); static int replace_u32(u32 *address, u32 mask, u32 new) { @@ -89,7 +89,6 @@ int nf_conntrack_labels_init(void) { BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE / sizeof(long) >= U8_MAX); - spin_lock_init(&nf_connlabels_lock); return nf_ct_extend_register(&labels_extend); } -- GitLab From 7188f656cdf762d4ea8ce16b6aaf4c6b06e119ec Mon Sep 17 00:00:00 2001 From: Cheng-Yi Chiang Date: Tue, 13 Aug 2019 15:44:30 +0800 Subject: [PATCH 2788/7155] ASoC: rockchip: rockchip_max98090: Set period size to 240 From stress testing of arecord, we found that period size greater than ~900 will bring pl330 to DYING state and can not recover within 100 iterations. The result is that arecord will stuck and get I/O error, and issue can not be recovered until reboot. This issue does not happen when period size is small. Set constraint of period size to 240 to prevent such issue. With the constraint, there will be no issue after 2000 iterations. We can revert this patch once the root cause is found in rockchip's pl330 implementation. Signed-off-by: Cheng-Yi Chiang Link: https://lore.kernel.org/r/20190813074430.191791-1-cychiang@chromium.org Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 782e534d4c0d..d54f672d38d8 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -138,8 +138,19 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, return ret; } +static int rk_aif1_startup(struct snd_pcm_substream *substream) +{ + /* + * Set period size to 240 because pl330 has issue + * dealing with larger period in stress testing. + */ + return snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 240, 240); +} + static const struct snd_soc_ops rk_aif1_ops = { .hw_params = rk_aif1_hw_params, + .startup = rk_aif1_startup, }; SND_SOC_DAILINK_DEFS(hifi, -- GitLab From ae3a5901dde2ab136ec0cebda2fccc48e810d2ec Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 13 Aug 2019 12:42:35 +0900 Subject: [PATCH 2789/7155] ASoC: ti: Fix typos in ti/Kconfig This patch fixes some spelling typo in Kconfig. Signed-off-by: Masanari Iida Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20190813034235.30673-1-standby24x7@gmail.com Signed-off-by: Mark Brown --- sound/soc/ti/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index 2197f3e1eaed..87a9b9dd4e98 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -12,7 +12,7 @@ config SND_SOC_TI_SDMA_PCM comment "Texas Instruments DAI support for:" config SND_SOC_DAVINCI_ASP - tristate "daVinci Audio Serial Port (ASP) or McBSP suport" + tristate "daVinci Audio Serial Port (ASP) or McBSP support" depends on ARCH_DAVINCI || COMPILE_TEST select SND_SOC_TI_EDMA_PCM help @@ -33,7 +33,7 @@ config SND_SOC_DAVINCI_MCASP - Keystone devices config SND_SOC_DAVINCI_VCIF - tristate "daVinci Voice Interface (VCIF) suport" + tristate "daVinci Voice Interface (VCIF) support" depends on ARCH_DAVINCI || COMPILE_TEST select SND_SOC_TI_EDMA_PCM help -- GitLab From 8da2d74c10fd71cc04e2585fe8bb3ced325f8e25 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 12 Aug 2019 09:03:05 -0500 Subject: [PATCH 2790/7155] ASoC: Intel: hsw: remove i386 build warning w/ size_t argument Recent changes in the common IPC code introduced a build warning with size_t fields, use the correct %zu format. include/linux/dynamic_debug.h:82:16: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'size_t' [-Wformat=] Fixes: abf31feea26c0 ('ASoC: Intel: Update request-reply IPC model') Reported-by: kbuild test robot Cc: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Acked-By: Cezary Rojewski Link: https://lore.kernel.org/r/20190812140305.17570-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/haswell/sst-haswell-ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 5c73b11375e3..0ff89ea96ccf 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -2015,11 +2015,11 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) { /* short parameter, mailbox can contain data */ - dev_dbg(dev, "transfer parameter size : %lu\n", + dev_dbg(dev, "transfer parameter size : %zu\n", request.size); request.size = ALIGN(payload_size, 4); - dev_dbg(dev, "transfer parameter aligned size : %lu\n", + dev_dbg(dev, "transfer parameter aligned size : %zu\n", request.size); parameter = kzalloc(request.size, GFP_KERNEL); -- GitLab From 9c6c417d95d83999c16965186f6e755ad8a8b658 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 12 Aug 2019 14:05:02 -0500 Subject: [PATCH 2791/7155] ASoC: SOF: fix HDA direct MMIO access The recent change to remove the bus->io_ops callbacks used an older version of the SOF code base, and when merged into Mark's for-next it invalidated changes, resulting in broken compilation identified by kbuild and reproduced during the weekly SOF rebase. Restore SOF code overridden by git merge and apply Takashi's intended change in the 'right' location. Fixes: c2f16a94a8049 ("Merge branch 'topic/hda-bus-ops-cleanup'") Reported-by: kbuild test robot Cc: Takashi Iwai Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190812190502.30729-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 39 ---------------------------------- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index a7fee403cb90..bc41028a7a01 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -254,7 +254,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* Reset stream-to-link mapping */ list_for_each_entry(hlink, &bus->hlink_list, list) - bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); + writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); #endif bus->chip_init = true; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 097727cda5cb..fb55a3c5afd0 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -354,45 +354,6 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) return ret; } - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* Reset stream-to-link mapping */ - list_for_each_entry(hlink, &bus->hlink_list, list) - writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); -#else - - hda_dsp_ctrl_misc_clock_gating(sdev, false); - - /* reset controller */ - ret = hda_dsp_ctrl_link_reset(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to reset controller during resume\n"); - return ret; - } - - /* take controller out of reset */ - ret = hda_dsp_ctrl_link_reset(sdev, false); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to ready controller during resume\n"); - return ret; - } - - /* enable hda bus irq */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); - - hda_dsp_ctrl_misc_clock_gating(sdev, true); -#endif - - /* enable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, true); - hda_dsp_ctrl_ppcap_int_enable(sdev, true); - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* check jack status */ if (runtime_resume) -- GitLab From dc1b6ca8fa66fac58e133786295fac0a237e6d73 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 21 Jul 2019 20:24:54 -0300 Subject: [PATCH 2792/7155] ARM: dts: am335x-cm-t335: Remove regulator-boot-off property This property was never supported upstream. Get rid of it. Signed-off-by: Ezequiel Garcia Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-cm-t335.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts index ceecbfd29d2c..1fe3b566ba3d 100644 --- a/arch/arm/boot/dts/am335x-cm-t335.dts +++ b/arch/arm/boot/dts/am335x-cm-t335.dts @@ -44,7 +44,6 @@ regulator-name = "vwlan_fixed"; gpio = <&gpio0 20 GPIO_ACTIVE_HIGH>; /* gpio0_20 */ enable-active-high; - regulator-boot-off; }; backlight { -- GitLab From 9fc6bff8078ba350ca335eeab81d568073d44f65 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 21 Jul 2019 20:24:55 -0300 Subject: [PATCH 2793/7155] ARM: dts: omap3-n950-n9: Remove regulator-boot-off property This property was never supported upstream. Get rid of it. Signed-off-by: Ezequiel Garcia Acked-by: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950-n9.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index 5441e9ffdbb4..6681d4519e97 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -41,7 +41,6 @@ regulator-name = "VWLAN"; gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>; /* gpio 35 */ enable-active-high; - regulator-boot-off; }; leds { -- GitLab From 26b1c8bed58637d88022ca2a937fc9c031f6dd31 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 8 Jul 2019 16:46:04 +0200 Subject: [PATCH 2794/7155] ARM: dts: gta04: define chosen/stdout-path This allows to remove the console= entry in the kernel command line. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-gta04.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi index b295f6fad2a5..d01fc8744fd7 100644 --- a/arch/arm/boot/dts/omap3-gta04.dtsi +++ b/arch/arm/boot/dts/omap3-gta04.dtsi @@ -24,6 +24,10 @@ reg = <0x80000000 0x20000000>; /* 512 MB */ }; + chosen { + stdout-path = &uart3; + }; + aliases { display0 = &lcd; display1 = &tv0; -- GitLab From a27401cecf7795cda7e0c17751feb98fedbaa99d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 7 Aug 2019 15:09:34 -0500 Subject: [PATCH 2795/7155] ARM: dts: am335x-boneblue: Use of am335x-osd335x-common.dtsi This makes use of the am335x-osd335x-common.dtsi file that contains the common device tree components for Octavo Systems AM335x System-in- Package that is used on the BeagleBone Blue. This has two minor side-effects: 1. pinmux_i2c0_pins is renamed to pinmux-i2c0-pins 2. the 1000MHz cpufreq operating point is enabled Cc: Robert Nelson Signed-off-by: David Lechner Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-boneblue.dts | 92 +-------------------------- 1 file changed, 2 insertions(+), 90 deletions(-) diff --git a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts index 0257576d5d16..2f6652ef9a15 100644 --- a/arch/arm/boot/dts/am335x-boneblue.dts +++ b/arch/arm/boot/dts/am335x-boneblue.dts @@ -5,23 +5,13 @@ /dts-v1/; #include "am33xx.dtsi" +#include "am335x-osd335x-common.dtsi" #include / { model = "TI AM335x BeagleBone Blue"; compatible = "ti,am335x-bone-blue", "ti,am33xx"; - cpus { - cpu@0 { - cpu0-supply = <&dcdc2_reg>; - }; - }; - - memory@80000000 { - device_type = "memory"; - reg = <0x80000000 0x20000000>; /* 512 MB */ - }; - chosen { stdout-path = &uart0; }; @@ -142,13 +132,6 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { - pinctrl-single,pins = < - AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */ - AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */ - >; - }; - i2c2_pins: pinmux_i2c2_pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* (D18) uart1_ctsn.I2C2_SDA */ @@ -328,16 +311,6 @@ }; &i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins>; - - status = "okay"; - clock-frequency = <400000>; - - tps: tps@24 { - reg = <0x24>; - }; - baseboard_eeprom: baseboard_eeprom@50 { compatible = "atmel,24c256"; reg = <0x50>; @@ -381,66 +354,13 @@ /include/ "tps65217.dtsi" &tps { - interrupts = <7>; /* NMI */ - interrupt-parent = <&intc>; + /delete-property/ ti,pmic-shutdown-controller; charger { interrupts = <0>, <1>; interrupt-names = "USB", "AC"; status = "okay"; }; - - pwrbutton { - interrupts = <2>; - status = "okay"; - }; - - regulators { - dcdc1_reg: regulator@0 { - regulator-name = "vdds_dpr"; - regulator-always-on; - }; - - dcdc2_reg: regulator@1 { - /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ - regulator-name = "vdd_mpu"; - regulator-min-microvolt = <925000>; - regulator-max-microvolt = <1351500>; - regulator-boot-on; - regulator-always-on; - }; - - dcdc3_reg: regulator@2 { - /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ - regulator-name = "vdd_core"; - regulator-min-microvolt = <925000>; - regulator-max-microvolt = <1150000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo1_reg: regulator@3 { - regulator-name = "vio,vrtc,vdds"; - regulator-always-on; - }; - - ldo2_reg: regulator@4 { - regulator-name = "vdd_3v3aux"; - regulator-always-on; - }; - - ldo3_reg: regulator@5 { - regulator-name = "vdd_1v8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - ldo4_reg: regulator@6 { - regulator-name = "vdd_3v3a"; - regulator-always-on; - }; - }; }; &mmc1 { @@ -502,14 +422,6 @@ }; }; -&aes { - status = "okay"; -}; - -&sham { - status = "okay"; -}; - &rtc { system-power-controller; clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; -- GitLab From 115f3bad1a36791b5293aeebde342a95a516198e Mon Sep 17 00:00:00 2001 From: Matthias Maennich Date: Tue, 13 Aug 2019 13:17:06 +0100 Subject: [PATCH 2796/7155] usb-storage: remove single-use define for debugging USB_STORAGE was defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call. Signed-off-by: Matthias Maennich Link: https://lore.kernel.org/r/20190813121733.52480-10-maennich@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h index 6d64f342f587..16ce06039a4d 100644 --- a/drivers/usb/storage/debug.h +++ b/drivers/usb/storage/debug.h @@ -29,8 +29,6 @@ #include -#define USB_STORAGE "usb-storage: " - #ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key, diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 05b80211290d..df4de8323eff 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb, /* check for state-transition errors */ if (us->srb != NULL) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", + printk(KERN_ERR "usb-storage: Error in %s: us->srb = %p\n", __func__, us->srb); return SCSI_MLQUEUE_HOST_BUSY; } -- GitLab From c08b598410559c7006f2cea04ba80646eb214212 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 13 Aug 2019 09:27:31 +0200 Subject: [PATCH 2797/7155] ARM: dts: nomadik: Set up the CS GPIO right Now that the SPI GPIO driver knows how to handle these chip select GPIOs and we get nasty messages about the core having to enforce active low on the GPIO, fix this up by actually requesting the CS GPIO line as active low. Link: https://lore.kernel.org/r/20190813072731.4558-1-linus.walleij@linaro.org Signed-off-by: Linus Walleij Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/ste-nomadik-nhk15.dts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/ste-nomadik-nhk15.dts index 04066f9cb8a3..41ed21a4fdc1 100644 --- a/arch/arm/boot/dts/ste-nomadik-nhk15.dts +++ b/arch/arm/boot/dts/ste-nomadik-nhk15.dts @@ -212,13 +212,7 @@ */ gpio-sck = <&gpio0 5 GPIO_ACTIVE_HIGH>; gpio-mosi = <&gpio0 4 GPIO_ACTIVE_HIGH>; - /* - * It's not actually active high, but the frameworks assume - * the polarity of the passed-in GPIO is "normal" (active - * high) then actively drives the line low to select the - * chip. - */ - cs-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; num-chipselects = <1>; /* -- GitLab From da5fbcb1d03a41c69287595e1364c86a498c8087 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 10 Aug 2019 09:42:30 +0200 Subject: [PATCH 2798/7155] ARM: dts: Update the NSPIRE DTS files for DRM The DRM subsystem graphics drivers require more granular definition of the connection between display drivers and panels, and a proper panel compatible. This utilizes the bindings merged to the DRM subsystem to properly define the display on the NSPIRE devices. We also do away with the undocumented DT binding "lcd-type". We add both the clocks to the CLCD block so the driver have full control over its clocking. Link: https://lore.kernel.org/r/20190810074230.6492-1-linus.walleij@linaro.org Cc: Daniel Tang Cc: Fabian Vogt Tested-by: Fabian Vogt Acked-by: Sam Ravnborg Signed-off-by: Linus Walleij Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/nspire-classic.dtsi | 15 ++++++++++++++- arch/arm/boot/dts/nspire-cx.dts | 15 ++++++++++++++- arch/arm/boot/dts/nspire.dtsi | 10 ++++++++-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/nspire-classic.dtsi b/arch/arm/boot/dts/nspire-classic.dtsi index c53f42777851..41744cc2bc72 100644 --- a/arch/arm/boot/dts/nspire-classic.dtsi +++ b/arch/arm/boot/dts/nspire-classic.dtsi @@ -8,7 +8,11 @@ /include/ "nspire.dtsi" &lcd { - lcd-type = "classic"; + port { + clcd_pads: endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; &fast_timer { @@ -69,6 +73,15 @@ #interrupt-cells = <1>; }; }; + + panel { + compatible = "ti,nspire-classic-lcd-panel"; + port { + panel_in: endpoint { + remote-endpoint = <&clcd_pads>; + }; + }; + }; chosen { bootargs = "debug earlyprintk console=tty0 console=ttyS0,115200n8 root=/dev/ram0"; }; diff --git a/arch/arm/boot/dts/nspire-cx.dts b/arch/arm/boot/dts/nspire-cx.dts index da95c3736651..0c16b04e2744 100644 --- a/arch/arm/boot/dts/nspire-cx.dts +++ b/arch/arm/boot/dts/nspire-cx.dts @@ -9,7 +9,11 @@ /include/ "nspire.dtsi" &lcd { - lcd-type = "cx"; + port { + clcd_pads: endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; &fast_timer { @@ -106,6 +110,15 @@ }; }; }; + + panel { + compatible = "ti,nspire-cx-lcd-panel"; + port { + panel_in: endpoint { + remote-endpoint = <&clcd_pads>; + }; + }; + }; chosen { bootargs = "debug earlyprintk console=tty0 console=ttyAMA0,115200n8 root=/dev/ram0"; }; diff --git a/arch/arm/boot/dts/nspire.dtsi b/arch/arm/boot/dts/nspire.dtsi index c35fd6667716..d9a0fd7524dc 100644 --- a/arch/arm/boot/dts/nspire.dtsi +++ b/arch/arm/boot/dts/nspire.dtsi @@ -95,8 +95,14 @@ reg = <0xC0000000 0x1000>; interrupts = <21>; - clocks = <&apb_pclk>; - clock-names = "apb_pclk"; + /* + * We assume the same clock is fed to APB and CLCDCLK. + * There is some code to scale the clock down by a factor + * 48 for the display so likely the frequency to the + * display is 1MHz and the CLCDCLK is 48 MHz. + */ + clocks = <&apb_pclk>, <&apb_pclk>; + clock-names = "clcdclk", "apb_pclk"; }; adc: adc@C4000000 { -- GitLab From 367f4acc69909bfbbab2839a33cfe66ffa075b0b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 10 Aug 2019 09:50:23 +0200 Subject: [PATCH 2799/7155] ARM: mach-nspire: Kill off CLCD auxdata After transitioning the CLCD to use DRM we can now kill off the final piece of auxdata on the NSPIRE. Link: https://lore.kernel.org/r/20190810075023.7327-1-linus.walleij@linaro.org Cc: Daniel Tang Cc: Fabian Vogt Tested-by: Fabian Vogt Acked-by: Sam Ravnborg Signed-off-by: Linus Walleij Signed-off-by: Arnd Bergmann --- arch/arm/mach-nspire/Makefile | 1 - arch/arm/mach-nspire/clcd.c | 114 ---------------------------------- arch/arm/mach-nspire/clcd.h | 10 --- arch/arm/mach-nspire/nspire.c | 25 -------- 4 files changed, 150 deletions(-) delete mode 100644 arch/arm/mach-nspire/clcd.c delete mode 100644 arch/arm/mach-nspire/clcd.h diff --git a/arch/arm/mach-nspire/Makefile b/arch/arm/mach-nspire/Makefile index 1d568c600452..4716b9b9aa7b 100644 --- a/arch/arm/mach-nspire/Makefile +++ b/arch/arm/mach-nspire/Makefile @@ -1,3 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += nspire.o -obj-y += clcd.o diff --git a/arch/arm/mach-nspire/clcd.c b/arch/arm/mach-nspire/clcd.c deleted file mode 100644 index 44738dcb391d..000000000000 --- a/arch/arm/mach-nspire/clcd.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/arch/arm/mach-nspire/clcd.c - * - * Copyright (C) 2013 Daniel Tang - */ - -#include -#include -#include -#include -#include - -static struct clcd_panel nspire_cx_lcd_panel = { - .mode = { - .name = "Color LCD", - .refresh = 60, - .xres = 320, - .yres = 240, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED, - .pixclock = 1, - .hsync_len = 6, - .vsync_len = 1, - .right_margin = 50, - .left_margin = 38, - .lower_margin = 3, - .upper_margin = 17, - }, - .width = 65, /* ~6.50 cm */ - .height = 49, /* ~4.87 cm */ - .tim2 = TIM2_IPC, - .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), - .bpp = 16, - .caps = CLCD_CAP_565, -}; - -static struct clcd_panel nspire_classic_lcd_panel = { - .mode = { - .name = "Grayscale LCD", - .refresh = 60, - .xres = 320, - .yres = 240, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - .vmode = FB_VMODE_NONINTERLACED, - .pixclock = 1, - .hsync_len = 6, - .vsync_len = 1, - .right_margin = 6, - .left_margin = 6, - }, - .width = 71, /* 7.11cm */ - .height = 53, /* 5.33cm */ - .tim2 = 0x80007d0, - .cntl = CNTL_LCDMONO8, - .bpp = 8, - .grayscale = 1, - .caps = CLCD_CAP_5551, -}; - -int nspire_clcd_setup(struct clcd_fb *fb) -{ - struct clcd_panel *panel; - size_t panel_size; - const char *type; - dma_addr_t dma; - int err; - - BUG_ON(!fb->dev->dev.of_node); - - err = of_property_read_string(fb->dev->dev.of_node, "lcd-type", &type); - if (err) { - pr_err("CLCD: Could not find lcd-type property\n"); - return err; - } - - if (!strcmp(type, "cx")) { - panel = &nspire_cx_lcd_panel; - } else if (!strcmp(type, "classic")) { - panel = &nspire_classic_lcd_panel; - } else { - pr_err("CLCD: Unknown lcd-type %s\n", type); - return -EINVAL; - } - - panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8; - panel_size = ALIGN(panel_size, PAGE_SIZE); - - fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, panel_size, &dma, - GFP_KERNEL); - - if (!fb->fb.screen_base) { - pr_err("CLCD: unable to map framebuffer\n"); - return -ENOMEM; - } - - fb->fb.fix.smem_start = dma; - fb->fb.fix.smem_len = panel_size; - fb->panel = panel; - - return 0; -} - -int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) -{ - return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base, - fb->fb.fix.smem_start, fb->fb.fix.smem_len); -} - -void nspire_clcd_remove(struct clcd_fb *fb) -{ - dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base, - fb->fb.fix.smem_start); -} diff --git a/arch/arm/mach-nspire/clcd.h b/arch/arm/mach-nspire/clcd.h deleted file mode 100644 index 7f36bd8511c5..000000000000 --- a/arch/arm/mach-nspire/clcd.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/arch/arm/mach-nspire/clcd.h - * - * Copyright (C) 2013 Daniel Tang - */ - -int nspire_clcd_setup(struct clcd_fb *fb); -int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma); -void nspire_clcd_remove(struct clcd_fb *fb); diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c index 957bd0c0fbd5..2d4abb0288b9 100644 --- a/arch/arm/mach-nspire/nspire.c +++ b/arch/arm/mach-nspire/nspire.c @@ -12,14 +12,12 @@ #include #include #include -#include #include #include #include #include "mmio.h" -#include "clcd.h" static const char *const nspire_dt_match[] __initconst = { "ti,nspire", @@ -29,28 +27,6 @@ static const char *const nspire_dt_match[] __initconst = { NULL, }; -static struct clcd_board nspire_clcd_data = { - .name = "LCD", - .caps = CLCD_CAP_5551 | CLCD_CAP_565, - .check = clcdfb_check, - .decode = clcdfb_decode, - .setup = nspire_clcd_setup, - .mmap = nspire_clcd_mmap, - .remove = nspire_clcd_remove, -}; - - -static struct of_dev_auxdata nspire_auxdata[] __initdata = { - OF_DEV_AUXDATA("arm,pl111", NSPIRE_LCD_PHYS_BASE, - NULL, &nspire_clcd_data), - { } -}; - -static void __init nspire_init(void) -{ - of_platform_default_populate(NULL, nspire_auxdata, NULL); -} - static void nspire_restart(enum reboot_mode mode, const char *cmd) { void __iomem *base = ioremap(NSPIRE_MISC_PHYS_BASE, SZ_4K); @@ -62,6 +38,5 @@ static void nspire_restart(enum reboot_mode mode, const char *cmd) DT_MACHINE_START(NSPIRE, "TI-NSPIRE") .dt_compat = nspire_dt_match, - .init_machine = nspire_init, .restart = nspire_restart, MACHINE_END -- GitLab From 341dfcf8d78eaa3a2dc96dea06f0392eb2978364 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 12 Aug 2019 11:39:47 -0700 Subject: [PATCH 2800/7155] btf: expose BTF info through sysfs Make .BTF section allocated and expose its contents through sysfs. /sys/kernel/btf directory is created to contain all the BTFs present inside kernel. Currently there is only kernel's main BTF, represented as /sys/kernel/btf/kernel file. Once kernel modules' BTFs are supported, each module will expose its BTF as /sys/kernel/btf/ file. Current approach relies on a few pieces coming together: 1. pahole is used to take almost final vmlinux image (modulo .BTF and kallsyms) and generate .BTF section by converting DWARF info into BTF. This section is not allocated and not mapped to any segment, though, so is not yet accessible from inside kernel at runtime. 2. objcopy dumps .BTF contents into binary file and subsequently convert binary file into linkable object file with automatically generated symbols _binary__btf_kernel_bin_start and _binary__btf_kernel_bin_end, pointing to start and end, respectively, of BTF raw data. 3. final vmlinux image is generated by linking this object file (and kallsyms, if necessary). sysfs_btf.c then creates /sys/kernel/btf/kernel file and exposes embedded BTF contents through it. This allows, e.g., libbpf and bpftool access BTF info at well-known location, without resorting to searching for vmlinux image on disk (location of which is not standardized and vmlinux image might not be even available in some scenarios, e.g., inside qemu during testing). Alternative approach using .incbin assembler directive to embed BTF contents directly was attempted but didn't work, because sysfs_proc.o is not re-compiled during link-vmlinux.sh stage. This is required, though, to update embedded BTF data (initially empty data is embedded, then pahole generates BTF info and we need to regenerate sysfs_btf.o with updated contents, but it's too late at that point). If BTF couldn't be generated due to missing or too old pahole, sysfs_btf.c handles that gracefully by detecting that _binary__btf_kernel_bin_start (weak symbol) is 0 and not creating /sys/kernel/btf at all. v2->v3: - added Documentation/ABI/testing/sysfs-kernel-btf (Greg K-H); - created proper kobject (btf_kobj) for btf directory (Greg K-H); - undo v2 change of reusing vmlinux, as it causes extra kallsyms pass due to initially missing __binary__btf_kernel_bin_{start/end} symbols; v1->v2: - allow kallsyms stage to re-use vmlinux generated by gen_btf(); Reviewed-by: Greg Kroah-Hartman Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann --- Documentation/ABI/testing/sysfs-kernel-btf | 17 +++++++ kernel/bpf/Makefile | 3 ++ kernel/bpf/sysfs_btf.c | 51 +++++++++++++++++++++ scripts/link-vmlinux.sh | 52 ++++++++++++++-------- 4 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-kernel-btf create mode 100644 kernel/bpf/sysfs_btf.c diff --git a/Documentation/ABI/testing/sysfs-kernel-btf b/Documentation/ABI/testing/sysfs-kernel-btf new file mode 100644 index 000000000000..5390f8001f96 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-btf @@ -0,0 +1,17 @@ +What: /sys/kernel/btf +Date: Aug 2019 +KernelVersion: 5.5 +Contact: bpf@vger.kernel.org +Description: + Contains BTF type information and related data for kernel and + kernel modules. + +What: /sys/kernel/btf/kernel +Date: Aug 2019 +KernelVersion: 5.5 +Contact: bpf@vger.kernel.org +Description: + Read-only binary attribute exposing kernel's own BTF type + information with description of all internal kernel types. See + Documentation/bpf/btf.rst for detailed description of format + itself. diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index 29d781061cd5..e1d9adb212f9 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -22,3 +22,6 @@ obj-$(CONFIG_CGROUP_BPF) += cgroup.o ifeq ($(CONFIG_INET),y) obj-$(CONFIG_BPF_SYSCALL) += reuseport_array.o endif +ifeq ($(CONFIG_SYSFS),y) +obj-$(CONFIG_DEBUG_INFO_BTF) += sysfs_btf.o +endif diff --git a/kernel/bpf/sysfs_btf.c b/kernel/bpf/sysfs_btf.c new file mode 100644 index 000000000000..092e63b9758b --- /dev/null +++ b/kernel/bpf/sysfs_btf.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Provide kernel BTF information for introspection and use by eBPF tools. + */ +#include +#include +#include +#include +#include + +/* See scripts/link-vmlinux.sh, gen_btf() func for details */ +extern char __weak _binary__btf_kernel_bin_start[]; +extern char __weak _binary__btf_kernel_bin_end[]; + +static ssize_t +btf_kernel_read(struct file *file, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t len) +{ + memcpy(buf, _binary__btf_kernel_bin_start + off, len); + return len; +} + +static struct bin_attribute bin_attr_btf_kernel __ro_after_init = { + .attr = { .name = "kernel", .mode = 0444, }, + .read = btf_kernel_read, +}; + +static struct kobject *btf_kobj; + +static int __init btf_kernel_init(void) +{ + int err; + + if (!_binary__btf_kernel_bin_start) + return 0; + + btf_kobj = kobject_create_and_add("btf", kernel_kobj); + if (IS_ERR(btf_kobj)) { + err = PTR_ERR(btf_kobj); + btf_kobj = NULL; + return err; + } + + bin_attr_btf_kernel.size = _binary__btf_kernel_bin_end - + _binary__btf_kernel_bin_start; + + return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_kernel); +} + +subsys_initcall(btf_kernel_init); diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index a7124f895b24..cb93832c6ad7 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -56,8 +56,8 @@ modpost_link() } # Link of vmlinux -# ${1} - optional extra .o files -# ${2} - output file +# ${1} - output file +# ${@:2} - optional extra .o files vmlinux_link() { local lds="${objtree}/${KBUILD_LDS}" @@ -70,9 +70,9 @@ vmlinux_link() --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group \ - ${1}" + ${@:2}" - ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ + ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${1} \ -T ${lds} ${objects} else objects="-Wl,--whole-archive \ @@ -81,9 +81,9 @@ vmlinux_link() -Wl,--start-group \ ${KBUILD_VMLINUX_LIBS} \ -Wl,--end-group \ - ${1}" + ${@:2}" - ${CC} ${CFLAGS_vmlinux} -o ${2} \ + ${CC} ${CFLAGS_vmlinux} -o ${1} \ -Wl,-T,${lds} \ ${objects} \ -lutil -lrt -lpthread @@ -92,23 +92,34 @@ vmlinux_link() } # generate .BTF typeinfo from DWARF debuginfo +# ${1} - vmlinux image +# ${2} - file to dump raw BTF data into gen_btf() { - local pahole_ver; + local pahole_ver + local bin_arch if ! [ -x "$(command -v ${PAHOLE})" ]; then info "BTF" "${1}: pahole (${PAHOLE}) is not available" - return 0 + return 1 fi pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" - return 0 + return 1 fi - info "BTF" ${1} + info "BTF" ${2} + vmlinux_link ${1} LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} + + # dump .BTF section into raw binary file to link with final vmlinux + bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \ + cut -d, -f1 | cut -d' ' -f2) + ${OBJCOPY} --dump-section .BTF=.btf.kernel.bin ${1} 2>/dev/null + ${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \ + --rename-section .data=.BTF .btf.kernel.bin ${2} } # Create ${2} .o file with all symbols from the ${1} object file @@ -153,6 +164,7 @@ sortextable() # Delete output files in case of error cleanup() { + rm -f .btf.* rm -f .tmp_System.map rm -f .tmp_kallsyms* rm -f .tmp_vmlinux* @@ -215,6 +227,13 @@ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o info MODINFO modules.builtin.modinfo ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo +btf_kernel_bin_o="" +if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then + if gen_btf .tmp_vmlinux.btf .btf.kernel.bin.o ; then + btf_kernel_bin_o=.btf.kernel.bin.o + fi +fi + kallsymso="" kallsyms_vmlinux="" if [ -n "${CONFIG_KALLSYMS}" ]; then @@ -246,11 +265,11 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then kallsyms_vmlinux=.tmp_vmlinux2 # step 1 - vmlinux_link "" .tmp_vmlinux1 + vmlinux_link .tmp_vmlinux1 ${btf_kernel_bin_o} kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o # step 2 - vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 + vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_kernel_bin_o} kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o # step 3 @@ -261,18 +280,13 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then kallsymso=.tmp_kallsyms3.o kallsyms_vmlinux=.tmp_vmlinux3 - vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 - + vmlinux_link .tmp_vmlinux3 .tmp_kallsyms2.o ${btf_kernel_bin_o} kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o fi fi info LD vmlinux -vmlinux_link "${kallsymso}" vmlinux - -if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then - gen_btf vmlinux -fi +vmlinux_link vmlinux "${kallsymso}" "${btf_kernel_bin_o}" if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then info SORTEX vmlinux -- GitLab From d66fa3c70e598746a907e5db5ed024035e01817a Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Tue, 13 Aug 2019 01:38:33 +0100 Subject: [PATCH 2801/7155] tools: bpftool: add feature check for zlib bpftool requires libelf, and zlib for decompressing /proc/config.gz. zlib is a transitive dependency via libelf, and became mandatory since elfutils 0.165 (Jan 2016). The feature check of libelf is already done in the elfdep target of tools/lib/bpf/Makefile, pulled in by bpftool via a dependency on libbpf.a. Add a similar feature check for zlib. Suggested-by: Jakub Kicinski Signed-off-by: Peter Wu Acked-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile index 078bd0dcfba5..4c9d1ffc3fc7 100644 --- a/tools/bpf/bpftool/Makefile +++ b/tools/bpf/bpftool/Makefile @@ -58,8 +58,8 @@ INSTALL ?= install RM ?= rm -f FEATURE_USER = .bpftool -FEATURE_TESTS = libbfd disassembler-four-args reallocarray -FEATURE_DISPLAY = libbfd disassembler-four-args +FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib +FEATURE_DISPLAY = libbfd disassembler-four-args zlib check_feat := 1 NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall @@ -111,6 +111,8 @@ OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $< +$(OUTPUT)feature.o: | zdep + $(OUTPUT)bpftool: $(OBJS) $(LIBBPF) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) @@ -149,6 +151,9 @@ doc-uninstall: FORCE: -.PHONY: all FORCE clean install uninstall +zdep: + @if [ "$(feature-zlib)" != "1" ]; then echo "No zlib found"; exit 1 ; fi + +.PHONY: all FORCE clean install uninstall zdep .PHONY: doc doc-clean doc-install doc-uninstall .DEFAULT_GOAL := all -- GitLab From 9840a4ffcf0b26e08472ed53d176a6a0f1d4c498 Mon Sep 17 00:00:00 2001 From: Petar Penkov Date: Mon, 12 Aug 2019 16:30:39 -0700 Subject: [PATCH 2802/7155] selftests/bpf: fix race in flow dissector tests Since the "last_dissection" map holds only the flow keys for the most recent packet, there is a small race in the skb-less flow dissector tests if a new packet comes between transmitting the test packet, and reading its keys from the map. If this happens, the test packet keys will be overwritten and the test will fail. Changing the "last_dissection" map to a hash map, keyed on the source/dest port pair resolves this issue. Additionally, let's clear the last test results from the map between tests to prevent previous test cases from interfering with the following test cases. Fixes: 0905beec9f52 ("selftests/bpf: run flow dissector tests in skb-less mode") Signed-off-by: Petar Penkov Signed-off-by: Daniel Borkmann --- .../selftests/bpf/prog_tests/flow_dissector.c | 22 ++++++++++++++++++- tools/testing/selftests/bpf/progs/bpf_flow.c | 13 +++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c index 700d73d2f22a..6892b88ae065 100644 --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c @@ -109,6 +109,8 @@ struct test tests[] = { .iph.protocol = IPPROTO_TCP, .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, }, .keys = { .nhoff = ETH_HLEN, @@ -116,6 +118,8 @@ struct test tests[] = { .addr_proto = ETH_P_IP, .ip_proto = IPPROTO_TCP, .n_proto = __bpf_constant_htons(ETH_P_IP), + .sport = 80, + .dport = 8080, }, }, { @@ -125,6 +129,8 @@ struct test tests[] = { .iph.nexthdr = IPPROTO_TCP, .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, }, .keys = { .nhoff = ETH_HLEN, @@ -132,6 +138,8 @@ struct test tests[] = { .addr_proto = ETH_P_IPV6, .ip_proto = IPPROTO_TCP, .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .sport = 80, + .dport = 8080, }, }, { @@ -143,6 +151,8 @@ struct test tests[] = { .iph.protocol = IPPROTO_TCP, .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, }, .keys = { .nhoff = ETH_HLEN + VLAN_HLEN, @@ -150,6 +160,8 @@ struct test tests[] = { .addr_proto = ETH_P_IP, .ip_proto = IPPROTO_TCP, .n_proto = __bpf_constant_htons(ETH_P_IP), + .sport = 80, + .dport = 8080, }, }, { @@ -161,6 +173,8 @@ struct test tests[] = { .iph.nexthdr = IPPROTO_TCP, .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), .tcp.doff = 5, + .tcp.source = 80, + .tcp.dest = 8080, }, .keys = { .nhoff = ETH_HLEN + VLAN_HLEN * 2, @@ -169,6 +183,8 @@ struct test tests[] = { .addr_proto = ETH_P_IPV6, .ip_proto = IPPROTO_TCP, .n_proto = __bpf_constant_htons(ETH_P_IPV6), + .sport = 80, + .dport = 8080, }, }, { @@ -487,7 +503,8 @@ void test_flow_dissector(void) BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG; struct bpf_prog_test_run_attr tattr = {}; struct bpf_flow_keys flow_keys = {}; - __u32 key = 0; + __u32 key = (__u32)(tests[i].keys.sport) << 16 | + tests[i].keys.dport; /* For skb-less case we can't pass input flags; run * only the tests that have a matching set of flags. @@ -504,6 +521,9 @@ void test_flow_dissector(void) CHECK_ATTR(err, tests[i].name, "skb-less err %d\n", err); CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys); + + err = bpf_map_delete_elem(keys_fd, &key); + CHECK_ATTR(err, tests[i].name, "bpf_map_delete_elem %d\n", err); } bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR); diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c index 08bd8b9d58d0..040a44206f29 100644 --- a/tools/testing/selftests/bpf/progs/bpf_flow.c +++ b/tools/testing/selftests/bpf/progs/bpf_flow.c @@ -65,8 +65,8 @@ struct { } jmp_table SEC(".maps"); struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(max_entries, 1); + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); __type(key, __u32); __type(value, struct bpf_flow_keys); } last_dissection SEC(".maps"); @@ -74,12 +74,11 @@ struct { static __always_inline int export_flow_keys(struct bpf_flow_keys *keys, int ret) { - struct bpf_flow_keys *val; - __u32 key = 0; + __u32 key = (__u32)(keys->sport) << 16 | keys->dport; + struct bpf_flow_keys val; - val = bpf_map_lookup_elem(&last_dissection, &key); - if (val) - memcpy(val, keys, sizeof(*val)); + memcpy(&val, keys, sizeof(val)); + bpf_map_update_elem(&last_dissection, &key, &val, BPF_ANY); return ret; } -- GitLab From 839b9d2c59b3b3e74cb58b457615ff61154d8a41 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Jul 2019 03:38:16 -0300 Subject: [PATCH 2803/7155] media: omap_vout: fix various v4l2-compliance failures This patch fixes the following v4l2-compliance failures: - FIELD_ANY could be returned, which is not allowed. - JPEG colorspace was set instead of SRGB. - No control events. - Empty bus_info in QUERYCAP. - Overlay format handling wasn't zeroing bitmap/clips and didn't return the chromakey correctly. - G_FBUF didn't fill in many of the v4l2_framebuffer values. Now also return the base address of the corresponding framebuffer that this overlays. - Missing ENUM/G/S_OUTPUT ioctls. - ROTATE/VFLIP controls were added when the HW didn't support them. With these changes 'v4l2-compliance' passes all non-streaming tests. Tested on a Pandaboard and a Beagle XM board. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap/omap_vout.c | 170 ++++++++++++++++----- drivers/media/platform/omap/omap_voutlib.c | 6 +- 2 files changed, 134 insertions(+), 42 deletions(-) diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index b0f03c2ca65d..97b9089baa41 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -43,6 +43,7 @@ #include #include #include +#include #include

    .*), .*', m.group('msg')); + if(not m): + continue + dev = m.group('d') + if dev not in props: + props[dev] = DevProps() + tf.close() + + # now get the syspath for each target device + for dirname, dirnames, filenames in os.walk('/sys/devices'): + if(re.match('.*/power', dirname) and 'async' in filenames): + dev = dirname.split('/')[-2] + if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): + props[dev].syspath = dirname[:-6] + + # now fill in the properties for our target devices + for dev in sorted(props): + dirname = props[dev].syspath + if not dirname or not os.path.exists(dirname): + continue + with open(dirname+'/power/async') as fp: + text = fp.read() + props[dev].isasync = False + if 'enabled' in text: + props[dev].isasync = True + fields = os.listdir(dirname) + if 'product' in fields: + with open(dirname+'/product', 'rb') as fp: + props[dev].altname = ascii(fp.read()) + elif 'name' in fields: + with open(dirname+'/name', 'rb') as fp: + props[dev].altname = ascii(fp.read()) + elif 'model' in fields: + with open(dirname+'/model', 'rb') as fp: + props[dev].altname = ascii(fp.read()) + elif 'description' in fields: + with open(dirname+'/description', 'rb') as fp: + props[dev].altname = ascii(fp.read()) + elif 'id' in fields: + with open(dirname+'/id', 'rb') as fp: + props[dev].altname = ascii(fp.read()) + elif 'idVendor' in fields and 'idProduct' in fields: + idv, idp = '', '' + with open(dirname+'/idVendor', 'rb') as fp: + idv = ascii(fp.read()).strip() + with open(dirname+'/idProduct', 'rb') as fp: + idp = ascii(fp.read()).strip() + props[dev].altname = '%s:%s' % (idv, idp) + if props[dev].altname: + out = props[dev].altname.strip().replace('\n', ' ')\ + .replace(',', ' ').replace(';', ' ') + props[dev].altname = out + + # add a devinfo line to the bottom of ftrace + out = '' + for dev in sorted(props): + out += props[dev].out(dev) + footer += '# platform-devinfo: %s\n' % self.b64zip(out) + + # add a line for each of these commands with their outputs + cmds = [ + ['pcidevices', 'lspci', '-tv'], + ['interrupts', 'cat', '/proc/interrupts'], + ['gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/gpe*'], + ] + for cargs in cmds: + name = cargs[0] + cmdline = ' '.join(cargs[1:]) + cmdpath = self.getExec(cargs[1]) + if not cmdpath: + continue + cmd = [cmdpath] + cargs[2:] + try: + fp = Popen(cmd, stdout=PIPE, stderr=PIPE).stdout + info = ascii(fp.read()).strip() + fp.close() + except: + continue + if not info: + continue + footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info)) + + with self.openlog(self.ftracefile, 'a') as fp: + fp.write(footer) + return True def haveTurbostat(self): if not self.tstat: return False @@ -891,31 +1033,40 @@ class SystemValues: if not cmd: return False fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr - out = fp.read().strip() + out = ascii(fp.read()).strip() fp.close() - return re.match('turbostat version [0-9\.]* .*', out) + if re.match('turbostat version [0-9\.]* .*', out): + sysvals.vprint(out) + return True + return False def turbostat(self): cmd = self.getExec('turbostat') - if not cmd: - return 'missing turbostat executable' - text = [] + rawout = keyline = valline = '' fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile) fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr for line in fp: - if re.match('[0-9.]* sec', line): + line = ascii(line) + rawout += line + if keyline and valline: continue - text.append(line.split()) + if re.match('(?i)Avg_MHz.*', line): + keyline = line.strip().split() + elif keyline: + valline = line.strip().split() fp.close() - if len(text) < 2: - return 'turbostat output format error' + if not keyline or not valline or len(keyline) != len(valline): + errmsg = 'unrecognized turbostat output:\n'+rawout.strip() + sysvals.vprint(errmsg) + if not sysvals.verbose: + pprint(errmsg) + return '' + if sysvals.verbose: + pprint(rawout.strip()) out = [] - for key in text[0]: - values = [] - idx = text[0].index(key) - for line in text[1:]: - if len(line) > idx: - values.append(line[idx]) - out.append('%s=%s' % (key, ','.join(values))) + for key in keyline: + idx = keyline.index(key) + val = valline[idx] + out.append('%s=%s' % (key, val)) return '|'.join(out) def checkWifi(self): out = dict() @@ -924,7 +1075,7 @@ class SystemValues: return out fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout for line in fp: - m = re.match('(?P\S*) .* ESSID:(?P\S*)', line) + m = re.match('(?P\S*) .* ESSID:(?P\S*)', ascii(line)) if not m: continue out['device'] = m.group('dev') @@ -935,7 +1086,7 @@ class SystemValues: if 'device' in out: fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout for line in fp: - m = re.match('.* inet (?P[0-9\.]*)', line) + m = re.match('.* inet (?P[0-9\.]*)', ascii(line)) if m: out['ip'] = m.group('ip') break @@ -990,13 +1141,13 @@ class DevProps: def __init__(self): self.syspath = '' self.altname = '' - self.async = True + self.isasync = True self.xtraclass = '' self.xtrainfo = '' def out(self, dev): - return '%s,%s,%d;' % (dev, self.altname, self.async) + return '%s,%s,%d;' % (dev, self.altname, self.isasync) def debug(self, dev): - pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)) + pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.isasync)) def altName(self, dev): if not self.altname or self.altname == dev: return dev @@ -1004,13 +1155,13 @@ class DevProps: def xtraClass(self): if self.xtraclass: return ' '+self.xtraclass - if not self.async: + if not self.isasync: return ' sync' return '' def xtraInfo(self): if self.xtraclass: return ' '+self.xtraclass - if self.async: + if self.isasync: return ' async_device' return ' sync_device' @@ -1108,7 +1259,7 @@ class Data: return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order']) def initDevicegroups(self): # called when phases are all finished being added - for phase in self.dmesg.keys(): + for phase in sorted(self.dmesg.keys()): if '*' in phase: p = phase.split('*') pnew = '%s%d' % (p[0], len(p)) @@ -1430,16 +1581,7 @@ class Data: return phase def sortedDevices(self, phase): list = self.dmesg[phase]['list'] - slist = [] - tmp = dict() - for devname in list: - dev = list[devname] - if dev['length'] == 0: - continue - tmp[dev['start']] = devname - for t in sorted(tmp): - slist.append(tmp[t]) - return slist + return sorted(list, key=lambda k:list[k]['start']) def fixupInitcalls(self, phase): # if any calls never returned, clip them at system resume end phaselist = self.dmesg[phase]['list'] @@ -1576,7 +1718,7 @@ class Data: maxname = '%d' % self.maxDeviceNameSize(phase) fmt = '%3d) %'+maxname+'s - %f - %f' c = 1 - for name in devlist: + for name in sorted(devlist): s = devlist[name]['start'] e = devlist[name]['end'] sysvals.vprint(fmt % (c, name, s, e)) @@ -1588,7 +1730,7 @@ class Data: devlist = [] for phase in self.sortedPhases(): list = self.deviceChildren(devname, phase) - for dev in list: + for dev in sorted(list): if dev not in devlist: devlist.append(dev) return devlist @@ -1628,16 +1770,16 @@ class Data: def rootDeviceList(self): # list of devices graphed real = [] - for phase in self.dmesg: + for phase in self.sortedPhases(): list = self.dmesg[phase]['list'] - for dev in list: + for dev in sorted(list): if list[dev]['pid'] >= 0 and dev not in real: real.append(dev) # list of top-most root devices rootlist = [] - for phase in self.dmesg: + for phase in self.sortedPhases(): list = self.dmesg[phase]['list'] - for dev in list: + for dev in sorted(list): pdev = list[dev]['par'] pid = list[dev]['pid'] if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): @@ -1718,9 +1860,9 @@ class Data: def createProcessUsageEvents(self): # get an array of process names proclist = [] - for t in self.pstl: + for t in sorted(self.pstl): pslist = self.pstl[t] - for ps in pslist: + for ps in sorted(pslist): if ps not in proclist: proclist.append(ps) # get a list of data points for suspend and resume @@ -1765,7 +1907,7 @@ class Data: def debugPrint(self): for p in self.sortedPhases(): list = self.dmesg[p]['list'] - for devname in list: + for devname in sorted(list): dev = list[devname] if 'ftrace' in dev: dev['ftrace'].debugPrint(' [%s]' % devname) @@ -2466,7 +2608,7 @@ class Timeline: # if there is 1 line per row, draw them the standard way for t, p in standardphases: for i in sorted(self.rowheight[t][p]): - self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) + self.rowheight[t][p][i] = float(self.bodyH)/len(self.rowlines[t][p]) def createZoomBox(self, mode='command', testcount=1): # Create bounding box, add buttons html_zoombox = '

    \n' @@ -2537,6 +2679,7 @@ class TestProps: cmdlinefmt = '^# command \| (?P.*)' kparamsfmt = '^# kparams \| (?P.*)' devpropfmt = '# Device Properties: .*' + pinfofmt = '# platform-(?P[a-z,A-Z,0-9]*): (?P.*)' tracertypefmt = '# tracer: (?P.*)' firmwarefmt = '# fwsuspend (?P[0-9]*) fwresume (?P[0-9]*)$' procexecfmt = 'ps - (?P.*)$' @@ -2571,12 +2714,6 @@ class TestProps: self.ftrace_line_fmt = self.ftrace_line_fmt_nop else: doError('Invalid tracer format: [%s]' % tracer) - def decode(self, data): - try: - out = base64.b64decode(data).decode('zlib') - except: - out = data - return out def stampInfo(self, line): if re.match(self.stampfmt, line): self.stamp = line @@ -2660,7 +2797,7 @@ class TestProps: if len(self.mcelog) > data.testnumber: m = re.match(self.mcelogfmt, self.mcelog[data.testnumber]) if m: - data.mcelog = self.decode(m.group('m')) + data.mcelog = sv.b64unzip(m.group('m')) # turbostat data if len(self.turbostat) > data.testnumber: m = re.match(self.tstatfmt, self.turbostat[data.testnumber]) @@ -2681,6 +2818,46 @@ class TestProps: m = re.match(self.testerrfmt, self.testerror[data.testnumber]) if m: data.enterfail = m.group('e') + def devprops(self, data): + props = dict() + devlist = data.split(';') + for dev in devlist: + f = dev.split(',') + if len(f) < 3: + continue + dev = f[0] + props[dev] = DevProps() + props[dev].altname = f[1] + if int(f[2]): + props[dev].isasync = True + else: + props[dev].isasync = False + return props + def parseDevprops(self, line, sv): + idx = line.index(': ') + 2 + if idx >= len(line): + return + props = self.devprops(line[idx:]) + if sv.suspendmode == 'command' and 'testcommandstring' in props: + sv.testcommand = props['testcommandstring'].altname + sv.devprops = props + def parsePlatformInfo(self, line, sv): + m = re.match(self.pinfofmt, line) + if not m: + return + name, info = m.group('val'), m.group('info') + if name == 'devinfo': + sv.devprops = self.devprops(sv.b64unzip(info)) + return + elif name == 'testcmd': + sv.testcommand = info + return + field = info.split('|') + if len(field) < 2: + return + cmdline = field[0].strip() + output = sv.b64unzip(field[1].strip()) + sv.platinfo.append([name, cmdline, output]) # Class: TestRun # Description: @@ -2701,7 +2878,7 @@ class ProcessMonitor: process = Popen(c, shell=True, stdout=PIPE) running = dict() for line in process.stdout: - data = line.split() + data = ascii(line).split() pid = data[0] name = re.sub('[()]', '', data[1]) user = int(data[13]) @@ -2805,7 +2982,11 @@ def appendIncompleteTraceLog(testruns): continue # device properties line if(re.match(tp.devpropfmt, line)): - devProps(line) + tp.parseDevprops(line, sysvals) + continue + # platform info line + if(re.match(tp.pinfofmt, line)): + tp.parsePlatformInfo(line, sysvals) continue # parse only valid lines, if this is not one move on m = re.match(tp.ftrace_line_fmt, line) @@ -2902,7 +3083,7 @@ def parseTraceLog(live=False): sysvals.setupAllKprobes() ksuscalls = ['pm_prepare_console'] krescalls = ['pm_restore_console'] - tracewatch = [] + tracewatch = ['irq_wakeup'] if sysvals.usekprobes: tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', @@ -2928,7 +3109,11 @@ def parseTraceLog(live=False): continue # device properties line if(re.match(tp.devpropfmt, line)): - devProps(line) + tp.parseDevprops(line, sysvals) + continue + # platform info line + if(re.match(tp.pinfofmt, line)): + tp.parsePlatformInfo(line, sysvals) continue # ignore all other commented lines if line[0] == '#': @@ -3001,16 +3186,11 @@ def parseTraceLog(live=False): isbegin = False else: continue - m = re.match('(?P.*)\[(?P[0-9]*)\] .*', t.name) - if(m): - val = m.group('val') - if val == '0': - name = m.group('name') - else: - name = m.group('name')+'['+val+']' + if '[' in t.name: + m = re.match('(?P.*)\[.*', t.name) else: m = re.match('(?P.*) .*', t.name) - name = m.group('name') + name = m.group('name') # ignore these events if(name.split('[')[0] in tracewatch): continue @@ -3045,6 +3225,8 @@ def parseTraceLog(live=False): elif(re.match('machine_suspend\[.*', t.name)): if(isbegin): lp = data.lastPhase() + if lp == 'resume_machine': + data.dmesg[lp]['end'] = t.time phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) data.setPhase(phase, t.time, False) if data.tSuspended == 0: @@ -3213,11 +3395,11 @@ def parseTraceLog(live=False): # add the traceevent data to the device hierarchy if(sysvals.usetraceevents): # add actual trace funcs - for name in test.ttemp: + for name in sorted(test.ttemp): for event in test.ttemp[name]: data.newActionGlobal(name, event['begin'], event['end'], event['pid']) # add the kprobe based virtual tracefuncs as actual devices - for key in tp.ktemp: + for key in sorted(tp.ktemp): name, pid = key if name not in sysvals.tracefuncs: continue @@ -3231,7 +3413,7 @@ def parseTraceLog(live=False): data.newActionGlobal(e['name'], kb, ke, pid, color) # add config base kprobes and dev kprobes if sysvals.usedevsrc: - for key in tp.ktemp: + for key in sorted(tp.ktemp): name, pid = key if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: continue @@ -3244,7 +3426,7 @@ def parseTraceLog(live=False): if sysvals.usecallgraph: # add the callgraph data to the device hierarchy sortlist = dict() - for key in test.ftemp: + for key in sorted(test.ftemp): proc, pid = key for cg in test.ftemp[key]: if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): @@ -3582,7 +3764,7 @@ def parseKernelLog(data): # if trace events are not available, these are better than nothing if(not sysvals.usetraceevents): # look for known actions - for a in at: + for a in sorted(at): if(re.match(at[a]['smsg'], msg)): if(a not in actions): actions[a] = [] @@ -3641,7 +3823,7 @@ def parseKernelLog(data): data.tResumed = data.tSuspended # fill in any actions we've found - for name in actions: + for name in sorted(actions): for event in actions[name]: data.newActionGlobal(name, event['begin'], event['end']) @@ -3761,7 +3943,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title): if lastmode and lastmode != mode and num > 0: for i in range(2): s = sorted(tMed[i]) - list[lastmode]['med'][i] = s[int(len(s)/2)] + list[lastmode]['med'][i] = s[int(len(s)//2)] iMed[i] = tMed[i][list[lastmode]['med'][i]] list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] list[lastmode]['min'] = tMin @@ -3803,7 +3985,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title): if lastmode and num > 0: for i in range(2): s = sorted(tMed[i]) - list[lastmode]['med'][i] = s[int(len(s)/2)] + list[lastmode]['med'][i] = s[int(len(s)//2)] iMed[i] = tMed[i][list[lastmode]['med'][i]] list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] list[lastmode]['min'] = tMin @@ -3845,7 +4027,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title): '\n' headnone = '{0}{1}\n' - for mode in list: + for mode in sorted(list): # header line for each suspend mode num = 0 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ @@ -3944,7 +4126,8 @@ def createHTMLDeviceSummary(testruns, htmlfile, title): th.format('Average Time') + th.format('Count') +\ th.format('Worst Time') + th.format('Host (worst time)') +\ th.format('Link (worst time)') + '\n' - for name in sorted(devlist, key=lambda k:devlist[k]['worst'], reverse=True): + for name in sorted(devlist, key=lambda k:(devlist[k]['worst'], \ + devlist[k]['total'], devlist[k]['name']), reverse=True): data = devall[type][name] data['average'] = data['total'] / data['count'] if data['average'] < limit: @@ -4085,7 +4268,7 @@ def createHTML(testruns, testfail): if(tTotal == 0): doError('No timeline data') if(len(data.tLow) > 0): - low_time = '|'.join(data.tLow) + low_time = '+'.join(data.tLow) if sysvals.suspendmode == 'command': run_time = '%.0f'%((data.end-data.start)*1000) if sysvals.testcommand: @@ -4151,7 +4334,7 @@ def createHTML(testruns, testfail): for group in data.devicegroups: devlist = [] for phase in group: - for devname in data.tdevlist[phase]: + for devname in sorted(data.tdevlist[phase]): d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) devlist.append(d) if d.isa('kth'): @@ -4230,7 +4413,7 @@ def createHTML(testruns, testfail): for b in phases[dir]: # draw the devices for this phase phaselist = data.dmesg[b]['list'] - for d in data.tdevlist[b]: + for d in sorted(data.tdevlist[b]): name = d drv = '' dev = phaselist[d] @@ -4971,13 +5154,9 @@ def executeSuspend(): if mode == 'freeze' and sysvals.haveTurbostat(): # execution will pause here turbo = sysvals.turbostat() - if '|' in turbo: + if turbo: tdata['turbo'] = turbo - else: - tdata['error'] = turbo else: - if sysvals.haveTurbostat(): - sysvals.vprint('WARNING: ignoring turbostat in mode "%s"' % mode) pf = open(sysvals.powerfile, 'w') pf.write(mode) # execution will pause here @@ -5024,7 +5203,7 @@ def executeSuspend(): op.write(line) op.close() sysvals.fsetVal('', 'trace') - devProps() + sysvals.platforminfo() return testdata def readFile(file): @@ -5040,9 +5219,9 @@ def readFile(file): # The time string, e.g. "1901m16s" def ms2nice(val): val = int(val) - h = val / 3600000 - m = (val / 60000) % 60 - s = (val / 1000) % 60 + h = val // 3600000 + m = (val // 60000) % 60 + s = (val // 1000) % 60 if h > 0: return '%d:%02d:%02d' % (h, m, s) if m > 0: @@ -5115,127 +5294,6 @@ def deviceInfo(output=''): print(lines[i]) return res -# Function: devProps -# Description: -# Retrieve a list of properties for all devices in the trace log -def devProps(data=0): - props = dict() - - if data: - idx = data.index(': ') + 2 - if idx >= len(data): - return - devlist = data[idx:].split(';') - for dev in devlist: - f = dev.split(',') - if len(f) < 3: - continue - dev = f[0] - props[dev] = DevProps() - props[dev].altname = f[1] - if int(f[2]): - props[dev].async = True - else: - props[dev].async = False - sysvals.devprops = props - if sysvals.suspendmode == 'command' and 'testcommandstring' in props: - sysvals.testcommand = props['testcommandstring'].altname - return - - if(os.path.exists(sysvals.ftracefile) == False): - doError('%s does not exist' % sysvals.ftracefile) - - # first get the list of devices we need properties for - msghead = 'Additional data added by AnalyzeSuspend' - alreadystamped = False - tp = TestProps() - tf = sysvals.openlog(sysvals.ftracefile, 'r') - for line in tf: - if msghead in line: - alreadystamped = True - continue - # determine the trace data type (required for further parsing) - m = re.match(tp.tracertypefmt, line) - if(m): - tp.setTracerType(m.group('t')) - continue - # parse only valid lines, if this is not one move on - m = re.match(tp.ftrace_line_fmt, line) - if(not m or 'device_pm_callback_start' not in line): - continue - m = re.match('.*: (?P.*) (?P.*), parent: *(?P

    .*), .*', m.group('msg')); - if(not m): - continue - dev = m.group('d') - if dev not in props: - props[dev] = DevProps() - tf.close() - - if not alreadystamped and sysvals.suspendmode == 'command': - out = '#\n# '+msghead+'\n# Device Properties: ' - out += 'testcommandstring,%s,0;' % (sysvals.testcommand) - with sysvals.openlog(sysvals.ftracefile, 'a') as fp: - fp.write(out+'\n') - sysvals.devprops = props - return - - # now get the syspath for each of our target devices - for dirname, dirnames, filenames in os.walk('/sys/devices'): - if(re.match('.*/power', dirname) and 'async' in filenames): - dev = dirname.split('/')[-2] - if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): - props[dev].syspath = dirname[:-6] - - # now fill in the properties for our target devices - for dev in props: - dirname = props[dev].syspath - if not dirname or not os.path.exists(dirname): - continue - with open(dirname+'/power/async') as fp: - text = fp.read() - props[dev].async = False - if 'enabled' in text: - props[dev].async = True - fields = os.listdir(dirname) - if 'product' in fields: - with open(dirname+'/product') as fp: - props[dev].altname = fp.read() - elif 'name' in fields: - with open(dirname+'/name') as fp: - props[dev].altname = fp.read() - elif 'model' in fields: - with open(dirname+'/model') as fp: - props[dev].altname = fp.read() - elif 'description' in fields: - with open(dirname+'/description') as fp: - props[dev].altname = fp.read() - elif 'id' in fields: - with open(dirname+'/id') as fp: - props[dev].altname = fp.read() - elif 'idVendor' in fields and 'idProduct' in fields: - idv, idp = '', '' - with open(dirname+'/idVendor') as fp: - idv = fp.read().strip() - with open(dirname+'/idProduct') as fp: - idp = fp.read().strip() - props[dev].altname = '%s:%s' % (idv, idp) - - if props[dev].altname: - out = props[dev].altname.strip().replace('\n', ' ') - out = out.replace(',', ' ') - out = out.replace(';', ' ') - props[dev].altname = out - - # and now write the data to the ftrace file - if not alreadystamped: - out = '#\n# '+msghead+'\n# Device Properties: ' - for dev in sorted(props): - out += props[dev].out(dev) - with sysvals.openlog(sysvals.ftracefile, 'a') as fp: - fp.write(out+'\n') - - sysvals.devprops = props - # Function: getModes # Description: # Determine the supported power modes on this system @@ -5339,11 +5397,11 @@ def dmidecode(mempath, fatal=False): # search for either an SM table or DMI table i = base = length = num = 0 while(i < memsize): - if buf[i:i+4] == '_SM_' and i < memsize - 16: + if buf[i:i+4] == b'_SM_' and i < memsize - 16: length = struct.unpack('H', buf[i+22:i+24])[0] base, num = struct.unpack('IH', buf[i+24:i+30]) break - elif buf[i:i+5] == '_DMI_': + elif buf[i:i+5] == b'_DMI_': length = struct.unpack('H', buf[i+6:i+8])[0] base, num = struct.unpack('IH', buf[i+8:i+14]) break @@ -5376,15 +5434,15 @@ def dmidecode(mempath, fatal=False): if 0 == struct.unpack('H', buf[n:n+2])[0]: break n += 1 - data = buf[i+size:n+2].split('\0') + data = buf[i+size:n+2].split(b'\0') for name in info: itype, idxadr = info[name] if itype == type: - idx = struct.unpack('B', buf[i+idxadr])[0] + idx = struct.unpack('B', buf[i+idxadr:i+idxadr+1])[0] if idx > 0 and idx < len(data) - 1: - s = data[idx-1].strip() - if s and s.lower() != 'to be filled by o.e.m.': - out[name] = data[idx-1] + s = data[idx-1].decode('utf-8') + if s.strip() and s.strip().lower() != 'to be filled by o.e.m.': + out[name] = s i = n + 2 count += 1 return out @@ -5409,7 +5467,7 @@ def getBattery(): return (ac, charge) def displayControl(cmd): - xset, ret = 'xset -d :0.0 {0}', 0 + xset, ret = 'timeout 10 xset -d :0.0 {0}', 0 if sysvals.sudouser: xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) if cmd == 'init': @@ -5433,7 +5491,7 @@ def displayControl(cmd): fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout ret = 'unknown' for line in fp: - m = re.match('[\s]*Monitor is (?P.*)', line) + m = re.match('[\s]*Monitor is (?P.*)', ascii(line)) if(m and len(m.group('m')) >= 2): out = m.group('m').lower() ret = out[3:] if out[0:2] == 'in' else out @@ -5495,10 +5553,11 @@ def getFPDT(output): ' OEM Revision : %u\n'\ ' Creator ID : %s\n'\ ' Creator Revision : 0x%x\n'\ - '' % (table[0], table[0], table[1], table[2], table[3], - table[4], table[5], table[6], table[7], table[8])) + '' % (ascii(table[0]), ascii(table[0]), table[1], table[2], + table[3], ascii(table[4]), ascii(table[5]), table[6], + ascii(table[7]), table[8])) - if(table[0] != 'FPDT'): + if(table[0] != b'FPDT'): if(output): doError('Invalid FPDT table') return False @@ -5530,8 +5589,8 @@ def getFPDT(output): return [0, 0] rechead = struct.unpack('4sI', first) recdata = fp.read(rechead[1]-8) - if(rechead[0] == 'FBPT'): - record = struct.unpack('HBBIQQQQQ', recdata) + if(rechead[0] == b'FBPT'): + record = struct.unpack('HBBIQQQQQ', recdata[:48]) if(output): pprint('%s (%s)\n'\ ' Reset END : %u ns\n'\ @@ -5539,11 +5598,11 @@ def getFPDT(output): ' OS Loader StartImage Start : %u ns\n'\ ' ExitBootServices Entry : %u ns\n'\ ' ExitBootServices Exit : %u ns'\ - '' % (rectype[header[0]], rechead[0], record[4], record[5], + '' % (rectype[header[0]], ascii(rechead[0]), record[4], record[5], record[6], record[7], record[8])) - elif(rechead[0] == 'S3PT'): + elif(rechead[0] == b'S3PT'): if(output): - pprint('%s (%s)' % (rectype[header[0]], rechead[0])) + pprint('%s (%s)' % (rectype[header[0]], ascii(rechead[0]))) j = 0 while(j < len(recdata)): prechead = struct.unpack('HBB', recdata[j:j+4]) @@ -5689,7 +5748,7 @@ def doError(msg, help=False): def getArgInt(name, args, min, max, main=True): if main: try: - arg = args.next() + arg = next(args) except: doError(name+': no argument supplied', True) else: @@ -5708,7 +5767,7 @@ def getArgInt(name, args, min, max, main=True): def getArgFloat(name, args, min, max, main=True): if main: try: - arg = args.next() + arg = next(args) except: doError(name+': no argument supplied', True) else: @@ -5737,9 +5796,12 @@ def processData(live=False): parseKernelLog(data) if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): appendIncompleteTraceLog(testruns) + shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr', + 'memsz', 'mode', 'numcpu', 'plat', 'time'] sysvals.vprint('System Info:') for key in sorted(sysvals.stamp): - sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) + if key in shown: + sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key])) if sysvals.kparams: sysvals.vprint('Kparams:\n %s' % sysvals.kparams) sysvals.vprint('Command:\n %s' % sysvals.cmdline) @@ -5768,6 +5830,12 @@ def processData(live=False): (w[0], w[1]) sysvals.vprint(s) data.printDetails() + if len(sysvals.platinfo) > 0: + sysvals.vprint('\nPlatform Info:') + for info in sysvals.platinfo: + sysvals.vprint(info[0]+' - '+info[1]) + sysvals.vprint(info[2]) + sysvals.vprint('') if sysvals.cgdump: for data in testruns: data.debugPrint() @@ -5951,7 +6019,7 @@ def data_from_html(file, outpath, issues, fulldetail=False): worst[d] = {'name':'', 'time': 0.0} dev = devices[d] if d in devices else 0 if dev and len(dev.keys()) > 0: - n = sorted(dev, key=dev.get, reverse=True)[0] + n = sorted(dev, key=lambda k:(dev[k], k), reverse=True)[0] worst[d]['name'], worst[d]['time'] = n, dev[n] data = { 'mode': stmp[2], @@ -5976,7 +6044,7 @@ def data_from_html(file, outpath, issues, fulldetail=False): data['funclist'] = find_in_html(html, '

    Date: Fri, 9 Aug 2019 07:52:49 +0530 Subject: [PATCH 3765/7155] cpufreq: intel_pstate: Implement QoS supported freq constraints Intel pstate driver exposes min_perf_pct and max_perf_pct sysfs files, which can be used to force a limit on the min/max P state of the driver. Though these files eventually control the min/max frequencies that the CPUs will run at, they don't make a change to policy->min/max values. When the values of these files are changed (in passive mode of the driver), it leads to calling ->limits() callback of the cpufreq governors, like schedutil. On a call to it the governors shall forcefully update the frequency to come within the limits. Since the limits, i.e. policy->min/max, aren't updated by the driver, the governors fails to get the target freq within limit and sometimes aborts the update believing that the frequency is already set to the target value. This patch implements the QoS supported frequency constraints to update policy->min/max values whenever min_perf_pct or max_perf_pct files are updated. This is only done for the passive mode as of now, as the driver is already working fine in active mode. Fixes: ecd288429126 ("cpufreq: schedutil: Don't set next_freq to UINT_MAX") Reported-by: Doug Smythies Tested-by: Doug Smythies Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 120 +++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cc27d4c59dca..32f27563613b 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -1085,6 +1086,47 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b, return count; } +static struct cpufreq_driver intel_pstate; + +static void update_qos_request(enum dev_pm_qos_req_type type) +{ + int max_state, turbo_max, freq, i, perf_pct; + struct dev_pm_qos_request *req; + struct cpufreq_policy *policy; + + for_each_possible_cpu(i) { + struct cpudata *cpu = all_cpu_data[i]; + + policy = cpufreq_cpu_get(i); + if (!policy) + continue; + + req = policy->driver_data; + cpufreq_cpu_put(policy); + + if (!req) + continue; + + if (hwp_active) + intel_pstate_get_hwp_max(i, &turbo_max, &max_state); + else + turbo_max = cpu->pstate.turbo_pstate; + + if (type == DEV_PM_QOS_MIN_FREQUENCY) { + perf_pct = global.min_perf_pct; + } else { + req++; + perf_pct = global.max_perf_pct; + } + + freq = DIV_ROUND_UP(turbo_max * perf_pct, 100); + freq *= cpu->pstate.scaling; + + if (dev_pm_qos_update_request(req, freq) < 0) + pr_warn("Failed to update freq constraint: CPU%d\n", i); + } +} + static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, const char *buf, size_t count) { @@ -1108,7 +1150,10 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, mutex_unlock(&intel_pstate_limits_lock); - intel_pstate_update_policies(); + if (intel_pstate_driver == &intel_pstate) + intel_pstate_update_policies(); + else + update_qos_request(DEV_PM_QOS_MAX_FREQUENCY); mutex_unlock(&intel_pstate_driver_lock); @@ -1139,7 +1184,10 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b, mutex_unlock(&intel_pstate_limits_lock); - intel_pstate_update_policies(); + if (intel_pstate_driver == &intel_pstate) + intel_pstate_update_policies(); + else + update_qos_request(DEV_PM_QOS_MIN_FREQUENCY); mutex_unlock(&intel_pstate_driver_lock); @@ -2332,8 +2380,16 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy, static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) { - int ret = __intel_pstate_cpu_init(policy); + int max_state, turbo_max, min_freq, max_freq, ret; + struct dev_pm_qos_request *req; + struct cpudata *cpu; + struct device *dev; + + dev = get_cpu_device(policy->cpu); + if (!dev) + return -ENODEV; + ret = __intel_pstate_cpu_init(policy); if (ret) return ret; @@ -2342,7 +2398,63 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) /* This reflects the intel_pstate_get_cpu_pstates() setting. */ policy->cur = policy->cpuinfo.min_freq; + req = kcalloc(2, sizeof(*req), GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto pstate_exit; + } + + cpu = all_cpu_data[policy->cpu]; + + if (hwp_active) + intel_pstate_get_hwp_max(policy->cpu, &turbo_max, &max_state); + else + turbo_max = cpu->pstate.turbo_pstate; + + min_freq = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100); + min_freq *= cpu->pstate.scaling; + max_freq = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100); + max_freq *= cpu->pstate.scaling; + + ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY, + min_freq); + if (ret < 0) { + dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret); + goto free_req; + } + + ret = dev_pm_qos_add_request(dev, req + 1, DEV_PM_QOS_MAX_FREQUENCY, + max_freq); + if (ret < 0) { + dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret); + goto remove_min_req; + } + + policy->driver_data = req; + return 0; + +remove_min_req: + dev_pm_qos_remove_request(req); +free_req: + kfree(req); +pstate_exit: + intel_pstate_exit_perf_limits(policy); + + return ret; +} + +static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + struct dev_pm_qos_request *req; + + req = policy->driver_data; + + dev_pm_qos_remove_request(req + 1); + dev_pm_qos_remove_request(req); + kfree(req); + + return intel_pstate_cpu_exit(policy); } static struct cpufreq_driver intel_cpufreq = { @@ -2351,7 +2463,7 @@ static struct cpufreq_driver intel_cpufreq = { .target = intel_cpufreq_target, .fast_switch = intel_cpufreq_fast_switch, .init = intel_cpufreq_cpu_init, - .exit = intel_pstate_cpu_exit, + .exit = intel_cpufreq_cpu_exit, .stop_cpu = intel_cpufreq_stop_cpu, .update_limits = intel_pstate_update_limits, .name = "intel_cpufreq", -- GitLab From c3082a674f46fe49383b157882c41dfabaa37113 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 11 Jul 2019 19:51:25 +0530 Subject: [PATCH 3766/7155] PM: QoS: Get rid of unused flags The network_latency and network_throughput flags for PM-QoS have not found much use in drivers or in userspace since they were introduced. Commit 4a733ef1bea7 ("mac80211: remove PM-QoS listener") removed the only user PM_QOS_NETWORK_LATENCY in the kernel a while ago and there don't seem to be any userspace tools using the character device files either. PM_QOS_MEMORY_BANDWIDTH was never even added to the trace events. Remove all the flags except cpu_dma_latency. Signed-off-by: Amit Kucheria Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- Documentation/power/pm_qos_interface.rst | 5 +-- include/linux/pm_qos.h | 6 --- include/trace/events/power.h | 8 +--- kernel/power/qos.c | 48 ------------------------ 4 files changed, 4 insertions(+), 63 deletions(-) diff --git a/Documentation/power/pm_qos_interface.rst b/Documentation/power/pm_qos_interface.rst index 69921f072ce1..3097694fba69 100644 --- a/Documentation/power/pm_qos_interface.rst +++ b/Documentation/power/pm_qos_interface.rst @@ -7,8 +7,7 @@ performance expectations by drivers, subsystems and user space applications on one of the parameters. Two different PM QoS frameworks are available: -1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput, -memory_bandwidth. +1. PM QoS classes for cpu_dma_latency 2. the per-device PM QoS framework provides the API to manage the per-device latency constraints and PM QoS flags. @@ -79,7 +78,7 @@ cleanup of a process, the interface requires the process to register its parameter requests in the following way: To register the default pm_qos target for the specific parameter, the process -must open one of /dev/[cpu_dma_latency, network_latency, network_throughput] +must open /dev/cpu_dma_latency As long as the device node is held open that process has a registered request on the parameter. diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 2aebbc5b9950..222c3e01397c 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -13,9 +13,6 @@ enum { PM_QOS_RESERVED = 0, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_NETWORK_LATENCY, - PM_QOS_NETWORK_THROUGHPUT, - PM_QOS_MEMORY_BANDWIDTH, /* insert new class ID */ PM_QOS_NUM_CLASSES, @@ -33,9 +30,6 @@ enum pm_qos_flags_status { #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) -#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) -#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 -#define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS diff --git a/include/trace/events/power.h b/include/trace/events/power.h index f7aece721aed..7457e238e1b7 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -379,9 +379,7 @@ DECLARE_EVENT_CLASS(pm_qos_request, TP_printk("pm_qos_class=%s value=%d", __print_symbolic(__entry->pm_qos_class, - { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, - { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, - { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }), __entry->value) ); @@ -426,9 +424,7 @@ TRACE_EVENT(pm_qos_update_request_timeout, TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld", __print_symbolic(__entry->pm_qos_class, - { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, - { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, - { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }), __entry->value, __entry->timeout_us) ); diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 33e3febaba53..9568a2fe7c11 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -78,57 +78,9 @@ static struct pm_qos_object cpu_dma_pm_qos = { .name = "cpu_dma_latency", }; -static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); -static struct pm_qos_constraints network_lat_constraints = { - .list = PLIST_HEAD_INIT(network_lat_constraints.list), - .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, - .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, - .no_constraint_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, - .type = PM_QOS_MIN, - .notifiers = &network_lat_notifier, -}; -static struct pm_qos_object network_lat_pm_qos = { - .constraints = &network_lat_constraints, - .name = "network_latency", -}; - - -static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier); -static struct pm_qos_constraints network_tput_constraints = { - .list = PLIST_HEAD_INIT(network_tput_constraints.list), - .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, - .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, - .no_constraint_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, - .type = PM_QOS_MAX, - .notifiers = &network_throughput_notifier, -}; -static struct pm_qos_object network_throughput_pm_qos = { - .constraints = &network_tput_constraints, - .name = "network_throughput", -}; - - -static BLOCKING_NOTIFIER_HEAD(memory_bandwidth_notifier); -static struct pm_qos_constraints memory_bw_constraints = { - .list = PLIST_HEAD_INIT(memory_bw_constraints.list), - .target_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, - .default_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, - .no_constraint_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE, - .type = PM_QOS_SUM, - .notifiers = &memory_bandwidth_notifier, -}; -static struct pm_qos_object memory_bandwidth_pm_qos = { - .constraints = &memory_bw_constraints, - .name = "memory_bandwidth", -}; - - static struct pm_qos_object *pm_qos_array[] = { &null_pm_qos, &cpu_dma_pm_qos, - &network_lat_pm_qos, - &network_throughput_pm_qos, - &memory_bandwidth_pm_qos, }; static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, -- GitLab From a64d9493f587f8ec101d92ec19c7d88d6d3b5567 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Sun, 18 Aug 2019 18:28:24 +0800 Subject: [PATCH 3767/7155] staging: erofs: refuse to mount images with malformed volume name As Richard reminder [1], A valid volume name should be ended in NIL terminator within the length of volume_name. Since this field currently isn't really used, let's fix it to avoid potential bugs in the future. [1] https://lore.kernel.org/r/1133002215.69049.1566119033047.JavaMail.zimbra@nod.at/ Reported-by: Richard Weinberger Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190818102824.22330-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index f65a1ff9f42f..2da471010a86 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -131,9 +131,14 @@ static int superblock_read(struct super_block *sb) sbi->build_time_nsec = le32_to_cpu(layout->build_time_nsec); memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); - memcpy(sbi->volume_name, layout->volume_name, - sizeof(layout->volume_name)); + ret = strscpy(sbi->volume_name, layout->volume_name, + sizeof(layout->volume_name)); + if (ret < 0) { /* -E2BIG */ + errln("bad volume name without NIL terminator"); + ret = -EFSCORRUPTED; + goto out; + } ret = 0; out: brelse(bh); -- GitLab From acb383f1dcb4f1e79b66d4be3a0b6f519a957b0d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Sun, 18 Aug 2019 20:54:57 +0800 Subject: [PATCH 3768/7155] staging: erofs: fix an error handling in erofs_readdir() Richard observed a forever loop of erofs_read_raw_page() [1] which can be generated by forcely setting ->u.i_blkaddr to 0xdeadbeef (as my understanding block layer can handle access beyond end of device correctly). After digging into that, it seems the problem is highly related with directories and then I found the root cause is an improper error handling in erofs_readdir(). Let's fix it now. [1] https://lore.kernel.org/r/1163995781.68824.1566084358245.JavaMail.zimbra@nod.at/ Reported-by: Richard Weinberger Fixes: 3aa8ec716e52 ("staging: erofs: add directory operations") Cc: # 4.19+ Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190818125457.25906-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/dir.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index 5f38382637e6..77ef856df9f3 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -82,8 +82,15 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) unsigned int nameoff, maxsize; dentry_page = read_mapping_page(mapping, i, NULL); - if (IS_ERR(dentry_page)) - continue; + if (dentry_page == ERR_PTR(-ENOMEM)) { + err = -ENOMEM; + break; + } else if (IS_ERR(dentry_page)) { + errln("fail to readdir of logical block %u of nid %llu", + i, EROFS_V(dir)->nid); + err = -EFSCORRUPTED; + break; + } de = (struct erofs_dirent *)kmap(dentry_page); -- GitLab From ee45197c807895e156b2be0abcaebdfc116487c8 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:21 +0800 Subject: [PATCH 3769/7155] staging: erofs: some compressed cluster should be submitted for corrupted images As reported by erofs_utils fuzzer, a logical page can belong to at most 2 compressed clusters, if one compressed cluster is corrupted, but the other has been ready in submitting chain. The chain needs to submit anyway in order to keep the page working properly (page unlocked with PG_error set, PG_uptodate not set). Let's fix it now. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 2d7aaf98f7de..87b0c96caf8f 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -1307,19 +1307,18 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, err = z_erofs_do_read_page(&f, page, &pagepool); (void)z_erofs_collector_end(&f.clt); - if (err) { + /* if some compressed cluster ready, need submit them anyway */ + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); + + if (err) errln("%s, failed to read, err [%d]", __func__, err); - goto out; - } - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); -out: if (f.map.mpage) put_page(f.map.mpage); /* clean up the remaining free pages */ put_pages_list(&pagepool); - return 0; + return err; } static bool should_decompress_synchronously(struct erofs_sb_info *sbi, -- GitLab From 3407a4198faf01c9d7596c45b8606834b8dfc2b7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:22 +0800 Subject: [PATCH 3770/7155] staging: erofs: cannot set EROFS_V_Z_INITED_BIT if fill_inode_lazy fails As reported by erofs-utils fuzzer, unsupported compressed clustersize will make fill_inode_lazy fail, for such case we cannot set EROFS_V_Z_INITED_BIT since we need return failure for each z_erofs_map_blocks_iter(). Fixes: 152a333a5895 ("staging: erofs: add compacted compression indexes support") Cc: # 5.3+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zmap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index b61b9b5950ac..7408e86823a4 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -85,12 +85,11 @@ static int fill_inode_lazy(struct inode *inode) vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + ((h->h_clusterbits >> 5) & 7); + set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); unmap_done: kunmap_atomic(kaddr); unlock_page(page); put_page(page); - - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); out_unlock: clear_and_wake_up_bit(EROFS_V_BL_Z_BIT, &vi->flags); return err; -- GitLab From 138e1a0990e80db486ab9f6c06bd5c01f9a97999 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:23 +0800 Subject: [PATCH 3771/7155] staging: erofs: add two missing erofs_workgroup_put for corrupted images As reported by erofs-utils fuzzer, these error handling path will be entered to handle corrupted images. Lack of erofs_workgroup_puts will cause unmounting unsuccessfully. Fix these return values to EFSCORRUPTED as well. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-4-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 87b0c96caf8f..23283c97fd3b 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -357,14 +357,16 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, cl = z_erofs_primarycollection(pcl); if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { DBG_BUGON(1); - return ERR_PTR(-EIO); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } length = READ_ONCE(pcl->length); if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { DBG_BUGON(1); - return ERR_PTR(-EIO); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } } else { unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; -- GitLab From c35227958d7ecceae42a7d958380eae906f7b8e6 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 12 Jul 2019 13:07:25 +0930 Subject: [PATCH 3772/7155] ARM: dts: aspeed: Describe SD controllers The AST2400 and AST2500 both share the same SD controller, at the same location in the physical address space and the same hardware interrupt, with the same clock configurations. Signed-off-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-g4.dtsi | 28 ++++++++++++++++++++++++++++ arch/arm/boot/dts/aspeed-g5.dtsi | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index dd4b0b15afcf..e465cda40fe7 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -192,6 +192,34 @@ reg = <0x1e720000 0x8000>; // 32K }; + sdmmc: sd-controller@1e740000 { + compatible = "aspeed,ast2400-sd-controller"; + reg = <0x1e740000 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1e740000 0x10000>; + clocks = <&syscon ASPEED_CLK_GATE_SDCLK>; + status = "disabled"; + + sdhci0: sdhci@100 { + compatible = "aspeed,ast2400-sdhci"; + reg = <0x100 0x100>; + interrupts = <26>; + sdhci,auto-cmd12; + clocks = <&syscon ASPEED_CLK_SDIO>; + status = "disabled"; + }; + + sdhci1: sdhci@200 { + compatible = "aspeed,ast2400-sdhci"; + reg = <0x200 0x100>; + interrupts = <26>; + sdhci,auto-cmd12; + clocks = <&syscon ASPEED_CLK_SDIO>; + status = "disabled"; + }; + }; + gpio: gpio@1e780000 { #gpio-cells = <2>; gpio-controller; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index ca36d18d41f4..f360b6c565a5 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -267,6 +267,34 @@ reg = <0x1e720000 0x9000>; // 36K }; + sdmmc: sd-controller@1e740000 { + compatible = "aspeed,ast2500-sd-controller"; + reg = <0x1e740000 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1e740000 0x10000>; + clocks = <&syscon ASPEED_CLK_GATE_SDCLK>; + status = "disabled"; + + sdhci0: sdhci@100 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x100 0x100>; + interrupts = <26>; + sdhci,auto-cmd12; + clocks = <&syscon ASPEED_CLK_SDIO>; + status = "disabled"; + }; + + sdhci1: sdhci@200 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x200 0x100>; + interrupts = <26>; + sdhci,auto-cmd12; + clocks = <&syscon ASPEED_CLK_SDIO>; + status = "disabled"; + }; + }; + gpio: gpio@1e780000 { #gpio-cells = <2>; gpio-controller; -- GitLab From a6bc332373e5176c2d085657bc643a28950b20b0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:37 +0300 Subject: [PATCH 3773/7155] dmaengine: acpi: Set up DMA mask based on CSRT CSRT has an information about address width, which is supported by the certain DMA controller. Use information from CSRT to set up DMA mask for shared controller. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-2-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/acpi-dma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c index 30243f5c0710..4d66ee059808 100644 --- a/drivers/dma/acpi-dma.c +++ b/drivers/dma/acpi-dma.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -82,6 +83,12 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, if (si->base_request_line == 0 && si->num_handshake_signals == 0) return 0; + /* Set up DMA mask based on value from CSRT */ + ret = dma_coerce_mask_and_coherent(&adev->dev, + DMA_BIT_MASK(si->dma_address_width)); + if (ret) + return 0; + adma->base_request_line = si->base_request_line; adma->end_request_line = si->base_request_line + si->num_handshake_signals - 1; -- GitLab From 4b8584bac0407367f8157244c8952ed80bdb12fb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:38 +0300 Subject: [PATCH 3774/7155] dmaengine: acpi: Add kernel doc parameter descriptions Kernel documentation script is not happy about absence of function parameter descriptions: drivers/dma/acpi-dma.c:163: warning: Function parameter or member 'data' not described in 'acpi_dma_controller_register' drivers/dma/acpi-dma.c:247: warning: Function parameter or member 'data' not described in 'devm_acpi_dma_controller_register' drivers/dma/acpi-dma.c:274: warning: Function parameter or member 'dev' not described in 'devm_acpi_dma_controller_free' Append the descriptions of above mentioned function parameters. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-3-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/acpi-dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c index 4d66ee059808..8a05db3343d3 100644 --- a/drivers/dma/acpi-dma.c +++ b/drivers/dma/acpi-dma.c @@ -147,7 +147,7 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma) * @dev: struct device of DMA controller * @acpi_dma_xlate: translation function which converts a dma specifier * into a dma_chan structure - * @data pointer to controller specific data to be used by + * @data: pointer to controller specific data to be used by * translation function * * Allocated memory should be freed with appropriate acpi_dma_controller_free() @@ -231,7 +231,7 @@ static void devm_acpi_dma_release(struct device *dev, void *res) * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register() * @dev: device that is registering this DMA controller * @acpi_dma_xlate: translation function - * @data pointer to controller specific data + * @data: pointer to controller specific data * * Managed acpi_dma_controller_register(). DMA controller registered by this * function are automatically freed on driver detach. See @@ -264,6 +264,7 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register); /** * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free() + * @dev: device that is unregistering as DMA controller * * Unregister a DMA controller registered with * devm_acpi_dma_controller_register(). Normally this function will not need to -- GitLab From ae923c91aa3b4f7e20b764744188c0d859243d81 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:39 +0300 Subject: [PATCH 3775/7155] dmaengine: dw: Export struct dw_dma_chip_pdata for wider use We are expecting some devices can be enumerated either as PCI or ACPI. Nevertheless, they will share same information, thus, provide a generic struct dw_dma_chip_pdata for all glue drivers. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-4-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/internal.h | 28 ++++++++++++++++++ drivers/dma/dw/pci.c | 60 +++++++++++---------------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h index 1dd7a4e6dd23..df5c84e2a4fd 100644 --- a/drivers/dma/dw/internal.h +++ b/drivers/dma/dw/internal.h @@ -23,4 +23,32 @@ int do_dw_dma_enable(struct dw_dma_chip *chip); extern bool dw_dma_filter(struct dma_chan *chan, void *param); +struct dw_dma_chip_pdata { + const struct dw_dma_platform_data *pdata; + int (*probe)(struct dw_dma_chip *chip); + int (*remove)(struct dw_dma_chip *chip); + struct dw_dma_chip *chip; +}; + +static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = { + .probe = dw_dma_probe, + .remove = dw_dma_remove, +}; + +static const struct dw_dma_platform_data idma32_pdata = { + .nr_channels = 8, + .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, + .chan_priority = CHAN_PRIORITY_ASCENDING, + .block_size = 131071, + .nr_masters = 1, + .data_width = {4}, + .multi_block = {1, 1, 1, 1, 1, 1, 1, 1}, +}; + +static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = { + .pdata = &idma32_pdata, + .probe = idma32_dma_probe, + .remove = idma32_dma_remove, +}; + #endif /* _DMA_DW_INTERNAL_H */ diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index ad6db1cc287e..cf6e8ec4c0ff 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c @@ -12,38 +12,10 @@ #include "internal.h" -struct dw_dma_pci_data { - const struct dw_dma_platform_data *pdata; - int (*probe)(struct dw_dma_chip *chip); - int (*remove)(struct dw_dma_chip *chip); - struct dw_dma_chip *chip; -}; - -static const struct dw_dma_pci_data dw_pci_data = { - .probe = dw_dma_probe, - .remove = dw_dma_remove, -}; - -static const struct dw_dma_platform_data idma32_pdata = { - .nr_channels = 8, - .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, - .chan_priority = CHAN_PRIORITY_ASCENDING, - .block_size = 131071, - .nr_masters = 1, - .data_width = {4}, - .multi_block = {1, 1, 1, 1, 1, 1, 1, 1}, -}; - -static const struct dw_dma_pci_data idma32_pci_data = { - .pdata = &idma32_pdata, - .probe = idma32_dma_probe, - .remove = idma32_dma_remove, -}; - static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) { - const struct dw_dma_pci_data *drv_data = (void *)pid->driver_data; - struct dw_dma_pci_data *data; + const struct dw_dma_chip_pdata *drv_data = (void *)pid->driver_data; + struct dw_dma_chip_pdata *data; struct dw_dma_chip *chip; int ret; @@ -95,7 +67,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) static void dw_pci_remove(struct pci_dev *pdev) { - struct dw_dma_pci_data *data = pci_get_drvdata(pdev); + struct dw_dma_chip_pdata *data = pci_get_drvdata(pdev); struct dw_dma_chip *chip = data->chip; int ret; @@ -108,7 +80,7 @@ static void dw_pci_remove(struct pci_dev *pdev) static int dw_pci_suspend_late(struct device *dev) { - struct dw_dma_pci_data *data = dev_get_drvdata(dev); + struct dw_dma_chip_pdata *data = dev_get_drvdata(dev); struct dw_dma_chip *chip = data->chip; return do_dw_dma_disable(chip); @@ -116,7 +88,7 @@ static int dw_pci_suspend_late(struct device *dev) static int dw_pci_resume_early(struct device *dev) { - struct dw_dma_pci_data *data = dev_get_drvdata(dev); + struct dw_dma_chip_pdata *data = dev_get_drvdata(dev); struct dw_dma_chip *chip = data->chip; return do_dw_dma_enable(chip); @@ -130,29 +102,29 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = { static const struct pci_device_id dw_pci_id_table[] = { /* Medfield (GPDMA) */ - { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_data }, + { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_dma_chip_pdata }, /* BayTrail */ - { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_data }, - { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_data }, + { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_dma_chip_pdata }, + { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_dma_chip_pdata }, /* Merrifield */ - { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&idma32_pci_data }, + { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&idma32_chip_pdata }, /* Braswell */ - { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_data }, - { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_data }, + { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_dma_chip_pdata }, + { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_dma_chip_pdata }, /* Elkhart Lake iDMA 32-bit (PSE DMA) */ - { PCI_VDEVICE(INTEL, 0x4bb4), (kernel_ulong_t)&idma32_pci_data }, - { PCI_VDEVICE(INTEL, 0x4bb5), (kernel_ulong_t)&idma32_pci_data }, - { PCI_VDEVICE(INTEL, 0x4bb6), (kernel_ulong_t)&idma32_pci_data }, + { PCI_VDEVICE(INTEL, 0x4bb4), (kernel_ulong_t)&idma32_chip_pdata }, + { PCI_VDEVICE(INTEL, 0x4bb5), (kernel_ulong_t)&idma32_chip_pdata }, + { PCI_VDEVICE(INTEL, 0x4bb6), (kernel_ulong_t)&idma32_chip_pdata }, /* Haswell */ - { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_data }, + { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_dma_chip_pdata }, /* Broadwell */ - { PCI_VDEVICE(INTEL, 0x9ce0), (kernel_ulong_t)&dw_pci_data }, + { PCI_VDEVICE(INTEL, 0x9ce0), (kernel_ulong_t)&dw_dma_chip_pdata }, { } }; -- GitLab From b3757413b91ecf4a227c5f075446afe8126d882f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:40 +0300 Subject: [PATCH 3776/7155] dmaengine: dw: platform: Use struct dw_dma_chip_pdata Now, when we have a generic structure for the chip and platform data, use it in the platform glue driver. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-5-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 382dfd9e9600..234abbd6359a 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -168,12 +168,22 @@ dw_dma_parse_dt(struct platform_device *pdev) static int dw_probe(struct platform_device *pdev) { + const struct dw_dma_chip_pdata *match; + struct dw_dma_chip_pdata *data; struct dw_dma_chip *chip; struct device *dev = &pdev->dev; struct resource *mem; const struct dw_dma_platform_data *pdata; int err; + match = device_get_match_data(dev); + if (!match) + return -ENODEV; + + data = devm_kmemdup(&pdev->dev, match, sizeof(*match), GFP_KERNEL); + if (!data) + return -ENOMEM; + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -199,6 +209,8 @@ static int dw_probe(struct platform_device *pdev) chip->id = pdev->id; chip->pdata = pdata; + data->chip = chip; + chip->clk = devm_clk_get(chip->dev, "hclk"); if (IS_ERR(chip->clk)) return PTR_ERR(chip->clk); @@ -208,11 +220,11 @@ static int dw_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - err = dw_dma_probe(chip); + err = data->probe(chip); if (err) goto err_dw_dma_probe; - platform_set_drvdata(pdev, chip); + platform_set_drvdata(pdev, data); if (pdev->dev.of_node) { err = of_dma_controller_register(pdev->dev.of_node, @@ -235,12 +247,17 @@ static int dw_probe(struct platform_device *pdev) static int dw_remove(struct platform_device *pdev) { - struct dw_dma_chip *chip = platform_get_drvdata(pdev); + struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev); + struct dw_dma_chip *chip = data->chip; + int ret; if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); - dw_dma_remove(chip); + ret = data->remove(chip); + if (ret) + dev_warn(chip->dev, "can't remove device properly: %d\n", ret); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(chip->clk); @@ -249,7 +266,8 @@ static int dw_remove(struct platform_device *pdev) static void dw_shutdown(struct platform_device *pdev) { - struct dw_dma_chip *chip = platform_get_drvdata(pdev); + struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev); + struct dw_dma_chip *chip = data->chip; /* * We have to call do_dw_dma_disable() to stop any ongoing transfer. On @@ -269,7 +287,7 @@ static void dw_shutdown(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id dw_dma_of_id_table[] = { - { .compatible = "snps,dma-spear1340" }, + { .compatible = "snps,dma-spear1340", .data = &dw_dma_chip_pdata }, {} }; MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); @@ -277,9 +295,9 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); #ifdef CONFIG_ACPI static const struct acpi_device_id dw_dma_acpi_id_table[] = { - { "INTL9C60", 0 }, - { "80862286", 0 }, - { "808622C0", 0 }, + { "INTL9C60", (kernel_ulong_t)&dw_dma_chip_pdata }, + { "80862286", (kernel_ulong_t)&dw_dma_chip_pdata }, + { "808622C0", (kernel_ulong_t)&dw_dma_chip_pdata }, { } }; MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); @@ -289,7 +307,8 @@ MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); static int dw_suspend_late(struct device *dev) { - struct dw_dma_chip *chip = dev_get_drvdata(dev); + struct dw_dma_chip_pdata *data = dev_get_drvdata(dev); + struct dw_dma_chip *chip = data->chip; do_dw_dma_disable(chip); clk_disable_unprepare(chip->clk); @@ -299,7 +318,8 @@ static int dw_suspend_late(struct device *dev) static int dw_resume_early(struct device *dev) { - struct dw_dma_chip *chip = dev_get_drvdata(dev); + struct dw_dma_chip_pdata *data = dev_get_drvdata(dev); + struct dw_dma_chip *chip = data->chip; int ret; ret = clk_prepare_enable(chip->clk); -- GitLab From f8d9ddbc28518a0f7d39d2ce51f778759b49f73e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:41 +0300 Subject: [PATCH 3777/7155] dmaengine: dw: platform: Enable iDMA 32-bit on Intel Elkhart Lake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel® PSE (Programmable Services Engine) provides few DMA controllers to the host on Intel Elkhart Lake. Enable them in the ACPI glue driver. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-6-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 234abbd6359a..63465fd0e286 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -173,7 +173,6 @@ static int dw_probe(struct platform_device *pdev) struct dw_dma_chip *chip; struct device *dev = &pdev->dev; struct resource *mem; - const struct dw_dma_platform_data *pdata; int err; match = device_get_match_data(dev); @@ -201,13 +200,14 @@ static int dw_probe(struct platform_device *pdev) if (err) return err; - pdata = dev_get_platdata(dev); - if (!pdata) - pdata = dw_dma_parse_dt(pdev); + if (!data->pdata) + data->pdata = dev_get_platdata(dev); + if (!data->pdata) + data->pdata = dw_dma_parse_dt(pdev); chip->dev = dev; chip->id = pdev->id; - chip->pdata = pdata; + chip->pdata = data->pdata; data->chip = chip; @@ -298,6 +298,12 @@ static const struct acpi_device_id dw_dma_acpi_id_table[] = { { "INTL9C60", (kernel_ulong_t)&dw_dma_chip_pdata }, { "80862286", (kernel_ulong_t)&dw_dma_chip_pdata }, { "808622C0", (kernel_ulong_t)&dw_dma_chip_pdata }, + + /* Elkhart Lake iDMA 32-bit (PSE DMA) */ + { "80864BB4", (kernel_ulong_t)&idma32_chip_pdata }, + { "80864BB5", (kernel_ulong_t)&idma32_chip_pdata }, + { "80864BB6", (kernel_ulong_t)&idma32_chip_pdata }, + { } }; MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); -- GitLab From a9c56721d6ae99b22e983d0722e6b1b53a11dd59 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:42 +0300 Subject: [PATCH 3778/7155] dmaengine: dw: platform: Use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-7-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 63465fd0e286..8576439d0035 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -172,7 +172,6 @@ static int dw_probe(struct platform_device *pdev) struct dw_dma_chip_pdata *data; struct dw_dma_chip *chip; struct device *dev = &pdev->dev; - struct resource *mem; int err; match = device_get_match_data(dev); @@ -191,8 +190,7 @@ static int dw_probe(struct platform_device *pdev) if (chip->irq < 0) return chip->irq; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->regs = devm_ioremap_resource(dev, mem); + chip->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->regs)) return PTR_ERR(chip->regs); -- GitLab From e7b8514e4d68bec21fc6385fa0a66797ddc34ac9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:43 +0300 Subject: [PATCH 3779/7155] dmaengine: dw: platform: Switch to acpi_dma_controller_register() There is a possibility to have registered ACPI DMA controller while it has been gone already. To avoid the potential crash, move to non-managed acpi_dma_controller_register(). Fixes: 42c91ee71d6d ("dw_dmac: add ACPI support") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-8-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 8576439d0035..44fec1eabccd 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -84,13 +84,20 @@ static void dw_dma_acpi_controller_register(struct dw_dma *dw) dma_cap_set(DMA_SLAVE, info->dma_cap); info->filter_fn = dw_dma_acpi_filter; - ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate, - info); + ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info); if (ret) dev_err(dev, "could not register acpi_dma_controller\n"); } + +static void dw_dma_acpi_controller_free(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + + acpi_dma_controller_free(dev); +} #else /* !CONFIG_ACPI */ static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} +static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {} #endif /* !CONFIG_ACPI */ #ifdef CONFIG_OF @@ -249,6 +256,9 @@ static int dw_remove(struct platform_device *pdev) struct dw_dma_chip *chip = data->chip; int ret; + if (ACPI_HANDLE(&pdev->dev)) + dw_dma_acpi_controller_free(chip->dw); + if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); -- GitLab From 84da042e702347c186b84d9cc2e766f83e1814d6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:44 +0300 Subject: [PATCH 3780/7155] dmaengine: dw: platform: Move handle check to dw_dma_acpi_controller_register() Move ACPI handle check to the dw_dma_acpi_controller_register(). While here, convert it to has_acpi_companion() which is recommended way. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-9-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/platform.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 44fec1eabccd..b8514d7895d1 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -76,6 +76,9 @@ static void dw_dma_acpi_controller_register(struct dw_dma *dw) struct acpi_dma_filter_info *info; int ret; + if (!has_acpi_companion(dev)) + return; + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); if (!info) return; @@ -93,6 +96,9 @@ static void dw_dma_acpi_controller_free(struct dw_dma *dw) { struct device *dev = dw->dma.dev; + if (!has_acpi_companion(dev)) + return; + acpi_dma_controller_free(dev); } #else /* !CONFIG_ACPI */ @@ -239,8 +245,7 @@ static int dw_probe(struct platform_device *pdev) "could not register of_dma_controller\n"); } - if (ACPI_HANDLE(&pdev->dev)) - dw_dma_acpi_controller_register(chip->dw); + dw_dma_acpi_controller_register(chip->dw); return 0; @@ -256,8 +261,7 @@ static int dw_remove(struct platform_device *pdev) struct dw_dma_chip *chip = data->chip; int ret; - if (ACPI_HANDLE(&pdev->dev)) - dw_dma_acpi_controller_free(chip->dw); + dw_dma_acpi_controller_free(chip->dw); if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); -- GitLab From b685fe26e9af7318d73bf50af659a282d188a3e5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:45 +0300 Subject: [PATCH 3781/7155] dmaengine: dw: platform: Split ACPI helpers to separate module For better maintenance split ACPI helpers to the separate module. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-10-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/Makefile | 3 ++- drivers/dma/dw/acpi.c | 53 +++++++++++++++++++++++++++++++++++++++ drivers/dma/dw/internal.h | 8 ++++++ drivers/dma/dw/platform.c | 52 -------------------------------------- 4 files changed, 63 insertions(+), 53 deletions(-) create mode 100644 drivers/dma/dw/acpi.c diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile index 63ed895c09aa..5e69815f3cf1 100644 --- a/drivers/dma/dw/Makefile +++ b/drivers/dma/dw/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw_dmac_core.o dw_dmac_core-objs := core.o dw.o idma32.o obj-$(CONFIG_DW_DMAC) += dw_dmac.o -dw_dmac-objs := platform.o +dw_dmac-y := platform.o +dw_dmac-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_DW_DMAC_PCI) += dw_dmac_pci.o dw_dmac_pci-objs := pci.o diff --git a/drivers/dma/dw/acpi.c b/drivers/dma/dw/acpi.c new file mode 100644 index 000000000000..f6e8d55b4f6e --- /dev/null +++ b/drivers/dma/dw/acpi.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2013,2019 Intel Corporation + +#include +#include + +#include "internal.h" + +static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) +{ + struct acpi_dma_spec *dma_spec = param; + struct dw_dma_slave slave = { + .dma_dev = dma_spec->dev, + .src_id = dma_spec->slave_id, + .dst_id = dma_spec->slave_id, + .m_master = 0, + .p_master = 1, + }; + + return dw_dma_filter(chan, &slave); +} + +void dw_dma_acpi_controller_register(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + struct acpi_dma_filter_info *info; + int ret; + + if (!has_acpi_companion(dev)) + return; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return; + + dma_cap_zero(info->dma_cap); + dma_cap_set(DMA_SLAVE, info->dma_cap); + info->filter_fn = dw_dma_acpi_filter; + + ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info); + if (ret) + dev_err(dev, "could not register acpi_dma_controller\n"); +} + +void dw_dma_acpi_controller_free(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + + if (!has_acpi_companion(dev)) + return; + + acpi_dma_controller_free(dev); +} diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h index df5c84e2a4fd..acada530aa96 100644 --- a/drivers/dma/dw/internal.h +++ b/drivers/dma/dw/internal.h @@ -23,6 +23,14 @@ int do_dw_dma_enable(struct dw_dma_chip *chip); extern bool dw_dma_filter(struct dma_chan *chan, void *param); +#ifdef CONFIG_ACPI +void dw_dma_acpi_controller_register(struct dw_dma *dw); +void dw_dma_acpi_controller_free(struct dw_dma *dw); +#else /* !CONFIG_ACPI */ +static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} +static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {} +#endif /* !CONFIG_ACPI */ + struct dw_dma_chip_pdata { const struct dw_dma_platform_data *pdata; int (*probe)(struct dw_dma_chip *chip); diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index b8514d7895d1..d50e038acb1e 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "internal.h" @@ -55,57 +54,6 @@ static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, return dma_request_channel(cap, dw_dma_filter, &slave); } -#ifdef CONFIG_ACPI -static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) -{ - struct acpi_dma_spec *dma_spec = param; - struct dw_dma_slave slave = { - .dma_dev = dma_spec->dev, - .src_id = dma_spec->slave_id, - .dst_id = dma_spec->slave_id, - .m_master = 0, - .p_master = 1, - }; - - return dw_dma_filter(chan, &slave); -} - -static void dw_dma_acpi_controller_register(struct dw_dma *dw) -{ - struct device *dev = dw->dma.dev; - struct acpi_dma_filter_info *info; - int ret; - - if (!has_acpi_companion(dev)) - return; - - info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); - if (!info) - return; - - dma_cap_zero(info->dma_cap); - dma_cap_set(DMA_SLAVE, info->dma_cap); - info->filter_fn = dw_dma_acpi_filter; - - ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info); - if (ret) - dev_err(dev, "could not register acpi_dma_controller\n"); -} - -static void dw_dma_acpi_controller_free(struct dw_dma *dw) -{ - struct device *dev = dw->dma.dev; - - if (!has_acpi_companion(dev)) - return; - - acpi_dma_controller_free(dev); -} -#else /* !CONFIG_ACPI */ -static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} -static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {} -#endif /* !CONFIG_ACPI */ - #ifdef CONFIG_OF static struct dw_dma_platform_data * dw_dma_parse_dt(struct platform_device *pdev) -- GitLab From f5e84eae7956c694d27ddaba7113fe7d1174eff7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Aug 2019 16:15:46 +0300 Subject: [PATCH 3782/7155] dmaengine: dw: platform: Split OF helpers to separate module For better maintenance split OF helpers to the separate module. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190820131546.75744-11-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/Makefile | 1 + drivers/dma/dw/internal.h | 15 +++++ drivers/dma/dw/of.c | 131 ++++++++++++++++++++++++++++++++++++++ drivers/dma/dw/platform.c | 115 +-------------------------------- 4 files changed, 149 insertions(+), 113 deletions(-) create mode 100644 drivers/dma/dw/of.c diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile index 5e69815f3cf1..b6f06699e91a 100644 --- a/drivers/dma/dw/Makefile +++ b/drivers/dma/dw/Makefile @@ -5,6 +5,7 @@ dw_dmac_core-objs := core.o dw.o idma32.o obj-$(CONFIG_DW_DMAC) += dw_dmac.o dw_dmac-y := platform.o dw_dmac-$(CONFIG_ACPI) += acpi.o +dw_dmac-$(CONFIG_OF) += of.o obj-$(CONFIG_DW_DMAC_PCI) += dw_dmac_pci.o dw_dmac_pci-objs := pci.o diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h index acada530aa96..2e1c52eefdeb 100644 --- a/drivers/dma/dw/internal.h +++ b/drivers/dma/dw/internal.h @@ -31,6 +31,21 @@ static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {} #endif /* !CONFIG_ACPI */ +struct platform_device; + +#ifdef CONFIG_OF +struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev); +void dw_dma_of_controller_register(struct dw_dma *dw); +void dw_dma_of_controller_free(struct dw_dma *dw); +#else +static inline struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev) +{ + return NULL; +} +static inline void dw_dma_of_controller_register(struct dw_dma *dw) {} +static inline void dw_dma_of_controller_free(struct dw_dma *dw) {} +#endif + struct dw_dma_chip_pdata { const struct dw_dma_platform_data *pdata; int (*probe)(struct dw_dma_chip *chip); diff --git a/drivers/dma/dw/of.c b/drivers/dma/dw/of.c new file mode 100644 index 000000000000..9e27831dee32 --- /dev/null +++ b/drivers/dma/dw/of.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Platform driver for the Synopsys DesignWare DMA Controller + * + * Copyright (C) 2007-2008 Atmel Corporation + * Copyright (C) 2010-2011 ST Microelectronics + * Copyright (C) 2013 Intel Corporation + */ + +#include +#include +#include + +#include "internal.h" + +static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct dw_dma *dw = ofdma->of_dma_data; + struct dw_dma_slave slave = { + .dma_dev = dw->dma.dev, + }; + dma_cap_mask_t cap; + + if (dma_spec->args_count != 3) + return NULL; + + slave.src_id = dma_spec->args[0]; + slave.dst_id = dma_spec->args[0]; + slave.m_master = dma_spec->args[1]; + slave.p_master = dma_spec->args[2]; + + if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || + slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || + slave.m_master >= dw->pdata->nr_masters || + slave.p_master >= dw->pdata->nr_masters)) + return NULL; + + dma_cap_zero(cap); + dma_cap_set(DMA_SLAVE, cap); + + /* TODO: there should be a simpler way to do this */ + return dma_request_channel(cap, dw_dma_filter, &slave); +} + +struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct dw_dma_platform_data *pdata; + u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS]; + u32 nr_masters; + u32 nr_channels; + + if (!np) { + dev_err(&pdev->dev, "Missing DT data\n"); + return NULL; + } + + if (of_property_read_u32(np, "dma-masters", &nr_masters)) + return NULL; + if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS) + return NULL; + + if (of_property_read_u32(np, "dma-channels", &nr_channels)) + return NULL; + if (nr_channels > DW_DMA_MAX_NR_CHANNELS) + return NULL; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->nr_masters = nr_masters; + pdata->nr_channels = nr_channels; + + if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) + pdata->chan_allocation_order = (unsigned char)tmp; + + if (!of_property_read_u32(np, "chan_priority", &tmp)) + pdata->chan_priority = tmp; + + if (!of_property_read_u32(np, "block_size", &tmp)) + pdata->block_size = tmp; + + if (!of_property_read_u32_array(np, "data-width", arr, nr_masters)) { + for (tmp = 0; tmp < nr_masters; tmp++) + pdata->data_width[tmp] = arr[tmp]; + } else if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) { + for (tmp = 0; tmp < nr_masters; tmp++) + pdata->data_width[tmp] = BIT(arr[tmp] & 0x07); + } + + if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) { + for (tmp = 0; tmp < nr_channels; tmp++) + pdata->multi_block[tmp] = mb[tmp]; + } else { + for (tmp = 0; tmp < nr_channels; tmp++) + pdata->multi_block[tmp] = 1; + } + + if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) { + if (tmp > CHAN_PROTCTL_MASK) + return NULL; + pdata->protctl = tmp; + } + + return pdata; +} + +void dw_dma_of_controller_register(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + int ret; + + if (!dev->of_node) + return; + + ret = of_dma_controller_register(dev->of_node, dw_dma_of_xlate, dw); + if (ret) + dev_err(dev, "could not register of_dma_controller\n"); +} + +void dw_dma_of_controller_free(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + + if (!dev->of_node) + return; + + of_dma_controller_free(dev->of_node); +} diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index d50e038acb1e..c90c798e5ec3 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -17,116 +17,12 @@ #include #include #include -#include #include #include "internal.h" #define DRV_NAME "dw_dmac" -static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, - struct of_dma *ofdma) -{ - struct dw_dma *dw = ofdma->of_dma_data; - struct dw_dma_slave slave = { - .dma_dev = dw->dma.dev, - }; - dma_cap_mask_t cap; - - if (dma_spec->args_count != 3) - return NULL; - - slave.src_id = dma_spec->args[0]; - slave.dst_id = dma_spec->args[0]; - slave.m_master = dma_spec->args[1]; - slave.p_master = dma_spec->args[2]; - - if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || - slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || - slave.m_master >= dw->pdata->nr_masters || - slave.p_master >= dw->pdata->nr_masters)) - return NULL; - - dma_cap_zero(cap); - dma_cap_set(DMA_SLAVE, cap); - - /* TODO: there should be a simpler way to do this */ - return dma_request_channel(cap, dw_dma_filter, &slave); -} - -#ifdef CONFIG_OF -static struct dw_dma_platform_data * -dw_dma_parse_dt(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct dw_dma_platform_data *pdata; - u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS]; - u32 nr_masters; - u32 nr_channels; - - if (!np) { - dev_err(&pdev->dev, "Missing DT data\n"); - return NULL; - } - - if (of_property_read_u32(np, "dma-masters", &nr_masters)) - return NULL; - if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS) - return NULL; - - if (of_property_read_u32(np, "dma-channels", &nr_channels)) - return NULL; - if (nr_channels > DW_DMA_MAX_NR_CHANNELS) - return NULL; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - pdata->nr_masters = nr_masters; - pdata->nr_channels = nr_channels; - - if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) - pdata->chan_allocation_order = (unsigned char)tmp; - - if (!of_property_read_u32(np, "chan_priority", &tmp)) - pdata->chan_priority = tmp; - - if (!of_property_read_u32(np, "block_size", &tmp)) - pdata->block_size = tmp; - - if (!of_property_read_u32_array(np, "data-width", arr, nr_masters)) { - for (tmp = 0; tmp < nr_masters; tmp++) - pdata->data_width[tmp] = arr[tmp]; - } else if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) { - for (tmp = 0; tmp < nr_masters; tmp++) - pdata->data_width[tmp] = BIT(arr[tmp] & 0x07); - } - - if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) { - for (tmp = 0; tmp < nr_channels; tmp++) - pdata->multi_block[tmp] = mb[tmp]; - } else { - for (tmp = 0; tmp < nr_channels; tmp++) - pdata->multi_block[tmp] = 1; - } - - if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) { - if (tmp > CHAN_PROTCTL_MASK) - return NULL; - pdata->protctl = tmp; - } - - return pdata; -} -#else -static inline struct dw_dma_platform_data * -dw_dma_parse_dt(struct platform_device *pdev) -{ - return NULL; -} -#endif - static int dw_probe(struct platform_device *pdev) { const struct dw_dma_chip_pdata *match; @@ -185,13 +81,7 @@ static int dw_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - if (pdev->dev.of_node) { - err = of_dma_controller_register(pdev->dev.of_node, - dw_dma_of_xlate, chip->dw); - if (err) - dev_err(&pdev->dev, - "could not register of_dma_controller\n"); - } + dw_dma_of_controller_register(chip->dw); dw_dma_acpi_controller_register(chip->dw); @@ -211,8 +101,7 @@ static int dw_remove(struct platform_device *pdev) dw_dma_acpi_controller_free(chip->dw); - if (pdev->dev.of_node) - of_dma_controller_free(pdev->dev.of_node); + dw_dma_of_controller_free(chip->dw); ret = data->remove(chip); if (ret) -- GitLab From 150a6a931a328fa043522bce86db1501f2f1cb6f Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 12 Jul 2019 13:07:26 +0930 Subject: [PATCH 3783/7155] ARM: dts: aspeed: Enable first MMC slot on AST2500 EVB The EVB contains two slots. Enable one of them for testing purposes. Signed-off-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-ast2500-evb.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts index 556ed469830c..c9d88c90135e 100644 --- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts +++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts @@ -94,6 +94,17 @@ }; }; +&sdmmc { + status = "okay"; +}; + +&sdhci0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1_default>; +}; + /* * Enable port A as device (via the virtual hub) and port B as * host by default on the eval board. This can be easily changed -- GitLab From 57012813f1ba82412cdcc3665b04d4353b357378 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 7 May 2018 11:16:48 +0200 Subject: [PATCH 3784/7155] ARM: dts: r8a77470: Add PMU device node Enable support for the ARM Performance Monitor Units in the Cortex-A7 CPU cores on RZ/G1C by adding a device node for the PMU. New Linux output: hw perfevents: enabled with armv7_cortex_a7 PMU driver, 5 counters available Signed-off-by: Geert Uytterhoeven Tested-by: Fabrizio Castro Reviewed-by: Fabrizio Castro --- arch/arm/boot/dts/r8a77470.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi index 56cb10b42ed9..51806c7f486a 100644 --- a/arch/arm/boot/dts/r8a77470.dtsi +++ b/arch/arm/boot/dts/r8a77470.dtsi @@ -63,6 +63,13 @@ clock-frequency = <0>; }; + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts-extended = <&gic GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + /* External SCIF clock */ scif_clk: scif { compatible = "fixed-clock"; -- GitLab From dc649d649a5e07eaf8f4aefb8f0e35cc178dd11f Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 7 Aug 2019 09:59:46 +0200 Subject: [PATCH 3785/7155] mac80211: fix TX legacy rate reporting when tx_status_ext is used The RX Radiotap header length was not calculated properly when reporting legacy rates using tx_status_ext. Fixes: 3d07ffcaf320 ("mac80211: add struct ieee80211_tx_status support to ieee80211_add_tx_radiotap_header") Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190807075949.32414-1-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/status.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index f03aa8924d23..f984943cdabd 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -260,9 +260,15 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info, int len = sizeof(struct ieee80211_radiotap_header); /* IEEE80211_RADIOTAP_RATE rate */ - if (info->status.rates[0].idx >= 0 && - !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS | - IEEE80211_TX_RC_VHT_MCS))) + if (status && status->rate && !(status->rate->flags & + (RATE_INFO_FLAGS_MCS | + RATE_INFO_FLAGS_60G | + RATE_INFO_FLAGS_VHT_MCS | + RATE_INFO_FLAGS_HE_MCS))) + len += 2; + else if (info->status.rates[0].idx >= 0 && + !(info->status.rates[0].flags & + (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) len += 2; /* IEEE80211_RADIOTAP_TX_FLAGS */ -- GitLab From 8db6e7367d3ca78dd85c5e9fec2bd6d69981a980 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 7 Aug 2019 09:59:47 +0200 Subject: [PATCH 3786/7155] mac80211: fix bad guard when reporting legacy rates When reporting legacy rates inside the TX Radiotap header we need to split the check between "uses tx_statua_ext" and "is legacy rate". Not doing so would make the code drop into the !tx_status_ext path. Fixes: 3d07ffcaf320 ("mac80211: add struct ieee80211_tx_status support to ieee80211_add_tx_radiotap_header") Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190807075949.32414-2-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/status.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index f984943cdabd..4eac88fd2903 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -327,13 +327,13 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_RATE */ - if (status && status->rate && !(status->rate->flags & - (RATE_INFO_FLAGS_MCS | - RATE_INFO_FLAGS_60G | - RATE_INFO_FLAGS_VHT_MCS | - RATE_INFO_FLAGS_HE_MCS))) - legacy_rate = status->rate->legacy; - else if (info->status.rates[0].idx >= 0 && + if (status && status->rate) { + if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS | + RATE_INFO_FLAGS_60G | + RATE_INFO_FLAGS_VHT_MCS | + RATE_INFO_FLAGS_HE_MCS))) + legacy_rate = status->rate->legacy; + } else if (info->status.rates[0].idx >= 0 && !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) legacy_rate = -- GitLab From a027c3041fef93da93a2c49eb22b05891d2350b6 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 7 Aug 2019 09:59:48 +0200 Subject: [PATCH 3787/7155] mac80211: 80Mhz was not reported properly when using tx_status_ext When reporting 80MHz, we need to set 4 and not 2 inside the corresponding field inside the Tx Radiotap header. Fixes: 3d07ffcaf320 ("mac80211: add struct ieee80211_tx_status support to ieee80211_add_tx_radiotap_header") Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190807075949.32414-3-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/status.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 4eac88fd2903..ce0c50efd804 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -403,7 +403,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, *pos = 11; break; case RATE_INFO_BW_80: - *pos = 2; + *pos = 4; break; case RATE_INFO_BW_40: *pos = 1; -- GitLab From 3a00f08140646a54e0eff2ce8938bf248dad6153 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 7 Aug 2019 09:59:49 +0200 Subject: [PATCH 3788/7155] mac80211: add missing length field increment when generating Radiotap header The code generating the Tx Radiotap header when using tx_status_ext was missing a field increment after setting the VHT bandwidth. Fixes: 3d07ffcaf320 ("mac80211: add struct ieee80211_tx_status support to ieee80211_add_tx_radiotap_header") Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190807075949.32414-4-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/status.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ce0c50efd804..f88f94d1f177 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -412,6 +412,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, *pos = 0; break; } + pos++; /* u8 mcs_nss[4] */ *pos = (status->rate->mcs << 4) | status->rate->nss; -- GitLab From c5b9a7f826735228a38fab4a7b2707f032468c88 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:30:58 +0200 Subject: [PATCH 3789/7155] nl80211: add 6GHz band definition to enum nl80211_band In the 802.11ax specification a new band is introduced, which is also proposed by FCC for unlicensed use. This band is referred to as 6GHz spanning frequency range from 5925 to 7125 MHz. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-2-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 2 ++ net/mac80211/tx.c | 1 + 2 files changed, 3 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 822851d369ab..4d5988f47118 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4543,6 +4543,7 @@ enum nl80211_txrate_gi { * @NL80211_BAND_2GHZ: 2.4 GHz ISM band * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) + * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace * since newer kernel versions may support more bands */ @@ -4550,6 +4551,7 @@ enum nl80211_band { NL80211_BAND_2GHZ, NL80211_BAND_5GHZ, NL80211_BAND_60GHZ, + NL80211_BAND_6GHZ, NUM_NL80211_BANDS, }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 235c6377a203..1fa422782905 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -162,6 +162,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, break; } case NL80211_BAND_5GHZ: + case NL80211_BAND_6GHZ: if (r->flags & IEEE80211_RATE_MANDATORY_A) mrate = r->bitrate; break; -- GitLab From f89769cfdd5a469c9d5791a06a670d424e847477 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:30:59 +0200 Subject: [PATCH 3790/7155] cfg80211: add 6GHz UNII band definitions For the new 6GHz there are new UNII band definitions as listed in the FCC notice [1]. [1] https://docs.fcc.gov/public/attachments/FCC-18-147A1_Rcd.pdf Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-3-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/reg.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4831ad745f91..646107af9f41 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -3806,8 +3806,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) } /* - * See http://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii, for - * UNII band definitions + * See FCC notices for UNII band definitions + * 5GHz: https://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii + * 6GHz: https://www.fcc.gov/document/fcc-proposes-more-spectrum-unlicensed-use-0 */ int cfg80211_get_unii(int freq) { @@ -3831,6 +3832,22 @@ int cfg80211_get_unii(int freq) if (freq > 5725 && freq <= 5825) return 4; + /* UNII-5 */ + if (freq > 5925 && freq <= 6425) + return 5; + + /* UNII-6 */ + if (freq > 6425 && freq <= 6525) + return 6; + + /* UNII-7 */ + if (freq > 6525 && freq <= 6875) + return 7; + + /* UNII-8 */ + if (freq > 6875 && freq <= 7125) + return 8; + return -EINVAL; } -- GitLab From fadbdd069376833015f56dac27f9ed3b5d5caeb4 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 19 Aug 2019 21:54:55 +0900 Subject: [PATCH 3791/7155] arm64: dts: renesas: r8a774a1: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 174 +++++++++++----------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index bdb4675249fa..06c7c849c8ab 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -1726,6 +1726,28 @@ "ssi.1", "ssi.0"; status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + }; + port@1 { + reg = <1>; + }; + }; + + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + rcar_sound,dvc { dvc0: dvc-0 { dmas = <&audma1 0xbc>; @@ -1742,17 +1764,6 @@ mix1: mix-1 { }; }; - rcar_sound,ctu { - ctu00: ctu-0 { }; - ctu01: ctu-1 { }; - ctu02: ctu-2 { }; - ctu03: ctu-3 { }; - ctu10: ctu-4 { }; - ctu11: ctu-5 { }; - ctu12: ctu-6 { }; - ctu13: ctu-7 { }; - }; - rcar_sound,src { src0: src-0 { interrupts = ; @@ -1806,6 +1817,59 @@ }; }; + rcar_sound,ssi { + ssi0: ssi-0 { + interrupts = ; + dmas = <&audma0 0x01>, <&audma1 0x02>; + dma-names = "rx", "tx"; + }; + ssi1: ssi-1 { + interrupts = ; + dmas = <&audma0 0x03>, <&audma1 0x04>; + dma-names = "rx", "tx"; + }; + ssi2: ssi-2 { + interrupts = ; + dmas = <&audma0 0x05>, <&audma1 0x06>; + dma-names = "rx", "tx"; + }; + ssi3: ssi-3 { + interrupts = ; + dmas = <&audma0 0x07>, <&audma1 0x08>; + dma-names = "rx", "tx"; + }; + ssi4: ssi-4 { + interrupts = ; + dmas = <&audma0 0x09>, <&audma1 0x0a>; + dma-names = "rx", "tx"; + }; + ssi5: ssi-5 { + interrupts = ; + dmas = <&audma0 0x0b>, <&audma1 0x0c>; + dma-names = "rx", "tx"; + }; + ssi6: ssi-6 { + interrupts = ; + dmas = <&audma0 0x0d>, <&audma1 0x0e>; + dma-names = "rx", "tx"; + }; + ssi7: ssi-7 { + interrupts = ; + dmas = <&audma0 0x0f>, <&audma1 0x10>; + dma-names = "rx", "tx"; + }; + ssi8: ssi-8 { + interrupts = ; + dmas = <&audma0 0x11>, <&audma1 0x12>; + dma-names = "rx", "tx"; + }; + ssi9: ssi-9 { + interrupts = ; + dmas = <&audma0 0x13>, <&audma1 0x14>; + dma-names = "rx", "tx"; + }; + }; + rcar_sound,ssiu { ssiu00: ssiu-0 { dmas = <&audma0 0x15>, <&audma1 0x16>; @@ -2016,70 +2080,6 @@ dma-names = "rx", "tx"; }; }; - - rcar_sound,ssi { - ssi0: ssi-0 { - interrupts = ; - dmas = <&audma0 0x01>, <&audma1 0x02>; - dma-names = "rx", "tx"; - }; - ssi1: ssi-1 { - interrupts = ; - dmas = <&audma0 0x03>, <&audma1 0x04>; - dma-names = "rx", "tx"; - }; - ssi2: ssi-2 { - interrupts = ; - dmas = <&audma0 0x05>, <&audma1 0x06>; - dma-names = "rx", "tx"; - }; - ssi3: ssi-3 { - interrupts = ; - dmas = <&audma0 0x07>, <&audma1 0x08>; - dma-names = "rx", "tx"; - }; - ssi4: ssi-4 { - interrupts = ; - dmas = <&audma0 0x09>, <&audma1 0x0a>; - dma-names = "rx", "tx"; - }; - ssi5: ssi-5 { - interrupts = ; - dmas = <&audma0 0x0b>, <&audma1 0x0c>; - dma-names = "rx", "tx"; - }; - ssi6: ssi-6 { - interrupts = ; - dmas = <&audma0 0x0d>, <&audma1 0x0e>; - dma-names = "rx", "tx"; - }; - ssi7: ssi-7 { - interrupts = ; - dmas = <&audma0 0x0f>, <&audma1 0x10>; - dma-names = "rx", "tx"; - }; - ssi8: ssi-8 { - interrupts = ; - dmas = <&audma0 0x11>, <&audma1 0x12>; - dma-names = "rx", "tx"; - }; - ssi9: ssi-9 { - interrupts = ; - dmas = <&audma0 0x13>, <&audma1 0x14>; - dma-names = "rx", "tx"; - }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - }; - port@1 { - reg = <1>; - }; - }; }; audma0: dma-controller@ec700000 { @@ -2746,6 +2746,18 @@ thermal-sensors = <&tsc 2>; sustainable-power = <3874>; + cooling-maps { + map0 { + trip = <&target>; + cooling-device = <&a57_0 0 2>; + contribution = <1024>; + }; + map1 { + trip = <&target>; + cooling-device = <&a53_0 0 2>; + contribution = <1024>; + }; + }; trips { target: trip-point1 { temperature = <100000>; @@ -2759,18 +2771,6 @@ type = "critical"; }; }; - cooling-maps { - map0 { - trip = <&target>; - cooling-device = <&a57_0 0 2>; - contribution = <1024>; - }; - map1 { - trip = <&target>; - cooling-device = <&a53_0 0 2>; - contribution = <1024>; - }; - }; }; }; -- GitLab From 63a0f811558b9a5587a8c52978a57a8b528b074a Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 19 Aug 2019 21:55:41 +0900 Subject: [PATCH 3792/7155] arm64: dts: renesas: r8a774c0: cat874: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a774c0-cat874.dts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts index 651383cd048c..c99b1dec52ef 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts +++ b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts @@ -82,13 +82,13 @@ simple-audio-card,bitclock-master = <&sndcpu>; simple-audio-card,frame-master = <&sndcpu>; - sndcpu: simple-audio-card,cpu { - sound-dai = <&rcar_sound>; - }; - sndcodec: simple-audio-card,codec { sound-dai = <&tda19988>; }; + + sndcpu: simple-audio-card,cpu { + sound-dai = <&rcar_sound>; + }; }; vcc_sdhi0: regulator-vcc-sdhi0 { @@ -280,16 +280,16 @@ function = "du"; }; - i2c1_pins: i2c1 { - groups = "i2c1_b"; - function = "i2c1"; - }; - hscif2_pins: hscif2 { groups = "hscif2_data_a", "hscif2_ctrl_a"; function = "hscif2"; }; + i2c1_pins: i2c1 { + groups = "i2c1_b"; + function = "i2c1"; + }; + scif2_pins: scif2 { groups = "scif2_data_a"; function = "scif2"; @@ -313,16 +313,16 @@ power-source = <1800>; }; - sound_pins: sound { - groups = "ssi01239_ctrl", "ssi0_data"; - function = "ssi"; - }; - sound_clk_pins: sound_clk { groups = "audio_clkout1_a"; function = "audio_clk"; }; + sound_pins: sound { + groups = "ssi01239_ctrl", "ssi0_data"; + function = "ssi"; + }; + usb30_pins: usb30 { groups = "usb30", "usb30_id"; function = "usb30"; -- GitLab From fa1f1085bc063da5a44f779c9b655b7026c52d68 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:00 +0200 Subject: [PATCH 3793/7155] cfg80211: util: add 6GHz channel to freq conversion and vice versa Extend the functions ieee80211_channel_to_frequency() and ieee80211_frequency_to_channel() to support 6GHz band according specification in 802.11ax D4.1 27.3.22.2. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-4-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/util.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index d0e35b7b9e35..c18d4fc440f4 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -91,6 +91,11 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band) else return 5000 + chan * 5; break; + case NL80211_BAND_6GHZ: + /* see 802.11ax D4.1 27.3.22.2 */ + if (chan <= 253) + return 5940 + chan * 5; + break; case NL80211_BAND_60GHZ: if (chan < 7) return 56160 + chan * 2160; @@ -111,8 +116,11 @@ int ieee80211_frequency_to_channel(int freq) return (freq - 2407) / 5; else if (freq >= 4910 && freq <= 4980) return (freq - 4000) / 5; - else if (freq <= 45000) /* DMG band lower limit */ + else if (freq < 5940) return (freq - 5000) / 5; + else if (freq <= 45000) /* DMG band lower limit */ + /* see 802.11ax D4.1 27.3.22.2 */ + return (freq - 5940) / 5; else if (freq >= 58320 && freq <= 70200) return (freq - 56160) / 2160; else -- GitLab From 852f04620e5b7c27eadbf81d086d04f61431c9dc Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:01 +0200 Subject: [PATCH 3794/7155] cfg80211: extend ieee80211_operating_class_to_band() for 6GHz Add 6GHz operating class range as defined in 802.11ax D4.1 Annex E. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-5-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/util.c b/net/wireless/util.c index c18d4fc440f4..27171aa10e9f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1474,6 +1474,9 @@ bool ieee80211_operating_class_to_band(u8 operating_class, case 128 ... 130: *band = NL80211_BAND_5GHZ; return true; + case 131 ... 135: + *band = NL80211_BAND_6GHZ; + return true; case 81: case 82: case 83: -- GitLab From e548a1c36b11ccf56627e5a2581409e2f27a6ac4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:02 +0200 Subject: [PATCH 3795/7155] cfg80211: add 6GHz in code handling array with NUM_NL80211_BANDS entries In nl80211.c there is a policy for all bands in NUM_NL80211_BANDS and in trace.h there is a callback trace for multicast rates which is per band in NUM_NL80211_BANDS. Both need to be extended for the new NL80211_BAND_6GHZ. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-6-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 1 + net/wireless/trace.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 92e06482563c..9a642219a8c7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -677,6 +677,7 @@ static const struct nla_policy nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = { [NL80211_BAND_2GHZ] = { .type = NLA_S32 }, [NL80211_BAND_5GHZ] = { .type = NLA_S32 }, + [NL80211_BAND_6GHZ] = { .type = NLA_S32 }, [NL80211_BAND_60GHZ] = { .type = NLA_S32 }, }; diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 4fbb91a511ae..d98ad2b3143b 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2446,10 +2446,11 @@ TRACE_EVENT(rdev_set_mcast_rate, sizeof(int) * NUM_NL80211_BANDS); ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " - "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]", + "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 6GHz=0x%x, 60GHz=0x%x]", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mcast_rate[NL80211_BAND_2GHZ], __entry->mcast_rate[NL80211_BAND_5GHZ], + __entry->mcast_rate[NL80211_BAND_6GHZ], __entry->mcast_rate[NL80211_BAND_60GHZ]) ); -- GitLab From 0816e6b1177adb4f120767434c67441c30de10d2 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:03 +0200 Subject: [PATCH 3796/7155] cfg80211: use same IR permissive rules for 6GHz band The function cfg80211_ir_permissive_chan() is applicable for 6GHz band as well so make sure it is handled. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-7-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/chan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 7dc1bbd0888f..7c9d204838d4 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -894,7 +894,8 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, if (chan == other_chan) return true; - if (chan->band != NL80211_BAND_5GHZ) + if (chan->band != NL80211_BAND_5GHZ && + chan->band != NL80211_BAND_6GHZ) continue; r1 = cfg80211_get_unii(chan->center_freq); -- GitLab From 5ea4e7802c43144f5529d1b60c01853dc5c24797 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:04 +0200 Subject: [PATCH 3797/7155] cfg80211: ibss: use 11a mandatory rates for 6GHz band operation The default mandatory rates, ie. when not specified by user-space, is determined by the band. Select 11a rateset for 6GHz band. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-8-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/ibss.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index d1743e6abc34..ae8fe66a9bb8 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -104,13 +104,19 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, * use the mandatory rate set for 11b or * 11a for maximum compatibility. */ - struct ieee80211_supported_band *sband = - rdev->wiphy.bands[params->chandef.chan->band]; + struct ieee80211_supported_band *sband; + enum nl80211_band band; + u32 flag; int j; - u32 flag = params->chandef.chan->band == NL80211_BAND_5GHZ ? - IEEE80211_RATE_MANDATORY_A : - IEEE80211_RATE_MANDATORY_B; + band = params->chandef.chan->band; + if (band == NL80211_BAND_5GHZ || + band == NL80211_BAND_6GHZ) + flag = IEEE80211_RATE_MANDATORY_A; + else + flag = IEEE80211_RATE_MANDATORY_B; + + sband = rdev->wiphy.bands[band]; for (j = 0; j < sband->n_bitrates; j++) { if (sband->bitrates[j].flags & flag) params->basic_rates |= BIT(j); -- GitLab From 62524a5857d2356b53e6e75fdce95dfd3454ab9e Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Aug 2019 13:31:05 +0200 Subject: [PATCH 3798/7155] cfg80211: apply same mandatory rate flags for 5GHz and 6GHz For the new 6GHz band the same rules apply for mandatory rates so add it to set_mandatory_flags_band() function. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Leon Zegers Signed-off-by: Arend van Spriel Link: https://lore.kernel.org/r/1564745465-21234-9-git-send-email-arend.vanspriel@broadcom.com Signed-off-by: Johannes Berg --- net/wireless/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/util.c b/net/wireless/util.c index 27171aa10e9f..59ed0808c13e 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -156,6 +156,7 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband) switch (sband->band) { case NL80211_BAND_5GHZ: + case NL80211_BAND_6GHZ: want = 3; for (i = 0; i < sband->n_bitrates; i++) { if (sband->bitrates[i].bitrate == 60 || -- GitLab From 6c7a00339e2a64b068c986301f37bd31eb83d7e9 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 9 Aug 2019 11:00:00 -0700 Subject: [PATCH 3799/7155] cfg80211: Support assoc-at timer in sta-info Report timestamp of when sta became associated. This is the boottime clock, units are nano-seconds. Signed-off-by: Ben Greear Link: https://lore.kernel.org/r/20190809180001.26393-1-greearb@candelatech.com Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 3 +++ net/wireless/nl80211.c | 1 + 3 files changed, 6 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8140c4837122..1e32b11e1730 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1330,6 +1330,7 @@ struct cfg80211_tid_stats { * indicate the relevant values in this struct for them * @connected_time: time(in secs) since a station is last connected * @inactive_time: time since last station activity (tx/rx) in milliseconds + * @assoc_at: bootime (ns) of the last association * @rx_bytes: bytes (size of MPDUs) received from this station * @tx_bytes: bytes (size of MPDUs) transmitted to this station * @llid: mesh local link id @@ -1390,6 +1391,7 @@ struct station_info { u64 filled; u32 connected_time; u32 inactive_time; + u64 assoc_at; u64 rx_bytes; u64 tx_bytes; u16 llid; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 4d5988f47118..04b58295c8d9 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3201,6 +3201,8 @@ enum nl80211_sta_bss_param { * sent to the station (u64, usec) * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16) * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station + * @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds) + * of STA's association * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3247,6 +3249,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_TX_DURATION, NL80211_STA_INFO_AIRTIME_WEIGHT, NL80211_STA_INFO_AIRTIME_LINK_METRIC, + NL80211_STA_INFO_ASSOC_AT_BOOTTIME, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9a642219a8c7..cacd96704647 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5032,6 +5032,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, PUT_SINFO(CONNECTED_TIME, connected_time, u32); PUT_SINFO(INACTIVE_TIME, inactive_time, u32); + PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at); if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) | BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) && -- GitLab From e376df94d3f75161fa7a0f114fd2dff190d0b6af Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 19 Aug 2019 21:56:01 +0900 Subject: [PATCH 3800/7155] arm64: dts: renesas: r8a774c0: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 90 +++++++++++------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index 746775f4ab99..dc80c1a2ac1d 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1371,6 +1371,17 @@ "ssi.1", "ssi.0"; status = "disabled"; + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + rcar_sound,dvc { dvc0: dvc-0 { dmas = <&audma0 0xbc>; @@ -1387,17 +1398,6 @@ mix1: mix-1 { }; }; - rcar_sound,ctu { - ctu00: ctu-0 { }; - ctu01: ctu-1 { }; - ctu02: ctu-2 { }; - ctu03: ctu-3 { }; - ctu10: ctu-4 { }; - ctu11: ctu-5 { }; - ctu12: ctu-6 { }; - ctu13: ctu-7 { }; - }; - rcar_sound,src { src0: src-0 { interrupts = ; @@ -1706,13 +1706,24 @@ renesas,fcp = <&fcpvb0>; }; - fcpvb0: fcp@fe96f000 { - compatible = "renesas,fcpv"; - reg = <0 0xfe96f000 0 0x200>; - clocks = <&cpg CPG_MOD 607>; + vspd0: vsp@fea20000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea20000 0 0x7000>; + interrupts = ; + clocks = <&cpg CPG_MOD 623>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; - resets = <&cpg 607>; - iommus = <&ipmmu_vp0 5>; + resets = <&cpg 623>; + renesas,fcp = <&fcpvd0>; + }; + + vspd1: vsp@fea28000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea28000 0 0x7000>; + interrupts = ; + clocks = <&cpg CPG_MOD 622>; + power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; + resets = <&cpg 622>; + renesas,fcp = <&fcpvd1>; }; vspi0: vsp@fe9a0000 { @@ -1725,23 +1736,13 @@ renesas,fcp = <&fcpvi0>; }; - fcpvi0: fcp@fe9af000 { + fcpvb0: fcp@fe96f000 { compatible = "renesas,fcpv"; - reg = <0 0xfe9af000 0 0x200>; - clocks = <&cpg CPG_MOD 611>; - power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; - resets = <&cpg 611>; - iommus = <&ipmmu_vp0 8>; - }; - - vspd0: vsp@fea20000 { - compatible = "renesas,vsp2"; - reg = <0 0xfea20000 0 0x7000>; - interrupts = ; - clocks = <&cpg CPG_MOD 623>; + reg = <0 0xfe96f000 0 0x200>; + clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; - resets = <&cpg 623>; - renesas,fcp = <&fcpvd0>; + resets = <&cpg 607>; + iommus = <&ipmmu_vp0 5>; }; fcpvd0: fcp@fea27000 { @@ -1753,16 +1754,6 @@ iommus = <&ipmmu_vi0 8>; }; - vspd1: vsp@fea28000 { - compatible = "renesas,vsp2"; - reg = <0 0xfea28000 0 0x7000>; - interrupts = ; - clocks = <&cpg CPG_MOD 622>; - power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; - resets = <&cpg 622>; - renesas,fcp = <&fcpvd1>; - }; - fcpvd1: fcp@fea2f000 { compatible = "renesas,fcpv"; reg = <0 0xfea2f000 0 0x200>; @@ -1772,6 +1763,15 @@ iommus = <&ipmmu_vi0 9>; }; + fcpvi0: fcp@fe9af000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9af000 0 0x200>; + clocks = <&cpg CPG_MOD 611>; + power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; + resets = <&cpg 611>; + iommus = <&ipmmu_vp0 8>; + }; + csi40: csi2@feaa0000 { compatible = "renesas,r8a774c0-csi2"; reg = <0 0xfeaa0000 0 0x10000>; @@ -1908,6 +1908,9 @@ polling-delay = <1000>; thermal-sensors = <&thermal>; + cooling-maps { + }; + trips { cpu-crit { temperature = <120000>; @@ -1915,9 +1918,6 @@ type = "critical"; }; }; - - cooling-maps { - }; }; }; -- GitLab From 9cf02338880dfc5928e98e3a1200d5aacfa6d1c6 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 9 Aug 2019 11:00:01 -0700 Subject: [PATCH 3801/7155] mac80211: add assoc-at support Report timestamp for when sta becomes associated. Signed-off-by: Ben Greear Link: https://lore.kernel.org/r/20190809180001.26393-2-greearb@candelatech.com [fix ktime_get_boot_ns() to ktime_get_boottime_ns(), assoc_at type to u64] Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 3 +++ net/mac80211/sta_info.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb6614f57cbc..df553070206c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1961,6 +1961,7 @@ int sta_info_move_state(struct sta_info *sta, case IEEE80211_STA_ASSOC: if (sta->sta_state == IEEE80211_STA_AUTH) { set_bit(WLAN_STA_ASSOC, &sta->_flags); + sta->assoc_at = ktime_get_boottime_ns(); ieee80211_recalc_min_chandef(sta->sdata); if (!sta->sta.support_p2p_ps) ieee80211_recalc_p2p_go_ps_allowed(sta->sdata); @@ -2190,6 +2191,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, BIT_ULL(NL80211_STA_INFO_STA_FLAGS) | BIT_ULL(NL80211_STA_INFO_BSS_PARAM) | BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) | + BIT_ULL(NL80211_STA_INFO_ASSOC_AT_BOOTTIME) | BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC); if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -2198,6 +2200,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, } sinfo->connected_time = ktime_get_seconds() - sta->last_connected; + sinfo->assoc_at = sta->assoc_at; sinfo->inactive_time = jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta)); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 3260d4234920..369c2dddce52 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -466,6 +466,7 @@ struct ieee80211_sta_rx_stats { * the station when it leaves powersave or polls for frames * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on + * @assoc_at: clock boottime (in ns) of last association * @last_connected: time (in seconds) when a station got connected * @last_seq_ctrl: last received seq/frag number from this STA (per TID * plus one for non-QoS frames) @@ -562,6 +563,7 @@ struct sta_info { unsigned long driver_buffered_tids; unsigned long txq_buffered_tids; + u64 assoc_at; long last_connected; /* Updated from RX path only, no locking requirements */ -- GitLab From 5db16ba82f38849a78ae932c0b7eada4cd2eb919 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 13 Aug 2019 09:07:12 +0200 Subject: [PATCH 3802/7155] mac80211: fix possible NULL pointerderef in obss pd code he_spr_ie_elem is dereferenced before the NULL check. fix this by moving the assignment after the check. fixes commit 697f6c507c74 ("mac80211: propagate HE operation info into bss_conf") This was reported by the static code checker. Reported-by: Dan Carpenter Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20190813070712.25509-1-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/he.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/he.c b/net/mac80211/he.c index a02abfc424aa..736da0035135 100644 --- a/net/mac80211/he.c +++ b/net/mac80211/he.c @@ -72,12 +72,13 @@ ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif, { struct ieee80211_he_obss_pd *he_obss_pd = &vif->bss_conf.he_obss_pd; - const u8 *data = he_spr_ie_elem->optional; + const u8 *data; memset(he_obss_pd, 0, sizeof(*he_obss_pd)); if (!he_spr_ie_elem) return; + data = he_spr_ie_elem->optional; if (he_spr_ie_elem->he_sr_control & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) -- GitLab From 13a398a17afed664d3539d9d2c85fcb489b494e5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 19 Aug 2019 21:56:18 +0900 Subject: [PATCH 3803/7155] arm64: dts: renesas: r8a7796: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7796.dtsi | 152 +++++++++++------------ 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi index 26df5b88efd7..3dc9d73f589a 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi @@ -1833,6 +1833,17 @@ "ssi.1", "ssi.0"; status = "disabled"; + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + rcar_sound,dvc { dvc0: dvc-0 { dmas = <&audma1 0xbc>; @@ -1849,17 +1860,6 @@ mix1: mix-1 { }; }; - rcar_sound,ctu { - ctu00: ctu-0 { }; - ctu01: ctu-1 { }; - ctu02: ctu-2 { }; - ctu03: ctu-3 { }; - ctu10: ctu-4 { }; - ctu11: ctu-5 { }; - ctu12: ctu-6 { }; - ctu13: ctu-7 { }; - }; - rcar_sound,src { src0: src-0 { interrupts = ; @@ -1913,6 +1913,59 @@ }; }; + rcar_sound,ssi { + ssi0: ssi-0 { + interrupts = ; + dmas = <&audma0 0x01>, <&audma1 0x02>; + dma-names = "rx", "tx"; + }; + ssi1: ssi-1 { + interrupts = ; + dmas = <&audma0 0x03>, <&audma1 0x04>; + dma-names = "rx", "tx"; + }; + ssi2: ssi-2 { + interrupts = ; + dmas = <&audma0 0x05>, <&audma1 0x06>; + dma-names = "rx", "tx"; + }; + ssi3: ssi-3 { + interrupts = ; + dmas = <&audma0 0x07>, <&audma1 0x08>; + dma-names = "rx", "tx"; + }; + ssi4: ssi-4 { + interrupts = ; + dmas = <&audma0 0x09>, <&audma1 0x0a>; + dma-names = "rx", "tx"; + }; + ssi5: ssi-5 { + interrupts = ; + dmas = <&audma0 0x0b>, <&audma1 0x0c>; + dma-names = "rx", "tx"; + }; + ssi6: ssi-6 { + interrupts = ; + dmas = <&audma0 0x0d>, <&audma1 0x0e>; + dma-names = "rx", "tx"; + }; + ssi7: ssi-7 { + interrupts = ; + dmas = <&audma0 0x0f>, <&audma1 0x10>; + dma-names = "rx", "tx"; + }; + ssi8: ssi-8 { + interrupts = ; + dmas = <&audma0 0x11>, <&audma1 0x12>; + dma-names = "rx", "tx"; + }; + ssi9: ssi-9 { + interrupts = ; + dmas = <&audma0 0x13>, <&audma1 0x14>; + dma-names = "rx", "tx"; + }; + }; + rcar_sound,ssiu { ssiu00: ssiu-0 { dmas = <&audma0 0x15>, <&audma1 0x16>; @@ -2123,59 +2176,6 @@ dma-names = "rx", "tx"; }; }; - - rcar_sound,ssi { - ssi0: ssi-0 { - interrupts = ; - dmas = <&audma0 0x01>, <&audma1 0x02>; - dma-names = "rx", "tx"; - }; - ssi1: ssi-1 { - interrupts = ; - dmas = <&audma0 0x03>, <&audma1 0x04>; - dma-names = "rx", "tx"; - }; - ssi2: ssi-2 { - interrupts = ; - dmas = <&audma0 0x05>, <&audma1 0x06>; - dma-names = "rx", "tx"; - }; - ssi3: ssi-3 { - interrupts = ; - dmas = <&audma0 0x07>, <&audma1 0x08>; - dma-names = "rx", "tx"; - }; - ssi4: ssi-4 { - interrupts = ; - dmas = <&audma0 0x09>, <&audma1 0x0a>; - dma-names = "rx", "tx"; - }; - ssi5: ssi-5 { - interrupts = ; - dmas = <&audma0 0x0b>, <&audma1 0x0c>; - dma-names = "rx", "tx"; - }; - ssi6: ssi-6 { - interrupts = ; - dmas = <&audma0 0x0d>, <&audma1 0x0e>; - dma-names = "rx", "tx"; - }; - ssi7: ssi-7 { - interrupts = ; - dmas = <&audma0 0x0f>, <&audma1 0x10>; - dma-names = "rx", "tx"; - }; - ssi8: ssi-8 { - interrupts = ; - dmas = <&audma0 0x11>, <&audma1 0x12>; - dma-names = "rx", "tx"; - }; - ssi9: ssi-9 { - interrupts = ; - dmas = <&audma0 0x13>, <&audma1 0x14>; - dma-names = "rx", "tx"; - }; - }; }; audma0: dma-controller@ec700000 { @@ -2860,6 +2860,18 @@ thermal-sensors = <&tsc 2>; sustainable-power = <3874>; + cooling-maps { + map0 { + trip = <&target>; + cooling-device = <&a57_0 2 4>; + contribution = <1024>; + }; + map1 { + trip = <&target>; + cooling-device = <&a53_0 0 2>; + contribution = <1024>; + }; + }; trips { target: trip-point1 { temperature = <100000>; @@ -2873,18 +2885,6 @@ type = "critical"; }; }; - cooling-maps { - map0 { - trip = <&target>; - cooling-device = <&a57_0 2 4>; - contribution = <1024>; - }; - map1 { - trip = <&target>; - cooling-device = <&a53_0 0 2>; - contribution = <1024>; - }; - }; }; }; -- GitLab From 5eb624ebc700592d0c9e9e1b3ad59ffc6108c683 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 19 Aug 2019 21:56:33 +0900 Subject: [PATCH 3804/7155] arm64: dts: renesas: r8a77970: Sort nodes Sort nodes. If node address is present * Sort by node address, grouping all nodes with the same compat string and sorting the group alphabetically. Else * Sort alphabetically This should not have any run-time effect. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Simon Horman Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77970.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi index 5b6164d4b8e3..0cd3b376635d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi @@ -1181,6 +1181,9 @@ polling-delay = <1000>; thermal-sensors = <&thermal>; + cooling-maps { + }; + trips { cpu-crit { temperature = <120000>; @@ -1188,9 +1191,6 @@ type = "critical"; }; }; - - cooling-maps { - }; }; }; -- GitLab From 2a38075cd0beefa4da326380cf54c7b365ddc035 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Sun, 18 Aug 2019 17:35:17 +0300 Subject: [PATCH 3805/7155] nl80211: Add support for EDMG channels 802.11ay specification defines Enhanced Directional Multi-Gigabit (EDMG) STA and AP which allow channel bonding of 2 channels and more. Introduce new NL attributes that are needed for enabling and configuring EDMG support. Two new attributes are used by kernel to publish driver's EDMG capabilities to the userspace: NL80211_BAND_ATTR_EDMG_CHANNELS - bitmap field that indicates the 2.16 GHz channel(s) that are supported by the driver. When this attribute is not set it means driver does not support EDMG. NL80211_BAND_ATTR_EDMG_BW_CONFIG - represent the channel bandwidth configurations supported by the driver. Additional two new attributes are used by the userspace for connect command and for AP configuration: NL80211_ATTR_WIPHY_EDMG_CHANNELS NL80211_ATTR_WIPHY_EDMG_BW_CONFIG New rate info flag - RATE_INFO_FLAGS_EDMG, can be reported from driver and used for bitrate calculation that will take into account EDMG according to the 802.11ay specification. Signed-off-by: Alexei Avshalom Lazar Link: https://lore.kernel.org/r/1566138918-3823-2-git-send-email-ailizaro@codeaurora.org Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/wil6210/cfg80211.c | 2 +- include/net/cfg80211.h | 86 ++++++++++- include/uapi/linux/nl80211.h | 24 +++ net/mac80211/mlme.c | 2 +- net/mac80211/status.c | 6 +- net/wireless/chan.c | 159 ++++++++++++++++++++ net/wireless/nl80211.c | 37 +++++ net/wireless/util.c | 42 +++++- 8 files changed, 349 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 2fb4258941a5..2414f574bf69 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -351,7 +351,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) | BIT_ULL(NL80211_STA_INFO_TX_FAILED); - sinfo->txrate.flags = RATE_INFO_FLAGS_60G; + sinfo->txrate.flags = RATE_INFO_FLAGS_DMG; sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); sinfo->rxrate.mcs = stats->last_mcs_rx; sinfo->rx_bytes = stats->rx_bytes; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1e32b11e1730..5253e7f667bd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -330,6 +330,60 @@ struct ieee80211_sband_iftype_data { struct ieee80211_sta_he_cap he_cap; }; +/** + * enum ieee80211_edmg_bw_config - allowed channel bandwidth configurations + * + * @IEEE80211_EDMG_BW_CONFIG_4: 2.16GHz + * @IEEE80211_EDMG_BW_CONFIG_5: 2.16GHz and 4.32GHz + * @IEEE80211_EDMG_BW_CONFIG_6: 2.16GHz, 4.32GHz and 6.48GHz + * @IEEE80211_EDMG_BW_CONFIG_7: 2.16GHz, 4.32GHz, 6.48GHz and 8.64GHz + * @IEEE80211_EDMG_BW_CONFIG_8: 2.16GHz and 2.16GHz + 2.16GHz + * @IEEE80211_EDMG_BW_CONFIG_9: 2.16GHz, 4.32GHz and 2.16GHz + 2.16GHz + * @IEEE80211_EDMG_BW_CONFIG_10: 2.16GHz, 4.32GHz, 6.48GHz and 2.16GHz+2.16GHz + * @IEEE80211_EDMG_BW_CONFIG_11: 2.16GHz, 4.32GHz, 6.48GHz, 8.64GHz and + * 2.16GHz+2.16GHz + * @IEEE80211_EDMG_BW_CONFIG_12: 2.16GHz, 2.16GHz + 2.16GHz and + * 4.32GHz + 4.32GHz + * @IEEE80211_EDMG_BW_CONFIG_13: 2.16GHz, 4.32GHz, 2.16GHz + 2.16GHz and + * 4.32GHz + 4.32GHz + * @IEEE80211_EDMG_BW_CONFIG_14: 2.16GHz, 4.32GHz, 6.48GHz, 2.16GHz + 2.16GHz + * and 4.32GHz + 4.32GHz + * @IEEE80211_EDMG_BW_CONFIG_15: 2.16GHz, 4.32GHz, 6.48GHz, 8.64GHz, + * 2.16GHz + 2.16GHz and 4.32GHz + 4.32GHz + */ +enum ieee80211_edmg_bw_config { + IEEE80211_EDMG_BW_CONFIG_4 = 4, + IEEE80211_EDMG_BW_CONFIG_5 = 5, + IEEE80211_EDMG_BW_CONFIG_6 = 6, + IEEE80211_EDMG_BW_CONFIG_7 = 7, + IEEE80211_EDMG_BW_CONFIG_8 = 8, + IEEE80211_EDMG_BW_CONFIG_9 = 9, + IEEE80211_EDMG_BW_CONFIG_10 = 10, + IEEE80211_EDMG_BW_CONFIG_11 = 11, + IEEE80211_EDMG_BW_CONFIG_12 = 12, + IEEE80211_EDMG_BW_CONFIG_13 = 13, + IEEE80211_EDMG_BW_CONFIG_14 = 14, + IEEE80211_EDMG_BW_CONFIG_15 = 15, +}; + +/** + * struct ieee80211_edmg - EDMG configuration + * + * This structure describes most essential parameters needed + * to describe 802.11ay EDMG configuration + * + * @channels: bitmap that indicates the 2.16 GHz channel(s) + * that are allowed to be used for transmissions. + * Bit 0 indicates channel 1, bit 1 indicates channel 2, etc. + * Set to 0 indicate EDMG not supported. + * @bw_config: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations + */ +struct ieee80211_edmg { + u8 channels; + enum ieee80211_edmg_bw_config bw_config; +}; + /** * struct ieee80211_supported_band - frequency band definition * @@ -346,6 +400,7 @@ struct ieee80211_sband_iftype_data { * @n_bitrates: Number of bitrates in @bitrates * @ht_cap: HT capabilities in this band * @vht_cap: VHT capabilities in this band + * @edmg_cap: EDMG capabilities in this band * @n_iftype_data: number of iftype data entries * @iftype_data: interface type data entries. Note that the bits in * @types_mask inside this structure cannot overlap (i.e. only @@ -360,6 +415,7 @@ struct ieee80211_supported_band { int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; struct ieee80211_sta_vht_cap vht_cap; + struct ieee80211_edmg edmg_cap; u16 n_iftype_data; const struct ieee80211_sband_iftype_data *iftype_data; }; @@ -527,12 +583,17 @@ struct key_params { * @center_freq1: center frequency of first segment * @center_freq2: center frequency of second segment * (only with 80+80 MHz) + * @edmg: define the EDMG channels configuration. + * If edmg is requested (i.e. the .channels member is non-zero), + * chan will define the primary channel and all other + * parameters are ignored. */ struct cfg80211_chan_def { struct ieee80211_channel *chan; enum nl80211_chan_width width; u32 center_freq1; u32 center_freq2; + struct ieee80211_edmg edmg; }; /** @@ -590,6 +651,19 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1, chandef1->center_freq2 == chandef2->center_freq2); } +/** + * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel + * + * @chandef: the channel definition + * + * Return: %true if EDMG defined, %false otherwise. + */ +static inline bool +cfg80211_chandef_is_edmg(const struct cfg80211_chan_def *chandef) +{ + return chandef->edmg.channels || chandef->edmg.bw_config; +} + /** * cfg80211_chandef_compatible - check if two channel definitions are compatible * @chandef1: first channel definition @@ -1177,15 +1251,17 @@ int cfg80211_check_station_change(struct wiphy *wiphy, * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval - * @RATE_INFO_FLAGS_60G: 60GHz MCS + * @RATE_INFO_FLAGS_DMG: 60GHz MCS * @RATE_INFO_FLAGS_HE_MCS: HE MCS information + * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode */ enum rate_info_flags { RATE_INFO_FLAGS_MCS = BIT(0), RATE_INFO_FLAGS_VHT_MCS = BIT(1), RATE_INFO_FLAGS_SHORT_GI = BIT(2), - RATE_INFO_FLAGS_60G = BIT(3), + RATE_INFO_FLAGS_DMG = BIT(3), RATE_INFO_FLAGS_HE_MCS = BIT(4), + RATE_INFO_FLAGS_EDMG = BIT(5), }; /** @@ -1225,6 +1301,7 @@ enum rate_info_bw { * @he_dcm: HE DCM value * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc, * only valid if bw is %RATE_INFO_BW_HE_RU) + * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4) */ struct rate_info { u8 flags; @@ -1235,6 +1312,7 @@ struct rate_info { u8 he_gi; u8 he_dcm; u8 he_ru_alloc; + u8 n_bonded_ch; }; /** @@ -2438,6 +2516,9 @@ struct cfg80211_bss_selection { * @fils_erp_rrk_len: Length of @fils_erp_rrk in octets. * @want_1x: indicates user-space supports and wants to use 802.1X driver * offload of 4-way handshake. + * @edmg: define the EDMG channels. + * This may specify multiple channels and bonding options for the driver + * to choose from, based on BSS configuration. */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -2471,6 +2552,7 @@ struct cfg80211_connect_params { const u8 *fils_erp_rrk; size_t fils_erp_rrk_len; bool want_1x; + struct ieee80211_edmg edmg; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 04b58295c8d9..bf7c4222f512 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -52,6 +52,11 @@ #define NL80211_MULTICAST_GROUP_NAN "nan" #define NL80211_MULTICAST_GROUP_TESTMODE "testmode" +#define NL80211_EDMG_BW_CONFIG_MIN 4 +#define NL80211_EDMG_BW_CONFIG_MAX 15 +#define NL80211_EDMG_CHANNELS_MIN 1 +#define NL80211_EDMG_CHANNELS_MAX 0x3c /* 0b00111100 */ + /** * DOC: Station handling * @@ -2361,6 +2366,13 @@ enum nl80211_commands { * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection * functionality. * + * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute) + * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. (u8 attribute) + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2820,6 +2832,9 @@ enum nl80211_attrs { NL80211_ATTR_HE_OBSS_PD, + NL80211_ATTR_WIPHY_EDMG_CHANNELS, + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3431,6 +3446,12 @@ enum nl80211_band_iftype_attr { * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using * attributes from &enum nl80211_band_iftype_attr + * @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. + * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ @@ -3448,6 +3469,9 @@ enum nl80211_band_attr { NL80211_BAND_ATTR_VHT_CAPA, NL80211_BAND_ATTR_IFTYPE_DATA, + NL80211_BAND_ATTR_EDMG_CHANNELS, + NL80211_BAND_ATTR_EDMG_BW_CONFIG, + /* keep last */ __NL80211_BAND_ATTR_AFTER_LAST, NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 641876982ab9..6471f552a942 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -158,10 +158,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); + memset(chandef, 0, sizeof(struct cfg80211_chan_def)); chandef->chan = channel; chandef->width = NL80211_CHAN_WIDTH_20_NOHT; chandef->center_freq1 = channel->center_freq; - chandef->center_freq2 = 0; if (!ht_oper || !sta_ht_cap.ht_supported) { ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index f88f94d1f177..ab8ba5835ca0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -262,7 +262,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info, /* IEEE80211_RADIOTAP_RATE rate */ if (status && status->rate && !(status->rate->flags & (RATE_INFO_FLAGS_MCS | - RATE_INFO_FLAGS_60G | + RATE_INFO_FLAGS_DMG | + RATE_INFO_FLAGS_EDMG | RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_HE_MCS))) len += 2; @@ -329,7 +330,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, if (status && status->rate) { if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS | - RATE_INFO_FLAGS_60G | + RATE_INFO_FLAGS_DMG | + RATE_INFO_FLAGS_EDMG | RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_HE_MCS))) legacy_rate = status->rate->legacy; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 7c9d204838d4..e851cafd8e2f 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -14,6 +14,11 @@ #include "core.h" #include "rdev-ops.h" +static bool cfg80211_valid_60g_freq(u32 freq) +{ + return freq >= 58320 && freq <= 70200; +} + void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, struct ieee80211_channel *chan, enum nl80211_channel_type chan_type) @@ -23,6 +28,8 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, chandef->chan = chan; chandef->center_freq2 = 0; + chandef->edmg.bw_config = 0; + chandef->edmg.channels = 0; switch (chan_type) { case NL80211_CHAN_NO_HT: @@ -47,6 +54,91 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, } EXPORT_SYMBOL(cfg80211_chandef_create); +static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef) +{ + int max_contiguous = 0; + int num_of_enabled = 0; + int contiguous = 0; + int i; + + if (!chandef->edmg.channels || !chandef->edmg.bw_config) + return false; + + if (!cfg80211_valid_60g_freq(chandef->chan->center_freq)) + return false; + + for (i = 0; i < 6; i++) { + if (chandef->edmg.channels & BIT(i)) { + contiguous++; + num_of_enabled++; + } else { + contiguous = 0; + } + + max_contiguous = max(contiguous, max_contiguous); + } + /* basic verification of edmg configuration according to + * IEEE P802.11ay/D4.0 section 9.4.2.251 + */ + /* check bw_config against contiguous edmg channels */ + switch (chandef->edmg.bw_config) { + case IEEE80211_EDMG_BW_CONFIG_4: + case IEEE80211_EDMG_BW_CONFIG_8: + case IEEE80211_EDMG_BW_CONFIG_12: + if (max_contiguous < 1) + return false; + break; + case IEEE80211_EDMG_BW_CONFIG_5: + case IEEE80211_EDMG_BW_CONFIG_9: + case IEEE80211_EDMG_BW_CONFIG_13: + if (max_contiguous < 2) + return false; + break; + case IEEE80211_EDMG_BW_CONFIG_6: + case IEEE80211_EDMG_BW_CONFIG_10: + case IEEE80211_EDMG_BW_CONFIG_14: + if (max_contiguous < 3) + return false; + break; + case IEEE80211_EDMG_BW_CONFIG_7: + case IEEE80211_EDMG_BW_CONFIG_11: + case IEEE80211_EDMG_BW_CONFIG_15: + if (max_contiguous < 4) + return false; + break; + + default: + return false; + } + + /* check bw_config against aggregated (non contiguous) edmg channels */ + switch (chandef->edmg.bw_config) { + case IEEE80211_EDMG_BW_CONFIG_4: + case IEEE80211_EDMG_BW_CONFIG_5: + case IEEE80211_EDMG_BW_CONFIG_6: + case IEEE80211_EDMG_BW_CONFIG_7: + break; + case IEEE80211_EDMG_BW_CONFIG_8: + case IEEE80211_EDMG_BW_CONFIG_9: + case IEEE80211_EDMG_BW_CONFIG_10: + case IEEE80211_EDMG_BW_CONFIG_11: + if (num_of_enabled < 2) + return false; + break; + case IEEE80211_EDMG_BW_CONFIG_12: + case IEEE80211_EDMG_BW_CONFIG_13: + case IEEE80211_EDMG_BW_CONFIG_14: + case IEEE80211_EDMG_BW_CONFIG_15: + if (num_of_enabled < 4 || max_contiguous < 2) + return false; + break; + default: + return false; + } + + return true; +} + bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) { u32 control_freq; @@ -112,6 +204,10 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) return false; } + if (cfg80211_chandef_is_edmg(chandef) && + !cfg80211_edmg_chandef_valid(chandef)) + return false; + return true; } EXPORT_SYMBOL(cfg80211_chandef_valid); @@ -721,12 +817,66 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, return true; } +/* check if the operating channels are valid and supported */ +static bool cfg80211_edmg_usable(struct wiphy *wiphy, u8 edmg_channels, + enum ieee80211_edmg_bw_config edmg_bw_config, + int primary_channel, + struct ieee80211_edmg *edmg_cap) +{ + struct ieee80211_channel *chan; + int i, freq; + int channels_counter = 0; + + if (!edmg_channels && !edmg_bw_config) + return true; + + if ((!edmg_channels && edmg_bw_config) || + (edmg_channels && !edmg_bw_config)) + return false; + + if (!(edmg_channels & BIT(primary_channel - 1))) + return false; + + /* 60GHz channels 1..6 */ + for (i = 0; i < 6; i++) { + if (!(edmg_channels & BIT(i))) + continue; + + if (!(edmg_cap->channels & BIT(i))) + return false; + + channels_counter++; + + freq = ieee80211_channel_to_frequency(i + 1, + NL80211_BAND_60GHZ); + chan = ieee80211_get_channel(wiphy, freq); + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) + return false; + } + + /* IEEE802.11 allows max 4 channels */ + if (channels_counter > 4) + return false; + + /* check bw_config is a subset of what driver supports + * (see IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13) + */ + if ((edmg_bw_config % 4) > (edmg_cap->bw_config % 4)) + return false; + + if (edmg_bw_config > edmg_cap->bw_config) + return false; + + return true; +} + bool cfg80211_chandef_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef, u32 prohibited_flags) { struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_vht_cap *vht_cap; + struct ieee80211_edmg *edmg_cap; u32 width, control_freq, cap; if (WARN_ON(!cfg80211_chandef_valid(chandef))) @@ -734,6 +884,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap; vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap; + edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap; + + if (edmg_cap->channels && + !cfg80211_edmg_usable(wiphy, + chandef->edmg.channels, + chandef->edmg.bw_config, + chandef->chan->hw_value, + edmg_cap)) + return false; control_freq = chandef->chan->center_freq; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cacd96704647..4565d7385884 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -298,6 +298,13 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8, + NL80211_EDMG_CHANNELS_MIN, + NL80211_EDMG_CHANNELS_MAX), + [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8, + NL80211_EDMG_BW_CONFIG_MIN, + NL80211_EDMG_BW_CONFIG_MAX), + [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 }, [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 }, [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 }, @@ -1574,6 +1581,15 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg, nla_nest_end(msg, nl_iftype_data); } + /* add EDMG info */ + if (sband->edmg_cap.channels && + (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS, + sband->edmg_cap.channels) || + nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG, + sband->edmg_cap.bw_config))) + + return -ENOBUFS; + /* add bitrates */ nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES); if (!nl_rates) @@ -2677,6 +2693,18 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]); } + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) { + chandef->edmg.channels = + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]); + + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]) + chandef->edmg.bw_config = + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]); + } else { + chandef->edmg.bw_config = 0; + chandef->edmg.channels = 0; + } + if (!cfg80211_chandef_valid(chandef)) { NL_SET_ERR_MSG(extack, "invalid channel definition"); return -EINVAL; @@ -9894,6 +9922,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) { + connect.edmg.channels = + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]); + + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]) + connect.edmg.bw_config = + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]); + } + if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { connkeys = nl80211_parse_connkeys(rdev, info, NULL); if (IS_ERR(connkeys)) diff --git a/net/wireless/util.c b/net/wireless/util.c index 59ed0808c13e..c99939067bb0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1043,7 +1043,7 @@ static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate) return (bitrate + 50000) / 100000; } -static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) +static u32 cfg80211_calculate_bitrate_dmg(struct rate_info *rate) { static const u32 __mcs2bitrate[] = { /* control PHY */ @@ -1090,6 +1090,40 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) return __mcs2bitrate[rate->mcs]; } +static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate) +{ + static const u32 __mcs2bitrate[] = { + /* control PHY */ + [0] = 275, + /* SC PHY */ + [1] = 3850, + [2] = 7700, + [3] = 9625, + [4] = 11550, + [5] = 12512, /* 1251.25 mbps */ + [6] = 13475, + [7] = 15400, + [8] = 19250, + [9] = 23100, + [10] = 25025, + [11] = 26950, + [12] = 30800, + [13] = 38500, + [14] = 46200, + [15] = 50050, + [16] = 53900, + [17] = 57750, + [18] = 69300, + [19] = 75075, + [20] = 80850, + }; + + if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate))) + return 0; + + return __mcs2bitrate[rate->mcs] * rate->n_bonded_ch; +} + static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) { static const u32 base[4][10] = { @@ -1262,8 +1296,10 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) { if (rate->flags & RATE_INFO_FLAGS_MCS) return cfg80211_calculate_bitrate_ht(rate); - if (rate->flags & RATE_INFO_FLAGS_60G) - return cfg80211_calculate_bitrate_60g(rate); + if (rate->flags & RATE_INFO_FLAGS_DMG) + return cfg80211_calculate_bitrate_dmg(rate); + if (rate->flags & RATE_INFO_FLAGS_EDMG) + return cfg80211_calculate_bitrate_edmg(rate); if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) return cfg80211_calculate_bitrate_vht(rate); if (rate->flags & RATE_INFO_FLAGS_HE_MCS) -- GitLab From 56dd918ff06e3ee24d8067e93ed12b2a39e71394 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 20 Aug 2019 11:54:46 +0200 Subject: [PATCH 3806/7155] mac80211: minstrel_ht: fix per-group max throughput rate initialization The group number needs to be multiplied by the number of rates per group to get the full rate index Fixes: 5935839ad735 ("mac80211: improve minstrel_ht rate sorting by throughput & probability") Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20190820095449.45255-1-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 5a882da82f0e..ba230b037257 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -575,7 +575,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) /* (re)Initialize group rate indexes */ for(j = 0; j < MAX_THR_RATES; j++) - tmp_group_tp_rate[j] = group; + tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; for (i = 0; i < MCS_GROUP_RATES; i++) { if (!(mi->supported[group] & BIT(i))) -- GitLab From f793c7eedd94fa41e8b969b18c4907335065a376 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 20 Aug 2019 11:54:47 +0200 Subject: [PATCH 3807/7155] mac80211: minstrel_ht: reduce unnecessary rate probing attempts On hardware with static fallback tables (e.g. mt76x2), rate probing attempts can be very expensive. On such devices, avoid sampling rates slower than the per-group max throughput rate, based on the assumption that the fallback table will take care of probing lower rates within that group if the higher rates fail. To further reduce unnecessary probing attempts, skip duplicate attempts on rates slower than the max throughput rate. Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20190820095449.45255-2-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index ba230b037257..ad5da9a71da0 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1059,6 +1059,21 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) return -1; + + /* + * For devices with no configurable multi-rate retry, skip sampling + * below the per-group max throughput rate, and only use one sampling + * attempt per rate + */ + if (mp->hw->max_rates == 1 && + (minstrel_get_duration(mg->max_group_tp_rate[0]) < sample_dur || + mrs->attempts)) + return -1; + + /* Skip already sampled slow rates */ + if (sample_dur >= minstrel_get_duration(tp_rate1) && mrs->attempts) + return -1; + /* * Make sure that lower rates get sampled only occasionally, * if the link is working perfectly. -- GitLab From 21f7981b4bd904871c6bbd67333cf0f69ff7c06a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 20 Aug 2019 11:54:48 +0200 Subject: [PATCH 3808/7155] mac80211: minstrel_ht: fix default max throughput rate indexes Use the first supported rate instead of 0 (which can be invalid) Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20190820095449.45255-3-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index ad5da9a71da0..c5868a1de306 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -486,7 +486,7 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi, tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); - if (tmp_cck_tp > tmp_mcs_tp) { + if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) { for(i = 0; i < MAX_THR_RATES; i++) { minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i], tmp_mcs_tp_rate); @@ -558,11 +558,19 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) mi->sample_slow = 0; mi->sample_count = 0; - /* Initialize global rate indexes */ - for(j = 0; j < MAX_THR_RATES; j++){ - tmp_mcs_tp_rate[j] = 0; - tmp_cck_tp_rate[j] = 0; - } + memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate)); + memset(tmp_cck_tp_rate, 0, sizeof(tmp_cck_tp_rate)); + if (mi->supported[MINSTREL_CCK_GROUP]) + for (j = 0; j < ARRAY_SIZE(tmp_cck_tp_rate); j++) + tmp_cck_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; + + if (mi->supported[MINSTREL_VHT_GROUP_0]) + index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES; + else + index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES; + + for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) + tmp_mcs_tp_rate[j] = index; /* Find best rate sets within all MCS groups*/ for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { -- GitLab From 48cb39522a9d4d4680865e40a88f975a1cee6abc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 20 Aug 2019 11:54:49 +0200 Subject: [PATCH 3809/7155] mac80211: minstrel_ht: improve rate probing for devices with static fallback On some devices that only support static rate fallback tables sending rate control probing packets can be really expensive. Probing lower rates can already hurt throughput quite a bit. What hurts even more is the fact that on mt76x0/mt76x2, single probing packets can only be forced by directing packets at a different internal hardware queue, which causes some heavy reordering and extra latency. The reordering issue is mainly problematic while pushing lots of packets to a particular station. If there is little activity, the overhead of probing is neglegible. The static fallback behavior is designed to pretty much only handle rate control algorithms that use only a very limited set of rates on which the algorithm switches up/down based on packet error rate. In order to better support that kind of hardware, this patch implements a different approach to rate probing where it switches to a slightly higher rate, waits for tx status feedback, then updates the stats and switches back to the new max throughput rate. This only triggers above a packet rate of 100 per stats interval (~50ms). For that kind of probing, the code has to reduce the set of probing rates a lot more compared to single packet probing, so it uses only one packet per MCS group which is either slightly faster, or as close as possible to the max throughput rate. This allows switching between similar rates with different numbers of streams. The algorithm assumes that the hardware will work its way lower within an MCS group in case of retransmissions, so that lower rates don't have to be probed by the high packets per second rate probing code. To further reduce the search space, it also does not probe rates with lower channel bandwidth than the max throughput rate. At the moment, these changes will only affect mt76x0/mt76x2. Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20190820095449.45255-4-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.h | 1 + net/mac80211/rc80211_minstrel_ht.c | 240 +++++++++++++++++++++++++---- net/mac80211/rc80211_minstrel_ht.h | 12 ++ 3 files changed, 225 insertions(+), 28 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 3c96a853adbd..51d8b2c846e7 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -95,6 +95,7 @@ struct minstrel_sta_info { struct minstrel_priv { struct ieee80211_hw *hw; bool has_mrr; + u32 sample_switch; unsigned int cw_min; unsigned int cw_max; unsigned int max_retry; diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c5868a1de306..a01168514840 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -18,6 +18,8 @@ #define AVG_AMPDU_SIZE 16 #define AVG_PKT_SIZE 1200 +#define SAMPLE_SWITCH_THR 100 + /* Number of bits for an average sized packet */ #define MCS_NBITS ((AVG_PKT_SIZE * AVG_AMPDU_SIZE) << 3) @@ -58,6 +60,7 @@ [GROUP_IDX(_streams, _sgi, _ht40)] = { \ .streams = _streams, \ .shift = _s, \ + .bw = _ht40, \ .flags = \ IEEE80211_TX_RC_MCS | \ (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ @@ -94,6 +97,7 @@ [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ .streams = _streams, \ .shift = _s, \ + .bw = _bw, \ .flags = \ IEEE80211_TX_RC_VHT_MCS | \ (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ @@ -526,6 +530,133 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) } } +static inline int +minstrel_get_duration(int index) +{ + const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; + unsigned int duration = group->duration[index % MCS_GROUP_RATES]; + return duration << group->shift; +} + +static bool +minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group, + int tp_idx, const struct mcs_group *group) +{ + if (group->bw < tp_group->bw) + return false; + + if (group->streams == tp_group->streams) + return true; + + if (tp_idx < 4 && group->streams == tp_group->streams - 1) + return true; + + return group->streams == tp_group->streams + 1; +} + +static void +minstrel_ht_find_probe_rates(struct minstrel_ht_sta *mi, u16 *rates, int *n_rates, + bool faster_rate) +{ + const struct mcs_group *group, *tp_group; + int i, g, max_dur; + int tp_idx; + + tp_group = &minstrel_mcs_groups[mi->max_tp_rate[0] / MCS_GROUP_RATES]; + tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; + + max_dur = minstrel_get_duration(mi->max_tp_rate[0]); + if (faster_rate) + max_dur -= max_dur / 16; + + for (g = 0; g < MINSTREL_GROUPS_NB; g++) { + u16 supported = mi->supported[g]; + + if (!supported) + continue; + + group = &minstrel_mcs_groups[g]; + if (!minstrel_ht_probe_group(mi, tp_group, tp_idx, group)) + continue; + + for (i = 0; supported; supported >>= 1, i++) { + int idx; + + if (!(supported & 1)) + continue; + + if ((group->duration[i] << group->shift) > max_dur) + continue; + + idx = g * MCS_GROUP_RATES + i; + if (idx == mi->max_tp_rate[0]) + continue; + + rates[(*n_rates)++] = idx; + break; + } + } +} + +static void +minstrel_ht_rate_sample_switch(struct minstrel_priv *mp, + struct minstrel_ht_sta *mi) +{ + struct minstrel_rate_stats *mrs; + u16 rates[MINSTREL_GROUPS_NB]; + int n_rates = 0; + int probe_rate = 0; + bool faster_rate; + int i; + u8 random; + + /* + * Use rate switching instead of probing packets for devices with + * little control over retry fallback behavior + */ + if (mp->hw->max_rates > 1) + return; + + /* + * If the current EWMA prob is >75%, look for a rate that's 6.25% + * faster than the max tp rate. + * If that fails, look again for a rate that is at least as fast + */ + mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); + faster_rate = mrs->prob_ewma > MINSTREL_FRAC(75, 100); + minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate); + if (!n_rates && faster_rate) + minstrel_ht_find_probe_rates(mi, rates, &n_rates, false); + + /* If no suitable rate was found, try to pick the next one in the group */ + if (!n_rates) { + int g_idx = mi->max_tp_rate[0] / MCS_GROUP_RATES; + u16 supported = mi->supported[g_idx]; + + supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES; + for (i = 0; supported; i++) { + if (!(supported & 1)) + continue; + + probe_rate = mi->max_tp_rate[0] + i; + goto out; + } + + return; + } + + i = 0; + if (n_rates > 1) { + random = prandom_u32(); + i = random % n_rates; + } + probe_rate = rates[i]; + +out: + mi->sample_rate = probe_rate; + mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; +} + /* * Update rate statistics and select new primary rates * @@ -536,7 +667,8 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) * higher throughput rates, even if the probablity is a bit lower */ static void -minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) +minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, + bool sample) { struct minstrel_mcs_group_data *mg; struct minstrel_rate_stats *mrs; @@ -544,6 +676,18 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; u16 tmp_cck_tp_rate[MAX_THR_RATES], index; + mi->sample_mode = MINSTREL_SAMPLE_IDLE; + + if (sample) { + mi->total_packets_cur = mi->total_packets - + mi->total_packets_last; + mi->total_packets_last = mi->total_packets; + } + if (!mp->sample_switch) + sample = false; + if (mi->total_packets_cur < SAMPLE_SWITCH_THR && mp->sample_switch != 1) + sample = false; + if (mi->ampdu_packets > 0) { if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN)) mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, @@ -630,12 +774,16 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) /* try to sample all available rates during each interval */ mi->sample_count *= 8; + if (sample) + minstrel_ht_rate_sample_switch(mp, mi); + #ifdef CONFIG_MAC80211_DEBUGFS /* use fixed index if set */ if (mp->fixed_rate_idx != -1) { for (i = 0; i < 4; i++) mi->max_tp_rate[i] = mp->fixed_rate_idx; mi->max_prob_rate = mp->fixed_rate_idx; + mi->sample_mode = MINSTREL_SAMPLE_IDLE; } #endif @@ -739,15 +887,17 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, struct minstrel_ht_sta_priv *msp = priv_sta; struct minstrel_ht_sta *mi = &msp->ht; struct ieee80211_tx_rate *ar = info->status.rates; - struct minstrel_rate_stats *rate, *rate2; + struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; struct minstrel_priv *mp = priv; bool last, update = false; + bool sample_status = false; int i; if (!msp->is_ht) return mac80211_minstrel.tx_status_ext(priv, sband, &msp->legacy, st); + /* This packet was aggregated but doesn't carry status info */ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && !(info->flags & IEEE80211_TX_STAT_AMPDU)) @@ -773,12 +923,17 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) mi->sample_packets += info->status.ampdu_len; + if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) + rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); + last = !minstrel_ht_txstat_valid(mp, &ar[0]); for (i = 0; !last; i++) { last = (i == IEEE80211_TX_MAX_RATES - 1) || !minstrel_ht_txstat_valid(mp, &ar[i + 1]); rate = minstrel_ht_get_stats(mp, mi, &ar[i]); + if (rate == rate_sample) + sample_status = true; if (last) rate->success += info->status.ampdu_ack_len; @@ -786,44 +941,60 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, rate->attempts += ar[i].count * info->status.ampdu_len; } - /* - * check for sudden death of spatial multiplexing, - * downgrade to a lower number of streams if necessary. - */ - rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); - if (rate->attempts > 30 && - MINSTREL_FRAC(rate->success, rate->attempts) < - MINSTREL_FRAC(20, 100)) { - minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); + switch (mi->sample_mode) { + case MINSTREL_SAMPLE_IDLE: + break; + + case MINSTREL_SAMPLE_ACTIVE: + if (!sample_status) + break; + + mi->sample_mode = MINSTREL_SAMPLE_PENDING; update = true; - } + break; + + case MINSTREL_SAMPLE_PENDING: + if (sample_status) + break; - rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); - if (rate2->attempts > 30 && - MINSTREL_FRAC(rate2->success, rate2->attempts) < - MINSTREL_FRAC(20, 100)) { - minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); update = true; + minstrel_ht_update_stats(mp, mi, false); + break; + } + + + if (mp->hw->max_rates > 1) { + /* + * check for sudden death of spatial multiplexing, + * downgrade to a lower number of streams if necessary. + */ + rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); + if (rate->attempts > 30 && + MINSTREL_FRAC(rate->success, rate->attempts) < + MINSTREL_FRAC(20, 100)) { + minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); + update = true; + } + + rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); + if (rate2->attempts > 30 && + MINSTREL_FRAC(rate2->success, rate2->attempts) < + MINSTREL_FRAC(20, 100)) { + minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); + update = true; + } } if (time_after(jiffies, mi->last_stats_update + (mp->update_interval / 2 * HZ) / 1000)) { update = true; - minstrel_ht_update_stats(mp, mi); + minstrel_ht_update_stats(mp, mi, true); } if (update) minstrel_ht_update_rates(mp, mi); } -static inline int -minstrel_get_duration(int index) -{ - const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; - unsigned int duration = group->duration[index % MCS_GROUP_RATES]; - return duration << group->shift; -} - static void minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, int index) @@ -988,14 +1159,18 @@ static void minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) { struct ieee80211_sta_rates *rates; + u16 first_rate = mi->max_tp_rate[0]; int i = 0; + if (mi->sample_mode == MINSTREL_SAMPLE_ACTIVE) + first_rate = mi->sample_rate; + rates = kzalloc(sizeof(*rates), GFP_ATOMIC); if (!rates) return; /* Start with max_tp_rate[0] */ - minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]); + minstrel_ht_set_rate(mp, mi, rates, i++, first_rate); if (mp->hw->max_rates >= 3) { /* At least 3 tx rates supported, use max_tp_rate[1] next */ @@ -1020,6 +1195,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) int tp_rate1, tp_rate2; int sample_idx = 0; + if (mp->hw->max_rates == 1 && mp->sample_switch && + (mi->total_packets_cur >= SAMPLE_SWITCH_THR || + mp->sample_switch == 1)) + return -1; + if (mi->sample_wait > 0) { mi->sample_wait--; return -1; @@ -1341,7 +1521,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4; /* create an initial rate table with the lowest supported rates */ - minstrel_ht_update_stats(mp, mi); + minstrel_ht_update_stats(mp, mi, true); minstrel_ht_update_rates(mp, mi); return; @@ -1459,6 +1639,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) if (!mp) return NULL; + mp->sample_switch = -1; + /* contention window settings * Just an approximation. Using the per-queue values would complicate * the calculations and is probably unnecessary */ @@ -1490,6 +1672,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) mp->fixed_rate_idx = (u32) -1; debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx); + debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir, + &mp->sample_switch); #endif minstrel_ht_init_cck_rates(mp); diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index 80296268c778..f938701e7ab7 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h @@ -33,6 +33,7 @@ struct mcs_group { u16 flags; u8 streams; u8 shift; + u8 bw; u16 duration[MCS_GROUP_RATES]; }; @@ -50,6 +51,12 @@ struct minstrel_mcs_group_data { struct minstrel_rate_stats rates[MCS_GROUP_RATES]; }; +enum minstrel_sample_mode { + MINSTREL_SAMPLE_IDLE, + MINSTREL_SAMPLE_ACTIVE, + MINSTREL_SAMPLE_PENDING, +}; + struct minstrel_ht_sta { struct ieee80211_sta *sta; @@ -71,6 +78,8 @@ struct minstrel_ht_sta { unsigned int overhead; unsigned int overhead_rtscts; + unsigned int total_packets_last; + unsigned int total_packets_cur; unsigned int total_packets; unsigned int sample_packets; @@ -82,6 +91,9 @@ struct minstrel_ht_sta { u8 sample_count; u8 sample_slow; + enum minstrel_sample_mode sample_mode; + u16 sample_rate; + /* current MCS group to be sampled */ u8 sample_group; -- GitLab From e9670ccb39dbcfc934ae9533163e81a769d2cb82 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Jun 2019 09:37:19 +0200 Subject: [PATCH 3810/7155] ARM: debug-ll: Add support for r7s9210 Enable low-level debugging support for RZ/A2M (r7s9210). The RZA2MEVB board uses either SCIF2 (SDRAM enabled) or SCIF4 (HyperRAM only) for the serial console. Note that "SCIFA" serial ports on RZ/A2 SoCs use a compressed register layout, hence add support for that to renesas-scif.S. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman --- arch/arm/Kconfig.debug | 20 +++++++++++++++++++- arch/arm/include/debug/renesas-scif.S | 6 +++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index c929bea9a9ff..c029961d3795 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -924,6 +924,20 @@ choice Say Y here if you want kernel low-level debugging support via SCIF2 on Renesas RZ/A1H (R7S72100). + config DEBUG_R7S9210_SCIF2 + bool "Kernel low-level debugging messages via SCIF2 on R7S9210" + depends on ARCH_R7S9210 + help + Say Y here if you want kernel low-level debugging support + via SCIF2 on Renesas RZ/A2M (R7S9210). + + config DEBUG_R7S9210_SCIF4 + bool "Kernel low-level debugging messages via SCIF4 on R7S9210" + depends on ARCH_R7S9210 + help + Say Y here if you want kernel low-level debugging support + via SCIF4 on Renesas RZ/A2M (R7S9210). + config DEBUG_RCAR_GEN1_SCIF0 bool "Kernel low-level debugging messages via SCIF0 on R8A7778" depends on ARCH_R8A7778 @@ -1538,6 +1552,8 @@ config DEBUG_LL_INCLUDE default "debug/netx.S" if DEBUG_NETX_UART default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2 + default "debug/renesas-scif.S" if DEBUG_R7S9210_SCIF2 + default "debug/renesas-scif.S" if DEBUG_R7S9210_SCIF4 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0 @@ -1668,7 +1684,8 @@ config DEBUG_UART_PHYS default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0 default 0xe6e68000 if DEBUG_RCAR_GEN2_SCIF1 default 0xe6ee0000 if DEBUG_RCAR_GEN2_SCIF4 - default 0xe8008000 if DEBUG_R7S72100_SCIF2 + default 0xe8008000 if DEBUG_R7S72100_SCIF2 || DEBUG_R7S9210_SCIF2 + default 0xe8009000 if DEBUG_R7S9210_SCIF4 default 0xf0000000 if DEBUG_DIGICOLOR_UA0 default 0xf0000be0 if ARCH_EBSA110 default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE @@ -1702,6 +1719,7 @@ config DEBUG_UART_PHYS DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \ DEBUG_NETX_UART || \ DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \ + DEBUG_R7S9210_SCIF2 || DEBUG_R7S9210_SCIF4 || \ DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \ DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \ DEBUG_RCAR_GEN2_SCIF2 || DEBUG_RCAR_GEN2_SCIF4 || \ diff --git a/arch/arm/include/debug/renesas-scif.S b/arch/arm/include/debug/renesas-scif.S index 1c5f795587fc..25f06663a9a4 100644 --- a/arch/arm/include/debug/renesas-scif.S +++ b/arch/arm/include/debug/renesas-scif.S @@ -11,7 +11,11 @@ #define SCIF_PHYS CONFIG_DEBUG_UART_PHYS #define SCIF_VIRT ((SCIF_PHYS & 0x00ffffff) | 0xfd000000) -#if CONFIG_DEBUG_UART_PHYS < 0xe6e00000 +#if defined(CONFIG_DEBUG_R7S9210_SCIF2) || defined(CONFIG_DEBUG_R7S9210_SCIF4) +/* RZ/A2 SCIFA */ +#define FTDR 0x06 +#define FSR 0x08 +#elif CONFIG_DEBUG_UART_PHYS < 0xe6e00000 /* SCIFA */ #define FTDR 0x20 #define FSR 0x14 -- GitLab From ca084e178bb42d7433b8d463e90b75786463b806 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 28 Jul 2019 13:36:24 +0200 Subject: [PATCH 3811/7155] ARM: dts: ux500: Drop TV-out muxgroup on HREFs The reference designs are not using TV-out so let's drop that mux group from this file. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-href-family-pinctrl.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi index 86621196abda..2c382d274ff6 100644 --- a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi +++ b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi @@ -607,7 +607,6 @@ groups = "lcdvsi0_a_1", /* VSI0 for LCD */ "lcd_d0_d7_a_1", /* Data lines */ - "lcd_d8_d11_a_1", /* TV-out */ "lcdvsi1_a_1"; /* VSI1 for HDMI */ }; default_mux2 { -- GitLab From 8c72e0c85212df4e7c77fca55556e423fe17e801 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 25 Jul 2019 09:21:47 +0200 Subject: [PATCH 3812/7155] Documentation/s390: remove outdated dasd documentation The contents of the file is completely outdated - just remove it. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- Documentation/s390/dasd.rst | 84 ------------------------------------ Documentation/s390/index.rst | 1 - 2 files changed, 85 deletions(-) delete mode 100644 Documentation/s390/dasd.rst diff --git a/Documentation/s390/dasd.rst b/Documentation/s390/dasd.rst deleted file mode 100644 index 9e22247285c8..000000000000 --- a/Documentation/s390/dasd.rst +++ /dev/null @@ -1,84 +0,0 @@ -================== -DASD device driver -================== - -S/390's disk devices (DASDs) are managed by Linux via the DASD device -driver. It is valid for all types of DASDs and represents them to -Linux as block devices, namely "dd". Currently the DASD driver uses a -single major number (254) and 4 minor numbers per volume (1 for the -physical volume and 3 for partitions). With respect to partitions see -below. Thus you may have up to 64 DASD devices in your system. - -The kernel parameter 'dasd=from-to,...' may be issued arbitrary times -in the kernel's parameter line or not at all. The 'from' and 'to' -parameters are to be given in hexadecimal notation without a leading -0x. -If you supply kernel parameters the different instances are processed -in order of appearance and a minor number is reserved for any device -covered by the supplied range up to 64 volumes. Additional DASDs are -ignored. If you do not supply the 'dasd=' kernel parameter at all, the -DASD driver registers all supported DASDs of your system to a minor -number in ascending order of the subchannel number. - -The driver currently supports ECKD-devices and there are stubs for -support of the FBA and CKD architectures. For the FBA architecture -only some smart data structures are missing to make the support -complete. -We performed our testing on 3380 and 3390 type disks of different -sizes, under VM and on the bare hardware (LPAR), using internal disks -of the multiprise as well as a RAMAC virtual array. Disks exported by -an Enterprise Storage Server (Seascape) should work fine as well. - -We currently implement one partition per volume, which is the whole -volume, skipping the first blocks up to the volume label. These are -reserved for IPL records and IBM's volume label to assure -accessibility of the DASD from other OSs. In a later stage we will -provide support of partitions, maybe VTOC oriented or using a kind of -partition table in the label record. - -Usage -===== - --Low-level format (?CKD only) -For using an ECKD-DASD as a Linux harddisk you have to low-level -format the tracks by issuing the BLKDASDFORMAT-ioctl on that -device. This will erase any data on that volume including IBM volume -labels, VTOCs etc. The ioctl may take a `struct format_data *` or -'NULL' as an argument:: - - typedef struct { - int start_unit; - int stop_unit; - int blksize; - } format_data_t; - -When a NULL argument is passed to the BLKDASDFORMAT ioctl the whole -disk is formatted to a blocksize of 1024 bytes. Otherwise start_unit -and stop_unit are the first and last track to be formatted. If -stop_unit is -1 it implies that the DASD is formatted from start_unit -up to the last track. blksize can be any power of two between 512 and -4096. We recommend no blksize lower than 1024 because the ext2fs uses -1kB blocks anyway and you gain approx. 50% of capacity increasing your -blksize from 512 byte to 1kB. - -Make a filesystem -================= - -Then you can mk??fs the filesystem of your choice on that volume or -partition. For reasons of sanity you should build your filesystem on -the partition /dev/dd?1 instead of the whole volume. You only lose 3kB -but may be sure that you can reuse your data after introduction of a -real partition table. - -Bugs -==== - -- Performance sometimes is rather low because we don't fully exploit clustering - -TODO-List -========= - -- Add IBM'S Disk layout to genhd -- Enhance driver to use more than one major number -- Enable usage as a module -- Support Cache fast write and DASD fast write (ECKD) diff --git a/Documentation/s390/index.rst b/Documentation/s390/index.rst index 4602312909d3..f8c01cb7fa37 100644 --- a/Documentation/s390/index.rst +++ b/Documentation/s390/index.rst @@ -15,7 +15,6 @@ s390 Architecture vfio-ap vfio-ccw zfcpdump - dasd common_io text_files -- GitLab From f62f7dcbf023160ca47eb4bc7228ece8207f8a8e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 25 Jul 2019 09:23:39 +0200 Subject: [PATCH 3813/7155] Documentation/s390: remove outdated debugging390 documentation This file would need a lot of work to make sense again. Thomas Huth started working on that four years ago, but that wasn't finished. Therefore remove this. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- Documentation/s390/debugging390.rst | 2613 --------------------------- Documentation/s390/index.rst | 1 - 2 files changed, 2614 deletions(-) delete mode 100644 Documentation/s390/debugging390.rst diff --git a/Documentation/s390/debugging390.rst b/Documentation/s390/debugging390.rst deleted file mode 100644 index 73ad0b06c666..000000000000 --- a/Documentation/s390/debugging390.rst +++ /dev/null @@ -1,2613 +0,0 @@ -============================================= -Debugging on Linux for s/390 & z/Architecture -============================================= - -Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) - -Copyright (C) 2000-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation - -.. Best viewed with fixed width fonts - -Overview of Document: -===================== -This document is intended to give a good overview of how to debug Linux for -s/390 and z/Architecture. It is not intended as a complete reference and not a -tutorial on the fundamentals of C & assembly. It doesn't go into -390 IO in any detail. It is intended to complement the documents in the -reference section below & any other worthwhile references you get. - -It is intended like the Enterprise Systems Architecture/390 Reference Summary -to be printed out & used as a quick cheat sheet self help style reference when -problems occur. - -.. Contents - ======== - Register Set - Address Spaces on Intel Linux - Address Spaces on Linux for s/390 & z/Architecture - The Linux for s/390 & z/Architecture Kernel Task Structure - Register Usage & Stackframes on Linux for s/390 & z/Architecture - A sample program with comments - Compiling programs for debugging on Linux for s/390 & z/Architecture - Debugging under VM - s/390 & z/Architecture IO Overview - Debugging IO on s/390 & z/Architecture under VM - GDB on s/390 & z/Architecture - Stack chaining in gdb by hand - Examining core dumps - ldd - Debugging modules - The proc file system - SysRq - References - Special Thanks - -Register Set -============ -The current architectures have the following registers. - -16 General propose registers, 32 bit on s/390 and 64 bit on z/Architecture, -r0-r15 (or gpr0-gpr15), used for arithmetic and addressing. - -16 Control registers, 32 bit on s/390 and 64 bit on z/Architecture, cr0-cr15, -kernel usage only, used for memory management, interrupt control, debugging -control etc. - -16 Access registers (ar0-ar15), 32 bit on both s/390 and z/Architecture, -normally not used by normal programs but potentially could be used as -temporary storage. These registers have a 1:1 association with general -purpose registers and are designed to be used in the so-called access -register mode to select different address spaces. -Access register 0 (and access register 1 on z/Architecture, which needs a -64 bit pointer) is currently used by the pthread library as a pointer to -the current running threads private area. - -16 64-bit floating point registers (fp0-fp15 ) IEEE & HFP floating -point format compliant on G5 upwards & a Floating point control reg (FPC) - -4 64-bit registers (fp0,fp2,fp4 & fp6) HFP only on older machines. - -Note: - Linux (currently) always uses IEEE & emulates G5 IEEE format on older - machines, ( provided the kernel is configured for this ). - - -The PSW is the most important register on the machine it -is 64 bit on s/390 & 128 bit on z/Architecture & serves the roles of -a program counter (pc), condition code register,memory space designator. -In IBM standard notation I am counting bit 0 as the MSB. -It has several advantages over a normal program counter -in that you can change address translation & program counter -in a single instruction. To change address translation, -e.g. switching address translation off requires that you -have a logical=physical mapping for the address you are -currently running at. - -+-------------------------+-------------------------------------------------+ -| Bit | | -+--------+----------------+ Value | -| s/390 | z/Architecture | | -+========+================+=================================================+ -| 0 | 0 | Reserved (must be 0) otherwise specification | -| | | exception occurs. | -+--------+----------------+-------------------------------------------------+ -| 1 | 1 | Program Event Recording 1 PER enabled, | -| | | PER is used to facilitate debugging e.g. | -| | | single stepping. | -+--------+----------------+-------------------------------------------------+ -| 2-4 | 2-4 | Reserved (must be 0). | -+--------+----------------+-------------------------------------------------+ -| 5 | 5 | Dynamic address translation 1=DAT on. | -+--------+----------------+-------------------------------------------------+ -| 6 | 6 | Input/Output interrupt Mask | -+--------+----------------+-------------------------------------------------+ -| 7 | 7 | External interrupt Mask used primarily for | -| | | interprocessor signalling and clock interrupts. | -+--------+----------------+-------------------------------------------------+ -| 8-11 | 8-11 | PSW Key used for complex memory protection | -| | | mechanism (not used under linux) | -+--------+----------------+-------------------------------------------------+ -| 12 | 12 | 1 on s/390 0 on z/Architecture | -+--------+----------------+-------------------------------------------------+ -| 13 | 13 | Machine Check Mask 1=enable machine check | -| | | interrupts | -+--------+----------------+-------------------------------------------------+ -| 14 | 14 | Wait State. Set this to 1 to stop the processor | -| | | except for interrupts and give time to other | -| | | LPARS. Used in CPU idle in the kernel to | -| | | increase overall usage of processor resources. | -+--------+----------------+-------------------------------------------------+ -| 15 | 15 | Problem state (if set to 1 certain instructions | -| | | are disabled). All linux user programs run with | -| | | this bit 1 (useful info for debugging under VM).| -+--------+----------------+-------------------------------------------------+ -| 16-17 | 16-17 | Address Space Control | -| | | | -| | | 00 Primary Space Mode: | -| | | | -| | | The register CR1 contains the primary | -| | | address-space control element (PASCE), which | -| | | points to the primary space region/segment | -| | | table origin. | -| | | | -| | | 01 Access register mode | -| | | | -| | | 10 Secondary Space Mode: | -| | | | -| | | The register CR7 contains the secondary | -| | | address-space control element (SASCE), which | -| | | points to the secondary space region or | -| | | segment table origin. | -| | | | -| | | 11 Home Space Mode: | -| | | | -| | | The register CR13 contains the home space | -| | | address-space control element (HASCE), which | -| | | points to the home space region/segment | -| | | table origin. | -| | | | -| | | See "Address Spaces on Linux for s/390 & | -| | | z/Architecture" below for more information | -| | | about address space usage in Linux. | -+--------+----------------+-------------------------------------------------+ -| 18-19 | 18-19 | Condition codes (CC) | -+--------+----------------+-------------------------------------------------+ -| 20 | 20 | Fixed point overflow mask if 1=FPU exceptions | -| | | for this event occur (normally 0) | -+--------+----------------+-------------------------------------------------+ -| 21 | 21 | Decimal overflow mask if 1=FPU exceptions for | -| | | this event occur (normally 0) | -+--------+----------------+-------------------------------------------------+ -| 22 | 22 | Exponent underflow mask if 1=FPU exceptions | -| | | for this event occur (normally 0) | -+--------+----------------+-------------------------------------------------+ -| 23 | 23 | Significance Mask if 1=FPU exceptions for this | -| | | event occur (normally 0) | -+--------+----------------+-------------------------------------------------+ -| 24-31 | 24-30 | Reserved Must be 0. | -| +----------------+-------------------------------------------------+ -| | 31 | Extended Addressing Mode | -| +----------------+-------------------------------------------------+ -| | 32 | Basic Addressing Mode | -| | | | -| | | Used to set addressing mode:: | -| | | | -| | | +---------+----------+----------+ | -| | | | PSW 31 | PSW 32 | | | -| | | +---------+----------+----------+ | -| | | | 0 | 0 | 24 bit | | -| | | +---------+----------+----------+ | -| | | | 0 | 1 | 31 bit | | -| | | +---------+----------+----------+ | -| | | | 1 | 1 | 64 bit | | -| | | +---------+----------+----------+ | -+--------+----------------+-------------------------------------------------+ -| 32 | | 1=31 bit addressing mode 0=24 bit addressing | -| | | mode (for backward compatibility), linux | -| | | always runs with this bit set to 1 | -+--------+----------------+-------------------------------------------------+ -| 33-64 | | Instruction address. | -| +----------------+-------------------------------------------------+ -| | 33-63 | Reserved must be 0 | -| +----------------+-------------------------------------------------+ -| | 64-127 | Address | -| | | | -| | | - In 24 bits mode bits 64-103=0 bits 104-127 | -| | | Address | -| | | - In 31 bits mode bits 64-96=0 bits 97-127 | -| | | Address | -| | | | -| | | Note: | -| | | unlike 31 bit mode on s/390 bit 96 must be | -| | | zero when loading the address with LPSWE | -| | | otherwise a specification exception occurs, | -| | | LPSW is fully backward compatible. | -+--------+----------------+-------------------------------------------------+ - -Prefix Page(s) --------------- -This per cpu memory area is too intimately tied to the processor not to mention. -It exists between the real addresses 0-4096 on s/390 and between 0-8192 on -z/Architecture and is exchanged with one page on s/390 or two pages on -z/Architecture in absolute storage by the set prefix instruction during Linux -startup. - -This page is mapped to a different prefix for each processor in an SMP -configuration (assuming the OS designer is sane of course). - -Bytes 0-512 (200 hex) on s/390 and 0-512, 4096-4544, 4604-5119 currently on -z/Architecture are used by the processor itself for holding such information -as exception indications and entry points for exceptions. - -Bytes after 0xc00 hex are used by linux for per processor globals on s/390 and -z/Architecture (there is a gap on z/Architecture currently between 0xc00 and -0x1000, too, which is used by Linux). - -The closest thing to this on traditional architectures is the interrupt -vector table. This is a good thing & does simplify some of the kernel coding -however it means that we now cannot catch stray NULL pointers in the -kernel without hard coded checks. - - - -Address Spaces on Intel Linux -============================= - -The traditional Intel Linux is approximately mapped as follows forgive -the ascii art:: - - 0xFFFFFFFF 4GB Himem ***************** - * * - * Kernel Space * - * * - ***************** **************** - User Space Himem * User Stack * * * - (typically 0xC0000000 3GB ) ***************** * * - * Shared Libs * * Next Process * - ***************** * to * - * * <== * Run * <== - * User Program * * * - * Data BSS * * * - * Text * * * - * Sections * * * - 0x00000000 ***************** **************** - -Now it is easy to see that on Intel it is quite easy to recognise a kernel -address as being one greater than user space himem (in this case 0xC0000000), -and addresses of less than this are the ones in the current running program on -this processor (if an smp box). - -If using the virtual machine ( VM ) as a debugger it is quite difficult to -know which user process is running as the address space you are looking at -could be from any process in the run queue. - -The limitation of Intels addressing technique is that the linux -kernel uses a very simple real address to virtual addressing technique -of Real Address=Virtual Address-User Space Himem. -This means that on Intel the kernel linux can typically only address -Himem=0xFFFFFFFF-0xC0000000=1GB & this is all the RAM these machines -can typically use. - -They can lower User Himem to 2GB or lower & thus be -able to use 2GB of RAM however this shrinks the maximum size -of User Space from 3GB to 2GB they have a no win limit of 4GB unless -they go to 64 Bit. - - -On 390 our limitations & strengths make us slightly different. -For backward compatibility we are only allowed use 31 bits (2GB) -of our 32 bit addresses, however, we use entirely separate address -spaces for the user & kernel. - -This means we can support 2GB of non Extended RAM on s/390, & more -with the Extended memory management swap device & -currently 4TB of physical memory currently on z/Architecture. - - -Address Spaces on Linux for s/390 & z/Architecture -================================================== - -Our addressing scheme is basically as follows:: - - Primary Space Home Space - Himem 0x7fffffff 2GB on s/390 ***************** **************** - currently 0x3ffffffffff (2^42)-1 * User Stack * * * - on z/Architecture. ***************** * * - * Shared Libs * * * - ***************** * * - * * * Kernel * - * User Program * * * - * Data BSS * * * - * Text * * * - * Sections * * * - 0x00000000 ***************** **************** - -This also means that we need to look at the PSW problem state bit and the -addressing mode to decide whether we are looking at user or kernel space. - -User space runs in primary address mode (or access register mode within -the vdso code). - -The kernel usually also runs in home space mode, however when accessing -user space the kernel switches to primary or secondary address mode if -the mvcos instruction is not available or if a compare-and-swap (futex) -instruction on a user space address is performed. - -When also looking at the ASCE control registers, this means: - -User space: - -- runs in primary or access register mode -- cr1 contains the user asce -- cr7 contains the user asce -- cr13 contains the kernel asce - -Kernel space: - -- runs in home space mode -- cr1 contains the user or kernel asce - - - the kernel asce is loaded when a uaccess requires primary or - secondary address mode - -- cr7 contains the user or kernel asce, (changed with set_fs()) -- cr13 contains the kernel asce - -In case of uaccess the kernel changes to: - -- primary space mode in case of a uaccess (copy_to_user) and uses - e.g. the mvcp instruction to access user space. However the kernel - will stay in home space mode if the mvcos instruction is available -- secondary space mode in case of futex atomic operations, so that the - instructions come from primary address space and data from secondary - space - -In case of KVM, the kernel runs in home space mode, but cr1 gets switched -to contain the gmap asce before the SIE instruction gets executed. When -the SIE instruction is finished, cr1 will be switched back to contain the -user asce. - - -Virtual Addresses on s/390 & z/Architecture -=========================================== - -A virtual address on s/390 is made up of 3 parts -The SX (segment index, roughly corresponding to the PGD & PMD in Linux -terminology) being bits 1-11. - -The PX (page index, corresponding to the page table entry (pte) in Linux -terminology) being bits 12-19. - -The remaining bits BX (the byte index are the offset in the page ) -i.e. bits 20 to 31. - -On z/Architecture in linux we currently make up an address from 4 parts. - -- The region index bits (RX) 0-32 we currently use bits 22-32 -- The segment index (SX) being bits 33-43 -- The page index (PX) being bits 44-51 -- The byte index (BX) being bits 52-63 - -Notes: - 1) s/390 has no PMD so the PMD is really the PGD also. - A lot of this stuff is defined in pgtable.h. - - 2) Also seeing as s/390's page indexes are only 1k in size - (bits 12-19 x 4 bytes per pte ) we use 1 ( page 4k ) - to make the best use of memory by updating 4 segment indices - entries each time we mess with a PMD & use offsets - 0,1024,2048 & 3072 in this page as for our segment indexes. - On z/Architecture our page indexes are now 2k in size - ( bits 12-19 x 8 bytes per pte ) we do a similar trick - but only mess with 2 segment indices each time we mess with - a PMD. - - 3) As z/Architecture supports up to a massive 5-level page table lookup we - can only use 3 currently on Linux ( as this is all the generic kernel - currently supports ) however this may change in future - this allows us to access ( according to my sums ) - 4TB of virtual storage per process i.e. - 4096*512(PTES)*1024(PMDS)*2048(PGD) = 4398046511104 bytes, - enough for another 2 or 3 of years I think :-). - to do this we use a region-third-table designation type in - our address space control registers. - - -The Linux for s/390 & z/Architecture Kernel Task Structure -========================================================== -Each process/thread under Linux for S390 has its own kernel task_struct -defined in linux/include/linux/sched.h -The S390 on initialisation & resuming of a process on a cpu sets -the __LC_KERNEL_STACK variable in the spare prefix area for this cpu -(which we use for per-processor globals). - -The kernel stack pointer is intimately tied with the task structure for -each processor as follows:: - - s/390 - ************************ - * 1 page kernel stack * - * ( 4K ) * - ************************ - * 1 page task_struct * - * ( 4K ) * - 8K aligned ************************ - - z/Architecture - ************************ - * 2 page kernel stack * - * ( 8K ) * - ************************ - * 2 page task_struct * - * ( 8K ) * - 16K aligned ************************ - -What this means is that we don't need to dedicate any register or global -variable to point to the current running process & can retrieve it with the -following very simple construct for s/390 & one very similar for -z/Architecture:: - - static inline struct task_struct * get_current(void) - { - struct task_struct *current; - __asm__("lhi %0,-8192\n\t" - "nr %0,15" - : "=r" (current) ); - return current; - } - -i.e. just anding the current kernel stack pointer with the mask -8192. -Thankfully because Linux doesn't have support for nested IO interrupts -& our devices have large buffers can survive interrupts being shut for -short amounts of time we don't need a separate stack for interrupts. - - - - -Register Usage & Stackframes on Linux for s/390 & z/Architecture -================================================================= -Overview: ---------- -This is the code that gcc produces at the top & the bottom of -each function. It usually is fairly consistent & similar from -function to function & if you know its layout you can probably -make some headway in finding the ultimate cause of a problem -after a crash without a source level debugger. - -Note: To follow stackframes requires a knowledge of C or Pascal & -limited knowledge of one assembly language. - -It should be noted that there are some differences between the -s/390 and z/Architecture stack layouts as the z/Architecture stack layout -didn't have to maintain compatibility with older linkage formats. - -Glossary: ---------- -alloca: - This is a built in compiler function for runtime allocation - of extra space on the callers stack which is obviously freed - up on function exit ( e.g. the caller may choose to allocate nothing - of a buffer of 4k if required for temporary purposes ), it generates - very efficient code ( a few cycles ) when compared to alternatives - like malloc. - -automatics: - These are local variables on the stack, i.e they aren't in registers & - they aren't static. - -back-chain: - This is a pointer to the stack pointer before entering a - framed functions ( see frameless function ) prologue got by - dereferencing the address of the current stack pointer, - i.e. got by accessing the 32 bit value at the stack pointers - current location. - -base-pointer: - This is a pointer to the back of the literal pool which - is an area just behind each procedure used to store constants - in each function. - -call-clobbered: - The caller probably needs to save these registers if there - is something of value in them, on the stack or elsewhere before making a - call to another procedure so that it can restore it later. - -epilogue: - The code generated by the compiler to return to the caller. - -frameless-function: - A frameless function in Linux for s390 & z/Architecture is one which doesn't - need more than the register save area (96 bytes on s/390, 160 on z/Architecture) - given to it by the caller. - - A frameless function never: - - 1) Sets up a back chain. - 2) Calls alloca. - 3) Calls other normal functions - 4) Has automatics. - -GOT-pointer: - This is a pointer to the global-offset-table in ELF - ( Executable Linkable Format, Linux'es most common executable format ), - all globals & shared library objects are found using this pointer. - -lazy-binding - ELF shared libraries are typically only loaded when routines in the shared - library are actually first called at runtime. This is lazy binding. - -procedure-linkage-table - This is a table found from the GOT which contains pointers to routines - in other shared libraries which can't be called to by easier means. - -prologue: - The code generated by the compiler to set up the stack frame. - -outgoing-args: - This is extra area allocated on the stack of the calling function if the - parameters for the callee's cannot all be put in registers, the same - area can be reused by each function the caller calls. - -routine-descriptor: - A COFF executable format based concept of a procedure reference - actually being 8 bytes or more as opposed to a simple pointer to the routine. - This is typically defined as follows: - - - Routine Descriptor offset 0=Pointer to Function - - Routine Descriptor offset 4=Pointer to Table of Contents - - The table of contents/TOC is roughly equivalent to a GOT pointer. - & it means that shared libraries etc. can be shared between several - environments each with their own TOC. - -static-chain: - This is used in nested functions a concept adopted from pascal - by gcc not used in ansi C or C++ ( although quite useful ), basically it - is a pointer used to reference local variables of enclosing functions. - You might come across this stuff once or twice in your lifetime. - - e.g. - - The function below should return 11 though gcc may get upset & toss warnings - about unused variables:: - - int FunctionA(int a) - { - int b; - FunctionC(int c) - { - b=c+1; - } - FunctionC(10); - return(b); - } - - -s/390 & z/Architecture Register usage -===================================== - -======== ========================================== =============== -r0 used by syscalls/assembly call-clobbered -r1 used by syscalls/assembly call-clobbered -r2 argument 0 / return value 0 call-clobbered -r3 argument 1 / return value 1 (if long long) call-clobbered -r4 argument 2 call-clobbered -r5 argument 3 call-clobbered -r6 argument 4 saved -r7 pointer-to arguments 5 to ... saved -r8 this & that saved -r9 this & that saved -r10 static-chain ( if nested function ) saved -r11 frame-pointer ( if function used alloca ) saved -r12 got-pointer saved -r13 base-pointer saved -r14 return-address saved -r15 stack-pointer saved - -f0 argument 0 / return value ( float/double ) call-clobbered -f2 argument 1 call-clobbered -f4 z/Architecture argument 2 saved -f6 z/Architecture argument 3 saved -======== ========================================== =============== - -The remaining floating points -f1,f3,f5 f7-f15 are call-clobbered. - -Notes: ------- -1) The only requirement is that registers which are used - by the callee are saved, e.g. the compiler is perfectly - capable of using r11 for purposes other than a frame a - frame pointer if a frame pointer is not needed. -2) In functions with variable arguments e.g. printf the calling procedure - is identical to one without variable arguments & the same number of - parameters. However, the prologue of this function is somewhat more - hairy owing to it having to move these parameters to the stack to - get va_start, va_arg & va_end to work. -3) Access registers are currently unused by gcc but are used in - the kernel. Possibilities exist to use them at the moment for - temporary storage but it isn't recommended. -4) Only 4 of the floating point registers are used for - parameter passing as older machines such as G3 only have only 4 - & it keeps the stack frame compatible with other compilers. - However with IEEE floating point emulation under linux on the - older machines you are free to use the other 12. -5) A long long or double parameter cannot be have the - first 4 bytes in a register & the second four bytes in the - outgoing args area. It must be purely in the outgoing args - area if crossing this boundary. -6) Floating point parameters are mixed with outgoing args - on the outgoing args area in the order the are passed in as parameters. -7) Floating point arguments 2 & 3 are saved in the outgoing args area for - z/Architecture - - -Stack Frame Layout ------------------- - -========= ============== ====================================================== -s/390 z/Architecture -========= ============== ====================================================== -0 0 back chain ( a 0 here signifies end of back chain ) -4 8 eos ( end of stack, not used on Linux for S390 used - in other linkage formats ) -8 16 glue used in other s/390 linkage formats for saved - routine descriptors etc. -12 24 glue used in other s/390 linkage formats for saved - routine descriptors etc. -16 32 scratch area -20 40 scratch area -24 48 saved r6 of caller function -28 56 saved r7 of caller function -32 64 saved r8 of caller function -36 72 saved r9 of caller function -40 80 saved r10 of caller function -44 88 saved r11 of caller function -48 96 saved r12 of caller function -52 104 saved r13 of caller function -56 112 saved r14 of caller function -60 120 saved r15 of caller function -64 128 saved f4 of caller function -72 132 saved f6 of caller function -80 undefined -96 160 outgoing args passed from caller to callee -96+x 160+x possible stack alignment ( 8 bytes desirable ) -96+x+y 160+x+y alloca space of caller ( if used ) -96+x+y+z 160+x+y+z automatics of caller ( if used ) -0 back-chain -========= ============== ====================================================== - -A sample program with comments. -=============================== - -Comments on the function test ------------------------------ -1) It didn't need to set up a pointer to the constant pool gpr13 as it is not - used ( :-( ). -2) This is a frameless function & no stack is bought. -3) The compiler was clever enough to recognise that it could return the - value in r2 as well as use it for the passed in parameter ( :-) ). -4) The basr ( branch relative & save ) trick works as follows the instruction - has a special case with r0,r0 with some instruction operands is understood as - the literal value 0, some risc architectures also do this ). So now - we are branching to the next address & the address new program counter is - in r13,so now we subtract the size of the function prologue we have executed - the size of the literal pool to get to the top of the literal pool:: - - - 0040037c int test(int b) - { # Function prologue below - 40037c: 90 de f0 34 stm %r13,%r14,52(%r15) # Save registers r13 & r14 - 400380: 0d d0 basr %r13,%r0 # Set up pointer to constant pool using - 400382: a7 da ff fa ahi %r13,-6 # basr trick - return(5+b); - # Huge main program - 400386: a7 2a 00 05 ahi %r2,5 # add 5 to r2 - - # Function epilogue below - 40038a: 98 de f0 34 lm %r13,%r14,52(%r15) # restore registers r13 & 14 - 40038e: 07 fe br %r14 # return - } - -Comments on the function main ------------------------------ -1) The compiler did this function optimally ( 8-) ):: - - Literal pool for main. - 400390: ff ff ff ec .long 0xffffffec - main(int argc,char *argv[]) - { # Function prologue below - 400394: 90 bf f0 2c stm %r11,%r15,44(%r15) # Save necessary registers - 400398: 18 0f lr %r0,%r15 # copy stack pointer to r0 - 40039a: a7 fa ff a0 ahi %r15,-96 # Make area for callee saving - 40039e: 0d d0 basr %r13,%r0 # Set up r13 to point to - 4003a0: a7 da ff f0 ahi %r13,-16 # literal pool - 4003a4: 50 00 f0 00 st %r0,0(%r15) # Save backchain - - return(test(5)); # Main Program Below - 4003a8: 58 e0 d0 00 l %r14,0(%r13) # load relative address of test from - # literal pool - 4003ac: a7 28 00 05 lhi %r2,5 # Set first parameter to 5 - 4003b0: 4d ee d0 00 bas %r14,0(%r14,%r13) # jump to test setting r14 as return - # address using branch & save instruction. - - # Function Epilogue below - 4003b4: 98 bf f0 8c lm %r11,%r15,140(%r15)# Restore necessary registers. - 4003b8: 07 fe br %r14 # return to do program exit - } - - -Compiler updates ----------------- - -:: - - main(int argc,char *argv[]) - { - 4004fc: 90 7f f0 1c stm %r7,%r15,28(%r15) - 400500: a7 d5 00 04 bras %r13,400508 - 400504: 00 40 04 f4 .long 0x004004f4 - # compiler now puts constant pool in code to so it saves an instruction - 400508: 18 0f lr %r0,%r15 - 40050a: a7 fa ff a0 ahi %r15,-96 - 40050e: 50 00 f0 00 st %r0,0(%r15) - return(test(5)); - 400512: 58 10 d0 00 l %r1,0(%r13) - 400516: a7 28 00 05 lhi %r2,5 - 40051a: 0d e1 basr %r14,%r1 - # compiler adds 1 extra instruction to epilogue this is done to - # avoid processor pipeline stalls owing to data dependencies on g5 & - # above as register 14 in the old code was needed directly after being loaded - # by the lm %r11,%r15,140(%r15) for the br %14. - 40051c: 58 40 f0 98 l %r4,152(%r15) - 400520: 98 7f f0 7c lm %r7,%r15,124(%r15) - 400524: 07 f4 br %r4 - } - - -Hartmut ( our compiler developer ) also has been threatening to take out the -stack backchain in optimised code as this also causes pipeline stalls, you -have been warned. - -64 bit z/Architecture code disassembly --------------------------------------- - -If you understand the stuff above you'll understand the stuff -below too so I'll avoid repeating myself & just say that -some of the instructions have g's on the end of them to indicate -they are 64 bit & the stack offsets are a bigger, -the only other difference you'll find between 32 & 64 bit is that -we now use f4 & f6 for floating point arguments on 64 bit:: - - 00000000800005b0 : - int test(int b) - { - return(5+b); - 800005b0: a7 2a 00 05 ahi %r2,5 - 800005b4: b9 14 00 22 lgfr %r2,%r2 # downcast to integer - 800005b8: 07 fe br %r14 - 800005ba: 07 07 bcr 0,%r7 - - - } - - 00000000800005bc
    : - main(int argc,char *argv[]) - { - 800005bc: eb bf f0 58 00 24 stmg %r11,%r15,88(%r15) - 800005c2: b9 04 00 1f lgr %r1,%r15 - 800005c6: a7 fb ff 60 aghi %r15,-160 - 800005ca: e3 10 f0 00 00 24 stg %r1,0(%r15) - return(test(5)); - 800005d0: a7 29 00 05 lghi %r2,5 - # brasl allows jumps > 64k & is overkill here bras would do fune - 800005d4: c0 e5 ff ff ff ee brasl %r14,800005b0 - 800005da: e3 40 f1 10 00 04 lg %r4,272(%r15) - 800005e0: eb bf f0 f8 00 04 lmg %r11,%r15,248(%r15) - 800005e6: 07 f4 br %r4 - } - - - -Compiling programs for debugging on Linux for s/390 & z/Architecture -==================================================================== --gdwarf-2 now works it should be considered the default debugging -format for s/390 & z/Architecture as it is more reliable for debugging -shared libraries, normal -g debugging works much better now -Thanks to the IBM java compiler developers bug reports. - -This is typically done adding/appending the flags -g or -gdwarf-2 to the -CFLAGS & LDFLAGS variables Makefile of the program concerned. - -If using gdb & you would like accurate displays of registers & -stack traces compile without optimisation i.e make sure -that there is no -O2 or similar on the CFLAGS line of the Makefile & -the emitted gcc commands, obviously this will produce worse code -( not advisable for shipment ) but it is an aid to the debugging process. - -This aids debugging because the compiler will copy parameters passed in -in registers onto the stack so backtracing & looking at passed in -parameters will work, however some larger programs which use inline functions -will not compile without optimisation. - -Debugging with optimisation has since much improved after fixing -some bugs, please make sure you are using gdb-5.0 or later developed -after Nov'2000. - - - -Debugging under VM -================== - -Notes ------ -Addresses & values in the VM debugger are always hex never decimal -Address ranges are of the format - or -. -For example, the address range 0x2000 to 0x3000 can be described as 2000-3000 -or 2000.1000 - -The VM Debugger is case insensitive. - -VM's strengths are usually other debuggers weaknesses you can get at any -resource no matter how sensitive e.g. memory management resources, change -address translation in the PSW. For kernel hacking you will reap dividends if -you get good at it. - -The VM Debugger displays operators but not operands, and also the debugger -displays useful information on the same line as the author of the code probably -felt that it was a good idea not to go over the 80 columns on the screen. -This isn't as unintuitive as it may seem as the s/390 instructions are easy to -decode mentally and you can make a good guess at a lot of them as all the -operands are nibble (half byte aligned). -So if you have an objdump listing by hand, it is quite easy to follow, and if -you don't have an objdump listing keep a copy of the s/390 Reference Summary -or alternatively the s/390 principles of operation next to you. -e.g. even I can guess that -0001AFF8' LR 180F CC 0 -is a ( load register ) lr r0,r15 - -Also it is very easy to tell the length of a 390 instruction from the 2 most -significant bits in the instruction (not that this info is really useful except -if you are trying to make sense of a hexdump of code). -Here is a table - -======================= ================== -Bits Instruction Length -======================= ================== -00 2 Bytes -01 4 Bytes -10 4 Bytes -11 6 Bytes -======================= ================== - -The debugger also displays other useful info on the same line such as the -addresses being operated on destination addresses of branches & condition codes. -e.g.:: - - 00019736' AHI A7DAFF0E CC 1 - 000198BA' BRC A7840004 -> 000198C2' CC 0 - 000198CE' STM 900EF068 >> 0FA95E78 CC 2 - - - -Useful VM debugger commands ---------------------------- - -I suppose I'd better mention this before I start -to list the current active traces do:: - - Q TR - -there can be a maximum of 255 of these per set -( more about trace sets later ). - -To stop traces issue a:: - - TR END. - -To delete a particular breakpoint issue:: - - TR DEL - -The PA1 key drops to CP mode so you can issue debugger commands, -Doing alt c (on my 3270 console at least ) clears the screen. - -hitting b comes back to the running operating system -from cp mode ( in our case linux ). - -It is typically useful to add shortcuts to your profile.exec file -if you have one ( this is roughly equivalent to autoexec.bat in DOS ). -file here are a few from mine:: - - /* this gives me command history on issuing f12 */ - set pf12 retrieve - /* this continues */ - set pf8 imm b - /* goes to trace set a */ - set pf1 imm tr goto a - /* goes to trace set b */ - set pf2 imm tr goto b - /* goes to trace set c */ - set pf3 imm tr goto c - - - -Instruction Tracing -------------------- -Setting a simple breakpoint:: - - TR I PSWA
    - -To debug a particular function try:: - - TR I R - TR I on its own will single step. - TR I DATA will trace for particular mnemonics - -e.g.:: - - TR I DATA 4D R 0197BC.4000 - -will trace for BAS'es ( opcode 4D ) in the range 0197BC.4000 - -if you were inclined you could add traces for all branch instructions & -suffix them with the run prefix so you would have a backtrace on screen -when a program crashes:: - - TR BR will trace branches into or out of an address. - -e.g.:: - - TR BR INTO 0 - -is often quite useful if a program is getting awkward & deciding -to branch to 0 & crashing as this will stop at the address before in jumps to 0. - -:: - - TR I R
    RUN cmd d g - -single steps a range of addresses but stays running & -displays the gprs on each step. - - - -Displaying & modifying Registers --------------------------------- -D G - will display all the gprs - -Adding a extra G to all the commands is necessary to access the full 64 bit -content in VM on z/Architecture. Obviously this isn't required for access -registers as these are still 32 bit. - -e.g. - -DGG - instead of DG - -D X - will display all the control registers -D AR - will display all the access registers -D AR4-7 - will display access registers 4 to 7 -CPU ALL D G - will display the GRPS of all CPUS in the configuration -D PSW - will display the current PSW -st PSW 2000 - will put the value 2000 into the PSW & cause crash your machine. -D PREFIX - displays the prefix offset - - -Displaying Memory ------------------ -To display memory mapped using the current PSW's mapping try:: - - D - -To make VM display a message each time it hits a particular address and -continue try: - -D I - will disassemble/display a range of instructions. - -ST addr 32 bit word - will store a 32 bit aligned address -D T - will display the EBCDIC in an address (if you are that way inclined) -D R - will display real addresses ( without DAT ) but with prefixing. - -There are other complex options to display if you need to get at say home space -but are in primary space the easiest thing to do is to temporarily -modify the PSW to the other addressing mode, display the stuff & then -restore it. - - - -Hints ------ -If you want to issue a debugger command without halting your virtual machine -with the PA1 key try prefixing the command with #CP e.g.:: - - #cp tr i pswa 2000 - -also suffixing most debugger commands with RUN will cause them not -to stop just display the mnemonic at the current instruction on the console. - -If you have several breakpoints you want to put into your program & -you get fed up of cross referencing with System.map -you can do the following trick for several symbols. - -:: - - grep do_signal System.map - -which emits the following among other things:: - - 0001f4e0 T do_signal - -now you can do:: - - TR I PSWA 0001f4e0 cmd msg * do_signal - -This sends a message to your own console each time do_signal is entered. -( As an aside I wrote a perl script once which automatically generated a REXX -script with breakpoints on every kernel procedure, this isn't a good idea -because there are thousands of these routines & VM can only set 255 breakpoints -at a time so you nearly had to spend as long pruning the file down as you would -entering the msgs by hand), however, the trick might be useful for a single -object file. In the 3270 terminal emulator x3270 there is a very useful option -in the file menu called "Save Screen In File" - this is very good for keeping a -copy of traces. - -From CMS help will give you online help on a particular command. -e.g.:: - - HELP DISPLAY - -Also CP has a file called profile.exec which automatically gets called -on startup of CMS ( like autoexec.bat ), keeping on a DOS analogy session -CP has a feature similar to doskey, it may be useful for you to -use profile.exec to define some keystrokes. - -SET PF9 IMM B - This does a single step in VM on pressing F8. - -SET PF10 ^ - This sets up the ^ key. - which can be used for ^c (ctrl-c),^z (ctrl-z) which can't be typed - directly into some 3270 consoles. - -SET PF11 ^- - This types the starting keystrokes for a sysrq see SysRq below. -SET PF12 RETRIEVE - This retrieves command history on pressing F12. - - -Sometimes in VM the display is set up to scroll automatically this -can be very annoying if there are messages you wish to look at -to stop this do - -TERM MORE 255 255 - This will nearly stop automatic screen updates, however it will - cause a denial of service if lots of messages go to the 3270 console, - so it would be foolish to use this as the default on a production machine. - - -Tracing particular processes ----------------------------- -The kernel's text segment is intentionally at an address in memory that it will -very seldom collide with text segments of user programs ( thanks Martin ), -this simplifies debugging the kernel. -However it is quite common for user processes to have addresses which collide -this can make debugging a particular process under VM painful under normal -circumstances as the process may change when doing a:: - - TR I R
    . - -Thankfully after reading VM's online help I figured out how to debug -I particular process. - -Your first problem is to find the STD ( segment table designation ) -of the program you wish to debug. -There are several ways you can do this here are a few - -Run:: - - objdump --syms | grep main - -To get the address of main in the program. Then:: - - tr i pswa
    - -Start the program, if VM drops to CP on what looks like the entry -point of the main function this is most likely the process you wish to debug. -Now do a D X13 or D XG13 on z/Architecture. - -On 31 bit the STD is bits 1-19 ( the STO segment table origin ) -& 25-31 ( the STL segment table length ) of CR13. - -now type:: - - TR I R STD 0.7fffffff - -e.g.:: - - TR I R STD 8F32E1FF 0.7fffffff - -Another very useful variation is:: - - TR STORE INTO STD
    - -for finding out when a particular variable changes. - -An alternative way of finding the STD of a currently running process -is to do the following, ( this method is more complex but -could be quite convenient if you aren't updating the kernel much & -so your kernel structures will stay constant for a reasonable period of -time ). - -:: - - grep task /proc//status - -from this you should see something like:: - - task: 0f160000 ksp: 0f161de8 pt_regs: 0f161f68 - -This now gives you a pointer to the task structure. - -Now make:: - - CC:="s390-gcc -g" kernel/sched.s - -To get the task_struct stabinfo. - -( task_struct is defined in include/linux/sched.h ). - -Now we want to look at -task->active_mm->pgd - -on my machine the active_mm in the task structure stab is -active_mm:(4,12),672,32 - -its offset is 672/8=84=0x54 - -the pgd member in the mm_struct stab is -pgd:(4,6)=*(29,5),96,32 -so its offset is 96/8=12=0xc - -so we'll:: - - hexdump -s 0xf160054 /dev/mem | more - -i.e. task_struct+active_mm offset -to look at the active_mm member:: - - f160054 0fee cc60 0019 e334 0000 0000 0000 0011 - -:: - - hexdump -s 0x0feecc6c /dev/mem | more - -i.e. active_mm+pgd offset:: - - feecc6c 0f2c 0000 0000 0001 0000 0001 0000 0010 - -we get something like -now do:: - - TR I R STD 0.7fffffff - -i.e. the 0x7f is added because the pgd only -gives the page table origin & we need to set the low bits -to the maximum possible segment table length. - -:: - - TR I R STD 0f2c007f 0.7fffffff - -on z/Architecture you'll probably need to do:: - - TR I R STD 0.ffffffffffffffff - -to set the TableType to 0x1 & the Table length to 3. - - - -Tracing Program Exceptions --------------------------- -If you get a crash which says something like -illegal operation or specification exception followed by a register dump -You can restart linux & trace these using the tr prog trace -option. - - -The most common ones you will normally be tracing for is: - -- 1=operation exception -- 2=privileged operation exception -- 4=protection exception -- 5=addressing exception -- 6=specification exception -- 10=segment translation exception -- 11=page translation exception - -The full list of these is on page 22 of the current s/390 Reference Summary. -e.g. - -tr prog 10 will trace segment translation exceptions. - -tr prog on its own will trace all program interruption codes. - -Trace Sets ----------- -On starting VM you are initially in the INITIAL trace set. -You can do a Q TR to verify this. -If you have a complex tracing situation where you wish to wait for instance -till a driver is open before you start tracing IO, but know in your -heart that you are going to have to make several runs through the code till you -have a clue whats going on. - -What you can do is:: - - TR I PSWA - -hit b to continue till breakpoint - -reach the breakpoint - -now do your:: - - TR GOTO B - TR IO 7c08-7c09 inst int run - -or whatever the IO channels you wish to trace are & hit b - -To got back to the initial trace set do:: - - TR GOTO INITIAL - -& the TR I PSWA will be the only active breakpoint again. - - -Tracing linux syscalls under VM -------------------------------- -Syscalls are implemented on Linux for S390 by the Supervisor call instruction -(SVC). There 256 possibilities of these as the instruction is made up of a 0xA -opcode and the second byte being the syscall number. They are traced using the -simple command:: - - TR SVC - -the syscalls are defined in linux/arch/s390/include/asm/unistd.h -e.g. to trace all file opens just do:: - - TR SVC 5 ( as this is the syscall number of open ) - - -SMP Specific commands ---------------------- -To find out how many cpus you have -Q CPUS displays all the CPU's available to your virtual machine -To find the cpu that the current cpu VM debugger commands are being directed at -do Q CPU to change the current cpu VM debugger commands are being directed at -do:: - - CPU - -On a SMP guest issue a command to all CPUs try prefixing the command with cpu -all. To issue a command to a particular cpu try cpu e.g.:: - - CPU 01 TR I R 2000.3000 - -If you are running on a guest with several cpus & you have a IO related problem -& cannot follow the flow of code but you know it isn't smp related. - -from the bash prompt issue:: - - shutdown -h now or halt. - -do a:: - - Q CPUS - -to find out how many cpus you have detach each one of them from cp except -cpu 0 by issuing a:: - - DETACH CPU 01-(number of cpus in configuration) - -& boot linux again. - -TR SIGP - will trace inter processor signal processor instructions. - -DEFINE CPU 01-(number in configuration) - will get your guests cpus back. - - -Help for displaying ascii textstrings -------------------------------------- -On the very latest VM Nucleus'es VM can now display ascii -( thanks Neale for the hint ) by doing:: - - D TX. - -e.g.:: - - D TX0.100 - -Alternatively -============= -Under older VM debuggers (I love EBDIC too) you can use following little -program which converts a command line of hex digits to ascii text. It can be -compiled under linux and you can copy the hex digits from your x3270 terminal -to your xterm if you are debugging from a linuxbox. - -This is quite useful when looking at a parameter passed in as a text string -under VM ( unless you are good at decoding ASCII in your head ). - -e.g. consider tracing an open syscall:: - - TR SVC 5 - -We have stopped at a breakpoint:: - - 000151B0' SVC 0A05 -> 0001909A' CC 0 - -D 20.8 to check the SVC old psw in the prefix area and see was it from userspace -(for the layout of the prefix area consult the "Fixed Storage Locations" -chapter of the s/390 Reference Summary if you have it available). - -:: - - V00000020 070C2000 800151B2 - -The problem state bit wasn't set & it's also too early in the boot sequence -for it to be a userspace SVC if it was we would have to temporarily switch the -psw to user space addressing so we could get at the first parameter of the open -in gpr2. - -Next do a:: - - D G2 - GPR 2 = 00014CB4 - -Now display what gpr2 is pointing to:: - - D 00014CB4.20 - V00014CB4 2F646576 2F636F6E 736F6C65 00001BF5 - V00014CC4 FC00014C B4001001 E0001000 B8070707 - -Now copy the text till the first 00 hex ( which is the end of the string -to an xterm & do hex2ascii on it:: - - hex2ascii 2F646576 2F636F6E 736F6C65 00 - -outputs:: - - Decoded Hex:=/ d e v / c o n s o l e 0x00 - -We were opening the console device, - -You can compile the code below yourself for practice :-), - -:: - - /* - * hex2ascii.c - * a useful little tool for converting a hexadecimal command line to ascii - * - * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) - * (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation. - */ - #include - - int main(int argc,char *argv[]) - { - int cnt1,cnt2,len,toggle=0; - int startcnt=1; - unsigned char c,hex; - - if(argc>1&&(strcmp(argv[1],"-a")==0)) - startcnt=2; - printf("Decoded Hex:="); - for(cnt1=startcnt;cnt1='0'&&c<='9') - c=c-'0'; - if(c>='A'&&c<='F') - c=c-'A'+10; - if(c>='a'&&c<='f') - c=c-'a'+10; - switch(toggle) - { - case 0: - hex=c<<4; - toggle=1; - break; - case 1: - hex+=c; - if(hex<32||hex>127) - { - if(startcnt==1) - printf("0x%02X ",(int)hex); - else - printf("."); - } - else - { - printf("%c",hex); - if(startcnt==1) - printf(" "); - } - toggle=0; - break; - } - } - } - printf("\n"); - } - - - - -Stack tracing under VM ----------------------- -A basic backtrace ------------------ - -Here are the tricks I use 9 out of 10 times it works pretty well, - -When your backchain reaches a dead end --------------------------------------- -This can happen when an exception happens in the kernel and the kernel is -entered twice. If you reach the NULL pointer at the end of the back chain you -should be able to sniff further back if you follow the following tricks. -1) A kernel address should be easy to recognise since it is in -primary space & the problem state bit isn't set & also -The Hi bit of the address is set. -2) Another backchain should also be easy to recognise since it is an -address pointing to another address approximately 100 bytes or 0x70 hex -behind the current stackpointer. - - -Here is some practice. - -boot the kernel & hit PA1 at some random time - -d g to display the gprs, this should display something like:: - - GPR 0 = 00000001 00156018 0014359C 00000000 - GPR 4 = 00000001 001B8888 000003E0 00000000 - GPR 8 = 00100080 00100084 00000000 000FE000 - GPR 12 = 00010400 8001B2DC 8001B36A 000FFED8 - -Note that GPR14 is a return address but as we are real men we are going to -trace the stack. -display 0x40 bytes after the stack pointer:: - - V000FFED8 000FFF38 8001B838 80014C8E 000FFF38 - V000FFEE8 00000000 00000000 000003E0 00000000 - V000FFEF8 00100080 00100084 00000000 000FE000 - V000FFF08 00010400 8001B2DC 8001B36A 000FFED8 - - -Ah now look at whats in sp+56 (sp+0x38) this is 8001B36A our saved r14 if -you look above at our stackframe & also agrees with GPR14. - -now backchain:: - - d 000FFF38.40 - -we now are taking the contents of SP to get our first backchain:: - - V000FFF38 000FFFA0 00000000 00014995 00147094 - V000FFF48 00147090 001470A0 000003E0 00000000 - V000FFF58 00100080 00100084 00000000 001BF1D0 - V000FFF68 00010400 800149BA 80014CA6 000FFF38 - -This displays a 2nd return address of 80014CA6 - -now do:: - - d 000FFFA0.40 - -for our 3rd backchain:: - - V000FFFA0 04B52002 0001107F 00000000 00000000 - V000FFFB0 00000000 00000000 FF000000 0001107F - V000FFFC0 00000000 00000000 00000000 00000000 - V000FFFD0 00010400 80010802 8001085A 000FFFA0 - - -our 3rd return address is 8001085A - -as the 04B52002 looks suspiciously like rubbish it is fair to assume that the -kernel entry routines for the sake of optimisation don't set up a backchain. - -now look at System.map to see if the addresses make any sense:: - - grep -i 0001b3 System.map - -outputs among other things:: - - 0001b304 T cpu_idle - -so 8001B36A -is cpu_idle+0x66 ( quiet the cpu is asleep, don't wake it ) - -:: - - grep -i 00014 System.map - -produces among other things:: - - 00014a78 T start_kernel - -so 0014CA6 is start_kernel+some hex number I can't add in my head. - -:: - - grep -i 00108 System.map - -this produces:: - - 00010800 T _stext - -so 8001085A is _stext+0x5a - -Congrats you've done your first backchain. - - - -s/390 & z/Architecture IO Overview -================================== - -I am not going to give a course in 390 IO architecture as this would take me -quite a while and I'm no expert. Instead I'll give a 390 IO architecture -summary for Dummies. If you have the s/390 principles of operation available -read this instead. If nothing else you may find a few useful keywords in here -and be able to use them on a web search engine to find more useful information. - -Unlike other bus architectures modern 390 systems do their IO using mostly -fibre optics and devices such as tapes and disks can be shared between several -mainframes. Also S390 can support up to 65536 devices while a high end PC based -system might be choking with around 64. - -Here is some of the common IO terminology: - -Subchannel: - This is the logical number most IO commands use to talk to an IO device. There - can be up to 0x10000 (65536) of these in a configuration, typically there are a - few hundred. Under VM for simplicity they are allocated contiguously, however - on the native hardware they are not. They typically stay consistent between - boots provided no new hardware is inserted or removed. - - Under Linux for s390 we use these as IRQ's and also when issuing an IO command - (CLEAR SUBCHANNEL, HALT SUBCHANNEL, MODIFY SUBCHANNEL, RESUME SUBCHANNEL, - START SUBCHANNEL, STORE SUBCHANNEL and TEST SUBCHANNEL). We use this as the ID - of the device we wish to talk to. The most important of these instructions are - START SUBCHANNEL (to start IO), TEST SUBCHANNEL (to check whether the IO - completed successfully) and HALT SUBCHANNEL (to kill IO). A subchannel can have - up to 8 channel paths to a device, this offers redundancy if one is not - available. - -Device Number: - This number remains static and is closely tied to the hardware. There are 65536 - of these, made up of a CHPID (Channel Path ID, the most significant 8 bits) and - another lsb 8 bits. These remain static even if more devices are inserted or - removed from the hardware. There is a 1 to 1 mapping between subchannels and - device numbers, provided devices aren't inserted or removed. - -Channel Control Words: - CCWs are linked lists of instructions initially pointed to by an operation - request block (ORB), which is initially given to Start Subchannel (SSCH) - command along with the subchannel number for the IO subsystem to process - while the CPU continues executing normal code. - CCWs come in two flavours, Format 0 (24 bit for backward compatibility) and - Format 1 (31 bit). These are typically used to issue read and write (and many - other) instructions. They consist of a length field and an absolute address - field. - - Each IO typically gets 1 or 2 interrupts, one for channel end (primary status) - when the channel is idle, and the second for device end (secondary status). - Sometimes you get both concurrently. You check how the IO went on by issuing a - TEST SUBCHANNEL at each interrupt, from which you receive an Interruption - response block (IRB). If you get channel and device end status in the IRB - without channel checks etc. your IO probably went okay. If you didn't you - probably need to examine the IRB, extended status word etc. - If an error occurs, more sophisticated control units have a facility known as - concurrent sense. This means that if an error occurs Extended sense information - will be presented in the Extended status word in the IRB. If not you have to - issue a subsequent SENSE CCW command after the test subchannel. - - -TPI (Test pending interrupt) can also be used for polled IO, but in -multitasking multiprocessor systems it isn't recommended except for -checking special cases (i.e. non looping checks for pending IO etc.). - -Store Subchannel and Modify Subchannel can be used to examine and modify -operating characteristics of a subchannel (e.g. channel paths). - -Other IO related Terms: - -Sysplex: - S390's Clustering Technology -QDIO: - S390's new high speed IO architecture to support devices such as gigabit - ethernet, this architecture is also designed to be forward compatible with - upcoming 64 bit machines. - - -General Concepts ----------------- - -Input Output Processors (IOP's) are responsible for communicating between -the mainframe CPU's & the channel & relieve the mainframe CPU's from the -burden of communicating with IO devices directly, this allows the CPU's to -concentrate on data processing. - -IOP's can use one or more links ( known as channel paths ) to talk to each -IO device. It first checks for path availability & chooses an available one, -then starts ( & sometimes terminates IO ). -There are two types of channel path: ESCON & the Parallel IO interface. - -IO devices are attached to control units, control units provide the -logic to interface the channel paths & channel path IO protocols to -the IO devices, they can be integrated with the devices or housed separately -& often talk to several similar devices ( typical examples would be raid -controllers or a control unit which connects to 1000 3270 terminals ):: - - - +---------------------------------------------------------------+ - | +-----+ +-----+ +-----+ +-----+ +----------+ +----------+ | - | | CPU | | CPU | | CPU | | CPU | | Main | | Expanded | | - | | | | | | | | | | Memory | | Storage | | - | +-----+ +-----+ +-----+ +-----+ +----------+ +----------+ | - |---------------------------------------------------------------+ - | IOP | IOP | IOP | - |--------------------------------------------------------------- - | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | - ---------------------------------------------------------------- - || || - || Bus & Tag Channel Path || ESCON - || ====================== || Channel - || || || || Path - +----------+ +----------+ +----------+ - | | | | | | - | CU | | CU | | CU | - | | | | | | - +----------+ +----------+ +----------+ - | | | | | - +----------+ +----------+ +----------+ +----------+ +----------+ - |I/O Device| |I/O Device| |I/O Device| |I/O Device| |I/O Device| - +----------+ +----------+ +----------+ +----------+ +----------+ - CPU = Central Processing Unit - C = Channel - IOP = IP Processor - CU = Control Unit - -The 390 IO systems come in 2 flavours the current 390 machines support both - -The Older 360 & 370 Interface,sometimes called the Parallel I/O interface, -sometimes called Bus-and Tag & sometimes Original Equipment Manufacturers -Interface (OEMI). - -This byte wide Parallel channel path/bus has parity & data on the "Bus" cable -and control lines on the "Tag" cable. These can operate in byte multiplex mode -for sharing between several slow devices or burst mode and monopolize the -channel for the whole burst. Up to 256 devices can be addressed on one of these -cables. These cables are about one inch in diameter. The maximum unextended -length supported by these cables is 125 Meters but this can be extended up to -2km with a fibre optic channel extended such as a 3044. The maximum burst speed -supported is 4.5 megabytes per second. However, some really old processors -support only transfer rates of 3.0, 2.0 & 1.0 MB/sec. -One of these paths can be daisy chained to up to 8 control units. - - -ESCON if fibre optic it is also called FICON -Was introduced by IBM in 1990. Has 2 fibre optic cables and uses either leds or -lasers for communication at a signaling rate of up to 200 megabits/sec. As -10bits are transferred for every 8 bits info this drops to 160 megabits/sec -and to 18.6 Megabytes/sec once control info and CRC are added. ESCON only -operates in burst mode. - -ESCONs typical max cable length is 3km for the led version and 20km for the -laser version known as XDF (extended distance facility). This can be further -extended by using an ESCON director which triples the above mentioned ranges. -Unlike Bus & Tag as ESCON is serial it uses a packet switching architecture, -the standard Bus & Tag control protocol is however present within the packets. -Up to 256 devices can be attached to each control unit that uses one of these -interfaces. - -Common 390 Devices include: -Network adapters typically OSA2,3172's,2116's & OSA-E gigabit ethernet adapters, -Consoles 3270 & 3215 (a teletype emulated under linux for a line mode console). -DASD's direct access storage devices ( otherwise known as hard disks ). -Tape Drives. -CTC ( Channel to Channel Adapters ), -ESCON or Parallel Cables used as a very high speed serial link -between 2 machines. - - -Debugging IO on s/390 & z/Architecture under VM -=============================================== - -Now we are ready to go on with IO tracing commands under VM - -A few self explanatory queries:: - - Q OSA - Q CTC - Q DISK ( This command is CMS specific ) - Q DASD - -Q OSA on my machine returns:: - - OSA 7C08 ON OSA 7C08 SUBCHANNEL = 0000 - OSA 7C09 ON OSA 7C09 SUBCHANNEL = 0001 - OSA 7C14 ON OSA 7C14 SUBCHANNEL = 0002 - OSA 7C15 ON OSA 7C15 SUBCHANNEL = 0003 - -If you have a guest with certain privileges you may be able to see devices -which don't belong to you. To avoid this, add the option V. -e.g.:: - - Q V OSA - -Now using the device numbers returned by this command we will -Trace the io starting up on the first device 7c08 & 7c09 -In our simplest case we can trace the -start subchannels -like TR SSCH 7C08-7C09 -or the halt subchannels -or TR HSCH 7C08-7C09 -MSCH's ,STSCH's I think you can guess the rest - -A good trick is tracing all the IO's and CCWS and spooling them into the reader -of another VM guest so he can ftp the logfile back to his own machine. I'll do -a small bit of this and give you a look at the output. - -1) Spool stdout to VM reader:: - - SP PRT TO (another vm guest ) or * for the local vm guest - -2) Fill the reader with the trace:: - - TR IO 7c08-7c09 INST INT CCW PRT RUN - -3) Start up linux:: - - i 00c -4) Finish the trace:: - - TR END - -5) close the reader:: - - C PRT - -6) list reader contents:: - - RDRLIST - -7) copy it to linux4's minidisk:: - - RECEIVE / LOG TXT A1 ( replace - -8) -filel & press F11 to look at it -You should see something like:: - - 00020942' SSCH B2334000 0048813C CC 0 SCH 0000 DEV 7C08 - CPA 000FFDF0 PARM 00E2C9C4 KEY 0 FPI C0 LPM 80 - CCW 000FFDF0 E4200100 00487FE8 0000 E4240100 ........ - IDAL 43D8AFE8 - IDAL 0FB76000 - 00020B0A' I/O DEV 7C08 -> 000197BC' SCH 0000 PARM 00E2C9C4 - 00021628' TSCH B2354000 >> 00488164 CC 0 SCH 0000 DEV 7C08 - CCWA 000FFDF8 DEV STS 0C SCH STS 00 CNT 00EC - KEY 0 FPI C0 CC 0 CTLS 4007 - 00022238' STSCH B2344000 >> 00488108 CC 0 SCH 0000 DEV 7C08 - -If you don't like messing up your readed ( because you possibly booted from it ) -you can alternatively spool it to another readers guest. - - -Other common VM device related commands ---------------------------------------------- -These commands are listed only because they have -been of use to me in the past & may be of use to -you too. For more complete info on each of the commands -use type HELP from CMS. - -detaching devices:: - - DET - ATT - -attach a device to guest * for your own guest - -READY - cause VM to issue a fake interrupt. - -The VARY command is normally only available to VM administrators:: - - VARY ON PATH TO - VARY OFF PATH FROM - -This is used to switch on or off channel paths to devices. - -Q CHPID - This displays state of devices using this channel path - -D SCHIB - This displays the subchannel information SCHIB block for the device. - this I believe is also only available to administrators. - -DEFINE CTC - defines a virtual CTC channel to channel connection - 2 need to be defined on each guest for the CTC driver to use. - -COUPLE devno userid remote devno - Joins a local virtual device to a remote virtual device - ( commonly used for the CTC driver ). - -Building a VM ramdisk under CMS which linux can use:: - - def vfb- - -blocksize is commonly 4096 for linux. - -Formatting it:: - - format (blksize - -Sharing a disk between multiple guests:: - - LINK userid devno1 devno2 mode password - - - -GDB on S390 -=========== -N.B. if compiling for debugging gdb works better without optimisation -( see Compiling programs for debugging ) - -invocation ----------- -gdb - -Online help ------------ -help: gives help on commands - -e.g.:: - - help - help display - -Note gdb's online help is very good use it. - - -Assembly --------- -info registers: - displays registers other than floating point. - -info all-registers: - displays floating points as well. - -disassemble: - disassembles - -e.g.:: - - disassemble without parameters will disassemble the current function - disassemble $pc $pc+10 - -Viewing & modifying variables ------------------------------ -print or p: - displays variable or register - -e.g. p/x $sp will display the stack pointer - -display: - prints variable or register each time program stops - -e.g.:: - - display/x $pc will display the program counter - display argc - -undisplay: - undo's display's - -info breakpoints: - shows all current breakpoints - -info stack: - shows stack back trace (if this doesn't work too well, I'll show - you the stacktrace by hand below). - -info locals: - displays local variables. - -info args: - display current procedure arguments. - -set args: - will set argc & argv each time the victim program is invoked - -e.g.:: - - set =value - set argc=100 - set $pc=0 - - - -Modifying execution -------------------- -step: - steps n lines of sourcecode - -step - steps 1 line. - -step 100 - steps 100 lines of code. - -next: - like step except this will not step into subroutines - -stepi: - steps a single machine code instruction. - -e.g.:: - - stepi 100 - -nexti: - steps a single machine code instruction but will not step into - subroutines. - -finish: - will run until exit of the current routine - -run: - (re)starts a program - -cont: - continues a program - -quit: - exits gdb. - - -breakpoints ------------- - -break - sets a breakpoint - -e.g.:: - - break main - break *$pc - break *0x400618 - -Here's a really useful one for large programs - -rbr - Set a breakpoint for all functions matching REGEXP - -e.g.:: - - rbr 390 - -will set a breakpoint with all functions with 390 in their name. - -info breakpoints - lists all breakpoints - -delete: - delete breakpoint by number or delete them all - -e.g. - -delete 1 - will delete the first breakpoint - - -delete - will delete them all - -watch: - This will set a watchpoint ( usually hardware assisted ), - -This will watch a variable till it changes - -e.g. - -watch cnt - will watch the variable cnt till it changes. - -As an aside unfortunately gdb's, architecture independent watchpoint code -is inconsistent & not very good, watchpoints usually work but not always. - -info watchpoints: - Display currently active watchpoints - -condition: ( another useful one ) - Specify breakpoint number N to break only if COND is true. - -Usage is `condition N COND`, where N is an integer and COND is an -expression to be evaluated whenever breakpoint N is reached. - - - -User defined functions/macros ------------------------------ -define: ( Note this is very very useful,simple & powerful ) - -usage define end - -examples which you should consider putting into .gdbinit in your home -directory:: - - define d - stepi - disassemble $pc $pc+10 - end - define e - nexti - disassemble $pc $pc+10 - end - - -Other hard to classify stuff ----------------------------- -signal n: - sends the victim program a signal. - -e.g. `signal 3` will send a SIGQUIT. - -info signals: - what gdb does when the victim receives certain signals. - -list: - -e.g.: - -list - lists current function source -list 1,10 - list first 10 lines of current file. - -list test.c:1,10 - - -directory: - Adds directories to be searched for source if gdb cannot find the source. - (note it is a bit sensitive about slashes) - -e.g. To add the root of the filesystem to the searchpath do:: - - directory // - - -call -This calls a function in the victim program, this is pretty powerful -e.g. -(gdb) call printf("hello world") -outputs: -$1 = 11 - -You might now be thinking that the line above didn't work, something extra had -to be done. -(gdb) call fflush(stdout) -hello world$2 = 0 -As an aside the debugger also calls malloc & free under the hood -to make space for the "hello world" string. - - - -hints ------ -1) command completion works just like bash - ( if you are a bad typist like me this really helps ) - -e.g. hit br & cursor up & down :-). - -2) if you have a debugging problem that takes a few steps to recreate -put the steps into a file called .gdbinit in your current working directory -if you have defined a few extra useful user defined commands put these in -your home directory & they will be read each time gdb is launched. - -A typical .gdbinit file might be.:: - - break main - run - break runtime_exception - cont - - -stack chaining in gdb by hand ------------------------------ -This is done using a the same trick described for VM:: - - p/x (*($sp+56))&0x7fffffff - -get the first backchain. - -For z/Architecture -Replace 56 with 112 & ignore the &0x7fffffff -in the macros below & do nasty casts to longs like the following -as gdb unfortunately deals with printed arguments as ints which -messes up everything. - -i.e. here is a 3rd backchain dereference:: - - p/x *(long *)(***(long ***)$sp+112) - - -this outputs:: - - $5 = 0x528f18 - -on my machine. - -Now you can use:: - - info symbol (*($sp+56))&0x7fffffff - -you might see something like:: - - rl_getc + 36 in section .text - -telling you what is located at address 0x528f18 -Now do:: - - p/x (*(*$sp+56))&0x7fffffff - -This outputs:: - - $6 = 0x528ed0 - -Now do:: - - info symbol (*(*$sp+56))&0x7fffffff - rl_read_key + 180 in section .text - -now do:: - - p/x (*(**$sp+56))&0x7fffffff - -& so on. - -Disassembling instructions without debug info ---------------------------------------------- -gdb typically complains if there is a lack of debugging -symbols in the disassemble command with -"No function contains specified address." To get around -this do:: - - x/xi
    - -e.g.:: - - x/20xi 0x400730 - - - -Note: - Remember gdb has history just like bash you don't need to retype the - whole line just use the up & down arrows. - - - -For more info -------------- -From your linuxbox do:: - - man gdb - -or:: - - info gdb. - -core dumps ----------- - -What a core dump ? -^^^^^^^^^^^^^^^^^^ - -A core dump is a file generated by the kernel (if allowed) which contains the -registers and all active pages of the program which has crashed. - -From this file gdb will allow you to look at the registers, stack trace and -memory of the program as if it just crashed on your system. It is usually -called core and created in the current working directory. - -This is very useful in that a customer can mail a core dump to a technical -support department and the technical support department can reconstruct what -happened. Provided they have an identical copy of this program with debugging -symbols compiled in and the source base of this build is available. - -In short it is far more useful than something like a crash log could ever hope -to be. - -Why have I never seen one ? -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Probably because you haven't used the command:: - - ulimit -c unlimited in bash - -to allow core dumps, now do:: - - ulimit -a - -to verify that the limit was accepted. - -A sample core dump - To create this I'm going to do:: - - ulimit -c unlimited - gdb - -to launch gdb (my victim app. ) now be bad & do the following from another -telnet/xterm session to the same machine:: - - ps -aux | grep gdb - kill -SIGSEGV - -or alternatively use `killall -SIGSEGV gdb` if you have the killall command. - -Now look at the core dump:: - - ./gdb core - -Displays the following:: - - GNU gdb 4.18 - Copyright 1998 Free Software Foundation, Inc. - GDB is free software, covered by the GNU General Public License, and you are - welcome to change it and/or distribute copies of it under certain conditions. - Type "show copying" to see the conditions. - There is absolutely no warranty for GDB. Type "show warranty" for details. - This GDB was configured as "s390-ibm-linux"... - Core was generated by `./gdb'. - Program terminated with signal 11, Segmentation fault. - Reading symbols from /usr/lib/libncurses.so.4...done. - Reading symbols from /lib/libm.so.6...done. - Reading symbols from /lib/libc.so.6...done. - Reading symbols from /lib/ld-linux.so.2...done. - #0 0x40126d1a in read () from /lib/libc.so.6 - Setting up the environment for debugging gdb. - Breakpoint 1 at 0x4dc6f8: file utils.c, line 471. - Breakpoint 2 at 0x4d87a4: file top.c, line 2609. - (top-gdb) info stack - #0 0x40126d1a in read () from /lib/libc.so.6 - #1 0x528f26 in rl_getc (stream=0x7ffffde8) at input.c:402 - #2 0x528ed0 in rl_read_key () at input.c:381 - #3 0x5167e6 in readline_internal_char () at readline.c:454 - #4 0x5168ee in readline_internal_charloop () at readline.c:507 - #5 0x51692c in readline_internal () at readline.c:521 - #6 0x5164fe in readline (prompt=0x7ffff810) - at readline.c:349 - #7 0x4d7a8a in command_line_input (prompt=0x564420 "(gdb) ", repeat=1, - annotation_suffix=0x4d6b44 "prompt") at top.c:2091 - #8 0x4d6cf0 in command_loop () at top.c:1345 - #9 0x4e25bc in main (argc=1, argv=0x7ffffdf4) at main.c:635 - - -LDD -=== -This is a program which lists the shared libraries which a library needs, -Note you also get the relocations of the shared library text segments which -help when using objdump --source. - -e.g.:: - - ldd ./gdb - -outputs:: - - libncurses.so.4 => /usr/lib/libncurses.so.4 (0x40018000) - libm.so.6 => /lib/libm.so.6 (0x4005e000) - libc.so.6 => /lib/libc.so.6 (0x40084000) - /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) - - -Debugging shared libraries -========================== -Most programs use shared libraries, however it can be very painful -when you single step instruction into a function like printf for the -first time & you end up in functions like _dl_runtime_resolve this is -the ld.so doing lazy binding, lazy binding is a concept in ELF where -shared library functions are not loaded into memory unless they are -actually used, great for saving memory but a pain to debug. - -To get around this either relink the program -static or exit gdb type -export LD_BIND_NOW=true this will stop lazy binding & restart the gdb'ing -the program in question. - - - -Debugging modules -================= -As modules are dynamically loaded into the kernel their address can be -anywhere to get around this use the -m option with insmod to emit a load -map which can be piped into a file if required. - -The proc file system -==================== -What is it ?. -It is a filesystem created by the kernel with files which are created on demand -by the kernel if read, or can be used to modify kernel parameters, -it is a powerful concept. - -e.g.:: - - cat /proc/sys/net/ipv4/ip_forward - -On my machine outputs:: - - 0 - -telling me ip_forwarding is not on to switch it on I can do:: - - echo 1 > /proc/sys/net/ipv4/ip_forward - -cat it again:: - - cat /proc/sys/net/ipv4/ip_forward - -On my machine now outputs:: - - 1 - -IP forwarding is on. - -There is a lot of useful info in here best found by going in and having a look -around, so I'll take you through some entries I consider important. - -All the processes running on the machine have their own entry defined by -/proc/ - -So lets have a look at the init process:: - - cd /proc/1 - cat cmdline - -emits:: - - init [2] - -:: - - cd /proc/1/fd - -This contains numerical entries of all the open files, -some of these you can cat e.g. stdout (2):: - - cat /proc/29/maps - -on my machine emits:: - - 00400000-00478000 r-xp 00000000 5f:00 4103 /bin/bash - 00478000-0047e000 rw-p 00077000 5f:00 4103 /bin/bash - 0047e000-00492000 rwxp 00000000 00:00 0 - 40000000-40015000 r-xp 00000000 5f:00 14382 /lib/ld-2.1.2.so - 40015000-40016000 rw-p 00014000 5f:00 14382 /lib/ld-2.1.2.so - 40016000-40017000 rwxp 00000000 00:00 0 - 40017000-40018000 rw-p 00000000 00:00 0 - 40018000-4001b000 r-xp 00000000 5f:00 14435 /lib/libtermcap.so.2.0.8 - 4001b000-4001c000 rw-p 00002000 5f:00 14435 /lib/libtermcap.so.2.0.8 - 4001c000-4010d000 r-xp 00000000 5f:00 14387 /lib/libc-2.1.2.so - 4010d000-40111000 rw-p 000f0000 5f:00 14387 /lib/libc-2.1.2.so - 40111000-40114000 rw-p 00000000 00:00 0 - 40114000-4011e000 r-xp 00000000 5f:00 14408 /lib/libnss_files-2.1.2.so - 4011e000-4011f000 rw-p 00009000 5f:00 14408 /lib/libnss_files-2.1.2.so - 7fffd000-80000000 rwxp ffffe000 00:00 0 - - -Showing us the shared libraries init uses where they are in memory -& memory access permissions for each virtual memory area. - -/proc/1/cwd is a softlink to the current working directory. - -/proc/1/root is the root of the filesystem for this process. - -/proc/1/mem is the current running processes memory which you -can read & write to like a file. - -strace uses this sometimes as it is a bit faster than the -rather inefficient ptrace interface for peeking at DATA. - -:: - - cat status - - Name: init - State: S (sleeping) - Pid: 1 - PPid: 0 - Uid: 0 0 0 0 - Gid: 0 0 0 0 - Groups: - VmSize: 408 kB - VmLck: 0 kB - VmRSS: 208 kB - VmData: 24 kB - VmStk: 8 kB - VmExe: 368 kB - VmLib: 0 kB - SigPnd: 0000000000000000 - SigBlk: 0000000000000000 - SigIgn: 7fffffffd7f0d8fc - SigCgt: 00000000280b2603 - CapInh: 00000000fffffeff - CapPrm: 00000000ffffffff - CapEff: 00000000fffffeff - - User PSW: 070de000 80414146 - task: 004b6000 tss: 004b62d8 ksp: 004b7ca8 pt_regs: 004b7f68 - User GPRS: - 00000400 00000000 0000000b 7ffffa90 - 00000000 00000000 00000000 0045d9f4 - 0045cafc 7ffffa90 7fffff18 0045cb08 - 00010400 804039e8 80403af8 7ffff8b0 - User ACRS: - 00000000 00000000 00000000 00000000 - 00000001 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 - Kernel BackChain CallChain BackChain CallChain - 004b7ca8 8002bd0c 004b7d18 8002b92c - 004b7db8 8005cd50 004b7e38 8005d12a - 004b7f08 80019114 - -Showing among other things memory usage & status of some signals & -the processes'es registers from the kernel task_structure -as well as a backchain which may be useful if a process crashes -in the kernel for some unknown reason. - -Some driver debugging techniques -================================ -debug feature -------------- -Some of our drivers now support a "debug feature" in -/proc/s390dbf see s390dbf.txt in the linux/Documentation directory -for more info. - -e.g. -to switch on the lcs "debug feature":: - - echo 5 > /proc/s390dbf/lcs/level - -& then after the error occurred:: - - cat /proc/s390dbf/lcs/sprintf >/logfile - -the logfile now contains some information which may help -tech support resolve a problem in the field. - - - -high level debugging network drivers ------------------------------------- -ifconfig is a quite useful command -it gives the current state of network drivers. - -If you suspect your network device driver is dead -one way to check is type:: - - ifconfig - -e.g. tr0 - -You should see something like:: - - ifconfig tr0 - tr0 Link encap:16/4 Mbps Token Ring (New) HWaddr 00:04:AC:20:8E:48 - inet addr:9.164.185.132 Bcast:9.164.191.255 Mask:255.255.224.0 - UP BROADCAST RUNNING MULTICAST MTU:2000 Metric:1 - RX packets:246134 errors:0 dropped:0 overruns:0 frame:0 - TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:100 - -if the device doesn't say up -try:: - - /etc/rc.d/init.d/network start - -( this starts the network stack & hopefully calls ifconfig tr0 up ). -ifconfig looks at the output of /proc/net/dev and presents it in a more -presentable form. - -Now ping the device from a machine in the same subnet. - -if the RX packets count & TX packets counts don't increment you probably -have problems. - -next:: - - cat /proc/net/arp - -Do you see any hardware addresses in the cache if not you may have problems. -Next try:: - - ping -c 5 - -i.e. the Bcast field above in the output of -ifconfig. Do you see any replies from machines other than the local machine -if not you may have problems. also if the TX packets count in ifconfig -hasn't incremented either you have serious problems in your driver -(e.g. the txbusy field of the network device being stuck on ) -or you may have multiple network devices connected. - - -chandev -------- -There is a new device layer for channel devices, some -drivers e.g. lcs are registered with this layer. - -If the device uses the channel device layer you'll be -able to find what interrupts it uses & the current state -of the device. - -See the manpage chandev.8 &type cat /proc/chandev for more info. - - -SysRq -===== -This is now supported by linux for s/390 & z/Architecture. - -To enable it do compile the kernel with:: - - Kernel Hacking -> Magic SysRq Key Enabled - -Then:: - - echo "1" > /proc/sys/kernel/sysrq - -also type:: - - echo "8" >/proc/sys/kernel/printk - -To make printk output go to console. - -On 390 all commands are prefixed with:: - - ^- - -e.g.:: - - ^-t will show tasks. - ^-? or some unknown command will display help. - -The sysrq key reading is very picky ( I have to type the keys in an -xterm session & paste them into the x3270 console ) -& it may be wise to predefine the keys as described in the VM hints above - -This is particularly useful for syncing disks unmounting & rebooting -if the machine gets partially hung. - -Read Documentation/admin-guide/sysrq.rst for more info - -References: -=========== -- Enterprise Systems Architecture Reference Summary -- Enterprise Systems Architecture Principles of Operation -- Hartmut Penners s390 stack frame sheet. -- IBM Mainframe Channel Attachment a technology brief from a CISCO webpage -- Various bits of man & info pages of Linux. -- Linux & GDB source. -- Various info & man pages. -- CMS Help on tracing commands. -- Linux for s/390 Elf Application Binary Interface -- Linux for z/Series Elf Application Binary Interface ( Both Highly Recommended ) -- z/Architecture Principles of Operation SA22-7832-00 -- Enterprise Systems Architecture/390 Reference Summary SA22-7209-01 & the -- Enterprise Systems Architecture/390 Principles of Operation SA22-7201-05 - -Special Thanks -============== -Special thanks to Neale Ferguson who maintains a much -prettier HTML version of this page at -http://linuxvm.org/penguinvm/ -Bob Grainger Stefan Bader & others for reporting bugs diff --git a/Documentation/s390/index.rst b/Documentation/s390/index.rst index f8c01cb7fa37..f7af2061e406 100644 --- a/Documentation/s390/index.rst +++ b/Documentation/s390/index.rst @@ -7,7 +7,6 @@ s390 Architecture cds 3270 - debugging390 driver-model monreader qeth -- GitLab From 59793c5ab93fed9661deaf6d8ba054af681c0a6a Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Fri, 2 Aug 2019 12:28:20 +0200 Subject: [PATCH 3814/7155] s390: move vmalloc option parsing to startup code Few other crucial memory setup options are already handled in the startup code. Those values are needed by kaslr and kasan implementations. "vmalloc" is the last piece required for future improvements such as early decision on kernel page levels depth required for actual memory setup, as well as vmalloc memory area access monitoring in kasan. Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_parm.c | 5 +++++ arch/s390/include/asm/pgtable.h | 1 + arch/s390/include/asm/setup.h | 1 + arch/s390/kernel/setup.c | 13 ++----------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 3c49bde8aa5e..449d26a42f3f 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "boot.h" @@ -14,6 +15,7 @@ char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; struct ipl_parameter_block __bootdata_preserved(ipl_block); int __bootdata_preserved(ipl_block_valid); +unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE; unsigned long __bootdata(memory_end); int __bootdata(memory_end_set); int __bootdata(noexec_disabled); @@ -226,6 +228,9 @@ void parse_boot_command_line(void) memory_end_set = 1; } + if (!strcmp(param, "vmalloc")) + vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE); + if (!strcmp(param, "noexec")) { rc = kstrtobool(val, &enabled); if (!rc && !enabled) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 9b274fcaacb6..0c4600725fc2 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -86,6 +86,7 @@ extern unsigned long zero_page_mask; */ extern unsigned long VMALLOC_START; extern unsigned long VMALLOC_END; +#define VMALLOC_DEFAULT_SIZE ((128UL << 30) - MODULES_LEN) extern struct page *vmemmap; #define VMEM_MAX_PHYS ((unsigned long) vmemmap) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index c5cfff7b1f91..a82d5a98428a 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -83,6 +83,7 @@ struct parmarea { extern int noexec_disabled; extern int memory_end_set; extern unsigned long memory_end; +extern unsigned long vmalloc_size; extern unsigned long max_physmem_end; #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2b94b0ad3588..0c3f1cd69ed1 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -99,6 +99,7 @@ int __bootdata_preserved(prot_virt_guest); int __bootdata(noexec_disabled); int __bootdata(memory_end_set); unsigned long __bootdata(memory_end); +unsigned long __bootdata(vmalloc_size); unsigned long __bootdata(max_physmem_end); struct mem_detect_info __bootdata(mem_detect); @@ -302,15 +303,6 @@ void machine_power_off(void) void (*pm_power_off)(void) = machine_power_off; EXPORT_SYMBOL_GPL(pm_power_off); -static int __init parse_vmalloc(char *arg) -{ - if (!arg) - return -EINVAL; - VMALLOC_END = (memparse(arg, &arg) + PAGE_SIZE - 1) & PAGE_MASK; - return 0; -} -early_param("vmalloc", parse_vmalloc); - void *restart_stack __section(.data); unsigned long stack_alloc(void) @@ -563,10 +555,9 @@ static void __init setup_resources(void) static void __init setup_memory_end(void) { - unsigned long vmax, vmalloc_size, tmp; + unsigned long vmax, tmp; /* Choose kernel address space layout: 3 or 4 levels. */ - vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN; if (IS_ENABLED(CONFIG_KASAN)) { vmax = IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING) ? _REGION1_SIZE -- GitLab From c4c3772384bc93e3d1eccd88bd7f5d74de74e0d7 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 6 Aug 2019 19:01:37 +0300 Subject: [PATCH 3815/7155] s390/pci: PCI_IOV_RESOURCES loop refactoring in zpci_map_resources This patch alters the for loop iteration scheme in zpci_map_resources to make it more usual. Thus, the patch generalizes the style for PCI_IOV_RESOURCES iteration and improves readability. Link: http://lkml.kernel.org/r/20190806160137.29275-1-efremov@linux.com Signed-off-by: Denis Efremov Signed-off-by: Sebastian Ott Signed-off-by: Vasily Gorbik --- arch/s390/pci/pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index b0e3b9a0e488..c7fea9bea8cb 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -431,13 +431,13 @@ static void zpci_map_resources(struct pci_dev *pdev) } #ifdef CONFIG_PCI_IOV - i = PCI_IOV_RESOURCES; + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + int bar = i + PCI_IOV_RESOURCES; - for (; i < PCI_SRIOV_NUM_BARS + PCI_IOV_RESOURCES; i++) { - len = pci_resource_len(pdev, i); + len = pci_resource_len(pdev, bar); if (!len) continue; - pdev->resource[i].parent = &iov_res; + pdev->resource[bar].parent = &iov_res; } #endif } -- GitLab From 3434caec5b70519ead87e7b66dbdc18e8dbaa506 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 8 Aug 2019 15:18:17 +0800 Subject: [PATCH 3816/7155] s390/extmem: use refcount_t for refcount Reference counters are preferred to use refcount_t instead of atomic_t. This is because the implementation of refcount_t can prevent overflows and detect possible use-after-free. So convert atomic_t ref counters to refcount_t. Link: http://lkml.kernel.org/r/20190808071817.6595-1-hslester96@gmail.com Signed-off-by: Chuhong Yuan Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/mm/extmem.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 0b5622714c12..fd0dae9d10f4 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,7 @@ struct dcss_segment { char res_name[16]; unsigned long start_addr; unsigned long end; - atomic_t ref_count; + refcount_t ref_count; int do_nonshared; unsigned int vm_segtype; struct qrange range[6]; @@ -362,7 +363,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long seg->start_addr = start_addr; seg->end = end_addr; seg->do_nonshared = do_nonshared; - atomic_set(&seg->ref_count, 1); + refcount_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); *addr = seg->start_addr; *end = seg->end; @@ -422,7 +423,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, rc = __segment_load (name, do_nonshared, addr, end); else { if (do_nonshared == seg->do_nonshared) { - atomic_inc(&seg->ref_count); + refcount_inc(&seg->ref_count); *addr = seg->start_addr; *end = seg->end; rc = seg->vm_segtype; @@ -468,7 +469,7 @@ segment_modify_shared (char *name, int do_nonshared) rc = 0; goto out_unlock; } - if (atomic_read (&seg->ref_count) != 1) { + if (refcount_read(&seg->ref_count) != 1) { pr_warn("DCSS %s is in use and cannot be reloaded\n", name); rc = -EAGAIN; goto out_unlock; @@ -544,7 +545,7 @@ segment_unload(char *name) pr_err("Unloading unknown DCSS %s failed\n", name); goto out_unlock; } - if (atomic_dec_return(&seg->ref_count) != 0) + if (!refcount_dec_and_test(&seg->ref_count)) goto out_unlock; release_resource(seg->res); kfree(seg->res); -- GitLab From 40e90656c13587c0826e8afeef3cebe585db2d2c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 8 Aug 2019 15:18:26 +0800 Subject: [PATCH 3817/7155] s390/mm: use refcount_t for refcount Reference counters are preferred to use refcount_t instead of atomic_t. This is because the implementation of refcount_t can prevent overflows and detect possible use-after-free. So convert atomic_t ref counters to refcount_t. Link: http://lkml.kernel.org/r/20190808071826.6649-1-hslester96@gmail.com Signed-off-by: Chuhong Yuan Reviewed-by: David Hildenbrand Reviewed-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/gmap.h | 4 +++- arch/s390/mm/gmap.c | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h index fcbd638fb9f4..37f96b6f0e61 100644 --- a/arch/s390/include/asm/gmap.h +++ b/arch/s390/include/asm/gmap.h @@ -9,6 +9,8 @@ #ifndef _ASM_S390_GMAP_H #define _ASM_S390_GMAP_H +#include + /* Generic bits for GMAP notification on DAT table entry changes. */ #define GMAP_NOTIFY_SHADOW 0x2 #define GMAP_NOTIFY_MPROT 0x1 @@ -46,7 +48,7 @@ struct gmap { struct radix_tree_root guest_to_host; struct radix_tree_root host_to_guest; spinlock_t guest_table_lock; - atomic_t ref_count; + refcount_t ref_count; unsigned long *table; unsigned long asce; unsigned long asce_end; diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 1e668b95e0c6..3770f12d9252 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -67,7 +67,7 @@ static struct gmap *gmap_alloc(unsigned long limit) INIT_RADIX_TREE(&gmap->host_to_rmap, GFP_ATOMIC); spin_lock_init(&gmap->guest_table_lock); spin_lock_init(&gmap->shadow_lock); - atomic_set(&gmap->ref_count, 1); + refcount_set(&gmap->ref_count, 1); page = alloc_pages(GFP_KERNEL, CRST_ALLOC_ORDER); if (!page) goto out_free; @@ -214,7 +214,7 @@ static void gmap_free(struct gmap *gmap) */ struct gmap *gmap_get(struct gmap *gmap) { - atomic_inc(&gmap->ref_count); + refcount_inc(&gmap->ref_count); return gmap; } EXPORT_SYMBOL_GPL(gmap_get); @@ -227,7 +227,7 @@ EXPORT_SYMBOL_GPL(gmap_get); */ void gmap_put(struct gmap *gmap) { - if (atomic_dec_return(&gmap->ref_count) == 0) + if (refcount_dec_and_test(&gmap->ref_count)) gmap_free(gmap); } EXPORT_SYMBOL_GPL(gmap_put); @@ -1594,7 +1594,7 @@ static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce, continue; if (!sg->initialized) return ERR_PTR(-EAGAIN); - atomic_inc(&sg->ref_count); + refcount_inc(&sg->ref_count); return sg; } return NULL; @@ -1682,7 +1682,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, } } } - atomic_set(&new->ref_count, 2); + refcount_set(&new->ref_count, 2); list_add(&new->list, &parent->children); if (asce & _ASCE_REAL_SPACE) { /* nothing to protect, return right away */ -- GitLab From da9ed30d29c48233cec4a19e2bd794bcaa230341 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 8 Aug 2019 13:50:02 +0200 Subject: [PATCH 3818/7155] s390/startup: add initial pgm check handler The startup code is getting more complicated with features like kaslr and secure boot in place. In a potential unexpected startup code crash case the system would end up in a pgm check loop at address 0, overwriting pgm check old psw value and just making debugging more complicated. To avoid that introduce startup program check handler which is active immediately after kernel start and until early_pgm_check_handler is set in kernel/early.c. So it covers kernel relocation phase and transition to it. This pgm check handler simply saves general/control registers and psw in the save area which should guarantee that we still have something to look at when standalone dumper is called without saving registers. And it does disabled wait with a faulty address in the end. Acked-by: Ilya Leoshkevich Signed-off-by: Vasily Gorbik --- arch/s390/boot/head.S | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 2087bed6e60f..5b79ae7b44f3 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -60,8 +60,10 @@ __HEAD .long 0x02000690,0x60000050 .long 0x020006e0,0x20000050 - .org 0x1a0 + .org __LC_RST_NEW_PSW # 0x1a0 .quad 0,iplstart + .org __LC_PGM_NEW_PSW # 0x1d0 + .quad 0x0000000180000000,startup_pgm_check_handler .org 0x200 @@ -351,6 +353,26 @@ ENTRY(startup_kdump) #include "head_kdump.S" +# +# This program check is active immediately after kernel start +# and until early_pgm_check_handler is set in kernel/early.c +# It simply saves general/control registers and psw in +# the save area and does disabled wait with a faulty address. +# +ENTRY(startup_pgm_check_handler) + stmg %r0,%r15,__LC_SAVE_AREA_SYNC + la %r1,4095 + stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r1) + mvc __LC_GPREGS_SAVE_AREA-4095(128,%r1),__LC_SAVE_AREA_SYNC + mvc __LC_PSW_SAVE_AREA-4095(16,%r1),__LC_PGM_OLD_PSW + lg %r1,__LC_SAVE_AREA_SYNC+8 + mvc __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW + ni __LC_RETURN_PSW,0xfc # remove IO and EX bits + ni __LC_RETURN_PSW+1,0xfb # remove MCHK bit + oi __LC_RETURN_PSW+1,0x2 # set wait state bit + lpswe __LC_RETURN_PSW # disabled wait +ENDPROC(startup_pgm_check_handler) + # # params at 10400 (setup.h) # Must be keept in sync with struct parmarea in setup.h -- GitLab From 19413fe04f49b32c63b470079afef8d1c7995cc1 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Sun, 11 Aug 2019 22:04:54 +0200 Subject: [PATCH 3819/7155] s390/startup: purge obsolete .gitignore patterns sizes.h and vmlinux.scr.lds are not generated since commit 369f91c37451 ("s390/decompressor: rework uncompressed image info collection"). vmlinux.bin.full is not generated since commit 183ab05ff285 ("s390: get rid of the first mb of uncompressed image"). Signed-off-by: Vasily Gorbik --- arch/s390/boot/compressed/.gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore index 45aeb4f08752..e72fcd7ecebb 100644 --- a/arch/s390/boot/compressed/.gitignore +++ b/arch/s390/boot/compressed/.gitignore @@ -1,5 +1,2 @@ -sizes.h vmlinux vmlinux.lds -vmlinux.scr.lds -vmlinux.bin.full -- GitLab From 2e83e0eb85ca62985406920f97ece36d822d421f Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Sun, 11 Aug 2019 20:55:18 +0200 Subject: [PATCH 3820/7155] s390: clean .bss before running uncompressed kernel Clean uncompressed kernel .bss section in the startup code before the uncompressed kernel is executed. At this point of time initrd and certificates have been already rescued. Uncompressed kernel .bss size is known from vmlinux_info. It is also taken into consideration during uncompressed kernel positioning by kaslr (so it is safe to clean it). With that uncompressed kernel is starting with .bss section zeroed and no .bss section usage restrictions apply. Which makes chkbss checks for uncompressed kernel objects obsolete and they can be removed. early_nobss.c is also not needed anymore. Parts of it which are still relevant are moved to early.c. Kasan initialization code is now called directly from head64 (early.c is instrumented and should not be executed before kasan shadow memory is set up). Reviewed-by: Philipp Rudo Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 6 +++++ arch/s390/kernel/Makefile | 13 +--------- arch/s390/kernel/early.c | 16 ++++++++++++ arch/s390/kernel/early_nobss.c | 45 ---------------------------------- arch/s390/kernel/head64.S | 8 +++--- arch/s390/lib/Makefile | 3 --- drivers/s390/char/Makefile | 3 --- 7 files changed, 26 insertions(+), 68 deletions(-) delete mode 100644 arch/s390/kernel/early_nobss.c diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 7b0d05414618..596ca7cc4d7b 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -112,6 +112,11 @@ static void handle_relocs(unsigned long offset) } } +static void clear_bss_section(void) +{ + memset((void *)vmlinux.default_lma + vmlinux.image_size, 0, vmlinux.bss_size); +} + void startup_kernel(void) { unsigned long random_lma; @@ -151,6 +156,7 @@ void startup_kernel(void) } else if (__kaslr_offset) memcpy((void *)vmlinux.default_lma, img, vmlinux.image_size); + clear_bss_section(); copy_bootdata(); if (IS_ENABLED(CONFIG_RELOCATABLE)) handle_relocs(__kaslr_offset); diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 0f255b54b051..7edbbcd8228a 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -10,20 +10,12 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) # Do not trace early setup code CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE) -CFLAGS_REMOVE_early_nobss.o = $(CC_FLAGS_FTRACE) endif GCOV_PROFILE_early.o := n -GCOV_PROFILE_early_nobss.o := n - KCOV_INSTRUMENT_early.o := n -KCOV_INSTRUMENT_early_nobss.o := n - UBSAN_SANITIZE_early.o := n -UBSAN_SANITIZE_early_nobss.o := n - -KASAN_SANITIZE_early_nobss.o := n KASAN_SANITIZE_ipl.o := n KASAN_SANITIZE_machine_kexec.o := n @@ -48,7 +40,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o -obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o early_nobss.o +obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o obj-y += sysinfo.o lgr.o os_info.o machine_kexec.o pgm_check.o obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o @@ -90,6 +82,3 @@ obj-$(CONFIG_TRACEPOINTS) += trace.o # vdso obj-y += vdso64/ obj-$(CONFIG_COMPAT_VDSO) += vdso32/ - -chkbss := head64.o early_nobss.o -include $(srctree)/arch/s390/scripts/Makefile.chkbss diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 6312fed48530..b432d63d0b37 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -32,6 +32,21 @@ #include #include "entry.h" +static void __init reset_tod_clock(void) +{ + u64 time; + + if (store_tod_clock(&time) == 0) + return; + /* TOD clock not running. Set the clock to Unix Epoch. */ + if (set_tod_clock(TOD_UNIX_EPOCH) != 0 || store_tod_clock(&time) != 0) + disabled_wait(); + + memset(tod_clock_base, 0, 16); + *(__u64 *) &tod_clock_base[1] = TOD_UNIX_EPOCH; + S390_lowcore.last_update_clock = TOD_UNIX_EPOCH; +} + /* * Initialize storage key for kernel pages */ @@ -301,6 +316,7 @@ static void __init check_image_bootable(void) void __init startup_init(void) { + reset_tod_clock(); check_image_bootable(); time_early_init(); init_kernel_storage_key(); diff --git a/arch/s390/kernel/early_nobss.c b/arch/s390/kernel/early_nobss.c deleted file mode 100644 index 52a3ef959341..000000000000 --- a/arch/s390/kernel/early_nobss.c +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright IBM Corp. 2007, 2018 - */ - -/* - * Early setup functions which may not rely on an initialized bss - * section. The last thing that is supposed to happen here is - * initialization of the bss section. - */ - -#include -#include -#include -#include -#include -#include -#include "entry.h" - -static void __init reset_tod_clock(void) -{ - u64 time; - - if (store_tod_clock(&time) == 0) - return; - /* TOD clock not running. Set the clock to Unix Epoch. */ - if (set_tod_clock(TOD_UNIX_EPOCH) != 0 || store_tod_clock(&time) != 0) - disabled_wait(); - - memset(tod_clock_base, 0, 16); - *(__u64 *) &tod_clock_base[1] = TOD_UNIX_EPOCH; - S390_lowcore.last_update_clock = TOD_UNIX_EPOCH; -} - -static void __init clear_bss_section(void) -{ - memset(__bss_start, 0, __bss_stop - __bss_start); -} - -void __init startup_init_nobss(void) -{ - reset_tod_clock(); - clear_bss_section(); - kasan_early_init(); -} diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 5aea1a527443..143ed71221fe 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -34,11 +34,9 @@ ENTRY(startup_continue) larl %r14,init_task stg %r14,__LC_CURRENT larl %r15,init_thread_union+THREAD_SIZE-STACK_FRAME_OVERHEAD -# -# Early setup functions that may not rely on an initialized bss section, -# like moving the initrd. Returns with an initialized bss section. -# - brasl %r14,startup_init_nobss +#ifdef CONFIG_KASAN + brasl %r14,kasan_early_init +#endif # # Early machine initialization and detection functions. # diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index a1ec63abfb95..d7c218e8b559 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -11,6 +11,3 @@ lib-$(CONFIG_UPROBES) += probes.o # Instrumenting memory accesses to __user data (in different address space) # produce false positives KASAN_SANITIZE_uaccess.o := n - -chkbss := mem.o -include $(srctree)/arch/s390/scripts/Makefile.chkbss diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index b8a8816d94e7..845e12ac5954 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -49,6 +49,3 @@ obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o obj-$(CONFIG_HMC_DRV) += hmcdrv.o - -chkbss := sclp_early_core.o -include $(srctree)/arch/s390/scripts/Makefile.chkbss -- GitLab From f45f7b5bdaa4828ce871cf03f7c01599a0de57a5 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Mon, 12 Aug 2019 15:52:07 +0200 Subject: [PATCH 3821/7155] s390/kasan: provide uninstrumented __strlen s390 kasan code uses sclp_early_printk to report initialization failures. The code doing that should not be instrumented, because kasan shadow memory has not been set up yet. Even though sclp_early_core.c is compiled with instrumentation disabled it uses strlen function, which is instrumented and would produce shadow memory access if used. To avoid that, introduce uninstrumented __strlen function to be used instead. Before commit 7e0d92f00246 ("s390/kasan: improve string/memory functions checks") few string functions (including strlen) were escaping kasan instrumentation due to usage of platform specific versions which are implemented in inline assembly. Fixes: 7e0d92f00246 ("s390/kasan: improve string/memory functions checks") Acked-by: Ilya Leoshkevich Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/string.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index 70d87db54e62..4c0690fc5167 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h @@ -71,11 +71,16 @@ extern void *__memmove(void *dest, const void *src, size_t n); #define memcpy(dst, src, len) __memcpy(dst, src, len) #define memmove(dst, src, len) __memmove(dst, src, len) #define memset(s, c, n) __memset(s, c, n) +#define strlen(s) __strlen(s) + +#define __no_sanitize_prefix_strfunc(x) __##x #ifndef __NO_FORTIFY #define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */ #endif +#else +#define __no_sanitize_prefix_strfunc(x) x #endif /* defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) */ void *__memset16(uint16_t *s, uint16_t v, size_t count); @@ -163,8 +168,8 @@ static inline char *strcpy(char *dst, const char *src) } #endif -#ifdef __HAVE_ARCH_STRLEN -static inline size_t strlen(const char *s) +#if defined(__HAVE_ARCH_STRLEN) || (defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)) +static inline size_t __no_sanitize_prefix_strfunc(strlen)(const char *s) { register unsigned long r0 asm("0") = 0; const char *tmp = s; -- GitLab From 8769f610fe6d473e5e8e221709c3ac402037da6c Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Tue, 13 Aug 2019 20:11:08 +0200 Subject: [PATCH 3822/7155] s390/process: avoid potential reading of freed stack With THREAD_INFO_IN_TASK (which is selected on s390) task's stack usage is refcounted and should always be protected by get/put when touching other task's stack to avoid race conditions with task's destruction code. Fixes: d5c352cdd022 ("s390: move thread_info into task_struct") Cc: stable@vger.kernel.org # v4.10+ Acked-by: Ilya Leoshkevich Signed-off-by: Vasily Gorbik --- arch/s390/kernel/process.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 63873aa6693f..9f2727bf3cbe 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -184,20 +184,30 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING || !task_stack_page(p)) return 0; + + if (!try_get_task_stack(p)) + return 0; + low = task_stack_page(p); high = (struct stack_frame *) task_pt_regs(p); sf = (struct stack_frame *) p->thread.ksp; - if (sf <= low || sf > high) - return 0; + if (sf <= low || sf > high) { + return_address = 0; + goto out; + } for (count = 0; count < 16; count++) { sf = (struct stack_frame *) sf->back_chain; - if (sf <= low || sf > high) - return 0; + if (sf <= low || sf > high) { + return_address = 0; + goto out; + } return_address = sf->gprs[8]; if (!in_sched_functions(return_address)) - return return_address; + goto out; } - return 0; +out: + put_task_stack(p); + return return_address; } unsigned long arch_align_stack(unsigned long sp) -- GitLab From 2c7fa8a11cc528e49e88352fce8cf083104b3797 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Tue, 13 Aug 2019 19:23:51 +0200 Subject: [PATCH 3823/7155] s390/kasan: avoid report in get_wchan Reading other running task's stack can be a dangerous endeavor. Kasan stack memory access instrumentation includes special prologue and epilogue to mark/remove red zones in shadow memory between stack variables. For that reason there is always a race between a task reading value in other task's stack and that other task returning from a function and entering another one generating different red zones pattern. To avoid kasan reports simply perform uninstrumented memory reads. Acked-by: Ilya Leoshkevich Signed-off-by: Vasily Gorbik --- arch/s390/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 9f2727bf3cbe..b0afec673f77 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -196,12 +196,12 @@ unsigned long get_wchan(struct task_struct *p) goto out; } for (count = 0; count < 16; count++) { - sf = (struct stack_frame *) sf->back_chain; + sf = (struct stack_frame *)READ_ONCE_NOCHECK(sf->back_chain); if (sf <= low || sf > high) { return_address = 0; goto out; } - return_address = sf->gprs[8]; + return_address = READ_ONCE_NOCHECK(sf->gprs[8]); if (!in_sched_functions(return_address)) goto out; } -- GitLab From e991e5bb11d6eacf8a49867ff9d4ec6e1cde3718 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Wed, 14 Aug 2019 14:27:44 +0200 Subject: [PATCH 3824/7155] s390/stacktrace: use common arch_stack_walk infrastructure Use common arch_stack_walk infrastructure to avoid duplicated code and avoid taking care of the stack storage and filtering. Common code also uses try_get_task_stack/put_task_stack when needed which have been missing in our code, which also solves potential problem for us. Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 1 + arch/s390/kernel/stacktrace.c | 50 +++++------------------------------ 2 files changed, 7 insertions(+), 44 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a4ad2733eedf..3289cc243d92 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -105,6 +105,7 @@ config S390 select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE select ARCH_KEEP_MEMBLOCK select ARCH_SAVE_PAGE_KEYS if HIBERNATION + select ARCH_STACKWALK select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_USE_BUILTIN_BSWAP diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index f6a620f854e1..f8fc4f8aef9b 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c @@ -6,57 +6,19 @@ * Author(s): Heiko Carstens */ -#include -#include #include -#include -#include #include #include -void save_stack_trace(struct stack_trace *trace) +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, + struct task_struct *task, struct pt_regs *regs) { struct unwind_state state; + unsigned long addr; - unwind_for_each_frame(&state, current, NULL, 0) { - if (trace->nr_entries >= trace->max_entries) + unwind_for_each_frame(&state, task, regs, 0) { + addr = unwind_get_return_address(&state); + if (!addr || !consume_entry(cookie, addr, false)) break; - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = state.ip; } } -EXPORT_SYMBOL_GPL(save_stack_trace); - -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) -{ - struct unwind_state state; - - unwind_for_each_frame(&state, tsk, NULL, 0) { - if (trace->nr_entries >= trace->max_entries) - break; - if (in_sched_functions(state.ip)) - continue; - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = state.ip; - } -} -EXPORT_SYMBOL_GPL(save_stack_trace_tsk); - -void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) -{ - struct unwind_state state; - - unwind_for_each_frame(&state, current, regs, 0) { - if (trace->nr_entries >= trace->max_entries) - break; - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = state.ip; - } -} -EXPORT_SYMBOL_GPL(save_stack_trace_regs); -- GitLab From 80ef517b018257220f14410004ede094c577c276 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 15 Aug 2019 14:49:02 +0200 Subject: [PATCH 3825/7155] s390/startup: adjust _sdma and _edma to page boundaries Move .dma.text section alignment out of section description, otherwise zeros used to align the section are included in the section itself (and section is not really aligned by itself). $ objdump -h arch/s390/boot/compressed/vmlinux 5 .dma.text 00001e38 000000000001b1c8 000000000001b1c8 0001c1c8 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 6 .dma.ex_table 00000018 000000000001d000 000000000001d000 0001e000 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .dma.data 00000240 000000000001d080 000000000001d080 0001e080 2**7 CONTENTS, ALLOC, LOAD, DATA $ cat /sys/kernel/debug/memblock/reserved 0: 0x0000000000000000..0x0000000000011fff 1: 0x000000000001b1c8..0x000000000001d2bf ... Also add alignment before _edma linker symbol definition, so that entire .dma* region is rounded up to page boundaries. $ objdump -h arch/s390/boot/compressed/vmlinux 5 .dma.text 00001000 000000000001c000 000000000001c000 0001d000 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 6 .dma.ex_table 00000018 000000000001d000 000000000001d000 0001e000 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .dma.data 00000240 000000000001d080 000000000001d080 0001e080 2**7 CONTENTS, ALLOC, LOAD, DATA $ cat /sys/kernel/debug/memblock/reserved 0: 0x0000000000000000..0x0000000000011fff 1: 0x000000000001c000..0x000000000001dfff ... $ cat /sys/kernel/debug/kernel_page_tables ---[ Identity Mapping ]--- 0x0000000000000000-0x000000000001c000 112K PTE RW NX 0x000000000001c000-0x000000000001d000 4K PTE RO X 0x000000000001d000-0x0000000000100000 908K PTE RW NX ... Reviewed-by: Gerald Schaefer Signed-off-by: Vasily Gorbik --- arch/s390/boot/compressed/vmlinux.lds.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index 635217eb3d91..44561b2c3712 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -37,9 +37,9 @@ SECTIONS * .dma section for code, data, ex_table that need to stay below 2 GB, * even when the kernel is relocate: above 2 GB. */ + . = ALIGN(PAGE_SIZE); _sdma = .; .dma.text : { - . = ALIGN(PAGE_SIZE); _stext_dma = .; *(.dma.text) . = ALIGN(PAGE_SIZE); @@ -52,6 +52,7 @@ SECTIONS _stop_dma_ex_table = .; } .dma.data : { *(.dma.data) } + . = ALIGN(PAGE_SIZE); _edma = .; BOOT_DATA -- GitLab From 22a33c7e4ed6aae8c47de72461162021dad87473 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Fri, 16 Aug 2019 10:43:55 +0200 Subject: [PATCH 3826/7155] s390/startup: round down "mem" option to page boundary Make a usable value out of "mem" option once and for all. Kasan memory allocator just takes memory_end or online memory size as allocation base. If memory_end is not aligned paging structures allocated in kasan end up unaligned as well. So this change fixes potential kasan crash as well. Fixes: 78333d1f908a ("s390/kasan: add support for mem= kernel parameter") Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_parm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 449d26a42f3f..4a052a844f9b 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -224,7 +224,7 @@ void parse_boot_command_line(void) args = next_arg(args, ¶m, &val); if (!strcmp(param, "mem")) { - memory_end = memparse(val, NULL); + memory_end = round_down(memparse(val, NULL), PAGE_SIZE); memory_end_set = 1; } -- GitLab From 183cb46954dd204e3578a25ad1284aab3debec52 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 3 Jul 2019 13:09:03 +0200 Subject: [PATCH 3827/7155] s390/pkey: pkey cleanup: narrow in-kernel API, fix some variable types There are a lot of pkey functions exported as in-kernel callable API functions but not used at all. This patch narrows down the pkey in-kernel API to what is currently only used and exploited. Within the kernel just use u32 without any leading __u32. Also functions declared in a header file in arch/s390/include/asm don't need a comment 'In-kernel API', this is by definition, otherwise the header file would be in arch/s390/include/uapi/asm. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/pkey.h | 114 +-------------------------------- drivers/s390/crypto/pkey_api.c | 37 +++++------ 2 files changed, 18 insertions(+), 133 deletions(-) diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h index 9b6e79077866..dd3d20c332ac 100644 --- a/arch/s390/include/asm/pkey.h +++ b/arch/s390/include/asm/pkey.h @@ -2,7 +2,7 @@ /* * Kernelspace interface to the pkey device driver * - * Copyright IBM Corp. 2016 + * Copyright IBM Corp. 2016,2019 * * Author: Harald Freudenberger * @@ -15,116 +15,6 @@ #include #include -/* - * Generate (AES) random secure key. - * @param cardnr may be -1 (use default card) - * @param domain may be -1 (use default domain) - * @param keytype one of the PKEY_KEYTYPE values - * @param seckey pointer to buffer receiving the secure key - * @return 0 on success, negative errno value on failure - */ -int pkey_genseckey(__u16 cardnr, __u16 domain, - __u32 keytype, struct pkey_seckey *seckey); - -/* - * Generate (AES) secure key with given key value. - * @param cardnr may be -1 (use default card) - * @param domain may be -1 (use default domain) - * @param keytype one of the PKEY_KEYTYPE values - * @param clrkey pointer to buffer with clear key data - * @param seckey pointer to buffer receiving the secure key - * @return 0 on success, negative errno value on failure - */ -int pkey_clr2seckey(__u16 cardnr, __u16 domain, __u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_seckey *seckey); - -/* - * Derive (AES) proteced key from the (AES) secure key blob. - * @param cardnr may be -1 (use default card) - * @param domain may be -1 (use default domain) - * @param seckey pointer to buffer with the input secure key - * @param protkey pointer to buffer receiving the protected key and - * additional info (type, length) - * @return 0 on success, negative errno value on failure - */ -int pkey_sec2protkey(__u16 cardnr, __u16 domain, - const struct pkey_seckey *seckey, - struct pkey_protkey *protkey); - -/* - * Derive (AES) protected key from a given clear key value. - * @param keytype one of the PKEY_KEYTYPE values - * @param clrkey pointer to buffer with clear key data - * @param protkey pointer to buffer receiving the protected key and - * additional info (type, length) - * @return 0 on success, negative errno value on failure - */ -int pkey_clr2protkey(__u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_protkey *protkey); - -/* - * Search for a matching crypto card based on the Master Key - * Verification Pattern provided inside a secure key. - * @param seckey pointer to buffer with the input secure key - * @param cardnr pointer to cardnr, receives the card number on success - * @param domain pointer to domain, receives the domain number on success - * @param verify if set, always verify by fetching verification pattern - * from card - * @return 0 on success, negative errno value on failure. If no card could be - * found, -ENODEV is returned. - */ -int pkey_findcard(const struct pkey_seckey *seckey, - __u16 *cardnr, __u16 *domain, int verify); - -/* - * Find card and transform secure key to protected key. - * @param seckey pointer to buffer with the input secure key - * @param protkey pointer to buffer receiving the protected key and - * additional info (type, length) - * @return 0 on success, negative errno value on failure - */ -int pkey_skey2pkey(const struct pkey_seckey *seckey, - struct pkey_protkey *protkey); - -/* - * Verify the given secure key for being able to be useable with - * the pkey module. Check for correct key type and check for having at - * least one crypto card being able to handle this key (master key - * or old master key verification pattern matches). - * Return some info about the key: keysize in bits, keytype (currently - * only AES), flag if key is wrapped with an old MKVP. - * @param seckey pointer to buffer with the input secure key - * @param pcardnr pointer to cardnr, receives the card number on success - * @param pdomain pointer to domain, receives the domain number on success - * @param pkeysize pointer to keysize, receives the bitsize of the key - * @param pattributes pointer to attributes, receives additional info - * PKEY_VERIFY_ATTR_AES if the key is an AES key - * PKEY_VERIFY_ATTR_OLD_MKVP if key has old mkvp stored in - * @return 0 on success, negative errno value on failure. If no card could - * be found which is able to handle this key, -ENODEV is returned. - */ -int pkey_verifykey(const struct pkey_seckey *seckey, - u16 *pcardnr, u16 *pdomain, - u16 *pkeysize, u32 *pattributes); - -/* - * In-kernel API: Generate (AES) random protected key. - * @param keytype one of the PKEY_KEYTYPE values - * @param protkey pointer to buffer receiving the protected key - * @return 0 on success, negative errno value on failure - */ -int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey); - -/* - * In-kernel API: Verify an (AES) protected key. - * @param protkey pointer to buffer containing the protected key to verify - * @return 0 on success, negative errno value on failure. In case the protected - * key is not valid -EKEYREJECTED is returned - */ -int pkey_verifyprotkey(const struct pkey_protkey *protkey); - /* * In-kernel API: Transform an key blob (of any type) into a protected key. * @param key pointer to a buffer containing the key blob @@ -132,7 +22,7 @@ int pkey_verifyprotkey(const struct pkey_protkey *protkey); * @param protkey pointer to buffer receiving the protected key * @return 0 on success, negative errno value on failure */ -int pkey_keyblob2pkey(const __u8 *key, __u32 keylen, +int pkey_keyblob2pkey(const u8 *key, u32 keylen, struct pkey_protkey *protkey); #endif /* _KAPI_PKEY_H */ diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 9f7c26b6ca04..cd7e654bd18e 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -2,7 +2,7 @@ /* * pkey device driver * - * Copyright IBM Corp. 2017 + * Copyright IBM Corp. 2017,2019 * Author(s): Harald Freudenberger */ @@ -71,9 +71,9 @@ struct protaeskeytoken { /* * Create a protected key from a clear key value. */ -int pkey_clr2protkey(u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_protkey *protkey) +static int pkey_clr2protkey(u32 keytype, + const struct pkey_clrkey *clrkey, + struct pkey_protkey *protkey) { long fc; int keysize; @@ -122,13 +122,12 @@ int pkey_clr2protkey(u32 keytype, return 0; } -EXPORT_SYMBOL(pkey_clr2protkey); /* * Find card and transform secure key into protected key. */ -int pkey_skey2pkey(const struct pkey_seckey *seckey, - struct pkey_protkey *pkey) +static int pkey_skey2pkey(const struct pkey_seckey *seckey, + struct pkey_protkey *pkey) { u16 cardnr, domain; int rc, verify; @@ -157,14 +156,13 @@ int pkey_skey2pkey(const struct pkey_seckey *seckey, return rc; } -EXPORT_SYMBOL(pkey_skey2pkey); /* * Verify key and give back some info about the key. */ -int pkey_verifykey(const struct pkey_seckey *seckey, - u16 *pcardnr, u16 *pdomain, - u16 *pkeysize, u32 *pattributes) +static int pkey_verifykey(const struct pkey_seckey *seckey, + u16 *pcardnr, u16 *pdomain, + u16 *pkeysize, u32 *pattributes) { struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; u16 cardnr, domain; @@ -201,12 +199,11 @@ int pkey_verifykey(const struct pkey_seckey *seckey, DEBUG_DBG("%s rc=%d\n", __func__, rc); return rc; } -EXPORT_SYMBOL(pkey_verifykey); /* * Generate a random protected key */ -int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) +static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) { struct pkey_clrkey clrkey; int keysize; @@ -241,12 +238,11 @@ int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) return 0; } -EXPORT_SYMBOL(pkey_genprotkey); /* * Verify if a protected key is still valid */ -int pkey_verifyprotkey(const struct pkey_protkey *protkey) +static int pkey_verifyprotkey(const struct pkey_protkey *protkey) { unsigned long fc; struct { @@ -287,12 +283,11 @@ int pkey_verifyprotkey(const struct pkey_protkey *protkey) return 0; } -EXPORT_SYMBOL(pkey_verifyprotkey); /* * Transform a non-CCA key token into a protected key */ -static int pkey_nonccatok2pkey(const __u8 *key, __u32 keylen, +static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, struct pkey_protkey *protkey) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -320,7 +315,7 @@ static int pkey_nonccatok2pkey(const __u8 *key, __u32 keylen, /* * Transform a CCA internal key token into a protected key */ -static int pkey_ccainttok2pkey(const __u8 *key, __u32 keylen, +static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, struct pkey_protkey *protkey) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -342,7 +337,7 @@ static int pkey_ccainttok2pkey(const __u8 *key, __u32 keylen, /* * Transform a key blob (of any type) into a protected key */ -int pkey_keyblob2pkey(const __u8 *key, __u32 keylen, +int pkey_keyblob2pkey(const u8 *key, u32 keylen, struct pkey_protkey *protkey) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -507,8 +502,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, case PKEY_KBLOB2PROTK: { struct pkey_kblob2pkey __user *utp = (void __user *) arg; struct pkey_kblob2pkey ktp; - __u8 __user *ukey; - __u8 *kkey; + u8 __user *ukey; + u8 *kkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) return -EFAULT; -- GitLab From 4da57a2fea064f662c29e77da043baebb8d6cdc8 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Tue, 18 Jun 2019 15:53:12 +0200 Subject: [PATCH 3828/7155] s390/zcrypt: extend cca_findcard function and helper Rework and extension of the cca_findcard function to be prepared for other types of secure key blobs. Split the function and extract an internal function which has no awareness of key blobs any more. Improve this function and the helper code around to be able to check for a minimal crypto card hardware level (Background: the newer AES cipher keys need to match to the master key verification pattern and need to have a crypto card CEX6 or higher). No API change, neither for the in-kernel API nor the ioctl interface. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_api.c | 28 +++++++++++ drivers/s390/crypto/zcrypt_api.h | 7 +-- drivers/s390/crypto/zcrypt_ccamisc.c | 69 ++++++++++++++++++++-------- drivers/s390/crypto/zcrypt_ccamisc.h | 3 +- 4 files changed, 83 insertions(+), 24 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 69ac7bf09a57..563801427fe4 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -1161,6 +1161,34 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus) } EXPORT_SYMBOL(zcrypt_device_status_mask_ext); +int zcrypt_device_status_ext(int card, int queue, + struct zcrypt_device_status_ext *devstat) +{ + struct zcrypt_card *zc; + struct zcrypt_queue *zq; + + memset(devstat, 0, sizeof(*devstat)); + + spin_lock(&zcrypt_list_lock); + for_each_zcrypt_card(zc) { + for_each_zcrypt_queue(zq, zc) { + if (card == AP_QID_CARD(zq->queue->qid) && + queue == AP_QID_QUEUE(zq->queue->qid)) { + devstat->hwtype = zc->card->ap_dev.device_type; + devstat->functions = zc->card->functions >> 26; + devstat->qid = zq->queue->qid; + devstat->online = zq->online ? 0x01 : 0x00; + spin_unlock(&zcrypt_list_lock); + return 0; + } + } + } + spin_unlock(&zcrypt_list_lock); + + return -ENODEV; +} +EXPORT_SYMBOL(zcrypt_device_status_ext); + static void zcrypt_status_mask(char status[], size_t max_adapters) { struct zcrypt_card *zc; diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index af67a768a3fc..2d3f2732344f 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -121,9 +121,6 @@ void zcrypt_card_get(struct zcrypt_card *); int zcrypt_card_put(struct zcrypt_card *); int zcrypt_card_register(struct zcrypt_card *); void zcrypt_card_unregister(struct zcrypt_card *); -struct zcrypt_card *zcrypt_card_get_best(unsigned int *, - unsigned int, unsigned int); -void zcrypt_card_put_best(struct zcrypt_card *, unsigned int); struct zcrypt_queue *zcrypt_queue_alloc(size_t); void zcrypt_queue_free(struct zcrypt_queue *); @@ -132,8 +129,6 @@ int zcrypt_queue_put(struct zcrypt_queue *); int zcrypt_queue_register(struct zcrypt_queue *); void zcrypt_queue_unregister(struct zcrypt_queue *); void zcrypt_queue_force_online(struct zcrypt_queue *, int); -struct zcrypt_queue *zcrypt_queue_get_best(unsigned int, unsigned int); -void zcrypt_queue_put_best(struct zcrypt_queue *, unsigned int); int zcrypt_rng_device_add(void); void zcrypt_rng_device_remove(void); @@ -145,5 +140,7 @@ int zcrypt_api_init(void); void zcrypt_api_exit(void); long zcrypt_send_cprb(struct ica_xcRB *xcRB); void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus); +int zcrypt_device_status_ext(int card, int queue, + struct zcrypt_device_status_ext *devstatus); #endif /* _ZCRYPT_API_H_ */ diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 9dd31577ce47..9b7a866141b8 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -779,7 +779,17 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) int rc, found = 0; size_t rlen, vlen; u8 *rarray, *varray, *pg; + struct zcrypt_device_status_ext devstat; + memset(ci, 0, sizeof(*ci)); + + /* get first info from zcrypt device driver about this apqn */ + rc = zcrypt_device_status_ext(cardnr, domain, &devstat); + if (rc) + return rc; + ci->hwtype = devstat.hwtype; + + /* prep page for rule array and var array use */ pg = (u8 *) __get_free_page(GFP_KERNEL); if (!pg) return -ENOMEM; @@ -787,10 +797,10 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) varray = pg + PAGE_SIZE/2; rlen = vlen = PAGE_SIZE/2; + /* QF for this card/domain */ rc = cca_query_crypto_facility(cardnr, domain, "STATICSA", rarray, &rlen, varray, &vlen); if (rc == 0 && rlen >= 10*8 && vlen >= 204) { - memset(ci, 0, sizeof(*ci)); memcpy(ci->serial, rarray, 8); ci->new_mk_state = (char) rarray[7*8]; ci->cur_mk_state = (char) rarray[8*8]; @@ -828,23 +838,19 @@ int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify) EXPORT_SYMBOL(cca_get_info); /* - * Search for a matching crypto card based on the Master Key - * Verification Pattern provided inside a secure key. - * Returns < 0 on failure, 0 if CURRENT MKVP matches and - * 1 if OLD MKVP matches. + * Search for a matching crypto card based on the + * Master Key Verification Pattern given. */ -int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) +static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, + int verify, int minhwtype) { - const struct secaeskeytoken *t = (const struct secaeskeytoken *) seckey; struct zcrypt_device_status_ext *device_status; u16 card, dom; struct cca_info ci; int i, rc, oi = -1; - /* some simple checks of the given secure key token */ - if (t->type != TOKTYPE_CCA_INTERNAL || - t->version != TOKVER_CCA_AES || - t->mkvp == 0) + /* mkvp must not be zero, minhwtype needs to be >= 0 */ + if (mkvp == 0 || minhwtype < 0) return -EINVAL; /* fetch status of all crypto cards */ @@ -863,15 +869,17 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) device_status[i].functions & 0x04) { /* enabled CCA card, check current mkvp from cache */ if (cca_info_cache_fetch(card, dom, &ci) == 0 && + ci.hwtype >= minhwtype && ci.cur_mk_state == '2' && - ci.cur_mkvp == t->mkvp) { + ci.cur_mkvp == mkvp) { if (!verify) break; /* verify: refresh card info */ if (fetch_cca_info(card, dom, &ci) == 0) { cca_info_cache_update(card, dom, &ci); - if (ci.cur_mk_state == '2' && - ci.cur_mkvp == t->mkvp) + if (ci.hwtype >= minhwtype && + ci.cur_mk_state == '2' && + ci.cur_mkvp == mkvp) break; } } @@ -892,11 +900,13 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) /* fresh fetch mkvp from adapter */ if (fetch_cca_info(card, dom, &ci) == 0) { cca_info_cache_update(card, dom, &ci); - if (ci.cur_mk_state == '2' && - ci.cur_mkvp == t->mkvp) + if (ci.hwtype >= minhwtype && + ci.cur_mk_state == '2' && + ci.cur_mkvp == mkvp) break; - if (ci.old_mk_state == '2' && - ci.old_mkvp == t->mkvp && + if (ci.hwtype >= minhwtype && + ci.old_mk_state == '2' && + ci.old_mkvp == mkvp && oi < 0) oi = i; } @@ -919,6 +929,29 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) kfree(device_status); return rc; } + +/* + * Search for a matching crypto card based on the Master Key + * Verification Pattern provided inside a secure key token. + */ +int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) +{ + u64 mkvp; + const struct keytoken_header *hdr = (struct keytoken_header *) key; + + if (hdr->type != TOKTYPE_CCA_INTERNAL) + return -EINVAL; + + switch (hdr->version) { + case TOKVER_CCA_AES: + mkvp = ((struct secaeskeytoken *)key)->mkvp; + break; + default: + return -EINVAL; + } + + return findcard(mkvp, pcardnr, pdomain, verify, 0); +} EXPORT_SYMBOL(cca_findcard); void __exit zcrypt_ccamisc_exit(void) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index d92fb731602a..e6f41e5baf18 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -88,10 +88,11 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, * Returns < 0 on failure, 0 if CURRENT MKVP matches and * 1 if OLD MKVP matches. */ -int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify); +int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify); /* struct to hold info for each CCA queue */ struct cca_info { + int hwtype; /* one of the defined AP_DEVICE_TYPE_* */ char new_mk_state; /* '1' empty, '2' partially full, '3' full */ char cur_mk_state; /* '1' invalid, '2' valid */ char old_mk_state; /* '1' invalid, '2' valid */ -- GitLab From 4bc123b18ce6ae6c42c69d0456b5acbd2f7bc8bd Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 3 Jul 2019 13:16:51 +0200 Subject: [PATCH 3829/7155] s390/zcrypt: Add low level functions for CCA AES cipher keys This patch adds low level functions, structs and defines to support CCA AES cipher keys: - struct cipherkeytoken can be used for an inside view of the CCA AES cipher key token blob. - function cca_cipher2protkey() derives an CPACF protected key from an CCA AES cipher key. - function cca_gencipherkey() generates an CCA AES cipher key with random value. - function cca_findcard2() constructs a list of apqns based on input constrains like min hardware type, mkvp values. - cca_check_secaescipherkey() does a check on the given CCA AES cipher key blob. - cca_clr2cipherkey() generates an CCA AES cipher key from a given clear key value. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_ccamisc.c | 800 ++++++++++++++++++++++++++- drivers/s390/crypto/zcrypt_ccamisc.h | 107 +++- 2 files changed, 903 insertions(+), 4 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 9b7a866141b8..88c5f4a56be7 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -45,13 +46,12 @@ static LIST_HEAD(cca_info_list); static DEFINE_SPINLOCK(cca_info_list_lock); /* - * Simple check if the token is a valid CCA secure AES key + * Simple check if the token is a valid CCA secure AES data key * token. If keybitsize is given, the bitsize of the key is * also checked. Returns 0 on success or errno value on failure. */ int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, const u8 *token, int keybitsize) - { struct secaeskeytoken *t = (struct secaeskeytoken *) token; @@ -82,6 +82,96 @@ int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, } EXPORT_SYMBOL(cca_check_secaeskeytoken); +/* + * Simple check if the token is a valid CCA secure AES cipher key + * token. If keybitsize is given, the bitsize of the key is + * also checked. If checkcpacfexport is enabled, the key is also + * checked for the export flag to allow CPACF export. + * Returns 0 on success or errno value on failure. + */ +int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, + const u8 *token, int keybitsize, + int checkcpacfexport) +{ + struct cipherkeytoken *t = (struct cipherkeytoken *) token; + bool keybitsizeok = true; + +#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) + + if (t->type != TOKTYPE_CCA_INTERNAL) { + if (dbg) + DBF("%s token check failed, type 0x%02x != 0x%02x\n", + __func__, (int) t->type, TOKTYPE_CCA_INTERNAL); + return -EINVAL; + } + if (t->version != TOKVER_CCA_VLSC) { + if (dbg) + DBF("%s token check failed, version 0x%02x != 0x%02x\n", + __func__, (int) t->version, TOKVER_CCA_VLSC); + return -EINVAL; + } + if (t->algtype != 0x02) { + if (dbg) + DBF("%s token check failed, algtype 0x%02x != 0x02\n", + __func__, (int) t->algtype); + return -EINVAL; + } + if (t->keytype != 0x0001) { + if (dbg) + DBF("%s token check failed, keytype 0x%04x != 0x0001\n", + __func__, (int) t->keytype); + return -EINVAL; + } + if (t->plfver != 0x00 && t->plfver != 0x01) { + if (dbg) + DBF("%s token check failed, unknown plfver 0x%02x\n", + __func__, (int) t->plfver); + return -EINVAL; + } + if (t->wpllen != 512 && t->wpllen != 576 && t->wpllen != 640) { + if (dbg) + DBF("%s token check failed, unknown wpllen %d\n", + __func__, (int) t->wpllen); + return -EINVAL; + } + if (keybitsize > 0) { + switch (keybitsize) { + case 128: + if (t->wpllen != (t->plfver ? 640 : 512)) + keybitsizeok = false; + break; + case 192: + if (t->wpllen != (t->plfver ? 640 : 576)) + keybitsizeok = false; + break; + case 256: + if (t->wpllen != 640) + keybitsizeok = false; + break; + default: + keybitsizeok = false; + break; + } + if (!keybitsizeok) { + if (dbg) + DBF("%s token check failed, bitsize %d\n", + __func__, keybitsize); + return -EINVAL; + } + } + if (checkcpacfexport && !(t->kmf1 & KMF1_XPRT_CPAC)) { + if (dbg) + DBF("%s token check failed, XPRT_CPAC bit is 0\n", + __func__); + return -EINVAL; + } + +#undef DBF + + return 0; +} +EXPORT_SYMBOL(cca_check_secaescipherkey); + /* * Allocate consecutive memory for request CPRB, request param * block, reply CPRB and reply param block and fill in values @@ -441,7 +531,8 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, } /* copy the generated secure key token */ - memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); + if (seckey) + memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); out: free_cprbmem(mem, PARMBSIZE, 1); @@ -594,6 +685,623 @@ int cca_sec2protkey(u16 cardnr, u16 domain, } EXPORT_SYMBOL(cca_sec2protkey); +/* + * AES cipher key skeleton created with CSNBKTB2 with these flags: + * INTERNAL, NO-KEY, AES, CIPHER, ANY-MODE, NOEX-SYM, NOEXAASY, + * NOEXUASY, XPRTCPAC, NOEX-RAW, NOEX-DES, NOEX-AES, NOEX-RSA + * used by cca_gencipherkey() and cca_clr2cipherkey(). + */ +static const u8 aes_cipher_key_skeleton[] = { + 0x01, 0x00, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x01, 0x02, 0xc0, 0x00, 0xff, + 0x00, 0x03, 0x08, 0xc8, 0x00, 0x00, 0x00, 0x00 }; +#define SIZEOF_SKELETON (sizeof(aes_cipher_key_skeleton)) + +/* + * Generate (random) CCA AES CIPHER secure key. + */ +int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize) +{ + int rc; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct gkreqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + char rule_array[2*8]; + struct { + u16 len; + u8 key_type_1[8]; + u8 key_type_2[8]; + u16 clear_key_bit_len; + u16 key_name_1_len; + u16 key_name_2_len; + u16 user_data_1_len; + u16 user_data_2_len; + u8 key_name_1[0]; + u8 key_name_2[0]; + u8 user_data_1[0]; + u8 user_data_2[0]; + } vud; + struct { + u16 len; + struct { + u16 len; + u16 flag; + u8 kek_id_1[0]; + } tlv1; + struct { + u16 len; + u16 flag; + u8 kek_id_2[0]; + } tlv2; + struct { + u16 len; + u16 flag; + u8 gen_key_id_1[SIZEOF_SKELETON]; + } tlv3; + struct { + u16 len; + u16 flag; + u8 gen_key_id_1_label[0]; + } tlv4; + struct { + u16 len; + u16 flag; + u8 gen_key_id_2[0]; + } tlv5; + struct { + u16 len; + u16 flag; + u8 gen_key_id_2_label[0]; + } tlv6; + } kb; + } __packed * preqparm; + struct gkrepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct { + u16 len; + } vud; + struct { + u16 len; + struct { + u16 len; + u16 flag; + u8 gen_key[0]; /* 120-136 bytes */ + } tlv1; + } kb; + } __packed * prepparm; + struct cipherkeytoken *t; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + preqcblk->req_parml = sizeof(struct gkreqparm); + + /* prepare request param block with GK request */ + preqparm = (struct gkreqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "GK", 2); + preqparm->rule_array_len = sizeof(uint16_t) + 2 * 8; + memcpy(preqparm->rule_array, "AES OP ", 2*8); + + /* prepare vud block */ + preqparm->vud.len = sizeof(preqparm->vud); + switch (keybitsize) { + case 128: + case 192: + case 256: + break; + default: + DEBUG_ERR( + "%s unknown/unsupported keybitsize %d\n", + __func__, keybitsize); + rc = -EINVAL; + goto out; + } + preqparm->vud.clear_key_bit_len = keybitsize; + memcpy(preqparm->vud.key_type_1, "TOKEN ", 8); + memset(preqparm->vud.key_type_2, ' ', sizeof(preqparm->vud.key_type_2)); + + /* prepare kb block */ + preqparm->kb.len = sizeof(preqparm->kb); + preqparm->kb.tlv1.len = sizeof(preqparm->kb.tlv1); + preqparm->kb.tlv1.flag = 0x0030; + preqparm->kb.tlv2.len = sizeof(preqparm->kb.tlv2); + preqparm->kb.tlv2.flag = 0x0030; + preqparm->kb.tlv3.len = sizeof(preqparm->kb.tlv3); + preqparm->kb.tlv3.flag = 0x0030; + memcpy(preqparm->kb.tlv3.gen_key_id_1, + aes_cipher_key_skeleton, SIZEOF_SKELETON); + preqparm->kb.tlv4.len = sizeof(preqparm->kb.tlv4); + preqparm->kb.tlv4.flag = 0x0030; + preqparm->kb.tlv5.len = sizeof(preqparm->kb.tlv5); + preqparm->kb.tlv5.flag = 0x0030; + preqparm->kb.tlv6.len = sizeof(preqparm->kb.tlv6); + preqparm->kb.tlv6.flag = 0x0030; + + /* patch the skeleton key token export flags inside the kb block */ + if (keygenflags) { + t = (struct cipherkeytoken *) preqparm->kb.tlv3.gen_key_id_1; + t->kmf1 |= (u16) (keygenflags & 0x0000FFFF); + } + + /* prepare xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR( + "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR( + "%s cipher key generate failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct gkrepparm *) prepcblk->rpl_parmb; + + /* do some plausibility checks on the key block */ + if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) || + prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) { + DEBUG_ERR("%s reply with invalid or unknown key block\n", + __func__); + rc = -EIO; + goto out; + } + + /* and some checks on the generated key */ + rc = cca_check_secaescipherkey(zcrypt_dbf_info, DBF_ERR, + prepparm->kb.tlv1.gen_key, + keybitsize, 1); + if (rc) { + rc = -EIO; + goto out; + } + + /* copy the generated vlsc key token */ + t = (struct cipherkeytoken *) prepparm->kb.tlv1.gen_key; + if (keybuf) { + if (*keybufsize >= t->len) + memcpy(keybuf, t, t->len); + else + rc = -EINVAL; + } + *keybufsize = t->len; + +out: + free_cprbmem(mem, PARMBSIZE, 0); + return rc; +} +EXPORT_SYMBOL(cca_gencipherkey); + +/* + * Helper function, does a the CSNBKPI2 CPRB. + */ +static int _ip_cprb_helper(u16 cardnr, u16 domain, + const char *rule_array_1, + const char *rule_array_2, + const char *rule_array_3, + const u8 *clr_key_value, + int clr_key_bit_size, + u8 *key_token, + int *key_token_size) +{ + int rc, n; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct rule_array_block { + u8 subfunc_code[2]; + u16 rule_array_len; + char rule_array[0]; + } __packed * preq_ra_block; + struct vud_block { + u16 len; + struct { + u16 len; + u16 flag; /* 0x0064 */ + u16 clr_key_bit_len; + } tlv1; + struct { + u16 len; + u16 flag; /* 0x0063 */ + u8 clr_key[0]; /* clear key value bytes */ + } tlv2; + } __packed * preq_vud_block; + struct key_block { + u16 len; + struct { + u16 len; + u16 flag; /* 0x0030 */ + u8 key_token[0]; /* key skeleton */ + } tlv1; + } __packed * preq_key_block; + struct iprepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct { + u16 len; + } vud; + struct { + u16 len; + struct { + u16 len; + u16 flag; /* 0x0030 */ + u8 key_token[0]; /* key token */ + } tlv1; + } kb; + } __packed * prepparm; + struct cipherkeytoken *t; + int complete = strncmp(rule_array_2, "COMPLETE", 8) ? 0 : 1; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + preqcblk->req_parml = 0; + + /* prepare request param block with IP request */ + preq_ra_block = (struct rule_array_block *) preqcblk->req_parmb; + memcpy(preq_ra_block->subfunc_code, "IP", 2); + preq_ra_block->rule_array_len = sizeof(uint16_t) + 2 * 8; + memcpy(preq_ra_block->rule_array, rule_array_1, 8); + memcpy(preq_ra_block->rule_array + 8, rule_array_2, 8); + preqcblk->req_parml = sizeof(struct rule_array_block) + 2 * 8; + if (rule_array_3) { + preq_ra_block->rule_array_len += 8; + memcpy(preq_ra_block->rule_array + 16, rule_array_3, 8); + preqcblk->req_parml += 8; + } + + /* prepare vud block */ + preq_vud_block = (struct vud_block *) + (preqcblk->req_parmb + preqcblk->req_parml); + n = complete ? 0 : (clr_key_bit_size + 7) / 8; + preq_vud_block->len = sizeof(struct vud_block) + n; + preq_vud_block->tlv1.len = sizeof(preq_vud_block->tlv1); + preq_vud_block->tlv1.flag = 0x0064; + preq_vud_block->tlv1.clr_key_bit_len = complete ? 0 : clr_key_bit_size; + preq_vud_block->tlv2.len = sizeof(preq_vud_block->tlv2) + n; + preq_vud_block->tlv2.flag = 0x0063; + if (!complete) + memcpy(preq_vud_block->tlv2.clr_key, clr_key_value, n); + preqcblk->req_parml += preq_vud_block->len; + + /* prepare key block */ + preq_key_block = (struct key_block *) + (preqcblk->req_parmb + preqcblk->req_parml); + n = *key_token_size; + preq_key_block->len = sizeof(struct key_block) + n; + preq_key_block->tlv1.len = sizeof(preq_key_block->tlv1) + n; + preq_key_block->tlv1.flag = 0x0030; + memcpy(preq_key_block->tlv1.key_token, key_token, *key_token_size); + preqcblk->req_parml += preq_key_block->len; + + /* prepare xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR( + "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR( + "%s CSNBKPI2 failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct iprepparm *) prepcblk->rpl_parmb; + + /* do some plausibility checks on the key block */ + if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) || + prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) { + DEBUG_ERR("%s reply with invalid or unknown key block\n", + __func__); + rc = -EIO; + goto out; + } + + /* do not check the key here, it may be incomplete */ + + /* copy the vlsc key token back */ + t = (struct cipherkeytoken *) prepparm->kb.tlv1.key_token; + memcpy(key_token, t, t->len); + *key_token_size = t->len; + +out: + free_cprbmem(mem, PARMBSIZE, 0); + return rc; +} + +/* + * Build CCA AES CIPHER secure key with a given clear key value. + */ +int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags, + const u8 *clrkey, u8 *keybuf, size_t *keybufsize) +{ + int rc; + u8 *token; + int tokensize; + u8 exorbuf[32]; + struct cipherkeytoken *t; + + /* fill exorbuf with random data */ + get_random_bytes(exorbuf, sizeof(exorbuf)); + + /* allocate space for the key token to build */ + token = kmalloc(MAXCCAVLSCTOKENSIZE, GFP_KERNEL); + if (!token) + return -ENOMEM; + + /* prepare the token with the key skeleton */ + tokensize = SIZEOF_SKELETON; + memcpy(token, aes_cipher_key_skeleton, tokensize); + + /* patch the skeleton key token export flags */ + if (keygenflags) { + t = (struct cipherkeytoken *) token; + t->kmf1 |= (u16) (keygenflags & 0x0000FF00); + t->kmf1 &= (u16) ~(keygenflags & 0x000000FF); + } + + /* + * Do the key import with the clear key value in 4 steps: + * 1/4 FIRST import with only random data + * 2/4 EXOR the clear key + * 3/4 EXOR the very same random data again + * 4/4 COMPLETE the secure cipher key import + */ + rc = _ip_cprb_helper(card, dom, "AES ", "FIRST ", "MIN3PART", + exorbuf, keybitsize, token, &tokensize); + if (rc) { + DEBUG_ERR( + "%s clear key import 1/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL, + clrkey, keybitsize, token, &tokensize); + if (rc) { + DEBUG_ERR( + "%s clear key import 2/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL, + exorbuf, keybitsize, token, &tokensize); + if (rc) { + DEBUG_ERR( + "%s clear key import 3/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "COMPLETE", NULL, + NULL, keybitsize, token, &tokensize); + if (rc) { + DEBUG_ERR( + "%s clear key import 4/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + + /* copy the generated key token */ + if (keybuf) { + if (tokensize > *keybufsize) + rc = -EINVAL; + else + memcpy(keybuf, token, tokensize); + } + *keybufsize = tokensize; + +out: + kfree(token); + return rc; +} +EXPORT_SYMBOL(cca_clr2cipherkey); + +/* + * Derive proteced key from CCA AES cipher secure key. + */ +int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + int rc; + u8 *mem; + struct CPRBX *preqcblk, *prepcblk; + struct ica_xcRB xcrb; + struct aureqparm { + u8 subfunc_code[2]; + u16 rule_array_len; + u8 rule_array[8]; + struct { + u16 len; + u16 tk_blob_len; + u16 tk_blob_tag; + u8 tk_blob[66]; + } vud; + struct { + u16 len; + u16 cca_key_token_len; + u16 cca_key_token_flags; + u8 cca_key_token[0]; // 64 or more + } kb; + } __packed * preqparm; + struct aurepparm { + u8 subfunc_code[2]; + u16 rule_array_len; + struct { + u16 len; + u16 sublen; + u16 tag; + struct cpacfkeyblock { + u8 version; /* version of this struct */ + u8 flags[2]; + u8 algo; + u8 form; + u8 pad1[3]; + u16 keylen; + u8 key[64]; /* the key (keylen bytes) */ + u16 keyattrlen; + u8 keyattr[32]; + u8 pad2[1]; + u8 vptype; + u8 vp[32]; /* verification pattern */ + } ckb; + } vud; + struct { + u16 len; + } kb; + } __packed * prepparm; + int keytoklen = ((struct cipherkeytoken *)ckey)->len; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); + if (rc) + return rc; + + /* fill request cprb struct */ + preqcblk->domain = domain; + + /* fill request cprb param block with AU request */ + preqparm = (struct aureqparm *) preqcblk->req_parmb; + memcpy(preqparm->subfunc_code, "AU", 2); + preqparm->rule_array_len = + sizeof(preqparm->rule_array_len) + + sizeof(preqparm->rule_array); + memcpy(preqparm->rule_array, "EXPT-SK ", 8); + /* vud, tk blob */ + preqparm->vud.len = sizeof(preqparm->vud); + preqparm->vud.tk_blob_len = sizeof(preqparm->vud.tk_blob) + + 2 * sizeof(uint16_t); + preqparm->vud.tk_blob_tag = 0x00C2; + /* kb, cca token */ + preqparm->kb.len = keytoklen + 3 * sizeof(uint16_t); + preqparm->kb.cca_key_token_len = keytoklen + 2 * sizeof(uint16_t); + memcpy(preqparm->kb.cca_key_token, ckey, keytoklen); + /* now fill length of param block into cprb */ + preqcblk->req_parml = sizeof(struct aureqparm) + keytoklen; + + /* fill xcrb struct */ + prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); + + /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ + rc = _zcrypt_send_cprb(&xcrb); + if (rc) { + DEBUG_ERR( + "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n", + __func__, (int) cardnr, (int) domain, rc); + goto out; + } + + /* check response returncode and reasoncode */ + if (prepcblk->ccp_rtcode != 0) { + DEBUG_ERR( + "%s unwrap secure key failure, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + rc = -EIO; + goto out; + } + if (prepcblk->ccp_rscode != 0) { + DEBUG_WARN( + "%s unwrap secure key warning, card response %d/%d\n", + __func__, + (int) prepcblk->ccp_rtcode, + (int) prepcblk->ccp_rscode); + } + + /* process response cprb param block */ + prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); + prepparm = (struct aurepparm *) prepcblk->rpl_parmb; + + /* check the returned keyblock */ + if (prepparm->vud.ckb.version != 0x01) { + DEBUG_ERR( + "%s reply param keyblock version mismatch 0x%02x != 0x01\n", + __func__, (int) prepparm->vud.ckb.version); + rc = -EIO; + goto out; + } + if (prepparm->vud.ckb.algo != 0x02) { + DEBUG_ERR( + "%s reply param keyblock algo mismatch 0x%02x != 0x02\n", + __func__, (int) prepparm->vud.ckb.algo); + rc = -EIO; + goto out; + } + + /* copy the translated protected key */ + switch (prepparm->vud.ckb.keylen) { + case 16+32: + /* AES 128 protected key */ + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_128; + break; + case 24+32: + /* AES 192 protected key */ + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_192; + break; + case 32+32: + /* AES 256 protected key */ + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_256; + break; + default: + DEBUG_ERR("%s unknown/unsupported keylen %d\n", + __func__, prepparm->vud.ckb.keylen); + rc = -EIO; + goto out; + } + memcpy(protkey, prepparm->vud.ckb.key, prepparm->vud.ckb.keylen); + if (protkeylen) + *protkeylen = prepparm->vud.ckb.keylen; + +out: + free_cprbmem(mem, PARMBSIZE, 0); + return rc; +} +EXPORT_SYMBOL(cca_cipher2protkey); + /* * query cryptographic facility from CCA adapter */ @@ -954,6 +1662,92 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) } EXPORT_SYMBOL(cca_findcard); +int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, + int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify) +{ + struct zcrypt_device_status_ext *device_status; + int i, n, card, dom, curmatch, oldmatch, rc = 0; + struct cca_info ci; + + *apqns = NULL; + *nr_apqns = 0; + + /* fetch status of all crypto cards */ + device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, + sizeof(struct zcrypt_device_status_ext), + GFP_KERNEL); + if (!device_status) + return -ENOMEM; + zcrypt_device_status_mask_ext(device_status); + + /* loop two times: first gather eligible apqns, then store them */ + while (1) { + n = 0; + /* walk through all the crypto cards */ + for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { + card = AP_QID_CARD(device_status[i].qid); + dom = AP_QID_QUEUE(device_status[i].qid); + /* check online state */ + if (!device_status[i].online) + continue; + /* check for cca functions */ + if (!(device_status[i].functions & 0x04)) + continue; + /* check cardnr */ + if (cardnr != 0xFFFF && card != cardnr) + continue; + /* check domain */ + if (domain != 0xFFFF && dom != domain) + continue; + /* get cca info on this apqn */ + if (cca_get_info(card, dom, &ci, verify)) + continue; + /* current master key needs to be valid */ + if (ci.cur_mk_state != '2') + continue; + /* check min hardware type */ + if (minhwtype > 0 && minhwtype > ci.hwtype) + continue; + if (cur_mkvp || old_mkvp) { + /* check mkvps */ + curmatch = oldmatch = 0; + if (cur_mkvp && cur_mkvp == ci.cur_mkvp) + curmatch = 1; + if (old_mkvp && ci.old_mk_state == '2' && + old_mkvp == ci.old_mkvp) + oldmatch = 1; + if ((cur_mkvp || old_mkvp) && + (curmatch + oldmatch < 1)) + continue; + } + /* apqn passed all filtering criterons */ + if (*apqns && n < *nr_apqns) + (*apqns)[n] = (((u16)card) << 16) | ((u16) dom); + n++; + } + /* loop 2nd time: array has been filled */ + if (*apqns) + break; + /* loop 1st time: have # of eligible apqns in n */ + if (!n) { + rc = -ENODEV; /* no eligible apqns found */ + break; + } + *nr_apqns = n; + /* allocate array to store n apqns into */ + *apqns = kmalloc_array(n, sizeof(u32), GFP_KERNEL); + if (!*apqns) { + rc = -ENOMEM; + break; + } + verify = 0; + } + + kfree(device_status); + return rc; +} +EXPORT_SYMBOL(cca_findcard2); + void __exit zcrypt_ccamisc_exit(void) { mkvp_cache_free(); diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index e6f41e5baf18..e97cda0f61e0 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -22,11 +22,16 @@ /* For TOKTYPE_CCA_INTERNAL: */ #define TOKVER_CCA_AES 0x04 /* CCA AES key token */ +#define TOKVER_CCA_VLSC 0x05 /* var length sym cipher key token */ + +/* Max size of a cca variable length cipher key token */ +#define MAXCCAVLSCTOKENSIZE 725 /* header part of a CCA key token */ struct keytoken_header { u8 type; /* one of the TOKTYPE values */ - u8 res0[3]; + u8 res0[1]; + u16 len; /* vlsc token: total length in bytes */ u8 version; /* one of the TOKVER values */ u8 res1[3]; } __packed; @@ -47,6 +52,56 @@ struct secaeskeytoken { u8 tvv[4]; /* token validation value */ } __packed; +/* inside view of a variable length symmetric cipher AES key token */ +struct cipherkeytoken { + u8 type; /* 0x01 for internal key token */ + u8 res0[1]; + u16 len; /* total key token length in bytes */ + u8 version; /* should be 0x05 */ + u8 res1[3]; + u8 kms; /* key material state, 0x03 means wrapped with MK */ + u8 kvpt; /* key verification pattern type, should be 0x01 */ + u64 mkvp0; /* master key verification pattern, lo part */ + u64 mkvp1; /* master key verification pattern, hi part (unused) */ + u8 eskwm; /* encrypted section key wrapping method */ + u8 hashalg; /* hash algorithmus used for wrapping key */ + u8 plfver; /* pay load format version */ + u8 res2[1]; + u8 adsver; /* associated data section version */ + u8 res3[1]; + u16 adslen; /* associated data section length */ + u8 kllen; /* optional key label length */ + u8 ieaslen; /* optional extended associated data length */ + u8 uadlen; /* optional user definable associated data length */ + u8 res4[1]; + u16 wpllen; /* wrapped payload length in bits: */ + /* plfver 0x00 0x01 */ + /* AES-128 512 640 */ + /* AES-192 576 640 */ + /* AES-256 640 640 */ + u8 res5[1]; + u8 algtype; /* 0x02 for AES cipher */ + u16 keytype; /* 0x0001 for 'cipher' */ + u8 kufc; /* key usage field count */ + u16 kuf1; /* key usage field 1 */ + u16 kuf2; /* key usage field 2 */ + u8 kmfc; /* key management field count */ + u16 kmf1; /* key management field 1 */ + u16 kmf2; /* key management field 2 */ + u16 kmf3; /* key management field 3 */ + u8 vdata[0]; /* variable part data follows */ +} __packed; + +/* Some defines for the CCA AES cipherkeytoken kmf1 field */ +#define KMF1_XPRT_SYM 0x8000 +#define KMF1_XPRT_UASY 0x4000 +#define KMF1_XPRT_AASY 0x2000 +#define KMF1_XPRT_RAW 0x1000 +#define KMF1_XPRT_CPAC 0x0800 +#define KMF1_XPRT_DES 0x0080 +#define KMF1_XPRT_AES 0x0040 +#define KMF1_XPRT_RSA 0x0008 + /* * Simple check if the token is a valid CCA secure AES data key * token. If keybitsize is given, the bitsize of the key is @@ -55,6 +110,17 @@ struct secaeskeytoken { int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, const u8 *token, int keybitsize); +/* + * Simple check if the token is a valid CCA secure AES cipher key + * token. If keybitsize is given, the bitsize of the key is + * also checked. If checkcpacfexport is enabled, the key is also + * checked for the export flag to allow CPACF export. + * Returns 0 on success or errno value on failure. + */ +int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, + const u8 *token, int keybitsize, + int checkcpacfexport); + /* * Generate (random) CCA AES DATA secure key. */ @@ -74,6 +140,24 @@ int cca_sec2protkey(u16 cardnr, u16 domain, u8 *protkey, u32 *protkeylen, u32 *protkeytype); +/* + * Generate (random) CCA AES CIPHER secure key. + */ +int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize); + +/* + * Derive proteced key from CCA AES cipher secure key. + */ +int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, + u8 *protkey, u32 *protkeylen, u32 *protkeytype); + +/* + * Build CCA AES CIPHER secure key with a given clear key value. + */ +int cca_clr2cipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, + const u8 *clrkey, u8 *keybuf, size_t *keybufsize); + /* * Query cryptographic facility from CCA adapter */ @@ -90,6 +174,27 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, */ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify); +/* + * Build a list of cca apqns meeting the following constrains: + * - apqn is online and is in fact a CCA apqn + * - if cardnr is not FFFF only apqns with this cardnr + * - if domain is not FFFF only apqns with this domainnr + * - if minhwtype > 0 only apqns with hwtype >= minhwtype + * - if cur_mkvp != 0 only apqns where cur_mkvp == mkvp + * - if old_mkvp != 0 only apqns where old_mkvp == mkvp + * - if verify is enabled and a cur_mkvp and/or old_mkvp + * value is given, then refetch the cca_info and make sure the current + * cur_mkvp or old_mkvp values of the apqn are used. + * The array of apqn entries is allocated with kmalloc and returned in *apqns; + * the number of apqns stored into the list is returned in *nr_apqns. One apqn + * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and + * may be casted to struct pkey_apqn. The return value is either 0 for success + * or a negative errno value. If no apqn meeting the criterias is found, + * -ENODEV is returned. + */ +int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, + int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify); + /* struct to hold info for each CCA queue */ struct cca_info { int hwtype; /* one of the defined AP_DEVICE_TYPE_* */ -- GitLab From f2bbc96e7cfad3891b7bf9bd3e566b9b7ab4553d Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 19 Jun 2019 14:26:05 +0200 Subject: [PATCH 3830/7155] s390/pkey: add CCA AES cipher key support Introduce new ioctls and structs to be used with these new ioctls which are able to handle CCA AES secure keys and CCA AES cipher keys: PKEY_GENSECK2: Generate secure key, version 2. Generate either a CCA AES secure key or a CCA AES cipher key. PKEY_CLR2SECK2: Generate secure key from clear key value, version 2. Construct a CCA AES secure key or CCA AES cipher key from a given clear key value. PKEY_VERIFYKEY2: Verify the given secure key, version 2. Check for correct key type. If cardnr and domain are given, also check if this apqn is able to handle this type of key. If cardnr and domain are 0xFFFF, on return these values are filled with an apqn able to handle this key. The function also checks for the master key verification patterns of the key matching to the current or alternate mkvp of the apqn. CCA AES cipher keys are also checked for CPACF export allowed (CPRTCPAC flag). Currently CCA AES secure keys and CCA AES cipher keys are supported (may get extended in the future). PKEY_KBLOB2PROTK2: Transform a key blob (of any type) into a protected key, version 2. Difference to version 1 is only that this new ioctl has additional parameters to provide a list of apqns to be used for the transformation. PKEY_APQNS4K: Generate a list of APQNs based on the key blob given. Is able to find out which type of secure key is given (CCA AES secure key or CCA AES cipher key) and tries to find all matching crypto cards based on the MKVP and maybe other criterias (like CCA AES cipher keys need a CEX6C or higher). The list of APQNs is further filtered by the key's mkvp which needs to match to either the current mkvp or the alternate mkvp (which is the old mkvp on CCA adapters) of the apqns. The flags argument may be used to limit the matching apqns. If the PKEY_FLAGS_MATCH_CUR_MKVP is given, only the current mkvp of each apqn is compared. Likewise with the PKEY_FLAGS_MATCH_ALT_MKVP. If both are given it is assumed to return apqns where either the current or the alternate mkvp matches. If no matching APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. PKEY_APQNS4KT: Generate a list of APQNs based on the key type given. Build a list of APQNs based on the given key type and maybe further restrict the list by given master key verification patterns. For different key types there may be different ways to match the master key verification patterns. For CCA keys (CCA data key and CCA cipher key) the first 8 bytes of cur_mkvp refer to the current mkvp value of the apqn and the first 8 bytes of the alt_mkvp refer to the old mkvp. The flags argument controls if the apqns current and/or alternate mkvp should match. If the PKEY_FLAGS_MATCH_CUR_MKVP is given, only the current mkvp of each apqn is compared. Likewise with the PKEY_FLAGS_MATCH_ALT_MKVP. If both are given, it is assumed to return apqns where either the current or the alternate mkvp matches. If no matching APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. These new ioctls are now prepared for another new type of secure key blob which may come in the future. They all use a pointer to the key blob and a key blob length information instead of some hardcoded byte array. They all use the new enums pkey_key_type, pkey_key_size and pkey_key_info for getting/setting key type, key size and additional info about the key. All but the PKEY_VERIFY2 ioctl now work based on a list of apqns. This list is walked through trying to perform the operation on exactly this apqn without any further checking (like card type or online state). If the apqn fails, simple the next one in the list is tried until success (return 0) or the end of the list is reached (return -1 with errno ENODEV). All apqns in the list need to be exact apqns (0xFFFF as any card or domain is not allowed). There are two new ioctls which can be used to build a list of apqns based on a key or key type and maybe restricted by match to a current or alternate master key verifcation pattern. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- arch/s390/include/uapi/asm/pkey.h | 257 ++++++++++- drivers/s390/crypto/pkey_api.c | 652 +++++++++++++++++++++++++-- drivers/s390/crypto/zcrypt_ccamisc.c | 58 ++- drivers/s390/crypto/zcrypt_ccamisc.h | 8 +- 4 files changed, 899 insertions(+), 76 deletions(-) diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h index c0e86ce4a00b..e22f0720bbb8 100644 --- a/arch/s390/include/uapi/asm/pkey.h +++ b/arch/s390/include/uapi/asm/pkey.h @@ -2,7 +2,7 @@ /* * Userspace interface to the pkey device driver * - * Copyright IBM Corp. 2017 + * Copyright IBM Corp. 2017, 2019 * * Author: Harald Freudenberger * @@ -20,38 +20,74 @@ #define PKEY_IOCTL_MAGIC 'p' -#define SECKEYBLOBSIZE 64 /* secure key blob size is always 64 bytes */ -#define PROTKEYBLOBSIZE 80 /* protected key blob size is always 80 bytes */ -#define MAXPROTKEYSIZE 64 /* a protected key blob may be up to 64 bytes */ -#define MAXCLRKEYSIZE 32 /* a clear key value may be up to 32 bytes */ +#define SECKEYBLOBSIZE 64 /* secure key blob size is always 64 bytes */ +#define PROTKEYBLOBSIZE 80 /* protected key blob size is always 80 bytes */ +#define MAXPROTKEYSIZE 64 /* a protected key blob may be up to 64 bytes */ +#define MAXCLRKEYSIZE 32 /* a clear key value may be up to 32 bytes */ +#define MAXAESCIPHERKEYSIZE 136 /* our aes cipher keys have always 136 bytes */ -#define MINKEYBLOBSIZE SECKEYBLOBSIZE /* Minimum size of a key blob */ -#define MAXKEYBLOBSIZE PROTKEYBLOBSIZE /* Maximum size of a key blob */ +/* Minimum and maximum size of a key blob */ +#define MINKEYBLOBSIZE SECKEYBLOBSIZE +#define MAXKEYBLOBSIZE MAXAESCIPHERKEYSIZE /* defines for the type field within the pkey_protkey struct */ -#define PKEY_KEYTYPE_AES_128 1 -#define PKEY_KEYTYPE_AES_192 2 -#define PKEY_KEYTYPE_AES_256 3 +#define PKEY_KEYTYPE_AES_128 1 +#define PKEY_KEYTYPE_AES_192 2 +#define PKEY_KEYTYPE_AES_256 3 -/* Struct to hold a secure key blob */ +/* the newer ioctls use a pkey_key_type enum for type information */ +enum pkey_key_type { + PKEY_TYPE_CCA_DATA = (__u32) 1, + PKEY_TYPE_CCA_CIPHER = (__u32) 2, +}; + +/* the newer ioctls use a pkey_key_size enum for key size information */ +enum pkey_key_size { + PKEY_SIZE_AES_128 = (__u32) 128, + PKEY_SIZE_AES_192 = (__u32) 192, + PKEY_SIZE_AES_256 = (__u32) 256, + PKEY_SIZE_UNKNOWN = (__u32) 0xFFFFFFFF, +}; + +/* some of the newer ioctls use these flags */ +#define PKEY_FLAGS_MATCH_CUR_MKVP 0x00000002 +#define PKEY_FLAGS_MATCH_ALT_MKVP 0x00000004 + +/* keygenflags defines for CCA AES cipher keys */ +#define PKEY_KEYGEN_XPRT_SYM 0x00008000 +#define PKEY_KEYGEN_XPRT_UASY 0x00004000 +#define PKEY_KEYGEN_XPRT_AASY 0x00002000 +#define PKEY_KEYGEN_XPRT_RAW 0x00001000 +#define PKEY_KEYGEN_XPRT_CPAC 0x00000800 +#define PKEY_KEYGEN_XPRT_DES 0x00000080 +#define PKEY_KEYGEN_XPRT_AES 0x00000040 +#define PKEY_KEYGEN_XPRT_RSA 0x00000008 + +/* Struct to hold apqn target info (card/domain pair) */ +struct pkey_apqn { + __u16 card; + __u16 domain; +}; + +/* Struct to hold a CCA AES secure key blob */ struct pkey_seckey { __u8 seckey[SECKEYBLOBSIZE]; /* the secure key blob */ }; /* Struct to hold protected key and length info */ struct pkey_protkey { - __u32 type; /* key type, one of the PKEY_KEYTYPE values */ + __u32 type; /* key type, one of the PKEY_KEYTYPE_AES values */ __u32 len; /* bytes actually stored in protkey[] */ __u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ }; -/* Struct to hold a clear key value */ +/* Struct to hold an AES clear key value */ struct pkey_clrkey { __u8 clrkey[MAXCLRKEYSIZE]; /* 16, 24, or 32 byte clear key value */ }; /* - * Generate secure key + * Generate CCA AES secure key. */ struct pkey_genseck { __u16 cardnr; /* in: card to use or FFFF for any */ @@ -62,7 +98,7 @@ struct pkey_genseck { #define PKEY_GENSECK _IOWR(PKEY_IOCTL_MAGIC, 0x01, struct pkey_genseck) /* - * Construct secure key from clear key value + * Construct CCA AES secure key from clear key value */ struct pkey_clr2seck { __u16 cardnr; /* in: card to use or FFFF for any */ @@ -74,7 +110,7 @@ struct pkey_clr2seck { #define PKEY_CLR2SECK _IOWR(PKEY_IOCTL_MAGIC, 0x02, struct pkey_clr2seck) /* - * Fabricate protected key from a secure key + * Fabricate AES protected key from a CCA AES secure key */ struct pkey_sec2protk { __u16 cardnr; /* in: card to use or FFFF for any */ @@ -85,7 +121,7 @@ struct pkey_sec2protk { #define PKEY_SEC2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x03, struct pkey_sec2protk) /* - * Fabricate protected key from an clear key value + * Fabricate AES protected key from clear key value */ struct pkey_clr2protk { __u32 keytype; /* in: key type to generate */ @@ -96,7 +132,7 @@ struct pkey_clr2protk { /* * Search for matching crypto card based on the Master Key - * Verification Pattern provided inside a secure key. + * Verification Pattern provided inside a CCA AES secure key. */ struct pkey_findcard { struct pkey_seckey seckey; /* in: the secure key blob */ @@ -115,7 +151,7 @@ struct pkey_skey2pkey { #define PKEY_SKEY2PKEY _IOWR(PKEY_IOCTL_MAGIC, 0x06, struct pkey_skey2pkey) /* - * Verify the given secure key for being able to be useable with + * Verify the given CCA AES secure key for being able to be useable with * the pkey module. Check for correct key type and check for having at * least one crypto card being able to handle this key (master key * or old master key verification pattern matches). @@ -134,7 +170,7 @@ struct pkey_verifykey { #define PKEY_VERIFY_ATTR_OLD_MKVP 0x00000100 /* key has old MKVP value */ /* - * Generate (AES) random protected key. + * Generate AES random protected key. */ struct pkey_genprotk { __u32 keytype; /* in: key type to generate */ @@ -144,7 +180,7 @@ struct pkey_genprotk { #define PKEY_GENPROTK _IOWR(PKEY_IOCTL_MAGIC, 0x08, struct pkey_genprotk) /* - * Verify an (AES) protected key. + * Verify an AES protected key. */ struct pkey_verifyprotk { struct pkey_protkey protkey; /* in: the protected key to verify */ @@ -160,7 +196,184 @@ struct pkey_kblob2pkey { __u32 keylen; /* in: the key blob length */ struct pkey_protkey protkey; /* out: the protected key */ }; - #define PKEY_KBLOB2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x0A, struct pkey_kblob2pkey) +/* + * Generate secure key, version 2. + * Generate either a CCA AES secure key or a CCA AES cipher key. + * There needs to be a list of apqns given with at least one entry in there. + * All apqns in the list need to be exact apqns, 0xFFFF as ANY card or domain + * is not supported. The implementation walks through the list of apqns and + * tries to send the request to each apqn without any further checking (like + * card type or online state). If the apqn fails, simple the next one in the + * list is tried until success (return 0) or the end of the list is reached + * (return -1 with errno ENODEV). You may use the PKEY_APQNS4KT ioctl to + * generate a list of apqns based on the key type to generate. + * The keygenflags argument is passed to the low level generation functions + * individual for the key type and has a key type specific meaning. Currently + * only CCA AES cipher keys react to this parameter: Use one or more of the + * PKEY_KEYGEN_* flags to widen the export possibilities. By default a cipher + * key is only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC). + */ +struct pkey_genseck2 { + struct pkey_apqn __user *apqns; /* in: ptr to list of apqn targets*/ + __u32 apqn_entries; /* in: # of apqn target list entries */ + enum pkey_key_type type; /* in: key type to generate */ + enum pkey_key_size size; /* in: key size to generate */ + __u32 keygenflags; /* in: key generation flags */ + __u8 __user *key; /* in: pointer to key blob buffer */ + __u32 keylen; /* in: available key blob buffer size */ + /* out: actual key blob size */ +}; +#define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2) + +/* + * Generate secure key from clear key value, version 2. + * Construct a CCA AES secure key or CCA AES cipher key from a given clear key + * value. + * There needs to be a list of apqns given with at least one entry in there. + * All apqns in the list need to be exact apqns, 0xFFFF as ANY card or domain + * is not supported. The implementation walks through the list of apqns and + * tries to send the request to each apqn without any further checking (like + * card type or online state). If the apqn fails, simple the next one in the + * list is tried until success (return 0) or the end of the list is reached + * (return -1 with errno ENODEV). You may use the PKEY_APQNS4KT ioctl to + * generate a list of apqns based on the key type to generate. + * The keygenflags argument is passed to the low level generation functions + * individual for the key type and has a key type specific meaning. Currently + * only CCA AES cipher keys react to this parameter: Use one or more of the + * PKEY_KEYGEN_* flags to widen the export possibilities. By default a cipher + * key is only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC). + */ +struct pkey_clr2seck2 { + struct pkey_apqn __user *apqns; /* in: ptr to list of apqn targets */ + __u32 apqn_entries; /* in: # of apqn target list entries */ + enum pkey_key_type type; /* in: key type to generate */ + enum pkey_key_size size; /* in: key size to generate */ + __u32 keygenflags; /* in: key generation flags */ + struct pkey_clrkey clrkey; /* in: the clear key value */ + __u8 __user *key; /* in: pointer to key blob buffer */ + __u32 keylen; /* in: available key blob buffer size */ + /* out: actual key blob size */ +}; +#define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2) + +/* + * Verify the given secure key, version 2. + * Check for correct key type. If cardnr and domain are given (are not + * 0xFFFF) also check if this apqn is able to handle this type of key. + * If cardnr and/or domain is 0xFFFF, on return these values are filled + * with one apqn able to handle this key. + * The function also checks for the master key verification patterns + * of the key matching to the current or alternate mkvp of the apqn. + * Currently CCA AES secure keys and CCA AES cipher keys are supported. + * The flags field is updated with some additional info about the apqn mkvp + * match: If the current mkvp matches to the key's mkvp then the + * PKEY_FLAGS_MATCH_CUR_MKVP bit is set, if the alternate mkvp matches to + * the key's mkvp the PKEY_FLAGS_MATCH_ALT_MKVP is set. For CCA keys the + * alternate mkvp is the old master key verification pattern. + * CCA AES secure keys are also checked to have the CPACF export allowed + * bit enabled (XPRTCPAC) in the kmf1 field. + * The ioctl returns 0 as long as the given or found apqn matches to + * matches with the current or alternate mkvp to the key's mkvp. If the given + * apqn does not match or there is no such apqn found, -1 with errno + * ENODEV is returned. + */ +struct pkey_verifykey2 { + __u8 __user *key; /* in: pointer to key blob */ + __u32 keylen; /* in: key blob size */ + __u16 cardnr; /* in/out: card number */ + __u16 domain; /* in/out: domain number */ + enum pkey_key_type type; /* out: the key type */ + enum pkey_key_size size; /* out: the key size */ + __u32 flags; /* out: additional key info flags */ +}; +#define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2) + +/* + * Transform a key blob (of any type) into a protected key, version 2. + * There needs to be a list of apqns given with at least one entry in there. + * All apqns in the list need to be exact apqns, 0xFFFF as ANY card or domain + * is not supported. The implementation walks through the list of apqns and + * tries to send the request to each apqn without any further checking (like + * card type or online state). If the apqn fails, simple the next one in the + * list is tried until success (return 0) or the end of the list is reached + * (return -1 with errno ENODEV). You may use the PKEY_APQNS4K ioctl to + * generate a list of apqns based on the key. + */ +struct pkey_kblob2pkey2 { + __u8 __user *key; /* in: pointer to key blob */ + __u32 keylen; /* in: key blob size */ + struct pkey_apqn __user *apqns; /* in: ptr to list of apqn targets */ + __u32 apqn_entries; /* in: # of apqn target list entries */ + struct pkey_protkey protkey; /* out: the protected key */ +}; +#define PKEY_KBLOB2PROTK2 _IOWR(PKEY_IOCTL_MAGIC, 0x1A, struct pkey_kblob2pkey2) + +/* + * Build a list of APQNs based on a key blob given. + * Is able to find out which type of secure key is given (CCA AES secure + * key or CCA AES cipher key) and tries to find all matching crypto cards + * based on the MKVP and maybe other criterias (like CCA AES cipher keys + * need a CEX5C or higher). The list of APQNs is further filtered by the key's + * mkvp which needs to match to either the current mkvp or the alternate mkvp + * (which is the old mkvp on CCA adapters) of the apqns. The flags argument may + * be used to limit the matching apqns. If the PKEY_FLAGS_MATCH_CUR_MKVP is + * given, only the current mkvp of each apqn is compared. Likewise with the + * PKEY_FLAGS_MATCH_ALT_MKVP. If both are given, it is assumed to + * return apqns where either the current or the alternate mkvp + * matches. At least one of the matching flags needs to be given. + * The list of matching apqns is stored into the space given by the apqns + * argument and the number of stored entries goes into apqn_entries. If the list + * is empty (apqn_entries is 0) the apqn_entries field is updated to the number + * of apqn targets found and the ioctl returns with 0. If apqn_entries is > 0 + * but the number of apqn targets does not fit into the list, the apqn_targets + * field is updatedd with the number of reqired entries but there are no apqn + * values stored in the list and the ioctl returns with ENOSPC. If no matching + * APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. + */ +struct pkey_apqns4key { + __u8 __user *key; /* in: pointer to key blob */ + __u32 keylen; /* in: key blob size */ + __u32 flags; /* in: match controlling flags */ + struct pkey_apqn __user *apqns; /* in/out: ptr to list of apqn targets*/ + __u32 apqn_entries; /* in: max # of apqn entries in the list */ + /* out: # apqns stored into the list */ +}; +#define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key) + +/* + * Build a list of APQNs based on a key type given. + * Build a list of APQNs based on a given key type and maybe further + * restrict the list by given master key verification patterns. + * For different key types there may be different ways to match the + * master key verification patterns. For CCA keys (CCA data key and CCA + * cipher key) the first 8 bytes of cur_mkvp refer to the current mkvp value + * of the apqn and the first 8 bytes of the alt_mkvp refer to the old mkvp. + * The flags argument controls if the apqns current and/or alternate mkvp + * should match. If the PKEY_FLAGS_MATCH_CUR_MKVP is given, only the current + * mkvp of each apqn is compared. Likewise with the PKEY_FLAGS_MATCH_ALT_MKVP. + * If both are given, it is assumed to return apqns where either the + * current or the alternate mkvp matches. If no match flag is given + * (flags is 0) the mkvp values are ignored for the match process. + * The list of matching apqns is stored into the space given by the apqns + * argument and the number of stored entries goes into apqn_entries. If the list + * is empty (apqn_entries is 0) the apqn_entries field is updated to the number + * of apqn targets found and the ioctl returns with 0. If apqn_entries is > 0 + * but the number of apqn targets does not fit into the list, the apqn_targets + * field is updatedd with the number of reqired entries but there are no apqn + * values stored in the list and the ioctl returns with ENOSPC. If no matching + * APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. + */ +struct pkey_apqns4keytype { + enum pkey_key_type type; /* in: key type */ + __u8 cur_mkvp[32]; /* in: current mkvp */ + __u8 alt_mkvp[32]; /* in: alternate mkvp */ + __u32 flags; /* in: match controlling flags */ + struct pkey_apqn __user *apqns; /* in/out: ptr to list of apqn targets*/ + __u32 apqn_entries; /* in: max # of apqn entries in the list */ + /* out: # apqns stored into the list */ +}; +#define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, struct pkey_apqns4keytype) + #endif /* _UAPI_PKEY_H */ diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index cd7e654bd18e..f76a1d0f54c4 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -30,6 +30,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key interface"); +#define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ +#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ + /* mask of available pckmo subfunctions, fetched once at module init */ static cpacf_mask_t pckmo_functions; @@ -126,27 +129,39 @@ static int pkey_clr2protkey(u32 keytype, /* * Find card and transform secure key into protected key. */ -static int pkey_skey2pkey(const struct pkey_seckey *seckey, - struct pkey_protkey *pkey) +static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) { - u16 cardnr, domain; int rc, verify; + u16 cardnr, domain; + struct keytoken_header *hdr = (struct keytoken_header *)key; /* - * The cca_sec2protkey call may fail when a card has been + * The cca_xxx2protkey call may fail when a card has been * addressed where the master key was changed after last fetch * of the mkvp into the cache. Try 3 times: First witout verify * then with verify and last round with verify and old master * key verification pattern match not ignored. */ for (verify = 0; verify < 3; verify++) { - rc = cca_findcard(seckey->seckey, &cardnr, &domain, verify); + rc = cca_findcard(key, &cardnr, &domain, verify); if (rc < 0) continue; if (rc > 0 && verify < 2) continue; - rc = cca_sec2protkey(cardnr, domain, seckey->seckey, - pkey->protkey, &pkey->len, &pkey->type); + switch (hdr->version) { + case TOKVER_CCA_AES: + rc = cca_sec2protkey(cardnr, domain, + key, pkey->protkey, + &pkey->len, &pkey->type); + break; + case TOKVER_CCA_VLSC: + rc = cca_cipher2protkey(cardnr, domain, + key, pkey->protkey, + &pkey->len, &pkey->type); + break; + default: + return -EINVAL; + } if (rc == 0) break; } @@ -324,14 +339,18 @@ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, case TOKVER_CCA_AES: if (keylen != sizeof(struct secaeskeytoken)) return -EINVAL; - - return pkey_skey2pkey((struct pkey_seckey *)key, - protkey); + break; + case TOKVER_CCA_VLSC: + if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) + return -EINVAL; + break; default: DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", __func__, hdr->version); return -EINVAL; } + + return pkey_skey2pkey(key, protkey); } /* @@ -340,28 +359,394 @@ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, int pkey_keyblob2pkey(const u8 *key, u32 keylen, struct pkey_protkey *protkey) { + int rc; struct keytoken_header *hdr = (struct keytoken_header *)key; - if (keylen < sizeof(struct keytoken_header)) + if (keylen < sizeof(struct keytoken_header)) { + DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); return -EINVAL; + } switch (hdr->type) { case TOKTYPE_NON_CCA: - return pkey_nonccatok2pkey(key, keylen, protkey); + rc = pkey_nonccatok2pkey(key, keylen, protkey); + break; case TOKTYPE_CCA_INTERNAL: - return pkey_ccainttok2pkey(key, keylen, protkey); + rc = pkey_ccainttok2pkey(key, keylen, protkey); + break; default: - DEBUG_ERR("%s unknown/unsupported blob type %d\n", __func__, - hdr->type); + DEBUG_ERR("%s unknown/unsupported blob type %d\n", + __func__, hdr->type); return -EINVAL; } + + DEBUG_DBG("%s rc=%d\n", __func__, rc); + return rc; + } EXPORT_SYMBOL(pkey_keyblob2pkey); +static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, + enum pkey_key_type ktype, enum pkey_key_size ksize, + u32 kflags, u8 *keybuf, size_t *keybufsize) +{ + int i, card, dom, rc; + + /* check for at least one apqn given */ + if (!apqns || !nr_apqns) + return -EINVAL; + + /* check key type and size */ + switch (ktype) { + case PKEY_TYPE_CCA_DATA: + case PKEY_TYPE_CCA_CIPHER: + if (*keybufsize < SECKEYBLOBSIZE) + return -EINVAL; + break; + default: + return -EINVAL; + } + switch (ksize) { + case PKEY_SIZE_AES_128: + case PKEY_SIZE_AES_192: + case PKEY_SIZE_AES_256: + break; + default: + return -EINVAL; + } + + /* simple try all apqns from the list */ + for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { + card = apqns[i].card; + dom = apqns[i].domain; + if (ktype == PKEY_TYPE_CCA_DATA) { + rc = cca_genseckey(card, dom, ksize, keybuf); + *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); + } else /* TOKVER_CCA_VLSC */ + rc = cca_gencipherkey(card, dom, ksize, kflags, + keybuf, keybufsize); + if (rc == 0) + break; + } + + return rc; +} + +static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, + enum pkey_key_type ktype, enum pkey_key_size ksize, + u32 kflags, const u8 *clrkey, + u8 *keybuf, size_t *keybufsize) +{ + int i, card, dom, rc; + + /* check for at least one apqn given */ + if (!apqns || !nr_apqns) + return -EINVAL; + + /* check key type and size */ + switch (ktype) { + case PKEY_TYPE_CCA_DATA: + case PKEY_TYPE_CCA_CIPHER: + if (*keybufsize < SECKEYBLOBSIZE) + return -EINVAL; + break; + default: + return -EINVAL; + } + switch (ksize) { + case PKEY_SIZE_AES_128: + case PKEY_SIZE_AES_192: + case PKEY_SIZE_AES_256: + break; + default: + return -EINVAL; + } + + /* simple try all apqns from the list */ + for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { + card = apqns[i].card; + dom = apqns[i].domain; + if (ktype == PKEY_TYPE_CCA_DATA) { + rc = cca_clr2seckey(card, dom, ksize, + clrkey, keybuf); + *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); + } else /* TOKVER_CCA_VLSC */ + rc = cca_clr2cipherkey(card, dom, ksize, kflags, + clrkey, keybuf, keybufsize); + if (rc == 0) + break; + } + + return rc; +} + +static int pkey_verifykey2(const u8 *key, size_t keylen, + u16 *cardnr, u16 *domain, + enum pkey_key_type *ktype, + enum pkey_key_size *ksize, u32 *flags) +{ + int rc; + u32 _nr_apqns, *_apqns = NULL; + struct keytoken_header *hdr = (struct keytoken_header *)key; + + if (keylen < sizeof(struct keytoken_header) || + hdr->type != TOKTYPE_CCA_INTERNAL) + return -EINVAL; + + if (hdr->version == TOKVER_CCA_AES) { + struct secaeskeytoken *t = (struct secaeskeytoken *)key; + + rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); + if (rc) + goto out; + if (ktype) + *ktype = PKEY_TYPE_CCA_DATA; + if (ksize) + *ksize = (enum pkey_key_size) t->bitsize; + + rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, + ZCRYPT_CEX3C, t->mkvp, 0, 1); + if (rc == 0 && flags) + *flags = PKEY_FLAGS_MATCH_CUR_MKVP; + if (rc == -ENODEV) { + rc = cca_findcard2(&_apqns, &_nr_apqns, + *cardnr, *domain, + ZCRYPT_CEX3C, 0, t->mkvp, 1); + if (rc == 0 && flags) + *flags = PKEY_FLAGS_MATCH_ALT_MKVP; + } + if (rc) + goto out; + + *cardnr = ((struct pkey_apqn *)_apqns)->card; + *domain = ((struct pkey_apqn *)_apqns)->domain; + + } else if (hdr->version == TOKVER_CCA_VLSC) { + struct cipherkeytoken *t = (struct cipherkeytoken *)key; + + rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); + if (rc) + goto out; + if (ktype) + *ktype = PKEY_TYPE_CCA_CIPHER; + if (ksize) { + *ksize = PKEY_SIZE_UNKNOWN; + if (!t->plfver && t->wpllen == 512) + *ksize = PKEY_SIZE_AES_128; + else if (!t->plfver && t->wpllen == 576) + *ksize = PKEY_SIZE_AES_192; + else if (!t->plfver && t->wpllen == 640) + *ksize = PKEY_SIZE_AES_256; + } + + rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, + ZCRYPT_CEX6, t->mkvp0, 0, 1); + if (rc == 0 && flags) + *flags = PKEY_FLAGS_MATCH_CUR_MKVP; + if (rc == -ENODEV) { + rc = cca_findcard2(&_apqns, &_nr_apqns, + *cardnr, *domain, + ZCRYPT_CEX6, 0, t->mkvp0, 1); + if (rc == 0 && flags) + *flags = PKEY_FLAGS_MATCH_ALT_MKVP; + } + if (rc) + goto out; + + *cardnr = ((struct pkey_apqn *)_apqns)->card; + *domain = ((struct pkey_apqn *)_apqns)->domain; + + } else + rc = -EINVAL; + +out: + kfree(_apqns); + return rc; +} + +static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, size_t keylen, + struct pkey_protkey *pkey) +{ + int i, card, dom, rc; + struct keytoken_header *hdr = (struct keytoken_header *)key; + + /* check for at least one apqn given */ + if (!apqns || !nr_apqns) + return -EINVAL; + + if (keylen < sizeof(struct keytoken_header)) + return -EINVAL; + + switch (hdr->type) { + case TOKTYPE_NON_CCA: + return pkey_nonccatok2pkey(key, keylen, pkey); + case TOKTYPE_CCA_INTERNAL: + switch (hdr->version) { + case TOKVER_CCA_AES: + if (keylen != sizeof(struct secaeskeytoken)) + return -EINVAL; + if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) + return -EINVAL; + break; + case TOKVER_CCA_VLSC: + if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) + return -EINVAL; + if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) + return -EINVAL; + break; + default: + DEBUG_ERR("%s unknown CCA internal token version %d\n", + __func__, hdr->version); + return -EINVAL; + } + break; + default: + DEBUG_ERR("%s unknown/unsupported blob type %d\n", + __func__, hdr->type); + return -EINVAL; + } + + /* simple try all apqns from the list */ + for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { + card = apqns[i].card; + dom = apqns[i].domain; + if (hdr->version == TOKVER_CCA_AES) + rc = cca_sec2protkey(card, dom, key, pkey->protkey, + &pkey->len, &pkey->type); + else /* TOKVER_CCA_VLSC */ + rc = cca_cipher2protkey(card, dom, key, pkey->protkey, + &pkey->len, &pkey->type); + if (rc == 0) + break; + } + + return rc; +} + +static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + int rc = EINVAL; + u32 _nr_apqns, *_apqns = NULL; + struct keytoken_header *hdr = (struct keytoken_header *)key; + + if (keylen < sizeof(struct keytoken_header) || + hdr->type != TOKTYPE_CCA_INTERNAL || + flags == 0) + return -EINVAL; + + if (hdr->version == TOKVER_CCA_AES || hdr->version == TOKVER_CCA_VLSC) { + int minhwtype = ZCRYPT_CEX3C; + u64 cur_mkvp = 0, old_mkvp = 0; + + if (hdr->version == TOKVER_CCA_AES) { + struct secaeskeytoken *t = (struct secaeskeytoken *)key; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp; + } else { + struct cipherkeytoken *t = (struct cipherkeytoken *)key; + + minhwtype = ZCRYPT_CEX6; + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp0; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp0; + } + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + } + +out: + kfree(_apqns); + return rc; +} + +static int pkey_apqns4keytype(enum pkey_key_type ktype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + int rc = -EINVAL; + u32 _nr_apqns, *_apqns = NULL; + + if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { + u64 cur_mkvp = 0, old_mkvp = 0; + int minhwtype = ZCRYPT_CEX3C; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = *((u64 *) cur_mkvp); + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = *((u64 *) alt_mkvp); + if (ktype == PKEY_TYPE_CCA_CIPHER) + minhwtype = ZCRYPT_CEX6; + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + } + +out: + kfree(_apqns); + return rc; +} + /* * File io functions */ +static void *_copy_key_from_user(void __user *ukey, size_t keylen) +{ + void *kkey; + + if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) + return ERR_PTR(-EINVAL); + kkey = kmalloc(keylen, GFP_KERNEL); + if (!kkey) + return ERR_PTR(-ENOMEM); + if (copy_from_user(kkey, ukey, keylen)) { + kfree(kkey); + return ERR_PTR(-EFAULT); + } + + return kkey; +} + +static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) +{ + void *kapqns = NULL; + size_t nbytes; + + if (uapqns && nr_apqns > 0) { + nbytes = nr_apqns * sizeof(struct pkey_apqn); + kapqns = kmalloc(nbytes, GFP_KERNEL); + if (!kapqns) + return ERR_PTR(-ENOMEM); + if (copy_from_user(kapqns, uapqns, nbytes)) + return ERR_PTR(-EFAULT); + } + + return kapqns; +} + static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -452,7 +837,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; - rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); + rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); if (rc) break; @@ -502,24 +887,148 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, case PKEY_KBLOB2PROTK: { struct pkey_kblob2pkey __user *utp = (void __user *) arg; struct pkey_kblob2pkey ktp; - u8 __user *ukey; u8 *kkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) return -EFAULT; - if (ktp.keylen < MINKEYBLOBSIZE || - ktp.keylen > MAXKEYBLOBSIZE) - return -EINVAL; - ukey = ktp.key; - kkey = kmalloc(ktp.keylen, GFP_KERNEL); - if (kkey == NULL) + kkey = _copy_key_from_user(ktp.key, ktp.keylen); + if (IS_ERR(kkey)) + return PTR_ERR(kkey); + rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); + DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); + kfree(kkey); + if (rc) + break; + if (copy_to_user(utp, &ktp, sizeof(ktp))) + return -EFAULT; + break; + } + case PKEY_GENSECK2: { + struct pkey_genseck2 __user *ugs = (void __user *) arg; + struct pkey_genseck2 kgs; + struct pkey_apqn *apqns; + size_t klen = KEYBLOBBUFSIZE; + u8 *kkey; + + if (copy_from_user(&kgs, ugs, sizeof(kgs))) + return -EFAULT; + apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); + if (IS_ERR(apqns)) + return PTR_ERR(apqns); + kkey = kmalloc(klen, GFP_KERNEL); + if (!kkey) { + kfree(apqns); return -ENOMEM; - if (copy_from_user(kkey, ukey, ktp.keylen)) { + } + rc = pkey_genseckey2(apqns, kgs.apqn_entries, + kgs.type, kgs.size, kgs.keygenflags, + kkey, &klen); + DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); + kfree(apqns); + if (rc) { kfree(kkey); + break; + } + if (kgs.key) { + if (kgs.keylen < klen) { + kfree(kkey); + return -EINVAL; + } + if (copy_to_user(kgs.key, kkey, klen)) { + kfree(kkey); + return -EFAULT; + } + } + kgs.keylen = klen; + if (copy_to_user(ugs, &kgs, sizeof(kgs))) + rc = -EFAULT; + kfree(kkey); + break; + } + case PKEY_CLR2SECK2: { + struct pkey_clr2seck2 __user *ucs = (void __user *) arg; + struct pkey_clr2seck2 kcs; + struct pkey_apqn *apqns; + size_t klen = KEYBLOBBUFSIZE; + u8 *kkey; + + if (copy_from_user(&kcs, ucs, sizeof(kcs))) return -EFAULT; + apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); + if (IS_ERR(apqns)) + return PTR_ERR(apqns); + kkey = kmalloc(klen, GFP_KERNEL); + if (!kkey) { + kfree(apqns); + return -ENOMEM; } - rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); - DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); + rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, + kcs.type, kcs.size, kcs.keygenflags, + kcs.clrkey.clrkey, kkey, &klen); + DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); + kfree(apqns); + if (rc) { + kfree(kkey); + break; + } + if (kcs.key) { + if (kcs.keylen < klen) { + kfree(kkey); + return -EINVAL; + } + if (copy_to_user(kcs.key, kkey, klen)) { + kfree(kkey); + return -EFAULT; + } + } + kcs.keylen = klen; + if (copy_to_user(ucs, &kcs, sizeof(kcs))) + rc = -EFAULT; + memzero_explicit(&kcs, sizeof(kcs)); + kfree(kkey); + break; + } + case PKEY_VERIFYKEY2: { + struct pkey_verifykey2 __user *uvk = (void __user *) arg; + struct pkey_verifykey2 kvk; + u8 *kkey; + + if (copy_from_user(&kvk, uvk, sizeof(kvk))) + return -EFAULT; + kkey = _copy_key_from_user(kvk.key, kvk.keylen); + if (IS_ERR(kkey)) + return PTR_ERR(kkey); + rc = pkey_verifykey2(kkey, kvk.keylen, + &kvk.cardnr, &kvk.domain, + &kvk.type, &kvk.size, &kvk.flags); + DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); + kfree(kkey); + if (rc) + break; + if (copy_to_user(uvk, &kvk, sizeof(kvk))) + return -EFAULT; + break; + } + case PKEY_KBLOB2PROTK2: { + struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; + struct pkey_kblob2pkey2 ktp; + struct pkey_apqn *apqns = NULL; + u8 *kkey; + + if (copy_from_user(&ktp, utp, sizeof(ktp))) + return -EFAULT; + apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); + if (IS_ERR(apqns)) + return PTR_ERR(apqns); + kkey = _copy_key_from_user(ktp.key, ktp.keylen); + if (IS_ERR(kkey)) { + kfree(apqns); + return PTR_ERR(kkey); + } + rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, + kkey, ktp.keylen, &ktp.protkey); + DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); + kfree(apqns); kfree(kkey); if (rc) break; @@ -527,6 +1036,97 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, return -EFAULT; break; } + case PKEY_APQNS4K: { + struct pkey_apqns4key __user *uak = (void __user *) arg; + struct pkey_apqns4key kak; + struct pkey_apqn *apqns = NULL; + size_t nr_apqns, len; + u8 *kkey; + + if (copy_from_user(&kak, uak, sizeof(kak))) + return -EFAULT; + nr_apqns = kak.apqn_entries; + if (nr_apqns) { + apqns = kmalloc_array(nr_apqns, + sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!apqns) + return -ENOMEM; + } + kkey = _copy_key_from_user(kak.key, kak.keylen); + if (IS_ERR(kkey)) { + kfree(apqns); + return PTR_ERR(kkey); + } + rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, + apqns, &nr_apqns); + DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); + kfree(kkey); + if (rc && rc != -ENOSPC) { + kfree(apqns); + break; + } + if (!rc && kak.apqns) { + if (nr_apqns > kak.apqn_entries) { + kfree(apqns); + return -EINVAL; + } + len = nr_apqns * sizeof(struct pkey_apqn); + if (len) { + if (copy_to_user(kak.apqns, apqns, len)) { + kfree(apqns); + return -EFAULT; + } + } + } + kak.apqn_entries = nr_apqns; + if (copy_to_user(uak, &kak, sizeof(kak))) + rc = -EFAULT; + kfree(apqns); + break; + } + case PKEY_APQNS4KT: { + struct pkey_apqns4keytype __user *uat = (void __user *) arg; + struct pkey_apqns4keytype kat; + struct pkey_apqn *apqns = NULL; + size_t nr_apqns, len; + + if (copy_from_user(&kat, uat, sizeof(kat))) + return -EFAULT; + nr_apqns = kat.apqn_entries; + if (nr_apqns) { + apqns = kmalloc_array(nr_apqns, + sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!apqns) + return -ENOMEM; + } + rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, + kat.flags, apqns, &nr_apqns); + DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); + if (rc && rc != -ENOSPC) { + kfree(apqns); + break; + } + if (!rc && kat.apqns) { + if (nr_apqns > kat.apqn_entries) { + kfree(apqns); + return -EINVAL; + } + len = nr_apqns * sizeof(struct pkey_apqn); + if (len) { + if (copy_to_user(kat.apqns, apqns, len)) { + kfree(apqns); + return -EFAULT; + } + } + } + kat.apqn_entries = nr_apqns; + if (copy_to_user(uat, &kat, sizeof(kat))) + rc = -EFAULT; + kfree(apqns); + break; + } default: /* unknown/unsupported ioctl cmd */ return -ENOTTY; diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 88c5f4a56be7..3b2d3705d2db 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -270,7 +270,7 @@ static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) * Generate (random) CCA AES DATA secure key. */ int cca_genseckey(u16 cardnr, u16 domain, - u32 keytype, u8 seckey[SECKEYBLOBSIZE]) + u32 keybitsize, u8 seckey[SECKEYBLOBSIZE]) { int i, rc, keysize; int seckeysize; @@ -325,22 +325,25 @@ int cca_genseckey(u16 cardnr, u16 domain, preqparm->rule_array_len = sizeof(preqparm->rule_array_len); preqparm->lv1.len = sizeof(struct lv1); memcpy(preqparm->lv1.key_form, "OP ", 8); - switch (keytype) { - case PKEY_KEYTYPE_AES_128: + switch (keybitsize) { + case PKEY_SIZE_AES_128: + case PKEY_KEYTYPE_AES_128: /* older ioctls used this */ keysize = 16; memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); break; - case PKEY_KEYTYPE_AES_192: + case PKEY_SIZE_AES_192: + case PKEY_KEYTYPE_AES_192: /* older ioctls used this */ keysize = 24; memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); break; - case PKEY_KEYTYPE_AES_256: + case PKEY_SIZE_AES_256: + case PKEY_KEYTYPE_AES_256: /* older ioctls used this */ keysize = 32; memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", - __func__, keytype); + DEBUG_ERR("%s unknown/unsupported keybitsize %d\n", + __func__, keybitsize); rc = -EINVAL; goto out; } @@ -408,7 +411,7 @@ EXPORT_SYMBOL(cca_genseckey); /* * Generate an CCA AES DATA secure key with given key value. */ -int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, +int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) { int rc, keysize, seckeysize; @@ -462,19 +465,22 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, memcpy(preqparm->rule_array, "AES ", 8); preqparm->rule_array_len = sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); - switch (keytype) { - case PKEY_KEYTYPE_AES_128: + switch (keybitsize) { + case PKEY_SIZE_AES_128: + case PKEY_KEYTYPE_AES_128: /* older ioctls used this */ keysize = 16; break; - case PKEY_KEYTYPE_AES_192: + case PKEY_SIZE_AES_192: + case PKEY_KEYTYPE_AES_192: /* older ioctls used this */ keysize = 24; break; - case PKEY_KEYTYPE_AES_256: + case PKEY_SIZE_AES_256: + case PKEY_KEYTYPE_AES_256: /* older ioctls used this */ keysize = 32; break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", - __func__, keytype); + DEBUG_ERR("%s unknown/unsupported keybitsize %d\n", + __func__, keybitsize); rc = -EINVAL; goto out; } @@ -545,8 +551,7 @@ EXPORT_SYMBOL(cca_clr2seckey); */ int cca_sec2protkey(u16 cardnr, u16 domain, const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, - u32 *keytype) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { int rc; u8 *mem; @@ -656,21 +661,21 @@ int cca_sec2protkey(u16 cardnr, u16 domain, switch (prepparm->lv3.keyblock.len) { case 16+32: /* AES 128 protected key */ - if (keytype) - *keytype = PKEY_KEYTYPE_AES_128; + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_128; break; case 24+32: /* AES 192 protected key */ - if (keytype) - *keytype = PKEY_KEYTYPE_AES_192; + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_192; break; case 32+32: /* AES 256 protected key */ - if (keytype) - *keytype = PKEY_KEYTYPE_AES_256; + if (protkeytype) + *protkeytype = PKEY_KEYTYPE_AES_256; break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", + DEBUG_ERR("%s unknown/unsupported keylen %d\n", __func__, prepparm->lv3.keyblock.len); rc = -EIO; goto out; @@ -1645,6 +1650,7 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) { u64 mkvp; + int minhwtype = 0; const struct keytoken_header *hdr = (struct keytoken_header *) key; if (hdr->type != TOKTYPE_CCA_INTERNAL) @@ -1654,11 +1660,15 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) case TOKVER_CCA_AES: mkvp = ((struct secaeskeytoken *)key)->mkvp; break; + case TOKVER_CCA_VLSC: + mkvp = ((struct cipherkeytoken *)key)->mkvp0; + minhwtype = AP_DEVICE_TYPE_CEX6; + break; default: return -EINVAL; } - return findcard(mkvp, pcardnr, pdomain, verify, 0); + return findcard(mkvp, pcardnr, pdomain, verify, minhwtype); } EXPORT_SYMBOL(cca_findcard); diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index e97cda0f61e0..77b6cc7b8f82 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -124,12 +124,12 @@ int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, /* * Generate (random) CCA AES DATA secure key. */ -int cca_genseckey(u16 cardnr, u16 domain, u32 keytype, u8 *seckey); +int cca_genseckey(u16 cardnr, u16 domain, u32 keybitsize, u8 *seckey); /* * Generate CCA AES DATA secure key with given clear key value. */ -int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, +int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, const u8 *clrkey, u8 *seckey); /* @@ -137,8 +137,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keytype, */ int cca_sec2protkey(u16 cardnr, u16 domain, const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, - u32 *protkeytype); + u8 *protkey, u32 *protkeylen, u32 *protkeytype); /* * Generate (random) CCA AES CIPHER secure key. @@ -169,6 +168,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, /* * Search for a matching crypto card based on the Master Key * Verification Pattern provided inside a secure key. + * Works with CCA AES data and cipher keys. * Returns < 0 on failure, 0 if CURRENT MKVP matches and * 1 if OLD MKVP matches. */ -- GitLab From 416f79c23dbe47e0e223efc06d3487e1d90a92ee Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Fri, 19 Jul 2019 15:22:26 +0200 Subject: [PATCH 3831/7155] s390/paes: Prepare paes functions for large key blobs The context used to store the key blob used a fixed 80 bytes buffer. And all the set_key functions did not even check the given key size. With CCA variable length AES cipher keys there come key blobs with about 136 bytes and maybe in the future there will arise the need to store even bigger key blobs. This patch reworks the paes set_key functions and the context buffers to work with small key blobs (<= 128 bytes) directly in the context buffer and larger blobs by allocating additional memory and storing the pointer in the context buffer. If there has been memory allocated for storing a key blob, it also needs to be freed on release of the tfm. So all the paes ciphers now have a init and exit function implemented for this job. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Vasily Gorbik --- arch/s390/crypto/paes_s390.c | 184 ++++++++++++++++++++++++++++++----- 1 file changed, 160 insertions(+), 24 deletions(-) diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index e8d9fa54569c..6184dceed340 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -5,7 +5,7 @@ * s390 implementation of the AES Cipher Algorithm with protected keys. * * s390 Version: - * Copyright IBM Corp. 2017 + * Copyright IBM Corp. 2017,2019 * Author(s): Martin Schwidefsky * Harald Freudenberger */ @@ -25,16 +25,59 @@ #include #include +/* + * Key blobs smaller/bigger than these defines are rejected + * by the common code even before the individual setkey function + * is called. As paes can handle different kinds of key blobs + * and padding is also possible, the limits need to be generous. + */ +#define PAES_MIN_KEYSIZE 64 +#define PAES_MAX_KEYSIZE 256 + static u8 *ctrblk; static DEFINE_SPINLOCK(ctrblk_lock); static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; struct key_blob { - __u8 key[MAXKEYBLOBSIZE]; + /* + * Small keys will be stored in the keybuf. Larger keys are + * stored in extra allocated memory. In both cases does + * key point to the memory where the key is stored. + * The code distinguishes by checking keylen against + * sizeof(keybuf). See the two following helper functions. + */ + u8 *key; + u8 keybuf[128]; unsigned int keylen; }; +static inline int _copy_key_to_kb(struct key_blob *kb, + const u8 *key, + unsigned int keylen) +{ + if (keylen <= sizeof(kb->keybuf)) + kb->key = kb->keybuf; + else { + kb->key = kmalloc(keylen, GFP_KERNEL); + if (!kb->key) + return -ENOMEM; + } + memcpy(kb->key, key, keylen); + kb->keylen = keylen; + + return 0; +} + +static inline void _free_kb_keybuf(struct key_blob *kb) +{ + if (kb->key && kb->key != kb->keybuf + && kb->keylen > sizeof(kb->keybuf)) { + kfree(kb->key); + kb->key = NULL; + } +} + struct s390_paes_ctx { struct key_blob kb; struct pkey_protkey pk; @@ -80,13 +123,33 @@ static int __paes_set_key(struct s390_paes_ctx *ctx) return ctx->fc ? 0 : -EINVAL; } +static int ecb_paes_init(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->kb.key = NULL; + + return 0; +} + +static void ecb_paes_exit(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + _free_kb_keybuf(&ctx->kb); +} + static int ecb_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { + int rc; struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); - memcpy(ctx->kb.key, in_key, key_len); - ctx->kb.keylen = key_len; + _free_kb_keybuf(&ctx->kb); + rc = _copy_key_to_kb(&ctx->kb, in_key, key_len); + if (rc) + return rc; + if (__paes_set_key(ctx)) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; @@ -148,10 +211,12 @@ static struct crypto_alg ecb_paes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(ecb_paes_alg.cra_list), + .cra_init = ecb_paes_init, + .cra_exit = ecb_paes_exit, .cra_u = { .blkcipher = { - .min_keysize = MINKEYBLOBSIZE, - .max_keysize = MAXKEYBLOBSIZE, + .min_keysize = PAES_MIN_KEYSIZE, + .max_keysize = PAES_MAX_KEYSIZE, .setkey = ecb_paes_set_key, .encrypt = ecb_paes_encrypt, .decrypt = ecb_paes_decrypt, @@ -159,6 +224,22 @@ static struct crypto_alg ecb_paes_alg = { } }; +static int cbc_paes_init(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->kb.key = NULL; + + return 0; +} + +static void cbc_paes_exit(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + _free_kb_keybuf(&ctx->kb); +} + static int __cbc_paes_set_key(struct s390_paes_ctx *ctx) { unsigned long fc; @@ -180,10 +261,14 @@ static int __cbc_paes_set_key(struct s390_paes_ctx *ctx) static int cbc_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { + int rc; struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); - memcpy(ctx->kb.key, in_key, key_len); - ctx->kb.keylen = key_len; + _free_kb_keybuf(&ctx->kb); + rc = _copy_key_to_kb(&ctx->kb, in_key, key_len); + if (rc) + return rc; + if (__cbc_paes_set_key(ctx)) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; @@ -252,10 +337,12 @@ static struct crypto_alg cbc_paes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(cbc_paes_alg.cra_list), + .cra_init = cbc_paes_init, + .cra_exit = cbc_paes_exit, .cra_u = { .blkcipher = { - .min_keysize = MINKEYBLOBSIZE, - .max_keysize = MAXKEYBLOBSIZE, + .min_keysize = PAES_MIN_KEYSIZE, + .max_keysize = PAES_MAX_KEYSIZE, .ivsize = AES_BLOCK_SIZE, .setkey = cbc_paes_set_key, .encrypt = cbc_paes_encrypt, @@ -264,6 +351,24 @@ static struct crypto_alg cbc_paes_alg = { } }; +static int xts_paes_init(struct crypto_tfm *tfm) +{ + struct s390_pxts_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->kb[0].key = NULL; + ctx->kb[1].key = NULL; + + return 0; +} + +static void xts_paes_exit(struct crypto_tfm *tfm) +{ + struct s390_pxts_ctx *ctx = crypto_tfm_ctx(tfm); + + _free_kb_keybuf(&ctx->kb[0]); + _free_kb_keybuf(&ctx->kb[1]); +} + static int __xts_paes_set_key(struct s390_pxts_ctx *ctx) { unsigned long fc; @@ -287,20 +392,27 @@ static int __xts_paes_set_key(struct s390_pxts_ctx *ctx) } static int xts_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int xts_key_len) { + int rc; struct s390_pxts_ctx *ctx = crypto_tfm_ctx(tfm); u8 ckey[2 * AES_MAX_KEY_SIZE]; - unsigned int ckey_len, keytok_len; + unsigned int ckey_len, key_len; - if (key_len % 2) + if (xts_key_len % 2) return -EINVAL; - keytok_len = key_len / 2; - memcpy(ctx->kb[0].key, in_key, keytok_len); - ctx->kb[0].keylen = keytok_len; - memcpy(ctx->kb[1].key, in_key + keytok_len, keytok_len); - ctx->kb[1].keylen = keytok_len; + key_len = xts_key_len / 2; + + _free_kb_keybuf(&ctx->kb[0]); + _free_kb_keybuf(&ctx->kb[1]); + rc = _copy_key_to_kb(&ctx->kb[0], in_key, key_len); + if (rc) + return rc; + rc = _copy_key_to_kb(&ctx->kb[1], in_key + key_len, key_len); + if (rc) + return rc; + if (__xts_paes_set_key(ctx)) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; @@ -394,10 +506,12 @@ static struct crypto_alg xts_paes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(xts_paes_alg.cra_list), + .cra_init = xts_paes_init, + .cra_exit = xts_paes_exit, .cra_u = { .blkcipher = { - .min_keysize = 2 * MINKEYBLOBSIZE, - .max_keysize = 2 * MAXKEYBLOBSIZE, + .min_keysize = 2 * PAES_MIN_KEYSIZE, + .max_keysize = 2 * PAES_MAX_KEYSIZE, .ivsize = AES_BLOCK_SIZE, .setkey = xts_paes_set_key, .encrypt = xts_paes_encrypt, @@ -406,6 +520,22 @@ static struct crypto_alg xts_paes_alg = { } }; +static int ctr_paes_init(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->kb.key = NULL; + + return 0; +} + +static void ctr_paes_exit(struct crypto_tfm *tfm) +{ + struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); + + _free_kb_keybuf(&ctx->kb); +} + static int __ctr_paes_set_key(struct s390_paes_ctx *ctx) { unsigned long fc; @@ -428,10 +558,14 @@ static int __ctr_paes_set_key(struct s390_paes_ctx *ctx) static int ctr_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { + int rc; struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); - memcpy(ctx->kb.key, in_key, key_len); - ctx->kb.keylen = key_len; + _free_kb_keybuf(&ctx->kb); + rc = _copy_key_to_kb(&ctx->kb, in_key, key_len); + if (rc) + return rc; + if (__ctr_paes_set_key(ctx)) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; @@ -541,10 +675,12 @@ static struct crypto_alg ctr_paes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(ctr_paes_alg.cra_list), + .cra_init = ctr_paes_init, + .cra_exit = ctr_paes_exit, .cra_u = { .blkcipher = { - .min_keysize = MINKEYBLOBSIZE, - .max_keysize = MAXKEYBLOBSIZE, + .min_keysize = PAES_MIN_KEYSIZE, + .max_keysize = PAES_MAX_KEYSIZE, .ivsize = AES_BLOCK_SIZE, .setkey = ctr_paes_set_key, .encrypt = ctr_paes_encrypt, -- GitLab From ac1213b7d79580ca52d7517e61e1ec4120134f0c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 3832/7155] gpio/ixp4xx: Register the base PA instead of its VA in fwnode Do not expose the base VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Reviewed-by: Linus Walleij Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ixp4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 8bd23e80c61f..1a57e74fdb91 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -231,7 +231,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) g->fwnode = of_node_to_fwnode(np); } else { parent = ixp4xx_get_irq_domain(); - g->fwnode = irq_domain_alloc_fwnode(g->base); + g->fwnode = irq_domain_alloc_fwnode(&res->start); if (!g->fwnode) { dev_err(dev, "no domain base\n"); return -ENODEV; -- GitLab From 23ad2b4672a7572e0f091cfe90aac1cd9bdca28a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Aug 2019 11:52:19 +0200 Subject: [PATCH 3833/7155] arm64: dts: renesas: r8a774c0: Fix register range of display node Since the R8A774C0 SoC uses DU{0,1} only, the register block length should be 0x40000. Based on commit 06585ed38b6698bc ("arm64: dts: renesas: r8a77990: Fix register range of display node") for R-Car E3. Fixes: 8ed3a6b223159df3 ("arm64: dts: renesas: r8a774c0: Add display output support") Signed-off-by: Geert Uytterhoeven Reviewed-by: Fabrizio Castro Reviewed-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index dc80c1a2ac1d..d0c9b419d190 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1805,7 +1805,7 @@ du: display@feb00000 { compatible = "renesas,du-r8a774c0"; - reg = <0 0xfeb00000 0 0x80000>; + reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; clocks = <&cpg CPG_MOD 724>, -- GitLab From 6eeb60be5ebb73b2e5911e26fb1aed02940b7d09 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 14 Aug 2019 11:29:10 +0300 Subject: [PATCH 3834/7155] ASoC: fsl_sai: Add support for imx8qm SAI module on imx8qm features a register map similar with imx6 series (it doesn't have VERID and PARAM registers at the beginning of address spece). Also, it has one FIFO which can help up to 64 * 32 bit samples. Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20190814082911.665-2-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 4a346fcb5630..728307acab90 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1031,12 +1031,19 @@ static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = { .reg_offset = 8, }; +static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = { + .use_imx_pcm = true, + .fifo_depth = 64, + .reg_offset = 0, +}; + static const struct of_device_id fsl_sai_ids[] = { { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data }, { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data }, { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data }, { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data }, { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data }, + { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); -- GitLab From c1fe93581ae9d85c3a783b5fad21912bb88a0f34 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 14 Aug 2019 11:29:11 +0300 Subject: [PATCH 3835/7155] ASoC: dt-bindings: Introduce compatible string for imx8qm Register map for i.MX8QM is similar with i.MX6 series. Integration of SAI IP into i.MX8QM SOC features a FIFO size of 64 X 32 bits samples. Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20190814082911.665-3-daniel.baluta@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-sai.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index e61c0dc1fc0b..0dc83cc4a236 100644 --- a/Documentation/devicetree/bindings/sound/fsl-sai.txt +++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt @@ -9,7 +9,8 @@ Required properties: - compatible : Compatible list, contains "fsl,vf610-sai", "fsl,imx6sx-sai", "fsl,imx6ul-sai", - "fsl,imx7ulp-sai" or "fsl,imx8mq-sai". + "fsl,imx7ulp-sai", "fsl,imx8mq-sai" or + "fsl,imx8qm-sai". - reg : Offset and length of the register set for the device. -- GitLab From b03bfaec1d52123d5d941488f71e06964535e471 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:04:54 +0900 Subject: [PATCH 3836/7155] ASoC: soc-core: merge snd_soc_initialize_card_lists() snd_soc_initialize_card_lists() is doing card related INIT_LIST_HEAD(), but, it is already doing at snd_soc_register_card(). We don't need to do it separately. This patch merges these. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/877e781ldq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ---------- sound/soc/soc-core.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 5c841c2ee814..f264c6509f00 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1220,16 +1220,6 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) return card->drvdata; } -static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) -{ - INIT_LIST_HEAD(&card->widgets); - INIT_LIST_HEAD(&card->paths); - INIT_LIST_HEAD(&card->dapm_list); - INIT_LIST_HEAD(&card->aux_comp_list); - INIT_LIST_HEAD(&card->component_dev_list); - INIT_LIST_HEAD(&card->list); -} - static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b3f820fb53e6..d428491d51a7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2370,15 +2370,18 @@ int snd_soc_register_card(struct snd_soc_card *card) dev_set_drvdata(card->dev, card); - snd_soc_initialize_card_lists(card); - + INIT_LIST_HEAD(&card->widgets); + INIT_LIST_HEAD(&card->paths); + INIT_LIST_HEAD(&card->dapm_list); + INIT_LIST_HEAD(&card->aux_comp_list); + INIT_LIST_HEAD(&card->component_dev_list); + INIT_LIST_HEAD(&card->list); INIT_LIST_HEAD(&card->dai_link_list); - INIT_LIST_HEAD(&card->rtd_list); - card->num_rtd = 0; - INIT_LIST_HEAD(&card->dapm_dirty); INIT_LIST_HEAD(&card->dobj_list); + + card->num_rtd = 0; card->instantiated = 0; mutex_init(&card->mutex); mutex_init(&card->dapm_mutex); -- GitLab From c26a8841119826badc8d358a4266880f83359f26 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:04:58 +0900 Subject: [PATCH 3837/7155] ASoC: soc-core: remove unneeded dai_link check from snd_soc_remove_dai_link() snd_soc_remove_dai_link() has card connected dai_link check. but 1) we need to call list_del() anyway, because it is "remove" function, 2) It is doing many thing for this card / dai_link already before checking dai_link. This patch removes poinless dai_link check Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/875zms1ldm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d428491d51a7..6df880be1622 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1182,8 +1182,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_link); void snd_soc_remove_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct snd_soc_dai_link *link, *_link; - if (dai_link->dobj.type && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) { dev_err(card->dev, "Invalid dai link type %d\n", @@ -1199,12 +1197,7 @@ void snd_soc_remove_dai_link(struct snd_soc_card *card, if (dai_link->dobj.type && card->remove_dai_link) card->remove_dai_link(card, dai_link); - for_each_card_links_safe(card, link, _link) { - if (link == dai_link) { - list_del(&link->list); - return; - } - } + list_del(&dai_link->list); } EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link); -- GitLab From 137befe19f310400a8b20fd8a4ce8c4141aafde0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 19 Aug 2019 21:25:27 +0200 Subject: [PATCH 3838/7155] ASoC: sun4i-i2s: Add support for TDM slots The i2s controller supports TDM, for up to 8 slots. Let's support the TDM API. Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/26392af30b3e7b31ee48d5b867d45be8675db046.1566242458.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 40 +++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 9e691baee1e8..8326b8cfa569 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -168,6 +168,8 @@ struct sun4i_i2s { struct reset_control *rst; unsigned int mclk_freq; + unsigned int slots; + unsigned int slot_width; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; @@ -287,7 +289,7 @@ static bool sun4i_i2s_oversample_is_valid(unsigned int oversample) static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, unsigned int rate, - unsigned int channels, + unsigned int slots, unsigned int word_size) { struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); @@ -335,7 +337,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s); bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate, - rate, channels, word_size); + rate, slots, word_size); if (bclk_div < 0) { dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); return -EINVAL; @@ -419,6 +421,10 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, const struct snd_pcm_hw_params *params) { unsigned int channels = params_channels(params); + unsigned int slots = channels; + + if (i2s->slots) + slots = i2s->slots; /* Map the channels for playback and capture */ regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); @@ -428,7 +434,6 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, SUN4I_I2S_CHAN_SEL_MASK, SUN4I_I2S_CHAN_SEL(channels)); - regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, SUN4I_I2S_CHAN_SEL_MASK, SUN4I_I2S_CHAN_SEL(channels)); @@ -452,10 +457,18 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int word_size = params_width(params); unsigned int channels = params_channels(params); + unsigned int slots = channels; int ret, sr, wss; u32 width; + if (i2s->slots) + slots = i2s->slots; + + if (i2s->slot_width) + word_size = i2s->slot_width; + ret = i2s->variant->set_chan_cfg(i2s, params); if (ret < 0) { dev_err(dai->dev, "Invalid channel configuration\n"); @@ -477,15 +490,14 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, if (sr < 0) return -EINVAL; - wss = i2s->variant->get_wss(i2s, params_width(params)); + wss = i2s->variant->get_wss(i2s, word_size); if (wss < 0) return -EINVAL; regmap_field_write(i2s->field_fmt_wss, wss); regmap_field_write(i2s->field_fmt_sr, sr); - return sun4i_i2s_set_clk_rate(dai, params_rate(params), - channels, params_width(params)); + return sun4i_i2s_set_clk_rate(dai, params_rate(params), slots, word_size); } static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, @@ -785,10 +797,26 @@ static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } +static int sun4i_i2s_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + if (slots > 8) + return -EINVAL; + + i2s->slots = slots; + i2s->slot_width = slot_width; + + return 0; +} + static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { .hw_params = sun4i_i2s_hw_params, .set_fmt = sun4i_i2s_set_fmt, .set_sysclk = sun4i_i2s_set_sysclk, + .set_tdm_slot = sun4i_i2s_set_tdm_slot, .trigger = sun4i_i2s_trigger, }; -- GitLab From fe9841595c604ce942c3729a72411096c3f4b675 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 27 Feb 2019 14:02:54 +0900 Subject: [PATCH 3839/7155] arm64: dts: renesas: r8a77965-salvator-x(s): Enable HDMI sound Signed-off-by: Kuninori Morimoto Tested-by: Jacopo Mondi # Salvator-XS [geert: Preserve sort order] Signed-off-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a77965-salvator-x.dts | 28 +++++++++++++++++++ .../boot/dts/renesas/r8a77965-salvator-xs.dts | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts index 340a3c72b65a..660a0240eec5 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts @@ -41,9 +41,37 @@ remote-endpoint = <&hdmi0_con>; }; }; + port@2 { + reg = <2>; + dw_hdmi0_snd_in: endpoint { + remote-endpoint = <&rsnd_endpoint1>; + }; + }; }; }; &hdmi0_con { remote-endpoint = <&rcar_dw_hdmi0_out>; }; + +&rcar_sound { + ports { + rsnd_port1: port@1 { + reg = <1>; + rsnd_endpoint1: endpoint { + remote-endpoint = <&dw_hdmi0_snd_in>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_endpoint1>; + frame-master = <&rsnd_endpoint1>; + + playback = <&ssi2>; + }; + }; + }; +}; + +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1>; /* HDMI0 */ +}; diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts index f03a5e9e0c42..5cef64605464 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts +++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts @@ -41,6 +41,12 @@ remote-endpoint = <&hdmi0_con>; }; }; + port@2 { + reg = <2>; + dw_hdmi0_snd_in: endpoint { + remote-endpoint = <&rsnd_endpoint1>; + }; + }; }; }; @@ -57,7 +63,29 @@ }; }; +&rcar_sound { + ports { + rsnd_port1: port@1 { + reg = <1>; + rsnd_endpoint1: endpoint { + remote-endpoint = <&dw_hdmi0_snd_in>; + + dai-format = "i2s"; + bitclock-master = <&rsnd_endpoint1>; + frame-master = <&rsnd_endpoint1>; + + playback = <&ssi2>; + }; + }; + }; +}; + /* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */ &sata { status = "okay"; }; + +&sound_card { + dais = <&rsnd_port0 /* ak4613 */ + &rsnd_port1>; /* HDMI0 */ +}; -- GitLab From 38290431d56d7d3928ac89e9f8d3d6b3c8df4c6e Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Sat, 6 Jul 2019 16:07:30 +0200 Subject: [PATCH 3840/7155] arm64: dts: renesas: Update 'vsps' properties for readability Update the 'vsps' property in the R-Car Gen3 SoC device tree files to match what's in the documentation example. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77965.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77990.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index d0c9b419d190..a1c2de90e470 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1811,7 +1811,7 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; - vsps = <&vspd0 0 &vspd1 0>; + vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 6cd5fe4c1da6..95deff66eeb6 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -3112,7 +3112,7 @@ <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.2", "du.3"; - vsps = <&vspd0 0 &vspd1 0 &vspd2 0 &vspd0 1>; + vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 09e4f52db764..4ae163220f60 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2469,7 +2469,7 @@ clock-names = "du.0", "du.1", "du.3"; status = "disabled"; - vsps = <&vspd0 0 &vspd1 0 &vspd0 1>; + vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index e51bc4c8a0bb..455954c3d98e 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1768,7 +1768,7 @@ clock-names = "du.0", "du.1"; resets = <&cpg 724>; reset-names = "du.0"; - vsps = <&vspd0 0 &vspd1 0>; + vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index b3dbf557bc97..183fef86cf7c 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -1003,7 +1003,7 @@ clock-names = "du.0", "du.1"; resets = <&cpg 724>; reset-names = "du.0"; - vsps = <&vspd0 0 &vspd1 0>; + vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; ports { -- GitLab From 71dd77fd4bf7d1675a95dfe04a99669ce15b58f8 Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Thu, 15 Aug 2019 15:13:54 +0300 Subject: [PATCH 3841/7155] libbpf: use LFS (_FILE_OFFSET_BITS) instead of direct mmap2 syscall Drop __NR_mmap2 fork in flavor of LFS, that is _FILE_OFFSET_BITS=64 (glibc & bionic) / LARGEFILE64_SOURCE (for musl) decision. It allows mmap() to use 64bit offset that is passed to mmap2 syscall. As result pgoff is not truncated and no need to use direct access to mmap2 for 32 bits systems. Signed-off-by: Ivan Khoronzhuk Acked-by: Yonghong Song Signed-off-by: Daniel Borkmann --- tools/lib/bpf/Makefile | 1 + tools/lib/bpf/xsk.c | 49 ++++++++++++------------------------------ 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index 148a27164189..613acb93b144 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -108,6 +108,7 @@ override CFLAGS += -Werror -Wall override CFLAGS += -fPIC override CFLAGS += $(INCLUDES) override CFLAGS += -fvisibility=hidden +override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ifeq ($(VERBOSE),1) Q = diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index 17e8d79c11a8..12ad78510147 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -74,23 +74,6 @@ struct xsk_nl_info { int fd; }; -/* For 32-bit systems, we need to use mmap2 as the offsets are 64-bit. - * Unfortunately, it is not part of glibc. - */ -static inline void *xsk_mmap(void *addr, size_t length, int prot, int flags, - int fd, __u64 offset) -{ -#ifdef __NR_mmap2 - unsigned int page_shift = __builtin_ffs(getpagesize()) - 1; - long ret = syscall(__NR_mmap2, addr, length, prot, flags, fd, - (off_t)(offset >> page_shift)); - - return (void *)ret; -#else - return mmap(addr, length, prot, flags, fd, offset); -#endif -} - int xsk_umem__fd(const struct xsk_umem *umem) { return umem ? umem->fd : -EINVAL; @@ -210,10 +193,9 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size, goto out_socket; } - map = xsk_mmap(NULL, off.fr.desc + - umem->config.fill_size * sizeof(__u64), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, - umem->fd, XDP_UMEM_PGOFF_FILL_RING); + map = mmap(NULL, off.fr.desc + umem->config.fill_size * sizeof(__u64), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd, + XDP_UMEM_PGOFF_FILL_RING); if (map == MAP_FAILED) { err = -errno; goto out_socket; @@ -228,10 +210,9 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size, fill->ring = map + off.fr.desc; fill->cached_cons = umem->config.fill_size; - map = xsk_mmap(NULL, - off.cr.desc + umem->config.comp_size * sizeof(__u64), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, - umem->fd, XDP_UMEM_PGOFF_COMPLETION_RING); + map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd, + XDP_UMEM_PGOFF_COMPLETION_RING); if (map == MAP_FAILED) { err = -errno; goto out_mmap; @@ -552,11 +533,10 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname, } if (rx) { - rx_map = xsk_mmap(NULL, off.rx.desc + - xsk->config.rx_size * sizeof(struct xdp_desc), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, - xsk->fd, XDP_PGOFF_RX_RING); + rx_map = mmap(NULL, off.rx.desc + + xsk->config.rx_size * sizeof(struct xdp_desc), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + xsk->fd, XDP_PGOFF_RX_RING); if (rx_map == MAP_FAILED) { err = -errno; goto out_socket; @@ -572,11 +552,10 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname, xsk->rx = rx; if (tx) { - tx_map = xsk_mmap(NULL, off.tx.desc + - xsk->config.tx_size * sizeof(struct xdp_desc), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, - xsk->fd, XDP_PGOFF_TX_RING); + tx_map = mmap(NULL, off.tx.desc + + xsk->config.tx_size * sizeof(struct xdp_desc), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + xsk->fd, XDP_PGOFF_TX_RING); if (tx_map == MAP_FAILED) { err = -errno; goto out_mmap_rx; -- GitLab From 624676e788992e4da8de1fad93bfe51563a7f9a0 Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Thu, 15 Aug 2019 15:13:55 +0300 Subject: [PATCH 3842/7155] xdp: xdp_umem: replace kmap on vmap for umem map For 64-bit there is no reason to use vmap/vunmap, so use page_address as it was initially. For 32 bits, in some apps, like in samples xdpsock_user.c when number of pgs in use is quite big, the kmap memory can be not enough, despite on this, kmap looks like is deprecated in such cases as it can block and should be used rather for dynamic mm. Signed-off-by: Ivan Khoronzhuk Acked-by: Jonathan Lemon Signed-off-by: Daniel Borkmann --- net/xdp/xdp_umem.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index cda6feb1edb0..2d65779282a1 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "xdp_umem.h" #include "xsk_queue.h" @@ -178,7 +178,30 @@ static void xdp_umem_unmap_pages(struct xdp_umem *umem) unsigned int i; for (i = 0; i < umem->npgs; i++) - kunmap(umem->pgs[i]); + if (PageHighMem(umem->pgs[i])) + vunmap(umem->pages[i].addr); +} + +static int xdp_umem_map_pages(struct xdp_umem *umem) +{ + unsigned int i; + void *addr; + + for (i = 0; i < umem->npgs; i++) { + if (PageHighMem(umem->pgs[i])) + addr = vmap(&umem->pgs[i], 1, VM_MAP, PAGE_KERNEL); + else + addr = page_address(umem->pgs[i]); + + if (!addr) { + xdp_umem_unmap_pages(umem); + return -ENOMEM; + } + + umem->pages[i].addr = addr; + } + + return 0; } static void xdp_umem_unpin_pages(struct xdp_umem *umem) @@ -320,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) u32 chunk_size = mr->chunk_size, headroom = mr->headroom; unsigned int chunks, chunks_per_page; u64 addr = mr->addr, size = mr->len; - int size_chk, err, i; + int size_chk, err; if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { /* Strictly speaking we could support this, if: @@ -386,10 +409,11 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) goto out_account; } - for (i = 0; i < umem->npgs; i++) - umem->pages[i].addr = kmap(umem->pgs[i]); + err = xdp_umem_map_pages(umem); + if (!err) + return 0; - return 0; + kfree(umem->pages); out_account: xdp_umem_unaccount_pages(umem); -- GitLab From bb4b5c08a8e0f854a313184498b22fa37dd087db Mon Sep 17 00:00:00 2001 From: Ivan Khoronzhuk Date: Thu, 15 Aug 2019 15:13:56 +0300 Subject: [PATCH 3843/7155] samples: bpf: syscall_nrs: use mmap2 if defined For arm32 xdp sockets mmap2 is preferred, so use it if it's defined. Declaration of __NR_mmap can be skipped and it breaks build. Signed-off-by: Ivan Khoronzhuk Acked-by: Jonathan Lemon Signed-off-by: Daniel Borkmann --- samples/bpf/syscall_nrs.c | 6 ++++++ samples/bpf/tracex5_kern.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/samples/bpf/syscall_nrs.c b/samples/bpf/syscall_nrs.c index 516e255cbe8f..88f940052450 100644 --- a/samples/bpf/syscall_nrs.c +++ b/samples/bpf/syscall_nrs.c @@ -9,5 +9,11 @@ void syscall_defines(void) COMMENT("Linux system call numbers."); SYSNR(__NR_write); SYSNR(__NR_read); +#ifdef __NR_mmap2 + SYSNR(__NR_mmap2); +#endif +#ifdef __NR_mmap SYSNR(__NR_mmap); +#endif + } diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c index f57f4e1ea1ec..35cb0eed3be5 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5_kern.c @@ -68,12 +68,25 @@ PROG(SYS__NR_read)(struct pt_regs *ctx) return 0; } +#ifdef __NR_mmap2 +PROG(SYS__NR_mmap2)(struct pt_regs *ctx) +{ + char fmt[] = "mmap2\n"; + + bpf_trace_printk(fmt, sizeof(fmt)); + return 0; +} +#endif + +#ifdef __NR_mmap PROG(SYS__NR_mmap)(struct pt_regs *ctx) { char fmt[] = "mmap\n"; + bpf_trace_printk(fmt, sizeof(fmt)); return 0; } +#endif char _license[] SEC("license") = "GPL"; u32 _version SEC("version") = LINUX_VERSION_CODE; -- GitLab From 97c62614331a34cd84f4db563169e8004b2e3fc3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 9 Aug 2019 17:20:29 -0700 Subject: [PATCH 3844/7155] ARM: ux500: improve BU21013 touchpad bindings In preparation to update to bu21013_tp driver properly annotate GPIOs property (the INT GPIOs are active low, not open drain), and also define interrupt lines so we do not have to have special conversion in the driver. Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-hrefprev60-stuib.dts | 14 ++++++++++---- arch/arm/boot/dts/ste-hrefv60plus-stuib.dts | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts index aed940bd65a8..b78be5f4c212 100644 --- a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts +++ b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include +#include #include "ste-hrefprev60.dtsi" #include "ste-href-stuib.dtsi" @@ -23,12 +25,16 @@ i2c@80110000 { /* Only one of these will be used */ bu21013_tp@5c { - touch-gpio = <&gpio2 12 0x4>; - reset-gpio = <&tc3589x_gpio 13 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>; }; bu21013_tp@5d { - touch-gpio = <&gpio2 12 0x4>; - reset-gpio = <&tc3589x_gpio 13 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>; }; }; }; diff --git a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts index 0f3c3b86bb20..9be513aad549 100644 --- a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts +++ b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts @@ -6,6 +6,8 @@ */ /dts-v1/; +#include +#include #include "ste-hrefv60plus.dtsi" #include "ste-href-stuib.dtsi" @@ -25,12 +27,16 @@ i2c@80110000 { /* Only one of these will be used */ bu21013_tp@5c { - touch-gpio = <&gpio2 20 0x4>; - reset-gpio = <&gpio4 17 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>; }; bu21013_tp@5d { - touch-gpio = <&gpio2 20 0x4>; - reset-gpio = <&gpio4 17 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>; }; }; }; -- GitLab From 598bb8913d015150b7734b55443c0e53e7189fc7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:26 +0800 Subject: [PATCH 3845/7155] staging: erofs: avoid endless loop of invalid lookback distance 0 As reported by erofs-utils fuzzer, Lookback distance should be a positive number, so it should be actually looked back rather than spinning. Fixes: 02827e1796b3 ("staging: erofs: add erofs_map_blocks_iter") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-7-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zmap.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 7408e86823a4..774dacbc5b32 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -350,6 +350,12 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, switch (m->type) { case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + if (unlikely(!m->delta[0])) { + errln("invalid lookback distance 0 at nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } return vle_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; -- GitLab From 88db7fc592559226cda373245770d90af0af3b0a Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 21 Aug 2019 00:33:56 +0900 Subject: [PATCH 3846/7155] staging: comedi: ni_mio_common: Fix a typo in ni_mio_common.c This patch fix a spelling typo in ni_mio_common.c Signed-off-by: Masanari Iida Link: https://lore.kernel.org/r/20190820153356.25189-1-standby24x7@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index c175227009f1..f98e3ae27bff 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -596,7 +596,7 @@ static int ni_request_ao_mite_channel(struct comedi_device *dev) if (!mite_chan) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); dev_err(dev->class_dev, - "failed to reserve mite dma channel for analog outut\n"); + "failed to reserve mite dma channel for analog output\n"); return -EBUSY; } mite_chan->dir = COMEDI_OUTPUT; -- GitLab From 2cb05d8788f77ed14b99a0fbb2748346071f3a33 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Mon, 19 Aug 2019 22:27:05 +0530 Subject: [PATCH 3847/7155] staging: rtl8723bs: core: Remove unneeded declaration WFD_OUI Remove unneeded declaration "extern unsigned char WFD_OUI" Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190819165705.GA5782@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 02f5478845b4..6d18d23acdc0 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -13,7 +13,6 @@ extern unsigned char RTW_WPA_OUI[]; extern unsigned char WMM_OUI[]; extern unsigned char WPS_OUI[]; extern unsigned char P2P_OUI[]; -extern unsigned char WFD_OUI[]; void init_mlme_ap_info(struct adapter *padapter) { -- GitLab From bfc4ccb1584129d3ef051f8bf6155835374f132f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 21 Aug 2019 11:09:08 +0800 Subject: [PATCH 3848/7155] staging: erofs: avoid loop in submit chains As reported by erofs-utils fuzzer, 2 conditions can happen in corrupted images, which can cause unexpected behaviors. - access the same pcluster one more time; - access the tail end pcluster again, e.g. _ access again (will trigger tail merging) | 1 2 3 1 2 -> 1 2 3 1 |_ tail end of the chain \___/ (unexpected behavior) Let's detect and avoid them now. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190821030908.40282-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 23283c97fd3b..4d6faaab04f5 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -132,7 +132,7 @@ enum z_erofs_collectmode { struct z_erofs_collector { struct z_erofs_pagevec_ctor vector; - struct z_erofs_pcluster *pcl; + struct z_erofs_pcluster *pcl, *tailpcl; struct z_erofs_collection *cl; struct page **compressedpages; z_erofs_next_pcluster_t owned_head; @@ -353,6 +353,11 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, return NULL; pcl = container_of(grp, struct z_erofs_pcluster, obj); + if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } cl = z_erofs_primarycollection(pcl); if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { @@ -381,7 +386,13 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, } } mutex_lock(&cl->lock); + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = NULL; clt->pcl = pcl; clt->cl = cl; return cl; @@ -434,6 +445,9 @@ static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, kmem_cache_free(pcluster_cachep, pcl); return ERR_PTR(-EAGAIN); } + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; clt->owned_head = &pcl->next; clt->pcl = pcl; clt->cl = cl; -- GitLab From f55ef00e0ea2664e1a2a7bd4e8670d27a0bf2b86 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 18 Aug 2019 17:06:09 +0200 Subject: [PATCH 3849/7155] staging: rtl8712: Improve naming of include hearder guards Choose a better name for the include hearder guard used in rtl871x_io.h. '_IO_H_' is to generic and does not match the comment after the #endif. Use '_RTL871X_IO_H_' instead. Also make the comments in the #endif /* XXX */ match the name used in #ifndef. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190818150609.3376-1-christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_io.h | 7 +++---- drivers/staging/rtl8712/rtl871x_rf.h | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index 28941423b7ed..c20dd5a6bbd1 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -11,8 +11,8 @@ * Larry Finger * ******************************************************************************/ -#ifndef _IO_H_ -#define _IO_H_ +#ifndef _RTL871X_IO_H_ +#define _RTL871X_IO_H_ #include "osdep_service.h" #include "osdep_intf.h" @@ -234,5 +234,4 @@ void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); uint r8712_alloc_io_queue(struct _adapter *adapter); void r8712_free_io_queue(struct _adapter *adapter); -#endif /*_RTL8711_IO_H_*/ - +#endif /*_RTL871X_IO_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h index cc54453cd424..7d98921a48fa 100644 --- a/drivers/staging/rtl8712/rtl871x_rf.h +++ b/drivers/staging/rtl8712/rtl871x_rf.h @@ -52,5 +52,4 @@ enum { RTL8712_RFC_2T2R = 0x22 }; -#endif /*_RTL8711_RF_H_*/ - +#endif /*__RTL871X_RF_H_*/ -- GitLab From be237202ee052ef2885285b4550d9638470ce38d Mon Sep 17 00:00:00 2001 From: Donald Yandt Date: Sun, 18 Aug 2019 11:20:23 -0400 Subject: [PATCH 3850/7155] staging: android: Remove ion device tree bindings from the TODO Commit 23a4388f24f5 ("staging: android: ion: Remove file ion_chunk_heap.c") and eadbf7a34e44 ("staging: android: ion: Remove file ion_carveout_heap.c") removed the chunk and carveout heaps from ion but left behind the device tree bindings for them in the TODO, this patch removes it. Signed-off-by: Donald Yandt Link: https://lore.kernel.org/r/20190818152023.891-1-donald.yandt@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index fbf015cc6d62..767dd98fd92d 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -6,8 +6,6 @@ TODO: ion/ - - Add dt-bindings for remaining heaps (chunk and carveout heaps). This would - involve putting appropriate bindings in a memory node for Ion to find. - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0) - Better test framework (integration with VGEM was suggested) -- GitLab From 1327d35ac3c187b3c1ae650d90400f8fe5e41b94 Mon Sep 17 00:00:00 2001 From: Eduardo Barretto Date: Sun, 18 Aug 2019 15:35:55 -0300 Subject: [PATCH 3851/7155] staging: kpc2000: kpc2000_i2c: Fix different address spaces warnings This patch fixes the following sparse warnings: kpc2000_i2c.c:137: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:137: expected void const volatile [noderef] *addr kpc2000_i2c.c:137: got void * kpc2000_i2c.c:146: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:146: expected void volatile [noderef] *addr kpc2000_i2c.c:146: got void * kpc2000_i2c.c:147: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:147: expected void const volatile [noderef] *addr kpc2000_i2c.c:147: got void * kpc2000_i2c.c:166: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:166: expected void const volatile [noderef] *addr kpc2000_i2c.c:166: got void * kpc2000_i2c.c:166: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:166: expected void volatile [noderef] *addr kpc2000_i2c.c:166: got void * kpc2000_i2c.c:168: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:168: expected void const volatile [noderef] *addr kpc2000_i2c.c:168: got void * kpc2000_i2c.c:168: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:168: expected void volatile [noderef] *addr kpc2000_i2c.c:168: got void * kpc2000_i2c.c:171: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:171: expected void const volatile [noderef] *addr kpc2000_i2c.c:171: got void * kpc2000_i2c.c:174: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:174: expected void volatile [noderef] *addr kpc2000_i2c.c:174: got void * kpc2000_i2c.c:193: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:193: expected void volatile [noderef] *addr kpc2000_i2c.c:193: got void * kpc2000_i2c.c:194: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:194: expected void const volatile [noderef] *addr kpc2000_i2c.c:194: got void * kpc2000_i2c.c:214: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:214: expected void volatile [noderef] *addr kpc2000_i2c.c:214: got void * kpc2000_i2c.c:219: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:219: expected void const volatile [noderef] *addr kpc2000_i2c.c:219: got void * kpc2000_i2c.c:226: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:226: expected void volatile [noderef] *addr kpc2000_i2c.c:226: got void * kpc2000_i2c.c:238: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:238: expected void const volatile [noderef] *addr kpc2000_i2c.c:238: got void * kpc2000_i2c.c:244: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:244: expected void volatile [noderef] *addr kpc2000_i2c.c:244: got void * kpc2000_i2c.c:252: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:252: expected void const volatile [noderef] *addr kpc2000_i2c.c:252: got void * kpc2000_i2c.c:257: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:257: expected void volatile [noderef] *addr kpc2000_i2c.c:257: got void * kpc2000_i2c.c:259: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:259: expected void volatile [noderef] *addr kpc2000_i2c.c:259: got void * kpc2000_i2c.c:267: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:267: expected void const volatile [noderef] *addr kpc2000_i2c.c:267: got void * kpc2000_i2c.c:273: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:273: expected void const volatile [noderef] *addr kpc2000_i2c.c:273: got void * kpc2000_i2c.c:293: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:293: expected void volatile [noderef] *addr kpc2000_i2c.c:293: got void * kpc2000_i2c.c:294: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:294: expected void volatile [noderef] *addr kpc2000_i2c.c:294: got void * kpc2000_i2c.c:309: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:309: expected void volatile [noderef] *addr kpc2000_i2c.c:309: got void * kpc2000_i2c.c:312: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:312: expected void volatile [noderef] *addr kpc2000_i2c.c:312: got void * kpc2000_i2c.c:317: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:317: expected void const volatile [noderef] *addr kpc2000_i2c.c:317: got void * kpc2000_i2c.c:324: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:324: expected void const volatile [noderef] *addr kpc2000_i2c.c:324: got void * kpc2000_i2c.c:328: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:328: expected void const volatile [noderef] *addr kpc2000_i2c.c:328: got void * kpc2000_i2c.c:329: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:329: expected void volatile [noderef] *addr kpc2000_i2c.c:329: got void * kpc2000_i2c.c:330: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:330: expected void volatile [noderef] *addr kpc2000_i2c.c:330: got void * kpc2000_i2c.c:338: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:338: expected void const volatile [noderef] *addr kpc2000_i2c.c:338: got void * kpc2000_i2c.c:340: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:340: expected void volatile [noderef] *addr kpc2000_i2c.c:340: got void * kpc2000_i2c.c:342: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:342: expected void volatile [noderef] *addr kpc2000_i2c.c:342: got void * kpc2000_i2c.c:350: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:350: expected void const volatile [noderef] *addr kpc2000_i2c.c:350: got void * kpc2000_i2c.c:350: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:350: expected void volatile [noderef] *addr kpc2000_i2c.c:350: got void * kpc2000_i2c.c:351: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:351: expected void const volatile [noderef] *addr kpc2000_i2c.c:351: got void * kpc2000_i2c.c:414: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:414: expected void volatile [noderef] *addr kpc2000_i2c.c:414: got void * kpc2000_i2c.c:420: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:420: expected void volatile [noderef] *addr kpc2000_i2c.c:420: got void * kpc2000_i2c.c:422: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:422: expected void volatile [noderef] *addr kpc2000_i2c.c:422: got void * kpc2000_i2c.c:427: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:427: expected void volatile [noderef] *addr kpc2000_i2c.c:427: got void * kpc2000_i2c.c:428: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:428: expected void volatile [noderef] *addr kpc2000_i2c.c:428: got void * kpc2000_i2c.c:430: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:430: expected void volatile [noderef] *addr kpc2000_i2c.c:430: got void * kpc2000_i2c.c:435: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:435: expected void volatile [noderef] *addr kpc2000_i2c.c:435: got void * kpc2000_i2c.c:436: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:436: expected void volatile [noderef] *addr kpc2000_i2c.c:436: got void * kpc2000_i2c.c:438: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:438: expected void volatile [noderef] *addr kpc2000_i2c.c:438: got void * kpc2000_i2c.c:439: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:439: expected void volatile [noderef] *addr kpc2000_i2c.c:439: got void * kpc2000_i2c.c:445: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:445: expected void volatile [noderef] *addr kpc2000_i2c.c:445: got void * kpc2000_i2c.c:446: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:446: expected void volatile [noderef] *addr kpc2000_i2c.c:446: got void * kpc2000_i2c.c:454: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:454: expected void volatile [noderef] *addr kpc2000_i2c.c:454: got void * kpc2000_i2c.c:459: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:459: expected void volatile [noderef] *addr kpc2000_i2c.c:459: got void * kpc2000_i2c.c:461: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:461: expected void volatile [noderef] *addr kpc2000_i2c.c:461: got void * kpc2000_i2c.c:472: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:472: expected void const volatile [noderef] *addr kpc2000_i2c.c:472: got void * kpc2000_i2c.c:472: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:472: expected void volatile [noderef] *addr kpc2000_i2c.c:472: got void * kpc2000_i2c.c:475: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:475: expected void const volatile [noderef] *addr kpc2000_i2c.c:475: got void * kpc2000_i2c.c:475: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:475: expected void volatile [noderef] *addr kpc2000_i2c.c:475: got void * kpc2000_i2c.c:493: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:493: expected void const volatile [noderef] *addr kpc2000_i2c.c:493: got void * kpc2000_i2c.c:493: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:493: expected void volatile [noderef] *addr kpc2000_i2c.c:493: got void * kpc2000_i2c.c:512: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:512: expected void const volatile [noderef] *addr kpc2000_i2c.c:512: got void * kpc2000_i2c.c:516: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:516: expected void const volatile [noderef] *addr kpc2000_i2c.c:516: got void * kpc2000_i2c.c:516: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:516: expected void const volatile [noderef] *addr kpc2000_i2c.c:516: got void * Signed-off-by: Eduardo Barretto Link: https://lore.kernel.org/r/20190818183555.7167-1-edusbarretto@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index b108da4ac633..bc02534d8dc3 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -123,9 +123,9 @@ struct i2c_device { // FIXME! #undef inb_p -#define inb_p(a) readq((void *)a) +#define inb_p(a) readq((void __iomem *)a) #undef outb_p -#define outb_p(d, a) writeq(d, (void *)a) +#define outb_p(d, a) writeq(d, (void __iomem *)a) /* Make sure the SMBus host is ready to start transmitting. * Return 0 if it is, -EBUSY if it is not. -- GitLab From 8467c3b456b57fcb4b3179c34c20cbc9c88956c5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 18 Aug 2019 19:46:49 +0100 Subject: [PATCH 3852/7155] staging: rts5208: remove redundant assignment to retval Variable retval is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190818184649.13828-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 1128eec3bd08..e853fa9cc950 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -3842,7 +3842,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - int retval = STATUS_FAIL; + int retval; int bufflen; unsigned int lun = SCSI_LUN(srb); u8 *buf = NULL; -- GitLab From fdf37037664041cfdbcab6cf54ddb2c1c219034b Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 20 Aug 2019 13:29:39 +0200 Subject: [PATCH 3853/7155] btf: do not use CONFIG_OUTPUT_FORMAT Building s390 kernel with CONFIG_DEBUG_INFO_BTF fails, because CONFIG_OUTPUT_FORMAT is not defined. As a matter of fact, this variable appears to be x86-only, so other arches might be affected as well. Fix by obtaining this value from objdump output, just like it's already done for bin_arch. The exact objdump invocation is "inspired" by arch/powerpc/boot/wrapper. Also, use LANG=C for the existing bin_arch objdump invocation to avoid potential build issues on systems with non-English locale. Fixes: 341dfcf8d78e ("btf: expose BTF info through sysfs") Signed-off-by: Ilya Leoshkevich Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index c31193340108..0d8f41db8cd6 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -115,10 +115,12 @@ gen_btf() LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} # dump .BTF section into raw binary file to link with final vmlinux - bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \ + bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \ cut -d, -f1 | cut -d' ' -f2) + bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \ + awk '{print $4}') ${OBJCOPY} --dump-section .BTF=.btf.vmlinux.bin ${1} 2>/dev/null - ${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \ + ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \ --rename-section .data=.BTF .btf.vmlinux.bin ${2} } -- GitLab From 5389f4765789e4ecf9831bc968562befdd2f3bee Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 15:06:53 +0200 Subject: [PATCH 3854/7155] ASoC: sun4i-i2s: Use the physical / slot width for the clocks The clock dividers function has been using the word size to compute the clock rate at which it's supposed to be running, but the proper formula would be to use the physical width and / or slot width in TDM. It doesn't make any difference at the moment since all the formats supported have the same sample width and physical width, but it's not going to last forever. Fixes: 7d2993811a1e ("ASoC: sun4i-i2s: Add support for H3") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/41a359d9885f397e066816961e5e3236afcbe0a1.1566392800.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 8326b8cfa569..cdc3fa60ff33 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -290,7 +290,7 @@ static bool sun4i_i2s_oversample_is_valid(unsigned int oversample) static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, unsigned int rate, unsigned int slots, - unsigned int word_size) + unsigned int slot_width) { struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); unsigned int oversample_rate, clk_rate, bclk_parent_rate; @@ -337,7 +337,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s); bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate, - rate, slots, word_size); + rate, slots, slot_width); if (bclk_div < 0) { dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); return -EINVAL; @@ -458,6 +458,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, { struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); unsigned int word_size = params_width(params); + unsigned int slot_width = params_physical_width(params); unsigned int channels = params_channels(params); unsigned int slots = channels; int ret, sr, wss; @@ -467,7 +468,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, slots = i2s->slots; if (i2s->slot_width) - word_size = i2s->slot_width; + slot_width = i2s->slot_width; ret = i2s->variant->set_chan_cfg(i2s, params); if (ret < 0) { @@ -490,14 +491,15 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, if (sr < 0) return -EINVAL; - wss = i2s->variant->get_wss(i2s, word_size); + wss = i2s->variant->get_wss(i2s, slot_width); if (wss < 0) return -EINVAL; regmap_field_write(i2s->field_fmt_wss, wss); regmap_field_write(i2s->field_fmt_sr, sr); - return sun4i_i2s_set_clk_rate(dai, params_rate(params), slots, word_size); + return sun4i_i2s_set_clk_rate(dai, params_rate(params), + slots, slot_width); } static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, -- GitLab From 9e8a93ac27d101e0ace024196a4bc3386568cc00 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 15:06:54 +0200 Subject: [PATCH 3855/7155] ASoC: sun4i-i2s: Use the actual format width instead of an hardcoded one The LRCK period field in the FMT0 register holds the number of LRCK period for one channel in I2S mode. This has been hardcoded to 32, while it really should be the physical width of the format, which creates an improper clock when using a 16bit format, with the i2s controller as LRCK master. Fixes: 7d2993811a1e ("ASoC: sun4i-i2s: Add support for H3") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/f08a0c3605cd1d79752b38d704690190183f7865.1566392800.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index cdc3fa60ff33..9ef784b8867c 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -359,7 +359,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, if (i2s->variant->has_fmt_set_lrck_period) regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, - SUN8I_I2S_FMT0_LRCK_PERIOD(32)); + SUN8I_I2S_FMT0_LRCK_PERIOD(slot_width)); return 0; } -- GitLab From 84884c7ad5e8794aa19e48eaa8de93f4e1d26af9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 15:06:55 +0200 Subject: [PATCH 3856/7155] ASoC: sun4i-i2s: Replace call to params_width by local variable The sun4i_i2s_hw_params function already has a variable holding the value returned by params_width, so let's just use that variable instead of calling params_width multiple times. Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/f85a1c1e014080a4bbc3abd19bc8fdcb86f0981a.1566392800.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 9ef784b8867c..69162af9fd65 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -487,7 +487,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, } i2s->playback_dma_data.addr_width = width; - sr = i2s->variant->get_sr(i2s, params_width(params)); + sr = i2s->variant->get_sr(i2s, word_size); if (sr < 0) return -EINVAL; -- GitLab From 7ae7834ec446e5f7fed9bb990d16354853a206d0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 15:06:56 +0200 Subject: [PATCH 3857/7155] ASoC: sun4i-i2s: Add support for DSP formats In addition to the I2S format, the controller also supports the DSP_* formats. This requires some extra care on the LRCK period calculation, since the controller, with the PCM formats, require that the value set is no longer the periods of LRCK for a single channel, but for all of them. Let's add the code to deal with this, and support the DSP_A and DSP_B formats. Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/5562db1ac8759f12b1b87c3258223eed629ef771.1566392800.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 44 +++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 69162af9fd65..57bf2a33753e 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -130,7 +130,6 @@ struct sun4i_i2s; * struct sun4i_i2s_quirks - Differences between SoC variants. * * @has_reset: SoC needs reset deasserted. - * @has_fmt_set_lrck_period: SoC requires lrclk period to be set. * @reg_offset_txdata: offset of the tx fifo. * @sun4i_i2s_regmap: regmap config to use. * @field_clkdiv_mclk_en: regmap field to enable mclk output. @@ -139,7 +138,6 @@ struct sun4i_i2s; */ struct sun4i_i2s_quirks { bool has_reset; - bool has_fmt_set_lrck_period; unsigned int reg_offset_txdata; /* TX FIFO */ const struct regmap_config *sun4i_i2s_regmap; @@ -167,6 +165,7 @@ struct sun4i_i2s { struct regmap *regmap; struct reset_control *rst; + unsigned int format; unsigned int mclk_freq; unsigned int slots; unsigned int slot_width; @@ -355,12 +354,6 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, regmap_field_write(i2s->field_clkdiv_mclk_en, 1); - /* Set sync period */ - if (i2s->variant->has_fmt_set_lrck_period) - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, - SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, - SUN8I_I2S_FMT0_LRCK_PERIOD(slot_width)); - return 0; } @@ -422,6 +415,7 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, { unsigned int channels = params_channels(params); unsigned int slots = channels; + unsigned int lrck_period; if (i2s->slots) slots = i2s->slots; @@ -445,6 +439,26 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); + switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + lrck_period = params_physical_width(params) * slots; + break; + + case SND_SOC_DAIFMT_I2S: + lrck_period = params_physical_width(params); + break; + + default: + return -EINVAL; + } + + regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, + SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, + SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); + regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, SUN8I_I2S_TX_CHAN_EN_MASK, SUN8I_I2S_TX_CHAN_EN(channels)); @@ -616,6 +630,16 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, /* DAI Mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + mode = SUN8I_I2S_CTRL_MODE_PCM; + offset = 1; + break; + + case SND_SOC_DAIFMT_DSP_B: + mode = SUN8I_I2S_CTRL_MODE_PCM; + offset = 0; + break; + case SND_SOC_DAIFMT_I2S: mode = SUN8I_I2S_CTRL_MODE_LEFT; offset = 1; @@ -684,6 +708,9 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); + + i2s->format = fmt; + return 0; } @@ -1074,7 +1101,6 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .has_reset = true, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, - .has_fmt_set_lrck_period = true, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), -- GitLab From f66ad830b11406cdff84e7d8656a0a9e34b0b606 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Mon, 19 Aug 2019 14:36:24 +0300 Subject: [PATCH 3858/7155] net/mlx5: Add per-namespace flow table default miss action support Currently all the namespaces under the same steering domain share the same default table miss action, however in some situations (e.g., RDMA RX) different actions are required. This patch adds a per-namespace default table miss action instead of using the miss action of the steering domain. Signed-off-by: Mark Zhang Reviewed-by: Mark Bloch Signed-off-by: Leon Romanovsky --- .../net/ethernet/mellanox/mlx5/core/fs_cmd.c | 4 +- .../net/ethernet/mellanox/mlx5/core/fs_core.c | 73 +++++++++++-------- .../net/ethernet/mellanox/mlx5/core/fs_core.h | 3 +- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index b84a225bbe86..1e3381604b3d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -182,7 +182,7 @@ static int mlx5_cmd_create_flow_table(struct mlx5_flow_root_namespace *ns, } else { MLX5_SET(create_flow_table_in, in, flow_table_context.table_miss_action, - ns->def_miss_action); + ft->def_miss_action); } break; @@ -262,7 +262,7 @@ static int mlx5_cmd_modify_flow_table(struct mlx5_flow_root_namespace *ns, } else { MLX5_SET(modify_flow_table_in, in, flow_table_context.table_miss_action, - ns->def_miss_action); + ft->def_miss_action); } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 3e99799bdb40..fb3cfdfbafbe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -60,7 +60,8 @@ ADD_PRIO(num_prios_val, 0, num_levels_val, {},\ __VA_ARGS__)\ -#define ADD_NS(...) {.type = FS_TYPE_NAMESPACE,\ +#define ADD_NS(def_miss_act, ...) {.type = FS_TYPE_NAMESPACE, \ + .def_miss_action = def_miss_act,\ .children = (struct init_tree_node[]) {__VA_ARGS__},\ .ar_size = INIT_TREE_NODE_ARRAY_SIZE(__VA_ARGS__) \ } @@ -131,33 +132,41 @@ static struct init_tree_node { int num_leaf_prios; int prio; int num_levels; + enum mlx5_flow_table_miss_action def_miss_action; } root_fs = { .type = FS_TYPE_NAMESPACE, .ar_size = 7, - .children = (struct init_tree_node[]) { - ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0, - FS_CHAINING_CAPS, - ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS, - BY_PASS_PRIO_NUM_LEVELS))), - ADD_PRIO(0, LAG_MIN_LEVEL, 0, - FS_CHAINING_CAPS, - ADD_NS(ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS, - LAG_PRIO_NUM_LEVELS))), - ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {}, - ADD_NS(ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, OFFLOADS_MAX_FT))), - ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0, - FS_CHAINING_CAPS, - ADD_NS(ADD_MULTIPLE_PRIO(ETHTOOL_NUM_PRIOS, - ETHTOOL_PRIO_NUM_LEVELS))), - ADD_PRIO(0, KERNEL_MIN_LEVEL, 0, {}, - ADD_NS(ADD_MULTIPLE_PRIO(KERNEL_NIC_TC_NUM_PRIOS, KERNEL_NIC_TC_NUM_LEVELS), - ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS, - KERNEL_NIC_PRIO_NUM_LEVELS))), - ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0, - FS_CHAINING_CAPS, - ADD_NS(ADD_MULTIPLE_PRIO(LEFTOVERS_NUM_PRIOS, LEFTOVERS_NUM_LEVELS))), - ADD_PRIO(0, ANCHOR_MIN_LEVEL, 0, {}, - ADD_NS(ADD_MULTIPLE_PRIO(ANCHOR_NUM_PRIOS, ANCHOR_NUM_LEVELS))), + .children = (struct init_tree_node[]){ + ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0, FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS, + BY_PASS_PRIO_NUM_LEVELS))), + ADD_PRIO(0, LAG_MIN_LEVEL, 0, FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS, + LAG_PRIO_NUM_LEVELS))), + ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {}, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, + OFFLOADS_MAX_FT))), + ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0, FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(ETHTOOL_NUM_PRIOS, + ETHTOOL_PRIO_NUM_LEVELS))), + ADD_PRIO(0, KERNEL_MIN_LEVEL, 0, {}, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(KERNEL_NIC_TC_NUM_PRIOS, + KERNEL_NIC_TC_NUM_LEVELS), + ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS, + KERNEL_NIC_PRIO_NUM_LEVELS))), + ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0, FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(LEFTOVERS_NUM_PRIOS, + LEFTOVERS_NUM_LEVELS))), + ADD_PRIO(0, ANCHOR_MIN_LEVEL, 0, {}, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(ANCHOR_NUM_PRIOS, + ANCHOR_NUM_LEVELS))), } }; @@ -167,7 +176,8 @@ static struct init_tree_node egress_root_fs = { .children = (struct init_tree_node[]) { ADD_PRIO(0, MLX5_BY_PASS_NUM_PRIOS, 0, FS_CHAINING_CAPS_EGRESS, - ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS, BY_PASS_PRIO_NUM_LEVELS))), } }; @@ -1014,6 +1024,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table); log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0; next_ft = find_next_chained_ft(fs_prio); + ft->def_miss_action = ns->def_miss_action; err = root->cmds->create_flow_table(root, ft, log_table_sz, next_ft); if (err) goto free_ft; @@ -2155,7 +2166,8 @@ static struct mlx5_flow_namespace *fs_init_namespace(struct mlx5_flow_namespace return ns; } -static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio) +static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio, + int def_miss_act) { struct mlx5_flow_namespace *ns; @@ -2164,6 +2176,7 @@ static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio) return ERR_PTR(-ENOMEM); fs_init_namespace(ns); + ns->def_miss_action = def_miss_act; tree_init_node(&ns->node, NULL, del_sw_ns); tree_add_node(&ns->node, &prio->node); list_add_tail(&ns->node.list, &prio->node.children); @@ -2230,7 +2243,7 @@ static int init_root_tree_recursive(struct mlx5_flow_steering *steering, base = &fs_prio->node; } else if (init_node->type == FS_TYPE_NAMESPACE) { fs_get_obj(fs_prio, fs_parent_node); - fs_ns = fs_create_namespace(fs_prio); + fs_ns = fs_create_namespace(fs_prio, init_node->def_miss_action); if (IS_ERR(fs_ns)) return PTR_ERR(fs_ns); base = &fs_ns->node; @@ -2500,7 +2513,7 @@ static int init_rdma_rx_root_ns(struct mlx5_flow_steering *steering) if (!steering->rdma_rx_root_ns) return -ENOMEM; - steering->rdma_rx_root_ns->def_miss_action = + steering->rdma_rx_root_ns->ns.def_miss_action = MLX5_FLOW_TABLE_MISS_ACTION_SWITCH_DOMAIN; /* Create single prio */ @@ -2543,7 +2556,7 @@ static int init_fdb_root_ns(struct mlx5_flow_steering *steering) } for (chain = 0; chain <= FDB_MAX_CHAIN; chain++) { - ns = fs_create_namespace(maj_prio); + ns = fs_create_namespace(maj_prio, MLX5_FLOW_TABLE_MISS_ACTION_DEF); if (IS_ERR(ns)) { err = PTR_ERR(ns); goto out_err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index c48c382f926f..69f809831959 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -145,6 +145,7 @@ struct mlx5_flow_table { struct list_head fwd_rules; u32 flags; struct rhltable fgs_hash; + enum mlx5_flow_table_miss_action def_miss_action; }; struct mlx5_ft_underlay_qp { @@ -191,6 +192,7 @@ struct fs_prio { struct mlx5_flow_namespace { /* parent == NULL => root ns */ struct fs_node node; + enum mlx5_flow_table_miss_action def_miss_action; }; struct mlx5_flow_group_mask { @@ -219,7 +221,6 @@ struct mlx5_flow_root_namespace { struct mutex chain_lock; struct list_head underlay_qpns; const struct mlx5_flow_cmds *cmds; - enum mlx5_flow_table_miss_action def_miss_action; }; int mlx5_init_fc_stats(struct mlx5_core_dev *dev); -- GitLab From e6806e9a63a759e445383915bb9d2ec85a90aebf Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Mon, 19 Aug 2019 14:36:25 +0300 Subject: [PATCH 3859/7155] net/mlx5: Create bypass and loopback flow steering namespaces for RDMA RX Use different namespaces for bypass and switchdev loopback because they have different priorities and default table miss action requirement: 1. bypass: with multiple priorities support, and MLX5_FLOW_TABLE_MISS_ACTION_DEF as the default table miss action; 2. switchdev loopback: with single priority support, and MLX5_FLOW_TABLE_MISS_ACTION_SWITCH_DOMAIN as the default table miss action. Signed-off-by: Mark Zhang Reviewed-by: Mark Bloch Signed-off-by: Leon Romanovsky --- .../net/ethernet/mellanox/mlx5/core/fs_core.c | 49 +++++++++++++++---- .../net/ethernet/mellanox/mlx5/core/rdma.c | 2 +- include/linux/mlx5/fs.h | 1 + 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index fb3cfdfbafbe..7bdec442f0ac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -182,6 +182,26 @@ static struct init_tree_node egress_root_fs = { } }; +#define RDMA_RX_BYPASS_PRIO 0 +#define RDMA_RX_KERNEL_PRIO 1 +static struct init_tree_node rdma_rx_root_fs = { + .type = FS_TYPE_NAMESPACE, + .ar_size = 2, + .children = (struct init_tree_node[]) { + [RDMA_RX_BYPASS_PRIO] = + ADD_PRIO(0, MLX5_BY_PASS_NUM_REGULAR_PRIOS, 0, + FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_REGULAR_PRIOS, + BY_PASS_PRIO_NUM_LEVELS))), + [RDMA_RX_KERNEL_PRIO] = + ADD_PRIO(0, MLX5_BY_PASS_NUM_REGULAR_PRIOS + 1, 0, + FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_SWITCH_DOMAIN, + ADD_MULTIPLE_PRIO(1, 1))), + } +}; + enum fs_i_lock_class { FS_LOCK_GRANDPARENT, FS_LOCK_PARENT, @@ -2067,16 +2087,18 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev, if (steering->sniffer_tx_root_ns) return &steering->sniffer_tx_root_ns->ns; return NULL; - case MLX5_FLOW_NAMESPACE_RDMA_RX: - if (steering->rdma_rx_root_ns) - return &steering->rdma_rx_root_ns->ns; - return NULL; default: break; } if (type == MLX5_FLOW_NAMESPACE_EGRESS) { root_ns = steering->egress_root_ns; + } else if (type == MLX5_FLOW_NAMESPACE_RDMA_RX) { + root_ns = steering->rdma_rx_root_ns; + prio = RDMA_RX_BYPASS_PRIO; + } else if (type == MLX5_FLOW_NAMESPACE_RDMA_RX_KERNEL) { + root_ns = steering->rdma_rx_root_ns; + prio = RDMA_RX_KERNEL_PRIO; } else { /* Must be NIC RX */ root_ns = steering->root_ns; prio = type; @@ -2507,18 +2529,25 @@ static int init_sniffer_rx_root_ns(struct mlx5_flow_steering *steering) static int init_rdma_rx_root_ns(struct mlx5_flow_steering *steering) { - struct fs_prio *prio; + int err; steering->rdma_rx_root_ns = create_root_ns(steering, FS_FT_RDMA_RX); if (!steering->rdma_rx_root_ns) return -ENOMEM; - steering->rdma_rx_root_ns->ns.def_miss_action = - MLX5_FLOW_TABLE_MISS_ACTION_SWITCH_DOMAIN; + err = init_root_tree(steering, &rdma_rx_root_fs, + &steering->rdma_rx_root_ns->ns.node); + if (err) + goto out_err; - /* Create single prio */ - prio = fs_create_prio(&steering->rdma_rx_root_ns->ns, 0, 1); - return PTR_ERR_OR_ZERO(prio); + set_prio_attrs(steering->rdma_rx_root_ns); + + return 0; + +out_err: + cleanup_root_ns(steering->rdma_rx_root_ns); + steering->rdma_rx_root_ns = NULL; + return err; } static int init_fdb_root_ns(struct mlx5_flow_steering *steering) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c index 17ce9dd56b13..18af6981e0be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c @@ -51,7 +51,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) return -ENOMEM; } - ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_RDMA_RX); + ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_RDMA_RX_KERNEL); if (!ns) { mlx5_core_err(dev, "Failed to get RDMA RX namespace"); err = -EOPNOTSUPP; diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index 04a569568eac..5235b09a8ef3 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -75,6 +75,7 @@ enum mlx5_flow_namespace_type { MLX5_FLOW_NAMESPACE_SNIFFER_TX, MLX5_FLOW_NAMESPACE_EGRESS, MLX5_FLOW_NAMESPACE_RDMA_RX, + MLX5_FLOW_NAMESPACE_RDMA_RX_KERNEL, }; enum { -- GitLab From 05cbaf4ddd02b69d78d43481e3813b4579572f71 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 20 Aug 2019 13:25:36 +0100 Subject: [PATCH 3860/7155] iommu/arm-smmu-v3: Document ordering guarantees of command insertion It turns out that we've always relied on some subtle ordering guarantees when inserting commands into the SMMUv3 command queue. With the recent changes to elide locking when possible, these guarantees become more subtle and even more important. Add a comment documented the barrier semantics of command insertion so that we don't have to derive the behaviour from scratch each time it comes up on the list. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index b36a99971401..3402b1bc8e94 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1286,6 +1286,22 @@ static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds, } } +/* + * This is the actual insertion function, and provides the following + * ordering guarantees to callers: + * + * - There is a dma_wmb() before publishing any commands to the queue. + * This can be relied upon to order prior writes to data structures + * in memory (such as a CD or an STE) before the command. + * + * - On completion of a CMD_SYNC, there is a control dependency. + * This can be relied upon to order subsequent writes to memory (e.g. + * freeing an IOVA) after completion of the CMD_SYNC. + * + * - Command insertion is totally ordered, so if two CPUs each race to + * insert their own list of commands then all of the commands from one + * CPU will appear before any of the commands from the other CPU. + */ static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu, u64 *cmds, int n, bool sync) { -- GitLab From dd2261ed45aaeddeb77768f291d604179bcab096 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Wed, 21 Aug 2019 10:24:07 +0100 Subject: [PATCH 3861/7155] hrtimer: Protect lockless access to timer->base The update to timer->base is protected by the base->cpu_base->lock(). However, hrtimer_cancel_wait_running() does access it lockless. So the compiler is allowed to refetch timer->base which can cause havoc when the timer base is changed concurrently. Use READ_ONCE() to prevent this. [ tglx: Adapted from a RT patch ] Signed-off-by: Julien Grall Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190821092409.13225-2-julien.grall@arm.com --- kernel/time/hrtimer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 833353732554..f48864e2ff8a 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1214,7 +1214,8 @@ static void hrtimer_sync_wait_running(struct hrtimer_cpu_base *cpu_base, */ void hrtimer_cancel_wait_running(const struct hrtimer *timer) { - struct hrtimer_clock_base *base = timer->base; + /* Lockless read. Prevent the compiler from reloading it below */ + struct hrtimer_clock_base *base = READ_ONCE(timer->base); if (!timer->is_soft || !base || !base->cpu_base) { cpu_relax(); -- GitLab From 68b2c8c1e421096f4b46ac2ac502d25ca067a2a6 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Wed, 21 Aug 2019 10:24:09 +0100 Subject: [PATCH 3862/7155] hrtimer: Don't take expiry_lock when timer is currently migrated migration_base is used as a placeholder when an hrtimer is migrated to a different CPU. In the case that hrtimer_cancel_wait_running() hits a timer which is currently migrated it would pointlessly acquire the expiry lock of the migration base, which is even not initialized. Surely it could be initialized, but there is absolutely no point in acquiring this lock because the timer is guaranteed not to run it's callback for which the caller waits to finish on that base. So it would just do the inc/lock/dec/unlock dance for nothing. As the base switch is short and non-preemptible, there is no issue when the wait function returns immediately. The timer base and base->cpu_base cannot be NULL in the code path which is invoking that, so just replace those checks with a check whether base is migration base. [ tglx: Updated from RT patch. Massaged changelog. Added comment. ] Signed-off-by: Julien Grall Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190821092409.13225-4-julien.grall@arm.com --- kernel/time/hrtimer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index f48864e2ff8a..ebbd0fb3512b 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1217,7 +1217,11 @@ void hrtimer_cancel_wait_running(const struct hrtimer *timer) /* Lockless read. Prevent the compiler from reloading it below */ struct hrtimer_clock_base *base = READ_ONCE(timer->base); - if (!timer->is_soft || !base || !base->cpu_base) { + /* + * Just relax if the timer expires in hard interrupt context or if + * it is currently on the migration base. + */ + if (!timer->is_soft || base == &migration_base) cpu_relax(); return; } -- GitLab From e12a0ce2fa69798194f3a8628baf6edfbd5c548f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 21 Aug 2019 22:01:52 +0800 Subject: [PATCH 3863/7155] staging: erofs: detect potential multiref due to corrupted images As reported by erofs-utils fuzzer, currently, multiref (ondisk deduplication) hasn't been supported for now, we should forbid it properly. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190821140152.229648-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 4d6faaab04f5..60d7c20db87d 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -798,6 +798,7 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, for (i = 0; i < nr_pages; ++i) pages[i] = NULL; + err = 0; z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, cl->pagevec, 0); @@ -819,8 +820,17 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, pagenr = z_erofs_onlinepage_index(page); DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); + /* + * currently EROFS doesn't support multiref(dedup), + * so here erroring out one multiref page. + */ + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } pages[pagenr] = page; } z_erofs_pagevec_ctor_exit(&ctor, true); @@ -828,7 +838,6 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = false; compressed_pages = pcl->compressed_pages; - err = 0; for (i = 0; i < clusterpages; ++i) { unsigned int pagenr; @@ -852,7 +861,12 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, pagenr = z_erofs_onlinepage_index(page); DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } pages[pagenr] = page; overlapped = true; -- GitLab From 68772c84f7e0380033ce560802b0d179d76be392 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:22:50 +0800 Subject: [PATCH 3864/7155] staging: rtl8192u: ieee80211: remove set but not used variable 'data_len' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c: In function ieee80211_ccmp_encrypt: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c:162:6: warning: variable data_len set but not used [-Wunused-but-set-variable] It is not used since commit eb0e7bf3ca94 ("staging: rtl8192u: ieee80211: ieee80211_crypt_ccmp.c: Use crypto API ccm(aes)") Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122250.71404-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c index aecee42be95e..a43a5d617bd9 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -159,7 +159,7 @@ static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr, static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct ieee80211_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtl_80211_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); @@ -169,7 +169,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; -- GitLab From 4a67342ea9c7c34903f4068f21c98385f9f62b8d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:25:56 +0800 Subject: [PATCH 3865/7155] staging: rtl8192e: remove two set but not used variables Fixes gcc '-Wunused-but-set-variable' warning: In function '_rtl92e_dm_tx_power_tracking_callback_tssi': drivers/staging/rtl8192e/rtl8192e/rtl_dm.c:621:7: warning: variable 'bHighpowerstate' set but not used [-Wunused-but-set-variable] In function '_rtl92e_dm_rx_path_sel_byrssi': drivers/staging/rtl8192e/rtl8192e/rtl_dm.c:1904:32: warning: variable 'cck_rx_ver2_min_index' set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122556.37636-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 1b7e3fda7905..20e494186c9e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -618,7 +618,7 @@ static void _rtl92e_dm_tx_update_tssi_strong_signal(struct net_device *dev, static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - bool bHighpowerstate, viviflag = false; + bool viviflag = false; struct dcmd_txcmd tx_cmd; u8 powerlevelOFDM24G; int i = 0, j = 0, k = 0; @@ -632,7 +632,6 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) rtl92e_writeb(dev, Pw_Track_Flag, 0); rtl92e_writeb(dev, FW_Busy_Flag, 0); priv->rtllib->bdynamic_txpower_enable = false; - bHighpowerstate = priv->bDynamicTxHighPower; powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); RF_Type = priv->rf_type; @@ -1901,7 +1900,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) u8 cck_default_Rx = 0x2; u8 cck_optional_Rx = 0x3; long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; - u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0; + u8 cck_rx_ver2_max_index = 0; u8 cck_rx_ver2_sec_index = 0; u8 cur_rf_rssi; long cur_cck_pwdb; @@ -1984,7 +1983,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) if (rf_num == 1) { cck_rx_ver2_max_index = i; - cck_rx_ver2_min_index = i; cck_rx_ver2_sec_index = i; tmp_cck_max_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; @@ -1997,7 +1995,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) tmp_cck_sec_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - cck_rx_ver2_min_index = i; } } else { if (cur_cck_pwdb > tmp_cck_max_pwdb) { @@ -2027,13 +2024,10 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) (cur_cck_pwdb > tmp_cck_min_pwdb)) { ; } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; - } } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; } } -- GitLab From 6808f8cf57f10c1491074572eb247e7fc2a60f47 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:28:02 +0800 Subject: [PATCH 3866/7155] staging: rtl8192e: remove set but not used variable 'data_len' Fixes gcc '-Wunused-but-set-variable' warning: In function ieee80211_ccmp_encrypt: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c:162:6: warning: variable data_len set but not used [-Wunused-but-set-variable] It is not used since commit 5ee5265674ce ("staging: rtl8192e: rtllib_crypt_ccmp.c: Use crypto API ccm(aes)") Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122802.44028-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 44ec45d5c87f..0cbf4a1a326b 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -153,7 +153,7 @@ static int ccmp_init_iv_and_aad(struct rtllib_hdr_4addr *hdr, static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct rtllib_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + @@ -163,7 +163,6 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; -- GitLab From ee16d7d3e0128b347210b27214043e245d03c256 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:38 -0700 Subject: [PATCH 3867/7155] staging: rtl8192u: fix OPEN_BRACE errors in ieee80211 Checkpatch emits several errors regarding braces being on the incorrect line. These can be fixed by moving the brace, do this. In a few cases, some comments were moved to facilitate this. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-2-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211.h | 3 +- .../staging/rtl8192u/ieee80211/ieee80211_rx.c | 116 ++++++------------ .../staging/rtl8192u/ieee80211/ieee80211_tx.c | 81 +++++------- .../staging/rtl8192u/ieee80211/ieee80211_wx.c | 3 +- .../staging/rtl8192u/ieee80211/rtl819x_HT.h | 3 +- 5 files changed, 73 insertions(+), 133 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 3963a08b9eb2..129dcb5a0f2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -458,8 +458,7 @@ do { if (ieee80211_debug_level & (level)) \ int i; \ u8 *pdata = (u8 *) data; \ printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ - for (i = 0; i < (int)(datalen); i++) \ - { \ + for (i = 0; i < (int)(datalen); i++) { \ printk("%2x ", pdata[i]); \ if ((i + 1) % 16 == 0) printk("\n"); \ } \ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 7ef1e89de269..9d8b2ff700fe 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -218,8 +218,8 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, rx_stats->len = skb->len; ieee80211_rx_mgt(ieee, (struct rtl_80211_hdr_4addr *)skb->data, rx_stats); /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */ - if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */ - { + if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) { + /* use ADDR1 to perform address matching for Management frames */ dev_kfree_skb_any(skb); return 0; } @@ -339,8 +339,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, if (!crypt || !crypt->ops->decrypt_mpdu) return 0; - if (ieee->hwsec_active) - { + if (ieee->hwsec_active) { struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } @@ -386,8 +385,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s if (!crypt || !crypt->ops->decrypt_msdu) return 0; - if (ieee->hwsec_active) - { + if (ieee->hwsec_active) { struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } @@ -507,8 +505,7 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *pReorderEntry) { struct list_head *pList = &pTS->rx_pending_pkt_list; - while (pList->next != &pTS->rx_pending_pkt_list) - { + while (pList->next != &pTS->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) pList = pList->next; else if (SN_EQUAL(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) @@ -530,8 +527,7 @@ void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_ u16 ethertype; // if(index > 1) // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__func__,index); - for (j = 0; j < index; j++) - { + for (j = 0; j < index; j++) { //added by amy for reorder struct ieee80211_rxb *prxb = prxbIndicateArray[j]; for (i = 0; i < prxb->nr_subframes; i++) { @@ -699,8 +695,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): start RREORDER indicate\n", __func__); pReorderEntry = list_entry(pTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List); if (SN_LESS(pReorderEntry->SeqNum, pTS->rx_indicate_seq) || - SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) - { + SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) { /* This protect buffer from overflow. */ if (index >= REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n"); @@ -922,8 +917,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); - if (HTCCheck(ieee, skb->data)) - { + if (HTCCheck(ieee, skb->data)) { if (net_ratelimit()) printk("find HTCControl\n"); hdrlen += 4; @@ -1010,8 +1004,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, hdr->addr2, Frame_QoSTID((u8 *)(skb->data)), RX_DIR, - true)) - { + true)) { // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc)); if ((fc & (1 << 11)) && @@ -1119,8 +1112,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) - { + (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) { printk("decrypt frame error\n"); goto rx_dropped; } @@ -1185,8 +1177,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possible reassembled) full MSDU payload; possibly still * encrypted/authenticated */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - { + ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) { printk("==>decrypt msdu error\n"); goto rx_dropped; } @@ -1243,13 +1234,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, */ //added by amy for reorder if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) - && !is_multicast_ether_addr(hdr->addr1)) - { + && !is_multicast_ether_addr(hdr->addr1)) { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); - if (TID != 0 && TID != 3) - { + if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } } @@ -1549,15 +1538,12 @@ static inline void ieee80211_extract_country_ie( u8 *addr2 ) { - if (IS_DOT11D_ENABLE(ieee)) - { - if (info_element->len != 0) - { + if (IS_DOT11D_ENABLE(ieee)) { + if (info_element->len != 0) { memcpy(network->CountryIeBuf, info_element->data, info_element->len); network->CountryIeLen = info_element->len; - if (!IS_COUNTRY_IE_VALID(ieee)) - { + if (!IS_COUNTRY_IE_VALID(ieee)) { dot11d_update_country_ie(ieee, addr2, info_element->len, info_element->data); } } @@ -1567,8 +1553,7 @@ static inline void ieee80211_extract_country_ie( // some AP (e.g. Cisco 1242) don't include country IE in their // probe response frame. // - if (IS_EQUAL_CIE_SRC(ieee, addr2)) - { + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { UPDATE_CIE_WATCHDOG(ieee); } } @@ -1865,8 +1850,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x0c && - info_element->data[2] == 0x43) - { + info_element->data[2] == 0x43) { network->ralink_cap_exist = true; } else network->ralink_cap_exist = false; @@ -1878,8 +1862,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x13 && - info_element->data[2] == 0x74)) - { + info_element->data[2] == 0x74)) { printk("========>%s(): athros AP is exist\n", __func__); network->atheros_cap_exist = true; } else @@ -1888,8 +1871,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && - info_element->data[2] == 0x96) - { + info_element->data[2] == 0x96) { network->cisco_cap_exist = true; } else network->cisco_cap_exist = false; @@ -1898,22 +1880,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x01) - { - if (info_element->len == 6) - { + info_element->data[3] == 0x01) { + if (info_element->len == 6) { memcpy(network->CcxRmState, &info_element[4], 2); if (network->CcxRmState[0] != 0) - { network->bCcxRmEnable = true; - } else + else network->bCcxRmEnable = false; // // CCXv4 Table 59-1 MBSSID Masks. // network->MBssidMask = network->CcxRmState[1] & 0x07; - if (network->MBssidMask != 0) - { + if (network->MBssidMask != 0) { network->bMBssidValid = true; network->MBssidMask = 0xff << (network->MBssidMask); ether_addr_copy(network->MBssid, network->bssid); @@ -1929,8 +1907,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x03) - { + info_element->data[3] == 0x03) { if (info_element->len == 5) { network->bWithCcxVerNum = true; network->BssCcxVerNumber = info_element->data[4]; @@ -1985,16 +1962,14 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_AIRONET: IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); - if (info_element->len > IE_CISCO_FLAG_POSITION) - { + if (info_element->len > IE_CISCO_FLAG_POSITION) { network->bWithAironetIE = true; // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): // "A Cisco access point advertises support for CKIP in beacon and probe response packets, // by adding an Aironet element and setting one or both of the CKIP negotiation bits." if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) - { + (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) { network->bCkipSupported = true; } else { network->bCkipSupported = false; @@ -2214,8 +2189,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->rates_len = src->rates_len; memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); dst->rates_ex_len = src->rates_ex_len; - if (src->ssid_len > 0) - { + if (src->ssid_len > 0) { memset(dst->ssid, 0, dst->ssid_len); dst->ssid_len = src->ssid_len; memcpy(dst->ssid, src->ssid, src->ssid_len); @@ -2224,8 +2198,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->flags = src->flags; dst->time_stamp[0] = src->time_stamp[0]; dst->time_stamp[1] = src->time_stamp[1]; - if (src->flags & NETWORK_HAS_ERP_VALUE) - { + if (src->flags & NETWORK_HAS_ERP_VALUE) { dst->erp_value = src->erp_value; dst->berp_info_valid = src->berp_info_valid = true; } @@ -2379,41 +2352,33 @@ static inline void ieee80211_process_probe_response( if (!is_legal_channel(ieee, network->channel)) goto out; - if (ieee->bGlobalDomain) - { - if (fc == IEEE80211_STYPE_PROBE_RESP) - { - // Case 1: Country code + if (ieee->bGlobalDomain) { + if (fc == IEEE80211_STYPE_PROBE_RESP) { if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 11) - { + if (network->channel > 11) { printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto out; } } } else { - // Case 1: Country code if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 14) - { + if (network->channel > 14) { printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } @@ -2442,8 +2407,7 @@ static inline void ieee80211_process_probe_response( else ieee->current_network.buseprotection = false; } - if (is_beacon(beacon->header.frame_ctl)) - { + if (is_beacon(beacon->header.frame_ctl)) { if (ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; } else //hidden AP diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index fc6eb97801e1..c49357067735 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -214,7 +214,8 @@ int ieee80211_encrypt_fragment( } -void ieee80211_txb_free(struct ieee80211_txb *txb) { +void ieee80211_txb_free(struct ieee80211_txb *txb) +{ //int i; if (unlikely(!txb)) return; @@ -333,8 +334,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, } } FORCED_AGG_SETTING: - switch (pHTInfo->ForcedAMPDUMode ) - { + switch (pHTInfo->ForcedAMPDUMode ) { case HT_AGG_AUTO: break; @@ -424,19 +424,15 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. return; - if (ieee->mode < IEEE_N_24G) //b, g mode - { + if (ieee->mode < IEEE_N_24G) /* b, g mode */ { // (1) RTS_Threshold is compared to the MPDU, not MSDU. // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. // Other fragments are protected by previous fragment. // So we only need to check the length of first fragment. - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->bRTSEnable = true; tcb_desc->rts_rate = MGN_24M; - } - else if (ieee->current_network.buseprotection) - { + } else if (ieee->current_network.buseprotection) { // Use CTS-to-SELF in protection mode. tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; @@ -444,43 +440,35 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, } //otherwise return; return; - } - else - {// 11n High throughput case. + } else { // 11n High throughput case. PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; - while (true) - { + while (true) { //check ERP protection - if (ieee->current_network.buseprotection) - {// CTS-to-SELF + if (ieee->current_network.buseprotection) {// CTS-to-SELF tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; break; } //check HT op mode - if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) - { + if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { u8 HTOpMode = pHTInfo->CurrentOpMode; if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || - (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) - { + (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } } //check rts - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } //to do list: check MIMO power save condition. //check AMPDU aggregation for TXOP - if(tcb_desc->bAMPDUEnable) - { + if(tcb_desc->bAMPDUEnable) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily @@ -488,8 +476,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check IOT action - if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) - { + if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; tcb_desc->bRTSEnable = true; @@ -541,8 +528,7 @@ static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, if (ieee->bTxUseDriverAssingedRate) tcb_desc->bTxUseDriverAssingedRate = true; - if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) - { + if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) { if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) tcb_desc->RATRIndex = 0; } @@ -553,11 +539,9 @@ static void ieee80211_query_seqnum(struct ieee80211_device *ieee, { if (is_multicast_ether_addr(dst)) return; - if (IsQoSDataFrame(skb->data)) //we deal qos data only - { + if (IsQoSDataFrame(skb->data)) /* we deal qos data only */ { struct tx_ts_record *pTS = NULL; - if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) - { + if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) { return; } pTS->tx_cur_seq = (pTS->tx_cur_seq + 1) % 4096; @@ -749,15 +733,13 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } skb_reserve(skb_frag, ieee->tx_headroom); - if (encrypt){ + if (encrypt) { if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); - } - else - { + } else { tcb_desc->bHwSec = 0; } frag_hdr = skb_put_data(skb_frag, &header, hdr_len); @@ -775,8 +757,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) - if(qos_actived) - { + if(qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); } else { @@ -806,17 +787,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) skb_put(skb_frag, 4); } - if(qos_actived) - { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; + if (qos_actived) { + if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) + ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; + else + ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; } } else { if (unlikely(skb->len < sizeof(struct rtl_80211_hdr_3addr))) { @@ -839,8 +819,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. - if (txb) - { + if (txb) { struct cb_desc *tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index be08cd1d37a7..8ad85331f020 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -130,8 +130,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, max_rate = rate; } - if (network->mode >= IEEE_N_24G)//add N rate here; - { + if (network->mode >= IEEE_N_24G) /* add N rate here */ { struct ht_capability_ele *ht_cap = NULL; bool is40M = false, isShortGI = false; u8 max_mcs = 0; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index b7769bca9740..3fca0d3a1d05 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -273,8 +273,7 @@ typedef enum _HT_AGGRE_SIZE { }HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; /* Indicate different AP vendor for IOT issue */ -typedef enum _HT_IOT_PEER -{ +typedef enum _HT_IOT_PEER { HT_IOT_PEER_UNKNOWN = 0, HT_IOT_PEER_REALTEK = 1, HT_IOT_PEER_BROADCOM = 2, -- GitLab From 2b1d4c425ae548f3f8da11238abf59a08f1626b7 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:39 -0700 Subject: [PATCH 3868/7155] staging: rtl8192u: fix macro alignment in ieee80211 Several macros display unaligned, due to mixes of tabs and spaces. These can be fixed by making spacing consistent, do this. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-3-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211.h | 35 ++++++++++--------- .../staging/rtl8192u/ieee80211/rtl819x_HT.h | 8 ++--- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 129dcb5a0f2e..6b7828a9e71d 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -169,9 +169,9 @@ struct cb_desc { #define MGN_MCS14 0x8e #define MGN_MCS15 0x8f -#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ +#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ priv->ieee80211->current_network.mode == IEEE_N_24G || \ - priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ + priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ 16 : 10) #define MGMT_QUEUE_NUM 5 @@ -387,7 +387,7 @@ struct ieee_param { #define IEEE80211_STYPE_ACK 0x00D0 #define IEEE80211_STYPE_CFEND 0x00E0 #define IEEE80211_STYPE_CFENDACK 0x00F0 -#define IEEE80211_STYPE_BLOCKACK 0x0094 +#define IEEE80211_STYPE_BLOCKACK 0x0094 /* data */ #define IEEE80211_STYPE_DATA 0x0000 @@ -452,18 +452,19 @@ do { if (ieee80211_debug_level & (level)) \ printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0) //wb added to debug out data buf //if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA -#define IEEE80211_DEBUG_DATA(level, data, datalen) \ - do { if ((ieee80211_debug_level & (level)) == (level)) \ - { \ - int i; \ - u8 *pdata = (u8 *) data; \ - printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ - for (i = 0; i < (int)(datalen); i++) { \ - printk("%2x ", pdata[i]); \ - if ((i + 1) % 16 == 0) printk("\n"); \ - } \ - printk("\n"); \ - } \ +#define IEEE80211_DEBUG_DATA(level, data, datalen) \ + do { if ((ieee80211_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8 *pdata = (u8 *) data; \ + printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ + for (i = 0; i < (int)(datalen); i++) { \ + printk("%2x ", pdata[i]); \ + if ((i + 1) % 16 == 0) \ + printk("\n"); \ + } \ + printk("\n"); \ + } \ } while (0) #else #define IEEE80211_DEBUG (level, fmt, args...) do {} while (0) @@ -2014,8 +2015,8 @@ struct ieee80211_device { #define IEEE_A (1<<0) #define IEEE_B (1<<1) #define IEEE_G (1<<2) -#define IEEE_N_24G (1<<4) -#define IEEE_N_5G (1<<5) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) #define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G) /* Generate a 802.11 header */ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index 3fca0d3a1d05..586d93720e37 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -253,10 +253,10 @@ extern u8 MCS_FILTER_1SS[16]; /* 2007/07/12 MH We only define legacy and HT wireless mode now. */ #define LEGACY_WIRELESS_MODE IEEE_MODE_MASK -#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ - ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ?\ - (LegacyRate) :\ - (PICK_RATE(LegacyRate, HTRate)) +#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ + ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ? \ + (LegacyRate) : \ + (PICK_RATE(LegacyRate, HTRate)) // MCS Bw 40 {1~7, 12~15,32} #define RATE_ADPT_1SS_MASK 0xFF -- GitLab From f401441deda68326852560bf70d59e95f585bbb3 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:40 -0700 Subject: [PATCH 3869/7155] staging: rtl8192u: fix spacing in ieee80211 Checkpatch emits several errors, warnings, and checks about spacing. Apply checkpatch's suggested spacing rules. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-4-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/dot11d.c | 10 ++-- .../staging/rtl8192u/ieee80211/ieee80211.h | 4 +- .../rtl8192u/ieee80211/ieee80211_crypt.c | 2 +- .../rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 22 ++++---- .../rtl8192u/ieee80211/ieee80211_crypt_wep.c | 4 +- .../staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- .../rtl8192u/ieee80211/ieee80211_softmac_wx.c | 14 +++--- .../staging/rtl8192u/ieee80211/ieee80211_tx.c | 50 +++++++++---------- .../staging/rtl8192u/ieee80211/ieee80211_wx.c | 32 ++++++------ .../rtl8192u/ieee80211/rtl819x_BAProc.c | 12 ++--- .../staging/rtl8192u/ieee80211/rtl819x_HT.h | 6 +-- .../rtl8192u/ieee80211/rtl819x_TSProc.c | 14 +++--- 12 files changed, 86 insertions(+), 86 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.c b/drivers/staging/rtl8192u/ieee80211/dot11d.c index 130ddfe9868f..bc642076b96f 100644 --- a/drivers/staging/rtl8192u/ieee80211/dot11d.c +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.c @@ -12,7 +12,7 @@ void rtl8192u_dot11d_init(struct ieee80211_device *ieee) dot11d_info->state = DOT11D_STATE_NONE; dot11d_info->country_ie_len = 0; memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); netdev_info(ieee->dev, "rtl8192u_dot11d_init()\n"); @@ -25,8 +25,8 @@ void dot11d_reset(struct ieee80211_device *ieee) u32 i; struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee); /* Clear old channel map */ - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); /* Set new channel map */ for (i = 1; i <= 11; i++) (dot11d_info->channel_map)[i] = 1; @@ -56,8 +56,8 @@ void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr, u8 i, j, NumTriples, MaxChnlNum; struct chnl_txpower_triple *pTriple; - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); MaxChnlNum = 0; NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 6b7828a9e71d..daebbbd8f4dd 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -456,7 +456,7 @@ do { if (ieee80211_debug_level & (level)) \ do { if ((ieee80211_debug_level & (level)) == (level)) \ { \ int i; \ - u8 *pdata = (u8 *) data; \ + u8 *pdata = (u8 *)data; \ printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ for (i = 0; i < (int)(datalen); i++) { \ printk("%2x ", pdata[i]); \ @@ -468,7 +468,7 @@ do { if (ieee80211_debug_level & (level)) \ } while (0) #else #define IEEE80211_DEBUG (level, fmt, args...) do {} while (0) -#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while(0) +#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while (0) #endif /* CONFIG_IEEE80211_DEBUG */ /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c index 36987fccac5d..01012dddcd73 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c @@ -176,7 +176,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) } -static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } +static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; } static void ieee80211_crypt_null_deinit(void *priv) {} static struct ieee80211_crypto_ops ieee80211_crypt_null = { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 0927b2b15151..6f4710171151 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -160,7 +160,7 @@ static inline u16 Hi16(u32 val) static inline u16 Mk16(u8 hi, u8 lo) { - return lo | (((u16) hi) << 8); + return lo | (((u16)hi) << 8); } static const u16 Sbox[256] = { @@ -238,7 +238,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, * Make temporary area overlap WEP seed so that the final copy can be * avoided on little endian hosts. */ - u16 *PPK = (u16 *) &WEPSeed[4]; + u16 *PPK = (u16 *)&WEPSeed[4]; /* Step 1 - make copy of TTAK and bring in TSC */ PPK[0] = TTAK[0]; @@ -299,7 +299,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tcb_desc->bHwSec) { if (!tkey->tx_phase1_done) { @@ -343,7 +343,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; crypto_sync_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, tkey->tx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); @@ -383,7 +383,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) if (skb->len < hdr_len + 8 + 4) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; pos = skb->data + hdr_len; keyidx = pos[3]; if (!(keyidx & BIT(5))) { @@ -435,7 +435,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; crypto_sync_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, tkey->rx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -523,7 +523,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) { struct rtl_80211_hdr_4addr *hdr11; - hdr11 = (struct rtl_80211_hdr_4addr *) skb->data; + hdr11 = (struct rtl_80211_hdr_4addr *)skb->data; switch (le16_to_cpu(hdr11->frame_ctl) & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { case IEEE80211_FCTL_TODS: @@ -556,7 +556,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri u8 *pos; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { printk(KERN_DEBUG "Invalid packet for Michael MIC add " @@ -599,7 +599,7 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); } static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, @@ -609,7 +609,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, u8 mic[8]; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tkey->key_set) return -1; @@ -626,7 +626,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, return -1; if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; printk(KERN_DEBUG "%s: Michael MIC verification failed for " "MSDU from %pM keyidx=%d\n", diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 805493a0870d..26482c3dcd1c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -135,7 +135,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; crypto_sync_skcipher_setkey(wep->tx_tfm, key, klen); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, wep->tx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -192,7 +192,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) SYNC_SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); crypto_sync_skcipher_setkey(wep->rx_tfm, key, klen); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, wep->rx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 9d8b2ff700fe..a1462ec55767 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1237,7 +1237,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, && !is_multicast_ether_addr(hdr->addr1)) { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); - GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); + GetTs(ieee, (struct ts_common_info **)&pTS, hdr->addr2, TID, RX_DIR, true); if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c index 4a8d16a45fc5..b1baaa18b129 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c @@ -42,8 +42,8 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info /* if setting by freq convert to channel */ if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { + if ((fwrq->m >= (int)2.412e8 && + fwrq->m <= (int)2.487e8)) { int f = fwrq->m / 100000; int c = 0; @@ -92,7 +92,7 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee, if (ieee->current_network.channel == 0) return -1; /* NM 0.7.0 will not accept channel any more. */ - fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000; + fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel - 1] * 100000; fwrq->e = 1; /* fwrq->m = ieee->current_network.channel; */ /* fwrq->e = 0; */ @@ -220,7 +220,7 @@ int ieee80211_wx_set_rate(struct ieee80211_device *ieee, u32 target_rate = wrqu->bitrate.value; - ieee->rate = target_rate/100000; + ieee->rate = target_rate / 100000; /* FIXME: we might want to limit rate also in management protocols. */ return 0; } @@ -415,9 +415,9 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee, if (wrqu->essid.flags && wrqu->essid.length) { /* first flush current network.ssid */ - len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; - strncpy(ieee->current_network.ssid, extra, len+1); - ieee->current_network.ssid_len = len+1; + len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE; + strncpy(ieee->current_network.ssid, extra, len + 1); + ieee->current_network.ssid_len = len + 1; ieee->ssid_set = 1; } else { ieee->ssid_set = 0; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index c49357067735..e76bdedc8409 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -294,7 +294,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, struct tx_ts_record *pTxTs = NULL; struct rtl_80211_hdr_1addr *hdr = (struct rtl_80211_hdr_1addr *)skb->data; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; @@ -334,7 +334,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, } } FORCED_AGG_SETTING: - switch (pHTInfo->ForcedAMPDUMode ) { + switch (pHTInfo->ForcedAMPDUMode) { case HT_AGG_AUTO: break; @@ -372,7 +372,7 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ tcb_desc->bUseShortGI = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (pHTInfo->bForcedShortGI) { @@ -380,9 +380,9 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ return; } - if ((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) + if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz) tcb_desc->bUseShortGI = true; - else if ((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) + else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz) tcb_desc->bUseShortGI = true; } @@ -393,16 +393,16 @@ static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, tcb_desc->bPacketBW = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (tcb_desc->bMulticast || tcb_desc->bBroadcast) return; - if ((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel. + if ((tcb_desc->data_rate & 0x80) == 0) // If using legacy rate, it shall use 20MHz channel. return; //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance - if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) tcb_desc->bPacketBW = true; return; } @@ -418,10 +418,10 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate. tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz - if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts + if (tcb_desc->bBroadcast || tcb_desc->bMulticast) //only unicast frame will use rts/cts return; - if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. + if (is_broadcast_ether_addr(skb->data + 16)) //check addr3 as infrastructure add3 is DA. return; if (ieee->mode < IEEE_N_24G) /* b, g mode */ { @@ -451,9 +451,9 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check HT op mode - if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { + if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { u8 HTOpMode = pHTInfo->CurrentOpMode; - if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || + if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; @@ -468,7 +468,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, } //to do list: check MIMO power save condition. //check AMPDU aggregation for TXOP - if(tcb_desc->bAMPDUEnable) { + if (tcb_desc->bAMPDUEnable) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily @@ -476,7 +476,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check IOT action - if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { + if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; tcb_desc->bRTSEnable = true; @@ -517,7 +517,7 @@ static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, return; } - if (pMgntInfo->ForcedDataRate!= 0) { + if (pMgntInfo->ForcedDataRate != 0) { pTcb->bTxDisableRateFallBack = true; pTcb->bTxUseDriverAssingedRate = true; return; @@ -576,7 +576,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* If there is no driver handler to take the TXB, dont' bother * creating it... */ - if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| + if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); @@ -615,7 +615,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); - memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); + memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); @@ -630,7 +630,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) fc = IEEE80211_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) - if(qos_actived) + if (qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; @@ -724,7 +724,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (struct cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); - if(qos_actived){ + if (qos_actived) { skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { @@ -757,11 +757,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) - if(qos_actived) { + if (qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority) + 1] << 4 | i); } else { - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4 | i); } /* Put a SNAP header on the first fragment */ @@ -806,7 +806,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); - if(!txb){ + if (!txb) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; @@ -841,9 +841,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { ieee80211_softmac_xmit(txb, ieee); - }else{ + } else { if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += __le16_to_cpu(txb->payload_size); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index 8ad85331f020..8ca7a7fd74f9 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -70,10 +70,10 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; - for(i=0; imode & BIT(i)) { - sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size); - pname +=ieee80211_modes[i].mode_size; + sprintf(pname, ieee80211_modes[i].mode_string, ieee80211_modes[i].mode_size); + pname += ieee80211_modes[i].mode_size; } } *pname = '\0'; @@ -138,13 +138,13 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[4]; else ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[0]; - is40M = (ht_cap->ChlWidth)?1:0; - isShortGI = (ht_cap->ChlWidth)? - ((ht_cap->ShortGI40Mhz)?1:0): - ((ht_cap->ShortGI20Mhz)?1:0); + is40M = (ht_cap->ChlWidth) ? 1 : 0; + isShortGI = (ht_cap->ChlWidth) ? + ((ht_cap->ShortGI40Mhz) ? 1 : 0) : + ((ht_cap->ShortGI20Mhz) ? 1 : 0); max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL); - rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f]; + rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f]; if (rate > max_rate) max_rate = rate; } @@ -242,7 +242,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, list_for_each_entry(network, &ieee->network_list, list) { i++; - if((stop-ev)<200) { + if ((stop - ev) < 200) { err = -E2BIG; break; } @@ -453,7 +453,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, IEEE80211_DEBUG_WX("GET_ENCODE\n"); - if(ieee->iw_mode == IW_MODE_MONITOR) + if (ieee->iw_mode == IW_MODE_MONITOR) return -1; key = erq->flags & IW_ENCODE_INDEX; @@ -570,7 +570,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, ret = -EINVAL; goto done; } - printk("alg name:%s\n",alg); + printk("alg name:%s\n", alg); ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module); if (!ops) { @@ -687,7 +687,7 @@ int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, ext->key_len = 0; encoding->flags |= IW_ENCODE_DISABLED; } else { - if (strcmp(crypt->ops->name, "WEP") == 0 ) + if (strcmp(crypt->ops->name, "WEP") == 0) ext->alg = IW_ENCODE_ALG_WEP; else if (strcmp(crypt->ops->name, "TKIP")) ext->alg = IW_ENCODE_ALG_TKIP; @@ -711,7 +711,7 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct iw_mlme *mlme = (struct iw_mlme *) extra; + struct iw_mlme *mlme = (struct iw_mlme *)extra; switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: @@ -764,7 +764,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee, break; case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value)?1:0; + ieee->wpa_enabled = (data->value) ? 1 : 0; break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: @@ -784,14 +784,14 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) { u8 *buf; - if (len>MAX_WPA_IE_LEN || (len && !ie)) { + if (len > MAX_WPA_IE_LEN || (len && !ie)) { // printk("return error out, len:%d\n", len); return -EINVAL; } if (len) { - if (len != ie[1]+2) { + if (len != ie[1] + 2) { printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 53869b3c985c..379a2ccf4d9f 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -162,7 +162,7 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, s tag += 2; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); return skb; //return NULL; } @@ -229,7 +229,7 @@ static struct sk_buff *ieee80211_DELBA( put_unaligned_le16(ReasonCode, tag); tag += 2; - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); if (net_ratelimit()) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __func__); @@ -331,9 +331,9 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); - req = (struct rtl_80211_hdr_3addr *) skb->data; + req = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)req; dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); @@ -556,7 +556,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; dst = &delba->addr2[0]; pDelBaParamSet = (union delba_param_set *)&delba->payload[2]; @@ -643,7 +643,7 @@ TsInitDelBA(struct ieee80211_device *ieee, struct ts_common_info *pTsCommonInfo, ieee80211_send_DELBA( ieee, pTsCommonInfo->addr, - (pTxTs->tx_admitted_ba_record.valid)?(&pTxTs->tx_admitted_ba_record):(&pTxTs->tx_pending_ba_record), + (pTxTs->tx_admitted_ba_record.valid) ? (&pTxTs->tx_admitted_ba_record) : (&pTxTs->tx_pending_ba_record), TxRxSelect, DELBA_REASON_END_BA); } else if (TxRxSelect == RX_DIR) { diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index 586d93720e37..79346a00af09 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -270,7 +270,7 @@ typedef enum _HT_AGGRE_SIZE { HT_AGG_SIZE_16K = 1, HT_AGG_SIZE_32K = 2, HT_AGG_SIZE_64K = 3, -}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; +} HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; /* Indicate different AP vendor for IOT issue */ typedef enum _HT_IOT_PEER { @@ -281,7 +281,7 @@ typedef enum _HT_IOT_PEER { HT_IOT_PEER_ATHEROS = 4, HT_IOT_PEER_CISCO = 5, HT_IOT_PEER_MAX = 6 -}HT_IOT_PEER_E, *PHTIOT_PEER_E; +} HT_IOT_PEER_E, *PHTIOT_PEER_E; /* * IOT Action for different AP @@ -297,6 +297,6 @@ typedef enum _HT_IOT_ACTION { HT_IOT_ACT_CDD_FSYNC = 0x00000080, HT_IOT_ACT_PURE_N_MODE = 0x00000100, HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, -}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; +} HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; #endif //_RTL819XU_HTTYPE_H_ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index 59d179ae7ad2..f4e5aa07421f 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -105,7 +105,7 @@ static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo) { eth_zero_addr(pTsCommonInfo->addr); memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body)); - memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas)*TCLAS_NUM); + memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM); pTsCommonInfo->t_clas_proc = 0; pTsCommonInfo->t_clas_num = 0; } @@ -183,9 +183,9 @@ void TSInitialize(struct ieee80211_device *ieee) //#ifdef TO_DO_LIST for (count = 0; count < REORDER_ENTRY_NUM; count++) { list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); - if (count == (REORDER_ENTRY_NUM-1)) + if (count == (REORDER_ENTRY_NUM - 1)) break; - pRxReorderEntry = &ieee->RxReorderEntry[count+1]; + pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; } //#endif } @@ -259,7 +259,7 @@ static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee, } if (&pRet->list != psearch_list) - return pRet ; + return pRet; else return NULL; } @@ -367,8 +367,8 @@ bool GetTs( (&ieee->Rx_TS_Admit_List); enum direction_value Dir = (ieee->iw_mode == IW_MODE_MASTER) ? - ((TxRxSelect == TX_DIR)?DIR_DOWN:DIR_UP) : - ((TxRxSelect == TX_DIR)?DIR_UP:DIR_DOWN); + ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) : + ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN); IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n"); if (!list_empty(pUnusedList)) { (*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list); @@ -530,7 +530,7 @@ void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTx jiffies + msecs_to_jiffies(TS_ADDBA_DELAY)); } else { IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__); - mod_timer(&pTxTS->ts_add_ba_timer, jiffies+10); //set 10 ticks + mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); //set 10 ticks } } else { IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__); -- GitLab From 1fef2bf578f084daaebc84435803da3b44f7ac77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:49 +0200 Subject: [PATCH 3870/7155] ARM: dts: at91: Add label for sam9x5's internal RTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to simplify several machine device trees using this label instead of duplicating the SoC's hierarchy. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-1-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9x5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index ef47c005ef03..7c2eb93f8cac 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -941,7 +941,7 @@ status = "disabled"; }; - rtc@fffffeb0 { + rtc: rtc@fffffeb0 { compatible = "atmel,at91sam9x5-rtc"; reg = <0xfffffeb0 0x40>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; -- GitLab From 60839c530853312a0a32e7588966524ac6030a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:50 +0200 Subject: [PATCH 3871/7155] ARM: dts: at91: ariag25: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - newline between properties and sub-nodes - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtb Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-2-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-ariag25.dts | 255 ++++++++++++++--------------- 1 file changed, 124 insertions(+), 131 deletions(-) diff --git a/arch/arm/boot/dts/at91-ariag25.dts b/arch/arm/boot/dts/at91-ariag25.dts index 0d695c762e54..dbfefef2869d 100644 --- a/arch/arm/boot/dts/at91-ariag25.dts +++ b/arch/arm/boot/dts/at91-ariag25.dts @@ -14,11 +14,6 @@ "atmel,at91sam9x5", "atmel,at91sam9"; aliases { - serial0 = &dbgu; - serial1 = &usart0; - serial2 = &usart1; - serial3 = &usart2; - serial4 = &usart3; serial5 = &uart0; serial6 = &uart1; }; @@ -42,132 +37,6 @@ }; }; - ahb { - apb { - mmc0: mmc@f0008000 { - /* N.B. Aria has no SD card detect (CD), assumed present */ - - pinctrl-0 = < - &pinctrl_mmc0_slot0_clk_cmd_dat0 - &pinctrl_mmc0_slot0_dat1_3>; - status = "okay"; - slot@0 { - reg = <0>; - bus-width = <4>; - }; - }; - - tcb0: timer@f8008000 { - timer@0 { - compatible = "atmel,tcb-timer"; - reg = <0>; - }; - - timer@1 { - compatible = "atmel,tcb-timer"; - reg = <1>; - }; - }; - - i2c0: i2c@f8010000 { - status = "okay"; - }; - - i2c1: i2c@f8014000 { - status = "okay"; - }; - - /* TWD2+TCLK2 hidden behind ethernet, so no i2c2 */ - - usart0: serial@f801c000 { - pinctrl-0 = <&pinctrl_usart0 - &pinctrl_usart0_rts - &pinctrl_usart0_cts>; - status = "okay"; - }; - - usart1: serial@f8020000 { - pinctrl-0 = <&pinctrl_usart1 - /* &pinctrl_usart1_rts */ - /* &pinctrl_usart1_cts */ - >; - status = "okay"; - }; - - usart2: serial@f8024000 { - /* cannot activate RTS2+CTS2, clash with - * ethernet on PB0 and PB1 */ - pinctrl-0 = <&pinctrl_usart2>; - status = "okay"; - }; - - usart3: serial@f8028000 { - compatible = "atmel,at91sam9260-usart"; - reg = <0xf8028000 0x200>; - interrupts = <8 4 5>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usart3 - /* &pinctrl_usart3_rts */ - /* &pinctrl_usart3_cts */ - >; - status = "okay"; - }; - - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - /* - * following can be overwritten by bootloader: - * for example u-boot 'ftd set' command - */ - local-mac-address = [00 00 00 00 00 00]; - status = "okay"; - }; - - /* - * UART0/1 pins are marked as GPIO on - * Aria documentation. - * Change to "okay" if you need additional serial ports - */ - uart0: serial@f8040000 { - status = "disabled"; - }; - - uart1: serial@f8044000 { - status = "disabled"; - }; - - adc0: adc@f804c000 { - status = "okay"; - atmel,adc-channels-used = <0xf>; - }; - - dbgu: serial@fffff200 { - status = "okay"; - }; - - pinctrl@fffff400 { - w1_0 { - pinctrl_w1_0: w1_0-0 { - atmel,pins = <0 21 0x0 0x1>; /* PA21 PIO, pull-up */ - }; - }; - }; - - rtc@fffffeb0 { - status = "okay"; - }; - }; - - usb0: ohci@600000 { - status = "okay"; - num-ports = <3>; - }; - - usb1: ehci@700000 { - status = "okay"; - }; - }; - leds { compatible = "gpio-leds"; @@ -187,3 +56,127 @@ pinctrl-0 = <&pinctrl_w1_0>; }; }; + +&adc0 { + status = "okay"; + atmel,adc-channels-used = <0xf>; +}; + +&dbgu { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; + +/* TWD2+TCLK2 hidden behind ethernet, so no i2c2 */ + +&macb0 { + phy-mode = "rmii"; + /* + * following can be overwritten by bootloader: + * for example u-boot 'ftd set' command + */ + local-mac-address = [00 00 00 00 00 00]; + status = "okay"; +}; + + +&mmc0 { + /* N.B. Aria has no SD card detect (CD), assumed present */ + + pinctrl-0 = < + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + }; +}; + +&pinctrl { + w1_0 { + pinctrl_w1_0: w1_0-0 { + atmel,pins = <0 21 0x0 0x1>; /* PA21 PIO, pull-up */ + }; + }; +}; + +&rtc { + status = "okay"; +}; + +&tcb0 { + timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; +}; + +/* + * UART0/1 pins are marked as GPIO on + * Aria documentation. + * Change to "okay" if you need additional serial ports + */ +&uart0 { + status = "disabled"; +}; + +&uart1 { + status = "disabled"; +}; + +&usart0 { + pinctrl-0 = <&pinctrl_usart0 + &pinctrl_usart0_rts + &pinctrl_usart0_cts>; + status = "okay"; +}; + +&usart1 { + pinctrl-0 = <&pinctrl_usart1 + /* &pinctrl_usart1_rts */ + /* &pinctrl_usart1_cts */ + >; + status = "okay"; +}; + +&usart2 { + /* cannot activate RTS2+CTS2, clash with + * ethernet on PB0 and PB1 */ + pinctrl-0 = <&pinctrl_usart2>; + status = "okay"; +}; + +&usart3 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xf8028000 0x200>; + interrupts = <8 4 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart3 + /* &pinctrl_usart3_rts */ + /* &pinctrl_usart3_cts */ + >; + status = "okay"; +}; + +&usb0 { + status = "okay"; + num-ports = <3>; +}; + +&usb1 { + status = "okay"; +}; -- GitLab From c756f614577e7c725efdae106fb8e329b3b12005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:51 +0200 Subject: [PATCH 3872/7155] ARM: dts: at91: ariettag25: style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - newline between properties and sub-nodes - use tags from included dtsi instead of duplicating the hierarchy - status should be the last property - drop duplicated alias There are no differences in the generated .dtb Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-3-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-ariettag25.dts | 100 ++++++++++++-------------- 1 file changed, 47 insertions(+), 53 deletions(-) diff --git a/arch/arm/boot/dts/at91-ariettag25.dts b/arch/arm/boot/dts/at91-ariettag25.dts index 7a34c4dc05d2..0267e72c074a 100644 --- a/arch/arm/boot/dts/at91-ariettag25.dts +++ b/arch/arm/boot/dts/at91-ariettag25.dts @@ -6,14 +6,11 @@ */ /dts-v1/; #include "at91sam9g25.dtsi" + / { model = "Acme Systems Arietta G25"; compatible = "acme,ariettag25", "atmel,at91sam9x5", "atmel,at91sam9"; - aliases { - serial0 = &dbgu; - }; - chosen { stdout-path = "serial0:115200n8"; }; @@ -32,57 +29,9 @@ }; }; - ahb { - apb { - mmc0: mmc@f0008000 { - pinctrl-0 = < - &pinctrl_mmc0_slot0_clk_cmd_dat0 - &pinctrl_mmc0_slot0_dat1_3>; - status = "okay"; - - slot@0 { - reg = <0>; - bus-width = <4>; - }; - }; - - tcb0: timer@f8008000 { - timer@0 { - compatible = "atmel,tcb-timer"; - reg = <0>; - }; - - timer@1 { - compatible = "atmel,tcb-timer"; - reg = <1>; - }; - }; - - usb2: gadget@f803c000 { - status = "okay"; - }; - - dbgu: serial@fffff200 { - status = "okay"; - }; - - rtc@fffffeb0 { - status = "okay"; - }; - }; - - usb0: ohci@600000 { - status = "okay"; - num-ports = <3>; - }; - - usb1: ehci@700000 { - status = "okay"; - }; - }; - leds { compatible = "gpio-leds"; + arietta_led { label = "arietta_led"; gpios = <&pioB 8 GPIO_ACTIVE_HIGH>; /* PB8 */ @@ -90,3 +39,48 @@ }; }; }; + +&dbgu { + status = "okay"; +}; + +&mmc0 { + pinctrl-0 = < + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + }; +}; + +&rtc { + status = "okay"; +}; + +&tcb0 { + timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; +}; + +&usb0 { + num-ports = <3>; + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&usb2 { + status = "okay"; +}; -- GitLab From fd117bba8c1e6a2726e52662aceb1076d4b4280f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:52 +0200 Subject: [PATCH 3873/7155] ARM: dts: at91: cosino: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - newline between properties and sub-nodes - use tags from included dtsi instead of duplicating the hierarchy - status should be the last property There are no differences in the generated .dtb Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-4-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-cosino.dtsi | 203 ++++++++++----------- arch/arm/boot/dts/at91-cosino_mega2560.dts | 93 +++++----- 2 files changed, 145 insertions(+), 151 deletions(-) diff --git a/arch/arm/boot/dts/at91-cosino.dtsi b/arch/arm/boot/dts/at91-cosino.dtsi index 47721c9a2e42..feebd54f670e 100644 --- a/arch/arm/boot/dts/at91-cosino.dtsi +++ b/arch/arm/boot/dts/at91-cosino.dtsi @@ -33,122 +33,119 @@ clock-frequency = <12000000>; }; }; +}; - ahb { - apb { - tcb0: timer@f8008000 { - timer@0 { - compatible = "atmel,tcb-timer"; - reg = <0>; - }; +&adc0 { + atmel,adc-ts-wires = <4>; + atmel,adc-ts-pressure-threshold = <10000>; + status = "okay"; +}; + +&dbgu { + status = "okay"; +}; - timer@1 { - compatible = "atmel,tcb-timer"; - reg = <1>; +&ebi { + pinctrl-0 = <&pinctrl_ebi_addr_nand + &pinctrl_ebi_data_0_7>; + pinctrl-names = "default"; + status = "okay"; + + nand-controller { + pinctrl-0 = <&pinctrl_nand_oe_we + &pinctrl_nand_cs + &pinctrl_nand_rb>; + pinctrl-names = "default"; + status = "okay"; + + nand@3 { + reg = <0x3 0x0 0x800000>; + rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>; + cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>; + nand-bus-width = <8>; + nand-ecc-mode = "hw"; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-on-flash-bbt; + label = "atmel_nand"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x40000>; }; - }; - mmc0: mmc@f0008000 { - pinctrl-0 = < - &pinctrl_board_mmc0 - &pinctrl_mmc0_slot0_clk_cmd_dat0 - &pinctrl_mmc0_slot0_dat1_3>; - status = "okay"; - slot@0 { - reg = <0>; - bus-width = <4>; - cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>; + uboot@40000 { + label = "u-boot"; + reg = <0x40000 0x80000>; }; - }; - dbgu: serial@fffff200 { - status = "okay"; - }; + ubootenv@c0000 { + label = "U-Boot Env"; + reg = <0xc0000 0x140000>; + }; - usart0: serial@f801c000 { - status = "okay"; - }; + kernel@200000 { + label = "kernel"; + reg = <0x200000 0x600000>; + }; - i2c0: i2c@f8010000 { - status = "okay"; + rootfs@800000 { + label = "rootfs"; + reg = <0x800000 0x0f800000>; + }; }; + }; + }; +}; - adc0: adc@f804c000 { - atmel,adc-ts-wires = <4>; - atmel,adc-ts-pressure-threshold = <10000>; - status = "okay"; - }; +&i2c0 { + status = "okay"; +}; - pinctrl@fffff400 { - mmc0 { - pinctrl_board_mmc0: mmc0-board { - atmel,pins = - ; /* PD15 gpio CD pin pull up and deglitch */ - }; - }; - }; +&mmc0 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>; + }; +}; - watchdog@fffffe40 { - status = "okay"; - }; +&pinctrl { + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + ; /* PD15 gpio CD pin pull up and deglitch */ }; + }; +}; - ebi: ebi@10000000 { - pinctrl-0 = <&pinctrl_ebi_addr_nand - &pinctrl_ebi_data_0_7>; - pinctrl-names = "default"; - status = "okay"; - - nand_controller: nand-controller { - status = "okay"; - pinctrl-0 = <&pinctrl_nand_oe_we - &pinctrl_nand_cs - &pinctrl_nand_rb>; - pinctrl-names = "default"; - - nand@3 { - reg = <0x3 0x0 0x800000>; - rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>; - cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>; - nand-bus-width = <8>; - nand-ecc-mode = "hw"; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-on-flash-bbt; - label = "atmel_nand"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - at91bootstrap@0 { - label = "at91bootstrap"; - reg = <0x0 0x40000>; - }; - - uboot@40000 { - label = "u-boot"; - reg = <0x40000 0x80000>; - }; - - ubootenv@c0000 { - label = "U-Boot Env"; - reg = <0xc0000 0x140000>; - }; - - kernel@200000 { - label = "kernel"; - reg = <0x200000 0x600000>; - }; - - rootfs@800000 { - label = "rootfs"; - reg = <0x800000 0x0f800000>; - }; - }; - }; - }; - }; +&tcb0 { + timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; }; }; + +&usart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/at91-cosino_mega2560.dts b/arch/arm/boot/dts/at91-cosino_mega2560.dts index 8fde06adf7cb..73e88d1ba4ed 100644 --- a/arch/arm/boot/dts/at91-cosino_mega2560.dts +++ b/arch/arm/boot/dts/at91-cosino_mega2560.dts @@ -17,61 +17,58 @@ / { model = "HCE Cosino Mega 2560"; compatible = "hce,cosino_mega2560", "atmel,at91sam9x5", "atmel,at91sam9"; +}; + +&adc0 { + atmel,adc-ts-wires = <4>; + atmel,adc-ts-pressure-threshold = <10000>; + status = "okay"; +}; - ahb { - apb { - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; - adc0: adc@f804c000 { - atmel,adc-ts-wires = <4>; - atmel,adc-ts-pressure-threshold = <10000>; - status = "okay"; - }; +&mmc1 { + pinctrl-0 = < + &pinctrl_mmc1_slot0_clk_cmd_dat0 + &pinctrl_mmc1_slot0_dat1_3>; + status = "okay"; - rtc@fffffeb0 { - status = "okay"; - }; + slot@0 { + reg = <0>; + bus-width = <4>; + non-removable; + }; +}; - usart1: serial@f8020000 { - status = "okay"; - }; +&rtc { + status = "okay"; +}; - usart2: serial@f8024000 { - status = "okay"; - }; +&usart1 { + status = "okay"; +}; - usb2: gadget@f803c000 { - atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +&usart2 { + status = "okay"; +}; - mmc1: mmc@f000c000 { - pinctrl-0 = < - &pinctrl_mmc1_slot0_clk_cmd_dat0 - &pinctrl_mmc1_slot0_dat1_3>; - status = "okay"; - slot@0 { - reg = <0>; - bus-width = <4>; - non-removable; - }; - }; - }; +&usb0 { + num-ports = <3>; + atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW */ + &pioD 19 GPIO_ACTIVE_LOW + &pioD 20 GPIO_ACTIVE_LOW + >; + status = "okay"; +}; - usb0: ohci@600000 { - status = "okay"; - num-ports = <3>; - atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW */ - &pioD 19 GPIO_ACTIVE_LOW - &pioD 20 GPIO_ACTIVE_LOW - >; - }; +&usb1 { + status = "okay"; +}; - usb1: ehci@700000 { - status = "okay"; - }; - }; +&usb2 { + atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>; + status = "okay"; }; -- GitLab From a77eb442f98747a5d567ea0b1a7b95949415fce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:53 +0200 Subject: [PATCH 3874/7155] ARM: dts: at91: kizboxmini: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtb Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-5-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-kizboxmini.dts | 179 +++++++++++++------------- 1 file changed, 88 insertions(+), 91 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizboxmini.dts b/arch/arm/boot/dts/at91-kizboxmini.dts index 0620dcdf4dfb..cb22f5fb055f 100644 --- a/arch/arm/boot/dts/at91-kizboxmini.dts +++ b/arch/arm/boot/dts/at91-kizboxmini.dts @@ -32,96 +32,6 @@ }; ahb { - apb { - tcb0: timer@f8008000 { - timer@0 { - compatible = "atmel,tcb-timer"; - reg = <0>; - }; - - timer@1 { - compatible = "atmel,tcb-timer"; - reg = <1>; - }; - }; - - usart0: serial@f801c000 { - status = "okay"; - }; - - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; - - pwm0: pwm@f8034000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pwm0_pwm0_1 - &pinctrl_pwm0_pwm1_1>; - status = "okay"; - }; - - dbgu: serial@fffff200 { - status = "okay"; - }; - - watchdog@fffffe40 { - status = "okay"; - }; - }; - - usb0: ohci@600000 { - num-ports = <1>; - status = "okay"; - }; - - usb1: ehci@700000 { - status = "okay"; - }; - - ebi: ebi@10000000 { - pinctrl-0 = <&pinctrl_ebi_addr_nand - &pinctrl_ebi_data_0_7>; - pinctrl-names = "default"; - status = "okay"; - - nand_controller: nand-controller { - status = "okay"; - pinctrl-0 = <&pinctrl_nand_oe_we - &pinctrl_nand_cs - &pinctrl_nand_rb>; - pinctrl-names = "default"; - - nand@3 { - reg = <0x3 0x0 0x800000>; - rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>; - cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>; - nand-bus-width = <8>; - nand-ecc-mode = "hw"; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-on-flash-bbt; - label = "atmel_nand"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - bootstrap@0 { - label = "bootstrap"; - reg = <0x0 0x20000>; - }; - - ubi@20000 { - label = "ubi"; - reg = <0x20000 0x7fe0000>; - }; - }; - }; - }; - }; - nand0: nand@40000000 { nand-bus-width = <8>; nand-ecc-mode = "hw"; @@ -130,7 +40,6 @@ atmel,pmecc-sector-size = <512>; nand-on-flash-bbt; status = "okay"; - }; }; @@ -172,3 +81,91 @@ }; }; }; + +&dbgu { + status = "okay"; +}; + +&ebi { + pinctrl-0 = <&pinctrl_ebi_addr_nand + &pinctrl_ebi_data_0_7>; + pinctrl-names = "default"; + status = "okay"; + + nand-controller { + pinctrl-0 = <&pinctrl_nand_oe_we + &pinctrl_nand_cs + &pinctrl_nand_rb>; + pinctrl-names = "default"; + status = "okay"; + + nand@3 { + reg = <0x3 0x0 0x800000>; + rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>; + cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>; + nand-bus-width = <8>; + nand-ecc-mode = "hw"; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-on-flash-bbt; + label = "atmel_nand"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + bootstrap@0 { + label = "bootstrap"; + reg = <0x0 0x20000>; + }; + + ubi@20000 { + label = "ubi"; + reg = <0x20000 0x7fe0000>; + }; + }; + }; + }; +}; + +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; + +&pwm0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_pwm0_1 + &pinctrl_pwm0_pwm1_1>; + status = "okay"; +}; + +&tcb0 { + timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; +}; + +&usart0 { + status = "okay"; +}; + +&usb0 { + num-ports = <1>; + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; -- GitLab From c1ad3ffb182e31eb445b7afbb0c02c70a3eef48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:54 +0200 Subject: [PATCH 3875/7155] ARM: dts: at91: at91sam9g15: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtbs Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-6-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9g15.dtsi | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi index d77c69ad7f02..dde88276fe52 100644 --- a/arch/arm/boot/dts/at91sam9g15.dtsi +++ b/arch/arm/boot/dts/at91sam9g15.dtsi @@ -11,22 +11,18 @@ / { model = "Atmel AT91SAM9G15 SoC"; compatible = "atmel,at91sam9g15", "atmel,at91sam9x5"; +}; - ahb { - apb { - pinctrl@fffff400 { - atmel,mux-mask = < - /* A B C */ - 0xffffffff 0xffe0399f 0x00000000 /* pioA */ - 0x00040000 0x00047e3f 0x00000000 /* pioB */ - 0xfdffffff 0x00000000 0xb83fffff /* pioC */ - 0x003fffff 0x003f8000 0x00000000 /* pioD */ - >; - }; +&pinctrl { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe0399f 0x00000000 /* pioA */ + 0x00040000 0x00047e3f 0x00000000 /* pioB */ + 0xfdffffff 0x00000000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; +}; - pmc: pmc@fffffc00 { - compatible = "atmel,at91sam9g15-pmc", "atmel,at91sam9x5-pmc", "syscon"; - }; - }; - }; +&pmc { + compatible = "atmel,at91sam9g15-pmc", "atmel,at91sam9x5-pmc", "syscon"; }; -- GitLab From b222de0242dfb7efaa6e35b68ce844878667ca82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:55 +0200 Subject: [PATCH 3876/7155] ARM: dts: at91: at91sam9xx5ek: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - newline between properties and sub-nodes - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtbs Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-7-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9g15ek.dts | 12 +- arch/arm/boot/dts/at91sam9g25ek.dts | 89 +++++----- arch/arm/boot/dts/at91sam9g35ek.dts | 22 +-- arch/arm/boot/dts/at91sam9x25ek.dts | 36 ++-- arch/arm/boot/dts/at91sam9x35ek.dts | 43 +++-- arch/arm/boot/dts/at91sam9x5ek.dtsi | 265 ++++++++++++++-------------- 6 files changed, 224 insertions(+), 243 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts index 97100d298400..889a5097eb2d 100644 --- a/arch/arm/boot/dts/at91sam9g15ek.dts +++ b/arch/arm/boot/dts/at91sam9g15ek.dts @@ -14,14 +14,6 @@ model = "Atmel AT91SAM9G15-EK"; compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; - ahb { - apb { - hlcdc: hlcdc@f8038000 { - status = "okay"; - }; - }; - }; - backlight: backlight { status = "okay"; }; @@ -38,3 +30,7 @@ status = "okay"; }; }; + +&hlcdc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index a02c6c79ce52..61b0bdb615dc 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -12,57 +12,54 @@ / { model = "Atmel AT91SAM9G25-EK"; compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; - ahb { - apb { - spi0: spi@f0000000 { - status = "disabled"; - }; - - mmc1: mmc@f000c000 { - status = "disabled"; - }; - - i2c0: i2c@f8010000 { - ov2640: camera@30 { - compatible = "ovti,ov2640"; - reg = <0x30>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>; - resetb-gpios = <&pioA 7 GPIO_ACTIVE_LOW>; - pwdn-gpios = <&pioA 13 GPIO_ACTIVE_HIGH>; - clocks = <&pmc PMC_TYPE_SYSTEM 8>; - clock-names = "xvclk"; - assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>; - assigned-clock-rates = <25000000>; - status = "okay"; +&i2c0 { + camera@30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>; + resetb-gpios = <&pioA 7 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&pioA 13 GPIO_ACTIVE_HIGH>; + clocks = <&pmc PMC_TYPE_SYSTEM 8>; + clock-names = "xvclk"; + assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>; + assigned-clock-rates = <25000000>; + status = "okay"; - port { - ov2640_0: endpoint { - remote-endpoint = <&isi_0>; - bus-width = <8>; - }; - }; - }; + port { + ov2640_0: endpoint { + remote-endpoint = <&isi_0>; + bus-width = <8>; }; + }; + }; +}; - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; +&isi { + status = "okay"; - isi: isi@f8048000 { - status = "okay"; - port { - isi_0: endpoint@0 { - reg = <0>; - remote-endpoint = <&ov2640_0>; - bus-width = <8>; - vsync-active = <1>; - hsync-active = <1>; - }; - }; - }; + port { + isi_0: endpoint@0 { + reg = <0>; + remote-endpoint = <&ov2640_0>; + bus-width = <8>; + vsync-active = <1>; + hsync-active = <1>; }; }; }; + +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; + +&mmc1 { + status = "disabled"; +}; + +&spi0 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts index 449ec712ab52..f966b56de63c 100644 --- a/arch/arm/boot/dts/at91sam9g35ek.dts +++ b/arch/arm/boot/dts/at91sam9g35ek.dts @@ -14,19 +14,6 @@ model = "Atmel AT91SAM9G35-EK"; compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; - ahb { - apb { - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; - - hlcdc: hlcdc@f8038000 { - status = "okay"; - }; - }; - }; - backlight: backlight { status = "okay"; }; @@ -43,3 +30,12 @@ status = "okay"; }; }; + +&hlcdc { + status = "okay"; +}; + +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts index 4e1c3df89a6c..ad7c6b36f0ba 100644 --- a/arch/arm/boot/dts/at91sam9x25ek.dts +++ b/arch/arm/boot/dts/at91sam9x25ek.dts @@ -12,28 +12,24 @@ / { model = "Atmel AT91SAM9X25-EK"; compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; - ahb { - apb { - can1: can@f8004000 { - status = "okay"; - }; +&can1 { + status = "okay"; +}; - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; - macb1: ethernet@f8030000 { - phy-mode = "rmii"; - status = "okay"; - }; +&macb1 { + phy-mode = "rmii"; + status = "okay"; +}; - pwm0: pwm@f8034000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pwm0_pwm0_1>; - status = "okay"; - }; - }; - }; +&pwm0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_pwm0_1>; + status = "okay"; }; diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts index 7646c680fa97..66675c787b97 100644 --- a/arch/arm/boot/dts/at91sam9x35ek.dts +++ b/arch/arm/boot/dts/at91sam9x35ek.dts @@ -13,32 +13,29 @@ / { model = "Atmel AT91SAM9X35-EK"; compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; - ahb { - apb { - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; - hlcdc: hlcdc@f8038000 { - status = "okay"; - }; - }; - }; +&backlight { + status = "okay"; +}; - backlight: backlight { - status = "okay"; - }; +&bl_reg { + status = "okay"; +}; - bl_reg: backlight_regulator { - status = "okay"; - }; +&hlcdc { + status = "okay"; +}; - panel: panel { - status = "okay"; - }; +&macb0 { + phy-mode = "rmii"; + status = "okay"; +}; + +&panel { + status = "okay"; +}; - panel_reg: panel_regulator { - status = "okay"; - }; +&panel_reg { + status = "okay"; }; diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi index 2ad0a43656e4..c934928742b0 100644 --- a/arch/arm/boot/dts/at91sam9x5ek.dtsi +++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi @@ -16,139 +16,6 @@ stdout-path = "serial0:115200n8"; }; - ahb { - apb { - mmc0: mmc@f0008000 { - pinctrl-0 = < - &pinctrl_board_mmc0 - &pinctrl_mmc0_slot0_clk_cmd_dat0 - &pinctrl_mmc0_slot0_dat1_3>; - status = "okay"; - slot@0 { - reg = <0>; - bus-width = <4>; - cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>; - }; - }; - - mmc1: mmc@f000c000 { - pinctrl-0 = < - &pinctrl_board_mmc1 - &pinctrl_mmc1_slot0_clk_cmd_dat0 - &pinctrl_mmc1_slot0_dat1_3>; - status = "okay"; - slot@0 { - reg = <0>; - bus-width = <4>; - cd-gpios = <&pioD 14 GPIO_ACTIVE_HIGH>; - }; - }; - - dbgu: serial@fffff200 { - status = "okay"; - }; - - usart0: serial@f801c000 { - atmel,use-dma-rx; - atmel,use-dma-tx; - status = "okay"; - }; - - usb2: gadget@f803c000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_board_usb2>; - atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - i2c0: i2c@f8010000 { - status = "okay"; - - wm8731: wm8731@1a { - compatible = "wm8731"; - reg = <0x1a>; - }; - }; - - adc0: adc@f804c000 { - atmel,adc-ts-wires = <4>; - atmel,adc-ts-pressure-threshold = <10000>; - status = "okay"; - }; - - pinctrl@fffff400 { - camera_sensor { - pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 { - atmel,pins = - ; /* ISI_MCK */ - }; - - pinctrl_sensor_power: sensor_power-0 { - atmel,pins = - ; - }; - - pinctrl_sensor_reset: sensor_reset-0 { - atmel,pins = - ; - }; - }; - - mmc0 { - pinctrl_board_mmc0: mmc0-board { - atmel,pins = - ; /* PD15 gpio CD pin pull up and deglitch */ - }; - }; - - mmc1 { - pinctrl_board_mmc1: mmc1-board { - atmel,pins = - ; /* PD14 gpio CD pin pull up and deglitch */ - }; - }; - - usb2 { - pinctrl_board_usb2: usb2-board { - atmel,pins = - ; /* PB16 gpio vbus sense, deglitch */ - }; - }; - }; - - spi0: spi@f0000000 { - status = "disabled"; /* conflicts with mmc1 */ - cs-gpios = <&pioA 14 0>, <0>, <0>, <0>; - m25p80@0 { - compatible = "atmel,at25df321a"; - spi-max-frequency = <50000000>; - reg = <0>; - }; - }; - - watchdog@fffffe40 { - status = "okay"; - }; - - ssc0: ssc@f0010000 { - status = "okay"; - }; - }; - - usb0: ohci@600000 { - status = "okay"; - num-ports = <3>; - atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */ - &pioD 19 GPIO_ACTIVE_LOW - &pioD 20 GPIO_ACTIVE_LOW - >; - }; - - usb1: ehci@700000 { - status = "okay"; - }; - }; - sound { compatible = "atmel,sam9x5-wm8731-audio"; @@ -164,3 +31,135 @@ atmel,audio-codec = <&wm8731>; }; }; + +&adc0 { + atmel,adc-ts-wires = <4>; + atmel,adc-ts-pressure-threshold = <10000>; + status = "okay"; +}; + +&dbgu { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + wm8731: wm8731@1a { + compatible = "wm8731"; + reg = <0x1a>; + }; +}; + +&mmc0 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>; + }; +}; + +&mmc1 { + pinctrl-0 = < + &pinctrl_board_mmc1 + &pinctrl_mmc1_slot0_clk_cmd_dat0 + &pinctrl_mmc1_slot0_dat1_3>; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 14 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + camera_sensor { + pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 { + atmel,pins = + ; /* ISI_MCK */ + }; + + pinctrl_sensor_power: sensor_power-0 { + atmel,pins = + ; + }; + + pinctrl_sensor_reset: sensor_reset-0 { + atmel,pins = + ; + }; + }; + + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + ; /* PD15 gpio CD pin pull up and deglitch */ + }; + }; + + mmc1 { + pinctrl_board_mmc1: mmc1-board { + atmel,pins = + ; /* PD14 gpio CD pin pull up and deglitch */ + }; + }; + + usb2 { + pinctrl_board_usb2: usb2-board { + atmel,pins = + ; /* PB16 gpio vbus sense, deglitch */ + }; + }; +}; + +&spi0 { + cs-gpios = <&pioA 14 0>, <0>, <0>, <0>; + status = "disabled"; /* conflicts with mmc1 */ + + m25p80@0 { + compatible = "atmel,at25df321a"; + spi-max-frequency = <50000000>; + reg = <0>; + }; +}; + +&ssc0 { + status = "okay"; +}; + +&usart0 { + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; +}; + +&usb0 { + num-ports = <3>; + atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */ + &pioD 19 GPIO_ACTIVE_LOW + &pioD 20 GPIO_ACTIVE_LOW + >; + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&usb2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_board_usb2>; + atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; -- GitLab From 532173b404a8d6b39d17c4db457915bd793ec918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:56 +0200 Subject: [PATCH 3877/7155] ARM: dts: at91: at91sam9x5_lcd.dtsi: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtbs Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-8-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9x5_lcd.dtsi | 194 +++++++++++++------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi index 584f840cc6a5..f81c9d1691e0 100644 --- a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi +++ b/arch/arm/boot/dts/at91sam9x5_lcd.dtsi @@ -39,109 +39,109 @@ #pwm-cells = <3>; }; }; + }; + }; +}; - pinctrl@fffff400 { - lcd { - pinctrl_lcd_base: lcd-base-0 { - atmel,pins = - ; /* LCDPCK */ - }; +&pinctrl { + lcd { + pinctrl_lcd_base: lcd-base-0 { + atmel,pins = + ; /* LCDPCK */ + }; - pinctrl_lcd_pwm: lcd-pwm-0 { - atmel,pins = ; /* LCDPWM */ - }; + pinctrl_lcd_pwm: lcd-pwm-0 { + atmel,pins = ; /* LCDPWM */ + }; - pinctrl_lcd_rgb444: lcd-rgb-0 { - atmel,pins = - ; /* LCDD11 pin */ - }; + pinctrl_lcd_rgb444: lcd-rgb-0 { + atmel,pins = + ; /* LCDD11 pin */ + }; - pinctrl_lcd_rgb565: lcd-rgb-1 { - atmel,pins = - ; /* LCDD15 pin */ - }; + pinctrl_lcd_rgb565: lcd-rgb-1 { + atmel,pins = + ; /* LCDD15 pin */ + }; - pinctrl_lcd_rgb666: lcd-rgb-2 { - atmel,pins = - ; /* LCDD17 pin */ - }; + pinctrl_lcd_rgb666: lcd-rgb-2 { + atmel,pins = + ; /* LCDD17 pin */ + }; - pinctrl_lcd_rgb888: lcd-rgb-3 { - atmel,pins = - ; /* LCDD23 pin */ - }; - }; - }; + pinctrl_lcd_rgb888: lcd-rgb-3 { + atmel,pins = + ; /* LCDD23 pin */ }; }; }; -- GitLab From bb3e9c767c6134a5761470038e8c75cdb6f04867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Aug 2019 23:27:57 +0200 Subject: [PATCH 3878/7155] ARM: dts: at91: at91sam9x5dm.dtsi: Style cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use tags from included dtsi instead of duplicating the hierarchy There are no differences in the generated .dtbs Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190812212757.23432-9-uwe@kleine-koenig.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91sam9x5dm.dtsi | 86 ++++++++++++++--------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/at91sam9x5dm.dtsi index b04ebf1a3131..7f00c1f57b90 100644 --- a/arch/arm/boot/dts/at91sam9x5dm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5dm.dtsi @@ -9,51 +9,6 @@ */ / { - ahb { - apb { - i2c0: i2c@f8010000 { - qt1070: keyboard@1b { - compatible = "qt1070"; - reg = <0x1b>; - interrupt-parent = <&pioA>; - interrupts = <7 0x0>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_qt1070_irq>; - wakeup-source; - }; - }; - - hlcdc: hlcdc@f8038000 { - hlcdc-display-controller { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>; - - port@0 { - hlcdc_panel_output: endpoint@0 { - reg = <0>; - remote-endpoint = <&panel_input>; - }; - }; - }; - }; - - adc0: adc@f804c000 { - atmel,adc-ts-wires = <4>; - atmel,adc-ts-pressure-threshold = <10000>; - status = "okay"; - }; - - pinctrl@fffff400 { - board { - pinctrl_qt1070_irq: qt1070_irq { - atmel,pins = - ; - }; - }; - }; - }; - }; - backlight: backlight { compatible = "pwm-backlight"; pwms = <&hlcdc_pwm 0 50000 0>; @@ -98,3 +53,44 @@ status = "disabled"; }; }; + +&adc0 { + atmel,adc-ts-wires = <4>; + atmel,adc-ts-pressure-threshold = <10000>; + status = "okay"; +}; + +&i2c0 { + keyboard@1b { + compatible = "qt1070"; + reg = <0x1b>; + interrupt-parent = <&pioA>; + interrupts = <7 0x0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qt1070_irq>; + wakeup-source; + }; +}; + +&hlcdc { + hlcdc-display-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>; + + port@0 { + hlcdc_panel_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_input>; + }; + }; + }; +}; + +&pinctrl { + board { + pinctrl_qt1070_irq: qt1070_irq { + atmel,pins = + ; + }; + }; +}; -- GitLab From a599e48662b4b505bef45d4831061f9d50703e17 Mon Sep 17 00:00:00 2001 From: Jacob Huisman Date: Thu, 15 Aug 2019 18:42:10 +0100 Subject: [PATCH 3879/7155] usb: usb-skeleton: make comment block in line with coding style Comment block was not in accordance with coding style. Fixes two checkpatch warnings: WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Jacob Huisman Link: https://lore.kernel.org/r/20190815174210.580-1-jacobhuisman@kernelthusiast.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index f101347e3ea3..c31d17d05810 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -35,9 +35,11 @@ MODULE_DEVICE_TABLE(usb, skel_table); /* our private defines. if this grows any larger, use your own .h file */ #define MAX_TRANSFER (PAGE_SIZE - 512) -/* MAX_TRANSFER is chosen so that the VM is not stressed by - allocations > PAGE_SIZE and the number of packets in a page - is an integer 512 is the largest possible packet on EHCI */ +/* + * MAX_TRANSFER is chosen so that the VM is not stressed by + * allocations > PAGE_SIZE and the number of packets in a page + * is an integer 512 is the largest possible packet on EHCI + */ #define WRITES_IN_FLIGHT 8 /* arbitrarily chosen */ -- GitLab From b08a6259a141baba98c57524ee4283fd91445bb8 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Wed, 14 Aug 2019 14:29:24 -0700 Subject: [PATCH 3880/7155] usb: usbfs: only account once for mmap()'ed usb memory usage Memory usage for USB memory allocated via mmap() is already accounted for at mmap() time; no need to account for it again at submiturb time. Signed-off-by: Gavin Li Acked-by: Alan Stern Link: https://lore.kernel.org/r/20190814212924.10381-1-gavinli@thegavinli.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 24d4a801ca64..63f23f567680 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1664,7 +1664,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb if (as->usbm) num_sgs = 0; - u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + + u += sizeof(struct async) + sizeof(struct urb) + + (as->usbm ? 0 : uurb->buffer_length) + num_sgs * sizeof(struct scatterlist); ret = usbfs_increase_memory_usage(u); if (ret) -- GitLab From b5e86196b83fd68e065a7c811ab8925fb0dc3893 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 21 Aug 2019 14:17:00 +0100 Subject: [PATCH 3881/7155] iommu/arm-smmu-v3: Disable detection of ATS and PRI Detecting the ATS capability of the SMMU at probe time introduces a spinlock into the ->unmap() fast path, even when ATS is not actually in use. Furthermore, the ATC invalidation that exists is broken, as it occurs before invalidation of the main SMMU TLB which leaves a window where the ATC can be repopulated with stale entries. Given that ATS is both a new feature and a specialist sport, disable it for now whilst we fix it properly in subsequent patches. Since PRI requires ATS, disable that too. Cc: Fixes: 9ce27afc0830 ("iommu/arm-smmu-v3: Add support for PCI ATS") Acked-by: Robin Murphy Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 3402b1bc8e94..7a368059cd7d 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -3295,11 +3295,13 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) } /* Boolean feature flags */ +#if 0 /* ATS invalidation is slow and broken */ if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI) smmu->features |= ARM_SMMU_FEAT_PRI; if (IS_ENABLED(CONFIG_PCI_ATS) && reg & IDR0_ATS) smmu->features |= ARM_SMMU_FEAT_ATS; +#endif if (reg & IDR0_SEV) smmu->features |= ARM_SMMU_FEAT_SEV; -- GitLab From f75d8e33df91ee66fc12820d0da1454b76ebcff9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 20 Aug 2019 17:32:18 +0100 Subject: [PATCH 3882/7155] iommu/arm-smmu-v3: Remove boolean bitfield for 'ats_enabled' flag There's really no need for this to be a bitfield, particularly as we don't have bitwise addressing on arm64. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 7a368059cd7d..2be11a11bb8b 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -637,7 +637,7 @@ struct arm_smmu_master { struct list_head domain_head; u32 *sids; unsigned int num_sids; - bool ats_enabled :1; + bool ats_enabled; }; /* SMMU private data for an IOMMU domain */ -- GitLab From 7314ca8699e1defd6f2883f203c0e828a4f51f9f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 21 Aug 2019 12:38:15 +0100 Subject: [PATCH 3883/7155] iommu/arm-smmu-v3: Don't issue CMD_SYNC for zero-length invalidations Calling arm_smmu_tlb_inv_range() with a size of zero, perhaps due to an empty 'iommu_iotlb_gather' structure, should be a NOP. Elide the CMD_SYNC when there is no invalidation to be performed. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 2be11a11bb8b..b7b3b0ff8ed6 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1977,6 +1977,9 @@ static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size, }, }; + if (!size) + return; + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { cmd.opcode = CMDQ_OP_TLBI_NH_VA; cmd.tlbi.asid = smmu_domain->s1_cfg.cd.asid; -- GitLab From bfff88ec1afefb76669d29da9fc90d5ad7c53ec3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 20 Aug 2019 14:28:59 +0100 Subject: [PATCH 3884/7155] iommu/arm-smmu-v3: Rework enabling/disabling of ATS for PCI masters To prevent any potential issues arising from speculative Address Translation Requests from an ATS-enabled PCIe endpoint, rework our ATS enabling/disabling logic so that we enable ATS at the SMMU before we enable it at the endpoint, and disable things in the opposite order. Reviewed-by: Robin Murphy Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 47 ++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index b7b3b0ff8ed6..d7c65dfe42dc 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2286,44 +2286,52 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master) } } -static int arm_smmu_enable_ats(struct arm_smmu_master *master) +static bool arm_smmu_ats_supported(struct arm_smmu_master *master) { - int ret; - size_t stu; struct pci_dev *pdev; struct arm_smmu_device *smmu = master->smmu; struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev); if (!(smmu->features & ARM_SMMU_FEAT_ATS) || !dev_is_pci(master->dev) || !(fwspec->flags & IOMMU_FWSPEC_PCI_RC_ATS) || pci_ats_disabled()) - return -ENXIO; + return false; pdev = to_pci_dev(master->dev); - if (pdev->untrusted) - return -EPERM; + return !pdev->untrusted && pdev->ats_cap; +} - /* Smallest Translation Unit: log2 of the smallest supported granule */ - stu = __ffs(smmu->pgsize_bitmap); +static void arm_smmu_enable_ats(struct arm_smmu_master *master) +{ + size_t stu; + struct pci_dev *pdev; + struct arm_smmu_device *smmu = master->smmu; - ret = pci_enable_ats(pdev, stu); - if (ret) - return ret; + /* Don't enable ATS at the endpoint if it's not enabled in the STE */ + if (!master->ats_enabled) + return; - master->ats_enabled = true; - return 0; + /* Smallest Translation Unit: log2 of the smallest supported granule */ + stu = __ffs(smmu->pgsize_bitmap); + pdev = to_pci_dev(master->dev); + if (pci_enable_ats(pdev, stu)) + dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu); } static void arm_smmu_disable_ats(struct arm_smmu_master *master) { struct arm_smmu_cmdq_ent cmd; - if (!master->ats_enabled || !dev_is_pci(master->dev)) + if (!master->ats_enabled) return; + pci_disable_ats(to_pci_dev(master->dev)); + /* + * Ensure ATS is disabled at the endpoint before we issue the + * ATC invalidation via the SMMU. + */ + wmb(); arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd); arm_smmu_atc_inv_master(master, &cmd); - pci_disable_ats(to_pci_dev(master->dev)); - master->ats_enabled = false; } static void arm_smmu_detach_dev(struct arm_smmu_master *master) @@ -2338,10 +2346,10 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master) list_del(&master->domain_head); spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); + arm_smmu_disable_ats(master); master->domain = NULL; + master->ats_enabled = false; arm_smmu_install_ste_for_dev(master); - - arm_smmu_disable_ats(master); } static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) @@ -2386,12 +2394,13 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS) - arm_smmu_enable_ats(master); + master->ats_enabled = arm_smmu_ats_supported(master); if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg); arm_smmu_install_ste_for_dev(master); + arm_smmu_enable_ats(master); out_unlock: mutex_unlock(&smmu_domain->init_mutex); return ret; -- GitLab From 353e3cf8590cf182a9f42e67993de3aca91e8090 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 20 Aug 2019 15:12:12 +0100 Subject: [PATCH 3885/7155] iommu/arm-smmu-v3: Fix ATC invalidation ordering wrt main TLBs When invalidating the ATC for an PCIe endpoint using ATS, we must take care to complete invalidation of the main SMMU TLBs beforehand, otherwise the device could immediately repopulate its ATC with stale translations. Hooking the ATC invalidation into ->unmap() as we currently do does the exact opposite: it ensures that the ATC is invalidated *before* the main TLBs, which is bogus. Move ATC invalidation into the actual (leaf) invalidation routines so that it is always called after completing main TLB invalidation. Reviewed-by: Robin Murphy Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index d7c65dfe42dc..ca504a60312d 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1961,6 +1961,7 @@ static void arm_smmu_tlb_inv_context(void *cookie) */ arm_smmu_cmdq_issue_cmd(smmu, &cmd); arm_smmu_cmdq_issue_sync(smmu); + arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0); } static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size, @@ -1969,7 +1970,7 @@ static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size, { u64 cmds[CMDQ_BATCH_ENTRIES * CMDQ_ENT_DWORDS]; struct arm_smmu_device *smmu = smmu_domain->smmu; - unsigned long end = iova + size; + unsigned long start = iova, end = iova + size; int i = 0; struct arm_smmu_cmdq_ent cmd = { .tlbi = { @@ -2001,6 +2002,12 @@ static void arm_smmu_tlb_inv_range(unsigned long iova, size_t size, } arm_smmu_cmdq_issue_cmdlist(smmu, cmds, i, true); + + /* + * Unfortunately, this can't be leaf-only since we may have + * zapped an entire table. + */ + arm_smmu_atc_inv_domain(smmu_domain, 0, start, size); } static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, @@ -2420,18 +2427,13 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size, struct iommu_iotlb_gather *gather) { - int ret; struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops; if (!ops) return 0; - ret = ops->unmap(ops, iova, size, gather); - if (ret && arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size)) - return 0; - - return ret; + return ops->unmap(ops, iova, size, gather); } static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) -- GitLab From 0709831a50d31b3caf2237e8d7fe89e15b0d919d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 17 Aug 2019 09:55:20 +0300 Subject: [PATCH 3886/7155] usb: host: ohci-pxa27x: Fix and & vs | typo The code is supposed to clear the RH_A_NPS and RH_A_PSM bits, but it's a no-op because of the & vs | typo. This bug predates git and it was only discovered using static analysis so it must not affect too many people in real life. Signed-off-by: Dan Carpenter Acked-by: Alan Stern Link: https://lore.kernel.org/r/20190817065520.GA29951@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pxa27x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 3e2474959735..7679fb583e41 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -148,7 +148,7 @@ static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode) uhcrhda |= RH_A_NPS; break; case PMM_GLOBAL_MODE: - uhcrhda &= ~(RH_A_NPS & RH_A_PSM); + uhcrhda &= ~(RH_A_NPS | RH_A_PSM); break; case PMM_PERPORT_MODE: uhcrhda &= ~(RH_A_NPS); -- GitLab From 7b81cb6bddd2c4f2489506771070924bd0ae9902 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 16 Aug 2019 08:24:32 +0200 Subject: [PATCH 3887/7155] usb: add a HCD_DMA flag instead of guestimating DMA capabilities The usb core is the only major place in the kernel that checks for a non-NULL device dma_mask to see if a device is DMA capable. This is generally a bad idea, as all major busses always set up a DMA mask, even if the device is not DMA capable - in fact bus layers like PCI can't even know if a device is DMA capable at enumeration time. This leads to lots of workaround in HCD drivers, and also prevented us from setting up a DMA mask for platform devices by default last time we tried. Replace this guess with an explicit HCD_DMA that is set by drivers that appear to have DMA support. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20190816062435.881-4-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 2 +- drivers/usb/core/hcd.c | 1 - drivers/usb/dwc2/hcd.c | 6 +++--- drivers/usb/host/ehci-grlib.c | 2 +- drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/ehci-pmcmsp.c | 2 +- drivers/usb/host/ehci-ppc-of.c | 2 +- drivers/usb/host/ehci-ps3.c | 2 +- drivers/usb/host/ehci-sh.c | 2 +- drivers/usb/host/ehci-xilinx-of.c | 2 +- drivers/usb/host/fhci-hcd.c | 2 +- drivers/usb/host/fotg210-hcd.c | 2 +- drivers/usb/host/imx21-hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 6 ------ drivers/usb/host/isp1362-hcd.c | 5 ----- drivers/usb/host/ohci-hcd.c | 2 +- drivers/usb/host/ohci-ppc-of.c | 2 +- drivers/usb/host/ohci-ps3.c | 2 +- drivers/usb/host/ohci-sa1111.c | 2 +- drivers/usb/host/ohci-sm501.c | 2 +- drivers/usb/host/ohci-tmio.c | 2 +- drivers/usb/host/oxu210hp-hcd.c | 3 --- drivers/usb/host/r8a66597-hcd.c | 6 ------ drivers/usb/host/sl811-hcd.c | 6 ------ drivers/usb/host/u132-hcd.c | 2 -- drivers/usb/host/uhci-grlib.c | 2 +- drivers/usb/host/uhci-pci.c | 2 +- drivers/usb/host/uhci-platform.c | 2 +- drivers/usb/host/xhci.c | 2 +- drivers/usb/isp1760/isp1760-core.c | 3 --- drivers/usb/isp1760/isp1760-if.c | 1 - drivers/usb/musb/musb_host.c | 2 +- drivers/usb/renesas_usbhs/mod_host.c | 2 +- include/linux/usb.h | 1 - include/linux/usb/hcd.h | 7 +++++-- 35 files changed, 31 insertions(+), 62 deletions(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index cd2b777073c4..a5321cc692c5 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -3512,7 +3512,7 @@ static const struct hc_driver octeon_hc_driver = { .product_desc = "Octeon Host Controller", .hcd_priv_size = sizeof(struct octeon_hcd), .irq = octeon_usb_irq, - .flags = HCD_MEMORY | HCD_USB2, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, .start = octeon_usb_start, .stop = octeon_usb_stop, .urb_enqueue = octeon_usb_urb_enqueue, diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8592c0344fe8..add2af4af766 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2454,7 +2454,6 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, hcd->self.controller = dev; hcd->self.sysdev = sysdev; hcd->self.bus_name = bus_name; - hcd->self.uses_dma = (sysdev->dma_mask != NULL); timer_setup(&hcd->rh_timer, rh_timer_func, 0); #ifdef CONFIG_PM diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 111787a137ee..81afe553aa66 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -5062,13 +5062,13 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) dwc2_hc_driver.reset_device = dwc2_reset_device; } + if (hsotg->params.host_dma) + dwc2_hc_driver.flags |= HCD_DMA; + hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); if (!hcd) goto error1; - if (!hsotg->params.host_dma) - hcd->self.uses_dma = 0; - hcd->has_tt = 1; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 656b8c08efc8..a2c3b4ec8a8b 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -30,7 +30,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9da7e22848c9..cf2b7ae93b7e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1193,7 +1193,7 @@ static const struct hc_driver ehci_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 46e160370d6e..a2b610dbedfc 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -250,7 +250,7 @@ static const struct hc_driver ehci_msp_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 576f7d79ad4e..6bbaee74f7e7 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -31,7 +31,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 454d8c624a3f..fb52133c3557 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -59,7 +59,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { .product_desc = "PS3 EHCI Host Controller", .hcd_priv_size = sizeof(struct ehci_hcd), .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, .reset = ps3_ehci_hc_reset, .start = ehci_run, .stop = ehci_stop, diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index ef75b9d70eb4..2afde14dc425 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -33,7 +33,7 @@ static const struct hc_driver ehci_sh_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY | HCD_BH, + .flags = HCD_USB2 | HCD_DMA | HCD_MEMORY | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index d2a27578e440..67a6ee8cb5d8 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -66,7 +66,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH, /* * basic lifecycle operations diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 48fe9e6c2465..04733876c9c6 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -538,7 +538,7 @@ static const struct hc_driver fhci_driver = { /* generic hardware linkage */ .irq = fhci_irq, - .flags = HCD_USB11 | HCD_MEMORY, + .flags = HCD_DMA | HCD_USB11 | HCD_MEMORY, /* basic lifecycle operation */ .start = fhci_start, diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 0dbfa5c10703..9e0c98d6bdb0 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -5508,7 +5508,7 @@ static const struct hc_driver fotg210_fotg210_hc_driver = { * generic hardware linkage */ .irq = fotg210_irq, - .flags = HCD_MEMORY | HCD_USB2, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index e406c5459a97..5835f9966204 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1771,7 +1771,7 @@ static const struct hc_driver imx21_hc_driver = { .product_desc = "IMX21 USB Host Controller", .hcd_priv_size = sizeof(struct imx21), - .flags = HCD_USB11, + .flags = HCD_DMA | HCD_USB11, .irq = imx21_irq, .reset = imx21_hc_reset, diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 74da136d322a..a87c0b26279e 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1581,12 +1581,6 @@ static int isp116x_probe(struct platform_device *pdev) irq = ires->start; irqflags = ires->flags & IRQF_TRIGGER_MASK; - if (pdev->dev.dma_mask) { - DBG("DMA not supported\n"); - ret = -EINVAL; - goto err1; - } - if (!request_mem_region(addr->start, 2, hcd_name)) { ret = -EBUSY; goto err1; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 28bf8bfb091e..96f8daa11f25 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2645,11 +2645,6 @@ static int isp1362_probe(struct platform_device *pdev) if (pdev->num_resources < 3) return -ENODEV; - if (pdev->dev.dma_mask) { - DBG(1, "won't do DMA"); - return -ENODEV; - } - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) return -ENODEV; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b457fdaff297..1eb8d17e19db 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1178,7 +1178,7 @@ static const struct hc_driver ohci_hc_driver = { * generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, /* * basic lifecycle operations diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 76a9b40b08f1..45f7cceb6df3 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -50,7 +50,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { * generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, + .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 395f9d3bc849..f77cd6af0ccf 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -46,7 +46,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { .product_desc = "PS3 OHCI Host Controller", .hcd_priv_size = sizeof(struct ohci_hcd), .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, .reset = ps3_ohci_hc_reset, .start = ps3_ohci_hc_start, .stop = ohci_stop, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index ebec9a7699e3..8e19a5eb5b62 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -84,7 +84,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { * generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, + .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index c158cda9e4b9..0b2aea6e28d4 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -49,7 +49,7 @@ static const struct hc_driver ohci_sm501_hc_driver = { * generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, + .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index fb6f5e9ae5c6..221593d75556 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -156,7 +156,7 @@ static const struct hc_driver ohci_tmio_hc_driver = { /* generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, + .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, /* basic lifecycle operations */ .start = ohci_tmio_start, diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 09cc19df798e..e67242e437ed 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -3088,9 +3088,6 @@ static int oxu_reset(struct usb_hcd *hcd) INIT_LIST_HEAD(&oxu->urb_list); oxu->urb_len = 0; - /* FIMXE */ - hcd->self.controller->dma_mask = NULL; - if (oxu->is_otg) { oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; oxu->regs = hcd->regs + OXU_OTG_CAP_OFFSET + \ diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 42668aeca57c..0c03ac6b0213 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2411,12 +2411,6 @@ static int r8a66597_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; - if (pdev->dev.dma_mask) { - ret = -EINVAL; - dev_err(&pdev->dev, "dma not supported\n"); - goto clean_up; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 5b061e599948..72a34a1eb618 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1632,12 +1632,6 @@ sl811h_probe(struct platform_device *dev) irq = ires->start; irqflags = ires->flags & IRQF_TRIGGER_MASK; - /* refuse to confuse usbcore */ - if (dev->dev.dma_mask) { - dev_dbg(&dev->dev, "no we won't dma\n"); - return -EINVAL; - } - /* the chip may be wired for either kind of addressing */ addr = platform_get_resource(dev, IORESOURCE_MEM, 0); data = platform_get_resource(dev, IORESOURCE_MEM, 1); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 400c40bc43a6..4efee34f154f 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3077,8 +3077,6 @@ static int u132_probe(struct platform_device *pdev) retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); if (retval) return retval; - if (pdev->dev.dma_mask) - return -EINVAL; hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index 2103b1ed0f8f..0a201a73b196 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c @@ -63,7 +63,7 @@ static const struct hc_driver uhci_grlib_hc_driver = { /* Generic hardware linkage */ .irq = uhci_irq, - .flags = HCD_MEMORY | HCD_USB11, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, /* Basic lifecycle operations */ .reset = uhci_grlib_init, diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 0dd944277c99..0fa3d72bae26 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c @@ -261,7 +261,7 @@ static const struct hc_driver uhci_driver = { /* Generic hardware linkage */ .irq = uhci_irq, - .flags = HCD_USB11, + .flags = HCD_DMA | HCD_USB11, /* Basic lifecycle operations */ .reset = uhci_pci_init, diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index 89700e26fb29..70dbd95c3f06 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -41,7 +41,7 @@ static const struct hc_driver uhci_platform_hc_driver = { /* Generic hardware linkage */ .irq = uhci_irq, - .flags = HCD_MEMORY | HCD_USB11, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, /* Basic lifecycle operations */ .reset = uhci_platform_init, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 03d1e552769b..e315c0158e90 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -5217,7 +5217,7 @@ static const struct hc_driver xhci_hc_driver = { * generic hardware linkage */ .irq = xhci_irq, - .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, + .flags = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED, /* * basic lifecycle operations diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c index 55b94fd10331..fdeb4cf97cc5 100644 --- a/drivers/usb/isp1760/isp1760-core.c +++ b/drivers/usb/isp1760/isp1760-core.c @@ -120,9 +120,6 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled)) return -ENODEV; - /* prevent usb-core allocating DMA pages */ - dev->dma_mask = NULL; - isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); if (!isp) return -ENOMEM; diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 241a00d75027..07cc82ff327c 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -139,7 +139,6 @@ static int isp1761_pci_probe(struct pci_dev *dev, pci_set_master(dev); - dev->dev.dma_mask = NULL; ret = isp1760_register(&dev->resource[3], dev->irq, 0, &dev->dev, devflags); if (ret < 0) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index eb308ec35c66..5a44b70372d9 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2689,7 +2689,7 @@ static const struct hc_driver musb_hc_driver = { .description = "musb-hcd", .product_desc = "MUSB HDRC host driver", .hcd_priv_size = sizeof(struct musb *), - .flags = HCD_USB2 | HCD_MEMORY, + .flags = HCD_USB2 | HCD_DMA | HCD_MEMORY, /* not using irq handler or reset hooks from usbcore, since * those must be shared with peripheral code for OTG configs diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index ddd3be48f948..ae54221011c3 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1283,7 +1283,7 @@ static const struct hc_driver usbhsh_driver = { /* * generic hardware linkage */ - .flags = HCD_USB2, + .flags = HCD_DMA | HCD_USB2, .start = usbhsh_host_start, .stop = usbhsh_host_stop, diff --git a/include/linux/usb.h b/include/linux/usb.h index b548c530f988..e656e7b4b1e4 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -426,7 +426,6 @@ struct usb_bus { struct device *sysdev; /* as seen from firmware or bus */ int busnum; /* Bus number (in order of reg) */ const char *bus_name; /* stable id (PCI slot_name etc) */ - u8 uses_dma; /* Does the host controller use DMA? */ u8 uses_pio_for_control; /* * Does the host controller use PIO * for control transfers? diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index a20e7815d814..8d3869c7de85 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -256,6 +256,7 @@ struct hc_driver { int flags; #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ +#define HCD_DMA 0x0002 /* HC uses DMA */ #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ #define HCD_USB11 0x0010 /* USB 1.1 */ #define HCD_USB2 0x0020 /* USB 2.0 */ @@ -422,8 +423,10 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd, return hcd->high_prio_bh.completing_ep == ep; } -#define hcd_uses_dma(hcd) \ - (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma) +static inline bool hcd_uses_dma(struct usb_hcd *hcd) +{ + return IS_ENABLED(CONFIG_HAS_DMA) && (hcd->driver->flags & HCD_DMA); +} extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, -- GitLab From 5d6ff300f0114e64f4ad911d256ac1587204ac5d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 16 Aug 2019 08:24:33 +0200 Subject: [PATCH 3888/7155] usb/max3421: remove the dummy {un,}map_urb_for_dma methods Now that we have an explicit HCD_DMA flag, there is not need to override these methods. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20190816062435.881-5-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/max3421-hcd.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index afa321ab55fc..8819f502b6a6 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1800,21 +1800,6 @@ max3421_bus_resume(struct usb_hcd *hcd) return -1; } -/* - * The SPI driver already takes care of DMA-mapping/unmapping, so no - * reason to do it twice. - */ -static int -max3421_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) -{ - return 0; -} - -static void -max3421_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) -{ -} - static const struct hc_driver max3421_hcd_desc = { .description = "max3421", .product_desc = DRIVER_DESC, @@ -1826,8 +1811,6 @@ static const struct hc_driver max3421_hcd_desc = { .get_frame_number = max3421_get_frame_number, .urb_enqueue = max3421_urb_enqueue, .urb_dequeue = max3421_urb_dequeue, - .map_urb_for_dma = max3421_map_urb_for_dma, - .unmap_urb_for_dma = max3421_unmap_urb_for_dma, .endpoint_disable = max3421_endpoint_disable, .hub_status_data = max3421_hub_status_data, .hub_control = max3421_hub_control, -- GitLab From bd5defaee872da9b81e3c72045eb6794445cd2e6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 16 Aug 2019 08:24:34 +0200 Subject: [PATCH 3889/7155] dma-mapping: remove is_device_dma_capable No users left. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20190816062435.881-6-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- include/linux/dma-mapping.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index f7d1eea32c78..14702e2d6fa8 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -149,11 +149,6 @@ static inline int valid_dma_direction(int dma_direction) (dma_direction == DMA_FROM_DEVICE)); } -static inline int is_device_dma_capable(struct device *dev) -{ - return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE; -} - #ifdef CONFIG_DMA_DECLARE_COHERENT /* * These three functions are only for dma allocator. -- GitLab From 5cbd22c179012114099fe3996999b54fd2a092c5 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 21 Aug 2019 00:08:57 +0100 Subject: [PATCH 3890/7155] bpf: clarify description for CONFIG_BPF_EVENTS PERF_EVENT_IOC_SET_BPF supports uprobes since v4.3, and tracepoints since v4.7 via commit 04a22fae4cbc ("tracing, perf: Implement BPF programs attached to uprobes"), and commit 98b5c2c65c29 ("perf, bpf: allow bpf programs attach to tracepoints") respectively. Signed-off-by: Peter Wu Signed-off-by: Alexei Starovoitov --- kernel/trace/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 98da8998c25c..b09d7b1ffffd 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -520,7 +520,8 @@ config BPF_EVENTS bool default y help - This allows the user to attach BPF programs to kprobe events. + This allows the user to attach BPF programs to kprobe, uprobe, and + tracepoint events. config DYNAMIC_EVENTS def_bool n -- GitLab From 8050a395112db5bedb7caa6cb673e711a3c04cd9 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 21 Aug 2019 00:08:58 +0100 Subject: [PATCH 3891/7155] bpf: fix 'struct pt_reg' typo in documentation There is no 'struct pt_reg'. Signed-off-by: Peter Wu Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- include/uapi/linux/bpf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 8aa6126f0b6e..267544e140be 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1018,7 +1018,7 @@ union bpf_attr { * The realm of the route for the packet associated to *skb*, or 0 * if none was found. * - * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) + * int bpf_perf_event_output(struct pt_regs *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) * Description * Write raw *data* blob into a special BPF perf event held by * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf @@ -1080,7 +1080,7 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. * - * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) + * int bpf_get_stackid(struct pt_regs *ctx, struct bpf_map *map, u64 flags) * Description * Walk a user or a kernel stack and return its id. To achieve * this, the helper needs *ctx*, which is a pointer to the context @@ -1729,7 +1729,7 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. * - * int bpf_override_return(struct pt_reg *regs, u64 rc) + * int bpf_override_return(struct pt_regs *regs, u64 rc) * Description * Used for error injection, this helper uses kprobes to override * the return value of the probed function, and to set it to *rc*. -- GitLab From 55c33dfbeb831eb3ab7cc1a3e295b0d4d57f23a3 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 21 Aug 2019 00:08:59 +0100 Subject: [PATCH 3892/7155] bpf: clarify when bpf_trace_printk discards lines I opened /sys/kernel/tracing/trace once and kept reading from it. bpf_trace_printk somehow did not seem to work, no entries were appended to that trace file. It turns out that tracing is disabled when that file is open. Save the next person some time and document this. The trace file is described in Documentation/trace/ftrace.rst, however the implication "tracing is disabled" did not immediate translate to "bpf_trace_printk silently discards entries". Signed-off-by: Peter Wu Signed-off-by: Alexei Starovoitov --- include/uapi/linux/bpf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 267544e140be..b5889257cc33 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -580,6 +580,8 @@ union bpf_attr { * limited to five). * * Each time the helper is called, it appends a line to the trace. + * Lines are discarded while *\/sys/kernel/debug/tracing/trace* is + * open, use *\/sys/kernel/debug/tracing/trace_pipe* to avoid this. * The format of the trace is customizable, and the exact output * one will get depends on the options set in * *\/sys/kernel/debug/tracing/trace_options* (see also the -- GitLab From 1f8919b170318e7e13e303eedac363d44057995f Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 21 Aug 2019 00:09:00 +0100 Subject: [PATCH 3893/7155] bpf: sync bpf.h to tools/ Fix a 'struct pt_reg' typo and clarify when bpf_trace_printk discards lines. Affects documentation only. Signed-off-by: Peter Wu Signed-off-by: Alexei Starovoitov --- tools/include/uapi/linux/bpf.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 8aa6126f0b6e..b5889257cc33 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -580,6 +580,8 @@ union bpf_attr { * limited to five). * * Each time the helper is called, it appends a line to the trace. + * Lines are discarded while *\/sys/kernel/debug/tracing/trace* is + * open, use *\/sys/kernel/debug/tracing/trace_pipe* to avoid this. * The format of the trace is customizable, and the exact output * one will get depends on the options set in * *\/sys/kernel/debug/tracing/trace_options* (see also the @@ -1018,7 +1020,7 @@ union bpf_attr { * The realm of the route for the packet associated to *skb*, or 0 * if none was found. * - * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) + * int bpf_perf_event_output(struct pt_regs *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) * Description * Write raw *data* blob into a special BPF perf event held by * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf @@ -1080,7 +1082,7 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. * - * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) + * int bpf_get_stackid(struct pt_regs *ctx, struct bpf_map *map, u64 flags) * Description * Walk a user or a kernel stack and return its id. To achieve * this, the helper needs *ctx*, which is a pointer to the context @@ -1729,7 +1731,7 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. * - * int bpf_override_return(struct pt_reg *regs, u64 rc) + * int bpf_override_return(struct pt_regs *regs, u64 rc) * Description * Used for error injection, this helper uses kprobes to override * the return value of the probed function, and to set it to *rc*. -- GitLab From 2671828c3ff4ffadf777f793a1f3232d6e51394a Mon Sep 17 00:00:00 2001 From: James Morse Date: Tue, 20 Aug 2019 18:45:57 +0100 Subject: [PATCH 3894/7155] arm64: entry: Move ct_user_exit before any other exception When taking an SError or Debug exception from EL0, we run the C handler for these exceptions before updating the context tracking code and unmasking lower priority interrupts. When booting with nohz_full lockdep tells us we got this wrong: | ============================= | WARNING: suspicious RCU usage | 5.3.0-rc2-00010-gb4b5e9dcb11b-dirty #11271 Not tainted | ----------------------------- | include/linux/rcupdate.h:643 rcu_read_unlock() used illegally wh! | | other info that might help us debug this: | | | RCU used illegally from idle CPU! | rcu_scheduler_active = 2, debug_locks = 1 | RCU used illegally from extended quiescent state! | 1 lock held by a.out/432: | #0: 00000000c7a79515 (rcu_read_lock){....}, at: brk_handler+0x00 | | stack backtrace: | CPU: 1 PID: 432 Comm: a.out Not tainted 5.3.0-rc2-00010-gb4b5e9d1 | Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno De8 | Call trace: | dump_backtrace+0x0/0x140 | show_stack+0x14/0x20 | dump_stack+0xbc/0x104 | lockdep_rcu_suspicious+0xf8/0x108 | brk_handler+0x164/0x1b0 | do_debug_exception+0x11c/0x278 | el0_dbg+0x14/0x20 Moving the ct_user_exit calls to be before do_debug_exception() means they are also before trace_hardirqs_off() has been updated. Add a new ct_user_exit_irqoff macro to avoid the context-tracking code using irqsave/restore before we've updated trace_hardirqs_off(). To be consistent, do this everywhere. The C helper is called enter_from_user_mode() to match x86 in the hope we can merge them into kernel/context_tracking.c later. Cc: Masami Hiramatsu Fixes: 6c81fe7925cc4c42 ("arm64: enable context tracking") Signed-off-by: James Morse Signed-off-by: Will Deacon --- arch/arm64/include/asm/exception.h | 2 ++ arch/arm64/kernel/entry.S | 36 ++++++++++++++++-------------- arch/arm64/kernel/traps.c | 9 ++++++++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index ed57b760f38c..a17393ff6677 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -30,4 +30,6 @@ static inline u32 disr_to_esr(u64 disr) return esr; } +asmlinkage void enter_from_user_mode(void); + #endif /* __ASM_EXCEPTION_H */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 320a30dbe35e..84a822748c84 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -30,9 +30,9 @@ * Context tracking subsystem. Used to instrument transitions * between user and kernel mode. */ - .macro ct_user_exit + .macro ct_user_exit_irqoff #ifdef CONFIG_CONTEXT_TRACKING - bl context_tracking_user_exit + bl enter_from_user_mode #endif .endm @@ -792,8 +792,8 @@ el0_cp15: /* * Trapped CP15 (MRC, MCR, MRRC, MCRR) instructions */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, x25 mov x1, sp bl do_cp15instr @@ -805,8 +805,8 @@ el0_da: * Data abort handling */ mrs x26, far_el1 + ct_user_exit_irqoff enable_daif - ct_user_exit clear_address_tag x0, x26 mov x1, x25 mov x2, sp @@ -818,11 +818,11 @@ el0_ia: */ mrs x26, far_el1 gic_prio_kentry_setup tmp=x0 + ct_user_exit_irqoff enable_da_f #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif - ct_user_exit mov x0, x26 mov x1, x25 mov x2, sp @@ -832,8 +832,8 @@ el0_fpsimd_acc: /* * Floating Point or Advanced SIMD access */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, x25 mov x1, sp bl do_fpsimd_acc @@ -842,8 +842,8 @@ el0_sve_acc: /* * Scalable Vector Extension access */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, x25 mov x1, sp bl do_sve_acc @@ -852,8 +852,8 @@ el0_fpsimd_exc: /* * Floating Point, Advanced SIMD or SVE exception */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, x25 mov x1, sp bl do_fpsimd_exc @@ -868,11 +868,11 @@ el0_sp_pc: * Stack or PC alignment exception handling */ gic_prio_kentry_setup tmp=x0 + ct_user_exit_irqoff enable_da_f #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif - ct_user_exit mov x0, x26 mov x1, x25 mov x2, sp @@ -882,8 +882,8 @@ el0_undef: /* * Undefined instruction */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, sp bl do_undefinstr b ret_to_user @@ -891,8 +891,8 @@ el0_sys: /* * System instructions, for trapped cache maintenance instructions */ + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, x25 mov x1, sp bl do_sysinstr @@ -902,17 +902,18 @@ el0_dbg: * Debug exception handling */ tbnz x24, #0, el0_inv // EL0 only + mrs x24, far_el1 gic_prio_kentry_setup tmp=x3 - mrs x0, far_el1 + ct_user_exit_irqoff + mov x0, x24 mov x1, x25 mov x2, sp bl do_debug_exception enable_da_f - ct_user_exit b ret_to_user el0_inv: + ct_user_exit_irqoff enable_daif - ct_user_exit mov x0, sp mov x1, #BAD_SYNC mov x2, x25 @@ -925,13 +926,13 @@ el0_irq: kernel_entry 0 el0_irq_naked: gic_prio_irq_setup pmr=x20, tmp=x0 + ct_user_exit_irqoff enable_da_f #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif - ct_user_exit #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR tbz x22, #55, 1f bl do_el0_irq_bp_hardening @@ -958,13 +959,14 @@ ENDPROC(el1_error) el0_error: kernel_entry 0 el0_error_naked: - mrs x1, esr_el1 + mrs x25, esr_el1 gic_prio_kentry_setup tmp=x2 + ct_user_exit_irqoff enable_dbg mov x0, sp + mov x1, x25 bl do_serror enable_da_f - ct_user_exit b ret_to_user ENDPROC(el0_error) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index a5d7ce4297b0..6e950908eb97 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -7,9 +7,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -900,6 +902,13 @@ asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr) nmi_exit(); } +asmlinkage void enter_from_user_mode(void) +{ + CT_WARN_ON(ct_state() != CONTEXT_USER); + user_exit_irqoff(); +} +NOKPROBE_SYMBOL(enter_from_user_mode); + void __pte_error(const char *file, int line, unsigned long val) { pr_err("%s:%d: bad pte %016lx.\n", file, line, val); -- GitLab From 6bfa3134bd3a185e98031c8a8dee18e82153df2d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 21 Aug 2019 18:11:17 +0900 Subject: [PATCH 3895/7155] arm64: add arch/arm64/Kbuild Use the standard obj-y form to specify the sub-directories under arch/arm64/. No functional change intended. Signed-off-by: Masahiro Yamada Signed-off-by: Will Deacon --- arch/arm64/Kbuild | 6 ++++++ arch/arm64/Makefile | 6 +----- 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 arch/arm64/Kbuild diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild new file mode 100644 index 000000000000..d6465823b281 --- /dev/null +++ b/arch/arm64/Kbuild @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += kernel/ mm/ +obj-$(CONFIG_NET) += net/ +obj-$(CONFIG_KVM) += kvm/ +obj-$(CONFIG_XEN) += xen/ +obj-$(CONFIG_CRYPTO) += crypto/ diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 61de992bbea3..dcbbd53b7f5a 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -136,11 +136,7 @@ KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \ export TEXT_OFFSET GZFLAGS -core-y += arch/arm64/kernel/ arch/arm64/mm/ -core-$(CONFIG_NET) += arch/arm64/net/ -core-$(CONFIG_KVM) += arch/arm64/kvm/ -core-$(CONFIG_XEN) += arch/arm64/xen/ -core-$(CONFIG_CRYPTO) += arch/arm64/crypto/ +core-y += arch/arm64/ libs-y := arch/arm64/lib/ $(libs-y) core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a -- GitLab From b4d08173bfef9b138e55022f5a3eb90c6246e7e9 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 21 Aug 2019 13:50:35 +0100 Subject: [PATCH 3896/7155] arm64: sdm845: add adsp and cdsp fastrpc nodes Add fastrpc compute context bank nodes to both cdsp and adsp. Signed-off-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index e285cbd8211c..0bfae6c046b2 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -491,6 +491,25 @@ label = "lpass"; qcom,remote-pid = <2>; mboxes = <&apss_shared 8>; + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x1823 0x0>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x1824 0x0>; + }; + }; }; }; @@ -520,6 +539,61 @@ label = "turing"; qcom,remote-pid = <5>; mboxes = <&apss_shared 4>; + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x1401 0x30>; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x1402 0x30>; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x1403 0x30>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x1404 0x30>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x1405 0x30>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x1406 0x30>; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x1407 0x30>; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu 0x1408 0x30>; + }; + }; }; }; -- GitLab From d1dec5ca5fb87d64d1e7405bd6006728915ea5c6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 20 Aug 2019 00:56:02 +0900 Subject: [PATCH 3897/7155] ARM: s3c64xx: squash samsung_usb_phy.h into setup-usb-phy.c This is only used by arch/arm/mach-s3c64xx/setup-usb-phy.c $ git grep samsung_usb_phy_type include/linux/usb/samsung_usb_phy.h:enum samsung_usb_phy_type { $ git grep USB_PHY_TYPE_DEVICE arch/arm/mach-s3c64xx/setup-usb-phy.c: if (type == USB_PHY_TYPE_DEVICE) arch/arm/mach-s3c64xx/setup-usb-phy.c: if (type == USB_PHY_TYPE_DEVICE) include/linux/usb/samsung_usb_phy.h: USB_PHY_TYPE_DEVICE, $ git grep USB_PHY_TYPE_HOST include/linux/usb/samsung_usb_phy.h: USB_PHY_TYPE_HOST, Actually, 'enum samsung_usb_phy_type' is unused; the 'type' parameter has 'int' type. Anyway, there is no need to declare this enum in the globally visible header. Squash the header. Signed-off-by: Masahiro Yamada Signed-off-by: Krzysztof Kozlowski --- arch/arm/mach-s3c64xx/setup-usb-phy.c | 5 +++++ arch/arm/plat-samsung/include/plat/usb-phy.h | 2 -- include/linux/usb/samsung_usb_phy.h | 17 ----------------- 3 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 include/linux/usb/samsung_usb_phy.h diff --git a/arch/arm/mach-s3c64xx/setup-usb-phy.c b/arch/arm/mach-s3c64xx/setup-usb-phy.c index 46a9e955607f..6aaaa1d8e8b9 100644 --- a/arch/arm/mach-s3c64xx/setup-usb-phy.c +++ b/arch/arm/mach-s3c64xx/setup-usb-phy.c @@ -15,6 +15,11 @@ #include "regs-sys.h" #include "regs-usb-hsotg-phy.h" +enum samsung_usb_phy_type { + USB_PHY_TYPE_DEVICE, + USB_PHY_TYPE_HOST, +}; + static int s3c_usb_otgphy_init(struct platform_device *pdev) { struct clk *xusbxti; diff --git a/arch/arm/plat-samsung/include/plat/usb-phy.h b/arch/arm/plat-samsung/include/plat/usb-phy.h index 6d0c788beb9d..94da89ecbd3b 100644 --- a/arch/arm/plat-samsung/include/plat/usb-phy.h +++ b/arch/arm/plat-samsung/include/plat/usb-phy.h @@ -7,8 +7,6 @@ #ifndef __PLAT_SAMSUNG_USB_PHY_H #define __PLAT_SAMSUNG_USB_PHY_H __FILE__ -#include - extern int s5p_usb_phy_init(struct platform_device *pdev, int type); extern int s5p_usb_phy_exit(struct platform_device *pdev, int type); diff --git a/include/linux/usb/samsung_usb_phy.h b/include/linux/usb/samsung_usb_phy.h deleted file mode 100644 index dc0071741695..000000000000 --- a/include/linux/usb/samsung_usb_phy.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * http://www.samsung.com/ - * - * Defines phy types for samsung usb phy controllers - HOST or DEIVCE. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -enum samsung_usb_phy_type { - USB_PHY_TYPE_DEVICE, - USB_PHY_TYPE_HOST, -}; -- GitLab From 692117c1f7a6770ed41dd8f277cd9fed1dfb16f1 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 19 Aug 2019 16:31:46 +0200 Subject: [PATCH 3898/7155] posix-cpu-timers: Sanitize bogus WARNONS Warning when p == NULL and then proceeding and dereferencing p does not make any sense as the kernel will crash with a NULL pointer dereference right away. Bailing out when p == NULL and returning an error code does not cure the underlying problem which caused p to be NULL. Though it might allow to do proper debugging. Same applies to the clock id check in set_process_cpu_timer(). Clean them up and make them return without trying to do further damage. Signed-off-by: Thomas Gleixner Reviewed-by: Frederic Weisbecker Link: https://lkml.kernel.org/r/20190819143801.846497772@linutronix.de --- kernel/time/posix-cpu-timers.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 742d4a4e6f71..98223d2805c2 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -375,7 +375,8 @@ static int posix_cpu_timer_del(struct k_itimer *timer) struct sighand_struct *sighand; struct task_struct *p = timer->it.cpu.task; - WARN_ON_ONCE(p == NULL); + if (WARN_ON_ONCE(!p)) + return -EINVAL; /* * Protect against sighand release/switch in exit/exec and process/ @@ -581,7 +582,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, u64 old_expires, new_expires, old_incr, val; int ret; - WARN_ON_ONCE(p == NULL); + if (WARN_ON_ONCE(!p)) + return -EINVAL; /* * Use the to_ktime conversion because that clamps the maximum @@ -716,10 +718,11 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp) { - u64 now; struct task_struct *p = timer->it.cpu.task; + u64 now; - WARN_ON_ONCE(p == NULL); + if (WARN_ON_ONCE(!p)) + return; /* * Easy part: convert the reload time. @@ -1001,12 +1004,13 @@ static void check_process_timers(struct task_struct *tsk, */ static void posix_cpu_timer_rearm(struct k_itimer *timer) { + struct task_struct *p = timer->it.cpu.task; struct sighand_struct *sighand; unsigned long flags; - struct task_struct *p = timer->it.cpu.task; u64 now; - WARN_ON_ONCE(p == NULL); + if (WARN_ON_ONCE(!p)) + return; /* * Fetch the current sample and update the timer's expiry time. @@ -1203,7 +1207,9 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, u64 now; int ret; - WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); + if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED)) + return; + ret = cpu_timer_sample_group(clock_idx, tsk, &now); if (oldval && ret != -EINVAL) { -- GitLab From dce3e8fd039cc1b62760b3ad6822cf04c262cd0e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 19 Aug 2019 16:31:47 +0200 Subject: [PATCH 3899/7155] posix-cpu-timers: Remove tsk argument from run_posix_cpu_timers() It's always current. Don't give people wrong ideas. Signed-off-by: Thomas Gleixner Reviewed-by: Frederic Weisbecker Link: https://lkml.kernel.org/r/20190819143801.945469967@linutronix.de --- include/linux/posix-timers.h | 2 +- kernel/time/posix-cpu-timers.c | 5 +++-- kernel/time/timer.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 26c636d1485b..033374b99767 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -118,7 +118,7 @@ struct k_itimer { struct rcu_head rcu; }; -void run_posix_cpu_timers(struct task_struct *task); +void run_posix_cpu_timers(void); void posix_cpu_timers_exit(struct task_struct *task); void posix_cpu_timers_exit_group(struct task_struct *task); void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 98223d2805c2..387e0e86e1b8 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1137,11 +1137,12 @@ static inline int fastpath_timer_check(struct task_struct *tsk) * already updated our counts. We need to check if any timers fire now. * Interrupts are disabled. */ -void run_posix_cpu_timers(struct task_struct *tsk) +void run_posix_cpu_timers(void) { - LIST_HEAD(firing); + struct task_struct *tsk = current; struct k_itimer *timer, *next; unsigned long flags; + LIST_HEAD(firing); lockdep_assert_irqs_disabled(); diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 673c6a0f0c45..0e315a2e77ae 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1728,7 +1728,7 @@ void update_process_times(int user_tick) #endif scheduler_tick(); if (IS_ENABLED(CONFIG_POSIX_TIMERS)) - run_posix_cpu_timers(p); + run_posix_cpu_timers(); } /** -- GitLab From c354ff2ef233a694d657b03a499c3c3fddbec599 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Wed, 21 Aug 2019 09:52:18 +0100 Subject: [PATCH 3900/7155] tools: bpftool: show frozen status for maps When listing maps, read their "frozen" status from procfs, and tell if maps are frozen. As commit log for map freezing command mentions that the feature might be extended with flags (e.g. for write-only instead of read-only) in the future, use an integer and not a boolean for JSON output. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/map.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index bfbbc6b4cb83..af2e9eb9747b 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -481,9 +481,11 @@ static int parse_elem(char **argv, struct bpf_map_info *info, static int show_map_close_json(int fd, struct bpf_map_info *info) { - char *memlock; + char *memlock, *frozen_str; + int frozen = 0; memlock = get_fdinfo(fd, "memlock"); + frozen_str = get_fdinfo(fd, "frozen"); jsonw_start_object(json_wtr); @@ -533,6 +535,12 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) } close(fd); + if (frozen_str) { + frozen = atoi(frozen_str); + free(frozen_str); + } + jsonw_int_field(json_wtr, "frozen", frozen); + if (info->btf_id) jsonw_int_field(json_wtr, "btf_id", info->btf_id); @@ -555,9 +563,11 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) static int show_map_close_plain(int fd, struct bpf_map_info *info) { - char *memlock; + char *memlock, *frozen_str; + int frozen = 0; memlock = get_fdinfo(fd, "memlock"); + frozen_str = get_fdinfo(fd, "frozen"); printf("%u: ", info->id); if (info->type < ARRAY_SIZE(map_type_name)) @@ -610,9 +620,23 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) printf("\n\tpinned %s", obj->path); } } + printf("\n"); + + if (frozen_str) { + frozen = atoi(frozen_str); + free(frozen_str); + } + + if (!info->btf_id && !frozen) + return 0; + + printf("\t"); if (info->btf_id) - printf("\n\tbtf_id %d", info->btf_id); + printf("btf_id %d", info->btf_id); + + if (frozen) + printf("%sfrozen", info->btf_id ? " " : ""); printf("\n"); return 0; -- GitLab From 0bb52b0dfc88a155688f492aba8e686147600278 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Wed, 21 Aug 2019 09:52:19 +0100 Subject: [PATCH 3901/7155] tools: bpftool: add "bpftool map freeze" subcommand Add a new subcommand to freeze maps from user space. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- .../bpf/bpftool/Documentation/bpftool-map.rst | 9 +++++ tools/bpf/bpftool/bash-completion/bpftool | 4 +-- tools/bpf/bpftool/map.c | 34 ++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 61d1d270eb5e..1c0f7146aab0 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -36,6 +36,7 @@ MAP COMMANDS | **bpftool** **map pop** *MAP* | **bpftool** **map enqueue** *MAP* **value** *VALUE* | **bpftool** **map dequeue** *MAP* +| **bpftool** **map freeze** *MAP* | **bpftool** **map help** | | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } @@ -127,6 +128,14 @@ DESCRIPTION **bpftool map dequeue** *MAP* Dequeue and print **value** from the queue. + **bpftool map freeze** *MAP* + Freeze the map as read-only from user space. Entries from a + frozen map can not longer be updated or deleted with the + **bpf\ ()** system call. This operation is not reversible, + and the map remains immutable from user space until its + destruction. However, read and write permissions for BPF + programs to the map remain unchanged. + **bpftool map help** Print short help message. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 2ffd351f9dbf..70493a6da206 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -449,7 +449,7 @@ _bpftool() map) local MAP_TYPE='id pinned' case $command in - show|list|dump|peek|pop|dequeue) + show|list|dump|peek|pop|dequeue|freeze) case $prev in $command) COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) @@ -638,7 +638,7 @@ _bpftool() [[ $prev == $object ]] && \ COMPREPLY=( $( compgen -W 'delete dump getnext help \ lookup pin event_pipe show list update create \ - peek push enqueue pop dequeue' -- \ + peek push enqueue pop dequeue freeze' -- \ "$cur" ) ) ;; esac diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index af2e9eb9747b..de61d73b9030 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -1262,6 +1262,35 @@ static int do_pop_dequeue(int argc, char **argv) return err; } +static int do_freeze(int argc, char **argv) +{ + int err, fd; + + if (!REQ_ARGS(2)) + return -1; + + fd = map_parse_fd(&argc, &argv); + if (fd < 0) + return -1; + + if (argc) { + close(fd); + return BAD_ARG(); + } + + err = bpf_map_freeze(fd); + close(fd); + if (err) { + p_err("failed to freeze map: %s", strerror(errno)); + return err; + } + + if (json_output) + jsonw_null(json_wtr); + + return 0; +} + static int do_help(int argc, char **argv) { if (json_output) { @@ -1286,6 +1315,7 @@ static int do_help(int argc, char **argv) " %s %s pop MAP\n" " %s %s enqueue MAP value VALUE\n" " %s %s dequeue MAP\n" + " %s %s freeze MAP\n" " %s %s help\n" "\n" " " HELP_SPEC_MAP "\n" @@ -1304,7 +1334,8 @@ static int do_help(int argc, char **argv) bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], - bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); + bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], + bin_name, argv[-2]); return 0; } @@ -1326,6 +1357,7 @@ static const struct cmd cmds[] = { { "enqueue", do_update }, { "pop", do_pop_dequeue }, { "dequeue", do_pop_dequeue }, + { "freeze", do_freeze }, { 0 } }; -- GitLab From b7bf027087cb81b4673515ea8a0e3850ab2f9055 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:31 +0300 Subject: [PATCH 3902/7155] mlxsw: core: Add API to set trap action Up until now the action of a trap was never changed during its lifetime. This is going to change by subsequent patches that will allow devlink to control the action of certain traps. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 12 ++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 17ceac7505e5..6ec07ecfb5f6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1477,6 +1477,18 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_trap_unregister); +int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + enum mlxsw_reg_hpkt_action action) +{ + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + + mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id, + listener->trap_group, listener->is_ctrl); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); +} +EXPORT_SYMBOL(mlxsw_core_trap_action_set); + static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core) { return atomic64_inc_return(&mlxsw_core->emad.tid); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 8efcff4b59cb..19cea16c30bb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -128,6 +128,9 @@ int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, const struct mlxsw_listener *listener, void *priv); +int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + enum mlxsw_reg_hpkt_action action); typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload, size_t payload_len, unsigned long cb_priv); -- GitLab From 6a44bae3b2b9b03c03712c0460f674efaf684131 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:32 +0300 Subject: [PATCH 3903/7155] mlxsw: reg: Add new trap actions Subsequent patches will add discard traps support in mlxsw. The driver cannot configure such traps with a normal trap action, but needs to use exception trap action, which also increments an error counter. On the other hand, when these traps are initialized or set to drop action, they should use the default drop action set by the firmware. This guarantees that when the feature is disabled we get the exact same behavior as before the feature was introduced. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index ead36702549a..59e296562b5a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5559,6 +5559,8 @@ enum mlxsw_reg_hpkt_action { MLXSW_REG_HPKT_ACTION_DISCARD, MLXSW_REG_HPKT_ACTION_SOFT_DISCARD, MLXSW_REG_HPKT_ACTION_TRAP_AND_SOFT_DISCARD, + MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU, + MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT = 15, }; /* reg_hpkt_action @@ -5569,6 +5571,8 @@ enum mlxsw_reg_hpkt_action { * 3 - Discard. * 4 - Soft discard (allow other traps to act on the packet). * 5 - Trap and soft discard (allow other traps to overwrite this trap). + * 6 - Trap to CPU (CPU receives sole copy) and count it as error. + * 15 - Restore the firmware's default action. * Access: RW * * Note: Must be set to 0 (forward) for event trap IDs, as they are already -- GitLab From a812cedb8e3594833986fe690b0224d5577644ce Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:33 +0300 Subject: [PATCH 3904/7155] mlxsw: Add layer 2 discard trap IDs Add the trap IDs used to report layer 2 drops. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/trap.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index 19202bdb5105..7618f084cae9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -66,6 +66,13 @@ enum { MLXSW_TRAP_ID_NVE_ENCAP_ARP = 0xBD, MLXSW_TRAP_ID_ROUTER_ALERT_IPV4 = 0xD6, MLXSW_TRAP_ID_ROUTER_ALERT_IPV6 = 0xD7, + MLXSW_TRAP_ID_DISCARD_ING_PACKET_SMAC_MC = 0x140, + MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VTAG_ALLOW = 0x148, + MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VLAN = 0x149, + MLXSW_TRAP_ID_DISCARD_ING_SWITCH_STP = 0x14A, + MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_UC = 0x150, + MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_MC_NULL = 0x151, + MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_LB = 0x152, MLXSW_TRAP_ID_ACL0 = 0x1C0, /* Multicast trap used for routes with trap action */ MLXSW_TRAP_ID_ACL1 = 0x1C1, -- GitLab From 9e6290c75a5078d0a8fac89d908dc59db9c27a15 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:34 +0300 Subject: [PATCH 3905/7155] mlxsw: Add trap group for layer 2 discards Discard trap groups are defined in a different enum so that they could all share the same policer ID: MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 59e296562b5a..baa20cdd65df 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5422,6 +5422,14 @@ enum mlxsw_reg_htgt_trap_group { MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR, MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0, MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1, + + __MLXSW_REG_HTGT_TRAP_GROUP_MAX, + MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1 +}; + +enum mlxsw_reg_htgt_discard_trap_group { + MLXSW_REG_HTGT_DISCARD_TRAP_GROUP_BASE = MLXSW_REG_HTGT_TRAP_GROUP_MAX, + MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS, }; /* reg_htgt_trap_group -- GitLab From b5ce611fd96e18711d1b580170676fba9cafe258 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:35 +0300 Subject: [PATCH 3906/7155] mlxsw: spectrum: Add devlink-trap support Register supported packet traps (layer 2 drops only, currently) and associated trap group with devlink during driver initialization. The amount of traffic generated by these packet drop traps is capped at 10Kpps to ensure the CPU is not overwhelmed by incoming packets. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Makefile | 2 +- drivers/net/ethernet/mellanox/mlxsw/core.c | 52 ++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 9 + .../net/ethernet/mellanox/mlxsw/spectrum.c | 21 ++ .../net/ethernet/mellanox/mlxsw/spectrum.h | 13 + .../ethernet/mellanox/mlxsw/spectrum_trap.c | 267 ++++++++++++++++++ 6 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 171b36bd8a4e..0e86a581d45b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -29,7 +29,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_mr_tcam.o spectrum_mr.o \ spectrum_qdisc.o spectrum_span.o \ spectrum_nve.o spectrum_nve_vxlan.o \ - spectrum_dpipe.o + spectrum_dpipe.o spectrum_trap.o mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o mlxsw_spectrum-$(CONFIG_PTP_1588_CLOCK) += spectrum_ptp.o obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 6ec07ecfb5f6..963a2b4b61b1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1017,6 +1017,54 @@ static int mlxsw_devlink_flash_update(struct devlink *devlink, component, extack); } +static int mlxsw_devlink_trap_init(struct devlink *devlink, + const struct devlink_trap *trap, + void *trap_ctx) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->trap_init) + return -EOPNOTSUPP; + return mlxsw_driver->trap_init(mlxsw_core, trap, trap_ctx); +} + +static void mlxsw_devlink_trap_fini(struct devlink *devlink, + const struct devlink_trap *trap, + void *trap_ctx) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->trap_fini) + return; + mlxsw_driver->trap_fini(mlxsw_core, trap, trap_ctx); +} + +static int mlxsw_devlink_trap_action_set(struct devlink *devlink, + const struct devlink_trap *trap, + enum devlink_trap_action action) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->trap_action_set) + return -EOPNOTSUPP; + return mlxsw_driver->trap_action_set(mlxsw_core, trap, action); +} + +static int +mlxsw_devlink_trap_group_init(struct devlink *devlink, + const struct devlink_trap_group *group) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->trap_group_init) + return -EOPNOTSUPP; + return mlxsw_driver->trap_group_init(mlxsw_core, group); +} + static const struct devlink_ops mlxsw_devlink_ops = { .reload = mlxsw_devlink_core_bus_device_reload, .port_type_set = mlxsw_devlink_port_type_set, @@ -1034,6 +1082,10 @@ static const struct devlink_ops mlxsw_devlink_ops = { .sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get, .info_get = mlxsw_devlink_info_get, .flash_update = mlxsw_devlink_flash_update, + .trap_init = mlxsw_devlink_trap_init, + .trap_fini = mlxsw_devlink_trap_fini, + .trap_action_set = mlxsw_devlink_trap_action_set, + .trap_group_init = mlxsw_devlink_trap_group_init, }; static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 19cea16c30bb..b65a17d49e43 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -292,6 +292,15 @@ struct mlxsw_driver { int (*flash_update)(struct mlxsw_core *mlxsw_core, const char *file_name, const char *component, struct netlink_ext_ack *extack); + int (*trap_init)(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx); + void (*trap_fini)(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx); + int (*trap_action_set)(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, + enum devlink_trap_action action); + int (*trap_group_init)(struct mlxsw_core *mlxsw_core, + const struct devlink_trap_group *group); void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); int (*resources_register)(struct mlxsw_core *mlxsw_core); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 389861ece418..7de9833fc60b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4665,6 +4665,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, goto err_traps_init; } + err = mlxsw_sp_devlink_traps_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize devlink traps\n"); + goto err_devlink_traps_init; + } + err = mlxsw_sp_buffers_init(mlxsw_sp); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n"); @@ -4798,6 +4804,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, err_lag_init: mlxsw_sp_buffers_fini(mlxsw_sp); err_buffers_init: + mlxsw_sp_devlink_traps_fini(mlxsw_sp); +err_devlink_traps_init: mlxsw_sp_traps_fini(mlxsw_sp); err_traps_init: mlxsw_sp_fids_fini(mlxsw_sp); @@ -4870,6 +4878,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) mlxsw_sp_span_fini(mlxsw_sp); mlxsw_sp_lag_fini(mlxsw_sp); mlxsw_sp_buffers_fini(mlxsw_sp); + mlxsw_sp_devlink_traps_fini(mlxsw_sp); mlxsw_sp_traps_fini(mlxsw_sp); mlxsw_sp_fids_fini(mlxsw_sp); mlxsw_sp_kvdl_fini(mlxsw_sp); @@ -5251,6 +5260,10 @@ static struct mlxsw_driver mlxsw_sp1_driver = { .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, .flash_update = mlxsw_sp_flash_update, + .trap_init = mlxsw_sp_trap_init, + .trap_fini = mlxsw_sp_trap_fini, + .trap_action_set = mlxsw_sp_trap_action_set, + .trap_group_init = mlxsw_sp_trap_group_init, .txhdr_construct = mlxsw_sp_txhdr_construct, .resources_register = mlxsw_sp1_resources_register, .kvd_sizes_get = mlxsw_sp_kvd_sizes_get, @@ -5281,6 +5294,10 @@ static struct mlxsw_driver mlxsw_sp2_driver = { .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, .flash_update = mlxsw_sp_flash_update, + .trap_init = mlxsw_sp_trap_init, + .trap_fini = mlxsw_sp_trap_fini, + .trap_action_set = mlxsw_sp_trap_action_set, + .trap_group_init = mlxsw_sp_trap_group_init, .txhdr_construct = mlxsw_sp_txhdr_construct, .resources_register = mlxsw_sp2_resources_register, .params_register = mlxsw_sp2_params_register, @@ -5310,6 +5327,10 @@ static struct mlxsw_driver mlxsw_sp3_driver = { .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, .flash_update = mlxsw_sp_flash_update, + .trap_init = mlxsw_sp_trap_init, + .trap_fini = mlxsw_sp_trap_fini, + .trap_action_set = mlxsw_sp_trap_action_set, + .trap_group_init = mlxsw_sp_trap_group_init, .txhdr_construct = mlxsw_sp_txhdr_construct, .resources_register = mlxsw_sp2_resources_register, .params_register = mlxsw_sp2_params_register, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index db17ba35ec84..20c14bba9ccb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -958,4 +958,17 @@ void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp); +/* spectrum_trap.c */ +int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp); +void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp); +int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx); +void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx); +int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, + enum devlink_trap_action action); +int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, + const struct devlink_trap_group *group); + #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c new file mode 100644 index 000000000000..899450b28621 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2019 Mellanox Technologies. All rights reserved */ + +#include +#include +#include + +#include "core.h" +#include "reg.h" +#include "spectrum.h" + +#define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT + +static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port, + void *priv); + +#define MLXSW_SP_TRAP_DROP(_id, _group_id) \ + DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ + DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + MLXSW_SP_TRAP_METADATA) + +#define MLXSW_SP_RXL_DISCARD(_id, _group_id) \ + MLXSW_RXL(mlxsw_sp_rx_drop_listener, DISCARD_##_id, SET_FW_DEFAULT, \ + false, SP_##_group_id, DISCARD) + +static struct devlink_trap mlxsw_sp_traps_arr[] = { + MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS), + MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS), + MLXSW_SP_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS), + MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS), + MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS), + MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS), +}; + +static struct mlxsw_listener mlxsw_sp_listeners_arr[] = { + MLXSW_SP_RXL_DISCARD(ING_PACKET_SMAC_MC, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(ING_SWITCH_VTAG_ALLOW, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(ING_SWITCH_VLAN, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(ING_SWITCH_STP, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS), + MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS), +}; + +/* Mapping between hardware trap and devlink trap. Multiple hardware traps can + * be mapped to the same devlink trap. Order is according to + * 'mlxsw_sp_listeners_arr'. + */ +static u16 mlxsw_sp_listener_devlink_map[] = { + DEVLINK_TRAP_GENERIC_ID_SMAC_MC, + DEVLINK_TRAP_GENERIC_ID_VLAN_TAG_MISMATCH, + DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER, + DEVLINK_TRAP_GENERIC_ID_INGRESS_STP_FILTER, + DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST, + DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST, + DEVLINK_TRAP_GENERIC_ID_PORT_LOOPBACK_FILTER, +}; + +static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb, + u8 local_port, + struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp_port_pcpu_stats *pcpu_stats; + + if (unlikely(!mlxsw_sp_port)) { + dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n", + local_port); + kfree_skb(skb); + return -EINVAL; + } + + skb->dev = mlxsw_sp_port->dev; + + pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats); + u64_stats_update_begin(&pcpu_stats->syncp); + pcpu_stats->rx_packets++; + pcpu_stats->rx_bytes += skb->len; + u64_stats_update_end(&pcpu_stats->syncp); + + skb->protocol = eth_type_trans(skb, skb->dev); + + return 0; +} + +static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port, + void *trap_ctx) +{ + struct devlink_port *in_devlink_port; + struct mlxsw_sp_port *mlxsw_sp_port; + struct mlxsw_sp *mlxsw_sp; + struct devlink *devlink; + + mlxsw_sp = devlink_trap_ctx_priv(trap_ctx); + mlxsw_sp_port = mlxsw_sp->ports[local_port]; + + if (mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port)) + return; + + devlink = priv_to_devlink(mlxsw_sp->core); + in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core, + local_port); + devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port); + consume_skb(skb); +} + +int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); + + if (WARN_ON(ARRAY_SIZE(mlxsw_sp_listener_devlink_map) != + ARRAY_SIZE(mlxsw_sp_listeners_arr))) + return -EINVAL; + + return devlink_traps_register(devlink, mlxsw_sp_traps_arr, + ARRAY_SIZE(mlxsw_sp_traps_arr), + mlxsw_sp); +} + +void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); + + devlink_traps_unregister(devlink, mlxsw_sp_traps_arr, + ARRAY_SIZE(mlxsw_sp_traps_arr)); +} + +int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) { + struct mlxsw_listener *listener; + int err; + + if (mlxsw_sp_listener_devlink_map[i] != trap->id) + continue; + listener = &mlxsw_sp_listeners_arr[i]; + + err = mlxsw_core_trap_register(mlxsw_core, listener, trap_ctx); + if (err) + return err; + } + + return 0; +} + +void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, void *trap_ctx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) { + struct mlxsw_listener *listener; + + if (mlxsw_sp_listener_devlink_map[i] != trap->id) + continue; + listener = &mlxsw_sp_listeners_arr[i]; + + mlxsw_core_trap_unregister(mlxsw_core, listener, trap_ctx); + } +} + +int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, + const struct devlink_trap *trap, + enum devlink_trap_action action) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) { + enum mlxsw_reg_hpkt_action hw_action; + struct mlxsw_listener *listener; + int err; + + if (mlxsw_sp_listener_devlink_map[i] != trap->id) + continue; + listener = &mlxsw_sp_listeners_arr[i]; + + switch (action) { + case DEVLINK_TRAP_ACTION_DROP: + hw_action = MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT; + break; + case DEVLINK_TRAP_ACTION_TRAP: + hw_action = MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU; + break; + default: + return -EINVAL; + } + + err = mlxsw_core_trap_action_set(mlxsw_core, listener, + hw_action); + if (err) + return err; + } + + return 0; +} + +#define MLXSW_SP_DISCARD_POLICER_ID (MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1) + +static int +mlxsw_sp_trap_group_policer_init(struct mlxsw_sp *mlxsw_sp, + const struct devlink_trap_group *group) +{ + enum mlxsw_reg_qpcr_ir_units ir_units; + char qpcr_pl[MLXSW_REG_QPCR_LEN]; + u16 policer_id; + u8 burst_size; + bool is_bytes; + u32 rate; + + switch (group->id) { + case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS: + policer_id = MLXSW_SP_DISCARD_POLICER_ID; + ir_units = MLXSW_REG_QPCR_IR_UNITS_M; + is_bytes = false; + rate = 10 * 1024; /* 10Kpps */ + burst_size = 7; + break; + default: + return -EINVAL; + } + + mlxsw_reg_qpcr_pack(qpcr_pl, policer_id, ir_units, is_bytes, rate, + burst_size); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl); +} + +static int +__mlxsw_sp_trap_group_init(struct mlxsw_sp *mlxsw_sp, + const struct devlink_trap_group *group) +{ + char htgt_pl[MLXSW_REG_HTGT_LEN]; + u8 priority, tc, group_id; + u16 policer_id; + + switch (group->id) { + case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS: + group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS; + policer_id = MLXSW_SP_DISCARD_POLICER_ID; + priority = 0; + tc = 1; + break; + default: + return -EINVAL; + } + + mlxsw_reg_htgt_pack(htgt_pl, group_id, policer_id, priority, tc); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl); +} + +int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, + const struct devlink_trap_group *group) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + int err; + + err = mlxsw_sp_trap_group_policer_init(mlxsw_sp, group); + if (err) + return err; + + err = __mlxsw_sp_trap_group_init(mlxsw_sp, group); + if (err) + return err; + + return 0; +} -- GitLab From 170270329b1b5f854e8a98aea16bfa4af6922146 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:36 +0300 Subject: [PATCH 3907/7155] selftests: mlxsw: Add test cases for devlink-trap L2 drops Test that each supported packet trap is triggered under the right conditions and that packets are indeed dropped and not forwarded. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/mlxsw/devlink_trap_l2_drops.sh | 484 ++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh new file mode 100755 index 000000000000..5dcdfa20fc6c --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh @@ -0,0 +1,484 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test devlink-trap L2 drops functionality over mlxsw. Each registered L2 drop +# packet trap is tested to make sure it is triggered under the right +# conditions. + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" + source_mac_is_multicast_test + vlan_tag_mismatch_test + ingress_vlan_filter_test + ingress_stp_filter_test + port_list_is_empty_test + port_loopback_filter_test +" +NUM_NETIFS=4 +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ + simple_if_init $h1 +} + +h1_destroy() +{ + simple_if_fini $h1 +} + +h2_create() +{ + simple_if_init $h2 +} + +h2_destroy() +{ + simple_if_fini $h2 +} + +switch_create() +{ + ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 + + ip link set dev $swp1 master br0 + ip link set dev $swp2 master br0 + + ip link set dev br0 up + ip link set dev $swp1 up + ip link set dev $swp2 up + + tc qdisc add dev $swp2 clsact +} + +switch_destroy() +{ + tc qdisc del dev $swp2 clsact + + ip link set dev $swp2 down + ip link set dev $swp1 down + + ip link del dev br0 +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + swp1=${NETIFS[p2]} + + swp2=${NETIFS[p3]} + h2=${NETIFS[p4]} + + vrf_prepare + + h1_create + h2_create + + switch_create +} + +cleanup() +{ + pre_cleanup + + switch_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +l2_drops_test() +{ + local trap_name=$1; shift + local group_name=$1; shift + + # This is the common part of all the tests. It checks that stats are + # initially idle, then non-idle after changing the trap action and + # finally idle again. It also makes sure the packets are dropped and + # never forwarded. + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle with initial drop action" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with initial drop action" + + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_fail $? "Trap stats idle after setting action to trap" + devlink_trap_group_stats_idle_test $group_name + check_fail $? "Trap group stats idle after setting action to trap" + + devlink_trap_action_set $trap_name "drop" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle after setting action to drop" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle after setting action to drop" + + tc_check_packets "dev $swp2 egress" 101 0 + check_err $? "Packets were not dropped" +} + +l2_drops_cleanup() +{ + local mz_pid=$1; shift + + kill $mz_pid && wait $mz_pid &> /dev/null + tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower +} + +source_mac_is_multicast_test() +{ + local trap_name="source_mac_is_multicast" + local smac=01:02:03:04:05:06 + local group_name="l2_drops" + local mz_pid + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower src_mac $smac action drop + + $MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -d 1msec -q & + mz_pid=$! + + RET=0 + + l2_drops_test $trap_name $group_name + + log_test "Source MAC is multicast" + + l2_drops_cleanup $mz_pid +} + +__vlan_tag_mismatch_test() +{ + local trap_name="vlan_tag_mismatch" + local dmac=de:ad:be:ef:13:37 + local group_name="l2_drops" + local opt=$1; shift + local mz_pid + + # Remove PVID flag. This should prevent untagged and prio-tagged + # packets from entering the bridge. + bridge vlan add vid 1 dev $swp1 untagged master + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Add PVID and make sure packets are no longer dropped. + bridge vlan add vid 1 dev $swp1 pvid untagged master + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + l2_drops_cleanup $mz_pid +} + +vlan_tag_mismatch_untagged_test() +{ + RET=0 + + __vlan_tag_mismatch_test + + log_test "VLAN tag mismatch - untagged packets" +} + +vlan_tag_mismatch_vid_0_test() +{ + RET=0 + + __vlan_tag_mismatch_test "-Q 0" + + log_test "VLAN tag mismatch - prio-tagged packets" +} + +vlan_tag_mismatch_test() +{ + vlan_tag_mismatch_untagged_test + vlan_tag_mismatch_vid_0_test +} + +ingress_vlan_filter_test() +{ + local trap_name="ingress_vlan_filter" + local dmac=de:ad:be:ef:13:37 + local group_name="l2_drops" + local mz_pid + local vid=10 + + bridge vlan add vid $vid dev $swp2 master + # During initialization the firmware enables all the VLAN filters and + # the driver does not turn them off since the traffic will be discarded + # by the STP filter whose default is DISCARD state. Add the VID on the + # ingress bridge port and then remove it to make sure it is not member + # in the VLAN. + bridge vlan add vid $vid dev $swp1 master + bridge vlan del vid $vid dev $swp1 master + + RET=0 + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Add the VLAN on the bridge port and make sure packets are no longer + # dropped. + bridge vlan add vid $vid dev $swp1 master + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + log_test "Ingress VLAN filter" + + l2_drops_cleanup $mz_pid + + bridge vlan del vid $vid dev $swp1 master + bridge vlan del vid $vid dev $swp2 master +} + +__ingress_stp_filter_test() +{ + local trap_name="ingress_spanning_tree_filter" + local dmac=de:ad:be:ef:13:37 + local group_name="l2_drops" + local state=$1; shift + local mz_pid + local vid=20 + + bridge vlan add vid $vid dev $swp2 master + bridge vlan add vid $vid dev $swp1 master + ip link set dev $swp1 type bridge_slave state $state + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Change STP state to forwarding and make sure packets are no longer + # dropped. + ip link set dev $swp1 type bridge_slave state 3 + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + l2_drops_cleanup $mz_pid + + bridge vlan del vid $vid dev $swp1 master + bridge vlan del vid $vid dev $swp2 master +} + +ingress_stp_filter_listening_test() +{ + local state=$1; shift + + RET=0 + + __ingress_stp_filter_test $state + + log_test "Ingress STP filter - listening state" +} + +ingress_stp_filter_learning_test() +{ + local state=$1; shift + + RET=0 + + __ingress_stp_filter_test $state + + log_test "Ingress STP filter - learning state" +} + +ingress_stp_filter_test() +{ + ingress_stp_filter_listening_test 1 + ingress_stp_filter_learning_test 2 +} + +port_list_is_empty_uc_test() +{ + local trap_name="port_list_is_empty" + local dmac=de:ad:be:ef:13:37 + local group_name="l2_drops" + local mz_pid + + # Disable unicast flooding on both ports, so that packets cannot egress + # any port. + ip link set dev $swp1 type bridge_slave flood off + ip link set dev $swp2 type bridge_slave flood off + + RET=0 + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Allow packets to be flooded to one port. + ip link set dev $swp2 type bridge_slave flood on + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + log_test "Port list is empty - unicast" + + l2_drops_cleanup $mz_pid + + ip link set dev $swp1 type bridge_slave flood on +} + +port_list_is_empty_mc_test() +{ + local trap_name="port_list_is_empty" + local dmac=01:00:5e:00:00:01 + local group_name="l2_drops" + local dip=239.0.0.1 + local mz_pid + + # Disable multicast flooding on both ports, so that packets cannot + # egress any port. We also need to flush IP addresses from the bridge + # in order to prevent packets from being flooded to the router port. + ip link set dev $swp1 type bridge_slave mcast_flood off + ip link set dev $swp2 type bridge_slave mcast_flood off + ip address flush dev br0 + + RET=0 + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Allow packets to be flooded to one port. + ip link set dev $swp2 type bridge_slave mcast_flood on + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + log_test "Port list is empty - multicast" + + l2_drops_cleanup $mz_pid + + ip link set dev $swp1 type bridge_slave mcast_flood on +} + +port_list_is_empty_test() +{ + port_list_is_empty_uc_test + port_list_is_empty_mc_test +} + +port_loopback_filter_uc_test() +{ + local trap_name="port_loopback_filter" + local dmac=de:ad:be:ef:13:37 + local group_name="l2_drops" + local mz_pid + + # Make sure packets can only egress the input port. + ip link set dev $swp2 type bridge_slave flood off + + RET=0 + + tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ + flower dst_mac $dmac action drop + + $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & + mz_pid=$! + + l2_drops_test $trap_name $group_name + + # Allow packets to be flooded. + ip link set dev $swp2 type bridge_slave flood on + devlink_trap_action_set $trap_name "trap" + + devlink_trap_stats_idle_test $trap_name + check_err $? "Trap stats not idle when packets should not be dropped" + devlink_trap_group_stats_idle_test $group_name + check_err $? "Trap group stats not idle with when packets should not be dropped" + + tc_check_packets "dev $swp2 egress" 101 0 + check_fail $? "Packets not forwarded when should" + + devlink_trap_action_set $trap_name "drop" + + log_test "Port loopback filter - unicast" + + l2_drops_cleanup $mz_pid +} + +port_loopback_filter_test() +{ + port_loopback_filter_uc_test +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS -- GitLab From 1455865a040a0f632dce5d8f7cb6604517f56c6d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 21 Aug 2019 10:19:37 +0300 Subject: [PATCH 3908/7155] selftests: mlxsw: Add a test case for devlink-trap Test generic devlink-trap functionality over mlxsw. These tests are not specific to a single trap, but do not check the devlink-trap common infrastructure either. Currently, the only test case is device deletion (by reloading the driver) while packets are being trapped. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../drivers/net/mlxsw/devlink_trap.sh | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh new file mode 100755 index 000000000000..89b55e946eed --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test generic devlink-trap functionality over mlxsw. These tests are not +# specific to a single trap, but do not check the devlink-trap common +# infrastructure either. + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" + dev_del_test +" +NUM_NETIFS=4 +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ + simple_if_init $h1 +} + +h1_destroy() +{ + simple_if_fini $h1 +} + +h2_create() +{ + simple_if_init $h2 +} + +h2_destroy() +{ + simple_if_fini $h2 +} + +switch_create() +{ + ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 + + ip link set dev $swp1 master br0 + ip link set dev $swp2 master br0 + + ip link set dev br0 up + ip link set dev $swp1 up + ip link set dev $swp2 up +} + +switch_destroy() +{ + ip link set dev $swp2 down + ip link set dev $swp1 down + + ip link del dev br0 +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + swp1=${NETIFS[p2]} + + swp2=${NETIFS[p3]} + h2=${NETIFS[p4]} + + vrf_prepare + + h1_create + h2_create + + switch_create +} + +cleanup() +{ + pre_cleanup + + switch_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +dev_del_test() +{ + local trap_name="source_mac_is_multicast" + local smac=01:02:03:04:05:06 + local num_iter=5 + local mz_pid + local i + + $MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -q & + mz_pid=$! + + # The purpose of this test is to make sure we correctly dismantle a + # port while packets are trapped from it. This is done by reloading the + # the driver while the 'ingress_smac_mc_drop' trap is triggered. + RET=0 + + for i in $(seq 1 $num_iter); do + log_info "Iteration $i / $num_iter" + + devlink_trap_action_set $trap_name "trap" + sleep 1 + + devlink_reload + # Allow netdevices to be re-created following the reload + sleep 20 + + cleanup + setup_prepare + setup_wait + done + + log_test "Device delete" + + kill $mz_pid && wait $mz_pid &> /dev/null +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS -- GitLab From eba39fd6fe310710f011130e46e6d13e5c87d6f9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:32:03 +0800 Subject: [PATCH 3909/7155] amd-xgbe: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-platform.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c index dce9e59e8881..4ebd2410185a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c @@ -301,7 +301,6 @@ static int xgbe_platform_probe(struct platform_device *pdev) struct xgbe_prv_data *pdata; struct device *dev = &pdev->dev; struct platform_device *phy_pdev; - struct resource *res; const char *phy_mode; unsigned int phy_memnum, phy_irqnum; unsigned int dma_irqnum, dma_irqend; @@ -353,8 +352,7 @@ static int xgbe_platform_probe(struct platform_device *pdev) } /* Obtain the mmio areas for the device */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdata->xgmac_regs = devm_ioremap_resource(dev, res); + pdata->xgmac_regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pdata->xgmac_regs)) { dev_err(dev, "xgmac ioremap failed\n"); ret = PTR_ERR(pdata->xgmac_regs); @@ -363,8 +361,7 @@ static int xgbe_platform_probe(struct platform_device *pdev) if (netif_msg_probe(pdata)) dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - pdata->xpcs_regs = devm_ioremap_resource(dev, res); + pdata->xpcs_regs = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(pdata->xpcs_regs)) { dev_err(dev, "xpcs ioremap failed\n"); ret = PTR_ERR(pdata->xpcs_regs); @@ -373,8 +370,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) if (netif_msg_probe(pdata)) dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs); - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->rxtx_regs = devm_ioremap_resource(dev, res); + pdata->rxtx_regs = devm_platform_ioremap_resource(phy_pdev, + phy_memnum++); if (IS_ERR(pdata->rxtx_regs)) { dev_err(dev, "rxtx ioremap failed\n"); ret = PTR_ERR(pdata->rxtx_regs); @@ -383,8 +380,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) if (netif_msg_probe(pdata)) dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs); - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->sir0_regs = devm_ioremap_resource(dev, res); + pdata->sir0_regs = devm_platform_ioremap_resource(phy_pdev, + phy_memnum++); if (IS_ERR(pdata->sir0_regs)) { dev_err(dev, "sir0 ioremap failed\n"); ret = PTR_ERR(pdata->sir0_regs); @@ -393,8 +390,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) if (netif_msg_probe(pdata)) dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs); - res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); - pdata->sir1_regs = devm_ioremap_resource(dev, res); + pdata->sir1_regs = devm_platform_ioremap_resource(phy_pdev, + phy_memnum++); if (IS_ERR(pdata->sir1_regs)) { dev_err(dev, "sir1 ioremap failed\n"); ret = PTR_ERR(pdata->sir1_regs); -- GitLab From c8ace62ff3a98bdc52c6df23c23465cfd9e3a847 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:48:50 +0800 Subject: [PATCH 3910/7155] net: ethernet: ti: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Grygorii Strashko Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 32a89744972d..54010957da5c 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -2764,7 +2764,7 @@ static int cpsw_probe(struct platform_device *pdev) struct net_device *ndev; struct cpsw_priv *priv; void __iomem *ss_regs; - struct resource *res, *ss_res; + struct resource *ss_res; struct gpio_descs *mode; const struct soc_device_attribute *soc; struct cpsw_common *cpsw; @@ -2798,8 +2798,7 @@ static int cpsw_probe(struct platform_device *pdev) return PTR_ERR(ss_regs); cpsw->regs = ss_regs; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - cpsw->wr_regs = devm_ioremap_resource(dev, res); + cpsw->wr_regs = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(cpsw->wr_regs)) return PTR_ERR(cpsw->wr_regs); -- GitLab From 8a54d4c21919022e9fc59e71ca0f86d4431a8e2a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:50:50 +0800 Subject: [PATCH 3911/7155] via-rhine: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-rhine.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index ab55416a10fa..ed12dbd156f0 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1127,15 +1127,13 @@ static int rhine_init_one_platform(struct platform_device *pdev) const struct of_device_id *match; const u32 *quirks; int irq; - struct resource *res; void __iomem *ioaddr; match = of_match_device(rhine_of_tbl, &pdev->dev); if (!match) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ioaddr = devm_ioremap_resource(&pdev->dev, res); + ioaddr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ioaddr)) return PTR_ERR(ioaddr); -- GitLab From 5bd5b56457b0415c82f359ad67dc38d1b7eb381d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:53:57 +0800 Subject: [PATCH 3912/7155] net: socionext: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/socionext/sni_ave.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 87ab0b5da91e..10d0c3e478ab 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1553,7 +1553,6 @@ static int ave_probe(struct platform_device *pdev) struct ave_private *priv; struct net_device *ndev; struct device_node *np; - struct resource *res; const void *mac_addr; void __iomem *base; const char *name; @@ -1576,8 +1575,7 @@ static int ave_probe(struct platform_device *pdev) if (irq < 0) return irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From 4865695c0f1aa302db2b817be3ef6b0cba53763b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:58:11 +0800 Subject: [PATCH 3913/7155] net: ks8851-ml: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/micrel/ks8851_mll.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index e52b015e31a9..a41a90c589db 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1225,7 +1225,6 @@ MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids); static int ks8851_probe(struct platform_device *pdev) { int err; - struct resource *io_d, *io_c; struct net_device *netdev; struct ks_net *ks; u16 id, data; @@ -1240,15 +1239,13 @@ static int ks8851_probe(struct platform_device *pdev) ks = netdev_priv(netdev); ks->netdev = netdev; - io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ks->hw_addr = devm_ioremap_resource(&pdev->dev, io_d); + ks->hw_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ks->hw_addr)) { err = PTR_ERR(ks->hw_addr); goto err_free; } - io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1); - ks->hw_addr_cmd = devm_ioremap_resource(&pdev->dev, io_c); + ks->hw_addr_cmd = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(ks->hw_addr_cmd)) { err = PTR_ERR(ks->hw_addr_cmd); goto err_free; -- GitLab From ffb36a10c656c0b106401c6792b55b6506078949 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:59:59 +0800 Subject: [PATCH 3914/7155] net: sxgbe: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index d2c48116f181..2412c87561e0 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -78,7 +78,6 @@ static int sxgbe_platform_probe(struct platform_device *pdev) { int ret; int i, chan; - struct resource *res; struct device *dev = &pdev->dev; void __iomem *addr; struct sxgbe_priv_data *priv = NULL; @@ -88,8 +87,7 @@ static int sxgbe_platform_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; /* Get memory resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - addr = devm_ioremap_resource(dev, res); + addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(addr)) return PTR_ERR(addr); -- GitLab From 1a1ba7118807e82fab7d44ccf0910d3bb0015b0b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:02:41 +0800 Subject: [PATCH 3915/7155] cirrus: cs89x0: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/cirrus/cs89x0.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index b3e7fafee3df..2d30972df06b 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1845,7 +1845,6 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); struct net_local *lp; - struct resource *mem_res; void __iomem *virt_addr; int err; @@ -1861,8 +1860,7 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev) goto free; } - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - virt_addr = devm_ioremap_resource(&pdev->dev, mem_res); + virt_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(virt_addr)) { err = PTR_ERR(virt_addr); goto free; -- GitLab From b6df983076e517af660e14a3ed6d3b1a986dfc2c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:05:09 +0800 Subject: [PATCH 3916/7155] ezchip: nps_enet: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/ezchip/nps_enet.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c index 027225e1ade2..815fb62c4b02 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.c +++ b/drivers/net/ethernet/ezchip/nps_enet.c @@ -576,7 +576,6 @@ static s32 nps_enet_probe(struct platform_device *pdev) struct nps_enet_priv *priv; s32 err = 0; const char *mac_addr; - struct resource *res_regs; if (!dev->of_node) return -ENODEV; @@ -595,8 +594,7 @@ static s32 nps_enet_probe(struct platform_device *pdev) /* FIXME :: no multicast support yet */ ndev->flags &= ~IFF_MULTICAST; - res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs_base = devm_ioremap_resource(dev, res_regs); + priv->regs_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs_base)) { err = PTR_ERR(priv->regs_base); goto out_netdev; -- GitLab From 4f830a5af7b5b3614a03ef784cd2f4a83ceebf27 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:29:45 +0800 Subject: [PATCH 3917/7155] net: fec: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index c01d3ec3e9af..cacc671e486e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3338,7 +3338,6 @@ fec_probe(struct platform_device *pdev) struct fec_platform_data *pdata; struct net_device *ndev; int i, irq, ret = 0; - struct resource *r; const struct of_device_id *of_id; static int dev_id; struct device_node *np = pdev->dev.of_node, *phy_node; @@ -3378,8 +3377,7 @@ fec_probe(struct platform_device *pdev) /* Select default pin state */ pinctrl_pm_select_default_state(&pdev->dev); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - fep->hwp = devm_ioremap_resource(&pdev->dev, r); + fep->hwp = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(fep->hwp)) { ret = PTR_ERR(fep->hwp); goto failed_ioremap; -- GitLab From 37f76049b095da153efa047538f73b1af8dfbc6a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:33:02 +0800 Subject: [PATCH 3918/7155] net: mvneta: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta_bm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta_bm.c b/drivers/net/ethernet/marvell/mvneta_bm.c index 82ee2bcca6fd..46c942ef2287 100644 --- a/drivers/net/ethernet/marvell/mvneta_bm.c +++ b/drivers/net/ethernet/marvell/mvneta_bm.c @@ -411,15 +411,13 @@ static int mvneta_bm_probe(struct platform_device *pdev) { struct device_node *dn = pdev->dev.of_node; struct mvneta_bm *priv; - struct resource *res; int err; priv = devm_kzalloc(&pdev->dev, sizeof(struct mvneta_bm), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->reg_base = devm_ioremap_resource(&pdev->dev, res); + priv->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->reg_base)) return PTR_ERR(priv->reg_base); -- GitLab From 531fd23b00610fb066da7776ea25db8aa383a4b8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:38:54 +0800 Subject: [PATCH 3919/7155] pxa168_eth: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/pxa168_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 3aa998797bc1..51b77c2de400 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1425,8 +1425,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep->dev = dev; pep->clk = clk; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pep->base = devm_ioremap_resource(&pdev->dev, res); + pep->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pep->base)) { err = -ENOMEM; goto err_netdev; -- GitLab From 4ca3348dff9ac63a571288019f6030a3d7e1e940 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:41:31 +0800 Subject: [PATCH 3920/7155] net: bcmgenet: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index d3a0b614dbfa..2108e59f592b 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -3437,7 +3437,6 @@ static int bcmgenet_probe(struct platform_device *pdev) struct bcmgenet_priv *priv; struct net_device *dev; const void *macaddr; - struct resource *r; unsigned int i; int err = -EIO; const char *phy_mode_str; @@ -3477,8 +3476,7 @@ static int bcmgenet_probe(struct platform_device *pdev) macaddr = pd->mac_address; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, r); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { err = PTR_ERR(priv->base); goto err; -- GitLab From 913919e51ee69df7a3250056c522d683c937bf46 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:46:13 +0800 Subject: [PATCH 3921/7155] net: systemport: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 9483553ce444..cae66ba33c0b 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2420,12 +2420,10 @@ static int bcm_sysport_probe(struct platform_device *pdev) struct device_node *dn; struct net_device *dev; const void *macaddr; - struct resource *r; u32 txq, rxq; int ret; dn = pdev->dev.of_node; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); of_id = of_match_node(bcm_sysport_of_match, dn); if (!of_id || !of_id->data) return -EINVAL; @@ -2473,7 +2471,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) goto err_free_netdev; } - priv->base = devm_ioremap_resource(&pdev->dev, r); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto err_free_netdev; -- GitLab From 999232a38ff10209df1ce40cabe8cf8982c530e7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:51:30 +0800 Subject: [PATCH 3922/7155] net: stmmac: dwmac-meson8b: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index 786ca4a7bf36..9cda29e4b89d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -308,7 +308,6 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; - struct resource *res; struct meson8b_dwmac *dwmac; int ret; @@ -332,8 +331,7 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) ret = -EINVAL; goto err_remove_config_dt; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dwmac->regs = devm_ioremap_resource(&pdev->dev, res); + dwmac->regs = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dwmac->regs)) { ret = PTR_ERR(dwmac->regs); goto err_remove_config_dt; -- GitLab From f33bf6b00f20c9d26c42dfdaf8b83c2b0c1e6f71 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:54:06 +0800 Subject: [PATCH 3923/7155] net: stmmac: dwmac-meson: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 88eb16954627..bbc16b5a410a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -46,7 +46,6 @@ static int meson6_dwmac_probe(struct platform_device *pdev) struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct meson_dwmac *dwmac; - struct resource *res; int ret; ret = stmmac_get_platform_resources(pdev, &stmmac_res); @@ -63,8 +62,7 @@ static int meson6_dwmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dwmac->reg = devm_ioremap_resource(&pdev->dev, res); + dwmac->reg = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dwmac->reg)) { ret = PTR_ERR(dwmac->reg); goto err_remove_config_dt; -- GitLab From ad124aa34e514393218f46f9701fdeaf35cbf5d3 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:55:50 +0800 Subject: [PATCH 3924/7155] net: stmmac: dwmac-anarion: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c index 6ce3a7fb41ab..527f93320a5a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c @@ -62,12 +62,10 @@ static void anarion_gmac_exit(struct platform_device *pdev, void *priv) static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev) { int phy_mode; - struct resource *res; void __iomem *ctl_block; struct anarion_gmac *gmac; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - ctl_block = devm_ioremap_resource(&pdev->dev, res); + ctl_block = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(ctl_block)) { dev_err(&pdev->dev, "Cannot get reset region (%ld)!\n", PTR_ERR(ctl_block)); -- GitLab From 2b9b5e74507fe8e6146b048c0dadbe2fe7b298e5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 21:57:01 +0800 Subject: [PATCH 3925/7155] net: stmmac: dwc-qos: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index f2197b066ed1..dd9967aeda22 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -418,7 +418,6 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) const struct dwc_eth_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; - struct resource *res; void *priv; int ret; @@ -435,8 +434,7 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) return stmmac_res.irq; stmmac_res.wol_irq = stmmac_res.irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - stmmac_res.addr = devm_ioremap_resource(&pdev->dev, res); + stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(stmmac_res.addr)) return PTR_ERR(stmmac_res.addr); -- GitLab From c268e7adea52be0093de1164c425f3c8d8927770 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sat, 3 Aug 2019 00:12:03 -0300 Subject: [PATCH 3926/7155] media: dvb-frontends: use ida for pll number KASAN: global-out-of-bounds Read in dvb_pll_attach Syzbot reported global-out-of-bounds Read in dvb_pll_attach, while accessing id[dvb_pll_devcount], because dvb_pll_devcount was 65, that is more than size of 'id' which is DVB_PLL_MAX(64). Rather than increasing dvb_pll_devcount every time, use ida so that numbers are allocated correctly. This does mean that no more than 64 devices can be attached at the same time, but this is more than sufficient. usb 1-1: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer dvbdev: DVB: registering new adapter (774 Friio White ISDB-T USB2.0) usb 1-1: media controller created dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered. tc90522 0-0018: Toshiba TC90522 attached. usb 1-1: DVB: registering adapter 0 frontend 0 (Toshiba TC90522 ISDB-T module)... dvbdev: dvb_create_media_entity: media entity 'Toshiba TC90522 ISDB-T module' registered. ================================================================== BUG: KASAN: global-out-of-bounds in dvb_pll_attach+0x6c5/0x830 drivers/media/dvb-frontends/dvb-pll.c:798 Read of size 4 at addr ffffffff89c9e5e0 by task kworker/0:1/12 CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.2.0-rc6+ #13 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xca/0x13e lib/dump_stack.c:113 print_address_description+0x67/0x231 mm/kasan/report.c:188 __kasan_report.cold+0x1a/0x32 mm/kasan/report.c:317 kasan_report+0xe/0x20 mm/kasan/common.c:614 dvb_pll_attach+0x6c5/0x830 drivers/media/dvb-frontends/dvb-pll.c:798 dvb_pll_probe+0xfe/0x174 drivers/media/dvb-frontends/dvb-pll.c:877 i2c_device_probe+0x790/0xaa0 drivers/i2c/i2c-core-base.c:389 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 i2c_new_client_device+0x5b3/0xc40 drivers/i2c/i2c-core-base.c:778 i2c_new_device+0x19/0x50 drivers/i2c/i2c-core-base.c:821 dvb_module_probe+0xf9/0x220 drivers/media/dvb-core/dvbdev.c:985 friio_tuner_attach+0x125/0x1d0 drivers/media/usb/dvb-usb-v2/gl861.c:536 dvb_usbv2_adapter_frontend_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:675 [inline] dvb_usbv2_adapter_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:804 [inline] dvb_usbv2_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:865 [inline] dvb_usbv2_probe.cold+0x24dc/0x255d drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:980 usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023 generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210 usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 usb_new_device.cold+0x8c1/0x1016 drivers/usb/core/hub.c:2534 hub_port_connect drivers/usb/core/hub.c:5089 [inline] hub_port_connect_change drivers/usb/core/hub.c:5204 [inline] port_event drivers/usb/core/hub.c:5350 [inline] hub_event+0x1ada/0x3590 drivers/usb/core/hub.c:5432 process_one_work+0x905/0x1570 kernel/workqueue.c:2269 process_scheduled_works kernel/workqueue.c:2331 [inline] worker_thread+0x7ab/0xe20 kernel/workqueue.c:2417 kthread+0x30b/0x410 kernel/kthread.c:255 ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 The buggy address belongs to the variable: id+0x100/0x120 Memory state around the buggy address: ffffffff89c9e480: fa fa fa fa 00 00 fa fa fa fa fa fa 00 00 00 00 ffffffff89c9e500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ffffffff89c9e580: 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa ^ ffffffff89c9e600: 04 fa fa fa fa fa fa fa 04 fa fa fa fa fa fa fa ffffffff89c9e680: 04 fa fa fa fa fa fa fa 04 fa fa fa fa fa fa fa ================================================================== Reported-by: syzbot+8a8f48672560c8ca59dd@syzkaller.appspotmail.com Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dvb-pll.c | 40 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index ba0c49107bd2..d45b4ddc8f91 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -34,8 +35,7 @@ struct dvb_pll_priv { }; #define DVB_PLL_MAX 64 - -static unsigned int dvb_pll_devcount; +static DEFINE_IDA(pll_ida); static int debug; module_param(debug, int, 0644); @@ -787,6 +787,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct dvb_pll_priv *priv = NULL; int ret; const struct dvb_pll_desc *desc; + int nr; b1 = kmalloc(1, GFP_KERNEL); if (!b1) @@ -795,9 +796,14 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, b1[0] = 0; msg.buf = b1; - if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && - (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) - pll_desc_id = id[dvb_pll_devcount]; + nr = ida_simple_get(&pll_ida, 0, DVB_PLL_MAX, GFP_KERNEL); + if (nr < 0) { + kfree(b1); + return NULL; + } + + if (id[nr] > DVB_PLL_UNDEFINED && id[nr] < ARRAY_SIZE(pll_list)) + pll_desc_id = id[nr]; BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list)); @@ -808,24 +814,20 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, fe->ops.i2c_gate_ctrl(fe, 1); ret = i2c_transfer (i2c, &msg, 1); - if (ret != 1) { - kfree(b1); - return NULL; - } + if (ret != 1) + goto out; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); - if (!priv) { - kfree(b1); - return NULL; - } + if (!priv) + goto out; priv->pll_i2c_address = pll_addr; priv->i2c = i2c; priv->pll_desc = desc; - priv->nr = dvb_pll_devcount++; + priv->nr = nr; memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); @@ -858,6 +860,11 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, kfree(b1); return fe; +out: + kfree(b1); + ida_simple_remove(&pll_ida, nr); + + return NULL; } EXPORT_SYMBOL(dvb_pll_attach); @@ -894,9 +901,10 @@ dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id) static int dvb_pll_remove(struct i2c_client *client) { - struct dvb_frontend *fe; + struct dvb_frontend *fe = i2c_get_clientdata(client); + struct dvb_pll_priv *priv = fe->tuner_priv; - fe = i2c_get_clientdata(client); + ida_simple_remove(&pll_ida, priv->nr); dvb_pll_release(fe); return 0; } -- GitLab From 619f6fc390909fce3247c3e07e6882b868b645da Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Mon, 15 Jul 2019 06:50:29 -0300 Subject: [PATCH 3927/7155] media: si2168: Refactor command setup code Use cmd_init() to fill a struct si2168_cmd command. Signed-off-by: Marc Gonzalez Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 159 ++++++++------------------- 1 file changed, 48 insertions(+), 111 deletions(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index a574f1d77c56..14b93a7d3358 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -11,6 +11,13 @@ static const struct dvb_frontend_ops si2168_ops; +static void cmd_init(struct si2168_cmd *cmd, const u8 *buf, int wlen, int rlen) +{ + memcpy(cmd->args, buf, wlen); + cmd->wlen = wlen; + cmd->rlen = rlen; +} + /* execute firmware command */ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) { @@ -84,15 +91,13 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) /* set manual value */ if (dev->ts_mode & SI2168_TS_CLK_MANUAL) { - memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x0d\x10\xe8\x03", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) return ret; } /* set TS_MODE property */ - memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); + cmd_init(&cmd, "\x14\x00\x01\x10\x10\x00", 6, 4); if (dev->ts_mode & SI2168_TS_CLK_MANUAL) cmd.args[4] = SI2168_TS_CLK_MANUAL; if (acquire) @@ -101,8 +106,6 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) cmd.args[4] |= SI2168_TS_TRISTATE; if (dev->ts_clock_gapped) cmd.args[4] |= 0x40; - cmd.wlen = 6; - cmd.rlen = 4; ret = si2168_cmd_execute(client, &cmd); return ret; @@ -126,19 +129,13 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) switch (c->delivery_system) { case SYS_DVBT: - memcpy(cmd.args, "\xa0\x01", 2); - cmd.wlen = 2; - cmd.rlen = 13; + cmd_init(&cmd, "\xa0\x01", 2, 13); break; case SYS_DVBC_ANNEX_A: - memcpy(cmd.args, "\x90\x01", 2); - cmd.wlen = 2; - cmd.rlen = 9; + cmd_init(&cmd, "\x90\x01", 2, 9); break; case SYS_DVBT2: - memcpy(cmd.args, "\x50\x01", 2); - cmd.wlen = 2; - cmd.rlen = 14; + cmd_init(&cmd, "\x50\x01", 2, 14); break; default: ret = -EINVAL; @@ -175,9 +172,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) /* BER */ if (*status & FE_HAS_VITERBI) { - memcpy(cmd.args, "\x82\x00", 2); - cmd.wlen = 2; - cmd.rlen = 3; + cmd_init(&cmd, "\x82\x00", 2, 3); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -208,9 +203,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) /* UCB */ if (*status & FE_HAS_SYNC) { - memcpy(cmd.args, "\x84\x01", 2); - cmd.wlen = 2; - cmd.rlen = 3; + cmd_init(&cmd, "\x84\x01", 2, 3); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -296,22 +289,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe) goto err; } - memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); - cmd.wlen = 5; - cmd.rlen = 5; + cmd_init(&cmd, "\x88\x02\x02\x02\x02", 5, 5); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; /* that has no big effect */ if (c->delivery_system == SYS_DVBT) - memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6); + cmd_init(&cmd, "\x89\x21\x06\x11\xff\x98", 6, 3); else if (c->delivery_system == SYS_DVBC_ANNEX_A) - memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6); + cmd_init(&cmd, "\x89\x21\x06\x11\x89\xf0", 6, 3); else if (c->delivery_system == SYS_DVBT2) - memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); - cmd.wlen = 6; - cmd.rlen = 3; + cmd_init(&cmd, "\x89\x21\x06\x11\x89\x20", 6, 3); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -328,103 +317,77 @@ static int si2168_set_frontend(struct dvb_frontend *fe) goto err; } - memcpy(cmd.args, "\x51\x03", 2); - cmd.wlen = 2; - cmd.rlen = 12; + cmd_init(&cmd, "\x51\x03", 2, 12); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x12\x08\x04", 3); - cmd.wlen = 3; - cmd.rlen = 3; + cmd_init(&cmd, "\x12\x08\x04", 3, 3); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x0c\x10\x12\x00", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x06\x10\x24\x00", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x07\x10\x00\x24", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6); + cmd_init(&cmd, "\x14\x00\x0a\x10\x00\x00", 6, 4); cmd.args[4] = delivery_system | bandwidth; if (dev->spectral_inversion) cmd.args[5] |= 1; - cmd.wlen = 6; - cmd.rlen = 4; ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; /* set DVB-C symbol rate */ if (c->delivery_system == SYS_DVBC_ANNEX_A) { - memcpy(cmd.args, "\x14\x00\x02\x11", 4); + cmd_init(&cmd, "\x14\x00\x02\x11\x00\x00", 6, 4); cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff; cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; - cmd.wlen = 6; - cmd.rlen = 4; ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; } - memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x0f\x10\x10\x00", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6); + cmd_init(&cmd, "\x14\x00\x09\x10\xe3\x08", 6, 4); cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; - cmd.wlen = 6; - cmd.rlen = 4; ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6); + cmd_init(&cmd, "\x14\x00\x08\x10\xd7\x05", 6, 4); cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; - cmd.wlen = 6; - cmd.rlen = 4; ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x01\x12\x00\x00", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6); - cmd.wlen = 6; - cmd.rlen = 4; + cmd_init(&cmd, "\x14\x00\x01\x03\x0c\x00", 6, 4); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; - memcpy(cmd.args, "\x85", 1); - cmd.wlen = 1; - cmd.rlen = 1; + cmd_init(&cmd, "\x85", 1, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -454,26 +417,21 @@ static int si2168_init(struct dvb_frontend *fe) dev_dbg(&client->dev, "\n"); /* initialize */ - memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); - cmd.wlen = 13; - cmd.rlen = 0; + cmd_init(&cmd, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", + 13, 0); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; if (dev->warm) { /* resume */ - memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); - cmd.wlen = 8; - cmd.rlen = 1; + cmd_init(&cmd, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; udelay(100); - memcpy(cmd.args, "\x85", 1); - cmd.wlen = 1; - cmd.rlen = 1; + cmd_init(&cmd, "\x85", 1, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -482,9 +440,7 @@ static int si2168_init(struct dvb_frontend *fe) } /* power up */ - memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); - cmd.wlen = 8; - cmd.rlen = 1; + cmd_init(&cmd, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -522,9 +478,8 @@ static int si2168_init(struct dvb_frontend *fe) ret = -EINVAL; break; } - memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); - cmd.wlen = len; - cmd.rlen = 1; + cmd_init(&cmd, &fw->data[(fw->size - remaining) + 1], + len, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) break; @@ -532,10 +487,7 @@ static int si2168_init(struct dvb_frontend *fe) } else if (fw->size % 8 == 0) { /* firmware is in the old format */ for (remaining = fw->size; remaining > 0; remaining -= 8) { - len = 8; - memcpy(cmd.args, &fw->data[fw->size - remaining], len); - cmd.wlen = len; - cmd.rlen = 1; + cmd_init(&cmd, &fw->data[fw->size - remaining], 8, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) break; @@ -552,17 +504,13 @@ static int si2168_init(struct dvb_frontend *fe) release_firmware(fw); - memcpy(cmd.args, "\x01\x01", 2); - cmd.wlen = 2; - cmd.rlen = 1; + cmd_init(&cmd, "\x01\x01", 2, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; /* query firmware version */ - memcpy(cmd.args, "\x11", 1); - cmd.wlen = 1; - cmd.rlen = 10; + cmd_init(&cmd, "\x11", 1, 10); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -620,9 +568,7 @@ static int si2168_sleep(struct dvb_frontend *fe) if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0)) dev->warm = false; - memcpy(cmd.args, "\x13", 1); - cmd.wlen = 1; - cmd.rlen = 0; + cmd_init(&cmd, "\x13", 1, 0); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -648,9 +594,7 @@ static int si2168_select(struct i2c_mux_core *muxc, u32 chan) struct si2168_cmd cmd; /* open I2C gate */ - memcpy(cmd.args, "\xc0\x0d\x01", 3); - cmd.wlen = 3; - cmd.rlen = 0; + cmd_init(&cmd, "\xc0\x0d\x01", 3, 0); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -668,9 +612,7 @@ static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan) struct si2168_cmd cmd; /* close I2C gate */ - memcpy(cmd.args, "\xc0\x0d\x00", 3); - cmd.wlen = 3; - cmd.rlen = 0; + cmd_init(&cmd, "\xc0\x0d\x00", 3, 0); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -741,25 +683,20 @@ static int si2168_probe(struct i2c_client *client, mutex_init(&dev->i2c_mutex); /* Initialize */ - memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); - cmd.wlen = 13; - cmd.rlen = 0; + cmd_init(&cmd, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", + 13, 0); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err_kfree; /* Power up */ - memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); - cmd.wlen = 8; - cmd.rlen = 1; + cmd_init(&cmd, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8, 1); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err_kfree; /* Query chip revision */ - memcpy(cmd.args, "\x02", 1); - cmd.wlen = 1; - cmd.rlen = 13; + cmd_init(&cmd, "\x02", 1, 13); ret = si2168_cmd_execute(client, &cmd); if (ret) goto err_kfree; -- GitLab From 9b9e9e5b461789668ce0271f968d8eb5c5d3a332 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 15 Aug 2019 11:59:11 -0300 Subject: [PATCH 3928/7155] media: rc: add keymap for Amediatech X96-MAX remote The X96-Max Android STB ships with a simple NEC remote. It includes a TV section with preset buttons for controlling a TV. These are not configurable, but are noted to aid visual recognition of the device. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-x96max.c | 83 ++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 85 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-x96max.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 5b1399af6b3a..b88c4e76cdc6 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -117,4 +117,5 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-winfast-usbii-deluxe.o \ rc-su3000.o \ rc-xbox-dvd.o \ + rc-x96max.o \ rc-zx-irdec.o diff --git a/drivers/media/rc/keymaps/rc-x96max.c b/drivers/media/rc/keymaps/rc-x96max.c new file mode 100644 index 000000000000..0998ec3320e4 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-x96max.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2019 Christian Hewitt + +#include +#include + +// +// Keytable for the X96-max STB remote control +// + +static struct rc_map_table x96max[] = { + { 0x140, KEY_POWER }, + + // ** TV CONTROL ** + // SET + // AV/TV + // POWER + // VOLUME UP + // VOLUME DOWN + + { 0x118, KEY_VOLUMEUP }, + { 0x110, KEY_VOLUMEDOWN }, + + { 0x143, KEY_MUTE }, // config + + { 0x100, KEY_EPG }, // mouse + { 0x119, KEY_BACK }, + + { 0x116, KEY_UP }, + { 0x151, KEY_LEFT }, + { 0x150, KEY_RIGHT }, + { 0x11a, KEY_DOWN }, + { 0x113, KEY_OK }, + + { 0x111, KEY_HOME }, + { 0x14c, KEY_CONTEXT_MENU }, + + { 0x159, KEY_PREVIOUS }, + { 0x15a, KEY_PLAYPAUSE }, + { 0x158, KEY_NEXT }, + + { 0x147, KEY_MENU }, // @ key + { 0x101, KEY_NUMERIC_0 }, + { 0x142, KEY_BACKSPACE }, + + { 0x14e, KEY_NUMERIC_1 }, + { 0x10d, KEY_NUMERIC_2 }, + { 0x10c, KEY_NUMERIC_3 }, + + { 0x14a, KEY_NUMERIC_4 }, + { 0x109, KEY_NUMERIC_5 }, + { 0x108, KEY_NUMERIC_6 }, + + { 0x146, KEY_NUMERIC_7 }, + { 0x105, KEY_NUMERIC_8 }, + { 0x104, KEY_NUMERIC_9 }, +}; + +static struct rc_map_list x96max_map = { + .map = { + .scan = x96max, + .size = ARRAY_SIZE(x96max), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_X96MAX, + } +}; + +static int __init init_rc_map_x96max(void) +{ + return rc_map_register(&x96max_map); +} + +static void __exit exit_rc_map_x96max(void) +{ + rc_map_unregister(&x96max_map); +} + +module_init(init_rc_map_x96max) +module_exit(exit_rc_map_x96max) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt Date: Thu, 15 Aug 2019 11:59:12 -0300 Subject: [PATCH 3929/7155] media: rc: add keymap for Khadas VIM/EDGE remote Khadas VIM and Edge SBC devices use the same NEC remote device. The remote includes a mouse button for Android use. This has been mapped to KEY_MUTE. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-khadas.c | 54 ++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 56 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-khadas.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index b88c4e76cdc6..39192b0abf91 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-it913x-v1.o \ rc-it913x-v2.o \ rc-kaiomy.o \ + rc-khadas.o \ rc-kworld-315u.o \ rc-kworld-pc150u.o \ rc-kworld-plus-tv-analog.o \ diff --git a/drivers/media/rc/keymaps/rc-khadas.c b/drivers/media/rc/keymaps/rc-khadas.c new file mode 100644 index 000000000000..ce4938444d90 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-khadas.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2019 Christian Hewitt + +/* + * Keytable for the Khadas VIM/EDGE SBC remote control + */ + +#include +#include + +static struct rc_map_table khadas[] = { + { 0x14, KEY_POWER }, + + { 0x03, KEY_UP }, + { 0x02, KEY_DOWN }, + { 0x0e, KEY_LEFT }, + { 0x1a, KEY_RIGHT }, + { 0x07, KEY_OK }, + + { 0x01, KEY_BACK }, + { 0x5b, KEY_MUTE }, // mouse + { 0x13, KEY_MENU }, + + { 0x58, KEY_VOLUMEDOWN }, + { 0x0b, KEY_VOLUMEUP }, + + { 0x48, KEY_HOME }, +}; + +static struct rc_map_list khadas_map = { + .map = { + .scan = khadas, + .size = ARRAY_SIZE(khadas), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_KHADAS, + } +}; + +static int __init init_rc_map_khadas(void) +{ + return rc_map_register(&khadas_map); +} + +static void __exit exit_rc_map_khadas(void) +{ + rc_map_unregister(&khadas_map); +} + +module_init(init_rc_map_khadas) +module_exit(exit_rc_map_khadas) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index bff5a6b4cbc6..9754017518a0 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -211,6 +211,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_IT913X_V1 "rc-it913x-v1" #define RC_MAP_IT913X_V2 "rc-it913x-v2" #define RC_MAP_KAIOMY "rc-kaiomy" +#define RC_MAP_KHADAS "rc-khadas" #define RC_MAP_KWORLD_315U "rc-kworld-315u" #define RC_MAP_KWORLD_PC150U "rc-kworld-pc150u" #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" -- GitLab From e30399e1bd6e215ec20981612646ec73a4385c33 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 15 Aug 2019 11:59:13 -0300 Subject: [PATCH 3930/7155] media: rc: add keymap for Tanix TX3 mini remote The Tanix TX3 mini Android STB ships with a simple NEC remote. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-tanix-tx3mini.c | 77 +++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 79 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-tanix-tx3mini.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 39192b0abf91..31720d842f88 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-snapstream-firefly.o \ rc-streamzap.o \ rc-tango.o \ + rc-tanix-tx3mini.o \ rc-tbs-nec.o \ rc-technisat-ts35.o \ rc-technisat-usb2.o \ diff --git a/drivers/media/rc/keymaps/rc-tanix-tx3mini.c b/drivers/media/rc/keymaps/rc-tanix-tx3mini.c new file mode 100644 index 000000000000..d486cd69afb2 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tanix-tx3mini.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Christian Hewitt + +#include +#include + +/* + * Keymap for the Tanix TX3 mini STB remote control + */ + +static struct rc_map_table tanix_tx3mini[] = { + { 0x8051, KEY_POWER }, + { 0x804d, KEY_MUTE }, + + { 0x8009, KEY_RED }, + { 0x8011, KEY_GREEN }, + { 0x8054, KEY_YELLOW }, + { 0x804f, KEY_BLUE }, + + { 0x8056, KEY_VOLUMEDOWN }, + { 0x80bd, KEY_PREVIOUS }, + { 0x80bb, KEY_NEXT }, + { 0x804e, KEY_VOLUMEUP }, + + { 0x8053, KEY_HOME }, + { 0x801b, KEY_BACK }, + + { 0x8026, KEY_UP }, + { 0x8028, KEY_DOWN }, + { 0x8025, KEY_LEFT }, + { 0x8027, KEY_RIGHT }, + { 0x800d, KEY_OK }, + + { 0x8049, KEY_MENU }, + { 0x8052, KEY_EPG }, // mouse + + { 0x8031, KEY_1 }, + { 0x8032, KEY_2 }, + { 0x8033, KEY_3 }, + + { 0x8034, KEY_4 }, + { 0x8035, KEY_5 }, + { 0x8036, KEY_6 }, + + { 0x8037, KEY_7 }, + { 0x8038, KEY_8 }, + { 0x8039, KEY_9 }, + + { 0x8058, KEY_SUBTITLE }, // 1/a + { 0x8030, KEY_0 }, + { 0x8044, KEY_DELETE }, +}; + +static struct rc_map_list tanix_tx3mini_map = { + .map = { + .scan = tanix_tx3mini, + .size = ARRAY_SIZE(tanix_tx3mini), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_TANIX_TX3MINI, + } +}; + +static int __init init_rc_map_tanix_tx3mini(void) +{ + return rc_map_register(&tanix_tx3mini_map); +} + +static void __exit exit_rc_map_tanix_tx3mini(void) +{ + rc_map_unregister(&tanix_tx3mini_map); +} + +module_init(init_rc_map_tanix_tx3mini) +module_exit(exit_rc_map_tanix_tx3mini) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 9754017518a0..b8929d0c5d6b 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -249,6 +249,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_SNAPSTREAM_FIREFLY "rc-snapstream-firefly" #define RC_MAP_STREAMZAP "rc-streamzap" #define RC_MAP_TANGO "rc-tango" +#define RC_MAP_TANIX_TX3MINI "rc-tanix-tx3mini" #define RC_MAP_TBS_NEC "rc-tbs-nec" #define RC_MAP_TECHNISAT_TS35 "rc-technisat-ts35" #define RC_MAP_TECHNISAT_USB2 "rc-technisat-usb2" -- GitLab From 7bb53f361c59b68e521a05fce579ccfa8021c3a0 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 15 Aug 2019 11:59:14 -0300 Subject: [PATCH 3931/7155] media: rc: add keymap for Tanix TX5 max remote The Tanix TX5 max Android STB ships with a simple NEC remote. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-tanix-tx5max.c | 68 ++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 70 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-tanix-tx5max.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 31720d842f88..85423cc84149 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-streamzap.o \ rc-tango.o \ rc-tanix-tx3mini.o \ + rc-tanix-tx5max.o \ rc-tbs-nec.o \ rc-technisat-ts35.o \ rc-technisat-usb2.o \ diff --git a/drivers/media/rc/keymaps/rc-tanix-tx5max.c b/drivers/media/rc/keymaps/rc-tanix-tx5max.c new file mode 100644 index 000000000000..59aaabed80dd --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tanix-tx5max.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Christian Hewitt + +#include +#include + +/* + * Keymap for the Tanix TX5 max STB remote control + */ + +static struct rc_map_table tanix_tx5max[] = { + { 0x40404d, KEY_POWER }, + { 0x404043, KEY_MUTE }, + + { 0x404017, KEY_VOLUMEDOWN }, + { 0x404018, KEY_VOLUMEUP }, + + { 0x40400b, KEY_UP }, + { 0x404010, KEY_LEFT }, + { 0x404011, KEY_RIGHT }, + { 0x40400e, KEY_DOWN }, + { 0x40400d, KEY_OK }, + + { 0x40401a, KEY_HOME }, + { 0x404045, KEY_MENU }, + { 0x404042, KEY_BACK }, + + { 0x404001, KEY_1 }, + { 0x404002, KEY_2 }, + { 0x404003, KEY_3 }, + + { 0x404004, KEY_4 }, + { 0x404005, KEY_5 }, + { 0x404006, KEY_6 }, + + { 0x404007, KEY_7 }, + { 0x404008, KEY_8 }, + { 0x404009, KEY_9 }, + + { 0x404047, KEY_SUBTITLE }, // mouse + { 0x404000, KEY_0 }, + { 0x40400c, KEY_DELETE }, +}; + +static struct rc_map_list tanix_tx5max_map = { + .map = { + .scan = tanix_tx5max, + .size = ARRAY_SIZE(tanix_tx5max), + .rc_proto = RC_PROTO_NECX, + .name = RC_MAP_TANIX_TX5MAX, + } +}; + +static int __init init_rc_map_tanix_tx5max(void) +{ + return rc_map_register(&tanix_tx5max_map); +} + +static void __exit exit_rc_map_tanix_tx5max(void) +{ + rc_map_unregister(&tanix_tx5max_map); +} + +module_init(init_rc_map_tanix_tx5max) +module_exit(exit_rc_map_tanix_tx5max) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index b8929d0c5d6b..a2ebe4868567 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -250,6 +250,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_STREAMZAP "rc-streamzap" #define RC_MAP_TANGO "rc-tango" #define RC_MAP_TANIX_TX3MINI "rc-tanix-tx3mini" +#define RC_MAP_TANIX_TX5MAX "rc-tanix-tx5max" #define RC_MAP_TBS_NEC "rc-tbs-nec" #define RC_MAP_TECHNISAT_TS35 "rc-technisat-ts35" #define RC_MAP_TECHNISAT_USB2 "rc-technisat-usb2" -- GitLab From 373078971272e9dfcb5f80e309f148a88e36dba8 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 15 Aug 2019 11:59:15 -0300 Subject: [PATCH 3932/7155] media: rc: add keymap for WeTek Hub remote The WeTek Hub Android STB ships with a simple NEC remote. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-wetek-hub.c | 53 +++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 55 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-wetek-hub.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 85423cc84149..6d744aca74a2 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -116,6 +116,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-videomate-m1f.o \ rc-videomate-s350.o \ rc-videomate-tv-pvr.o \ + rc-wetek-hub.o \ rc-winfast.o \ rc-winfast-usbii-deluxe.o \ rc-su3000.o \ diff --git a/drivers/media/rc/keymaps/rc-wetek-hub.c b/drivers/media/rc/keymaps/rc-wetek-hub.c new file mode 100644 index 000000000000..b5a21aff45f5 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-wetek-hub.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Christian Hewitt + +#include +#include + +/* + * This keymap is used with the WeTek Hub STB. + */ + +static struct rc_map_table wetek_hub[] = { + { 0x77f1, KEY_POWER }, + + { 0x77f2, KEY_HOME }, + { 0x77f3, KEY_MUTE }, // mouse + + { 0x77f4, KEY_UP }, + { 0x77f5, KEY_DOWN }, + { 0x77f6, KEY_LEFT }, + { 0x77f7, KEY_RIGHT }, + { 0x77f8, KEY_OK }, + + { 0x77f9, KEY_BACK }, + { 0x77fa, KEY_MENU }, + + { 0x77fb, KEY_VOLUMEUP }, + { 0x77fc, KEY_VOLUMEDOWN }, +}; + +static struct rc_map_list wetek_hub_map = { + .map = { + .scan = wetek_hub, + .size = ARRAY_SIZE(wetek_hub), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_WETEK_HUB, + } +}; + +static int __init init_rc_map_wetek_hub(void) +{ + return rc_map_register(&wetek_hub_map); +} + +static void __exit exit_rc_map_wetek_hub(void) +{ + rc_map_unregister(&wetek_hub_map); +} + +module_init(init_rc_map_wetek_hub) +module_exit(exit_rc_map_wetek_hub) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index a2ebe4868567..032e989418ac 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -270,6 +270,7 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_VIDEOMATE_K100 "rc-videomate-k100" #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" +#define RC_MAP_WETEK_HUB "rc-wetek-hub" #define RC_MAP_WINFAST "rc-winfast" #define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe" #define RC_MAP_SU3000 "rc-su3000" -- GitLab From fa992b335aa778db112e91aac19c45e4d914a1f4 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 15 Aug 2019 11:59:16 -0300 Subject: [PATCH 3933/7155] media: rc: add keymap for WeTeK Play 2 remote The WeTek Play 2 Android STB ships with an unusual remote where the main up/down/left/right/enter controls are surrounded with an outer ring of additional keys which are listed in clockwise order. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-wetek-play2.c | 93 +++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 95 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-wetek-play2.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 6d744aca74a2..d316a9966716 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -117,6 +117,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-videomate-s350.o \ rc-videomate-tv-pvr.o \ rc-wetek-hub.o \ + rc-wetek-play2.o \ rc-winfast.o \ rc-winfast-usbii-deluxe.o \ rc-su3000.o \ diff --git a/drivers/media/rc/keymaps/rc-wetek-play2.c b/drivers/media/rc/keymaps/rc-wetek-play2.c new file mode 100644 index 000000000000..bbbb11fa3c11 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-wetek-play2.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2019 Christian Hewitt + +#include +#include + +// +// Keytable for the WeTek Play 2 STB remote control +// + +static struct rc_map_table wetek_play2[] = { + { 0x5e5f02, KEY_POWER }, + { 0x5e5f46, KEY_SLEEP }, // tv + { 0x5e5f10, KEY_MUTE }, + + { 0x5e5f22, KEY_1 }, + { 0x5e5f23, KEY_2 }, + { 0x5e5f24, KEY_3 }, + + { 0x5e5f25, KEY_4 }, + { 0x5e5f26, KEY_5 }, + { 0x5e5f27, KEY_6 }, + + { 0x5e5f28, KEY_7 }, + { 0x5e5f29, KEY_8 }, + { 0x5e5f30, KEY_9 }, + + { 0x5e5f71, KEY_BACK }, + { 0x5e5f21, KEY_0 }, + { 0x5e5f72, KEY_CAPSLOCK }, + + // outer ring clockwide from top + { 0x5e5f03, KEY_HOME }, + { 0x5e5f61, KEY_BACK }, + { 0x5e5f77, KEY_CONFIG }, // mouse + { 0x5e5f83, KEY_EPG }, + { 0x5e5f84, KEY_SCREEN }, // square + { 0x5e5f48, KEY_MENU }, + + // inner ring + { 0x5e5f50, KEY_UP }, + { 0x5e5f4b, KEY_DOWN }, + { 0x5e5f4c, KEY_LEFT }, + { 0x5e5f4d, KEY_RIGHT }, + { 0x5e5f47, KEY_OK }, + + { 0x5e5f44, KEY_VOLUMEUP }, + { 0x5e5f43, KEY_VOLUMEDOWN }, + { 0x5e5f4f, KEY_FAVORITES }, + { 0x5e5f82, KEY_SUBTITLE }, // txt + { 0x5e5f41, KEY_PAGEUP }, + { 0x5e5f42, KEY_PAGEDOWN }, + + { 0x5e5f73, KEY_RED }, + { 0x5e5f74, KEY_GREEN }, + { 0x5e5f75, KEY_YELLOW }, + { 0x5e5f76, KEY_BLUE }, + + { 0x5e5f67, KEY_PREVIOUSSONG }, + { 0x5e5f79, KEY_REWIND }, + { 0x5e5f80, KEY_FASTFORWARD }, + { 0x5e5f81, KEY_NEXTSONG }, + + { 0x5e5f04, KEY_RECORD }, + { 0x5e5f2c, KEY_PLAYPAUSE }, + { 0x5e5f2b, KEY_STOP }, +}; + +static struct rc_map_list wetek_play2_map = { + .map = { + .scan = wetek_play2, + .size = ARRAY_SIZE(wetek_play2), + .rc_proto = RC_PROTO_NECX, + .name = RC_MAP_WETEK_PLAY2, + } +}; + +static int __init init_rc_map_wetek_play2(void) +{ + return rc_map_register(&wetek_play2_map); +} + +static void __exit exit_rc_map_wetek_play2(void) +{ + rc_map_unregister(&wetek_play2_map); +} + +module_init(init_rc_map_wetek_play2) +module_exit(exit_rc_map_wetek_play2) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt Date: Thu, 15 Aug 2019 11:59:17 -0300 Subject: [PATCH 3934/7155] media: rc: add keymap for HardKernel ODROID remote This is a simple NEC remote control device shipped with the HardKernel ODROID range of SBC devices. Signed-off-by: Christian Hewitt Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-odroid.c | 54 ++++++++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 56 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-odroid.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index d316a9966716..a56fc634d2d6 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-nec-terratec-cinergy-xs.o \ rc-norwood.o \ rc-npgtech.o \ + rc-odroid.o \ rc-pctv-sedna.o \ rc-pinnacle-color.o \ rc-pinnacle-grey.o \ diff --git a/drivers/media/rc/keymaps/rc-odroid.c b/drivers/media/rc/keymaps/rc-odroid.c new file mode 100644 index 000000000000..c6fbb64b5c41 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-odroid.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2019 Christian Hewitt + +#include +#include + +// +// Keytable for the HardKernel ODROID remote control +// + +static struct rc_map_table odroid[] = { + { 0xb2dc, KEY_POWER }, + + { 0xb288, KEY_MUTE }, + { 0xb282, KEY_HOME }, + + { 0xb2ca, KEY_UP }, + { 0xb299, KEY_LEFT }, + { 0xb2ce, KEY_OK }, + { 0xb2c1, KEY_RIGHT }, + { 0xb2d2, KEY_DOWN }, + + { 0xb2c5, KEY_MENU }, + { 0xb29a, KEY_BACK }, + + { 0xb281, KEY_VOLUMEDOWN }, + { 0xb280, KEY_VOLUMEUP }, +}; + +static struct rc_map_list odroid_map = { + .map = { + .scan = odroid, + .size = ARRAY_SIZE(odroid), + .rc_proto = RC_PROTO_NEC, + .name = RC_MAP_ODROID, + } +}; + +static int __init init_rc_map_odroid(void) +{ + return rc_map_register(&odroid_map); +} + +static void __exit exit_rc_map_odroid(void) +{ + rc_map_unregister(&odroid_map); +} + +module_init(init_rc_map_odroid) +module_exit(exit_rc_map_odroid) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hewitt Date: Thu, 15 Aug 2019 13:41:19 -0300 Subject: [PATCH 3935/7155] media: mceusb: fix (eliminate) TX IR signal length limit Fix and eliminate mceusb's IR length limit for IR signals transmitted to the MCE IR blaster ports. An IR signal TX exceeding 306 pulse/space samples presently causes -EINVAL return error. There's no such limitation nor error with the MCE device hardware. And valid IR signals exist with more than 400 pulse/space for the control of certain appliances (eg Panasonic ACXA75C00600 air conditioner). The scope of this patch is limited to the mceusb driver. There are still IR signal TX length and time constraints that related modules of rc core (eg LIRC) impose, further up the driver stack. Changes for mceusb_tx_ir(): Converts and sends LIRC IR pulse/space sequence to MCE device IR pulse/space format. Break long length LIRC sequence into multiple (unlimited number of) parts for sending to the MCE device. Reduce kernel stack IR buffer size: 128 (was 384) Increase MCE IR data packet size: 31 (was 5) Zero time LIRC pulse/space no longer copied to MCE IR data. Eliminate overwriting the source/input LIRC IR data in txbuf[]. Eliminate -EINVAL return; return number of IR samples sent (>0) or MCE write error code (<0). New mce_write() and mce_write_callback(): Implements synchronous blocking I/O, with timeout, for writing/sending data to the MCE device. An unlimited multipart IR signal sent to the MCE device faster than real time requires flow control absent with the original mce_request_packet() and mce_async_callback() asynchronous I/O implementation. Also absent is TX error feedback. mce_write() combines and replaces mce_request_packet() and mce_async_callback() with conversion to synchronous I/O. mce_write() returns bytes sent (>0) or MCE device write error (<0). Debug hex dump TX data before processing. Rename mce_async_out() -> mce_command_out(): The original name is misleading with underlying synchronous I/O implementation. Function renamed to mce_command_out(). Changes in mceusb_handle_command(): Add support for MCE device error case MCE_RSP_TX_TIMEOUT "IR TX timeout (TX buffer underrun)" Changes in mceusb_dev_printdata(): Changes support test and debug of multipart TX IR. Add buffer boundary information (offset and buffer size) to TX hex dump. Correct TX trace bug "Raw IR data, 0 pulse/space samples" Add trace for MCE_RSP_TX_TIMEOUT "IR TX timeout (TX buffer underrun)" Other changes: The driver's write to USB device architecture change (async to sync I/O) is significant so we bump DRIVER_VERSION to "1.95" (from "1.94"). Tests: $ cat -n irdata1 | head -3 1 carrier 36000 2 pulse 6350 3 space 6350 $ cat -n irdata1 | tail -3 76 pulse 6350 77 space 6350 78 pulse 6350 $ ir-ctl -s irdata1 [1549021.073612] mceusb 1-1.3:1.0: requesting 36000 HZ carrier [1549021.073635] mceusb 1-1.3:1.0: tx data[0]: 9f 06 01 45 (len=4 sz=4) [1549021.073649] mceusb 1-1.3:1.0: Request carrier of 35714 Hz (period 28us) [1549021.073848] mceusb 1-1.3:1.0: tx done status = 4 (wait = 100, expire = 100 (1000ms), urb->actual_length = 4, urb->status = 0) [1549021.074689] mceusb 1-1.3:1.0: rx data[0]: 9f 06 01 45 (len=4 sz=4) [1549021.074701] mceusb 1-1.3:1.0: Got carrier of 35714 Hz (period 28us) [1549021.102023] mceusb 1-1.3:1.0: tx data[0]: 9f 08 03 (len=3 sz=3) [1549021.102036] mceusb 1-1.3:1.0: Request transmit blaster mask of 0x03 [1549021.102219] mceusb 1-1.3:1.0: tx done status = 3 (wait = 100, expire = 100 (1000ms), urb->actual_length = 3, urb->status = 0) [1549021.131979] mceusb 1-1.3:1.0: tx data[0]: 9e ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f 9e ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f ff 7f 91 ff (len=81 sz=81) [1549021.131992] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples [1549021.133592] mceusb 1-1.3:1.0: tx done status = 81 (wait = 100, expire = 100 (1000ms), urb->actual_length = 81, urb->status = 0) Hex dumps limited to 64 bytes. 0xff is MCE maximum time pulse, 0x7f is MCE maximum time space. $ cat -n irdata2 | head -3 1 carrier 36000 2 pulse 50 3 space 50 $ cat -n irdata2 | tail -3 254 pulse 50 255 space 50 256 pulse 50 $ ir-ctl -s irdata2 [1549306.586998] mceusb 1-1.3:1.0: tx data[0]: 9f 08 03 (len=3 sz=3) [1549306.587015] mceusb 1-1.3:1.0: Request transmit blaster mask of 0x03 [1549306.587252] mceusb 1-1.3:1.0: tx done status = 3 (wait = 100, expire = 100 (1000ms), urb->actual_length = 3, urb->status = 0) [1549306.613275] mceusb 1-1.3:1.0: tx data[0]: 9e 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 9e 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 9e 81 (len=128 sz=128) [1549306.613291] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples [1549306.614837] mceusb 1-1.3:1.0: tx done status = 128 (wait = 100, expire = 100 (1000ms), urb->actual_length = 128, urb->status = 0) [1549306.614861] mceusb 1-1.3:1.0: tx data[0]: 9e 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 9e 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 01 81 9e 01 (len=128 sz=128) [1549306.614869] mceusb 1-1.3:1.0: Raw IR data, 30 pulse/space samples [1549306.620199] mceusb 1-1.3:1.0: tx done status = 128 (wait = 100, expire = 100 (1000ms), urb->actual_length = 128, urb->status = 0) [1549306.620212] mceusb 1-1.3:1.0: tx data[0]: 89 81 01 81 01 81 01 81 01 81 80 (len=11 sz=11) [1549306.620221] mceusb 1-1.3:1.0: Raw IR data, 9 pulse/space samples [1549306.633294] mceusb 1-1.3:1.0: tx done status = 11 (wait = 98, expire = 100 (1000ms), urb->actual_length = 11, urb->status = 0) Hex dumps limited to 64 bytes. 0x81 is MCE minimum time pulse, 0x01 is MCE minimum time space. TX IR part 3 sz=11 shows 20msec I/O blocking delay (100expire - 98wait = 2jiffies) Signed-off-by: A Sun Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 334 ++++++++++++++++++++++---------------- 1 file changed, 196 insertions(+), 138 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index bc74c09ddeb6..3fc9829a9233 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -31,21 +31,22 @@ #include #include -#define DRIVER_VERSION "1.94" +#define DRIVER_VERSION "1.95" #define DRIVER_AUTHOR "Jarod Wilson " #define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ "device driver" #define DRIVER_NAME "mceusb" +#define USB_TX_TIMEOUT 1000 /* in milliseconds */ #define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ #define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ /* MCE constants */ -#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ +#define MCE_IRBUF_SIZE 128 /* TX IR buffer length */ #define MCE_TIME_UNIT 50 /* Approx 50us resolution */ -#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ -#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ -#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ +#define MCE_PACKET_SIZE 31 /* Max length of packet (with header) */ +#define MCE_IRDATA_HEADER (0x80 + MCE_PACKET_SIZE - 1) + /* Actual format is 0x80 + num_bytes */ #define MCE_IRDATA_TRAILER 0x80 /* End of IR data */ #define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ #define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */ @@ -609,9 +610,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, if (len <= skip) return; - dev_dbg(dev, "%cx data: %*ph (length=%d)", - (out ? 't' : 'r'), - min(len, buf_len - offset), buf + offset, len); + dev_dbg(dev, "%cx data[%d]: %*ph (len=%d sz=%d)", + (out ? 't' : 'r'), offset, + min(len, buf_len - offset), buf + offset, len, buf_len); inout = out ? "Request" : "Got"; @@ -733,6 +734,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, case MCE_RSP_CMD_ILLEGAL: dev_dbg(dev, "Illegal PORT_IR command"); break; + case MCE_RSP_TX_TIMEOUT: + dev_dbg(dev, "IR TX timeout (TX buffer underrun)"); + break; default: dev_dbg(dev, "Unknown command 0x%02x 0x%02x", cmd, subcmd); @@ -747,13 +751,14 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, dev_dbg(dev, "End of raw IR data"); else if ((cmd != MCE_CMD_PORT_IR) && ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA)) - dev_dbg(dev, "Raw IR data, %d pulse/space samples", ir->rem); + dev_dbg(dev, "Raw IR data, %d pulse/space samples", + cmd & MCE_PACKET_LENGTH_MASK); #endif } /* * Schedule work that can't be done in interrupt handlers - * (mceusb_dev_recv() and mce_async_callback()) nor tasklets. + * (mceusb_dev_recv() and mce_write_callback()) nor tasklets. * Invokes mceusb_deferred_kevent() for recovering from * error events specified by the kevent bit field. */ @@ -773,23 +778,80 @@ static void mceusb_defer_kevent(struct mceusb_dev *ir, int kevent) dev_dbg(ir->dev, "kevent %d scheduled", kevent); } -static void mce_async_callback(struct urb *urb) +static void mce_write_callback(struct urb *urb) { - struct mceusb_dev *ir; - int len; - if (!urb) return; - ir = urb->context; + complete(urb->context); +} + +/* + * Write (TX/send) data to MCE device USB endpoint out. + * Used for IR blaster TX and MCE device commands. + * + * Return: The number of bytes written (> 0) or errno (< 0). + */ +static int mce_write(struct mceusb_dev *ir, u8 *data, int size) +{ + int ret; + struct urb *urb; + struct device *dev = ir->dev; + unsigned char *buf_out; + struct completion tx_done; + unsigned long expire; + unsigned long ret_wait; + + mceusb_dev_printdata(ir, data, size, 0, size, true); + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (unlikely(!urb)) { + dev_err(dev, "Error: mce write couldn't allocate urb"); + return -ENOMEM; + } + + buf_out = kmalloc(size, GFP_KERNEL); + if (!buf_out) { + usb_free_urb(urb); + return -ENOMEM; + } + + init_completion(&tx_done); + + /* outbound data */ + if (usb_endpoint_xfer_int(ir->usb_ep_out)) + usb_fill_int_urb(urb, ir->usbdev, ir->pipe_out, + buf_out, size, mce_write_callback, &tx_done, + ir->usb_ep_out->bInterval); + else + usb_fill_bulk_urb(urb, ir->usbdev, ir->pipe_out, + buf_out, size, mce_write_callback, &tx_done); + memcpy(buf_out, data, size); + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(dev, "Error: mce write submit urb error = %d", ret); + kfree(buf_out); + usb_free_urb(urb); + return ret; + } + + expire = msecs_to_jiffies(USB_TX_TIMEOUT); + ret_wait = wait_for_completion_timeout(&tx_done, expire); + if (!ret_wait) { + dev_err(dev, "Error: mce write timed out (expire = %lu (%dms))", + expire, USB_TX_TIMEOUT); + usb_kill_urb(urb); + ret = (urb->status == -ENOENT ? -ETIMEDOUT : urb->status); + } else { + ret = urb->status; + } + if (ret >= 0) + ret = urb->actual_length; /* bytes written */ switch (urb->status) { /* success */ case 0: - len = urb->actual_length; - - mceusb_dev_printdata(ir, urb->transfer_buffer, len, - 0, len, true); break; case -ECONNRESET: @@ -799,140 +861,135 @@ static void mce_async_callback(struct urb *urb) break; case -EPIPE: - dev_err(ir->dev, "Error: request urb status = %d (TX HALT)", + dev_err(ir->dev, "Error: mce write urb status = %d (TX HALT)", urb->status); mceusb_defer_kevent(ir, EVENT_TX_HALT); break; default: - dev_err(ir->dev, "Error: request urb status = %d", urb->status); + dev_err(ir->dev, "Error: mce write urb status = %d", + urb->status); break; } - /* the transfer buffer and urb were allocated in mce_request_packet */ - kfree(urb->transfer_buffer); - usb_free_urb(urb); -} - -/* request outgoing (send) usb packet - used to initialize remote */ -static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, - int size) -{ - int res; - struct urb *async_urb; - struct device *dev = ir->dev; - unsigned char *async_buf; + dev_dbg(dev, "tx done status = %d (wait = %lu, expire = %lu (%dms), urb->actual_length = %d, urb->status = %d)", + ret, ret_wait, expire, USB_TX_TIMEOUT, + urb->actual_length, urb->status); - async_urb = usb_alloc_urb(0, GFP_KERNEL); - if (unlikely(!async_urb)) { - dev_err(dev, "Error, couldn't allocate urb!"); - return; - } - - async_buf = kmalloc(size, GFP_KERNEL); - if (!async_buf) { - usb_free_urb(async_urb); - return; - } - - /* outbound data */ - if (usb_endpoint_xfer_int(ir->usb_ep_out)) - usb_fill_int_urb(async_urb, ir->usbdev, ir->pipe_out, - async_buf, size, mce_async_callback, ir, - ir->usb_ep_out->bInterval); - else - usb_fill_bulk_urb(async_urb, ir->usbdev, ir->pipe_out, - async_buf, size, mce_async_callback, ir); - - memcpy(async_buf, data, size); - - dev_dbg(dev, "send request called (size=%#x)", size); + kfree(buf_out); + usb_free_urb(urb); - res = usb_submit_urb(async_urb, GFP_ATOMIC); - if (res) { - dev_err(dev, "send request FAILED! (res=%d)", res); - kfree(async_buf); - usb_free_urb(async_urb); - return; - } - dev_dbg(dev, "send request complete (res=%d)", res); + return ret; } -static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) +static void mce_command_out(struct mceusb_dev *ir, u8 *data, int size) { int rsize = sizeof(DEVICE_RESUME); if (ir->need_reset) { ir->need_reset = false; - mce_request_packet(ir, DEVICE_RESUME, rsize); + mce_write(ir, DEVICE_RESUME, rsize); msleep(10); } - mce_request_packet(ir, data, size); + mce_write(ir, data, size); msleep(10); } -/* Send data out the IR blaster port(s) */ +/* + * Transmit IR out the MCE device IR blaster port(s). + * + * Convert IR pulse/space sequence from LIRC to MCE format. + * Break up a long IR sequence into multiple parts (MCE IR data packets). + * + * u32 txbuf[] consists of IR pulse, space, ..., and pulse times in usec. + * Pulses and spaces are implicit by their position. + * The first IR sample, txbuf[0], is always a pulse. + * + * u8 irbuf[] consists of multiple IR data packets for the MCE device. + * A packet is 1 u8 MCE_IRDATA_HEADER and up to 30 u8 IR samples. + * An IR sample is 1-bit pulse/space flag with 7-bit time + * in MCE time units (50usec). + * + * Return: The number of IR samples sent (> 0) or errno (< 0). + */ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) { struct mceusb_dev *ir = dev->priv; - int i, length, ret = 0; - int cmdcount = 0; - unsigned char cmdbuf[MCE_CMDBUF_SIZE]; - - /* MCE tx init header */ - cmdbuf[cmdcount++] = MCE_CMD_PORT_IR; - cmdbuf[cmdcount++] = MCE_CMD_SETIRTXPORTS; - cmdbuf[cmdcount++] = ir->tx_mask; + u8 cmdbuf[3] = { MCE_CMD_PORT_IR, MCE_CMD_SETIRTXPORTS, 0x00 }; + u8 irbuf[MCE_IRBUF_SIZE]; + int ircount = 0; + unsigned int irsample; + int i, length, ret; /* Send the set TX ports command */ - mce_async_out(ir, cmdbuf, cmdcount); - cmdcount = 0; - - /* Generate mce packet data */ - for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { - txbuf[i] = txbuf[i] / MCE_TIME_UNIT; - - do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ - - /* Insert mce packet header every 4th entry */ - if ((cmdcount < MCE_CMDBUF_SIZE) && - (cmdcount % MCE_CODE_LENGTH) == 0) - cmdbuf[cmdcount++] = MCE_IRDATA_HEADER; - - /* Insert mce packet data */ - if (cmdcount < MCE_CMDBUF_SIZE) - cmdbuf[cmdcount++] = - (txbuf[i] < MCE_PULSE_BIT ? - txbuf[i] : MCE_MAX_PULSE_LENGTH) | - (i & 1 ? 0x00 : MCE_PULSE_BIT); - else { - ret = -EINVAL; - goto out; + cmdbuf[2] = ir->tx_mask; + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); + + /* Generate mce IR data packet */ + for (i = 0; i < count; i++) { + irsample = txbuf[i] / MCE_TIME_UNIT; + + /* loop to support long pulses/spaces > 6350us (127*50us) */ + while (irsample > 0) { + /* Insert IR header every 30th entry */ + if (ircount % MCE_PACKET_SIZE == 0) { + /* Room for IR header and one IR sample? */ + if (ircount >= MCE_IRBUF_SIZE - 1) { + /* Send near full buffer */ + ret = mce_write(ir, irbuf, ircount); + if (ret < 0) + return ret; + ircount = 0; + } + irbuf[ircount++] = MCE_IRDATA_HEADER; } - } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && - (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); - } - - /* Check if we have room for the empty packet at the end */ - if (cmdcount >= MCE_CMDBUF_SIZE) { - ret = -EINVAL; - goto out; - } + /* Insert IR sample */ + if (irsample <= MCE_MAX_PULSE_LENGTH) { + irbuf[ircount] = irsample; + irsample = 0; + } else { + irbuf[ircount] = MCE_MAX_PULSE_LENGTH; + irsample -= MCE_MAX_PULSE_LENGTH; + } + /* + * Even i = IR pulse + * Odd i = IR space + */ + irbuf[ircount] |= (i & 1 ? 0 : MCE_PULSE_BIT); + ircount++; + + /* IR buffer full? */ + if (ircount >= MCE_IRBUF_SIZE) { + /* Fix packet length in last header */ + length = ircount % MCE_PACKET_SIZE; + if (length > 0) + irbuf[ircount - length] -= + MCE_PACKET_SIZE - length; + /* Send full buffer */ + ret = mce_write(ir, irbuf, ircount); + if (ret < 0) + return ret; + ircount = 0; + } + } + } /* after for loop, 0 <= ircount < MCE_IRBUF_SIZE */ /* Fix packet length in last header */ - length = cmdcount % MCE_CODE_LENGTH; - cmdbuf[cmdcount - length] -= MCE_CODE_LENGTH - length; + length = ircount % MCE_PACKET_SIZE; + if (length > 0) + irbuf[ircount - length] -= MCE_PACKET_SIZE - length; - /* All mce commands end with an empty packet (0x80) */ - cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER; + /* Append IR trailer (0x80) to final partial (or empty) IR buffer */ + irbuf[ircount++] = MCE_IRDATA_TRAILER; - /* Transmit the command to the mce device */ - mce_async_out(ir, cmdbuf, cmdcount); + /* Send final buffer */ + ret = mce_write(ir, irbuf, ircount); + if (ret < 0) + return ret; -out: - return ret ? ret : count; + return count; } /* Sets active IR outputs -- mce devices typically have two */ @@ -972,7 +1029,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) cmdbuf[2] = MCE_CMD_SIG_END; cmdbuf[3] = MCE_IRDATA_TRAILER; dev_dbg(ir->dev, "disabling carrier modulation"); - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); return 0; } @@ -986,7 +1043,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) carrier); /* Transmit new carrier to mce device */ - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); return 0; } } @@ -1009,10 +1066,10 @@ static int mceusb_set_timeout(struct rc_dev *dev, unsigned int timeout) cmdbuf[2] = units >> 8; cmdbuf[3] = units; - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); /* get receiver timeout value */ - mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); + mce_command_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); return 0; } @@ -1037,7 +1094,7 @@ static int mceusb_set_rx_wideband(struct rc_dev *dev, int enable) ir->wideband_rx_enabled = false; cmdbuf[2] = 1; /* port 1 is long range receiver */ } - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); /* response from device sets ir->learning_active */ return 0; @@ -1060,7 +1117,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable) ir->carrier_report_enabled = true; if (!ir->learning_active) { cmdbuf[2] = 2; /* port 2 is short range receiver */ - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); } } else { ir->carrier_report_enabled = false; @@ -1071,7 +1128,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable) */ if (ir->learning_active && !ir->wideband_rx_enabled) { cmdbuf[2] = 1; /* port 1 is long range receiver */ - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); } } @@ -1150,6 +1207,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) } break; case MCE_RSP_CMD_ILLEGAL: + case MCE_RSP_TX_TIMEOUT: ir->need_reset = true; break; default: @@ -1288,7 +1346,7 @@ static void mceusb_get_emulator_version(struct mceusb_dev *ir) { /* If we get no reply or an illegal command reply, its ver 1, says MS */ ir->emver = 1; - mce_async_out(ir, GET_EMVER, sizeof(GET_EMVER)); + mce_command_out(ir, GET_EMVER, sizeof(GET_EMVER)); } static void mceusb_gen1_init(struct mceusb_dev *ir) @@ -1334,10 +1392,10 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) dev_dbg(dev, "set handshake - retC = %d", ret); /* device resume */ - mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); + mce_command_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); /* get hw/sw revision? */ - mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); + mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION)); kfree(data); } @@ -1345,13 +1403,13 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) static void mceusb_gen2_init(struct mceusb_dev *ir) { /* device resume */ - mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); + mce_command_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME)); /* get wake version (protocol, key, address) */ - mce_async_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION)); + mce_command_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION)); /* unknown what this one actually returns... */ - mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); + mce_command_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); } static void mceusb_get_parameters(struct mceusb_dev *ir) @@ -1365,24 +1423,24 @@ static void mceusb_get_parameters(struct mceusb_dev *ir) ir->num_rxports = 2; /* get number of tx and rx ports */ - mce_async_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS)); + mce_command_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS)); /* get the carrier and frequency */ - mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); + mce_command_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); if (ir->num_txports && !ir->flags.no_tx) /* get the transmitter bitmask */ - mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); + mce_command_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); /* get receiver timeout value */ - mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); + mce_command_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); /* get receiver sensor setting */ - mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); + mce_command_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); for (i = 0; i < ir->num_txports; i++) { cmdbuf[2] = i; - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + mce_command_out(ir, cmdbuf, sizeof(cmdbuf)); } } @@ -1391,7 +1449,7 @@ static void mceusb_flash_led(struct mceusb_dev *ir) if (ir->emver < 2) return; - mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED)); + mce_command_out(ir, FLASH_LED, sizeof(FLASH_LED)); } /* -- GitLab From 8c3d3cdbd5dde9bc87d556d2daa9d771ac5254dc Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Sat, 17 Aug 2019 03:42:24 -0300 Subject: [PATCH 3936/7155] media: dvb-frontends: fix memory leaks In dib7000pc_detection(), 'tx' and 'rx' are allocated through kzalloc() respectively. However, if DiB7000PC is detected, they are not deallocated, leading to memory leaks. To fix this issue, create a label to free 'tx' and 'rx' before returning from the function. Signed-off-by: Wenwen Wang Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib7000p.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 52f5e697c5dc..0d22c700016d 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2036,7 +2036,8 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap) if (i2c_transfer(i2c_adap, msg, 2) == 2) if (rx[0] == 0x01 && rx[1] == 0xb3) { dprintk("-D- DiB7000PC detected\n"); - return 1; + ret = 1; + goto out; } msg[0].addr = msg[1].addr = 0x40; @@ -2044,11 +2045,13 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap) if (i2c_transfer(i2c_adap, msg, 2) == 2) if (rx[0] == 0x01 && rx[1] == 0xb3) { dprintk("-D- DiB7000PC detected\n"); - return 1; + ret = 1; + goto out; } dprintk("-D- DiB7000PC not detected\n"); +out: kfree(rx); rx_memory_error: kfree(tx); -- GitLab From 2f6451ed8b5223a28eab81116dd2f901c0dc9f4a Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Sat, 17 Aug 2019 04:04:04 -0300 Subject: [PATCH 3937/7155] media: dvb-frontends: fix a memory leak bug In cx24117_load_firmware(), 'buf' is allocated through kmalloc() to hold the firmware. However, if i2c_transfer() fails, it is not deallocated, leading to a memory leak bug. Signed-off-by: Wenwen Wang Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cx24117.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 42697a5999f7..9fccc906d85a 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -619,8 +619,10 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, /* send fw */ ret = i2c_transfer(state->priv->i2c, &msg, 1); - if (ret < 0) + if (ret < 0) { + kfree(buf); return ret; + } kfree(buf); -- GitLab From b1da86fce4299ab1060a5e878696d29ce29fed6e Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sat, 17 Aug 2019 09:02:40 -0300 Subject: [PATCH 3938/7155] media: ttpci: unknown protocol is rc-mm-32 This protocol responds to a real philips rc-mm remote; it does not respond to IR encoded with the encoder in ir-rcmm-decoder.c. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/av7110_ir.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c index 432789a3c312..a851ba328e4a 100644 --- a/drivers/media/pci/ttpci/av7110_ir.c +++ b/drivers/media/pci/ttpci/av7110_ir.c @@ -37,12 +37,10 @@ void av7110_ir_handler(struct av7110 *av7110, u32 ircom) proto = RC_PROTO_RC5; break; - case IR_RCMM: /* RCMM: ? bits device address, ? bits command */ - command = ircom & 0xff; - addr = (ircom >> 8) & 0x1f; - scancode = ircom; + case IR_RCMM: /* RCMM: 32 bits scancode */ + scancode = ircom & ~0x8000; toggle = ircom & 0x8000; - proto = RC_PROTO_UNKNOWN; + proto = RC_PROTO_RCMM32; break; case IR_RC5_EXT: @@ -83,9 +81,9 @@ static int change_protocol(struct rc_dev *rcdev, u64 *rc_type) struct av7110 *av7110 = rcdev->priv; u32 ir_config; - if (*rc_type & RC_PROTO_BIT_UNKNOWN) { + if (*rc_type & RC_PROTO_BIT_RCMM32) { ir_config = IR_RCMM; - *rc_type = RC_PROTO_UNKNOWN; + *rc_type = RC_PROTO_BIT_RCMM32; } else if (*rc_type & RC_PROTO_BIT_RC5) { if (FW_VERSION(av7110->arm_app) >= 0x2620) ir_config = IR_RC5_EXT; @@ -133,7 +131,7 @@ int av7110_ir_init(struct av7110 *av7110) } rcdev->dev.parent = &pci->dev; - rcdev->allowed_protocols = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_UNKNOWN; + rcdev->allowed_protocols = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RCMM32; rcdev->change_protocol = change_protocol; rcdev->map_name = RC_MAP_HAUPPAUGE; rcdev->priv = av7110; -- GitLab From fcd5ce4b3936242e6679875a4d3c3acfc8743e15 Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Sun, 18 Aug 2019 00:45:40 -0300 Subject: [PATCH 3939/7155] media: dvb-core: fix a memory leak bug In dvb_create_media_entity(), 'dvbdev->entity' is allocated through kzalloc(). Then, 'dvbdev->pads' is allocated through kcalloc(). However, if kcalloc() fails, the allocated 'dvbdev->entity' is not deallocated, leading to a memory leak bug. To fix this issue, free 'dvbdev->entity' before returning -ENOMEM. Signed-off-by: Wenwen Wang Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index d7532f5a352a..917fe034af37 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -339,8 +339,10 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, if (npads) { dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), GFP_KERNEL); - if (!dvbdev->pads) + if (!dvbdev->pads) { + kfree(dvbdev->entity); return -ENOMEM; + } } switch (type) { -- GitLab From fe087322f289718a39b4c947adddd1ce0eab801c Mon Sep 17 00:00:00 2001 From: Jan Pieter van Woerkom Date: Thu, 15 Aug 2019 13:41:58 -0300 Subject: [PATCH 3940/7155] media: dvb-usb: remove T230 from cxusb Remove this device from the cxusb driver so it can be added to the dvbsky driver. Signed-off-by: Jan Pieter van Woerkom Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/cxusb.c | 161 ------------------------------ 1 file changed, 161 deletions(-) diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index bac0778f7def..f02fa0a67aa4 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -78,7 +78,6 @@ enum cxusb_table_index { DVICO_BLUEBIRD_DUAL_4_REV_2, CONEXANT_D680_DMB, MYGICA_D689, - MYGICA_T230, NR__cxusb_table_index }; @@ -456,26 +455,6 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return 0; } -static int cxusb_read_status(struct dvb_frontend *fe, - enum fe_status *status) -{ - struct dvb_usb_adapter *adap = (struct dvb_usb_adapter *)fe->dvb->priv; - struct cxusb_state *state = (struct cxusb_state *)adap->dev->priv; - int ret; - - ret = state->fe_read_status(fe, status); - - /* it need resync slave fifo when signal change from unlock to lock.*/ - if ((*status & FE_HAS_LOCK) && (!state->last_lock)) { - mutex_lock(&state->stream_mutex); - cxusb_streaming_ctrl(adap, 1); - mutex_unlock(&state->stream_mutex); - } - - state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; - return ret; -} - static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) { int ep = d->props.generic_bulk_ctrl_endpoint; @@ -1374,86 +1353,6 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) return 0; } -static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct cxusb_state *st = d->priv; - struct i2c_adapter *adapter; - struct i2c_client *client_demod; - struct i2c_client *client_tuner; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; - - /* Select required USB configuration */ - if (usb_set_interface(d->udev, 0, 0) < 0) - err("set interface failed"); - - /* Unblock all USB pipes */ - usb_clear_halt(d->udev, - usb_sndbulkpipe(d->udev, - d->props.generic_bulk_ctrl_endpoint)); - usb_clear_halt(d->udev, - usb_rcvbulkpipe(d->udev, - d->props.generic_bulk_ctrl_endpoint)); - usb_clear_halt(d->udev, - usb_rcvbulkpipe(d->udev, - d->props.adapter[0].fe[0].stream.endpoint)); - - /* attach frontend */ - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &adap->fe_adap[0].fe; - si2168_config.ts_mode = SI2168_TS_PARALLEL; - si2168_config.ts_clock_inv = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strscpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - request_module(info.type); - client_demod = i2c_new_device(&d->i2c_adap, &info); - if (!client_demod || !client_demod->dev.driver) - return -ENODEV; - - if (!try_module_get(client_demod->dev.driver->owner)) { - i2c_unregister_device(client_demod); - return -ENODEV; - } - - st->i2c_client_demod = client_demod; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); - si2157_config.fe = adap->fe_adap[0].fe; - si2157_config.if_port = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strscpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module(info.type); - client_tuner = i2c_new_device(adapter, &info); - if (!client_tuner || !client_tuner->dev.driver) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - return -ENODEV; - } - if (!try_module_get(client_tuner->dev.driver->owner)) { - i2c_unregister_device(client_tuner); - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - return -ENODEV; - } - - st->i2c_client_tuner = client_tuner; - - /* hook fe: need to resync the slave fifo when signal locks. */ - mutex_init(&st->stream_mutex); - st->last_lock = 0; - st->fe_read_status = adap->fe_adap[0].fe->ops.read_status; - adap->fe_adap[0].fe->ops.read_status = cxusb_read_status; - - return 0; -} - /* * DViCO has shipped two devices with the same USB ID, but only one of them * needs a firmware download. Check the device class details to see if they @@ -1633,7 +1532,6 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope static struct dvb_usb_device_properties cxusb_aver_a868r_properties; static struct dvb_usb_device_properties cxusb_d680_dmb_properties; static struct dvb_usb_device_properties cxusb_mygica_d689_properties; -static struct dvb_usb_device_properties cxusb_mygica_t230_properties; static int cxusb_medion_priv_init(struct dvb_usb_device *dvbdev) { @@ -1759,8 +1657,6 @@ static int cxusb_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr) || !dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, THIS_MODULE, NULL, adapter_nr) || - !dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, - THIS_MODULE, NULL, adapter_nr) || 0) return 0; @@ -1862,9 +1758,6 @@ static struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = { [MYGICA_D689] = { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, - [MYGICA_T230] = { - USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) - }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, cxusb_table); @@ -2535,60 +2428,6 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { } }; -static struct dvb_usb_device_properties cxusb_mygica_t230_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = CYPRESS_FX2, - - .size_of_priv = sizeof(struct cxusb_state), - - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = {{ - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mygica_t230_frontend_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, - } }, - }, - }, - - .power_ctrl = cxusb_d680_dmb_power_ctrl, - - .i2c_algo = &cxusb_i2c_algo, - - .generic_bulk_ctrl_endpoint = 0x01, - - .rc.core = { - .rc_interval = 100, - .rc_codes = RC_MAP_D680_DMB, - .module_name = KBUILD_MODNAME, - .rc_query = cxusb_d680_dmb_rc_query, - .allowed_protos = RC_PROTO_BIT_UNKNOWN, - }, - - .num_device_descs = 1, - .devices = { - { - "Mygica T230 DVB-T/T2/C", - { NULL }, - { &cxusb_table[MYGICA_T230], NULL }, - }, - } -}; - static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, -- GitLab From a9547e520b423a4eb89186b86e7afa937405f3a2 Mon Sep 17 00:00:00 2001 From: Jan Pieter van Woerkom Date: Thu, 15 Aug 2019 13:37:33 -0300 Subject: [PATCH 3941/7155] media: dvb-usb: add T230 to dvbsky commit 5fa88151ecdb ("[media] dvb-usb-cxusb: Geniatech T230 - resync TS FIFO after lock") does not solve the problem for all devices. This is the same issue reported on the T230C, which was moved to the dvbsky.c driver to work around this issue in commit 5742240577b6 ("media: dvbsky: MyGica T230C support"). In addition, the cxusb driver causes an oops when unplugging the device while streaming; this problem does not happen any more. Signed-off-by: Jan Pieter van Woerkom Tested-by: James Hutchinson Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvbsky.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index bbfe1cfdc013..617a306f6815 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -552,11 +552,19 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) /* attach tuner */ si2157_config.fe = adap->fe[0]; - si2157_config.if_port = 0; - - state->i2c_client_tuner = dvb_module_probe("si2157", "si2141", - i2c_adapter, - 0x60, &si2157_config); + if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230) { + si2157_config.if_port = 1; + state->i2c_client_tuner = dvb_module_probe("si2157", NULL, + i2c_adapter, + 0x60, + &si2157_config); + } else { + si2157_config.if_port = 0; + state->i2c_client_tuner = dvb_module_probe("si2157", "si2141", + i2c_adapter, + 0x60, + &si2157_config); + } if (!state->i2c_client_tuner) { dvb_module_release(state->i2c_client_demod); return -ENODEV; @@ -778,6 +786,9 @@ static const struct usb_device_id dvbsky_id_table[] = { { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", RC_MAP_DVBSKY) }, + { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230, + &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230", + RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C", RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, -- GitLab From b501b09ae8c02bc38479c18b9ccb9946c6f252dc Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 04:35:42 -0300 Subject: [PATCH 3942/7155] media: dvb-bt8xx: Make variable dst_config constant Static structure dst_config, of type dst_config, is not used except to be assigned as the value of field state of a variable having type dst_state *. In the definition of dst_state, field config is declared as const. Hence dst_config, when assigned to config, cannot be modified. Therefore, make dst_config const as well. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 64df9d491941..02ebd43e672e 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -393,7 +393,7 @@ static struct mt352_config advbt771_samsung_tdtc9251dh0_config = { .demod_init = advbt771_samsung_tdtc9251dh0_demod_init, }; -static struct dst_config dst_config = { +static const struct dst_config dst_config = { .demod_address = 0x55, }; -- GitLab From a37c2efc087ce849e75ee135e1a52fd1fb2f81eb Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 04:36:54 -0300 Subject: [PATCH 3943/7155] media: firewire: Make structure fdtv_ca constant Static structure fdtv_ca, of type dvb_device, is only used when it is passed as the third argument to function dvb_register_device(). However, in the definition of dvb_register_device, the third parameter is declared as constant. Hence make fdtv_ca const as well. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/firewire/firedtv-ci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index a960a0ce9deb..9363d005e2b6 100644 --- a/drivers/media/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c @@ -217,7 +217,7 @@ static const struct file_operations fdtv_ca_fops = { .llseek = noop_llseek, }; -static struct dvb_device fdtv_ca = { +static const struct dvb_device fdtv_ca = { .users = 1, .readers = 1, .writers = 1, -- GitLab From 05fa782e2547e2fa2d9233182abdb406605346e0 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 04:38:18 -0300 Subject: [PATCH 3944/7155] media: ec168: Make structure ec168_props constant The static structure ec168_props, of type dvb_usb_device_properties, is used only once, when it is assigned to field props of the constant structure ec168_driver_info. As this means that ec168_props will never be modified, make it const as well in order to prevent unintended modification of its fields. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/ec168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c index 0c1fef118be4..e30305876840 100644 --- a/drivers/media/usb/dvb-usb-v2/ec168.c +++ b/drivers/media/usb/dvb-usb-v2/ec168.c @@ -309,7 +309,7 @@ static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff) /* DVB USB Driver stuff */ /* bInterfaceNumber 0 is HID * bInterfaceNumber 1 is DVB-T */ -static struct dvb_usb_device_properties ec168_props = { +static const struct dvb_usb_device_properties ec168_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .adapter_nr = adapter_nr, -- GitLab From 6f005abb00848556a6bff1d3bc8a76f7dc2f9c24 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 19 Aug 2019 04:47:01 -0300 Subject: [PATCH 3945/7155] media: dvb-frontends/cxd2099: Make en_templ constant Static structure en_templ, of type dvb_ca_en50221, is not used except to be copied into a local variable. Hence make it const to prevent unintended modification of the original fields. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cxd2099.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c index 5264e873850e..f88b5355493e 100644 --- a/drivers/media/dvb-frontends/cxd2099.c +++ b/drivers/media/dvb-frontends/cxd2099.c @@ -594,7 +594,7 @@ static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) return ecount; } -static struct dvb_ca_en50221 en_templ = { +static const struct dvb_ca_en50221 en_templ = { .read_attribute_mem = read_attribute_mem, .write_attribute_mem = write_attribute_mem, .read_cam_control = read_cam_control, -- GitLab From a10feaf8c464c3f9cfdd3a8a7ce17e1c0d498da1 Mon Sep 17 00:00:00 2001 From: Tomas Bortoli Date: Wed, 31 Jul 2019 12:19:05 -0300 Subject: [PATCH 3946/7155] media: ttusb-dec: Fix info-leak in ttusb_dec_send_command() The function at issue does not always initialize each byte allocated for 'b' and can therefore leak uninitialized memory to a USB device in the call to usb_bulk_msg() Use kzalloc() instead of kmalloc() Signed-off-by: Tomas Bortoli Reported-by: syzbot+0522702e9d67142379f1@syzkaller.appspotmail.com Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/ttusb-dec/ttusb_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 1d0afa340f47..3198f9624b7c 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -319,7 +319,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, dprintk("%s\n", __func__); - b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); + b = kzalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); if (!b) return -ENOMEM; -- GitLab From 7c31b9d6734241480578de0b2c6bfa6d7e85dc96 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 19 Aug 2019 15:26:18 -0300 Subject: [PATCH 3947/7155] media: dt-bindings: media: Add YAML schemas for the generic RC bindings The RC controllers have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/rc.txt | 118 +------------- .../devicetree/bindings/media/rc.yaml | 145 ++++++++++++++++++ 2 files changed, 146 insertions(+), 117 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/rc.yaml diff --git a/Documentation/devicetree/bindings/media/rc.txt b/Documentation/devicetree/bindings/media/rc.txt index d3e7a012bfda..be629f7fa77e 100644 --- a/Documentation/devicetree/bindings/media/rc.txt +++ b/Documentation/devicetree/bindings/media/rc.txt @@ -1,117 +1 @@ -The following properties are common to the infrared remote controllers: - -- linux,rc-map-name: string, specifies the scancode/key mapping table - defined in-kernel for the remote controller. Support values are: - * "rc-adstech-dvb-t-pci" - * "rc-alink-dtu-m" - * "rc-anysee" - * "rc-apac-viewcomp" - * "rc-asus-pc39" - * "rc-asus-ps3-100" - * "rc-ati-tv-wonder-hd-600" - * "rc-ati-x10" - * "rc-avermedia-a16d" - * "rc-avermedia-cardbus" - * "rc-avermedia-dvbt" - * "rc-avermedia-m135a" - * "rc-avermedia-m733a-rm-k6" - * "rc-avermedia-rm-ks" - * "rc-avermedia" - * "rc-avertv-303" - * "rc-azurewave-ad-tu700" - * "rc-behold-columbus" - * "rc-behold" - * "rc-budget-ci-old" - * "rc-cec" - * "rc-cinergy-1400" - * "rc-cinergy" - * "rc-delock-61959" - * "rc-dib0700-nec" - * "rc-dib0700-rc5" - * "rc-digitalnow-tinytwin" - * "rc-digittrade" - * "rc-dm1105-nec" - * "rc-dntv-live-dvbt-pro" - * "rc-dntv-live-dvb-t" - * "rc-dtt200u" - * "rc-dvbsky" - * "rc-empty" - * "rc-em-terratec" - * "rc-encore-enltv2" - * "rc-encore-enltv-fm53" - * "rc-encore-enltv" - * "rc-evga-indtube" - * "rc-eztv" - * "rc-flydvb" - * "rc-flyvideo" - * "rc-fusionhdtv-mce" - * "rc-gadmei-rm008z" - * "rc-geekbox" - * "rc-genius-tvgo-a11mce" - * "rc-gotview7135" - * "rc-hauppauge" - * "rc-imon-mce" - * "rc-imon-pad" - * "rc-iodata-bctv7e" - * "rc-it913x-v1" - * "rc-it913x-v2" - * "rc-kaiomy" - * "rc-kworld-315u" - * "rc-kworld-pc150u" - * "rc-kworld-plus-tv-analog" - * "rc-leadtek-y04g0051" - * "rc-lirc" - * "rc-lme2510" - * "rc-manli" - * "rc-medion-x10" - * "rc-medion-x10-digitainer" - * "rc-medion-x10-or2x" - * "rc-msi-digivox-ii" - * "rc-msi-digivox-iii" - * "rc-msi-tvanywhere-plus" - * "rc-msi-tvanywhere" - * "rc-nebula" - * "rc-nec-terratec-cinergy-xs" - * "rc-norwood" - * "rc-npgtech" - * "rc-pctv-sedna" - * "rc-pinnacle-color" - * "rc-pinnacle-grey" - * "rc-pinnacle-pctv-hd" - * "rc-pixelview-new" - * "rc-pixelview" - * "rc-pixelview-002t" - * "rc-pixelview-mk12" - * "rc-powercolor-real-angel" - * "rc-proteus-2309" - * "rc-purpletv" - * "rc-pv951" - * "rc-hauppauge" - * "rc-rc5-tv" - * "rc-rc6-mce" - * "rc-real-audio-220-32-keys" - * "rc-reddo" - * "rc-snapstream-firefly" - * "rc-streamzap" - * "rc-tbs-nec" - * "rc-technisat-ts35" - * "rc-technisat-usb2" - * "rc-terratec-cinergy-c-pci" - * "rc-terratec-cinergy-s2-hd" - * "rc-terratec-cinergy-xs" - * "rc-terratec-slim" - * "rc-terratec-slim-2" - * "rc-tevii-nec" - * "rc-tivo" - * "rc-total-media-in-hand" - * "rc-total-media-in-hand-02" - * "rc-trekstor" - * "rc-tt-1500" - * "rc-twinhan-dtv-cab-ci" - * "rc-twinhan1027" - * "rc-videomate-k100" - * "rc-videomate-s350" - * "rc-videomate-tv-pvr" - * "rc-winfast" - * "rc-winfast-usbii-deluxe" - * "rc-su3000" +This file has been moved to rc.yaml. diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml new file mode 100644 index 000000000000..3d5c154fd230 --- /dev/null +++ b/Documentation/devicetree/bindings/media/rc.yaml @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/rc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic Infrared Remote Controller Device Tree Bindings + +maintainers: + - Mauro Carvalho Chehab + - Sean Young + +properties: + $nodename: + pattern: "^ir(@[a-f0-9]+)?$" + + linux,rc-map-name: + description: + Specifies the scancode/key mapping table defined in-kernel for + the remote controller. + allOf: + - $ref: '/schemas/types.yaml#/definitions/string' + - enum: + - rc-adstech-dvb-t-pci + - rc-alink-dtu-m + - rc-anysee + - rc-apac-viewcomp + - rc-astrometa-t2hybrid + - rc-asus-pc39 + - rc-asus-ps3-100 + - rc-ati-tv-wonder-hd-600 + - rc-ati-x10 + - rc-avermedia + - rc-avermedia-a16d + - rc-avermedia-cardbus + - rc-avermedia-dvbt + - rc-avermedia-m135a + - rc-avermedia-m733a-rm-k6 + - rc-avermedia-rm-ks + - rc-avertv-303 + - rc-azurewave-ad-tu700 + - rc-behold + - rc-behold-columbus + - rc-budget-ci-old + - rc-cec + - rc-cinergy + - rc-cinergy-1400 + - rc-d680-dmb + - rc-delock-61959 + - rc-dib0700-nec + - rc-dib0700-rc5 + - rc-digitalnow-tinytwin + - rc-digittrade + - rc-dm1105-nec + - rc-dntv-live-dvb-t + - rc-dntv-live-dvbt-pro + - rc-dtt200u + - rc-dvbsky + - rc-dvico-mce + - rc-dvico-portable + - rc-em-terratec + - rc-empty + - rc-encore-enltv + - rc-encore-enltv-fm53 + - rc-encore-enltv2 + - rc-evga-indtube + - rc-eztv + - rc-flydvb + - rc-flyvideo + - rc-fusionhdtv-mce + - rc-gadmei-rm008z + - rc-geekbox + - rc-genius-tvgo-a11mce + - rc-gotview7135 + - rc-hauppauge + - rc-hauppauge + - rc-hisi-poplar + - rc-hisi-tv-demo + - rc-imon-mce + - rc-imon-pad + - rc-imon-rsc + - rc-iodata-bctv7e + - rc-it913x-v1 + - rc-it913x-v2 + - rc-kaiomy + - rc-kworld-315u + - rc-kworld-pc150u + - rc-kworld-plus-tv-analog + - rc-leadtek-y04g0051 + - rc-lme2510 + - rc-manli + - rc-medion-x10 + - rc-medion-x10-digitainer + - rc-medion-x10-or2x + - rc-msi-digivox-ii + - rc-msi-digivox-iii + - rc-msi-tvanywhere + - rc-msi-tvanywhere-plus + - rc-nebula + - rc-nec-terratec-cinergy-xs + - rc-norwood + - rc-npgtech + - rc-pctv-sedna + - rc-pinnacle-color + - rc-pinnacle-grey + - rc-pinnacle-pctv-hd + - rc-pixelview + - rc-pixelview-002t + - rc-pixelview-mk12 + - rc-pixelview-new + - rc-powercolor-real-angel + - rc-proteus-2309 + - rc-purpletv + - rc-pv951 + - rc-rc5-tv + - rc-rc6-mce + - rc-real-audio-220-32-keys + - rc-reddo + - rc-snapstream-firefly + - rc-streamzap + - rc-su3000 + - rc-tango + - rc-tbs-nec + - rc-technisat-ts35 + - rc-technisat-usb2 + - rc-terratec-cinergy-c-pci + - rc-terratec-cinergy-s2-hd + - rc-terratec-cinergy-xs + - rc-terratec-slim + - rc-terratec-slim-2 + - rc-tevii-nec + - rc-tivo + - rc-total-media-in-hand + - rc-total-media-in-hand-02 + - rc-trekstor + - rc-tt-1500 + - rc-twinhan-dtv-cab-ci + - rc-twinhan1027 + - rc-videomate-k100 + - rc-videomate-s350 + - rc-videomate-tv-pvr + - rc-winfast + - rc-winfast-usbii-deluxe + - rc-xbox-dvd + - rc-zx-irdec -- GitLab From 01faced6f65d0224bf6ce1262a4137771e28519f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 19 Aug 2019 15:26:19 -0300 Subject: [PATCH 3948/7155] media: dt-bindings: media: Convert Allwinner A10 IR to a schema The older Allwinner SoCs have a IR receiver supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- .../media/allwinner,sun4i-a10-ir.yaml | 80 +++++++++++++++++++ .../devicetree/bindings/media/sunxi-ir.txt | 35 -------- 2 files changed, 80 insertions(+), 35 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml delete mode 100644 Documentation/devicetree/bindings/media/sunxi-ir.txt diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml new file mode 100644 index 000000000000..98c1bdde9a86 --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/allwinner,sun4i-a10-ir.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Infrared Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +allOf: + - $ref: "rc.yaml#" + +properties: + compatible: + oneOf: + - const: allwinner,sun4i-a10-ir + - const: allwinner,sun5i-a13-ir + - items: + - const: allwinner,sun8i-a83t-ir + - const: allwinner,sun6i-a31-ir + - const: allwinner,sun6i-a31-ir + - items: + - const: allwinner,sun50i-a64-ir + - const: allwinner,sun6i-a31-ir + - items: + - const: allwinner,sun50i-h6-ir + - const: allwinner,sun6i-a31-ir + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: apb + - const: ir + + resets: + maxItems: 1 + + clock-frequency: + default: 8000000 + description: + IR Receiver clock frequency, in Hertz. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +# FIXME: We should set it, but it would report all the generic +# properties as additional properties. +# additionalProperties: false + +examples: + - | + ir0: ir@1c21800 { + compatible = "allwinner,sun4i-a10-ir"; + clocks = <&apb0_gates 6>, <&ir0_clk>; + clock-names = "apb", "ir"; + clock-frequency = <3000000>; + resets = <&apb0_rst 1>; + interrupts = <0 5 1>; + reg = <0x01C21800 0x40>; + linux,rc-map-name = "rc-rc6-mce"; + }; + +... diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt deleted file mode 100644 index 81eaf95fb764..000000000000 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ /dev/null @@ -1,35 +0,0 @@ -Device-Tree bindings for SUNXI IR controller found in sunXi SoC family - -Required properties: -- compatible : - "allwinner,sun4i-a10-ir" - "allwinner,sun5i-a13-ir" - "allwinner,sun6i-a31-ir" - "allwinner,sun50i-a64-ir", "allwinner,sun6i-a31-ir" - "allwinner,sun50i-h6-ir", "allwinner,sun6i-a31-ir" -- clocks : list of clock specifiers, corresponding to - entries in clock-names property; -- clock-names : should contain "apb" and "ir" entries; -- interrupts : should contain IR IRQ number; -- reg : should contain IO map address for IR. - -Required properties since A31: -- resets : phandle + reset specifier pair - -Optional properties: -- linux,rc-map-name: see rc.txt file in the same directory. -- clock-frequency : IR Receiver clock frequency, in Hertz. Defaults to 8 MHz - if missing. - -Example: - -ir0: ir@1c21800 { - compatible = "allwinner,sun4i-a10-ir"; - clocks = <&apb0_gates 6>, <&ir0_clk>; - clock-names = "apb", "ir"; - clock-frequency = <3000000>; - resets = <&apb0_rst 1>; - interrupts = <0 5 1>; - reg = <0x01C21800 0x40>; - linux,rc-map-name = "rc-rc6-mce"; -}; -- GitLab From 45dc1576e4575ba621cb6d017faf41531d8c1073 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 19 Aug 2019 12:35:03 +0200 Subject: [PATCH 3949/7155] ACPI: PM: s2idle: Avoid rearming SCI for wakeup unnecessarily It is only necessary to rearm the ACPI SCI for wakeup if pm_system_cancel_wakeup() has been called, so invoke rearm_wake_irq() only in that case. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 8f7e95f97e1f..c52ecbda863f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -1012,9 +1012,9 @@ static void acpi_s2idle_wake(void) acpi_os_wait_events_complete(); /* synchronize EC GPE processing */ acpi_ec_flush_work(); acpi_os_wait_events_complete(); /* synchronize Notify handling */ - } - rearm_wake_irq(acpi_sci_irq); + rearm_wake_irq(acpi_sci_irq); + } } static void acpi_s2idle_restore_early(void) -- GitLab From b90ff3554aa3e123bb7e6d08789f6fd92d86ddde Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 21 Aug 2019 11:40:19 +0200 Subject: [PATCH 3950/7155] ACPI: PM: s2idle: Always set up EC GPE for system wakeup Commit 10a08fd65ec1 ("ACPI: PM: Set up EC GPE for system wakeup from drivers that need it") assumed that the EC GPE would only need to be set up for system wakeup if either the intel-hid or the intel-vbtn driver was in use, but that turns out to be incorrect. In particular, on ASUS Zenbook UX430UNR/i7-8550U, if the EC GPE is not enabled while suspended, the system cannot be woken up by opening the lid or pressing a key, and that machine doesn't use any of the drivers mentioned above. For this reason, always set up the EC GPE for system wakeup from suspend-to-idle by setting and clearing its wake mask in the ACPI suspend-to-idle callbacks. Fixes: 10a08fd65ec1 ("ACPI: PM: Set up EC GPE for system wakeup from drivers that need it") Reported-by: Kristian Klausen Tested-by: Kristian Klausen Acked-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 1 - drivers/acpi/sleep.c | 15 +++++++++++++-- drivers/platform/x86/intel-hid.c | 6 +----- drivers/platform/x86/intel-vbtn.c | 6 +----- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 58597ec813eb..da1e5c5ce150 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1970,7 +1970,6 @@ void acpi_ec_set_gpe_wake_mask(u8 action) if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); } -EXPORT_SYMBOL_GPL(acpi_ec_set_gpe_wake_mask); bool acpi_ec_dispatch_gpe(void) { diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index c52ecbda863f..9fa77d72ef27 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -938,6 +938,13 @@ static int lps0_device_attach(struct acpi_device *adev, if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) mem_sleep_current = PM_SUSPEND_TO_IDLE; + /* + * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the + * EC GPE to be enabled while suspended for certain wakeup devices to + * work, so mark it as wakeup-capable. + */ + acpi_ec_mark_gpe_for_wake(); + return 0; } @@ -954,8 +961,10 @@ static int acpi_s2idle_begin(void) static int acpi_s2idle_prepare(void) { - if (acpi_sci_irq_valid()) + if (acpi_sci_irq_valid()) { enable_irq_wake(acpi_sci_irq); + acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); + } acpi_enable_wakeup_devices(ACPI_STATE_S0); @@ -1034,8 +1043,10 @@ static void acpi_s2idle_restore(void) acpi_disable_wakeup_devices(ACPI_STATE_S0); - if (acpi_sci_irq_valid()) + if (acpi_sci_irq_valid()) { + acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); disable_irq_wake(acpi_sci_irq); + } } static void acpi_s2idle_end(void) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 18ac237114ff..ef6d4bd77b1a 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -257,7 +257,6 @@ static int intel_hid_pm_prepare(struct device *device) struct intel_hid_priv *priv = dev_get_drvdata(device); priv->wakeup_mode = true; - acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); } return 0; } @@ -266,10 +265,7 @@ static void intel_hid_pm_complete(struct device *device) { struct intel_hid_priv *priv = dev_get_drvdata(device); - if (priv->wakeup_mode) { - acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); - priv->wakeup_mode = false; - } + priv->wakeup_mode = false; } static int intel_hid_pl_suspend_handler(struct device *device) diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index b28e5519337e..b74932307d69 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -205,7 +205,6 @@ static int intel_vbtn_pm_prepare(struct device *dev) struct intel_vbtn_priv *priv = dev_get_drvdata(dev); priv->wakeup_mode = true; - acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); } return 0; } @@ -214,10 +213,7 @@ static void intel_vbtn_pm_complete(struct device *dev) { struct intel_vbtn_priv *priv = dev_get_drvdata(dev); - if (priv->wakeup_mode) { - acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); - priv->wakeup_mode = false; - } + priv->wakeup_mode = false; } static int intel_vbtn_pm_resume(struct device *dev) -- GitLab From e13c6d144fa0fd378c4062459736b4da28555414 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:32 +0530 Subject: [PATCH 3951/7155] arm64: dts: qcom: sm8150: Add base dts file This add base DTS file with cpu, psci, firmware, clock node tlmm and spmi and enables boot to console Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 308 +++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8150.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi new file mode 100644 index 000000000000..417b21d1897c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <38400000>; + clock-output-names = "xo_board"; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32764>; + clock-output-names = "sleep_clk"; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + L3_0: l3-cache { + compatible = "cache"; + }; + }; + }; + + CPU1: cpu@100 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&L2_100>; + L2_100: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + + }; + + CPU2: cpu@200 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x200>; + enable-method = "psci"; + next-level-cache = <&L2_200>; + L2_200: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU3: cpu@300 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x300>; + enable-method = "psci"; + next-level-cache = <&L2_300>; + L2_300: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU4: cpu@400 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x400>; + enable-method = "psci"; + next-level-cache = <&L2_400>; + L2_400: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU5: cpu@500 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x500>; + enable-method = "psci"; + next-level-cache = <&L2_500>; + L2_500: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU6: cpu@600 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x600>; + enable-method = "psci"; + next-level-cache = <&L2_600>; + L2_600: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU7: cpu@700 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x700>; + enable-method = "psci"; + next-level-cache = <&L2_700>; + L2_700: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + }; + + firmware { + scm: scm { + compatible = "qcom,scm-sm8150", "qcom,scm"; + #reset-cells = <1>; + }; + }; + + memory@80000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0x80000000 0x0 0x0>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + soc: soc@0 { + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x10 0>; + dma-ranges = <0 0 0 0 0x10 0>; + compatible = "simple-bus"; + + gcc: clock-controller@100000 { + compatible = "qcom,gcc-sm8150"; + reg = <0x0 0x00100000 0x0 0x1f0000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + clock-names = "bi_tcxo", + "sleep_clk"; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>; + }; + + qupv3_id_1: geniqup@ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00ac0000 0x0 0x6000>; + clock-names = "m-ahb", "s-ahb"; + clocks = <&gcc 123>, + <&gcc 124>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + uart2: serial@a90000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x00a90000 0x0 0x4000>; + clock-names = "se"; + clocks = <&gcc 105>; + interrupts = ; + status = "disabled"; + }; + }; + + tlmm: pinctrl@3100000 { + compatible = "qcom,sm8150-pinctrl"; + reg = <0x0 0x03100000 0x0 0x300000>, + <0x0 0x03500000 0x0 0x300000>, + <0x0 0x03900000 0x0 0x300000>, + <0x0 0x03D00000 0x0 0x300000>; + reg-names = "west", "east", "north", "south"; + interrupts = ; + gpio-ranges = <&tlmm 0 0 175>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + spmi_bus: spmi@c440000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x0c440000 0x0 0x0001100>, + <0x0 0x0c600000 0x0 0x2000000>, + <0x0 0x0e600000 0x0 0x0100000>, + <0x0 0x0e700000 0x0 0x00a0000>, + <0x0 0x0c40a000 0x0 0x0026000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + }; + + intc: interrupt-controller@17a00000 { + compatible = "arm,gic-v3"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x0 0x17a00000 0x0 0x10000>, /* GICD */ + <0x0 0x17a60000 0x0 0x100000>; /* GICR * 8 */ + interrupts = ; + }; + + timer@17c20000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x17c20000 0x0 0x1000>; + clock-frequency = <19200000>; + + frame@17c21000{ + frame-number = <0>; + interrupts = , + ; + reg = <0x0 0x17c21000 0x0 0x1000>, + <0x0 0x17c22000 0x0 0x1000>; + }; + + frame@17c23000 { + frame-number = <1>; + interrupts = ; + reg = <0x0 0x17c23000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c25000 { + frame-number = <2>; + interrupts = ; + reg = <0x0 0x17c25000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c27000 { + frame-number = <3>; + interrupts = ; + reg = <0x0 0x17c26000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c29000 { + frame-number = <4>; + interrupts = ; + reg = <0x0 0x17c29000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c2b000 { + frame-number = <5>; + interrupts = ; + reg = <0x0 0x17c2b000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c2d000 { + frame-number = <6>; + interrupts = ; + reg = <0x0 0x17c2d000 0x0 0x1000>; + status = "disabled"; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; -- GitLab From 5101f22a5c37c01677785f61a3ede97737e7c832 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:33 +0530 Subject: [PATCH 3952/7155] arm64: dts: qcom: pm8150: Add base dts file Add base DTS file for pm8150 along with GPIOs, power-on, rtc and vadc nodes Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm8150.dtsi | 97 ++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pm8150.dtsi diff --git a/arch/arm64/boot/dts/qcom/pm8150.dtsi b/arch/arm64/boot/dts/qcom/pm8150.dtsi new file mode 100644 index 000000000000..b6e304748a57 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pm8150.dtsi @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include + +&spmi_bus { + pm8150_0: pmic@0 { + compatible = "qcom,pm8150", "qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pon: power-on@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x0800>; + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0x0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = ; + + status = "disabled"; + }; + }; + + pm8150_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + status = "disabled"; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + die-temp@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + }; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>; + + status = "disabled"; + }; + + pm8150_gpios: gpio@c000 { + compatible = "qcom,pm8150-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0x0 0xc0 0x0 IRQ_TYPE_NONE>, + <0x0 0xc1 0x0 IRQ_TYPE_NONE>, + <0x0 0xc2 0x0 IRQ_TYPE_NONE>, + <0x0 0xc3 0x0 IRQ_TYPE_NONE>, + <0x0 0xc4 0x0 IRQ_TYPE_NONE>, + <0x0 0xc5 0x0 IRQ_TYPE_NONE>, + <0x0 0xc6 0x0 IRQ_TYPE_NONE>, + <0x0 0xc7 0x0 IRQ_TYPE_NONE>, + <0x0 0xc8 0x0 IRQ_TYPE_NONE>, + <0x0 0xc9 0x0 IRQ_TYPE_NONE>, + <0x0 0xca 0x0 IRQ_TYPE_NONE>, + <0x0 0xcb 0x0 IRQ_TYPE_NONE>; + }; + }; + + pmic@1 { + compatible = "qcom,pm8150", "qcom,spmi-pmic"; + reg = <0x1 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; -- GitLab From 229d5bcad0d038c836dd036aa8dd315a88b48df0 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:34 +0530 Subject: [PATCH 3953/7155] arm64: dts: qcom: pm8150b: Add base dts file PMIC pm8150b is a slave pmic and this adds base DTS file for pm8150b with power-on, adc, and gpio nodes Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm8150b.dtsi | 86 +++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pm8150b.dtsi diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi new file mode 100644 index 000000000000..322379d5c31f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include + +&spmi_bus { + pmic@2 { + compatible = "qcom,pm8150b", "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + power-on@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x0800>; + + status = "disabled"; + }; + + adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + status = "disabled"; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + die-temp@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + + chg-temp@9 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "chg_temp"; + }; + }; + + pm8150b_gpios: gpio@c000 { + compatible = "qcom,pm8150b-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0x2 0xc0 0x0 IRQ_TYPE_NONE>, + <0x2 0xc1 0x0 IRQ_TYPE_NONE>, + <0x2 0xc2 0x0 IRQ_TYPE_NONE>, + <0x2 0xc3 0x0 IRQ_TYPE_NONE>, + <0x2 0xc4 0x0 IRQ_TYPE_NONE>, + <0x2 0xc5 0x0 IRQ_TYPE_NONE>, + <0x2 0xc6 0x0 IRQ_TYPE_NONE>, + <0x2 0xc7 0x0 IRQ_TYPE_NONE>, + <0x2 0xc8 0x0 IRQ_TYPE_NONE>, + <0x2 0xc9 0x0 IRQ_TYPE_NONE>, + <0x2 0xca 0x0 IRQ_TYPE_NONE>, + <0x2 0xcb 0x0 IRQ_TYPE_NONE>; + }; + }; + + pmic@3 { + compatible = "qcom,pm8150b", "qcom,spmi-pmic"; + reg = <0x3 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; -- GitLab From e92b61c8e77596e5cbe0b5e4a96f651ed7fb97fc Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:35 +0530 Subject: [PATCH 3954/7155] arm64: dts: qcom: pm8150l: Add base dts file PMIC pm8150l is a slave pmic and this adds base DTS file for pm8150l with power-on, adc and gpio nodes Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm8150l.dtsi | 80 +++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pm8150l.dtsi diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi new file mode 100644 index 000000000000..eb0e9a090e42 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include + +&spmi_bus { + pmic@4 { + compatible = "qcom,pm8150l", "qcom,spmi-pmic"; + reg = <0x4 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + power-on@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x0800>; + + status = "disabled"; + }; + + adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x4 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + status = "disabled"; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + die-temp@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + }; + + pm8150l_gpios: gpio@c000 { + compatible = "qcom,pm8150l-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0x4 0xc0 0x0 IRQ_TYPE_NONE>, + <0x4 0xc1 0x0 IRQ_TYPE_NONE>, + <0x4 0xc2 0x0 IRQ_TYPE_NONE>, + <0x4 0xc3 0x0 IRQ_TYPE_NONE>, + <0x4 0xc4 0x0 IRQ_TYPE_NONE>, + <0x4 0xc5 0x0 IRQ_TYPE_NONE>, + <0x4 0xc6 0x0 IRQ_TYPE_NONE>, + <0x4 0xc7 0x0 IRQ_TYPE_NONE>, + <0x4 0xc8 0x0 IRQ_TYPE_NONE>, + <0x4 0xc9 0x0 IRQ_TYPE_NONE>, + <0x4 0xca 0x0 IRQ_TYPE_NONE>, + <0x4 0xcb 0x0 IRQ_TYPE_NONE>; + }; + }; + + pmic@5 { + compatible = "qcom,pm8150l", "qcom,spmi-pmic"; + reg = <0x5 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; -- GitLab From 63db27709e48d9981b02511bc73fcc5112b6b038 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:36 +0530 Subject: [PATCH 3955/7155] arm64: dts: qcom: sm8150-mtp: Add base dts file This add base DTS file for sm8150-mtp and enables boot to console, adds tlmm reserved range, resin node, volume down key and also includes pmic file. Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 51 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8150-mtp.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 90ae31513e98..085d4c31b143 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -18,5 +18,6 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts new file mode 100644 index 000000000000..6f5777f530ae --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +/dts-v1/; + +#include "sm8150.dtsi" +#include "pm8150.dtsi" +#include "pm8150b.dtsi" +#include "pm8150l.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SM8150 MTP"; + compatible = "qcom,sm8150-mtp"; + + aliases { + serial0 = &uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&pon { + pwrkey { + status = "okay"; + }; + + resin { + compatible = "qcom,pm8941-resin"; + interrupts = <0x0 0x8 0x1 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = ; + }; +}; + +&tlmm { + gpio-reserved-ranges = <0 4>, <126 4>; +}; + +&uart2 { + status = "okay"; +}; -- GitLab From 22076f3bbb06e86a4907e825ac9f305413a5bbeb Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:37 +0530 Subject: [PATCH 3956/7155] arm64: dts: qcom: sm8150-mtp: Add regulators Add the regulators found in the mtp platform. This platform consists of pmic PM8150, PM8150L and PM8009. Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 324 ++++++++++++++++++++++++ 1 file changed, 324 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts index 6f5777f530ae..aa5de42fcae4 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts @@ -6,6 +6,7 @@ /dts-v1/; +#include #include "sm8150.dtsi" #include "pm8150.dtsi" #include "pm8150b.dtsi" @@ -22,6 +23,329 @@ chosen { stdout-path = "serial0:115200n8"; }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + + /* + * Apparently RPMh does not provide support for PM8150 S4 because it + * is always-on; model it as a fixed regulator. + */ + vreg_s4a_1p8: pm8150-s4 { + compatible = "regulator-fixed"; + regulator-name = "vreg_s4a_1p8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-always-on; + regulator-boot-on; + + vin-supply = <&vph_pwr>; + }; +}; + +&apps_rsc { + pm8150-rpmh-regulators { + compatible = "qcom,pm8150-rpmh-regulators"; + qcom,pmic-id = "a"; + + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + vdd-s3-supply = <&vph_pwr>; + vdd-s4-supply = <&vph_pwr>; + vdd-s5-supply = <&vph_pwr>; + vdd-s6-supply = <&vph_pwr>; + vdd-s7-supply = <&vph_pwr>; + vdd-s8-supply = <&vph_pwr>; + vdd-s9-supply = <&vph_pwr>; + vdd-s10-supply = <&vph_pwr>; + + vdd-l1-l8-l11-supply = <&vreg_s6a_0p9>; + vdd-l2-l10-supply = <&vreg_bob>; + vdd-l3-l4-l5-l18-supply = <&vreg_s6a_0p9>; + vdd-l6-l9-supply = <&vreg_s8c_1p3>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p0>; + vdd-l13-l16-l17-supply = <&vreg_bob>; + + vreg_s5a_2p0: smps5 { + regulator-min-microvolt = <1904000>; + regulator-max-microvolt = <2000000>; + }; + + vreg_s6a_0p9: smps6 { + regulator-min-microvolt = <920000>; + regulator-max-microvolt = <1128000>; + }; + + vdda_wcss_pll: + vreg_l1a_0p75: ldo1 { + regulator-min-microvolt = <752000>; + regulator-max-microvolt = <752000>; + regulator-initial-mode = ; + }; + + vdd_pdphy: + vdda_usb_hs_3p1: + vreg_l2a_3p1: ldo2 { + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l3a_0p8: ldo3 { + regulator-min-microvolt = <480000>; + regulator-max-microvolt = <932000>; + regulator-initial-mode = ; + }; + + vdd_usb_hs_core: + vdda_csi_0_0p9: + vdda_csi_1_0p9: + vdda_csi_2_0p9: + vdda_csi_3_0p9: + vdda_dsi_0_0p9: + vdda_dsi_1_0p9: + vdda_dsi_0_pll_0p9: + vdda_dsi_1_pll_0p9: + vdda_pcie_1ln_core: + vdda_pcie_2ln_core: + vdda_pll_hv_cc_ebi01: + vdda_pll_hv_cc_ebi23: + vdda_qrefs_0p875_5: + vdda_sp_sensor: + vdda_ufs_2ln_core_1: + vdda_ufs_2ln_core_2: + vdda_usb_ss_dp_core_1: + vdda_usb_ss_dp_core_2: + vdda_qlink_lv: + vdda_qlink_lv_ck: + vreg_l5a_0p875: ldo5 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = ; + }; + + vreg_l6a_1p2: ldo6 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l7a_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vddpx_10: + vreg_l9a_1p2: ldo9 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l10a_2p5: ldo10 { + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l11a_0p8: ldo11 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + regulator-initial-mode = ; + }; + + vdd_qfprom: + vdd_qfprom_sp: + vdda_apc_cs_1p8: + vdda_gfx_cs_1p8: + vdda_usb_hs_1p8: + vdda_qrefs_vref_1p8: + vddpx_10_a: + vreg_l12a_1p8: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l13a_2p7: ldo13 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + regulator-initial-mode = ; + }; + + vreg_l14a_1p8: ldo14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1880000>; + regulator-initial-mode = ; + }; + + vreg_l15a_1p7: ldo15 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <1704000>; + regulator-initial-mode = ; + }; + + vreg_l16a_2p7: ldo16 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l17a_3p0: ldo17 { + regulator-min-microvolt = <2856000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = ; + }; + }; + + pm8150l-rpmh-regulators { + compatible = "qcom,pm8150l-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + vdd-s3-supply = <&vph_pwr>; + vdd-s4-supply = <&vph_pwr>; + vdd-s5-supply = <&vph_pwr>; + vdd-s6-supply = <&vph_pwr>; + vdd-s7-supply = <&vph_pwr>; + vdd-s8-supply = <&vph_pwr>; + + vdd-l1-l8-supply = <&vreg_s4a_1p8>; + vdd-l2-l3-supply = <&vreg_s8c_1p3>; + vdd-l4-l5-l6-supply = <&vreg_bob>; + vdd-l7-l11-supply = <&vreg_bob>; + vdd-l9-l10-supply = <&vreg_bob>; + + vdd-bob-supply = <&vph_pwr>; + vdd-flash-supply = <&vreg_bob>; + vdd-rgb-supply = <&vreg_bob>; + + vreg_bob: bob { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <4000000>; + regulator-initial-mode = ; + regulator-allow-bypass; + }; + + vreg_s8c_1p3: smps8 { + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + }; + + vreg_l1c_1p8: ldo1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vdda_wcss_adcdac_1: + vdda_wcss_adcdac_22: + vreg_l2c_1p3: ldo2 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = ; + }; + + vdda_hv_ebi0: + vdda_hv_ebi1: + vdda_hv_ebi2: + vdda_hv_ebi3: + vdda_hv_refgen0: + vdda_qlink_hv_ck: + vreg_l3c_1p2: ldo3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vddpx_5: + vreg_l4c_1p8: ldo4 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <2928000>; + regulator-initial-mode = ; + }; + + vddpx_6: + vreg_l5c_1p8: ldo5 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <2928000>; + regulator-initial-mode = ; + }; + + vddpx_2: + vreg_l6c_2p9: ldo6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l7c_3p0: ldo7 { + regulator-min-microvolt = <2856000>; + regulator-max-microvolt = <3104000>; + regulator-initial-mode = ; + }; + + vreg_l8c_1p8: ldo8 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l9c_2p9: ldo9 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l10c_3p3: ldo10 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + + vreg_l11c_3p3: ldo11 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + }; + + pm8009-rpmh-regulators { + compatible = "qcom,pm8009-rpmh-regulators"; + qcom,pmic-id = "f"; + + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vreg_bob>; + + vdd-l2-supply = <&vreg_s8c_1p3>; + vdd-l5-l6-supply = <&vreg_bob>; + + vreg_l2f_1p2: ldo2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l5f_2p85: ldo5 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + + vreg_l6f_2p85: ldo6 { + regulator-initial-mode = ; + regulator-min-microvolt = <2856000>; + regulator-max-microvolt = <2856000>; + }; + }; }; &qupv3_id_1 { -- GitLab From 912c373a764ffcf81e80c2550b9d95cbec5b5438 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:38 +0530 Subject: [PATCH 3957/7155] arm64: dts: qcom: sm8150: Add reserved-memory regions Add the reserved memory regions in SM8150 Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 111 +++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 417b21d1897c..c739b4647db9 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -155,6 +155,117 @@ method = "smc"; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_mem: memory@85700000 { + reg = <0x0 0x85700000 0x0 0x600000>; + no-map; + }; + + xbl_mem: memory@85d00000 { + reg = <0x0 0x85d00000 0x0 0x140000>; + no-map; + }; + + aop_mem: memory@85f00000 { + reg = <0x0 0x85f00000 0x0 0x20000>; + no-map; + }; + + aop_cmd_db: memory@85f20000 { + compatible = "qcom,cmd-db"; + reg = <0x0 0x85f20000 0x0 0x20000>; + no-map; + }; + + smem_mem: memory@86000000 { + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + }; + + tz_mem: memory@86200000 { + reg = <0x0 0x86200000 0x0 0x3900000>; + no-map; + }; + + rmtfs_mem: memory@89b00000 { + compatible = "qcom,rmtfs-mem"; + reg = <0x0 0x89b00000 0x0 0x200000>; + no-map; + + qcom,client-id = <1>; + qcom,vmid = <15>; + }; + + camera_mem: memory@8b700000 { + reg = <0x0 0x8b700000 0x0 0x500000>; + no-map; + }; + + wlan_mem: memory@8bc00000 { + reg = <0x0 0x8bc00000 0x0 0x180000>; + no-map; + }; + + npu_mem: memory@8bd80000 { + reg = <0x0 0x8bd80000 0x0 0x80000>; + no-map; + }; + + adsp_mem: memory@8be00000 { + reg = <0x0 0x8be00000 0x0 0x1a00000>; + no-map; + }; + + mpss_mem: memory@8d800000 { + reg = <0x0 0x8d800000 0x0 0x9600000>; + no-map; + }; + + venus_mem: memory@96e00000 { + reg = <0x0 0x96e00000 0x0 0x500000>; + no-map; + }; + + slpi_mem: memory@97300000 { + reg = <0x0 0x97300000 0x0 0x1400000>; + no-map; + }; + + ipa_fw_mem: memory@98700000 { + reg = <0x0 0x98700000 0x0 0x10000>; + no-map; + }; + + ipa_gsi_mem: memory@98710000 { + reg = <0x0 0x98710000 0x0 0x5000>; + no-map; + }; + + gpu_mem: memory@98715000 { + reg = <0x0 0x98715000 0x0 0x2000>; + no-map; + }; + + spss_mem: memory@98800000 { + reg = <0x0 0x98800000 0x0 0x100000>; + no-map; + }; + + cdsp_mem: memory@98900000 { + reg = <0x0 0x98900000 0x0 0x1400000>; + no-map; + }; + + qseecom_mem: memory@9e400000 { + reg = <0x0 0x9e400000 0x0 0x1400000>; + no-map; + }; + }; + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; -- GitLab From d8cf9372b654406c92cbe1d342359dc58368bfe7 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 00:12:39 +0530 Subject: [PATCH 3958/7155] arm64: dts: qcom: sm8150: Add apps shared nodes Add hwlock, pmu, smem, tcsr_mutex_regs, apss_shared mailbox, apps_rsc including the rpmhcc child nodes to the SM8150 DTSI Co-developed-by: Sibi Sankar Signed-off-by: Sibi Sankar Signed-off-by: Vinod Koul Reviewed-by: Niklas Cassel Reviewed-by: Amit Kucheria Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index c739b4647db9..8f23fcadecb8 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -144,12 +144,23 @@ }; }; + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x1000>; + #hwlock-cells = <1>; + }; + memory@80000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ reg = <0x0 0x80000000 0x0 0x0>; }; + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -266,6 +277,12 @@ }; }; + smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; @@ -306,6 +323,11 @@ }; }; + tcsr_mutex_regs: syscon@1f40000 { + compatible = "syscon"; + reg = <0x0 0x01f40000 0x0 0x40000>; + }; + tlmm: pinctrl@3100000 { compatible = "qcom,sm8150-pinctrl"; reg = <0x0 0x03100000 0x0 0x300000>, @@ -321,6 +343,16 @@ #interrupt-cells = <2>; }; + aoss_qmp: power-controller@c300000 { + compatible = "qcom,sm8150-aoss-qmp"; + reg = <0x0 0x0c300000 0x0 0x100000>; + interrupts = ; + mboxes = <&apss_shared 0>; + + #clock-cells = <0>; + #power-domain-cells = <1>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0 0x0c440000 0x0 0x0001100>, @@ -349,6 +381,12 @@ interrupts = ; }; + apss_shared: mailbox@17c00000 { + compatible = "qcom,sm8150-apss-shared"; + reg = <0x0 0x17c00000 0x0 0x1000>; + #mbox-cells = <1>; + }; + timer@17c20000 { #address-cells = <2>; #size-cells = <2>; @@ -407,6 +445,31 @@ status = "disabled"; }; }; + + apps_rsc: rsc@18200000 { + label = "apps_rsc"; + compatible = "qcom,rpmh-rsc"; + reg = <0x0 0x18200000 0x0 0x10000>, + <0x0 0x18210000 0x0 0x10000>, + <0x0 0x18220000 0x0 0x10000>; + reg-names = "drv-0", "drv-1", "drv-2"; + interrupts = , + , + ; + qcom,tcs-offset = <0xd00>; + qcom,drv-id = <2>; + qcom,tcs-config = , + , + , + ; + + rpmhcc: clock-controller { + compatible = "qcom,sm8150-rpmh-clk"; + #clock-cells = <1>; + clock-names = "xo"; + clocks = <&xo_board>; + }; + }; }; timer { -- GitLab From 93415e45d30cbcb24ea0e45d2efd0a3511866f26 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 13 Jun 2018 14:49:46 +0300 Subject: [PATCH 3959/7155] net/mlx5e: Extract code that queues neigh update work into function As a preparation for following refactoring that removes rtnl lock dependency from neigh hash entry handlers, extract code that enqueues neigh update work into standalone function. This commit doesn't change functionality. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 7ce5cb6e527e..85a503f0423b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -821,6 +821,28 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb, return NOTIFY_OK; } +static void +mlx5e_rep_queue_neigh_update_work(struct mlx5e_priv *priv, + struct mlx5e_neigh_hash_entry *nhe, + struct neighbour *n) +{ + /* Take a reference to ensure the neighbour and mlx5 encap + * entry won't be destructed until we drop the reference in + * delayed work. + */ + neigh_hold(n); + + /* This assignment is valid as long as the the neigh reference + * is taken + */ + nhe->n = n; + + if (!queue_work(priv->wq, &nhe->neigh_update_work)) { + mlx5e_rep_neigh_entry_release(nhe); + neigh_release(n); + } +} + static struct mlx5e_neigh_hash_entry * mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv, struct mlx5e_neigh *m_neigh); @@ -864,22 +886,8 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb, return NOTIFY_DONE; } - /* This assignment is valid as long as the the neigh reference - * is taken - */ - nhe->n = n; - - /* Take a reference to ensure the neighbour and mlx5 encap - * entry won't be destructed until we drop the reference in - * delayed work. - */ - neigh_hold(n); mlx5e_rep_neigh_entry_hold(nhe); - - if (!queue_work(priv->wq, &nhe->neigh_update_work)) { - mlx5e_rep_neigh_entry_release(nhe); - neigh_release(n); - } + mlx5e_rep_queue_neigh_update_work(priv, nhe, n); spin_unlock_bh(&neigh_update->encap_lock); break; -- GitLab From 61081f9c09df33fe0123d234e840e3b4d3c17269 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 8 Jun 2018 11:31:28 +0300 Subject: [PATCH 3960/7155] net/mlx5e: Always take reference to neigh entry Neigh entry has reference counter, however it is only used when scheduling neigh update event. In all other cases reference to neigh entry is not taken while working with it. Neigh code relies on synchronization provided by rtnl lock and uses encap list size as implicit reference counter. To remove dependency on rtnl lock, always take reference to neigh entry while using it. Remove neigh entry from hash table and delete it only when reference counter reaches zero. This can result spurious neigh update events, when there is an event on entry that has zero encaps attached. However, such events are rare and properly handled by neigh update handler. Extend encap entry with reference to neigh hash entry in order to be able to directly release it when encap is detached, instead of lookup nhe by key through hash table. Extend nhe with reference to device priv structure to guarantee correctness when nhe is used with stack devices, bond setup, in which case it is non-trivial to determine correct device when releasing the nhe. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 76 +++++++++---------- .../net/ethernet/mellanox/mlx5/core/en_rep.h | 3 + 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 85a503f0423b..23087f9abe74 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -524,6 +524,21 @@ void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv) neigh_update->min_interval); } +static bool mlx5e_rep_neigh_entry_hold(struct mlx5e_neigh_hash_entry *nhe) +{ + return refcount_inc_not_zero(&nhe->refcnt); +} + +static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe); + +static void mlx5e_rep_neigh_entry_release(struct mlx5e_neigh_hash_entry *nhe) +{ + if (refcount_dec_and_test(&nhe->refcnt)) { + mlx5e_rep_neigh_entry_remove(nhe); + kfree(nhe); + } +} + static void mlx5e_rep_neigh_stats_work(struct work_struct *work) { struct mlx5e_rep_priv *rpriv = container_of(work, struct mlx5e_rep_priv, @@ -536,23 +551,16 @@ static void mlx5e_rep_neigh_stats_work(struct work_struct *work) if (!list_empty(&rpriv->neigh_update.neigh_list)) mlx5e_rep_queue_neigh_stats_work(priv); - list_for_each_entry(nhe, &rpriv->neigh_update.neigh_list, neigh_list) - mlx5e_tc_update_neigh_used_value(nhe); + list_for_each_entry(nhe, &rpriv->neigh_update.neigh_list, neigh_list) { + if (mlx5e_rep_neigh_entry_hold(nhe)) { + mlx5e_tc_update_neigh_used_value(nhe); + mlx5e_rep_neigh_entry_release(nhe); + } + } rtnl_unlock(); } -static void mlx5e_rep_neigh_entry_hold(struct mlx5e_neigh_hash_entry *nhe) -{ - refcount_inc(&nhe->refcnt); -} - -static void mlx5e_rep_neigh_entry_release(struct mlx5e_neigh_hash_entry *nhe) -{ - if (refcount_dec_and_test(&nhe->refcnt)) - kfree(nhe); -} - static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e, bool neigh_connected, @@ -881,14 +889,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb, */ spin_lock_bh(&neigh_update->encap_lock); nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh); - if (!nhe) { - spin_unlock_bh(&neigh_update->encap_lock); + spin_unlock_bh(&neigh_update->encap_lock); + if (!nhe) return NOTIFY_DONE; - } - mlx5e_rep_neigh_entry_hold(nhe); mlx5e_rep_queue_neigh_update_work(priv, nhe, n); - spin_unlock_bh(&neigh_update->encap_lock); break; case NETEVENT_DELAY_PROBE_TIME_UPDATE: @@ -995,10 +1000,9 @@ static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv, return err; } -static void mlx5e_rep_neigh_entry_remove(struct mlx5e_priv *priv, - struct mlx5e_neigh_hash_entry *nhe) +static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe) { - struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5e_rep_priv *rpriv = nhe->priv->ppriv; spin_lock_bh(&rpriv->neigh_update.encap_lock); @@ -1019,9 +1023,11 @@ mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv, { struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update; + struct mlx5e_neigh_hash_entry *nhe; - return rhashtable_lookup_fast(&neigh_update->neigh_ht, m_neigh, - mlx5e_neigh_ht_params); + nhe = rhashtable_lookup_fast(&neigh_update->neigh_ht, m_neigh, + mlx5e_neigh_ht_params); + return nhe && mlx5e_rep_neigh_entry_hold(nhe) ? nhe : NULL; } static int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv, @@ -1034,6 +1040,7 @@ static int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv, if (!*nhe) return -ENOMEM; + (*nhe)->priv = priv; memcpy(&(*nhe)->m_neigh, &e->m_neigh, sizeof(e->m_neigh)); INIT_WORK(&(*nhe)->neigh_update_work, mlx5e_rep_neigh_update); INIT_LIST_HEAD(&(*nhe)->encap_list); @@ -1049,19 +1056,6 @@ static int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv, return err; } -static void mlx5e_rep_neigh_entry_destroy(struct mlx5e_priv *priv, - struct mlx5e_neigh_hash_entry *nhe) -{ - /* The neigh hash entry must be removed from the hash table regardless - * of the reference count value, so it won't be found by the next - * neigh notification call. The neigh hash entry reference count is - * incremented only during creation and neigh notification calls and - * protects from freeing the nhe struct. - */ - mlx5e_rep_neigh_entry_remove(priv, nhe); - mlx5e_rep_neigh_entry_release(nhe); -} - int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { @@ -1083,6 +1077,7 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, return err; } } + e->nhe = nhe; list_add(&e->encap_list, &nhe->encap_list); return 0; } @@ -1093,13 +1088,14 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv, struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv; struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy; - struct mlx5e_neigh_hash_entry *nhe; + + if (!e->nhe) + return; list_del(&e->encap_list); - nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh); - if (list_empty(&nhe->encap_list)) - mlx5e_rep_neigh_entry_destroy(priv, nhe); + mlx5e_rep_neigh_entry_release(e->nhe); + e->nhe = NULL; mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 8ac96727cad8..f5bc9772be98 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -110,6 +110,7 @@ struct mlx5e_neigh { struct mlx5e_neigh_hash_entry { struct rhash_head rhash_node; struct mlx5e_neigh m_neigh; + struct mlx5e_priv *priv; /* Save the neigh hash entry in a list on the representor in * addition to the hash table. In order to iterate easily over the @@ -145,6 +146,8 @@ enum { }; struct mlx5e_encap_entry { + /* attached neigh hash entry */ + struct mlx5e_neigh_hash_entry *nhe; /* neigh hash entry list of encaps sharing the same neigh */ struct list_head encap_list; struct mlx5e_neigh m_neigh; -- GitLab From 1216ce9d4a740bed88393177174fef275069a560 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Fri, 8 Jun 2018 11:49:28 +0300 Subject: [PATCH 3961/7155] net/mlx5e: Extend neigh hash entry with rcu To remove dependency on rtnl lock and to allow unlocked iteration over list of neigh hash entries, extend nhe with rcu. Change operations on neigh list to their rcu counterparts and free neigh hash entry with rcu timeout. Introduce mlx5e_get_next_nhe() helper that is used to iterate over rcu neigh list with reference to nhe taken. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 68 ++++++++++++------- .../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 + 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 23087f9abe74..a294dc6b5a0c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -535,28 +535,56 @@ static void mlx5e_rep_neigh_entry_release(struct mlx5e_neigh_hash_entry *nhe) { if (refcount_dec_and_test(&nhe->refcnt)) { mlx5e_rep_neigh_entry_remove(nhe); - kfree(nhe); + kfree_rcu(nhe, rcu); } } +static struct mlx5e_neigh_hash_entry * +mlx5e_get_next_nhe(struct mlx5e_rep_priv *rpriv, + struct mlx5e_neigh_hash_entry *nhe) +{ + struct mlx5e_neigh_hash_entry *next = NULL; + + rcu_read_lock(); + + for (next = nhe ? + list_next_or_null_rcu(&rpriv->neigh_update.neigh_list, + &nhe->neigh_list, + struct mlx5e_neigh_hash_entry, + neigh_list) : + list_first_or_null_rcu(&rpriv->neigh_update.neigh_list, + struct mlx5e_neigh_hash_entry, + neigh_list); + next; + next = list_next_or_null_rcu(&rpriv->neigh_update.neigh_list, + &next->neigh_list, + struct mlx5e_neigh_hash_entry, + neigh_list)) + if (mlx5e_rep_neigh_entry_hold(next)) + break; + + rcu_read_unlock(); + + if (nhe) + mlx5e_rep_neigh_entry_release(nhe); + + return next; +} + static void mlx5e_rep_neigh_stats_work(struct work_struct *work) { struct mlx5e_rep_priv *rpriv = container_of(work, struct mlx5e_rep_priv, neigh_update.neigh_stats_work.work); struct net_device *netdev = rpriv->netdev; struct mlx5e_priv *priv = netdev_priv(netdev); - struct mlx5e_neigh_hash_entry *nhe; + struct mlx5e_neigh_hash_entry *nhe = NULL; rtnl_lock(); if (!list_empty(&rpriv->neigh_update.neigh_list)) mlx5e_rep_queue_neigh_stats_work(priv); - list_for_each_entry(nhe, &rpriv->neigh_update.neigh_list, neigh_list) { - if (mlx5e_rep_neigh_entry_hold(nhe)) { - mlx5e_tc_update_neigh_used_value(nhe); - mlx5e_rep_neigh_entry_release(nhe); - } - } + while ((nhe = mlx5e_get_next_nhe(rpriv, nhe)) != NULL) + mlx5e_tc_update_neigh_used_value(nhe); rtnl_unlock(); } @@ -883,13 +911,9 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb, m_neigh.family = n->ops->family; memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len); - /* We are in atomic context and can't take RTNL mutex, so use - * spin_lock_bh to lookup the neigh table. bh is used since - * netevent can be called from a softirq context. - */ - spin_lock_bh(&neigh_update->encap_lock); + rcu_read_lock(); nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh); - spin_unlock_bh(&neigh_update->encap_lock); + rcu_read_unlock(); if (!nhe) return NOTIFY_DONE; @@ -910,19 +934,15 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb, #endif return NOTIFY_DONE; - /* We are in atomic context and can't take RTNL mutex, - * so use spin_lock_bh to walk the neigh list and look for - * the relevant device. bh is used since netevent can be - * called from a softirq context. - */ - spin_lock_bh(&neigh_update->encap_lock); - list_for_each_entry(nhe, &neigh_update->neigh_list, neigh_list) { + rcu_read_lock(); + list_for_each_entry_rcu(nhe, &neigh_update->neigh_list, + neigh_list) { if (p->dev == nhe->m_neigh.dev) { found = true; break; } } - spin_unlock_bh(&neigh_update->encap_lock); + rcu_read_unlock(); if (!found) return NOTIFY_DONE; @@ -995,7 +1015,7 @@ static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv, if (err) return err; - list_add(&nhe->neigh_list, &rpriv->neigh_update.neigh_list); + list_add_rcu(&nhe->neigh_list, &rpriv->neigh_update.neigh_list); return err; } @@ -1006,7 +1026,7 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe) spin_lock_bh(&rpriv->neigh_update.encap_lock); - list_del(&nhe->neigh_list); + list_del_rcu(&nhe->neigh_list); rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht, &nhe->rhash_node, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index f5bc9772be98..d057e401b0de 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -138,6 +138,8 @@ struct mlx5e_neigh_hash_entry { * 'used' value and avoid neigh deleting by the kernel. */ unsigned long reported_lastuse; + + struct rcu_head rcu; }; enum { -- GitLab From 70e83bd3b0e434ee9fa8e0010f76080aa4320725 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 12 Jun 2018 11:59:43 +0300 Subject: [PATCH 3962/7155] net/mlx5e: Refactor mlx5e_neigh_update_table->encap_lock To remove dependency on rtnl lock, always take neigh update encap lock when modifying neigh update hash table and list. Originally, this lock was only used to synchronize with netevent handler function, which is called from bh context and cannot use rtnl lock for synchronization. Take lock in encap entry attach function to prevent concurrent modifications of neigh update hash table and list. Taking the encap lock when creating new nhe introduces a problem that we need to allocate new entry with sleeping GFP_KERNEL flag while holding a spinlock. However, since previous patch in this series has already converted lookup in netevent handler function to user rcu read lock instead of encap lock, we can safely convert the lock type to mutex. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 17 ++++++++++++----- .../net/ethernet/mellanox/mlx5/core/en_rep.h | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index a294dc6b5a0c..218772d5c062 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -973,7 +973,7 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv) return err; INIT_LIST_HEAD(&neigh_update->neigh_list); - spin_lock_init(&neigh_update->encap_lock); + mutex_init(&neigh_update->encap_lock); INIT_DELAYED_WORK(&neigh_update->neigh_stats_work, mlx5e_rep_neigh_stats_work); mlx5e_rep_neigh_update_init_interval(rpriv); @@ -1000,6 +1000,7 @@ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv) cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work); + mutex_destroy(&neigh_update->encap_lock); rhashtable_destroy(&neigh_update->neigh_ht); } @@ -1024,18 +1025,18 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe) { struct mlx5e_rep_priv *rpriv = nhe->priv->ppriv; - spin_lock_bh(&rpriv->neigh_update.encap_lock); + mutex_lock(&rpriv->neigh_update.encap_lock); list_del_rcu(&nhe->neigh_list); rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht, &nhe->rhash_node, mlx5e_neigh_ht_params); - spin_unlock_bh(&rpriv->neigh_update.encap_lock); + mutex_unlock(&rpriv->neigh_update.encap_lock); } -/* This function must only be called under RTNL lock or under the - * representor's encap_lock in case RTNL mutex can't be held. +/* This function must only be called under the representor's encap_lock or + * inside rcu read lock section. */ static struct mlx5e_neigh_hash_entry * mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv, @@ -1088,17 +1089,23 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type); if (err) return err; + + mutex_lock(&rpriv->neigh_update.encap_lock); nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh); if (!nhe) { err = mlx5e_rep_neigh_entry_create(priv, e, &nhe); if (err) { + mutex_unlock(&rpriv->neigh_update.encap_lock); mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type); return err; } } + e->nhe = nhe; list_add(&e->encap_list, &nhe->encap_list); + mutex_unlock(&rpriv->neigh_update.encap_lock); + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index d057e401b0de..8fa27832bd81 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -35,6 +35,7 @@ #include #include +#include #include "eswitch.h" #include "en.h" #include "lib/port_tun.h" @@ -48,7 +49,7 @@ struct mlx5e_neigh_update_table { */ struct list_head neigh_list; /* protect lookup/remove operations */ - spinlock_t encap_lock; + struct mutex encap_lock; struct notifier_block netevent_nb; struct delayed_work neigh_stats_work; unsigned long min_interval; /* jiffies */ -- GitLab From ac0d917632cf7fbbe953f2ec82c2c979ab1b4a06 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Mon, 11 Jun 2018 14:16:14 +0300 Subject: [PATCH 3963/7155] net/mlx5e: Protect neigh hash encap list with spinlock and rcu Rcu-ify mlx5e_neigh_hash_entry->encap_list by changing operations on encap list to their rcu counterparts and extending encap structure with rcu_head to free the encap instances after rcu grace period. Use rcu read lock when traversing encap list. Implement helper mlx5e_get_next_valid_encap() function that is used by mlx5e_tc_update_neigh_used_value() to safely iterate over valid entries of nhe->encap_list. Signed-off-by: Vlad Buslov Reviewed-by: Jianbo Liu Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 10 ++- .../net/ethernet/mellanox/mlx5/core/en_rep.h | 3 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 64 ++++++++++++++++--- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 218772d5c062..f26edf458152 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1064,6 +1064,7 @@ static int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv, (*nhe)->priv = priv; memcpy(&(*nhe)->m_neigh, &e->m_neigh, sizeof(e->m_neigh)); INIT_WORK(&(*nhe)->neigh_update_work, mlx5e_rep_neigh_update); + spin_lock_init(&(*nhe)->encap_list_lock); INIT_LIST_HEAD(&(*nhe)->encap_list); refcount_set(&(*nhe)->refcnt, 1); @@ -1103,7 +1104,10 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, } e->nhe = nhe; - list_add(&e->encap_list, &nhe->encap_list); + spin_lock(&nhe->encap_list_lock); + list_add_rcu(&e->encap_list, &nhe->encap_list); + spin_unlock(&nhe->encap_list_lock); + mutex_unlock(&rpriv->neigh_update.encap_lock); return 0; @@ -1119,7 +1123,9 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv, if (!e->nhe) return; - list_del(&e->encap_list); + spin_lock(&e->nhe->encap_list_lock); + list_del_rcu(&e->encap_list); + spin_unlock(&e->nhe->encap_list_lock); mlx5e_rep_neigh_entry_release(e->nhe); e->nhe = NULL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 8fa27832bd81..a0ae5069d8c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -119,6 +119,8 @@ struct mlx5e_neigh_hash_entry { */ struct list_head neigh_list; + /* protects encap list */ + spinlock_t encap_list_lock; /* encap list sharing the same neigh */ struct list_head encap_list; @@ -173,6 +175,7 @@ struct mlx5e_encap_entry { refcount_t refcnt; struct completion res_ready; int compl_result; + struct rcu_head rcu; }; struct mlx5e_rep_sq { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 3917834b48ff..a4d11274be30 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1412,11 +1412,56 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow) return flow->nic_attr->counter; } +static struct mlx5e_encap_entry * +mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe, + struct mlx5e_encap_entry *e) +{ + struct mlx5e_encap_entry *next = NULL; + +retry: + rcu_read_lock(); + + /* find encap with non-zero reference counter value */ + for (next = e ? + list_next_or_null_rcu(&nhe->encap_list, + &e->encap_list, + struct mlx5e_encap_entry, + encap_list) : + list_first_or_null_rcu(&nhe->encap_list, + struct mlx5e_encap_entry, + encap_list); + next; + next = list_next_or_null_rcu(&nhe->encap_list, + &next->encap_list, + struct mlx5e_encap_entry, + encap_list)) + if (mlx5e_encap_take(next)) + break; + + rcu_read_unlock(); + + /* release starting encap */ + if (e) + mlx5e_encap_put(netdev_priv(e->out_dev), e); + if (!next) + return next; + + /* wait for encap to be fully initialized */ + wait_for_completion(&next->res_ready); + /* continue searching if encap entry is not in valid state after completion */ + if (!(next->flags & MLX5_ENCAP_ENTRY_VALID)) { + e = next; + goto retry; + } + + return next; +} + void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) { struct mlx5e_neigh *m_neigh = &nhe->m_neigh; + struct mlx5e_encap_entry *e = NULL; struct mlx5e_tc_flow *flow; - struct mlx5e_encap_entry *e; struct mlx5_fc *counter; struct neigh_table *tbl; bool neigh_used = false; @@ -1432,13 +1477,12 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) else return; - list_for_each_entry(e, &nhe->encap_list, encap_list) { + /* mlx5e_get_next_valid_encap() releases previous encap before returning + * next one. + */ + while ((e = mlx5e_get_next_valid_encap(nhe, e)) != NULL) { struct encap_flow_item *efi, *tmp; - if (!(e->flags & MLX5_ENCAP_ENTRY_VALID) || - !mlx5e_encap_take(e)) - continue; - list_for_each_entry_safe(efi, tmp, &e->flows, list) { flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); @@ -1458,9 +1502,11 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) mlx5e_flow_put(netdev_priv(e->out_dev), flow); } - mlx5e_encap_put(netdev_priv(e->out_dev), e); - if (neigh_used) + if (neigh_used) { + /* release current encap before breaking the loop */ + mlx5e_encap_put(netdev_priv(e->out_dev), e); break; + } } if (neigh_used) { @@ -1490,7 +1536,7 @@ static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entr } kfree(e->encap_header); - kfree(e); + kfree_rcu(e, rcu); } void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) -- GitLab From 6a06c2f7843d85b43ccea6e89de8e432834c089b Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Sat, 3 Aug 2019 21:43:06 +0300 Subject: [PATCH 3964/7155] net/mlx5e: Refactor neigh used value update for concurrent execution In order to remove dependency on rtnl lock and allow neigh used value update workqueue task to execute concurrently with tc, refactor mlx5e_tc_update_neigh_used_value() for concurrent execution: - Lock encap table when accessing encap entry to prevent concurrent changes. - Save offloaded encap flows to temporary list and release them after encap entry is updated. Add mlx5e_put_encap_flow_list() helper which is intended to be shared with neigh update code in following patch in this series. This is necessary because mlx5e_flow_put() can't be called while holding encap_tbl_lock. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a4d11274be30..3a562189af71 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -126,6 +126,7 @@ struct mlx5e_tc_flow { struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ + struct list_head tmp_list; /* temporary flow list used by neigh update */ refcount_t refcnt; struct rcu_head rcu_head; union { @@ -1412,6 +1413,15 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow) return flow->nic_attr->counter; } +/* Iterate over tmp_list of flows attached to flow_list head. */ +static void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) +{ + struct mlx5e_tc_flow *flow, *tmp; + + list_for_each_entry_safe(flow, tmp, flow_list, tmp_list) + mlx5e_flow_put(priv, flow); +} + static struct mlx5e_encap_entry * mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe, struct mlx5e_encap_entry *e) @@ -1481,30 +1491,35 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) * next one. */ while ((e = mlx5e_get_next_valid_encap(nhe, e)) != NULL) { + struct mlx5e_priv *priv = netdev_priv(e->out_dev); struct encap_flow_item *efi, *tmp; + struct mlx5_eswitch *esw; + LIST_HEAD(flow_list); + esw = priv->mdev->priv.eswitch; + mutex_lock(&esw->offloads.encap_tbl_lock); list_for_each_entry_safe(efi, tmp, &e->flows, list) { flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); if (IS_ERR(mlx5e_flow_get(flow))) continue; + list_add(&flow->tmp_list, &flow_list); if (mlx5e_is_offloaded_flow(flow)) { counter = mlx5e_tc_get_counter(flow); lastuse = mlx5_fc_query_lastuse(counter); if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) { - mlx5e_flow_put(netdev_priv(e->out_dev), flow); neigh_used = true; break; } } - - mlx5e_flow_put(netdev_priv(e->out_dev), flow); } + mutex_unlock(&esw->offloads.encap_tbl_lock); + mlx5e_put_encap_flow_list(priv, &flow_list); if (neigh_used) { /* release current encap before breaking the loop */ - mlx5e_encap_put(netdev_priv(e->out_dev), e); + mlx5e_encap_put(priv, e); break; } } -- GitLab From 2a1f1768fa17805ca2e937e2e034a7c3433d3bdc Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Sun, 4 Aug 2019 12:25:57 +0300 Subject: [PATCH 3965/7155] net/mlx5e: Refactor neigh update for concurrent execution In order to remove dependency on rtnl lock and allow neigh update workqueue task to execute concurrently with tc, refactor mlx5e_rep_neigh_update() for concurrent execution: - Lock encap table when accessing encap entry to prevent concurrent changes. To do this properly, the initial encap state check is moved from mlx5e_rep_neigh_update() into mlx5e_rep_update_flows() to be performed under encap_tbl_lock protection. - Wait for encap to be fully initialized before accessing it by means of 'res_ready' completion. - Add mlx5e_take_all_encap_flows() helper which is used to construct a temporary list of flows and efi indexes that is used to access current encap data in flow which can be attached to multiple encaps simultaneously. Release the flows from temporary list after encap_tbl_lock critical section. This is necessary because mlx5e_flow_put() can't be called while holding encap_tbl_lock. - Modify mlx5e_tc_encap_flows_add() and mlx5e_tc_encap_flows_del() to work with user-provided list of flows built by mlx5e_take_all_encap_flows(), instead of traversing encap flow list directly. This is first step in complex neigh update refactoring, which is finished by following commit in this series. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 29 ++++++--- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 59 ++++++++++--------- .../net/ethernet/mellanox/mlx5/core/en_tc.h | 9 ++- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index f26edf458152..5217f39828a4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -595,12 +595,26 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, unsigned char ha[ETH_ALEN]) { struct ethhdr *eth = (struct ethhdr *)e->encap_header; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + bool encap_connected; + LIST_HEAD(flow_list); ASSERT_RTNL(); + /* wait for encap to be fully initialized */ + wait_for_completion(&e->res_ready); + + mutex_lock(&esw->offloads.encap_tbl_lock); + encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); + if (e->compl_result || (encap_connected == neigh_connected && + ether_addr_equal(e->h_dest, ha))) + goto unlock; + + mlx5e_take_all_encap_flows(e, &flow_list); + if ((e->flags & MLX5_ENCAP_ENTRY_VALID) && (!neigh_connected || !ether_addr_equal(e->h_dest, ha))) - mlx5e_tc_encap_flows_del(priv, e); + mlx5e_tc_encap_flows_del(priv, e, &flow_list); if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) { ether_addr_copy(e->h_dest, ha); @@ -610,8 +624,11 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, */ ether_addr_copy(eth->h_source, e->route_dev->dev_addr); - mlx5e_tc_encap_flows_add(priv, e); + mlx5e_tc_encap_flows_add(priv, e, &flow_list); } +unlock: + mutex_unlock(&esw->offloads.encap_tbl_lock); + mlx5e_put_encap_flow_list(priv, &flow_list); } static void mlx5e_rep_neigh_update(struct work_struct *work) @@ -623,7 +640,6 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) unsigned char ha[ETH_ALEN]; struct mlx5e_priv *priv; bool neigh_connected; - bool encap_connected; u8 nud_state, dead; rtnl_lock(); @@ -645,13 +661,8 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) if (!mlx5e_encap_take(e)) continue; - encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); priv = netdev_priv(e->out_dev); - - if (encap_connected != neigh_connected || - !ether_addr_equal(e->h_dest, ha)) - mlx5e_rep_update_flows(priv, e, neigh_connected, ha); - + mlx5e_rep_update_flows(priv, e, neigh_connected, ha); mlx5e_encap_put(priv, e); } mlx5e_rep_neigh_entry_release(nhe); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 3a562189af71..b63bae05955b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -126,6 +126,7 @@ struct mlx5e_tc_flow { struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ + int tmp_efi_index; struct list_head tmp_list; /* temporary flow list used by neigh update */ refcount_t refcnt; struct rcu_head rcu_head; @@ -1291,11 +1292,11 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, } void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, - struct mlx5e_encap_entry *e) + struct mlx5e_encap_entry *e, + struct list_head *flow_list) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr slow_attr, *esw_attr; - struct encap_flow_item *efi, *tmp; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; struct mlx5e_tc_flow *flow; @@ -1314,19 +1315,15 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(priv); - list_for_each_entry_safe(efi, tmp, &e->flows, list) { + list_for_each_entry(flow, flow_list, tmp_list) { bool all_flow_encaps_valid = true; int i; - flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); - if (IS_ERR(mlx5e_flow_get(flow))) - continue; - esw_attr = flow->esw_attr; spec = &esw_attr->parse_attr->spec; - esw_attr->dests[efi->index].encap_id = e->encap_id; - esw_attr->dests[efi->index].flags |= MLX5_ESW_DEST_ENCAP_VALID; + esw_attr->dests[flow->tmp_efi_index].encap_id = e->encap_id; + esw_attr->dests[flow->tmp_efi_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; /* Flow can be associated with multiple encap entries. * Before offloading the flow verify that all of them have * a valid neighbour. @@ -1341,63 +1338,53 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, } /* Do not offload flows with unresolved neighbors */ if (!all_flow_encaps_valid) - goto loop_cont; + continue; /* update from slow path rule to encap rule */ rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, esw_attr); if (IS_ERR(rule)) { err = PTR_ERR(rule); mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n", err); - goto loop_cont; + continue; } mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); flow->rule[0] = rule; /* was unset when slow path rule removed */ flow_flag_set(flow, OFFLOADED); - -loop_cont: - mlx5e_flow_put(priv, flow); } } void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, - struct mlx5e_encap_entry *e) + struct mlx5e_encap_entry *e, + struct list_head *flow_list) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr slow_attr; - struct encap_flow_item *efi, *tmp; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; struct mlx5e_tc_flow *flow; int err; - list_for_each_entry_safe(efi, tmp, &e->flows, list) { - flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); - if (IS_ERR(mlx5e_flow_get(flow))) - continue; - + list_for_each_entry(flow, flow_list, tmp_list) { spec = &flow->esw_attr->parse_attr->spec; /* update from encap rule to slow path rule */ rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec, &slow_attr); /* mark the flow's encap dest as non-valid */ - flow->esw_attr->dests[efi->index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; + flow->esw_attr->dests[flow->tmp_efi_index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; if (IS_ERR(rule)) { err = PTR_ERR(rule); mlx5_core_warn(priv->mdev, "Failed to update slow path (encap) flow, %d\n", err); - goto loop_cont; + continue; } mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->esw_attr); flow->rule[0] = rule; /* was unset when fast path rule removed */ flow_flag_set(flow, OFFLOADED); - -loop_cont: - mlx5e_flow_put(priv, flow); } /* we know that the encap is valid */ @@ -1413,8 +1400,26 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow) return flow->nic_attr->counter; } +/* Takes reference to all flows attached to encap and adds the flows to + * flow_list using 'tmp_list' list_head in mlx5e_tc_flow. + */ +void mlx5e_take_all_encap_flows(struct mlx5e_encap_entry *e, struct list_head *flow_list) +{ + struct encap_flow_item *efi; + struct mlx5e_tc_flow *flow; + + list_for_each_entry(efi, &e->flows, list) { + flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); + if (IS_ERR(mlx5e_flow_get(flow))) + continue; + + flow->tmp_efi_index = efi->index; + list_add(&flow->tmp_list, flow_list); + } +} + /* Iterate over tmp_list of flows attached to flow_list head. */ -static void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) +void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) { struct mlx5e_tc_flow *flow, *tmp; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index ea2072e2fe84..924c6ef86a14 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -72,12 +72,17 @@ void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, struct mlx5e_encap_entry; void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, - struct mlx5e_encap_entry *e); + struct mlx5e_encap_entry *e, + struct list_head *flow_list); void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, - struct mlx5e_encap_entry *e); + struct mlx5e_encap_entry *e, + struct list_head *flow_list); bool mlx5e_encap_take(struct mlx5e_encap_entry *e); void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); +void mlx5e_take_all_encap_flows(struct mlx5e_encap_entry *e, struct list_head *flow_list); +void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list); + struct mlx5e_neigh_hash_entry; void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe); -- GitLab From 95435ad7999b1218367f0667ed5fe98d042ffe78 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Sun, 4 Aug 2019 13:52:31 +0300 Subject: [PATCH 3966/7155] net/mlx5e: Only access fully initialized flows in neigh update To remove dependency on rtnl lock and prevent neigh update code from accessing uninitialized flows when executing concurrently with tc, extend mlx5e_tc_flow with 'init_done' completion. Modify helper mlx5e_take_all_encap_flows() to wait for flow completion after obtaining reference to it. Modify mlx5e_tc_encap_flows_del() and mlx5e_tc_encap_flows_add() to skip flows that don't have OFFLOADED flag set, which can happen if concurrent flow initialization failed. This commit finishes neigh update refactoring for concurrent execution started in previous change in this series. Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index b63bae05955b..5d4ce3d58832 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -130,6 +130,7 @@ struct mlx5e_tc_flow { struct list_head tmp_list; /* temporary flow list used by neigh update */ refcount_t refcnt; struct rcu_head rcu_head; + struct completion init_done; union { struct mlx5_esw_flow_attr esw_attr[0]; struct mlx5_nic_flow_attr nic_attr[0]; @@ -1319,6 +1320,8 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, bool all_flow_encaps_valid = true; int i; + if (!mlx5e_is_offloaded_flow(flow)) + continue; esw_attr = flow->esw_attr; spec = &esw_attr->parse_attr->spec; @@ -1367,6 +1370,8 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, int err; list_for_each_entry(flow, flow_list, tmp_list) { + if (!mlx5e_is_offloaded_flow(flow)) + continue; spec = &flow->esw_attr->parse_attr->spec; /* update from encap rule to slow path rule */ @@ -1412,6 +1417,7 @@ void mlx5e_take_all_encap_flows(struct mlx5e_encap_entry *e, struct list_head *f flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); if (IS_ERR(mlx5e_flow_get(flow))) continue; + wait_for_completion(&flow->init_done); flow->tmp_efi_index = efi->index; list_add(&flow->tmp_list, flow_list); @@ -3492,6 +3498,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, INIT_LIST_HEAD(&flow->mod_hdr); INIT_LIST_HEAD(&flow->hairpin); refcount_set(&flow->refcnt, 1); + init_completion(&flow->init_done); *__flow = flow; *__parse_attr = parse_attr; @@ -3564,6 +3571,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, goto err_free; err = mlx5e_tc_add_fdb_flow(priv, flow, extack); + complete_all(&flow->init_done); if (err) { if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev))) goto err_free; -- GitLab From 7a978759b4e0e7a2ad3f10cbf9077915a85ec956 Mon Sep 17 00:00:00 2001 From: Dmytro Linkin Date: Thu, 27 Jun 2019 10:55:02 +0000 Subject: [PATCH 3967/7155] net/mlx5e: Add tc flower tracepoints Implemented following tracepoints: 1. Configure flower (mlx5e_configure_flower) 2. Delete flower (mlx5e_delete_flower) 3. Stats flower (mlx5e_stats_flower) Usage example: ># cd /sys/kernel/debug/tracing ># echo mlx5:mlx5e_configure_flower >> set_event ># cat trace ... tc-6535 [019] ...1 2672.404466: mlx5e_configure_flower: cookie=0000000067874a55 actions= REDIRECT Added corresponding documentation in Documentation/networking/device-driver/mellanox/mlx5.rst Signed-off-by: Dmytro Linkin Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../device_drivers/mellanox/mlx5.rst | 32 +++++++ .../net/ethernet/mellanox/mlx5/core/Makefile | 2 +- .../mlx5/core/diag/en_tc_tracepoint.c | 58 +++++++++++++ .../mlx5/core/diag/en_tc_tracepoint.h | 83 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tc.c | 4 + include/net/flow_offload.h | 1 + 6 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h diff --git a/Documentation/networking/device_drivers/mellanox/mlx5.rst b/Documentation/networking/device_drivers/mellanox/mlx5.rst index cfda464e52de..1339dbf52431 100644 --- a/Documentation/networking/device_drivers/mellanox/mlx5.rst +++ b/Documentation/networking/device_drivers/mellanox/mlx5.rst @@ -12,6 +12,7 @@ Contents - `Enabling the driver and kconfig options`_ - `Devlink info`_ - `Devlink health reporters`_ +- `mlx5 tracepoints`_ Enabling the driver and kconfig options ================================================ @@ -219,3 +220,34 @@ User commands examples: $ devlink health dump show pci/0000:82:00.1 reporter fw_fatal NOTE: This command can run only on PF. + +mlx5 tracepoints +================ + +mlx5 driver provides internal trace points for tracking and debugging using +kernel tracepoints interfaces (refer to Documentation/trace/ftrase.rst). + +For the list of support mlx5 events check /sys/kernel/debug/tracing/events/mlx5/ + +tc and eswitch offloads tracepoints: + +- mlx5e_configure_flower: trace flower filter actions and cookies offloaded to mlx5:: + + $ echo mlx5:mlx5e_configure_flower >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + tc-6535 [019] ...1 2672.404466: mlx5e_configure_flower: cookie=0000000067874a55 actions= REDIRECT + +- mlx5e_delete_flower: trace flower filter actions and cookies deleted from mlx5:: + + $ echo mlx5:mlx5e_delete_flower >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + tc-6569 [010] .N.1 2686.379075: mlx5e_delete_flower: cookie=0000000067874a55 actions= NULL + +- mlx5e_stats_flower: trace flower stats request:: + + $ echo mlx5:mlx5e_stats_flower >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + tc-6546 [010] ...1 2679.704889: mlx5e_stats_flower: cookie=0000000060eb3d6a bytes=0 packets=0 lastused=4295560217 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index a3b9659649a8..bcf36552f069 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -35,7 +35,7 @@ mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o \ lib/geneve.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ - en/tc_tun_geneve.o + en/tc_tun_geneve.o diag/en_tc_tracepoint.o # # Core extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.c new file mode 100644 index 000000000000..c5dc6c50fa87 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2019 Mellanox Technologies. */ + +#define CREATE_TRACE_POINTS +#include "en_tc_tracepoint.h" + +void put_ids_to_array(int *ids, + const struct flow_action_entry *entries, + unsigned int num) +{ + unsigned int i; + + for (i = 0; i < num; i++) + ids[i] = entries[i].id; +} + +#define NAME_SIZE 16 + +static const char FLOWACT2STR[NUM_FLOW_ACTIONS][NAME_SIZE] = { + [FLOW_ACTION_ACCEPT] = "ACCEPT", + [FLOW_ACTION_DROP] = "DROP", + [FLOW_ACTION_TRAP] = "TRAP", + [FLOW_ACTION_GOTO] = "GOTO", + [FLOW_ACTION_REDIRECT] = "REDIRECT", + [FLOW_ACTION_MIRRED] = "MIRRED", + [FLOW_ACTION_VLAN_PUSH] = "VLAN_PUSH", + [FLOW_ACTION_VLAN_POP] = "VLAN_POP", + [FLOW_ACTION_VLAN_MANGLE] = "VLAN_MANGLE", + [FLOW_ACTION_TUNNEL_ENCAP] = "TUNNEL_ENCAP", + [FLOW_ACTION_TUNNEL_DECAP] = "TUNNEL_DECAP", + [FLOW_ACTION_MANGLE] = "MANGLE", + [FLOW_ACTION_ADD] = "ADD", + [FLOW_ACTION_CSUM] = "CSUM", + [FLOW_ACTION_MARK] = "MARK", + [FLOW_ACTION_WAKE] = "WAKE", + [FLOW_ACTION_QUEUE] = "QUEUE", + [FLOW_ACTION_SAMPLE] = "SAMPLE", + [FLOW_ACTION_POLICE] = "POLICE", + [FLOW_ACTION_CT] = "CT", +}; + +const char *parse_action(struct trace_seq *p, + int *ids, + unsigned int num) +{ + const char *ret = trace_seq_buffer_ptr(p); + unsigned int i; + + for (i = 0; i < num; i++) { + if (ids[i] < NUM_FLOW_ACTIONS) + trace_seq_printf(p, "%s ", FLOWACT2STR[ids[i]]); + else + trace_seq_printf(p, "UNKNOWN "); + } + + trace_seq_putc(p, 0); + return ret; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h new file mode 100644 index 000000000000..a362100fe6d3 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlx5 + +#if !defined(_MLX5_TC_TP_) || defined(TRACE_HEADER_MULTI_READ) +#define _MLX5_TC_TP_ + +#include +#include +#include + +#define __parse_action(ids, num) parse_action(p, ids, num) + +void put_ids_to_array(int *ids, + const struct flow_action_entry *entries, + unsigned int num); + +const char *parse_action(struct trace_seq *p, + int *ids, + unsigned int num); + +DECLARE_EVENT_CLASS(mlx5e_flower_template, + TP_PROTO(const struct flow_cls_offload *f), + TP_ARGS(f), + TP_STRUCT__entry(__field(void *, cookie) + __field(unsigned int, num) + __dynamic_array(int, ids, f->rule ? + f->rule->action.num_entries : 0) + ), + TP_fast_assign(__entry->cookie = (void *)f->cookie; + __entry->num = (f->rule ? + f->rule->action.num_entries : 0); + if (__entry->num) + put_ids_to_array(__get_dynamic_array(ids), + f->rule->action.entries, + f->rule->action.num_entries); + ), + TP_printk("cookie=%p actions= %s\n", + __entry->cookie, __entry->num ? + __parse_action(__get_dynamic_array(ids), + __entry->num) : "NULL" + ) +); + +DEFINE_EVENT(mlx5e_flower_template, mlx5e_configure_flower, + TP_PROTO(const struct flow_cls_offload *f), + TP_ARGS(f) + ); + +DEFINE_EVENT(mlx5e_flower_template, mlx5e_delete_flower, + TP_PROTO(const struct flow_cls_offload *f), + TP_ARGS(f) + ); + +TRACE_EVENT(mlx5e_stats_flower, + TP_PROTO(const struct flow_cls_offload *f), + TP_ARGS(f), + TP_STRUCT__entry(__field(void *, cookie) + __field(u64, bytes) + __field(u64, packets) + __field(u64, lastused) + ), + TP_fast_assign(__entry->cookie = (void *)f->cookie; + __entry->bytes = f->stats.bytes; + __entry->packets = f->stats.pkts; + __entry->lastused = f->stats.lastused; + ), + TP_printk("cookie=%p bytes=%llu packets=%llu lastused=%llu\n", + __entry->cookie, __entry->bytes, + __entry->packets, __entry->lastused + ) +); + +#endif /* _MLX5_TC_TP_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ./diag +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE en_tc_tracepoint +#include diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 5d4ce3d58832..c40cca08c8cc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -56,6 +56,7 @@ #include "en/tc_tun.h" #include "lib/devcom.h" #include "lib/geneve.h" +#include "diag/en_tc_tracepoint.h" struct mlx5_nic_flow_attr { u32 action; @@ -3769,6 +3770,7 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, goto out; } + trace_mlx5e_configure_flower(f); err = mlx5e_tc_add_flow(priv, f, flags, dev, &flow); if (err) goto out; @@ -3818,6 +3820,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params); rcu_read_unlock(); + trace_mlx5e_delete_flower(f); mlx5e_flow_put(priv, flow); return 0; @@ -3887,6 +3890,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); out: flow_stats_update(&f->stats, bytes, packets, lastuse); + trace_mlx5e_stats_flower(f); errout: mlx5e_flow_put(priv, flow); return err; diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index e8069b6c474c..757fa84de654 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -138,6 +138,7 @@ enum flow_action_id { FLOW_ACTION_MPLS_PUSH, FLOW_ACTION_MPLS_POP, FLOW_ACTION_MPLS_MANGLE, + NUM_FLOW_ACTIONS, }; /* This is mirroring enum pedit_header_type definition for easy mapping between -- GitLab From c786fe596bede275f887f212eebee74490043b84 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 25 Jun 2019 22:33:15 +0300 Subject: [PATCH 3968/7155] net/mlx5e: Add trace point for neigh used value update Allow tracing result of neigh used value update task that is executed periodically on workqueue. Usage example: ># cd /sys/kernel/debug/tracing ># echo mlx5:mlx5e_tc_update_neigh_used_value >> set_event ># cat trace ... kworker/u48:4-8806 [009] ...1 55117.882428: mlx5e_tc_update_neigh_used_value: netdev: ens1f0 IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_used=1 Added corresponding documentation in Documentation/networking/device-driver/mellanox/mlx5.rst Signed-off-by: Vlad Buslov Reviewed-by: Dmytro Linkin Signed-off-by: Saeed Mahameed --- .../device_drivers/mellanox/mlx5.rst | 7 +++++ .../mlx5/core/diag/en_tc_tracepoint.h | 31 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tc.c | 2 ++ 3 files changed, 40 insertions(+) diff --git a/Documentation/networking/device_drivers/mellanox/mlx5.rst b/Documentation/networking/device_drivers/mellanox/mlx5.rst index 1339dbf52431..b2f21ce9b090 100644 --- a/Documentation/networking/device_drivers/mellanox/mlx5.rst +++ b/Documentation/networking/device_drivers/mellanox/mlx5.rst @@ -251,3 +251,10 @@ tc and eswitch offloads tracepoints: $ cat /sys/kernel/debug/tracing/trace ... tc-6546 [010] ...1 2679.704889: mlx5e_stats_flower: cookie=0000000060eb3d6a bytes=0 packets=0 lastused=4295560217 + +- mlx5e_tc_update_neigh_used_value: trace tunnel rule neigh update value offloaded to mlx5:: + + $ echo mlx5:mlx5e_tc_update_neigh_used_value >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u48:4-8806 [009] ...1 55117.882428: mlx5e_tc_update_neigh_used_value: netdev: ens1f0 IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_used=1 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h index a362100fe6d3..d4e6cfaaade3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_tc_tracepoint.h @@ -10,6 +10,7 @@ #include #include #include +#include "en_rep.h" #define __parse_action(ids, num) parse_action(p, ids, num) @@ -73,6 +74,36 @@ TRACE_EVENT(mlx5e_stats_flower, ) ); +TRACE_EVENT(mlx5e_tc_update_neigh_used_value, + TP_PROTO(const struct mlx5e_neigh_hash_entry *nhe, bool neigh_used), + TP_ARGS(nhe, neigh_used), + TP_STRUCT__entry(__string(devname, nhe->m_neigh.dev->name) + __array(u8, v4, 4) + __array(u8, v6, 16) + __field(bool, neigh_used) + ), + TP_fast_assign(const struct mlx5e_neigh *mn = &nhe->m_neigh; + struct in6_addr *pin6; + __be32 *p32; + + __assign_str(devname, mn->dev->name); + __entry->neigh_used = neigh_used; + + p32 = (__be32 *)__entry->v4; + pin6 = (struct in6_addr *)__entry->v6; + if (mn->family == AF_INET) { + *p32 = mn->dst_ip.v4; + ipv6_addr_set_v4mapped(*p32, pin6); + } else if (mn->family == AF_INET6) { + *pin6 = mn->dst_ip.v6; + } + ), + TP_printk("netdev: %s IPv4: %pI4 IPv6: %pI6c neigh_used=%d\n", + __get_str(devname), __entry->v4, __entry->v6, + __entry->neigh_used + ) +); + #endif /* _MLX5_TC_TP_ */ /* This part must be outside protection */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c40cca08c8cc..5581a8045ede 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1536,6 +1536,8 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) } } + trace_mlx5e_tc_update_neigh_used_value(nhe, neigh_used); + if (neigh_used) { nhe->reported_lastuse = jiffies; -- GitLab From 5970882a2510e8bffaef518a82ea207798187a93 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 25 Jun 2019 22:40:20 +0300 Subject: [PATCH 3969/7155] net/mlx5e: Add trace point for neigh update Allow tracing neigh state during neigh update task that is executed on workqueue and is scheduled by neigh state change event. Usage example: ># cd /sys/kernel/debug/tracing ># echo mlx5:mlx5e_rep_neigh_update >> set_event ># cat trace ... kworker/u48:7-2221 [009] ...1 1475.387435: mlx5e_rep_neigh_update: netdev: ens1f0 MAC: 24:8a:07:9a:17:9a IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_connected=1 Added corresponding documentation in Documentation/networking/device-driver/mellanox/mlx5.rst Signed-off-by: Vlad Buslov Reviewed-by: Dmytro Linkin Signed-off-by: Saeed Mahameed --- .../device_drivers/mellanox/mlx5.rst | 7 +++ .../mlx5/core/diag/en_rep_tracepoint.h | 54 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_rep.c | 4 ++ 3 files changed, 65 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/diag/en_rep_tracepoint.h diff --git a/Documentation/networking/device_drivers/mellanox/mlx5.rst b/Documentation/networking/device_drivers/mellanox/mlx5.rst index b2f21ce9b090..b30a63dbf4b7 100644 --- a/Documentation/networking/device_drivers/mellanox/mlx5.rst +++ b/Documentation/networking/device_drivers/mellanox/mlx5.rst @@ -258,3 +258,10 @@ tc and eswitch offloads tracepoints: $ cat /sys/kernel/debug/tracing/trace ... kworker/u48:4-8806 [009] ...1 55117.882428: mlx5e_tc_update_neigh_used_value: netdev: ens1f0 IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_used=1 + +- mlx5e_rep_neigh_update: trace neigh update tasks scheduled due to neigh state change events:: + + $ echo mlx5:mlx5e_rep_neigh_update >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u48:7-2221 [009] ...1 1475.387435: mlx5e_rep_neigh_update: netdev: ens1f0 MAC: 24:8a:07:9a:17:9a IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_connected=1 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/en_rep_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_rep_tracepoint.h new file mode 100644 index 000000000000..1177860a2ee4 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/en_rep_tracepoint.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlx5 + +#if !defined(_MLX5_EN_REP_TP_) || defined(TRACE_HEADER_MULTI_READ) +#define _MLX5_EN_REP_TP_ + +#include +#include +#include "en_rep.h" + +TRACE_EVENT(mlx5e_rep_neigh_update, + TP_PROTO(const struct mlx5e_neigh_hash_entry *nhe, const u8 *ha, + bool neigh_connected), + TP_ARGS(nhe, ha, neigh_connected), + TP_STRUCT__entry(__string(devname, nhe->m_neigh.dev->name) + __array(u8, ha, ETH_ALEN) + __array(u8, v4, 4) + __array(u8, v6, 16) + __field(bool, neigh_connected) + ), + TP_fast_assign(const struct mlx5e_neigh *mn = &nhe->m_neigh; + struct in6_addr *pin6; + __be32 *p32; + + __assign_str(devname, mn->dev->name); + __entry->neigh_connected = neigh_connected; + memcpy(__entry->ha, ha, ETH_ALEN); + + p32 = (__be32 *)__entry->v4; + pin6 = (struct in6_addr *)__entry->v6; + if (mn->family == AF_INET) { + *p32 = mn->dst_ip.v4; + ipv6_addr_set_v4mapped(*p32, pin6); + } else if (mn->family == AF_INET6) { + *pin6 = mn->dst_ip.v6; + } + ), + TP_printk("netdev: %s MAC: %pM IPv4: %pI4 IPv6: %pI6c neigh_connected=%d\n", + __get_str(devname), __entry->ha, + __entry->v4, __entry->v6, __entry->neigh_connected + ) +); + +#endif /* _MLX5_EN_REP_TP_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ./diag +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE en_rep_tracepoint +#include diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 5217f39828a4..3c0d36b2b91c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -46,6 +46,8 @@ #include "en/tc_tun.h" #include "fs_core.h" #include "lib/port_tun.h" +#define CREATE_TRACE_POINTS +#include "diag/en_rep_tracepoint.h" #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \ max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE) @@ -657,6 +659,8 @@ static void mlx5e_rep_neigh_update(struct work_struct *work) neigh_connected = (nud_state & NUD_VALID) && !dead; + trace_mlx5e_rep_neigh_update(nhe, ha, neigh_connected); + list_for_each_entry(e, &nhe->encap_list, encap_list) { if (!mlx5e_encap_take(e)) continue; -- GitLab From f117249e4b7831248404ff1fb47bfe44c355caea Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 12:39:51 +0530 Subject: [PATCH 3970/7155] soc: qcom: smem: Update max processor count Update max processor count to reflect the number of co-processors on SC7180 SoCs. Reviewed-by: Vinod Koul Tested-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 0caf67e2f037..28c19bcb2f20 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -84,7 +84,7 @@ #define SMEM_GLOBAL_HOST 0xfffe /* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 10 +#define SMEM_HOST_COUNT 11 /** * struct smem_proc_comm - proc_comm communication struct (legacy) -- GitLab From 2aabdf3b50eabad59107f6adfc24436d9bda4fb9 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 12:39:52 +0530 Subject: [PATCH 3971/7155] dt-bindings: firmware: scm: re-order compatible list re-order compatible list to maintain sort order. Tested-by: Vinod Koul Reviewed-by: Rob Herring Reviewed-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt index 41f133a4e2fa..d19be836df53 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt @@ -9,13 +9,13 @@ Required properties: - compatible: must contain one of the following: * "qcom,scm-apq8064" * "qcom,scm-apq8084" + * "qcom,scm-ipq4019" * "qcom,scm-msm8660" * "qcom,scm-msm8916" * "qcom,scm-msm8960" * "qcom,scm-msm8974" * "qcom,scm-msm8996" * "qcom,scm-msm8998" - * "qcom,scm-ipq4019" * "qcom,scm-sdm845" and: * "qcom,scm" -- GitLab From e6fdc7ad66f115a24e00058299297c33ba34343a Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 12:39:53 +0530 Subject: [PATCH 3972/7155] dt-bindings: firmware: scm: Add SM8150 and SC7180 support Add compatible for SM8150 and SC7180 SoCs. Tested-by: Vinod Koul Reviewed-by: Rob Herring Reviewed-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/firmware/qcom,scm.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt index d19be836df53..3f29ea04b5fe 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt @@ -16,7 +16,9 @@ Required properties: * "qcom,scm-msm8974" * "qcom,scm-msm8996" * "qcom,scm-msm8998" + * "qcom,scm-sc7180" * "qcom,scm-sdm845" + * "qcom,scm-sm8150" and: * "qcom,scm" - clocks: Specifies clocks needed by the SCM interface, if any: -- GitLab From a1c4743e990d9a4a3254b4d13be2921f59bee019 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 12:39:56 +0530 Subject: [PATCH 3973/7155] dt-bindings: soc: qcom: aoss: Add SM8150 and SC7180 support Add SM8150 and SC7180 AOSS QMP to the list of possible bindings. Tested-by: Vinod Koul Reviewed-by: Rob Herring Reviewed-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt index 954ffee0a9c4..4fc571e78f01 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt @@ -15,7 +15,10 @@ power-domains. - compatible: Usage: required Value type: - Definition: must be "qcom,sdm845-aoss-qmp" + Definition: must be one of: + "qcom,sc7180-aoss-qmp" + "qcom,sdm845-aoss-qmp" + "qcom,sm8150-aoss-qmp" - reg: Usage: required -- GitLab From 1709510221c57fd566479c228434ff9edd6435be Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 12:39:57 +0530 Subject: [PATCH 3974/7155] soc: qcom: aoss: Add AOSS QMP support Add AOSS QMP support for SM8150 and SC7180 SoCs. Reviewed-by: Vinod Koul Tested-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 443dab2207de..33a27e6c6d67 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -592,7 +592,9 @@ static int qmp_remove(struct platform_device *pdev) } static const struct of_device_id qmp_dt_match[] = { + { .compatible = "qcom,sc7180-aoss-qmp", }, { .compatible = "qcom,sdm845-aoss-qmp", }, + { .compatible = "qcom,sm8150-aoss-qmp", }, {} }; MODULE_DEVICE_TABLE(of, qmp_dt_match); -- GitLab From ff296293b3538d19278a7f7cd1f3aa600ad9164c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 19 Aug 2019 08:02:45 -0700 Subject: [PATCH 3975/7155] random: Support freezable kthreads in add_hwgenerator_randomness() The kthread calling this function is freezable after commit 03a3bb7ae631 ("hwrng: core - Freeze khwrng thread during suspend") is applied. Unfortunately, this function uses wait_event_interruptible() but doesn't check for the kthread being woken up by the fake freezer signal. When a user suspends the system, this kthread will wake up and if it fails the entropy size check it will immediately go back to sleep and not go into the freezer. Eventually, suspend will fail because the task never froze and a warning message like this may appear: PM: suspend entry (deep) Filesystems sync: 0.000 seconds Freezing user space processes ... (elapsed 0.001 seconds) done. OOM killer disabled. Freezing remaining freezable tasks ... Freezing of tasks failed after 20.003 seconds (1 tasks refusing to freeze, wq_busy=0): hwrng R running task 0 289 2 0x00000020 [] (__schedule) from [] (schedule+0x3c/0xc0) [] (schedule) from [] (add_hwgenerator_randomness+0xb0/0x100) [] (add_hwgenerator_randomness) from [] (hwrng_fillfn+0xc0/0x14c [rng_core]) [] (hwrng_fillfn [rng_core]) from [] (kthread+0x134/0x148) [] (kthread) from [] (ret_from_fork+0x14/0x2c) Check for a freezer signal here and skip adding any randomness if the task wakes up because it was frozen. This should make the kthread freeze properly and suspend work again. Fixes: 03a3bb7ae631 ("hwrng: core - Freeze khwrng thread during suspend") Reported-by: Keerthy Tested-by: Keerthy Signed-off-by: Stephen Boyd Signed-off-by: Herbert Xu --- drivers/char/random.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 5d5ea4ce1442..e2e85ca16410 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2429,6 +2429,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy) { struct entropy_store *poolp = &input_pool; + bool frozen = false; if (unlikely(crng_init == 0)) { crng_fast_load(buffer, count); @@ -2439,9 +2440,12 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, * We'll be woken up again once below random_write_wakeup_thresh, * or when the calling thread is about to terminate. */ - wait_event_interruptible(random_write_wait, kthread_should_stop() || + wait_event_interruptible(random_write_wait, + kthread_freezable_should_stop(&frozen) || ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); - mix_pool_bytes(poolp, buffer, count); - credit_entropy_bits(poolp, entropy); + if (!frozen) { + mix_pool_bytes(poolp, buffer, count); + credit_entropy_bits(poolp, entropy); + } } EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); -- GitLab From b0c091ae04f6746f541b9be91809e1f4f43e9a65 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 12 Aug 2019 12:32:57 -0700 Subject: [PATCH 3976/7155] lib/mpi: Eliminate unused umul_ppmm definitions for MIPS Clang errors out when building this macro: lib/mpi/generic_mpih-mul1.c:37:24: error: invalid use of a cast in a inline asm context requiring an l-value: remove the cast or build with -fheinous-gnu-extensions umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb); ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lib/mpi/longlong.h:652:20: note: expanded from macro 'umul_ppmm' : "=l" ((USItype)(w0)), \ ~~~~~~~~~~^~~ lib/mpi/generic_mpih-mul1.c:37:3: error: invalid output constraint '=h' in asm umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb); ^ lib/mpi/longlong.h:653:7: note: expanded from macro 'umul_ppmm' "=h" ((USItype)(w1)) \ ^ 2 errors generated. The C version that is used for GCC 4.4 and up works well with clang; however, it is not currently being used because Clang masks itself as GCC 4.2.1 for compatibility reasons. As Nick points out, we require GCC 4.6 and newer in the kernel so we can eliminate all of the versioning checks and just use the C version of umul_ppmm for all supported compilers. Link: https://github.com/ClangBuiltLinux/linux/issues/605 Suggested-by: Nick Desaulniers Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: Herbert Xu --- lib/mpi/longlong.h | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 3bb6260d8f42..2dceaca27489 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -639,30 +639,12 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4) #define umul_ppmm(w1, w0, u, v) \ do { \ UDItype __ll = (UDItype)(u) * (v); \ w1 = __ll >> 32; \ w0 = __ll; \ } while (0) -#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3" \ - : "=l" ((USItype)(w0)), \ - "=h" ((USItype)(w1)) \ - : "d" ((USItype)(u)), \ - "d" ((USItype)(v))) -#else -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3\n" \ - "mflo %0\n" \ - "mfhi %1" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "d" ((USItype)(u)), \ - "d" ((USItype)(v))) -#endif #define UMUL_TIME 10 #define UDIV_TIME 100 #endif /* __mips__ */ @@ -687,7 +669,7 @@ do { \ : "d" ((UDItype)(u)), \ "d" ((UDItype)(v))); \ } while (0) -#elif (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4) +#else #define umul_ppmm(w1, w0, u, v) \ do { \ typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ @@ -695,22 +677,6 @@ do { \ w1 = __ll >> 64; \ w0 = __ll; \ } while (0) -#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3" \ - : "=l" ((UDItype)(w0)), \ - "=h" ((UDItype)(w1)) \ - : "d" ((UDItype)(u)), \ - "d" ((UDItype)(v))) -#else -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3\n" \ - "mflo %0\n" \ - "mfhi %1" \ - : "=d" ((UDItype)(w0)), \ - "=d" ((UDItype)(w1)) \ - : "d" ((UDItype)(u)), \ - "d" ((UDItype)(v))) #endif #define UMUL_TIME 20 #define UDIV_TIME 140 -- GitLab From 220f67917ae649336b5fef4dec8024fed4b177f3 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 13 Aug 2019 09:06:10 +0300 Subject: [PATCH 3977/7155] MAINTAINERS: nx crypto: Fix typo in a filepath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typo in nx_debugfs.c filepath. File extension changed from .h to .c The file nx_debugfs.h never existed. Cc: Breno Leitão Cc: Nayna Jain Cc: Paulo Flabiano Smorigo Cc: Dan Streetman Cc: Herbert Xu Cc: linux-crypto@vger.kernel.org Signed-off-by: Denis Efremov Signed-off-by: Herbert Xu --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 667aac441f75..99e41aba12ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7671,7 +7671,7 @@ F: drivers/crypto/nx/nx-aes* F: drivers/crypto/nx/nx-sha* F: drivers/crypto/nx/nx.* F: drivers/crypto/nx/nx_csbcpb.h -F: drivers/crypto/nx/nx_debugfs.h +F: drivers/crypto/nx/nx_debugfs.c IBM Power Linux RAID adapter M: Brian King -- GitLab From 6ee41e5420d0afa8cddf09aa7384dabe570f8dc7 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:43 +0300 Subject: [PATCH 3978/7155] crypto: des/3des_ede - add new helpers to verify keys The recently added helper routine to perform key strength validation of triple DES keys is slightly inadequate, since it comes in two versions, neither of which are highly useful for anything other than skciphers (and many drivers still use the older blkcipher interfaces). So let's add a new helper and, considering that this is a helper function that is only intended to be used by crypto code itself, put it in a new des.h header under crypto/internal. While at it, implement a similar helper for single DES, so that we can start replacing the pattern of calling des_ekey() into a temp buffer that occurs in many drivers in drivers/crypto. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/des_generic.c | 13 ---- include/crypto/internal/des.h | 141 ++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 13 deletions(-) create mode 100644 include/crypto/internal/des.h diff --git a/crypto/des_generic.c b/crypto/des_generic.c index dc085514408a..c4d8ecda4ddf 100644 --- a/crypto/des_generic.c +++ b/crypto/des_generic.c @@ -841,19 +841,6 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) d[1] = cpu_to_le32(L); } -/* - * RFC2451: - * - * For DES-EDE3, there is no known need to reject weak or - * complementation keys. Any weakness is obviated by the use of - * multiple keys. - * - * However, if the first two or last two independent 64-bit keys are - * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the - * same as DES. Implementers MUST reject keys that exhibit this - * property. - * - */ int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, unsigned int keylen) { diff --git a/include/crypto/internal/des.h b/include/crypto/internal/des.h new file mode 100644 index 000000000000..f5d2e696522e --- /dev/null +++ b/include/crypto/internal/des.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * DES & Triple DES EDE key verification helpers + */ + +#ifndef __CRYPTO_INTERNAL_DES_H +#define __CRYPTO_INTERNAL_DES_H + +#include +#include +#include +#include +#include + +/** + * crypto_des_verify_key - Check whether a DES key is weak + * @tfm: the crypto algo + * @key: the key buffer + * + * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak + * keys. Otherwise, 0 is returned. + * + * It is the job of the caller to ensure that the size of the key equals + * DES_KEY_SIZE. + */ +static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key) +{ + u32 tmp[DES_EXPKEY_WORDS]; + int err = 0; + + if (!(crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) + return 0; + + if (!des_ekey(tmp, key)) { + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); + err = -EINVAL; + } + + memzero_explicit(tmp, sizeof(tmp)); + return err; +} + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + * + */ + +/** + * crypto_des3_ede_verify_key - Check whether a DES3-EDE key is weak + * @tfm: the crypto algo + * @key: the key buffer + * + * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak + * keys or when running in FIPS mode. Otherwise, 0 is returned. Note that some + * keys are rejected in FIPS mode even if weak keys are permitted by the TFM + * flags. + * + * It is the job of the caller to ensure that the size of the key equals + * DES3_EDE_KEY_SIZE. + */ +static inline int crypto_des3_ede_verify_key(struct crypto_tfm *tfm, + const u8 *key) +{ + int err = -EINVAL; + u32 K[6]; + + memcpy(K, key, DES3_EDE_KEY_SIZE); + + if ((!((K[0] ^ K[2]) | (K[1] ^ K[3])) || + !((K[2] ^ K[4]) | (K[3] ^ K[5]))) && + (fips_enabled || (crypto_tfm_get_flags(tfm) & + CRYPTO_TFM_REQ_FORBID_WEAK_KEYS))) + goto bad; + + if ((!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled) + goto bad; + + err = 0; +out: + memzero_explicit(K, DES3_EDE_KEY_SIZE); + return err; + +bad: + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); + goto out; +} + +static inline int verify_skcipher_des_key(struct crypto_skcipher *tfm, + const u8 *key) +{ + return crypto_des_verify_key(crypto_skcipher_tfm(tfm), key); +} + +static inline int verify_skcipher_des3_key(struct crypto_skcipher *tfm, + const u8 *key) +{ + return crypto_des3_ede_verify_key(crypto_skcipher_tfm(tfm), key); +} + +static inline int verify_ablkcipher_des_key(struct crypto_ablkcipher *tfm, + const u8 *key) +{ + return crypto_des_verify_key(crypto_ablkcipher_tfm(tfm), key); +} + +static inline int verify_ablkcipher_des3_key(struct crypto_ablkcipher *tfm, + const u8 *key) +{ + return crypto_des3_ede_verify_key(crypto_ablkcipher_tfm(tfm), key); +} + +static inline int verify_aead_des_key(struct crypto_aead *tfm, const u8 *key, + int keylen) +{ + if (keylen != DES_KEY_SIZE) { + crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + return crypto_des_verify_key(crypto_aead_tfm(tfm), key); +} + +static inline int verify_aead_des3_key(struct crypto_aead *tfm, const u8 *key, + int keylen) +{ + if (keylen != DES3_EDE_KEY_SIZE) { + crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + return crypto_des3_ede_verify_key(crypto_aead_tfm(tfm), key); +} + +#endif /* __CRYPTO_INTERNAL_DES_H */ -- GitLab From 4e2c820897d93a4dbe76865d860087f809963308 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:44 +0300 Subject: [PATCH 3979/7155] crypto: s390/des - switch to new verification routines Switch to the refactored DES key verification routines. While at it, rename the DES encrypt/decrypt routines so they will not conflict with the DES library later on. Reviewed-by: Harald Freudenberger Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/s390/crypto/des_s390.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index 374b42fc7637..439b100c6f2e 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) @@ -35,27 +35,24 @@ static int des_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); - u32 tmp[DES_EXPKEY_WORDS]; + int err; - /* check for weak keys */ - if (!des_ekey(tmp, key) && - (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = crypto_des_verify_key(tfm, key); + if (err) + return err; memcpy(ctx->key, key, key_len); return 0; } -static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void s390_des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); } -static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static void s390_des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); @@ -76,8 +73,8 @@ static struct crypto_alg des_alg = { .cia_min_keysize = DES_KEY_SIZE, .cia_max_keysize = DES_KEY_SIZE, .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt, + .cia_encrypt = s390_des_encrypt, + .cia_decrypt = s390_des_decrypt, } } }; @@ -227,8 +224,8 @@ static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); int err; - err = __des3_verify_key(&tfm->crt_flags, key); - if (unlikely(err)) + err = crypto_des3_ede_verify_key(tfm, key); + if (err) return err; memcpy(ctx->key, key, key_len); -- GitLab From 8f467cf29f192f9ebd89dcc4a18901e62c17e37a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:45 +0300 Subject: [PATCH 3980/7155] crypto: sparc/des - switch to new verification routines Switch to the refactored DES key verification routines. While at it, rename the DES encrypt/decrypt routines so they will not conflict with the DES library later on. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/sparc/crypto/des_glue.c | 37 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c index 281448f72c90..db6010b4e52e 100644 --- a/arch/sparc/crypto/des_glue.c +++ b/arch/sparc/crypto/des_glue.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -45,19 +45,15 @@ static int des_set_key(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - u32 tmp[DES_EXPKEY_WORDS]; - int ret; + int err; /* Even though we have special instructions for key expansion, - * we call des_ekey() so that we don't have to write our own + * we call des_verify_key() so that we don't have to write our own * weak key detection code. */ - ret = des_ekey(tmp, key); - if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = crypto_des_verify_key(tfm, key); + if (err) + return err; des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]); encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]); @@ -68,7 +64,7 @@ static int des_set_key(struct crypto_tfm *tfm, const u8 *key, extern void des_sparc64_crypt(const u64 *key, const u64 *input, u64 *output); -static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void sparc_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); const u64 *K = ctx->encrypt_expkey; @@ -76,7 +72,7 @@ static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); } -static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void sparc_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); const u64 *K = ctx->decrypt_expkey; @@ -202,14 +198,13 @@ static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; u64 k1[DES_EXPKEY_WORDS / 2]; u64 k2[DES_EXPKEY_WORDS / 2]; u64 k3[DES_EXPKEY_WORDS / 2]; int err; - err = __des3_verify_key(flags, key); - if (unlikely(err)) + err = crypto_des3_ede_verify_key(tfm, key); + if (err) return err; des_sparc64_key_expand((const u32 *)key, k1); @@ -235,7 +230,7 @@ static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key, extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input, u64 *output); -static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void sparc_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); const u64 *K = ctx->encrypt_expkey; @@ -243,7 +238,7 @@ static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); } -static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void sparc_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); const u64 *K = ctx->decrypt_expkey; @@ -390,8 +385,8 @@ static struct crypto_alg algs[] = { { .cia_min_keysize = DES_KEY_SIZE, .cia_max_keysize = DES_KEY_SIZE, .cia_setkey = des_set_key, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt + .cia_encrypt = sparc_des_encrypt, + .cia_decrypt = sparc_des_decrypt } } }, { @@ -447,8 +442,8 @@ static struct crypto_alg algs[] = { { .cia_min_keysize = DES3_EDE_KEY_SIZE, .cia_max_keysize = DES3_EDE_KEY_SIZE, .cia_setkey = des3_ede_set_key, - .cia_encrypt = des3_ede_encrypt, - .cia_decrypt = des3_ede_decrypt + .cia_encrypt = sparc_des3_ede_encrypt, + .cia_decrypt = sparc_des3_ede_decrypt } } }, { -- GitLab From 92c203e2dca3c816c7001e429134f412d9d89389 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:46 +0300 Subject: [PATCH 3981/7155] crypto: atmel/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 6256883a89ed..1a6c86ae6148 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -773,22 +773,12 @@ static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd) static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { - u32 tmp[DES_EXPKEY_WORDS]; - int err; - struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); - struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + int err; - if (keylen != DES_KEY_SIZE) { - crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - err = des_ekey(tmp, key); - if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = verify_ablkcipher_des_key(tfm, key); + if (err) + return err; memcpy(ctx->key, key, keylen); ctx->keylen = keylen; @@ -800,15 +790,11 @@ static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(tfm); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(tfm, flags); + err = verify_ablkcipher_des3_key(tfm, key); + if (err) return err; - } memcpy(ctx->key, key, keylen); ctx->keylen = keylen; -- GitLab From 05a7238d085f6cfaff9ad41e56f74d9923afa091 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:47 +0300 Subject: [PATCH 3982/7155] crypto: bcm/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/bcm/cipher.c | 79 ++++++++----------------------------- 1 file changed, 17 insertions(+), 62 deletions(-) diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 1c23e452700b..f85356a48e7e 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -1802,24 +1802,13 @@ static int des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct iproc_ctx_s *ctx = crypto_ablkcipher_ctx(cipher); - u32 tmp[DES_EXPKEY_WORDS]; - - if (keylen == DES_KEY_SIZE) { - if (des_ekey(tmp, key) == 0) { - if (crypto_ablkcipher_get_flags(cipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) { - u32 flags = CRYPTO_TFM_RES_WEAK_KEY; + int err; - crypto_ablkcipher_set_flags(cipher, flags); - return -EINVAL; - } - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; - ctx->cipher_type = CIPHER_TYPE_DES; - } else { - crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } + ctx->cipher_type = CIPHER_TYPE_DES; return 0; } @@ -1827,23 +1816,13 @@ static int threedes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct iproc_ctx_s *ctx = crypto_ablkcipher_ctx(cipher); + int err; - if (keylen == (DES_KEY_SIZE * 3)) { - u32 flags; - int ret; - - flags = crypto_ablkcipher_get_flags(cipher); - ret = __des3_verify_key(&flags, key); - if (unlikely(ret)) { - crypto_ablkcipher_set_flags(cipher, flags); - return ret; - } + err = verify_ablkcipher_des3_key(cipher, key); + if (err) + return err; - ctx->cipher_type = CIPHER_TYPE_3DES; - } else { - crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } + ctx->cipher_type = CIPHER_TYPE_3DES; return 0; } @@ -2868,40 +2847,16 @@ static int aead_authenc_setkey(struct crypto_aead *cipher, switch (ctx->alg->cipher_info.alg) { case CIPHER_ALG_DES: - if (ctx->enckeylen == DES_KEY_SIZE) { - u32 tmp[DES_EXPKEY_WORDS]; - u32 flags = CRYPTO_TFM_RES_WEAK_KEY; - - if (des_ekey(tmp, keys.enckey) == 0) { - if (crypto_aead_get_flags(cipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) { - crypto_aead_set_flags(cipher, flags); - return -EINVAL; - } - } + if (verify_aead_des_key(cipher, keys.enckey, keys.enckeylen)) + return -EINVAL; - ctx->cipher_type = CIPHER_TYPE_DES; - } else { - goto badkey; - } + ctx->cipher_type = CIPHER_TYPE_DES; break; case CIPHER_ALG_3DES: - if (ctx->enckeylen == (DES_KEY_SIZE * 3)) { - u32 flags; - - flags = crypto_aead_get_flags(cipher); - ret = __des3_verify_key(&flags, keys.enckey); - if (unlikely(ret)) { - crypto_aead_set_flags(cipher, flags); - return ret; - } - - ctx->cipher_type = CIPHER_TYPE_3DES; - } else { - crypto_aead_set_flags(cipher, - CRYPTO_TFM_RES_BAD_KEY_LEN); + if (verify_aead_des3_key(cipher, keys.enckey, keys.enckeylen)) return -EINVAL; - } + + ctx->cipher_type = CIPHER_TYPE_3DES; break; case CIPHER_ALG_AES: switch (ctx->enckeylen) { -- GitLab From a628c5a11d8b87a16dbc0d5bbc9b6ff233865622 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:48 +0300 Subject: [PATCH 3983/7155] crypto: caam/des - switch to new verification routines Cc: Horia Geanta Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 49 ++++++++----------------------- drivers/crypto/caam/caamalg_qi.c | 36 ++++------------------- drivers/crypto/caam/caamalg_qi2.c | 36 +++++++---------------- drivers/crypto/caam/compat.h | 2 +- 4 files changed, 31 insertions(+), 92 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 947ba8ef487a..3e2662cda9fd 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -628,33 +628,17 @@ static int des3_aead_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_authenc_keys keys; - u32 flags; int err; err = crypto_authenc_extractkeys(&keys, key, keylen); if (unlikely(err)) - goto badkey; - - err = -EINVAL; - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; - - flags = crypto_aead_get_flags(aead); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) { - crypto_aead_set_flags(aead, flags); - goto out; - } + return err; - err = aead_setkey(aead, key, keylen); + err = verify_aead_des3_key(aead, keys.enckey, keys.enckeylen) ?: + aead_setkey(aead, key, keylen); -out: memzero_explicit(&keys, sizeof(keys)); return err; - -badkey: - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - goto out; } static int gcm_setkey(struct crypto_aead *aead, @@ -843,22 +827,15 @@ static int arc4_skcipher_setkey(struct crypto_skcipher *skcipher, static int des_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { - u32 tmp[DES3_EDE_EXPKEY_WORDS]; - struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); - - if (keylen == DES3_EDE_KEY_SIZE && - __des3_ede_setkey(tmp, &tfm->crt_flags, key, DES3_EDE_KEY_SIZE)) { - return -EINVAL; - } - - if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - crypto_skcipher_set_flags(skcipher, - CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; - } + return verify_skcipher_des_key(skcipher, key) ?: + skcipher_setkey(skcipher, key, keylen, 0); +} - return skcipher_setkey(skcipher, key, keylen, 0); +static int des3_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + return verify_skcipher_des3_key(skcipher, key) ?: + skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, @@ -1954,7 +1931,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-3des-caam", .cra_blocksize = DES3_EDE_BLOCK_SIZE, }, - .setkey = des_skcipher_setkey, + .setkey = des3_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, @@ -2073,7 +2050,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "ecb-des3-caam", .cra_blocksize = DES3_EDE_BLOCK_SIZE, }, - .setkey = des_skcipher_setkey, + .setkey = des3_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index fb54b2c9d337..932643c88a5d 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -278,33 +278,17 @@ static int des3_aead_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_authenc_keys keys; - u32 flags; int err; err = crypto_authenc_extractkeys(&keys, key, keylen); if (unlikely(err)) - goto badkey; - - err = -EINVAL; - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; - - flags = crypto_aead_get_flags(aead); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) { - crypto_aead_set_flags(aead, flags); - goto out; - } + return err; - err = aead_setkey(aead, key, keylen); + err = verify_aead_des3_key(aead, keys.enckey, keys.enckeylen) ?: + aead_setkey(aead, key, keylen); -out: memzero_explicit(&keys, sizeof(keys)); return err; - -badkey: - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - goto out; } static int gcm_set_sh_desc(struct crypto_aead *aead) @@ -745,23 +729,15 @@ static int ctr_skcipher_setkey(struct crypto_skcipher *skcipher, static int des3_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { - return unlikely(des3_verify_key(skcipher, key)) ?: + return verify_skcipher_des3_key(skcipher, key) ?: skcipher_setkey(skcipher, key, keylen, 0); } static int des_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { - u32 tmp[DES_EXPKEY_WORDS]; - - if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - crypto_skcipher_set_flags(skcipher, - CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; - } - - return skcipher_setkey(skcipher, key, keylen, 0); + return verify_skcipher_des_key(skcipher, key) ?: + skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index bd01bcd799e8..3443f6d6dd83 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -322,7 +322,6 @@ static int des3_aead_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_authenc_keys keys; - u32 flags; int err; err = crypto_authenc_extractkeys(&keys, key, keylen); @@ -333,14 +332,8 @@ static int des3_aead_setkey(struct crypto_aead *aead, const u8 *key, if (keys.enckeylen != DES3_EDE_KEY_SIZE) goto badkey; - flags = crypto_aead_get_flags(aead); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) { - crypto_aead_set_flags(aead, flags); - goto out; - } - - err = aead_setkey(aead, key, keylen); + err = crypto_des3_ede_verify_key(crypto_aead_tfm(aead), keys.enckey) ?: + aead_setkey(aead, key, keylen); out: memzero_explicit(&keys, sizeof(keys)); @@ -1070,22 +1063,15 @@ static int chacha20_skcipher_setkey(struct crypto_skcipher *skcipher, static int des_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, unsigned int keylen) { - u32 tmp[DES3_EDE_EXPKEY_WORDS]; - struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); - - if (keylen == DES3_EDE_KEY_SIZE && - __des3_ede_setkey(tmp, &tfm->crt_flags, key, DES3_EDE_KEY_SIZE)) { - return -EINVAL; - } - - if (!des_ekey(tmp, key) && (crypto_skcipher_get_flags(skcipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - crypto_skcipher_set_flags(skcipher, - CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; - } + return verify_skcipher_des_key(skcipher, key) ?: + skcipher_setkey(skcipher, key, keylen, 0); +} - return skcipher_setkey(skcipher, key, keylen, 0); +static int des3_skcipher_setkey(struct crypto_skcipher *skcipher, + const u8 *key, unsigned int keylen) +{ + return verify_skcipher_des3_key(skcipher, key) ?: + skcipher_setkey(skcipher, key, keylen, 0); } static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, @@ -1634,7 +1620,7 @@ static struct caam_skcipher_alg driver_algs[] = { .cra_driver_name = "cbc-3des-caam-qi2", .cra_blocksize = DES3_EDE_BLOCK_SIZE, }, - .setkey = des_skcipher_setkey, + .setkey = des3_skcipher_setkey, .encrypt = skcipher_encrypt, .decrypt = skcipher_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h index 8639b2df0371..60e2a54c19f1 100644 --- a/drivers/crypto/caam/compat.h +++ b/drivers/crypto/caam/compat.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include -- GitLab From 0e1cbe9795ace1ea5e1621e52b9d918d9382fcfd Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:49 +0300 Subject: [PATCH 3984/7155] crypto: cpt/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/cavium/cpt/cptvf_algs.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/cavium/cpt/cptvf_algs.c b/drivers/crypto/cavium/cpt/cptvf_algs.c index ff3cb1f8f2b6..596ce28b957d 100644 --- a/drivers/crypto/cavium/cpt/cptvf_algs.c +++ b/drivers/crypto/cavium/cpt/cptvf_algs.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -322,31 +322,15 @@ static int cvm_cfb_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, static int cvm_cbc_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, u32 keylen) { - u32 flags = crypto_ablkcipher_get_flags(cipher); - int err; - - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); - return err; - } - - return cvm_setkey(cipher, key, keylen, DES3_CBC); + return verify_ablkcipher_des3_key(cipher, key) ?: + cvm_setkey(cipher, key, keylen, DES3_CBC); } static int cvm_ecb_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, u32 keylen) { - u32 flags = crypto_ablkcipher_get_flags(cipher); - int err; - - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); - return err; - } - - return cvm_setkey(cipher, key, keylen, DES3_ECB); + return verify_ablkcipher_des3_key(cipher, key) ?: + cvm_setkey(cipher, key, keylen, DES3_ECB); } static int cvm_enc_dec_init(struct crypto_tfm *tfm) -- GitLab From 43d81a8b258e1ed894af0f5d81921365004b6d90 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:50 +0300 Subject: [PATCH 3985/7155] crypto: nitrox/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/cavium/nitrox/nitrox_skcipher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/cavium/nitrox/nitrox_skcipher.c b/drivers/crypto/cavium/nitrox/nitrox_skcipher.c index 7e4a5e69085e..3cdce1f0f257 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_skcipher.c +++ b/drivers/crypto/cavium/nitrox/nitrox_skcipher.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include "nitrox_dev.h" @@ -257,7 +257,7 @@ static int nitrox_aes_decrypt(struct skcipher_request *skreq) static int nitrox_3des_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int keylen) { - return unlikely(des3_verify_key(cipher, key)) ?: + return verify_skcipher_des3_key(cipher, key) ?: nitrox_skcipher_setkey(cipher, 0, key, keylen); } -- GitLab From b525041633145828bd6744a4d1b79dbc084315b3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:51 +0300 Subject: [PATCH 3986/7155] crypto: ccp/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-des3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/ccp/ccp-crypto-des3.c b/drivers/crypto/ccp/ccp-crypto-des3.c index 5f05f834c7cd..d2c49b2f0323 100644 --- a/drivers/crypto/ccp/ccp-crypto-des3.c +++ b/drivers/crypto/ccp/ccp-crypto-des3.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "ccp-crypto.h" @@ -39,11 +39,10 @@ static int ccp_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); struct ccp_crypto_ablkcipher_alg *alg = ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm)); - u32 *flags = &tfm->base.crt_flags; int err; - err = __des3_verify_key(flags, key); - if (unlikely(err)) + err = verify_ablkcipher_des3_key(tfm, key); + if (err) return err; /* It's not clear that there is any support for a keysize of 112. -- GitLab From 00cd6b233fc89463d4f4eddeb9abf1e009cc09c0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:52 +0300 Subject: [PATCH 3987/7155] crypto: ccree/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 24 ++++-------------------- drivers/crypto/ccree/cc_cipher.c | 15 ++++----------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index a9779a212b18..d3e8faa03f15 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include "cc_driver.h" #include "cc_buffer_mgr.h" @@ -649,33 +649,17 @@ static int cc_des3_aead_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_authenc_keys keys; - u32 flags; int err; err = crypto_authenc_extractkeys(&keys, key, keylen); if (unlikely(err)) - goto badkey; - - err = -EINVAL; - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; + return err; - flags = crypto_aead_get_flags(aead); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) { - crypto_aead_set_flags(aead, flags); - goto out; - } + err = verify_aead_des3_key(aead, keys.enckey, keys.enckeylen) ?: + cc_aead_setkey(aead, key, keylen); - err = cc_aead_setkey(aead, key, keylen); - -out: memzero_explicit(&keys, sizeof(keys)); return err; - -badkey: - crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); - goto out; } static int cc_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c index 5b58226ea24d..c7ec20e90fc0 100644 --- a/drivers/crypto/ccree/cc_cipher.c +++ b/drivers/crypto/ccree/cc_cipher.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include @@ -411,16 +411,9 @@ static int cc_cipher_setkey(struct crypto_skcipher *sktfm, const u8 *key, * HW does the expansion on its own. */ if (ctx_p->flow_mode == S_DIN_to_DES) { - u32 tmp[DES3_EDE_EXPKEY_WORDS]; - if (keylen == DES3_EDE_KEY_SIZE && - __des3_ede_setkey(tmp, &tfm->crt_flags, key, - DES3_EDE_KEY_SIZE)) { - dev_dbg(dev, "weak 3DES key"); - return -EINVAL; - } else if (!des_ekey(tmp, key) && - (crypto_tfm_get_flags(tfm) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; + if ((keylen == DES3_EDE_KEY_SIZE && + verify_skcipher_des3_key(sktfm, key)) || + verify_skcipher_des_key(sktfm, key)) { dev_dbg(dev, "weak DES key"); return -EINVAL; } -- GitLab From f4ed68609798211f6503e66d7d371230ea18cf14 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:53 +0300 Subject: [PATCH 3988/7155] crypto: hifn/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/hifn_795x.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 5c3f02e4aece..a18e62df68d9 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -21,7 +21,7 @@ #include #include -#include +#include static char hifn_pll_ref[sizeof("extNNN")] = "ext"; module_param_string(hifn_pll_ref, hifn_pll_ref, sizeof(hifn_pll_ref), 0444); @@ -1939,25 +1939,13 @@ static void hifn_flush(struct hifn_device *dev) static int hifn_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len) { - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); - struct hifn_context *ctx = crypto_tfm_ctx(tfm); + struct hifn_context *ctx = crypto_ablkcipher_ctx(cipher); struct hifn_device *dev = ctx->dev; + int err; - if (len > HIFN_MAX_CRYPT_KEY_LENGTH) { - crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -1; - } - - if (len == HIFN_DES_KEY_LENGTH) { - u32 tmp[DES_EXPKEY_WORDS]; - int ret = des_ekey(tmp, key); - - if (unlikely(ret == 0) && - (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; dev->flags &= ~HIFN_FLAG_OLD_KEY; @@ -1972,15 +1960,11 @@ static int hifn_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, { struct hifn_context *ctx = crypto_ablkcipher_ctx(cipher); struct hifn_device *dev = ctx->dev; - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } dev->flags &= ~HIFN_FLAG_OLD_KEY; -- GitLab From 894b68d8be4b305615ab3be52667478fe5f6e0b5 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:54 +0300 Subject: [PATCH 3989/7155] crypto: hisilicon/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec/sec_algs.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c index 02768af0dccd..e0508ea160f1 100644 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -347,25 +347,21 @@ static int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm, static int sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { - if (keylen != DES_KEY_SIZE) - return -EINVAL; - - return sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64); + return verify_skcipher_des_key(tfm, key) ?: + sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64); } static int sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { - if (keylen != DES_KEY_SIZE) - return -EINVAL; - - return sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64); + return verify_skcipher_des_key(tfm, key) ?: + sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64); } static int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { - return unlikely(des3_verify_key(tfm, key)) ?: + return verify_skcipher_des3_key(tfm, key) ?: sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_3DES_ECB_192_3KEY); } @@ -373,7 +369,7 @@ static int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm, static int sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { - return unlikely(des3_verify_key(tfm, key)) ?: + return verify_skcipher_des3_key(tfm, key) ?: sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_3DES_CBC_192_3KEY); } -- GitLab From 21f5a15e0f26c7ea15bee9ed3c5fd1daa40b0b77 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:55 +0300 Subject: [PATCH 3990/7155] crypto: safexcel/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- .../crypto/inside-secure/safexcel_cipher.c | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 5682fe8b606e..16c4d5460334 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -220,7 +220,6 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, struct safexcel_crypto_priv *priv = ctx->priv; struct crypto_authenc_keys keys; struct crypto_aes_ctx aes; - u32 flags; int err = -EINVAL; if (crypto_authenc_extractkeys(&keys, key, len) != 0) @@ -241,12 +240,7 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, /* Encryption key */ switch (ctx->alg) { case SAFEXCEL_3DES: - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; - flags = crypto_aead_get_flags(ctfm); - err = __des3_verify_key(&flags, keys.enckey); - crypto_aead_set_flags(ctfm, flags); - + err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen); if (unlikely(err)) goto badkey_expflags; break; @@ -1192,16 +1186,12 @@ static int safexcel_cbc_des_decrypt(struct skcipher_request *req) static int safexcel_des_setkey(struct crypto_skcipher *ctfm, const u8 *key, unsigned int len) { - struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); - struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); - u32 tmp[DES_EXPKEY_WORDS]; + struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); int ret; - ret = des_ekey(tmp, key); - if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + ret = verify_skcipher_des_key(ctfm, key); + if (ret) + return ret; /* if context exits and key changed, need to invalidate it */ if (ctx->base.ctxr_dma) @@ -1299,8 +1289,8 @@ static int safexcel_des3_ede_setkey(struct crypto_skcipher *ctfm, struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); int err; - err = des3_verify_key(ctfm, key); - if (unlikely(err)) + err = verify_skcipher_des3_key(ctfm, key); + if (err) return err; /* if context exits and key changed, need to invalidate it */ -- GitLab From 3ca20b65cbfd1acd733c2d12848261b00b2d55e1 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:56 +0300 Subject: [PATCH 3991/7155] crypto: ixp4xx/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/ixp4xx_crypto.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index acedafe3fa98..9181523ba760 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -756,10 +756,7 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt, } cipher_cfg |= keylen_cfg; } else { - u32 tmp[DES_EXPKEY_WORDS]; - if (des_ekey(tmp, key) == 0) { - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - } + crypto_des_verify_key(tfm, key); } /* write cfg word to cryptinfo */ *(u32*)cinfo = cpu_to_be32(cipher_cfg); @@ -851,14 +848,8 @@ static int ablk_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int ablk_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int key_len) { - u32 flags = crypto_ablkcipher_get_flags(tfm); - int err; - - err = __des3_verify_key(&flags, key); - if (unlikely(err)) - crypto_ablkcipher_set_flags(tfm, flags); - - return ablk_setkey(tfm, key, key_len); + return verify_ablkcipher_des3_key(tfm, key) ?: + ablk_setkey(tfm, key, key_len); } static int ablk_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key, @@ -1181,7 +1172,6 @@ static int des3_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) { struct ixp_ctx *ctx = crypto_aead_ctx(tfm); - u32 flags = CRYPTO_TFM_RES_BAD_KEY_LEN; struct crypto_authenc_keys keys; int err; @@ -1193,12 +1183,8 @@ static int des3_aead_setkey(struct crypto_aead *tfm, const u8 *key, if (keys.authkeylen > sizeof(ctx->authkey)) goto badkey; - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; - - flags = crypto_aead_get_flags(tfm); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) + err = verify_aead_des3_key(tfm, keys.enckey, keys.enckeylen); + if (err) goto badkey; memcpy(ctx->authkey, keys.authkey, keys.authkeylen); @@ -1209,7 +1195,6 @@ static int des3_aead_setkey(struct crypto_aead *tfm, const u8 *key, memzero_explicit(&keys, sizeof(keys)); return aead_setup(tfm, crypto_aead_authsize(tfm)); badkey: - crypto_aead_set_flags(tfm, flags); memzero_explicit(&keys, sizeof(keys)); return err; } -- GitLab From 9bfa85ebd5eec6c357ab348b8fbca73529111bd7 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:57 +0300 Subject: [PATCH 3992/7155] crypto: cesa/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cipher.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index fa1997e70b63..84ceddfee76b 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -10,7 +10,7 @@ */ #include -#include +#include #include "cesa.h" @@ -272,21 +272,12 @@ static int mv_cesa_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len) { - struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); - struct mv_cesa_des_ctx *ctx = crypto_tfm_ctx(tfm); - u32 tmp[DES_EXPKEY_WORDS]; - int ret; - - if (len != DES_KEY_SIZE) { - crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } + struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher); + int err; - ret = des_ekey(tmp, key); - if (!ret && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = verify_skcipher_des_key(cipher, key); + if (err) + return err; memcpy(ctx->key, key, DES_KEY_SIZE); @@ -299,8 +290,8 @@ static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher, struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher); int err; - err = des3_verify_key(cipher, key); - if (unlikely(err)) + err = verify_skcipher_des3_key(cipher, key); + if (err) return err; memcpy(ctx->key, key, DES3_EDE_KEY_SIZE); -- GitLab From d4b90dbc8578c567827901e625018ead7561f741 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:58 +0300 Subject: [PATCH 3993/7155] crypto: n2/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/n2_core.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 760e72a5893b..4765163df6be 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -757,24 +757,15 @@ static int n2_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, static int n2_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); - struct n2_cipher_context *ctx = crypto_tfm_ctx(tfm); + struct n2_cipher_context *ctx = crypto_ablkcipher_ctx(cipher); struct n2_cipher_alg *n2alg = n2_cipher_alg(tfm); - u32 tmp[DES_EXPKEY_WORDS]; int err; - ctx->enc_type = n2alg->enc_type; - - if (keylen != DES_KEY_SIZE) { - crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; - err = des_ekey(tmp, key); - if (err == 0 && (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + ctx->enc_type = n2alg->enc_type; ctx->key_len = keylen; memcpy(ctx->key.des, key, keylen); @@ -784,18 +775,13 @@ static int n2_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, static int n2_3des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); - struct n2_cipher_context *ctx = crypto_tfm_ctx(tfm); + struct n2_cipher_context *ctx = crypto_ablkcipher_ctx(cipher); struct n2_cipher_alg *n2alg = n2_cipher_alg(tfm); - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } ctx->enc_type = n2alg->enc_type; -- GitLab From 304daa4f0ee54e42dea9e167e162caba17d48543 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:00:59 +0300 Subject: [PATCH 3994/7155] crypto: omap/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/omap-des.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 484a693122af..b19d7e5d55ec 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -650,20 +650,13 @@ static int omap_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(cipher); - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + int err; pr_debug("enter, keylen: %d\n", keylen); - /* Do we need to test against weak key? */ - if (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) { - u32 tmp[DES_EXPKEY_WORDS]; - int ret = des_ekey(tmp, key); - - if (!ret) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; memcpy(ctx->key, key, keylen); ctx->keylen = keylen; @@ -672,20 +665,16 @@ static int omap_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, } static int omap_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, - unsigned int keylen) + unsigned int keylen) { struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(cipher); - u32 flags; int err; pr_debug("enter, keylen: %d\n", keylen); - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } memcpy(ctx->key, key, keylen); ctx->keylen = keylen; -- GitLab From 0157fb268893cddeb79c3cb6fc05d13a132aa66c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:00 +0300 Subject: [PATCH 3995/7155] crypto: picoxcell/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/picoxcell_crypto.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c index 9a939b4fd32f..3cbefb41b099 100644 --- a/drivers/crypto/picoxcell_crypto.c +++ b/drivers/crypto/picoxcell_crypto.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -736,16 +736,12 @@ static void spacc_aead_cra_exit(struct crypto_aead *tfm) static int spacc_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len) { - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); - struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm); - u32 tmp[DES_EXPKEY_WORDS]; + struct spacc_ablk_ctx *ctx = crypto_ablkcipher_ctx(cipher); + int err; - if (unlikely(!des_ekey(tmp, key)) && - (crypto_ablkcipher_get_flags(cipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; memcpy(ctx->key, key, len); ctx->key_len = len; @@ -761,15 +757,11 @@ static int spacc_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len) { struct spacc_ablk_ctx *ctx = crypto_ablkcipher_ctx(cipher); - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } memcpy(ctx->key, key, len); ctx->key_len = len; -- GitLab From f96c897c855cfbde74d92f5cd65dc1108799bd8a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:01 +0300 Subject: [PATCH 3996/7155] crypto: qce/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/qce/ablkcipher.c | 55 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c index a976210ba41c..7a98bf5cc967 100644 --- a/drivers/crypto/qce/ablkcipher.c +++ b/drivers/crypto/qce/ablkcipher.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include "cipher.h" @@ -154,27 +154,17 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); - unsigned long flags = to_cipher_tmpl(tfm)->alg_flags; int ret; if (!key || !keylen) return -EINVAL; - if (IS_AES(flags)) { - switch (keylen) { - case AES_KEYSIZE_128: - case AES_KEYSIZE_256: - break; - default: - goto fallback; - } - } else if (IS_DES(flags)) { - u32 tmp[DES_EXPKEY_WORDS]; - - ret = des_ekey(tmp, key); - if (!ret && (crypto_ablkcipher_get_flags(ablk) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) - goto weakkey; + switch (keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: + break; + default: + goto fallback; } ctx->enc_keylen = keylen; @@ -185,24 +175,32 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, if (!ret) ctx->enc_keylen = keylen; return ret; -weakkey: - crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; +} + +static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key, + unsigned int keylen) +{ + struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); + int err; + + err = verify_ablkcipher_des_key(ablk, key); + if (err) + return err; + + ctx->enc_keylen = keylen; + memcpy(ctx->enc_key, key, keylen); + return 0; } static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key, unsigned int keylen) { struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(ablk); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(ablk, flags); + err = verify_ablkcipher_des3_key(ablk, key); + if (err) return err; - } ctx->enc_keylen = keylen; memcpy(ctx->enc_key, key, keylen); @@ -374,8 +372,9 @@ static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, alg->cra_ablkcipher.ivsize = def->ivsize; alg->cra_ablkcipher.min_keysize = def->min_keysize; alg->cra_ablkcipher.max_keysize = def->max_keysize; - alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? - qce_des3_setkey : qce_ablkcipher_setkey; + alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey : + IS_DES(def->flags) ? qce_des_setkey : + qce_ablkcipher_setkey; alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; -- GitLab From 4eaef05210cbe7052adf53d030fd44b37b69c5a3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:02 +0300 Subject: [PATCH 3997/7155] crypto: rk3288/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto.h | 2 +- .../rockchip/rk3288_crypto_ablkcipher.c | 21 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h index 54ee5b3ed9db..18e2b3f29336 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.h +++ b/drivers/crypto/rockchip/rk3288_crypto.h @@ -3,7 +3,7 @@ #define __RK3288_CRYPTO_H__ #include -#include +#include #include #include #include diff --git a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c index 96078aaa2098..d0f4b2d18059 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c +++ b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c @@ -46,15 +46,12 @@ static int rk_aes_setkey(struct crypto_ablkcipher *cipher, static int rk_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); - struct rk_cipher_ctx *ctx = crypto_tfm_ctx(tfm); - u32 tmp[DES_EXPKEY_WORDS]; + struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(cipher); + int err; - if (!des_ekey(tmp, key) && - (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; ctx->keylen = keylen; memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); @@ -65,15 +62,11 @@ static int rk_tdes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(cipher); - u32 flags; int err; - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } ctx->keylen = keylen; memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); -- GitLab From b5d0ba83a0fb09b8dfd8bfdd9072d532da4f3091 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:03 +0300 Subject: [PATCH 3998/7155] crypto: stm32/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/stm32/stm32-cryp.c | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index 5cf6679da580..ba5ea6434f9c 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -767,35 +767,15 @@ static int stm32_cryp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int stm32_cryp_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { - u32 tmp[DES_EXPKEY_WORDS]; - - if (keylen != DES_KEY_SIZE) - return -EINVAL; - - if ((crypto_ablkcipher_get_flags(tfm) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) && - unlikely(!des_ekey(tmp, key))) { - crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; - } - - return stm32_cryp_setkey(tfm, key, keylen); + return verify_ablkcipher_des_key(tfm, key) ?: + stm32_cryp_setkey(tfm, key, keylen); } static int stm32_cryp_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { - u32 flags; - int err; - - flags = crypto_ablkcipher_get_flags(tfm); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(tfm, flags); - return err; - } - - return stm32_cryp_setkey(tfm, key, keylen); + return verify_ablkcipher_des3_key(tfm, key) ?: + stm32_cryp_setkey(tfm, key, keylen); } static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, -- GitLab From 08d4b408e8f51562676fa47b728abd6ddf9828c2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:04 +0300 Subject: [PATCH 3999/7155] crypto: sun4i/des - switch to new verification routines Cc: Corentin Labbe Acked-by: Corentin Labbe Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 26 ++++++----------------- drivers/crypto/sunxi-ss/sun4i-ss.h | 2 +- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 6f7cbf6c2b55..6536fd4bee65 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -542,25 +542,11 @@ int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); - struct sun4i_ss_ctx *ss = op->ss; - u32 flags; - u32 tmp[DES_EXPKEY_WORDS]; - int ret; - - if (unlikely(keylen != DES_KEY_SIZE)) { - dev_err(ss->dev, "Invalid keylen %u\n", keylen); - crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - flags = crypto_skcipher_get_flags(tfm); + int err; - ret = des_ekey(tmp, key); - if (unlikely(!ret) && (flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - dev_dbg(ss->dev, "Weak key %u\n", keylen); - return -EINVAL; - } + err = verify_skcipher_des_key(tfm, key); + if (err) + return err; op->keylen = keylen; memcpy(op->key, key, keylen); @@ -578,8 +564,8 @@ int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); int err; - err = des3_verify_key(tfm, key); - if (unlikely(err)) + err = verify_skcipher_des3_key(tfm, key); + if (err) return err; op->keylen = keylen; diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h index 8654d48aedc0..35a27a7145f8 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss.h +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include -- GitLab From 9d574ae8ebc1e6e485ef949f086157601008a9d3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:05 +0300 Subject: [PATCH 4000/7155] crypto: talitos/des - switch to new verification routines Cc: Christophe Leroy Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index c9d686a0e805..117c831b5ede 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include @@ -936,15 +936,9 @@ static int aead_des3_setkey(struct crypto_aead *authenc, if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) goto badkey; - if (keys.enckeylen != DES3_EDE_KEY_SIZE) - goto badkey; - - flags = crypto_aead_get_flags(authenc); - err = __des3_verify_key(&flags, keys.enckey); - if (unlikely(err)) { - crypto_aead_set_flags(authenc, flags); + err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen); + if (err) goto out; - } if (ctx->keylen) dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); @@ -1517,32 +1511,15 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, static int ablkcipher_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - u32 tmp[DES_EXPKEY_WORDS]; - - if (unlikely(crypto_ablkcipher_get_flags(cipher) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) && - !des_ekey(tmp, key)) { - crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY); - return -EINVAL; - } - - return ablkcipher_setkey(cipher, key, keylen); + return verify_ablkcipher_des_key(cipher, key) ?: + ablkcipher_setkey(cipher, key, keylen); } static int ablkcipher_des3_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - u32 flags; - int err; - - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); - return err; - } - - return ablkcipher_setkey(cipher, key, keylen); + return verify_ablkcipher_des3_key(cipher, key) ?: + ablkcipher_setkey(cipher, key, keylen); } static int ablkcipher_aes_setkey(struct crypto_ablkcipher *cipher, -- GitLab From dcb15794ec571c10243c24eaff8512b789dfef2a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:06 +0300 Subject: [PATCH 4001/7155] crypto: ux500/des - switch to new verification routines Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/ux500/cryp/cryp_core.c | 31 ++++++--------------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index b4beb54c0dbe..e966e9a64501 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -987,26 +987,13 @@ static int des_ablkcipher_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher); - u32 *flags = &cipher->base.crt_flags; - u32 tmp[DES_EXPKEY_WORDS]; - int ret; + int err; pr_debug(DEV_DBG_NAME " [%s]", __func__); - if (keylen != DES_KEY_SIZE) { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_BAD_KEY_LEN", - __func__); - return -EINVAL; - } - ret = des_ekey(tmp, key); - if (unlikely(ret == 0) && - (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - pr_debug(DEV_DBG_NAME " [%s]: CRYPTO_TFM_RES_WEAK_KEY", - __func__); - return -EINVAL; - } + err = verify_ablkcipher_des_key(cipher, key); + if (err) + return err; memcpy(ctx->key, key, keylen); ctx->keylen = keylen; @@ -1019,17 +1006,13 @@ static int des3_ablkcipher_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct cryp_ctx *ctx = crypto_ablkcipher_ctx(cipher); - u32 flags; int err; pr_debug(DEV_DBG_NAME " [%s]", __func__); - flags = crypto_ablkcipher_get_flags(cipher); - err = __des3_verify_key(&flags, key); - if (unlikely(err)) { - crypto_ablkcipher_set_flags(cipher, flags); + err = verify_ablkcipher_des3_key(cipher, key); + if (err) return err; - } memcpy(ctx->key, key, keylen); ctx->keylen = keylen; -- GitLab From 4fd4be0576166f0b360d22744e143cd7847b0c29 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:07 +0300 Subject: [PATCH 4002/7155] crypto: 3des - move verification out of exported routine In preparation of moving the shared key expansion routine into the DES library, move the verification done by __des3_ede_setkey() into its callers. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/des3_ede_glue.c | 4 ++++ crypto/des_generic.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/crypto/des3_ede_glue.c b/arch/x86/crypto/des3_ede_glue.c index 968386c21ef4..ec608babc22b 100644 --- a/arch/x86/crypto/des3_ede_glue.c +++ b/arch/x86/crypto/des3_ede_glue.c @@ -348,6 +348,10 @@ static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key, u32 i, j, tmp; int err; + err = crypto_des3_ede_verify_key(tfm, key); + if (err) + return err; + /* Generate encryption context using generic implementation. */ err = __des3_ede_setkey(ctx->enc_expkey, &tfm->crt_flags, key, keylen); if (err < 0) diff --git a/crypto/des_generic.c b/crypto/des_generic.c index c4d8ecda4ddf..f15ae7660f1b 100644 --- a/crypto/des_generic.c +++ b/crypto/des_generic.c @@ -846,10 +846,6 @@ int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, { int err; - err = __des3_verify_key(flags, key); - if (unlikely(err)) - return err; - des_ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; des_ekey(expkey, key); @@ -862,8 +858,12 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; u32 *expkey = dctx->expkey; + int err; + + err = crypto_des3_ede_verify_key(tfm, key); + if (err) + return err; return __des3_ede_setkey(expkey, flags, key, keylen); } -- GitLab From 6b5c4818621fb0d3eda1d4059634b38e09bd7243 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:08 +0300 Subject: [PATCH 4003/7155] crypto: des - remove unused function Remove the old DES3 verification functions that are no longer used. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- include/crypto/des.h | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/include/crypto/des.h b/include/crypto/des.h index 72c7c8e5a5a7..31b04ba835b1 100644 --- a/include/crypto/des.h +++ b/include/crypto/des.h @@ -19,47 +19,6 @@ #define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS) #define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE -static inline int __des3_verify_key(u32 *flags, const u8 *key) -{ - int err = -EINVAL; - u32 K[6]; - - memcpy(K, key, DES3_EDE_KEY_SIZE); - - if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) || - !((K[2] ^ K[4]) | (K[3] ^ K[5]))) && - (fips_enabled || - (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS))) - goto bad; - - if (unlikely(!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled) - goto bad; - - err = 0; - -out: - memzero_explicit(K, DES3_EDE_KEY_SIZE); - - return err; - -bad: - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - goto out; -} - -static inline int des3_verify_key(struct crypto_skcipher *tfm, const u8 *key) -{ - u32 flags; - int err; - - flags = crypto_skcipher_get_flags(tfm); - err = __des3_verify_key(&flags, key); - crypto_skcipher_set_flags(tfm, flags); - return err; -} - -extern unsigned long des_ekey(u32 *pe, const u8 *k); - extern int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, unsigned int keylen); -- GitLab From 04007b0e6cbbab5836ac891626e91edf10d46341 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:09 +0300 Subject: [PATCH 4004/7155] crypto: des - split off DES library from generic DES cipher driver Another one for the cipher museum: split off DES core processing into a separate module so other drivers (mostly for crypto accelerators) can reuse the code without pulling in the generic DES cipher itself. This will also permit the cipher interface to be made private to the crypto API itself once we move the only user in the kernel (CIFS) to this library interface. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/des3_ede_glue.c | 2 +- crypto/Kconfig | 8 +- crypto/des_generic.c | 917 +----------------- drivers/crypto/Kconfig | 28 +- drivers/crypto/caam/Kconfig | 2 +- drivers/crypto/cavium/nitrox/Kconfig | 2 +- .../crypto/inside-secure/safexcel_cipher.c | 2 +- drivers/crypto/stm32/Kconfig | 2 +- drivers/crypto/ux500/Kconfig | 2 +- include/crypto/des.h | 43 +- include/crypto/internal/des.h | 69 +- lib/crypto/Makefile | 3 + lib/crypto/des.c | 902 +++++++++++++++++ 13 files changed, 1053 insertions(+), 929 deletions(-) create mode 100644 lib/crypto/des.c diff --git a/arch/x86/crypto/des3_ede_glue.c b/arch/x86/crypto/des3_ede_glue.c index ec608babc22b..f730a312ce35 100644 --- a/arch/x86/crypto/des3_ede_glue.c +++ b/arch/x86/crypto/des3_ede_glue.c @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include diff --git a/crypto/Kconfig b/crypto/Kconfig index 455a3354e291..42a17fe97703 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1306,9 +1306,13 @@ config CRYPTO_CAST6_AVX_X86_64 This module provides the Cast6 cipher algorithm that processes eight blocks parallel using the AVX instruction set. +config CRYPTO_LIB_DES + tristate + config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" select CRYPTO_ALGAPI + select CRYPTO_LIB_DES help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). @@ -1316,7 +1320,7 @@ config CRYPTO_DES_SPARC64 tristate "DES and Triple DES EDE cipher algorithms (SPARC64)" depends on SPARC64 select CRYPTO_ALGAPI - select CRYPTO_DES + select CRYPTO_LIB_DES help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3), optimized using SPARC64 crypto opcodes. @@ -1325,7 +1329,7 @@ config CRYPTO_DES3_EDE_X86_64 tristate "Triple DES EDE cipher algorithm (x86-64)" depends on X86 && 64BIT select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES help Triple DES EDE (FIPS 46-3) algorithm. diff --git a/crypto/des_generic.c b/crypto/des_generic.c index f15ae7660f1b..e021a321f584 100644 --- a/crypto/des_generic.c +++ b/crypto/des_generic.c @@ -13,832 +13,42 @@ #include #include #include -#include -#include - -#define ROL(x, r) ((x) = rol32((x), (r))) -#define ROR(x, r) ((x) = ror32((x), (r))) - -struct des_ctx { - u32 expkey[DES_EXPKEY_WORDS]; -}; - -struct des3_ede_ctx { - u32 expkey[DES3_EDE_EXPKEY_WORDS]; -}; - -/* Lookup tables for key expansion */ - -static const u8 pc1[256] = { - 0x00, 0x00, 0x40, 0x04, 0x10, 0x10, 0x50, 0x14, - 0x04, 0x40, 0x44, 0x44, 0x14, 0x50, 0x54, 0x54, - 0x02, 0x02, 0x42, 0x06, 0x12, 0x12, 0x52, 0x16, - 0x06, 0x42, 0x46, 0x46, 0x16, 0x52, 0x56, 0x56, - 0x80, 0x08, 0xc0, 0x0c, 0x90, 0x18, 0xd0, 0x1c, - 0x84, 0x48, 0xc4, 0x4c, 0x94, 0x58, 0xd4, 0x5c, - 0x82, 0x0a, 0xc2, 0x0e, 0x92, 0x1a, 0xd2, 0x1e, - 0x86, 0x4a, 0xc6, 0x4e, 0x96, 0x5a, 0xd6, 0x5e, - 0x20, 0x20, 0x60, 0x24, 0x30, 0x30, 0x70, 0x34, - 0x24, 0x60, 0x64, 0x64, 0x34, 0x70, 0x74, 0x74, - 0x22, 0x22, 0x62, 0x26, 0x32, 0x32, 0x72, 0x36, - 0x26, 0x62, 0x66, 0x66, 0x36, 0x72, 0x76, 0x76, - 0xa0, 0x28, 0xe0, 0x2c, 0xb0, 0x38, 0xf0, 0x3c, - 0xa4, 0x68, 0xe4, 0x6c, 0xb4, 0x78, 0xf4, 0x7c, - 0xa2, 0x2a, 0xe2, 0x2e, 0xb2, 0x3a, 0xf2, 0x3e, - 0xa6, 0x6a, 0xe6, 0x6e, 0xb6, 0x7a, 0xf6, 0x7e, - 0x08, 0x80, 0x48, 0x84, 0x18, 0x90, 0x58, 0x94, - 0x0c, 0xc0, 0x4c, 0xc4, 0x1c, 0xd0, 0x5c, 0xd4, - 0x0a, 0x82, 0x4a, 0x86, 0x1a, 0x92, 0x5a, 0x96, - 0x0e, 0xc2, 0x4e, 0xc6, 0x1e, 0xd2, 0x5e, 0xd6, - 0x88, 0x88, 0xc8, 0x8c, 0x98, 0x98, 0xd8, 0x9c, - 0x8c, 0xc8, 0xcc, 0xcc, 0x9c, 0xd8, 0xdc, 0xdc, - 0x8a, 0x8a, 0xca, 0x8e, 0x9a, 0x9a, 0xda, 0x9e, - 0x8e, 0xca, 0xce, 0xce, 0x9e, 0xda, 0xde, 0xde, - 0x28, 0xa0, 0x68, 0xa4, 0x38, 0xb0, 0x78, 0xb4, - 0x2c, 0xe0, 0x6c, 0xe4, 0x3c, 0xf0, 0x7c, 0xf4, - 0x2a, 0xa2, 0x6a, 0xa6, 0x3a, 0xb2, 0x7a, 0xb6, - 0x2e, 0xe2, 0x6e, 0xe6, 0x3e, 0xf2, 0x7e, 0xf6, - 0xa8, 0xa8, 0xe8, 0xac, 0xb8, 0xb8, 0xf8, 0xbc, - 0xac, 0xe8, 0xec, 0xec, 0xbc, 0xf8, 0xfc, 0xfc, - 0xaa, 0xaa, 0xea, 0xae, 0xba, 0xba, 0xfa, 0xbe, - 0xae, 0xea, 0xee, 0xee, 0xbe, 0xfa, 0xfe, 0xfe -}; - -static const u8 rs[256] = { - 0x00, 0x00, 0x80, 0x80, 0x02, 0x02, 0x82, 0x82, - 0x04, 0x04, 0x84, 0x84, 0x06, 0x06, 0x86, 0x86, - 0x08, 0x08, 0x88, 0x88, 0x0a, 0x0a, 0x8a, 0x8a, - 0x0c, 0x0c, 0x8c, 0x8c, 0x0e, 0x0e, 0x8e, 0x8e, - 0x10, 0x10, 0x90, 0x90, 0x12, 0x12, 0x92, 0x92, - 0x14, 0x14, 0x94, 0x94, 0x16, 0x16, 0x96, 0x96, - 0x18, 0x18, 0x98, 0x98, 0x1a, 0x1a, 0x9a, 0x9a, - 0x1c, 0x1c, 0x9c, 0x9c, 0x1e, 0x1e, 0x9e, 0x9e, - 0x20, 0x20, 0xa0, 0xa0, 0x22, 0x22, 0xa2, 0xa2, - 0x24, 0x24, 0xa4, 0xa4, 0x26, 0x26, 0xa6, 0xa6, - 0x28, 0x28, 0xa8, 0xa8, 0x2a, 0x2a, 0xaa, 0xaa, - 0x2c, 0x2c, 0xac, 0xac, 0x2e, 0x2e, 0xae, 0xae, - 0x30, 0x30, 0xb0, 0xb0, 0x32, 0x32, 0xb2, 0xb2, - 0x34, 0x34, 0xb4, 0xb4, 0x36, 0x36, 0xb6, 0xb6, - 0x38, 0x38, 0xb8, 0xb8, 0x3a, 0x3a, 0xba, 0xba, - 0x3c, 0x3c, 0xbc, 0xbc, 0x3e, 0x3e, 0xbe, 0xbe, - 0x40, 0x40, 0xc0, 0xc0, 0x42, 0x42, 0xc2, 0xc2, - 0x44, 0x44, 0xc4, 0xc4, 0x46, 0x46, 0xc6, 0xc6, - 0x48, 0x48, 0xc8, 0xc8, 0x4a, 0x4a, 0xca, 0xca, - 0x4c, 0x4c, 0xcc, 0xcc, 0x4e, 0x4e, 0xce, 0xce, - 0x50, 0x50, 0xd0, 0xd0, 0x52, 0x52, 0xd2, 0xd2, - 0x54, 0x54, 0xd4, 0xd4, 0x56, 0x56, 0xd6, 0xd6, - 0x58, 0x58, 0xd8, 0xd8, 0x5a, 0x5a, 0xda, 0xda, - 0x5c, 0x5c, 0xdc, 0xdc, 0x5e, 0x5e, 0xde, 0xde, - 0x60, 0x60, 0xe0, 0xe0, 0x62, 0x62, 0xe2, 0xe2, - 0x64, 0x64, 0xe4, 0xe4, 0x66, 0x66, 0xe6, 0xe6, - 0x68, 0x68, 0xe8, 0xe8, 0x6a, 0x6a, 0xea, 0xea, - 0x6c, 0x6c, 0xec, 0xec, 0x6e, 0x6e, 0xee, 0xee, - 0x70, 0x70, 0xf0, 0xf0, 0x72, 0x72, 0xf2, 0xf2, - 0x74, 0x74, 0xf4, 0xf4, 0x76, 0x76, 0xf6, 0xf6, - 0x78, 0x78, 0xf8, 0xf8, 0x7a, 0x7a, 0xfa, 0xfa, - 0x7c, 0x7c, 0xfc, 0xfc, 0x7e, 0x7e, 0xfe, 0xfe -}; - -static const u32 pc2[1024] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00040000, 0x00000000, 0x04000000, 0x00100000, - 0x00400000, 0x00000008, 0x00000800, 0x40000000, - 0x00440000, 0x00000008, 0x04000800, 0x40100000, - 0x00000400, 0x00000020, 0x08000000, 0x00000100, - 0x00040400, 0x00000020, 0x0c000000, 0x00100100, - 0x00400400, 0x00000028, 0x08000800, 0x40000100, - 0x00440400, 0x00000028, 0x0c000800, 0x40100100, - 0x80000000, 0x00000010, 0x00000000, 0x00800000, - 0x80040000, 0x00000010, 0x04000000, 0x00900000, - 0x80400000, 0x00000018, 0x00000800, 0x40800000, - 0x80440000, 0x00000018, 0x04000800, 0x40900000, - 0x80000400, 0x00000030, 0x08000000, 0x00800100, - 0x80040400, 0x00000030, 0x0c000000, 0x00900100, - 0x80400400, 0x00000038, 0x08000800, 0x40800100, - 0x80440400, 0x00000038, 0x0c000800, 0x40900100, - 0x10000000, 0x00000000, 0x00200000, 0x00001000, - 0x10040000, 0x00000000, 0x04200000, 0x00101000, - 0x10400000, 0x00000008, 0x00200800, 0x40001000, - 0x10440000, 0x00000008, 0x04200800, 0x40101000, - 0x10000400, 0x00000020, 0x08200000, 0x00001100, - 0x10040400, 0x00000020, 0x0c200000, 0x00101100, - 0x10400400, 0x00000028, 0x08200800, 0x40001100, - 0x10440400, 0x00000028, 0x0c200800, 0x40101100, - 0x90000000, 0x00000010, 0x00200000, 0x00801000, - 0x90040000, 0x00000010, 0x04200000, 0x00901000, - 0x90400000, 0x00000018, 0x00200800, 0x40801000, - 0x90440000, 0x00000018, 0x04200800, 0x40901000, - 0x90000400, 0x00000030, 0x08200000, 0x00801100, - 0x90040400, 0x00000030, 0x0c200000, 0x00901100, - 0x90400400, 0x00000038, 0x08200800, 0x40801100, - 0x90440400, 0x00000038, 0x0c200800, 0x40901100, - 0x00000200, 0x00080000, 0x00000000, 0x00000004, - 0x00040200, 0x00080000, 0x04000000, 0x00100004, - 0x00400200, 0x00080008, 0x00000800, 0x40000004, - 0x00440200, 0x00080008, 0x04000800, 0x40100004, - 0x00000600, 0x00080020, 0x08000000, 0x00000104, - 0x00040600, 0x00080020, 0x0c000000, 0x00100104, - 0x00400600, 0x00080028, 0x08000800, 0x40000104, - 0x00440600, 0x00080028, 0x0c000800, 0x40100104, - 0x80000200, 0x00080010, 0x00000000, 0x00800004, - 0x80040200, 0x00080010, 0x04000000, 0x00900004, - 0x80400200, 0x00080018, 0x00000800, 0x40800004, - 0x80440200, 0x00080018, 0x04000800, 0x40900004, - 0x80000600, 0x00080030, 0x08000000, 0x00800104, - 0x80040600, 0x00080030, 0x0c000000, 0x00900104, - 0x80400600, 0x00080038, 0x08000800, 0x40800104, - 0x80440600, 0x00080038, 0x0c000800, 0x40900104, - 0x10000200, 0x00080000, 0x00200000, 0x00001004, - 0x10040200, 0x00080000, 0x04200000, 0x00101004, - 0x10400200, 0x00080008, 0x00200800, 0x40001004, - 0x10440200, 0x00080008, 0x04200800, 0x40101004, - 0x10000600, 0x00080020, 0x08200000, 0x00001104, - 0x10040600, 0x00080020, 0x0c200000, 0x00101104, - 0x10400600, 0x00080028, 0x08200800, 0x40001104, - 0x10440600, 0x00080028, 0x0c200800, 0x40101104, - 0x90000200, 0x00080010, 0x00200000, 0x00801004, - 0x90040200, 0x00080010, 0x04200000, 0x00901004, - 0x90400200, 0x00080018, 0x00200800, 0x40801004, - 0x90440200, 0x00080018, 0x04200800, 0x40901004, - 0x90000600, 0x00080030, 0x08200000, 0x00801104, - 0x90040600, 0x00080030, 0x0c200000, 0x00901104, - 0x90400600, 0x00080038, 0x08200800, 0x40801104, - 0x90440600, 0x00080038, 0x0c200800, 0x40901104, - 0x00000002, 0x00002000, 0x20000000, 0x00000001, - 0x00040002, 0x00002000, 0x24000000, 0x00100001, - 0x00400002, 0x00002008, 0x20000800, 0x40000001, - 0x00440002, 0x00002008, 0x24000800, 0x40100001, - 0x00000402, 0x00002020, 0x28000000, 0x00000101, - 0x00040402, 0x00002020, 0x2c000000, 0x00100101, - 0x00400402, 0x00002028, 0x28000800, 0x40000101, - 0x00440402, 0x00002028, 0x2c000800, 0x40100101, - 0x80000002, 0x00002010, 0x20000000, 0x00800001, - 0x80040002, 0x00002010, 0x24000000, 0x00900001, - 0x80400002, 0x00002018, 0x20000800, 0x40800001, - 0x80440002, 0x00002018, 0x24000800, 0x40900001, - 0x80000402, 0x00002030, 0x28000000, 0x00800101, - 0x80040402, 0x00002030, 0x2c000000, 0x00900101, - 0x80400402, 0x00002038, 0x28000800, 0x40800101, - 0x80440402, 0x00002038, 0x2c000800, 0x40900101, - 0x10000002, 0x00002000, 0x20200000, 0x00001001, - 0x10040002, 0x00002000, 0x24200000, 0x00101001, - 0x10400002, 0x00002008, 0x20200800, 0x40001001, - 0x10440002, 0x00002008, 0x24200800, 0x40101001, - 0x10000402, 0x00002020, 0x28200000, 0x00001101, - 0x10040402, 0x00002020, 0x2c200000, 0x00101101, - 0x10400402, 0x00002028, 0x28200800, 0x40001101, - 0x10440402, 0x00002028, 0x2c200800, 0x40101101, - 0x90000002, 0x00002010, 0x20200000, 0x00801001, - 0x90040002, 0x00002010, 0x24200000, 0x00901001, - 0x90400002, 0x00002018, 0x20200800, 0x40801001, - 0x90440002, 0x00002018, 0x24200800, 0x40901001, - 0x90000402, 0x00002030, 0x28200000, 0x00801101, - 0x90040402, 0x00002030, 0x2c200000, 0x00901101, - 0x90400402, 0x00002038, 0x28200800, 0x40801101, - 0x90440402, 0x00002038, 0x2c200800, 0x40901101, - 0x00000202, 0x00082000, 0x20000000, 0x00000005, - 0x00040202, 0x00082000, 0x24000000, 0x00100005, - 0x00400202, 0x00082008, 0x20000800, 0x40000005, - 0x00440202, 0x00082008, 0x24000800, 0x40100005, - 0x00000602, 0x00082020, 0x28000000, 0x00000105, - 0x00040602, 0x00082020, 0x2c000000, 0x00100105, - 0x00400602, 0x00082028, 0x28000800, 0x40000105, - 0x00440602, 0x00082028, 0x2c000800, 0x40100105, - 0x80000202, 0x00082010, 0x20000000, 0x00800005, - 0x80040202, 0x00082010, 0x24000000, 0x00900005, - 0x80400202, 0x00082018, 0x20000800, 0x40800005, - 0x80440202, 0x00082018, 0x24000800, 0x40900005, - 0x80000602, 0x00082030, 0x28000000, 0x00800105, - 0x80040602, 0x00082030, 0x2c000000, 0x00900105, - 0x80400602, 0x00082038, 0x28000800, 0x40800105, - 0x80440602, 0x00082038, 0x2c000800, 0x40900105, - 0x10000202, 0x00082000, 0x20200000, 0x00001005, - 0x10040202, 0x00082000, 0x24200000, 0x00101005, - 0x10400202, 0x00082008, 0x20200800, 0x40001005, - 0x10440202, 0x00082008, 0x24200800, 0x40101005, - 0x10000602, 0x00082020, 0x28200000, 0x00001105, - 0x10040602, 0x00082020, 0x2c200000, 0x00101105, - 0x10400602, 0x00082028, 0x28200800, 0x40001105, - 0x10440602, 0x00082028, 0x2c200800, 0x40101105, - 0x90000202, 0x00082010, 0x20200000, 0x00801005, - 0x90040202, 0x00082010, 0x24200000, 0x00901005, - 0x90400202, 0x00082018, 0x20200800, 0x40801005, - 0x90440202, 0x00082018, 0x24200800, 0x40901005, - 0x90000602, 0x00082030, 0x28200000, 0x00801105, - 0x90040602, 0x00082030, 0x2c200000, 0x00901105, - 0x90400602, 0x00082038, 0x28200800, 0x40801105, - 0x90440602, 0x00082038, 0x2c200800, 0x40901105, - - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000008, 0x00080000, 0x10000000, - 0x02000000, 0x00000000, 0x00000080, 0x00001000, - 0x02000000, 0x00000008, 0x00080080, 0x10001000, - 0x00004000, 0x00000000, 0x00000040, 0x00040000, - 0x00004000, 0x00000008, 0x00080040, 0x10040000, - 0x02004000, 0x00000000, 0x000000c0, 0x00041000, - 0x02004000, 0x00000008, 0x000800c0, 0x10041000, - 0x00020000, 0x00008000, 0x08000000, 0x00200000, - 0x00020000, 0x00008008, 0x08080000, 0x10200000, - 0x02020000, 0x00008000, 0x08000080, 0x00201000, - 0x02020000, 0x00008008, 0x08080080, 0x10201000, - 0x00024000, 0x00008000, 0x08000040, 0x00240000, - 0x00024000, 0x00008008, 0x08080040, 0x10240000, - 0x02024000, 0x00008000, 0x080000c0, 0x00241000, - 0x02024000, 0x00008008, 0x080800c0, 0x10241000, - 0x00000000, 0x01000000, 0x00002000, 0x00000020, - 0x00000000, 0x01000008, 0x00082000, 0x10000020, - 0x02000000, 0x01000000, 0x00002080, 0x00001020, - 0x02000000, 0x01000008, 0x00082080, 0x10001020, - 0x00004000, 0x01000000, 0x00002040, 0x00040020, - 0x00004000, 0x01000008, 0x00082040, 0x10040020, - 0x02004000, 0x01000000, 0x000020c0, 0x00041020, - 0x02004000, 0x01000008, 0x000820c0, 0x10041020, - 0x00020000, 0x01008000, 0x08002000, 0x00200020, - 0x00020000, 0x01008008, 0x08082000, 0x10200020, - 0x02020000, 0x01008000, 0x08002080, 0x00201020, - 0x02020000, 0x01008008, 0x08082080, 0x10201020, - 0x00024000, 0x01008000, 0x08002040, 0x00240020, - 0x00024000, 0x01008008, 0x08082040, 0x10240020, - 0x02024000, 0x01008000, 0x080020c0, 0x00241020, - 0x02024000, 0x01008008, 0x080820c0, 0x10241020, - 0x00000400, 0x04000000, 0x00100000, 0x00000004, - 0x00000400, 0x04000008, 0x00180000, 0x10000004, - 0x02000400, 0x04000000, 0x00100080, 0x00001004, - 0x02000400, 0x04000008, 0x00180080, 0x10001004, - 0x00004400, 0x04000000, 0x00100040, 0x00040004, - 0x00004400, 0x04000008, 0x00180040, 0x10040004, - 0x02004400, 0x04000000, 0x001000c0, 0x00041004, - 0x02004400, 0x04000008, 0x001800c0, 0x10041004, - 0x00020400, 0x04008000, 0x08100000, 0x00200004, - 0x00020400, 0x04008008, 0x08180000, 0x10200004, - 0x02020400, 0x04008000, 0x08100080, 0x00201004, - 0x02020400, 0x04008008, 0x08180080, 0x10201004, - 0x00024400, 0x04008000, 0x08100040, 0x00240004, - 0x00024400, 0x04008008, 0x08180040, 0x10240004, - 0x02024400, 0x04008000, 0x081000c0, 0x00241004, - 0x02024400, 0x04008008, 0x081800c0, 0x10241004, - 0x00000400, 0x05000000, 0x00102000, 0x00000024, - 0x00000400, 0x05000008, 0x00182000, 0x10000024, - 0x02000400, 0x05000000, 0x00102080, 0x00001024, - 0x02000400, 0x05000008, 0x00182080, 0x10001024, - 0x00004400, 0x05000000, 0x00102040, 0x00040024, - 0x00004400, 0x05000008, 0x00182040, 0x10040024, - 0x02004400, 0x05000000, 0x001020c0, 0x00041024, - 0x02004400, 0x05000008, 0x001820c0, 0x10041024, - 0x00020400, 0x05008000, 0x08102000, 0x00200024, - 0x00020400, 0x05008008, 0x08182000, 0x10200024, - 0x02020400, 0x05008000, 0x08102080, 0x00201024, - 0x02020400, 0x05008008, 0x08182080, 0x10201024, - 0x00024400, 0x05008000, 0x08102040, 0x00240024, - 0x00024400, 0x05008008, 0x08182040, 0x10240024, - 0x02024400, 0x05008000, 0x081020c0, 0x00241024, - 0x02024400, 0x05008008, 0x081820c0, 0x10241024, - 0x00000800, 0x00010000, 0x20000000, 0x00000010, - 0x00000800, 0x00010008, 0x20080000, 0x10000010, - 0x02000800, 0x00010000, 0x20000080, 0x00001010, - 0x02000800, 0x00010008, 0x20080080, 0x10001010, - 0x00004800, 0x00010000, 0x20000040, 0x00040010, - 0x00004800, 0x00010008, 0x20080040, 0x10040010, - 0x02004800, 0x00010000, 0x200000c0, 0x00041010, - 0x02004800, 0x00010008, 0x200800c0, 0x10041010, - 0x00020800, 0x00018000, 0x28000000, 0x00200010, - 0x00020800, 0x00018008, 0x28080000, 0x10200010, - 0x02020800, 0x00018000, 0x28000080, 0x00201010, - 0x02020800, 0x00018008, 0x28080080, 0x10201010, - 0x00024800, 0x00018000, 0x28000040, 0x00240010, - 0x00024800, 0x00018008, 0x28080040, 0x10240010, - 0x02024800, 0x00018000, 0x280000c0, 0x00241010, - 0x02024800, 0x00018008, 0x280800c0, 0x10241010, - 0x00000800, 0x01010000, 0x20002000, 0x00000030, - 0x00000800, 0x01010008, 0x20082000, 0x10000030, - 0x02000800, 0x01010000, 0x20002080, 0x00001030, - 0x02000800, 0x01010008, 0x20082080, 0x10001030, - 0x00004800, 0x01010000, 0x20002040, 0x00040030, - 0x00004800, 0x01010008, 0x20082040, 0x10040030, - 0x02004800, 0x01010000, 0x200020c0, 0x00041030, - 0x02004800, 0x01010008, 0x200820c0, 0x10041030, - 0x00020800, 0x01018000, 0x28002000, 0x00200030, - 0x00020800, 0x01018008, 0x28082000, 0x10200030, - 0x02020800, 0x01018000, 0x28002080, 0x00201030, - 0x02020800, 0x01018008, 0x28082080, 0x10201030, - 0x00024800, 0x01018000, 0x28002040, 0x00240030, - 0x00024800, 0x01018008, 0x28082040, 0x10240030, - 0x02024800, 0x01018000, 0x280020c0, 0x00241030, - 0x02024800, 0x01018008, 0x280820c0, 0x10241030, - 0x00000c00, 0x04010000, 0x20100000, 0x00000014, - 0x00000c00, 0x04010008, 0x20180000, 0x10000014, - 0x02000c00, 0x04010000, 0x20100080, 0x00001014, - 0x02000c00, 0x04010008, 0x20180080, 0x10001014, - 0x00004c00, 0x04010000, 0x20100040, 0x00040014, - 0x00004c00, 0x04010008, 0x20180040, 0x10040014, - 0x02004c00, 0x04010000, 0x201000c0, 0x00041014, - 0x02004c00, 0x04010008, 0x201800c0, 0x10041014, - 0x00020c00, 0x04018000, 0x28100000, 0x00200014, - 0x00020c00, 0x04018008, 0x28180000, 0x10200014, - 0x02020c00, 0x04018000, 0x28100080, 0x00201014, - 0x02020c00, 0x04018008, 0x28180080, 0x10201014, - 0x00024c00, 0x04018000, 0x28100040, 0x00240014, - 0x00024c00, 0x04018008, 0x28180040, 0x10240014, - 0x02024c00, 0x04018000, 0x281000c0, 0x00241014, - 0x02024c00, 0x04018008, 0x281800c0, 0x10241014, - 0x00000c00, 0x05010000, 0x20102000, 0x00000034, - 0x00000c00, 0x05010008, 0x20182000, 0x10000034, - 0x02000c00, 0x05010000, 0x20102080, 0x00001034, - 0x02000c00, 0x05010008, 0x20182080, 0x10001034, - 0x00004c00, 0x05010000, 0x20102040, 0x00040034, - 0x00004c00, 0x05010008, 0x20182040, 0x10040034, - 0x02004c00, 0x05010000, 0x201020c0, 0x00041034, - 0x02004c00, 0x05010008, 0x201820c0, 0x10041034, - 0x00020c00, 0x05018000, 0x28102000, 0x00200034, - 0x00020c00, 0x05018008, 0x28182000, 0x10200034, - 0x02020c00, 0x05018000, 0x28102080, 0x00201034, - 0x02020c00, 0x05018008, 0x28182080, 0x10201034, - 0x00024c00, 0x05018000, 0x28102040, 0x00240034, - 0x00024c00, 0x05018008, 0x28182040, 0x10240034, - 0x02024c00, 0x05018000, 0x281020c0, 0x00241034, - 0x02024c00, 0x05018008, 0x281820c0, 0x10241034 -}; - -/* S-box lookup tables */ - -static const u32 S1[64] = { - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const u32 S2[64] = { - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const u32 S3[64] = { - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const u32 S4[64] = { - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const u32 S5[64] = { - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const u32 S6[64] = { - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const u32 S7[64] = { - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const u32 S8[64] = { - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* Encryption components: IP, FP, and round function */ - -#define IP(L, R, T) \ - ROL(R, 4); \ - T = L; \ - L ^= R; \ - L &= 0xf0f0f0f0; \ - R ^= L; \ - L ^= T; \ - ROL(R, 12); \ - T = L; \ - L ^= R; \ - L &= 0xffff0000; \ - R ^= L; \ - L ^= T; \ - ROR(R, 14); \ - T = L; \ - L ^= R; \ - L &= 0xcccccccc; \ - R ^= L; \ - L ^= T; \ - ROL(R, 6); \ - T = L; \ - L ^= R; \ - L &= 0xff00ff00; \ - R ^= L; \ - L ^= T; \ - ROR(R, 7); \ - T = L; \ - L ^= R; \ - L &= 0xaaaaaaaa; \ - R ^= L; \ - L ^= T; \ - ROL(L, 1); - -#define FP(L, R, T) \ - ROR(L, 1); \ - T = L; \ - L ^= R; \ - L &= 0xaaaaaaaa; \ - R ^= L; \ - L ^= T; \ - ROL(R, 7); \ - T = L; \ - L ^= R; \ - L &= 0xff00ff00; \ - R ^= L; \ - L ^= T; \ - ROR(R, 6); \ - T = L; \ - L ^= R; \ - L &= 0xcccccccc; \ - R ^= L; \ - L ^= T; \ - ROL(R, 14); \ - T = L; \ - L ^= R; \ - L &= 0xffff0000; \ - R ^= L; \ - L ^= T; \ - ROR(R, 12); \ - T = L; \ - L ^= R; \ - L &= 0xf0f0f0f0; \ - R ^= L; \ - L ^= T; \ - ROR(R, 4); - -#define ROUND(L, R, A, B, K, d) \ - B = K[0]; A = K[1]; K += d; \ - B ^= R; A ^= R; \ - B &= 0x3f3f3f3f; ROR(A, 4); \ - L ^= S8[0xff & B]; A &= 0x3f3f3f3f; \ - L ^= S6[0xff & (B >> 8)]; B >>= 16; \ - L ^= S7[0xff & A]; \ - L ^= S5[0xff & (A >> 8)]; A >>= 16; \ - L ^= S4[0xff & B]; \ - L ^= S2[0xff & (B >> 8)]; \ - L ^= S3[0xff & A]; \ - L ^= S1[0xff & (A >> 8)]; - -/* - * PC2 lookup tables are organized as 2 consecutive sets of 4 interleaved - * tables of 128 elements. One set is for C_i and the other for D_i, while - * the 4 interleaved tables correspond to four 7-bit subsets of C_i or D_i. - * - * After PC1 each of the variables a,b,c,d contains a 7 bit subset of C_i - * or D_i in bits 7-1 (bit 0 being the least significant). - */ - -#define T1(x) pt[2 * (x) + 0] -#define T2(x) pt[2 * (x) + 1] -#define T3(x) pt[2 * (x) + 2] -#define T4(x) pt[2 * (x) + 3] - -#define DES_PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a)) - -/* - * Encryption key expansion - * - * RFC2451: Weak key checks SHOULD be performed. - * - * FIPS 74: - * - * Keys having duals are keys which produce all zeros, all ones, or - * alternating zero-one patterns in the C and D registers after Permuted - * Choice 1 has operated on the key. - * - */ -unsigned long des_ekey(u32 *pe, const u8 *k) -{ - /* K&R: long is at least 32 bits */ - unsigned long a, b, c, d, w; - const u32 *pt = pc2; - - d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d]; - c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c]; - b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b]; - a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a]; - - pe[15 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; - pe[14 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[13 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[12 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[11 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[10 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 9 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 8 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; - pe[ 7 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 6 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 5 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 4 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 3 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 2 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 1 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; - pe[ 0 * 2 + 0] = DES_PC2(b, c, d, a); - - /* Check if first half is weak */ - w = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]); - - /* Skip to next table set */ - pt += 512; - - d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1]; - c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1]; - b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1]; - a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1]; - - /* Check if second half is weak */ - w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]); - - pe[15 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; - pe[14 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[13 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[12 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[11 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[10 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 9 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 8 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; - pe[ 7 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 6 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 5 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 4 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 3 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 2 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[ 1 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; - pe[ 0 * 2 + 1] = DES_PC2(b, c, d, a); - - /* Fixup: 2413 5768 -> 1357 2468 */ - for (d = 0; d < 16; ++d) { - a = pe[2 * d]; - b = pe[2 * d + 1]; - c = a ^ b; - c &= 0xffff0000; - a ^= c; - b ^= c; - ROL(b, 18); - pe[2 * d] = a; - pe[2 * d + 1] = b; - } - - /* Zero if weak key */ - return w; -} -EXPORT_SYMBOL_GPL(des_ekey); - -/* - * Decryption key expansion - * - * No weak key checking is performed, as this is only used by triple DES - * - */ -static void dkey(u32 *pe, const u8 *k) -{ - /* K&R: long is at least 32 bits */ - unsigned long a, b, c, d; - const u32 *pt = pc2; - - d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d]; - c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c]; - b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b]; - a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a]; - - pe[ 0 * 2] = DES_PC2(a, b, c, d); d = rs[d]; - pe[ 1 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 2 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 3 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 4 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 5 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 6 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 7 * 2] = DES_PC2(d, a, b, c); c = rs[c]; - pe[ 8 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 9 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[10 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[11 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[12 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[13 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[14 * 2] = DES_PC2(c, d, a, b); b = rs[b]; - pe[15 * 2] = DES_PC2(b, c, d, a); - - /* Skip to next table set */ - pt += 512; - - d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1]; - c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1]; - b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1]; - a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1]; - - pe[ 0 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; - pe[ 1 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 2 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 3 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 4 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 5 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; - pe[ 6 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; - pe[ 7 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; - pe[ 8 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[ 9 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[10 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[11 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[12 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; - pe[13 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; - pe[14 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; - pe[15 * 2 + 1] = DES_PC2(b, c, d, a); - - /* Fixup: 2413 5768 -> 1357 2468 */ - for (d = 0; d < 16; ++d) { - a = pe[2 * d]; - b = pe[2 * d + 1]; - c = a ^ b; - c &= 0xffff0000; - a ^= c; - b ^= c; - ROL(b, 18); - pe[2 * d] = a; - pe[2 * d + 1] = b; - } -} +#include static int des_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct des_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - u32 tmp[DES_EXPKEY_WORDS]; - int ret; - - /* Expand to tmp */ - ret = des_ekey(tmp, key); + int err; - if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { - *flags |= CRYPTO_TFM_RES_WEAK_KEY; - return -EINVAL; + err = des_expand_key(dctx, key, keylen); + if (err == -ENOKEY) { + if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) + err = -EINVAL; + else + err = 0; } - /* Copy to output */ - memcpy(dctx->expkey, tmp, sizeof(dctx->expkey)); - - return 0; + if (err) { + memset(dctx, 0, sizeof(*dctx)); + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); + } + return err; } -static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct des_ctx *ctx = crypto_tfm_ctx(tfm); - const u32 *K = ctx->expkey; - const __le32 *s = (const __le32 *)src; - __le32 *d = (__le32 *)dst; - u32 L, R, A, B; - int i; - - L = le32_to_cpu(s[0]); - R = le32_to_cpu(s[1]); - - IP(L, R, A); - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, 2); - ROUND(R, L, A, B, K, 2); - } - FP(R, L, A); + const struct des_ctx *dctx = crypto_tfm_ctx(tfm); - d[0] = cpu_to_le32(R); - d[1] = cpu_to_le32(L); + des_encrypt(dctx, dst, src); } -static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct des_ctx *ctx = crypto_tfm_ctx(tfm); - const u32 *K = ctx->expkey + DES_EXPKEY_WORDS - 2; - const __le32 *s = (const __le32 *)src; - __le32 *d = (__le32 *)dst; - u32 L, R, A, B; - int i; - - L = le32_to_cpu(s[0]); - R = le32_to_cpu(s[1]); + const struct des_ctx *dctx = crypto_tfm_ctx(tfm); - IP(L, R, A); - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, -2); - ROUND(R, L, A, B, K, -2); - } - FP(R, L, A); - - d[0] = cpu_to_le32(R); - d[1] = cpu_to_le32(L); + des_decrypt(dctx, dst, src); } int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, @@ -858,76 +68,37 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *expkey = dctx->expkey; int err; - err = crypto_des3_ede_verify_key(tfm, key); - if (err) - return err; + err = des3_ede_expand_key(dctx, key, keylen); + if (err == -ENOKEY) { + if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) + err = -EINVAL; + else + err = 0; + } - return __des3_ede_setkey(expkey, flags, key, keylen); + if (err) { + memset(dctx, 0, sizeof(*dctx)); + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); + } + return err; } -static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, + const u8 *src) { - struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - const u32 *K = dctx->expkey; - const __le32 *s = (const __le32 *)src; - __le32 *d = (__le32 *)dst; - u32 L, R, A, B; - int i; - - L = le32_to_cpu(s[0]); - R = le32_to_cpu(s[1]); + const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - IP(L, R, A); - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, 2); - ROUND(R, L, A, B, K, 2); - } - for (i = 0; i < 8; i++) { - ROUND(R, L, A, B, K, 2); - ROUND(L, R, A, B, K, 2); - } - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, 2); - ROUND(R, L, A, B, K, 2); - } - FP(R, L, A); - - d[0] = cpu_to_le32(R); - d[1] = cpu_to_le32(L); + des3_ede_encrypt(dctx, dst, src); } -static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +static void crypto_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, + const u8 *src) { - struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - const u32 *K = dctx->expkey + DES3_EDE_EXPKEY_WORDS - 2; - const __le32 *s = (const __le32 *)src; - __le32 *d = (__le32 *)dst; - u32 L, R, A, B; - int i; - - L = le32_to_cpu(s[0]); - R = le32_to_cpu(s[1]); - - IP(L, R, A); - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, -2); - ROUND(R, L, A, B, K, -2); - } - for (i = 0; i < 8; i++) { - ROUND(R, L, A, B, K, -2); - ROUND(L, R, A, B, K, -2); - } - for (i = 0; i < 8; i++) { - ROUND(L, R, A, B, K, -2); - ROUND(R, L, A, B, K, -2); - } - FP(R, L, A); + const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); - d[0] = cpu_to_le32(R); - d[1] = cpu_to_le32(L); + des3_ede_decrypt(dctx, dst, src); } static struct crypto_alg des_algs[2] = { { @@ -938,13 +109,12 @@ static struct crypto_alg des_algs[2] = { { .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct des_ctx), .cra_module = THIS_MODULE, - .cra_alignmask = 3, .cra_u = { .cipher = { .cia_min_keysize = DES_KEY_SIZE, .cia_max_keysize = DES_KEY_SIZE, .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt } } + .cia_encrypt = crypto_des_encrypt, + .cia_decrypt = crypto_des_decrypt } } }, { .cra_name = "des3_ede", .cra_driver_name = "des3_ede-generic", @@ -953,13 +123,12 @@ static struct crypto_alg des_algs[2] = { { .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct des3_ede_ctx), .cra_module = THIS_MODULE, - .cra_alignmask = 3, .cra_u = { .cipher = { .cia_min_keysize = DES3_EDE_KEY_SIZE, .cia_max_keysize = DES3_EDE_KEY_SIZE, .cia_setkey = des3_ede_setkey, - .cia_encrypt = des3_ede_encrypt, - .cia_decrypt = des3_ede_decrypt } } + .cia_encrypt = crypto_des3_ede_encrypt, + .cia_decrypt = crypto_des3_ede_decrypt } } } }; static int __init des_generic_mod_init(void) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index b8c50871f11b..5cd6e3d12bac 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -150,7 +150,7 @@ config CRYPTO_DES_S390 depends on S390 select CRYPTO_ALGAPI select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES help This is the s390 hardware accelerated implementation of the DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). @@ -215,7 +215,7 @@ config CRYPTO_DEV_MARVELL_CESA tristate "Marvell's Cryptographic Engine driver" depends on PLAT_ORION || ARCH_MVEBU select CRYPTO_LIB_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER select CRYPTO_HASH select SRAM @@ -227,7 +227,7 @@ config CRYPTO_DEV_MARVELL_CESA config CRYPTO_DEV_NIAGARA2 tristate "Niagara2 Stream Processing Unit driver" - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER select CRYPTO_HASH select CRYPTO_MD5 @@ -244,7 +244,7 @@ config CRYPTO_DEV_NIAGARA2 config CRYPTO_DEV_HIFN_795X tristate "Driver HIFN 795x crypto accelerator chips" - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG depends on PCI @@ -300,7 +300,7 @@ config CRYPTO_DEV_TALITOS2 config CRYPTO_DEV_IXP4XX tristate "Driver for IXP4xx crypto hardware acceleration" depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_AEAD select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER @@ -366,7 +366,7 @@ config CRYPTO_DEV_OMAP_AES config CRYPTO_DEV_OMAP_DES tristate "Support for OMAP DES/3DES hw engine" depends on ARCH_OMAP2PLUS - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER select CRYPTO_ENGINE help @@ -384,7 +384,7 @@ config CRYPTO_DEV_PICOXCELL select CRYPTO_AES select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_CBC select CRYPTO_ECB select CRYPTO_SEQIV @@ -497,7 +497,7 @@ config CRYPTO_DEV_ATMEL_AES config CRYPTO_DEV_ATMEL_TDES tristate "Support for Atmel DES/TDES hw accelerator" depends on ARCH_AT91 || COMPILE_TEST - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER help Some Atmel processors have DES/TDES hw accelerator. @@ -595,7 +595,7 @@ config CRYPTO_DEV_QCE depends on ARCH_QCOM || COMPILE_TEST depends on HAS_IOMEM select CRYPTO_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_ECB select CRYPTO_CBC select CRYPTO_XTS @@ -643,7 +643,7 @@ config CRYPTO_DEV_SUN4I_SS select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_BLKCIPHER help Some Allwinner SoC have a crypto accelerator named @@ -666,7 +666,7 @@ config CRYPTO_DEV_ROCKCHIP tristate "Rockchip's Cryptographic Engine driver" depends on OF && ARCH_ROCKCHIP select CRYPTO_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_SHA256 @@ -703,7 +703,7 @@ config CRYPTO_DEV_BCM_SPU depends on MAILBOX default m select CRYPTO_AUTHENC - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_SHA256 @@ -722,7 +722,7 @@ config CRYPTO_DEV_SAFEXCEL select CRYPTO_LIB_AES select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_HASH select CRYPTO_HMAC select CRYPTO_MD5 @@ -760,7 +760,7 @@ config CRYPTO_DEV_CCREE default n select CRYPTO_HASH select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES select CRYPTO_AEAD select CRYPTO_AUTHENC select CRYPTO_SHA1 diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index e4fdf545ac90..137ed3df0c74 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -98,7 +98,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API select CRYPTO_AEAD select CRYPTO_AUTHENC select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES help Selecting this will offload crypto for users of the scatterlist crypto API (such as the linux native IPSec diff --git a/drivers/crypto/cavium/nitrox/Kconfig b/drivers/crypto/cavium/nitrox/Kconfig index dab162af41b8..7b1e751bb9cd 100644 --- a/drivers/crypto/cavium/nitrox/Kconfig +++ b/drivers/crypto/cavium/nitrox/Kconfig @@ -6,7 +6,7 @@ config CRYPTO_DEV_NITROX tristate select CRYPTO_BLKCIPHER select CRYPTO_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select FW_LOADER config CRYPTO_DEV_NITROX_CNN55XX diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 16c4d5460334..b68b6a7c0a32 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig index d6576280fc9b..1aba9372cd23 100644 --- a/drivers/crypto/stm32/Kconfig +++ b/drivers/crypto/stm32/Kconfig @@ -25,7 +25,7 @@ config CRYPTO_DEV_STM32_CRYP depends on ARCH_STM32 select CRYPTO_HASH select CRYPTO_ENGINE - select CRYPTO_DES + select CRYPTO_LIB_DES help This enables support for the CRYP (AES/DES/TDES) hw accelerator which can be found on STMicroelectronics STM32 SOC. diff --git a/drivers/crypto/ux500/Kconfig b/drivers/crypto/ux500/Kconfig index 349d34eaac13..b1c6f739f77b 100644 --- a/drivers/crypto/ux500/Kconfig +++ b/drivers/crypto/ux500/Kconfig @@ -9,7 +9,7 @@ config CRYPTO_DEV_UX500_CRYP depends on CRYPTO_DEV_UX500 select CRYPTO_ALGAPI select CRYPTO_BLKCIPHER - select CRYPTO_DES + select CRYPTO_LIB_DES help This selects the crypto driver for the UX500_CRYP hardware. It supports AES-ECB, CBC and CTR with keys sizes of 128, 192 and 256 bit sizes. diff --git a/include/crypto/des.h b/include/crypto/des.h index 31b04ba835b1..2c864a4e6707 100644 --- a/include/crypto/des.h +++ b/include/crypto/des.h @@ -6,10 +6,7 @@ #ifndef __CRYPTO_DES_H #define __CRYPTO_DES_H -#include -#include -#include -#include +#include #define DES_KEY_SIZE 8 #define DES_EXPKEY_WORDS 32 @@ -19,6 +16,44 @@ #define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS) #define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE +struct des_ctx { + u32 expkey[DES_EXPKEY_WORDS]; +}; + +struct des3_ede_ctx { + u32 expkey[DES3_EDE_EXPKEY_WORDS]; +}; + +void des_encrypt(const struct des_ctx *ctx, u8 *dst, const u8 *src); +void des_decrypt(const struct des_ctx *ctx, u8 *dst, const u8 *src); + +void des3_ede_encrypt(const struct des3_ede_ctx *dctx, u8 *dst, const u8 *src); +void des3_ede_decrypt(const struct des3_ede_ctx *dctx, u8 *dst, const u8 *src); + +/** + * des_expand_key - Expand a DES input key into a key schedule + * @ctx: the key schedule + * @key: buffer containing the input key + * @len: size of the buffer contents + * + * Returns 0 on success, -EINVAL if the input key is rejected and -ENOKEY if + * the key is accepted but has been found to be weak. + */ +int des_expand_key(struct des_ctx *ctx, const u8 *key, unsigned int keylen); + +/** + * des3_ede_expand_key - Expand a triple DES input key into a key schedule + * @ctx: the key schedule + * @key: buffer containing the input key + * @len: size of the buffer contents + * + * Returns 0 on success, -EINVAL if the input key is rejected and -ENOKEY if + * the key is accepted but has been found to be weak. Note that weak keys will + * be rejected (and -EINVAL will be returned) when running in FIPS mode. + */ +int des3_ede_expand_key(struct des3_ede_ctx *ctx, const u8 *key, + unsigned int keylen); + extern int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, unsigned int keylen); diff --git a/include/crypto/internal/des.h b/include/crypto/internal/des.h index f5d2e696522e..81ea1a425e9c 100644 --- a/include/crypto/internal/des.h +++ b/include/crypto/internal/des.h @@ -25,18 +25,21 @@ */ static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key) { - u32 tmp[DES_EXPKEY_WORDS]; - int err = 0; - - if (!(crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) - return 0; + struct des_ctx tmp; + int err; + + err = des_expand_key(&tmp, key, DES_KEY_SIZE); + if (err == -ENOKEY) { + if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) + err = -EINVAL; + else + err = 0; + } - if (!des_ekey(tmp, key)) { + if (err) crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - err = -EINVAL; - } - memzero_explicit(tmp, sizeof(tmp)); + memzero_explicit(&tmp, sizeof(tmp)); return err; } @@ -53,6 +56,28 @@ static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key) * property. * */ +static inline int des3_ede_verify_key(const u8 *key, unsigned int key_len, + bool check_weak) +{ + int ret = fips_enabled ? -EINVAL : -ENOKEY; + u32 K[6]; + + memcpy(K, key, DES3_EDE_KEY_SIZE); + + if ((!((K[0] ^ K[2]) | (K[1] ^ K[3])) || + !((K[2] ^ K[4]) | (K[3] ^ K[5]))) && + (fips_enabled || check_weak)) + goto bad; + + if ((!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled) + goto bad; + + ret = 0; +bad: + memzero_explicit(K, DES3_EDE_KEY_SIZE); + + return ret; +} /** * crypto_des3_ede_verify_key - Check whether a DES3-EDE key is weak @@ -70,28 +95,14 @@ static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key) static inline int crypto_des3_ede_verify_key(struct crypto_tfm *tfm, const u8 *key) { - int err = -EINVAL; - u32 K[6]; - - memcpy(K, key, DES3_EDE_KEY_SIZE); - - if ((!((K[0] ^ K[2]) | (K[1] ^ K[3])) || - !((K[2] ^ K[4]) | (K[3] ^ K[5]))) && - (fips_enabled || (crypto_tfm_get_flags(tfm) & - CRYPTO_TFM_REQ_FORBID_WEAK_KEYS))) - goto bad; - - if ((!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled) - goto bad; + int err; - err = 0; -out: - memzero_explicit(K, DES3_EDE_KEY_SIZE); + err = des3_ede_verify_key(key, DES3_EDE_KEY_SIZE, + crypto_tfm_get_flags(tfm) & + CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); + if (err) + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); return err; - -bad: - crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); - goto out; } static inline int verify_skcipher_des_key(struct crypto_skcipher *tfm, diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 42a91c62d96d..101a321b8a99 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -5,3 +5,6 @@ libaes-y := aes.o obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o libarc4-y := arc4.o + +obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o +libdes-y := des.o diff --git a/lib/crypto/des.c b/lib/crypto/des.c new file mode 100644 index 000000000000..ef5bb8822aba --- /dev/null +++ b/lib/crypto/des.c @@ -0,0 +1,902 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Cryptographic API. + * + * DES & Triple DES EDE Cipher Algorithms. + * + * Copyright (c) 2005 Dag Arne Osvik + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define ROL(x, r) ((x) = rol32((x), (r))) +#define ROR(x, r) ((x) = ror32((x), (r))) + +/* Lookup tables for key expansion */ + +static const u8 pc1[256] = { + 0x00, 0x00, 0x40, 0x04, 0x10, 0x10, 0x50, 0x14, + 0x04, 0x40, 0x44, 0x44, 0x14, 0x50, 0x54, 0x54, + 0x02, 0x02, 0x42, 0x06, 0x12, 0x12, 0x52, 0x16, + 0x06, 0x42, 0x46, 0x46, 0x16, 0x52, 0x56, 0x56, + 0x80, 0x08, 0xc0, 0x0c, 0x90, 0x18, 0xd0, 0x1c, + 0x84, 0x48, 0xc4, 0x4c, 0x94, 0x58, 0xd4, 0x5c, + 0x82, 0x0a, 0xc2, 0x0e, 0x92, 0x1a, 0xd2, 0x1e, + 0x86, 0x4a, 0xc6, 0x4e, 0x96, 0x5a, 0xd6, 0x5e, + 0x20, 0x20, 0x60, 0x24, 0x30, 0x30, 0x70, 0x34, + 0x24, 0x60, 0x64, 0x64, 0x34, 0x70, 0x74, 0x74, + 0x22, 0x22, 0x62, 0x26, 0x32, 0x32, 0x72, 0x36, + 0x26, 0x62, 0x66, 0x66, 0x36, 0x72, 0x76, 0x76, + 0xa0, 0x28, 0xe0, 0x2c, 0xb0, 0x38, 0xf0, 0x3c, + 0xa4, 0x68, 0xe4, 0x6c, 0xb4, 0x78, 0xf4, 0x7c, + 0xa2, 0x2a, 0xe2, 0x2e, 0xb2, 0x3a, 0xf2, 0x3e, + 0xa6, 0x6a, 0xe6, 0x6e, 0xb6, 0x7a, 0xf6, 0x7e, + 0x08, 0x80, 0x48, 0x84, 0x18, 0x90, 0x58, 0x94, + 0x0c, 0xc0, 0x4c, 0xc4, 0x1c, 0xd0, 0x5c, 0xd4, + 0x0a, 0x82, 0x4a, 0x86, 0x1a, 0x92, 0x5a, 0x96, + 0x0e, 0xc2, 0x4e, 0xc6, 0x1e, 0xd2, 0x5e, 0xd6, + 0x88, 0x88, 0xc8, 0x8c, 0x98, 0x98, 0xd8, 0x9c, + 0x8c, 0xc8, 0xcc, 0xcc, 0x9c, 0xd8, 0xdc, 0xdc, + 0x8a, 0x8a, 0xca, 0x8e, 0x9a, 0x9a, 0xda, 0x9e, + 0x8e, 0xca, 0xce, 0xce, 0x9e, 0xda, 0xde, 0xde, + 0x28, 0xa0, 0x68, 0xa4, 0x38, 0xb0, 0x78, 0xb4, + 0x2c, 0xe0, 0x6c, 0xe4, 0x3c, 0xf0, 0x7c, 0xf4, + 0x2a, 0xa2, 0x6a, 0xa6, 0x3a, 0xb2, 0x7a, 0xb6, + 0x2e, 0xe2, 0x6e, 0xe6, 0x3e, 0xf2, 0x7e, 0xf6, + 0xa8, 0xa8, 0xe8, 0xac, 0xb8, 0xb8, 0xf8, 0xbc, + 0xac, 0xe8, 0xec, 0xec, 0xbc, 0xf8, 0xfc, 0xfc, + 0xaa, 0xaa, 0xea, 0xae, 0xba, 0xba, 0xfa, 0xbe, + 0xae, 0xea, 0xee, 0xee, 0xbe, 0xfa, 0xfe, 0xfe +}; + +static const u8 rs[256] = { + 0x00, 0x00, 0x80, 0x80, 0x02, 0x02, 0x82, 0x82, + 0x04, 0x04, 0x84, 0x84, 0x06, 0x06, 0x86, 0x86, + 0x08, 0x08, 0x88, 0x88, 0x0a, 0x0a, 0x8a, 0x8a, + 0x0c, 0x0c, 0x8c, 0x8c, 0x0e, 0x0e, 0x8e, 0x8e, + 0x10, 0x10, 0x90, 0x90, 0x12, 0x12, 0x92, 0x92, + 0x14, 0x14, 0x94, 0x94, 0x16, 0x16, 0x96, 0x96, + 0x18, 0x18, 0x98, 0x98, 0x1a, 0x1a, 0x9a, 0x9a, + 0x1c, 0x1c, 0x9c, 0x9c, 0x1e, 0x1e, 0x9e, 0x9e, + 0x20, 0x20, 0xa0, 0xa0, 0x22, 0x22, 0xa2, 0xa2, + 0x24, 0x24, 0xa4, 0xa4, 0x26, 0x26, 0xa6, 0xa6, + 0x28, 0x28, 0xa8, 0xa8, 0x2a, 0x2a, 0xaa, 0xaa, + 0x2c, 0x2c, 0xac, 0xac, 0x2e, 0x2e, 0xae, 0xae, + 0x30, 0x30, 0xb0, 0xb0, 0x32, 0x32, 0xb2, 0xb2, + 0x34, 0x34, 0xb4, 0xb4, 0x36, 0x36, 0xb6, 0xb6, + 0x38, 0x38, 0xb8, 0xb8, 0x3a, 0x3a, 0xba, 0xba, + 0x3c, 0x3c, 0xbc, 0xbc, 0x3e, 0x3e, 0xbe, 0xbe, + 0x40, 0x40, 0xc0, 0xc0, 0x42, 0x42, 0xc2, 0xc2, + 0x44, 0x44, 0xc4, 0xc4, 0x46, 0x46, 0xc6, 0xc6, + 0x48, 0x48, 0xc8, 0xc8, 0x4a, 0x4a, 0xca, 0xca, + 0x4c, 0x4c, 0xcc, 0xcc, 0x4e, 0x4e, 0xce, 0xce, + 0x50, 0x50, 0xd0, 0xd0, 0x52, 0x52, 0xd2, 0xd2, + 0x54, 0x54, 0xd4, 0xd4, 0x56, 0x56, 0xd6, 0xd6, + 0x58, 0x58, 0xd8, 0xd8, 0x5a, 0x5a, 0xda, 0xda, + 0x5c, 0x5c, 0xdc, 0xdc, 0x5e, 0x5e, 0xde, 0xde, + 0x60, 0x60, 0xe0, 0xe0, 0x62, 0x62, 0xe2, 0xe2, + 0x64, 0x64, 0xe4, 0xe4, 0x66, 0x66, 0xe6, 0xe6, + 0x68, 0x68, 0xe8, 0xe8, 0x6a, 0x6a, 0xea, 0xea, + 0x6c, 0x6c, 0xec, 0xec, 0x6e, 0x6e, 0xee, 0xee, + 0x70, 0x70, 0xf0, 0xf0, 0x72, 0x72, 0xf2, 0xf2, + 0x74, 0x74, 0xf4, 0xf4, 0x76, 0x76, 0xf6, 0xf6, + 0x78, 0x78, 0xf8, 0xf8, 0x7a, 0x7a, 0xfa, 0xfa, + 0x7c, 0x7c, 0xfc, 0xfc, 0x7e, 0x7e, 0xfe, 0xfe +}; + +static const u32 pc2[1024] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00040000, 0x00000000, 0x04000000, 0x00100000, + 0x00400000, 0x00000008, 0x00000800, 0x40000000, + 0x00440000, 0x00000008, 0x04000800, 0x40100000, + 0x00000400, 0x00000020, 0x08000000, 0x00000100, + 0x00040400, 0x00000020, 0x0c000000, 0x00100100, + 0x00400400, 0x00000028, 0x08000800, 0x40000100, + 0x00440400, 0x00000028, 0x0c000800, 0x40100100, + 0x80000000, 0x00000010, 0x00000000, 0x00800000, + 0x80040000, 0x00000010, 0x04000000, 0x00900000, + 0x80400000, 0x00000018, 0x00000800, 0x40800000, + 0x80440000, 0x00000018, 0x04000800, 0x40900000, + 0x80000400, 0x00000030, 0x08000000, 0x00800100, + 0x80040400, 0x00000030, 0x0c000000, 0x00900100, + 0x80400400, 0x00000038, 0x08000800, 0x40800100, + 0x80440400, 0x00000038, 0x0c000800, 0x40900100, + 0x10000000, 0x00000000, 0x00200000, 0x00001000, + 0x10040000, 0x00000000, 0x04200000, 0x00101000, + 0x10400000, 0x00000008, 0x00200800, 0x40001000, + 0x10440000, 0x00000008, 0x04200800, 0x40101000, + 0x10000400, 0x00000020, 0x08200000, 0x00001100, + 0x10040400, 0x00000020, 0x0c200000, 0x00101100, + 0x10400400, 0x00000028, 0x08200800, 0x40001100, + 0x10440400, 0x00000028, 0x0c200800, 0x40101100, + 0x90000000, 0x00000010, 0x00200000, 0x00801000, + 0x90040000, 0x00000010, 0x04200000, 0x00901000, + 0x90400000, 0x00000018, 0x00200800, 0x40801000, + 0x90440000, 0x00000018, 0x04200800, 0x40901000, + 0x90000400, 0x00000030, 0x08200000, 0x00801100, + 0x90040400, 0x00000030, 0x0c200000, 0x00901100, + 0x90400400, 0x00000038, 0x08200800, 0x40801100, + 0x90440400, 0x00000038, 0x0c200800, 0x40901100, + 0x00000200, 0x00080000, 0x00000000, 0x00000004, + 0x00040200, 0x00080000, 0x04000000, 0x00100004, + 0x00400200, 0x00080008, 0x00000800, 0x40000004, + 0x00440200, 0x00080008, 0x04000800, 0x40100004, + 0x00000600, 0x00080020, 0x08000000, 0x00000104, + 0x00040600, 0x00080020, 0x0c000000, 0x00100104, + 0x00400600, 0x00080028, 0x08000800, 0x40000104, + 0x00440600, 0x00080028, 0x0c000800, 0x40100104, + 0x80000200, 0x00080010, 0x00000000, 0x00800004, + 0x80040200, 0x00080010, 0x04000000, 0x00900004, + 0x80400200, 0x00080018, 0x00000800, 0x40800004, + 0x80440200, 0x00080018, 0x04000800, 0x40900004, + 0x80000600, 0x00080030, 0x08000000, 0x00800104, + 0x80040600, 0x00080030, 0x0c000000, 0x00900104, + 0x80400600, 0x00080038, 0x08000800, 0x40800104, + 0x80440600, 0x00080038, 0x0c000800, 0x40900104, + 0x10000200, 0x00080000, 0x00200000, 0x00001004, + 0x10040200, 0x00080000, 0x04200000, 0x00101004, + 0x10400200, 0x00080008, 0x00200800, 0x40001004, + 0x10440200, 0x00080008, 0x04200800, 0x40101004, + 0x10000600, 0x00080020, 0x08200000, 0x00001104, + 0x10040600, 0x00080020, 0x0c200000, 0x00101104, + 0x10400600, 0x00080028, 0x08200800, 0x40001104, + 0x10440600, 0x00080028, 0x0c200800, 0x40101104, + 0x90000200, 0x00080010, 0x00200000, 0x00801004, + 0x90040200, 0x00080010, 0x04200000, 0x00901004, + 0x90400200, 0x00080018, 0x00200800, 0x40801004, + 0x90440200, 0x00080018, 0x04200800, 0x40901004, + 0x90000600, 0x00080030, 0x08200000, 0x00801104, + 0x90040600, 0x00080030, 0x0c200000, 0x00901104, + 0x90400600, 0x00080038, 0x08200800, 0x40801104, + 0x90440600, 0x00080038, 0x0c200800, 0x40901104, + 0x00000002, 0x00002000, 0x20000000, 0x00000001, + 0x00040002, 0x00002000, 0x24000000, 0x00100001, + 0x00400002, 0x00002008, 0x20000800, 0x40000001, + 0x00440002, 0x00002008, 0x24000800, 0x40100001, + 0x00000402, 0x00002020, 0x28000000, 0x00000101, + 0x00040402, 0x00002020, 0x2c000000, 0x00100101, + 0x00400402, 0x00002028, 0x28000800, 0x40000101, + 0x00440402, 0x00002028, 0x2c000800, 0x40100101, + 0x80000002, 0x00002010, 0x20000000, 0x00800001, + 0x80040002, 0x00002010, 0x24000000, 0x00900001, + 0x80400002, 0x00002018, 0x20000800, 0x40800001, + 0x80440002, 0x00002018, 0x24000800, 0x40900001, + 0x80000402, 0x00002030, 0x28000000, 0x00800101, + 0x80040402, 0x00002030, 0x2c000000, 0x00900101, + 0x80400402, 0x00002038, 0x28000800, 0x40800101, + 0x80440402, 0x00002038, 0x2c000800, 0x40900101, + 0x10000002, 0x00002000, 0x20200000, 0x00001001, + 0x10040002, 0x00002000, 0x24200000, 0x00101001, + 0x10400002, 0x00002008, 0x20200800, 0x40001001, + 0x10440002, 0x00002008, 0x24200800, 0x40101001, + 0x10000402, 0x00002020, 0x28200000, 0x00001101, + 0x10040402, 0x00002020, 0x2c200000, 0x00101101, + 0x10400402, 0x00002028, 0x28200800, 0x40001101, + 0x10440402, 0x00002028, 0x2c200800, 0x40101101, + 0x90000002, 0x00002010, 0x20200000, 0x00801001, + 0x90040002, 0x00002010, 0x24200000, 0x00901001, + 0x90400002, 0x00002018, 0x20200800, 0x40801001, + 0x90440002, 0x00002018, 0x24200800, 0x40901001, + 0x90000402, 0x00002030, 0x28200000, 0x00801101, + 0x90040402, 0x00002030, 0x2c200000, 0x00901101, + 0x90400402, 0x00002038, 0x28200800, 0x40801101, + 0x90440402, 0x00002038, 0x2c200800, 0x40901101, + 0x00000202, 0x00082000, 0x20000000, 0x00000005, + 0x00040202, 0x00082000, 0x24000000, 0x00100005, + 0x00400202, 0x00082008, 0x20000800, 0x40000005, + 0x00440202, 0x00082008, 0x24000800, 0x40100005, + 0x00000602, 0x00082020, 0x28000000, 0x00000105, + 0x00040602, 0x00082020, 0x2c000000, 0x00100105, + 0x00400602, 0x00082028, 0x28000800, 0x40000105, + 0x00440602, 0x00082028, 0x2c000800, 0x40100105, + 0x80000202, 0x00082010, 0x20000000, 0x00800005, + 0x80040202, 0x00082010, 0x24000000, 0x00900005, + 0x80400202, 0x00082018, 0x20000800, 0x40800005, + 0x80440202, 0x00082018, 0x24000800, 0x40900005, + 0x80000602, 0x00082030, 0x28000000, 0x00800105, + 0x80040602, 0x00082030, 0x2c000000, 0x00900105, + 0x80400602, 0x00082038, 0x28000800, 0x40800105, + 0x80440602, 0x00082038, 0x2c000800, 0x40900105, + 0x10000202, 0x00082000, 0x20200000, 0x00001005, + 0x10040202, 0x00082000, 0x24200000, 0x00101005, + 0x10400202, 0x00082008, 0x20200800, 0x40001005, + 0x10440202, 0x00082008, 0x24200800, 0x40101005, + 0x10000602, 0x00082020, 0x28200000, 0x00001105, + 0x10040602, 0x00082020, 0x2c200000, 0x00101105, + 0x10400602, 0x00082028, 0x28200800, 0x40001105, + 0x10440602, 0x00082028, 0x2c200800, 0x40101105, + 0x90000202, 0x00082010, 0x20200000, 0x00801005, + 0x90040202, 0x00082010, 0x24200000, 0x00901005, + 0x90400202, 0x00082018, 0x20200800, 0x40801005, + 0x90440202, 0x00082018, 0x24200800, 0x40901005, + 0x90000602, 0x00082030, 0x28200000, 0x00801105, + 0x90040602, 0x00082030, 0x2c200000, 0x00901105, + 0x90400602, 0x00082038, 0x28200800, 0x40801105, + 0x90440602, 0x00082038, 0x2c200800, 0x40901105, + + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000008, 0x00080000, 0x10000000, + 0x02000000, 0x00000000, 0x00000080, 0x00001000, + 0x02000000, 0x00000008, 0x00080080, 0x10001000, + 0x00004000, 0x00000000, 0x00000040, 0x00040000, + 0x00004000, 0x00000008, 0x00080040, 0x10040000, + 0x02004000, 0x00000000, 0x000000c0, 0x00041000, + 0x02004000, 0x00000008, 0x000800c0, 0x10041000, + 0x00020000, 0x00008000, 0x08000000, 0x00200000, + 0x00020000, 0x00008008, 0x08080000, 0x10200000, + 0x02020000, 0x00008000, 0x08000080, 0x00201000, + 0x02020000, 0x00008008, 0x08080080, 0x10201000, + 0x00024000, 0x00008000, 0x08000040, 0x00240000, + 0x00024000, 0x00008008, 0x08080040, 0x10240000, + 0x02024000, 0x00008000, 0x080000c0, 0x00241000, + 0x02024000, 0x00008008, 0x080800c0, 0x10241000, + 0x00000000, 0x01000000, 0x00002000, 0x00000020, + 0x00000000, 0x01000008, 0x00082000, 0x10000020, + 0x02000000, 0x01000000, 0x00002080, 0x00001020, + 0x02000000, 0x01000008, 0x00082080, 0x10001020, + 0x00004000, 0x01000000, 0x00002040, 0x00040020, + 0x00004000, 0x01000008, 0x00082040, 0x10040020, + 0x02004000, 0x01000000, 0x000020c0, 0x00041020, + 0x02004000, 0x01000008, 0x000820c0, 0x10041020, + 0x00020000, 0x01008000, 0x08002000, 0x00200020, + 0x00020000, 0x01008008, 0x08082000, 0x10200020, + 0x02020000, 0x01008000, 0x08002080, 0x00201020, + 0x02020000, 0x01008008, 0x08082080, 0x10201020, + 0x00024000, 0x01008000, 0x08002040, 0x00240020, + 0x00024000, 0x01008008, 0x08082040, 0x10240020, + 0x02024000, 0x01008000, 0x080020c0, 0x00241020, + 0x02024000, 0x01008008, 0x080820c0, 0x10241020, + 0x00000400, 0x04000000, 0x00100000, 0x00000004, + 0x00000400, 0x04000008, 0x00180000, 0x10000004, + 0x02000400, 0x04000000, 0x00100080, 0x00001004, + 0x02000400, 0x04000008, 0x00180080, 0x10001004, + 0x00004400, 0x04000000, 0x00100040, 0x00040004, + 0x00004400, 0x04000008, 0x00180040, 0x10040004, + 0x02004400, 0x04000000, 0x001000c0, 0x00041004, + 0x02004400, 0x04000008, 0x001800c0, 0x10041004, + 0x00020400, 0x04008000, 0x08100000, 0x00200004, + 0x00020400, 0x04008008, 0x08180000, 0x10200004, + 0x02020400, 0x04008000, 0x08100080, 0x00201004, + 0x02020400, 0x04008008, 0x08180080, 0x10201004, + 0x00024400, 0x04008000, 0x08100040, 0x00240004, + 0x00024400, 0x04008008, 0x08180040, 0x10240004, + 0x02024400, 0x04008000, 0x081000c0, 0x00241004, + 0x02024400, 0x04008008, 0x081800c0, 0x10241004, + 0x00000400, 0x05000000, 0x00102000, 0x00000024, + 0x00000400, 0x05000008, 0x00182000, 0x10000024, + 0x02000400, 0x05000000, 0x00102080, 0x00001024, + 0x02000400, 0x05000008, 0x00182080, 0x10001024, + 0x00004400, 0x05000000, 0x00102040, 0x00040024, + 0x00004400, 0x05000008, 0x00182040, 0x10040024, + 0x02004400, 0x05000000, 0x001020c0, 0x00041024, + 0x02004400, 0x05000008, 0x001820c0, 0x10041024, + 0x00020400, 0x05008000, 0x08102000, 0x00200024, + 0x00020400, 0x05008008, 0x08182000, 0x10200024, + 0x02020400, 0x05008000, 0x08102080, 0x00201024, + 0x02020400, 0x05008008, 0x08182080, 0x10201024, + 0x00024400, 0x05008000, 0x08102040, 0x00240024, + 0x00024400, 0x05008008, 0x08182040, 0x10240024, + 0x02024400, 0x05008000, 0x081020c0, 0x00241024, + 0x02024400, 0x05008008, 0x081820c0, 0x10241024, + 0x00000800, 0x00010000, 0x20000000, 0x00000010, + 0x00000800, 0x00010008, 0x20080000, 0x10000010, + 0x02000800, 0x00010000, 0x20000080, 0x00001010, + 0x02000800, 0x00010008, 0x20080080, 0x10001010, + 0x00004800, 0x00010000, 0x20000040, 0x00040010, + 0x00004800, 0x00010008, 0x20080040, 0x10040010, + 0x02004800, 0x00010000, 0x200000c0, 0x00041010, + 0x02004800, 0x00010008, 0x200800c0, 0x10041010, + 0x00020800, 0x00018000, 0x28000000, 0x00200010, + 0x00020800, 0x00018008, 0x28080000, 0x10200010, + 0x02020800, 0x00018000, 0x28000080, 0x00201010, + 0x02020800, 0x00018008, 0x28080080, 0x10201010, + 0x00024800, 0x00018000, 0x28000040, 0x00240010, + 0x00024800, 0x00018008, 0x28080040, 0x10240010, + 0x02024800, 0x00018000, 0x280000c0, 0x00241010, + 0x02024800, 0x00018008, 0x280800c0, 0x10241010, + 0x00000800, 0x01010000, 0x20002000, 0x00000030, + 0x00000800, 0x01010008, 0x20082000, 0x10000030, + 0x02000800, 0x01010000, 0x20002080, 0x00001030, + 0x02000800, 0x01010008, 0x20082080, 0x10001030, + 0x00004800, 0x01010000, 0x20002040, 0x00040030, + 0x00004800, 0x01010008, 0x20082040, 0x10040030, + 0x02004800, 0x01010000, 0x200020c0, 0x00041030, + 0x02004800, 0x01010008, 0x200820c0, 0x10041030, + 0x00020800, 0x01018000, 0x28002000, 0x00200030, + 0x00020800, 0x01018008, 0x28082000, 0x10200030, + 0x02020800, 0x01018000, 0x28002080, 0x00201030, + 0x02020800, 0x01018008, 0x28082080, 0x10201030, + 0x00024800, 0x01018000, 0x28002040, 0x00240030, + 0x00024800, 0x01018008, 0x28082040, 0x10240030, + 0x02024800, 0x01018000, 0x280020c0, 0x00241030, + 0x02024800, 0x01018008, 0x280820c0, 0x10241030, + 0x00000c00, 0x04010000, 0x20100000, 0x00000014, + 0x00000c00, 0x04010008, 0x20180000, 0x10000014, + 0x02000c00, 0x04010000, 0x20100080, 0x00001014, + 0x02000c00, 0x04010008, 0x20180080, 0x10001014, + 0x00004c00, 0x04010000, 0x20100040, 0x00040014, + 0x00004c00, 0x04010008, 0x20180040, 0x10040014, + 0x02004c00, 0x04010000, 0x201000c0, 0x00041014, + 0x02004c00, 0x04010008, 0x201800c0, 0x10041014, + 0x00020c00, 0x04018000, 0x28100000, 0x00200014, + 0x00020c00, 0x04018008, 0x28180000, 0x10200014, + 0x02020c00, 0x04018000, 0x28100080, 0x00201014, + 0x02020c00, 0x04018008, 0x28180080, 0x10201014, + 0x00024c00, 0x04018000, 0x28100040, 0x00240014, + 0x00024c00, 0x04018008, 0x28180040, 0x10240014, + 0x02024c00, 0x04018000, 0x281000c0, 0x00241014, + 0x02024c00, 0x04018008, 0x281800c0, 0x10241014, + 0x00000c00, 0x05010000, 0x20102000, 0x00000034, + 0x00000c00, 0x05010008, 0x20182000, 0x10000034, + 0x02000c00, 0x05010000, 0x20102080, 0x00001034, + 0x02000c00, 0x05010008, 0x20182080, 0x10001034, + 0x00004c00, 0x05010000, 0x20102040, 0x00040034, + 0x00004c00, 0x05010008, 0x20182040, 0x10040034, + 0x02004c00, 0x05010000, 0x201020c0, 0x00041034, + 0x02004c00, 0x05010008, 0x201820c0, 0x10041034, + 0x00020c00, 0x05018000, 0x28102000, 0x00200034, + 0x00020c00, 0x05018008, 0x28182000, 0x10200034, + 0x02020c00, 0x05018000, 0x28102080, 0x00201034, + 0x02020c00, 0x05018008, 0x28182080, 0x10201034, + 0x00024c00, 0x05018000, 0x28102040, 0x00240034, + 0x00024c00, 0x05018008, 0x28182040, 0x10240034, + 0x02024c00, 0x05018000, 0x281020c0, 0x00241034, + 0x02024c00, 0x05018008, 0x281820c0, 0x10241034 +}; + +/* S-box lookup tables */ + +static const u32 S1[64] = { + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const u32 S2[64] = { + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const u32 S3[64] = { + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const u32 S4[64] = { + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const u32 S5[64] = { + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const u32 S6[64] = { + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const u32 S7[64] = { + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const u32 S8[64] = { + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* Encryption components: IP, FP, and round function */ + +#define IP(L, R, T) \ + ROL(R, 4); \ + T = L; \ + L ^= R; \ + L &= 0xf0f0f0f0; \ + R ^= L; \ + L ^= T; \ + ROL(R, 12); \ + T = L; \ + L ^= R; \ + L &= 0xffff0000; \ + R ^= L; \ + L ^= T; \ + ROR(R, 14); \ + T = L; \ + L ^= R; \ + L &= 0xcccccccc; \ + R ^= L; \ + L ^= T; \ + ROL(R, 6); \ + T = L; \ + L ^= R; \ + L &= 0xff00ff00; \ + R ^= L; \ + L ^= T; \ + ROR(R, 7); \ + T = L; \ + L ^= R; \ + L &= 0xaaaaaaaa; \ + R ^= L; \ + L ^= T; \ + ROL(L, 1); + +#define FP(L, R, T) \ + ROR(L, 1); \ + T = L; \ + L ^= R; \ + L &= 0xaaaaaaaa; \ + R ^= L; \ + L ^= T; \ + ROL(R, 7); \ + T = L; \ + L ^= R; \ + L &= 0xff00ff00; \ + R ^= L; \ + L ^= T; \ + ROR(R, 6); \ + T = L; \ + L ^= R; \ + L &= 0xcccccccc; \ + R ^= L; \ + L ^= T; \ + ROL(R, 14); \ + T = L; \ + L ^= R; \ + L &= 0xffff0000; \ + R ^= L; \ + L ^= T; \ + ROR(R, 12); \ + T = L; \ + L ^= R; \ + L &= 0xf0f0f0f0; \ + R ^= L; \ + L ^= T; \ + ROR(R, 4); + +#define ROUND(L, R, A, B, K, d) \ + B = K[0]; A = K[1]; K += d; \ + B ^= R; A ^= R; \ + B &= 0x3f3f3f3f; ROR(A, 4); \ + L ^= S8[0xff & B]; A &= 0x3f3f3f3f; \ + L ^= S6[0xff & (B >> 8)]; B >>= 16; \ + L ^= S7[0xff & A]; \ + L ^= S5[0xff & (A >> 8)]; A >>= 16; \ + L ^= S4[0xff & B]; \ + L ^= S2[0xff & (B >> 8)]; \ + L ^= S3[0xff & A]; \ + L ^= S1[0xff & (A >> 8)]; + +/* + * PC2 lookup tables are organized as 2 consecutive sets of 4 interleaved + * tables of 128 elements. One set is for C_i and the other for D_i, while + * the 4 interleaved tables correspond to four 7-bit subsets of C_i or D_i. + * + * After PC1 each of the variables a,b,c,d contains a 7 bit subset of C_i + * or D_i in bits 7-1 (bit 0 being the least significant). + */ + +#define T1(x) pt[2 * (x) + 0] +#define T2(x) pt[2 * (x) + 1] +#define T3(x) pt[2 * (x) + 2] +#define T4(x) pt[2 * (x) + 3] + +#define DES_PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a)) + +/* + * Encryption key expansion + * + * RFC2451: Weak key checks SHOULD be performed. + * + * FIPS 74: + * + * Keys having duals are keys which produce all zeros, all ones, or + * alternating zero-one patterns in the C and D registers after Permuted + * Choice 1 has operated on the key. + * + */ +static unsigned long des_ekey(u32 *pe, const u8 *k) +{ + /* K&R: long is at least 32 bits */ + unsigned long a, b, c, d, w; + const u32 *pt = pc2; + + d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d]; + c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c]; + b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b]; + a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a]; + + pe[15 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; + pe[14 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[13 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[12 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[11 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[10 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 9 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 8 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; + pe[ 7 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 6 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 5 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 4 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 3 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 2 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 1 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; + pe[ 0 * 2 + 0] = DES_PC2(b, c, d, a); + + /* Check if first half is weak */ + w = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]); + + /* Skip to next table set */ + pt += 512; + + d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1]; + c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1]; + b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1]; + a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1]; + + /* Check if second half is weak */ + w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]); + + pe[15 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; + pe[14 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[13 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[12 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[11 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[10 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 9 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 8 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; + pe[ 7 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 6 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 5 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 4 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 3 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 2 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[ 1 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; + pe[ 0 * 2 + 1] = DES_PC2(b, c, d, a); + + /* Fixup: 2413 5768 -> 1357 2468 */ + for (d = 0; d < 16; ++d) { + a = pe[2 * d]; + b = pe[2 * d + 1]; + c = a ^ b; + c &= 0xffff0000; + a ^= c; + b ^= c; + ROL(b, 18); + pe[2 * d] = a; + pe[2 * d + 1] = b; + } + + /* Zero if weak key */ + return w; +} + +int des_expand_key(struct des_ctx *ctx, const u8 *key, unsigned int keylen) +{ + if (keylen != DES_KEY_SIZE) + return -EINVAL; + + return des_ekey(ctx->expkey, key) ? 0 : -ENOKEY; +} +EXPORT_SYMBOL_GPL(des_expand_key); + +/* + * Decryption key expansion + * + * No weak key checking is performed, as this is only used by triple DES + * + */ +static void dkey(u32 *pe, const u8 *k) +{ + /* K&R: long is at least 32 bits */ + unsigned long a, b, c, d; + const u32 *pt = pc2; + + d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d]; + c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c]; + b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b]; + a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a]; + + pe[ 0 * 2] = DES_PC2(a, b, c, d); d = rs[d]; + pe[ 1 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 2 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 3 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 4 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 5 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 6 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 7 * 2] = DES_PC2(d, a, b, c); c = rs[c]; + pe[ 8 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 9 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[10 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[11 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[12 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[13 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[14 * 2] = DES_PC2(c, d, a, b); b = rs[b]; + pe[15 * 2] = DES_PC2(b, c, d, a); + + /* Skip to next table set */ + pt += 512; + + d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1]; + c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1]; + b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1]; + a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1]; + + pe[ 0 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; + pe[ 1 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 2 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 3 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 4 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 5 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b]; + pe[ 6 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d]; + pe[ 7 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; + pe[ 8 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[ 9 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[10 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[11 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[12 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a]; + pe[13 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c]; + pe[14 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; + pe[15 * 2 + 1] = DES_PC2(b, c, d, a); + + /* Fixup: 2413 5768 -> 1357 2468 */ + for (d = 0; d < 16; ++d) { + a = pe[2 * d]; + b = pe[2 * d + 1]; + c = a ^ b; + c &= 0xffff0000; + a ^= c; + b ^= c; + ROL(b, 18); + pe[2 * d] = a; + pe[2 * d + 1] = b; + } +} + +void des_encrypt(const struct des_ctx *ctx, u8 *dst, const u8 *src) +{ + const u32 *K = ctx->expkey; + u32 L, R, A, B; + int i; + + L = get_unaligned_le32(src); + R = get_unaligned_le32(src + 4); + + IP(L, R, A); + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, 2); + ROUND(R, L, A, B, K, 2); + } + FP(R, L, A); + + put_unaligned_le32(R, dst); + put_unaligned_le32(L, dst + 4); +} +EXPORT_SYMBOL_GPL(des_encrypt); + +void des_decrypt(const struct des_ctx *ctx, u8 *dst, const u8 *src) +{ + const u32 *K = ctx->expkey + DES_EXPKEY_WORDS - 2; + u32 L, R, A, B; + int i; + + L = get_unaligned_le32(src); + R = get_unaligned_le32(src + 4); + + IP(L, R, A); + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, -2); + ROUND(R, L, A, B, K, -2); + } + FP(R, L, A); + + put_unaligned_le32(R, dst); + put_unaligned_le32(L, dst + 4); +} +EXPORT_SYMBOL_GPL(des_decrypt); + +int des3_ede_expand_key(struct des3_ede_ctx *ctx, const u8 *key, + unsigned int keylen) +{ + u32 *pe = ctx->expkey; + int err; + + if (keylen != DES3_EDE_KEY_SIZE) + return -EINVAL; + + err = des3_ede_verify_key(key, keylen, true); + if (err && err != -ENOKEY) + return err; + + des_ekey(pe, key); pe += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; + dkey(pe, key); pe += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; + des_ekey(pe, key); + + return err; +} +EXPORT_SYMBOL_GPL(des3_ede_expand_key); + +void des3_ede_encrypt(const struct des3_ede_ctx *dctx, u8 *dst, const u8 *src) +{ + const u32 *K = dctx->expkey; + u32 L, R, A, B; + int i; + + L = get_unaligned_le32(src); + R = get_unaligned_le32(src + 4); + + IP(L, R, A); + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, 2); + ROUND(R, L, A, B, K, 2); + } + for (i = 0; i < 8; i++) { + ROUND(R, L, A, B, K, 2); + ROUND(L, R, A, B, K, 2); + } + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, 2); + ROUND(R, L, A, B, K, 2); + } + FP(R, L, A); + + put_unaligned_le32(R, dst); + put_unaligned_le32(L, dst + 4); +} +EXPORT_SYMBOL_GPL(des3_ede_encrypt); + +void des3_ede_decrypt(const struct des3_ede_ctx *dctx, u8 *dst, const u8 *src) +{ + const u32 *K = dctx->expkey + DES3_EDE_EXPKEY_WORDS - 2; + u32 L, R, A, B; + int i; + + L = get_unaligned_le32(src); + R = get_unaligned_le32(src + 4); + + IP(L, R, A); + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, -2); + ROUND(R, L, A, B, K, -2); + } + for (i = 0; i < 8; i++) { + ROUND(R, L, A, B, K, -2); + ROUND(L, R, A, B, K, -2); + } + for (i = 0; i < 8; i++) { + ROUND(L, R, A, B, K, -2); + ROUND(R, L, A, B, K, -2); + } + FP(R, L, A); + + put_unaligned_le32(R, dst); + put_unaligned_le32(L, dst + 4); +} +EXPORT_SYMBOL_GPL(des3_ede_decrypt); + +MODULE_LICENSE("GPL"); -- GitLab From cc1d24b980ded2124f6f80b1321427031fd2beb3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:10 +0300 Subject: [PATCH 4005/7155] crypto: x86/des - switch to library interface Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/des3_ede_glue.c | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/x86/crypto/des3_ede_glue.c b/arch/x86/crypto/des3_ede_glue.c index f730a312ce35..89830e531350 100644 --- a/arch/x86/crypto/des3_ede_glue.c +++ b/arch/x86/crypto/des3_ede_glue.c @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include @@ -19,8 +19,8 @@ #include struct des3_ede_x86_ctx { - u32 enc_expkey[DES3_EDE_EXPKEY_WORDS]; - u32 dec_expkey[DES3_EDE_EXPKEY_WORDS]; + struct des3_ede_ctx enc; + struct des3_ede_ctx dec; }; /* regular block cipher functions */ @@ -34,7 +34,7 @@ asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst, static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, const u8 *src) { - u32 *enc_ctx = ctx->enc_expkey; + u32 *enc_ctx = ctx->enc.expkey; des3_ede_x86_64_crypt_blk(enc_ctx, dst, src); } @@ -42,7 +42,7 @@ static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, const u8 *src) { - u32 *dec_ctx = ctx->dec_expkey; + u32 *dec_ctx = ctx->dec.expkey; des3_ede_x86_64_crypt_blk(dec_ctx, dst, src); } @@ -50,7 +50,7 @@ static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, const u8 *src) { - u32 *enc_ctx = ctx->enc_expkey; + u32 *enc_ctx = ctx->enc.expkey; des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src); } @@ -58,7 +58,7 @@ static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, const u8 *src) { - u32 *dec_ctx = ctx->dec_expkey; + u32 *dec_ctx = ctx->dec.expkey; des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src); } @@ -122,7 +122,7 @@ static int ecb_encrypt(struct skcipher_request *req) struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); - return ecb_crypt(req, ctx->enc_expkey); + return ecb_crypt(req, ctx->enc.expkey); } static int ecb_decrypt(struct skcipher_request *req) @@ -130,7 +130,7 @@ static int ecb_decrypt(struct skcipher_request *req) struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); - return ecb_crypt(req, ctx->dec_expkey); + return ecb_crypt(req, ctx->dec.expkey); } static unsigned int __cbc_encrypt(struct des3_ede_x86_ctx *ctx, @@ -348,24 +348,28 @@ static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key, u32 i, j, tmp; int err; - err = crypto_des3_ede_verify_key(tfm, key); - if (err) - return err; + err = des3_ede_expand_key(&ctx->enc, key, keylen); + if (err == -ENOKEY) { + if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) + err = -EINVAL; + else + err = 0; + } - /* Generate encryption context using generic implementation. */ - err = __des3_ede_setkey(ctx->enc_expkey, &tfm->crt_flags, key, keylen); - if (err < 0) + if (err) { + memset(ctx, 0, sizeof(*ctx)); return err; + } /* Fix encryption context for this implementation and form decryption * context. */ j = DES3_EDE_EXPKEY_WORDS - 2; for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) { - tmp = ror32(ctx->enc_expkey[i + 1], 4); - ctx->enc_expkey[i + 1] = tmp; + tmp = ror32(ctx->enc.expkey[i + 1], 4); + ctx->enc.expkey[i + 1] = tmp; - ctx->dec_expkey[j + 0] = ctx->enc_expkey[i + 0]; - ctx->dec_expkey[j + 1] = tmp; + ctx->dec.expkey[j + 0] = ctx->enc.expkey[i + 0]; + ctx->dec.expkey[j + 1] = tmp; } return 0; -- GitLab From 18fbe0da8e98fe167fbfe1757003e2a2a74d24f3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:11 +0300 Subject: [PATCH 4006/7155] crypto: des - remove now unused __des3_ede_setkey() Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/des_generic.c | 13 ------------- include/crypto/des.h | 3 --- 2 files changed, 16 deletions(-) diff --git a/crypto/des_generic.c b/crypto/des_generic.c index e021a321f584..6e13a4a29ecb 100644 --- a/crypto/des_generic.c +++ b/crypto/des_generic.c @@ -51,19 +51,6 @@ static void crypto_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) des_decrypt(dctx, dst, src); } -int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, - unsigned int keylen) -{ - int err; - - des_ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; - dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE; - des_ekey(expkey, key); - - return 0; -} -EXPORT_SYMBOL_GPL(__des3_ede_setkey); - static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { diff --git a/include/crypto/des.h b/include/crypto/des.h index 2c864a4e6707..7812b4331ae4 100644 --- a/include/crypto/des.h +++ b/include/crypto/des.h @@ -54,7 +54,4 @@ int des_expand_key(struct des_ctx *ctx, const u8 *key, unsigned int keylen); int des3_ede_expand_key(struct des3_ede_ctx *ctx, const u8 *key, unsigned int keylen); -extern int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, - unsigned int keylen); - #endif /* __CRYPTO_DES_H */ -- GitLab From 9a394d1208147715b8a365f44b4e7bfbb2094748 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 15 Aug 2019 12:01:12 +0300 Subject: [PATCH 4007/7155] fs: cifs: move from the crypto cipher API to the new DES library interface Some legacy code in the CIFS driver uses single DES to calculate some password hash, and uses the crypto cipher API to do so. Given that there is no point in invoking an accelerated cipher for doing 56-bit symmetric encryption on a single 8-byte block of input, the flexibility of the crypto cipher API does not add much value here, and so we're much better off using a library call into the generic C implementation. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- fs/cifs/Kconfig | 2 +- fs/cifs/cifsfs.c | 1 - fs/cifs/smbencrypt.c | 18 +++++++++--------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index b16219e5dac9..350bc3061656 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -16,7 +16,7 @@ config CIFS select CRYPTO_GCM select CRYPTO_ECB select CRYPTO_AES - select CRYPTO_DES + select CRYPTO_LIB_DES select KEYS help This is the client VFS module for the SMB3 family of NAS protocols, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3289b566463f..4e2f74894e9b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1601,7 +1601,6 @@ MODULE_DESCRIPTION ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and " "also older servers complying with the SNIA CIFS Specification)"); MODULE_VERSION(CIFS_VERSION); -MODULE_SOFTDEP("pre: des"); MODULE_SOFTDEP("pre: ecb"); MODULE_SOFTDEP("pre: hmac"); MODULE_SOFTDEP("pre: md4"); diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 2b6d87bfdf8e..39a938443e3e 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -11,13 +11,14 @@ */ -#include #include #include +#include #include #include #include #include +#include #include "cifs_fs_sb.h" #include "cifs_unicode.h" #include "cifspdu.h" @@ -58,19 +59,18 @@ static int smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) { unsigned char key2[8]; - struct crypto_cipher *tfm_des; + struct des_ctx ctx; str_to_key(key, key2); - tfm_des = crypto_alloc_cipher("des", 0, 0); - if (IS_ERR(tfm_des)) { - cifs_dbg(VFS, "could not allocate des crypto API\n"); - return PTR_ERR(tfm_des); + if (fips_enabled) { + cifs_dbg(VFS, "FIPS compliance enabled: DES not permitted\n"); + return -ENOENT; } - crypto_cipher_setkey(tfm_des, key2, 8); - crypto_cipher_encrypt_one(tfm_des, out, in); - crypto_free_cipher(tfm_des); + des_expand_key(&ctx, key2, DES_KEY_SIZE); + des_encrypt(&ctx, out, in); + memzero_explicit(&ctx, sizeof(ctx)); return 0; } -- GitLab From b395ed4f948a21c27391ed7981e7e210d19c9366 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 16 Aug 2019 08:47:43 +1000 Subject: [PATCH 4008/7155] crypto: hisilicon - Fix warning on printing %p with dma_addr_t This patch fixes a printk format warning by replacing %p with %#llx for dma_addr_t. Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index d72e062a3619..f975c393a603 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -347,8 +347,8 @@ static int qm_mb(struct hisi_qm *qm, u8 cmd, dma_addr_t dma_addr, u16 queue, struct qm_mailbox mailbox; int ret = 0; - dev_dbg(&qm->pdev->dev, "QM mailbox request to q%u: %u-%pad\n", queue, - cmd, dma_addr); + dev_dbg(&qm->pdev->dev, "QM mailbox request to q%u: %u-%llx\n", + queue, cmd, (unsigned long long)dma_addr); mailbox.w0 = cmd | (op ? 0x1 << QM_MB_OP_SHIFT : 0) | -- GitLab From 8ce5fac2dc1bf64e1e6d2371e4ff9a9bfe8fd49f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 16 Aug 2019 15:21:50 +0300 Subject: [PATCH 4009/7155] crypto: x86/xts - implement support for ciphertext stealing Align the x86 code with the generic XTS template, which now supports ciphertext stealing as described by the IEEE XTS-AES spec P1619. Tested-by: Stephan Mueller Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/x86/crypto/aesni-intel_glue.c | 6 +- arch/x86/crypto/camellia_aesni_avx2_glue.c | 4 +- arch/x86/crypto/camellia_aesni_avx_glue.c | 4 +- arch/x86/crypto/cast6_avx_glue.c | 4 +- arch/x86/crypto/glue_helper.c | 67 +++++++++++++++++++++- arch/x86/crypto/serpent_avx2_glue.c | 4 +- arch/x86/crypto/serpent_avx_glue.c | 4 +- arch/x86/crypto/twofish_avx_glue.c | 4 +- arch/x86/include/asm/crypto/glue_helper.h | 2 +- 9 files changed, 81 insertions(+), 18 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index ef165d8cf443..bf12bb71cecc 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -609,7 +609,8 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&aesni_enc_xts, req, XTS_TWEAK_CAST(aesni_xts_tweak), aes_ctx(ctx->raw_tweak_ctx), - aes_ctx(ctx->raw_crypt_ctx)); + aes_ctx(ctx->raw_crypt_ctx), + false); } static int xts_decrypt(struct skcipher_request *req) @@ -620,7 +621,8 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&aesni_dec_xts, req, XTS_TWEAK_CAST(aesni_xts_tweak), aes_ctx(ctx->raw_tweak_ctx), - aes_ctx(ctx->raw_crypt_ctx)); + aes_ctx(ctx->raw_crypt_ctx), + true); } static int diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c index abf298c272dc..a4f00128ea55 100644 --- a/arch/x86/crypto/camellia_aesni_avx2_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c @@ -182,7 +182,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&camellia_enc_xts, req, XTS_TWEAK_CAST(camellia_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -192,7 +192,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&camellia_dec_xts, req, XTS_TWEAK_CAST(camellia_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg camellia_algs[] = { diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c index 0c22d84750a3..f28d282779b8 100644 --- a/arch/x86/crypto/camellia_aesni_avx_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx_glue.c @@ -208,7 +208,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&camellia_enc_xts, req, XTS_TWEAK_CAST(camellia_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -218,7 +218,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&camellia_dec_xts, req, XTS_TWEAK_CAST(camellia_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg camellia_algs[] = { diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c index 645f8f16815c..a8a38fffb4a9 100644 --- a/arch/x86/crypto/cast6_avx_glue.c +++ b/arch/x86/crypto/cast6_avx_glue.c @@ -201,7 +201,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&cast6_enc_xts, req, XTS_TWEAK_CAST(__cast6_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -211,7 +211,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&cast6_dec_xts, req, XTS_TWEAK_CAST(__cast6_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg cast6_algs[] = { diff --git a/arch/x86/crypto/glue_helper.c b/arch/x86/crypto/glue_helper.c index 901551445387..d15b99397480 100644 --- a/arch/x86/crypto/glue_helper.c +++ b/arch/x86/crypto/glue_helper.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -259,17 +260,36 @@ static unsigned int __glue_xts_req_128bit(const struct common_glue_ctx *gctx, int glue_xts_req_128bit(const struct common_glue_ctx *gctx, struct skcipher_request *req, common_glue_func_t tweak_fn, void *tweak_ctx, - void *crypt_ctx) + void *crypt_ctx, bool decrypt) { + const bool cts = (req->cryptlen % XTS_BLOCK_SIZE); const unsigned int bsize = 128 / 8; + struct skcipher_request subreq; struct skcipher_walk walk; bool fpu_enabled = false; - unsigned int nbytes; + unsigned int nbytes, tail; int err; + if (req->cryptlen < XTS_BLOCK_SIZE) + return -EINVAL; + + if (unlikely(cts)) { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + + tail = req->cryptlen % XTS_BLOCK_SIZE + XTS_BLOCK_SIZE; + + skcipher_request_set_tfm(&subreq, tfm); + skcipher_request_set_callback(&subreq, + crypto_skcipher_get_flags(tfm), + NULL, NULL); + skcipher_request_set_crypt(&subreq, req->src, req->dst, + req->cryptlen - tail, req->iv); + req = &subreq; + } + err = skcipher_walk_virt(&walk, req, false); nbytes = walk.nbytes; - if (!nbytes) + if (err) return err; /* set minimum length to bsize, for tweak_fn */ @@ -287,6 +307,47 @@ int glue_xts_req_128bit(const struct common_glue_ctx *gctx, nbytes = walk.nbytes; } + if (unlikely(cts)) { + u8 *next_tweak, *final_tweak = req->iv; + struct scatterlist *src, *dst; + struct scatterlist s[2], d[2]; + le128 b[2]; + + dst = src = scatterwalk_ffwd(s, req->src, req->cryptlen); + if (req->dst != req->src) + dst = scatterwalk_ffwd(d, req->dst, req->cryptlen); + + if (decrypt) { + next_tweak = memcpy(b, req->iv, XTS_BLOCK_SIZE); + gf128mul_x_ble(b, b); + } else { + next_tweak = req->iv; + } + + skcipher_request_set_crypt(&subreq, src, dst, XTS_BLOCK_SIZE, + next_tweak); + + err = skcipher_walk_virt(&walk, req, false) ?: + skcipher_walk_done(&walk, + __glue_xts_req_128bit(gctx, crypt_ctx, &walk)); + if (err) + goto out; + + scatterwalk_map_and_copy(b, dst, 0, XTS_BLOCK_SIZE, 0); + memcpy(b + 1, b, tail - XTS_BLOCK_SIZE); + scatterwalk_map_and_copy(b, src, XTS_BLOCK_SIZE, + tail - XTS_BLOCK_SIZE, 0); + scatterwalk_map_and_copy(b, dst, 0, tail, 1); + + skcipher_request_set_crypt(&subreq, dst, dst, XTS_BLOCK_SIZE, + final_tweak); + + err = skcipher_walk_virt(&walk, req, false) ?: + skcipher_walk_done(&walk, + __glue_xts_req_128bit(gctx, crypt_ctx, &walk)); + } + +out: glue_fpu_end(fpu_enabled); return err; diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c index b871728e0b2f..13fd8d3d2da0 100644 --- a/arch/x86/crypto/serpent_avx2_glue.c +++ b/arch/x86/crypto/serpent_avx2_glue.c @@ -167,7 +167,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&serpent_enc_xts, req, XTS_TWEAK_CAST(__serpent_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -177,7 +177,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&serpent_dec_xts, req, XTS_TWEAK_CAST(__serpent_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg serpent_algs[] = { diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c index 4a9a9f2ee1d8..7d3dca38a5a2 100644 --- a/arch/x86/crypto/serpent_avx_glue.c +++ b/arch/x86/crypto/serpent_avx_glue.c @@ -207,7 +207,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&serpent_enc_xts, req, XTS_TWEAK_CAST(__serpent_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -217,7 +217,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&serpent_dec_xts, req, XTS_TWEAK_CAST(__serpent_encrypt), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg serpent_algs[] = { diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c index 0dbf8e8b09d7..d561c821788b 100644 --- a/arch/x86/crypto/twofish_avx_glue.c +++ b/arch/x86/crypto/twofish_avx_glue.c @@ -210,7 +210,7 @@ static int xts_encrypt(struct skcipher_request *req) return glue_xts_req_128bit(&twofish_enc_xts, req, XTS_TWEAK_CAST(twofish_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, false); } static int xts_decrypt(struct skcipher_request *req) @@ -220,7 +220,7 @@ static int xts_decrypt(struct skcipher_request *req) return glue_xts_req_128bit(&twofish_dec_xts, req, XTS_TWEAK_CAST(twofish_enc_blk), - &ctx->tweak_ctx, &ctx->crypt_ctx); + &ctx->tweak_ctx, &ctx->crypt_ctx, true); } static struct skcipher_alg twofish_algs[] = { diff --git a/arch/x86/include/asm/crypto/glue_helper.h b/arch/x86/include/asm/crypto/glue_helper.h index d1818634ae7e..8d4a8e1226ee 100644 --- a/arch/x86/include/asm/crypto/glue_helper.h +++ b/arch/x86/include/asm/crypto/glue_helper.h @@ -114,7 +114,7 @@ extern int glue_ctr_req_128bit(const struct common_glue_ctx *gctx, extern int glue_xts_req_128bit(const struct common_glue_ctx *gctx, struct skcipher_request *req, common_glue_func_t tweak_fn, void *tweak_ctx, - void *crypt_ctx); + void *crypt_ctx, bool decrypt); extern void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src, le128 *iv, common_glue_func_t fn); -- GitLab From ce68acbcb6a5d5dbaa9e76df924e1c191e8c7516 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 16 Aug 2019 15:35:45 +0300 Subject: [PATCH 4010/7155] crypto: s390/xts-aes - invoke fallback for ciphertext stealing For correctness and compliance with the XTS-AES specification, we are adding support for ciphertext stealing to XTS implementations, even though no use cases are known that will be enabled by this. Since the s390 implementation already has a fallback skcipher standby for other purposes, let's use it for this purpose as well. If ciphertext stealing use cases ever become a bottleneck, we can always revisit this. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/s390/crypto/aes_s390.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index dc0f72dd6e03..a34faadc757e 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -512,7 +512,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned long fc; int err; - err = xts_check_key(tfm, in_key, key_len); + err = xts_fallback_setkey(tfm, in_key, key_len); if (err) return err; @@ -529,7 +529,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, /* Check if the function code is available */ xts_ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; if (!xts_ctx->fc) - return xts_fallback_setkey(tfm, in_key, key_len); + return 0; /* Split the XTS key into the two subkeys */ key_len = key_len / 2; @@ -586,7 +586,7 @@ static int xts_aes_encrypt(struct blkcipher_desc *desc, struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; - if (unlikely(!xts_ctx->fc)) + if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCKSIZE) != 0)) return xts_fallback_encrypt(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); @@ -600,7 +600,7 @@ static int xts_aes_decrypt(struct blkcipher_desc *desc, struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; - if (unlikely(!xts_ctx->fc)) + if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCKSIZE) != 0)) return xts_fallback_decrypt(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); -- GitLab From 23966841934908ad4ef997231f1fdd1f9a9d0f42 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 16 Aug 2019 17:06:24 +0300 Subject: [PATCH 4011/7155] crypto: vmx/xts - use fallback for ciphertext stealing For correctness and compliance with the XTS-AES specification, we are adding support for ciphertext stealing to XTS implementations, even though no use cases are known that will be enabled by this. Since the Power8 implementation already has a fallback skcipher standby for other purposes, let's use it for this purpose as well. If ciphertext stealing use cases ever become a bottleneck, we can always revisit this. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/vmx/aes_xts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/vmx/aes_xts.c b/drivers/crypto/vmx/aes_xts.c index 49f7258045fa..d59e736882f6 100644 --- a/drivers/crypto/vmx/aes_xts.c +++ b/drivers/crypto/vmx/aes_xts.c @@ -84,7 +84,7 @@ static int p8_aes_xts_crypt(struct skcipher_request *req, int enc) u8 tweak[AES_BLOCK_SIZE]; int ret; - if (!crypto_simd_usable()) { + if (!crypto_simd_usable() || (req->cryptlen % XTS_BLOCK_SIZE) != 0) { struct skcipher_request *subreq = skcipher_request_ctx(req); *subreq = *req; -- GitLab From aca1111965d78477f9169c0df54d0ea06173572f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:29 +0200 Subject: [PATCH 4012/7155] crypto: sha256 - Fix some coding style issues For some reason after the first 15 steps the last statement of each step ends with "t1+t2", missing spaces around the "+". This commit fixes this. This was done with a 's/= t1+t2/= t1 + t2/' to make sure no functional changes are introduced. Note the main goal of this is to make lib/sha256.c's sha256_transform and its helpers identical in formatting too the duplcate implementation in crypto/sha256_generic.c so that "diff -u" can be used to compare them to prove that no functional changes are made when further patches in this series consolidate the 2 implementations into 1. Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- lib/sha256.c | 98 ++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/lib/sha256.c b/lib/sha256.c index d9af148d4349..ba4dce0b3711 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -92,109 +92,109 @@ static void sha256_transform(u32 *state, const u8 *input) t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14]; t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; -- GitLab From 1a01333d313447f0cdfcc2882ea3afe387a24be0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:30 +0200 Subject: [PATCH 4013/7155] crypto: sha256_generic - Fix some coding style issues Add a bunch of missing spaces after commas and arround operators. Note the main goal of this is to make sha256_transform and its helpers identical in formatting too the duplcate implementation in lib/sha256.c, so that "diff -u" can be used to compare them to prove that no functional changes are made when further patches in this series consolidate the 2 implementations into 1. Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- crypto/sha256_generic.c | 268 ++++++++++++++++++++-------------------- 1 file changed, 134 insertions(+), 134 deletions(-) diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c index b7502a96a0d4..dac930ca827d 100644 --- a/crypto/sha256_generic.c +++ b/crypto/sha256_generic.c @@ -48,10 +48,10 @@ static inline u32 Maj(u32 x, u32 y, u32 z) return (x & y) | (z & (x | y)); } -#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22)) -#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25)) -#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3)) -#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10)) +#define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22)) +#define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25)) +#define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3)) +#define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10)) static inline void LOAD_OP(int I, u32 *W, const u8 *input) { @@ -78,145 +78,145 @@ static void sha256_transform(u32 *state, const u8 *input) BLEND_OP(i, W); /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; + a = state[0]; b = state[1]; c = state[2]; d = state[3]; + e = state[4]; f = state[5]; g = state[6]; h = state[7]; /* now iterate */ - t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56]; + t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; + t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57]; + t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; + t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58]; + t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; + t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59]; + t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; + t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60]; + t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; + t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61]; + t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; + t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62]; + t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; + t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63]; + t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; -- GitLab From ad767ee858b38af634c957a792cb001d54a7b981 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:31 +0200 Subject: [PATCH 4014/7155] crypto: sha256 - Move lib/sha256.c to lib/crypto Generic crypto implementations belong under lib/crypto not directly in lib, likewise the header should be in include/crypto, not include/linux. Note that the code in lib/crypto/sha256.c is not yet available for generic use after this commit, it is still only used by the s390 and x86 purgatory code. Making it suitable for generic use is done in further patches in this series. Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- arch/s390/purgatory/Makefile | 2 +- arch/s390/purgatory/purgatory.c | 2 +- arch/x86/purgatory/Makefile | 2 +- arch/x86/purgatory/purgatory.c | 2 +- include/{linux => crypto}/sha256.h | 2 +- lib/{ => crypto}/sha256.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename include/{linux => crypto}/sha256.h (94%) rename lib/{ => crypto}/sha256.c (99%) diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index dc1ae4ff79d7..85b05c9e40f5 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -7,7 +7,7 @@ purgatory-y := head.o purgatory.o string.o sha256.o mem.o targets += $(purgatory-y) purgatory.lds purgatory purgatory.ro PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) -$(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE +$(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c index 3528e6da4e87..a80c78da9985 100644 --- a/arch/s390/purgatory/purgatory.c +++ b/arch/s390/purgatory/purgatory.c @@ -8,8 +8,8 @@ */ #include -#include #include +#include #include int verify_sha256_digest(void) diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 3cf302b26332..026fa0006f0b 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -6,7 +6,7 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string targets += $(purgatory-y) PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) -$(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE +$(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c index 6d8d5a34c377..7cd7a2618180 100644 --- a/arch/x86/purgatory/purgatory.c +++ b/arch/x86/purgatory/purgatory.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include "../boot/string.h" diff --git a/include/linux/sha256.h b/include/crypto/sha256.h similarity index 94% rename from include/linux/sha256.h rename to include/crypto/sha256.h index 26972b9e92db..b1f9c6781082 100644 --- a/include/linux/sha256.h +++ b/include/crypto/sha256.h @@ -17,7 +17,7 @@ * kexec_file purgatory. In other cases you should use the implementation in * crypto/. * - * For details see lib/sha256.c + * For details see lib/crypto/sha256.c */ extern int sha256_init(struct sha256_state *sctx); diff --git a/lib/sha256.c b/lib/crypto/sha256.c similarity index 99% rename from lib/sha256.c rename to lib/crypto/sha256.c index ba4dce0b3711..b8114028d06f 100644 --- a/lib/sha256.c +++ b/lib/crypto/sha256.c @@ -12,8 +12,8 @@ */ #include -#include #include +#include #include static inline u32 Ch(u32 x, u32 y, u32 z) -- GitLab From 906a4bb97f5d0389cae9cc3634e8059fed5334b5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:32 +0200 Subject: [PATCH 4015/7155] crypto: sha256 - Use get/put_unaligned_be32 to get input, memzero_explicit Use get/put_unaligned_be32 in lib/crypto/sha256.c to load / store data so that it can be used with unaligned buffers too, making it more generic. And use memzero_explicit for better clearing of sensitive data. Note unlike other patches in this series this commit actually makes functional changes to the sha256 code as used by the purgatory code. This fully aligns the lib/crypto/sha256.c sha256 implementation with the one from crypto/sha256_generic.c allowing us to remove the latter in further patches in this series. Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index b8114028d06f..1458a20d53a5 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include static inline u32 Ch(u32 x, u32 y, u32 z) { @@ -33,7 +33,7 @@ static inline u32 Maj(u32 x, u32 y, u32 z) static inline void LOAD_OP(int I, u32 *W, const u8 *input) { - W[I] = __be32_to_cpu(((__be32 *)(input))[I]); + W[I] = get_unaligned_be32((__u32 *)input + I); } static inline void BLEND_OP(int I, u32 *W) @@ -201,7 +201,7 @@ static void sha256_transform(u32 *state, const u8 *input) /* clear any sensitive info... */ a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, 64 * sizeof(u32)); + memzero_explicit(W, 64 * sizeof(u32)); } int sha256_init(struct sha256_state *sctx) @@ -270,7 +270,7 @@ int sha256_final(struct sha256_state *sctx, u8 *out) /* Store state in digest */ for (i = 0; i < 8; i++) - dst[i] = cpu_to_be32(sctx->state[i]); + put_unaligned_be32(sctx->state[i], &dst[i]); /* Zeroize sensitive information. */ memset(sctx, 0, sizeof(*sctx)); -- GitLab From 01d3aee86625bd798a5e69afb92517d5530c7ed1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:33 +0200 Subject: [PATCH 4016/7155] crypto: sha256 - Make lib/crypto/sha256.c suitable for generic use Before this commit lib/crypto/sha256.c has only been used in the s390 and x86 purgatory code, make it suitable for generic use: * Export interesting symbols * Add -D__DISABLE_EXPORTS to CFLAGS_sha256.o for purgatory builds to avoid the exports for the purgatory builds * Add to lib/crypto/Makefile and crypto/Kconfig Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- arch/s390/purgatory/Makefile | 2 ++ arch/x86/purgatory/Makefile | 2 ++ crypto/Kconfig | 3 +++ include/crypto/sha256.h | 5 +++-- lib/crypto/Makefile | 3 +++ lib/crypto/sha256.c | 4 ++++ 6 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index 85b05c9e40f5..bc0d7a0d0394 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -10,6 +10,8 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) +CFLAGS_sha256.o := -D__DISABLE_EXPORTS + $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE $(call if_changed_rule,as_o_S) diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 026fa0006f0b..ea86982aba27 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -9,6 +9,8 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) +CFLAGS_sha256.o := -D__DISABLE_EXPORTS + LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib targets += purgatory.ro diff --git a/crypto/Kconfig b/crypto/Kconfig index 42a17fe97703..e96b321b51af 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -849,6 +849,9 @@ config CRYPTO_SHA1_PPC_SPE SHA-1 secure hash standard (DFIPS 180-4) implemented using powerpc SPE SIMD instruction set. +config CRYPTO_LIB_SHA256 + tristate + config CRYPTO_SHA256 tristate "SHA224 and SHA256 digest algorithm" select CRYPTO_HASH diff --git a/include/crypto/sha256.h b/include/crypto/sha256.h index b1f9c6781082..9cbb3589b8b3 100644 --- a/include/crypto/sha256.h +++ b/include/crypto/sha256.h @@ -14,8 +14,9 @@ /* * Stand-alone implementation of the SHA256 algorithm. It is designed to * have as little dependencies as possible so it can be used in the - * kexec_file purgatory. In other cases you should use the implementation in - * crypto/. + * kexec_file purgatory. In other cases you should generally use the + * hash APIs from include/crypto/hash.h. Especially when hashing large + * amounts of data as those APIs may be hw-accelerated. * * For details see lib/crypto/sha256.c */ diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 101a321b8a99..cbe0b6a6450d 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -8,3 +8,6 @@ libarc4-y := arc4.o obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o libdes-y := des.o + +obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o +libsha256-y := sha256.o diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index 1458a20d53a5..f2ed75ae6910 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -218,6 +219,7 @@ int sha256_init(struct sha256_state *sctx) return 0; } +EXPORT_SYMBOL(sha256_init); int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) { @@ -248,6 +250,7 @@ int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) return 0; } +EXPORT_SYMBOL(sha256_update); int sha256_final(struct sha256_state *sctx, u8 *out) { @@ -277,3 +280,4 @@ int sha256_final(struct sha256_state *sctx, u8 *out) return 0; } +EXPORT_SYMBOL(sha256_final); -- GitLab From 7d2f5b0c43e0bb346fbf78daefd68cd0bfc56ca3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:34 +0200 Subject: [PATCH 4017/7155] crypto: sha256 - Add sha224 support to sha256 library code Add sha224 support to the lib/crypto/sha256 library code. This will allow us to replace both the sha256 and sha224 parts of crypto/sha256_generic.c when we remove the code duplication in further patches in this series. Suggested-by: Eric Biggers Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- include/crypto/sha256.h | 5 +++++ lib/crypto/sha256.c | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/crypto/sha256.h b/include/crypto/sha256.h index 9cbb3589b8b3..a75998d65a41 100644 --- a/include/crypto/sha256.h +++ b/include/crypto/sha256.h @@ -26,4 +26,9 @@ extern int sha256_update(struct sha256_state *sctx, const u8 *input, unsigned int length); extern int sha256_final(struct sha256_state *sctx, u8 *hash); +extern int sha224_init(struct sha256_state *sctx); +extern int sha224_update(struct sha256_state *sctx, const u8 *input, + unsigned int length); +extern int sha224_final(struct sha256_state *sctx, u8 *hash); + #endif /* SHA256_H */ diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index f2ed75ae6910..45ad87520769 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -221,6 +221,22 @@ int sha256_init(struct sha256_state *sctx) } EXPORT_SYMBOL(sha256_init); +int sha224_init(struct sha256_state *sctx) +{ + sctx->state[0] = SHA224_H0; + sctx->state[1] = SHA224_H1; + sctx->state[2] = SHA224_H2; + sctx->state[3] = SHA224_H3; + sctx->state[4] = SHA224_H4; + sctx->state[5] = SHA224_H5; + sctx->state[6] = SHA224_H6; + sctx->state[7] = SHA224_H7; + sctx->count = 0; + + return 0; +} +EXPORT_SYMBOL(sha224_init); + int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) { unsigned int partial, done; @@ -252,7 +268,13 @@ int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) } EXPORT_SYMBOL(sha256_update); -int sha256_final(struct sha256_state *sctx, u8 *out) +int sha224_update(struct sha256_state *sctx, const u8 *data, unsigned int len) +{ + return sha256_update(sctx, data, len); +} +EXPORT_SYMBOL(sha224_update); + +static int __sha256_final(struct sha256_state *sctx, u8 *out, int digest_words) { __be32 *dst = (__be32 *)out; __be64 bits; @@ -272,7 +294,7 @@ int sha256_final(struct sha256_state *sctx, u8 *out) sha256_update(sctx, (const u8 *)&bits, sizeof(bits)); /* Store state in digest */ - for (i = 0; i < 8; i++) + for (i = 0; i < digest_words; i++) put_unaligned_be32(sctx->state[i], &dst[i]); /* Zeroize sensitive information. */ @@ -280,4 +302,15 @@ int sha256_final(struct sha256_state *sctx, u8 *out) return 0; } + +int sha256_final(struct sha256_state *sctx, u8 *out) +{ + return __sha256_final(sctx, out, 8); +} EXPORT_SYMBOL(sha256_final); + +int sha224_final(struct sha256_state *sctx, u8 *out) +{ + return __sha256_final(sctx, out, 7); +} +EXPORT_SYMBOL(sha224_final); -- GitLab From 08c327f63f355fce190ac3e1ac62e19d2c5f004d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 Aug 2019 16:24:35 +0200 Subject: [PATCH 4018/7155] crypto: sha256_generic - Switch to the generic lib/crypto/sha256.c lib code Drop the duplicate generic sha256 (and sha224) implementation from crypto/sha256_generic.c and use the implementation from lib/crypto/sha256.c instead. "diff -u lib/crypto/sha256.c sha256_generic.c" shows that the core sha256_transform function from both implementations is identical and the other code is functionally identical too. Suggested-by: Eric Biggers Signed-off-by: Hans de Goede Signed-off-by: Herbert Xu --- crypto/Kconfig | 1 + crypto/sha256_generic.c | 225 ++++------------------------------------ 2 files changed, 19 insertions(+), 207 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index e96b321b51af..ad86463de715 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -855,6 +855,7 @@ config CRYPTO_LIB_SHA256 config CRYPTO_SHA256 tristate "SHA224 and SHA256 digest algorithm" select CRYPTO_HASH + select CRYPTO_LIB_SHA256 help SHA256 secure hash standard (DFIPS 180-2). diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c index dac930ca827d..eafd10f9bf86 100644 --- a/crypto/sha256_generic.c +++ b/crypto/sha256_generic.c @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Cryptographic API. - * - * SHA-256, as specified in - * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf - * - * SHA-256 code by Jean-Luc Cooke . + * Crypto API wrapper for the generic SHA256 code from lib/crypto/sha256.c * * Copyright (c) Jean-Luc Cooke * Copyright (c) Andrew McDonald @@ -18,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -38,229 +34,44 @@ const u8 sha256_zero_message_hash[SHA256_DIGEST_SIZE] = { }; EXPORT_SYMBOL_GPL(sha256_zero_message_hash); -static inline u32 Ch(u32 x, u32 y, u32 z) -{ - return z ^ (x & (y ^ z)); -} - -static inline u32 Maj(u32 x, u32 y, u32 z) +static int crypto_sha256_init(struct shash_desc *desc) { - return (x & y) | (z & (x | y)); + return sha256_init(shash_desc_ctx(desc)); } -#define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22)) -#define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25)) -#define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3)) -#define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10)) - -static inline void LOAD_OP(int I, u32 *W, const u8 *input) +static int crypto_sha224_init(struct shash_desc *desc) { - W[I] = get_unaligned_be32((__u32 *)input + I); -} - -static inline void BLEND_OP(int I, u32 *W) -{ - W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; -} - -static void sha256_transform(u32 *state, const u8 *input) -{ - u32 a, b, c, d, e, f, g, h, t1, t2; - u32 W[64]; - int i; - - /* load the input */ - for (i = 0; i < 16; i++) - LOAD_OP(i, W, input); - - /* now blend */ - for (i = 16; i < 64; i++) - BLEND_OP(i, W); - - /* load the state into our registers */ - a = state[0]; b = state[1]; c = state[2]; d = state[3]; - e = state[4]; f = state[5]; g = state[6]; h = state[7]; - - /* now iterate */ - t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - state[0] += a; state[1] += b; state[2] += c; state[3] += d; - state[4] += e; state[5] += f; state[6] += g; state[7] += h; - - /* clear any sensitive info... */ - a = b = c = d = e = f = g = h = t1 = t2 = 0; - memzero_explicit(W, 64 * sizeof(u32)); -} - -static void sha256_generic_block_fn(struct sha256_state *sst, u8 const *src, - int blocks) -{ - while (blocks--) { - sha256_transform(sst->state, src); - src += SHA256_BLOCK_SIZE; - } + return sha224_init(shash_desc_ctx(desc)); } int crypto_sha256_update(struct shash_desc *desc, const u8 *data, unsigned int len) { - return sha256_base_do_update(desc, data, len, sha256_generic_block_fn); + return sha256_update(shash_desc_ctx(desc), data, len); } EXPORT_SYMBOL(crypto_sha256_update); -static int sha256_final(struct shash_desc *desc, u8 *out) +static int crypto_sha256_final(struct shash_desc *desc, u8 *out) { - sha256_base_do_finalize(desc, sha256_generic_block_fn); - return sha256_base_finish(desc, out); + if (crypto_shash_digestsize(desc->tfm) == SHA224_DIGEST_SIZE) + return sha224_final(shash_desc_ctx(desc), out); + else + return sha256_final(shash_desc_ctx(desc), out); } int crypto_sha256_finup(struct shash_desc *desc, const u8 *data, unsigned int len, u8 *hash) { - sha256_base_do_update(desc, data, len, sha256_generic_block_fn); - return sha256_final(desc, hash); + sha256_update(shash_desc_ctx(desc), data, len); + return crypto_sha256_final(desc, hash); } EXPORT_SYMBOL(crypto_sha256_finup); static struct shash_alg sha256_algs[2] = { { .digestsize = SHA256_DIGEST_SIZE, - .init = sha256_base_init, + .init = crypto_sha256_init, .update = crypto_sha256_update, - .final = sha256_final, + .final = crypto_sha256_final, .finup = crypto_sha256_finup, .descsize = sizeof(struct sha256_state), .base = { @@ -272,9 +83,9 @@ static struct shash_alg sha256_algs[2] = { { } }, { .digestsize = SHA224_DIGEST_SIZE, - .init = sha224_base_init, + .init = crypto_sha224_init, .update = crypto_sha256_update, - .final = sha256_final, + .final = crypto_sha256_final, .finup = crypto_sha256_finup, .descsize = sizeof(struct sha256_state), .base = { -- GitLab From 0eae1e37db8acef1e511cdbc63634cb700188644 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 7 Aug 2019 17:15:43 +0530 Subject: [PATCH 4019/7155] cpufreq: qcom-hw: Update logic to detect turbo frequency The core count read back from the each domain's look up table serves as an indicator for the onset of the turbo frequency and not accurate representation of number of cores in a paticular domain. Update turbo detection logic accordingly to add support for SM8150 SoCs. Signed-off-by: Sibi Sankar Signed-off-by: Viresh Kumar --- drivers/cpufreq/qcom-cpufreq-hw.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 4b0b50403901..c9a9da592f10 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -20,6 +20,7 @@ #define LUT_VOLT GENMASK(11, 0) #define LUT_ROW_SIZE 32 #define CLK_HW_DIV 2 +#define LUT_TURBO_IND 1 /* Register offsets */ #define REG_ENABLE 0x0 @@ -77,9 +78,8 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, struct cpufreq_policy *policy, void __iomem *base) { - u32 data, src, lval, i, core_count, prev_cc = 0, prev_freq = 0, freq; + u32 data, src, lval, i, core_count, prev_freq = 0, freq; u32 volt; - unsigned int max_cores = cpumask_weight(policy->cpus); struct cpufreq_frequency_table *table; table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL); @@ -102,12 +102,12 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, else freq = cpu_hw_rate / 1000; - if (freq != prev_freq && core_count == max_cores) { + if (freq != prev_freq && core_count != LUT_TURBO_IND) { table[i].frequency = freq; dev_pm_opp_add(cpu_dev, freq * 1000, volt); dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i, freq, core_count); - } else { + } else if (core_count == LUT_TURBO_IND) { table[i].frequency = CPUFREQ_ENTRY_INVALID; } @@ -115,14 +115,14 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, * Two of the same frequencies with the same core counts means * end of table */ - if (i > 0 && prev_freq == freq && prev_cc == core_count) { + if (i > 0 && prev_freq == freq) { struct cpufreq_frequency_table *prev = &table[i - 1]; /* * Only treat the last frequency that might be a boost * as the boost frequency */ - if (prev_cc != max_cores) { + if (prev->frequency == CPUFREQ_ENTRY_INVALID) { prev->frequency = prev_freq; prev->flags = CPUFREQ_BOOST_FREQ; dev_pm_opp_add(cpu_dev, prev_freq * 1000, volt); @@ -131,7 +131,6 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, break; } - prev_cc = core_count; prev_freq = freq; } -- GitLab From ada54f35b2270942f45250fa1c553a426b579f9e Mon Sep 17 00:00:00 2001 From: Douglas RAILLARD Date: Thu, 8 Aug 2019 14:18:57 +0100 Subject: [PATCH 4020/7155] cpufreq: qcom-hw: invoke frequency-invariance setter function Add calls to arch_set_freq_scale() in qcom-cpufreq-hw driver to enable frequency invariance. Signed-off-by: Douglas RAILLARD Reviewed-by: Quentin Perret Signed-off-by: Viresh Kumar --- drivers/cpufreq/qcom-cpufreq-hw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index c9a9da592f10..a9ae2f84a4ef 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -35,9 +35,12 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy, unsigned int index) { void __iomem *perf_state_reg = policy->driver_data; + unsigned long freq = policy->freq_table[index].frequency; writel_relaxed(index, perf_state_reg); + arch_set_freq_scale(policy->related_cpus, freq, + policy->cpuinfo.max_freq); return 0; } @@ -64,6 +67,7 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, { void __iomem *perf_state_reg = policy->driver_data; int index; + unsigned long freq; index = policy->cached_resolved_idx; if (index < 0) @@ -71,7 +75,11 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, writel_relaxed(index, perf_state_reg); - return policy->freq_table[index].frequency; + freq = policy->freq_table[index].frequency; + arch_set_freq_scale(policy->related_cpus, freq, + policy->cpuinfo.max_freq); + + return freq; } static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, -- GitLab From 8ec5035039c743888c5ecd04a680676ef1537fe8 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sun, 18 Aug 2019 02:32:21 -0400 Subject: [PATCH 4021/7155] cpufreq: Use imx-cpufreq-dt for i.MX8MN's speed grading Add i.MX8MN to blacklist, so that imx-cpufreq-dt driver can handle speed grading bits just like other i.MX8M SoCs. Signed-off-by: Anson Huang Reviewed-by: Leonard Crestez Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index f9444ddd35ab..6fce11f63403 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -109,6 +109,7 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "fsl,imx7d", }, { .compatible = "fsl,imx8mq", }, { .compatible = "fsl,imx8mm", }, + { .compatible = "fsl,imx8mn", }, { .compatible = "marvell,armadaxp", }, -- GitLab From 75c000c4bcbe2b0eb82baf90c7dd75c7380cc3fd Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sun, 18 Aug 2019 02:32:22 -0400 Subject: [PATCH 4022/7155] cpufreq: imx-cpufreq-dt: Add i.MX8MN support i.MX8MN has different speed grading definition as below, it has 4 bits to define speed grading, add support for it. SPEED_GRADE[3:0] MHz 0000 2300 0001 2200 0010 2100 0011 2000 0100 1900 0101 1800 0110 1700 0111 1600 1000 1500 1001 1400 1010 1300 1011 1200 1100 1100 1101 1000 1110 900 1111 800 Signed-off-by: Anson Huang Reviewed-by: Leonard Crestez Signed-off-by: Viresh Kumar --- drivers/cpufreq/imx-cpufreq-dt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/imx-cpufreq-dt.c b/drivers/cpufreq/imx-cpufreq-dt.c index 4f85f3112784..35db14cf3102 100644 --- a/drivers/cpufreq/imx-cpufreq-dt.c +++ b/drivers/cpufreq/imx-cpufreq-dt.c @@ -16,6 +16,7 @@ #define OCOTP_CFG3_SPEED_GRADE_SHIFT 8 #define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 8) +#define IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK (0xf << 8) #define OCOTP_CFG3_MKT_SEGMENT_SHIFT 6 #define OCOTP_CFG3_MKT_SEGMENT_MASK (0x3 << 6) @@ -34,7 +35,12 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev) if (ret) return ret; - speed_grade = (cell_value & OCOTP_CFG3_SPEED_GRADE_MASK) >> OCOTP_CFG3_SPEED_GRADE_SHIFT; + if (of_machine_is_compatible("fsl,imx8mn")) + speed_grade = (cell_value & IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK) + >> OCOTP_CFG3_SPEED_GRADE_SHIFT; + else + speed_grade = (cell_value & OCOTP_CFG3_SPEED_GRADE_MASK) + >> OCOTP_CFG3_SPEED_GRADE_SHIFT; mkt_segment = (cell_value & OCOTP_CFG3_MKT_SEGMENT_MASK) >> OCOTP_CFG3_MKT_SEGMENT_SHIFT; /* -- GitLab From dce0bb84a73bac8a5bf3ad54e922215b61350481 Mon Sep 17 00:00:00 2001 From: "Andrew-sh.Cheng" Date: Tue, 13 Aug 2019 21:31:46 +0800 Subject: [PATCH 4023/7155] cpufreq: mediatek: change to regulator_get_optional For new mediatek chip mt8183, cci and little cluster share the same buck, so need to modify the attribute of regulator from exclusive to optional Signed-off-by: Andrew-sh.Cheng Signed-off-by: Viresh Kumar --- drivers/cpufreq/mediatek-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 10bc06f5dd45..42bc4c9044f6 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -338,7 +338,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) goto out_free_resources; } - proc_reg = regulator_get_exclusive(cpu_dev, "proc"); + proc_reg = regulator_get_optional(cpu_dev, "proc"); if (IS_ERR(proc_reg)) { if (PTR_ERR(proc_reg) == -EPROBE_DEFER) pr_warn("proc regulator for cpu%d not ready, retry.\n", -- GitLab From 9176b425bf8ff98fd12bffeea8e39373345cd745 Mon Sep 17 00:00:00 2001 From: "Andrew-sh.Cheng" Date: Tue, 13 Aug 2019 21:31:48 +0800 Subject: [PATCH 4024/7155] cpufreq: mediatek: Add support for mt8183 Add compatible string for mediatek mt8183 Signed-off-by: Andrew-sh.Cheng [ VK: Fixed rebase conflict ] Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + drivers/cpufreq/mediatek-cpufreq.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 6fce11f63403..d51bfef286e3 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -120,6 +120,7 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "mediatek,mt817x", }, { .compatible = "mediatek,mt8173", }, { .compatible = "mediatek,mt8176", }, + { .compatible = "mediatek,mt8183", }, { .compatible = "nvidia,tegra124", }, { .compatible = "nvidia,tegra210", }, diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 42bc4c9044f6..0c98dd08273d 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -535,6 +535,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { { .compatible = "mediatek,mt817x", }, { .compatible = "mediatek,mt8173", }, { .compatible = "mediatek,mt8176", }, + { .compatible = "mediatek,mt8183", }, { .compatible = "mediatek,mt8516", }, { } -- GitLab From 49b0f3be0b86292eed6f6aedadf4252131d9c111 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 14:26:55 +0930 Subject: [PATCH 4025/7155] ARM: dts: aspeed: swift: Add eMMC device Swift contains an eMMC device attached to the second SDHCI controller. Reviewed-by: Adriana Kobylak Signed-off-by: Joel Stanley --- arch/arm/boot/dts/aspeed-bmc-opp-swift.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts index f14f745b34ca..25bc0e1bbced 100644 --- a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts +++ b/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts @@ -963,4 +963,15 @@ status = "okay"; }; +&sdmmc { + status = "okay"; +}; + +&sdhci1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd2_default>; +}; + #include "ibm-power9-dual.dtsi" -- GitLab From e5d2f910cfeca852f6e2dc19dfa8dab264ce0cde Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Thu, 22 Aug 2019 05:05:37 +0000 Subject: [PATCH 4026/7155] PCI: hv: Add a paravirtual backchannel in software Windows SR-IOV provides a backchannel mechanism in software for communication between a VF driver and a PF driver. These "configuration blocks" are similar in concept to PCI configuration space, but instead of doing reads and writes in 32-bit chunks through a very slow path, packets of up to 128 bytes can be sent or received asynchronously. Nearly every SR-IOV device contains just such a communications channel in hardware, so using this one in software is usually optional. Using the software channel, however, allows driver implementers to leverage software tools that fuzz the communications channel looking for vulnerabilities. The usage model for these packets puts the responsibility for reading or writing on the VF driver. The VF driver sends a read or a write packet, indicating which "block" is being referred to by number. If the PF driver wishes to initiate communication, it can "invalidate" one or more of the first 64 blocks. This invalidation is delivered via a callback supplied by the VF driver by this driver. No protocol is implied, except that supplied by the PF and VF drivers. Signed-off-by: Jake Oshins Signed-off-by: Dexuan Cui Cc: Haiyang Zhang Cc: K. Y. Srinivasan Cc: Stephen Hemminger Signed-off-by: Saeed Mahameed Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/pci/controller/pci-hyperv.c | 302 ++++++++++++++++++++++++++++ include/linux/hyperv.h | 15 ++ 2 files changed, 317 insertions(+) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 40b625458afa..57adeca7bda9 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -365,6 +365,39 @@ struct pci_delete_interrupt { struct tran_int_desc int_desc; } __packed; +/* + * Note: the VM must pass a valid block id, wslot and bytes_requested. + */ +struct pci_read_block { + struct pci_message message_type; + u32 block_id; + union win_slot_encoding wslot; + u32 bytes_requested; +} __packed; + +struct pci_read_block_response { + struct vmpacket_descriptor hdr; + u32 status; + u8 bytes[HV_CONFIG_BLOCK_SIZE_MAX]; +} __packed; + +/* + * Note: the VM must pass a valid block id, wslot and byte_count. + */ +struct pci_write_block { + struct pci_message message_type; + u32 block_id; + union win_slot_encoding wslot; + u32 byte_count; + u8 bytes[HV_CONFIG_BLOCK_SIZE_MAX]; +} __packed; + +struct pci_dev_inval_block { + struct pci_incoming_message incoming; + union win_slot_encoding wslot; + u64 block_mask; +} __packed; + struct pci_dev_incoming { struct pci_incoming_message incoming; union win_slot_encoding wslot; @@ -499,6 +532,9 @@ struct hv_pci_dev { struct hv_pcibus_device *hbus; struct work_struct wrk; + void (*block_invalidate)(void *context, u64 block_mask); + void *invalidate_context; + /* * What would be observed if one wrote 0xFFFFFFFF to a BAR and then * read it back, for each of the BAR offsets within config space. @@ -817,6 +853,256 @@ static struct pci_ops hv_pcifront_ops = { .write = hv_pcifront_write_config, }; +/* + * Paravirtual backchannel + * + * Hyper-V SR-IOV provides a backchannel mechanism in software for + * communication between a VF driver and a PF driver. These + * "configuration blocks" are similar in concept to PCI configuration space, + * but instead of doing reads and writes in 32-bit chunks through a very slow + * path, packets of up to 128 bytes can be sent or received asynchronously. + * + * Nearly every SR-IOV device contains just such a communications channel in + * hardware, so using this one in software is usually optional. Using the + * software channel, however, allows driver implementers to leverage software + * tools that fuzz the communications channel looking for vulnerabilities. + * + * The usage model for these packets puts the responsibility for reading or + * writing on the VF driver. The VF driver sends a read or a write packet, + * indicating which "block" is being referred to by number. + * + * If the PF driver wishes to initiate communication, it can "invalidate" one or + * more of the first 64 blocks. This invalidation is delivered via a callback + * supplied by the VF driver by this driver. + * + * No protocol is implied, except that supplied by the PF and VF drivers. + */ + +struct hv_read_config_compl { + struct hv_pci_compl comp_pkt; + void *buf; + unsigned int len; + unsigned int bytes_returned; +}; + +/** + * hv_pci_read_config_compl() - Invoked when a response packet + * for a read config block operation arrives. + * @context: Identifies the read config operation + * @resp: The response packet itself + * @resp_packet_size: Size in bytes of the response packet + */ +static void hv_pci_read_config_compl(void *context, struct pci_response *resp, + int resp_packet_size) +{ + struct hv_read_config_compl *comp = context; + struct pci_read_block_response *read_resp = + (struct pci_read_block_response *)resp; + unsigned int data_len, hdr_len; + + hdr_len = offsetof(struct pci_read_block_response, bytes); + if (resp_packet_size < hdr_len) { + comp->comp_pkt.completion_status = -1; + goto out; + } + + data_len = resp_packet_size - hdr_len; + if (data_len > 0 && read_resp->status == 0) { + comp->bytes_returned = min(comp->len, data_len); + memcpy(comp->buf, read_resp->bytes, comp->bytes_returned); + } else { + comp->bytes_returned = 0; + } + + comp->comp_pkt.completion_status = read_resp->status; +out: + complete(&comp->comp_pkt.host_event); +} + +/** + * hv_read_config_block() - Sends a read config block request to + * the back-end driver running in the Hyper-V parent partition. + * @pdev: The PCI driver's representation for this device. + * @buf: Buffer into which the config block will be copied. + * @len: Size in bytes of buf. + * @block_id: Identifies the config block which has been requested. + * @bytes_returned: Size which came back from the back-end driver. + * + * Return: 0 on success, -errno on failure + */ +int hv_read_config_block(struct pci_dev *pdev, void *buf, unsigned int len, + unsigned int block_id, unsigned int *bytes_returned) +{ + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct { + struct pci_packet pkt; + char buf[sizeof(struct pci_read_block)]; + } pkt; + struct hv_read_config_compl comp_pkt; + struct pci_read_block *read_blk; + int ret; + + if (len == 0 || len > HV_CONFIG_BLOCK_SIZE_MAX) + return -EINVAL; + + init_completion(&comp_pkt.comp_pkt.host_event); + comp_pkt.buf = buf; + comp_pkt.len = len; + + memset(&pkt, 0, sizeof(pkt)); + pkt.pkt.completion_func = hv_pci_read_config_compl; + pkt.pkt.compl_ctxt = &comp_pkt; + read_blk = (struct pci_read_block *)&pkt.pkt.message; + read_blk->message_type.type = PCI_READ_BLOCK; + read_blk->wslot.slot = devfn_to_wslot(pdev->devfn); + read_blk->block_id = block_id; + read_blk->bytes_requested = len; + + ret = vmbus_sendpacket(hbus->hdev->channel, read_blk, + sizeof(*read_blk), (unsigned long)&pkt.pkt, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) + return ret; + + ret = wait_for_response(hbus->hdev, &comp_pkt.comp_pkt.host_event); + if (ret) + return ret; + + if (comp_pkt.comp_pkt.completion_status != 0 || + comp_pkt.bytes_returned == 0) { + dev_err(&hbus->hdev->device, + "Read Config Block failed: 0x%x, bytes_returned=%d\n", + comp_pkt.comp_pkt.completion_status, + comp_pkt.bytes_returned); + return -EIO; + } + + *bytes_returned = comp_pkt.bytes_returned; + return 0; +} +EXPORT_SYMBOL(hv_read_config_block); + +/** + * hv_pci_write_config_compl() - Invoked when a response packet for a write + * config block operation arrives. + * @context: Identifies the write config operation + * @resp: The response packet itself + * @resp_packet_size: Size in bytes of the response packet + */ +static void hv_pci_write_config_compl(void *context, struct pci_response *resp, + int resp_packet_size) +{ + struct hv_pci_compl *comp_pkt = context; + + comp_pkt->completion_status = resp->status; + complete(&comp_pkt->host_event); +} + +/** + * hv_write_config_block() - Sends a write config block request to the + * back-end driver running in the Hyper-V parent partition. + * @pdev: The PCI driver's representation for this device. + * @buf: Buffer from which the config block will be copied. + * @len: Size in bytes of buf. + * @block_id: Identifies the config block which is being written. + * + * Return: 0 on success, -errno on failure + */ +int hv_write_config_block(struct pci_dev *pdev, void *buf, unsigned int len, + unsigned int block_id) +{ + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct { + struct pci_packet pkt; + char buf[sizeof(struct pci_write_block)]; + u32 reserved; + } pkt; + struct hv_pci_compl comp_pkt; + struct pci_write_block *write_blk; + u32 pkt_size; + int ret; + + if (len == 0 || len > HV_CONFIG_BLOCK_SIZE_MAX) + return -EINVAL; + + init_completion(&comp_pkt.host_event); + + memset(&pkt, 0, sizeof(pkt)); + pkt.pkt.completion_func = hv_pci_write_config_compl; + pkt.pkt.compl_ctxt = &comp_pkt; + write_blk = (struct pci_write_block *)&pkt.pkt.message; + write_blk->message_type.type = PCI_WRITE_BLOCK; + write_blk->wslot.slot = devfn_to_wslot(pdev->devfn); + write_blk->block_id = block_id; + write_blk->byte_count = len; + memcpy(write_blk->bytes, buf, len); + pkt_size = offsetof(struct pci_write_block, bytes) + len; + /* + * This quirk is required on some hosts shipped around 2018, because + * these hosts don't check the pkt_size correctly (new hosts have been + * fixed since early 2019). The quirk is also safe on very old hosts + * and new hosts, because, on them, what really matters is the length + * specified in write_blk->byte_count. + */ + pkt_size += sizeof(pkt.reserved); + + ret = vmbus_sendpacket(hbus->hdev->channel, write_blk, pkt_size, + (unsigned long)&pkt.pkt, VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) + return ret; + + ret = wait_for_response(hbus->hdev, &comp_pkt.host_event); + if (ret) + return ret; + + if (comp_pkt.completion_status != 0) { + dev_err(&hbus->hdev->device, + "Write Config Block failed: 0x%x\n", + comp_pkt.completion_status); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL(hv_write_config_block); + +/** + * hv_register_block_invalidate() - Invoked when a config block invalidation + * arrives from the back-end driver. + * @pdev: The PCI driver's representation for this device. + * @context: Identifies the device. + * @block_invalidate: Identifies all of the blocks being invalidated. + * + * Return: 0 on success, -errno on failure + */ +int hv_register_block_invalidate(struct pci_dev *pdev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)) +{ + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct hv_pci_dev *hpdev; + + hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(pdev->devfn)); + if (!hpdev) + return -ENODEV; + + hpdev->block_invalidate = block_invalidate; + hpdev->invalidate_context = context; + + put_pcichild(hpdev); + return 0; + +} +EXPORT_SYMBOL(hv_register_block_invalidate); + /* Interrupt management hooks */ static void hv_int_desc_free(struct hv_pci_dev *hpdev, struct tran_int_desc *int_desc) @@ -1968,6 +2254,7 @@ static void hv_pci_onchannelcallback(void *context) struct pci_response *response; struct pci_incoming_message *new_message; struct pci_bus_relations *bus_rel; + struct pci_dev_inval_block *inval; struct pci_dev_incoming *dev_message; struct hv_pci_dev *hpdev; @@ -2045,6 +2332,21 @@ static void hv_pci_onchannelcallback(void *context) } break; + case PCI_INVALIDATE_BLOCK: + + inval = (struct pci_dev_inval_block *)buffer; + hpdev = get_pcichild_wslot(hbus, + inval->wslot.slot); + if (hpdev) { + if (hpdev->block_invalidate) { + hpdev->block_invalidate( + hpdev->invalidate_context, + inval->block_mask); + } + put_pcichild(hpdev); + } + break; + default: dev_warn(&hbus->hdev->device, "Unimplemented protocol message %x\n", diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 6256cc34c4a6..9d37f8cf1245 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1578,4 +1578,19 @@ hv_pkt_iter_next(struct vmbus_channel *channel, for (pkt = hv_pkt_iter_first(channel); pkt; \ pkt = hv_pkt_iter_next(channel, pkt)) +/* + * Functions for passing data between SR-IOV PF and VF drivers. The VF driver + * sends requests to read and write blocks. Each block must be 128 bytes or + * smaller. Optionally, the VF driver can register a callback function which + * will be invoked when the host says that one or more of the first 64 block + * IDs is "invalid" which means that the VF driver should reread them. + */ +#define HV_CONFIG_BLOCK_SIZE_MAX 128 +int hv_read_config_block(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned); +int hv_write_config_block(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id); +int hv_register_block_invalidate(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); #endif /* _HYPERV_H */ -- GitLab From 348dd93e40c112afda3cd07daa6f470e474d29dc Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 22 Aug 2019 05:05:41 +0000 Subject: [PATCH 4027/7155] PCI: hv: Add a Hyper-V PCI interface driver for software backchannel interface This interface driver is a helper driver allows other drivers to have a common interface with the Hyper-V PCI frontend driver. Signed-off-by: Haiyang Zhang Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- MAINTAINERS | 1 + drivers/pci/Kconfig | 1 + drivers/pci/controller/Kconfig | 7 +++ drivers/pci/controller/Makefile | 1 + drivers/pci/controller/pci-hyperv-intf.c | 67 ++++++++++++++++++++++++ drivers/pci/controller/pci-hyperv.c | 12 +++-- include/linux/hyperv.h | 30 ++++++++--- 7 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 drivers/pci/controller/pci-hyperv-intf.c diff --git a/MAINTAINERS b/MAINTAINERS index a406947b369e..986085351d79 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7469,6 +7469,7 @@ F: drivers/hid/hid-hyperv.c F: drivers/hv/ F: drivers/input/serio/hyperv-keyboard.c F: drivers/pci/controller/pci-hyperv.c +F: drivers/pci/controller/pci-hyperv-intf.c F: drivers/net/hyperv/ F: drivers/scsi/storvsc_drv.c F: drivers/uio/uio_hv_generic.c diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 2ab92409210a..c313de96a357 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -182,6 +182,7 @@ config PCI_LABEL config PCI_HYPERV tristate "Hyper-V PCI Frontend" depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 + select PCI_HYPERV_INTERFACE help The PCI device frontend driver allows the kernel to import arbitrary PCI devices from a PCI backend to support PCI driver domains. diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index fe9f9f13ce11..70e078238899 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -281,5 +281,12 @@ config VMD To compile this driver as a module, choose M here: the module will be called vmd. +config PCI_HYPERV_INTERFACE + tristate "Hyper-V PCI Interface" + depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 + help + The Hyper-V PCI Interface is a helper driver allows other drivers to + have a common interface with the Hyper-V PCI frontend driver. + source "drivers/pci/controller/dwc/Kconfig" endmenu diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index d56a507495c5..a2a22c9d91af 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o +obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o diff --git a/drivers/pci/controller/pci-hyperv-intf.c b/drivers/pci/controller/pci-hyperv-intf.c new file mode 100644 index 000000000000..cc96be450360 --- /dev/null +++ b/drivers/pci/controller/pci-hyperv-intf.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Microsoft Corporation. + * + * Author: + * Haiyang Zhang + * + * This small module is a helper driver allows other drivers to + * have a common interface with the Hyper-V PCI frontend driver. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +struct hyperv_pci_block_ops hvpci_block_ops; +EXPORT_SYMBOL_GPL(hvpci_block_ops); + +int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned) +{ + if (!hvpci_block_ops.read_block) + return -EOPNOTSUPP; + + return hvpci_block_ops.read_block(dev, buf, buf_len, block_id, + bytes_returned); +} +EXPORT_SYMBOL_GPL(hyperv_read_cfg_blk); + +int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id) +{ + if (!hvpci_block_ops.write_block) + return -EOPNOTSUPP; + + return hvpci_block_ops.write_block(dev, buf, len, block_id); +} +EXPORT_SYMBOL_GPL(hyperv_write_cfg_blk); + +int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)) +{ + if (!hvpci_block_ops.reg_blk_invalidate) + return -EOPNOTSUPP; + + return hvpci_block_ops.reg_blk_invalidate(dev, context, + block_invalidate); +} +EXPORT_SYMBOL_GPL(hyperv_reg_block_invalidate); + +static void __exit exit_hv_pci_intf(void) +{ +} + +static int __init init_hv_pci_intf(void) +{ + return 0; +} + +module_init(init_hv_pci_intf); +module_exit(exit_hv_pci_intf); + +MODULE_DESCRIPTION("Hyper-V PCI Interface"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 57adeca7bda9..9c93ac2215b7 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -983,7 +983,6 @@ int hv_read_config_block(struct pci_dev *pdev, void *buf, unsigned int len, *bytes_returned = comp_pkt.bytes_returned; return 0; } -EXPORT_SYMBOL(hv_read_config_block); /** * hv_pci_write_config_compl() - Invoked when a response packet for a write @@ -1070,7 +1069,6 @@ int hv_write_config_block(struct pci_dev *pdev, void *buf, unsigned int len, return 0; } -EXPORT_SYMBOL(hv_write_config_block); /** * hv_register_block_invalidate() - Invoked when a config block invalidation @@ -1101,7 +1099,6 @@ int hv_register_block_invalidate(struct pci_dev *pdev, void *context, return 0; } -EXPORT_SYMBOL(hv_register_block_invalidate); /* Interrupt management hooks */ static void hv_int_desc_free(struct hv_pci_dev *hpdev, @@ -3045,10 +3042,19 @@ static struct hv_driver hv_pci_drv = { static void __exit exit_hv_pci_drv(void) { vmbus_driver_unregister(&hv_pci_drv); + + hvpci_block_ops.read_block = NULL; + hvpci_block_ops.write_block = NULL; + hvpci_block_ops.reg_blk_invalidate = NULL; } static int __init init_hv_pci_drv(void) { + /* Initialize PCI block r/w interface */ + hvpci_block_ops.read_block = hv_read_config_block; + hvpci_block_ops.write_block = hv_write_config_block; + hvpci_block_ops.reg_blk_invalidate = hv_register_block_invalidate; + return vmbus_driver_register(&hv_pci_drv); } diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 9d37f8cf1245..2afe6fdc1dda 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1579,18 +1579,32 @@ hv_pkt_iter_next(struct vmbus_channel *channel, pkt = hv_pkt_iter_next(channel, pkt)) /* - * Functions for passing data between SR-IOV PF and VF drivers. The VF driver + * Interface for passing data between SR-IOV PF and VF drivers. The VF driver * sends requests to read and write blocks. Each block must be 128 bytes or * smaller. Optionally, the VF driver can register a callback function which * will be invoked when the host says that one or more of the first 64 block * IDs is "invalid" which means that the VF driver should reread them. */ #define HV_CONFIG_BLOCK_SIZE_MAX 128 -int hv_read_config_block(struct pci_dev *dev, void *buf, unsigned int buf_len, - unsigned int block_id, unsigned int *bytes_returned); -int hv_write_config_block(struct pci_dev *dev, void *buf, unsigned int len, - unsigned int block_id); -int hv_register_block_invalidate(struct pci_dev *dev, void *context, - void (*block_invalidate)(void *context, - u64 block_mask)); + +int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned); +int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id); +int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); + +struct hyperv_pci_block_ops { + int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned); + int (*write_block)(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id); + int (*reg_blk_invalidate)(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); +}; + +extern struct hyperv_pci_block_ops hvpci_block_ops; + #endif /* _HYPERV_H */ -- GitLab From 913d14e866573350de3adede3c90cefb81944b0c Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 22 Aug 2019 05:05:47 +0000 Subject: [PATCH 4028/7155] net/mlx5: Add wrappers for HyperV PCIe operations Add wrapper functions for HyperV PCIe read / write / block_invalidate_register operations. This will be used as an infrastructure in the downstream patch for software communication. This will be enabled by default if CONFIG_PCI_HYPERV_INTERFACE is set. Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/Makefile | 1 + .../net/ethernet/mellanox/mlx5/core/lib/hv.c | 64 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/lib/hv.h | 22 +++++++ 3 files changed, 87 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index bcf36552f069..fd32a5beba72 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -45,6 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o +mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += lib/hv.o # # Ipoib netdev diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c new file mode 100644 index 000000000000..cf08d02703fb --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2018 Mellanox Technologies + +#include +#include "mlx5_core.h" +#include "lib/hv.h" + +static int mlx5_hv_config_common(struct mlx5_core_dev *dev, void *buf, int len, + int offset, bool read) +{ + int rc = -EOPNOTSUPP; + int bytes_returned; + int block_id; + + if (offset % HV_CONFIG_BLOCK_SIZE_MAX || len % HV_CONFIG_BLOCK_SIZE_MAX) + return -EINVAL; + + block_id = offset / HV_CONFIG_BLOCK_SIZE_MAX; + + rc = read ? + hyperv_read_cfg_blk(dev->pdev, buf, + HV_CONFIG_BLOCK_SIZE_MAX, block_id, + &bytes_returned) : + hyperv_write_cfg_blk(dev->pdev, buf, + HV_CONFIG_BLOCK_SIZE_MAX, block_id); + + /* Make sure len bytes were read successfully */ + if (read) + rc |= !(len == bytes_returned); + + if (rc) { + mlx5_core_err(dev, "Failed to %s hv config, err = %d, len = %d, offset = %d\n", + read ? "read" : "write", rc, len, + offset); + return rc; + } + + return 0; +} + +int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len, + int offset) +{ + return mlx5_hv_config_common(dev, buf, len, offset, true); +} + +int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len, + int offset) +{ + return mlx5_hv_config_common(dev, buf, len, offset, false); +} + +int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)) +{ + return hyperv_reg_block_invalidate(dev->pdev, context, + block_invalidate); +} + +void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev) +{ + hyperv_reg_block_invalidate(dev->pdev, NULL, NULL); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h new file mode 100644 index 000000000000..f9a45573f459 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __LIB_HV_H__ +#define __LIB_HV_H__ + +#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) + +#include +#include + +int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len, + int offset); +int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len, + int offset); +int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); +void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev); +#endif + +#endif /* __LIB_HV_H__ */ -- GitLab From 87175120defd2907d42592653c35feea9de0437a Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 22 Aug 2019 05:05:51 +0000 Subject: [PATCH 4029/7155] net/mlx5: Add HV VHCA infrastructure HV VHCA is a layer which provides PF to VF communication channel based on HyperV PCI config channel. It implements Mellanox's Inter VHCA control communication protocol. The protocol contains control block in order to pass messages between the PF and VF drivers, and data blocks in order to pass actual data. The infrastructure is agent based. Each agent will be responsible of contiguous buffer blocks in the VHCA config space. This infrastructure will bind agents to their blocks, and those agents can only access read/write the buffer blocks assigned to them. Each agent will provide three callbacks (control, invalidate, cleanup). Control will be invoked when block-0 is invalidated with a command that concerns this agent. Invalidate callback will be invoked if one of the blocks assigned to this agent was invalidated. Cleanup will be invoked before the agent is being freed in order to clean all of its open resources or deferred works. Block-0 serves as the control block. All execution commands from the PF will be written by the PF over this block. VF will ack on those by writing on block-0 as well. Its format is described by struct mlx5_hv_vhca_control_block layout. Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/Makefile | 2 +- .../ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 253 ++++++++++++++++++ .../ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 102 +++++++ .../net/ethernet/mellanox/mlx5/core/main.c | 7 + include/linux/mlx5/driver.h | 2 + 5 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index fd32a5beba72..8d443fca199e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -45,7 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o -mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += lib/hv.o +mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += lib/hv.o lib/hv_vhca.o # # Ipoib netdev diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c new file mode 100644 index 000000000000..84d1d75a1608 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2018 Mellanox Technologies + +#include +#include "mlx5_core.h" +#include "lib/hv.h" +#include "lib/hv_vhca.h" + +struct mlx5_hv_vhca { + struct mlx5_core_dev *dev; + struct workqueue_struct *work_queue; + struct mlx5_hv_vhca_agent *agents[MLX5_HV_VHCA_AGENT_MAX]; + struct mutex agents_lock; /* Protect agents array */ +}; + +struct mlx5_hv_vhca_work { + struct work_struct invalidate_work; + struct mlx5_hv_vhca *hv_vhca; + u64 block_mask; +}; + +struct mlx5_hv_vhca_data_block { + u16 sequence; + u16 offset; + u8 reserved[4]; + u64 data[15]; +}; + +struct mlx5_hv_vhca_agent { + enum mlx5_hv_vhca_agent_type type; + struct mlx5_hv_vhca *hv_vhca; + void *priv; + u16 seq; + void (*control)(struct mlx5_hv_vhca_agent *agent, + struct mlx5_hv_vhca_control_block *block); + void (*invalidate)(struct mlx5_hv_vhca_agent *agent, + u64 block_mask); + void (*cleanup)(struct mlx5_hv_vhca_agent *agent); +}; + +struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev) +{ + struct mlx5_hv_vhca *hv_vhca = NULL; + + hv_vhca = kzalloc(sizeof(*hv_vhca), GFP_KERNEL); + if (!hv_vhca) + return ERR_PTR(-ENOMEM); + + hv_vhca->work_queue = create_singlethread_workqueue("mlx5_hv_vhca"); + if (!hv_vhca->work_queue) { + kfree(hv_vhca); + return ERR_PTR(-ENOMEM); + } + + hv_vhca->dev = dev; + mutex_init(&hv_vhca->agents_lock); + + return hv_vhca; +} + +void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca) +{ + if (IS_ERR_OR_NULL(hv_vhca)) + return; + + destroy_workqueue(hv_vhca->work_queue); + kfree(hv_vhca); +} + +static void mlx5_hv_vhca_invalidate_work(struct work_struct *work) +{ + struct mlx5_hv_vhca_work *hwork; + struct mlx5_hv_vhca *hv_vhca; + int i; + + hwork = container_of(work, struct mlx5_hv_vhca_work, invalidate_work); + hv_vhca = hwork->hv_vhca; + + mutex_lock(&hv_vhca->agents_lock); + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) { + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i]; + + if (!agent || !agent->invalidate) + continue; + + if (!(BIT(agent->type) & hwork->block_mask)) + continue; + + agent->invalidate(agent, hwork->block_mask); + } + mutex_unlock(&hv_vhca->agents_lock); + + kfree(hwork); +} + +void mlx5_hv_vhca_invalidate(void *context, u64 block_mask) +{ + struct mlx5_hv_vhca *hv_vhca = (struct mlx5_hv_vhca *)context; + struct mlx5_hv_vhca_work *work; + + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return; + + INIT_WORK(&work->invalidate_work, mlx5_hv_vhca_invalidate_work); + work->hv_vhca = hv_vhca; + work->block_mask = block_mask; + + queue_work(hv_vhca->work_queue, &work->invalidate_work); +} + +int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca) +{ + if (IS_ERR_OR_NULL(hv_vhca)) + return IS_ERR_OR_NULL(hv_vhca); + + return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca, + mlx5_hv_vhca_invalidate); +} + +void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca) +{ + int i; + + if (IS_ERR_OR_NULL(hv_vhca)) + return; + + mutex_lock(&hv_vhca->agents_lock); + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) + WARN_ON(hv_vhca->agents[i]); + + mutex_unlock(&hv_vhca->agents_lock); + + mlx5_hv_unregister_invalidate(hv_vhca->dev); +} + +struct mlx5_hv_vhca_agent * +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca, + enum mlx5_hv_vhca_agent_type type, + void (*control)(struct mlx5_hv_vhca_agent*, + struct mlx5_hv_vhca_control_block *block), + void (*invalidate)(struct mlx5_hv_vhca_agent*, + u64 block_mask), + void (*cleaup)(struct mlx5_hv_vhca_agent *agent), + void *priv) +{ + struct mlx5_hv_vhca_agent *agent; + + if (IS_ERR_OR_NULL(hv_vhca)) + return ERR_PTR(-ENOMEM); + + if (type >= MLX5_HV_VHCA_AGENT_MAX) + return ERR_PTR(-EINVAL); + + mutex_lock(&hv_vhca->agents_lock); + if (hv_vhca->agents[type]) { + mutex_unlock(&hv_vhca->agents_lock); + return ERR_PTR(-EINVAL); + } + mutex_unlock(&hv_vhca->agents_lock); + + agent = kzalloc(sizeof(*agent), GFP_KERNEL); + if (!agent) + return ERR_PTR(-ENOMEM); + + agent->type = type; + agent->hv_vhca = hv_vhca; + agent->priv = priv; + agent->control = control; + agent->invalidate = invalidate; + agent->cleanup = cleaup; + + mutex_lock(&hv_vhca->agents_lock); + hv_vhca->agents[type] = agent; + mutex_unlock(&hv_vhca->agents_lock); + + return agent; +} + +void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent) +{ + struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca; + + mutex_lock(&hv_vhca->agents_lock); + + if (WARN_ON(agent != hv_vhca->agents[agent->type])) { + mutex_unlock(&hv_vhca->agents_lock); + return; + } + + hv_vhca->agents[agent->type] = NULL; + mutex_unlock(&hv_vhca->agents_lock); + + if (agent->cleanup) + agent->cleanup(agent); + + kfree(agent); +} + +static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent, + struct mlx5_hv_vhca_data_block *data_block, + void *src, int len, int *offset) +{ + int bytes = min_t(int, (int)sizeof(data_block->data), len); + + data_block->sequence = agent->seq; + data_block->offset = (*offset)++; + memcpy(data_block->data, src, bytes); + + return bytes; +} + +static void mlx5_hv_vhca_agent_seq_update(struct mlx5_hv_vhca_agent *agent) +{ + agent->seq++; +} + +int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent, + void *buf, int len) +{ + int offset = agent->type * HV_CONFIG_BLOCK_SIZE_MAX; + int block_offset = 0; + int total = 0; + int err; + + while (len) { + struct mlx5_hv_vhca_data_block data_block = {0}; + int bytes; + + bytes = mlx5_hv_vhca_data_block_prepare(agent, &data_block, + buf + total, + len, &block_offset); + if (!bytes) + return -ENOMEM; + + err = mlx5_hv_write_config(agent->hv_vhca->dev, &data_block, + sizeof(data_block), offset); + if (err) + return err; + + total += bytes; + len -= bytes; + } + + mlx5_hv_vhca_agent_seq_update(agent); + + return 0; +} + +void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent) +{ + return agent->priv; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h new file mode 100644 index 000000000000..cdf13039489c --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __LIB_HV_VHCA_H__ +#define __LIB_HV_VHCA_H__ + +#include "en.h" +#include "lib/hv.h" + +struct mlx5_hv_vhca_agent; +struct mlx5_hv_vhca; +struct mlx5_hv_vhca_control_block; + +enum mlx5_hv_vhca_agent_type { + MLX5_HV_VHCA_AGENT_MAX = 32, +}; + +#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) + +struct mlx5_hv_vhca_control_block { + u32 capabilities; + u32 control; + u16 command; + u16 command_ack; + u16 version; + u16 rings; + u32 reserved1[28]; +}; + +struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev); +void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca); +int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca); +void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca); +void mlx5_hv_vhca_invalidate(void *context, u64 block_mask); + +struct mlx5_hv_vhca_agent * +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca, + enum mlx5_hv_vhca_agent_type type, + void (*control)(struct mlx5_hv_vhca_agent*, + struct mlx5_hv_vhca_control_block *block), + void (*invalidate)(struct mlx5_hv_vhca_agent*, + u64 block_mask), + void (*cleanup)(struct mlx5_hv_vhca_agent *agent), + void *context); + +void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent); +int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent, + void *buf, int len); +void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent); + +#else + +static inline struct mlx5_hv_vhca * +mlx5_hv_vhca_create(struct mlx5_core_dev *dev) +{ + return NULL; +} + +static inline void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca) +{ +} + +static inline int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca) +{ + return 0; +} + +static inline void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca) +{ +} + +static inline void mlx5_hv_vhca_invalidate(void *context, + u64 block_mask) +{ +} + +static inline struct mlx5_hv_vhca_agent * +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca, + enum mlx5_hv_vhca_agent_type type, + void (*control)(struct mlx5_hv_vhca_agent*, + struct mlx5_hv_vhca_control_block *block), + void (*invalidate)(struct mlx5_hv_vhca_agent*, + u64 block_mask), + void (*cleanup)(struct mlx5_hv_vhca_agent *agent), + void *context) +{ + return NULL; +} + +static inline void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent) +{ +} + +static inline int +mlx5_hv_vhca_write_agent(struct mlx5_hv_vhca_agent *agent, + void *buf, int len) +{ + return 0; +} +#endif + +#endif /* __LIB_HV_VHCA_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 0b70b1d6338d..61388ca7233b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -69,6 +69,7 @@ #include "lib/pci_vsc.h" #include "diag/fw_tracer.h" #include "ecpf.h" +#include "lib/hv_vhca.h" MODULE_AUTHOR("Eli Cohen "); MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver"); @@ -870,6 +871,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) } dev->tracer = mlx5_fw_tracer_create(dev); + dev->hv_vhca = mlx5_hv_vhca_create(dev); return 0; @@ -900,6 +902,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) static void mlx5_cleanup_once(struct mlx5_core_dev *dev) { + mlx5_hv_vhca_destroy(dev->hv_vhca); mlx5_fw_tracer_destroy(dev->tracer); mlx5_fpga_cleanup(dev); mlx5_eswitch_cleanup(dev->priv.eswitch); @@ -1067,6 +1070,8 @@ static int mlx5_load(struct mlx5_core_dev *dev) goto err_fw_tracer; } + mlx5_hv_vhca_init(dev->hv_vhca); + err = mlx5_fpga_device_start(dev); if (err) { mlx5_core_err(dev, "fpga device start failed %d\n", err); @@ -1122,6 +1127,7 @@ static int mlx5_load(struct mlx5_core_dev *dev) err_ipsec_start: mlx5_fpga_device_stop(dev); err_fpga_start: + mlx5_hv_vhca_cleanup(dev->hv_vhca); mlx5_fw_tracer_cleanup(dev->tracer); err_fw_tracer: mlx5_eq_table_destroy(dev); @@ -1142,6 +1148,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev) mlx5_accel_ipsec_cleanup(dev); mlx5_accel_tls_cleanup(dev); mlx5_fpga_device_stop(dev); + mlx5_hv_vhca_cleanup(dev->hv_vhca); mlx5_fw_tracer_cleanup(dev->tracer); mlx5_eq_table_destroy(dev); mlx5_irq_table_destroy(dev); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index df23f17eed64..13b4cf22f3ab 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -659,6 +659,7 @@ struct mlx5_clock { struct mlx5_fw_tracer; struct mlx5_vxlan; struct mlx5_geneve; +struct mlx5_hv_vhca; struct mlx5_core_dev { struct device *device; @@ -706,6 +707,7 @@ struct mlx5_core_dev { struct mlx5_ib_clock_info *clock_info; struct mlx5_fw_tracer *tracer; u32 vsc_addr; + struct mlx5_hv_vhca *hv_vhca; }; struct mlx5_db { -- GitLab From 29ddad43166db232955e686758e6fc23d97e3a6a Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 22 Aug 2019 05:05:56 +0000 Subject: [PATCH 4030/7155] net/mlx5: Add HV VHCA control agent Control agent is responsible over of the control block (ID 0). It should update the PF via this block about every capability change. In addition, upon block 0 invalidate, it should activate all other supported agents with data requests from the PF. Upon agent create/destroy, the invalidate callback of the control agent is being called in order to update the PF driver about this change. The control agent is an integral part of HV VHCA and will be created and destroy as part of the HV VHCA init/cleanup flow. Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 122 +++++++++++++++++- .../ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 1 + 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c index 84d1d75a1608..4047629a876b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c @@ -109,22 +109,131 @@ void mlx5_hv_vhca_invalidate(void *context, u64 block_mask) queue_work(hv_vhca->work_queue, &work->invalidate_work); } +#define AGENT_MASK(type) (type ? BIT(type - 1) : 0 /* control */) + +static void mlx5_hv_vhca_agents_control(struct mlx5_hv_vhca *hv_vhca, + struct mlx5_hv_vhca_control_block *block) +{ + int i; + + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) { + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i]; + + if (!agent || !agent->control) + continue; + + if (!(AGENT_MASK(agent->type) & block->control)) + continue; + + agent->control(agent, block); + } +} + +static void mlx5_hv_vhca_capabilities(struct mlx5_hv_vhca *hv_vhca, + u32 *capabilities) +{ + int i; + + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) { + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i]; + + if (agent) + *capabilities |= AGENT_MASK(agent->type); + } +} + +static void +mlx5_hv_vhca_control_agent_invalidate(struct mlx5_hv_vhca_agent *agent, + u64 block_mask) +{ + struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca; + struct mlx5_core_dev *dev = hv_vhca->dev; + struct mlx5_hv_vhca_control_block *block; + u32 capabilities = 0; + int err; + + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (!block) + return; + + err = mlx5_hv_read_config(dev, block, sizeof(*block), 0); + if (err) + goto free_block; + + mlx5_hv_vhca_capabilities(hv_vhca, &capabilities); + + /* In case no capabilities, send empty block in return */ + if (!capabilities) { + memset(block, 0, sizeof(*block)); + goto write; + } + + if (block->capabilities != capabilities) + block->capabilities = capabilities; + + if (block->control & ~capabilities) + goto free_block; + + mlx5_hv_vhca_agents_control(hv_vhca, block); + block->command_ack = block->command; + +write: + mlx5_hv_write_config(dev, block, sizeof(*block), 0); + +free_block: + kfree(block); +} + +static struct mlx5_hv_vhca_agent * +mlx5_hv_vhca_control_agent_create(struct mlx5_hv_vhca *hv_vhca) +{ + return mlx5_hv_vhca_agent_create(hv_vhca, MLX5_HV_VHCA_AGENT_CONTROL, + NULL, + mlx5_hv_vhca_control_agent_invalidate, + NULL, NULL); +} + +static void mlx5_hv_vhca_control_agent_destroy(struct mlx5_hv_vhca_agent *agent) +{ + mlx5_hv_vhca_agent_destroy(agent); +} + int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca) { + struct mlx5_hv_vhca_agent *agent; + int err; + if (IS_ERR_OR_NULL(hv_vhca)) return IS_ERR_OR_NULL(hv_vhca); - return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca, - mlx5_hv_vhca_invalidate); + err = mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca, + mlx5_hv_vhca_invalidate); + if (err) + return err; + + agent = mlx5_hv_vhca_control_agent_create(hv_vhca); + if (IS_ERR_OR_NULL(agent)) { + mlx5_hv_unregister_invalidate(hv_vhca->dev); + return IS_ERR_OR_NULL(agent); + } + + hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL] = agent; + + return 0; } void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca) { + struct mlx5_hv_vhca_agent *agent; int i; if (IS_ERR_OR_NULL(hv_vhca)) return; + agent = hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL]; + if (agent) + mlx5_hv_vhca_control_agent_destroy(agent); + mutex_lock(&hv_vhca->agents_lock); for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) WARN_ON(hv_vhca->agents[i]); @@ -134,6 +243,11 @@ void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca) mlx5_hv_unregister_invalidate(hv_vhca->dev); } +static void mlx5_hv_vhca_agents_update(struct mlx5_hv_vhca *hv_vhca) +{ + mlx5_hv_vhca_invalidate(hv_vhca, BIT(MLX5_HV_VHCA_AGENT_CONTROL)); +} + struct mlx5_hv_vhca_agent * mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca, enum mlx5_hv_vhca_agent_type type, @@ -174,6 +288,8 @@ mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca, hv_vhca->agents[type] = agent; mutex_unlock(&hv_vhca->agents_lock); + mlx5_hv_vhca_agents_update(hv_vhca); + return agent; } @@ -195,6 +311,8 @@ void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent) agent->cleanup(agent); kfree(agent); + + mlx5_hv_vhca_agents_update(hv_vhca); } static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h index cdf13039489c..984e7ad7cde4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h @@ -12,6 +12,7 @@ struct mlx5_hv_vhca; struct mlx5_hv_vhca_control_block; enum mlx5_hv_vhca_agent_type { + MLX5_HV_VHCA_AGENT_CONTROL = 0, MLX5_HV_VHCA_AGENT_MAX = 32, }; -- GitLab From cef35af34d6dc3792333075115c7deb7062b6e18 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 22 Aug 2019 05:06:00 +0000 Subject: [PATCH 4031/7155] net/mlx5e: Add mlx5e HV VHCA stats agent HV VHCA stats agent is responsible on running a preiodic rx/tx packets/bytes stats update. Currently the supported format is version MLX5_HV_VHCA_STATS_VERSION. Block ID 1 is dedicated for statistics data transfer from the VF to the PF. The reporter fetch the statistics data from all opened channels, fill it in a buffer and send it to mlx5_hv_vhca_write_agent. As the stats layer should include some metadata per block (sequence and offset), the HV VHCA layer shall modify the buffer before actually send it over block 1. Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed Signed-off-by: Haiyang Zhang Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/Makefile | 1 + drivers/net/ethernet/mellanox/mlx5/core/en.h | 13 ++ .../mellanox/mlx5/core/en/hv_vhca_stats.c | 162 ++++++++++++++++++ .../mellanox/mlx5/core/en/hv_vhca_stats.h | 25 +++ .../net/ethernet/mellanox/mlx5/core/en_main.c | 3 + .../ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 1 + 6 files changed, 205 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.h diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 8d443fca199e..f4de9ccb5df1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -36,6 +36,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o \ lib/geneve.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ en/tc_tun_geneve.o diag/en_tc_tracepoint.o +mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o # # Core extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 7316571a4df5..446792799125 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -54,6 +54,7 @@ #include "mlx5_core.h" #include "en_stats.h" #include "en/fs.h" +#include "lib/hv_vhca.h" extern const struct net_device_ops mlx5e_netdev_ops; struct page_pool; @@ -782,6 +783,15 @@ struct mlx5e_modify_sq_param { int rl_index; }; +#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) +struct mlx5e_hv_vhca_stats_agent { + struct mlx5_hv_vhca_agent *agent; + struct delayed_work work; + u16 delay; + void *buf; +}; +#endif + struct mlx5e_xsk { /* UMEMs are stored separately from channels, because we don't want to * lose them when channels are recreated. The kernel also stores UMEMs, @@ -853,6 +863,9 @@ struct mlx5e_priv { struct devlink_health_reporter *tx_reporter; struct devlink_health_reporter *rx_reporter; struct mlx5e_xsk xsk; +#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) + struct mlx5e_hv_vhca_stats_agent stats_agent; +#endif }; struct mlx5e_profile { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c new file mode 100644 index 000000000000..c37b4acd9bd5 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2018 Mellanox Technologies + +#include "en.h" +#include "en/hv_vhca_stats.h" +#include "lib/hv_vhca.h" +#include "lib/hv.h" + +struct mlx5e_hv_vhca_per_ring_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; +}; + +static void +mlx5e_hv_vhca_fill_ring_stats(struct mlx5e_priv *priv, int ch, + struct mlx5e_hv_vhca_per_ring_stats *data) +{ + struct mlx5e_channel_stats *stats; + int tc; + + stats = &priv->channel_stats[ch]; + data->rx_packets = stats->rq.packets; + data->rx_bytes = stats->rq.bytes; + + for (tc = 0; tc < priv->max_opened_tc; tc++) { + data->tx_packets += stats->sq[tc].packets; + data->tx_bytes += stats->sq[tc].bytes; + } +} + +static void mlx5e_hv_vhca_fill_stats(struct mlx5e_priv *priv, u64 *data, + int buf_len) +{ + int ch, i = 0; + + for (ch = 0; ch < priv->max_nch; ch++) { + u64 *buf = data + i; + + if (WARN_ON_ONCE(buf + + sizeof(struct mlx5e_hv_vhca_per_ring_stats) > + data + buf_len)) + return; + + mlx5e_hv_vhca_fill_ring_stats(priv, ch, + (struct mlx5e_hv_vhca_per_ring_stats *)buf); + i += sizeof(struct mlx5e_hv_vhca_per_ring_stats) / sizeof(u64); + } +} + +static int mlx5e_hv_vhca_stats_buf_size(struct mlx5e_priv *priv) +{ + return (sizeof(struct mlx5e_hv_vhca_per_ring_stats) * + priv->max_nch); +} + +static void mlx5e_hv_vhca_stats_work(struct work_struct *work) +{ + struct mlx5e_hv_vhca_stats_agent *sagent; + struct mlx5_hv_vhca_agent *agent; + struct delayed_work *dwork; + struct mlx5e_priv *priv; + int buf_len, rc; + void *buf; + + dwork = to_delayed_work(work); + sagent = container_of(dwork, struct mlx5e_hv_vhca_stats_agent, work); + priv = container_of(sagent, struct mlx5e_priv, stats_agent); + buf_len = mlx5e_hv_vhca_stats_buf_size(priv); + agent = sagent->agent; + buf = sagent->buf; + + memset(buf, 0, buf_len); + mlx5e_hv_vhca_fill_stats(priv, buf, buf_len); + + rc = mlx5_hv_vhca_agent_write(agent, buf, buf_len); + if (rc) { + mlx5_core_err(priv->mdev, + "%s: Failed to write stats, err = %d\n", + __func__, rc); + return; + } + + if (sagent->delay) + queue_delayed_work(priv->wq, &sagent->work, sagent->delay); +} + +enum { + MLX5_HV_VHCA_STATS_VERSION = 1, + MLX5_HV_VHCA_STATS_UPDATE_ONCE = 0xFFFF, +}; + +static void mlx5e_hv_vhca_stats_control(struct mlx5_hv_vhca_agent *agent, + struct mlx5_hv_vhca_control_block *block) +{ + struct mlx5e_hv_vhca_stats_agent *sagent; + struct mlx5e_priv *priv; + + priv = mlx5_hv_vhca_agent_priv(agent); + sagent = &priv->stats_agent; + + block->version = MLX5_HV_VHCA_STATS_VERSION; + block->rings = priv->max_nch; + + if (!block->command) { + cancel_delayed_work_sync(&priv->stats_agent.work); + return; + } + + sagent->delay = block->command == MLX5_HV_VHCA_STATS_UPDATE_ONCE ? 0 : + msecs_to_jiffies(block->command * 100); + + queue_delayed_work(priv->wq, &sagent->work, sagent->delay); +} + +static void mlx5e_hv_vhca_stats_cleanup(struct mlx5_hv_vhca_agent *agent) +{ + struct mlx5e_priv *priv = mlx5_hv_vhca_agent_priv(agent); + + cancel_delayed_work_sync(&priv->stats_agent.work); +} + +int mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv) +{ + int buf_len = mlx5e_hv_vhca_stats_buf_size(priv); + struct mlx5_hv_vhca_agent *agent; + + priv->stats_agent.buf = kvzalloc(buf_len, GFP_KERNEL); + if (!priv->stats_agent.buf) + return -ENOMEM; + + agent = mlx5_hv_vhca_agent_create(priv->mdev->hv_vhca, + MLX5_HV_VHCA_AGENT_STATS, + mlx5e_hv_vhca_stats_control, NULL, + mlx5e_hv_vhca_stats_cleanup, + priv); + + if (IS_ERR_OR_NULL(agent)) { + if (IS_ERR(agent)) + netdev_warn(priv->netdev, + "Failed to create hv vhca stats agent, err = %ld\n", + PTR_ERR(agent)); + + kfree(priv->stats_agent.buf); + return IS_ERR_OR_NULL(agent); + } + + priv->stats_agent.agent = agent; + INIT_DELAYED_WORK(&priv->stats_agent.work, mlx5e_hv_vhca_stats_work); + + return 0; +} + +void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv) +{ + if (IS_ERR_OR_NULL(priv->stats_agent.agent)) + return; + + mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent); + kfree(priv->stats_agent.buf); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.h new file mode 100644 index 000000000000..664463faf77b --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5_EN_STATS_VHCA_H__ +#define __MLX5_EN_STATS_VHCA_H__ +#include "en.h" + +#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) + +int mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv); +void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv); + +#else + +static inline int mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv) +{ + return 0; +} + +static inline void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv) +{ +} +#endif + +#endif /* __MLX5_EN_STATS_VHCA_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 7fdea6479ff6..fa4bf2d4bcd4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -62,6 +62,7 @@ #include "en/xsk/setup.h" #include "en/xsk/rx.h" #include "en/xsk/tx.h" +#include "en/hv_vhca_stats.h" bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) @@ -5109,6 +5110,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) if (mlx5e_monitor_counter_supported(priv)) mlx5e_monitor_counter_init(priv); + mlx5e_hv_vhca_stats_create(priv); if (netdev->reg_state != NETREG_REGISTERED) return; #ifdef CONFIG_MLX5_CORE_EN_DCB @@ -5141,6 +5143,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) queue_work(priv->wq, &priv->set_rx_mode_work); + mlx5e_hv_vhca_stats_destroy(priv); if (mlx5e_monitor_counter_supported(priv)) mlx5e_monitor_counter_cleanup(priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h index 984e7ad7cde4..4bad6a5fde56 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h @@ -13,6 +13,7 @@ struct mlx5_hv_vhca_control_block; enum mlx5_hv_vhca_agent_type { MLX5_HV_VHCA_AGENT_CONTROL = 0, + MLX5_HV_VHCA_AGENT_STATS = 1, MLX5_HV_VHCA_AGENT_MAX = 32, }; -- GitLab From e9a7cc1d97f13f11970f7c484bdfc0502efc4223 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 21 Aug 2019 16:16:32 -0700 Subject: [PATCH 4032/7155] cpufreq: Print driver name if cpufreq_suspend() fails Instead of printing the policy, which is incidentally a kernel pointer, so with limited interest, print the cpufreq driver name that failed to be suspend, which is more useful for debugging. Signed-off-by: Florian Fainelli Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 26d82e0a2de5..5bfda2bfdf4f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1807,8 +1807,8 @@ void cpufreq_suspend(void) } if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy)) - pr_err("%s: Failed to suspend driver: %p\n", __func__, - policy); + pr_err("%s: Failed to suspend driver: %s\n", __func__, + cpufreq_driver->name); } suspend: -- GitLab From 2722b535337b35a9c0be50de687cccda4ab9468d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Aug 2019 09:55:37 +0200 Subject: [PATCH 4033/7155] ALSA: hda/realtek - Check beep whitelist before assigning in all codecs Some Realtek codec parsers didn't check the availability of PC beep. Add has_cdefine_beep() check appropriately. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b6ae452a1d8f..19831521bd95 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2848,7 +2848,8 @@ static int patch_alc268(struct hda_codec *codec) return err; spec = codec->spec; - spec->gen.beep_nid = 0x01; + if (has_cdefine_beep(codec)) + spec->gen.beep_nid = 0x01; spec->shutup = alc_eapd_shutup; @@ -8102,7 +8103,8 @@ static int patch_alc861(struct hda_codec *codec) return err; spec = codec->spec; - spec->gen.beep_nid = 0x23; + if (has_cdefine_beep(codec)) + spec->gen.beep_nid = 0x23; #ifdef CONFIG_PM spec->power_hook = alc_power_eapd; @@ -8203,7 +8205,8 @@ static int patch_alc861vd(struct hda_codec *codec) return err; spec = codec->spec; - spec->gen.beep_nid = 0x23; + if (has_cdefine_beep(codec)) + spec->gen.beep_nid = 0x23; spec->shutup = alc_eapd_shutup; -- GitLab From 051c78af14fcd74a22b5af45548ad9d588247cc7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Aug 2019 09:58:07 +0200 Subject: [PATCH 4034/7155] ALSA: hda/realtek - Blacklist PC beep for Lenovo ThinkCentre M73/93 Lenovo ThinkCentre M73 and M93 don't seem to have a proper beep although the driver tries to probe and set up blindly. Blacklist these machines for suppressing the beep creation. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204635 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 19831521bd95..0585484a469a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1065,6 +1065,9 @@ static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), + /* blacklist -- no beep available */ + SND_PCI_QUIRK(0x17aa, 0x309e, "Lenovo ThinkCentre M73", 0), + SND_PCI_QUIRK(0x17aa, 0x30a3, "Lenovo ThinkCentre M93", 0), {} }; -- GitLab From 4c6903a0f9d76be8a907d8238a5e86c829c8954d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Aug 2019 12:07:34 -0400 Subject: [PATCH 4035/7155] KVM: x86: fix reporting of AMD speculation bug CPUID leaf The AMD_* bits have to be set from the vendor-independent feature and bug flags, because KVM_GET_SUPPORTED_CPUID does not care about the vendor and they should be set on Intel processors as well. On top of this, SSBD, STIBP and AMD_SSB_NO bit were not set, and VIRT_SSBD does not have to be added manually because it is a cpufeature that comes directly from the host's CPUID bit. Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/cpuid.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 22c2720cd948..43caeb6059b9 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -729,18 +729,23 @@ static inline int __do_cpuid_func(struct kvm_cpuid_entry2 *entry, u32 function, g_phys_as = phys_as; entry->eax = g_phys_as | (virt_as << 8); entry->edx = 0; + entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features; + cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX); /* - * IBRS, IBPB and VIRT_SSBD aren't necessarily present in - * hardware cpuid + * AMD has separate bits for each SPEC_CTRL bit. + * arch/x86/kernel/cpu/bugs.c is kind enough to + * record that in cpufeatures so use them. */ - if (boot_cpu_has(X86_FEATURE_AMD_IBPB)) + if (boot_cpu_has(X86_FEATURE_IBPB)) entry->ebx |= F(AMD_IBPB); - if (boot_cpu_has(X86_FEATURE_AMD_IBRS)) + if (boot_cpu_has(X86_FEATURE_IBRS)) entry->ebx |= F(AMD_IBRS); - if (boot_cpu_has(X86_FEATURE_VIRT_SSBD)) - entry->ebx |= F(VIRT_SSBD); - entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features; - cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX); + if (boot_cpu_has(X86_FEATURE_STIBP)) + entry->ebx |= F(AMD_STIBP); + if (boot_cpu_has(X86_FEATURE_SSBD)) + entry->ebx |= F(AMD_SSBD); + if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS)) + entry->ebx |= F(AMD_SSB_NO); /* * The preference is to use SPEC CTRL MSR instead of the * VIRT_SPEC MSR. -- GitLab From 50896de4be7e08fc47f857f6e0c0e9ab2654b941 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 15 Aug 2019 09:17:31 +0200 Subject: [PATCH 4036/7155] KVM: x86: always expose VIRT_SSBD to guests Even though it is preferrable to use SPEC_CTRL (represented by X86_FEATURE_AMD_SSBD) instead of VIRT_SPEC, VIRT_SPEC is always supported anyway because otherwise it would be impossible to migrate from old to new CPUs. Make this apparent in the result of KVM_GET_SUPPORTED_CPUID as well. However, we need to hide the bit on Intel processors, so move the setting to svm_set_supported_cpuid. Cc: Konrad Rzeszutek Wilk Reported-by: Eduardo Habkost Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e3d3b2128f2b..c5120a9519f3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -68,10 +68,8 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id); #define SEG_TYPE_LDT 2 #define SEG_TYPE_BUSY_TSS16 3 -#define SVM_FEATURE_NPT (1 << 0) #define SVM_FEATURE_LBRV (1 << 1) #define SVM_FEATURE_SVML (1 << 2) -#define SVM_FEATURE_NRIP (1 << 3) #define SVM_FEATURE_TSC_RATE (1 << 4) #define SVM_FEATURE_VMCB_CLEAN (1 << 5) #define SVM_FEATURE_FLUSH_ASID (1 << 6) @@ -5933,6 +5931,8 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) guest_cpuid_clear(vcpu, X86_FEATURE_X2APIC); } +#define F(x) bit(X86_FEATURE_##x) + static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) { switch (func) { @@ -5944,6 +5944,11 @@ static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) if (nested) entry->ecx |= (1 << 2); /* Set SVM bit */ break; + case 0x80000008: + if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD) || + boot_cpu_has(X86_FEATURE_AMD_SSBD)) + entry->ebx |= F(VIRT_SSBD); + break; case 0x8000000A: entry->eax = 1; /* SVM revision 1 */ entry->ebx = 8; /* Lets support 8 ASIDs in case we add proper @@ -5954,11 +5959,11 @@ static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) /* Support next_rip if host supports it */ if (boot_cpu_has(X86_FEATURE_NRIPS)) - entry->edx |= SVM_FEATURE_NRIP; + entry->edx |= F(NRIPS); /* Support NPT for the guest if enabled */ if (npt_enabled) - entry->edx |= SVM_FEATURE_NPT; + entry->edx |= F(NPT); break; case 0x8000001F: -- GitLab From 0c54914d0c52a15db9954a76ce80fee32cf318f4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 19 Aug 2019 17:24:07 +0200 Subject: [PATCH 4037/7155] KVM: x86: use Intel speculation bugs and features as derived in generic x86 code Similar to AMD bits, set the Intel bits from the vendor-independent feature and bug flags, because KVM_GET_SUPPORTED_CPUID does not care about the vendor and they should be set on AMD processors as well. Suggested-by: Jim Mattson Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/cpuid.c | 6 ++++++ arch/x86/kvm/x86.c | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 43caeb6059b9..dd5985eb61b4 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -392,6 +392,12 @@ static inline void do_cpuid_7_mask(struct kvm_cpuid_entry2 *entry, int index) entry->edx &= kvm_cpuid_7_0_edx_x86_features; cpuid_mask(&entry->edx, CPUID_7_EDX); + if (boot_cpu_has(X86_FEATURE_IBPB) && boot_cpu_has(X86_FEATURE_IBRS)) + entry->edx |= F(SPEC_CTRL); + if (boot_cpu_has(X86_FEATURE_STIBP)) + entry->edx |= F(INTEL_STIBP); + if (boot_cpu_has(X86_FEATURE_SSBD)) + entry->edx |= F(SPEC_CTRL_SSBD); /* * We emulate ARCH_CAPABILITIES in software even * if the host doesn't support it. diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 93b0bd45ac73..6b81c7609d09 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1254,6 +1254,13 @@ static u64 kvm_get_arch_capabilities(void) if (l1tf_vmx_mitigation != VMENTER_L1D_FLUSH_NEVER) data |= ARCH_CAP_SKIP_VMENTRY_L1DFLUSH; + if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN)) + data |= ARCH_CAP_RDCL_NO; + if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS)) + data |= ARCH_CAP_SSB_NO; + if (!boot_cpu_has_bug(X86_BUG_MDS)) + data |= ARCH_CAP_MDS_NO; + return data; } -- GitLab From 016cd759642c5d313cb36e817362ade13f04ca94 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 15 Aug 2019 09:20:32 -0700 Subject: [PATCH 4038/7155] KVM: x86: Fix x86_decode_insn() return when fetching insn bytes fails Jump to the common error handling in x86_decode_insn() if __do_insn_fetch_bytes() fails so that its error code is converted to the appropriate return type. Although the various helpers used by x86_decode_insn() return X86EMUL_* values, x86_decode_insn() itself returns EMULATION_FAILED or EMULATION_OK. This doesn't cause a functional issue as the sole caller, x86_emulate_instruction(), currently only cares about success vs. failure, and success is indicated by '0' for both types (X86EMUL_CONTINUE and EMULATION_OK). Fixes: 285ca9e948fa ("KVM: emulate: speed up do_insn_fetch") Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 718f7d9afedc..6170ddfdb285 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5144,7 +5144,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) else { rc = __do_insn_fetch_bytes(ctxt, 1); if (rc != X86EMUL_CONTINUE) - return rc; + goto done; } switch (mode) { -- GitLab From 05402f64544f054edbe41f45f6ec52dbe0c1a324 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:29 +0200 Subject: [PATCH 4039/7155] x86: KVM: svm: don't pretend to advance RIP in case wrmsr_interception() results in #GP svm->next_rip is only used by skip_emulated_instruction() and in case kvm_set_msr() fails we rightfully don't do that. Move svm->next_rip advancement to 'else' branch to avoid creating false impression that it's always advanced (and make it look like rdmsr_interception()). This is a preparatory change to removing hardcoded RIP advancement from instruction intercepts, no functional change. Signed-off-by: Vitaly Kuznetsov Reviewed-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c5120a9519f3..18190333bde9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -4444,13 +4444,13 @@ static int wrmsr_interception(struct vcpu_svm *svm) msr.index = ecx; msr.host_initiated = false; - svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; if (kvm_set_msr(&svm->vcpu, &msr)) { trace_kvm_msr_write_ex(ecx, data); kvm_inject_gp(&svm->vcpu, 0); return 1; } else { trace_kvm_msr_write(ecx, data); + svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; return kvm_skip_emulated_instruction(&svm->vcpu); } } -- GitLab From f8ea7c6049d5d0766b84c8107583ed0094773d06 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:30 +0200 Subject: [PATCH 4040/7155] x86: kvm: svm: propagate errors from skip_emulated_instruction() On AMD, kvm_x86_ops->skip_emulated_instruction(vcpu) can, in theory, fail: in !nrips case we call kvm_emulate_instruction(EMULTYPE_SKIP). Currently, we only do printk(KERN_DEBUG) when this happens and this is not ideal. Propagate the error up the stack. On VMX, skip_emulated_instruction() doesn't fail, we have two call sites calling it explicitly: handle_exception_nmi() and handle_task_switch(), we can just ignore the result. On SVM, we also have two explicit call sites: svm_queue_exception() and it seems we don't need to do anything there as we check if RIP was advanced or not. In task_switch_interception(), however, we are better off not proceeding to kvm_task_switch() in case skip_emulated_instruction() failed. Suggested-by: Sean Christopherson Signed-off-by: Vitaly Kuznetsov Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/svm.c | 36 ++++++++++++++++++--------------- arch/x86/kvm/vmx/vmx.c | 16 ++++++++++++--- arch/x86/kvm/x86.c | 6 ++++-- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 74e88e5edd9c..707ae7ff8e1e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1070,7 +1070,7 @@ struct kvm_x86_ops { void (*run)(struct kvm_vcpu *vcpu); int (*handle_exit)(struct kvm_vcpu *vcpu); - void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); + int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask); u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu); void (*patch_hypercall)(struct kvm_vcpu *vcpu, diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 18190333bde9..1ff786d04993 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -768,7 +768,7 @@ static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask) } -static void skip_emulated_instruction(struct kvm_vcpu *vcpu) +static int skip_emulated_instruction(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -777,18 +777,17 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) svm->next_rip = svm->vmcb->control.next_rip; } - if (!svm->next_rip) { - if (kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) != - EMULATE_DONE) - printk(KERN_DEBUG "%s: NOP\n", __func__); - return; - } + if (!svm->next_rip) + return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP); + if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE) printk(KERN_ERR "%s: ip 0x%lx next 0x%llx\n", __func__, kvm_rip_read(vcpu), svm->next_rip); kvm_rip_write(vcpu, svm->next_rip); svm_set_interrupt_shadow(vcpu, 0); + + return EMULATE_DONE; } static void svm_queue_exception(struct kvm_vcpu *vcpu) @@ -819,7 +818,7 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu) * raises a fault that is not intercepted. Still better than * failing in all cases. */ - skip_emulated_instruction(&svm->vcpu); + (void)skip_emulated_instruction(&svm->vcpu); rip = kvm_rip_read(&svm->vcpu); svm->int3_rip = rip + svm->vmcb->save.cs.base; svm->int3_injected = rip - old_rip; @@ -3896,20 +3895,25 @@ static int task_switch_interception(struct vcpu_svm *svm) if (reason != TASK_SWITCH_GATE || int_type == SVM_EXITINTINFO_TYPE_SOFT || (int_type == SVM_EXITINTINFO_TYPE_EXEPT && - (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) - skip_emulated_instruction(&svm->vcpu); + (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) { + if (skip_emulated_instruction(&svm->vcpu) != EMULATE_DONE) + goto fail; + } if (int_type != SVM_EXITINTINFO_TYPE_SOFT) int_vec = -1; if (kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason, - has_error_code, error_code) == EMULATE_FAIL) { - svm->vcpu.run->exit_reason = KVM_EXIT_INTERNAL_ERROR; - svm->vcpu.run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; - svm->vcpu.run->internal.ndata = 0; - return 0; - } + has_error_code, error_code) == EMULATE_FAIL) + goto fail; + return 1; + +fail: + svm->vcpu.run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + svm->vcpu.run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; + svm->vcpu.run->internal.ndata = 0; + return 0; } static int cpuid_interception(struct vcpu_svm *svm) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 42ed3faa6af8..26cf4fe2ff5c 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1472,8 +1472,11 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data) return 0; } - -static void skip_emulated_instruction(struct kvm_vcpu *vcpu) +/* + * Returns an int to be compatible with SVM implementation (which can fail). + * Do not use directly, use skip_emulated_instruction() instead. + */ +static int __skip_emulated_instruction(struct kvm_vcpu *vcpu) { unsigned long rip; @@ -1483,6 +1486,13 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) /* skipping an emulated instruction also counts */ vmx_set_interrupt_shadow(vcpu, 0); + + return EMULATE_DONE; +} + +static inline void skip_emulated_instruction(struct kvm_vcpu *vcpu) +{ + (void)__skip_emulated_instruction(vcpu); } static void vmx_clear_hlt(struct kvm_vcpu *vcpu) @@ -7705,7 +7715,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = { .run = vmx_vcpu_run, .handle_exit = vmx_handle_exit, - .skip_emulated_instruction = skip_emulated_instruction, + .skip_emulated_instruction = __skip_emulated_instruction, .set_interrupt_shadow = vmx_set_interrupt_shadow, .get_interrupt_shadow = vmx_get_interrupt_shadow, .patch_hypercall = vmx_patch_hypercall, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6b81c7609d09..73825abb92b3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6390,9 +6390,11 @@ static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r) int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu) { unsigned long rflags = kvm_x86_ops->get_rflags(vcpu); - int r = EMULATE_DONE; + int r; - kvm_x86_ops->skip_emulated_instruction(vcpu); + r = kvm_x86_ops->skip_emulated_instruction(vcpu); + if (unlikely(r != EMULATE_DONE)) + return 0; /* * rflags is the old, "raw" value of the flags. The new value has -- GitLab From 97413d2981bb3619a9d39f0b611318664d7231f5 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:31 +0200 Subject: [PATCH 4041/7155] x86: KVM: clear interrupt shadow on EMULTYPE_SKIP When doing x86_emulate_instruction(EMULTYPE_SKIP) interrupt shadow has to be cleared if and only if the skipping is successful. There are two immediate issues: - In SVM skip_emulated_instruction() we are not zapping interrupt shadow in case kvm_emulate_instruction(EMULTYPE_SKIP) is used to advance RIP (!nrpip_save). - In VMX handle_ept_misconfig() when running as a nested hypervisor we (static_cpu_has(X86_FEATURE_HYPERVISOR) case) forget to clear interrupt shadow. Note that we intentionally don't handle the case when the skipped instruction is supposed to prolong the interrupt shadow ("MOV/POP SS") as skip-emulation of those instructions should not happen under normal circumstances. Suggested-by: Sean Christopherson Reviewed-by: Sean Christopherson Signed-off-by: Vitaly Kuznetsov Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 73825abb92b3..90a895de5e43 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6546,6 +6546,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, kvm_rip_write(vcpu, ctxt->_eip); if (ctxt->eflags & X86_EFLAGS_RF) kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF); + kvm_x86_ops->set_interrupt_shadow(vcpu, 0); return EMULATE_DONE; } -- GitLab From 02d4160fbd765110e836c84c30c7babb5af84a44 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:32 +0200 Subject: [PATCH 4042/7155] x86: KVM: add xsetbv to the emulator To avoid hardcoding xsetbv length to '3' we need to support decoding it in the emulator. Signed-off-by: Vitaly Kuznetsov Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_emulate.h | 3 ++- arch/x86/kvm/emulate.c | 23 ++++++++++++++++++++++- arch/x86/kvm/svm.c | 1 + arch/x86/kvm/x86.c | 6 ++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index feab24cac610..77cf6c11f66b 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -229,7 +229,7 @@ struct x86_emulate_ops { int (*pre_leave_smm)(struct x86_emulate_ctxt *ctxt, const char *smstate); void (*post_leave_smm)(struct x86_emulate_ctxt *ctxt); - + int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr); }; typedef u32 __attribute__((vector_size(16))) sse128_t; @@ -429,6 +429,7 @@ enum x86_intercept { x86_intercept_ins, x86_intercept_out, x86_intercept_outs, + x86_intercept_xsetbv, nr_x86_intercepts }; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 6170ddfdb285..bef3c3c695d7 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4156,6 +4156,20 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt) return rc; } +static int em_xsetbv(struct x86_emulate_ctxt *ctxt) +{ + u32 eax, ecx, edx; + + eax = reg_read(ctxt, VCPU_REGS_RAX); + edx = reg_read(ctxt, VCPU_REGS_RDX); + ecx = reg_read(ctxt, VCPU_REGS_RCX); + + if (ctxt->ops->set_xcr(ctxt, ecx, ((u64)edx << 32) | eax)) + return emulate_gp(ctxt, 0); + + return X86EMUL_CONTINUE; +} + static bool valid_cr(int nr) { switch (nr) { @@ -4409,6 +4423,12 @@ static const struct opcode group7_rm1[] = { N, N, N, N, N, N, }; +static const struct opcode group7_rm2[] = { + N, + II(ImplicitOps | Priv, em_xsetbv, xsetbv), + N, N, N, N, N, N, +}; + static const struct opcode group7_rm3[] = { DIP(SrcNone | Prot | Priv, vmrun, check_svme_pa), II(SrcNone | Prot | EmulateOnUD, em_hypercall, vmmcall), @@ -4498,7 +4518,8 @@ static const struct group_dual group7 = { { }, { EXT(0, group7_rm0), EXT(0, group7_rm1), - N, EXT(0, group7_rm3), + EXT(0, group7_rm2), + EXT(0, group7_rm3), II(SrcNone | DstMem | Mov, em_smsw, smsw), N, II(SrcMem16 | Mov | Priv, em_lmsw, lmsw), EXT(0, group7_rm7), diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1ff786d04993..6aba0a0202f7 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -6076,6 +6076,7 @@ static const struct __x86_intercept { [x86_intercept_ins] = POST_EX(SVM_EXIT_IOIO), [x86_intercept_out] = POST_EX(SVM_EXIT_IOIO), [x86_intercept_outs] = POST_EX(SVM_EXIT_IOIO), + [x86_intercept_xsetbv] = PRE_EX(SVM_EXIT_XSETBV), }; #undef PRE_EX diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 90a895de5e43..9f46b0456c4b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6075,6 +6075,11 @@ static void emulator_post_leave_smm(struct x86_emulate_ctxt *ctxt) kvm_smm_changed(emul_to_vcpu(ctxt)); } +static int emulator_set_xcr(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr) +{ + return __kvm_set_xcr(emul_to_vcpu(ctxt), index, xcr); +} + static const struct x86_emulate_ops emulate_ops = { .read_gpr = emulator_read_gpr, .write_gpr = emulator_write_gpr, @@ -6116,6 +6121,7 @@ static const struct x86_emulate_ops emulate_ops = { .set_hflags = emulator_set_hflags, .pre_leave_smm = emulator_pre_leave_smm, .post_leave_smm = emulator_post_leave_smm, + .set_xcr = emulator_set_xcr, }; static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask) -- GitLab From c4762fdab55cb1ad715c427f875a549ef257dbb9 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:33 +0200 Subject: [PATCH 4043/7155] x86: KVM: svm: remove hardcoded instruction length from intercepts Various intercepts hard-code the respective instruction lengths to optimize skip_emulated_instruction(): when next_rip is pre-set we skip kvm_emulate_instruction(vcpu, EMULTYPE_SKIP). The optimization is, however, incorrect: different (redundant) prefixes could be used to enlarge the instruction. We can't really avoid decoding. svm->next_rip is not used when CPU supports 'nrips' (X86_FEATURE_NRIPS) feature: next RIP is provided in VMCB. The feature is not really new (Opteron G3s had it already) and the change should have zero affect. Remove manual svm->next_rip setting with hard-coded instruction lengths. The only case where we now use svm->next_rip is EXIT_IOIO: the instruction length is provided to us by hardware. Hardcoded RIP advancement remains in vmrun_interception(), this is going to be taken care of separately. Reported-by: Jim Mattson Reviewed-by: Sean Christopherson Signed-off-by: Vitaly Kuznetsov Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 6aba0a0202f7..db43edc8e99d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2900,13 +2900,11 @@ static int nop_on_interception(struct vcpu_svm *svm) static int halt_interception(struct vcpu_svm *svm) { - svm->next_rip = kvm_rip_read(&svm->vcpu) + 1; return kvm_emulate_halt(&svm->vcpu); } static int vmmcall_interception(struct vcpu_svm *svm) { - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; return kvm_emulate_hypercall(&svm->vcpu); } @@ -3694,7 +3692,6 @@ static int vmload_interception(struct vcpu_svm *svm) nested_vmcb = map.hva; - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; ret = kvm_skip_emulated_instruction(&svm->vcpu); nested_svm_vmloadsave(nested_vmcb, svm->vmcb); @@ -3721,7 +3718,6 @@ static int vmsave_interception(struct vcpu_svm *svm) nested_vmcb = map.hva; - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; ret = kvm_skip_emulated_instruction(&svm->vcpu); nested_svm_vmloadsave(svm->vmcb, nested_vmcb); @@ -3772,7 +3768,6 @@ static int stgi_interception(struct vcpu_svm *svm) if (vgif_enabled(svm)) clr_intercept(svm, INTERCEPT_STGI); - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; ret = kvm_skip_emulated_instruction(&svm->vcpu); kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); @@ -3788,7 +3783,6 @@ static int clgi_interception(struct vcpu_svm *svm) if (nested_svm_check_permissions(svm)) return 1; - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; ret = kvm_skip_emulated_instruction(&svm->vcpu); disable_gif(svm); @@ -3813,7 +3807,6 @@ static int invlpga_interception(struct vcpu_svm *svm) /* Let's treat INVLPGA the same as INVLPG (can be optimized!) */ kvm_mmu_invlpg(vcpu, kvm_rax_read(&svm->vcpu)); - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; return kvm_skip_emulated_instruction(&svm->vcpu); } @@ -3836,7 +3829,6 @@ static int xsetbv_interception(struct vcpu_svm *svm) u32 index = kvm_rcx_read(&svm->vcpu); if (kvm_set_xcr(&svm->vcpu, index, new_bv) == 0) { - svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; return kvm_skip_emulated_instruction(&svm->vcpu); } @@ -3918,7 +3910,6 @@ static int task_switch_interception(struct vcpu_svm *svm) static int cpuid_interception(struct vcpu_svm *svm) { - svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; return kvm_emulate_cpuid(&svm->vcpu); } @@ -4248,7 +4239,6 @@ static int rdmsr_interception(struct vcpu_svm *svm) kvm_rax_write(&svm->vcpu, msr_info.data & 0xffffffff); kvm_rdx_write(&svm->vcpu, msr_info.data >> 32); - svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; return kvm_skip_emulated_instruction(&svm->vcpu); } } @@ -4454,7 +4444,6 @@ static int wrmsr_interception(struct vcpu_svm *svm) return 1; } else { trace_kvm_msr_write(ecx, data); - svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; return kvm_skip_emulated_instruction(&svm->vcpu); } } -- GitLab From e7134c1bb5af1ca6dcbd983e036e67b82e6a2de4 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:34 +0200 Subject: [PATCH 4044/7155] x86: KVM: svm: eliminate weird goto from vmrun_interception() Regardless of whether or not nested_svm_vmrun_msrpm() fails, we return 1 from vmrun_interception() so there's no point in doing goto. Also, nested_svm_vmrun_msrpm() call can be made from nested_svm_vmrun() where other nested launch issues are handled. nested_svm_vmrun() returns a bool, however, its result is ignored in vmrun_interception() as we always return '1'. As a preparatory change to putting kvm_skip_emulated_instruction() inside nested_svm_vmrun() make nested_svm_vmrun() return an int (always '1' for now). Suggested-by: Sean Christopherson Signed-off-by: Vitaly Kuznetsov Reviewed-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index db43edc8e99d..248ea13d6853 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3583,7 +3583,7 @@ static void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, mark_all_dirty(svm->vmcb); } -static bool nested_svm_vmrun(struct vcpu_svm *svm) +static int nested_svm_vmrun(struct vcpu_svm *svm) { int rc; struct vmcb *nested_vmcb; @@ -3598,7 +3598,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) if (rc) { if (rc == -EINVAL) kvm_inject_gp(&svm->vcpu, 0); - return false; + return 1; } nested_vmcb = map.hva; @@ -3611,7 +3611,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) kvm_vcpu_unmap(&svm->vcpu, &map, true); - return false; + return 1; } trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb_gpa, @@ -3655,7 +3655,16 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) enter_svm_guest_mode(svm, vmcb_gpa, nested_vmcb, &map); - return true; + if (!nested_svm_vmrun_msrpm(svm)) { + svm->vmcb->control.exit_code = SVM_EXIT_ERR; + svm->vmcb->control.exit_code_hi = 0; + svm->vmcb->control.exit_info_1 = 0; + svm->vmcb->control.exit_info_2 = 0; + + nested_svm_vmexit(svm); + } + + return 1; } static void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) @@ -3734,24 +3743,7 @@ static int vmrun_interception(struct vcpu_svm *svm) /* Save rip after vmrun instruction */ kvm_rip_write(&svm->vcpu, kvm_rip_read(&svm->vcpu) + 3); - if (!nested_svm_vmrun(svm)) - return 1; - - if (!nested_svm_vmrun_msrpm(svm)) - goto failed; - - return 1; - -failed: - - svm->vmcb->control.exit_code = SVM_EXIT_ERR; - svm->vmcb->control.exit_code_hi = 0; - svm->vmcb->control.exit_info_1 = 0; - svm->vmcb->control.exit_info_2 = 0; - - nested_svm_vmexit(svm); - - return 1; + return nested_svm_vmrun(svm); } static int stgi_interception(struct vcpu_svm *svm) -- GitLab From c8e16b78c6142afea428dc316c900644951cf7f3 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 13 Aug 2019 15:53:35 +0200 Subject: [PATCH 4045/7155] x86: KVM: svm: eliminate hardcoded RIP advancement from vmrun_interception() Just like we do with other intercepts, in vmrun_interception() we should be doing kvm_skip_emulated_instruction() and not just RIP += 3. Also, it is wrong to increment RIP before nested_svm_vmrun() as it can result in kvm_inject_gp(). We can't call kvm_skip_emulated_instruction() after nested_svm_vmrun() so move it inside. Suggested-by: Sean Christopherson Signed-off-by: Vitaly Kuznetsov Reviewed-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 248ea13d6853..6708bb82d8a8 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3585,7 +3585,7 @@ static void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, static int nested_svm_vmrun(struct vcpu_svm *svm) { - int rc; + int ret; struct vmcb *nested_vmcb; struct vmcb *hsave = svm->nested.hsave; struct vmcb *vmcb = svm->vmcb; @@ -3594,13 +3594,16 @@ static int nested_svm_vmrun(struct vcpu_svm *svm) vmcb_gpa = svm->vmcb->save.rax; - rc = kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(vmcb_gpa), &map); - if (rc) { - if (rc == -EINVAL) - kvm_inject_gp(&svm->vcpu, 0); + ret = kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(vmcb_gpa), &map); + if (ret == EINVAL) { + kvm_inject_gp(&svm->vcpu, 0); return 1; + } else if (ret) { + return kvm_skip_emulated_instruction(&svm->vcpu); } + ret = kvm_skip_emulated_instruction(&svm->vcpu); + nested_vmcb = map.hva; if (!nested_vmcb_checks(nested_vmcb)) { @@ -3611,7 +3614,7 @@ static int nested_svm_vmrun(struct vcpu_svm *svm) kvm_vcpu_unmap(&svm->vcpu, &map, true); - return 1; + return ret; } trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb_gpa, @@ -3664,7 +3667,7 @@ static int nested_svm_vmrun(struct vcpu_svm *svm) nested_svm_vmexit(svm); } - return 1; + return ret; } static void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) @@ -3740,9 +3743,6 @@ static int vmrun_interception(struct vcpu_svm *svm) if (nested_svm_check_permissions(svm)) return 1; - /* Save rip after vmrun instruction */ - kvm_rip_write(&svm->vcpu, kvm_rip_read(&svm->vcpu) + 3); - return nested_svm_vmrun(svm); } -- GitLab From 871bd0346018df53055141f09754cb5ffb334c7b Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 1 Aug 2019 13:35:21 -0700 Subject: [PATCH 4046/7155] KVM: x86: Rename access permissions cache member in struct kvm_vcpu_arch Rename "access" to "mmio_access" to match the other MMIO cache members and to make it more obvious that it's tracking the access permissions for the MMIO cache. Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- Documentation/virt/kvm/mmu.txt | 4 ++-- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/x86.c | 2 +- arch/x86/kvm/x86.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/virt/kvm/mmu.txt b/Documentation/virt/kvm/mmu.txt index 1b9880dfba0a..dadb29e8738f 100644 --- a/Documentation/virt/kvm/mmu.txt +++ b/Documentation/virt/kvm/mmu.txt @@ -294,7 +294,7 @@ Handling a page fault is performed as follows: - walk shadow page table - check for valid generation number in the spte (see "Fast invalidation of MMIO sptes" below) - - cache the information to vcpu->arch.mmio_gva, vcpu->arch.access and + - cache the information to vcpu->arch.mmio_gva, vcpu->arch.mmio_access and vcpu->arch.mmio_gfn, and call the emulator - If both P bit and R/W bit of error code are set, this could possibly be handled as a "fast page fault" (fixed without taking the MMU lock). See @@ -304,7 +304,7 @@ Handling a page fault is performed as follows: - if permissions are insufficient, reflect the fault back to the guest - determine the host page - if this is an mmio request, there is no host page; cache the info to - vcpu->arch.mmio_gva, vcpu->arch.access and vcpu->arch.mmio_gfn + vcpu->arch.mmio_gva, vcpu->arch.mmio_access and vcpu->arch.mmio_gfn - walk the shadow page table to find the spte for the translation, instantiating missing intermediate page tables as necessary - If this is an mmio request, cache the mmio info to the spte and set some diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 707ae7ff8e1e..44a5ce57a905 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -717,7 +717,7 @@ struct kvm_vcpu_arch { /* Cache MMIO info */ u64 mmio_gva; - unsigned access; + unsigned mmio_access; gfn_t mmio_gfn; u64 mmio_gen; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9f46b0456c4b..c4aea2adeaea 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5377,7 +5377,7 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva, */ if (vcpu_match_mmio_gva(vcpu, gva) && !permission_fault(vcpu, vcpu->arch.walk_mmu, - vcpu->arch.access, 0, access)) { + vcpu->arch.mmio_access, 0, access)) { *gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT | (gva & (PAGE_SIZE - 1)); trace_vcpu_match_mmio(gva, *gpa, write, false); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 6594020c0691..b5274e2a53cf 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -196,7 +196,7 @@ static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu, * actually a nGPA. */ vcpu->arch.mmio_gva = mmu_is_nested(vcpu) ? 0 : gva & PAGE_MASK; - vcpu->arch.access = access; + vcpu->arch.mmio_access = access; vcpu->arch.mmio_gfn = gfn; vcpu->arch.mmio_gen = gen; } -- GitLab From 4af7715110a2617fc40ac2c1232f664019269f3a Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 1 Aug 2019 13:35:22 -0700 Subject: [PATCH 4047/7155] KVM: x86/mmu: Add explicit access mask for MMIO SPTEs When shadow paging is enabled, KVM tracks the allowed access type for MMIO SPTEs so that it can do a permission check on a MMIO GVA cache hit without having to walk the guest's page tables. The tracking is done by retaining the WRITE and USER bits of the access when inserting the MMIO SPTE (read access is implicitly allowed), which allows the MMIO page fault handler to retrieve and cache the WRITE/USER bits from the SPTE. Unfortunately for EPT, the mask used to retain the WRITE/USER bits is hardcoded using the x86 paging versions of the bits. This funkiness happens to work because KVM uses a completely different mask/value for MMIO SPTEs when EPT is enabled, and the EPT mask/value just happens to overlap exactly with the x86 WRITE/USER bits[*]. Explicitly define the access mask for MMIO SPTEs to accurately reflect that EPT does not want to incorporate any access bits into the SPTE, and so that KVM isn't subtly relying on EPT's WX bits always being set in MMIO SPTEs, e.g. attempting to use other bits for experimentation breaks horribly. Note, vcpu_match_mmio_gva() explicits prevents matching GVA==0, and all TDP flows explicit set mmio_gva to 0, i.e. zeroing vcpu->arch.access for EPT has no (known) functional impact. [*] Using WX to generate EPT misconfigurations (equivalent to reserved bit page fault) ensures KVM can employ its MMIO page fault tricks even platforms without reserved address bits. Fixes: ce88decffd17 ("KVM: MMU: mmio page fault support") Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 15 +++++++++------ arch/x86/kvm/mmu.h | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 218b277bfda3..546afb29389f 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -214,6 +214,7 @@ static u64 __read_mostly shadow_accessed_mask; static u64 __read_mostly shadow_dirty_mask; static u64 __read_mostly shadow_mmio_mask; static u64 __read_mostly shadow_mmio_value; +static u64 __read_mostly shadow_mmio_access_mask; static u64 __read_mostly shadow_present_mask; static u64 __read_mostly shadow_me_mask; @@ -299,11 +300,13 @@ static void kvm_flush_remote_tlbs_with_address(struct kvm *kvm, kvm_flush_remote_tlbs_with_range(kvm, &range); } -void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value) +void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value, u64 access_mask) { + BUG_ON((u64)(unsigned)access_mask != access_mask); BUG_ON((mmio_mask & mmio_value) != mmio_value); shadow_mmio_value = mmio_value | SPTE_SPECIAL_MASK; shadow_mmio_mask = mmio_mask | SPTE_SPECIAL_MASK; + shadow_mmio_access_mask = access_mask; } EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask); @@ -389,7 +392,7 @@ static void mark_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, u64 gfn, u64 mask = generation_mmio_spte_mask(gen); u64 gpa = gfn << PAGE_SHIFT; - access &= ACC_WRITE_MASK | ACC_USER_MASK; + access &= shadow_mmio_access_mask; mask |= shadow_mmio_value | access; mask |= gpa | shadow_nonpresent_or_rsvd_mask; mask |= (gpa & shadow_nonpresent_or_rsvd_mask) @@ -418,8 +421,7 @@ static gfn_t get_mmio_spte_gfn(u64 spte) static unsigned get_mmio_spte_access(u64 spte) { - u64 mask = generation_mmio_spte_mask(MMIO_SPTE_GEN_MASK) | shadow_mmio_mask; - return (spte & ~mask) & ~PAGE_MASK; + return spte & shadow_mmio_access_mask; } static bool set_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, gfn_t gfn, @@ -3290,7 +3292,8 @@ static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, } if (unlikely(is_noslot_pfn(pfn))) - vcpu_cache_mmio_info(vcpu, gva, gfn, access); + vcpu_cache_mmio_info(vcpu, gva, gfn, + access & shadow_mmio_access_mask); return false; } @@ -5997,7 +6000,7 @@ static void kvm_set_mmio_spte_mask(void) if (IS_ENABLED(CONFIG_X86_64) && shadow_phys_bits == 52) mask &= ~1ull; - kvm_mmu_set_mmio_spte_mask(mask, mask); + kvm_mmu_set_mmio_spte_mask(mask, mask, ACC_WRITE_MASK | ACC_USER_MASK); } int kvm_mmu_module_init(void) diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 54c2a377795b..11f8ec89433b 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -51,7 +51,7 @@ static inline u64 rsvd_bits(int s, int e) return ((1ULL << (e - s + 1)) - 1) << s; } -void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value); +void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value, u64 access_mask); void reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 26cf4fe2ff5c..bf70c0292e70 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4036,7 +4036,7 @@ static void ept_set_mmio_spte_mask(void) * of an EPT paging-structure entry is 110b (write/execute). */ kvm_mmu_set_mmio_spte_mask(VMX_EPT_RWX_MASK, - VMX_EPT_MISCONFIG_WX_VALUE); + VMX_EPT_MISCONFIG_WX_VALUE, 0); } #define VMX_XSS_EXIT_BITMAP 0 -- GitLab From 26c44a63a291893e0a00f01e96b6e1d0310a79a9 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 1 Aug 2019 13:35:23 -0700 Subject: [PATCH 4048/7155] KVM: x86/mmu: Consolidate "is MMIO SPTE" code Replace the open-coded "is MMIO SPTE" checks in the MMU warnings related to software-based access/dirty tracking to make the code slightly more self-documenting. No functional change intended. Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 546afb29389f..4c45ff0cfbd0 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -310,6 +310,11 @@ void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value, u64 access_mask) } EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask); +static bool is_mmio_spte(u64 spte) +{ + return (spte & shadow_mmio_mask) == shadow_mmio_value; +} + static inline bool sp_ad_disabled(struct kvm_mmu_page *sp) { return sp->role.ad_disabled; @@ -317,19 +322,19 @@ static inline bool sp_ad_disabled(struct kvm_mmu_page *sp) static inline bool spte_ad_enabled(u64 spte) { - MMU_WARN_ON((spte & shadow_mmio_mask) == shadow_mmio_value); + MMU_WARN_ON(is_mmio_spte(spte)); return !(spte & shadow_acc_track_value); } static inline u64 spte_shadow_accessed_mask(u64 spte) { - MMU_WARN_ON((spte & shadow_mmio_mask) == shadow_mmio_value); + MMU_WARN_ON(is_mmio_spte(spte)); return spte_ad_enabled(spte) ? shadow_accessed_mask : 0; } static inline u64 spte_shadow_dirty_mask(u64 spte) { - MMU_WARN_ON((spte & shadow_mmio_mask) == shadow_mmio_value); + MMU_WARN_ON(is_mmio_spte(spte)); return spte_ad_enabled(spte) ? shadow_dirty_mask : 0; } @@ -404,11 +409,6 @@ static void mark_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, u64 gfn, mmu_spte_set(sptep, mask); } -static bool is_mmio_spte(u64 spte) -{ - return (spte & shadow_mmio_mask) == shadow_mmio_value; -} - static gfn_t get_mmio_spte_gfn(u64 spte) { u64 gpa = spte & shadow_nonpresent_or_rsvd_lower_gfn_mask; -- GitLab From 92735b1b3313c97d24b54492a21083c75206e6ed Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 2 Aug 2019 15:06:17 -0700 Subject: [PATCH 4049/7155] KVM: x86: Unconditionally call x86 ops that are always implemented Remove a few stale checks for non-NULL ops now that the ops in question are implemented by both VMX and SVM. Note, this is **not** stable material, the Fixes tags are there purely to show when a particular op was first supported by both VMX and SVM. Fixes: 74f169090b6f ("kvm/svm: Setup MCG_CAP on AMD properly") Fixes: b31c114b82b2 ("KVM: X86: Provide a capability to disable PAUSE intercepts") Fixes: 411b44ba80ab ("svm: Implements update_pi_irte hook to setup posted interrupt") Cc: Krish Sadhukhan Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c4aea2adeaea..cc1e92da8f3c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3513,8 +3513,7 @@ static int kvm_vcpu_ioctl_x86_setup_mce(struct kvm_vcpu *vcpu, for (bank = 0; bank < bank_num; bank++) vcpu->arch.mce_banks[bank*4] = ~(u64)0; - if (kvm_x86_ops->setup_mce) - kvm_x86_ops->setup_mce(vcpu); + kvm_x86_ops->setup_mce(vcpu); out: return r; } @@ -9330,10 +9329,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm_page_track_init(kvm); kvm_mmu_init_vm(kvm); - if (kvm_x86_ops->vm_init) - return kvm_x86_ops->vm_init(kvm); - - return 0; + return kvm_x86_ops->vm_init(kvm); } static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) @@ -10025,7 +10021,7 @@ EXPORT_SYMBOL_GPL(kvm_arch_has_noncoherent_dma); bool kvm_arch_has_irq_bypass(void) { - return kvm_x86_ops->update_pi_irte != NULL; + return true; } int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons, @@ -10065,9 +10061,6 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons, int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, bool set) { - if (!kvm_x86_ops->update_pi_irte) - return -EINVAL; - return kvm_x86_ops->update_pi_irte(kvm, host_irq, guest_irq, set); } -- GitLab From b382f44e98506bcb00acada0e30151a73e782a93 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Mon, 5 Aug 2019 10:03:24 +0800 Subject: [PATCH 4050/7155] KVM: X86: Add pv tlb shootdown tracepoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add pv tlb shootdown tracepoint. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/trace.h | 19 +++++++++++++++++++ arch/x86/kvm/x86.c | 2 ++ 2 files changed, 21 insertions(+) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index b5c831e79094..6ce853a2e867 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -1462,6 +1462,25 @@ TRACE_EVENT(kvm_hv_send_ipi_ex, __entry->vector, __entry->format, __entry->valid_bank_mask) ); + +TRACE_EVENT(kvm_pv_tlb_flush, + TP_PROTO(unsigned int vcpu_id, bool need_flush_tlb), + TP_ARGS(vcpu_id, need_flush_tlb), + + TP_STRUCT__entry( + __field( unsigned int, vcpu_id ) + __field( bool, need_flush_tlb ) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->need_flush_tlb = need_flush_tlb; + ), + + TP_printk("vcpu %u need_flush_tlb %s", __entry->vcpu_id, + __entry->need_flush_tlb ? "true" : "false") +); + #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cc1e92da8f3c..b4cfd786d0b6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2459,6 +2459,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu) * Doing a TLB flush here, on the guest's behalf, can avoid * expensive IPIs. */ + trace_kvm_pv_tlb_flush(vcpu->vcpu_id, + vcpu->arch.st.steal.preempted & KVM_VCPU_FLUSH_TLB); if (xchg(&vcpu->arch.st.steal.preempted, 0) & KVM_VCPU_FLUSH_TLB) kvm_vcpu_flush_tlb(vcpu, false); -- GitLab From 12b58f4ed2a1b93f0eae84f308f6e0a143a533d4 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 15 Aug 2019 10:22:37 -0700 Subject: [PATCH 4051/7155] KVM: Assert that struct kvm_vcpu is always as offset zero KVM implementations that wrap struct kvm_vcpu with a vendor specific struct, e.g. struct vcpu_vmx, must place the vcpu member at offset 0, otherwise the usercopy region intended to encompass struct kvm_vcpu_arch will instead overlap random chunks of the vendor specific struct. E.g. padding a large number of bytes before struct kvm_vcpu triggers a usercopy warn when running with CONFIG_HARDENED_USERCOPY=y. Signed-off-by: Sean Christopherson Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500.c | 3 +++ arch/x86/kvm/svm.c | 3 +++ arch/x86/kvm/vmx/vmx.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index b5a848a55504..00649ca5fa9a 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c @@ -440,6 +440,9 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_e500(struct kvm *kvm, struct kvm_vcpu *vcpu; int err; + BUILD_BUG_ON_MSG(offsetof(struct kvmppc_vcpu_e500, vcpu) != 0, + "struct kvm_vcpu must be at offset 0 for arch usercopy region"); + vcpu_e500 = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); if (!vcpu_e500) { err = -ENOMEM; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 6708bb82d8a8..1f220a85514f 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2133,6 +2133,9 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) struct page *nested_msrpm_pages; int err; + BUILD_BUG_ON_MSG(offsetof(struct vcpu_svm, vcpu) != 0, + "struct kvm_vcpu must be at offset 0 for arch usercopy region"); + svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL_ACCOUNT); if (!svm) { err = -ENOMEM; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index bf70c0292e70..570a233e272b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6625,6 +6625,9 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) unsigned long *msr_bitmap; int cpu; + BUILD_BUG_ON_MSG(offsetof(struct vcpu_vmx, vcpu) != 0, + "struct kvm_vcpu must be at offset 0 for arch usercopy region"); + vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL_ACCOUNT); if (!vmx) return ERR_PTR(-ENOMEM); -- GitLab From b6852ae75d4be5d3398a4a501443de221151fa9b Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 15 Aug 2019 13:09:31 -0700 Subject: [PATCH 4052/7155] KVM: VMX: Fix and tweak the comments for VM-Enter Fix an incorrect/stale comment regarding the vmx_vcpu pointer, as guest registers are now loaded using a direct pointer to the start of the register array. Opportunistically add a comment to document why the vmx_vcpu pointer is needed, its consumption via 'call vmx_update_host_rsp' is rather subtle. Signed-off-by: Sean Christopherson Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/vmenter.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 4010d519eb8c..751a384c2eb0 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -94,7 +94,7 @@ ENDPROC(vmx_vmexit) /** * __vmx_vcpu_run - Run a vCPU via a transition to VMX guest mode - * @vmx: struct vcpu_vmx * + * @vmx: struct vcpu_vmx * (forwarded to vmx_update_host_rsp) * @regs: unsigned long * (to guest registers) * @launched: %true if the VMCS has been launched * @@ -151,7 +151,7 @@ ENTRY(__vmx_vcpu_run) mov VCPU_R14(%_ASM_AX), %r14 mov VCPU_R15(%_ASM_AX), %r15 #endif - /* Load guest RAX. This kills the vmx_vcpu pointer! */ + /* Load guest RAX. This kills the @regs pointer! */ mov VCPU_RAX(%_ASM_AX), %_ASM_AX /* Enter guest mode */ -- GitLab From 57f8770620e9b51c61089751f0b5ad3dbe376ff2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Aug 2019 17:17:09 +0200 Subject: [PATCH 4053/7155] ALSA: usb-audio: More validations of descriptor units Introduce a new helper to validate each audio descriptor unit before and check the unit before actually accessing it. This should harden against the OOB access cases with malformed descriptors that have been recently frequently reported by fuzzers. The existing descriptor checks are still kept although they become superfluous after this patch. They'll be cleaned up eventually later. Signed-off-by: Takashi Iwai --- sound/usb/Makefile | 3 +- sound/usb/helper.h | 4 + sound/usb/mixer.c | 10 ++ sound/usb/power.c | 2 + sound/usb/quirks.c | 3 + sound/usb/stream.c | 25 ++-- sound/usb/validate.c | 332 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 366 insertions(+), 13 deletions(-) create mode 100644 sound/usb/validate.c diff --git a/sound/usb/Makefile b/sound/usb/Makefile index e1ce257ab705..d27a21b0ff9c 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -16,7 +16,8 @@ snd-usb-audio-objs := card.o \ power.o \ proc.o \ quirks.o \ - stream.o + stream.o \ + validate.o snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o diff --git a/sound/usb/helper.h b/sound/usb/helper.h index 6afb70156ec4..5e8a18b4e7b9 100644 --- a/sound/usb/helper.h +++ b/sound/usb/helper.h @@ -31,4 +31,8 @@ static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip) return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber; } +/* in validate.c */ +bool snd_usb_validate_audio_desc(void *p, int protocol); +bool snd_usb_validate_midi_desc(void *p); + #endif /* __USBAUDIO_HELPER_H */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index eceab19766db..a1093fb9bf09 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -785,6 +785,8 @@ static int __check_input_term(struct mixer_build *state, int id, p1 = find_audio_control_unit(state, id); if (!p1) break; + if (!snd_usb_validate_audio_desc(p1, protocol)) + break; /* bad descriptor */ hdr = p1; term->id = id; @@ -2775,6 +2777,11 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) return -EINVAL; } + if (!snd_usb_validate_audio_desc(p1, protocol)) { + usb_audio_dbg(state->chip, "invalid unit %d\n", unitid); + return 0; /* skip invalid unit */ + } + if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) { switch (p1[2]) { case UAC_INPUT_TERMINAL: @@ -3145,6 +3152,9 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) { + if (!snd_usb_validate_audio_desc(p, mixer->protocol)) + continue; /* skip invalid descriptor */ + if (mixer->protocol == UAC_VERSION_1) { struct uac1_output_terminal_descriptor *desc = p; diff --git a/sound/usb/power.c b/sound/usb/power.c index bd303a1ba1b7..606a2cb23eab 100644 --- a/sound/usb/power.c +++ b/sound/usb/power.c @@ -31,6 +31,8 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface, struct uac3_power_domain_descriptor *pd_desc = p; int i; + if (!snd_usb_validate_audio_desc(p, UAC_VERSION_3)) + continue; for (i = 0; i < pd_desc->bNrEntities; i++) { if (pd_desc->baEntityID[i] == id) { pd->pd_id = pd_desc->bPowerDomainID; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 78858918cbc1..7e9735aa7ac9 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -248,6 +248,9 @@ static int create_yamaha_midi_quirk(struct snd_usb_audio *chip, NULL, USB_MS_MIDI_OUT_JACK); if (!injd && !outjd) return -ENODEV; + if (!snd_usb_validate_midi_desc(injd) || + !snd_usb_validate_midi_desc(outjd)) + return -ENODEV; if (injd && (injd->bLength < 5 || (injd->bJackType != USB_MS_EMBEDDED && injd->bJackType != USB_MS_EXTERNAL))) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index e852c7fd6109..a0649c8ae460 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -627,16 +627,14 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, */ static void * snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id, bool uac23) + int terminal_id, int protocol) { struct uac2_input_terminal_descriptor *term = NULL; - size_t minlen = uac23 ? sizeof(struct uac2_input_terminal_descriptor) : - sizeof(struct uac_input_terminal_descriptor); while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, ctrl_iface->extralen, term, UAC_INPUT_TERMINAL))) { - if (term->bLength < minlen) + if (!snd_usb_validate_audio_desc(term, protocol)) continue; if (term->bTerminalID == terminal_id) return term; @@ -647,7 +645,7 @@ snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, static void * snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) + int terminal_id, int protocol) { /* OK to use with both UAC2 and UAC3 */ struct uac2_output_terminal_descriptor *term = NULL; @@ -655,8 +653,9 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, ctrl_iface->extralen, term, UAC_OUTPUT_TERMINAL))) { - if (term->bLength >= sizeof(*term) && - term->bTerminalID == terminal_id) + if (!snd_usb_validate_audio_desc(term, protocol)) + continue; + if (term->bTerminalID == terminal_id) return term; } @@ -731,7 +730,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, as->bTerminalLink, - false); + protocol); if (iterm) { num_channels = iterm->bNrChannels; chconfig = le16_to_cpu(iterm->wChannelConfig); @@ -767,7 +766,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, */ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, as->bTerminalLink, - true); + protocol); if (input_term) { clock = input_term->bCSourceID; if (!chconfig && (num_channels == input_term->bNrChannels)) @@ -776,7 +775,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, } output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, + protocol); if (output_term) { clock = output_term->bCSourceID; goto found_clock; @@ -1002,14 +1002,15 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, */ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, as->bTerminalLink, - true); + UAC_VERSION_3); if (input_term) { clock = input_term->bCSourceID; goto found_clock; } output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, + UAC_VERSION_3); if (output_term) { clock = output_term->bCSourceID; goto found_clock; diff --git a/sound/usb/validate.c b/sound/usb/validate.c new file mode 100644 index 000000000000..3c8f73a0eb12 --- /dev/null +++ b/sound/usb/validate.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Validation of USB-audio class descriptors +// + +#include +#include +#include +#include +#include +#include +#include "usbaudio.h" +#include "helper.h" + +struct usb_desc_validator { + unsigned char protocol; + unsigned char type; + bool (*func)(const void *p, const struct usb_desc_validator *v); + size_t size; +}; + +#define UAC_VERSION_ALL (unsigned char)(-1) + +/* UAC1 only */ +static bool validate_uac1_header(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac1_ac_header_descriptor *d = p; + + return d->bLength >= sizeof(*d) && + d->bLength >= sizeof(*d) + d->bInCollection; +} + +/* for mixer unit; covering all UACs */ +static bool validate_mixer_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac_mixer_unit_descriptor *d = p; + size_t len; + + if (d->bLength < sizeof(*d) || !d->bNrInPins) + return false; + len = sizeof(*d) + d->bNrInPins; + /* We can't determine the bitmap size only from this unit descriptor, + * so just check with the remaining length. + * The actual bitmap is checked at mixer unit parser. + */ + switch (v->protocol) { + case UAC_VERSION_1: + default: + len += 2 + 1; /* wChannelConfig, iChannelNames */ + /* bmControls[n*m] */ + len += 1; /* iMixer */ + break; + case UAC_VERSION_2: + len += 4 + 1; /* bmChannelConfig, iChannelNames */ + /* bmMixerControls[n*m] */ + len += 1 + 1; /* bmControls, iMixer */ + break; + case UAC_VERSION_3: + len += 2; /* wClusterDescrID */ + /* bmMixerControls[n*m] */ + break; + } + return d->bLength >= len; +} + +/* both for processing and extension units; covering all UACs */ +static bool validate_processing_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac_processing_unit_descriptor *d = p; + const unsigned char *hdr = p; + size_t len, m; + + if (d->bLength < sizeof(*d)) + return false; + len = d->bLength < sizeof(*d) + d->bNrInPins; + if (d->bLength < len) + return false; + switch (v->protocol) { + case UAC_VERSION_1: + default: + /* bNrChannels, wChannelConfig, iChannelNames, bControlSize */ + len += 1 + 2 + 1 + 1; + if (d->bLength < len) /* bControlSize */ + return false; + m = hdr[len]; + len += 1 + m + 1; /* bControlSize, bmControls, iProcessing */ + break; + case UAC_VERSION_2: + /* bNrChannels, bmChannelConfig, iChannelNames */ + len += 1 + 4 + 1; + if (v->type == UAC2_PROCESSING_UNIT_V2) + len += 2; /* bmControls -- 2 bytes for PU */ + else + len += 1; /* bmControls -- 1 byte for EU */ + len += 1; /* iProcessing */ + break; + case UAC_VERSION_3: + /* wProcessingDescrStr, bmControls */ + len += 2 + 4; + break; + } + if (d->bLength < len) + return false; + + switch (v->protocol) { + case UAC_VERSION_1: + default: + if (v->type == UAC1_EXTENSION_UNIT) + return true; /* OK */ + switch (d->wProcessType) { + case UAC_PROCESS_UP_DOWNMIX: + case UAC_PROCESS_DOLBY_PROLOGIC: + if (d->bLength < len + 1) /* bNrModes */ + return false; + m = hdr[len]; + len += 1 + m * 2; /* bNrModes, waModes(n) */ + break; + default: + break; + } + break; + case UAC_VERSION_2: + if (v->type == UAC2_EXTENSION_UNIT_V2) + return true; /* OK */ + switch (d->wProcessType) { + case UAC2_PROCESS_UP_DOWNMIX: + case UAC2_PROCESS_DOLBY_PROLOCIC: /* SiC! */ + if (d->bLength < len + 1) /* bNrModes */ + return false; + m = hdr[len]; + len += 1 + m * 4; /* bNrModes, daModes(n) */ + break; + default: + break; + } + break; + case UAC_VERSION_3: + if (v->type == UAC3_EXTENSION_UNIT) { + len += 2; /* wClusterDescrID */ + break; + } + switch (d->wProcessType) { + case UAC3_PROCESS_UP_DOWNMIX: + if (d->bLength < len + 1) /* bNrModes */ + return false; + m = hdr[len]; + len += 1 + m * 2; /* bNrModes, waClusterDescrID(n) */ + break; + case UAC3_PROCESS_MULTI_FUNCTION: + len += 2 + 4; /* wClusterDescrID, bmAlgorighms */ + break; + default: + break; + } + break; + } + if (d->bLength < len) + return false; + + return true; +} + +/* both for selector and clock selector units; covering all UACs */ +static bool validate_selector_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac_selector_unit_descriptor *d = p; + size_t len; + + if (d->bLength < sizeof(*d)) + return false; + len = sizeof(*d) + d->bNrInPins; + switch (v->protocol) { + case UAC_VERSION_1: + default: + len += 1; /* iSelector */ + break; + case UAC_VERSION_2: + len += 1 + 1; /* bmControls, iSelector */ + break; + case UAC_VERSION_3: + len += 4 + 2; /* bmControls, wSelectorDescrStr */ + break; + } + return d->bLength >= len; +} + +static bool validate_uac1_feature_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac_feature_unit_descriptor *d = p; + + if (d->bLength < sizeof(*d) || !d->bControlSize) + return false; + /* at least bmaControls(0) for master channel + iFeature */ + return d->bLength >= sizeof(*d) + d->bControlSize + 1; +} + +static bool validate_uac2_feature_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac2_feature_unit_descriptor *d = p; + + if (d->bLength < sizeof(*d)) + return false; + /* at least bmaControls(0) for master channel + iFeature */ + return d->bLength >= sizeof(*d) + 4 + 1; +} + +static bool validate_uac3_feature_unit(const void *p, + const struct usb_desc_validator *v) +{ + const struct uac3_feature_unit_descriptor *d = p; + + if (d->bLength < sizeof(*d)) + return false; + /* at least bmaControls(0) for master channel + wFeatureDescrStr */ + return d->bLength >= sizeof(*d) + 4 + 2; +} + +static bool validate_midi_out_jack(const void *p, + const struct usb_desc_validator *v) +{ + const struct usb_midi_out_jack_descriptor *d = p; + + return d->bLength >= sizeof(*d) && + d->bLength >= sizeof(*d) + d->bNrInputPins * 2; +} + +#define FIXED(p, t, s) { .protocol = (p), .type = (t), .size = sizeof(s) } +#define FUNC(p, t, f) { .protocol = (p), .type = (t), .func = (f) } + +static struct usb_desc_validator audio_validators[] = { + /* UAC1 */ + FUNC(UAC_VERSION_1, UAC_HEADER, validate_uac1_header), + FIXED(UAC_VERSION_1, UAC_INPUT_TERMINAL, + struct uac_input_terminal_descriptor), + FIXED(UAC_VERSION_1, UAC_OUTPUT_TERMINAL, + struct uac1_output_terminal_descriptor), + FUNC(UAC_VERSION_1, UAC_MIXER_UNIT, validate_mixer_unit), + FUNC(UAC_VERSION_1, UAC_SELECTOR_UNIT, validate_selector_unit), + FUNC(UAC_VERSION_1, UAC_FEATURE_UNIT, validate_uac1_feature_unit), + FUNC(UAC_VERSION_1, UAC1_PROCESSING_UNIT, validate_processing_unit), + FUNC(UAC_VERSION_1, UAC1_EXTENSION_UNIT, validate_processing_unit), + + /* UAC2 */ + FIXED(UAC_VERSION_2, UAC_HEADER, struct uac2_ac_header_descriptor), + FIXED(UAC_VERSION_2, UAC_INPUT_TERMINAL, + struct uac2_input_terminal_descriptor), + FIXED(UAC_VERSION_2, UAC_OUTPUT_TERMINAL, + struct uac2_output_terminal_descriptor), + FUNC(UAC_VERSION_2, UAC_MIXER_UNIT, validate_mixer_unit), + FUNC(UAC_VERSION_2, UAC_SELECTOR_UNIT, validate_selector_unit), + FUNC(UAC_VERSION_2, UAC_FEATURE_UNIT, validate_uac2_feature_unit), + /* UAC_VERSION_2, UAC2_EFFECT_UNIT: not implemented yet */ + FUNC(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2, validate_processing_unit), + FUNC(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2, validate_processing_unit), + FIXED(UAC_VERSION_2, UAC2_CLOCK_SOURCE, + struct uac_clock_source_descriptor), + FUNC(UAC_VERSION_2, UAC2_CLOCK_SELECTOR, validate_selector_unit), + FIXED(UAC_VERSION_2, UAC2_CLOCK_MULTIPLIER, + struct uac_clock_multiplier_descriptor), + /* UAC_VERSION_2, UAC2_SAMPLE_RATE_CONVERTER: not implemented yet */ + + /* UAC3 */ + FIXED(UAC_VERSION_2, UAC_HEADER, struct uac3_ac_header_descriptor), + FIXED(UAC_VERSION_3, UAC_INPUT_TERMINAL, + struct uac3_input_terminal_descriptor), + FIXED(UAC_VERSION_3, UAC_OUTPUT_TERMINAL, + struct uac3_output_terminal_descriptor), + /* UAC_VERSION_3, UAC3_EXTENDED_TERMINAL: not implemented yet */ + FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), + FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), + FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit), + /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ + FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), + FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit), + FIXED(UAC_VERSION_3, UAC3_CLOCK_SOURCE, + struct uac3_clock_source_descriptor), + FUNC(UAC_VERSION_3, UAC3_CLOCK_SELECTOR, validate_selector_unit), + FIXED(UAC_VERSION_3, UAC3_CLOCK_MULTIPLIER, + struct uac3_clock_multiplier_descriptor), + /* UAC_VERSION_3, UAC3_SAMPLE_RATE_CONVERTER: not implemented yet */ + /* UAC_VERSION_3, UAC3_CONNECTORS: not implemented yet */ + { } /* terminator */ +}; + +static struct usb_desc_validator midi_validators[] = { + FIXED(UAC_VERSION_ALL, USB_MS_HEADER, + struct usb_ms_header_descriptor), + FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_JACK, + struct usb_midi_in_jack_descriptor), + FUNC(UAC_VERSION_ALL, USB_MS_MIDI_OUT_JACK, + validate_midi_out_jack), + { } /* terminator */ +}; + + +/* Validate the given unit descriptor, return true if it's OK */ +static bool validate_desc(unsigned char *hdr, int protocol, + const struct usb_desc_validator *v) +{ + if (hdr[1] != USB_DT_CS_INTERFACE) + return true; /* don't care */ + + for (; v->type; v++) { + if (v->type == hdr[2] && + (v->protocol == UAC_VERSION_ALL || + v->protocol == protocol)) { + if (v->func) + return v->func(hdr, v); + /* check for the fixed size */ + return hdr[0] >= v->size; + } + } + + return true; /* not matching, skip validation */ +} + +bool snd_usb_validate_audio_desc(void *p, int protocol) +{ + return validate_desc(p, protocol, audio_validators); +} + +bool snd_usb_validate_midi_desc(void *p) +{ + return validate_desc(p, UAC_VERSION_1, midi_validators); +} + -- GitLab From 68e9fde245591d18200f8a9054cac22339437adb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Aug 2019 16:30:39 +0200 Subject: [PATCH 4054/7155] ALSA: usb-audio: Simplify parse_audio_unit() Minor code refactoring by combining the UAC version and the type in the switch-case flow, so that we reduce the indentation and redundancy. One good bonus is that the duplicated definition of the same type value (e.g. UAC2_EFFECT_UNIT) can be handled more cleanly. Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 95 +++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 56 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index a1093fb9bf09..34def5911af2 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2782,62 +2782,45 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) return 0; /* skip invalid unit */ } - if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) { - switch (p1[2]) { - case UAC_INPUT_TERMINAL: - return parse_audio_input_terminal(state, unitid, p1); - case UAC_MIXER_UNIT: - return parse_audio_mixer_unit(state, unitid, p1); - case UAC2_CLOCK_SOURCE: - return parse_clock_source_unit(state, unitid, p1); - case UAC_SELECTOR_UNIT: - case UAC2_CLOCK_SELECTOR: - return parse_audio_selector_unit(state, unitid, p1); - case UAC_FEATURE_UNIT: - return parse_audio_feature_unit(state, unitid, p1); - case UAC1_PROCESSING_UNIT: - /* UAC2_EFFECT_UNIT has the same value */ - if (protocol == UAC_VERSION_1) - return parse_audio_processing_unit(state, unitid, p1); - else - return 0; /* FIXME - effect units not implemented yet */ - case UAC1_EXTENSION_UNIT: - /* UAC2_PROCESSING_UNIT_V2 has the same value */ - if (protocol == UAC_VERSION_1) - return parse_audio_extension_unit(state, unitid, p1); - else /* UAC_VERSION_2 */ - return parse_audio_processing_unit(state, unitid, p1); - case UAC2_EXTENSION_UNIT_V2: - return parse_audio_extension_unit(state, unitid, p1); - default: - usb_audio_err(state->chip, - "unit %u: unexpected type 0x%02x\n", unitid, p1[2]); - return -EINVAL; - } - } else { /* UAC_VERSION_3 */ - switch (p1[2]) { - case UAC_INPUT_TERMINAL: - return parse_audio_input_terminal(state, unitid, p1); - case UAC3_MIXER_UNIT: - return parse_audio_mixer_unit(state, unitid, p1); - case UAC3_CLOCK_SOURCE: - return parse_clock_source_unit(state, unitid, p1); - case UAC3_SELECTOR_UNIT: - case UAC3_CLOCK_SELECTOR: - return parse_audio_selector_unit(state, unitid, p1); - case UAC3_FEATURE_UNIT: - return parse_audio_feature_unit(state, unitid, p1); - case UAC3_EFFECT_UNIT: - return 0; /* FIXME - effect units not implemented yet */ - case UAC3_PROCESSING_UNIT: - return parse_audio_processing_unit(state, unitid, p1); - case UAC3_EXTENSION_UNIT: - return parse_audio_extension_unit(state, unitid, p1); - default: - usb_audio_err(state->chip, - "unit %u: unexpected type 0x%02x\n", unitid, p1[2]); - return -EINVAL; - } +#define PTYPE(a, b) ((a) << 8 | (b)) + switch (PTYPE(protocol, p1[2])) { + case PTYPE(UAC_VERSION_1, UAC_INPUT_TERMINAL): + case PTYPE(UAC_VERSION_2, UAC_INPUT_TERMINAL): + case PTYPE(UAC_VERSION_3, UAC_INPUT_TERMINAL): + return parse_audio_input_terminal(state, unitid, p1); + case PTYPE(UAC_VERSION_1, UAC_MIXER_UNIT): + case PTYPE(UAC_VERSION_2, UAC_MIXER_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_MIXER_UNIT): + return parse_audio_mixer_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_2, UAC2_CLOCK_SOURCE): + case PTYPE(UAC_VERSION_3, UAC3_CLOCK_SOURCE): + return parse_clock_source_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_1, UAC_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_2, UAC_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_CLOCK_SELECTOR): + case PTYPE(UAC_VERSION_3, UAC3_CLOCK_SELECTOR): + return parse_audio_selector_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_1, UAC_FEATURE_UNIT): + case PTYPE(UAC_VERSION_2, UAC_FEATURE_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_FEATURE_UNIT): + return parse_audio_feature_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_1, UAC1_PROCESSING_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2): + case PTYPE(UAC_VERSION_3, UAC3_PROCESSING_UNIT): + return parse_audio_processing_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_1, UAC1_EXTENSION_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2): + case PTYPE(UAC_VERSION_3, UAC3_EXTENSION_UNIT): + return parse_audio_extension_unit(state, unitid, p1); + case PTYPE(UAC_VERSION_2, UAC2_EFFECT_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_EFFECT_UNIT): + return 0; /* FIXME - effect units not implemented yet */ + default: + usb_audio_err(state->chip, + "unit %u: unexpected type 0x%02x\n", + unitid, p1[2]); + return -EINVAL; } } -- GitLab From 52c3e317a857091fd746e15179a637f32be4d337 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Aug 2019 08:23:10 +0200 Subject: [PATCH 4055/7155] ALSA: usb-audio: Unify the release of usb_mixer_elem_info objects Instead of the direct kfree() calls, introduce a new local helper to release the usb_mixer_elem_info object. This will be extended to do more than a single kfree() in the later patches. Also, use the standard goto instead of multiple calls in parse_audio_selector_unit() error paths. Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 48 +++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 34def5911af2..277660fd6e0a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1026,10 +1026,15 @@ static struct usb_feature_control_info audio_feature_info[] = { { UAC2_FU_PHASE_INVERTER, "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 }, }; +static void usb_mixer_elem_info_free(struct usb_mixer_elem_info *cval) +{ + kfree(cval); +} + /* private_free callback */ void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl) { - kfree(kctl->private_data); + usb_mixer_elem_info_free(kctl->private_data); kctl->private_data = NULL; } @@ -1552,7 +1557,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, ctl_info = get_feature_control_info(control); if (!ctl_info) { - kfree(cval); + usb_mixer_elem_info_free(cval); return; } if (mixer->protocol == UAC_VERSION_1) @@ -1585,7 +1590,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, if (!kctl) { usb_audio_err(mixer->chip, "cannot malloc kcontrol\n"); - kfree(cval); + usb_mixer_elem_info_free(cval); return; } kctl->private_free = snd_usb_mixer_elem_free; @@ -1755,7 +1760,7 @@ static void build_connector_control(struct usb_mixer_interface *mixer, kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval); if (!kctl) { usb_audio_err(mixer->chip, "cannot malloc kcontrol\n"); - kfree(cval); + usb_mixer_elem_info_free(cval); return; } get_connector_control_name(mixer, term, is_input, kctl->id.name, @@ -1808,7 +1813,7 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid, kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval); if (!kctl) { - kfree(cval); + usb_mixer_elem_info_free(cval); return -ENOMEM; } @@ -2070,7 +2075,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); if (!kctl) { usb_audio_err(state->chip, "cannot malloc kcontrol\n"); - kfree(cval); + usb_mixer_elem_info_free(cval); return; } kctl->private_free = snd_usb_mixer_elem_free; @@ -2468,7 +2473,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); if (!kctl) { - kfree(cval); + usb_mixer_elem_info_free(cval); return -ENOMEM; } kctl->private_free = snd_usb_mixer_elem_free; @@ -2606,7 +2611,7 @@ static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl) if (kctl->private_data) { struct usb_mixer_elem_info *cval = kctl->private_data; num_ins = cval->max; - kfree(cval); + usb_mixer_elem_info_free(cval); kctl->private_data = NULL; } if (kctl->private_value) { @@ -2678,10 +2683,10 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, break; } - namelist = kmalloc_array(desc->bNrInPins, sizeof(char *), GFP_KERNEL); + namelist = kcalloc(desc->bNrInPins, sizeof(char *), GFP_KERNEL); if (!namelist) { - kfree(cval); - return -ENOMEM; + err = -ENOMEM; + goto error_cval; } #define MAX_ITEM_NAME_LEN 64 for (i = 0; i < desc->bNrInPins; i++) { @@ -2689,11 +2694,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, len = 0; namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL); if (!namelist[i]) { - while (i--) - kfree(namelist[i]); - kfree(namelist); - kfree(cval); - return -ENOMEM; + err = -ENOMEM; + goto error_name; } len = check_mapped_selector_name(state, unitid, i, namelist[i], MAX_ITEM_NAME_LEN); @@ -2707,10 +2709,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); if (! kctl) { usb_audio_err(state->chip, "cannot malloc kcontrol\n"); - for (i = 0; i < desc->bNrInPins; i++) - kfree(namelist[i]); - kfree(namelist); - kfree(cval); + err = -ENOMEM; + goto error_name; return -ENOMEM; } kctl->private_value = (unsigned long)namelist; @@ -2757,6 +2757,14 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", cval->head.id, kctl->id.name, desc->bNrInPins); return snd_usb_mixer_add_control(&cval->head, kctl); + + error_name: + for (i = 0; i < desc->bNrInPins; i++) + kfree(namelist[i]); + kfree(namelist); + error_cval: + usb_mixer_elem_info_free(cval); + return err; } /* -- GitLab From b8e4f1fdfa422398c2d6c47bfb7d1feb3046d70a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Aug 2019 09:25:27 +0200 Subject: [PATCH 4056/7155] ALSA: usb-audio: Remove superfluous bLength checks Now that we got the more comprehensive validation code for USB-audio descriptors, the check of overflow in each descriptor unit parser became superfluous. Drop some of the obvious cases. Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 14 ++++---- sound/usb/mixer.c | 84 ----------------------------------------------- 2 files changed, 6 insertions(+), 92 deletions(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 72e9bdf76115..6b8c14f9b5d4 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -38,39 +38,37 @@ static void *find_uac_clock_desc(struct usb_host_interface *iface, int id, static bool validate_clock_source_v2(void *p, int id) { struct uac_clock_source_descriptor *cs = p; - return cs->bLength == sizeof(*cs) && cs->bClockID == id; + return cs->bClockID == id; } static bool validate_clock_source_v3(void *p, int id) { struct uac3_clock_source_descriptor *cs = p; - return cs->bLength == sizeof(*cs) && cs->bClockID == id; + return cs->bClockID == id; } static bool validate_clock_selector_v2(void *p, int id) { struct uac_clock_selector_descriptor *cs = p; - return cs->bLength >= sizeof(*cs) && cs->bClockID == id && - cs->bLength == 7 + cs->bNrInPins; + return cs->bClockID == id; } static bool validate_clock_selector_v3(void *p, int id) { struct uac3_clock_selector_descriptor *cs = p; - return cs->bLength >= sizeof(*cs) && cs->bClockID == id && - cs->bLength == 11 + cs->bNrInPins; + return cs->bClockID == id; } static bool validate_clock_multiplier_v2(void *p, int id) { struct uac_clock_multiplier_descriptor *cs = p; - return cs->bLength == sizeof(*cs) && cs->bClockID == id; + return cs->bClockID == id; } static bool validate_clock_multiplier_v3(void *p, int id) { struct uac3_clock_multiplier_descriptor *cs = p; - return cs->bLength == sizeof(*cs) && cs->bClockID == id; + return cs->bClockID == id; } #define DEFINE_FIND_HELPER(name, obj, validator, type) \ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 277660fd6e0a..c9777d8a76f5 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -740,13 +740,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, { int mu_channels; - if (desc->bLength < sizeof(*desc)) - return -EINVAL; - if (!desc->bNrInPins) - return -EINVAL; - if (desc->bLength < sizeof(*desc) + desc->bNrInPins) - return -EINVAL; - switch (state->mixer->protocol) { case UAC_VERSION_1: case UAC_VERSION_2: @@ -1781,13 +1774,6 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid, if (state->mixer->protocol != UAC_VERSION_2) return -EINVAL; - if (hdr->bLength != sizeof(*hdr)) { - usb_audio_dbg(state->chip, - "Bogus clock source descriptor length of %d, ignoring.\n", - hdr->bLength); - return 0; - } - /* * The only property of this unit we are interested in is the * clock source validity. If that isn't readable, just bail out. @@ -1846,62 +1832,20 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, __u8 *bmaControls; if (state->mixer->protocol == UAC_VERSION_1) { - if (hdr->bLength < 7) { - usb_audio_err(state->chip, - "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } csize = hdr->bControlSize; - if (!csize) { - usb_audio_dbg(state->chip, - "unit %u: invalid bControlSize == 0\n", - unitid); - return -EINVAL; - } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; - if (hdr->bLength < 7 + csize) { - usb_audio_err(state->chip, - "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } } else if (state->mixer->protocol == UAC_VERSION_2) { struct uac2_feature_unit_descriptor *ftr = _ftr; - if (hdr->bLength < 6) { - usb_audio_err(state->chip, - "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } csize = 4; channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; - if (hdr->bLength < 6 + csize) { - usb_audio_err(state->chip, - "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } } else { /* UAC_VERSION_3 */ struct uac3_feature_unit_descriptor *ftr = _ftr; - if (hdr->bLength < 7) { - usb_audio_err(state->chip, - "unit %u: invalid UAC3_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } csize = 4; channels = (ftr->bLength - 7) / 4 - 1; bmaControls = ftr->bmaControls; - if (hdr->bLength < 7 + csize) { - usb_audio_err(state->chip, - "unit %u: invalid UAC3_FEATURE_UNIT descriptor\n", - unitid); - return -EINVAL; - } } /* parse the source unit */ @@ -2101,15 +2045,11 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid, if (state->mixer->protocol == UAC_VERSION_2) { struct uac2_input_terminal_descriptor *d_v2 = raw_desc; - if (d_v2->bLength < sizeof(*d_v2)) - return -EINVAL; control = UAC2_TE_CONNECTOR; term_id = d_v2->bTerminalID; bmctls = le16_to_cpu(d_v2->bmControls); } else if (state->mixer->protocol == UAC_VERSION_3) { struct uac3_input_terminal_descriptor *d_v3 = raw_desc; - if (d_v3->bLength < sizeof(*d_v3)) - return -EINVAL; control = UAC3_TE_INSERTION; term_id = d_v3->bTerminalID; bmctls = le32_to_cpu(d_v3->bmControls); @@ -2371,18 +2311,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, const char *name = extension_unit ? "Extension Unit" : "Processing Unit"; - if (desc->bLength < 13) { - usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); - return -EINVAL; - } - num_ins = desc->bNrInPins; - if (desc->bLength < 13 + num_ins || - desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { - usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); - return -EINVAL; - } - for (i = 0; i < num_ins; i++) { err = parse_audio_unit(state, desc->baSourceID[i]); if (err < 0) @@ -2637,13 +2566,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, const struct usbmix_name_map *map; char **namelist; - if (desc->bLength < 5 || !desc->bNrInPins || - desc->bLength < 5 + desc->bNrInPins) { - usb_audio_err(state->chip, - "invalid SELECTOR UNIT descriptor %d\n", unitid); - return -EINVAL; - } - for (i = 0; i < desc->bNrInPins; i++) { err = parse_audio_unit(state, desc->baSourceID[i]); if (err < 0) @@ -3149,8 +3071,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) if (mixer->protocol == UAC_VERSION_1) { struct uac1_output_terminal_descriptor *desc = p; - if (desc->bLength < sizeof(*desc)) - continue; /* invalid descriptor? */ /* mark terminal ID as visited */ set_bit(desc->bTerminalID, state.unitbitmap); state.oterm.id = desc->bTerminalID; @@ -3162,8 +3082,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) } else if (mixer->protocol == UAC_VERSION_2) { struct uac2_output_terminal_descriptor *desc = p; - if (desc->bLength < sizeof(*desc)) - continue; /* invalid descriptor? */ /* mark terminal ID as visited */ set_bit(desc->bTerminalID, state.unitbitmap); state.oterm.id = desc->bTerminalID; @@ -3189,8 +3107,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) } else { /* UAC_VERSION_3 */ struct uac3_output_terminal_descriptor *desc = p; - if (desc->bLength < sizeof(*desc)) - continue; /* invalid descriptor? */ /* mark terminal ID as visited */ set_bit(desc->bTerminalID, state.unitbitmap); state.oterm.id = desc->bTerminalID; -- GitLab From cc212241df0b8975bb0e6d7f9028405a9c664e49 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 11 Jul 2019 10:14:23 +0800 Subject: [PATCH 4057/7155] arm: dts: mediatek: add basic support for MT7629 SoC This adds basic support for MT7629 reference board. Tested-by: Kevin Hilman Signed-off-by: Ryder Lee Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/mt7629-rfb.dts | 263 ++++++++++++ arch/arm/boot/dts/mt7629.dtsi | 481 ++++++++++++++++++++++ include/dt-bindings/reset/mt7629-resets.h | 71 ++++ 4 files changed, 816 insertions(+) create mode 100644 arch/arm/boot/dts/mt7629-rfb.dts create mode 100644 arch/arm/boot/dts/mt7629.dtsi create mode 100644 include/dt-bindings/reset/mt7629-resets.h diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9159fa2cea90..ff5d6ae7d502 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1262,6 +1262,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt7623a-rfb-nand.dtb \ mt7623n-rfb-emmc.dtb \ mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb \ mt8127-moose.dtb \ mt8135-evbp1.dtb dtb-$(CONFIG_ARCH_MILBEAUT) += milbeaut-m10v-evb.dtb diff --git a/arch/arm/boot/dts/mt7629-rfb.dts b/arch/arm/boot/dts/mt7629-rfb.dts new file mode 100644 index 000000000000..3621b7d2b22a --- /dev/null +++ b/arch/arm/boot/dts/mt7629-rfb.dts @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Ryder Lee + */ + +/dts-v1/; +#include +#include "mt7629.dtsi" + +/ { + model = "MediaTek MT7629 reference board"; + compatible = "mediatek,mt7629-rfb", "mediatek,mt7629"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "factory"; + linux,code = ; + gpios = <&pio 60 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 58 GPIO_ACTIVE_LOW>; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x10000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + pinctrl-1 = <&ephy_leds_pins>; + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy0>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "gmii"; + }; + }; +}; + +&i2c { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&qspi_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x00000 0x60000>; + read-only; + }; + + partition@60000 { + label = "u-boot-env"; + reg = <0x60000 0x10000>; + read-only; + }; + + factory: partition@70000 { + label = "factory"; + reg = <0x70000 0x40000>; + read-only; + }; + + partition@b0000 { + label = "kernel"; + reg = <0xb0000 0xb50000>; + }; + }; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; +}; + +&pciephy1 { + status = "okay"; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio"; + }; + }; + + ephy_leds_pins: ephy-leds-pins { + mux { + function = "led"; + groups = "gphy_leds_0", "ephy_leds"; + }; + }; + + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c_0"; + }; + + conf { + pins = "I2C_SDA", "I2C_SCL"; + drive-strength = <4>; + bias-disable; + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clkreq", + "pcie_pereset", + "pcie_wake"; + }; + }; + + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm_0"; + }; + }; + + /* SPI-NOR is shared pin with serial NAND */ + qspi_pins: qspi-pins { + mux { + function = "flash"; + groups = "spi_nor"; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + spi_pins: spi-pins { + mux { + function = "spi"; + groups = "spi_0"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_txd_rxd" ; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1_0_tx_rx" ; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2_0_txd_rxd" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&spi { + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + status = "okay"; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&u3phy0 { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mt7629.dtsi new file mode 100644 index 000000000000..9608bc2ccb3f --- /dev/null +++ b/arch/arm/boot/dts/mt7629.dtsi @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * + * Author: Ryder Lee + */ + +#include +#include +#include +#include +#include +#include +#include + +/ { + compatible = "mediatek,mt7629"; + interrupt-parent = <&sysirq>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "mediatek,mt6589-smp"; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x0>; + clock-frequency = <1250000000>; + cci-control-port = <&cci_control2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x1>; + clock-frequency = <1250000000>; + cci-control-port = <&cci_control2>; + }; + }; + + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = , + ; + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + + clk20m: oscillator-0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <20000000>; + clock-output-names = "clk20m"; + }; + + clk40m: oscillator-1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <40000000>; + clock-output-names = "clkxtal"; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + clock-frequency = <20000000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + infracfg: syscon@10000000 { + compatible = "mediatek,mt7629-infracfg", "syscon"; + reg = <0x10000000 0x1000>; + #clock-cells = <1>; + }; + + pericfg: syscon@10002000 { + compatible = "mediatek,mt7629-pericfg", "syscon"; + reg = <0x10002000 0x1000>; + #clock-cells = <1>; + }; + + scpsys: scpsys@10006000 { + compatible = "mediatek,mt7629-scpsys", + "mediatek,mt7622-scpsys"; + #power-domain-cells = <1>; + reg = <0x10006000 0x1000>; + clocks = <&topckgen CLK_TOP_HIF_SEL>; + clock-names = "hif_sel"; + assigned-clocks = <&topckgen CLK_TOP_HIF_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>; + infracfg = <&infracfg>; + }; + + timer: timer@10009000 { + compatible = "mediatek,mt7629-timer", + "mediatek,mt6765-timer"; + reg = <0x10009000 0x60>; + interrupts = , + ; + clocks = <&clk20m>; + clock-names = "clk20m"; + }; + + sysirq: interrupt-controller@10200a80 { + compatible = "mediatek,mt7629-sysirq", + "mediatek,mt6577-sysirq"; + reg = <0x10200a80 0x20>; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + }; + + apmixedsys: syscon@10209000 { + compatible = "mediatek,mt7629-apmixedsys", "syscon"; + reg = <0x10209000 0x1000>; + #clock-cells = <1>; + }; + + rng: rng@1020f000 { + compatible = "mediatek,mt7629-rng", + "mediatek,mt7623-rng"; + reg = <0x1020f000 0x100>; + clocks = <&infracfg CLK_INFRA_TRNG_PD>; + clock-names = "rng"; + }; + + topckgen: syscon@10210000 { + compatible = "mediatek,mt7629-topckgen", "syscon"; + reg = <0x10210000 0x1000>; + #clock-cells = <1>; + }; + + watchdog: watchdog@10212000 { + compatible = "mediatek,mt7629-wdt", + "mediatek,mt6589-wdt"; + reg = <0x10212000 0x100>; + }; + + pio: pinctrl@10217000 { + compatible = "mediatek,mt7629-pinctrl"; + reg = <0x10217000 0x8000>, + <0x10005000 0x1000>; + reg-names = "base", "eint"; + gpio-controller; + gpio-ranges = <&pio 0 0 79>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + }; + + gic: interrupt-controller@10300000 { + compatible = "arm,gic-400"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0x10310000 0x1000>, + <0x10320000 0x1000>, + <0x10340000 0x2000>, + <0x10360000 0x2000>; + }; + + cci: cci@10390000 { + compatible = "arm,cci-400"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x10390000 0x1000>; + ranges = <0 0x10390000 0x10000>; + + cci_control0: slave-if@1000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace-lite"; + reg = <0x1000 0x1000>; + }; + + cci_control1: slave-if@4000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x4000 0x1000>; + }; + + cci_control2: slave-if@5000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x5000 0x1000>; + }; + + pmu@9000 { + compatible = "arm,cci-400-pmu,r1"; + reg = <0x9000 0x5000>; + interrupts = , + , + , + , + ; + }; + }; + + uart0: serial@11002000 { + compatible = "mediatek,mt7629-uart", + "mediatek,mt6577-uart"; + reg = <0x11002000 0x400>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART_SEL>, + <&pericfg CLK_PERI_UART0_PD>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + uart1: serial@11003000 { + compatible = "mediatek,mt7629-uart", + "mediatek,mt6577-uart"; + reg = <0x11003000 0x400>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART_SEL>, + <&pericfg CLK_PERI_UART1_PD>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + uart2: serial@11004000 { + compatible = "mediatek,mt7629-uart", + "mediatek,mt6577-uart"; + reg = <0x11004000 0x400>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART_SEL>, + <&pericfg CLK_PERI_UART2_PD>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + i2c: i2c@11007000 { + compatible = "mediatek,mt7629-i2c", + "mediatek,mt2712-i2c"; + reg = <0x11007000 0x90>, + <0x11000100 0x80>; + interrupts = ; + clock-div = <4>; + clocks = <&pericfg CLK_PERI_I2C0_PD>, + <&pericfg CLK_PERI_AP_DMA_PD>; + clock-names = "main", "dma"; + assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi: spi@1100a000 { + compatible = "mediatek,mt7629-spi", + "mediatek,mt7622-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1100a000 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, + <&topckgen CLK_TOP_SPI0_SEL>, + <&pericfg CLK_PERI_SPI0_PD>; + clock-names = "parent-clk", "sel-clk", "spi-clk"; + status = "disabled"; + }; + + qspi: spi@11014000 { + compatible = "mediatek,mt7629-nor", + "mediatek,mt8173-nor"; + reg = <0x11014000 0xe0>; + clocks = <&pericfg CLK_PERI_FLASH_PD>, + <&topckgen CLK_TOP_FLASH_SEL>; + clock-names = "spi", "sf"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ssusbsys: syscon@1a000000 { + compatible = "mediatek,mt7629-ssusbsys", "syscon"; + reg = <0x1a000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + ssusb: usb@1a0c0000 { + compatible = "mediatek,mt7629-xhci", + "mediatek,mtk-xhci"; + reg = <0x1a0c0000 0x01000>, + <0x1a0c3e00 0x0100>; + reg-names = "mac", "ippc"; + interrupts = ; + clocks = <&ssusbsys CLK_SSUSB_SYS_EN>, + <&ssusbsys CLK_SSUSB_REF_EN>, + <&ssusbsys CLK_SSUSB_MCU_EN>, + <&ssusbsys CLK_SSUSB_DMA_EN>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck"; + assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>, + <&topckgen CLK_TOP_SATA_SEL>, + <&topckgen CLK_TOP_HIF_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>, + <&topckgen CLK_TOP_UNIVPLL2_D4>, + <&topckgen CLK_TOP_UNIVPLL1_D2>; + power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + status = "disabled"; + }; + + u3phy0: usb-phy@1a0c4000 { + compatible = "mediatek,generic-tphy-v2"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1a0c4000 0xe00>; + status = "disabled"; + + u2port0: usb-phy@0 { + reg = <0 0x700>; + clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + + u3port0: usb-phy@700 { + reg = <0x700 0x700>; + clocks = <&clk20m>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + }; + + pciesys: syscon@1a100800 { + compatible = "mediatek,mt7629-pciesys", "syscon"; + reg = <0x1a100800 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pcie: pcie@1a140000 { + compatible = "mediatek,mt7629-pcie"; + device_type = "pci"; + reg = <0x1a140000 0x1000>, + <0x1a145000 0x1000>; + reg-names = "subsys","port1"; + #address-cells = <3>; + #size-cells = <2>; + interrupts = , + ; + clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, + <&pciesys CLK_PCIE_P0_AHB_EN>, + <&pciesys CLK_PCIE_P1_AUX_EN>, + <&pciesys CLK_PCIE_P1_AXI_EN>, + <&pciesys CLK_PCIE_P1_OBFF_EN>, + <&pciesys CLK_PCIE_P1_PIPE_EN>; + clock-names = "sys_ck1", "ahb_ck1", + "aux_ck1", "axi_ck1", + "obff_ck1", "pipe_ck1"; + assigned-clocks = <&topckgen CLK_TOP_SATA_SEL>, + <&topckgen CLK_TOP_AXI_SEL>, + <&topckgen CLK_TOP_HIF_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL2_D4>, + <&topckgen CLK_TOP_SYSPLL1_D2>, + <&topckgen CLK_TOP_UNIVPLL1_D2>; + phys = <&pcieport1 PHY_TYPE_PCIE>; + phy-names = "pcie-phy1"; + power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>; + + pcie1: pcie@1,0 { + device_type = "pci"; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + num-lanes = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc1 0>, + <0 0 0 2 &pcie_intc1 1>, + <0 0 0 3 &pcie_intc1 2>, + <0 0 0 4 &pcie_intc1 3>; + + pcie_intc1: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + }; + + pciephy1: pcie-phy@1a14a000 { + compatible = "mediatek,generic-tphy-v2"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1a14a000 0x1000>; + status = "disabled"; + + pcieport1: port1phy@0 { + reg = <0 0x1000>; + clocks = <&clk20m>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + }; + + ethsys: syscon@1b000000 { + compatible = "mediatek,mt7629-ethsys", "syscon"; + reg = <0x1b000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + eth: ethernet@1b100000 { + compatible = "mediatek,mt7629-eth","syscon"; + reg = <0x1b100000 0x20000>; + interrupts = , + , + ; + clocks = <&topckgen CLK_TOP_ETH_SEL>, + <&topckgen CLK_TOP_F10M_REF_SEL>, + <ðsys CLK_ETH_ESW_EN>, + <ðsys CLK_ETH_GP0_EN>, + <ðsys CLK_ETH_GP1_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_FE_EN>, + <&sgmiisys0 CLK_SGMII_TX_EN>, + <&sgmiisys0 CLK_SGMII_RX_EN>, + <&sgmiisys0 CLK_SGMII_CDR_REF>, + <&sgmiisys0 CLK_SGMII_CDR_FB>, + <&sgmiisys1 CLK_SGMII_TX_EN>, + <&sgmiisys1 CLK_SGMII_RX_EN>, + <&sgmiisys1 CLK_SGMII_CDR_REF>, + <&sgmiisys1 CLK_SGMII_CDR_FB>, + <&apmixedsys CLK_APMIXED_SGMIPLL>, + <&apmixedsys CLK_APMIXED_ETH2PLL>; + clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1", + "gp2", "fe", "sgmii_tx250m", "sgmii_rx250m", + "sgmii_cdr_ref", "sgmii_cdr_fb", + "sgmii2_tx250m", "sgmii2_rx250m", + "sgmii2_cdr_ref", "sgmii2_cdr_fb", + "sgmii_ck", "eth2pll"; + assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>, + <&topckgen CLK_TOP_F10M_REF_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>, + <&topckgen CLK_TOP_SGMIIPLL_D2>; + power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; + mediatek,infracfg = <&infracfg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + sgmiisys0: syscon@1b128000 { + compatible = "mediatek,mt7629-sgmiisys", "syscon"; + reg = <0x1b128000 0x3000>; + #clock-cells = <1>; + mediatek,physpeed = "2500"; + }; + + sgmiisys1: syscon@1b130000 { + compatible = "mediatek,mt7629-sgmiisys", "syscon"; + reg = <0x1b130000 0x3000>; + #clock-cells = <1>; + mediatek,physpeed = "2500"; + }; + }; +}; diff --git a/include/dt-bindings/reset/mt7629-resets.h b/include/dt-bindings/reset/mt7629-resets.h new file mode 100644 index 000000000000..6bb85734f68d --- /dev/null +++ b/include/dt-bindings/reset/mt7629-resets.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 MediaTek Inc. + */ + +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7629 +#define _DT_BINDINGS_RESET_CONTROLLER_MT7629 + +/* INFRACFG resets */ +#define MT7629_INFRA_EMI_MPU_RST 0 +#define MT7629_INFRA_UART5_RST 2 +#define MT7629_INFRA_CIRQ_EINT_RST 3 +#define MT7629_INFRA_APXGPT_RST 4 +#define MT7629_INFRA_SCPSYS_RST 5 +#define MT7629_INFRA_KP_RST 6 +#define MT7629_INFRA_SPI1_RST 7 +#define MT7629_INFRA_SPI4_RST 8 +#define MT7629_INFRA_SYSTIMER_RST 9 +#define MT7629_INFRA_IRRX_RST 10 +#define MT7629_INFRA_AO_BUS_RST 16 +#define MT7629_INFRA_EMI_RST 32 +#define MT7629_INFRA_APMIXED_RST 35 +#define MT7629_INFRA_MIPI_RST 36 +#define MT7629_INFRA_TRNG_RST 37 +#define MT7629_INFRA_SYSCIRQ_RST 38 +#define MT7629_INFRA_MIPI_CSI_RST 39 +#define MT7629_INFRA_GCE_FAXI_RST 40 +#define MT7629_INFRA_I2C_SRAM_RST 41 +#define MT7629_INFRA_IOMMU_RST 47 + +/* PERICFG resets */ +#define MT7629_PERI_UART0_SW_RST 0 +#define MT7629_PERI_UART1_SW_RST 1 +#define MT7629_PERI_UART2_SW_RST 2 +#define MT7629_PERI_BTIF_SW_RST 6 +#define MT7629_PERI_PWN_SW_RST 8 +#define MT7629_PERI_DMA_SW_RST 11 +#define MT7629_PERI_NFI_SW_RST 14 +#define MT7629_PERI_I2C0_SW_RST 22 +#define MT7629_PERI_SPI0_SW_RST 33 +#define MT7629_PERI_SPI1_SW_RST 34 +#define MT7629_PERI_FLASHIF_SW_RST 36 + +/* PCIe Subsystem resets */ +#define MT7629_PCIE1_CORE_RST 19 +#define MT7629_PCIE1_MMIO_RST 20 +#define MT7629_PCIE1_HRST 21 +#define MT7629_PCIE1_USER_RST 22 +#define MT7629_PCIE1_PIPE_RST 23 +#define MT7629_PCIE0_CORE_RST 27 +#define MT7629_PCIE0_MMIO_RST 28 +#define MT7629_PCIE0_HRST 29 +#define MT7629_PCIE0_USER_RST 30 +#define MT7629_PCIE0_PIPE_RST 31 + +/* SSUSB Subsystem resets */ +#define MT7629_SSUSB_PHY_PWR_RST 3 +#define MT7629_SSUSB_MAC_PWR_RST 4 + +/* ETH Subsystem resets */ +#define MT7629_ETHSYS_SYS_RST 0 +#define MT7629_ETHSYS_MCM_RST 2 +#define MT7629_ETHSYS_HSDMA_RST 5 +#define MT7629_ETHSYS_FE_RST 6 +#define MT7629_ETHSYS_ESW_RST 16 +#define MT7629_ETHSYS_GMAC_RST 23 +#define MT7629_ETHSYS_EPHY_RST 24 +#define MT7629_ETHSYS_CRYPTO_RST 29 +#define MT7629_ETHSYS_PPE_RST 31 + +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7629 */ -- GitLab From cac33c104a1007fb679011807c57553ac1288efe Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Thu, 22 Aug 2019 16:55:40 +0800 Subject: [PATCH 4058/7155] arm64: dts: mt8183: fix pwrap gic number The correct gic number of pwrap is 185 instead of 209. This patch fixes it to avoid triggering error interrupt. Fixes: e526c9bc11f8 ("arm64: dts: Add Mediatek SoC MT8183 and evaluation board dts and Makefile") Signed-off-by: Hsin-Hsiung Wang Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index c2749c4631bc..afb0996d46a3 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -248,7 +248,7 @@ compatible = "mediatek,mt8183-pwrap"; reg = <0 0x1000d000 0 0x1000>; reg-names = "pwrap"; - interrupts = ; + interrupts = ; clocks = <&topckgen CLK_TOP_MUX_PMICSPI>, <&infracfg CLK_INFRA_PMIC_AP>; clock-names = "spi", "wrap"; -- GitLab From e1b832503e8f29ea6e20c30db9c3176576c0fc78 Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 21 Aug 2019 17:47:29 +0100 Subject: [PATCH 4059/7155] arm64: Define Documentation/arm64/tagged-address-abi.rst On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace (EL0) to perform memory accesses through 64-bit pointers with a non-zero top byte. Introduce the document describing the relaxation of the syscall ABI that allows userspace to pass certain tagged pointers to kernel syscalls. Cc: Will Deacon Cc: Szabolcs Nagy Acked-by: Kevin Brodsky Acked-by: Andrey Konovalov Signed-off-by: Vincenzo Frascino Co-developed-by: Catalin Marinas Signed-off-by: Catalin Marinas Signed-off-by: Will Deacon --- Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 Documentation/arm64/tagged-address-abi.rst diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst new file mode 100644 index 000000000000..d4a85d535bf9 --- /dev/null +++ b/Documentation/arm64/tagged-address-abi.rst @@ -0,0 +1,156 @@ +========================== +AArch64 TAGGED ADDRESS ABI +========================== + +Authors: Vincenzo Frascino + Catalin Marinas + +Date: 21 August 2019 + +This document describes the usage and semantics of the Tagged Address +ABI on AArch64 Linux. + +1. Introduction +--------------- + +On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing +userspace (EL0) to perform memory accesses through 64-bit pointers with +a non-zero top byte. This document describes the relaxation of the +syscall ABI that allows userspace to pass certain tagged pointers to +kernel syscalls. + +2. AArch64 Tagged Address ABI +----------------------------- + +From the kernel syscall interface perspective and for the purposes of +this document, a "valid tagged pointer" is a pointer with a potentially +non-zero top-byte that references an address in the user process address +space obtained in one of the following ways: + +- ``mmap()`` syscall where either: + + - flags have the ``MAP_ANONYMOUS`` bit set or + - the file descriptor refers to a regular file (including those + returned by ``memfd_create()``) or ``/dev/zero`` + +- ``brk()`` syscall (i.e. the heap area between the initial location of + the program break at process creation and its current location). + +- any memory mapped by the kernel in the address space of the process + during creation and with the same restrictions as for ``mmap()`` above + (e.g. data, bss, stack). + +The AArch64 Tagged Address ABI has two stages of relaxation depending +how the user addresses are used by the kernel: + +1. User addresses not accessed by the kernel but used for address space + management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use + of valid tagged pointers in this context is always allowed. + +2. User addresses accessed by the kernel (e.g. ``write()``). This ABI + relaxation is disabled by default and the application thread needs to + explicitly enable it via ``prctl()`` as follows: + + - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged + Address ABI for the calling thread. + + The ``(unsigned int) arg2`` argument is a bit mask describing the + control mode used: + + - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI. + Default status is disabled. + + Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0. + + - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged + Address ABI for the calling thread. + + Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0. + + The ABI properties described above are thread-scoped, inherited on + clone() and fork() and cleared on exec(). + + Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)`` + returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally + disabled by ``sysctl abi.tagged_addr_disabled=1``. The default + ``sysctl abi.tagged_addr_disabled`` configuration is 0. + +When the AArch64 Tagged Address ABI is enabled for a thread, the +following behaviours are guaranteed: + +- All syscalls except the cases mentioned in section 3 can accept any + valid tagged pointer. + +- The syscall behaviour is undefined for invalid tagged pointers: it may + result in an error code being returned, a (fatal) signal being raised, + or other modes of failure. + +- The syscall behaviour for a valid tagged pointer is the same as for + the corresponding untagged pointer. + + +A definition of the meaning of tagged pointers on AArch64 can be found +in Documentation/arm64/tagged-pointers.rst. + +3. AArch64 Tagged Address ABI Exceptions +----------------------------------------- + +The following system call parameters must be untagged regardless of the +ABI relaxation: + +- ``prctl()`` other than pointers to user data either passed directly or + indirectly as arguments to be accessed by the kernel. + +- ``ioctl()`` other than pointers to user data either passed directly or + indirectly as arguments to be accessed by the kernel. + +- ``shmat()`` and ``shmdt()``. + +Any attempt to use non-zero tagged pointers may result in an error code +being returned, a (fatal) signal being raised, or other modes of +failure. + +4. Example of correct usage +--------------------------- +.. code-block:: c + + #include + #include + #include + #include + #include + + #define PR_SET_TAGGED_ADDR_CTRL 55 + #define PR_TAGGED_ADDR_ENABLE (1UL << 0) + + #define TAG_SHIFT 56 + + int main(void) + { + int tbi_enabled = 0; + unsigned long tag = 0; + char *ptr; + + /* check/enable the tagged address ABI */ + if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)) + tbi_enabled = 1; + + /* memory allocation */ + ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ptr == MAP_FAILED) + return 1; + + /* set a non-zero tag if the ABI is available */ + if (tbi_enabled) + tag = rand() & 0xff; + ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT)); + + /* memory access to a tagged address */ + strcpy(ptr, "tagged pointer\n"); + + /* syscall with a tagged pointer */ + write(1, ptr, strlen(ptr)); + + return 0; + } -- GitLab From 5a74362c9a8b122366dd8f2197fc6b784300d6a2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 22 Aug 2019 13:24:54 +0300 Subject: [PATCH 4060/7155] crypto: s390/aes - fix typo in XTS_BLOCK_SIZE identifier Fix a typo XTS_BLOCKSIZE -> XTS_BLOCK_SIZE, causing the build to break. Fixes: ce68acbcb6a5 ("crypto: s390/xts-aes - invoke fallback for...") Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/s390/crypto/aes_s390.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index a34faadc757e..d4f6fd42a105 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -586,7 +586,7 @@ static int xts_aes_encrypt(struct blkcipher_desc *desc, struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; - if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCKSIZE) != 0)) + if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCK_SIZE) != 0)) return xts_fallback_encrypt(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); @@ -600,7 +600,7 @@ static int xts_aes_decrypt(struct blkcipher_desc *desc, struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; - if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCKSIZE) != 0)) + if (unlikely(!xts_ctx->fc || (nbytes % XTS_BLOCK_SIZE) != 0)) return xts_fallback_decrypt(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); -- GitLab From c963050259f2daccb7141ee58bc0fc0b760836ba Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 22 Aug 2019 14:49:15 +0300 Subject: [PATCH 4061/7155] crypto: n2/des - fix build breakage after DES updates Fix build breakage caused by the DES library refactor. Fixes: d4b90dbc8578 ("crypto: n2/des - switch to new verification routines") Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/n2_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 4765163df6be..63923cc33727 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -757,7 +757,8 @@ static int n2_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, static int n2_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - struct n2_cipher_context *ctx = crypto_ablkcipher_ctx(cipher); + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct n2_cipher_context *ctx = crypto_tfm_ctx(tfm); struct n2_cipher_alg *n2alg = n2_cipher_alg(tfm); int err; @@ -775,7 +776,8 @@ static int n2_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, static int n2_3des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { - struct n2_cipher_context *ctx = crypto_ablkcipher_ctx(cipher); + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct n2_cipher_context *ctx = crypto_tfm_ctx(tfm); struct n2_cipher_alg *n2alg = n2_cipher_alg(tfm); int err; -- GitLab From e31b791fae32d01e8d0ee2e731b74d5471293cba Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Aug 2019 22:09:15 +1000 Subject: [PATCH 4062/7155] crypto: talitos - Fix build warning in aead_des3_setkey This patch removes the variable flags which is now unused thanks to the new DES helpers. Fixes: 9d574ae8ebc1 ("crypto: talitos/des - switch to new...") Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 117c831b5ede..cb6c10b1bf36 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -925,7 +925,6 @@ static int aead_des3_setkey(struct crypto_aead *authenc, struct talitos_ctx *ctx = crypto_aead_ctx(authenc); struct device *dev = ctx->dev; struct crypto_authenc_keys keys; - u32 flags; int err; err = crypto_authenc_extractkeys(&keys, key, keylen); -- GitLab From 320ea869a12cec206756207c6ca5f817ec45c7f2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 17:39:56 +0200 Subject: [PATCH 4063/7155] block: improve the gap check in __bio_add_pc_page If we can add more data into an existing segment we do not create a gap per definition, so move the check for a gap after the attempt to merge into the segment. Signed-off-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- block/bio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/block/bio.c b/block/bio.c index 54769659a434..537d71a30e56 100644 --- a/block/bio.c +++ b/block/bio.c @@ -710,18 +710,18 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, goto done; } - /* - * If the queue doesn't support SG gaps and adding this - * offset would create a gap, disallow it. - */ - if (bvec_gap_to_prev(q, bvec, offset)) - return 0; - if (page_is_mergeable(bvec, page, len, offset, &same_page) && can_add_page_to_seg(q, bvec, page, len, offset)) { bvec->bv_len += len; goto done; } + + /* + * If the queue doesn't support SG gaps and adding this segment + * would create a gap, disallow it. + */ + if (bvec_gap_to_prev(q, bvec, offset)) + return 0; } if (bio_full(bio, len)) -- GitLab From 384209cd5b93a926321fafe880ed05b1bca97260 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 17:39:57 +0200 Subject: [PATCH 4064/7155] block: create a bio_try_merge_pc_page helper Passsthrough bio handling should be the same as normal bio handling, except that we need to take hardware limitations into account. Thus use the common try_merge implementation after checking the hardware limits. This changes behavior in that we now also check segment and dma boundary settings for same page merges, which is a little more work but has no effect as those need to be larger than the page size. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/bio.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/block/bio.c b/block/bio.c index 537d71a30e56..c1782df36dff 100644 --- a/block/bio.c +++ b/block/bio.c @@ -646,25 +646,20 @@ static inline bool page_is_mergeable(const struct bio_vec *bv, return true; } -/* - * Check if the @page can be added to the current segment(@bv), and make - * sure to call it only if page_is_mergeable(@bv, @page) is true - */ -static bool can_add_page_to_seg(struct request_queue *q, - struct bio_vec *bv, struct page *page, unsigned len, - unsigned offset) +static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio, + struct page *page, unsigned len, unsigned offset, + bool *same_page) { + struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1]; unsigned long mask = queue_segment_boundary(q); phys_addr_t addr1 = page_to_phys(bv->bv_page) + bv->bv_offset; phys_addr_t addr2 = page_to_phys(page) + offset + len - 1; if ((addr1 | mask) != (addr2 | mask)) return false; - if (bv->bv_len + len > queue_max_segment_size(q)) return false; - - return true; + return __bio_try_merge_page(bio, page, len, offset, same_page); } /** @@ -700,26 +695,18 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, return 0; if (bio->bi_vcnt > 0) { - bvec = &bio->bi_io_vec[bio->bi_vcnt - 1]; - - if (page == bvec->bv_page && - offset == bvec->bv_offset + bvec->bv_len) { - if (put_same_page) + if (bio_try_merge_pc_page(q, bio, page, len, offset, + &same_page)) { + if (put_same_page && same_page) put_page(page); - bvec->bv_len += len; - goto done; - } - - if (page_is_mergeable(bvec, page, len, offset, &same_page) && - can_add_page_to_seg(q, bvec, page, len, offset)) { - bvec->bv_len += len; - goto done; + return len; } /* * If the queue doesn't support SG gaps and adding this segment * would create a gap, disallow it. */ + bvec = &bio->bi_io_vec[bio->bi_vcnt - 1]; if (bvec_gap_to_prev(q, bvec, offset)) return 0; } @@ -735,7 +722,6 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, bvec->bv_len = len; bvec->bv_offset = offset; bio->bi_vcnt++; - done: bio->bi_iter.bi_size += len; return len; } -- GitLab From d1916c86ccdcb67996278a850a22762102702d85 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 Aug 2019 17:39:58 +0200 Subject: [PATCH 4065/7155] block: move same page handling from __bio_add_pc_page to the callers Hiding page refcount manipulation inside a low-level bio helper is somewhat awkward. Instead return the same page information to the callers, where it fits in much better. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/bio.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/block/bio.c b/block/bio.c index c1782df36dff..8f0ed6228fc5 100644 --- a/block/bio.c +++ b/block/bio.c @@ -669,7 +669,7 @@ static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio, * @page: page to add * @len: vec entry length * @offset: vec entry offset - * @put_same_page: put the page if it is same with last added page + * @same_page: return if the merge happen inside the same page * * Attempt to add a page to the bio_vec maplist. This can fail for a * number of reasons, such as the bio being full or target block device @@ -680,10 +680,9 @@ static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio, */ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page, unsigned int len, unsigned int offset, - bool put_same_page) + bool *same_page) { struct bio_vec *bvec; - bool same_page = false; /* * cloned bio must not modify vec list @@ -695,12 +694,8 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, return 0; if (bio->bi_vcnt > 0) { - if (bio_try_merge_pc_page(q, bio, page, len, offset, - &same_page)) { - if (put_same_page && same_page) - put_page(page); + if (bio_try_merge_pc_page(q, bio, page, len, offset, same_page)) return len; - } /* * If the queue doesn't support SG gaps and adding this segment @@ -729,7 +724,8 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio, int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page *page, unsigned int len, unsigned int offset) { - return __bio_add_pc_page(q, bio, page, len, offset, false); + bool same_page = false; + return __bio_add_pc_page(q, bio, page, len, offset, &same_page); } EXPORT_SYMBOL(bio_add_pc_page); @@ -1373,13 +1369,17 @@ struct bio *bio_map_user_iov(struct request_queue *q, for (j = 0; j < npages; j++) { struct page *page = pages[j]; unsigned int n = PAGE_SIZE - offs; + bool same_page = false; if (n > bytes) n = bytes; if (!__bio_add_pc_page(q, bio, page, n, offs, - true)) + &same_page)) { + if (same_page) + put_page(page); break; + } added += n; bytes -= n; -- GitLab From 251137b8fa97ef37ed7dadbed9de48475021fd8b Mon Sep 17 00:00:00 2001 From: Qii Wang Date: Thu, 22 Aug 2019 20:35:16 +0800 Subject: [PATCH 4066/7155] arm64: dts: mt8183: add I2C nodes Add i2c nodes to mt8183 and mt8183-evb. Signed-off-by: Qii Wang Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 96 ++++++++++ arch/arm64/boot/dts/mediatek/mt8183.dtsi | 189 ++++++++++++++++++++ 2 files changed, 285 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts index d8e555cbb5d3..1fb195c683c3 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts @@ -30,7 +30,103 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_0>; + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_1>; + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_2>; + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_3>; + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_4>; + status = "okay"; + clock-frequency = <1000000>; +}; + +&i2c5 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_5>; + status = "okay"; + clock-frequency = <1000000>; +}; + &pio { + i2c_pins_0: i2c0{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + + i2c_pins_1: i2c1{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + + i2c_pins_2: i2c2{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + + i2c_pins_3: i2c3{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + + i2c_pins_4: i2c4{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + + i2c_pins_5: i2c5{ + pins_i2c{ + pinmux = , + ; + mediatek,pull-up-adv = <3>; + mediatek,drive-strength-adv = <00>; + }; + }; + spi_pins_0: spi0{ pins_spi{ pinmux = , diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index afb0996d46a3..97f84aa9fc6e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -16,6 +16,21 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c7; + i2c8 = &i2c8; + i2c9 = &i2c9; + i2c10 = &i2c10; + i2c11 = &i2c11; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -294,6 +309,64 @@ status = "disabled"; }; + i2c6: i2c@11005000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11005000 0 0x1000>, + <0 0x11000600 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C6>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c0: i2c@11007000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11007000 0 0x1000>, + <0 0x11000080 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C0>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@11008000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11008000 0 0x1000>, + <0 0x11000100 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C1>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C1_ARBITER>; + clock-names = "main", "dma","arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@11009000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11009000 0 0x1000>, + <0 0x11000280 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C2>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C2_ARBITER>; + clock-names = "main", "dma", "arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + spi0: spi@1100a000 { compatible = "mediatek,mt8183-spi"; #address-cells = <1>; @@ -307,6 +380,20 @@ status = "disabled"; }; + i2c3: i2c@1100f000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x1100f000 0 0x1000>, + <0 0x11000400 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C3>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + spi1: spi@11010000 { compatible = "mediatek,mt8183-spi"; #address-cells = <1>; @@ -320,6 +407,20 @@ status = "disabled"; }; + i2c1: i2c@11011000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11011000 0 0x1000>, + <0 0x11000480 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C4>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + spi2: spi@11012000 { compatible = "mediatek,mt8183-spi"; #address-cells = <1>; @@ -346,6 +447,66 @@ status = "disabled"; }; + i2c9: i2c@11014000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11014000 0 0x1000>, + <0 0x11000180 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C1_IMM>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C1_ARBITER>; + clock-names = "main", "dma", "arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c10: i2c@11015000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11015000 0 0x1000>, + <0 0x11000300 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C2_IMM>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C2_ARBITER>; + clock-names = "main", "dma", "arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@11016000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11016000 0 0x1000>, + <0 0x11000500 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C5>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C5_ARBITER>; + clock-names = "main", "dma", "arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c11: i2c@11017000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x11017000 0 0x1000>, + <0 0x11000580 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C5_IMM>, + <&infracfg CLK_INFRA_AP_DMA>, + <&infracfg CLK_INFRA_I2C5_ARBITER>; + clock-names = "main", "dma", "arb"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + spi4: spi@11018000 { compatible = "mediatek,mt8183-spi"; #address-cells = <1>; @@ -372,6 +533,34 @@ status = "disabled"; }; + i2c7: i2c@1101a000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x1101a000 0 0x1000>, + <0 0x11000680 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C7>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c8: i2c@1101b000 { + compatible = "mediatek,mt8183-i2c"; + reg = <0 0x1101b000 0 0x1000>, + <0 0x11000700 0 0x80>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_I2C8>, + <&infracfg CLK_INFRA_AP_DMA>; + clock-names = "main", "dma"; + clock-div = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + audiosys: syscon@11220000 { compatible = "mediatek,mt8183-audiosys", "syscon"; reg = <0 0x11220000 0 0x1000>; -- GitLab From db9a5fd02a06113848fd3eabe302f56059d27366 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 22 Aug 2019 13:11:37 +0200 Subject: [PATCH 4067/7155] tools headers: Add missing perf_event.h include We need perf_event.h include for 'struct perf_event_mmap_page'. Link: http://lkml.kernel.org/n/tip-bolqkmqajexhccjb0ib0an8w@git.kernel.org Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190822111141.25823-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/ring_buffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/include/linux/ring_buffer.h b/tools/include/linux/ring_buffer.h index 9a083ae60473..6c02617377c2 100644 --- a/tools/include/linux/ring_buffer.h +++ b/tools/include/linux/ring_buffer.h @@ -2,6 +2,7 @@ #define _TOOLS_LINUX_RING_BUFFER_H_ #include +#include /* * Contract with kernel for walking the perf ring buffer from -- GitLab From 6549cd8f2cc2cdf7e107fbbc3a68ecefb774bb2f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 22 Aug 2019 13:11:38 +0200 Subject: [PATCH 4068/7155] perf tools: Use perf_cpu_map__nr instead of cpu_map__nr Switch the rest of the perf code to use libperf's perf_cpu_map__nr(), which is the same as current cpu_map__nr() and remove the cpu_map__nr() function. Link: http://lkml.kernel.org/n/tip-6e0guy75clis7nm0xpuz9fga@git.kernel.org Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190822111141.25823-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 4 ++-- tools/perf/util/cpumap.h | 5 ----- tools/perf/util/evlist.c | 10 +++++----- tools/perf/util/mmap.c | 2 +- tools/perf/util/stat-display.c | 2 +- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 5cb07e8cb296..c786ab095d15 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -653,7 +653,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, cpu_map = online_cpus; } else { /* Make sure all specified CPUs are online */ - for (i = 0; i < cpu_map__nr(event_cpus); i++) { + for (i = 0; i < perf_cpu_map__nr(event_cpus); i++) { if (cpu_map__has(event_cpus, i) && !cpu_map__has(online_cpus, i)) return -EINVAL; @@ -662,7 +662,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, cpu_map = event_cpus; } - nr_cpu = cpu_map__nr(cpu_map); + nr_cpu = perf_cpu_map__nr(cpu_map); /* Get PMU type as dynamically assigned by the core */ type = cs_etm_pmu->type; diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index a3d27f4131be..77f85e9c88d4 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -49,11 +49,6 @@ static inline int cpu_map__id_to_cpu(int id) return id & 0xffff; } -static inline int cpu_map__nr(const struct perf_cpu_map *map) -{ - return map ? map->nr : 1; -} - static inline bool cpu_map__empty(const struct perf_cpu_map *map) { return map ? map->map[0] == -1 : true; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c4489a1ad6bc..15d1046014d7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -370,7 +370,7 @@ static int perf_evlist__enable_event_thread(struct evlist *evlist, int thread) { int cpu; - int nr_cpus = cpu_map__nr(evlist->core.cpus); + int nr_cpus = perf_cpu_map__nr(evlist->core.cpus); if (!evsel->core.fd) return -EINVAL; @@ -396,7 +396,7 @@ int perf_evlist__enable_event_idx(struct evlist *evlist, int perf_evlist__alloc_pollfd(struct evlist *evlist) { - int nr_cpus = cpu_map__nr(evlist->core.cpus); + int nr_cpus = perf_cpu_map__nr(evlist->core.cpus); int nr_threads = thread_map__nr(evlist->core.threads); int nfds = 0; struct evsel *evsel; @@ -692,7 +692,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, int i; struct perf_mmap *map; - evlist->nr_mmaps = cpu_map__nr(evlist->core.cpus); + evlist->nr_mmaps = perf_cpu_map__nr(evlist->core.cpus); if (cpu_map__empty(evlist->core.cpus)) evlist->nr_mmaps = thread_map__nr(evlist->core.threads); map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); @@ -807,7 +807,7 @@ static int perf_evlist__mmap_per_cpu(struct evlist *evlist, struct mmap_params *mp) { int cpu, thread; - int nr_cpus = cpu_map__nr(evlist->core.cpus); + int nr_cpus = perf_cpu_map__nr(evlist->core.cpus); int nr_threads = thread_map__nr(evlist->core.threads); pr_debug2("perf event ring buffer mmapped per cpu\n"); @@ -1014,7 +1014,7 @@ int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, evlist__for_each_entry(evlist, evsel) { if ((evsel->core.attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL && - perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) + perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0) return -ENOMEM; } diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 42a5971146ae..5f3532e51ec9 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -331,7 +331,7 @@ static void build_node_mask(int node, cpu_set_t *mask) if (!cpu_map) return; - nr_cpus = cpu_map__nr(cpu_map); + nr_cpus = perf_cpu_map__nr(cpu_map); for (c = 0; c < nr_cpus; c++) { cpu = cpu_map->map[c]; /* map c index to online cpu index */ if (cpu__get_node(cpu) == node) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index f7b39f4bc51e..3df0e39ccd52 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -745,7 +745,7 @@ static void print_aggr_thread(struct perf_stat_config *config, { FILE *output = config->output; int nthreads = thread_map__nr(counter->core.threads); - int ncpus = cpu_map__nr(counter->core.cpus); + int ncpus = perf_cpu_map__nr(counter->core.cpus); int thread, sorted_threads, id; struct perf_aggr_thread_value *buf; -- GitLab From 315c0a1f0ccdd44c65f80ccbc62202fed8a23050 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 22 Aug 2019 13:11:39 +0200 Subject: [PATCH 4069/7155] libperf: Move perf's cpu_map__empty() to perf_cpu_map__empty() So it's part of the libperf library as one of basic functions operating on the perf_cpu_map class. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190822111141.25823-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 8 ++++---- tools/perf/arch/x86/util/intel-bts.c | 4 ++-- tools/perf/arch/x86/util/intel-pt.c | 10 +++++----- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-stat.c | 4 ++-- tools/perf/lib/cpumap.c | 5 +++++ tools/perf/lib/include/perf/cpumap.h | 2 ++ tools/perf/lib/libperf.map | 1 + tools/perf/util/cpumap.c | 6 +++--- tools/perf/util/cpumap.h | 7 +------ tools/perf/util/event.c | 2 +- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/record.c | 2 +- tools/perf/util/stat.c | 2 +- 14 files changed, 32 insertions(+), 29 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index c786ab095d15..c73da3245b67 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -396,7 +396,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, * AUX event. We also need the contextID in order to be notified * when a context switch happened. */ - if (!cpu_map__empty(cpus)) { + if (!perf_cpu_map__empty(cpus)) { perf_evsel__set_sample_bit(cs_etm_evsel, CPU); err = cs_etm_set_option(itr, cs_etm_evsel, @@ -420,7 +420,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, tracking_evsel->core.attr.sample_period = 1; /* In per-cpu case, always need the time of mmap events etc */ - if (!cpu_map__empty(cpus)) + if (!perf_cpu_map__empty(cpus)) perf_evsel__set_sample_bit(tracking_evsel, TIME); } @@ -493,7 +493,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL); /* cpu map is not empty, we have specific CPUs to work with */ - if (!cpu_map__empty(event_cpus)) { + if (!perf_cpu_map__empty(event_cpus)) { for (i = 0; i < cpu__max_cpu(); i++) { if (!cpu_map__has(event_cpus, i) || !cpu_map__has(online_cpus, i)) @@ -649,7 +649,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, return -EINVAL; /* If the cpu_map is empty all online CPUs are involved */ - if (cpu_map__empty(event_cpus)) { + if (perf_cpu_map__empty(event_cpus)) { cpu_map = online_cpus; } else { /* Make sure all specified CPUs are online */ diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 7b23318ebd7b..2d5d8a12dd1f 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -133,7 +133,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, if (!opts->full_auxtrace) return 0; - if (opts->full_auxtrace && !cpu_map__empty(cpus)) { + if (opts->full_auxtrace && !perf_cpu_map__empty(cpus)) { pr_err(INTEL_BTS_PMU_NAME " does not support per-cpu recording\n"); return -EINVAL; } @@ -214,7 +214,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, * In the case of per-cpu mmaps, we need the CPU on the * AUX event. */ - if (!cpu_map__empty(cpus)) + if (!perf_cpu_map__empty(cpus)) perf_evsel__set_sample_bit(intel_bts_evsel, CPU); } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index a8e633aa278a..c72a77a82b39 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -365,7 +365,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, ui__warning("Intel Processor Trace: TSC not available\n"); } - per_cpu_mmaps = !cpu_map__empty(session->evlist->core.cpus); + per_cpu_mmaps = !perf_cpu_map__empty(session->evlist->core.cpus); auxtrace_info->type = PERF_AUXTRACE_INTEL_PT; auxtrace_info->priv[INTEL_PT_PMU_TYPE] = intel_pt_pmu->type; @@ -702,7 +702,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, * Per-cpu recording needs sched_switch events to distinguish different * threads. */ - if (have_timing_info && !cpu_map__empty(cpus)) { + if (have_timing_info && !perf_cpu_map__empty(cpus)) { if (perf_can_record_switch_events()) { bool cpu_wide = !target__none(&opts->target) && !target__has_task(&opts->target); @@ -760,7 +760,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, * In the case of per-cpu mmaps, we need the CPU on the * AUX event. */ - if (!cpu_map__empty(cpus)) + if (!perf_cpu_map__empty(cpus)) perf_evsel__set_sample_bit(intel_pt_evsel, CPU); } @@ -784,7 +784,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, tracking_evsel->immediate = true; /* In per-cpu case, always need the time of mmap events etc */ - if (!cpu_map__empty(cpus)) { + if (!perf_cpu_map__empty(cpus)) { perf_evsel__set_sample_bit(tracking_evsel, TIME); /* And the CPU for switch events */ perf_evsel__set_sample_bit(tracking_evsel, CPU); @@ -796,7 +796,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, * Warn the user when we do not have enough information to decode i.e. * per-cpu with no sched_switch (except workload-only). */ - if (!ptr->have_sched_switch && !cpu_map__empty(cpus) && + if (!ptr->have_sched_switch && !perf_cpu_map__empty(cpus) && !target__none(&opts->target)) ui__warning("Intel Processor Trace decoding will not be possible except for kernel tracing!\n"); diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index f0aae6e13a33..01629f5b6d1f 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2059,7 +2059,7 @@ static int setup_nodes(struct perf_session *session) nodes[node] = set; /* empty node, skip */ - if (cpu_map__empty(map)) + if (perf_cpu_map__empty(map)) continue; for (cpu = 0; cpu < map->nr; cpu++) { diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index b19df671111e..90636a811b36 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -928,7 +928,7 @@ static int perf_stat_init_aggr_mode(void) * the aggregation translate cpumap. */ nr = cpu_map__get_max(evsel_list->core.cpus); - stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1); + stat_config.cpus_aggr_map = perf_cpu_map__empty_new(nr + 1); return stat_config.cpus_aggr_map ? 0 : -ENOMEM; } @@ -1493,7 +1493,7 @@ int process_stat_config_event(struct perf_session *session, perf_event__read_stat_config(&stat_config, &event->stat_config); - if (cpu_map__empty(st->cpus)) { + if (perf_cpu_map__empty(st->cpus)) { if (st->aggr_mode != AGGR_UNSET) pr_warning("warning: processing task data, aggregation mode not set\n"); return 0; diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index 1ddb69e796e5..63f7df7e47ff 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -237,3 +237,8 @@ int perf_cpu_map__nr(const struct perf_cpu_map *cpus) { return cpus ? cpus->nr : 1; } + +bool perf_cpu_map__empty(const struct perf_cpu_map *map) +{ + return map ? map->map[0] == -1 : true; +} diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h index 1b6e7db3fa2b..8aa995c59498 100644 --- a/tools/perf/lib/include/perf/cpumap.h +++ b/tools/perf/lib/include/perf/cpumap.h @@ -4,6 +4,7 @@ #include #include +#include struct perf_cpu_map; @@ -14,6 +15,7 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx); LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); +LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map); #define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \ for ((idx) = 0, (cpu) = perf_cpu_map__cpu(cpus, idx); \ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index e24d3cec01c1..3373dd51fcda 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -8,6 +8,7 @@ LIBPERF_0.0.1 { perf_cpu_map__read; perf_cpu_map__nr; perf_cpu_map__cpu; + perf_cpu_map__empty; perf_thread_map__new_dummy; perf_thread_map__set_pid; perf_thread_map__comm; diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index beb3525e9e45..4402e67445a4 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -21,7 +21,7 @@ static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) { struct perf_cpu_map *map; - map = cpu_map__empty_new(cpus->nr); + map = perf_cpu_map__empty_new(cpus->nr); if (map) { unsigned i; @@ -48,7 +48,7 @@ static struct perf_cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask) nr = bitmap_weight(mask->mask, nbits); - map = cpu_map__empty_new(nr); + map = perf_cpu_map__empty_new(nr); if (map) { int cpu, i = 0; @@ -77,7 +77,7 @@ size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) #undef BUFSIZE } -struct perf_cpu_map *cpu_map__empty_new(int nr) +struct perf_cpu_map *perf_cpu_map__empty_new(int nr) { struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 77f85e9c88d4..3e068090612f 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -11,7 +11,7 @@ #include "perf.h" #include "util/debug.h" -struct perf_cpu_map *cpu_map__empty_new(int nr); +struct perf_cpu_map *perf_cpu_map__empty_new(int nr); struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); @@ -49,11 +49,6 @@ static inline int cpu_map__id_to_cpu(int id) return id & 0xffff; } -static inline bool cpu_map__empty(const struct perf_cpu_map *map) -{ - return map ? map->map[0] == -1 : true; -} - int cpu__setup_cpunode_map(void); int cpu__max_node(void); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f440fdc3e953..f433da85c45e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1055,7 +1055,7 @@ static size_t mask_size(struct perf_cpu_map *map, int *max) void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max) { size_t size_cpus, size_mask; - bool is_dummy = cpu_map__empty(map); + bool is_dummy = perf_cpu_map__empty(map); /* * Both array and mask data have variable size based diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 15d1046014d7..ba49b5ecffd0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -386,7 +386,7 @@ static int perf_evlist__enable_event_thread(struct evlist *evlist, int perf_evlist__enable_event_idx(struct evlist *evlist, struct evsel *evsel, int idx) { - bool per_cpu_mmaps = !cpu_map__empty(evlist->core.cpus); + bool per_cpu_mmaps = !perf_cpu_map__empty(evlist->core.cpus); if (per_cpu_mmaps) return perf_evlist__enable_event_cpu(evlist, evsel, idx); @@ -693,7 +693,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, struct perf_mmap *map; evlist->nr_mmaps = perf_cpu_map__nr(evlist->core.cpus); - if (cpu_map__empty(evlist->core.cpus)) + if (perf_cpu_map__empty(evlist->core.cpus)) evlist->nr_mmaps = thread_map__nr(evlist->core.threads); map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); if (!map) @@ -1018,7 +1018,7 @@ int perf_evlist__mmap_ex(struct evlist *evlist, unsigned int pages, return -ENOMEM; } - if (cpu_map__empty(cpus)) + if (perf_cpu_map__empty(cpus)) return perf_evlist__mmap_per_thread(evlist, &mp); return perf_evlist__mmap_per_cpu(evlist, &mp); diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index e59382d99196..51bbd0714e6d 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -275,7 +275,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) evsel = perf_evlist__last(temp_evlist); - if (!evlist || cpu_map__empty(evlist->core.cpus)) { + if (!evlist || perf_cpu_map__empty(evlist->core.cpus)) { struct perf_cpu_map *cpus = perf_cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index e4e4e3bf8b2b..2715112290cf 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -223,7 +223,7 @@ static int check_per_pkg(struct evsel *counter, if (!counter->per_pkg) return 0; - if (cpu_map__empty(cpus)) + if (perf_cpu_map__empty(cpus)) return 0; if (!mask) { -- GitLab From b4df75de3b3930703415aa053a269ae07c78d9b2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 22 Aug 2019 13:11:40 +0200 Subject: [PATCH 4070/7155] libperf: Move perf's cpu_map__idx() to perf_cpu_map__idx() As an internal function that will be used by both perf and libperf, but is not exported at this point. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190822111141.25823-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/cpumap.c | 12 ++++++++++++ tools/perf/lib/include/internal/cpumap.h | 2 ++ tools/perf/util/cpumap.c | 14 +------------- tools/perf/util/cpumap.h | 1 - tools/perf/util/evlist.c | 2 +- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c index 63f7df7e47ff..2834753576b2 100644 --- a/tools/perf/lib/cpumap.c +++ b/tools/perf/lib/cpumap.c @@ -242,3 +242,15 @@ bool perf_cpu_map__empty(const struct perf_cpu_map *map) { return map ? map->map[0] == -1 : true; } + +int perf_cpu_map__idx(struct perf_cpu_map *cpus, int cpu) +{ + int i; + + for (i = 0; i < cpus->nr; ++i) { + if (cpus->map[i] == cpu) + return i; + } + + return -1; +} diff --git a/tools/perf/lib/include/internal/cpumap.h b/tools/perf/lib/include/internal/cpumap.h index 3306319f7df8..840d4032587b 100644 --- a/tools/perf/lib/include/internal/cpumap.h +++ b/tools/perf/lib/include/internal/cpumap.h @@ -14,4 +14,6 @@ struct perf_cpu_map { #define MAX_NR_CPUS 2048 #endif +int perf_cpu_map__idx(struct perf_cpu_map *cpus, int cpu); + #endif /* __LIBPERF_INTERNAL_CPUMAP_H */ diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 4402e67445a4..8e6c2cbffedc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -458,19 +458,7 @@ int cpu__setup_cpunode_map(void) bool cpu_map__has(struct perf_cpu_map *cpus, int cpu) { - return cpu_map__idx(cpus, cpu) != -1; -} - -int cpu_map__idx(struct perf_cpu_map *cpus, int cpu) -{ - int i; - - for (i = 0; i < cpus->nr; ++i) { - if (cpus->map[i] == cpu) - return i; - } - - return -1; + return perf_cpu_map__idx(cpus, cpu) != -1; } int cpu_map__cpu(struct perf_cpu_map *cpus, int idx) diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 3e068090612f..8dbedda7af45 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -62,5 +62,4 @@ int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res, int cpu_map__cpu(struct perf_cpu_map *cpus, int idx); bool cpu_map__has(struct perf_cpu_map *cpus, int cpu); -int cpu_map__idx(struct perf_cpu_map *cpus, int cpu); #endif /* __PERF_CPUMAP_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index ba49b5ecffd0..8582560b59af 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -758,7 +758,7 @@ static int perf_evlist__mmap_per_evsel(struct evlist *evlist, int idx, if (evsel->system_wide && thread) continue; - cpu = cpu_map__idx(evsel->core.cpus, evlist_cpu); + cpu = perf_cpu_map__idx(evsel->core.cpus, evlist_cpu); if (cpu == -1) continue; -- GitLab From fe59fbd5dba9ae3bc94fc3d7d8556fe1e8707b61 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 22 Aug 2019 11:33:47 +0530 Subject: [PATCH 4071/7155] arm64: defconfig: Enable SM8150 GCC and pinctrl driver Enable GCC config CONFIG_SM_GCC_8150 and pinctrl config CONFIG_PINCTRL_SM8150 to make it possible to boot the SM8150 MTP. Signed-off-by: Vinod Koul Signed-off-by: Bjorn Andersson --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0e58ef02880c..09be33cb4d76 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -403,6 +403,7 @@ CONFIG_PINCTRL_QCS404=y CONFIG_PINCTRL_QDF2XXX=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_SDM845=y +CONFIG_PINCTRL_SM8150=y CONFIG_GPIO_DWAPB=y CONFIG_GPIO_MB86S7X=y CONFIG_GPIO_PL061=y @@ -690,6 +691,7 @@ CONFIG_MSM_MMCC_8996=y CONFIG_MSM_GCC_8998=y CONFIG_QCS_GCC_404=y CONFIG_SDM_GCC_845=y +CONFIG_SM_GCC_8150=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_ARM_MHU=y -- GitLab From a46f7c6762d8dce835a21e66eba263c5895d1aa0 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 22 Aug 2019 13:07:19 +0200 Subject: [PATCH 4072/7155] ARM: dts: ux500: Move ab8500 nodes to ste-ab8500.dtsi Some Ux500 devices use the newer AB8505 PMIC instead of AB8500. Although they are very similar, there are subtle differences like the number of regulators or the available GPIO pins. At the moment, ste-dbx5x0.dtsi always configures the AB8500 PMIC. To support devices with AB8505, it is necessary to split the AB8500-specific parts into a separate .dtsi file. Boards can then select the PMIC by including either ste-ab8500.dtsi or ste-ab8505.dtsi. Signed-off-by: Stephan Gerhold Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-ab8500.dtsi | 232 +++++++++++++++++++++++++ arch/arm/boot/dts/ste-dbx5x0.dtsi | 208 ---------------------- arch/arm/boot/dts/ste-href-ab8500.dtsi | 2 + 3 files changed, 234 insertions(+), 208 deletions(-) create mode 100644 arch/arm/boot/dts/ste-ab8500.dtsi diff --git a/arch/arm/boot/dts/ste-ab8500.dtsi b/arch/arm/boot/dts/ste-ab8500.dtsi new file mode 100644 index 000000000000..3ef1906e375c --- /dev/null +++ b/arch/arm/boot/dts/ste-ab8500.dtsi @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2012 Linaro Ltd + */ + +#include + +/ { + soc { + prcmu@80157000 { + ab8500 { + compatible = "stericsson,ab8500"; + interrupt-parent = <&intc>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <2>; + + ab8500_clock: clock-controller { + compatible = "stericsson,ab8500-clk"; + #clock-cells = <1>; + }; + + ab8500_gpio: ab8500-gpio { + compatible = "stericsson,ab8500-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + ab8500-rtc { + compatible = "stericsson,ab8500-rtc"; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH + 18 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "60S", "ALARM"; + }; + + ab8500-gpadc { + compatible = "stericsson,ab8500-gpadc"; + interrupts = <32 IRQ_TYPE_LEVEL_HIGH + 39 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "HW_CONV_END", "SW_CONV_END"; + vddadc-supply = <&ab8500_ldo_tvout_reg>; + }; + + ab8500_battery: ab8500_battery { + stericsson,battery-type = "LIPO"; + thermistor-on-batctrl; + }; + + ab8500_fg { + compatible = "stericsson,ab8500-fg"; + battery = <&ab8500_battery>; + }; + + ab8500_btemp { + compatible = "stericsson,ab8500-btemp"; + battery = <&ab8500_battery>; + }; + + ab8500_charger { + compatible = "stericsson,ab8500-charger"; + battery = <&ab8500_battery>; + vddadc-supply = <&ab8500_ldo_tvout_reg>; + }; + + ab8500_chargalg { + compatible = "stericsson,ab8500-chargalg"; + battery = <&ab8500_battery>; + }; + + ab8500_usb { + compatible = "stericsson,ab8500-usb"; + interrupts = < 90 IRQ_TYPE_LEVEL_HIGH + 96 IRQ_TYPE_LEVEL_HIGH + 14 IRQ_TYPE_LEVEL_HIGH + 15 IRQ_TYPE_LEVEL_HIGH + 79 IRQ_TYPE_LEVEL_HIGH + 74 IRQ_TYPE_LEVEL_HIGH + 75 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ID_WAKEUP_R", + "ID_WAKEUP_F", + "VBUS_DET_F", + "VBUS_DET_R", + "USB_LINK_STATUS", + "USB_ADP_PROBE_PLUG", + "USB_ADP_PROBE_UNPLUG"; + vddulpivio18-supply = <&ab8500_ldo_intcore_reg>; + v-ape-supply = <&db8500_vape_reg>; + musb_1v8-supply = <&db8500_vsmps2_reg>; + clocks = <&prcmu_clk PRCMU_SYSCLK>; + clock-names = "sysclk"; + }; + + ab8500-ponkey { + compatible = "stericsson,ab8500-poweron-key"; + interrupts = <6 IRQ_TYPE_LEVEL_HIGH + 7 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ONKEY_DBF", "ONKEY_DBR"; + }; + + ab8500-sysctrl { + compatible = "stericsson,ab8500-sysctrl"; + }; + + ab8500-pwm { + compatible = "stericsson,ab8500-pwm"; + clocks = <&ab8500_clock AB8500_SYSCLK_INT>; + clock-names = "intclk"; + }; + + ab8500-debugfs { + compatible = "stericsson,ab8500-debug"; + }; + + codec: ab8500-codec { + compatible = "stericsson,ab8500-codec"; + + V-AUD-supply = <&ab8500_ldo_audio_reg>; + V-AMIC1-supply = <&ab8500_ldo_anamic1_reg>; + V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>; + V-DMIC-supply = <&ab8500_ldo_dmic_reg>; + + clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>; + clock-names = "audioclk"; + + stericsson,earpeice-cmv = <950>; /* Units in mV. */ + }; + + ext_regulators: ab8500-ext-regulators { + compatible = "stericsson,ab8500-ext-regulator"; + + ab8500_ext1_reg: ab8500_ext1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ab8500_ext2_reg: ab8500_ext2 { + regulator-min-microvolt = <1360000>; + regulator-max-microvolt = <1360000>; + regulator-boot-on; + regulator-always-on; + }; + + ab8500_ext3_reg: ab8500_ext3 { + regulator-min-microvolt = <3400000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + }; + }; + + ab8500-regulators { + compatible = "stericsson,ab8500-regulator"; + vin-supply = <&ab8500_ext3_reg>; + + // supplies to the display/camera + ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + /* BUG: If turned off MMC will be affected. */ + regulator-always-on; + }; + + // supplies to the on-board eMMC + ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <3300000>; + }; + + // supply for VAUX3; SDcard slots + ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <3300000>; + }; + + // supply for v-intcore12; VINTCORE12 LDO + ab8500_ldo_intcore_reg: ab8500_ldo_intcore { + }; + + // supply for tvout; gpadc; TVOUT LDO + ab8500_ldo_tvout_reg: ab8500_ldo_tvout { + }; + + // supply for ab8500-usb; USB LDO + ab8500_ldo_usb_reg: ab8500_ldo_usb { + }; + + // supply for ab8500-vaudio; VAUDIO LDO + ab8500_ldo_audio_reg: ab8500_ldo_audio { + }; + + // supply for v-anamic1 VAMIC1 LDO + ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { + }; + + // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1 + ab8500_ldo_anamic2_reg: ab8500_ldo_anamic2 { + }; + + // supply for v-dmic; VDMIC LDO + ab8500_ldo_dmic_reg: ab8500_ldo_dmic { + }; + + // supply for U8500 CSI/DSI; VANA LDO + ab8500_ldo_ana_reg: ab8500_ldo_ana { + }; + }; + }; + }; + + sound { + stericsson,audio-codec = <&codec>; + clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>; + clock-names = "sysclk", "ulpclk", "intclk"; + }; + + mcde@a0350000 { + vana-supply = <&ab8500_ldo_ana_reg>; + + dsi@a0351000 { + vana-supply = <&ab8500_ldo_ana_reg>; + }; + dsi@a0352000 { + vana-supply = <&ab8500_ldo_ana_reg>; + }; + dsi@a0353000 { + vana-supply = <&ab8500_ldo_ana_reg>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 90dcbc3a29c3..527ee577e9a9 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -8,7 +8,6 @@ #include #include #include -#include / { #address-cells = <1>; @@ -617,206 +616,6 @@ db8500_esram34_ret_reg: db8500_esram34_ret { }; }; - - ab8500 { - compatible = "stericsson,ab8500"; - interrupt-parent = <&intc>; - interrupts = ; - interrupt-controller; - #interrupt-cells = <2>; - - ab8500_clock: clock-controller { - compatible = "stericsson,ab8500-clk"; - #clock-cells = <1>; - }; - - ab8500_gpio: ab8500-gpio { - compatible = "stericsson,ab8500-gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - - ab8500-rtc { - compatible = "stericsson,ab8500-rtc"; - interrupts = <17 IRQ_TYPE_LEVEL_HIGH - 18 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "60S", "ALARM"; - }; - - ab8500-gpadc { - compatible = "stericsson,ab8500-gpadc"; - interrupts = <32 IRQ_TYPE_LEVEL_HIGH - 39 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "HW_CONV_END", "SW_CONV_END"; - vddadc-supply = <&ab8500_ldo_tvout_reg>; - }; - - ab8500_battery: ab8500_battery { - stericsson,battery-type = "LIPO"; - thermistor-on-batctrl; - }; - - ab8500_fg { - compatible = "stericsson,ab8500-fg"; - battery = <&ab8500_battery>; - }; - - ab8500_btemp { - compatible = "stericsson,ab8500-btemp"; - battery = <&ab8500_battery>; - }; - - ab8500_charger { - compatible = "stericsson,ab8500-charger"; - battery = <&ab8500_battery>; - vddadc-supply = <&ab8500_ldo_tvout_reg>; - }; - - ab8500_chargalg { - compatible = "stericsson,ab8500-chargalg"; - battery = <&ab8500_battery>; - }; - - ab8500_usb { - compatible = "stericsson,ab8500-usb"; - interrupts = < 90 IRQ_TYPE_LEVEL_HIGH - 96 IRQ_TYPE_LEVEL_HIGH - 14 IRQ_TYPE_LEVEL_HIGH - 15 IRQ_TYPE_LEVEL_HIGH - 79 IRQ_TYPE_LEVEL_HIGH - 74 IRQ_TYPE_LEVEL_HIGH - 75 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "ID_WAKEUP_R", - "ID_WAKEUP_F", - "VBUS_DET_F", - "VBUS_DET_R", - "USB_LINK_STATUS", - "USB_ADP_PROBE_PLUG", - "USB_ADP_PROBE_UNPLUG"; - vddulpivio18-supply = <&ab8500_ldo_intcore_reg>; - v-ape-supply = <&db8500_vape_reg>; - musb_1v8-supply = <&db8500_vsmps2_reg>; - clocks = <&prcmu_clk PRCMU_SYSCLK>; - clock-names = "sysclk"; - }; - - ab8500-ponkey { - compatible = "stericsson,ab8500-poweron-key"; - interrupts = <6 IRQ_TYPE_LEVEL_HIGH - 7 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "ONKEY_DBF", "ONKEY_DBR"; - }; - - ab8500-sysctrl { - compatible = "stericsson,ab8500-sysctrl"; - }; - - ab8500-pwm { - compatible = "stericsson,ab8500-pwm"; - clocks = <&ab8500_clock AB8500_SYSCLK_INT>; - clock-names = "intclk"; - }; - - ab8500-debugfs { - compatible = "stericsson,ab8500-debug"; - }; - - codec: ab8500-codec { - compatible = "stericsson,ab8500-codec"; - - V-AUD-supply = <&ab8500_ldo_audio_reg>; - V-AMIC1-supply = <&ab8500_ldo_anamic1_reg>; - V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>; - V-DMIC-supply = <&ab8500_ldo_dmic_reg>; - - clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>; - clock-names = "audioclk"; - - stericsson,earpeice-cmv = <950>; /* Units in mV. */ - }; - - ext_regulators: ab8500-ext-regulators { - compatible = "stericsson,ab8500-ext-regulator"; - - ab8500_ext1_reg: ab8500_ext1 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - ab8500_ext2_reg: ab8500_ext2 { - regulator-min-microvolt = <1360000>; - regulator-max-microvolt = <1360000>; - regulator-boot-on; - regulator-always-on; - }; - - ab8500_ext3_reg: ab8500_ext3 { - regulator-min-microvolt = <3400000>; - regulator-max-microvolt = <3400000>; - regulator-boot-on; - }; - }; - - ab8500-regulators { - compatible = "stericsson,ab8500-regulator"; - vin-supply = <&ab8500_ext3_reg>; - - // supplies to the display/camera - ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2900000>; - regulator-boot-on; - /* BUG: If turned off MMC will be affected. */ - regulator-always-on; - }; - - // supplies to the on-board eMMC - ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for VAUX3; SDcard slots - ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for v-intcore12; VINTCORE12 LDO - ab8500_ldo_intcore_reg: ab8500_ldo_intcore { - }; - - // supply for tvout; gpadc; TVOUT LDO - ab8500_ldo_tvout_reg: ab8500_ldo_tvout { - }; - - // supply for ab8500-usb; USB LDO - ab8500_ldo_usb_reg: ab8500_ldo_usb { - }; - - // supply for ab8500-vaudio; VAUDIO LDO - ab8500_ldo_audio_reg: ab8500_ldo_audio { - }; - - // supply for v-anamic1 VAMIC1 LDO - ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { - }; - - // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1 - ab8500_ldo_anamic2_reg: ab8500_ldo_anamic2 { - }; - - // supply for v-dmic; VDMIC LDO - ab8500_ldo_dmic_reg: ab8500_ldo_dmic { - }; - - // supply for U8500 CSI/DSI; VANA LDO - ab8500_ldo_ana_reg: ab8500_ldo_ana { - }; - }; - }; }; i2c@80004000 { @@ -1130,9 +929,6 @@ sound { compatible = "stericsson,snd-soc-mop500"; stericsson,cpu-dai = <&msp1 &msp3>; - stericsson,audio-codec = <&codec>; - clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>; - clock-names = "sysclk", "ulpclk", "intclk"; }; msp0: msp@80123000 { @@ -1239,7 +1035,6 @@ reg = <0xa0350000 0x1000>; interrupts = ; epod-supply = <&db8500_b2r2_mcde_reg>; - vana-supply = <&ab8500_ldo_ana_reg>; clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */ <&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */ <&prcmu_clk PRCMU_PLLDSI>; /* HDMI clock */ @@ -1252,7 +1047,6 @@ dsi0: dsi@a0351000 { compatible = "ste,mcde-dsi"; reg = <0xa0351000 0x1000>; - vana-supply = <&ab8500_ldo_ana_reg>; clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>; clock-names = "hs", "lp"; #address-cells = <1>; @@ -1261,7 +1055,6 @@ dsi1: dsi@a0352000 { compatible = "ste,mcde-dsi"; reg = <0xa0352000 0x1000>; - vana-supply = <&ab8500_ldo_ana_reg>; clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>; clock-names = "hs", "lp"; #address-cells = <1>; @@ -1270,7 +1063,6 @@ dsi2: dsi@a0353000 { compatible = "ste,mcde-dsi"; reg = <0xa0353000 0x1000>; - vana-supply = <&ab8500_ldo_ana_reg>; /* This DSI port only has the Low Power / Energy Save clock */ clocks = <&prcmu_clk PRCMU_DSI2ESCCLK>; clock-names = "lp"; diff --git a/arch/arm/boot/dts/ste-href-ab8500.dtsi b/arch/arm/boot/dts/ste-href-ab8500.dtsi index 8e3e947d181f..4946743de7b9 100644 --- a/arch/arm/boot/dts/ste-href-ab8500.dtsi +++ b/arch/arm/boot/dts/ste-href-ab8500.dtsi @@ -3,6 +3,8 @@ * Copyright 2014 Linaro Ltd. */ +#include "ste-ab8500.dtsi" + / { soc { prcmu@80157000 { -- GitLab From 547c9983f2fb5240780d1a1d1235e7334d33dc0a Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 22 Aug 2019 13:07:20 +0200 Subject: [PATCH 4073/7155] ARM: dts: ux500: Remove ab8500_ldo_usb regulator from device tree Support for the USB regulator of AB8500 was removed in commit 41a06aa738ad ("regulator: ab8500: Remove USB regulator"). However, the configuration was never removed from the device tree. It does no longer have any effect, remove it from the device tree. Signed-off-by: Stephan Gerhold Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-ab8500.dtsi | 4 ---- arch/arm/boot/dts/ste-href.dtsi | 4 ---- arch/arm/boot/dts/ste-snowball.dts | 4 ---- 3 files changed, 12 deletions(-) diff --git a/arch/arm/boot/dts/ste-ab8500.dtsi b/arch/arm/boot/dts/ste-ab8500.dtsi index 3ef1906e375c..55fff4d44277 100644 --- a/arch/arm/boot/dts/ste-ab8500.dtsi +++ b/arch/arm/boot/dts/ste-ab8500.dtsi @@ -182,10 +182,6 @@ ab8500_ldo_tvout_reg: ab8500_ldo_tvout { }; - // supply for ab8500-usb; USB LDO - ab8500_ldo_usb_reg: ab8500_ldo_usb { - }; - // supply for ab8500-vaudio; VAUDIO LDO ab8500_ldo_audio_reg: ab8500_ldo_audio { }; diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index 6422c53f2046..4f6acbd8c040 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -234,10 +234,6 @@ regulator-name = "V-TVOUT"; }; - ab8500_ldo_usb_reg: ab8500_ldo_usb { - regulator-name = "dummy"; - }; - ab8500_ldo_audio_reg: ab8500_ldo_audio { regulator-name = "V-AUD"; }; diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index 064e8abec954..efbc4467b8b7 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -445,10 +445,6 @@ regulator-name = "V-TVOUT"; }; - ab8500_ldo_usb_reg: ab8500_ldo_usb { - regulator-name = "dummy"; - }; - ab8500_ldo_audio_reg: ab8500_ldo_audio { regulator-name = "V-AUD"; }; -- GitLab From cdfee5623290bc893f595636b44fa28e8207c5b3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 16 Aug 2019 08:24:35 +0200 Subject: [PATCH 4074/7155] driver core: initialize a default DMA mask for platform device We still treat devices without a DMA mask as defaulting to 32-bits for both mask, but a few releases ago we've started warning about such cases, as they require special cases to work around this sloppyness. Add a dma_mask field to struct platform_device so that we can initialize the dma_mask pointer in struct device and initialize both masks to 32-bits by default, replacing similar functionality in m68k and powerpc. The arch_setup_pdev_archdata hooks is now unused and removed. Note that the code looks a little odd with the various conditionals because we have to support platform_device structures that are statically allocated. Signed-off-by: Christoph Hellwig Acked-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190816062435.881-7-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- arch/m68k/kernel/dma.c | 9 ------- arch/powerpc/kernel/setup-common.c | 6 ----- arch/sh/boards/mach-ap325rxa/setup.c | 1 - arch/sh/boards/mach-ecovec24/setup.c | 2 -- arch/sh/boards/mach-kfr2r09/setup.c | 1 - arch/sh/boards/mach-migor/setup.c | 1 - arch/sh/boards/mach-se/7724/setup.c | 2 -- drivers/base/platform.c | 37 ++++++++++++---------------- include/linux/platform_device.h | 2 +- 9 files changed, 17 insertions(+), 44 deletions(-) diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c index 30cd59caf037..447849d1d645 100644 --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -79,12 +79,3 @@ void arch_sync_dma_for_device(struct device *dev, phys_addr_t handle, break; } } - -void arch_setup_pdev_archdata(struct platform_device *pdev) -{ - if (pdev->dev.coherent_dma_mask == DMA_MASK_NONE && - pdev->dev.dma_mask == NULL) { - pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; - } -} diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1f8db666468d..5e6543aba1b3 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -778,12 +778,6 @@ void ppc_printk_progress(char *s, unsigned short hex) pr_info("%s\n", s); } -void arch_setup_pdev_archdata(struct platform_device *pdev) -{ - pdev->archdata.dma_mask = DMA_BIT_MASK(32); - pdev->dev.dma_mask = &pdev->archdata.dma_mask; -} - static __init void print_system_info(void) { pr_info("-----------------------------------------------------\n"); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 8301a4378f50..665cad452798 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -527,7 +527,6 @@ static int __init ap325rxa_devices_setup(void) /* Initialize CEU platform device separately to map memory first */ device_initialize(&ap325rxa_ceu_device.dev); - arch_setup_pdev_archdata(&ap325rxa_ceu_device); dma_declare_coherent_memory(&ap325rxa_ceu_device.dev, ceu_dma_membase, ceu_dma_membase, ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index f402aa741bf3..acaa97459531 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1440,7 +1440,6 @@ static int __init arch_setup(void) /* Initialize CEU platform devices separately to map memory first */ device_initialize(&ecovec_ceu_devices[0]->dev); - arch_setup_pdev_archdata(ecovec_ceu_devices[0]); dma_declare_coherent_memory(&ecovec_ceu_devices[0]->dev, ceu0_dma_membase, ceu0_dma_membase, ceu0_dma_membase + @@ -1448,7 +1447,6 @@ static int __init arch_setup(void) platform_device_add(ecovec_ceu_devices[0]); device_initialize(&ecovec_ceu_devices[1]->dev); - arch_setup_pdev_archdata(ecovec_ceu_devices[1]); dma_declare_coherent_memory(&ecovec_ceu_devices[1]->dev, ceu1_dma_membase, ceu1_dma_membase, ceu1_dma_membase + diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 1cf9a47ac90e..96538ba3aa32 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -601,7 +601,6 @@ static int __init kfr2r09_devices_setup(void) /* Initialize CEU platform device separately to map memory first */ device_initialize(&kfr2r09_ceu_device.dev); - arch_setup_pdev_archdata(&kfr2r09_ceu_device); dma_declare_coherent_memory(&kfr2r09_ceu_device.dev, ceu_dma_membase, ceu_dma_membase, ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 90702740f207..9ed369dad62d 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -602,7 +602,6 @@ static int __init migor_devices_setup(void) /* Initialize CEU platform device separately to map memory first */ device_initialize(&migor_ceu_device.dev); - arch_setup_pdev_archdata(&migor_ceu_device); dma_declare_coherent_memory(&migor_ceu_device.dev, ceu_dma_membase, ceu_dma_membase, ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1); diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 3674064816c7..32f5dd944889 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -937,7 +937,6 @@ static int __init devices_setup(void) /* Initialize CEU platform devices separately to map memory first */ device_initialize(&ms7724se_ceu_devices[0]->dev); - arch_setup_pdev_archdata(ms7724se_ceu_devices[0]); dma_declare_coherent_memory(&ms7724se_ceu_devices[0]->dev, ceu0_dma_membase, ceu0_dma_membase, ceu0_dma_membase + @@ -945,7 +944,6 @@ static int __init devices_setup(void) platform_device_add(ms7724se_ceu_devices[0]); device_initialize(&ms7724se_ceu_devices[1]->dev); - arch_setup_pdev_archdata(ms7724se_ceu_devices[1]); dma_declare_coherent_memory(&ms7724se_ceu_devices[1]->dev, ceu1_dma_membase, ceu1_dma_membase, ceu1_dma_membase + diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ec974ba9c0c4..600913aea73b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -39,25 +39,6 @@ struct device platform_bus = { }; EXPORT_SYMBOL_GPL(platform_bus); -/** - * arch_setup_pdev_archdata - Allow manipulation of archdata before its used - * @pdev: platform device - * - * This is called before platform_device_add() such that any pdev_archdata may - * be setup before the platform_notifier is called. So if a user needs to - * manipulate any relevant information in the pdev_archdata they can do: - * - * platform_device_alloc() - * ... manipulate ... - * platform_device_add() - * - * And if they don't care they can just call platform_device_register() and - * everything will just work out. - */ -void __weak arch_setup_pdev_archdata(struct platform_device *pdev) -{ -} - /** * platform_get_resource - get a resource for a device * @dev: platform device @@ -264,6 +245,20 @@ struct platform_object { char name[]; }; +/* + * Set up default DMA mask for platform devices if the they weren't + * previously set by the architecture / DT. + */ +static void setup_pdev_dma_masks(struct platform_device *pdev) +{ + if (!pdev->dev.coherent_dma_mask) + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + if (!pdev->dma_mask) + pdev->dma_mask = DMA_BIT_MASK(32); + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dma_mask; +}; + /** * platform_device_put - destroy a platform device * @pdev: platform device to free @@ -310,7 +305,7 @@ struct platform_device *platform_device_alloc(const char *name, int id) pa->pdev.id = id; device_initialize(&pa->pdev.dev); pa->pdev.dev.release = platform_device_release; - arch_setup_pdev_archdata(&pa->pdev); + setup_pdev_dma_masks(&pa->pdev); } return pa ? &pa->pdev : NULL; @@ -512,7 +507,7 @@ EXPORT_SYMBOL_GPL(platform_device_del); int platform_device_register(struct platform_device *pdev) { device_initialize(&pdev->dev); - arch_setup_pdev_archdata(pdev); + setup_pdev_dma_masks(pdev); return platform_device_add(pdev); } EXPORT_SYMBOL_GPL(platform_device_register); diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 9bc36b589827..34a3d8ed8ba7 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -24,6 +24,7 @@ struct platform_device { int id; bool id_auto; struct device dev; + u64 dma_mask; u32 num_resources; struct resource *resource; @@ -48,7 +49,6 @@ extern void platform_device_unregister(struct platform_device *); extern struct bus_type platform_bus_type; extern struct device platform_bus; -extern void arch_setup_pdev_archdata(struct platform_device *); extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int); extern void __iomem * -- GitLab From d971e28e2ce4696fcc32998c8aced5e47701fffe Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 21 Aug 2019 23:59:55 +0000 Subject: [PATCH 4075/7155] EDAC/amd64: Support more than two controllers for chip selects handling The struct chip_select array that's used for saving chip select bases and masks is fixed at length of two. There should be one struct chip_select for each controller, so this array should be increased to support systems that may have more than two controllers. Increase the size of the struct chip_select array to eight, which is the largest number of controllers per die currently supported on AMD systems. Fix number of DIMMs and Chip Select bases/masks on Family17h, because AMD Family 17h systems support 2 DIMMs, 4 CS bases, and 2 CS masks per channel. Also, carve out the Family 17h+ reading of the bases/masks into a separate function. This effectively reverts the original bases/masks reading code to before Family 17h support was added. Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-2-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 123 +++++++++++++++++++++----------------- drivers/edac/amd64_edac.h | 5 +- 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 873437be86d9..dd60cf5a3d96 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -810,7 +810,7 @@ static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl) edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); - for (dimm = 0; dimm < 4; dimm++) { + for (dimm = 0; dimm < 2; dimm++) { size0 = 0; cs0 = dimm * 2; @@ -942,89 +942,102 @@ static void prep_chip_selects(struct amd64_pvt *pvt) } else if (pvt->fam == 0x15 && pvt->model == 0x30) { pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4; pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2; + } else if (pvt->fam >= 0x17) { + int umc; + + for_each_umc(umc) { + pvt->csels[umc].b_cnt = 4; + pvt->csels[umc].m_cnt = 2; + } + } else { pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4; } } +static void read_umc_base_mask(struct amd64_pvt *pvt) +{ + u32 umc_base_reg, umc_mask_reg; + u32 base_reg, mask_reg; + u32 *base, *mask; + int cs, umc; + + for_each_umc(umc) { + umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR; + + for_each_chip_select(cs, umc, pvt) { + base = &pvt->csels[umc].csbases[cs]; + + base_reg = umc_base_reg + (cs * 4); + + if (!amd_smn_read(pvt->mc_node_id, base_reg, base)) + edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *base, base_reg); + } + + umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK; + + for_each_chip_select_mask(cs, umc, pvt) { + mask = &pvt->csels[umc].csmasks[cs]; + + mask_reg = umc_mask_reg + (cs * 4); + + if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask)) + edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *mask, mask_reg); + } + } +} + /* * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers */ static void read_dct_base_mask(struct amd64_pvt *pvt) { - int base_reg0, base_reg1, mask_reg0, mask_reg1, cs; + int cs; prep_chip_selects(pvt); - if (pvt->umc) { - base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR; - base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR; - mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK; - mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK; - } else { - base_reg0 = DCSB0; - base_reg1 = DCSB1; - mask_reg0 = DCSM0; - mask_reg1 = DCSM1; - } + if (pvt->umc) + return read_umc_base_mask(pvt); for_each_chip_select(cs, 0, pvt) { - int reg0 = base_reg0 + (cs * 4); - int reg1 = base_reg1 + (cs * 4); + int reg0 = DCSB0 + (cs * 4); + int reg1 = DCSB1 + (cs * 4); u32 *base0 = &pvt->csels[0].csbases[cs]; u32 *base1 = &pvt->csels[1].csbases[cs]; - if (pvt->umc) { - if (!amd_smn_read(pvt->mc_node_id, reg0, base0)) - edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n", - cs, *base0, reg0); - - if (!amd_smn_read(pvt->mc_node_id, reg1, base1)) - edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n", - cs, *base1, reg1); - } else { - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) - edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", - cs, *base0, reg0); + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) + edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", + cs, *base0, reg0); - if (pvt->fam == 0xf) - continue; + if (pvt->fam == 0xf) + continue; - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) - edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", - cs, *base1, (pvt->fam == 0x10) ? reg1 - : reg0); - } + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) + edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", + cs, *base1, (pvt->fam == 0x10) ? reg1 + : reg0); } for_each_chip_select_mask(cs, 0, pvt) { - int reg0 = mask_reg0 + (cs * 4); - int reg1 = mask_reg1 + (cs * 4); + int reg0 = DCSM0 + (cs * 4); + int reg1 = DCSM1 + (cs * 4); u32 *mask0 = &pvt->csels[0].csmasks[cs]; u32 *mask1 = &pvt->csels[1].csmasks[cs]; - if (pvt->umc) { - if (!amd_smn_read(pvt->mc_node_id, reg0, mask0)) - edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n", - cs, *mask0, reg0); - - if (!amd_smn_read(pvt->mc_node_id, reg1, mask1)) - edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n", - cs, *mask1, reg1); - } else { - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) - edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", - cs, *mask0, reg0); + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) + edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", + cs, *mask0, reg0); - if (pvt->fam == 0xf) - continue; + if (pvt->fam == 0xf) + continue; - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) - edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", - cs, *mask1, (pvt->fam == 0x10) ? reg1 - : reg0); - } + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) + edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", + cs, *mask1, (pvt->fam == 0x10) ? reg1 + : reg0); } } diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 8f66472f7adc..4dce6a2ac75f 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -96,6 +96,7 @@ /* Hardware limit on ChipSelect rows per MC and processors per system */ #define NUM_CHIPSELECTS 8 #define DRAM_RANGES 8 +#define NUM_CONTROLLERS 8 #define ON true #define OFF false @@ -351,8 +352,8 @@ struct amd64_pvt { u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */ u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ - /* one for each DCT */ - struct chip_select csels[2]; + /* one for each DCT/UMC */ + struct chip_select csels[NUM_CONTROLLERS]; /* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */ struct dram_range ranges[DRAM_RANGES]; -- GitLab From cdb8a3c3463563b7bdb6f653bf4b0ffa3a95f366 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 20 Aug 2019 16:28:54 +0100 Subject: [PATCH 4076/7155] iommu/arm-smmu-v3: Avoid locking on invalidation path when not using ATS When ATS is not in use, we can avoid taking the 'devices_lock' for the domain on the invalidation path by simply caching the number of ATS masters currently attached. The fiddly part is handling a concurrent ->attach() of an ATS-enabled master to a domain that is being invalidated, but we can handle this using an 'smp_mb()' to ensure that our check of the count is ordered after completion of our prior TLB invalidation. This also makes our ->attach() and ->detach() flows symmetric wrt ATS interactions. Acked-by: Robin Murphy Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index ca504a60312d..0e43529d55fe 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -654,6 +654,7 @@ struct arm_smmu_domain { struct io_pgtable_ops *pgtbl_ops; bool non_strict; + atomic_t nr_ats_masters; enum arm_smmu_domain_stage stage; union { @@ -1926,6 +1927,23 @@ static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS)) return 0; + /* + * Ensure that we've completed prior invalidation of the main TLBs + * before we read 'nr_ats_masters' in case of a concurrent call to + * arm_smmu_enable_ats(): + * + * // unmap() // arm_smmu_enable_ats() + * TLBI+SYNC atomic_inc(&nr_ats_masters); + * smp_mb(); [...] + * atomic_read(&nr_ats_masters); pci_enable_ats() // writel() + * + * Ensures that we always see the incremented 'nr_ats_masters' count if + * ATS was enabled at the PCI device before completion of the TLBI. + */ + smp_mb(); + if (!atomic_read(&smmu_domain->nr_ats_masters)) + return 0; + arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd); spin_lock_irqsave(&smmu_domain->devices_lock, flags); @@ -2312,6 +2330,7 @@ static void arm_smmu_enable_ats(struct arm_smmu_master *master) size_t stu; struct pci_dev *pdev; struct arm_smmu_device *smmu = master->smmu; + struct arm_smmu_domain *smmu_domain = master->domain; /* Don't enable ATS at the endpoint if it's not enabled in the STE */ if (!master->ats_enabled) @@ -2320,6 +2339,9 @@ static void arm_smmu_enable_ats(struct arm_smmu_master *master) /* Smallest Translation Unit: log2 of the smallest supported granule */ stu = __ffs(smmu->pgsize_bitmap); pdev = to_pci_dev(master->dev); + + atomic_inc(&smmu_domain->nr_ats_masters); + arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0); if (pci_enable_ats(pdev, stu)) dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu); } @@ -2327,6 +2349,7 @@ static void arm_smmu_enable_ats(struct arm_smmu_master *master) static void arm_smmu_disable_ats(struct arm_smmu_master *master) { struct arm_smmu_cmdq_ent cmd; + struct arm_smmu_domain *smmu_domain = master->domain; if (!master->ats_enabled) return; @@ -2339,6 +2362,7 @@ static void arm_smmu_disable_ats(struct arm_smmu_master *master) wmb(); arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd); arm_smmu_atc_inv_master(master, &cmd); + atomic_dec(&smmu_domain->nr_ats_masters); } static void arm_smmu_detach_dev(struct arm_smmu_master *master) @@ -2349,11 +2373,12 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master) if (!smmu_domain) return; + arm_smmu_disable_ats(master); + spin_lock_irqsave(&smmu_domain->devices_lock, flags); list_del(&master->domain_head); spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); - arm_smmu_disable_ats(master); master->domain = NULL; master->ats_enabled = false; arm_smmu_install_ste_for_dev(master); @@ -2396,10 +2421,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) master->domain = smmu_domain; - spin_lock_irqsave(&smmu_domain->devices_lock, flags); - list_add(&master->domain_head, &smmu_domain->devices); - spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); - if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS) master->ats_enabled = arm_smmu_ats_supported(master); @@ -2407,7 +2428,13 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg); arm_smmu_install_ste_for_dev(master); + + spin_lock_irqsave(&smmu_domain->devices_lock, flags); + list_add(&master->domain_head, &smmu_domain->devices); + spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); + arm_smmu_enable_ats(master); + out_unlock: mutex_unlock(&smmu_domain->init_mutex); return ret; -- GitLab From a91bcc2b65370e7debf1fc26b93a4c2a54433220 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 21 Aug 2019 18:41:27 +0100 Subject: [PATCH 4077/7155] Revert "iommu/arm-smmu-v3: Disable detection of ATS and PRI" This reverts commit b5e86196b83fd68e065a7c811ab8925fb0dc3893. Now that ATC invalidation is performed in the correct places and without incurring a locking overhead for non-ATS systems, we can re-enable the corresponding SMMU feature detection. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 0e43529d55fe..b8049ea2e455 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -3336,13 +3336,11 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) } /* Boolean feature flags */ -#if 0 /* ATS invalidation is slow and broken */ if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI) smmu->features |= ARM_SMMU_FEAT_PRI; if (IS_ENABLED(CONFIG_PCI_ATS) && reg & IDR0_ATS) smmu->features |= ARM_SMMU_FEAT_ATS; -#endif if (reg & IDR0_SEV) smmu->features |= ARM_SMMU_FEAT_SEV; -- GitLab From 1243cb6a676ffcfa72dd25859edddf66cde0b638 Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Thu, 22 Aug 2019 15:17:43 +0100 Subject: [PATCH 4078/7155] arm64: Add tagged-address-abi.rst to index.rst Documentation/arm64/tagged-address-abi.rst introduces the relaxation of the syscall ABI that allows userspace to pass certain tagged pointers to kernel syscalls. Add the document to index.rst for a correct generation of the table of content. Cc: Will Deacon Cc: Catalin Marinas Signed-off-by: Vincenzo Frascino Signed-off-by: Will Deacon --- Documentation/arm64/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/arm64/index.rst b/Documentation/arm64/index.rst index 96b696ba4e6c..5c0c69dc58aa 100644 --- a/Documentation/arm64/index.rst +++ b/Documentation/arm64/index.rst @@ -16,6 +16,7 @@ ARM64 Architecture pointer-authentication silicon-errata sve + tagged-address-abi tagged-pointers .. only:: subproject and html -- GitLab From 0ce6a624473e7e5752a84416f85f73d082308edd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:30:07 +0800 Subject: [PATCH 4079/7155] ASoC: AMD: Fix Kconfig warning without GPIOLIB While do rand build without GPIOLIB, we get Kconfig warning:\ WARNING: unmet direct dependencies detected for SND_SOC_MAX98357A Depends on [n]: SOUND [=y] && !UML && SND [=m] && SND_SOC [=m] && GPIOLIB [=n] Selected by [m]: - SND_SOC_AMD_CZ_DA7219MX98357_MACH [=m] && SOUND [=y] && !UML && SND [=m] && SND_SOC [=m] && SND_SOC_AMD_ACP [=m] && I2C [=y] Add GPIOLIB dependency to fix this. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822143007.73644-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 9ca9214cb7fb..5f40517717c4 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -10,7 +10,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH select SND_SOC_MAX98357A select SND_SOC_ADAU7002 select REGULATOR - depends on SND_SOC_AMD_ACP && I2C + depends on SND_SOC_AMD_ACP && I2C && GPIOLIB help This option enables machine driver for DA7219 and MAX9835. -- GitLab From 7db2f2dfc701f9f903283e830653b02fb6ce823c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 21 Aug 2019 11:47:28 -0500 Subject: [PATCH 4080/7155] dt-bindings: dsp: fsl: Add DSP core binding support This describes the DSP device tree node. Signed-off-by: Daniel Baluta Reviewed-by: Rob Herring Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190821164730.7385-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../devicetree/bindings/dsp/fsl,dsp.yaml | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Documentation/devicetree/bindings/dsp/fsl,dsp.yaml diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml new file mode 100644 index 000000000000..3248595dc93c --- /dev/null +++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX8 DSP core + +maintainers: + - Daniel Baluta + +description: | + Some boards from i.MX8 family contain a DSP core used for + advanced pre- and post- audio processing. + +properties: + compatible: + enum: + - fsl,imx8qxp-dsp + + reg: + description: Should contain register location and length + + clocks: + items: + - description: ipg clock + - description: ocram clock + - description: core clock + + clock-names: + items: + - const: ipg + - const: ocram + - const: core + + power-domains: + description: + List of phandle and PM domain specifier as documented in + Documentation/devicetree/bindings/power/power_domain.txt + maxItems: 4 + + mboxes: + description: + List of <&phandle type channel> - 2 channels for TXDB, 2 channels for RXDB + (see mailbox/fsl,mu.txt) + maxItems: 4 + + mbox-names: + items: + - const: txdb0 + - const: txdb1 + - const: rxdb0 + - const: rxdb1 + + memory-region: + description: + phandle to a node describing reserved memory (System RAM memory) + used by DSP (see bindings/reserved-memory/reserved-memory.txt) + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - power-domains + - mboxes + - mbox-names + - memory-region + +examples: + - | + #include + #include + dsp@596e8000 { + compatible = "fsl,imx8qxp-dsp"; + reg = <0x596e8000 0x88000>; + clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>, + <&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>; + clock-names = "ipg", "ocram", "core"; + power-domains = <&pd IMX_SC_R_MU_13A>, + <&pd IMX_SC_R_MU_13B>, + <&pd IMX_SC_R_DSP>, + <&pd IMX_SC_R_DSP_RAM>; + mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1"; + mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>; + }; -- GitLab From b9132b89933177286fb427bd03affcebc4d649e1 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 21 Aug 2019 11:47:29 -0500 Subject: [PATCH 4081/7155] ASoC: SOF: Add OF DSP device support Add support for device tree based SOF DSP devices. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190821164730.7385-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 10 +++ sound/soc/sof/Makefile | 3 + sound/soc/sof/sof-of-dev.c | 143 +++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 sound/soc/sof/sof-of-dev.c diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index fb01f0ca6027..01acb580b817 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -36,6 +36,16 @@ config SND_SOC_SOF_ACPI Say Y if you need this option If unsure select "N". +config SND_SOC_SOF_OF + tristate "SOF OF enumeration support" + depends on OF || COMPILE_TEST + select SND_SOC_SOF + select SND_SOC_SOF_OPTIONS + help + This adds support for Device Tree enumeration. This option is + required to enable i.MX8 devices. + Say Y if you need this option. If unsure select "N". + config SND_SOC_SOF_OPTIONS tristate help diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 585fb6917489..772c452d1ae2 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -5,6 +5,8 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o +snd-sof-of-objs := sof-of-dev.o + snd-sof-nocodec-objs := nocodec.o obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o @@ -12,6 +14,7 @@ obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o obj-$(CONFIG_SND_SOC_SOF_ACPI) += snd-sof-acpi.o +obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c new file mode 100644 index 000000000000..28a9692974e5 --- /dev/null +++ b/sound/soc/sof/sof-of-dev.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// Copyright 2019 NXP +// +// Author: Daniel Baluta +// + +#include +#include +#include +#include + +#include "ops.h" + +extern struct snd_sof_dsp_ops sof_imx8_ops; + +/* platform specific devices */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) +static struct sof_dev_desc sof_of_imx8qxp_desc = { + .default_fw_path = "imx/sof", + .default_tplg_path = "imx/sof-tplg", + .nocodec_fw_filename = "sof-imx8.ri", + .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", + .ops = &sof_imx8_ops, +}; +#endif + +static const struct dev_pm_ops sof_of_pm = { + SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) + SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, + NULL) +}; + +static void sof_of_probe_complete(struct device *dev) +{ + /* allow runtime_pm */ + pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); +} + +static int sof_of_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct sof_dev_desc *desc; + /*TODO: create a generic snd_soc_xxx_mach */ + struct snd_soc_acpi_mach *mach; + struct snd_sof_pdata *sof_pdata; + const struct snd_sof_dsp_ops *ops; + int ret; + + dev_info(&pdev->dev, "DT DSP detected"); + + sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); + if (!sof_pdata) + return -ENOMEM; + + desc = device_get_match_data(dev); + if (!desc) + return -ENODEV; + + /* get ops for platform */ + ops = desc->ops; + if (!ops) { + dev_err(dev, "error: no matching DT descriptor ops\n"); + return -ENODEV; + } + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) + /* force nocodec mode */ + dev_warn(dev, "Force to use nocodec mode\n"); + mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL); + if (!mach) + return -ENOMEM; + ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops); + if (ret < 0) + return ret; +#else + /* TODO: implement case where we actually have a codec */ + return -ENODEV; +#endif + + if (mach) + mach->mach_params.platform = dev_name(dev); + + sof_pdata->machine = mach; + sof_pdata->desc = desc; + sof_pdata->dev = &pdev->dev; + sof_pdata->platform = dev_name(dev); + + /* TODO: read alternate fw and tplg filenames from DT */ + sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; + sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) + /* set callback to enable runtime_pm */ + sof_pdata->sof_probe_complete = sof_of_probe_complete; +#endif + /* call sof helper for DSP hardware probe */ + ret = snd_sof_device_probe(dev, sof_pdata); + if (ret) { + dev_err(dev, "error: failed to probe DSP hardware\n"); + return ret; + } + +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) + sof_of_probe_complete(dev); +#endif + + return ret; +} + +static int sof_of_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + /* call sof helper for DSP hardware remove */ + snd_sof_device_remove(&pdev->dev); + + return 0; +} + +static const struct of_device_id sof_of_ids[] = { +#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) + { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, +#endif + { } +}; +MODULE_DEVICE_TABLE(of, sof_of_ids); + +/* DT driver definition */ +static struct platform_driver snd_sof_of_driver = { + .probe = sof_of_probe, + .remove = sof_of_remove, + .driver = { + .name = "sof-audio-of", + .pm = &sof_of_pm, + .of_match_table = sof_of_ids, + }, +}; +module_platform_driver(snd_sof_of_driver); + +MODULE_LICENSE("Dual BSD/GPL"); -- GitLab From 202acc565a1f050f82fdab646fd9c86bfdb21733 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 21 Aug 2019 11:47:30 -0500 Subject: [PATCH 4082/7155] ASoC: SOF: imx: Add i.MX8 HW support Add support for the audio DSP hardware found on NXP i.MX8 platform. Signed-off-by: Daniel Baluta Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190821164730.7385-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 1 + sound/soc/sof/Makefile | 1 + sound/soc/sof/imx/Kconfig | 22 +++ sound/soc/sof/imx/Makefile | 4 + sound/soc/sof/imx/imx8.c | 394 +++++++++++++++++++++++++++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 sound/soc/sof/imx/Kconfig create mode 100644 sound/soc/sof/imx/Makefile create mode 100644 sound/soc/sof/imx/imx8.c diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 01acb580b817..bb8036ae567e 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -173,6 +173,7 @@ config SND_SOC_SOF_PROBE_WORK_QUEUE When selected, the probe is handled in two steps, for example to avoid lockdeps if request_module is used in the probe. +source "sound/soc/sof/imx/Kconfig" source "sound/soc/sof/intel/Kconfig" source "sound/soc/sof/xtensa/Kconfig" diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 772c452d1ae2..b0a6f01bdc44 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -18,4 +18,5 @@ obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ +obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig new file mode 100644 index 000000000000..fd73d8402dbf --- /dev/null +++ b/sound/soc/sof/imx/Kconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) + +config SND_SOC_SOF_IMX_TOPLEVEL + bool "SOF support for NXP i.MX audio DSPs" + depends on ARM64 && SND_SOC_SOF_OF || COMPILE_TEST + help + This adds support for Sound Open Firmware for NXP i.MX platforms. + Say Y if you have such a device. + If unsure select "N". + +if SND_SOC_SOF_IMX_TOPLEVEL + +config SND_SOC_SOF_IMX8 + tristate "SOF support for i.MX8" + depends on IMX_SCU + depends on IMX_DSP + help + This adds support for Sound Open Firmware for NXP i.MX8 platforms + Say Y if you have such a device. + If unsure select "N". + +endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile new file mode 100644 index 000000000000..6ef908e8c807 --- /dev/null +++ b/sound/soc/sof/imx/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +snd-sof-imx8-objs := imx8.o + +obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c new file mode 100644 index 000000000000..e502f584207f --- /dev/null +++ b/sound/soc/sof/imx/imx8.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// Copyright 2019 NXP +// +// Author: Daniel Baluta +// +// Hardware interface for audio DSP on i.MX8 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "../ops.h" + +/* DSP memories */ +#define IRAM_OFFSET 0x10000 +#define IRAM_SIZE (2 * 1024) +#define DRAM0_OFFSET 0x0 +#define DRAM0_SIZE (32 * 1024) +#define DRAM1_OFFSET 0x8000 +#define DRAM1_SIZE (32 * 1024) +#define SYSRAM_OFFSET 0x18000 +#define SYSRAM_SIZE (256 * 1024) +#define SYSROM_OFFSET 0x58000 +#define SYSROM_SIZE (192 * 1024) + +#define RESET_VECTOR_VADDR 0x596f8000 + +#define MBOX_OFFSET 0x800000 +#define MBOX_SIZE 0x1000 + +struct imx8_priv { + struct device *dev; + struct snd_sof_dev *sdev; + + /* DSP IPC handler */ + struct imx_dsp_ipc *dsp_ipc; + struct platform_device *ipc_dev; + + /* System Controller IPC handler */ + struct imx_sc_ipc *sc_ipc; + + /* Power domain handling */ + int num_domains; + struct device **pd_dev; + struct device_link **link; + +}; + +static void imx8_get_reply(struct snd_sof_dev *sdev) +{ + struct snd_sof_ipc_msg *msg = sdev->msg; + struct sof_ipc_reply reply; + int ret = 0; + + if (!msg) { + dev_warn(sdev->dev, "unexpected ipc interrupt\n"); + return; + } + + /* get reply */ + sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); + + if (reply.error < 0) { + memcpy(msg->reply_data, &reply, sizeof(reply)); + ret = reply.error; + } else { + /* reply has correct size? */ + if (reply.hdr.size != msg->reply_size) { + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", + msg->reply_size, reply.hdr.size); + ret = -EINVAL; + } + + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); + } + + msg->reply_error = ret; +} + +static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + return MBOX_OFFSET; +} + +static int imx8_get_window_offset(struct snd_sof_dev *sdev, u32 id) +{ + return MBOX_OFFSET; +} + +void imx8_dsp_handle_reply(struct imx_dsp_ipc *ipc) +{ + struct imx8_priv *priv = imx_dsp_get_data(ipc); + unsigned long flags; + + spin_lock_irqsave(&priv->sdev->ipc_lock, flags); + imx8_get_reply(priv->sdev); + snd_sof_ipc_reply(priv->sdev, 0); + spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); +} + +void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc) +{ + struct imx8_priv *priv = imx_dsp_get_data(ipc); + + snd_sof_ipc_msgs_rx(priv->sdev); +} + +struct imx_dsp_ops dsp_ops = { + .handle_reply = imx8_dsp_handle_reply, + .handle_request = imx8_dsp_handle_request, +}; + +static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +{ + struct imx8_priv *priv = (struct imx8_priv *)sdev->private; + + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, + msg->msg_size); + imx_dsp_ring_doorbell(priv->dsp_ipc, 0); + + return 0; +} + +/* + * DSP control. + */ +static int imx8_run(struct snd_sof_dev *sdev) +{ + struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; + int ret; + + ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + IMX_SC_C_OFS_SEL, 1); + if (ret < 0) { + dev_err(sdev->dev, "Error system address offset source select\n"); + return ret; + } + + ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + IMX_SC_C_OFS_AUDIO, 0x80); + if (ret < 0) { + dev_err(sdev->dev, "Error system address offset of AUDIO\n"); + return ret; + } + + ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + IMX_SC_C_OFS_PERIPH, 0x5A); + if (ret < 0) { + dev_err(sdev->dev, "Error system address offset of PERIPH %d\n", + ret); + return ret; + } + + ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + IMX_SC_C_OFS_IRQ, 0x51); + if (ret < 0) { + dev_err(sdev->dev, "Error system address offset of IRQ\n"); + return ret; + } + + imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true, + RESET_VECTOR_VADDR); + + return 0; +} + +static int imx8_probe(struct snd_sof_dev *sdev) +{ + struct platform_device *pdev = + container_of(sdev->dev, struct platform_device, dev); + struct device_node *np = pdev->dev.of_node; + struct device_node *res_node; + struct resource *mmio; + struct imx8_priv *priv; + struct resource res; + u32 base, size; + int ret = 0; + int i; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + sdev->private = priv; + priv->dev = sdev->dev; + priv->sdev = sdev; + + /* power up device associated power domains */ + priv->num_domains = of_count_phandle_with_args(np, "power-domains", + "#power-domain-cells"); + if (priv->num_domains < 0) { + dev_err(sdev->dev, "no power-domains property in %pOF\n", np); + return priv->num_domains; + } + + priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains, + sizeof(*priv->pd_dev), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains, + sizeof(*priv->link), GFP_KERNEL); + if (!priv->link) + return -ENOMEM; + + for (i = 0; i < priv->num_domains; i++) { + priv->pd_dev[i] = dev_pm_domain_attach_by_id(&pdev->dev, i); + if (IS_ERR(priv->pd_dev[i])) { + ret = PTR_ERR(priv->pd_dev[i]); + goto exit_unroll_pm; + } + priv->link[i] = device_link_add(&pdev->dev, priv->pd_dev[i], + DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); + if (IS_ERR(priv->link[i])) { + ret = PTR_ERR(priv->link[i]); + dev_pm_domain_detach(priv->pd_dev[i], false); + goto exit_unroll_pm; + } + } + + ret = imx_scu_get_handle(&priv->sc_ipc); + if (ret) { + dev_err(sdev->dev, "Cannot obtain SCU handle (err = %d)\n", + ret); + goto exit_unroll_pm; + } + + priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", + PLATFORM_DEVID_NONE, + pdev, sizeof(*pdev)); + if (IS_ERR(priv->ipc_dev)) { + ret = PTR_ERR(priv->ipc_dev); + goto exit_unroll_pm; + } + + priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); + if (!priv->dsp_ipc) { + /* DSP IPC driver not probed yet, try later */ + ret = -EPROBE_DEFER; + dev_err(sdev->dev, "Failed to get drvdata\n"); + goto exit_pdev_unregister; + } + + imx_dsp_set_data(priv->dsp_ipc, priv); + priv->dsp_ipc->ops = &dsp_ops; + + /* DSP base */ + mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (mmio) { + base = mmio->start; + size = resource_size(mmio); + } else { + dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); + ret = -EINVAL; + goto exit_pdev_unregister; + } + + sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); + if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { + dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", + base, size); + ret = -ENODEV; + goto exit_pdev_unregister; + } + sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; + + res_node = of_parse_phandle(np, "memory-region", 0); + if (!res_node) { + dev_err(&pdev->dev, "failed to get memory region node\n"); + ret = -ENODEV; + goto exit_pdev_unregister; + } + + ret = of_address_to_resource(res_node, 0, &res); + if (ret) { + dev_err(&pdev->dev, "failed to get reserved region address\n"); + goto exit_pdev_unregister; + } + + sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, + res.end - res.start + + 1); + if (IS_ERR(sdev->bar[SOF_FW_BLK_TYPE_SRAM])) { + dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", + base, size); + ret = PTR_ERR(sdev->bar[SOF_FW_BLK_TYPE_SRAM]); + goto exit_pdev_unregister; + } + sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; + + return 0; + +exit_pdev_unregister: + platform_device_unregister(priv->ipc_dev); +exit_unroll_pm: + while (--i >= 0) { + device_link_del(priv->link[i]); + dev_pm_domain_detach(priv->pd_dev[i], false); + } + + return ret; +} + +static int imx8_remove(struct snd_sof_dev *sdev) +{ + struct imx8_priv *priv = (struct imx8_priv *)sdev->private; + int i; + + platform_device_unregister(priv->ipc_dev); + + for (i = 0; i < priv->num_domains; i++) { + device_link_del(priv->link[i]); + dev_pm_domain_detach(priv->pd_dev[i], false); + } + + return 0; +} + +/* on i.MX8 there is 1 to 1 match between type and BAR idx */ +int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type) +{ + return type; +} + +void imx8_ipc_msg_data(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + void *p, size_t sz) +{ + sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); +} + +int imx8_ipc_pcm_params(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + const struct sof_ipc_pcm_params_reply *reply) +{ + return 0; +} + +static struct snd_soc_dai_driver imx8_dai[] = { +{ + .name = "esai-port", +}, +}; + +/* i.MX8 ops */ +struct snd_sof_dsp_ops sof_imx8_ops = { + /* probe and remove */ + .probe = imx8_probe, + .remove = imx8_remove, + /* DSP core boot */ + .run = imx8_run, + + /* Block IO */ + .block_read = sof_block_read, + .block_write = sof_block_write, + + /* ipc */ + .send_msg = imx8_send_msg, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = imx8_get_mailbox_offset, + .get_window_offset = imx8_get_window_offset, + + .ipc_msg_data = imx8_ipc_msg_data, + .ipc_pcm_params = imx8_ipc_pcm_params, + + /* module loading */ + .load_module = snd_sof_parse_module_memcpy, + .get_bar_index = imx8_get_bar_index, + /* firmware loading */ + .load_firmware = snd_sof_load_firmware_memcpy, + + /* DAI drivers */ + .drv = imx8_dai, + .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ +}; +EXPORT_SYMBOL(sof_imx8_ops); + +MODULE_LICENSE("Dual BSD/GPL"); -- GitLab From c101fb29737f4558bf589d0d66371d9e21040568 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:36:08 +0800 Subject: [PATCH 4083/7155] ASoC: wm8988: fix typo in wm8988_right_line_controls sound/soc/codecs/wm8988.c:270:30: warning: wm8988_rline_enum defined but not used [-Wunused-const-variable=] wm8988_rline_enum should be used in wm8988_right_line_controls. Reported-by: Hulk Robot Fixes: 5409fb4e327a ("ASoC: Add WM8988 CODEC driver") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822143608.59824-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8988.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 25e74cf0666a..85bfd041d546 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -273,7 +273,7 @@ static const struct soc_enum wm8988_rline_enum = wm8988_line_texts, wm8988_line_values); static const struct snd_kcontrol_new wm8988_right_line_controls = - SOC_DAPM_ENUM("Route", wm8988_lline_enum); + SOC_DAPM_ENUM("Route", wm8988_rline_enum); /* Left Mixer */ static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = { -- GitLab From 97aad5ce88164bc5f884b5234f015ac553ea2fe5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:37:47 +0800 Subject: [PATCH 4084/7155] ASoC: mediatek: mt2701: Fix -Wunused-const-variable warnings sound/soc/mediatek/mt2701/mt2701-afe-common.h:66:27: warning: mt2701_afe_backup_list defined but not used [-Wunused-const-variable=] mt2701_afe_backup_list is only used in mt2701-afe-pcm.c, so just move the definition over there. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822143747.20944-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-common.h | 21 ------------------- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h index d44faba27d3c..32bef5e2a56d 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h +++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h @@ -63,27 +63,6 @@ enum audio_base_clock { MT2701_BASE_CLK_NUM, }; -static const unsigned int mt2701_afe_backup_list[] = { - AUDIO_TOP_CON0, - AUDIO_TOP_CON4, - AUDIO_TOP_CON5, - ASYS_TOP_CON, - AFE_CONN0, - AFE_CONN1, - AFE_CONN2, - AFE_CONN3, - AFE_CONN15, - AFE_CONN16, - AFE_CONN17, - AFE_CONN18, - AFE_CONN19, - AFE_CONN20, - AFE_CONN21, - AFE_CONN22, - AFE_DAC_CON0, - AFE_MEMIF_PBUF_SIZE, -}; - struct mt2701_i2s_data { int i2s_ctrl_reg; int i2s_asrc_fs_shift; diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index d7f5defa50c2..76502ba261c8 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -60,6 +60,27 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { { .rate = 352800, .regvalue = 24 }, }; +static const unsigned int mt2701_afe_backup_list[] = { + AUDIO_TOP_CON0, + AUDIO_TOP_CON4, + AUDIO_TOP_CON5, + ASYS_TOP_CON, + AFE_CONN0, + AFE_CONN1, + AFE_CONN2, + AFE_CONN3, + AFE_CONN15, + AFE_CONN16, + AFE_CONN17, + AFE_CONN18, + AFE_CONN19, + AFE_CONN20, + AFE_CONN21, + AFE_CONN22, + AFE_DAC_CON0, + AFE_MEMIF_PBUF_SIZE, +}; + static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) { struct mt2701_afe_private *afe_priv = afe->platform_priv; -- GitLab From 6191cbde5ff02ef5307e7b2e4f5b8f7607c2b1df Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Thu, 22 Aug 2019 20:51:00 +0800 Subject: [PATCH 4085/7155] ASoC: mediatek: mt8183: switch tdm pins gpio function when playback on or off Pull TDM pins down when TDM BE shutdown to avoid current leakage. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/1566478261-13464-2-git-send-email-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 115 +++++++++++++++++- 1 file changed, 109 insertions(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 272766c1b859..fe8a7461ace5 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -46,6 +46,32 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static const struct snd_soc_dapm_widget +mt8183_mt6358_ts3a227_max98357_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("IT6505_8CH"), +}; + +static const struct snd_soc_dapm_route +mt8183_mt6358_ts3a227_max98357_dapm_routes[] = { + {"IT6505_8CH", NULL, "TDM"}, +}; + +enum PINCTRL_PIN_STATE { + PIN_STATE_DEFAULT = 0, + PIN_TDM_OUT_ON, + PIN_TDM_OUT_OFF, + PIN_STATE_MAX +}; + +static const char * const mt8183_pin_str[PIN_STATE_MAX] = { + "default", "aud_tdm_out_on", "aud_tdm_out_off", +}; + +struct mt8183_mt6358_ts3a227_max98357_priv { + struct pinctrl *pinctrl; + struct pinctrl_state *pin_states[PIN_STATE_MAX]; +}; + static int mt8183_mt6358_ts3a227_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -173,6 +199,47 @@ SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); +static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8183_mt6358_ts3a227_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) + return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_ON]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + + return ret; +} + +static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8183_mt6358_ts3a227_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) + return; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_OFF]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); +} + +static struct snd_soc_ops mt8183_mt6358_tdm_ops = { + .startup = mt8183_mt6358_tdm_startup, + .shutdown = mt8183_mt6358_tdm_shutdown, +}; + static struct snd_soc_dai_link mt8183_mt6358_ts3a227_max98357_dai_links[] = { /* FE */ @@ -325,6 +392,8 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, + .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, + .ops = &mt8183_mt6358_tdm_ops, SND_SOC_DAILINK_REG(tdm), }, }; @@ -371,7 +440,8 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card; struct device_node *platform_node; struct snd_soc_dai_link *dai_link; - struct pinctrl *default_pins; + struct mt8183_mt6358_ts3a227_max98357_priv *priv; + int ret; int i; card->dev = &pdev->dev; @@ -397,12 +467,45 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) card->num_aux_devs = 1; } - default_pins = - devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); - if (IS_ERR(default_pins)) { - dev_err(&pdev->dev, "%s set pins failed\n", + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(priv->pinctrl)) { + dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", __func__); - return PTR_ERR(default_pins); + return PTR_ERR(priv->pinctrl); + } + + for (i = 0 ; i < PIN_STATE_MAX ; i++) { + priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, + mt8183_pin_str[i]); + if (IS_ERR(priv->pin_states[i])) { + ret = PTR_ERR(priv->pin_states[i]); + dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", + __func__, mt8183_pin_str[i], ret); + } + } + + if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_OFF]); + if (ret) + dev_info(&pdev->dev, + "%s failed to select state %d\n", + __func__, ret); + } + + if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_DEFAULT]); + if (ret) + dev_info(&pdev->dev, + "%s failed to select state %d\n", + __func__, ret); } return devm_snd_soc_register_card(&pdev->dev, card); -- GitLab From 4168ddabb480bef818c93f378428632fb681b500 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:04:49 +0900 Subject: [PATCH 4086/7155] ASoC: soc-core: use device_register() It is easy to read code if it is cleanly using paired function/naming, like start <-> stop, register <-> unregister, etc, etc. But, current ALSA SoC code is very random, unbalance, not paired, etc. soc-core.c is using device_unregiser(), but there is no its paired device_regiser(). We can find its code at soc_post_component_init() which is using device_initialize() and device_add(). Here, device_initialize() + device_add() = device_register(). -- linux/drivers/base/core.c -- int device_register(struct device *dev) { device_initialize(dev); return device_add(dev); } device_initialize() is doing each dev member's initialization only, not related to device parent/release/groups. Thus, we can postpone it. let's use device_register() instead of device_initialize()/device_add(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/878sro1ldw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6df880be1622..3860d8521734 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1347,7 +1347,6 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (!rtd->dev) return -ENOMEM; - device_initialize(rtd->dev); rtd->dev->parent = rtd->card->dev; rtd->dev->release = rtd_release; rtd->dev->groups = soc_dev_attr_groups; @@ -1357,7 +1356,7 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); - ret = device_add(rtd->dev); + ret = device_register(rtd->dev); if (ret < 0) { /* calling put_device() here to free the rtd->dev */ put_device(rtd->dev); -- GitLab From a33c0d166cc5bcb3b9718649b84974216709acb1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:02 +0900 Subject: [PATCH 4087/7155] ASoC: soc-core: add NOTE to snd_soc_rtdcom_lookup() We can find specified name component via snd_soc_rtdcom_lookup(). But, it is not enough under multi CPU/Codec/Platform, because many components which have same driver name might be connected to same rtd. Not using this function as much as possible is best solution, but some drivers are already deeply depended to it. We can expand this function, for example having "num" which specifies found order at parameter, etc (In such case, it need to have fixed probing order). Or, use different driver name in such component, etc. We will have such issue if multi CPU/Codec/Platform were supported. To indicate it, this patch adds NOTE to this function. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/874l2c1ldi.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3860d8521734..0ed6576bfef4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -315,6 +315,14 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd, if (!driver_name) return NULL; + /* + * NOTE + * + * snd_soc_rtdcom_lookup() will find component from rtd by using + * specified driver name. + * But, if many components which have same driver name are connected + * to 1 rtd, this function will return 1st found component. + */ for_each_rtdcom(rtd, rtdcom) { const char *component_name = rtdcom->component->driver->name; -- GitLab From a4de83a385670c22c31e9bbb726595a447b32ba4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:10 +0900 Subject: [PATCH 4088/7155] ASoC: soc-core: soc_cleanup_card_resources() become void There is no need to check return value for soc_cleanup_card_resources(). Let't makes it as void. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/871rxg1lda.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0ed6576bfef4..1be069c2ac8d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1885,7 +1885,7 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) } } -static int soc_cleanup_card_resources(struct snd_soc_card *card) +static void soc_cleanup_card_resources(struct snd_soc_card *card) { /* free the ALSA card at first; this syncs with pending operations */ if (card->snd_card) { @@ -1906,8 +1906,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) /* remove the card */ if (card->remove) card->remove(card); - - return 0; } static int snd_soc_instantiate_card(struct snd_soc_card *card) -- GitLab From 6b8ac43c33b912bc5435192ce3b3f051f6f2dc9d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:28 +0900 Subject: [PATCH 4089/7155] ASoC: soc-dai: use bit field for bus_control .bus_control can be bit field. this patch do it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9uszazh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index dc48fe081a20..939c73db6a03 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -293,8 +293,6 @@ struct snd_soc_dai_driver { /* Optional Callback used at pcm creation*/ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); - /* DAI is also used for the control bus */ - bool bus_control; /* ops */ const struct snd_soc_dai_ops *ops; @@ -306,6 +304,7 @@ struct snd_soc_dai_driver { unsigned int symmetric_rates:1; unsigned int symmetric_channels:1; unsigned int symmetric_samplebits:1; + unsigned int bus_control:1; /* DAI is also used for the control bus */ /* probe ordering - for components with runtime dependencies */ int probe_order; -- GitLab From 43ca5dab978294eae26a36f8989b6f0769da4256 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:32 +0900 Subject: [PATCH 4090/7155] ASoC: soc-topology: use for_each_component_dais() at remove_dai() commit 52abe6cc1866a ("ASoC: topology: fix oops/use-after-free case with dai driver") fixups remove_dai() error, but it is using list_for_each_entry() for component->dai_list. We already have for_each_component_dais() macro for it. Let's use exising method. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tvaczazd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index dc463f1a9e24..b8690715abb5 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -530,7 +530,7 @@ static void remove_dai(struct snd_soc_component *comp, if (dobj->ops && dobj->ops->dai_unload) dobj->ops->dai_unload(comp, dobj); - list_for_each_entry(dai, &comp->dai_list, list) + for_each_component_dais(comp, dai) if (dai->driver == dai_drv) dai->driver = NULL; -- GitLab From 8d92bb516831e80fac916701447ee6e9f0a6f0f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:16 +0900 Subject: [PATCH 4091/7155] ASoC: soc-core: initialize component list It might return without initializing in error case. In such case, uninitialized variable might be used at error handler. This patch initializes all necessary variable before return. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87zhk4zazt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1be069c2ac8d..1a17cb1bc03b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2647,6 +2647,9 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, { struct snd_soc_dapm_context *dapm; + INIT_LIST_HEAD(&component->dai_list); + mutex_init(&component->io_mutex); + component->name = fmt_single_name(dev, &component->id); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); @@ -2663,9 +2666,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, dapm->idle_bias_off = !driver->idle_bias_on; dapm->suspend_bias_off = driver->suspend_bias_off; - INIT_LIST_HEAD(&component->dai_list); - mutex_init(&component->io_mutex); - return 0; } -- GitLab From b2f3e0c9e4ee2e07fd880cc0c4da20c42d633d4b Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Thu, 22 Aug 2019 00:11:38 +0300 Subject: [PATCH 4092/7155] ASoC: SOF: topology: fix get control data return type and arguments sof_get_control_data returns negative values even though the return value is defined unsigned (size_t). So change the return value type to int and add the data size as pointer argument to sof_get_control_data to avoid ambiquity in the meaning of the return type. Fixes: cac974a51ebb ("ASoC: SOF: topology: use set_get_data in process load") Reported by: Dan Carpenter Signed-off-by: Jaska Uimonen Link: https://lore.kernel.org/r/20190821211138.14618-1-jaska.uimonen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 28a7a6e06a53..fc85efbad378 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1752,17 +1752,19 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index, return ret; } -static size_t sof_get_control_data(struct snd_sof_dev *sdev, - struct snd_soc_dapm_widget *widget, - struct sof_widget_data *wdata) +static int sof_get_control_data(struct snd_sof_dev *sdev, + struct snd_soc_dapm_widget *widget, + struct sof_widget_data *wdata, + size_t *size) { const struct snd_kcontrol_new *kc; struct soc_mixer_control *sm; struct soc_bytes_ext *sbe; struct soc_enum *se; - size_t size = 0; int i; + *size = 0; + for (i = 0; i < widget->num_kcontrols; i++) { kc = &widget->kcontrol_news[i]; @@ -1800,7 +1802,7 @@ static size_t sof_get_control_data(struct snd_sof_dev *sdev, if (wdata[i].pdata->magic != SOF_ABI_MAGIC) return -EINVAL; - size += wdata[i].pdata->size; + *size += wdata[i].pdata->size; /* get data type */ switch (wdata[i].control->cmd) { @@ -1819,7 +1821,7 @@ static size_t sof_get_control_data(struct snd_sof_dev *sdev, } } - return size; + return 0; } static int sof_process_load(struct snd_soc_component *scomp, int index, @@ -1855,12 +1857,11 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, return -ENOMEM; /* get possible component controls and get size of all pdata */ - ipc_data_size = sof_get_control_data(sdev, widget, wdata); + ret = sof_get_control_data(sdev, widget, wdata, + &ipc_data_size); - if (ipc_data_size <= 0) { - ret = ipc_data_size; + if (ret < 0) goto out; - } } ipc_size = sizeof(struct sof_ipc_comp_process) + -- GitLab From 495efdb01f89a5fc53f9b2e61f5726d804d4a15d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 20 Aug 2019 14:05:20 +0900 Subject: [PATCH 4093/7155] ASoC: soc-core: initialize list at one place Initialize component related list at random place is very difficult to read. This patch initialize it at snd_soc_component_initialize(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2zozazp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1a17cb1bc03b..0af83963289f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1272,7 +1272,6 @@ static int soc_probe_component(struct snd_soc_card *card, component->card = card; dapm->card = card; - INIT_LIST_HEAD(&component->card_list); INIT_LIST_HEAD(&dapm->list); soc_set_name_prefix(card, component); @@ -2648,6 +2647,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, struct snd_soc_dapm_context *dapm; INIT_LIST_HEAD(&component->dai_list); + INIT_LIST_HEAD(&component->dobj_list); + INIT_LIST_HEAD(&component->card_list); mutex_init(&component->io_mutex); component->name = fmt_single_name(dev, &component->id); @@ -2733,7 +2734,6 @@ static void snd_soc_component_add(struct snd_soc_component *component) /* see for_each_component */ list_add(&component->list, &component_list); - INIT_LIST_HEAD(&component->dobj_list); mutex_unlock(&client_mutex); } -- GitLab From 45a2c0ccf6b96b046ad167a8c90ceaa5e59d07cb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Aug 2019 15:03:37 -0300 Subject: [PATCH 4094/7155] perf arm64: Add missing debug.h header This file uses pr_debug() but isn't including debug.h, getting it by luck, fix it. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-t7pisnsdfh88kclpw52jcwl7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm64/util/header.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c index 602caf550e7f..e41defaaa2e6 100644 --- a/tools/perf/arch/arm64/util/header.c +++ b/tools/perf/arch/arm64/util/header.c @@ -1,6 +1,7 @@ #include #include #include +#include "debug.h" #include "header.h" #define MIDR "/regs/identification/midr_el1" -- GitLab From 823034575c177d1d69673102a994d5d33b05e3de Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 21 Aug 2019 17:05:39 +0200 Subject: [PATCH 4095/7155] soc: samsung: chipid: Remove the regmap lookup error log In commit 40d8aff614f7 ("soc: samsung: chipid: Convert exynos-chipid driver to use the regmap API") of_find_compatible_node() call was substituted with syscon_regmap_lookup_by_compatible() but also an error log was added for case where lookup fails. On multiplatform the lookup will always fail on any non-samsung device so the log is incorrect. Remove the error log and just return an error code from syscon_regmap_lookup_by_compatible() which internally calls of_find_compatible_node(). Reported-by: Jon Hunter Signed-off-by: Sylwester Nawrocki Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-chipid.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 75b6b880d9ef..c55a47cfe617 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -56,10 +56,8 @@ int __init exynos_chipid_early_init(void) int ret; regmap = syscon_regmap_lookup_by_compatible("samsung,exynos4210-chipid"); - if (IS_ERR(regmap)) { - pr_err("Failed to get CHIPID regmap\n"); + if (IS_ERR(regmap)) return PTR_ERR(regmap); - } ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id); if (ret < 0) -- GitLab From 28578825ede61834a2c46e7f9a89012c4c7a667f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 21 Aug 2019 17:39:26 +0200 Subject: [PATCH 4096/7155] soc: samsung: chipid: Select missing dependency for EXYNOS_CHIPID The chipid driver uses the MFD syscon API but it was not covered properly in Kconfig. Signed-off-by: Sylwester Nawrocki Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index 2905f5262197..33ad0de2de3c 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -10,6 +10,7 @@ if SOC_SAMSUNG config EXYNOS_CHIPID bool "Exynos Chipid controller driver" if COMPILE_TEST depends on ARCH_EXYNOS || COMPILE_TEST + select MFD_SYSCON select SOC_BUS config EXYNOS_PMU -- GitLab From c663d542bfb40eeeb6d393ed155c23a4666d65e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 18 Aug 2019 19:27:50 +0200 Subject: [PATCH 4097/7155] MAINTAINERS: Extend patterns for Samsung SoC, Security Subsystem and clock drivers Extend the patterns to cover all related files in respective categories: 1. Samsung Exynos ARM architecture: add soc drivers headers and make directory matches consistent, 2. Samsung Security SubSystem driver (crypto): add bindings, 3. Samsung SoC clock drivers: add S3C24xx, S3C64xx and S5Pv210 bindings. Cc: Kukjin Kim Cc: Vladimir Zapolskiy Cc: Kamil Konieczny Cc: Sylwester Nawrocki Cc: Tomasz Figa Cc: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski Acked-by: Chanwoo Choi Acked-by: Sylwester Nawrocki --- MAINTAINERS | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..d16c50b3514e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2217,8 +2217,9 @@ F: drivers/*/*s3c24* F: drivers/*/*/*s3c24* F: drivers/*/*s3c64xx* F: drivers/*/*s5pv210* -F: drivers/memory/samsung/* -F: drivers/soc/samsung/* +F: drivers/memory/samsung/ +F: drivers/soc/samsung/ +F: include/linux/soc/samsung/ F: Documentation/arm/samsung/ F: Documentation/devicetree/bindings/arm/samsung/ F: Documentation/devicetree/bindings/sram/samsung-sram.txt @@ -14106,6 +14107,8 @@ M: Kamil Konieczny L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/crypto/samsung-slimsss.txt +F: Documentation/devicetree/bindings/crypto/samsung-sss.txt F: drivers/crypto/s5p-sss.c SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS @@ -14126,6 +14129,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git F: drivers/clk/samsung/ F: include/dt-bindings/clock/exynos*.h F: Documentation/devicetree/bindings/clock/exynos*.txt +F: Documentation/devicetree/bindings/clock/samsung,s3c* +F: Documentation/devicetree/bindings/clock/samsung,s5p* SAMSUNG SPI DRIVERS M: Kukjin Kim -- GitLab From 303290e130bfd504a8230f49e545f6b91e120553 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 13 Aug 2019 15:53:11 +0530 Subject: [PATCH 4098/7155] spi: fsl-qspi: Enhance binding to extend example for flash entry Add example for adding flash entry on various boards' dts using flash manufacture spansion/cypress. Signed-off-by: Ashish Kumar Link: https://lore.kernel.org/r/1565691791-26167-3-git-send-email-Ashish.Kumar@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt index e8f1d627d288..1b23cfd7b39b 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt @@ -34,7 +34,11 @@ qspi0: quadspi@40044000 { clock-names = "qspi_en", "qspi"; flash0: s25fl128s@0 { - .... + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s", "jedec,spi-nor"; + spi-max-frequency = <50000000>; + reg = <0>; }; }; -- GitLab From c76c992525245ec1c7b6738bf887c42099abab02 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Aug 2019 13:53:40 +0100 Subject: [PATCH 4099/7155] nexthops: remove redundant assignment to variable err Variable err is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused Value") Signed-off-by: Colin Ian King Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv4/nexthop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 5fe5a3981d43..fc34fd1668d6 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -1151,7 +1151,7 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh, .fc_encap_type = cfg->nh_encap_type, }; u32 tb_id = l3mdev_fib_table(cfg->dev); - int err = -EINVAL; + int err; err = fib_nh_init(net, fib_nh, &fib_cfg, 1, extack); if (err) { -- GitLab From be28f76b7e8ffaf04690e30fd17683d8afea1fd9 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Tue, 13 Aug 2019 15:53:09 +0530 Subject: [PATCH 4100/7155] spi: spi-fsl-qspi: Add ls2080a compatibility string to bindings There are 2 version of QSPI-IP, according to which controller registers sets can be big endian or little endian.There are some other minor changes like RX fifo depth etc. The big endian version uses driver compatible "fsl,ls1021a-qspi" and little endian version uses driver compatible "fsl,ls2080a-qspi" Signed-off-by: Kuldeep Singh Signed-off-by: Ashish Kumar Reviewed-by: Rob Herring Acked-by: Han Xu Link: https://lore.kernel.org/r/1565691791-26167-1-git-send-email-Ashish.Kumar@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt index 1b23cfd7b39b..69dc5d57b1ef 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt @@ -3,9 +3,8 @@ Required properties: - compatible : Should be "fsl,vf610-qspi", "fsl,imx6sx-qspi", "fsl,imx7d-qspi", "fsl,imx6ul-qspi", - "fsl,ls1021a-qspi" + "fsl,ls1021a-qspi", "fsl,ls2080a-qspi" or - "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi", "fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi" - reg : the first contains the register location and length, the second contains the memory mapping address and length -- GitLab From e8cae2e64202f5acc209e81cb4f24614daa900b7 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 21 Aug 2019 17:54:38 +0000 Subject: [PATCH 4101/7155] arm64: dts: rockchip: add rk3328 VPU node This patch add a VPU device node for rk3328. Signed-off-by: Jonas Karlman Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index e9fefd8a7e02..4a175fff2861 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -278,6 +278,7 @@ }; pd_vpu@RK3328_PD_VPU { reg = ; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; }; }; @@ -596,6 +597,17 @@ status = "disabled"; }; + vpu: video-codec@ff350000 { + compatible = "rockchip,rk3328-vpu"; + reg = <0x0 0xff350000 0x0 0x800>; + interrupts = ; + interrupt-names = "vdpu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "hclk"; + iommus = <&vpu_mmu>; + power-domains = <&power RK3328_PD_VPU>; + }; + vpu_mmu: iommu@ff350800 { compatible = "rockchip,iommu"; reg = <0x0 0xff350800 0x0 0x40>; @@ -604,7 +616,7 @@ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; clock-names = "aclk", "iface"; #iommu-cells = <0>; - status = "disabled"; + power-domains = <&power RK3328_PD_VPU>; }; rkvdec_mmu: iommu@ff360480 { -- GitLab From 3bf7ec62f8b37143d1f18bc30f77c8f4093c1e09 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 21 Aug 2019 11:11:23 +0800 Subject: [PATCH 4102/7155] ARM: dts: rockchip: remove rk3288 fennec board support Since there is no one using this board, remove it. Signed-off-by: Kever Yang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/Makefile | 1 - arch/arm/boot/dts/rk3288-fennec.dts | 347 ---------------------------- 2 files changed, 348 deletions(-) delete mode 100644 arch/arm/boot/dts/rk3288-fennec.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a84a04cf894b..f69eeb0db66c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -908,7 +908,6 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3229-xms6.dtb \ rk3288-evb-act8846.dtb \ rk3288-evb-rk808.dtb \ - rk3288-fennec.dtb \ rk3288-firefly-beta.dtb \ rk3288-firefly.dtb \ rk3288-firefly-reload.dtb \ diff --git a/arch/arm/boot/dts/rk3288-fennec.dts b/arch/arm/boot/dts/rk3288-fennec.dts deleted file mode 100644 index 4847cf902a15..000000000000 --- a/arch/arm/boot/dts/rk3288-fennec.dts +++ /dev/null @@ -1,347 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) - -/dts-v1/; - -#include "rk3288.dtsi" - -/ { - model = "Rockchip RK3288 Fennec Board"; - compatible = "rockchip,rk3288-fennec", "rockchip,rk3288"; - - memory@0 { - reg = <0x0 0x0 0x0 0x80000000>; - device_type = "memory"; - }; - - ext_gmac: external-gmac-clock { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <125000000>; - clock-output-names = "ext_gmac"; - }; - - vcc_sys: vsys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; - }; -}; - -&cpu0 { - cpu0-supply = <&vdd_cpu>; -}; - -&emmc { - bus-width = <8>; - cap-mmc-highspeed; - non-removable; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; - status = "okay"; -}; - -&gmac { - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; - clock_in_out = "input"; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>; - phy-supply = <&vcc_lan>; - phy-mode = "rgmii"; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 1000000>; - snps,reset-gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_LOW>; - tx_delay = <0x30>; - rx_delay = <0x10>; - status = "okay"; -}; - -&gpu { - mali-supply = <&vdd_gpu>; - status = "okay"; -}; - -&hdmi { - status = "okay"; -}; - -&i2c0 { - status = "okay"; - clock-frequency = <400000>; - - rk808: pmic@1b { - compatible = "rockchip,rk808"; - reg = <0x1b>; - interrupt-parent = <&gpio0>; - interrupts = ; - #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int &global_pwroff>; - rockchip,system-power-controller; - wakeup-source; - - vcc1-supply = <&vcc_sys>; - vcc2-supply = <&vcc_sys>; - vcc3-supply = <&vcc_sys>; - vcc4-supply = <&vcc_sys>; - vcc6-supply = <&vcc_sys>; - vcc7-supply = <&vcc_sys>; - vcc8-supply = <&vcc_io>; - vcc9-supply = <&vcc_io>; - vcc10-supply = <&vcc_io>; - vcc11-supply = <&vcc_io>; - vcc12-supply = <&vcc_io>; - vddio-supply = <&vcc_io>; - - regulators { - vdd_cpu: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_gpu: DCDC_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1250000>; - regulator-name = "vdd_gpu"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_ddr"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_io: DCDC_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_io"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vccio_pmu: LDO_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vccio_pmu"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcca_33: LDO_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcca_33"; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_10: LDO_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd_10"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc_wl: LDO_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_wl"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vccio_sd: LDO_REG5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vccio_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vdd10_lcd: LDO_REG6 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd10_lcd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc_18: LDO_REG7 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_18"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc18_lcd: LDO_REG8 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc18_lcd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc_sd: SWITCH_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_sd"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_lan: SWITCH_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_lan"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - }; - }; -}; - -&pinctrl { - pcfg_output_high: pcfg-output-high { - output-high; - }; - - pcfg_output_low: pcfg-output-low { - output-low; - }; - - pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { - drive-strength = <8>; - }; - - pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { - bias-pull-up; - drive-strength = <8>; - }; - - gmac { - phy_int: phy-int { - rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - phy_pmeb: phy-pmeb { - rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - phy_rst: phy-rst { - rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>; - }; - }; - - pmic { - pmic_int: pmic-int { - rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - usbphy { - host_drv: host-drv { - rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - -&uart2 { - status = "okay"; -}; - -&usbphy { - pinctrl-names = "default"; - pinctrl-0 = <&host_drv>; - vbus_drv-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host1 { - status = "okay"; -}; - -&usb_otg { - status = "okay"; -}; - -&usb_hsic { - status = "okay"; -}; - -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; -- GitLab From 9f72a1d0300b03a9fc6cba93f8cc0ab326185788 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 21 Aug 2019 11:11:24 +0800 Subject: [PATCH 4103/7155] dt-bindings: arm: rockchip: remove reference to fennec board The rk3288 fennec board has been removed, remove the binding document at the same time. Signed-off-by: Kever Yang Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 4a1a28e7a812..48b09483381a 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -459,11 +459,6 @@ properties: - rockchip,rk3288-evb-rk808 - const: rockchip,rk3288 - - description: Rockchip RK3288 Fennec - items: - - const: rockchip,rk3288-fennec - - const: rockchip,rk3288 - - description: Rockchip RK3328 Evaluation board items: - const: rockchip,rk3328-evb -- GitLab From b26af9304467d8e7844397e702b51a4bdc74bedd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Aug 2019 13:20:34 +0100 Subject: [PATCH 4104/7155] mac80211: minstrel_ht: fix infinite loop because supported is not being shifted Currently the for-loop will spin forever if variable supported is non-zero because supported is never changed. Fix this by adding in the missing right shift of supported. Addresses-Coverity: ("Infinite loop") Fixes: 48cb39522a9d ("mac80211: minstrel_ht: improve rate probing for devices with static fallback") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190822122034.28664-1-colin.king@canonical.com Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index a01168514840..0ef2633349b5 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -634,7 +634,7 @@ minstrel_ht_rate_sample_switch(struct minstrel_priv *mp, u16 supported = mi->supported[g_idx]; supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES; - for (i = 0; supported; i++) { + for (i = 0; supported; supported >>= 1, i++) { if (!(supported & 1)) continue; -- GitLab From 7010998c6caf7cf9706f31c1880b7aeac904e874 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Thu, 22 Aug 2019 10:48:06 -0700 Subject: [PATCH 4105/7155] nl80211: add NL80211_CMD_UPDATE_FT_IES to supported commands Add NL80211_CMD_UPDATE_FT_IES to supported commands. In mac80211 drivers, this can be implemented via existing NL80211_CMD_AUTHENTICATE and NL80211_ATTR_IE, but non-mac80211 drivers have a separate command for this. A driver supports FT if it either is mac80211 or supports this command. Signed-off-by: Matthew Wang Reviewed-by: Brian Norris Link: https://lore.kernel.org/r/20190822174806.2954-1-matthewmwang@chromium.org Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4565d7385884..8a6cef949210 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2100,6 +2100,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, CMD(add_tx_ts, ADD_TX_TS); CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); CMD(update_connect_params, UPDATE_CONNECT_PARAMS); + CMD(update_ft_ies, UPDATE_FT_IES); } #undef CMD -- GitLab From e740ca86f354038f55978c8ac7bec69b57f0c8e0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Aug 2019 17:15:42 -0300 Subject: [PATCH 4106/7155] perf kvm s390: Add missing string.h header It uses strstr(), needs to include string.h or its not going to build when we remove string.h from the place it is getting from indirectly, by luck. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-72y0i0uiaqght5b83e3ae7p4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/kvm-stat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c index dac78441338c..0fd4e9f49ed0 100644 --- a/tools/perf/arch/s390/util/kvm-stat.c +++ b/tools/perf/arch/s390/util/kvm-stat.c @@ -7,6 +7,7 @@ */ #include +#include #include "../../util/kvm-stat.h" #include "../../util/evsel.h" #include -- GitLab From 0b8026e8fb0ea3893caa2f1924a2c15fcf6760b3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 10:54:14 -0300 Subject: [PATCH 4107/7155] perf metricgroup: Remove needless includes from metricgroup.h There we need just some struct forward declarations, do that instead and add the includes needed by metricgroup.c. That should help with needless rebuilds when changing the removed headers from metricgroup.h. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-1fkskjws6imir2hhztqhdyb0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 3 ++- tools/perf/util/metricgroup.h | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index fdb0d1c5c5cf..aaf55444f81b 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -7,18 +7,19 @@ #include "metricgroup.h" #include "evlist.h" +#include "evsel.h" #include "strbuf.h" #include "pmu.h" #include "expr.h" #include "rblist.h" #include -#include #include #include "pmu-events/pmu-events.h" #include "strlist.h" #include #include #include +#include struct metric_event *metricgroup__lookup(struct rblist *metric_events, struct evsel *evsel, diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 500e828533f8..e5092f6404ae 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -1,11 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-only #ifndef METRICGROUP_H #define METRICGROUP_H 1 -#include "linux/list.h" -#include "rblist.h" -#include -#include "evlist.h" -#include "strbuf.h" +#include +#include +#include + +struct evsel; +struct option; +struct rblist; struct metric_event { struct rb_node nd; -- GitLab From 7646602401e6f45e4013ddb7c41f6bc211032d02 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 11:30:29 -0300 Subject: [PATCH 4108/7155] perf evsel: Move xyarray.h from evsel.c to evsel.h to reduce include dep tree All we need in util/evsel.h is the foward declaration of 'struct xyarray', not the internal/xyarray.h, that can be moved to util/evsel.c and then we reduce the header dependency tree. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-wwqce6ixwcyq6yzx3ljrdm80@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0a33f7322ecc..477c47c84971 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -39,6 +39,7 @@ #include "string2.h" #include "memswap.h" #include "util/parse-branch-options.h" +#include #include diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index efe08065838f..2928eee78427 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "symbol_conf.h" #include "cpumap.h" #include "counts.h" @@ -93,6 +92,7 @@ enum perf_tool_event { }; struct bpf_object; +struct xyarray; /** struct evsel - event selector * -- GitLab From 2d64ae9b85614dc0fcca68aad5da305dec44a9b1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 11:56:13 -0300 Subject: [PATCH 4109/7155] perf counts: Add missing headers needed for types used We get these by sheer luck, since we're cleaning unneeded headers use, this needs to be done first to avoid breakage down the line. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-p7bncbi53t4p2kobkbmu86a4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/counts.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h index 13430f353c19..92196df4945f 100644 --- a/tools/perf/util/counts.h +++ b/tools/perf/util/counts.h @@ -2,8 +2,12 @@ #ifndef __PERF_COUNTS_H #define __PERF_COUNTS_H +#include #include #include +#include + +struct evsel; struct perf_counts { s8 scaled; -- GitLab From 964f384989585bc265fd929b2a7977b83fbe4c3b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 11:57:50 -0300 Subject: [PATCH 4110/7155] perf bpf: Add missing xyarray.h header This was being obtained indirectly via evsel.h -> counts.h, since we don't need xyarray in counts.h, we need to add it here explicitely before removing it from counts.h. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-jirmxg527i82yz31bwad9we7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-loader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 9c219d413e57..e20d7c5e1925 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -26,6 +26,8 @@ #include "llvm-utils.h" #include "c++/clang-c.h" +#include + static int libbpf_perf_print(enum libbpf_print_level level __attribute__((unused)), const char *fmt, va_list args) { -- GitLab From e14e5497d5253712e1545f79ad93309499ffb544 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 13:58:12 -0300 Subject: [PATCH 4111/7155] perf evlist: Add missing xyarray.h header It gets it very indirectly, via evsel.h -> counts.h, and since counts.h doesn't need xyarray.h at all, add it here before we remove it there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-hkizv6gojwfklj9ezaiiztll@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 8582560b59af..68b7c949017e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -37,6 +37,8 @@ #include #include +#include + #ifdef LACKS_SIGQUEUE_PROTOTYPE int sigqueue(pid_t pid, int sig, const union sigval value); #endif -- GitLab From 0f31c0195c14cc37b2f2a08e3f4219d69faa1b34 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:00:17 -0300 Subject: [PATCH 4112/7155] perf script: Add missing counts.h It is getting this via evsel.h, that don't strictly need counts.h, just forward declarations for some structs, so add it here before we remove it from there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-q4shpvlxyjqz7val1hyrdak9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1764efd16cd4..e957b870869b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -3,6 +3,7 @@ #include "perf.h" #include "util/cache.h" +#include "util/counts.h" #include "util/debug.h" #include #include "util/header.h" -- GitLab From e4aec1b1bdad744f3afc3ebf2b337ac1bcfa9be0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:01:24 -0300 Subject: [PATCH 4113/7155] perf tests: Add missing counts.h Those are getting counts.h via evsel.h, that don't strictly need counts.h, just forward declarations for some structs, so add it here before we remove it from there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-phldqlfxxu563txja7evd4zt@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/openat-syscall-all-cpus.c | 1 + tools/perf/tests/openat-syscall.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 8322b6aa4047..4ae4dea07466 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -16,6 +16,7 @@ #include "cpumap.h" #include "debug.h" #include "stat.h" +#include "util/counts.h" int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused) { diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index f217972977e0..58df4bda5e12 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -10,6 +10,7 @@ #include "evsel.h" #include "debug.h" #include "tests.h" +#include "util/counts.h" int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused) { -- GitLab From bfc49182c64e9dbdea494a577894194701b61e72 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:02:05 -0300 Subject: [PATCH 4114/7155] perf stat: Add missing counts.h It is getting this via evsel.h, that don't strictly need counts.h, just forward declarations for some structs, so add it here before we remove it from there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-jwcbm9gv9llloe3he5qkdefs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-display.c | 1 + tools/perf/util/stat.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 3df0e39ccd52..605a1fdbda7a 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -4,6 +4,7 @@ #include #include #include "color.h" +#include "counts.h" #include "evlist.h" #include "evsel.h" #include "stat.h" diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 2715112290cf..1e6a25abe00f 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -2,6 +2,7 @@ #include #include #include +#include "counts.h" #include "stat.h" #include "evlist.h" #include "evsel.h" -- GitLab From 430482c2e34ea8c164240ce295b5f57f16ab5621 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:02:35 -0300 Subject: [PATCH 4115/7155] perf scripting python: Add missing counts.h header It is getting this via evsel.h, that don't strictly need counts.h, just forward declarations for some structs, so add it here before we remove it from there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-6bxk3ltwkw91qcld2ot86bgg@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 32c17a727450..51771fc0d0df 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -32,6 +32,7 @@ #include #include "../../perf.h" +#include "../counts.h" #include "../debug.h" #include "../callchain.h" #include "../evsel.h" -- GitLab From 69714a4e3959eb051e685c6dce06c6d5a8f27c3c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:09:54 -0300 Subject: [PATCH 4116/7155] perf evsel: Add missing perf/evsel.h header in util/evsel.h Since util/evsel.h uses perf_evsel__cpus() that has its prototype in libperf's perf/evsel.h file, we need it explicitely included. This was working by luck as util/evsel.h includes counts.h, but that is not necessary, just some forward declarations, so, before we remove counts.h from util/evsel.h, add what is realli needed. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-nfb9e0t4jm9zhvr0q86hc29d@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 2928eee78427..da91d6f57f44 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "symbol_conf.h" #include "cpumap.h" #include "counts.h" -- GitLab From ddee688a83073a9beebc5c86b67c712de5861411 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:20:54 -0300 Subject: [PATCH 4117/7155] perf evsel: Remove needless counts.h header from util/evsel.h We need only a struct forward declaration, so prune the header dependency tree a bit more. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-oqvgf04w4ku8xasrz79zquim@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 477c47c84971..7b4350681d64 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -26,6 +26,7 @@ #include "asm/bug.h" #include "callchain.h" #include "cgroup.h" +#include "counts.h" #include "event.h" #include "evsel.h" #include "evlist.h" diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index da91d6f57f44..296390541030 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -11,7 +11,6 @@ #include #include "symbol_conf.h" #include "cpumap.h" -#include "counts.h" struct evsel; @@ -93,6 +92,7 @@ enum perf_tool_event { }; struct bpf_object; +struct perf_counts; struct xyarray; /** struct evsel - event selector -- GitLab From a06b7f422d6a759b085ab2988d878b70e2dd0064 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:24:10 -0300 Subject: [PATCH 4118/7155] perf evsel: Remove needless stddef.h from util/evsel.h We added it in 07ac002f2fcc ("perf evsel: Introduce is_group_member method") but we already ditched that function, and there was nothing else left that needed NULL nor anything else from stddef.h, ditch it. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-1zy0xfsy61x81f3fpyx5znco@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 296390541030..1f749a783d8f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -4,7 +4,6 @@ #include #include -#include #include #include #include -- GitLab From 43cc5d5ecbd194a730f3045547afc1fa8e694389 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:44:25 -0300 Subject: [PATCH 4119/7155] perf evsel: util/evsel.h needs stdio.h as it uses FILE And it was getting it by luck from util/cpumap.h that shouldn't be included in util/evsel.h as it only needs what is in libperf, i.e. struct cpu_map, that is in internal/cpumap.h, so add stdio.h before we fix that. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-2ywx5sl031tj3zske7c7edgv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1f749a783d8f..cd336cf2eaa9 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include -- GitLab From 1028f96226b1f4419bd5b56c3d234a83329d4f5b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 14:48:57 -0300 Subject: [PATCH 4120/7155] perf x86 kvm-stat: Add missing string.h header It uses strcmp(), strstr() and was getting the required string.h header by luck, from evsel.h -> cpumap.h -> debug.h -> string.h, add the missing header. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-qrz8hhvrhwnmt5ocfwk4br5d@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/kvm-stat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c index 81b531a707bf..c0775c39227f 100644 --- a/tools/perf/arch/x86/util/kvm-stat.c +++ b/tools/perf/arch/x86/util/kvm-stat.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include "../../../util/kvm-stat.h" #include "../../../util/evsel.h" #include -- GitLab From f7004f5990e230710112b89f2f11777e5e64e258 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Aug 2019 16:39:29 -0300 Subject: [PATCH 4121/7155] perf evsel: Switch to libperf's cpumap.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need what is in perf's util/cpumap.h, just the struct cpu_map that is in libperf's internal/cpumap.h file to cover this one case: tools/perf/util/evsel.h:215:27: error: dereferencing pointer to incomplete type ‘struct perf_cpu_map’ 215 | return evsel__cpus(evsel)->nr; So switch to libperf's cpumap.h and add some missing struct foward declarations and include sys/types.h to get pid_t. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-ufjkpohijti05ggk69s91ktf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index cd336cf2eaa9..5a351cae66df 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -5,14 +5,17 @@ #include #include #include +#include #include #include #include #include #include "symbol_conf.h" -#include "cpumap.h" +#include +struct addr_location; struct evsel; +union perf_event; /* * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are -- GitLab From 5e51b0bb245d963f5ce750256c504be95201e38c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Aug 2019 10:48:31 -0300 Subject: [PATCH 4122/7155] perf cpumap: Remove needless includes from cpumap.h The util/cpumap.h file doesn't use anything in refcount.h not in debug.h, it needs just a forward reference to 'struct cpu_map_data', that is defined in util/event.h and cpumap.h was getting indirectly via, of all things, debug.h Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-mtjww98yptt4ppo6g2blavg5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/header.c | 1 + tools/perf/tests/mem2node.c | 1 + tools/perf/util/cpumap.c | 2 ++ tools/perf/util/cpumap.h | 4 ++-- tools/perf/util/cputopo.c | 2 ++ tools/perf/util/env.c | 1 + tools/perf/util/mem2node.c | 1 + tools/perf/util/pmu.c | 1 + tools/perf/util/svghelper.c | 1 + 9 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c index af9a9f2600be..662ecf84a421 100644 --- a/tools/perf/arch/x86/util/header.c +++ b/tools/perf/arch/x86/util/header.c @@ -6,6 +6,7 @@ #include #include +#include "../../util/debug.h" #include "../../util/header.h" static inline void diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c index 5ec193f7968d..73b2855acaf4 100644 --- a/tools/perf/tests/mem2node.c +++ b/tools/perf/tests/mem2node.c @@ -4,6 +4,7 @@ #include #include #include "cpumap.h" +#include "debug.h" #include "mem2node.h" #include "tests.h" diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 8e6c2cbffedc..f5c21184e1fc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -2,6 +2,8 @@ #include #include "../perf.h" #include "cpumap.h" +#include "debug.h" +#include "event.h" #include #include #include diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 8dbedda7af45..d0c5bbfd91af 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -4,12 +4,12 @@ #include #include -#include #include #include #include "perf.h" -#include "util/debug.h" + +struct cpu_map_data; struct perf_cpu_map *perf_cpu_map__empty_new(int nr); struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 4f70155eaf83..1b52402a8923 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -3,12 +3,14 @@ #include #include #include +#include #include #include #include #include "cputopo.h" #include "cpumap.h" +#include "debug.h" #include "env.h" #define CORE_SIB_FMT \ diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index d77912b2b5e7..571efb4f0351 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "cpumap.h" +#include "debug.h" #include "env.h" #include #include diff --git a/tools/perf/util/mem2node.c b/tools/perf/util/mem2node.c index cacc2fc4dcbd..14fb9e72aeeb 100644 --- a/tools/perf/util/mem2node.c +++ b/tools/perf/util/mem2node.c @@ -2,6 +2,7 @@ #include #include #include +#include "debug.h" #include "mem2node.h" struct phys_entry { diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index b7da21a7d627..9807be6f09bb 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -16,6 +16,7 @@ #include #include #include +#include "debug.h" #include "pmu.h" #include "parse-events.h" #include "cpumap.h" diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index ae6a534a7a80..bbdd87163285 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include -- GitLab From a2f354e3abb853f9a40048829e1f839e8f7fada5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 22 Aug 2019 13:11:41 +0200 Subject: [PATCH 4123/7155] libperf: Add perf_thread_map__nr/perf_thread_map__pid functions So it's part of libperf library as basic functions operating on perf_thread_map objects. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190822111141.25823-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-ftrace.c | 2 +- tools/perf/builtin-script.c | 4 ++-- tools/perf/builtin-stat.c | 4 ++-- tools/perf/builtin-trace.c | 4 ++-- tools/perf/lib/include/perf/threadmap.h | 2 ++ tools/perf/lib/libperf.map | 2 ++ tools/perf/lib/threadmap.c | 10 ++++++++++ tools/perf/tests/thread-map.c | 6 +++--- tools/perf/util/auxtrace.c | 4 ++-- tools/perf/util/event.c | 8 ++++---- tools/perf/util/evlist.c | 12 ++++++------ tools/perf/util/evsel.c | 4 ++-- .../perf/util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/stat-display.c | 4 ++-- tools/perf/util/stat.c | 4 ++-- tools/perf/util/thread_map.c | 4 ++-- tools/perf/util/thread_map.h | 10 ---------- 17 files changed, 45 insertions(+), 41 deletions(-) diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 1367bb5046a7..565db782c1b9 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -158,7 +158,7 @@ static int set_tracing_pid(struct perf_ftrace *ftrace) if (target__has_cpu(&ftrace->target)) return 0; - for (i = 0; i < thread_map__nr(ftrace->evlist->core.threads); i++) { + for (i = 0; i < perf_thread_map__nr(ftrace->evlist->core.threads); i++) { scnprintf(buf, sizeof(buf), "%d", ftrace->evlist->core.threads->map[i]); if (append_tracing_file("set_ftrace_pid", buf) < 0) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index e957b870869b..9b93ddeaeafa 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1906,7 +1906,7 @@ static struct scripting_ops *scripting_ops; static void __process_stat(struct evsel *counter, u64 tstamp) { - int nthreads = thread_map__nr(counter->core.threads); + int nthreads = perf_thread_map__nr(counter->core.threads); int ncpus = perf_evsel__nr_cpus(counter); int cpu, thread; static int header_printed; @@ -1928,7 +1928,7 @@ static void __process_stat(struct evsel *counter, u64 tstamp) printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n", counter->core.cpus->map[cpu], - thread_map__pid(counter->core.threads, thread), + perf_thread_map__pid(counter->core.threads, thread), counts->val, counts->ena, counts->run, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 90636a811b36..8a4f1a7d0cba 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -264,7 +264,7 @@ static int read_single_counter(struct evsel *counter, int cpu, */ static int read_counter(struct evsel *counter, struct timespec *rs) { - int nthreads = thread_map__nr(evsel_list->core.threads); + int nthreads = perf_thread_map__nr(evsel_list->core.threads); int ncpus, cpu, thread; if (target__has_cpu(&target) && !target__has_per_thread(&target)) @@ -1893,7 +1893,7 @@ int cmd_stat(int argc, const char **argv) thread_map__read_comms(evsel_list->core.threads); if (target.system_wide) { if (runtime_stat_new(&stat_config, - thread_map__nr(evsel_list->core.threads))) { + perf_thread_map__nr(evsel_list->core.threads))) { goto out; } } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index bc44ed29e05a..de126258ca10 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3188,7 +3188,7 @@ static int trace__set_filter_pids(struct trace *trace) err = bpf_map__set_filter_pids(trace->filter_pids.map, trace->filter_pids.nr, trace->filter_pids.entries); } - } else if (thread_map__pid(trace->evlist->core.threads, 0) == -1) { + } else if (perf_thread_map__pid(trace->evlist->core.threads, 0) == -1) { err = trace__set_filter_loop_pids(trace); } @@ -3417,7 +3417,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) evlist__enable(evlist); } - trace->multiple_threads = thread_map__pid(evlist->core.threads, 0) == -1 || + trace->multiple_threads = perf_thread_map__pid(evlist->core.threads, 0) == -1 || evlist->core.threads->nr > 1 || perf_evlist__first(evlist)->core.attr.inherit; diff --git a/tools/perf/lib/include/perf/threadmap.h b/tools/perf/lib/include/perf/threadmap.h index 456295273daa..a7c50de8d010 100644 --- a/tools/perf/lib/include/perf/threadmap.h +++ b/tools/perf/lib/include/perf/threadmap.h @@ -11,6 +11,8 @@ LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void); LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid); LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int thread); +LIBPERF_API int perf_thread_map__nr(struct perf_thread_map *threads); +LIBPERF_API pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread); LIBPERF_API struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map); LIBPERF_API void perf_thread_map__put(struct perf_thread_map *map); diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 3373dd51fcda..dc4d66363bc4 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -12,6 +12,8 @@ LIBPERF_0.0.1 { perf_thread_map__new_dummy; perf_thread_map__set_pid; perf_thread_map__comm; + perf_thread_map__nr; + perf_thread_map__pid; perf_thread_map__get; perf_thread_map__put; perf_evsel__new; diff --git a/tools/perf/lib/threadmap.c b/tools/perf/lib/threadmap.c index 4865b73e2586..e92c368b0a6c 100644 --- a/tools/perf/lib/threadmap.c +++ b/tools/perf/lib/threadmap.c @@ -79,3 +79,13 @@ void perf_thread_map__put(struct perf_thread_map *map) if (map && refcount_dec_and_test(&map->refcnt)) perf_thread_map__delete(map); } + +int perf_thread_map__nr(struct perf_thread_map *threads) +{ + return threads ? threads->nr : 1; +} + +pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread) +{ + return map->map[thread].pid; +} diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c index d61773cacf0b..d803eafedc60 100644 --- a/tools/perf/tests/thread-map.c +++ b/tools/perf/tests/thread-map.c @@ -26,7 +26,7 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", - thread_map__pid(map, 0) == getpid()); + perf_thread_map__pid(map, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", perf_thread_map__comm(map, 0) && !strcmp(perf_thread_map__comm(map, 0), NAME)); @@ -41,7 +41,7 @@ int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unuse thread_map__read_comms(map); TEST_ASSERT_VAL("wrong nr", map->nr == 1); - TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1); + TEST_ASSERT_VAL("wrong pid", perf_thread_map__pid(map, 0) == -1); TEST_ASSERT_VAL("wrong comm", perf_thread_map__comm(map, 0) && !strcmp(perf_thread_map__comm(map, 0), "dummy")); @@ -68,7 +68,7 @@ static int process_event(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong nr", threads->nr == 1); TEST_ASSERT_VAL("wrong pid", - thread_map__pid(threads, 0) == getpid()); + perf_thread_map__pid(threads, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", perf_thread_map__comm(threads, 0) && !strcmp(perf_thread_map__comm(threads, 0), NAME)); diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 60428576426e..094e6ceb3cf2 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -132,12 +132,12 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, if (per_cpu) { mp->cpu = evlist->core.cpus->map[idx]; if (evlist->core.threads) - mp->tid = thread_map__pid(evlist->core.threads, 0); + mp->tid = perf_thread_map__pid(evlist->core.threads, 0); else mp->tid = -1; } else { mp->cpu = -1; - mp->tid = thread_map__pid(evlist->core.threads, idx); + mp->tid = perf_thread_map__pid(evlist->core.threads, idx); } } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f433da85c45e..332edef8d394 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -647,7 +647,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, fork_event, namespaces_event, - thread_map__pid(threads, thread), 0, + perf_thread_map__pid(threads, thread), 0, process, tool, machine, mmap_data)) { err = -1; @@ -658,12 +658,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, * comm.pid is set to thread group id by * perf_event__synthesize_comm */ - if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) { + if ((int) comm_event->comm.pid != perf_thread_map__pid(threads, thread)) { bool need_leader = true; /* is thread group leader in thread_map? */ for (j = 0; j < threads->nr; ++j) { - if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) { + if ((int) comm_event->comm.pid == perf_thread_map__pid(threads, j)) { need_leader = false; break; } @@ -997,7 +997,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, if (!comm) comm = (char *) ""; - entry->pid = thread_map__pid(threads, i); + entry->pid = perf_thread_map__pid(threads, i); strncpy((char *) &entry->comm, comm, sizeof(entry->comm)); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 68b7c949017e..ff415680fe0a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -316,7 +316,7 @@ static int perf_evlist__nr_threads(struct evlist *evlist, if (evsel->system_wide) return 1; else - return thread_map__nr(evlist->core.threads); + return perf_thread_map__nr(evlist->core.threads); } void evlist__disable(struct evlist *evlist) @@ -399,7 +399,7 @@ int perf_evlist__enable_event_idx(struct evlist *evlist, int perf_evlist__alloc_pollfd(struct evlist *evlist) { int nr_cpus = perf_cpu_map__nr(evlist->core.cpus); - int nr_threads = thread_map__nr(evlist->core.threads); + int nr_threads = perf_thread_map__nr(evlist->core.threads); int nfds = 0; struct evsel *evsel; @@ -531,7 +531,7 @@ static void perf_evlist__set_sid_idx(struct evlist *evlist, else sid->cpu = -1; if (!evsel->system_wide && evlist->core.threads && thread >= 0) - sid->tid = thread_map__pid(evlist->core.threads, thread); + sid->tid = perf_thread_map__pid(evlist->core.threads, thread); else sid->tid = -1; } @@ -696,7 +696,7 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct evlist *evlist, evlist->nr_mmaps = perf_cpu_map__nr(evlist->core.cpus); if (perf_cpu_map__empty(evlist->core.cpus)) - evlist->nr_mmaps = thread_map__nr(evlist->core.threads); + evlist->nr_mmaps = perf_thread_map__nr(evlist->core.threads); map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); if (!map) return NULL; @@ -810,7 +810,7 @@ static int perf_evlist__mmap_per_cpu(struct evlist *evlist, { int cpu, thread; int nr_cpus = perf_cpu_map__nr(evlist->core.cpus); - int nr_threads = thread_map__nr(evlist->core.threads); + int nr_threads = perf_thread_map__nr(evlist->core.threads); pr_debug2("perf event ring buffer mmapped per cpu\n"); for (cpu = 0; cpu < nr_cpus; cpu++) { @@ -838,7 +838,7 @@ static int perf_evlist__mmap_per_thread(struct evlist *evlist, struct mmap_params *mp) { int thread; - int nr_threads = thread_map__nr(evlist->core.threads); + int nr_threads = perf_thread_map__nr(evlist->core.threads); pr_debug2("perf event ring buffer mmapped per thread\n"); for (thread = 0; thread < nr_threads; thread++) { diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7b4350681d64..e983e721beca 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1653,7 +1653,7 @@ static bool ignore_missing_thread(struct evsel *evsel, struct perf_thread_map *threads, int thread, int err) { - pid_t ignore_pid = thread_map__pid(threads, thread); + pid_t ignore_pid = perf_thread_map__pid(threads, thread); if (!evsel->ignore_missing_thread) return false; @@ -1816,7 +1816,7 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, int fd, group_fd; if (!evsel->cgrp && !evsel->system_wide) - pid = thread_map__pid(threads, thread); + pid = perf_thread_map__pid(threads, thread); group_fd = get_group_fd(evsel, cpu, thread); retry_open: diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 51771fc0d0df..78c8bc9380bd 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1406,7 +1406,7 @@ static void python_process_stat(struct perf_stat_config *config, for (thread = 0; thread < threads->nr; thread++) { for (cpu = 0; cpu < cpus->nr; cpu++) { process_stat(counter, cpus->map[cpu], - thread_map__pid(threads, thread), tstamp, + perf_thread_map__pid(threads, thread), tstamp, perf_counts(counter->counts, cpu, thread)); } } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 605a1fdbda7a..51d6781aa90d 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -119,7 +119,7 @@ static void aggr_printout(struct perf_stat_config *config, config->csv_output ? 0 : 16, perf_thread_map__comm(evsel->core.threads, id), config->csv_output ? 0 : -8, - thread_map__pid(evsel->core.threads, id), + perf_thread_map__pid(evsel->core.threads, id), config->csv_sep); break; case AGGR_GLOBAL: @@ -745,7 +745,7 @@ static void print_aggr_thread(struct perf_stat_config *config, struct evsel *counter, char *prefix) { FILE *output = config->output; - int nthreads = thread_map__nr(counter->core.threads); + int nthreads = perf_thread_map__nr(counter->core.threads); int ncpus = perf_cpu_map__nr(counter->core.cpus); int thread, sorted_threads, id; struct perf_aggr_thread_value *buf; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 1e6a25abe00f..0cbfd1eca1dd 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -159,7 +159,7 @@ static void perf_evsel__free_prev_raw_counts(struct evsel *evsel) static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw) { int ncpus = perf_evsel__nr_cpus(evsel); - int nthreads = thread_map__nr(evsel->core.threads); + int nthreads = perf_thread_map__nr(evsel->core.threads); if (perf_evsel__alloc_stat_priv(evsel) < 0 || perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || @@ -309,7 +309,7 @@ process_counter_values(struct perf_stat_config *config, struct evsel *evsel, static int process_counter_maps(struct perf_stat_config *config, struct evsel *counter) { - int nthreads = thread_map__nr(counter->core.threads); + int nthreads = perf_thread_map__nr(counter->core.threads); int ncpus = perf_evsel__nr_cpus(counter); int cpu, thread; diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index c58385ea05be..3e64525bf604 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -310,7 +310,7 @@ size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp) size_t printed = fprintf(fp, "%d thread%s: ", threads->nr, threads->nr > 1 ? "s" : ""); for (i = 0; i < threads->nr; ++i) - printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i)); + printed += fprintf(fp, "%s%d", i ? ", " : "", perf_thread_map__pid(threads, i)); return printed + fprintf(fp, "\n"); } @@ -341,7 +341,7 @@ static int get_comm(char **comm, pid_t pid) static void comm_init(struct perf_thread_map *map, int i) { - pid_t pid = thread_map__pid(map, i); + pid_t pid = perf_thread_map__pid(map, i); char *comm = NULL; /* dummy pid comm initialization */ diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index ba45c760be72..ca165fdf6cb0 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -25,16 +25,6 @@ struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str); size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp); -static inline int thread_map__nr(struct perf_thread_map *threads) -{ - return threads ? threads->nr : 1; -} - -static inline pid_t thread_map__pid(struct perf_thread_map *map, int thread) -{ - return map->map[thread].pid; -} - void thread_map__read_comms(struct perf_thread_map *threads); bool thread_map__has(struct perf_thread_map *threads, pid_t pid); int thread_map__remove(struct perf_thread_map *threads, int idx); -- GitLab From 1ea770f6c1971bc101b3741f4d88b0b4ea5c4181 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Thu, 22 Aug 2019 14:20:45 +0530 Subject: [PATCH 4124/7155] perf c2c: Fix report with offline cpus If c2c is recorded on a machine where any cpus are offline, 'perf c2c report' throws an error "node/cpu topology bugFailed setup nodes". It fails because while preparing node-cpu mapping we don't consider offline cpus. Reported-by: Nageswara R Sastry Signed-off-by: Ravi Bangoria Acked-by: Jiri Olsa Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key") Link: http://lkml.kernel.org/r/20190822085045.25108-1-ravi.bangoria@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 01629f5b6d1f..211143720078 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2027,7 +2027,7 @@ static int setup_nodes(struct perf_session *session) c2c.node_info = 2; c2c.nodes_cnt = session->header.env.nr_numa_nodes; - c2c.cpus_cnt = session->header.env.nr_cpus_online; + c2c.cpus_cnt = session->header.env.nr_cpus_avail; n = session->header.env.numa_nodes; if (!n) -- GitLab From d9c5c083416500e95da098c01be092b937def7fa Mon Sep 17 00:00:00 2001 From: Gerald BAEZA Date: Thu, 22 Aug 2019 09:07:01 +0000 Subject: [PATCH 4125/7155] libperf: Fix alignment trap with xyarray contents in 'perf stat' Following the patch 'perf stat: Fix --no-scale', an alignment trap happens in process_counter_values() on ARMv7 platforms due to the attempt to copy non 64 bits aligned double words (pointed by 'count') via a NEON vectored instruction ('vld1' with 64 bits alignment constraint). This patch sets a 64 bits alignment constraint on 'contents[]' field in 'struct xyarray' since the 'count' pointer used above points to such a structure. Signed-off-by: Gerald Baeza Cc: Alexander Shishkin Cc: Alexandre Torgue Cc: Andi Kleen Cc: Jiri Olsa Cc: Mathieu Poirier Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1566464769-16374-1-git-send-email-gerald.baeza@st.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/lib/include/internal/xyarray.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/lib/include/internal/xyarray.h b/tools/perf/lib/include/internal/xyarray.h index 3bf70e4d474c..51e35d6c8ec4 100644 --- a/tools/perf/lib/include/internal/xyarray.h +++ b/tools/perf/lib/include/internal/xyarray.h @@ -2,6 +2,7 @@ #ifndef __LIBPERF_INTERNAL_XYARRAY_H #define __LIBPERF_INTERNAL_XYARRAY_H +#include #include struct xyarray { @@ -10,7 +11,7 @@ struct xyarray { size_t entries; size_t max_x; size_t max_y; - char contents[]; + char contents[] __aligned(8); }; struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size); -- GitLab From 33b165684ab70867d4545643f550a5d48d3ddc57 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 15 Jul 2019 14:35:07 +0200 Subject: [PATCH 4126/7155] i40e: reduce stack usage in i40e_set_fc The functions i40e_aq_get_phy_abilities_resp() and i40e_set_fc() both have giant structure on the stack, which makes each one use stack frames larger than 500 bytes. As clang decides one function into the other, we get a warning for exceeding the frame size limit on 32-bit architectures: drivers/net/ethernet/intel/i40e/i40e_common.c:1654:23: error: stack frame size of 1116 bytes in function 'i40e_set_fc' [-Werror,-Wframe-larger-than=] When building with gcc, the inlining does not happen, but i40e_set_fc() calls i40e_aq_get_phy_abilities_resp() anyway, so they add up on the kernel stack just as much. The parts that actually use large stacks don't overlap, so make sure each one is a separate function, and mark them as noinline_for_stack to prevent the compilers from combining them again. Fixes: 0a862b43acc6 ("i40e/i40evf: Add module_types and update_link_info") Signed-off-by: Arnd Bergmann Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 906cf68d3453..7af1b7477140 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1643,25 +1643,15 @@ enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, return status; } -/** - * i40e_set_fc - * @hw: pointer to the hw struct - * @aq_failures: buffer to return AdminQ failure information - * @atomic_restart: whether to enable atomic link restart - * - * Set the requested flow control mode using set_phy_config. - **/ -enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, - bool atomic_restart) +static noinline_for_stack enum i40e_status_code +i40e_set_fc_status(struct i40e_hw *hw, + struct i40e_aq_get_phy_abilities_resp *abilities, + bool atomic_restart) { - enum i40e_fc_mode fc_mode = hw->fc.requested_mode; - struct i40e_aq_get_phy_abilities_resp abilities; struct i40e_aq_set_phy_config config; - enum i40e_status_code status; + enum i40e_fc_mode fc_mode = hw->fc.requested_mode; u8 pause_mask = 0x0; - *aq_failures = 0x0; - switch (fc_mode) { case I40E_FC_FULL: pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX; @@ -1677,6 +1667,48 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, break; } + memset(&config, 0, sizeof(struct i40e_aq_set_phy_config)); + /* clear the old pause settings */ + config.abilities = abilities->abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) & + ~(I40E_AQ_PHY_FLAG_PAUSE_RX); + /* set the new abilities */ + config.abilities |= pause_mask; + /* If the abilities have changed, then set the new config */ + if (config.abilities == abilities->abilities) + return 0; + + /* Auto restart link so settings take effect */ + if (atomic_restart) + config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; + /* Copy over all the old settings */ + config.phy_type = abilities->phy_type; + config.phy_type_ext = abilities->phy_type_ext; + config.link_speed = abilities->link_speed; + config.eee_capability = abilities->eee_capability; + config.eeer = abilities->eeer_val; + config.low_power_ctrl = abilities->d3_lpan; + config.fec_config = abilities->fec_cfg_curr_mod_ext_info & + I40E_AQ_PHY_FEC_CONFIG_MASK; + + return i40e_aq_set_phy_config(hw, &config, NULL); +} + +/** + * i40e_set_fc + * @hw: pointer to the hw struct + * @aq_failures: buffer to return AdminQ failure information + * @atomic_restart: whether to enable atomic link restart + * + * Set the requested flow control mode using set_phy_config. + **/ +enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, + bool atomic_restart) +{ + struct i40e_aq_get_phy_abilities_resp abilities; + enum i40e_status_code status; + + *aq_failures = 0x0; + /* Get the current phy config */ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, NULL); @@ -1685,31 +1717,10 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, return status; } - memset(&config, 0, sizeof(struct i40e_aq_set_phy_config)); - /* clear the old pause settings */ - config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) & - ~(I40E_AQ_PHY_FLAG_PAUSE_RX); - /* set the new abilities */ - config.abilities |= pause_mask; - /* If the abilities have changed, then set the new config */ - if (config.abilities != abilities.abilities) { - /* Auto restart link so settings take effect */ - if (atomic_restart) - config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; - /* Copy over all the old settings */ - config.phy_type = abilities.phy_type; - config.phy_type_ext = abilities.phy_type_ext; - config.link_speed = abilities.link_speed; - config.eee_capability = abilities.eee_capability; - config.eeer = abilities.eeer_val; - config.low_power_ctrl = abilities.d3_lpan; - config.fec_config = abilities.fec_cfg_curr_mod_ext_info & - I40E_AQ_PHY_FEC_CONFIG_MASK; - status = i40e_aq_set_phy_config(hw, &config, NULL); + status = i40e_set_fc_status(hw, &abilities, atomic_restart); + if (status) + *aq_failures |= I40E_SET_FC_AQ_FAIL_SET; - if (status) - *aq_failures |= I40E_SET_FC_AQ_FAIL_SET; - } /* Update the link info */ status = i40e_update_link_info(hw); if (status) { @@ -2537,7 +2548,7 @@ i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up) * i40e_updatelink_status - update status of the HW network link * @hw: pointer to the hw struct **/ -i40e_status i40e_update_link_info(struct i40e_hw *hw) +noinline_for_stack i40e_status i40e_update_link_info(struct i40e_hw *hw) { struct i40e_aq_get_phy_abilities_resp abilities; i40e_status status = 0; -- GitLab From bc6c1eaaedee7bb1bbdef27e155f15510128762e Mon Sep 17 00:00:00 2001 From: "Mauro S. M. Rodrigues" Date: Thu, 18 Jul 2019 14:52:02 -0300 Subject: [PATCH 4127/7155] i40e: Check if transceiver implements DDM before access Similar to the ixgbe issue fixed in: 655c91414579 ("ixgbe: Check DDM existence in transceiver before access) i40e has the same issue when reading eeprom from SFP's module that comply with SFF-8472 but not implement the Digital Diagnostic Monitoring (DDM) interface described in it. The existence of such area is specified by bit 6 of byte 92, set to 1 if implemented. Without this patch, due to not checking this bit i40e fails to read SFP module's eeprom with the follow message: ethtool -m enP51p1s0f0 Cannot get Module EEPROM data: Input/output error Because it fails to read the additional 256 bytes in which it was assumed to exist the DDM data. Signed-off-by: "Mauro S. M. Rodrigues" Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 ++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 01e4615b1b4b..41e1240acaea 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -5137,6 +5137,12 @@ static int i40e_get_module_info(struct net_device *netdev, /* Module is not SFF-8472 compliant */ modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; + } else if (!(sff8472_swap & I40E_MODULE_SFF_DDM_IMPLEMENTED)) { + /* Module is SFF-8472 compliant but doesn't implement + * Digital Diagnostic Monitoring (DDM). + */ + modinfo->type = ETH_MODULE_SFF_8079; + modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; } else { modinfo->type = ETH_MODULE_SFF_8472; modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 8f43aa47c263..2a6219d66771 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -443,6 +443,7 @@ struct i40e_nvm_access { #define I40E_MODULE_SFF_8472_COMP 0x5E #define I40E_MODULE_SFF_8472_SWAP 0x5C #define I40E_MODULE_SFF_ADDR_MODE 0x04 +#define I40E_MODULE_SFF_DDM_IMPLEMENTED 0x40 #define I40E_MODULE_TYPE_QSFP_PLUS 0x0D #define I40E_MODULE_TYPE_QSFP28 0x11 #define I40E_MODULE_QSFP_MAX_LEN 640 -- GitLab From 408bfc382efca14cc02c57ae935d5b7efd72e02a Mon Sep 17 00:00:00 2001 From: huhai Date: Mon, 22 Jul 2019 19:55:59 +0800 Subject: [PATCH 4128/7155] i40e: add check on i40e_configure_tx_ring() return value When i40e_configure_tx_ring(vsi->tx_rings[i]) returns an error, we should exit from i40e_vsi_configure_tx and return the error, instead of continuing to check whether xdp is enable, and configure the xdp transmit ring. Signed-off-by: huhai Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 6d456e579314..b807dd6b1417 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3364,7 +3364,7 @@ static int i40e_vsi_configure_tx(struct i40e_vsi *vsi) for (i = 0; (i < vsi->num_queue_pairs) && !err; i++) err = i40e_configure_tx_ring(vsi->tx_rings[i]); - if (!i40e_enabled_xdp_vsi(vsi)) + if (err || !i40e_enabled_xdp_vsi(vsi)) return err; for (i = 0; (i < vsi->num_queue_pairs) && !err; i++) -- GitLab From fb59826288a662e0a0c1934d7d068dc91f35764d Mon Sep 17 00:00:00 2001 From: Beilei Xing Date: Tue, 23 Jul 2019 06:01:33 -0400 Subject: [PATCH 4129/7155] i40e: fix shifts of signed values This patch fixes following error reported by cppcheck: (error) Shifting signed 32-bit value by 31 bits is undefined behaviour Signed-off-by: Beilei Xing Signed-off-by: Ferruh Yigit Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/i40e/i40e_register.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 52e3680c57f8..330ac19a5dae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -58,7 +58,7 @@ #define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30 #define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT) #define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31 -#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT) +#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1u, I40E_PF_ARQLEN_ARQENABLE_SHIFT) #define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */ #define I40E_PF_ARQT_ARQT_SHIFT 0 #define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT) @@ -81,7 +81,7 @@ #define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30 #define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT) #define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31 -#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT) +#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1u, I40E_PF_ATQLEN_ATQENABLE_SHIFT) #define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */ #define I40E_PF_ATQT_ATQT_SHIFT 0 #define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT) @@ -108,7 +108,7 @@ #define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30 #define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT) #define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31 -#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT) +#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1u, I40E_VF_ARQLEN_ARQENABLE_SHIFT) #define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQT_MAX_INDEX 127 #define I40E_VF_ARQT_ARQT_SHIFT 0 @@ -136,7 +136,7 @@ #define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30 #define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT) #define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31 -#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT) +#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1u, I40E_VF_ATQLEN_ATQENABLE_SHIFT) #define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQT_MAX_INDEX 127 #define I40E_VF_ATQT_ATQT_SHIFT 0 @@ -259,7 +259,7 @@ #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30 #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) #define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31 -#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) +#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1u, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) #define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */ #define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0 #define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT) @@ -503,7 +503,7 @@ #define I40E_GLGEN_MSCA_MDICMD_SHIFT 30 #define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT) #define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31 -#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT) +#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1u, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT) #define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_MSRWD_MAX_INDEX 3 #define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0 @@ -1242,14 +1242,14 @@ #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30 #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT) #define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31 -#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT) +#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1u, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT) #define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */ #define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0 #define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT) #define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16 #define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT) #define I40E_PFLAN_QALLOC_VALID_SHIFT 31 -#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT) +#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1u, I40E_PFLAN_QALLOC_VALID_SHIFT) #define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */ #define I40E_QRX_ENA_MAX_INDEX 1535 #define I40E_QRX_ENA_QENA_REQ_SHIFT 0 @@ -1658,7 +1658,7 @@ #define I40E_GLNVM_SRCTL_START_SHIFT 30 #define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT) #define I40E_GLNVM_SRCTL_DONE_SHIFT 31 -#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT) +#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1u, I40E_GLNVM_SRCTL_DONE_SHIFT) #define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */ #define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0 #define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT) @@ -3025,7 +3025,7 @@ #define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8 #define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT) #define I40E_PF_VT_PFALLOC_VALID_SHIFT 31 -#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT) +#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1u, I40E_PF_VT_PFALLOC_VALID_SHIFT) #define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VP_MDET_RX_MAX_INDEX 127 #define I40E_VP_MDET_RX_VALID_SHIFT 0 @@ -3161,7 +3161,7 @@ #define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30 #define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT) #define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31 -#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT) +#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1u, I40E_VF_ARQLEN1_ARQENABLE_SHIFT) #define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */ #define I40E_VF_ARQT1_ARQT_SHIFT 0 #define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT) @@ -3184,7 +3184,7 @@ #define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30 #define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT) #define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31 -#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT) +#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1u, I40E_VF_ATQLEN1_ATQENABLE_SHIFT) #define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */ #define I40E_VF_ATQT1_ATQT_SHIFT 0 #define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT) -- GitLab From d802c760ab87bc0d98e7517b766cf1b9f186fe65 Mon Sep 17 00:00:00 2001 From: Sylwia Wnuczko Date: Tue, 23 Jul 2019 06:01:34 -0400 Subject: [PATCH 4130/7155] i40e: Add drop mode parameter to set mac config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds "drop mode" parameter to set mac config AQ command. This bit controls the behavior when a no-drop packet is blocking a TC queue. 0 – The PF driver is notified. 1 – The blocking packet is dropped and then the PF driver is notified. Signed-off-by: Sylwia Wnuczko Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 4 ++- .../net/ethernet/intel/i40e/i40e_adminq_cmd.h | 29 ++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 814acbe79ffd..72c04881d290 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -610,8 +610,10 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) if (hw->aq.api_maj_ver > 1 || (hw->aq.api_maj_ver == 1 && - hw->aq.api_min_ver >= 8)) + hw->aq.api_min_ver >= 8)) { hw->flags |= I40E_HW_FLAG_FW_LLDP_PERSISTENT; + hw->flags |= I40E_HW_FLAG_DROP_MODE; + } if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) { ret_code = I40E_ERR_FIRMWARE_API_VERSION; diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 6536023fa074..4d966d80305f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -2051,20 +2051,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); struct i40e_aq_set_mac_config { __le16 max_frame_size; u8 params; -#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 -#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 -#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 -#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 -#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 -#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 +#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 +#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 +#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 +#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 +#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 +#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 +#define I40E_AQ_SET_MAC_CONFIG_DROP_BLOCKING_PACKET_EN 0x80 u8 tx_timer_priority; /* bitmap */ __le16 tx_timer_value; __le16 fc_refresh_threshold; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 2a6219d66771..7c1d57683b53 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -624,6 +624,7 @@ struct i40e_hw { #define I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK BIT_ULL(3) #define I40E_HW_FLAG_FW_LLDP_STOPPABLE BIT_ULL(4) #define I40E_HW_FLAG_FW_LLDP_PERSISTENT BIT_ULL(5) +#define I40E_HW_FLAG_DROP_MODE BIT_ULL(7) u64 flags; /* Used in set switch config AQ command */ -- GitLab From d4256c8e9a7fab6e6c5cc3aa52ef7d2ff543b1ff Mon Sep 17 00:00:00 2001 From: Adrian Podlawski Date: Tue, 23 Jul 2019 06:01:35 -0400 Subject: [PATCH 4131/7155] i40e: check_recovery_mode had wrong if statement Function check_recovery_mode had wrong if statement. Now we check proper FWS1B register values, which are responsible for the recovery mode. Recovery mode has 4 values for x710 and 2 for x722. That's why we need 6 different flags which are defined in the code. Now in the if statement, we recognize type of mac address and register value. Without those changes driver could show wrong state. Signed-off-by: Adrian Podlawski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 17 ++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_register.h | 6 ++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b807dd6b1417..4551d97771c9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -14578,9 +14578,20 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags) **/ static bool i40e_check_recovery_mode(struct i40e_pf *pf) { - u32 val = rd32(&pf->hw, I40E_GL_FWSTS); - - if (val & I40E_GL_FWSTS_FWS1B_MASK) { + u32 val = rd32(&pf->hw, I40E_GL_FWSTS) & I40E_GL_FWSTS_FWS1B_MASK; + bool is_recovery_mode = false; + + if (pf->hw.mac.type == I40E_MAC_XL710) + is_recovery_mode = + val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK || + val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK || + val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_TRANSITION_MASK || + val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_NVM_MASK; + if (pf->hw.mac.type == I40E_MAC_X722) + is_recovery_mode = + val == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK || + val == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK; + if (is_recovery_mode) { dev_notice(&pf->pdev->dev, "Firmware recovery mode detected. Limiting functionality.\n"); dev_notice(&pf->pdev->dev, "Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n"); set_bit(__I40E_RECOVERY_MODE, pf->state); diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 330ac19a5dae..d35d690ca10f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -363,6 +363,12 @@ #define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT) #define I40E_GL_FWSTS_FWS1B_SHIFT 16 #define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK I40E_MASK(0x30, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK I40E_MASK(0x31, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_TRANSITION_MASK I40E_MASK(0x32, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_NVM_MASK I40E_MASK(0x33, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_X722_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK I40E_MASK(0xB, I40E_GL_FWSTS_FWS1B_SHIFT) +#define I40E_X722_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK I40E_MASK(0xC, I40E_GL_FWSTS_FWS1B_SHIFT) #define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */ #define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0 #define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT) -- GitLab From f93b3fd9a34ba8ac2228e219e05259e503325ab7 Mon Sep 17 00:00:00 2001 From: Piotr Azarewicz Date: Tue, 23 Jul 2019 06:01:36 -0400 Subject: [PATCH 4132/7155] i40e: Update FW API version to 1.9 Upcoming FW increment API version to 1.9 due to Extend PHY access AQ command support. SW is ready for that support as well. Signed-off-by: Piotr Azarewicz Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 4d966d80305f..21cccec328e3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -11,8 +11,8 @@ */ #define I40E_FW_API_VERSION_MAJOR 0x0001 -#define I40E_FW_API_VERSION_MINOR_X722 0x0008 -#define I40E_FW_API_VERSION_MINOR_X710 0x0008 +#define I40E_FW_API_VERSION_MINOR_X722 0x0009 +#define I40E_FW_API_VERSION_MINOR_X710 0x0009 #define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \ I40E_FW_API_VERSION_MINOR_X710 : \ -- GitLab From 1e0303fd29428e3e3bbd8edf72f80750f86a7116 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 23 Jul 2019 06:01:37 -0400 Subject: [PATCH 4133/7155] i40e: reset veb.tc_stats when resetting veb.stats The stats structure for the VEB switch statistics is reset periodically, but the tc_stats are not reset at the same time. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4551d97771c9..5c280c025085 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -534,6 +534,10 @@ void i40e_pf_reset_stats(struct i40e_pf *pf) sizeof(pf->veb[i]->stats)); memset(&pf->veb[i]->stats_offsets, 0, sizeof(pf->veb[i]->stats_offsets)); + memset(&pf->veb[i]->tc_stats, 0, + sizeof(pf->veb[i]->tc_stats)); + memset(&pf->veb[i]->tc_stats_offsets, 0, + sizeof(pf->veb[i]->tc_stats_offsets)); pf->veb[i]->stat_offsets_loaded = false; } } -- GitLab From 9889707b06acfe9bb37a6edcaae627d4a5eacc72 Mon Sep 17 00:00:00 2001 From: Slawomir Laba Date: Tue, 23 Jul 2019 06:01:39 -0400 Subject: [PATCH 4134/7155] i40e: Fix crash caused by stress setting of VF MAC addresses Add update to the VSI pointer passed to the i40e_set_vf_mac function. If VF is in reset state the driver waits in i40e_set_vf_mac function for the reset to be complete, yet after reset the vsi pointer that was passed into this function is no longer valid. The patch updates local VSI pointer directly from pf->vsi array, by using the id stored in VF pointer (lan_vsi_idx). Without this commit the driver might occasionally invoke general protection fault in kernel and disable the OS entirely. Signed-off-by: Slawomir Laba Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 4601f9e4e998..f8aa4deceb5e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -3967,10 +3967,15 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) /* When the VF is resetting wait until it is done. * It can take up to 200 milliseconds, * but wait for up to 300 milliseconds to be safe. + * If the VF is indeed in reset, the vsi pointer has + * to show on the newly loaded vsi under pf->vsi[id]. */ for (i = 0; i < 15; i++) { - if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) + if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { + if (i > 0) + vsi = pf->vsi[vf->lan_vsi_idx]; break; + } msleep(20); } if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { -- GitLab From 541d97310ae3c02675578a236674e0bea1ad6483 Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Tue, 23 Jul 2019 06:01:40 -0400 Subject: [PATCH 4135/7155] i40e: Remove function i40e_update_dcb_config() This patch removes function i40e_update_dcb_config(). Instead of i40e_update_dcb_config() we use i40e_init_dcb(), which implements the correct NVM read. Signed-off-by: Grzegorz Siwik Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 46 +-------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5c280c025085..8d6b9515b595 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6419,50 +6419,6 @@ static int i40e_resume_port_tx(struct i40e_pf *pf) return ret; } -/** - * i40e_update_dcb_config - * @hw: pointer to the HW struct - * @enable_mib_change: enable MIB change event - * - * Update DCB configuration from the firmware - **/ -static enum i40e_status_code -i40e_update_dcb_config(struct i40e_hw *hw, bool enable_mib_change) -{ - struct i40e_lldp_variables lldp_cfg; - i40e_status ret; - - if (!hw->func_caps.dcb) - return I40E_NOT_SUPPORTED; - - /* Read LLDP NVM area */ - ret = i40e_read_lldp_cfg(hw, &lldp_cfg); - if (ret) - return I40E_ERR_NOT_READY; - - /* Get DCBX status */ - ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); - if (ret) - return ret; - - /* Check the DCBX Status */ - if (hw->dcbx_status == I40E_DCBX_STATUS_DONE || - hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) { - /* Get current DCBX configuration */ - ret = i40e_get_dcb_config(hw); - if (ret) - return ret; - } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) { - return I40E_ERR_NOT_READY; - } - - /* Configure the LLDP MIB change event */ - if (enable_mib_change) - ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL); - - return ret; -} - /** * i40e_init_pf_dcb - Initialize DCB configuration * @pf: PF being configured @@ -6485,7 +6441,7 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) goto out; } - err = i40e_update_dcb_config(hw, true); + err = i40e_init_dcb(hw, true); if (!err) { /* Device/Function is not DCBX capable */ if ((!hw->func_caps.dcb) || -- GitLab From a39f165db5c4f00becb3e50d65ea2321df64cdf3 Mon Sep 17 00:00:00 2001 From: Piotr Kwapulinski Date: Tue, 23 Jul 2019 06:01:41 -0400 Subject: [PATCH 4136/7155] i40e: allow reset in recovery mode Driver waits after issuing a reset. When a reset takes too long a driver gives up. Implemented by invoking PF reset in a loop. After defined number of unsuccessful PF reset trials it returns error. Without this patch PF reset fails when NIC is in recovery mode. So make i40e_set_mac_type() public. i40e driver requires i40e_set_mac_type() to be public. It is required for recovery mode handling. Without this patch recovery mode could not be detected in i40e_probe(). Signed-off-by: Piotr Kwapulinski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 67 +++++++++++++++++-- .../net/ethernet/intel/i40e/i40e_prototype.h | 2 + 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 7af1b7477140..de996a80013e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -13,7 +13,7 @@ * This function sets the mac type of the adapter based on the * vendor ID and device ID stored in the hw structure. **/ -static i40e_status i40e_set_mac_type(struct i40e_hw *hw) +i40e_status i40e_set_mac_type(struct i40e_hw *hw) { i40e_status status = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8d6b9515b595..fdf43d87e983 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -14564,6 +14564,51 @@ static bool i40e_check_recovery_mode(struct i40e_pf *pf) return false; } +/** + * i40e_pf_loop_reset - perform reset in a loop. + * @pf: board private structure + * + * This function is useful when a NIC is about to enter recovery mode. + * When a NIC's internal data structures are corrupted the NIC's + * firmware is going to enter recovery mode. + * Right after a POR it takes about 7 minutes for firmware to enter + * recovery mode. Until that time a NIC is in some kind of intermediate + * state. After that time period the NIC almost surely enters + * recovery mode. The only way for a driver to detect intermediate + * state is to issue a series of pf-resets and check a return value. + * If a PF reset returns success then the firmware could be in recovery + * mode so the caller of this code needs to check for recovery mode + * if this function returns success. There is a little chance that + * firmware will hang in intermediate state forever. + * Since waiting 7 minutes is quite a lot of time this function waits + * 10 seconds and then gives up by returning an error. + * + * Return 0 on success, negative on failure. + **/ +static i40e_status i40e_pf_loop_reset(struct i40e_pf *pf) +{ + const unsigned short MAX_CNT = 1000; + const unsigned short MSECS = 10; + struct i40e_hw *hw = &pf->hw; + i40e_status ret; + int cnt; + + for (cnt = 0; cnt < MAX_CNT; ++cnt) { + ret = i40e_pf_reset(hw); + if (!ret) + break; + msleep(MSECS); + } + + if (cnt == MAX_CNT) { + dev_info(&pf->pdev->dev, "PF reset failed: %d\n", ret); + return ret; + } + + pf->pfr_count++; + return ret; +} + /** * i40e_init_recovery_mode - initialize subsystems needed in recovery mode * @pf: board private structure @@ -14792,14 +14837,22 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Reset here to make sure all is clean and to define PF 'n' */ i40e_clear_hw(hw); - if (!i40e_check_recovery_mode(pf)) { - err = i40e_pf_reset(hw); - if (err) { - dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err); - goto err_pf_reset; - } - pf->pfr_count++; + + err = i40e_set_mac_type(hw); + if (err) { + dev_warn(&pdev->dev, "unidentified MAC or BLANK NVM: %d\n", + err); + goto err_pf_reset; } + + err = i40e_pf_loop_reset(pf); + if (err) { + dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err); + goto err_pf_reset; + } + + i40e_check_recovery_mode(pf); + hw->aq.num_arq_entries = I40E_AQ_LEN; hw->aq.num_asq_entries = I40E_AQ_LEN; hw->aq.arq_buf_size = I40E_MAX_AQ_BUF_SIZE; diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index eac88bcc6c06..9c810d54df1c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -326,6 +326,8 @@ void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode, void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw); void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status); +i40e_status i40e_set_mac_type(struct i40e_hw *hw); + extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[]; static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) -- GitLab From 65c275e40164d5ef62f2dd8f2705db29b64978f4 Mon Sep 17 00:00:00 2001 From: Sylwia Wnuczko Date: Tue, 23 Jul 2019 06:01:43 -0400 Subject: [PATCH 4137/7155] i40e: Persistent LLDP support This patch adds a function to read NVM module data and uses it to read current LLDP agent configuration from NVM API version 1.8. Signed-off-by: Sylwia Wnuczko Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 18 +++- drivers/net/ethernet/intel/i40e/i40e_dcb.h | 2 + drivers/net/ethernet/intel/i40e/i40e_nvm.c | 101 ++++++++++++++++++ .../net/ethernet/intel/i40e/i40e_prototype.h | 6 ++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 5 files changed, 127 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 292eeb3def10..200a1cb3b536 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -877,7 +877,23 @@ i40e_status i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) return I40E_NOT_SUPPORTED; /* Read LLDP NVM area */ - ret = i40e_read_lldp_cfg(hw, &lldp_cfg); + if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) { + u8 offset = 0; + + if (hw->mac.type == I40E_MAC_XL710) + offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET; + else if (hw->mac.type == I40E_MAC_X722) + offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET; + else + return I40E_NOT_SUPPORTED; + + ret = i40e_read_nvm_module_data(hw, + I40E_SR_EMP_SR_SETTINGS_PTR, + offset, 1, + &lldp_cfg.adminstatus); + } else { + ret = i40e_read_lldp_cfg(hw, &lldp_cfg); + } if (ret) return I40E_ERR_NOT_READY; diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.h b/drivers/net/ethernet/intel/i40e/i40e_dcb.h index ddb48ae7cce4..2a80c5daa376 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.h +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.h @@ -30,6 +30,8 @@ #define I40E_CEE_SUBTYPE_APP_PRI 4 #define I40E_CEE_MAX_FEAT_TYPE 3 +#define I40E_LLDP_CURRENT_STATUS_XL710_OFFSET 0x2B +#define I40E_LLDP_CURRENT_STATUS_X722_OFFSET 0x31 /* Defines for LLDP TLV header */ #define I40E_LLDP_TLV_LEN_SHIFT 0 #define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT) diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index c508b75c3c09..e4d8d20baf3b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -321,6 +321,77 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, return ret_code; } +/** + * i40e_read_nvm_module_data - Reads NVM Buffer to specified memory location + * @hw: pointer to the HW structure + * @module_ptr: Pointer to module in words with respect to NVM beginning + * @offset: offset in words from module start + * @words_data_size: Words to read from NVM + * @data_ptr: Pointer to memory location where resulting buffer will be stored + **/ +i40e_status i40e_read_nvm_module_data(struct i40e_hw *hw, + u8 module_ptr, u16 offset, + u16 words_data_size, + u16 *data_ptr) +{ + i40e_status status; + u16 ptr_value = 0; + u32 flat_offset; + + if (module_ptr != 0) { + status = i40e_read_nvm_word(hw, module_ptr, &ptr_value); + if (status) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm word failed.Error code: %d.\n", + status); + return I40E_ERR_NVM; + } + } +#define I40E_NVM_INVALID_PTR_VAL 0x7FFF +#define I40E_NVM_INVALID_VAL 0xFFFF + + /* Pointer not initialized */ + if (ptr_value == I40E_NVM_INVALID_PTR_VAL || + ptr_value == I40E_NVM_INVALID_VAL) + return I40E_ERR_BAD_PTR; + + /* Check whether the module is in SR mapped area or outside */ + if (ptr_value & I40E_PTR_TYPE) { + /* Pointer points outside of the Shared RAM mapped area */ + ptr_value &= ~I40E_PTR_TYPE; + + /* PtrValue in 4kB units, need to convert to words */ + ptr_value /= 2; + flat_offset = ((u32)ptr_value * 0x1000) + (u32)offset; + status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (!status) { + status = i40e_aq_read_nvm(hw, 0, 2 * flat_offset, + 2 * words_data_size, + data_ptr, true, NULL); + i40e_release_nvm(hw); + if (status) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm aq failed.Error code: %d.\n", + status); + return I40E_ERR_NVM; + } + } else { + return I40E_ERR_NVM; + } + } else { + /* Read from the Shadow RAM */ + status = i40e_read_nvm_buffer(hw, ptr_value + offset, + &words_data_size, data_ptr); + if (status) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm buffer failed.Error code: %d.\n", + status); + } + } + + return status; +} + /** * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register * @hw: pointer to the HW structure @@ -429,6 +500,36 @@ static i40e_status __i40e_read_nvm_buffer(struct i40e_hw *hw, return i40e_read_nvm_buffer_srctl(hw, offset, words, data); } +/** + * i40e_read_nvm_buffer - Reads Shadow RAM buffer and acquire lock if necessary + * @hw: pointer to the HW structure + * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). + * @words: (in) number of words to read; (out) number of words actually read + * @data: words read from the Shadow RAM + * + * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() + * method. The buffer read is preceded by the NVM ownership take + * and followed by the release. + **/ +i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, + u16 *words, u16 *data) +{ + i40e_status ret_code = 0; + + if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) { + ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (!ret_code) { + ret_code = i40e_read_nvm_buffer_aq(hw, offset, words, + data); + i40e_release_nvm(hw); + } + } else { + ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data); + } + + return ret_code; +} + /** * i40e_write_nvm_aq - Writes Shadow RAM. * @hw: pointer to the HW structure. diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 9c810d54df1c..5250441bf75b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -315,6 +315,12 @@ i40e_status i40e_acquire_nvm(struct i40e_hw *hw, void i40e_release_nvm(struct i40e_hw *hw); i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, u16 *data); +i40e_status i40e_read_nvm_module_data(struct i40e_hw *hw, + u8 module_ptr, u16 offset, + u16 words_data_size, + u16 *data_ptr); +i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, + u16 *words, u16 *data); i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw); i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, u16 *checksum); diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 7c1d57683b53..b43ec94a0f29 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1318,6 +1318,7 @@ struct i40e_hw_port_stats { #define I40E_SR_VPD_PTR 0x2F #define I40E_SR_PCIE_ALT_AUTO_LOAD_PTR 0x3E #define I40E_SR_SW_CHECKSUM_WORD 0x3F +#define I40E_SR_EMP_SR_SETTINGS_PTR 0x48 /* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */ #define I40E_SR_VPD_MODULE_MAX_SIZE 1024 -- GitLab From 1b5f5d388b2b4fcb3324914bc90b3956e50ac2b0 Mon Sep 17 00:00:00 2001 From: Marcin Formela Date: Tue, 23 Jul 2019 06:01:44 -0400 Subject: [PATCH 4138/7155] i40e: fix retrying in i40e_aq_get_phy_capabilities Fixed a bug where driver was breaking out of the loop and reporting an error without retrying first. Signed-off-by: Marcin Formela Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index de996a80013e..46e649c09f72 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1577,19 +1577,22 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw, status = i40e_asq_send_command(hw, &desc, abilities, abilities_size, cmd_details); - if (status) - break; - - if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) { + switch (hw->aq.asq_last_status) { + case I40E_AQ_RC_EIO: status = I40E_ERR_UNKNOWN_PHY; break; - } else if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) { + case I40E_AQ_RC_EAGAIN: usleep_range(1000, 2000); total_delay++; status = I40E_ERR_TIMEOUT; + break; + /* also covers I40E_AQ_RC_OK */ + default: + break; } - } while ((hw->aq.asq_last_status != I40E_AQ_RC_OK) && - (total_delay < max_delay)); + + } while ((hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) && + (total_delay < max_delay)); if (status) return status; -- GitLab From dac4f1964a9cbfbf81df8d31caa04ced0d7613b5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 21 Aug 2019 10:06:06 +0300 Subject: [PATCH 4139/7155] misc: xilinx_sdfec: Fix a couple small information leaks These structs have holes in them so we end up disclosing a few bytes of uninitialized stack data. drivers/misc/xilinx_sdfec.c:305 xsdfec_get_status() warn: check that 'status' doesn't leak information (struct has a hole after 'activity') drivers/misc/xilinx_sdfec.c:449 xsdfec_get_turbo() warn: check that 'turbo_params' doesn't leak information (struct has a hole after 'scale') We need to zero out the holes with memset(). Fixes: 6bd6a690c2e7 ("misc: xilinx_sdfec: Add stats & status ioctls") Signed-off-by: Dan Carpenter Reviewed-by: Dragan Cvetic Reviewed-by: Michal Simek Link: https://lore.kernel.org/r/20190821070606.GA26957@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/misc/xilinx_sdfec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 912e939dec62..dc1b8b412712 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -295,6 +295,7 @@ static int xsdfec_get_status(struct xsdfec_dev *xsdfec, void __user *arg) struct xsdfec_status status; int err; + memset(&status, 0, sizeof(status)); spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); status.state = xsdfec->state; xsdfec->state_updated = false; @@ -440,6 +441,7 @@ static int xsdfec_get_turbo(struct xsdfec_dev *xsdfec, void __user *arg) if (xsdfec->config.code == XSDFEC_LDPC_CODE) return -EIO; + memset(&turbo_params, 0, sizeof(turbo_params)); reg_value = xsdfec_regread(xsdfec, XSDFEC_TURBO_ADDR); turbo_params.scale = (reg_value & XSDFEC_TURBO_SCALE_MASK) >> -- GitLab From 129c3b082c636087a72a30b17c87c57d197f08f5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 22 Aug 2019 11:31:05 +0300 Subject: [PATCH 4140/7155] misc: xilinx_sdfec: Return -EFAULT if copy_from_user() fails The copy_from_user() function returns the number of bytes remaining to be copied but we want to return -EFAULT to the user. Fixes: 20ec628e8007 ("misc: xilinx_sdfec: Add ability to configure LDPC") Signed-off-by: Dan Carpenter Reviewed-by: Michal Simek Reviewed-by: Dragan Cvetic Link: https://lore.kernel.org/r/20190822083105.GI3964@kadam Signed-off-by: Greg Kroah-Hartman --- drivers/misc/xilinx_sdfec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index dc1b8b412712..813b82c59360 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -651,9 +651,10 @@ static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg) if (!ldpc) return -ENOMEM; - ret = copy_from_user(ldpc, arg, sizeof(*ldpc)); - if (ret) + if (copy_from_user(ldpc, arg, sizeof(*ldpc))) { + ret = -EFAULT; goto err_out; + } if (xsdfec->config.code == XSDFEC_TURBO_CODE) { ret = -EIO; -- GitLab From 56a635c0ec14950bd6a5bfb4d9d497897f64179f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 21 Aug 2019 10:09:53 +0300 Subject: [PATCH 4141/7155] misc: xilinx_sdfec: Prevent a divide by zero in xsdfec_reg0_write() The "psize" value comes from the user so we need to verify that it's non-zero before we check if "n % psize" or it will crash. Fixes: 20ec628e8007 ("misc: xilinx_sdfec: Add ability to configure LDPC") Signed-off-by: Dan Carpenter Reviewed-by: Michal Simek Link: https://lore.kernel.org/r/20190821070953.GC26957@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/misc/xilinx_sdfec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 813b82c59360..3fc53d20abf3 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -460,7 +460,7 @@ static int xsdfec_reg0_write(struct xsdfec_dev *xsdfec, u32 n, u32 k, u32 psize, { u32 wdata; - if (n < XSDFEC_REG0_N_MIN || n > XSDFEC_REG0_N_MAX || + if (n < XSDFEC_REG0_N_MIN || n > XSDFEC_REG0_N_MAX || psize == 0 || (n > XSDFEC_REG0_N_MUL_P * psize) || n <= k || ((n % psize) != 0)) { dev_dbg(xsdfec->dev, "N value is not in range"); return -EINVAL; -- GitLab From 6123f1fe53985645992b2ff648b3087b77b3ed16 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 21 Aug 2019 10:11:22 +0300 Subject: [PATCH 4142/7155] misc: xilinx_sdfec: Prevent integer overflow in xsdfec_table_write() The checking here needs to handle integer overflows because "offset" and "len" come from the user. Fixes: 20ec628e8007 ("misc: xilinx_sdfec: Add ability to configure LDPC") Signed-off-by: Dan Carpenter Reviewed-by: Michal Simek Reviewed-by: Dragan Cvetic Link: https://lore.kernel.org/r/20190821071122.GD26957@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/misc/xilinx_sdfec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 3fc53d20abf3..0bf3bcc8e1ef 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -611,7 +611,9 @@ static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset, * Writes that go beyond the length of * Shared Scale(SC) table should fail */ - if ((XSDFEC_REG_WIDTH_JUMP * (offset + len)) > depth) { + if (offset > depth / XSDFEC_REG_WIDTH_JUMP || + len > depth / XSDFEC_REG_WIDTH_JUMP || + offset + len > depth / XSDFEC_REG_WIDTH_JUMP) { dev_dbg(xsdfec->dev, "Write exceeds SC table length"); return -EINVAL; } -- GitLab From 3b420aeb7525db8e19ee48fdb1a2fc1d430765d5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 19 Aug 2019 10:41:37 +0100 Subject: [PATCH 4143/7155] misc: xilinx_sdfec: fix spelling mistake: "Schdule" -> "Schedule" There is a spelling mistake in a dev_dbg message, fix it. Signed-off-by: Colin Ian King Reviewed-by: Dragan Cvetic Link: https://lore.kernel.org/r/20190819094137.390-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/xilinx_sdfec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 0bf3bcc8e1ef..11835969e982 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -555,7 +555,7 @@ static int xsdfec_reg2_write(struct xsdfec_dev *xsdfec, u32 nlayers, u32 nmqc, XSDFEC_REG2_NO_FINAL_PARITY_MASK); if (max_schedule & ~(XSDFEC_REG2_MAX_SCHEDULE_MASK >> XSDFEC_REG2_MAX_SCHEDULE_LSB)) - dev_dbg(xsdfec->dev, "Max Schdule exceeds 2 bits"); + dev_dbg(xsdfec->dev, "Max Schedule exceeds 2 bits"); max_schedule = ((max_schedule << XSDFEC_REG2_MAX_SCHEDULE_LSB) & XSDFEC_REG2_MAX_SCHEDULE_MASK); -- GitLab From 57b77df7b71904b00ed70acdf3fde01b5a3e88e2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 20 Aug 2019 09:57:41 +0200 Subject: [PATCH 4144/7155] dt-bindings: net: snps, dwmac: update reg minItems maxItems The Amlogic Meson DWMAC glue bindings needs a second reg cells for the glue registers, thus update the reg minItems/maxItems to allow more than a single reg cell. Also update the allwinner,sun7i-a20-gmac.yaml derivative schema to specify maxItems to 1. Signed-off-by: Neil Armstrong Acked-by: Rob Herring Acked-by: Maxime Ripard Reviewed-by: Martin Blumenstingl Signed-off-by: David S. Miller --- .../devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml | 3 +++ Documentation/devicetree/bindings/net/snps,dwmac.yaml | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml index 06b1cc8bea14..ef446ae166f3 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml @@ -17,6 +17,9 @@ properties: compatible: const: allwinner,sun7i-a20-gmac + reg: + maxItems: 1 + interrupts: maxItems: 1 diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 76fea2be66ac..4377f511a51d 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -61,7 +61,8 @@ properties: - snps,dwxgmac-2.10 reg: - maxItems: 1 + minItems: 1 + maxItems: 2 interrupts: minItems: 1 -- GitLab From d5a57e4e31d1bba5f9603a74660c3dddb173626b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 20 Aug 2019 09:57:42 +0200 Subject: [PATCH 4145/7155] dt-bindings: net: meson-dwmac: convert to yaml Now that we have the DT validation in place, let's convert the device tree bindings for the Synopsys DWMAC Glue for Amlogic SoCs over to a YAML schemas. Reviewed-by: Rob Herring Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- .../bindings/net/amlogic,meson-dwmac.yaml | 113 ++++++++++++++++++ .../devicetree/bindings/net/meson-dwmac.txt | 71 ----------- .../devicetree/bindings/net/snps,dwmac.yaml | 5 + 3 files changed, 118 insertions(+), 71 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml delete mode 100644 Documentation/devicetree/bindings/net/meson-dwmac.txt diff --git a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml new file mode 100644 index 000000000000..ae91aa9d8616 --- /dev/null +++ b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 BayLibre, SAS +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/net/amlogic,meson-dwmac.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic Meson DWMAC Ethernet controller + +maintainers: + - Neil Armstrong + - Martin Blumenstingl + +# We need a select here so we don't match all nodes with 'snps,dwmac' +select: + properties: + compatible: + contains: + enum: + - amlogic,meson6-dwmac + - amlogic,meson8b-dwmac + - amlogic,meson8m2-dwmac + - amlogic,meson-gxbb-dwmac + - amlogic,meson-axg-dwmac + required: + - compatible + +allOf: + - $ref: "snps,dwmac.yaml#" + - if: + properties: + compatible: + contains: + enum: + - amlogic,meson8b-dwmac + - amlogic,meson8m2-dwmac + - amlogic,meson-gxbb-dwmac + - amlogic,meson-axg-dwmac + + then: + properties: + clocks: + items: + - description: GMAC main clock + - description: First parent clock of the internal mux + - description: Second parent clock of the internal mux + + clock-names: + minItems: 3 + maxItems: 3 + items: + - const: stmmaceth + - const: clkin0 + - const: clkin1 + + amlogic,tx-delay-ns: + $ref: /schemas/types.yaml#definitions/uint32 + description: + The internal RGMII TX clock delay (provided by this driver) in + nanoseconds. Allowed values are 0ns, 2ns, 4ns, 6ns. + When phy-mode is set to "rgmii" then the TX delay should be + explicitly configured. When not configured a fallback of 2ns is + used. When the phy-mode is set to either "rgmii-id" or "rgmii-txid" + the TX clock delay is already provided by the PHY. In that case + this property should be set to 0ns (which disables the TX clock + delay in the MAC to prevent the clock from going off because both + PHY and MAC are adding a delay). + Any configuration is ignored when the phy-mode is set to "rmii". + +properties: + compatible: + additionalItems: true + maxItems: 3 + items: + - enum: + - amlogic,meson6-dwmac + - amlogic,meson8b-dwmac + - amlogic,meson8m2-dwmac + - amlogic,meson-gxbb-dwmac + - amlogic,meson-axg-dwmac + contains: + enum: + - snps,dwmac-3.70a + - snps,dwmac + + reg: + items: + - description: + The first register range should be the one of the DWMAC controller + - description: + The second range is is for the Amlogic specific configuration + (for example the PRG_ETHERNET register range on Meson8b and newer) + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - clock-names + - phy-mode + +examples: + - | + ethmac: ethernet@c9410000 { + compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac"; + reg = <0xc9410000 0x10000>, <0xc8834540 0x8>; + interrupts = <8>; + interrupt-names = "macirq"; + clocks = <&clk_eth>, <&clkc_fclk_div2>, <&clk_mpll2>; + clock-names = "stmmaceth", "clkin0", "clkin1"; + phy-mode = "rgmii"; + }; diff --git a/Documentation/devicetree/bindings/net/meson-dwmac.txt b/Documentation/devicetree/bindings/net/meson-dwmac.txt deleted file mode 100644 index 1321bb194ed9..000000000000 --- a/Documentation/devicetree/bindings/net/meson-dwmac.txt +++ /dev/null @@ -1,71 +0,0 @@ -* Amlogic Meson DWMAC Ethernet controller - -The device inherits all the properties of the dwmac/stmmac devices -described in the file stmmac.txt in the current directory with the -following changes. - -Required properties on all platforms: - -- compatible: Depending on the platform this should be one of: - - "amlogic,meson6-dwmac" - - "amlogic,meson8b-dwmac" - - "amlogic,meson8m2-dwmac" - - "amlogic,meson-gxbb-dwmac" - - "amlogic,meson-axg-dwmac" - Additionally "snps,dwmac" and any applicable more - detailed version number described in net/stmmac.txt - should be used. - -- reg: The first register range should be the one of the DWMAC - controller. The second range is is for the Amlogic specific - configuration (for example the PRG_ETHERNET register range - on Meson8b and newer) - -Required properties on Meson8b, Meson8m2, GXBB and newer: -- clock-names: Should contain the following: - - "stmmaceth" - see stmmac.txt - - "clkin0" - first parent clock of the internal mux - - "clkin1" - second parent clock of the internal mux - -Optional properties on Meson8b, Meson8m2, GXBB and newer: -- amlogic,tx-delay-ns: The internal RGMII TX clock delay (provided - by this driver) in nanoseconds. Allowed values - are: 0ns, 2ns, 4ns, 6ns. - When phy-mode is set to "rgmii" then the TX - delay should be explicitly configured. When - not configured a fallback of 2ns is used. - When the phy-mode is set to either "rgmii-id" - or "rgmii-txid" the TX clock delay is already - provided by the PHY. In that case this - property should be set to 0ns (which disables - the TX clock delay in the MAC to prevent the - clock from going off because both PHY and MAC - are adding a delay). - Any configuration is ignored when the phy-mode - is set to "rmii". - -Example for Meson6: - - ethmac: ethernet@c9410000 { - compatible = "amlogic,meson6-dwmac", "snps,dwmac"; - reg = <0xc9410000 0x10000 - 0xc1108108 0x4>; - interrupts = <0 8 1>; - interrupt-names = "macirq"; - clocks = <&clk81>; - clock-names = "stmmaceth"; - } - -Example for GXBB: - ethmac: ethernet@c9410000 { - compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac"; - reg = <0x0 0xc9410000 0x0 0x10000>, - <0x0 0xc8834540 0x0 0x8>; - interrupts = <0 8 1>; - interrupt-names = "macirq"; - clocks = <&clkc CLKID_ETH>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_MPLL2>; - clock-names = "stmmaceth", "clkin0", "clkin1"; - phy-mode = "rgmii"; - }; diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 4377f511a51d..c78be15704b9 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -50,6 +50,11 @@ properties: - allwinner,sun8i-r40-emac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - amlogic,meson6-dwmac + - amlogic,meson8b-dwmac + - amlogic,meson8m2-dwmac + - amlogic,meson-gxbb-dwmac + - amlogic,meson-axg-dwmac - snps,dwmac - snps,dwmac-3.50a - snps,dwmac-3.610 -- GitLab From d3ee8ec7de83abf4325c11bcd36cbd01d7a66789 Mon Sep 17 00:00:00 2001 From: Marco Hartmann Date: Wed, 21 Aug 2019 11:43:49 +0000 Subject: [PATCH 4146/7155] net: fec: add C45 MDIO read/write support IEEE 802.3ae clause 45 defines a modified MDIO protocol that uses a two staged access model in order to increase the address space. This patch adds support for C45 MDIO read and write accesses, which are used whenever the MII_ADDR_C45 flag in the regnum argument is set. In case it is not set, C22 accesses are used as before. Signed-off-by: Marco Hartmann Acked-by: Fugang Duan Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 70 +++++++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index cacc671e486e..d4d4c72adf49 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -208,8 +208,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); /* FEC MII MMFR bits definition */ #define FEC_MMFR_ST (1 << 30) +#define FEC_MMFR_ST_C45 (0) #define FEC_MMFR_OP_READ (2 << 28) +#define FEC_MMFR_OP_READ_C45 (3 << 28) #define FEC_MMFR_OP_WRITE (1 << 28) +#define FEC_MMFR_OP_ADDR_WRITE (0) #define FEC_MMFR_PA(v) ((v & 0x1f) << 23) #define FEC_MMFR_RA(v) ((v & 0x1f) << 18) #define FEC_MMFR_TA (2 << 16) @@ -1767,7 +1770,8 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) struct fec_enet_private *fep = bus->priv; struct device *dev = &fep->pdev->dev; unsigned long time_left; - int ret = 0; + int ret = 0, frame_start, frame_addr, frame_op; + bool is_c45 = !!(regnum & MII_ADDR_C45); ret = pm_runtime_get_sync(dev); if (ret < 0) @@ -1775,9 +1779,37 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) reinit_completion(&fep->mdio_done); + if (is_c45) { + frame_start = FEC_MMFR_ST_C45; + + /* write address */ + frame_addr = (regnum >> 16); + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | + FEC_MMFR_TA | (regnum & 0xFFFF), + fep->hwp + FEC_MII_DATA); + + /* wait for end of transfer */ + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { + netdev_err(fep->netdev, "MDIO address write timeout\n"); + ret = -ETIMEDOUT; + goto out; + } + + frame_op = FEC_MMFR_OP_READ_C45; + + } else { + /* C22 read */ + frame_op = FEC_MMFR_OP_READ; + frame_start = FEC_MMFR_ST; + frame_addr = regnum; + } + /* start a read op */ - writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | + writel(frame_start | frame_op | + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); /* wait for end of transfer */ @@ -1804,7 +1836,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, struct fec_enet_private *fep = bus->priv; struct device *dev = &fep->pdev->dev; unsigned long time_left; - int ret; + int ret, frame_start, frame_addr; + bool is_c45 = !!(regnum & MII_ADDR_C45); ret = pm_runtime_get_sync(dev); if (ret < 0) @@ -1814,9 +1847,33 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, reinit_completion(&fep->mdio_done); + if (is_c45) { + frame_start = FEC_MMFR_ST_C45; + + /* write address */ + frame_addr = (regnum >> 16); + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | + FEC_MMFR_TA | (regnum & 0xFFFF), + fep->hwp + FEC_MII_DATA); + + /* wait for end of transfer */ + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { + netdev_err(fep->netdev, "MDIO address write timeout\n"); + ret = -ETIMEDOUT; + goto out; + } + } else { + /* C22 write */ + frame_start = FEC_MMFR_ST; + frame_addr = regnum; + } + /* start a write op */ - writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | + writel(frame_start | FEC_MMFR_OP_WRITE | + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | FEC_MMFR_TA | FEC_MMFR_DATA(value), fep->hwp + FEC_MII_DATA); @@ -1828,6 +1885,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ret = -ETIMEDOUT; } +out: pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); -- GitLab From 0f817a5eb9e33cec5baf9dc265bdf240b03cf51b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 21 Aug 2019 20:10:56 +0200 Subject: [PATCH 4147/7155] =?UTF-8?q?mISDN:=20Delete=20unnecessary=20check?= =?UTF-8?q?s=20before=20the=20macro=20call=20=E2=80=9Cdev=5Fkfree=5Fskb?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev_kfree_skb() function performs also input parameter validation. Thus the test around the shown calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/avmfritz.c | 3 +-- drivers/isdn/hardware/mISDN/hfcpci.c | 6 ++---- drivers/isdn/hardware/mISDN/mISDNipac.c | 12 ++++-------- drivers/isdn/hardware/mISDN/mISDNisar.c | 3 +-- drivers/isdn/hardware/mISDN/netjet.c | 3 +-- drivers/isdn/hardware/mISDN/w6692.c | 9 +++------ drivers/isdn/mISDN/l1oip_core.c | 3 +-- drivers/isdn/mISDN/layer2.c | 9 +++------ drivers/isdn/mISDN/stack.c | 6 ++---- drivers/isdn/mISDN/tei.c | 6 ++---- 10 files changed, 20 insertions(+), 40 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 81f2b183acc8..1137dd152b5c 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -509,8 +509,7 @@ HDLC_irq_xpr(struct bchannel *bch) if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) { hdlc_fill_fifo(bch); } else { - if (bch->tx_skb) - dev_kfree_skb(bch->tx_skb); + dev_kfree_skb(bch->tx_skb); if (get_next_bframe(bch)) { hdlc_fill_fifo(bch); test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags); diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 4a069582fc6b..2330a7d24267 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -1119,8 +1119,7 @@ tx_birq(struct bchannel *bch) if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) hfcpci_fill_fifo(bch); else { - if (bch->tx_skb) - dev_kfree_skb(bch->tx_skb); + dev_kfree_skb(bch->tx_skb); if (get_next_bframe(bch)) hfcpci_fill_fifo(bch); } @@ -1132,8 +1131,7 @@ tx_dirq(struct dchannel *dch) if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len) hfcpci_fill_dfifo(dch->hw); else { - if (dch->tx_skb) - dev_kfree_skb(dch->tx_skb); + dev_kfree_skb(dch->tx_skb); if (get_next_dframe(dch)) hfcpci_fill_dfifo(dch->hw); } diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index f915399d75ca..bca880213e91 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -190,8 +190,7 @@ isac_rme_irq(struct isac_hw *isac) #endif } WriteISAC(isac, ISAC_CMDR, 0x80); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); + dev_kfree_skb(isac->dch.rx_skb); isac->dch.rx_skb = NULL; } else { count = ReadISAC(isac, ISAC_RBCL) & 0x1f; @@ -210,8 +209,7 @@ isac_xpr_irq(struct isac_hw *isac) if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) { isac_fill_fifo(isac); } else { - if (isac->dch.tx_skb) - dev_kfree_skb(isac->dch.tx_skb); + dev_kfree_skb(isac->dch.tx_skb); if (get_next_dframe(&isac->dch)) isac_fill_fifo(isac); } @@ -464,8 +462,7 @@ isacsx_rme_irq(struct isac_hw *isac) isac->dch.err_crc++; #endif WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); + dev_kfree_skb(isac->dch.rx_skb); isac->dch.rx_skb = NULL; } else { count = ReadISAC(isac, ISACX_RBCLD) & 0x1f; @@ -1012,8 +1009,7 @@ hscx_xpr(struct hscx_hw *hx) if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) { hscx_fill_fifo(hx); } else { - if (hx->bch.tx_skb) - dev_kfree_skb(hx->bch.tx_skb); + dev_kfree_skb(hx->bch.tx_skb); if (get_next_bframe(&hx->bch)) { hscx_fill_fifo(hx); test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index fd5c52f37802..4a3e748a1c26 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -690,8 +690,7 @@ send_next(struct isar_ch *ch) } } } - if (ch->bch.tx_skb) - dev_kfree_skb(ch->bch.tx_skb); + dev_kfree_skb(ch->bch.tx_skb); if (get_next_bframe(&ch->bch)) { isar_fill_fifo(ch); test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 4e30affd1a7c..61caa7e50b9a 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -605,8 +605,7 @@ bc_next_frame(struct tiger_ch *bc) if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) { fill_dma(bc); } else { - if (bc->bch.tx_skb) - dev_kfree_skb(bc->bch.tx_skb); + dev_kfree_skb(bc->bch.tx_skb); if (get_next_bframe(&bc->bch)) { fill_dma(bc); test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 2402608dc98d..bad55fdacd36 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -356,8 +356,7 @@ handle_rxD(struct w6692_hw *card) { card->dch.err_rx++; #endif } - if (card->dch.rx_skb) - dev_kfree_skb(card->dch.rx_skb); + dev_kfree_skb(card->dch.rx_skb); card->dch.rx_skb = NULL; WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); } else { @@ -376,8 +375,7 @@ handle_txD(struct w6692_hw *card) { if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) { W6692_fill_Dfifo(card); } else { - if (card->dch.tx_skb) - dev_kfree_skb(card->dch.tx_skb); + dev_kfree_skb(card->dch.tx_skb); if (get_next_dframe(&card->dch)) W6692_fill_Dfifo(card); } @@ -636,8 +634,7 @@ send_next(struct w6692_ch *wch) if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) { W6692_fill_Bfifo(wch); } else { - if (wch->bch.tx_skb) - dev_kfree_skb(wch->bch.tx_skb); + dev_kfree_skb(wch->bch.tx_skb); if (get_next_bframe(&wch->bch)) { W6692_fill_Bfifo(wch); test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags); diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 447f241467bd..b57dcb834594 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -1254,8 +1254,7 @@ release_card(struct l1oip *hc) mISDN_freebchannel(hc->chan[ch].bch); kfree(hc->chan[ch].bch); #ifdef REORDER_DEBUG - if (hc->chan[ch].disorder_skb) - dev_kfree_skb(hc->chan[ch].disorder_skb); + dev_kfree_skb(hc->chan[ch].disorder_skb); #endif } } diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 68a481516729..5bf7fcb282c4 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -900,8 +900,7 @@ l2_disconnect(struct FsmInst *fi, int event, void *arg) send_uframe(l2, NULL, DISC | 0x10, CMD); mISDN_FsmDelTimer(&l2->t203, 1); restart_t200(l2, 2); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void @@ -1722,8 +1721,7 @@ l2_set_own_busy(struct FsmInst *fi, int event, void *arg) enquiry_cr(l2, RNR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &l2->flag); } - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void @@ -1736,8 +1734,7 @@ l2_clear_own_busy(struct FsmInst *fi, int event, void *arg) enquiry_cr(l2, RR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &l2->flag); } - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index fa2237e7bcf8..27aa32914425 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -75,8 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) cskb = NULL; } read_unlock(&sl->lock); - if (cskb) - dev_kfree_skb(cskb); + dev_kfree_skb(cskb); } static void @@ -134,8 +133,7 @@ send_layer2(struct mISDNstack *st, struct sk_buff *skb) } out: mutex_unlock(&st->lmutex); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static inline int diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index a4fa594e1caf..59d28cb19738 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1328,10 +1328,8 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) } out: read_unlock_irqrestore(&mgr->lock, flags); - if (cskb) - dev_kfree_skb(cskb); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(cskb); + dev_kfree_skb(skb); return 0; } -- GitLab From 038dab7efc38254e151adbbade13b8860055d44a Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 21 Aug 2019 21:16:15 +0200 Subject: [PATCH 4148/7155] =?UTF-8?q?can:=20Delete=20unnecessary=20checks?= =?UTF-8?q?=20before=20the=20macro=20call=20=E2=80=9Cdev=5Fkfree=5Fskb?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev_kfree_skb() function performs also input parameter validation. Thus the test around the shown calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Sean Nyekjaer Signed-off-by: David S. Miller --- drivers/net/can/spi/hi311x.c | 3 +-- drivers/net/can/spi/mcp251x.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index 28badace720e..73d48c3b8ded 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -177,8 +177,7 @@ static void hi3110_clean(struct net_device *net) if (priv->tx_skb || priv->tx_len) net->stats.tx_errors++; - if (priv->tx_skb) - dev_kfree_skb(priv->tx_skb); + dev_kfree_skb(priv->tx_skb); if (priv->tx_len) can_free_echo_skb(priv->net, 0); priv->tx_skb = NULL; diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 05547dd36d61..58992fd61cb9 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -264,8 +264,7 @@ static void mcp251x_clean(struct net_device *net) if (priv->tx_skb || priv->tx_len) net->stats.tx_errors++; - if (priv->tx_skb) - dev_kfree_skb(priv->tx_skb); + dev_kfree_skb(priv->tx_skb); if (priv->tx_len) can_free_echo_skb(priv->net, 0); priv->tx_skb = NULL; -- GitLab From b7deac31979bd09c69e0e6e064609fad55df35be Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 21 Aug 2019 21:48:46 +0200 Subject: [PATCH 4149/7155] =?UTF-8?q?hamradio:=20Delete=20unnecessary=20ch?= =?UTF-8?q?ecks=20before=20the=20macro=20call=20=E2=80=9Cdev=5Fkfree=5Fskb?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev_kfree_skb() function performs also input parameter validation. Thus the test around the shown calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/net/hamradio/baycom_epp.c | 3 +-- drivers/net/hamradio/hdlcdrv.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 9303aeb2595f..4476491b58f9 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -961,8 +961,7 @@ static int epp_close(struct net_device *dev) parport_write_control(pp, 0); /* reset the adapter */ parport_release(bc->pdev); parport_unregister_device(bc->pdev); - if (bc->skb) - dev_kfree_skb(bc->skb); + dev_kfree_skb(bc->skb); bc->skb = NULL; printk(KERN_INFO "%s: close epp at iobase 0x%lx irq %u\n", bc_drvname, dev->base_addr, dev->irq); diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index c6f83e0df0a3..df495b5595f5 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -475,8 +475,7 @@ static int hdlcdrv_close(struct net_device *dev) if (s->ops && s->ops->close) i = s->ops->close(dev); - if (s->skb) - dev_kfree_skb(s->skb); + dev_kfree_skb(s->skb); s->skb = NULL; s->opened = 0; return i; -- GitLab From 5477fccf9abd7342a987d401fa50c0d93ebd09b9 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 21 Aug 2019 22:16:02 +0200 Subject: [PATCH 4150/7155] =?UTF-8?q?net:=20usb:=20Delete=20unnecessary=20?= =?UTF-8?q?checks=20before=20the=20macro=20call=20=E2=80=9Cdev=5Fkfree=5Fs?= =?UTF-8?q?kb=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev_kfree_skb() function performs also input parameter validation. Thus the test around the shown calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/net/usb/lg-vl600.c | 4 +--- drivers/net/usb/rtl8150.c | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c index 6c2b3e368efe..217a2d8fa47b 100644 --- a/drivers/net/usb/lg-vl600.c +++ b/drivers/net/usb/lg-vl600.c @@ -87,9 +87,7 @@ static void vl600_unbind(struct usbnet *dev, struct usb_interface *intf) { struct vl600_state *s = dev->driver_priv; - if (s->current_rx_buf) - dev_kfree_skb(s->current_rx_buf); - + dev_kfree_skb(s->current_rx_buf); kfree(s); return usbnet_cdc_unbind(dev, intf); diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 98f33e270af1..13e51ccf0214 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -586,8 +586,7 @@ static void free_skb_pool(rtl8150_t *dev) int i; for (i = 0; i < RX_SKB_POOL_SIZE; i++) - if (dev->rx_skb_pool[i]) - dev_kfree_skb(dev->rx_skb_pool[i]); + dev_kfree_skb(dev->rx_skb_pool[i]); } static void rx_fixup(unsigned long data) @@ -946,8 +945,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) unlink_all_urbs(dev); free_all_urbs(dev); free_skb_pool(dev); - if (dev->rx_skb) - dev_kfree_skb(dev->rx_skb); + dev_kfree_skb(dev->rx_skb); kfree(dev->intr_buff); free_netdev(dev->netdev); } -- GitLab From 399e06a517b6f1da5f617d413f6e5489f5054f7a Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 22 Aug 2019 20:02:56 +0200 Subject: [PATCH 4151/7155] =?UTF-8?q?ethernet:=20Delete=20unnecessary=20ch?= =?UTF-8?q?ecks=20before=20the=20macro=20call=20=E2=80=9Cdev=5Fkfree=5Fskb?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev_kfree_skb() function performs also input parameter validation. Thus the test around the shown calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/ni65.c | 6 ++---- drivers/net/ethernet/broadcom/bcmsysport.c | 3 +-- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 11 +++-------- drivers/net/ethernet/freescale/gianfar.c | 3 +-- drivers/net/ethernet/ibm/ehea/ehea_main.c | 12 ++++-------- drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 3 +-- drivers/net/ethernet/intel/e1000/e1000_main.c | 3 +-- drivers/net/ethernet/intel/e1000e/ethtool.c | 6 ++---- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 3 +-- drivers/net/ethernet/intel/igb/igb_main.c | 3 +-- drivers/net/ethernet/intel/igc/igc_main.c | 3 +-- drivers/net/ethernet/micrel/ks8842.c | 4 +--- drivers/net/ethernet/microchip/lan743x_ptp.c | 3 +-- drivers/net/ethernet/packetengines/yellowfin.c | 3 +-- drivers/net/ethernet/qualcomm/qca_spi.c | 3 +-- drivers/net/ethernet/qualcomm/qca_uart.c | 3 +-- drivers/net/ethernet/sgi/meth.c | 3 +-- drivers/net/ethernet/smsc/smc91x.c | 3 +-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +-- drivers/net/ethernet/sun/sunvnet_common.c | 3 +-- 20 files changed, 27 insertions(+), 57 deletions(-) diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c index 87ff5d6d1b22..c6c2a54c1121 100644 --- a/drivers/net/ethernet/amd/ni65.c +++ b/drivers/net/ethernet/amd/ni65.c @@ -697,16 +697,14 @@ static void ni65_free_buffer(struct priv *p) for(i=0;itmdbounce[i]); #ifdef XMT_VIA_SKB - if(p->tmd_skb[i]) - dev_kfree_skb(p->tmd_skb[i]); + dev_kfree_skb(p->tmd_skb[i]); #endif } for(i=0;irecv_skb[i]) - dev_kfree_skb(p->recv_skb[i]); + dev_kfree_skb(p->recv_skb[i]); #else kfree(p->recvbounce[i]); #endif diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index cae66ba33c0b..7df887e4024c 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -708,8 +708,7 @@ static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv) for (i = 0; i < priv->num_rx_bds; i++) { cb = &priv->rx_cbs[i]; skb = bcm_sysport_rx_refill(priv, cb); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); if (!cb->skb) return -ENOMEM; } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 2108e59f592b..1586316eb6f1 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2515,19 +2515,14 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) { struct netdev_queue *txq; - struct sk_buff *skb; - struct enet_cb *cb; int i; bcmgenet_fini_rx_napi(priv); bcmgenet_fini_tx_napi(priv); - for (i = 0; i < priv->num_tx_bds; i++) { - cb = priv->tx_cbs + i; - skb = bcmgenet_free_tx_cb(&priv->pdev->dev, cb); - if (skb) - dev_kfree_skb(skb); - } + for (i = 0; i < priv->num_tx_bds; i++) + dev_kfree_skb(bcmgenet_free_tx_cb(&priv->pdev->dev, + priv->tx_cbs + i)); for (i = 0; i < priv->hw_params->tx_queues; i++) { txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[i].queue); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 7ea19e173339..412c0340fed9 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2005,8 +2005,7 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) struct rxbd8 *rxbdp = rx_queue->rx_bd_base; - if (rx_queue->skb) - dev_kfree_skb(rx_queue->skb); + dev_kfree_skb(rx_queue->skb); for (i = 0; i < rx_queue->rx_ring_size; i++) { struct gfar_rx_buff *rxb = &rx_queue->rx_buff[i]; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index cca71ba7a74a..13e30eba5349 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -1577,20 +1577,16 @@ static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr) ehea_destroy_eq(pr->eq); for (i = 0; i < pr->rq1_skba.len; i++) - if (pr->rq1_skba.arr[i]) - dev_kfree_skb(pr->rq1_skba.arr[i]); + dev_kfree_skb(pr->rq1_skba.arr[i]); for (i = 0; i < pr->rq2_skba.len; i++) - if (pr->rq2_skba.arr[i]) - dev_kfree_skb(pr->rq2_skba.arr[i]); + dev_kfree_skb(pr->rq2_skba.arr[i]); for (i = 0; i < pr->rq3_skba.len; i++) - if (pr->rq3_skba.arr[i]) - dev_kfree_skb(pr->rq3_skba.arr[i]); + dev_kfree_skb(pr->rq3_skba.arr[i]); for (i = 0; i < pr->sq_skba.len; i++) - if (pr->sq_skba.arr[i]) - dev_kfree_skb(pr->sq_skba.arr[i]); + dev_kfree_skb(pr->sq_skba.arr[i]); vfree(pr->rq1_skba.arr); vfree(pr->rq2_skba.arr); diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index a41008523c98..71d3d8854d8f 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -937,8 +937,7 @@ static void e1000_free_desc_rings(struct e1000_adapter *adapter) txdr->buffer_info[i].dma, txdr->buffer_info[i].length, DMA_TO_DEVICE); - if (txdr->buffer_info[i].skb) - dev_kfree_skb(txdr->buffer_info[i].skb); + dev_kfree_skb(txdr->buffer_info[i].skb); } } diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 6b6ba1c38235..86493fea56e4 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -4175,8 +4175,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, /* an error means any chain goes out the window * too */ - if (rx_ring->rx_skb_top) - dev_kfree_skb(rx_ring->rx_skb_top); + dev_kfree_skb(rx_ring->rx_skb_top); rx_ring->rx_skb_top = NULL; goto next_desc; } diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 08342698386d..de8c5818a305 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -1126,8 +1126,7 @@ static void e1000_free_desc_rings(struct e1000_adapter *adapter) buffer_info->dma, buffer_info->length, DMA_TO_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb(buffer_info->skb); } } @@ -1139,8 +1138,7 @@ static void e1000_free_desc_rings(struct e1000_adapter *adapter) dma_unmap_single(&pdev->dev, buffer_info->dma, 2048, DMA_FROM_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb(buffer_info->skb); } } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index d3e85480f46d..09f7a246e134 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -253,8 +253,7 @@ static void fm10k_clean_rx_ring(struct fm10k_ring *rx_ring) if (!rx_ring->rx_buffer) return; - if (rx_ring->skb) - dev_kfree_skb(rx_ring->skb); + dev_kfree_skb(rx_ring->skb); rx_ring->skb = NULL; /* Free all the Rx ring sk_buffs */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b63e77528a91..105b0624081a 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4731,8 +4731,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring) { u16 i = rx_ring->next_to_clean; - if (rx_ring->skb) - dev_kfree_skb(rx_ring->skb); + dev_kfree_skb(rx_ring->skb); rx_ring->skb = NULL; /* Free all the Rx ring sk_buffs */ diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index e5114bebd30b..251552855c40 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -352,8 +352,7 @@ static void igc_clean_rx_ring(struct igc_ring *rx_ring) { u16 i = rx_ring->next_to_clean; - if (rx_ring->skb) - dev_kfree_skb(rx_ring->skb); + dev_kfree_skb(rx_ring->skb); rx_ring->skb = NULL; /* Free all the Rx ring sk_buffs */ diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index ccd06702cc56..da329ca115cc 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -580,9 +580,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev) dma_unmap_single(adapter->dev, sg_dma_address(sg), DMA_BUFFER_SIZE, DMA_FROM_DEVICE); sg_dma_address(sg) = 0; - if (ctl->skb) - dev_kfree_skb(ctl->skb); - + dev_kfree_skb(ctl->skb); ctl->skb = NULL; printk(KERN_ERR DRV_NAME": Failed to start RX DMA: %d\n", err); diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c index b2109eca81fd..57b26c2acf87 100644 --- a/drivers/net/ethernet/microchip/lan743x_ptp.c +++ b/drivers/net/ethernet/microchip/lan743x_ptp.c @@ -963,8 +963,7 @@ void lan743x_ptp_close(struct lan743x_adapter *adapter) index++) { struct sk_buff *skb = ptp->tx_ts_skb_queue[index]; - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); ptp->tx_ts_skb_queue[index] = NULL; ptp->tx_ts_seconds_queue[index] = 0; ptp->tx_ts_nseconds_queue[index] = 0; diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index 6f8d6584f809..5113ee647090 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -1258,8 +1258,7 @@ static int yellowfin_close(struct net_device *dev) yp->rx_skbuff[i] = NULL; } for (i = 0; i < TX_RING_SIZE; i++) { - if (yp->tx_skbuff[i]) - dev_kfree_skb(yp->tx_skbuff[i]); + dev_kfree_skb(yp->tx_skbuff[i]); yp->tx_skbuff[i] = NULL; } diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index b28360bc2255..5ecf61df78bd 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -837,8 +837,7 @@ qcaspi_netdev_uninit(struct net_device *dev) kfree(qca->rx_buffer); qca->buffer_size = 0; - if (qca->rx_skb) - dev_kfree_skb(qca->rx_skb); + dev_kfree_skb(qca->rx_skb); } static const struct net_device_ops qcaspi_netdev_ops = { diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c index 590616846cd1..0981068504fa 100644 --- a/drivers/net/ethernet/qualcomm/qca_uart.c +++ b/drivers/net/ethernet/qualcomm/qca_uart.c @@ -285,8 +285,7 @@ static void qcauart_netdev_uninit(struct net_device *dev) { struct qcauart *qca = netdev_priv(dev); - if (qca->rx_skb) - dev_kfree_skb(qca->rx_skb); + dev_kfree_skb(qca->rx_skb); } static const struct net_device_ops qcauart_netdev_ops = { diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 00660dd820e2..539bc5db989c 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -247,8 +247,7 @@ static void meth_free_tx_ring(struct meth_private *priv) /* Remove any pending skb */ for (i = 0; i < TX_RING_ENTRIES; i++) { - if (priv->tx_skbs[i]) - dev_kfree_skb(priv->tx_skbs[i]); + dev_kfree_skb(priv->tx_skbs[i]); priv->tx_skbs[i] = NULL; } dma_free_coherent(&priv->pdev->dev, TX_RING_BUFFER_SIZE, priv->tx_ring, diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 601e76ad99a0..3a6761131f4c 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -378,8 +378,7 @@ static void smc_shutdown(struct net_device *dev) pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; spin_unlock_irq(&lp->lock); - if (pending_skb) - dev_kfree_skb(pending_skb); + dev_kfree_skb(pending_skb); /* and tell the card to stay away from that nasty outside world */ SMC_SELECT_BANK(lp, 0); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index bd1078433448..06ccd216ae90 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3519,8 +3519,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) if (unlikely(error && (status & rx_not_ls))) goto read_again; if (unlikely(error)) { - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); continue; } diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index 646e67236b65..8b94d9ad9e2b 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1532,8 +1532,7 @@ sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, else if (port) del_timer(&port->clean_timer); rcu_read_unlock(); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); vnet_free_skbs(freeskbs); dev->stats.tx_dropped++; return NETDEV_TX_OK; -- GitLab From 6d24e14140053febc5ac1ce46baca6a4334c5f6c Mon Sep 17 00:00:00 2001 From: Ben Wei Date: Wed, 21 Aug 2019 22:08:49 +0000 Subject: [PATCH 4152/7155] net/ncsi: update response packet length for GCPS/GNS/GNPTS commands Update response packet length for the following commands per NC-SI spec - Get Controller Packet Statistics - Get NC-SI Statistics - Get NC-SI Pass-through Statistics command Signed-off-by: Ben Wei Reviewed-by: Justin Lee Signed-off-by: David S. Miller --- net/ncsi/ncsi-rsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c index 7581bf919885..5254004f2b42 100644 --- a/net/ncsi/ncsi-rsp.c +++ b/net/ncsi/ncsi-rsp.c @@ -1083,9 +1083,9 @@ static struct ncsi_rsp_handler { { NCSI_PKT_RSP_GVI, 40, ncsi_rsp_handler_gvi }, { NCSI_PKT_RSP_GC, 32, ncsi_rsp_handler_gc }, { NCSI_PKT_RSP_GP, -1, ncsi_rsp_handler_gp }, - { NCSI_PKT_RSP_GCPS, 172, ncsi_rsp_handler_gcps }, - { NCSI_PKT_RSP_GNS, 172, ncsi_rsp_handler_gns }, - { NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts }, + { NCSI_PKT_RSP_GCPS, 204, ncsi_rsp_handler_gcps }, + { NCSI_PKT_RSP_GNS, 32, ncsi_rsp_handler_gns }, + { NCSI_PKT_RSP_GNPTS, 48, ncsi_rsp_handler_gnpts }, { NCSI_PKT_RSP_GPS, 8, ncsi_rsp_handler_gps }, { NCSI_PKT_RSP_OEM, -1, ncsi_rsp_handler_oem }, { NCSI_PKT_RSP_PLDM, 0, NULL }, -- GitLab From 088e88be5a380cc4e81963a9a02815da465d144f Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:04:12 +0200 Subject: [PATCH 4153/7155] dt-bindings: phy: add binding for the Lantiq VRX200 and ARX300 PCIe PHYs Add the bindings for the PCIe PHY on Lantiq VRX200 and ARX300 SoCs. The IP block contains settings for the PHY and a PLL. The PLL mode is configurable through a dedicated #phy-cell in .dts. Signed-off-by: Martin Blumenstingl Reviewed-by: Rob Herring Signed-off-by: Kishon Vijay Abraham I --- .../bindings/phy/lantiq,vrx200-pcie-phy.yaml | 95 +++++++++++++++++++ .../dt-bindings/phy/phy-lantiq-vrx200-pcie.h | 11 +++ 2 files changed, 106 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/lantiq,vrx200-pcie-phy.yaml create mode 100644 include/dt-bindings/phy/phy-lantiq-vrx200-pcie.h diff --git a/Documentation/devicetree/bindings/phy/lantiq,vrx200-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/lantiq,vrx200-pcie-phy.yaml new file mode 100644 index 000000000000..8a56a8526cef --- /dev/null +++ b/Documentation/devicetree/bindings/phy/lantiq,vrx200-pcie-phy.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/lantiq,vrx200-pcie-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lantiq VRX200 and ARX300 PCIe PHY Device Tree Bindings + +maintainers: + - Martin Blumenstingl + +properties: + "#phy-cells": + const: 1 + description: selects the PHY mode as defined in + + compatible: + enum: + - lantiq,vrx200-pcie-phy + - lantiq,arx300-pcie-phy + + reg: + maxItems: 1 + + clocks: + items: + - description: PHY module clock + - description: PDI register clock + + clock-names: + items: + - const: phy + - const: pdi + + resets: + items: + - description: exclusive PHY reset line + - description: shared reset line between the PCIe PHY and PCIe controller + + resets-names: + items: + - const: phy + - const: pcie + + lantiq,rcu: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the RCU syscon + + lantiq,rcu-endian-offset: + $ref: /schemas/types.yaml#/definitions/uint32 + description: the offset of the endian registers for this PHY instance in the RCU syscon + + lantiq,rcu-big-endian-mask: + $ref: /schemas/types.yaml#/definitions/uint32 + description: the mask to set the PDI (PHY) registers for this PHY instance to big endian + + big-endian: + description: Configures the PDI (PHY) registers in big-endian mode + type: boolean + + little-endian: + description: Configures the PDI (PHY) registers in big-endian mode + type: boolean + +required: + - "#phy-cells" + - compatible + - reg + - clocks + - clock-names + - resets + - reset-names + - lantiq,rcu + - lantiq,rcu-endian-offset + - lantiq,rcu-big-endian-mask + +additionalProperties: false + +examples: + - | + pcie0_phy: phy@106800 { + compatible = "lantiq,vrx200-pcie-phy"; + reg = <0x106800 0x100>; + lantiq,rcu = <&rcu0>; + lantiq,rcu-endian-offset = <0x4c>; + lantiq,rcu-big-endian-mask = <0x80>; /* bit 7 */ + big-endian; + clocks = <&pmu 32>, <&pmu 36>; + clock-names = "phy", "pdi"; + resets = <&reset0 12 24>, <&reset0 22 22>; + reset-names = "phy", "pcie"; + #phy-cells = <1>; + }; + +... diff --git a/include/dt-bindings/phy/phy-lantiq-vrx200-pcie.h b/include/dt-bindings/phy/phy-lantiq-vrx200-pcie.h new file mode 100644 index 000000000000..95a7896356d6 --- /dev/null +++ b/include/dt-bindings/phy/phy-lantiq-vrx200-pcie.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2019 Martin Blumenstingl + */ + +#define LANTIQ_PCIE_PHY_MODE_25MHZ 0 +#define LANTIQ_PCIE_PHY_MODE_25MHZ_SSC 1 +#define LANTIQ_PCIE_PHY_MODE_36MHZ 2 +#define LANTIQ_PCIE_PHY_MODE_36MHZ_SSC 3 +#define LANTIQ_PCIE_PHY_MODE_100MHZ 4 +#define LANTIQ_PCIE_PHY_MODE_100MHZ_SSC 5 -- GitLab From e52a632195bf43d1a91ae699e7536a6ead736aa7 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:04:13 +0200 Subject: [PATCH 4154/7155] phy: lantiq: vrx200-pcie: add a driver for the Lantiq VRX200 PCIe PHY The Lantiq VRX200 SoCs embed a PCIe PHY in the "sram" bus. Unlike most other IP blocks on this SoC the register values are only 16-bit wide. Like other IP blocks on this SoC the register values are in big endian. The PHY embeds a PLL which can be configured in various modes. Only the 36MHz mode is supported for now, the other modes can be implemented when there's a board which actually needs them. OpenWrt uses the out-of-tree vendor driver and all supported boards there only need the 36MHz mode. There are two input clocks: - the "pdi" clock enables the register access - the "phy" clock is the clock input and enables the internal PLL There are two reset lines: - "phy" resets the PHY itself - the "pcie" reset line is shared between the PHY and the PCIe controller While the VRX200 SoC has only one PCIe controller and PHY the ARX300 uses two identical PCIe controllers and PHYs which are compatible with the PCIe controller and PHY on VRX200. Add a driver for this PHY so PCIe support can be enabled on these SoCs. Signed-off-by: Martin Blumenstingl Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/lantiq/Kconfig | 11 + drivers/phy/lantiq/Makefile | 1 + drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c | 494 ++++++++++++++++++++ 3 files changed, 506 insertions(+) create mode 100644 drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c diff --git a/drivers/phy/lantiq/Kconfig b/drivers/phy/lantiq/Kconfig index eb66c857ce25..c4df9709d53f 100644 --- a/drivers/phy/lantiq/Kconfig +++ b/drivers/phy/lantiq/Kconfig @@ -2,6 +2,17 @@ # # Phy drivers for Lantiq / Intel platforms # +config PHY_LANTIQ_VRX200_PCIE + tristate "Lantiq VRX200/ARX300 PCIe PHY" + depends on SOC_TYPE_XWAY || COMPILE_TEST + depends on OF && HAS_IOMEM + select GENERIC_PHY + select REGMAP_MMIO + help + Support for the PCIe PHY(s) on the Lantiq / Intel VRX200 and ARX300 + family SoCs. + If unsure, say N. + config PHY_LANTIQ_RCU_USB2 tristate "Lantiq XWAY SoC RCU based USB PHY" depends on OF && (SOC_TYPE_XWAY || COMPILE_TEST) diff --git a/drivers/phy/lantiq/Makefile b/drivers/phy/lantiq/Makefile index 540049039092..7c14eb24ab73 100644 --- a/drivers/phy/lantiq/Makefile +++ b/drivers/phy/lantiq/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_PHY_LANTIQ_RCU_USB2) += phy-lantiq-rcu-usb2.o +obj-$(CONFIG_PHY_LANTIQ_VRX200_PCIE) += phy-lantiq-vrx200-pcie.o diff --git a/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c new file mode 100644 index 000000000000..544d64a84cc0 --- /dev/null +++ b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PCIe PHY driver for Lantiq VRX200 and ARX300 SoCs. + * + * Copyright (C) 2019 Martin Blumenstingl + * + * Based on the BSP (called "UGW") driver: + * Copyright (C) 2009-2015 Lei Chuanhua + * Copyright (C) 2016 Intel Corporation + * + * TODO: PHY modes other than 36MHz (without "SSC") + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PCIE_PHY_PLL_CTRL1 0x44 + +#define PCIE_PHY_PLL_CTRL2 0x46 +#define PCIE_PHY_PLL_CTRL2_CONST_SDM_MASK GENMASK(7, 0) +#define PCIE_PHY_PLL_CTRL2_CONST_SDM_EN BIT(8) +#define PCIE_PHY_PLL_CTRL2_PLL_SDM_EN BIT(9) + +#define PCIE_PHY_PLL_CTRL3 0x48 +#define PCIE_PHY_PLL_CTRL3_EXT_MMD_DIV_RATIO_EN BIT(1) +#define PCIE_PHY_PLL_CTRL3_EXT_MMD_DIV_RATIO_MASK GENMASK(6, 4) + +#define PCIE_PHY_PLL_CTRL4 0x4a +#define PCIE_PHY_PLL_CTRL5 0x4c +#define PCIE_PHY_PLL_CTRL6 0x4e +#define PCIE_PHY_PLL_CTRL7 0x50 +#define PCIE_PHY_PLL_A_CTRL1 0x52 + +#define PCIE_PHY_PLL_A_CTRL2 0x54 +#define PCIE_PHY_PLL_A_CTRL2_LF_MODE_EN BIT(14) + +#define PCIE_PHY_PLL_A_CTRL3 0x56 +#define PCIE_PHY_PLL_A_CTRL3_MMD_MASK GENMASK(15, 13) + +#define PCIE_PHY_PLL_STATUS 0x58 + +#define PCIE_PHY_TX1_CTRL1 0x60 +#define PCIE_PHY_TX1_CTRL1_FORCE_EN BIT(3) +#define PCIE_PHY_TX1_CTRL1_LOAD_EN BIT(4) + +#define PCIE_PHY_TX1_CTRL2 0x62 +#define PCIE_PHY_TX1_CTRL3 0x64 +#define PCIE_PHY_TX1_A_CTRL1 0x66 +#define PCIE_PHY_TX1_A_CTRL2 0x68 +#define PCIE_PHY_TX1_MOD1 0x6a +#define PCIE_PHY_TX1_MOD2 0x6c +#define PCIE_PHY_TX1_MOD3 0x6e + +#define PCIE_PHY_TX2_CTRL1 0x70 +#define PCIE_PHY_TX2_CTRL1_LOAD_EN BIT(4) + +#define PCIE_PHY_TX2_CTRL2 0x72 +#define PCIE_PHY_TX2_A_CTRL1 0x76 +#define PCIE_PHY_TX2_A_CTRL2 0x78 +#define PCIE_PHY_TX2_MOD1 0x7a +#define PCIE_PHY_TX2_MOD2 0x7c +#define PCIE_PHY_TX2_MOD3 0x7e + +#define PCIE_PHY_RX1_CTRL1 0xa0 +#define PCIE_PHY_RX1_CTRL1_LOAD_EN BIT(1) + +#define PCIE_PHY_RX1_CTRL2 0xa2 +#define PCIE_PHY_RX1_CDR 0xa4 +#define PCIE_PHY_RX1_EI 0xa6 +#define PCIE_PHY_RX1_A_CTRL 0xaa + +struct ltq_vrx200_pcie_phy_priv { + struct phy *phy; + unsigned int mode; + struct device *dev; + struct regmap *phy_regmap; + struct regmap *rcu_regmap; + struct clk *pdi_clk; + struct clk *phy_clk; + struct reset_control *phy_reset; + struct reset_control *pcie_reset; + u32 rcu_ahb_endian_offset; + u32 rcu_ahb_endian_big_endian_mask; +}; + +static void ltq_vrx200_pcie_phy_common_setup(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + + /* PLL Setting */ + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL1, 0x120e); + + /* increase the bias reference voltage */ + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL2, 0x39d7); + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL3, 0x0900); + + /* Endcnt */ + regmap_write(priv->phy_regmap, PCIE_PHY_RX1_EI, 0x0004); + regmap_write(priv->phy_regmap, PCIE_PHY_RX1_A_CTRL, 0x6803); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_TX1_CTRL1, + PCIE_PHY_TX1_CTRL1_FORCE_EN, + PCIE_PHY_TX1_CTRL1_FORCE_EN); + + /* predrv_ser_en */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_A_CTRL2, 0x0706); + + /* ctrl_lim */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_CTRL3, 0x1fff); + + /* ctrl */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_A_CTRL1, 0x0810); + + /* predrv_ser_en */ + regmap_update_bits(priv->phy_regmap, PCIE_PHY_TX2_A_CTRL2, 0x7f00, + 0x4700); + + /* RTERM */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_CTRL2, 0x2e00); + + /* Improved 100MHz clock output */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_CTRL2, 0x3096); + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_A_CTRL2, 0x4707); + + /* Reduced CDR BW to avoid glitches */ + regmap_write(priv->phy_regmap, PCIE_PHY_RX1_CDR, 0x0235); +} + +static void pcie_phy_36mhz_mode_setup(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL3, + PCIE_PHY_PLL_CTRL3_EXT_MMD_DIV_RATIO_EN, 0x0000); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL3, + PCIE_PHY_PLL_CTRL3_EXT_MMD_DIV_RATIO_MASK, 0x0000); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, + PCIE_PHY_PLL_CTRL2_PLL_SDM_EN, + PCIE_PHY_PLL_CTRL2_PLL_SDM_EN); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, + PCIE_PHY_PLL_CTRL2_CONST_SDM_EN, + PCIE_PHY_PLL_CTRL2_CONST_SDM_EN); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL3, + PCIE_PHY_PLL_A_CTRL3_MMD_MASK, + FIELD_PREP(PCIE_PHY_PLL_A_CTRL3_MMD_MASK, 0x1)); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL2, + PCIE_PHY_PLL_A_CTRL2_LF_MODE_EN, 0x0000); + + /* const_sdm */ + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL1, 0x38e4); + + regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, + PCIE_PHY_PLL_CTRL2_CONST_SDM_MASK, + FIELD_PREP(PCIE_PHY_PLL_CTRL2_CONST_SDM_MASK, + 0xee)); + + /* pllmod */ + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL7, 0x0002); + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL6, 0x3a04); + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL5, 0xfae3); + regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL4, 0x1b72); +} + +static int ltq_vrx200_pcie_phy_wait_for_pll(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + unsigned int tmp; + int ret; + + ret = regmap_read_poll_timeout(priv->phy_regmap, PCIE_PHY_PLL_STATUS, + tmp, ((tmp & 0x0070) == 0x0070), 10, + 10000); + if (ret) { + dev_err(priv->dev, "PLL Link timeout, PLL status = 0x%04x\n", + tmp); + return ret; + } + + return 0; +} + +static void ltq_vrx200_pcie_phy_apply_workarounds(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + static const struct reg_default slices[] = { + { + .reg = PCIE_PHY_TX1_CTRL1, + .def = PCIE_PHY_TX1_CTRL1_LOAD_EN, + }, + { + .reg = PCIE_PHY_TX2_CTRL1, + .def = PCIE_PHY_TX2_CTRL1_LOAD_EN, + }, + { + .reg = PCIE_PHY_RX1_CTRL1, + .def = PCIE_PHY_RX1_CTRL1_LOAD_EN, + } + }; + int i; + + for (i = 0; i < ARRAY_SIZE(slices); i++) { + /* enable load_en */ + regmap_update_bits(priv->phy_regmap, slices[i].reg, + slices[i].def, slices[i].def); + + udelay(1); + + /* disable load_en */ + regmap_update_bits(priv->phy_regmap, slices[i].reg, + slices[i].def, 0x0); + } + + for (i = 0; i < 5; i++) { + /* TX2 modulation */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD1, 0x1ffe); + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD2, 0xfffe); + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD3, 0x0601); + usleep_range(1000, 2000); + regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD3, 0x0001); + + /* TX1 modulation */ + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD1, 0x1ffe); + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD2, 0xfffe); + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD3, 0x0601); + usleep_range(1000, 2000); + regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD3, 0x0001); + } +} + +static int ltq_vrx200_pcie_phy_init(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + int ret; + + if (of_device_is_big_endian(priv->dev->of_node)) + regmap_update_bits(priv->rcu_regmap, + priv->rcu_ahb_endian_offset, + priv->rcu_ahb_endian_big_endian_mask, + priv->rcu_ahb_endian_big_endian_mask); + else + regmap_update_bits(priv->rcu_regmap, + priv->rcu_ahb_endian_offset, + priv->rcu_ahb_endian_big_endian_mask, 0x0); + + ret = reset_control_assert(priv->phy_reset); + if (ret) + goto err; + + udelay(1); + + ret = reset_control_deassert(priv->phy_reset); + if (ret) + goto err; + + udelay(1); + + ret = reset_control_deassert(priv->pcie_reset); + if (ret) + goto err_assert_phy_reset; + + /* Make sure PHY PLL is stable */ + usleep_range(20, 40); + + return 0; + +err_assert_phy_reset: + reset_control_assert(priv->phy_reset); +err: + return ret; +} + +static int ltq_vrx200_pcie_phy_exit(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_assert(priv->pcie_reset); + if (ret) + return ret; + + ret = reset_control_assert(priv->phy_reset); + if (ret) + return ret; + + return 0; +} + +static int ltq_vrx200_pcie_phy_power_on(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + int ret; + + /* Enable PDI to access PCIe PHY register */ + ret = clk_prepare_enable(priv->pdi_clk); + if (ret) + goto err; + + /* Configure PLL and PHY clock */ + ltq_vrx200_pcie_phy_common_setup(phy); + + pcie_phy_36mhz_mode_setup(phy); + + /* Enable the PCIe PHY and make PLL setting take effect */ + ret = clk_prepare_enable(priv->phy_clk); + if (ret) + goto err_disable_pdi_clk; + + /* Check if we are in "startup ready" status */ + if (ltq_vrx200_pcie_phy_wait_for_pll(phy) != 0) + goto err_disable_phy_clk; + + ltq_vrx200_pcie_phy_apply_workarounds(phy); + + return 0; + +err_disable_phy_clk: + clk_disable_unprepare(priv->phy_clk); +err_disable_pdi_clk: + clk_disable_unprepare(priv->pdi_clk); +err: + return ret; +} + +static int ltq_vrx200_pcie_phy_power_off(struct phy *phy) +{ + struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); + + clk_disable_unprepare(priv->phy_clk); + clk_disable_unprepare(priv->pdi_clk); + + return 0; +} + +static struct phy_ops ltq_vrx200_pcie_phy_ops = { + .init = ltq_vrx200_pcie_phy_init, + .exit = ltq_vrx200_pcie_phy_exit, + .power_on = ltq_vrx200_pcie_phy_power_on, + .power_off = ltq_vrx200_pcie_phy_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *ltq_vrx200_pcie_phy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct ltq_vrx200_pcie_phy_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count != 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + switch (mode) { + case LANTIQ_PCIE_PHY_MODE_36MHZ: + priv->mode = mode; + break; + + case LANTIQ_PCIE_PHY_MODE_25MHZ: + case LANTIQ_PCIE_PHY_MODE_25MHZ_SSC: + case LANTIQ_PCIE_PHY_MODE_36MHZ_SSC: + case LANTIQ_PCIE_PHY_MODE_100MHZ: + case LANTIQ_PCIE_PHY_MODE_100MHZ_SSC: + dev_err(dev, "PHY mode not implemented yet: %u\n", mode); + return ERR_PTR(-EINVAL); + + default: + dev_err(dev, "invalid PHY mode %u\n", mode); + return ERR_PTR(-EINVAL); + }; + + return priv->phy; +} + +static int ltq_vrx200_pcie_phy_probe(struct platform_device *pdev) +{ + static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .reg_stride = 2, + .max_register = PCIE_PHY_RX1_A_CTRL, + }; + struct ltq_vrx200_pcie_phy_priv *priv; + struct device *dev = &pdev->dev; + struct phy_provider *provider; + struct resource *res; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->phy_regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(priv->phy_regmap)) + return PTR_ERR(priv->phy_regmap); + + priv->rcu_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "lantiq,rcu"); + if (IS_ERR(priv->rcu_regmap)) + return PTR_ERR(priv->rcu_regmap); + + ret = device_property_read_u32(dev, "lantiq,rcu-endian-offset", + &priv->rcu_ahb_endian_offset); + if (ret) { + dev_err(dev, + "failed to parse the 'lantiq,rcu-endian-offset' property\n"); + return ret; + } + + ret = device_property_read_u32(dev, "lantiq,rcu-big-endian-mask", + &priv->rcu_ahb_endian_big_endian_mask); + if (ret) { + dev_err(dev, + "failed to parse the 'lantiq,rcu-big-endian-mask' property\n"); + return ret; + } + + priv->pdi_clk = devm_clk_get(dev, "pdi"); + if (IS_ERR(priv->pdi_clk)) + return PTR_ERR(priv->pdi_clk); + + priv->phy_clk = devm_clk_get(dev, "phy"); + if (IS_ERR(priv->phy_clk)) + return PTR_ERR(priv->phy_clk); + + priv->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); + if (IS_ERR(priv->phy_reset)) + return PTR_ERR(priv->phy_reset); + + priv->pcie_reset = devm_reset_control_get_shared(dev, "pcie"); + if (IS_ERR(priv->pcie_reset)) + return PTR_ERR(priv->pcie_reset); + + priv->dev = dev; + + priv->phy = devm_phy_create(dev, dev->of_node, + <q_vrx200_pcie_phy_ops); + if (IS_ERR(priv->phy)) { + dev_err(dev, "failed to create PHY\n"); + return PTR_ERR(priv->phy); + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + + provider = devm_of_phy_provider_register(dev, + ltq_vrx200_pcie_phy_xlate); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct of_device_id ltq_vrx200_pcie_phy_of_match[] = { + { .compatible = "lantiq,vrx200-pcie-phy", }, + { .compatible = "lantiq,arx300-pcie-phy", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ltq_vrx200_pcie_phy_of_match); + +static struct platform_driver ltq_vrx200_pcie_phy_driver = { + .probe = ltq_vrx200_pcie_phy_probe, + .driver = { + .name = "ltq-vrx200-pcie-phy", + .of_match_table = ltq_vrx200_pcie_phy_of_match, + } +}; +module_platform_driver(ltq_vrx200_pcie_phy_driver); + +MODULE_AUTHOR("Martin Blumenstingl "); +MODULE_DESCRIPTION("Lantiq VRX200 and ARX300 PCIe PHY driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 4e99276a6f7cf6cbf1d375e2da59c358ca0fd0a8 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 27 Jul 2019 14:04:14 +0200 Subject: [PATCH 4155/7155] phy: enable compile-testing for the Lantiq PHY drivers Unconditionally include the lantiq subdirectory in the phy Makefile. All drivers in there have their dependencies maintained. One of these (optional) dependencies is COMPILE_TEST, however this can only be evaluated when Kconfig scans the lantiq subdirectory. Signed-off-by: Martin Blumenstingl Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 0d9fddc498a6..c96a1afc95bd 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_ARCH_SUNXI) += allwinner/ obj-$(CONFIG_ARCH_MESON) += amlogic/ -obj-$(CONFIG_LANTIQ) += lantiq/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ @@ -19,6 +18,7 @@ obj-y += broadcom/ \ cadence/ \ freescale/ \ hisilicon/ \ + lantiq/ \ marvell/ \ motorola/ \ mscc/ \ -- GitLab From 8d160f6b491ec2bcfba2233121ab81f0424e133f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 23 Jul 2019 16:19:19 +0530 Subject: [PATCH 4156/7155] phy: marvell: phy-armada38x-comphy: Add of_node_put() before return Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/marvell/phy-armada38x-comphy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/phy/marvell/phy-armada38x-comphy.c b/drivers/phy/marvell/phy-armada38x-comphy.c index 3e00bc679d4e..6960dfd8ad8c 100644 --- a/drivers/phy/marvell/phy-armada38x-comphy.c +++ b/drivers/phy/marvell/phy-armada38x-comphy.c @@ -200,8 +200,10 @@ static int a38x_comphy_probe(struct platform_device *pdev) } phy = devm_phy_create(&pdev->dev, child, &a38x_comphy_ops); - if (IS_ERR(phy)) + if (IS_ERR(phy)) { + of_node_put(child); return PTR_ERR(phy); + } priv->lane[val].base = base + 0x28 * val; priv->lane[val].priv = priv; -- GitLab From 5b43a20ac6c4c1b3445618c6e0bed6937709eea8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 23 Jul 2019 16:23:27 +0530 Subject: [PATCH 4157/7155] phy: marvell: phy-mvebu-cp110-comphy: Add of_node_put() before return Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/marvell/phy-mvebu-cp110-comphy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c index d98e0451f6a1..f7a16dc6e171 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c @@ -626,12 +626,16 @@ static int mvebu_comphy_probe(struct platform_device *pdev) } lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL); - if (!lane) + if (!lane) { + of_node_put(child); return -ENOMEM; + } phy = devm_phy_create(&pdev->dev, child, &mvebu_comphy_ops); - if (IS_ERR(phy)) + if (IS_ERR(phy)) { + of_node_put(child); return PTR_ERR(phy); + } lane->priv = priv; lane->mode = PHY_MODE_INVALID; -- GitLab From beae796d66165b40d80b743ae301a29c312d7320 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 23 Jul 2019 16:21:08 +0530 Subject: [PATCH 4158/7155] phy: marvell: phy-mvebu-a3700-comphy: Add of_node_put() before return Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c index 8812a104c233..0ebac46435bd 100644 --- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c @@ -277,13 +277,17 @@ static int mvebu_a3700_comphy_probe(struct platform_device *pdev) } lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL); - if (!lane) + if (!lane) { + of_node_put(child); return -ENOMEM; + } phy = devm_phy_create(&pdev->dev, child, &mvebu_a3700_comphy_ops); - if (IS_ERR(phy)) + if (IS_ERR(phy)) { + of_node_put(child); return PTR_ERR(phy); + } lane->dev = &pdev->dev; lane->mode = PHY_MODE_INVALID; -- GitLab From bbae18f0fc621df81d05d614eff31f90495516d3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 22 Jul 2019 19:32:23 +0200 Subject: [PATCH 4159/7155] phy: core: document phy_calibrate() Commit 36914111e682 ("drivers: phy: add calibrate method") added support for generic phy_calibrate() method, but it didn't explain in detail when such method is supposed to be called. Add some more documentation directly to the phy.h to make it clean that it is intended to be called after every host controller reset. Signed-off-by: Marek Szyprowski Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index e3880c4a15f2..b04f4fe85ac2 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -394,6 +394,16 @@ int phy_reset(struct phy *phy) } EXPORT_SYMBOL_GPL(phy_reset); +/** + * phy_calibrate() - Tunes the phy hw parameters for current configuration + * @phy: the phy returned by phy_get() + * + * Used to calibrate phy hardware, typically by adjusting some parameters in + * runtime, which are otherwise lost after host controller reset and cannot + * be applied in phy_init() or phy_power_on(). + * + * Returns: 0 if successful, an negative error code otherwise + */ int phy_calibrate(struct phy *phy) { int ret; -- GitLab From 6aeec986f1bc5d8b30bf23b2bf330deed28f37ea Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 19 Jul 2019 14:25:32 +0200 Subject: [PATCH 4160/7155] phy: samsung: disable bind/unbind platform driver feature Samsung PHY drivers control the power to the SoC core components needed by their client devices (USB HCDs, SATA, camera ISP bridge, DP encoder) to properly operate. Disabling PHYs in runtime usually causes the client device to crash with external abort exception or similar issue due to lack of API to notify clients about PHY removal. This patch removes the possiblity to unbind Samsung Exynos PHY drivers in runtime. Signed-off-by: Marek Szyprowski Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/samsung/phy-exynos-dp-video.c | 1 + drivers/phy/samsung/phy-exynos-mipi-video.c | 1 + drivers/phy/samsung/phy-exynos-pcie.c | 1 + drivers/phy/samsung/phy-exynos5-usbdrd.c | 1 + drivers/phy/samsung/phy-exynos5250-sata.c | 1 + drivers/phy/samsung/phy-samsung-usb2.c | 1 + 6 files changed, 6 insertions(+) diff --git a/drivers/phy/samsung/phy-exynos-dp-video.c b/drivers/phy/samsung/phy-exynos-dp-video.c index aebd216dcf2f..6c607df1dc9a 100644 --- a/drivers/phy/samsung/phy-exynos-dp-video.c +++ b/drivers/phy/samsung/phy-exynos-dp-video.c @@ -109,6 +109,7 @@ static struct platform_driver exynos_dp_video_phy_driver = { .driver = { .name = "exynos-dp-video-phy", .of_match_table = exynos_dp_video_phy_of_match, + .suppress_bind_attrs = true, } }; module_platform_driver(exynos_dp_video_phy_driver); diff --git a/drivers/phy/samsung/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c index 3784bf100b95..bb51195f189f 100644 --- a/drivers/phy/samsung/phy-exynos-mipi-video.c +++ b/drivers/phy/samsung/phy-exynos-mipi-video.c @@ -359,6 +359,7 @@ static struct platform_driver exynos_mipi_video_phy_driver = { .driver = { .of_match_table = exynos_mipi_video_phy_of_match, .name = "exynos-mipi-video-phy", + .suppress_bind_attrs = true, } }; module_platform_driver(exynos_mipi_video_phy_driver); diff --git a/drivers/phy/samsung/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c index 1b4ba8bdb43c..659e7ae0a6cf 100644 --- a/drivers/phy/samsung/phy-exynos-pcie.c +++ b/drivers/phy/samsung/phy-exynos-pcie.c @@ -272,6 +272,7 @@ static struct platform_driver exynos_pcie_phy_driver = { .driver = { .of_match_table = exynos_pcie_phy_match, .name = "exynos_pcie_phy", + .suppress_bind_attrs = true, } }; diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 646259bee909..e510732afb8b 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -953,6 +953,7 @@ static struct platform_driver exynos5_usb3drd_phy = { .driver = { .of_match_table = exynos5_usbdrd_phy_of_match, .name = "exynos5_usb3drd_phy", + .suppress_bind_attrs = true, } }; diff --git a/drivers/phy/samsung/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c index 9e5fc126032c..4dd7324d91b2 100644 --- a/drivers/phy/samsung/phy-exynos5250-sata.c +++ b/drivers/phy/samsung/phy-exynos5250-sata.c @@ -237,6 +237,7 @@ static struct platform_driver exynos_sata_phy_driver = { .driver = { .of_match_table = exynos_sata_phy_of_match, .name = "samsung,sata-phy", + .suppress_bind_attrs = true, } }; module_platform_driver(exynos_sata_phy_driver); diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c index 6c82f4fbe8a2..090aa02e02de 100644 --- a/drivers/phy/samsung/phy-samsung-usb2.c +++ b/drivers/phy/samsung/phy-samsung-usb2.c @@ -250,6 +250,7 @@ static struct platform_driver samsung_usb2_phy_driver = { .driver = { .of_match_table = samsung_usb2_phy_of_match, .name = "samsung-usb2-phy", + .suppress_bind_attrs = true, } }; -- GitLab From cacc9539cff118735b11a350d121cb7eeca7e358 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 31 Jul 2019 14:15:13 +0200 Subject: [PATCH 4161/7155] phy: mvebu-a3700-comphy: Inform users if their firmware is too old PHY configuration has been implemented in the firmware and accessed through SMC calls. In the past, it worked magically if the bootloader was correctly doing the initializations. With up-to-date bindings, the kernel will need a recent firmware in order to do the initializations himself (we assume people must update their firmware along with their kernel). People might not understand why IPs that were working correctly before stopped to be probed suddendly. In this case, let's advise the users to update their firmware with a visual warning. Signed-off-by: Miquel Raynal Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c index 0ebac46435bd..1a138be8bd6a 100644 --- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c @@ -26,6 +26,7 @@ #define COMPHY_SIP_POWER_ON 0x82000001 #define COMPHY_SIP_POWER_OFF 0x82000002 #define COMPHY_SIP_PLL_LOCK 0x82000003 +#define COMPHY_FW_NOT_SUPPORTED (-1) #define COMPHY_FW_MODE_SATA 0x1 #define COMPHY_FW_MODE_SGMII 0x2 @@ -169,6 +170,7 @@ static int mvebu_a3700_comphy_power_on(struct phy *phy) struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); u32 fw_param; int fw_mode; + int ret; fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, lane->mode, lane->submode); @@ -217,7 +219,12 @@ static int mvebu_a3700_comphy_power_on(struct phy *phy) return -ENOTSUPP; } - return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); + ret = mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); + if (ret == COMPHY_FW_NOT_SUPPORTED) + dev_err(lane->dev, + "unsupported SMC call, try updating your firmware\n"); + + return ret; } static int mvebu_a3700_comphy_power_off(struct phy *phy) -- GitLab From f8be8e5680225ac9caf07d4545f8529b7395327f Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 21 Aug 2019 23:59:56 +0000 Subject: [PATCH 4162/7155] EDAC/amd64: Recognize DRAM device type ECC capability AMD Family 17h systems support x4 and x16 DRAM devices. However, the device type is not checked when setting mci.edac_ctl_cap. Set the appropriate capability flag based on the device type. Default to x8 DRAM device when neither the x4 or x16 bits are set. [ bp: reverse cpk_en check to save an indentation level. ] Fixes: 2d09d8f301f5 ("EDAC, amd64: Determine EDAC MC capabilities on Fam17h") Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-3-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index dd60cf5a3d96..ffe56a8fe39d 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3150,12 +3150,15 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid) static inline void f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt) { - u8 i, ecc_en = 1, cpk_en = 1; + u8 i, ecc_en = 1, cpk_en = 1, dev_x4 = 1, dev_x16 = 1; for_each_umc(i) { if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) { ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED); cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP); + + dev_x4 &= !!(pvt->umc[i].dimm_cfg & BIT(6)); + dev_x16 &= !!(pvt->umc[i].dimm_cfg & BIT(7)); } } @@ -3163,8 +3166,15 @@ f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt) if (ecc_en) { mci->edac_ctl_cap |= EDAC_FLAG_SECDED; - if (cpk_en) + if (!cpk_en) + return; + + if (dev_x4) mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; + else if (dev_x16) + mci->edac_ctl_cap |= EDAC_FLAG_S16ECD16ED; + else + mci->edac_ctl_cap |= EDAC_FLAG_S8ECD8ED; } } -- GitLab From 353a1fcb8f9e5857c0fb720b9e57a86c1fb7c17e Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 21 Aug 2019 23:59:57 +0000 Subject: [PATCH 4163/7155] EDAC/amd64: Initialize DIMM info for systems with more than two channels Currently, the DIMM info for AMD Family 17h systems is initialized in init_csrows(). This function is shared with legacy systems, and it has a limit of two channel support. This prevents initialization of the DIMM info for a number of ranks, so there will be missing ranks in the EDAC sysfs. Create a new init_csrows_df() for Family17h+ and revert init_csrows() back to pre-Family17h support. Loop over all channels in the new function in order to support systems with more than two channels. Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-4-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 66 ++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ffe56a8fe39d..6f67c48b66cd 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2837,6 +2837,49 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) return nr_pages; } +static int init_csrows_df(struct mem_ctl_info *mci) +{ + struct amd64_pvt *pvt = mci->pvt_info; + enum edac_type edac_mode = EDAC_NONE; + enum dev_type dev_type = DEV_UNKNOWN; + struct dimm_info *dimm; + int empty = 1; + u8 umc, cs; + + if (mci->edac_ctl_cap & EDAC_FLAG_S16ECD16ED) { + edac_mode = EDAC_S16ECD16ED; + dev_type = DEV_X16; + } else if (mci->edac_ctl_cap & EDAC_FLAG_S8ECD8ED) { + edac_mode = EDAC_S8ECD8ED; + dev_type = DEV_X8; + } else if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) { + edac_mode = EDAC_S4ECD4ED; + dev_type = DEV_X4; + } else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) { + edac_mode = EDAC_SECDED; + } + + for_each_umc(umc) { + for_each_chip_select(cs, umc, pvt) { + if (!csrow_enabled(cs, umc, pvt)) + continue; + + empty = 0; + dimm = mci->csrows[cs]->channels[umc]->dimm; + + edac_dbg(1, "MC node: %d, csrow: %d\n", + pvt->mc_node_id, cs); + + dimm->nr_pages = get_csrow_nr_pages(pvt, umc, cs); + dimm->mtype = pvt->dram_type; + dimm->edac_mode = edac_mode; + dimm->dtype = dev_type; + } + } + + return empty; +} + /* * Initialize the array of csrow attribute instances, based on the values * from pci config hardware registers. @@ -2851,15 +2894,16 @@ static int init_csrows(struct mem_ctl_info *mci) int nr_pages = 0; u32 val; - if (!pvt->umc) { - amd64_read_pci_cfg(pvt->F3, NBCFG, &val); + if (pvt->umc) + return init_csrows_df(mci); + + amd64_read_pci_cfg(pvt->F3, NBCFG, &val); - pvt->nbcfg = val; + pvt->nbcfg = val; - edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", - pvt->mc_node_id, val, - !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); - } + edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", + pvt->mc_node_id, val, + !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); /* * We iterate over DCT0 here but we look at DCT1 in parallel, if needed. @@ -2896,13 +2940,7 @@ static int init_csrows(struct mem_ctl_info *mci) edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); /* Determine DIMM ECC mode: */ - if (pvt->umc) { - if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) - edac_mode = EDAC_S4ECD4ED; - else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) - edac_mode = EDAC_SECDED; - - } else if (pvt->nbcfg & NBCFG_ECC_ENABLE) { + if (pvt->nbcfg & NBCFG_ECC_ENABLE) { edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ? EDAC_S4ECD4ED : EDAC_SECDED; -- GitLab From e53a3b267fb0a79db9ca1f1e08b97889b22013e6 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 21 Aug 2019 23:59:59 +0000 Subject: [PATCH 4164/7155] EDAC/amd64: Find Chip Select memory size using Address Mask Chip Select memory size reporting on AMD Family 17h was recently fixed in order to account for interleaving. However, the current method is not robust. The Chip Select Address Mask can be used to find the memory size. There are a couple of cases. 1) For single-rank and dual-rank non-interleaved, use the address mask plus 1 as the size. 2) For dual-rank interleaved, do #1 but "de-interleave" the address mask first. Always "de-interleave" the address mask in order to simplify the code flow. Bit mask manipulation is necessary to check for interleaving, so just go ahead and do the de-interleaving. In the non-interleaved case, the original and de-interleaved address masks will be the same. To de-interleave the mask, count the number of zero bits in the middle of the mask and swap them with the most significant bits. For example, Original=0xFFFF9FE, De-interleaved=0x3FFFFFE Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-5-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 114 +++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 44 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 6f67c48b66cd..8f300c0714b8 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -788,51 +788,39 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) (dclr & BIT(15)) ? "yes" : "no"); } -/* - * The Address Mask should be a contiguous set of bits in the non-interleaved - * case. So to check for CS interleaving, find the most- and least-significant - * bits of the mask, generate a contiguous bitmask, and compare the two. - */ -static bool f17_cs_interleaved(struct amd64_pvt *pvt, u8 ctrl, int cs) +#define CS_EVEN_PRIMARY BIT(0) +#define CS_ODD_PRIMARY BIT(1) + +#define CS_EVEN CS_EVEN_PRIMARY +#define CS_ODD CS_ODD_PRIMARY + +static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) { - u32 mask = pvt->csels[ctrl].csmasks[cs >> 1]; - u32 msb = fls(mask) - 1, lsb = ffs(mask) - 1; - u32 test_mask = GENMASK(msb, lsb); + int cs_mode = 0; - edac_dbg(1, "mask=0x%08x test_mask=0x%08x\n", mask, test_mask); + if (csrow_enabled(2 * dimm, ctrl, pvt)) + cs_mode |= CS_EVEN_PRIMARY; - return mask ^ test_mask; + if (csrow_enabled(2 * dimm + 1, ctrl, pvt)) + cs_mode |= CS_ODD_PRIMARY; + + return cs_mode; } static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl) { - int dimm, size0, size1, cs0, cs1; + int dimm, size0, size1, cs0, cs1, cs_mode; edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); for (dimm = 0; dimm < 2; dimm++) { - size0 = 0; cs0 = dimm * 2; - - if (csrow_enabled(cs0, ctrl, pvt)) - size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0); - - size1 = 0; cs1 = dimm * 2 + 1; - if (csrow_enabled(cs1, ctrl, pvt)) { - /* - * CS interleaving is only supported if both CSes have - * the same amount of memory. Because they are - * interleaved, it will look like both CSes have the - * full amount of memory. Save the size for both as - * half the amount we found on CS0, if interleaved. - */ - if (f17_cs_interleaved(pvt, ctrl, cs1)) - size1 = size0 = (size0 >> 1); - else - size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1); - } + cs_mode = f17_get_cs_mode(dimm, ctrl, pvt); + + size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0); + size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1); amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", cs0, size0, @@ -1569,18 +1557,54 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, return ddr3_cs_size(cs_mode, false); } -static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc, +static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, unsigned int cs_mode, int csrow_nr) { - u32 base_addr = pvt->csels[umc].csbases[csrow_nr]; + u32 addr_mask_orig, addr_mask_deinterleaved; + u32 msb, weight, num_zero_bits; + int dimm, size = 0; - /* Each mask is used for every two base addresses. */ - u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1]; + /* No Chip Selects are enabled. */ + if (!cs_mode) + return size; - /* Register [31:1] = Address [39:9]. Size is in kBs here. */ - u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1; + /* Requested size of an even CS but none are enabled. */ + if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1)) + return size; - edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask); + /* Requested size of an odd CS but none are enabled. */ + if (!(cs_mode & CS_ODD) && (csrow_nr & 1)) + return size; + + /* + * There is one mask per DIMM, and two Chip Selects per DIMM. + * CS0 and CS1 -> DIMM0 + * CS2 and CS3 -> DIMM1 + */ + dimm = csrow_nr >> 1; + + addr_mask_orig = pvt->csels[umc].csmasks[dimm]; + + /* + * The number of zero bits in the mask is equal to the number of bits + * in a full mask minus the number of bits in the current mask. + * + * The MSB is the number of bits in the full mask because BIT[0] is + * always 0. + */ + msb = fls(addr_mask_orig) - 1; + weight = hweight_long(addr_mask_orig); + num_zero_bits = msb - weight; + + /* Take the number of zero bits off from the top of the mask. */ + addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); + + edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm); + edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig); + edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved); + + /* Register [31:1] = Address [39:9]. Size is in kBs here. */ + size = (addr_mask_deinterleaved >> 2) + 1; /* Return size in MBs. */ return size >> 10; @@ -2245,7 +2269,7 @@ static struct amd64_family_type family_types[] = { .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6, .ops = { .early_channel_count = f17_early_channel_count, - .dbam_to_cs = f17_base_addr_to_cs_size, + .dbam_to_cs = f17_addr_mask_to_cs_size, } }, [F17_M10H_CPUS] = { @@ -2254,7 +2278,7 @@ static struct amd64_family_type family_types[] = { .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6, .ops = { .early_channel_count = f17_early_channel_count, - .dbam_to_cs = f17_base_addr_to_cs_size, + .dbam_to_cs = f17_addr_mask_to_cs_size, } }, [F17_M30H_CPUS] = { @@ -2263,7 +2287,7 @@ static struct amd64_family_type family_types[] = { .f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6, .ops = { .early_channel_count = f17_early_channel_count, - .dbam_to_cs = f17_base_addr_to_cs_size, + .dbam_to_cs = f17_addr_mask_to_cs_size, } }, }; @@ -2822,10 +2846,12 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) int csrow_nr = csrow_nr_orig; u32 cs_mode, nr_pages; - if (!pvt->umc) + if (!pvt->umc) { csrow_nr >>= 1; - - cs_mode = DBAM_DIMM(csrow_nr, dbam); + cs_mode = DBAM_DIMM(csrow_nr, dbam); + } else { + cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt); + } nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr); nr_pages <<= 20 - PAGE_SHIFT; -- GitLab From 8a2eaab7daf03b23ac902481218034ae2fae5e16 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Thu, 22 Aug 2019 00:00:00 +0000 Subject: [PATCH 4165/7155] EDAC/amd64: Decode syndrome before translating address AMD Family 17h systems currently require address translation in order to report the system address of a DRAM ECC error. This is currently done before decoding the syndrome information. The syndrome information does not depend on the address translation, so the proper EDAC csrow/channel reporting can function without the address. However, the syndrome information will not be decoded if the address translation fails. Decode the syndrome information before doing the address translation. The syndrome information is architecturally defined in MCA_SYND and can be considered robust. The address translation is system-specific and may fail on newer systems without proper updates to the translation algorithm. Fixes: 713ad54675fd ("EDAC, amd64: Define and register UMC error decode function") Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-6-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8f300c0714b8..e4bc48201b0c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2574,13 +2574,6 @@ static void decode_umc_error(int node_id, struct mce *m) err.channel = find_umc_channel(m); - if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) { - err.err_code = ERR_NORM_ADDR; - goto log_error; - } - - error_address_to_page_and_offset(sys_addr, &err); - if (!(m->status & MCI_STATUS_SYNDV)) { err.err_code = ERR_SYND; goto log_error; @@ -2597,6 +2590,13 @@ static void decode_umc_error(int node_id, struct mce *m) err.csrow = m->synd & 0x7; + if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) { + err.err_code = ERR_NORM_ADDR; + goto log_error; + } + + error_address_to_page_and_offset(sys_addr, &err); + log_error: __log_ecc_error(mci, &err, ecc_type); } -- GitLab From ff7240ccf0cdab86762635840c6d62eec7147d18 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Tue, 30 Jul 2019 10:53:10 +0200 Subject: [PATCH 4166/7155] KVM: PPC: Book3S: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the error below triggered by `-Wimplicit-fallthrough`, by tagging it as an expected fall-through. arch/powerpc/kvm/book3s_32_mmu.c: In function ‘kvmppc_mmu_book3s_32_xlate_pte’: arch/powerpc/kvm/book3s_32_mmu.c:241:21: error: this statement may fall through [-Werror=implicit-fallthrough=] pte->may_write = true; ~~~~~~~~~~~~~~~^~~~~~ arch/powerpc/kvm/book3s_32_mmu.c:242:5: note: here case 3: ^~~~ Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/book3s_32_mmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c index 653936177857..18f244aad7aa 100644 --- a/arch/powerpc/kvm/book3s_32_mmu.c +++ b/arch/powerpc/kvm/book3s_32_mmu.c @@ -239,6 +239,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, case 2: case 6: pte->may_write = true; + /* fall through */ case 3: case 5: case 7: -- GitLab From d22deab6960a6cb015a36e74a2dcbab6ca9f5544 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Tue, 20 Aug 2019 16:13:49 +1000 Subject: [PATCH 4167/7155] KVM: PPC: Book3S HV: Define usage types for rmap array in guest memslot The rmap array in the guest memslot is an array of size number of guest pages, allocated at memslot creation time. Each rmap entry in this array is used to store information about the guest page to which it corresponds. For example for a hpt guest it is used to store a lock bit, rc bits, a present bit and the index of a hpt entry in the guest hpt which maps this page. For a radix guest which is running nested guests it is used to store a pointer to a linked list of nested rmap entries which store the nested guest physical address which maps this guest address and for which there is a pte in the shadow page table. As there are currently two uses for the rmap array, and the potential for this to expand to more in the future, define a type field (being the top 8 bits of the rmap entry) to be used to define the type of the rmap entry which is currently present and define two values for this field for the two current uses of the rmap array. Since the nested case uses the rmap entry to store a pointer, define this type as having the two high bits set as is expected for a pointer. Define the hpt entry type as having bit 56 set (bit 7 IBM bit ordering). Signed-off-by: Suraj Jitindar Singh Signed-off-by: Paul Mackerras --- arch/powerpc/include/asm/kvm_host.h | 22 ++++++++++++++++++---- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index e6e5f59aaa97..6fb5fb4779e0 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -232,11 +232,25 @@ struct revmap_entry { }; /* - * We use the top bit of each memslot->arch.rmap entry as a lock bit, - * and bit 32 as a present flag. The bottom 32 bits are the - * index in the guest HPT of a HPTE that points to the page. + * The rmap array of size number of guest pages is allocated for each memslot. + * This array is used to store usage specific information about the guest page. + * Below are the encodings of the various possible usage types. */ -#define KVMPPC_RMAP_LOCK_BIT 63 +/* Free bits which can be used to define a new usage */ +#define KVMPPC_RMAP_TYPE_MASK 0xff00000000000000 +#define KVMPPC_RMAP_NESTED 0xc000000000000000 /* Nested rmap array */ +#define KVMPPC_RMAP_HPT 0x0100000000000000 /* HPT guest */ + +/* + * rmap usage definition for a hash page table (hpt) guest: + * 0x0000080000000000 Lock bit + * 0x0000018000000000 RC bits + * 0x0000000100000000 Present bit + * 0x00000000ffffffff HPT index bits + * The bottom 32 bits are the index in the guest HPT of a HPTE that points to + * the page. + */ +#define KVMPPC_RMAP_LOCK_BIT 43 #define KVMPPC_RMAP_RC_SHIFT 32 #define KVMPPC_RMAP_REFERENCED (HPTE_R_R << KVMPPC_RMAP_RC_SHIFT) #define KVMPPC_RMAP_PRESENT 0x100000000ul diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 63e0ce91e29d..7186c65c61c9 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -99,7 +99,7 @@ void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, } else { rev->forw = rev->back = pte_index; *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) | - pte_index | KVMPPC_RMAP_PRESENT; + pte_index | KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_HPT; } unlock_rmap(rmap); } -- GitLab From 56e7c8e021443d7f07e1399f86720448ee8377c5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 28 Jul 2019 22:59:44 +0800 Subject: [PATCH 4168/7155] ARM: dts: sun8i: a83t: Enable HDMI output on Cubietruck Plus The Cubietruck Plus has an HDMI connector tied to the HDMI output of the SoC. Enables display output via HDMI on the Cubietruck Plus. The connector device node is named "hdmi-connector" as there is also a display port connector, which is tied to the MIPI DSI output of the SoC through a MIPI-DSI-to-DP bridge. This part is not supported yet. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- .../boot/dts/sun8i-a83t-cubietruck-plus.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts index ea299d3d84d0..fb928503ad45 100644 --- a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts +++ b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts @@ -60,6 +60,17 @@ stdout-path = "serial0:115200n8"; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + leds { compatible = "gpio-leds"; @@ -153,6 +164,10 @@ cpu-supply = <®_dcdc3>; }; +&de { + status = "okay"; +}; + &ehci0 { /* GL830 USB-to-SATA bridge here */ status = "okay"; @@ -172,6 +187,16 @@ status = "okay"; }; +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &mdio { rgmii_phy: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; -- GitLab From 802cbe1b46dca72c922f1ed33333e1d19e4c988e Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 6 Aug 2019 17:57:43 +0200 Subject: [PATCH 4169/7155] arm64: dts: allwinner: orange-pi-3: Enable HDMI output Orange Pi 3 has a DDC_CEC_EN signal connected to PH2, that enables the DDC I2C bus voltage shifter. Before EDID can be read, we need to pull PH2 high. This is realized by the ddc-en-gpios property. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-h6-orangepi-3.dts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts index 17d496990108..eda9d5f640b9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts @@ -21,6 +21,18 @@ stdout-path = "serial0:115200n8"; }; + connector { + compatible = "hdmi-connector"; + ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + leds { compatible = "gpio-leds"; @@ -50,6 +62,10 @@ cpu-supply = <®_dcdca>; }; +&de { + status = "okay"; +}; + &ehci0 { status = "okay"; }; @@ -58,6 +74,16 @@ status = "okay"; }; +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &mmc0 { vmmc-supply = <®_cldo1>; cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ -- GitLab From d400cc4ad18f55a8253b2694f5594738e5cfacc2 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 28 Jul 2019 11:12:26 +0800 Subject: [PATCH 4170/7155] dt-bindings: arm: sunxi: add binding for Lichee Zero Plus core board The Lichee Zero Plus is a core board made by Sipeed, with a microUSB connector on it, TF slot or WSON8 SD chip, optional eMMC or SPI Flash. It has a gold finger connector for expansion, and UART is available from reserved pins w/ 2.54mm pitch. The board can use either SoChip S3 or Allwinner V3L SoCs. Add the device tree binding of the basic version of the core board -- w/o eMMC or SPI Flash, w/ TF slot or WSON8 SD, and use S3 SoC. Signed-off-by: Icenowy Zheng Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 000a00d12d6a..8888f6fc68ad 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -353,6 +353,12 @@ properties: - const: licheepi,licheepi-zero - const: allwinner,sun8i-v3s + - description: Lichee Zero Plus (with S3, without eMMC/SPI Flash) + items: + - const: sipeed,lichee-zero-plus + - const: sochip,s3 + - const: allwinner,sun8i-v3 + - description: Linksprite PCDuino items: - const: linksprite,a10-pcduino -- GitLab From 11d1bdead79c0df33ba831d307af76730e4c1559 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 28 Jul 2019 11:12:25 +0800 Subject: [PATCH 4171/7155] ARM: sunxi: dts: s3/s3l/v3: add DTSI files for S3/S3L/V3 SoCs The Allwinner S3/S3L/V3 SoCs all share the same die with the V3s SoC, but with more GPIO wired out of the package. Add a DTSI file for these SoCs. It just replaces some compatible strings of the V3s DTSI now. As these SoCs share the same feature set on Linux, we use the first known chip (V3) as the file's name. Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-v3.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-v3.dtsi diff --git a/arch/arm/boot/dts/sun8i-v3.dtsi b/arch/arm/boot/dts/sun8i-v3.dtsi new file mode 100644 index 000000000000..6ae8645ade50 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-v3.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 Icenowy Zheng + */ + +#include "sun8i-v3s.dtsi" + +&ccu { + compatible = "allwinner,sun8i-v3-ccu"; +}; + +&pio { + compatible = "allwinner,sun8i-v3-pinctrl"; +}; -- GitLab From 6f002c57c74616ab2bfd236f48bf254c30c5f36a Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 28 Jul 2019 11:12:27 +0800 Subject: [PATCH 4172/7155] ARM: dts: sun8i: s3: add devicetree for Lichee zero plus w/ S3 Lichee zero plus is a core board made by Sipeed, which includes on-board TF slot or SMT SD NAND, and optional SPI NOR or eMMC, a UART debug header, a microUSB slot and a gold finger connector for expansion. It can use either Sochip S3 or Allwinner S3L SoC. Add the basic device tree for the core board, w/o optional onboard storage, and with S3 SoC. Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/sun8i-s3-lichee-zero-plus.dts | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9159fa2cea90..e320460a952b 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1114,6 +1114,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-r16-nintendo-super-nes-classic.dtb \ sun8i-r16-parrot.dtb \ sun8i-r40-bananapi-m2-ultra.dtb \ + sun8i-s3-lichee-zero-plus.dtb \ sun8i-t3-cqa3t-bv3.dtb \ sun8i-v3s-licheepi-zero.dtb \ sun8i-v3s-licheepi-zero-dock.dtb \ diff --git a/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts new file mode 100644 index 000000000000..d18192d51d1b --- /dev/null +++ b/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 Icenowy Zheng + */ + +/dts-v1/; +#include "sun8i-v3.dtsi" + +#include + +/ { + model = "Sipeed Lichee Zero Plus"; + compatible = "sipeed,lichee-zero-plus", "sochip,s3", + "allwinner,sun8i-v3"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&mmc0 { + broken-cd; + bus-width = <4>; + vmmc-supply = <®_vcc3v3>; + status = "okay"; +}; + +&uart0 { + pinctrl-0 = <&uart0_pb_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usb_otg { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; -- GitLab From f95b598df4195c7e2a7116ba3eeb3742a4cb3e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 12 Aug 2019 12:51:14 +0200 Subject: [PATCH 4173/7155] arm64: dts: allwinner: Add SPDIF node for Allwinner H6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Allwinner H6 has a SPDIF controller called OWA (One Wire Audio). Only one pinmuxing is available so set it as default. Signed-off-by: Clément Péron Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index e8bed58e7246..02d79c6431c5 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -282,6 +282,11 @@ bias-pull-up; }; + spdif_tx_pin: spdif-tx-pin { + pins = "PH7"; + function = "spdif"; + }; + uart0_ph_pins: uart0-ph-pins { pins = "PH0", "PH1"; function = "uart0"; @@ -411,6 +416,21 @@ }; }; + spdif: spdif@5093000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-spdif"; + reg = <0x05093000 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>; + clock-names = "apb", "spdif"; + resets = <&ccu RST_BUS_SPDIF>; + dmas = <&dma 2>; + dma-names = "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx_pin>; + status = "disabled"; + }; + usb2otg: usb@5100000 { compatible = "allwinner,sun50i-h6-musb", "allwinner,sun8i-a33-musb"; -- GitLab From 45dd5cf87291fabcef8ce8817d8f2277ccdd14f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 12 Aug 2019 12:51:15 +0200 Subject: [PATCH 4174/7155] arm64: dts: allwinner: h6: Enable SPDIF for Beelink GS1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beelink GS1 board has a SPDIF out connector, so enable it in the device-tree and add a simple SPDIF soundcard. Signed-off-by: Clément Péron Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-h6-beelink-gs1.dts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts index 680dc29cb089..675c602b0e33 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts @@ -51,6 +51,24 @@ regulator-max-microvolt = <5000000>; regulator-always-on; }; + + sound-spdif { + compatible = "simple-audio-card"; + simple-audio-card,name = "sun50i-h6-spdif"; + + simple-audio-card,cpu { + sound-dai = <&spdif>; + }; + + simple-audio-card,codec { + sound-dai = <&spdif_out>; + }; + }; + + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; }; &de { @@ -247,6 +265,10 @@ vcc-pm-supply = <®_aldo1>; }; +&spdif { + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; -- GitLab From f46f408c152ac925e56c0f38138ae49ba16bbc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 12 Aug 2019 12:23:55 +0200 Subject: [PATCH 4175/7155] arm64: dts: allwinner: Enable DDC regulator for Beelink GS1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beelink GS1 has a DDC I2C bus voltage shifter. This is actually missing and video is limited to 1024x768 due to missing EDID information. Add the DDC regulator in the device-tree. Signed-off-by: Clément Péron Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts index 675c602b0e33..1d05d570142f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts @@ -25,6 +25,7 @@ connector { compatible = "hdmi-connector"; type = "a"; + ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ port { hdmi_con_in: endpoint { -- GitLab From 968f2c9169399fce43c11a89cbf4ac697f86de6e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 14 Aug 2019 12:22:08 +0800 Subject: [PATCH 4176/7155] ARM: dts: sunxi: Add mdio bus sub-node to GMAC The DWMAC binding never supported having the Ethernet PHY node as a direct child to the controller, nor did it support the "phy" property as a way to specify which Ethernet PHY to use. What seemed to work was simply the implementation ignoring the "phy" property and instead probing all addresses on the MDIO bus and using the first available one. The recent switch from "phy" to "phy-handle" breaks the assumptions of the implementation, and does not match what the binding requires. The binding requires that if an MDIO bus is described, it shall be a sub-node with the "snps,dwmac-mdio" compatible string. Add a device node for the MDIO bus, and move the Ethernet PHY node under it. Also fix up the #address-cells and #size-cells properties where needed. Fixes: de332de26d19 ("ARM: dts: sunxi: Switch from phy to phy-handle") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-colombus.dts | 10 ++++++---- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 16 +++++++++------- arch/arm/boot/dts/sun6i-a31-i7.dts | 10 ++++++---- arch/arm/boot/dts/sun6i-a31-m9.dts | 10 ++++++---- .../boot/dts/sun6i-a31-mele-a1000g-quad.dts | 10 ++++++---- arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++++-- arch/arm/boot/dts/sun6i-a31s-cs908.dts | 9 ++++++--- arch/arm/boot/dts/sun6i-a31s-sina31s.dts | 10 ++++++---- .../boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts | 14 ++++++++------ .../boot/dts/sun7i-a20-bananapi-m1-plus.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-bananapi.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-bananapro.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 18 ++++++++++-------- arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-icnova-swac.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-itead-ibox.dts | 2 ++ arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts | 2 -- arch/arm/boot/dts/sun7i-a20-m3.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts | 10 ++++++---- .../boot/dts/sun7i-a20-olimex-som204-evb.dts | 18 ++++++++++-------- arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts | 10 ++++++---- .../arm/boot/dts/sun7i-a20-olinuxino-lime2.dts | 10 ++++++---- .../arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-orangepi.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20-pcduino3.dts | 10 ++++++---- .../boot/dts/sun7i-a20-wits-pro-a20-dkt.dts | 10 ++++++---- arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++-- arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 10 ++++++---- arch/arm/boot/dts/sun9i-a80-optimus.dts | 2 ++ arch/arm/boot/dts/sun9i-a80.dtsi | 8 ++++++-- 34 files changed, 203 insertions(+), 132 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index 50092b0bd0fe..93a15eaaa8cb 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -79,10 +79,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -104,6 +100,12 @@ }; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v0>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 7c611ddbaf2f..049e6ab3cf56 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -156,13 +156,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; - reset-assert-us = <10000>; - reset-deassert-us = <30000>; - }; }; &hdmi { @@ -199,6 +192,15 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <30000>; + }; +}; + &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/sun6i-a31-i7.dts index ebb0b4710afb..6cc8ccf53d88 100644 --- a/arch/arm/boot/dts/sun6i-a31-i7.dts +++ b/arch/arm/boot/dts/sun6i-a31-i7.dts @@ -120,10 +120,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -142,6 +138,12 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts index 4910c6ccf2f7..a645c8f4257c 100644 --- a/arch/arm/boot/dts/sun6i-a31-m9.dts +++ b/arch/arm/boot/dts/sun6i-a31-m9.dts @@ -88,10 +88,6 @@ phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &ir { @@ -100,6 +96,12 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts index 703e1c19b407..648f24746234 100644 --- a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts +++ b/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts @@ -88,10 +88,6 @@ phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &ir { @@ -100,6 +96,12 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 9ddde111f675..8d0db8a2f9d1 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -939,8 +939,12 @@ snps,fixed-burst; snps,force_sf_dma_mode; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; + + mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; }; crypto: crypto-engine@1c15000 { diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/sun6i-a31s-cs908.dts index 6e9ec3f1695e..1d15e15011c6 100644 --- a/arch/arm/boot/dts/sun6i-a31s-cs908.dts +++ b/arch/arm/boot/dts/sun6i-a31s-cs908.dts @@ -70,9 +70,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &ir { @@ -81,6 +78,12 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &ohci1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts index c92779bc8f85..0af48e143b66 100644 --- a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts +++ b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts @@ -119,10 +119,6 @@ phy-mode = "mii"; phy-supply = <®_dldo1>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -160,6 +156,12 @@ }; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts index e993b2d8ddd0..708caee52425 100644 --- a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts +++ b/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts @@ -96,7 +96,15 @@ phy-mode = "rgmii"; phy-supply = <®_dldo1>; status = "okay"; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&s_ir_rx_pin>; + status = "okay"; +}; +&mdio { phy1: ethernet-phy@1 { reg = <1>; reset-gpios = <&pio 0 21 GPIO_ACTIVE_LOW>; /* PA21 */ @@ -105,12 +113,6 @@ }; }; -&ir { - pinctrl-names = "default"; - pinctrl-0 = <&s_ir_rx_pin>; - status = "okay"; -}; - &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts index c601ecf5ab35..32d5d45a35c0 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts @@ -133,10 +133,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -171,6 +167,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts index c5730b30a15d..bb3987e101c2 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts @@ -135,10 +135,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -171,6 +167,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/sun7i-a20-bananapro.dts index 86f4ebb77703..01ccff756996 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapro.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapro.dts @@ -113,10 +113,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -143,6 +139,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index e322f0f06003..b8203e4ef21c 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -118,10 +118,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -161,6 +157,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &ohci0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index a8f7f63fdde1..8c8dee6ea461 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -153,10 +153,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -194,6 +190,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index 322717cb0b9a..3def2a330598 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -104,14 +104,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_vdd>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ - reset-assert-us = <10000>; - /* wait 1s after reset, otherwise fail to read phy id */ - reset-deassert-us = <1000000>; - }; }; &i2c0 { @@ -145,6 +137,16 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ + reset-assert-us = <10000>; + /* wait 1s after reset, otherwise fail to read phy id */ + reset-deassert-us = <1000000>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v0>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index 8a610dacb983..358ed5f1b1c1 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -119,10 +119,6 @@ phy-mode = "mii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -145,6 +141,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts index a20e91c8dbe5..413505f45a81 100644 --- a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts +++ b/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts @@ -79,10 +79,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -99,6 +95,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts index c27567c0b027..946c27278321 100644 --- a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts +++ b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts @@ -100,7 +100,9 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; +}; +&gmac_mdio { phy1: ethernet-phy@1 { reg = <1>; }; diff --git a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts index 3e170cfac86a..17fa8901fc00 100644 --- a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts +++ b/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts @@ -123,8 +123,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - /delete-property/#address-cells; - /delete-property/#size-cells; fixed-link { speed = <1000>; diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts index bde0ef783e71..6bff9e731fc3 100644 --- a/arch/arm/boot/dts/sun7i-a20-m3.dts +++ b/arch/arm/boot/dts/sun7i-a20-m3.dts @@ -85,10 +85,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -111,6 +107,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts index f419b9ee9d1e..6f9c54b8e49a 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts @@ -114,10 +114,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -202,6 +198,12 @@ }; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts index d3d03b7ffb1a..230d62a6b8f1 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts @@ -109,14 +109,6 @@ phy-mode = "rgmii"; phy-supply = <®_vcc3v3>; status = "okay"; - - phy3: ethernet-phy@3 { - reg = <3>; - reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ - reset-assert-us = <10000>; - /* wait 1s after reset, otherwise fail to read phy id */ - reset-deassert-us = <1000000>; - }; }; &hdmi { @@ -161,6 +153,16 @@ status = "okay"; }; +&gmac_mdio { + phy3: ethernet-phy@3 { + reg = <3>; + reset-gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */ + reset-assert-us = <10000>; + /* wait 1s after reset, otherwise fail to read phy id */ + reset-deassert-us = <1000000>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts index 70a883276d34..2adbac860119 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts @@ -109,10 +109,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -149,6 +145,12 @@ }; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 0fe657e062a7..9ba62774e89a 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -114,10 +114,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -154,6 +150,12 @@ vref-supply = <®_vcc3v0>; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index 559736961b54..359bd0d5b3b1 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -121,10 +121,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -215,6 +211,12 @@ }; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts index a94ff50bcf73..2e328d2cefc1 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts @@ -124,10 +124,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -158,6 +154,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts index 956579a10b5f..d75b2e2bab28 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts @@ -100,10 +100,6 @@ phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -124,6 +120,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts index 993fb97d19df..fce2f7fcd084 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts @@ -117,10 +117,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &hdmi { @@ -149,6 +145,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index 02e321523d0e..cc8271d777b8 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -125,10 +125,6 @@ phy-handle = <&phy1>; phy-mode = "mii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -149,6 +145,12 @@ status = "okay"; }; +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts index 9dfe7e2a08cc..3bfae98f3cc3 100644 --- a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts +++ b/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts @@ -84,10 +84,6 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c0 { @@ -110,6 +106,12 @@ #include "axp209.dtsi" +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 9ad8e445b240..651d7fe6b8ba 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1437,8 +1437,12 @@ snps,fixed-burst; snps,force_sf_dma_mode; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; + + gmac_mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; }; hstimer@1c60000 { diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts index 650890b049e2..d3b337b043a1 100644 --- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts +++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts @@ -132,10 +132,6 @@ phy-mode = "rgmii"; phy-supply = <®_cldo1>; status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; }; &i2c3 { @@ -144,6 +140,12 @@ status = "okay"; }; +&mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts index 03ad25534f20..bbc6335e5631 100644 --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts @@ -127,7 +127,9 @@ phy-mode = "rgmii"; phy-supply = <®_cldo1>; status = "okay"; +}; +&mdio { phy1: ethernet-phy@1 { reg = <1>; }; diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 310cd972ee5b..c34d505c7efe 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -331,8 +331,12 @@ snps,fixed-burst; snps,force_sf_dma_mode; status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; + + mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; }; ehci0: usb@a00000 { -- GitLab From 88dc4e7ea714787642708fb0fc460bb7e262b234 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Fri, 16 Aug 2019 14:13:08 +0530 Subject: [PATCH 4177/7155] dt-bindings: i2c: mv64xxx: Add compatible for the H6 i2c node. Allwinner H6 have a mv64xxx i2c interface available to be used. Signed-off-by: Bhushan Shah Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml index 001f2b7abad0..c779000515d6 100644 --- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml @@ -26,6 +26,9 @@ properties: - items: - const: allwinner,sun50i-a64-i2c - const: allwinner,sun6i-a31-i2c + - items: + - const: allwinner,sun50i-h6-i2c + - const: allwinner,sun6i-a31-i2c - const: marvell,mv64xxx-i2c - const: marvell,mv78230-i2c -- GitLab From 89336e1f096d6e8d99e74df63652f8e64d788cac Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Fri, 16 Aug 2019 14:13:09 +0530 Subject: [PATCH 4178/7155] arm64: allwinner: h6: add I2C nodes Add device-tree nodes for i2c0 to i2c2, and also add relevant pinctrl nodes. Suggested-by: Icenowy Zheng Signed-off-by: Bhushan Shah Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 60 +++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 02d79c6431c5..67b732e34091 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -256,6 +256,21 @@ function = "hdmi"; }; + i2c0_pins: i2c0-pins { + pins = "PD25", "PD26"; + function = "i2c0"; + }; + + i2c1_pins: i2c1-pins { + pins = "PH5", "PH6"; + function = "i2c1"; + }; + + i2c2_pins: i2c2-pins { + pins = "PD23", "PD24"; + function = "i2c2"; + }; + mmc0_pins: mmc0-pins { pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; @@ -396,6 +411,48 @@ status = "disabled"; }; + i2c0: i2c@5002000 { + compatible = "allwinner,sun50i-h6-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x05002000 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_I2C0>; + resets = <&ccu RST_BUS_I2C0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@5002400 { + compatible = "allwinner,sun50i-h6-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x05002400 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_I2C1>; + resets = <&ccu RST_BUS_I2C1>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@5002800 { + compatible = "allwinner,sun50i-h6-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x05002800 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_I2C2>; + resets = <&ccu RST_BUS_I2C2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + emac: ethernet@5020000 { compatible = "allwinner,sun50i-h6-emac", "allwinner,sun50i-a64-emac"; @@ -717,7 +774,8 @@ }; r_i2c: i2c@7081400 { - compatible = "allwinner,sun6i-a31-i2c"; + compatible = "allwinner,sun50i-h6-i2c", + "allwinner,sun6i-a31-i2c"; reg = <0x07081400 0x400>; interrupts = ; clocks = <&r_ccu CLK_R_APB2_I2C>; -- GitLab From 8e3efec9b97fc797d4558b72ac2c1587e16cae6c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Fri, 16 Aug 2019 22:53:41 +0200 Subject: [PATCH 4179/7155] dt-bindings: arm: sunxi: Add compatible for Tanix TX6 board Add new Oranth Tanix TX6 board compatible string to the bindings documentation. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 8888f6fc68ad..93dc4c607f07 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -677,6 +677,11 @@ properties: - const: sinlinx,sina33 - const: allwinner,sun8i-a33 + - description: Tanix TX6 + items: + - const: oranth,tanix-tx6 + - const: allwinner,sun50i-h6 + - description: TBS A711 Tablet items: - const: tbs-biometrics,a711 -- GitLab From 652a458eb92018c5126701e721255356fdab94a9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Fri, 16 Aug 2019 22:53:42 +0200 Subject: [PATCH 4180/7155] arm64: dts: allwinner: h6: Introduce Tanix TX6 board Tanix TX6 is an Allwinner H6 based TV box, which supports: - Allwinner H6 Quad-core 64-bit ARM Cortex-A53 - GPU Mali-T720 - 4GiB DDR3 RAM (3GiB useable) - 100Mbps EMAC via AC200 EPHY - Cdtech 47822BS Wifi/BT - 2x USB 2.0 Host and 1x USB 3.0 Host - HDMI port - IR receiver - 64GiB eMMC - 5V/2A DC power supply Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/Makefile | 1 + .../dts/allwinner/sun50i-h6-tanix-tx6.dts | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index f6db0611cb85..395fe76f6819 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -25,3 +25,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts new file mode 100644 index 000000000000..7e7cb10e3d96 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (c) 2019 Jernej Skrabec + */ + +/dts-v1/; + +#include "sun50i-h6.dtsi" + +#include + +/ { + model = "Tanix TX6"; + compatible = "oranth,tanix-tx6", "allwinner,sun50i-h6"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector { + compatible = "hdmi-connector"; + ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + vmmc-supply = <®_vcc3v3>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + bus-width = <4>; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; + +&r_ir { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; +}; + +&usb2otg { + dr_mode = "host"; + status = "okay"; +}; + +&usb2phy { + status = "okay"; +}; -- GitLab From 0988e6c2cd6cd64f7272c18fe58f3fca26b9120d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 13 Aug 2019 14:47:40 +0200 Subject: [PATCH 4181/7155] dt-bindings: mfd: Convert Allwinner GPADC bindings to a schema The Allwinner SoCs have an embedded GPADC that is doing thermal reading as well, supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard --- .../iio/adc/allwinner,sun8i-a33-ths.yaml | 43 +++++++++++ .../bindings/mfd/allwinner,sun4i-a10-ts.yaml | 76 +++++++++++++++++++ .../devicetree/bindings/mfd/sun4i-gpadc.txt | 59 -------------- 3 files changed, 119 insertions(+), 59 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml create mode 100644 Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml delete mode 100644 Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt diff --git a/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml b/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml new file mode 100644 index 000000000000..d74962c0f5ae --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/allwinner,sun8i-a33-ths.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A33 Thermal Sensor Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#io-channel-cells": + const: 0 + + "#thermal-sensor-cells": + const: 0 + + compatible: + const: allwinner,sun8i-a33-ths + + reg: + maxItems: 1 + +required: + - "#io-channel-cells" + - "#thermal-sensor-cells" + - compatible + - reg + +additionalProperties: false + +examples: + - | + ths: ths@1c25000 { + compatible = "allwinner,sun8i-a33-ths"; + reg = <0x01c25000 0x100>; + #thermal-sensor-cells = <0>; + #io-channel-cells = <0>; + }; + +... diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml new file mode 100644 index 000000000000..4b1a09acb98b --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/allwinner,sun4i-a10-ts.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Resistive Touchscreen Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#thermal-sensor-cells": + const: 0 + + compatible: + enum: + - allwinner,sun4i-a10-ts + - allwinner,sun5i-a13-ts + - allwinner,sun6i-a31-ts + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + allwinner,ts-attached: + $ref: /schemas/types.yaml#/definitions/flag + description: A touchscreen is attached to the controller + + allwinner,tp-sensitive-adjust: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 0 + maximum: 15 + default: 15 + description: Sensitivity of pen down detection + + allwinner,filter-type: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 0 + maximum: 3 + default: 1 + description: | + Select median and averaging filter. Sample used for median / + averaging filter: + 0: 4/2 + 1: 5/3 + 2: 8/4 + 3: 16/8 + +required: + - "#thermal-sensor-cells" + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + rtp: rtp@1c25000 { + compatible = "allwinner,sun4i-a10-ts"; + reg = <0x01c25000 0x100>; + interrupts = <29>; + allwinner,ts-attached; + #thermal-sensor-cells = <0>; + /* sensitive/noisy touch panel */ + allwinner,tp-sensitive-adjust = <0>; + allwinner,filter-type = <3>; + }; + +... diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt deleted file mode 100644 index 86dd8191b04c..000000000000 --- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt +++ /dev/null @@ -1,59 +0,0 @@ -Allwinner SoCs' GPADC Device Tree bindings ------------------------------------------- -The Allwinner SoCs all have an ADC that can also act as a thermal sensor -and sometimes as a touchscreen controller. - -Required properties: - - compatible: "allwinner,sun8i-a33-ths", - - reg: mmio address range of the chip, - - #thermal-sensor-cells: shall be 0, - - #io-channel-cells: shall be 0, - -Example: - ths: ths@1c25000 { - compatible = "allwinner,sun8i-a33-ths"; - reg = <0x01c25000 0x100>; - #thermal-sensor-cells = <0>; - #io-channel-cells = <0>; - }; - -sun4i, sun5i and sun6i SoCs are also supported via the older binding: - -sun4i resistive touchscreen controller --------------------------------------- - -Required properties: - - compatible: "allwinner,sun4i-a10-ts", "allwinner,sun5i-a13-ts" or - "allwinner,sun6i-a31-ts" - - reg: mmio address range of the chip - - interrupts: interrupt to which the chip is connected - - #thermal-sensor-cells: shall be 0 - -Optional properties: - - allwinner,ts-attached : boolean indicating that an actual touchscreen - is attached to the controller - - allwinner,tp-sensitive-adjust : integer (4 bits) - adjust sensitivity of pen down detection - between 0 (least sensitive) and 15 - (defaults to 15) - - allwinner,filter-type : integer (2 bits) - select median and averaging filter - samples used for median / averaging filter - 0: 4/2 - 1: 5/3 - 2: 8/4 - 3: 16/8 - (defaults to 1) - -Example: - - rtp: rtp@1c25000 { - compatible = "allwinner,sun4i-a10-ts"; - reg = <0x01c25000 0x100>; - interrupts = <29>; - allwinner,ts-attached; - #thermal-sensor-cells = <0>; - /* sensitive/noisy touch panel */ - allwinner,tp-sensitive-adjust = <0>; - allwinner,filter-type = <3>; - }; -- GitLab From 14c17ed24851746b20480d82eba8a67e6a572ea1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:23 +0200 Subject: [PATCH 4182/7155] ARM: dts: sun4i: Add missing timers interrupts The timer unit in the A10 has 6 interrupts available. List all of them. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index e88daa4ef1af..077d45c7db6f 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -803,7 +803,12 @@ timer@1c20c00 { compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; - interrupts = <22>; + interrupts = <22>, + <23>, + <24>, + <25>, + <67>, + <68>; clocks = <&osc24M>; }; -- GitLab From f49f797c2b4e79df328008bb995adbd180f72ed2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:24 +0200 Subject: [PATCH 4183/7155] ARM: dts: sun5i: Add missing timers interrupts The timer unit in the sun5i die has 6 interrupts available. List all of them. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 2fb438c4fe9d..4e725afe7203 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -588,7 +588,12 @@ timer@1c20c00 { compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; - interrupts = <22>; + interrupts = <22>, + <23>, + <24>, + <25>, + <67>, + <68>; clocks = <&ccu CLK_HOSC>; }; -- GitLab From 628f020d13209ffef6d12ad7868d8cf11ef22c95 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:25 +0200 Subject: [PATCH 4184/7155] ARM: dts: sun6i: Add missing timers interrupts The timer unit in the A31 has 6 interrupts available. List all of them. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 8d0db8a2f9d1..8176da53dadf 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -736,7 +736,8 @@ , , , - ; + , + ; clocks = <&osc24M>; }; -- GitLab From 2b9df83fa6b0d1c393c9aa0dfa0c87892b1ac807 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:26 +0200 Subject: [PATCH 4185/7155] ARM: dts: a23/a33: Change the timers compatible Unlike the A10 that has 6 timers available, the A23 and A33 has only two, with only two interrupts. Let's change the compatible to reflect that. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-a33.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index af2fa694a467..954489b4ec66 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -441,7 +441,7 @@ }; timer@1c20c00 { - compatible = "allwinner,sun4i-a10-timer"; + compatible = "allwinner,sun8i-a23-timer"; reg = <0x01c20c00 0xa0>; interrupts = , ; -- GitLab From df75eaac4938b0a8a5e4de65526a37e67bd33d94 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:27 +0200 Subject: [PATCH 4186/7155] ARM: dts: a83t: Change the timers compatible Unlike the A10 that has 6 timers available, the A83t has only two, with only two interrupts, just like the A23. Let's change the compatible to reflect that. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 13bc83191899..523be6611c50 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -806,7 +806,7 @@ }; timer@1c20c00 { - compatible = "allwinner,sun4i-a10-timer"; + compatible = "allwinner,sun8i-a23-timer"; reg = <0x01c20c00 0xa0>; interrupts = , ; -- GitLab From 19aeb5a80cfac916225aca6143ffb1785c780c51 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:28 +0200 Subject: [PATCH 4187/7155] ARM: dts: h3: Change the timers compatible Unlike the A10 that has 6 timers available, the H3 has only two, with only two interrupts, just like the A23. Let's change the compatible to reflect that. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 97550a40b6e1..224e105a994a 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -484,7 +484,7 @@ }; timer@1c20c00 { - compatible = "allwinner,sun4i-a10-timer"; + compatible = "allwinner,sun8i-a23-timer"; reg = <0x01c20c00 0xa0>; interrupts = , ; -- GitLab From 18742b249e37ef13967a34eaf26270a0a00477f6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2019 10:12:29 +0200 Subject: [PATCH 4188/7155] ARM: dts: v3s: Change the timers compatible Unlike the A10 that has 6 timers available, the v3s has only three, with only three interrupts. Let's change the compatible to reflect that, and add the missing interrupts. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-v3s.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index 20a3f11bddcc..ddbcc28dc541 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -327,10 +327,11 @@ }; timer@1c20c00 { - compatible = "allwinner,sun4i-a10-timer"; + compatible = "allwinner,sun8i-v3s-timer"; reg = <0x01c20c00 0xa0>; interrupts = , - ; + , + ; clocks = <&osc24M>; }; -- GitLab From 2063288662f2dbfa25d4bc25526f0543308bc077 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 21 Aug 2019 12:52:16 -0700 Subject: [PATCH 4189/7155] dt-bindings: arm: sunxi: Add compatible for A64 OlinuXino with eMMC A64 OLinuXino board from Olimex has three variants with onboard eMMC: A64-OLinuXino-1Ge16GW, A64-OLinuXino-1Ge4GW and A64-OLinuXino-2Ge8G-IND. In addition, there are two variants without eMMC. One without eMMC and one with SPI flash. This suggests the need for separate device tree for the three eMMC variants. Add new compatible string to the bindings documentation for the A64 OlinuXino board variant with on-board eMMC. Signed-off-by: Sunil Mohan Adapa Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 93dc4c607f07..972b1e9ee804 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -574,6 +574,11 @@ properties: - const: olimex,a64-olinuxino - const: allwinner,sun50i-a64 + - description: Olimex A64-OlinuXino (with eMMC) + items: + - const: olimex,a64-olinuxino-emmc + - const: allwinner,sun50i-a64 + - description: Olimex A64 Teres-I items: - const: olimex,a64-teres-i -- GitLab From 94f68f3a4b2ae71ef4cd4a4be94d76c98df9625b Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 21 Aug 2019 12:52:17 -0700 Subject: [PATCH 4190/7155] arm64: dts: allwinner: a64: Add A64 OlinuXino board (with eMMC) A64 OLinuXino board from Olimex has three variants with onboard eMMC: A64-OLinuXino-1Ge16GW, A64-OLinuXino-1Ge4GW and A64-OLinuXino-2Ge8G-IND. In addition, there are two variants without eMMC. One without eMMC and one with SPI flash. This suggests the need for separate device tree for the three eMMC variants. This patch has been tested on A64-OLinuXino-1Ge16GW with Linux 5.0 from Debain. Basic benchmarks using Flexible IO Tester show reasonable performance from the eMMC. eMMC - Random Write: 21.3MiB/s eMMC - Sequential Write: 68.2MiB/s SD Card - Random Write: 1690KiB/s SD Card - Sequential Write: 11.0MiB/s Changes: v3: Separate dts for eMMC variants v2: Fix descriptions for VCC and VCCQ Link: https://github.com/armbian/build/commit/174953de1eb09e6aa1ef7075066b573dba625398 Signed-off-by: Martin Ayotte [sunil@medhas.org Fix descriptions for VCC and VCCQ, separate dts for eMMC] Signed-off-by: Sunil Mohan Adapa Tested-by: Sunil Mohan Adapa Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/Makefile | 1 + .../allwinner/sun50i-a64-olinuxino-emmc.dts | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 395fe76f6819..d2418021768b 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-oceanic-5205-5inmfd.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino-emmc.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts new file mode 100644 index 000000000000..96ab0227e82d --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Martin Ayotte + * Copyright (C) 2019 Sunil Mohan Adapa + */ + +#include "sun50i-a64-olinuxino.dts" + +/ { + model = "Olimex A64-Olinuxino-eMMC"; + compatible = "olimex,a64-olinuxino-emmc", "allwinner,sun50i-a64"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_dcdc1>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; -- GitLab From ff6cd68d6601f9aae3eccd691af68f47cf81ec7d Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 8 Aug 2019 18:16:26 +0800 Subject: [PATCH 4191/7155] gpio: mpc8xxx: add ls1088a platform gpio node DT binding description ls1088a and ls1028a platform share common gpio node. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190808101628.36782-1-hui.song_1@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index baf95d93f85d..cd28e932bf50 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -4,7 +4,7 @@ Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, - ls1021a, ls1043a, ls2080a, ls1028a. + ls1021a, ls1043a, ls2080a, ls1028a, ls1088a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -39,10 +39,10 @@ gpio0: gpio@2300000 { }; -Example of gpio-controller node for a ls1028a SoC: +Example of gpio-controller node for a ls1028a/ls1088a SoC: gpio1: gpio@2300000 { - compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; + compatible = "fsl,ls1028a-gpio", "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = ; gpio-controller; -- GitLab From 7b732209eb5d78ab114ae5e2a480d7417f30a2b1 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 8 Aug 2019 18:16:28 +0800 Subject: [PATCH 4192/7155] gpio: mpc8xxx: add ls1088a platform special function ls1028a and ls1088a platform share common special function. The gpio hardware what they use is the same version. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190808101628.36782-3-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mpc8xxx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 1a680aa28769..16a47de29c94 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -319,6 +319,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = { { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,pq3-gpio", }, { .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, }, + { .compatible = "fsl,ls1088a-gpio", .data = &ls1028a_gpio_devtype, }, { .compatible = "fsl,qoriq-gpio", }, {} }; -- GitLab From 49751efbf63024816d2791e2a173b35c3112f32d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 15:38:45 +0200 Subject: [PATCH 4193/7155] gpio: zx: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Jonas Gorski Cc: Jun Nie Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809133845.30991-1-linus.walleij@linaro.org --- drivers/gpio/gpio-zx.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 8d9b9bf8510a..98cbaf0e415e 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -215,6 +215,7 @@ static int zx_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct zx_gpio *chip; + struct gpio_irq_chip *girq; int irq, id, ret; chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); @@ -242,31 +243,30 @@ static int zx_gpio_probe(struct platform_device *pdev) chip->gc.parent = dev; chip->gc.owner = THIS_MODULE; - ret = gpiochip_add_data(&chip->gc, chip); - if (ret) - return ret; - /* * irq_chip support */ writew_relaxed(0xffff, chip->base + ZX_GPIO_IM); writew_relaxed(0, chip->base + ZX_GPIO_IE); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - gpiochip_remove(&chip->gc); - return -ENODEV; - } + if (irq < 0) + return irq; + girq = &chip->gc.irq; + girq->chip = &zx_irqchip; + girq->parent_handler = zx_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; - ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip, - 0, handle_simple_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "could not add irqchip\n"); - gpiochip_remove(&chip->gc); + ret = gpiochip_add_data(&chip->gc, chip); + if (ret) return ret; - } - gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip, - irq, zx_irq_handler); platform_set_drvdata(pdev, chip); dev_info(dev, "ZX GPIO chip registered\n"); -- GitLab From e599256ab78b99614b361b551145f3f95c9b3041 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:19:16 +0200 Subject: [PATCH 4194/7155] gpio: vf610: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andrey Smirnov Cc: Andrew Lunn Cc: Dong Aisheng Cc: Stefan Agner Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809141916.20999-1-linus.walleij@linaro.org --- drivers/gpio/gpio-vf610.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 7ba668db171b..58776f2d69ff 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -243,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct vf610_gpio_port *port; struct gpio_chip *gc; + struct gpio_irq_chip *girq; struct irq_chip *ic; int i; int ret; @@ -318,10 +319,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) ic->irq_set_type = vf610_gpio_irq_set_type; ic->irq_set_wake = vf610_gpio_irq_set_wake; - ret = devm_gpiochip_add_data(dev, gc, port); - if (ret < 0) - return ret; - /* Mask all GPIO interrupts */ for (i = 0; i < gc->ngpio; i++) vf610_gpio_writel(0, port->base + PORT_PCR(i)); @@ -329,15 +326,20 @@ static int vf610_gpio_probe(struct platform_device *pdev) /* Clear the interrupt status register for all GPIO's */ vf610_gpio_writel(~0, port->base + PORT_ISFR); - ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add irqchip\n"); - return ret; - } - gpiochip_set_chained_irqchip(gc, ic, port->irq, - vf610_gpio_irq_handler); + girq = &gc->irq; + girq->chip = ic; + girq->parent_handler = vf610_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = port->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_edge_irq; - return 0; + return devm_gpiochip_add_data(dev, gc, port); } static struct platform_driver vf610_gpio_driver = { -- GitLab From 74639d66e1ec069d27eebb97b545916a86d983ea Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:40:45 +0200 Subject: [PATCH 4195/7155] gpio: tqmx86: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andrew Lunn Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809144045.26018-1-linus.walleij@linaro.org --- drivers/gpio/gpio-tqmx86.c | 41 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index d5880db7f9d4..07050cdbadb9 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -219,6 +219,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct tqmx86_gpio_data *gpio; struct gpio_chip *chip; + struct gpio_irq_chip *girq; void __iomem *io_base; struct resource *res; int ret, irq; @@ -264,12 +265,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = devm_gpiochip_add_data(dev, chip, gpio); - if (ret) { - dev_err(dev, "Could not register GPIO chip\n"); - goto out_pm_dis; - } - if (irq) { struct irq_chip *irq_chip = &gpio->irq_chip; u8 irq_status; @@ -287,23 +282,35 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); - ret = gpiochip_irqchip_add(chip, irq_chip, - 0, handle_simple_irq, - IRQ_TYPE_EDGE_BOTH); - if (ret) { - dev_err(dev, "Could not add irq chip\n"); + girq = &chip->irq; + girq->chip = irq_chip; + girq->parent_handler = tqmx86_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) { + ret = -ENOMEM; goto out_pm_dis; } + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + } - gpiochip_set_chained_irqchip(chip, irq_chip, - irq, tqmx86_gpio_irq_handler); + ret = devm_gpiochip_add_data(dev, chip, gpio); + if (ret) { + dev_err(dev, "Could not register GPIO chip\n"); + goto out_pm_dis; } /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ - clear_bit(0, chip->irq.valid_mask); - clear_bit(1, chip->irq.valid_mask); - clear_bit(2, chip->irq.valid_mask); - clear_bit(3, chip->irq.valid_mask); + if (irq) { + clear_bit(0, girq->valid_mask); + clear_bit(1, girq->valid_mask); + clear_bit(2, girq->valid_mask); + clear_bit(3, girq->valid_mask); + } dev_info(dev, "GPIO functionality initialized with %d pins\n", chip->ngpio); -- GitLab From d2b9c64443013197fbb71984e85f4c9551ffe26c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Aug 2019 10:21:15 +0200 Subject: [PATCH 4196/7155] ARM: dts: sun7i: Add CSI0 controller The CSI controller embedded in the A20 can be supported by our new driver. Let's add it to our DT. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 651d7fe6b8ba..524c1d5a7d0d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -376,6 +376,17 @@ num-cs = <1>; }; + csi0: csi@1c09000 { + compatible = "allwinner,sun7i-a20-csi0"; + reg = <0x01c09000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>, + <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>; + clock-names = "bus", "mod", "isp", "ram"; + resets = <&ccu RST_CSI0>; + status = "disabled"; + }; + emac: ethernet@1c0b000 { compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; @@ -774,6 +785,20 @@ function = "clk_out_b"; }; + /omit-if-no-ref/ + csi0_8bits_pins: csi-8bits-pins { + pins = "PE0", "PE2", "PE3", "PE4", "PE5", + "PE6", "PE7", "PE8", "PE9", "PE10", + "PE11"; + function = "csi0"; + }; + + /omit-if-no-ref/ + csi0_clk_pin: csi-clk-pin { + pins = "PE1"; + function = "csi0"; + }; + /omit-if-no-ref/ emac_pa_pins: emac-pa-pins { pins = "PA0", "PA1", "PA2", -- GitLab From d5d4aa1ec1983911b0e1c656c97da16332f85fc9 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 13 Aug 2019 09:15:47 +0300 Subject: [PATCH 4197/7155] MAINTAINERS: Remove FMC subsystem Cleanup MAINTAINERS from FMC record since the subsystem was removed. Cc: Pat Riehecky Fixes: 6a80b30086b8 ("fmc: Delete the FMC subsystem") Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20190813061547.17847-1-efremov@linux.com Reviewed-by: Federico Vaga Signed-off-by: Linus Walleij --- MAINTAINERS | 9 --------- 1 file changed, 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..b9d8bc8241b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6326,15 +6326,6 @@ S: Orphan L: linux-block@vger.kernel.org F: drivers/block/floppy.c -FMC SUBSYSTEM -M: Alessandro Rubini -W: http://www.ohwr.org/projects/fmc-bus -S: Supported -F: drivers/fmc/ -F: include/linux/fmc*.h -F: include/linux/ipmi-fru.h -K: fmc_d.*register - FPGA MANAGER FRAMEWORK M: Moritz Fischer L: linux-fpga@vger.kernel.org -- GitLab From af0bc634728c0bc6a3f66f911f227d5c6396db88 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 9 Aug 2019 15:43:07 +0200 Subject: [PATCH 4198/7155] soc: renesas: rmobile-sysc: Set GENPD_FLAG_ALWAYS_ON for always-on domain Currently the R-Mobile "always-on" PM Domain is implemented by returning -EBUSY from the generic_pm_domain.power_off() callback, and doing nothing in the generic_pm_domain.power_on() callback. However, this means the PM Domain core code is not aware of the semantics of this special domain, leading to boot warnings like the following on SH/R-Mobile SoCs: sh_cmt e6130000.timer: PM domain c5 will not be powered off Fix this by making the always-on nature of the domain explicit instead, by setting the GENPD_FLAG_ALWAYS_ON flag. This removes the need for the domain to provide power control callbacks. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Reviewed-by: Ulf Hansson --- drivers/soc/renesas/rmobile-sysc.c | 31 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c index 421ae1c887d8..54b616ad4a62 100644 --- a/drivers/soc/renesas/rmobile-sysc.c +++ b/drivers/soc/renesas/rmobile-sysc.c @@ -48,12 +48,8 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) static int rmobile_pd_power_down(struct generic_pm_domain *genpd) { struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); - unsigned int mask; + unsigned int mask = BIT(rmobile_pd->bit_shift); - if (rmobile_pd->bit_shift == ~0) - return -EBUSY; - - mask = BIT(rmobile_pd->bit_shift); if (rmobile_pd->suspend) { int ret = rmobile_pd->suspend(); @@ -80,14 +76,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) { - unsigned int mask; + unsigned int mask = BIT(rmobile_pd->bit_shift); unsigned int retry_count; int ret = 0; - if (rmobile_pd->bit_shift == ~0) - return 0; - - mask = BIT(rmobile_pd->bit_shift); if (__raw_readl(rmobile_pd->base + PSTR) & mask) return ret; @@ -122,11 +114,15 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) struct dev_power_governor *gov = rmobile_pd->gov; genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; - genpd->power_off = rmobile_pd_power_down; - genpd->power_on = rmobile_pd_power_up; - genpd->attach_dev = cpg_mstp_attach_dev; - genpd->detach_dev = cpg_mstp_detach_dev; - __rmobile_pd_power_up(rmobile_pd); + genpd->attach_dev = cpg_mstp_attach_dev; + genpd->detach_dev = cpg_mstp_detach_dev; + + if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) { + genpd->power_off = rmobile_pd_power_down; + genpd->power_on = rmobile_pd_power_up; + __rmobile_pd_power_up(rmobile_pd); + } + pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); } @@ -270,6 +266,11 @@ static void __init rmobile_setup_pm_domain(struct device_node *np, break; case PD_NORMAL: + if (pd->bit_shift == ~0) { + /* Top-level always-on domain */ + pr_debug("PM domain %s is always-on domain\n", name); + pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; + } break; } -- GitLab From faf1498993cdf65fd3a624b7653bc91909135a55 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:46 +0200 Subject: [PATCH 4199/7155] iommu: Remember when default domain type was set on kernel command line Introduce an extensible concept to remember when certain configuration settings for the IOMMU code have been set on the kernel command line. This will be used later to prevent overwriting these settings with other defaults. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 70bfbcc09248..0ae34cca0d4a 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -32,6 +32,7 @@ static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY; static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA; #endif static bool iommu_dma_strict __read_mostly = true; +static u32 iommu_cmd_line __read_mostly; struct iommu_group { struct kobject kobj; @@ -68,6 +69,18 @@ static const char * const iommu_group_resv_type_string[] = { [IOMMU_RESV_SW_MSI] = "msi", }; +#define IOMMU_CMD_LINE_DMA_API BIT(0) + +static void iommu_set_cmd_line_dma_api(void) +{ + iommu_cmd_line |= IOMMU_CMD_LINE_DMA_API; +} + +static bool __maybe_unused iommu_cmd_line_dma_api(void) +{ + return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API); +} + #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ struct iommu_group_attribute iommu_group_attr_##_name = \ __ATTR(_name, _mode, _show, _store) @@ -165,6 +178,8 @@ static int __init iommu_set_def_domain_type(char *str) if (ret) return ret; + iommu_set_cmd_line_dma_api(); + iommu_def_domain_type = pt ? IOMMU_DOMAIN_IDENTITY : IOMMU_DOMAIN_DMA; return 0; } -- GitLab From 8a69961c7f7583742ab9064feab5ea533a6b1b97 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:47 +0200 Subject: [PATCH 4200/7155] iommu: Add helpers to set/get default domain type Add a couple of functions to allow changing the default domain type from architecture code and a function for iommu drivers to request whether the default domain is passthrough. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 22 ++++++++++++++++++++++ include/linux/iommu.h | 16 ++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 0ae34cca0d4a..c5e0fc5ffe8b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2213,6 +2213,28 @@ int iommu_request_dma_domain_for_dev(struct device *dev) return request_default_domain_for_dev(dev, IOMMU_DOMAIN_DMA); } +void iommu_set_default_passthrough(bool cmd_line) +{ + if (cmd_line) + iommu_set_cmd_line_dma_api(); + + iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY; +} + +void iommu_set_default_translated(bool cmd_line) +{ + if (cmd_line) + iommu_set_cmd_line_dma_api(); + + iommu_def_domain_type = IOMMU_DOMAIN_DMA; +} + +bool iommu_default_passthrough(void) +{ + return iommu_def_domain_type == IOMMU_DOMAIN_IDENTITY; +} +EXPORT_SYMBOL_GPL(iommu_default_passthrough); + const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) { const struct iommu_ops *ops = NULL; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 64ebaff33455..29bac5345563 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -436,6 +436,9 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern int iommu_request_dm_for_dev(struct device *dev); extern int iommu_request_dma_domain_for_dev(struct device *dev); +extern void iommu_set_default_passthrough(bool cmd_line); +extern void iommu_set_default_translated(bool cmd_line); +extern bool iommu_default_passthrough(void); extern struct iommu_resv_region * iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, enum iommu_resv_type type); @@ -736,6 +739,19 @@ static inline int iommu_request_dma_domain_for_dev(struct device *dev) return -ENODEV; } +static inline void iommu_set_default_passthrough(bool cmd_line) +{ +} + +static inline void iommu_set_default_translated(bool cmd_line) +{ +} + +static inline bool iommu_default_passthrough(void) +{ + return true; +} + static inline int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) { -- GitLab From adab0b07cbbc73f9fc338e4fc1749714dd093a7c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:48 +0200 Subject: [PATCH 4201/7155] iommu: Use Functions to set default domain type in iommu_set_def_domain_type() There are functions now to set the default domain type which take care of updating other necessary state. Don't open-code it in iommu_set_def_domain_type() and use those functions instead. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index c5e0fc5ffe8b..544f44fc08e4 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -178,9 +178,11 @@ static int __init iommu_set_def_domain_type(char *str) if (ret) return ret; - iommu_set_cmd_line_dma_api(); + if (pt) + iommu_set_default_passthrough(true); + else + iommu_set_default_translated(true); - iommu_def_domain_type = pt ? IOMMU_DOMAIN_IDENTITY : IOMMU_DOMAIN_DMA; return 0; } early_param("iommu.passthrough", iommu_set_def_domain_type); -- GitLab From cc7c8ad9736b5db994b84cbb1347972d28852d3b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:49 +0200 Subject: [PATCH 4202/7155] iommu/amd: Request passthrough mode from IOMMU core Get rid of the iommu_pass_through variable and request passthrough mode via the new iommu core function. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 29eeea914660..07512d08dd00 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -436,7 +436,7 @@ static int iommu_init_device(struct device *dev) * invalid address), we ignore the capability for the device so * it'll be forced to go into translation mode. */ - if ((iommu_pass_through || !amd_iommu_force_isolation) && + if ((iommu_default_passthrough() || !amd_iommu_force_isolation) && dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) { struct amd_iommu *iommu; @@ -2226,7 +2226,7 @@ static int amd_iommu_add_device(struct device *dev) BUG_ON(!dev_data); - if (iommu_pass_through || dev_data->iommu_v2) + if (dev_data->iommu_v2) iommu_request_dm_for_dev(dev); /* Domains are initialized for this device - have a look what we ended up with */ @@ -2805,7 +2805,7 @@ int __init amd_iommu_init_api(void) int __init amd_iommu_init_dma_ops(void) { - swiotlb = (iommu_pass_through || sme_me_mask) ? 1 : 0; + swiotlb = (iommu_default_passthrough() || sme_me_mask) ? 1 : 0; iommu_detected = 1; if (amd_iommu_unmap_flush) -- GitLab From 6b9a7d3a466fffc97c4b133852d3dd7905510dd6 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:50 +0200 Subject: [PATCH 4203/7155] iommu/vt-d: Request passthrough mode from IOMMU core Get rid of the iommu_pass_through variable and request passthrough mode via the new iommu core function. Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d6003b391e2c..587337534b76 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3267,7 +3267,7 @@ static int __init init_dmars(void) iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); } - if (iommu_pass_through) + if (iommu_default_passthrough()) iommu_identity_mapping |= IDENTMAP_ALL; #ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA -- GitLab From c53c47aac4ff9509e7e1a32666baefbd9793c5a0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:51 +0200 Subject: [PATCH 4204/7155] x86/dma: Get rid of iommu_pass_through This variable has no users anymore. Remove it and tell the IOMMU code via its new functions about requested DMA modes. Reviewed-by: Borislav Petkov Signed-off-by: Joerg Roedel --- arch/x86/include/asm/iommu.h | 1 - arch/x86/kernel/pci-dma.c | 20 +++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index baedab8ac538..b91623d521d9 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -4,7 +4,6 @@ extern int force_iommu, no_iommu; extern int iommu_detected; -extern int iommu_pass_through; /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index f62b498b18fb..fa4352dce491 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -34,21 +35,6 @@ int no_iommu __read_mostly; /* Set this to 1 if there is a HW IOMMU in the system */ int iommu_detected __read_mostly = 0; -/* - * This variable becomes 1 if iommu=pt is passed on the kernel command line. - * If this variable is 1, IOMMU implementations do no DMA translation for - * devices and allow every device to access to whole physical memory. This is - * useful if a user wants to use an IOMMU only for KVM device assignment to - * guests and not for driver dma translation. - * It is also possible to disable by default in kernel config, and enable with - * iommu=nopt at boot time. - */ -#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH -int iommu_pass_through __read_mostly = 1; -#else -int iommu_pass_through __read_mostly; -#endif - extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; void __init pci_iommu_alloc(void) @@ -120,9 +106,9 @@ static __init int iommu_setup(char *p) swiotlb = 1; #endif if (!strncmp(p, "pt", 2)) - iommu_pass_through = 1; + iommu_set_default_passthrough(true); if (!strncmp(p, "nopt", 4)) - iommu_pass_through = 0; + iommu_set_default_translated(true); gart_parse_options(p); -- GitLab From 74bc0f6b22fd1a3c839f61d8475335a98af53c7a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:52 +0200 Subject: [PATCH 4205/7155] ia64: Get rid of iommu_pass_through This variable has no users anymore so it can be removed. Signed-off-by: Joerg Roedel --- arch/ia64/include/asm/iommu.h | 2 -- arch/ia64/kernel/pci-dma.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h index 7429a72f3f92..92aceef63710 100644 --- a/arch/ia64/include/asm/iommu.h +++ b/arch/ia64/include/asm/iommu.h @@ -8,10 +8,8 @@ extern void no_iommu_init(void); #ifdef CONFIG_INTEL_IOMMU extern int force_iommu, no_iommu; -extern int iommu_pass_through; extern int iommu_detected; #else -#define iommu_pass_through (0) #define no_iommu (1) #define iommu_detected (0) #endif diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index fe988c49f01c..f5d49cd3fbb0 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -22,8 +22,6 @@ int force_iommu __read_mostly = 1; int force_iommu __read_mostly; #endif -int iommu_pass_through; - static int __init pci_iommu_init(void) { if (iommu_detected) -- GitLab From 5fa9e7c5fa50f27afd71f2f6373179739bfa4034 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:53 +0200 Subject: [PATCH 4206/7155] iommu: Print default domain type on boot Introduce a subsys_initcall for IOMMU code and use it to print the default domain type at boot. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 544f44fc08e4..31a66c4600bc 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -93,12 +93,40 @@ struct iommu_group_attribute iommu_group_attr_##_name = \ static LIST_HEAD(iommu_device_list); static DEFINE_SPINLOCK(iommu_device_lock); +/* + * Use a function instead of an array here because the domain-type is a + * bit-field, so an array would waste memory. + */ +static const char *iommu_domain_type_str(unsigned int t) +{ + switch (t) { + case IOMMU_DOMAIN_BLOCKED: + return "Blocked"; + case IOMMU_DOMAIN_IDENTITY: + return "Passthrough"; + case IOMMU_DOMAIN_UNMANAGED: + return "Unmanaged"; + case IOMMU_DOMAIN_DMA: + return "Translated"; + default: + return "Unknown"; + } +} + +static int __init iommu_subsys_init(void) +{ + pr_info("Default domain type: %s\n", + iommu_domain_type_str(iommu_def_domain_type)); + + return 0; +} +subsys_initcall(iommu_subsys_init); + int iommu_device_register(struct iommu_device *iommu) { spin_lock(&iommu_device_lock); list_add_tail(&iommu->list, &iommu_device_list); spin_unlock(&iommu_device_lock); - return 0; } -- GitLab From 22bb182c839d8ef6c08cf548feb0451c429216d8 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:54 +0200 Subject: [PATCH 4207/7155] iommu: Set default domain type at runtime Set the default domain-type at runtime, not at compile-time. This keeps default domain type setting in one place when we have to change it at runtime. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 31a66c4600bc..9ad1b0af2306 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -26,11 +26,8 @@ static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); -#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH -static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY; -#else -static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA; -#endif + +static unsigned int iommu_def_domain_type __read_mostly; static bool iommu_dma_strict __read_mostly = true; static u32 iommu_cmd_line __read_mostly; @@ -76,7 +73,7 @@ static void iommu_set_cmd_line_dma_api(void) iommu_cmd_line |= IOMMU_CMD_LINE_DMA_API; } -static bool __maybe_unused iommu_cmd_line_dma_api(void) +static bool iommu_cmd_line_dma_api(void) { return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API); } @@ -115,8 +112,18 @@ static const char *iommu_domain_type_str(unsigned int t) static int __init iommu_subsys_init(void) { - pr_info("Default domain type: %s\n", - iommu_domain_type_str(iommu_def_domain_type)); + bool cmd_line = iommu_cmd_line_dma_api(); + + if (!cmd_line) { + if (IS_ENABLED(CONFIG_IOMMU_DEFAULT_PASSTHROUGH)) + iommu_set_default_passthrough(false); + else + iommu_set_default_translated(false); + } + + pr_info("Default domain type: %s %s\n", + iommu_domain_type_str(iommu_def_domain_type), + cmd_line ? "(set via kernel command line)" : ""); return 0; } -- GitLab From 2cc13bb4f59fa7e66acf5b1b78bdf97d73d3416a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:55 +0200 Subject: [PATCH 4208/7155] iommu: Disable passthrough mode when SME is active Using Passthrough mode when SME is active causes certain devices to use the SWIOTLB bounce buffer. The bounce buffer code has an upper limit of 256kb for the size of DMA allocations, which is too small for certain devices and causes them to fail. With this patch we enable IOMMU by default when SME is active in the system, making the default configuration work for more systems than it does now. Users that don't want IOMMUs to be enabled still can disable them with kernel parameters. Reviewed-by: Tom Lendacky Tested-by: Tom Lendacky Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 9ad1b0af2306..0f585b614657 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -119,6 +119,11 @@ static int __init iommu_subsys_init(void) iommu_set_default_passthrough(false); else iommu_set_default_translated(false); + + if (iommu_default_passthrough() && sme_active()) { + pr_info("SME detected - Disabling default IOMMU Passthrough\n"); + iommu_set_default_translated(false); + } } pr_info("Default domain type: %s %s\n", -- GitLab From c8fb436b3b633183a4c2b5a958c01baaf8bc42a7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 19 Aug 2019 15:22:56 +0200 Subject: [PATCH 4209/7155] Documentation: Update Documentation for iommu.passthrough This kernel parameter now takes also effect on X86. Signed-off-by: Joerg Roedel --- Documentation/admin-guide/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 7ccd158b3894..0c59398519be 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1811,7 +1811,7 @@ synchronously. iommu.passthrough= - [ARM64] Configure DMA to bypass the IOMMU by default. + [ARM64, X86] Configure DMA to bypass the IOMMU by default. Format: { "0" | "1" } 0 - Use IOMMU translation for DMA. 1 - Bypass the IOMMU for DMA. -- GitLab From 4cdc12a3ef424361f81bb30a34a3148b03df640c Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 20 Aug 2019 17:19:34 +0200 Subject: [PATCH 4210/7155] arm64: dts: allwinner: h6: Add support for RTC and fix the clock tree This patch adds RTC node and fixes the clock properties and nodes to reflect the real clock tree. The device nodes for the internal oscillator and osc32k are removed, as these clocks are now provided by the RTC device. Clock references are fixed accordingly, too. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 30 +++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 67b732e34091..67f920e0fc33 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -56,14 +56,6 @@ status = "disabled"; }; - iosc: internal-osc-clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <16000000>; - clock-accuracy = <300000000>; - clock-output-names = "iosc"; - }; - osc24M: osc24M_clk { #clock-cells = <0>; compatible = "fixed-clock"; @@ -71,11 +63,11 @@ clock-output-names = "osc24M"; }; - osc32k: osc32k_clk { + ext_osc32k: ext_osc32k_clk { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32768>; - clock-output-names = "osc32k"; + clock-output-names = "ext_osc32k"; }; psci { @@ -197,7 +189,7 @@ ccu: clock@3001000 { compatible = "allwinner,sun50i-h6-ccu"; reg = <0x03001000 0x1000>; - clocks = <&osc24M>, <&osc32k>, <&iosc>; + clocks = <&osc24M>, <&rtc 0>, <&rtc 2>; clock-names = "hosc", "losc", "iosc"; #clock-cells = <1>; #reset-cells = <1>; @@ -236,7 +228,7 @@ , , ; - clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>; + clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>; clock-names = "apb", "hosc", "losc"; gpio-controller; #gpio-cells = <3>; @@ -710,10 +702,20 @@ }; }; + rtc: rtc@7000000 { + compatible = "allwinner,sun50i-h6-rtc"; + reg = <0x07000000 0x400>; + interrupts = , + ; + clock-output-names = "osc32k", "osc32k-out", "iosc"; + clocks = <&ext_osc32k>; + #clock-cells = <1>; + }; + r_ccu: clock@7010000 { compatible = "allwinner,sun50i-h6-r-ccu"; reg = <0x07010000 0x400>; - clocks = <&osc24M>, <&osc32k>, <&iosc>, + clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, <&ccu CLK_PLL_PERIPH0>; clock-names = "hosc", "losc", "iosc", "pll-periph"; #clock-cells = <1>; @@ -741,7 +743,7 @@ reg = <0x07022000 0x400>; interrupts = , ; - clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k>; + clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>; clock-names = "apb", "hosc", "losc"; gpio-controller; #gpio-cells = <3>; -- GitLab From 93d051550ee02eaff9a2541d825605a7bd778027 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 21 Aug 2019 13:10:04 +0800 Subject: [PATCH 4211/7155] iommu/amd: Override wrong IVRS IOAPIC on Raven Ridge systems Raven Ridge systems may have malfunction touchpad or hang at boot if incorrect IVRS IOAPIC is provided by BIOS. Users already found correct "ivrs_ioapic=" values, let's put them inside kernel to workaround buggy BIOS. BugLink: https://bugs.launchpad.net/bugs/1795292 BugLink: https://bugs.launchpad.net/bugs/1837688 Reported-by: kbuild test robot Signed-off-by: Kai-Heng Feng Signed-off-by: Joerg Roedel --- drivers/iommu/Makefile | 2 +- drivers/iommu/amd_iommu.h | 14 +++++ drivers/iommu/amd_iommu_init.c | 5 +- drivers/iommu/amd_iommu_quirks.c | 92 ++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 drivers/iommu/amd_iommu.h create mode 100644 drivers/iommu/amd_iommu_quirks.c diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index f13f36ae1af6..c6a277e69848 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o obj-$(CONFIG_IOMMU_IOVA) += iova.o obj-$(CONFIG_OF_IOMMU) += of_iommu.o obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o -obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o +obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o obj-$(CONFIG_ARM_SMMU) += arm-smmu.o diff --git a/drivers/iommu/amd_iommu.h b/drivers/iommu/amd_iommu.h new file mode 100644 index 000000000000..12d540d9b59b --- /dev/null +++ b/drivers/iommu/amd_iommu.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_IOMMU_H +#define AMD_IOMMU_H + +int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line); + +#ifdef CONFIG_DMI +void amd_iommu_apply_ivrs_quirks(void); +#else +static void amd_iommu_apply_ivrs_quirks(void) { } +#endif + +#endif diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 4413aa67000e..568c52317757 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -32,6 +32,7 @@ #include #include +#include "amd_iommu.h" #include "amd_iommu_proto.h" #include "amd_iommu_types.h" #include "irq_remapping.h" @@ -1002,7 +1003,7 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu, set_iommu_for_device(iommu, devid); } -static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line) +int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line) { struct devid_map *entry; struct list_head *list; @@ -1153,6 +1154,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, if (ret) return ret; + amd_iommu_apply_ivrs_quirks(); + /* * First save the recommended feature enable bits from ACPI */ diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c new file mode 100644 index 000000000000..c235f79b7a20 --- /dev/null +++ b/drivers/iommu/amd_iommu_quirks.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * Quirks for AMD IOMMU + * + * Copyright (C) 2019 Kai-Heng Feng + */ + +#ifdef CONFIG_DMI +#include + +#include "amd_iommu.h" + +#define IVHD_SPECIAL_IOAPIC 1 + +struct ivrs_quirk_entry { + u8 id; + u16 devid; +}; + +enum { + DELL_INSPIRON_7375 = 0, + DELL_LATITUDE_5495, + LENOVO_IDEAPAD_330S_15ARR, +}; + +static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = { + /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */ + [DELL_INSPIRON_7375] = { + { .id = 4, .devid = 0xa0 }, + { .id = 5, .devid = 0x2 }, + {} + }, + /* ivrs_ioapic[4]=00:14.0 */ + [DELL_LATITUDE_5495] = { + { .id = 4, .devid = 0xa0 }, + {} + }, + /* ivrs_ioapic[32]=00:14.0 */ + [LENOVO_IDEAPAD_330S_15ARR] = { + { .id = 32, .devid = 0xa0 }, + {} + }, + {} +}; + +static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d) +{ + const struct ivrs_quirk_entry *i; + + for (i = d->driver_data; i->id != 0 && i->devid != 0; i++) + add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 *)&i->devid, 0); + + return 0; +} + +static const struct dmi_system_id ivrs_quirks[] __initconst = { + { + .callback = ivrs_ioapic_quirk_cb, + .ident = "Dell Inspiron 7375", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"), + }, + .driver_data = (void *)&ivrs_ioapic_quirks[DELL_INSPIRON_7375], + }, + { + .callback = ivrs_ioapic_quirk_cb, + .ident = "Dell Latitude 5495", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 5495"), + }, + .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], + }, + { + .callback = ivrs_ioapic_quirk_cb, + .ident = "Lenovo ideapad 330S-15ARR", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "81FB"), + }, + .driver_data = (void *)&ivrs_ioapic_quirks[LENOVO_IDEAPAD_330S_15ARR], + }, + {} +}; + +void __init amd_iommu_apply_ivrs_quirks(void) +{ + dmi_check_system(ivrs_quirks); +} +#endif -- GitLab From 435dce2da218b0eb1ff758b77831562845394848 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 19 Aug 2019 19:05:58 +0200 Subject: [PATCH 4212/7155] soc: renesas: Enable ARM_ERRATA_814220 for affected Cortex-A7 ARM Erratum 814220 affects Cortex-A7 revisions r0p2-r0p5. Automatically enable support code to mitigate the erratum when compiling a kernel for any of the affected Renesas SoCs: - R-Mobile APE6: r0p2, - RZ/G1E: r0p5, - RZ/G1C: r0p5, - R-Car H2: r0p3, - R-Car E2: r0p5, - RZ/N1: r0p5. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman --- drivers/soc/renesas/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 2bbf49e5d441..a72d014ea37c 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -72,6 +72,7 @@ config ARCH_R8A73A4 bool "R-Mobile APE6 (R8A73A40)" select ARCH_RMOBILE select ARM_ERRATA_798181 if SMP + select ARM_ERRATA_814220 select HAVE_ARM_ARCH_TIMER select RENESAS_IRQC @@ -95,11 +96,13 @@ config ARCH_R8A7744 config ARCH_R8A7745 bool "RZ/G1E (R8A77450)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_814220 select SYSC_R8A7745 config ARCH_R8A77470 bool "RZ/G1C (R8A77470)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_814220 select SYSC_R8A77470 config ARCH_R8A7778 @@ -117,6 +120,7 @@ config ARCH_R8A7790 bool "R-Car H2 (R8A77900)" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP + select ARM_ERRATA_814220 select I2C select SYSC_R8A7790 @@ -143,11 +147,13 @@ config ARCH_R8A7793 config ARCH_R8A7794 bool "R-Car E2 (R8A77940)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_814220 select SYSC_R8A7794 config ARCH_R9A06G032 bool "RZ/N1D (R9A06G032)" select ARCH_RZN1 + select ARM_ERRATA_814220 config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" -- GitLab From 2eced4607a1e6f51f928ae3e521fe02be5cb7d23 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 19 Aug 2019 18:54:02 +0200 Subject: [PATCH 4213/7155] soc: renesas: Enable ARM_ERRATA_754322 for affected Cortex-A9 ARM Erratum 754322 affects Cortex-A9 revisions r2p* and r3p*. Automatically enable support code to mitigate the erratum when compiling a kernel for any of the affected Renesas SoCs: - RZ/A1: r3p0, - R-Mobile A1: r2p4, - R-Car M1A: r2p2-00rel0, - R-Car H1: r3p0, - SH-Mobile AG5: r2p2. EMMA Mobile EV2 (r1p3) and RZ/A2 (r4p1) are not affected. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman --- drivers/soc/renesas/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index a72d014ea37c..3c5e017bacba 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -55,6 +55,7 @@ config ARCH_EMEV2 config ARCH_R7S72100 bool "RZ/A1H (R7S72100)" + select ARM_ERRATA_754322 select PM select PM_GENERIC_DOMAINS select RENESAS_OSTM @@ -79,6 +80,7 @@ config ARCH_R8A73A4 config ARCH_R8A7740 bool "R-Mobile A1 (R8A77400)" select ARCH_RMOBILE + select ARM_ERRATA_754322 select RENESAS_INTC_IRQPIN config ARCH_R8A7743 @@ -108,10 +110,12 @@ config ARCH_R8A77470 config ARCH_R8A7778 bool "R-Car M1A (R8A77781)" select ARCH_RCAR_GEN1 + select ARM_ERRATA_754322 config ARCH_R8A7779 bool "R-Car H1 (R8A77790)" select ARCH_RCAR_GEN1 + select ARM_ERRATA_754322 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select SYSC_R8A7779 @@ -158,6 +162,7 @@ config ARCH_R9A06G032 config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" select ARCH_RMOBILE + select ARM_ERRATA_754322 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select RENESAS_INTC_IRQPIN -- GitLab From 7db47faae79bbffe2da15af4d5e061a49a56169b Mon Sep 17 00:00:00 2001 From: Hongwei Zhang Date: Tue, 20 Aug 2019 17:05:28 -0400 Subject: [PATCH 4214/7155] gpio: aspeed: Add SGPIO driver Add SGPIO driver support for Aspeed AST2500 SoC. Signed-off-by: Hongwei Zhang Reviewed-by: Andrew Jeffery Link: https://lore.kernel.org/r/1566335128-31498-2-git-send-email-hongweiz@ami.com Signed-off-by: Linus Walleij --- drivers/gpio/sgpio-aspeed.c | 533 ++++++++++++++++++++++++++++++++++++ 1 file changed, 533 insertions(+) create mode 100644 drivers/gpio/sgpio-aspeed.c diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c new file mode 100644 index 000000000000..7e99860ca447 --- /dev/null +++ b/drivers/gpio/sgpio-aspeed.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2019 American Megatrends International LLC. + * + * Author: Karthikeyan Mani + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NR_SGPIO 80 + +#define ASPEED_SGPIO_CTRL 0x54 + +#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6) +#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) +#define ASPEED_SGPIO_ENABLE BIT(0) + +struct aspeed_sgpio { + struct gpio_chip chip; + struct clk *pclk; + spinlock_t lock; + void __iomem *base; + uint32_t dir_in[3]; + int irq; +}; + +struct aspeed_sgpio_bank { + uint16_t val_regs; + uint16_t rdata_reg; + uint16_t irq_regs; + const char names[4][3]; +}; + +/* + * Note: The "value" register returns the input value when the GPIO is + * configured as an input. + * + * The "rdata" register returns the output value when the GPIO is + * configured as an output. + */ +static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = { + { + .val_regs = 0x0000, + .rdata_reg = 0x0070, + .irq_regs = 0x0004, + .names = { "A", "B", "C", "D" }, + }, + { + .val_regs = 0x001C, + .rdata_reg = 0x0074, + .irq_regs = 0x0020, + .names = { "E", "F", "G", "H" }, + }, + { + .val_regs = 0x0038, + .rdata_reg = 0x0078, + .irq_regs = 0x003C, + .names = { "I", "J" }, + }, +}; + +enum aspeed_sgpio_reg { + reg_val, + reg_rdata, + reg_irq_enable, + reg_irq_type0, + reg_irq_type1, + reg_irq_type2, + reg_irq_status, +}; + +#define GPIO_VAL_VALUE 0x00 +#define GPIO_IRQ_ENABLE 0x00 +#define GPIO_IRQ_TYPE0 0x04 +#define GPIO_IRQ_TYPE1 0x08 +#define GPIO_IRQ_TYPE2 0x0C +#define GPIO_IRQ_STATUS 0x10 + +static void __iomem *bank_reg(struct aspeed_sgpio *gpio, + const struct aspeed_sgpio_bank *bank, + const enum aspeed_sgpio_reg reg) +{ + switch (reg) { + case reg_val: + return gpio->base + bank->val_regs + GPIO_VAL_VALUE; + case reg_rdata: + return gpio->base + bank->rdata_reg; + case reg_irq_enable: + return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE; + case reg_irq_type0: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0; + case reg_irq_type1: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1; + case reg_irq_type2: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; + case reg_irq_status: + return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; + default: + /* acturally if code runs to here, it's an error case */ + BUG_ON(1); + } +} + +#define GPIO_BANK(x) ((x) >> 5) +#define GPIO_OFFSET(x) ((x) & 0x1f) +#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) + +static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) +{ + unsigned int bank = GPIO_BANK(offset); + + WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks)); + return &aspeed_sgpio_banks[bank]; +} + +static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + const struct aspeed_sgpio_bank *bank = to_bank(offset); + unsigned long flags; + enum aspeed_sgpio_reg reg; + bool is_input; + int rc = 0; + + spin_lock_irqsave(&gpio->lock, flags); + + is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset); + reg = is_input ? reg_val : reg_rdata; + rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset)); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; +} + +static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + const struct aspeed_sgpio_bank *bank = to_bank(offset); + void __iomem *addr; + u32 reg = 0; + + addr = bank_reg(gpio, bank, reg_val); + reg = ioread32(addr); + + if (val) + reg |= GPIO_BIT(offset); + else + reg &= ~GPIO_BIT(offset); + + iowrite32(reg, addr); +} + +static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + + sgpio_set_value(gc, offset, val); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset); + spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +} + +static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + + gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset); + sgpio_set_value(gc, offset, val); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +} + +static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + int dir_status; + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset); + spin_unlock_irqrestore(&gpio->lock, flags); + + return dir_status; + +} + +static void irqd_to_aspeed_sgpio_data(struct irq_data *d, + struct aspeed_sgpio **gpio, + const struct aspeed_sgpio_bank **bank, + u32 *bit, int *offset) +{ + struct aspeed_sgpio *internal; + + *offset = irqd_to_hwirq(d); + internal = irq_data_get_irq_chip_data(d); + WARN_ON(!internal); + + *gpio = internal; + *bank = to_bank(*offset); + *bit = GPIO_BIT(*offset); +} + +static void aspeed_sgpio_irq_ack(struct irq_data *d) +{ + const struct aspeed_sgpio_bank *bank; + struct aspeed_sgpio *gpio; + unsigned long flags; + void __iomem *status_addr; + int offset; + u32 bit; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + + status_addr = bank_reg(gpio, bank, reg_irq_status); + + spin_lock_irqsave(&gpio->lock, flags); + + iowrite32(bit, status_addr); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) +{ + const struct aspeed_sgpio_bank *bank; + struct aspeed_sgpio *gpio; + unsigned long flags; + u32 reg, bit; + void __iomem *addr; + int offset; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + addr = bank_reg(gpio, bank, reg_irq_enable); + + spin_lock_irqsave(&gpio->lock, flags); + + reg = ioread32(addr); + if (set) + reg |= bit; + else + reg &= ~bit; + + iowrite32(reg, addr); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static void aspeed_sgpio_irq_mask(struct irq_data *d) +{ + aspeed_sgpio_irq_set_mask(d, false); +} + +static void aspeed_sgpio_irq_unmask(struct irq_data *d) +{ + aspeed_sgpio_irq_set_mask(d, true); +} + +static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) +{ + u32 type0 = 0; + u32 type1 = 0; + u32 type2 = 0; + u32 bit, reg; + const struct aspeed_sgpio_bank *bank; + irq_flow_handler_t handler; + struct aspeed_sgpio *gpio; + unsigned long flags; + void __iomem *addr; + int offset; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_BOTH: + type2 |= bit; + /* fall through */ + case IRQ_TYPE_EDGE_RISING: + type0 |= bit; + /* fall through */ + case IRQ_TYPE_EDGE_FALLING: + handler = handle_edge_irq; + break; + case IRQ_TYPE_LEVEL_HIGH: + type0 |= bit; + /* fall through */ + case IRQ_TYPE_LEVEL_LOW: + type1 |= bit; + handler = handle_level_irq; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&gpio->lock, flags); + + addr = bank_reg(gpio, bank, reg_irq_type0); + reg = ioread32(addr); + reg = (reg & ~bit) | type0; + iowrite32(reg, addr); + + addr = bank_reg(gpio, bank, reg_irq_type1); + reg = ioread32(addr); + reg = (reg & ~bit) | type1; + iowrite32(reg, addr); + + addr = bank_reg(gpio, bank, reg_irq_type2); + reg = ioread32(addr); + reg = (reg & ~bit) | type2; + iowrite32(reg, addr); + + spin_unlock_irqrestore(&gpio->lock, flags); + + irq_set_handler_locked(d, handler); + + return 0; +} + +static void aspeed_sgpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct irq_chip *ic = irq_desc_get_chip(desc); + struct aspeed_sgpio *data = gpiochip_get_data(gc); + unsigned int i, p, girq; + unsigned long reg; + + chained_irq_enter(ic, desc); + + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i]; + + reg = ioread32(bank_reg(data, bank, reg_irq_status)); + + for_each_set_bit(p, ®, 32) { + girq = irq_find_mapping(gc->irq.domain, i * 32 + p); + generic_handle_irq(girq); + } + + } + + chained_irq_exit(ic, desc); +} + +static struct irq_chip aspeed_sgpio_irqchip = { + .name = "aspeed-sgpio", + .irq_ack = aspeed_sgpio_irq_ack, + .irq_mask = aspeed_sgpio_irq_mask, + .irq_unmask = aspeed_sgpio_irq_unmask, + .irq_set_type = aspeed_sgpio_set_type, +}; + +static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, + struct platform_device *pdev) +{ + int rc, i; + const struct aspeed_sgpio_bank *bank; + struct gpio_irq_chip *irq; + + rc = platform_get_irq(pdev, 0); + if (rc < 0) + return rc; + + gpio->irq = rc; + + /* Disable IRQ and clear Interrupt status registers for all SPGIO Pins. */ + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + bank = &aspeed_sgpio_banks[i]; + /* disable irq enable bits */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable)); + /* clear status bits */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); + } + + irq = &gpio->chip.irq; + irq->chip = &aspeed_sgpio_irqchip; + irq->handler = handle_bad_irq; + irq->default_type = IRQ_TYPE_NONE; + irq->parent_handler = aspeed_sgpio_irq_handler; + irq->parent_handler_data = gpio; + irq->parents = &gpio->irq; + irq->num_parents = 1; + + /* set IRQ settings and Enable Interrupt */ + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + bank = &aspeed_sgpio_banks[i]; + /* set falling or level-low irq */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0)); + /* trigger type is edge */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1)); + /* dual edge trigger mode. */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2)); + /* enable irq */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable)); + } + + return 0; +} + +static const struct of_device_id aspeed_sgpio_of_table[] = { + { .compatible = "aspeed,ast2400-sgpio" }, + { .compatible = "aspeed,ast2500-sgpio" }, + {} +}; + +MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); + +static int __init aspeed_sgpio_probe(struct platform_device *pdev) +{ + struct aspeed_sgpio *gpio; + u32 nr_gpios, sgpio_freq, sgpio_clk_div; + int rc; + unsigned long apb_freq; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); + + rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios); + if (rc < 0) { + dev_err(&pdev->dev, "Could not read ngpios property\n"); + return -EINVAL; + } else if (nr_gpios > MAX_NR_SGPIO) { + dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n", + MAX_NR_SGPIO, nr_gpios); + return -EINVAL; + } + + rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq); + if (rc < 0) { + dev_err(&pdev->dev, "Could not read bus-frequency property\n"); + return -EINVAL; + } + + gpio->pclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(gpio->pclk)) { + dev_err(&pdev->dev, "devm_clk_get failed\n"); + return PTR_ERR(gpio->pclk); + } + + apb_freq = clk_get_rate(gpio->pclk); + + /* + * From the datasheet, + * SGPIO period = 1/PCLK * 2 * (GPIO254[31:16] + 1) + * period = 2 * (GPIO254[31:16] + 1) / PCLK + * frequency = 1 / (2 * (GPIO254[31:16] + 1) / PCLK) + * frequency = PCLK / (2 * (GPIO254[31:16] + 1)) + * frequency * 2 * (GPIO254[31:16] + 1) = PCLK + * GPIO254[31:16] = PCLK / (frequency * 2) - 1 + */ + if (sgpio_freq == 0) + return -EINVAL; + + sgpio_clk_div = (apb_freq / (sgpio_freq * 2)) - 1; + + if (sgpio_clk_div > (1 << 16) - 1) + return -EINVAL; + + iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | + FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) | + ASPEED_SGPIO_ENABLE, + gpio->base + ASPEED_SGPIO_CTRL); + + spin_lock_init(&gpio->lock); + + gpio->chip.parent = &pdev->dev; + gpio->chip.ngpio = nr_gpios; + gpio->chip.direction_input = aspeed_sgpio_dir_in; + gpio->chip.direction_output = aspeed_sgpio_dir_out; + gpio->chip.get_direction = aspeed_sgpio_get_direction; + gpio->chip.request = NULL; + gpio->chip.free = NULL; + gpio->chip.get = aspeed_sgpio_get; + gpio->chip.set = aspeed_sgpio_set; + gpio->chip.set_config = NULL; + gpio->chip.label = dev_name(&pdev->dev); + gpio->chip.base = -1; + + /* set all SGPIO pins as input (1). */ + memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in)); + + aspeed_sgpio_setup_irqs(gpio, pdev); + + rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); + if (rc < 0) + return rc; + + return 0; +} + +static struct platform_driver aspeed_sgpio_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = aspeed_sgpio_of_table, + }, +}; + +module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); +MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); +MODULE_LICENSE("GPL"); -- GitLab From c7663fa2a6631e5dddc1b7b2ba2e905ddffaff90 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 11:18:17 +0800 Subject: [PATCH 4215/7155] gpio: Move gpiochip_lock/unlock_as_irq to gpio/driver.h If CONFIG_GPIOLIB is not, gpiochip_lock/unlock_as_irq will conflict as this: In file included from sound/soc/codecs/wm5100.c:18:0: ./include/linux/gpio.h:224:19: error: static declaration of gpiochip_lock_as_irq follows non-static declaration static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, ^~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:17:0: ./include/linux/gpio/driver.h:494:5: note: previous declaration of gpiochip_lock_as_irq was here int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); ^~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:18:0: ./include/linux/gpio.h:231:20: error: static declaration of gpiochip_unlock_as_irq follows non-static declaration static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, ^~~~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:17:0: ./include/linux/gpio/driver.h:495:6: note: previous declaration of gpiochip_unlock_as_irq was here void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); ^~~~~~~~~~~~~~~~~~~~~~ Move them to gpio/driver.h and use CONFIG_GPIOLIB guard this. Reported-by: Hulk Robot Fixes: d74be6dfea1b ("gpio: remove gpiod_lock/unlock_as_irq()") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822031817.32888-1-yuehaibing@huawei.com Signed-off-by: Linus Walleij --- include/linux/gpio.h | 13 ------------- include/linux/gpio/driver.h | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 40915b461f18..d20e224804e6 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -221,19 +221,6 @@ static inline int gpio_to_irq(unsigned gpio) return -EINVAL; } -static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); -} - static inline int irq_to_gpio(unsigned irq) { /* irq can never have been returned from gpio_to_irq() */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 340121c7d2fb..8d06a054abc8 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -495,9 +495,6 @@ extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, extern struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *chip, void *data)); -/* lock/unlock as IRQ */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); @@ -723,6 +720,10 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); +/* lock/unlock as IRQ */ +int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -732,6 +733,18 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) return ERR_PTR(-ENODEV); } +static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); + return -EINVAL; +} + +static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); +} #endif /* CONFIG_GPIOLIB */ #endif -- GitLab From 89d1e51462d4749874ba3505c7de46734fda82f1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 16:38:34 +0200 Subject: [PATCH 4216/7155] ARM: dts: sunxi: Add missing watchdog interrupts The watchdog has an interrupt on all our SoCs, but it wasn't always listed. Add it to the devicetree where it's missing. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 1 + arch/arm/boot/dts/sun5i.dtsi | 1 + arch/arm/boot/dts/sun6i-a31.dtsi | 1 + arch/arm/boot/dts/sun7i-a20.dtsi | 1 + arch/arm/boot/dts/sun8i-r40.dtsi | 1 + 5 files changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 077d45c7db6f..eed9fcb46185 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -815,6 +815,7 @@ wdt: watchdog@1c20c90 { compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; + interrupts = <24>; }; rtc: rtc@1c20d00 { diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 4e725afe7203..29a825f7afd1 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -600,6 +600,7 @@ wdt: watchdog@1c20c90 { compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; + interrupts = <24>; }; ir0: ir@1c21800 { diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 8176da53dadf..cba8864bb8f9 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -744,6 +744,7 @@ wdt1: watchdog@1c20ca0 { compatible = "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; + interrupts = ; }; spdif: spdif@1c21000 { diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 524c1d5a7d0d..747ead92d09a 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1140,6 +1140,7 @@ wdt: watchdog@1c20c90 { compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; + interrupts = ; }; rtc: rtc@1c20d00 { diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 09e20768228c..f1be554b5894 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -404,6 +404,7 @@ wdt: watchdog@1c20c90 { compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; + interrupts = ; }; uart0: serial@1c28000 { -- GitLab From 9e1975f0bca9ef9fc5d76f056cab7240e25bca76 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Aug 2019 16:38:35 +0200 Subject: [PATCH 4217/7155] ARM: dts: sunxi: Add missing watchdog clocks The watchdog has a clock on all our SoCs, but it wasn't always listed. Add it to the devicetree where it's missing. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 1 + arch/arm/boot/dts/sun5i.dtsi | 1 + arch/arm/boot/dts/sun6i-a31.dtsi | 1 + arch/arm/boot/dts/sun7i-a20.dtsi | 1 + arch/arm/boot/dts/sun8i-a23-a33.dtsi | 1 + arch/arm/boot/dts/sun8i-r40.dtsi | 1 + arch/arm/boot/dts/sun8i-v3s.dtsi | 1 + arch/arm/boot/dts/sunxi-h3-h5.dtsi | 1 + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 2 ++ 10 files changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index eed9fcb46185..ce823c44e98a 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -816,6 +816,7 @@ compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; interrupts = <24>; + clocks = <&osc24M>; }; rtc: rtc@1c20d00 { diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 29a825f7afd1..cfb1efc8828c 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -601,6 +601,7 @@ compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; interrupts = <24>; + clocks = <&osc24M>; }; ir0: ir@1c21800 { diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index cba8864bb8f9..bbeb743633c6 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -745,6 +745,7 @@ compatible = "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; interrupts = ; + clocks = <&osc24M>; }; spdif: spdif@1c21000 { diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 747ead92d09a..49380de754a9 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1141,6 +1141,7 @@ compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; interrupts = ; + clocks = <&osc24M>; }; rtc: rtc@1c20d00 { diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 954489b4ec66..52eed0ae3607 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -452,6 +452,7 @@ compatible = "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; interrupts = ; + clocks = <&osc24M>; }; pwm: pwm@1c21400 { diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index f1be554b5894..bde068111b85 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -405,6 +405,7 @@ compatible = "allwinner,sun4i-a10-wdt"; reg = <0x01c20c90 0x10>; interrupts = ; + clocks = <&osc24M>; }; uart0: serial@1c28000 { diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index ddbcc28dc541..23ba56df38f7 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -339,6 +339,7 @@ compatible = "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; interrupts = ; + clocks = <&osc24M>; }; lradc: lradc@1c22800 { diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 224e105a994a..eba190b3f9de 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -574,6 +574,7 @@ compatible = "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; interrupts = ; + clocks = <&osc24M>; }; spdif: spdif@1c21000 { diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index ddb6f11e89df..69128a6dfc46 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1169,6 +1169,7 @@ "allwinner,sun6i-a31-wdt"; reg = <0x01c20ca0 0x20>; interrupts = ; + clocks = <&osc24M>; }; }; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 67f920e0fc33..4020a1aafa3e 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -217,6 +217,7 @@ "allwinner,sun6i-a31-wdt"; reg = <0x030090a0 0x20>; interrupts = ; + clocks = <&osc24M>; /* Broken on some H6 boards */ status = "disabled"; }; @@ -727,6 +728,7 @@ "allwinner,sun6i-a31-wdt"; reg = <0x07020400 0x20>; interrupts = ; + clocks = <&osc24M>; }; r_intc: interrupt-controller@7021000 { -- GitLab From b1d64c7139c1ec673bac8be88b27caf02cf73118 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 22 Aug 2019 22:45:38 +0200 Subject: [PATCH 4218/7155] gpio: ftgpio: Fix an error handling path in 'ftgpio_gpio_probe()' If 'devm_kcalloc()' fails, we should go through the error handling path, should some clean-up be needed. Fixes: 42d9fc7176eb ("gpio: ftgpio: Pass irqchip when adding gpiochip") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190822204538.4791-1-christophe.jaillet@wanadoo.fr Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ftgpio010.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 3118d282514a..fbddb1662428 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -290,8 +290,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), GFP_KERNEL); - if (!girq->parents) - return -ENOMEM; + if (!girq->parents) { + ret = -ENOMEM; + goto dis_clk; + } girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; girq->parents[0] = irq; -- GitLab From f4e9bcc05f4e8d543afbfc0ca1fd4435a2204776 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:11:16 +0200 Subject: [PATCH 4219/7155] gpio: mt7621: Pass irqchip when adding gpiochip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. This driver requests the IRQ directly in the driver so it differs a bit from the others. Cc: Greg Ungerer Cc: Nicholas Mc Guire Cc: Sergio Paracuellos Cc: Thierry Reding Signed-off-by: Linus Walleij Tested-by: René van Dorst Link: https://lore.kernel.org/r/20190809141116.16403-1-linus.walleij@linaro.org --- drivers/gpio/gpio-mt7621.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index 79654fb2e50f..d1d785f983a7 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -241,13 +241,6 @@ mediatek_gpio_bank_probe(struct device *dev, if (!rg->chip.label) return -ENOMEM; - ret = devm_gpiochip_add_data(dev, &rg->chip, mtk); - if (ret < 0) { - dev_err(dev, "Could not register gpio %d, ret=%d\n", - rg->chip.ngpio, ret); - return ret; - } - rg->irq_chip.name = dev_name(dev); rg->irq_chip.parent_device = dev; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; @@ -256,8 +249,10 @@ mediatek_gpio_bank_probe(struct device *dev, rg->irq_chip.irq_set_type = mediatek_gpio_irq_type; if (mtk->gpio_irq) { + struct gpio_irq_chip *girq; + /* - * Manually request the irq here instead of passing + * Directly request the irq here instead of passing * a flow-handler to gpiochip_set_chained_irqchip, * because the irq is shared. */ @@ -271,15 +266,21 @@ mediatek_gpio_bank_probe(struct device *dev, return ret; } - ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip, - 0, handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add gpiochip_irqchip\n"); - return ret; - } + girq = &rg->chip.irq; + girq->chip = &rg->irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + } - gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip, - mtk->gpio_irq, NULL); + ret = devm_gpiochip_add_data(dev, &rg->chip, mtk); + if (ret < 0) { + dev_err(dev, "Could not register gpio %d, ret=%d\n", + rg->chip.ngpio, ret); + return ret; } /* set polarity to low for all gpios */ -- GitLab From 623fd246bb40234fe68dd4e7c1f1f081f9c45a3d Mon Sep 17 00:00:00 2001 From: Alexandre Kroupski Date: Tue, 20 Aug 2019 08:37:45 -0300 Subject: [PATCH 4220/7155] media: atmel: atmel-isi: fix timeout value for stop streaming In case of sensor malfunction, stop streaming timeout takes much longer than expected. This is due to conversion of time to jiffies: milliseconds multiplied with HZ (ticks/second) gives out a value of jiffies with 10^3 greater. We need to also divide by 10^3 to obtain the right jiffies value. In other words FRAME_INTERVAL_MILLI_SEC must be in seconds in order to multiply by HZ and get the right jiffies value to add to the current jiffies for the timeout expire time. Fixes: 195ebc43bf76 ("[media] V4L: at91: add Atmel Image Sensor Interface (ISI) support") Signed-off-by: Alexandre Kroupski Reviewed-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/atmel/atmel-isi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index d7d94c1a39d3..428f117caa59 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -493,7 +493,7 @@ static void stop_streaming(struct vb2_queue *vq) spin_unlock_irq(&isi->irqlock); if (!isi->enable_preview_path) { - timeout = jiffies + FRAME_INTERVAL_MILLI_SEC * HZ; + timeout = jiffies + (FRAME_INTERVAL_MILLI_SEC * HZ) / 1000; /* Wait until the end of the current frame. */ while ((isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) && time_before(jiffies, timeout)) -- GitLab From c5e8f4ccd7750487f4ce05d0e801637124f14609 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Aug 2019 05:21:12 -0300 Subject: [PATCH 4221/7155] media: dt-bindings: media: Add Allwinner A10 CSI binding The Allwinner A10 CMOS Sensor Interface is a camera capture interface also used in later (A10s, A13, A20, R8 and GR8) SoCs. On some SoCs, like the A10, there's multiple instances of that controller, with one instance supporting more channels and having an ISP. [Sakari Ailus: Add type: object to the endpoint node.] Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/allwinner,sun4i-a10-csi.yaml | 109 ++++++++++++++++++ MAINTAINERS | 7 ++ 2 files changed, 116 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml new file mode 100644 index 000000000000..27f38eed389e --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/allwinner,sun4i-a10-csi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +description: |- + The Allwinner A10 and later has a CMOS Sensor Interface to retrieve + frames from a parallel or BT656 sensor. + +properties: + compatible: + const: allwinner,sun7i-a20-csi0 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: The CSI interface clock + - description: The CSI module clock + - description: The CSI ISP clock + - description: The CSI DRAM clock + + clock-names: + items: + - const: bus + - const: mod + - const: isp + - const: ram + + resets: + maxItems: 1 + + # See ./video-interfaces.txt for details + port: + type: object + additionalProperties: false + + properties: + endpoint: + type: object + + properties: + bus-width: + enum: [8, 16] + + data-active: true + hsync-active: true + pclk-sample: true + remote-endpoint: true + vsync-active: true + + required: + - bus-width + - data-active + - hsync-active + - pclk-sample + - remote-endpoint + - vsync-active + + required: + - endpoint + +required: + - compatible + - reg + - interrupts + - clocks + +additionalProperties: false + +examples: + - | + #include + #include + #include + + csi0: csi@1c09000 { + compatible = "allwinner,sun7i-a20-csi0"; + reg = <0x01c09000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>, + <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>; + clock-names = "bus", "mod", "isp", "ram"; + resets = <&ccu RST_CSI0>; + + port { + csi_from_ov5640: endpoint { + remote-endpoint = <&ov5640_to_csi>; + bus-width = <8>; + hsync-active = <1>; /* Active high */ + vsync-active = <0>; /* Active low */ + data-active = <1>; /* Active high */ + pclk-sample = <1>; /* Rising */ + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 7dfe381c8b43..496f521356c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1421,6 +1421,13 @@ F: drivers/pinctrl/sunxi/ F: drivers/soc/sunxi/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git +Allwinner A10 CSI driver +M: Maxime Ripard +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml +S: Maintained + ARM/Amlogic Meson SoC CLOCK FRAMEWORK M: Neil Armstrong M: Jerome Brunet -- GitLab From 3f0e6df62213ede83e3b223d36594cbcc953cb08 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Aug 2019 05:21:13 -0300 Subject: [PATCH 4222/7155] media: sunxi: Refactor the Makefile and Kconfig The Makefile and Kconfig for the sun6i CSI driver are included in the main Makefile / KConfig file. Since we're going to add a new CSI driver for an older chip, and the Cedrus driver eventually, it makes more sense to put those in our directory. Signed-off-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 2 +- drivers/media/platform/Makefile | 2 +- drivers/media/platform/sunxi/Kconfig | 1 + drivers/media/platform/sunxi/Makefile | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/sunxi/Kconfig create mode 100644 drivers/media/platform/sunxi/Makefile diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index ca8455d77dc7..83a785010753 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -146,7 +146,7 @@ source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" source "drivers/media/platform/rcar-vin/Kconfig" source "drivers/media/platform/atmel/Kconfig" -source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" +source "drivers/media/platform/sunxi/Kconfig" config VIDEO_TI_CAL tristate "TI CAL (Camera Adaptation Layer) driver" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 7cbbd925124c..6ee7eb0d36f4 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -100,4 +100,4 @@ obj-y += meson/ obj-y += cros-ec-cec/ -obj-$(CONFIG_VIDEO_SUN6I_CSI) += sunxi/sun6i-csi/ +obj-y += sunxi/ diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig new file mode 100644 index 000000000000..1b6e89cb78b2 --- /dev/null +++ b/drivers/media/platform/sunxi/Kconfig @@ -0,0 +1 @@ +source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile new file mode 100644 index 000000000000..8d06f98500ee --- /dev/null +++ b/drivers/media/platform/sunxi/Makefile @@ -0,0 +1 @@ +obj-y += sun6i-csi/ -- GitLab From 577bbf23b758848f0c4a50d346460b690c753024 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Aug 2019 05:21:14 -0300 Subject: [PATCH 4223/7155] media: sunxi: Add A10 CSI driver The older CSI drivers have camera capture interface different from the one in the newer ones. This IP is pretty simple. Some variants (one controller out of two instances on some SoCs) have an ISP embedded, but there's no code that make use of it, so we ignored that part for now. [Sakari Ailus: Wrapped a few long lines, set mbus code using a macro.] Signed-off-by: Maxime Ripard Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + drivers/media/platform/sunxi/Kconfig | 1 + drivers/media/platform/sunxi/Makefile | 1 + .../media/platform/sunxi/sun4i-csi/Kconfig | 11 + .../media/platform/sunxi/sun4i-csi/Makefile | 5 + .../platform/sunxi/sun4i-csi/sun4i_csi.c | 314 ++++++++++++ .../platform/sunxi/sun4i-csi/sun4i_csi.h | 160 ++++++ .../platform/sunxi/sun4i-csi/sun4i_dma.c | 454 ++++++++++++++++++ .../platform/sunxi/sun4i-csi/sun4i_v4l2.c | 385 +++++++++++++++ 9 files changed, 1332 insertions(+) create mode 100644 drivers/media/platform/sunxi/sun4i-csi/Kconfig create mode 100644 drivers/media/platform/sunxi/sun4i-csi/Makefile create mode 100644 drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c create mode 100644 drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h create mode 100644 drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c create mode 100644 drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c diff --git a/MAINTAINERS b/MAINTAINERS index 496f521356c8..7c62b45201d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1425,6 +1425,7 @@ Allwinner A10 CSI driver M: Maxime Ripard L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git +F: drivers/media/platform/sunxi/sun4i-csi/ F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml S: Maintained diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig index 1b6e89cb78b2..71808e93ac2e 100644 --- a/drivers/media/platform/sunxi/Kconfig +++ b/drivers/media/platform/sunxi/Kconfig @@ -1 +1,2 @@ +source "drivers/media/platform/sunxi/sun4i-csi/Kconfig" source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile index 8d06f98500ee..a05127529006 100644 --- a/drivers/media/platform/sunxi/Makefile +++ b/drivers/media/platform/sunxi/Makefile @@ -1 +1,2 @@ +obj-y += sun4i-csi/ obj-y += sun6i-csi/ diff --git a/drivers/media/platform/sunxi/sun4i-csi/Kconfig b/drivers/media/platform/sunxi/sun4i-csi/Kconfig new file mode 100644 index 000000000000..e86e29b6a603 --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_SUN4I_CSI + tristate "Allwinner A10 CMOS Sensor Interface Support" + depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA + depends on ARCH_SUNXI || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + select V4L2_FWNODE + help + This is a V4L2 driver for the Allwinner A10 CSI + + To compile this driver as a module, choose M here: the module + will be called sun4i_csi. diff --git a/drivers/media/platform/sunxi/sun4i-csi/Makefile b/drivers/media/platform/sunxi/sun4i-csi/Makefile new file mode 100644 index 000000000000..7c790a57f5ee --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/Makefile @@ -0,0 +1,5 @@ +sun4i-csi-y += sun4i_csi.o +sun4i-csi-y += sun4i_dma.o +sun4i-csi-y += sun4i_v4l2.o + +obj-$(CONFIG_VIDEO_SUN4I_CSI) += sun4i-csi.o diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c new file mode 100644 index 000000000000..f36dc6258900 --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 NextThing Co + * Copyright (C) 2016-2019 Bootlin + * + * Author: Maxime Ripard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "sun4i_csi.h" + +static const struct media_entity_operations sun4i_csi_video_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi, + notifier); + + csi->src_subdev = subdev; + csi->src_pad = media_entity_get_fwnode_pad(&subdev->entity, + subdev->fwnode, + MEDIA_PAD_FL_SOURCE); + if (csi->src_pad < 0) { + dev_err(csi->dev, "Couldn't find output pad for subdev %s\n", + subdev->name); + return csi->src_pad; + } + + dev_dbg(csi->dev, "Bound %s pad: %d\n", subdev->name, csi->src_pad); + return 0; +} + +static int sun4i_csi_notify_complete(struct v4l2_async_notifier *notifier) +{ + struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi, + notifier); + struct v4l2_subdev *subdev = &csi->subdev; + struct video_device *vdev = &csi->vdev; + int ret; + + ret = v4l2_device_register_subdev(&csi->v4l, subdev); + if (ret < 0) + return ret; + + ret = sun4i_csi_v4l2_register(csi); + if (ret < 0) + return ret; + + ret = media_device_register(&csi->mdev); + if (ret) + return ret; + + /* Create link from subdev to main device */ + ret = media_create_pad_link(&subdev->entity, CSI_SUBDEV_SOURCE, + &vdev->entity, 0, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) + goto err_clean_media; + + ret = media_create_pad_link(&csi->src_subdev->entity, csi->src_pad, + &subdev->entity, CSI_SUBDEV_SINK, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) + goto err_clean_media; + + ret = v4l2_device_register_subdev_nodes(&csi->v4l); + if (ret < 0) + goto err_clean_media; + + return 0; + +err_clean_media: + media_device_unregister(&csi->mdev); + + return ret; +} + +static const struct v4l2_async_notifier_operations sun4i_csi_notify_ops = { + .bound = sun4i_csi_notify_bound, + .complete = sun4i_csi_notify_complete, +}; + +static int sun4i_csi_notifier_init(struct sun4i_csi *csi) +{ + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_PARALLEL, + }; + struct fwnode_handle *ep; + int ret; + + v4l2_async_notifier_init(&csi->notifier); + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + return -EINVAL; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto out; + + csi->bus = vep.bus.parallel; + + ret = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier, + ep, &csi->asd); + if (ret) + goto out; + + csi->notifier.ops = &sun4i_csi_notify_ops; + +out: + fwnode_handle_put(ep); + return ret; +} + +static int sun4i_csi_probe(struct platform_device *pdev) +{ + struct v4l2_subdev *subdev; + struct video_device *vdev; + struct sun4i_csi *csi; + struct resource *res; + int ret; + int irq; + + csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL); + if (!csi) + return -ENOMEM; + platform_set_drvdata(pdev, csi); + csi->dev = &pdev->dev; + subdev = &csi->subdev; + vdev = &csi->vdev; + + csi->mdev.dev = csi->dev; + strscpy(csi->mdev.model, "Allwinner Video Capture Device", + sizeof(csi->mdev.model)); + csi->mdev.hw_revision = 0; + media_device_init(&csi->mdev); + csi->v4l.mdev = &csi->mdev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + csi->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(csi->regs)) + return PTR_ERR(csi->regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + csi->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(csi->bus_clk)) { + dev_err(&pdev->dev, "Couldn't get our bus clock\n"); + return PTR_ERR(csi->bus_clk); + } + + csi->isp_clk = devm_clk_get(&pdev->dev, "isp"); + if (IS_ERR(csi->isp_clk)) { + dev_err(&pdev->dev, "Couldn't get our ISP clock\n"); + return PTR_ERR(csi->isp_clk); + } + + csi->ram_clk = devm_clk_get(&pdev->dev, "ram"); + if (IS_ERR(csi->ram_clk)) { + dev_err(&pdev->dev, "Couldn't get our ram clock\n"); + return PTR_ERR(csi->ram_clk); + } + + csi->rst = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(csi->rst)) { + dev_err(&pdev->dev, "Couldn't get our reset line\n"); + return PTR_ERR(csi->rst); + } + + /* Initialize subdev */ + v4l2_subdev_init(subdev, &sun4i_csi_subdev_ops); + subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + subdev->owner = THIS_MODULE; + snprintf(subdev->name, sizeof(subdev->name), "sun4i-csi-0"); + v4l2_set_subdevdata(subdev, csi); + + csi->subdev_pads[CSI_SUBDEV_SINK].flags = + MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; + csi->subdev_pads[CSI_SUBDEV_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&subdev->entity, CSI_SUBDEV_PADS, + csi->subdev_pads); + if (ret < 0) + return ret; + + csi->vdev_pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; + vdev->entity.ops = &sun4i_csi_video_entity_ops; + ret = media_entity_pads_init(&vdev->entity, 1, &csi->vdev_pad); + if (ret < 0) + return ret; + + ret = sun4i_csi_dma_register(csi, irq); + if (ret) + goto err_clean_pad; + + ret = sun4i_csi_notifier_init(csi); + if (ret) + goto err_unregister_media; + + ret = v4l2_async_notifier_register(&csi->v4l, &csi->notifier); + if (ret) { + dev_err(csi->dev, "Couldn't register our notifier.\n"); + goto err_unregister_media; + } + + pm_runtime_enable(&pdev->dev); + + return 0; + +err_unregister_media: + media_device_unregister(&csi->mdev); + sun4i_csi_dma_unregister(csi); + +err_clean_pad: + media_device_cleanup(&csi->mdev); + + return ret; +} + +static int sun4i_csi_remove(struct platform_device *pdev) +{ + struct sun4i_csi *csi = platform_get_drvdata(pdev); + + v4l2_async_notifier_unregister(&csi->notifier); + v4l2_async_notifier_cleanup(&csi->notifier); + media_device_unregister(&csi->mdev); + sun4i_csi_dma_unregister(csi); + media_device_cleanup(&csi->mdev); + + return 0; +} + +static const struct of_device_id sun4i_csi_of_match[] = { + { .compatible = "allwinner,sun7i-a20-csi0" }, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sun4i_csi_of_match); + +static int __maybe_unused sun4i_csi_runtime_resume(struct device *dev) +{ + struct sun4i_csi *csi = dev_get_drvdata(dev); + + reset_control_deassert(csi->rst); + clk_prepare_enable(csi->bus_clk); + clk_prepare_enable(csi->ram_clk); + clk_set_rate(csi->isp_clk, 80000000); + clk_prepare_enable(csi->isp_clk); + + writel(1, csi->regs + CSI_EN_REG); + + return 0; +} + +static int __maybe_unused sun4i_csi_runtime_suspend(struct device *dev) +{ + struct sun4i_csi *csi = dev_get_drvdata(dev); + + clk_disable_unprepare(csi->isp_clk); + clk_disable_unprepare(csi->ram_clk); + clk_disable_unprepare(csi->bus_clk); + + reset_control_assert(csi->rst); + + return 0; +} + +static const struct dev_pm_ops sun4i_csi_pm_ops = { + SET_RUNTIME_PM_OPS(sun4i_csi_runtime_suspend, + sun4i_csi_runtime_resume, + NULL) +}; + +static struct platform_driver sun4i_csi_driver = { + .probe = sun4i_csi_probe, + .remove = sun4i_csi_remove, + .driver = { + .name = "sun4i-csi", + .of_match_table = sun4i_csi_of_match, + .pm = &sun4i_csi_pm_ops, + }, +}; +module_platform_driver(sun4i_csi_driver); + +MODULE_DESCRIPTION("Allwinner A10 Camera Sensor Interface driver"); +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h new file mode 100644 index 000000000000..001c8bde006c --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 NextThing Co + * Copyright (C) 2016-2019 Bootlin + * + * Author: Maxime Ripard + */ + +#ifndef _SUN4I_CSI_H_ +#define _SUN4I_CSI_H_ + +#include +#include +#include +#include +#include +#include + +#define CSI_EN_REG 0x00 + +#define CSI_CFG_REG 0x04 +#define CSI_CFG_INPUT_FMT(fmt) ((fmt) << 20) +#define CSI_CFG_OUTPUT_FMT(fmt) ((fmt) << 16) +#define CSI_CFG_YUV_DATA_SEQ(seq) ((seq) << 8) +#define CSI_CFG_VSYNC_POL(pol) ((pol) << 2) +#define CSI_CFG_HSYNC_POL(pol) ((pol) << 1) +#define CSI_CFG_PCLK_POL(pol) ((pol) << 0) + +#define CSI_CPT_CTRL_REG 0x08 +#define CSI_CPT_CTRL_VIDEO_START BIT(1) +#define CSI_CPT_CTRL_IMAGE_START BIT(0) + +#define CSI_BUF_ADDR_REG(fifo, buf) (0x10 + (0x8 * (fifo)) + (0x4 * (buf))) + +#define CSI_BUF_CTRL_REG 0x28 +#define CSI_BUF_CTRL_DBN BIT(2) +#define CSI_BUF_CTRL_DBS BIT(1) +#define CSI_BUF_CTRL_DBE BIT(0) + +#define CSI_INT_EN_REG 0x30 +#define CSI_INT_FRM_DONE BIT(1) +#define CSI_INT_CPT_DONE BIT(0) + +#define CSI_INT_STA_REG 0x34 + +#define CSI_WIN_CTRL_W_REG 0x40 +#define CSI_WIN_CTRL_W_ACTIVE(w) ((w) << 16) + +#define CSI_WIN_CTRL_H_REG 0x44 +#define CSI_WIN_CTRL_H_ACTIVE(h) ((h) << 16) + +#define CSI_BUF_LEN_REG 0x48 + +#define CSI_MAX_BUFFER 2 +#define CSI_MAX_HEIGHT 8192U +#define CSI_MAX_WIDTH 8192U + +enum csi_input { + CSI_INPUT_RAW = 0, + CSI_INPUT_BT656 = 2, + CSI_INPUT_YUV = 3, +}; + +enum csi_output_raw { + CSI_OUTPUT_RAW_PASSTHROUGH = 0, +}; + +enum csi_output_yuv { + CSI_OUTPUT_YUV_422_PLANAR = 0, + CSI_OUTPUT_YUV_420_PLANAR = 1, + CSI_OUTPUT_YUV_422_UV = 4, + CSI_OUTPUT_YUV_420_UV = 5, + CSI_OUTPUT_YUV_422_MACRO = 8, + CSI_OUTPUT_YUV_420_MACRO = 9, +}; + +enum csi_yuv_data_seq { + CSI_YUV_DATA_SEQ_YUYV = 0, + CSI_YUV_DATA_SEQ_YVYU = 1, + CSI_YUV_DATA_SEQ_UYVY = 2, + CSI_YUV_DATA_SEQ_VYUY = 3, +}; + +enum csi_subdev_pads { + CSI_SUBDEV_SINK, + CSI_SUBDEV_SOURCE, + + CSI_SUBDEV_PADS, +}; + +extern const struct v4l2_subdev_ops sun4i_csi_subdev_ops; + +struct sun4i_csi_format { + u32 mbus; + u32 fourcc; + enum csi_input input; + u32 output; + unsigned int num_planes; + u8 bpp[3]; + unsigned int hsub; + unsigned int vsub; +}; + +const struct sun4i_csi_format *sun4i_csi_find_format(const u32 *fourcc, + const u32 *mbus); + +struct sun4i_csi { + /* Device resources */ + struct device *dev; + + void __iomem *regs; + struct clk *bus_clk; + struct clk *isp_clk; + struct clk *ram_clk; + struct reset_control *rst; + + struct vb2_v4l2_buffer *current_buf[CSI_MAX_BUFFER]; + + struct { + size_t size; + void *vaddr; + dma_addr_t paddr; + } scratch; + + struct v4l2_fwnode_bus_parallel bus; + + /* Main Device */ + struct v4l2_device v4l; + struct media_device mdev; + struct video_device vdev; + struct media_pad vdev_pad; + struct v4l2_pix_format_mplane fmt; + + /* Local subdev */ + struct v4l2_subdev subdev; + struct media_pad subdev_pads[CSI_SUBDEV_PADS]; + struct v4l2_mbus_framefmt subdev_fmt; + + /* V4L2 Async variables */ + struct v4l2_async_subdev asd; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *src_subdev; + int src_pad; + + /* V4L2 variables */ + struct mutex lock; + + /* Videobuf2 */ + struct vb2_queue queue; + struct list_head buf_list; + spinlock_t qlock; + unsigned int sequence; +}; + +int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq); +void sun4i_csi_dma_unregister(struct sun4i_csi *csi); + +int sun4i_csi_v4l2_register(struct sun4i_csi *csi); + +#endif /* _SUN4I_CSI_H_ */ diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c new file mode 100644 index 000000000000..d6979e11a67b --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 NextThing Co + * Copyright (C) 2016-2019 Bootlin + * + * Author: Maxime Ripard + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sun4i_csi.h" + +struct sun4i_csi_buffer { + struct vb2_v4l2_buffer vb; + struct list_head list; +}; + +static inline struct sun4i_csi_buffer * +vb2_v4l2_to_csi_buffer(const struct vb2_v4l2_buffer *p) +{ + return container_of(p, struct sun4i_csi_buffer, vb); +} + +static inline struct sun4i_csi_buffer * +vb2_to_csi_buffer(const struct vb2_buffer *p) +{ + return vb2_v4l2_to_csi_buffer(to_vb2_v4l2_buffer(p)); +} + +static void sun4i_csi_capture_start(struct sun4i_csi *csi) +{ + writel(CSI_CPT_CTRL_VIDEO_START, csi->regs + CSI_CPT_CTRL_REG); +} + +static void sun4i_csi_capture_stop(struct sun4i_csi *csi) +{ + writel(0, csi->regs + CSI_CPT_CTRL_REG); +} + +static int sun4i_csi_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, + unsigned int *nplanes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct sun4i_csi *csi = vb2_get_drv_priv(vq); + unsigned int num_planes = csi->fmt.num_planes; + unsigned int i; + + if (*nplanes) { + if (*nplanes != num_planes) + return -EINVAL; + + for (i = 0; i < num_planes; i++) + if (sizes[i] < csi->fmt.plane_fmt[i].sizeimage) + return -EINVAL; + return 0; + } + + *nplanes = num_planes; + for (i = 0; i < num_planes; i++) + sizes[i] = csi->fmt.plane_fmt[i].sizeimage; + + return 0; +}; + +static int sun4i_csi_buffer_prepare(struct vb2_buffer *vb) +{ + struct sun4i_csi *csi = vb2_get_drv_priv(vb->vb2_queue); + unsigned int i; + + for (i = 0; i < csi->fmt.num_planes; i++) { + unsigned long size = csi->fmt.plane_fmt[i].sizeimage; + + if (vb2_plane_size(vb, i) < size) { + dev_err(csi->dev, "buffer too small (%lu < %lu)\n", + vb2_plane_size(vb, i), size); + return -EINVAL; + } + + vb2_set_plane_payload(vb, i, size); + } + + return 0; +} + +static int sun4i_csi_setup_scratch_buffer(struct sun4i_csi *csi, + unsigned int slot) +{ + dma_addr_t addr = csi->scratch.paddr; + unsigned int plane; + + dev_dbg(csi->dev, + "No more available buffer, using the scratch buffer\n"); + + for (plane = 0; plane < csi->fmt.num_planes; plane++) { + writel(addr, csi->regs + CSI_BUF_ADDR_REG(plane, slot)); + addr += csi->fmt.plane_fmt[plane].sizeimage; + } + + csi->current_buf[slot] = NULL; + return 0; +} + +static int sun4i_csi_buffer_fill_slot(struct sun4i_csi *csi, unsigned int slot) +{ + struct sun4i_csi_buffer *c_buf; + struct vb2_v4l2_buffer *v_buf; + unsigned int plane; + + /* + * We should never end up in a situation where we overwrite an + * already filled slot. + */ + if (WARN_ON(csi->current_buf[slot])) + return -EINVAL; + + if (list_empty(&csi->buf_list)) + return sun4i_csi_setup_scratch_buffer(csi, slot); + + c_buf = list_first_entry(&csi->buf_list, struct sun4i_csi_buffer, list); + list_del_init(&c_buf->list); + + v_buf = &c_buf->vb; + csi->current_buf[slot] = v_buf; + + for (plane = 0; plane < csi->fmt.num_planes; plane++) { + dma_addr_t buf_addr; + + buf_addr = vb2_dma_contig_plane_dma_addr(&v_buf->vb2_buf, + plane); + writel(buf_addr, csi->regs + CSI_BUF_ADDR_REG(plane, slot)); + } + + return 0; +} + +static int sun4i_csi_buffer_fill_all(struct sun4i_csi *csi) +{ + unsigned int slot; + int ret; + + for (slot = 0; slot < CSI_MAX_BUFFER; slot++) { + ret = sun4i_csi_buffer_fill_slot(csi, slot); + if (ret) + return ret; + } + + return 0; +} + +static void sun4i_csi_buffer_mark_done(struct sun4i_csi *csi, + unsigned int slot, + unsigned int sequence) +{ + struct vb2_v4l2_buffer *v_buf; + + if (!csi->current_buf[slot]) { + dev_dbg(csi->dev, "Scratch buffer was used, ignoring..\n"); + return; + } + + v_buf = csi->current_buf[slot]; + v_buf->field = csi->fmt.field; + v_buf->sequence = sequence; + v_buf->vb2_buf.timestamp = ktime_get_ns(); + vb2_buffer_done(&v_buf->vb2_buf, VB2_BUF_STATE_DONE); + + csi->current_buf[slot] = NULL; +} + +static int sun4i_csi_buffer_flip(struct sun4i_csi *csi, unsigned int sequence) +{ + u32 reg = readl(csi->regs + CSI_BUF_CTRL_REG); + unsigned int next; + + /* Our next buffer is not the current buffer */ + next = !(reg & CSI_BUF_CTRL_DBS); + + /* Report the previous buffer as done */ + sun4i_csi_buffer_mark_done(csi, next, sequence); + + /* Put a new buffer in there */ + return sun4i_csi_buffer_fill_slot(csi, next); +} + +static void sun4i_csi_buffer_queue(struct vb2_buffer *vb) +{ + struct sun4i_csi *csi = vb2_get_drv_priv(vb->vb2_queue); + struct sun4i_csi_buffer *buf = vb2_to_csi_buffer(vb); + unsigned long flags; + + spin_lock_irqsave(&csi->qlock, flags); + list_add_tail(&buf->list, &csi->buf_list); + spin_unlock_irqrestore(&csi->qlock, flags); +} + +static void return_all_buffers(struct sun4i_csi *csi, + enum vb2_buffer_state state) +{ + struct sun4i_csi_buffer *buf, *node; + unsigned int slot; + + list_for_each_entry_safe(buf, node, &csi->buf_list, list) { + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); + } + + for (slot = 0; slot < CSI_MAX_BUFFER; slot++) { + struct vb2_v4l2_buffer *v_buf = csi->current_buf[slot]; + + if (!v_buf) + continue; + + vb2_buffer_done(&v_buf->vb2_buf, state); + csi->current_buf[slot] = NULL; + } +} + +static int sun4i_csi_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct sun4i_csi *csi = vb2_get_drv_priv(vq); + struct v4l2_fwnode_bus_parallel *bus = &csi->bus; + const struct sun4i_csi_format *csi_fmt; + unsigned long hsync_pol, pclk_pol, vsync_pol; + unsigned long flags; + unsigned int i; + int ret; + + csi_fmt = sun4i_csi_find_format(&csi->fmt.pixelformat, NULL); + if (!csi_fmt) + return -EINVAL; + + dev_dbg(csi->dev, "Starting capture\n"); + + csi->sequence = 0; + + /* + * We need a scratch buffer in case where we'll not have any + * more buffer queued so that we don't error out. One of those + * cases is when you end up at the last frame to capture, you + * don't havea any buffer queued any more, and yet it doesn't + * really matter since you'll never reach the next buffer. + * + * Since we support the multi-planar API, we need to have a + * buffer for each plane. Allocating a single one large enough + * to hold all the buffers is simpler, so let's go for that. + */ + csi->scratch.size = 0; + for (i = 0; i < csi->fmt.num_planes; i++) + csi->scratch.size += csi->fmt.plane_fmt[i].sizeimage; + + csi->scratch.vaddr = dma_alloc_coherent(csi->dev, + csi->scratch.size, + &csi->scratch.paddr, + GFP_KERNEL); + if (!csi->scratch.vaddr) { + dev_err(csi->dev, "Failed to allocate scratch buffer\n"); + ret = -ENOMEM; + goto err_clear_dma_queue; + } + + ret = media_pipeline_start(&csi->vdev.entity, &csi->vdev.pipe); + if (ret < 0) + goto err_free_scratch_buffer; + + spin_lock_irqsave(&csi->qlock, flags); + + /* Setup timings */ + writel(CSI_WIN_CTRL_W_ACTIVE(csi->fmt.width * 2), + csi->regs + CSI_WIN_CTRL_W_REG); + writel(CSI_WIN_CTRL_H_ACTIVE(csi->fmt.height), + csi->regs + CSI_WIN_CTRL_H_REG); + + hsync_pol = !!(bus->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH); + pclk_pol = !!(bus->flags & V4L2_MBUS_DATA_ACTIVE_HIGH); + vsync_pol = !!(bus->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH); + writel(CSI_CFG_INPUT_FMT(csi_fmt->input) | + CSI_CFG_OUTPUT_FMT(csi_fmt->output) | + CSI_CFG_VSYNC_POL(vsync_pol) | + CSI_CFG_HSYNC_POL(hsync_pol) | + CSI_CFG_PCLK_POL(pclk_pol), + csi->regs + CSI_CFG_REG); + + /* Setup buffer length */ + writel(csi->fmt.plane_fmt[0].bytesperline, + csi->regs + CSI_BUF_LEN_REG); + + /* Prepare our buffers in hardware */ + ret = sun4i_csi_buffer_fill_all(csi); + if (ret) { + spin_unlock_irqrestore(&csi->qlock, flags); + goto err_disable_pipeline; + } + + /* Enable double buffering */ + writel(CSI_BUF_CTRL_DBE, csi->regs + CSI_BUF_CTRL_REG); + + /* Clear the pending interrupts */ + writel(CSI_INT_FRM_DONE, csi->regs + 0x34); + + /* Enable frame done interrupt */ + writel(CSI_INT_FRM_DONE, csi->regs + CSI_INT_EN_REG); + + sun4i_csi_capture_start(csi); + + spin_unlock_irqrestore(&csi->qlock, flags); + + ret = v4l2_subdev_call(csi->src_subdev, video, s_stream, 1); + if (ret < 0 && ret != -ENOIOCTLCMD) + goto err_disable_device; + + return 0; + +err_disable_device: + sun4i_csi_capture_stop(csi); + +err_disable_pipeline: + media_pipeline_stop(&csi->vdev.entity); + +err_free_scratch_buffer: + dma_free_coherent(csi->dev, csi->scratch.size, csi->scratch.vaddr, + csi->scratch.paddr); + +err_clear_dma_queue: + spin_lock_irqsave(&csi->qlock, flags); + return_all_buffers(csi, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&csi->qlock, flags); + + return ret; +} + +static void sun4i_csi_stop_streaming(struct vb2_queue *vq) +{ + struct sun4i_csi *csi = vb2_get_drv_priv(vq); + unsigned long flags; + + dev_dbg(csi->dev, "Stopping capture\n"); + + v4l2_subdev_call(csi->src_subdev, video, s_stream, 0); + sun4i_csi_capture_stop(csi); + + /* Release all active buffers */ + spin_lock_irqsave(&csi->qlock, flags); + return_all_buffers(csi, VB2_BUF_STATE_ERROR); + spin_unlock_irqrestore(&csi->qlock, flags); + + media_pipeline_stop(&csi->vdev.entity); + + dma_free_coherent(csi->dev, csi->scratch.size, csi->scratch.vaddr, + csi->scratch.paddr); +} + +static const struct vb2_ops sun4i_csi_qops = { + .queue_setup = sun4i_csi_queue_setup, + .buf_prepare = sun4i_csi_buffer_prepare, + .buf_queue = sun4i_csi_buffer_queue, + .start_streaming = sun4i_csi_start_streaming, + .stop_streaming = sun4i_csi_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static irqreturn_t sun4i_csi_irq(int irq, void *data) +{ + struct sun4i_csi *csi = data; + u32 reg; + + reg = readl(csi->regs + CSI_INT_STA_REG); + + /* Acknowledge the interrupts */ + writel(reg, csi->regs + CSI_INT_STA_REG); + + if (!(reg & CSI_INT_FRM_DONE)) + return IRQ_HANDLED; + + spin_lock(&csi->qlock); + if (sun4i_csi_buffer_flip(csi, csi->sequence++)) { + dev_warn(csi->dev, "%s: Flip failed\n", __func__); + sun4i_csi_capture_stop(csi); + } + spin_unlock(&csi->qlock); + + return IRQ_HANDLED; +} + +int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq) +{ + struct vb2_queue *q = &csi->queue; + int ret; + int i; + + spin_lock_init(&csi->qlock); + mutex_init(&csi->lock); + + INIT_LIST_HEAD(&csi->buf_list); + for (i = 0; i < CSI_MAX_BUFFER; i++) + csi->current_buf[i] = NULL; + + q->min_buffers_needed = 3; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->io_modes = VB2_MMAP; + q->lock = &csi->lock; + q->drv_priv = csi; + q->buf_struct_size = sizeof(struct sun4i_csi_buffer); + q->ops = &sun4i_csi_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->dev = csi->dev; + + ret = vb2_queue_init(q); + if (ret < 0) { + dev_err(csi->dev, "failed to initialize VB2 queue\n"); + goto err_free_mutex; + } + + ret = v4l2_device_register(csi->dev, &csi->v4l); + if (ret) { + dev_err(csi->dev, "Couldn't register the v4l2 device\n"); + goto err_free_queue; + } + + ret = devm_request_irq(csi->dev, irq, sun4i_csi_irq, 0, + dev_name(csi->dev), csi); + if (ret) { + dev_err(csi->dev, "Couldn't register our interrupt\n"); + goto err_unregister_device; + } + + return 0; + +err_unregister_device: + v4l2_device_unregister(&csi->v4l); + +err_free_queue: + vb2_queue_release(q); + +err_free_mutex: + mutex_destroy(&csi->lock); + return ret; +} + +void sun4i_csi_dma_unregister(struct sun4i_csi *csi) +{ + v4l2_device_unregister(&csi->v4l); + vb2_queue_release(&csi->queue); + mutex_destroy(&csi->lock); +} diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c new file mode 100644 index 000000000000..772b0fc5920f --- /dev/null +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 NextThing Co + * Copyright (C) 2016-2019 Bootlin + * + * Author: Maxime Ripard + */ + +#include +#include + +#include +#include +#include + +#include "sun4i_csi.h" + +#define CSI_DEFAULT_WIDTH 640 +#define CSI_DEFAULT_HEIGHT 480 + +const struct sun4i_csi_format sun4i_csi_formats[] = { + /* YUV422 inputs */ + { + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + .fourcc = V4L2_PIX_FMT_YUV420M, + .input = CSI_INPUT_YUV, + .output = CSI_OUTPUT_YUV_420_PLANAR, + .num_planes = 3, + .bpp = { 8, 8, 8 }, + .hsub = 2, + .vsub = 2, + }, +}; + +const struct sun4i_csi_format *sun4i_csi_find_format(const u32 *fourcc, + const u32 *mbus) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sun4i_csi_formats); i++) { + if (fourcc && *fourcc != sun4i_csi_formats[i].fourcc) + continue; + + if (mbus && *mbus != sun4i_csi_formats[i].mbus) + continue; + + return &sun4i_csi_formats[i]; + } + + return NULL; +} + +static int sun4i_csi_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct sun4i_csi *csi = video_drvdata(file); + + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, "sun4i-csi", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + dev_name(csi->dev)); + + return 0; +} + +static int sun4i_csi_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + strscpy(inp->name, "Camera", sizeof(inp->name)); + + return 0; +} + +static int sun4i_csi_g_input(struct file *file, void *fh, + unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int sun4i_csi_s_input(struct file *file, void *fh, + unsigned int i) +{ + if (i != 0) + return -EINVAL; + + return 0; +} + +static void _sun4i_csi_try_fmt(struct sun4i_csi *csi, + struct v4l2_pix_format_mplane *pix) +{ + const struct sun4i_csi_format *_fmt; + unsigned int height, width; + unsigned int i; + + _fmt = sun4i_csi_find_format(&pix->pixelformat, NULL); + if (!_fmt) + _fmt = &sun4i_csi_formats[0]; + + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace); + pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace); + pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, pix->colorspace, + pix->ycbcr_enc); + + pix->num_planes = _fmt->num_planes; + pix->pixelformat = _fmt->fourcc; + + memset(pix->reserved, 0, sizeof(pix->reserved)); + + /* Align the width and height on the subsampling */ + width = ALIGN(pix->width, _fmt->hsub); + height = ALIGN(pix->height, _fmt->vsub); + + /* Clamp the width and height to our capabilities */ + pix->width = clamp(width, _fmt->hsub, CSI_MAX_WIDTH); + pix->height = clamp(height, _fmt->vsub, CSI_MAX_HEIGHT); + + for (i = 0; i < _fmt->num_planes; i++) { + unsigned int hsub = i > 0 ? _fmt->hsub : 1; + unsigned int vsub = i > 0 ? _fmt->vsub : 1; + unsigned int bpl; + + bpl = pix->width / hsub * _fmt->bpp[i] / 8; + pix->plane_fmt[i].bytesperline = bpl; + pix->plane_fmt[i].sizeimage = bpl * pix->height / vsub; + memset(pix->plane_fmt[i].reserved, 0, + sizeof(pix->plane_fmt[i].reserved)); + } +} + +static int sun4i_csi_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct sun4i_csi *csi = video_drvdata(file); + + _sun4i_csi_try_fmt(csi, &f->fmt.pix_mp); + + return 0; +} + +static int sun4i_csi_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct sun4i_csi *csi = video_drvdata(file); + + _sun4i_csi_try_fmt(csi, &f->fmt.pix_mp); + csi->fmt = f->fmt.pix_mp; + + return 0; +} + +static int sun4i_csi_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct sun4i_csi *csi = video_drvdata(file); + + f->fmt.pix_mp = csi->fmt; + + return 0; +} + +static int sun4i_csi_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(sun4i_csi_formats)) + return -EINVAL; + + f->pixelformat = sun4i_csi_formats[f->index].fourcc; + + return 0; +} + +static const struct v4l2_ioctl_ops sun4i_csi_ioctl_ops = { + .vidioc_querycap = sun4i_csi_querycap, + + .vidioc_enum_fmt_vid_cap = sun4i_csi_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap_mplane = sun4i_csi_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap_mplane = sun4i_csi_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap_mplane = sun4i_csi_try_fmt_vid_cap, + + .vidioc_enum_input = sun4i_csi_enum_input, + .vidioc_g_input = sun4i_csi_g_input, + .vidioc_s_input = sun4i_csi_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, +}; + +static int sun4i_csi_open(struct file *file) +{ + struct sun4i_csi *csi = video_drvdata(file); + int ret; + + ret = mutex_lock_interruptible(&csi->lock); + if (ret) + return ret; + + ret = pm_runtime_get_sync(csi->dev); + if (ret < 0) + goto err_pm_put; + + ret = v4l2_pipeline_pm_use(&csi->vdev.entity, 1); + if (ret) + goto err_pm_put; + + ret = v4l2_fh_open(file); + if (ret) + goto err_pipeline_pm_put; + + mutex_unlock(&csi->lock); + + return 0; + +err_pipeline_pm_put: + v4l2_pipeline_pm_use(&csi->vdev.entity, 0); + +err_pm_put: + pm_runtime_put(csi->dev); + mutex_unlock(&csi->lock); + + return ret; +} + +static int sun4i_csi_release(struct file *file) +{ + struct sun4i_csi *csi = video_drvdata(file); + + mutex_lock(&csi->lock); + + v4l2_fh_release(file); + v4l2_pipeline_pm_use(&csi->vdev.entity, 0); + pm_runtime_put(csi->dev); + + mutex_unlock(&csi->lock); + + return 0; +} + +static const struct v4l2_file_operations sun4i_csi_fops = { + .owner = THIS_MODULE, + .open = sun4i_csi_open, + .release = sun4i_csi_release, + .unlocked_ioctl = video_ioctl2, + .read = vb2_fop_read, + .write = vb2_fop_write, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_mbus_framefmt sun4i_csi_pad_fmt_default = { + .width = CSI_DEFAULT_WIDTH, + .height = CSI_DEFAULT_HEIGHT, + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_RAW, + .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, + .quantization = V4L2_QUANTIZATION_DEFAULT, + .xfer_func = V4L2_XFER_FUNC_DEFAULT, +}; + +static int sun4i_csi_subdev_init_cfg(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg) +{ + struct v4l2_mbus_framefmt *fmt; + + fmt = v4l2_subdev_get_try_format(subdev, cfg, CSI_SUBDEV_SINK); + *fmt = sun4i_csi_pad_fmt_default; + + return 0; +} + +static int sun4i_csi_subdev_get_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct sun4i_csi *csi = container_of(subdev, struct sun4i_csi, subdev); + struct v4l2_mbus_framefmt *subdev_fmt; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + subdev_fmt = v4l2_subdev_get_try_format(subdev, cfg, fmt->pad); + else + subdev_fmt = &csi->subdev_fmt; + + fmt->format = *subdev_fmt; + + return 0; +} + +static int sun4i_csi_subdev_set_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct sun4i_csi *csi = container_of(subdev, struct sun4i_csi, subdev); + struct v4l2_mbus_framefmt *subdev_fmt; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + subdev_fmt = v4l2_subdev_get_try_format(subdev, cfg, fmt->pad); + else + subdev_fmt = &csi->subdev_fmt; + + /* We can only set the format on the sink pad */ + if (fmt->pad == CSI_SUBDEV_SINK) { + /* It's the sink, only allow changing the frame size */ + subdev_fmt->width = fmt->format.width; + subdev_fmt->height = fmt->format.height; + subdev_fmt->code = fmt->format.code; + } + + fmt->format = *subdev_fmt; + + return 0; +} + +static int +sun4i_csi_subdev_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *mbus) +{ + if (mbus->index >= ARRAY_SIZE(sun4i_csi_formats)) + return -EINVAL; + + mbus->code = sun4i_csi_formats[mbus->index].mbus; + + return 0; +} + +static const struct v4l2_subdev_pad_ops sun4i_csi_subdev_pad_ops = { + .link_validate = v4l2_subdev_link_validate_default, + .init_cfg = sun4i_csi_subdev_init_cfg, + .get_fmt = sun4i_csi_subdev_get_fmt, + .set_fmt = sun4i_csi_subdev_set_fmt, + .enum_mbus_code = sun4i_csi_subdev_enum_mbus_code, +}; + +const struct v4l2_subdev_ops sun4i_csi_subdev_ops = { + .pad = &sun4i_csi_subdev_pad_ops, +}; + +int sun4i_csi_v4l2_register(struct sun4i_csi *csi) +{ + struct video_device *vdev = &csi->vdev; + int ret; + + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; + vdev->v4l2_dev = &csi->v4l; + vdev->queue = &csi->queue; + strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); + vdev->release = video_device_release_empty; + vdev->lock = &csi->lock; + + /* Set a default format */ + csi->fmt.pixelformat = sun4i_csi_formats[0].fourcc, + csi->fmt.width = CSI_DEFAULT_WIDTH; + csi->fmt.height = CSI_DEFAULT_HEIGHT; + _sun4i_csi_try_fmt(csi, &csi->fmt); + csi->subdev_fmt = sun4i_csi_pad_fmt_default; + + vdev->fops = &sun4i_csi_fops; + vdev->ioctl_ops = &sun4i_csi_ioctl_ops; + video_set_drvdata(vdev, csi); + + ret = video_register_device(&csi->vdev, VFL_TYPE_GRABBER, -1); + if (ret) + return ret; + + dev_info(csi->dev, "Device registered as %s\n", + video_device_node_name(vdev)); + + return 0; +} -- GitLab From 542694df7511977c3baa6ba855126a0cce883977 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 23 Aug 2019 09:58:32 +0900 Subject: [PATCH 4224/7155] ASoC: soc-core: rename soc_post_component_init() to soc_rtd_init() It is easy to read code if it is cleanly using paired function/naming, like start <-> stop, register <-> unregister, etc, etc. But, current ALSA SoC code is very random, unbalance, not paired, etc. It is easy to create bug at the such code, and it will be difficult to debug. From function name point of view, "soc_post_component_init()" sounds like "component initialize function". But in reality it is rtd setup function. This patch renames soc_post_component_init() to soc_rtd_init() Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9uo7lc3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0af83963289f..3c087b478398 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1340,13 +1340,12 @@ static int soc_probe_component(struct snd_soc_card *card, return ret; } -static void rtd_release(struct device *dev) +static void soc_rtd_release(struct device *dev) { kfree(dev); } -static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, - const char *name) +static int soc_rtd_init(struct snd_soc_pcm_runtime *rtd, const char *name) { int ret = 0; @@ -1355,7 +1354,7 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, if (!rtd->dev) return -ENOMEM; rtd->dev->parent = rtd->card->dev; - rtd->dev->release = rtd_release; + rtd->dev->release = soc_rtd_release; rtd->dev->groups = soc_dev_attr_groups; dev_set_name(rtd->dev, "%s", name); dev_set_drvdata(rtd->dev, rtd); @@ -1483,7 +1482,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, return ret; } - ret = soc_post_component_init(rtd, dai_link->name); + ret = soc_rtd_init(rtd, dai_link->name); if (ret) return ret; -- GitLab From d41f36a6464a85c06ad920703d878e4491d2c023 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:24:50 +0300 Subject: [PATCH 4225/7155] spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours The DSPI interrupt can be shared between two controllers at least on the LX2160A. In that case, the driver for one controller might misbehave and consume the other's interrupt. Fix this by actually checking if any of the bits in the status register have been asserted. Fixes: 13aed2392741 ("spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822212450.21420-2-olteanv@gmail.com Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-fsl-dspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 53335ccc98f6..545fc8189fb0 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -886,9 +886,11 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) trans_mode); } } + + return IRQ_HANDLED; } - return IRQ_HANDLED; + return IRQ_NONE; } static const struct of_device_id fsl_dspi_dt_ids[] = { -- GitLab From 57b3006492a4c11b2d4a772b5b2905d544a32037 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 22 Aug 2019 11:32:00 +0300 Subject: [PATCH 4226/7155] ACPI / LPSS: Save/restore LPSS private registers also on Lynxpoint My assumption in commit b53548f9d9e4 ("spi: pxa2xx: Remove LPSS private register restoring during resume") that Intel Lynxpoint and compatible based chipsets may not need LPSS private registers saving and restoring over suspend/resume cycle turned out to be false on Intel Broadwell. Curtis Malainey sent a patch bringing above change back and reported the LPSS SPI Chip Select control was lost over suspend/resume cycle on Broadwell machine. Instead of reverting above commit lets add LPSS private register saving/restoring also for all LPSS SPI, I2C and UART controllers on Lynxpoint and compatible chipset to make sure context is not lost in case nothing else preserves it like firmware or if LPSS is always on. Fixes: b53548f9d9e4 ("spi: pxa2xx: Remove LPSS private register restoring during resume") Reported-by: Curtis Malainey Tested-by: Curtis Malainey Cc: 5.0+ # 5.0+ Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index d696f165a50e..60bbc5090abe 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -219,12 +219,13 @@ static void bsw_pwm_setup(struct lpss_private_data *pdata) } static const struct lpss_device_desc lpt_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR + | LPSS_SAVE_CTX, .prv_offset = 0x800, }; static const struct lpss_device_desc lpt_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR | LPSS_SAVE_CTX, .prv_offset = 0x800, }; @@ -236,7 +237,8 @@ static struct property_entry uart_properties[] = { }; static const struct lpss_device_desc lpt_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR + | LPSS_SAVE_CTX, .clk_con_id = "baudclk", .prv_offset = 0x800, .setup = lpss_uart_setup, -- GitLab From 60e05d1cf0875f0cf73472f7dff71d9933c5b697 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 15 Aug 2019 13:53:41 +0200 Subject: [PATCH 4227/7155] vfio-ccw: add some logging Usually, the common I/O layer logs various things into the s390 cio debug feature, which has been very helpful in the past when looking at crash dumps. As vfio-ccw devices unbind from the standard I/O subchannel driver, we lose some information there. Let's introduce some vfio-ccw debug features and log some things there. (Unfortunately we cannot reuse the cio debug feature from a module.) Message-Id: <20190816151505.9853-2-cohuck@redhat.com> Reviewed-by: Eric Farman Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_drv.c | 50 ++++++++++++++++++++++++++-- drivers/s390/cio/vfio_ccw_fsm.c | 51 ++++++++++++++++++++++++++++- drivers/s390/cio/vfio_ccw_ops.c | 10 ++++++ drivers/s390/cio/vfio_ccw_private.h | 17 ++++++++++ 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 9208c0e56c33..45e792f6afd0 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -27,6 +27,9 @@ struct workqueue_struct *vfio_ccw_work_q; static struct kmem_cache *vfio_ccw_io_region; static struct kmem_cache *vfio_ccw_cmd_region; +debug_info_t *vfio_ccw_debug_msg_id; +debug_info_t *vfio_ccw_debug_trace_id; + /* * Helpers */ @@ -164,6 +167,9 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) if (ret) goto out_disable; + VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n", + sch->schid.cssid, sch->schid.ssid, + sch->schid.sch_no); return 0; out_disable: @@ -194,6 +200,9 @@ static int vfio_ccw_sch_remove(struct subchannel *sch) kfree(private->cp.guest_cp); kfree(private); + VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", + sch->schid.cssid, sch->schid.ssid, + sch->schid.sch_no); return 0; } @@ -263,13 +272,46 @@ static struct css_driver vfio_ccw_sch_driver = { .sch_event = vfio_ccw_sch_event, }; +static int __init vfio_ccw_debug_init(void) +{ + vfio_ccw_debug_msg_id = debug_register("vfio_ccw_msg", 16, 1, + 11 * sizeof(long)); + if (!vfio_ccw_debug_msg_id) + goto out_unregister; + debug_register_view(vfio_ccw_debug_msg_id, &debug_sprintf_view); + debug_set_level(vfio_ccw_debug_msg_id, 2); + vfio_ccw_debug_trace_id = debug_register("vfio_ccw_trace", 16, 1, 16); + if (!vfio_ccw_debug_trace_id) + goto out_unregister; + debug_register_view(vfio_ccw_debug_trace_id, &debug_hex_ascii_view); + debug_set_level(vfio_ccw_debug_trace_id, 2); + return 0; + +out_unregister: + debug_unregister(vfio_ccw_debug_msg_id); + debug_unregister(vfio_ccw_debug_trace_id); + return -1; +} + +static void vfio_ccw_debug_exit(void) +{ + debug_unregister(vfio_ccw_debug_msg_id); + debug_unregister(vfio_ccw_debug_trace_id); +} + static int __init vfio_ccw_sch_init(void) { - int ret = -ENOMEM; + int ret; + + ret = vfio_ccw_debug_init(); + if (ret) + return ret; vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw"); - if (!vfio_ccw_work_q) - return -ENOMEM; + if (!vfio_ccw_work_q) { + ret = -ENOMEM; + goto out_err; + } vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region", sizeof(struct ccw_io_region), 0, @@ -298,6 +340,7 @@ static int __init vfio_ccw_sch_init(void) kmem_cache_destroy(vfio_ccw_cmd_region); kmem_cache_destroy(vfio_ccw_io_region); destroy_workqueue(vfio_ccw_work_q); + vfio_ccw_debug_exit(); return ret; } @@ -308,6 +351,7 @@ static void __exit vfio_ccw_sch_exit(void) kmem_cache_destroy(vfio_ccw_io_region); kmem_cache_destroy(vfio_ccw_cmd_region); destroy_workqueue(vfio_ccw_work_q); + vfio_ccw_debug_exit(); } module_init(vfio_ccw_sch_init); module_exit(vfio_ccw_sch_exit); diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index 49d9d3da0282..4a1e727c62d9 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -37,9 +37,14 @@ static int fsm_io_helper(struct vfio_ccw_private *private) goto out; } + VFIO_CCW_TRACE_EVENT(5, "stIO"); + VFIO_CCW_TRACE_EVENT(5, dev_name(&sch->dev)); + /* Issue "Start Subchannel" */ ccode = ssch(sch->schid, orb); + VFIO_CCW_HEX_EVENT(5, &ccode, sizeof(ccode)); + switch (ccode) { case 0: /* @@ -86,9 +91,14 @@ static int fsm_do_halt(struct vfio_ccw_private *private) spin_lock_irqsave(sch->lock, flags); + VFIO_CCW_TRACE_EVENT(2, "haltIO"); + VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev)); + /* Issue "Halt Subchannel" */ ccode = hsch(sch->schid); + VFIO_CCW_HEX_EVENT(2, &ccode, sizeof(ccode)); + switch (ccode) { case 0: /* @@ -122,9 +132,14 @@ static int fsm_do_clear(struct vfio_ccw_private *private) spin_lock_irqsave(sch->lock, flags); + VFIO_CCW_TRACE_EVENT(2, "clearIO"); + VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev)); + /* Issue "Clear Subchannel" */ ccode = csch(sch->schid); + VFIO_CCW_HEX_EVENT(2, &ccode, sizeof(ccode)); + switch (ccode) { case 0: /* @@ -149,6 +164,9 @@ static void fsm_notoper(struct vfio_ccw_private *private, { struct subchannel *sch = private->sch; + VFIO_CCW_TRACE_EVENT(2, "notoper"); + VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev)); + /* * TODO: * Probably we should send the machine check to the guest. @@ -229,6 +247,7 @@ static void fsm_io_request(struct vfio_ccw_private *private, struct ccw_io_region *io_region = private->io_region; struct mdev_device *mdev = private->mdev; char *errstr = "request"; + struct subchannel_id schid = get_schid(private); private->state = VFIO_CCW_STATE_CP_PROCESSING; memcpy(scsw, io_region->scsw_area, sizeof(*scsw)); @@ -239,18 +258,32 @@ static void fsm_io_request(struct vfio_ccw_private *private, /* Don't try to build a cp if transport mode is specified. */ if (orb->tm.b) { io_region->ret_code = -EOPNOTSUPP; + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): transport mode\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no); errstr = "transport mode"; goto err_out; } io_region->ret_code = cp_init(&private->cp, mdev_dev(mdev), orb); if (io_region->ret_code) { + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): cp_init=%d\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no, + io_region->ret_code); errstr = "cp init"; goto err_out; } io_region->ret_code = cp_prefetch(&private->cp); if (io_region->ret_code) { + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): cp_prefetch=%d\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no, + io_region->ret_code); errstr = "cp prefetch"; cp_free(&private->cp); goto err_out; @@ -259,23 +292,36 @@ static void fsm_io_request(struct vfio_ccw_private *private, /* Start channel program and wait for I/O interrupt. */ io_region->ret_code = fsm_io_helper(private); if (io_region->ret_code) { + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): fsm_io_helper=%d\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no, + io_region->ret_code); errstr = "cp fsm_io_helper"; cp_free(&private->cp); goto err_out; } return; } else if (scsw->cmd.fctl & SCSW_FCTL_HALT_FUNC) { + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): halt on io_region\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no); /* halt is handled via the async cmd region */ io_region->ret_code = -EOPNOTSUPP; goto err_out; } else if (scsw->cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { + VFIO_CCW_MSG_EVENT(2, + "%pUl (%x.%x.%04x): clear on io_region\n", + mdev_uuid(mdev), schid.cssid, + schid.ssid, schid.sch_no); /* clear is handled via the async cmd region */ io_region->ret_code = -EOPNOTSUPP; goto err_out; } err_out: - trace_vfio_ccw_io_fctl(scsw->cmd.fctl, get_schid(private), + trace_vfio_ccw_io_fctl(scsw->cmd.fctl, schid, io_region->ret_code, errstr); } @@ -308,6 +354,9 @@ static void fsm_irq(struct vfio_ccw_private *private, { struct irb *irb = this_cpu_ptr(&cio_irb); + VFIO_CCW_TRACE_EVENT(6, "IRQ"); + VFIO_CCW_TRACE_EVENT(6, dev_name(&private->sch->dev)); + memcpy(&private->irb, irb, sizeof(*irb)); queue_work(vfio_ccw_work_q, &private->io_work); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 5eb61116ca6f..f0d71ab77c50 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -124,6 +124,11 @@ static int vfio_ccw_mdev_create(struct kobject *kobj, struct mdev_device *mdev) private->mdev = mdev; private->state = VFIO_CCW_STATE_IDLE; + VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: create\n", + mdev_uuid(mdev), private->sch->schid.cssid, + private->sch->schid.ssid, + private->sch->schid.sch_no); + return 0; } @@ -132,6 +137,11 @@ static int vfio_ccw_mdev_remove(struct mdev_device *mdev) struct vfio_ccw_private *private = dev_get_drvdata(mdev_parent_dev(mdev)); + VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n", + mdev_uuid(mdev), private->sch->schid.cssid, + private->sch->schid.ssid, + private->sch->schid.sch_no); + if ((private->state != VFIO_CCW_STATE_NOT_OPER) && (private->state != VFIO_CCW_STATE_STANDBY)) { if (!vfio_ccw_sch_quiesce(private->sch)) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index f1092c3dc1b1..bbe9babf767b 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "css.h" #include "vfio_ccw_cp.h" @@ -139,4 +140,20 @@ static inline void vfio_ccw_fsm_event(struct vfio_ccw_private *private, extern struct workqueue_struct *vfio_ccw_work_q; + +/* s390 debug feature, similar to base cio */ +extern debug_info_t *vfio_ccw_debug_msg_id; +extern debug_info_t *vfio_ccw_debug_trace_id; + +#define VFIO_CCW_TRACE_EVENT(imp, txt) \ + debug_text_event(vfio_ccw_debug_trace_id, imp, txt) + +#define VFIO_CCW_MSG_EVENT(imp, args...) \ + debug_sprintf_event(vfio_ccw_debug_msg_id, imp, ##args) + +static inline void VFIO_CCW_HEX_EVENT(int level, void *data, int length) +{ + debug_event(vfio_ccw_debug_trace_id, level, data, length); +} + #endif -- GitLab From 7574729e91468d568cc198de438feb35ef04f41a Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Thu, 22 Aug 2019 00:00:01 +0000 Subject: [PATCH 4228/7155] EDAC/amd64: Cache secondary Chip Select registers AMD Family 17h systems have a set of secondary Chip Select Base Addresses and Address Masks. These do not represent unique Chip Selects, rather they are used in conjunction with the primary Chip Select registers in certain cases. Cache these secondary Chip Select registers for future use. Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-7-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 23 ++++++++++++++++++++--- drivers/edac/amd64_edac.h | 4 ++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e4bc48201b0c..23251bba8eb6 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -946,34 +946,51 @@ static void prep_chip_selects(struct amd64_pvt *pvt) static void read_umc_base_mask(struct amd64_pvt *pvt) { - u32 umc_base_reg, umc_mask_reg; - u32 base_reg, mask_reg; - u32 *base, *mask; + u32 umc_base_reg, umc_base_reg_sec; + u32 umc_mask_reg, umc_mask_reg_sec; + u32 base_reg, base_reg_sec; + u32 mask_reg, mask_reg_sec; + u32 *base, *base_sec; + u32 *mask, *mask_sec; int cs, umc; for_each_umc(umc) { umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR; + umc_base_reg_sec = get_umc_base(umc) + UMCCH_BASE_ADDR_SEC; for_each_chip_select(cs, umc, pvt) { base = &pvt->csels[umc].csbases[cs]; + base_sec = &pvt->csels[umc].csbases_sec[cs]; base_reg = umc_base_reg + (cs * 4); + base_reg_sec = umc_base_reg_sec + (cs * 4); if (!amd_smn_read(pvt->mc_node_id, base_reg, base)) edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n", umc, cs, *base, base_reg); + + if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, base_sec)) + edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *base_sec, base_reg_sec); } umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK; + umc_mask_reg_sec = get_umc_base(umc) + UMCCH_ADDR_MASK_SEC; for_each_chip_select_mask(cs, umc, pvt) { mask = &pvt->csels[umc].csmasks[cs]; + mask_sec = &pvt->csels[umc].csmasks_sec[cs]; mask_reg = umc_mask_reg + (cs * 4); + mask_reg_sec = umc_mask_reg_sec + (cs * 4); if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask)) edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n", umc, cs, *mask, mask_reg); + + if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, mask_sec)) + edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *mask_sec, mask_reg_sec); } } } diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 4dce6a2ac75f..68f12de6e654 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -259,7 +259,9 @@ /* UMC CH register offsets */ #define UMCCH_BASE_ADDR 0x0 +#define UMCCH_BASE_ADDR_SEC 0x10 #define UMCCH_ADDR_MASK 0x20 +#define UMCCH_ADDR_MASK_SEC 0x28 #define UMCCH_ADDR_CFG 0x30 #define UMCCH_DIMM_CFG 0x80 #define UMCCH_UMC_CFG 0x100 @@ -312,9 +314,11 @@ struct dram_range { /* A DCT chip selects collection */ struct chip_select { u32 csbases[NUM_CHIPSELECTS]; + u32 csbases_sec[NUM_CHIPSELECTS]; u8 b_cnt; u32 csmasks[NUM_CHIPSELECTS]; + u32 csmasks_sec[NUM_CHIPSELECTS]; u8 m_cnt; }; -- GitLab From 85a5f06773c85f8ec5030ed65e5fa3190b3f16bd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:43:46 +0800 Subject: [PATCH 4229/7155] ACPI: SBS: remove unused const variable 'SMBUS_PEC' drivers/acpi/sbshc.h:18:17: warning: SMBUS_PEC defined but not used [-Wunused-const-variable=] SMBUS_PEC is never used since introduction in commit 91087dfa51a2 ("ACPI: SBS: Split host controller (ACPI0001) from SBS driver (ACPI0002)"), so just remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sbshc.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h index 06372a37df10..c3522bb82792 100644 --- a/drivers/acpi/sbshc.h +++ b/drivers/acpi/sbshc.h @@ -15,8 +15,6 @@ enum acpi_smb_protocol { SMBUS_BLOCK_PROCESS_CALL = 0xd, }; -static const u8 SMBUS_PEC = 0x80; - enum acpi_sbs_device_addr { ACPI_SBS_CHARGER = 0x9, ACPI_SBS_MANAGER = 0xa, -- GitLab From 12fb61a973935c63f2580b3b053017cc14b51f42 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:10 +0300 Subject: [PATCH 4230/7155] spi: spi-fsl-dspi: Reduce indentation level in dspi_interrupt If the entire function depends on the SPI status register having the interrupt bits asserted, then just check it and exit early if those bits aren't set (such as in the case of the shared IRQ being triggered for the other peripheral). Cosmetic patch. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-2-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 79 +++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 790cb02fc181..c90db7db4121 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -658,47 +658,48 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); + if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) + return IRQ_HANDLED; + + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; + + trans_mode = dspi->devtype_data->trans_mode; + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_read(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_read(dspi); + break; + default: + dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", + trans_mode); + return IRQ_HANDLED; + } - if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { - /* Get transfer counter (in number of SPI transfers). It was - * reset to 0 when transfer(s) were started. - */ - regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); - spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); - /* Update total number of bytes that were transferred */ - msg->actual_length += spi_tcnt * dspi->bytes_per_word; - - trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } + if (!dspi->len) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + return IRQ_HANDLED; + } - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - } else { - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } - } + switch (trans_mode) { + case DSPI_EOQ_MODE: + dspi_eoq_write(dspi); + break; + case DSPI_TCFQ_MODE: + dspi_tcfq_write(dspi); + break; + default: + dev_err(&dspi->pdev->dev, + "unsupported trans_mode %u\n", + trans_mode); } return IRQ_HANDLED; -- GitLab From 37b4100180641968056cb4e034cebc38338e8652 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:11 +0300 Subject: [PATCH 4231/7155] spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours The DSPI interrupt can be shared between two controllers at least on the LX2160A. In that case, the driver for one controller might misbehave and consume the other's interrupt. Fix this by actually checking if any of the bits in the status register have been asserted. Fixes: 13aed2392741 ("spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-3-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c90db7db4121..6ef2279a3699 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -659,7 +659,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) regmap_write(dspi->regmap, SPI_SR, spi_sr); if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) - return IRQ_HANDLED; + return IRQ_NONE; /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. -- GitLab From 1eaeba70738e723be1e5787bdfd9a30f7471d730 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:12 +0300 Subject: [PATCH 4232/7155] spi: spi-fsl-dspi: Remove impossible to reach error check dspi->devtype_data is under the total control of the driver. Therefore, a bad value is a driver bug and checking it at runtime (and during an ISR, at that!) is pointless. The second "else if" check is only for clarity (instead of a broader "else") in case other transfer modes are added in the future. But the printing is dead code and can be removed. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-4-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6ef2279a3699..6d2c7984ab0e 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -670,18 +670,10 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) msg->actual_length += spi_tcnt * dspi->bytes_per_word; trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: + if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: + else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } if (!dspi->len) { dspi->waitflags = 1; @@ -689,18 +681,10 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - switch (trans_mode) { - case DSPI_EOQ_MODE: + if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: + else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } return IRQ_HANDLED; } -- GitLab From c55be305915974db160ce6472722ff74f45b8d4e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 23 Aug 2019 00:15:13 +0300 Subject: [PATCH 4233/7155] spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing On platforms like LS1021A which use TCFQ mode, an interrupt needs to be processed after each byte is TXed/RXed. I tried to make the DSPI implementation on this SoC operate in other, more efficient modes (EOQ, DMA) but it looks like it simply isn't possible. Therefore allow the driver to operate in poll mode, to ease a bit of this absurd amount of IRQ load generated in TCFQ mode. Doing so reduces both the net time it takes to transmit a SPI message, as well as the inter-frame jitter that occurs while doing so. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20190822211514.19288-5-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 87 ++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6d2c7984ab0e..77db43f1290f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -647,19 +647,12 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) dspi_push_rx(dspi, fifo_read(dspi)); } -static irqreturn_t dspi_interrupt(int irq, void *dev_id) +static int dspi_rxtx(struct fsl_dspi *dspi) { - struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; struct spi_message *msg = dspi->cur_msg; enum dspi_trans_mode trans_mode; - u32 spi_sr, spi_tcr; u16 spi_tcnt; - - regmap_read(dspi->regmap, SPI_SR, &spi_sr); - regmap_write(dspi->regmap, SPI_SR, spi_sr); - - if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) - return IRQ_NONE; + u32 spi_tcr; /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. @@ -675,17 +668,55 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_read(dspi); - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - return IRQ_HANDLED; - } + if (!dspi->len) + /* Success! */ + return 0; if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); else if (trans_mode == DSPI_TCFQ_MODE) dspi_tcfq_write(dspi); + return -EINPROGRESS; +} + +static int dspi_poll(struct fsl_dspi *dspi) +{ + int tries = 1000; + u32 spi_sr; + + do { + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) + break; + } while (--tries); + + if (!tries) + return -ETIMEDOUT; + + return dspi_rxtx(dspi); +} + +static irqreturn_t dspi_interrupt(int irq, void *dev_id) +{ + struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; + u32 spi_sr; + + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) + return IRQ_NONE; + + dspi_rxtx(dspi); + + if (!dspi->len) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + } + return IRQ_HANDLED; } @@ -773,13 +804,18 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, goto out; } - if (trans_mode != DSPI_DMA_MODE) { - if (wait_event_interruptible(dspi->waitq, - dspi->waitflags)) - dev_err(&dspi->pdev->dev, - "wait transfer complete fail!\n"); + if (!dspi->irq) { + do { + status = dspi_poll(dspi); + } while (status == -EINPROGRESS); + } else if (trans_mode != DSPI_DMA_MODE) { + status = wait_event_interruptible(dspi->waitq, + dspi->waitflags); dspi->waitflags = 0; } + if (status) + dev_err(&dspi->pdev->dev, + "Waiting for transfer to complete failed!\n"); if (transfer->delay_usecs) udelay(transfer->delay_usecs); @@ -1079,10 +1115,13 @@ static int dspi_probe(struct platform_device *pdev) goto out_ctlr_put; dspi_init(dspi); + dspi->irq = platform_get_irq(pdev, 0); - if (dspi->irq < 0) { - ret = dspi->irq; - goto out_clk_put; + if (dspi->irq <= 0) { + dev_info(&pdev->dev, + "can't get platform irq, using poll mode\n"); + dspi->irq = 0; + goto poll_mode; } ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, @@ -1092,6 +1131,9 @@ static int dspi_probe(struct platform_device *pdev) goto out_clk_put; } + init_waitqueue_head(&dspi->waitq); + +poll_mode: if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); if (ret < 0) { @@ -1103,7 +1145,6 @@ static int dspi_probe(struct platform_device *pdev) ctlr->max_speed_hz = clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; - init_waitqueue_head(&dspi->waitq); platform_set_drvdata(pdev, ctlr); ret = spi_register_controller(ctlr); -- GitLab From 15ede97054889c0bec09f1f9b71beffecf06fc67 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Fri, 23 Aug 2019 11:42:28 +0200 Subject: [PATCH 4234/7155] arm64: dts: allwinner: orange-pi-3: Enable WiFi Orange Pi 3 has AP6256 WiFi/BT module. WiFi part of the module is called bcm43356 and can be used with the brcmfmac driver. The module is powered by the two always on regulators (not AXP805). WiFi uses a PG port with 1.8V voltage level signals. SoC needs to be configured so that it sets up an 1.8V input bias on this port. This is done by the pio driver by reading the vcc-pg-supply voltage. You'll need a fw_bcm43456c5_ag.bin firmware file and nvram.txt configuration that can be found in the Xulongs's repository for H6: https://github.com/orangepi-xunlong/OrangePiH6_external/tree/master/ap6256 Mainline brcmfmac driver expects the firmware and nvram at the following paths relative to the firmware directory: brcm/brcmfmac43456-sdio.bin brcm/brcmfmac43456-sdio.txt Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-h6-orangepi-3.dts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts index eda9d5f640b9..eb379cd402ac 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts @@ -56,6 +56,34 @@ regulator-max-microvolt = <5000000>; regulator-always-on; }; + + reg_vcc33_wifi: vcc33-wifi { + /* Always on 3.3V regulator for WiFi and BT */ + compatible = "regulator-fixed"; + regulator-name = "vcc33-wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <®_vcc5v>; + }; + + reg_vcc_wifi_io: vcc-wifi-io { + /* Always on 1.8V/300mA regulator for WiFi and BT IO */ + compatible = "regulator-fixed"; + regulator-name = "vcc-wifi-io"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + vin-supply = <®_vcc33_wifi>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rtc 1>; + clock-names = "ext_clock"; + reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ + post-power-on-delay-ms = <200>; + }; }; &cpu0 { @@ -91,6 +119,23 @@ status = "okay"; }; +&mmc1 { + vmmc-supply = <®_vcc33_wifi>; + vqmmc-supply = <®_vcc_wifi_io>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + brcm: sdio-wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&r_pio>; + interrupts = <1 0 IRQ_TYPE_LEVEL_LOW>; /* PM0 */ + interrupt-names = "host-wake"; + }; +}; + &ohci0 { status = "okay"; }; @@ -102,6 +147,7 @@ &pio { vcc-pc-supply = <®_bldo2>; vcc-pd-supply = <®_cldo1>; + vcc-pg-supply = <®_vcc_wifi_io>; }; &r_i2c { -- GitLab From 1a92f989126ef0743650d43f75bfc431a5c3a310 Mon Sep 17 00:00:00 2001 From: Bibby Hsieh Date: Tue, 20 Aug 2019 16:49:27 +0800 Subject: [PATCH 4235/7155] soc: mediatek: cmdq: reorder the parameter The order of gce instructions is [subsys offset value] so reorder the parameter of cmdq_pkt_write_mask and cmdq_pkt_write function. Signed-off-by: Bibby Hsieh Reviewed-by: CK Hu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 6 +++--- include/linux/soc/mediatek/mtk-cmdq.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index ff9fef5a032b..082b8978651e 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -136,7 +136,7 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, return 0; } -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset) +int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value) { u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | (subsys << CMDQ_SUBSYS_SHIFT); @@ -145,8 +145,8 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset) } EXPORT_SYMBOL(cmdq_pkt_write); -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, - u32 subsys, u32 offset, u32 mask) +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, + u32 offset, u32 value, u32 mask) { u32 offset_mask = offset; int err = 0; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 54ade13a9b15..4bba1c8d97fa 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -63,26 +63,26 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt); /** * cmdq_pkt_write() - append write command to the CMDQ packet * @pkt: the CMDQ packet - * @value: the specified target register value * @subsys: the CMDQ sub system code * @offset: register offset from CMDQ sub system + * @value: the specified target register value * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset); +int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value); /** * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet * @pkt: the CMDQ packet - * @value: the specified target register value * @subsys: the CMDQ sub system code * @offset: register offset from CMDQ sub system + * @value: the specified target register value * @mask: the specified target register mask * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, - u32 subsys, u32 offset, u32 mask); +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, + u32 offset, u32 value, u32 mask); /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet -- GitLab From 556030f0604f3cf5f1ea91307c0695541e5c74ca Mon Sep 17 00:00:00 2001 From: Bibby Hsieh Date: Tue, 20 Aug 2019 16:49:28 +0800 Subject: [PATCH 4236/7155] soc: mediatek: cmdq: change the type of input parameter According to the cmdq hardware design, the subsys is u8, the offset is u16 and the event id is u16. This patch changes the type of subsys, offset and event id to the correct type. Signed-off-by: Bibby Hsieh Reviewed-by: CK Hu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 10 +++++----- include/linux/soc/mediatek/mtk-cmdq.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 082b8978651e..7aa0517ff2f3 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -136,7 +136,7 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, return 0; } -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value) +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) { u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | (subsys << CMDQ_SUBSYS_SHIFT); @@ -145,8 +145,8 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value) } EXPORT_SYMBOL(cmdq_pkt_write); -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, - u32 offset, u32 value, u32 mask) +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, + u16 offset, u32 value, u32 mask) { u32 offset_mask = offset; int err = 0; @@ -161,7 +161,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, } EXPORT_SYMBOL(cmdq_pkt_write_mask); -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { u32 arg_b; @@ -181,7 +181,7 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) } EXPORT_SYMBOL(cmdq_pkt_wfe); -int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event) +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) { if (event >= CMDQ_MAX_EVENT) return -EINVAL; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 4bba1c8d97fa..f3ae45d02e80 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -69,7 +69,7 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt); * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value); +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); /** * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet @@ -81,8 +81,8 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 subsys, u32 offset, u32 value); * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, - u32 offset, u32 value, u32 mask); +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, + u16 offset, u32 value, u32 mask); /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet @@ -91,7 +91,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 subsys, * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event); /** * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet @@ -100,7 +100,7 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event); +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); /** * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ -- GitLab From 3bbda1431b43f65736fa8aa7ccfa8a5d5c98b2b8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 18 Nov 2018 18:30:56 +0100 Subject: [PATCH 4237/7155] dt-bindings: can: rcar_can: document r8a77990 support Document the support for rcar_can on R8A77990 SoC devices. Add R8A77990 to the list of SoCs which require the "assigned-clocks" and "assigned-clock-rates" properties. Signed-off-by: Marek Vasut Cc: Marc Kleine-Budde Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_can.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index e1f315ab2353..93ac849f42b0 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -17,6 +17,7 @@ Required properties: "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC. "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC. "renesas,can-r8a77965" if CAN controller is a part of R8A77965 SoC. + "renesas,can-r8a77990" if CAN controller is a part of R8A77990 SoC. "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1 compatible device. @@ -33,7 +34,8 @@ Required properties: - pinctrl-0: pin control group to be used for this controller. - pinctrl-names: must be "default". -Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796 and R8A77965: +Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, +and R8A77990: For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can be used by both CAN and CAN FD controller at the same time. It needs to be scaled to maximum frequency if any of these controllers use it. This is done -- GitLab From 81633d7509b3bfeae81a0ee3116739812b685177 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 5 Dec 2018 09:17:04 +0800 Subject: [PATCH 4238/7155] dt-bindings: can: rcar_can: document r8a77995 support Adds compatible strings for the R-Car CAN controller in the D3 SoC. Signed-off-by: Ulrich Hecht Acked-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_can.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index 93ac849f42b0..1f9db8baea7d 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -18,6 +18,7 @@ Required properties: "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC. "renesas,can-r8a77965" if CAN controller is a part of R8A77965 SoC. "renesas,can-r8a77990" if CAN controller is a part of R8A77990 SoC. + "renesas,can-r8a77995" if CAN controller is a part of R8A77995 SoC. "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1 compatible device. @@ -35,7 +36,7 @@ Required properties: - pinctrl-names: must be "default". Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, -and R8A77990: +R8A77990, and R8A77995: For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can be used by both CAN and CAN FD controller at the same time. It needs to be scaled to maximum frequency if any of these controllers use it. This is done -- GitLab From 80bd043dc1ff179deb7007da92abb8d1ae01919c Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 5 Dec 2018 09:17:05 +0800 Subject: [PATCH 4239/7155] dt-bindings: can: rcar_canfd: document r8a77995 support Adds compatible strings for the R-Car CAN FD controller in the D3 SoC. Signed-off-by: Ulrich Hecht Acked-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/net/can/rcar_canfd.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt index 00afaffb9614..a901cd9be29e 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt @@ -12,6 +12,7 @@ Required properties: - "renesas,r8a77970-canfd" for R8A77970 (R-Car V3M) compatible controller. - "renesas,r8a77980-canfd" for R8A77980 (R-Car V3H) compatible controller. - "renesas,r8a77990-canfd" for R8A77990 (R-Car E3) compatible controller. + - "renesas,r8a77995-canfd" for R8A77995 (R-Car D3) compatible controller. When compatible with the generic version, nodes must list the SoC-specific version corresponding to the platform first, followed by the @@ -30,13 +31,12 @@ The name of the child nodes are "channel0" and "channel1" respectively. Each child node supports the "status" property only, which is used to enable/disable the respective channel. -Required properties for "renesas,r8a774c0-canfd", "renesas,r8a7795-canfd", -"renesas,r8a7796-canfd", "renesas,r8a77965-canfd", and "renesas,r8a77990-canfd" -compatible: -In R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, and R8A77990 SoCs, canfd -clock is a div6 clock and can be used by both CAN and CAN FD controller at the -same time. It needs to be scaled to maximum frequency if any of these -controllers use it. This is done using the below properties: +Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, +R8A77990, and R8A77995: +In the denoted SoCs, canfd clock is a div6 clock and can be used by both CAN +and CAN FD controller at the same time. It needs to be scaled to maximum +frequency if any of these controllers use it. This is done using the below +properties: - assigned-clocks: phandle of canfd clock. - assigned-clock-rates: maximum frequency of this clock. -- GitLab From 7ac2d56f783d6d546e89a4e44fb46532667aa7a5 Mon Sep 17 00:00:00 2001 From: Cao Van Dong Date: Thu, 11 Apr 2019 16:54:22 +0900 Subject: [PATCH 4240/7155] dt-bindings: can: rcar_can: document r8a77470 support Document SoC specific bindings for R-Car RZ/G1C(r8a77470) SoC. Signed-off-by: Cao Van Dong Reviewed-by: Rob Herring Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_can.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index 1f9db8baea7d..19e4a7d91511 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -5,6 +5,7 @@ Required properties: - compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC. "renesas,can-r8a7744" if CAN controller is a part of R8A7744 SoC. "renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC. + "renesas,can-r8a77470" if CAN controller is a part of R8A77470 SoC. "renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC. "renesas,can-r8a774c0" if CAN controller is a part of R8A774C0 SoC. "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC. -- GitLab From d4b186ed227b80334abf1fe2c918c0ddc4374f38 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:14 -0700 Subject: [PATCH 4241/7155] null_blk: move duplicate code to callers This is a preparation patch which moves the duplicate code for sectors and nr_sectors calculations for bio vs request mode into their respective callers (null_queue_bio(), null_qeueue_req()). Now the core function only deals with the respective actions and commands instead of having to calculte the bio vs req operations and different sector related variables. We also move the flush command handling at the top which significantly simplifies the rest of the code. Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 66 +++++++++++------------------------ 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 99c56d72ff78..7277f2db8ec9 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1133,7 +1133,8 @@ static void null_restart_queue_async(struct nullb *nullb) blk_mq_start_stopped_hw_queues(q, true); } -static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) +static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, + sector_t nr_sectors, enum req_opf op) { struct nullb_device *dev = cmd->nq->dev; struct nullb *nullb = dev->nullb; @@ -1156,60 +1157,31 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) } } + if (op == REQ_OP_FLUSH) { + cmd->error = errno_to_blk_status(null_handle_flush(nullb)); + goto out; + } if (nullb->dev->badblocks.shift != -1) { int bad_sectors; - sector_t sector, size, first_bad; - bool is_flush = true; - - if (dev->queue_mode == NULL_Q_BIO && - bio_op(cmd->bio) != REQ_OP_FLUSH) { - is_flush = false; - sector = cmd->bio->bi_iter.bi_sector; - size = bio_sectors(cmd->bio); - } - if (dev->queue_mode != NULL_Q_BIO && - req_op(cmd->rq) != REQ_OP_FLUSH) { - is_flush = false; - sector = blk_rq_pos(cmd->rq); - size = blk_rq_sectors(cmd->rq); - } - if (!is_flush && badblocks_check(&nullb->dev->badblocks, sector, - size, &first_bad, &bad_sectors)) { + sector_t first_bad; + + if (badblocks_check(&nullb->dev->badblocks, sector, nr_sectors, + &first_bad, &bad_sectors)) { cmd->error = BLK_STS_IOERR; goto out; } } if (dev->memory_backed) { - if (dev->queue_mode == NULL_Q_BIO) { - if (bio_op(cmd->bio) == REQ_OP_FLUSH) - err = null_handle_flush(nullb); - else - err = null_handle_bio(cmd); - } else { - if (req_op(cmd->rq) == REQ_OP_FLUSH) - err = null_handle_flush(nullb); - else - err = null_handle_rq(cmd); - } + if (dev->queue_mode == NULL_Q_BIO) + err = null_handle_bio(cmd); + else + err = null_handle_rq(cmd); } + cmd->error = errno_to_blk_status(err); if (!cmd->error && dev->zoned) { - sector_t sector; - unsigned int nr_sectors; - enum req_opf op; - - if (dev->queue_mode == NULL_Q_BIO) { - op = bio_op(cmd->bio); - sector = cmd->bio->bi_iter.bi_sector; - nr_sectors = cmd->bio->bi_iter.bi_size >> 9; - } else { - op = req_op(cmd->rq); - sector = blk_rq_pos(cmd->rq); - nr_sectors = blk_rq_sectors(cmd->rq); - } - if (op == REQ_OP_WRITE) null_zone_write(cmd, sector, nr_sectors); else if (op == REQ_OP_ZONE_RESET) @@ -1282,6 +1254,8 @@ static struct nullb_queue *nullb_to_queue(struct nullb *nullb) static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio) { + sector_t sector = bio->bi_iter.bi_sector; + sector_t nr_sectors = bio_sectors(bio); struct nullb *nullb = q->queuedata; struct nullb_queue *nq = nullb_to_queue(nullb); struct nullb_cmd *cmd; @@ -1289,7 +1263,7 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio) cmd = alloc_cmd(nq, 1); cmd->bio = bio; - null_handle_cmd(cmd); + null_handle_cmd(cmd, sector, nr_sectors, bio_op(bio)); return BLK_QC_T_NONE; } @@ -1323,6 +1297,8 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, { struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq); struct nullb_queue *nq = hctx->driver_data; + sector_t nr_sectors = blk_rq_sectors(bd->rq); + sector_t sector = blk_rq_pos(bd->rq); might_sleep_if(hctx->flags & BLK_MQ_F_BLOCKING); @@ -1351,7 +1327,7 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, if (should_timeout_request(bd->rq)) return BLK_STS_OK; - return null_handle_cmd(cmd); + return null_handle_cmd(cmd, sector, nr_sectors, req_op(bd->rq)); } static const struct blk_mq_ops null_mq_ops = { -- GitLab From adb84284796be4989dc3b48c7eef2784af45431d Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:15 -0700 Subject: [PATCH 4242/7155] null_blk: create a helper for throttling This patch creates a helper for handling throttling code in the null_handle_cmd(). Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 39 ++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 7277f2db8ec9..751679fadc9d 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1133,28 +1133,39 @@ static void null_restart_queue_async(struct nullb *nullb) blk_mq_start_stopped_hw_queues(q, true); } +static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd) +{ + struct nullb_device *dev = cmd->nq->dev; + struct nullb *nullb = dev->nullb; + blk_status_t sts = BLK_STS_OK; + struct request *rq = cmd->rq; + + if (!hrtimer_active(&nullb->bw_timer)) + hrtimer_restart(&nullb->bw_timer); + + if (atomic_long_sub_return(blk_rq_bytes(rq), &nullb->cur_bytes) < 0) { + null_stop_queue(nullb); + /* race with timer */ + if (atomic_long_read(&nullb->cur_bytes) > 0) + null_restart_queue_async(nullb); + /* requeue request */ + sts = BLK_STS_DEV_RESOURCE; + } + return sts; +} + static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, sector_t nr_sectors, enum req_opf op) { struct nullb_device *dev = cmd->nq->dev; struct nullb *nullb = dev->nullb; + blk_status_t sts; int err = 0; if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) { - struct request *rq = cmd->rq; - - if (!hrtimer_active(&nullb->bw_timer)) - hrtimer_restart(&nullb->bw_timer); - - if (atomic_long_sub_return(blk_rq_bytes(rq), - &nullb->cur_bytes) < 0) { - null_stop_queue(nullb); - /* race with timer */ - if (atomic_long_read(&nullb->cur_bytes) > 0) - null_restart_queue_async(nullb); - /* requeue request */ - return BLK_STS_DEV_RESOURCE; - } + sts = null_handle_throttled(cmd); + if (sts != BLK_STS_OK) + return sts; } if (op == REQ_OP_FLUSH) { -- GitLab From 8f94d1c1dc1e1094ef83fcadf1b992cf8ff7869e Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:16 -0700 Subject: [PATCH 4243/7155] null_blk: create a helper for badblocks This patch creates a helper for handling badblocks code in the null_handle_cmd(). Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 751679fadc9d..eefaea1aaa45 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1154,6 +1154,20 @@ static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd) return sts; } +static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, + sector_t sector, + sector_t nr_sectors) +{ + struct badblocks *bb = &cmd->nq->dev->badblocks; + sector_t first_bad; + int bad_sectors; + + if (badblocks_check(bb, sector, nr_sectors, &first_bad, &bad_sectors)) + return BLK_STS_IOERR; + + return BLK_STS_OK; +} + static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, sector_t nr_sectors, enum req_opf op) { @@ -1172,15 +1186,11 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, cmd->error = errno_to_blk_status(null_handle_flush(nullb)); goto out; } - if (nullb->dev->badblocks.shift != -1) { - int bad_sectors; - sector_t first_bad; - if (badblocks_check(&nullb->dev->badblocks, sector, nr_sectors, - &first_bad, &bad_sectors)) { - cmd->error = BLK_STS_IOERR; + if (nullb->dev->badblocks.shift != -1) { + cmd->error = null_handle_badblocks(cmd, sector, nr_sectors); + if (cmd->error != BLK_STS_OK) goto out; - } } if (dev->memory_backed) { -- GitLab From 7ea88e229e9df18ecd624b0d39f3dba87432ba33 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:17 -0700 Subject: [PATCH 4244/7155] null_blk: create a helper for mem-backed ops This patch creates a helper for handling requests when null_blk is memory backed in the null_handle_cmd(). Although the helper is very simple right now, it makes the code flow consistent with the rest of code in the null_handle_cmd() and provides a uniform code structure for future code. Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index eefaea1aaa45..4299274cccfb 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1168,13 +1168,26 @@ static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, return BLK_STS_OK; } +static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, + enum req_opf op) +{ + struct nullb_device *dev = cmd->nq->dev; + int err; + + if (dev->queue_mode == NULL_Q_BIO) + err = null_handle_bio(cmd); + else + err = null_handle_rq(cmd); + + return errno_to_blk_status(err); +} + static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, sector_t nr_sectors, enum req_opf op) { struct nullb_device *dev = cmd->nq->dev; struct nullb *nullb = dev->nullb; blk_status_t sts; - int err = 0; if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) { sts = null_handle_throttled(cmd); @@ -1193,14 +1206,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, goto out; } - if (dev->memory_backed) { - if (dev->queue_mode == NULL_Q_BIO) - err = null_handle_bio(cmd); - else - err = null_handle_rq(cmd); - } - - cmd->error = errno_to_blk_status(err); + if (dev->memory_backed) + cmd->error = null_handle_memory_backed(cmd, op); if (!cmd->error && dev->zoned) { if (op == REQ_OP_WRITE) -- GitLab From fceb5d1b19cbe6263f09dbe8e8138edf02eb6e6b Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:18 -0700 Subject: [PATCH 4245/7155] null_blk: create a helper for zoned devices This patch creates a helper function for handling zoned block device operations. This patch also restructured the code for null_blk_zoned.c and uses the pattern to return blk_status_t and catch the error in the function null_handle_cmd() into cmd->error variable instead of setting it up in the deeper layer just like the way it is done for flush, badblocks and memory backed case in the null_handle_cmd(). We also move null_handle_zoned() to the null_blk_zoned.c to keep the zoned code separate. Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk.h | 13 ++++++------ drivers/block/null_blk_main.c | 11 +++------- drivers/block/null_blk_zoned.c | 38 ++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index a1b9929bd911..4895c02e0c65 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -90,9 +90,9 @@ int null_zone_init(struct nullb_device *dev); void null_zone_exit(struct nullb_device *dev); int null_zone_report(struct gendisk *disk, sector_t sector, struct blk_zone *zones, unsigned int *nr_zones); -void null_zone_write(struct nullb_cmd *cmd, sector_t sector, - unsigned int nr_sectors); -void null_zone_reset(struct nullb_cmd *cmd, sector_t sector); +inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, + enum req_opf op, sector_t sector, + sector_t nr_sectors); #else static inline int null_zone_init(struct nullb_device *dev) { @@ -106,10 +106,11 @@ static inline int null_zone_report(struct gendisk *disk, sector_t sector, { return -EOPNOTSUPP; } -static inline void null_zone_write(struct nullb_cmd *cmd, sector_t sector, - unsigned int nr_sectors) +static inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, + enum req_opf op, sector_t sector, + sector_t nr_sectors) { + return BLK_STS_NOTSUPP; } -static inline void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) {} #endif /* CONFIG_BLK_DEV_ZONED */ #endif /* __NULL_BLK_H */ diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 4299274cccfb..bf40c3115bb9 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1209,14 +1209,9 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, if (dev->memory_backed) cmd->error = null_handle_memory_backed(cmd, op); - if (!cmd->error && dev->zoned) { - if (op == REQ_OP_WRITE) - null_zone_write(cmd, sector, nr_sectors); - else if (op == REQ_OP_ZONE_RESET) - null_zone_reset(cmd, sector); - else if (op == REQ_OP_ZONE_RESET_ALL) - null_zone_reset(cmd, 0); - } + if (!cmd->error && dev->zoned) + cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors); + out: /* Complete IO by inline, softirq or timer */ switch (dev->irqmode) { diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index 8c7f5bf81975..90092247e7eb 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -84,7 +84,7 @@ int null_zone_report(struct gendisk *disk, sector_t sector, return 0; } -void null_zone_write(struct nullb_cmd *cmd, sector_t sector, +static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector, unsigned int nr_sectors) { struct nullb_device *dev = cmd->nq->dev; @@ -95,14 +95,12 @@ void null_zone_write(struct nullb_cmd *cmd, sector_t sector, case BLK_ZONE_COND_FULL: /* Cannot write to a full zone */ cmd->error = BLK_STS_IOERR; - break; + return BLK_STS_IOERR; case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_IMP_OPEN: /* Writes must be at the write pointer position */ - if (sector != zone->wp) { - cmd->error = BLK_STS_IOERR; - break; - } + if (sector != zone->wp) + return BLK_STS_IOERR; if (zone->cond == BLK_ZONE_COND_EMPTY) zone->cond = BLK_ZONE_COND_IMP_OPEN; @@ -115,12 +113,12 @@ void null_zone_write(struct nullb_cmd *cmd, sector_t sector, break; default: /* Invalid zone condition */ - cmd->error = BLK_STS_IOERR; - break; + return BLK_STS_IOERR; } + return BLK_STS_OK; } -void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) +static blk_status_t null_zone_reset(struct nullb_cmd *cmd, sector_t sector) { struct nullb_device *dev = cmd->nq->dev; unsigned int zno = null_zone_no(dev, sector); @@ -137,10 +135,8 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) } break; case REQ_OP_ZONE_RESET: - if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) { - cmd->error = BLK_STS_IOERR; - return; - } + if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) + return BLK_STS_IOERR; zone->cond = BLK_ZONE_COND_EMPTY; zone->wp = zone->start; @@ -149,4 +145,20 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) cmd->error = BLK_STS_NOTSUPP; break; } + return BLK_STS_OK; +} + +inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, + enum req_opf op, sector_t sector, + sector_t nr_sectors) +{ + switch (op) { + case REQ_OP_WRITE: + return null_zone_write(cmd, sector, nr_sectors); + case REQ_OP_ZONE_RESET: + case REQ_OP_ZONE_RESET_ALL: + return null_zone_reset(cmd, sector); + default: + return BLK_STS_OK; + } } -- GitLab From a3d7d67403fcff366dafe8a7c04b15deec3d9022 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Thu, 22 Aug 2019 21:45:19 -0700 Subject: [PATCH 4246/7155] null_blk: create a helper for req completion This patch creates a helper function for handling the request completion in the null_handle_cmd(). Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 49 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index bf40c3115bb9..b26a178d064d 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1182,6 +1182,32 @@ static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, return errno_to_blk_status(err); } +static inline void nullb_complete_cmd(struct nullb_cmd *cmd) +{ + /* Complete IO by inline, softirq or timer */ + switch (cmd->nq->dev->irqmode) { + case NULL_IRQ_SOFTIRQ: + switch (cmd->nq->dev->queue_mode) { + case NULL_Q_MQ: + blk_mq_complete_request(cmd->rq); + break; + case NULL_Q_BIO: + /* + * XXX: no proper submitting cpu information available. + */ + end_cmd(cmd); + break; + } + break; + case NULL_IRQ_NONE: + end_cmd(cmd); + break; + case NULL_IRQ_TIMER: + null_cmd_end_timer(cmd); + break; + } +} + static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, sector_t nr_sectors, enum req_opf op) { @@ -1213,28 +1239,7 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors); out: - /* Complete IO by inline, softirq or timer */ - switch (dev->irqmode) { - case NULL_IRQ_SOFTIRQ: - switch (dev->queue_mode) { - case NULL_Q_MQ: - blk_mq_complete_request(cmd->rq); - break; - case NULL_Q_BIO: - /* - * XXX: no proper submitting cpu information available. - */ - end_cmd(cmd); - break; - } - break; - case NULL_IRQ_NONE: - end_cmd(cmd); - break; - case NULL_IRQ_TIMER: - null_cmd_end_timer(cmd); - break; - } + nullb_complete_cmd(cmd); return BLK_STS_OK; } -- GitLab From 12ce6b0d21c2038ddae9da418aab198e284ad922 Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Fri, 23 Aug 2019 12:49:11 +0200 Subject: [PATCH 4247/7155] ata/pata_buddha: Probe via modalias instead of initcall Up until now, the pata_buddha driver would only check for cards on initcall time. Now, the kernel will call its probe function as soon as a compatible card is detected. v7: Removed suppress_bind_attrs that slipped in v6: Only do the drvdata workaround for X-Surf (remove breaks otherwise) Style v5: Remove module_exit(): There's no good way to handle the X-Surf hack. Also include a workaround to save X-Surf's drvdata in case zorro8390 is active. v4: Clean up pata_buddha_probe() by using ent->driver_data. Support X-Surf via late_initcall() v3: Clean up devm_*, implement device removal. v2: Rename 'zdev' to 'z' to make the patch easy to analyse with git diff --ignore-space-change Signed-off-by: Max Staudt Signed-off-by: Jens Axboe --- drivers/ata/pata_buddha.c | 228 ++++++++++++++++++++++---------------- 1 file changed, 135 insertions(+), 93 deletions(-) diff --git a/drivers/ata/pata_buddha.c b/drivers/ata/pata_buddha.c index 11a8044ff633..27d4c417fc60 100644 --- a/drivers/ata/pata_buddha.c +++ b/drivers/ata/pata_buddha.c @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -29,7 +31,7 @@ #include #define DRV_NAME "pata_buddha" -#define DRV_VERSION "0.1.0" +#define DRV_VERSION "0.1.1" #define BUDDHA_BASE1 0x800 #define BUDDHA_BASE2 0xa00 @@ -47,11 +49,11 @@ enum { BOARD_XSURF }; -static unsigned int buddha_bases[3] __initdata = { +static unsigned int buddha_bases[3] = { BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 }; -static unsigned int xsurf_bases[2] __initdata = { +static unsigned int xsurf_bases[2] = { XSURF_BASE1, XSURF_BASE2 }; @@ -145,111 +147,151 @@ static struct ata_port_operations pata_xsurf_ops = { .set_mode = pata_buddha_set_mode, }; -static int __init pata_buddha_init_one(void) +static int pata_buddha_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) { - struct zorro_dev *z = NULL; + static const char * const board_name[] = { + "Buddha", "Catweasel", "X-Surf" + }; + struct ata_host *host; + void __iomem *buddha_board; + unsigned long board; + unsigned int type = ent->driver_data; + unsigned int nr_ports = (type == BOARD_CATWEASEL) ? 3 : 2; + void *old_drvdata; + int i; + + dev_info(&z->dev, "%s IDE controller\n", board_name[type]); + + board = z->resource.start; + + if (type != BOARD_XSURF) { + if (!devm_request_mem_region(&z->dev, + board + BUDDHA_BASE1, + 0x800, DRV_NAME)) + return -ENXIO; + } else { + if (!devm_request_mem_region(&z->dev, + board + XSURF_BASE1, + 0x1000, DRV_NAME)) + return -ENXIO; + if (!devm_request_mem_region(&z->dev, + board + XSURF_BASE2, + 0x1000, DRV_NAME)) { + } + } + + /* Workaround for X-Surf: Save drvdata in case zorro8390 has set it */ + if (type == BOARD_XSURF) + old_drvdata = dev_get_drvdata(&z->dev); + + /* allocate host */ + host = ata_host_alloc(&z->dev, nr_ports); + if (type == BOARD_XSURF) + dev_set_drvdata(&z->dev, old_drvdata); + if (!host) + return -ENXIO; + + buddha_board = ZTWO_VADDR(board); + + /* enable the board IRQ on Buddha/Catweasel */ + if (type != BOARD_XSURF) + z_writeb(0, buddha_board + BUDDHA_IRQ_MR); - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - static const char *board_name[] - = { "Buddha", "Catweasel", "X-Surf" }; - struct ata_host *host; - void __iomem *buddha_board; - unsigned long board; - unsigned int type, nr_ports = 2; - int i; - - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - type = BOARD_BUDDHA; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { - type = BOARD_CATWEASEL; - nr_ports++; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { - type = BOARD_XSURF; - } else - continue; - - dev_info(&z->dev, "%s IDE controller\n", board_name[type]); - - board = z->resource.start; + for (i = 0; i < nr_ports; i++) { + struct ata_port *ap = host->ports[i]; + void __iomem *base, *irqport; + unsigned long ctl = 0; if (type != BOARD_XSURF) { - if (!devm_request_mem_region(&z->dev, - board + BUDDHA_BASE1, - 0x800, DRV_NAME)) - continue; + ap->ops = &pata_buddha_ops; + base = buddha_board + buddha_bases[i]; + ctl = BUDDHA_CONTROL; + irqport = buddha_board + BUDDHA_IRQ + i * 0x40; } else { - if (!devm_request_mem_region(&z->dev, - board + XSURF_BASE1, - 0x1000, DRV_NAME)) - continue; - if (!devm_request_mem_region(&z->dev, - board + XSURF_BASE2, - 0x1000, DRV_NAME)) - continue; + ap->ops = &pata_xsurf_ops; + base = buddha_board + xsurf_bases[i]; + /* X-Surf has no CS1* (Control/AltStat) */ + irqport = buddha_board + XSURF_IRQ; } - /* allocate host */ - host = ata_host_alloc(&z->dev, nr_ports); - if (!host) - continue; - - buddha_board = ZTWO_VADDR(board); - - /* enable the board IRQ on Buddha/Catweasel */ - if (type != BOARD_XSURF) - z_writeb(0, buddha_board + BUDDHA_IRQ_MR); - - for (i = 0; i < nr_ports; i++) { - struct ata_port *ap = host->ports[i]; - void __iomem *base, *irqport; - unsigned long ctl = 0; - - if (type != BOARD_XSURF) { - ap->ops = &pata_buddha_ops; - base = buddha_board + buddha_bases[i]; - ctl = BUDDHA_CONTROL; - irqport = buddha_board + BUDDHA_IRQ + i * 0x40; - } else { - ap->ops = &pata_xsurf_ops; - base = buddha_board + xsurf_bases[i]; - /* X-Surf has no CS1* (Control/AltStat) */ - irqport = buddha_board + XSURF_IRQ; - } - - ap->pio_mask = ATA_PIO4; - ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; - - ap->ioaddr.data_addr = base; - ap->ioaddr.error_addr = base + 2 + 1 * 4; - ap->ioaddr.feature_addr = base + 2 + 1 * 4; - ap->ioaddr.nsect_addr = base + 2 + 2 * 4; - ap->ioaddr.lbal_addr = base + 2 + 3 * 4; - ap->ioaddr.lbam_addr = base + 2 + 4 * 4; - ap->ioaddr.lbah_addr = base + 2 + 5 * 4; - ap->ioaddr.device_addr = base + 2 + 6 * 4; - ap->ioaddr.status_addr = base + 2 + 7 * 4; - ap->ioaddr.command_addr = base + 2 + 7 * 4; - - if (ctl) { - ap->ioaddr.altstatus_addr = base + ctl; - ap->ioaddr.ctl_addr = base + ctl; - } - - ap->private_data = (void *)irqport; - - ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", board, - ctl ? board + buddha_bases[i] + ctl : 0); + ap->pio_mask = ATA_PIO4; + ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; + + ap->ioaddr.data_addr = base; + ap->ioaddr.error_addr = base + 2 + 1 * 4; + ap->ioaddr.feature_addr = base + 2 + 1 * 4; + ap->ioaddr.nsect_addr = base + 2 + 2 * 4; + ap->ioaddr.lbal_addr = base + 2 + 3 * 4; + ap->ioaddr.lbam_addr = base + 2 + 4 * 4; + ap->ioaddr.lbah_addr = base + 2 + 5 * 4; + ap->ioaddr.device_addr = base + 2 + 6 * 4; + ap->ioaddr.status_addr = base + 2 + 7 * 4; + ap->ioaddr.command_addr = base + 2 + 7 * 4; + + if (ctl) { + ap->ioaddr.altstatus_addr = base + ctl; + ap->ioaddr.ctl_addr = base + ctl; } - ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt, - IRQF_SHARED, &pata_buddha_sht); + ap->private_data = (void *)irqport; + ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", board, + ctl ? board + buddha_bases[i] + ctl : 0); } + ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt, + IRQF_SHARED, &pata_buddha_sht); + return 0; } -module_init(pata_buddha_init_one); +static void pata_buddha_remove(struct zorro_dev *z) +{ + struct ata_host *host = dev_get_drvdata(&z->dev); + + ata_host_detach(host); +} + +static const struct zorro_device_id pata_buddha_zorro_tbl[] = { + { ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, BOARD_BUDDHA}, + { ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, BOARD_CATWEASEL}, + { 0 } +}; +MODULE_DEVICE_TABLE(zorro, pata_buddha_zorro_tbl); + +static struct zorro_driver pata_buddha_driver = { + .name = "pata_buddha", + .id_table = pata_buddha_zorro_tbl, + .probe = pata_buddha_probe, + .remove = pata_buddha_remove, +}; + +/* + * We cannot have a modalias for X-Surf boards, as it competes with the + * zorro8390 network driver. As a stopgap measure until we have proper + * MFD support for this board, we manually attach to it late after Zorro + * has enumerated its boards. + */ +static int __init pata_buddha_late_init(void) +{ + struct zorro_dev *z = NULL; + + /* Auto-bind to regular boards */ + zorro_register_driver(&pata_buddha_driver); + + /* Manually bind to all X-Surf boards */ + while ((z = zorro_find_device(ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, z))) { + static struct zorro_device_id xsurf_ent = { + ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, BOARD_XSURF + }; + + pata_buddha_probe(z, &xsurf_ent); + } + + return 0; +} +late_initcall(pata_buddha_late_init); MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); MODULE_DESCRIPTION("low-level driver for Buddha/Catweasel/X-Surf PATA"); -- GitLab From 81f5090db843be897414418c24fe472fa6e082b6 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Thu, 22 Aug 2019 00:00:02 +0000 Subject: [PATCH 4248/7155] EDAC/amd64: Support asymmetric dual-rank DIMMs Future AMD systems will support asymmetric dual-rank DIMMs. These are DIMMs where the ranks are of different sizes. The even rank will use the Primary Even Chip Select registers and the odd rank will use the Secondary Odd Chip Select registers. Recognize if a Secondary Odd Chip Select is being used. Use the Secondary Odd Address Mask when calculating the chip select size. [ bp: move csrow_sec_enabled() to the header, fix CS_ODD define and tone-down the capitalized words spelling. ] Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov Cc: "linux-edac@vger.kernel.org" Cc: James Morse Cc: Mauro Carvalho Chehab Cc: Tony Luck Link: https://lkml.kernel.org/r/20190821235938.118710-8-Yazen.Ghannam@amd.com --- drivers/edac/amd64_edac.c | 16 +++++++++++++--- drivers/edac/amd64_edac.h | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 23251bba8eb6..18ba9c898389 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -790,9 +790,11 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) #define CS_EVEN_PRIMARY BIT(0) #define CS_ODD_PRIMARY BIT(1) +#define CS_EVEN_SECONDARY BIT(2) +#define CS_ODD_SECONDARY BIT(3) -#define CS_EVEN CS_EVEN_PRIMARY -#define CS_ODD CS_ODD_PRIMARY +#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY) +#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY) static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) { @@ -804,6 +806,10 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) if (csrow_enabled(2 * dimm + 1, ctrl, pvt)) cs_mode |= CS_ODD_PRIMARY; + /* Asymmetric dual-rank DIMM support. */ + if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt)) + cs_mode |= CS_ODD_SECONDARY; + return cs_mode; } @@ -1600,7 +1606,11 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, */ dimm = csrow_nr >> 1; - addr_mask_orig = pvt->csels[umc].csmasks[dimm]; + /* Asymmetric dual-rank DIMM support. */ + if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY)) + addr_mask_orig = pvt->csels[umc].csmasks_sec[dimm]; + else + addr_mask_orig = pvt->csels[umc].csmasks[dimm]; /* * The number of zero bits in the mask is equal to the number of bits diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 68f12de6e654..8addc4d95577 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -169,7 +169,8 @@ #define DCSM0 0x60 #define DCSM1 0x160 -#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE) +#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE) +#define csrow_sec_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases_sec[(i)] & DCSB_CS_ENABLE) #define DRAM_CONTROL 0x78 -- GitLab From adb87ff4f96c9700718e09c97a804124d5cd61ff Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Wed, 14 Aug 2019 20:32:15 +0800 Subject: [PATCH 4249/7155] clocksource/drivers/hyperv: Allocate Hyper-V TSC page statically Prepare to add Hyper-V sched clock callback and move Hyper-V Reference TSC initialization much earlier in the boot process. Earlier initialization is needed so that it happens while the timestamp value is still 0 and no discontinuity in the timestamp will occur when pv_ops.time.sched_clock calculates its offset. The earlier initialization requires that the Hyper-V TSC page be allocated statically instead of with vmalloc(), so fixup the references to the TSC page and the method of getting its physical address. Signed-off-by: Tianyu Lan Signed-off-by: Thomas Gleixner Acked-by: Daniel Lezcano Link: https://lkml.kernel.org/r/20190814123216.32245-2-Tianyu.Lan@microsoft.com --- arch/x86/entry/vdso/vma.c | 2 +- drivers/clocksource/hyperv_timer.c | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 349a61d8bf34..f5937742b290 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -122,7 +122,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, if (tsc_pg && vclock_was_used(VCLOCK_HVCLOCK)) return vmf_insert_pfn(vma, vmf->address, - vmalloc_to_pfn(tsc_pg)); + virt_to_phys(tsc_pg) >> PAGE_SHIFT); } return VM_FAULT_SIGBUS; diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index ba2c79e6a0ee..432aa331df04 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -214,17 +214,17 @@ EXPORT_SYMBOL_GPL(hyperv_cs); #ifdef CONFIG_HYPERV_TSCPAGE -static struct ms_hyperv_tsc_page *tsc_pg; +static struct ms_hyperv_tsc_page tsc_pg __aligned(PAGE_SIZE); struct ms_hyperv_tsc_page *hv_get_tsc_page(void) { - return tsc_pg; + return &tsc_pg; } EXPORT_SYMBOL_GPL(hv_get_tsc_page); static u64 notrace read_hv_sched_clock_tsc(void) { - u64 current_tick = hv_read_tsc_page(tsc_pg); + u64 current_tick = hv_read_tsc_page(&tsc_pg); if (current_tick == U64_MAX) hv_get_time_ref_count(current_tick); @@ -280,12 +280,8 @@ static bool __init hv_init_tsc_clocksource(void) if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) return false; - tsc_pg = vmalloc(PAGE_SIZE); - if (!tsc_pg) - return false; - hyperv_cs = &hyperv_cs_tsc; - phys_addr = page_to_phys(vmalloc_to_page(tsc_pg)); + phys_addr = virt_to_phys(&tsc_pg); /* * The Hyper-V TLFS specifies to preserve the value of reserved -- GitLab From bd00cd52d5be655a2f217e2ed74b91a71cb2b14f Mon Sep 17 00:00:00 2001 From: Tianyu Lan Date: Wed, 14 Aug 2019 20:32:16 +0800 Subject: [PATCH 4250/7155] clocksource/drivers/hyperv: Add Hyper-V specific sched clock function Hyper-V guests use the default native_sched_clock() in pv_ops.time.sched_clock on x86. But native_sched_clock() directly uses the raw TSC value, which can be discontinuous in a Hyper-V VM. Add the generic hv_setup_sched_clock() to set the sched clock function appropriately. On x86, this sets pv_ops.time.sched_clock to read the Hyper-V reference TSC value that is scaled and adjusted to be continuous. Also move the Hyper-V reference TSC initialization much earlier in the boot process so no discontinuity is observed when pv_ops.time.sched_clock calculates its offset. [ tglx: Folded build fix ] Signed-off-by: Tianyu Lan Signed-off-by: Thomas Gleixner Reviewed-by: Michael Kelley Link: https://lkml.kernel.org/r/20190814123216.32245-3-Tianyu.Lan@microsoft.com --- arch/x86/hyperv/hv_init.c | 2 -- arch/x86/kernel/cpu/mshyperv.c | 8 ++++++++ drivers/clocksource/hyperv_timer.c | 22 ++++++++++++---------- include/asm-generic/mshyperv.h | 1 + 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 0d258688c8cf..866dfb3dca48 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -301,8 +301,6 @@ void __init hyperv_init(void) x86_init.pci.arch_init = hv_pci_init; - /* Register Hyper-V specific clocksource */ - hv_init_clocksource(); return; remove_cpuhp_state: diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 062f77279ce3..53afd33990eb 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -29,6 +29,7 @@ #include #include #include +#include struct ms_hyperv_info ms_hyperv; EXPORT_SYMBOL_GPL(ms_hyperv); @@ -338,9 +339,16 @@ static void __init ms_hyperv_init_platform(void) x2apic_phys = 1; # endif + /* Register Hyper-V specific clocksource */ + hv_init_clocksource(); #endif } +void hv_setup_sched_clock(void *sched_clock) +{ + pv_ops.time.sched_clock = sched_clock; +} + const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = { .name = "Microsoft Hyper-V", .detect = ms_hyperv_platform, diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index 432aa331df04..c322ab4d3689 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -22,6 +22,7 @@ #include static struct clock_event_device __percpu *hv_clock_event; +static u64 hv_sched_clock_offset __ro_after_init; /* * If false, we're using the old mechanism for stimer0 interrupts @@ -222,7 +223,7 @@ struct ms_hyperv_tsc_page *hv_get_tsc_page(void) } EXPORT_SYMBOL_GPL(hv_get_tsc_page); -static u64 notrace read_hv_sched_clock_tsc(void) +static u64 notrace read_hv_clock_tsc(struct clocksource *arg) { u64 current_tick = hv_read_tsc_page(&tsc_pg); @@ -232,9 +233,9 @@ static u64 notrace read_hv_sched_clock_tsc(void) return current_tick; } -static u64 read_hv_clock_tsc(struct clocksource *arg) +static u64 read_hv_sched_clock_tsc(void) { - return read_hv_sched_clock_tsc(); + return read_hv_clock_tsc(NULL) - hv_sched_clock_offset; } static struct clocksource hyperv_cs_tsc = { @@ -246,7 +247,7 @@ static struct clocksource hyperv_cs_tsc = { }; #endif -static u64 notrace read_hv_sched_clock_msr(void) +static u64 notrace read_hv_clock_msr(struct clocksource *arg) { u64 current_tick; /* @@ -258,9 +259,9 @@ static u64 notrace read_hv_sched_clock_msr(void) return current_tick; } -static u64 read_hv_clock_msr(struct clocksource *arg) +static u64 read_hv_sched_clock_msr(void) { - return read_hv_sched_clock_msr(); + return read_hv_clock_msr(NULL) - hv_sched_clock_offset; } static struct clocksource hyperv_cs_msr = { @@ -298,8 +299,9 @@ static bool __init hv_init_tsc_clocksource(void) hv_set_clocksource_vdso(hyperv_cs_tsc); clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); - /* sched_clock_register is needed on ARM64 but is a no-op on x86 */ - sched_clock_register(read_hv_sched_clock_tsc, 64, HV_CLOCK_HZ); + hv_sched_clock_offset = hyperv_cs->read(hyperv_cs); + hv_setup_sched_clock(read_hv_sched_clock_tsc); + return true; } #else @@ -329,7 +331,7 @@ void __init hv_init_clocksource(void) hyperv_cs = &hyperv_cs_msr; clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); - /* sched_clock_register is needed on ARM64 but is a no-op on x86 */ - sched_clock_register(read_hv_sched_clock_msr, 64, HV_CLOCK_HZ); + hv_sched_clock_offset = hyperv_cs->read(hyperv_cs); + hv_setup_sched_clock(read_hv_sched_clock_msr); } EXPORT_SYMBOL_GPL(hv_init_clocksource); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 0becb7d9704d..18d8e2d8210f 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -167,6 +167,7 @@ void hyperv_report_panic(struct pt_regs *regs, long err); void hyperv_report_panic_msg(phys_addr_t pa, size_t size); bool hv_is_hyperv_initialized(void); void hyperv_cleanup(void); +void hv_setup_sched_clock(void *sched_clock); #else /* CONFIG_HYPERV */ static inline bool hv_is_hyperv_initialized(void) { return false; } static inline void hyperv_cleanup(void) {} -- GitLab From 3e2d94535adb2df15f3907e4b4c7cd8a5a4c2b5a Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 22 Aug 2019 10:36:30 +0200 Subject: [PATCH 4251/7155] clocksource/drivers/hyperv: Enable TSC page clocksource on 32bit There is no particular reason to not enable TSC page clocksource on 32-bit. mul_u64_u64_shr() is available and despite the increased computational complexity (compared to 64bit) TSC page is still a huge win compared to MSR-based clocksource. In-kernel reads: MSR based clocksource: 3361 cycles TSC page clocksource: 49 cycles Reads from userspace (utilizing vDSO in case of TSC page): MSR based clocksource: 5664 cycles TSC page clocksource: 131 cycles Enabling TSC page on 32bits allows to get rid of CONFIG_HYPERV_TSCPAGE as it is now not any different from CONFIG_HYPERV_TIMER. Signed-off-by: Vitaly Kuznetsov Signed-off-by: Thomas Gleixner Reviewed-by: Michael Kelley Link: https://lkml.kernel.org/r/20190822083630.17059-1-vkuznets@redhat.com --- arch/x86/include/asm/vdso/gettimeofday.h | 6 +++--- drivers/clocksource/hyperv_timer.c | 11 ----------- drivers/hv/Kconfig | 3 --- include/clocksource/hyperv_timer.h | 8 +++----- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h index ae91429129a6..bcbf901befbe 100644 --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -51,7 +51,7 @@ extern struct pvclock_vsyscall_time_info pvclock_page __attribute__((visibility("hidden"))); #endif -#ifdef CONFIG_HYPERV_TSCPAGE +#ifdef CONFIG_HYPERV_TIMER extern struct ms_hyperv_tsc_page hvclock_page __attribute__((visibility("hidden"))); #endif @@ -192,7 +192,7 @@ static u64 vread_pvclock(void) } #endif -#ifdef CONFIG_HYPERV_TSCPAGE +#ifdef CONFIG_HYPERV_TIMER static u64 vread_hvclock(void) { return hv_read_tsc_page(&hvclock_page); @@ -215,7 +215,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode) return vread_pvclock(); } #endif -#ifdef CONFIG_HYPERV_TSCPAGE +#ifdef CONFIG_HYPERV_TIMER if (clock_mode == VCLOCK_HVCLOCK) { barrier(); return vread_hvclock(); diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index c322ab4d3689..2317d4e3daaf 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -213,8 +213,6 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup); struct clocksource *hyperv_cs; EXPORT_SYMBOL_GPL(hyperv_cs); -#ifdef CONFIG_HYPERV_TSCPAGE - static struct ms_hyperv_tsc_page tsc_pg __aligned(PAGE_SIZE); struct ms_hyperv_tsc_page *hv_get_tsc_page(void) @@ -245,7 +243,6 @@ static struct clocksource hyperv_cs_tsc = { .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#endif static u64 notrace read_hv_clock_msr(struct clocksource *arg) { @@ -272,7 +269,6 @@ static struct clocksource hyperv_cs_msr = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#ifdef CONFIG_HYPERV_TSCPAGE static bool __init hv_init_tsc_clocksource(void) { u64 tsc_msr; @@ -304,13 +300,6 @@ static bool __init hv_init_tsc_clocksource(void) return true; } -#else -static bool __init hv_init_tsc_clocksource(void) -{ - return false; -} -#endif - void __init hv_init_clocksource(void) { diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index 9a59957922d4..79e5356a737a 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig @@ -14,9 +14,6 @@ config HYPERV config HYPERV_TIMER def_bool HYPERV -config HYPERV_TSCPAGE - def_bool HYPERV && X86_64 - config HYPERV_UTILS tristate "Microsoft Hyper-V Utilities driver" depends on HYPERV && CONNECTOR && NLS diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h index a821deb8ecb2..422f5e5237be 100644 --- a/include/clocksource/hyperv_timer.h +++ b/include/clocksource/hyperv_timer.h @@ -28,12 +28,10 @@ extern void hv_stimer_cleanup(unsigned int cpu); extern void hv_stimer_global_cleanup(void); extern void hv_stimer0_isr(void); -#if IS_ENABLED(CONFIG_HYPERV) +#ifdef CONFIG_HYPERV_TIMER extern struct clocksource *hyperv_cs; extern void hv_init_clocksource(void); -#endif /* CONFIG_HYPERV */ -#ifdef CONFIG_HYPERV_TSCPAGE extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void); static inline notrace u64 @@ -91,7 +89,7 @@ hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) return hv_read_tsc_page_tsc(tsc_pg, &cur_tsc); } -#else /* CONFIG_HYPERV_TSC_PAGE */ +#else /* CONFIG_HYPERV_TIMER */ static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void) { return NULL; @@ -102,6 +100,6 @@ static inline u64 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg, { return U64_MAX; } -#endif /* CONFIG_HYPERV_TSCPAGE */ +#endif /* CONFIG_HYPERV_TIMER */ #endif -- GitLab From e112b032a72c78f15d0c803c5dc6be444c2e6c66 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Fri, 23 Aug 2019 14:24:50 +0800 Subject: [PATCH 4252/7155] arm64: map FDT as RW for early_init_dt_scan() Currently in arm64, FDT is mapped to RO before it's passed to early_init_dt_scan(). However, there might be some codes (eg. commit "fdt: add support for rng-seed") that need to modify FDT during init. Map FDT to RO after early fixups are done. Signed-off-by: Hsin-Yi Wang Reviewed-by: Stephen Boyd Reviewed-by: Mike Rapoport Signed-off-by: Will Deacon --- arch/arm64/include/asm/mmu.h | 2 +- arch/arm64/kernel/kaslr.c | 5 +---- arch/arm64/kernel/setup.c | 9 ++++++++- arch/arm64/mm/mmu.c | 15 +-------------- 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index fd6161336653..f217e3292919 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -126,7 +126,7 @@ extern void init_mem_pgprot(void); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot, bool page_mappings_only); -extern void *fixmap_remap_fdt(phys_addr_t dt_phys); +extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot); extern void mark_linear_text_alias_ro(void); #define INIT_MM_CONTEXT(name) \ diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index 708051655ad9..d94a3e41cef9 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -62,9 +62,6 @@ static __init const u8 *kaslr_get_cmdline(void *fdt) return default_cmdline; } -extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, - pgprot_t prot); - /* * This routine will be executed with the kernel mapped at its default virtual * address, and if it returns successfully, the kernel will be remapped, and @@ -93,7 +90,7 @@ u64 __init kaslr_early_init(u64 dt_phys) * attempt at mapping the FDT in setup_machine() */ early_fixmap_init(); - fdt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); + fdt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); if (!fdt) return 0; diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 9c4bad7d7131..25f5127210f8 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -170,9 +170,13 @@ static void __init smp_build_mpidr_hash(void) static void __init setup_machine_fdt(phys_addr_t dt_phys) { - void *dt_virt = fixmap_remap_fdt(dt_phys); + int size; + void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); const char *name; + if (dt_virt) + memblock_reserve(dt_phys, size); + if (!dt_virt || !early_init_dt_scan(dt_virt)) { pr_crit("\n" "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" @@ -184,6 +188,9 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) cpu_relax(); } + /* Early fixups are done, map the FDT as read-only now */ + fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); + name = of_flat_dt_get_machine_name(); if (!name) return; diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 750a69dde39b..54e93583085c 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -876,7 +876,7 @@ void __set_fixmap(enum fixed_addresses idx, } } -void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) +void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) { const u64 dt_virt_base = __fix_to_virt(FIX_FDT); int offset; @@ -929,19 +929,6 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) return dt_virt; } -void *__init fixmap_remap_fdt(phys_addr_t dt_phys) -{ - void *dt_virt; - int size; - - dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); - if (!dt_virt) - return NULL; - - memblock_reserve(dt_phys, size); - return dt_virt; -} - int __init arch_ioremap_p4d_supported(void) { return 0; -- GitLab From 428826f5358c922dc378830a1717b682c0823160 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Fri, 23 Aug 2019 14:24:51 +0800 Subject: [PATCH 4253/7155] fdt: add support for rng-seed Introducing a chosen node, rng-seed, which is an entropy that can be passed to kernel called very early to increase initial device randomness. Bootloader should provide this entropy and the value is read from /chosen/rng-seed in DT. Obtain of_fdt_crc32 for CRC check after early_init_dt_scan_nodes(), since early_init_dt_scan_chosen() would modify fdt to erase rng-seed. Add a new interface add_bootloader_randomness() for rng-seed use case. Depends on whether the seed is trustworthy, rng seed would be passed to add_hwgenerator_randomness(). Otherwise it would be passed to add_device_randomness(). Decision is controlled by kernel config RANDOM_TRUST_BOOTLOADER. Signed-off-by: Hsin-Yi Wang Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Reviewed-by: Theodore Ts'o # drivers/char/random.c Signed-off-by: Will Deacon --- drivers/char/Kconfig | 9 +++++++++ drivers/char/random.c | 14 ++++++++++++++ drivers/of/fdt.c | 14 ++++++++++++-- include/linux/random.h | 1 + 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 3e866885a405..2794f4b3f62d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -573,3 +573,12 @@ config RANDOM_TRUST_CPU has not installed a hidden back door to compromise the CPU's random number generation facilities. This can also be configured at boot with "random.trust_cpu=on/off". + +config RANDOM_TRUST_BOOTLOADER + bool "Trust the bootloader to initialize Linux's CRNG" + help + Some bootloaders can provide entropy to increase the kernel's initial + device randomness. Say Y here to assume the entropy provided by the + booloader is trustworthy so it will be added to the kernel's entropy + pool. Otherwise, say N here so it will be regarded as device input that + only mixes the entropy pool. \ No newline at end of file diff --git a/drivers/char/random.c b/drivers/char/random.c index 5d5ea4ce1442..566922df4b7b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2445,3 +2445,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, credit_entropy_bits(poolp, entropy); } EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); + +/* Handle random seed passed by bootloader. + * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise + * it would be regarded as device data. + * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER. + */ +void add_bootloader_randomness(const void *buf, unsigned int size) +{ + if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER)) + add_hwgenerator_randomness(buf, size, size * 8); + else + add_device_randomness(buf, size); +} +EXPORT_SYMBOL_GPL(add_bootloader_randomness); \ No newline at end of file diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9cdf14b9aaab..7d97ab6d0e31 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -24,6 +24,7 @@ #include #include #include +#include #include /* for COMMAND_LINE_SIZE */ #include @@ -1044,6 +1045,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, { int l; const char *p; + const void *rng_seed; pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); @@ -1078,6 +1080,14 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, pr_debug("Command line is: %s\n", (char*)data); + rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l); + if (rng_seed && l > 0) { + add_bootloader_randomness(rng_seed, l); + + /* try to clear seed so it won't be found. */ + fdt_nop_property(initial_boot_params, node, "rng-seed"); + } + /* break now */ return 1; } @@ -1166,8 +1176,6 @@ bool __init early_init_dt_verify(void *params) /* Setup flat device-tree pointer */ initial_boot_params = params; - of_fdt_crc32 = crc32_be(~0, initial_boot_params, - fdt_totalsize(initial_boot_params)); return true; } @@ -1197,6 +1205,8 @@ bool __init early_init_dt_scan(void *params) return false; early_init_dt_scan_nodes(); + of_fdt_crc32 = crc32_be(~0, initial_boot_params, + fdt_totalsize(initial_boot_params)); return true; } diff --git a/include/linux/random.h b/include/linux/random.h index 1f7dced2bba6..f189c927fdea 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -19,6 +19,7 @@ struct random_ready_callback { }; extern void add_device_randomness(const void *, unsigned int); +extern void add_bootloader_randomness(const void *, unsigned int); #if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__) static inline void add_latent_entropy(void) -- GitLab From 7f591fa7a62d3a3f585fd4ba5c3e7b05f4b931be Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Fri, 23 Aug 2019 14:24:52 +0800 Subject: [PATCH 4254/7155] arm64: kexec_file: add rng-seed support Adding "rng-seed" to dtb. It's fine to add this property if original fdt doesn't contain it. Since original seed will be wiped after read, so use a default size 128 bytes here. Signed-off-by: Hsin-Yi Wang Reviewed-by: Stephen Boyd Signed-off-by: Will Deacon --- arch/arm64/kernel/machine_kexec_file.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c index 58871333737a..81b5baad97aa 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -27,6 +27,8 @@ #define FDT_PROP_INITRD_END "linux,initrd-end" #define FDT_PROP_BOOTARGS "bootargs" #define FDT_PROP_KASLR_SEED "kaslr-seed" +#define FDT_PROP_RNG_SEED "rng-seed" +#define RNG_SEED_SIZE 128 const struct kexec_file_ops * const kexec_file_loaders[] = { &kexec_image_ops, @@ -102,6 +104,19 @@ static int setup_dtb(struct kimage *image, FDT_PROP_KASLR_SEED); } + /* add rng-seed */ + if (rng_is_initialized()) { + u8 rng_seed[RNG_SEED_SIZE]; + get_random_bytes(rng_seed, RNG_SEED_SIZE); + ret = fdt_setprop(dtb, off, FDT_PROP_RNG_SEED, rng_seed, + RNG_SEED_SIZE); + if (ret) + goto out; + } else { + pr_notice("RNG is not initialised: omitting \"%s\" property\n", + FDT_PROP_RNG_SEED); + } + out: if (ret) return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL; @@ -110,7 +125,8 @@ static int setup_dtb(struct kimage *image, } /* - * More space needed so that we can add initrd, bootargs and kaslr-seed. + * More space needed so that we can add initrd, bootargs, kaslr-seed, and + * rng-seed. */ #define DTB_EXTRA_SPACE 0x1000 -- GitLab From d9bd211dfa9377754c4b81333c376036b3a7164b Mon Sep 17 00:00:00 2001 From: Mars Cheng Date: Mon, 19 Aug 2019 17:21:32 +0800 Subject: [PATCH 4255/7155] dt-bindings: mediatek: add support for mt6779 reference board Update binding document for mt6779 reference board Signed-off-by: Mars Cheng Reviewed-by: Rob Herring Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/arm/mediatek.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml index a4ad2eb926f9..4043c5046441 100644 --- a/Documentation/devicetree/bindings/arm/mediatek.yaml +++ b/Documentation/devicetree/bindings/arm/mediatek.yaml @@ -46,6 +46,10 @@ properties: - enum: - mediatek,mt6765-evb - const: mediatek,mt6765 + - items: + - enum: + - mediatek,mt6779-evb + - const: mediatek,mt6779 - items: - enum: - mediatek,mt6795-evb -- GitLab From 563d4f0fa998000e5657ee7145aa4648ac4bf16c Mon Sep 17 00:00:00 2001 From: Mars Cheng Date: Mon, 19 Aug 2019 17:21:33 +0800 Subject: [PATCH 4256/7155] dt-bindings: mtk-uart: add mt6779 uart bindings Add documentation for mt6779 uart dt-bindings Signed-off-by: Mars Cheng Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/serial/mtk-uart.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt index 6fdffb735fb9..3a3b57079f0d 100644 --- a/Documentation/devicetree/bindings/serial/mtk-uart.txt +++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt @@ -9,6 +9,7 @@ Required properties: * "mediatek,mt6589-uart" for MT6589 compatible UARTS * "mediatek,mt6755-uart" for MT6755 compatible UARTS * "mediatek,mt6765-uart" for MT6765 compatible UARTS + * "mediatek,mt6779-uart" for MT6779 compatible UARTS * "mediatek,mt6795-uart" for MT6795 compatible UARTS * "mediatek,mt6797-uart" for MT6797 compatible UARTS * "mediatek,mt7622-uart" for MT7622 compatible UARTS -- GitLab From 7b07a7a4e169180c7da5078bdf5254515e69c152 Mon Sep 17 00:00:00 2001 From: Mars Cheng Date: Mon, 19 Aug 2019 17:21:34 +0800 Subject: [PATCH 4257/7155] dt-bindings: irq: mtk, sysirq: add support for mt6779 Add binding documentation of mediatek,sysirq for mt6779 SoC. Signed-off-by: Mars Cheng Reviewed-by: Matthias Brugger Signed-off-by: Matthias Brugger --- .../devicetree/bindings/interrupt-controller/mediatek,sysirq.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt index 0e312fea2a5d..84ced3f4179b 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt @@ -15,6 +15,7 @@ Required properties: "mediatek,mt7629-sysirq", "mediatek,mt6577-sysirq": for MT7629 "mediatek,mt6795-sysirq", "mediatek,mt6577-sysirq": for MT6795 "mediatek,mt6797-sysirq", "mediatek,mt6577-sysirq": for MT6797 + "mediatek,mt6779-sysirq", "mediatek,mt6577-sysirq": for MT6779 "mediatek,mt6765-sysirq", "mediatek,mt6577-sysirq": for MT6765 "mediatek,mt6755-sysirq", "mediatek,mt6577-sysirq": for MT6755 "mediatek,mt6592-sysirq", "mediatek,mt6577-sysirq": for MT6592 -- GitLab From 0c3a6101ff2df98d5d960bda9b159d7c4a952f27 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Mon, 29 Jul 2019 02:04:43 -0700 Subject: [PATCH 4258/7155] ice: Allow egress control packets from PF_VSI For control packets (i.e. LLDP packets) to be able to egress from the main VSI, a bit has to be set in the TX_descriptor. This should only be done for the main VSI and only if the FW LLDP agent is disabled. A bit to allow this also has to be set in the VSI context. Add the logic to add the necessary bits in the VSI context for the PF_VSI and the TX_descriptors for control packets egressing the PF_VSI. Signed-off-by: Dave Ertman Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 7 +++++++ drivers/net/ethernet/intel/ice/ice_txrx.c | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 6e34c40e7840..d6279dfe029e 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1010,6 +1010,13 @@ static int ice_vsi_init(struct ice_vsi *vsi) ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; } + /* Allow control frames out of main VSI */ + if (vsi->type == ICE_VSI_PF) { + ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; + ctxt->info.valid_sections |= + cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); + } + ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); if (ret) { dev_err(&pf->pdev->dev, diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index e5c4c9139e54..5bf5c179a738 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -2106,6 +2106,7 @@ static netdev_tx_t ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring) { struct ice_tx_offload_params offload = { 0 }; + struct ice_vsi *vsi = tx_ring->vsi; struct ice_tx_buf *first; unsigned int count; int tso, csum; @@ -2153,7 +2154,15 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring) if (csum < 0) goto out_drop; - if (tso || offload.cd_tunnel_params) { + /* allow CONTROL frames egress from main VSI if FW LLDP disabled */ + if (unlikely(skb->priority == TC_PRIO_CONTROL && + vsi->type == ICE_VSI_PF && + vsi->port_info->is_sw_lldp)) + offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX | + ICE_TX_CTX_DESC_SWTCH_UPLINK << + ICE_TXD_CTX_QW1_CMD_S); + + if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) { struct ice_tx_ctx_desc *cdesc; int i = tx_ring->next_to_use; -- GitLab From 1b0c3247a092db672bf4599f234f0e90d6e30e8b Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Mon, 29 Jul 2019 02:04:44 -0700 Subject: [PATCH 4259/7155] ice: Account for all states of FW DCBx and LLDP Currently, only the DCBx status is taken into account to determine if FW LLDP is possible. But there are NVM version coming out with DCBx enabled, and FW LLDP disabled. This is causing errors where the driver sees that DCBx is not disabled, and then tries to register for LLDP MIB change events, and fails. Change the logic to detect both DCBx and LLDP states in the FW engine. Signed-off-by: Dave Ertman Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 34 +++++++------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c index bf6cd4760a48..22bdc244c7e0 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c @@ -319,6 +319,11 @@ void ice_dcb_rebuild(struct ice_pf *pf) } ice_init_dcb(&pf->hw); + if (pf->hw.port_info->dcbx_status == ICE_DCBX_STATUS_DIS) + pf->hw.port_info->is_sw_lldp = true; + else + pf->hw.port_info->is_sw_lldp = false; + if (ice_dcb_need_recfg(pf, prev_cfg, local_dcbx_cfg)) { /* difference in cfg detected - disable DCB till next MIB */ dev_err(&pf->pdev->dev, "Set local MIB not accurate\n"); @@ -440,35 +445,17 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked) struct device *dev = &pf->pdev->dev; struct ice_port_info *port_info; struct ice_hw *hw = &pf->hw; - int sw_default = 0; int err; port_info = hw->port_info; err = ice_init_dcb(hw); if (err) { - /* FW LLDP is not active, default to SW DCBX/LLDP */ - dev_info(&pf->pdev->dev, "FW LLDP is not active\n"); - hw->port_info->dcbx_status = ICE_DCBX_STATUS_NOT_STARTED; - hw->port_info->is_sw_lldp = true; - } - - if (port_info->dcbx_status == ICE_DCBX_STATUS_DIS) - dev_info(&pf->pdev->dev, "DCBX disabled\n"); - - /* LLDP disabled in FW */ - if (port_info->is_sw_lldp) { - sw_default = 1; - dev_info(&pf->pdev->dev, "DCBx/LLDP in SW mode.\n"); + /* FW LLDP is disabled, activate SW DCBX/LLDP mode */ + dev_info(&pf->pdev->dev, + "FW LLDP is disabled, DCBx/LLDP in SW mode.\n"); + port_info->is_sw_lldp = true; clear_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags); - } else { - set_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags); - } - - if (port_info->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) - dev_info(&pf->pdev->dev, "DCBX not started\n"); - - if (sw_default) { err = ice_dcb_sw_dflt_cfg(pf, locked); if (err) { dev_err(&pf->pdev->dev, @@ -483,6 +470,9 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked) return 0; } + port_info->is_sw_lldp = false; + set_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags); + /* DCBX in FW and LLDP enabled in FW */ pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE; -- GitLab From da4a9e73d8a58eccef93682c9f2d910c346d2c1e Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Mon, 29 Jul 2019 02:04:45 -0700 Subject: [PATCH 4260/7155] ice: Don't call synchronize_irq() for VF's from the host Currently we will call synchronize_irq() from the host for VF's. This is not correct, so don't allow it. Signed-off-by: Brett Creeley Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index d6279dfe029e..c067ef6be7f4 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2817,6 +2817,10 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) ice_flush(hw); + /* don't call synchronize_irq() for VF's from the host */ + if (vsi->type == ICE_VSI_VF) + return; + ice_for_each_q_vector(vsi, i) synchronize_irq(pf->msix_entries[i + base].vector); } -- GitLab From 64bcaec64284e08430db5f00944443ec41a86df2 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Mon, 29 Jul 2019 02:04:46 -0700 Subject: [PATCH 4261/7155] ice: Treat DCBx state NOT_STARTED as valid When a port is not cabled, but DCBx is enabled in the firmware, the status of DCBx will be NOT_STARTED. This is a valid state for FW enabled and should not be treated as a is_fw_lldp true automatically. Add the code to treat NOT_STARTED as another valid state. Signed-off-by: Dave Ertman Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_dcb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index c2002ded65f6..d60c942249e8 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -954,7 +954,8 @@ enum ice_status ice_init_dcb(struct ice_hw *hw) pi->dcbx_status = ice_get_dcbx_status(hw); if (pi->dcbx_status == ICE_DCBX_STATUS_DONE || - pi->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS) { + pi->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS || + pi->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { /* Get current DCBX configuration */ ret = ice_get_dcb_cfg(pi); pi->is_sw_lldp = (hw->adminq.sq_last_status == ICE_AQ_RC_EPERM); -- GitLab From 42a179c80ddd19955ec90f01858b2993145dc874 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Mon, 29 Jul 2019 02:04:48 -0700 Subject: [PATCH 4262/7155] ice: Copy dcbx configuration only if mode is correct In rebuild DCB desired_dcbx_cfg was copy to local_dcbx_cfg, but if DCBX mode is IEEE desired_dcbx_cfg is not initialized by DCBX config from FW. Change logic to copy config value only if mode is set to CEE. If driver copy desired_dcbx_cfg to local_dcbx_cfg in IEEE mode there is problem with globr. System is frozen after two or more globr. Signed-off-by: Michal Swiatkowski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c index 22bdc244c7e0..4fc9faf5bc71 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c @@ -334,8 +334,10 @@ void ice_dcb_rebuild(struct ice_pf *pf) devm_kfree(&pf->pdev->dev, prev_cfg); /* Set the local desired config */ - memset(&pf->hw.port_info->local_dcbx_cfg, 0, sizeof(*local_dcbx_cfg)); - memcpy(local_dcbx_cfg, desired_dcbx_cfg, sizeof(*local_dcbx_cfg)); + if (local_dcbx_cfg->dcbx_mode == ICE_DCBX_MODE_CEE) + memcpy(local_dcbx_cfg, desired_dcbx_cfg, + sizeof(*local_dcbx_cfg)); + ice_cfg_etsrec_defaults(pf->hw.port_info); ret = ice_set_dcb_cfg(pf->hw.port_info); if (ret) { -- GitLab From f8af5bf5b45ecbbef2c246865b02c7350db81392 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 29 Jul 2019 02:04:49 -0700 Subject: [PATCH 4263/7155] ice: reject VF attempts to enable head writeback The virtchnl interface provides a mechanism for a VF driver to request head writeback support. This feature is deprecated as of AVF 1.0, but older versions of a VF driver may still attempt to request the mode. Since the ice hardware does not support head writeback, we should not accept Tx queue configuration which attempts to enable it. Currently, the driver simply assumes that the headwb_enabled bit will never be set. If a VF driver does request head writeback, the configuration will return successfully, even though head writeback is not enabled. This leaves the VF driver in a non functional state since it is assuming to be operating in head writeback mode. Fix the PF driver to reject any attempt to setup headwb_enabled. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 1b1d1ea0c8f9..73ab6222d29b 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -2109,6 +2109,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) if (qpi->txq.vsi_id != qci->vsi_id || qpi->rxq.vsi_id != qci->vsi_id || qpi->rxq.queue_id != qpi->txq.queue_id || + qpi->txq.headwb_enabled || !ice_vc_isvalid_q_id(vf, qci->vsi_id, qpi->txq.queue_id)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; -- GitLab From 84a118ab58edddf3d29e9972136a4c4a923ea1fa Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Mon, 29 Jul 2019 02:04:50 -0700 Subject: [PATCH 4264/7155] ice: Rename ethtool private flag for lldp The current flag name of "enable-fw-lldp" is a bit cumbersome. Change priv-flag name to "fw-lldp-agent" with a value of on or off. This is more straight-forward in meaning. Signed-off-by: Dave Ertman Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 2 +- drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 4 ++-- drivers/net/ethernet/intel/ice/ice_ethtool.c | 6 +++--- drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 9f9c30d29eb5..99e0febd8e50 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -329,7 +329,7 @@ enum ice_pf_flags { ICE_FLAG_DCB_ENA, ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, ICE_FLAG_NO_MEDIA, - ICE_FLAG_ENABLE_FW_LLDP, + ICE_FLAG_FW_LLDP_AGENT, ICE_FLAG_ETHTOOL_CTXT, /* set when ethtool holds RTNL lock */ ICE_PF_FLAGS_NBITS /* must be last */ }; diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c index 4fc9faf5bc71..734cef8eed9e 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c @@ -457,7 +457,7 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked) dev_info(&pf->pdev->dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n"); port_info->is_sw_lldp = true; - clear_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags); + clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); err = ice_dcb_sw_dflt_cfg(pf, locked); if (err) { dev_err(&pf->pdev->dev, @@ -473,7 +473,7 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked) } port_info->is_sw_lldp = false; - set_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags); + set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); /* DCBX in FW and LLDP enabled in FW */ pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 6a97ddbbda76..948a33716290 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -155,7 +155,7 @@ struct ice_priv_flag { static const struct ice_priv_flag ice_gstrings_priv_flags[] = { ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), - ICE_PRIV_FLAG("enable-fw-lldp", ICE_FLAG_ENABLE_FW_LLDP), + ICE_PRIV_FLAG("fw-lldp-agent", ICE_FLAG_FW_LLDP_AGENT), }; #define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) @@ -1201,8 +1201,8 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags) bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS); - if (test_bit(ICE_FLAG_ENABLE_FW_LLDP, change_flags)) { - if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) { + if (test_bit(ICE_FLAG_FW_LLDP_AGENT, change_flags)) { + if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) { enum ice_status status; /* Disable FW LLDP engine */ diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index c067ef6be7f4..343d0c305423 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2541,7 +2541,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, ice_cfg_sw_lldp(vsi, true, true); /* Rx LLDP packets */ - if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) + if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) ice_cfg_sw_lldp(vsi, false, true); } @@ -2888,7 +2888,7 @@ int ice_vsi_release(struct ice_vsi *vsi) /* The Rx rule will only exist to remove if the LLDP FW * engine is currently stopped */ - if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) + if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) ice_cfg_sw_lldp(vsi, false, false); } -- GitLab From 90e477379e92c110a34ca0d108aa97d5b02076ee Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 29 Jul 2019 02:04:51 -0700 Subject: [PATCH 4265/7155] ice: silence some bogus error messages In some circumstances, VF devices can be deactivated while a message is in-flight. In that case, a series of scary error message will be printed in the log. Since these are actually harmless, check for this case and suppress them. No harm, no foul. Signed-off-by: Mitch Williams Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 1 + drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 765e3c2ed045..bf9aa533a7c6 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1610,6 +1610,7 @@ enum ice_aq_err { ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */ ICE_AQ_RC_EEXIST = 13, /* Object already exists */ ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */ + ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */ }; /* Admin Queue command opcodes */ diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 73ab6222d29b..83e58e71081e 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -1512,10 +1512,10 @@ ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode, aq_ret = ice_aq_send_msg_to_vf(&pf->hw, vf->vf_id, v_opcode, v_retval, msg, msglen, NULL); - if (aq_ret) { + if (aq_ret && pf->hw.mailboxq.sq_last_status != ICE_AQ_RC_ENOSYS) { dev_info(&pf->pdev->dev, - "Unable to send the message to VF %d aq_err %d\n", - vf->vf_id, pf->hw.mailboxq.sq_last_status); + "Unable to send the message to VF %d ret %d aq_err %d\n", + vf->vf_id, aq_ret, pf->hw.mailboxq.sq_last_status); return -EIO; } -- GitLab From 057911ba9b7939a3395e5c3c497fa2af830123e4 Mon Sep 17 00:00:00 2001 From: Chinh T Cao Date: Mon, 29 Jul 2019 02:04:52 -0700 Subject: [PATCH 4266/7155] ice: Fix flag used for module query When checking the PHY for status, by specification, the driver should be using "topology" mode when querying the module type. Signed-off-by: Chinh T Cao Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 5f9dc76699d2..15648d4a8bab 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2031,7 +2031,7 @@ enum ice_status ice_update_link_info(struct ice_port_info *pi) if (!pcaps) return ICE_ERR_NO_MEMORY; - status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, + status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL); if (!status) memcpy(li->module_type, &pcaps->module_type, -- GitLab From 3747f03115c1c7e577e86c7698e061a21f20576c Mon Sep 17 00:00:00 2001 From: Chinh T Cao Date: Mon, 29 Jul 2019 02:04:53 -0700 Subject: [PATCH 4267/7155] ice: Don't clear auto_fec bit in ice_cfg_phy_fec() The driver should never clear the auto_fec_enable bit. Signed-off-by: Chinh T Cao Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 15648d4a8bab..4b43e6de847b 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2181,27 +2181,24 @@ ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec) { switch (fec) { case ICE_FEC_BASER: - /* Clear auto FEC and RS bits, and AND BASE-R ability + /* Clear RS bits, and AND BASE-R ability * bits and OR request bits. */ - cfg->caps &= ~ICE_AQC_PHY_EN_AUTO_FEC; cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN | ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN; cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ | ICE_AQC_PHY_FEC_25G_KR_REQ; break; case ICE_FEC_RS: - /* Clear auto FEC and BASE-R bits, and AND RS ability + /* Clear BASE-R bits, and AND RS ability * bits and OR request bits. */ - cfg->caps &= ~ICE_AQC_PHY_EN_AUTO_FEC; cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN; cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ | ICE_AQC_PHY_FEC_25G_RS_544_REQ; break; case ICE_FEC_NONE: - /* Clear auto FEC and all FEC option bits. */ - cfg->caps &= ~ICE_AQC_PHY_EN_AUTO_FEC; + /* Clear all FEC option bits. */ cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK; break; case ICE_FEC_AUTO: -- GitLab From 3f416961b0a5000bf5556de1a53cc3cf87a6e744 Mon Sep 17 00:00:00 2001 From: "Amruth G.P" Date: Mon, 29 Jul 2019 02:04:54 -0700 Subject: [PATCH 4268/7155] ice: Add input handlers for virtual channel handlers Move the assignment to local variables after validation. Remove unnecessary checks in ice_vc_process_vf_msg() as the respective functions are now performing the checks. Signed-off-by: "Amruth G.P" Signed-off-by: Nitesh B Venkatesh Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 83e58e71081e..de0a1ef54e83 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -1734,18 +1734,18 @@ static int ice_vc_config_rss_key(struct ice_vf *vf, u8 *msg) goto error_param; } - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!vsi) { + if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } - if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) { + if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } - if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { + vsi = pf->vsi[vf->lan_vsi_idx]; + if (!vsi) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } @@ -1781,18 +1781,18 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg) goto error_param; } - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!vsi) { + if (vrl->lut_entries != ICE_VSIQF_HLUT_ARRAY_SIZE) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } - if (vrl->lut_entries != ICE_VSIQF_HLUT_ARRAY_SIZE) { + if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } - if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { + vsi = pf->vsi[vf->lan_vsi_idx]; + if (!vsi) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } @@ -1877,6 +1877,12 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg) goto error_param; } + if (vqs->rx_queues > ICE_MAX_BASE_QS_PER_VF || + vqs->tx_queues > ICE_MAX_BASE_QS_PER_VF) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto error_param; + } + vsi = pf->vsi[vf->lan_vsi_idx]; if (!vsi) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; @@ -1932,6 +1938,12 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) goto error_param; } + if (vqs->rx_queues > ICE_MAX_BASE_QS_PER_VF || + vqs->tx_queues > ICE_MAX_BASE_QS_PER_VF) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto error_param; + } + vsi = pf->vsi[vf->lan_vsi_idx]; if (!vsi) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; @@ -1984,12 +1996,6 @@ static int ice_vc_cfg_irq_map_msg(struct ice_vf *vf, u8 *msg) irqmap_info = (struct virtchnl_irq_map_info *)msg; num_q_vectors_mapped = irqmap_info->num_vectors; - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto error_param; - } - /* Check to make sure number of VF vectors mapped is not greater than * number of VF vectors originally allocated, and check that * there is actually at least a single VF queue vector mapped @@ -2001,6 +2007,12 @@ static int ice_vc_cfg_irq_map_msg(struct ice_vf *vf, u8 *msg) goto error_param; } + vsi = pf->vsi[vf->lan_vsi_idx]; + if (!vsi) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto error_param; + } + for (i = 0; i < num_q_vectors_mapped; i++) { struct ice_q_vector *q_vector; @@ -2092,10 +2104,6 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) goto error_param; } - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!vsi) - goto error_param; - if (qci->num_queue_pairs > ICE_MAX_BASE_QS_PER_VF) { dev_err(&pf->pdev->dev, "VF-%d requesting more than supported number of queues: %d\n", @@ -2104,6 +2112,12 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) goto error_param; } + vsi = pf->vsi[vf->lan_vsi_idx]; + if (!vsi) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto error_param; + } + for (i = 0; i < qci->num_queue_pairs; i++) { qpi = &qci->qpair[i]; if (qpi->txq.vsi_id != qci->vsi_id || @@ -2755,20 +2769,6 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) err = -EPERM; else err = -EINVAL; - goto error_handler; - } - - /* Perform additional checks specific to RSS and Virtchnl */ - if (v_opcode == VIRTCHNL_OP_CONFIG_RSS_KEY) { - struct virtchnl_rss_key *vrk = (struct virtchnl_rss_key *)msg; - - if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) - err = -EINVAL; - } else if (v_opcode == VIRTCHNL_OP_CONFIG_RSS_LUT) { - struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg; - - if (vrl->lut_entries != ICE_VSIQF_HLUT_ARRAY_SIZE) - err = -EINVAL; } error_handler: -- GitLab From 5a4a8673102761fb87c94ee20633bf1f2a6911ca Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 25 Jul 2019 02:53:50 -0700 Subject: [PATCH 4269/7155] ice: update ethtool stats on-demand Users expect ethtool statistics to be updated on-demand when invoking 'ethtool -S ' instead of providing a snapshot of statistics taken once a second (the frequency of the watchdog task where stats are currently updated). Update stats every time 'ethtool -S ' is run. Also, fix an indentation style issue and an unnecessary local variable initialization in ice_get_ethtool_stats() discovered while investigating the subject issue. Signed-off-by: Bruce Allan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 2 ++ drivers/net/ethernet/intel/ice/ice_ethtool.c | 7 +++++-- drivers/net/ethernet/intel/ice/ice_main.c | 6 ++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 99e0febd8e50..97d0f61cf52b 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -447,6 +447,8 @@ ice_find_vsi_by_type(struct ice_pf *pf, enum ice_vsi_type type) int ice_vsi_setup_tx_rings(struct ice_vsi *vsi); int ice_vsi_setup_rx_rings(struct ice_vsi *vsi); void ice_set_ethtool_ops(struct net_device *netdev); +void ice_update_vsi_stats(struct ice_vsi *vsi); +void ice_update_pf_stats(struct ice_pf *pf); int ice_up(struct ice_vsi *vsi); int ice_down(struct ice_vsi *vsi); int ice_vsi_cfg(struct ice_vsi *vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 948a33716290..f7dd0bd03d39 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1319,14 +1319,17 @@ ice_get_ethtool_stats(struct net_device *netdev, struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; struct ice_ring *ring; - unsigned int j = 0; + unsigned int j; int i = 0; char *p; + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + for (j = 0; j < ICE_VSI_STATS_LEN; j++) { p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } /* populate per queue stats */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index a0d148f590c2..6dd806b763ea 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -34,8 +34,6 @@ static const struct net_device_ops ice_netdev_ops; static void ice_rebuild(struct ice_pf *pf); static void ice_vsi_release_all(struct ice_pf *pf); -static void ice_update_vsi_stats(struct ice_vsi *vsi); -static void ice_update_pf_stats(struct ice_pf *pf); /** * ice_get_tx_pending - returns number of Tx descriptors not processed @@ -3254,7 +3252,7 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) * ice_update_vsi_stats - Update VSI stats counters * @vsi: the VSI to be updated */ -static void ice_update_vsi_stats(struct ice_vsi *vsi) +void ice_update_vsi_stats(struct ice_vsi *vsi) { struct rtnl_link_stats64 *cur_ns = &vsi->net_stats; struct ice_eth_stats *cur_es = &vsi->eth_stats; @@ -3290,7 +3288,7 @@ static void ice_update_vsi_stats(struct ice_vsi *vsi) * ice_update_pf_stats - Update PF port stats counters * @pf: PF whose stats needs to be updated */ -static void ice_update_pf_stats(struct ice_pf *pf) +void ice_update_pf_stats(struct ice_pf *pf) { struct ice_hw_port_stats *prev_ps, *cur_ps; struct ice_hw *hw = &pf->hw; -- GitLab From bbb968e8b34c2cf5ff99d0dfdb73639070b3dee1 Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Thu, 25 Jul 2019 02:53:51 -0700 Subject: [PATCH 4270/7155] ice: Fix issues updating VSI MAC filters VSI, especially VF could request to add or remove filter for another VSI, driver should really guide such request and disallow it. However, instead of returning error for such malicious request, driver can simply return success. In addition, we are not tracking number of MAC filters configured per VF correctly - and this leads to issue updating VF MAC filters whenever they were removed and re-configured via bringing VF interface down and up. Also, since VF could send request to update multiple MAC filters at once, driver should program those filters individually in the switch, in order to determine which action resulted to error, and communicate accordingly to the VF. So, with this changes, we now track number of filters added right from when VF resources allocation is done, and could properly add filters for both trusted and non_trusted VFs, without MAC filters mis-match issue in the switch... Also refactor code, so that driver can use new function to add or remove MAC filters. Signed-off-by: Akeem G Abodunrin Signed-off-by: Tony Nguyen Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 30 +++++++++ drivers/net/ethernet/intel/ice/ice_lib.h | 4 ++ drivers/net/ethernet/intel/ice/ice_main.c | 64 +++++-------------- .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 42 ++++++------ 4 files changed, 73 insertions(+), 67 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 343d0c305423..8d5d6635a123 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3181,3 +3181,33 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) return ret; } #endif /* CONFIG_DCB */ + +/** + * ice_vsi_cfg_mac_fltr - Add or remove a MAC address filter for a VSI + * @vsi: the VSI being configured MAC filter + * @macaddr: the MAC address to be added. + * @set: Add or delete a MAC filter + * + * Adds or removes MAC address filter entry for VF VSI + */ +enum ice_status +ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set) +{ + LIST_HEAD(tmp_add_list); + enum ice_status status; + + /* Update MAC filter list to be added or removed for a VSI */ + if (ice_add_mac_to_list(vsi, &tmp_add_list, macaddr)) { + status = ICE_ERR_NO_MEMORY; + goto cfg_mac_fltr_exit; + } + + if (set) + status = ice_add_mac(&vsi->back->hw, &tmp_add_list); + else + status = ice_remove_mac(&vsi->back->hw, &tmp_add_list); + +cfg_mac_fltr_exit: + ice_free_fltr_list(&vsi->back->pdev->dev, &tmp_add_list); + return status; +} diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index 6e43ef03bfc3..969ba27cba95 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -95,4 +95,8 @@ void ice_vsi_free_tx_rings(struct ice_vsi *vsi); int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena); u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran); + +enum ice_status +ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set); + #endif /* !_ICE_LIB_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 6dd806b763ea..f3923dec32b7 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -116,10 +116,9 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf) */ static int ice_init_mac_fltr(struct ice_pf *pf) { - LIST_HEAD(tmp_add_list); + enum ice_status status; u8 broadcast[ETH_ALEN]; struct ice_vsi *vsi; - int status; vsi = ice_find_vsi_by_type(pf, ICE_VSI_PF); if (!vsi) @@ -130,8 +129,7 @@ static int ice_init_mac_fltr(struct ice_pf *pf) */ /* Add a unicast MAC filter so the VSI can get its packets */ - status = ice_add_mac_to_list(vsi, &tmp_add_list, - vsi->port_info->mac.perm_addr); + status = ice_vsi_cfg_mac_fltr(vsi, vsi->port_info->mac.perm_addr, true); if (status) goto unregister; @@ -139,18 +137,11 @@ static int ice_init_mac_fltr(struct ice_pf *pf) * MAC address to the list as well. */ eth_broadcast_addr(broadcast); - status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast); - if (status) - goto free_mac_list; - - /* Program MAC filters for entries in tmp_add_list */ - status = ice_add_mac(&pf->hw, &tmp_add_list); + status = ice_vsi_cfg_mac_fltr(vsi, broadcast, true); if (status) - status = -ENOMEM; - -free_mac_list: - ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); + goto unregister; + return 0; unregister: /* We aren't useful with no MAC filters, so unregister if we * had an error @@ -164,7 +155,7 @@ static int ice_init_mac_fltr(struct ice_pf *pf) vsi->netdev = NULL; } - return status; + return -EIO; } /** @@ -2834,10 +2825,8 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi) struct ice_hw *hw = &pf->hw; struct sockaddr *addr = pi; enum ice_status status; - LIST_HEAD(a_mac_list); - LIST_HEAD(r_mac_list); u8 flags = 0; - int err; + int err = 0; u8 *mac; mac = (u8 *)addr->sa_data; @@ -2860,42 +2849,23 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi) /* When we change the MAC address we also have to change the MAC address * based filter rules that were created previously for the old MAC * address. So first, we remove the old filter rule using ice_remove_mac - * and then create a new filter rule using ice_add_mac. Note that for - * both these operations, we first need to form a "list" of MAC - * addresses (even though in this case, we have only 1 MAC address to be - * added/removed) and this done using ice_add_mac_to_list. Depending on - * the ensuing operation this "list" of MAC addresses is either to be - * added or removed from the filter. + * and then create a new filter rule using ice_add_mac via + * ice_vsi_cfg_mac_fltr function call for both add and/or remove + * filters. */ - err = ice_add_mac_to_list(vsi, &r_mac_list, netdev->dev_addr); - if (err) { - err = -EADDRNOTAVAIL; - goto free_lists; - } - - status = ice_remove_mac(hw, &r_mac_list); + status = ice_vsi_cfg_mac_fltr(vsi, netdev->dev_addr, false); if (status) { err = -EADDRNOTAVAIL; - goto free_lists; - } - - err = ice_add_mac_to_list(vsi, &a_mac_list, mac); - if (err) { - err = -EADDRNOTAVAIL; - goto free_lists; + goto err_update_filters; } - status = ice_add_mac(hw, &a_mac_list); + status = ice_vsi_cfg_mac_fltr(vsi, mac, true); if (status) { err = -EADDRNOTAVAIL; - goto free_lists; + goto err_update_filters; } -free_lists: - /* free list entries */ - ice_free_fltr_list(&pf->pdev->dev, &r_mac_list); - ice_free_fltr_list(&pf->pdev->dev, &a_mac_list); - +err_update_filters: if (err) { netdev_err(netdev, "can't set MAC %pM. filter update failed\n", mac); @@ -2911,8 +2881,8 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi) flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL; status = ice_aq_manage_mac_write(hw, mac, flags, NULL); if (status) { - netdev_err(netdev, "can't set MAC %pM. write to firmware failed.\n", - mac); + netdev_err(netdev, "can't set MAC %pM. write to firmware failed error %d\n", + mac, status); } return 0; } diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index de0a1ef54e83..86637d99ee77 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -540,7 +540,10 @@ static int ice_alloc_vsi_res(struct ice_vf *vf) status = ice_add_mac(&pf->hw, &tmp_add_list); if (status) - dev_err(&pf->pdev->dev, "could not add mac filters\n"); + dev_err(&pf->pdev->dev, + "could not add mac filters error %d\n", status); + else + vf->num_mac = 1; /* Clear this bit after VF initialization since we shouldn't reclaim * and reassign interrupts for synchronous or asynchronous VFR events. @@ -2208,7 +2211,7 @@ ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) (struct virtchnl_ether_addr_list *)msg; struct ice_pf *pf = vf->pf; enum virtchnl_ops vc_op; - LIST_HEAD(mac_list); + enum ice_status status; struct ice_vsi *vsi; int mac_count = 0; int i; @@ -2282,33 +2285,32 @@ ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set) goto handle_mac_exit; } - /* get here if maddr is multicast or if VF can change MAC */ - if (ice_add_mac_to_list(vsi, &mac_list, al->list[i].addr)) { - v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; + /* program the updated filter list */ + status = ice_vsi_cfg_mac_fltr(vsi, maddr, set); + if (status == ICE_ERR_DOES_NOT_EXIST || + status == ICE_ERR_ALREADY_EXISTS) { + dev_info(&pf->pdev->dev, + "can't %s MAC filters %pM for VF %d, error %d\n", + set ? "add" : "remove", maddr, vf->vf_id, + status); + } else if (status) { + dev_err(&pf->pdev->dev, + "can't %s MAC filters for VF %d, error %d\n", + set ? "add" : "remove", vf->vf_id, status); + v_ret = ice_err_to_virt_err(status); goto handle_mac_exit; } + mac_count++; } - /* program the updated filter list */ + /* Track number of MAC filters programmed for the VF VSI */ if (set) - v_ret = ice_err_to_virt_err(ice_add_mac(&pf->hw, &mac_list)); + vf->num_mac += mac_count; else - v_ret = ice_err_to_virt_err(ice_remove_mac(&pf->hw, &mac_list)); - - if (v_ret) { - dev_err(&pf->pdev->dev, - "can't %s MAC filters for VF %d, error %d\n", - set ? "add" : "remove", vf->vf_id, v_ret); - } else { - if (set) - vf->num_mac += mac_count; - else - vf->num_mac -= mac_count; - } + vf->num_mac -= mac_count; handle_mac_exit: - ice_free_fltr_list(&pf->pdev->dev, &mac_list); /* send the response to the VF */ return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0); } -- GitLab From 8b2c858240aca43c59fc7762f10754354406883d Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Thu, 25 Jul 2019 02:53:52 -0700 Subject: [PATCH 4271/7155] ice: Don't allow VSI to remove unassociated ucast filter If a VSI is not using a unicast filter or did not configure that particular unicast filter, driver should not allow it to be removed by the rogue VSI. Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_switch.c | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 8271fd651725..99cf527d2b1a 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -2136,6 +2136,38 @@ ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction) return status; } +/** + * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry + * @hw: pointer to the hardware structure + * @recp_id: lookup type for which the specified rule needs to be searched + * @f_info: rule information + * + * Helper function to search for a unicast rule entry - this is to be used + * to remove unicast MAC filter that is not shared with other VSIs on the + * PF switch. + * + * Returns pointer to entry storing the rule if found + */ +static struct ice_fltr_mgmt_list_entry * +ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id, + struct ice_fltr_info *f_info) +{ + struct ice_switch_info *sw = hw->switch_info; + struct ice_fltr_mgmt_list_entry *list_itr; + struct list_head *list_head; + + list_head = &sw->recp_list[recp_id].filt_rules; + list_for_each_entry(list_itr, list_head, list_entry) { + if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, + sizeof(f_info->l_data)) && + f_info->fwd_id.hw_vsi_id == + list_itr->fltr_info.fwd_id.hw_vsi_id && + f_info->flag == list_itr->fltr_info.flag) + return list_itr; + } + return NULL; +} + /** * ice_remove_mac - remove a MAC address based filter rule * @hw: pointer to the hardware structure @@ -2153,15 +2185,39 @@ enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) { struct ice_fltr_list_entry *list_itr, *tmp; + struct mutex *rule_lock; /* Lock to protect filter rule list */ if (!m_list) return ICE_ERR_PARAM; + rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) { enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; + u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; + u16 vsi_handle; if (l_type != ICE_SW_LKUP_MAC) return ICE_ERR_PARAM; + + vsi_handle = list_itr->fltr_info.vsi_handle; + if (!ice_is_vsi_valid(hw, vsi_handle)) + return ICE_ERR_PARAM; + + list_itr->fltr_info.fwd_id.hw_vsi_id = + ice_get_hw_vsi_num(hw, vsi_handle); + if (is_unicast_ether_addr(add) && !hw->ucast_shared) { + /* Don't remove the unicast address that belongs to + * another VSI on the switch, since it is not being + * shared... + */ + mutex_lock(rule_lock); + if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC, + &list_itr->fltr_info)) { + mutex_unlock(rule_lock); + return ICE_ERR_DOES_NOT_EXIST; + } + mutex_unlock(rule_lock); + } list_itr->status = ice_remove_rule_internal(hw, ICE_SW_LKUP_MAC, list_itr); -- GitLab From 38b4e09fbccab6457536563823222921c49601bb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 23 Aug 2019 12:49:00 -0600 Subject: [PATCH 4272/7155] null_blk: fix inline misuse You can't magically mark a function inline and expect that to work. Fixes: fceb5d1b19cb ("null_blk: create a helper for zoned devices") Signed-off-by: Jens Axboe --- drivers/block/null_blk.h | 6 +++--- drivers/block/null_blk_zoned.c | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index 4895c02e0c65..6fa3c07af63a 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -90,9 +90,9 @@ int null_zone_init(struct nullb_device *dev); void null_zone_exit(struct nullb_device *dev); int null_zone_report(struct gendisk *disk, sector_t sector, struct blk_zone *zones, unsigned int *nr_zones); -inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, - enum req_opf op, sector_t sector, - sector_t nr_sectors); +blk_status_t null_handle_zoned(struct nullb_cmd *cmd, + enum req_opf op, sector_t sector, + sector_t nr_sectors); #else static inline int null_zone_init(struct nullb_device *dev) { diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index 90092247e7eb..c07a05315e25 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -148,9 +148,8 @@ static blk_status_t null_zone_reset(struct nullb_cmd *cmd, sector_t sector) return BLK_STS_OK; } -inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, - enum req_opf op, sector_t sector, - sector_t nr_sectors) +blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op, + sector_t sector, sector_t nr_sectors) { switch (op) { case REQ_OP_WRITE: -- GitLab From 9fac85a6db8999922f2cd92dfe2e83e063b31a94 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Aug 2019 11:43:45 +0900 Subject: [PATCH 4273/7155] ARM: at91: move platform-specific asm-offset.h to arch/arm/mach-at91 is only generated and included by arch/arm/mach-at91/, so it does not need to reside in the globally visible include/generated/. I renamed it to arch/arm/mach-at91/pm_data-offsets.h since the prefix 'at91_' is just redundant in mach-at91/. My main motivation of this change is to avoid the race condition for the parallel build (-j) when CONFIG_IKHEADERS is enabled. When it is enabled, all the headers under include/ are archived into kernel/kheaders_data.tar.xz and exposed in the sysfs. In the parallel build, we have no idea in which order files are built. - If at91_pm_data-offsets.h is built before kheaders_data.tar.xz, the header will be included in the archive. Probably nobody will use it, but it is harmless except that it will increase the archive size needlessly. - If kheaders_data.tar.xz is built before at91_pm_data-offsets.h, the header will not be included in the archive. However, in the next build, the archive will be re-generated to include the newly-found at91_pm_data-offsets.h. This is not nice from the build system point of view. - If at91_pm_data-offsets.h and kheaders_data.tar.xz are built at the same time, the corrupted header might be included in the archive, which does not look nice either. This commit fixes the race. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190823024346.591-1-yamada.masahiro@socionext.com Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/.gitignore | 1 + arch/arm/mach-at91/Makefile | 5 +++-- arch/arm/mach-at91/pm_suspend.S | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-at91/.gitignore diff --git a/arch/arm/mach-at91/.gitignore b/arch/arm/mach-at91/.gitignore new file mode 100644 index 000000000000..2ecd6f51c8a9 --- /dev/null +++ b/arch/arm/mach-at91/.gitignore @@ -0,0 +1 @@ +pm_data-offsets.h diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 31b61f0e1c07..de64301dcff2 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -19,9 +19,10 @@ ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG endif -include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE +$(obj)/pm_data-offsets.h: $(obj)/pm_data-offsets.s FORCE $(call filechk,offsets,__PM_DATA_OFFSETS_H__) -arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h +$(obj)/pm_suspend.o: $(obj)/pm_data-offsets.h targets += pm_data-offsets.s +clean-files += pm_data-offsets.h diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index c751f047b116..ed57c879d4e1 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -10,7 +10,7 @@ #include #include #include "pm.h" -#include "generated/at91_pm_data-offsets.h" +#include "pm_data-offsets.h" #define SRAMC_SELF_FRESH_ACTIVE 0x01 #define SRAMC_SELF_FRESH_EXIT 0x00 -- GitLab From ec8005339badea37d18eb19f02efcc4a98dafc52 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 23 Aug 2019 10:31:56 +0200 Subject: [PATCH 4274/7155] MAINTAINERS: at91: Collect all pinctrl/gpio drivers in same entry Andrei's address is not valid anymore, collect all pinctrl/gpio entries in the common "PIN CONTROLLER - MICROCHIP AT91" one and remove the PIOBU specific one. Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20190823083158.2649-1-nicolas.ferre@microchip.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..646e0b576acd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10615,12 +10615,6 @@ M: Nicolas Ferre S: Supported F: drivers/power/reset/at91-sama5d2_shdwc.c -MICROCHIP SAMA5D2-COMPATIBLE PIOBU GPIO -M: Andrei Stefanescu -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -L: linux-gpio@vger.kernel.org -F: drivers/gpio/gpio-sama5d2-piobu.c - MICROCHIP SPI DRIVER M: Nicolas Ferre S: Supported @@ -12679,6 +12673,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-gpio@vger.kernel.org S: Supported F: drivers/pinctrl/pinctrl-at91* +F: drivers/gpio/gpio-sama5d2-piobu.c PIN CONTROLLER - FREESCALE M: Dong Aisheng -- GitLab From 44015a8181a54ce0376513645a5a8d1652677019 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 23 Aug 2019 10:31:57 +0200 Subject: [PATCH 4275/7155] MAINTAINERS: at91: remove the TC entry "MICROCHIP TIMER COUNTER (TC) AND CLOCKSOURCE DRIVERS" is better removed because one file entry is outdated and basically, the maintainer's pool of Alexandre, Ludovic and myself is better suited. drivers/misc/atmel_tclib.c file is going away in a patch to come and drivers/clocksource/tcb_clksrc.c file is actually named timer-atmel-tcb.c. This new name matches the AT91 entry regular expression. Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20190823083158.2649-2-nicolas.ferre@microchip.com Signed-off-by: Alexandre Belloni --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 646e0b576acd..f97a372c6873 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10627,13 +10627,6 @@ S: Supported F: drivers/misc/atmel-ssc.c F: include/linux/atmel-ssc.h -MICROCHIP TIMER COUNTER (TC) AND CLOCKSOURCE DRIVERS -M: Nicolas Ferre -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Supported -F: drivers/misc/atmel_tclib.c -F: drivers/clocksource/tcb_clksrc.c - MICROCHIP USBA UDC DRIVER M: Cristian Birsan L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- GitLab From 2cb831e0f152e483ab797b44787a4ff426267fbc Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 23 Aug 2019 10:31:58 +0200 Subject: [PATCH 4276/7155] mailmap: map old company name to new one @microchip.com Map my old email address @atmel.com to my new company name. It happened 3 years ago but I realized the existence of this file recently. Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20190823083158.2649-3-nicolas.ferre@microchip.com Signed-off-by: Alexandre Belloni --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 0fef932de3db..80be83cff32a 100644 --- a/.mailmap +++ b/.mailmap @@ -170,6 +170,7 @@ Morten Welinder Morten Welinder Mythri P K Nguyen Anh Quynh +Nicolas Ferre Nicolas Pitre Nicolas Pitre Paolo 'Blaisorblade' Giarrusso -- GitLab From f4a93be689dfc887d73cdaf4245a8a7d031aa912 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Fri, 23 Aug 2019 15:33:40 +0800 Subject: [PATCH 4277/7155] r8152: saving the settings of EEE Saving the settings of EEE to avoid they become the default settings after reset_resume(). Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 80 +++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 1aa61610f0bb..a7aa48bee732 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -751,6 +751,7 @@ struct r8152 { atomic_t rx_count; + bool eee_en; int intr_interval; u32 saved_wolopts; u32 msg_enable; @@ -762,6 +763,7 @@ struct r8152 { u16 ocp_base; u16 speed; + u16 eee_adv; u8 *intr_buff; u8 version; u8 duplex; @@ -3202,8 +3204,13 @@ static void r8152_eee_en(struct r8152 *tp, bool enable) static void r8152b_enable_eee(struct r8152 *tp) { - r8152_eee_en(tp, true); - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, MDIO_EEE_100TX); + if (tp->eee_en) { + r8152_eee_en(tp, true); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, tp->eee_adv); + } else { + r8152_eee_en(tp, false); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + } } static void r8152b_enable_fc(struct r8152 *tp) @@ -3495,8 +3502,10 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) sram_write(tp, SRAM_10M_AMP1, 0x00af); sram_write(tp, SRAM_10M_AMP2, 0x0208); - r8153_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX); + if (tp->eee_en) { + r8153_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } r8153_aldps_en(tp, true); r8152b_enable_fc(tp); @@ -3599,8 +3608,10 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) r8153b_ups_flags_w1w0(tp, ups_flags, 0); - r8153b_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX); + if (tp->eee_en) { + r8153b_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } r8153b_aldps_en(tp, true); r8153b_enable_fc(tp); @@ -4891,7 +4902,7 @@ static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data) static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee) { - u32 ocp_data, lp, adv, supported = 0; + u32 lp, adv, supported = 0; u16 val; val = r8152_mmd_read(tp, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); @@ -4903,13 +4914,10 @@ static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee) val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); lp = mmd_eee_adv_to_ethtool_adv_t(val); - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - ocp_data &= EEE_RX_EN | EEE_TX_EN; - - eee->eee_enabled = !!ocp_data; + eee->eee_enabled = tp->eee_en; eee->eee_active = !!(supported & adv & lp); eee->supported = supported; - eee->advertised = adv; + eee->advertised = tp->eee_adv; eee->lp_advertised = lp; return 0; @@ -4919,19 +4927,22 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee) { u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - r8152_eee_en(tp, eee->eee_enabled); + tp->eee_en = eee->eee_enabled; + tp->eee_adv = val; - if (!eee->eee_enabled) - val = 0; + r8152_eee_en(tp, eee->eee_enabled); - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); + if (eee->eee_enabled) + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); + else + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); return 0; } static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee) { - u32 ocp_data, lp, adv, supported = 0; + u32 lp, adv, supported = 0; u16 val; val = ocp_reg_read(tp, OCP_EEE_ABLE); @@ -4943,13 +4954,10 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee) val = ocp_reg_read(tp, OCP_EEE_LPABLE); lp = mmd_eee_adv_to_ethtool_adv_t(val); - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - ocp_data &= EEE_RX_EN | EEE_TX_EN; - - eee->eee_enabled = !!ocp_data; + eee->eee_enabled = tp->eee_en; eee->eee_active = !!(supported & adv & lp); eee->supported = supported; - eee->advertised = adv; + eee->advertised = tp->eee_adv; eee->lp_advertised = lp; return 0; @@ -4959,12 +4967,15 @@ static int r8153_set_eee(struct r8152 *tp, struct ethtool_eee *eee) { u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - r8153_eee_en(tp, eee->eee_enabled); + tp->eee_en = eee->eee_enabled; + tp->eee_adv = val; - if (!eee->eee_enabled) - val = 0; + r8153_eee_en(tp, eee->eee_enabled); - ocp_reg_write(tp, OCP_EEE_ADV, val); + if (eee->eee_enabled) + ocp_reg_write(tp, OCP_EEE_ADV, val); + else + ocp_reg_write(tp, OCP_EEE_ADV, 0); return 0; } @@ -4973,12 +4984,15 @@ static int r8153b_set_eee(struct r8152 *tp, struct ethtool_eee *eee) { u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - r8153b_eee_en(tp, eee->eee_enabled); + tp->eee_en = eee->eee_enabled; + tp->eee_adv = val; - if (!eee->eee_enabled) - val = 0; + r8153b_eee_en(tp, eee->eee_enabled); - ocp_reg_write(tp, OCP_EEE_ADV, val); + if (eee->eee_enabled) + ocp_reg_write(tp, OCP_EEE_ADV, val); + else + ocp_reg_write(tp, OCP_EEE_ADV, 0); return 0; } @@ -5353,6 +5367,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8152b_hw_phy_cfg; ops->autosuspend_en = rtl_runtime_suspend_enable; tp->rx_buf_sz = 16 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_100TX; break; case RTL_VER_03: @@ -5371,6 +5387,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8153_hw_phy_cfg; ops->autosuspend_en = rtl8153_runtime_enable; tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; break; case RTL_VER_08: @@ -5387,6 +5405,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8153b_hw_phy_cfg; ops->autosuspend_en = rtl8153b_runtime_enable; tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; break; default: -- GitLab From e7bde56b7446ccda351a216ff55af09a96fea940 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Fri, 23 Aug 2019 15:33:41 +0800 Subject: [PATCH 4278/7155] r8152: add a helper function about setting EEE Add a helper function "rtl_eee_enable" for setting EEE. Besides, I move r8153_eee_en() and r8153b_eee_en(). And, I remove r8152b_enable_eee(), r8153_set_eee(), and r8153b_set_eee(). Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 168 ++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 91 deletions(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index a7aa48bee732..17f0e9e98697 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3202,14 +3202,75 @@ static void r8152_eee_en(struct r8152 *tp, bool enable) ocp_reg_write(tp, OCP_EEE_CONFIG3, config3); } -static void r8152b_enable_eee(struct r8152 *tp) +static void r8153_eee_en(struct r8152 *tp, bool enable) { - if (tp->eee_en) { - r8152_eee_en(tp, true); - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, tp->eee_adv); + u32 ocp_data; + u16 config; + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); + config = ocp_reg_read(tp, OCP_EEE_CFG); + + if (enable) { + ocp_data |= EEE_RX_EN | EEE_TX_EN; + config |= EEE10_EN; } else { - r8152_eee_en(tp, false); - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + ocp_data &= ~(EEE_RX_EN | EEE_TX_EN); + config &= ~EEE10_EN; + } + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data); + ocp_reg_write(tp, OCP_EEE_CFG, config); +} + +static void r8153b_eee_en(struct r8152 *tp, bool enable) +{ + r8153_eee_en(tp, enable); + + if (enable) + r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_EEE, 0); + else + r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_EEE); +} + +static void rtl_eee_enable(struct r8152 *tp, bool enable) +{ + switch (tp->version) { + case RTL_VER_01: + case RTL_VER_02: + case RTL_VER_07: + if (enable) { + r8152_eee_en(tp, true); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + tp->eee_adv); + } else { + r8152_eee_en(tp, false); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + } + break; + case RTL_VER_03: + case RTL_VER_04: + case RTL_VER_05: + case RTL_VER_06: + if (enable) { + r8153_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } else { + r8153_eee_en(tp, false); + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; + case RTL_VER_08: + case RTL_VER_09: + if (enable) { + r8153b_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } else { + r8153b_eee_en(tp, false); + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; + default: + break; } } @@ -3231,7 +3292,7 @@ static void rtl8152_disable(struct r8152 *tp) static void r8152b_hw_phy_cfg(struct r8152 *tp) { - r8152b_enable_eee(tp); + rtl_eee_enable(tp, tp->eee_en); r8152_aldps_en(tp, true); r8152b_enable_fc(tp); @@ -3425,36 +3486,6 @@ static void r8153b_aldps_en(struct r8152 *tp, bool enable) r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_ALDPS); } -static void r8153_eee_en(struct r8152 *tp, bool enable) -{ - u32 ocp_data; - u16 config; - - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - config = ocp_reg_read(tp, OCP_EEE_CFG); - - if (enable) { - ocp_data |= EEE_RX_EN | EEE_TX_EN; - config |= EEE10_EN; - } else { - ocp_data &= ~(EEE_RX_EN | EEE_TX_EN); - config &= ~EEE10_EN; - } - - ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data); - ocp_reg_write(tp, OCP_EEE_CFG, config); -} - -static void r8153b_eee_en(struct r8152 *tp, bool enable) -{ - r8153_eee_en(tp, enable); - - if (enable) - r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_EEE, 0); - else - r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_EEE); -} - static void r8153b_enable_fc(struct r8152 *tp) { r8152b_enable_fc(tp); @@ -3470,8 +3501,7 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) r8153_aldps_en(tp, false); /* disable EEE before updating the PHY parameters */ - r8153_eee_en(tp, false); - ocp_reg_write(tp, OCP_EEE_ADV, 0); + rtl_eee_enable(tp, false); if (tp->version == RTL_VER_03) { data = ocp_reg_read(tp, OCP_EEE_CFG); @@ -3502,10 +3532,8 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) sram_write(tp, SRAM_10M_AMP1, 0x00af); sram_write(tp, SRAM_10M_AMP2, 0x0208); - if (tp->eee_en) { - r8153_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); - } + if (tp->eee_en) + rtl_eee_enable(tp, true); r8153_aldps_en(tp, true); r8152b_enable_fc(tp); @@ -3545,8 +3573,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) r8153b_aldps_en(tp, false); /* disable EEE before updating the PHY parameters */ - r8153b_eee_en(tp, false); - ocp_reg_write(tp, OCP_EEE_ADV, 0); + rtl_eee_enable(tp, false); r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); @@ -3608,10 +3635,8 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) r8153b_ups_flags_w1w0(tp, ups_flags, 0); - if (tp->eee_en) { - r8153b_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); - } + if (tp->eee_en) + rtl_eee_enable(tp, true); r8153b_aldps_en(tp, true); r8153b_enable_fc(tp); @@ -4930,12 +4955,7 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee) tp->eee_en = eee->eee_enabled; tp->eee_adv = val; - r8152_eee_en(tp, eee->eee_enabled); - - if (eee->eee_enabled) - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); - else - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + rtl_eee_enable(tp, tp->eee_en); return 0; } @@ -4963,40 +4983,6 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee) return 0; } -static int r8153_set_eee(struct r8152 *tp, struct ethtool_eee *eee) -{ - u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - tp->eee_en = eee->eee_enabled; - tp->eee_adv = val; - - r8153_eee_en(tp, eee->eee_enabled); - - if (eee->eee_enabled) - ocp_reg_write(tp, OCP_EEE_ADV, val); - else - ocp_reg_write(tp, OCP_EEE_ADV, 0); - - return 0; -} - -static int r8153b_set_eee(struct r8152 *tp, struct ethtool_eee *eee) -{ - u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - tp->eee_en = eee->eee_enabled; - tp->eee_adv = val; - - r8153b_eee_en(tp, eee->eee_enabled); - - if (eee->eee_enabled) - ocp_reg_write(tp, OCP_EEE_ADV, val); - else - ocp_reg_write(tp, OCP_EEE_ADV, 0); - - return 0; -} - static int rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) { @@ -5382,7 +5368,7 @@ static int rtl_ops_init(struct r8152 *tp) ops->down = rtl8153_down; ops->unload = rtl8153_unload; ops->eee_get = r8153_get_eee; - ops->eee_set = r8153_set_eee; + ops->eee_set = r8152_set_eee; ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153_hw_phy_cfg; ops->autosuspend_en = rtl8153_runtime_enable; @@ -5400,7 +5386,7 @@ static int rtl_ops_init(struct r8152 *tp) ops->down = rtl8153b_down; ops->unload = rtl8153b_unload; ops->eee_get = r8153_get_eee; - ops->eee_set = r8153b_set_eee; + ops->eee_set = r8152_set_eee; ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153b_hw_phy_cfg; ops->autosuspend_en = rtl8153b_runtime_enable; -- GitLab From ae6c4c70dfd184f69a24342c09678fb161a7cb4c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 18:19:27 +0300 Subject: [PATCH 4279/7155] leds: max77650: Switch to fwnode property API Switch the max77650 from OF to the fwnode property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 5a14f9775b0e..4c2d0b3c6dad 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -62,7 +62,7 @@ static int max77650_led_brightness_set(struct led_classdev *cdev, static int max77650_led_probe(struct platform_device *pdev) { - struct device_node *of_node, *child; + struct fwnode_handle *child; struct max77650_led *leds, *led; struct device *dev; struct regmap *map; @@ -71,10 +71,6 @@ static int max77650_led_probe(struct platform_device *pdev) u32 reg; dev = &pdev->dev; - of_node = dev->of_node; - - if (!of_node) - return -ENODEV; leds = devm_kcalloc(dev, sizeof(*leds), MAX77650_LED_NUM_LEDS, GFP_KERNEL); @@ -85,12 +81,12 @@ static int max77650_led_probe(struct platform_device *pdev) if (!map) return -ENODEV; - num_leds = of_get_child_count(of_node); + num_leds = device_get_child_node_count(dev); if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS) return -ENODEV; - for_each_child_of_node(of_node, child) { - rv = of_property_read_u32(child, "reg", ®); + device_for_each_child_node(dev, child) { + rv = fwnode_property_read_u32(child, "reg", ®); if (rv || reg >= MAX77650_LED_NUM_LEDS) { rv = -EINVAL; goto err_node_put; @@ -103,8 +99,8 @@ static int max77650_led_probe(struct platform_device *pdev) led->cdev.brightness_set_blocking = max77650_led_brightness_set; led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS; - label = of_get_property(child, "label", NULL); - if (!label) { + rv = fwnode_property_read_string(child, "label", &label); + if (rv) { led->cdev.name = "max77650::"; } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, @@ -115,8 +111,8 @@ static int max77650_led_probe(struct platform_device *pdev) } } - of_property_read_string(child, "linux,default-trigger", - &led->cdev.default_trigger); + fwnode_property_read_string(child, "linux,default-trigger", + &led->cdev.default_trigger); rv = devm_led_classdev_register(dev, &led->cdev); if (rv) @@ -135,7 +131,7 @@ static int max77650_led_probe(struct platform_device *pdev) MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); err_node_put: - of_node_put(child); + fwnode_handle_put(child); return rv; } -- GitLab From fd81d7e946c6bdb86dbf0bd88fee3e1a545e7979 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 18:19:28 +0300 Subject: [PATCH 4280/7155] leds: Switch to use fwnode instead of be stuck with OF one There is no need to be stuck with OF node when we may use agnostic firmware node instead. It allows users to get property if needed independently of provider. Note, some OF parts are left because %pfw [1] is in progress. [1]: https://lore.kernel.org/patchwork/cover/1054863/ Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/led-class.c | 4 ++-- drivers/leds/led-core.c | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index d231240c2047..052c7571e188 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -277,7 +277,7 @@ int led_classdev_register_ext(struct device *parent, return PTR_ERR(led_cdev->dev); } if (init_data && init_data->fwnode) - led_cdev->dev->of_node = to_of_node(init_data->fwnode); + led_cdev->dev->fwnode = init_data->fwnode; if (ret) dev_warn(parent, "Led %s renamed to %s due to name collision", diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index f0c1c403f678..f1f718dbe0f8 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -324,14 +324,11 @@ EXPORT_SYMBOL_GPL(led_update_brightness); u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size) { - struct device_node *np = dev_of_node(led_cdev->dev); + struct fwnode_handle *fwnode = led_cdev->dev->fwnode; u32 *pattern; int count; - if (!np) - return NULL; - - count = of_property_count_u32_elems(np, "led-pattern"); + count = fwnode_property_count_u32(fwnode, "led-pattern"); if (count < 0) return NULL; @@ -339,7 +336,7 @@ u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size) if (!pattern) return NULL; - if (of_property_read_u32_array(np, "led-pattern", pattern, count)) { + if (fwnode_property_read_u32_array(fwnode, "led-pattern", pattern, count)) { kfree(pattern); return NULL; } -- GitLab From c7a42eb49212f93a800560662d17d5293960d3c3 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Fri, 23 Aug 2019 19:33:03 +0800 Subject: [PATCH 4281/7155] net: ipv6: fix listify ip6_rcv_finish in case of forwarding We need a similar fix for ipv6 as Commit 0761680d5215 ("net: ipv4: fix listify ip_rcv_finish in case of forwarding") does for ipv4. This issue can be reprocuded by syzbot since Commit 323ebb61e32b ("net: use listified RX for handling GRO_NORMAL skbs") on net-next. The call trace was: kernel BUG at include/linux/skbuff.h:2225! RIP: 0010:__skb_pull include/linux/skbuff.h:2225 [inline] RIP: 0010:skb_pull+0xea/0x110 net/core/skbuff.c:1902 Call Trace: sctp_inq_pop+0x2f1/0xd80 net/sctp/inqueue.c:202 sctp_endpoint_bh_rcv+0x184/0x8d0 net/sctp/endpointola.c:385 sctp_inq_push+0x1e4/0x280 net/sctp/inqueue.c:80 sctp_rcv+0x2807/0x3590 net/sctp/input.c:256 sctp6_rcv+0x17/0x30 net/sctp/ipv6.c:1049 ip6_protocol_deliver_rcu+0x2fe/0x1660 net/ipv6/ip6_input.c:397 ip6_input_finish+0x84/0x170 net/ipv6/ip6_input.c:438 NF_HOOK include/linux/netfilter.h:305 [inline] NF_HOOK include/linux/netfilter.h:299 [inline] ip6_input+0xe4/0x3f0 net/ipv6/ip6_input.c:447 dst_input include/net/dst.h:442 [inline] ip6_sublist_rcv_finish+0x98/0x1e0 net/ipv6/ip6_input.c:84 ip6_list_rcv_finish net/ipv6/ip6_input.c:118 [inline] ip6_sublist_rcv+0x80c/0xcf0 net/ipv6/ip6_input.c:282 ipv6_list_rcv+0x373/0x4b0 net/ipv6/ip6_input.c:316 __netif_receive_skb_list_ptype net/core/dev.c:5049 [inline] __netif_receive_skb_list_core+0x5fc/0x9d0 net/core/dev.c:5097 __netif_receive_skb_list net/core/dev.c:5149 [inline] netif_receive_skb_list_internal+0x7eb/0xe60 net/core/dev.c:5244 gro_normal_list.part.0+0x1e/0xb0 net/core/dev.c:5757 gro_normal_list net/core/dev.c:5755 [inline] gro_normal_one net/core/dev.c:5769 [inline] napi_frags_finish net/core/dev.c:5782 [inline] napi_gro_frags+0xa6a/0xea0 net/core/dev.c:5855 tun_get_user+0x2e98/0x3fa0 drivers/net/tun.c:1974 tun_chr_write_iter+0xbd/0x156 drivers/net/tun.c:2020 Fixes: d8269e2cbf90 ("net: ipv6: listify ipv6_rcv() and ip6_rcv_finish()") Fixes: 323ebb61e32b ("net: use listified RX for handling GRO_NORMAL skbs") Reported-by: syzbot+eb349eeee854e389c36d@syzkaller.appspotmail.com Reported-by: syzbot+4a0643a653ac375612d1@syzkaller.appspotmail.com Signed-off-by: Xin Long Acked-by: Edward Cree Signed-off-by: David S. Miller --- net/ipv6/ip6_input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index fa014d5f1732..d432d0011c16 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -80,8 +80,10 @@ static void ip6_sublist_rcv_finish(struct list_head *head) { struct sk_buff *skb, *next; - list_for_each_entry_safe(skb, next, head, list) + list_for_each_entry_safe(skb, next, head, list) { + skb_list_del_init(skb); dst_input(skb); + } } static void ip6_list_rcv_finish(struct net *net, struct sock *sk, -- GitLab From 87cade2997c9210cfeb625957e44b865a89d0c13 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Fri, 23 Aug 2019 15:34:47 +0300 Subject: [PATCH 4282/7155] net/mlx5: Fix return code in case of hyperv wrong size read Return code value could be non deterministic in case of wrong size read. With this patch, if such error occurs, set rc to be -EIO. In addition, mlx5_hv_config_common() supports reading of HV_CONFIG_BLOCK_SIZE_MAX bytes only, fix to early return error with bad input. Fixes: 913d14e86657 ("net/mlx5: Add wrappers for HyperV PCIe operations") Reported-by: Leon Romanovsky Signed-off-by: Eran Ben Elisha Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c index cf08d02703fb..583dc7e2aca8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c @@ -12,7 +12,7 @@ static int mlx5_hv_config_common(struct mlx5_core_dev *dev, void *buf, int len, int bytes_returned; int block_id; - if (offset % HV_CONFIG_BLOCK_SIZE_MAX || len % HV_CONFIG_BLOCK_SIZE_MAX) + if (offset % HV_CONFIG_BLOCK_SIZE_MAX || len != HV_CONFIG_BLOCK_SIZE_MAX) return -EINVAL; block_id = offset / HV_CONFIG_BLOCK_SIZE_MAX; @@ -25,8 +25,8 @@ static int mlx5_hv_config_common(struct mlx5_core_dev *dev, void *buf, int len, HV_CONFIG_BLOCK_SIZE_MAX, block_id); /* Make sure len bytes were read successfully */ - if (read) - rc |= !(len == bytes_returned); + if (read && !rc && len != bytes_returned) + rc = -EIO; if (rc) { mlx5_core_err(dev, "Failed to %s hv config, err = %d, len = %d, offset = %d\n", -- GitLab From bf1867db9b850fff2dd54a1a117a684a10b8cd90 Mon Sep 17 00:00:00 2001 From: Dag Moxnes Date: Fri, 23 Aug 2019 16:03:18 +0200 Subject: [PATCH 4283/7155] net/rds: Whitelist rdma_cookie and rx_tstamp for usercopy Add the RDMA cookie and RX timestamp to the usercopy whitelist. After the introduction of hardened usercopy whitelisting (https://lwn.net/Articles/727322/), a warning is displayed when the RDMA cookie or RX timestamp is copied to userspace: kernel: WARNING: CPU: 3 PID: 5750 at mm/usercopy.c:81 usercopy_warn+0x8e/0xa6 [...] kernel: Call Trace: kernel: __check_heap_object+0xb8/0x11b kernel: __check_object_size+0xe3/0x1bc kernel: put_cmsg+0x95/0x115 kernel: rds_recvmsg+0x43d/0x620 [rds] kernel: sock_recvmsg+0x43/0x4a kernel: ___sys_recvmsg+0xda/0x1e6 kernel: ? __handle_mm_fault+0xcae/0xf79 kernel: __sys_recvmsg+0x51/0x8a kernel: SyS_recvmsg+0x12/0x1c kernel: do_syscall_64+0x79/0x1ae When the whitelisting feature was introduced, the memory for the RDMA cookie and RX timestamp in RDS was not added to the whitelist, causing the warning above. Signed-off-by: Dag Moxnes Tested-by: Jenny Acked-by: Santosh Shilimkar Signed-off-by: David S. Miller --- net/rds/ib_recv.c | 11 ++++++++--- net/rds/rds.h | 9 +++++++-- net/rds/recv.c | 22 ++++++++++++---------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 1a8a4a760b84..a0f99bbf362c 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -1048,9 +1048,14 @@ int rds_ib_recv_init(void) si_meminfo(&si); rds_ib_sysctl_max_recv_allocation = si.totalram / 3 * PAGE_SIZE / RDS_FRAG_SIZE; - rds_ib_incoming_slab = kmem_cache_create("rds_ib_incoming", - sizeof(struct rds_ib_incoming), - 0, SLAB_HWCACHE_ALIGN, NULL); + rds_ib_incoming_slab = + kmem_cache_create_usercopy("rds_ib_incoming", + sizeof(struct rds_ib_incoming), + 0, SLAB_HWCACHE_ALIGN, + offsetof(struct rds_ib_incoming, + ii_inc.i_usercopy), + sizeof(struct rds_inc_usercopy), + NULL); if (!rds_ib_incoming_slab) goto out; diff --git a/net/rds/rds.h b/net/rds/rds.h index ad605fd61655..53e86911773a 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -271,6 +271,12 @@ struct rds_ext_header_rdma_dest { #define RDS_MSG_RX_END 2 #define RDS_MSG_RX_CMSG 3 +/* The following values are whitelisted for usercopy */ +struct rds_inc_usercopy { + rds_rdma_cookie_t rdma_cookie; + ktime_t rx_tstamp; +}; + struct rds_incoming { refcount_t i_refcount; struct list_head i_item; @@ -280,8 +286,7 @@ struct rds_incoming { unsigned long i_rx_jiffies; struct in6_addr i_saddr; - rds_rdma_cookie_t i_rdma_cookie; - ktime_t i_rx_tstamp; + struct rds_inc_usercopy i_usercopy; u64 i_rx_lat_trace[RDS_RX_MAX_TRACES]; }; diff --git a/net/rds/recv.c b/net/rds/recv.c index 853de4876088..7e451c82595b 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -47,8 +47,8 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, INIT_LIST_HEAD(&inc->i_item); inc->i_conn = conn; inc->i_saddr = *saddr; - inc->i_rdma_cookie = 0; - inc->i_rx_tstamp = ktime_set(0, 0); + inc->i_usercopy.rdma_cookie = 0; + inc->i_usercopy.rx_tstamp = ktime_set(0, 0); memset(inc->i_rx_lat_trace, 0, sizeof(inc->i_rx_lat_trace)); } @@ -62,8 +62,8 @@ void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp, inc->i_conn = cp->cp_conn; inc->i_conn_path = cp; inc->i_saddr = *saddr; - inc->i_rdma_cookie = 0; - inc->i_rx_tstamp = ktime_set(0, 0); + inc->i_usercopy.rdma_cookie = 0; + inc->i_usercopy.rx_tstamp = ktime_set(0, 0); } EXPORT_SYMBOL_GPL(rds_inc_path_init); @@ -186,7 +186,7 @@ static void rds_recv_incoming_exthdrs(struct rds_incoming *inc, struct rds_sock case RDS_EXTHDR_RDMA_DEST: /* We ignore the size for now. We could stash it * somewhere and use it for error checking. */ - inc->i_rdma_cookie = rds_rdma_make_cookie( + inc->i_usercopy.rdma_cookie = rds_rdma_make_cookie( be32_to_cpu(buffer.rdma_dest.h_rdma_rkey), be32_to_cpu(buffer.rdma_dest.h_rdma_offset)); @@ -380,7 +380,7 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, be32_to_cpu(inc->i_hdr.h_len), inc->i_hdr.h_dport); if (sock_flag(sk, SOCK_RCVTSTAMP)) - inc->i_rx_tstamp = ktime_get_real(); + inc->i_usercopy.rx_tstamp = ktime_get_real(); rds_inc_addref(inc); inc->i_rx_lat_trace[RDS_MSG_RX_END] = local_clock(); list_add_tail(&inc->i_item, &rs->rs_recv_queue); @@ -540,16 +540,18 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg, { int ret = 0; - if (inc->i_rdma_cookie) { + if (inc->i_usercopy.rdma_cookie) { ret = put_cmsg(msg, SOL_RDS, RDS_CMSG_RDMA_DEST, - sizeof(inc->i_rdma_cookie), &inc->i_rdma_cookie); + sizeof(inc->i_usercopy.rdma_cookie), + &inc->i_usercopy.rdma_cookie); if (ret) goto out; } - if ((inc->i_rx_tstamp != 0) && + if ((inc->i_usercopy.rx_tstamp != 0) && sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) { - struct __kernel_old_timeval tv = ns_to_kernel_old_timeval(inc->i_rx_tstamp); + struct __kernel_old_timeval tv = + ns_to_kernel_old_timeval(inc->i_usercopy.rx_tstamp); if (!sock_flag(rds_rs_to_sk(rs), SOCK_TSTAMP_NEW)) { ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, -- GitLab From bd1200b79510a68554890af2f48d92be6eb1daf8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 23 Aug 2019 18:47:21 +0300 Subject: [PATCH 4284/7155] drop_monitor: Make timestamps y2038 safe Timestamps are currently communicated to user space as 'struct timespec', which is not considered y2038 safe since it uses a 32-bit signed value for seconds. Fix this while the API is still not part of any official kernel release by using 64-bit nanoseconds timestamps instead. Fixes: ca30707dee2b ("drop_monitor: Add packet alert mode") Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops") Signed-off-by: Ido Schimmel Acked-by: Neil Horman Signed-off-by: David S. Miller --- include/uapi/linux/net_dropmon.h | 2 +- net/core/drop_monitor.c | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 75a35dccb675..8bf79a9eb234 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -75,7 +75,7 @@ enum net_dm_attr { NET_DM_ATTR_PC, /* u64 */ NET_DM_ATTR_SYMBOL, /* string */ NET_DM_ATTR_IN_PORT, /* nested */ - NET_DM_ATTR_TIMESTAMP, /* struct timespec */ + NET_DM_ATTR_TIMESTAMP, /* u64 */ NET_DM_ATTR_PROTO, /* u16 */ NET_DM_ATTR_PAYLOAD, /* binary */ NET_DM_ATTR_PAD, diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index bfc024024aa3..cc60cc22e2db 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -552,7 +552,7 @@ static size_t net_dm_packet_report_size(size_t payload_len) /* NET_DM_ATTR_IN_PORT */ net_dm_in_port_size() + /* NET_DM_ATTR_TIMESTAMP */ - nla_total_size(sizeof(struct timespec)) + + nla_total_size(sizeof(u64)) + /* NET_DM_ATTR_ORIG_LEN */ nla_total_size(sizeof(u32)) + /* NET_DM_ATTR_PROTO */ @@ -592,7 +592,6 @@ static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb, u64 pc = (u64)(uintptr_t) NET_DM_SKB_CB(skb)->pc; char buf[NET_DM_MAX_SYMBOL_LEN]; struct nlattr *attr; - struct timespec ts; void *hdr; int rc; @@ -615,8 +614,8 @@ static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb, if (rc) goto nla_put_failure; - if (ktime_to_timespec_cond(skb->tstamp, &ts) && - nla_put(msg, NET_DM_ATTR_TIMESTAMP, sizeof(ts), &ts)) + if (nla_put_u64_64bit(msg, NET_DM_ATTR_TIMESTAMP, + ktime_to_ns(skb->tstamp), NET_DM_ATTR_PAD)) goto nla_put_failure; if (nla_put_u32(msg, NET_DM_ATTR_ORIG_LEN, skb->len)) @@ -716,7 +715,7 @@ net_dm_hw_packet_report_size(size_t payload_len, /* NET_DM_ATTR_IN_PORT */ net_dm_in_port_size() + /* NET_DM_ATTR_TIMESTAMP */ - nla_total_size(sizeof(struct timespec)) + + nla_total_size(sizeof(u64)) + /* NET_DM_ATTR_ORIG_LEN */ nla_total_size(sizeof(u32)) + /* NET_DM_ATTR_PROTO */ @@ -730,7 +729,6 @@ static int net_dm_hw_packet_report_fill(struct sk_buff *msg, { struct net_dm_hw_metadata *hw_metadata; struct nlattr *attr; - struct timespec ts; void *hdr; hw_metadata = NET_DM_SKB_CB(skb)->hw_metadata; @@ -761,8 +759,8 @@ static int net_dm_hw_packet_report_fill(struct sk_buff *msg, goto nla_put_failure; } - if (ktime_to_timespec_cond(skb->tstamp, &ts) && - nla_put(msg, NET_DM_ATTR_TIMESTAMP, sizeof(ts), &ts)) + if (nla_put_u64_64bit(msg, NET_DM_ATTR_TIMESTAMP, + ktime_to_ns(skb->tstamp), NET_DM_ATTR_PAD)) goto nla_put_failure; if (nla_put_u32(msg, NET_DM_ATTR_ORIG_LEN, skb->len)) -- GitLab From d4ed7463d02aef4b2270ec2a680813cd8b17def7 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 23 Aug 2019 20:07:26 +0200 Subject: [PATCH 4285/7155] r8169: fix DMA issue on MIPS platform As reported by Aaro this patch causes network problems on MIPS Loongson platform. Therefore revert it. Fixes: f072218cca5b ("r8169: remove not needed call to dma_sync_single_for_device") Signed-off-by: Heiner Kallweit Reported-by: Aaro Koskinen Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 910944120a65..6182e7d33e01 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5822,6 +5822,10 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget skb->tail += pkt_size; skb->len = pkt_size; + dma_sync_single_for_device(tp_to_dev(tp), + le64_to_cpu(desc->addr), + pkt_size, DMA_FROM_DEVICE); + rtl8169_rx_csum(skb, status); skb->protocol = eth_type_trans(skb, dev); -- GitLab From 62bacb06b9f08965c4ef10e17875450490c948c0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:00 +0300 Subject: [PATCH 4286/7155] PM / devfreq: tegra: Fix kHz to Hz conversion The kHz to Hz is incorrectly converted in a few places in the code, this results in a wrong frequency being calculated because devfreq core uses OPP frequencies that are given in Hz to clamp the rate, while tegra-devfreq gives to the core value in kHz and then it also expects to receive value in kHz from the core. In a result memory freq is always set to a value which is close to ULONG_MAX because of the bug. Hence the EMC frequency is always capped to the maximum and the driver doesn't do anything useful. This patch was tested on Tegra30 and Tegra124 SoC's, EMC frequency scaling works properly now. Cc: # 4.14+ Tested-by: Steev Klimaszewski Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 35c38aad8b4f..cd15c96dd27f 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -474,11 +474,11 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq, { struct tegra_devfreq *tegra = dev_get_drvdata(dev); struct dev_pm_opp *opp; - unsigned long rate = *freq * KHZ; + unsigned long rate; - opp = devfreq_recommended_opp(dev, &rate, flags); + opp = devfreq_recommended_opp(dev, freq, flags); if (IS_ERR(opp)) { - dev_err(dev, "Failed to find opp for %lu KHz\n", *freq); + dev_err(dev, "Failed to find opp for %lu Hz\n", *freq); return PTR_ERR(opp); } rate = dev_pm_opp_get_freq(opp); @@ -487,8 +487,6 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq, clk_set_min_rate(tegra->emc_clock, rate); clk_set_rate(tegra->emc_clock, 0); - *freq = rate; - return 0; } @@ -498,7 +496,7 @@ static int tegra_devfreq_get_dev_status(struct device *dev, struct tegra_devfreq *tegra = dev_get_drvdata(dev); struct tegra_devfreq_device *actmon_dev; - stat->current_frequency = tegra->cur_freq; + stat->current_frequency = tegra->cur_freq * KHZ; /* To be used by the tegra governor */ stat->private_data = tegra; @@ -553,7 +551,7 @@ static int tegra_governor_get_target(struct devfreq *devfreq, target_freq = max(target_freq, dev->target_freq); } - *freq = target_freq; + *freq = target_freq * KHZ; return 0; } -- GitLab From efe9043db49649c1f6c21df8a3860689c2035911 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:01 +0300 Subject: [PATCH 4287/7155] PM / devfreq: tegra: Replace readl-writel with relaxed versions There is no need to insert memory barrier on each readl/writel invocation, hence use the relaxed versions. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index cd15c96dd27f..9d9bfef1465d 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -179,23 +179,23 @@ static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = { static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset) { - return readl(tegra->regs + offset); + return readl_relaxed(tegra->regs + offset); } static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset) { - writel(val, tegra->regs + offset); + writel_relaxed(val, tegra->regs + offset); } static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset) { - return readl(dev->regs + offset); + return readl_relaxed(dev->regs + offset); } static void device_writel(struct tegra_devfreq_device *dev, u32 val, u32 offset) { - writel(val, dev->regs + offset); + writel_relaxed(val, dev->regs + offset); } static unsigned long do_percent(unsigned long val, unsigned int pct) -- GitLab From ed2a8dd22a752af60282af38a47d26b227f772a7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:02 +0300 Subject: [PATCH 4288/7155] PM / devfreq: tegra: Replace write memory barrier with the read barrier The write memory barrier isn't needed because the BUS buffer is flushed by read after write that happens after the removed wmb(), we will also use readl() instead of the relaxed version to ensure that read is indeed completed. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 9d9bfef1465d..986f3dfbcab9 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -231,8 +231,7 @@ static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra, static void actmon_write_barrier(struct tegra_devfreq *tegra) { /* ensure the update has reached the ACTMON */ - wmb(); - actmon_readl(tegra, ACTMON_GLB_STATUS); + readl(tegra->regs + ACTMON_GLB_STATUS); } static void actmon_isr_device(struct tegra_devfreq *tegra, -- GitLab From 30af44fae8bdccfb21a45dfb4029f954f618d2e3 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:03 +0300 Subject: [PATCH 4289/7155] PM / devfreq: tegra: Don't ignore clk errors The clk_set_min_rate() could fail and in this case clk_set_rate() sets rate to 0, which may drop EMC rate to minimum and make machine very difficult to use. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 986f3dfbcab9..325443f67725 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -472,8 +472,10 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) { struct tegra_devfreq *tegra = dev_get_drvdata(dev); + struct devfreq *devfreq = tegra->devfreq; struct dev_pm_opp *opp; unsigned long rate; + int err; opp = devfreq_recommended_opp(dev, freq, flags); if (IS_ERR(opp)) { @@ -483,10 +485,20 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq, rate = dev_pm_opp_get_freq(opp); dev_pm_opp_put(opp); - clk_set_min_rate(tegra->emc_clock, rate); - clk_set_rate(tegra->emc_clock, 0); + err = clk_set_min_rate(tegra->emc_clock, rate); + if (err) + return err; + + err = clk_set_rate(tegra->emc_clock, 0); + if (err) + goto restore_min_rate; return 0; + +restore_min_rate: + clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq); + + return err; } static int tegra_devfreq_get_dev_status(struct device *dev, -- GitLab From b061312f4bca20ed60246f7fe2e1ffa247ce5bf7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:04 +0300 Subject: [PATCH 4290/7155] PM / devfreq: tegra: Don't set EMC clock rate to maximum on probe There is no real benefit from doing so, hence let's drop that rate setting for consistency. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 325443f67725..6780fb41ed12 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -641,8 +641,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev) return PTR_ERR(tegra->emc_clock); } - clk_set_rate(tegra->emc_clock, ULONG_MAX); - tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb; err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); if (err) { -- GitLab From dd3f2616bb99f1d2bfd0536074824722e953f6be Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:05 +0300 Subject: [PATCH 4291/7155] PM / devfreq: tegra: Drop primary interrupt handler There is no real need in the primary interrupt handler, hence move everything to the secondary (threaded) handler. In a result locking is consistent now and there are no potential races with the interrupt handler because it is protected with the devfreq's mutex. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 55 +++++++++++---------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 6780fb41ed12..b923d216a4a9 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -132,7 +132,6 @@ static struct tegra_devfreq_device_config actmon_device_configs[] = { struct tegra_devfreq_device { const struct tegra_devfreq_device_config *config; void __iomem *regs; - spinlock_t lock; /* Average event count sampled in the last interrupt */ u32 avg_count; @@ -237,11 +236,8 @@ static void actmon_write_barrier(struct tegra_devfreq *tegra) static void actmon_isr_device(struct tegra_devfreq *tegra, struct tegra_devfreq_device *dev) { - unsigned long flags; u32 intr_status, dev_ctrl; - spin_lock_irqsave(&dev->lock, flags); - dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT); tegra_devfreq_update_avg_wmark(tegra, dev); @@ -290,26 +286,6 @@ static void actmon_isr_device(struct tegra_devfreq *tegra, device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS); actmon_write_barrier(tegra); - - spin_unlock_irqrestore(&dev->lock, flags); -} - -static irqreturn_t actmon_isr(int irq, void *data) -{ - struct tegra_devfreq *tegra = data; - bool handled = false; - unsigned int i; - u32 val; - - val = actmon_readl(tegra, ACTMON_GLB_STATUS); - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { - if (val & tegra->devices[i].config->irq_mask) { - actmon_isr_device(tegra, tegra->devices + i); - handled = true; - } - } - - return handled ? IRQ_WAKE_THREAD : IRQ_NONE; } static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra, @@ -336,15 +312,12 @@ static void actmon_update_target(struct tegra_devfreq *tegra, unsigned long cpu_freq = 0; unsigned long static_cpu_emc_freq = 0; unsigned int avg_sustain_coef; - unsigned long flags; if (dev->config->avg_dependency_threshold) { cpu_freq = cpufreq_get(0); static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq); } - spin_lock_irqsave(&dev->lock, flags); - dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD; avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold; dev->target_freq = do_percent(dev->target_freq, avg_sustain_coef); @@ -352,19 +325,31 @@ static void actmon_update_target(struct tegra_devfreq *tegra, if (dev->avg_count >= dev->config->avg_dependency_threshold) dev->target_freq = max(dev->target_freq, static_cpu_emc_freq); - - spin_unlock_irqrestore(&dev->lock, flags); } static irqreturn_t actmon_thread_isr(int irq, void *data) { struct tegra_devfreq *tegra = data; + bool handled = false; + unsigned int i; + u32 val; mutex_lock(&tegra->devfreq->lock); - update_devfreq(tegra->devfreq); + + val = actmon_readl(tegra, ACTMON_GLB_STATUS); + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { + if (val & tegra->devices[i].config->irq_mask) { + actmon_isr_device(tegra, tegra->devices + i); + handled = true; + } + } + + if (handled) + update_devfreq(tegra->devfreq); + mutex_unlock(&tegra->devfreq->lock); - return IRQ_HANDLED; + return handled ? IRQ_HANDLED : IRQ_NONE; } static int tegra_actmon_rate_notify_cb(struct notifier_block *nb, @@ -374,7 +359,6 @@ static int tegra_actmon_rate_notify_cb(struct notifier_block *nb, struct tegra_devfreq *tegra; struct tegra_devfreq_device *dev; unsigned int i; - unsigned long flags; if (action != POST_RATE_CHANGE) return NOTIFY_OK; @@ -386,9 +370,7 @@ static int tegra_actmon_rate_notify_cb(struct notifier_block *nb, for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { dev = &tegra->devices[i]; - spin_lock_irqsave(&dev->lock, flags); tegra_devfreq_update_wmark(tegra, dev); - spin_unlock_irqrestore(&dev->lock, flags); } actmon_write_barrier(tegra); @@ -670,7 +652,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev) dev = tegra->devices + i; dev->config = actmon_device_configs + i; dev->regs = tegra->regs + dev->config->offset; - spin_lock_init(&dev->lock); tegra_actmon_configure_device(tegra, dev); } @@ -688,8 +669,8 @@ static int tegra_devfreq_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tegra); - err = devm_request_threaded_irq(&pdev->dev, irq, actmon_isr, - actmon_thread_isr, IRQF_SHARED, + err = devm_request_threaded_irq(&pdev->dev, irq, NULL, + actmon_thread_isr, IRQF_ONESHOT, "tegra-devfreq", tegra); if (err) { dev_err(&pdev->dev, "Interrupt request failed\n"); -- GitLab From 7514dd05eaae5b8cf0b2af34f75a048ee023fe2c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:06 +0300 Subject: [PATCH 4292/7155] PM / devfreq: tegra: Properly disable interrupts There is no guarantee that interrupt handling isn't running in parallel with tegra_actmon_disable_interrupts(), hence it is necessary to protect DEV_CTRL register accesses and clear IRQ status with ACTMON's IRQ being disabled in the Interrupt Controller in order to ensure that device interrupt is indeed being disabled. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index b923d216a4a9..d88f81fc99de 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -159,6 +159,8 @@ struct tegra_devfreq { struct notifier_block rate_change_nb; struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)]; + + int irq; }; struct tegra_actmon_emc_ratio { @@ -405,6 +407,8 @@ static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra) u32 val; unsigned int i; + disable_irq(tegra->irq); + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { dev = &tegra->devices[i]; @@ -415,9 +419,14 @@ static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra) val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; device_writel(dev, val, ACTMON_DEV_CTRL); + + device_writel(dev, ACTMON_INTR_STATUS_CLEAR, + ACTMON_DEV_INTR_STATUS); } actmon_write_barrier(tegra); + + enable_irq(tegra->irq); } static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, @@ -592,7 +601,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev) struct resource *res; unsigned int i; unsigned long rate; - int irq; int err; tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); @@ -661,15 +669,16 @@ static int tegra_devfreq_probe(struct platform_device *pdev) dev_pm_opp_add(&pdev->dev, rate, 0); } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); - return irq; + tegra->irq = platform_get_irq(pdev, 0); + if (tegra->irq < 0) { + err = tegra->irq; + dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err); + return err; } platform_set_drvdata(pdev, tegra); - err = devm_request_threaded_irq(&pdev->dev, irq, NULL, + err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL, actmon_thread_isr, IRQF_ONESHOT, "tegra-devfreq", tegra); if (err) { -- GitLab From 8fda5c1fab4f8df22bad43ba93a5ba83594ac256 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:07 +0300 Subject: [PATCH 4293/7155] PM / devfreq: tegra: Clean up driver's probe / remove Reset hardware, disable ACTMON clock, release OPP's and handle all possible error cases correctly, maintaining the correct tear down order. Also use devm_platform_ioremap_resource() which is now available in the kernel. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 83 +++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index d88f81fc99de..7e9145bd3686 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -598,7 +598,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev) { struct tegra_devfreq *tegra; struct tegra_devfreq_device *dev; - struct resource *res; unsigned int i; unsigned long rate; int err; @@ -607,9 +606,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev) if (!tegra) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - tegra->regs = devm_ioremap_resource(&pdev->dev, res); + tegra->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tegra->regs)) return PTR_ERR(tegra->regs); @@ -631,11 +628,10 @@ static int tegra_devfreq_probe(struct platform_device *pdev) return PTR_ERR(tegra->emc_clock); } - tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb; - err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); - if (err) { - dev_err(&pdev->dev, - "Failed to register rate change notifier\n"); + tegra->irq = platform_get_irq(pdev, 0); + if (tegra->irq < 0) { + err = tegra->irq; + dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err); return err; } @@ -666,54 +662,69 @@ static int tegra_devfreq_probe(struct platform_device *pdev) for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) { rate = clk_round_rate(tegra->emc_clock, rate); - dev_pm_opp_add(&pdev->dev, rate, 0); - } - tegra->irq = platform_get_irq(pdev, 0); - if (tegra->irq < 0) { - err = tegra->irq; - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err); - return err; + err = dev_pm_opp_add(&pdev->dev, rate, 0); + if (err) { + dev_err(&pdev->dev, "Failed to add OPP: %d\n", err); + goto remove_opps; + } } platform_set_drvdata(pdev, tegra); + tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb; + err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); + if (err) { + dev_err(&pdev->dev, + "Failed to register rate change notifier\n"); + goto remove_opps; + } + + tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); + tegra->devfreq = devfreq_add_device(&pdev->dev, + &tegra_devfreq_profile, + "tegra_actmon", + NULL); + if (IS_ERR(tegra->devfreq)) { + err = PTR_ERR(tegra->devfreq); + goto unreg_notifier; + } + err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL, actmon_thread_isr, IRQF_ONESHOT, "tegra-devfreq", tegra); if (err) { - dev_err(&pdev->dev, "Interrupt request failed\n"); - return err; + dev_err(&pdev->dev, "Interrupt request failed: %d\n", err); + goto remove_devfreq; } - tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); - tegra->devfreq = devm_devfreq_add_device(&pdev->dev, - &tegra_devfreq_profile, - "tegra_actmon", - NULL); - return 0; + +remove_devfreq: + devfreq_remove_device(tegra->devfreq); + +unreg_notifier: + clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); + +remove_opps: + dev_pm_opp_remove_all_dynamic(&pdev->dev); + + reset_control_reset(tegra->reset); + clk_disable_unprepare(tegra->clock); + + return err; } static int tegra_devfreq_remove(struct platform_device *pdev) { struct tegra_devfreq *tegra = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - u32 val; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { - val = device_readl(&tegra->devices[i], ACTMON_DEV_CTRL); - val &= ~ACTMON_DEV_CTRL_ENB; - device_writel(&tegra->devices[i], val, ACTMON_DEV_CTRL); - } - - actmon_write_barrier(tegra); - devm_free_irq(&pdev->dev, irq, tegra); + devfreq_remove_device(tegra->devfreq); clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); + dev_pm_opp_remove_all_dynamic(&pdev->dev); + reset_control_reset(tegra->reset); clk_disable_unprepare(tegra->clock); return 0; -- GitLab From 151531f79a2daa30141c9fdb23e0cff00195b17a Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:08 +0300 Subject: [PATCH 4294/7155] PM / devfreq: tegra: Avoid inconsistency of current frequency value The frequency value potentially could change in-between. It doesn't cause any real problem at all right now, but that could change in the future. Hence let's avoid the inconsistency. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 7e9145bd3686..f23f7b35863b 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -497,13 +497,15 @@ static int tegra_devfreq_get_dev_status(struct device *dev, { struct tegra_devfreq *tegra = dev_get_drvdata(dev); struct tegra_devfreq_device *actmon_dev; + unsigned long cur_freq; - stat->current_frequency = tegra->cur_freq * KHZ; + cur_freq = READ_ONCE(tegra->cur_freq); /* To be used by the tegra governor */ stat->private_data = tegra; /* The below are to be used by the other governors */ + stat->current_frequency = cur_freq * KHZ; actmon_dev = &tegra->devices[MCALL]; @@ -514,7 +516,7 @@ static int tegra_devfreq_get_dev_status(struct device *dev, stat->busy_time *= 100 / BUS_SATURATION_RATIO; /* Number of cycles in a sampling period */ - stat->total_time = ACTMON_SAMPLING_PERIOD * tegra->cur_freq; + stat->total_time = ACTMON_SAMPLING_PERIOD * cur_freq; stat->busy_time = min(stat->busy_time, stat->total_time); -- GitLab From 386789ebbdd3a204ebe16b7a6277f7a45823549d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:09 +0300 Subject: [PATCH 4295/7155] PM / devfreq: tegra: Mark ACTMON's governor as immutable The ACTMON's governor supports only the Tegra's devfreq device and there is no need to use any other governor, hence let's mark Tegra governor as immutable to permanently stick it with Tegra's devfreq device. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/Kconfig | 1 - drivers/devfreq/tegra-devfreq.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index ba98a4e3ad33..7dd46d44579d 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -95,7 +95,6 @@ config ARM_EXYNOS_BUS_DEVFREQ config ARM_TEGRA_DEVFREQ tristate "Tegra DEVFREQ Driver" depends on ARCH_TEGRA_124_SOC - select DEVFREQ_GOV_SIMPLE_ONDEMAND select PM_OPP help This adds the DEVFREQ driver for the Tegra family of SoCs. diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index f23f7b35863b..bf3fe2e81bc9 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -594,6 +594,7 @@ static struct devfreq_governor tegra_devfreq_governor = { .name = "tegra_actmon", .get_target_freq = tegra_governor_get_target, .event_handler = tegra_governor_event_handler, + .immutable = true, }; static int tegra_devfreq_probe(struct platform_device *pdev) -- GitLab From 5a7e10c89501ec69adc5c39b24d7d69a223bf275 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:10 +0300 Subject: [PATCH 4296/7155] PM / devfreq: tegra: Move governor registration to driver's probe There is no need to register the ACTMON's governor separately from the driver, hence let's move the registration into the driver's probe function for consistency and to make code cleaner a tad. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 43 +++++++++------------------------ 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index bf3fe2e81bc9..d78f29ac138b 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -683,6 +683,12 @@ static int tegra_devfreq_probe(struct platform_device *pdev) goto remove_opps; } + err = devfreq_add_governor(&tegra_devfreq_governor); + if (err) { + dev_err(&pdev->dev, "Failed to add governor: %d\n", err); + goto unreg_notifier; + } + tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock); tegra->devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, @@ -690,7 +696,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev) NULL); if (IS_ERR(tegra->devfreq)) { err = PTR_ERR(tegra->devfreq); - goto unreg_notifier; + goto remove_governor; } err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL, @@ -706,6 +712,9 @@ static int tegra_devfreq_probe(struct platform_device *pdev) remove_devfreq: devfreq_remove_device(tegra->devfreq); +remove_governor: + devfreq_remove_governor(&tegra_devfreq_governor); + unreg_notifier: clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); @@ -723,6 +732,7 @@ static int tegra_devfreq_remove(struct platform_device *pdev) struct tegra_devfreq *tegra = platform_get_drvdata(pdev); devfreq_remove_device(tegra->devfreq); + devfreq_remove_governor(&tegra_devfreq_governor); clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); dev_pm_opp_remove_all_dynamic(&pdev->dev); @@ -748,36 +758,7 @@ static struct platform_driver tegra_devfreq_driver = { .of_match_table = tegra_devfreq_of_match, }, }; - -static int __init tegra_devfreq_init(void) -{ - int ret = 0; - - ret = devfreq_add_governor(&tegra_devfreq_governor); - if (ret) { - pr_err("%s: failed to add governor: %d\n", __func__, ret); - return ret; - } - - ret = platform_driver_register(&tegra_devfreq_driver); - if (ret) - devfreq_remove_governor(&tegra_devfreq_governor); - - return ret; -} -module_init(tegra_devfreq_init) - -static void __exit tegra_devfreq_exit(void) -{ - int ret = 0; - - platform_driver_unregister(&tegra_devfreq_driver); - - ret = devfreq_remove_governor(&tegra_devfreq_governor); - if (ret) - pr_err("%s: failed to remove governor: %d\n", __func__, ret); -} -module_exit(tegra_devfreq_exit) +module_platform_driver(tegra_devfreq_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Tegra devfreq driver"); -- GitLab From 546ff09381370015ffaf4d139aae671a0bb66af2 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:11 +0300 Subject: [PATCH 4297/7155] PM / devfreq: tegra: Reconfigure hardware on governor's restart Move hardware configuration to governor's start/resume methods. This allows to re-initialize hardware counters and reconfigure cleanly if governor was stopped/paused. That is needed because we are not aware of all hardware changes that happened while governor was stopped and the paused state may get out of sync with reality, hence it's better to start with a clean slate after the pause. In a result there is no memory bandwidth starvation after resume from suspend-to-ram that results in display controller underflowing that happens on resume because of improper decision made by devfreq about the required memory frequency. This change also cleans up code a tad by moving hardware-configuration code into a single location. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: MyungJoo Ham --- drivers/devfreq/tegra-devfreq.c | 98 ++++++++++++++------------------- 1 file changed, 40 insertions(+), 58 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index d78f29ac138b..5cddf2199c4e 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -380,55 +380,6 @@ static int tegra_actmon_rate_notify_cb(struct notifier_block *nb, return NOTIFY_OK; } -static void tegra_actmon_enable_interrupts(struct tegra_devfreq *tegra) -{ - struct tegra_devfreq_device *dev; - u32 val; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { - dev = &tegra->devices[i]; - - val = device_readl(dev, ACTMON_DEV_CTRL); - val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; - val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; - val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; - val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; - - device_writel(dev, val, ACTMON_DEV_CTRL); - } - - actmon_write_barrier(tegra); -} - -static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra) -{ - struct tegra_devfreq_device *dev; - u32 val; - unsigned int i; - - disable_irq(tegra->irq); - - for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { - dev = &tegra->devices[i]; - - val = device_readl(dev, ACTMON_DEV_CTRL); - val &= ~ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; - val &= ~ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; - val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; - val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; - - device_writel(dev, val, ACTMON_DEV_CTRL); - - device_writel(dev, ACTMON_INTR_STATUS_CLEAR, - ACTMON_DEV_INTR_STATUS); - } - - actmon_write_barrier(tegra); - - enable_irq(tegra->irq); -} - static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, struct tegra_devfreq_device *dev) { @@ -452,11 +403,47 @@ static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT; val |= (ACTMON_ABOVE_WMARK_WINDOW - 1) << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT; + val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN; + val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN; + val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; + val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN; val |= ACTMON_DEV_CTRL_ENB; device_writel(dev, val, ACTMON_DEV_CTRL); +} + +static void tegra_actmon_start(struct tegra_devfreq *tegra) +{ + unsigned int i; + + disable_irq(tegra->irq); + + actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1, + ACTMON_GLB_PERIOD_CTRL); + + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) + tegra_actmon_configure_device(tegra, &tegra->devices[i]); + + actmon_write_barrier(tegra); + + enable_irq(tegra->irq); +} + +static void tegra_actmon_stop(struct tegra_devfreq *tegra) +{ + unsigned int i; + + disable_irq(tegra->irq); + + for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { + device_writel(&tegra->devices[i], 0x00000000, ACTMON_DEV_CTRL); + device_writel(&tegra->devices[i], ACTMON_INTR_STATUS_CLEAR, + ACTMON_DEV_INTR_STATUS); + } actmon_write_barrier(tegra); + + enable_irq(tegra->irq); } static int tegra_devfreq_target(struct device *dev, unsigned long *freq, @@ -568,22 +555,22 @@ static int tegra_governor_event_handler(struct devfreq *devfreq, switch (event) { case DEVFREQ_GOV_START: devfreq_monitor_start(devfreq); - tegra_actmon_enable_interrupts(tegra); + tegra_actmon_start(tegra); break; case DEVFREQ_GOV_STOP: - tegra_actmon_disable_interrupts(tegra); + tegra_actmon_stop(tegra); devfreq_monitor_stop(devfreq); break; case DEVFREQ_GOV_SUSPEND: - tegra_actmon_disable_interrupts(tegra); + tegra_actmon_stop(tegra); devfreq_monitor_suspend(devfreq); break; case DEVFREQ_GOV_RESUME: devfreq_monitor_resume(devfreq); - tegra_actmon_enable_interrupts(tegra); + tegra_actmon_start(tegra); break; } @@ -652,15 +639,10 @@ static int tegra_devfreq_probe(struct platform_device *pdev) tegra->max_freq = clk_round_rate(tegra->emc_clock, ULONG_MAX) / KHZ; tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ; - actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1, - ACTMON_GLB_PERIOD_CTRL); - for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { dev = tegra->devices + i; dev->config = actmon_device_configs + i; dev->regs = tegra->regs + dev->config->offset; - - tegra_actmon_configure_device(tegra, dev); } for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) { -- GitLab From 1ac347488529939d74f5e2d17948825b5bc6f5e6 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:12 +0300 Subject: [PATCH 4298/7155] PM / devfreq: tegra: Support Tegra30 The devfreq driver can be used on Tegra30 without any code change and it works perfectly fine, the default Tegra124 parameters are good enough for Tegra30. Signed-off-by: Dmitry Osipenko Reviewed-by: Chanwoo Choi [Modified by MyungJoo to depends on Tegra30/114/124/210 only] Signed-off-by: MyungJoo Ham --- drivers/devfreq/Kconfig | 6 ++++-- drivers/devfreq/tegra-devfreq.c | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 7dd46d44579d..8f3f0ed17d85 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -93,8 +93,10 @@ config ARM_EXYNOS_BUS_DEVFREQ This does not yet operate with optimal voltages. config ARM_TEGRA_DEVFREQ - tristate "Tegra DEVFREQ Driver" - depends on ARCH_TEGRA_124_SOC + tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver" + depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \ + ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \ + ARCH_TEGRA_210_SOC select PM_OPP help This adds the DEVFREQ driver for the Tegra family of SoCs. diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index 5cddf2199c4e..a6ba75f4106d 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -726,6 +726,7 @@ static int tegra_devfreq_remove(struct platform_device *pdev) } static const struct of_device_id tegra_devfreq_of_match[] = { + { .compatible = "nvidia,tegra30-actmon" }, { .compatible = "nvidia,tegra124-actmon" }, { }, }; -- GitLab From 35f8dbc727212bc5a49b90961d98f9ef596e2072 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:13 +0300 Subject: [PATCH 4299/7155] PM / devfreq: tegra: Enable COMPILE_TEST for the driver The driver's compilation doesn't have any specific dependencies, hence the COMPILE_TEST option can be supported in Kconfig. Signed-off-by: Dmitry Osipenko Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 8f3f0ed17d85..1091119c1d0a 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -96,7 +96,8 @@ config ARM_TEGRA_DEVFREQ tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver" depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \ ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \ - ARCH_TEGRA_210_SOC + ARCH_TEGRA_210_SOC || \ + COMPILE_TEST select PM_OPP help This adds the DEVFREQ driver for the Tegra family of SoCs. -- GitLab From 23601752911b5dac91207859e0ab77bd8c77545c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:14 +0300 Subject: [PATCH 4300/7155] PM / devfreq: tegra: Rename tegra-devfreq.c to tegra30-devfreq.c In order to reflect that driver serves NVIDIA Tegra30 and later SoC generations, let's rename the driver's source file to "tegra30-devfreq.c". This will make driver files to look more consistent after addition of a driver for Tegra20. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko Signed-off-by: MyungJoo Ham --- drivers/devfreq/Makefile | 2 +- drivers/devfreq/{tegra-devfreq.c => tegra30-devfreq.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/devfreq/{tegra-devfreq.c => tegra30-devfreq.c} (100%) diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 32b8d4d3f12c..47e5aeeebfd1 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o -obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o +obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o # DEVFREQ Event Drivers obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/ diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra30-devfreq.c similarity index 100% rename from drivers/devfreq/tegra-devfreq.c rename to drivers/devfreq/tegra30-devfreq.c -- GitLab From d196175ed8f45248b54bf5c2e7c05ac0e1e97d70 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 2 May 2019 02:38:15 +0300 Subject: [PATCH 4301/7155] PM / devfreq: Introduce driver for NVIDIA Tegra20 Add devfreq driver for NVIDIA Tegra20 SoC's. The driver periodically reads out Memory Controller counters and adjusts memory frequency based on the memory clients activity. Reviewed-by: Chanwoo Choi Signed-off-by: Dmitry Osipenko [Removed MAINTAINERS updates by MyungJoo so that it can be sent elsewhere.] Signed-off-by: MyungJoo Ham --- drivers/devfreq/Kconfig | 10 ++ drivers/devfreq/Makefile | 1 + drivers/devfreq/tegra20-devfreq.c | 212 ++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 drivers/devfreq/tegra20-devfreq.c diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 1091119c1d0a..f3b242987fd9 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -104,6 +104,16 @@ config ARM_TEGRA_DEVFREQ It reads ACTMON counters of memory controllers and adjusts the operating frequencies and voltages with OPP support. +config ARM_TEGRA20_DEVFREQ + tristate "NVIDIA Tegra20 DEVFREQ Driver" + depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST + select DEVFREQ_GOV_SIMPLE_ONDEMAND + select PM_OPP + help + This adds the DEVFREQ driver for the Tegra20 family of SoCs. + It reads Memory Controller counters and adjusts the operating + frequencies and voltages with OPP support. + config ARM_RK3399_DMC_DEVFREQ tristate "ARM RK3399 DMC DEVFREQ Driver" depends on ARCH_ROCKCHIP diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 47e5aeeebfd1..338ae8440db6 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o +obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Drivers obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/ diff --git a/drivers/devfreq/tegra20-devfreq.c b/drivers/devfreq/tegra20-devfreq.c new file mode 100644 index 000000000000..ff82bac9ee4e --- /dev/null +++ b/drivers/devfreq/tegra20-devfreq.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NVIDIA Tegra20 devfreq driver + * + * Copyright (C) 2019 GRATE-DRIVER project + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "governor.h" + +#define MC_STAT_CONTROL 0x90 +#define MC_STAT_EMC_CLOCK_LIMIT 0xa0 +#define MC_STAT_EMC_CLOCKS 0xa4 +#define MC_STAT_EMC_CONTROL 0xa8 +#define MC_STAT_EMC_COUNT 0xb8 + +#define EMC_GATHER_CLEAR (1 << 8) +#define EMC_GATHER_ENABLE (3 << 8) + +struct tegra_devfreq { + struct devfreq *devfreq; + struct clk *emc_clock; + void __iomem *regs; +}; + +static int tegra_devfreq_target(struct device *dev, unsigned long *freq, + u32 flags) +{ + struct tegra_devfreq *tegra = dev_get_drvdata(dev); + struct devfreq *devfreq = tegra->devfreq; + struct dev_pm_opp *opp; + unsigned long rate; + int err; + + opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(opp)) + return PTR_ERR(opp); + + rate = dev_pm_opp_get_freq(opp); + dev_pm_opp_put(opp); + + err = clk_set_min_rate(tegra->emc_clock, rate); + if (err) + return err; + + err = clk_set_rate(tegra->emc_clock, 0); + if (err) + goto restore_min_rate; + + return 0; + +restore_min_rate: + clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq); + + return err; +} + +static int tegra_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + struct tegra_devfreq *tegra = dev_get_drvdata(dev); + + /* + * EMC_COUNT returns number of memory events, that number is lower + * than the number of clocks. Conversion ratio of 1/8 results in a + * bit higher bandwidth than actually needed, it is good enough for + * the time being because drivers don't support requesting minimum + * needed memory bandwidth yet. + * + * TODO: adjust the ratio value once relevant drivers will support + * memory bandwidth management. + */ + stat->busy_time = readl_relaxed(tegra->regs + MC_STAT_EMC_COUNT); + stat->total_time = readl_relaxed(tegra->regs + MC_STAT_EMC_CLOCKS) / 8; + stat->current_frequency = clk_get_rate(tegra->emc_clock); + + writel_relaxed(EMC_GATHER_CLEAR, tegra->regs + MC_STAT_CONTROL); + writel_relaxed(EMC_GATHER_ENABLE, tegra->regs + MC_STAT_CONTROL); + + return 0; +} + +static struct devfreq_dev_profile tegra_devfreq_profile = { + .polling_ms = 500, + .target = tegra_devfreq_target, + .get_dev_status = tegra_devfreq_get_dev_status, +}; + +static struct tegra_mc *tegra_get_memory_controller(void) +{ + struct platform_device *pdev; + struct device_node *np; + struct tegra_mc *mc; + + np = of_find_compatible_node(NULL, NULL, "nvidia,tegra20-mc-gart"); + if (!np) + return ERR_PTR(-ENOENT); + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) + return ERR_PTR(-ENODEV); + + mc = platform_get_drvdata(pdev); + if (!mc) + return ERR_PTR(-EPROBE_DEFER); + + return mc; +} + +static int tegra_devfreq_probe(struct platform_device *pdev) +{ + struct tegra_devfreq *tegra; + struct tegra_mc *mc; + unsigned long max_rate; + unsigned long rate; + int err; + + mc = tegra_get_memory_controller(); + if (IS_ERR(mc)) { + err = PTR_ERR(mc); + dev_err(&pdev->dev, "failed to get memory controller: %d\n", + err); + return err; + } + + tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); + if (!tegra) + return -ENOMEM; + + /* EMC is a system-critical clock that is always enabled */ + tegra->emc_clock = devm_clk_get(&pdev->dev, "emc"); + if (IS_ERR(tegra->emc_clock)) { + err = PTR_ERR(tegra->emc_clock); + dev_err(&pdev->dev, "failed to get emc clock: %d\n", err); + return err; + } + + tegra->regs = mc->regs; + + max_rate = clk_round_rate(tegra->emc_clock, ULONG_MAX); + + for (rate = 0; rate <= max_rate; rate++) { + rate = clk_round_rate(tegra->emc_clock, rate); + + err = dev_pm_opp_add(&pdev->dev, rate, 0); + if (err) { + dev_err(&pdev->dev, "failed to add opp: %d\n", err); + goto remove_opps; + } + } + + /* + * Reset statistic gathers state, select global bandwidth for the + * statistics collection mode and set clocks counter saturation + * limit to maximum. + */ + writel_relaxed(0x00000000, tegra->regs + MC_STAT_CONTROL); + writel_relaxed(0x00000000, tegra->regs + MC_STAT_EMC_CONTROL); + writel_relaxed(0xffffffff, tegra->regs + MC_STAT_EMC_CLOCK_LIMIT); + + platform_set_drvdata(pdev, tegra); + + tegra->devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, + DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); + if (IS_ERR(tegra->devfreq)) { + err = PTR_ERR(tegra->devfreq); + goto remove_opps; + } + + return 0; + +remove_opps: + dev_pm_opp_remove_all_dynamic(&pdev->dev); + + return err; +} + +static int tegra_devfreq_remove(struct platform_device *pdev) +{ + struct tegra_devfreq *tegra = platform_get_drvdata(pdev); + + devfreq_remove_device(tegra->devfreq); + dev_pm_opp_remove_all_dynamic(&pdev->dev); + + return 0; +} + +static struct platform_driver tegra_devfreq_driver = { + .probe = tegra_devfreq_probe, + .remove = tegra_devfreq_remove, + .driver = { + .name = "tegra20-devfreq", + }, +}; +module_platform_driver(tegra_devfreq_driver); + +MODULE_ALIAS("platform:tegra20-devfreq"); +MODULE_AUTHOR("Dmitry Osipenko "); +MODULE_DESCRIPTION("NVIDIA Tegra20 devfreq driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 2c09083293f46eb1a17be8dd7e92efbdcab43fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 2 May 2019 14:27:36 -0400 Subject: [PATCH 4302/7155] PM / devfreq: Fix spelling typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing 'r' in "monitoing". Signed-off-by: Gaël PORTAY Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index ab22bf8a12d6..bed647637a93 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -402,7 +402,7 @@ static void devfreq_monitor(struct work_struct *work) * devfreq_monitor_start() - Start load monitoring of devfreq instance * @devfreq: the devfreq instance. * - * Helper function for starting devfreq device load monitoing. By + * Helper function for starting devfreq device load monitoring. By * default delayed work based monitoring is supported. Function * to be called from governor in response to DEVFREQ_GOV_START * event when device is added to devfreq framework. @@ -420,7 +420,7 @@ EXPORT_SYMBOL(devfreq_monitor_start); * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance * @devfreq: the devfreq instance. * - * Helper function to stop devfreq device load monitoing. Function + * Helper function to stop devfreq device load monitoring. Function * to be called from governor in response to DEVFREQ_GOV_STOP * event when device is removed from devfreq framework. */ @@ -434,7 +434,7 @@ EXPORT_SYMBOL(devfreq_monitor_stop); * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance * @devfreq: the devfreq instance. * - * Helper function to suspend devfreq device load monitoing. Function + * Helper function to suspend devfreq device load monitoring. Function * to be called from governor in response to DEVFREQ_GOV_SUSPEND * event or when polling interval is set to zero. * @@ -461,7 +461,7 @@ EXPORT_SYMBOL(devfreq_monitor_suspend); * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance * @devfreq: the devfreq instance. * - * Helper function to resume devfreq device load monitoing. Function + * Helper function to resume devfreq device load monitoring. Function * to be called from governor in response to DEVFREQ_GOV_RESUME * event or when polling interval is set to non-zero. */ -- GitLab From 0a453aca94bd7886bca86cc78ce2771f55152232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 2 May 2019 14:40:13 -0400 Subject: [PATCH 4303/7155] PM / devfreq: rk3399_dmc: Fix spelling typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorder 'i' and 'v' in "drvier". Signed-off-by: Gaël PORTAY Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/rk3399_dmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index 682465fa57e1..2e65d7279d79 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c @@ -351,7 +351,7 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) /* * Get dram timing and pass it to arm trust firmware, - * the dram drvier in arm trust firmware will get these + * the dram driver in arm trust firmware will get these * timing and to do dram initial. */ if (!of_get_ddr_timings(&data->timing, np)) { -- GitLab From 7544fd7f384591038646d3cd9efb311ab4509e24 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 21 Jun 2019 18:39:49 -0300 Subject: [PATCH 4304/7155] PM / devfreq: Fix kernel oops on governor module load A bit unexpectedly (but still documented), request_module may return a positive value, in case of a modprobe error. This is currently causing issues in the devfreq framework. When a request_module exits with a positive value, we currently return that via ERR_PTR. However, because the value is positive, it's not a ERR_VALUE proper, and is therefore treated as a valid struct devfreq_governor pointer, leading to a kernel oops. Fix this by returning -EINVAL if request_module returns a positive value. Fixes: b53b0128052ff ("PM / devfreq: Fix static checker warning in try_then_request_governor") Signed-off-by: Ezequiel Garcia Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index bed647637a93..784c08e4f931 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -254,7 +254,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name) /* Restore previous state before return */ mutex_lock(&devfreq_list_lock); if (err) - return ERR_PTR(err); + return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL); governor = find_devfreq_governor(name); } -- GitLab From 5f8669639f3ec6723ebebd83aaccfbea4b5c362b Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Fri, 14 Jun 2019 11:53:05 +0200 Subject: [PATCH 4305/7155] PM / devfreq: events: add Exynos PPMU new events Define new performance events supported by Exynos5422 SoC counters. The counters are built-in in Dynamic Memory Controller and provide information regarding memory utilization. Signed-off-by: Lukasz Luba Acked-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/event/exynos-ppmu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index 3ee3dd5653aa..aae1fd6c91f7 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c @@ -86,6 +86,12 @@ static struct __exynos_ppmu_events { PPMU_EVENT(d1-cpu), PPMU_EVENT(d1-general), PPMU_EVENT(d1-rt), + + /* For Exynos5422 SoC */ + PPMU_EVENT(dmc0_0), + PPMU_EVENT(dmc0_1), + PPMU_EVENT(dmc1_0), + PPMU_EVENT(dmc1_1), }; static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev) -- GitLab From 23ca7d2503d895c80b65e4321fc6cc678c7642f2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Jun 2019 12:32:20 +0200 Subject: [PATCH 4306/7155] PM / devfreq: tegra20: add COMMON_CLK dependency Compile-testing the new driver on platforms without CONFIG_COMMON_CLK leads to a link error: drivers/devfreq/tegra20-devfreq.o: In function `tegra_devfreq_target': tegra20-devfreq.c:(.text+0x288): undefined reference to `clk_set_min_rate' Add a dependency on COMMON_CLK to avoid this. Fixes: 1d39ee8dad6d ("PM / devfreq: Introduce driver for NVIDIA Tegra20") Signed-off-by: Arnd Bergmann Reviewed-by: Dmitry Osipenko Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index f3b242987fd9..defe1d438710 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -107,6 +107,7 @@ config ARM_TEGRA_DEVFREQ config ARM_TEGRA20_DEVFREQ tristate "NVIDIA Tegra20 DEVFREQ Driver" depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST + depends on COMMON_CLK select DEVFREQ_GOV_SIMPLE_ONDEMAND select PM_OPP help -- GitLab From 47e4937a4a7ca4184fd282791dfee76c6799966a Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 23 Aug 2019 05:36:59 +0800 Subject: [PATCH 4307/7155] erofs: move erofs out of staging EROFS filesystem has been merged into linux-staging for a year. EROFS is designed to be a better solution of saving extra storage space with guaranteed end-to-end performance for read-only files with the help of reduced metadata, fixed-sized output compression and decompression inplace technologies. In the past year, EROFS was greatly improved by many people as a staging driver, self-tested, betaed by a large number of our internal users, successfully applied to almost all in-service HUAWEI smartphones as the part of EMUI 9.1 and proven to be stable enough to be moved out of staging. EROFS is a self-contained filesystem driver. Although there are still some TODOs to be more generic, we have a dedicated team actively keeping on working on EROFS in order to make it better with the evolution of Linux kernel as the other in-kernel filesystems. As Pavel suggested, it's better to do as one commit since git can do moves and all histories will be saved in this way. Let's promote it from staging and enhance it more actively as a "real" part of kernel for more wider scenarios! Cc: Greg Kroah-Hartman Cc: Alexander Viro Cc: Andrew Morton Cc: Stephen Rothwell Cc: Theodore Ts'o Cc: Pavel Machek Cc: David Sterba Cc: Amir Goldstein Cc: Christoph Hellwig Cc: Darrick J . Wong Cc: Dave Chinner Cc: Jaegeuk Kim Cc: Jan Kara Cc: Richard Weinberger Cc: Linus Torvalds Cc: Chao Yu Cc: Miao Xie Cc: Li Guifu Cc: Fang Wei Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190822213659.5501-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- .../filesystems/erofs.txt | 4 -- MAINTAINERS | 14 +++--- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/erofs/TODO | 46 ------------------- fs/Kconfig | 1 + fs/Makefile | 1 + {drivers/staging => fs}/erofs/Kconfig | 0 {drivers/staging => fs}/erofs/Makefile | 4 +- {drivers/staging => fs}/erofs/compress.h | 2 - {drivers/staging => fs}/erofs/data.c | 2 - {drivers/staging => fs}/erofs/decompressor.c | 2 - {drivers/staging => fs}/erofs/dir.c | 2 - {drivers/staging => fs}/erofs/erofs_fs.h | 3 -- {drivers/staging => fs}/erofs/inode.c | 2 - {drivers/staging => fs}/erofs/internal.h | 3 +- {drivers/staging => fs}/erofs/namei.c | 2 - {drivers/staging => fs}/erofs/super.c | 2 - {drivers/staging => fs}/erofs/tagptr.h | 0 {drivers/staging => fs}/erofs/utils.c | 2 - {drivers/staging => fs}/erofs/xattr.c | 2 - {drivers/staging => fs}/erofs/xattr.h | 2 - {drivers/staging => fs}/erofs/zdata.c | 2 - {drivers/staging => fs}/erofs/zdata.h | 2 - {drivers/staging => fs}/erofs/zmap.c | 2 - {drivers/staging => fs}/erofs/zpvec.h | 2 - .../include => include}/trace/events/erofs.h | 0 include/uapi/linux/magic.h | 1 + 28 files changed, 12 insertions(+), 96 deletions(-) rename {drivers/staging/erofs/Documentation => Documentation}/filesystems/erofs.txt (98%) delete mode 100644 drivers/staging/erofs/TODO rename {drivers/staging => fs}/erofs/Kconfig (100%) rename {drivers/staging => fs}/erofs/Makefile (68%) rename {drivers/staging => fs}/erofs/compress.h (96%) rename {drivers/staging => fs}/erofs/data.c (99%) rename {drivers/staging => fs}/erofs/decompressor.c (99%) rename {drivers/staging => fs}/erofs/dir.c (98%) rename {drivers/staging => fs}/erofs/erofs_fs.h (99%) rename {drivers/staging => fs}/erofs/inode.c (99%) rename {drivers/staging => fs}/erofs/internal.h (99%) rename {drivers/staging => fs}/erofs/namei.c (99%) rename {drivers/staging => fs}/erofs/super.c (99%) rename {drivers/staging => fs}/erofs/tagptr.h (100%) rename {drivers/staging => fs}/erofs/utils.c (99%) rename {drivers/staging => fs}/erofs/xattr.c (99%) rename {drivers/staging => fs}/erofs/xattr.h (98%) rename {drivers/staging => fs}/erofs/zdata.c (99%) rename {drivers/staging => fs}/erofs/zdata.h (99%) rename {drivers/staging => fs}/erofs/zmap.c (99%) rename {drivers/staging => fs}/erofs/zpvec.h (98%) rename {drivers/staging/erofs/include => include}/trace/events/erofs.h (100%) diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/Documentation/filesystems/erofs.txt similarity index 98% rename from drivers/staging/erofs/Documentation/filesystems/erofs.txt rename to Documentation/filesystems/erofs.txt index 0eab600ca7ca..38aa9126ec98 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/Documentation/filesystems/erofs.txt @@ -49,10 +49,6 @@ Bugs and patches are welcome, please kindly help us and send to the following linux-erofs mailing list: >> linux-erofs mailing list -Note that EROFS is still working in progress as a Linux staging driver, -Cc the staging mailing list as well is highly recommended: ->> Linux Driver Project Developer List - Mount options ============= diff --git a/MAINTAINERS b/MAINTAINERS index 6847372cfab8..0f38cba2c581 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6046,6 +6046,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: drivers/video/fbdev/s1d13xxxfb.c F: include/video/s1d13xxxfb.h +EROFS FILE SYSTEM +M: Gao Xiang +M: Chao Yu +L: linux-erofs@lists.ozlabs.org +S: Maintained +F: fs/erofs/ + ERRSEQ ERROR TRACKING INFRASTRUCTURE M: Jeff Layton S: Maintained @@ -15229,13 +15236,6 @@ M: H Hartley Sweeten S: Odd Fixes F: drivers/staging/comedi/ -STAGING - EROFS FILE SYSTEM -M: Gao Xiang -M: Chao Yu -L: linux-erofs@lists.ozlabs.org -S: Maintained -F: drivers/staging/erofs/ - STAGING - FIELDBUS SUBSYSTEM M: Sven Van Asbroeck S: Maintained diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7c96a01eef6c..d972ec8e71fb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -112,8 +112,6 @@ source "drivers/staging/gasket/Kconfig" source "drivers/staging/axis-fifo/Kconfig" -source "drivers/staging/erofs/Kconfig" - source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/kpc2000/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fcaac9693b83..6018b9a4a077 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ -obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ diff --git a/drivers/staging/erofs/TODO b/drivers/staging/erofs/TODO deleted file mode 100644 index a8608b2f72bd..000000000000 --- a/drivers/staging/erofs/TODO +++ /dev/null @@ -1,46 +0,0 @@ - -EROFS is still working in progress, thus it is not suitable -for all productive uses. play at your own risk :) - -TODO List: - - add the missing error handling code - (mainly existed in xattr and decompression submodules); - - - finalize erofs ondisk format design (which means that - minor on-disk revisions could happen later); - - - documentation and detailed technical analysis; - - - general code review and clean up - (including confusing variable names and code snippets); - - - support larger compressed clustersizes for selection - (currently erofs only works as expected with the page-sized - compressed cluster configuration, usually 4KB); - - - support more lossless data compression algorithms - in addition to LZ4 algorithms in VLE approach; - - - data deduplication and other useful features. - -The following git tree provides the file system user-space -tools under development (ex, formatting tool mkfs.erofs): ->> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git - -The open-source development of erofs-utils is at the early stage. -Contact the original author Li Guifu and -the co-maintainer Fang Wei for the latest news -and more details. - -Code, suggestions, etc, are welcome. Please feel free to -ask and send patches, - -To: - linux-erofs mailing list - Gao Xiang - Chao Yu - -Cc: (for linux-kernel upstream patches) - Greg Kroah-Hartman - linux-staging mailing list - diff --git a/fs/Kconfig b/fs/Kconfig index bfb1c6095c7a..669d46550e6d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -261,6 +261,7 @@ source "fs/romfs/Kconfig" source "fs/pstore/Kconfig" source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" +source "fs/erofs/Kconfig" endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile index d60089fd689b..b2e4973a0bea 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -130,3 +130,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/ obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +obj-$(CONFIG_EROFS_FS) += erofs/ diff --git a/drivers/staging/erofs/Kconfig b/fs/erofs/Kconfig similarity index 100% rename from drivers/staging/erofs/Kconfig rename to fs/erofs/Kconfig diff --git a/drivers/staging/erofs/Makefile b/fs/erofs/Makefile similarity index 68% rename from drivers/staging/erofs/Makefile rename to fs/erofs/Makefile index 5cdae21cb5af..46f2aa4ba46c 100644 --- a/drivers/staging/erofs/Makefile +++ b/fs/erofs/Makefile @@ -1,12 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only -EROFS_VERSION = "1.0pre1" +EROFS_VERSION = "1.0" ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" obj-$(CONFIG_EROFS_FS) += erofs.o -# staging requirement: to be self-contained in its own directory -ccflags-y += -I $(srctree)/$(src)/include erofs-objs := super.o inode.o data.o namei.o dir.o utils.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o diff --git a/drivers/staging/erofs/compress.h b/fs/erofs/compress.h similarity index 96% rename from drivers/staging/erofs/compress.h rename to fs/erofs/compress.h index 043013f9ef1b..07d279fd5d67 100644 --- a/drivers/staging/erofs/compress.h +++ b/fs/erofs/compress.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/compress.h - * * Copyright (C) 2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/data.c b/fs/erofs/data.c similarity index 99% rename from drivers/staging/erofs/data.c rename to fs/erofs/data.c index 72c4b4c5296b..fda16ec8863e 100644 --- a/drivers/staging/erofs/data.c +++ b/fs/erofs/data.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/data.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/decompressor.c b/fs/erofs/decompressor.c similarity index 99% rename from drivers/staging/erofs/decompressor.c rename to fs/erofs/decompressor.c index 32a811ac704a..5f4b7f302863 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/decompressor.c - * * Copyright (C) 2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/dir.c b/fs/erofs/dir.c similarity index 98% rename from drivers/staging/erofs/dir.c rename to fs/erofs/dir.c index 77ef856df9f3..1976e60e5174 100644 --- a/drivers/staging/erofs/dir.c +++ b/fs/erofs/dir.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/dir.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h similarity index 99% rename from drivers/staging/erofs/erofs_fs.h rename to fs/erofs/erofs_fs.h index 6db70f395937..afa7d45ca958 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ /* - * linux/drivers/staging/erofs/erofs_fs.h - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang @@ -10,7 +8,6 @@ #define __EROFS_FS_H /* Enhanced(Extended) ROM File System */ -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 #define EROFS_SUPER_OFFSET 1024 /* diff --git a/drivers/staging/erofs/inode.c b/fs/erofs/inode.c similarity index 99% rename from drivers/staging/erofs/inode.c rename to fs/erofs/inode.c index cbc2c342a37f..80f4fe919ee7 100644 --- a/drivers/staging/erofs/inode.c +++ b/fs/erofs/inode.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/inode.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/internal.h b/fs/erofs/internal.h similarity index 99% rename from drivers/staging/erofs/internal.h rename to fs/erofs/internal.h index 0e8d58546c52..620b73fcc416 100644 --- a/drivers/staging/erofs/internal.h +++ b/fs/erofs/internal.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/internal.h - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang @@ -15,6 +13,7 @@ #include #include #include +#include #include #include #include "erofs_fs.h" diff --git a/drivers/staging/erofs/namei.c b/fs/erofs/namei.c similarity index 99% rename from drivers/staging/erofs/namei.c rename to fs/erofs/namei.c index 8334a910acef..8832b5d95d91 100644 --- a/drivers/staging/erofs/namei.c +++ b/fs/erofs/namei.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/namei.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/super.c b/fs/erofs/super.c similarity index 99% rename from drivers/staging/erofs/super.c rename to fs/erofs/super.c index 2da471010a86..6d3a9bcb8daa 100644 --- a/drivers/staging/erofs/super.c +++ b/fs/erofs/super.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/super.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/tagptr.h b/fs/erofs/tagptr.h similarity index 100% rename from drivers/staging/erofs/tagptr.h rename to fs/erofs/tagptr.h diff --git a/drivers/staging/erofs/utils.c b/fs/erofs/utils.c similarity index 99% rename from drivers/staging/erofs/utils.c rename to fs/erofs/utils.c index 814c2ee037ae..1dd041aa0f5a 100644 --- a/drivers/staging/erofs/utils.c +++ b/fs/erofs/utils.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/utils.c - * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/xattr.c b/fs/erofs/xattr.c similarity index 99% rename from drivers/staging/erofs/xattr.c rename to fs/erofs/xattr.c index e7e5840e3f9d..a8286998a079 100644 --- a/drivers/staging/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/xattr.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/xattr.h b/fs/erofs/xattr.h similarity index 98% rename from drivers/staging/erofs/xattr.h rename to fs/erofs/xattr.h index e20249647541..c5ca47d814dd 100644 --- a/drivers/staging/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/xattr.h - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/zdata.c b/fs/erofs/zdata.c similarity index 99% rename from drivers/staging/erofs/zdata.c rename to fs/erofs/zdata.c index 60d7c20db87d..b32ad585237c 100644 --- a/drivers/staging/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/zdata.c - * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/zdata.h b/fs/erofs/zdata.h similarity index 99% rename from drivers/staging/erofs/zdata.h rename to fs/erofs/zdata.h index e11fe1959ca2..4fc547bc01f9 100644 --- a/drivers/staging/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/zdata.h - * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/zmap.c b/fs/erofs/zmap.c similarity index 99% rename from drivers/staging/erofs/zmap.c rename to fs/erofs/zmap.c index 774dacbc5b32..4dc9cec01297 100644 --- a/drivers/staging/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/zmap.c - * * Copyright (C) 2018-2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/zpvec.h b/fs/erofs/zpvec.h similarity index 98% rename from drivers/staging/erofs/zpvec.h rename to fs/erofs/zpvec.h index 9798f5627786..bd3cee16491c 100644 --- a/drivers/staging/erofs/zpvec.h +++ b/fs/erofs/zpvec.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/zpvec.h - * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang diff --git a/drivers/staging/erofs/include/trace/events/erofs.h b/include/trace/events/erofs.h similarity index 100% rename from drivers/staging/erofs/include/trace/events/erofs.h rename to include/trace/events/erofs.h diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 1274c692e59c..903cc2d2750b 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -19,6 +19,7 @@ #define SQUASHFS_MAGIC 0x73717368 #define ECRYPTFS_SUPER_MAGIC 0xf15f #define EFS_SUPER_MAGIC 0x414A53 +#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 #define EXT2_SUPER_MAGIC 0xEF53 #define EXT3_SUPER_MAGIC 0xEF53 #define XENFS_SUPER_MAGIC 0xabba1974 -- GitLab From 929c11a55b9ec08fc21fe47e1f64245c333d9a15 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 22 Aug 2019 23:35:03 +0200 Subject: [PATCH 4308/7155] ARM: dts: pbab01: correct rtc vendor The rtc8564 is made by Epson but is similar to the NXP pcf8563. Use the correct vendor name. Signed-off-by: Alexandre Belloni Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi index 82802f8ce7a0..d434868e870a 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi @@ -128,7 +128,7 @@ }; rtc@51 { - compatible = "nxp,rtc8564"; + compatible = "epson,rtc8564"; reg = <0x51>; }; -- GitLab From acf993a0f22215dbc1d39f974e3053d6b4f4e594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Fri, 9 Aug 2019 04:12:56 +0100 Subject: [PATCH 4309/7155] ARM: imx: stop adjusting ar8031 phy tx delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent changes to the Atheros at803x driver cause the approach taken here to stop working because commit 6d4cd041f0af ("net: phy: at803x: disable delay only for RGMII mode") and commit cd28d1d6e52e ("net: phy: at803x: Disable phy delay for RGMII mode") fix the AR8031 driver to configure the phy's (RX/TX) delays as per the 'phy-mode' in the device tree. In particular, the phy tx (and rx) delays are updated again as per the 'phy-mode' *after* the code in here runs. Things worked before above commits, because the AR8031 comes out of reset with RX delay enabled, and the at803x driver didn't touch the delay configuration at all when "rgmii" mode was selected. It appears the code in here tries to make device trees work that incorrectly specify "rgmii", but that can't work any more and it is imperative since above commits to have the phy-mode configured correctly in the device tree. I suspect there are a few imx7d based boards using the ar8031 phy and phy-mode = "rgmii", but given I don't know which ones exactly, I am not in a position to update the respective device trees. Hence this patch is simply removing the superfluous code from the imx7d initialisation. An alternative could be to add a warning instead, but that would penalize all boards that have been updated already. Signed-off-by: André Draszik CC: Russell King CC: Shawn Guo CC: Sascha Hauer CC: Pengutronix Kernel Team CC: Fabio Estevam CC: NXP Linux Team CC: Kate Stewart CC: Greg Kroah-Hartman CC: Thomas Gleixner CC: Leonard Crestez CC: linux-arm-kernel@lists.infradead.org Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-imx7d.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c index 95713450591a..ebb27592a9f7 100644 --- a/arch/arm/mach-imx/mach-imx7d.c +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -30,12 +30,6 @@ static int ar8031_phy_fixup(struct phy_device *dev) val &= ~(0x1 << 8); phy_write(dev, 0xe, val); - /* introduce tx clock delay */ - phy_write(dev, 0x1d, 0x5); - val = phy_read(dev, 0x1e); - val |= 0x0100; - phy_write(dev, 0x1e, val); - return 0; } -- GitLab From 1e58b6f0cc8fbfb2bc0575aec7a5dea6fc6d01b0 Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Thu, 1 Aug 2019 16:31:03 +0800 Subject: [PATCH 4310/7155] dt-bindings: fsl: dspi: Add fsl,ls1088a-dspi compatible string new compatible string: "fsl,ls1088a-dspi". Signed-off-by: Chuanhua Han Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index dcc7eaada511..162e024b95a0 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt @@ -6,6 +6,7 @@ Required properties: or "fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi" "fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi" + "fsl,ls1088a-dspi" followed by "fsl,ls1021a-v1.0-dspi" - reg : Offset and length of the register set for the device - interrupts : Should contain SPI controller interrupt - clocks: from common clock binding: handle to dspi clock. -- GitLab From 60ca9248e47011f86e13e945c2673af0fa24a074 Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Thu, 1 Aug 2019 16:31:04 +0800 Subject: [PATCH 4311/7155] arm64: dts: ls1088a: Add the DSPI controller node This patch adds the DSPI controller node for ls1088a boards. Signed-off-by: Chuanhua Han Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index 847050a4ac5d..c1eb7cb001b4 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -252,6 +252,19 @@ #thermal-sensor-cells = <1>; }; + dspi: spi@2100000 { + compatible = "fsl,ls1088a-dspi", + "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2100000 0x0 0x10000>; + interrupts = ; + clock-names = "dspi"; + clocks = <&clockgen 4 1>; + spi-num-chipselects = <6>; + status = "disabled"; + }; + duart0: serial@21c0500 { compatible = "fsl,ns16550", "ns16550a"; reg = <0x0 0x21c0500 0x0 0x100>; -- GitLab From 34a33ba609dc19703ab478ab9cb94518e6eb6cc5 Mon Sep 17 00:00:00 2001 From: Chuanhua Han Date: Thu, 1 Aug 2019 16:31:05 +0800 Subject: [PATCH 4312/7155] arm64: dts: ls1088a-qds: Add the spi-flash nodes under the DSPI controller This patch adds the spi-flash nodes under the DSPI controller for ls1088a-qds boards. Signed-off-by: Chuanhua Han Signed-off-by: Shawn Guo --- .../boot/dts/freescale/fsl-ls1088a-qds.dts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts index 6f48d21b97c0..120e62dad154 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts @@ -17,6 +17,39 @@ compatible = "fsl,ls1088a-qds", "fsl,ls1088a"; }; +&dspi { + bus-num = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <1000000>; + }; + + flash@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + spi-cpol; + spi-cpha; + spi-max-frequency = <3500000>; + reg = <1>; + }; + + flash@2 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + spi-cpol; + spi-cpha; + spi-max-frequency = <3500000>; + reg = <2>; + }; +}; + &i2c0 { status = "okay"; -- GitLab From eb12511f0d47b4da58cc9fc1e93362081fa3331b Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 19 Aug 2019 15:48:06 -0500 Subject: [PATCH 4313/7155] fpga: altera-cvp: Discover Vendor Specific offset Newer Intel FPGAs have different Vendor Specific offsets than legacy parts. Use PCI discovery to find the CvP registers. Since the register positions remain the same, change the hard coded address to a more flexible way of indexing registers from the offset. Adding new PCI read and write abstraction functions to handle the offset (altera_read_config_dword() and altera_write_config_dword()). Signed-off-by: Thor Thayer Signed-off-by: Moritz Fischer --- drivers/fpga/altera-cvp.c | 95 ++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 53b963071c7b..9df2073331cb 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -22,10 +22,10 @@ #define TIMEOUT_US 2000 /* CVP STATUS timeout for USERMODE polling */ /* Vendor Specific Extended Capability Registers */ -#define VSE_PCIE_EXT_CAP_ID 0x200 +#define VSE_PCIE_EXT_CAP_ID 0x0 #define VSE_PCIE_EXT_CAP_ID_VAL 0x000b /* 16bit */ -#define VSE_CVP_STATUS 0x21c /* 32bit */ +#define VSE_CVP_STATUS 0x1c /* 32bit */ #define VSE_CVP_STATUS_CFG_RDY BIT(18) /* CVP_CONFIG_READY */ #define VSE_CVP_STATUS_CFG_ERR BIT(19) /* CVP_CONFIG_ERROR */ #define VSE_CVP_STATUS_CVP_EN BIT(20) /* ctrl block is enabling CVP */ @@ -33,18 +33,18 @@ #define VSE_CVP_STATUS_CFG_DONE BIT(23) /* CVP_CONFIG_DONE */ #define VSE_CVP_STATUS_PLD_CLK_IN_USE BIT(24) /* PLD_CLK_IN_USE */ -#define VSE_CVP_MODE_CTRL 0x220 /* 32bit */ +#define VSE_CVP_MODE_CTRL 0x20 /* 32bit */ #define VSE_CVP_MODE_CTRL_CVP_MODE BIT(0) /* CVP (1) or normal mode (0) */ #define VSE_CVP_MODE_CTRL_HIP_CLK_SEL BIT(1) /* PMA (1) or fabric clock (0) */ #define VSE_CVP_MODE_CTRL_NUMCLKS_OFF 8 /* NUMCLKS bits offset */ #define VSE_CVP_MODE_CTRL_NUMCLKS_MASK GENMASK(15, 8) -#define VSE_CVP_DATA 0x228 /* 32bit */ -#define VSE_CVP_PROG_CTRL 0x22c /* 32bit */ +#define VSE_CVP_DATA 0x28 /* 32bit */ +#define VSE_CVP_PROG_CTRL 0x2c /* 32bit */ #define VSE_CVP_PROG_CTRL_CONFIG BIT(0) #define VSE_CVP_PROG_CTRL_START_XFER BIT(1) -#define VSE_UNCOR_ERR_STATUS 0x234 /* 32bit */ +#define VSE_UNCOR_ERR_STATUS 0x34 /* 32bit */ #define VSE_UNCOR_ERR_CVP_CFG_ERR BIT(5) /* CVP_CONFIG_ERROR_LATCHED */ #define DRV_NAME "altera-cvp" @@ -61,14 +61,29 @@ struct altera_cvp_conf { u32 data); char mgr_name[64]; u8 numclks; + u32 vsec_offset; }; +static int altera_read_config_dword(struct altera_cvp_conf *conf, + int where, u32 *val) +{ + return pci_read_config_dword(conf->pci_dev, conf->vsec_offset + where, + val); +} + +static int altera_write_config_dword(struct altera_cvp_conf *conf, + int where, u32 val) +{ + return pci_write_config_dword(conf->pci_dev, conf->vsec_offset + where, + val); +} + static enum fpga_mgr_states altera_cvp_state(struct fpga_manager *mgr) { struct altera_cvp_conf *conf = mgr->priv; u32 status; - pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &status); + altera_read_config_dword(conf, VSE_CVP_STATUS, &status); if (status & VSE_CVP_STATUS_CFG_DONE) return FPGA_MGR_STATE_OPERATING; @@ -86,7 +101,8 @@ static void altera_cvp_write_data_iomem(struct altera_cvp_conf *conf, u32 val) static void altera_cvp_write_data_config(struct altera_cvp_conf *conf, u32 val) { - pci_write_config_dword(conf->pci_dev, VSE_CVP_DATA, val); + pci_write_config_dword(conf->pci_dev, conf->vsec_offset + VSE_CVP_DATA, + val); } /* switches between CvP clock and internal clock */ @@ -96,10 +112,10 @@ static void altera_cvp_dummy_write(struct altera_cvp_conf *conf) u32 val; /* set 1 CVP clock cycle for every CVP Data Register Write */ - pci_read_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; val |= 1 << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; - pci_write_config_dword(conf->pci_dev, VSE_CVP_MODE_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); for (i = 0; i < CVP_DUMMY_WR; i++) conf->write_data(conf, 0); /* dummy data, could be any value */ @@ -116,7 +132,7 @@ static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask, retries++; do { - pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); + altera_read_config_dword(conf, VSE_CVP_STATUS, &val); if ((val & status_mask) == status_val) return 0; @@ -131,18 +147,17 @@ static int altera_cvp_teardown(struct fpga_manager *mgr, struct fpga_image_info *info) { struct altera_cvp_conf *conf = mgr->priv; - struct pci_dev *pdev = conf->pci_dev; int ret; u32 val; /* STEP 12 - reset START_XFER bit */ - pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); val &= ~VSE_CVP_PROG_CTRL_START_XFER; - pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); /* STEP 13 - reset CVP_CONFIG bit */ val &= ~VSE_CVP_PROG_CTRL_CONFIG; - pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); /* * STEP 14 @@ -164,7 +179,6 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, const char *buf, size_t count) { struct altera_cvp_conf *conf = mgr->priv; - struct pci_dev *pdev = conf->pci_dev; u32 iflags, val; int ret; @@ -184,7 +198,7 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, conf->numclks = 1; /* for uncompressed and unencrypted images */ /* STEP 1 - read CVP status and check CVP_EN flag */ - pci_read_config_dword(pdev, VSE_CVP_STATUS, &val); + altera_read_config_dword(conf, VSE_CVP_STATUS, &val); if (!(val & VSE_CVP_STATUS_CVP_EN)) { dev_err(&mgr->dev, "CVP mode off: 0x%04x\n", val); return -ENODEV; @@ -202,14 +216,14 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, * - set HIP_CLK_SEL and CVP_MODE (must be set in the order mentioned) */ /* switch from fabric to PMA clock */ - pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); val |= VSE_CVP_MODE_CTRL_HIP_CLK_SEL; - pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); /* set CVP mode */ - pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); val |= VSE_CVP_MODE_CTRL_CVP_MODE; - pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); /* * STEP 3 @@ -218,10 +232,10 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, altera_cvp_dummy_write(conf); /* STEP 4 - set CVP_CONFIG bit */ - pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); /* request control block to begin transfer using CVP */ val |= VSE_CVP_PROG_CTRL_CONFIG; - pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); /* STEP 5 - poll CVP_CONFIG READY for 1 with 10us timeout */ ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, @@ -238,15 +252,15 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, altera_cvp_dummy_write(conf); /* STEP 7 - set START_XFER */ - pci_read_config_dword(pdev, VSE_CVP_PROG_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); val |= VSE_CVP_PROG_CTRL_START_XFER; - pci_write_config_dword(pdev, VSE_CVP_PROG_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); /* STEP 8 - start transfer (set CVP_NUMCLKS for bitstream) */ - pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; - pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); return 0; } @@ -257,7 +271,7 @@ static inline int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) u32 val; /* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ - pci_read_config_dword(conf->pci_dev, VSE_CVP_STATUS, &val); + altera_read_config_dword(conf, VSE_CVP_STATUS, &val); if (val & VSE_CVP_STATUS_CFG_ERR) { dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", bytes); @@ -316,27 +330,25 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) { struct altera_cvp_conf *conf = mgr->priv; - struct pci_dev *pdev = conf->pci_dev; + u32 mask, val; int ret; - u32 mask; - u32 val; ret = altera_cvp_teardown(mgr, info); if (ret) return ret; /* STEP 16 - check CVP_CONFIG_ERROR_LATCHED bit */ - pci_read_config_dword(pdev, VSE_UNCOR_ERR_STATUS, &val); + altera_read_config_dword(conf, VSE_UNCOR_ERR_STATUS, &val); if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) { dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n"); return -EPROTO; } /* STEP 17 - reset CVP_MODE and HIP_CLK_SEL bit */ - pci_read_config_dword(pdev, VSE_CVP_MODE_CTRL, &val); + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); val &= ~VSE_CVP_MODE_CTRL_HIP_CLK_SEL; val &= ~VSE_CVP_MODE_CTRL_CVP_MODE; - pci_write_config_dword(pdev, VSE_CVP_MODE_CTRL, val); + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); /* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */ mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE; @@ -395,22 +407,29 @@ static int altera_cvp_probe(struct pci_dev *pdev, { struct altera_cvp_conf *conf; struct fpga_manager *mgr; + int ret, offset; u16 cmd, val; u32 regval; - int ret; + + /* Discover the Vendor Specific Offset for this device */ + offset = pci_find_next_ext_capability(pdev, 0, PCI_EXT_CAP_ID_VNDR); + if (!offset) { + dev_err(&pdev->dev, "No Vendor Specific Offset.\n"); + return -ENODEV; + } /* * First check if this is the expected FPGA device. PCI config * space access works without enabling the PCI device, memory * space access is enabled further down. */ - pci_read_config_word(pdev, VSE_PCIE_EXT_CAP_ID, &val); + pci_read_config_word(pdev, offset + VSE_PCIE_EXT_CAP_ID, &val); if (val != VSE_PCIE_EXT_CAP_ID_VAL) { dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val); return -ENODEV; } - pci_read_config_dword(pdev, VSE_CVP_STATUS, ®val); + pci_read_config_dword(pdev, offset + VSE_CVP_STATUS, ®val); if (!(regval & VSE_CVP_STATUS_CVP_EN)) { dev_err(&pdev->dev, "CVP is disabled for this device: CVP_STATUS Reg 0x%x\n", @@ -422,6 +441,8 @@ static int altera_cvp_probe(struct pci_dev *pdev, if (!conf) return -ENOMEM; + conf->vsec_offset = offset; + /* * Enable memory BAR access. We cannot use pci_enable_device() here * because it will make the driver unusable with FPGA devices that -- GitLab From d2083d040a95b923a217377dd51c27d57eecf5e6 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 19 Aug 2019 15:48:07 -0500 Subject: [PATCH 4314/7155] fpga: altera-cvp: Preparation for V2 parts. In preparation for adding newer V2 parts that use a FIFO, reorganize altera_cvp_chk_error() and change the write function to block based. V2 parts have a block size matching the FIFO while older V1 parts write a 32 bit word at a time. Signed-off-by: Thor Thayer Signed-off-by: Moritz Fischer --- drivers/fpga/altera-cvp.c | 69 ++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 9df2073331cb..3b8386fd32e7 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -143,6 +143,42 @@ static int altera_cvp_wait_status(struct altera_cvp_conf *conf, u32 status_mask, return -ETIMEDOUT; } +static int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) +{ + struct altera_cvp_conf *conf = mgr->priv; + u32 val; + int ret; + + /* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ + ret = altera_read_config_dword(conf, VSE_CVP_STATUS, &val); + if (ret || (val & VSE_CVP_STATUS_CFG_ERR)) { + dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", + bytes); + return -EPROTO; + } + return 0; +} + +static int altera_cvp_send_block(struct altera_cvp_conf *conf, + const u32 *data, size_t len) +{ + u32 mask, words = len / sizeof(u32); + int i, remainder; + + for (i = 0; i < words; i++) + conf->write_data(conf, *data++); + + /* write up to 3 trailing bytes, if any */ + remainder = len % sizeof(u32); + if (remainder) { + mask = BIT(remainder * 8) - 1; + if (mask) + conf->write_data(conf, *data & mask); + } + + return 0; +} + static int altera_cvp_teardown(struct fpga_manager *mgr, struct fpga_image_info *info) { @@ -265,39 +301,25 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, return 0; } -static inline int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) -{ - struct altera_cvp_conf *conf = mgr->priv; - u32 val; - - /* STEP 10 (optional) - check CVP_CONFIG_ERROR flag */ - altera_read_config_dword(conf, VSE_CVP_STATUS, &val); - if (val & VSE_CVP_STATUS_CFG_ERR) { - dev_err(&mgr->dev, "CVP_CONFIG_ERROR after %zu bytes!\n", - bytes); - return -EPROTO; - } - return 0; -} - static int altera_cvp_write(struct fpga_manager *mgr, const char *buf, size_t count) { struct altera_cvp_conf *conf = mgr->priv; + size_t done, remaining, len; const u32 *data; - size_t done, remaining; int status = 0; - u32 mask; /* STEP 9 - write 32-bit data from RBF file to CVP data register */ data = (u32 *)buf; remaining = count; done = 0; - while (remaining >= 4) { - conf->write_data(conf, *data++); - done += 4; - remaining -= 4; + while (remaining) { + len = min(sizeof(u32), remaining); + altera_cvp_send_block(conf, data, len); + data++; + done += len; + remaining -= len; /* * STEP 10 (optional) and STEP 11 @@ -315,11 +337,6 @@ static int altera_cvp_write(struct fpga_manager *mgr, const char *buf, } } - /* write up to 3 trailing bytes, if any */ - mask = BIT(remaining * 8) - 1; - if (mask) - conf->write_data(conf, *data & mask); - if (altera_cvp_chkcfg) status = altera_cvp_chk_error(mgr, count); -- GitLab From e58915179f3f4a839ea3b9aeae1c1e13e98e33b1 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 19 Aug 2019 15:48:08 -0500 Subject: [PATCH 4315/7155] fpga: altera-cvp: Add Stratix10 (V2) Support Add Stratix10 specific functions that use a credit mechanism to throttle data to the CvP FIFOs. Add a private structure with function pointers for V1 vs V2 functions. Signed-off-by: Thor Thayer Signed-off-by: Moritz Fischer --- drivers/fpga/Kconfig | 6 +- drivers/fpga/altera-cvp.c | 187 +++++++++++++++++++++++++++++++++++--- 2 files changed, 176 insertions(+), 17 deletions(-) diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 474f304ec109..f50956ec1300 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -45,11 +45,11 @@ config FPGA_MGR_ALTERA_PS_SPI using the passive serial interface over SPI. config FPGA_MGR_ALTERA_CVP - tristate "Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager" + tristate "Altera CvP FPGA Manager" depends on PCI help - FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V - and Arria 10 Altera FPGAs using the CvP interface over PCIe. + FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V, + Arria 10 and Stratix10 Altera FPGAs using the CvP interface over PCIe. config FPGA_MGR_ZYNQ_FPGA tristate "Xilinx Zynq FPGA" diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 3b8386fd32e7..4e0edb60bfba 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -43,16 +43,34 @@ #define VSE_CVP_PROG_CTRL 0x2c /* 32bit */ #define VSE_CVP_PROG_CTRL_CONFIG BIT(0) #define VSE_CVP_PROG_CTRL_START_XFER BIT(1) +#define VSE_CVP_PROG_CTRL_MASK GENMASK(1, 0) #define VSE_UNCOR_ERR_STATUS 0x34 /* 32bit */ #define VSE_UNCOR_ERR_CVP_CFG_ERR BIT(5) /* CVP_CONFIG_ERROR_LATCHED */ +#define V1_VSEC_OFFSET 0x200 /* Vendor Specific Offset V1 */ +/* V2 Defines */ +#define VSE_CVP_TX_CREDITS 0x49 /* 8bit */ + +#define V2_CREDIT_TIMEOUT_US 20000 +#define V2_CHECK_CREDIT_US 10 +#define V2_POLL_TIMEOUT_US 1000000 +#define V2_USER_TIMEOUT_US 500000 + +#define V1_POLL_TIMEOUT_US 10 + #define DRV_NAME "altera-cvp" #define ALTERA_CVP_MGR_NAME "Altera CvP FPGA Manager" +/* Write block sizes */ +#define ALTERA_CVP_V1_SIZE 4 +#define ALTERA_CVP_V2_SIZE 4096 + /* Optional CvP config error status check for debugging */ static bool altera_cvp_chkcfg; +struct cvp_priv; + struct altera_cvp_conf { struct fpga_manager *mgr; struct pci_dev *pci_dev; @@ -61,9 +79,27 @@ struct altera_cvp_conf { u32 data); char mgr_name[64]; u8 numclks; + u32 sent_packets; u32 vsec_offset; + const struct cvp_priv *priv; }; +struct cvp_priv { + void (*switch_clk)(struct altera_cvp_conf *conf); + int (*clear_state)(struct altera_cvp_conf *conf); + int (*wait_credit)(struct fpga_manager *mgr, u32 blocks); + size_t block_size; + int poll_time_us; + int user_time_us; +}; + +static int altera_read_config_byte(struct altera_cvp_conf *conf, + int where, u8 *val) +{ + return pci_read_config_byte(conf->pci_dev, conf->vsec_offset + where, + val); +} + static int altera_read_config_dword(struct altera_cvp_conf *conf, int where, u32 *val) { @@ -159,6 +195,73 @@ static int altera_cvp_chk_error(struct fpga_manager *mgr, size_t bytes) return 0; } +/* + * CvP Version2 Functions + * Recent Intel FPGAs use a credit mechanism to throttle incoming + * bitstreams and a different method of clearing the state. + */ + +static int altera_cvp_v2_clear_state(struct altera_cvp_conf *conf) +{ + u32 val; + int ret; + + /* Clear the START_XFER and CVP_CONFIG bits */ + ret = altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); + if (ret) { + dev_err(&conf->pci_dev->dev, + "Error reading CVP Program Control Register\n"); + return ret; + } + + val &= ~VSE_CVP_PROG_CTRL_MASK; + ret = altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); + if (ret) { + dev_err(&conf->pci_dev->dev, + "Error writing CVP Program Control Register\n"); + return ret; + } + + return altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, + conf->priv->poll_time_us); +} + +static int altera_cvp_v2_wait_for_credit(struct fpga_manager *mgr, + u32 blocks) +{ + u32 timeout = V2_CREDIT_TIMEOUT_US / V2_CHECK_CREDIT_US; + struct altera_cvp_conf *conf = mgr->priv; + int ret; + u8 val; + + do { + ret = altera_read_config_byte(conf, VSE_CVP_TX_CREDITS, &val); + if (ret) { + dev_err(&conf->pci_dev->dev, + "Error reading CVP Credit Register\n"); + return ret; + } + + /* Return if there is space in FIFO */ + if (val - (u8)conf->sent_packets) + return 0; + + ret = altera_cvp_chk_error(mgr, blocks * ALTERA_CVP_V2_SIZE); + if (ret) { + dev_err(&conf->pci_dev->dev, + "CE Bit error credit reg[0x%x]:sent[0x%x]\n", + val, conf->sent_packets); + return -EAGAIN; + } + + /* Limit the check credit byte traffic */ + usleep_range(V2_CHECK_CREDIT_US, V2_CHECK_CREDIT_US + 1); + } while (timeout--); + + dev_err(&conf->pci_dev->dev, "Timeout waiting for credit\n"); + return -ETIMEDOUT; +} + static int altera_cvp_send_block(struct altera_cvp_conf *conf, const u32 *data, size_t len) { @@ -200,10 +303,12 @@ static int altera_cvp_teardown(struct fpga_manager *mgr, * - set CVP_NUMCLKS to 1 and then issue CVP_DUMMY_WR dummy * writes to the HIP */ - altera_cvp_dummy_write(conf); /* from CVP clock to internal clock */ + if (conf->priv->switch_clk) + conf->priv->switch_clk(conf); /* STEP 15 - poll CVP_CONFIG_READY bit for 0 with 10us timeout */ - ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, 10); + ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0, + conf->priv->poll_time_us); if (ret) dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n"); @@ -265,7 +370,18 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, * STEP 3 * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP */ - altera_cvp_dummy_write(conf); + if (conf->priv->switch_clk) + conf->priv->switch_clk(conf); + + if (conf->priv->clear_state) { + ret = conf->priv->clear_state(conf); + if (ret) { + dev_err(&mgr->dev, "Problem clearing out state\n"); + return ret; + } + } + + conf->sent_packets = 0; /* STEP 4 - set CVP_CONFIG bit */ altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); @@ -273,9 +389,10 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, val |= VSE_CVP_PROG_CTRL_CONFIG; altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); - /* STEP 5 - poll CVP_CONFIG READY for 1 with 10us timeout */ + /* STEP 5 - poll CVP_CONFIG READY for 1 with timeout */ ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, - VSE_CVP_STATUS_CFG_RDY, 10); + VSE_CVP_STATUS_CFG_RDY, + conf->priv->poll_time_us); if (ret) { dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n"); return ret; @@ -285,7 +402,16 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, * STEP 6 * - set CVP_NUMCLKS to 1 and issue CVP_DUMMY_WR dummy writes to the HIP */ - altera_cvp_dummy_write(conf); + if (conf->priv->switch_clk) + conf->priv->switch_clk(conf); + + if (altera_cvp_chkcfg) { + ret = altera_cvp_chk_error(mgr, 0); + if (ret) { + dev_warn(&mgr->dev, "CFG_RDY == 1 timeout\n"); + return ret; + } + } /* STEP 7 - set START_XFER */ altera_read_config_dword(conf, VSE_CVP_PROG_CTRL, &val); @@ -293,11 +419,12 @@ static int altera_cvp_write_init(struct fpga_manager *mgr, altera_write_config_dword(conf, VSE_CVP_PROG_CTRL, val); /* STEP 8 - start transfer (set CVP_NUMCLKS for bitstream) */ - altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); - val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; - val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; - altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); - + if (conf->priv->switch_clk) { + altera_read_config_dword(conf, VSE_CVP_MODE_CTRL, &val); + val &= ~VSE_CVP_MODE_CTRL_NUMCLKS_MASK; + val |= conf->numclks << VSE_CVP_MODE_CTRL_NUMCLKS_OFF; + altera_write_config_dword(conf, VSE_CVP_MODE_CTRL, val); + } return 0; } @@ -315,11 +442,22 @@ static int altera_cvp_write(struct fpga_manager *mgr, const char *buf, done = 0; while (remaining) { - len = min(sizeof(u32), remaining); + /* Use credit throttling if available */ + if (conf->priv->wait_credit) { + status = conf->priv->wait_credit(mgr, done); + if (status) { + dev_err(&conf->pci_dev->dev, + "Wait Credit ERR: 0x%x\n", status); + return status; + } + } + + len = min(conf->priv->block_size, remaining); altera_cvp_send_block(conf, data, len); - data++; + data += len / sizeof(u32); done += len; remaining -= len; + conf->sent_packets++; /* * STEP 10 (optional) and STEP 11 @@ -369,7 +507,8 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr, /* STEP 18 - poll PLD_CLK_IN_USE and USER_MODE bits */ mask = VSE_CVP_STATUS_PLD_CLK_IN_USE | VSE_CVP_STATUS_USERMODE; - ret = altera_cvp_wait_status(conf, mask, mask, TIMEOUT_US); + ret = altera_cvp_wait_status(conf, mask, mask, + conf->priv->user_time_us); if (ret) dev_err(&mgr->dev, "PLD_CLK_IN_USE|USERMODE timeout\n"); @@ -383,6 +522,21 @@ static const struct fpga_manager_ops altera_cvp_ops = { .write_complete = altera_cvp_write_complete, }; +static const struct cvp_priv cvp_priv_v1 = { + .switch_clk = altera_cvp_dummy_write, + .block_size = ALTERA_CVP_V1_SIZE, + .poll_time_us = V1_POLL_TIMEOUT_US, + .user_time_us = TIMEOUT_US, +}; + +static const struct cvp_priv cvp_priv_v2 = { + .clear_state = altera_cvp_v2_clear_state, + .wait_credit = altera_cvp_v2_wait_for_credit, + .block_size = ALTERA_CVP_V2_SIZE, + .poll_time_us = V2_POLL_TIMEOUT_US, + .user_time_us = V2_USER_TIMEOUT_US, +}; + static ssize_t chkcfg_show(struct device_driver *dev, char *buf) { return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg); @@ -484,6 +638,11 @@ static int altera_cvp_probe(struct pci_dev *pdev, conf->pci_dev = pdev; conf->write_data = altera_cvp_write_data_iomem; + if (conf->vsec_offset == V1_VSEC_OFFSET) + conf->priv = &cvp_priv_v1; + else + conf->priv = &cvp_priv_v2; + conf->map = pci_iomap(pdev, CVP_BAR, 0); if (!conf->map) { dev_warn(&pdev->dev, "Mapping CVP BAR failed\n"); -- GitLab From e0496bfd4887b7a046f8fda096fb1f881c00270e Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Mon, 19 Aug 2019 19:26:05 +0200 Subject: [PATCH 4316/7155] dt-bindings: arm: imx: add imx8mq nitrogen support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Nitrogen8M is an ARM based single board computer (SBC) designed to leverage the full capabilities of NXP’s i.MX8M Quad processor. Signed-off-by: Gary Bisson Signed-off-by: Troy Kisky [Dafna: porting vendor's code to mainline] Signed-off-by: Dafna Hirschfeld Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 362bf827cad1..16db1c699ba7 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -224,6 +224,7 @@ properties: - description: i.MX8MQ based Boards items: - enum: + - boundary,imx8mq-nitrogen8m # i.MX8MQ NITROGEN Board - fsl,imx8mq-evk # i.MX8MQ EVK Board - purism,librem5-devkit # Purism Librem5 devkit - technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk -- GitLab From 90771e50d5bd020a46102275e2bfcc0f60f86958 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Mon, 19 Aug 2019 19:26:06 +0200 Subject: [PATCH 4317/7155] arm64: dts: imx: Add i.mx8mq nitrogen8m basic dts support Add basic dts support for i.MX8MQ NITROGEN8M. Signed-off-by: Gary Bisson Signed-off-by: Troy Kisky [Dafna: porting vendor's code to mainline] Signed-off-by: Dafna Hirschfeld Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../boot/dts/freescale/imx8mq-nitrogen.dts | 405 ++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 9efa96924c69..c0e6579c3ae8 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -24,6 +24,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mq-nitrogen.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts new file mode 100644 index 000000000000..c832bf0fcc60 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2018 Boundary Devices + */ + +/dts-v1/; + +#include +#include "imx8mq.dtsi" + +/ { + model = "Boundary Devices i.MX8MQ Nitrogen8M"; + compatible = "boundary,imx8mq-nitrogen8m", "fsl,imx8mq"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x00000000 0x40000000 0 0x80000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_keys>; + + power { + label = "Power Button"; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + linux,code = ; + wakeup-source; + }; + }; + + reg_vref_0v9: regulator-vref-0v9 { + compatible = "regulator-fixed"; + regulator-name = "vref-0v9"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + }; + + reg_vref_1v8: regulator-vref-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vref-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + reg_vref_2v5: regulator-vref-2v5 { + compatible = "regulator-fixed"; + regulator-name = "vref-2v5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + }; + + reg_vref_3v3: regulator-vref-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vref-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_vref_5v: regulator-vref-5v { + compatible = "regulator-fixed"; + regulator-name = "vref-5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; +}; + + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + interrupts-extended = <&gpio1 11 IRQ_TYPE_LEVEL_LOW>; + }; + }; +}; + +&i2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + i2cmux@70 { + compatible = "nxp,pca9546"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_pca9546>; + reg = <0x70>; + reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <0>; + + i2c1a: i2c1@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + reg_arm_dram: regulator@60 { + compatible = "fcs,fan53555"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_arm_dram>; + reg = <0x60>; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + vsel-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c1b: i2c1@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + reg_dram_1p1v: regulator@60 { + compatible = "fcs,fan53555"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_dram_1p1v>; + reg = <0x60>; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + vsel-gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c1c: i2c1@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + reg_soc_gpu_vpu: regulator@60 { + compatible = "fcs,fan53555"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_soc_gpu_vpu>; + reg = <0x60>; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + vsel-gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c1d: i2c1@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + rtc@68 { + compatible = "microcrystal,rv4162"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1d_rv4162>; + reg = <0x68>; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_LOW>; + wakeup-source; + }; + }; + }; +}; + +&uart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + assigned-clocks = <&clk IMX8MQ_CLK_UART1>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clk IMX8MQ_CLK_UART2>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + status = "okay"; +}; + +&usdhc1 { + bus-width = <8>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + non-removable; + vmmc-supply = <®_vref_1v8>; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + /* J17 connector, odd */ + MX8MQ_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x19 /* Pin 19 */ + MX8MQ_IOMUXC_SAI1_RXC_GPIO4_IO1 0x19 /* Pin 21 */ + MX8MQ_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x19 /* Pin 23 */ + MX8MQ_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x19 /* Pin 25 */ + MX8MQ_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x19 /* Pin 27 */ + MX8MQ_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x19 /* Pin 29 */ + MX8MQ_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x19 /* Pin 31 */ + MX8MQ_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x19 /* Pin 33 */ + MX8MQ_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x19 /* Pin 35 */ + MX8MQ_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x19 /* Pin 39 */ + MX8MQ_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x19 /* Pin 41 */ + MX8MQ_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x19 /* Pin 43 */ + MX8MQ_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x19 /* Pin 45 */ + MX8MQ_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x19 /* Pin 47 */ + MX8MQ_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x19 /* Pin 49 */ + MX8MQ_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x19 /* Pin 51 */ + + /* J17 connector, even */ + MX8MQ_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x19 /* Pin 44 */ + MX8MQ_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19 /* Pin 48 */ + MX8MQ_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* Pin 50 */ + MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19 /* Pin 54 */ + MX8MQ_IOMUXC_GPIO1_IO05_GPIO1_IO5 0x19 /* Pin 56 */ + + /* J18 connector, odd */ + MX8MQ_IOMUXC_NAND_CE3_B_GPIO3_IO4 0x19 /* Pin 41 */ + MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5 0x19 /* Pin 43 */ + MX8MQ_IOMUXC_NAND_READY_B_GPIO3_IO16 0x19 /* Pin 45 */ + MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x19 /* Pin 47 */ + MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18 0x19 /* Pin 49 */ + MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* Pin 53 */ + + /* J18 connector, even */ + MX8MQ_IOMUXC_NAND_ALE_GPIO3_IO0 0x19 /* Pin 32 */ + MX8MQ_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x19 /* Pin 36 */ + MX8MQ_IOMUXC_NAND_DATA00_GPIO3_IO6 0x19 /* Pin 38 */ + MX8MQ_IOMUXC_NAND_DATA01_GPIO3_IO7 0x19 /* Pin 40 */ + MX8MQ_IOMUXC_NAND_DATA02_GPIO3_IO8 0x19 /* Pin 42 */ + MX8MQ_IOMUXC_NAND_DATA03_GPIO3_IO9 0x19 /* Pin 44 */ + MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10 0x19 /* Pin 46 */ + + /* J13 Pin 2, WL_WAKE */ + MX8MQ_IOMUXC_SAI5_RXD2_GPIO3_IO23 0xd6 + /* J13 Pin 4, WL_IRQ, not needed for Silex */ + MX8MQ_IOMUXC_SAI5_RXD0_GPIO3_IO21 0xd6 + /* J13 pin 9, unused */ + MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19 + /* J13 Pin 41, BT_CLK_REQ */ + MX8MQ_IOMUXC_SAI5_RXD1_GPIO3_IO22 0xd6 + /* J13 Pin 42, BT_HOST_WAKE */ + MX8MQ_IOMUXC_SAI5_MCLK_GPIO3_IO25 0xd6 + + /* Clock for both CSI1 and CSI2 */ + MX8MQ_IOMUXC_GPIO1_IO15_CCMSRCGPCMIX_CLKO2 0x07 + /* test points */ + MX8MQ_IOMUXC_GPIO1_IO04_GPIO1_IO4 0xc1 /* TP87 */ + >; + }; + + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 + MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 + MX8MQ_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x59 + >; + }; + + pinctrl_gpio_keys: gpio-keysgrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19 + >; + }; + + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f + MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f + >; + }; + + pinctrl_i2c1_pca9546: i2c1-pca9546grp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x49 + >; + }; + + pinctrl_i2c1d_rv4162: i2c1d-rv4162grp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x49 + >; + }; + + pinctrl_reg_arm_dram: reg-arm-dramgrp { + fsl,pins = < + MX8MQ_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x16 + >; + }; + + pinctrl_reg_dram_1p1v: reg-dram-1p1vgrp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_STROBE_GPIO2_IO11 0x16 + >; + }; + + pinctrl_reg_soc_gpu_vpu: reg-soc-gpu-vpugrp { + fsl,pins = < + MX8MQ_IOMUXC_SD2_WP_GPIO2_IO20 0x16 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x45 + MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x45 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x45 + MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x45 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3 + MX8MQ_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x8d + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xcd + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xcd + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xcd + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xcd + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xcd + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xcd + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xcd + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xcd + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xcd + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x9f + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xdf + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xdf + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xdf + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xdf + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xdf + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xdf + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xdf + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xdf + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xdf + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; +}; -- GitLab From afd3b35fdb0dda18192d1ea1435e609f329c95a8 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Tue, 20 Aug 2019 13:54:38 +0800 Subject: [PATCH 4318/7155] arm64: dts: ls1088a: update gpio compatible add ls1088a gpio specify compatible. Signed-off-by: Song Hui Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index c1eb7cb001b4..d1469b0747c7 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -282,7 +282,7 @@ }; gpio0: gpio@2300000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; little-endian; @@ -293,7 +293,7 @@ }; gpio1: gpio@2310000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; little-endian; @@ -304,7 +304,7 @@ }; gpio2: gpio@2320000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; little-endian; @@ -315,7 +315,7 @@ }; gpio3: gpio@2330000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2330000 0x0 0x10000>; interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; little-endian; -- GitLab From 801592402c392acb0f2ead971d1e8f0e0565b60e Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 20 Aug 2019 18:39:36 -0700 Subject: [PATCH 4319/7155] ARM: dts: vf610-zii-cfu1: Slow I2C0 down to 100 kHz Fiber-optic modules attached to the bus are only rated to work at 100 kHz, so decrease the bus frequency to accommodate that. Signed-off-by: Andrey Smirnov Cc: Shawn Guo Cc: Chris Healy Cc: Fabio Estevam Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Reviewed-by: Andrew Lunn Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-cfu1.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/vf610-zii-cfu1.dts index ff460a1de85a..28732249cfc0 100644 --- a/arch/arm/boot/dts/vf610-zii-cfu1.dts +++ b/arch/arm/boot/dts/vf610-zii-cfu1.dts @@ -207,7 +207,7 @@ }; &i2c0 { - clock-frequency = <400000>; + clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c0>; status = "okay"; -- GitLab From 0a6a928300df3cc11047b216c609c75e51aa5729 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 21 Aug 2019 11:20:19 +0300 Subject: [PATCH 4320/7155] dt-bindings: arm: fsl: add Hummingboard Pulse Add binding documentation for the SolidRun Hummingboard Pulse board. Signed-off-by: Baruch Siach Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 16db1c699ba7..73dcb8772234 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -227,6 +227,7 @@ properties: - boundary,imx8mq-nitrogen8m # i.MX8MQ NITROGEN Board - fsl,imx8mq-evk # i.MX8MQ EVK Board - purism,librem5-devkit # Purism Librem5 devkit + - solidrun,hummingboard-pulse # SolidRun Hummingboard Pulse - technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk - const: fsl,imx8mq -- GitLab From ffe0f9a0baf9f10135ea272ef4d944179d106d59 Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Wed, 21 Aug 2019 11:20:18 +0300 Subject: [PATCH 4321/7155] arm64: dts: fsl: add support for Hummingboard Pulse The SolidRun Hummingboard Pulse carrier board carries the SolidRun i.MX8MQ based SOM. Notably missing is PCIe support that depends on analog PLLOUT clock. Current imx clk driver does not support this clock. Signed-off-by: Jon Nettleton Signed-off-by: Baruch Siach Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../freescale/imx8mq-hummingboard-pulse.dts | 256 +++++++++++++++ .../boot/dts/freescale/imx8mq-sr-som.dtsi | 309 ++++++++++++++++++ 3 files changed, 566 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index c0e6579c3ae8..5d64ff40d862 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -23,6 +23,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-nitrogen.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts b/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts new file mode 100644 index 000000000000..f52e872ac96f --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2018 Jon Nettleton + */ + +/dts-v1/; + +#include "dt-bindings/usb/pd.h" +#include "imx8mq-sr-som.dtsi" + +/ { + model = "SolidRun i.MX8MQ HummingBoard Pulse"; + compatible = "solidrun,hummingboard-pulse", "fsl,imx8mq"; + + chosen { + stdout-path = &uart1; + }; + + reg_usdhc2_vmmc: regulator-usdhc2-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2_vmmc>; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 13 GPIO_ACTIVE_LOW>; + }; + + reg_v_5v0: regulator-v-5v0 { + compatible = "regulator-fixed"; + regulator-name = "v_5v0"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + clock-frequency = <100000>; + status = "okay"; + + typec_ptn5100: usb-typec@50 { + compatible = "nxp,ptn5110"; + reg = <0x50>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_typec>; + interrupt-parent = <&gpio1>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <9000000>; + + port { + typec1_dr_sw: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + }; + }; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + clock-frequency = <100000>; + status = "okay"; + + rtc@69 { + compatible = "abracon,ab1805"; + reg = <0x69>; + abracon,tc-diode = "schottky"; + abracon,tc-resistor = <3>; + }; +}; + +&uart2 { /* J35 header */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clk IMX8MQ_CLK_UART2>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + status = "okay"; +}; + +&uart3 { /* Mikrobus */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + assigned-clocks = <&clk IMX8MQ_CLK_UART3>; + assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>; + uart-has-rtscts; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + status = "okay"; +}; + +&usb_dwc3_0 { + dr_mode = "otg"; + status = "okay"; + + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&typec1_dr_sw>; + }; + }; +}; + +&usb_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +&usb3_phy1 { + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + /* MikroBus Analog */ + MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x41 + /* MikroBus Reset */ + MX8MQ_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x41 + /* + * The following 2 pins need to be commented out and + * reconfigured to enable RTS/CTS on UART3 + */ + /* MikroBus PWM */ + MX8MQ_IOMUXC_ECSPI1_MISO_GPIO5_IO8 0x41 + /* MikroBus INT */ + MX8MQ_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x41 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f + MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL 0x4000007f + MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA 0x4000007f + >; + }; + + pinctrl_typec: typecgrp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_RE_B_GPIO3_IO15 0x16 + MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x17059 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49 + MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX8MQ_IOMUXC_UART3_TXD_UART3_DCE_TX 0x49 + MX8MQ_IOMUXC_UART3_RXD_UART3_DCE_RX 0x49 + /* + * These pins are by default GPIO on the Mikro Bus + * Header. To use RTS/CTS on UART3 comment them out + * of the hoggrp and enable them here + */ + /* MX8MQ_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x49 */ + /* MX8MQ_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x49 */ + >; + }; + + pinctrl_usdhc2_gpio: usdhc2grpgpio { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 + >; + }; + + pinctrl_usdhc2_vmmc: usdhc2vmmcgpio { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x41 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x8d + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xcd + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xcd + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xcd + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xcd + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xcd + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x9f + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xdf + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xdf + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xdf + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xdf + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xdf + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi new file mode 100644 index 000000000000..d7f03c65832b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2018 Jon Nettleton + */ + +#include "imx8mq.dtsi" + +/ { + reg_vdd_3v3: regulator-vdd-3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-name = "vdd_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + phy-reset-duration = <2>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + clock-frequency = <400000>; + status = "okay"; + + pmic: pmic@8 { + compatible = "fsl,pfuze100"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1ab { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + }; + + sw1c_reg: sw1c { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sw3a_reg: sw3ab { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-always-on; + }; + + vgen1_reg: vgen1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen2_reg: vgen2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + regulator-always-on; + }; + + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen4_reg: vgen4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vgen5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vgen6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; +}; + +&pgc_gpu{ + power-supply = <&sw1a_reg>; +}; + +&pgc_vpu { + power-supply = <&sw1c_reg>; +}; + +&qspi0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi>; + status = "okay"; + + /* SPI flash; not assembled by default */ + spi_flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "micron,n25q256a", "jedec,spi-nor"; + spi-max-frequency = <29000000>; + status = "disabled"; + }; +}; + +&uart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + assigned-clocks = <&clk IMX8MQ_CLK_UART1>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + assigned-clock-rates = <25000000>; + status = "okay"; +}; + +&uart4 { /* ublox BT */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + assigned-clocks = <&clk IMX8MQ_CLK_UART4>; + assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>; + assigned-clock-rates = <80000000>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 + MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f + MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f + >; + }; + + pinctrl_pcie0: pcie0grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B 0x74 + MX8MQ_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x16 + MX8MQ_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x16 + >; + }; + + pinctrl_qspi: qspigrp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_ALE_QSPI_A_SCLK 0x82 + MX8MQ_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B 0x82 + MX8MQ_IOMUXC_NAND_DATA00_QSPI_A_DATA0 0x82 + MX8MQ_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x82 + MX8MQ_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x82 + MX8MQ_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x82 + + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 + MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 + MX8MQ_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX8MQ_IOMUXC_UART4_TXD_UART4_DCE_TX 0x49 + MX8MQ_IOMUXC_UART4_RXD_UART4_DCE_RX 0x49 + MX8MQ_IOMUXC_SAI3_TXD_GPIO5_IO1 0x19 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83 + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x8d + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xcd + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xcd + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xcd + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xcd + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xcd + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xcd + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xcd + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xcd + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xcd + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x8d + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x9f + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xdf + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xdf + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xdf + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xdf + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xdf + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xdf + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xdf + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xdf + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xdf + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x9f + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; +}; -- GitLab From 968c6f4b3c21e9fae9b49cc91214a01b4827625d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 21 Aug 2019 18:33:04 +0200 Subject: [PATCH 4322/7155] soc: imx: gpcv2: Print the correct error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code prints 'ret' (thus 0) while it should use 'err'. Signed-off-by: Guido Günther Reviewed-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 31b8d002d855..b0dffb06c05d 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -198,7 +198,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, err = regulator_disable(domain->regulator); if (err) dev_err(domain->dev, - "failed to disable regulator: %d\n", ret); + "failed to disable regulator: %d\n", err); /* Preserve earlier error code */ ret = ret ?: err; } -- GitLab From 082b1ed591b177cb55f885090e42067b3f3093c6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2019 08:02:35 +0200 Subject: [PATCH 4323/7155] dt-bindings: vendor-prefixes: Add Anvo-Systems Add vendor prefix for Anvo-Systems Dresden GmbH. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index b01b6fe8a8ce..7d57ffec6f5b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -81,6 +81,8 @@ patternProperties: description: Analogix Semiconductor, Inc. "^andestech,.*": description: Andes Technology Corporation + "^anvo,.*": + description: Anvo-Systems Dresden GmbH "^apm,.*": description: Applied Micro Circuits Corporation (APM) "^aptina,.*": -- GitLab From 730fd9d736290b011b9c344d5e26ed29900a2d94 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2019 08:02:36 +0200 Subject: [PATCH 4324/7155] dt-bindings: eeprom: at25: Add Anvo ANV32E61W Document the compatible for ANV32E61W 64kb Serial SPI non-volatile SRAM. Although it is a SRAM device, it can be accessed through EEPROM interface. At least until there is no proper SRAM driver support for it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/eeprom/at25.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/eeprom/at25.txt b/Documentation/devicetree/bindings/eeprom/at25.txt index b3bde97dc199..42577dd113dd 100644 --- a/Documentation/devicetree/bindings/eeprom/at25.txt +++ b/Documentation/devicetree/bindings/eeprom/at25.txt @@ -3,6 +3,7 @@ EEPROMs (SPI) compatible with Atmel at25. Required properties: - compatible : Should be ",", and generic value "atmel,at25". Example "," values: + "anvo,anv32e61w" "microchip,25lc040" "st,m95m02" "st,m95256" -- GitLab From 8d5fc0b95fd1542c575ac64457bd17d74a206497 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2019 08:02:37 +0200 Subject: [PATCH 4325/7155] dt-bindings: arm: fsl: Add Kontron i.MX6UL N6310 compatibles Add the compatibles for Kontron i.MX6UL N6310 SoM and boards. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 73dcb8772234..1b4b4e6573b5 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -161,6 +161,20 @@ properties: items: - enum: - fsl,imx6ul-14x14-evk # i.MX6 UltraLite 14x14 EVK Board + - kontron,imx6ul-n6310-som # Kontron N6310 SOM + - const: fsl,imx6ul + + - description: Kontron N6310 S Board + items: + - const: kontron,imx6ul-n6310-s + - const: kontron,imx6ul-n6310-som + - const: fsl,imx6ul + + - description: Kontron N6310 S 43 Board + items: + - const: kontron,imx6ul-n6310-s-43 + - const: kontron,imx6ul-n6310-s + - const: kontron,imx6ul-n6310-som - const: fsl,imx6ul - description: i.MX6ULL based Boards -- GitLab From 1ea4b76cdfde49a2421523769cb99d4be6aedea3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 22 Aug 2019 08:02:38 +0200 Subject: [PATCH 4326/7155] ARM: dts: imx6ul-kontron-n6310: Add Kontron i.MX6UL N6310 SoM and boards Add support for i.MX6UL modules from Kontron Electronics GmbH (before acquisition: Exceet Electronics) and evalkit boards based on it: 1. N6310 SOM: i.MX6 UL System-on-Module, a 25x25 mm solderable module (LGA pads and pin castellations) with 256 MB RAM, 1 MB NOR-Flash, 256 MB NAND and other interfaces, 2. N6310 S: evalkit, w/wo eMMC, without display, 3. N6310 S 43: evalkit with 4.3" display, The work is based on Exceet/Kontron source code (GPLv2) with numerous changes: 1. Reorganize files, 2. Rename Exceet -> Kontron, 3. Rename models/compatibles to match newest Kontron product naming, 4. Fix coding style errors and adjust to device tree coding guidelines, 5. Fix DTC warnings, 6. Extend compatibles so eval boards inherit the SoM compatible, 7. Use defines instead of GPIO and interrupt flag values, 8. Use proper vendor compatible for Macronix SPI NOR, 9. Replace deprecated bindings with proper ones, 10. Sort nodes alphabetically, 11. Remove Admatec display nodes (not yet supported). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Frieder Schrempf Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 2 + .../boot/dts/imx6ul-kontron-n6310-s-43.dts | 102 +++++ arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts | 420 ++++++++++++++++++ .../boot/dts/imx6ul-kontron-n6310-som.dtsi | 134 ++++++ 4 files changed, 658 insertions(+) create mode 100644 arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts create mode 100644 arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts create mode 100644 arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7fe6667f466c..de55b9f2339c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -569,6 +569,8 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-geam.dtb \ imx6ul-isiot-emmc.dtb \ imx6ul-isiot-nand.dtb \ + imx6ul-kontron-n6310-s.dtb \ + imx6ul-kontron-n6310-s-43.dtb \ imx6ul-liteboard.dtb \ imx6ul-opos6uldev.dtb \ imx6ul-pico-hobbit.dtb \ diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts b/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts new file mode 100644 index 000000000000..5bad29683cc3 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 exceet electronics GmbH + * Copyright (C) 2018 Kontron Electronics GmbH + * Copyright (c) 2019 Krzysztof Kozlowski + */ + +#include "imx6ul-kontron-n6310-s.dts" + +/ { + model = "Kontron N6310 S 43"; + compatible = "kontron,imx6ul-n6310-s-43", "kontron,imx6ul-n6310-s", + "kontron,imx6ul-n6310-som", "fsl,imx6ul"; + + backlight { + compatible = "pwm-backlight"; + pwms = <&pwm7 0 5000000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + status = "okay"; + }; +}; + +&i2c4 { + touchscreen@5d { + compatible = "goodix,gt928"; + reg = <0x5d>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cap_touch>; + interrupt-parent = <&gpio5>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>; + }; +}; + +&lcdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif_dat &pinctrl_lcdif_ctrl>; + /* Leave status disabled because of missing display panel node */ +}; + +&pwm7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm7>; + status = "okay"; +}; + +&iomuxc { + pinctrl_cap_touch: captouchgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b0b0 /* Touch Interrupt */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b0b0 /* Touch Reset */ + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b0b0 /* Touch Wake */ + >; + }; + + pinctrl_lcdif_ctrl: lcdifctrlgrp { + fsl,pins = < + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79 + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79 + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79 + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79 + MX6UL_PAD_LCD_RESET__LCDIF_RESET 0x79 + >; + }; + + pinctrl_lcdif_dat: lcdifdatgrp { + fsl,pins = < + MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79 + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79 + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79 + MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79 + MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79 + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79 + MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79 + MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79 + MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79 + MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79 + MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79 + MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79 + MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79 + MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79 + >; + }; + + pinctrl_pwm7: pwm7grp { + fsl,pins = < + MX6UL_PAD_CSI_VSYNC__PWM7_OUT 0x110b0 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts new file mode 100644 index 000000000000..0205fd56d975 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts @@ -0,0 +1,420 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 exceet electronics GmbH + * Copyright (C) 2018 Kontron Electronics GmbH + * Copyright (c) 2019 Krzysztof Kozlowski + */ + +/dts-v1/; + +#include "imx6ul-kontron-n6310-som.dtsi" + +/ { + model = "Kontron N6310 S"; + compatible = "kontron,imx6ul-n6310-s", "kontron,imx6ul-n6310-som", + "fsl,imx6ul"; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + led1 { + label = "debug-led1"; + gpios = <&gpio1 30 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; + + led2 { + label = "debug-led2"; + gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led3 { + label = "debug-led3"; + gpios = <&gpio5 2 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + pwm-beeper { + compatible = "pwm-beeper"; + pwms = <&pwm8 0 5000>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_usb_otg1_vbus: regulator-usb-otg1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_vref_adc: regulator-vref-adc { + compatible = "regulator-fixed"; + regulator-name = "vref-adc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc1>; + num-channels = <3>; + vref-supply = <®_vref_adc>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "okay"; +}; + +&ecspi1 { + cs-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + eeprom@0 { + compatible = "anvo,anv32e61w", "atmel,at25"; + reg = <0>; + spi-max-frequency = <20000000>; + spi-cpha; + spi-cpol; + pagesize = <1>; + size = <8192>; + address-width = <16>; + }; +}; + +&fec1 { + pinctrl-0 = <&pinctrl_enet1>; + /delete-node/ mdio; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio>; + phy-mode = "rmii"; + phy-handle = <ðphy2>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@1 { + reg = <1>; + micrel,led-mode = <0>; + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + }; + + ethphy2: ethernet-phy@2 { + reg = <2>; + micrel,led-mode = <0>; + clocks = <&clks IMX6UL_CLK_ENET2_REF>; + clock-names = "rmii-ref"; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&i2c4 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c4>; + status = "okay"; + + rtc@32 { + compatible = "epson,rx8900"; + reg = <0x32>; + }; +}; + +&pwm8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm8>; + status = "okay"; +}; + +&snvs_poweroff { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + linux,rs485-enabled-at-boot-time; + rs485-rx-during-tx; + rs485-rts-active-low; + uart-has-rtscts; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&usbotg1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg1>; + dr_mode = "otg"; + srp-disable; + hnp-disable; + adp-disable; + vbus-supply = <®_usb_otg1_vbus>; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + keep-power-in-suspend; + wakeup-source; + vmmc-supply = <®_3v3>; + voltage-ranges = <3300 3300>; + no-1-8-v; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>; + non-removable; + keep-power-in-suspend; + wakeup-source; + vmmc-supply = <®_3v3>; + voltage-ranges = <3300 3300>; + no-1-8-v; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl-0 = <&pinctrl_reset_out &pinctrl_gpio>; + + pinctrl_adc1: adc1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0 + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0xb0 + >; + }; + + /* FRAM */ + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x100b1 + MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x100b1 + MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x100b1 + MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x100b1 /* ECSPI1-CS1 */ + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009 + >; + }; + + pinctrl_enet2_mdio: enet2mdiogrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + >; + }; + + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + >; + }; + + pinctrl_gpio: gpiogrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b0b0 /* DOUT1 */ + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b0b0 /* DIN1 */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0 /* DOUT2 */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* DIN2 */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x1b0b0 /* LED H14 */ + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0b0 /* LED H15 */ + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0 /* LED H16 */ + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_CSI_PIXCLK__I2C1_SCL 0x4001b8b0 + MX6UL_PAD_CSI_MCLK__I2C1_SDA 0x4001b8b0 + >; + }; + + pinctrl_i2c4: i2c4grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__I2C4_SCL 0x4001f8b0 + MX6UL_PAD_UART2_RX_DATA__I2C4_SDA 0x4001f8b0 + >; + }; + + pinctrl_pwm8: pwm8grp { + fsl,pins = < + MX6UL_PAD_CSI_HSYNC__PWM8_OUT 0x110b0 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_NAND_DATA04__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_NAND_DATA05__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_NAND_DATA06__UART2_DCE_CTS 0x1b0b1 + /* + * mux unused RTS to make sure it doesn't cause + * any interrupts when it is undefined + */ + MX6UL_PAD_NAND_DATA07__UART2_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_usbotg1: usbotg1 { + fsl,pins = < + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10059 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x100b1 /* SD1_CD */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10059 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO09__WDOG1_WDOG_ANY 0x30b0 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi new file mode 100644 index 000000000000..a896b2348dd2 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 exceet electronics GmbH + * Copyright (C) 2018 Kontron Electronics GmbH + * Copyright (c) 2019 Krzysztof Kozlowski + */ + +#include "imx6ul.dtsi" +#include + +/ { + model = "Kontron N6310 SOM"; + compatible = "kontron,imx6ul-n6310-som", "fsl,imx6ul"; + + memory@80000000 { + reg = <0x80000000 0x10000000>; + device_type = "memory"; + }; +}; + +&ecspi2 { + cs-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + status = "okay"; + + spi-flash@0 { + compatible = "mxicy,mx25v8035f", "jedec,spi-nor"; + spi-max-frequency = <50000000>; + reg = <0>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@1 { + reg = <1>; + micrel,led-mode = <0>; + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + }; + }; +}; + +&fec2 { + phy-mode = "rmii"; + status = "disabled"; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi>; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-max-frequency = <108000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + reg = <0>; + + partition@0 { + label = "ubi1"; + reg = <0x00000000 0x08000000>; + }; + + partition@8000000 { + label = "ubi2"; + reg = <0x08000000 0x08000000>; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reset_out>; + + pinctrl_ecspi2: ecspi2grp { + fsl,pins = < + MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x100b1 + MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x100b1 + MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x100b1 + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x100b1 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009 + >; + }; + + pinctrl_enet1_mdio: enet1mdiogrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + >; + }; + + pinctrl_qspi: qspigrp { + fsl,pins = < + MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK 0x70a1 + MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1 + MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01 0x70a1 + MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02 0x70a1 + MX6UL_PAD_NAND_CLE__QSPI_A_DATA03 0x70a1 + MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B 0x70a1 + >; + }; + + pinctrl_reset_out: rstoutgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b0b0 + >; + }; +}; -- GitLab From 215701807e53a379e1c9b2e6401676779ef85ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Thu, 22 Aug 2019 13:10:23 +0200 Subject: [PATCH 4327/7155] arm64: dts: imx8mq: Add mux controller to iomuxc_gpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only mux controls the MIPI DSI input selection. Signed-off-by: Guido Günther Reviewed-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index f5d4b12a5fa8..c51d571c05e4 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -440,8 +440,15 @@ }; iomuxc_gpr: syscon@30340000 { - compatible = "fsl,imx8mq-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon"; + compatible = "fsl,imx8mq-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", + "syscon", "simple-mfd"; reg = <0x30340000 0x10000>; + + mux: mux-controller { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x34 0x00000004>; /* MIPI_MUX_SEL */ + }; }; ocotp: ocotp-ctrl@30350000 { -- GitLab From 5aff7c46172b270af2a9b10eed3a8215c4ba9a87 Mon Sep 17 00:00:00 2001 From: Jacob Huisman Date: Fri, 16 Aug 2019 13:22:09 +0100 Subject: [PATCH 4328/7155] docs: process: fix broken link http://linux.yyz.us/patch-format.html seems to be down since approximately September 2018. There is a working archive copy on arhive.org. Replaced the links in documenation + translations. Signed-off-by: Jacob Huisman Reviewed-by: Federico Vaga Signed-off-by: Jonathan Corbet --- Documentation/process/howto.rst | 2 +- Documentation/process/submitting-patches.rst | 2 +- Documentation/translations/it_IT/process/howto.rst | 2 +- Documentation/translations/it_IT/process/submitting-patches.rst | 2 +- Documentation/translations/ja_JP/SubmittingPatches | 2 +- Documentation/translations/ja_JP/howto.rst | 2 +- Documentation/translations/ko_KR/howto.rst | 2 +- Documentation/translations/zh_CN/process/howto.rst | 2 +- Documentation/translations/zh_CN/process/submitting-patches.rst | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/process/howto.rst b/Documentation/process/howto.rst index 6ab75c11d2c3..b6f5a379ad6c 100644 --- a/Documentation/process/howto.rst +++ b/Documentation/process/howto.rst @@ -123,7 +123,7 @@ required reading: https://www.ozlabs.org/~akpm/stuff/tpp.txt "Linux kernel patch submission format" - http://linux.yyz.us/patch-format.html + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html :ref:`Documentation/process/stable-api-nonsense.rst ` This file describes the rationale behind the conscious decision to diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index 9c4299293c72..fb56297f70dc 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -844,7 +844,7 @@ Andrew Morton, "The perfect patch" (tpp). Jeff Garzik, "Linux kernel patch submission format". - + Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". diff --git a/Documentation/translations/it_IT/process/howto.rst b/Documentation/translations/it_IT/process/howto.rst index 44e6077730e8..1db5a1082389 100644 --- a/Documentation/translations/it_IT/process/howto.rst +++ b/Documentation/translations/it_IT/process/howto.rst @@ -129,7 +129,7 @@ Di seguito una lista di file che sono presenti nei sorgente del kernel e che https://www.ozlabs.org/~akpm/stuff/tpp.txt "Linux kernel patch submission format" - http://linux.yyz.us/patch-format.html + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html :ref:`Documentation/translations/it_IT/process/stable-api-nonsense.rst ` diff --git a/Documentation/translations/it_IT/process/submitting-patches.rst b/Documentation/translations/it_IT/process/submitting-patches.rst index 7d7ea92c5c5a..cba1f8cb61ed 100644 --- a/Documentation/translations/it_IT/process/submitting-patches.rst +++ b/Documentation/translations/it_IT/process/submitting-patches.rst @@ -868,7 +868,7 @@ Andrew Morton, "La patch perfetta" (tpp). Jeff Garzik, "Formato per la sottomissione di patch per il kernel Linux" - + Greg Kroah-Hartman, "Come scocciare un manutentore di un sottosistema" diff --git a/Documentation/translations/ja_JP/SubmittingPatches b/Documentation/translations/ja_JP/SubmittingPatches index ad979c3c06a6..dd0c3280ba5a 100644 --- a/Documentation/translations/ja_JP/SubmittingPatches +++ b/Documentation/translations/ja_JP/SubmittingPatches @@ -693,7 +693,7 @@ Andrew Morton, "The perfect patch" (tpp). Jeff Garzik, "Linux kernel patch submission format". - + Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". diff --git a/Documentation/translations/ja_JP/howto.rst b/Documentation/translations/ja_JP/howto.rst index 2621b770a745..73ebdab4ced7 100644 --- a/Documentation/translations/ja_JP/howto.rst +++ b/Documentation/translations/ja_JP/howto.rst @@ -139,7 +139,7 @@ linux-api@vger.kernel.org に送ることを勧めます。 "The Perfect Patch" http://www.ozlabs.org/~akpm/stuff/tpp.txt "Linux kernel patch submission format" - http://linux.yyz.us/patch-format.html + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html :ref:`Documentation/process/stable-api-nonsense.rst ` このファイルはカーネルの中に不変の API を持たないことにした意識的 diff --git a/Documentation/translations/ko_KR/howto.rst b/Documentation/translations/ko_KR/howto.rst index bcd63731b80a..b3f51b19de7c 100644 --- a/Documentation/translations/ko_KR/howto.rst +++ b/Documentation/translations/ko_KR/howto.rst @@ -135,7 +135,7 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다. https://www.ozlabs.org/~akpm/stuff/tpp.txt "Linux kernel patch submission format" - http://linux.yyz.us/patch-format.html + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html :ref:`Documentation/process/stable-api-nonsense.rst ` 이 문서는 의도적으로 커널이 불변하는 API를 갖지 않도록 결정한 diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst index b244a7190eb6..a8e6ab818983 100644 --- a/Documentation/translations/zh_CN/process/howto.rst +++ b/Documentation/translations/zh_CN/process/howto.rst @@ -113,7 +113,7 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与 "Linux kernel patch submission format" - http://linux.yyz.us/patch-format.html + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html :ref:`Documentation/translations/zh_CN/process/stable-api-nonsense.rst ` 论证内核为什么特意不包括稳定的内核内部API,也就是说不包括像这样的特 diff --git a/Documentation/translations/zh_CN/process/submitting-patches.rst b/Documentation/translations/zh_CN/process/submitting-patches.rst index 437c23b367bb..1bb4271ab420 100644 --- a/Documentation/translations/zh_CN/process/submitting-patches.rst +++ b/Documentation/translations/zh_CN/process/submitting-patches.rst @@ -652,7 +652,7 @@ Andrew Morton, "The perfect patch" (tpp). Jeff Garzik, "Linux kernel patch submission format". - + Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". -- GitLab From f3acd33d840d3ea3e1233d234605c85cbbf26054 Mon Sep 17 00:00:00 2001 From: xiaolinkui Date: Thu, 22 Aug 2019 14:58:16 +0800 Subject: [PATCH 4329/7155] net: use unlikely for dql_avail case This is an unlikely case, use unlikely() on it seems logical. Signed-off-by: xiaolinkui Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 55ac223553f8..b5d28dadf964 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3272,7 +3272,7 @@ static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue, */ smp_mb(); - if (dql_avail(&dev_queue->dql) < 0) + if (unlikely(dql_avail(&dev_queue->dql) < 0)) return; if (test_and_clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state)) -- GitLab From 2307f4a517c7dbb26fe0c0513ee0ba9d3239362f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 22:49:37 +0800 Subject: [PATCH 4330/7155] net: hns3: Fix -Wunused-const-variable warning drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h:542:30: warning: meta_data_key_info defined but not used [-Wunused-const-variable=] drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h:553:30: warning: tuple_key_info defined but not used [-Wunused-const-variable=] The two variable is only used in hclge_main.c, so just move the definition over there. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- .../hisilicon/hns3/hns3pf/hclge_main.c | 44 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 44 ------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9d64c4304e5e..dde17be33767 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -364,6 +364,50 @@ static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { HCLGE_OPC_DFX_SSU_REG_2 }; +static const struct key_info meta_data_key_info[] = { + { PACKET_TYPE_ID, 6}, + { IP_FRAGEMENT, 1}, + { ROCE_TYPE, 1}, + { NEXT_KEY, 5}, + { VLAN_NUMBER, 2}, + { SRC_VPORT, 12}, + { DST_VPORT, 12}, + { TUNNEL_PACKET, 1}, +}; + +static const struct key_info tuple_key_info[] = { + { OUTER_DST_MAC, 48}, + { OUTER_SRC_MAC, 48}, + { OUTER_VLAN_TAG_FST, 16}, + { OUTER_VLAN_TAG_SEC, 16}, + { OUTER_ETH_TYPE, 16}, + { OUTER_L2_RSV, 16}, + { OUTER_IP_TOS, 8}, + { OUTER_IP_PROTO, 8}, + { OUTER_SRC_IP, 32}, + { OUTER_DST_IP, 32}, + { OUTER_L3_RSV, 16}, + { OUTER_SRC_PORT, 16}, + { OUTER_DST_PORT, 16}, + { OUTER_L4_RSV, 32}, + { OUTER_TUN_VNI, 24}, + { OUTER_TUN_FLOW_ID, 8}, + { INNER_DST_MAC, 48}, + { INNER_SRC_MAC, 48}, + { INNER_VLAN_TAG_FST, 16}, + { INNER_VLAN_TAG_SEC, 16}, + { INNER_ETH_TYPE, 16}, + { INNER_L2_RSV, 16}, + { INNER_IP_TOS, 8}, + { INNER_IP_PROTO, 8}, + { INNER_SRC_IP, 32}, + { INNER_DST_IP, 32}, + { INNER_L3_RSV, 16}, + { INNER_SRC_PORT, 16}, + { INNER_DST_PORT, 16}, + { INNER_L4_RSV, 32}, +}; + static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) { #define HCLGE_MAC_CMD_NUM 21 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 7c28933e6f3d..7ff03b9605e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -539,50 +539,6 @@ struct key_info { u8 key_length; /* use bit as unit */ }; -static const struct key_info meta_data_key_info[] = { - { PACKET_TYPE_ID, 6}, - { IP_FRAGEMENT, 1}, - { ROCE_TYPE, 1}, - { NEXT_KEY, 5}, - { VLAN_NUMBER, 2}, - { SRC_VPORT, 12}, - { DST_VPORT, 12}, - { TUNNEL_PACKET, 1}, -}; - -static const struct key_info tuple_key_info[] = { - { OUTER_DST_MAC, 48}, - { OUTER_SRC_MAC, 48}, - { OUTER_VLAN_TAG_FST, 16}, - { OUTER_VLAN_TAG_SEC, 16}, - { OUTER_ETH_TYPE, 16}, - { OUTER_L2_RSV, 16}, - { OUTER_IP_TOS, 8}, - { OUTER_IP_PROTO, 8}, - { OUTER_SRC_IP, 32}, - { OUTER_DST_IP, 32}, - { OUTER_L3_RSV, 16}, - { OUTER_SRC_PORT, 16}, - { OUTER_DST_PORT, 16}, - { OUTER_L4_RSV, 32}, - { OUTER_TUN_VNI, 24}, - { OUTER_TUN_FLOW_ID, 8}, - { INNER_DST_MAC, 48}, - { INNER_SRC_MAC, 48}, - { INNER_VLAN_TAG_FST, 16}, - { INNER_VLAN_TAG_SEC, 16}, - { INNER_ETH_TYPE, 16}, - { INNER_L2_RSV, 16}, - { INNER_IP_TOS, 8}, - { INNER_IP_PROTO, 8}, - { INNER_SRC_IP, 32}, - { INNER_DST_IP, 32}, - { INNER_L3_RSV, 16}, - { INNER_SRC_PORT, 16}, - { INNER_DST_PORT, 16}, - { INNER_L4_RSV, 32}, -}; - #define MAX_KEY_LENGTH 400 #define MAX_KEY_DWORDS DIV_ROUND_UP(MAX_KEY_LENGTH / 8, 4) #define MAX_KEY_BYTES (MAX_KEY_DWORDS * 4) -- GitLab From dd016aca28f67603f32c4e666805db519df2120a Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 22 Aug 2019 18:00:40 +0200 Subject: [PATCH 4331/7155] =?UTF-8?q?net/core/skmsg:=20Delete=20an=20unnec?= =?UTF-8?q?essary=20check=20before=20the=20function=20call=20=E2=80=9Ccons?= =?UTF-8?q?ume=5Fskb=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The consume_skb() function performs also input parameter validation. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Song Liu Signed-off-by: David S. Miller --- net/core/skmsg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 6832eeb4b785..cf390e0aa73d 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -190,8 +190,7 @@ static int __sk_msg_free(struct sock *sk, struct sk_msg *msg, u32 i, sk_msg_check_to_free(msg, i, msg->sg.size); sge = sk_msg_elem(msg, i); } - if (msg->skb) - consume_skb(msg->skb); + consume_skb(msg->skb); sk_msg_init(msg); return freed; } -- GitLab From fbbdbc6473070dcb3ee1d69cf1c49ff78677d716 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 23 Aug 2019 01:51:41 -0400 Subject: [PATCH 4332/7155] bnxt_en: Fix allocation of zero statistics block size regression. Recent commit added logic to determine the appropriate statistics block size to allocate and the size is stored in bp->hw_ring_stats_size. But if the firmware spec is older than 1.6.0, it is 0 and not initialized. This causes the allocation to fail with size 0 and bnxt_open() to abort. Fix it by always initializing bp->hw_ring_stats_size to the legacy default size value. Fixes: 4e7485066373 ("bnxt_en: Allocate the larger per-ring statistics block for 57500 chips.") Reported-by: Jonathan Lemon Signed-off-by: Michael Chan Tested-by: Jonathan Lemon Acked-by: Jonathan Lemon Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4c790ffa1a73..b9ad43d3dc51 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4985,6 +4985,7 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) struct hwrm_vnic_qcaps_input req = {0}; int rc; + bp->hw_ring_stats_size = sizeof(struct ctx_hw_stats); if (bp->hwrm_spec_code < 0x10600) return 0; @@ -5004,8 +5005,6 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) if (bp->max_tpa_v2) bp->hw_ring_stats_size = sizeof(struct ctx_hw_stats_ext); - else - bp->hw_ring_stats_size = sizeof(struct ctx_hw_stats); } mutex_unlock(&bp->hwrm_cmd_lock); return rc; -- GitLab From 7c47f5afdeef763599f1ae22d29b8c3904c58315 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:47 +0200 Subject: [PATCH 4333/7155] s390/qdio: enable drivers to poll for Output completions While commit d36deae75011 ("qdio: extend API to allow polling") enhanced the qdio layer so that drivers can poll their Input Queues, we don't have the corresponding infrastructure for Output Queues yet. Factor out a helper that scans a single QDIO Queue, so that qeth can implement TX NAPI on top of it. While doing so, remove the duplicated tracking of the next-to-scan index (q->first_to_check vs q->first_to_kick) in this code path. qdio_handle_aobs() needs to move slightly upwards in the code hierarchy, so that it's still called from the polling path. Signed-off-by: Julian Wiedmann Acked-by: Vasily Gorbik Signed-off-by: David S. Miller --- arch/s390/include/asm/qdio.h | 3 ++ drivers/s390/cio/qdio_main.c | 64 ++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index f647d565bd6d..79b4a3e9dc5d 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -416,6 +416,9 @@ extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int, extern int qdio_start_irq(struct ccw_device *, int); extern int qdio_stop_irq(struct ccw_device *, int); extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *); +extern int qdio_inspect_queue(struct ccw_device *cdev, unsigned int nr, + bool is_input, unsigned int *bufnr, + unsigned int *error); extern int qdio_shutdown(struct ccw_device *, int); extern int qdio_free(struct ccw_device *); extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 4142c85e77d8..5efba0d29190 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -647,8 +647,6 @@ static void qdio_kick_handler(struct qdio_q *q, unsigned int count) qperf_inc(q, outbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", start, count); - if (q->u.out.use_cq) - qdio_handle_aobs(q, start, count); } q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, @@ -774,8 +772,11 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start) count = get_outbound_buffer_frontier(q, start); - if (count) + if (count) { DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); + if (q->u.out.use_cq) + qdio_handle_aobs(q, start, count); + } return count; } @@ -1655,6 +1656,44 @@ int qdio_start_irq(struct ccw_device *cdev, int nr) } EXPORT_SYMBOL(qdio_start_irq); +static int __qdio_inspect_queue(struct qdio_q *q, unsigned int *bufnr, + unsigned int *error) +{ + unsigned int start = q->first_to_check; + int count; + + count = q->is_input_q ? qdio_inbound_q_moved(q, start) : + qdio_outbound_q_moved(q, start); + if (count == 0) + return 0; + + *bufnr = start; + *error = q->qdio_error; + + /* for the next time */ + q->first_to_check = add_buf(start, count); + q->qdio_error = 0; + + return count; +} + +int qdio_inspect_queue(struct ccw_device *cdev, unsigned int nr, bool is_input, + unsigned int *bufnr, unsigned int *error) +{ + struct qdio_irq *irq_ptr = cdev->private->qdio_data; + struct qdio_q *q; + + if (!irq_ptr) + return -ENODEV; + q = is_input ? irq_ptr->input_qs[nr] : irq_ptr->output_qs[nr]; + + if (need_siga_sync(q)) + qdio_siga_sync_q(q); + + return __qdio_inspect_queue(q, bufnr, error); +} +EXPORT_SYMBOL_GPL(qdio_inspect_queue); + /** * qdio_get_next_buffers - process input buffers * @cdev: associated ccw_device for the qdio subchannel @@ -1672,13 +1711,10 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr, { struct qdio_q *q; struct qdio_irq *irq_ptr = cdev->private->qdio_data; - unsigned int start; - int count; if (!irq_ptr) return -ENODEV; q = irq_ptr->input_qs[nr]; - start = q->first_to_check; /* * Cannot rely on automatic sync after interrupt since queues may @@ -1689,25 +1725,11 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr, qdio_check_outbound_pci_queues(irq_ptr); - count = qdio_inbound_q_moved(q, start); - if (count == 0) - return 0; - - start = add_buf(start, count); - q->first_to_check = start; - /* Note: upper-layer MUST stop processing immediately here ... */ if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) return -EIO; - *bufnr = q->first_to_kick; - *error = q->qdio_error; - - /* for the next time */ - q->first_to_kick = add_buf(q->first_to_kick, count); - q->qdio_error = 0; - - return count; + return __qdio_inspect_queue(q, bufnr, error); } EXPORT_SYMBOL(qdio_get_next_buffers); -- GitLab From 313dc689b16c08b081939ee9b87dac3736c780e3 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:48 +0200 Subject: [PATCH 4334/7155] s390/qdio: let drivers opt-out from Output Queue scanning If a driver wants to use the new Output Queue poll code, then the qdio layer must disable its internal Queue scanning. Let the driver select this mode by passing a special scan_threshold of 0. As the scan_threshold is the same for all Output Queues, also move it into the main qdio_irq struct. This allows for fast opt-out checking, a driver is expected to operate either _all_ or none of its Output Queues in polling mode. Signed-off-by: Julian Wiedmann Acked-by: Vasily Gorbik Signed-off-by: David S. Miller --- arch/s390/include/asm/qdio.h | 2 +- drivers/s390/cio/qdio.h | 3 +-- drivers/s390/cio/qdio_main.c | 11 ++++++++--- drivers/s390/cio/qdio_setup.c | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 79b4a3e9dc5d..556d3e703fae 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -359,7 +359,7 @@ struct qdio_initialize { qdio_handler_t *output_handler; void (**queue_start_poll_array) (struct ccw_device *, int, unsigned long); - int scan_threshold; + unsigned int scan_threshold; unsigned long int_parm; struct qdio_buffer **input_sbal_addr_array; struct qdio_buffer **output_sbal_addr_array; diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index a06944399865..a58b45df95d7 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -206,8 +206,6 @@ struct qdio_output_q { struct qdio_outbuf_state *sbal_state; /* timer to check for more outbound work */ struct timer_list timer; - /* used SBALs before tasklet schedule */ - int scan_threshold; }; /* @@ -295,6 +293,7 @@ struct qdio_irq { struct qdio_ssqd_desc ssqd_desc; void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); + unsigned int scan_threshold; /* used SBALs before tasklet schedule */ int perf_stat_enabled; struct qdr *qdr; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 5efba0d29190..5b63c505a2f7 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -880,7 +880,7 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq) struct qdio_q *out; int i; - if (!pci_out_supported(irq)) + if (!pci_out_supported(irq) || !irq->scan_threshold) return; for_each_output_queue(irq, out, i) @@ -973,7 +973,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) } } - if (!pci_out_supported(irq_ptr)) + if (!pci_out_supported(irq_ptr) || !irq_ptr->scan_threshold) return; for_each_output_queue(irq_ptr, q, i) { @@ -1528,6 +1528,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, static int handle_outbound(struct qdio_q *q, unsigned int callflags, int bufnr, int count) { + const unsigned int scan_threshold = q->irq_ptr->scan_threshold; unsigned char state = 0; int used, rc = 0; @@ -1566,8 +1567,12 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, rc = qdio_kick_outbound_q(q, 0); } + /* Let drivers implement their own completion scanning: */ + if (!scan_threshold) + return rc; + /* in case of SIGA errors we must process the error immediately */ - if (used >= q->u.out.scan_threshold || rc) + if (used >= scan_threshold || rc) qdio_tasklet_schedule(q); else /* free the SBALs in case of no further traffic */ diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index d4101cecdc8d..f4ca1d29d61b 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -248,7 +248,6 @@ static void setup_queues(struct qdio_irq *irq_ptr, output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q; q->is_input_q = 0; - q->u.out.scan_threshold = qdio_init->scan_threshold; setup_storage_lists(q, irq_ptr, output_sbal_array, i); output_sbal_array += QDIO_MAX_BUFFERS_PER_Q; @@ -474,6 +473,7 @@ int qdio_setup_irq(struct qdio_initialize *init_data) irq_ptr->nr_input_qs = init_data->no_input_qs; irq_ptr->nr_output_qs = init_data->no_output_qs; irq_ptr->cdev = init_data->cdev; + irq_ptr->scan_threshold = init_data->scan_threshold; ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid); setup_queues(irq_ptr, init_data); -- GitLab From eeac0e20a173dd9407e7092b3ddb45917249d68d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:49 +0200 Subject: [PATCH 4335/7155] s390/qeth: collect accurate TX statistics This consolidates the SW statistics code, and improves it to (1) account for the header overhead of each segment on a TSO skb, (2) count dangling packets as in-error (during eg. shutdown), and (3) only count offloads when the skb was successfully transmitted. We also count each segment of an TSO skb as one packet - except for tx_dropped, to be consistent with dev->tx_dropped. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_core_main.c | 66 +++++++++++++++++++------------ drivers/s390/net/qeth_l2_main.c | 12 ++---- drivers/s390/net/qeth_l3_main.c | 9 ++--- 4 files changed, 49 insertions(+), 39 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 72755a025b4d..a0911ce55db3 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 44fbaa4f7264..d7a15a88bdba 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -71,7 +71,7 @@ static void qeth_free_qdio_queues(struct qeth_card *card); static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf, enum iucv_tx_notify notification); -static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); +static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); static void qeth_close_dev_handler(struct work_struct *work) @@ -411,7 +411,7 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, /* release here to avoid interleaving between outbound tasklet and inbound tasklet regarding notifications and lifecycle */ - qeth_release_skbs(c); + qeth_tx_complete_buf(c, forced_cleanup); c = f->next_pending; WARN_ON_ONCE(head->next_pending != f); @@ -1077,22 +1077,51 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, } } -static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf) +static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error) { + struct qeth_qdio_out_q *queue = buf->q; struct sk_buff *skb; /* release may never happen from within CQ tasklet scope */ WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) - qeth_notify_skbs(buf->q, buf, TX_NOTIFY_GENERALERROR); + qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR); + + /* Empty buffer? */ + if (buf->next_element_to_fill == 0) + return; + + QETH_TXQ_STAT_INC(queue, bufs); + QETH_TXQ_STAT_ADD(queue, buf_elements, buf->next_element_to_fill); + while ((skb = __skb_dequeue(&buf->skb_list)) != NULL) { + unsigned int bytes = qdisc_pkt_len(skb); + bool is_tso = skb_is_gso(skb); + unsigned int packets; + + packets = is_tso ? skb_shinfo(skb)->gso_segs : 1; + if (error) { + QETH_TXQ_STAT_ADD(queue, tx_errors, packets); + } else { + QETH_TXQ_STAT_ADD(queue, tx_packets, packets); + QETH_TXQ_STAT_ADD(queue, tx_bytes, bytes); + if (skb->ip_summed == CHECKSUM_PARTIAL) + QETH_TXQ_STAT_ADD(queue, skbs_csum, packets); + if (skb_is_nonlinear(skb)) + QETH_TXQ_STAT_INC(queue, skbs_sg); + if (is_tso) { + QETH_TXQ_STAT_INC(queue, skbs_tso); + QETH_TXQ_STAT_ADD(queue, tso_bytes, bytes); + } + } - while ((skb = __skb_dequeue(&buf->skb_list)) != NULL) consume_skb(skb); + } } static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, - struct qeth_qdio_out_buffer *buf) + struct qeth_qdio_out_buffer *buf, + bool error) { int i; @@ -1100,7 +1129,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ) atomic_dec(&queue->set_pci_flags_count); - qeth_release_skbs(buf); + qeth_tx_complete_buf(buf, error); for (i = 0; i < queue->max_elements; ++i) { if (buf->buffer->element[i].addr && buf->is_header[i]) @@ -1122,7 +1151,7 @@ static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free) if (!q->bufs[j]) continue; qeth_cleanup_handled_pending(q, j, 1); - qeth_clear_output_buffer(q, q->bufs[j]); + qeth_clear_output_buffer(q, q->bufs[j], true); if (free) { kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]); q->bufs[j] = NULL; @@ -3240,14 +3269,12 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, } } - QETH_TXQ_STAT_ADD(queue, bufs, count); qdio_flags = QDIO_FLAG_SYNC_OUTPUT; if (atomic_read(&queue->set_pci_flags_count)) qdio_flags |= QDIO_FLAG_PCI_OUT; rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count); if (rc) { - QETH_TXQ_STAT_ADD(queue, tx_errors, count); /* ignore temporary SIGA errors without busy condition */ if (rc == -ENOBUFS) return; @@ -3456,7 +3483,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, qeth_notify_skbs(queue, buffer, n); } - qeth_clear_output_buffer(queue, buffer); + qeth_clear_output_buffer(queue, buffer, qdio_error); } qeth_cleanup_handled_pending(queue, bidx, 0); } @@ -3942,7 +3969,6 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, unsigned int hd_len = 0; unsigned int elements; int push_len, rc; - bool is_sg; if (is_tso) { hw_hdr_len = sizeof(struct qeth_hdr_tso); @@ -3971,7 +3997,6 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, qeth_fill_tso_ext((struct qeth_hdr_tso *) hdr, frame_len - proto_len, skb, proto_len); - is_sg = skb_is_nonlinear(skb); if (IS_IQD(card)) { rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset, hd_len); @@ -3982,18 +4007,9 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, hd_len, elements); } - if (!rc) { - QETH_TXQ_STAT_ADD(queue, buf_elements, elements); - if (is_sg) - QETH_TXQ_STAT_INC(queue, skbs_sg); - if (is_tso) { - QETH_TXQ_STAT_INC(queue, skbs_tso); - QETH_TXQ_STAT_ADD(queue, tso_bytes, frame_len); - } - } else { - if (!push_len) - kmem_cache_free(qeth_core_header_cache, hdr); - } + if (rc && !push_len) + kmem_cache_free(qeth_core_header_cache, hdr); + return rc; } EXPORT_SYMBOL_GPL(qeth_xmit); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 662bd51f922f..b8799cd3e7aa 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -175,10 +175,8 @@ static void qeth_l2_fill_header(struct qeth_qdio_out_q *queue, hdr->hdr.l2.id = QETH_HEADER_TYPE_L2_TSO; } else { hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_PARTIAL) qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv); - QETH_TXQ_STAT_INC(queue, skbs_csum); - } } /* set byte byte 3 to casting flags */ @@ -588,9 +586,10 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, struct qeth_card *card = dev->ml_priv; u16 txq = skb_get_queue_mapping(skb); struct qeth_qdio_out_q *queue; - int tx_bytes = skb->len; int rc; + if (!skb_is_gso(skb)) + qdisc_skb_cb(skb)->pkt_len = skb->len; if (IS_IQD(card)) txq = qeth_iqd_translate_txq(dev, txq); queue = card->qdio.out_qs[txq]; @@ -601,11 +600,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, rc = qeth_xmit(card, skb, queue, qeth_get_ip_version(skb), qeth_l2_fill_header); - if (!rc) { - QETH_TXQ_STAT_INC(queue, tx_packets); - QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes); + if (!rc) return NETDEV_TX_OK; - } QETH_TXQ_STAT_INC(queue, tx_dropped); kfree_skb(skb); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 54799fe6a700..d7bfc7a0e4c0 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1957,7 +1957,6 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue, /* some HW requires combined L3+L4 csum offload: */ if (ipv == 4) hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_HDR_REQ; - QETH_TXQ_STAT_INC(queue, skbs_csum); } } @@ -2044,9 +2043,10 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, u16 txq = skb_get_queue_mapping(skb); int ipv = qeth_get_ip_version(skb); struct qeth_qdio_out_q *queue; - int tx_bytes = skb->len; int rc; + if (!skb_is_gso(skb)) + qdisc_skb_cb(skb)->pkt_len = skb->len; if (IS_IQD(card)) { queue = card->qdio.out_qs[qeth_iqd_translate_txq(dev, txq)]; @@ -2069,11 +2069,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, else rc = qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header); - if (!rc) { - QETH_TXQ_STAT_INC(queue, tx_packets); - QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes); + if (!rc) return NETDEV_TX_OK; - } tx_drop: QETH_TXQ_STAT_INC(queue, tx_dropped); -- GitLab From e53edf743d26b39dfd78af43ff97620a4ac13ffc Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:50 +0200 Subject: [PATCH 4336/7155] s390/qeth: add TX NAPI support for IQD devices Due to their large MTU and potentially low utilization of TX buffers, IQD devices in particular require fast TX recycling. This makes them a prime candidate for a TX NAPI path in qeth. qeth_tx_poll() uses the recently introduced qdio_inspect_queue() helper to poll the TX queue for completed buffers. To avoid hogging the CPU for too long, we yield to the stack after completing an entire queue's worth of buffers. While IQD is expected to transfer its buffers synchronously (and thus doesn't support TX interrupts), a timer covers for the odd case where a TX buffer doesn't complete synchronously. Currently this timer should only ever fire for (1) the mcast queue, (2) the occasional race, where the NAPI poll code observes an update to queue->used_buffers while the TX doorbell hasn't been issued yet. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- arch/s390/include/asm/qdio.h | 1 + drivers/s390/net/qeth_core.h | 26 ++++ drivers/s390/net/qeth_core_main.c | 202 +++++++++++++++++++++++------- drivers/s390/net/qeth_ethtool.c | 2 + 4 files changed, 183 insertions(+), 48 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 556d3e703fae..78e8a888306d 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -16,6 +16,7 @@ #define QDIO_MAX_QUEUES_PER_IRQ 4 #define QDIO_MAX_BUFFERS_PER_Q 128 #define QDIO_MAX_BUFFERS_MASK (QDIO_MAX_BUFFERS_PER_Q - 1) +#define QDIO_BUFNR(num) ((num) & QDIO_MAX_BUFFERS_MASK) #define QDIO_MAX_ELEMENTS_PER_BUFFER 16 #define QDIO_SBAL_SIZE 256 diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a0911ce55db3..ae2ae17e3e76 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -474,6 +475,8 @@ struct qeth_out_q_stats { u64 tso_bytes; u64 packing_mode_switch; u64 stopped; + u64 completion_yield; + u64 completion_timer; /* rtnl_link_stats64 */ u64 tx_packets; @@ -482,6 +485,8 @@ struct qeth_out_q_stats { u64 tx_dropped; }; +#define QETH_TX_TIMER_USECS 500 + struct qeth_qdio_out_q { struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; @@ -500,13 +505,34 @@ struct qeth_qdio_out_q { atomic_t used_buffers; /* indicates whether PCI flag must be set (or if one is outstanding) */ atomic_t set_pci_flags_count; + struct napi_struct napi; + struct timer_list timer; }; +#define qeth_for_each_output_queue(card, q, i) \ + for (i = 0; i < card->qdio.no_out_queues && \ + (q = card->qdio.out_qs[i]); i++) + +#define qeth_napi_to_out_queue(n) container_of(n, struct qeth_qdio_out_q, napi) + +static inline void qeth_tx_arm_timer(struct qeth_qdio_out_q *queue) +{ + if (timer_pending(&queue->timer)) + return; + mod_timer(&queue->timer, usecs_to_jiffies(QETH_TX_TIMER_USECS) + + jiffies); +} + static inline bool qeth_out_queue_is_full(struct qeth_qdio_out_q *queue) { return atomic_read(&queue->used_buffers) >= QDIO_MAX_BUFFERS_PER_Q; } +static inline bool qeth_out_queue_is_empty(struct qeth_qdio_out_q *queue) +{ + return atomic_read(&queue->used_buffers) == 0; +} + struct qeth_qdio_info { atomic_t state; /* input */ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d7a15a88bdba..3223ad80998c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2284,6 +2284,14 @@ static struct qeth_qdio_out_q *qeth_alloc_output_queue(void) return q; } +static void qeth_tx_completion_timer(struct timer_list *timer) +{ + struct qeth_qdio_out_q *queue = from_timer(queue, timer, timer); + + napi_schedule(&queue->napi); + QETH_TXQ_STAT_INC(queue, completion_timer); +} + static int qeth_alloc_qdio_queues(struct qeth_card *card) { int i, j; @@ -2305,17 +2313,22 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) /* outbound */ for (i = 0; i < card->qdio.no_out_queues; ++i) { - card->qdio.out_qs[i] = qeth_alloc_output_queue(); - if (!card->qdio.out_qs[i]) + struct qeth_qdio_out_q *queue; + + queue = qeth_alloc_output_queue(); + if (!queue) goto out_freeoutq; QETH_CARD_TEXT_(card, 2, "outq %i", i); - QETH_CARD_HEX(card, 2, &card->qdio.out_qs[i], sizeof(void *)); - card->qdio.out_qs[i]->card = card; - card->qdio.out_qs[i]->queue_no = i; + QETH_CARD_HEX(card, 2, &queue, sizeof(void *)); + card->qdio.out_qs[i] = queue; + queue->card = card; + queue->queue_no = i; + timer_setup(&queue->timer, qeth_tx_completion_timer, 0); + /* give outbound qeth_qdio_buffers their qdio_buffers */ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { - WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL); - if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j)) + WARN_ON(queue->bufs[j]); + if (qeth_init_qdio_out_buf(queue, j)) goto out_freeoutqbufs; } } @@ -3226,6 +3239,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, int count) { + struct qeth_card *card = queue->card; struct qeth_qdio_out_buffer *buf; int rc; int i; @@ -3274,6 +3288,11 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, qdio_flags |= QDIO_FLAG_PCI_OUT; rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count); + + /* Fake the TX completion interrupt: */ + if (IS_IQD(card)) + napi_schedule(&queue->napi); + if (rc) { /* ignore temporary SIGA errors without busy condition */ if (rc == -ENOBUFS) @@ -3452,48 +3471,12 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, int bidx = i % QDIO_MAX_BUFFERS_PER_Q; buffer = queue->bufs[bidx]; qeth_handle_send_error(card, buffer, qdio_error); - - if (queue->bufstates && - (queue->bufstates[bidx].flags & - QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) { - WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); - - if (atomic_cmpxchg(&buffer->state, - QETH_QDIO_BUF_PRIMED, - QETH_QDIO_BUF_PENDING) == - QETH_QDIO_BUF_PRIMED) { - qeth_notify_skbs(queue, buffer, - TX_NOTIFY_PENDING); - } - QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx); - - /* prepare the queue slot for re-use: */ - qeth_scrub_qdio_buffer(buffer->buffer, - queue->max_elements); - if (qeth_init_qdio_out_buf(queue, bidx)) { - QETH_CARD_TEXT(card, 2, "outofbuf"); - qeth_schedule_recovery(card); - } - } else { - if (card->options.cq == QETH_CQ_ENABLED) { - enum iucv_tx_notify n; - - n = qeth_compute_cq_notification( - buffer->buffer->element[15].sflags, 0); - qeth_notify_skbs(queue, buffer, n); - } - - qeth_clear_output_buffer(queue, buffer, qdio_error); - } - qeth_cleanup_handled_pending(queue, bidx, 0); + qeth_clear_output_buffer(queue, buffer, qdio_error); } + atomic_sub(count, &queue->used_buffers); - /* check if we need to do something on this outbound queue */ - if (!IS_IQD(card)) - qeth_check_outbound_queue(queue); + qeth_check_outbound_queue(queue); - if (IS_IQD(card)) - __queue = qeth_iqd_translate_txq(dev, __queue); txq = netdev_get_tx_queue(dev, __queue); /* xmit may have observed the full-condition, but not yet stopped the * txq. In which case the code below won't trigger. So before returning, @@ -4740,7 +4723,7 @@ static int qeth_qdio_establish(struct qeth_card *card) init_data.input_sbal_addr_array = in_sbal_ptrs; init_data.output_sbal_addr_array = out_sbal_ptrs; init_data.output_sbal_state_array = card->qdio.out_bufstates; - init_data.scan_threshold = IS_IQD(card) ? 1 : 32; + init_data.scan_threshold = IS_IQD(card) ? 0 : 32; if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { @@ -5154,6 +5137,99 @@ int qeth_poll(struct napi_struct *napi, int budget) } EXPORT_SYMBOL_GPL(qeth_poll); +static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, + unsigned int bidx, bool error) +{ + struct qeth_qdio_out_buffer *buffer = queue->bufs[bidx]; + u8 sflags = buffer->buffer->element[15].sflags; + struct qeth_card *card = queue->card; + + if (queue->bufstates && (queue->bufstates[bidx].flags & + QDIO_OUTBUF_STATE_FLAG_PENDING)) { + WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); + + if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, + QETH_QDIO_BUF_PENDING) == + QETH_QDIO_BUF_PRIMED) + qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING); + + QETH_CARD_TEXT_(card, 5, "pel%u", bidx); + + /* prepare the queue slot for re-use: */ + qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements); + if (qeth_init_qdio_out_buf(queue, bidx)) { + QETH_CARD_TEXT(card, 2, "outofbuf"); + qeth_schedule_recovery(card); + } + + return; + } + + if (card->options.cq == QETH_CQ_ENABLED) + qeth_notify_skbs(queue, buffer, + qeth_compute_cq_notification(sflags, 0)); + qeth_clear_output_buffer(queue, buffer, error); +} + +static int qeth_tx_poll(struct napi_struct *napi, int budget) +{ + struct qeth_qdio_out_q *queue = qeth_napi_to_out_queue(napi); + unsigned int queue_no = queue->queue_no; + struct qeth_card *card = queue->card; + struct net_device *dev = card->dev; + unsigned int work_done = 0; + struct netdev_queue *txq; + + txq = netdev_get_tx_queue(dev, qeth_iqd_translate_txq(dev, queue_no)); + + while (1) { + unsigned int start, error, i; + int completed; + + if (qeth_out_queue_is_empty(queue)) { + napi_complete(napi); + return 0; + } + + /* Give the CPU a breather: */ + if (work_done >= QDIO_MAX_BUFFERS_PER_Q) { + QETH_TXQ_STAT_INC(queue, completion_yield); + if (napi_complete_done(napi, 0)) + napi_schedule(napi); + return 0; + } + + completed = qdio_inspect_queue(CARD_DDEV(card), queue_no, false, + &start, &error); + if (completed <= 0) { + /* Ensure we see TX completion for pending work: */ + if (napi_complete_done(napi, 0)) + qeth_tx_arm_timer(queue); + return 0; + } + + for (i = start; i < start + completed; i++) { + unsigned int bidx = QDIO_BUFNR(i); + + qeth_handle_send_error(card, queue->bufs[bidx], error); + qeth_iqd_tx_complete(queue, bidx, error); + qeth_cleanup_handled_pending(queue, bidx, false); + } + + atomic_sub(completed, &queue->used_buffers); + work_done += completed; + + /* xmit may have observed the full-condition, but not yet + * stopped the txq. In which case the code below won't trigger. + * So before returning, xmit will re-check the txq's fill level + * and wake it up if needed. + */ + if (netif_tx_queue_stopped(txq) && + !qeth_out_queue_is_full(queue)) + netif_tx_wake_queue(txq); + } +} + static int qeth_setassparms_inspect_rc(struct qeth_ipa_cmd *cmd) { if (!cmd->hdr.return_code) @@ -6100,6 +6176,17 @@ int qeth_open(struct net_device *dev) napi_enable(&card->napi); local_bh_disable(); napi_schedule(&card->napi); + if (IS_IQD(card)) { + struct qeth_qdio_out_q *queue; + unsigned int i; + + qeth_for_each_output_queue(card, queue, i) { + netif_tx_napi_add(dev, &queue->napi, qeth_tx_poll, + QETH_NAPI_WEIGHT); + napi_enable(&queue->napi); + napi_schedule(&queue->napi); + } + } /* kick-start the NAPI softirq: */ local_bh_enable(); return 0; @@ -6111,7 +6198,26 @@ int qeth_stop(struct net_device *dev) struct qeth_card *card = dev->ml_priv; QETH_CARD_TEXT(card, 4, "qethstop"); - netif_tx_disable(dev); + if (IS_IQD(card)) { + struct qeth_qdio_out_q *queue; + unsigned int i; + + /* Quiesce the NAPI instances: */ + qeth_for_each_output_queue(card, queue, i) { + napi_disable(&queue->napi); + del_timer_sync(&queue->timer); + } + + /* Stop .ndo_start_xmit, might still access queue->napi. */ + netif_tx_disable(dev); + + /* Queues may get re-allocated, so remove the NAPIs here. */ + qeth_for_each_output_queue(card, queue, i) + netif_napi_del(&queue->napi); + } else { + netif_tx_disable(dev); + } + napi_disable(&card->napi); return 0; } diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index 4166eb29f0bd..096698df3886 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -39,6 +39,8 @@ static const struct qeth_stats txq_stats[] = { QETH_TXQ_STAT("TSO bytes", tso_bytes), QETH_TXQ_STAT("Packing mode switches", packing_mode_switch), QETH_TXQ_STAT("Queue stopped", stopped), + QETH_TXQ_STAT("Completion yield", completion_yield), + QETH_TXQ_STAT("Completion timer", completion_timer), }; static const struct qeth_stats card_stats[] = { -- GitLab From 85e537d8f1b6b1201ced628b124b3d08436f5a04 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:51 +0200 Subject: [PATCH 4337/7155] s390/qeth: when in TX NAPI mode, use napi_consume_skb() This allows the stack to bulk-free our TX-completed skbs. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3223ad80998c..70c7e675431e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -71,7 +71,8 @@ static void qeth_free_qdio_queues(struct qeth_card *card); static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf, enum iucv_tx_notify notification); -static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error); +static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, + int budget); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); static void qeth_close_dev_handler(struct work_struct *work) @@ -411,7 +412,7 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, /* release here to avoid interleaving between outbound tasklet and inbound tasklet regarding notifications and lifecycle */ - qeth_tx_complete_buf(c, forced_cleanup); + qeth_tx_complete_buf(c, forced_cleanup, 0); c = f->next_pending; WARN_ON_ONCE(head->next_pending != f); @@ -1077,7 +1078,8 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, } } -static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error) +static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, + int budget) { struct qeth_qdio_out_q *queue = buf->q; struct sk_buff *skb; @@ -1115,13 +1117,13 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error) } } - consume_skb(skb); + napi_consume_skb(skb, budget); } } static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf, - bool error) + bool error, int budget) { int i; @@ -1129,7 +1131,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ) atomic_dec(&queue->set_pci_flags_count); - qeth_tx_complete_buf(buf, error); + qeth_tx_complete_buf(buf, error, budget); for (i = 0; i < queue->max_elements; ++i) { if (buf->buffer->element[i].addr && buf->is_header[i]) @@ -1151,7 +1153,7 @@ static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free) if (!q->bufs[j]) continue; qeth_cleanup_handled_pending(q, j, 1); - qeth_clear_output_buffer(q, q->bufs[j], true); + qeth_clear_output_buffer(q, q->bufs[j], true, 0); if (free) { kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]); q->bufs[j] = NULL; @@ -3471,7 +3473,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, int bidx = i % QDIO_MAX_BUFFERS_PER_Q; buffer = queue->bufs[bidx]; qeth_handle_send_error(card, buffer, qdio_error); - qeth_clear_output_buffer(queue, buffer, qdio_error); + qeth_clear_output_buffer(queue, buffer, qdio_error, 0); } atomic_sub(count, &queue->used_buffers); @@ -5138,7 +5140,7 @@ int qeth_poll(struct napi_struct *napi, int budget) EXPORT_SYMBOL_GPL(qeth_poll); static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, - unsigned int bidx, bool error) + unsigned int bidx, bool error, int budget) { struct qeth_qdio_out_buffer *buffer = queue->bufs[bidx]; u8 sflags = buffer->buffer->element[15].sflags; @@ -5168,7 +5170,7 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, if (card->options.cq == QETH_CQ_ENABLED) qeth_notify_skbs(queue, buffer, qeth_compute_cq_notification(sflags, 0)); - qeth_clear_output_buffer(queue, buffer, error); + qeth_clear_output_buffer(queue, buffer, error, budget); } static int qeth_tx_poll(struct napi_struct *napi, int budget) @@ -5212,7 +5214,7 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget) unsigned int bidx = QDIO_BUFNR(i); qeth_handle_send_error(card, queue->bufs[bidx], error); - qeth_iqd_tx_complete(queue, bidx, error); + qeth_iqd_tx_complete(queue, bidx, error, budget); qeth_cleanup_handled_pending(queue, bidx, false); } -- GitLab From 96bd6c94bdf9de38b0fa0ec679fe40013f1c4576 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:52 +0200 Subject: [PATCH 4338/7155] s390/qeth: add BQL support for IQD devices Each TX buffer may contain multiple skbs. So just accumulate the sent byte count in the buffer struct, and later use the same count when completing the buffer. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_core_main.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index ae2ae17e3e76..d5f796380cd0 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -426,6 +426,7 @@ struct qeth_qdio_out_buffer { struct qdio_buffer *buffer; atomic_t state; int next_element_to_fill; + unsigned int bytes; struct sk_buff_head skb_list; int is_header[QDIO_MAX_ELEMENTS_PER_BUFFER]; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 70c7e675431e..4c7c7d320c9c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1142,6 +1142,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, qeth_scrub_qdio_buffer(buf->buffer, queue->max_elements); buf->next_element_to_fill = 0; + buf->bytes = 0; atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } @@ -2673,6 +2674,7 @@ int qeth_init_qdio_queues(struct qeth_card *card) atomic_set(&queue->used_buffers, 0); atomic_set(&queue->set_pci_flags_count, 0); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); + netdev_tx_reset_queue(netdev_get_tx_queue(card->dev, i)); } return 0; } @@ -3790,6 +3792,7 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, { int index = queue->next_buf_to_fill; struct qeth_qdio_out_buffer *buffer = queue->bufs[index]; + unsigned int bytes = qdisc_pkt_len(skb); struct netdev_queue *txq; bool stopped = false; @@ -3811,6 +3814,9 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, } qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len, stopped); + netdev_tx_sent_queue(txq, bytes); + buffer->bytes += bytes; + qeth_flush_buffers(queue, index, 1); if (stopped && !qeth_out_queue_is_full(queue)) @@ -5186,6 +5192,8 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget) while (1) { unsigned int start, error, i; + unsigned int packets = 0; + unsigned int bytes = 0; int completed; if (qeth_out_queue_is_empty(queue)) { @@ -5211,13 +5219,19 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget) } for (i = start; i < start + completed; i++) { + struct qeth_qdio_out_buffer *buffer; unsigned int bidx = QDIO_BUFNR(i); - qeth_handle_send_error(card, queue->bufs[bidx], error); + buffer = queue->bufs[bidx]; + packets += skb_queue_len(&buffer->skb_list); + bytes += buffer->bytes; + + qeth_handle_send_error(card, buffer, error); qeth_iqd_tx_complete(queue, bidx, error, budget); qeth_cleanup_handled_pending(queue, bidx, false); } + netdev_tx_completed_queue(txq, packets, bytes); atomic_sub(completed, &queue->used_buffers); work_done += completed; -- GitLab From 9549d70a2d71526b8dc41cc0b255219ba46e5bf7 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 23 Aug 2019 11:48:53 +0200 Subject: [PATCH 4339/7155] s390/qeth: add xmit_more support for IQD devices IQD devices offer limited support for bulking: all frames in a TX buffer need to have the same target. qeth_iqd_may_bulk() implements this constraint, and allows us to defer the TX doorbell until (a) the buffer is full (since each buffer needs its own doorbell), or (b) the entire TX queue is full, or (b) we reached the BQL limit. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 24 ++++++ drivers/s390/net/qeth_core_main.c | 128 ++++++++++++++++++++---------- 2 files changed, 109 insertions(+), 43 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d5f796380cd0..e4b55f9aa062 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -378,6 +378,28 @@ enum qeth_header_ids { #define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20 #define QETH_HDR_EXT_UDP 0x40 /*bit off for TCP*/ +static inline bool qeth_l2_same_vlan(struct qeth_hdr_layer2 *h1, + struct qeth_hdr_layer2 *h2) +{ + return !((h1->flags[2] ^ h2->flags[2]) & QETH_LAYER2_FLAG_VLAN) && + h1->vlan_id == h2->vlan_id; +} + +static inline bool qeth_l3_iqd_same_vlan(struct qeth_hdr_layer3 *h1, + struct qeth_hdr_layer3 *h2) +{ + return !((h1->ext_flags ^ h2->ext_flags) & QETH_HDR_EXT_VLAN_FRAME) && + h1->vlan_id == h2->vlan_id; +} + +static inline bool qeth_l3_same_next_hop(struct qeth_hdr_layer3 *h1, + struct qeth_hdr_layer3 *h2) +{ + return !((h1->flags ^ h2->flags) & QETH_HDR_IPV6) && + ipv6_addr_equal(&h1->next_hop.ipv6_addr, + &h2->next_hop.ipv6_addr); +} + enum qeth_qdio_info_states { QETH_QDIO_UNINITIALIZED, QETH_QDIO_ALLOCATED, @@ -508,6 +530,8 @@ struct qeth_qdio_out_q { atomic_t set_pci_flags_count; struct napi_struct napi; struct timer_list timer; + struct qeth_hdr *prev_hdr; + u8 bulk_start; }; #define qeth_for_each_output_queue(card, q, i) \ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4c7c7d320c9c..8b4ea5f2832b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2671,6 +2671,8 @@ int qeth_init_qdio_queues(struct qeth_card *card) queue->max_elements = QETH_MAX_BUFFER_ELEMENTS(card); queue->next_buf_to_fill = 0; queue->do_pack = 0; + queue->prev_hdr = NULL; + queue->bulk_start = 0; atomic_set(&queue->used_buffers, 0); atomic_set(&queue->set_pci_flags_count, 0); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); @@ -3314,6 +3316,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, } } +static void qeth_flush_queue(struct qeth_qdio_out_q *queue) +{ + qeth_flush_buffers(queue, queue->bulk_start, 1); + + queue->bulk_start = QDIO_BUFNR(queue->bulk_start + 1); + queue->prev_hdr = NULL; +} + static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) { int index; @@ -3669,9 +3679,32 @@ static int qeth_add_hw_header(struct qeth_qdio_out_q *queue, return 0; } -static void __qeth_fill_buffer(struct sk_buff *skb, - struct qeth_qdio_out_buffer *buf, - bool is_first_elem, unsigned int offset) +static bool qeth_iqd_may_bulk(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buffer, + struct sk_buff *curr_skb, + struct qeth_hdr *curr_hdr) +{ + struct qeth_hdr *prev_hdr = queue->prev_hdr; + + if (!prev_hdr) + return true; + + /* All packets must have the same target: */ + if (curr_hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { + struct sk_buff *prev_skb = skb_peek(&buffer->skb_list); + + return ether_addr_equal(eth_hdr(prev_skb)->h_dest, + eth_hdr(curr_skb)->h_dest) && + qeth_l2_same_vlan(&prev_hdr->hdr.l2, &curr_hdr->hdr.l2); + } + + return qeth_l3_same_next_hop(&prev_hdr->hdr.l3, &curr_hdr->hdr.l3) && + qeth_l3_iqd_same_vlan(&prev_hdr->hdr.l3, &curr_hdr->hdr.l3); +} + +static unsigned int __qeth_fill_buffer(struct sk_buff *skb, + struct qeth_qdio_out_buffer *buf, + bool is_first_elem, unsigned int offset) { struct qdio_buffer *buffer = buf->buffer; int element = buf->next_element_to_fill; @@ -3728,24 +3761,21 @@ static void __qeth_fill_buffer(struct sk_buff *skb, if (buffer->element[element - 1].eflags) buffer->element[element - 1].eflags = SBAL_EFLAGS_LAST_FRAG; buf->next_element_to_fill = element; + return element; } /** * qeth_fill_buffer() - map skb into an output buffer - * @queue: QDIO queue to submit the buffer on * @buf: buffer to transport the skb * @skb: skb to map into the buffer * @hdr: qeth_hdr for this skb. Either at skb->data, or allocated * from qeth_core_header_cache. * @offset: when mapping the skb, start at skb->data + offset * @hd_len: if > 0, build a dedicated header element of this size - * flush: Prepare the buffer to be flushed, regardless of its fill level. */ -static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, - struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb, struct qeth_hdr *hdr, - unsigned int offset, unsigned int hd_len, - bool flush) +static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf, + struct sk_buff *skb, struct qeth_hdr *hdr, + unsigned int offset, unsigned int hd_len) { struct qdio_buffer *buffer = buf->buffer; bool is_first_elem = true; @@ -3765,36 +3795,22 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, buf->next_element_to_fill++; } - __qeth_fill_buffer(skb, buf, is_first_elem, offset); - - if (!queue->do_pack) { - QETH_CARD_TEXT(queue->card, 6, "fillbfnp"); - } else { - QETH_CARD_TEXT(queue->card, 6, "fillbfpa"); - - QETH_TXQ_STAT_INC(queue, skbs_pack); - /* If the buffer still has free elements, keep using it. */ - if (!flush && - buf->next_element_to_fill < queue->max_elements) - return 0; - } - - /* flush out the buffer */ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; - return 1; + return __qeth_fill_buffer(skb, buf, is_first_elem, offset); } -static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, - struct sk_buff *skb, struct qeth_hdr *hdr, - unsigned int offset, unsigned int hd_len) +static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue, + struct sk_buff *skb, unsigned int elements, + struct qeth_hdr *hdr, unsigned int offset, + unsigned int hd_len) { - int index = queue->next_buf_to_fill; - struct qeth_qdio_out_buffer *buffer = queue->bufs[index]; + struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start]; unsigned int bytes = qdisc_pkt_len(skb); + unsigned int next_element; struct netdev_queue *txq; bool stopped = false; + bool flush; + + txq = netdev_get_tx_queue(card->dev, skb_get_queue_mapping(skb)); /* Just a sanity check, the wake/stop logic should ensure that we always * get a free buffer. @@ -3802,9 +3818,19 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) return -EBUSY; - txq = netdev_get_tx_queue(queue->card->dev, skb_get_queue_mapping(skb)); + if ((buffer->next_element_to_fill + elements > queue->max_elements) || + !qeth_iqd_may_bulk(queue, buffer, skb, hdr)) { + atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); + qeth_flush_queue(queue); + buffer = queue->bufs[queue->bulk_start]; - if (atomic_inc_return(&queue->used_buffers) >= QDIO_MAX_BUFFERS_PER_Q) { + /* Sanity-check again: */ + if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) + return -EBUSY; + } + + if (buffer->next_element_to_fill == 0 && + atomic_inc_return(&queue->used_buffers) >= QDIO_MAX_BUFFERS_PER_Q) { /* If a TX completion happens right _here_ and misses to wake * the txq, then our re-check below will catch the race. */ @@ -3813,11 +3839,17 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, stopped = true; } - qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len, stopped); - netdev_tx_sent_queue(txq, bytes); + next_element = qeth_fill_buffer(buffer, skb, hdr, offset, hd_len); buffer->bytes += bytes; + queue->prev_hdr = hdr; - qeth_flush_buffers(queue, index, 1); + flush = __netdev_tx_sent_queue(txq, bytes, + !stopped && netdev_xmit_more()); + + if (flush || next_element >= queue->max_elements) { + atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); + qeth_flush_queue(queue); + } if (stopped && !qeth_out_queue_is_full(queue)) netif_tx_start_queue(txq); @@ -3830,6 +3862,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, int elements_needed) { struct qeth_qdio_out_buffer *buffer; + unsigned int next_element; struct netdev_queue *txq; bool stopped = false; int start_index; @@ -3892,8 +3925,17 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, stopped = true; } - flush_count += qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len, - stopped); + next_element = qeth_fill_buffer(buffer, skb, hdr, offset, hd_len); + + if (queue->do_pack) + QETH_TXQ_STAT_INC(queue, skbs_pack); + if (!queue->do_pack || stopped || next_element >= queue->max_elements) { + flush_count++; + atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); + queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % + QDIO_MAX_BUFFERS_PER_Q; + } + if (flush_count) qeth_flush_buffers(queue, start_index, flush_count); else if (!atomic_read(&queue->set_pci_flags_count)) @@ -3989,8 +4031,8 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, frame_len - proto_len, skb, proto_len); if (IS_IQD(card)) { - rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset, - hd_len); + rc = __qeth_xmit(card, queue, skb, elements, hdr, data_offset, + hd_len); } else { /* TODO: drop skb_orphan() once TX completion is fast enough */ skb_orphan(skb); -- GitLab From c1236979b4d2cbaef8bb34aec83a44de445e4210 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 25 Aug 2019 01:04:17 +0200 Subject: [PATCH 4340/7155] net: phy: sfp: Add labels to hwmon sensors SFPs can report two different power values, the transmit power and the receive power. Add labels to make it clear which is which. Also add labels to the other sensors, VCC power supply, bias and module temperature. sensors(1) now shows: sff2-isa-0000 Adapter: ISA adapter VCC: +3.23 V temperature: +33.4 C TX_power: 276.00 uW RX_power: 20.00 uW bias: +0.01 A Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/sfp.c | 73 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index e36c04c26866..272d5773573e 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -429,6 +429,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, return 0; /* fall through */ case hwmon_temp_input: + case hwmon_temp_label: return 0444; default: return 0; @@ -447,6 +448,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, return 0; /* fall through */ case hwmon_in_input: + case hwmon_in_label: return 0444; default: return 0; @@ -465,6 +467,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, return 0; /* fall through */ case hwmon_curr_input: + case hwmon_curr_label: return 0444; default: return 0; @@ -492,6 +495,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, return 0; /* fall through */ case hwmon_power_input: + case hwmon_power_label: return 0444; default: return 0; @@ -987,9 +991,63 @@ static int sfp_hwmon_read(struct device *dev, enum hwmon_sensor_types type, } } +static const char *const sfp_hwmon_power_labels[] = { + "TX_power", + "RX_power", +}; + +static int sfp_hwmon_read_string(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_curr: + switch (attr) { + case hwmon_curr_label: + *str = "bias"; + return 0; + default: + return -EOPNOTSUPP; + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_label: + *str = "temperature"; + return 0; + default: + return -EOPNOTSUPP; + } + break; + case hwmon_in: + switch (attr) { + case hwmon_in_label: + *str = "VCC"; + return 0; + default: + return -EOPNOTSUPP; + } + break; + case hwmon_power: + switch (attr) { + case hwmon_power_label: + *str = sfp_hwmon_power_labels[channel]; + return 0; + default: + return -EOPNOTSUPP; + } + break; + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} + static const struct hwmon_ops sfp_hwmon_ops = { .is_visible = sfp_hwmon_is_visible, .read = sfp_hwmon_read, + .read_string = sfp_hwmon_read_string, }; static u32 sfp_hwmon_chip_config[] = { @@ -1007,7 +1065,8 @@ static u32 sfp_hwmon_temp_config[] = { HWMON_T_MAX | HWMON_T_MIN | HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | HWMON_T_CRIT | HWMON_T_LCRIT | - HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, + HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM | + HWMON_T_LABEL, 0, }; @@ -1021,7 +1080,8 @@ static u32 sfp_hwmon_vcc_config[] = { HWMON_I_MAX | HWMON_I_MIN | HWMON_I_MAX_ALARM | HWMON_I_MIN_ALARM | HWMON_I_CRIT | HWMON_I_LCRIT | - HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM, + HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM | + HWMON_I_LABEL, 0, }; @@ -1035,7 +1095,8 @@ static u32 sfp_hwmon_bias_config[] = { HWMON_C_MAX | HWMON_C_MIN | HWMON_C_MAX_ALARM | HWMON_C_MIN_ALARM | HWMON_C_CRIT | HWMON_C_LCRIT | - HWMON_C_CRIT_ALARM | HWMON_C_LCRIT_ALARM, + HWMON_C_CRIT_ALARM | HWMON_C_LCRIT_ALARM | + HWMON_C_LABEL, 0, }; @@ -1050,13 +1111,15 @@ static u32 sfp_hwmon_power_config[] = { HWMON_P_MAX | HWMON_P_MIN | HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM | HWMON_P_CRIT | HWMON_P_LCRIT | - HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM, + HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM | + HWMON_P_LABEL, /* Receive power */ HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MIN | HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM | HWMON_P_CRIT | HWMON_P_LCRIT | - HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM, + HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM | + HWMON_P_LABEL, 0, }; -- GitLab From 0ae9c3213c2ca34f7e7ebad1436267778d37ba9f Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Wed, 5 Jun 2019 11:12:33 +0200 Subject: [PATCH 4341/7155] PM / devfreq: exynos-events: change matching code during probe The patch changes the way how the 'ops' gets populated for different device versions. The matching function now uses 'of_device_id' in order to identify the device type. Signed-off-by: Lukasz Luba Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/event/exynos-ppmu.c | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index aae1fd6c91f7..1756c6b5cb09 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,11 @@ #include "exynos-ppmu.h" +enum exynos_ppmu_type { + EXYNOS_TYPE_PPMU, + EXYNOS_TYPE_PPMU_V2, +}; + struct exynos_ppmu_data { struct clk *clk; }; @@ -33,6 +39,7 @@ struct exynos_ppmu { struct regmap *regmap; struct exynos_ppmu_data ppmu; + enum exynos_ppmu_type ppmu_type; }; #define PPMU_EVENT(name) \ @@ -486,31 +493,23 @@ static const struct devfreq_event_ops exynos_ppmu_v2_ops = { static const struct of_device_id exynos_ppmu_id_match[] = { { .compatible = "samsung,exynos-ppmu", - .data = (void *)&exynos_ppmu_ops, + .data = (void *)EXYNOS_TYPE_PPMU, }, { .compatible = "samsung,exynos-ppmu-v2", - .data = (void *)&exynos_ppmu_v2_ops, + .data = (void *)EXYNOS_TYPE_PPMU_V2, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match); -static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np) -{ - const struct of_device_id *match; - - match = of_match_node(exynos_ppmu_id_match, np); - return (struct devfreq_event_ops *)match->data; -} - static int of_get_devfreq_events(struct device_node *np, struct exynos_ppmu *info) { struct devfreq_event_desc *desc; - struct devfreq_event_ops *event_ops; struct device *dev = info->dev; struct device_node *events_np, *node; int i, j, count; + const struct of_device_id *of_id; events_np = of_get_child_by_name(np, "events"); if (!events_np) { @@ -518,7 +517,6 @@ static int of_get_devfreq_events(struct device_node *np, "failed to get child node of devfreq-event devices\n"); return -EINVAL; } - event_ops = exynos_bus_get_ops(np); count = of_get_child_count(events_np); desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL); @@ -526,6 +524,12 @@ static int of_get_devfreq_events(struct device_node *np, return -ENOMEM; info->num_events = count; + of_id = of_match_device(exynos_ppmu_id_match, dev); + if (of_id) + info->ppmu_type = (enum exynos_ppmu_type)of_id->data; + else + return -EINVAL; + j = 0; for_each_child_of_node(events_np, node) { for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) { @@ -543,7 +547,15 @@ static int of_get_devfreq_events(struct device_node *np, continue; } - desc[j].ops = event_ops; + switch (info->ppmu_type) { + case EXYNOS_TYPE_PPMU: + desc[j].ops = &exynos_ppmu_ops; + break; + case EXYNOS_TYPE_PPMU_V2: + desc[j].ops = &exynos_ppmu_v2_ops; + break; + } + desc[j].driver_data = info; of_property_read_string(node, "event-name", &desc[j].name); -- GitLab From 1dd62c66d345a4e5dcfa5a4e81999600515b4309 Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Wed, 5 Jun 2019 11:12:34 +0200 Subject: [PATCH 4342/7155] PM / devfreq: events: extend events by type of counted data This patch adds posibility to choose what type of data should be counted by the PPMU counter. Now the type comes from DT where the event has been defined. When there is no 'event-data-type' the default value is used, which is 'read+write data in bytes'. It is needed when you want to know not only read+write data bytes but i.e. only write data in byte, or number of read requests, etc. Signed-off-by: Lukasz Luba Acked-by: Chanwoo Choi [Updated property by MyungJoo. data_type --> event_type] Signed-off-by: MyungJoo Ham --- drivers/devfreq/event/exynos-ppmu.c | 60 ++++++++++++++++++++--------- include/linux/devfreq-event.h | 6 +++ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index 1756c6b5cb09..87b42055e6bc 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c @@ -164,9 +164,9 @@ static int exynos_ppmu_set_event(struct devfreq_event_dev *edev) if (ret < 0) return ret; - /* Set the event of Read/Write data count */ + /* Set the event of proper data type monitoring */ ret = regmap_write(info->regmap, PPMU_BEVTxSEL(id), - PPMU_RO_DATA_CNT | PPMU_WO_DATA_CNT); + edev->desc->event_type); if (ret < 0) return ret; @@ -378,23 +378,11 @@ static int exynos_ppmu_v2_set_event(struct devfreq_event_dev *edev) if (ret < 0) return ret; - /* Set the event of Read/Write data count */ - switch (id) { - case PPMU_PMNCNT0: - case PPMU_PMNCNT1: - case PPMU_PMNCNT2: - ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), - PPMU_V2_RO_DATA_CNT | PPMU_V2_WO_DATA_CNT); - if (ret < 0) - return ret; - break; - case PPMU_PMNCNT3: - ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), - PPMU_V2_EVT3_RW_DATA_CNT); - if (ret < 0) - return ret; - break; - } + /* Set the event of proper data type monitoring */ + ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id), + edev->desc->event_type); + if (ret < 0) + return ret; /* Reset cycle counter/performance counter and enable PPMU */ ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc); @@ -510,6 +498,7 @@ static int of_get_devfreq_events(struct device_node *np, struct device_node *events_np, *node; int i, j, count; const struct of_device_id *of_id; + int ret; events_np = of_get_child_by_name(np, "events"); if (!events_np) { @@ -559,6 +548,39 @@ static int of_get_devfreq_events(struct device_node *np, desc[j].driver_data = info; of_property_read_string(node, "event-name", &desc[j].name); + ret = of_property_read_u32(node, "event-data-type", + &desc[j].event_type); + if (ret) { + /* Set the event of proper data type counting. + * Check if the data type has been defined in DT, + * use default if not. + */ + if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) { + struct devfreq_event_dev edev; + int id; + /* Not all registers take the same value for + * read+write data count. + */ + edev.desc = &desc[j]; + id = exynos_ppmu_find_ppmu_id(&edev); + + switch (id) { + case PPMU_PMNCNT0: + case PPMU_PMNCNT1: + case PPMU_PMNCNT2: + desc[j].event_type = PPMU_V2_RO_DATA_CNT + | PPMU_V2_WO_DATA_CNT; + break; + case PPMU_PMNCNT3: + desc[j].event_type = + PPMU_V2_EVT3_RW_DATA_CNT; + break; + } + } else { + desc[j].event_type = PPMU_RO_DATA_CNT | + PPMU_WO_DATA_CNT; + } + } j++; } diff --git a/include/linux/devfreq-event.h b/include/linux/devfreq-event.h index 29fc0dd735ae..f14f17f8cb7f 100644 --- a/include/linux/devfreq-event.h +++ b/include/linux/devfreq-event.h @@ -78,14 +78,20 @@ struct devfreq_event_ops { * struct devfreq_event_desc - the descriptor of devfreq-event device * * @name : the name of devfreq-event device. + * @event_type : the type of the event determined and used by driver * @driver_data : the private data for devfreq-event driver. * @ops : the operation to control devfreq-event device. * * Each devfreq-event device is described with a this structure. * This structure contains the various data for devfreq-event device. + * The event_type describes what is going to be counted in the register. + * It might choose to count e.g. read requests, write data in bytes, etc. + * The full supported list of types is present in specyfic header in: + * include/dt-bindings/pmu/. */ struct devfreq_event_desc { const char *name; + u32 event_type; void *driver_data; const struct devfreq_event_ops *ops; -- GitLab From e2fc1677eea749414a7db0058847509566bf64e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 24 Jul 2019 20:59:53 +0200 Subject: [PATCH 4343/7155] PM / devfreq: Correct devm_devfreq_remove_device() documentation Correct the documentation for devm_devfreq_remove_device() argument. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 784c08e4f931..446490c9d635 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -867,7 +867,7 @@ EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle); /** * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device() - * @dev: the device to add devfreq feature. + * @dev: the device from which to remove devfreq feature. * @devfreq: the devfreq instance to be removed */ void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq) -- GitLab From 2c2b20e0da89c76759ee28c6824413ab2fa3bfc6 Mon Sep 17 00:00:00 2001 From: Kamil Konieczny Date: Wed, 7 Aug 2019 15:38:35 +0200 Subject: [PATCH 4344/7155] PM / devfreq: exynos-bus: Correct clock enable sequence Regulators should be enabled before clocks to avoid h/w hang. This require change in exynos_bus_probe() to move exynos_bus_parse_of() after exynos_bus_parent_parse_of() and change in error handling. Similar change is needed in exynos_bus_exit() where clock should be disabled before regulators. Signed-off-by: Kamil Konieczny Acked-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/exynos-bus.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c index d9f377912c10..7c06df8bd74f 100644 --- a/drivers/devfreq/exynos-bus.c +++ b/drivers/devfreq/exynos-bus.c @@ -191,11 +191,10 @@ static void exynos_bus_exit(struct device *dev) if (ret < 0) dev_warn(dev, "failed to disable the devfreq-event devices\n"); - if (bus->regulator) - regulator_disable(bus->regulator); - dev_pm_opp_of_remove_table(dev); clk_disable_unprepare(bus->clk); + if (bus->regulator) + regulator_disable(bus->regulator); } /* @@ -383,6 +382,7 @@ static int exynos_bus_probe(struct platform_device *pdev) struct exynos_bus *bus; int ret, max_state; unsigned long min_freq, max_freq; + bool passive = false; if (!np) { dev_err(dev, "failed to find devicetree node\n"); @@ -396,27 +396,27 @@ static int exynos_bus_probe(struct platform_device *pdev) bus->dev = &pdev->dev; platform_set_drvdata(pdev, bus); - /* Parse the device-tree to get the resource information */ - ret = exynos_bus_parse_of(np, bus); - if (ret < 0) - return ret; - profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL); - if (!profile) { - ret = -ENOMEM; - goto err; - } + if (!profile) + return -ENOMEM; node = of_parse_phandle(dev->of_node, "devfreq", 0); if (node) { of_node_put(node); - goto passive; + passive = true; } else { ret = exynos_bus_parent_parse_of(np, bus); + if (ret < 0) + return ret; } + /* Parse the device-tree to get the resource information */ + ret = exynos_bus_parse_of(np, bus); if (ret < 0) - goto err; + goto err_reg; + + if (passive) + goto passive; /* Initialize the struct profile and governor data for parent device */ profile->polling_ms = 50; @@ -507,6 +507,9 @@ static int exynos_bus_probe(struct platform_device *pdev) err: dev_pm_opp_of_remove_table(dev); clk_disable_unprepare(bus->clk); +err_reg: + if (!passive) + regulator_disable(bus->regulator); return ret; } -- GitLab From 4294a779bd8dff6c65e7e85ffe7a1ea236e92a68 Mon Sep 17 00:00:00 2001 From: Kamil Konieczny Date: Wed, 7 Aug 2019 15:38:36 +0200 Subject: [PATCH 4345/7155] PM / devfreq: exynos-bus: Convert to use dev_pm_opp_set_rate() Reuse opp core code for setting bus clock and voltage. As a side effect this allow usage of coupled regulators feature (required for boards using Exynos5422/5800 SoCs) because dev_pm_opp_set_rate() uses regulator_set_voltage_triplet() for setting regulator voltage while the old code used regulator_set_voltage_tol() with fixed tolerance. This patch also removes no longer needed parsing of DT property "exynos,voltage-tolerance" (no Exynos devfreq DT node uses it). After applying changes both functions exynos_bus_passive_target() and exynos_bus_target() have the same code, so remove exynos_bus_passive_target(). In exynos_bus_probe() replace it with exynos_bus_target. Signed-off-by: Kamil Konieczny Acked-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/exynos-bus.c | 130 +++++++---------------------------- 1 file changed, 24 insertions(+), 106 deletions(-) diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c index 7c06df8bd74f..c832673273a2 100644 --- a/drivers/devfreq/exynos-bus.c +++ b/drivers/devfreq/exynos-bus.c @@ -22,7 +22,6 @@ #include #define DEFAULT_SATURATION_RATIO 40 -#define DEFAULT_VOLTAGE_TOLERANCE 2 struct exynos_bus { struct device *dev; @@ -34,9 +33,8 @@ struct exynos_bus { unsigned long curr_freq; - struct regulator *regulator; + struct opp_table *opp_table; struct clk *clk; - unsigned int voltage_tolerance; unsigned int ratio; }; @@ -90,62 +88,29 @@ static int exynos_bus_get_event(struct exynos_bus *bus, } /* - * Must necessary function for devfreq simple-ondemand governor + * devfreq function for both simple-ondemand and passive governor */ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) { struct exynos_bus *bus = dev_get_drvdata(dev); struct dev_pm_opp *new_opp; - unsigned long old_freq, new_freq, new_volt, tol; int ret = 0; - /* Get new opp-bus instance according to new bus clock */ + /* Get correct frequency for bus. */ new_opp = devfreq_recommended_opp(dev, freq, flags); if (IS_ERR(new_opp)) { dev_err(dev, "failed to get recommended opp instance\n"); return PTR_ERR(new_opp); } - new_freq = dev_pm_opp_get_freq(new_opp); - new_volt = dev_pm_opp_get_voltage(new_opp); dev_pm_opp_put(new_opp); - old_freq = bus->curr_freq; - - if (old_freq == new_freq) - return 0; - tol = new_volt * bus->voltage_tolerance / 100; - /* Change voltage and frequency according to new OPP level */ mutex_lock(&bus->lock); + ret = dev_pm_opp_set_rate(dev, *freq); + if (!ret) + bus->curr_freq = *freq; - if (old_freq < new_freq) { - ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol); - if (ret < 0) { - dev_err(bus->dev, "failed to set voltage\n"); - goto out; - } - } - - ret = clk_set_rate(bus->clk, new_freq); - if (ret < 0) { - dev_err(dev, "failed to change clock of bus\n"); - clk_set_rate(bus->clk, old_freq); - goto out; - } - - if (old_freq > new_freq) { - ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol); - if (ret < 0) { - dev_err(bus->dev, "failed to set voltage\n"); - goto out; - } - } - bus->curr_freq = new_freq; - - dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n", - old_freq, new_freq, clk_get_rate(bus->clk)); -out: mutex_unlock(&bus->lock); return ret; @@ -193,54 +158,10 @@ static void exynos_bus_exit(struct device *dev) dev_pm_opp_of_remove_table(dev); clk_disable_unprepare(bus->clk); - if (bus->regulator) - regulator_disable(bus->regulator); -} - -/* - * Must necessary function for devfreq passive governor - */ -static int exynos_bus_passive_target(struct device *dev, unsigned long *freq, - u32 flags) -{ - struct exynos_bus *bus = dev_get_drvdata(dev); - struct dev_pm_opp *new_opp; - unsigned long old_freq, new_freq; - int ret = 0; - - /* Get new opp-bus instance according to new bus clock */ - new_opp = devfreq_recommended_opp(dev, freq, flags); - if (IS_ERR(new_opp)) { - dev_err(dev, "failed to get recommended opp instance\n"); - return PTR_ERR(new_opp); - } - - new_freq = dev_pm_opp_get_freq(new_opp); - dev_pm_opp_put(new_opp); - - old_freq = bus->curr_freq; - - if (old_freq == new_freq) - return 0; - - /* Change the frequency according to new OPP level */ - mutex_lock(&bus->lock); - - ret = clk_set_rate(bus->clk, new_freq); - if (ret < 0) { - dev_err(dev, "failed to set the clock of bus\n"); - goto out; + if (bus->opp_table) { + dev_pm_opp_put_regulators(bus->opp_table); + bus->opp_table = NULL; } - - *freq = new_freq; - bus->curr_freq = new_freq; - - dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n", - old_freq, new_freq, clk_get_rate(bus->clk)); -out: - mutex_unlock(&bus->lock); - - return ret; } static void exynos_bus_passive_exit(struct device *dev) @@ -255,21 +176,19 @@ static int exynos_bus_parent_parse_of(struct device_node *np, struct exynos_bus *bus) { struct device *dev = bus->dev; + struct opp_table *opp_table; + const char *vdd = "vdd"; int i, ret, count, size; - /* Get the regulator to provide each bus with the power */ - bus->regulator = devm_regulator_get(dev, "vdd"); - if (IS_ERR(bus->regulator)) { - dev_err(dev, "failed to get VDD regulator\n"); - return PTR_ERR(bus->regulator); - } - - ret = regulator_enable(bus->regulator); - if (ret < 0) { - dev_err(dev, "failed to enable VDD regulator\n"); + opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + dev_err(dev, "failed to set regulators %d\n", ret); return ret; } + bus->opp_table = opp_table; + /* * Get the devfreq-event devices to get the current utilization of * buses. This raw data will be used in devfreq ondemand governor. @@ -310,14 +229,11 @@ static int exynos_bus_parent_parse_of(struct device_node *np, if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio)) bus->ratio = DEFAULT_SATURATION_RATIO; - if (of_property_read_u32(np, "exynos,voltage-tolerance", - &bus->voltage_tolerance)) - bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE; - return 0; err_regulator: - regulator_disable(bus->regulator); + dev_pm_opp_put_regulators(bus->opp_table); + bus->opp_table = NULL; return ret; } @@ -468,7 +384,7 @@ static int exynos_bus_probe(struct platform_device *pdev) goto out; passive: /* Initialize the struct profile and governor data for passive device */ - profile->target = exynos_bus_passive_target; + profile->target = exynos_bus_target; profile->exit = exynos_bus_passive_exit; /* Get the instance of parent devfreq device */ @@ -508,8 +424,10 @@ static int exynos_bus_probe(struct platform_device *pdev) dev_pm_opp_of_remove_table(dev); clk_disable_unprepare(bus->clk); err_reg: - if (!passive) - regulator_disable(bus->regulator); + if (!passive) { + dev_pm_opp_put_regulators(bus->opp_table); + bus->opp_table = NULL; + } return ret; } -- GitLab From 0ef7c7cce43f6ecc2b96d447e69b2900a9655f7c Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 8 Aug 2019 19:54:08 +0300 Subject: [PATCH 4346/7155] PM / devfreq: passive: Use non-devm notifiers The devfreq passive governor registers and unregisters devfreq transition notifiers on DEVFREQ_GOV_START/GOV_STOP using devm wrappers. If devfreq itself is registered with devm then a warning is triggered on rmmod from devm_devfreq_unregister_notifier. Call stack looks like this: devm_devfreq_unregister_notifier+0x30/0x40 devfreq_passive_event_handler+0x4c/0x88 devfreq_remove_device.part.8+0x6c/0x9c devm_devfreq_dev_release+0x18/0x20 release_nodes+0x1b0/0x220 devres_release_all+0x78/0x84 device_release_driver_internal+0x100/0x1c0 driver_detach+0x4c/0x90 bus_remove_driver+0x7c/0xd0 driver_unregister+0x2c/0x58 platform_driver_unregister+0x10/0x18 imx_devfreq_platdrv_exit+0x14/0xd40 [imx_devfreq] This happens because devres_release_all will first remove all the nodes into a separate todo list so the nested devres_release from devm_devfreq_unregister_notifier won't find anything. Fix the warning by calling the non-devm APIS for frequency notification. Using devm wrappers is not actually useful for a governor anyway: it relies on the devfreq core to correctly match the GOV_START/GOV_STOP notifications. Fixes: 996133119f57 ("PM / devfreq: Add new passive governor") Signed-off-by: Leonard Crestez Acked-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/governor_passive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c index 58308948b863..da485477065c 100644 --- a/drivers/devfreq/governor_passive.c +++ b/drivers/devfreq/governor_passive.c @@ -165,12 +165,12 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq, p_data->this = devfreq; nb->notifier_call = devfreq_passive_notifier_call; - ret = devm_devfreq_register_notifier(dev, parent, nb, + ret = devfreq_register_notifier(parent, nb, DEVFREQ_TRANSITION_NOTIFIER); break; case DEVFREQ_GOV_STOP: - devm_devfreq_unregister_notifier(dev, parent, nb, - DEVFREQ_TRANSITION_NOTIFIER); + WARN_ON(devfreq_unregister_notifier(parent, nb, + DEVFREQ_TRANSITION_NOTIFIER)); break; default: break; -- GitLab From b04f537caab4deae1b839438e8fd5ed4bc598b43 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 23 Aug 2019 17:27:03 -0700 Subject: [PATCH 4347/7155] ARM: dts: vf610-zii-scu4-aib: Configure IRQ line for GPIO expander Configure IRQ line for SX1503 GPIO expander. We already have appropriate pinmux entry and all that is missing is "interrupt-parent" and "interrupts" properties. Add them. Signed-off-by: Andrey Smirnov Cc: Shawn Guo Cc: Chris Healy Cc: Cory Tusar Cc: Fabio Estevam Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Tested-by: Chris Healy Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-scu4-aib.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts index 666ec27a73e3..dc8a5f37a1ef 100644 --- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts +++ b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts @@ -565,6 +565,8 @@ #gpio-cells = <2>; reg = <0x20>; gpio-controller; + interrupt-parent = <&gpio1>; + interrupts = <31 IRQ_TYPE_EDGE_FALLING>; }; lm75@4e { -- GitLab From e0ccdef92653f8867e2d1667facfd3c23699f540 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Aug 2019 12:38:07 +0200 Subject: [PATCH 4348/7155] ALSA: usb-audio: Clean up check_input_term() The primary changes in this patch are cleanups of __check_input_term() and move to a non-nested switch-case block by evaluating the pair of UAC version and the unit type, as we've done for parse_audio_unit(). Also each parser is split into the function for readability. Now, a slight behavior change by this cleanup is the handling of processing and extension units. Formerly we've dealt with them differently between UAC1/2 and UAC3; the latter returns an error if no input sources are available, while the former continues to parse. In this patch, unify the behavior in all cases: when input sources are available, it parses recursively, then override the type and the id, as well as channel information if not provided yet. Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 401 ++++++++++++++++++++++++---------------------- 1 file changed, 209 insertions(+), 192 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index a0468c4a6326..83d22f241bdd 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -758,224 +758,242 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, } /* - * parse the source unit recursively until it reaches to a terminal - * or a branched unit. + * Parse Input Terminal Unit */ static int __check_input_term(struct mixer_build *state, int id, - struct usb_audio_term *term) + struct usb_audio_term *term); + +static int parse_term_uac1_iterm_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) { - int protocol = state->mixer->protocol; + struct uac_input_terminal_descriptor *d = p1; + + term->type = le16_to_cpu(d->wTerminalType); + term->channels = d->bNrChannels; + term->chconfig = le16_to_cpu(d->wChannelConfig); + term->name = d->iTerminal; + return 0; +} + +static int parse_term_uac2_iterm_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac2_input_terminal_descriptor *d = p1; int err; - void *p1; - unsigned char *hdr; - memset(term, 0, sizeof(*term)); - for (;;) { - /* a loop in the terminal chain? */ - if (test_and_set_bit(id, state->termbitmap)) - return -EINVAL; + /* call recursively to verify the referenced clock entity */ + err = __check_input_term(state, d->bCSourceID, term); + if (err < 0) + return err; - p1 = find_audio_control_unit(state, id); - if (!p1) - break; - if (!snd_usb_validate_audio_desc(p1, protocol)) - break; /* bad descriptor */ + /* save input term properties after recursion, + * to ensure they are not overriden by the recursion calls + */ + term->id = id; + term->type = le16_to_cpu(d->wTerminalType); + term->channels = d->bNrChannels; + term->chconfig = le32_to_cpu(d->bmChannelConfig); + term->name = d->iTerminal; + return 0; +} - hdr = p1; - term->id = id; +static int parse_term_uac3_iterm_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac3_input_terminal_descriptor *d = p1; + int err; - if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) { - switch (hdr[2]) { - case UAC_INPUT_TERMINAL: - if (protocol == UAC_VERSION_1) { - struct uac_input_terminal_descriptor *d = p1; - - term->type = le16_to_cpu(d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig = le16_to_cpu(d->wChannelConfig); - term->name = d->iTerminal; - } else { /* UAC_VERSION_2 */ - struct uac2_input_terminal_descriptor *d = p1; - - /* call recursively to verify that the - * referenced clock entity is valid */ - err = __check_input_term(state, d->bCSourceID, term); - if (err < 0) - return err; + /* call recursively to verify the referenced clock entity */ + err = __check_input_term(state, d->bCSourceID, term); + if (err < 0) + return err; - /* save input term properties after recursion, - * to ensure they are not overriden by the - * recursion calls */ - term->id = id; - term->type = le16_to_cpu(d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig = le32_to_cpu(d->bmChannelConfig); - term->name = d->iTerminal; - } - return 0; - case UAC_FEATURE_UNIT: { - /* the header is the same for v1 and v2 */ - struct uac_feature_unit_descriptor *d = p1; + /* save input term properties after recursion, + * to ensure they are not overriden by the recursion calls + */ + term->id = id; + term->type = le16_to_cpu(d->wTerminalType); - id = d->bSourceID; - break; /* continue to parse */ - } - case UAC_MIXER_UNIT: { - struct uac_mixer_unit_descriptor *d = p1; - - term->type = UAC3_MIXER_UNIT << 16; /* virtual type */ - term->channels = uac_mixer_unit_bNrChannels(d); - term->chconfig = uac_mixer_unit_wChannelConfig(d, protocol); - term->name = uac_mixer_unit_iMixer(d); - return 0; - } - case UAC_SELECTOR_UNIT: - case UAC2_CLOCK_SELECTOR: { - struct uac_selector_unit_descriptor *d = p1; - /* call recursively to retrieve the channel info */ - err = __check_input_term(state, d->baSourceID[0], term); - if (err < 0) - return err; - term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */ - term->id = id; - term->name = uac_selector_unit_iSelector(d); - return 0; - } - case UAC1_PROCESSING_UNIT: - /* UAC2_EFFECT_UNIT */ - if (protocol == UAC_VERSION_1) - term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ - else /* UAC_VERSION_2 */ - term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ - /* fall through */ - case UAC1_EXTENSION_UNIT: - /* UAC2_PROCESSING_UNIT_V2 */ - if (protocol == UAC_VERSION_1 && !term->type) - term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */ - else if (protocol == UAC_VERSION_2 && !term->type) - term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ - /* fall through */ - case UAC2_EXTENSION_UNIT_V2: { - struct uac_processing_unit_descriptor *d = p1; - - if (protocol == UAC_VERSION_2 && - hdr[2] == UAC2_EFFECT_UNIT) { - /* UAC2/UAC1 unit IDs overlap here in an - * uncompatible way. Ignore this unit for now. - */ - return 0; - } + err = get_cluster_channels_v3(state, le16_to_cpu(d->wClusterDescrID)); + if (err < 0) + return err; + term->channels = err; - if (d->bNrInPins) { - id = d->baSourceID[0]; - break; /* continue to parse */ - } - if (!term->type) - term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */ + /* REVISIT: UAC3 IT doesn't have channels cfg */ + term->chconfig = 0; - term->channels = uac_processing_unit_bNrChannels(d); - term->chconfig = uac_processing_unit_wChannelConfig(d, protocol); - term->name = uac_processing_unit_iProcessing(d, protocol); - return 0; - } - case UAC2_CLOCK_SOURCE: { - struct uac_clock_source_descriptor *d = p1; + term->name = le16_to_cpu(d->wTerminalDescrStr); + return 0; +} - term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ - term->id = id; - term->name = d->iClockSource; - return 0; - } - default: - return -ENODEV; - } - } else { /* UAC_VERSION_3 */ - switch (hdr[2]) { - case UAC_INPUT_TERMINAL: { - struct uac3_input_terminal_descriptor *d = p1; - - /* call recursively to verify that the - * referenced clock entity is valid */ - err = __check_input_term(state, d->bCSourceID, term); - if (err < 0) - return err; +static int parse_term_mixer_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac_mixer_unit_descriptor *d = p1; + int protocol = state->mixer->protocol; + int err; - /* save input term properties after recursion, - * to ensure they are not overriden by the - * recursion calls */ - term->id = id; - term->type = le16_to_cpu(d->wTerminalType); + err = uac_mixer_unit_get_channels(state, d); + if (err <= 0) + return err; - err = get_cluster_channels_v3(state, le16_to_cpu(d->wClusterDescrID)); - if (err < 0) - return err; - term->channels = err; + term->type = UAC3_MIXER_UNIT << 16; /* virtual type */ + term->channels = err; + if (protocol != UAC_VERSION_3) { + term->chconfig = uac_mixer_unit_wChannelConfig(d, protocol); + term->name = uac_mixer_unit_iMixer(d); + } + return 0; +} + +static int parse_term_selector_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac_selector_unit_descriptor *d = p1; + int err; - /* REVISIT: UAC3 IT doesn't have channels cfg */ - term->chconfig = 0; + /* call recursively to retrieve the channel info */ + err = __check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */ + term->id = id; + if (state->mixer->protocol != UAC_VERSION_3) + term->name = uac_selector_unit_iSelector(d); + return 0; +} - term->name = le16_to_cpu(d->wTerminalDescrStr); - return 0; - } - case UAC3_FEATURE_UNIT: { - struct uac3_feature_unit_descriptor *d = p1; +static int parse_term_proc_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id, int vtype) +{ + struct uac_processing_unit_descriptor *d = p1; + int protocol = state->mixer->protocol; + int err; - id = d->bSourceID; - break; /* continue to parse */ - } - case UAC3_CLOCK_SOURCE: { - struct uac3_clock_source_descriptor *d = p1; + if (d->bNrInPins) { + /* call recursively to retrieve the channel info */ + err = __check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + } - term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ - term->id = id; - term->name = le16_to_cpu(d->wClockSourceStr); - return 0; - } - case UAC3_MIXER_UNIT: { - struct uac_mixer_unit_descriptor *d = p1; + term->type = vtype << 16; /* virtual type */ + term->id = id; - err = uac_mixer_unit_get_channels(state, d); - if (err <= 0) - return err; + if (protocol == UAC_VERSION_3) + return 0; - term->channels = err; - term->type = UAC3_MIXER_UNIT << 16; /* virtual type */ + if (!term->channels) { + term->channels = uac_processing_unit_bNrChannels(d); + term->chconfig = uac_processing_unit_wChannelConfig(d, protocol); + } + term->name = uac_processing_unit_iProcessing(d, protocol); + return 0; +} - return 0; - } - case UAC3_SELECTOR_UNIT: - case UAC3_CLOCK_SELECTOR: { - struct uac_selector_unit_descriptor *d = p1; - /* call recursively to retrieve the channel info */ - err = __check_input_term(state, d->baSourceID[0], term); - if (err < 0) - return err; - term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */ - term->id = id; - term->name = 0; /* TODO: UAC3 Class-specific strings */ +static int parse_term_uac2_clock_source(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac_clock_source_descriptor *d = p1; - return 0; - } - case UAC3_PROCESSING_UNIT: { - struct uac_processing_unit_descriptor *d = p1; + term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ + term->id = id; + term->name = d->iClockSource; + return 0; +} - if (!d->bNrInPins) - return -EINVAL; +static int parse_term_uac3_clock_source(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +{ + struct uac3_clock_source_descriptor *d = p1; - /* call recursively to retrieve the channel info */ - err = __check_input_term(state, d->baSourceID[0], term); - if (err < 0) - return err; + term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */ + term->id = id; + term->name = le16_to_cpu(d->wClockSourceStr); + return 0; +} - term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */ - term->id = id; - term->name = 0; /* TODO: UAC3 Class-specific strings */ +#define PTYPE(a, b) ((a) << 8 | (b)) - return 0; - } - default: - return -ENODEV; - } +/* + * parse the source unit recursively until it reaches to a terminal + * or a branched unit. + */ +static int __check_input_term(struct mixer_build *state, int id, + struct usb_audio_term *term) +{ + int protocol = state->mixer->protocol; + void *p1; + unsigned char *hdr; + + for (;;) { + /* a loop in the terminal chain? */ + if (test_and_set_bit(id, state->termbitmap)) + return -EINVAL; + + p1 = find_audio_control_unit(state, id); + if (!p1) + break; + if (!snd_usb_validate_audio_desc(p1, protocol)) + break; /* bad descriptor */ + + hdr = p1; + term->id = id; + + switch (PTYPE(protocol, hdr[2])) { + case PTYPE(UAC_VERSION_1, UAC_FEATURE_UNIT): + case PTYPE(UAC_VERSION_2, UAC_FEATURE_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_FEATURE_UNIT): { + /* the header is the same for all versions */ + struct uac_feature_unit_descriptor *d = p1; + + id = d->bSourceID; + break; /* continue to parse */ + } + case PTYPE(UAC_VERSION_1, UAC_INPUT_TERMINAL): + return parse_term_uac1_iterm_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_2, UAC_INPUT_TERMINAL): + return parse_term_uac2_iterm_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_3, UAC_INPUT_TERMINAL): + return parse_term_uac3_iterm_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_1, UAC_MIXER_UNIT): + case PTYPE(UAC_VERSION_2, UAC_MIXER_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_MIXER_UNIT): + return parse_term_mixer_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_1, UAC_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_2, UAC_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_CLOCK_SELECTOR): + case PTYPE(UAC_VERSION_3, UAC3_SELECTOR_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_CLOCK_SELECTOR): + return parse_term_selector_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_1, UAC1_PROCESSING_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_PROCESSING_UNIT_V2): + case PTYPE(UAC_VERSION_3, UAC3_PROCESSING_UNIT): + return parse_term_proc_unit(state, term, p1, id, + UAC3_PROCESSING_UNIT); + case PTYPE(UAC_VERSION_2, UAC2_EFFECT_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_EFFECT_UNIT): + return parse_term_proc_unit(state, term, p1, id, + UAC3_EFFECT_UNIT); + case PTYPE(UAC_VERSION_1, UAC1_EXTENSION_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2): + case PTYPE(UAC_VERSION_3, UAC3_EXTENSION_UNIT): + return parse_term_proc_unit(state, term, p1, id, + UAC3_EXTENSION_UNIT); + case PTYPE(UAC_VERSION_2, UAC2_CLOCK_SOURCE): + return parse_term_uac2_clock_source(state, term, p1, id); + case PTYPE(UAC_VERSION_3, UAC3_CLOCK_SOURCE): + return parse_term_uac3_clock_source(state, term, p1, id); + default: + return -ENODEV; } } return -ENODEV; @@ -2712,7 +2730,6 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) return 0; /* skip invalid unit */ } -#define PTYPE(a, b) ((a) << 8 | (b)) switch (PTYPE(protocol, p1[2])) { case PTYPE(UAC_VERSION_1, UAC_INPUT_TERMINAL): case PTYPE(UAC_VERSION_2, UAC_INPUT_TERMINAL): -- GitLab From de9defd21539d37816dc869b098ae8eed12857ad Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 21 Aug 2019 22:31:10 +0530 Subject: [PATCH 4349/7155] staging: rtl8723bs: os_dep: Remove unused declarations Remove unused Macro declarations Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/1566406901-6700-1-git-send-email-hariprasad.kelam@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 2 -- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 3 --- drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 5 ----- 3 files changed, 10 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 57876463b9b2..f819abb756dc 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -19,8 +19,6 @@ #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */ #define RTW_MAX_NUM_PMKIDS 4 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - static const u32 rtw_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 90c2997256b7..0e565c0ed6bc 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -21,13 +21,10 @@ #define RATE_COUNT 4 /* combo scan */ -#define WEXT_CSCAN_AMOUNT 9 -#define WEXT_CSCAN_BUF_LEN 360 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" #define WEXT_CSCAN_HEADER_SIZE 12 #define WEXT_CSCAN_SSID_SECTION 'S' #define WEXT_CSCAN_CHANNEL_SECTION 'C' -#define WEXT_CSCAN_NPROBE_SECTION 'N' #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' #define WEXT_CSCAN_PASV_DWELL_SECTION 'P' #define WEXT_CSCAN_HOME_DWELL_SECTION 'H' diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index aa2f62acc994..578b9f734231 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -33,11 +33,6 @@ REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, \ NL80211_RRF_PASSIVE_SCAN) -/* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */ -#define RTW_2GHZ_CH14 \ - REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) - static const struct ieee80211_regdomain rtw_regdom_rd = { .n_reg_rules = 3, .alpha2 = "99", -- GitLab From eac53016919f2d2a8df607c69dc2b1d47273a61e Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Wed, 21 Aug 2019 23:32:01 +0530 Subject: [PATCH 4350/7155] staging: rtl8723bs: hal: Drop condition with no effect As the "else if" and "else" branch body are identical the condition has no effect. So drop the else if condition. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190821180153.GA10678@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 19486f0e0ead..6e4a1fcb8790 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -482,10 +482,8 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) *pU4Tmp = BTC_WIFI_BW_LEGACY; else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20) *pU4Tmp = BTC_WIFI_BW_HT20; - else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) - *pU4Tmp = BTC_WIFI_BW_HT40; else - *pU4Tmp = BTC_WIFI_BW_HT40; /* todo */ + *pU4Tmp = BTC_WIFI_BW_HT40; break; case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: -- GitLab From 5ab706bd0bcaea0296426ecca333f69bad60d24e Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Wed, 21 Aug 2019 23:46:34 +0530 Subject: [PATCH 4351/7155] staging: rtl8723bs: os_dep: Drop condition with no effect As the "else if" and "else" branch body are identical the condition has no effect. So drop the "else if" condition. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190821181631.GA11082@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 0e565c0ed6bc..d1b199e3e5bd 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -212,8 +212,6 @@ static char *translate_scan(struct adapter *padapter, } else if (ht_cap) { if (mcs_rate&0x8000) { /* MCS15 */ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); - } else if (mcs_rate&0x0080) { /* MCS7 */ - max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); } else { /* default MCS7 */ /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); -- GitLab From 5e718a12e1a125045b451678faf6ceffc7591e3b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Aug 2019 09:46:09 +0100 Subject: [PATCH 4352/7155] staging: rtl8192u: remove redundant assignment to pointer crypt The pointer crypt is being set with a value that is never read, the assignment is redundant and hence can be removed. Thanks to Dan Carpenter for sanity checking that this was indeed redundant. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190822084609.8971-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index e0da0900a4f7..33a6af7aad22 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -743,7 +743,6 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - crypt = ieee->crypt[ieee->tx_keyidx]; if (encrypt) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); -- GitLab From 76fe9cfb09e7bf261b814a155f5953fa4d2df89a Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Thu, 22 Aug 2019 20:25:45 +0530 Subject: [PATCH 4353/7155] staging: rtl8192u: Remove unnecessary blank lines This patch fixes the file r8180_93cx6.c to avoid the checkpatch.pl warning: CHECK: Please don't use multiple blank lines Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190822145545.19894-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8180_93cx6.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c index de83daa0c9ed..6ebf121eac0c 100644 --- a/drivers/staging/rtl8192u/r8180_93cx6.c +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -39,7 +39,6 @@ static void eprom_cs(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static void eprom_ck_cycle(struct net_device *dev) { u8 cmdreg; @@ -58,7 +57,6 @@ static void eprom_ck_cycle(struct net_device *dev) udelay(EPROM_DELAY); } - static void eprom_w(struct net_device *dev, short bit) { u8 cmdreg; @@ -76,7 +74,6 @@ static void eprom_w(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static short eprom_r(struct net_device *dev) { u8 bit; @@ -94,7 +91,6 @@ static short eprom_r(struct net_device *dev) return 0; } - static void eprom_send_bits_string(struct net_device *dev, short b[], int len) { int i; @@ -105,7 +101,6 @@ static void eprom_send_bits_string(struct net_device *dev, short b[], int len) } } - int eprom_read(struct net_device *dev, u32 addr) { struct r8192_priv *priv = ieee80211_priv(dev); -- GitLab From 684c215dd06eccc515dfd786347ac556c00f895a Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Fri, 23 Aug 2019 09:24:10 -0700 Subject: [PATCH 4354/7155] staging: rtl8192u: remove code under TO_DO_LIST Several blocks of code are guarded by #ifdef TO_DO_LIST. If this is defined, compilation fails. No machinery exists to define this, and no documenation on the in-progress feature exists. Since this code is dead, let's delete it. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190823162410.10038-1-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211.h | 2 - .../staging/rtl8192u/ieee80211/ieee80211_tx.c | 21 ---- .../rtl8192u/ieee80211/rtl819x_HTProc.c | 4 - .../rtl8192u/ieee80211/rtl819x_TSProc.c | 4 - drivers/staging/rtl8192u/r8192U_core.c | 101 +----------------- drivers/staging/rtl8192u/r819xU_phy.c | 59 ---------- 6 files changed, 4 insertions(+), 187 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index daebbbd8f4dd..9576b647f6b1 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -1649,10 +1649,8 @@ struct ieee80211_device { struct list_head Rx_TS_Pending_List; struct list_head Rx_TS_Unused_List; struct rx_ts_record RxTsRecord[TOTAL_TS_NUM]; -//#ifdef TO_DO_LIST struct rx_reorder_entry RxReorderEntry[128]; struct list_head RxReorder_Unused_List; -//#endif // Qos related. Added by Annie, 2005-11-01. // PSTA_QOS pStaQos; u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index e76bdedc8409..140e3cb66a2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -302,13 +302,6 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, if (is_multicast_ether_addr(hdr->addr1)) return; //check packet and mode later -#ifdef TO_DO_LIST - if (pTcb->PacketLength >= 4096) - return; - // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. - if (!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) - return; -#endif if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { return; } @@ -509,20 +502,6 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, struct cb_desc *tcb_desc) { -#ifdef TO_DO_LIST - if (!IsDataFrame(pFrame)) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - pTcb->RATRIndex = 7; - return; - } - - if (pMgntInfo->ForcedDataRate != 0) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - return; - } -#endif if (ieee->bTxDisableRateFallBack) tcb_desc->bTxDisableRateFallBack = true; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index c73a8058cf87..dba3f2db9f48 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -93,10 +93,6 @@ void HTUpdateDefaultSetting(struct ieee80211_device *ieee) ieee->bTxDisableRateFallBack = 0; ieee->bTxUseDriverAssingedRate = 0; -#ifdef TO_DO_LIST - // 8190 only. Assign duration operation mode to firmware - pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur; -#endif /* * 8190 only, Realtek proprietary aggregation mode * Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index f4e5aa07421f..5cee1031a27c 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -180,14 +180,12 @@ void TSInitialize(struct ieee80211_device *ieee) } // Initialize unused Rx Reorder List. INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); -//#ifdef TO_DO_LIST for (count = 0; count < REORDER_ENTRY_NUM; count++) { list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); if (count == (REORDER_ENTRY_NUM - 1)) break; pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; } -//#endif } static void AdmitTS(struct ieee80211_device *ieee, @@ -417,7 +415,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * TsInitDelBA(ieee, pTs, TxRxSelect); if (TxRxSelect == RX_DIR) { -//#ifdef TO_DO_LIST struct rx_reorder_entry *pRxReorderEntry; struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs; if (timer_pending(&pRxTS->rx_pkt_pending_timer)) @@ -445,7 +442,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); } -//#endif } else { struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs; del_timer_sync(&pTxTS->ts_add_ba_timer); diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 569d02240bf5..2821411878ce 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2076,14 +2076,6 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) wireless_mode = WIRELESS_MODE_B; } } -#ifdef TO_DO_LIST - /* TODO: this function doesn't work well at this time, - * we should wait for FPGA - */ - ActUpdateChannelAccessSetting( - pAdapter, pHalData->CurrentWirelessMode, - &pAdapter->MgntInfo.Info8185.ChannelAccessSetting); -#endif priv->ieee80211->mode = wireless_mode; if (wireless_mode == WIRELESS_MODE_N_24G || @@ -2159,12 +2151,6 @@ static int rtl8192_init_priv_variable(struct net_device *dev) priv->ieee80211->InitialGainHandler = InitialGain819xUsb; priv->card_type = USB; -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - pHalData->ShortRetryLimit = 7; - pHalData->LongRetryLimit = 7; - } -#endif priv->ShortRetryLimit = 0x30; priv->LongRetryLimit = 0x30; priv->EarlyRxThreshold = 7; @@ -2180,34 +2166,6 @@ static int rtl8192_init_priv_variable(struct net_device *dev) * TRUE: SW provides them */ (false ? TCR_SAT : 0); -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) - pHalData->ReceiveConfig = - pHalData->CSMethod | - /* accept management/data */ - RCR_AMF | RCR_ADF | - /* accept control frame for SW - * AP needs PS-poll - */ - RCR_ACF | - /* accept BC/MC/UC */ - RCR_AB | RCR_AM | RCR_APM | - /* accept ICV/CRC error - * packet - */ - RCR_AICV | RCR_ACRC32 | - /* Max DMA Burst Size per Tx - * DMA Burst, 7: unlimited. - */ - ((u32)7 << RCR_MXDMA_OFFSET) | - /* Rx FIFO Threshold, - * 7: No Rx threshold. - */ - (pHalData->EarlyRxThreshold << RCR_FIFO_OFFSET) | - (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0); - else - -#endif priv->ReceiveConfig = /* accept management/data */ RCR_AMF | RCR_ADF | @@ -2665,19 +2623,10 @@ static void rtl8192_hwconfig(struct net_device *dev) regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_AUTO: -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } else -#endif - { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_N_24G: /* It support CCK rate by default. CCK rate will be filtered @@ -2848,48 +2797,6 @@ static bool rtl8192_adapter_start(struct net_device *dev) } RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__); -#ifdef TO_DO_LIST - if (Adapter->ResetProgress == RESET_TYPE_NORESET) { - if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n")); - MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { - /* H/W or S/W RF OFF before sleep. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", - pMgntInfo->RfOffReason)); - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - } else { - pHalData->eRFPowerState = eRfOn; - pMgntInfo->RfOffReason = 0; - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): RF is on ----------\n")); - } - } else { - if (pHalData->eRFPowerState == eRfOff) { - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } - } -#endif /* config RF. */ if (priv->ResetProgress == RESET_TYPE_NORESET) { rtl8192_phy_RFConfig(dev); diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index 5f04afe53d69..c04d8eca0cfb 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -516,16 +516,6 @@ static void rtl8192_phyConfigBB(struct net_device *dev, { u32 i; -#ifdef TO_DO_LIST - u32 *rtl8192PhyRegArrayTable = NULL, *rtl8192AgcTabArrayTable = NULL; - - if (Adapter->bInHctTest) { - PHY_REGArrayLen = PHY_REGArrayLengthDTM; - AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM; - Rtl8190PHY_REGArray_Table = Rtl819XPHY_REGArrayDTM; - Rtl8190AGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM; - } -#endif if (ConfigType == BASEBAND_CONFIG_PHY_REG) { for (i = 0; i < PHY_REG_1T2RArrayLength; i += 2) { rtl8192_setBBreg(dev, Rtl8192UsbPHY_REG_1T2RArray[i], @@ -1059,10 +1049,6 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel) switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225CckTxPower(Adapter, powerlevel); - PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G); -#endif break; case RF_8256: @@ -1160,48 +1146,6 @@ bool rtl8192_SetRFPowerState(struct net_device *dev, RT_TRACE(COMP_ERR, "Not support rf_chip(%x)\n", priv->rf_chip); break; } -#ifdef TO_DO_LIST - if (bResult) { - /* Update current RF state variable. */ - pHalData->eRFPowerState = eRFPowerState; - switch (pHalData->RFChipID) { - case RF_8256: - switch (pHalData->eRFPowerState) { - case eRfOff: - /* If Rf off reason is from IPS, - * LED should blink with no link - */ - if (pMgntInfo->RfOffReason == RF_CHANGE_BY_IPS) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF); - break; - - case eRfOn: - /* Turn on RF we are still linked, which might - * happen when we quickly turn off and on HW RF. - */ - if (pMgntInfo->bMediaConnect) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - break; - - default: - break; - } - break; - - default: - RT_TRACE(COMP_RF, DBG_LOUD, "%s(): Unknown RF type\n", - __func__); - break; - } - - } -#endif priv->SetRFPowerStateInProgress = false; return bResult; @@ -1628,9 +1572,6 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev) /* <3> Set RF related register */ switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225Bandwidth(Adapter, pHalData->CurrentChannelBW); -#endif break; case RF_8256: -- GitLab From cadcc6b20d971510f00ea19f3da6d3b992658f0b Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Fri, 23 Aug 2019 01:05:35 +0530 Subject: [PATCH 4355/7155] staging: rtl8192u: Add space around binary operators This patch fixes the file r8180_93cx6.c to avoid the checkpatch.pl warnings: CHECK: spaces preferred around that '<<' (ctx:VxV) CHECK: spaces preferred around that '-' (ctx:VxV) Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190822193535.14357-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8180_93cx6.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c index 6ebf121eac0c..2527cea60e3e 100644 --- a/drivers/staging/rtl8192u/r8180_93cx6.c +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -114,7 +114,7 @@ int eprom_read(struct net_device *dev, u32 addr) ret = 0; /* enable EPROM programming */ write_nic_byte_E(dev, EPROM_CMD, - (EPROM_CMD_PROGRAM< Date: Sun, 25 Aug 2019 10:44:17 +0100 Subject: [PATCH 4356/7155] KVM: arm/arm64: vgic: Remove spurious semicolons Detected by Coccinelle (and Will Deacon) using scripts/coccinelle/misc/semicolon.cocci. Reported-by: Will Deacon Signed-off-by: Marc Zyngier --- virt/kvm/arm/vgic/vgic-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 80127ca9269f..9175bfd83263 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c @@ -510,7 +510,7 @@ int kvm_vgic_hyp_init(void) break; default: ret = -ENODEV; - }; + } if (ret) return ret; -- GitLab From 3109741a8d773b91eec4a1f7764c97a1176ec32d Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 23 Aug 2019 19:33:30 +0200 Subject: [PATCH 4357/7155] KVM: arm/arm64: vgic: Use a single IO device per redistributor At the moment we use 2 IO devices per GICv3 redistributor: one one for the RD_base frame and one for the SGI_base frame. Instead we can use a single IO device per redistributor (the 2 frames are contiguous). This saves slots on the KVM_MMIO_BUS which is currently limited to NR_IOBUS_DEVS (1000). This change allows to instantiate up to 512 redistributors and may speed the guest boot with a large number of VCPUs. Signed-off-by: Eric Auger Signed-off-by: Marc Zyngier --- include/kvm/arm_vgic.h | 1 - virt/kvm/arm/vgic/vgic-init.c | 1 - virt/kvm/arm/vgic/vgic-mmio-v3.c | 81 ++++++++++---------------------- 3 files changed, 24 insertions(+), 59 deletions(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index ded50a30e2d5..af4f09c02bf1 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -314,7 +314,6 @@ struct vgic_cpu { * parts of the redistributor. */ struct vgic_io_device rd_iodev; - struct vgic_io_device sgi_iodev; struct vgic_redist_region *rdreg; /* Contains the attributes and gpa of the LPI pending tables. */ diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 9175bfd83263..958e2f0d2207 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c @@ -193,7 +193,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) int i; vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; - vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF; INIT_LIST_HEAD(&vgic_cpu->ap_list_head); raw_spin_lock_init(&vgic_cpu->ap_list_lock); diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index fdcfb7ae4491..7dfd15dbb308 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -517,7 +517,8 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = { VGIC_ACCESS_32bit), }; -static const struct vgic_register_region vgic_v3_rdbase_registers[] = { +static const struct vgic_register_region vgic_v3_rd_registers[] = { + /* RD_base registers */ REGISTER_DESC_WITH_LENGTH(GICR_CTLR, vgic_mmio_read_v3r_ctlr, vgic_mmio_write_v3r_ctlr, 4, VGIC_ACCESS_32bit), @@ -542,44 +543,42 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = { REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48, VGIC_ACCESS_32bit), -}; - -static const struct vgic_register_region vgic_v3_sgibase_registers[] = { - REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, + /* SGI_base registers */ + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGROUPR0, vgic_mmio_read_group, vgic_mmio_write_group, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ISENABLER0, vgic_mmio_read_enable, vgic_mmio_write_senable, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICENABLER0, vgic_mmio_read_enable, vgic_mmio_write_cenable, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISPENDR0, + REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0, vgic_mmio_read_pending, vgic_mmio_write_spending, vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICPENDR0, + REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICPENDR0, vgic_mmio_read_pending, vgic_mmio_write_cpending, vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISACTIVER0, + REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISACTIVER0, vgic_mmio_read_active, vgic_mmio_write_sactive, NULL, vgic_mmio_uaccess_write_sactive, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICACTIVER0, + REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICACTIVER0, vgic_mmio_read_active, vgic_mmio_write_cactive, NULL, vgic_mmio_uaccess_write_cactive, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IPRIORITYR0, vgic_mmio_read_priority, vgic_mmio_write_priority, 32, VGIC_ACCESS_32bit | VGIC_ACCESS_8bit), - REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICFGR0, vgic_mmio_read_config, vgic_mmio_write_config, 8, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGRPMODR0, vgic_mmio_read_raz, vgic_mmio_write_wi, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_NSACR, + REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_NSACR, vgic_mmio_read_raz, vgic_mmio_write_wi, 4, VGIC_ACCESS_32bit), }; @@ -609,9 +608,8 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) struct vgic_dist *vgic = &kvm->arch.vgic; struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; - struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev; struct vgic_redist_region *rdreg; - gpa_t rd_base, sgi_base; + gpa_t rd_base; int ret; if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr)) @@ -633,52 +631,31 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) vgic_cpu->rdreg = rdreg; rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE; - sgi_base = rd_base + SZ_64K; kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops); rd_dev->base_addr = rd_base; rd_dev->iodev_type = IODEV_REDIST; - rd_dev->regions = vgic_v3_rdbase_registers; - rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); + rd_dev->regions = vgic_v3_rd_registers; + rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rd_registers); rd_dev->redist_vcpu = vcpu; mutex_lock(&kvm->slots_lock); ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base, - SZ_64K, &rd_dev->dev); + 2 * SZ_64K, &rd_dev->dev); mutex_unlock(&kvm->slots_lock); if (ret) return ret; - kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops); - sgi_dev->base_addr = sgi_base; - sgi_dev->iodev_type = IODEV_REDIST; - sgi_dev->regions = vgic_v3_sgibase_registers; - sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); - sgi_dev->redist_vcpu = vcpu; - - mutex_lock(&kvm->slots_lock); - ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base, - SZ_64K, &sgi_dev->dev); - if (ret) { - kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, - &rd_dev->dev); - goto out; - } - rdreg->free_index++; -out: - mutex_unlock(&kvm->slots_lock); - return ret; + return 0; } static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) { struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; - struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev; kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &rd_dev->dev); - kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &sgi_dev->dev); } static int vgic_register_all_redist_iodevs(struct kvm *kvm) @@ -828,8 +805,8 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr) iodev.base_addr = 0; break; case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:{ - iodev.regions = vgic_v3_rdbase_registers; - iodev.nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); + iodev.regions = vgic_v3_rd_registers; + iodev.nr_regions = ARRAY_SIZE(vgic_v3_rd_registers); iodev.base_addr = 0; break; } @@ -987,21 +964,11 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write, int offset, u32 *val) { struct vgic_io_device rd_dev = { - .regions = vgic_v3_rdbase_registers, - .nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers), + .regions = vgic_v3_rd_registers, + .nr_regions = ARRAY_SIZE(vgic_v3_rd_registers), }; - struct vgic_io_device sgi_dev = { - .regions = vgic_v3_sgibase_registers, - .nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers), - }; - - /* SGI_base is the next 64K frame after RD_base */ - if (offset >= SZ_64K) - return vgic_uaccess(vcpu, &sgi_dev, is_write, offset - SZ_64K, - val); - else - return vgic_uaccess(vcpu, &rd_dev, is_write, offset, val); + return vgic_uaccess(vcpu, &rd_dev, is_write, offset, val); } int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write, -- GitLab From e6fe57ebd5290ef7548c298ff0cf5da575600ff3 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:29 +0930 Subject: [PATCH 4358/7155] ARM: configs: multi_v7: Add ASPEED G6 This adds the ASPEED AST2600 system and associated ASPEED devices so we get build coverage. The changes to the UART configuration to ensure the default console (UART5) works. Acked-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/configs/multi_v7_defconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6a40bc2ef271..a731cd103abd 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -9,6 +9,8 @@ CONFIG_ARCH_VIRT=y CONFIG_ARCH_ALPINE=y CONFIG_ARCH_ARTPEC=y CONFIG_MACH_ARTPEC6=y +CONFIG_ARCH_ASPEED=y +CONFIG_MACH_ASPEED_G6=y CONFIG_ARCH_AT91=y CONFIG_SOC_SAMA5D2=y CONFIG_SOC_SAMA5D3=y @@ -198,6 +200,7 @@ CONFIG_MTD_NAND_BRCMNAND=y CONFIG_MTD_NAND_VF610_NFC=y CONFIG_MTD_NAND_DAVINCI=y CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_ASPEED_SMC=m CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y @@ -304,7 +307,11 @@ CONFIG_INPUT_STPMIC1_ONKEY=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_ASPEED_VUART=m CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_8250_DW=y @@ -349,6 +356,8 @@ CONFIG_SERIAL_STM32=y CONFIG_SERIAL_STM32_CONSOLE=y CONFIG_SERIAL_DEV_BUS=y CONFIG_VIRTIO_CONSOLE=y +CONFIG_ASPEED_KCS_IPMI_BMC=m +CONFIG_ASPEED_BT_IPMI_BMC=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_ST=y CONFIG_TCG_TPM=m @@ -358,6 +367,7 @@ CONFIG_I2C_ARB_GPIO_CHALLENGE=m CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_MUX_PINCTRL=y CONFIG_I2C_DEMUX_PINCTRL=y +CONFIG_I2C_ASPEED=m CONFIG_I2C_AT91=m CONFIG_I2C_BCM2835=y CONFIG_I2C_CADENCE=y @@ -461,6 +471,7 @@ CONFIG_CHARGER_MAX77693=m CONFIG_CHARGER_MAX8997=m CONFIG_CHARGER_MAX8998=m CONFIG_CHARGER_TPS65090=y +CONFIG_SENSORS_ASPEED=m CONFIG_SENSORS_IIO_HWMON=y CONFIG_SENSORS_LM90=y CONFIG_SENSORS_LM95245=y @@ -590,6 +601,7 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_ASPEED=m CONFIG_VIDEO_STM32_DCMI=m CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS=m CONFIG_VIDEO_S5P_FIMC=m @@ -659,6 +671,7 @@ CONFIG_DRM_MXSFB=m CONFIG_DRM_PL111=m CONFIG_DRM_LIMA=m CONFIG_DRM_PANFROST=m +CONFIG_DRM_ASPEED_GFX=m CONFIG_FB_EFI=y CONFIG_FB_WM8505=y CONFIG_FB_SH_MOBILE_LCDC=y @@ -758,6 +771,7 @@ CONFIG_USB_MXS_PHY=y CONFIG_USB_GADGET=y CONFIG_USB_FSL_USB2=y CONFIG_USB_RENESAS_USBHS_UDC=m +CONFIG_USB_ASPEED_VHUB=m CONFIG_USB_CONFIGFS=m CONFIG_USB_CONFIGFS_SERIAL=y CONFIG_USB_CONFIGFS_ACM=y @@ -866,6 +880,7 @@ CONFIG_RTC_DRV_TEGRA=y CONFIG_RTC_DRV_ST_LPC=y CONFIG_RTC_DRV_STM32=y CONFIG_RTC_DRV_CPCAP=m +CONFIG_RTC_DRV_ASPEED=m CONFIG_DMADEVICES=y CONFIG_AT_HDMAC=y CONFIG_AT_XDMAC=y @@ -915,6 +930,9 @@ CONFIG_TEGRA_IOMMU_SMMU=y CONFIG_REMOTEPROC=m CONFIG_ST_REMOTEPROC=m CONFIG_RPMSG_VIRTIO=m +CONFIG_ASPEED_LPC_CTRL=m +CONFIG_ASPEED_LPC_SNOOP=m +CONFIG_ASPEED_P2A_CTRL=m CONFIG_RASPBERRYPI_POWER=y CONFIG_QCOM_GSBI=y CONFIG_QCOM_PM=y @@ -947,6 +965,7 @@ CONFIG_ARM_TEGRA_DEVFREQ=m CONFIG_TI_AEMIF=y CONFIG_IIO=y CONFIG_IIO_SW_TRIGGER=y +CONFIG_ASPEED_ADC=m CONFIG_AT91_ADC=m CONFIG_AT91_SAMA5D2_ADC=m CONFIG_BERLIN2_ADC=m -- GitLab From 4cdabee7d6d2e439fea726a101e448c4ca6837f4 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:30 +0930 Subject: [PATCH 4359/7155] ARM: configs: aspeed_g5: Enable AST2600 CONFIG_STRICT_KERNEL_RWX is enabled by default with ARMv7. Turn on HIGHMEM as the EVB has 2GB of RAM, and not all is usable without hihgmem. The SoC contains Cortex A7 supporting VFP and has two CPUs. Acked-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/configs/aspeed_g5_defconfig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index 426d8e0c9890..597536cc9573 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -21,21 +21,26 @@ CONFIG_PERF_EVENTS=y CONFIG_SLAB=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_ARCH_MULTI_V6=y -# CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_ASPEED=y CONFIG_MACH_ASPEED_G5=y +CONFIG_MACH_ASPEED_G6=y # CONFIG_CACHE_L2X0 is not set +CONFIG_SMP=y +# CONFIG_ARM_CPU_TOPOLOGY is not set CONFIG_VMSPLIT_2G=y +CONFIG_NR_CPUS=2 +CONFIG_HIGHMEM=y CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y # CONFIG_ATAGS is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_KEXEC=y -# CONFIG_SUSPEND is not set +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_JUMP_LABEL=y -CONFIG_STRICT_KERNEL_RWX=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEBUG_FS is not set # CONFIG_MQ_IOSCHED_DEADLINE is not set @@ -140,10 +145,12 @@ CONFIG_ASPEED_BT_IPMI_BMC=y CONFIG_HW_RANDOM_TIMERIOMEM=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA9541=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_ASPEED=y CONFIG_I2C_FSI=y +CONFIG_SPI=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_ASPEED=y @@ -194,6 +201,10 @@ CONFIG_USB_CONFIGFS_F_LB_SS=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ASPEED=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_CLASS_FLASH=y -- GitLab From 5177cabf5cfdc018b4110e6fa2f6f72229ee0e60 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:24 +0930 Subject: [PATCH 4360/7155] dt-bindings: arm: cpus: Add ASPEED SMP The AST2600 SoC contains two CPUs and requires the operating system to bring the second one out of firmware. Acked-by: Rob Herring Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- Documentation/devicetree/bindings/arm/cpus.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index aa40b074b864..727e0ffc702b 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -175,6 +175,7 @@ properties: - amlogic,meson8-smp - amlogic,meson8b-smp - arm,realview-smp + - aspeed,ast2600-smp - brcm,bcm11351-cpu-method - brcm,bcm23550 - brcm,bcm2836-smp -- GitLab From e35d7db99430731dae04feeeb5cb6ec3e77cd5e5 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:25 +0930 Subject: [PATCH 4361/7155] ARM: aspeed: Select timer in each SoC In preparation for adding the ast2600 which does not use this timer. Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/mach-aspeed/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig index a15c3a291386..2979aa4daeea 100644 --- a/arch/arm/mach-aspeed/Kconfig +++ b/arch/arm/mach-aspeed/Kconfig @@ -5,7 +5,6 @@ menuconfig ARCH_ASPEED select SRAM select WATCHDOG select ASPEED_WATCHDOG - select FTTMR010_TIMER select MFD_SYSCON select PINCTRL help @@ -18,6 +17,7 @@ config MACH_ASPEED_G4 depends on ARCH_MULTI_V5 select CPU_ARM926T select PINCTRL_ASPEED_G4 + select FTTMR010_TIMER help Say yes if you intend to run on an Aspeed ast2400 or similar fourth generation BMCs, such as those used by OpenPower Power8 @@ -28,6 +28,7 @@ config MACH_ASPEED_G5 depends on ARCH_MULTI_V6 select CPU_V6 select PINCTRL_ASPEED_G5 + select FTTMR010_TIMER help Say yes if you intend to run on an Aspeed ast2500 or similar fifth generation Aspeed BMCs. -- GitLab From 9afe2c0a376f56f6bd78c7c5b9dec5e8f5d5a327 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:26 +0930 Subject: [PATCH 4362/7155] ARM: aspeed: Add ASPEED AST2600 architecture The AST2600 is a Cortex A7 dual core CPU that uses the ARM GIC for interrupts and ARM timer as a clocksource. Reviewed-by: Andrew Jeffery Signed-off-by: Joel Stanley --- arch/arm/mach-aspeed/Kconfig | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig index 2979aa4daeea..56007b0b6120 100644 --- a/arch/arm/mach-aspeed/Kconfig +++ b/arch/arm/mach-aspeed/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only menuconfig ARCH_ASPEED bool "Aspeed BMC architectures" - depends on ARCH_MULTI_V5 || ARCH_MULTI_V6 + depends on ARCH_MULTI_V5 || ARCH_MULTI_V6 || ARCH_MULTI_V7 select SRAM select WATCHDOG select ASPEED_WATCHDOG @@ -33,4 +33,16 @@ config MACH_ASPEED_G5 Say yes if you intend to run on an Aspeed ast2500 or similar fifth generation Aspeed BMCs. +config MACH_ASPEED_G6 + bool "Aspeed SoC 6th Generation" + depends on ARCH_MULTI_V7 + select CPU_V7 + select PINCTRL_ASPEED_G6 + select ARM_GIC + select HAVE_ARM_ARCH_TIMER + select HAVE_SMP + help + Say yes if you intend to run on an Aspeed ast2600 or similar + sixth generation Aspeed BMCs. + endif -- GitLab From 87dfe49691a3aefd66ebe76a4a0cc9e872d2587b Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 21 Aug 2019 15:25:27 +0930 Subject: [PATCH 4363/7155] ARM: aspeed: Enable SMP boot This brings the secondary CPU into Linux. It depends on the setup performed by ASPEED's u-boot. Signed-off-by: Joel Stanley --- arch/arm/Makefile | 1 + arch/arm/mach-aspeed/Makefile | 5 +++ arch/arm/mach-aspeed/platsmp.c | 61 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 arch/arm/mach-aspeed/Makefile create mode 100644 arch/arm/mach-aspeed/platsmp.c diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c3624ca6c0bc..5fe6bd23dcd2 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -155,6 +155,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 machine-$(CONFIG_ARCH_ACTIONS) += actions machine-$(CONFIG_ARCH_ALPINE) += alpine machine-$(CONFIG_ARCH_ARTPEC) += artpec +machine-$(CONFIG_ARCH_ASPEED) += aspeed machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_AXXIA) += axxia machine-$(CONFIG_ARCH_BCM) += bcm diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile new file mode 100644 index 000000000000..1951b3317a76 --- /dev/null +++ b/arch/arm/mach-aspeed/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) ASPEED Technology Inc. +# Copyright IBM Corp. + +obj-$(CONFIG_SMP) += platsmp.o diff --git a/arch/arm/mach-aspeed/platsmp.c b/arch/arm/mach-aspeed/platsmp.c new file mode 100644 index 000000000000..2324becf7991 --- /dev/null +++ b/arch/arm/mach-aspeed/platsmp.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) ASPEED Technology Inc. +// Copyright IBM Corp. + +#include +#include +#include +#include + +#define BOOT_ADDR 0x00 +#define BOOT_SIG 0x04 + +static struct device_node *secboot_node; + +static int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + void __iomem *base; + + base = of_iomap(secboot_node, 0); + if (!base) { + pr_err("could not map the secondary boot base!"); + return -ENODEV; + } + + writel_relaxed(0, base + BOOT_ADDR); + writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR); + writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG); + + dsb_sev(); + + iounmap(base); + + return 0; +} + +static void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus) +{ + void __iomem *base; + + secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem"); + if (!secboot_node) { + pr_err("secboot device node found!!\n"); + return; + } + + base = of_iomap(secboot_node, 0); + if (!base) { + pr_err("could not map the secondary boot base!"); + return; + } + __raw_writel(0xBADABABA, base + BOOT_SIG); + + iounmap(base); +} + +static const struct smp_operations aspeed_smp_ops __initconst = { + .smp_prepare_cpus = aspeed_g6_smp_prepare_cpus, + .smp_boot_secondary = aspeed_g6_boot_secondary, +}; + +CPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops); -- GitLab From d2a415c86c6b07c10ba2decc7c9edb21d58f9c01 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Wed, 21 Aug 2019 17:16:53 +0300 Subject: [PATCH 4364/7155] iio: adc: ad7606: Add support for AD7606B ADC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AD7606B is a 16-bit ADC that supports simultaneous sampling of 8 channels. It is pin compatible to AD7606, but adds extra modes by writing to the register map. The AD7606B can be configured to work in software mode by setting all oversampling pins to high. This mode is selected by default. The oversampling ratio is configured from the OS_MODE register (address 0x08) with the addition of OS=128 and OS=256 that were not available in hardware mode. The device is configured to output data on a single spi channel, but this configuration must be done right after restart. That is why the delay was removed for devices which doesn't require it. Moreover, in software mode, the range gpio has no longer its function. Instead, the scale can be configured individually for each channel from the RANGE_CH registers (address 0x03 to 0x06). Besides the already supported ±10 V and ±5 V ranges, software mode can also accommodate the ±2.5 V range. Signed-off-by: Stefan Popa Co-developed-by: Beniamin Bia Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 13 ++++- drivers/iio/adc/ad7606.h | 4 ++ drivers/iio/adc/ad7606_spi.c | 109 ++++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index ed2d08437e5d..f5ba94c03a8d 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -410,12 +410,19 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, + [ID_AD7606B] = { + .channels = ad7606_channels, + .num_channels = 9, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), + }, [ID_AD7616] = { .channels = ad7616_channels, .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, + .init_delay_ms = 15, }, }; @@ -631,8 +638,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); /* AD7616 requires al least 15ms to reconfigure after a reset */ - if (msleep_interruptible(15)) - return -ERESTARTSYS; + if (st->chip_info->init_delay_ms) { + if (msleep_interruptible(st->chip_info->init_delay_ms)) + return -ERESTARTSYS; + } st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index eeaaa8b905db..9350ef1f63b5 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -46,6 +46,8 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling + * @init_delay_ms required delay in miliseconds for initialization + * after a restart */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -53,6 +55,7 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; + unsigned long init_delay_ms; }; /** @@ -155,6 +158,7 @@ enum ad7606_supported_device_ids { ID_AD7606_8, ID_AD7606_6, ID_AD7606_4, + ID_AD7606B, ID_AD7616, }; diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 98ed52b74507..29945ad07dca 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -28,9 +28,23 @@ * an offset of 2 for register address. */ #define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) -/* The range of the channel is stored on 2 bits*/ +/* The range of the channel is stored in 2 bits */ #define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) #define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) + +#define AD7606_CONFIGURATION_REGISTER 0x02 +#define AD7606_SINGLE_DOUT 0x00 + +/* + * Range for AD7606B channels are stored in registers starting with address 0x3. + * Each register stores range for 2 channels(4 bits per channel). + */ +#define AD7606_RANGE_CH_MSK(ch) (GENMASK(3, 0) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_MODE(ch, mode) \ + ((GENMASK(3, 0) & mode) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) +#define AD7606_OS_MODE 0x08 + static const struct iio_chan_spec ad7616_sw_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(16), AD7616_CHANNEL(0), @@ -51,6 +65,22 @@ static const struct iio_chan_spec ad7616_sw_channels[] = { AD7616_CHANNEL(15), }; +static const struct iio_chan_spec ad7606b_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), +}; + +static const unsigned int ad7606B_oversampling_avail[9] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 +}; + static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) { /* @@ -60,6 +90,16 @@ static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); } +static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op) +{ + /* + * The address of register consists of one bit which + * specifies a read command placed in bit 6, followed by + * 6 bits of address. + */ + return (addr & 0x3F) | (((~is_write_op) & 0x1) << 6); +} + static int ad7606_spi_read_block(struct device *dev, int count, void *buf) { @@ -169,6 +209,23 @@ static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) AD7616_OS_MASK, val << 2); } +static int ad7606_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_write_mask(st, + AD7606_RANGE_CH_ADDR(ch), + AD7606_RANGE_CH_MSK(ch), + AD7606_RANGE_CH_MODE(ch, val)); +} + +static int ad7606_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_reg_write(st, AD7606_OS_MODE, val); +} + static int ad7616_sw_mode_config(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); @@ -189,6 +246,42 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev) AD7616_BURST_MODE | AD7616_SEQEN_MODE); } +static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned long os[3] = {1}; + + /* + * Software mode is enabled when all three oversampling + * pins are set to high. If oversampling gpios are defined + * in the device tree, then they need to be set to high, + * otherwise, they must be hardwired to VDD + */ + if (st->gpio_os) { + gpiod_set_array_value(ARRAY_SIZE(os), + st->gpio_os->desc, st->gpio_os->info, os); + } + /* OS of 128 and 256 are available only in software mode */ + st->oversampling_avail = ad7606B_oversampling_avail; + st->num_os_ratios = ARRAY_SIZE(ad7606B_oversampling_avail); + + st->write_scale = ad7606_write_scale_sw; + st->write_os = &ad7606_write_os_sw; + + /* Configure device spi to output on a single channel */ + st->bops->reg_write(st, + AD7606_CONFIGURATION_REGISTER, + AD7606_SINGLE_DOUT); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7606b_sw_channels; + + return 0; +} + static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; @@ -202,6 +295,15 @@ static const struct ad7606_bus_ops ad7616_spi_bops = { .sw_mode_config = ad7616_sw_mode_config, }; +static const struct ad7606_bus_ops ad7606B_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, + .sw_mode_config = ad7606B_sw_mode_config, +}; + static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -211,6 +313,9 @@ static int ad7606_spi_probe(struct spi_device *spi) case ID_AD7616: bops = &ad7616_spi_bops; break; + case ID_AD7606B: + bops = &ad7606B_spi_bops; + break; default: bops = &ad7606_spi_bops; break; @@ -226,6 +331,7 @@ static const struct spi_device_id ad7606_id_table[] = { { "ad7606-4", ID_AD7606_4 }, { "ad7606-6", ID_AD7606_6 }, { "ad7606-8", ID_AD7606_8 }, + { "ad7606b", ID_AD7606B }, { "ad7616", ID_AD7616 }, {} }; @@ -236,6 +342,7 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-4" }, { .compatible = "adi,ad7606-6" }, { .compatible = "adi,ad7606-8" }, + { .compatible = "adi,ad7606b" }, { .compatible = "adi,ad7616" }, { }, }; -- GitLab From 75338cc8eb29c90323eb7d54ec09d25e86625515 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:54 +0300 Subject: [PATCH 4365/7155] MAINTAINERS: Add Beniamin Bia for AD7606 driver Add Beniamin Bia as maintainer for AD7606 driver. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index ac3a5cd6a682..92c2603b71b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -903,6 +903,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml ANALOG DEVICES INC AD7606 DRIVER M: Stefan Popa +M: Beniamin Bia L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported -- GitLab From 416f882c3b404938ba26622469a956c4cd9f7558 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:55 +0300 Subject: [PATCH 4366/7155] dt-bindings: iio: adc: Migrate AD7606 documentation to yaml The documentation for ad7606 was migrated to yaml. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/adi,ad7606.txt | 66 --------- .../bindings/iio/adc/adi,ad7606.yaml | 136 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 137 insertions(+), 67 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt deleted file mode 100644 index d8652460198e..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +++ /dev/null @@ -1,66 +0,0 @@ -Analog Devices AD7606 Simultaneous Sampling ADC - -Required properties for the AD7606: - -- compatible: Must be one of - * "adi,ad7605-4" - * "adi,ad7606-8" - * "adi,ad7606-6" - * "adi,ad7606-4" - * "adi,ad7616" -- reg: SPI chip select number for the device -- spi-max-frequency: Max SPI frequency to use - see: Documentation/devicetree/bindings/spi/spi-bus.txt -- spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt -- avcc-supply: phandle to the Avcc power supply -- interrupts: IRQ line for the ADC - see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -- adi,conversion-start-gpios: must be the device tree identifier of the CONVST pin. - This logic input is used to initiate conversions on the analog - input channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Optional properties: - -- reset-gpios: must be the device tree identifier of the RESET pin. If specified, - it will be asserted during driver probe. As the line is active high, - it should be marked GPIO_ACTIVE_HIGH. -- standby-gpios: must be the device tree identifier of the STBY pin. This pin is used - to place the AD7606 into one of two power-down modes, Standby mode or - Shutdown mode. As the line is active low, it should be marked - GPIO_ACTIVE_LOW. -- adi,first-data-gpios: must be the device tree identifier of the FRSTDATA pin. - The FRSTDATA output indicates when the first channel, V1, is - being read back on either the parallel, byte or serial interface. - As the line is active high, it should be marked GPIO_ACTIVE_HIGH. -- adi,range-gpios: must be the device tree identifier of the RANGE pin. The polarity on - this pin determines the input range of the analog input channels. If - this pin is tied to a logic high, the analog input range is ±10V for - all channels. If this pin is tied to a logic low, the analog input range - is ±5V for all channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. -- adi,oversampling-ratio-gpios: must be the device tree identifier of the over-sampling - mode pins. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Example: - - adc@0 { - compatible = "adi,ad7606-8"; - reg = <0>; - spi-max-frequency = <1000000>; - spi-cpol; - - avcc-supply = <&adc_vref>; - - interrupts = <25 IRQ_TYPE_EDGE_FALLING>; - interrupt-parent = <&gpio>; - - adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; - adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; - adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH - &gpio 23 GPIO_ACTIVE_HIGH - &gpio 26 GPIO_ACTIVE_HIGH>; - standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml new file mode 100644 index 000000000000..3ecdfa780ae3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7606.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7606 Simultaneous Sampling ADC + +maintainers: + - Beniamin Bia + - Stefan Popa + +description: | + Analog Devices AD7606 Simultaneous Sampling ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf + +properties: + compatible: + enum: + - adi,ad7605-4 + - adi,ad7606-8 + - adi,ad7606-6 + - adi,ad7606-4 + - adi,ad7616 + + reg: + maxItems: 1 + + spi-cpha: true + + avcc-supply: + description: + Phandle to the Avcc power supply + maxItems: 1 + + interrupts: + maxItems: 1 + + adi,conversion-start-gpios: + description: + Must be the device tree identifier of the CONVST pin. + This logic input is used to initiate conversions on the analog + input channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + reset-gpios: + description: + Must be the device tree identifier of the RESET pin. If specified, + it will be asserted during driver probe. As the line is active high, + it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + standby-gpios: + description: + Must be the device tree identifier of the STBY pin. This pin is used + to place the AD7606 into one of two power-down modes, Standby mode or + Shutdown mode. As the line is active low, it should be marked + GPIO_ACTIVE_LOW. + maxItems: 1 + + adi,first-data-gpios: + description: + Must be the device tree identifier of the FRSTDATA pin. + The FRSTDATA output indicates when the first channel, V1, is + being read back on either the parallel, byte or serial interface. + As the line is active high, it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,range-gpios: + description: + Must be the device tree identifier of the RANGE pin. The polarity on + this pin determines the input range of the analog input channels. If + this pin is tied to a logic high, the analog input range is ±10V for + all channels. If this pin is tied to a logic low, the analog input range + is ±5V for all channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,oversampling-ratio-gpios: + description: + Must be the device tree identifier of the over-sampling + mode pins. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,sw-mode: + description: + Software mode of operation, so far available only for ad7616. + It is enabled when all three oversampling mode pins are connected to + high level. The device is configured by the corresponding registers. If the + adi,oversampling-ratio-gpios property is defined, then the driver will set the + oversampling gpios to high. Otherwise, it is assumed that the pins are hardwired + to VDD. + type: boolean + +required: + - compatible + - reg + - spi-cpha + - avcc-supply + - interrupts + - adi,conversion-start-gpios + +examples: + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7606-8"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + + avcc-supply = <&adc_vref>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + + adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; + adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; + adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH + &gpio 23 GPIO_ACTIVE_HIGH + &gpio 26 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; + adi,sw-mode; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 92c2603b71b7..f0c03740b9fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -908,7 +908,7 @@ L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported F: drivers/iio/adc/ad7606.c -F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml ANALOG DEVICES INC AD7768-1 DRIVER M: Stefan Popa -- GitLab From 6b4d6822eef58dc17d35ece72369045247843990 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:56 +0300 Subject: [PATCH 4367/7155] dt-bindings: iio: adc: Add AD7606B ADC documentation Documentation for AD7606B Analog to Digital Converter and software mode was added. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml index 3ecdfa780ae3..cc544fdc38be 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -13,6 +13,7 @@ maintainers: description: | Analog Devices AD7606 Simultaneous Sampling ADC https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf properties: @@ -22,6 +23,7 @@ properties: - adi,ad7606-8 - adi,ad7606-6 - adi,ad7606-4 + - adi,ad7606b - adi,ad7616 reg: @@ -87,7 +89,7 @@ properties: adi,sw-mode: description: - Software mode of operation, so far available only for ad7616. + Software mode of operation, so far available only for ad7616 and ad7606b. It is enabled when all three oversampling mode pins are connected to high level. The device is configured by the corresponding registers. If the adi,oversampling-ratio-gpios property is defined, then the driver will set the -- GitLab From 258128e8e953c84bd46e487deedcae2bd6543bd4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 23 Aug 2019 20:18:52 +0800 Subject: [PATCH 4368/7155] iio: st_sensors: Fix build error IIO_ST_SENSORS_CORE select IIO_ST_SENSORS_I2C unconditionally, if REGMAP_I2C is not set, build fails drivers/iio/common/st_sensors/st_sensors_i2c.o: In function `st_sensors_i2c_configure': st_sensors_i2c.c:(.text+0x58): undefined reference to `__devm_regmap_init_i2c' This patch selects REGMAP_I2C to fix it. IIO_ST_SENSORS_SPI is similar to SPI issue. Reported-by: Hulk Robot Fixes: 062809ef7733 ("iio: make st_sensors drivers use regmap") Signed-off-by: YueHaibing Signed-off-by: Jonathan Cameron --- drivers/iio/common/st_sensors/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig index 91b98e152d75..9364ec7a811f 100644 --- a/drivers/iio/common/st_sensors/Kconfig +++ b/drivers/iio/common/st_sensors/Kconfig @@ -5,9 +5,11 @@ config IIO_ST_SENSORS_I2C tristate + select REGMAP_I2C config IIO_ST_SENSORS_SPI tristate + select REGMAP_SPI config IIO_ST_SENSORS_CORE tristate -- GitLab From 4a5e353c16d13168b8906c96013b887896ccf41a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 19 Aug 2019 06:48:27 +0200 Subject: [PATCH 4369/7155] Kconfig: Fix the reference to the RFD77402 ToF sensor in the 'help' section This should be RFD77402, not RFD77420. Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 6b5cce6f1a7b..d53601447da4 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -62,7 +62,7 @@ config RFD77402 tristate "RFD77402 ToF sensor" depends on I2C help - Say Y to build a driver for the RFD77420 Time-of-Flight (distance) + Say Y to build a driver for the RFD77402 Time-of-Flight (distance) sensor module with I2C interface. To compile this driver as a module, choose M here: the -- GitLab From 88149b520950956f0f786d06693d11df8d6f6da4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 19 Aug 2019 16:17:08 +0200 Subject: [PATCH 4370/7155] dt-bindings: iio: light: isl29501: Rename bindings documentation file Rename the bindings documentation file for Renesas ISL29501 Time-of-flight sensor from isl29501.txt to renesas,isl29501.txt. This is part of an ongoing effort to name bindings documentation files for Renesas IP blocks consistently, in line with the compat strings they document. Signed-off-by: Simon Horman Signed-off-by: Jonathan Cameron --- .../bindings/iio/light/{isl29501.txt => renesas,isl29501.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/iio/light/{isl29501.txt => renesas,isl29501.txt} (100%) diff --git a/Documentation/devicetree/bindings/iio/light/isl29501.txt b/Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt similarity index 100% rename from Documentation/devicetree/bindings/iio/light/isl29501.txt rename to Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt -- GitLab From ee641b0cdb9486f8212a3da153a46ab3551a97e5 Mon Sep 17 00:00:00 2001 From: Mao Wenan Date: Mon, 26 Aug 2019 09:31:18 +0800 Subject: [PATCH 4371/7155] net: mediatek: remove set but not used variable 'status' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/ethernet/mediatek/mtk_eth_soc.c: In function mtk_handle_irq: drivers/net/ethernet/mediatek/mtk_eth_soc.c:1951:6: warning: variable status set but not used [-Wunused-but-set-variable] Fixes: 296c9120752b ("net: ethernet: mediatek: Add MT7628/88 SoC support") Signed-off-by: Mao Wenan Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 8ddbb8dcf032..bb7d623c6044 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1948,9 +1948,7 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) static irqreturn_t mtk_handle_irq(int irq, void *_eth) { struct mtk_eth *eth = _eth; - u32 status; - status = mtk_r32(eth, MTK_PDMA_INT_STATUS); if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) { if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT) mtk_handle_irq_rx(irq, _eth); -- GitLab From 2889456498c635f4e8262a8401b2eddc263953c7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 25 Aug 2019 19:07:04 -0700 Subject: [PATCH 4372/7155] Revert "net: mediatek: remove set but not used variable 'status'" This reverts commit ee641b0cdb9486f8212a3da153a46ab3551a97e5. Actually it is not clear whether this register read is not needed for it's HW side effects or not. Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index bb7d623c6044..8ddbb8dcf032 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1948,7 +1948,9 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) static irqreturn_t mtk_handle_irq(int irq, void *_eth) { struct mtk_eth *eth = _eth; + u32 status; + status = mtk_r32(eth, MTK_PDMA_INT_STATUS); if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) { if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT) mtk_handle_irq_rx(irq, _eth); -- GitLab From 0846e1616f0f3365cea732e82e2383932fe644e5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 26 Aug 2019 02:49:15 +0000 Subject: [PATCH 4373/7155] cirrus: cs89x0: remove set but not used variable 'lp' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/ethernet/cirrus/cs89x0.c: In function 'cs89x0_platform_probe': drivers/net/ethernet/cirrus/cs89x0.c:1847:20: warning: variable 'lp' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Fixes: 6751edeb8700 ("cirrus: cs89x0: Use managed interfaces") Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/cirrus/cs89x0.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index 2d30972df06b..c9aebcde403a 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1844,15 +1844,12 @@ cleanup_module(void) static int __init cs89x0_platform_probe(struct platform_device *pdev) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); - struct net_local *lp; void __iomem *virt_addr; int err; if (!dev) return -ENOMEM; - lp = netdev_priv(dev); - dev->irq = platform_get_irq(pdev, 0); if (dev->irq <= 0) { dev_warn(&dev->dev, "interrupt resource missing\n"); -- GitLab From 3b72950d5a331686f55a11149b93e2543289b19b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 21 Aug 2019 15:25:17 +0200 Subject: [PATCH 4374/7155] iio: imu: st_lsm6dsx: introduce update_fifo function pointer Introduce update_fifo routine pointer in st_lsm6dsx_fifo_ops data structure since we will need a different update FIFO configuration callback adding support for lsm6ds0/lsm9ds1 imu device Signed-off-by: Lorenzo Bianconi Tested-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 ++++ .../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 19 +++++++++++++++---- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 6 ++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 4e8e67ae1632..055e52dec36a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -75,6 +75,7 @@ struct st_lsm6dsx_reg { u8 mask; }; +struct st_lsm6dsx_sensor; struct st_lsm6dsx_hw; struct st_lsm6dsx_odr { @@ -101,12 +102,14 @@ struct st_lsm6dsx_fs_table_entry { /** * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings + * @update_fifo: Update FIFO configuration callback. * @read_fifo: Read FIFO callback. * @fifo_th: FIFO threshold register info (addr + mask). * @fifo_diff: FIFO diff status register info (addr + mask). * @th_wl: FIFO threshold word length. */ struct st_lsm6dsx_fifo_ops { + int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); int (*read_fifo)(struct st_lsm6dsx_hw *hw); struct { u8 addr; @@ -327,6 +330,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark); +int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, enum st_lsm6dsx_fifo_mode fifo_mode); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 2c03a5b80f80..b0f3da1976e4 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -602,9 +602,8 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) return err; } -static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable) +int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) { - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_hw *hw = sensor->hw; int err; @@ -676,12 +675,24 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, true); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, true); } static int st_lsm6dsx_buffer_postdisable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, false); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, false); } static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 85824d6739ee..0aa93b45d772 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -154,6 +154,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -262,6 +263,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -379,6 +381,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -490,6 +493,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -616,6 +620,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -719,6 +724,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, -- GitLab From dce2e3a8414e31fc286a3f8064df773a3af83a26 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:03 +0530 Subject: [PATCH 4375/7155] cpufreq: powerpc: macintosh: Switch to QoS requests for freq limits The cpufreq core now takes the min/max frequency constraints via QoS requests and the CPUFREQ_ADJUST notifier shall get removed later on. Switch over to using the QoS request for maximum frequency constraint for windfarm_cpufreq_clamp driver. Signed-off-by: Viresh Kumar [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- drivers/macintosh/windfarm_cpufreq_clamp.c | 77 ++++++++++++++-------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c index 52fd5fca89a0..705c6200814b 100644 --- a/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -16,36 +18,24 @@ static int clamped; static struct wf_control *clamp_control; - -static int clamp_notifier_call(struct notifier_block *self, - unsigned long event, void *data) -{ - struct cpufreq_policy *p = data; - unsigned long max_freq; - - if (event != CPUFREQ_ADJUST) - return 0; - - max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq); - cpufreq_verify_within_limits(p, 0, max_freq); - - return 0; -} - -static struct notifier_block clamp_notifier = { - .notifier_call = clamp_notifier_call, -}; +static struct dev_pm_qos_request qos_req; +static unsigned int min_freq, max_freq; static int clamp_set(struct wf_control *ct, s32 value) { - if (value) + unsigned int freq; + + if (value) { + freq = min_freq; printk(KERN_INFO "windfarm: Clamping CPU frequency to " "minimum !\n"); - else + } else { + freq = max_freq; printk(KERN_INFO "windfarm: CPU frequency unclamped !\n"); + } clamped = value; - cpufreq_update_policy(0); - return 0; + + return dev_pm_qos_update_request(&qos_req, freq); } static int clamp_get(struct wf_control *ct, s32 *value) @@ -74,27 +64,60 @@ static const struct wf_control_ops clamp_ops = { static int __init wf_cpufreq_clamp_init(void) { + struct cpufreq_policy *policy; struct wf_control *clamp; + struct device *dev; + int ret; + + policy = cpufreq_cpu_get(0); + if (!policy) { + pr_warn("%s: cpufreq policy not found cpu0\n", __func__); + return -EPROBE_DEFER; + } + + min_freq = policy->cpuinfo.min_freq; + max_freq = policy->cpuinfo.max_freq; + cpufreq_cpu_put(policy); + + dev = get_cpu_device(0); + if (unlikely(!dev)) { + pr_warn("%s: No cpu device for cpu0\n", __func__); + return -ENODEV; + } clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); if (clamp == NULL) return -ENOMEM; - cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER); + + ret = dev_pm_qos_add_request(dev, &qos_req, DEV_PM_QOS_MAX_FREQUENCY, + max_freq); + if (ret < 0) { + pr_err("%s: Failed to add freq constraint (%d)\n", __func__, + ret); + goto free; + } + clamp->ops = &clamp_ops; clamp->name = "cpufreq-clamp"; - if (wf_register_control(clamp)) + ret = wf_register_control(clamp); + if (ret) goto fail; clamp_control = clamp; return 0; fail: + dev_pm_qos_remove_request(&qos_req); + + free: kfree(clamp); - return -ENODEV; + return ret; } static void __exit wf_cpufreq_clamp_exit(void) { - if (clamp_control) + if (clamp_control) { wf_unregister_control(clamp_control); + dev_pm_qos_remove_request(&qos_req); + } } -- GitLab From afe969074eb7d0f52761ed80da15e9a282d19677 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 5 Jul 2019 15:49:48 +0530 Subject: [PATCH 4376/7155] cpufreq: powerpc_cbe: Switch to QoS requests for freq limits The cpufreq core now takes the min/max frequency constraints via QoS requests and the CPUFREQ_ADJUST notifier shall get removed later on. Switch over to using the QoS request for maximum frequency constraint for ppc_cbe_cpufreq driver. Signed-off-by: Viresh Kumar [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/ppc_cbe_cpufreq.c | 19 +++++- drivers/cpufreq/ppc_cbe_cpufreq.h | 8 +++ drivers/cpufreq/ppc_cbe_cpufreq_pmi.c | 96 +++++++++++++++++---------- 3 files changed, 86 insertions(+), 37 deletions(-) diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index b83f36febf03..c58abb4cca3a 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -110,6 +110,13 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) #endif policy->freq_table = cbe_freqs; + cbe_cpufreq_pmi_policy_init(policy); + return 0; +} + +static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + cbe_cpufreq_pmi_policy_exit(policy); return 0; } @@ -129,6 +136,7 @@ static struct cpufreq_driver cbe_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = cbe_cpufreq_target, .init = cbe_cpufreq_cpu_init, + .exit = cbe_cpufreq_cpu_exit, .name = "cbe-cpufreq", .flags = CPUFREQ_CONST_LOOPS, }; @@ -139,15 +147,24 @@ static struct cpufreq_driver cbe_cpufreq_driver = { static int __init cbe_cpufreq_init(void) { + int ret; + if (!machine_is(cell)) return -ENODEV; - return cpufreq_register_driver(&cbe_cpufreq_driver); + cbe_cpufreq_pmi_init(); + + ret = cpufreq_register_driver(&cbe_cpufreq_driver); + if (ret) + cbe_cpufreq_pmi_exit(); + + return ret; } static void __exit cbe_cpufreq_exit(void) { cpufreq_unregister_driver(&cbe_cpufreq_driver); + cbe_cpufreq_pmi_exit(); } module_init(cbe_cpufreq_init); diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.h b/drivers/cpufreq/ppc_cbe_cpufreq.h index 9d973519d669..00cd8633b0d9 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.h +++ b/drivers/cpufreq/ppc_cbe_cpufreq.h @@ -20,6 +20,14 @@ int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode); #if IS_ENABLED(CONFIG_CPU_FREQ_CBE_PMI) extern bool cbe_cpufreq_has_pmi; +void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy); +void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy); +void cbe_cpufreq_pmi_init(void); +void cbe_cpufreq_pmi_exit(void); #else #define cbe_cpufreq_has_pmi (0) +static inline void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) {} +static inline void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy) {} +static inline void cbe_cpufreq_pmi_init(void) {} +static inline void cbe_cpufreq_pmi_exit(void) {} #endif diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c index 97c8ee4614b7..bc9dd30395c4 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -24,8 +25,6 @@ #include "ppc_cbe_cpufreq.h" -static u8 pmi_slow_mode_limit[MAX_CBE]; - bool cbe_cpufreq_has_pmi = false; EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi); @@ -65,64 +64,89 @@ EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi); static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg) { + struct cpufreq_policy *policy; + struct dev_pm_qos_request *req; u8 node, slow_mode; + int cpu, ret; BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE); node = pmi_msg.data1; slow_mode = pmi_msg.data2; - pmi_slow_mode_limit[node] = slow_mode; + cpu = cbe_node_to_cpu(node); pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode); -} - -static int pmi_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_policy *policy = data; - struct cpufreq_frequency_table *cbe_freqs = policy->freq_table; - u8 node; - - /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY - * policy events?) - */ - node = cbe_cpu_to_node(policy->cpu); - - pr_debug("got notified, event=%lu, node=%u\n", event, node); - if (pmi_slow_mode_limit[node] != 0) { - pr_debug("limiting node %d to slow mode %d\n", - node, pmi_slow_mode_limit[node]); + policy = cpufreq_cpu_get(cpu); + if (!policy) { + pr_warn("cpufreq policy not found cpu%d\n", cpu); + return; + } - cpufreq_verify_within_limits(policy, 0, + req = policy->driver_data; - cbe_freqs[pmi_slow_mode_limit[node]].frequency); - } + ret = dev_pm_qos_update_request(req, + policy->freq_table[slow_mode].frequency); + if (ret < 0) + pr_warn("Failed to update freq constraint: %d\n", ret); + else + pr_debug("limiting node %d to slow mode %d\n", node, slow_mode); - return 0; + cpufreq_cpu_put(policy); } -static struct notifier_block pmi_notifier_block = { - .notifier_call = pmi_notifier, -}; - static struct pmi_handler cbe_pmi_handler = { .type = PMI_TYPE_FREQ_CHANGE, .handle_pmi_message = cbe_cpufreq_handle_pmi, }; +void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) +{ + struct dev_pm_qos_request *req; + int ret; + + if (!cbe_cpufreq_has_pmi) + return; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return; + + ret = dev_pm_qos_add_request(get_cpu_device(policy->cpu), req, + DEV_PM_QOS_MAX_FREQUENCY, + policy->freq_table[0].frequency); + if (ret < 0) { + pr_err("Failed to add freq constraint (%d)\n", ret); + kfree(req); + return; + } + policy->driver_data = req; +} +EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init); -static int __init cbe_cpufreq_pmi_init(void) +void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy) { - cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0; + struct dev_pm_qos_request *req = policy->driver_data; - if (!cbe_cpufreq_has_pmi) - return -ENODEV; + if (cbe_cpufreq_has_pmi) { + dev_pm_qos_remove_request(req); + kfree(req); + } +} +EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_exit); - cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); +void cbe_cpufreq_pmi_init(void) +{ + if (!pmi_register_handler(&cbe_pmi_handler)) + cbe_cpufreq_has_pmi = true; +} +EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_init); - return 0; +void cbe_cpufreq_pmi_exit(void) +{ + pmi_unregister_handler(&cbe_pmi_handler); + cbe_cpufreq_has_pmi = false; } -device_initcall(cbe_cpufreq_pmi_init); +EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_exit); -- GitLab From 40f0fc2a416b343a604a8131247a150588658d32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:06 +0530 Subject: [PATCH 4377/7155] arch_topology: Use CPUFREQ_CREATE_POLICY instead of CPUFREQ_NOTIFY CPUFREQ_NOTIFY is going to get removed soon, lets use CPUFREQ_CREATE_POLICY instead of that here. CPUFREQ_CREATE_POLICY is called only once (which is exactly what we want here) for each cpufreq policy when it is first created. Signed-off-by: Viresh Kumar Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/base/arch_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 63c1e76739f1..8cab1f5a8e0c 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -174,7 +174,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, if (!raw_capacity) return 0; - if (val != CPUFREQ_NOTIFY) + if (val != CPUFREQ_CREATE_POLICY) return 0; pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", -- GitLab From eb58a4fad3432be6e9dc2e35b78ae99f4a40ce5f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:07 +0530 Subject: [PATCH 4378/7155] video: sa1100fb: Remove cpufreq policy notifier The cpufreq policy notifier's CPUFREQ_ADJUST notification is going to get removed soon. The notifier callback sa1100fb_freq_policy() isn't doing anything apart from printing a debug message on CPUFREQ_ADJUST notification. There is no point in keeping an otherwise empty callback and registering the notifier. Remove it. Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/video/fbdev/sa1100fb.c | 27 --------------------------- drivers/video/fbdev/sa1100fb.h | 1 - 2 files changed, 28 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index f7f8dee044b1..ae2bcfee338a 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1005,31 +1005,6 @@ sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, } return 0; } - -static int -sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); - struct cpufreq_policy *policy = data; - - switch (val) { - case CPUFREQ_ADJUST: - dev_dbg(fbi->dev, "min dma period: %d ps, " - "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), - policy->max); - /* todo: fill in min/max values */ - break; - case CPUFREQ_NOTIFY: - do {} while(0); - /* todo: panic if min/max values aren't fulfilled - * [can't really happen unless there's a bug in the - * CPU policy verififcation process * - */ - break; - } - return 0; -} #endif #ifdef CONFIG_PM @@ -1242,9 +1217,7 @@ static int sa1100fb_probe(struct platform_device *pdev) #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = sa1100fb_freq_transition; - fbi->freq_policy.notifier_call = sa1100fb_freq_policy; cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); #endif /* This driver cannot be unloaded at the moment */ diff --git a/drivers/video/fbdev/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h index 7a1a9ca33cec..d0aa33b0b88a 100644 --- a/drivers/video/fbdev/sa1100fb.h +++ b/drivers/video/fbdev/sa1100fb.h @@ -64,7 +64,6 @@ struct sa1100fb_info { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; - struct notifier_block freq_policy; #endif const struct sa1100fb_mach_info *inf; -- GitLab From 8c7d7b4bb172709f71975c2a6e95c9715171603f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 23 Jul 2019 11:44:08 +0530 Subject: [PATCH 4379/7155] video: pxafb: Remove cpufreq policy notifier The cpufreq policy notifier's CPUFREQ_ADJUST notification is going to get removed soon. The notifier callback pxafb_freq_policy() isn't doing anything apart from printing a debug message on CPUFREQ_ADJUST notification. There is no point in keeping an otherwise empty callback and registering the notifier. Remove it. Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/video/fbdev/pxafb.c | 21 --------------------- drivers/video/fbdev/pxafb.h | 1 - 2 files changed, 22 deletions(-) diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 4282cb117b92..f70c9f79622e 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -1678,24 +1678,6 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) } return 0; } - -static int -pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data) -{ - struct pxafb_info *fbi = TO_INF(nb, freq_policy); - struct fb_var_screeninfo *var = &fbi->fb.var; - struct cpufreq_policy *policy = data; - - switch (val) { - case CPUFREQ_ADJUST: - pr_debug("min dma period: %d ps, " - "new clock %d kHz\n", pxafb_display_dma_period(var), - policy->max); - /* TODO: fill in min/max values */ - break; - } - return 0; -} #endif #ifdef CONFIG_PM @@ -2400,11 +2382,8 @@ static int pxafb_probe(struct platform_device *dev) #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = pxafb_freq_transition; - fbi->freq_policy.notifier_call = pxafb_freq_policy; cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - cpufreq_register_notifier(&fbi->freq_policy, - CPUFREQ_POLICY_NOTIFIER); #endif /* diff --git a/drivers/video/fbdev/pxafb.h b/drivers/video/fbdev/pxafb.h index b641289c8a99..86b1e9ab1a38 100644 --- a/drivers/video/fbdev/pxafb.h +++ b/drivers/video/fbdev/pxafb.h @@ -162,7 +162,6 @@ struct pxafb_info { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; - struct notifier_block freq_policy; #endif struct regulator *lcd_supply; -- GitLab From cda4569137b90f200bee4922d894ca49d4188681 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 26 Aug 2019 09:25:35 +0200 Subject: [PATCH 4380/7155] dt-bindings: clk: meson: add sm1 periph clock controller bindings Update the documentation to support clock driver for the Amlogic SM1 SoC and expose the GP1, DSU and the CPU 1, 2 & 3 clocks. SM1 clock tree is very close, the main differences are : - each CPU core can achieve a different frequency, albeit a common PLL - a similar tree as the clock tree has been added for the DynamIQ Shared Unit - has a new GP1 PLL used for the DynamIQ Shared Unit - SM1 has additional clocks like for CSI, NanoQ an other components Signed-off-by: Neil Armstrong Reviewed-by: Kevin Hilman Signed-off-by: Jerome Brunet --- .../devicetree/bindings/clock/amlogic,gxbb-clkc.txt | 1 + include/dt-bindings/clock/g12a-clkc.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt index 6eaa52092313..7ccecd5c02c1 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt @@ -11,6 +11,7 @@ Required Properties: "amlogic,axg-clkc" for AXG SoC. "amlogic,g12a-clkc" for G12A SoC. "amlogic,g12b-clkc" for G12B SoC. + "amlogic,sm1-clkc" for SM1 SoC. - clocks : list of clock phandle, one for each entry clock-names. - clock-names : should contain the following: * "xtal": the platform xtal diff --git a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h index 8ccc29ac7a72..0837c1a7ae49 100644 --- a/include/dt-bindings/clock/g12a-clkc.h +++ b/include/dt-bindings/clock/g12a-clkc.h @@ -138,5 +138,10 @@ #define CLKID_VDEC_HEVCF 210 #define CLKID_TS 212 #define CLKID_CPUB_CLK 224 +#define CLKID_GP1_PLL 243 +#define CLKID_DSU_CLK 252 +#define CLKID_CPU1_CLK 253 +#define CLKID_CPU2_CLK 254 +#define CLKID_CPU3_CLK 255 #endif /* __G12A_CLKC_H */ -- GitLab From a1b840adafcbdc27da2982e7305c342204b8cfd8 Mon Sep 17 00:00:00 2001 From: Ander Juaristi Date: Sat, 17 Aug 2019 13:17:52 +0200 Subject: [PATCH 4381/7155] netfilter: nf_tables: Introduce new 64-bit helper register functions Introduce new helper functions to load/store 64-bit values onto/from registers: - nft_reg_store64 - nft_reg_load64 This commit also re-orders all these helpers from smallest to largest target bit size. Signed-off-by: Ander Juaristi Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 25 ++++++++++++++++++------- net/netfilter/nft_byteorder.c | 9 +++++---- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index e73d16f8b870..64765140657b 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -2,6 +2,7 @@ #ifndef _NET_NF_TABLES_H #define _NET_NF_TABLES_H +#include #include #include #include @@ -102,23 +103,28 @@ struct nft_regs { }; }; -/* Store/load an u16 or u8 integer to/from the u32 data register. +/* Store/load an u8, u16 or u64 integer to/from the u32 data register. * * Note, when using concatenations, register allocation happens at 32-bit * level. So for store instruction, pad the rest part with zero to avoid * garbage values. */ -static inline void nft_reg_store16(u32 *dreg, u16 val) +static inline void nft_reg_store8(u32 *dreg, u8 val) { *dreg = 0; - *(u16 *)dreg = val; + *(u8 *)dreg = val; } -static inline void nft_reg_store8(u32 *dreg, u8 val) +static inline u8 nft_reg_load8(u32 *sreg) +{ + return *(u8 *)sreg; +} + +static inline void nft_reg_store16(u32 *dreg, u16 val) { *dreg = 0; - *(u8 *)dreg = val; + *(u16 *)dreg = val; } static inline u16 nft_reg_load16(u32 *sreg) @@ -126,9 +132,14 @@ static inline u16 nft_reg_load16(u32 *sreg) return *(u16 *)sreg; } -static inline u8 nft_reg_load8(u32 *sreg) +static inline void nft_reg_store64(u32 *dreg, u64 val) { - return *(u8 *)sreg; + put_unaligned(val, (u64 *)dreg); +} + +static inline u64 nft_reg_load64(u32 *sreg) +{ + return get_unaligned((u64 *)sreg); } static inline void nft_data_copy(u32 *dst, const struct nft_data *src, diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index e06318428ea0..12bed3f7bbc6 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c @@ -43,14 +43,15 @@ void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 8; i++) { - src64 = get_unaligned((u64 *)&src[i]); - put_unaligned_be64(src64, &dst[i]); + src64 = nft_reg_load64(&src[i]); + nft_reg_store64(&dst[i], be64_to_cpu(src64)); } break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 8; i++) { - src64 = get_unaligned_be64(&src[i]); - put_unaligned(src64, (u64 *)&dst[i]); + src64 = (__force __u64) + cpu_to_be64(nft_reg_load64(&src[i])); + nft_reg_store64(&dst[i], src64); } break; } -- GitLab From 63d10e12b00dfc8d8387bea9eaab376881335731 Mon Sep 17 00:00:00 2001 From: Ander Juaristi Date: Sat, 17 Aug 2019 13:17:53 +0200 Subject: [PATCH 4382/7155] netfilter: nft_meta: support for time matching This patch introduces meta matches in the kernel for time (a UNIX timestamp), day (a day of week, represented as an integer between 0-6), and hour (an hour in the current day, or: number of seconds since midnight). All values are taken as unsigned 64-bit integers. The 'time' keyword is internally converted to nanoseconds by nft in userspace, and hence the timestamp is taken in nanoseconds as well. Signed-off-by: Ander Juaristi Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nf_tables.h | 6 ++++ net/netfilter/nft_meta.c | 46 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 82abaa183fc3..b83b62eb4b01 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -799,6 +799,9 @@ enum nft_exthdr_attributes { * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind) * @NFT_META_BRI_IIFPVID: packet input bridge port pvid * @NFT_META_BRI_IIFVPROTO: packet input bridge vlan proto + * @NFT_META_TIME_NS: time since epoch (in nanoseconds) + * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday) + * @NFT_META_TIME_HOUR: hour of day (in seconds) */ enum nft_meta_keys { NFT_META_LEN, @@ -831,6 +834,9 @@ enum nft_meta_keys { NFT_META_OIFKIND, NFT_META_BRI_IIFPVID, NFT_META_BRI_IIFVPROTO, + NFT_META_TIME_NS, + NFT_META_TIME_DAY, + NFT_META_TIME_HOUR, }; /** diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index f69afb9ff3cb..317e3a9e8c5b 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -26,8 +26,36 @@ #include /* NF_BR_PRE_ROUTING */ +#define NFT_META_SECS_PER_MINUTE 60 +#define NFT_META_SECS_PER_HOUR 3600 +#define NFT_META_SECS_PER_DAY 86400 +#define NFT_META_DAYS_PER_WEEK 7 + static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state); +static u8 nft_meta_weekday(unsigned long secs) +{ + unsigned int dse; + u8 wday; + + secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest; + dse = secs / NFT_META_SECS_PER_DAY; + wday = (4 + dse) % NFT_META_DAYS_PER_WEEK; + + return wday; +} + +static u32 nft_meta_hour(unsigned long secs) +{ + struct tm tm; + + time64_to_tm(secs, 0, &tm); + + return tm.tm_hour * NFT_META_SECS_PER_HOUR + + tm.tm_min * NFT_META_SECS_PER_MINUTE + + tm.tm_sec; +} + void nft_meta_get_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) @@ -218,6 +246,15 @@ void nft_meta_get_eval(const struct nft_expr *expr, goto err; strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ); break; + case NFT_META_TIME_NS: + nft_reg_store64(dest, ktime_get_real_ns()); + break; + case NFT_META_TIME_DAY: + nft_reg_store8(dest, nft_meta_weekday(get_seconds())); + break; + case NFT_META_TIME_HOUR: + *dest = nft_meta_hour(get_seconds()); + break; default: WARN_ON(1); goto err; @@ -330,6 +367,15 @@ int nft_meta_get_init(const struct nft_ctx *ctx, len = sizeof(u8); break; #endif + case NFT_META_TIME_NS: + len = sizeof(u64); + break; + case NFT_META_TIME_DAY: + len = sizeof(u8); + break; + case NFT_META_TIME_HOUR: + len = sizeof(u32); + break; default: return -EOPNOTSUPP; } -- GitLab From 65af4a10743b766e319fb53812c5926c6d98b100 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Tue, 20 Aug 2019 15:11:46 +0200 Subject: [PATCH 4383/7155] netfilter: nfnetlink_log: add support for VLAN information Currently, there is no vlan information (e.g. when used with a vlan aware bridge) passed to userspache, HWHEADER will contain an 08 00 (ip) suffix even for tagged ip packets. Therefore, add an extra netlink attribute that passes the vlan information to userspace similarly to 15824ab29f for nfqueue. Signed-off-by: Michael Braun Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nfnetlink_log.h | 11 ++++ net/netfilter/nfnetlink_log.c | 57 ++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/uapi/linux/netfilter/nfnetlink_log.h b/include/uapi/linux/netfilter/nfnetlink_log.h index 20983cb195a0..45c8d3b027e0 100644 --- a/include/uapi/linux/netfilter/nfnetlink_log.h +++ b/include/uapi/linux/netfilter/nfnetlink_log.h @@ -33,6 +33,15 @@ struct nfulnl_msg_packet_timestamp { __aligned_be64 usec; }; +enum nfulnl_vlan_attr { + NFULA_VLAN_UNSPEC, + NFULA_VLAN_PROTO, /* __be16 skb vlan_proto */ + NFULA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ + __NFULA_VLAN_MAX, +}; + +#define NFULA_VLAN_MAX (__NFULA_VLAN_MAX + 1) + enum nfulnl_attr_type { NFULA_UNSPEC, NFULA_PACKET_HDR, @@ -54,6 +63,8 @@ enum nfulnl_attr_type { NFULA_HWLEN, /* hardware header length */ NFULA_CT, /* nf_conntrack_netlink.h */ NFULA_CT_INFO, /* enum ip_conntrack_info */ + NFULA_VLAN, /* nested attribute: packet vlan info */ + NFULA_L2HDR, /* full L2 header */ __NFULA_MAX }; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d69e1863e536..0ba020ca38e6 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -385,6 +385,57 @@ nfulnl_timer(struct timer_list *t) instance_put(inst); } +static u32 nfulnl_get_bridge_size(const struct sk_buff *skb) +{ + u32 size = 0; + + if (!skb_mac_header_was_set(skb)) + return 0; + + if (skb_vlan_tag_present(skb)) { + size += nla_total_size(0); /* nested */ + size += nla_total_size(sizeof(u16)); /* id */ + size += nla_total_size(sizeof(u16)); /* tag */ + } + + if (skb->network_header > skb->mac_header) + size += nla_total_size(skb->network_header - skb->mac_header); + + return size; +} + +static int nfulnl_put_bridge(struct nfulnl_instance *inst, const struct sk_buff *skb) +{ + if (!skb_mac_header_was_set(skb)) + return 0; + + if (skb_vlan_tag_present(skb)) { + struct nlattr *nest; + + nest = nla_nest_start(inst->skb, NFULA_VLAN); + if (!nest) + goto nla_put_failure; + + if (nla_put_be16(inst->skb, NFULA_VLAN_TCI, htons(skb->vlan_tci)) || + nla_put_be16(inst->skb, NFULA_VLAN_PROTO, skb->vlan_proto)) + goto nla_put_failure; + + nla_nest_end(inst->skb, nest); + } + + if (skb->mac_header < skb->network_header) { + int len = (int)(skb->network_header - skb->mac_header); + + if (nla_put(inst->skb, NFULA_L2HDR, len, skb_mac_header(skb))) + goto nla_put_failure; + } + + return 0; + +nla_put_failure: + return -1; +} + /* This is an inline function, we don't really care about a long * list of arguments */ static inline int @@ -580,6 +631,10 @@ __build_packet_message(struct nfnl_log_net *log, NFULA_CT, NFULA_CT_INFO) < 0) goto nla_put_failure; + if ((pf == NFPROTO_NETDEV || pf == NFPROTO_BRIDGE) && + nfulnl_put_bridge(inst, skb) < 0) + goto nla_put_failure; + if (data_len) { struct nlattr *nla; int size = nla_attr_size(data_len); @@ -687,6 +742,8 @@ nfulnl_log_packet(struct net *net, size += nfnl_ct->build_size(ct); } } + if (pf == NFPROTO_NETDEV || pf == NFPROTO_BRIDGE) + size += nfulnl_get_bridge_size(skb); qthreshold = inst->qthreshold; /* per-rule qthreshold overrides per-instance */ -- GitLab From ce19f91eae43e39d5a1da55344756ab5a3c7e8d1 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 11 Jun 2019 19:31:26 +0300 Subject: [PATCH 4384/7155] thunderbolt: Correct path indices for PCIe tunnel PCIe tunnel path indices got mixed up when we added support for tunnels between switches that are not adjacent. This did not affect the functionality as it is just an index but fix it now nevertheless to make the code easier to understand. Reported-by: Rajmohan Mani Fixes: 8c7acaaf020f ("thunderbolt: Extend tunnel creation to more than 2 adjacent switches") Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat --- drivers/thunderbolt/tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 31d0234837e4..5a99234826e7 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -211,7 +211,7 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up, return NULL; } tb_pci_init_path(path); - tunnel->paths[TB_PCI_PATH_UP] = path; + tunnel->paths[TB_PCI_PATH_DOWN] = path; path = tb_path_alloc(tb, up, TB_PCI_HOPID, down, TB_PCI_HOPID, 0, "PCIe Up"); @@ -220,7 +220,7 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up, return NULL; } tb_pci_init_path(path); - tunnel->paths[TB_PCI_PATH_DOWN] = path; + tunnel->paths[TB_PCI_PATH_UP] = path; return tunnel; } -- GitLab From f437c24bf694b0293f835dea8c25e3a5c1433d07 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 16 Jan 2018 22:30:40 +0200 Subject: [PATCH 4385/7155] thunderbolt: Move NVM upgrade support flag to struct icm This is depends on the controller and on the platform/CPU we are running. Move it to struct icm so we can set it per controller. Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/icm.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index fbdcef56a676..e9835ab35465 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -55,6 +55,7 @@ * @safe_mode: ICM is in safe mode * @max_boot_acl: Maximum number of preboot ACL entries (%0 if not supported) * @rpm: Does the controller support runtime PM (RTD3) + * @can_upgrade_nvm: Can the NVM firmware be upgrade on this controller * @is_supported: Checks if we can support ICM on this controller * @cio_reset: Trigger CIO reset * @get_mode: Read and return the ICM firmware mode (optional) @@ -74,6 +75,7 @@ struct icm { int vnd_cap; bool safe_mode; bool rpm; + bool can_upgrade_nvm; bool (*is_supported)(struct tb *tb); int (*cio_reset)(struct tb *tb); int (*get_mode)(struct tb *tb); @@ -1913,12 +1915,7 @@ static int icm_start(struct tb *tb) if (IS_ERR(tb->root_switch)) return PTR_ERR(tb->root_switch); - /* - * NVM upgrade has not been tested on Apple systems and they - * don't provide images publicly either. To be on the safe side - * prevent root switch NVM upgrade on Macs for now. - */ - tb->root_switch->no_nvm_upgrade = x86_apple_machine; + tb->root_switch->no_nvm_upgrade = !icm->can_upgrade_nvm; tb->root_switch->rpm = icm->rpm; ret = tb_switch_add(tb->root_switch); @@ -2021,6 +2018,7 @@ struct tb *icm_probe(struct tb_nhi *nhi) switch (nhi->pdev->device) { case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: + icm->can_upgrade_nvm = true; icm->is_supported = icm_fr_is_supported; icm->get_route = icm_fr_get_route; icm->save_devices = icm_fr_save_devices; @@ -2038,6 +2036,13 @@ struct tb *icm_probe(struct tb_nhi *nhi) case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_NHI: case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI: icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES; + /* + * NVM upgrade has not been tested on Apple systems and + * they don't provide images publicly either. To be on + * the safe side prevent root switch NVM upgrade on Macs + * for now. + */ + icm->can_upgrade_nvm = !x86_apple_machine; icm->is_supported = icm_ar_is_supported; icm->cio_reset = icm_ar_cio_reset; icm->get_mode = icm_ar_get_mode; @@ -2054,6 +2059,7 @@ struct tb *icm_probe(struct tb_nhi *nhi) case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI: case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI: icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES; + icm->can_upgrade_nvm = !x86_apple_machine; icm->is_supported = icm_ar_is_supported; icm->cio_reset = icm_tr_cio_reset; icm->get_mode = icm_ar_get_mode; -- GitLab From 943795219d3cb9f8ce6ce51cad3ffe1f61e95c6b Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 4 Jul 2018 08:46:07 +0300 Subject: [PATCH 4386/7155] thunderbolt: Use 32-bit writes when writing ring producer/consumer The register access should be using 32-bit reads/writes according to the datasheet. With the previous generation hardware 16-bit writes have been working but starting with ICL this is not the case anymore so fix producer/consumer register update to use correct width register address. Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/nhi.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 27fbe62c7ddd..9c782706e652 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -143,9 +143,20 @@ static void __iomem *ring_options_base(struct tb_ring *ring) return io; } -static void ring_iowrite16desc(struct tb_ring *ring, u32 value, u32 offset) +static void ring_iowrite_cons(struct tb_ring *ring, u16 cons) { - iowrite16(value, ring_desc_base(ring) + offset); + /* + * The other 16-bits in the register is read-only and writes to it + * are ignored by the hardware so we can save one ioread32() by + * filling the read-only bits with zeroes. + */ + iowrite32(cons, ring_desc_base(ring) + 8); +} + +static void ring_iowrite_prod(struct tb_ring *ring, u16 prod) +{ + /* See ring_iowrite_cons() above for explanation */ + iowrite32(prod << 16, ring_desc_base(ring) + 8); } static void ring_iowrite32desc(struct tb_ring *ring, u32 value, u32 offset) @@ -197,7 +208,10 @@ static void ring_write_descriptors(struct tb_ring *ring) descriptor->sof = frame->sof; } ring->head = (ring->head + 1) % ring->size; - ring_iowrite16desc(ring, ring->head, ring->is_tx ? 10 : 8); + if (ring->is_tx) + ring_iowrite_prod(ring, ring->head); + else + ring_iowrite_cons(ring, ring->head); } } @@ -662,7 +676,7 @@ void tb_ring_stop(struct tb_ring *ring) ring_iowrite32options(ring, 0, 0); ring_iowrite64desc(ring, 0, 0); - ring_iowrite16desc(ring, 0, ring->is_tx ? 10 : 8); + ring_iowrite32desc(ring, 0, 8); ring_iowrite32desc(ring, 0, 12); ring->head = 0; ring->tail = 0; -- GitLab From d94dcbb10183f3b384c84e65724d2b753aa53c4d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 4 Jul 2018 08:50:01 +0300 Subject: [PATCH 4387/7155] thunderbolt: Do not fail adding switch if some port is not implemented There are two ways to mark a port as unimplemented. Typical way is to return port type as TB_TYPE_INACTIVE when its config space is read. Alternatively if the port is not physically present (such as ports 10 and 11 in ICL) reading from port config space returns TB_CFG_ERROR_INVALID_CONFIG_SPACE instead. Currently the driver bails out from adding the switch if it receives any error during port inititialization which is wrong. Handle this properly and just leave the port as TB_TYPE_INACTIVE before continuing to the next port. This also allows us to get rid of special casing for Light Ridge port 5 in eeprom.c. Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/ctl.c | 23 +++++++++++++++++++---- drivers/thunderbolt/eeprom.c | 4 ---- drivers/thunderbolt/switch.c | 8 +++++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c index 2427d73be731..2ec1af8f7968 100644 --- a/drivers/thunderbolt/ctl.c +++ b/drivers/thunderbolt/ctl.c @@ -930,6 +930,23 @@ struct tb_cfg_result tb_cfg_write_raw(struct tb_ctl *ctl, const void *buffer, return res; } +static int tb_cfg_get_error(struct tb_ctl *ctl, enum tb_cfg_space space, + const struct tb_cfg_result *res) +{ + /* + * For unimplemented ports access to port config space may return + * TB_CFG_ERROR_INVALID_CONFIG_SPACE (alternatively their type is + * set to TB_TYPE_INACTIVE). In the former case return -ENODEV so + * that the caller can mark the port as disabled. + */ + if (space == TB_CFG_PORT && + res->tb_error == TB_CFG_ERROR_INVALID_CONFIG_SPACE) + return -ENODEV; + + tb_cfg_print_error(ctl, res); + return -EIO; +} + int tb_cfg_read(struct tb_ctl *ctl, void *buffer, u64 route, u32 port, enum tb_cfg_space space, u32 offset, u32 length) { @@ -942,8 +959,7 @@ int tb_cfg_read(struct tb_ctl *ctl, void *buffer, u64 route, u32 port, case 1: /* Thunderbolt error, tb_error holds the actual number */ - tb_cfg_print_error(ctl, &res); - return -EIO; + return tb_cfg_get_error(ctl, space, &res); case -ETIMEDOUT: tb_ctl_warn(ctl, "timeout reading config space %u from %#x\n", @@ -969,8 +985,7 @@ int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port, case 1: /* Thunderbolt error, tb_error holds the actual number */ - tb_cfg_print_error(ctl, &res); - return -EIO; + return tb_cfg_get_error(ctl, space, &res); case -ETIMEDOUT: tb_ctl_warn(ctl, "timeout writing config space %u to %#x\n", diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 2366406e49ac..ee5196479854 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -525,10 +525,6 @@ int tb_drom_read(struct tb_switch *sw) sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].dual_link_port = &sw->ports[3]; - /* Port 5 is inaccessible on this gen 1 controller */ - if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE) - sw->ports[5].disabled = true; - return 0; } diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 5668a44e0653..64f845fe4690 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -611,8 +611,14 @@ static int tb_init_port(struct tb_port *port) int cap; res = tb_port_read(port, &port->config, TB_CFG_PORT, 0, 8); - if (res) + if (res) { + if (res == -ENODEV) { + tb_dbg(port->sw->tb, " Port %d: not implemented\n", + port->port); + return 0; + } return res; + } /* Port 0 is the switch itself and has no PHY. */ if (port->config.type == TB_TYPE_PORT && port->port != 0) { -- GitLab From 58f414fa435cf728a82f435bac4781da86afb623 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 11 Sep 2018 15:34:23 +0300 Subject: [PATCH 4388/7155] thunderbolt: Hide switch attributes that are not set Thunderbolt host routers may not always contain DROM that includes device identification information. This is mostly needed for Ice Lake systems but some Falcon Ridge controllers on PCs also do not have DROM. In that case hide the identification attributes. Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/switch.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 64f845fe4690..bd3eaaf34ea1 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1337,7 +1337,19 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, struct device *dev = container_of(kobj, struct device, kobj); struct tb_switch *sw = tb_to_switch(dev); - if (attr == &dev_attr_key.attr) { + if (attr == &dev_attr_device.attr) { + if (!sw->device) + return 0; + } else if (attr == &dev_attr_device_name.attr) { + if (!sw->device_name) + return 0; + } else if (attr == &dev_attr_vendor.attr) { + if (!sw->vendor) + return 0; + } else if (attr == &dev_attr_vendor_name.attr) { + if (!sw->vendor_name) + return 0; + } else if (attr == &dev_attr_key.attr) { if (tb_route(sw) && sw->tb->security_level == TB_SECURITY_SECURE && sw->security_level == TB_SECURITY_SECURE) -- GitLab From 3f415e5ee18b0097755afc3ac3a5640b196a239e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 5 Feb 2019 12:51:40 +0300 Subject: [PATCH 4389/7155] thunderbolt: Expose active parts of NVM even if upgrade is not supported Ice Lake Thunderbolt controller NVM firmware is part of the BIOS image which means it is not writable through the DMA port anymore. However, we can still read it so we can keep nvm_version and active parts of NVM. This way users still can find out the active NVM version and other potentially useful information directly from Linux. Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/switch.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index bd3eaaf34ea1..531f11fecf75 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -364,12 +364,14 @@ static int tb_switch_nvm_add(struct tb_switch *sw) nvm->active = nvm_dev; } - nvm_dev = register_nvmem(sw, nvm->id, NVM_MAX_SIZE, false); - if (IS_ERR(nvm_dev)) { - ret = PTR_ERR(nvm_dev); - goto err_nvm_active; + if (!sw->no_nvm_upgrade) { + nvm_dev = register_nvmem(sw, nvm->id, NVM_MAX_SIZE, false); + if (IS_ERR(nvm_dev)) { + ret = PTR_ERR(nvm_dev); + goto err_nvm_active; + } + nvm->non_active = nvm_dev; } - nvm->non_active = nvm_dev; sw->nvm = nvm; return 0; @@ -398,7 +400,8 @@ static void tb_switch_nvm_remove(struct tb_switch *sw) if (!nvm->authenticating) nvm_clear_auth_status(sw); - nvmem_unregister(nvm->non_active); + if (nvm->non_active) + nvmem_unregister(nvm->non_active); if (nvm->active) nvmem_unregister(nvm->active); ida_simple_remove(&nvm_ida, nvm->id); @@ -1355,8 +1358,11 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, sw->security_level == TB_SECURITY_SECURE) return attr->mode; return 0; - } else if (attr == &dev_attr_nvm_authenticate.attr || - attr == &dev_attr_nvm_version.attr) { + } else if (attr == &dev_attr_nvm_authenticate.attr) { + if (sw->dma_port && !sw->no_nvm_upgrade) + return attr->mode; + return 0; + } else if (attr == &dev_attr_nvm_version.attr) { if (sw->dma_port) return attr->mode; return 0; @@ -1707,13 +1713,17 @@ static int tb_switch_add_dma_port(struct tb_switch *sw) break; } - if (sw->no_nvm_upgrade) + /* Root switch DMA port requires running firmware */ + if (!tb_route(sw) && sw->config.enabled) return 0; sw->dma_port = dma_port_alloc(sw); if (!sw->dma_port) return 0; + if (sw->no_nvm_upgrade) + return 0; + /* * Check status of the previous flash authentication. If there * is one we need to power cycle the switch in any case to make -- GitLab From 3cdb9446a117d5d63af823bde6fe6babc312e77b Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 16 Jan 2018 22:19:00 +0200 Subject: [PATCH 4390/7155] thunderbolt: Add support for Intel Ice Lake The Thunderbolt controller is integrated into the Ice Lake CPU itself and requires special flows to power it on and off using force power bit in NHI VSEC registers. Runtime PM (RTD3) and Sx flows also differ from the discrete solutions. Now the firmware notifies the driver whether RTD3 entry or exit are possible. The driver is responsible of sending Go2Sx command through link controller mailbox when system enters Sx states (suspend-to-mem/disk). Rest of the ICM firwmare flows follow Titan Ridge. Signed-off-by: Raanan Avargil Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Tested-by: Mario Limonciello --- drivers/thunderbolt/Makefile | 2 +- drivers/thunderbolt/icm.c | 176 ++++++++++++++++++++++++++++++-- drivers/thunderbolt/nhi.c | 112 +++++++++++++++++++-- drivers/thunderbolt/nhi.h | 22 ++++ drivers/thunderbolt/nhi_ops.c | 179 +++++++++++++++++++++++++++++++++ drivers/thunderbolt/nhi_regs.h | 37 +++++++ drivers/thunderbolt/switch.c | 2 + drivers/thunderbolt/tb_msgs.h | 16 ++- include/linux/thunderbolt.h | 2 + 9 files changed, 526 insertions(+), 22 deletions(-) create mode 100644 drivers/thunderbolt/nhi_ops.c diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 3f55cb3c81b2..001187c577bf 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-${CONFIG_THUNDERBOLT} := thunderbolt.o -thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o +thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index e9835ab35465..245588f691e7 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -56,16 +56,19 @@ * @max_boot_acl: Maximum number of preboot ACL entries (%0 if not supported) * @rpm: Does the controller support runtime PM (RTD3) * @can_upgrade_nvm: Can the NVM firmware be upgrade on this controller + * @veto: Is RTD3 veto in effect * @is_supported: Checks if we can support ICM on this controller * @cio_reset: Trigger CIO reset * @get_mode: Read and return the ICM firmware mode (optional) * @get_route: Find a route string for given switch * @save_devices: Ask ICM to save devices to ACL when suspending (optional) * @driver_ready: Send driver ready message to ICM + * @set_uuid: Set UUID for the root switch (optional) * @device_connected: Handle device connected ICM message * @device_disconnected: Handle device disconnected ICM message * @xdomain_connected - Handle XDomain connected ICM message * @xdomain_disconnected - Handle XDomain disconnected ICM message + * @rtd3_veto: Handle RTD3 veto notification ICM message */ struct icm { struct mutex request_lock; @@ -76,6 +79,7 @@ struct icm { bool safe_mode; bool rpm; bool can_upgrade_nvm; + bool veto; bool (*is_supported)(struct tb *tb); int (*cio_reset)(struct tb *tb); int (*get_mode)(struct tb *tb); @@ -84,6 +88,7 @@ struct icm { int (*driver_ready)(struct tb *tb, enum tb_security_level *security_level, size_t *nboot_acl, bool *rpm); + void (*set_uuid)(struct tb *tb); void (*device_connected)(struct tb *tb, const struct icm_pkg_header *hdr); void (*device_disconnected)(struct tb *tb, @@ -92,6 +97,7 @@ struct icm { const struct icm_pkg_header *hdr); void (*xdomain_disconnected)(struct tb *tb, const struct icm_pkg_header *hdr); + void (*rtd3_veto)(struct tb *tb, const struct icm_pkg_header *hdr); }; struct icm_notification { @@ -296,6 +302,43 @@ static int icm_request(struct tb *tb, const void *request, size_t request_size, return -ETIMEDOUT; } +/* + * If rescan is queued to run (we are resuming), postpone it to give the + * firmware some more time to send device connected notifications for next + * devices in the chain. + */ +static void icm_postpone_rescan(struct tb *tb) +{ + struct icm *icm = tb_priv(tb); + + if (delayed_work_pending(&icm->rescan_work)) + mod_delayed_work(tb->wq, &icm->rescan_work, + msecs_to_jiffies(500)); +} + +static void icm_veto_begin(struct tb *tb) +{ + struct icm *icm = tb_priv(tb); + + if (!icm->veto) { + icm->veto = true; + /* Keep the domain powered while veto is in effect */ + pm_runtime_get(&tb->dev); + } +} + +static void icm_veto_end(struct tb *tb) +{ + struct icm *icm = tb_priv(tb); + + if (icm->veto) { + icm->veto = false; + /* Allow the domain suspend now */ + pm_runtime_mark_last_busy(&tb->dev); + pm_runtime_put_autosuspend(&tb->dev); + } +} + static bool icm_fr_is_supported(struct tb *tb) { return !x86_apple_machine; @@ -519,14 +562,16 @@ static int icm_fr_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) return 0; } -static void add_switch(struct tb_switch *parent_sw, u64 route, - const uuid_t *uuid, const u8 *ep_name, - size_t ep_name_size, u8 connection_id, u8 connection_key, - u8 link, u8 depth, enum tb_security_level security_level, - bool authorized, bool boot) +static struct tb_switch *add_switch(struct tb_switch *parent_sw, u64 route, + const uuid_t *uuid, const u8 *ep_name, + size_t ep_name_size, u8 connection_id, + u8 connection_key, u8 link, u8 depth, + enum tb_security_level security_level, + bool authorized, bool boot) { const struct intel_vss *vss; struct tb_switch *sw; + int ret; pm_runtime_get_sync(&parent_sw->dev); @@ -557,14 +602,18 @@ static void add_switch(struct tb_switch *parent_sw, u64 route, tb_port_at(route, parent_sw)->remote = tb_upstream_port(sw); tb_upstream_port(sw)->remote = tb_port_at(route, parent_sw); - if (tb_switch_add(sw)) { + ret = tb_switch_add(sw); + if (ret) { tb_port_at(tb_route(sw), parent_sw)->remote = NULL; tb_switch_put(sw); + sw = ERR_PTR(ret); } out: pm_runtime_mark_last_busy(&parent_sw->dev); pm_runtime_put_autosuspend(&parent_sw->dev); + + return sw; } static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, @@ -656,6 +705,8 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) u64 route; int ret; + icm_postpone_rescan(tb); + link = pkg->link_info & ICM_LINK_INFO_LINK_MASK; depth = (pkg->link_info & ICM_LINK_INFO_DEPTH_MASK) >> ICM_LINK_INFO_DEPTH_SHIFT; @@ -1086,7 +1137,8 @@ static int icm_tr_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) } static void -icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) +__icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr, + bool force_rtd3) { const struct icm_tr_event_device_connected *pkg = (const struct icm_tr_event_device_connected *)hdr; @@ -1096,6 +1148,8 @@ icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) bool authorized, boot; u64 route; + icm_postpone_rescan(tb); + /* * Currently we don't use the QoS information coming with the * device connected message so simply just ignore that extra @@ -1151,13 +1205,21 @@ icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) return; } - add_switch(parent_sw, route, &pkg->ep_uuid, (const u8 *)pkg->ep_name, - sizeof(pkg->ep_name), pkg->connection_id, - 0, 0, 0, security_level, authorized, boot); + sw = add_switch(parent_sw, route, &pkg->ep_uuid, (const u8 *)pkg->ep_name, + sizeof(pkg->ep_name), pkg->connection_id, 0, 0, 0, + security_level, authorized, boot); + if (!IS_ERR(sw) && force_rtd3) + sw->rpm = true; tb_switch_put(parent_sw); } +static void +icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) +{ + __icm_tr_device_connected(tb, hdr, false); +} + static void icm_tr_device_disconnected(struct tb *tb, const struct icm_pkg_header *hdr) { @@ -1468,6 +1530,61 @@ static int icm_ar_set_boot_acl(struct tb *tb, const uuid_t *uuids, return 0; } +static int +icm_icl_driver_ready(struct tb *tb, enum tb_security_level *security_level, + size_t *nboot_acl, bool *rpm) +{ + struct icm_tr_pkg_driver_ready_response reply; + struct icm_pkg_driver_ready request = { + .hdr.code = ICM_DRIVER_READY, + }; + int ret; + + memset(&reply, 0, sizeof(reply)); + ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), + 1, 20000); + if (ret) + return ret; + + /* Ice Lake always supports RTD3 */ + if (rpm) + *rpm = true; + + return 0; +} + +static void icm_icl_set_uuid(struct tb *tb) +{ + struct tb_nhi *nhi = tb->nhi; + u32 uuid[4]; + + pci_read_config_dword(nhi->pdev, VS_CAP_10, &uuid[0]); + pci_read_config_dword(nhi->pdev, VS_CAP_11, &uuid[1]); + uuid[2] = 0xffffffff; + uuid[3] = 0xffffffff; + + tb->root_switch->uuid = kmemdup(uuid, sizeof(uuid), GFP_KERNEL); +} + +static void +icm_icl_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) +{ + __icm_tr_device_connected(tb, hdr, true); +} + +static void icm_icl_rtd3_veto(struct tb *tb, const struct icm_pkg_header *hdr) +{ + const struct icm_icl_event_rtd3_veto *pkg = + (const struct icm_icl_event_rtd3_veto *)hdr; + + tb_dbg(tb, "ICM rtd3 veto=0x%08x\n", pkg->veto_reason); + + if (pkg->veto_reason) + icm_veto_begin(tb); + else + icm_veto_end(tb); +} + static void icm_handle_notification(struct work_struct *work) { struct icm_notification *n = container_of(work, typeof(*n), work); @@ -1495,6 +1612,9 @@ static void icm_handle_notification(struct work_struct *work) case ICM_EVENT_XDOMAIN_DISCONNECTED: icm->xdomain_disconnected(tb, n->pkg); break; + case ICM_EVENT_RTD3_VETO: + icm->rtd3_veto(tb, n->pkg); + break; } } @@ -1853,6 +1973,13 @@ static void icm_complete(struct tb *tb) if (tb->nhi->going_away) return; + /* + * If RTD3 was vetoed before we entered system suspend allow it + * again now before driver ready is sent. Firmware sends a new RTD3 + * veto if it is still the case after we have sent it driver ready + * command. + */ + icm_veto_end(tb); icm_unplug_children(tb->root_switch); /* @@ -1918,6 +2045,9 @@ static int icm_start(struct tb *tb) tb->root_switch->no_nvm_upgrade = !icm->can_upgrade_nvm; tb->root_switch->rpm = icm->rpm; + if (icm->set_uuid) + icm->set_uuid(tb); + ret = tb_switch_add(tb->root_switch); if (ret) { tb_switch_put(tb->root_switch); @@ -2002,6 +2132,19 @@ static const struct tb_cm_ops icm_tr_ops = { .disconnect_xdomain_paths = icm_tr_disconnect_xdomain_paths, }; +/* Ice Lake */ +static const struct tb_cm_ops icm_icl_ops = { + .driver_ready = icm_driver_ready, + .start = icm_start, + .stop = icm_stop, + .complete = icm_complete, + .runtime_suspend = icm_runtime_suspend, + .runtime_resume = icm_runtime_resume, + .handle_event = icm_handle_event, + .approve_xdomain_paths = icm_tr_approve_xdomain_paths, + .disconnect_xdomain_paths = icm_tr_disconnect_xdomain_paths, +}; + struct tb *icm_probe(struct tb_nhi *nhi) { struct icm *icm; @@ -2070,6 +2213,19 @@ struct tb *icm_probe(struct tb_nhi *nhi) icm->xdomain_disconnected = icm_tr_xdomain_disconnected; tb->cm_ops = &icm_tr_ops; break; + + case PCI_DEVICE_ID_INTEL_ICL_NHI0: + case PCI_DEVICE_ID_INTEL_ICL_NHI1: + icm->is_supported = icm_ar_is_supported; + icm->driver_ready = icm_icl_driver_ready; + icm->set_uuid = icm_icl_set_uuid; + icm->device_connected = icm_icl_device_connected; + icm->device_disconnected = icm_tr_device_disconnected; + icm->xdomain_connected = icm_tr_xdomain_connected; + icm->xdomain_disconnected = icm_tr_xdomain_disconnected; + icm->rtd3_veto = icm_icl_rtd3_veto; + tb->cm_ops = &icm_icl_ops; + break; } if (!icm->is_supported || !icm->is_supported(tb)) { diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 9c782706e652..641b21b54460 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "nhi.h" #include "nhi_regs.h" @@ -859,12 +860,52 @@ static irqreturn_t nhi_msi(int irq, void *data) return IRQ_HANDLED; } -static int nhi_suspend_noirq(struct device *dev) +static int __nhi_suspend_noirq(struct device *dev, bool wakeup) { struct pci_dev *pdev = to_pci_dev(dev); struct tb *tb = pci_get_drvdata(pdev); + struct tb_nhi *nhi = tb->nhi; + int ret; + + ret = tb_domain_suspend_noirq(tb); + if (ret) + return ret; + + if (nhi->ops && nhi->ops->suspend_noirq) { + ret = nhi->ops->suspend_noirq(tb->nhi, wakeup); + if (ret) + return ret; + } + + return 0; +} + +static int nhi_suspend_noirq(struct device *dev) +{ + return __nhi_suspend_noirq(dev, device_may_wakeup(dev)); +} + +static bool nhi_wake_supported(struct pci_dev *pdev) +{ + u8 val; + + /* + * If power rails are sustainable for wakeup from S4 this + * property is set by the BIOS. + */ + if (device_property_read_u8(&pdev->dev, "WAKE_SUPPORTED", &val)) + return !!val; + + return true; +} + +static int nhi_poweroff_noirq(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + bool wakeup; - return tb_domain_suspend_noirq(tb); + wakeup = device_may_wakeup(dev) && nhi_wake_supported(pdev); + return __nhi_suspend_noirq(dev, wakeup); } static void nhi_enable_int_throttling(struct tb_nhi *nhi) @@ -887,16 +928,24 @@ static int nhi_resume_noirq(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct tb *tb = pci_get_drvdata(pdev); + struct tb_nhi *nhi = tb->nhi; + int ret; /* * Check that the device is still there. It may be that the user * unplugged last device which causes the host controller to go * away on PCs. */ - if (!pci_device_is_present(pdev)) - tb->nhi->going_away = true; - else + if (!pci_device_is_present(pdev)) { + nhi->going_away = true; + } else { + if (nhi->ops && nhi->ops->resume_noirq) { + ret = nhi->ops->resume_noirq(nhi); + if (ret) + return ret; + } nhi_enable_int_throttling(tb->nhi); + } return tb_domain_resume_noirq(tb); } @@ -929,16 +978,35 @@ static int nhi_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct tb *tb = pci_get_drvdata(pdev); + struct tb_nhi *nhi = tb->nhi; + int ret; + + ret = tb_domain_runtime_suspend(tb); + if (ret) + return ret; - return tb_domain_runtime_suspend(tb); + if (nhi->ops && nhi->ops->runtime_suspend) { + ret = nhi->ops->runtime_suspend(tb->nhi); + if (ret) + return ret; + } + return 0; } static int nhi_runtime_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct tb *tb = pci_get_drvdata(pdev); + struct tb_nhi *nhi = tb->nhi; + int ret; + + if (nhi->ops && nhi->ops->runtime_resume) { + ret = nhi->ops->runtime_resume(nhi); + if (ret) + return ret; + } - nhi_enable_int_throttling(tb->nhi); + nhi_enable_int_throttling(nhi); return tb_domain_runtime_resume(tb); } @@ -966,6 +1034,9 @@ static void nhi_shutdown(struct tb_nhi *nhi) flush_work(&nhi->interrupt_work); } ida_destroy(&nhi->msix_ida); + + if (nhi->ops && nhi->ops->shutdown) + nhi->ops->shutdown(nhi); } static int nhi_init_msi(struct tb_nhi *nhi) @@ -1010,12 +1081,27 @@ static int nhi_init_msi(struct tb_nhi *nhi) return 0; } +static bool nhi_imr_valid(struct pci_dev *pdev) +{ + u8 val; + + if (!device_property_read_u8(&pdev->dev, "IMR_VALID", &val)) + return !!val; + + return true; +} + static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tb_nhi *nhi; struct tb *tb; int res; + if (!nhi_imr_valid(pdev)) { + dev_warn(&pdev->dev, "firmware image not valid, aborting\n"); + return -ENODEV; + } + res = pcim_enable_device(pdev); if (res) { dev_err(&pdev->dev, "cannot enable PCI device, aborting\n"); @@ -1033,6 +1119,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; nhi->pdev = pdev; + nhi->ops = (const struct tb_nhi_ops *)id->driver_data; /* cannot fail - table is allocated bin pcim_iomap_regions */ nhi->iobase = pcim_iomap_table(pdev)[0]; nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff; @@ -1065,6 +1152,12 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); + if (nhi->ops && nhi->ops->init) { + res = nhi->ops->init(nhi); + if (res) + return res; + } + tb = icm_probe(nhi); if (!tb) tb = tb_probe(nhi); @@ -1125,6 +1218,7 @@ static const struct dev_pm_ops nhi_pm_ops = { .restore_noirq = nhi_resume_noirq, .suspend = nhi_suspend, .freeze = nhi_suspend, + .poweroff_noirq = nhi_poweroff_noirq, .poweroff = nhi_suspend, .complete = nhi_complete, .runtime_suspend = nhi_runtime_suspend, @@ -1172,6 +1266,10 @@ static struct pci_device_id nhi_ids[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_USBONLY_NHI) }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_NHI) }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICL_NHI0), + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICL_NHI1), + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, { 0,} }; diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h index 1b5d47ecd3ed..b7b973949f8e 100644 --- a/drivers/thunderbolt/nhi.h +++ b/drivers/thunderbolt/nhi.h @@ -30,6 +30,26 @@ enum nhi_mailbox_cmd { int nhi_mailbox_cmd(struct tb_nhi *nhi, enum nhi_mailbox_cmd cmd, u32 data); enum nhi_fw_mode nhi_mailbox_mode(struct tb_nhi *nhi); +/** + * struct tb_nhi_ops - NHI specific optional operations + * @init: NHI specific initialization + * @suspend_noirq: NHI specific suspend_noirq hook + * @resume_noirq: NHI specific resume_noirq hook + * @runtime_suspend: NHI specific runtime_suspend hook + * @runtime_resume: NHI specific runtime_resume hook + * @shutdown: NHI specific shutdown + */ +struct tb_nhi_ops { + int (*init)(struct tb_nhi *nhi); + int (*suspend_noirq)(struct tb_nhi *nhi, bool wakeup); + int (*resume_noirq)(struct tb_nhi *nhi); + int (*runtime_suspend)(struct tb_nhi *nhi); + int (*runtime_resume)(struct tb_nhi *nhi); + void (*shutdown)(struct tb_nhi *nhi); +}; + +extern const struct tb_nhi_ops icl_nhi_ops; + /* * PCI IDs used in this driver from Win Ridge forward. There is no * need for the PCI quirk anymore as we will use ICM also on Apple @@ -51,5 +71,7 @@ enum nhi_fw_mode nhi_mailbox_mode(struct tb_nhi *nhi); #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE 0x15ea #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI 0x15eb #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef +#define PCI_DEVICE_ID_INTEL_ICL_NHI1 0x8a0d +#define PCI_DEVICE_ID_INTEL_ICL_NHI0 0x8a17 #endif diff --git a/drivers/thunderbolt/nhi_ops.c b/drivers/thunderbolt/nhi_ops.c new file mode 100644 index 000000000000..61cd09cef943 --- /dev/null +++ b/drivers/thunderbolt/nhi_ops.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NHI specific operations + * + * Copyright (C) 2019, Intel Corporation + * Author: Mika Westerberg + */ + +#include +#include + +#include "nhi.h" +#include "nhi_regs.h" +#include "tb.h" + +/* Ice Lake specific NHI operations */ + +#define ICL_LC_MAILBOX_TIMEOUT 500 /* ms */ + +static int check_for_device(struct device *dev, void *data) +{ + return tb_is_switch(dev); +} + +static bool icl_nhi_is_device_connected(struct tb_nhi *nhi) +{ + struct tb *tb = pci_get_drvdata(nhi->pdev); + int ret; + + ret = device_for_each_child(&tb->root_switch->dev, NULL, + check_for_device); + return ret > 0; +} + +static int icl_nhi_force_power(struct tb_nhi *nhi, bool power) +{ + u32 vs_cap; + + /* + * The Thunderbolt host controller is present always in Ice Lake + * but the firmware may not be loaded and running (depending + * whether there is device connected and so on). Each time the + * controller is used we need to "Force Power" it first and wait + * for the firmware to indicate it is up and running. This "Force + * Power" is really not about actually powering on/off the + * controller so it is accessible even if "Force Power" is off. + * + * The actual power management happens inside shared ACPI power + * resources using standard ACPI methods. + */ + pci_read_config_dword(nhi->pdev, VS_CAP_22, &vs_cap); + if (power) { + vs_cap &= ~VS_CAP_22_DMA_DELAY_MASK; + vs_cap |= 0x22 << VS_CAP_22_DMA_DELAY_SHIFT; + vs_cap |= VS_CAP_22_FORCE_POWER; + } else { + vs_cap &= ~VS_CAP_22_FORCE_POWER; + } + pci_write_config_dword(nhi->pdev, VS_CAP_22, vs_cap); + + if (power) { + unsigned int retries = 10; + u32 val; + + /* Wait until the firmware tells it is up and running */ + do { + pci_read_config_dword(nhi->pdev, VS_CAP_9, &val); + if (val & VS_CAP_9_FW_READY) + return 0; + msleep(250); + } while (--retries); + + return -ETIMEDOUT; + } + + return 0; +} + +static void icl_nhi_lc_mailbox_cmd(struct tb_nhi *nhi, enum icl_lc_mailbox_cmd cmd) +{ + u32 data; + + pci_read_config_dword(nhi->pdev, VS_CAP_19, &data); + data = (cmd << VS_CAP_19_CMD_SHIFT) & VS_CAP_19_CMD_MASK; + pci_write_config_dword(nhi->pdev, VS_CAP_19, data | VS_CAP_19_VALID); +} + +static int icl_nhi_lc_mailbox_cmd_complete(struct tb_nhi *nhi, int timeout) +{ + unsigned long end; + u32 data; + + if (!timeout) + goto clear; + + end = jiffies + msecs_to_jiffies(timeout); + do { + pci_read_config_dword(nhi->pdev, VS_CAP_18, &data); + if (data & VS_CAP_18_DONE) + goto clear; + msleep(100); + } while (time_before(jiffies, end)); + + return -ETIMEDOUT; + +clear: + /* Clear the valid bit */ + pci_write_config_dword(nhi->pdev, VS_CAP_19, 0); + return 0; +} + +static void icl_nhi_set_ltr(struct tb_nhi *nhi) +{ + u32 max_ltr, ltr; + + pci_read_config_dword(nhi->pdev, VS_CAP_16, &max_ltr); + max_ltr &= 0xffff; + /* Program the same value for both snoop and no-snoop */ + ltr = max_ltr << 16 | max_ltr; + pci_write_config_dword(nhi->pdev, VS_CAP_15, ltr); +} + +static int icl_nhi_suspend(struct tb_nhi *nhi) +{ + int ret; + + if (icl_nhi_is_device_connected(nhi)) + return 0; + + /* + * If there is no device connected we need to perform both: a + * handshake through LC mailbox and force power down before + * entering D3. + */ + icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET); + ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); + if (ret) + return ret; + + return icl_nhi_force_power(nhi, false); +} + +static int icl_nhi_suspend_noirq(struct tb_nhi *nhi, bool wakeup) +{ + enum icl_lc_mailbox_cmd cmd; + + if (!pm_suspend_via_firmware()) + return icl_nhi_suspend(nhi); + + cmd = wakeup ? ICL_LC_GO2SX : ICL_LC_GO2SX_NO_WAKE; + icl_nhi_lc_mailbox_cmd(nhi, cmd); + return icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); +} + +static int icl_nhi_resume(struct tb_nhi *nhi) +{ + int ret; + + ret = icl_nhi_force_power(nhi, true); + if (ret) + return ret; + + icl_nhi_set_ltr(nhi); + return 0; +} + +static void icl_nhi_shutdown(struct tb_nhi *nhi) +{ + icl_nhi_force_power(nhi, false); +} + +const struct tb_nhi_ops icl_nhi_ops = { + .init = icl_nhi_resume, + .suspend_noirq = icl_nhi_suspend_noirq, + .resume_noirq = icl_nhi_resume, + .runtime_suspend = icl_nhi_suspend, + .runtime_resume = icl_nhi_resume, + .shutdown = icl_nhi_shutdown, +}; diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index a60bd98c1d04..0d4970dcef84 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -124,4 +124,41 @@ struct ring_desc { #define REG_FW_STS_ICM_EN_INVERT BIT(1) #define REG_FW_STS_ICM_EN BIT(0) +/* ICL NHI VSEC registers */ + +/* FW ready */ +#define VS_CAP_9 0xc8 +#define VS_CAP_9_FW_READY BIT(31) +/* UUID */ +#define VS_CAP_10 0xcc +#define VS_CAP_11 0xd0 +/* LTR */ +#define VS_CAP_15 0xe0 +#define VS_CAP_16 0xe4 +/* TBT2PCIe */ +#define VS_CAP_18 0xec +#define VS_CAP_18_DONE BIT(0) +/* PCIe2TBT */ +#define VS_CAP_19 0xf0 +#define VS_CAP_19_VALID BIT(0) +#define VS_CAP_19_CMD_SHIFT 1 +#define VS_CAP_19_CMD_MASK GENMASK(7, 1) +/* Force power */ +#define VS_CAP_22 0xfc +#define VS_CAP_22_FORCE_POWER BIT(1) +#define VS_CAP_22_DMA_DELAY_MASK GENMASK(31, 24) +#define VS_CAP_22_DMA_DELAY_SHIFT 24 + +/** + * enum icl_lc_mailbox_cmd - ICL specific LC mailbox commands + * @ICL_LC_GO2SX: Ask LC to enter Sx without wake + * @ICL_LC_GO2SX_NO_WAKE: Ask LC to enter Sx with wake + * @ICL_LC_PREPARE_FOR_RESET: Prepare LC for reset + */ +enum icl_lc_mailbox_cmd { + ICL_LC_GO2SX = 0x02, + ICL_LC_GO2SX_NO_WAKE = 0x03, + ICL_LC_PREPARE_FOR_RESET = 0x21, +}; + #endif diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 531f11fecf75..410bf1bceeee 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1470,6 +1470,8 @@ static int tb_switch_get_generation(struct tb_switch *sw) case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE: case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE: case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE: + case PCI_DEVICE_ID_INTEL_ICL_NHI0: + case PCI_DEVICE_ID_INTEL_ICL_NHI1: return 3; default: diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h index afbe1d29bb03..4b641e4ee0c5 100644 --- a/drivers/thunderbolt/tb_msgs.h +++ b/drivers/thunderbolt/tb_msgs.h @@ -104,10 +104,11 @@ enum icm_pkg_code { }; enum icm_event_code { - ICM_EVENT_DEVICE_CONNECTED = 3, - ICM_EVENT_DEVICE_DISCONNECTED = 4, - ICM_EVENT_XDOMAIN_CONNECTED = 6, - ICM_EVENT_XDOMAIN_DISCONNECTED = 7, + ICM_EVENT_DEVICE_CONNECTED = 0x3, + ICM_EVENT_DEVICE_DISCONNECTED = 0x4, + ICM_EVENT_XDOMAIN_CONNECTED = 0x6, + ICM_EVENT_XDOMAIN_DISCONNECTED = 0x7, + ICM_EVENT_RTD3_VETO = 0xa, }; struct icm_pkg_header { @@ -463,6 +464,13 @@ struct icm_tr_pkg_disconnect_xdomain_response { uuid_t remote_uuid; }; +/* Ice Lake messages */ + +struct icm_icl_event_rtd3_veto { + struct icm_pkg_header hdr; + u32 veto_reason; +}; + /* XDomain messages */ struct tb_xdomain_header { diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 2d7e012db03f..ece782ef5466 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -429,6 +429,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) * @lock: Must be held during ring creation/destruction. Is acquired by * interrupt_work when dispatching interrupts to individual rings. * @pdev: Pointer to the PCI device + * @ops: NHI specific optional ops * @iobase: MMIO space of the NHI * @tx_rings: All Tx rings available on this host controller * @rx_rings: All Rx rings available on this host controller @@ -442,6 +443,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) struct tb_nhi { spinlock_t lock; struct pci_dev *pdev; + const struct tb_nhi_ops *ops; void __iomem *iobase; struct tb_ring **tx_rings; struct tb_ring **rx_rings; -- GitLab From dfda204198848b47bdb98ab83b94dbb7c7692b55 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 14 May 2019 16:56:21 +0300 Subject: [PATCH 4391/7155] ACPI / property: Add two new Thunderbolt property GUIDs to the list Ice Lake Thunderbolt controller includes two new device property compatible properties that we need to be able to extract in the driver so add them to the growing array of GUIDs. Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki --- drivers/acpi/property.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index ea3d700da3ca..e095334eaec9 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -39,6 +39,12 @@ static const guid_t prp_guids[] = { /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */ GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3, 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89), + /* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */ + GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d, + 0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7), + /* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */ + GUID_INIT(0x6c501103, 0xc189, 0x4296, + 0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d), }; /* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ -- GitLab From 8f4b5b0af7e451a4c6698ad3441dde8d1286c80d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 23 Aug 2019 08:07:21 -0300 Subject: [PATCH 4392/7155] media: cec-adap: return from cec_s_conn_info() if adap is invalid Check if cec_s_conn_info is called with a valid cec adapter, do nothing if it is invalid. This makes it possible to call this function even if CEC support is disabled in the kernel config. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-adap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 451c61bde4d4..5ef7daeb8cbd 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -1614,6 +1614,9 @@ EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid); void cec_s_conn_info(struct cec_adapter *adap, const struct cec_connector_info *conn_info) { + if (IS_ERR_OR_NULL(adap)) + return; + if (!(adap->capabilities & CEC_CAP_CONNECTOR_INFO)) return; -- GitLab From 14d5511691e5290103bc480998bc322e68f139d4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 23 Aug 2019 08:12:59 -0300 Subject: [PATCH 4393/7155] media: cec-notifier: clear cec_adap in cec_notifier_unregister If cec_notifier_cec_adap_unregister() is called before cec_unregister_adapter() then everything is OK (and this is the case today). But if it is the other way around, then cec_notifier_unregister() is called first, and that doesn't set n->cec_adap to NULL. So if e.g. cec_notifier_set_phys_addr() is called after cec_notifier_unregister() but before cec_unregister_adapter() then n->cec_adap points to an unregistered and likely deleted cec adapter. So just set n->cec_adap->notifier and n->cec_adap to NULL for rubustness. Eventually cec_notifier_unregister will disappear and this will be simplified substantially. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-notifier.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c index 52a867bde15f..4d82a5522072 100644 --- a/drivers/media/cec/cec-notifier.c +++ b/drivers/media/cec/cec-notifier.c @@ -218,6 +218,8 @@ void cec_notifier_unregister(struct cec_notifier *n) mutex_lock(&n->lock); n->callback = NULL; + n->cec_adap->notifier = NULL; + n->cec_adap = NULL; mutex_unlock(&n->lock); cec_notifier_put(n); } -- GitLab From a8ef0488cc592921a917362cca66af4a601987b9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 14 Aug 2019 09:24:44 -0300 Subject: [PATCH 4394/7155] media: imx: add csc/scaler mem2mem device Add a single imx-media mem2mem video device that uses the IPU IC PP (image converter post processing) task for scaling and colorspace conversion. On i.MX6Q/DL SoCs with two IPUs currently only the first IPU is used. The hardware only supports writing to destination buffers up to 1024x1024 pixels in a single pass, arbitrary sizes can be achieved by rendering multiple tiles per frame. [slongerbeam@gmail.com: use ipu_image_convert_adjust(), fix device_run() error handling, add missing media-device header, unregister and remove the mem2mem device in error paths in imx_media_probe_complete() and in imx_media_remove(), updated for sync subdev registration] Signed-off-by: Philipp Zabel Signed-off-by: Steve Longerbeam Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: correct two minor checkpatch issues] [hverkuil-cisco@xs4all.nl: sparse warning: make imx6_media_probe_complete static] Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/Kconfig | 1 + drivers/staging/media/imx/Makefile | 3 +- .../staging/media/imx/imx-media-csc-scaler.c | 926 ++++++++++++++++++ drivers/staging/media/imx/imx-media-dev.c | 28 +- .../staging/media/imx/imx-media-internal-sd.c | 4 + drivers/staging/media/imx/imx-media.h | 12 + 6 files changed, 972 insertions(+), 2 deletions(-) create mode 100644 drivers/staging/media/imx/imx-media-csc-scaler.c diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig index f51476243016..8f1ae50a4abd 100644 --- a/drivers/staging/media/imx/Kconfig +++ b/drivers/staging/media/imx/Kconfig @@ -7,6 +7,7 @@ config VIDEO_IMX_MEDIA depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE + select V4L2_MEM2MEM_DEV help Say yes here to enable support for video4linux media controller driver for the i.MX5/6 SOC. diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile index aa6c4b4ad37e..9bd9e873ba7c 100644 --- a/drivers/staging/media/imx/Makefile +++ b/drivers/staging/media/imx/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \ - imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o + imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o \ + imx-media-csc-scaler.o imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \ imx-media-of.o imx-media-utils.o diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c new file mode 100644 index 000000000000..de599af59ffc --- /dev/null +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -0,0 +1,926 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * i.MX IPUv3 IC PP mem2mem CSC/Scaler driver + * + * Copyright (C) 2011 Pengutronix, Sascha Hauer + * Copyright (C) 2018 Pengutronix, Philipp Zabel + */ +#include +#include +#include +#include +#include +#include +#include